From 5380d133e42298c8e41192ec824c6894145030f0 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 23 Nov 2018 17:07:13 -0700 Subject: [PATCH 001/265] Adjusted Linux boot options --- .linux_items/include/EFI/boot/refind.conf | 4 ++-- .linux_items/include/syslinux/wk_iso_linux.cfg | 6 +++--- .linux_items/include/syslinux/wk_pxe_linux.cfg | 6 +++--- .linux_items/include/syslinux/wk_sys_linux.cfg | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.linux_items/include/EFI/boot/refind.conf b/.linux_items/include/EFI/boot/refind.conf index f4a128e2..1406ac73 100644 --- a/.linux_items/include/EFI/boot/refind.conf +++ b/.linux_items/include/EFI/boot/refind.conf @@ -25,12 +25,12 @@ menuentry "Linux" { initrd /arch/boot/intel_ucode.img initrd /arch/boot/amd_ucode.img initrd /arch/boot/x86_64/archiso.img - options "archisobasedir=arch archisolabel=%ARCHISO_LABEL% quiet copytoram loglevel=3" + options "archisobasedir=arch archisolabel=%ARCHISO_LABEL% copytoram loglevel=3" submenuentry "Linux (i3)" { add_options "i3" } submenuentry "Linux (CLI)" { - add_options "nox" + add_options "loglevel=4 nomodeset nox" } } #UFD#menuentry "WindowsPE" { diff --git a/.linux_items/include/syslinux/wk_iso_linux.cfg b/.linux_items/include/syslinux/wk_iso_linux.cfg index 3f2c3556..fef9a9e1 100644 --- a/.linux_items/include/syslinux/wk_iso_linux.cfg +++ b/.linux_items/include/syslinux/wk_iso_linux.cfg @@ -6,7 +6,7 @@ ENDTEXT MENU LABEL Linux LINUX boot/x86_64/vmlinuz INITRD boot/intel_ucode.img,boot/amd_ucode.img,boot/x86_64/archiso.img -APPEND archisobasedir=%INSTALL_DIR% archisolabel=%ARCHISO_LABEL% quiet loglevel=3 +APPEND archisobasedir=%INSTALL_DIR% archisolabel=%ARCHISO_LABEL% loglevel=3 LABEL wk_iso_linux_i3 TEXT HELP @@ -16,7 +16,7 @@ ENDTEXT MENU LABEL Linux (i3) LINUX boot/x86_64/vmlinuz INITRD boot/intel_ucode.img,boot/amd_ucode.img,boot/x86_64/archiso.img -APPEND archisobasedir=%INSTALL_DIR% archisolabel=%ARCHISO_LABEL% quiet loglevel=3 i3 +APPEND archisobasedir=%INSTALL_DIR% archisolabel=%ARCHISO_LABEL% loglevel=3 i3 SYSAPPEND 3 LABEL wk_iso_linux_cli @@ -27,5 +27,5 @@ ENDTEXT MENU LABEL Linux (CLI) LINUX boot/x86_64/vmlinuz INITRD boot/intel_ucode.img,boot/amd_ucode.img,boot/x86_64/archiso.img -APPEND archisobasedir=%INSTALL_DIR% archisolabel=%ARCHISO_LABEL% nox nomodeset +APPEND archisobasedir=%INSTALL_DIR% archisolabel=%ARCHISO_LABEL% loglevel=4 nomodeset nox SYSAPPEND 3 diff --git a/.linux_items/include/syslinux/wk_pxe_linux.cfg b/.linux_items/include/syslinux/wk_pxe_linux.cfg index d2468e03..caa6a1cc 100644 --- a/.linux_items/include/syslinux/wk_pxe_linux.cfg +++ b/.linux_items/include/syslinux/wk_pxe_linux.cfg @@ -6,7 +6,7 @@ ENDTEXT MENU LABEL Linux (PXE) LINUX boot/x86_64/vmlinuz INITRD boot/intel_ucode.img,boot/amd_ucode.img,boot/x86_64/archiso.img -APPEND archisobasedir=%INSTALL_DIR% archiso_http_srv=http://${pxeserver}/ quiet loglevel=3 +APPEND archisobasedir=%INSTALL_DIR% archiso_http_srv=http://${pxeserver}/ loglevel=3 SYSAPPEND 3 LABEL wk_http_linux_i3 @@ -17,7 +17,7 @@ ENDTEXT MENU LABEL Linux (PXE) (i3) LINUX boot/x86_64/vmlinuz INITRD boot/intel_ucode.img,boot/amd_ucode.img,boot/x86_64/archiso.img -APPEND archisobasedir=%INSTALL_DIR% archiso_http_srv=http://${pxeserver}/ quiet loglevel=3 i3 +APPEND archisobasedir=%INSTALL_DIR% archiso_http_srv=http://${pxeserver}/ loglevel=3 i3 SYSAPPEND 3 LABEL wk_http_linux_cli @@ -28,5 +28,5 @@ ENDTEXT MENU LABEL Linux (PXE) (CLI) LINUX boot/x86_64/vmlinuz INITRD boot/intel_ucode.img,boot/amd_ucode.img,boot/x86_64/archiso.img -APPEND archisobasedir=%INSTALL_DIR% archiso_http_srv=http://${pxeserver}/ nox nomodeset +APPEND archisobasedir=%INSTALL_DIR% archiso_http_srv=http://${pxeserver}/ loglevel=4 nomodeset nox SYSAPPEND 3 diff --git a/.linux_items/include/syslinux/wk_sys_linux.cfg b/.linux_items/include/syslinux/wk_sys_linux.cfg index 55b5f239..d4319c00 100644 --- a/.linux_items/include/syslinux/wk_sys_linux.cfg +++ b/.linux_items/include/syslinux/wk_sys_linux.cfg @@ -6,7 +6,7 @@ ENDTEXT MENU LABEL Linux LINUX boot/x86_64/vmlinuz INITRD boot/intel_ucode.img,boot/amd_ucode.img,boot/x86_64/archiso.img -APPEND archisobasedir=%INSTALL_DIR% archisolabel=%ARCHISO_LABEL% quiet copytoram loglevel=3 +APPEND archisobasedir=%INSTALL_DIR% archisolabel=%ARCHISO_LABEL% copytoram loglevel=3 LABEL wk_linux_i3 TEXT HELP @@ -16,7 +16,7 @@ ENDTEXT MENU LABEL Linux (i3) LINUX boot/x86_64/vmlinuz INITRD boot/intel_ucode.img,boot/amd_ucode.img,boot/x86_64/archiso.img -APPEND archisobasedir=%INSTALL_DIR% archisolabel=%ARCHISO_LABEL% quiet copytoram loglevel=3 i3 +APPEND archisobasedir=%INSTALL_DIR% archisolabel=%ARCHISO_LABEL% copytoram loglevel=3 i3 SYSAPPEND 3 LABEL wk_linux_cli From 5e1daf36dfae16d5e5ed680da6fbbc1a32d80373 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 23 Nov 2018 17:08:32 -0700 Subject: [PATCH 002/265] Updated Notepad++ config --- .cbin/_include/NotepadPlusPlus/config.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.cbin/_include/NotepadPlusPlus/config.xml b/.cbin/_include/NotepadPlusPlus/config.xml index c2dd100c..1975e9a7 100644 --- a/.cbin/_include/NotepadPlusPlus/config.xml +++ b/.cbin/_include/NotepadPlusPlus/config.xml @@ -4,8 +4,8 @@ standard - hide - + show + vertical hide @@ -18,7 +18,7 @@ no yes - + yes @@ -29,7 +29,7 @@ - hide + show @@ -37,10 +37,10 @@ - + yes - + From 63fcaed8cd172d25a8b8ccc7314257b140682abd Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 23 Nov 2018 17:54:46 -0700 Subject: [PATCH 003/265] Updated Launchers --- .bin/Scripts/Launch.cmd | 10 +++++----- .bin/Scripts/Launcher_Template.cmd | 4 ++-- .bin/Scripts/init_client_dir.cmd | 8 +++++--- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/.bin/Scripts/Launch.cmd b/.bin/Scripts/Launch.cmd index f7080adb..0a0330c6 100644 --- a/.bin/Scripts/Launch.cmd +++ b/.bin/Scripts/Launch.cmd @@ -279,9 +279,9 @@ rem Create VB script mkdir "%bin%\tmp" 2>nul echo Set UAC = CreateObject^("Shell.Application"^) > "%bin%\tmp\Elevate.vbs" if defined L_NCMD ( - echo UAC.ShellExecute "%PYTHON%", """%script%""", "", "runas", 3 >> "%bin%\tmp\Elevate.vbs" + echo UAC.ShellExecute "%PYTHON%", """%script%"" %L_ARGS%", "", "runas", 3 >> "%bin%\tmp\Elevate.vbs" ) else ( - echo UAC.ShellExecute "%CON%", "-run ""%PYTHON%"" ""%script%"" -new_console:n", "", "runas", 1 >> "%bin%\tmp\Elevate.vbs" + echo UAC.ShellExecute "%CON%", "-run ""%PYTHON%"" ""%script%"" %L_ARGS% -new_console:n", "", "runas", 1 >> "%bin%\tmp\Elevate.vbs" ) rem Run @@ -290,9 +290,9 @@ goto Exit :LaunchPyScriptUser if defined L_NCMD ( - start "" "%PYTHON%" "%script%" || goto ErrorUnknown + start "" "%PYTHON%" "%script%" %L_ARGS% || goto ErrorUnknown ) else ( - start "" "%CON%" -run "%PYTHON%" "%script%" -new_console:n || goto ErrorUnknown + start "" "%CON%" -run "%PYTHON%" "%script%" %L_ARGS% -new_console:n || goto ErrorUnknown ) goto Exit @@ -332,7 +332,7 @@ echo. Executable Working Dir Program Args [L_7ZIP] [L_ELEV] [L__CLI] echo. Folder Folder '.' [L_7ZIP] echo. Office Year Product [L_7ZIP] echo. PSScript Scripts Script [L_7ZIP] [L_ELEV] [L_NCMD] -echo. PyScript Scripts Script [L_7ZIP] [L_ELEV] [L_NCMD] +echo. PyScript Scripts Script Args [L_7ZIP] [L_ELEV] [L_NCMD] echo. QuickBooks Year Product [L_7ZIP] echo. echo.L_7ZIP: Extra arguments for 7-Zip (in the :ExtractCBin label) diff --git a/.bin/Scripts/Launcher_Template.cmd b/.bin/Scripts/Launcher_Template.cmd index 90b15482..01d1758d 100644 --- a/.bin/Scripts/Launcher_Template.cmd +++ b/.bin/Scripts/Launcher_Template.cmd @@ -17,7 +17,7 @@ call :SetTitle Launcher rem EXTRA_CODE :DefineLaunch -:: See %bin%\SCripts\Launch.cmd for details under :Usage label +:: See %bin%\Scripts\Launch.cmd for details under :Usage label set L_TYPE= set L_PATH= set L_ITEM= @@ -110,4 +110,4 @@ goto Exit :: Cleanup and exit :: :Exit endlocal -exit /b %errorlevel% \ No newline at end of file +exit /b %errorlevel% diff --git a/.bin/Scripts/init_client_dir.cmd b/.bin/Scripts/init_client_dir.cmd index 4d73e7ab..302b27d1 100644 --- a/.bin/Scripts/init_client_dir.cmd +++ b/.bin/Scripts/init_client_dir.cmd @@ -33,7 +33,7 @@ for /f "tokens=* usebackq" %%f in (`findstr KIT_NAME_SHORT "%SETTINGS%"`) do ( set "KIT_NAME_SHORT=!_v:~0,-1!" ) set "client_dir=%systemdrive%\%KIT_NAME_SHORT%" -set "log_dir=%client_dir%\Info\%iso_date%" +set "log_dir=%client_dir%\Logs\%iso_date%" :Flags set _backups= @@ -45,7 +45,7 @@ set _transfer= for %%f in (%*) do ( if /i "%%f" == "/DEBUG" (@echo on) if /i "%%f" == "/Backups" set _backups=True - if /i "%%f" == "/Info" set _info=True + if /i "%%f" == "/Logs" set _logs=True if /i "%%f" == "/Office" set _office=True if /i "%%f" == "/Quarantine" set _quarantine=True if /i "%%f" == "/QuickBooks" set _quickbooks=True @@ -54,7 +54,9 @@ for %%f in (%*) do ( :CreateDirs if defined _backups mkdir "%client_dir%\Backups">nul 2>&1 -if defined _info mkdir "%client_dir%\Info">nul 2>&1 +if defined _logs ( + mkdir "%log_dir%\%KIT_NAME_FULL%">nul 2>&1 + mkdir "%log_dir%\Tools">nul 2>&1) if defined _office mkdir "%client_dir%\Office">nul 2>&1 if defined _quarantine mkdir "%client_dir%\Quarantine">nul 2>&1 if defined _quickbooks mkdir "%client_dir%\QuickBooks">nul 2>&1 From 8064fc4a1721d2fcd27edcc15efabf42769871cc Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 23 Nov 2018 18:01:03 -0700 Subject: [PATCH 004/265] Removed whitespace from empty lines --- .bin/Scripts/activate.py | 2 +- .bin/Scripts/borrowed/sensors.py | 54 +++++++++++----------- .bin/Scripts/cbs_fix.py | 8 ++-- .bin/Scripts/check_disk.py | 4 +- .bin/Scripts/dism.py | 4 +- .bin/Scripts/functions/activation.py | 2 +- .bin/Scripts/functions/backup.py | 26 +++++------ .bin/Scripts/functions/disk.py | 60 ++++++++++++------------- .bin/Scripts/functions/network.py | 4 +- .bin/Scripts/functions/product_keys.py | 2 +- .bin/Scripts/functions/windows_setup.py | 16 +++---- .bin/Scripts/functions/winpe_menus.py | 30 ++++++------- .bin/Scripts/safemode_enter.py | 6 +-- .bin/Scripts/safemode_exit.py | 6 +-- .bin/Scripts/sfc_scan.py | 4 +- .bin/Scripts/transferred_keys.py | 4 +- .bin/Scripts/user_data_transfer.py | 16 +++---- .bin/Scripts/winpe_root_menu.py | 2 +- 18 files changed, 125 insertions(+), 125 deletions(-) diff --git a/.bin/Scripts/activate.py b/.bin/Scripts/activate.py index 3555c46a..642e5edd 100644 --- a/.bin/Scripts/activate.py +++ b/.bin/Scripts/activate.py @@ -39,7 +39,7 @@ if __name__ == '__main__': selection = menu_select( '{}: Windows Activation Menu'.format(KIT_NAME_FULL), main_entries=activation_methods, action_entries=actions) - + if (selection.isnumeric()): result = try_and_print( message = activation_methods[int(selection)-1]['Name'], diff --git a/.bin/Scripts/borrowed/sensors.py b/.bin/Scripts/borrowed/sensors.py index 847f2619..39b00a4f 100644 --- a/.bin/Scripts/borrowed/sensors.py +++ b/.bin/Scripts/borrowed/sensors.py @@ -35,7 +35,7 @@ class feature(Structure): _fields_ = [("name", c_char_p), ("number", c_int), ("type", c_int)] - + # sensors_feature_type IN = 0x00 FAN = 0x01 @@ -71,10 +71,10 @@ COMPUTE_MAPPING = 4 def init(cfg_file = None): file = _libc.fopen(cfg_file.encode("utf-8"), "r") if cfg_file is not None else None - + if _hdl.sensors_init(file) != 0: raise Exception("sensors_init failed") - + if file is not None: _libc.fclose(file) @@ -84,10 +84,10 @@ def cleanup(): def parse_chip_name(orig_name): ret = chip_name() err= _hdl.sensors_parse_chip_name(orig_name.encode("utf-8"), byref(ret)) - + if err < 0: raise Exception(strerror(err)) - + return ret def strerror(errnum): @@ -101,10 +101,10 @@ def get_detected_chips(match, nr): @return: (chip, next nr to query) """ _nr = c_int(nr) - + if match is not None: match = byref(match) - + chip = _hdl.sensors_get_detected_chips(match, byref(_nr)) chip = chip.contents if bool(chip) else None return chip, _nr.value @@ -115,10 +115,10 @@ def chip_snprintf_name(chip, buffer_size=200): """ ret = create_string_buffer(buffer_size) err = _hdl.sensors_snprintf_chip_name(ret, buffer_size, byref(chip)) - + if err < 0: raise Exception(strerror(err)) - + return ret.value.decode("utf-8") def do_chip_sets(chip): @@ -128,7 +128,7 @@ def do_chip_sets(chip): err = _hdl.sensors_do_chip_sets(byref(chip)) if err < 0: raise Exception(strerror(err)) - + def get_adapter_name(bus): return _hdl.sensors_get_adapter_name(byref(bus)).decode("utf-8") @@ -177,60 +177,60 @@ class ChipIterator: def __init__(self, match = None): self.match = parse_chip_name(match) if match is not None else None self.nr = 0 - + def __iter__(self): return self - + def __next__(self): chip, self.nr = get_detected_chips(self.match, self.nr) - + if chip is None: raise StopIteration - + return chip - + def __del__(self): if self.match is not None: free_chip_name(self.match) - + def next(self): # python2 compability return self.__next__() - + class FeatureIterator: def __init__(self, chip): self.chip = chip self.nr = 0 - + def __iter__(self): return self - + def __next__(self): feature, self.nr = get_features(self.chip, self.nr) - + if feature is None: raise StopIteration - + return feature def next(self): # python2 compability return self.__next__() - + class SubFeatureIterator: def __init__(self, chip, feature): self.chip = chip self.feature = feature self.nr = 0 - + def __iter__(self): return self - + def __next__(self): subfeature, self.nr = get_all_subfeatures(self.chip, self.feature, self.nr) - + if subfeature is None: raise StopIteration - + return subfeature - + def next(self): # python2 compability return self.__next__() diff --git a/.bin/Scripts/cbs_fix.py b/.bin/Scripts/cbs_fix.py index a3b40a8d..9a8ff10c 100644 --- a/.bin/Scripts/cbs_fix.py +++ b/.bin/Scripts/cbs_fix.py @@ -10,7 +10,7 @@ from functions.cleanup import * from functions.data import * init_global_vars() os.system('title {}: CBS Cleanup'.format(KIT_NAME_FULL)) -global_vars['LogFile'] = r'{LogDir}\CBS Cleanup.log'.format(**global_vars) +set_log_file('CBS Cleanup.log') if __name__ == '__main__': try: @@ -20,18 +20,18 @@ if __name__ == '__main__': folder_path = r'{}\Backups'.format(KIT_NAME_SHORT) dest = select_destination(folder_path=folder_path, prompt='Which disk are we using for temp data and backup?') - + # Show details print_info('{}: CBS Cleanup Tool\n'.format(KIT_NAME_FULL)) show_data('Backup / Temp path:', dest) print_standard('\n') if (not ask('Proceed with CBS cleanup?')): abort() - + # Run Cleanup try_and_print(message='Running cleanup...', function=cleanup_cbs, cs='Done', dest_folder=dest) - + # Done print_standard('\nDone.') pause("Press Enter to exit...") diff --git a/.bin/Scripts/check_disk.py b/.bin/Scripts/check_disk.py index 734319f0..7e59fb2b 100644 --- a/.bin/Scripts/check_disk.py +++ b/.bin/Scripts/check_disk.py @@ -9,7 +9,7 @@ sys.path.append(os.getcwd()) from functions.repairs import * init_global_vars() os.system('title {}: Check Disk Tool'.format(KIT_NAME_FULL)) -global_vars['LogFile'] = r'{LogDir}\Check Disk.log'.format(**global_vars) +set_log_file('Check Disk.log') if __name__ == '__main__': try: @@ -45,7 +45,7 @@ if __name__ == '__main__': cs=cs, other_results=other_results, repair=repair) else: abort() - + # Done print_success('Done.') pause("Press Enter to exit...") diff --git a/.bin/Scripts/dism.py b/.bin/Scripts/dism.py index 1c88e51b..e49a9512 100644 --- a/.bin/Scripts/dism.py +++ b/.bin/Scripts/dism.py @@ -9,7 +9,7 @@ sys.path.append(os.getcwd()) from functions.repairs import * init_global_vars() os.system('title {}: DISM helper Tool'.format(KIT_NAME_FULL)) -global_vars['LogFile'] = r'{LogDir}\DISM helper tool.log'.format(**global_vars) +set_log_file('DISM Helper.log') if __name__ == '__main__': try: @@ -46,7 +46,7 @@ if __name__ == '__main__': other_results=other_results, repair=repair) else: abort() - + # Done print_success('Done.') pause("Press Enter to exit...") diff --git a/.bin/Scripts/functions/activation.py b/.bin/Scripts/functions/activation.py index f54d1dca..24436418 100644 --- a/.bin/Scripts/functions/activation.py +++ b/.bin/Scripts/functions/activation.py @@ -59,7 +59,7 @@ def windows_is_activated(): ['cscript', '//nologo', SLMGR, '/xpr'], check=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) activation_string = activation_string.stdout.decode() - + return bool(activation_string and 'permanent' in activation_string) if __name__ == '__main__': diff --git a/.bin/Scripts/functions/backup.py b/.bin/Scripts/functions/backup.py index e33cea2c..d872c4d0 100644 --- a/.bin/Scripts/functions/backup.py +++ b/.bin/Scripts/functions/backup.py @@ -16,7 +16,7 @@ def backup_partition(disk, par): """Create a backup image of a partition.""" if par.get('Image Exists', False) or par['Number'] in disk['Bad Partitions']: raise GenericAbort - + cmd = [ global_vars['Tools']['wimlib-imagex'], 'capture', @@ -48,7 +48,7 @@ def get_volume_display_name(mountpoint): serial_number = None max_component_length = None file_system_flags = None - + vol_info = kernel32.GetVolumeInformationW( ctypes.c_wchar_p(mountpoint), vol_name_buffer, @@ -59,16 +59,16 @@ def get_volume_display_name(mountpoint): fs_name_buffer, ctypes.sizeof(fs_name_buffer) ) - + name = '{} "{}"'.format(name, vol_name_buffer.value) except: pass - + return name def prep_disk_for_backup(destination, disk, backup_prefix): """Gather details about the disk and its partitions. - + This includes partitions that can't be backed up, whether backups already exist on the BACKUP_SERVER, partition names/sizes/used space, etc.""" @@ -83,7 +83,7 @@ def prep_disk_for_backup(destination, disk, backup_prefix): if disk['Valid Partitions'] <= 0: print_error('ERROR: No partitions can be backed up for this disk') raise GenericAbort - + # Prep partitions for par in disk['Partitions']: display = '{size} {fs}'.format( @@ -91,7 +91,7 @@ def prep_disk_for_backup(destination, disk, backup_prefix): width = width, size = par['Size'], fs = par['FileSystem']) - + if par['Number'] in disk['Bad Partitions']: # Set display string using partition description & OS type display = '* {display}\t\t{q}{name}{q}\t{desc} ({os})'.format( @@ -120,7 +120,7 @@ def prep_disk_for_backup(destination, disk, backup_prefix): display = '+ {}'.format(display) else: display = ' {}'.format(display) - + # Append rest of Display String for valid/clobber partitions display += ' (Used: {used})\t{q}{name}{q}'.format( used = par['Used Space'], @@ -128,7 +128,7 @@ def prep_disk_for_backup(destination, disk, backup_prefix): name = par['Name']) # For all partitions par['Display String'] = display - + # Set description for bad partitions warnings = '\n' if disk['Bad Partitions']: @@ -148,7 +148,7 @@ def select_backup_destination(auto_select=True): actions = [ {'Name': 'Main Menu', 'Letter': 'M'}, ] - + # Add local disks for d in psutil.disk_partitions(): if re.search(r'^{}'.format(global_vars['Env']['SYSTEMDRIVE']), d.mountpoint, re.IGNORECASE): @@ -161,7 +161,7 @@ def select_backup_destination(auto_select=True): get_volume_display_name(d.mountpoint)), 'Letter': re.sub(r'^(\w):\\.*$', r'\1', d.mountpoint), }) - + # Size check for dest in destinations: if 'IP' in dest: @@ -175,11 +175,11 @@ def select_backup_destination(auto_select=True): if not destinations: print_warning('No backup destinations found.') raise GenericAbort - + # Skip menu? if len(destinations) == 1 and auto_select: return destinations[0] - + selection = menu_select( title = 'Where are we backing up to?', main_entries = destinations, diff --git a/.bin/Scripts/functions/disk.py b/.bin/Scripts/functions/disk.py index 2d7cf0bb..75879ff8 100644 --- a/.bin/Scripts/functions/disk.py +++ b/.bin/Scripts/functions/disk.py @@ -14,13 +14,13 @@ REGEX_DISK_RAW = re.compile(r'Disk ID: 00000000', re.IGNORECASE) def assign_volume_letters(): """Assign a volume letter to all available volumes.""" remove_volume_letters() - + # Write script script = [] for vol in get_volumes(): script.append('select volume {}'.format(vol['Number'])) script.append('assign') - + # Run run_diskpart(script) @@ -35,7 +35,7 @@ def get_boot_mode(): boot_mode = 'UEFI' except: boot_mode = 'Unknown' - + return boot_mode def get_disk_details(disk): @@ -44,7 +44,7 @@ def get_disk_details(disk): script = [ 'select disk {}'.format(disk['Number']), 'detail disk'] - + # Run try: result = run_diskpart(script) @@ -60,13 +60,13 @@ def get_disk_details(disk): tmp = [s.split(':') for s in tmp if ':' in s] # Add key/value pairs to the details variable and return dict details.update({key.strip(): value.strip() for (key, value) in tmp}) - + return details - + def get_disks(): """Get list of attached disks using DiskPart.""" disks = [] - + try: # Run script result = run_diskpart(['list disk']) @@ -79,7 +79,7 @@ def get_disks(): num = tmp[0] size = human_readable_size(tmp[1]) disks.append({'Number': num, 'Size': size}) - + return disks def get_partition_details(disk, partition): @@ -89,7 +89,7 @@ def get_partition_details(disk, partition): 'select disk {}'.format(disk['Number']), 'select partition {}'.format(partition['Number']), 'detail partition'] - + # Diskpart details try: # Run script @@ -111,14 +111,14 @@ def get_partition_details(disk, partition): tmp = [s.split(':') for s in tmp if ':' in s] # Add key/value pairs to the details variable and return dict details.update({key.strip(): value.strip() for (key, value) in tmp}) - + # Get MBR type / GPT GUID for extra details on "Unknown" partitions guid = partition_uids.lookup_guid(details.get('Type')) if guid: details.update({ 'Description': guid.get('Description', '')[:29], 'OS': guid.get('OS', 'Unknown')[:27]}) - + if 'Letter' in details: # Disk usage try: @@ -128,7 +128,7 @@ def get_partition_details(disk, partition): details['Error'] = err.strerror else: details['Used Space'] = human_readable_size(tmp.used) - + # fsutil details cmd = [ 'fsutil', @@ -151,14 +151,14 @@ def get_partition_details(disk, partition): tmp = [s.split(':') for s in tmp if ':' in s] # Add key/value pairs to the details variable and return dict details.update({key.strip(): value.strip() for (key, value) in tmp}) - + # Set Volume Name details['Name'] = details.get('Volume Name', '') - + # Set FileSystem Type if details.get('FileSystem', '') not in ['RAW', 'Unknown']: details['FileSystem'] = details.get('File System Name', 'Unknown') - + return details def get_partitions(disk): @@ -167,7 +167,7 @@ def get_partitions(disk): script = [ 'select disk {}'.format(disk['Number']), 'list partition'] - + try: # Run script result = run_diskpart(script) @@ -181,7 +181,7 @@ def get_partitions(disk): num = tmp[0] size = human_readable_size(tmp[1]) partitions.append({'Number': num, 'Size': size}) - + return partitions def get_table_type(disk): @@ -190,7 +190,7 @@ def get_table_type(disk): script = [ 'select disk {}'.format(disk['Number']), 'uniqueid disk'] - + try: result = run_diskpart(script) except subprocess.CalledProcessError: @@ -203,7 +203,7 @@ def get_table_type(disk): part_type = 'MBR' elif REGEX_DISK_RAW.search(output): part_type = 'RAW' - + return part_type def get_volumes(): @@ -218,7 +218,7 @@ def get_volumes(): output = result.stdout.decode().strip() for tmp in re.findall(r'Volume (\d+)\s+([A-Za-z]?)\s+', output): vols.append({'Number': tmp[0], 'Letter': tmp[1]}) - + return vols def is_bad_partition(par): @@ -229,7 +229,7 @@ def prep_disk_for_formatting(disk=None): """Gather details about the disk and its partitions.""" disk['Format Warnings'] = '\n' width = len(str(len(disk['Partitions']))) - + # Bail early if disk is None: raise Exception('Disk not provided.') @@ -242,7 +242,7 @@ def prep_disk_for_formatting(disk=None): else: if (ask("Setup Windows to use BIOS/Legacy booting?")): disk['Use GPT'] = False - + # Set Display and Warning Strings if len(disk['Partitions']) == 0: disk['Format Warnings'] += 'No partitions found\n' @@ -252,7 +252,7 @@ def prep_disk_for_formatting(disk=None): width = width, size = partition['Size'], fs = partition['FileSystem']) - + if is_bad_partition(partition): # Set display string using partition description & OS type display += '\t\t{q}{name}{q}\t{desc} ({os})'.format( @@ -290,13 +290,13 @@ def remove_volume_letters(keep=None): """Remove all assigned volume letters using DiskPart.""" if not keep: keep = '' - + script = [] for vol in get_volumes(): if vol['Letter'].upper() != keep.upper(): script.append('select volume {}'.format(vol['Number'])) script.append('remove noerr') - + # Run script try: run_diskpart(script) @@ -306,12 +306,12 @@ def remove_volume_letters(keep=None): def run_diskpart(script): """Run DiskPart script.""" tempfile = r'{}\diskpart.script'.format(global_vars['Env']['TMP']) - + # Write script with open(tempfile, 'w') as f: for line in script: f.write('{}\n'.format(line)) - + # Run script cmd = [ r'{}\Windows\System32\diskpart.exe'.format( @@ -335,7 +335,7 @@ def scan_disks(): # Get partition info for disk disk['Partitions'] = get_partitions(disk) - + for partition in disk['Partitions']: # Get partition details partition.update(get_partition_details(disk, partition)) @@ -364,12 +364,12 @@ def select_disk(title='Which disk?', disks=[]): fs = partition['FileSystem']) if partition['Name']: p_name += '\t"{}"'.format(partition['Name']) - + # Show unsupported partition(s) if is_bad_partition(partition): p_name = '{YELLOW}{p_name}{CLEAR}'.format( p_name=p_name, **COLORS) - + display_name += '\n\t\t\t{}'.format(p_name) if not disk['Partitions']: display_name += '\n\t\t\t{}No partitions found.{}'.format( diff --git a/.bin/Scripts/functions/network.py b/.bin/Scripts/functions/network.py index d040e343..5735c486 100644 --- a/.bin/Scripts/functions/network.py +++ b/.bin/Scripts/functions/network.py @@ -26,7 +26,7 @@ def connect_to_network(): # Bail if currently connected if is_connected(): return - + # WiFi if 'wl' in net_ifs: cmd = [ @@ -37,7 +37,7 @@ def connect_to_network(): message = 'Connecting to {}...'.format(WIFI_SSID), function = run_program, cmd = cmd) - + def is_connected(): """Check for a valid private IP.""" devs = psutil.net_if_addrs() diff --git a/.bin/Scripts/functions/product_keys.py b/.bin/Scripts/functions/product_keys.py index 705f46e9..988d36fd 100644 --- a/.bin/Scripts/functions/product_keys.py +++ b/.bin/Scripts/functions/product_keys.py @@ -39,7 +39,7 @@ def extract_keys(): keys[product] = [] if key not in keys[product]: keys[product].append(key) - + # Done return keys diff --git a/.bin/Scripts/functions/windows_setup.py b/.bin/Scripts/functions/windows_setup.py index cd7f8444..0952e64d 100644 --- a/.bin/Scripts/functions/windows_setup.py +++ b/.bin/Scripts/functions/windows_setup.py @@ -17,7 +17,7 @@ WINDOWS_VERSIONS = [ {'Name': 'Windows 7 Ultimate', 'Image File': 'Win7', 'Image Name': 'Windows 7 ULTIMATE'}, - + {'Name': 'Windows 8.1', 'Image File': 'Win8', 'Image Name': 'Windows 8.1', @@ -25,7 +25,7 @@ WINDOWS_VERSIONS = [ {'Name': 'Windows 8.1 Pro', 'Image File': 'Win8', 'Image Name': 'Windows 8.1 Pro'}, - + {'Name': 'Windows 10 Home', 'Image File': 'Win10', 'Image Name': 'Windows 10 Home', @@ -75,7 +75,7 @@ def find_windows_image(windows_version): image['Glob'] = '--ref="{}*.swm"'.format( image['Path'][:-4]) break - + # Display image to be used (if any) and return if image: print_info('Using image: {}'.format(image['Path'])) @@ -122,7 +122,7 @@ def format_gpt(disk): 'set id="de94bba4-06d1-4d40-a16a-bfd50179d6ac"', 'gpt attributes=0x8000000000000001', ] - + # Run run_diskpart(script) @@ -151,7 +151,7 @@ def format_mbr(disk): 'assign letter="T"', 'set id=27', ] - + # Run run_diskpart(script) @@ -197,11 +197,11 @@ def setup_windows_re(windows_version, windows_letter='W', tools_letter='T'): win = r'{}:\Windows'.format(windows_letter) winre = r'{}\System32\Recovery\WinRE.wim'.format(win) dest = r'{}:\Recovery\WindowsRE'.format(tools_letter) - + # Copy WinRE.wim os.makedirs(dest, exist_ok=True) shutil.copy(winre, r'{}\WinRE.wim'.format(dest)) - + # Set location cmd = [ r'{}\System32\ReAgentc.exe'.format(win), @@ -231,7 +231,7 @@ def wim_contains_image(filename, imagename): run_program(cmd) except subprocess.CalledProcessError: return False - + return True if __name__ == '__main__': diff --git a/.bin/Scripts/functions/winpe_menus.py b/.bin/Scripts/functions/winpe_menus.py index 64ffb666..1c732eca 100644 --- a/.bin/Scripts/functions/winpe_menus.py +++ b/.bin/Scripts/functions/winpe_menus.py @@ -90,7 +90,7 @@ def menu_backup(): message = 'Assigning letters...', function = assign_volume_letters, other_results = other_results) - + # Mount backup shares mount_backup_shares(read_write=True) @@ -107,12 +107,12 @@ def menu_backup(): else: print_error('ERROR: No disks found.') raise GenericAbort - + # Select disk to backup disk = select_disk('For which disk are we creating backups?', disks) if not disk: raise GenericAbort - + # "Prep" disk prep_disk_for_backup(destination, disk, backup_prefix) @@ -150,7 +150,7 @@ def menu_backup(): # Ask to proceed if (not ask('Proceed with backup?')): raise GenericAbort - + # Backup partition(s) print_info('\n\nStarting task.\n') for par in disk['Partitions']: @@ -163,7 +163,7 @@ def menu_backup(): if not result['CS'] and not isinstance(result['Error'], GenericAbort): errors = True par['Error'] = result['Error'] - + # Verify backup(s) if disk['Valid Partitions']: print_info('\n\nVerifying backup images(s)\n') @@ -270,7 +270,7 @@ def menu_setup(): # Select the version of Windows to apply windows_version = select_windows_version() - + # Find Windows image # NOTE: Reassign volume letters to ensure all devices are scanned try_and_print( @@ -289,12 +289,12 @@ def menu_setup(): else: print_error('ERROR: No disks found.') raise GenericAbort - + # Select disk to use as the OS disk dest_disk = select_disk('To which disk are we installing Windows?', disks) if not dest_disk: raise GenericAbort - + # "Prep" disk prep_disk_for_formatting(dest_disk) @@ -323,10 +323,10 @@ def menu_setup(): data = par['Display String'], warning = True) print_warning(dest_disk['Format Warnings']) - + if (not ask('Is this correct?')): raise GenericAbort - + # Safety check print_standard('\nSAFETY CHECK') print_warning('All data will be DELETED from the ' @@ -342,7 +342,7 @@ def menu_setup(): function = remove_volume_letters, other_results = other_results, keep=windows_image['Letter']) - + # Assign new letter for local source if necessary if windows_image['Local'] and windows_image['Letter'] in ['S', 'T', 'W']: new_letter = try_and_print( @@ -377,13 +377,13 @@ def menu_setup(): # We need to crash as the disk is in an unknown state print_error('ERROR: Failed to apply image.') raise GenericAbort - + # Create Boot files try_and_print( message = 'Updating boot files...', function = update_boot_partition, other_results = other_results) - + # Setup WinRE try_and_print( message = 'Updating recovery tools...', @@ -392,8 +392,8 @@ def menu_setup(): windows_version = windows_version) # Copy WinPE log(s) - source = r'{}\Info'.format(global_vars['ClientDir']) - dest = r'W:\{}\Info'.format(KIT_NAME_SHORT) + source = r'{}\Logs'.format(global_vars['ClientDir']) + dest = r'W:\{}\Logs\WinPE'.format(KIT_NAME_SHORT) shutil.copytree(source, dest) # Print summary diff --git a/.bin/Scripts/safemode_enter.py b/.bin/Scripts/safemode_enter.py index c3213cb9..cce7e28a 100644 --- a/.bin/Scripts/safemode_enter.py +++ b/.bin/Scripts/safemode_enter.py @@ -17,16 +17,16 @@ if __name__ == '__main__': other_results = { 'Error': {'CalledProcessError': 'Unknown Error'}, 'Warning': {}} - + if not ask('Enable booting to SafeMode (with Networking)?'): abort() - + # Configure SafeMode try_and_print(message='Set BCD option...', function=enable_safemode, other_results=other_results) try_and_print(message='Enable MSI in SafeMode...', function=enable_safemode_msi, other_results=other_results) - + # Done print_standard('\nDone.') pause('Press Enter to reboot...') diff --git a/.bin/Scripts/safemode_exit.py b/.bin/Scripts/safemode_exit.py index 1449cff5..af66222e 100644 --- a/.bin/Scripts/safemode_exit.py +++ b/.bin/Scripts/safemode_exit.py @@ -17,16 +17,16 @@ if __name__ == '__main__': other_results = { 'Error': {'CalledProcessError': 'Unknown Error'}, 'Warning': {}} - + if not ask('Disable booting to SafeMode?'): abort() - + # Configure SafeMode try_and_print(message='Remove BCD option...', function=disable_safemode, other_results=other_results) try_and_print(message='Disable MSI in SafeMode...', function=disable_safemode_msi, other_results=other_results) - + # Done print_standard('\nDone.') pause('Press Enter to reboot...') diff --git a/.bin/Scripts/sfc_scan.py b/.bin/Scripts/sfc_scan.py index 81211747..d7a3d3fc 100644 --- a/.bin/Scripts/sfc_scan.py +++ b/.bin/Scripts/sfc_scan.py @@ -9,7 +9,7 @@ sys.path.append(os.getcwd()) from functions.repairs import * init_global_vars() os.system('title {}: SFC Tool'.format(KIT_NAME_FULL)) -global_vars['LogFile'] = r'{LogDir}\SFC Tool.log'.format(**global_vars) +set_log_file('SFC Tool.log') if __name__ == '__main__': try: @@ -28,7 +28,7 @@ if __name__ == '__main__': function=run_sfc_scan, other_results=other_results) else: abort() - + # Done print_standard('\nDone.') pause('Press Enter to exit...') diff --git a/.bin/Scripts/transferred_keys.py b/.bin/Scripts/transferred_keys.py index 9829207e..b95ff3c9 100644 --- a/.bin/Scripts/transferred_keys.py +++ b/.bin/Scripts/transferred_keys.py @@ -9,7 +9,7 @@ sys.path.append(os.getcwd()) from functions.product_keys import * init_global_vars() os.system('title {}: Transferred Key Finder'.format(KIT_NAME_FULL)) -global_vars['LogFile'] = r'{LogDir}\Transferred Keys.log'.format(**global_vars) +set_log_file('Transferred Keys.log') if __name__ == '__main__': try: @@ -18,7 +18,7 @@ if __name__ == '__main__': print_info('{}: Transferred Key Finder\n'.format(KIT_NAME_FULL)) try_and_print(message='Searching for keys...', function=list_clientdir_keys, print_return=True) - + # Done print_standard('\nDone.') exit_script() diff --git a/.bin/Scripts/user_data_transfer.py b/.bin/Scripts/user_data_transfer.py index ce572f69..981e235a 100644 --- a/.bin/Scripts/user_data_transfer.py +++ b/.bin/Scripts/user_data_transfer.py @@ -10,7 +10,7 @@ from functions.data import * from functions.repairs import * init_global_vars() os.system('title {}: User Data Transfer Tool'.format(KIT_NAME_FULL)) -global_vars['LogFile'] = r'{LogDir}\User Data Transfer.log'.format(**global_vars) +set_log_file('User Data Transfer.log') if __name__ == '__main__': try: @@ -18,7 +18,7 @@ if __name__ == '__main__': stay_awake() clear_screen() print_info('{}: User Data Transfer Tool\n'.format(KIT_NAME_FULL)) - + # Get backup name prefix ticket_number = get_ticket_number() if ENABLED_TICKET_NUMBERS: @@ -26,16 +26,16 @@ if __name__ == '__main__': else: backup_prefix = get_simple_string(prompt='Enter backup name prefix') backup_prefix = backup_prefix.replace(' ', '_') - + # Set destination folder_path = r'{}\Transfer'.format(KIT_NAME_SHORT) dest = select_destination(folder_path=folder_path, prompt='Which disk are we transferring to?') - + # Set source items source = select_source(backup_prefix) items = scan_source(source, dest) - + # Transfer clear_screen() print_info('Transfer Details:\n') @@ -43,17 +43,17 @@ if __name__ == '__main__': show_data('Ticket:', ticket_number) show_data('Source:', source.path) show_data('Destination:', dest) - + if (not ask('Proceed with transfer?')): umount_backup_shares() abort() - + print_info('Transferring Data') transfer_source(source, dest, items) try_and_print(message='Removing extra files...', function=cleanup_transfer, cs='Done', dest_path=dest) umount_backup_shares() - + # Done try_and_print(message='Running KVRT...', function=run_kvrt, cs='Started') diff --git a/.bin/Scripts/winpe_root_menu.py b/.bin/Scripts/winpe_root_menu.py index 03c763af..743d987b 100644 --- a/.bin/Scripts/winpe_root_menu.py +++ b/.bin/Scripts/winpe_root_menu.py @@ -11,7 +11,7 @@ from functions.winpe_menus import * TOOLS['SevenZip'].pop('64') init_global_vars() set_title('{}: Root Menu'.format(KIT_NAME_FULL)) -global_vars['LogFile'] = r'{LogDir}\WinPE.log'.format(**global_vars) +set_log_file('WinPE.log') if __name__ == '__main__': try: From 923ddd7cd388c97450a7e234dc844fbc82a81b5e Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 23 Nov 2018 18:04:12 -0700 Subject: [PATCH 005/265] Removed whitespace from more empty lines --- .bin/Scripts/install_sw_bundle.py | 6 ++++-- .bin/Scripts/install_vcredists.py | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.bin/Scripts/install_sw_bundle.py b/.bin/Scripts/install_sw_bundle.py index d98eb8d2..5ee1a8f3 100644 --- a/.bin/Scripts/install_sw_bundle.py +++ b/.bin/Scripts/install_sw_bundle.py @@ -9,7 +9,7 @@ sys.path.append(os.getcwd()) from functions.setup import * init_global_vars() os.system('title {}: SW Bundle Tool'.format(KIT_NAME_FULL)) -global_vars['LogFile'] = r'{LogDir}\Install SW Bundle.log'.format(**global_vars) +set_log_file('Install SW Bundle.log') if __name__ == '__main__': try: @@ -34,7 +34,7 @@ if __name__ == '__main__': answer_mse = ask('Install MSE?') else: answer_mse = False - + print_info('Installing Programs') if answer_adobe_reader: try_and_print(message='Adobe Reader DC...', @@ -62,3 +62,5 @@ if __name__ == '__main__': pass except: major_exception() + +# vim: sts=4 sw=4 ts=4 diff --git a/.bin/Scripts/install_vcredists.py b/.bin/Scripts/install_vcredists.py index 4a1f53ea..fd953551 100644 --- a/.bin/Scripts/install_vcredists.py +++ b/.bin/Scripts/install_vcredists.py @@ -9,7 +9,7 @@ sys.path.append(os.getcwd()) from functions.setup import * init_global_vars() os.system('title {}: Install Visual C++ Runtimes'.format(KIT_NAME_FULL)) -global_vars['LogFile'] = r'{LogDir}\Install Visual C++ Runtimes.log'.format(**global_vars) +set_log_file('Install Visual C++ Runtimes.log') if __name__ == '__main__': try: @@ -20,12 +20,12 @@ if __name__ == '__main__': 'Error': { 'CalledProcessError': 'Unknown Error', }} - + if ask('Install Visual C++ Runtimes?'): install_vcredists() else: abort() - + print_standard('\nDone.') exit_script() except SystemExit: From 18b13cf506a89d2f8f4a93853950601c1067f6f9 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 23 Nov 2018 18:06:57 -0700 Subject: [PATCH 006/265] Updated common.py --- .bin/Scripts/functions/common.py | 35 +++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index 9bc4732d..ae958645 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -32,7 +32,8 @@ COLORS = { 'BLUE': '\033[34m' } try: - HKU = winreg.HKEY_USERS + HKU = winreg.HKEY_USERS + HKCR = winreg.HKEY_CLASSES_ROOT HKCU = winreg.HKEY_CURRENT_USER HKLM = winreg.HKEY_LOCAL_MACHINE except NameError: @@ -167,14 +168,13 @@ def exit_script(return_value=0): # Remove dirs (if empty) for dir in ['BackupDir', 'LogDir', 'TmpDir']: try: - dir = global_vars[dir] - os.rmdir(dir) + os.rmdir(global_vars[dir]) except Exception: pass # Open Log (if it exists) log = global_vars.get('LogFile', '') - if log and os.path.exists(log) and psutil.WINDOWS: + if log and os.path.exists(log) and psutil.WINDOWS and ENABLED_OPEN_LOGS: try: extract_item('NotepadPlusPlus', silent=True) popen_program( @@ -499,6 +499,8 @@ def sleep(seconds=2): def stay_awake(): """Prevent the system from sleeping or hibernating.""" + # DISABLED due to VCR2008 dependency + return # Bail if caffeine is already running for proc in psutil.process_iter(): if proc.name() == 'caffeine.exe': @@ -506,7 +508,7 @@ def stay_awake(): # Extract and run extract_item('Caffeine', silent=True) try: - popen_program(global_vars['Tools']['Caffeine']) + popen_program([global_vars['Tools']['Caffeine']]) except Exception: print_error('ERROR: No caffeine available.') print_warning('Please set the power setting to High Performance.') @@ -601,9 +603,10 @@ global_vars: {}'''.format(f.read(), sys.argv, global_vars) CRASH_SERVER['Url'], global_vars.get('Date-Time', 'Unknown Date-Time'), filename) - r = requests.put(url, data=data, - headers = {'X-Requested-With': 'XMLHttpRequest'}, - auth = (CRASH_SERVER['User'], CRASH_SERVER['Pass'])) + r = requests.put( + url, data=data, + headers={'X-Requested-With': 'XMLHttpRequest'}, + auth=(CRASH_SERVER['User'], CRASH_SERVER['Pass'])) # Raise exception if upload NS if not r.ok: raise Exception @@ -752,6 +755,9 @@ def make_tmp_dirs(): """Make temp directories.""" os.makedirs(global_vars['BackupDir'], exist_ok=True) os.makedirs(global_vars['LogDir'], exist_ok=True) + os.makedirs(r'{}\{}'.format( + global_vars['LogDir'], KIT_NAME_FULL), exist_ok=True) + os.makedirs(r'{}\Tools'.format(global_vars['LogDir']), exist_ok=True) os.makedirs(global_vars['TmpDir'], exist_ok=True) def set_common_vars(): @@ -767,11 +773,9 @@ def set_common_vars(): **global_vars) global_vars['ClientDir'] = r'{SYSTEMDRIVE}\{prefix}'.format( prefix=KIT_NAME_SHORT, **global_vars['Env']) - global_vars['BackupDir'] = r'{ClientDir}\Backups\{Date}'.format( + global_vars['BackupDir'] = r'{ClientDir}\Backups'.format( **global_vars) - global_vars['LogDir'] = r'{ClientDir}\Info\{Date}'.format( - **global_vars) - global_vars['ProgBackupDir'] = r'{ClientDir}\Backups'.format( + global_vars['LogDir'] = r'{ClientDir}\Logs\{Date}'.format( **global_vars) global_vars['QuarantineDir'] = r'{ClientDir}\Quarantine'.format( **global_vars) @@ -794,5 +798,12 @@ def set_linux_vars(): 'SevenZip': '7z', } +def set_log_file(log_name): + """Sets global var LogFile and creates path as needed.""" + folder_path = r'{}\{}'.format(global_vars['LogDir'], KIT_NAME_FULL) + log_file = r'{}\{}'.format(folder_path, log_name) + os.makedirs(folder_path, exist_ok=True) + global_vars['LogFile'] = log_file + if __name__ == '__main__': print("This file is not meant to be called directly.") From 7f7c220073ea57c2a4fd061e27fd3d70a92facf3 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 23 Nov 2018 18:08:41 -0700 Subject: [PATCH 007/265] Updated browsers.py --- .bin/Scripts/functions/browsers.py | 91 +++++++++++++++++++++++------- 1 file changed, 72 insertions(+), 19 deletions(-) diff --git a/.bin/Scripts/functions/browsers.py b/.bin/Scripts/functions/browsers.py index 99086f18..143d018d 100644 --- a/.bin/Scripts/functions/browsers.py +++ b/.bin/Scripts/functions/browsers.py @@ -2,6 +2,8 @@ from functions.common import * +from operator import itemgetter + # Define other_results for later try_and_print browser_data = {} other_results = { @@ -101,16 +103,63 @@ SUPPORTED_BROWSERS = { }, } +def archive_all_users(): + """Create backups for all browsers for all users.""" + users_root = r'{}\Users'.format(global_vars['Env']['SYSTEMDRIVE']) + user_envs = [] + + # Build list of valid users + for user_name in os.listdir(users_root): + valid_user = True + if user_name in ('Default', 'Default User'): + # Skip default users + continue + user_path = os.path.join(users_root, user_name) + appdata_local = os.path.join(user_path, r'AppData\Local') + appdata_roaming = os.path.join(user_path, r'AppData\Roaming') + valid_user &= os.path.exists(appdata_local) + valid_user &= os.path.exists(appdata_roaming) + if valid_user: + user_envs.append({ + 'USERNAME': user_name, + 'USERPROFILE': user_path, + 'APPDATA': appdata_roaming, + 'LOCALAPPDATA': appdata_local}) + + # Backup browsers for all valid users + print_info('Backing up browsers') + for fake_env in sorted(user_envs, key=itemgetter('USERPROFILE')): + print_standard(' {}'.format(fake_env['USERNAME'])) + for b_k, b_v in sorted(SUPPORTED_BROWSERS.items()): + if b_k == 'Mozilla Firefox Dev': + continue + source_path = b_v['user_data_path'].format(**fake_env) + if not os.path.exists(source_path): + continue + source_items = source_path + '*' + archive_path = r'{BackupDir}\Browsers ({USERNAME})\{Date}'.format( + **global_vars, **fake_env) + os.makedirs(archive_path, exist_ok=True) + archive_path += r'\{}.7z'.format(b_k) + cmd = [ + global_vars['Tools']['SevenZip'], + 'a', '-aoa', '-bso0', '-bse0', '-mx=1', + archive_path, source_items] + try_and_print(message='{}...'.format(b_k), + function=run_program, cmd=cmd) + print_standard(' ') + def archive_browser(name): """Create backup of Browser saved in the BackupDir.""" source = '{}*'.format(browser_data[name]['user_data_path']) - dest = r'{BackupDir}\Browsers ({USERNAME})'.format( + dest = r'{BackupDir}\Browsers ({USERNAME})\{Date}'.format( **global_vars, **global_vars['Env']) archive = r'{}\{}.7z'.format(dest, name) os.makedirs(dest, exist_ok=True) cmd = [ global_vars['Tools']['SevenZip'], 'a', '-aoa', '-bso0', '-bse0', '-mx=1', + '-mhe=on', '-p{}'.format(ARCHIVE_PASSWORD), archive, source] run_program(cmd) @@ -138,7 +187,7 @@ def clean_chromium_profile(profile): def clean_internet_explorer(**kwargs): """Uses the built-in function to reset IE and sets the homepage. - + NOTE: kwargs set but unused as a workaround.""" kill_process('iexplore.exe') run_program(['rundll32.exe', 'inetcpl.cpl,ResetIEtoDefaults'], check=False) @@ -182,11 +231,11 @@ def clean_mozilla_profile(profile): def get_browser_details(name): """Get installation status and profile details for all supported browsers.""" browser = SUPPORTED_BROWSERS[name].copy() - + # Update user_data_path browser['user_data_path'] = browser['user_data_path'].format( **global_vars['Env']) - + # Find executable (if multiple files are found, the last one is used) exe_path = None num_installs = 0 @@ -197,7 +246,7 @@ def get_browser_details(name): if os.path.exists(test_path): num_installs += 1 exe_path = test_path - + # Find profile(s) profiles = [] if browser['base'] == 'ie': @@ -225,12 +274,12 @@ def get_browser_details(name): profiles.extend( get_mozilla_profiles( search_path=browser['user_data_path'], dev=dev)) - + elif 'Opera' in name: if os.path.exists(browser['user_data_path']): profiles.append( {'name': 'Default', 'path': browser['user_data_path']}) - + # Get homepages if browser['base'] == 'ie': # IE is set to only have one profile above @@ -239,14 +288,14 @@ def get_browser_details(name): for profile in profiles: prefs_path = r'{path}\prefs.js'.format(**profile) profile['homepages'] = get_mozilla_homepages(prefs_path=prefs_path) - + # Add to browser_data browser_data[name] = browser browser_data[name].update({ 'exe_path': exe_path, 'profiles': profiles, }) - + # Raise installation warnings (if any) if num_installs == 0: raise NotInstalledError @@ -305,7 +354,7 @@ def get_mozilla_homepages(prefs_path): homepages = search.group(1).split('|') except Exception: pass - + return homepages def get_mozilla_profiles(search_path, dev=False): @@ -332,9 +381,11 @@ def get_mozilla_profiles(search_path, dev=False): return profiles -def install_adblock(indent=8, width=32): +def install_adblock(indent=8, width=32, just_firefox=False): """Install adblock for all supported browsers.""" for browser in sorted(browser_data): + if just_firefox and browser_data[browser]['base'] != 'mozilla': + continue exe_path = browser_data[browser].get('exe_path', None) function=run_program if not exe_path: @@ -362,7 +413,7 @@ def install_adblock(indent=8, width=32): winreg.QueryValue(HKLM, UBO_EXTRA_CHROME_REG) except FileNotFoundError: urls.append(UBO_EXTRA_CHROME) - + if len(urls) == 0: urls = ['chrome://extensions'] elif 'Opera' in browser: @@ -370,7 +421,7 @@ def install_adblock(indent=8, width=32): else: urls.append(UBO_CHROME) urls.append(UBO_EXTRA_CHROME) - + elif browser_data[browser]['base'] == 'mozilla': # Check for system extensions try: @@ -383,11 +434,11 @@ def install_adblock(indent=8, width=32): urls = ['about:addons'] else: urls = [UBO_MOZILLA] - + elif browser_data[browser]['base'] == 'ie': urls.append(IE_GALLERY) function=popen_program - + # By using check=False we're skipping any return codes so # it should only fail if the program can't be run # (or can't be found). @@ -400,7 +451,7 @@ def install_adblock(indent=8, width=32): def list_homepages(indent=8, width=32): """List current homepages for reference.""" - + for browser in [k for k, v in sorted(browser_data.items()) if v['exe_path']]: # Skip Chromium-based browsers if browser_data[browser]['base'] == 'chromium': @@ -410,7 +461,7 @@ def list_homepages(indent=8, width=32): end='', flush=True) print_warning('Not implemented', timestamp=False) continue - + # All other browsers print_info('{indent}{browser:<{width}}'.format( indent=' '*indent, width=width, browser=browser+'...')) @@ -444,9 +495,11 @@ def reset_browsers(indent=8, width=32): indent=indent, width=width, function=function, other_results=other_results, profile=profile) -def scan_for_browsers(): +def scan_for_browsers(just_firefox=False): """Scan system for any supported browsers.""" - for name in sorted(SUPPORTED_BROWSERS): + for name, details in sorted(SUPPORTED_BROWSERS.items()): + if just_firefox and details['base'] != 'mozilla': + continue try_and_print(message='{}...'.format(name), function=get_browser_details, cs='Detected', other_results=other_results, name=name) From 1839edf84d84623dc140acba49bebef67c14d34a Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 23 Nov 2018 18:09:31 -0700 Subject: [PATCH 008/265] Updated cleanup.py --- .bin/Scripts/functions/cleanup.py | 72 +++++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 17 deletions(-) diff --git a/.bin/Scripts/functions/cleanup.py b/.bin/Scripts/functions/cleanup.py index 1bac4c6c..d401b555 100644 --- a/.bin/Scripts/functions/cleanup.py +++ b/.bin/Scripts/functions/cleanup.py @@ -6,7 +6,7 @@ def cleanup_adwcleaner(): """Move AdwCleaner folders into the ClientDir.""" source_path = r'{SYSTEMDRIVE}\AdwCleaner'.format(**global_vars['Env']) source_quarantine = r'{}\Quarantine'.format(source_path) - + # Quarantine if os.path.exists(source_quarantine): os.makedirs(global_vars['QuarantineDir'], exist_ok=True) @@ -14,27 +14,24 @@ def cleanup_adwcleaner(): **global_vars) dest_name = non_clobber_rename(dest_name) shutil.move(source_quarantine, dest_name) - + # Delete source folder if empty - try: - os.rmdir(source_path) - except OSError: - pass - + delete_empty_folders(source_path) + # Main folder if os.path.exists(source_path): - os.makedirs(global_vars['ProgBackupDir'], exist_ok=True) - dest_name = r'{ProgBackupDir}\AdwCleaner_{Date-Time}'.format( + os.makedirs(global_vars['LogDir'], exist_ok=True) + dest_name = r'{LogDir}\Tools\AdwCleaner'.format( **global_vars) dest_name = non_clobber_rename(dest_name) shutil.move(source_path, dest_name) def cleanup_cbs(dest_folder): """Safely cleanup a known CBS archive bug under Windows 7. - + If a CbsPersist file is larger than 2 Gb then the auto archive feature continually fails and will fill up the system drive with temp files. - + This function moves the temp files and CbsPersist file to a temp folder, compresses the CbsPersist files with 7-Zip, and then opens the temp folder for the user to manually save the backup files and delete the temp files. @@ -43,7 +40,7 @@ def cleanup_cbs(dest_folder): temp_folder = r'{backup_folder}\Temp'.format(backup_folder=backup_folder) os.makedirs(backup_folder, exist_ok=True) os.makedirs(temp_folder, exist_ok=True) - + # Move files into temp folder cbs_path = r'{SYSTEMROOT}\Logs\CBS'.format(**global_vars['Env']) for entry in os.scandir(cbs_path): @@ -59,7 +56,7 @@ def cleanup_cbs(dest_folder): dest_name = r'{}\{}'.format(temp_folder, entry.name) dest_name = non_clobber_rename(dest_name) shutil.move(entry.path, dest_name) - + # Compress CbsPersist files with 7-Zip cmd = [ global_vars['Tools']['SevenZip'], @@ -70,9 +67,9 @@ def cleanup_cbs(dest_folder): def cleanup_desktop(): """Move known backup files and reports into the ClientDir.""" - dest_folder = r'{ProgBackupDir}\Desktop_{Date-Time}'.format(**global_vars) + dest_folder = r'{LogDir}\Tools'.format(**global_vars) os.makedirs(dest_folder, exist_ok=True) - + desktop_path = r'{USERPROFILE}\Desktop'.format(**global_vars['Env']) for entry in os.scandir(desktop_path): # JRT, RKill, Shortcut cleaner @@ -80,12 +77,53 @@ def cleanup_desktop(): dest_name = r'{}\{}'.format(dest_folder, entry.name) dest_name = non_clobber_rename(dest_name) shutil.move(entry.path, dest_name) - + # Remove dir if empty + delete_empty_folders(dest_folder) + +def delete_empty_folders(folder_path): + """Delete all empty folders in path (depth first).""" + if not os.path.exists(folder_path) or not os.path.isdir(folder_path): + # Bail early (silently) + return + + # Delete empty subfolders first + for item in os.scandir(folder_path): + if item.is_dir(): + delete_empty_folders(item.path) + + # Remove top folder try: - os.rmdir(dest_folder) + os.rmdir(folder_path) except OSError: pass +def delete_registry_key(hive, key, recurse=False): + """Delete a registry key and all it's subkeys.""" + access = winreg.KEY_ALL_ACCESS + + try: + if recurse: + # Delete all subkeys first + with winreg.OpenKeyEx(hive, key, 0, access) as k: + key_info = winreg.QueryInfoKey(k) + for x in range(key_info[0]): + subkey = r'{}\{}'.format(key, winreg.EnumKey(k, 0)) + delete_registry_key(hive, subkey) + + # Delete key + winreg.DeleteKey(hive, key) + except FileNotFoundError: + # Ignore + pass + +def delete_registry_value(hive, key, value): + """Delete a registry value.""" + access = winreg.KEY_ALL_ACCESS + with winreg.OpenKeyEx(hive, key, 0, access) as k: + winreg.DeleteValue(k, value) + if __name__ == '__main__': print("This file is not meant to be called directly.") + +# vim: sts=4 sw=4 ts=4 From 7f37bc88021458f8f70e7cec3b0610b2266b4d3e Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 23 Nov 2018 18:10:50 -0700 Subject: [PATCH 009/265] Updated diags.py --- .bin/Scripts/functions/diags.py | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/.bin/Scripts/functions/diags.py b/.bin/Scripts/functions/diags.py index f66d59e0..e55f5b12 100644 --- a/.bin/Scripts/functions/diags.py +++ b/.bin/Scripts/functions/diags.py @@ -38,7 +38,7 @@ def check_connection(): else: abort() -def check_secure_boot_status(): +def check_secure_boot_status(show_alert=False): """Checks UEFI Secure Boot status via PowerShell.""" boot_mode = get_boot_mode() cmd = ['PowerShell', '-Command', 'Confirm-SecureBootUEFI'] @@ -51,18 +51,30 @@ def check_secure_boot_status(): # It's on, do nothing return elif 'False' in out: + if show_alert: + show_alert_box('Secure Boot DISABLED') raise SecureBootDisabledError else: + if show_alert: + show_alert_box('Secure Boot status UNKNOWN') raise SecureBootUnknownError else: if boot_mode != 'UEFI': + if (show_alert and + global_vars['OS']['Version'] in ('8', '8.1', '10')): + # OS supports Secure Boot + show_alert_box('Secure Boot DISABLED\n\nOS installed LEGACY') raise OSInstalledLegacyError else: # Check error message err = result.stderr.decode() if 'Cmdlet not supported' in err: + if show_alert: + show_alert_box('Secure Boot UNAVAILABLE?') raise SecureBootNotAvailError else: + if show_alert: + show_alert_box('Secure Boot ERROR') raise GenericError def get_boot_mode(): @@ -123,7 +135,8 @@ def run_xmplay(): r'{BinDir}\XMPlay\music.7z'.format(**global_vars)] # Unmute audio first - run_nircmd(['mutesysvolume', '0']) + extract_item('NirCmd', silent=True) + run_nircmd('mutesysvolume', '0') # Open XMPlay popen_program(cmd) @@ -134,7 +147,7 @@ def run_hitmanpro(): cmd = [ global_vars['Tools']['HitmanPro'], '/quiet', '/noinstall', '/noupload', - r'/log={LogDir}\hitman.xml'.format(**global_vars)] + r'/log={LogDir}\Tools\HitmanPro.txt'.format(**global_vars)] popen_program(cmd) def run_process_killer(): @@ -152,23 +165,25 @@ def run_rkill(): extract_item('RKill', silent=True) cmd = [ global_vars['Tools']['RKill'], - '-l', r'{LogDir}\RKill.log'.format(**global_vars), + '-s', '-l', r'{LogDir}\Tools\RKill.log'.format(**global_vars), '-new_console:n', '-new_console:s33V'] run_program(cmd, check=False) wait_for_process('RKill') - kill_process('notepad.exe') # RKill cleanup desktop_path = r'{USERPROFILE}\Desktop'.format(**global_vars['Env']) if os.path.exists(desktop_path): for item in os.scandir(desktop_path): if re.search(r'^RKill', item.name, re.IGNORECASE): - dest = re.sub(r'^(.*)\.', '\1_{Date-Time}.'.format( - **global_vars), item.name) - dest = r'{ClientDir}\Info\{name}'.format( + dest = r'{LogDir}\Tools\{name}'.format( name=dest, **global_vars) dest = non_clobber_rename(dest) shutil.move(item.path, dest) +def show_alert_box(message, title='Wizard Kit Warning'): + """Show Windows alert box with message.""" + message_box = ctypes.windll.user32.MessageBoxW + message_box(None, message, title, 0x00001030) + if __name__ == '__main__': print("This file is not meant to be called directly.") From 1cac083916867d31082e608ca62b50db87d2ba97 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 23 Nov 2018 18:12:36 -0700 Subject: [PATCH 010/265] Updated info.py --- .bin/Scripts/functions/info.py | 89 ++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 37 deletions(-) diff --git a/.bin/Scripts/functions/info.py b/.bin/Scripts/functions/info.py index b81a4922..7630a766 100644 --- a/.bin/Scripts/functions/info.py +++ b/.bin/Scripts/functions/info.py @@ -68,7 +68,8 @@ def backup_file_list(): def backup_power_plans(): """Export current power plans.""" - os.makedirs(r'{BackupDir}\Power Plans'.format(**global_vars), exist_ok=True) + os.makedirs(r'{BackupDir}\Power Plans\{Date}'.format( + **global_vars), exist_ok=True) plans = run_program(['powercfg', '/L']) plans = plans.stdout.decode().splitlines() plans = [p for p in plans if re.search(r'^Power Scheme', p)] @@ -76,22 +77,24 @@ def backup_power_plans(): guid = re.sub(r'Power Scheme GUID:\s+([0-9a-f\-]+).*', r'\1', p) name = re.sub( r'Power Scheme GUID:\s+[0-9a-f\-]+\s+\(([^\)]+)\).*', r'\1', p) - out = r'{BackupDir}\Power Plans\{name}.pow'.format( + out = r'{BackupDir}\Power Plans\{Date}\{name}.pow'.format( name=name, **global_vars) if not os.path.exists(out): cmd = ['powercfg', '-export', out, guid] run_program(cmd, check=False) -def backup_registry(): +def backup_registry(overwrite=False): """Backup registry including user hives.""" extract_item('erunt', silent=True) cmd = [ global_vars['Tools']['ERUNT'], - r'{BackupDir}\Registry'.format(**global_vars), + r'{BackupDir}\Registry\{Date}'.format(**global_vars), 'sysreg', 'curuser', 'otherusers', '/noprogresswindow'] + if overwrite: + cmd.append('/noconfirmdelete') run_program(cmd) def get_folder_size(path): @@ -162,7 +165,7 @@ def get_installed_office(): def get_shell_path(folder, user='current'): """Get shell path using SHGetKnownFolderPath via knownpaths, returns str. - + NOTE: Only works for the current user. Code based on https://gist.github.com/mkropat/7550097 """ @@ -175,14 +178,14 @@ def get_shell_path(folder, user='current'): except AttributeError: # Unknown folder ID, ignore and return None pass - + if folderid: try: path = knownpaths.get_path(folderid, getattr(knownpaths.UserHandle, user)) except PathNotFoundError: # Folder not found, ignore and return None pass - + return path def get_user_data_paths(user): @@ -196,7 +199,7 @@ def get_user_data_paths(user): 'Extra Folders': {}, } unload_hive = False - + if user['Name'] == global_vars['Env']['USERNAME']: # We can use SHGetKnownFolderPath for the current user paths['Profile']['Path'] = get_shell_path('Profile') @@ -212,7 +215,7 @@ def get_user_data_paths(user): except Exception: # Profile path not found, leaving as None. pass - + # Shell folders (Prep) if not reg_path_exists(HKU, hive_path) and paths['Profile']['Path']: # User not logged-in, loading hive @@ -226,7 +229,7 @@ def get_user_data_paths(user): except subprocess.CalledProcessError: # Failed to load user hive pass - + # Shell folders shell_folders = r'{}\{}'.format(hive_path, REG_SHELL_FOLDERS) if (reg_path_exists(HKU, hive_path) @@ -252,7 +255,7 @@ def get_user_data_paths(user): if (folder not in paths['Shell Folders'] and os.path.exists(folder_path)): paths['Shell Folders'][folder] = {'Path': folder_path} - + # Extra folders if paths['Profile']['Path']: for folder in EXTRA_FOLDERS: @@ -260,12 +263,12 @@ def get_user_data_paths(user): folder=folder, **paths['Profile']) if os.path.exists(folder_path): paths['Extra Folders'][folder] = {'Path': folder_path} - + # Shell folders (cleanup) if unload_hive: cmd = ['reg', 'unload', r'HKU\{}'.format(TMP_HIVE_PATH)] run_program(cmd, check=False) - + # Done return paths @@ -277,7 +280,7 @@ def get_user_folder_sizes(users): with winreg.OpenKey(HKCU, r'Software\Sysinternals\Du', access=winreg.KEY_WRITE) as key: winreg.SetValueEx(key, 'EulaAccepted', 0, winreg.REG_DWORD, 1) - + for u in users: u.update(get_user_data_paths(u)) if u['Profile']['Path']: @@ -292,7 +295,7 @@ def get_user_folder_sizes(users): def get_user_list(): """Get user list via WMIC, returns list of dicts.""" users = [] - + # Get user info from WMI cmd = ['wmic', 'useraccount', 'get', '/format:csv'] try: @@ -300,10 +303,10 @@ def get_user_list(): except subprocess.CalledProcessError: # Meh, return empty list to avoid a full crash return users - + entries = out.stdout.decode().splitlines() entries = [e.strip().split(',') for e in entries if e.strip()] - + # Add user(s) to dict keys = entries[0] for e in entries[1:]: @@ -314,10 +317,10 @@ def get_user_list(): # Assume SIDs ending with 1000+ are "Standard" and others are "System" e['Type'] = 'Standard' if re.search(r'-1\d+$', e['SID']) else 'System' users.append(e) - + # Sort list users.sort(key=itemgetter('Name')) - + # Done return users @@ -368,26 +371,38 @@ def run_aida64(): '/TEXT', '/SILENT', '/SAFEST'] run_program(cmd, check=False) -def run_bleachbit(): +def run_bleachbit(cleaners=None, preview=True): """Run BleachBit preview and save log. - - This is a preview so no files should be deleted.""" - if not os.path.exists(global_vars['LogDir']+r'\BleachBit.log'): - extract_item('BleachBit', silent=True) - cmd = [global_vars['Tools']['BleachBit'], '--preview', '--preset'] - out = run_program(cmd, check=False) - # Save stderr - if out.stderr.decode().splitlines(): - with open(global_vars['LogDir']+r'\BleachBit.err', 'a', - encoding='utf-8') as f: - for line in out.stderr.decode().splitlines(): - f.write(line.strip() + '\n') - # Save stdout - with open(global_vars['LogDir']+r'\BleachBit.log', 'a', - encoding='utf-8') as f: - for line in out.stdout.decode().splitlines(): + + If preview is True then no files should be deleted.""" + error_path = r'{}\Tools\BleachBit.err'.format(global_vars['LogDir']) + log_path = error_path.replace('err', 'log') + extract_item('BleachBit', silent=True) + + # Safety check + if not cleaners: + # Disable cleaning and use preset config + cleaners = ['--preset'] + preview = True + + # Run + cmd = [ + global_vars['Tools']['BleachBit'], + '--preview' if preview else '--clean'] + cmd.extend(cleaners) + out = run_program(cmd, check=False) + + # Save stderr + if out.stderr.decode().splitlines(): + with open(error_path, 'a', encoding='utf-8') as f: + for line in out.stderr.decode().splitlines(): f.write(line.strip() + '\n') + # Save stdout + with open(log_path, 'a', encoding='utf-8') as f: + for line in out.stdout.decode().splitlines(): + f.write(line.strip() + '\n') + def show_disk_usage(disk): """Show free and used space for a specified disk.""" print_standard('{:5}'.format(disk.device.replace('/', ' ')), @@ -459,7 +474,7 @@ def show_os_name(): def show_temp_files_size(): """Show total size of temp files identified by BleachBit.""" size = None - with open(r'{LogDir}\BleachBit.log'.format(**global_vars), 'r') as f: + with open(r'{LogDir}\Tools\BleachBit.log'.format(**global_vars), 'r') as f: for line in f.readlines(): if re.search(r'^disk space to be recovered:', line, re.IGNORECASE): size = re.sub(r'.*: ', '', line.strip()) From 832ef993e69c625c239ade1c64825545cae47e20 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 23 Nov 2018 18:13:11 -0700 Subject: [PATCH 011/265] Updated repairs.py --- .bin/Scripts/functions/repairs.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.bin/Scripts/functions/repairs.py b/.bin/Scripts/functions/repairs.py index e4d5e74f..589dccc3 100644 --- a/.bin/Scripts/functions/repairs.py +++ b/.bin/Scripts/functions/repairs.py @@ -24,11 +24,11 @@ def run_chkdsk_scan(): raise GenericError # Save stderr - with open(r'{LogDir}\CHKDSK.err'.format(**global_vars), 'a') as f: + with open(r'{LogDir}\Tools\CHKDSK.err'.format(**global_vars), 'a') as f: for line in out.stderr.decode().splitlines(): f.write(line.strip() + '\n') # Save stdout - with open(r'{LogDir}\CHKDSK.log'.format(**global_vars), 'a') as f: + with open(r'{LogDir}\Tools\CHKDSK.log'.format(**global_vars), 'a') as f: for line in out.stdout.decode().splitlines(): f.write(line.strip() + '\n') @@ -50,7 +50,7 @@ def run_dism(repair=False): cmd = [ 'DISM', '/Online', '/Cleanup-Image', '/RestoreHealth', - r'/LogPath:"{LogDir}\DISM_RestoreHealth.log"'.format( + r'/LogPath:"{LogDir}\Tools\DISM_RestoreHealth.log"'.format( **global_vars), '-new_console:n', '-new_console:s33V'] else: @@ -58,7 +58,7 @@ def run_dism(repair=False): cmd = [ 'DISM', '/Online', '/Cleanup-Image', '/ScanHealth', - r'/LogPath:"{LogDir}\DISM_ScanHealth.log"'.format( + r'/LogPath:"{LogDir}\Tools\DISM_ScanHealth.log"'.format( **global_vars), '-new_console:n', '-new_console:s33V'] run_program(cmd, pipe=False, check=False, shell=True) @@ -67,7 +67,7 @@ def run_dism(repair=False): cmd = [ 'DISM', '/Online', '/Cleanup-Image', '/CheckHealth', - r'/LogPath:"{LogDir}\DISM_CheckHealth.log"'.format(**global_vars)] + r'/LogPath:"{LogDir}\Tools\DISM_CheckHealth.log"'.format(**global_vars)] result = run_program(cmd, shell=True).stdout.decode() # Check result if 'no component store corruption detected' not in result.lower(): @@ -93,11 +93,11 @@ def run_sfc_scan(): '/scannow'] out = run_program(cmd, check=False) # Save stderr - with open(r'{LogDir}\SFC.err'.format(**global_vars), 'a') as f: + with open(r'{LogDir}\Tools\SFC.err'.format(**global_vars), 'a') as f: for line in out.stderr.decode('utf-8', 'ignore').splitlines(): f.write(line.strip() + '\n') # Save stdout - with open(r'{LogDir}\SFC.log'.format(**global_vars), 'a') as f: + with open(r'{LogDir}\Tools\SFC.log'.format(**global_vars), 'a') as f: for line in out.stdout.decode('utf-8', 'ignore').splitlines(): f.write(line.strip() + '\n') # Check result @@ -116,7 +116,7 @@ def run_tdsskiller(): **global_vars), exist_ok=True) cmd = [ global_vars['Tools']['TDSSKiller'], - '-l', r'{LogDir}\TDSSKiller.log'.format(**global_vars), + '-l', r'{LogDir}\Tools\TDSSKiller.log'.format(**global_vars), '-qpath', r'{QuarantineDir}\TDSSKiller'.format(**global_vars), '-accepteula', '-accepteulaksn', '-dcexact', '-tdlfs'] From 7e960df2d6353c608137ca5848a2aadb9ac50df0 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 23 Nov 2018 18:18:00 -0700 Subject: [PATCH 012/265] Updated setup.py --- .bin/Scripts/functions/setup.py | 91 ++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 40 deletions(-) diff --git a/.bin/Scripts/functions/setup.py b/.bin/Scripts/functions/setup.py index c5c10a48..4e1e2ee7 100644 --- a/.bin/Scripts/functions/setup.py +++ b/.bin/Scripts/functions/setup.py @@ -1,8 +1,11 @@ # Wizard Kit: Functions - Setup from functions.common import * +from functions.update import * # STATIC VARIABLES +HKU = winreg.HKEY_USERS +HKCR = winreg.HKEY_CLASSES_ROOT HKCU = winreg.HKEY_CURRENT_USER HKLM = winreg.HKEY_LOCAL_MACHINE MOZILLA_FIREFOX_UBO_PATH = r'{}\{}\ublock_origin.xpi'.format( @@ -29,15 +32,22 @@ SETTINGS_CLASSIC_START = { }, } SETTINGS_EXPLORER_SYSTEM = { + # Disable Location Tracking + r'Software\Microsoft\Windows NT\CurrentVersion\Sensor\Overrides\{BFA794E4-F964-4FDB-90F6-51056BFE4B44}': { + 'DWORD Items': {'SensorPermissionState': 0}, + }, + r'System\CurrentControlSet\Services\lfsvc\Service\Configuration': { + 'Status': {'Value': 0}, + }, # Disable Telemetry - r'SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection': { + r'Software\Microsoft\Windows\CurrentVersion\Policies\DataCollection': { 'DWORD Items': {'AllowTelemetry': 0}, }, - r'SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection': { + r'Software\Microsoft\Windows\CurrentVersion\Policies\DataCollection': { 'DWORD Items': {'AllowTelemetry': 0}, 'WOW64_32': True, }, - r'SOFTWARE\Policies\Microsoft\Windows\DataCollection': { + r'Software\Policies\Microsoft\Windows\DataCollection': { 'DWORD Items': {'AllowTelemetry': 0}, }, # Disable Wi-Fi Sense @@ -47,27 +57,19 @@ SETTINGS_EXPLORER_SYSTEM = { r'Software\Microsoft\PolicyManager\default\WiFi\AllowAutoConnectToWiFiSenseHotspots': { 'DWORD Items': {'Value': 0}, }, - # Disable Location Tracking - r'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Sensor\Overrides\{BFA794E4-F964-4FDB-90F6-51056BFE4B44}': { - 'DWORD Items': {'SensorPermissionState': 0}, - }, - r'System\CurrentControlSet\Services\lfsvc\Service\Configuration': { - 'Status': {'Value': 0}, - }, } SETTINGS_EXPLORER_USER = { - # Disable Cortana - r'Software\Microsoft\Personalization\Settings': { - 'DWORD Items': {'AcceptedPrivacyPolicy': 0}, + # Disable silently installed apps + r'Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager': { + 'DWORD Items': {'SilentInstalledAppsEnabled': 0}, }, - r'Software\Microsoft\InputPersonalization': { - 'DWORD Items': { - 'RestrictImplicitTextCollection': 1, - 'RestrictImplicitInkCollection': 1 - }, + # Disable Tips and Tricks + r'Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager': { + 'DWORD Items': {'SoftLandingEnabled ': 0}, }, - r'Software\Microsoft\InputPersonalization\TrainedDataStore': { - 'DWORD Items': {'HarvestContacts': 1}, + # Hide People bar + r'Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\People': { + 'DWORD Items': {'PeopleBand': 0}, }, # Hide Search button / box r'Software\Microsoft\Windows\CurrentVersion\Search': { @@ -178,25 +180,6 @@ def config_classicstart(): sleep(1) popen_program(cs_exe) -def write_registry_settings(settings, all_users=False): - """Write registry values from custom dict of dicts.""" - hive = HKCU - if all_users: - hive = HKLM - for k, v in settings.items(): - # CreateKey - access = winreg.KEY_WRITE - if 'WOW64_32' in v: - access = access | winreg.KEY_WOW64_32KEY - winreg.CreateKeyEx(hive, k, 0, access) - - # Create values - with winreg.OpenKeyEx(hive, k, 0, access) as key: - for name, value in v.get('DWORD Items', {}).items(): - winreg.SetValueEx(key, name, 0, winreg.REG_DWORD, value) - for name, value in v.get('SZ Items', {}).items(): - winreg.SetValueEx(key, name, 0, winreg.REG_SZ, value) - def config_explorer_system(): """Configure Windows Explorer for all users via Registry settings.""" write_registry_settings(SETTINGS_EXPLORER_SYSTEM, all_users=True) @@ -205,6 +188,15 @@ def config_explorer_user(): """Configure Windows Explorer for current user via Registry settings.""" write_registry_settings(SETTINGS_EXPLORER_USER, all_users=False) +def disable_windows_telemetry(): + """Disable Windows 10 telemetry settings with O&O ShutUp10.""" + extract_item('ShutUp10', silent=True) + cmd = [ + r'{BinDir}\ShutUp10\OOSU10.exe'.format(**global_vars), + r'{BinDir}\ShutUp10\1201.cfg'.format(**global_vars), + '/quiet'] + run_program(cmd) + def update_clock(): """Set Timezone and sync clock.""" run_program(['tzutil' ,'/s', WINDOWS_TIME_ZONE], check=False) @@ -217,6 +209,25 @@ def update_clock(): run_program(['net', 'start', 'w32ime'], check=False) run_program(['w32tm', '/resync', '/nowait'], check=False) +def write_registry_settings(settings, all_users=False): + """Write registry values from custom dict of dicts.""" + hive = HKCU + if all_users: + hive = HKLM + for k, v in settings.items(): + # CreateKey + access = winreg.KEY_WRITE + if 'WOW64_32' in v: + access = access | winreg.KEY_WOW64_32KEY + winreg.CreateKeyEx(hive, k, 0, access) + + # Create values + with winreg.OpenKeyEx(hive, k, 0, access) as key: + for name, value in v.get('DWORD Items', {}).items(): + winreg.SetValueEx(key, name, 0, winreg.REG_DWORD, value) + for name, value in v.get('SZ Items', {}).items(): + winreg.SetValueEx(key, name, 0, winreg.REG_SZ, value) + # Installations def install_adobe_reader(): """Install Adobe Reader.""" @@ -257,7 +268,7 @@ def install_firefox_extensions(): # Update registry write_registry_settings(SETTINGS_MOZILLA_FIREFOX_32, all_users=True) write_registry_settings(SETTINGS_MOZILLA_FIREFOX_64, all_users=True) - + # Extract extension(s) to distribution folder cmd = [ global_vars['Tools']['SevenZip'], 'e', '-aos', '-bso0', '-bse0', From 5da9d4e36bc77c8adc002fe46119580c985e5d26 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 23 Nov 2018 18:21:33 -0700 Subject: [PATCH 013/265] Updated update.py and update_kit.py --- .bin/Scripts/functions/update.py | 17 +++++++++++++++++ .bin/Scripts/update_kit.py | 9 +++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/.bin/Scripts/functions/update.py b/.bin/Scripts/functions/update.py index ca48ff3f..b4068c22 100644 --- a/.bin/Scripts/functions/update.py +++ b/.bin/Scripts/functions/update.py @@ -138,7 +138,9 @@ def remove_from_kit(item): item_locations = [] for p in [global_vars['BinDir'], global_vars['CBinDir']]: item_locations.append(r'{}\{}'.format(p, item)) + item_locations.append(r'{}\{}.7z'.format(p, item)) item_locations.append(r'{}\_Drivers\{}'.format(p, item)) + item_locations.append(r'{}\_Drivers\{}.7z'.format(p, item)) for item_path in item_locations: remove_item(item_path) @@ -597,6 +599,21 @@ def update_adobe_reader_dc(): download_generic( dest, 'Adobe Reader DC.exe', SOURCE_URLS['Adobe Reader DC']) +def update_macs_fan_control(): + # Prep + dest = r'{}\Installers'.format( + global_vars['BaseDir']) + + # Remove existing installer + try: + os.remove(r'{}\Macs Fan Control.exe'.format(dest)) + except FileNotFoundError: + pass + + # Download + download_generic( + dest, 'Macs Fan Control.exe', SOURCE_URLS['Macs Fan Control']) + def update_office(): # Remove existing folders remove_from_kit('_Office') diff --git a/.bin/Scripts/update_kit.py b/.bin/Scripts/update_kit.py index 075c699c..67949d93 100644 --- a/.bin/Scripts/update_kit.py +++ b/.bin/Scripts/update_kit.py @@ -40,9 +40,9 @@ if __name__ == '__main__': try_and_print(message='AIDA64...', function=update_aida64, other_results=other_results, width=40) try_and_print(message='Autoruns...', function=update_autoruns, other_results=other_results, width=40) try_and_print(message='BleachBit...', function=update_bleachbit, other_results=other_results, width=40) - try_and_print(message='BlueScreenView...', function=update_bluescreenview, other_results=other_results, width=40) + try_and_print(message='Blue Screen View...', function=update_bluescreenview, other_results=other_results, width=40) try_and_print(message='ERUNT...', function=update_erunt, other_results=other_results, width=40) - try_and_print(message='HitmanPro...', function=update_hitmanpro, other_results=other_results, width=40) + try_and_print(message='Hitman Pro...', function=update_hitmanpro, other_results=other_results, width=40) try_and_print(message='HWiNFO...', function=update_hwinfo, other_results=other_results, width=40) try_and_print(message='NirCmd...', function=update_nircmd, other_results=other_results, width=40) try_and_print(message='ProduKey...', function=update_produkey, other_results=other_results, width=40) @@ -58,6 +58,7 @@ if __name__ == '__main__': # Installers print_info(' Installers') try_and_print(message='Adobe Reader DC...', function=update_adobe_reader_dc, other_results=other_results, width=40) + try_and_print(message='Macs Fan Control...', function=update_macs_fan_control, other_results=other_results, width=40) try_and_print(message='MS Office...', function=update_office, other_results=other_results, width=40) try_and_print(message='Visual C++ Runtimes...', function=update_vcredists, other_results=other_results, width=40) update_all_ninite(other_results=other_results, width=40) @@ -68,7 +69,7 @@ if __name__ == '__main__': try_and_print(message='Classic Start Skin...', function=update_classic_start_skin, other_results=other_results, width=40) try_and_print(message='Du...', function=update_du, other_results=other_results, width=40) try_and_print(message='Everything...', function=update_everything, other_results=other_results, width=40) - try_and_print(message='FirefoxExtensions...', function=update_firefox_ublock_origin, other_results=other_results, width=40) + try_and_print(message='Firefox Extensions...', function=update_firefox_ublock_origin, other_results=other_results, width=40) try_and_print(message='PuTTY...', function=update_putty, other_results=other_results, width=40) try_and_print(message='Notepad++...', function=update_notepadplusplus, other_results=other_results, width=40) try_and_print(message='WizTree...', function=update_wiztree, other_results=other_results, width=40) @@ -79,7 +80,7 @@ if __name__ == '__main__': try_and_print(message='AdwCleaner...', function=update_adwcleaner, other_results=other_results, width=40) try_and_print(message='KVRT...', function=update_kvrt, other_results=other_results, width=40) try_and_print(message='RKill...', function=update_rkill, other_results=other_results, width=40) - try_and_print(message='TDSSKiller...', function=update_tdsskiller, other_results=other_results, width=40) + try_and_print(message='TDSS Killer...', function=update_tdsskiller, other_results=other_results, width=40) # Uninstallers print_info(' Uninstallers') From 2d9de7b69ea0f26986f0092b33dc2a5bc947037e Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 23 Nov 2018 18:22:56 -0700 Subject: [PATCH 014/265] Updated system diags/checklist and user checklist --- .bin/Scripts/system_checklist.py | 16 ++++-- .bin/Scripts/system_diagnostics.py | 82 ++++++++++++++++++++++++------ .bin/Scripts/user_checklist.py | 19 +++---- 3 files changed, 90 insertions(+), 27 deletions(-) diff --git a/.bin/Scripts/system_checklist.py b/.bin/Scripts/system_checklist.py index 72bb82bf..a76433ee 100644 --- a/.bin/Scripts/system_checklist.py +++ b/.bin/Scripts/system_checklist.py @@ -14,7 +14,7 @@ from functions.product_keys import * from functions.setup import * init_global_vars() os.system('title {}: System Checklist Tool'.format(KIT_NAME_FULL)) -global_vars['LogFile'] = r'{LogDir}\System Checklist.log'.format(**global_vars) +set_log_file('System Checklist.log') if __name__ == '__main__': try: @@ -49,10 +49,13 @@ if __name__ == '__main__': # Cleanup print_info('Cleanup') - try_and_print(message='Desktop...', - function=cleanup_desktop, cs='Done') try_and_print(message='AdwCleaner...', function=cleanup_adwcleaner, cs='Done', other_results=other_results) + try_and_print(message='Desktop...', + function=cleanup_desktop, cs='Done') + try_and_print(message='{}...'.format(KIT_NAME_FULL), + function=delete_empty_folders, cs='Done', + folder_path=global_vars['ClientDir']) # Export system info print_info('Backup System Information') @@ -107,6 +110,11 @@ if __name__ == '__main__': sleep(3) try_and_print(message='Running XMPlay...', function=run_xmplay, cs='Started', other_results=other_results) + try: + check_secure_boot_status(show_alert=True) + except: + # Only trying to open alert message boxes + pass # Done print_standard('\nDone.') @@ -116,3 +124,5 @@ if __name__ == '__main__': pass except: major_exception() + +# vim: sts=4 sw=4 ts=4 diff --git a/.bin/Scripts/system_diagnostics.py b/.bin/Scripts/system_diagnostics.py index 9a6e1c0b..bbeb2d11 100644 --- a/.bin/Scripts/system_diagnostics.py +++ b/.bin/Scripts/system_diagnostics.py @@ -13,8 +13,54 @@ from functions.product_keys import * from functions.repairs import * init_global_vars() os.system('title {}: System Diagnostics Tool'.format(KIT_NAME_FULL)) -global_vars['LogFile'] = r'{LogDir}\System Diagnostics.log'.format( - **global_vars) +set_log_file('System Diagnostics.log') + +# Static Variables +BLEACH_BIT_CLEANERS = { + 'Applications': ( + 'adobe_reader.cache', + 'adobe_reader.tmp', + 'amule.tmp', + 'flash.cache', + 'gimp.tmp', + 'hippo_opensim_viewer.cache', + 'java.cache', + 'libreoffice.cache', + 'liferea.cache', + 'miro.cache', + 'openofficeorg.cache', + 'pidgin.cache', + 'secondlife_viewer.Cache', + 'thunderbird.cache', + 'vuze.backup_files', + 'vuze.cache', + 'vuze.tmp', + 'yahoo_messenger.cache', + ), + 'Browsers': ( + 'chromium.cache', + 'chromium.current_session', + 'firefox.cache', + 'firefox.session_restore', + 'google_chrome.cache', + 'google_chrome.session', + 'google_earth.temporary_files', + 'internet_explorer.temporary_files', + 'opera.cache', + 'opera.current_session', + 'safari.cache', + 'seamonkey.cache', + ), + 'System': ( + 'system.clipboard', + 'system.tmp', + 'winapp2_windows.jump_lists', + 'winapp2_windows.ms_search', + 'windows_explorer.run', + 'windows_explorer.search_history', + 'windows_explorer.thumbnails', + ), +} if __name__ == '__main__': try: @@ -34,19 +80,17 @@ if __name__ == '__main__': if ENABLED_TICKET_NUMBERS: print_info('Starting System Diagnostics for Ticket #{}\n'.format( ticket_number)) - + # Sanitize Environment print_info('Sanitizing Environment') - # try_and_print(message='Killing processes...', - # function=run_process_killer, cs='Done') try_and_print(message='Running RKill...', function=run_rkill, cs='Done', other_results=other_results) try_and_print(message='Running TDSSKiller...', function=run_tdsskiller, cs='Done', other_results=other_results) - + # Re-run if earlier process was stopped. stay_awake() - + # Start diags print_info('Starting Background Scans') check_connection() @@ -54,7 +98,7 @@ if __name__ == '__main__': function=run_hitmanpro, cs='Started', other_results=other_results) try_and_print(message='Running Autoruns...', function=run_autoruns, cs='Started', other_results=other_results) - + # OS Health Checks print_info('OS Health Checks') try_and_print( @@ -64,17 +108,23 @@ if __name__ == '__main__': function=run_sfc_scan, other_results=other_results) try_and_print(message='DISM CheckHealth...', function=run_dism, other_results=other_results, repair=False) - + # Scan for supported browsers print_info('Scanning for browsers') scan_for_browsers() - + + # Run BleachBit cleaners + print_info('BleachBit Cleanup') + for k, v in sorted(BLEACH_BIT_CLEANERS.items()): + try_and_print(message=' {}...'.format(k), + function=run_bleachbit, + cs='Done', other_results=other_results, + cleaners=v, preview=True) + # Export system info print_info('Backup System Information') try_and_print(message='AIDA64 reports...', function=run_aida64, cs='Done', other_results=other_results) - try_and_print(message='BleachBit report...', - function=run_bleachbit, cs='Done', other_results=other_results) backup_browsers() try_and_print(message='File listing...', function=backup_file_list, cs='Done', other_results=other_results) @@ -84,7 +134,7 @@ if __name__ == '__main__': function=run_produkey, cs='Done', other_results=other_results) try_and_print(message='Registry...', function=backup_registry, cs='Done', other_results=other_results) - + # Summary print_info('Summary') try_and_print(message='Operating System:', @@ -104,14 +154,14 @@ if __name__ == '__main__': other_results=other_results, print_return=True) try_and_print(message='Product Keys:', function=get_product_keys, ns='Unknown', print_return=True) - + # User data print_info('User Data') try: show_user_data_summary() except Exception: print_error(' Unknown error.') - + # Done print_standard('\nDone.') pause('Press Enter to exit...') @@ -120,3 +170,5 @@ if __name__ == '__main__': pass except: major_exception() + +# vim: sts=4 sw=4 ts=4 diff --git a/.bin/Scripts/user_checklist.py b/.bin/Scripts/user_checklist.py index 72697af7..fd348dec 100644 --- a/.bin/Scripts/user_checklist.py +++ b/.bin/Scripts/user_checklist.py @@ -11,8 +11,7 @@ from functions.cleanup import * from functions.setup import * init_global_vars() os.system('title {}: User Checklist Tool'.format(KIT_NAME_FULL)) -global_vars['LogFile'] = r'{LogDir}\User Checklist ({USERNAME}).log'.format( - **global_vars, **global_vars['Env']) +set_log_file('User Checklist ({USERNAME}).log'.format(**global_vars['Env'])) if __name__ == '__main__': try: @@ -31,29 +30,29 @@ if __name__ == '__main__': if global_vars['OS']['Version'] == '10': answer_config_classicshell = ask('Configure ClassicShell?') answer_config_explorer_user = ask('Configure Explorer?') - + # Cleanup print_info('Cleanup') try_and_print(message='Desktop...', function=cleanup_desktop, cs='Done') - + # Scan for supported browsers print_info('Scanning for browsers') scan_for_browsers() - + # Homepages print_info('Current homepages') list_homepages() - + # Backup print_info('Backing up browsers') backup_browsers() - + # Reset if answer_config_browsers and answer_reset_browsers: print_info('Resetting browsers') reset_browsers() - + # Configure print_info('Configuring programs') if answer_config_browsers: @@ -75,7 +74,7 @@ if __name__ == '__main__': # Run speedtest popen_program(['start', '', 'https://fast.com'], shell=True) - + # Done print_standard('\nDone.') pause('Press Enter to exit...') @@ -84,3 +83,5 @@ if __name__ == '__main__': pass except: major_exception() + +# vim: sts=4 sw=4 ts=4 From 566e1474a59c688672477e09fc36e9d832e7f886 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 23 Nov 2018 18:24:05 -0700 Subject: [PATCH 015/265] Updated launchers.py --- .bin/Scripts/settings/launchers.py | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/.bin/Scripts/settings/launchers.py b/.bin/Scripts/settings/launchers.py index a125a1f8..ea77d983 100644 --- a/.bin/Scripts/settings/launchers.py +++ b/.bin/Scripts/settings/launchers.py @@ -54,7 +54,7 @@ LAUNCHERS = { 'L_PATH': 'FastCopy', 'L_ITEM': 'FastCopy.exe', 'L_ARGS': ( - r' /logfile=%log_dir%\FastCopy.log' + r' /logfile=%log_dir%\Tools\FastCopy.log' r' /cmd=noexist_only' r' /utf8' r' /skip_empty_dir' @@ -94,7 +94,7 @@ LAUNCHERS = { ), 'L_ELEV': 'True', 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Info /Transfer', + r'call "%bin%\Scripts\init_client_dir.cmd" /Logs /Transfer', ], }, 'FastCopy': { @@ -102,7 +102,7 @@ LAUNCHERS = { 'L_PATH': 'FastCopy', 'L_ITEM': 'FastCopy.exe', 'L_ARGS': ( - r' /logfile=%log_dir%\FastCopy.log' + r' /logfile=%log_dir%\Tools\FastCopy.log' r' /cmd=noexist_only' r' /utf8' r' /skip_empty_dir' @@ -141,7 +141,7 @@ LAUNCHERS = { r' /to=%client_dir%\Transfer_%iso_date%\ ' ), 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Info /Transfer', + r'call "%bin%\Scripts\init_client_dir.cmd" /Logs /Transfer', ], }, 'KVRT': { @@ -212,7 +212,6 @@ LAUNCHERS = { r')', ], }, - }, r'Diagnostics\Extras': { 'AIDA64': { 'L_TYPE': 'Executable', @@ -251,10 +250,10 @@ LAUNCHERS = { 'L_TYPE': 'Executable', 'L_PATH': 'erunt', 'L_ITEM': 'ERUNT.EXE', - 'L_ARGS': '%client_dir%\Backups\%iso_date%\Registry sysreg curuser otherusers', + 'L_ARGS': '%client_dir%\Backups\Registry\%iso_date% sysreg curuser otherusers', 'L_ELEV': 'True', 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Info', + r'call "%bin%\Scripts\init_client_dir.cmd" /Logs', ], }, 'HitmanPro': { @@ -262,7 +261,7 @@ LAUNCHERS = { 'L_PATH': 'HitmanPro', 'L_ITEM': 'HitmanPro.exe', 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Info', + r'call "%bin%\Scripts\init_client_dir.cmd" /Logs', ], }, 'HWiNFO (Sensors)': { @@ -455,11 +454,6 @@ LAUNCHERS = { 'L_ITEM': 'WizTree.exe', 'L_ELEV': 'True', }, - 'Update Kit': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'update_kit.py', - }, 'XMPlay': { 'L_TYPE': 'Executable', 'L_PATH': 'XMPlay', @@ -524,8 +518,10 @@ LAUNCHERS = { 'L_TYPE': 'Executable', 'L_PATH': 'RKill', 'L_ITEM': 'RKill.exe', + 'L_ARGS': '-s -l %log_dir%\Tools\RKill.log', + 'L_ELEV': 'True', 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Info', + r'call "%bin%\Scripts\init_client_dir.cmd" /Logs', ], }, 'SFC Scan': { @@ -539,7 +535,7 @@ LAUNCHERS = { 'L_PATH': 'TDSSKiller', 'L_ITEM': 'TDSSKiller.exe', 'L_ARGS': ( - r' -l %log_dir%\TDSSKiller.log' + r' -l %log_dir%\Tools\TDSSKiller.log' r' -qpath %q_dir%' r' -accepteula' r' -accepteulaksn' From e3076152ba8d5137b4007cc0c8081abf0225fcdf Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 23 Nov 2018 18:31:36 -0700 Subject: [PATCH 016/265] Updated main.py --- .bin/Scripts/settings/main.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.bin/Scripts/settings/main.py b/.bin/Scripts/settings/main.py index c49da96e..75fef0fd 100644 --- a/.bin/Scripts/settings/main.py +++ b/.bin/Scripts/settings/main.py @@ -1,14 +1,15 @@ # Wizard Kit: Settings - Main / Branding # Features -ENABLED_UPLOAD_DATA = False +ENABLED_OPEN_LOGS = False ENABLED_TICKET_NUMBERS = False +ENABLED_UPLOAD_DATA = False # STATIC VARIABLES (also used by BASH and BATCH files) ## NOTE: There are no spaces around the = for easier parsing in BASH and BATCH # Main Kit ARCHIVE_PASSWORD='Abracadabra' -KIT_NAME_FULL='Wizard Kit' +KIT_NAME_FULL='WizardKit' KIT_NAME_SHORT='WK' SUPPORT_MESSAGE='Please let 2Shirt know by opening an issue on GitHub' # Live Linux @@ -19,10 +20,10 @@ TECH_PASSWORD='Abracadabra' OFFICE_SERVER_IP='10.0.0.10' QUICKBOOKS_SERVER_IP='10.0.0.10' # Time Zones -LINUX_TIME_ZONE='America/Los_Angeles' # See 'timedatectl list-timezones' for valid values -WINDOWS_TIME_ZONE='Pacific Standard Time' # See 'tzutil /l' for valid values +LINUX_TIME_ZONE='America/Denver' # See 'timedatectl list-timezones' for valid values +WINDOWS_TIME_ZONE='Mountain Standard Time' # See 'tzutil /l' for valid values # WiFi -WIFI_SSID='SomeWifi' +WIFI_SSID='SomeWiFi' WIFI_PASSWORD='Abracadabra' # SERVER VARIABLES From 972d91a4b869fd563a0c70f16721f636bf59e376 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 23 Nov 2018 18:32:52 -0700 Subject: [PATCH 017/265] Updated sources.py --- .bin/Scripts/settings/sources.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.bin/Scripts/settings/sources.py b/.bin/Scripts/settings/sources.py index 5f4947b4..9f4350db 100644 --- a/.bin/Scripts/settings/sources.py +++ b/.bin/Scripts/settings/sources.py @@ -23,6 +23,7 @@ SOURCE_URLS = { 'Intel SSD Toolbox': r'https://downloadmirror.intel.com/27656/eng/Intel%20SSD%20Toolbox%20-%20v3.5.2.exe', 'IOBit_Uninstaller': 'https://portableapps.duckduckgo.com/IObitUninstallerPortable_7.5.0.7.paf.exe', 'KVRT': 'http://devbuilds.kaspersky-labs.com/devbuilds/KVRT/latest/full/KVRT.exe', + 'Macs Fan Control': 'https://www.crystalidea.com/downloads/macsfancontrol_setup.exe', 'NirCmd32': 'https://www.nirsoft.net/utils/nircmd.zip', 'NirCmd64': 'https://www.nirsoft.net/utils/nircmd-x64.zip', 'NotepadPlusPlus': 'https://notepad-plus-plus.org/repository/7.x/7.5.8/npp.7.5.8.bin.minimalist.7z', @@ -197,3 +198,5 @@ RST_SOURCES = { if __name__ == '__main__': print("This file is not meant to be called directly.") + +# vim: sts=4 sw=4 ts=4 tw=0 nowrap From 8a86edb5bb7293292581aecbca0d287c1503eb21 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 23 Nov 2018 18:33:18 -0700 Subject: [PATCH 018/265] Updated windows_builds.py --- .bin/Scripts/settings/windows_builds.py | 36 ++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/.bin/Scripts/settings/windows_builds.py b/.bin/Scripts/settings/windows_builds.py index bdac8bf4..2db18b6f 100644 --- a/.bin/Scripts/settings/windows_builds.py +++ b/.bin/Scripts/settings/windows_builds.py @@ -6,16 +6,16 @@ WINDOWS_BUILDS = { '6000': ( 'Vista', 'RTM', 'Longhorn', None, 'unsupported'), '6001': ( 'Vista', 'SP1', 'Longhorn', None, 'unsupported'), '6002': ( 'Vista', 'SP2', 'Longhorn', None, 'unsupported'), - + '7600': ( '7', 'RTM', 'Vienna', None, 'unsupported'), '7601': ( '7', 'SP1', 'Vienna', None, 'outdated'), - + #9199 is a fake build since Win 8 is 6.2.9200 but that collides with Win 8.1 (6.3.9200) '9199': ( '8', 'RTM', None, None, 'unsupported'), '9200': ( '8.1', None, 'Blue', None, 'outdated'), '9600': ( '8.1', None, 'Update', None, None), - + '9841': ( '10', None, 'Threshold 1', None, 'preview build'), '9860': ( '10', None, 'Threshold 1', None, 'preview build'), '9879': ( '10', None, 'Threshold 1', None, 'preview build'), @@ -149,6 +149,36 @@ WINDOWS_BUILDS = { '17655': ( '10', None, 'Redstone 5', None, 'preview build'), '17661': ( '10', None, 'Redstone 5', None, 'preview build'), '17666': ( '10', None, 'Redstone 5', None, 'preview build'), + '17677': ( '10', None, 'Redstone 5', None, 'preview build'), + '17682': ( '10', None, 'Redstone 5', None, 'preview build'), + '17686': ( '10', None, 'Redstone 5', None, 'preview build'), + '17692': ( '10', None, 'Redstone 5', None, 'preview build'), + '17704': ( '10', None, 'Redstone 5', None, 'preview build'), + '17711': ( '10', None, 'Redstone 5', None, 'preview build'), + '17713': ( '10', None, 'Redstone 5', None, 'preview build'), + '17723': ( '10', None, 'Redstone 5', None, 'preview build'), + '17728': ( '10', None, 'Redstone 5', None, 'preview build'), + '17730': ( '10', None, 'Redstone 5', None, 'preview build'), + '17733': ( '10', None, 'Redstone 5', None, 'preview build'), + '17735': ( '10', None, 'Redstone 5', None, 'preview build'), + '17738': ( '10', None, 'Redstone 5', None, 'preview build'), + '17741': ( '10', None, 'Redstone 5', None, 'preview build'), + '17744': ( '10', None, 'Redstone 5', None, 'preview build'), + '17746': ( '10', None, 'Redstone 5', None, 'preview build'), + '17751': ( '10', None, 'Redstone 5', None, 'preview build'), + '17754': ( '10', None, 'Redstone 5', None, 'preview build'), + '17755': ( '10', None, 'Redstone 5', None, 'preview build'), + '17758': ( '10', None, 'Redstone 5', None, 'preview build'), + '17760': ( '10', None, 'Redstone 5', None, 'preview build'), + '17763': ( '10', 'v1809', 'Redstone 5', 'October 2018 Update', 'preview build'), + '18204': ( '10', None, '19H1', None, 'preview build'), + '18214': ( '10', None, '19H1', None, 'preview build'), + '18219': ( '10', None, '19H1', None, 'preview build'), + '18234': ( '10', None, '19H1', None, 'preview build'), + '18237': ( '10', None, '19H1', None, 'preview build'), + '18242': ( '10', None, '19H1', None, 'preview build'), + '18247': ( '10', None, '19H1', None, 'preview build'), + '18252': ( '10', None, '19H1', None, 'preview build'), } if __name__ == '__main__': From b3b821a8689849e540350df722678431e7f01db5 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 26 Nov 2018 18:12:24 -0700 Subject: [PATCH 019/265] Allow mounting all volumes per device --- .bin/Scripts/functions/data.py | 56 +++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/.bin/Scripts/functions/data.py b/.bin/Scripts/functions/data.py index c8eec384..029c674b 100644 --- a/.bin/Scripts/functions/data.py +++ b/.bin/Scripts/functions/data.py @@ -126,11 +126,11 @@ def cleanup_transfer(dest_path): if not os.path.exists(dest_path): # Bail if dest_path was empty and removed raise Exception - + # Fix attributes cmd = ['attrib', '-a', '-h', '-r', '-s', dest_path] run_program(cmd, check=False) - + for root, dirs, files in os.walk(dest_path, topdown=False): for name in dirs: # Remove empty directories and junction points @@ -153,7 +153,7 @@ def cleanup_transfer(dest_path): except Exception: pass -def find_core_storage_volumes(): +def find_core_storage_volumes(device_path=None): """Try to create block devices for any Apple CoreStorage volumes.""" corestorage_uuid = '53746f72-6167-11aa-aa11-00306543ecac' dmsetup_cmd_file = '{TmpDir}/dmsetup_command'.format(**global_vars) @@ -162,6 +162,8 @@ def find_core_storage_volumes(): cmd = [ 'lsblk', '--json', '--list', '--paths', '--output', 'NAME,PARTTYPE'] + if device_path: + cmd.append(device_path) result = run_program(cmd) json_data = json.loads(result.stdout.decode()) devs = json_data.get('blockdevices', []) @@ -248,7 +250,9 @@ def get_mounted_volumes(): mounted_volumes.extend(item.get('children', [])) return {item['source']: item for item in mounted_volumes} -def mount_volumes(all_devices=True, device_path=None, read_write=False): +def mount_volumes( + all_devices=True, device_path=None, + read_write=False, core_storage=True): """Mount all detected filesystems.""" report = {} cmd = [ @@ -257,9 +261,10 @@ def mount_volumes(all_devices=True, device_path=None, read_write=False): if not all_devices and device_path: # Only mount volumes for specific device cmd.append(device_path) - else: - # Check for Apple CoreStorage volumes first - find_core_storage_volumes() + + # Check for Apple CoreStorage volumes first + if core_storage: + find_core_storage_volumes(device_path) # Get list of block devices result = run_program(cmd) @@ -269,11 +274,14 @@ def mount_volumes(all_devices=True, device_path=None, read_write=False): # Get list of volumes volumes = {} for dev in devs: + if not dev.get('children', []): + volumes.update({dev['name']: dev}) for child in dev.get('children', []): - volumes.update({child['name']: child}) + if not child.get('children', []): + volumes.update({child['name']: child}) for grandchild in child.get('children', []): volumes.update({grandchild['name']: grandchild}) - + # Get list of mounted volumes mounted_volumes = get_mounted_volumes() @@ -352,7 +360,7 @@ def mount_backup_shares(read_write=False): if server['Mounted']: print_warning(mounted_str) continue - + mount_network_share(server, read_write) def mount_network_share(server, read_write=False): @@ -414,12 +422,12 @@ def run_fast_copy(items, dest): """Copy items to dest using FastCopy.""" if not items: raise Exception - + cmd = [global_vars['Tools']['FastCopy'], *FAST_COPY_ARGS] - cmd.append(r'/logfile={}\FastCopy.log'.format(global_vars['LogDir'])) + cmd.append(r'/logfile={LogDir}\Tools\FastCopy.log'.format(**global_vars)) cmd.extend(items) cmd.append('/to={}\\'.format(dest)) - + run_program(cmd) def run_wimextract(source, items, dest): @@ -486,7 +494,7 @@ def list_source_items(source_obj, rel_path=None): def scan_source(source_obj, dest_path, rel_path='', interactive=True): """Scan source for files/folders to transfer, returns list. - + This will scan the root and (recursively) any Windows.old folders.""" selected_items = [] win_olds = [] @@ -563,7 +571,7 @@ def scan_source(source_obj, dest_path, rel_path='', interactive=True): '{}{}{}'.format(dest_path, os.sep, old.name), rel_path=old.name, interactive=False)) - + # Done return selected_items @@ -707,7 +715,7 @@ def select_source(backup_prefix): item.name, # Image file ), 'Source': item}) - + # Check for local sources print_standard('Scanning for local sources...') set_thread_error_mode(silent=True) # Prevents "No disk" popups @@ -747,7 +755,7 @@ def select_source(backup_prefix): ' Local', d.mountpoint, item.name), 'Sort': r'{}{}'.format(d.mountpoint, item.name), 'Source': item}) - + set_thread_error_mode(silent=False) # Return to normal # Build Menu @@ -775,7 +783,7 @@ def select_source(backup_prefix): umount_backup_shares() pause("Press Enter to exit...") exit_script() - + # Sanity check if selected_source.is_file(): # Image-Based @@ -783,7 +791,7 @@ def select_source(backup_prefix): print_error('ERROR: Unsupported image: {}'.format( selected_source.path)) raise GenericError - + # Done return selected_source @@ -791,7 +799,7 @@ def select_volume(title='Select disk', auto_select=True): """Select disk from attached disks. returns dict.""" actions = [{'Name': 'Quit', 'Letter': 'Q'}] disks = [] - + # Build list of disks set_thread_error_mode(silent=True) # Prevents "No disk" popups for d in psutil.disk_partitions(): @@ -812,11 +820,11 @@ def select_volume(title='Select disk', auto_select=True): info['Display Name'] = '{} ({})'.format(info['Name'], free) disks.append(info) set_thread_error_mode(silent=False) # Return to normal - + # Skip menu? if len(disks) == 1 and auto_select: return disks[0] - + # Show menu selection = menu_select(title, main_entries=disks, action_entries=actions) if selection == 'Q': @@ -826,12 +834,12 @@ def select_volume(title='Select disk', auto_select=True): def set_thread_error_mode(silent=True): """Disable or Enable Windows error message dialogs. - + Disable when scanning for disks to avoid popups for empty cardreaders, etc """ # Code borrowed from: https://stackoverflow.com/a/29075319 kernel32 = ctypes.WinDLL('kernel32') - + if silent: kernel32.SetThreadErrorMode(SEM_FAIL, ctypes.byref(SEM_NORMAL)) else: From bb23d49833e90c58dbc852cf709925d175b0b8ca Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 26 Nov 2018 18:14:06 -0700 Subject: [PATCH 020/265] Adjusted mounting shares/volumes --- .bin/Scripts/functions/data.py | 9 +++------ .bin/Scripts/mount-backup-shares | 2 +- .bin/Scripts/remount-rw | 2 -- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/.bin/Scripts/functions/data.py b/.bin/Scripts/functions/data.py index 029c674b..9557ebdb 100644 --- a/.bin/Scripts/functions/data.py +++ b/.bin/Scripts/functions/data.py @@ -372,12 +372,9 @@ def mount_network_share(server, read_write=False): username = server['User'] password = server['Pass'] if psutil.WINDOWS: - cmd = r'net use \\{ip}\{share} /user:{username} {password}'.format( - ip = server['IP'], - share = server['Share'], - username = username, - password = password) - cmd = cmd.split(' ') + cmd = [ + 'net', 'use', r'\\{IP}\{Share}'.format(**server), + '/user:{}'.format(username), password] warning = r'Failed to mount \\{Name}\{Share}, {IP} unreachable.'.format( **server) error = r'Failed to mount \\{Name}\{Share} ({IP})'.format(**server) diff --git a/.bin/Scripts/mount-backup-shares b/.bin/Scripts/mount-backup-shares index 9706a0a5..9f3612b6 100755 --- a/.bin/Scripts/mount-backup-shares +++ b/.bin/Scripts/mount-backup-shares @@ -22,7 +22,7 @@ if __name__ == '__main__': # Mount if is_connected(): - mount_backup_shares() + mount_backup_shares(read_write=True) else: # Couldn't connect print_error('ERROR: No network connectivity.') diff --git a/.bin/Scripts/remount-rw b/.bin/Scripts/remount-rw index 4a0b833e..1ba4b41d 100755 --- a/.bin/Scripts/remount-rw +++ b/.bin/Scripts/remount-rw @@ -18,6 +18,4 @@ if udevil mount $DEVICE; then else echo "Failed" fi - -sleep 2s exit 0 From f802ea860d20ac2f99d51515fd8ea949a3d41958 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 26 Nov 2018 18:15:41 -0700 Subject: [PATCH 021/265] Updated ddrescue.py --- .bin/Scripts/functions/ddrescue.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.bin/Scripts/functions/ddrescue.py b/.bin/Scripts/functions/ddrescue.py index eba04452..7f1fc7aa 100644 --- a/.bin/Scripts/functions/ddrescue.py +++ b/.bin/Scripts/functions/ddrescue.py @@ -323,7 +323,7 @@ class RecoveryState(): elif not is_writable_filesystem(dest): raise GenericError( 'Destination is mounted read-only, refusing to continue.') - + # Safety checks passed self.block_pairs.append(BlockPair(self.mode, source, dest)) @@ -392,7 +392,7 @@ class RecoveryState(): self.status_percent = get_formatted_status( label='Recovered:', data=self.rescued_percent) self.status_amount = get_formatted_status( - label='', data=human_readable_size(self.rescued)) + label='', data=human_readable_size(self.rescued, decimals=2)) # Functions @@ -1084,7 +1084,7 @@ def select_path(skip_device=None): except OSError: raise GenericError( 'Failed to create folder "{}"'.format(s_path)) - + # Create DirObj selected_path = DirObj(s_path) From c42c7647896ff36eab988d2e58c704a2eda1bd78 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 26 Nov 2018 18:35:33 -0700 Subject: [PATCH 022/265] Updated hw_diags.py --- .bin/Scripts/functions/hw_diags.py | 172 ++++++++++++++++++----------- 1 file changed, 110 insertions(+), 62 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index d2282692..169eb337 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -8,23 +8,23 @@ from functions.common import * # STATIC VARIABLES ATTRIBUTES = { 'NVMe': { - 'critical_warning': {'Error': 1}, - 'media_errors': {'Error': 1}, - 'power_on_hours': {'Warning': 12000, 'Error': 18000, 'Ignore': True}, + 'critical_warning': {'Error': 1}, + 'media_errors': {'Error': 1}, + 'power_on_hours': {'Warning': 12000, 'Error': 18000, 'Ignore': True}, 'unsafe_shutdowns': {'Warning': 1}, }, 'SMART': { - 5: {'Error': 1}, - 9: {'Warning': 12000, 'Error': 18000, 'Ignore': True}, - 10: {'Warning': 1}, - 184: {'Error': 1}, - 187: {'Warning': 1}, - 188: {'Warning': 1}, - 196: {'Warning': 1, 'Error': 10, 'Ignore': True}, - 197: {'Error': 1}, - 198: {'Error': 1}, - 199: {'Error': 1, 'Ignore': True}, - 201: {'Warning': 1}, + 5: {'Hex': '05', 'Error': 1}, + 9: {'Hex': '09', 'Warning': 12000, 'Error': 18000, 'Ignore': True}, + 10: {'Hex': '0A', 'Error': 1}, + 184: {'Hex': 'B8', 'Error': 1}, + 187: {'Hex': 'BB', 'Error': 1}, + 188: {'Hex': 'BC', 'Error': 1}, + 196: {'Hex': 'C4', 'Error': 1}, + 197: {'Hex': 'C5', 'Error': 1}, + 198: {'Hex': 'C6', 'Error': 1}, + 199: {'Hex': 'C7', 'Error': 1, 'Ignore': True}, + 201: {'Hex': 'C9', 'Error': 1}, }, } IO_VARS = { @@ -37,9 +37,15 @@ IO_VARS = { 'Scale 8': [2**(0.56*(x+1))+(16*(x+1)) for x in range(8)], 'Scale 16': [2**(0.56*(x+1))+(16*(x+1)) for x in range(16)], 'Scale 32': [2**(0.56*(x+1)/2)+(16*(x+1)/2) for x in range(32)], - 'Threshold Fail': 65*1024**2, - 'Threshold Warn': 135*1024**2, - 'Threshold Great': 750*1024**2, + 'Threshold Graph Fail': 65*1024**2, + 'Threshold Graph Warn': 135*1024**2, + 'Threshold Graph Great': 750*1024**2, + 'Threshold HDD Min': 50*1024**2, + 'Threshold HDD High Avg': 75*1024**2, + 'Threshold HDD Low Avg': 65*1024**2, + 'Threshold SSD Min': 90*1024**2, + 'Threshold SSD High Avg': 135*1024**2, + 'Threshold SSD Low Avg': 100*1024**2, 'Graph Horizontal': ('▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'), 'Graph Horizontal Width': 40, 'Graph Vertical': ( @@ -60,6 +66,7 @@ TESTS = { 'NVMe/SMART': { 'Enabled': False, 'Quick': False, + 'Short Test': {}, 'Status': {}, }, 'badblocks': { @@ -88,11 +95,11 @@ def generate_horizontal_graph(rates, oneline=False): # Set color r_color = COLORS['CLEAR'] - if r < IO_VARS['Threshold Fail']: + if r < IO_VARS['Threshold Graph Fail']: r_color = COLORS['RED'] - elif r < IO_VARS['Threshold Warn']: + elif r < IO_VARS['Threshold Graph Warn']: r_color = COLORS['YELLOW'] - elif r > IO_VARS['Threshold Great']: + elif r > IO_VARS['Threshold Graph Great']: r_color = COLORS['GREEN'] # Build graph @@ -225,16 +232,21 @@ def menu_diags(*args): action_entries = actions, spacer = '──────────────────────────') if selection.isnumeric(): + ticket_number = None if diag_modes[int(selection)-1]['Name'] != 'Quick drive test': - # Save log for non-quick tests + clear_screen() + print_standard(' ') ticket_number = get_ticket_number() - global_vars['LogDir'] = '{}/Logs/{}'.format( + # Save log for non-quick tests + global_vars['Date-Time'] = time.strftime("%Y-%m-%d_%H%M_%z") + global_vars['LogDir'] = '{}/Logs/{}_{}'.format( global_vars['Env']['HOME'], - ticket_number if ticket_number else global_vars['Date-Time']) + ticket_number, + global_vars['Date-Time']) os.makedirs(global_vars['LogDir'], exist_ok=True) global_vars['LogFile'] = '{}/Hardware Diagnostics.log'.format( global_vars['LogDir']) - run_tests(diag_modes[int(selection)-1]['Tests']) + run_tests(diag_modes[int(selection)-1]['Tests'], ticket_number) elif selection == 'A': run_program(['hw-diags-audio'], check=False, pipe=False) pause('Press Enter to return to main menu... ') @@ -256,7 +268,7 @@ def menu_diags(*args): elif selection == 'Q': break -def run_badblocks(): +def run_badblocks(ticket_number): """Run a read-only test for all detected disks.""" aborted = False clear_screen() @@ -318,7 +330,7 @@ def run_badblocks(): run_program('tmux kill-pane -a'.split(), check=False) pass -def run_iobenchmark(): +def run_iobenchmark(ticket_number): """Run a read-only test for all detected disks.""" aborted = False clear_screen() @@ -469,10 +481,25 @@ def run_iobenchmark(): TESTS['iobenchmark']['Results'][name] = report # Set CS/NS - if min(TESTS['iobenchmark']['Data'][name]['Read Rates']) <= IO_VARS['Threshold Fail']: + min_read = min(TESTS['iobenchmark']['Data'][name]['Read Rates']) + avg_read = sum( + TESTS['iobenchmark']['Data'][name]['Read Rates'])/len( + TESTS['iobenchmark']['Data'][name]['Read Rates']) + dev_rotational = dev['lsblk'].get('rota', None) + if dev_rotational == "0": + # Use SSD scale + thresh_min = IO_VARS['Threshold SSD Min'] + thresh_high_avg = IO_VARS['Threshold SSD High Avg'] + thresh_low_avg = IO_VARS['Threshold SSD Low Avg'] + else: + # Use HDD scale + thresh_min = IO_VARS['Threshold HDD Min'] + thresh_high_avg = IO_VARS['Threshold HDD High Avg'] + thresh_low_avg = IO_VARS['Threshold HDD Low Avg'] + if min_read <= thresh_min and avg_read <= thresh_high_avg: + TESTS['iobenchmark']['Status'][name] = 'NS' + elif avg_read <= thresh_low_avg: TESTS['iobenchmark']['Status'][name] = 'NS' - elif min(TESTS['iobenchmark']['Data'][name]['Read Rates']) <= IO_VARS['Threshold Warn']: - TESTS['iobenchmark']['Status'][name] = 'Unknown' else: TESTS['iobenchmark']['Status'][name] = 'CS' @@ -487,7 +514,7 @@ def run_iobenchmark(): run_program('tmux kill-pane -a'.split(), check=False) pass -def run_mprime(): +def run_mprime(ticket_number): """Run Prime95 for MPRIME_LIMIT minutes while showing the temps.""" aborted = False print_log('\nStart Prime95 test') @@ -501,7 +528,7 @@ def run_mprime(): TESTS['Progress Out']).split()) run_program('tmux split-window -bd watch -c -n1 -t hw-sensors'.split()) run_program('tmux resize-pane -y 3'.split()) - + # Start test run_program(['apple-fans', 'max']) try: @@ -516,6 +543,9 @@ def run_mprime(): except KeyboardInterrupt: # Catch CTRL+C aborted = True + TESTS['Prime95']['Status'] = 'Aborted' + print_warning('\nAborted.') + update_progress() # Save "final" temps run_program( @@ -563,15 +593,7 @@ def run_mprime(): TESTS['Prime95']['CS'] = bool(r) # Update status - if aborted: - TESTS['Prime95']['Status'] = 'Aborted' - print_warning('\nAborted.') - update_progress() - if TESTS['NVMe/SMART']['Enabled'] or TESTS['badblocks']['Enabled']: - if not ask('Proceed to next test?'): - run_program('tmux kill-pane -a'.split()) - raise GenericError - else: + if not aborted: if TESTS['Prime95']['NS']: TESTS['Prime95']['Status'] = 'NS' elif TESTS['Prime95']['CS']: @@ -580,10 +602,21 @@ def run_mprime(): TESTS['Prime95']['Status'] = 'Unknown' update_progress() + if aborted: + if TESTS['NVMe/SMART']['Enabled'] or TESTS['badblocks']['Enabled']: + if not ask('Proceed to next test?'): + for name in TESTS['NVMe/SMART']['Devices'].keys(): + for t in ['NVMe/SMART', 'badblocks', 'iobenchmark']: + cur_status = TESTS[t]['Status'][name] + if cur_status not in ['CS', 'Denied', 'NS']: + TESTS[t]['Status'][name] = 'Aborted' + run_program('tmux kill-pane -a'.split()) + raise GenericError + # Done run_program('tmux kill-pane -a'.split()) -def run_nvme_smart(): +def run_nvme_smart(ticket_number): """Run the built-in NVMe or SMART test for all detected disks.""" aborted = False clear_screen() @@ -605,6 +638,7 @@ def run_nvme_smart(): # Run for name, dev in sorted(TESTS['NVMe/SMART']['Devices'].items()): + TESTS['NVMe/SMART']['Short Test'][name] = None cur_status = TESTS['NVMe/SMART']['Status'][name] if cur_status == 'OVERRIDE': # Skipping test per user request @@ -635,7 +669,7 @@ def run_nvme_smart(): run_program( 'sudo smartctl -t short /dev/{}'.format(name).split(), check=False) - + # Wait and show progress (in 10 second increments) for iteration in range(int(test_length*60/10)): # Update SMART data @@ -670,18 +704,24 @@ def run_nvme_smart(): 'passed', False) if test_passed: TESTS['NVMe/SMART']['Status'][name] = 'CS' + TESTS['NVMe/SMART']['Short Test'][name] = 'CS' else: TESTS['NVMe/SMART']['Status'][name] = 'NS' + TESTS['NVMe/SMART']['Short Test'][name] = 'NS' update_progress() print_standard('Done', timestamp=False) # Done run_program('tmux kill-pane -a'.split(), check=False) -def run_tests(tests): +def run_tests(tests, ticket_number=None): """Run selected hardware test(s).""" - print_log('Starting Hardware Diagnostics') - print_log('\nRunning tests: {}'.format(', '.join(tests))) + clear_screen() + print_standard('Starting Hardware Diagnostics') + if ticket_number: + print_standard(' For Ticket #{}'.format(ticket_number)) + print_standard(' ') + print_standard('Running tests: {}'.format(', '.join(tests))) # Enable selected tests for t in ['Prime95', 'NVMe/SMART', 'badblocks', 'iobenchmark']: TESTS[t]['Enabled'] = t in tests @@ -690,7 +730,6 @@ def run_tests(tests): # Initialize if TESTS['NVMe/SMART']['Enabled'] or TESTS['badblocks']['Enabled'] or TESTS['iobenchmark']['Enabled']: print_standard(' ') - print_standard('Scanning disks...') scan_disks() update_progress() @@ -698,22 +737,22 @@ def run_tests(tests): mprime_aborted = False if TESTS['Prime95']['Enabled']: try: - run_mprime() + run_mprime(ticket_number) except GenericError: mprime_aborted = True if not mprime_aborted: if TESTS['NVMe/SMART']['Enabled']: - run_nvme_smart() + run_nvme_smart(ticket_number) if TESTS['badblocks']['Enabled']: - run_badblocks() + run_badblocks(ticket_number) if TESTS['iobenchmark']['Enabled']: - run_iobenchmark() - + run_iobenchmark(ticket_number) + # Show results show_results() # Open log - if not TESTS['NVMe/SMART']['Quick']: + if not TESTS['NVMe/SMART']['Quick'] and ENABLED_OPEN_LOGS: try: popen_program(['nohup', 'leafpad', global_vars['LogFile']], pipe=True) except Exception: @@ -723,7 +762,6 @@ def run_tests(tests): def scan_disks(full_paths=False, only_path=None): """Scan for disks eligible for hardware testing.""" - clear_screen() # Get eligible disk list cmd = ['lsblk', '-J', '-O'] @@ -743,13 +781,18 @@ def scan_disks(full_paths=False, only_path=None): TESTS['iobenchmark']['Status'][d['name']] = 'Pending' else: # Skip WizardKit devices - wk_label = '{}_LINUX'.format(KIT_NAME_SHORT) - if wk_label not in [c.get('label', '') for c in d.get('children', [])]: + skip_dev=False + wk_label_regex = r'{}_(LINUX|UFD)'.format(KIT_NAME_SHORT) + for c in d.get('children', []): + r = re.search( + wk_label_regex, c.get('label', ''), re.IGNORECASE) + skip_dev = bool(r) + if not skip_dev: devs[d['name']] = {'lsblk': d} TESTS['NVMe/SMART']['Status'][d['name']] = 'Pending' TESTS['badblocks']['Status'][d['name']] = 'Pending' TESTS['iobenchmark']['Status'][d['name']] = 'Pending' - + for dev, data in devs.items(): # Get SMART attributes run_program( @@ -758,7 +801,7 @@ def scan_disks(full_paths=False, only_path=None): dev).split(), check = False) data['smartctl'] = get_smart_details(dev) - + # Get NVMe attributes if data['lsblk']['tran'] == 'nvme': cmd = 'sudo nvme smart-log /dev/{} -o json'.format(dev).split() @@ -782,7 +825,12 @@ def scan_disks(full_paths=False, only_path=None): ] if data.get('NVMe Disk', False): crit_warn = data['nvme-cli'].get('critical_warning', 1) - data['Quick Health OK'] = True if crit_warn == 0 else False + if crit_warn == 0: + dev_name = data['lsblk']['name'] + data['Quick Health OK'] = True + TESTS['NVMe/SMART']['Status'][dev_name] = 'CS' + else: + data['Quick Health OK'] = False elif set(wanted_smart_list).issubset(data['smartctl'].keys()): data['SMART Pass'] = data['smartctl'].get('smart_status', {}).get( 'passed', False) @@ -791,7 +839,7 @@ def scan_disks(full_paths=False, only_path=None): else: data['Quick Health OK'] = False data['SMART Support'] = False - + # Ask for manual overrides if necessary if TESTS['badblocks']['Enabled'] or TESTS['iobenchmark']['Enabled']: show_disk_details(data) @@ -989,13 +1037,13 @@ def update_io_progress(percent, rate, progress_file): bar_color = COLORS['CLEAR'] rate_color = COLORS['CLEAR'] step = get_graph_step(rate, scale=32) - if rate < IO_VARS['Threshold Fail']: + if rate < IO_VARS['Threshold Graph Fail']: bar_color = COLORS['RED'] rate_color = COLORS['YELLOW'] - elif rate < IO_VARS['Threshold Warn']: + elif rate < IO_VARS['Threshold Graph Warn']: bar_color = COLORS['YELLOW'] rate_color = COLORS['YELLOW'] - elif rate > IO_VARS['Threshold Great']: + elif rate > IO_VARS['Threshold Graph Great']: bar_color = COLORS['GREEN'] rate_color = COLORS['GREEN'] line = ' {p:5.1f}% {b_color}{b:<4} {r_color}{r:6.1f} Mb/s{c}\n'.format( From 83dda97ff62ace7e445816543ac72778e802243c Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 26 Nov 2018 19:13:00 -0700 Subject: [PATCH 023/265] Bugfix: launchers.py --- .bin/Scripts/settings/launchers.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.bin/Scripts/settings/launchers.py b/.bin/Scripts/settings/launchers.py index ea77d983..43e8e158 100644 --- a/.bin/Scripts/settings/launchers.py +++ b/.bin/Scripts/settings/launchers.py @@ -556,7 +556,8 @@ LAUNCHERS = { 'L_ITEM': 'IObitUninstallerPortable.exe', }, }, - } + }, +} if __name__ == '__main__': print("This file is not meant to be called directly.") From 10f2fca2bfa7e24d52e238e1d3ed611e5e9200fe Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 3 Dec 2018 17:52:07 -0700 Subject: [PATCH 024/265] Added classes DevObj and State --- .bin/Scripts/functions/hw_diags.py | 1310 +++++----------------------- 1 file changed, 221 insertions(+), 1089 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 169eb337..830d948a 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -1,1114 +1,246 @@ # Wizard Kit: Functions - HW Diagnostics import json +import re import time from functions.common import * # STATIC VARIABLES ATTRIBUTES = { - 'NVMe': { - 'critical_warning': {'Error': 1}, - 'media_errors': {'Error': 1}, - 'power_on_hours': {'Warning': 12000, 'Error': 18000, 'Ignore': True}, - 'unsafe_shutdowns': {'Warning': 1}, - }, - 'SMART': { - 5: {'Hex': '05', 'Error': 1}, - 9: {'Hex': '09', 'Warning': 12000, 'Error': 18000, 'Ignore': True}, - 10: {'Hex': '0A', 'Error': 1}, - 184: {'Hex': 'B8', 'Error': 1}, - 187: {'Hex': 'BB', 'Error': 1}, - 188: {'Hex': 'BC', 'Error': 1}, - 196: {'Hex': 'C4', 'Error': 1}, - 197: {'Hex': 'C5', 'Error': 1}, - 198: {'Hex': 'C6', 'Error': 1}, - 199: {'Hex': 'C7', 'Error': 1, 'Ignore': True}, - 201: {'Hex': 'C9', 'Error': 1}, - }, - } + 'NVMe': { + 'critical_warning': {'Error': 1}, + 'media_errors': {'Error': 1}, + 'power_on_hours': {'Warning': 12000, 'Error': 26298, 'Ignore': True}, + 'unsafe_shutdowns': {'Warning': 1}, + }, + 'SMART': { + 5: {'Hex': '05', 'Error': 1}, + 9: {'Hex': '09', 'Warning': 12000, 'Error': 26298, 'Ignore': True}, + 10: {'Hex': '0A', 'Error': 1}, + 184: {'Hex': 'B8', 'Error': 1}, + 187: {'Hex': 'BB', 'Error': 1}, + 188: {'Hex': 'BC', 'Error': 1}, + 196: {'Hex': 'C4', 'Error': 1}, + 197: {'Hex': 'C5', 'Error': 1}, + 198: {'Hex': 'C6', 'Error': 1}, + 199: {'Hex': 'C7', 'Error': 1, 'Ignore': True}, + 201: {'Hex': 'C9', 'Error': 1}, + }, + } IO_VARS = { - 'Block Size': 512*1024, - 'Chunk Size': 32*1024**2, - 'Minimum Dev Size': 8*1024**3, - 'Minimum Test Size': 10*1024**3, - 'Alt Test Size Factor': 0.01, - 'Progress Refresh Rate': 5, - 'Scale 8': [2**(0.56*(x+1))+(16*(x+1)) for x in range(8)], - 'Scale 16': [2**(0.56*(x+1))+(16*(x+1)) for x in range(16)], - 'Scale 32': [2**(0.56*(x+1)/2)+(16*(x+1)/2) for x in range(32)], - 'Threshold Graph Fail': 65*1024**2, - 'Threshold Graph Warn': 135*1024**2, - 'Threshold Graph Great': 750*1024**2, - 'Threshold HDD Min': 50*1024**2, - 'Threshold HDD High Avg': 75*1024**2, - 'Threshold HDD Low Avg': 65*1024**2, - 'Threshold SSD Min': 90*1024**2, - 'Threshold SSD High Avg': 135*1024**2, - 'Threshold SSD Low Avg': 100*1024**2, - 'Graph Horizontal': ('▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'), - 'Graph Horizontal Width': 40, - 'Graph Vertical': ( - '▏', '▎', '▍', '▌', - '▋', '▊', '▉', '█', - '█▏', '█▎', '█▍', '█▌', - '█▋', '█▊', '█▉', '██', - '██▏', '██▎', '██▍', '██▌', - '██▋', '██▊', '██▉', '███', - '███▏', '███▎', '███▍', '███▌', - '███▋', '███▊', '███▉', '████'), - } -TESTS = { - 'Prime95': { - 'Enabled': False, - 'Status': 'Pending', - }, - 'NVMe/SMART': { - 'Enabled': False, - 'Quick': False, - 'Short Test': {}, - 'Status': {}, - }, - 'badblocks': { - 'Enabled': False, - 'Results': {}, - 'Status': {}, - }, - 'iobenchmark': { - 'Data': {}, - 'Enabled': False, - 'Results': {}, - 'Status': {}, - }, - } + 'Block Size': 512*1024, + 'Chunk Size': 32*1024**2, + 'Minimum Dev Size': 8*1024**3, + 'Minimum Test Size': 10*1024**3, + 'Alt Test Size Factor': 0.01, + 'Progress Refresh Rate': 5, + 'Scale 8': [2**(0.56*(x+1))+(16*(x+1)) for x in range(8)], + 'Scale 16': [2**(0.56*(x+1))+(16*(x+1)) for x in range(16)], + 'Scale 32': [2**(0.56*(x+1)/2)+(16*(x+1)/2) for x in range(32)], + 'Threshold Graph Fail': 65*1024**2, + 'Threshold Graph Warn': 135*1024**2, + 'Threshold Graph Great': 750*1024**2, + 'Threshold HDD Min': 50*1024**2, + 'Threshold HDD High Avg': 75*1024**2, + 'Threshold HDD Low Avg': 65*1024**2, + 'Threshold SSD Min': 90*1024**2, + 'Threshold SSD High Avg': 135*1024**2, + 'Threshold SSD Low Avg': 100*1024**2, + 'Graph Horizontal': ('▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'), + 'Graph Horizontal Width': 40, + 'Graph Vertical': ( + '▏', '▎', '▍', '▌', + '▋', '▊', '▉', '█', + '█▏', '█▎', '█▍', '█▌', + '█▋', '█▊', '█▉', '██', + '██▏', '██▎', '██▍', '██▌', + '██▋', '██▊', '██▉', '███', + '███▏', '███▎', '███▍', '███▌', + '███▋', '███▊', '███▉', '████'), + } +KEY_NVME = 'nvme_smart_health_information_log' +KEY_SMART = 'ata_smart_attributes' +SIDE_PATH_WIDTH = 21 +# Classes +class DevObj(): + """Device object for tracking device specific data.""" + def __init__(self, dev_path): + self.failing = False + self.nvme_attributes = {} + self.override = False + self.path = dev_path + self.smart_attributes = {} + self.tests = { + 'NVMe / SMART': {'Result': None, 'Status': None}, + 'badblocks': {'Result': None, 'Status': None}, + 'I/O Benchmark': { + 'Result': None, + 'Status': None, + 'Read Rates': [], + 'Graph Data': []}, + } + self.get_details() + + def get_details(self): + """Get data from smartctl.""" + cmd = ['sudo', 'smartctl', '--all', '--json', self.path] + result = run_program(cmd, check=False) + self.data = json.loads(result.stdout.decode()) + + # Check for attributes + if KEY_NVME in self.data: + self.nvme_attributes.update(self.data[KEY_NVME]) + elif KEY_SMART in self.data: + for a in self.data[KEY_SMART].get('table', {}): + _id = str(a.get('id', 'UNKNOWN')) + _name = str(a.get('name', 'UNKNOWN')) + _raw = a.get('raw', {}).get('value', -1) + _raw_str = a.get('raw', {}).get('string', 'UNKNOWN') + + # Fix power-on time + _r = re.match(r'^(\d+)[Hh].*', _raw_str) + if _id == '9' and _r: + try: + _raw = int(_r.group(1)) + except ValueError: + # That's fine + pass + self.smart_attributes[_id] = { + 'name': _name, 'raw': _raw, 'raw_str': _raw_str} + +class State(): + """Object to track device objects and overall state.""" + def __init__(self): + self.devs = [] + self.finished = False + self.progress_out = '{}/progress.out'.format(global_vars['LogDir']) + self.started = False + self.tests = { + 'Prime95': {'Enabled': False, 'Result': None, 'Status': None}, + 'NVMe / SMART': {'Enabled': False}, + 'badblocks': {'Enabled': False}, + 'I/O Benchmark': {'Enabled': False}, + } + self.add_devs() + + def add_devs(self): + """Add all block devices listed by lsblk.""" + cmd = ['lsblk', '--json', '--nodeps', '--paths'] + result = run_program(cmd, check=False) + json_data = json.loads(result.stdout.decode()) + for dev in json_data['blockdevices']: + self.devs.append(DevObj(dev['name'])) + +# Functions def generate_horizontal_graph(rates, oneline=False): - """Generate two-line horizontal graph from rates, returns str.""" - line_1 = '' - line_2 = '' - line_3 = '' - line_4 = '' - for r in rates: - step = get_graph_step(r, scale=32) - if oneline: - step = get_graph_step(r, scale=8) - - # Set color - r_color = COLORS['CLEAR'] - if r < IO_VARS['Threshold Graph Fail']: - r_color = COLORS['RED'] - elif r < IO_VARS['Threshold Graph Warn']: - r_color = COLORS['YELLOW'] - elif r > IO_VARS['Threshold Graph Great']: - r_color = COLORS['GREEN'] - - # Build graph - full_block = '{}{}'.format(r_color, IO_VARS['Graph Horizontal'][-1]) - if step >= 24: - line_1 += '{}{}'.format(r_color, IO_VARS['Graph Horizontal'][step-24]) - line_2 += full_block - line_3 += full_block - line_4 += full_block - elif step >= 16: - line_1 += ' ' - line_2 += '{}{}'.format(r_color, IO_VARS['Graph Horizontal'][step-16]) - line_3 += full_block - line_4 += full_block - elif step >= 8: - line_1 += ' ' - line_2 += ' ' - line_3 += '{}{}'.format(r_color, IO_VARS['Graph Horizontal'][step-8]) - line_4 += full_block - else: - line_1 += ' ' - line_2 += ' ' - line_3 += ' ' - line_4 += '{}{}'.format(r_color, IO_VARS['Graph Horizontal'][step]) - line_1 += COLORS['CLEAR'] - line_2 += COLORS['CLEAR'] - line_3 += COLORS['CLEAR'] - line_4 += COLORS['CLEAR'] + """Generate two-line horizontal graph from rates, returns str.""" + line_1 = '' + line_2 = '' + line_3 = '' + line_4 = '' + for r in rates: + step = get_graph_step(r, scale=32) if oneline: - return line_4 + step = get_graph_step(r, scale=8) + + # Set color + r_color = COLORS['CLEAR'] + if r < IO_VARS['Threshold Graph Fail']: + r_color = COLORS['RED'] + elif r < IO_VARS['Threshold Graph Warn']: + r_color = COLORS['YELLOW'] + elif r > IO_VARS['Threshold Graph Great']: + r_color = COLORS['GREEN'] + + # Build graph + full_block = '{}{}'.format(r_color, IO_VARS['Graph Horizontal'][-1]) + if step >= 24: + line_1 += '{}{}'.format(r_color, IO_VARS['Graph Horizontal'][step-24]) + line_2 += full_block + line_3 += full_block + line_4 += full_block + elif step >= 16: + line_1 += ' ' + line_2 += '{}{}'.format(r_color, IO_VARS['Graph Horizontal'][step-16]) + line_3 += full_block + line_4 += full_block + elif step >= 8: + line_1 += ' ' + line_2 += ' ' + line_3 += '{}{}'.format(r_color, IO_VARS['Graph Horizontal'][step-8]) + line_4 += full_block else: - return '\n'.join([line_1, line_2, line_3, line_4]) + line_1 += ' ' + line_2 += ' ' + line_3 += ' ' + line_4 += '{}{}'.format(r_color, IO_VARS['Graph Horizontal'][step]) + line_1 += COLORS['CLEAR'] + line_2 += COLORS['CLEAR'] + line_3 += COLORS['CLEAR'] + line_4 += COLORS['CLEAR'] + if oneline: + return line_4 + else: + return '\n'.join([line_1, line_2, line_3, line_4]) def get_graph_step(rate, scale=16): - """Get graph step based on rate and scale, returns int.""" - m_rate = rate / (1024**2) - step = 0 - scale_name = 'Scale {}'.format(scale) - for x in range(scale-1, -1, -1): - # Iterate over scale backwards - if m_rate >= IO_VARS[scale_name][x]: - step = x - break - return step + """Get graph step based on rate and scale, returns int.""" + m_rate = rate / (1024**2) + step = 0 + scale_name = 'Scale {}'.format(scale) + for x in range(scale-1, -1, -1): + # Iterate over scale backwards + if m_rate >= IO_VARS[scale_name][x]: + step = x + break + return step def get_read_rate(s): - """Get read rate in bytes/s from dd progress output.""" - real_rate = None - if re.search(r'[KMGT]B/s', s): - human_rate = re.sub(r'^.*\s+(\d+\.?\d*)\s+(.B)/s\s*$', r'\1 \2', s) - real_rate = convert_to_bytes(human_rate) - return real_rate - -def get_smart_details(dev): - """Get SMART data for dev if possible, returns dict.""" - cmd = 'sudo smartctl --all --json {}{}'.format( - '' if '/dev/' in dev else '/dev/', - dev).split() - result = run_program(cmd, check=False) - try: - return json.loads(result.stdout.decode()) - except Exception: - # Let other sections deal with the missing data - return {} - -def get_smart_value(smart_data, smart_id): - """Get SMART value from table, returns int or None.""" - value = None - table = smart_data.get('ata_smart_attributes', {}).get('table', []) - for row in table: - if str(row.get('id', '?')) == str(smart_id): - value = row.get('raw', {}).get('value', None) - return value + """Get read rate in bytes/s from dd progress output.""" + real_rate = None + if re.search(r'[KMGT]B/s', s): + human_rate = re.sub(r'^.*\s+(\d+\.?\d*)\s+(.B)/s\s*$', r'\1 \2', s) + real_rate = convert_to_bytes(human_rate) + return real_rate def get_status_color(s): - """Get color based on status, returns str.""" - color = COLORS['CLEAR'] - if s in ['Denied', 'ERROR', 'NS', 'OVERRIDE']: - color = COLORS['RED'] - elif s in ['Aborted', 'Unknown', 'Working', 'Skipped']: - color = COLORS['YELLOW'] - elif s in ['CS']: - color = COLORS['GREEN'] - return color - -def menu_diags(*args): - """Main HW-Diagnostic menu.""" - diag_modes = [ - {'Name': 'All tests', - 'Tests': ['Prime95', 'NVMe/SMART', 'badblocks', 'iobenchmark']}, - {'Name': 'Prime95', - 'Tests': ['Prime95']}, - {'Name': 'All drive tests', - 'Tests': ['NVMe/SMART', 'badblocks', 'iobenchmark']}, - {'Name': 'NVMe/SMART', - 'Tests': ['NVMe/SMART']}, - {'Name': 'badblocks', - 'Tests': ['badblocks']}, - {'Name': 'I/O Benchmark', - 'Tests': ['iobenchmark']}, - {'Name': 'Quick drive test', - 'Tests': ['Quick', 'NVMe/SMART']}, - ] - actions = [ - {'Letter': 'A', 'Name': 'Audio test'}, - {'Letter': 'K', 'Name': 'Keyboard test'}, - {'Letter': 'N', 'Name': 'Network test'}, - {'Letter': 'M', 'Name': 'Screen Saver - Matrix', 'CRLF': True}, - {'Letter': 'P', 'Name': 'Screen Saver - Pipes'}, - {'Letter': 'Q', 'Name': 'Quit', 'CRLF': True}, - ] - - # CLI-mode actions - if 'DISPLAY' not in global_vars['Env']: - actions.extend([ - {'Letter': 'R', 'Name': 'Reboot', 'CRLF': True}, - {'Letter': 'S', 'Name': 'Shutdown'}, - ]) - - # Quick disk check - if 'quick' in args: - run_tests(['Quick', 'NVMe/SMART']) - exit_script() - - # Show menu - while True: - selection = menu_select( - title = 'Hardware Diagnostics: Menu', - main_entries = diag_modes, - action_entries = actions, - spacer = '──────────────────────────') - if selection.isnumeric(): - ticket_number = None - if diag_modes[int(selection)-1]['Name'] != 'Quick drive test': - clear_screen() - print_standard(' ') - ticket_number = get_ticket_number() - # Save log for non-quick tests - global_vars['Date-Time'] = time.strftime("%Y-%m-%d_%H%M_%z") - global_vars['LogDir'] = '{}/Logs/{}_{}'.format( - global_vars['Env']['HOME'], - ticket_number, - global_vars['Date-Time']) - os.makedirs(global_vars['LogDir'], exist_ok=True) - global_vars['LogFile'] = '{}/Hardware Diagnostics.log'.format( - global_vars['LogDir']) - run_tests(diag_modes[int(selection)-1]['Tests'], ticket_number) - elif selection == 'A': - run_program(['hw-diags-audio'], check=False, pipe=False) - pause('Press Enter to return to main menu... ') - elif selection == 'K': - run_program(['xev', '-event', 'keyboard'], check=False, pipe=False) - elif selection == 'N': - run_program(['hw-diags-network'], check=False, pipe=False) - pause('Press Enter to return to main menu... ') - elif selection == 'M': - run_program(['cmatrix', '-abs'], check=False, pipe=False) - elif selection == 'P': - run_program( - 'pipes -t 0 -t 1 -t 2 -t 3 -p 5 -R -r 4000'.split(), - check=False, pipe=False) - elif selection == 'R': - run_program(['systemctl', 'reboot']) - elif selection == 'S': - run_program(['systemctl', 'poweroff']) - elif selection == 'Q': - break - -def run_badblocks(ticket_number): - """Run a read-only test for all detected disks.""" - aborted = False - clear_screen() - print_log('\nStart badblocks test(s)\n') - progress_file = '{}/badblocks_progress.out'.format(global_vars['LogDir']) - update_progress() - - # Set Window layout and start test - run_program('tmux split-window -dhl 15 watch -c -n1 -t cat {}'.format( - TESTS['Progress Out']).split()) - - # Show disk details - for name, dev in sorted(TESTS['badblocks']['Devices'].items()): - show_disk_details(dev) - print_standard(' ') - update_progress() - - # Run - print_standard('Running badblock test(s):') - for name, dev in sorted(TESTS['badblocks']['Devices'].items()): - cur_status = TESTS['badblocks']['Status'][name] - nvme_smart_status = TESTS['NVMe/SMART']['Status'].get(name, None) - if cur_status == 'Denied': - # Skip denied disks - continue - if nvme_smart_status == 'NS': - TESTS['badblocks']['Status'][name] = 'Skipped' - else: - # Not testing SMART, SMART CS, or SMART OVERRIDE - TESTS['badblocks']['Status'][name] = 'Working' - update_progress() - print_standard(' /dev/{:11} '.format(name+'...'), end='', flush=True) - run_program('tmux split-window -dl 5 {} {} {}'.format( - 'hw-diags-badblocks', - '/dev/{}'.format(name), - progress_file).split()) - wait_for_process('badblocks') - print_standard('Done', timestamp=False) - - # Check results - if os.path.exists(progress_file): - with open(progress_file, 'r') as f: - text = f.read() - TESTS['badblocks']['Results'][name] = text - r = re.search(r'Pass completed.*0/0/0 errors', text) - if r: - TESTS['badblocks']['Status'][name] = 'CS' - else: - TESTS['badblocks']['Status'][name] = 'NS' - - # Move temp file - shutil.move(progress_file, '{}/badblocks-{}.log'.format( - global_vars['LogDir'], name)) - else: - TESTS['badblocks']['Status'][name] = 'NS' - update_progress() - - # Done - run_program('tmux kill-pane -a'.split(), check=False) - pass - -def run_iobenchmark(ticket_number): - """Run a read-only test for all detected disks.""" - aborted = False - clear_screen() - print_log('\nStart I/O Benchmark test(s)\n') - progress_file = '{}/iobenchmark_progress.out'.format(global_vars['LogDir']) - update_progress() - - # Set Window layout and start test - run_program('tmux split-window -dhl 15 watch -c -n1 -t cat {}'.format( - TESTS['Progress Out']).split()) - - # Show disk details - for name, dev in sorted(TESTS['iobenchmark']['Devices'].items()): - show_disk_details(dev) - print_standard(' ') - update_progress() - - # Run - print_standard('Running benchmark test(s):') - for name, dev in sorted(TESTS['iobenchmark']['Devices'].items()): - cur_status = TESTS['iobenchmark']['Status'][name] - nvme_smart_status = TESTS['NVMe/SMART']['Status'].get(name, None) - bb_status = TESTS['badblocks']['Status'].get(name, None) - if cur_status == 'Denied': - # Skip denied disks - continue - if nvme_smart_status == 'NS': - TESTS['iobenchmark']['Status'][name] = 'Skipped' - elif bb_status in ['NS', 'Skipped']: - TESTS['iobenchmark']['Status'][name] = 'Skipped' - else: - # (SMART tests not run or CS/OVERRIDE) - # AND (BADBLOCKS tests not run or CS) - TESTS['iobenchmark']['Status'][name] = 'Working' - update_progress() - print_standard(' /dev/{:11} '.format(name+'...'), end='', flush=True) - - # Get dev size - cmd = 'sudo lsblk -bdno size /dev/{}'.format(name) - try: - result = run_program(cmd.split()) - dev_size = result.stdout.decode().strip() - dev_size = int(dev_size) - except: - # Failed to get dev size, requires manual testing instead - TESTS['iobenchmark']['Status'][name] = 'ERROR' - continue - if dev_size < IO_VARS['Minimum Dev Size']: - TESTS['iobenchmark']['Status'][name] = 'ERROR' - continue - - # Calculate dd values - ## test_size is the area to be read in bytes - ## If the dev is < 10Gb then it's the whole dev - ## Otherwise it's the larger of 10Gb or 1% of the dev - ## - ## test_chunks is the number of groups of "Chunk Size" in test_size - ## This number is reduced to a multiple of the graph width in - ## order to allow for the data to be condensed cleanly - ## - ## skip_blocks is the number of "Block Size" groups not tested - ## skip_count is the number of blocks to skip per test_chunk - ## skip_extra is how often to add an additional skip block - ## This is needed to ensure an even testing across the dev - ## This is calculated by using the fractional amount left off - ## of the skip_count variable - test_size = min(IO_VARS['Minimum Test Size'], dev_size) - test_size = max( - test_size, dev_size*IO_VARS['Alt Test Size Factor']) - test_chunks = int(test_size // IO_VARS['Chunk Size']) - test_chunks -= test_chunks % IO_VARS['Graph Horizontal Width'] - test_size = test_chunks * IO_VARS['Chunk Size'] - skip_blocks = int((dev_size - test_size) // IO_VARS['Block Size']) - skip_count = int((skip_blocks / test_chunks) // 1) - skip_extra = 0 - try: - skip_extra = 1 + int(1 / ((skip_blocks / test_chunks) % 1)) - except ZeroDivisionError: - # skip_extra == 0 is fine - pass - - # Open dd progress pane after initializing file - with open(progress_file, 'w') as f: - f.write('') - sleep(1) - cmd = 'tmux split-window -dp 75 -PF #D tail -f {}'.format( - progress_file) - result = run_program(cmd.split()) - bottom_pane = result.stdout.decode().strip() - - # Run dd read tests - offset = 0 - TESTS['iobenchmark']['Data'][name] = { - 'Graph': [], - 'Read Rates': []} - for i in range(test_chunks): - i += 1 - s = skip_count - c = int(IO_VARS['Chunk Size'] / IO_VARS['Block Size']) - if skip_extra and i % skip_extra == 0: - s += 1 - cmd = 'sudo dd bs={b} skip={s} count={c} if=/dev/{n} of={o} iflag=direct'.format( - b=IO_VARS['Block Size'], - s=offset+s, - c=c, - n=name, - o='/dev/null') - result = run_program(cmd.split()) - result_str = result.stderr.decode().replace('\n', '') - cur_rate = get_read_rate(result_str) - TESTS['iobenchmark']['Data'][name]['Read Rates'].append( - cur_rate) - TESTS['iobenchmark']['Data'][name]['Graph'].append( - '{percent:0.1f} {rate}'.format( - percent=i/test_chunks*100, - rate=int(cur_rate/(1024**2)))) - if i % IO_VARS['Progress Refresh Rate'] == 0: - # Update vertical graph - update_io_progress( - percent=i/test_chunks*100, - rate=cur_rate, - progress_file=progress_file) - # Update offset - offset += s + c - print_standard('Done', timestamp=False) - - # Close bottom pane - run_program(['tmux', 'kill-pane', '-t', bottom_pane]) - - # Build report - avg_min_max = 'Average read speed: {:3.1f} MB/s (Min: {:3.1f}, Max: {:3.1f})'.format( - sum(TESTS['iobenchmark']['Data'][name]['Read Rates'])/len( - TESTS['iobenchmark']['Data'][name]['Read Rates'])/(1024**2), - min(TESTS['iobenchmark']['Data'][name]['Read Rates'])/(1024**2), - max(TESTS['iobenchmark']['Data'][name]['Read Rates'])/(1024**2)) - TESTS['iobenchmark']['Data'][name]['Avg/Min/Max'] = avg_min_max - TESTS['iobenchmark']['Data'][name]['Merged Rates'] = [] - pos = 0 - width = int(test_chunks / IO_VARS['Graph Horizontal Width']) - for i in range(IO_VARS['Graph Horizontal Width']): - # Append average rate for WIDTH number of rates to new array - TESTS['iobenchmark']['Data'][name]['Merged Rates'].append(sum( - TESTS['iobenchmark']['Data'][name]['Read Rates'][pos:pos+width])/width) - pos += width - report = generate_horizontal_graph( - TESTS['iobenchmark']['Data'][name]['Merged Rates']) - report += '\n{}'.format(avg_min_max) - TESTS['iobenchmark']['Results'][name] = report - - # Set CS/NS - min_read = min(TESTS['iobenchmark']['Data'][name]['Read Rates']) - avg_read = sum( - TESTS['iobenchmark']['Data'][name]['Read Rates'])/len( - TESTS['iobenchmark']['Data'][name]['Read Rates']) - dev_rotational = dev['lsblk'].get('rota', None) - if dev_rotational == "0": - # Use SSD scale - thresh_min = IO_VARS['Threshold SSD Min'] - thresh_high_avg = IO_VARS['Threshold SSD High Avg'] - thresh_low_avg = IO_VARS['Threshold SSD Low Avg'] - else: - # Use HDD scale - thresh_min = IO_VARS['Threshold HDD Min'] - thresh_high_avg = IO_VARS['Threshold HDD High Avg'] - thresh_low_avg = IO_VARS['Threshold HDD Low Avg'] - if min_read <= thresh_min and avg_read <= thresh_high_avg: - TESTS['iobenchmark']['Status'][name] = 'NS' - elif avg_read <= thresh_low_avg: - TESTS['iobenchmark']['Status'][name] = 'NS' - else: - TESTS['iobenchmark']['Status'][name] = 'CS' - - # Save logs - dest_filename = '{}/iobenchmark-{}.log'.format(global_vars['LogDir'], name) - shutil.move(progress_file, dest_filename) - with open(dest_filename.replace('.', '-raw.'), 'a') as f: - f.write('\n'.join(TESTS['iobenchmark']['Data'][name]['Graph'])) - update_progress() - - # Done - run_program('tmux kill-pane -a'.split(), check=False) - pass - -def run_mprime(ticket_number): - """Run Prime95 for MPRIME_LIMIT minutes while showing the temps.""" - aborted = False - print_log('\nStart Prime95 test') - TESTS['Prime95']['Status'] = 'Working' - update_progress() - - # Set Window layout and start test - run_program('tmux split-window -dl 10 -c {wd} {cmd} {wd}'.format( - wd=global_vars['TmpDir'], cmd='hw-diags-prime95').split()) - run_program('tmux split-window -dhl 15 watch -c -n1 -t cat {}'.format( - TESTS['Progress Out']).split()) - run_program('tmux split-window -bd watch -c -n1 -t hw-sensors'.split()) - run_program('tmux resize-pane -y 3'.split()) - - # Start test - run_program(['apple-fans', 'max']) - try: - for i in range(int(MPRIME_LIMIT)): - clear_screen() - min_left = int(MPRIME_LIMIT) - i - print_standard('Running Prime95 ({} minute{} left)'.format( - min_left, - 's' if min_left != 1 else '')) - print_warning('If running too hot, press CTRL+c to abort the test') - sleep(60) - except KeyboardInterrupt: - # Catch CTRL+C - aborted = True - TESTS['Prime95']['Status'] = 'Aborted' - print_warning('\nAborted.') - update_progress() - - # Save "final" temps - run_program( - cmd = 'hw-sensors >> "{}/Final Temps.out"'.format( - global_vars['LogDir']).split(), - check = False, - pipe = False, - shell = True) - run_program( - cmd = 'hw-sensors --nocolor >> "{}/Final Temps.log"'.format( - global_vars['LogDir']).split(), - check = False, - pipe = False, - shell = True) - - # Stop test - run_program('killall -s INT mprime'.split(), check=False) - run_program(['apple-fans', 'auto']) - - # Move logs to Ticket folder - for item in os.scandir(global_vars['TmpDir']): - try: - shutil.move(item.path, global_vars['LogDir']) - except Exception: - print_error('ERROR: Failed to move "{}" to "{}"'.format( - item.path, - global_vars['LogDir'])) - - # Check logs - TESTS['Prime95']['NS'] = False - TESTS['Prime95']['CS'] = False - log = '{}/results.txt'.format(global_vars['LogDir']) - if os.path.exists(log): - with open(log, 'r') as f: - text = f.read() - TESTS['Prime95']['results.txt'] = text - r = re.search(r'(error|fail)', text) - TESTS['Prime95']['NS'] = bool(r) - log = '{}/prime.log'.format(global_vars['LogDir']) - if os.path.exists(log): - with open(log, 'r') as f: - text = f.read() - TESTS['Prime95']['prime.log'] = text - r = re.search(r'completed.*0 errors, 0 warnings', text) - TESTS['Prime95']['CS'] = bool(r) - - # Update status - if not aborted: - if TESTS['Prime95']['NS']: - TESTS['Prime95']['Status'] = 'NS' - elif TESTS['Prime95']['CS']: - TESTS['Prime95']['Status'] = 'CS' - else: - TESTS['Prime95']['Status'] = 'Unknown' - update_progress() - - if aborted: - if TESTS['NVMe/SMART']['Enabled'] or TESTS['badblocks']['Enabled']: - if not ask('Proceed to next test?'): - for name in TESTS['NVMe/SMART']['Devices'].keys(): - for t in ['NVMe/SMART', 'badblocks', 'iobenchmark']: - cur_status = TESTS[t]['Status'][name] - if cur_status not in ['CS', 'Denied', 'NS']: - TESTS[t]['Status'][name] = 'Aborted' - run_program('tmux kill-pane -a'.split()) - raise GenericError - - # Done - run_program('tmux kill-pane -a'.split()) - -def run_nvme_smart(ticket_number): - """Run the built-in NVMe or SMART test for all detected disks.""" - aborted = False - clear_screen() - print_log('\nStart NVMe/SMART test(s)\n') - progress_file = '{}/selftest_progress.out'.format(global_vars['LogDir']) - update_progress() - - # Set Window layout and start test - run_program('tmux split-window -dl 3 watch -c -n1 -t cat {}'.format( - progress_file).split()) - run_program('tmux split-window -dhl 15 watch -c -n1 -t cat {}'.format( - TESTS['Progress Out']).split()) - - # Show disk details - for name, dev in sorted(TESTS['NVMe/SMART']['Devices'].items()): - show_disk_details(dev) - print_standard(' ') - update_progress() - - # Run - for name, dev in sorted(TESTS['NVMe/SMART']['Devices'].items()): - TESTS['NVMe/SMART']['Short Test'][name] = None - cur_status = TESTS['NVMe/SMART']['Status'][name] - if cur_status == 'OVERRIDE': - # Skipping test per user request - continue - if TESTS['NVMe/SMART']['Quick'] or dev.get('NVMe Disk', False): - # Skip SMART self-tests for quick checks and NVMe disks - if dev['Quick Health OK']: - TESTS['NVMe/SMART']['Status'][name] = 'CS' - else: - TESTS['NVMe/SMART']['Status'][name] = 'NS' - elif not dev['Quick Health OK']: - # SMART overall == Failed or attributes bad, avoid self-test - TESTS['NVMe/SMART']['Status'][name] = 'NS' - else: - # Start SMART short self-test - test_length = dev['smartctl'].get( - 'ata_smart_data', {}).get( - 'self_test', {}).get( - 'polling_minutes', {}).get( - 'short', 5) - test_length = int(test_length) + 5 - TESTS['NVMe/SMART']['Status'][name] = 'Working' - update_progress() - print_standard('Running SMART short self-test(s):') - print_standard( - ' /dev/{:8}({} minutes)... '.format(name, test_length), - end='', flush=True) - run_program( - 'sudo smartctl -t short /dev/{}'.format(name).split(), - check=False) - - # Wait and show progress (in 10 second increments) - for iteration in range(int(test_length*60/10)): - # Update SMART data - dev['smartctl'] = get_smart_details(name) - - # Check if test is complete - if iteration >= 6: - done = dev['smartctl'].get( - 'ata_smart_data', {}).get( - 'self_test', {}).get( - 'status', {}).get( - 'passed', False) - if done: - break - - # Update progress_file - with open(progress_file, 'w') as f: - f.write('SMART self-test status:\n {}'.format( - dev['smartctl'].get( - 'ata_smart_data', {}).get( - 'self_test', {}).get( - 'status', {}).get( - 'string', 'unknown'))) - sleep(10) - os.remove(progress_file) - - # Check result - test_passed = dev['smartctl'].get( - 'ata_smart_data', {}).get( - 'self_test', {}).get( - 'status', {}).get( - 'passed', False) - if test_passed: - TESTS['NVMe/SMART']['Status'][name] = 'CS' - TESTS['NVMe/SMART']['Short Test'][name] = 'CS' - else: - TESTS['NVMe/SMART']['Status'][name] = 'NS' - TESTS['NVMe/SMART']['Short Test'][name] = 'NS' - update_progress() - print_standard('Done', timestamp=False) - - # Done - run_program('tmux kill-pane -a'.split(), check=False) - -def run_tests(tests, ticket_number=None): - """Run selected hardware test(s).""" - clear_screen() - print_standard('Starting Hardware Diagnostics') - if ticket_number: - print_standard(' For Ticket #{}'.format(ticket_number)) - print_standard(' ') - print_standard('Running tests: {}'.format(', '.join(tests))) - # Enable selected tests - for t in ['Prime95', 'NVMe/SMART', 'badblocks', 'iobenchmark']: - TESTS[t]['Enabled'] = t in tests - TESTS['NVMe/SMART']['Quick'] = 'Quick' in tests - - # Initialize - if TESTS['NVMe/SMART']['Enabled'] or TESTS['badblocks']['Enabled'] or TESTS['iobenchmark']['Enabled']: - print_standard(' ') - scan_disks() - update_progress() - - # Run - mprime_aborted = False - if TESTS['Prime95']['Enabled']: - try: - run_mprime(ticket_number) - except GenericError: - mprime_aborted = True - if not mprime_aborted: - if TESTS['NVMe/SMART']['Enabled']: - run_nvme_smart(ticket_number) - if TESTS['badblocks']['Enabled']: - run_badblocks(ticket_number) - if TESTS['iobenchmark']['Enabled']: - run_iobenchmark(ticket_number) - - # Show results - show_results() - - # Open log - if not TESTS['NVMe/SMART']['Quick'] and ENABLED_OPEN_LOGS: - try: - popen_program(['nohup', 'leafpad', global_vars['LogFile']], pipe=True) - except Exception: - print_error('ERROR: Failed to open log: {}'.format( - global_vars['LogFile'])) - pause('Press Enter to exit...') - -def scan_disks(full_paths=False, only_path=None): - """Scan for disks eligible for hardware testing.""" - - # Get eligible disk list - cmd = ['lsblk', '-J', '-O'] - if full_paths: - cmd.append('-p') - if only_path: - cmd.append(only_path) - result = run_program(cmd) - json_data = json.loads(result.stdout.decode()) - devs = {} - for d in json_data.get('blockdevices', []): - if d['type'] == 'disk': - if d['hotplug'] == '0': - devs[d['name']] = {'lsblk': d} - TESTS['NVMe/SMART']['Status'][d['name']] = 'Pending' - TESTS['badblocks']['Status'][d['name']] = 'Pending' - TESTS['iobenchmark']['Status'][d['name']] = 'Pending' - else: - # Skip WizardKit devices - skip_dev=False - wk_label_regex = r'{}_(LINUX|UFD)'.format(KIT_NAME_SHORT) - for c in d.get('children', []): - r = re.search( - wk_label_regex, c.get('label', ''), re.IGNORECASE) - skip_dev = bool(r) - if not skip_dev: - devs[d['name']] = {'lsblk': d} - TESTS['NVMe/SMART']['Status'][d['name']] = 'Pending' - TESTS['badblocks']['Status'][d['name']] = 'Pending' - TESTS['iobenchmark']['Status'][d['name']] = 'Pending' - - for dev, data in devs.items(): - # Get SMART attributes - run_program( - cmd = 'sudo smartctl -s on {}{}'.format( - '' if full_paths else '/dev/', - dev).split(), - check = False) - data['smartctl'] = get_smart_details(dev) - - # Get NVMe attributes - if data['lsblk']['tran'] == 'nvme': - cmd = 'sudo nvme smart-log /dev/{} -o json'.format(dev).split() - cmd = 'sudo nvme smart-log {}{} -o json'.format( - '' if full_paths else '/dev/', - dev).split() - result = run_program(cmd, check=False) - try: - data['nvme-cli'] = json.loads(result.stdout.decode()) - except Exception: - # Let other sections deal with the missing data - data['nvme-cli'] = {} - data['NVMe Disk'] = True - - # Set "Quick Health OK" value - ## NOTE: If False then require override for badblocks test - wanted_smart_list = [ - 'ata_smart_attributes', - 'ata_smart_data', - 'smart_status', - ] - if data.get('NVMe Disk', False): - crit_warn = data['nvme-cli'].get('critical_warning', 1) - if crit_warn == 0: - dev_name = data['lsblk']['name'] - data['Quick Health OK'] = True - TESTS['NVMe/SMART']['Status'][dev_name] = 'CS' - else: - data['Quick Health OK'] = False - elif set(wanted_smart_list).issubset(data['smartctl'].keys()): - data['SMART Pass'] = data['smartctl'].get('smart_status', {}).get( - 'passed', False) - data['Quick Health OK'] = data['SMART Pass'] - data['SMART Support'] = True - else: - data['Quick Health OK'] = False - data['SMART Support'] = False - - # Ask for manual overrides if necessary - if TESTS['badblocks']['Enabled'] or TESTS['iobenchmark']['Enabled']: - show_disk_details(data) - needs_override = False - if not data['Quick Health OK']: - needs_override = True - print_warning( - "WARNING: Health can't be confirmed for: /dev/{}".format(dev)) - if get_smart_value(data['smartctl'], '199'): - # SMART attribute present and it's value is non-zero - needs_override = True - print_warning( - 'WARNING: SMART 199/C7 error detected on /dev/{}'.format(dev)) - print_standard(' (Have you tried swapping the drive cable?)') - if needs_override: - dev_name = data['lsblk']['name'] - print_standard(' ') - if ask('Run tests on this device anyway?'): - TESTS['NVMe/SMART']['Status'][dev_name] = 'OVERRIDE' - else: - TESTS['NVMe/SMART']['Status'][dev_name] = 'Skipped' - TESTS['badblocks']['Status'][dev_name] = 'Denied' - TESTS['iobenchmark']['Status'][dev_name] = 'Denied' - print_standard(' ') # In case there's more than one "OVERRIDE" disk - - TESTS['NVMe/SMART']['Devices'] = devs - TESTS['badblocks']['Devices'] = devs - TESTS['iobenchmark']['Devices'] = devs - return devs - -def show_disk_details(dev, only_attributes=False): - """Display disk details.""" - dev_name = dev['lsblk']['name'] - if not only_attributes: - # Device description - print_info('Device: {}{}'.format( - '' if '/dev/' in dev['lsblk']['name'] else '/dev/', - dev['lsblk']['name'])) - print_standard(' {:>4} ({}) {} {}'.format( - str(dev['lsblk'].get('size', '???b')).strip(), - str(dev['lsblk'].get('tran', '???')).strip().upper().replace( - 'NVME', 'NVMe'), - str(dev['lsblk'].get('model', 'Unknown Model')).strip(), - str(dev['lsblk'].get('serial', 'Unknown Serial')).strip(), - )) - - # Warnings - if dev.get('NVMe Disk', False): - if dev['Quick Health OK']: - print_warning('WARNING: NVMe support is still experimental') - else: - print_error('ERROR: NVMe disk is reporting critical warnings') - elif not dev['SMART Support']: - print_error('ERROR: Unable to retrieve SMART data') - elif not dev['SMART Pass']: - print_error('ERROR: SMART overall-health assessment result: FAILED') - - # Attributes - if dev.get('NVMe Disk', False): - if only_attributes: - print_info('SMART Attributes:', end='') - print_warning(' Updated: {}'.format( - time.strftime('%Y-%m-%d %H:%M %Z'))) - else: - print_info('Attributes:') - for attrib, threshold in sorted(ATTRIBUTES['NVMe'].items()): - if attrib in dev['nvme-cli']: - print_standard( - ' {:37}'.format(attrib.replace('_', ' ').title()), - end='', flush=True) - raw_num = dev['nvme-cli'][attrib] - raw_str = str(raw_num) - if (threshold.get('Error', False) and - raw_num >= threshold.get('Error', -1)): - print_error(raw_str, timestamp=False) - if not threshold.get('Ignore', False): - dev['Quick Health OK'] = False - TESTS['NVMe/SMART']['Status'][dev_name] = 'NS' - elif (threshold.get('Warning', False) and - raw_num >= threshold.get('Warning', -1)): - print_warning(raw_str, timestamp=False) - else: - print_success(raw_str, timestamp=False) - elif dev['smartctl'].get('ata_smart_attributes', None): - # SMART attributes - if only_attributes: - print_info('SMART Attributes:', end='') - print_warning(' Updated: {}'.format( - time.strftime('%Y-%m-%d %H:%M %Z'))) - else: - print_info('Attributes:') - s_table = dev['smartctl'].get('ata_smart_attributes', {}).get( - 'table', {}) - s_table = {a.get('id', 'Unknown'): a for a in s_table} - for attrib, threshold in sorted(ATTRIBUTES['SMART'].items()): - if attrib in s_table: - print_standard( - ' {:>3} {:32}'.format( - attrib, - s_table[attrib]['name']).replace('_', ' ').title(), - end='', flush=True) - raw_str = s_table[attrib]['raw']['string'] - raw_num = re.sub(r'^(\d+).*$', r'\1', raw_str) - try: - raw_num = float(raw_num) - except ValueError: - # Not sure about this one, print raw_str without color? - print_standard(raw_str, timestamp=False) - continue - if (threshold.get('Error', False) and - raw_num >= threshold.get('Error', -1)): - print_error(raw_str, timestamp=False) - if not threshold.get('Ignore', False): - dev['Quick Health OK'] = False - TESTS['NVMe/SMART']['Status'][dev_name] = 'NS' - elif (threshold.get('Warning', False) and - raw_num >= threshold.get('Warning', -1)): - print_warning(raw_str, timestamp=False) - else: - print_success(raw_str, timestamp=False) - -def show_results(): - """Show results for selected test(s).""" - clear_screen() - print_log('\n───────────────────────────') - print_standard('Hardware Diagnostic Results') - update_progress() - - # Set Window layout and show progress - run_program('tmux split-window -dhl 15 watch -c -n1 -t cat {}'.format( - TESTS['Progress Out']).split()) - - # Prime95 - if TESTS['Prime95']['Enabled']: - print_success('\nPrime95:') - for log, regex in [ - ['results.txt', r'(error|fail)'], - ['prime.log', r'completed.*0 errors, 0 warnings']]: - if log in TESTS['Prime95']: - print_info('Log: {}'.format(log)) - lines = [line.strip() for line - in TESTS['Prime95'][log].splitlines() - if re.search(regex, line, re.IGNORECASE)] - for line in lines[-4:]: - line = re.sub(r'^.*Worker #\d.*Torture Test (.*)', r'\1', - line, re.IGNORECASE) - if TESTS['Prime95'].get('NS', False): - print_error(' {}'.format(line)) - else: - print_standard(' {}'.format(line)) - print_info('Final temps') - print_log(' See Final Temps.log') - with open('{}/Final Temps.out'.format(global_vars['LogDir']), 'r') as f: - for line in f.readlines(): - if re.search(r'^\s*$', line.strip()): - # Stop after coretemps (which should be first) - break - print(' {}'.format(line.strip())) - print_standard(' ') - - # NVMe/SMART / badblocks / iobenchmark - if TESTS['NVMe/SMART']['Enabled'] or TESTS['badblocks']['Enabled'] or TESTS['iobenchmark']['Enabled']: - print_success('Disks:') - for name, dev in sorted(TESTS['NVMe/SMART']['Devices'].items()): - show_disk_details(dev) - bb_status = TESTS['badblocks']['Status'].get(name, None) - if (TESTS['badblocks']['Enabled'] - and bb_status not in ['Denied', 'OVERRIDE', 'Skipped']): - print_info('badblocks:') - result = TESTS['badblocks']['Results'].get(name, '') - for line in result.splitlines(): - if re.search(r'Pass completed', line, re.IGNORECASE): - line = re.sub( - r'Pass completed,?\s+', r'', - line.strip(), re.IGNORECASE) - if TESTS['badblocks']['Status'][name] == 'CS': - print_standard(' {}'.format(line)) - else: - print_error(' {}'.format(line)) - io_status = TESTS['iobenchmark']['Status'].get(name, None) - if (TESTS['iobenchmark']['Enabled'] - and io_status not in ['Denied', 'OVERRIDE', 'Skipped']): - print_info('Benchmark:') - result = TESTS['iobenchmark']['Results'].get(name, '') - for line in result.split('\n'): - print_standard(' {}'.format(line)) - print_standard(' ') - - # Done - pause('Press Enter to return to main menu... ') - run_program('tmux kill-pane -a'.split()) + """Get color based on status, returns str.""" + color = COLORS['CLEAR'] + if s in ['Denied', 'ERROR', 'NS', 'OVERRIDE']: + color = COLORS['RED'] + elif s in ['Aborted', 'Unknown', 'Working', 'Skipped']: + color = COLORS['YELLOW'] + elif s in ['CS']: + color = COLORS['GREEN'] + return color def update_io_progress(percent, rate, progress_file): - """Update I/O progress file.""" - bar_color = COLORS['CLEAR'] - rate_color = COLORS['CLEAR'] - step = get_graph_step(rate, scale=32) - if rate < IO_VARS['Threshold Graph Fail']: - bar_color = COLORS['RED'] - rate_color = COLORS['YELLOW'] - elif rate < IO_VARS['Threshold Graph Warn']: - bar_color = COLORS['YELLOW'] - rate_color = COLORS['YELLOW'] - elif rate > IO_VARS['Threshold Graph Great']: - bar_color = COLORS['GREEN'] - rate_color = COLORS['GREEN'] - line = ' {p:5.1f}% {b_color}{b:<4} {r_color}{r:6.1f} Mb/s{c}\n'.format( - p=percent, - b_color=bar_color, - b=IO_VARS['Graph Vertical'][step], - r_color=rate_color, - r=rate/(1024**2), - c=COLORS['CLEAR']) - with open(progress_file, 'a') as f: - f.write(line) - -def update_progress(): - """Update progress file.""" - if 'Progress Out' not in TESTS: - TESTS['Progress Out'] = '{}/progress.out'.format(global_vars['LogDir']) - output = [] - output.append('{BLUE}HW Diagnostics{CLEAR}'.format(**COLORS)) - output.append('───────────────') - if TESTS['Prime95']['Enabled']: - output.append(' ') - output.append('{BLUE}Prime95{s_color}{status:>8}{CLEAR}'.format( - s_color = get_status_color(TESTS['Prime95']['Status']), - status = TESTS['Prime95']['Status'], - **COLORS)) - if TESTS['NVMe/SMART']['Enabled']: - output.append(' ') - output.append('{BLUE}NVMe / SMART{CLEAR}'.format(**COLORS)) - if TESTS['NVMe/SMART']['Quick']: - output.append('{YELLOW} (Quick Check){CLEAR}'.format(**COLORS)) - for dev, status in sorted(TESTS['NVMe/SMART']['Status'].items()): - output.append('{dev}{s_color}{status:>{pad}}{CLEAR}'.format( - dev = dev, - pad = 15-len(dev), - s_color = get_status_color(status), - status = status, - **COLORS)) - if TESTS['badblocks']['Enabled']: - output.append(' ') - output.append('{BLUE}badblocks{CLEAR}'.format(**COLORS)) - for dev, status in sorted(TESTS['badblocks']['Status'].items()): - output.append('{dev}{s_color}{status:>{pad}}{CLEAR}'.format( - dev = dev, - pad = 15-len(dev), - s_color = get_status_color(status), - status = status, - **COLORS)) - if TESTS['iobenchmark']['Enabled']: - output.append(' ') - output.append('{BLUE}I/O Benchmark{CLEAR}'.format(**COLORS)) - for dev, status in sorted(TESTS['iobenchmark']['Status'].items()): - output.append('{dev}{s_color}{status:>{pad}}{CLEAR}'.format( - dev = dev, - pad = 15-len(dev), - s_color = get_status_color(status), - status = status, - **COLORS)) - - # Add line-endings - output = ['{}\n'.format(line) for line in output] - - with open(TESTS['Progress Out'], 'w') as f: - f.writelines(output) + """Update I/O progress file.""" + bar_color = COLORS['CLEAR'] + rate_color = COLORS['CLEAR'] + step = get_graph_step(rate, scale=32) + if rate < IO_VARS['Threshold Graph Fail']: + bar_color = COLORS['RED'] + rate_color = COLORS['YELLOW'] + elif rate < IO_VARS['Threshold Graph Warn']: + bar_color = COLORS['YELLOW'] + rate_color = COLORS['YELLOW'] + elif rate > IO_VARS['Threshold Graph Great']: + bar_color = COLORS['GREEN'] + rate_color = COLORS['GREEN'] + line = ' {p:5.1f}% {b_color}{b:<4} {r_color}{r:6.1f} Mb/s{c}\n'.format( + p=percent, + b_color=bar_color, + b=IO_VARS['Graph Vertical'][step], + r_color=rate_color, + r=rate/(1024**2), + c=COLORS['CLEAR']) + with open(progress_file, 'a') as f: + f.write(line) if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") -# vim: sts=4 sw=4 ts=4 +# vim: sts=2 sw=2 ts=2 From 3fdd8c629c8afd6c2ded1a52f821e63d548145ab Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 3 Dec 2018 19:47:44 -0700 Subject: [PATCH 025/265] Rewrote main menu * First options are presets followed by individual tests * Selecting presets will toggle the selections * Screensavers are hidden but still present --- .bin/Scripts/functions/common.py | 6 +- .bin/Scripts/functions/hw_diags.py | 168 +++++++++++++++++++++++++++++ .bin/Scripts/hw-diags-menu | 3 +- 3 files changed, 174 insertions(+), 3 deletions(-) diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index ae958645..d3f04ef6 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -318,7 +318,7 @@ def major_exception(): exit_script(1) def menu_select(title='~ Untitled Menu ~', - prompt='Please make a selection', secret_exit=False, + prompt='Please make a selection', secret_actions=[], secret_exit=False, main_entries=[], action_entries=[], disabled_label='DISABLED', spacer=''): """Display options in a menu and return selected option as a str.""" @@ -334,8 +334,10 @@ def menu_select(title='~ Untitled Menu ~', menu_splash = '{}\n{}\n'.format(title, spacer) width = len(str(len(main_entries))) valid_answers = [] - if (secret_exit): + if secret_exit: valid_answers.append('Q') + if secret_actions: + valid_answers.extend(secret_actions) # Add main entries for i in range(len(main_entries)): diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 830d948a..d32fb499 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -216,6 +216,174 @@ def get_status_color(s): color = COLORS['GREEN'] return color +def menu_diags(state, args): + """Main menu to select and run HW tests.""" + args = [a.lower() for a in args] + quick_label = '{YELLOW}(Quick){CLEAR}'.format(**COLORS) + title = '{GREEN}Hardware Diagnostics: Main Menu{CLEAR}'.format( + **COLORS) + # NOTE: Changing the order of main_options will break everything + main_options = [ + {'Base Name': 'Full Diagnostic', 'Enabled': True}, + {'Base Name': 'Drive Diagnostic', 'Enabled': False}, + {'Base Name': 'Drive Diagnostic (Quick)', 'Enabled': False}, + {'Base Name': 'Prime95 & Temps', 'Enabled': True, 'CRLF': True}, + {'Base Name': 'NVMe / SMART', 'Enabled': True}, + {'Base Name': 'badblocks', 'Enabled': True}, + {'Base Name': 'I/O Benchmark', 'Enabled': True}, + ] + actions = [ + {'Letter': 'A', 'Name': 'Audio Test'}, + {'Letter': 'K', 'Name': 'Keyboard Test'}, + {'Letter': 'N', 'Name': 'Network Test'}, + {'Letter': 'S', 'Name': 'Start', 'CRLF': True}, + {'Letter': 'Q', 'Name': 'Quit'}, + ] + secret_actions = ['M', 'T'] + + # CLI mode check + if '--cli' in args or 'DISPLAY' not in global_vars['Env']: + actions.append({'Letter': 'R', 'Name': 'Reboot'}) + actions.append({'Letter': 'P', 'Name': 'Power Off'}) + + while True: + # Set quick mode as necessary + if main_options[2]['Enabled'] and main_options[4]['Enabled']: + # Check if only Drive Diags (Quick) and NVMe/SMART are enabled + # If so, verify no other tests are enabled and set quick_mode + state.quick_mode = True + for opt in main_options[3:4] + main_options[5:]: + state.quick_mode &= not opt['Enabled'] + else: + state.quick_mode = False + + # Deselect presets + slice_end = 3 + if state.quick_mode: + slice_end = 2 + for opt in main_options[:slice_end]: + opt['Enabled'] = False + + # Verify preset selections + num_tests_selected = 0 + for opt in main_options[3:]: + if opt['Enabled']: + num_tests_selected += 1 + if num_tests_selected == 4: + # Full + main_options[0]['Enabled'] = True + elif num_tests_selected == 3 and not main_options[3]['Enabled']: + # Drive + main_options[1]['Enabled'] = True + + # Update checkboxes + for opt in main_options: + _nvme_smart = opt['Base Name'] == 'NVMe / SMART' + opt['Name'] = '{} {} {}'.format( + '[✓]' if opt['Enabled'] else '[ ]', + opt['Base Name'], + quick_label if state.quick_mode and _nvme_smart else '') + + # Show menu + selection = menu_select( + title=title, + main_entries=main_options, + action_entries=actions, + secret_actions=secret_actions, + spacer='───────────────────────────────') + + if selection.isnumeric(): + # Toggle selection + index = int(selection) - 1 + main_options[index]['Enabled'] = not main_options[index]['Enabled'] + + # Handle presets + if index == 0: + # Full + if main_options[index]['Enabled']: + for opt in main_options[1:3]: + opt['Enabled'] = False + for opt in main_options[3:]: + opt['Enabled'] = True + else: + for opt in main_options[3:]: + opt['Enabled'] = False + elif index == 1: + # Drive + if main_options[index]['Enabled']: + main_options[0]['Enabled'] = False + for opt in main_options[2:4]: + opt['Enabled'] = False + for opt in main_options[4:]: + opt['Enabled'] = True + else: + for opt in main_options[4:]: + opt['Enabled'] = False + elif index == 2: + # Drive (Quick) + if main_options[index]['Enabled']: + for opt in main_options[:2] + main_options[3:]: + opt['Enabled'] = False + main_options[4]['Enabled'] = True + else: + main_options[4]['Enabled'] = False + elif selection == 'A': + run_audio_test() + elif selection == 'K': + run_keyboard_test() + elif selection == 'N': + run_network_test() + elif selection == 'M': + secret_screensaver('matrix') + elif selection == 'T': + # Tubes is close to pipes + secret_screensaver('pipes') + elif selection == 'R': + run_program(['systemctl', 'reboot']) + elif selection == 'P': + run_program(['systemctl', 'poweroff']) + elif selection == 'Q': + break + elif selection == 'S': + # Run test(s) + clear_screen() + print('Fake test(s) placeholder for now...') + pause('Press Enter to return to main menu... ') + +def run_audio_test(): + """Run audio test.""" + # TODO: Enable real test and remove placeholder + clear_screen() + print('Fake audio placeholder for now...') + #run_program(['hw-diags-audio'], check=False, pipe=False) + pause('Press Enter to return to main menu... ') + +def run_keyboard_test(): + """Run keyboard test.""" + # TODO: Enable real test and remove placeholder + clear_screen() + print('Fake keyboard placeholder for now...') + #run_program(['xev', '-event', 'keyboard'], check=False, pipe=False) + pause('Press Enter to return to main menu... ') + +def run_network_test(): + """Run network test.""" + # TODO: Enable real test and remove placeholder + clear_screen() + print('Fake network placeholder for now...') + #run_program(['hw-diags-network'], check=False, pipe=False) + pause('Press Enter to return to main menu... ') + +def secret_screensaver(screensaver=None): + """Show screensaver.""" + if screensaver == 'matrix': + cmd = 'cmatrix -abs'.split() + elif screensaver == 'pipes': + cmd = 'pipes -t 0 -t 1 -t 2 -t 3 -p 5 -R -r 4000'.split() + else: + raise Exception('Invalid screensaver') + run_program(cmd, check=False, pipe=False) + def update_io_progress(percent, rate, progress_file): """Update I/O progress file.""" bar_color = COLORS['CLEAR'] diff --git a/.bin/Scripts/hw-diags-menu b/.bin/Scripts/hw-diags-menu index f7c1739c..c67cc5f4 100755 --- a/.bin/Scripts/hw-diags-menu +++ b/.bin/Scripts/hw-diags-menu @@ -17,7 +17,8 @@ if __name__ == '__main__': clear_screen() # Show menu - menu_diags(*sys.argv) + state = State() + menu_diags(state, sys.argv) # Done #print_standard('\nDone.') From 18fc97293e546d50e2606e055a8d1ec57be04913 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 3 Dec 2018 19:50:55 -0700 Subject: [PATCH 026/265] Renamed Drive to Disk to align options in menu --- .bin/Scripts/functions/hw_diags.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index d32fb499..b5d553de 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -225,8 +225,8 @@ def menu_diags(state, args): # NOTE: Changing the order of main_options will break everything main_options = [ {'Base Name': 'Full Diagnostic', 'Enabled': True}, - {'Base Name': 'Drive Diagnostic', 'Enabled': False}, - {'Base Name': 'Drive Diagnostic (Quick)', 'Enabled': False}, + {'Base Name': 'Disk Diagnostic', 'Enabled': False}, + {'Base Name': 'Disk Diagnostic (Quick)', 'Enabled': False}, {'Base Name': 'Prime95 & Temps', 'Enabled': True, 'CRLF': True}, {'Base Name': 'NVMe / SMART', 'Enabled': True}, {'Base Name': 'badblocks', 'Enabled': True}, @@ -249,7 +249,7 @@ def menu_diags(state, args): while True: # Set quick mode as necessary if main_options[2]['Enabled'] and main_options[4]['Enabled']: - # Check if only Drive Diags (Quick) and NVMe/SMART are enabled + # Check if only Disk Diags (Quick) and NVMe/SMART are enabled # If so, verify no other tests are enabled and set quick_mode state.quick_mode = True for opt in main_options[3:4] + main_options[5:]: @@ -273,7 +273,7 @@ def menu_diags(state, args): # Full main_options[0]['Enabled'] = True elif num_tests_selected == 3 and not main_options[3]['Enabled']: - # Drive + # Disk main_options[1]['Enabled'] = True # Update checkboxes @@ -309,7 +309,7 @@ def menu_diags(state, args): for opt in main_options[3:]: opt['Enabled'] = False elif index == 1: - # Drive + # Disk if main_options[index]['Enabled']: main_options[0]['Enabled'] = False for opt in main_options[2:4]: @@ -320,7 +320,7 @@ def menu_diags(state, args): for opt in main_options[4:]: opt['Enabled'] = False elif index == 2: - # Drive (Quick) + # Disk (Quick) if main_options[index]['Enabled']: for opt in main_options[:2] + main_options[3:]: opt['Enabled'] = False From 560929e2fa74ba35301758d17bfbfbfc526f1ad9 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 3 Dec 2018 19:54:06 -0700 Subject: [PATCH 027/265] Removed extra line break in menu_select --- .bin/Scripts/functions/common.py | 1 - 1 file changed, 1 deletion(-) diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index d3f04ef6..b5896966 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -369,7 +369,6 @@ def menu_select(title='~ Untitled Menu ~', letter = entry['Letter'].upper(), width = len(str(len(action_entries))), name = entry['Name']) - menu_splash += '\n' answer = '' From 2df4d48bb3af0f424fd1248a5e89af24035d588f Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 3 Dec 2018 20:15:56 -0700 Subject: [PATCH 028/265] Show selected tests on run --- .bin/Scripts/functions/hw_diags.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index b5d553de..3e08c9ed 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -118,10 +118,10 @@ class State(): self.progress_out = '{}/progress.out'.format(global_vars['LogDir']) self.started = False self.tests = { - 'Prime95': {'Enabled': False, 'Result': None, 'Status': None}, - 'NVMe / SMART': {'Enabled': False}, - 'badblocks': {'Enabled': False}, - 'I/O Benchmark': {'Enabled': False}, + 'Prime95 & Temps': {'Enabled': False, 'Result': None, 'Status': None}, + 'NVMe / SMART': {'Enabled': False}, + 'badblocks': {'Enabled': False}, + 'I/O Benchmark': {'Enabled': False}, } self.add_devs() @@ -347,7 +347,18 @@ def menu_diags(state, args): elif selection == 'S': # Run test(s) clear_screen() - print('Fake test(s) placeholder for now...') + print('Tests:') + for opt in main_options[3:]: + _nvme_smart = opt['Base Name'] == 'NVMe / SMART' + # Update state + state.tests[opt['Base Name']]['Enabled'] = opt['Enabled'] + print(' {:<15} {}{}{} {}'.format( + opt['Base Name'], + COLORS['GREEN'] if opt['Enabled'] else COLORS['RED'], + 'Enabled' if opt['Enabled'] else 'Disabled', + COLORS['CLEAR'], + quick_label if state.quick_mode and _nvme_smart else '')) + print('\nFake test(s) placeholder for now...') pause('Press Enter to return to main menu... ') def run_audio_test(): From 70a742e69c832484df6c5c1b6f70e5e6c1abde74 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 4 Dec 2018 16:10:58 -0700 Subject: [PATCH 029/265] Add device details from lsblk * Also ensure sane types for some attributes --- .bin/Scripts/functions/hw_diags.py | 52 ++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 3e08c9ed..5bb03c9b 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -68,10 +68,14 @@ class DevObj(): """Device object for tracking device specific data.""" def __init__(self, dev_path): self.failing = False + self.labels = [] + self.lsblk = {} + self.name = re.sub(r'^.*/(.*)', r'\1', dev_path) self.nvme_attributes = {} self.override = False self.path = dev_path self.smart_attributes = {} + self.smartctl = {} self.tests = { 'NVMe / SMART': {'Result': None, 'Status': None}, 'badblocks': {'Result': None, 'Status': None}, @@ -82,18 +86,54 @@ class DevObj(): 'Graph Data': []}, } self.get_details() + self.get_smart_details() def get_details(self): + """Get data from lsblk.""" + cmd = ['lsblk', '--json', '--output-all', '--paths', self.path] + try: + result = run_program(cmd, check=False) + json_data = json.loads(result.stdout.decode()) + self.lsblk = json_data['blockdevices'][0] + except Exception: + # Leave self.lsblk empty + pass + + # Set necessary details + self.lsblk['model'] = self.lsblk.get('model', 'Unknown Model') + self.lsblk['name'] = self.lsblk.get('name', self.path) + self.lsblk['rota'] = self.lsblk.get('rota', True) + self.lsblk['serial'] = self.lsblk.get('serial', 'Unknown Serial') + self.lsblk['size'] = self.lsblk.get('size', '???b') + self.lsblk['tran'] = self.lsblk.get('tran', '???') + + # Ensure certain attributes are strings + for attr in ['model', 'name', 'rota', 'serial', 'size', 'tran']: + if not isinstance(self.lsblk[attr], str): + self.lsblk[attr] = str(self.lsblk[attr]) + self.lsblk['tran'] = self.lsblk['tran'].upper().replace('NVME', 'NVMe') + + # Build list of labels + for dev in [self.lsblk, *self.lsblk.get('children', [])]: + self.labels.append(dev.get('label', '')) + self.labels.append(dev.get('partlabel', '')) + self.labels = [str(label) for label in self.labels if label] + + def get_smart_details(self): """Get data from smartctl.""" cmd = ['sudo', 'smartctl', '--all', '--json', self.path] - result = run_program(cmd, check=False) - self.data = json.loads(result.stdout.decode()) + try: + result = run_program(cmd, check=False) + self.smartctl = json.loads(result.stdout.decode()) + except Exception: + # Leave self.smartctl empty + pass # Check for attributes - if KEY_NVME in self.data: - self.nvme_attributes.update(self.data[KEY_NVME]) - elif KEY_SMART in self.data: - for a in self.data[KEY_SMART].get('table', {}): + if KEY_NVME in self.smartctl: + self.nvme_attributes.update(self.smartctl[KEY_NVME]) + elif KEY_SMART in self.smartctl: + for a in self.smartctl[KEY_SMART].get('table', {}): _id = str(a.get('id', 'UNKNOWN')) _name = str(a.get('name', 'UNKNOWN')) _raw = a.get('raw', {}).get('value', -1) From 6014a8fb70275d7be2b8b6a7f6c548b7ae718161 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 4 Dec 2018 16:18:45 -0700 Subject: [PATCH 030/265] Don't add WK or loopback devices --- .bin/Scripts/functions/hw_diags.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 5bb03c9b..8f543aa5 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -171,7 +171,22 @@ class State(): result = run_program(cmd, check=False) json_data = json.loads(result.stdout.decode()) for dev in json_data['blockdevices']: - self.devs.append(DevObj(dev['name'])) + skip_dev = False + dev_obj = DevObj(dev['name']) + + # Skip loopback devices + if dev_obj.lsblk['tran'] == 'NONE': + skip_dev = True + + # Skip WK devices + wk_label_regex = r'{}_(LINUX|UFD)'.format(KIT_NAME_SHORT) + for label in dev_obj.labels: + if re.search(wk_label_regex, label, re.IGNORECASE): + skip_dev = True + + # Add device + if not skip_dev: + self.devs.append(DevObj(dev['name'])) # Functions def generate_horizontal_graph(rates, oneline=False): From 5701b53026aa758c879db61454fcff9326a67e73 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 4 Dec 2018 16:55:17 -0700 Subject: [PATCH 031/265] Added --quick argument to skip menu --- .bin/Scripts/functions/hw_diags.py | 147 +++++++++++++++++------------ 1 file changed, 86 insertions(+), 61 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 8f543aa5..3de0806f 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -61,6 +61,7 @@ IO_VARS = { } KEY_NVME = 'nvme_smart_health_information_log' KEY_SMART = 'ata_smart_attributes' +QUICK_LABEL = '{YELLOW}(Quick){CLEAR}'.format(**COLORS) SIDE_PATH_WIDTH = 21 # Classes @@ -156,12 +157,14 @@ class State(): self.devs = [] self.finished = False self.progress_out = '{}/progress.out'.format(global_vars['LogDir']) + self.quick_mode = False self.started = False self.tests = { - 'Prime95 & Temps': {'Enabled': False, 'Result': None, 'Status': None}, - 'NVMe / SMART': {'Enabled': False}, - 'badblocks': {'Enabled': False}, - 'I/O Benchmark': {'Enabled': False}, + 'Prime95 & Temps': {'Enabled': False, 'Order': 1, + 'Result': None, 'Status': None}, + 'NVMe / SMART': {'Enabled': False, 'Order': 2}, + 'badblocks': {'Enabled': False, 'Order': 3}, + 'I/O Benchmark': {'Enabled': False, 'Order': 4}, } self.add_devs() @@ -274,18 +277,17 @@ def get_status_color(s): def menu_diags(state, args): """Main menu to select and run HW tests.""" args = [a.lower() for a in args] - quick_label = '{YELLOW}(Quick){CLEAR}'.format(**COLORS) title = '{GREEN}Hardware Diagnostics: Main Menu{CLEAR}'.format( **COLORS) # NOTE: Changing the order of main_options will break everything main_options = [ - {'Base Name': 'Full Diagnostic', 'Enabled': True}, + {'Base Name': 'Full Diagnostic', 'Enabled': False}, {'Base Name': 'Disk Diagnostic', 'Enabled': False}, {'Base Name': 'Disk Diagnostic (Quick)', 'Enabled': False}, - {'Base Name': 'Prime95 & Temps', 'Enabled': True, 'CRLF': True}, - {'Base Name': 'NVMe / SMART', 'Enabled': True}, - {'Base Name': 'badblocks', 'Enabled': True}, - {'Base Name': 'I/O Benchmark', 'Enabled': True}, + {'Base Name': 'Prime95 & Temps', 'Enabled': False, 'CRLF': True}, + {'Base Name': 'NVMe / SMART', 'Enabled': False}, + {'Base Name': 'badblocks', 'Enabled': False}, + {'Base Name': 'I/O Benchmark', 'Enabled': False}, ] actions = [ {'Letter': 'A', 'Name': 'Audio Test'}, @@ -295,12 +297,22 @@ def menu_diags(state, args): {'Letter': 'Q', 'Name': 'Quit'}, ] secret_actions = ['M', 'T'] + + # Set initial selections + update_main_options(state, '1', main_options) # CLI mode check if '--cli' in args or 'DISPLAY' not in global_vars['Env']: actions.append({'Letter': 'R', 'Name': 'Reboot'}) actions.append({'Letter': 'P', 'Name': 'Power Off'}) + # Skip menu if running quick check + if '--quick' in args: + update_main_options(state, '3', main_options) + state.quick_mode = True + run_hw_tests(state) + return True + while True: # Set quick mode as necessary if main_options[2]['Enabled'] and main_options[4]['Enabled']: @@ -337,7 +349,7 @@ def menu_diags(state, args): opt['Name'] = '{} {} {}'.format( '[✓]' if opt['Enabled'] else '[ ]', opt['Base Name'], - quick_label if state.quick_mode and _nvme_smart else '') + QUICK_LABEL if state.quick_mode and _nvme_smart else '') # Show menu selection = menu_select( @@ -348,40 +360,7 @@ def menu_diags(state, args): spacer='───────────────────────────────') if selection.isnumeric(): - # Toggle selection - index = int(selection) - 1 - main_options[index]['Enabled'] = not main_options[index]['Enabled'] - - # Handle presets - if index == 0: - # Full - if main_options[index]['Enabled']: - for opt in main_options[1:3]: - opt['Enabled'] = False - for opt in main_options[3:]: - opt['Enabled'] = True - else: - for opt in main_options[3:]: - opt['Enabled'] = False - elif index == 1: - # Disk - if main_options[index]['Enabled']: - main_options[0]['Enabled'] = False - for opt in main_options[2:4]: - opt['Enabled'] = False - for opt in main_options[4:]: - opt['Enabled'] = True - else: - for opt in main_options[4:]: - opt['Enabled'] = False - elif index == 2: - # Disk (Quick) - if main_options[index]['Enabled']: - for opt in main_options[:2] + main_options[3:]: - opt['Enabled'] = False - main_options[4]['Enabled'] = True - else: - main_options[4]['Enabled'] = False + update_main_options(state, selection, main_options) elif selection == 'A': run_audio_test() elif selection == 'K': @@ -391,7 +370,7 @@ def menu_diags(state, args): elif selection == 'M': secret_screensaver('matrix') elif selection == 'T': - # Tubes is close to pipes + # Tubes is close to pipes right? secret_screensaver('pipes') elif selection == 'R': run_program(['systemctl', 'reboot']) @@ -400,21 +379,7 @@ def menu_diags(state, args): elif selection == 'Q': break elif selection == 'S': - # Run test(s) - clear_screen() - print('Tests:') - for opt in main_options[3:]: - _nvme_smart = opt['Base Name'] == 'NVMe / SMART' - # Update state - state.tests[opt['Base Name']]['Enabled'] = opt['Enabled'] - print(' {:<15} {}{}{} {}'.format( - opt['Base Name'], - COLORS['GREEN'] if opt['Enabled'] else COLORS['RED'], - 'Enabled' if opt['Enabled'] else 'Disabled', - COLORS['CLEAR'], - quick_label if state.quick_mode and _nvme_smart else '')) - print('\nFake test(s) placeholder for now...') - pause('Press Enter to return to main menu... ') + run_hw_tests(state) def run_audio_test(): """Run audio test.""" @@ -424,6 +389,23 @@ def run_audio_test(): #run_program(['hw-diags-audio'], check=False, pipe=False) pause('Press Enter to return to main menu... ') +def run_hw_tests(state): + """Run enabled hardware tests.""" + # Run test(s) + clear_screen() + print('Tests:') + for k, v in sorted( + state.tests.items(), + key=lambda kv: kv[1]['Order']): + print_standard(' {:<15} {}{}{} {}'.format( + k, + COLORS['GREEN'] if v['Enabled'] else COLORS['RED'], + 'Enabled' if v['Enabled'] else 'Disabled', + COLORS['CLEAR'], + QUICK_LABEL if state.quick_mode and 'NVMe' in k else '')) + print('\nFake test(s) placeholder for now...') + pause('Press Enter to return to main menu... ') + def run_keyboard_test(): """Run keyboard test.""" # TODO: Enable real test and remove placeholder @@ -450,6 +432,49 @@ def secret_screensaver(screensaver=None): raise Exception('Invalid screensaver') run_program(cmd, check=False, pipe=False) +def update_main_options(state, selection, main_options): + """Update menu and state based on selection.""" + index = int(selection) - 1 + main_options[index]['Enabled'] = not main_options[index]['Enabled'] + + # Handle presets + if index == 0: + # Full + if main_options[index]['Enabled']: + for opt in main_options[1:3]: + opt['Enabled'] = False + for opt in main_options[3:]: + opt['Enabled'] = True + else: + for opt in main_options[3:]: + opt['Enabled'] = False + elif index == 1: + # Disk + if main_options[index]['Enabled']: + main_options[0]['Enabled'] = False + for opt in main_options[2:4]: + opt['Enabled'] = False + for opt in main_options[4:]: + opt['Enabled'] = True + else: + for opt in main_options[4:]: + opt['Enabled'] = False + elif index == 2: + # Disk (Quick) + if main_options[index]['Enabled']: + for opt in main_options[:2] + main_options[3:]: + opt['Enabled'] = False + main_options[4]['Enabled'] = True + else: + main_options[4]['Enabled'] = False + + # Update state + for opt in main_options[3:]: + state.tests[opt['Base Name']]['Enabled'] = opt['Enabled'] + + # Done + return main_options + def update_io_progress(percent, rate, progress_file): """Update I/O progress file.""" bar_color = COLORS['CLEAR'] From 62c9d82fd2cba7166c7c572e8de9f64387c2a417 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 4 Dec 2018 17:05:53 -0700 Subject: [PATCH 032/265] Adjusted placeholders --- .bin/Scripts/functions/hw_diags.py | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 3de0806f..4593392f 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -373,9 +373,15 @@ def menu_diags(state, args): # Tubes is close to pipes right? secret_screensaver('pipes') elif selection == 'R': - run_program(['systemctl', 'reboot']) + print('(FAKE) reboot...') + sleep(1) + # TODO uncomment below + #run_program(['systemctl', 'reboot']) elif selection == 'P': - run_program(['systemctl', 'poweroff']) + print('(FAKE) poweroff...') + sleep(1) + # TODO uncomment below + #run_program(['systemctl', 'poweroff']) elif selection == 'Q': break elif selection == 'S': @@ -383,10 +389,8 @@ def menu_diags(state, args): def run_audio_test(): """Run audio test.""" - # TODO: Enable real test and remove placeholder clear_screen() - print('Fake audio placeholder for now...') - #run_program(['hw-diags-audio'], check=False, pipe=False) + run_program(['hw-diags-audio'], check=False, pipe=False) pause('Press Enter to return to main menu... ') def run_hw_tests(state): @@ -403,23 +407,17 @@ def run_hw_tests(state): 'Enabled' if v['Enabled'] else 'Disabled', COLORS['CLEAR'], QUICK_LABEL if state.quick_mode and 'NVMe' in k else '')) - print('\nFake test(s) placeholder for now...') - pause('Press Enter to return to main menu... ') + pause('\nPress Enter to return to main menu... ') def run_keyboard_test(): """Run keyboard test.""" - # TODO: Enable real test and remove placeholder clear_screen() - print('Fake keyboard placeholder for now...') - #run_program(['xev', '-event', 'keyboard'], check=False, pipe=False) - pause('Press Enter to return to main menu... ') + run_program(['xev', '-event', 'keyboard'], check=False, pipe=False) def run_network_test(): """Run network test.""" - # TODO: Enable real test and remove placeholder clear_screen() - print('Fake network placeholder for now...') - #run_program(['hw-diags-network'], check=False, pipe=False) + run_program(['hw-diags-network'], check=False, pipe=False) pause('Press Enter to return to main menu... ') def secret_screensaver(screensaver=None): From 1489ad4237e3bc20d22fc0f89e7d0bdc0c378790 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 4 Dec 2018 18:43:50 -0700 Subject: [PATCH 033/265] Added safety check for devices --- .bin/Scripts/functions/hw_diags.py | 61 ++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 4593392f..67195d79 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -176,22 +176,53 @@ class State(): for dev in json_data['blockdevices']: skip_dev = False dev_obj = DevObj(dev['name']) - + # Skip loopback devices if dev_obj.lsblk['tran'] == 'NONE': skip_dev = True - + # Skip WK devices wk_label_regex = r'{}_(LINUX|UFD)'.format(KIT_NAME_SHORT) for label in dev_obj.labels: if re.search(wk_label_regex, label, re.IGNORECASE): skip_dev = True - + # Add device if not skip_dev: self.devs.append(DevObj(dev['name'])) # Functions +def check_dev_attributes(dev): + """Check if device should be tested and allow overrides.""" + needs_override = False + print_standard(' {size:>6} ({tran}) {model} {serial}'.format( + **dev.lsblk)) + + # General checks + if not dev.nvme_attributes and not dev.smart_attributes: + needs_override = True + print_warning( + ' WARNING: No NVMe or SMART attributes available for: {}'.format( + dev.path)) + + # NVMe checks + # TODO check all tracked attributes and set dev.failing if needed + + # SMART checks + # TODO check all tracked attributes and set dev.failing if needed + + # Ask for override if necessary + if needs_override: + if ask(' Run tests on this device anyway?'): + # TODO Set override for this dev + pass + else: + for v in dev.tests.values(): + v['Enabled'] = False + v['Result'] = 'Skipped' + v['Status'] = 'Skipped' + print_standard('') + def generate_horizontal_graph(rates, oneline=False): """Generate two-line horizontal graph from rates, returns str.""" line_1 = '' @@ -297,7 +328,7 @@ def menu_diags(state, args): {'Letter': 'Q', 'Name': 'Quit'}, ] secret_actions = ['M', 'T'] - + # Set initial selections update_main_options(state, '1', main_options) @@ -397,7 +428,7 @@ def run_hw_tests(state): """Run enabled hardware tests.""" # Run test(s) clear_screen() - print('Tests:') + print_info('Selected Tests:') for k, v in sorted( state.tests.items(), key=lambda kv: kv[1]['Order']): @@ -407,7 +438,21 @@ def run_hw_tests(state): 'Enabled' if v['Enabled'] else 'Disabled', COLORS['CLEAR'], QUICK_LABEL if state.quick_mode and 'NVMe' in k else '')) - pause('\nPress Enter to return to main menu... ') + print_standard('') + + # Check devices if necessary + if (state.tests['badblocks']['Enabled'] + or state.tests['I/O Benchmark']['Enabled']): + print_info('Selected Disks:') + for dev in state.devs: + check_dev_attributes(dev) + print_standard('') + + # Run tests + # TODO + + # Done + pause('Press Enter to return to main menu... ') def run_keyboard_test(): """Run keyboard test.""" @@ -465,11 +510,11 @@ def update_main_options(state, selection, main_options): main_options[4]['Enabled'] = True else: main_options[4]['Enabled'] = False - + # Update state for opt in main_options[3:]: state.tests[opt['Base Name']]['Enabled'] = opt['Enabled'] - + # Done return main_options From 597a23608951f38dfc3b987eed3ebff053081c98 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 4 Dec 2018 18:44:52 -0700 Subject: [PATCH 034/265] Don't clear screen twice at startup * Combined init_global_vars and add_devs output --- .bin/Scripts/functions/hw_diags.py | 5 ++++- .bin/Scripts/hw-diags-menu | 3 --- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 67195d79..6c43fe28 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -166,7 +166,10 @@ class State(): 'badblocks': {'Enabled': False, 'Order': 3}, 'I/O Benchmark': {'Enabled': False, 'Order': 4}, } - self.add_devs() + try_and_print( + message='Scanning devices...', + function=self.add_devs, + cs='Done') def add_devs(self): """Add all block devices listed by lsblk.""" diff --git a/.bin/Scripts/hw-diags-menu b/.bin/Scripts/hw-diags-menu index c67cc5f4..e60f8fc4 100755 --- a/.bin/Scripts/hw-diags-menu +++ b/.bin/Scripts/hw-diags-menu @@ -13,9 +13,6 @@ init_global_vars() if __name__ == '__main__': try: - # Prep - clear_screen() - # Show menu state = State() menu_diags(state, sys.argv) From 8fb1620c940ac2d337cb7cfb36998b3d1fac7c18 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 4 Dec 2018 19:23:35 -0700 Subject: [PATCH 035/265] Added placeholder functions for HW tests --- .bin/Scripts/functions/hw_diags.py | 45 ++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 6c43fe28..15bea407 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -302,7 +302,7 @@ def get_status_color(s): color = COLORS['CLEAR'] if s in ['Denied', 'ERROR', 'NS', 'OVERRIDE']: color = COLORS['RED'] - elif s in ['Aborted', 'Unknown', 'Working', 'Skipped']: + elif s in ['Aborted', 'N/A', 'Unknown', 'Working', 'Skipped']: color = COLORS['YELLOW'] elif s in ['CS']: color = COLORS['GREEN'] @@ -427,6 +427,10 @@ def run_audio_test(): run_program(['hw-diags-audio'], check=False, pipe=False) pause('Press Enter to return to main menu... ') +def run_badblocks_test(state): + """TODO""" + print_standard('TODO: run_badblocks_test()') + def run_hw_tests(state): """Run enabled hardware tests.""" # Run test(s) @@ -452,22 +456,55 @@ def run_hw_tests(state): print_standard('') # Run tests - # TODO + if state.tests['Prime95 & Temps']['Enabled']: + run_mprime_test(state) + if state.tests['NVMe / SMART']['Enabled']: + run_nvme_smart(state) + if state.tests['badblocks']['Enabled']: + run_badblocks_test(state) + if state.tests['I/O Benchmark']['Enabled']: + run_io_benchmark(state) # Done pause('Press Enter to return to main menu... ') +def run_io_benchmark(state): + """TODO""" + print_standard('TODO: run_io_benchmark()') + def run_keyboard_test(): """Run keyboard test.""" clear_screen() run_program(['xev', '-event', 'keyboard'], check=False, pipe=False) +def run_mprime_test(state): + """TODO""" + print_standard('TODO: run_mprime_test()') + def run_network_test(): """Run network test.""" clear_screen() run_program(['hw-diags-network'], check=False, pipe=False) pause('Press Enter to return to main menu... ') +def run_nvme_smart(state): + """TODO""" + for dev in state.devs: + if dev.nvme_attributes: + run_nvme_tests(dev) + elif dev.smart_attributes: + run_smart_tests(dev) + else: + print_standard('TODO: run_nvme_smart({})'.format( + dev.path)) + print_warning( + " WARNING: Device {} doesn't support NVMe or SMART test".format( + dev.path)) + +def run_nvme_tests(dev): + """TODO""" + print_standard('TODO: run_nvme_test({})'.format(dev.path)) + def secret_screensaver(screensaver=None): """Show screensaver.""" if screensaver == 'matrix': @@ -478,6 +515,10 @@ def secret_screensaver(screensaver=None): raise Exception('Invalid screensaver') run_program(cmd, check=False, pipe=False) +def run_smart_tests(dev): + """TODO""" + print_standard('TODO: run_smart_tests({})'.format(dev.path)) + def update_main_options(state, selection, main_options): """Update menu and state based on selection.""" index = int(selection) - 1 From 4bb1402ac5a992c2e5f3f030a7a9131f743d00fb Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 4 Dec 2018 20:50:47 -0700 Subject: [PATCH 036/265] Added tmux functions * Going to try and replace the send-keys sections next --- .bin/Scripts/functions/hw_diags.py | 80 +++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 15bea407..a446036d 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -62,7 +62,7 @@ IO_VARS = { KEY_NVME = 'nvme_smart_health_information_log' KEY_SMART = 'ata_smart_attributes' QUICK_LABEL = '{YELLOW}(Quick){CLEAR}'.format(**COLORS) -SIDE_PATH_WIDTH = 21 +SIDE_PANE_WIDTH = 21 # Classes class DevObj(): @@ -156,6 +156,7 @@ class State(): def __init__(self): self.devs = [] self.finished = False + self.panes = {} self.progress_out = '{}/progress.out'.format(global_vars['LogDir']) self.quick_mode = False self.started = False @@ -195,6 +196,31 @@ class State(): self.devs.append(DevObj(dev['name'])) # Functions +def build_outer_panes(state): + """Build top and side panes.""" + clear_screen() + + # Create panes + state.panes['Top'] = tmux_split_window( + behind=True, lines=2, vertical=True) + state.panes['Started'] = tmux_split_window( + lines=SIDE_PANE_WIDTH, target_pane=state.panes['Top']) + state.panes['Progress'] = tmux_split_window(lines=SIDE_PANE_WIDTH) + + # Set text + tmux_update_pane_text( + state.panes['Top'], + text='{GREEN}Hardware Diagnostics{CLEAR}'.format( + **COLORS)) + tmux_update_pane_text( + state.panes['Started'], + text='{BLUE}Started{CLEAR}\n{text}'.format( + text=time.strftime("%Y-%m-%d %H:%M %Z"), + **COLORS)) + tmux_update_pane_text( + state.panes['Progress'], + text='{BLUE}Progress{CLEAR}\nGoes here'.format(**COLORS)) + def check_dev_attributes(dev): """Check if device should be tested and allow overrides.""" needs_override = False @@ -433,8 +459,10 @@ def run_badblocks_test(state): def run_hw_tests(state): """Run enabled hardware tests.""" + # Build Panes + build_outer_panes(state) + # Run test(s) - clear_screen() print_info('Selected Tests:') for k, v in sorted( state.tests.items(), @@ -468,6 +496,9 @@ def run_hw_tests(state): # Done pause('Press Enter to return to main menu... ') + # Cleanup + tmux_kill_pane(*state.panes.values()) + def run_io_benchmark(state): """TODO""" print_standard('TODO: run_io_benchmark()') @@ -519,6 +550,51 @@ def run_smart_tests(dev): """TODO""" print_standard('TODO: run_smart_tests({})'.format(dev.path)) +def tmux_kill_pane(*panes): + """Kill tmux pane by id.""" + cmd = ['tmux', 'kill-pane', '-t'] + for pane_id in panes: + print(pane_id) + run_program(cmd+[pane_id], check=False) + +def tmux_split_window( + lines=None, percent=None, + behind=False, vertical=False, + follow=False, target_pane=None): + """Run tmux split-window command and return pane_id as str.""" + # Bail early + if not lines and not percent: + raise Exception('Neither lines nor percent specified.') + + # Build cmd + cmd = ['tmux', 'split-window', '-PF', '#D'] + if behind: + cmd.append('-b') + if vertical: + cmd.append('-v') + else: + cmd.append('-h') + if not follow: + cmd.append('-d') + if lines is not None: + cmd.extend(['-l', str(lines)]) + elif percent is not None: + cmd.extend(['-p', str(percent)]) + if target_pane: + cmd.extend(['-t', str(target_pane)]) + + # Run and return pane_id + result = run_program(cmd) + return result.stdout.decode().strip() + +def tmux_update_pane_text(pane_id, text): + """Print text to tmux pane.""" + text = text.replace('\033', r'\e') + cmd = ['tmux', 'send-keys', '-t', pane_id] + run_program(cmd+['Enter']) + run_program(cmd+['clear; echo-and-hold "{}"'.format(text)]) + run_program(cmd+['Enter']) + def update_main_options(state, selection, main_options): """Update menu and state based on selection.""" index = int(selection) - 1 From 43b9645c69fee66d5154013abe5d67b58bf54a77 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 4 Dec 2018 23:39:15 -0700 Subject: [PATCH 037/265] Update tmux panes via respawn-pane Instead of send-keys * Avoids flooding zsh history * Less flickering --- .bin/Scripts/functions/hw_diags.py | 121 +++++++++++++++++++++-------- 1 file changed, 87 insertions(+), 34 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index a446036d..743db0a2 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -63,6 +63,7 @@ KEY_NVME = 'nvme_smart_health_information_log' KEY_SMART = 'ata_smart_attributes' QUICK_LABEL = '{YELLOW}(Quick){CLEAR}'.format(**COLORS) SIDE_PANE_WIDTH = 21 +TOP_PANE_TEXT = '{GREEN}Hardware Diagnostics{CLEAR}'.format(**COLORS) # Classes class DevObj(): @@ -200,26 +201,24 @@ def build_outer_panes(state): """Build top and side panes.""" clear_screen() - # Create panes + # Top state.panes['Top'] = tmux_split_window( - behind=True, lines=2, vertical=True) - state.panes['Started'] = tmux_split_window( - lines=SIDE_PANE_WIDTH, target_pane=state.panes['Top']) - state.panes['Progress'] = tmux_split_window(lines=SIDE_PANE_WIDTH) + behind=True, lines=2, vertical=True, + text='{GREEN}Hardware Diagnostics{CLEAR}'.format(**COLORS)) - # Set text - tmux_update_pane_text( - state.panes['Top'], - text='{GREEN}Hardware Diagnostics{CLEAR}'.format( - **COLORS)) - tmux_update_pane_text( - state.panes['Started'], + # Started + state.panes['Started'] = tmux_split_window( + lines=SIDE_PANE_WIDTH, target_pane=state.panes['Top'], text='{BLUE}Started{CLEAR}\n{text}'.format( text=time.strftime("%Y-%m-%d %H:%M %Z"), **COLORS)) - tmux_update_pane_text( - state.panes['Progress'], - text='{BLUE}Progress{CLEAR}\nGoes here'.format(**COLORS)) + + # Progress + state.panes['Progress'] = tmux_split_window( + lines=SIDE_PANE_WIDTH, + text='{BLUE}Progress{CLEAR}\nGoes here\n\n{Meh}'.format( + Meh=time.strftime('%H:%M:%S %Z'), + **COLORS)) def check_dev_attributes(dev): """Check if device should be tested and allow overrides.""" @@ -337,8 +336,7 @@ def get_status_color(s): def menu_diags(state, args): """Main menu to select and run HW tests.""" args = [a.lower() for a in args] - title = '{GREEN}Hardware Diagnostics: Main Menu{CLEAR}'.format( - **COLORS) + title = '{}\nMain Menu'.format(TOP_PANE_TEXT) # NOTE: Changing the order of main_options will break everything main_options = [ {'Base Name': 'Full Diagnostic', 'Enabled': False}, @@ -455,7 +453,16 @@ def run_audio_test(): def run_badblocks_test(state): """TODO""" + tmux_update_pane( + state.panes['Top'], text='{}\n{}'.format( + TOP_PANE_TEXT, 'badblocks')) + tmux_update_pane( + state.panes['Progress'], + text='{BLUE}Progress{CLEAR}\nGoes here\n\n{Meh}'.format( + Meh=time.strftime('%H:%M:%S %Z'), + **COLORS)) print_standard('TODO: run_badblocks_test()') + sleep(3) def run_hw_tests(state): """Run enabled hardware tests.""" @@ -501,7 +508,16 @@ def run_hw_tests(state): def run_io_benchmark(state): """TODO""" + tmux_update_pane( + state.panes['Top'], text='{}\n{}'.format( + TOP_PANE_TEXT, 'I/O Benchmark')) + tmux_update_pane( + state.panes['Progress'], + text='{BLUE}Progress{CLEAR}\nGoes here\n\n{Meh}'.format( + Meh=time.strftime('%H:%M:%S %Z'), + **COLORS)) print_standard('TODO: run_io_benchmark()') + sleep(3) def run_keyboard_test(): """Run keyboard test.""" @@ -509,8 +525,21 @@ def run_keyboard_test(): run_program(['xev', '-event', 'keyboard'], check=False, pipe=False) def run_mprime_test(state): - """TODO""" - print_standard('TODO: run_mprime_test()') + """Test CPU with Prime95 and track temps.""" + # Prep + tmux_update_pane( + state.panes['Top'], text='{}\n{}'.format( + TOP_PANE_TEXT, 'Prime95 & Temps')) + tmux_update_pane( + state.panes['Progress'], + text='{BLUE}Progress{CLEAR}\nGoes here\n\n{Meh}'.format( + Meh=time.strftime('%H:%M:%S %Z'), + **COLORS)) + # Get idle temps + # Stress CPU + # Get max temp + # Get cooldown temp + sleep(3) def run_network_test(): """Run network test.""" @@ -521,21 +550,35 @@ def run_network_test(): def run_nvme_smart(state): """TODO""" for dev in state.devs: + tmux_update_pane( + state.panes['Top'], + text='{t}\nDisk Health: {size:>6} ({tran}) {model} {serial}'.format( + t=TOP_PANE_TEXT, **dev.lsblk)) + tmux_update_pane( + state.panes['Progress'], + text='{BLUE}Progress{CLEAR}\nGoes here\n\n{Meh}'.format( + Meh=time.strftime('%H:%M:%S %Z'), + **COLORS)) if dev.nvme_attributes: - run_nvme_tests(dev) + run_nvme_tests(state, dev) elif dev.smart_attributes: - run_smart_tests(dev) + run_smart_tests(state, dev) else: print_standard('TODO: run_nvme_smart({})'.format( dev.path)) print_warning( " WARNING: Device {} doesn't support NVMe or SMART test".format( dev.path)) + sleep(3) -def run_nvme_tests(dev): +def run_nvme_tests(state, dev): """TODO""" print_standard('TODO: run_nvme_test({})'.format(dev.path)) +def run_smart_tests(state, dev): + """TODO""" + print_standard('TODO: run_smart_tests({})'.format(dev.path)) + def secret_screensaver(screensaver=None): """Show screensaver.""" if screensaver == 'matrix': @@ -546,10 +589,6 @@ def secret_screensaver(screensaver=None): raise Exception('Invalid screensaver') run_program(cmd, check=False, pipe=False) -def run_smart_tests(dev): - """TODO""" - print_standard('TODO: run_smart_tests({})'.format(dev.path)) - def tmux_kill_pane(*panes): """Kill tmux pane by id.""" cmd = ['tmux', 'kill-pane', '-t'] @@ -560,11 +599,14 @@ def tmux_kill_pane(*panes): def tmux_split_window( lines=None, percent=None, behind=False, vertical=False, - follow=False, target_pane=None): + follow=False, target_pane=None, + command=None, text=None): """Run tmux split-window command and return pane_id as str.""" # Bail early if not lines and not percent: raise Exception('Neither lines nor percent specified.') + if not command and not text: + raise Exception('Neither command nor text specified.') # Build cmd cmd = ['tmux', 'split-window', '-PF', '#D'] @@ -583,17 +625,28 @@ def tmux_split_window( if target_pane: cmd.extend(['-t', str(target_pane)]) + if command: + cmd.extend(command) + elif text: + cmd.extend(['echo-and-hold', text]) + # Run and return pane_id result = run_program(cmd) return result.stdout.decode().strip() -def tmux_update_pane_text(pane_id, text): - """Print text to tmux pane.""" - text = text.replace('\033', r'\e') - cmd = ['tmux', 'send-keys', '-t', pane_id] - run_program(cmd+['Enter']) - run_program(cmd+['clear; echo-and-hold "{}"'.format(text)]) - run_program(cmd+['Enter']) +def tmux_update_pane(pane_id, command=None, text=None): + """Respawn with either a new command or new text.""" + # Bail early + if not command and not text: + raise Exception('Neither command nor text specified.') + + cmd = ['tmux', 'respawn-pane', '-k', '-t', pane_id] + if command: + cmd.extend(command) + elif text: + cmd.extend(['echo-and-hold', text]) + + run_program(cmd) def update_main_options(state, selection, main_options): """Update menu and state based on selection.""" From 2d69d93154f6fc2882b3cb6d85a6b8c55bed3a36 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 5 Dec 2018 03:41:27 -0700 Subject: [PATCH 038/265] Added watch option for tmux_split_window() --- .bin/Scripts/functions/hw_diags.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 743db0a2..440ec1c5 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -204,7 +204,7 @@ def build_outer_panes(state): # Top state.panes['Top'] = tmux_split_window( behind=True, lines=2, vertical=True, - text='{GREEN}Hardware Diagnostics{CLEAR}'.format(**COLORS)) + text=TOP_PANE_TEXT) # Started state.panes['Started'] = tmux_split_window( @@ -216,9 +216,7 @@ def build_outer_panes(state): # Progress state.panes['Progress'] = tmux_split_window( lines=SIDE_PANE_WIDTH, - text='{BLUE}Progress{CLEAR}\nGoes here\n\n{Meh}'.format( - Meh=time.strftime('%H:%M:%S %Z'), - **COLORS)) + watch=state.progress_out) def check_dev_attributes(dev): """Check if device should be tested and allow overrides.""" @@ -600,13 +598,13 @@ def tmux_split_window( lines=None, percent=None, behind=False, vertical=False, follow=False, target_pane=None, - command=None, text=None): + command=None, text=None, watch=None): """Run tmux split-window command and return pane_id as str.""" # Bail early if not lines and not percent: raise Exception('Neither lines nor percent specified.') - if not command and not text: - raise Exception('Neither command nor text specified.') + if not command and not text and not watch: + raise Exception('No command, text, or watch file specified.') # Build cmd cmd = ['tmux', 'split-window', '-PF', '#D'] @@ -628,7 +626,12 @@ def tmux_split_window( if command: cmd.extend(command) elif text: - cmd.extend(['echo-and-hold', text]) + cmd.extend(['echo-and-hold "{}"'.format(text)]) + elif watch: + cmd.extend([ + 'watch', '--color', '--no-title', + '--interval', '1', + 'cat', watch]) # Run and return pane_id result = run_program(cmd) @@ -644,7 +647,7 @@ def tmux_update_pane(pane_id, command=None, text=None): if command: cmd.extend(command) elif text: - cmd.extend(['echo-and-hold', text]) + cmd.extend(['echo-and-hold "{}"'.format(text)]) run_program(cmd) From d025b8dc9e91555b9cf123580a49ab8f09eeb3ea Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 5 Dec 2018 03:49:25 -0700 Subject: [PATCH 039/265] Adjusted how devices are added to the state obj * The change allows for devices to be (dis)connected while the script is running * Devices are scanned and added during run_hw_diags() * Fixes bug that prevented any devices from being added as well --- .bin/Scripts/functions/hw_diags.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 440ec1c5..9e720d92 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -78,6 +78,7 @@ class DevObj(): self.path = dev_path self.smart_attributes = {} self.smartctl = {} + self.state = state self.tests = { 'NVMe / SMART': {'Result': None, 'Status': None}, 'badblocks': {'Result': None, 'Status': None}, @@ -158,7 +159,8 @@ class State(): self.devs = [] self.finished = False self.panes = {} - self.progress_out = '{}/progress.out'.format(global_vars['LogDir']) + # TODO Switch to LogDir + self.progress_out = '{}/progress.out'.format(global_vars['TmpDir']) self.quick_mode = False self.started = False self.tests = { @@ -168,19 +170,20 @@ class State(): 'badblocks': {'Enabled': False, 'Order': 3}, 'I/O Benchmark': {'Enabled': False, 'Order': 4}, } - try_and_print( - message='Scanning devices...', - function=self.add_devs, - cs='Done') - def add_devs(self): - """Add all block devices listed by lsblk.""" + def init(self): + """Scan for block devices and reset all tests.""" + self.devs = [] + for k in ['Result', 'Started', 'Status']: + self.tests['Prime95 & Temps'][k] = False if k == 'Started' else '' + + # Add block devices cmd = ['lsblk', '--json', '--nodeps', '--paths'] result = run_program(cmd, check=False) json_data = json.loads(result.stdout.decode()) for dev in json_data['blockdevices']: skip_dev = False - dev_obj = DevObj(dev['name']) + dev_obj = DevObj(self, dev['name']) # Skip loopback devices if dev_obj.lsblk['tran'] == 'NONE': @@ -194,7 +197,7 @@ class State(): # Add device if not skip_dev: - self.devs.append(DevObj(dev['name'])) + self.devs.append(dev_obj) # Functions def build_outer_panes(state): @@ -464,6 +467,9 @@ def run_badblocks_test(state): def run_hw_tests(state): """Run enabled hardware tests.""" + print_standard('Scanning devices...') + state.init() + # Build Panes build_outer_panes(state) From 7c163a8110b8474a8d75dee1e091b7b109d43eea Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 5 Dec 2018 03:52:24 -0700 Subject: [PATCH 040/265] Added update progress sections --- .bin/Scripts/functions/hw_diags.py | 158 +++++++++++++++++++++++------ 1 file changed, 126 insertions(+), 32 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 9e720d92..ac128ea1 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -62,13 +62,13 @@ IO_VARS = { KEY_NVME = 'nvme_smart_health_information_log' KEY_SMART = 'ata_smart_attributes' QUICK_LABEL = '{YELLOW}(Quick){CLEAR}'.format(**COLORS) -SIDE_PANE_WIDTH = 21 +SIDE_PANE_WIDTH = 20 TOP_PANE_TEXT = '{GREEN}Hardware Diagnostics{CLEAR}'.format(**COLORS) # Classes class DevObj(): """Device object for tracking device specific data.""" - def __init__(self, dev_path): + def __init__(self, state, dev_path): self.failing = False self.labels = [] self.lsblk = {} @@ -80,13 +80,17 @@ class DevObj(): self.smartctl = {} self.state = state self.tests = { - 'NVMe / SMART': {'Result': None, 'Status': None}, - 'badblocks': {'Result': None, 'Status': None}, + 'NVMe / SMART': { + 'Result': '', 'Started': False, 'Status': '', 'Order': 1}, + 'badblocks': { + 'Result': '', 'Started': False, 'Status': '', 'Order': 2}, 'I/O Benchmark': { - 'Result': None, - 'Status': None, + 'Result': '', + 'Started': False, + 'Status': '', 'Read Rates': [], - 'Graph Data': []}, + 'Graph Data': [], + 'Order': 3}, } self.get_details() self.get_smart_details() @@ -153,6 +157,21 @@ class DevObj(): self.smart_attributes[_id] = { 'name': _name, 'raw': _raw, 'raw_str': _raw_str} + def update_progress(self): + """Update status strings.""" + for k, v in self.tests.items(): + if self.state.tests[k]['Enabled']: + _status = '' + if not v['Status']: + _status = 'Pending' + if v['Started']: + if v['Result']: + _status = v['Result'] + else: + _status = 'Working' + if _status: + v['Status'] = build_status_string(self.name, _status) + class State(): """Object to track device objects and overall state.""" def __init__(self): @@ -165,7 +184,7 @@ class State(): self.started = False self.tests = { 'Prime95 & Temps': {'Enabled': False, 'Order': 1, - 'Result': None, 'Status': None}, + 'Result': '', 'Started': False, 'Status': ''}, 'NVMe / SMART': {'Enabled': False, 'Order': 2}, 'badblocks': {'Enabled': False, 'Order': 3}, 'I/O Benchmark': {'Enabled': False, 'Order': 4}, @@ -199,6 +218,27 @@ class State(): if not skip_dev: self.devs.append(dev_obj) + def update_progress(self): + """Update status strings.""" + # Prime95 + p = self.tests['Prime95 & Temps'] + if p['Enabled']: + _status = '' + if not p['Status']: + _status = 'Pending' + if p['Started']: + if p['Result']: + _status = p['Result'] + else: + _status = 'Working' + if _status: + p['Status'] = build_status_string( + 'Prime95', _status, info_label=True) + + # Disks + for dev in self.devs: + dev.update_progress() + # Functions def build_outer_panes(state): """Build top and side panes.""" @@ -221,6 +261,24 @@ def build_outer_panes(state): lines=SIDE_PANE_WIDTH, watch=state.progress_out) +def build_status_string(label, status, info_label=False): + """Build status string with appropriate colors.""" + status_color = COLORS['CLEAR'] + if status in ['Denied', 'ERROR', 'NS', 'OVERRIDE']: + status_color = COLORS['RED'] + elif status in ['Aborted', 'Unknown', 'Working', 'Skipped']: + status_color = COLORS['YELLOW'] + elif status in ['CS']: + status_color = COLORS['GREEN'] + + return '{l_c}{l}{CLEAR}{s_c}{s:>{s_w}}{CLEAR}'.format( + l_c=COLORS['BLUE'] if info_label else '', + l=label, + s_c=status_color, + s=status, + s_w=SIDE_PANE_WIDTH-len(label), + **COLORS) + def check_dev_attributes(dev): """Check if device should be tested and allow overrides.""" needs_override = False @@ -247,8 +305,9 @@ def check_dev_attributes(dev): pass else: for v in dev.tests.values(): - v['Enabled'] = False + # Started is set to True to fix the status string v['Result'] = 'Skipped' + v['Started'] = True v['Status'] = 'Skipped' print_standard('') @@ -457,13 +516,13 @@ def run_badblocks_test(state): tmux_update_pane( state.panes['Top'], text='{}\n{}'.format( TOP_PANE_TEXT, 'badblocks')) - tmux_update_pane( - state.panes['Progress'], - text='{BLUE}Progress{CLEAR}\nGoes here\n\n{Meh}'.format( - Meh=time.strftime('%H:%M:%S %Z'), - **COLORS)) print_standard('TODO: run_badblocks_test()') - sleep(3) + for dev in state.devs: + dev.tests['badblocks']['Started'] = True + update_progress_pane(state) + sleep(3) + dev.tests['badblocks']['Result'] = 'OVERRIDE' + update_progress_pane(state) def run_hw_tests(state): """Run enabled hardware tests.""" @@ -471,6 +530,7 @@ def run_hw_tests(state): state.init() # Build Panes + update_progress_pane(state) build_outer_panes(state) # Run test(s) @@ -515,13 +575,13 @@ def run_io_benchmark(state): tmux_update_pane( state.panes['Top'], text='{}\n{}'.format( TOP_PANE_TEXT, 'I/O Benchmark')) - tmux_update_pane( - state.panes['Progress'], - text='{BLUE}Progress{CLEAR}\nGoes here\n\n{Meh}'.format( - Meh=time.strftime('%H:%M:%S %Z'), - **COLORS)) print_standard('TODO: run_io_benchmark()') - sleep(3) + for dev in state.devs: + dev.tests['I/O Benchmark']['Started'] = True + update_progress_pane(state) + sleep(3) + dev.tests['I/O Benchmark']['Result'] = 'Unknown' + update_progress_pane(state) def run_keyboard_test(): """Run keyboard test.""" @@ -534,16 +594,18 @@ def run_mprime_test(state): tmux_update_pane( state.panes['Top'], text='{}\n{}'.format( TOP_PANE_TEXT, 'Prime95 & Temps')) - tmux_update_pane( - state.panes['Progress'], - text='{BLUE}Progress{CLEAR}\nGoes here\n\n{Meh}'.format( - Meh=time.strftime('%H:%M:%S %Z'), - **COLORS)) + state.tests['Prime95 & Temps']['Started'] = True + update_progress_pane(state) + # Get idle temps # Stress CPU # Get max temp # Get cooldown temp + + # Done sleep(3) + state.tests['Prime95 & Temps']['Result'] = 'Unknown' + update_progress_pane(state) def run_network_test(): """Run network test.""" @@ -558,11 +620,8 @@ def run_nvme_smart(state): state.panes['Top'], text='{t}\nDisk Health: {size:>6} ({tran}) {model} {serial}'.format( t=TOP_PANE_TEXT, **dev.lsblk)) - tmux_update_pane( - state.panes['Progress'], - text='{BLUE}Progress{CLEAR}\nGoes here\n\n{Meh}'.format( - Meh=time.strftime('%H:%M:%S %Z'), - **COLORS)) + dev.tests['NVMe / SMART']['Started'] = True + update_progress_pane(state) if dev.nvme_attributes: run_nvme_tests(state, dev) elif dev.smart_attributes: @@ -573,15 +632,24 @@ def run_nvme_smart(state): print_warning( " WARNING: Device {} doesn't support NVMe or SMART test".format( dev.path)) - sleep(3) + dev.tests['NVMe / SMART']['Status'] = 'N/A' + dev.tests['NVMe / SMART']['Result'] = 'N/A' + update_progress_pane(state) + sleep(3) def run_nvme_tests(state, dev): """TODO""" print_standard('TODO: run_nvme_test({})'.format(dev.path)) + sleep(3) + dev.tests['NVMe / SMART']['Result'] = 'CS' + update_progress_pane(state) def run_smart_tests(state, dev): """TODO""" print_standard('TODO: run_smart_tests({})'.format(dev.path)) + sleep(3) + dev.tests['NVMe / SMART']['Result'] = 'CS' + update_progress_pane(state) def secret_screensaver(screensaver=None): """Show screensaver.""" @@ -724,6 +792,32 @@ def update_io_progress(percent, rate, progress_file): with open(progress_file, 'a') as f: f.write(line) +def update_progress_pane(state): + """Update progress file for side pane.""" + output = [] + state.update_progress() + + # Prime95 + output.append(state.tests['Prime95 & Temps']['Status']) + output.append(' ') + + # Disks + for k, v in sorted( + state.tests.items(), + key=lambda kv: kv[1]['Order']): + if 'Prime95' not in k and v['Enabled']: + output.append('{BLUE}{test_name}{CLEAR}'.format( + test_name=k, **COLORS)) + for dev in state.devs: + output.append(dev.tests[k]['Status']) + output.append(' ') + + # Add line-endings + output = ['{}\n'.format(line) for line in output] + + with open(state.progress_out, 'w') as f: + f.writelines(output) + if __name__ == '__main__': print("This file is not meant to be called directly.") From 372f80bf38d56dcb58a4ac76cf7b04555f3f66f5 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 5 Dec 2018 04:08:59 -0700 Subject: [PATCH 041/265] Skip optical drives --- .bin/Scripts/functions/hw_diags.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index ac128ea1..d122f6c6 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -204,8 +204,8 @@ class State(): skip_dev = False dev_obj = DevObj(self, dev['name']) - # Skip loopback devices - if dev_obj.lsblk['tran'] == 'NONE': + # Skip loopback and optical devices + if dev_obj.lsblk['type'] in ['loop', 'rom']: skip_dev = True # Skip WK devices From 163f64dda7921847a5601aaa3d2b0d7825b5a5b0 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 5 Dec 2018 04:10:20 -0700 Subject: [PATCH 042/265] Reduced timeout for major exceptions --- .bin/Scripts/functions/common.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index b5896966..cc3d98b8 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -305,13 +305,13 @@ def major_exception(): except GenericAbort: # User declined upload print_warning('Upload: Aborted') - sleep(30) + sleep(10) except GenericError: # No log file or uploading disabled - sleep(30) + sleep(10) except: print_error('Upload: NS') - sleep(30) + sleep(10) else: print_success('Upload: CS') pause('Press Enter to exit...') From 5dd8fa84164876952a85b4cb97b94eb0a691ea4c Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 5 Dec 2018 17:48:30 -0700 Subject: [PATCH 043/265] Get CPU details from lscpu --- .bin/Scripts/functions/hw_diags.py | 31 +++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index d122f6c6..892dff90 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -175,6 +175,7 @@ class DevObj(): class State(): """Object to track device objects and overall state.""" def __init__(self): + self.lscpu = {} self.devs = [] self.finished = False self.panes = {} @@ -189,6 +190,28 @@ class State(): 'badblocks': {'Enabled': False, 'Order': 3}, 'I/O Benchmark': {'Enabled': False, 'Order': 4}, } + self.get_cpu_details() + + def get_cpu_details(self): + """Get CPU details from lscpu.""" + cmd = ['lscpu', '--json'] + try: + result = run_program(cmd, check=False) + json_data = json.loads(result.stdout.decode()) + except Exception as err: + # Ignore and leave self.cpu empty + print_error(err) + pause() + return + for line in json_data.get('lscpu', []): + _field = line.get('field', None).replace(':', '') + _data = line.get('data', None) + if not _field and not _data: + # Skip + print_warning(_field, _data) + pause() + continue + self.lscpu[_field] = _data def init(self): """Scan for block devices and reset all tests.""" @@ -591,9 +614,11 @@ def run_keyboard_test(): def run_mprime_test(state): """Test CPU with Prime95 and track temps.""" # Prep - tmux_update_pane( - state.panes['Top'], text='{}\n{}'.format( - TOP_PANE_TEXT, 'Prime95 & Temps')) + _title = '{}\n{}{}{}'.format( + TOP_PANE_TEXT, 'Prime95 & Temps', + ': ' if 'Model name' in state.lscpu else '', + state.lscpu.get('Model name', '')) + tmux_update_pane(state.panes['Top'], text=_title) state.tests['Prime95 & Temps']['Started'] = True update_progress_pane(state) From cb67f7e3c3ce26c7475b739ae937849b970d198a Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 5 Dec 2018 19:59:41 -0700 Subject: [PATCH 044/265] Added new sensors.py and dropped borrowed sensors --- .bin/Scripts/borrowed/sensors-README.md | 35 ---- .bin/Scripts/borrowed/sensors.py | 236 ------------------------ .bin/Scripts/functions/common.py | 11 +- .bin/Scripts/functions/sensors.py | 111 +++++++++++ 4 files changed, 117 insertions(+), 276 deletions(-) delete mode 100644 .bin/Scripts/borrowed/sensors-README.md delete mode 100644 .bin/Scripts/borrowed/sensors.py create mode 100644 .bin/Scripts/functions/sensors.py diff --git a/.bin/Scripts/borrowed/sensors-README.md b/.bin/Scripts/borrowed/sensors-README.md deleted file mode 100644 index 11858382..00000000 --- a/.bin/Scripts/borrowed/sensors-README.md +++ /dev/null @@ -1,35 +0,0 @@ -sensors.py -========== -python bindings using ctypes for libsensors3 of the [lm-sensors project](https://github.com/groeck/lm-sensors). The code was written against libsensors 3.3.4. - -For documentation of the low level API see [sensors.h](https://github.com/groeck/lm-sensors/blob/master/lib/sensors.h). For an example of the high level API see [example.py](example.py). - -For a GUI application that displays the sensor readings and is based on this library, take a look at [sensors-unity](https://launchpad.net/sensors-unity). - -Features --------- -* Full access to low level libsensors3 API -* High level iterator API -* unicode handling -* Python2 and Python3 compatible - -Licensing ---------- -LGPLv2 (same as libsensors3) - -Usage Notes ------------ -As Python does not support call by reference for primitive types some of the libsensors API had to be adapted: - -```python -# nr is changed by refrence in the C API -chip_name, nr = sensors.get_detected_chips(None, nr) - -# returns the value. throws on error -val = sensors.get_value(chip, subfeature_nr) -``` - -Missing Features (pull requests are welcome): -* `sensors_subfeature_type` enum -* `sensors_get_subfeature` -* Error handlers diff --git a/.bin/Scripts/borrowed/sensors.py b/.bin/Scripts/borrowed/sensors.py deleted file mode 100644 index 39b00a4f..00000000 --- a/.bin/Scripts/borrowed/sensors.py +++ /dev/null @@ -1,236 +0,0 @@ -""" -@package sensors.py -Python Bindings for libsensors3 - -use the documentation of libsensors for the low level API. -see example.py for high level API usage. - -@author: Pavel Rojtberg (http://www.rojtberg.net) -@see: https://github.com/paroj/sensors.py -@copyright: LGPLv2 (same as libsensors) -""" - -from ctypes import * -import ctypes.util - -_libc = cdll.LoadLibrary(ctypes.util.find_library("c")) -# see https://github.com/paroj/sensors.py/issues/1 -_libc.free.argtypes = [c_void_p] - -_hdl = cdll.LoadLibrary(ctypes.util.find_library("sensors")) - -version = c_char_p.in_dll(_hdl, "libsensors_version").value.decode("ascii") - -class bus_id(Structure): - _fields_ = [("type", c_short), - ("nr", c_short)] - -class chip_name(Structure): - _fields_ = [("prefix", c_char_p), - ("bus", bus_id), - ("addr", c_int), - ("path", c_char_p)] - -class feature(Structure): - _fields_ = [("name", c_char_p), - ("number", c_int), - ("type", c_int)] - - # sensors_feature_type - IN = 0x00 - FAN = 0x01 - TEMP = 0x02 - POWER = 0x03 - ENERGY = 0x04 - CURR = 0x05 - HUMIDITY = 0x06 - MAX_MAIN = 0x7 - VID = 0x10 - INTRUSION = 0x11 - MAX_OTHER = 0x12 - BEEP_ENABLE = 0x18 - -class subfeature(Structure): - _fields_ = [("name", c_char_p), - ("number", c_int), - ("type", c_int), - ("mapping", c_int), - ("flags", c_uint)] - -_hdl.sensors_get_detected_chips.restype = POINTER(chip_name) -_hdl.sensors_get_features.restype = POINTER(feature) -_hdl.sensors_get_all_subfeatures.restype = POINTER(subfeature) -_hdl.sensors_get_label.restype = c_void_p # return pointer instead of str so we can free it -_hdl.sensors_get_adapter_name.restype = c_char_p # docs do not say whether to free this or not -_hdl.sensors_strerror.restype = c_char_p - -### RAW API ### -MODE_R = 1 -MODE_W = 2 -COMPUTE_MAPPING = 4 - -def init(cfg_file = None): - file = _libc.fopen(cfg_file.encode("utf-8"), "r") if cfg_file is not None else None - - if _hdl.sensors_init(file) != 0: - raise Exception("sensors_init failed") - - if file is not None: - _libc.fclose(file) - -def cleanup(): - _hdl.sensors_cleanup() - -def parse_chip_name(orig_name): - ret = chip_name() - err= _hdl.sensors_parse_chip_name(orig_name.encode("utf-8"), byref(ret)) - - if err < 0: - raise Exception(strerror(err)) - - return ret - -def strerror(errnum): - return _hdl.sensors_strerror(errnum).decode("utf-8") - -def free_chip_name(chip): - _hdl.sensors_free_chip_name(byref(chip)) - -def get_detected_chips(match, nr): - """ - @return: (chip, next nr to query) - """ - _nr = c_int(nr) - - if match is not None: - match = byref(match) - - chip = _hdl.sensors_get_detected_chips(match, byref(_nr)) - chip = chip.contents if bool(chip) else None - return chip, _nr.value - -def chip_snprintf_name(chip, buffer_size=200): - """ - @param buffer_size defaults to the size used in the sensors utility - """ - ret = create_string_buffer(buffer_size) - err = _hdl.sensors_snprintf_chip_name(ret, buffer_size, byref(chip)) - - if err < 0: - raise Exception(strerror(err)) - - return ret.value.decode("utf-8") - -def do_chip_sets(chip): - """ - @attention this function was not tested - """ - err = _hdl.sensors_do_chip_sets(byref(chip)) - if err < 0: - raise Exception(strerror(err)) - -def get_adapter_name(bus): - return _hdl.sensors_get_adapter_name(byref(bus)).decode("utf-8") - -def get_features(chip, nr): - """ - @return: (feature, next nr to query) - """ - _nr = c_int(nr) - feature = _hdl.sensors_get_features(byref(chip), byref(_nr)) - feature = feature.contents if bool(feature) else None - return feature, _nr.value - -def get_label(chip, feature): - ptr = _hdl.sensors_get_label(byref(chip), byref(feature)) - val = cast(ptr, c_char_p).value.decode("utf-8") - _libc.free(ptr) - return val - -def get_all_subfeatures(chip, feature, nr): - """ - @return: (subfeature, next nr to query) - """ - _nr = c_int(nr) - subfeature = _hdl.sensors_get_all_subfeatures(byref(chip), byref(feature), byref(_nr)) - subfeature = subfeature.contents if bool(subfeature) else None - return subfeature, _nr.value - -def get_value(chip, subfeature_nr): - val = c_double() - err = _hdl.sensors_get_value(byref(chip), subfeature_nr, byref(val)) - if err < 0: - raise Exception(strerror(err)) - return val.value - -def set_value(chip, subfeature_nr, value): - """ - @attention this function was not tested - """ - val = c_double(value) - err = _hdl.sensors_set_value(byref(chip), subfeature_nr, byref(val)) - if err < 0: - raise Exception(strerror(err)) - -### Convenience API ### -class ChipIterator: - def __init__(self, match = None): - self.match = parse_chip_name(match) if match is not None else None - self.nr = 0 - - def __iter__(self): - return self - - def __next__(self): - chip, self.nr = get_detected_chips(self.match, self.nr) - - if chip is None: - raise StopIteration - - return chip - - def __del__(self): - if self.match is not None: - free_chip_name(self.match) - - def next(self): # python2 compability - return self.__next__() - -class FeatureIterator: - def __init__(self, chip): - self.chip = chip - self.nr = 0 - - def __iter__(self): - return self - - def __next__(self): - feature, self.nr = get_features(self.chip, self.nr) - - if feature is None: - raise StopIteration - - return feature - - def next(self): # python2 compability - return self.__next__() - -class SubFeatureIterator: - def __init__(self, chip, feature): - self.chip = chip - self.feature = feature - self.nr = 0 - - def __iter__(self): - return self - - def __next__(self): - subfeature, self.nr = get_all_subfeatures(self.chip, self.feature, self.nr) - - if subfeature is None: - raise StopIteration - - return subfeature - - def next(self): # python2 compability - return self.__next__() diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index cc3d98b8..2bf52a85 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -25,12 +25,13 @@ global_vars = {} # STATIC VARIABLES COLORS = { - 'CLEAR': '\033[0m', - 'RED': '\033[31m', - 'GREEN': '\033[32m', + 'CLEAR': '\033[0m', + 'RED': '\033[31m', + 'GREEN': '\033[32m', 'YELLOW': '\033[33m', - 'BLUE': '\033[34m' -} + 'ORANGE': '\033[31;1m', + 'BLUE': '\033[34m' + } try: HKU = winreg.HKEY_USERS HKCR = winreg.HKEY_CLASSES_ROOT diff --git a/.bin/Scripts/functions/sensors.py b/.bin/Scripts/functions/sensors.py new file mode 100644 index 00000000..0cb65acd --- /dev/null +++ b/.bin/Scripts/functions/sensors.py @@ -0,0 +1,111 @@ +# Wizard Kit: Functions - Sensors + +import itertools +import json +import re + +from functions.common import * + +# STATIC VARIABLES +TEMP_LIMITS = { + 'GREEN': 60, + 'YELLOW': 70, + 'ORANGE': 80, + 'RED': 90, + } + +# REGEX +REGEX_COLORS = re.compile(r'\033\[\d+;?1?m') + +def fix_sensor_str(s): + """Cleanup string and return str.""" + s = re.sub(r'^(\w+)-(\w+)-(\w+)', r'\1 (\2 \3)', s, re.IGNORECASE) + s = s.title() + s = s.replace('Coretemp', 'CoreTemp') + s = s.replace('Acpi', 'ACPI') + s = s.replace('Isa ', 'ISA ') + s = s.replace('Id ', 'ID ') + s = re.sub(r'(\D+)(\d+)', r'\1 \2', s, re.IGNORECASE) + s = s.replace(' ', ' ') + return s + +def get_color_temp(temp): + """Get colored temp string, returns str.""" + try: + temp = float(temp) + except ValueError: + return '{YELLOW}{temp}{CLEAR}'.format(temp=temp, **COLORS) + if temp > TEMP_LIMITS['RED']: + color = COLORS['RED'] + elif temp > TEMP_LIMITS['ORANGE']: + color = COLORS['ORANGE'] + elif temp > TEMP_LIMITS['YELLOW']: + color = COLORS['YELLOW'] + elif temp > TEMP_LIMITS['GREEN']: + color = COLORS['GREEN'] + elif temp > 0: + color = COLORS['BLUE'] + else: + color = COLORS['CLEAR'] + return '{color}{prefix}{temp:2.0f}°C{CLEAR}'.format( + color = color, + prefix = '-' if temp < 0 else '', + temp = temp, + **COLORS) + +def get_raw_sensor_data(): + """Read sensor data and return dict.""" + cmd = ['sensors', '-j'] + result = run_program(cmd) + return json.loads(result.stdout.decode()) + +def get_sensor_data(): + """Parse raw sensor data and return new dict.""" + json_data = get_raw_sensor_data() + sensor_data = {'CoreTemps': {}, 'Other': {}} + for _adapter, _sources in json_data.items(): + if 'coretemp' in _adapter: + _section = 'CoreTemps' + else: + _section = 'Other' + sensor_data[_section][_adapter] = {} + _sources.pop('Adapter', None) + + # Find current temp and add to dict + ## current temp is labeled xxxx_input + for _source, _labels in _sources.items(): + for _label, _temp in _labels.items(): + if 'input' in _label: + sensor_data[_section][_adapter][_source] = { + 'Temps': [_temp], + 'Label': _label, + } + + # Remove empty sections + for k, v in sensor_data.items(): + v = {k2: v2 for k2, v2 in v.items() if v2} + + # Done + return sensor_data + +def update_sensor_data(sensor_data): + """Read sensors and update existing sensor_data, returns dict.""" + json_data = get_raw_sensor_data() + for _section, _adapters in sensor_data.items(): + for _adapter, _sources in _adapters.items(): + for _source, _data in _sources.items(): + _label = _ddata['Label'] + _temp = json_data[_adapter][_source][_label] + _data['Temps'].append(_temp) + return sensor_data + +def join_columns(column1, column2, width=55): + return '{:<{}}{}'.format( + column1, + 55+len(column1)-len(REGEX_COLORS.sub('', column1)), + column2) + +if __name__ == '__main__': + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From 7140f38ba4fefdfb571405b97a80e2eb7ee6f783 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 5 Dec 2018 20:11:10 -0700 Subject: [PATCH 045/265] Added average, clear, and max temps sections --- .bin/Scripts/functions/sensors.py | 38 ++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/.bin/Scripts/functions/sensors.py b/.bin/Scripts/functions/sensors.py index 0cb65acd..10a2e664 100644 --- a/.bin/Scripts/functions/sensors.py +++ b/.bin/Scripts/functions/sensors.py @@ -17,6 +17,14 @@ TEMP_LIMITS = { # REGEX REGEX_COLORS = re.compile(r'\033\[\d+;?1?m') +def clear_temps(sensor_data): + """Clear saved temps but keep structure, returns dict.""" + for _section, _adapters in sensor_data.items(): + for _adapter, _sources in _adapters.items(): + for _source, _data in _sources.items(): + _data['Temps'] = [] + return sensor_data + def fix_sensor_str(s): """Cleanup string and return str.""" s = re.sub(r'^(\w+)-(\w+)-(\w+)', r'\1 (\2 \3)', s, re.IGNORECASE) @@ -88,13 +96,41 @@ def get_sensor_data(): # Done return sensor_data +def save_max_temp(sensor_data): + """Record max temps seen this session, returns dict.""" + for _section, _adapters in sensor_data.items(): + for _adapter, _sources in _adapters.items(): + for _source, _data in _sources.items(): + _data['Max'] = max(_data['Temps']) + + # Done + return sensor_data + +def save_average_temp(sensor_data, save_label, seconds=10): + """Calculate average temps and record under save_label, returns dict.""" + clear_temps(sensor_data) + + # Get temps + for i in range(seconds): + sensor_data = update_sensor_data(sensor_data) + sleep(1) + + # Calculate averages + for _section, _adapters in sensor_data.items(): + for _adapter, _sources in _adapters.items(): + for _source, _data in _sources.items(): + _data[save_label] = sum(_data['Temps']) / len(_data['Temps']) + + # Done + return sensor_data + def update_sensor_data(sensor_data): """Read sensors and update existing sensor_data, returns dict.""" json_data = get_raw_sensor_data() for _section, _adapters in sensor_data.items(): for _adapter, _sources in _adapters.items(): for _source, _data in _sources.items(): - _label = _ddata['Label'] + _label = _data['Label'] _temp = json_data[_adapter][_source][_label] _data['Temps'].append(_temp) return sensor_data From 2eccc236a960235df41ec864116affae0efd281f Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 5 Dec 2018 20:40:25 -0700 Subject: [PATCH 046/265] Added generate_report() * Also merged save_max_temp() with update_sensor_data() * Max doesn't need resetting so just calc max everytime --- .bin/Scripts/functions/sensors.py | 59 +++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 15 deletions(-) diff --git a/.bin/Scripts/functions/sensors.py b/.bin/Scripts/functions/sensors.py index 10a2e664..30df47de 100644 --- a/.bin/Scripts/functions/sensors.py +++ b/.bin/Scripts/functions/sensors.py @@ -37,8 +37,30 @@ def fix_sensor_str(s): s = s.replace(' ', ' ') return s -def get_color_temp(temp): - """Get colored temp string, returns str.""" +def generate_report(sensor_data, *temp_labels, colors=True): + """Build report based on temp_labels, returns list if str.""" + report = [] + for _section, _adapters in sorted(sensor_data.items()): + # CoreTemps then Other temps + for _adapter, _sources in sorted(_adapters.items()): + # Adapter + report.append(fix_sensor_str(_adapter)) + for _source, _data in sorted(_sources.items()): + # Source + _line = '{:18} '.format(fix_sensor_str(_source)) + _temps = [] + for _label in temp_labels: + _temps.append('{}{}{}'.format( + _label.lower() if _label != 'Current' else '', + ': ' if _label != 'Current' else '', + get_temp_str(_data[_label], colors=colors))) + _line += ', '.join(_temps) + report.append(_line) + report.append(' ') + return sensor_data + +def get_colored_temp_str(temp): + """Get colored string based on temp, returns str.""" try: temp = float(temp) except ValueError: @@ -85,8 +107,10 @@ def get_sensor_data(): for _label, _temp in _labels.items(): if 'input' in _label: sensor_data[_section][_adapter][_source] = { - 'Temps': [_temp], + 'Current': _temp, 'Label': _label, + 'Max': _temp, + 'Temps': [_temp], } # Remove empty sections @@ -96,18 +120,21 @@ def get_sensor_data(): # Done return sensor_data -def save_max_temp(sensor_data): - """Record max temps seen this session, returns dict.""" - for _section, _adapters in sensor_data.items(): - for _adapter, _sources in _adapters.items(): - for _source, _data in _sources.items(): - _data['Max'] = max(_data['Temps']) +def get_temp_str(temp, colors=True): + """Get temp string, returns str.""" + if colors: + return get_colored_temp_str(temp) + try: + temp = float(temp) + except ValueError: + return '{}°C'.format(temp) + else: + return '{}{:2.0f}°C'.format( + '-' if temp < 0 else '', + temp) - # Done - return sensor_data - -def save_average_temp(sensor_data, save_label, seconds=10): - """Calculate average temps and record under save_label, returns dict.""" +def save_average_temp(sensor_data, temp_label, seconds=10): + """Calculate average temps and record under temp_label, returns dict.""" clear_temps(sensor_data) # Get temps @@ -119,7 +146,7 @@ def save_average_temp(sensor_data, save_label, seconds=10): for _section, _adapters in sensor_data.items(): for _adapter, _sources in _adapters.items(): for _source, _data in _sources.items(): - _data[save_label] = sum(_data['Temps']) / len(_data['Temps']) + _data[temp_label] = sum(_data['Temps']) / len(_data['Temps']) # Done return sensor_data @@ -132,6 +159,8 @@ def update_sensor_data(sensor_data): for _source, _data in _sources.items(): _label = _data['Label'] _temp = json_data[_adapter][_source][_label] + _data['Current'] = _temp + _data['Max'] = max(_temp, _data['Max']) _data['Temps'].append(_temp) return sensor_data From 328d6eb29484711774a5386c79a9415d25d2c3a4 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 5 Dec 2018 20:47:40 -0700 Subject: [PATCH 047/265] Modify sensor_data in place --- .bin/Scripts/functions/sensors.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.bin/Scripts/functions/sensors.py b/.bin/Scripts/functions/sensors.py index 30df47de..bead3bfa 100644 --- a/.bin/Scripts/functions/sensors.py +++ b/.bin/Scripts/functions/sensors.py @@ -23,7 +23,6 @@ def clear_temps(sensor_data): for _adapter, _sources in _adapters.items(): for _source, _data in _sources.items(): _data['Temps'] = [] - return sensor_data def fix_sensor_str(s): """Cleanup string and return str.""" @@ -57,7 +56,6 @@ def generate_report(sensor_data, *temp_labels, colors=True): _line += ', '.join(_temps) report.append(_line) report.append(' ') - return sensor_data def get_colored_temp_str(temp): """Get colored string based on temp, returns str.""" @@ -139,7 +137,7 @@ def save_average_temp(sensor_data, temp_label, seconds=10): # Get temps for i in range(seconds): - sensor_data = update_sensor_data(sensor_data) + update_sensor_data(sensor_data) sleep(1) # Calculate averages @@ -148,9 +146,6 @@ def save_average_temp(sensor_data, temp_label, seconds=10): for _source, _data in _sources.items(): _data[temp_label] = sum(_data['Temps']) / len(_data['Temps']) - # Done - return sensor_data - def update_sensor_data(sensor_data): """Read sensors and update existing sensor_data, returns dict.""" json_data = get_raw_sensor_data() @@ -162,7 +157,6 @@ def update_sensor_data(sensor_data): _data['Current'] = _temp _data['Max'] = max(_temp, _data['Max']) _data['Temps'].append(_temp) - return sensor_data def join_columns(column1, column2, width=55): return '{:<{}}{}'.format( From 95b0d1e3f4823d31bcbf5bc0c2ee20753b20379e Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 5 Dec 2018 21:54:41 -0700 Subject: [PATCH 048/265] Wrap reports if necessary --- .bin/Scripts/functions/sensors.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/.bin/Scripts/functions/sensors.py b/.bin/Scripts/functions/sensors.py index bead3bfa..5e33e1cb 100644 --- a/.bin/Scripts/functions/sensors.py +++ b/.bin/Scripts/functions/sensors.py @@ -3,6 +3,7 @@ import itertools import json import re +import shutil from functions.common import * @@ -37,7 +38,7 @@ def fix_sensor_str(s): return s def generate_report(sensor_data, *temp_labels, colors=True): - """Build report based on temp_labels, returns list if str.""" + """Generate report based on temp_labels, returns list if str.""" report = [] for _section, _adapters in sorted(sensor_data.items()): # CoreTemps then Other temps @@ -48,6 +49,7 @@ def generate_report(sensor_data, *temp_labels, colors=True): # Source _line = '{:18} '.format(fix_sensor_str(_source)) _temps = [] + # Temps (skip label for Current) for _label in temp_labels: _temps.append('{}{}{}'.format( _label.lower() if _label != 'Current' else '', @@ -57,6 +59,26 @@ def generate_report(sensor_data, *temp_labels, colors=True): report.append(_line) report.append(' ') + # Wrap lines if necessary + screen_size = shutil.get_terminal_size() + rows = screen_size.lines - 1 + if len(report) > rows and screen_size.columns > 55*2: + report = list(itertools.zip_longest( + report[:rows], report[rows:], fillvalue='')) + report = [join_columns(a, b) for a, b in report] + + # Handle empty reports (i.e. no sensors detected) + if not report: + report = [ + '{}WARNING: No sensors found{}'.format( + COLORS['YELLOW'] if colors else '', + COLORS['CLEAR'] if colors else ''), + ' ', + 'Please monitor temps manually'] + + # Done + return report + def get_colored_temp_str(temp): """Get colored string based on temp, returns str.""" try: From 0e5fab01047c69fd875d43e5ced54377f70a5ec5 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 5 Dec 2018 21:57:55 -0700 Subject: [PATCH 049/265] Handle missing labels in generate_report() --- .bin/Scripts/functions/sensors.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.bin/Scripts/functions/sensors.py b/.bin/Scripts/functions/sensors.py index 5e33e1cb..b47f9afd 100644 --- a/.bin/Scripts/functions/sensors.py +++ b/.bin/Scripts/functions/sensors.py @@ -54,7 +54,7 @@ def generate_report(sensor_data, *temp_labels, colors=True): _temps.append('{}{}{}'.format( _label.lower() if _label != 'Current' else '', ': ' if _label != 'Current' else '', - get_temp_str(_data[_label], colors=colors))) + get_temp_str(_data.get(_label, '???'), colors=colors))) _line += ', '.join(_temps) report.append(_line) report.append(' ') @@ -147,7 +147,7 @@ def get_temp_str(temp, colors=True): try: temp = float(temp) except ValueError: - return '{}°C'.format(temp) + return '{}'.format(temp) else: return '{}{:2.0f}°C'.format( '-' if temp < 0 else '', From 46080b43634f0317b78581c28a86493afc8acf06 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 5 Dec 2018 22:25:44 -0700 Subject: [PATCH 050/265] Moved tmux sections to separate file --- .bin/Scripts/functions/hw_diags.py | 66 +-------------------------- .bin/Scripts/functions/tmux.py | 72 ++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 65 deletions(-) create mode 100644 .bin/Scripts/functions/tmux.py diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 892dff90..cc9a2c40 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -4,7 +4,7 @@ import json import re import time -from functions.common import * +from functions.tmux import * # STATIC VARIABLES ATTRIBUTES = { @@ -686,70 +686,6 @@ def secret_screensaver(screensaver=None): raise Exception('Invalid screensaver') run_program(cmd, check=False, pipe=False) -def tmux_kill_pane(*panes): - """Kill tmux pane by id.""" - cmd = ['tmux', 'kill-pane', '-t'] - for pane_id in panes: - print(pane_id) - run_program(cmd+[pane_id], check=False) - -def tmux_split_window( - lines=None, percent=None, - behind=False, vertical=False, - follow=False, target_pane=None, - command=None, text=None, watch=None): - """Run tmux split-window command and return pane_id as str.""" - # Bail early - if not lines and not percent: - raise Exception('Neither lines nor percent specified.') - if not command and not text and not watch: - raise Exception('No command, text, or watch file specified.') - - # Build cmd - cmd = ['tmux', 'split-window', '-PF', '#D'] - if behind: - cmd.append('-b') - if vertical: - cmd.append('-v') - else: - cmd.append('-h') - if not follow: - cmd.append('-d') - if lines is not None: - cmd.extend(['-l', str(lines)]) - elif percent is not None: - cmd.extend(['-p', str(percent)]) - if target_pane: - cmd.extend(['-t', str(target_pane)]) - - if command: - cmd.extend(command) - elif text: - cmd.extend(['echo-and-hold "{}"'.format(text)]) - elif watch: - cmd.extend([ - 'watch', '--color', '--no-title', - '--interval', '1', - 'cat', watch]) - - # Run and return pane_id - result = run_program(cmd) - return result.stdout.decode().strip() - -def tmux_update_pane(pane_id, command=None, text=None): - """Respawn with either a new command or new text.""" - # Bail early - if not command and not text: - raise Exception('Neither command nor text specified.') - - cmd = ['tmux', 'respawn-pane', '-k', '-t', pane_id] - if command: - cmd.extend(command) - elif text: - cmd.extend(['echo-and-hold "{}"'.format(text)]) - - run_program(cmd) - def update_main_options(state, selection, main_options): """Update menu and state based on selection.""" index = int(selection) - 1 diff --git a/.bin/Scripts/functions/tmux.py b/.bin/Scripts/functions/tmux.py new file mode 100644 index 00000000..ba00220f --- /dev/null +++ b/.bin/Scripts/functions/tmux.py @@ -0,0 +1,72 @@ +# Wizard Kit: Functions - tmux + +from functions.common import * + +def tmux_kill_pane(*panes): + """Kill tmux pane by id.""" + cmd = ['tmux', 'kill-pane', '-t'] + for pane_id in panes: + print(pane_id) + run_program(cmd+[pane_id], check=False) + +def tmux_split_window( + lines=None, percent=None, + behind=False, vertical=False, + follow=False, target_pane=None, + command=None, text=None, watch=None): + """Run tmux split-window command and return pane_id as str.""" + # Bail early + if not lines and not percent: + raise Exception('Neither lines nor percent specified.') + if not command and not text and not watch: + raise Exception('No command, text, or watch file specified.') + + # Build cmd + cmd = ['tmux', 'split-window', '-PF', '#D'] + if behind: + cmd.append('-b') + if vertical: + cmd.append('-v') + else: + cmd.append('-h') + if not follow: + cmd.append('-d') + if lines is not None: + cmd.extend(['-l', str(lines)]) + elif percent is not None: + cmd.extend(['-p', str(percent)]) + if target_pane: + cmd.extend(['-t', str(target_pane)]) + + if command: + cmd.extend(command) + elif text: + cmd.extend(['echo-and-hold "{}"'.format(text)]) + elif watch: + cmd.extend([ + 'watch', '--color', '--no-title', + '--interval', '1', + 'cat', watch]) + + # Run and return pane_id + result = run_program(cmd) + return result.stdout.decode().strip() + +def tmux_update_pane(pane_id, command=None, text=None): + """Respawn with either a new command or new text.""" + # Bail early + if not command and not text: + raise Exception('Neither command nor text specified.') + + cmd = ['tmux', 'respawn-pane', '-k', '-t', pane_id] + if command: + cmd.extend(command) + elif text: + cmd.extend(['echo-and-hold "{}"'.format(text)]) + + run_program(cmd) + +if __name__ == '__main__': + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From 5405b97eb1cb6b6747ea44e9f64a848e5977f175 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 5 Dec 2018 23:09:42 -0700 Subject: [PATCH 051/265] Standalone sensor monitor working again --- .bin/Scripts/functions/sensors.py | 14 ++- .bin/Scripts/functions/tmux.py | 7 ++ .bin/Scripts/hw-sensors | 168 +----------------------------- .bin/Scripts/hw-sensors-monitor | 31 ++++++ 4 files changed, 56 insertions(+), 164 deletions(-) create mode 100755 .bin/Scripts/hw-sensors-monitor diff --git a/.bin/Scripts/functions/sensors.py b/.bin/Scripts/functions/sensors.py index b47f9afd..ec53e548 100644 --- a/.bin/Scripts/functions/sensors.py +++ b/.bin/Scripts/functions/sensors.py @@ -5,7 +5,7 @@ import json import re import shutil -from functions.common import * +from functions.tmux import * # STATIC VARIABLES TEMP_LIMITS = { @@ -153,6 +153,18 @@ def get_temp_str(temp, colors=True): '-' if temp < 0 else '', temp) +def monitor_sensors(monitor_pane, monitor_file): + """Continually update sensor data and report to screen.""" + sensor_data = get_sensor_data() + while True: + update_sensor_data(sensor_data) + with open(monitor_file, 'w') as f: + report = generate_report(sensor_data, 'Current', 'Max') + f.write('\n'.join(report)) + sleep(1) + if not tmux_poll_pane(monitor_pane): + break + def save_average_temp(sensor_data, temp_label, seconds=10): """Calculate average temps and record under temp_label, returns dict.""" clear_temps(sensor_data) diff --git a/.bin/Scripts/functions/tmux.py b/.bin/Scripts/functions/tmux.py index ba00220f..10412a8c 100644 --- a/.bin/Scripts/functions/tmux.py +++ b/.bin/Scripts/functions/tmux.py @@ -9,6 +9,13 @@ def tmux_kill_pane(*panes): print(pane_id) run_program(cmd+[pane_id], check=False) +def tmux_poll_pane(pane_id): + """Check if pane exists, returns bool.""" + cmd = ['tmux', 'list-panes', '-F', '#D'] + result = run_program(cmd, check=False) + panes = result.stdout.decode().splitlines() + return pane_id in panes + def tmux_split_window( lines=None, percent=None, behind=False, vertical=False, diff --git a/.bin/Scripts/hw-sensors b/.bin/Scripts/hw-sensors index f251c589..39ca7147 100755 --- a/.bin/Scripts/hw-sensors +++ b/.bin/Scripts/hw-sensors @@ -1,168 +1,10 @@ -#!/bin/python3 +#!/bin/bash # ## Wizard Kit: Sensor monitoring tool -import itertools -import os -import shutil -import sys +WINDOW_NAME="Hardware Sensors" +MONITOR="hw-sensors-monitor" -# Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) -from functions.common import * -from borrowed import sensors - -# STATIC VARIABLES -COLORS = { - 'CLEAR': '\033[0m', - 'RED': '\033[31m', - 'GREEN': '\033[32m', - 'YELLOW': '\033[33m', - 'ORANGE': '\033[31;1m', - 'BLUE': '\033[34m' - } -TEMP_LIMITS = { - 'GREEN': 60, - 'YELLOW': 70, - 'ORANGE': 80, - 'RED': 90, - } - -# REGEX -REGEX_COLORS = re.compile(r'\033\[\d+;?1?m') - -def color_temp(temp): - try: - temp = float(temp) - except ValueError: - return '{YELLOW}{temp}{CLEAR}'.format(temp=temp, **COLORS) - if temp > TEMP_LIMITS['RED']: - color = COLORS['RED'] - elif temp > TEMP_LIMITS['ORANGE']: - color = COLORS['ORANGE'] - elif temp > TEMP_LIMITS['YELLOW']: - color = COLORS['YELLOW'] - elif temp > TEMP_LIMITS['GREEN']: - color = COLORS['GREEN'] - elif temp > 0: - color = COLORS['BLUE'] - else: - color = COLORS['CLEAR'] - return '{color}{prefix}{temp:2.0f}°C{CLEAR}'.format( - color = color, - prefix = '-' if temp < 0 else '', - temp = temp, - **COLORS) - -def get_feature_string(chip, feature): - sfs = list(sensors.SubFeatureIterator(chip, feature)) # get a list of all subfeatures - label = sensors.get_label(chip, feature) - skipname = len(feature.name)+1 # skip common prefix - data = {} - - if feature.type != sensors.feature.TEMP: - # Skip non-temperature sensors - return None - - for sf in sfs: - name = sf.name[skipname:].decode("utf-8").strip() - try: - val = sensors.get_value(chip, sf.number) - except Exception: - # Ignore upstream sensor bugs and lie instead - val = -123456789 - if 'alarm' in name: - # Skip - continue - if '--nocolor' in sys.argv: - try: - temp = float(val) - except ValueError: - data[name] = ' {}°C'.format(val) - else: - data[name] = '{}{:2.0f}°C'.format( - '-' if temp < 0 else '', - temp) - else: - data[name] = color_temp(val) - - main_temp = data.pop('input', None) - if main_temp: - list_data = [] - for item in ['max', 'crit']: - if item in data: - list_data.append('{}: {}'.format(item, data.pop(item))) - list_data.extend( - ['{}: {}'.format(k, v) for k, v in sorted(data.items())]) - data_str = '{:18} {} {}'.format( - label, main_temp, ', '.join(list_data)) - else: - list_data.extend(sorted(data.items())) - list_data = ['{}: {}'.format(item[0], item[1]) for item in list_data] - data_str = '{:18} {}'.format(label, ', '.join(list_data)) - return data_str - -def join_columns(column1, column2, width=55): - return '{:<{}}{}'.format( - column1, - 55+len(column1)-len(REGEX_COLORS.sub('', column1)), - column2) - -if __name__ == '__main__': - try: - # Prep - sensors.init() - - # Get sensor data - chip_temps = {} - for chip in sensors.ChipIterator(): - chip_name = '{} ({})'.format( - sensors.chip_snprintf_name(chip), - sensors.get_adapter_name(chip.bus)) - chip_feats = [get_feature_string(chip, feature) - for feature in sensors.FeatureIterator(chip)] - # Strip empty/None items - chip_feats = [f for f in chip_feats if f] - - if chip_feats: - chip_temps[chip_name] = [chip_name, *chip_feats, ''] - - # Sort chips - sensor_temps = [] - for chip in [k for k in sorted(chip_temps.keys()) if 'coretemp' in k]: - sensor_temps.extend(chip_temps[chip]) - for chip in sorted(chip_temps.keys()): - if 'coretemp' not in chip: - sensor_temps.extend(chip_temps[chip]) - - # Wrap columns as needed - screen_size = shutil.get_terminal_size() - rows = screen_size.lines - 1 - if len(sensor_temps) > rows and screen_size.columns > 55*2: - sensor_temps = list(itertools.zip_longest( - sensor_temps[:rows], sensor_temps[rows:], fillvalue='')) - sensor_temps = [join_columns(a, b) for a, b in sensor_temps] - - # Print data - if sensor_temps: - for line in sensor_temps: - print_standard(line) - else: - if '--nocolor' in sys.argv: - print_standard('WARNING: No sensors found') - print_standard('\nPlease monitor temps manually') - else: - print_warning('WARNING: No sensors found') - print_standard('\nPlease monitor temps manually') - - # Done - sensors.cleanup() - exit_script() - except SystemExit: - sensors.cleanup() - pass - except: - sensors.cleanup() - major_exception() +# Start session +tmux new-session -n "$WINDOW_NAME" "$MONITOR" diff --git a/.bin/Scripts/hw-sensors-monitor b/.bin/Scripts/hw-sensors-monitor new file mode 100755 index 00000000..91651f32 --- /dev/null +++ b/.bin/Scripts/hw-sensors-monitor @@ -0,0 +1,31 @@ +#!/bin/python3 +# +## Wizard Kit: Sensor monitoring tool + +import os +import sys + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +sys.path.append(os.getcwd()) +from functions.sensors import * +from functions.tmux import * +init_global_vars() + +if __name__ == '__main__': + try: + result = run_program(['mktemp']) + monitor_file = result.stdout.decode().strip() + print(monitor_file) + monitor_pane = tmux_split_window( + percent=1, vertical=True, watch=monitor_file) + cmd = ['tmux', 'resize-pane', '-Z', '-t', monitor_pane] + run_program(cmd, check=False) + monitor_sensors(monitor_pane, monitor_file) + exit_script() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 From c777d490913d14666c958f7015996170e6d32c49 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 5 Dec 2018 23:54:37 -0700 Subject: [PATCH 052/265] Added tmux_resize_pane() --- .bin/Scripts/functions/tmux.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.bin/Scripts/functions/tmux.py b/.bin/Scripts/functions/tmux.py index 10412a8c..6726e3ff 100644 --- a/.bin/Scripts/functions/tmux.py +++ b/.bin/Scripts/functions/tmux.py @@ -16,6 +16,19 @@ def tmux_poll_pane(pane_id): panes = result.stdout.decode().splitlines() return pane_id in panes +def tmux_resize_pane(pane_id, x=None, y=None): + """Resize pane to specific hieght or width.""" + if not x and not y: + raise Exception('Neither height nor width specified.') + + cmd = ['tmux', 'resize-pane', '-t', pane_id] + if x: + cmd.extend(['-x', str(x)]) + elif y: + cmd.extend(['-y', str(y)]) + + run_program(cmd, check=False) + def tmux_split_window( lines=None, percent=None, behind=False, vertical=False, From 5550cce8dbf4c77d67f15213b2e016a321b6bf87 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 5 Dec 2018 23:55:15 -0700 Subject: [PATCH 053/265] Add background mode for monitoring sensors * This will be called by hw_diags.py to update a file in the background * NOTE: This uses a naive check before attempting to write data --- .bin/Scripts/functions/sensors.py | 2 +- .bin/Scripts/hw-sensors-monitor | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/.bin/Scripts/functions/sensors.py b/.bin/Scripts/functions/sensors.py index ec53e548..41508927 100644 --- a/.bin/Scripts/functions/sensors.py +++ b/.bin/Scripts/functions/sensors.py @@ -162,7 +162,7 @@ def monitor_sensors(monitor_pane, monitor_file): report = generate_report(sensor_data, 'Current', 'Max') f.write('\n'.join(report)) sleep(1) - if not tmux_poll_pane(monitor_pane): + if monitor_pane and not tmux_poll_pane(monitor_pane): break def save_average_temp(sensor_data, temp_label, seconds=10): diff --git a/.bin/Scripts/hw-sensors-monitor b/.bin/Scripts/hw-sensors-monitor index 91651f32..22067b91 100755 --- a/.bin/Scripts/hw-sensors-monitor +++ b/.bin/Scripts/hw-sensors-monitor @@ -13,14 +13,20 @@ from functions.tmux import * init_global_vars() if __name__ == '__main__': + background = False try: - result = run_program(['mktemp']) - monitor_file = result.stdout.decode().strip() - print(monitor_file) - monitor_pane = tmux_split_window( - percent=1, vertical=True, watch=monitor_file) - cmd = ['tmux', 'resize-pane', '-Z', '-t', monitor_pane] - run_program(cmd, check=False) + if len(sys.argv) > 1 and os.path.exists(sys.argv[1]): + background = True + monitor_file = sys.argv[1] + monitor_pane=None + else: + result = run_program(['mktemp']) + monitor_file = result.stdout.decode().strip() + if not background: + monitor_pane = tmux_split_window( + percent=1, vertical=True, watch=monitor_file) + cmd = ['tmux', 'resize-pane', '-Z', '-t', monitor_pane] + run_program(cmd, check=False) monitor_sensors(monitor_pane, monitor_file) exit_script() except SystemExit: From 74bb31e795c41b2466d33ef9fa76f169e3b8ad89 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 5 Dec 2018 23:57:38 -0700 Subject: [PATCH 054/265] Open temps monitor during run_mprime --- .bin/Scripts/functions/hw_diags.py | 17 +++++++++++++++++ .bin/Scripts/hw-sensors-monitor | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index cc9a2c40..594f807a 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -4,6 +4,7 @@ import json import re import time +from functions.sensors import * from functions.tmux import * # STATIC VARIABLES @@ -614,6 +615,13 @@ def run_keyboard_test(): def run_mprime_test(state): """Test CPU with Prime95 and track temps.""" # Prep + _sensors_out = '{}/sensors.out'.format(global_vars['TmpDir']) + with open(_sensors_out, 'w') as f: + f.write(' ') + sleep(1) + monitor_proc = popen_program( + ['hw-sensors-monitor', _sensors_out], + pipe=True) _title = '{}\n{}{}{}'.format( TOP_PANE_TEXT, 'Prime95 & Temps', ': ' if 'Model name' in state.lscpu else '', @@ -621,6 +629,15 @@ def run_mprime_test(state): tmux_update_pane(state.panes['Top'], text=_title) state.tests['Prime95 & Temps']['Started'] = True update_progress_pane(state) + state.panes['mprime'] = tmux_split_window( + lines=10, vertical=True, text='Prime95 output goes here...') + state.panes['Temps'] = tmux_split_window( + behind=True, percent=80, vertical=True, watch=_sensors_out) + tmux_resize_pane(global_vars['Env']['TMUX_PANE'], y=3) + + # Start live monitor + pause() + monitor_proc.kill() # Get idle temps # Stress CPU diff --git a/.bin/Scripts/hw-sensors-monitor b/.bin/Scripts/hw-sensors-monitor index 22067b91..42757748 100755 --- a/.bin/Scripts/hw-sensors-monitor +++ b/.bin/Scripts/hw-sensors-monitor @@ -18,7 +18,7 @@ if __name__ == '__main__': if len(sys.argv) > 1 and os.path.exists(sys.argv[1]): background = True monitor_file = sys.argv[1] - monitor_pane=None + monitor_pane = None else: result = run_program(['mktemp']) monitor_file = result.stdout.decode().strip() From 30ba6516745347f6a979c7f0763284938c0c62e8 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 6 Dec 2018 00:10:51 -0700 Subject: [PATCH 055/265] Removing report wrapping section * Doesn't work properly with background processes --- .bin/Scripts/functions/sensors.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.bin/Scripts/functions/sensors.py b/.bin/Scripts/functions/sensors.py index 41508927..29ceaa45 100644 --- a/.bin/Scripts/functions/sensors.py +++ b/.bin/Scripts/functions/sensors.py @@ -1,9 +1,7 @@ # Wizard Kit: Functions - Sensors -import itertools import json import re -import shutil from functions.tmux import * @@ -59,14 +57,6 @@ def generate_report(sensor_data, *temp_labels, colors=True): report.append(_line) report.append(' ') - # Wrap lines if necessary - screen_size = shutil.get_terminal_size() - rows = screen_size.lines - 1 - if len(report) > rows and screen_size.columns > 55*2: - report = list(itertools.zip_longest( - report[:rows], report[rows:], fillvalue='')) - report = [join_columns(a, b) for a, b in report] - # Handle empty reports (i.e. no sensors detected) if not report: report = [ From dc606a87806661a994d8472b188bdf5199fe90d0 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 6 Dec 2018 01:06:21 -0700 Subject: [PATCH 056/265] Main Prime95 sections working * Still need check results and update progress sections --- .bin/Scripts/functions/hw_diags.py | 102 ++++++++++++++++++++++++----- .bin/Scripts/functions/sensors.py | 6 +- .bin/Scripts/functions/tmux.py | 1 - .bin/Scripts/hw-diags-prime95 | 3 +- 4 files changed, 88 insertions(+), 24 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 594f807a..a2aca6c8 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -186,7 +186,8 @@ class State(): self.started = False self.tests = { 'Prime95 & Temps': {'Enabled': False, 'Order': 1, - 'Result': '', 'Started': False, 'Status': ''}, + 'Result': '', 'Sensor Data': get_sensor_data(), + 'Started': False, 'Status': ''}, 'NVMe / SMART': {'Enabled': False, 'Order': 2}, 'badblocks': {'Enabled': False, 'Order': 3}, 'I/O Benchmark': {'Enabled': False, 'Order': 4}, @@ -614,41 +615,106 @@ def run_keyboard_test(): def run_mprime_test(state): """Test CPU with Prime95 and track temps.""" - # Prep - _sensors_out = '{}/sensors.out'.format(global_vars['TmpDir']) - with open(_sensors_out, 'w') as f: - f.write(' ') - sleep(1) - monitor_proc = popen_program( - ['hw-sensors-monitor', _sensors_out], - pipe=True) + state.tests['Prime95 & Temps']['Started'] = True + update_progress_pane(state) + _sensor_data = state.tests['Prime95 & Temps']['Sensor Data'] + + # Update top pane _title = '{}\n{}{}{}'.format( TOP_PANE_TEXT, 'Prime95 & Temps', ': ' if 'Model name' in state.lscpu else '', state.lscpu.get('Model name', '')) tmux_update_pane(state.panes['Top'], text=_title) - state.tests['Prime95 & Temps']['Started'] = True - update_progress_pane(state) + + # Start live sensor monitor + _sensors_out = '{}/sensors.out'.format(global_vars['TmpDir']) + with open(_sensors_out, 'w') as f: + f.write(' ') + f.flush() + sleep(0.5) + monitor_proc = popen_program( + ['hw-sensors-monitor', _sensors_out], + pipe=True) + + # Create monitor and worker panes state.panes['mprime'] = tmux_split_window( - lines=10, vertical=True, text='Prime95 output goes here...') + lines=10, vertical=True, text=' ') state.panes['Temps'] = tmux_split_window( behind=True, percent=80, vertical=True, watch=_sensors_out) tmux_resize_pane(global_vars['Env']['TMUX_PANE'], y=3) - # Start live monitor - pause() - monitor_proc.kill() - # Get idle temps + clear_screen() + try_and_print( + message='Getting idle temps...', indent=0, + function=save_average_temp, cs='Done', + sensor_data=_sensor_data, temp_label='Idle') + # Stress CPU - # Get max temp + run_program(['apple-fans', 'max']) + tmux_update_pane( + state.panes['mprime'], + command=['hw-diags-prime95', global_vars['TmpDir']]) + time_limit = int(MPRIME_LIMIT) * 60 + try: + for i in range(time_limit): + clear_screen() + sec_left = time_limit - i + min_left = int(sec_left / 60) + if min_left > 0: + print_standard( + 'Running Prime95 ({} minute{} left)'.format( + min_left, + 's' if min_left != 1 else '')) + else: + print_standard( + 'Running Prime95 ({} second{} left)'.format( + sec_left, + 's' if sec_left != 1 else '')) + print_warning('If running too hot, press CTRL+c to abort the test') + update_sensor_data(_sensor_data) + sleep(1) + except KeyboardInterrupt: + # Catch CTRL+C + aborted = True + state.tests['Prime95 & Temps']['Result'] = 'Aborted' + print_warning('\nAborted.') + update_progress_pane(state) + + # Restart live monitor + monitor_proc = popen_program( + ['hw-sensors-monitor', _sensors_out], + pipe=True) + + # Stop Prime95 (twice for good measure) + tmux_kill_pane(state.panes['mprime']) + run_program(['killall', '-s', 'INT', 'mprime'], check=False) + # Get cooldown temp + run_program(['apple-fans', 'auto']) + clear_screen() + try_and_print( + message='Letting CPU cooldown for bit...', indent=0, + function=sleep, cs='Done', seconds=10) + try_and_print( + message='Getting cooldown temps...', indent=0, + function=save_average_temp, cs='Done', + sensor_data=_sensor_data, temp_label='Cooldown') + + # Check results + # TODO # Done - sleep(3) state.tests['Prime95 & Temps']['Result'] = 'Unknown' update_progress_pane(state) + # Cleanup + tmux_kill_pane(state.panes['mprime'], state.panes['Temps']) + monitor_proc.kill() + + # TODO Testing + print('\n'.join(generate_report(_sensor_data, 'Idle', 'Max', 'Cooldown'))) + def run_network_test(): """Run network test.""" clear_screen() diff --git a/.bin/Scripts/functions/sensors.py b/.bin/Scripts/functions/sensors.py index 29ceaa45..066dc446 100644 --- a/.bin/Scripts/functions/sensors.py +++ b/.bin/Scripts/functions/sensors.py @@ -46,14 +46,12 @@ def generate_report(sensor_data, *temp_labels, colors=True): for _source, _data in sorted(_sources.items()): # Source _line = '{:18} '.format(fix_sensor_str(_source)) - _temps = [] # Temps (skip label for Current) for _label in temp_labels: - _temps.append('{}{}{}'.format( + _line += '{}{}{} '.format( _label.lower() if _label != 'Current' else '', ': ' if _label != 'Current' else '', - get_temp_str(_data.get(_label, '???'), colors=colors))) - _line += ', '.join(_temps) + get_temp_str(_data.get(_label, '???'), colors=colors)) report.append(_line) report.append(' ') diff --git a/.bin/Scripts/functions/tmux.py b/.bin/Scripts/functions/tmux.py index 6726e3ff..c9a92194 100644 --- a/.bin/Scripts/functions/tmux.py +++ b/.bin/Scripts/functions/tmux.py @@ -6,7 +6,6 @@ def tmux_kill_pane(*panes): """Kill tmux pane by id.""" cmd = ['tmux', 'kill-pane', '-t'] for pane_id in panes: - print(pane_id) run_program(cmd+[pane_id], check=False) def tmux_poll_pane(pane_id): diff --git a/.bin/Scripts/hw-diags-prime95 b/.bin/Scripts/hw-diags-prime95 index 30c6994d..4927da76 100755 --- a/.bin/Scripts/hw-diags-prime95 +++ b/.bin/Scripts/hw-diags-prime95 @@ -14,5 +14,6 @@ if [ ! -d "$1" ]; then fi # Run Prime95 -mprime -t | grep -iv --line-buffered 'stress.txt' | tee -a "$1/prime.log" +cd "$1" +mprime -t | grep -iv --line-buffered 'stress.txt' | tee -a "prime.log" From ca4234b1c36ace85e82d98ff895885eda76b346d Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 6 Dec 2018 15:29:06 -0700 Subject: [PATCH 057/265] Added working_dir arg for tmux command sections --- .bin/Scripts/functions/hw_diags.py | 3 ++- .bin/Scripts/functions/tmux.py | 9 +++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index a2aca6c8..3c1fc5b3 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -654,7 +654,8 @@ def run_mprime_test(state): run_program(['apple-fans', 'max']) tmux_update_pane( state.panes['mprime'], - command=['hw-diags-prime95', global_vars['TmpDir']]) + command=['hw-diags-prime95', global_vars['TmpDir']], + working_dir=global_vars['TmpDir']) time_limit = int(MPRIME_LIMIT) * 60 try: for i in range(time_limit): diff --git a/.bin/Scripts/functions/tmux.py b/.bin/Scripts/functions/tmux.py index c9a92194..84ab96cc 100644 --- a/.bin/Scripts/functions/tmux.py +++ b/.bin/Scripts/functions/tmux.py @@ -32,7 +32,8 @@ def tmux_split_window( lines=None, percent=None, behind=False, vertical=False, follow=False, target_pane=None, - command=None, text=None, watch=None): + working_dir=None, command=None, + text=None, watch=None): """Run tmux split-window command and return pane_id as str.""" # Bail early if not lines and not percent: @@ -57,6 +58,8 @@ def tmux_split_window( if target_pane: cmd.extend(['-t', str(target_pane)]) + if working_dir: + cmd.extend(['-c', working_dir]) if command: cmd.extend(command) elif text: @@ -71,13 +74,15 @@ def tmux_split_window( result = run_program(cmd) return result.stdout.decode().strip() -def tmux_update_pane(pane_id, command=None, text=None): +def tmux_update_pane(pane_id, command=None, text=None, working_dir=None): """Respawn with either a new command or new text.""" # Bail early if not command and not text: raise Exception('Neither command nor text specified.') cmd = ['tmux', 'respawn-pane', '-k', '-t', pane_id] + if working_dir: + cmd.extend(['-c', working_dir]) if command: cmd.extend(command) elif text: From a910f2cb033066438af1030a1cc34d1af6c07f6f Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 6 Dec 2018 18:27:19 -0700 Subject: [PATCH 058/265] Adjusted Prime95 countdown --- .bin/Scripts/functions/hw_diags.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 3c1fc5b3..a76666ab 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -651,6 +651,8 @@ def run_mprime_test(state): sensor_data=_sensor_data, temp_label='Idle') # Stress CPU + print_log('Starting Prime95') + _abort_msg = 'If running too hot, press CTRL+c to abort the test' run_program(['apple-fans', 'max']) tmux_update_pane( state.panes['mprime'], @@ -660,24 +662,23 @@ def run_mprime_test(state): try: for i in range(time_limit): clear_screen() - sec_left = time_limit - i - min_left = int(sec_left / 60) + sec_left = (time_limit - i) % 60 + min_left = int( (time_limit - i) / 60) + _status_str = 'Running Prime95 (' if min_left > 0: - print_standard( - 'Running Prime95 ({} minute{} left)'.format( - min_left, - 's' if min_left != 1 else '')) - else: - print_standard( - 'Running Prime95 ({} second{} left)'.format( - sec_left, - 's' if sec_left != 1 else '')) - print_warning('If running too hot, press CTRL+c to abort the test') + _status_str += '{} minute{}, '.format( + min_left, + 's' if min_left != 1 else '') + _status_str += '{} second{} left)'.format( + sec_left, + 's' if sec_left != 1 else '') + # Not using print wrappers to avoid flooding the log + print(_status_str) + print('{YELLOW}{msg}{CLEAR}'.format(msg=_abort_msg, **COLORS)) update_sensor_data(_sensor_data) sleep(1) except KeyboardInterrupt: # Catch CTRL+C - aborted = True state.tests['Prime95 & Temps']['Result'] = 'Aborted' print_warning('\nAborted.') update_progress_pane(state) From 12ff99eb3213569a776363f630c3767efd596da6 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 6 Dec 2018 18:27:43 -0700 Subject: [PATCH 059/265] Set LogDir for non-quick tests --- .bin/Scripts/functions/hw_diags.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index a76666ab..e1b97df9 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -180,8 +180,7 @@ class State(): self.devs = [] self.finished = False self.panes = {} - # TODO Switch to LogDir - self.progress_out = '{}/progress.out'.format(global_vars['TmpDir']) + self.progress_out = '{}/progress.out'.format(global_vars['LogDir']) self.quick_mode = False self.started = False self.tests = { @@ -221,6 +220,16 @@ class State(): for k in ['Result', 'Started', 'Status']: self.tests['Prime95 & Temps'][k] = False if k == 'Started' else '' + # Update LogDir + if not self.quick_mode: + global_vars['LogDir'] = '{}/Logs/{}_{}'.format( + global_vars['Env']['HOME'], + get_ticket_number(), + time.strftime('%Y-%m-%d_%H%M_%z')) + os.makedirs(global_vars['LogDir'], exist_ok=True) + global_vars['LogFile'] = '{}/Hardware Diagnostics.log'.format( + global_vars['LogDir']) + # Add block devices cmd = ['lsblk', '--json', '--nodeps', '--paths'] result = run_program(cmd, check=False) @@ -703,6 +712,15 @@ def run_mprime_test(state): function=save_average_temp, cs='Done', sensor_data=_sensor_data, temp_label='Cooldown') + # Move logs to Ticket folder + for item in os.scandir(global_vars['TmpDir']): + try: + shutil.move(item.path, global_vars['LogDir']) + except Exception: + print_error('ERROR: Failed to move "{}" to "{}"'.format( + item.path, + global_vars['LogDir'])) + # Check results # TODO From 6a3ef60881ed43800605b4692e79836a2d978c03 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 8 Dec 2018 17:41:29 -0700 Subject: [PATCH 060/265] Added CpuObj and renamed dev names to disk * This should make the code more clear * The CpuObj is similar to DiskObj to abstract the device/tests calls * New calls will be like: run_test(state, dev) --- .bin/Scripts/functions/hw_diags.py | 204 +++++++++++++---------------- 1 file changed, 90 insertions(+), 114 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index e1b97df9..a2c8293d 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -67,32 +67,43 @@ SIDE_PANE_WIDTH = 20 TOP_PANE_TEXT = '{GREEN}Hardware Diagnostics{CLEAR}'.format(**COLORS) # Classes -class DevObj(): - """Device object for tracking device specific data.""" - def __init__(self, state, dev_path): - self.failing = False +class CpuObj(): + """Object for tracking CPU specific data.""" + def __init__(self): + self.lscpu = {} + self.tests = {} + self.get_details() + + def get_details(self): + """Get CPU details from lscpu.""" + cmd = ['lscpu', '--json'] + try: + result = run_program(cmd, check=False) + json_data = json.loads(result.stdout.decode()) + except Exception: + # Ignore and leave self.lscpu empty + return + for line in json_data.get('lscpu', []): + _field = line.get('field', None).replace(':', '') + _data = line.get('data', None) + if not _field and not _data: + # Skip + print_warning(_field, _data) + pause() + continue + self.lscpu[_field] = _data + +class DiskObj(): + """Object for tracking disk specific data.""" + def __init__(self, disk_path): self.labels = [] self.lsblk = {} - self.name = re.sub(r'^.*/(.*)', r'\1', dev_path) + self.name = re.sub(r'^.*/(.*)', r'\1', disk_path) self.nvme_attributes = {} - self.override = False - self.path = dev_path + self.path = disk_path self.smart_attributes = {} self.smartctl = {} - self.state = state - self.tests = { - 'NVMe / SMART': { - 'Result': '', 'Started': False, 'Status': '', 'Order': 1}, - 'badblocks': { - 'Result': '', 'Started': False, 'Status': '', 'Order': 2}, - 'I/O Benchmark': { - 'Result': '', - 'Started': False, - 'Status': '', - 'Read Rates': [], - 'Graph Data': [], - 'Order': 3}, - } + self.tests = {} self.get_details() self.get_smart_details() @@ -122,9 +133,9 @@ class DevObj(): self.lsblk['tran'] = self.lsblk['tran'].upper().replace('NVME', 'NVMe') # Build list of labels - for dev in [self.lsblk, *self.lsblk.get('children', [])]: - self.labels.append(dev.get('label', '')) - self.labels.append(dev.get('partlabel', '')) + for disk in [self.lsblk, *self.lsblk.get('children', [])]: + self.labels.append(disk.get('label', '')) + self.labels.append(disk.get('partlabel', '')) self.labels = [str(label) for label in self.labels if label] def get_smart_details(self): @@ -158,31 +169,15 @@ class DevObj(): self.smart_attributes[_id] = { 'name': _name, 'raw': _raw, 'raw_str': _raw_str} - def update_progress(self): - """Update status strings.""" - for k, v in self.tests.items(): - if self.state.tests[k]['Enabled']: - _status = '' - if not v['Status']: - _status = 'Pending' - if v['Started']: - if v['Result']: - _status = v['Result'] - else: - _status = 'Working' - if _status: - v['Status'] = build_status_string(self.name, _status) class State(): """Object to track device objects and overall state.""" def __init__(self): - self.lscpu = {} - self.devs = [] - self.finished = False + self.cpu = None + self.disks = [] self.panes = {} self.progress_out = '{}/progress.out'.format(global_vars['LogDir']) self.quick_mode = False - self.started = False self.tests = { 'Prime95 & Temps': {'Enabled': False, 'Order': 1, 'Result': '', 'Sensor Data': get_sensor_data(), @@ -191,32 +186,10 @@ class State(): 'badblocks': {'Enabled': False, 'Order': 3}, 'I/O Benchmark': {'Enabled': False, 'Order': 4}, } - self.get_cpu_details() - - def get_cpu_details(self): - """Get CPU details from lscpu.""" - cmd = ['lscpu', '--json'] - try: - result = run_program(cmd, check=False) - json_data = json.loads(result.stdout.decode()) - except Exception as err: - # Ignore and leave self.cpu empty - print_error(err) - pause() - return - for line in json_data.get('lscpu', []): - _field = line.get('field', None).replace(':', '') - _data = line.get('data', None) - if not _field and not _data: - # Skip - print_warning(_field, _data) - pause() - continue - self.lscpu[_field] = _data def init(self): - """Scan for block devices and reset all tests.""" - self.devs = [] + """Set log and add devices.""" + self.disks = [] for k in ['Result', 'Started', 'Status']: self.tests['Prime95 & Temps'][k] = False if k == 'Started' else '' @@ -230,27 +203,30 @@ class State(): global_vars['LogFile'] = '{}/Hardware Diagnostics.log'.format( global_vars['LogDir']) + # Add CPU + self.cpu = CpuObj() + # Add block devices cmd = ['lsblk', '--json', '--nodeps', '--paths'] result = run_program(cmd, check=False) json_data = json.loads(result.stdout.decode()) - for dev in json_data['blockdevices']: - skip_dev = False - dev_obj = DevObj(self, dev['name']) + for disk in json_data['blockdevices']: + skip_disk = False + disk_obj = DiskObj(disk['name']) - # Skip loopback and optical devices - if dev_obj.lsblk['type'] in ['loop', 'rom']: - skip_dev = True + # Skip loopback devices, optical devices, etc + if disk_obj.lsblk['type'] != 'disk': + skip_disk = True - # Skip WK devices + # Skip WK disks wk_label_regex = r'{}_(LINUX|UFD)'.format(KIT_NAME_SHORT) - for label in dev_obj.labels: + for label in disk_obj.labels: if re.search(wk_label_regex, label, re.IGNORECASE): - skip_dev = True + skip_disk = True - # Add device - if not skip_dev: - self.devs.append(dev_obj) + # Add disk + if not skip_disk: + self.disks.append(disk_obj) def update_progress(self): """Update status strings.""" @@ -313,32 +289,32 @@ def build_status_string(label, status, info_label=False): s_w=SIDE_PANE_WIDTH-len(label), **COLORS) -def check_dev_attributes(dev): - """Check if device should be tested and allow overrides.""" +def check_disk_attributes(disk): + """Check if disk should be tested and allow overrides.""" needs_override = False print_standard(' {size:>6} ({tran}) {model} {serial}'.format( - **dev.lsblk)) + **disk.lsblk)) # General checks - if not dev.nvme_attributes and not dev.smart_attributes: + if not disk.nvme_attributes and not disk.smart_attributes: needs_override = True print_warning( ' WARNING: No NVMe or SMART attributes available for: {}'.format( - dev.path)) + disk.path)) # NVMe checks - # TODO check all tracked attributes and set dev.failing if needed + # TODO check all tracked attributes and set disk.failing if needed # SMART checks - # TODO check all tracked attributes and set dev.failing if needed + # TODO check all tracked attributes and set disk.failing if needed # Ask for override if necessary if needs_override: if ask(' Run tests on this device anyway?'): - # TODO Set override for this dev + # TODO Set override for this disk pass else: - for v in dev.tests.values(): + for v in disk.tests.values(): # Started is set to True to fix the status string v['Result'] = 'Skipped' v['Started'] = True @@ -551,11 +527,11 @@ def run_badblocks_test(state): state.panes['Top'], text='{}\n{}'.format( TOP_PANE_TEXT, 'badblocks')) print_standard('TODO: run_badblocks_test()') - for dev in state.devs: - dev.tests['badblocks']['Started'] = True + for disk in state.disks: + disk.tests['badblocks']['Started'] = True update_progress_pane(state) sleep(3) - dev.tests['badblocks']['Result'] = 'OVERRIDE' + disk.tests['badblocks']['Result'] = 'OVERRIDE' update_progress_pane(state) def run_hw_tests(state): @@ -610,11 +586,11 @@ def run_io_benchmark(state): state.panes['Top'], text='{}\n{}'.format( TOP_PANE_TEXT, 'I/O Benchmark')) print_standard('TODO: run_io_benchmark()') - for dev in state.devs: - dev.tests['I/O Benchmark']['Started'] = True + for disk in state.disks: + disk.tests['I/O Benchmark']['Started'] = True update_progress_pane(state) sleep(3) - dev.tests['I/O Benchmark']['Result'] = 'Unknown' + disk.tests['I/O Benchmark']['Result'] = 'Unknown' update_progress_pane(state) def run_keyboard_test(): @@ -741,42 +717,42 @@ def run_network_test(): run_program(['hw-diags-network'], check=False, pipe=False) pause('Press Enter to return to main menu... ') -def run_nvme_smart(state): +def run_nvme_smart_tests(state): """TODO""" - for dev in state.devs: + for disk in state.disks: tmux_update_pane( state.panes['Top'], text='{t}\nDisk Health: {size:>6} ({tran}) {model} {serial}'.format( - t=TOP_PANE_TEXT, **dev.lsblk)) - dev.tests['NVMe / SMART']['Started'] = True + t=TOP_PANE_TEXT, **disk.lsblk)) + disk.tests['NVMe / SMART']['Started'] = True update_progress_pane(state) - if dev.nvme_attributes: - run_nvme_tests(state, dev) - elif dev.smart_attributes: - run_smart_tests(state, dev) + if disk.nvme_attributes: + run_nvme_tests(state, disk) + elif disk.smart_attributes: + run_smart_tests(state, disk) else: - print_standard('TODO: run_nvme_smart({})'.format( - dev.path)) + print_standard('TODO: run_nvme_smart_tests({})'.format( + disk.path)) print_warning( " WARNING: Device {} doesn't support NVMe or SMART test".format( - dev.path)) - dev.tests['NVMe / SMART']['Status'] = 'N/A' - dev.tests['NVMe / SMART']['Result'] = 'N/A' + disk.path)) + disk.tests['NVMe / SMART']['Status'] = 'N/A' + disk.tests['NVMe / SMART']['Result'] = 'N/A' update_progress_pane(state) sleep(3) -def run_nvme_tests(state, dev): +def run_nvme_tests(state, disk): """TODO""" - print_standard('TODO: run_nvme_test({})'.format(dev.path)) + print_standard('TODO: run_nvme_test({})'.format(disk.path)) sleep(3) - dev.tests['NVMe / SMART']['Result'] = 'CS' + disk.tests['NVMe / SMART']['Result'] = 'CS' update_progress_pane(state) -def run_smart_tests(state, dev): +def run_smart_tests(state, disk): """TODO""" - print_standard('TODO: run_smart_tests({})'.format(dev.path)) + print_standard('TODO: run_smart_tests({})'.format(disk.path)) sleep(3) - dev.tests['NVMe / SMART']['Result'] = 'CS' + disk.tests['NVMe / SMART']['Result'] = 'CS' update_progress_pane(state) def secret_screensaver(screensaver=None): @@ -872,8 +848,8 @@ def update_progress_pane(state): if 'Prime95' not in k and v['Enabled']: output.append('{BLUE}{test_name}{CLEAR}'.format( test_name=k, **COLORS)) - for dev in state.devs: - output.append(dev.tests[k]['Status']) + for disk in state.disks: + output.append(disk.tests[k]['Status']) output.append(' ') # Add line-endings From 0390290f10d44ec9ab8b41d3bfe374b61744795b Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 8 Dec 2018 17:46:17 -0700 Subject: [PATCH 061/265] Added TestObj() * This object will track test specific vars and results * Moved status code into TestObj * Test calls will now be: run_test(state, dev, test_obj) * NOTE: Code is not done and is quite broken --- .bin/Scripts/functions/hw_diags.py | 120 ++++++++++++++++++++--------- 1 file changed, 84 insertions(+), 36 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index a2c8293d..861305df 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -64,6 +64,12 @@ KEY_NVME = 'nvme_smart_health_information_log' KEY_SMART = 'ata_smart_attributes' QUICK_LABEL = '{YELLOW}(Quick){CLEAR}'.format(**COLORS) SIDE_PANE_WIDTH = 20 +TESTS_CPU = ['Prime95 & Temps'] +TESTS_DISK = [ + 'I/O Benchmark', + 'NVMe / SMART', + 'badblocks', + ] TOP_PANE_TEXT = '{GREEN}Hardware Diagnostics{CLEAR}'.format(**COLORS) # Classes @@ -169,6 +175,10 @@ class DiskObj(): self.smart_attributes[_id] = { 'name': _name, 'raw': _raw, 'raw_str': _raw_str} + def safety_check(self): + """Check enabled tests and verify it's safe to run them.""" + # TODO + pass class State(): """Object to track device objects and overall state.""" @@ -179,13 +189,31 @@ class State(): self.progress_out = '{}/progress.out'.format(global_vars['LogDir']) self.quick_mode = False self.tests = { - 'Prime95 & Temps': {'Enabled': False, 'Order': 1, - 'Result': '', 'Sensor Data': get_sensor_data(), - 'Started': False, 'Status': ''}, - 'NVMe / SMART': {'Enabled': False, 'Order': 2}, - 'badblocks': {'Enabled': False, 'Order': 3}, - 'I/O Benchmark': {'Enabled': False, 'Order': 4}, - } + 'Prime95 & Temps': { + 'Enabled': False, + 'Function': run_mprime_test, + 'Objects': [], + 'Order': 1, + }, + 'NVMe / SMART': { + 'Enabled': False, + 'Function': run_nvme_smart_tests, + 'Objects': [], + 'Order': 2, + }, + 'badblocks': { + 'Enabled': False, + 'Function': run_badblocks_test, + 'Objects': [], + 'Order': 3, + }, + 'I/O Benchmark': { + 'Enabled': False, + 'Function': run_io_benchmark, + 'Objects': [], + 'Order': 4, + }, + } def init(self): """Set log and add devices.""" @@ -228,26 +256,32 @@ class State(): if not skip_disk: self.disks.append(disk_obj) - def update_progress(self): - """Update status strings.""" - # Prime95 - p = self.tests['Prime95 & Temps'] - if p['Enabled']: - _status = '' - if not p['Status']: - _status = 'Pending' - if p['Started']: - if p['Result']: - _status = p['Result'] - else: - _status = 'Working' - if _status: - p['Status'] = build_status_string( - 'Prime95', _status, info_label=True) +class TestObj(): + """Object to track test data.""" + def __init__(self, label, info_label=False): + self.started = False + self.passed = False + self.failed = False + self.report = '' + self.status = '' + self.label = label + self.info_label = info_label + self.disabled = False + self.update_status() - # Disks - for dev in self.devs: - dev.update_progress() + def update_status(self, new_status=None): + """Update status strings.""" + if self.disabled: + return + if new_status: + self.status = build_status_string( + self.label, new_status, self.info_label) + elif not self.status: + self.status = build_status_string( + self.label, 'Pending', self.info_label) + elif self.started and 'Pending' in self.status: + self.status = build_status_string( + self.label, 'Working', self.info_label) # Functions def build_outer_panes(state): @@ -543,7 +577,7 @@ def run_hw_tests(state): update_progress_pane(state) build_outer_panes(state) - # Run test(s) + # Show selected tests and create TestObj()s print_info('Selected Tests:') for k, v in sorted( state.tests.items(), @@ -554,21 +588,36 @@ def run_hw_tests(state): 'Enabled' if v['Enabled'] else 'Disabled', COLORS['CLEAR'], QUICK_LABEL if state.quick_mode and 'NVMe' in k else '')) + if v['Enabled']: + # Create TestObj and track under both CpuObj/DiskObj and State + if k in TESTS_CPU: + test_obj = TestObj(info_label=True) + state.cpu.tests[k] = test_obj + v['Objects'].append(test_obj) + elif k in TESTS_DISK: + for disk in state.disks: + test_obj = TestObj() + disk.tests[k] = test_obj + v['Objects'].append(test_obj) print_standard('') - # Check devices if necessary - if (state.tests['badblocks']['Enabled'] - or state.tests['I/O Benchmark']['Enabled']): - print_info('Selected Disks:') - for dev in state.devs: - check_dev_attributes(dev) - print_standard('') + # Run safety checks + for disk in state.disks: + disk.safety_check() + + # Run tests + for k, v in sorted( + state.tests.items(), + key=lambda kv: kv[1]['Order']): + if v['Enabled']: + # TODO + pass # Run tests if state.tests['Prime95 & Temps']['Enabled']: run_mprime_test(state) if state.tests['NVMe / SMART']['Enabled']: - run_nvme_smart(state) + run_nvme_smart_tests(state) if state.tests['badblocks']['Enabled']: run_badblocks_test(state) if state.tests['I/O Benchmark']['Enabled']: @@ -835,7 +884,6 @@ def update_io_progress(percent, rate, progress_file): def update_progress_pane(state): """Update progress file for side pane.""" output = [] - state.update_progress() # Prime95 output.append(state.tests['Prime95 & Temps']['Status']) From 49471663f50ac3fe239a0417063b8ee814422976 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 8 Dec 2018 17:50:11 -0700 Subject: [PATCH 062/265] Use OrderedDicts to avoid lambda sorting --- .bin/Scripts/functions/hw_diags.py | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 861305df..05c7ebb7 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -4,6 +4,7 @@ import json import re import time +from collections import OrderedDict from functions.sensors import * from functions.tmux import * @@ -109,7 +110,7 @@ class DiskObj(): self.path = disk_path self.smart_attributes = {} self.smartctl = {} - self.tests = {} + self.tests = OrderedDict() self.get_details() self.get_smart_details() @@ -188,32 +189,28 @@ class State(): self.panes = {} self.progress_out = '{}/progress.out'.format(global_vars['LogDir']) self.quick_mode = False - self.tests = { + self.tests = OrderedDict({ 'Prime95 & Temps': { 'Enabled': False, 'Function': run_mprime_test, 'Objects': [], - 'Order': 1, }, 'NVMe / SMART': { 'Enabled': False, 'Function': run_nvme_smart_tests, 'Objects': [], - 'Order': 2, }, 'badblocks': { 'Enabled': False, 'Function': run_badblocks_test, 'Objects': [], - 'Order': 3, }, 'I/O Benchmark': { 'Enabled': False, 'Function': run_io_benchmark, 'Objects': [], - 'Order': 4, }, - } + }) def init(self): """Set log and add devices.""" @@ -579,9 +576,7 @@ def run_hw_tests(state): # Show selected tests and create TestObj()s print_info('Selected Tests:') - for k, v in sorted( - state.tests.items(), - key=lambda kv: kv[1]['Order']): + for k, v in state.tests.items(): print_standard(' {:<15} {}{}{} {}'.format( k, COLORS['GREEN'] if v['Enabled'] else COLORS['RED'], @@ -606,9 +601,7 @@ def run_hw_tests(state): disk.safety_check() # Run tests - for k, v in sorted( - state.tests.items(), - key=lambda kv: kv[1]['Order']): + for k, v in state.tests.items(): if v['Enabled']: # TODO pass @@ -890,9 +883,7 @@ def update_progress_pane(state): output.append(' ') # Disks - for k, v in sorted( - state.tests.items(), - key=lambda kv: kv[1]['Order']): + for k, v in state.tests.items(): if 'Prime95' not in k and v['Enabled']: output.append('{BLUE}{test_name}{CLEAR}'.format( test_name=k, **COLORS)) From 941a5537669a0c19f9c37f5f139211e1154b5c91 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 8 Dec 2018 18:16:31 -0700 Subject: [PATCH 063/265] Renamed "Prime95 & Temps" to "Prime95" for brevity --- .bin/Scripts/functions/hw_diags.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 05c7ebb7..fd8b0ebb 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -65,7 +65,7 @@ KEY_NVME = 'nvme_smart_health_information_log' KEY_SMART = 'ata_smart_attributes' QUICK_LABEL = '{YELLOW}(Quick){CLEAR}'.format(**COLORS) SIDE_PANE_WIDTH = 20 -TESTS_CPU = ['Prime95 & Temps'] +TESTS_CPU = ['Prime95'] TESTS_DISK = [ 'I/O Benchmark', 'NVMe / SMART', @@ -190,7 +190,7 @@ class State(): self.progress_out = '{}/progress.out'.format(global_vars['LogDir']) self.quick_mode = False self.tests = OrderedDict({ - 'Prime95 & Temps': { + 'Prime95': { 'Enabled': False, 'Function': run_mprime_test, 'Objects': [], @@ -216,7 +216,7 @@ class State(): """Set log and add devices.""" self.disks = [] for k in ['Result', 'Started', 'Status']: - self.tests['Prime95 & Temps'][k] = False if k == 'Started' else '' + self.tests['Prime95'][k] = False if k == 'Started' else '' # Update LogDir if not self.quick_mode: @@ -443,7 +443,7 @@ def menu_diags(state, args): {'Base Name': 'Full Diagnostic', 'Enabled': False}, {'Base Name': 'Disk Diagnostic', 'Enabled': False}, {'Base Name': 'Disk Diagnostic (Quick)', 'Enabled': False}, - {'Base Name': 'Prime95 & Temps', 'Enabled': False, 'CRLF': True}, + {'Base Name': 'Prime95', 'Enabled': False, 'CRLF': True}, {'Base Name': 'NVMe / SMART', 'Enabled': False}, {'Base Name': 'badblocks', 'Enabled': False}, {'Base Name': 'I/O Benchmark', 'Enabled': False}, @@ -642,13 +642,13 @@ def run_keyboard_test(): def run_mprime_test(state): """Test CPU with Prime95 and track temps.""" - state.tests['Prime95 & Temps']['Started'] = True + state.tests['Prime95']['Started'] = True update_progress_pane(state) - _sensor_data = state.tests['Prime95 & Temps']['Sensor Data'] + _sensor_data = state.tests['Prime95']['Sensor Data'] # Update top pane _title = '{}\n{}{}{}'.format( - TOP_PANE_TEXT, 'Prime95 & Temps', + TOP_PANE_TEXT, 'Prime95', ': ' if 'Model name' in state.lscpu else '', state.lscpu.get('Model name', '')) tmux_update_pane(state.panes['Top'], text=_title) @@ -706,7 +706,7 @@ def run_mprime_test(state): sleep(1) except KeyboardInterrupt: # Catch CTRL+C - state.tests['Prime95 & Temps']['Result'] = 'Aborted' + state.tests['Prime95']['Result'] = 'Aborted' print_warning('\nAborted.') update_progress_pane(state) @@ -743,7 +743,7 @@ def run_mprime_test(state): # TODO # Done - state.tests['Prime95 & Temps']['Result'] = 'Unknown' + state.tests['Prime95']['Result'] = 'Unknown' update_progress_pane(state) # Cleanup @@ -879,7 +879,7 @@ def update_progress_pane(state): output = [] # Prime95 - output.append(state.tests['Prime95 & Temps']['Status']) + output.append(state.tests['Prime95']['Status']) output.append(' ') # Disks From 668c7c4c6a440fdcee3fa281d0590d728b634545 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 8 Dec 2018 18:32:03 -0700 Subject: [PATCH 064/265] Updated run_mprime_test to use test_obj --- .bin/Scripts/functions/hw_diags.py | 95 +++++++++++++++--------------- 1 file changed, 49 insertions(+), 46 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index fd8b0ebb..cd64e2e8 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -80,6 +80,7 @@ class CpuObj(): self.lscpu = {} self.tests = {} self.get_details() + self.name = self.lscpu.get('Model name', 'Unknown CPU') def get_details(self): """Get CPU details from lscpu.""" @@ -255,15 +256,16 @@ class State(): class TestObj(): """Object to track test data.""" - def __init__(self, label, info_label=False): - self.started = False - self.passed = False - self.failed = False - self.report = '' - self.status = '' + def __init__(self, dev, label=None, info_label=False): + self.dev = dev self.label = label self.info_label = info_label self.disabled = False + self.failed = False + self.passed = False + self.report = '' + self.started = False + self.status = '' self.update_status() def update_status(self, new_status=None): @@ -552,12 +554,13 @@ def run_audio_test(): run_program(['hw-diags-audio'], check=False, pipe=False) pause('Press Enter to return to main menu... ') -def run_badblocks_test(state): +def run_badblocks_test(state, test_obj): """TODO""" tmux_update_pane( state.panes['Top'], text='{}\n{}'.format( TOP_PANE_TEXT, 'badblocks')) - print_standard('TODO: run_badblocks_test()') + print_standard('TODO: run_badblocks_test({})'.format( + test_obj.dev.path)) for disk in state.disks: disk.tests['badblocks']['Started'] = True update_progress_pane(state) @@ -586,12 +589,13 @@ def run_hw_tests(state): if v['Enabled']: # Create TestObj and track under both CpuObj/DiskObj and State if k in TESTS_CPU: - test_obj = TestObj(info_label=True) + test_obj = TestObj( + dev=state.cpu, label='Prime95', info_label=True) state.cpu.tests[k] = test_obj v['Objects'].append(test_obj) elif k in TESTS_DISK: for disk in state.disks: - test_obj = TestObj() + test_obj = TestObj(dev=k) disk.tests[k] = test_obj v['Objects'].append(test_obj) print_standard('') @@ -601,20 +605,13 @@ def run_hw_tests(state): disk.safety_check() # Run tests + ## Because state.tests is an OrderedDict and the disks were added + ## in order, the tests will be run in order. for k, v in state.tests.items(): if v['Enabled']: - # TODO - pass - - # Run tests - if state.tests['Prime95 & Temps']['Enabled']: - run_mprime_test(state) - if state.tests['NVMe / SMART']['Enabled']: - run_nvme_smart_tests(state) - if state.tests['badblocks']['Enabled']: - run_badblocks_test(state) - if state.tests['I/O Benchmark']['Enabled']: - run_io_benchmark(state) + f = v['Function'] + for test_obj in v['Objects']: + f(state, test_obj) # Done pause('Press Enter to return to main menu... ') @@ -622,12 +619,13 @@ def run_hw_tests(state): # Cleanup tmux_kill_pane(*state.panes.values()) -def run_io_benchmark(state): +def run_io_benchmark(state, test_obj): """TODO""" tmux_update_pane( state.panes['Top'], text='{}\n{}'.format( TOP_PANE_TEXT, 'I/O Benchmark')) - print_standard('TODO: run_io_benchmark()') + print_standard('TODO: run_io_benchmark({})'.format( + test_obj.dev.path)) for disk in state.disks: disk.tests['I/O Benchmark']['Started'] = True update_progress_pane(state) @@ -640,34 +638,32 @@ def run_keyboard_test(): clear_screen() run_program(['xev', '-event', 'keyboard'], check=False, pipe=False) -def run_mprime_test(state): +def run_mprime_test(state, test_obj): """Test CPU with Prime95 and track temps.""" state.tests['Prime95']['Started'] = True update_progress_pane(state) - _sensor_data = state.tests['Prime95']['Sensor Data'] + test_obj.sensor_data = get_sensor_data() # Update top pane - _title = '{}\n{}{}{}'.format( - TOP_PANE_TEXT, 'Prime95', - ': ' if 'Model name' in state.lscpu else '', - state.lscpu.get('Model name', '')) - tmux_update_pane(state.panes['Top'], text=_title) + test_obj.title = '{}\nPrime95: {}'.format( + TOP_PANE_TEXT, test_obj.dev.name) + tmux_update_pane(state.panes['Top'], text=test_obj.title) # Start live sensor monitor - _sensors_out = '{}/sensors.out'.format(global_vars['TmpDir']) - with open(_sensors_out, 'w') as f: + test_obj.sensors_out = '{}/sensors.out'.format(global_vars['TmpDir']) + with open(test_obj.sensors_out, 'w') as f: f.write(' ') f.flush() sleep(0.5) - monitor_proc = popen_program( - ['hw-sensors-monitor', _sensors_out], + test_obj.monitor_proc = popen_program( + ['hw-sensors-monitor', test_obj.sensors_out], pipe=True) # Create monitor and worker panes state.panes['mprime'] = tmux_split_window( lines=10, vertical=True, text=' ') state.panes['Temps'] = tmux_split_window( - behind=True, percent=80, vertical=True, watch=_sensors_out) + behind=True, percent=80, vertical=True, watch=test_obj.sensors_out) tmux_resize_pane(global_vars['Env']['TMUX_PANE'], y=3) # Get idle temps @@ -675,11 +671,11 @@ def run_mprime_test(state): try_and_print( message='Getting idle temps...', indent=0, function=save_average_temp, cs='Done', - sensor_data=_sensor_data, temp_label='Idle') + sensor_data=test_obj.sensor_data, temp_label='Idle') # Stress CPU print_log('Starting Prime95') - _abort_msg = 'If running too hot, press CTRL+c to abort the test' + test_obj.abort_msg = 'If running too hot, press CTRL+c to abort the test' run_program(['apple-fans', 'max']) tmux_update_pane( state.panes['mprime'], @@ -701,8 +697,8 @@ def run_mprime_test(state): 's' if sec_left != 1 else '') # Not using print wrappers to avoid flooding the log print(_status_str) - print('{YELLOW}{msg}{CLEAR}'.format(msg=_abort_msg, **COLORS)) - update_sensor_data(_sensor_data) + print('{YELLOW}{msg}{CLEAR}'.format(msg=test_obj.abort_msg, **COLORS)) + update_sensor_data(test_obj.sensor_data) sleep(1) except KeyboardInterrupt: # Catch CTRL+C @@ -711,8 +707,8 @@ def run_mprime_test(state): update_progress_pane(state) # Restart live monitor - monitor_proc = popen_program( - ['hw-sensors-monitor', _sensors_out], + test_obj.monitor_proc = popen_program( + ['hw-sensors-monitor', test_obj.sensors_out], pipe=True) # Stop Prime95 (twice for good measure) @@ -728,7 +724,7 @@ def run_mprime_test(state): try_and_print( message='Getting cooldown temps...', indent=0, function=save_average_temp, cs='Done', - sensor_data=_sensor_data, temp_label='Cooldown') + sensor_data=test_obj.sensor_data, temp_label='Cooldown') # Move logs to Ticket folder for item in os.scandir(global_vars['TmpDir']): @@ -741,6 +737,12 @@ def run_mprime_test(state): # Check results # TODO + _log = '{}/results.txt'.format(global_vars['LogDir']) + if os.path.exists(_log): + with open(_log, 'r') as f: + for line in f.readlines(): + if re.search(r'(error|fail)', line, re.IGNORECASE): + state.tests['Prime95']['Result'] = 'NS' # Done state.tests['Prime95']['Result'] = 'Unknown' @@ -748,10 +750,11 @@ def run_mprime_test(state): # Cleanup tmux_kill_pane(state.panes['mprime'], state.panes['Temps']) - monitor_proc.kill() + test_obj.monitor_proc.kill() # TODO Testing - print('\n'.join(generate_report(_sensor_data, 'Idle', 'Max', 'Cooldown'))) + print('\n'.join( + generate_report(test_obj.sensor_data, 'Idle', 'Max', 'Cooldown'))) def run_network_test(): """Run network test.""" @@ -759,7 +762,7 @@ def run_network_test(): run_program(['hw-diags-network'], check=False, pipe=False) pause('Press Enter to return to main menu... ') -def run_nvme_smart_tests(state): +def run_nvme_smart_tests(state, test_obj): """TODO""" for disk in state.disks: tmux_update_pane( From d88a9f39f2a0a85ce4e3fe9dde99a39a64c39046 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 8 Dec 2018 18:36:24 -0700 Subject: [PATCH 065/265] Added tmux_kill_all_panes() --- .bin/Scripts/functions/tmux.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.bin/Scripts/functions/tmux.py b/.bin/Scripts/functions/tmux.py index 84ab96cc..e1066e18 100644 --- a/.bin/Scripts/functions/tmux.py +++ b/.bin/Scripts/functions/tmux.py @@ -2,6 +2,13 @@ from functions.common import * +def tmux_kill_all_panes(pane_id=None): + """Kill all tmux panes except the active pane or pane_id if specified.""" + cmd = ['tmux', 'kill-pane', '-a'] + if pane_id: + cmd.extend(['-t', pane_id]) + run_program(cmd, check=False) + def tmux_kill_pane(*panes): """Kill tmux pane by id.""" cmd = ['tmux', 'kill-pane', '-t'] From 465a3b42fb0cc92c03600b820bca0007fd9c3227 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 8 Dec 2018 18:36:50 -0700 Subject: [PATCH 066/265] Kill all tmux panes before exiting --- .bin/Scripts/hw-diags-menu | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/.bin/Scripts/hw-diags-menu b/.bin/Scripts/hw-diags-menu index e60f8fc4..6f0247cd 100755 --- a/.bin/Scripts/hw-diags-menu +++ b/.bin/Scripts/hw-diags-menu @@ -9,20 +9,24 @@ import sys os.chdir(os.path.dirname(os.path.realpath(__file__))) sys.path.append(os.getcwd()) from functions.hw_diags import * +from functions.tmux import * init_global_vars() if __name__ == '__main__': - try: - # Show menu - state = State() - menu_diags(state, sys.argv) - - # Done - #print_standard('\nDone.') - #pause("Press Enter to exit...") - exit_script() - except SystemExit: - pass - except: - major_exception() + try: + # Show menu + state = State() + menu_diags(state, sys.argv) + # Done + #print_standard('\nDone.') + #pause("Press Enter to exit...") + exit_script() + except SystemExit: + tmux_kill_all_panes() + pass + except: + tmux_kill_all_panes() + major_exception() + +# vim: sts=2 sw=2 ts=2 From bb93386fa0b7dc9dec3f21529d9279cbbec62bc8 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 10 Dec 2018 16:32:00 -0700 Subject: [PATCH 067/265] Updated Prime95 checks --- .bin/Scripts/functions/hw_diags.py | 98 +++++++++++++++++++----------- 1 file changed, 64 insertions(+), 34 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index cd64e2e8..8cebd636 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -257,6 +257,7 @@ class State(): class TestObj(): """Object to track test data.""" def __init__(self, dev, label=None, info_label=False): + self.aborted = False self.dev = dev self.label = label self.info_label = info_label @@ -554,13 +555,13 @@ def run_audio_test(): run_program(['hw-diags-audio'], check=False, pipe=False) pause('Press Enter to return to main menu... ') -def run_badblocks_test(state, test_obj): +def run_badblocks_test(state, test): """TODO""" tmux_update_pane( state.panes['Top'], text='{}\n{}'.format( TOP_PANE_TEXT, 'badblocks')) print_standard('TODO: run_badblocks_test({})'.format( - test_obj.dev.path)) + test.dev.path)) for disk in state.disks: disk.tests['badblocks']['Started'] = True update_progress_pane(state) @@ -619,13 +620,13 @@ def run_hw_tests(state): # Cleanup tmux_kill_pane(*state.panes.values()) -def run_io_benchmark(state, test_obj): +def run_io_benchmark(state, test): """TODO""" tmux_update_pane( state.panes['Top'], text='{}\n{}'.format( TOP_PANE_TEXT, 'I/O Benchmark')) print_standard('TODO: run_io_benchmark({})'.format( - test_obj.dev.path)) + test.dev.path)) for disk in state.disks: disk.tests['I/O Benchmark']['Started'] = True update_progress_pane(state) @@ -638,32 +639,33 @@ def run_keyboard_test(): clear_screen() run_program(['xev', '-event', 'keyboard'], check=False, pipe=False) -def run_mprime_test(state, test_obj): +def run_mprime_test(state, test): """Test CPU with Prime95 and track temps.""" - state.tests['Prime95']['Started'] = True + test.started = True + test.update_status() update_progress_pane(state) - test_obj.sensor_data = get_sensor_data() + test.sensor_data = get_sensor_data() # Update top pane - test_obj.title = '{}\nPrime95: {}'.format( - TOP_PANE_TEXT, test_obj.dev.name) - tmux_update_pane(state.panes['Top'], text=test_obj.title) + test.title = '{}\nPrime95: {}'.format( + TOP_PANE_TEXT, test.dev.name) + tmux_update_pane(state.panes['Top'], text=test.title) # Start live sensor monitor - test_obj.sensors_out = '{}/sensors.out'.format(global_vars['TmpDir']) - with open(test_obj.sensors_out, 'w') as f: + test.sensors_out = '{}/sensors.out'.format(global_vars['TmpDir']) + with open(test.sensors_out, 'w') as f: f.write(' ') f.flush() sleep(0.5) - test_obj.monitor_proc = popen_program( - ['hw-sensors-monitor', test_obj.sensors_out], + test.monitor_proc = popen_program( + ['hw-sensors-monitor', test.sensors_out], pipe=True) # Create monitor and worker panes state.panes['mprime'] = tmux_split_window( lines=10, vertical=True, text=' ') state.panes['Temps'] = tmux_split_window( - behind=True, percent=80, vertical=True, watch=test_obj.sensors_out) + behind=True, percent=80, vertical=True, watch=test.sensors_out) tmux_resize_pane(global_vars['Env']['TMUX_PANE'], y=3) # Get idle temps @@ -671,11 +673,11 @@ def run_mprime_test(state, test_obj): try_and_print( message='Getting idle temps...', indent=0, function=save_average_temp, cs='Done', - sensor_data=test_obj.sensor_data, temp_label='Idle') + sensor_data=test.sensor_data, temp_label='Idle') # Stress CPU print_log('Starting Prime95') - test_obj.abort_msg = 'If running too hot, press CTRL+c to abort the test' + test.abort_msg = 'If running too hot, press CTRL+c to abort the test' run_program(['apple-fans', 'max']) tmux_update_pane( state.panes['mprime'], @@ -697,18 +699,19 @@ def run_mprime_test(state, test_obj): 's' if sec_left != 1 else '') # Not using print wrappers to avoid flooding the log print(_status_str) - print('{YELLOW}{msg}{CLEAR}'.format(msg=test_obj.abort_msg, **COLORS)) - update_sensor_data(test_obj.sensor_data) + print('{YELLOW}{msg}{CLEAR}'.format(msg=test.abort_msg, **COLORS)) + update_sensor_data(test.sensor_data) sleep(1) except KeyboardInterrupt: # Catch CTRL+C - state.tests['Prime95']['Result'] = 'Aborted' + test.aborted = True + test.status = 'Aborted' print_warning('\nAborted.') update_progress_pane(state) # Restart live monitor - test_obj.monitor_proc = popen_program( - ['hw-sensors-monitor', test_obj.sensors_out], + test.monitor_proc = popen_program( + ['hw-sensors-monitor', test.sensors_out], pipe=True) # Stop Prime95 (twice for good measure) @@ -724,7 +727,7 @@ def run_mprime_test(state, test_obj): try_and_print( message='Getting cooldown temps...', indent=0, function=save_average_temp, cs='Done', - sensor_data=test_obj.sensor_data, temp_label='Cooldown') + sensor_data=test.sensor_data, temp_label='Cooldown') # Move logs to Ticket folder for item in os.scandir(global_vars['TmpDir']): @@ -736,25 +739,52 @@ def run_mprime_test(state, test_obj): global_vars['LogDir'])) # Check results - # TODO - _log = '{}/results.txt'.format(global_vars['LogDir']) - if os.path.exists(_log): - with open(_log, 'r') as f: - for line in f.readlines(): - if re.search(r'(error|fail)', line, re.IGNORECASE): - state.tests['Prime95']['Result'] = 'NS' + test.logs = {} + for log in ['results.txt', 'prime.log']: + _data = '' + log_path = '{}/{}'.format(global_vars['LogDir'], log) + + # Read and save log + try: + with open(log_path, 'r') as f: + _data = f.read() + test.logs[log] = _data.splitlines() + except FileNotFoundError: + # Ignore since files may be missing for slower CPUs + pass + + # results.txt: NS check + if log == 'results.txt': + if re.search(r'(error|fail)', _data, re.IGNORECASE): + test.failed = True + test.status = 'NS' + + # prime.log: CS check + if log == 'prime.log': + if re.search( + r'completed.*0 errors, 0 warnings', _data, re.IGNORECASE): + test.passed = True + test.status = 'CS' + elif re.search( + r'completed.*\d+ errors, \d+ warnings', _data, re.IGNORECASE): + # If the first re.search does not match and this one does then + # that means that either errors or warnings, or both, are non-zero + test.failed = True + test.passed = False + test.status = 'NS' + if not (test.aborted or test.failed or test.passed): + test.status = 'Unknown' # Done - state.tests['Prime95']['Result'] = 'Unknown' update_progress_pane(state) # Cleanup tmux_kill_pane(state.panes['mprime'], state.panes['Temps']) - test_obj.monitor_proc.kill() + test.monitor_proc.kill() # TODO Testing print('\n'.join( - generate_report(test_obj.sensor_data, 'Idle', 'Max', 'Cooldown'))) + generate_report(test.sensor_data, 'Idle', 'Max', 'Cooldown'))) def run_network_test(): """Run network test.""" @@ -762,7 +792,7 @@ def run_network_test(): run_program(['hw-diags-network'], check=False, pipe=False) pause('Press Enter to return to main menu... ') -def run_nvme_smart_tests(state, test_obj): +def run_nvme_smart_tests(state, test): """TODO""" for disk in state.disks: tmux_update_pane( From a00105f71818bce77842be25ce36173c6cb5d000 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 10 Dec 2018 16:57:43 -0700 Subject: [PATCH 068/265] Fixed status updates --- .bin/Scripts/functions/hw_diags.py | 46 ++++++++++++++++-------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 8cebd636..6d6b1a2c 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -214,10 +214,10 @@ class State(): }) def init(self): - """Set log and add devices.""" + """Remove test objects, set log, and add devices.""" self.disks = [] - for k in ['Result', 'Started', 'Status']: - self.tests['Prime95'][k] = False if k == 'Started' else '' + for k, v in self.tests.items(): + v['Objects'] = [] # Update LogDir if not self.quick_mode: @@ -596,7 +596,7 @@ def run_hw_tests(state): v['Objects'].append(test_obj) elif k in TESTS_DISK: for disk in state.disks: - test_obj = TestObj(dev=k) + test_obj = TestObj(dev=k, label=disk.name) disk.tests[k] = test_obj v['Objects'].append(test_obj) print_standard('') @@ -705,7 +705,7 @@ def run_mprime_test(state, test): except KeyboardInterrupt: # Catch CTRL+C test.aborted = True - test.status = 'Aborted' + test.update_status('Aborted') print_warning('\nAborted.') update_progress_pane(state) @@ -757,23 +757,23 @@ def run_mprime_test(state, test): if log == 'results.txt': if re.search(r'(error|fail)', _data, re.IGNORECASE): test.failed = True - test.status = 'NS' + test.update_status('NS') # prime.log: CS check if log == 'prime.log': if re.search( r'completed.*0 errors, 0 warnings', _data, re.IGNORECASE): test.passed = True - test.status = 'CS' + test.update_status('CS') elif re.search( r'completed.*\d+ errors, \d+ warnings', _data, re.IGNORECASE): # If the first re.search does not match and this one does then # that means that either errors or warnings, or both, are non-zero test.failed = True test.passed = False - test.status = 'NS' + test.update_status('NS') if not (test.aborted or test.failed or test.passed): - test.status = 'Unknown' + test.update_status('Unknown') # Done update_progress_pane(state) @@ -910,19 +910,23 @@ def update_io_progress(percent, rate, progress_file): def update_progress_pane(state): """Update progress file for side pane.""" output = [] - - # Prime95 - output.append(state.tests['Prime95']['Status']) - output.append(' ') - - # Disks for k, v in state.tests.items(): - if 'Prime95' not in k and v['Enabled']: - output.append('{BLUE}{test_name}{CLEAR}'.format( - test_name=k, **COLORS)) - for disk in state.disks: - output.append(disk.tests[k]['Status']) - output.append(' ') + # Skip disabled sections + if not v['Enabled']: + continue + + # Add section name + if k != 'Prime95': + output.append('{BLUE}{name}{CLEAR}'.format(name=k, **COLORS)) + if 'SMART' in k and state.quick_mode: + output.append(' {YELLOW}(Quick Check){CLEAR}'.format(**COLORS)) + + # Add status from test object(s) + for test in v['Objects']: + output.append(test.status) + + # Add spacer before next section + output.append(' ') # Add line-endings output = ['{}\n'.format(line) for line in output] From 8a8a63eb66c412b428ddb0bb9ccd1ae8241dbd49 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 10 Dec 2018 19:16:43 -0700 Subject: [PATCH 069/265] Build Prime95 report --- .bin/Scripts/functions/hw_diags.py | 83 +++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 25 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 6d6b1a2c..181c3a4d 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -264,7 +264,7 @@ class TestObj(): self.disabled = False self.failed = False self.passed = False - self.report = '' + self.report = [] self.started = False self.status = '' self.update_status() @@ -615,6 +615,7 @@ def run_hw_tests(state): f(state, test_obj) # Done + show_results(state) pause('Press Enter to return to main menu... ') # Cleanup @@ -738,42 +739,67 @@ def run_mprime_test(state, test): item.path, global_vars['LogDir'])) - # Check results + # Check results and build report test.logs = {} for log in ['results.txt', 'prime.log']: - _data = '' + lines = [] log_path = '{}/{}'.format(global_vars['LogDir'], log) # Read and save log try: with open(log_path, 'r') as f: - _data = f.read() - test.logs[log] = _data.splitlines() + lines = f.read().splitlines() + test.logs[log] = lines except FileNotFoundError: # Ignore since files may be missing for slower CPUs pass - # results.txt: NS check + # results.txt (NS check) if log == 'results.txt': - if re.search(r'(error|fail)', _data, re.IGNORECASE): - test.failed = True - test.update_status('NS') + _tmp = [] + for line in lines: + if re.search(r'(error|fail)', line, re.IGNORECASE): + test.failed = True + test.update_status('NS') + _tmp.append(' {YELLOW}{line}{CLEAR}'.format(**COLORS)) + if _tmp: + test.report.append('{BLUE}Log: results.txt{CLEAR}'.format(**COLORS)) + test.report.extend(_tmp) - # prime.log: CS check + # prime.log (CS check) if log == 'prime.log': - if re.search( - r'completed.*0 errors, 0 warnings', _data, re.IGNORECASE): - test.passed = True - test.update_status('CS') - elif re.search( - r'completed.*\d+ errors, \d+ warnings', _data, re.IGNORECASE): - # If the first re.search does not match and this one does then - # that means that either errors or warnings, or both, are non-zero - test.failed = True - test.passed = False - test.update_status('NS') + _tmp_pass = [] + _tmp_warn = [] + for line in lines: + if re.search( + r'completed.*0 errors, 0 warnings', line, re.IGNORECASE): + _tmp_pass.append(line) + elif re.search( + r'completed.*\d+ errors, \d+ warnings', line, re.IGNORECASE): + # If the first re.search does not match and this one does then + # that means that either errors or warnings, or both, are non-zero + _tmp_warn.append(line) + if len(_tmp_warn) > 0: + test.failed = True + test.passed = False + test.update_status('NS') + elif len(_tmp_pass) > 0: + test.passed = True + test.update_status('CS') + if len(_tmp_pass) + len(_tmp_warn) > 0: + test.report.append('{BLUE}Log: prime.log{CLEAR}'.format(**COLORS)) + for line in _tmp_pass: + test.report.append(' {}'.format(line)) + for line in _tmp_warn: + test.report.append(' {YELLOW}{line}{CLEAR}'.format(line, **COLORS)) + test.report.append(' ') + + # Finalize report if not (test.aborted or test.failed or test.passed): test.update_status('Unknown') + test.report.append('{BLUE}Temps{CLEAR}'.format(**COLORS)) + for line in generate_report(test.sensor_data, 'Idle', 'Max', 'Cooldown'): + test.report.append(' {}'.format(line)) # Done update_progress_pane(state) @@ -782,10 +808,6 @@ def run_mprime_test(state, test): tmux_kill_pane(state.panes['mprime'], state.panes['Temps']) test.monitor_proc.kill() - # TODO Testing - print('\n'.join( - generate_report(test.sensor_data, 'Idle', 'Max', 'Cooldown'))) - def run_network_test(): """Run network test.""" clear_screen() @@ -840,6 +862,17 @@ def secret_screensaver(screensaver=None): raise Exception('Invalid screensaver') run_program(cmd, check=False, pipe=False) +def show_results(state): + """Show results for all tests.""" + for k, v in state.tests.items(): + print_success('{}:'.format(k)) + for obj in v['Objects']: + for line in obj.report: + print(line) + print_log(strip_colors(line)) + print_standard(' ') + print_standard(' ') + def update_main_options(state, selection, main_options): """Update menu and state based on selection.""" index = int(selection) - 1 From 30d4acd9861672340443ecbbfc5614d434245a01 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 10 Dec 2018 19:18:16 -0700 Subject: [PATCH 070/265] Added watch mode to respawn-pane --- .bin/Scripts/functions/tmux.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.bin/Scripts/functions/tmux.py b/.bin/Scripts/functions/tmux.py index e1066e18..e1892417 100644 --- a/.bin/Scripts/functions/tmux.py +++ b/.bin/Scripts/functions/tmux.py @@ -81,11 +81,14 @@ def tmux_split_window( result = run_program(cmd) return result.stdout.decode().strip() -def tmux_update_pane(pane_id, command=None, text=None, working_dir=None): +def tmux_update_pane( + pane_id, command=None, + text=None, watch=None, + working_dir=None): """Respawn with either a new command or new text.""" # Bail early - if not command and not text: - raise Exception('Neither command nor text specified.') + if not command and not text and not watch: + raise Exception('No command, text, or watch file specified.') cmd = ['tmux', 'respawn-pane', '-k', '-t', pane_id] if working_dir: @@ -94,6 +97,11 @@ def tmux_update_pane(pane_id, command=None, text=None, working_dir=None): cmd.extend(command) elif text: cmd.extend(['echo-and-hold "{}"'.format(text)]) + elif watch: + cmd.extend([ + 'watch', '--color', '--no-title', + '--interval', '1', + 'cat', watch]) run_program(cmd) From 2b43cdf9e27d861406b20e6c35512471450c5ae2 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 10 Dec 2018 19:19:11 -0700 Subject: [PATCH 071/265] Create watch file if it doesn't exist yet --- .bin/Scripts/functions/tmux.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.bin/Scripts/functions/tmux.py b/.bin/Scripts/functions/tmux.py index e1892417..69b906d1 100644 --- a/.bin/Scripts/functions/tmux.py +++ b/.bin/Scripts/functions/tmux.py @@ -2,6 +2,12 @@ from functions.common import * +def create_file(filepath): + """Create file if it doesn't exist.""" + if not os.path.exists(filepath): + with open(filepath, 'w') as f: + f.write('') + def tmux_kill_all_panes(pane_id=None): """Kill all tmux panes except the active pane or pane_id if specified.""" cmd = ['tmux', 'kill-pane', '-a'] @@ -72,6 +78,7 @@ def tmux_split_window( elif text: cmd.extend(['echo-and-hold "{}"'.format(text)]) elif watch: + create_file(watch) cmd.extend([ 'watch', '--color', '--no-title', '--interval', '1', @@ -98,6 +105,7 @@ def tmux_update_pane( elif text: cmd.extend(['echo-and-hold "{}"'.format(text)]) elif watch: + create_file(watch) cmd.extend([ 'watch', '--color', '--no-title', '--interval', '1', From a2ef06e6db0004bb9cb23af0a351cffd33326e2d Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 10 Dec 2018 19:19:35 -0700 Subject: [PATCH 072/265] Added strip_colors() function --- .bin/Scripts/functions/common.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index 2bf52a85..d87f772e 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -515,6 +515,12 @@ def stay_awake(): print_error('ERROR: No caffeine available.') print_warning('Please set the power setting to High Performance.') +def strip_colors(s): + """Remove all ASCII color escapes from string, returns str.""" + for c in COLORS.values(): + s = s.replace(c, '') + return s + def get_exception(s): """Get exception by name, returns Exception object.""" try: From d9554314d55ef845670887e3b019b39de449c343 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 10 Dec 2018 19:42:10 -0700 Subject: [PATCH 073/265] Updated run_program() and popen_program() * Use dicts for clarity * Support cwd flag --- .bin/Scripts/functions/common.py | 36 ++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index d87f772e..7f14bdbd 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -405,19 +405,24 @@ def ping(addr='google.com'): def popen_program(cmd, pipe=False, minimized=False, shell=False, **kwargs): """Run program and return a subprocess.Popen object.""" - startupinfo=None + cmd_kwargs = {'args': cmd, 'shell': shell} + if minimized: startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags = subprocess.STARTF_USESHOWWINDOW startupinfo.wShowWindow = 6 + cmd_kwargs['startupinfo'] = startupinfo if pipe: - popen_obj = subprocess.Popen(cmd, shell=shell, startupinfo=startupinfo, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - else: - popen_obj = subprocess.Popen(cmd, shell=shell, startupinfo=startupinfo) + cmd_kwargs.update({ + 'stdout': subprocess.PIPE, + 'stderr': subprocess.PIPE, + }) - return popen_obj + if 'cwd' in kwargs: + cmd_kwargs['cwd'] = kwargs['cwd'] + + return subprocess.Popen(**cmd_kwargs) def print_error(*args, **kwargs): """Prints message to screen in RED.""" @@ -456,7 +461,7 @@ def print_log(message='', end='\n', timestamp=True): line = line, end = end)) -def run_program(cmd, args=[], check=True, pipe=True, shell=False): +def run_program(cmd, args=[], check=True, pipe=True, shell=False, **kwargs): """Run program and return a subprocess.CompletedProcess object.""" if args: # Deprecated so let's raise an exception to find & fix all occurances @@ -466,13 +471,18 @@ def run_program(cmd, args=[], check=True, pipe=True, shell=False): if shell: cmd = ' '.join(cmd) - if pipe: - process_return = subprocess.run(cmd, check=check, shell=shell, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - else: - process_return = subprocess.run(cmd, check=check, shell=shell) + cmd_kwargs = {'args': cmd, 'check': check, 'shell': shell} - return process_return + if pipe: + cmd_kwargs.update({ + 'stdout': subprocess.PIPE, + 'stderr': subprocess.PIPE, + }) + + if 'cwd' in kwargs: + cmd_kwargs['cwd'] = kwargs['cwd'] + + return subprocess.run(**cmd_kwargs) def set_title(title='~Some Title~'): """Set title. From 6c06a67fdf0dafb0b792fdbf48d0608e08a73651 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 10 Dec 2018 22:54:56 -0700 Subject: [PATCH 074/265] Prime95 section complete --- .bin/Scripts/functions/hw_diags.py | 73 ++++++++++++++++++------------ .bin/Scripts/functions/sensors.py | 10 +++- 2 files changed, 51 insertions(+), 32 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 181c3a4d..9cdde459 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -674,7 +674,9 @@ def run_mprime_test(state, test): try_and_print( message='Getting idle temps...', indent=0, function=save_average_temp, cs='Done', - sensor_data=test.sensor_data, temp_label='Idle') + sensor_data=test.sensor_data, temp_label='Idle', + seconds=3) + # TODO: Remove seconds kwarg above # Stress CPU print_log('Starting Prime95') @@ -684,7 +686,9 @@ def run_mprime_test(state, test): state.panes['mprime'], command=['hw-diags-prime95', global_vars['TmpDir']], working_dir=global_vars['TmpDir']) - time_limit = int(MPRIME_LIMIT) * 60 + #time_limit = int(MPRIME_LIMIT) * 60 + # TODO: restore above line + time_limit = 10 try: for i in range(time_limit): clear_screen() @@ -716,19 +720,23 @@ def run_mprime_test(state, test): pipe=True) # Stop Prime95 (twice for good measure) - tmux_kill_pane(state.panes['mprime']) run_program(['killall', '-s', 'INT', 'mprime'], check=False) + sleep(1) + tmux_kill_pane(state.panes['mprime']) # Get cooldown temp run_program(['apple-fans', 'auto']) clear_screen() try_and_print( message='Letting CPU cooldown for bit...', indent=0, - function=sleep, cs='Done', seconds=10) + function=sleep, cs='Done', seconds=3) + # TODO: Above seconds should be 10 try_and_print( message='Getting cooldown temps...', indent=0, function=save_average_temp, cs='Done', - sensor_data=test.sensor_data, temp_label='Cooldown') + sensor_data=test.sensor_data, temp_label='Cooldown', + seconds=3) + # TODO: Remove seconds kwarg above # Move logs to Ticket folder for item in os.scandir(global_vars['TmpDir']): @@ -761,44 +769,47 @@ def run_mprime_test(state, test): if re.search(r'(error|fail)', line, re.IGNORECASE): test.failed = True test.update_status('NS') - _tmp.append(' {YELLOW}{line}{CLEAR}'.format(**COLORS)) + _tmp.append(' {YELLOW}{line}{CLEAR}'.format(line=line, **COLORS)) if _tmp: test.report.append('{BLUE}Log: results.txt{CLEAR}'.format(**COLORS)) test.report.extend(_tmp) # prime.log (CS check) if log == 'prime.log': - _tmp_pass = [] - _tmp_warn = [] + _tmp = {'Pass': {}, 'Warn': {}} for line in lines: - if re.search( - r'completed.*0 errors, 0 warnings', line, re.IGNORECASE): - _tmp_pass.append(line) - elif re.search( - r'completed.*\d+ errors, \d+ warnings', line, re.IGNORECASE): - # If the first re.search does not match and this one does then - # that means that either errors or warnings, or both, are non-zero - _tmp_warn.append(line) - if len(_tmp_warn) > 0: - test.failed = True - test.passed = False - test.update_status('NS') - elif len(_tmp_pass) > 0: - test.passed = True - test.update_status('CS') - if len(_tmp_pass) + len(_tmp_warn) > 0: + _r = re.search( + r'(completed.*(\d+) errors, (\d+) warnings)', + line, + re.IGNORECASE) + if _r: + if int(_r.group(2)) + int(_r.group(3)) > 0: + # Encountered errors and/or warnings + _tmp['Warn'][_r.group(1)] = None + else: + # No errors + _tmp['Pass'][_r.group(1)] = None + if len(_tmp['Warn']) > 0: + # NS + test.failed = True + test.passed = False + test.update_status('NS') + elif len(_tmp['Pass']) > 0: + test.passed = True + test.update_status('CS') + if len(_tmp['Pass']) + len(_tmp['Warn']) > 0: test.report.append('{BLUE}Log: prime.log{CLEAR}'.format(**COLORS)) - for line in _tmp_pass: + for line in sorted(_tmp['Pass'].keys()): test.report.append(' {}'.format(line)) - for line in _tmp_warn: - test.report.append(' {YELLOW}{line}{CLEAR}'.format(line, **COLORS)) - test.report.append(' ') + for line in sorted(_tmp['Warn'].keys()): + test.report.append(' {YELLOW}{line}{CLEAR}'.format(line=line, **COLORS)) # Finalize report if not (test.aborted or test.failed or test.passed): test.update_status('Unknown') test.report.append('{BLUE}Temps{CLEAR}'.format(**COLORS)) - for line in generate_report(test.sensor_data, 'Idle', 'Max', 'Cooldown'): + for line in generate_report( + test.sensor_data, 'Idle', 'Max', 'Cooldown', core_only=True): test.report.append(' {}'.format(line)) # Done @@ -864,6 +875,7 @@ def secret_screensaver(screensaver=None): def show_results(state): """Show results for all tests.""" + clear_screen() for k, v in state.tests.items(): print_success('{}:'.format(k)) for obj in v['Objects']: @@ -871,7 +883,8 @@ def show_results(state): print(line) print_log(strip_colors(line)) print_standard(' ') - print_standard(' ') + if 'Prime95' not in k: + print_standard(' ') def update_main_options(state, selection, main_options): """Update menu and state based on selection.""" diff --git a/.bin/Scripts/functions/sensors.py b/.bin/Scripts/functions/sensors.py index 066dc446..b6319744 100644 --- a/.bin/Scripts/functions/sensors.py +++ b/.bin/Scripts/functions/sensors.py @@ -29,17 +29,22 @@ def fix_sensor_str(s): s = s.title() s = s.replace('Coretemp', 'CoreTemp') s = s.replace('Acpi', 'ACPI') + s = s.replace('ACPItz', 'ACPI TZ') s = s.replace('Isa ', 'ISA ') s = s.replace('Id ', 'ID ') s = re.sub(r'(\D+)(\d+)', r'\1 \2', s, re.IGNORECASE) s = s.replace(' ', ' ') return s -def generate_report(sensor_data, *temp_labels, colors=True): +def generate_report( + sensor_data, *temp_labels, + colors=True, core_only=False): """Generate report based on temp_labels, returns list if str.""" report = [] for _section, _adapters in sorted(sensor_data.items()): # CoreTemps then Other temps + if core_only and 'Core' not in _section: + continue for _adapter, _sources in sorted(_adapters.items()): # Adapter report.append(fix_sensor_str(_adapter)) @@ -53,7 +58,8 @@ def generate_report(sensor_data, *temp_labels, colors=True): ': ' if _label != 'Current' else '', get_temp_str(_data.get(_label, '???'), colors=colors)) report.append(_line) - report.append(' ') + if not core_only: + report.append(' ') # Handle empty reports (i.e. no sensors detected) if not report: From a3f7e5ad89372c922917662626a5d1421686cba7 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 11 Dec 2018 00:54:16 -0700 Subject: [PATCH 075/265] Disk quick check almost done --- .bin/Scripts/functions/hw_diags.py | 193 +++++++++++++++++++++-------- 1 file changed, 142 insertions(+), 51 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 9cdde459..da4d24e7 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -11,23 +11,23 @@ from functions.tmux import * # STATIC VARIABLES ATTRIBUTES = { 'NVMe': { - 'critical_warning': {'Error': 1}, - 'media_errors': {'Error': 1}, + 'critical_warning': {'Error': 1, 'Critical': True}, + 'media_errors': {'Error': 1, 'Critical': True}, 'power_on_hours': {'Warning': 12000, 'Error': 26298, 'Ignore': True}, 'unsafe_shutdowns': {'Warning': 1}, }, 'SMART': { - 5: {'Hex': '05', 'Error': 1}, - 9: {'Hex': '09', 'Warning': 12000, 'Error': 26298, 'Ignore': True}, - 10: {'Hex': '0A', 'Error': 1}, - 184: {'Hex': 'B8', 'Error': 1}, - 187: {'Hex': 'BB', 'Error': 1}, - 188: {'Hex': 'BC', 'Error': 1}, - 196: {'Hex': 'C4', 'Error': 1}, - 197: {'Hex': 'C5', 'Error': 1}, - 198: {'Hex': 'C6', 'Error': 1}, - 199: {'Hex': 'C7', 'Error': 1, 'Ignore': True}, - 201: {'Hex': 'C9', 'Error': 1}, + '5': {'Hex': '05', 'Error': 1, 'Critical': True}, + '9': {'Hex': '09', 'Warning': 12000, 'Error': 26298, 'Ignore': True}, + '10': {'Hex': '0A', 'Error': 1}, + '184': {'Hex': 'B8', 'Error': 1}, + '187': {'Hex': 'BB', 'Error': 1}, + '188': {'Hex': 'BC', 'Error': 1}, + '196': {'Hex': 'C4', 'Error': 1}, + '197': {'Hex': 'C5', 'Error': 1, 'Critical': True}, + '198': {'Hex': 'C6', 'Error': 1, 'Critical': True}, + '199': {'Hex': 'C7', 'Error': 1, 'Ignore': True}, + '201': {'Hex': 'C9', 'Error': 1}, }, } IO_VARS = { @@ -284,6 +284,82 @@ class TestObj(): self.label, 'Working', self.info_label) # Functions +def attributes_ok_nvme(disk): + """Check NVMe attributes for errors, returns bool.""" + disk_ok = True + override_disabled = False + for k, v in disk.nvme_attributes.items(): + if k in ATTRIBUTES['NVMe']: + if 'Error' not in ATTRIBUTES['NVMe'][k]: + # Only worried about error thresholds + continue + if v['raw'] >= ATTRIBUTES['NVMe'][k]['Error']: + disk_ok = False + + # Disable override if necessary + override_disabled |= ATTRIBUTES['NVMe'][k].get( + 'Critical', False) + + # Print errors + if not disk_ok: + show_disk_attributes(disk) + if override_disabled: + print_error('NVMe error(s) detected.') + print_standard('Tests disabled for this device') + pause() + else: + print_warning('NVMe error(s) detected.') + disk_ok = ask('Run tests on this device anyway?') + + return disk_ok + +def attributes_ok_smart(disk): + """Check SMART attributes for errors, returns bool.""" + disk_ok = True + override_disabled = False + smart_overall_pass = True + for k, v in disk.smart_attributes.items(): + if k in ATTRIBUTES['SMART']: + if 'Error' not in ATTRIBUTES['SMART'][k]: + # Only worried about error thresholds + continue + if v['raw'] >= ATTRIBUTES['SMART'][k]['Error']: + disk_ok = False + + # Disable override if necessary + override_disabled |= ATTRIBUTES['SMART'][k].get( + 'Critical', False) + + # SMART overall assessment + if not disk.smartctl.get('smart_status', {}).get('passed', False): + smart_overall_pass = False + disk_ok = False + override_disabled = True + + # Print errors + if not disk_ok: + show_disk_attributes(disk) + + # 199/C7 warning + if disk.smart_attributes.get('199', {}).get('raw', 0) > 0: + print_warning('199/C7 error detected') + print_standard(' (Have you tried swapping the drive cable?)') + + # Override? + if not smart_overall_pass: + print_error('SMART overall self-assessment: Failed') + print_standard('Tests disabled for this device') + pause() + elif override_disabled: + print_error('SMART error(s) detected.') + print_standard('Tests disabled for this device') + pause() + else: + print_warning('SMART error(s) detected.') + disk_ok = ask('Run tests on this device anyway?') + + return disk_ok + def build_outer_panes(state): """Build top and side panes.""" clear_screen() @@ -310,7 +386,7 @@ def build_status_string(label, status, info_label=False): status_color = COLORS['CLEAR'] if status in ['Denied', 'ERROR', 'NS', 'OVERRIDE']: status_color = COLORS['RED'] - elif status in ['Aborted', 'Unknown', 'Working', 'Skipped']: + elif status in ['Aborted', 'N/A', 'Skipped', 'Unknown', 'Working']: status_color = COLORS['YELLOW'] elif status in ['CS']: status_color = COLORS['GREEN'] @@ -596,7 +672,7 @@ def run_hw_tests(state): v['Objects'].append(test_obj) elif k in TESTS_DISK: for disk in state.disks: - test_obj = TestObj(dev=k, label=disk.name) + test_obj = TestObj(dev=disk, label=disk.name) disk.tests[k] = test_obj v['Objects'].append(test_obj) print_standard('') @@ -616,7 +692,10 @@ def run_hw_tests(state): # Done show_results(state) - pause('Press Enter to return to main menu... ') + if '--quick' in sys.argv: + pause('Press Enter to exit...') + else: + pause('Press Enter to return to main menu... ') # Cleanup tmux_kill_pane(*state.panes.values()) @@ -826,42 +905,32 @@ def run_network_test(): pause('Press Enter to return to main menu... ') def run_nvme_smart_tests(state, test): - """TODO""" - for disk in state.disks: - tmux_update_pane( - state.panes['Top'], - text='{t}\nDisk Health: {size:>6} ({tran}) {model} {serial}'.format( - t=TOP_PANE_TEXT, **disk.lsblk)) - disk.tests['NVMe / SMART']['Started'] = True - update_progress_pane(state) - if disk.nvme_attributes: - run_nvme_tests(state, disk) - elif disk.smart_attributes: - run_smart_tests(state, disk) + """Run NVMe or SMART test for test.dev.""" + tmux_update_pane( + state.panes['Top'], + text='{t}\nDisk Health: {size:>6} ({tran}) {model} {serial}'.format( + t=TOP_PANE_TEXT, **test.dev.lsblk)) + if test.dev.nvme_attributes: + if attributes_ok_nvme(test.dev): + test.passed = True + test.update_status('CS') else: - print_standard('TODO: run_nvme_smart_tests({})'.format( - disk.path)) - print_warning( - " WARNING: Device {} doesn't support NVMe or SMART test".format( - disk.path)) - disk.tests['NVMe / SMART']['Status'] = 'N/A' - disk.tests['NVMe / SMART']['Result'] = 'N/A' - update_progress_pane(state) - sleep(3) - -def run_nvme_tests(state, disk): - """TODO""" - print_standard('TODO: run_nvme_test({})'.format(disk.path)) + test.failed = True + test.update_status('NS') + elif test.dev.smart_attributes: + if attributes_ok_smart(test.dev): + test.passed = True + test.update_status('CS') + else: + test.failed = True + test.update_status('NS') + else: + print_standard('Tests disabled for this device') + test.update_status('N/A') + if not ask('Run tests on this device anyway?'): + test.failed = True + update_progress_pane(state) sleep(3) - disk.tests['NVMe / SMART']['Result'] = 'CS' - update_progress_pane(state) - -def run_smart_tests(state, disk): - """TODO""" - print_standard('TODO: run_smart_tests({})'.format(disk.path)) - sleep(3) - disk.tests['NVMe / SMART']['Result'] = 'CS' - update_progress_pane(state) def secret_screensaver(screensaver=None): """Show screensaver.""" @@ -873,10 +942,32 @@ def secret_screensaver(screensaver=None): raise Exception('Invalid screensaver') run_program(cmd, check=False, pipe=False) +def show_disk_attributes(disk): + """Show NVMe/SMART attributes for disk.""" + print_info('Device: {}'.format(disk.path)) + print_standard(' {size:6} ({tran}) {model} {serial}'.format(**disk.lsblk)) + print_info('Attributes') + if disk.nvme_attributes: + for k, v in disk.nvme_attributes.items(): + if k in ATTRIBUTES['NVMe']: + print('TODO: {} {}'.format(k, v)) + elif disk.smart_attributes: + for k, v in disk.smart_attributes.items(): + if k in ATTRIBUTES['SMART']: + print('TODO: {} {}'.format(k, v)) + else: + print_warning(' No NVMe or SMART data available') + def show_results(state): """Show results for all tests.""" clear_screen() + tmux_update_pane( + state.panes['Top'], text='{}\n{}'.format( + TOP_PANE_TEXT, 'Results')) for k, v in state.tests.items(): + # Skip disabled tests + if not v['Enabled']: + continue print_success('{}:'.format(k)) for obj in v['Objects']: for line in obj.report: @@ -965,7 +1056,7 @@ def update_progress_pane(state): if k != 'Prime95': output.append('{BLUE}{name}{CLEAR}'.format(name=k, **COLORS)) if 'SMART' in k and state.quick_mode: - output.append(' {YELLOW}(Quick Check){CLEAR}'.format(**COLORS)) + output[-1] += ' {YELLOW}(Quick){CLEAR}'.format(**COLORS) # Add status from test object(s) for test in v['Objects']: From a967a5c425122f7d2bf1998f662e035e55b57865 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 11 Dec 2018 20:40:57 -0700 Subject: [PATCH 076/265] Switched back to int keys for SMART attributes * Allows for easier sorting --- .bin/Scripts/functions/hw_diags.py | 44 ++++++++++++++++-------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index da4d24e7..2c2d63fa 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -17,17 +17,19 @@ ATTRIBUTES = { 'unsafe_shutdowns': {'Warning': 1}, }, 'SMART': { - '5': {'Hex': '05', 'Error': 1, 'Critical': True}, - '9': {'Hex': '09', 'Warning': 12000, 'Error': 26298, 'Ignore': True}, - '10': {'Hex': '0A', 'Error': 1}, - '184': {'Hex': 'B8', 'Error': 1}, - '187': {'Hex': 'BB', 'Error': 1}, - '188': {'Hex': 'BC', 'Error': 1}, - '196': {'Hex': 'C4', 'Error': 1}, - '197': {'Hex': 'C5', 'Error': 1, 'Critical': True}, - '198': {'Hex': 'C6', 'Error': 1, 'Critical': True}, - '199': {'Hex': 'C7', 'Error': 1, 'Ignore': True}, - '201': {'Hex': 'C9', 'Error': 1}, + 5: {'Hex': '05', 'Error': 1, 'Critical': True}, + 9: {'Hex': '09', 'Warning': 12000, 'Error': 26298, 'Ignore': True}, + 10: {'Hex': '0A', 'Error': 1}, + 184: {'Hex': 'B8', 'Error': 1}, + 187: {'Hex': 'BB', 'Error': 1}, + 188: {'Hex': 'BC', 'Error': 1}, + 196: {'Hex': 'C4', 'Error': 1}, + 197: {'Hex': 'C5', 'Error': 1, 'Critical': True}, + 198: {'Hex': 'C6', 'Error': 1, 'Critical': True}, + 199: {'Hex': 'C7', 'Error': 1, 'Ignore': True}, + 201: {'Hex': 'C9', 'Error': 1}, + # TODO: Delete below + 177: {'Hex': 'FF', 'Error': 1}, }, } IO_VARS = { @@ -161,19 +163,21 @@ class DiskObj(): self.nvme_attributes.update(self.smartctl[KEY_NVME]) elif KEY_SMART in self.smartctl: for a in self.smartctl[KEY_SMART].get('table', {}): - _id = str(a.get('id', 'UNKNOWN')) + try: + _id = int(a.get('id', -1)) + except ValueError: + # Ignoring invalid attribute + continue _name = str(a.get('name', 'UNKNOWN')) - _raw = a.get('raw', {}).get('value', -1) + _raw = int(a.get('raw', {}).get('value', -1)) _raw_str = a.get('raw', {}).get('string', 'UNKNOWN') # Fix power-on time _r = re.match(r'^(\d+)[Hh].*', _raw_str) - if _id == '9' and _r: - try: - _raw = int(_r.group(1)) - except ValueError: - # That's fine - pass + if _id == 9 and _r: + _raw = int(_r.group(1)) + + # Add to dict self.smart_attributes[_id] = { 'name': _name, 'raw': _raw, 'raw_str': _raw_str} @@ -1056,7 +1060,7 @@ def update_progress_pane(state): if k != 'Prime95': output.append('{BLUE}{name}{CLEAR}'.format(name=k, **COLORS)) if 'SMART' in k and state.quick_mode: - output[-1] += ' {YELLOW}(Quick){CLEAR}'.format(**COLORS) + output[-1] += ' {}'.format(QUICK_LABEL) # Add status from test object(s) for test in v['Objects']: From 62a60ff3fd0ff1e24181ebb60d66b9cbfc38f02e Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 11 Dec 2018 22:56:09 -0700 Subject: [PATCH 077/265] Reworked disk safety checks * Moved several functions into DiskObj * Added HW_OVERRIDES_FORCED and HW_OVERRIDES_LIMITED to main.py * These adjust when overrides are requested * Disable badblocks and/or io_benchmark if disk fails safety check --- .bin/Scripts/functions/hw_diags.py | 220 ++++++++++++++++------------- .bin/Scripts/settings/main.py | 2 + 2 files changed, 122 insertions(+), 100 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 2c2d63fa..63003e8e 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -28,10 +28,9 @@ ATTRIBUTES = { 198: {'Hex': 'C6', 'Error': 1, 'Critical': True}, 199: {'Hex': 'C7', 'Error': 1, 'Ignore': True}, 201: {'Hex': 'C9', 'Error': 1}, - # TODO: Delete below - 177: {'Hex': 'FF', 'Error': 1}, }, } +HW_OVERRIDES_FORCED = HW_OVERRIDES_FORCED and not HW_OVERRIDES_LIMITED IO_VARS = { 'Block Size': 512*1024, 'Chunk Size': 32*1024**2, @@ -106,6 +105,7 @@ class CpuObj(): class DiskObj(): """Object for tracking disk specific data.""" def __init__(self, disk_path): + self.disk_ok = True self.labels = [] self.lsblk = {} self.name = re.sub(r'^.*/(.*)', r'\1', disk_path) @@ -181,10 +181,121 @@ class DiskObj(): self.smart_attributes[_id] = { 'name': _name, 'raw': _raw, 'raw_str': _raw_str} - def safety_check(self): - """Check enabled tests and verify it's safe to run them.""" - # TODO - pass + def nvme_check(self, silent=False): + """Check NVMe attributes for errors.""" + override_disabled = False + for k, v in self.nvme_attributes.items(): + if k in ATTRIBUTES['NVMe']: + if 'Error' not in ATTRIBUTES['NVMe'][k]: + # Only worried about error thresholds + continue + if ATTRIBUTES['NVMe'][k].get('Ignore', False): + # Attribute is non-failing, skip + continue + if v['raw'] >= ATTRIBUTES['NVMe'][k]['Error']: + self.disk_ok = False + + # Disable override if necessary + override_disabled |= ATTRIBUTES['NVMe'][k].get( + 'Critical', False) + + # Print errors + if not self.disk_ok and not silent: + self.show_attributes() + print_warning('NVMe error(s) detected.') + + # Override? + if override_disabled: + print_standard('Tests disabled for this device') + pause() + elif not (len(self.tests) == 3 and HW_OVERRIDES_LIMITED): + self.disk_ok = HW_OVERRIDES_FORCED or ask( + 'Run tests on this device anyway?') + + def safety_check(self, silent=False): + """Check attributes and disable tests if necessary.""" + if self.nvme_attributes: + self.nvme_check(silent) + elif self.smart_attributes: + self.smart_check(silent) + else: + # No NVMe/SMART details + if silent: + self.disk_ok = HW_OVERRIDES_FORCED + else: + print_warning( + ' WARNING: No NVMe or SMART attributes available for: {}'.format( + self.path)) + self.disk_ok = HW_OVERRIDES_FORCED or ask( + 'Run tests on this device anyway?') + + if not self.disk_ok: + for t in ['badblocks', 'I/O Benchmark']: + if t in self.tests: + self.tests[t].disabled = True + self.tests[t].update_status('Denied') + + def show_attributes(self): + """Show NVMe/SMART attributes.""" + print_info('Device: {}'.format(self.path)) + print_standard( + ' {size:>6} ({tran}) {model} {serial}'.format(**self.lsblk)) + print_info('Attributes') + if self.nvme_attributes: + for k, v in self.nvme_attributes.items(): + if k in ATTRIBUTES['NVMe']: + print('TODO: {} {}'.format(k, v)) + elif self.smart_attributes: + for k, v in self.smart_attributes.items(): + # TODO: If k == 199/C7 then append ' (bad cable?)' to line + if k in ATTRIBUTES['SMART']: + print('TODO: {} {}'.format(k, v)) + if not self.smartctl.get('smart_status', {}).get('passed', True): + print_error('SMART overall self-assessment: Failed') + else: + print_warning(' No NVMe or SMART data available') + + def smart_check(self, silent=False): + """Check SMART attributes for errors.""" + override_disabled = False + for k, v in self.smart_attributes.items(): + if k in ATTRIBUTES['SMART']: + if 'Error' not in ATTRIBUTES['SMART'][k]: + # Only worried about error thresholds + continue + if ATTRIBUTES['SMART'][k].get('Ignore', False): + # Attribute is non-failing, skip + continue + if v['raw'] >= ATTRIBUTES['SMART'][k]['Error']: + self.disk_ok = False + + # Disable override if necessary + override_disabled |= ATTRIBUTES['SMART'][k].get( + 'Critical', False) + + # SMART overall assessment + ## NOTE: Only fail drives if the overall value exists and reports failed + if not self.smartctl.get('smart_status', {}).get('passed', True): + self.disk_ok = False + override_disabled = True + + # Print errors + if not silent: + if self.disk_ok: + # 199/C7 warning + if self.smart_attributes.get(199, {}).get('raw', 0) > 0: + print_warning('199/C7 error detected') + print_standard(' (Have you tried swapping the disk cable?)') + else: + # Override? + self.show_attributes() + print_warning('SMART error(s) detected.') + if override_disabled: + print_standard('Tests disabled for this device') + pause() + elif not (len(self.tests) == 3 and HW_OVERRIDES_LIMITED): + self.disk_ok = HW_OVERRIDES_FORCED or ask( + 'Run tests on this device anyway?') class State(): """Object to track device objects and overall state.""" @@ -288,82 +399,6 @@ class TestObj(): self.label, 'Working', self.info_label) # Functions -def attributes_ok_nvme(disk): - """Check NVMe attributes for errors, returns bool.""" - disk_ok = True - override_disabled = False - for k, v in disk.nvme_attributes.items(): - if k in ATTRIBUTES['NVMe']: - if 'Error' not in ATTRIBUTES['NVMe'][k]: - # Only worried about error thresholds - continue - if v['raw'] >= ATTRIBUTES['NVMe'][k]['Error']: - disk_ok = False - - # Disable override if necessary - override_disabled |= ATTRIBUTES['NVMe'][k].get( - 'Critical', False) - - # Print errors - if not disk_ok: - show_disk_attributes(disk) - if override_disabled: - print_error('NVMe error(s) detected.') - print_standard('Tests disabled for this device') - pause() - else: - print_warning('NVMe error(s) detected.') - disk_ok = ask('Run tests on this device anyway?') - - return disk_ok - -def attributes_ok_smart(disk): - """Check SMART attributes for errors, returns bool.""" - disk_ok = True - override_disabled = False - smart_overall_pass = True - for k, v in disk.smart_attributes.items(): - if k in ATTRIBUTES['SMART']: - if 'Error' not in ATTRIBUTES['SMART'][k]: - # Only worried about error thresholds - continue - if v['raw'] >= ATTRIBUTES['SMART'][k]['Error']: - disk_ok = False - - # Disable override if necessary - override_disabled |= ATTRIBUTES['SMART'][k].get( - 'Critical', False) - - # SMART overall assessment - if not disk.smartctl.get('smart_status', {}).get('passed', False): - smart_overall_pass = False - disk_ok = False - override_disabled = True - - # Print errors - if not disk_ok: - show_disk_attributes(disk) - - # 199/C7 warning - if disk.smart_attributes.get('199', {}).get('raw', 0) > 0: - print_warning('199/C7 error detected') - print_standard(' (Have you tried swapping the drive cable?)') - - # Override? - if not smart_overall_pass: - print_error('SMART overall self-assessment: Failed') - print_standard('Tests disabled for this device') - pause() - elif override_disabled: - print_error('SMART error(s) detected.') - print_standard('Tests disabled for this device') - pause() - else: - print_warning('SMART error(s) detected.') - disk_ok = ask('Run tests on this device anyway?') - - return disk_ok - def build_outer_panes(state): """Build top and side panes.""" clear_screen() @@ -915,14 +950,15 @@ def run_nvme_smart_tests(state, test): text='{t}\nDisk Health: {size:>6} ({tran}) {model} {serial}'.format( t=TOP_PANE_TEXT, **test.dev.lsblk)) if test.dev.nvme_attributes: - if attributes_ok_nvme(test.dev): + # NOTE: Pass/Fail is just the attribute check + if test.dev.disk_ok: test.passed = True test.update_status('CS') else: test.failed = True test.update_status('NS') elif test.dev.smart_attributes: - if attributes_ok_smart(test.dev): + if test.dev.disk_ok: test.passed = True test.update_status('CS') else: @@ -946,22 +982,6 @@ def secret_screensaver(screensaver=None): raise Exception('Invalid screensaver') run_program(cmd, check=False, pipe=False) -def show_disk_attributes(disk): - """Show NVMe/SMART attributes for disk.""" - print_info('Device: {}'.format(disk.path)) - print_standard(' {size:6} ({tran}) {model} {serial}'.format(**disk.lsblk)) - print_info('Attributes') - if disk.nvme_attributes: - for k, v in disk.nvme_attributes.items(): - if k in ATTRIBUTES['NVMe']: - print('TODO: {} {}'.format(k, v)) - elif disk.smart_attributes: - for k, v in disk.smart_attributes.items(): - if k in ATTRIBUTES['SMART']: - print('TODO: {} {}'.format(k, v)) - else: - print_warning(' No NVMe or SMART data available') - def show_results(state): """Show results for all tests.""" clear_screen() diff --git a/.bin/Scripts/settings/main.py b/.bin/Scripts/settings/main.py index 75fef0fd..7b915bdb 100644 --- a/.bin/Scripts/settings/main.py +++ b/.bin/Scripts/settings/main.py @@ -4,6 +4,8 @@ ENABLED_OPEN_LOGS = False ENABLED_TICKET_NUMBERS = False ENABLED_UPLOAD_DATA = False +HW_OVERRIDES_FORCED = False +HW_OVERRIDES_LIMITED = True # If True this disables HW_OVERRIDE_FORCED # STATIC VARIABLES (also used by BASH and BATCH files) ## NOTE: There are no spaces around the = for easier parsing in BASH and BATCH From 47084efe1725aae5cdd302735d3f84097097d28d Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 11 Dec 2018 23:18:51 -0700 Subject: [PATCH 078/265] Combined nvme_check() and smart_check() --- .bin/Scripts/functions/hw_diags.py | 129 ++++++++++++----------------- 1 file changed, 51 insertions(+), 78 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 63003e8e..dd2bfa4f 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -117,6 +117,54 @@ class DiskObj(): self.get_details() self.get_smart_details() + def check_attributes(self, silent=False): + """Check NVMe / SMART attributes for errors.""" + override_disabled = False + if self.nvme_attributes: + attr_type = 'NVMe' + items = self.nvme_attributes.items() + elif self.smart_attributes: + attr_type = 'SMART' + items = self.smar_attributes.items() + for k, v in items: + if k in ATTRIBUTES[attr_type]: + if 'Error' not in ATTRIBUTES[attr_type][k]: + # Only worried about error thresholds + continue + if ATTRIBUTES[attr_type][k].get('Ignore', False): + # Attribute is non-failing, skip + continue + if v['raw'] >= ATTRIBUTES[attr_type][k]['Error']: + self.disk_ok = False + + # Disable override if necessary + override_disabled |= ATTRIBUTES[attr_type][k].get( + 'Critical', False) + + # SMART overall assessment + ## NOTE: Only fail drives if the overall value exists and reports failed + if not self.smartctl.get('smart_status', {}).get('passed', True): + self.disk_ok = False + override_disabled = True + + # Print errors + if not silent: + if self.disk_ok: + # 199/C7 warning + if self.smart_attributes.get(199, {}).get('raw', 0) > 0: + print_warning('199/C7 error detected') + print_standard(' (Have you tried swapping the disk cable?)') + else: + # Override? + self.show_attributes() + print_warning('{} error(s) detected.'.format(attr_type)) + if override_disabled: + print_standard('Tests disabled for this device') + pause() + elif not (len(self.tests) == 3 and HW_OVERRIDES_LIMITED): + self.disk_ok = HW_OVERRIDES_FORCED or ask( + 'Run tests on this device anyway?') + def get_details(self): """Get data from lsblk.""" cmd = ['lsblk', '--json', '--output-all', '--paths', self.path] @@ -181,43 +229,10 @@ class DiskObj(): self.smart_attributes[_id] = { 'name': _name, 'raw': _raw, 'raw_str': _raw_str} - def nvme_check(self, silent=False): - """Check NVMe attributes for errors.""" - override_disabled = False - for k, v in self.nvme_attributes.items(): - if k in ATTRIBUTES['NVMe']: - if 'Error' not in ATTRIBUTES['NVMe'][k]: - # Only worried about error thresholds - continue - if ATTRIBUTES['NVMe'][k].get('Ignore', False): - # Attribute is non-failing, skip - continue - if v['raw'] >= ATTRIBUTES['NVMe'][k]['Error']: - self.disk_ok = False - - # Disable override if necessary - override_disabled |= ATTRIBUTES['NVMe'][k].get( - 'Critical', False) - - # Print errors - if not self.disk_ok and not silent: - self.show_attributes() - print_warning('NVMe error(s) detected.') - - # Override? - if override_disabled: - print_standard('Tests disabled for this device') - pause() - elif not (len(self.tests) == 3 and HW_OVERRIDES_LIMITED): - self.disk_ok = HW_OVERRIDES_FORCED or ask( - 'Run tests on this device anyway?') - def safety_check(self, silent=False): - """Check attributes and disable tests if necessary.""" - if self.nvme_attributes: - self.nvme_check(silent) - elif self.smart_attributes: - self.smart_check(silent) + """Run safety checks and disable tests if necessary.""" + if self.nvme_attributes or self.smart_attributes: + self.check_attributes(silent) else: # No NVMe/SMART details if silent: @@ -255,48 +270,6 @@ class DiskObj(): else: print_warning(' No NVMe or SMART data available') - def smart_check(self, silent=False): - """Check SMART attributes for errors.""" - override_disabled = False - for k, v in self.smart_attributes.items(): - if k in ATTRIBUTES['SMART']: - if 'Error' not in ATTRIBUTES['SMART'][k]: - # Only worried about error thresholds - continue - if ATTRIBUTES['SMART'][k].get('Ignore', False): - # Attribute is non-failing, skip - continue - if v['raw'] >= ATTRIBUTES['SMART'][k]['Error']: - self.disk_ok = False - - # Disable override if necessary - override_disabled |= ATTRIBUTES['SMART'][k].get( - 'Critical', False) - - # SMART overall assessment - ## NOTE: Only fail drives if the overall value exists and reports failed - if not self.smartctl.get('smart_status', {}).get('passed', True): - self.disk_ok = False - override_disabled = True - - # Print errors - if not silent: - if self.disk_ok: - # 199/C7 warning - if self.smart_attributes.get(199, {}).get('raw', 0) > 0: - print_warning('199/C7 error detected') - print_standard(' (Have you tried swapping the disk cable?)') - else: - # Override? - self.show_attributes() - print_warning('SMART error(s) detected.') - if override_disabled: - print_standard('Tests disabled for this device') - pause() - elif not (len(self.tests) == 3 and HW_OVERRIDES_LIMITED): - self.disk_ok = HW_OVERRIDES_FORCED or ask( - 'Run tests on this device anyway?') - class State(): """Object to track device objects and overall state.""" def __init__(self): From b5c93317dc33716c813927097da0838a2a8ecc1b Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 11 Dec 2018 23:54:02 -0700 Subject: [PATCH 079/265] Override sections working --- .bin/Scripts/functions/hw_diags.py | 66 +++++++++++++++++++----------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index dd2bfa4f..345cb279 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -125,7 +125,7 @@ class DiskObj(): items = self.nvme_attributes.items() elif self.smart_attributes: attr_type = 'SMART' - items = self.smar_attributes.items() + items = self.smart_attributes.items() for k, v in items: if k in ATTRIBUTES[attr_type]: if 'Error' not in ATTRIBUTES[attr_type][k]: @@ -359,8 +359,6 @@ class TestObj(): def update_status(self, new_status=None): """Update status strings.""" - if self.disabled: - return if new_status: self.status = build_status_string( self.label, new_status, self.info_label) @@ -650,12 +648,12 @@ def run_badblocks_test(state, test): TOP_PANE_TEXT, 'badblocks')) print_standard('TODO: run_badblocks_test({})'.format( test.dev.path)) - for disk in state.disks: - disk.tests['badblocks']['Started'] = True - update_progress_pane(state) - sleep(3) - disk.tests['badblocks']['Result'] = 'OVERRIDE' - update_progress_pane(state) + test.started = True + test.update_status() + update_progress_pane(state) + sleep(3) + test.update_status('Unknown') + update_progress_pane(state) def run_hw_tests(state): """Run enabled hardware tests.""" @@ -691,7 +689,7 @@ def run_hw_tests(state): # Run safety checks for disk in state.disks: - disk.safety_check() + disk.safety_check(silent=state.quick_mode) # Run tests ## Because state.tests is an OrderedDict and the disks were added @@ -704,7 +702,7 @@ def run_hw_tests(state): # Done show_results(state) - if '--quick' in sys.argv: + if state.quick_mode: pause('Press Enter to exit...') else: pause('Press Enter to return to main menu... ') @@ -719,12 +717,12 @@ def run_io_benchmark(state, test): TOP_PANE_TEXT, 'I/O Benchmark')) print_standard('TODO: run_io_benchmark({})'.format( test.dev.path)) - for disk in state.disks: - disk.tests['I/O Benchmark']['Started'] = True - update_progress_pane(state) - sleep(3) - disk.tests['I/O Benchmark']['Result'] = 'Unknown' - update_progress_pane(state) + test.started = True + test.update_status() + update_progress_pane(state) + sleep(3) + test.update_status('Unknown') + update_progress_pane(state) def run_keyboard_test(): """Run keyboard test.""" @@ -928,22 +926,42 @@ def run_nvme_smart_tests(state, test): test.passed = True test.update_status('CS') else: + # NOTE: Other test(s) should've been disabled by DiskObj.safety_check() test.failed = True test.update_status('NS') elif test.dev.smart_attributes: + # NOTE: Pass/Fail based on both attributes and SMART short self-test if test.dev.disk_ok: - test.passed = True - test.update_status('CS') + # Run short test + pause('TODO: Run SMART short self-test') + + # Check result + # TODO + short_test_passed = True + if short_test_passed: + test.passed = True + test.update_status('CS') + else: + for t in ['badblocks', 'I/O Benchmark']: + if t in test.dev.tests: + test.dev.tests[t].disabled = True + test.dev.tests[t].update_status('Denied') + # TODO + if no_logs: + test.update_status('Unknown') + else: + test.failed = True + test.update_status('NS') else: test.failed = True test.update_status('NS') else: - print_standard('Tests disabled for this device') + # NOTE: Pass/Fail not applicable without NVMe/SMART data + # Override request earlier disabled other test(s) as appropriate test.update_status('N/A') - if not ask('Run tests on this device anyway?'): - test.failed = True - update_progress_pane(state) - sleep(3) + + # Done + update_progress_pane(state) def secret_screensaver(screensaver=None): """Show screensaver.""" From 5b748798053a97c200998286d1b67fcd64e70017 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 13 Dec 2018 19:02:28 -0700 Subject: [PATCH 080/265] Fixed OVERRIDE and N/A NVMe/SMART status handling --- .bin/Scripts/functions/hw_diags.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 345cb279..d967ae15 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -162,8 +162,11 @@ class DiskObj(): print_standard('Tests disabled for this device') pause() elif not (len(self.tests) == 3 and HW_OVERRIDES_LIMITED): - self.disk_ok = HW_OVERRIDES_FORCED or ask( - 'Run tests on this device anyway?') + if HW_OVERRIDES_FORCED or ask('Run tests on this device anyway?'): + self.disk_ok = True + if 'NVMe / SMART' in self.tests: + self.tests['NVMe / SMART'].update_status('OVERRIDE') + self.tests['NVMe / SMART'].disabled = True def get_details(self): """Get data from lsblk.""" @@ -235,6 +238,9 @@ class DiskObj(): self.check_attributes(silent) else: # No NVMe/SMART details + if 'NVMe / SMART' in self.tests: + self.tests['NVMe / SMART'].update_status('N/A') + self.tests['NVMe / SMART'].disabled = True if silent: self.disk_ok = HW_OVERRIDES_FORCED else: @@ -247,8 +253,8 @@ class DiskObj(): if not self.disk_ok: for t in ['badblocks', 'I/O Benchmark']: if t in self.tests: - self.tests[t].disabled = True self.tests[t].update_status('Denied') + self.tests[t].disabled = True def show_attributes(self): """Show NVMe/SMART attributes.""" @@ -359,6 +365,8 @@ class TestObj(): def update_status(self, new_status=None): """Update status strings.""" + if self.disabled: + return if new_status: self.status = build_status_string( self.label, new_status, self.info_label) @@ -944,8 +952,8 @@ def run_nvme_smart_tests(state, test): else: for t in ['badblocks', 'I/O Benchmark']: if t in test.dev.tests: - test.dev.tests[t].disabled = True test.dev.tests[t].update_status('Denied') + test.dev.tests[t].disabled = True # TODO if no_logs: test.update_status('Unknown') @@ -955,10 +963,6 @@ def run_nvme_smart_tests(state, test): else: test.failed = True test.update_status('NS') - else: - # NOTE: Pass/Fail not applicable without NVMe/SMART data - # Override request earlier disabled other test(s) as appropriate - test.update_status('N/A') # Done update_progress_pane(state) From 81f05fa79f3217cc37e000f4a9998278907508d4 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 14 Dec 2018 16:37:14 -0700 Subject: [PATCH 081/265] Replaced show_attributes() with generate_report() * Returns list of colored strings * Optionally includes short-test results * Optionally excludes disk info --- .bin/Scripts/functions/hw_diags.py | 157 ++++++++++++++++++++++++----- 1 file changed, 133 insertions(+), 24 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index d967ae15..7c40c741 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -112,6 +112,7 @@ class DiskObj(): self.nvme_attributes = {} self.path = disk_path self.smart_attributes = {} + self.smart_self_test = {} self.smartctl = {} self.tests = OrderedDict() self.get_details() @@ -156,7 +157,9 @@ class DiskObj(): print_standard(' (Have you tried swapping the disk cable?)') else: # Override? - self.show_attributes() + for line in self.generate_report(): + print(line) + print_log(strip_colors(line)) print_warning('{} error(s) detected.'.format(attr_type)) if override_disabled: print_standard('Tests disabled for this device') @@ -168,6 +171,93 @@ class DiskObj(): self.tests['NVMe / SMART'].update_status('OVERRIDE') self.tests['NVMe / SMART'].disabled = True + def generate_report(self, brief=False, short_test=False): + """Generate NVMe / SMART report, returns list.""" + report = [] + if not brief: + report.append('{BLUE}Device: {dev_path}{CLEAR}'.format( + dev_path=self.path, **COLORS)) + report.append(' {size:>6} ({tran}) {model} {serial}'.format( + **self.lsblk)) + + # Warnings + if self.nvme_attributes: + attr_type = 'NVMe' + report.append( + ' {YELLOW}NVMe disk support is still experimental{CLEAR}'.format( + **COLORS)) + elif self.smart_attributes: + attr_type = 'SMART' + else: + # No attribute data available, return short report + report.append( + ' {YELLOW}No NVMe or SMART data available{CLEAR}'.format( + **COLORS)) + return report + if not self.smartctl.get('smart_status', {}).get('passed', True): + report.append( + ' {RED}SMART overall self-assessment: Failed{CLEAR}'.format( + **COLORS)) + + # Attributes + report.append('{BLUE}{a} Attributes{YELLOW}{u:>23} {t}{CLEAR}'.format( + a=attr_type, + u='Updated:' if brief else '', + t=time.strftime('%Y-%m-%d %H:%M %Z') if brief else '', + **COLORS)) + if self.nvme_attributes: + attr_type = 'NVMe' + items = self.nvme_attributes.items() + elif self.smart_attributes: + attr_type = 'SMART' + items = self.smart_attributes.items() + for k, v in items: + if k in ATTRIBUTES[attr_type]: + _note = '' + _color = COLORS['GREEN'] + + # Attribute ID & Name + if attr_type == 'NVMe': + _line = ' {:38}'.format(k.replace('_', ' ').title()) + else: + _line = ' {i:>3} / {h}: {n:28}'.format( + i=k, + h=ATTRIBUTES[attr_type][k]['Hex'], + n=v['name'][:28]) + + # Set color + for _t, _c in [['Warning', 'YELLOW'], ['Error', 'RED']]: + if _t in ATTRIBUTES[attr_type][k]: + if v['raw'] >= ATTRIBUTES[attr_type][k][_t]: + _color = COLORS[_c] + + # 199/C7 warning + if str(k) == '199': + _note = '(bad cable?)' + + # Attribute value + _line += '{}{} {}{}'.format( + _color, + v['raw_str'], + _note, + COLORS['CLEAR']) + + # Add line to report + report.append(_line) + + # SMART short-test + if short_test: + report.append('{BLUE}SMART Short self-test{CLEAR}'.format(**COLORS)) + if 'TimedOut' in self.tests['NVMe / SMART'].status: + report.append(' {YELLOW}UNKNOWN{CLEAR}: Timed out'.format(**COLORS)) + else: + report.append(' {}'.format( + self.smart_self_test['status'].get( + 'string', 'UNKNOWN').capitalize())) + + # Done + return report + def get_details(self): """Get data from lsblk.""" cmd = ['lsblk', '--json', '--output-all', '--paths', self.path] @@ -219,7 +309,7 @@ class DiskObj(): except ValueError: # Ignoring invalid attribute continue - _name = str(a.get('name', 'UNKNOWN')) + _name = str(a.get('name', 'UNKNOWN')).replace('_', ' ').title() _raw = int(a.get('raw', {}).get('value', -1)) _raw_str = a.get('raw', {}).get('string', 'UNKNOWN') @@ -232,6 +322,13 @@ class DiskObj(): self.smart_attributes[_id] = { 'name': _name, 'raw': _raw, 'raw_str': _raw_str} + # Self-test data + for k in ['polling_minutes', 'status']: + self.smart_self_test[k] = self.smartctl.get( + 'ata_smart_data', {}).get( + 'self_test', {}).get( + k, {}) + def safety_check(self, silent=False): """Run safety checks and disable tests if necessary.""" if self.nvme_attributes or self.smart_attributes: @@ -251,31 +348,15 @@ class DiskObj(): 'Run tests on this device anyway?') if not self.disk_ok: + if 'NVMe / SMART' in self.tests: + # NOTE: This will not overwrite the existing status if set + self.tests['NVMe / SMART'].update_status('NS') + self.tests['NVMe / SMART'].disabled = True for t in ['badblocks', 'I/O Benchmark']: if t in self.tests: self.tests[t].update_status('Denied') self.tests[t].disabled = True - def show_attributes(self): - """Show NVMe/SMART attributes.""" - print_info('Device: {}'.format(self.path)) - print_standard( - ' {size:>6} ({tran}) {model} {serial}'.format(**self.lsblk)) - print_info('Attributes') - if self.nvme_attributes: - for k, v in self.nvme_attributes.items(): - if k in ATTRIBUTES['NVMe']: - print('TODO: {} {}'.format(k, v)) - elif self.smart_attributes: - for k, v in self.smart_attributes.items(): - # TODO: If k == 199/C7 then append ' (bad cable?)' to line - if k in ATTRIBUTES['SMART']: - print('TODO: {} {}'.format(k, v)) - if not self.smartctl.get('smart_status', {}).get('passed', True): - print_error('SMART overall self-assessment: Failed') - else: - print_warning(' No NVMe or SMART data available') - class State(): """Object to track device objects and overall state.""" def __init__(self): @@ -402,7 +483,7 @@ def build_outer_panes(state): def build_status_string(label, status, info_label=False): """Build status string with appropriate colors.""" status_color = COLORS['CLEAR'] - if status in ['Denied', 'ERROR', 'NS', 'OVERRIDE']: + if status in ['Denied', 'ERROR', 'NS', 'OVERRIDE', 'TimedOut']: status_color = COLORS['RED'] elif status in ['Aborted', 'N/A', 'Skipped', 'Unknown', 'Working']: status_color = COLORS['YELLOW'] @@ -651,6 +732,9 @@ def run_audio_test(): def run_badblocks_test(state, test): """TODO""" + # Bail early + if test.disabled: + return tmux_update_pane( state.panes['Top'], text='{}\n{}'.format( TOP_PANE_TEXT, 'badblocks')) @@ -699,6 +783,15 @@ def run_hw_tests(state): for disk in state.disks: disk.safety_check(silent=state.quick_mode) + # TODO Remove + clear_screen() + print_info('Running tests:') + for k, v in state.tests.items(): + if v['Enabled']: + print_standard(' {}'.format(k)) + update_progress_pane(state) + pause() + # Run tests ## Because state.tests is an OrderedDict and the disks were added ## in order, the tests will be run in order. @@ -720,6 +813,9 @@ def run_hw_tests(state): def run_io_benchmark(state, test): """TODO""" + # Bail early + if test.disabled: + return tmux_update_pane( state.panes['Top'], text='{}\n{}'.format( TOP_PANE_TEXT, 'I/O Benchmark')) @@ -739,6 +835,9 @@ def run_keyboard_test(): def run_mprime_test(state, test): """Test CPU with Prime95 and track temps.""" + # Bail early + if test.disabled: + return test.started = True test.update_status() update_progress_pane(state) @@ -924,6 +1023,7 @@ def run_network_test(): def run_nvme_smart_tests(state, test): """Run NVMe or SMART test for test.dev.""" + _include_short_test = False tmux_update_pane( state.panes['Top'], text='{t}\nDisk Health: {size:>6} ({tran}) {model} {serial}'.format( @@ -941,10 +1041,14 @@ def run_nvme_smart_tests(state, test): # NOTE: Pass/Fail based on both attributes and SMART short self-test if test.dev.disk_ok: # Run short test - pause('TODO: Run SMART short self-test') + # TODO + _include_short_test = True + _timeout = test.dev.smart_self_test['polling_minutes'].get('short', 5) + _timeout = int(_timeout) + 5 # Check result # TODO + # if 'remaining_percent' in 'status' then we've started. short_test_passed = True if short_test_passed: test.passed = True @@ -960,10 +1064,15 @@ def run_nvme_smart_tests(state, test): else: test.failed = True test.update_status('NS') + else: test.failed = True test.update_status('NS') + # Save report + test.report = test.dev.generate_report( + short_test=_include_short_test) + # Done update_progress_pane(state) From cee825245505376a757a3de5eda45cc7eb1deb95 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 14 Dec 2018 18:03:00 -0700 Subject: [PATCH 082/265] Added CYAN to COLORS --- .bin/Scripts/functions/common.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index 7f14bdbd..5327d895 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -27,10 +27,11 @@ global_vars = {} COLORS = { 'CLEAR': '\033[0m', 'RED': '\033[31m', + 'ORANGE': '\033[31;1m', 'GREEN': '\033[32m', 'YELLOW': '\033[33m', - 'ORANGE': '\033[31;1m', - 'BLUE': '\033[34m' + 'BLUE': '\033[34m', + 'CYAN': '\033[36m', } try: HKU = winreg.HKEY_USERS From 99984603ed601e1af78e688b2258d20ab9a7b7ef Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 14 Dec 2018 18:32:17 -0700 Subject: [PATCH 083/265] NVMe/SMART sections working * Added timout status for clarity * Added short-test result to report --- .bin/Scripts/functions/hw_diags.py | 123 +++++++++++++++++++++++------ 1 file changed, 99 insertions(+), 24 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 7c40c741..141d324e 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -169,7 +169,9 @@ class DiskObj(): self.disk_ok = True if 'NVMe / SMART' in self.tests: self.tests['NVMe / SMART'].update_status('OVERRIDE') - self.tests['NVMe / SMART'].disabled = True + if self.nvme_attributes or not self.smart_attributes: + # i.e. only leave enabled for SMART short-tests + self.tests['NVMe / SMART'].disabled = True def generate_report(self, brief=False, short_test=False): """Generate NVMe / SMART report, returns list.""" @@ -323,6 +325,7 @@ class DiskObj(): 'name': _name, 'raw': _raw, 'raw_str': _raw_str} # Self-test data + self.smart_self_test = {} for k in ['polling_minutes', 'status']: self.smart_self_test[k] = self.smartctl.get( 'ata_smart_data', {}).get( @@ -333,6 +336,22 @@ class DiskObj(): """Run safety checks and disable tests if necessary.""" if self.nvme_attributes or self.smart_attributes: self.check_attributes(silent) + + # Check if a self-test is currently running + if 'remaining_percent' in self.smart_self_test['status']: + _msg='SMART self-test in progress, all tests disabled' + if not silent: + print_warning('WARNING: {}'.format(_msg)) + print_standard(' ') + if ask('Abort HW Diagnostics?'): + exit_script() + if 'NVMe / SMART' in self.tests: + self.tests['NVMe / SMART'].report = self.generate_report() + self.tests['NVMe / SMART'].report.append( + '{YELLOW}WARNING: {msg}{CLEAR}'.format(msg=_msg, **COLORS)) + for t in self.tests.values(): + t.update_status('Denied') + t.disabled = True else: # No NVMe/SMART details if 'NVMe / SMART' in self.tests: @@ -350,6 +369,8 @@ class DiskObj(): if not self.disk_ok: if 'NVMe / SMART' in self.tests: # NOTE: This will not overwrite the existing status if set + if not self.tests['NVMe / SMART'].report: + self.tests['NVMe / SMART'].report = self.generate_report() self.tests['NVMe / SMART'].update_status('NS') self.tests['NVMe / SMART'].disabled = True for t in ['badblocks', 'I/O Benchmark']: @@ -446,7 +467,7 @@ class TestObj(): def update_status(self, new_status=None): """Update status strings.""" - if self.disabled: + if self.disabled or 'OVERRIDE' in self.status: return if new_status: self.status = build_status_string( @@ -1023,11 +1044,19 @@ def run_network_test(): def run_nvme_smart_tests(state, test): """Run NVMe or SMART test for test.dev.""" + # Bail early + if test.disabled: + return _include_short_test = False + test.started = True + test.update_status() tmux_update_pane( state.panes['Top'], text='{t}\nDisk Health: {size:>6} ({tran}) {model} {serial}'.format( t=TOP_PANE_TEXT, **test.dev.lsblk)) + update_progress_pane(state) + + # NVMe if test.dev.nvme_attributes: # NOTE: Pass/Fail is just the attribute check if test.dev.disk_ok: @@ -1037,37 +1066,80 @@ def run_nvme_smart_tests(state, test): # NOTE: Other test(s) should've been disabled by DiskObj.safety_check() test.failed = True test.update_status('NS') + + # SMART elif test.dev.smart_attributes: # NOTE: Pass/Fail based on both attributes and SMART short self-test - if test.dev.disk_ok: - # Run short test - # TODO + if not (test.dev.disk_ok or 'OVERRIDE' in test.status): + test.failed = True + test.update_status('NS') + else: + # Prep + test.timeout = test.dev.smart_self_test['polling_minutes'].get( + 'short', 5) + # TODO: fix timeout, set to polling + 5 + test.timeout = int(test.timeout) + 1 _include_short_test = True - _timeout = test.dev.smart_self_test['polling_minutes'].get('short', 5) - _timeout = int(_timeout) + 5 + _self_test_started = False - # Check result - # TODO - # if 'remaining_percent' in 'status' then we've started. - short_test_passed = True - if short_test_passed: - test.passed = True - test.update_status('CS') + # Create monitor pane + test.smart_out = '{}/smart.out'.format(global_vars['TmpDir']) + with open(test.smart_out, 'w') as f: + f.write('SMART self-test status:\n Pending') + state.panes['smart'] = tmux_split_window( + lines=3, vertical=True, watch=test.smart_out) + + # Show attributes + clear_screen() + for line in test.dev.generate_report(): + # Not saving to log; that will happen after all tests have been run + print(line) + print(' ') + + # Start short test + print_standard('Running self-test...') + cmd = ['sudo', 'smartctl', '--test=short', test.dev.path] + run_program(cmd, check=False) + + # Monitor progress (in 5 second increments) + for iteration in range(int(test.timeout*60/5)): + sleep(5) + + # Update SMART data + test.dev.get_smart_details() + + if _self_test_started: + # Update progress file + with open(test.smart_out, 'w') as f: + f.write('SMART self-test status:\n {}'.format( + test.dev.smart_self_test['status'].get('string', 'UNKNOWN'))) + + # Check if test has finished + if 'remaining_percent' not in test.dev.smart_self_test['status']: + break + + else: + # Check if test has started + if 'remaining_percent' in test.dev.smart_self_test['status']: + _self_test_started = True + + # Check if timed out + if test.dev.smart_self_test['status'].get('passed', False): + if 'OVERRIDE' not in test.status: + test.passed = True + test.update_status('CS') else: + test.failed = True + test.update_status('NS') + if not (test.failed or test.passed): + test.update_status('TimedOut') + + # Disable other drive tests if necessary + if not test.passed: for t in ['badblocks', 'I/O Benchmark']: if t in test.dev.tests: test.dev.tests[t].update_status('Denied') test.dev.tests[t].disabled = True - # TODO - if no_logs: - test.update_status('Unknown') - else: - test.failed = True - test.update_status('NS') - - else: - test.failed = True - test.update_status('NS') # Save report test.report = test.dev.generate_report( @@ -1076,6 +1148,9 @@ def run_nvme_smart_tests(state, test): # Done update_progress_pane(state) + # Cleanup + tmux_kill_pane(state.panes['smart']) + def secret_screensaver(screensaver=None): """Show screensaver.""" if screensaver == 'matrix': From 37b8676b9c436968ab7d68032b8deb3bc164f445 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 14 Dec 2018 18:57:30 -0700 Subject: [PATCH 084/265] Fixed quick check --- .bin/Scripts/functions/hw_diags.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 141d324e..a4bc4f5f 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -1073,6 +1073,13 @@ def run_nvme_smart_tests(state, test): if not (test.dev.disk_ok or 'OVERRIDE' in test.status): test.failed = True test.update_status('NS') + elif state.quick_mode: + if test.dev.disk_ok: + test.passed = True + test.update_status('CS') + else: + test.failed = True + test.update_status('NS') else: # Prep test.timeout = test.dev.smart_self_test['polling_minutes'].get( @@ -1141,6 +1148,9 @@ def run_nvme_smart_tests(state, test): test.dev.tests[t].update_status('Denied') test.dev.tests[t].disabled = True + # Cleanup + tmux_kill_pane(state.panes['smart']) + # Save report test.report = test.dev.generate_report( short_test=_include_short_test) @@ -1148,9 +1158,6 @@ def run_nvme_smart_tests(state, test): # Done update_progress_pane(state) - # Cleanup - tmux_kill_pane(state.panes['smart']) - def secret_screensaver(screensaver=None): """Show screensaver.""" if screensaver == 'matrix': From f2a519b7ec7ed3738ad3370c350e51ade8fd1d54 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 14 Dec 2018 18:58:32 -0700 Subject: [PATCH 085/265] Adjusted log and results screen --- .bin/Scripts/functions/hw_diags.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index a4bc4f5f..8fa6d743 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -157,9 +157,7 @@ class DiskObj(): print_standard(' (Have you tried swapping the disk cable?)') else: # Override? - for line in self.generate_report(): - print(line) - print_log(strip_colors(line)) + show_report(self.generate_report()) print_warning('{} error(s) detected.'.format(attr_type)) if override_disabled: print_standard('Tests disabled for this device') @@ -756,6 +754,7 @@ def run_badblocks_test(state, test): # Bail early if test.disabled: return + print_log('Starting badblocks test for {}'.format(test.dev.path)) tmux_update_pane( state.panes['Top'], text='{}\n{}'.format( TOP_PANE_TEXT, 'badblocks')) @@ -837,6 +836,7 @@ def run_io_benchmark(state, test): # Bail early if test.disabled: return + print_log('Starting I/O benchmark test for {}'.format(test.dev.path)) tmux_update_pane( state.panes['Top'], text='{}\n{}'.format( TOP_PANE_TEXT, 'I/O Benchmark')) @@ -859,6 +859,7 @@ def run_mprime_test(state, test): # Bail early if test.disabled: return + print_log('Starting Prime95 test') test.started = True test.update_status() update_progress_pane(state) @@ -1047,6 +1048,7 @@ def run_nvme_smart_tests(state, test): # Bail early if test.disabled: return + print_log('Starting NVMe/SMART test for {}'.format(test.dev.path)) _include_short_test = False test.started = True test.update_status() @@ -1168,6 +1170,12 @@ def secret_screensaver(screensaver=None): raise Exception('Invalid screensaver') run_program(cmd, check=False, pipe=False) +def show_report(report): + """Show report on screen and save to log w/out color.""" + for line in report: + print(line) + print_log(strip_colors(line)) + def show_results(state): """Show results for all tests.""" clear_screen() @@ -1180,11 +1188,7 @@ def show_results(state): continue print_success('{}:'.format(k)) for obj in v['Objects']: - for line in obj.report: - print(line) - print_log(strip_colors(line)) - print_standard(' ') - if 'Prime95' not in k: + show_report(obj.report) print_standard(' ') def update_main_options(state, selection, main_options): From a5d92537f54c8af6d96db97036b721289c317290 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 15 Dec 2018 16:54:48 -0700 Subject: [PATCH 086/265] Removed unused function --- .bin/Scripts/functions/hw_diags.py | 32 ------------------------------ 1 file changed, 32 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 8fa6d743..8409b4c8 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -517,38 +517,6 @@ def build_status_string(label, status, info_label=False): s_w=SIDE_PANE_WIDTH-len(label), **COLORS) -def check_disk_attributes(disk): - """Check if disk should be tested and allow overrides.""" - needs_override = False - print_standard(' {size:>6} ({tran}) {model} {serial}'.format( - **disk.lsblk)) - - # General checks - if not disk.nvme_attributes and not disk.smart_attributes: - needs_override = True - print_warning( - ' WARNING: No NVMe or SMART attributes available for: {}'.format( - disk.path)) - - # NVMe checks - # TODO check all tracked attributes and set disk.failing if needed - - # SMART checks - # TODO check all tracked attributes and set disk.failing if needed - - # Ask for override if necessary - if needs_override: - if ask(' Run tests on this device anyway?'): - # TODO Set override for this disk - pass - else: - for v in disk.tests.values(): - # Started is set to True to fix the status string - v['Result'] = 'Skipped' - v['Started'] = True - v['Status'] = 'Skipped' - print_standard('') - def generate_horizontal_graph(rates, oneline=False): """Generate two-line horizontal graph from rates, returns str.""" line_1 = '' From dc8416b5f71fb708a971fe6cde9a9bec9f2dff2a Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 15 Dec 2018 16:55:32 -0700 Subject: [PATCH 087/265] Adjusted formatting --- .bin/Scripts/functions/hw_diags.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 8409b4c8..0b88001b 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -117,6 +117,8 @@ class DiskObj(): self.tests = OrderedDict() self.get_details() self.get_smart_details() + self.description = '{size:>6} ({tran}) {model} {serial}'.format( + **self.lsblk) def check_attributes(self, silent=False): """Check NVMe / SMART attributes for errors.""" @@ -177,8 +179,7 @@ class DiskObj(): if not brief: report.append('{BLUE}Device: {dev_path}{CLEAR}'.format( dev_path=self.path, **COLORS)) - report.append(' {size:>6} ({tran}) {model} {serial}'.format( - **self.lsblk)) + report.append(' {}'.format(self.description)) # Warnings if self.nvme_attributes: @@ -718,14 +719,14 @@ def run_audio_test(): pause('Press Enter to return to main menu... ') def run_badblocks_test(state, test): - """TODO""" + """Run a read-only surface scan with badblocks.""" # Bail early if test.disabled: return print_log('Starting badblocks test for {}'.format(test.dev.path)) tmux_update_pane( - state.panes['Top'], text='{}\n{}'.format( - TOP_PANE_TEXT, 'badblocks')) + state.panes['Top'], + text='{}\nbadblocks: {}'.format(TOP_PANE_TEXT, test.dev.description)) print_standard('TODO: run_badblocks_test({})'.format( test.dev.path)) test.started = True @@ -1022,8 +1023,7 @@ def run_nvme_smart_tests(state, test): test.update_status() tmux_update_pane( state.panes['Top'], - text='{t}\nDisk Health: {size:>6} ({tran}) {model} {serial}'.format( - t=TOP_PANE_TEXT, **test.dev.lsblk)) + text='{}\nDisk Health: {}'.format(TOP_PANE_TEXT, test.dev.description)) update_progress_pane(state) # NVMe @@ -1062,7 +1062,7 @@ def run_nvme_smart_tests(state, test): # Create monitor pane test.smart_out = '{}/smart.out'.format(global_vars['TmpDir']) with open(test.smart_out, 'w') as f: - f.write('SMART self-test status:\n Pending') + f.write('SMART self-test status:\n Starting...') state.panes['smart'] = tmux_split_window( lines=3, vertical=True, watch=test.smart_out) @@ -1089,7 +1089,8 @@ def run_nvme_smart_tests(state, test): # Update progress file with open(test.smart_out, 'w') as f: f.write('SMART self-test status:\n {}'.format( - test.dev.smart_self_test['status'].get('string', 'UNKNOWN'))) + test.dev.smart_self_test['status'].get( + 'string', 'UNKNOWN').capitalize())) # Check if test has finished if 'remaining_percent' not in test.dev.smart_self_test['status']: From e96ac5c156c1eca05e14dda41a95cff0997ae492 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 15 Dec 2018 18:09:54 -0700 Subject: [PATCH 088/265] Added watch option to use tail instead of cat * tail -f acurately prints backspace (^H) characters * badblocks output uses them and wouldn't work with watch/cat --- .bin/Scripts/functions/tmux.py | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/.bin/Scripts/functions/tmux.py b/.bin/Scripts/functions/tmux.py index 69b906d1..5fbca65d 100644 --- a/.bin/Scripts/functions/tmux.py +++ b/.bin/Scripts/functions/tmux.py @@ -46,7 +46,7 @@ def tmux_split_window( behind=False, vertical=False, follow=False, target_pane=None, working_dir=None, command=None, - text=None, watch=None): + text=None, watch=None, watch_cmd='cat'): """Run tmux split-window command and return pane_id as str.""" # Bail early if not lines and not percent: @@ -79,19 +79,21 @@ def tmux_split_window( cmd.extend(['echo-and-hold "{}"'.format(text)]) elif watch: create_file(watch) - cmd.extend([ - 'watch', '--color', '--no-title', - '--interval', '1', - 'cat', watch]) + if watch_cmd == 'cat': + cmd.extend([ + 'watch', '--color', '--no-title', + '--interval', '1', + 'cat', watch]) + elif watch_cmd == 'tail': + cmd.extend(['tail', '-f', watch]) # Run and return pane_id result = run_program(cmd) return result.stdout.decode().strip() def tmux_update_pane( - pane_id, command=None, - text=None, watch=None, - working_dir=None): + pane_id, command=None, working_dir=None, + text=None, watch=None, watch_cmd='cat'): """Respawn with either a new command or new text.""" # Bail early if not command and not text and not watch: @@ -106,10 +108,13 @@ def tmux_update_pane( cmd.extend(['echo-and-hold "{}"'.format(text)]) elif watch: create_file(watch) - cmd.extend([ - 'watch', '--color', '--no-title', - '--interval', '1', - 'cat', watch]) + if watch_cmd == 'cat': + cmd.extend([ + 'watch', '--color', '--no-title', + '--interval', '1', + 'cat', watch]) + elif watch_cmd == 'tail': + cmd.extend(['tail', '-f', watch]) run_program(cmd) From 8b936f54137d0275fbdf398fa5722749aad8903f Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 15 Dec 2018 18:45:43 -0700 Subject: [PATCH 089/265] badblocks section working --- .bin/Scripts/functions/hw_diags.py | 73 +++++++++++++++++++++++++----- 1 file changed, 62 insertions(+), 11 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 0b88001b..54ce8ba5 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -383,7 +383,6 @@ class State(): self.cpu = None self.disks = [] self.panes = {} - self.progress_out = '{}/progress.out'.format(global_vars['LogDir']) self.quick_mode = False self.tests = OrderedDict({ 'Prime95': { @@ -423,6 +422,7 @@ class State(): os.makedirs(global_vars['LogDir'], exist_ok=True) global_vars['LogFile'] = '{}/Hardware Diagnostics.log'.format( global_vars['LogDir']) + self.progress_out = '{}/progress.out'.format(global_vars['LogDir']) # Add CPU self.cpu = CpuObj() @@ -723,19 +723,68 @@ def run_badblocks_test(state, test): # Bail early if test.disabled: return + + # Prep print_log('Starting badblocks test for {}'.format(test.dev.path)) - tmux_update_pane( - state.panes['Top'], - text='{}\nbadblocks: {}'.format(TOP_PANE_TEXT, test.dev.description)) - print_standard('TODO: run_badblocks_test({})'.format( - test.dev.path)) test.started = True test.update_status() update_progress_pane(state) - sleep(3) - test.update_status('Unknown') + + # Update top pane + tmux_update_pane( + state.panes['Top'], + text='{}\nbadblocks: {}'.format(TOP_PANE_TEXT, test.dev.description)) + + # Create monitor pane + test.badblocks_out = '{}/badblocks.out'.format(global_vars['LogDir']) + state.panes['badblocks'] = tmux_split_window( + lines=5, vertical=True, watch=test.badblocks_out, watch_cmd='tail') + + # Show disk details + clear_screen() + show_report(test.dev.generate_report()) + print_standard(' ') + + # Start badblocks + print_standard('Running badblocks test...') + test.badblocks_proc = popen_program( + ['sudo', 'hw-diags-badblocks', test.dev.path, test.badblocks_out], + pipe=True) + test.badblocks_proc.wait() + + # Check result and create report + try: + test.badblocks_out = test.badblocks_proc.stdout.read().decode() + except Exception as err: + test.badblocks_out = 'Error: {}'.format(err) + for line in test.badblocks_out.splitlines(): + line = line.strip() + if not line or re.search(r'^Checking', line, re.IGNORECASE): + # Skip empty and progress lines + continue + if re.search(r'^Pass completed.*0.*0/0/0', line, re.IGNORECASE): + test.report.append(' {}'.format(line)) + test.passed = True + else: + test.report.append(' {YELLOW}{line}{CLEAR}'.format( + line=line, **COLORS)) + test.failed = True + + # Update status + if test.failed: + test.update_status('NS') + elif test.passed: + test.update_status('CS') + else: + test.update_status('Unknown') + + # Done update_progress_pane(state) + # Cleanup + tmux_kill_pane(state.panes['badblocks']) + pause() + def run_hw_tests(state): """Run enabled hardware tests.""" print_standard('Scanning devices...') @@ -828,6 +877,8 @@ def run_mprime_test(state, test): # Bail early if test.disabled: return + + # Prep print_log('Starting Prime95 test') test.started = True test.update_status() @@ -835,9 +886,9 @@ def run_mprime_test(state, test): test.sensor_data = get_sensor_data() # Update top pane - test.title = '{}\nPrime95: {}'.format( - TOP_PANE_TEXT, test.dev.name) - tmux_update_pane(state.panes['Top'], text=test.title) + tmux_update_pane( + state.panes['Top'], + text='{}\nPrime95: {}'.format(TOP_PANE_TEXT, test.dev.name)) # Start live sensor monitor test.sensors_out = '{}/sensors.out'.format(global_vars['TmpDir']) From ef42b596d95199503380828c101eeb2d01554439 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 15 Dec 2018 18:56:41 -0700 Subject: [PATCH 090/265] Catch CTRL+c aborts and show results --- .bin/Scripts/functions/hw_diags.py | 78 ++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 26 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 54ce8ba5..2ed8e686 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -747,10 +747,13 @@ def run_badblocks_test(state, test): # Start badblocks print_standard('Running badblocks test...') - test.badblocks_proc = popen_program( - ['sudo', 'hw-diags-badblocks', test.dev.path, test.badblocks_out], - pipe=True) - test.badblocks_proc.wait() + try: + test.badblocks_proc = popen_program( + ['sudo', 'hw-diags-badblocks', test.dev.path, test.badblocks_out], + pipe=True) + test.badblocks_proc.wait() + except KeyboardInterrupt: + raise GenericAbort('Aborted') # Check result and create report try: @@ -833,11 +836,31 @@ def run_hw_tests(state): # Run tests ## Because state.tests is an OrderedDict and the disks were added ## in order, the tests will be run in order. - for k, v in state.tests.items(): - if v['Enabled']: - f = v['Function'] - for test_obj in v['Objects']: - f(state, test_obj) + try: + for k, v in state.tests.items(): + if v['Enabled']: + f = v['Function'] + for test_obj in v['Objects']: + f(state, test_obj) + except GenericAbort: + # Cleanup + tmux_kill_pane(*state.panes.values()) + + # Rebuild panes + update_progress_pane(state) + build_outer_panes(state) + + # Mark unfinished tests as aborted + for k, v in state.tests.items(): + if v['Enabled']: + for test_obj in v['Objects']: + if re.search(r'(Pending|Working)', test_obj.status): + test_obj.update_status('Aborted') + test_obj.report.append(' {YELLOW}Aborted{CLEAR}'.format( + **COLORS)) + + # Update side pane + update_progress_pane(state) # Done show_results(state) @@ -1130,27 +1153,30 @@ def run_nvme_smart_tests(state, test): run_program(cmd, check=False) # Monitor progress (in 5 second increments) - for iteration in range(int(test.timeout*60/5)): - sleep(5) + try: + for iteration in range(int(test.timeout*60/5)): + sleep(5) - # Update SMART data - test.dev.get_smart_details() + # Update SMART data + test.dev.get_smart_details() - if _self_test_started: - # Update progress file - with open(test.smart_out, 'w') as f: - f.write('SMART self-test status:\n {}'.format( - test.dev.smart_self_test['status'].get( - 'string', 'UNKNOWN').capitalize())) + if _self_test_started: + # Update progress file + with open(test.smart_out, 'w') as f: + f.write('SMART self-test status:\n {}'.format( + test.dev.smart_self_test['status'].get( + 'string', 'UNKNOWN').capitalize())) - # Check if test has finished - if 'remaining_percent' not in test.dev.smart_self_test['status']: - break + # Check if test has finished + if 'remaining_percent' not in test.dev.smart_self_test['status']: + break - else: - # Check if test has started - if 'remaining_percent' in test.dev.smart_self_test['status']: - _self_test_started = True + else: + # Check if test has started + if 'remaining_percent' in test.dev.smart_self_test['status']: + _self_test_started = True + except KeyboardInterrupt: + raise GenericAbort('Aborted') # Check if timed out if test.dev.smart_self_test['status'].get('passed', False): From 8993b483a633884bc6634e38c619701e4518dd3f Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sun, 16 Dec 2018 19:30:46 -0700 Subject: [PATCH 091/265] Fix bad cable note --- .bin/Scripts/functions/hw_diags.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 2ed8e686..f0fd09b4 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -233,15 +233,15 @@ class DiskObj(): _color = COLORS[_c] # 199/C7 warning - if str(k) == '199': + if str(k) == '199' and v['raw'] > 0: _note = '(bad cable?)' # Attribute value - _line += '{}{} {}{}'.format( - _color, - v['raw_str'], - _note, - COLORS['CLEAR']) + _line += '{c}{v} {YELLOW}{n}{CLEAR}'.format( + c=_color, + v=v['raw_str'], + n=_note, + **COLORS) # Add line to report report.append(_line) From a4896a55f619ed7709a7bfa9a490bcac0445fb04 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sun, 16 Dec 2018 19:31:34 -0700 Subject: [PATCH 092/265] Adjust log names --- .bin/Scripts/functions/hw_diags.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index f0fd09b4..f2fa7469 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -736,7 +736,8 @@ def run_badblocks_test(state, test): text='{}\nbadblocks: {}'.format(TOP_PANE_TEXT, test.dev.description)) # Create monitor pane - test.badblocks_out = '{}/badblocks.out'.format(global_vars['LogDir']) + test.badblocks_out = '{}/badblocks_{}.out'.format( + global_vars['LogDir'], test.dev.name) state.panes['badblocks'] = tmux_split_window( lines=5, vertical=True, watch=test.badblocks_out, watch_cmd='tail') @@ -1134,7 +1135,8 @@ def run_nvme_smart_tests(state, test): _self_test_started = False # Create monitor pane - test.smart_out = '{}/smart.out'.format(global_vars['TmpDir']) + test.smart_out = '{}/smart_{}.out'.format( + global_vars['LogDir'], test.dev.name) with open(test.smart_out, 'w') as f: f.write('SMART self-test status:\n Starting...') state.panes['smart'] = tmux_split_window( From 503e6f2b4251fbf7355d413fb3df680441a45abb Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sun, 16 Dec 2018 19:45:25 -0700 Subject: [PATCH 093/265] Fix SMART short-test timeout detection --- .bin/Scripts/functions/hw_diags.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index f2fa7469..361aad2d 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -1181,13 +1181,14 @@ def run_nvme_smart_tests(state, test): raise GenericAbort('Aborted') # Check if timed out - if test.dev.smart_self_test['status'].get('passed', False): - if 'OVERRIDE' not in test.status: - test.passed = True - test.update_status('CS') - else: - test.failed = True - test.update_status('NS') + if 'passed' in test.dev.smart_self_test['status']: + if test.dev.smart_self_test['status']['passed']: + if 'OVERRIDE' not in test.status: + test.passed = True + test.update_status('CS') + else: + test.failed = True + test.update_status('NS') if not (test.failed or test.passed): test.update_status('TimedOut') From 4c0bb1c9b7d954319f249422c1b41f2191fa0658 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sun, 16 Dec 2018 22:06:03 -0700 Subject: [PATCH 094/265] Group results by device instead of test --- .bin/Scripts/functions/hw_diags.py | 139 ++++++++++++++++++----------- 1 file changed, 87 insertions(+), 52 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 361aad2d..4b544303 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -79,7 +79,7 @@ class CpuObj(): """Object for tracking CPU specific data.""" def __init__(self): self.lscpu = {} - self.tests = {} + self.tests = OrderedDict() self.get_details() self.name = self.lscpu.get('Model name', 'Unknown CPU') @@ -102,6 +102,18 @@ class CpuObj(): continue self.lscpu[_field] = _data + def generate_cpu_report(self): + """Generate CPU report with data from all tests.""" + report = [] + report.append('{BLUE}Device{CLEAR}'.format(**COLORS)) + report.append(' {}'.format(self.name)) + + # Tests + for test in self.tests.values(): + report.extend(test.report) + + return report + class DiskObj(): """Object for tracking disk specific data.""" def __init__(self, disk_path): @@ -115,9 +127,10 @@ class DiskObj(): self.smart_self_test = {} self.smartctl = {} self.tests = OrderedDict() + self.warnings = [] self.get_details() self.get_smart_details() - self.description = '{size:>6} ({tran}) {model} {serial}'.format( + self.description = '{size} ({tran}) {model} {serial}'.format( **self.lsblk) def check_attributes(self, silent=False): @@ -159,8 +172,8 @@ class DiskObj(): print_standard(' (Have you tried swapping the disk cable?)') else: # Override? - show_report(self.generate_report()) - print_warning('{} error(s) detected.'.format(attr_type)) + show_report(self.generate_attribute_report(description=True)) + print_warning(' {} error(s) detected.'.format(attr_type)) if override_disabled: print_standard('Tests disabled for this device') pause() @@ -172,13 +185,15 @@ class DiskObj(): if self.nvme_attributes or not self.smart_attributes: # i.e. only leave enabled for SMART short-tests self.tests['NVMe / SMART'].disabled = True + print_standard(' ') - def generate_report(self, brief=False, short_test=False): + def generate_attribute_report( + self, description=False, short_test=False, timestamp=False): """Generate NVMe / SMART report, returns list.""" report = [] - if not brief: - report.append('{BLUE}Device: {dev_path}{CLEAR}'.format( - dev_path=self.path, **COLORS)) + if description: + report.append('{BLUE}Device ({name}){CLEAR}'.format( + name=self.name, **COLORS)) report.append(' {}'.format(self.description)) # Warnings @@ -203,8 +218,8 @@ class DiskObj(): # Attributes report.append('{BLUE}{a} Attributes{YELLOW}{u:>23} {t}{CLEAR}'.format( a=attr_type, - u='Updated:' if brief else '', - t=time.strftime('%Y-%m-%d %H:%M %Z') if brief else '', + u='Updated:' if timestamp else '', + t=time.strftime('%Y-%m-%d %H:%M %Z') if timestamp else '', **COLORS)) if self.nvme_attributes: attr_type = 'NVMe' @@ -259,6 +274,21 @@ class DiskObj(): # Done return report + def generate_disk_report(self): + """Generate disk report with data from all tests.""" + report = [] + report.append('{BLUE}Device ({name}){CLEAR}'.format( + name=self.name, **COLORS)) + report.append(' {}'.format(self.description)) + for w in self.warnings: + report.append(' {YELLOW}{w}{CLEAR}'.format(w=w, **COLORS)) + + # Tests + for test in self.tests.values(): + report.extend(test.report) + + return report + def get_details(self): """Get data from lsblk.""" cmd = ['lsblk', '--json', '--output-all', '--paths', self.path] @@ -338,14 +368,14 @@ class DiskObj(): # Check if a self-test is currently running if 'remaining_percent' in self.smart_self_test['status']: - _msg='SMART self-test in progress, all tests disabled' + _msg = 'SMART self-test in progress, all tests disabled' if not silent: print_warning('WARNING: {}'.format(_msg)) print_standard(' ') if ask('Abort HW Diagnostics?'): exit_script() if 'NVMe / SMART' in self.tests: - self.tests['NVMe / SMART'].report = self.generate_report() + self.tests['NVMe / SMART'].report = self.generate_attribute_report() self.tests['NVMe / SMART'].report.append( '{YELLOW}WARNING: {msg}{CLEAR}'.format(msg=_msg, **COLORS)) for t in self.tests.values(): @@ -359,17 +389,20 @@ class DiskObj(): if silent: self.disk_ok = HW_OVERRIDES_FORCED else: - print_warning( - ' WARNING: No NVMe or SMART attributes available for: {}'.format( - self.path)) + _msg = 'No NVMe or SMART data available' + self.warnings.append(_msg) + print_info('Device ({})'.format(self.name)) + print_standard(' {}'.format(self.description)) + print_warning(' {}'.format(_msg)) self.disk_ok = HW_OVERRIDES_FORCED or ask( 'Run tests on this device anyway?') + print_standard(' ') if not self.disk_ok: if 'NVMe / SMART' in self.tests: # NOTE: This will not overwrite the existing status if set if not self.tests['NVMe / SMART'].report: - self.tests['NVMe / SMART'].report = self.generate_report() + self.tests['NVMe / SMART'].report = self.generate_attribute_report() self.tests['NVMe / SMART'].update_status('NS') self.tests['NVMe / SMART'].disabled = True for t in ['badblocks', 'I/O Benchmark']: @@ -743,7 +776,7 @@ def run_badblocks_test(state, test): # Show disk details clear_screen() - show_report(test.dev.generate_report()) + show_report(test.dev.generate_attribute_report()) print_standard(' ') # Start badblocks @@ -757,6 +790,7 @@ def run_badblocks_test(state, test): raise GenericAbort('Aborted') # Check result and create report + test.report.append('{BLUE}badblocks{CLEAR}'.format(**COLORS)) try: test.badblocks_out = test.badblocks_proc.stdout.read().decode() except Exception as err: @@ -787,7 +821,6 @@ def run_badblocks_test(state, test): # Cleanup tmux_kill_pane(state.panes['badblocks']) - pause() def run_hw_tests(state): """Run enabled hardware tests.""" @@ -825,15 +858,6 @@ def run_hw_tests(state): for disk in state.disks: disk.safety_check(silent=state.quick_mode) - # TODO Remove - clear_screen() - print_info('Running tests:') - for k, v in state.tests.items(): - if v['Enabled']: - print_standard(' {}'.format(k)) - update_progress_pane(state) - pause() - # Run tests ## Because state.tests is an OrderedDict and the disks were added ## in order, the tests will be run in order. @@ -1010,6 +1034,7 @@ def run_mprime_test(state, test): global_vars['LogDir'])) # Check results and build report + test.report.append('{BLUE}Prime95{CLEAR}'.format(**COLORS)) test.logs = {} for log in ['results.txt', 'prime.log']: lines = [] @@ -1026,20 +1051,18 @@ def run_mprime_test(state, test): # results.txt (NS check) if log == 'results.txt': - _tmp = [] for line in lines: + line = line.strip() if re.search(r'(error|fail)', line, re.IGNORECASE): test.failed = True test.update_status('NS') - _tmp.append(' {YELLOW}{line}{CLEAR}'.format(line=line, **COLORS)) - if _tmp: - test.report.append('{BLUE}Log: results.txt{CLEAR}'.format(**COLORS)) - test.report.extend(_tmp) + test.report.append(' {YELLOW}{line}{CLEAR}'.format(line=line, **COLORS)) # prime.log (CS check) if log == 'prime.log': _tmp = {'Pass': {}, 'Warn': {}} for line in lines: + line = line.strip() _r = re.search( r'(completed.*(\d+) errors, (\d+) warnings)', line, @@ -1059,18 +1082,19 @@ def run_mprime_test(state, test): elif len(_tmp['Pass']) > 0: test.passed = True test.update_status('CS') - if len(_tmp['Pass']) + len(_tmp['Warn']) > 0: - test.report.append('{BLUE}Log: prime.log{CLEAR}'.format(**COLORS)) - for line in sorted(_tmp['Pass'].keys()): - test.report.append(' {}'.format(line)) - for line in sorted(_tmp['Warn'].keys()): - test.report.append(' {YELLOW}{line}{CLEAR}'.format(line=line, **COLORS)) + for line in sorted(_tmp['Pass'].keys()): + test.report.append(' {}'.format(line)) + for line in sorted(_tmp['Warn'].keys()): + test.report.append(' {YELLOW}{line}{CLEAR}'.format(line=line, **COLORS)) - # Finalize report + # Unknown result if not (test.aborted or test.failed or test.passed): + test.report.append(' {YELLOW}Unknown result{CLEAR}'.format(**COLORS)) test.update_status('Unknown') + + # Add temps to report test.report.append('{BLUE}Temps{CLEAR}'.format(**COLORS)) - for line in generate_report( + for line in generate_sensor_report( test.sensor_data, 'Idle', 'Max', 'Cooldown', core_only=True): test.report.append(' {}'.format(line)) @@ -1144,10 +1168,10 @@ def run_nvme_smart_tests(state, test): # Show attributes clear_screen() - for line in test.dev.generate_report(): - # Not saving to log; that will happen after all tests have been run - print(line) - print(' ') + print_info('Device ({})'.format(test.dev.name)) + print_standard(' {}'.format(test.dev.description)) + show_report(test.dev.generate_attribute_report()) + print_standard(' ') # Start short test print_standard('Running self-test...') @@ -1203,7 +1227,7 @@ def run_nvme_smart_tests(state, test): tmux_kill_pane(state.panes['smart']) # Save report - test.report = test.dev.generate_report( + test.report = test.dev.generate_attribute_report( short_test=_include_short_test) # Done @@ -1231,13 +1255,24 @@ def show_results(state): tmux_update_pane( state.panes['Top'], text='{}\n{}'.format( TOP_PANE_TEXT, 'Results')) - for k, v in state.tests.items(): - # Skip disabled tests - if not v['Enabled']: - continue - print_success('{}:'.format(k)) - for obj in v['Objects']: - show_report(obj.report) + + # CPU tests + _enabled = False + for k in TESTS_CPU: + _enabled |= state.tests[k]['Enabled'] + if _enabled: + print_success('CPU:'.format(k)) + show_report(state.cpu.generate_cpu_report()) + print_standard(' ') + + # Disk tests + for k in TESTS_DISK: + _enabled |= state.tests[k]['Enabled'] + if _enabled: + print_success('Disk{}:'.format( + '' if len(state.disks) == 1 else 's')) + for disk in state.disks: + show_report(disk.generate_disk_report()) print_standard(' ') def update_main_options(state, selection, main_options): From d8123a71ec5ca887115b76d07d197e54282bcd07 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sun, 16 Dec 2018 22:07:34 -0700 Subject: [PATCH 095/265] Renamed generate_report to generate_sensor_report --- .bin/Scripts/functions/sensors.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.bin/Scripts/functions/sensors.py b/.bin/Scripts/functions/sensors.py index b6319744..99e7999a 100644 --- a/.bin/Scripts/functions/sensors.py +++ b/.bin/Scripts/functions/sensors.py @@ -36,7 +36,7 @@ def fix_sensor_str(s): s = s.replace(' ', ' ') return s -def generate_report( +def generate_sensor_report( sensor_data, *temp_labels, colors=True, core_only=False): """Generate report based on temp_labels, returns list if str.""" @@ -153,7 +153,7 @@ def monitor_sensors(monitor_pane, monitor_file): while True: update_sensor_data(sensor_data) with open(monitor_file, 'w') as f: - report = generate_report(sensor_data, 'Current', 'Max') + report = generate_sensor_report(sensor_data, 'Current', 'Max') f.write('\n'.join(report)) sleep(1) if monitor_pane and not tmux_poll_pane(monitor_pane): From e0a2993c362469acaa08674bc85d28f3ef2920a2 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sun, 16 Dec 2018 22:18:34 -0700 Subject: [PATCH 096/265] Skip disk safety checks if only testing the CPU --- .bin/Scripts/functions/hw_diags.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 4b544303..6fd384a6 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -854,9 +854,13 @@ def run_hw_tests(state): v['Objects'].append(test_obj) print_standard('') - # Run safety checks - for disk in state.disks: - disk.safety_check(silent=state.quick_mode) + # Run disk safety checks (if necessary) + _disk_tests_enabled = False + for k in TESTS_DISK: + _disk_tests_enabled |= state.tests[k]['Enabled'] + if _disk_tests_enabled: + for disk in state.disks: + disk.safety_check(silent=state.quick_mode) # Run tests ## Because state.tests is an OrderedDict and the disks were added @@ -1266,6 +1270,7 @@ def show_results(state): print_standard(' ') # Disk tests + _enabled = False for k in TESTS_DISK: _enabled |= state.tests[k]['Enabled'] if _enabled: From baaf1994e3312df5f39ee4bdd8c3009dacd50b9f Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sun, 16 Dec 2018 22:44:46 -0700 Subject: [PATCH 097/265] Catch keyboard interrupt and gracefully abort --- .bin/Scripts/hw-diags-menu | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/.bin/Scripts/hw-diags-menu b/.bin/Scripts/hw-diags-menu index 6f0247cd..5b6f4f76 100755 --- a/.bin/Scripts/hw-diags-menu +++ b/.bin/Scripts/hw-diags-menu @@ -13,20 +13,25 @@ from functions.tmux import * init_global_vars() if __name__ == '__main__': + # Show menu try: - # Show menu state = State() menu_diags(state, sys.argv) - - # Done - #print_standard('\nDone.') - #pause("Press Enter to exit...") - exit_script() + except KeyboardInterrupt: + print_standard(' ') + print_warning('Aborted') + print_standard(' ') + sleep(1) + pause('Press Enter to exit...') except SystemExit: - tmux_kill_all_panes() + # Normal exit pass except: tmux_kill_all_panes() major_exception() + # Done + tmux_kill_all_panes() + exit_script() + # vim: sts=2 sw=2 ts=2 From c820d2ac6de623a4d6f1ef3400bca890b8f2965a Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 17 Dec 2018 13:20:39 -0700 Subject: [PATCH 098/265] Fixed Prime95 abort handling --- .bin/Scripts/functions/hw_diags.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 6fd384a6..ef411220 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -1083,7 +1083,7 @@ def run_mprime_test(state, test): test.failed = True test.passed = False test.update_status('NS') - elif len(_tmp['Pass']) > 0: + elif len(_tmp['Pass']) > 0 and not test.aborted: test.passed = True test.update_status('CS') for line in sorted(_tmp['Pass'].keys()): From a25a10e616cbeaaec796bc0c0c3cf22f6e9c35f7 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 17 Dec 2018 14:07:19 -0700 Subject: [PATCH 099/265] More abort logic updates --- .bin/Scripts/functions/hw_diags.py | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index ef411220..c9a84940 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -127,7 +127,6 @@ class DiskObj(): self.smart_self_test = {} self.smartctl = {} self.tests = OrderedDict() - self.warnings = [] self.get_details() self.get_smart_details() self.description = '{size} ({tran}) {model} {serial}'.format( @@ -280,8 +279,10 @@ class DiskObj(): report.append('{BLUE}Device ({name}){CLEAR}'.format( name=self.name, **COLORS)) report.append(' {}'.format(self.description)) - for w in self.warnings: - report.append(' {YELLOW}{w}{CLEAR}'.format(w=w, **COLORS)) + + # Attributes + if 'NVMe / SMART' not in self.tests: + report.extend(self.generate_attribute_report()) # Tests for test in self.tests.values(): @@ -389,11 +390,9 @@ class DiskObj(): if silent: self.disk_ok = HW_OVERRIDES_FORCED else: - _msg = 'No NVMe or SMART data available' - self.warnings.append(_msg) print_info('Device ({})'.format(self.name)) print_standard(' {}'.format(self.description)) - print_warning(' {}'.format(_msg)) + print_warning(' No NVMe or SMART data available') self.disk_ok = HW_OVERRIDES_FORCED or ask( 'Run tests on this device anyway?') print_standard(' ') @@ -787,9 +786,9 @@ def run_badblocks_test(state, test): pipe=True) test.badblocks_proc.wait() except KeyboardInterrupt: - raise GenericAbort('Aborted') + test.aborted = True - # Check result and create report + # Check result and build report test.report.append('{BLUE}badblocks{CLEAR}'.format(**COLORS)) try: test.badblocks_out = test.badblocks_proc.stdout.read().decode() @@ -802,11 +801,16 @@ def run_badblocks_test(state, test): continue if re.search(r'^Pass completed.*0.*0/0/0', line, re.IGNORECASE): test.report.append(' {}'.format(line)) - test.passed = True + if not test.aborted: + test.passed = True else: test.report.append(' {YELLOW}{line}{CLEAR}'.format( line=line, **COLORS)) test.failed = True + if test.aborted: + test.report.append(' {YELLOW}Aborted{CLEAR}'.format(**COLORS)) + test.update_status('Aborted') + raise GenericAbort('Aborted') # Update status if test.failed: @@ -885,8 +889,6 @@ def run_hw_tests(state): for test_obj in v['Objects']: if re.search(r'(Pending|Working)', test_obj.status): test_obj.update_status('Aborted') - test_obj.report.append(' {YELLOW}Aborted{CLEAR}'.format( - **COLORS)) # Update side pane update_progress_pane(state) @@ -1206,6 +1208,12 @@ def run_nvme_smart_tests(state, test): if 'remaining_percent' in test.dev.smart_self_test['status']: _self_test_started = True except KeyboardInterrupt: + test.aborted = True + test.report = test.dev.generate_attribute_report() + test.report.append('{BLUE}SMART Short self-test{CLEAR}'.format( + **COLORS)) + test.report.append(' {YELLOW}Aborted{CLEAR}'.format(**COLORS)) + test.update_status('Aborted') raise GenericAbort('Aborted') # Check if timed out From 385bdd7dbf11f3e5f6b99029263ea9f4fc2f7879 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 17 Dec 2018 20:10:58 -0700 Subject: [PATCH 100/265] Allow resizing current pane --- .bin/Scripts/functions/tmux.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.bin/Scripts/functions/tmux.py b/.bin/Scripts/functions/tmux.py index 5fbca65d..20f35921 100644 --- a/.bin/Scripts/functions/tmux.py +++ b/.bin/Scripts/functions/tmux.py @@ -28,12 +28,15 @@ def tmux_poll_pane(pane_id): panes = result.stdout.decode().splitlines() return pane_id in panes -def tmux_resize_pane(pane_id, x=None, y=None): +def tmux_resize_pane(pane_id=None, x=None, y=None): """Resize pane to specific hieght or width.""" if not x and not y: raise Exception('Neither height nor width specified.') - cmd = ['tmux', 'resize-pane', '-t', pane_id] + cmd = ['tmux', 'resize-pane'] + if pane_id: + # NOTE: If pane_id not specified then the current pane will be resized + cmd.extend(['-t', pane_id]) if x: cmd.extend(['-x', str(x)]) elif y: From ec8c78197b45b3a6d812474dc0f3d0d30af55ec6 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 17 Dec 2018 20:15:40 -0700 Subject: [PATCH 101/265] I/O Benchmark test is working --- .bin/Scripts/functions/hw_diags.py | 223 +++++++++++++++++++++++++++-- 1 file changed, 212 insertions(+), 11 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index c9a84940..50eca7b5 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -34,7 +34,6 @@ HW_OVERRIDES_FORCED = HW_OVERRIDES_FORCED and not HW_OVERRIDES_LIMITED IO_VARS = { 'Block Size': 512*1024, 'Chunk Size': 32*1024**2, - 'Minimum Dev Size': 8*1024**3, 'Minimum Test Size': 10*1024**3, 'Alt Test Size Factor': 0.01, 'Progress Refresh Rate': 5, @@ -74,6 +73,10 @@ TESTS_DISK = [ ] TOP_PANE_TEXT = '{GREEN}Hardware Diagnostics{CLEAR}'.format(**COLORS) +# Error Classe +class DeviceTooSmallError(Exception): + pass + # Classes class CpuObj(): """Object for tracking CPU specific data.""" @@ -132,6 +135,60 @@ class DiskObj(): self.description = '{size} ({tran}) {model} {serial}'.format( **self.lsblk) + def calc_io_dd_values(self): + """Calcualte I/O benchmark dd values.""" + # Get real disk size + cmd = ['lsblk', + '--bytes', '--nodeps', '--noheadings', + '--output', 'size', self.path] + result = run_program(cmd) + self.size_bytes = int(result.stdout.decode().strip()) + + # dd calculations + ## The minimum dev size is 'Graph Horizontal Width' * 'Chunk Size' + ## (e.g. 1.25 GB for a width of 40 and a chunk size of 32MB) + ## If the device is smaller than the minimum dd_chunks would be set + ## to zero which would cause a divide by zero error. + ## If the device is below the minimum size an Exception will be raised + ## + ## dd_size is the area to be read in bytes + ## If the dev is < 10Gb then it's the whole dev + ## Otherwise it's the larger of 10Gb or 1% of the dev + ## + ## dd_chunks is the number of groups of "Chunk Size" in self.dd_size + ## This number is reduced to a multiple of the graph width in + ## order to allow for the data to be condensed cleanly + ## + ## dd_chunk_blocks is the chunk size in number of blocks + ## (e.g. 64 if block size is 512KB and chunk size is 32MB + ## + ## dd_skip_blocks is the number of "Block Size" groups not tested + ## dd_skip_count is the number of blocks to skip per self.dd_chunk + ## dd_skip_extra is how often to add an additional skip block + ## This is needed to ensure an even testing across the dev + ## This is calculated by using the fractional amount left off + ## of the dd_skip_count variable + self.dd_size = min(IO_VARS['Minimum Test Size'], self.size_bytes) + self.dd_size = max( + self.dd_size, + self.size_bytes * IO_VARS['Alt Test Size Factor']) + self.dd_chunks = int(self.dd_size // IO_VARS['Chunk Size']) + self.dd_chunks -= self.dd_chunks % IO_VARS['Graph Horizontal Width'] + if self.dd_chunks < IO_VARS['Graph Horizontal Width']: + raise DeviceTooSmallError + self.dd_chunk_blocks = int(IO_VARS['Chunk Size'] / IO_VARS['Block Size']) + self.dd_size = self.dd_chunks * IO_VARS['Chunk Size'] + self.dd_skip_blocks = int( + (self.size_bytes - self.dd_size) // IO_VARS['Block Size']) + self.dd_skip_count = int((self.dd_skip_blocks / self.dd_chunks) // 1) + self.dd_skip_extra = 0 + try: + self.dd_skip_extra = 1 + int( + 1 / ((self.dd_skip_blocks / self.dd_chunks) % 1)) + except ZeroDivisionError: + # self.dd_skip_extra == 0 is fine + pass + def check_attributes(self, silent=False): """Check NVMe / SMART attributes for errors.""" override_disabled = False @@ -498,7 +555,7 @@ class TestObj(): def update_status(self, new_status=None): """Update status strings.""" - if self.disabled or 'OVERRIDE' in self.status: + if self.disabled or re.search(r'ERROR|OVERRIDE', self.status): return if new_status: self.status = build_status_string( @@ -904,23 +961,163 @@ def run_hw_tests(state): tmux_kill_pane(*state.panes.values()) def run_io_benchmark(state, test): - """TODO""" + """Run a read-only I/O benchmark using dd.""" # Bail early if test.disabled: return + + # Prep print_log('Starting I/O benchmark test for {}'.format(test.dev.path)) - tmux_update_pane( - state.panes['Top'], text='{}\n{}'.format( - TOP_PANE_TEXT, 'I/O Benchmark')) - print_standard('TODO: run_io_benchmark({})'.format( - test.dev.path)) test.started = True test.update_status() update_progress_pane(state) - sleep(3) - test.update_status('Unknown') + + # Update top pane + tmux_update_pane( + state.panes['Top'], + text='{}\nI/O Benchmark: {}'.format( + TOP_PANE_TEXT, test.dev.description)) + + # Create monitor pane + test.io_benchmark_out = '{}/io_benchmark_{}.out'.format( + global_vars['LogDir'], test.dev.name) + state.panes['io_benchmark'] = tmux_split_window( + percent=75, vertical=True, + watch=test.io_benchmark_out, watch_cmd='tail') + tmux_resize_pane(y=15) + + # Show disk details + clear_screen() + show_report(test.dev.generate_attribute_report()) + print_standard(' ') + + # Start I/O Benchmark + print_standard('Running I/O benchmark test...') + try: + test.merged_rates = [] + test.read_rates = [] + test.vertical_graph = [] + test.dev.calc_io_dd_values() + + # Run dd read tests + offset = 0 + for i in range(test.dev.dd_chunks): + # Build cmd + i += 1 + skip = test.dev.dd_skip_count + if test.dev.dd_skip_extra and i % test.dev.dd_skip_extra == 0: + skip += 1 + cmd = [ + 'sudo', 'dd', + 'bs={}'.format(IO_VARS['Block Size']), + 'skip={}'.format(offset+skip), + 'count={}'.format(test.dev.dd_chunk_blocks), + 'iflag=direct', + 'if={}'.format(test.dev.path), + 'of=/dev/null'] + + # Run cmd and get read rate + result = run_program(cmd) + result_str = result.stderr.decode().replace('\n', '') + cur_rate = get_read_rate(result_str) + + # Add rate to lists + test.read_rates.append(cur_rate) + test.vertical_graph.append( + '{percent:0.1f} {rate}'.format( + percent=(i/test.dev.dd_chunks)*100, + rate=int(cur_rate/(1024**2)))) + + # Show progress + if i % IO_VARS['Progress Refresh Rate'] == 0: + update_io_progress( + percent=(i/test.dev.dd_chunks)*100, + rate=cur_rate, + progress_file=test.io_benchmark_out) + + # Update offset + offset += test.dev.dd_chunk_blocks + skip + + except DeviceTooSmallError: + # Device too small, skipping test + test.update_status('N/A') + except KeyboardInterrupt: + test.aborted = True + except (subprocess.CalledProcessError, TypeError, ValueError): + # Something went wrong, results unknown + test.update_status('ERROR') + + # Check result and build report + test.report.append('{BLUE}I/O Benchmark{CLEAR}'.format(**COLORS)) + if test.aborted: + test.report.append(' {YELLOW}Aborted{CLEAR}'.format(**COLORS)) + raise GenericAbort('Aborted') + elif not test.read_rates: + if 'ERROR' in test.status: + test.report.append(' {RED}Unknown error{CLEAR}'.format(**COLORS)) + elif 'N/A' in test.status: + # Device too small + test.report.append(' {YELLOW}Disk too small to test{CLEAR}'.format( + **COLORS)) + else: + # Merge rates for horizontal graph + offset = 0 + width = int(test.dev.dd_chunks / IO_VARS['Graph Horizontal Width']) + for i in range(IO_VARS['Graph Horizontal Width']): + test.merged_rates.append( + sum(test.read_rates[offset:offset+width])/width) + offset += width + + # Add horizontal graph to report + for line in generate_horizontal_graph(test.merged_rates): + if not re.match(r'^\s+$', line): + test.report.append(line) + + # Add read speeds to report + avg_read = sum(test.read_rates) / len(test.read_rates) + min_read = min(test.read_rates) + max_read = max(test.read_rates) + avg_min_max = 'Read speeds avg: {:3.1f}'.format(avg_read/(1024**2)) + avg_min_max += ' min: {:3.1f}'.format(min_read/(1024**2)) + avg_min_max += ' max: {:3.1f}'.format(max_read/(1024**2)) + test.report.append(avg_min_max) + + # Compare read speeds to thresholds + if test.dev.lsblk['rota']: + # Use HDD scale + thresh_min = IO_VARS['Threshold HDD Min'] + thresh_high_avg = IO_VARS['Threshold HDD High Avg'] + thresh_low_avg = IO_VARS['Threshold HDD Low Avg'] + else: + # Use SSD scale + thresh_min = IO_VARS['Threshold SSD Min'] + thresh_high_avg = IO_VARS['Threshold SSD High Avg'] + thresh_low_avg = IO_VARS['Threshold SSD Low Avg'] + if min_read <= thresh_min and avg_read <= thresh_high_avg: + test.failed = True + elif avg_read <= thresh_low_avg: + test.failed = True + else: + test.passed = True + + # Update status + if test.failed: + test.update_status('NS') + elif test.passed: + test.update_status('CS') + elif not 'N/A' in test.status: + test.update_status('Unknown') + + # Save log + with open(test.io_benchmark_out.replace('.', '-raw.'), 'a') as f: + f.write('\n'.join(test.vertical_graph)) + + # Done update_progress_pane(state) + # Cleanup + tmux_kill_pane(state.panes['io_benchmark']) + def run_keyboard_test(): """Run keyboard test.""" clear_screen() @@ -1122,14 +1319,18 @@ def run_nvme_smart_tests(state, test): # Bail early if test.disabled: return + + # Prep print_log('Starting NVMe/SMART test for {}'.format(test.dev.path)) _include_short_test = False test.started = True test.update_status() + update_progress_pane(state) + + # Update top pane tmux_update_pane( state.panes['Top'], text='{}\nDisk Health: {}'.format(TOP_PANE_TEXT, test.dev.description)) - update_progress_pane(state) # NVMe if test.dev.nvme_attributes: From 8c5820d5aa73cbface183311655f97842854eb99 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 17 Dec 2018 20:16:35 -0700 Subject: [PATCH 102/265] Fix horizontal graph * generate_horizontal_graph() now returns a list instead of a str --- .bin/Scripts/functions/hw_diags.py | 48 +++++++++++++----------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 50eca7b5..85c4d86e 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -608,11 +608,8 @@ def build_status_string(label, status, info_label=False): **COLORS) def generate_horizontal_graph(rates, oneline=False): - """Generate two-line horizontal graph from rates, returns str.""" - line_1 = '' - line_2 = '' - line_3 = '' - line_4 = '' + """Generate horizontal graph from rates, returns list.""" + graph = ['', '', '', ''] for r in rates: step = get_graph_step(r, scale=32) if oneline: @@ -630,33 +627,30 @@ def generate_horizontal_graph(rates, oneline=False): # Build graph full_block = '{}{}'.format(r_color, IO_VARS['Graph Horizontal'][-1]) if step >= 24: - line_1 += '{}{}'.format(r_color, IO_VARS['Graph Horizontal'][step-24]) - line_2 += full_block - line_3 += full_block - line_4 += full_block + graph[0] += '{}{}'.format(r_color, IO_VARS['Graph Horizontal'][step-24]) + graph[1] += full_block + graph[2] += full_block + graph[3] += full_block elif step >= 16: - line_1 += ' ' - line_2 += '{}{}'.format(r_color, IO_VARS['Graph Horizontal'][step-16]) - line_3 += full_block - line_4 += full_block + graph[0] += ' ' + graph[1] += '{}{}'.format(r_color, IO_VARS['Graph Horizontal'][step-16]) + graph[2] += full_block + graph[3] += full_block elif step >= 8: - line_1 += ' ' - line_2 += ' ' - line_3 += '{}{}'.format(r_color, IO_VARS['Graph Horizontal'][step-8]) - line_4 += full_block + graph[0] += ' ' + graph[1] += ' ' + graph[2] += '{}{}'.format(r_color, IO_VARS['Graph Horizontal'][step-8]) + graph[3] += full_block else: - line_1 += ' ' - line_2 += ' ' - line_3 += ' ' - line_4 += '{}{}'.format(r_color, IO_VARS['Graph Horizontal'][step]) - line_1 += COLORS['CLEAR'] - line_2 += COLORS['CLEAR'] - line_3 += COLORS['CLEAR'] - line_4 += COLORS['CLEAR'] + graph[0] += ' ' + graph[1] += ' ' + graph[2] += ' ' + graph[3] += '{}{}'.format(r_color, IO_VARS['Graph Horizontal'][step]) + graph = [line+COLORS['CLEAR'] for line in graph] if oneline: - return line_4 + return graph[:-1] else: - return '\n'.join([line_1, line_2, line_3, line_4]) + return graph def get_graph_step(rate, scale=16): """Get graph step based on rate and scale, returns int.""" From 41c9a4d23fa5c9df58ceef85d6a2e35934827a59 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 17 Dec 2018 20:29:09 -0700 Subject: [PATCH 103/265] Fixed only showing non-empty graph lines --- .bin/Scripts/functions/hw_diags.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 85c4d86e..30220583 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -1064,7 +1064,7 @@ def run_io_benchmark(state, test): # Add horizontal graph to report for line in generate_horizontal_graph(test.merged_rates): - if not re.match(r'^\s+$', line): + if not re.match(r'^\s+$', strip_colors(line)): test.report.append(line) # Add read speeds to report From 0c0f8e895021c7bfae0ae1a1d258bf86046f54ae Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 17 Dec 2018 20:51:02 -0700 Subject: [PATCH 104/265] Added disable_test() to Disk class --- .bin/Scripts/functions/hw_diags.py | 44 ++++++++++++++++++------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 30220583..4a855dc6 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -237,12 +237,18 @@ class DiskObj(): if HW_OVERRIDES_FORCED or ask('Run tests on this device anyway?'): self.disk_ok = True if 'NVMe / SMART' in self.tests: - self.tests['NVMe / SMART'].update_status('OVERRIDE') - if self.nvme_attributes or not self.smart_attributes: - # i.e. only leave enabled for SMART short-tests - self.tests['NVMe / SMART'].disabled = True + self.disable_test('NVMe / SMART', 'OVERRIDE') + if not self.nvme_attributes and self.smart_attributes: + # Re-enable for SMART short-tests + self.tests['NVMe / SMART'].disabled = False print_standard(' ') + def disable_test(self, name, status): + """Disable test by name and update status.""" + if name in self.tests: + self.tests[name].update_status(status) + self.tests[name].disabled = True + def generate_attribute_report( self, description=False, short_test=False, timestamp=False): """Generate NVMe / SMART report, returns list.""" @@ -427,23 +433,26 @@ class DiskObj(): # Check if a self-test is currently running if 'remaining_percent' in self.smart_self_test['status']: _msg = 'SMART self-test in progress, all tests disabled' + + # Ask to abort if not silent: print_warning('WARNING: {}'.format(_msg)) print_standard(' ') if ask('Abort HW Diagnostics?'): exit_script() + + # Add warning to report if 'NVMe / SMART' in self.tests: self.tests['NVMe / SMART'].report = self.generate_attribute_report() self.tests['NVMe / SMART'].report.append( '{YELLOW}WARNING: {msg}{CLEAR}'.format(msg=_msg, **COLORS)) - for t in self.tests.values(): - t.update_status('Denied') - t.disabled = True + + # Disable all tests for this disk + for t in self.tests.keys(): + self.disable_test(k, 'Denied') else: # No NVMe/SMART details - if 'NVMe / SMART' in self.tests: - self.tests['NVMe / SMART'].update_status('N/A') - self.tests['NVMe / SMART'].disabled = True + self.disable_test('NVMe / SMART', 'N/A') if silent: self.disk_ok = HW_OVERRIDES_FORCED else: @@ -457,14 +466,11 @@ class DiskObj(): if not self.disk_ok: if 'NVMe / SMART' in self.tests: # NOTE: This will not overwrite the existing status if set + self.disable_test('NVMe / SMART', 'NS') if not self.tests['NVMe / SMART'].report: self.tests['NVMe / SMART'].report = self.generate_attribute_report() - self.tests['NVMe / SMART'].update_status('NS') - self.tests['NVMe / SMART'].disabled = True for t in ['badblocks', 'I/O Benchmark']: - if t in self.tests: - self.tests[t].update_status('Denied') - self.tests[t].disabled = True + self.disable_test(t, 'Denied') class State(): """Object to track device objects and overall state.""" @@ -863,6 +869,10 @@ def run_badblocks_test(state, test): test.update_status('Aborted') raise GenericAbort('Aborted') + # Disable other drive tests if necessary + if not test.passed: + test.dev.disable_test('I/O Benchmark', 'Denied') + # Update status if test.failed: test.update_status('NS') @@ -1426,9 +1436,7 @@ def run_nvme_smart_tests(state, test): # Disable other drive tests if necessary if not test.passed: for t in ['badblocks', 'I/O Benchmark']: - if t in test.dev.tests: - test.dev.tests[t].update_status('Denied') - test.dev.tests[t].disabled = True + test.dev.disable_test(t, 'Denied') # Cleanup tmux_kill_pane(state.panes['smart']) From 10ae59be197c431f74e64e03758cdd15b8599432 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 18 Dec 2018 00:55:57 -0700 Subject: [PATCH 105/265] Update tmux layout periodically --- .bin/Scripts/functions/hw_diags.py | 106 ++++++++++++++++++++++++++--- .bin/Scripts/functions/tmux.py | 20 +++++- 2 files changed, 117 insertions(+), 9 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 4a855dc6..56b3c501 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -72,6 +72,11 @@ TESTS_DISK = [ 'badblocks', ] TOP_PANE_TEXT = '{GREEN}Hardware Diagnostics{CLEAR}'.format(**COLORS) +TMUX_LAYOUT = OrderedDict({ + 'Top': {'y': 2, 'Check': True}, + 'Started': {'x': SIDE_PANE_WIDTH, 'Check': True}, + 'Progress': {'x': SIDE_PANE_WIDTH, 'Check': True}, +}) # Error Classe class DeviceTooSmallError(Exception): @@ -449,7 +454,7 @@ class DiskObj(): # Disable all tests for this disk for t in self.tests.keys(): - self.disable_test(k, 'Denied') + self.disable_test(t, 'Denied') else: # No NVMe/SMART details self.disable_test('NVMe / SMART', 'N/A') @@ -613,6 +618,49 @@ def build_status_string(label, status, info_label=False): s_w=SIDE_PANE_WIDTH-len(label), **COLORS) +def fix_tmux_panes(state, tmux_layout): + """Fix pane sizes in case the window has been resized.""" + needs_fixed = False + + # Check layout + for k, v in tmux_layout.items(): + if not v.get('Check'): + # Not concerned with the size of this pane + continue + # Get target + target = None + if k != 'Current': + if k not in state.panes: + # Skip missing panes + continue + else: + target = state.panes[k] + + # Get pane size + x, y = tmux_get_pane_size(pane_id=target) + if v.get('x', False) and v.get['x'] != x: + needs_fixed = True + if v.get('y', False) and v.get['y'] != y: + needs_fixed = True + + # Bail? + if not needs_fixed: + return + + # Update layout + for k, v in tmux_layout.items(): + # Get target + target = None + if k != 'Current': + if k not in state.panes: + # Skip missing panes + continue + else: + target = state.panes[k] + + # Resize pane + tmux_resize_pane(pane_id=target, **v) + def generate_horizontal_graph(rates, oneline=False): """Generate horizontal graph from rates, returns list.""" graph = ['', '', '', ''] @@ -819,10 +867,14 @@ def run_badblocks_test(state, test): test.update_status() update_progress_pane(state) - # Update top pane + # Update tmux layout tmux_update_pane( state.panes['Top'], text='{}\nbadblocks: {}'.format(TOP_PANE_TEXT, test.dev.description)) + test.tmux_layout = TMUX_LAYOUT.copy() + test.tmux_layout.update({ + 'badblocks': {'y': 5, 'Check': True}, + }) # Create monitor pane test.badblocks_out = '{}/badblocks_{}.out'.format( @@ -841,7 +893,15 @@ def run_badblocks_test(state, test): test.badblocks_proc = popen_program( ['sudo', 'hw-diags-badblocks', test.dev.path, test.badblocks_out], pipe=True) - test.badblocks_proc.wait() + while True: + try: + test.badblocks_proc.wait(timeout=10) + except subprocess.TimeoutExpired: + fix_tmux_panes(state, test.tmux_layout) + else: + # badblocks finished, exit loop + break + except KeyboardInterrupt: test.aborted = True @@ -976,11 +1036,16 @@ def run_io_benchmark(state, test): test.update_status() update_progress_pane(state) - # Update top pane + # Update tmux layout tmux_update_pane( state.panes['Top'], text='{}\nI/O Benchmark: {}'.format( TOP_PANE_TEXT, test.dev.description)) + test.tmux_layout = TMUX_LAYOUT.copy() + test.tmux_layout.update({ + 'io_benchmark': {'y': 1000, 'Check': False}, + 'Current': {'y': 15, 'Check': True}, + }) # Create monitor pane test.io_benchmark_out = '{}/io_benchmark_{}.out'.format( @@ -1042,6 +1107,10 @@ def run_io_benchmark(state, test): # Update offset offset += test.dev.dd_chunk_blocks + skip + # Fix panes + if i % 5 == 0: + fix_tmux_panes(state, test.tmux_layout) + except DeviceTooSmallError: # Device too small, skipping test test.update_status('N/A') @@ -1140,10 +1209,16 @@ def run_mprime_test(state, test): update_progress_pane(state) test.sensor_data = get_sensor_data() - # Update top pane + # Update tmux layout tmux_update_pane( state.panes['Top'], text='{}\nPrime95: {}'.format(TOP_PANE_TEXT, test.dev.name)) + test.tmux_layout = TMUX_LAYOUT.copy() + test.tmux_layout.update({ + 'Temps': {'y': 1000, 'Check': False}, + 'mprime': {'y': 11, 'Check': False}, + 'Current': {'y': 3, 'Check': True}, + }) # Start live sensor monitor test.sensors_out = '{}/sensors.out'.format(global_vars['TmpDir']) @@ -1181,7 +1256,7 @@ def run_mprime_test(state, test): working_dir=global_vars['TmpDir']) #time_limit = int(MPRIME_LIMIT) * 60 # TODO: restore above line - time_limit = 10 + time_limit = 30 try: for i in range(time_limit): clear_screen() @@ -1199,6 +1274,12 @@ def run_mprime_test(state, test): print(_status_str) print('{YELLOW}{msg}{CLEAR}'.format(msg=test.abort_msg, **COLORS)) update_sensor_data(test.sensor_data) + + # Fix panes + if i % 10 == 0: + fix_tmux_panes(state, test.tmux_layout) + + # Wait sleep(1) except KeyboardInterrupt: # Catch CTRL+C @@ -1331,10 +1412,14 @@ def run_nvme_smart_tests(state, test): test.update_status() update_progress_pane(state) - # Update top pane + # Update tmux layout tmux_update_pane( state.panes['Top'], text='{}\nDisk Health: {}'.format(TOP_PANE_TEXT, test.dev.description)) + test.tmux_layout = TMUX_LAYOUT.copy() + test.tmux_layout.update({ + 'smart': {'y': 3, 'Check': True}, + }) # NVMe if test.dev.nvme_attributes: @@ -1391,7 +1476,7 @@ def run_nvme_smart_tests(state, test): # Monitor progress (in 5 second increments) try: - for iteration in range(int(test.timeout*60/5)): + for i in range(int(test.timeout*60/5)): sleep(5) # Update SMART data @@ -1412,6 +1497,11 @@ def run_nvme_smart_tests(state, test): # Check if test has started if 'remaining_percent' in test.dev.smart_self_test['status']: _self_test_started = True + + # Fix panes + if i % 2 == 0: + fix_tmux_panes(state, test.tmux_layout) + except KeyboardInterrupt: test.aborted = True test.report = test.dev.generate_attribute_report() diff --git a/.bin/Scripts/functions/tmux.py b/.bin/Scripts/functions/tmux.py index 20f35921..0e585df6 100644 --- a/.bin/Scripts/functions/tmux.py +++ b/.bin/Scripts/functions/tmux.py @@ -8,6 +8,24 @@ def create_file(filepath): with open(filepath, 'w') as f: f.write('') +def tmux_get_pane_size(pane_id=None): + """Get target, or current, pane size, returns tuple.""" + x = -1 + y = -1 + cmd = ['tmux', 'display', '-p', '#{pane_width}x#{pane_height}'] + if pane_id: + cmd.extend(['-t', pane_id]) + + # Run cmd and set x & y + result = run_program(cmd, check=False) + try: + x, y = result.stdout.decode().strip().split() + except Exception: + # Ignore and return unrealistic values + pass + + return (x, y) + def tmux_kill_all_panes(pane_id=None): """Kill all tmux panes except the active pane or pane_id if specified.""" cmd = ['tmux', 'kill-pane', '-a'] @@ -28,7 +46,7 @@ def tmux_poll_pane(pane_id): panes = result.stdout.decode().splitlines() return pane_id in panes -def tmux_resize_pane(pane_id=None, x=None, y=None): +def tmux_resize_pane(pane_id=None, x=None, y=None, **kwargs): """Resize pane to specific hieght or width.""" if not x and not y: raise Exception('Neither height nor width specified.') From 932669844baee7a485ece26f83f7885875245641 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 18 Dec 2018 15:13:33 -0700 Subject: [PATCH 106/265] Fixed tmux pane size handling --- .bin/Scripts/functions/hw_diags.py | 29 +++++++++++++++-------------- .bin/Scripts/functions/tmux.py | 5 ++++- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 56b3c501..dc71c54f 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -638,9 +638,9 @@ def fix_tmux_panes(state, tmux_layout): # Get pane size x, y = tmux_get_pane_size(pane_id=target) - if v.get('x', False) and v.get['x'] != x: + if v.get('x', False) and v['x'] != x: needs_fixed = True - if v.get('y', False) and v.get['y'] != y: + if v.get('y', False) and v['y'] != y: needs_fixed = True # Bail? @@ -895,7 +895,7 @@ def run_badblocks_test(state, test): pipe=True) while True: try: - test.badblocks_proc.wait(timeout=10) + test.badblocks_proc.wait(timeout=1) except subprocess.TimeoutExpired: fix_tmux_panes(state, test.tmux_layout) else: @@ -1108,8 +1108,7 @@ def run_io_benchmark(state, test): offset += test.dev.dd_chunk_blocks + skip # Fix panes - if i % 5 == 0: - fix_tmux_panes(state, test.tmux_layout) + fix_tmux_panes(state, test.tmux_layout) except DeviceTooSmallError: # Device too small, skipping test @@ -1276,8 +1275,7 @@ def run_mprime_test(state, test): update_sensor_data(test.sensor_data) # Fix panes - if i % 10 == 0: - fix_tmux_panes(state, test.tmux_layout) + fix_tmux_panes(state, test.tmux_layout) # Wait sleep(1) @@ -1474,10 +1472,17 @@ def run_nvme_smart_tests(state, test): cmd = ['sudo', 'smartctl', '--test=short', test.dev.path] run_program(cmd, check=False) - # Monitor progress (in 5 second increments) + # Monitor progress try: - for i in range(int(test.timeout*60/5)): - sleep(5) + for i in range(int(test.timeout*60)): + sleep(1) + + # Fix panes + fix_tmux_panes(state, test.tmux_layout) + + # Only update SMART progress every 5 seconds + if i % 5 != 0: + continue # Update SMART data test.dev.get_smart_details() @@ -1498,10 +1503,6 @@ def run_nvme_smart_tests(state, test): if 'remaining_percent' in test.dev.smart_self_test['status']: _self_test_started = True - # Fix panes - if i % 2 == 0: - fix_tmux_panes(state, test.tmux_layout) - except KeyboardInterrupt: test.aborted = True test.report = test.dev.generate_attribute_report() diff --git a/.bin/Scripts/functions/tmux.py b/.bin/Scripts/functions/tmux.py index 0e585df6..ce35f5b0 100644 --- a/.bin/Scripts/functions/tmux.py +++ b/.bin/Scripts/functions/tmux.py @@ -12,14 +12,17 @@ def tmux_get_pane_size(pane_id=None): """Get target, or current, pane size, returns tuple.""" x = -1 y = -1 - cmd = ['tmux', 'display', '-p', '#{pane_width}x#{pane_height}'] + cmd = ['tmux', 'display', '-p'] if pane_id: cmd.extend(['-t', pane_id]) + cmd.append('#{pane_width} #{pane_height}') # Run cmd and set x & y result = run_program(cmd, check=False) try: x, y = result.stdout.decode().strip().split() + x = int(x) + y = int(y) except Exception: # Ignore and return unrealistic values pass From 7ac035c578b2fe62b308a14d783b96d6f3fbc98d Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 18 Dec 2018 15:21:05 -0700 Subject: [PATCH 107/265] Safety wheels off --- .bin/Scripts/functions/hw_diags.py | 22 +++++++--------------- .bin/Scripts/settings/main.py | 2 +- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index dc71c54f..cfe68c69 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -837,13 +837,11 @@ def menu_diags(state, args): elif selection == 'R': print('(FAKE) reboot...') sleep(1) - # TODO uncomment below - #run_program(['systemctl', 'reboot']) + run_program(['systemctl', 'reboot']) elif selection == 'P': print('(FAKE) poweroff...') sleep(1) - # TODO uncomment below - #run_program(['systemctl', 'poweroff']) + run_program(['systemctl', 'poweroff']) elif selection == 'Q': break elif selection == 'S': @@ -1242,8 +1240,7 @@ def run_mprime_test(state, test): message='Getting idle temps...', indent=0, function=save_average_temp, cs='Done', sensor_data=test.sensor_data, temp_label='Idle', - seconds=3) - # TODO: Remove seconds kwarg above + seconds=5) # Stress CPU print_log('Starting Prime95') @@ -1253,9 +1250,7 @@ def run_mprime_test(state, test): state.panes['mprime'], command=['hw-diags-prime95', global_vars['TmpDir']], working_dir=global_vars['TmpDir']) - #time_limit = int(MPRIME_LIMIT) * 60 - # TODO: restore above line - time_limit = 30 + time_limit = int(MPRIME_LIMIT) * 60 try: for i in range(time_limit): clear_screen() @@ -1301,14 +1296,12 @@ def run_mprime_test(state, test): clear_screen() try_and_print( message='Letting CPU cooldown for bit...', indent=0, - function=sleep, cs='Done', seconds=3) - # TODO: Above seconds should be 10 + function=sleep, cs='Done', seconds=10) try_and_print( message='Getting cooldown temps...', indent=0, function=save_average_temp, cs='Done', sensor_data=test.sensor_data, temp_label='Cooldown', - seconds=3) - # TODO: Remove seconds kwarg above + seconds=5) # Move logs to Ticket folder for item in os.scandir(global_vars['TmpDir']): @@ -1447,8 +1440,7 @@ def run_nvme_smart_tests(state, test): # Prep test.timeout = test.dev.smart_self_test['polling_minutes'].get( 'short', 5) - # TODO: fix timeout, set to polling + 5 - test.timeout = int(test.timeout) + 1 + test.timeout = int(test.timeout) + 5 _include_short_test = True _self_test_started = False diff --git a/.bin/Scripts/settings/main.py b/.bin/Scripts/settings/main.py index 7b915bdb..9d32b3ef 100644 --- a/.bin/Scripts/settings/main.py +++ b/.bin/Scripts/settings/main.py @@ -15,7 +15,7 @@ KIT_NAME_FULL='WizardKit' KIT_NAME_SHORT='WK' SUPPORT_MESSAGE='Please let 2Shirt know by opening an issue on GitHub' # Live Linux -MPRIME_LIMIT='7' # of minutes to run Prime95 during hw-diags +MPRIME_LIMIT='7' # of minutes to run Prime95 during hw-diags ROOT_PASSWORD='Abracadabra' TECH_PASSWORD='Abracadabra' # Server IP addresses From 91a77bb14e9bfb1f9525aaffc6390e667e32c2d9 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 18 Dec 2018 15:47:03 -0700 Subject: [PATCH 108/265] Ensure SMART timeout message is in the report --- .bin/Scripts/functions/hw_diags.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index cfe68c69..64d417da 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -132,6 +132,7 @@ class DiskObj(): self.nvme_attributes = {} self.path = disk_path self.smart_attributes = {} + self.smart_timeout = False self.smart_self_test = {} self.smartctl = {} self.tests = OrderedDict() @@ -331,12 +332,11 @@ class DiskObj(): # SMART short-test if short_test: report.append('{BLUE}SMART Short self-test{CLEAR}'.format(**COLORS)) - if 'TimedOut' in self.tests['NVMe / SMART'].status: - report.append(' {YELLOW}UNKNOWN{CLEAR}: Timed out'.format(**COLORS)) - else: - report.append(' {}'.format( - self.smart_self_test['status'].get( - 'string', 'UNKNOWN').capitalize())) + report.append(' {}'.format( + self.smart_self_test['status'].get( + 'string', 'UNKNOWN').capitalize())) + if self.smart_timeout: + report.append(' {YELLOW}Timed out{CLEAR}'.format(**COLORS)) # Done return report @@ -1443,6 +1443,7 @@ def run_nvme_smart_tests(state, test): test.timeout = int(test.timeout) + 5 _include_short_test = True _self_test_started = False + _self_test_finished = False # Create monitor pane test.smart_out = '{}/smart_{}.out'.format( @@ -1488,6 +1489,7 @@ def run_nvme_smart_tests(state, test): # Check if test has finished if 'remaining_percent' not in test.dev.smart_self_test['status']: + _self_test_finished = True break else: @@ -1505,15 +1507,16 @@ def run_nvme_smart_tests(state, test): raise GenericAbort('Aborted') # Check if timed out - if 'passed' in test.dev.smart_self_test['status']: - if test.dev.smart_self_test['status']['passed']: + if _self_test_finished: + if test.dev.smart_self_test['status'].get('passed', False): if 'OVERRIDE' not in test.status: test.passed = True test.update_status('CS') else: test.failed = True test.update_status('NS') - if not (test.failed or test.passed): + else: + test.dev.smart_timeout = True test.update_status('TimedOut') # Disable other drive tests if necessary From e5f0ccb5d51bf8d89460c3a35eff26d10e8dc333 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 18 Dec 2018 15:57:48 -0700 Subject: [PATCH 109/265] Formatting cleanup --- .bin/Scripts/functions/hw_diags.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 64d417da..b09dbf05 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -591,8 +591,8 @@ def build_outer_panes(state): # Started state.panes['Started'] = tmux_split_window( lines=SIDE_PANE_WIDTH, target_pane=state.panes['Top'], - text='{BLUE}Started{CLEAR}\n{text}'.format( - text=time.strftime("%Y-%m-%d %H:%M %Z"), + text='{BLUE}Started{CLEAR}\n{s}'.format( + s=time.strftime("%Y-%m-%d %H:%M %Z"), **COLORS)) # Progress @@ -868,7 +868,8 @@ def run_badblocks_test(state, test): # Update tmux layout tmux_update_pane( state.panes['Top'], - text='{}\nbadblocks: {}'.format(TOP_PANE_TEXT, test.dev.description)) + text='{}\nbadblocks: {}'.format( + TOP_PANE_TEXT, test.dev.description)) test.tmux_layout = TMUX_LAYOUT.copy() test.tmux_layout.update({ 'badblocks': {'y': 5, 'Check': True}, @@ -1037,8 +1038,8 @@ def run_io_benchmark(state, test): # Update tmux layout tmux_update_pane( state.panes['Top'], - text='{}\nI/O Benchmark: {}'.format( - TOP_PANE_TEXT, test.dev.description)) + text='{}\nI/O Benchmark: {}'.format( + TOP_PANE_TEXT, test.dev.description)) test.tmux_layout = TMUX_LAYOUT.copy() test.tmux_layout.update({ 'io_benchmark': {'y': 1000, 'Check': False}, @@ -1406,7 +1407,8 @@ def run_nvme_smart_tests(state, test): # Update tmux layout tmux_update_pane( state.panes['Top'], - text='{}\nDisk Health: {}'.format(TOP_PANE_TEXT, test.dev.description)) + text='{}\nDisk Health: {}'.format( + TOP_PANE_TEXT, test.dev.description)) test.tmux_layout = TMUX_LAYOUT.copy() test.tmux_layout.update({ 'smart': {'y': 3, 'Check': True}, @@ -1554,8 +1556,8 @@ def show_results(state): """Show results for all tests.""" clear_screen() tmux_update_pane( - state.panes['Top'], text='{}\n{}'.format( - TOP_PANE_TEXT, 'Results')) + state.panes['Top'], + text='{}\nResults'.format(TOP_PANE_TEXT)) # CPU tests _enabled = False From ad9662c1208f00071d6ce4e721fd996e3e320035 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 18 Dec 2018 16:38:40 -0700 Subject: [PATCH 110/265] Updated to use new hw_diags.py --- .bin/Scripts/ddrescue-tui-smart-display | 52 +++++++++++++------------ 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/.bin/Scripts/ddrescue-tui-smart-display b/.bin/Scripts/ddrescue-tui-smart-display index 285229d6..65b76890 100755 --- a/.bin/Scripts/ddrescue-tui-smart-display +++ b/.bin/Scripts/ddrescue-tui-smart-display @@ -10,30 +10,34 @@ import time os.chdir(os.path.dirname(os.path.realpath(__file__))) sys.path.append(os.getcwd()) from functions.hw_diags import * -#init_global_vars() +init_global_vars() if __name__ == '__main__': - try: - # Prep - clear_screen() - dev_path = sys.argv[1] - devs = scan_disks(True, dev_path) - - # Warn if SMART unavailable - if dev_path not in devs: - print_error('SMART data not available') - exit_script() - - # Initial screen - dev = devs[dev_path] - clear_screen() - show_disk_details(dev, only_attributes=True) - - # Done - exit_script() - except SystemExit: - pass - except: - major_exception() + try: + # Prep + clear_screen() + state = State() + state.init() -# vim: sts=4 sw=4 ts=4 + # Find disk + disk = None + for d in state.disks: + if d.path == sys.argv[1]: + disk = d + + # Show details + clear_screen() + if disk: + for line in disk.generate_attribute_report(timestamp=True): + print(line) + else: + print_error('Disk "{}" not found'.format(sys.argv[1])) + + # Done + exit_script() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 From e1834d517953fd6a183be960770a4c52a91a31a5 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 18 Dec 2018 17:26:20 -0700 Subject: [PATCH 111/265] Added silent mode to init_global_vars() --- .bin/Scripts/functions/common.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index 5327d895..82c65bb1 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -652,9 +652,10 @@ def wait_for_process(name, poll_rate=3): sleep(1) # global_vars functions -def init_global_vars(): +def init_global_vars(silent=False): """Sets global variables based on system info.""" - print_info('Initializing') + if not silent: + print_info('Initializing') if psutil.WINDOWS: os.system('title Wizard Kit') if psutil.LINUX: @@ -672,10 +673,14 @@ def init_global_vars(): ['Clearing collisions...', clean_env_vars], ] try: - for f in init_functions: - try_and_print( - message=f[0], function=f[1], - cs='Done', ns='Error', catch_all=False) + if silent: + for f in init_functions: + f[1]() + else: + for f in init_functions: + try_and_print( + message=f[0], function=f[1], + cs='Done', ns='Error', catch_all=False) except: major_exception() From 04cfdff2bf7a5f2f085caf165235a5a5219f261e Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 18 Dec 2018 17:27:15 -0700 Subject: [PATCH 112/265] Don't show init, just disk details --- .bin/Scripts/ddrescue-tui-smart-display | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.bin/Scripts/ddrescue-tui-smart-display b/.bin/Scripts/ddrescue-tui-smart-display index 65b76890..4b8afcde 100755 --- a/.bin/Scripts/ddrescue-tui-smart-display +++ b/.bin/Scripts/ddrescue-tui-smart-display @@ -10,12 +10,11 @@ import time os.chdir(os.path.dirname(os.path.realpath(__file__))) sys.path.append(os.getcwd()) from functions.hw_diags import * -init_global_vars() +init_global_vars(silent=True) if __name__ == '__main__': try: # Prep - clear_screen() state = State() state.init() @@ -26,7 +25,6 @@ if __name__ == '__main__': disk = d # Show details - clear_screen() if disk: for line in disk.generate_attribute_report(timestamp=True): print(line) From ad15cdad5612940940ba243b4b58911924fc3018 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 18 Dec 2018 17:28:06 -0700 Subject: [PATCH 113/265] Added warning if not saving map to a preferred FS * Fixes #76 --- .bin/Scripts/functions/ddrescue.py | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/.bin/Scripts/functions/ddrescue.py b/.bin/Scripts/functions/ddrescue.py index 7f1fc7aa..6d722165 100644 --- a/.bin/Scripts/functions/ddrescue.py +++ b/.bin/Scripts/functions/ddrescue.py @@ -351,7 +351,34 @@ class RecoveryState(): self.set_pass_num() def self_checks(self): - """Run self-checks for each BlockPair and update state values.""" + """Run self-checks and update state values.""" + cmd = ['findmnt', '--json', '--target', os.getcwd()] + map_allowed_fstypes = RECOMMENDED_FSTYPES.copy() + map_allowed_fstypes.extend(['cifs', 'ext2', 'vfat']) + map_allowed_fstypes.sort() + json_data = {} + + # Avoid saving map to non-persistent filesystem + try: + result = run_program(cmd) + json_data = json.loads(result.stdout.decode()) + except Exception: + print_error('ERROR: Failed to verify map path') + raise GenericAbort() + fstype = json_data.get( + 'filesystems', [{}])[0].get( + 'fstype', 'unknown') + if fstype not in map_allowed_fstypes: + print_error( + "Map isn't being saved to a recommended filesystem ({})".format( + fstype.upper())) + print_info('Recommended types are: {}'.format( + ' / '.join(map_allowed_fstypes).upper())) + print_standard(' ') + if not ask('Proceed anyways? (Strongly discouraged)'): + raise GenericAbort() + + # Run BlockPair self checks and get total size self.total_size = 0 for bp in self.block_pairs: bp.self_check() From 62b8e51705367034f03635aaab1d0e1e016e4a39 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 18 Dec 2018 19:45:02 -0700 Subject: [PATCH 114/265] Updated ddrescue-tui tmux pane size handling --- .bin/Scripts/functions/ddrescue.py | 190 +++++++++++++++++++---------- .bin/Scripts/functions/hw_diags.py | 4 +- .bin/Scripts/functions/tmux.py | 2 +- 3 files changed, 130 insertions(+), 66 deletions(-) diff --git a/.bin/Scripts/functions/ddrescue.py b/.bin/Scripts/functions/ddrescue.py index 6d722165..6cbc9430 100644 --- a/.bin/Scripts/functions/ddrescue.py +++ b/.bin/Scripts/functions/ddrescue.py @@ -8,8 +8,10 @@ import signal import stat import time +from collections import OrderedDict from functions.common import * from functions.data import * +from functions.tmux import * from operator import itemgetter # STATIC VARIABLES @@ -30,6 +32,11 @@ DDRESCUE_SETTINGS = { } RECOMMENDED_FSTYPES = ['ext3', 'ext4', 'xfs'] SIDE_PANE_WIDTH = 21 +TMUX_LAYOUT = OrderedDict({ + 'Source': {'y': 2, 'Check': True}, + 'Started': {'x': SIDE_PANE_WIDTH, 'Check': True}, + 'Progress': {'x': SIDE_PANE_WIDTH, 'Check': True}, +}) USAGE = """ {script_name} clone [source [destination]] {script_name} image [source [destination]] (e.g. {script_name} clone /dev/sda /dev/sdb) @@ -276,6 +283,7 @@ class RecoveryState(): self.current_pass_str = '0: Initializing' self.settings = DDRESCUE_SETTINGS.copy() self.finished = False + self.panes = {} self.progress_out = '{}/progress.out'.format(global_vars['LogDir']) self.rescued = 0 self.resumed = False @@ -425,46 +433,22 @@ class RecoveryState(): # Functions def build_outer_panes(state): """Build top and side panes.""" - clear_screen() - result = run_program(['tput', 'cols']) - width = int( - (int(result.stdout.decode().strip()) - SIDE_PANE_WIDTH) / 2) - 2 - - # Top panes - source_str = state.source.name - if len(source_str) > width: - source_str = '{}...'.format(source_str[:width-3]) - dest_str = state.dest.name - if len(dest_str) > width: - if state.mode == 'clone': - dest_str = '{}...'.format(dest_str[:width-3]) - else: - dest_str = '...{}'.format(dest_str[-width+3:]) - source_pane = tmux_splitw( - '-bdvl', '2', - '-PF', '#D', - 'echo-and-hold "{BLUE}Source{CLEAR}\n{text}"'.format( - text=source_str, - **COLORS)) - tmux_splitw( - '-t', source_pane, - '-dhl', '{}'.format(SIDE_PANE_WIDTH), - 'echo-and-hold "{BLUE}Started{CLEAR}\n{text}"'.format( - text=time.strftime("%Y-%m-%d %H:%M %Z"), - **COLORS)) - tmux_splitw( - '-t', source_pane, - '-dhp', '50', - 'echo-and-hold "{BLUE}Destination{CLEAR}\n{text}"'.format( - text=dest_str, + state.panes['Source'] = tmux_split_window( + behind=True, vertical=True, lines=2, + text='{BLUE}Source{CLEAR}'.format(**COLORS)) + state.panes['Started'] = tmux_split_window( + lines=SIDE_PANE_WIDTH, target_pane=state.panes['Source'], + text='{BLUE}Started{CLEAR}\n{s}'.format( + s=time.strftime("%Y-%m-%d %H:%M %Z"), **COLORS)) + state.panes['Destination'] = tmux_split_window( + percent=50, target_pane=state.panes['Source'], + text='{BLUE}Destination{CLEAR}'.format(**COLORS)) # Side pane update_sidepane(state) - tmux_splitw( - '-dhl', str(SIDE_PANE_WIDTH), - 'watch', '--color', '--no-title', '--interval', '1', - 'cat', state.progress_out) + state.panes['Progress'] = tmux_split_window( + lines=SIDE_PANE_WIDTH, watch=state.progress_out) def create_path_obj(path): @@ -491,6 +475,94 @@ def double_confirm_clone(): return ask('Asking again to confirm, is this correct?') +def fix_tmux_panes(state, forced=False): + """Fix pane sizes if the winodw has been resized.""" + needs_fixed = False + + # Check layout + for k, v in TMUX_LAYOUT.items(): + if not v.get('Check'): + # Not concerned with the size of this pane + continue + # Get target + target = None + if k != 'Current': + if k not in state.panes: + # Skip missing panes + continue + else: + target = state.panes[k] + + # Check pane size + x, y = tmux_get_pane_size(pane_id=target) + if v.get('x', False) and v['x'] != x: + needs_fixed = True + if v.get('y', False) and v['y'] != y: + needs_fixed = True + + # Bail? + if not needs_fixed and not forced: + return + + # Remove Destination pane (temporarily) + tmux_kill_pane(state.panes['Destination']) + + # Update layout + for k, v in TMUX_LAYOUT.items(): + # Get target + target = None + if k != 'Current': + if k not in state.panes: + # Skip missing panes + continue + else: + target = state.panes[k] + + # Resize pane + tmux_resize_pane(pane_id=target, **v) + + # Calc Source/Destination pane sizes + width, height = tmux_get_pane_size() + width = int(width / 2) - 1 + + # Update Source string + source_str = state.source.name + if len(source_str) > width: + source_str = '{}...'.format(source_str[:width-3]) + + # Update Destination string + dest_str = state.dest.name + if len(dest_str) > width: + if state.mode == 'clone': + dest_str = '{}...'.format(dest_str[:width-3]) + else: + dest_str = '...{}'.format(dest_str[-width+3:]) + + # Rebuild Source/Destination panes + tmux_update_pane( + pane_id=state.panes['Source'], + text='{BLUE}Source{CLEAR}\n{s}'.format( + s=source_str, **COLORS)) + state.panes['Destination'] = tmux_split_window( + percent=50, target_pane=state.panes['Source'], + text='{BLUE}Destination{CLEAR}\n{s}'.format( + s=dest_str, **COLORS)) + + if 'SMART' in state.panes: + # Calc SMART/ddrescue/Journal panes sizes + ratio = [12, 22, 4] + width, height = tmux_get_pane_size(pane_id=state.panes['Progress']) + height -= 2 + total = sum(ratio) + p_ratio = [int((x/total) * height) for x in ratio] + p_ratio[1] = height - p_ratio[0] - p_ratio[2] + + # Resize SMART/Journal panes + tmux_resize_pane(state.panes['SMART'], y=ratio[0]) + tmux_resize_pane(y=ratio[1]) + tmux_resize_pane(state.panes['Journal'], y=ratio[2]) + + def get_device_details(dev_path): """Get device details via lsblk, returns JSON dict.""" try: @@ -687,7 +759,9 @@ def menu_ddrescue(source_path, dest_path, run_mode): raise GenericAbort() # Main menu + clear_screen() build_outer_panes(state) + fix_tmux_panes(state, forced=True) menu_main(state) # Done @@ -877,29 +951,24 @@ def run_ddrescue(state, pass_settings): pause('Press Enter to return to main menu...') return - # Set heights - # NOTE: 12/33 is based on min heights for SMART/ddrescue panes (12+22+1sep) - result = run_program(['tput', 'lines']) - height = int(result.stdout.decode().strip()) - height_smart = int(height * (8 / 33)) - height_journal = int(height * (4 / 33)) - height_ddrescue = height - height_smart - height_journal - # Show SMART status smart_dev = state.source_path if state.source.parent: smart_dev = state.source.parent - smart_pane = tmux_splitw( - '-bdvl', str(height_smart), - '-PF', '#D', - 'watch', '--color', '--no-title', '--interval', '300', - 'ddrescue-tui-smart-display', smart_dev) + smart_cmd = [ + 'watch', '--color', '--no-title', '--interval', '5', + 'ddrescue-tui-smart-display', smart_dev, + ] + state.panes['SMART'] = tmux_split_window( + behind=True, lines=12, vertical=True, command=smart_cmd) # Show systemd journal output - journal_pane = tmux_splitw( - '-dvl', str(height_journal), - '-PF', '#D', - 'journalctl', '-f') + state.panes['Journal'] = tmux_split_window( + lines=4, vertical=True, + command=['sudo', 'journalctl', '-f']) + + # Fix layout + fix_tmux_panes(state, forced=True) # Run pass for each block-pair for bp in state.block_pairs: @@ -931,8 +1000,9 @@ def run_ddrescue(state, pass_settings): while True: bp.update_progress(state.current_pass) update_sidepane(state) + fix_tmux_panes(state) try: - ddrescue_proc.wait(timeout=10) + ddrescue_proc.wait(timeout=1) sleep(2) bp.update_progress(state.current_pass) update_sidepane(state) @@ -967,8 +1037,9 @@ def run_ddrescue(state, pass_settings): if str(return_code) != '0': # Pause on errors pause('Press Enter to return to main menu... ') - run_program(['tmux', 'kill-pane', '-t', smart_pane]) - run_program(['tmux', 'kill-pane', '-t', journal_pane]) + + # Cleanup + tmux_kill_pane(state.panes['SMART'], state.panes['Journal']) def select_parts(source_device): @@ -1219,13 +1290,6 @@ def show_usage(script_name): pause() -def tmux_splitw(*args): - """Run tmux split-window command and return output as str.""" - cmd = ['tmux', 'split-window', *args] - result = run_program(cmd) - return result.stdout.decode().strip() - - def update_sidepane(state): """Update progress file for side pane.""" output = [] diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index b09dbf05..9cef1d33 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -619,7 +619,7 @@ def build_status_string(label, status, info_label=False): **COLORS) def fix_tmux_panes(state, tmux_layout): - """Fix pane sizes in case the window has been resized.""" + """Fix pane sizes if the window has been resized.""" needs_fixed = False # Check layout @@ -636,7 +636,7 @@ def fix_tmux_panes(state, tmux_layout): else: target = state.panes[k] - # Get pane size + # Check pane size x, y = tmux_get_pane_size(pane_id=target) if v.get('x', False) and v['x'] != x: needs_fixed = True diff --git a/.bin/Scripts/functions/tmux.py b/.bin/Scripts/functions/tmux.py index ce35f5b0..84046d0b 100644 --- a/.bin/Scripts/functions/tmux.py +++ b/.bin/Scripts/functions/tmux.py @@ -69,7 +69,7 @@ def tmux_split_window( lines=None, percent=None, behind=False, vertical=False, follow=False, target_pane=None, - working_dir=None, command=None, + command=None, working_dir=None, text=None, watch=None, watch_cmd='cat'): """Run tmux split-window command and return pane_id as str.""" # Bail early From 44fe8882301095ae789de3b393a19a0ee92daca0 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 18 Dec 2018 20:15:35 -0700 Subject: [PATCH 115/265] Replaced ddrescue-tui-smart-display * Output data to file and have tmux pane watching said file * This method handles resizing much better --- .bin/Scripts/ddrescue-tui-smart-display | 41 ----------------------- .bin/Scripts/functions/ddrescue.py | 44 +++++++++++++++++++------ 2 files changed, 34 insertions(+), 51 deletions(-) delete mode 100755 .bin/Scripts/ddrescue-tui-smart-display diff --git a/.bin/Scripts/ddrescue-tui-smart-display b/.bin/Scripts/ddrescue-tui-smart-display deleted file mode 100755 index 4b8afcde..00000000 --- a/.bin/Scripts/ddrescue-tui-smart-display +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/python3 -# -## Wizard Kit: SMART attributes display for ddrescue TUI - -import os -import sys -import time - -# Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) -from functions.hw_diags import * -init_global_vars(silent=True) - -if __name__ == '__main__': - try: - # Prep - state = State() - state.init() - - # Find disk - disk = None - for d in state.disks: - if d.path == sys.argv[1]: - disk = d - - # Show details - if disk: - for line in disk.generate_attribute_report(timestamp=True): - print(line) - else: - print_error('Disk "{}" not found'.format(sys.argv[1])) - - # Done - exit_script() - except SystemExit: - pass - except: - major_exception() - -# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/functions/ddrescue.py b/.bin/Scripts/functions/ddrescue.py index 6cbc9430..00fb35f7 100644 --- a/.bin/Scripts/functions/ddrescue.py +++ b/.bin/Scripts/functions/ddrescue.py @@ -11,6 +11,7 @@ import time from collections import OrderedDict from functions.common import * from functions.data import * +from functions.hw_diags import * from functions.tmux import * from operator import itemgetter @@ -291,6 +292,7 @@ class RecoveryState(): self.total_size = 0 if mode not in ('clone', 'image'): raise GenericError('Unsupported mode') + self.get_smart_source() def add_block_pair(self, source, dest): """Run safety checks and append new BlockPair to internal list.""" @@ -349,6 +351,14 @@ class RecoveryState(): min_percent = min(min_percent, bp.rescued_percent) return min_percent + def get_smart_source(self): + """Get source for SMART dispay.""" + disk_path = self.source.path + if self.source.parent: + disk_path = self.source.parent + + self.smart_source = DiskObj(disk_path) + def retry_all_passes(self): """Mark all passes as pending for all block-pairs.""" self.finished = False @@ -951,16 +961,13 @@ def run_ddrescue(state, pass_settings): pause('Press Enter to return to main menu...') return - # Show SMART status - smart_dev = state.source_path - if state.source.parent: - smart_dev = state.source.parent - smart_cmd = [ - 'watch', '--color', '--no-title', '--interval', '5', - 'ddrescue-tui-smart-display', smart_dev, - ] + # Create SMART monitor pane + state.smart_out = '{}/smart_{}.out'.format( + global_vars['TmpDir'], state.smart_source.name) + with open(state.smart_out, 'w') as f: + f.write('Initializing...') state.panes['SMART'] = tmux_split_window( - behind=True, lines=12, vertical=True, command=smart_cmd) + behind=True, lines=12, vertical=True, watch=state.smart_out) # Show systemd journal output state.panes['Journal'] = tmux_split_window( @@ -997,10 +1004,26 @@ def run_ddrescue(state, pass_settings): clear_screen() print_info('Current dev: {}'.format(bp.source_path)) ddrescue_proc = popen_program(cmd) + i = 0 while True: + # Update SMART display (every 30 seconds) + i += 1 + if i % 30 == 0: + state.smart_source.get_smart_details() + with open(state.smart_out, 'w') as f: + report = state.smart_source.generate_attribute_report( + timestamp=True) + for line in report: + f.write('{}\n'.format(line)) + + # Update progress bp.update_progress(state.current_pass) update_sidepane(state) + + # Fix panes fix_tmux_panes(state) + + # Check if ddrescue has finished try: ddrescue_proc.wait(timeout=1) sleep(2) @@ -1008,8 +1031,9 @@ def run_ddrescue(state, pass_settings): update_sidepane(state) break except subprocess.TimeoutExpired: - # Catch to update bp/sidepane + # Catch to update smart/bp/sidepane pass + except KeyboardInterrupt: # Catch user abort pass From 42407f0eca0f75be518ecc34b99d8f09baad40c7 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 18 Dec 2018 20:35:21 -0700 Subject: [PATCH 116/265] Adjusted ddrescue exit handling * Wait for ddrescue_proc after KeyboardInterrupt * ddrescue prints extra info to the screen after a CTRL+c * Explicitly mark KeyboardInterrupt events as an abort * Add 'DDRESCUE PROCESS HALTED' message in red if exiting non-zero * More clearly indicates that user interaction is required * Fixes issue #72 --- .bin/Scripts/functions/ddrescue.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/.bin/Scripts/functions/ddrescue.py b/.bin/Scripts/functions/ddrescue.py index 00fb35f7..6e515655 100644 --- a/.bin/Scripts/functions/ddrescue.py +++ b/.bin/Scripts/functions/ddrescue.py @@ -953,7 +953,8 @@ def read_map_file(map_path): def run_ddrescue(state, pass_settings): """Run ddrescue pass.""" - return_code = None + return_code = -1 + aborted = False if state.finished: clear_screen() @@ -1007,7 +1008,6 @@ def run_ddrescue(state, pass_settings): i = 0 while True: # Update SMART display (every 30 seconds) - i += 1 if i % 30 == 0: state.smart_source.get_smart_details() with open(state.smart_out, 'w') as f: @@ -1015,6 +1015,7 @@ def run_ddrescue(state, pass_settings): timestamp=True) for line in report: f.write('{}\n'.format(line)) + i += 1 # Update progress bp.update_progress(state.current_pass) @@ -1036,7 +1037,8 @@ def run_ddrescue(state, pass_settings): except KeyboardInterrupt: # Catch user abort - pass + aborted = True + ddrescue_proc.wait(timeout=10) # Update progress/sidepane again bp.update_progress(state.current_pass) @@ -1044,12 +1046,19 @@ def run_ddrescue(state, pass_settings): # Was ddrescue aborted? return_code = ddrescue_proc.poll() - if return_code is None or return_code is 130: - clear_screen() + if aborted: + print_standard(' ') + print_standard(' ') + print_error('DDRESCUE PROCESS HALTED') + print_standard(' ') print_warning('Aborted') break elif return_code: - # i.e. not None and not 0 + # i.e. True when non-zero + print_standard(' ') + print_standard(' ') + print_error('DDRESCUE PROCESS HALTED') + print_standard(' ') print_error('Error(s) encountered, see message above.') break else: From f022d0ca76e369aa2a7f9792c58c2e98a5eae05a Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 19 Dec 2018 18:45:58 -0700 Subject: [PATCH 117/265] Fallback to HW-Diags CLI if X fails to start * Fixes issue #74 --- .linux_items/include/airootfs/etc/skel/.update_x | 3 +++ .linux_items/include/airootfs/etc/skel/.zlogin | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/.linux_items/include/airootfs/etc/skel/.update_x b/.linux_items/include/airootfs/etc/skel/.update_x index 4763a175..650d3162 100755 --- a/.linux_items/include/airootfs/etc/skel/.update_x +++ b/.linux_items/include/airootfs/etc/skel/.update_x @@ -92,3 +92,6 @@ else cbatticon --hide-notification & fi +# Prevent Xorg from being killed by .zlogin +touch "/tmp/x_ok" + diff --git a/.linux_items/include/airootfs/etc/skel/.zlogin b/.linux_items/include/airootfs/etc/skel/.zlogin index bd736280..56b47242 100644 --- a/.linux_items/include/airootfs/etc/skel/.zlogin +++ b/.linux_items/include/airootfs/etc/skel/.zlogin @@ -14,7 +14,18 @@ if [ "$(fgconsole 2>/dev/null)" -eq "1" ]; then # Start X or HW-diags if ! fgrep -q "nox" /proc/cmdline; then + # Kill Xorg after 30 seconds if it doesn't fully initialize + (sleep 30s; if ! [[ -f "/tmp/x_ok" ]]; then pkill '(Xorg|startx)'; fi) & + + # Try starting X startx >/dev/null + + # Run Hw-Diags CLI if necessary + if ! [[ -f "/tmp/x_ok" ]]; then + echo "There was an issue starting Xorg, starting CLI interface..." + sleep 2s + hw-diags cli + fi else hw-diags cli fi From c6eb7cdfd6e52fd1bcd533c49c74aeb8baecc3a0 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 19 Dec 2018 18:53:13 -0700 Subject: [PATCH 118/265] Use new arguments when calling hw-diags --- .linux_items/include/airootfs/etc/skel/.config/i3/config | 2 +- .linux_items/include/airootfs/etc/skel/.config/openbox/rc.xml | 2 +- .linux_items/include/airootfs/etc/skel/.zlogin | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.linux_items/include/airootfs/etc/skel/.config/i3/config b/.linux_items/include/airootfs/etc/skel/.config/i3/config index ca1a5439..102b50f5 100644 --- a/.linux_items/include/airootfs/etc/skel/.config/i3/config +++ b/.linux_items/include/airootfs/etc/skel/.config/i3/config @@ -72,7 +72,7 @@ bindsym $mod+d exec "urxvt -title 'Hardware Diagnostics' -e hw-diags" bindsym $mod+f exec "thunar ~" bindsym $mod+i exec "hardinfo" bindsym $mod+m exec "urxvt -title 'Mount All Volumes' -e mount-all-volumes gui" -bindsym $mod+s exec "urxvt -title 'Hardware Diagnostics' -e hw-diags quick" +bindsym $mod+s exec "urxvt -title 'Hardware Diagnostics' -e hw-diags --quick" bindsym $mod+t exec "urxvt -e zsh -c 'tmux new-session -A -t general; zsh'" bindsym $mod+v exec "urxvt -title 'Hardware Sensors' -e watch -c -n1 -t hw-sensors" bindsym $mod+w exec "firefox" diff --git a/.linux_items/include/airootfs/etc/skel/.config/openbox/rc.xml b/.linux_items/include/airootfs/etc/skel/.config/openbox/rc.xml index 90c7b0e0..e563ec04 100644 --- a/.linux_items/include/airootfs/etc/skel/.config/openbox/rc.xml +++ b/.linux_items/include/airootfs/etc/skel/.config/openbox/rc.xml @@ -324,7 +324,7 @@ - urxvt -title "Hardware Diagnostics" -e hw-diags quick + urxvt -title "Hardware Diagnostics" -e hw-diags --quick diff --git a/.linux_items/include/airootfs/etc/skel/.zlogin b/.linux_items/include/airootfs/etc/skel/.zlogin index 56b47242..04b1316e 100644 --- a/.linux_items/include/airootfs/etc/skel/.zlogin +++ b/.linux_items/include/airootfs/etc/skel/.zlogin @@ -24,9 +24,9 @@ if [ "$(fgconsole 2>/dev/null)" -eq "1" ]; then if ! [[ -f "/tmp/x_ok" ]]; then echo "There was an issue starting Xorg, starting CLI interface..." sleep 2s - hw-diags cli + hw-diags --cli fi else - hw-diags cli + hw-diags --cli fi fi From eed8a1e40c48b205e40c422a32cc608a1934b080 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 20 Dec 2018 15:25:39 -0700 Subject: [PATCH 119/265] Fix poweroff/reboot calls --- .bin/Scripts/functions/hw_diags.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 9cef1d33..9f10f997 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -835,13 +835,9 @@ def menu_diags(state, args): # Tubes is close to pipes right? secret_screensaver('pipes') elif selection == 'R': - print('(FAKE) reboot...') - sleep(1) - run_program(['systemctl', 'reboot']) + run_program(['/usr/local/bin/wk-power-command', 'reboot']) elif selection == 'P': - print('(FAKE) poweroff...') - sleep(1) - run_program(['systemctl', 'poweroff']) + run_program(['/usr/local/bin/wk-power-command', 'poweroff']) elif selection == 'Q': break elif selection == 'S': From d60aab958408d9eba1ddd9c38dde8bdcd7c17a77 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 20 Dec 2018 16:03:54 -0700 Subject: [PATCH 120/265] Updated MemTest86 to 8.0 * Passmark is no longer providing ISOs so the UFD image is used instead * This is an alternative solution to issue #71 --- Build Linux | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Build Linux b/Build Linux index 56233d51..41e5dea5 100755 --- a/Build Linux +++ b/Build Linux @@ -170,13 +170,15 @@ function update_live_env() { # Memtest86 mkdir -p "$LIVE_DIR/EFI/memtest86/Benchmark" mkdir -p "$TEMP_DIR/memtest86" - curl -Lo "$TEMP_DIR/memtest86/memtest86.iso.tar.gz" "https://www.memtest86.com/downloads/memtest86-iso.tar.gz" - tar xvf "$TEMP_DIR/memtest86/memtest86.iso.tar.gz" -C "$TEMP_DIR/memtest86" - 7z x "$TEMP_DIR/memtest86"/*.iso -o"$TEMP_DIR/memtest86" - mv "$TEMP_DIR/memtest86/EFI/BOOT/BLACKLIS.CFG" "$LIVE_DIR/EFI/memtest86/blacklist.cfg" + curl -Lo "$TEMP_DIR/memtest86/memtest86-usb.zip" "https://www.memtest86.com/downloads/memtest86-usb.zip" + 7z e "$TEMP_DIR/memtest86/memtest86-usb.zip" -o"$TEMP_DIR/memtest86" "memtest86-usb.img" + 7z e "$TEMP_DIR/memtest86/memtest86-usb.img" -o"$TEMP_DIR/memtest86" "MemTest86.img" + 7z x "$TEMP_DIR/memtest86/MemTest86.img" -o"$TEMP_DIR/memtest86" + rm "$TEMP_DIR/memtest86/EFI/BOOT/BOOTIA32.EFI" mv "$TEMP_DIR/memtest86/EFI/BOOT/BOOTX64.EFI" "$LIVE_DIR/EFI/memtest86/memtestx64.efi" - mv "$TEMP_DIR/memtest86/EFI/BOOT/MT86.PNG" "$LIVE_DIR/EFI/memtest86/mt86.png" - mv "$TEMP_DIR/memtest86/EFI/BOOT/UNIFONT.BIN" "$LIVE_DIR/EFI/memtest86/unifont.bin" + for f in "$TEMP_DIR/memtest86/EFI/BOOT"/* "help"/* license.rtf; do + mv "$f" "$LIVE_DIR/EFI/memtest86"/ + done # build.sh if ! grep -iq 'wizardkit additions' "$LIVE_DIR/build.sh"; then From d930bdddbda5a72eccd2bbff88a8b5442b5f6c7e Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 20 Dec 2018 16:10:08 -0700 Subject: [PATCH 121/265] Zero beginning of UFD before formatting * Fixes issue #68 --- .bin/Scripts/build-ufd | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.bin/Scripts/build-ufd b/.bin/Scripts/build-ufd index c606892b..1253472c 100755 --- a/.bin/Scripts/build-ufd +++ b/.bin/Scripts/build-ufd @@ -533,6 +533,9 @@ echo -e "${GREEN}Building Kit${CLEAR}" touch "${LOG_FILE}" tmux split-window -dl 10 tail -f "${LOG_FILE}" +# Zero beginning of device +dd bs=4M count=16 if=/dev/zero of="${DEST_DEV}" >> "${LOG_FILE}" 2>&1 + # Format echo "Formatting drive..." if [[ "${USE_MBR}" == "True" ]]; then From d37923a31cfc7471ac37e2e98efb7b900db7383c Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 20 Dec 2018 17:26:27 -0700 Subject: [PATCH 122/265] Bugfix: typo --- .bin/Scripts/settings/launchers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.bin/Scripts/settings/launchers.py b/.bin/Scripts/settings/launchers.py index 43e8e158..5135ec08 100644 --- a/.bin/Scripts/settings/launchers.py +++ b/.bin/Scripts/settings/launchers.py @@ -212,6 +212,7 @@ LAUNCHERS = { r')', ], }, + }, r'Diagnostics\Extras': { 'AIDA64': { 'L_TYPE': 'Executable', @@ -556,8 +557,7 @@ LAUNCHERS = { 'L_ITEM': 'IObitUninstallerPortable.exe', }, }, - }, -} + } if __name__ == '__main__': print("This file is not meant to be called directly.") From fb772143401dddc5a888314348cece9f5a96bcaf Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 22 Dec 2018 17:52:50 -0700 Subject: [PATCH 123/265] Reworked status/color sections --- .bin/Scripts/functions/hw_diags.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 9f10f997..3642f49c 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -65,6 +65,11 @@ KEY_NVME = 'nvme_smart_health_information_log' KEY_SMART = 'ata_smart_attributes' QUICK_LABEL = '{YELLOW}(Quick){CLEAR}'.format(**COLORS) SIDE_PANE_WIDTH = 20 +STATUSES = { + 'RED': ['Denied', 'ERROR', 'NS', 'OVERRIDE', 'TimedOut'], + 'YELLOW': ['Aborted', 'N/A', 'Skipped', 'Unknown', 'Working'], + 'GREEN': ['CS'], +} TESTS_CPU = ['Prime95'] TESTS_DISK = [ 'I/O Benchmark', @@ -78,7 +83,10 @@ TMUX_LAYOUT = OrderedDict({ 'Progress': {'x': SIDE_PANE_WIDTH, 'Check': True}, }) -# Error Classe +# Regex +REGEX_ERROR_STATUS = re.compile('|'.join(STATUSES['RED'])) + +# Error Classes class DeviceTooSmallError(Exception): pass @@ -566,7 +574,8 @@ class TestObj(): def update_status(self, new_status=None): """Update status strings.""" - if self.disabled or re.search(r'ERROR|OVERRIDE', self.status): + if self.disabled or REGEX_ERROR_STATUS.search(self.status): + # Don't update error statuses if test is enabled return if new_status: self.status = build_status_string( @@ -603,12 +612,9 @@ def build_outer_panes(state): def build_status_string(label, status, info_label=False): """Build status string with appropriate colors.""" status_color = COLORS['CLEAR'] - if status in ['Denied', 'ERROR', 'NS', 'OVERRIDE', 'TimedOut']: - status_color = COLORS['RED'] - elif status in ['Aborted', 'N/A', 'Skipped', 'Unknown', 'Working']: - status_color = COLORS['YELLOW'] - elif status in ['CS']: - status_color = COLORS['GREEN'] + for k, v in STATUSES.items(): + if status in v: + status_color = COLORS[k] return '{l_c}{l}{CLEAR}{s_c}{s:>{s_w}}{CLEAR}'.format( l_c=COLORS['BLUE'] if info_label else '', From 6d9f50629cff3e4ad60ce59abbc4edfa424229e6 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 22 Dec 2018 17:55:49 -0700 Subject: [PATCH 124/265] Reworked status/color sections --- .bin/Scripts/functions/hw_diags.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 9f10f997..3642f49c 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -65,6 +65,11 @@ KEY_NVME = 'nvme_smart_health_information_log' KEY_SMART = 'ata_smart_attributes' QUICK_LABEL = '{YELLOW}(Quick){CLEAR}'.format(**COLORS) SIDE_PANE_WIDTH = 20 +STATUSES = { + 'RED': ['Denied', 'ERROR', 'NS', 'OVERRIDE', 'TimedOut'], + 'YELLOW': ['Aborted', 'N/A', 'Skipped', 'Unknown', 'Working'], + 'GREEN': ['CS'], +} TESTS_CPU = ['Prime95'] TESTS_DISK = [ 'I/O Benchmark', @@ -78,7 +83,10 @@ TMUX_LAYOUT = OrderedDict({ 'Progress': {'x': SIDE_PANE_WIDTH, 'Check': True}, }) -# Error Classe +# Regex +REGEX_ERROR_STATUS = re.compile('|'.join(STATUSES['RED'])) + +# Error Classes class DeviceTooSmallError(Exception): pass @@ -566,7 +574,8 @@ class TestObj(): def update_status(self, new_status=None): """Update status strings.""" - if self.disabled or re.search(r'ERROR|OVERRIDE', self.status): + if self.disabled or REGEX_ERROR_STATUS.search(self.status): + # Don't update error statuses if test is enabled return if new_status: self.status = build_status_string( @@ -603,12 +612,9 @@ def build_outer_panes(state): def build_status_string(label, status, info_label=False): """Build status string with appropriate colors.""" status_color = COLORS['CLEAR'] - if status in ['Denied', 'ERROR', 'NS', 'OVERRIDE', 'TimedOut']: - status_color = COLORS['RED'] - elif status in ['Aborted', 'N/A', 'Skipped', 'Unknown', 'Working']: - status_color = COLORS['YELLOW'] - elif status in ['CS']: - status_color = COLORS['GREEN'] + for k, v in STATUSES.items(): + if status in v: + status_color = COLORS[k] return '{l_c}{l}{CLEAR}{s_c}{s:>{s_w}}{CLEAR}'.format( l_c=COLORS['BLUE'] if info_label else '', From c15eb85a5e46c881c4d4ca9b0e821cf1cb3aafc2 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 22 Dec 2018 18:07:06 -0700 Subject: [PATCH 125/265] Removed unused get_status_color and Skipped status --- .bin/Scripts/functions/hw_diags.py | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 3642f49c..c5002882 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -67,7 +67,7 @@ QUICK_LABEL = '{YELLOW}(Quick){CLEAR}'.format(**COLORS) SIDE_PANE_WIDTH = 20 STATUSES = { 'RED': ['Denied', 'ERROR', 'NS', 'OVERRIDE', 'TimedOut'], - 'YELLOW': ['Aborted', 'N/A', 'Skipped', 'Unknown', 'Working'], + 'YELLOW': ['Aborted', 'N/A', 'Unknown', 'Working'], 'GREEN': ['CS'], } TESTS_CPU = ['Prime95'] @@ -732,17 +732,6 @@ def get_read_rate(s): real_rate = convert_to_bytes(human_rate) return real_rate -def get_status_color(s): - """Get color based on status, returns str.""" - color = COLORS['CLEAR'] - if s in ['Denied', 'ERROR', 'NS', 'OVERRIDE']: - color = COLORS['RED'] - elif s in ['Aborted', 'N/A', 'Unknown', 'Working', 'Skipped']: - color = COLORS['YELLOW'] - elif s in ['CS']: - color = COLORS['GREEN'] - return color - def menu_diags(state, args): """Main menu to select and run HW tests.""" args = [a.lower() for a in args] From 44bde68803d31eecd2f980f86d99d13147c92ec7 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 22 Dec 2018 18:08:21 -0700 Subject: [PATCH 126/265] Removed unused get_status_color and Skipped status --- .bin/Scripts/functions/hw_diags.py | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 3642f49c..c5002882 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -67,7 +67,7 @@ QUICK_LABEL = '{YELLOW}(Quick){CLEAR}'.format(**COLORS) SIDE_PANE_WIDTH = 20 STATUSES = { 'RED': ['Denied', 'ERROR', 'NS', 'OVERRIDE', 'TimedOut'], - 'YELLOW': ['Aborted', 'N/A', 'Skipped', 'Unknown', 'Working'], + 'YELLOW': ['Aborted', 'N/A', 'Unknown', 'Working'], 'GREEN': ['CS'], } TESTS_CPU = ['Prime95'] @@ -732,17 +732,6 @@ def get_read_rate(s): real_rate = convert_to_bytes(human_rate) return real_rate -def get_status_color(s): - """Get color based on status, returns str.""" - color = COLORS['CLEAR'] - if s in ['Denied', 'ERROR', 'NS', 'OVERRIDE']: - color = COLORS['RED'] - elif s in ['Aborted', 'N/A', 'Unknown', 'Working', 'Skipped']: - color = COLORS['YELLOW'] - elif s in ['CS']: - color = COLORS['GREEN'] - return color - def menu_diags(state, args): """Main menu to select and run HW tests.""" args = [a.lower() for a in args] From 2750440c29ac08d71a3fab79639aea9f4a853033 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 22 Dec 2018 23:42:57 -0700 Subject: [PATCH 127/265] Readded osTicket functions --- .bin/Scripts/functions/hw_diags.py | 3 + .bin/Scripts/functions/osticket.py | 178 +++++++++++++++++++++++++++++ .bin/Scripts/settings/main.py | 7 -- .bin/Scripts/settings/osticket.py | 33 ++++++ 4 files changed, 214 insertions(+), 7 deletions(-) create mode 100644 .bin/Scripts/functions/osticket.py create mode 100644 .bin/Scripts/settings/osticket.py diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index c5002882..c1e0fefa 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -4,7 +4,10 @@ import json import re import time +# TODO: Still need functions.data ? from collections import OrderedDict +from functions.data import * +from functions.osticket import * from functions.sensors import * from functions.tmux import * diff --git a/.bin/Scripts/functions/osticket.py b/.bin/Scripts/functions/osticket.py new file mode 100644 index 00000000..0d1561c0 --- /dev/null +++ b/.bin/Scripts/functions/osticket.py @@ -0,0 +1,178 @@ +# Wizard Kit: Functions - osTicket + +import mysql.connector as mariadb + +from functions.common import * +from settings.osticket import * + +# Classes +class osTicket(): + """Class to track osTicket data and functions.""" + def __init__(self): + self.db_connection = None + self.db_cursor = None + self.errors = False + self.tunnel_proc = None + + def connect(self): + """Establish connection to osTicket via a SSH tunnel.""" + cmd = [ + 'ssh', '-N', + '-p', OSTICKET['SSH']['Port'], + '-L3306:127.0.0.1:{Port}'.format(**OSTICKET['Database']), + '{User}@{Host}'.format(**OSTICKET['SSH']), + ] + + # Only open tunnel if one doesn't exist + if self.tunnel_proc is None or self.tunnel_proc.poll() is not None: + self.tunnel_proc = popen_program(cmd) + + # Connect to database + for x in range(5): + sleep(2) + try: + self.db_connection = mariadb.connect( + user=OSTICKET['Database']['User'], + password=OSTICKET['Database']['Pass'], + database=OSTICKET['Database']['Name'], + ) + self.db_cursor = self.db_connection.cursor() + except Exception: + # TODO: Refine exception handling + pass + else: + # Connection established + break + + def disconnect(self, reset_errors=False): + """Close osTicket connection.""" + try: + self.db_cursor.close() + self.db_connection.close() + except Exception: + # TODO: Fix exception handling + pass + + # Reset errors + if reset_errors: + self.errors = False + + # Reset vars + self.db_cursor = None + self.db_connection = None + + def get_ticket_name(self, ticket_id): + """Lookup ticket and return name as str.""" + name = None + sql_cmd = "SELECT name FROM `{Ticket}`".format(**OSTICKET['Tables']) + sql_cmd += " WHERE `ticket_id` = `{}`".format(ticket_id) + sql_cmd += ";" + # TODO: Is the ';' needed above? It wasn't in the prev version?? + + # Lookup name + # NOTE: If multiple entries are found it will return the last + try: + self.db_cursor.execute(sql_cmd) + for s in self.db_cursor: + name = s[0] + except Exception: + # TODO: Fix exception handling + self.errors = True + + def get_ticket_number(self): + """Get ticket number and confirm with name from osTicket DB.""" + ticket_number = None + + # Main loop + while ticket_number is None: + print_standard(' ') + _input = input('Enter ticket number (or leave blank to disable): ') + _input = _input.strip() + + # No ticket ID entered + if re.match(r'^\s*$', _input): + if ask('Disable osTicket integration for this run?'): + break + + # Invalid ID entered + if not re.match(r'^([0-9]+)$', _input): + continue + + # Valid ID entered, lookup name and verify + _name = self.get_ticket_name(_input) + if _name: + print_standard('You have selected ticket #{} {}'.format( + _input, _name)) + if ask('Is this correct?'): + ticket_number = _input + + # Done + return ticket_number + + def post_response(self, ticket_id, response): + """Post a reply to a ticket in osTicket.""" + self.connect() + + # Build SQL cmd + sql_cmd = "INSERT INTO `{Name}`.`{Response}`".format( + **OSTICKET['Database'], **OSTICKET['Tables']) + sql_cmd += " (ticket_id, staff_id, staff_name, response, created)" + sql_cmd += " VALUES (" + sql_cmd += " '{}',".format(ticket_id) + sql_cmd += " '{ID}', '{Name}',".format(**OSTICKET['Staff']) + sql_cmd += " '{}',".format(response) + sql_cmd += " '{}'".format(time.strftime("%Y-%m-%d %H:%M:%S")) + sql_cmd += " );" + + # Run SQL cmd + try: + self.cursor.execute(sql_cmd) + except Exception: + # TODO: Fix exception handling + self.errors = True + + # Done + self.disconnect() + + def set_disk_failed(self, ticket_id): + """Mark disk as failed in osTicket.""" + self.set_flag( + ticket_id, + OSTICKET['Disk Flag']['Name'], + OSTICKET['Disk Flag']['Fail']) + + def set_disk_passed(self, ticket_id): + """Mark disk as passed in osTicket.""" + self.set_flag( + ticket_id, + OSTICKET['Disk Flag']['Name'], + OSTICKET['Disk Flag']['Pass']) + + def set_flag(self, ticket_id, flag_name, flag_value): + """Set flag in osTicket.""" + self.connect() + + # Build SQL cmd + sql_cmd = "UPDATE `{Name}`.`{Ticket}`".format( + **OSTICKET['Database'], **OSTICKET['Tables']) + sql_cmd += " SET `{}` = `{}`".format(flag_name, flag_value) + sql_cmd += " WHERE `{Ticket}`.`ticket_id` = `{ticket_id}`".format( + ticket_id=ticket_id, **OSTICKET['Tables']) + sql_cmd += ";" + + # Run SQL cmd + try: + self.cursor.execute(sql_cmd) + except Exception: + # TODO: Fix exception handling + self.errors = True + + # Done + self.disconnect() + +# Functions + +if __name__ == '__main__': + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/settings/main.py b/.bin/Scripts/settings/main.py index e6aff08f..5e9002f5 100644 --- a/.bin/Scripts/settings/main.py +++ b/.bin/Scripts/settings/main.py @@ -14,13 +14,6 @@ ARCHIVE_PASSWORD='Sorted1201' KIT_NAME_FULL='1201-WizardKit' KIT_NAME_SHORT='1201' SUPPORT_MESSAGE='Please let support know by opening an issue on Gogs' -# osTicket -DB_HOST='osticket.1201.com' -DB_NAME='osticket' -DB_USER='wizardkit' -DB_PASS='U9bJnF9eamVkfsVw' -SSH_PORT='22' -SSH_USER='sql_tunnel' # imgur IMGUR_CLIENT_ID='3d1ee1d38707b85' # Live Linux diff --git a/.bin/Scripts/settings/osticket.py b/.bin/Scripts/settings/osticket.py new file mode 100644 index 00000000..fe998eb2 --- /dev/null +++ b/.bin/Scripts/settings/osticket.py @@ -0,0 +1,33 @@ +# Wizard Kit: Settings - osTicket + +OSTICKET = { + 'Database': { + 'Name': 'osticket', + 'User': 'wizardkit', + 'Pass': 'U9bJnF9eamVkfsVw', + 'Port': '3306', + }, + 'Disk Flag': { + 'Name': 'zHDTune', + 'Pass': 1, + 'Fail': 2, + }, + 'SSH': { + 'Host': 'osticket.1201.com', + 'Port': '22', + 'User': 'sql_tunnel', + }, + 'Staff': { + 'ID': '23', + 'Name': 'Wizard Kit', + }, + 'Tables': { + 'Response': 'ost_ticket_response', + 'Ticket': 'ost_ticket', + }, + } + +if __name__ == '__main__': + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From ac40f6169548c62c39974a0c608affad930d8388 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 22 Dec 2018 23:47:30 -0700 Subject: [PATCH 128/265] Readded Gnuplot and image upload functions --- .bin/Scripts/functions/hw_diags.py | 1 + .bin/Scripts/functions/png_graph.py | 105 ++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 .bin/Scripts/functions/png_graph.py diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index c1e0fefa..ea94e457 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -7,6 +7,7 @@ import time # TODO: Still need functions.data ? from collections import OrderedDict from functions.data import * +from functions.png_graph import * from functions.osticket import * from functions.sensors import * from functions.tmux import * diff --git a/.bin/Scripts/functions/png_graph.py b/.bin/Scripts/functions/png_graph.py new file mode 100644 index 00000000..e429b9cc --- /dev/null +++ b/.bin/Scripts/functions/png_graph.py @@ -0,0 +1,105 @@ +# Wizard Kit: Functions - PNG graph for I/O Benchmark + +import base64 +import Gnuplot +import math + +from functions.common import * + +# Functions +def export_png_graph(name, dev): + """Exports PNG graph using gnuplot, returns file path as str.""" + max_rate = max(TESTS['iobenchmark']['Data'][name]['Read Rates']) + max_rate /= (1024**2) + max_rate = max(800, max_rate) + out_path = '{}/iobenchmark-{}.png'.format(global_vars['LogDir'], name) + plot_data = '{}/iobenchmark-{}-raw.log'.format(global_vars['LogDir'], name) + + # Adjust Y-axis range to either 1000 or roughly max rate + 200 + ## Round up to the nearest 100 and then add 200 + y_range = (math.ceil(max_rate/100)*100) + 200 + + # Run gnuplot commands + g = Gnuplot.Gnuplot() + g('reset') + g('set output "{}"'.format(out_path)) + g('set terminal png large size 660,300 truecolor font "Noto Sans,11"') + g('set title "I/O Benchmark"') + g('set yrange [0:{}]'.format(y_range)) + g('set style data lines') + g('plot "{data}" title "{size} ({tran}) {model} {serial}"'.format( + data=plot_data, + size=dev['lsblk'].get('size', '???b'), + tran=dev['lsblk'].get('tran', '???'), + model=dev['lsblk'].get('model', 'Unknown Model'), + serial=dev['lsblk'].get('serial', 'Unknown Serial'), + )) + + # Cleanup + g.close() + del(g) + + return out_path + +def upload_to_imgur(image_path): + """Upload image to Imgur and return image url as str.""" + image_data = None + image_link = None + + # Bail early + if not image_path: + raise GenericError + + # Read image file and convert to base64 then convert to str + with open(image_path, 'rb') as f: + image_data = base64.b64encode(f.read()).decode() + + # POST image + url = "https://api.imgur.com/3/image" + boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW' + payload = ('--{boundary}\r\nContent-Disposition: form-data; ' + 'name="image"\r\n\r\n{data}\r\n--{boundary}--') + payload = payload.format(boundary=boundary, data=image_data) + headers = { + 'content-type': 'multipart/form-data; boundary={}'.format(boundary), + 'Authorization': 'Client-ID {}'.format(IMGUR_CLIENT_ID), + } + response = requests.request("POST", url, data=payload, headers=headers) + + # Return image link + if response.ok: + json_data = json.loads(response.text) + image_link = json_data['data']['link'] + return image_link + +def upload_to_nextcloud(image_path, ticket_number, dev_name): + """Upload image to Nextcloud server and return folder url as str.""" + image_data = None + + # Bail early + if not image_path: + raise GenericError + + # Read image file and convert to base64 + with open(image_path, 'rb') as f: + image_data = f.read() + + # PUT image + url = '{base_url}/{ticket_number}_iobenchmark_{dev_name}_{date}.png'.format( + base_url=BENCHMARK_SERVER['Url'], + ticket_number=ticket_number, + dev_name=dev_name, + date=global_vars.get('Date-Time', 'Unknown Date-Time')) + requests.put( + url, + data=image_data, + headers = {'X-Requested-With': 'XMLHttpRequest'}, + auth = (BENCHMARK_SERVER['User'], BENCHMARK_SERVER['Pass'])) + + # Return folder link + return BENCHMARK_SERVER['Short Url'] + +if __name__ == '__main__': + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From 6e37736146e6c97008e324f2b4d4df647984242e Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sun, 23 Dec 2018 17:15:50 -0700 Subject: [PATCH 129/265] Only save attributes to log during show_results() --- .bin/Scripts/functions/hw_diags.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index c5002882..5e9e712b 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -242,7 +242,9 @@ class DiskObj(): print_standard(' (Have you tried swapping the disk cable?)') else: # Override? - show_report(self.generate_attribute_report(description=True)) + show_report( + self.generate_attribute_report(description=True), + log_report=True) print_warning(' {} error(s) detected.'.format(attr_type)) if override_disabled: print_standard('Tests disabled for this device') @@ -1448,8 +1450,6 @@ def run_nvme_smart_tests(state, test): # Show attributes clear_screen() - print_info('Device ({})'.format(test.dev.name)) - print_standard(' {}'.format(test.dev.description)) show_report(test.dev.generate_attribute_report()) print_standard(' ') @@ -1537,11 +1537,12 @@ def secret_screensaver(screensaver=None): raise Exception('Invalid screensaver') run_program(cmd, check=False, pipe=False) -def show_report(report): - """Show report on screen and save to log w/out color.""" +def show_report(report, log_report=False): + """Show report on screen and optionally save to log w/out color.""" for line in report: print(line) - print_log(strip_colors(line)) + if log_report: + print_log(strip_colors(line)) def show_results(state): """Show results for all tests.""" @@ -1556,7 +1557,7 @@ def show_results(state): _enabled |= state.tests[k]['Enabled'] if _enabled: print_success('CPU:'.format(k)) - show_report(state.cpu.generate_cpu_report()) + show_report(state.cpu.generate_cpu_report(), log_report=True) print_standard(' ') # Disk tests @@ -1567,7 +1568,7 @@ def show_results(state): print_success('Disk{}:'.format( '' if len(state.disks) == 1 else 's')) for disk in state.disks: - show_report(disk.generate_disk_report()) + show_report(disk.generate_disk_report(), log_report=True) print_standard(' ') def update_main_options(state, selection, main_options): From 96d34ceb5038549ffa09451f46a95b3a4598c98e Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sun, 23 Dec 2018 17:33:16 -0700 Subject: [PATCH 130/265] Fix SMART short-test results section * OVERRIDE status reduced to yellow/warning * Allows it to be elevated to NS or TimedOut * Only disable other disk tests on test.failed * OVERRIDE doesn't work if based on test.passed for this test --- .bin/Scripts/functions/hw_diags.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 5e9e712b..cbfd4377 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -66,8 +66,8 @@ KEY_SMART = 'ata_smart_attributes' QUICK_LABEL = '{YELLOW}(Quick){CLEAR}'.format(**COLORS) SIDE_PANE_WIDTH = 20 STATUSES = { - 'RED': ['Denied', 'ERROR', 'NS', 'OVERRIDE', 'TimedOut'], - 'YELLOW': ['Aborted', 'N/A', 'Unknown', 'Working'], + 'RED': ['Denied', 'ERROR', 'NS', 'TimedOut'], + 'YELLOW': ['Aborted', 'N/A', 'OVERRIDE', 'Unknown', 'Working'], 'GREEN': ['CS'], } TESTS_CPU = ['Prime95'] @@ -1513,7 +1513,7 @@ def run_nvme_smart_tests(state, test): test.update_status('TimedOut') # Disable other drive tests if necessary - if not test.passed: + if test.failed: for t in ['badblocks', 'I/O Benchmark']: test.dev.disable_test(t, 'Denied') From 57572c752782fa7d0aa8ad9c349ed27ba3a57320 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 24 Dec 2018 17:10:12 -0700 Subject: [PATCH 131/265] Added osTicket report sections --- .bin/Scripts/functions/hw_diags.py | 1 + .bin/Scripts/functions/osticket.py | 161 +++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index f516e5cc..48962299 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -102,6 +102,7 @@ class CpuObj(): self.tests = OrderedDict() self.get_details() self.name = self.lscpu.get('Model name', 'Unknown CPU') + self.description = self.name def get_details(self): """Get CPU details from lscpu.""" diff --git a/.bin/Scripts/functions/osticket.py b/.bin/Scripts/functions/osticket.py index 0d1561c0..8984be90 100644 --- a/.bin/Scripts/functions/osticket.py +++ b/.bin/Scripts/functions/osticket.py @@ -5,6 +5,11 @@ import mysql.connector as mariadb from functions.common import * from settings.osticket import * +# Regex +REGEX_BLOCK_GRAPH = re.compile(r'(▁|▂|▃|▄|▅|▆|▇|█)') +REGEX_NVME_SMART_ATTRIBUTES = re.compile(r'^\s*(\d+) / (\w+): (.{28})(.*)$') +REGEX_TEMPS = re.compile(r'^\s*(.*?)\s+(idle.*)$') + # Classes class osTicket(): """Class to track osTicket data and functions.""" @@ -171,6 +176,162 @@ class osTicket(): self.disconnect() # Functions +def convert_report(name, test): + """Convert report into an osTicket friendly format, returns list.""" + out_report = [] + source_report = test.source_report + status = strip_colors(test.status) + status = status.replace(test.label, '').strip() + + # Header + index = 1 + if name == 'NVMe / SMART': + out_report.append('{} ({})'.format(name, status)) + if not source_report: + index = 0 + source_report = test.dev.generate_attribute_source_report() + else: + out_report.append('{} ({})'.format(strip_colors(source_report[0]), status)) + + # Body + for line in source_report[index:]: + # Remove colors and leading spaces + line = strip_colors(line) + if line[:2] == ' ': + line = line[2:] + + # Test-specific modifications + if name == 'Prime95': + r = REGEX_TEMPS.match(line) + if r: + _sensor = '{:<20}'.format(r.group(1)) + _temps = r.group(2) + line = '{} {}'.format( + pad_with_dots(_sensor, pad_right=True), + _temps) + elif name == 'NVMe / SMART': + r = REGEX_NVME_SMART_ATTRIBUTES.match(line) + if r: + _dec = '{:>3}'.format(r.group(1)) + _hex = r.group(2) + _atr = r.group(3).strip() + _val = '{:<20}'.format(r.group(4)) + line = '{}/{}: {} {}'.format( + _hex, + pad_with_dots(_dec), + pad_with_dots(_val, pad_right=True), + _atr) + elif name == 'I/O Benchmark': + line = REGEX_BLOCK_GRAPH.sub('', line) + line = line.strip() + if not line: + continue + + # Remove extra spaces + line = line.strip() + line = re.sub(r'(\s+)', ' ', line) + + # Add line to report + out_report.append(line) + + # Done + return out_report + +def get_device_overall_results(dev): + """Get overall results from tests for device, returns dict.""" + results = { + 'Dev Type': 'Unknown', + 'Full Diag': False, + 'Asterisk': None, + 'Failed': 0, + 'N/A': 0, + 'Passed': 0, + 'Status': 'Unknown', + } + + # Get test list for device type + test_list = [] + if isinstance(dev, CpuObj): + results['Dev Type'] = 'CPU' + test_list = TESTS_CPU + elif isinstance(dev, DiskObj): + results['Dev Type'] = 'Disk' + test_list = TESTS_DISK + else: + raise GenericError('Unrecognized device type.') + + # Check if a full diag was run (i.e. all dev tests were enabled) + results['Full Diag'] = len(dev.tests) == len(test_list) + + # Tally test results + for test in dev.tests.value(): + if test.failed: + results['Failed'] += 1 + if test.passed: + results['Passed'] += 1 + if 'N/A' in test.status: + results['N/A'] += 1 + + # Set overall status + if results['Failed'] > 0: + dev.checkbox = False + results['Status'] = 'FAILED' + elif results['Passed'] + results['N/A'] == len(dev.tests): + dev.checkbox = True + results['Status'] = 'PASSED' + else: + results['Status'] = 'UNKNOWN' + if results['Full Diag'] and results['N/A'] > 0: + results['Asterisk'] = True + results['Status'] += '*' + + # Done + return results + +def generate_osticket_report(dev): + """Generate device report for osTicket, returns list.""" + report = [] + results = get_device_overall_results(dev) + + # Header + if results['Full Diag']: + report.append( + '{Dev Type} hardware diagnostic tests: {Status}'.format(**results)) + report.append(' ') + + # Device + report.append(dev.description) + report.append(' ') + + # Test reports + for name, test in dev.tests.items(): + report.extend(convert_report(name, test)) + if name == 'I/O Benchmark': + # TODO: Create PNG graph and upload to imgur/Nextcloud + report.append('Imgur: TODO') + report.append('Nextcloud: TODO') + report.append(' ') + + # Volumes + if results['Dev Type'] == 'Disk': + # TODO: Mount all volumes and extend report + report.append('Volumes:') + report.append('TODO') + report.append(' ') + + # Asterisk + if results['Asterisk']: + report.append('* NOTE: One or more tests were not run on this device') + +def pad_with_dots(s, pad_right=False): + """Replace space padding with dots, returns str.""" + s = str(s).replace(' ', '..') + if '.' in s: + if pad_right: + s = s + '.' + else: + s = '.' + s + return s if __name__ == '__main__': print("This file is not meant to be called directly.") From ad6980f82b2d19f568b4a1ca7bddca5a482630f5 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 24 Dec 2018 17:33:54 -0700 Subject: [PATCH 132/265] Moved report functions into osTicket object --- .bin/Scripts/functions/osticket.py | 202 +++++++++++++++-------------- 1 file changed, 105 insertions(+), 97 deletions(-) diff --git a/.bin/Scripts/functions/osticket.py b/.bin/Scripts/functions/osticket.py index 8984be90..ccfc59bc 100644 --- a/.bin/Scripts/functions/osticket.py +++ b/.bin/Scripts/functions/osticket.py @@ -49,6 +49,105 @@ class osTicket(): # Connection established break + def convert_report(name, test): + """Convert report into an osTicket friendly format, returns list.""" + out_report = [] + source_report = test.source_report + status = strip_colors(test.status) + status = status.replace(test.label, '').strip() + + # Header + index = 1 + if name == 'NVMe / SMART': + out_report.append('{} ({})'.format(name, status)) + if not source_report: + index = 0 + source_report = test.dev.generate_attribute_source_report() + else: + out_report.append('{} ({})'.format(strip_colors(source_report[0]), status)) + + # Body + for line in source_report[index:]: + # Remove colors and leading spaces + line = strip_colors(line) + if line[:2] == ' ': + line = line[2:] + + # Test-specific modifications + if name == 'Prime95': + r = REGEX_TEMPS.match(line) + if r: + _sensor = '{:<20}'.format(r.group(1)) + _temps = r.group(2) + line = '{} {}'.format( + pad_with_dots(_sensor, pad_right=True), + _temps) + elif name == 'NVMe / SMART': + r = REGEX_NVME_SMART_ATTRIBUTES.match(line) + if r: + _dec = '{:>3}'.format(r.group(1)) + _hex = r.group(2) + _atr = r.group(3).strip() + _val = '{:<20}'.format(r.group(4)) + line = '{}/{}: {} {}'.format( + _hex, + pad_with_dots(_dec), + pad_with_dots(_val, pad_right=True), + _atr) + elif name == 'I/O Benchmark': + line = REGEX_BLOCK_GRAPH.sub('', line) + line = line.strip() + if not line: + continue + + # Remove extra spaces + line = line.strip() + line = re.sub(r'(\s+)', ' ', line) + + # Add line to report + out_report.append(line) + + # Done + return out_report + + def generate_report(dev): + """Generate device report for osTicket, returns list.""" + report = [] + results = get_device_overall_results(dev) + + # Header + if results['Full Diag']: + report.append( + '{Dev Type} hardware diagnostic tests: {Status}'.format(**results)) + report.append(' ') + + # Device + report.append(dev.description) + report.append(' ') + + # Test reports + for name, test in dev.tests.items(): + report.extend(convert_report(name, test)) + if name == 'I/O Benchmark': + # TODO: Create PNG graph and upload to imgur/Nextcloud + report.append('Imgur: TODO') + report.append('Nextcloud: TODO') + report.append(' ') + + # Volumes + if results['Dev Type'] == 'Disk': + # TODO: Mount all volumes and extend report + report.append('Volumes:') + report.append('TODO') + report.append(' ') + + # Asterisk + if results['Asterisk']: + report.append('* NOTE: One or more tests were not run on this device') + + # Done + return report + def disconnect(self, reset_errors=False): """Close osTicket connection.""" try: @@ -114,7 +213,12 @@ class osTicket(): # Done return ticket_number - def post_response(self, ticket_id, response): + def post_device_results(self, dev, ticket_id): + """Generate osTicket friendly report and post as response to ticket.""" + response = self.generate_report(dev) + post_response(response, ticket_id) + + def post_response(self, response, ticket_id): """Post a reply to a ticket in osTicket.""" self.connect() @@ -176,67 +280,6 @@ class osTicket(): self.disconnect() # Functions -def convert_report(name, test): - """Convert report into an osTicket friendly format, returns list.""" - out_report = [] - source_report = test.source_report - status = strip_colors(test.status) - status = status.replace(test.label, '').strip() - - # Header - index = 1 - if name == 'NVMe / SMART': - out_report.append('{} ({})'.format(name, status)) - if not source_report: - index = 0 - source_report = test.dev.generate_attribute_source_report() - else: - out_report.append('{} ({})'.format(strip_colors(source_report[0]), status)) - - # Body - for line in source_report[index:]: - # Remove colors and leading spaces - line = strip_colors(line) - if line[:2] == ' ': - line = line[2:] - - # Test-specific modifications - if name == 'Prime95': - r = REGEX_TEMPS.match(line) - if r: - _sensor = '{:<20}'.format(r.group(1)) - _temps = r.group(2) - line = '{} {}'.format( - pad_with_dots(_sensor, pad_right=True), - _temps) - elif name == 'NVMe / SMART': - r = REGEX_NVME_SMART_ATTRIBUTES.match(line) - if r: - _dec = '{:>3}'.format(r.group(1)) - _hex = r.group(2) - _atr = r.group(3).strip() - _val = '{:<20}'.format(r.group(4)) - line = '{}/{}: {} {}'.format( - _hex, - pad_with_dots(_dec), - pad_with_dots(_val, pad_right=True), - _atr) - elif name == 'I/O Benchmark': - line = REGEX_BLOCK_GRAPH.sub('', line) - line = line.strip() - if not line: - continue - - # Remove extra spaces - line = line.strip() - line = re.sub(r'(\s+)', ' ', line) - - # Add line to report - out_report.append(line) - - # Done - return out_report - def get_device_overall_results(dev): """Get overall results from tests for device, returns dict.""" results = { @@ -288,41 +331,6 @@ def get_device_overall_results(dev): # Done return results -def generate_osticket_report(dev): - """Generate device report for osTicket, returns list.""" - report = [] - results = get_device_overall_results(dev) - - # Header - if results['Full Diag']: - report.append( - '{Dev Type} hardware diagnostic tests: {Status}'.format(**results)) - report.append(' ') - - # Device - report.append(dev.description) - report.append(' ') - - # Test reports - for name, test in dev.tests.items(): - report.extend(convert_report(name, test)) - if name == 'I/O Benchmark': - # TODO: Create PNG graph and upload to imgur/Nextcloud - report.append('Imgur: TODO') - report.append('Nextcloud: TODO') - report.append(' ') - - # Volumes - if results['Dev Type'] == 'Disk': - # TODO: Mount all volumes and extend report - report.append('Volumes:') - report.append('TODO') - report.append(' ') - - # Asterisk - if results['Asterisk']: - report.append('* NOTE: One or more tests were not run on this device') - def pad_with_dots(s, pad_right=False): """Replace space padding with dots, returns str.""" s = str(s).replace(' ', '..') From 8d6b29be53c50cbd7aabafe00c60e7831a8d0145 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 24 Dec 2018 21:11:13 -0700 Subject: [PATCH 133/265] Posting CPU results is working --- .bin/Scripts/functions/hw_diags.py | 1 + .bin/Scripts/functions/osticket.py | 160 +++++++++++++++++------------ 2 files changed, 95 insertions(+), 66 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 48962299..b50744aa 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -138,6 +138,7 @@ class CpuObj(): class DiskObj(): """Object for tracking disk specific data.""" def __init__(self, disk_path): + self.checkbox = None self.disk_ok = True self.labels = [] self.lsblk = {} diff --git a/.bin/Scripts/functions/osticket.py b/.bin/Scripts/functions/osticket.py index ccfc59bc..fb5649ba 100644 --- a/.bin/Scripts/functions/osticket.py +++ b/.bin/Scripts/functions/osticket.py @@ -5,18 +5,24 @@ import mysql.connector as mariadb from functions.common import * from settings.osticket import * +# STATIC VARIABLES +KNOWN_DEV_TYPES = ('CPU', 'Disk') + # Regex REGEX_BLOCK_GRAPH = re.compile(r'(▁|▂|▃|▄|▅|▆|▇|█)') REGEX_NVME_SMART_ATTRIBUTES = re.compile(r'^\s*(\d+) / (\w+): (.{28})(.*)$') REGEX_TEMPS = re.compile(r'^\s*(.*?)\s+(idle.*)$') +REGEX_SENSOR = re.compile(r'^(.*?)(\s*)$') # Classes class osTicket(): """Class to track osTicket data and functions.""" - def __init__(self): + def __init__(self, tests_cpu, tests_disk): self.db_connection = None self.db_cursor = None self.errors = False + self.tests_cpu = tests_cpu + self.tests_disk = tests_disk self.tunnel_proc = None def connect(self): @@ -49,10 +55,10 @@ class osTicket(): # Connection established break - def convert_report(name, test): + def convert_report(self, name, test): """Convert report into an osTicket friendly format, returns list.""" out_report = [] - source_report = test.source_report + source_report = test.report status = strip_colors(test.status) status = status.replace(test.label, '').strip() @@ -62,7 +68,7 @@ class osTicket(): out_report.append('{} ({})'.format(name, status)) if not source_report: index = 0 - source_report = test.dev.generate_attribute_source_report() + source_report = test.dev.generate_attribute_report() else: out_report.append('{} ({})'.format(strip_colors(source_report[0]), status)) @@ -79,9 +85,10 @@ class osTicket(): if r: _sensor = '{:<20}'.format(r.group(1)) _temps = r.group(2) - line = '{} {}'.format( - pad_with_dots(_sensor, pad_right=True), - _temps) + r2 = REGEX_SENSOR.match(_sensor) + _sensor = r2.group(1) + _spacer = pad_with_dots(r2.group(2)) + line = '{}{} {}'.format(_sensor, _spacer, _temps) elif name == 'NVMe / SMART': r = REGEX_NVME_SMART_ATTRIBUTES.match(line) if r: @@ -110,10 +117,10 @@ class osTicket(): # Done return out_report - def generate_report(dev): + def generate_report(self, dev): """Generate device report for osTicket, returns list.""" report = [] - results = get_device_overall_results(dev) + results = self.get_device_overall_results(dev) # Header if results['Full Diag']: @@ -127,7 +134,7 @@ class osTicket(): # Test reports for name, test in dev.tests.items(): - report.extend(convert_report(name, test)) + report.extend(self.convert_report(name, test)) if name == 'I/O Benchmark': # TODO: Create PNG graph and upload to imgur/Nextcloud report.append('Imgur: TODO') @@ -165,11 +172,74 @@ class osTicket(): self.db_cursor = None self.db_connection = None + def get_device_overall_results(self, dev): + """Get overall results from tests for device, returns dict.""" + results = { + 'Dev Type': self.get_device_type(dev), + 'Full Diag': False, + 'Asterisk': None, + 'Failed': 0, + 'N/A': 0, + 'Passed': 0, + 'Status': 'Unknown', + } + + # Bail on unknown device type + if results['Dev Type'] not in KNOWN_DEV_TYPES: + raise GenericError( + 'Unrecognized device type: {}.'.format(results['Dev Type'])) + + # Get test list for device type + test_list = [] + if results['Dev Type'] == 'CPU': + test_list = self.tests_cpu + elif results['Dev Type'] == 'Disk': + test_list = self.tests_disk + + # Check if a full diag was run (i.e. all dev tests were enabled) + results['Full Diag'] = len(dev.tests) == len(test_list) + + # Tally test results + for test in dev.tests.values(): + if test.failed: + results['Failed'] += 1 + if test.passed: + results['Passed'] += 1 + if 'N/A' in test.status: + results['N/A'] += 1 + + # Set overall status + if results['Failed'] > 0: + dev.checkbox = False + results['Status'] = 'FAILED' + elif results['Passed'] + results['N/A'] == len(dev.tests): + dev.checkbox = True + results['Status'] = 'PASSED' + else: + results['Status'] = 'UNKNOWN' + if results['Full Diag'] and results['N/A'] > 0: + results['Asterisk'] = True + results['Status'] += '*' + + # Done + return results + + def get_device_type(self, dev): + """Terrible hack to determine device type, returns str.""" + # TODO: Fix with proper isinstance() call + type_str = str(dev.__class__) + if 'CpuObj' in type_str: + type_str = 'CPU' + elif 'DiskObj' in type_str: + type_str = 'Disk' + + return type_str + def get_ticket_name(self, ticket_id): """Lookup ticket and return name as str.""" name = None sql_cmd = "SELECT name FROM `{Ticket}`".format(**OSTICKET['Tables']) - sql_cmd += " WHERE `ticket_id` = `{}`".format(ticket_id) + sql_cmd += " WHERE `ticket_id` = {}".format(ticket_id) sql_cmd += ";" # TODO: Is the ';' needed above? It wasn't in the prev version?? @@ -183,9 +253,13 @@ class osTicket(): # TODO: Fix exception handling self.errors = True + # Done + return name + def get_ticket_number(self): """Get ticket number and confirm with name from osTicket DB.""" ticket_number = None + self.connect() # Main loop while ticket_number is None: @@ -199,7 +273,7 @@ class osTicket(): break # Invalid ID entered - if not re.match(r'^([0-9]+)$', _input): + if not re.match(r'^(\d+)$', _input): continue # Valid ID entered, lookup name and verify @@ -211,17 +285,22 @@ class osTicket(): ticket_number = _input # Done + self.disconnect() return ticket_number def post_device_results(self, dev, ticket_id): """Generate osTicket friendly report and post as response to ticket.""" response = self.generate_report(dev) - post_response(response, ticket_id) + self.post_response(response, ticket_id) def post_response(self, response, ticket_id): """Post a reply to a ticket in osTicket.""" self.connect() + # Convert response to string + response = '\n'.join(response) + response = response.replace('`', '') + # Build SQL cmd sql_cmd = "INSERT INTO `{Name}`.`{Response}`".format( **OSTICKET['Database'], **OSTICKET['Tables']) @@ -235,7 +314,7 @@ class osTicket(): # Run SQL cmd try: - self.cursor.execute(sql_cmd) + self.db_cursor.execute(sql_cmd) except Exception: # TODO: Fix exception handling self.errors = True @@ -271,7 +350,7 @@ class osTicket(): # Run SQL cmd try: - self.cursor.execute(sql_cmd) + self.db_cursor.execute(sql_cmd) except Exception: # TODO: Fix exception handling self.errors = True @@ -280,57 +359,6 @@ class osTicket(): self.disconnect() # Functions -def get_device_overall_results(dev): - """Get overall results from tests for device, returns dict.""" - results = { - 'Dev Type': 'Unknown', - 'Full Diag': False, - 'Asterisk': None, - 'Failed': 0, - 'N/A': 0, - 'Passed': 0, - 'Status': 'Unknown', - } - - # Get test list for device type - test_list = [] - if isinstance(dev, CpuObj): - results['Dev Type'] = 'CPU' - test_list = TESTS_CPU - elif isinstance(dev, DiskObj): - results['Dev Type'] = 'Disk' - test_list = TESTS_DISK - else: - raise GenericError('Unrecognized device type.') - - # Check if a full diag was run (i.e. all dev tests were enabled) - results['Full Diag'] = len(dev.tests) == len(test_list) - - # Tally test results - for test in dev.tests.value(): - if test.failed: - results['Failed'] += 1 - if test.passed: - results['Passed'] += 1 - if 'N/A' in test.status: - results['N/A'] += 1 - - # Set overall status - if results['Failed'] > 0: - dev.checkbox = False - results['Status'] = 'FAILED' - elif results['Passed'] + results['N/A'] == len(dev.tests): - dev.checkbox = True - results['Status'] = 'PASSED' - else: - results['Status'] = 'UNKNOWN' - if results['Full Diag'] and results['N/A'] > 0: - results['Asterisk'] = True - results['Status'] += '*' - - # Done - return results - def pad_with_dots(s, pad_right=False): """Replace space padding with dots, returns str.""" s = str(s).replace(' ', '..') From b3f2a86f46d75087b2873cf4317df436a25639fa Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 24 Dec 2018 21:19:56 -0700 Subject: [PATCH 134/265] Add spacer line before Temps --- .bin/Scripts/functions/osticket.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.bin/Scripts/functions/osticket.py b/.bin/Scripts/functions/osticket.py index fb5649ba..e7f2ee19 100644 --- a/.bin/Scripts/functions/osticket.py +++ b/.bin/Scripts/functions/osticket.py @@ -89,6 +89,8 @@ class osTicket(): _sensor = r2.group(1) _spacer = pad_with_dots(r2.group(2)) line = '{}{} {}'.format(_sensor, _spacer, _temps) + if line == 'Temps': + out_report.append(' ') elif name == 'NVMe / SMART': r = REGEX_NVME_SMART_ATTRIBUTES.match(line) if r: From 12ea0fdd53edb88097e244fc0c437c9f64161a74 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 24 Dec 2018 21:59:00 -0700 Subject: [PATCH 135/265] Posting disk results is working --- .bin/Scripts/functions/hw_diags.py | 2 -- .bin/Scripts/functions/osticket.py | 7 +++++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index b50744aa..eb4154a7 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -4,9 +4,7 @@ import json import re import time -# TODO: Still need functions.data ? from collections import OrderedDict -from functions.data import * from functions.png_graph import * from functions.osticket import * from functions.sensors import * diff --git a/.bin/Scripts/functions/osticket.py b/.bin/Scripts/functions/osticket.py index e7f2ee19..d82db04a 100644 --- a/.bin/Scripts/functions/osticket.py +++ b/.bin/Scripts/functions/osticket.py @@ -69,6 +69,9 @@ class osTicket(): if not source_report: index = 0 source_report = test.dev.generate_attribute_report() + elif not source_report: + index = 0 + out_report.append('{} ({})'.format(name, status)) else: out_report.append('{} ({})'.format(strip_colors(source_report[0]), status)) @@ -345,8 +348,8 @@ class osTicket(): # Build SQL cmd sql_cmd = "UPDATE `{Name}`.`{Ticket}`".format( **OSTICKET['Database'], **OSTICKET['Tables']) - sql_cmd += " SET `{}` = `{}`".format(flag_name, flag_value) - sql_cmd += " WHERE `{Ticket}`.`ticket_id` = `{ticket_id}`".format( + sql_cmd += " SET `{}` = '{}'".format(flag_name, flag_value) + sql_cmd += " WHERE `{Ticket}`.`ticket_id` = {ticket_id}".format( ticket_id=ticket_id, **OSTICKET['Tables']) sql_cmd += ";" From 98c0c34bf8edf8d47381350621fe379a442abbff Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 26 Dec 2018 17:11:37 -0700 Subject: [PATCH 136/265] Removed unused vertical_graph data --- .bin/Scripts/functions/hw_diags.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index cbfd4377..c183a69d 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -1057,7 +1057,6 @@ def run_io_benchmark(state, test): try: test.merged_rates = [] test.read_rates = [] - test.vertical_graph = [] test.dev.calc_io_dd_values() # Run dd read tests @@ -1084,10 +1083,6 @@ def run_io_benchmark(state, test): # Add rate to lists test.read_rates.append(cur_rate) - test.vertical_graph.append( - '{percent:0.1f} {rate}'.format( - percent=(i/test.dev.dd_chunks)*100, - rate=int(cur_rate/(1024**2)))) # Show progress if i % IO_VARS['Progress Refresh Rate'] == 0: @@ -1172,10 +1167,6 @@ def run_io_benchmark(state, test): elif not 'N/A' in test.status: test.update_status('Unknown') - # Save log - with open(test.io_benchmark_out.replace('.', '-raw.'), 'a') as f: - f.write('\n'.join(test.vertical_graph)) - # Done update_progress_pane(state) From 2c0093aa9a9ab74a2fd586e6f902a1910779692f Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 26 Dec 2018 17:15:31 -0700 Subject: [PATCH 137/265] I/O graph export/upload sections working --- .bin/Scripts/functions/hw_diags.py | 10 ------- .../functions/{png_graph.py => io_graph.py} | 30 ++++++++++++------- .bin/Scripts/functions/osticket.py | 28 +++++++++++++---- 3 files changed, 41 insertions(+), 27 deletions(-) rename .bin/Scripts/functions/{png_graph.py => io_graph.py} (79%) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index eb4154a7..678e9d5d 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -5,7 +5,6 @@ import re import time from collections import OrderedDict -from functions.png_graph import * from functions.osticket import * from functions.sensors import * from functions.tmux import * @@ -1061,7 +1060,6 @@ def run_io_benchmark(state, test): try: test.merged_rates = [] test.read_rates = [] - test.vertical_graph = [] test.dev.calc_io_dd_values() # Run dd read tests @@ -1088,10 +1086,6 @@ def run_io_benchmark(state, test): # Add rate to lists test.read_rates.append(cur_rate) - test.vertical_graph.append( - '{percent:0.1f} {rate}'.format( - percent=(i/test.dev.dd_chunks)*100, - rate=int(cur_rate/(1024**2)))) # Show progress if i % IO_VARS['Progress Refresh Rate'] == 0: @@ -1176,10 +1170,6 @@ def run_io_benchmark(state, test): elif not 'N/A' in test.status: test.update_status('Unknown') - # Save log - with open(test.io_benchmark_out.replace('.', '-raw.'), 'a') as f: - f.write('\n'.join(test.vertical_graph)) - # Done update_progress_pane(state) diff --git a/.bin/Scripts/functions/png_graph.py b/.bin/Scripts/functions/io_graph.py similarity index 79% rename from .bin/Scripts/functions/png_graph.py rename to .bin/Scripts/functions/io_graph.py index e429b9cc..fb909c9f 100644 --- a/.bin/Scripts/functions/png_graph.py +++ b/.bin/Scripts/functions/io_graph.py @@ -2,23 +2,34 @@ import base64 import Gnuplot +import json import math +import requests from functions.common import * # Functions -def export_png_graph(name, dev): +def export_io_graph(disk): """Exports PNG graph using gnuplot, returns file path as str.""" - max_rate = max(TESTS['iobenchmark']['Data'][name]['Read Rates']) - max_rate /= (1024**2) + read_rates = disk.tests['I/O Benchmark'].read_rates + max_rate = max(read_rates) / (1024**2) max_rate = max(800, max_rate) - out_path = '{}/iobenchmark-{}.png'.format(global_vars['LogDir'], name) - plot_data = '{}/iobenchmark-{}-raw.log'.format(global_vars['LogDir'], name) + out_path = '{}/iobenchmark-{}.png'.format( + global_vars['LogDir'], disk.name) + plot_data = '{}/iobenchmark-{}-plot.data'.format( + global_vars['LogDir'], disk.name) # Adjust Y-axis range to either 1000 or roughly max rate + 200 ## Round up to the nearest 100 and then add 200 y_range = (math.ceil(max_rate/100)*100) + 200 + # Save plot data to file for Gnuplot + with open(plot_data, 'w') as f: + for i in range(len(read_rates)): + _percent = ( (i+1) / len(read_rates) ) * 100 + _rate = int( read_rates[i] / (1024**2) ) + f.write('{:0.1f} {}\n'.format(_percent, _rate)) + # Run gnuplot commands g = Gnuplot.Gnuplot() g('reset') @@ -27,12 +38,9 @@ def export_png_graph(name, dev): g('set title "I/O Benchmark"') g('set yrange [0:{}]'.format(y_range)) g('set style data lines') - g('plot "{data}" title "{size} ({tran}) {model} {serial}"'.format( - data=plot_data, - size=dev['lsblk'].get('size', '???b'), - tran=dev['lsblk'].get('tran', '???'), - model=dev['lsblk'].get('model', 'Unknown Model'), - serial=dev['lsblk'].get('serial', 'Unknown Serial'), + g('plot "{}" title "{}"'.format( + plot_data, + disk.description.replace('_', ' '), )) # Cleanup diff --git a/.bin/Scripts/functions/osticket.py b/.bin/Scripts/functions/osticket.py index d82db04a..a2142e1d 100644 --- a/.bin/Scripts/functions/osticket.py +++ b/.bin/Scripts/functions/osticket.py @@ -2,7 +2,7 @@ import mysql.connector as mariadb -from functions.common import * +from functions.io_graph import * from settings.osticket import * # STATIC VARIABLES @@ -122,7 +122,7 @@ class osTicket(): # Done return out_report - def generate_report(self, dev): + def generate_report(self, dev, ticket_id): """Generate device report for osTicket, returns list.""" report = [] results = self.get_device_overall_results(dev) @@ -141,9 +141,25 @@ class osTicket(): for name, test in dev.tests.items(): report.extend(self.convert_report(name, test)) if name == 'I/O Benchmark': - # TODO: Create PNG graph and upload to imgur/Nextcloud - report.append('Imgur: TODO') - report.append('Nextcloud: TODO') + # Create PNG graph + try: + graph_file = export_io_graph(dev) + except (AttributeError, KeyError): + report.append('Failed to export graph') + else: + # Upload to Imgur + try: + url = upload_to_imgur(graph_file) + report.append('Imgur: {}'.format(url)) + except Exception: + report.append('Imgur: Failed to upload graph') + + # Upload to Nextcloud + try: + url = upload_to_nextcloud(graph_file, ticket_id, dev.name) + report.append('Nextcloud: {}'.format(url)) + except Exception: + report.append('Nextcloud: Failed to upload graph') report.append(' ') # Volumes @@ -295,7 +311,7 @@ class osTicket(): def post_device_results(self, dev, ticket_id): """Generate osTicket friendly report and post as response to ticket.""" - response = self.generate_report(dev) + response = self.generate_report(dev, ticket_id) self.post_response(response, ticket_id) def post_response(self, response, ticket_id): From 7d7cf2126333c57707147e6dcd6a6f5f9a17faf8 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 26 Dec 2018 18:22:34 -0700 Subject: [PATCH 138/265] Show volume report if all disk tests are run * Enable CoreStorage mounting only if all tests were CS, N/A, or OVERRIDE --- .bin/Scripts/functions/osticket.py | 83 ++++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 17 deletions(-) diff --git a/.bin/Scripts/functions/osticket.py b/.bin/Scripts/functions/osticket.py index a2142e1d..1911727d 100644 --- a/.bin/Scripts/functions/osticket.py +++ b/.bin/Scripts/functions/osticket.py @@ -2,6 +2,7 @@ import mysql.connector as mariadb +from functions.data import * from functions.io_graph import * from settings.osticket import * @@ -122,6 +123,23 @@ class osTicket(): # Done return out_report + def disconnect(self, reset_errors=False): + """Close osTicket connection.""" + try: + self.db_cursor.close() + self.db_connection.close() + except Exception: + # TODO: Fix exception handling + pass + + # Reset errors + if reset_errors: + self.errors = False + + # Reset vars + self.db_cursor = None + self.db_connection = None + def generate_report(self, dev, ticket_id): """Generate device report for osTicket, returns list.""" report = [] @@ -163,10 +181,10 @@ class osTicket(): report.append(' ') # Volumes - if results['Dev Type'] == 'Disk': - # TODO: Mount all volumes and extend report + if results['Dev Type'] == 'Disk' and results['Full Diag']: + # Mount all volumes and extend report report.append('Volumes:') - report.append('TODO') + report.extend(self.generate_volume_report(dev, results)) report.append(' ') # Asterisk @@ -176,31 +194,56 @@ class osTicket(): # Done return report - def disconnect(self, reset_errors=False): - """Close osTicket connection.""" - try: - self.db_cursor.close() - self.db_connection.close() - except Exception: - # TODO: Fix exception handling - pass + def generate_volume_report(self, dev, results): + """Mount all volumes for dev and generate report, returns list.""" + report = [] + mount_report = mount_volumes( + all_devices=False, + device_path='{}'.format(dev.path), + core_storage=results['Core']) - # Reset errors - if reset_errors: - self.errors = False + # Format report + for v_path, v_data in sorted(mount_report.items()): + label = v_data.get('label', '') + if label: + label = '"{}"'.format(label) + else: + # Ensure string type + label = '' + size = v_data.get('size', '') + if size: + size = '{} {}B'.format(size[:-1], size[-1:]).upper() + else: + size = 'UNKNOWN' + size_used = v_data.get('size_used', 'UNKNOWN').upper() + size_avail = v_data.get('size_avail', 'UNKNOWN').upper() + v_data = [v_path, label, size, size_used, size_avail] + v_data = [v.strip().replace(' ', '_') for v in v_data] + for i in range(len(v_data)): + pad = 8 + if i < 2: + pad += 4 * (2 - i) + v_data[i] = pad_with_dots( + '{s:<{p}}'.format(s=v_data[i], p=pad), + pad_right=True) + v_data[-1] = re.sub(r'\.*$', '', v_data[-1]) + v_data = [v.replace('_', ' ') for v in v_data] + report.append( + '{}..{}..Total..{}..(Used..{}..Free..{})'.format(*v_data)) - # Reset vars - self.db_cursor = None - self.db_connection = None + # Done + return report def get_device_overall_results(self, dev): """Get overall results from tests for device, returns dict.""" results = { + 'Core': False, 'Dev Type': self.get_device_type(dev), 'Full Diag': False, 'Asterisk': None, 'Failed': 0, 'N/A': 0, + 'OVERRIDE': 0, 'Passed': 0, 'Status': 'Unknown', } @@ -228,6 +271,8 @@ class osTicket(): results['Passed'] += 1 if 'N/A' in test.status: results['N/A'] += 1 + if 'OVERRIDE' in test.status: + results['OVERRIDE'] += 1 # Set overall status if results['Failed'] > 0: @@ -242,6 +287,10 @@ class osTicket(): results['Asterisk'] = True results['Status'] += '*' + # Enable CoreStorage searches + results['Core'] = (results['Full Diag'] and + results['Passed']+results['N/A']+results['OVERRIDE'] == len(test_list)) + # Done return results From ff715b7a107c6f61591a18bf636d973326697d0a Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 26 Dec 2018 19:31:07 -0700 Subject: [PATCH 139/265] Better exception handling for MariaDB sections --- .bin/Scripts/functions/osticket.py | 63 ++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/.bin/Scripts/functions/osticket.py b/.bin/Scripts/functions/osticket.py index 1911727d..dc97c88f 100644 --- a/.bin/Scripts/functions/osticket.py +++ b/.bin/Scripts/functions/osticket.py @@ -21,6 +21,7 @@ class osTicket(): def __init__(self, tests_cpu, tests_disk): self.db_connection = None self.db_cursor = None + self.disabled = False self.errors = False self.tests_cpu = tests_cpu self.tests_disk = tests_disk @@ -35,6 +36,10 @@ class osTicket(): '{User}@{Host}'.format(**OSTICKET['SSH']), ] + # Bail if disabled + if self.disabled: + return + # Only open tunnel if one doesn't exist if self.tunnel_proc is None or self.tunnel_proc.poll() is not None: self.tunnel_proc = popen_program(cmd) @@ -49,13 +54,24 @@ class osTicket(): database=OSTICKET['Database']['Name'], ) self.db_cursor = self.db_connection.cursor() - except Exception: - # TODO: Refine exception handling + except mariadb.errors.InterfaceError: + # SSH issue?, try again pass + except mariadb.errors.Error: + # Bad creds or other SQL error, bail + break + except Exception: + # Unknown error + break else: # Connection established break + # Disable if necessary + if self.db_cursor is None: + self.disabled = True + self.tunnel_proc.kill() + def convert_report(self, name, test): """Convert report into an osTicket friendly format, returns list.""" out_report = [] @@ -129,13 +145,9 @@ class osTicket(): self.db_cursor.close() self.db_connection.close() except Exception: - # TODO: Fix exception handling + # Ignore errors since vars will be reset below pass - # Reset errors - if reset_errors: - self.errors = False - # Reset vars self.db_cursor = None self.db_connection = None @@ -311,17 +323,12 @@ class osTicket(): sql_cmd = "SELECT name FROM `{Ticket}`".format(**OSTICKET['Tables']) sql_cmd += " WHERE `ticket_id` = {}".format(ticket_id) sql_cmd += ";" - # TODO: Is the ';' needed above? It wasn't in the prev version?? # Lookup name # NOTE: If multiple entries are found it will return the last - try: - self.db_cursor.execute(sql_cmd) - for s in self.db_cursor: - name = s[0] - except Exception: - # TODO: Fix exception handling - self.errors = True + self.db_cursor.execute(sql_cmd) + for s in self.db_cursor: + name = s[0] # Done return name @@ -331,6 +338,10 @@ class osTicket(): ticket_number = None self.connect() + # Bail if disabled + if self.disabled: + return None + # Main loop while ticket_number is None: print_standard(' ') @@ -347,7 +358,11 @@ class osTicket(): continue # Valid ID entered, lookup name and verify - _name = self.get_ticket_name(_input) + try: + _name = self.get_ticket_name(_input) + except Exception: + # Ignore and return None below + break if _name: print_standard('You have selected ticket #{} {}'.format( _input, _name)) @@ -367,6 +382,10 @@ class osTicket(): """Post a reply to a ticket in osTicket.""" self.connect() + # Bail if disabled + if self.disabled: + return + # Convert response to string response = '\n'.join(response) response = response.replace('`', '') @@ -385,8 +404,8 @@ class osTicket(): # Run SQL cmd try: self.db_cursor.execute(sql_cmd) - except Exception: - # TODO: Fix exception handling + except mariadb.errors.Error: + # Set self.errors to enable warning line on results screen self.errors = True # Done @@ -410,6 +429,10 @@ class osTicket(): """Set flag in osTicket.""" self.connect() + # Bail if disabled + if self.disabled: + return + # Build SQL cmd sql_cmd = "UPDATE `{Name}`.`{Ticket}`".format( **OSTICKET['Database'], **OSTICKET['Tables']) @@ -421,8 +444,8 @@ class osTicket(): # Run SQL cmd try: self.db_cursor.execute(sql_cmd) - except Exception: - # TODO: Fix exception handling + except mariadb.errors.Error: + # Set self.errors to enable warning line on results screen self.errors = True # Done From 7205ac6c3532170bf27ca07e9012d7276d3f2b65 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 26 Dec 2018 19:46:27 -0700 Subject: [PATCH 140/265] Added osTicket integration toggle to menu --- .bin/Scripts/functions/hw_diags.py | 31 ++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 678e9d5d..046a3cf8 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -495,6 +495,7 @@ class State(): def __init__(self): self.cpu = None self.disks = [] + self.ost_integration = False self.panes = {} self.quick_mode = False self.tests = OrderedDict({ @@ -746,6 +747,7 @@ def menu_diags(state, args): {'Base Name': 'Full Diagnostic', 'Enabled': False}, {'Base Name': 'Disk Diagnostic', 'Enabled': False}, {'Base Name': 'Disk Diagnostic (Quick)', 'Enabled': False}, + {'Base Name': 'osTicket Integration', 'Enabled': True}, {'Base Name': 'Prime95', 'Enabled': False, 'CRLF': True}, {'Base Name': 'NVMe / SMART', 'Enabled': False}, {'Base Name': 'badblocks', 'Enabled': False}, @@ -777,11 +779,11 @@ def menu_diags(state, args): while True: # Set quick mode as necessary - if main_options[2]['Enabled'] and main_options[4]['Enabled']: + if main_options[2]['Enabled'] and main_options[5]['Enabled']: # Check if only Disk Diags (Quick) and NVMe/SMART are enabled # If so, verify no other tests are enabled and set quick_mode state.quick_mode = True - for opt in main_options[3:4] + main_options[5:]: + for opt in main_options[4:5] + main_options[6:]: state.quick_mode &= not opt['Enabled'] else: state.quick_mode = False @@ -795,13 +797,13 @@ def menu_diags(state, args): # Verify preset selections num_tests_selected = 0 - for opt in main_options[3:]: + for opt in main_options[4:]: if opt['Enabled']: num_tests_selected += 1 if num_tests_selected == 4: # Full main_options[0]['Enabled'] = True - elif num_tests_selected == 3 and not main_options[3]['Enabled']: + elif num_tests_selected == 3 and not main_options[4]['Enabled']: # Disk main_options[1]['Enabled'] = True @@ -1576,33 +1578,34 @@ def update_main_options(state, selection, main_options): if main_options[index]['Enabled']: for opt in main_options[1:3]: opt['Enabled'] = False - for opt in main_options[3:]: + for opt in main_options[4:]: opt['Enabled'] = True else: - for opt in main_options[3:]: + for opt in main_options[4:]: opt['Enabled'] = False elif index == 1: # Disk if main_options[index]['Enabled']: main_options[0]['Enabled'] = False - for opt in main_options[2:4]: - opt['Enabled'] = False - for opt in main_options[4:]: + main_options[2]['Enabled'] = False + main_options[4]['Enabled'] = False + for opt in main_options[5:]: opt['Enabled'] = True else: - for opt in main_options[4:]: + for opt in main_options[5:]: opt['Enabled'] = False elif index == 2: # Disk (Quick) if main_options[index]['Enabled']: - for opt in main_options[:2] + main_options[3:]: + for opt in main_options[:2] + main_options[4:]: opt['Enabled'] = False - main_options[4]['Enabled'] = True + main_options[5]['Enabled'] = True else: - main_options[4]['Enabled'] = False + main_options[5]['Enabled'] = False # Update state - for opt in main_options[3:]: + state.ost_integration = main_options[3]['Enabled'] + for opt in main_options[4:]: state.tests[opt['Base Name']]['Enabled'] = opt['Enabled'] # Done From b3da1390a10f93e3656cb74d710a08c90ba3f569 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 26 Dec 2018 20:43:17 -0700 Subject: [PATCH 141/265] Only set disk.checkbox=True if all tests enabled --- .bin/Scripts/functions/osticket.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.bin/Scripts/functions/osticket.py b/.bin/Scripts/functions/osticket.py index dc97c88f..3578bed6 100644 --- a/.bin/Scripts/functions/osticket.py +++ b/.bin/Scripts/functions/osticket.py @@ -290,7 +290,8 @@ class osTicket(): if results['Failed'] > 0: dev.checkbox = False results['Status'] = 'FAILED' - elif results['Passed'] + results['N/A'] == len(dev.tests): + elif results['Passed'] + results['N/A'] == len(test_list): + # Only mark true if all tests are enabled and all are "Passed" / "N/A" dev.checkbox = True results['Status'] = 'PASSED' else: From d9ab1730b416ecd1dbb21994031b5294e421968c Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 26 Dec 2018 20:44:20 -0700 Subject: [PATCH 142/265] Reset tunnel_proc to None on full disconnect --- .bin/Scripts/functions/osticket.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.bin/Scripts/functions/osticket.py b/.bin/Scripts/functions/osticket.py index 3578bed6..895c6130 100644 --- a/.bin/Scripts/functions/osticket.py +++ b/.bin/Scripts/functions/osticket.py @@ -139,7 +139,7 @@ class osTicket(): # Done return out_report - def disconnect(self, reset_errors=False): + def disconnect(self, full=False): """Close osTicket connection.""" try: self.db_cursor.close() @@ -148,10 +148,24 @@ class osTicket(): # Ignore errors since vars will be reset below pass + # Reset errors + if full: + self.errors = False + # Reset vars self.db_cursor = None self.db_connection = None + # Close tunnel + if full: + try: + self.tunnel_proc.kill() + self.tunnel_proc.wait(timeout=2) + except (AttributeError, subprocess.TimeoutExpired): + # Ignore and continue + pass + self.tunnel_proc = None + def generate_report(self, dev, ticket_id): """Generate device report for osTicket, returns list.""" report = [] From 495e265de0273e35072b66e9ec5a046ccf642668 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 26 Dec 2018 20:45:00 -0700 Subject: [PATCH 143/265] Only post results for devices with TestObj(s) --- .bin/Scripts/functions/osticket.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.bin/Scripts/functions/osticket.py b/.bin/Scripts/functions/osticket.py index 895c6130..13490e92 100644 --- a/.bin/Scripts/functions/osticket.py +++ b/.bin/Scripts/functions/osticket.py @@ -390,6 +390,9 @@ class osTicket(): def post_device_results(self, dev, ticket_id): """Generate osTicket friendly report and post as response to ticket.""" + if not dev.tests: + # No test results available, aborting post + return response = self.generate_report(dev, ticket_id) self.post_response(response, ticket_id) From 5cf2fa6f27f7b94e25874b155287abdbfa1c351a Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 26 Dec 2018 20:57:30 -0700 Subject: [PATCH 144/265] Added remaining osTicket sections --- .bin/Scripts/functions/hw_diags.py | 51 ++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 046a3cf8..26551f48 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -495,7 +495,7 @@ class State(): def __init__(self): self.cpu = None self.disks = [] - self.ost_integration = False + self.ost = osTicket(TESTS_CPU, TESTS_DISK) self.panes = {} self.quick_mode = False self.tests = OrderedDict({ @@ -520,6 +520,7 @@ class State(): 'Objects': [], }, }) + self.ticket_id = None def init(self): """Remove test objects, set log, and add devices.""" @@ -948,6 +949,10 @@ def run_hw_tests(state): """Run enabled hardware tests.""" print_standard('Scanning devices...') state.init() + tests_enabled = False + + # Disable osTicket Integration if in quick mode + state.ost.disabled |= state.quick_mode # Build Panes update_progress_pane(state) @@ -963,6 +968,8 @@ def run_hw_tests(state): COLORS['CLEAR'], QUICK_LABEL if state.quick_mode and 'NVMe' in k else '')) if v['Enabled']: + tests_enabled = True + # Create TestObj and track under both CpuObj/DiskObj and State if k in TESTS_CPU: test_obj = TestObj( @@ -976,6 +983,15 @@ def run_hw_tests(state): v['Objects'].append(test_obj) print_standard('') + # Bail if no tests selected + if not tests_enabled: + tmux_kill_pane(*state.panes.values()) + return + + # Get ticket_number + if not state.ost.disabled: + state.ticket_id = state.ost.get_ticket_number() + # Run disk safety checks (if necessary) _disk_tests_enabled = False for k in TESTS_DISK: @@ -993,6 +1009,9 @@ def run_hw_tests(state): f = v['Function'] for test_obj in v['Objects']: f(state, test_obj) + if k == TESTS_CPU[-1]: + # Last CPU test run, post CPU results + state.ost.post_device_results(state.cpu, state.ticket_id) except GenericAbort: # Cleanup tmux_kill_pane(*state.panes.values()) @@ -1011,14 +1030,40 @@ def run_hw_tests(state): # Update side pane update_progress_pane(state) - # Done + # Show results and determine if HDD checkbox needs updated + all_drives_passed = True + disk_failures = False show_results(state) + for disk in state.disks: + if disk.checkbox is None: + # Aborted/Unknown/etc + all_drives_passed = False + else: + all_drives_passed &= disk.checkbox + disk_failures |= not disk.checkbox + + # Post test results for disk + state.ost.post_device_results(disk, state.ticket_id) + + # Update checkbox if necessary + if disk_failures: + state.ost.set_disk_failed(state.ticket_id) + elif all_drives_passed: + state.ost.set_disk_passed(state.ticket_id) + + # Check for osTicket errors + if state.ost.errors: + print_warning('Errors encountered posting results to osTicket.') + print_standard(' ') + + # Done if state.quick_mode: pause('Press Enter to exit...') else: pause('Press Enter to return to main menu... ') # Cleanup + state.ost.disconnect(full=True) tmux_kill_pane(*state.panes.values()) def run_io_benchmark(state, test): @@ -1604,7 +1649,7 @@ def update_main_options(state, selection, main_options): main_options[5]['Enabled'] = False # Update state - state.ost_integration = main_options[3]['Enabled'] + state.ost.disabled = not main_options[3]['Enabled'] for opt in main_options[4:]: state.tests[opt['Base Name']]['Enabled'] = opt['Enabled'] From dcc2e5cd6a03784332a29bff51b731e64917f2ee Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 26 Dec 2018 21:00:29 -0700 Subject: [PATCH 145/265] Adjusted top pane text --- .bin/Scripts/functions/hw_diags.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index c183a69d..a4184689 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -861,7 +861,7 @@ def run_badblocks_test(state, test): # Update tmux layout tmux_update_pane( state.panes['Top'], - text='{}\nbadblocks: {}'.format( + text='{}\n{}'.format( TOP_PANE_TEXT, test.dev.description)) test.tmux_layout = TMUX_LAYOUT.copy() test.tmux_layout.update({ @@ -1031,7 +1031,7 @@ def run_io_benchmark(state, test): # Update tmux layout tmux_update_pane( state.panes['Top'], - text='{}\nI/O Benchmark: {}'.format( + text='{}\n{}'.format( TOP_PANE_TEXT, test.dev.description)) test.tmux_layout = TMUX_LAYOUT.copy() test.tmux_layout.update({ @@ -1194,7 +1194,7 @@ def run_mprime_test(state, test): # Update tmux layout tmux_update_pane( state.panes['Top'], - text='{}\nPrime95: {}'.format(TOP_PANE_TEXT, test.dev.name)) + text='{}\n{}'.format(TOP_PANE_TEXT, test.dev.name)) test.tmux_layout = TMUX_LAYOUT.copy() test.tmux_layout.update({ 'Temps': {'y': 1000, 'Check': False}, @@ -1391,7 +1391,7 @@ def run_nvme_smart_tests(state, test): # Update tmux layout tmux_update_pane( state.panes['Top'], - text='{}\nDisk Health: {}'.format( + text='{}\n{}'.format( TOP_PANE_TEXT, test.dev.description)) test.tmux_layout = TMUX_LAYOUT.copy() test.tmux_layout.update({ From 41b8d632aeea2b9edf407fc6635a79e7d84ead01 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 26 Dec 2018 21:32:03 -0700 Subject: [PATCH 146/265] Fix disk checkbox logic --- .bin/Scripts/functions/hw_diags.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 26551f48..43b97be8 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -1030,25 +1030,28 @@ def run_hw_tests(state): # Update side pane update_progress_pane(state) - # Show results and determine if HDD checkbox needs updated - all_drives_passed = True - disk_failures = False + # Show results show_results(state) + + # Post disk results + for disk in state.disks: + state.ost.post_device_results(disk, state.ticket_id) + + # Check if disk checkbox needs updating + all_disks_passed = True + disk_failures = False for disk in state.disks: if disk.checkbox is None: # Aborted/Unknown/etc - all_drives_passed = False + all_disks_passed = False else: - all_drives_passed &= disk.checkbox + all_disks_passed &= disk.checkbox disk_failures |= not disk.checkbox - # Post test results for disk - state.ost.post_device_results(disk, state.ticket_id) - # Update checkbox if necessary if disk_failures: state.ost.set_disk_failed(state.ticket_id) - elif all_drives_passed: + elif all_disks_passed: state.ost.set_disk_passed(state.ticket_id) # Check for osTicket errors From 1d9c3b18696e6ce767a3bc51918dae4440683cff Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 26 Dec 2018 21:50:34 -0700 Subject: [PATCH 147/265] Added posting results line to results screen --- .bin/Scripts/functions/hw_diags.py | 39 +++++++++++++++++------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 43b97be8..7e06ecf9 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -1034,25 +1034,30 @@ def run_hw_tests(state): show_results(state) # Post disk results - for disk in state.disks: - state.ost.post_device_results(disk, state.ticket_id) + if not state.ost.disabled: + print_standard('Posting results to osTicket...') + for disk in state.disks: + state.ost.post_device_results(disk, state.ticket_id) - # Check if disk checkbox needs updating - all_disks_passed = True - disk_failures = False - for disk in state.disks: - if disk.checkbox is None: - # Aborted/Unknown/etc - all_disks_passed = False - else: - all_disks_passed &= disk.checkbox - disk_failures |= not disk.checkbox + # Check if disk checkbox needs updating + all_disks_passed = True + disk_failures = False + for disk in state.disks: + if disk.checkbox is None: + # Aborted/Unknown/etc + all_disks_passed = False + else: + all_disks_passed &= disk.checkbox + disk_failures |= not disk.checkbox - # Update checkbox if necessary - if disk_failures: - state.ost.set_disk_failed(state.ticket_id) - elif all_disks_passed: - state.ost.set_disk_passed(state.ticket_id) + # Update checkbox if necessary + if disk_failures: + state.ost.set_disk_failed(state.ticket_id) + elif all_disks_passed: + state.ost.set_disk_passed(state.ticket_id) + + # Spacer + print_standard(' ') # Check for osTicket errors if state.ost.errors: From a39c62eabcea3707b34c22c988d021a739ef3b1f Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 17:47:01 -0700 Subject: [PATCH 148/265] Fix crash if no sensors available --- .bin/Scripts/functions/sensors.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.bin/Scripts/functions/sensors.py b/.bin/Scripts/functions/sensors.py index 99e7999a..eeb98922 100644 --- a/.bin/Scripts/functions/sensors.py +++ b/.bin/Scripts/functions/sensors.py @@ -99,9 +99,16 @@ def get_colored_temp_str(temp): def get_raw_sensor_data(): """Read sensor data and return dict.""" + data = {} cmd = ['sensors', '-j'] - result = run_program(cmd) - return json.loads(result.stdout.decode()) + try: + result = run_program(cmd) + data = json.loads(result.stdout.decode()) + except subprocess.CalledProcessError: + # Assuming no sensors available, return empty dict below + pass + + return data def get_sensor_data(): """Parse raw sensor data and return new dict.""" From c40c80069f74b884ff90f340b3f85c24475cbe39 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 17:51:46 -0700 Subject: [PATCH 149/265] Fix MemTest86 extraction --- Build Linux | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Build Linux b/Build Linux index 41e5dea5..87e93e2d 100755 --- a/Build Linux +++ b/Build Linux @@ -174,11 +174,11 @@ function update_live_env() { 7z e "$TEMP_DIR/memtest86/memtest86-usb.zip" -o"$TEMP_DIR/memtest86" "memtest86-usb.img" 7z e "$TEMP_DIR/memtest86/memtest86-usb.img" -o"$TEMP_DIR/memtest86" "MemTest86.img" 7z x "$TEMP_DIR/memtest86/MemTest86.img" -o"$TEMP_DIR/memtest86" - rm "$TEMP_DIR/memtest86/EFI/BOOT/BOOTIA32.EFI" - mv "$TEMP_DIR/memtest86/EFI/BOOT/BOOTX64.EFI" "$LIVE_DIR/EFI/memtest86/memtestx64.efi" - for f in "$TEMP_DIR/memtest86/EFI/BOOT"/* "help"/* license.rtf; do - mv "$f" "$LIVE_DIR/EFI/memtest86"/ - done + rm "$TEMP_DIR/memtest86/EFI/BOOT/BOOTIA32.efi" + mv "$TEMP_DIR/memtest86/EFI/BOOT/BOOTX64.efi" "$LIVE_DIR/EFI/memtest86/memtestx64.efi" + mv "$TEMP_DIR/memtest86/EFI/BOOT"/* "$LIVE_DIR/EFI/memtest86"/ + mv "$TEMP_DIR/memtest86/help"/* "$LIVE_DIR/EFI/memtest86"/ + mv "$TEMP_DIR/memtest86/license.rtf" "$LIVE_DIR/EFI/memtest86"/ # build.sh if ! grep -iq 'wizardkit additions' "$LIVE_DIR/build.sh"; then From 4b956d5eea0f3cc1641a3b5b449c00a05ad13fab Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 17:51:51 -0700 Subject: [PATCH 150/265] Fix MemTest86 extraction --- Build Linux | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Build Linux b/Build Linux index 41e5dea5..87e93e2d 100755 --- a/Build Linux +++ b/Build Linux @@ -174,11 +174,11 @@ function update_live_env() { 7z e "$TEMP_DIR/memtest86/memtest86-usb.zip" -o"$TEMP_DIR/memtest86" "memtest86-usb.img" 7z e "$TEMP_DIR/memtest86/memtest86-usb.img" -o"$TEMP_DIR/memtest86" "MemTest86.img" 7z x "$TEMP_DIR/memtest86/MemTest86.img" -o"$TEMP_DIR/memtest86" - rm "$TEMP_DIR/memtest86/EFI/BOOT/BOOTIA32.EFI" - mv "$TEMP_DIR/memtest86/EFI/BOOT/BOOTX64.EFI" "$LIVE_DIR/EFI/memtest86/memtestx64.efi" - for f in "$TEMP_DIR/memtest86/EFI/BOOT"/* "help"/* license.rtf; do - mv "$f" "$LIVE_DIR/EFI/memtest86"/ - done + rm "$TEMP_DIR/memtest86/EFI/BOOT/BOOTIA32.efi" + mv "$TEMP_DIR/memtest86/EFI/BOOT/BOOTX64.efi" "$LIVE_DIR/EFI/memtest86/memtestx64.efi" + mv "$TEMP_DIR/memtest86/EFI/BOOT"/* "$LIVE_DIR/EFI/memtest86"/ + mv "$TEMP_DIR/memtest86/help"/* "$LIVE_DIR/EFI/memtest86"/ + mv "$TEMP_DIR/memtest86/license.rtf" "$LIVE_DIR/EFI/memtest86"/ # build.sh if ! grep -iq 'wizardkit additions' "$LIVE_DIR/build.sh"; then From a124236defc24901b93f98be1ace8a8395aba952 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 18:01:42 -0700 Subject: [PATCH 151/265] Removed unused pydf config --- .linux_items/include/airootfs/etc/pydfrc | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 .linux_items/include/airootfs/etc/pydfrc diff --git a/.linux_items/include/airootfs/etc/pydfrc b/.linux_items/include/airootfs/etc/pydfrc deleted file mode 100644 index 100b1f05..00000000 --- a/.linux_items/include/airootfs/etc/pydfrc +++ /dev/null @@ -1,24 +0,0 @@ -normal_colour = 'default' -header_colour = 'blue' -local_fs_colour = 'default' -remote_fs_colour = 'green' -special_fs_colour = 'yellow' -readonly_fs_colour = 'cyan' -filled_fs_colour = 'red' -full_fs_colour = 'on_red', 'green', 'blink' -sizeformat = "-h" -column_separator = ' ' -column_separator_colour = 'none' -stretch_screen = 0.3 -FILL_THRESH = 75.0 -FULL_THRESH = 85.0 -format = [ - ('fs', 10, "l"), ('size', 5, "r"), - ('used', 5, "r"), ('avail', 5, "r"), ('perc', 5, "r"), - ('bar', 0.1, "l"), ('on', 11, "l") - ] -barchar = '#' -bar_fillchar = '.' -hidebinds = True -mountfile = ['/etc/mtab', '/etc/mnttab', '/proc/mounts'] - From 28e2ce90df96120e39a1733369d6f10e0f7279a2 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 18:03:16 -0700 Subject: [PATCH 152/265] Removed nvme-cli in favor of smartctl --- .linux_items/packages/aur | 1 - .linux_items/packages/live_add | 1 - 2 files changed, 2 deletions(-) diff --git a/.linux_items/packages/aur b/.linux_items/packages/aur index 326ca732..8d752673 100644 --- a/.linux_items/packages/aur +++ b/.linux_items/packages/aur @@ -3,7 +3,6 @@ bash-pipes hfsprogs i3lock-fancy-git mprime -nvme-cli openbox-patched smartmontools-svn testdisk-wip diff --git a/.linux_items/packages/live_add b/.linux_items/packages/live_add index 4a7245b4..a6da5f71 100644 --- a/.linux_items/packages/live_add +++ b/.linux_items/packages/live_add @@ -53,7 +53,6 @@ network-manager-applet networkmanager noto-fonts noto-fonts-cjk -nvme-cli oblogout openbox-patched otf-font-awesome-4 From 765673db6605edb92c4f6d29d6c5a5bb65a1fd26 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 18:06:59 -0700 Subject: [PATCH 153/265] Updated windows_builds.py --- .bin/Scripts/settings/windows_builds.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.bin/Scripts/settings/windows_builds.py b/.bin/Scripts/settings/windows_builds.py index 2db18b6f..2817979a 100644 --- a/.bin/Scripts/settings/windows_builds.py +++ b/.bin/Scripts/settings/windows_builds.py @@ -170,7 +170,7 @@ WINDOWS_BUILDS = { '17755': ( '10', None, 'Redstone 5', None, 'preview build'), '17758': ( '10', None, 'Redstone 5', None, 'preview build'), '17760': ( '10', None, 'Redstone 5', None, 'preview build'), - '17763': ( '10', 'v1809', 'Redstone 5', 'October 2018 Update', 'preview build'), + '17763': ( '10', 'v1809', 'Redstone 5', 'October 2018 Update', None), '18204': ( '10', None, '19H1', None, 'preview build'), '18214': ( '10', None, '19H1', None, 'preview build'), '18219': ( '10', None, '19H1', None, 'preview build'), @@ -179,6 +179,14 @@ WINDOWS_BUILDS = { '18242': ( '10', None, '19H1', None, 'preview build'), '18247': ( '10', None, '19H1', None, 'preview build'), '18252': ( '10', None, '19H1', None, 'preview build'), + '18262': ( '10', None, '19H1', None, 'preview build'), + '18267': ( '10', None, '19H1', None, 'preview build'), + '18272': ( '10', None, '19H1', None, 'preview build'), + '18277': ( '10', None, '19H1', None, 'preview build'), + '18282': ( '10', None, '19H1', None, 'preview build'), + '18290': ( '10', None, '19H1', None, 'preview build'), + '18298': ( '10', None, '19H1', None, 'preview build'), + '18305': ( '10', None, '19H1', None, 'preview build'), } if __name__ == '__main__': From 36e419bca0bea606d46a870747e5fa118d49e962 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 19:42:28 -0700 Subject: [PATCH 154/265] Updated activation.py --- .bin/Scripts/functions/activation.py | 90 ++++++++++++++-------------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/.bin/Scripts/functions/activation.py b/.bin/Scripts/functions/activation.py index 24436418..e10d088c 100644 --- a/.bin/Scripts/functions/activation.py +++ b/.bin/Scripts/functions/activation.py @@ -10,57 +10,59 @@ from os import environ SLMGR = r'{}\System32\slmgr.vbs'.format(environ.get('SYSTEMROOT')) def activate_with_bios(): - """Attempt to activate Windows with a key stored in the BIOS.""" - # Code borrowed from https://github.com/aeruder/get_win8key - ##################################################### - #script to query windows 8.x OEM key from PC firmware - #ACPI -> table MSDM -> raw content -> byte offset 56 to end - #ck, 03-Jan-2014 (christian@korneck.de) - ##################################################### - bios_key = None - table = b"MSDM" - if acpi.FindAcpiTable(table) is True: - rawtable = acpi.GetAcpiTable(table) - #http://msdn.microsoft.com/library/windows/hardware/hh673514 - #byte offset 36 from beginning \ - # = Microsoft 'software licensing data structure' \ - # / 36 + 20 bytes offset from beginning = Win Key - bios_key = rawtable[56:len(rawtable)].decode("utf-8") - if bios_key is None: - raise BIOSKeyNotFoundError + """Attempt to activate Windows with a key stored in the BIOS.""" + # Code borrowed from https://github.com/aeruder/get_win8key + ##################################################### + #script to query windows 8.x OEM key from PC firmware + #ACPI -> table MSDM -> raw content -> byte offset 56 to end + #ck, 03-Jan-2014 (christian@korneck.de) + ##################################################### + bios_key = None + table = b"MSDM" + if acpi.FindAcpiTable(table) is True: + rawtable = acpi.GetAcpiTable(table) + #http://msdn.microsoft.com/library/windows/hardware/hh673514 + #byte offset 36 from beginning \ + # = Microsoft 'software licensing data structure' \ + # / 36 + 20 bytes offset from beginning = Win Key + bios_key = rawtable[56:len(rawtable)].decode("utf-8") + if bios_key is None: + raise BIOSKeyNotFoundError - # Install Key - cmd = ['cscript', '//nologo', SLMGR, '/ipk', bios_key] - subprocess.run(cmd, check=False) - sleep(5) + # Install Key + cmd = ['cscript', '//nologo', SLMGR, '/ipk', bios_key] + subprocess.run(cmd, check=False) + sleep(5) - # Attempt activation - cmd = ['cscript', '//nologo', SLMGR, '/ato'] - subprocess.run(cmd, check=False) - sleep(5) + # Attempt activation + cmd = ['cscript', '//nologo', SLMGR, '/ato'] + subprocess.run(cmd, check=False) + sleep(5) - # Check status - if not windows_is_activated(): - raise Exception('Activation Failed') + # Check status + if not windows_is_activated(): + raise Exception('Activation Failed') def get_activation_string(): - """Get activation status, returns str.""" - act_str = subprocess.run( - ['cscript', '//nologo', SLMGR, '/xpr'], check=False, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - act_str = act_str.stdout.decode() - act_str = act_str.splitlines() - act_str = act_str[1].strip() - return act_str + """Get activation status, returns str.""" + act_str = subprocess.run( + ['cscript', '//nologo', SLMGR, '/xpr'], check=False, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + act_str = act_str.stdout.decode() + act_str = act_str.splitlines() + act_str = act_str[1].strip() + return act_str def windows_is_activated(): - """Check if Windows is activated via slmgr.vbs and return bool.""" - activation_string = subprocess.run( - ['cscript', '//nologo', SLMGR, '/xpr'], check=False, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - activation_string = activation_string.stdout.decode() + """Check if Windows is activated via slmgr.vbs and return bool.""" + activation_string = subprocess.run( + ['cscript', '//nologo', SLMGR, '/xpr'], check=False, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + activation_string = activation_string.stdout.decode() - return bool(activation_string and 'permanent' in activation_string) + return bool(activation_string and 'permanent' in activation_string) if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From a269859b1792ee210524c40c66a15fc9f0cf4e8a Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 19:42:58 -0700 Subject: [PATCH 155/265] Updated backup.py --- .bin/Scripts/functions/backup.py | 344 ++++++++++++++++--------------- 1 file changed, 175 insertions(+), 169 deletions(-) diff --git a/.bin/Scripts/functions/backup.py b/.bin/Scripts/functions/backup.py index d872c4d0..f7679db2 100644 --- a/.bin/Scripts/functions/backup.py +++ b/.bin/Scripts/functions/backup.py @@ -6,200 +6,206 @@ from functions.disk import * # Regex REGEX_BAD_PATH_NAMES = re.compile( - r'([<>:"/\|\?\*]' - r'|^(CON|PRN|AUX|NUL|COM\d*|LPT\d*)$)' - r'|^\s+' - r'|[\s\.]+$', - re.IGNORECASE) + r'([<>:"/\|\?\*]' + r'|^(CON|PRN|AUX|NUL|COM\d*|LPT\d*)$)' + r'|^\s+' + r'|[\s\.]+$', + re.IGNORECASE) def backup_partition(disk, par): - """Create a backup image of a partition.""" - if par.get('Image Exists', False) or par['Number'] in disk['Bad Partitions']: - raise GenericAbort + """Create a backup image of a partition.""" + if (par.get('Image Exists', False) + or par['Number'] in disk['Bad Partitions']): + raise GenericAbort - cmd = [ - global_vars['Tools']['wimlib-imagex'], - 'capture', - '{}:\\'.format(par['Letter']), - par['Image Path'], - par['Image Name'], # Image name - par['Image Name'], # Image description - '--compress=none', - ] - dest_dir = re.sub(r'(.*)\\.*$', r'\1', par['Image Path'], re.IGNORECASE) - os.makedirs(dest_dir, exist_ok=True) - run_program(cmd) + cmd = [ + global_vars['Tools']['wimlib-imagex'], + 'capture', + '{}:\\'.format(par['Letter']), + par['Image Path'], + par['Image Name'], # Image name + par['Image Name'], # Image description + '--compress=none', + ] + dest_dir = re.sub(r'(.*)\\.*$', r'\1', par['Image Path'], re.IGNORECASE) + os.makedirs(dest_dir, exist_ok=True) + run_program(cmd) def fix_path(path): - """Replace invalid filename characters with underscores.""" - local_drive = path[1:2] == ':' - new_path = REGEX_BAD_PATH_NAMES.sub('_', path) - if local_drive: - new_path = '{}:{}'.format(new_path[0:1], new_path[2:]) - return new_path + """Replace invalid filename characters with underscores.""" + local_drive = path[1:2] == ':' + new_path = REGEX_BAD_PATH_NAMES.sub('_', path) + if local_drive: + new_path = '{}:{}'.format(new_path[0:1], new_path[2:]) + return new_path def get_volume_display_name(mountpoint): - """Get display name from volume mountpoint and label, returns str.""" - name = mountpoint - try: - kernel32 = ctypes.windll.kernel32 - vol_name_buffer = ctypes.create_unicode_buffer(1024) - fs_name_buffer = ctypes.create_unicode_buffer(1024) - serial_number = None - max_component_length = None - file_system_flags = None + """Get display name from volume mountpoint and label, returns str.""" + name = mountpoint + try: + kernel32 = ctypes.windll.kernel32 + vol_name_buffer = ctypes.create_unicode_buffer(1024) + fs_name_buffer = ctypes.create_unicode_buffer(1024) + serial_number = None + max_component_length = None + file_system_flags = None - vol_info = kernel32.GetVolumeInformationW( - ctypes.c_wchar_p(mountpoint), - vol_name_buffer, - ctypes.sizeof(vol_name_buffer), - serial_number, - max_component_length, - file_system_flags, - fs_name_buffer, - ctypes.sizeof(fs_name_buffer) - ) + vol_info = kernel32.GetVolumeInformationW( + ctypes.c_wchar_p(mountpoint), + vol_name_buffer, + ctypes.sizeof(vol_name_buffer), + serial_number, + max_component_length, + file_system_flags, + fs_name_buffer, + ctypes.sizeof(fs_name_buffer) + ) - name = '{} "{}"'.format(name, vol_name_buffer.value) - except: - pass + name = '{} "{}"'.format(name, vol_name_buffer.value) + except: + pass - return name + return name def prep_disk_for_backup(destination, disk, backup_prefix): - """Gather details about the disk and its partitions. + """Gather details about the disk and its partitions. - This includes partitions that can't be backed up, - whether backups already exist on the BACKUP_SERVER, - partition names/sizes/used space, etc.""" - disk['Clobber Risk'] = [] - width = len(str(len(disk['Partitions']))) + This includes partitions that can't be backed up, + whether backups already exist on the BACKUP_SERVER, + partition names/sizes/used space, etc.""" + disk['Clobber Risk'] = [] + width = len(str(len(disk['Partitions']))) - # Get partition totals - disk['Bad Partitions'] = [par['Number'] for par in disk['Partitions'] - if is_bad_partition(par)] - num_valid_partitions = len(disk['Partitions']) - len(disk['Bad Partitions']) - disk['Valid Partitions'] = num_valid_partitions - if disk['Valid Partitions'] <= 0: - print_error('ERROR: No partitions can be backed up for this disk') - raise GenericAbort + # Get partition totals + disk['Bad Partitions'] = [par['Number'] for par in disk['Partitions'] + if is_bad_partition(par)] + num_valid_partitions = len(disk['Partitions']) - len(disk['Bad Partitions']) + disk['Valid Partitions'] = num_valid_partitions + if disk['Valid Partitions'] <= 0: + print_error('ERROR: No partitions can be backed up for this disk') + raise GenericAbort - # Prep partitions - for par in disk['Partitions']: - display = '{size} {fs}'.format( - num = par['Number'], - width = width, - size = par['Size'], - fs = par['FileSystem']) + # Prep partitions + for par in disk['Partitions']: + display = '{size} {fs}'.format( + num = par['Number'], + width = width, + size = par['Size'], + fs = par['FileSystem']) - if par['Number'] in disk['Bad Partitions']: - # Set display string using partition description & OS type - display = '* {display}\t\t{q}{name}{q}\t{desc} ({os})'.format( - display = display, - q = '"' if par['Name'] != '' else '', - name = par['Name'], - desc = par['Description'], - os = par['OS']) - else: - # Update info for WIM capturing - par['Image Name'] = par['Name'] if par['Name'] else 'Unknown' - if 'IP' in destination: - par['Image Path'] = r'\\{}\{}\{}'.format( - destination['IP'], destination['Share'], backup_prefix) - else: - par['Image Path'] = r'{}:\{}'.format( - destination['Letter'], backup_prefix) - par['Image Path'] += r'\{}_{}.wim'.format( - par['Number'], par['Image Name']) - par['Image Path'] = fix_path(par['Image Path']) + if par['Number'] in disk['Bad Partitions']: + # Set display string using partition description & OS type + display = '* {display}\t\t{q}{name}{q}\t{desc} ({os})'.format( + display = display, + q = '"' if par['Name'] != '' else '', + name = par['Name'], + desc = par['Description'], + os = par['OS']) + else: + # Update info for WIM capturing + par['Image Name'] = par['Name'] if par['Name'] else 'Unknown' + if 'IP' in destination: + par['Image Path'] = r'\\{}\{}\{}'.format( + destination['IP'], destination['Share'], backup_prefix) + else: + par['Image Path'] = r'{}:\{}'.format( + destination['Letter'], backup_prefix) + par['Image Path'] += r'\{}_{}.wim'.format( + par['Number'], par['Image Name']) + par['Image Path'] = fix_path(par['Image Path']) - # Check for existing backups - par['Image Exists'] = os.path.exists(par['Image Path']) - if par['Image Exists']: - disk['Clobber Risk'].append(par['Number']) - display = '+ {}'.format(display) - else: - display = ' {}'.format(display) + # Check for existing backups + par['Image Exists'] = os.path.exists(par['Image Path']) + if par['Image Exists']: + disk['Clobber Risk'].append(par['Number']) + display = '+ {}'.format(display) + else: + display = ' {}'.format(display) - # Append rest of Display String for valid/clobber partitions - display += ' (Used: {used})\t{q}{name}{q}'.format( - used = par['Used Space'], - q = '"' if par['Name'] != '' else '', - name = par['Name']) - # For all partitions - par['Display String'] = display + # Append rest of Display String for valid/clobber partitions + display += ' (Used: {used})\t{q}{name}{q}'.format( + used = par['Used Space'], + q = '"' if par['Name'] != '' else '', + name = par['Name']) + # For all partitions + par['Display String'] = display - # Set description for bad partitions - warnings = '\n' - if disk['Bad Partitions']: - warnings += '{} * Unsupported filesystem{}\n'.format( - COLORS['YELLOW'], COLORS['CLEAR']) - if disk['Clobber Risk']: - warnings += '{} + Backup exists on {}{}\n'.format( - COLORS['BLUE'], destination['Name'], COLORS['CLEAR']) - if disk['Bad Partitions'] or disk['Clobber Risk']: - warnings += '\n{}Marked partition(s) will NOT be backed up.{}\n'.format( - COLORS['YELLOW'], COLORS['CLEAR']) - disk['Backup Warnings'] = warnings + # Set description for bad partitions + warnings = '\n' + if disk['Bad Partitions']: + warnings += '{} * Unsupported filesystem{}\n'.format( + COLORS['YELLOW'], COLORS['CLEAR']) + if disk['Clobber Risk']: + warnings += '{} + Backup exists on {}{}\n'.format( + COLORS['BLUE'], destination['Name'], COLORS['CLEAR']) + if disk['Bad Partitions'] or disk['Clobber Risk']: + warnings += '\n{}Marked partition(s) will NOT be backed up.{}\n'.format( + COLORS['YELLOW'], COLORS['CLEAR']) + disk['Backup Warnings'] = warnings def select_backup_destination(auto_select=True): - """Select a backup destination from a menu, returns server dict.""" - destinations = [s for s in BACKUP_SERVERS if s['Mounted']] - actions = [ - {'Name': 'Main Menu', 'Letter': 'M'}, - ] + """Select a backup destination from a menu, returns server dict.""" + destinations = [s for s in BACKUP_SERVERS if s['Mounted']] + actions = [ + {'Name': 'Main Menu', 'Letter': 'M'}, + ] - # Add local disks - for d in psutil.disk_partitions(): - if re.search(r'^{}'.format(global_vars['Env']['SYSTEMDRIVE']), d.mountpoint, re.IGNORECASE): - # Skip current OS drive - pass - elif 'fixed' in d.opts: - # Skip DVD, etc - destinations.append({ - 'Name': 'Local Disk - {}'.format( - get_volume_display_name(d.mountpoint)), - 'Letter': re.sub(r'^(\w):\\.*$', r'\1', d.mountpoint), - }) + # Add local disks + for d in psutil.disk_partitions(): + if re.search( + r'^{}'.format(global_vars['Env']['SYSTEMDRIVE']), + d.mountpoint, + re.IGNORECASE): + # Skip current OS drive + pass + elif 'fixed' in d.opts: + # Skip DVD, etc + destinations.append({ + 'Name': 'Local Disk - {}'.format( + get_volume_display_name(d.mountpoint)), + 'Letter': re.sub(r'^(\w):\\.*$', r'\1', d.mountpoint), + }) - # Size check - for dest in destinations: - if 'IP' in dest: - dest['Usage'] = shutil.disk_usage(r'\\{IP}\{Share}'.format(**dest)) - else: - dest['Usage'] = shutil.disk_usage('{}:\\'.format(dest['Letter'])) - dest['Free Space'] = human_readable_size(dest['Usage'].free) - dest['Display Name'] = '{Name} ({Free Space} available)'.format(**dest) - - # Bail - if not destinations: - print_warning('No backup destinations found.') - raise GenericAbort - - # Skip menu? - if len(destinations) == 1 and auto_select: - return destinations[0] - - selection = menu_select( - title = 'Where are we backing up to?', - main_entries = destinations, - action_entries = actions) - if selection == 'M': - raise GenericAbort + # Size check + for dest in destinations: + if 'IP' in dest: + dest['Usage'] = shutil.disk_usage(r'\\{IP}\{Share}'.format(**dest)) else: - return destinations[int(selection)-1] + dest['Usage'] = shutil.disk_usage('{}:\\'.format(dest['Letter'])) + dest['Free Space'] = human_readable_size(dest['Usage'].free) + dest['Display Name'] = '{Name} ({Free Space} available)'.format(**dest) + + # Bail + if not destinations: + print_warning('No backup destinations found.') + raise GenericAbort + + # Skip menu? + if len(destinations) == 1 and auto_select: + return destinations[0] + + selection = menu_select( + title = 'Where are we backing up to?', + main_entries = destinations, + action_entries = actions) + if selection == 'M': + raise GenericAbort + else: + return destinations[int(selection)-1] def verify_wim_backup(partition): - """Verify WIM integrity.""" - if not os.path.exists(partition['Image Path']): - raise PathNotFoundError - cmd = [ - global_vars['Tools']['wimlib-imagex'], - 'verify', - partition['Image Path'], - '--nocheck', - ] - run_program(cmd) + """Verify WIM integrity.""" + if not os.path.exists(partition['Image Path']): + raise PathNotFoundError + cmd = [ + global_vars['Tools']['wimlib-imagex'], + 'verify', + partition['Image Path'], + '--nocheck', + ] + run_program(cmd) if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From 6a3e2251922e7da89b6265774b6b66253cb2ca4c Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 19:43:12 -0700 Subject: [PATCH 156/265] Updated browsers.py --- .bin/Scripts/functions/browsers.py | 847 +++++++++++++++-------------- 1 file changed, 425 insertions(+), 422 deletions(-) diff --git a/.bin/Scripts/functions/browsers.py b/.bin/Scripts/functions/browsers.py index 143d018d..750f8af7 100644 --- a/.bin/Scripts/functions/browsers.py +++ b/.bin/Scripts/functions/browsers.py @@ -7,42 +7,42 @@ from operator import itemgetter # Define other_results for later try_and_print browser_data = {} other_results = { - 'Error': { - 'MultipleInstallationsError': 'Multiple installations detected', - }, - 'Warning': { - 'NotInstalledError': 'Not installed', - 'NoProfilesError': 'No profiles found', - } + 'Error': { + 'MultipleInstallationsError': 'Multiple installations detected', + }, + 'Warning': { + 'NotInstalledError': 'Not installed', + 'NoProfilesError': 'No profiles found', } + } # Regex REGEX_BACKUP = re.compile( - r'\.\w*bak.*', - re.IGNORECASE) + r'\.\w*bak.*', + re.IGNORECASE) REGEX_CHROMIUM_PROFILE = re.compile( - r'^(Default|Profile)', - re.IGNORECASE) + r'^(Default|Profile)', + re.IGNORECASE) REGEX_CHROMIUM_ITEMS = re.compile( - r'^(Bookmarks|Cookies|Favicons|Google Profile' - r'|History|Login Data|Top Sites|TransportSecurity' - r'|Visited Links|Web Data)', - re.IGNORECASE) + r'^(Bookmarks|Cookies|Favicons|Google Profile' + r'|History|Login Data|Top Sites|TransportSecurity' + r'|Visited Links|Web Data)', + re.IGNORECASE) REGEX_MOZILLA = re.compile( - r'^(bookmarkbackups|(cookies|formhistory|places).sqlite' - r'|key3.db|logins.json|persdict.dat)$', - re.IGNORECASE) + r'^(bookmarkbackups|(cookies|formhistory|places).sqlite' + r'|key3.db|logins.json|persdict.dat)$', + re.IGNORECASE) # STATIC VARIABLES DEFAULT_HOMEPAGE = 'https://www.google.com/' IE_GALLERY = 'https://www.microsoft.com/en-us/iegallery' MOZILLA_PREFS = { - 'browser.search.defaultenginename': '"Google"', - 'browser.search.defaultenginename.US': '"Google"', - 'browser.search.geoSpecificDefaults': 'false', - 'browser.startup.homepage': '"{}"'.format(DEFAULT_HOMEPAGE), - 'extensions.ui.lastCategory': '"addons://list/extension"', - } + 'browser.search.defaultenginename': '"Google"', + 'browser.search.defaultenginename.US': '"Google"', + 'browser.search.geoSpecificDefaults': 'false', + 'browser.startup.homepage': '"{}"'.format(DEFAULT_HOMEPAGE), + 'extensions.ui.lastCategory': '"addons://list/extension"', + } UBO_CHROME = 'https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm?hl=en' UBO_CHROME_REG = r'Software\Wow6432Node\Google\Chrome\Extensions\cjpalhdlnbpafiamejdnhcphjbkeiagm' UBO_EXTRA_CHROME = 'https://chrome.google.com/webstore/detail/ublock-origin-extra/pgdnlhfefecpicbbihgmbmffkjpaplco?hl=en' @@ -53,456 +53,459 @@ UBO_MOZILLA_REG = r'Software\Mozilla\Firefox\Extensions' UBO_MOZILLA_REG_NAME = 'uBlock0@raymondhill.net' UBO_OPERA = 'https://addons.opera.com/en/extensions/details/ublock/?display=en' SUPPORTED_BROWSERS = { - 'Internet Explorer': { - 'base': 'ie', - 'exe_name': 'iexplore.exe', - 'rel_install_path': 'Internet Explorer', - 'user_data_path': r'{USERPROFILE}\Favorites', - }, - 'Google Chrome': { - 'base': 'chromium', - 'exe_name': 'chrome.exe', - 'rel_install_path': r'Google\Chrome\Application', - 'user_data_path': r'{LOCALAPPDATA}\Google\Chrome\User Data', - }, - 'Google Chrome Canary': { - 'base': 'chromium', - 'exe_name': 'chrome.exe', - 'rel_install_path': r'Google\Chrome SxS\Application', - 'user_data_path': r'{LOCALAPPDATA}\Google\Chrome SxS\User Data', - }, - 'Mozilla Firefox': { - 'base': 'mozilla', - 'exe_name': 'firefox.exe', - 'rel_install_path': 'Mozilla Firefox', - 'user_data_path': r'{APPDATA}\Mozilla\Firefox\Profiles', - }, - 'Mozilla Firefox Dev': { - 'base': 'mozilla', - 'exe_name': 'firefox.exe', - 'rel_install_path': 'Firefox Developer Edition', - 'user_data_path': r'{APPDATA}\Mozilla\Firefox\Profiles', - }, - 'Opera': { - 'base': 'chromium', - 'exe_name': 'launcher.exe', - 'rel_install_path': 'Opera', - 'user_data_path': r'{APPDATA}\Opera Software\Opera Stable', - }, - 'Opera Beta': { - 'base': 'chromium', - 'exe_name': 'launcher.exe', - 'rel_install_path': 'Opera beta', - 'user_data_path': r'{APPDATA}\Opera Software\Opera Next', - }, - 'Opera Dev': { - 'base': 'chromium', - 'exe_name': 'launcher.exe', - 'rel_install_path': 'Opera developer', - 'user_data_path': r'{APPDATA}\Opera Software\Opera Developer', - }, - } + 'Internet Explorer': { + 'base': 'ie', + 'exe_name': 'iexplore.exe', + 'rel_install_path': 'Internet Explorer', + 'user_data_path': r'{USERPROFILE}\Favorites', + }, + 'Google Chrome': { + 'base': 'chromium', + 'exe_name': 'chrome.exe', + 'rel_install_path': r'Google\Chrome\Application', + 'user_data_path': r'{LOCALAPPDATA}\Google\Chrome\User Data', + }, + 'Google Chrome Canary': { + 'base': 'chromium', + 'exe_name': 'chrome.exe', + 'rel_install_path': r'Google\Chrome SxS\Application', + 'user_data_path': r'{LOCALAPPDATA}\Google\Chrome SxS\User Data', + }, + 'Mozilla Firefox': { + 'base': 'mozilla', + 'exe_name': 'firefox.exe', + 'rel_install_path': 'Mozilla Firefox', + 'user_data_path': r'{APPDATA}\Mozilla\Firefox\Profiles', + }, + 'Mozilla Firefox Dev': { + 'base': 'mozilla', + 'exe_name': 'firefox.exe', + 'rel_install_path': 'Firefox Developer Edition', + 'user_data_path': r'{APPDATA}\Mozilla\Firefox\Profiles', + }, + 'Opera': { + 'base': 'chromium', + 'exe_name': 'launcher.exe', + 'rel_install_path': 'Opera', + 'user_data_path': r'{APPDATA}\Opera Software\Opera Stable', + }, + 'Opera Beta': { + 'base': 'chromium', + 'exe_name': 'launcher.exe', + 'rel_install_path': 'Opera beta', + 'user_data_path': r'{APPDATA}\Opera Software\Opera Next', + }, + 'Opera Dev': { + 'base': 'chromium', + 'exe_name': 'launcher.exe', + 'rel_install_path': 'Opera developer', + 'user_data_path': r'{APPDATA}\Opera Software\Opera Developer', + }, + } def archive_all_users(): - """Create backups for all browsers for all users.""" - users_root = r'{}\Users'.format(global_vars['Env']['SYSTEMDRIVE']) - user_envs = [] + """Create backups for all browsers for all users.""" + users_root = r'{}\Users'.format(global_vars['Env']['SYSTEMDRIVE']) + user_envs = [] - # Build list of valid users - for user_name in os.listdir(users_root): - valid_user = True - if user_name in ('Default', 'Default User'): - # Skip default users - continue - user_path = os.path.join(users_root, user_name) - appdata_local = os.path.join(user_path, r'AppData\Local') - appdata_roaming = os.path.join(user_path, r'AppData\Roaming') - valid_user &= os.path.exists(appdata_local) - valid_user &= os.path.exists(appdata_roaming) - if valid_user: - user_envs.append({ - 'USERNAME': user_name, - 'USERPROFILE': user_path, - 'APPDATA': appdata_roaming, - 'LOCALAPPDATA': appdata_local}) + # Build list of valid users + for user_name in os.listdir(users_root): + valid_user = True + if user_name in ('Default', 'Default User'): + # Skip default users + continue + user_path = os.path.join(users_root, user_name) + appdata_local = os.path.join(user_path, r'AppData\Local') + appdata_roaming = os.path.join(user_path, r'AppData\Roaming') + valid_user &= os.path.exists(appdata_local) + valid_user &= os.path.exists(appdata_roaming) + if valid_user: + user_envs.append({ + 'USERNAME': user_name, + 'USERPROFILE': user_path, + 'APPDATA': appdata_roaming, + 'LOCALAPPDATA': appdata_local}) - # Backup browsers for all valid users - print_info('Backing up browsers') - for fake_env in sorted(user_envs, key=itemgetter('USERPROFILE')): - print_standard(' {}'.format(fake_env['USERNAME'])) - for b_k, b_v in sorted(SUPPORTED_BROWSERS.items()): - if b_k == 'Mozilla Firefox Dev': - continue - source_path = b_v['user_data_path'].format(**fake_env) - if not os.path.exists(source_path): - continue - source_items = source_path + '*' - archive_path = r'{BackupDir}\Browsers ({USERNAME})\{Date}'.format( - **global_vars, **fake_env) - os.makedirs(archive_path, exist_ok=True) - archive_path += r'\{}.7z'.format(b_k) - cmd = [ - global_vars['Tools']['SevenZip'], - 'a', '-aoa', '-bso0', '-bse0', '-mx=1', - archive_path, source_items] - try_and_print(message='{}...'.format(b_k), - function=run_program, cmd=cmd) - print_standard(' ') - -def archive_browser(name): - """Create backup of Browser saved in the BackupDir.""" - source = '{}*'.format(browser_data[name]['user_data_path']) - dest = r'{BackupDir}\Browsers ({USERNAME})\{Date}'.format( - **global_vars, **global_vars['Env']) - archive = r'{}\{}.7z'.format(dest, name) - os.makedirs(dest, exist_ok=True) - cmd = [ + # Backup browsers for all valid users + print_info('Backing up browsers') + for fake_env in sorted(user_envs, key=itemgetter('USERPROFILE')): + print_standard(' {}'.format(fake_env['USERNAME'])) + for b_k, b_v in sorted(SUPPORTED_BROWSERS.items()): + if b_k == 'Mozilla Firefox Dev': + continue + source_path = b_v['user_data_path'].format(**fake_env) + if not os.path.exists(source_path): + continue + source_items = source_path + '*' + archive_path = r'{BackupDir}\Browsers ({USERNAME})\{Date}'.format( + **global_vars, **fake_env) + os.makedirs(archive_path, exist_ok=True) + archive_path += r'\{}.7z'.format(b_k) + cmd = [ global_vars['Tools']['SevenZip'], 'a', '-aoa', '-bso0', '-bse0', '-mx=1', - '-mhe=on', '-p{}'.format(ARCHIVE_PASSWORD), - archive, source] - run_program(cmd) + archive_path, source_items] + try_and_print(message='{}...'.format(b_k), + function=run_program, cmd=cmd) + print_standard(' ') + +def archive_browser(name): + """Create backup of Browser saved in the BackupDir.""" + source = '{}*'.format(browser_data[name]['user_data_path']) + dest = r'{BackupDir}\Browsers ({USERNAME})\{Date}'.format( + **global_vars, **global_vars['Env']) + archive = r'{}\{}.7z'.format(dest, name) + os.makedirs(dest, exist_ok=True) + cmd = [ + global_vars['Tools']['SevenZip'], + 'a', '-aoa', '-bso0', '-bse0', '-mx=1', + '-mhe=on', '-p{}'.format(ARCHIVE_PASSWORD), + archive, source] + run_program(cmd) def backup_browsers(): - """Create backup of all detected browser profiles.""" - for name in [k for k, v in sorted(browser_data.items()) if v['profiles']]: - try_and_print(message='{}...'.format(name), - function=archive_browser, name=name) + """Create backup of all detected browser profiles.""" + for name in [k for k, v in sorted(browser_data.items()) if v['profiles']]: + try_and_print(message='{}...'.format(name), + function=archive_browser, name=name) def clean_chromium_profile(profile): - """Renames profile, creates a new folder, and copies the user data to it.""" - if profile is None: - raise Exception - backup_path = '{path}_{Date}.bak'.format( - path=profile['path'], **global_vars) - backup_path = non_clobber_rename(backup_path) - shutil.move(profile['path'], backup_path) - os.makedirs(profile['path'], exist_ok=True) + """Renames profile, creates a new folder, and copies the user data to it.""" + if profile is None: + raise Exception + backup_path = '{path}_{Date}.bak'.format( + path=profile['path'], **global_vars) + backup_path = non_clobber_rename(backup_path) + shutil.move(profile['path'], backup_path) + os.makedirs(profile['path'], exist_ok=True) - # Restore essential files from backup_path - for entry in os.scandir(backup_path): - if REGEX_CHROMIUM_ITEMS.search(entry.name): - shutil.copy(entry.path, r'{}\{}'.format( - profile['path'], entry.name)) + # Restore essential files from backup_path + for entry in os.scandir(backup_path): + if REGEX_CHROMIUM_ITEMS.search(entry.name): + shutil.copy(entry.path, r'{}\{}'.format( + profile['path'], entry.name)) def clean_internet_explorer(**kwargs): - """Uses the built-in function to reset IE and sets the homepage. + """Uses the built-in function to reset IE and sets the homepage. - NOTE: kwargs set but unused as a workaround.""" - kill_process('iexplore.exe') - run_program(['rundll32.exe', 'inetcpl.cpl,ResetIEtoDefaults'], check=False) - key = r'Software\Microsoft\Internet Explorer\Main' + NOTE: kwargs set but unused as a workaround.""" + kill_process('iexplore.exe') + run_program(['rundll32.exe', 'inetcpl.cpl,ResetIEtoDefaults'], check=False) + key = r'Software\Microsoft\Internet Explorer\Main' - # Set homepage - with winreg.OpenKey(HKCU, key, access=winreg.KEY_WRITE) as _key: - winreg.SetValueEx(_key, 'Start Page', 0, - winreg.REG_SZ, DEFAULT_HOMEPAGE) - try: - winreg.DeleteValue(_key, 'Secondary Start Pages') - except FileNotFoundError: - pass + # Set homepage + with winreg.OpenKey(HKCU, key, access=winreg.KEY_WRITE) as _key: + winreg.SetValueEx(_key, 'Start Page', 0, + winreg.REG_SZ, DEFAULT_HOMEPAGE) + try: + winreg.DeleteValue(_key, 'Secondary Start Pages') + except FileNotFoundError: + pass def clean_mozilla_profile(profile): - """Renames profile, creates a new folder, and copies the user data to it.""" - if profile is None: - raise Exception - backup_path = '{path}_{Date}.bak'.format( - path=profile['path'], **global_vars) - backup_path = non_clobber_rename(backup_path) - shutil.move(profile['path'], backup_path) - homepages = [] - os.makedirs(profile['path'], exist_ok=True) + """Renames profile, creates a new folder, and copies the user data to it.""" + if profile is None: + raise Exception + backup_path = '{path}_{Date}.bak'.format( + path=profile['path'], **global_vars) + backup_path = non_clobber_rename(backup_path) + shutil.move(profile['path'], backup_path) + homepages = [] + os.makedirs(profile['path'], exist_ok=True) - # Restore essential files from backup_path - for entry in os.scandir(backup_path): - if REGEX_MOZILLA.search(entry.name): - if entry.is_dir(): - shutil.copytree(entry.path, r'{}\{}'.format( - profile['path'], entry.name)) - else: - shutil.copy(entry.path, r'{}\{}'.format( - profile['path'], entry.name)) + # Restore essential files from backup_path + for entry in os.scandir(backup_path): + if REGEX_MOZILLA.search(entry.name): + if entry.is_dir(): + shutil.copytree(entry.path, r'{}\{}'.format( + profile['path'], entry.name)) + else: + shutil.copy(entry.path, r'{}\{}'.format( + profile['path'], entry.name)) - # Set profile defaults - with open(r'{path}\prefs.js'.format(**profile), 'a', encoding='ascii') as f: - for k, v in MOZILLA_PREFS.items(): - f.write('user_pref("{}", {});\n'.format(k, v)) + # Set profile defaults + with open(r'{path}\prefs.js'.format(**profile), 'a', encoding='ascii') as f: + for k, v in MOZILLA_PREFS.items(): + f.write('user_pref("{}", {});\n'.format(k, v)) def get_browser_details(name): - """Get installation status and profile details for all supported browsers.""" - browser = SUPPORTED_BROWSERS[name].copy() + """Get install status and profile details for all supported browsers.""" + browser = SUPPORTED_BROWSERS[name].copy() - # Update user_data_path - browser['user_data_path'] = browser['user_data_path'].format( - **global_vars['Env']) + # Update user_data_path + browser['user_data_path'] = browser['user_data_path'].format( + **global_vars['Env']) - # Find executable (if multiple files are found, the last one is used) - exe_path = None - num_installs = 0 - for install_path in ['LOCALAPPDATA', 'PROGRAMFILES(X86)', 'PROGRAMFILES']: - test_path = r'{install_path}\{rel_install_path}\{exe_name}'.format( - install_path = global_vars['Env'].get(install_path, ''), - **browser) - if os.path.exists(test_path): - num_installs += 1 - exe_path = test_path + # Find executable (if multiple files are found, the last one is used) + exe_path = None + num_installs = 0 + for install_path in ['LOCALAPPDATA', 'PROGRAMFILES(X86)', 'PROGRAMFILES']: + test_path = r'{install_path}\{rel_install_path}\{exe_name}'.format( + install_path = global_vars['Env'].get(install_path, ''), + **browser) + if os.path.exists(test_path): + num_installs += 1 + exe_path = test_path - # Find profile(s) - profiles = [] - if browser['base'] == 'ie': - profiles.append({'name': 'Default', 'path': None}) - elif 'Google Chrome' in name: - profiles.extend( - get_chromium_profiles( - search_path=browser['user_data_path'])) - elif browser['base'] == 'mozilla': - dev = 'Dev' in name - profiles.extend( - get_mozilla_profiles( - search_path=browser['user_data_path'], dev=dev)) - if exe_path and not dev and len(profiles) == 0: - # e.g. If Firefox is installed but no profiles were found. - ## Rename profiles.ini and create a new default profile - profiles_ini_path = browser['user_data_path'].replace( - 'Profiles', 'profiles.ini') - if os.path.exists(profiles_ini_path): - backup_path = '{path}_{Date}.bak'.format( - path=profiles_ini_path, **global_vars) - backup_path = non_clobber_rename(backup_path) - shutil.move(profiles_ini_path, backup_path) - run_program([exe_path, '-createprofile', 'default'], check=False) - profiles.extend( - get_mozilla_profiles( - search_path=browser['user_data_path'], dev=dev)) + # Find profile(s) + profiles = [] + if browser['base'] == 'ie': + profiles.append({'name': 'Default', 'path': None}) + elif 'Google Chrome' in name: + profiles.extend( + get_chromium_profiles( + search_path=browser['user_data_path'])) + elif browser['base'] == 'mozilla': + dev = 'Dev' in name + profiles.extend( + get_mozilla_profiles( + search_path=browser['user_data_path'], dev=dev)) + if exe_path and not dev and len(profiles) == 0: + # e.g. If Firefox is installed but no profiles were found. + ## Rename profiles.ini and create a new default profile + profiles_ini_path = browser['user_data_path'].replace( + 'Profiles', 'profiles.ini') + if os.path.exists(profiles_ini_path): + backup_path = '{path}_{Date}.bak'.format( + path=profiles_ini_path, **global_vars) + backup_path = non_clobber_rename(backup_path) + shutil.move(profiles_ini_path, backup_path) + run_program([exe_path, '-createprofile', 'default'], check=False) + profiles.extend( + get_mozilla_profiles( + search_path=browser['user_data_path'], dev=dev)) - elif 'Opera' in name: - if os.path.exists(browser['user_data_path']): - profiles.append( - {'name': 'Default', 'path': browser['user_data_path']}) + elif 'Opera' in name: + if os.path.exists(browser['user_data_path']): + profiles.append( + {'name': 'Default', 'path': browser['user_data_path']}) - # Get homepages - if browser['base'] == 'ie': - # IE is set to only have one profile above - profiles[0]['homepages'] = get_ie_homepages() - elif browser['base'] == 'mozilla': - for profile in profiles: - prefs_path = r'{path}\prefs.js'.format(**profile) - profile['homepages'] = get_mozilla_homepages(prefs_path=prefs_path) + # Get homepages + if browser['base'] == 'ie': + # IE is set to only have one profile above + profiles[0]['homepages'] = get_ie_homepages() + elif browser['base'] == 'mozilla': + for profile in profiles: + prefs_path = r'{path}\prefs.js'.format(**profile) + profile['homepages'] = get_mozilla_homepages(prefs_path=prefs_path) - # Add to browser_data - browser_data[name] = browser - browser_data[name].update({ - 'exe_path': exe_path, - 'profiles': profiles, - }) + # Add to browser_data + browser_data[name] = browser + browser_data[name].update({ + 'exe_path': exe_path, + 'profiles': profiles, + }) - # Raise installation warnings (if any) - if num_installs == 0: - raise NotInstalledError - elif num_installs > 1 and browser['base'] != 'ie': - raise MultipleInstallationsError + # Raise installation warnings (if any) + if num_installs == 0: + raise NotInstalledError + elif num_installs > 1 and browser['base'] != 'ie': + raise MultipleInstallationsError def get_chromium_profiles(search_path): - """Find any chromium-style profiles and return as a list of dicts.""" - profiles = [] - try: - for entry in os.scandir(search_path): - if entry.is_dir() and REGEX_CHROMIUM_PROFILE.search(entry.name): - profiles.append(entry) - REGEX_PROFILE_BACKUP = r'\.\w+bak.*' - profiles = [p for p in profiles if not REGEX_BACKUP.search(p.name)] - # Convert os.DirEntries to dicts - profiles = [{'name': p.name, 'path': p.path} for p in profiles] - except Exception: - pass + """Find any chromium-style profiles and return as a list of dicts.""" + profiles = [] + try: + for entry in os.scandir(search_path): + if entry.is_dir() and REGEX_CHROMIUM_PROFILE.search(entry.name): + profiles.append(entry) + REGEX_PROFILE_BACKUP = r'\.\w+bak.*' + profiles = [p for p in profiles if not REGEX_BACKUP.search(p.name)] + # Convert os.DirEntries to dicts + profiles = [{'name': p.name, 'path': p.path} for p in profiles] + except Exception: + pass - return profiles + return profiles def get_ie_homepages(): - """Read homepages from the registry and return as a list.""" - homepages = [] - main_page = '' - extra_pages = [] - key = r'Software\Microsoft\Internet Explorer\Main' - with winreg.OpenKey(HKCU, key) as _key: - try: - main_page = winreg.QueryValueEx(_key, 'Start Page')[0] - except FileNotFoundError: - pass - try: - extra_pages = winreg.QueryValueEx(_key, 'Secondary Start Pages')[0] - except FileNotFoundError: - pass - if main_page != '': - homepages.append(main_page) - if len(extra_pages) > 0: - homepages.extend(extra_pages) + """Read homepages from the registry and return as a list.""" + homepages = [] + main_page = '' + extra_pages = [] + key = r'Software\Microsoft\Internet Explorer\Main' + with winreg.OpenKey(HKCU, key) as _key: + try: + main_page = winreg.QueryValueEx(_key, 'Start Page')[0] + except FileNotFoundError: + pass + try: + extra_pages = winreg.QueryValueEx(_key, 'Secondary Start Pages')[0] + except FileNotFoundError: + pass + if main_page != '': + homepages.append(main_page) + if len(extra_pages) > 0: + homepages.extend(extra_pages) - # Remove all curly braces - homepages = [h.replace('{', '').replace('}', '') for h in homepages] - return homepages + # Remove all curly braces + homepages = [h.replace('{', '').replace('}', '') for h in homepages] + return homepages def get_mozilla_homepages(prefs_path): - """Read homepages from prefs.js and return as a list.""" - homepages = [] - try: - with open(prefs_path, 'r') as f: - search = re.search( - r'browser\.startup\.homepage", "([^"]*)"', - f.read(), re.IGNORECASE) - if search: - homepages = search.group(1).split('|') - except Exception: - pass + """Read homepages from prefs.js and return as a list.""" + homepages = [] + try: + with open(prefs_path, 'r') as f: + search = re.search( + r'browser\.startup\.homepage", "([^"]*)"', + f.read(), re.IGNORECASE) + if search: + homepages = search.group(1).split('|') + except Exception: + pass - return homepages + return homepages def get_mozilla_profiles(search_path, dev=False): - """Find any mozilla-style profiles and return as a list of dicts.""" - profiles = [] - try: - for entry in os.scandir(search_path): - if entry.is_dir(): - if 'dev-edition' in entry.name: - # NOTE: Not always present which can lead - # to Dev profiles being marked as non-Dev - ## NOTE 2: It is possible that a non-Dev profile - ## to be created with 'dev-edition' in the name. - ## (It wouldn't make sense, but possible) - if dev: - profiles.append(entry) - elif not dev: - profiles.append(entry) - profiles = [p for p in profiles if not REGEX_BACKUP.search(p.name)] - # Convert os.DirEntries to dicts - profiles = [{'name': p.name, 'path': p.path} for p in profiles] - except Exception: - pass + """Find any mozilla-style profiles and return as a list of dicts.""" + profiles = [] + try: + for entry in os.scandir(search_path): + if entry.is_dir(): + if 'dev-edition' in entry.name: + # NOTE: Not always present which can lead + # to Dev profiles being marked as non-Dev + ## NOTE 2: It is possible that a non-Dev profile + ## to be created with 'dev-edition' in the name. + ## (It wouldn't make sense, but possible) + if dev: + profiles.append(entry) + elif not dev: + profiles.append(entry) + profiles = [p for p in profiles if not REGEX_BACKUP.search(p.name)] + # Convert os.DirEntries to dicts + profiles = [{'name': p.name, 'path': p.path} for p in profiles] + except Exception: + pass - return profiles + return profiles def install_adblock(indent=8, width=32, just_firefox=False): - """Install adblock for all supported browsers.""" - for browser in sorted(browser_data): - if just_firefox and browser_data[browser]['base'] != 'mozilla': - continue - exe_path = browser_data[browser].get('exe_path', None) - function=run_program - if not exe_path: - if browser_data[browser]['profiles']: - print_standard( - '{indent}{browser:<{width}}'.format( - indent=' '*indent, width=width, browser=browser+'...'), - end='', flush=True) - print_warning('Profile(s) detected but browser not installed', - timestamp=False) - else: - # Only warn if profile(s) are detected. - pass + """Install adblock for all supported browsers.""" + for browser in sorted(browser_data): + if just_firefox and browser_data[browser]['base'] != 'mozilla': + continue + exe_path = browser_data[browser].get('exe_path', None) + function=run_program + if not exe_path: + if browser_data[browser]['profiles']: + print_standard( + '{indent}{browser:<{width}}'.format( + indent=' '*indent, width=width, browser=browser+'...'), + end='', flush=True) + print_warning('Profile(s) detected but browser not installed', + timestamp=False) + else: + # Only warn if profile(s) are detected. + pass + else: + # Set urls to open + urls = [] + if browser_data[browser]['base'] == 'chromium': + if browser == 'Google Chrome': + # Check for system exensions + try: + winreg.QueryValue(HKLM, UBO_CHROME_REG) + except FileNotFoundError: + urls.append(UBO_CHROME) + try: + winreg.QueryValue(HKLM, UBO_EXTRA_CHROME_REG) + except FileNotFoundError: + urls.append(UBO_EXTRA_CHROME) + + if len(urls) == 0: + urls = ['chrome://extensions'] + elif 'Opera' in browser: + urls.append(UBO_OPERA) else: - # Set urls to open - urls = [] - if browser_data[browser]['base'] == 'chromium': - if browser == 'Google Chrome': - # Check for system exensions - try: - winreg.QueryValue(HKLM, UBO_CHROME_REG) - except FileNotFoundError: - urls.append(UBO_CHROME) - try: - winreg.QueryValue(HKLM, UBO_EXTRA_CHROME_REG) - except FileNotFoundError: - urls.append(UBO_EXTRA_CHROME) + urls.append(UBO_CHROME) + urls.append(UBO_EXTRA_CHROME) - if len(urls) == 0: - urls = ['chrome://extensions'] - elif 'Opera' in browser: - urls.append(UBO_OPERA) - else: - urls.append(UBO_CHROME) - urls.append(UBO_EXTRA_CHROME) + elif browser_data[browser]['base'] == 'mozilla': + # Check for system extensions + try: + with winreg.OpenKey(HKLM, UBO_MOZILLA_REG) as key: + winreg.QueryValueEx(key, UBO_MOZILLA_REG_NAME) + except FileNotFoundError: + urls = [UBO_MOZILLA] + else: + if os.path.exists(UBO_MOZZILA_PATH): + urls = ['about:addons'] + else: + urls = [UBO_MOZILLA] - elif browser_data[browser]['base'] == 'mozilla': - # Check for system extensions - try: - with winreg.OpenKey(HKLM, UBO_MOZILLA_REG) as key: - winreg.QueryValueEx(key, UBO_MOZILLA_REG_NAME) - except FileNotFoundError: - urls = [UBO_MOZILLA] - else: - if os.path.exists(UBO_MOZZILA_PATH): - urls = ['about:addons'] - else: - urls = [UBO_MOZILLA] + elif browser_data[browser]['base'] == 'ie': + urls.append(IE_GALLERY) + function=popen_program - elif browser_data[browser]['base'] == 'ie': - urls.append(IE_GALLERY) - function=popen_program - - # By using check=False we're skipping any return codes so - # it should only fail if the program can't be run - # (or can't be found). - # In other words, this isn't tracking the addon/extension's - # installation status. - try_and_print(message='{}...'.format(browser), - indent=indent, width=width, - cs='Done', function=function, - cmd=[exe_path, *urls], check=False) + # By using check=False we're skipping any return codes so + # it should only fail if the program can't be run + # (or can't be found). + # In other words, this isn't tracking the addon/extension's + # installation status. + try_and_print(message='{}...'.format(browser), + indent=indent, width=width, + cs='Done', function=function, + cmd=[exe_path, *urls], check=False) def list_homepages(indent=8, width=32): - """List current homepages for reference.""" + """List current homepages for reference.""" + browser_list = [k for k, v in sorted(browser_data.items()) if v['exe_path']] + for browser in browser_list: + # Skip Chromium-based browsers + if browser_data[browser]['base'] == 'chromium': + print_info( + '{indent}{browser:<{width}}'.format( + indent=' '*indent, width=width, browser=browser+'...'), + end='', flush=True) + print_warning('Not implemented', timestamp=False) + continue - for browser in [k for k, v in sorted(browser_data.items()) if v['exe_path']]: - # Skip Chromium-based browsers - if browser_data[browser]['base'] == 'chromium': - print_info( - '{indent}{browser:<{width}}'.format( - indent=' '*indent, width=width, browser=browser+'...'), - end='', flush=True) - print_warning('Not implemented', timestamp=False) - continue - - # All other browsers - print_info('{indent}{browser:<{width}}'.format( - indent=' '*indent, width=width, browser=browser+'...')) - for profile in browser_data[browser].get('profiles', []): - name = profile.get('name', '?') - homepages = profile.get('homepages', []) - if len(homepages) == 0: - print_standard( - '{indent}{name:<{width}}'.format( - indent=' '*indent, width=width, name=name), - end='', flush=True) - print_warning('None found', timestamp=False) - else: - for page in homepages: - print_standard('{indent}{name:<{width}}{page}'.format( - indent=' '*indent, width=width, name=name, page=page)) + # All other browsers + print_info('{indent}{browser:<{width}}'.format( + indent=' '*indent, width=width, browser=browser+'...')) + for profile in browser_data[browser].get('profiles', []): + name = profile.get('name', '?') + homepages = profile.get('homepages', []) + if len(homepages) == 0: + print_standard( + '{indent}{name:<{width}}'.format( + indent=' '*indent, width=width, name=name), + end='', flush=True) + print_warning('None found', timestamp=False) + else: + for page in homepages: + print_standard('{indent}{name:<{width}}{page}'.format( + indent=' '*indent, width=width, name=name, page=page)) def reset_browsers(indent=8, width=32): - """Reset all detected browsers to safe defaults.""" - for browser in [k for k, v in sorted(browser_data.items()) if v['profiles']]: - print_info('{indent}{name}'.format(indent=' '*indent, name=browser)) - for profile in browser_data[browser]['profiles']: - if browser_data[browser]['base'] == 'chromium': - function = clean_chromium_profile - elif browser_data[browser]['base'] == 'ie': - function = clean_internet_explorer - elif browser_data[browser]['base'] == 'mozilla': - function = clean_mozilla_profile - try_and_print( - message='{}...'.format(profile['name']), - indent=indent, width=width, function=function, - other_results=other_results, profile=profile) + """Reset all detected browsers to safe defaults.""" + browser_list = [k for k, v in sorted(browser_data.items()) if v['profiles']] + for browser in browser_list: + print_info('{indent}{name}'.format(indent=' '*indent, name=browser)) + for profile in browser_data[browser]['profiles']: + if browser_data[browser]['base'] == 'chromium': + function = clean_chromium_profile + elif browser_data[browser]['base'] == 'ie': + function = clean_internet_explorer + elif browser_data[browser]['base'] == 'mozilla': + function = clean_mozilla_profile + try_and_print( + message='{}...'.format(profile['name']), + indent=indent, width=width, function=function, + other_results=other_results, profile=profile) def scan_for_browsers(just_firefox=False): - """Scan system for any supported browsers.""" - for name, details in sorted(SUPPORTED_BROWSERS.items()): - if just_firefox and details['base'] != 'mozilla': - continue - try_and_print(message='{}...'.format(name), - function=get_browser_details, cs='Detected', - other_results=other_results, name=name) + """Scan system for any supported browsers.""" + for name, details in sorted(SUPPORTED_BROWSERS.items()): + if just_firefox and details['base'] != 'mozilla': + continue + try_and_print(message='{}...'.format(name), + function=get_browser_details, cs='Detected', + other_results=other_results, name=name) if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From 327c5b8a3393e7d1960c3f33b943e5a4d2114be9 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 19:43:25 -0700 Subject: [PATCH 157/265] Updated cleanup.py --- .bin/Scripts/functions/cleanup.py | 196 +++++++++++++++--------------- 1 file changed, 98 insertions(+), 98 deletions(-) diff --git a/.bin/Scripts/functions/cleanup.py b/.bin/Scripts/functions/cleanup.py index d401b555..80ffd879 100644 --- a/.bin/Scripts/functions/cleanup.py +++ b/.bin/Scripts/functions/cleanup.py @@ -3,127 +3,127 @@ from functions.common import * def cleanup_adwcleaner(): - """Move AdwCleaner folders into the ClientDir.""" - source_path = r'{SYSTEMDRIVE}\AdwCleaner'.format(**global_vars['Env']) - source_quarantine = r'{}\Quarantine'.format(source_path) + """Move AdwCleaner folders into the ClientDir.""" + source_path = r'{SYSTEMDRIVE}\AdwCleaner'.format(**global_vars['Env']) + source_quarantine = r'{}\Quarantine'.format(source_path) - # Quarantine - if os.path.exists(source_quarantine): - os.makedirs(global_vars['QuarantineDir'], exist_ok=True) - dest_name = r'{QuarantineDir}\AdwCleaner_{Date-Time}'.format( - **global_vars) - dest_name = non_clobber_rename(dest_name) - shutil.move(source_quarantine, dest_name) + # Quarantine + if os.path.exists(source_quarantine): + os.makedirs(global_vars['QuarantineDir'], exist_ok=True) + dest_name = r'{QuarantineDir}\AdwCleaner_{Date-Time}'.format( + **global_vars) + dest_name = non_clobber_rename(dest_name) + shutil.move(source_quarantine, dest_name) - # Delete source folder if empty - delete_empty_folders(source_path) + # Delete source folder if empty + delete_empty_folders(source_path) - # Main folder - if os.path.exists(source_path): - os.makedirs(global_vars['LogDir'], exist_ok=True) - dest_name = r'{LogDir}\Tools\AdwCleaner'.format( - **global_vars) - dest_name = non_clobber_rename(dest_name) - shutil.move(source_path, dest_name) + # Main folder + if os.path.exists(source_path): + os.makedirs(global_vars['LogDir'], exist_ok=True) + dest_name = r'{LogDir}\Tools\AdwCleaner'.format( + **global_vars) + dest_name = non_clobber_rename(dest_name) + shutil.move(source_path, dest_name) def cleanup_cbs(dest_folder): - """Safely cleanup a known CBS archive bug under Windows 7. + """Safely cleanup a known CBS archive bug under Windows 7. - If a CbsPersist file is larger than 2 Gb then the auto archive feature - continually fails and will fill up the system drive with temp files. + If a CbsPersist file is larger than 2 Gb then the auto archive feature + continually fails and will fill up the system drive with temp files. - This function moves the temp files and CbsPersist file to a temp folder, - compresses the CbsPersist files with 7-Zip, and then opens the temp folder - for the user to manually save the backup files and delete the temp files. - """ - backup_folder = r'{dest_folder}\CbsFix'.format(dest_folder=dest_folder) - temp_folder = r'{backup_folder}\Temp'.format(backup_folder=backup_folder) - os.makedirs(backup_folder, exist_ok=True) - os.makedirs(temp_folder, exist_ok=True) + This function moves the temp files and CbsPersist file to a temp folder, + compresses the CbsPersist files with 7-Zip, and then opens the temp folder + for the user to manually save the backup files and delete the temp files. + """ + backup_folder = r'{dest_folder}\CbsFix'.format(dest_folder=dest_folder) + temp_folder = r'{backup_folder}\Temp'.format(backup_folder=backup_folder) + os.makedirs(backup_folder, exist_ok=True) + os.makedirs(temp_folder, exist_ok=True) - # Move files into temp folder - cbs_path = r'{SYSTEMROOT}\Logs\CBS'.format(**global_vars['Env']) - for entry in os.scandir(cbs_path): - # CbsPersist files - if entry.name.lower().startswith('cbspersist'): - dest_name = r'{}\{}'.format(temp_folder, entry.name) - dest_name = non_clobber_rename(dest_name) - shutil.move(entry.path, dest_name) - temp_path = r'{SYSTEMROOT}\Temp'.format(**global_vars['Env']) - for entry in os.scandir(temp_path): - # cab_ files - if entry.name.lower().startswith('cab_'): - dest_name = r'{}\{}'.format(temp_folder, entry.name) - dest_name = non_clobber_rename(dest_name) - shutil.move(entry.path, dest_name) + # Move files into temp folder + cbs_path = r'{SYSTEMROOT}\Logs\CBS'.format(**global_vars['Env']) + for entry in os.scandir(cbs_path): + # CbsPersist files + if entry.name.lower().startswith('cbspersist'): + dest_name = r'{}\{}'.format(temp_folder, entry.name) + dest_name = non_clobber_rename(dest_name) + shutil.move(entry.path, dest_name) + temp_path = r'{SYSTEMROOT}\Temp'.format(**global_vars['Env']) + for entry in os.scandir(temp_path): + # cab_ files + if entry.name.lower().startswith('cab_'): + dest_name = r'{}\{}'.format(temp_folder, entry.name) + dest_name = non_clobber_rename(dest_name) + shutil.move(entry.path, dest_name) - # Compress CbsPersist files with 7-Zip - cmd = [ - global_vars['Tools']['SevenZip'], - 'a', '-t7z', '-mx=3', '-bso0', '-bse0', - r'{}\CbsPersists.7z'.format(backup_folder), - r'{}\CbsPersist*'.format(temp_folder)] - run_program(cmd) + # Compress CbsPersist files with 7-Zip + cmd = [ + global_vars['Tools']['SevenZip'], + 'a', '-t7z', '-mx=3', '-bso0', '-bse0', + r'{}\CbsPersists.7z'.format(backup_folder), + r'{}\CbsPersist*'.format(temp_folder)] + run_program(cmd) def cleanup_desktop(): - """Move known backup files and reports into the ClientDir.""" - dest_folder = r'{LogDir}\Tools'.format(**global_vars) - os.makedirs(dest_folder, exist_ok=True) + """Move known backup files and reports into the ClientDir.""" + dest_folder = r'{LogDir}\Tools'.format(**global_vars) + os.makedirs(dest_folder, exist_ok=True) - desktop_path = r'{USERPROFILE}\Desktop'.format(**global_vars['Env']) - for entry in os.scandir(desktop_path): - # JRT, RKill, Shortcut cleaner - if re.search(r'^(JRT|RKill|sc-cleaner)', entry.name, re.IGNORECASE): - dest_name = r'{}\{}'.format(dest_folder, entry.name) - dest_name = non_clobber_rename(dest_name) - shutil.move(entry.path, dest_name) + desktop_path = r'{USERPROFILE}\Desktop'.format(**global_vars['Env']) + for entry in os.scandir(desktop_path): + # JRT, RKill, Shortcut cleaner + if re.search(r'^(JRT|RKill|sc-cleaner)', entry.name, re.IGNORECASE): + dest_name = r'{}\{}'.format(dest_folder, entry.name) + dest_name = non_clobber_rename(dest_name) + shutil.move(entry.path, dest_name) - # Remove dir if empty - delete_empty_folders(dest_folder) + # Remove dir if empty + delete_empty_folders(dest_folder) def delete_empty_folders(folder_path): - """Delete all empty folders in path (depth first).""" - if not os.path.exists(folder_path) or not os.path.isdir(folder_path): - # Bail early (silently) - return + """Delete all empty folders in path (depth first).""" + if not os.path.exists(folder_path) or not os.path.isdir(folder_path): + # Bail early (silently) + return - # Delete empty subfolders first - for item in os.scandir(folder_path): - if item.is_dir(): - delete_empty_folders(item.path) + # Delete empty subfolders first + for item in os.scandir(folder_path): + if item.is_dir(): + delete_empty_folders(item.path) - # Remove top folder - try: - os.rmdir(folder_path) - except OSError: - pass + # Remove top folder + try: + os.rmdir(folder_path) + except OSError: + pass def delete_registry_key(hive, key, recurse=False): - """Delete a registry key and all it's subkeys.""" - access = winreg.KEY_ALL_ACCESS + """Delete a registry key and all it's subkeys.""" + access = winreg.KEY_ALL_ACCESS - try: - if recurse: - # Delete all subkeys first - with winreg.OpenKeyEx(hive, key, 0, access) as k: - key_info = winreg.QueryInfoKey(k) - for x in range(key_info[0]): - subkey = r'{}\{}'.format(key, winreg.EnumKey(k, 0)) - delete_registry_key(hive, subkey) + try: + if recurse: + # Delete all subkeys first + with winreg.OpenKeyEx(hive, key, 0, access) as k: + key_info = winreg.QueryInfoKey(k) + for x in range(key_info[0]): + subkey = r'{}\{}'.format(key, winreg.EnumKey(k, 0)) + delete_registry_key(hive, subkey) - # Delete key - winreg.DeleteKey(hive, key) - except FileNotFoundError: - # Ignore - pass + # Delete key + winreg.DeleteKey(hive, key) + except FileNotFoundError: + # Ignore + pass def delete_registry_value(hive, key, value): - """Delete a registry value.""" - access = winreg.KEY_ALL_ACCESS - with winreg.OpenKeyEx(hive, key, 0, access) as k: - winreg.DeleteValue(k, value) + """Delete a registry value.""" + access = winreg.KEY_ALL_ACCESS + with winreg.OpenKeyEx(hive, key, 0, access) as k: + winreg.DeleteValue(k, value) if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") -# vim: sts=4 sw=4 ts=4 +# vim: sts=2 sw=2 ts=2 From c74e2c766717e02468bc590ae932c7f2c24ef67c Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 19:43:37 -0700 Subject: [PATCH 158/265] Updated common.py --- .bin/Scripts/functions/common.py | 1272 +++++++++++++++--------------- 1 file changed, 642 insertions(+), 630 deletions(-) diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index 82c65bb1..24f8c1d5 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -9,10 +9,10 @@ import sys import time import traceback try: - import winreg + import winreg except ModuleNotFoundError: - if psutil.WINDOWS: - raise + if psutil.WINDOWS: + raise from subprocess import CalledProcessError @@ -25,809 +25,821 @@ global_vars = {} # STATIC VARIABLES COLORS = { - 'CLEAR': '\033[0m', - 'RED': '\033[31m', - 'ORANGE': '\033[31;1m', - 'GREEN': '\033[32m', - 'YELLOW': '\033[33m', - 'BLUE': '\033[34m', - 'CYAN': '\033[36m', + 'CLEAR': '\033[0m', + 'RED': '\033[31m', + 'ORANGE': '\033[31;1m', + 'GREEN': '\033[32m', + 'YELLOW': '\033[33m', + 'BLUE': '\033[34m', + 'CYAN': '\033[36m', } try: - HKU = winreg.HKEY_USERS - HKCR = winreg.HKEY_CLASSES_ROOT - HKCU = winreg.HKEY_CURRENT_USER - HKLM = winreg.HKEY_LOCAL_MACHINE + HKU = winreg.HKEY_USERS + HKCR = winreg.HKEY_CLASSES_ROOT + HKCU = winreg.HKEY_CURRENT_USER + HKLM = winreg.HKEY_LOCAL_MACHINE except NameError: - if psutil.WINDOWS: - raise + if psutil.WINDOWS: + raise # Error Classes class BIOSKeyNotFoundError(Exception): - pass + pass class BinNotFoundError(Exception): - pass + pass class GenericAbort(Exception): - pass + pass class GenericError(Exception): - pass + pass class GenericRepair(Exception): - pass + pass class MultipleInstallationsError(Exception): - pass + pass class NotInstalledError(Exception): - pass + pass class NoProfilesError(Exception): - pass + pass class OSInstalledLegacyError(Exception): - pass + pass class PathNotFoundError(Exception): - pass + pass class UnsupportedOSError(Exception): - pass + pass class SecureBootDisabledError(Exception): - pass + pass class SecureBootNotAvailError(Exception): - pass + pass class SecureBootUnknownError(Exception): - pass + pass # General functions def abort(): - """Abort script.""" - print_warning('Aborted.') - sleep(1) - pause(prompt='Press Enter to exit... ') - exit_script() + """Abort script.""" + print_warning('Aborted.') + sleep(1) + pause(prompt='Press Enter to exit... ') + exit_script() def ask(prompt='Kotaero!'): - """Prompt the user with a Y/N question, log answer, and return a bool.""" - answer = None - prompt = '{} [Y/N]: '.format(prompt) - while answer is None: - tmp = input(prompt) - if re.search(r'^y(es|)$', tmp, re.IGNORECASE): - answer = True - elif re.search(r'^n(o|ope|)$', tmp, re.IGNORECASE): - answer = False - message = '{prompt}{answer_text}'.format( - prompt = prompt, - answer_text = 'Yes' if answer else 'No') - print_log(message=message) - return answer + """Prompt the user with a Y/N question, log answer, and return a bool.""" + answer = None + prompt = '{} [Y/N]: '.format(prompt) + while answer is None: + tmp = input(prompt) + if re.search(r'^y(es|)$', tmp, re.IGNORECASE): + answer = True + elif re.search(r'^n(o|ope|)$', tmp, re.IGNORECASE): + answer = False + message = '{prompt}{answer_text}'.format( + prompt = prompt, + answer_text = 'Yes' if answer else 'No') + print_log(message=message) + return answer def choice(choices, prompt='Kotaero!'): - """Prompt the user with a choice question, log answer, and returns str.""" - answer = None - choices = [str(c) for c in choices] - choices_short = {c[:1].upper(): c for c in choices} - prompt = '{} [{}]: '.format(prompt, '/'.join(choices)) - regex = '^({}|{})$'.format( - '|'.join([c[:1] for c in choices]), - '|'.join(choices)) + """Prompt the user with a choice question, log answer, and returns str.""" + answer = None + choices = [str(c) for c in choices] + choices_short = {c[:1].upper(): c for c in choices} + prompt = '{} [{}]: '.format(prompt, '/'.join(choices)) + regex = '^({}|{})$'.format( + '|'.join([c[:1] for c in choices]), + '|'.join(choices)) - # Get user's choice - while answer is None: - tmp = input(prompt) - if re.search(regex, tmp, re.IGNORECASE): - answer = tmp + # Get user's choice + while answer is None: + tmp = input(prompt) + if re.search(regex, tmp, re.IGNORECASE): + answer = tmp - # Log result - message = '{prompt}{answer_text}'.format( - prompt = prompt, - answer_text = 'Yes' if answer else 'No') - print_log(message=message) + # Log result + message = '{prompt}{answer_text}'.format( + prompt = prompt, + answer_text = 'Yes' if answer else 'No') + print_log(message=message) - # Fix answer formatting to match provided values - answer = choices_short[answer[:1].upper()] + # Fix answer formatting to match provided values + answer = choices_short[answer[:1].upper()] - # Done - return answer + # Done + return answer def clear_screen(): - """Simple wrapper for cls/clear.""" - if psutil.WINDOWS: - os.system('cls') - else: - os.system('clear') + """Simple wrapper for cls/clear.""" + if psutil.WINDOWS: + os.system('cls') + else: + os.system('clear') def convert_to_bytes(size): - """Convert human-readable size str to bytes and return an int.""" - size = str(size) - tmp = re.search(r'(\d+\.?\d*)\s+([KMGT]B)', size.upper()) - if tmp: - size = float(tmp.group(1)) - units = tmp.group(2) - if units == 'TB': - size *= 1099511627776 - elif units == 'GB': - size *= 1073741824 - elif units == 'MB': - size *= 1048576 - elif units == 'KB': - size *= 1024 - size = int(size) - else: - return -1 + """Convert human-readable size str to bytes and return an int.""" + size = str(size) + tmp = re.search(r'(\d+\.?\d*)\s+([KMGT]B)', size.upper()) + if tmp: + size = float(tmp.group(1)) + units = tmp.group(2) + if units == 'TB': + size *= 1099511627776 + elif units == 'GB': + size *= 1073741824 + elif units == 'MB': + size *= 1048576 + elif units == 'KB': + size *= 1024 + size = int(size) + else: + return -1 - return size + return size def exit_script(return_value=0): - """Exits the script after some cleanup and opens the log (if set).""" - # Remove dirs (if empty) - for dir in ['BackupDir', 'LogDir', 'TmpDir']: - try: - os.rmdir(global_vars[dir]) - except Exception: - pass + """Exits the script after some cleanup and opens the log (if set).""" + # Remove dirs (if empty) + for dir in ['BackupDir', 'LogDir', 'TmpDir']: + try: + os.rmdir(global_vars[dir]) + except Exception: + pass - # Open Log (if it exists) - log = global_vars.get('LogFile', '') - if log and os.path.exists(log) and psutil.WINDOWS and ENABLED_OPEN_LOGS: - try: - extract_item('NotepadPlusPlus', silent=True) - popen_program( - [global_vars['Tools']['NotepadPlusPlus'], - global_vars['LogFile']]) - except Exception: - print_error('ERROR: Failed to extract Notepad++ and open log.') - pause('Press Enter to exit...') + # Open Log (if it exists) + log = global_vars.get('LogFile', '') + if log and os.path.exists(log) and psutil.WINDOWS and ENABLED_OPEN_LOGS: + try: + extract_item('NotepadPlusPlus', silent=True) + popen_program( + [global_vars['Tools']['NotepadPlusPlus'], + global_vars['LogFile']]) + except Exception: + print_error('ERROR: Failed to extract Notepad++ and open log.') + pause('Press Enter to exit...') - # Kill Caffeine if still running - kill_process('caffeine.exe') + # Kill Caffeine if still running + kill_process('caffeine.exe') - # Exit - sys.exit(return_value) + # Exit + sys.exit(return_value) def extract_item(item, filter='', silent=False): - """Extract item from .cbin into .bin.""" - cmd = [ - global_vars['Tools']['SevenZip'], 'x', '-aos', '-bso0', '-bse0', - '-p{ArchivePassword}'.format(**global_vars), - r'-o{BinDir}\{item}'.format(item=item, **global_vars), - r'{CBinDir}\{item}.7z'.format(item=item, **global_vars), - filter] + """Extract item from .cbin into .bin.""" + cmd = [ + global_vars['Tools']['SevenZip'], 'x', '-aos', '-bso0', '-bse0', + '-p{ArchivePassword}'.format(**global_vars), + r'-o{BinDir}\{item}'.format(item=item, **global_vars), + r'{CBinDir}\{item}.7z'.format(item=item, **global_vars), + filter] + if not silent: + print_standard('Extracting "{item}"...'.format(item=item)) + try: + run_program(cmd) + except FileNotFoundError: if not silent: - print_standard('Extracting "{item}"...'.format(item=item)) - try: - run_program(cmd) - except FileNotFoundError: - if not silent: - print_warning('WARNING: Archive not found') - except subprocess.CalledProcessError: - if not silent: - print_warning('WARNING: Errors encountered while exctracting data') + print_warning('WARNING: Archive not found') + except subprocess.CalledProcessError: + if not silent: + print_warning('WARNING: Errors encountered while exctracting data') def get_process(name=None): - """Get process by name, returns psutil.Process obj.""" - proc = None - if not name: - raise GenericError + """Get process by name, returns psutil.Process obj.""" + proc = None + if not name: + raise GenericError - for p in psutil.process_iter(): - try: - if p.name() == name: - proc = p - except psutil._exceptions.NoSuchProcess: - # Process finished during iteration? Going to ignore - pass - return proc + for p in psutil.process_iter(): + try: + if p.name() == name: + proc = p + except psutil._exceptions.NoSuchProcess: + # Process finished during iteration? Going to ignore + pass + return proc def get_simple_string(prompt='Enter string'): - """Get string from user (minimal allowed character set) and return as str.""" - simple_string = None - while simple_string is None: - _input = input('{}: '.format(prompt)) - if re.match(r"^(\w|-| |\.|')+$", _input, re.ASCII): - simple_string = _input.strip() - return simple_string + """Get string from user (restricted character set), returns str.""" + simple_string = None + while simple_string is None: + _input = input('{}: '.format(prompt)) + if re.match(r"^(\w|-| |\.|')+$", _input, re.ASCII): + simple_string = _input.strip() + return simple_string def get_ticket_number(): - """Get TicketNumber from user, save in LogDir, and return as str.""" - if not ENABLED_TICKET_NUMBERS: - return None - ticket_number = None - while ticket_number is None: - _input = input('Enter ticket number: ') - if re.match(r'^([0-9]+([-_]?\w+|))$', _input): - ticket_number = _input - out_file = r'{}\TicketNumber'.format(global_vars['LogDir']) - if not psutil.WINDOWS: - out_file = out_file.replace('\\', '/') - with open(out_file, 'w', encoding='utf-8') as f: - f.write(ticket_number) - return ticket_number + """Get TicketNumber from user, save in LogDir, and return as str.""" + if not ENABLED_TICKET_NUMBERS: + return None + ticket_number = None + while ticket_number is None: + _input = input('Enter ticket number: ') + if re.match(r'^([0-9]+([-_]?\w+|))$', _input): + ticket_number = _input + out_file = r'{}\TicketNumber'.format(global_vars['LogDir']) + if not psutil.WINDOWS: + out_file = out_file.replace('\\', '/') + with open(out_file, 'w', encoding='utf-8') as f: + f.write(ticket_number) + return ticket_number def human_readable_size(size, decimals=0): - """Convert size in bytes to a human-readable format and return a str.""" - # Prep string formatting - width = 3+decimals - if decimals > 0: - width += 1 + """Convert size in bytes to a human-readable format and return a str.""" + # Prep string formatting + width = 3+decimals + if decimals > 0: + width += 1 - # Convert size to int - try: - size = int(size) - except ValueError: - size = convert_to_bytes(size) - except TypeError: - size = -1 + # Convert size to int + try: + size = int(size) + except ValueError: + size = convert_to_bytes(size) + except TypeError: + size = -1 - # Verify we have a valid size - if size < 0: - return '{size:>{width}} b'.format(size='???', width=width) + # Verify we have a valid size + if size < 0: + return '{size:>{width}} b'.format(size='???', width=width) - # Convert to sensible units - if size >= 1099511627776: - size /= 1099511627776 - units = 'Tb' - elif size >= 1073741824: - size /= 1073741824 - units = 'Gb' - elif size >= 1048576: - size /= 1048576 - units = 'Mb' - elif size >= 1024: - size /= 1024 - units = 'Kb' - else: - units = ' b' + # Convert to sensible units + if size >= 1099511627776: + size /= 1099511627776 + units = 'Tb' + elif size >= 1073741824: + size /= 1073741824 + units = 'Gb' + elif size >= 1048576: + size /= 1048576 + units = 'Mb' + elif size >= 1024: + size /= 1024 + units = 'Kb' + else: + units = ' b' - # Return - return '{size:>{width}.{decimals}f} {units}'.format( - size=size, width=width, decimals=decimals, units=units) + # Return + return '{size:>{width}.{decimals}f} {units}'.format( + size=size, width=width, decimals=decimals, units=units) def kill_process(name): - """Kill any running caffeine.exe processes.""" - for proc in psutil.process_iter(): - if proc.name() == name: - proc.kill() + """Kill any running caffeine.exe processes.""" + for proc in psutil.process_iter(): + if proc.name() == name: + proc.kill() def major_exception(): - """Display traceback and exit""" - print_error('Major exception') - print_warning(SUPPORT_MESSAGE) - print(traceback.format_exc()) - print_log(traceback.format_exc()) - try: - upload_crash_details() - except GenericAbort: - # User declined upload - print_warning('Upload: Aborted') - sleep(10) - except GenericError: - # No log file or uploading disabled - sleep(10) - except: - print_error('Upload: NS') - sleep(10) - else: - print_success('Upload: CS') - pause('Press Enter to exit...') - exit_script(1) + """Display traceback and exit""" + print_error('Major exception') + print_warning(SUPPORT_MESSAGE) + print(traceback.format_exc()) + print_log(traceback.format_exc()) + try: + upload_crash_details() + except GenericAbort: + # User declined upload + print_warning('Upload: Aborted') + sleep(10) + except GenericError: + # No log file or uploading disabled + sleep(10) + except: + print_error('Upload: NS') + sleep(10) + else: + print_success('Upload: CS') + pause('Press Enter to exit...') + exit_script(1) -def menu_select(title='~ Untitled Menu ~', +def menu_select( + title='[Untitled Menu]', prompt='Please make a selection', secret_actions=[], secret_exit=False, main_entries=[], action_entries=[], disabled_label='DISABLED', spacer=''): - """Display options in a menu and return selected option as a str.""" - # Bail early - if not main_entries and not action_entries: - raise Exception("MenuError: No items given") + """Display options in a menu and return selected option as a str.""" + # Bail early + if not main_entries and not action_entries: + raise Exception("MenuError: No items given") - # Set title - if 'Title' in global_vars: - title = '{}\n\n{}'.format(global_vars['Title'], title) + # Set title + if 'Title' in global_vars: + title = '{}\n\n{}'.format(global_vars['Title'], title) - # Build menu - menu_splash = '{}\n{}\n'.format(title, spacer) - width = len(str(len(main_entries))) - valid_answers = [] - if secret_exit: - valid_answers.append('Q') - if secret_actions: - valid_answers.extend(secret_actions) + # Build menu + menu_splash = '{}\n{}\n'.format(title, spacer) + width = len(str(len(main_entries))) + valid_answers = [] + if secret_exit: + valid_answers.append('Q') + if secret_actions: + valid_answers.extend(secret_actions) - # Add main entries - for i in range(len(main_entries)): - entry = main_entries[i] - # Add Spacer - if ('CRLF' in entry): - menu_splash += '{}\n'.format(spacer) - entry_str = '{number:>{width}}: {name}'.format( - number = i+1, - width = width, - name = entry.get('Display Name', entry['Name'])) - if entry.get('Disabled', False): - entry_str = '{YELLOW}{entry_str} ({disabled}){CLEAR}'.format( - entry_str = entry_str, - disabled = disabled_label, - **COLORS) - else: - valid_answers.append(str(i+1)) - menu_splash += '{}\n'.format(entry_str) - menu_splash += '{}\n'.format(spacer) + # Add main entries + for i in range(len(main_entries)): + entry = main_entries[i] + # Add Spacer + if ('CRLF' in entry): + menu_splash += '{}\n'.format(spacer) + entry_str = '{number:>{width}}: {name}'.format( + number = i+1, + width = width, + name = entry.get('Display Name', entry['Name'])) + if entry.get('Disabled', False): + entry_str = '{YELLOW}{entry_str} ({disabled}){CLEAR}'.format( + entry_str = entry_str, + disabled = disabled_label, + **COLORS) + else: + valid_answers.append(str(i+1)) + menu_splash += '{}\n'.format(entry_str) + menu_splash += '{}\n'.format(spacer) - # Add action entries - for entry in action_entries: - # Add Spacer - if ('CRLF' in entry): - menu_splash += '{}\n'.format(spacer) - valid_answers.append(entry['Letter']) - menu_splash += '{letter:>{width}}: {name}\n'.format( - letter = entry['Letter'].upper(), - width = len(str(len(action_entries))), - name = entry['Name']) + # Add action entries + for entry in action_entries: + # Add Spacer + if ('CRLF' in entry): + menu_splash += '{}\n'.format(spacer) + valid_answers.append(entry['Letter']) + menu_splash += '{letter:>{width}}: {name}\n'.format( + letter = entry['Letter'].upper(), + width = len(str(len(action_entries))), + name = entry['Name']) - answer = '' + answer = '' - while (answer.upper() not in valid_answers): - clear_screen() - print(menu_splash) - answer = input('{}: '.format(prompt)) + while (answer.upper() not in valid_answers): + clear_screen() + print(menu_splash) + answer = input('{}: '.format(prompt)) - return answer.upper() + return answer.upper() def non_clobber_rename(full_path): - """Append suffix to path, if necessary, to avoid clobbering path""" - new_path = full_path - _i = 1; - while os.path.exists(new_path): - new_path = '{path}_{i}'.format(i=_i, path=full_path) - _i += 1 + """Append suffix to path, if necessary, to avoid clobbering path""" + new_path = full_path + _i = 1; + while os.path.exists(new_path): + new_path = '{path}_{i}'.format(i=_i, path=full_path) + _i += 1 - return new_path + return new_path def pause(prompt='Press Enter to continue... '): - """Simple pause implementation.""" - input(prompt) + """Simple pause implementation.""" + input(prompt) def ping(addr='google.com'): - """Attempt to ping addr.""" - cmd = [ - 'ping', - '-n' if psutil.WINDOWS else '-c', - '2', - addr] - run_program(cmd) + """Attempt to ping addr.""" + cmd = [ + 'ping', + '-n' if psutil.WINDOWS else '-c', + '2', + addr] + run_program(cmd) def popen_program(cmd, pipe=False, minimized=False, shell=False, **kwargs): - """Run program and return a subprocess.Popen object.""" - cmd_kwargs = {'args': cmd, 'shell': shell} + """Run program and return a subprocess.Popen object.""" + cmd_kwargs = {'args': cmd, 'shell': shell} - if minimized: - startupinfo = subprocess.STARTUPINFO() - startupinfo.dwFlags = subprocess.STARTF_USESHOWWINDOW - startupinfo.wShowWindow = 6 - cmd_kwargs['startupinfo'] = startupinfo + if minimized: + startupinfo = subprocess.STARTUPINFO() + startupinfo.dwFlags = subprocess.STARTF_USESHOWWINDOW + startupinfo.wShowWindow = 6 + cmd_kwargs['startupinfo'] = startupinfo - if pipe: - cmd_kwargs.update({ - 'stdout': subprocess.PIPE, - 'stderr': subprocess.PIPE, - }) + if pipe: + cmd_kwargs.update({ + 'stdout': subprocess.PIPE, + 'stderr': subprocess.PIPE, + }) - if 'cwd' in kwargs: - cmd_kwargs['cwd'] = kwargs['cwd'] + if 'cwd' in kwargs: + cmd_kwargs['cwd'] = kwargs['cwd'] - return subprocess.Popen(**cmd_kwargs) + return subprocess.Popen(**cmd_kwargs) def print_error(*args, **kwargs): - """Prints message to screen in RED.""" - print_standard(*args, color=COLORS['RED'], **kwargs) + """Prints message to screen in RED.""" + print_standard(*args, color=COLORS['RED'], **kwargs) def print_info(*args, **kwargs): - """Prints message to screen in BLUE.""" - print_standard(*args, color=COLORS['BLUE'], **kwargs) + """Prints message to screen in BLUE.""" + print_standard(*args, color=COLORS['BLUE'], **kwargs) def print_standard(message='Generic info', - color=None, end='\n', timestamp=True, **kwargs): - """Prints message to screen and log (if set).""" - display_message = message - if color: - display_message = color + message + COLORS['CLEAR'] - # **COLORS is used below to support non-"standard" color printing - print(display_message.format(**COLORS), end=end, **kwargs) - print_log(message, end, timestamp) + color=None, end='\n', timestamp=True, **kwargs): + """Prints message to screen and log (if set).""" + display_message = message + if color: + display_message = color + message + COLORS['CLEAR'] + # **COLORS is used below to support non-"standard" color printing + print(display_message.format(**COLORS), end=end, **kwargs) + print_log(message, end, timestamp) def print_success(*args, **kwargs): - """Prints message to screen in GREEN.""" - print_standard(*args, color=COLORS['GREEN'], **kwargs) + """Prints message to screen in GREEN.""" + print_standard(*args, color=COLORS['GREEN'], **kwargs) def print_warning(*args, **kwargs): - """Prints message to screen in YELLOW.""" - print_standard(*args, color=COLORS['YELLOW'], **kwargs) + """Prints message to screen in YELLOW.""" + print_standard(*args, color=COLORS['YELLOW'], **kwargs) def print_log(message='', end='\n', timestamp=True): - """Writes message to a log if LogFile is set.""" - time_str = time.strftime("%Y-%m-%d %H%M%z: ") if timestamp else '' - if 'LogFile' in global_vars and global_vars['LogFile']: - with open(global_vars['LogFile'], 'a', encoding='utf-8') as f: - for line in message.splitlines(): - f.write('{timestamp}{line}{end}'.format( - timestamp = time_str, - line = line, - end = end)) + """Writes message to a log if LogFile is set.""" + time_str = time.strftime("%Y-%m-%d %H%M%z: ") if timestamp else '' + if 'LogFile' in global_vars and global_vars['LogFile']: + with open(global_vars['LogFile'], 'a', encoding='utf-8') as f: + for line in message.splitlines(): + f.write('{timestamp}{line}{end}'.format( + timestamp = time_str, + line = line, + end = end)) def run_program(cmd, args=[], check=True, pipe=True, shell=False, **kwargs): - """Run program and return a subprocess.CompletedProcess object.""" - if args: - # Deprecated so let's raise an exception to find & fix all occurances - print_error('ERROR: Using args is no longer supported.') - raise Exception - cmd = [c for c in cmd if c] - if shell: - cmd = ' '.join(cmd) + """Run program and return a subprocess.CompletedProcess object.""" + if args: + # Deprecated so let's raise an exception to find & fix all occurances + print_error('ERROR: Using args is no longer supported.') + raise Exception + cmd = [c for c in cmd if c] + if shell: + cmd = ' '.join(cmd) - cmd_kwargs = {'args': cmd, 'check': check, 'shell': shell} + cmd_kwargs = {'args': cmd, 'check': check, 'shell': shell} - if pipe: - cmd_kwargs.update({ - 'stdout': subprocess.PIPE, - 'stderr': subprocess.PIPE, - }) + if pipe: + cmd_kwargs.update({ + 'stdout': subprocess.PIPE, + 'stderr': subprocess.PIPE, + }) - if 'cwd' in kwargs: - cmd_kwargs['cwd'] = kwargs['cwd'] + if 'cwd' in kwargs: + cmd_kwargs['cwd'] = kwargs['cwd'] - return subprocess.run(**cmd_kwargs) + return subprocess.run(**cmd_kwargs) -def set_title(title='~Some Title~'): - """Set title. +def set_title(title='[Some Title]'): + """Set title. - Used for window title and menu titles.""" - global_vars['Title'] = title - os.system('title {}'.format(title)) + Used for window title and menu titles.""" + global_vars['Title'] = title + os.system('title {}'.format(title)) -def show_data(message='~Some message~', data='~Some data~', indent=8, width=32, +def show_data( + message='[Some message]', data='[Some data]', + indent=8, width=32, info=False, warning=False, error=False): - """Display info with formatting.""" - message = '{indent}{message:<{width}}{data}'.format( - indent=' '*indent, width=width, message=message, data=data) - if error: - print_error(message) - elif warning: - print_warning(message) - elif info: - print_info(message) - else: - print_standard(message) + """Display info with formatting.""" + message = '{indent}{message:<{width}}{data}'.format( + indent=' '*indent, width=width, message=message, data=data) + if error: + print_error(message) + elif warning: + print_warning(message) + elif info: + print_info(message) + else: + print_standard(message) def sleep(seconds=2): - """Wait for a while.""" - time.sleep(seconds) + """Wait for a while.""" + time.sleep(seconds) def stay_awake(): - """Prevent the system from sleeping or hibernating.""" - # DISABLED due to VCR2008 dependency - return - # Bail if caffeine is already running - for proc in psutil.process_iter(): - if proc.name() == 'caffeine.exe': - return - # Extract and run - extract_item('Caffeine', silent=True) - try: - popen_program([global_vars['Tools']['Caffeine']]) - except Exception: - print_error('ERROR: No caffeine available.') - print_warning('Please set the power setting to High Performance.') + """Prevent the system from sleeping or hibernating.""" + # DISABLED due to VCR2008 dependency + return + # Bail if caffeine is already running + for proc in psutil.process_iter(): + if proc.name() == 'caffeine.exe': + return + # Extract and run + extract_item('Caffeine', silent=True) + try: + popen_program([global_vars['Tools']['Caffeine']]) + except Exception: + print_error('ERROR: No caffeine available.') + print_warning('Please set the power setting to High Performance.') def strip_colors(s): - """Remove all ASCII color escapes from string, returns str.""" - for c in COLORS.values(): - s = s.replace(c, '') - return s + """Remove all ASCII color escapes from string, returns str.""" + for c in COLORS.values(): + s = s.replace(c, '') + return s def get_exception(s): - """Get exception by name, returns Exception object.""" - try: - obj = getattr(sys.modules[__name__], s) - except AttributeError: - # Try builtin classes - obj = getattr(sys.modules['builtins'], s) - return obj + """Get exception by name, returns Exception object.""" + try: + obj = getattr(sys.modules[__name__], s) + except AttributeError: + # Try builtin classes + obj = getattr(sys.modules['builtins'], s) + return obj def try_and_print(message='Trying...', - function=None, cs='CS', ns='NS', other_results={}, - catch_all=True, print_return=False, silent_function=True, - indent=8, width=32, *args, **kwargs): - """Run function, print if successful or not, and return dict. + function=None, cs='CS', ns='NS', other_results={}, + catch_all=True, print_return=False, silent_function=True, + indent=8, width=32, *args, **kwargs): + """Run function, print if successful or not, and return dict. - other_results is in the form of - { - 'Warning': {'ExceptionClassName': 'Result Message'}, - 'Error': {'ExceptionClassName': 'Result Message'} - } - The the ExceptionClassNames will be excepted conditions - and the result string will be printed in the correct color. - catch_all=False will result in unspecified exceptions being re-raised.""" - err = None - out = None - w_exceptions = other_results.get('Warning', {}).keys() - w_exceptions = tuple(get_exception(e) for e in w_exceptions) - e_exceptions = other_results.get('Error', {}).keys() - e_exceptions = tuple(get_exception(e) for e in e_exceptions) - w_results = other_results.get('Warning', {}) - e_results = other_results.get('Error', {}) + other_results is in the form of + { + 'Warning': {'ExceptionClassName': 'Result Message'}, + 'Error': {'ExceptionClassName': 'Result Message'} + } + The the ExceptionClassNames will be excepted conditions + and the result string will be printed in the correct color. + catch_all=False will re-raise unspecified exceptions.""" + err = None + out = None + w_exceptions = other_results.get('Warning', {}).keys() + w_exceptions = tuple(get_exception(e) for e in w_exceptions) + e_exceptions = other_results.get('Error', {}).keys() + e_exceptions = tuple(get_exception(e) for e in e_exceptions) + w_results = other_results.get('Warning', {}) + e_results = other_results.get('Error', {}) - # Run function and catch errors - print_standard('{indent}{message:<{width}}'.format( - indent=' '*indent, message=message, width=width), end='', flush=True) - try: - out = function(*args, **kwargs) - if print_return: - str_list = out - if isinstance(out, subprocess.CompletedProcess): - str_list = out.stdout.decode().strip().splitlines() - print_standard(str_list[0].strip(), timestamp=False) - for item in str_list[1:]: - print_standard('{indent}{item}'.format( - indent=' '*(indent+width), item=item.strip())) - elif silent_function: - print_success(cs, timestamp=False) - except w_exceptions as e: - _result = w_results.get(e.__class__.__name__, 'Warning') - print_warning(_result, timestamp=False) - err = e - except e_exceptions as e: - _result = e_results.get(e.__class__.__name__, 'Error') - print_error(_result, timestamp=False) - err = e - except Exception: - print_error(ns, timestamp=False) - err = traceback.format_exc() + # Run function and catch errors + print_standard('{indent}{message:<{width}}'.format( + indent=' '*indent, message=message, width=width), end='', flush=True) + try: + out = function(*args, **kwargs) + if print_return: + str_list = out + if isinstance(out, subprocess.CompletedProcess): + str_list = out.stdout.decode().strip().splitlines() + print_standard(str_list[0].strip(), timestamp=False) + for item in str_list[1:]: + print_standard('{indent}{item}'.format( + indent=' '*(indent+width), item=item.strip())) + elif silent_function: + print_success(cs, timestamp=False) + except w_exceptions as e: + _result = w_results.get(e.__class__.__name__, 'Warning') + print_warning(_result, timestamp=False) + err = e + except e_exceptions as e: + _result = e_results.get(e.__class__.__name__, 'Error') + print_error(_result, timestamp=False) + err = e + except Exception: + print_error(ns, timestamp=False) + err = traceback.format_exc() - # Return or raise? - if err and not catch_all: - raise - else: - return {'CS': not bool(err), 'Error': err, 'Out': out} + # Return or raise? + if err and not catch_all: + raise + else: + return {'CS': not bool(err), 'Error': err, 'Out': out} def upload_crash_details(): - """Upload log and runtime data to the CRASH_SERVER. + """Upload log and runtime data to the CRASH_SERVER. - Intended for uploading to a public Nextcloud share.""" - if not ENABLED_UPLOAD_DATA: - raise GenericError + Intended for uploading to a public Nextcloud share.""" + if not ENABLED_UPLOAD_DATA: + raise GenericError - import requests - if 'LogFile' in global_vars and global_vars['LogFile']: - if ask('Upload crash details to {}?'.format(CRASH_SERVER['Name'])): - with open(global_vars['LogFile']) as f: - data = '''{} + import requests + if 'LogFile' in global_vars and global_vars['LogFile']: + if ask('Upload crash details to {}?'.format(CRASH_SERVER['Name'])): + with open(global_vars['LogFile']) as f: + data = '''{} ############################# Runtime Details: sys.argv: {} global_vars: {}'''.format(f.read(), sys.argv, global_vars) - filename = global_vars.get('LogFile', 'Unknown') - filename = re.sub(r'.*(\\|/)', '', filename) - filename += '.txt' - url = '{}/Crash_{}__{}'.format( - CRASH_SERVER['Url'], - global_vars.get('Date-Time', 'Unknown Date-Time'), - filename) - r = requests.put( - url, data=data, - headers={'X-Requested-With': 'XMLHttpRequest'}, - auth=(CRASH_SERVER['User'], CRASH_SERVER['Pass'])) - # Raise exception if upload NS - if not r.ok: - raise Exception - else: - # User said no - raise GenericAbort + filename = global_vars.get('LogFile', 'Unknown') + filename = re.sub(r'.*(\\|/)', '', filename) + filename += '.txt' + url = '{}/Crash_{}__{}'.format( + CRASH_SERVER['Url'], + global_vars.get('Date-Time', 'Unknown Date-Time'), + filename) + r = requests.put( + url, data=data, + headers={'X-Requested-With': 'XMLHttpRequest'}, + auth=(CRASH_SERVER['User'], CRASH_SERVER['Pass'])) + # Raise exception if upload NS + if not r.ok: + raise Exception else: - # No LogFile defined (or invalid LogFile) - raise GenericError + # User said no + raise GenericAbort + else: + # No LogFile defined (or invalid LogFile) + raise GenericError def wait_for_process(name, poll_rate=3): - """Wait for process by name.""" - running = True - while running: - sleep(poll_rate) - running = False - for proc in psutil.process_iter(): - try: - if re.search(r'^{}'.format(name), proc.name(), re.IGNORECASE): - running = True - except psutil._exceptions.NoSuchProcess: - # Assuming process closed during iteration - pass - sleep(1) + """Wait for process by name.""" + running = True + while running: + sleep(poll_rate) + running = False + for proc in psutil.process_iter(): + try: + if re.search(r'^{}'.format(name), proc.name(), re.IGNORECASE): + running = True + except psutil._exceptions.NoSuchProcess: + # Assuming process closed during iteration + pass + sleep(1) # global_vars functions def init_global_vars(silent=False): - """Sets global variables based on system info.""" - if not silent: - print_info('Initializing') - if psutil.WINDOWS: - os.system('title Wizard Kit') - if psutil.LINUX: - init_functions = [ - ['Checking environment...', set_linux_vars], - ['Clearing collisions...', clean_env_vars], - ] + """Sets global variables based on system info.""" + if not silent: + print_info('Initializing') + if psutil.WINDOWS: + os.system('title Wizard Kit') + if psutil.LINUX: + init_functions = [ + ['Checking environment...', set_linux_vars], + ['Clearing collisions...', clean_env_vars], + ] + else: + init_functions = [ + ['Checking .bin...', find_bin], + ['Checking environment...', set_common_vars], + ['Checking OS...', check_os], + ['Checking tools...', check_tools], + ['Creating folders...', make_tmp_dirs], + ['Clearing collisions...', clean_env_vars], + ] + try: + if silent: + for f in init_functions: + f[1]() else: - init_functions = [ - ['Checking .bin...', find_bin], - ['Checking environment...', set_common_vars], - ['Checking OS...', check_os], - ['Checking tools...', check_tools], - ['Creating folders...', make_tmp_dirs], - ['Clearing collisions...', clean_env_vars], - ] - try: - if silent: - for f in init_functions: - f[1]() - else: - for f in init_functions: - try_and_print( - message=f[0], function=f[1], - cs='Done', ns='Error', catch_all=False) - except: - major_exception() + for f in init_functions: + try_and_print( + message=f[0], function=f[1], + cs='Done', ns='Error', catch_all=False) + except: + major_exception() def check_os(): - """Set OS specific variables.""" - tmp = {} + """Set OS specific variables.""" + tmp = {} - # Query registry - path = r'SOFTWARE\Microsoft\Windows NT\CurrentVersion' - with winreg.OpenKey(HKLM, path) as key: - for name in ['CurrentBuild', 'CurrentVersion', 'ProductName']: - try: - tmp[name] = winreg.QueryValueEx(key, name)[0] - except FileNotFoundError: - tmp[name] = 'Unknown' + # Query registry + path = r'SOFTWARE\Microsoft\Windows NT\CurrentVersion' + with winreg.OpenKey(HKLM, path) as key: + for name in ['CurrentBuild', 'CurrentVersion', 'ProductName']: + try: + tmp[name] = winreg.QueryValueEx(key, name)[0] + except FileNotFoundError: + tmp[name] = 'Unknown' - # Handle CurrentBuild collision - if tmp['CurrentBuild'] == '9200': - if tmp['CurrentVersion'] == '6.2': - # Windown 8, set to fake build number - tmp['CurrentBuild'] = '9199' - else: - # Windows 8.1, leave alone - pass + # Handle CurrentBuild collision + if tmp['CurrentBuild'] == '9200': + if tmp['CurrentVersion'] == '6.2': + # Windown 8, set to fake build number + tmp['CurrentBuild'] = '9199' + else: + # Windows 8.1, leave alone + pass - # Check bit depth - tmp['Arch'] = 32 - if 'PROGRAMFILES(X86)' in global_vars['Env']: - tmp['Arch'] = 64 + # Check bit depth + tmp['Arch'] = 32 + if 'PROGRAMFILES(X86)' in global_vars['Env']: + tmp['Arch'] = 64 - # Get Windows build info - build_info = WINDOWS_BUILDS.get( - tmp['CurrentBuild'], - ('Unknown', 'Build {}'.format(tmp['CurrentBuild']), None, None, 'unrecognized')) + # Get Windows build info + build_info = WINDOWS_BUILDS.get(tmp['CurrentBuild'], None) + if build_info is None: + # Not in windows_builds.py + build_info = [ + 'Unknown', + 'Build {}'.format(tmp['CurrentBuild']), + None, + None, + 'unrecognized'] + else: build_info = list(build_info) - tmp['Version'] = build_info.pop(0) - tmp['Release'] = build_info.pop(0) - tmp['Codename'] = build_info.pop(0) - tmp['Marketing Name'] = build_info.pop(0) - tmp['Notes'] = build_info.pop(0) + tmp['Version'] = build_info.pop(0) + tmp['Release'] = build_info.pop(0) + tmp['Codename'] = build_info.pop(0) + tmp['Marketing Name'] = build_info.pop(0) + tmp['Notes'] = build_info.pop(0) - # Set name - tmp['Name'] = tmp['ProductName'] - if tmp['Release']: - tmp['Name'] += ' {}'.format(tmp['Release']) - if tmp['Codename']: - tmp['Name'] += ' "{}"'.format(tmp['Codename']) - if tmp['Marketing Name']: - tmp['Name'] += ' / "{}"'.format(tmp['Marketing Name']) - tmp['Name'] = re.sub(r'\s+', ' ', tmp['Name']) + # Set name + tmp['Name'] = tmp['ProductName'] + if tmp['Release']: + tmp['Name'] += ' {}'.format(tmp['Release']) + if tmp['Codename']: + tmp['Name'] += ' "{}"'.format(tmp['Codename']) + if tmp['Marketing Name']: + tmp['Name'] += ' / "{}"'.format(tmp['Marketing Name']) + tmp['Name'] = re.sub(r'\s+', ' ', tmp['Name']) - # Set display name - tmp['DisplayName'] = '{} x{}'.format(tmp['Name'], tmp['Arch']) - if tmp['Notes']: - tmp['DisplayName'] += ' ({})'.format(tmp['Notes']) + # Set display name + tmp['DisplayName'] = '{} x{}'.format(tmp['Name'], tmp['Arch']) + if tmp['Notes']: + tmp['DisplayName'] += ' ({})'.format(tmp['Notes']) - global_vars['OS'] = tmp + global_vars['OS'] = tmp def check_tools(): - """Set tool variables based on OS bit-depth and tool availability.""" - if global_vars['OS'].get('Arch', 32) == 64: - global_vars['Tools'] = { - k: v.get('64', v.get('32')) for (k, v) in TOOLS.items()} - else: - global_vars['Tools'] = {k: v.get('32') for (k, v) in TOOLS.items()} + """Set tool variables based on OS bit-depth and tool availability.""" + if global_vars['OS'].get('Arch', 32) == 64: + global_vars['Tools'] = { + k: v.get('64', v.get('32')) for (k, v) in TOOLS.items()} + else: + global_vars['Tools'] = {k: v.get('32') for (k, v) in TOOLS.items()} - # Fix paths - global_vars['Tools'] = {k: os.path.join(global_vars['BinDir'], v) - for (k, v) in global_vars['Tools'].items()} + # Fix paths + global_vars['Tools'] = {k: os.path.join(global_vars['BinDir'], v) + for (k, v) in global_vars['Tools'].items()} def clean_env_vars(): - """Remove conflicting global_vars and env variables. + """Remove conflicting global_vars and env variables. - This fixes an issue where both global_vars and - global_vars['Env'] are expanded at the same time.""" - for key in global_vars.keys(): - global_vars['Env'].pop(key, None) + This fixes an issue where both global_vars and + global_vars['Env'] are expanded at the same time.""" + for key in global_vars.keys(): + global_vars['Env'].pop(key, None) def find_bin(): - """Find .bin folder in the cwd or it's parents.""" - wd = os.getcwd() - base = None - while base is None: - if os.path.exists('.bin'): - base = os.getcwd() - break - if re.fullmatch(r'\w:\\', os.getcwd()): - break - os.chdir('..') - os.chdir(wd) - if base is None: - raise BinNotFoundError - global_vars['BaseDir'] = base + """Find .bin folder in the cwd or it's parents.""" + wd = os.getcwd() + base = None + while base is None: + if os.path.exists('.bin'): + base = os.getcwd() + break + if re.fullmatch(r'\w:\\', os.getcwd()): + break + os.chdir('..') + os.chdir(wd) + if base is None: + raise BinNotFoundError + global_vars['BaseDir'] = base def make_tmp_dirs(): - """Make temp directories.""" - os.makedirs(global_vars['BackupDir'], exist_ok=True) - os.makedirs(global_vars['LogDir'], exist_ok=True) - os.makedirs(r'{}\{}'.format( - global_vars['LogDir'], KIT_NAME_FULL), exist_ok=True) - os.makedirs(r'{}\Tools'.format(global_vars['LogDir']), exist_ok=True) - os.makedirs(global_vars['TmpDir'], exist_ok=True) + """Make temp directories.""" + os.makedirs(global_vars['BackupDir'], exist_ok=True) + os.makedirs(global_vars['LogDir'], exist_ok=True) + os.makedirs(r'{}\{}'.format( + global_vars['LogDir'], KIT_NAME_FULL), exist_ok=True) + os.makedirs(r'{}\Tools'.format(global_vars['LogDir']), exist_ok=True) + os.makedirs(global_vars['TmpDir'], exist_ok=True) def set_common_vars(): - """Set common variables.""" - global_vars['Date'] = time.strftime("%Y-%m-%d") - global_vars['Date-Time'] = time.strftime("%Y-%m-%d_%H%M_%z") - global_vars['Env'] = os.environ.copy() + """Set common variables.""" + global_vars['Date'] = time.strftime("%Y-%m-%d") + global_vars['Date-Time'] = time.strftime("%Y-%m-%d_%H%M_%z") + global_vars['Env'] = os.environ.copy() - global_vars['ArchivePassword'] = ARCHIVE_PASSWORD - global_vars['BinDir'] = r'{BaseDir}\.bin'.format( - **global_vars) - global_vars['CBinDir'] = r'{BaseDir}\.cbin'.format( - **global_vars) - global_vars['ClientDir'] = r'{SYSTEMDRIVE}\{prefix}'.format( - prefix=KIT_NAME_SHORT, **global_vars['Env']) - global_vars['BackupDir'] = r'{ClientDir}\Backups'.format( - **global_vars) - global_vars['LogDir'] = r'{ClientDir}\Logs\{Date}'.format( - **global_vars) - global_vars['QuarantineDir'] = r'{ClientDir}\Quarantine'.format( - **global_vars) - global_vars['TmpDir'] = r'{BinDir}\tmp'.format( - **global_vars) + global_vars['ArchivePassword'] = ARCHIVE_PASSWORD + global_vars['BinDir'] = r'{BaseDir}\.bin'.format( + **global_vars) + global_vars['CBinDir'] = r'{BaseDir}\.cbin'.format( + **global_vars) + global_vars['ClientDir'] = r'{SYSTEMDRIVE}\{prefix}'.format( + prefix=KIT_NAME_SHORT, **global_vars['Env']) + global_vars['BackupDir'] = r'{ClientDir}\Backups'.format( + **global_vars) + global_vars['LogDir'] = r'{ClientDir}\Logs\{Date}'.format( + **global_vars) + global_vars['QuarantineDir'] = r'{ClientDir}\Quarantine'.format( + **global_vars) + global_vars['TmpDir'] = r'{BinDir}\tmp'.format( + **global_vars) def set_linux_vars(): - """Set common variables in a Linux environment. + """Set common variables in a Linux environment. - These assume we're running under a WK-Linux build.""" - result = run_program(['mktemp', '-d']) - global_vars['TmpDir'] = result.stdout.decode().strip() - global_vars['Date'] = time.strftime("%Y-%m-%d") - global_vars['Date-Time'] = time.strftime("%Y-%m-%d_%H%M_%z") - global_vars['Env'] = os.environ.copy() - global_vars['BinDir'] = '/usr/local/bin' - global_vars['LogDir'] = global_vars['TmpDir'] - global_vars['Tools'] = { - 'wimlib-imagex': 'wimlib-imagex', - 'SevenZip': '7z', - } + These assume we're running under a WK-Linux build.""" + result = run_program(['mktemp', '-d']) + global_vars['TmpDir'] = result.stdout.decode().strip() + global_vars['Date'] = time.strftime("%Y-%m-%d") + global_vars['Date-Time'] = time.strftime("%Y-%m-%d_%H%M_%z") + global_vars['Env'] = os.environ.copy() + global_vars['BinDir'] = '/usr/local/bin' + global_vars['LogDir'] = global_vars['TmpDir'] + global_vars['Tools'] = { + 'wimlib-imagex': 'wimlib-imagex', + 'SevenZip': '7z', + } def set_log_file(log_name): - """Sets global var LogFile and creates path as needed.""" - folder_path = r'{}\{}'.format(global_vars['LogDir'], KIT_NAME_FULL) - log_file = r'{}\{}'.format(folder_path, log_name) - os.makedirs(folder_path, exist_ok=True) - global_vars['LogFile'] = log_file + """Sets global var LogFile and creates path as needed.""" + folder_path = r'{}\{}'.format(global_vars['LogDir'], KIT_NAME_FULL) + log_file = r'{}\{}'.format(folder_path, log_name) + os.makedirs(folder_path, exist_ok=True) + global_vars['LogFile'] = log_file if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From 4049272cbb52278fc8ee6c69b078dd79ac18d442 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 19:48:32 -0700 Subject: [PATCH 159/265] Updated data.py --- .bin/Scripts/functions/data.py | 1536 ++++++++++++++++---------------- 1 file changed, 769 insertions(+), 767 deletions(-) diff --git a/.bin/Scripts/functions/data.py b/.bin/Scripts/functions/data.py index 9557ebdb..ed4bfa9e 100644 --- a/.bin/Scripts/functions/data.py +++ b/.bin/Scripts/functions/data.py @@ -9,107 +9,107 @@ from functions.common import * # Classes class LocalDisk(): - def __init__(self, disk): - self.disk = disk - self.name = disk.mountpoint.upper() - self.path = self.name - def is_dir(self): - # Should always be true - return True - def is_file(self): - # Should always be false - return False + def __init__(self, disk): + self.disk = disk + self.name = disk.mountpoint.upper() + self.path = self.name + def is_dir(self): + # Should always be true + return True + def is_file(self): + # Should always be false + return False class SourceItem(): - def __init__(self, name, path): - self.name = name - self.path = path + def __init__(self, name, path): + self.name = name + self.path = path # Regex REGEX_EXCL_ITEMS = re.compile( - r'^(\.(AppleDB|AppleDesktop|AppleDouble' - r'|com\.apple\.timemachine\.supported|dbfseventsd' - r'|DocumentRevisions-V100.*|DS_Store|fseventsd|PKInstallSandboxManager' - r'|Spotlight.*|SymAV.*|symSchedScanLockxz|TemporaryItems|Trash.*' - r'|vol|VolumeIcon\.icns)|desktop\.(ini|.*DB|.*DF)' - r'|(hiberfil|pagefile)\.sys|lost\+found|Network\.*Trash\.*Folder' - r'|Recycle[dr]|System\.*Volume\.*Information|Temporary\.*Items' - r'|Thumbs\.db)$', - re.IGNORECASE) + r'^(\.(AppleDB|AppleDesktop|AppleDouble' + r'|com\.apple\.timemachine\.supported|dbfseventsd' + r'|DocumentRevisions-V100.*|DS_Store|fseventsd|PKInstallSandboxManager' + r'|Spotlight.*|SymAV.*|symSchedScanLockxz|TemporaryItems|Trash.*' + r'|vol|VolumeIcon\.icns)|desktop\.(ini|.*DB|.*DF)' + r'|(hiberfil|pagefile)\.sys|lost\+found|Network\.*Trash\.*Folder' + r'|Recycle[dr]|System\.*Volume\.*Information|Temporary\.*Items' + r'|Thumbs\.db)$', + re.IGNORECASE) REGEX_EXCL_ROOT_ITEMS = re.compile( - r'^(boot(mgr|nxt)$|Config.msi' - r'|(eula|globdata|install|vc_?red)' - r'|.*.sys$|System Volume Information|RECYCLER?|\$Recycle\.bin' - r'|\$?Win(dows(.old.*|\.~BT|)$|RE_)|\$GetCurrent|Windows10Upgrade' - r'|PerfLogs|Program Files|SYSTEM.SAV' - r'|.*\.(esd|swm|wim|dd|map|dmg|image)$)', - re.IGNORECASE) + r'^(boot(mgr|nxt)$|Config.msi' + r'|(eula|globdata|install|vc_?red)' + r'|.*.sys$|System Volume Information|RECYCLER?|\$Recycle\.bin' + r'|\$?Win(dows(.old.*|\. BT|)$|RE_)|\$GetCurrent|Windows10Upgrade' + r'|PerfLogs|Program Files|SYSTEM.SAV' + r'|.*\.(esd|swm|wim|dd|map|dmg|image)$)', + re.IGNORECASE) REGEX_INCL_ROOT_ITEMS = re.compile( - r'^(AdwCleaner|(My\s*|)(Doc(uments?( and Settings|)|s?)|Downloads' - r'|Media|Music|Pic(ture|)s?|Vid(eo|)s?)' - r'|{prefix}(-?Info|-?Transfer|)' - r'|(ProgramData|Recovery|Temp.*|Users)$' - r'|.*\.(log|txt|rtf|qb\w*|avi|m4a|m4v|mp4|mkv|jpg|png|tiff?)$)' - r''.format(prefix=KIT_NAME_SHORT), - re.IGNORECASE) + r'^(AdwCleaner|(My\s*|)(Doc(uments?( and Settings|)|s?)|Downloads' + r'|Media|Music|Pic(ture|)s?|Vid(eo|)s?)' + r'|{prefix}(-?Info|-?Transfer|)' + r'|(ProgramData|Recovery|Temp.*|Users)$' + r'|.*\.(log|txt|rtf|qb\w*|avi|m4a|m4v|mp4|mkv|jpg|png|tiff?)$)' + r''.format(prefix=KIT_NAME_SHORT), + re.IGNORECASE) REGEX_WIM_FILE = re.compile( - r'\.wim$', - re.IGNORECASE) + r'\.wim$', + re.IGNORECASE) REGEX_WINDOWS_OLD = re.compile( - r'^Win(dows|)\.old', - re.IGNORECASE) + r'^Win(dows|)\.old', + re.IGNORECASE) # STATIC VARIABLES FAST_COPY_EXCLUDES = [ - r'\*.esd', - r'\*.swm', - r'\*.wim', - r'\*.dd', - r'\*.dd.tgz', - r'\*.dd.txz', - r'\*.map', - r'\*.dmg', - r'\*.image', - r'$RECYCLE.BIN', - r'$Recycle.Bin', - r'.AppleDB', - r'.AppleDesktop', - r'.AppleDouble', - r'.com.apple.timemachine.supported', - r'.dbfseventsd', - r'.DocumentRevisions-V100*', - r'.DS_Store', - r'.fseventsd', - r'.PKInstallSandboxManager', - r'.Spotlight*', - r'.SymAV*', - r'.symSchedScanLockxz', - r'.TemporaryItems', - r'.Trash*', - r'.vol', - r'.VolumeIcon.icns', - r'desktop.ini', - r'Desktop?DB', - r'Desktop?DF', - r'hiberfil.sys', - r'lost+found', - r'Network?Trash?Folder', - r'pagefile.sys', - r'Recycled', - r'RECYCLER', - r'System?Volume?Information', - r'Temporary?Items', - r'Thumbs.db', - ] + r'\*.esd', + r'\*.swm', + r'\*.wim', + r'\*.dd', + r'\*.dd.tgz', + r'\*.dd.txz', + r'\*.map', + r'\*.dmg', + r'\*.image', + r'$RECYCLE.BIN', + r'$Recycle.Bin', + r'.AppleDB', + r'.AppleDesktop', + r'.AppleDouble', + r'.com.apple.timemachine.supported', + r'.dbfseventsd', + r'.DocumentRevisions-V100*', + r'.DS_Store', + r'.fseventsd', + r'.PKInstallSandboxManager', + r'.Spotlight*', + r'.SymAV*', + r'.symSchedScanLockxz', + r'.TemporaryItems', + r'.Trash*', + r'.vol', + r'.VolumeIcon.icns', + r'desktop.ini', + r'Desktop?DB', + r'Desktop?DF', + r'hiberfil.sys', + r'lost+found', + r'Network?Trash?Folder', + r'pagefile.sys', + r'Recycled', + r'RECYCLER', + r'System?Volume?Information', + r'Temporary?Items', + r'Thumbs.db', + ] FAST_COPY_ARGS = [ - '/cmd=noexist_only', - '/utf8', - '/skip_empty_dir', - '/linkdest', - '/no_ui', - '/auto_close', - '/exclude={}'.format(';'.join(FAST_COPY_EXCLUDES)), - ] + '/cmd=noexist_only', + '/utf8', + '/skip_empty_dir', + '/linkdest', + '/no_ui', + '/auto_close', + '/exclude={}'.format(';'.join(FAST_COPY_EXCLUDES)), + ] # Code borrowed from: https://stackoverflow.com/a/29075319 SEM_NORMAL = ctypes.c_uint() SEM_FAILCRITICALERRORS = 1 @@ -117,770 +117,772 @@ SEM_NOOPENFILEERRORBOX = 0x8000 SEM_FAIL = SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS def cleanup_transfer(dest_path): - """Fix attributes and move extraneous items outside the Transfer folder.""" - try: - # Remove dest_path if empty - os.rmdir(dest_path) - except OSError: + """Fix attributes and move extraneous items outside the Transfer folder.""" + try: + # Remove dest_path if empty + os.rmdir(dest_path) + except OSError: + pass + if not os.path.exists(dest_path): + # Bail if dest_path was empty and removed + raise Exception + + # Fix attributes + cmd = ['attrib', '-a', '-h', '-r', '-s', dest_path] + run_program(cmd, check=False) + + for root, dirs, files in os.walk(dest_path, topdown=False): + for name in dirs: + # Remove empty directories and junction points + try: + os.rmdir(os.path.join(root, name)) + except OSError: pass - if not os.path.exists(dest_path): - # Bail if dest_path was empty and removed - raise Exception - - # Fix attributes - cmd = ['attrib', '-a', '-h', '-r', '-s', dest_path] - run_program(cmd, check=False) - - for root, dirs, files in os.walk(dest_path, topdown=False): - for name in dirs: - # Remove empty directories and junction points - try: - os.rmdir(os.path.join(root, name)) - except OSError: - pass - for name in files: - # "Remove" files based on exclusion regex - if REGEX_EXCL_ITEMS.search(name): - # Make dest folder - dest_name = root.replace(dest_path, dest_path+'.Removed') - os.makedirs(dest_name, exist_ok=True) - # Set dest filename - dest_name = os.path.join(dest_name, name) - dest_name = non_clobber_rename(dest_name) - source_name = os.path.join(root, name) - try: - shutil.move(source_name, dest_name) - except Exception: - pass + for name in files: + # "Remove" files based on exclusion regex + if REGEX_EXCL_ITEMS.search(name): + # Make dest folder + dest_name = root.replace(dest_path, dest_path+'.Removed') + os.makedirs(dest_name, exist_ok=True) + # Set dest filename + dest_name = os.path.join(dest_name, name) + dest_name = non_clobber_rename(dest_name) + source_name = os.path.join(root, name) + try: + shutil.move(source_name, dest_name) + except Exception: + pass def find_core_storage_volumes(device_path=None): - """Try to create block devices for any Apple CoreStorage volumes.""" - corestorage_uuid = '53746f72-6167-11aa-aa11-00306543ecac' - dmsetup_cmd_file = '{TmpDir}/dmsetup_command'.format(**global_vars) + """Try to create block devices for any Apple CoreStorage volumes.""" + corestorage_uuid = '53746f72-6167-11aa-aa11-00306543ecac' + dmsetup_cmd_file = '{TmpDir}/dmsetup_command'.format(**global_vars) - # Get CoreStorage devices + # Get CoreStorage devices + cmd = [ + 'lsblk', '--json', '--list', '--paths', + '--output', 'NAME,PARTTYPE'] + if device_path: + cmd.append(device_path) + result = run_program(cmd) + json_data = json.loads(result.stdout.decode()) + devs = json_data.get('blockdevices', []) + devs = [d for d in devs if d.get('parttype', '') == corestorage_uuid] + if devs: + print_standard(' ') + print_standard('Detected CoreStorage partition{}'.format( + '' if len(devs) == 1 else 's')) + print_standard(' Scanning for inner volume(s)....') + + # Search for inner volumes and setup dev mappers + for dev in devs: + dev_path = dev.get('name', '') + if not dev_path: + # Can't setup block device without the dev path + continue + dev_name = re.sub(r'.*/', '', dev_path) + log_path = '{LogDir}/testdisk_{dev_name}.log'.format( + dev_name=dev_name, **global_vars) + + # Run TestDisk cmd = [ - 'lsblk', '--json', '--list', '--paths', - '--output', 'NAME,PARTTYPE'] - if device_path: - cmd.append(device_path) - result = run_program(cmd) - json_data = json.loads(result.stdout.decode()) - devs = json_data.get('blockdevices', []) - devs = [d for d in devs if d.get('parttype', '') == corestorage_uuid] - if devs: - print_standard(' ') - print_standard('Detected CoreStorage partition{}'.format( - '' if len(devs) == 1 else 's')) - print_standard(' Scanning for inner volume(s)....') + 'sudo', 'testdisk', + '/logname', log_path, '/debug', '/log', + '/cmd', dev_path, 'partition_none,analyze'] + result = run_program(cmd, check=False) + if result.returncode: + # i.e. return code is non-zero + continue + if not os.path.exists(log_path): + # TestDisk failed to write log + continue - # Search for inner volumes and setup dev mappers - for dev in devs: - dev_path = dev.get('name', '') - if not dev_path: - # Can't setup block device without the dev path - continue - dev_name = re.sub(r'.*/', '', dev_path) - log_path = '{LogDir}/testdisk_{dev_name}.log'.format( - dev_name=dev_name, **global_vars) + # Check log for found volumes + cs_vols = {} + with open(log_path, 'r') as f: + for line in f.readlines(): + r = re.match( + r'^.*echo "([^"]+)" . dmsetup create test(\d)$', + line.strip(), + re.IGNORECASE) + if r: + cs_name = 'CoreStorage_{}_{}'.format(dev_name, r.group(2)) + cs_vols[cs_name] = r.group(1) - # Run TestDisk - cmd = [ - 'sudo', 'testdisk', - '/logname', log_path, '/debug', '/log', - '/cmd', dev_path, 'partition_none,analyze'] - result = run_program(cmd, check=False) - if result.returncode: - # i.e. return code is non-zero - continue - if not os.path.exists(log_path): - # TestDisk failed to write log - continue - - # Check log for found volumes - cs_vols = {} - with open(log_path, 'r') as f: - for line in f.readlines(): - r = re.match( - r'^.*echo "([^"]+)" . dmsetup create test(\d)$', - line.strip(), - re.IGNORECASE) - if r: - cs_name = 'CoreStorage_{}_{}'.format(dev_name, r.group(2)) - cs_vols[cs_name] = r.group(1) - - # Create mapper device(s) - for name, dm_cmd in sorted(cs_vols.items()): - with open(dmsetup_cmd_file, 'w') as f: - f.write(dm_cmd) - cmd = ['sudo', 'dmsetup', 'create', name, dmsetup_cmd_file] - run_program(cmd, check=False) + # Create mapper device(s) + for name, dm_cmd in sorted(cs_vols.items()): + with open(dmsetup_cmd_file, 'w') as f: + f.write(dm_cmd) + cmd = ['sudo', 'dmsetup', 'create', name, dmsetup_cmd_file] + run_program(cmd, check=False) def fix_path_sep(path_str): - """Replace non-native and duplicate dir separators, returns str.""" - return re.sub(r'(\\|/)+', lambda s: os.sep, path_str) + """Replace non-native and duplicate dir separators, returns str.""" + return re.sub(r'(\\|/)+', lambda s: os.sep, path_str) def is_valid_wim_file(item): - """Checks if the provided os.DirEntry is a valid WIM file, returns bool.""" - valid = bool(item.is_file() and REGEX_WIM_FILE.search(item.name)) - if valid: - extract_item('wimlib', silent=True) - cmd = [global_vars['Tools']['wimlib-imagex'], 'info', item.path] - try: - run_program(cmd) - except subprocess.CalledProcessError: - valid = False - print_log('WARNING: Image "{}" damaged.'.format(item.name)) - return valid + """Checks if the provided os.DirEntry is a valid WIM file, returns bool.""" + valid = bool(item.is_file() and REGEX_WIM_FILE.search(item.name)) + if valid: + extract_item('wimlib', silent=True) + cmd = [global_vars['Tools']['wimlib-imagex'], 'info', item.path] + try: + run_program(cmd) + except subprocess.CalledProcessError: + valid = False + print_log('WARNING: Image "{}" damaged.'.format(item.name)) + return valid def get_mounted_volumes(): - """Get mounted volumes, returns dict.""" - cmd = [ - 'findmnt', '-J', '-b', '-i', - '-t', ( - 'autofs,binfmt_misc,bpf,cgroup,cgroup2,configfs,debugfs,devpts,devtmpfs,' - 'hugetlbfs,mqueue,proc,pstore,securityfs,sysfs,tmpfs' - ), - '-o', 'SOURCE,TARGET,FSTYPE,LABEL,SIZE,AVAIL,USED'] - result = run_program(cmd) - json_data = json.loads(result.stdout.decode()) - mounted_volumes = [] - for item in json_data.get('filesystems', []): - mounted_volumes.append(item) - mounted_volumes.extend(item.get('children', [])) - return {item['source']: item for item in mounted_volumes} + """Get mounted volumes, returns dict.""" + cmd = [ + 'findmnt', '-J', '-b', '-i', + '-t', ( + 'autofs,binfmt_misc,bpf,cgroup,cgroup2,configfs,debugfs,devpts,' + 'devtmpfs,hugetlbfs,mqueue,proc,pstore,securityfs,sysfs,tmpfs' + ), + '-o', 'SOURCE,TARGET,FSTYPE,LABEL,SIZE,AVAIL,USED'] + result = run_program(cmd) + json_data = json.loads(result.stdout.decode()) + mounted_volumes = [] + for item in json_data.get('filesystems', []): + mounted_volumes.append(item) + mounted_volumes.extend(item.get('children', [])) + return {item['source']: item for item in mounted_volumes} def mount_volumes( - all_devices=True, device_path=None, - read_write=False, core_storage=True): - """Mount all detected filesystems.""" - report = {} - cmd = [ - 'lsblk', '--json', '--paths', - '--output', 'NAME,FSTYPE,LABEL,UUID,PARTTYPE,TYPE,SIZE'] - if not all_devices and device_path: - # Only mount volumes for specific device - cmd.append(device_path) + all_devices=True, device_path=None, + read_write=False, core_storage=True): + """Mount all detected filesystems.""" + report = {} + cmd = [ + 'lsblk', '--json', '--paths', + '--output', 'NAME,FSTYPE,LABEL,UUID,PARTTYPE,TYPE,SIZE'] + if not all_devices and device_path: + # Only mount volumes for specific device + cmd.append(device_path) - # Check for Apple CoreStorage volumes first - if core_storage: - find_core_storage_volumes(device_path) + # Check for Apple CoreStorage volumes first + if core_storage: + find_core_storage_volumes(device_path) - # Get list of block devices - result = run_program(cmd) - json_data = json.loads(result.stdout.decode()) - devs = json_data.get('blockdevices', []) + # Get list of block devices + result = run_program(cmd) + json_data = json.loads(result.stdout.decode()) + devs = json_data.get('blockdevices', []) - # Get list of volumes - volumes = {} - for dev in devs: - if not dev.get('children', []): - volumes.update({dev['name']: dev}) - for child in dev.get('children', []): - if not child.get('children', []): - volumes.update({child['name']: child}) - for grandchild in child.get('children', []): - volumes.update({grandchild['name']: grandchild}) + # Get list of volumes + volumes = {} + for dev in devs: + if not dev.get('children', []): + volumes.update({dev['name']: dev}) + for child in dev.get('children', []): + if not child.get('children', []): + volumes.update({child['name']: child}) + for grandchild in child.get('children', []): + volumes.update({grandchild['name']: grandchild}) - # Get list of mounted volumes - mounted_volumes = get_mounted_volumes() + # Get list of mounted volumes + mounted_volumes = get_mounted_volumes() - # Loop over volumes - for vol_path, vol_data in volumes.items(): - vol_data['show_data'] = { - 'message': vol_path.replace('/dev/mapper/', ''), - 'data': None, - } - if re.search(r'^loop\d', vol_path, re.IGNORECASE): - # Skip loopback devices - vol_data['show_data']['data'] = 'Skipped' - vol_data['show_data']['warning'] = True - report[vol_path] = vol_data - elif 'children' in vol_data: - # Skip LVM/RAID partitions (the real volume is mounted separately) - vol_data['show_data']['data'] = vol_data.get('fstype', 'UNKNOWN') - if vol_data.get('label', None): - vol_data['show_data']['data'] += ' "{}"'.format(vol_data['label']) - vol_data['show_data']['info'] = True - report[vol_path] = vol_data - else: - if vol_path in mounted_volumes: - vol_data['show_data']['warning'] = True - else: - # Mount volume - cmd = ['udevil', 'mount', - '-o', 'rw' if read_write else 'ro', - vol_path] - try: - run_program(cmd) - except subprocess.CalledProcessError: - vol_data['show_data']['data'] = 'Failed to mount' - vol_data['show_data']['error'] = True - # Update mounted_volumes data - mounted_volumes = get_mounted_volumes() + # Loop over volumes + for vol_path, vol_data in volumes.items(): + vol_data['show_data'] = { + 'message': vol_path.replace('/dev/mapper/', ''), + 'data': None, + } + if re.search(r'^loop\d', vol_path, re.IGNORECASE): + # Skip loopback devices + vol_data['show_data']['data'] = 'Skipped' + vol_data['show_data']['warning'] = True + report[vol_path] = vol_data + elif 'children' in vol_data: + # Skip LVM/RAID partitions (the real volume is mounted separately) + vol_data['show_data']['data'] = vol_data.get('fstype', 'UNKNOWN') + if vol_data.get('label', None): + vol_data['show_data']['data'] += ' "{}"'.format(vol_data['label']) + vol_data['show_data']['info'] = True + report[vol_path] = vol_data + else: + if vol_path in mounted_volumes: + vol_data['show_data']['warning'] = True + else: + # Mount volume + cmd = ['udevil', 'mount', + '-o', 'rw' if read_write else 'ro', + vol_path] + try: + run_program(cmd) + except subprocess.CalledProcessError: + vol_data['show_data']['data'] = 'Failed to mount' + vol_data['show_data']['error'] = True + # Update mounted_volumes data + mounted_volumes = get_mounted_volumes() - # Format pretty result string - if vol_data['show_data']['data'] == 'Failed to mount': - vol_data['mount_point'] = None - else: - size_used = human_readable_size( - mounted_volumes[vol_path]['used']) - size_avail = human_readable_size( - mounted_volumes[vol_path]['avail']) - vol_data['size_avail'] = size_avail - vol_data['size_used'] = size_used - vol_data['mount_point'] = mounted_volumes[vol_path]['target'] - vol_data['show_data']['data'] = 'Mounted on {}'.format( - mounted_volumes[vol_path]['target']) - vol_data['show_data']['data'] = '{:40} ({} used, {} free)'.format( - vol_data['show_data']['data'], - size_used, - size_avail) + # Format pretty result string + if vol_data['show_data']['data'] == 'Failed to mount': + vol_data['mount_point'] = None + else: + size_used = human_readable_size( + mounted_volumes[vol_path]['used']) + size_avail = human_readable_size( + mounted_volumes[vol_path]['avail']) + vol_data['size_avail'] = size_avail + vol_data['size_used'] = size_used + vol_data['mount_point'] = mounted_volumes[vol_path]['target'] + vol_data['show_data']['data'] = 'Mounted on {}'.format( + mounted_volumes[vol_path]['target']) + vol_data['show_data']['data'] = '{:40} ({} used, {} free)'.format( + vol_data['show_data']['data'], + size_used, + size_avail) - # Update report - report[vol_path] = vol_data + # Update report + report[vol_path] = vol_data - return report + return report def mount_backup_shares(read_write=False): - """Mount the backup shares unless labeled as already mounted.""" + """Mount the backup shares unless labeled as already mounted.""" + if psutil.LINUX: + mounted_volumes = get_mounted_volumes() + for server in BACKUP_SERVERS: if psutil.LINUX: - mounted_volumes = get_mounted_volumes() - for server in BACKUP_SERVERS: - if psutil.LINUX: - # Update mounted status - source = '//{IP}/{Share}'.format(**server) - dest = '/Backups/{Name}'.format(**server) - mounted_str = '(Already) Mounted {}'.format(dest) - data = mounted_volumes.get(source, {}) - if dest == data.get('target', ''): - server['Mounted'] = True - elif psutil.WINDOWS: - mounted_str = '(Already) Mounted {Name}'.format(**server) - if server['Mounted']: - print_warning(mounted_str) - continue + # Update mounted status + source = '//{IP}/{Share}'.format(**server) + dest = '/Backups/{Name}'.format(**server) + mounted_str = '(Already) Mounted {}'.format(dest) + data = mounted_volumes.get(source, {}) + if dest == data.get('target', ''): + server['Mounted'] = True + elif psutil.WINDOWS: + mounted_str = '(Already) Mounted {Name}'.format(**server) + if server['Mounted']: + print_warning(mounted_str) + continue - mount_network_share(server, read_write) + mount_network_share(server, read_write) def mount_network_share(server, read_write=False): - """Mount a network share defined by server.""" - if read_write: - username = server['RW-User'] - password = server['RW-Pass'] - else: - username = server['User'] - password = server['Pass'] - if psutil.WINDOWS: - cmd = [ - 'net', 'use', r'\\{IP}\{Share}'.format(**server), - '/user:{}'.format(username), password] - warning = r'Failed to mount \\{Name}\{Share}, {IP} unreachable.'.format( - **server) - error = r'Failed to mount \\{Name}\{Share} ({IP})'.format(**server) - success = 'Mounted {Name}'.format(**server) - elif psutil.LINUX: - cmd = [ - 'sudo', 'mkdir', '-p', - '/Backups/{Name}'.format(**server)] - run_program(cmd) - cmd = [ - 'sudo', 'mount', - '//{IP}/{Share}'.format(**server), - '/Backups/{Name}'.format(**server), - '-o', '{}username={},password={}'.format( - '' if read_write else 'ro,', - username, - password)] - warning = 'Failed to mount /Backups/{Name}, {IP} unreachable.'.format( - **server) - error = 'Failed to mount /Backups/{Name}'.format(**server) - success = 'Mounted /Backups/{Name}'.format(**server) + """Mount a network share defined by server.""" + if read_write: + username = server['RW-User'] + password = server['RW-Pass'] + else: + username = server['User'] + password = server['Pass'] + if psutil.WINDOWS: + cmd = [ + 'net', 'use', r'\\{IP}\{Share}'.format(**server), + '/user:{}'.format(username), password] + warning = r'Failed to mount \\{Name}\{Share}, {IP} unreachable.'.format( + **server) + error = r'Failed to mount \\{Name}\{Share} ({IP})'.format(**server) + success = 'Mounted {Name}'.format(**server) + elif psutil.LINUX: + cmd = [ + 'sudo', 'mkdir', '-p', + '/Backups/{Name}'.format(**server)] + run_program(cmd) + cmd = [ + 'sudo', 'mount', + '//{IP}/{Share}'.format(**server), + '/Backups/{Name}'.format(**server), + '-o', '{}username={},password={}'.format( + '' if read_write else 'ro,', + username, + password)] + warning = 'Failed to mount /Backups/{Name}, {IP} unreachable.'.format( + **server) + error = 'Failed to mount /Backups/{Name}'.format(**server) + success = 'Mounted /Backups/{Name}'.format(**server) - # Test connection - try: - ping(server['IP']) - except subprocess.CalledProcessError: - print_warning(warning) - sleep(1) - return False + # Test connection + try: + ping(server['IP']) + except subprocess.CalledProcessError: + print_warning(warning) + sleep(1) + return False - # Mount - try: - run_program(cmd) - except Exception: - print_error(error) - sleep(1) - else: - print_info(success) - server['Mounted'] = True + # Mount + try: + run_program(cmd) + except Exception: + print_error(error) + sleep(1) + else: + print_info(success) + server['Mounted'] = True def run_fast_copy(items, dest): - """Copy items to dest using FastCopy.""" - if not items: - raise Exception + """Copy items to dest using FastCopy.""" + if not items: + raise Exception - cmd = [global_vars['Tools']['FastCopy'], *FAST_COPY_ARGS] - cmd.append(r'/logfile={LogDir}\Tools\FastCopy.log'.format(**global_vars)) - cmd.extend(items) - cmd.append('/to={}\\'.format(dest)) + cmd = [global_vars['Tools']['FastCopy'], *FAST_COPY_ARGS] + cmd.append(r'/logfile={LogDir}\Tools\FastCopy.log'.format(**global_vars)) + cmd.extend(items) + cmd.append('/to={}\\'.format(dest)) - run_program(cmd) + run_program(cmd) def run_wimextract(source, items, dest): - """Extract items from source WIM to dest folder.""" - if not items: - raise Exception - extract_item('wimlib', silent=True) + """Extract items from source WIM to dest folder.""" + if not items: + raise Exception + extract_item('wimlib', silent=True) - # Write files.txt - with open(r'{}\wim_files.txt'.format(global_vars['TmpDir']), 'w', - encoding='utf-8') as f: - # Defaults - for item in items: - f.write('{}\n'.format(item)) - sleep(1) # For safety? + # Write files.txt + with open(r'{}\wim_files.txt'.format(global_vars['TmpDir']), 'w', + encoding='utf-8') as f: + # Defaults + for item in items: + f.write('{}\n'.format(item)) + sleep(1) # For safety? - # Extract files - cmd = [ - global_vars['Tools']['wimlib-imagex'], - 'extract', - source, '1', - r'@{}\wim_files.txt'.format(global_vars['TmpDir']), - '--dest-dir={}\\'.format(dest), - '--no-acls', - '--nullglob'] - run_program(cmd) + # Extract files + cmd = [ + global_vars['Tools']['wimlib-imagex'], + 'extract', + source, '1', + r'@{}\wim_files.txt'.format(global_vars['TmpDir']), + '--dest-dir={}\\'.format(dest), + '--no-acls', + '--nullglob'] + run_program(cmd) def list_source_items(source_obj, rel_path=None): - """List items in a dir or WIM, returns a list of SourceItem objects.""" - items = [] - rel_path = '{}{}'.format(os.sep, rel_path) if rel_path else '' - if source_obj.is_dir(): - source_path = '{}{}'.format(source_obj.path, rel_path) - items = [SourceItem(name=item.name, path=item.path) - for item in os.scandir(source_path)] - else: - # Prep wimlib-imagex - if psutil.WINDOWS: - extract_item('wimlib', silent=True) - cmd = [ - global_vars['Tools']['wimlib-imagex'], 'dir', - source_obj.path, '1'] - if rel_path: - cmd.append('--path={}'.format(rel_path)) + """List items in a dir or WIM, returns list of SourceItem objects.""" + items = [] + rel_path = '{}{}'.format(os.sep, rel_path) if rel_path else '' + if source_obj.is_dir(): + source_path = '{}{}'.format(source_obj.path, rel_path) + items = [SourceItem(name=item.name, path=item.path) + for item in os.scandir(source_path)] + else: + # Prep wimlib-imagex + if psutil.WINDOWS: + extract_item('wimlib', silent=True) + cmd = [ + global_vars['Tools']['wimlib-imagex'], 'dir', + source_obj.path, '1'] + if rel_path: + cmd.append('--path={}'.format(rel_path)) - # Get item list - try: - items = run_program(cmd) - except subprocess.CalledProcessError: - print_error('ERROR: Failed to get file list.') - raise + # Get item list + try: + items = run_program(cmd) + except subprocess.CalledProcessError: + print_error('ERROR: Failed to get file list.') + raise - # Strip non-root items - items = [fix_path_sep(i.strip()) - for i in items.stdout.decode('utf-8', 'ignore').splitlines()] - if rel_path: - items = [i.replace(rel_path, '') for i in items] - items = [i for i in items - if i.count(os.sep) == 1 and i.strip() != os.sep] - items = [SourceItem(name=i[1:], path=rel_path+i) for i in items] + # Strip non-root items + items = [fix_path_sep(i.strip()) + for i in items.stdout.decode('utf-8', 'ignore').splitlines()] + if rel_path: + items = [i.replace(rel_path, '') for i in items] + items = [i for i in items + if i.count(os.sep) == 1 and i.strip() != os.sep] + items = [SourceItem(name=i[1:], path=rel_path+i) for i in items] - # Done - return items + # Done + return items def scan_source(source_obj, dest_path, rel_path='', interactive=True): - """Scan source for files/folders to transfer, returns list. + """Scan source for files/folders to transfer, returns list. - This will scan the root and (recursively) any Windows.old folders.""" - selected_items = [] - win_olds = [] + This will scan the root and (recursively) any Windows.old folders.""" + selected_items = [] + win_olds = [] - # Root Items - root_items = [] - item_list = list_source_items(source_obj, rel_path) - for item in item_list: - if REGEX_WINDOWS_OLD.search(item.name): - item.name = '{}{}{}'.format( - rel_path, - os.sep if rel_path else '', - item.name) - win_olds.append(item) - elif REGEX_INCL_ROOT_ITEMS.search(item.name): - print_success('Auto-Selected: {}'.format(item.path)) - root_items.append('{}'.format(item.path)) - elif not REGEX_EXCL_ROOT_ITEMS.search(item.name): - if not interactive: - print_success('Auto-Selected: {}'.format(item.path)) - root_items.append('{}'.format(item.path)) - else: - prompt = 'Transfer: "{}{}{}" ?'.format( - rel_path, - os.sep if rel_path else '', - item.name) - choices = ['Yes', 'No', 'All', 'Quit'] - answer = choice(prompt=prompt, choices=choices) - if answer == 'Quit': - abort() - elif answer == 'All': - interactive = False - if answer in ['Yes', 'All']: - root_items.append('{}'.format(item.path)) - if root_items: - selected_items.append({ - 'Message': '{}{}Root Items...'.format( - rel_path, - ' ' if rel_path else ''), - 'Items': root_items.copy(), - 'Destination': dest_path}) + # Root Items + root_items = [] + item_list = list_source_items(source_obj, rel_path) + for item in item_list: + if REGEX_WINDOWS_OLD.search(item.name): + item.name = '{}{}{}'.format( + rel_path, + os.sep if rel_path else '', + item.name) + win_olds.append(item) + elif REGEX_INCL_ROOT_ITEMS.search(item.name): + print_success('Auto-Selected: {}'.format(item.path)) + root_items.append('{}'.format(item.path)) + elif not REGEX_EXCL_ROOT_ITEMS.search(item.name): + if not interactive: + print_success('Auto-Selected: {}'.format(item.path)) + root_items.append('{}'.format(item.path)) + else: + prompt = 'Transfer: "{}{}{}" ?'.format( + rel_path, + os.sep if rel_path else '', + item.name) + choices = ['Yes', 'No', 'All', 'Quit'] + answer = choice(prompt=prompt, choices=choices) + if answer == 'Quit': + abort() + elif answer == 'All': + interactive = False + if answer in ['Yes', 'All']: + root_items.append('{}'.format(item.path)) + if root_items: + selected_items.append({ + 'Message': '{}{}Root Items...'.format( + rel_path, + ' ' if rel_path else ''), + 'Items': root_items.copy(), + 'Destination': dest_path}) - # Fonts - font_obj = get_source_item_obj(source_obj, rel_path, 'Windows/Fonts') - if font_obj: - selected_items.append({ - 'Message': '{}{}Fonts...'.format( - rel_path, - ' ' if rel_path else ''), - 'Items': [font_obj.path], - 'Destination': '{}{}Windows'.format( - dest_path, os.sep)}) + # Fonts + font_obj = get_source_item_obj(source_obj, rel_path, 'Windows/Fonts') + if font_obj: + selected_items.append({ + 'Message': '{}{}Fonts...'.format( + rel_path, + ' ' if rel_path else ''), + 'Items': [font_obj.path], + 'Destination': '{}{}Windows'.format( + dest_path, os.sep)}) - # Registry - registry_items = [] - for folder in ['config', 'OEM']: - folder_obj = get_source_item_obj( - source_obj, rel_path, 'Windows/System32/{}'.format(folder)) - if folder_obj: - registry_items.append(folder_obj.path) - if registry_items: - selected_items.append({ - 'Message': '{}{}Registry...'.format( - rel_path, - ' ' if rel_path else ''), - 'Items': registry_items.copy(), - 'Destination': '{}{}Windows{}System32'.format( - dest_path, os.sep, os.sep)}) + # Registry + registry_items = [] + for folder in ['config', 'OEM']: + folder_obj = get_source_item_obj( + source_obj, rel_path, 'Windows/System32/{}'.format(folder)) + if folder_obj: + registry_items.append(folder_obj.path) + if registry_items: + selected_items.append({ + 'Message': '{}{}Registry...'.format( + rel_path, + ' ' if rel_path else ''), + 'Items': registry_items.copy(), + 'Destination': '{}{}Windows{}System32'.format( + dest_path, os.sep, os.sep)}) - # Windows.old(s) - for old in win_olds: - selected_items.extend(scan_source( - source_obj, - '{}{}{}'.format(dest_path, os.sep, old.name), - rel_path=old.name, - interactive=False)) + # Windows.old(s) + for old in win_olds: + selected_items.extend(scan_source( + source_obj, + '{}{}{}'.format(dest_path, os.sep, old.name), + rel_path=old.name, + interactive=False)) - # Done - return selected_items + # Done + return selected_items def get_source_item_obj(source_obj, rel_path, item_path): - """Check if the item exists and return a SourceItem object if it does.""" - item_obj = None - item_path = fix_path_sep(item_path) - if source_obj.is_dir(): - item_obj = SourceItem( - name = item_path, - path = '{}{}{}{}{}'.format( - source_obj.path, - os.sep, - rel_path, - os.sep if rel_path else '', - item_path)) - if not os.path.exists(item_obj.path): - item_obj = None + """Check if the item exists, returns SourceItem object or None.""" + item_obj = None + item_path = fix_path_sep(item_path) + if source_obj.is_dir(): + item_obj = SourceItem( + name = item_path, + path = '{}{}{}{}{}'.format( + source_obj.path, + os.sep, + rel_path, + os.sep if rel_path else '', + item_path)) + if not os.path.exists(item_obj.path): + item_obj = None + else: + # Assuming WIM file + if psutil.WINDOWS: + extract_item('wimlib', silent=True) + cmd = [ + global_vars['Tools']['wimlib-imagex'], 'dir', + source_obj.path, '1', + '--path={}'.format(item_path), + '--one-file-only'] + try: + run_program(cmd) + except subprocess.CalledProcessError: + # function will return None below + pass else: - # Assuming WIM file - if psutil.WINDOWS: - extract_item('wimlib', silent=True) - cmd = [ - global_vars['Tools']['wimlib-imagex'], 'dir', - source_obj.path, '1', - '--path={}'.format(item_path), - '--one-file-only'] - try: - run_program(cmd) - except subprocess.CalledProcessError: - # function will return None below - pass - else: - item_obj = SourceItem( - name = item_path, - path = '{}{}{}{}'.format( - os.sep, - rel_path, - os.sep if rel_path else '', - item_path)) - return item_obj + item_obj = SourceItem( + name = item_path, + path = '{}{}{}{}'.format( + os.sep, + rel_path, + os.sep if rel_path else '', + item_path)) + return item_obj def select_destination(folder_path, prompt='Select destination'): - """Select destination drive, returns path as string.""" - disk = select_volume(prompt) - if 'fixed' not in disk['Disk'].opts: - folder_path = folder_path.replace('\\', '-') - path = '{disk}{folder_path}_{Date}'.format( - disk = disk['Disk'].mountpoint, - folder_path = folder_path, - **global_vars) + """Select destination drive, returns path as string.""" + disk = select_volume(prompt) + if 'fixed' not in disk['Disk'].opts: + folder_path = folder_path.replace('\\', '-') + path = '{disk}{folder_path}_{Date}'.format( + disk = disk['Disk'].mountpoint, + folder_path = folder_path, + **global_vars) - # Avoid merging with existing folder - path = non_clobber_rename(path) - os.makedirs(path, exist_ok=True) + # Avoid merging with existing folder + path = non_clobber_rename(path) + os.makedirs(path, exist_ok=True) - return path + return path def select_source(backup_prefix): - """Select backup from those found on the BACKUP_SERVERS matching the prefix.""" - selected_source = None - local_sources = [] - remote_sources = [] - sources = [] - mount_backup_shares(read_write=False) + """Select matching backup from BACKUP_SERVERS, returns obj.""" + selected_source = None + local_sources = [] + remote_sources = [] + sources = [] + mount_backup_shares(read_write=False) - # Check for prefix folders on servers - for server in BACKUP_SERVERS: - if server['Mounted']: - print_standard('Scanning {}...'.format(server['Name'])) - for d in os.scandir(r'\\{IP}\{Share}'.format(**server)): - if (d.is_dir() - and d.name.lower().startswith(backup_prefix.lower())): - # Add folder to remote_sources - remote_sources.append({ - 'Name': '{:9}| File-Based: [DIR] {}'.format( - server['Name'], d.name), - 'Server': server, - 'Sort': d.name, - 'Source': d}) + # Check for prefix folders on servers + for server in BACKUP_SERVERS: + if server['Mounted']: + print_standard('Scanning {}...'.format(server['Name'])) + for d in os.scandir(r'\\{IP}\{Share}'.format(**server)): + if (d.is_dir() + and d.name.lower().startswith(backup_prefix.lower())): + # Add folder to remote_sources + remote_sources.append({ + 'Name': '{:9}| File-Based: [DIR] {}'.format( + server['Name'], d.name), + 'Server': server, + 'Sort': d.name, + 'Source': d}) - # Check for images and subfolders - for prefix_path in remote_sources.copy(): - for item in os.scandir(prefix_path['Source'].path): - if item.is_dir(): - # Add folder to remote_sources - remote_sources.append({ - 'Name': r'{:9}| File-Based: [DIR] {}\{}'.format( - prefix_path['Server']['Name'], # Server - prefix_path['Source'].name, # Prefix folder - item.name, # Sub-folder - ), - 'Server': prefix_path['Server'], - 'Sort': r'{}\{}'.format( - prefix_path['Source'].name, # Prefix folder - item.name, # Sub-folder - ), - 'Source': item}) + # Check for images and subfolders + for prefix_path in remote_sources.copy(): + for item in os.scandir(prefix_path['Source'].path): + if item.is_dir(): + # Add folder to remote_sources + remote_sources.append({ + 'Name': r'{:9}| File-Based: [DIR] {}\{}'.format( + prefix_path['Server']['Name'], # Server + prefix_path['Source'].name, # Prefix folder + item.name, # Sub-folder + ), + 'Server': prefix_path['Server'], + 'Sort': r'{}\{}'.format( + prefix_path['Source'].name, # Prefix folder + item.name, # Sub-folder + ), + 'Source': item}) - # Check for images in folder - for subitem in os.scandir(item.path): - if REGEX_WIM_FILE.search(item.name): - # Add image to remote_sources - try: - size = human_readable_size(item.stat().st_size) - except Exception: - size = ' ? ?' # unknown - remote_sources.append({ - 'Disabled': bool(not is_valid_wim_file(subitem)), - 'Name': r'{:9}| Image-Based: {:>7} {}\{}\{}'.format( - prefix_path['Server']['Name'], # Server - size, # Size (duh) - prefix_path['Source'].name, # Prefix folder - item.name, # Sub-folder - subitem.name, # Image file - ), - 'Server': prefix_path['Server'], - 'Sort': r'{}\{}\{}'.format( - prefix_path['Source'].name, # Prefix folder - item.name, # Sub-folder - subitem.name, # Image file - ), - 'Source': subitem}) - elif REGEX_WIM_FILE.search(item.name): - # Add image to remote_sources - try: - size = human_readable_size(item.stat().st_size) - except Exception: - size = ' ? ?' # unknown - remote_sources.append({ - 'Disabled': bool(not is_valid_wim_file(item)), - 'Name': r'{:9}| Image-Based: {:>7} {}\{}'.format( - prefix_path['Server']['Name'], # Server - size, # Size (duh) - prefix_path['Source'].name, # Prefix folder - item.name, # Image file - ), - 'Server': prefix_path['Server'], - 'Sort': r'{}\{}'.format( - prefix_path['Source'].name, # Prefix folder - item.name, # Image file - ), - 'Source': item}) + # Check for images in folder + for subitem in os.scandir(item.path): + if REGEX_WIM_FILE.search(item.name): + # Add image to remote_sources + try: + size = human_readable_size(item.stat().st_size) + except Exception: + size = ' ? ?' # unknown + remote_sources.append({ + 'Disabled': bool(not is_valid_wim_file(subitem)), + 'Name': r'{:9}| Image-Based: {:>7} {}\{}\{}'.format( + prefix_path['Server']['Name'], # Server + size, # Size (duh) + prefix_path['Source'].name, # Prefix folder + item.name, # Sub-folder + subitem.name, # Image file + ), + 'Server': prefix_path['Server'], + 'Sort': r'{}\{}\{}'.format( + prefix_path['Source'].name, # Prefix folder + item.name, # Sub-folder + subitem.name, # Image file + ), + 'Source': subitem}) + elif REGEX_WIM_FILE.search(item.name): + # Add image to remote_sources + try: + size = human_readable_size(item.stat().st_size) + except Exception: + size = ' ? ?' # unknown + remote_sources.append({ + 'Disabled': bool(not is_valid_wim_file(item)), + 'Name': r'{:9}| Image-Based: {:>7} {}\{}'.format( + prefix_path['Server']['Name'], # Server + size, # Size (duh) + prefix_path['Source'].name, # Prefix folder + item.name, # Image file + ), + 'Server': prefix_path['Server'], + 'Sort': r'{}\{}'.format( + prefix_path['Source'].name, # Prefix folder + item.name, # Image file + ), + 'Source': item}) - # Check for local sources - print_standard('Scanning for local sources...') - set_thread_error_mode(silent=True) # Prevents "No disk" popups - sys_drive = global_vars['Env']['SYSTEMDRIVE'] - for d in psutil.disk_partitions(): - if re.search(r'^{}'.format(sys_drive), d.mountpoint, re.IGNORECASE): - # Skip current OS drive - continue - if 'fixed' in d.opts: - # Skip DVD, etc - local_sources.append({ - 'Name': '{:9}| File-Based: [DISK] {}'.format( - ' Local', d.mountpoint), - 'Sort': d.mountpoint, - 'Source': LocalDisk(d)}) - # Check for images and subfolders - for item in os.scandir(d.mountpoint): - if REGEX_WIM_FILE.search(item.name): - try: - size = human_readable_size(item.stat().st_size) - except Exception: - size = ' ? ?' # unknown - local_sources.append({ - 'Disabled': bool(not is_valid_wim_file(item)), - 'Name': r'{:9}| Image-Based: {:>7} {}{}'.format( - ' Local', size, d.mountpoint, item.name), - 'Sort': r'{}{}'.format(d.mountpoint, item.name), - 'Source': item}) - elif REGEX_EXCL_ROOT_ITEMS.search(item.name): - pass - elif REGEX_EXCL_ITEMS.search(item.name): - pass - elif item.is_dir(): - # Add folder to local_sources - local_sources.append({ - 'Name': r'{:9}| File-Based: [DIR] {}{}'.format( - ' Local', d.mountpoint, item.name), - 'Sort': r'{}{}'.format(d.mountpoint, item.name), - 'Source': item}) + # Check for local sources + print_standard('Scanning for local sources...') + set_thread_error_mode(silent=True) # Prevents "No disk" popups + sys_drive = global_vars['Env']['SYSTEMDRIVE'] + for d in psutil.disk_partitions(): + if re.search(r'^{}'.format(sys_drive), d.mountpoint, re.IGNORECASE): + # Skip current OS drive + continue + if 'fixed' in d.opts: + # Skip DVD, etc + local_sources.append({ + 'Name': '{:9}| File-Based: [DISK] {}'.format( + ' Local', d.mountpoint), + 'Sort': d.mountpoint, + 'Source': LocalDisk(d)}) + # Check for images and subfolders + for item in os.scandir(d.mountpoint): + if REGEX_WIM_FILE.search(item.name): + try: + size = human_readable_size(item.stat().st_size) + except Exception: + size = ' ? ?' # unknown + local_sources.append({ + 'Disabled': bool(not is_valid_wim_file(item)), + 'Name': r'{:9}| Image-Based: {:>7} {}{}'.format( + ' Local', size, d.mountpoint, item.name), + 'Sort': r'{}{}'.format(d.mountpoint, item.name), + 'Source': item}) + elif REGEX_EXCL_ROOT_ITEMS.search(item.name): + pass + elif REGEX_EXCL_ITEMS.search(item.name): + pass + elif item.is_dir(): + # Add folder to local_sources + local_sources.append({ + 'Name': r'{:9}| File-Based: [DIR] {}{}'.format( + ' Local', d.mountpoint, item.name), + 'Sort': r'{}{}'.format(d.mountpoint, item.name), + 'Source': item}) - set_thread_error_mode(silent=False) # Return to normal + set_thread_error_mode(silent=False) # Return to normal - # Build Menu - local_sources.sort(key=itemgetter('Sort')) - remote_sources.sort(key=itemgetter('Sort')) - sources.extend(local_sources) - sources.extend(remote_sources) - actions = [{'Name': 'Quit', 'Letter': 'Q'}] + # Build Menu + local_sources.sort(key=itemgetter('Sort')) + remote_sources.sort(key=itemgetter('Sort')) + sources.extend(local_sources) + sources.extend(remote_sources) + actions = [{'Name': 'Quit', 'Letter': 'Q'}] - # Select backup from sources - if len(sources) > 0: - selection = menu_select( - 'Which backup are we using?', - main_entries=sources, - action_entries=actions, - disabled_label='DAMAGED') - if selection == 'Q': - umount_backup_shares() - exit_script() - else: - selected_source = sources[int(selection)-1]['Source'] + # Select backup from sources + if len(sources) > 0: + selection = menu_select( + 'Which backup are we using?', + main_entries=sources, + action_entries=actions, + disabled_label='DAMAGED') + if selection == 'Q': + umount_backup_shares() + exit_script() else: - print_error('ERROR: No backups found using prefix: {}.'.format( - backup_prefix)) - umount_backup_shares() - pause("Press Enter to exit...") - exit_script() + selected_source = sources[int(selection)-1]['Source'] + else: + print_error('ERROR: No backups found using prefix: {}.'.format( + backup_prefix)) + umount_backup_shares() + pause("Press Enter to exit...") + exit_script() - # Sanity check - if selected_source.is_file(): - # Image-Based - if not REGEX_WIM_FILE.search(selected_source.name): - print_error('ERROR: Unsupported image: {}'.format( - selected_source.path)) - raise GenericError + # Sanity check + if selected_source.is_file(): + # Image-Based + if not REGEX_WIM_FILE.search(selected_source.name): + print_error('ERROR: Unsupported image: {}'.format( + selected_source.path)) + raise GenericError - # Done - return selected_source + # Done + return selected_source def select_volume(title='Select disk', auto_select=True): - """Select disk from attached disks. returns dict.""" - actions = [{'Name': 'Quit', 'Letter': 'Q'}] - disks = [] + """Select disk from attached disks. returns dict.""" + actions = [{'Name': 'Quit', 'Letter': 'Q'}] + disks = [] - # Build list of disks - set_thread_error_mode(silent=True) # Prevents "No disk" popups - for d in psutil.disk_partitions(): - info = { - 'Disk': d, - 'Name': d.mountpoint} - try: - usage = psutil.disk_usage(d.device) - free = '{free} / {total} available'.format( - free = human_readable_size(usage.free, 2), - total = human_readable_size(usage.total, 2)) - except Exception: - # Meh, leaving unsupported destinations out - pass - # free = 'Unknown' - # info['Disabled'] = True - else: - info['Display Name'] = '{} ({})'.format(info['Name'], free) - disks.append(info) - set_thread_error_mode(silent=False) # Return to normal - - # Skip menu? - if len(disks) == 1 and auto_select: - return disks[0] - - # Show menu - selection = menu_select(title, main_entries=disks, action_entries=actions) - if selection == 'Q': - exit_script() + # Build list of disks + set_thread_error_mode(silent=True) # Prevents "No disk" popups + for d in psutil.disk_partitions(): + info = { + 'Disk': d, + 'Name': d.mountpoint} + try: + usage = psutil.disk_usage(d.device) + free = '{free} / {total} available'.format( + free = human_readable_size(usage.free, 2), + total = human_readable_size(usage.total, 2)) + except Exception: + # Meh, leaving unsupported destinations out + pass + # free = 'Unknown' + # info['Disabled'] = True else: - return disks[int(selection)-1] + info['Display Name'] = '{} ({})'.format(info['Name'], free) + disks.append(info) + set_thread_error_mode(silent=False) # Return to normal + + # Skip menu? + if len(disks) == 1 and auto_select: + return disks[0] + + # Show menu + selection = menu_select(title, main_entries=disks, action_entries=actions) + if selection == 'Q': + exit_script() + else: + return disks[int(selection)-1] def set_thread_error_mode(silent=True): - """Disable or Enable Windows error message dialogs. + """Disable or Enable Windows error message dialogs. - Disable when scanning for disks to avoid popups for empty cardreaders, etc - """ - # Code borrowed from: https://stackoverflow.com/a/29075319 - kernel32 = ctypes.WinDLL('kernel32') + Disable when scanning disks to avoid popups for empty cardreaders, etc + """ + # Code borrowed from: https://stackoverflow.com/a/29075319 + kernel32 = ctypes.WinDLL('kernel32') - if silent: - kernel32.SetThreadErrorMode(SEM_FAIL, ctypes.byref(SEM_NORMAL)) - else: - kernel32.SetThreadErrorMode(SEM_NORMAL, ctypes.byref(SEM_NORMAL)) + if silent: + kernel32.SetThreadErrorMode(SEM_FAIL, ctypes.byref(SEM_NORMAL)) + else: + kernel32.SetThreadErrorMode(SEM_NORMAL, ctypes.byref(SEM_NORMAL)) def transfer_source(source_obj, dest_path, selected_items): - """Transfer, or extract, files/folders from source to destination.""" - if source_obj.is_dir(): - # Run FastCopy for each selection "group" - for group in selected_items: - try_and_print(message=group['Message'], - function=run_fast_copy, cs='Done', - items=group['Items'], - dest=group['Destination']) + """Transfer, or extract, files/folders from source to destination.""" + if source_obj.is_dir(): + # Run FastCopy for each selection "group" + for group in selected_items: + try_and_print(message=group['Message'], + function=run_fast_copy, cs='Done', + items=group['Items'], + dest=group['Destination']) + else: + if REGEX_WIM_FILE.search(source_obj.name): + # Extract files from WIM + for group in selected_items: + try_and_print(message=group['Message'], + function=run_wimextract, cs='Done', + source=source_obj.path, + items=group['Items'], + dest=dest_path) else: - if REGEX_WIM_FILE.search(source_obj.name): - # Extract files from WIM - for group in selected_items: - try_and_print(message=group['Message'], - function=run_wimextract, cs='Done', - source=source_obj.path, - items=group['Items'], - dest=dest_path) - else: - print_error('ERROR: Unsupported image: {}'.format(source_obj.path)) - raise GenericError + print_error('ERROR: Unsupported image: {}'.format(source_obj.path)) + raise GenericError def umount_backup_shares(): - """Unmount the backup shares regardless of current status.""" - for server in BACKUP_SERVERS: - umount_network_share(server) + """Unmount the backup shares regardless of current status.""" + for server in BACKUP_SERVERS: + umount_network_share(server) def umount_network_share(server): - """Unmount a network share defined by server.""" - cmd = r'net use \\{IP}\{Share} /delete'.format(**server) - cmd = cmd.split(' ') - try: - run_program(cmd) - except Exception: - print_error(r'Failed to umount \\{Name}\{Share}.'.format(**server)) - sleep(1) - else: - print_info('Umounted {Name}'.format(**server)) - server['Mounted'] = False + """Unmount a network share defined by server.""" + cmd = r'net use \\{IP}\{Share} /delete'.format(**server) + cmd = cmd.split(' ') + try: + run_program(cmd) + except Exception: + print_error(r'Failed to umount \\{Name}\{Share}.'.format(**server)) + sleep(1) + else: + print_info('Umounted {Name}'.format(**server)) + server['Mounted'] = False if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From 10e978d4c5657a412999a96609cd0191d3137461 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 19:50:51 -0700 Subject: [PATCH 160/265] Updated ddrescue.py --- .bin/Scripts/functions/ddrescue.py | 2282 ++++++++++++++-------------- 1 file changed, 1141 insertions(+), 1141 deletions(-) diff --git a/.bin/Scripts/functions/ddrescue.py b/.bin/Scripts/functions/ddrescue.py index 6e515655..7e3a06df 100644 --- a/.bin/Scripts/functions/ddrescue.py +++ b/.bin/Scripts/functions/ddrescue.py @@ -19,1345 +19,1345 @@ from operator import itemgetter AUTO_PASS_1_THRESHOLD = 95 AUTO_PASS_2_THRESHOLD = 98 DDRESCUE_SETTINGS = { - '--binary-prefixes': {'Enabled': True, 'Hidden': True}, - '--data-preview': {'Enabled': True, 'Hidden': True, 'Value': '5'}, - '--idirect': {'Enabled': True}, - '--odirect': {'Enabled': True}, - '--max-read-rate': {'Enabled': False, 'Value': '1MiB'}, - '--min-read-rate': {'Enabled': True, 'Value': '64KiB'}, - '--reopen-on-error': {'Enabled': True}, - '--retry-passes': {'Enabled': True, 'Value': '0'}, - '--test-mode': {'Enabled': False, 'Value': 'test.map'}, - '--timeout': {'Enabled': True, 'Value': '5m'}, - '-vvvv': {'Enabled': True, 'Hidden': True}, - } + '--binary-prefixes': {'Enabled': True, 'Hidden': True}, + '--data-preview': {'Enabled': True, 'Hidden': True, 'Value': '5'}, + '--idirect': {'Enabled': True}, + '--odirect': {'Enabled': True}, + '--max-read-rate': {'Enabled': False, 'Value': '1MiB'}, + '--min-read-rate': {'Enabled': True, 'Value': '64KiB'}, + '--reopen-on-error': {'Enabled': True}, + '--retry-passes': {'Enabled': True, 'Value': '0'}, + '--test-mode': {'Enabled': False, 'Value': 'test.map'}, + '--timeout': {'Enabled': True, 'Value': '5m'}, + '-vvvv': {'Enabled': True, 'Hidden': True}, + } RECOMMENDED_FSTYPES = ['ext3', 'ext4', 'xfs'] SIDE_PANE_WIDTH = 21 TMUX_LAYOUT = OrderedDict({ - 'Source': {'y': 2, 'Check': True}, + 'Source': {'y': 2, 'Check': True}, 'Started': {'x': SIDE_PANE_WIDTH, 'Check': True}, 'Progress': {'x': SIDE_PANE_WIDTH, 'Check': True}, }) -USAGE = """ {script_name} clone [source [destination]] - {script_name} image [source [destination]] - (e.g. {script_name} clone /dev/sda /dev/sdb) +USAGE = """ {script_name} clone [source [destination]] + {script_name} image [source [destination]] + (e.g. {script_name} clone /dev/sda /dev/sdb) """ # Clases class BaseObj(): - """Base object used by DevObj, DirObj, and ImageObj.""" - def __init__(self, path): - self.type = 'base' - self.parent = None - self.path = os.path.realpath(path) - self.set_details() + """Base object used by DevObj, DirObj, and ImageObj.""" + def __init__(self, path): + self.type = 'base' + self.parent = None + self.path = os.path.realpath(path) + self.set_details() - def is_dev(self): - return self.type == 'dev' + def is_dev(self): + return self.type == 'dev' - def is_dir(self): - return self.type == 'dir' + def is_dir(self): + return self.type == 'dir' - def is_image(self): - return self.type == 'image' + def is_image(self): + return self.type == 'image' - def self_check(self): - pass + def self_check(self): + pass - def set_details(self): - self.details = {} + def set_details(self): + self.details = {} class BlockPair(): - """Object to track data and methods together for source and dest.""" - def __init__(self, mode, source, dest): - self.mode = mode - self.source = source - self.source_path = source.path - self.dest = dest - self.pass_done = [False, False, False] - self.resumed = False - self.rescued = 0 - self.rescued_percent = 0 - self.status = ['Pending', 'Pending', 'Pending'] - self.size = source.size - # Set dest paths - if self.mode == 'clone': - # Cloning - self.dest_path = dest.path - self.map_path = '{pwd}/Clone_{prefix}.map'.format( - pwd=os.path.realpath(global_vars['Env']['PWD']), - prefix=source.prefix) - else: - # Imaging - self.dest_path = '{path}/{prefix}.dd'.format( - path=dest.path, - prefix=source.prefix) - self.map_path = '{path}/{prefix}.map'.format( - path=dest.path, - prefix=source.prefix) - if os.path.exists(self.map_path): - self.load_map_data() - self.resumed = True - self.fix_status_strings() + """Object to track data and methods together for source and dest.""" + def __init__(self, mode, source, dest): + self.mode = mode + self.source = source + self.source_path = source.path + self.dest = dest + self.pass_done = [False, False, False] + self.resumed = False + self.rescued = 0 + self.rescued_percent = 0 + self.status = ['Pending', 'Pending', 'Pending'] + self.size = source.size + # Set dest paths + if self.mode == 'clone': + # Cloning + self.dest_path = dest.path + self.map_path = '{pwd}/Clone_{prefix}.map'.format( + pwd=os.path.realpath(global_vars['Env']['PWD']), + prefix=source.prefix) + else: + # Imaging + self.dest_path = '{path}/{prefix}.dd'.format( + path=dest.path, + prefix=source.prefix) + self.map_path = '{path}/{prefix}.map'.format( + path=dest.path, + prefix=source.prefix) + if os.path.exists(self.map_path): + self.load_map_data() + self.resumed = True + self.fix_status_strings() - def fix_status_strings(self): - """Format status strings via get_formatted_status().""" - for pass_num in [1, 2, 3]: - self.status[pass_num-1] = get_formatted_status( - label='Pass {}'.format(pass_num), - data=self.status[pass_num-1]) + def fix_status_strings(self): + """Format status strings via get_formatted_status().""" + for pass_num in [1, 2, 3]: + self.status[pass_num-1] = get_formatted_status( + label='Pass {}'.format(pass_num), + data=self.status[pass_num-1]) - def finish_pass(self, pass_num): - """Mark pass as done and check if 100% recovered.""" - map_data = read_map_file(self.map_path) - if map_data['full recovery']: - self.pass_done = [True, True, True] - self.rescued = self.size - self.status[pass_num] = get_formatted_status( - label='Pass {}'.format(pass_num+1), - data=100) - # Mark future passes as Skipped - pass_num += 1 - while pass_num <= 2: - self.status[pass_num] = get_formatted_status( - label='Pass {}'.format(pass_num+1), - data='Skipped') - pass_num += 1 - else: - self.pass_done[pass_num] = True + def finish_pass(self, pass_num): + """Mark pass as done and check if 100% recovered.""" + map_data = read_map_file(self.map_path) + if map_data['full recovery']: + self.pass_done = [True, True, True] + self.rescued = self.size + self.status[pass_num] = get_formatted_status( + label='Pass {}'.format(pass_num+1), + data=100) + # Mark future passes as Skipped + pass_num += 1 + while pass_num <= 2: + self.status[pass_num] = get_formatted_status( + label='Pass {}'.format(pass_num+1), + data='Skipped') + pass_num += 1 + else: + self.pass_done[pass_num] = True - def load_map_data(self): - """Load data from map file and set progress.""" - map_data = read_map_file(self.map_path) - self.rescued_percent = map_data['rescued'] - self.rescued = (self.rescued_percent * self.size) / 100 - if map_data['full recovery']: - self.pass_done = [True, True, True] - self.rescued = self.size - self.status = ['Skipped', 'Skipped', 'Skipped'] - elif map_data['non-tried'] > 0: - # Initial pass incomplete - pass - elif map_data['non-trimmed'] > 0: - self.pass_done = [True, False, False] - self.status = ['Skipped', 'Pending', 'Pending'] - elif map_data['non-scraped'] > 0: - self.pass_done = [True, True, False] - self.status = ['Skipped', 'Skipped', 'Pending'] - else: - self.pass_done = [True, True, True] - self.status = ['Skipped', 'Skipped', 'Skipped'] + def load_map_data(self): + """Load data from map file and set progress.""" + map_data = read_map_file(self.map_path) + self.rescued_percent = map_data['rescued'] + self.rescued = (self.rescued_percent * self.size) / 100 + if map_data['full recovery']: + self.pass_done = [True, True, True] + self.rescued = self.size + self.status = ['Skipped', 'Skipped', 'Skipped'] + elif map_data['non-tried'] > 0: + # Initial pass incomplete + pass + elif map_data['non-trimmed'] > 0: + self.pass_done = [True, False, False] + self.status = ['Skipped', 'Pending', 'Pending'] + elif map_data['non-scraped'] > 0: + self.pass_done = [True, True, False] + self.status = ['Skipped', 'Skipped', 'Pending'] + else: + self.pass_done = [True, True, True] + self.status = ['Skipped', 'Skipped', 'Skipped'] - def self_check(self): - """Self check to abort on bad dest/map combinations.""" - dest_exists = os.path.exists(self.dest_path) - map_exists = os.path.exists(self.map_path) - if self.mode == 'image': - if dest_exists and not map_exists: - raise GenericError( - 'Detected image "{}" but not the matching map'.format( - self.dest_path)) - elif not dest_exists and map_exists: - raise GenericError( - 'Detected map "{}" but not the matching image'.format( - self.map_path)) - elif not dest_exists: - raise GenericError('Destination device "{}" missing'.format( - self.dest_path)) + def self_check(self): + """Self check to abort on bad dest/map combinations.""" + dest_exists = os.path.exists(self.dest_path) + map_exists = os.path.exists(self.map_path) + if self.mode == 'image': + if dest_exists and not map_exists: + raise GenericError( + 'Detected image "{}" but not the matching map'.format( + self.dest_path)) + elif not dest_exists and map_exists: + raise GenericError( + 'Detected map "{}" but not the matching image'.format( + self.map_path)) + elif not dest_exists: + raise GenericError('Destination device "{}" missing'.format( + self.dest_path)) - def update_progress(self, pass_num): - """Update progress using map file.""" - if os.path.exists(self.map_path): - map_data = read_map_file(self.map_path) - self.rescued_percent = map_data.get('rescued', 0) - self.rescued = (self.rescued_percent * self.size) / 100 - self.status[pass_num] = get_formatted_status( - label='Pass {}'.format(pass_num+1), - data=(self.rescued/self.size)*100) + def update_progress(self, pass_num): + """Update progress using map file.""" + if os.path.exists(self.map_path): + map_data = read_map_file(self.map_path) + self.rescued_percent = map_data.get('rescued', 0) + self.rescued = (self.rescued_percent * self.size) / 100 + self.status[pass_num] = get_formatted_status( + label='Pass {}'.format(pass_num+1), + data=(self.rescued/self.size)*100) class DevObj(BaseObj): - """Block device object.""" - def self_check(self): - """Verify that self.path points to a block device.""" - if not pathlib.Path(self.path).is_block_device(): - raise GenericError('Path "{}" is not a block device.'.format( - self.path)) - if self.parent: - print_warning('"{}" is a child device.'.format(self.path)) - if ask('Use parent device "{}" instead?'.format(self.parent)): - self.path = os.path.realpath(self.parent) - self.set_details() + """Block device object.""" + def self_check(self): + """Verify that self.path points to a block device.""" + if not pathlib.Path(self.path).is_block_device(): + raise GenericError('Path "{}" is not a block device.'.format( + self.path)) + if self.parent: + print_warning('"{}" is a child device.'.format(self.path)) + if ask('Use parent device "{}" instead?'.format(self.parent)): + self.path = os.path.realpath(self.parent) + self.set_details() - def set_details(self): - """Set details via lsblk.""" - self.type = 'dev' - self.details = get_device_details(self.path) - self.name = '{name} {size} {model} {serial}'.format( - name=self.details.get('name', 'UNKNOWN'), - size=self.details.get('size', 'UNKNOWN'), - model=self.details.get('model', 'UNKNOWN'), - serial=self.details.get('serial', 'UNKNOWN')) - self.model = self.details.get('model', 'UNKNOWN') - self.model_size = self.details.get('size', 'UNKNOWN') - self.size = get_size_in_bytes(self.details.get('size', 'UNKNOWN')) - self.report = get_device_report(self.path) - self.parent = self.details.get('pkname', '') - self.label = self.details.get('label', '') - if not self.label: - # Force empty string in case it's set to None - self.label = '' - self.update_filename_prefix() + def set_details(self): + """Set details via lsblk.""" + self.type = 'dev' + self.details = get_device_details(self.path) + self.name = '{name} {size} {model} {serial}'.format( + name=self.details.get('name', 'UNKNOWN'), + size=self.details.get('size', 'UNKNOWN'), + model=self.details.get('model', 'UNKNOWN'), + serial=self.details.get('serial', 'UNKNOWN')) + self.model = self.details.get('model', 'UNKNOWN') + self.model_size = self.details.get('size', 'UNKNOWN') + self.size = get_size_in_bytes(self.details.get('size', 'UNKNOWN')) + self.report = get_device_report(self.path) + self.parent = self.details.get('pkname', '') + self.label = self.details.get('label', '') + if not self.label: + # Force empty string in case it's set to None + self.label = '' + self.update_filename_prefix() - def update_filename_prefix(self): - """Set filename prefix based on details.""" - self.prefix = '{m_size}_{model}'.format( - m_size=self.model_size, - model=self.model) - self.prefix = self.prefix.strip() - if self.parent: - # Add child device details - c_num = self.path.replace(self.parent, '') - self.prefix += '_{c_prefix}{c_num}_{c_size}{sep}{c_label}'.format( - c_prefix='p' if len(c_num) == 1 else '', - c_num=c_num, - c_size=self.details.get('size', 'UNKNOWN'), - sep='_' if self.label else '', - c_label=self.label) - self.prefix = self.prefix.strip().replace(' ', '_') - self.prefix = self.prefix.strip().replace('/', '_') + def update_filename_prefix(self): + """Set filename prefix based on details.""" + self.prefix = '{m_size}_{model}'.format( + m_size=self.model_size, + model=self.model) + self.prefix = self.prefix.strip() + if self.parent: + # Add child device details + c_num = self.path.replace(self.parent, '') + self.prefix += '_{c_prefix}{c_num}_{c_size}{sep}{c_label}'.format( + c_prefix='p' if len(c_num) == 1 else '', + c_num=c_num, + c_size=self.details.get('size', 'UNKNOWN'), + sep='_' if self.label else '', + c_label=self.label) + self.prefix = self.prefix.strip().replace(' ', '_') + self.prefix = self.prefix.strip().replace('/', '_') class DirObj(BaseObj): - def self_check(self): - """Verify that self.path points to a directory.""" - if not pathlib.Path(self.path).is_dir(): - raise GenericError('Path "{}" is not a directory.'.format( - self.path)) + def self_check(self): + """Verify that self.path points to a directory.""" + if not pathlib.Path(self.path).is_dir(): + raise GenericError('Path "{}" is not a directory.'.format( + self.path)) - def set_details(self): - """Set details via findmnt.""" - self.type = 'dir' - self.details = get_dir_details(self.path) - self.fstype = self.details.get('fstype', 'UNKNOWN') - self.name = self.path + '/' - self.size = get_size_in_bytes(self.details.get('avail', 'UNKNOWN')) - self.report = get_dir_report(self.path) + def set_details(self): + """Set details via findmnt.""" + self.type = 'dir' + self.details = get_dir_details(self.path) + self.fstype = self.details.get('fstype', 'UNKNOWN') + self.name = self.path + '/' + self.size = get_size_in_bytes(self.details.get('avail', 'UNKNOWN')) + self.report = get_dir_report(self.path) class ImageObj(BaseObj): - def self_check(self): - """Verify that self.path points to a file.""" - if not pathlib.Path(self.path).is_file(): - raise GenericError('Path "{}" is not an image file.'.format( - self.path)) + def self_check(self): + """Verify that self.path points to a file.""" + if not pathlib.Path(self.path).is_file(): + raise GenericError('Path "{}" is not an image file.'.format( + self.path)) - def set_details(self): - """Setup loopback device, set details via lsblk, then detach device.""" - self.type = 'image' - self.loop_dev = setup_loopback_device(self.path) - self.details = get_device_details(self.loop_dev) - self.details['model'] = 'ImageFile' - self.name = '{name} {size}'.format( - name=self.path[self.path.rfind('/')+1:], - size=self.details.get('size', 'UNKNOWN')) - self.prefix = '{}_ImageFile'.format( - self.details.get('size', 'UNKNOWN')) - self.size = get_size_in_bytes(self.details.get('size', 'UNKNOWN')) - self.report = get_device_report(self.loop_dev) - self.report = self.report.replace( - self.loop_dev[self.loop_dev.rfind('/')+1:], '(Img)') - run_program(['losetup', '--detach', self.loop_dev], check=False) + def set_details(self): + """Setup loopback device, set details via lsblk, then detach device.""" + self.type = 'image' + self.loop_dev = setup_loopback_device(self.path) + self.details = get_device_details(self.loop_dev) + self.details['model'] = 'ImageFile' + self.name = '{name} {size}'.format( + name=self.path[self.path.rfind('/')+1:], + size=self.details.get('size', 'UNKNOWN')) + self.prefix = '{}_ImageFile'.format( + self.details.get('size', 'UNKNOWN')) + self.size = get_size_in_bytes(self.details.get('size', 'UNKNOWN')) + self.report = get_device_report(self.loop_dev) + self.report = self.report.replace( + self.loop_dev[self.loop_dev.rfind('/')+1:], '(Img)') + run_program(['losetup', '--detach', self.loop_dev], check=False) class RecoveryState(): - """Object to track BlockPair objects and overall state.""" - def __init__(self, mode, source, dest): - self.mode = mode.lower() - self.source = source - self.source_path = source.path - self.dest = dest - self.block_pairs = [] - self.current_pass = 0 - self.current_pass_str = '0: Initializing' - self.settings = DDRESCUE_SETTINGS.copy() - self.finished = False - self.panes = {} - self.progress_out = '{}/progress.out'.format(global_vars['LogDir']) - self.rescued = 0 - self.resumed = False - self.started = False - self.total_size = 0 - if mode not in ('clone', 'image'): - raise GenericError('Unsupported mode') - self.get_smart_source() + """Object to track BlockPair objects and overall state.""" + def __init__(self, mode, source, dest): + self.mode = mode.lower() + self.source = source + self.source_path = source.path + self.dest = dest + self.block_pairs = [] + self.current_pass = 0 + self.current_pass_str = '0: Initializing' + self.settings = DDRESCUE_SETTINGS.copy() + self.finished = False + self.panes = {} + self.progress_out = '{}/progress.out'.format(global_vars['LogDir']) + self.rescued = 0 + self.resumed = False + self.started = False + self.total_size = 0 + if mode not in ('clone', 'image'): + raise GenericError('Unsupported mode') + self.get_smart_source() - def add_block_pair(self, source, dest): - """Run safety checks and append new BlockPair to internal list.""" - if self.mode == 'clone': - # Cloning safety checks - if source.is_dir(): - raise GenericError('Invalid source "{}"'.format( - source.path)) - elif not dest.is_dev(): - raise GenericError('Invalid destination "{}"'.format( - dest.path)) - elif source.size > dest.size: - raise GenericError( - 'Destination is too small, refusing to continue.') - else: - # Imaging safety checks - if not source.is_dev(): - raise GenericError('Invalid source "{}"'.format( - source.path)) - elif not dest.is_dir(): - raise GenericError('Invalid destination "{}"'.format( - dest.path)) - elif (source.size * 1.2) > dest.size: - raise GenericError( - 'Not enough free space, refusing to continue.') - elif dest.fstype.lower() not in RECOMMENDED_FSTYPES: - print_error( - 'Destination filesystem "{}" is not recommended.'.format( - dest.fstype.upper())) - print_info('Recommended types are: {}'.format( - ' / '.join(RECOMMENDED_FSTYPES).upper())) - print_standard(' ') - if not ask('Proceed anyways? (Strongly discouraged)'): - raise GenericAbort() - elif not is_writable_dir(dest): - raise GenericError( - 'Destination is not writable, refusing to continue.') - elif not is_writable_filesystem(dest): - raise GenericError( - 'Destination is mounted read-only, refusing to continue.') + def add_block_pair(self, source, dest): + """Run safety checks and append new BlockPair to internal list.""" + if self.mode == 'clone': + # Cloning safety checks + if source.is_dir(): + raise GenericError('Invalid source "{}"'.format( + source.path)) + elif not dest.is_dev(): + raise GenericError('Invalid destination "{}"'.format( + dest.path)) + elif source.size > dest.size: + raise GenericError( + 'Destination is too small, refusing to continue.') + else: + # Imaging safety checks + if not source.is_dev(): + raise GenericError('Invalid source "{}"'.format( + source.path)) + elif not dest.is_dir(): + raise GenericError('Invalid destination "{}"'.format( + dest.path)) + elif (source.size * 1.2) > dest.size: + raise GenericError( + 'Not enough free space, refusing to continue.') + elif dest.fstype.lower() not in RECOMMENDED_FSTYPES: + print_error( + 'Destination filesystem "{}" is not recommended.'.format( + dest.fstype.upper())) + print_info('Recommended types are: {}'.format( + ' / '.join(RECOMMENDED_FSTYPES).upper())) + print_standard(' ') + if not ask('Proceed anyways? (Strongly discouraged)'): + raise GenericAbort() + elif not is_writable_dir(dest): + raise GenericError( + 'Destination is not writable, refusing to continue.') + elif not is_writable_filesystem(dest): + raise GenericError( + 'Destination is mounted read-only, refusing to continue.') - # Safety checks passed - self.block_pairs.append(BlockPair(self.mode, source, dest)) + # Safety checks passed + self.block_pairs.append(BlockPair(self.mode, source, dest)) - def current_pass_done(self): - """Checks if pass is done for all block-pairs, returns bool.""" - done = True - for bp in self.block_pairs: - done &= bp.pass_done[self.current_pass] - return done + def current_pass_done(self): + """Checks if pass is done for all block-pairs, returns bool.""" + done = True + for bp in self.block_pairs: + done &= bp.pass_done[self.current_pass] + return done - def current_pass_min(self): - """Gets minimum pass rescued percentage, returns float.""" - min_percent = 100 - for bp in self.block_pairs: - min_percent = min(min_percent, bp.rescued_percent) - return min_percent + def current_pass_min(self): + """Gets minimum pass rescued percentage, returns float.""" + min_percent = 100 + for bp in self.block_pairs: + min_percent = min(min_percent, bp.rescued_percent) + return min_percent - def get_smart_source(self): - """Get source for SMART dispay.""" - disk_path = self.source.path - if self.source.parent: - disk_path = self.source.parent + def get_smart_source(self): + """Get source for SMART dispay.""" + disk_path = self.source.path + if self.source.parent: + disk_path = self.source.parent - self.smart_source = DiskObj(disk_path) + self.smart_source = DiskObj(disk_path) - def retry_all_passes(self): - """Mark all passes as pending for all block-pairs.""" - self.finished = False - for bp in self.block_pairs: - bp.pass_done = [False, False, False] - bp.status = ['Pending', 'Pending', 'Pending'] - bp.fix_status_strings() - self.set_pass_num() + def retry_all_passes(self): + """Mark all passes as pending for all block-pairs.""" + self.finished = False + for bp in self.block_pairs: + bp.pass_done = [False, False, False] + bp.status = ['Pending', 'Pending', 'Pending'] + bp.fix_status_strings() + self.set_pass_num() - def self_checks(self): - """Run self-checks and update state values.""" - cmd = ['findmnt', '--json', '--target', os.getcwd()] - map_allowed_fstypes = RECOMMENDED_FSTYPES.copy() - map_allowed_fstypes.extend(['cifs', 'ext2', 'vfat']) - map_allowed_fstypes.sort() - json_data = {} + def self_checks(self): + """Run self-checks and update state values.""" + cmd = ['findmnt', '--json', '--target', os.getcwd()] + map_allowed_fstypes = RECOMMENDED_FSTYPES.copy() + map_allowed_fstypes.extend(['cifs', 'ext2', 'vfat']) + map_allowed_fstypes.sort() + json_data = {} - # Avoid saving map to non-persistent filesystem - try: - result = run_program(cmd) - json_data = json.loads(result.stdout.decode()) - except Exception: - print_error('ERROR: Failed to verify map path') - raise GenericAbort() - fstype = json_data.get( - 'filesystems', [{}])[0].get( - 'fstype', 'unknown') - if fstype not in map_allowed_fstypes: - print_error( - "Map isn't being saved to a recommended filesystem ({})".format( - fstype.upper())) - print_info('Recommended types are: {}'.format( - ' / '.join(map_allowed_fstypes).upper())) - print_standard(' ') - if not ask('Proceed anyways? (Strongly discouraged)'): - raise GenericAbort() + # Avoid saving map to non-persistent filesystem + try: + result = run_program(cmd) + json_data = json.loads(result.stdout.decode()) + except Exception: + print_error('ERROR: Failed to verify map path') + raise GenericAbort() + fstype = json_data.get( + 'filesystems', [{}])[0].get( + 'fstype', 'unknown') + if fstype not in map_allowed_fstypes: + print_error( + "Map isn't being saved to a recommended filesystem ({})".format( + fstype.upper())) + print_info('Recommended types are: {}'.format( + ' / '.join(map_allowed_fstypes).upper())) + print_standard(' ') + if not ask('Proceed anyways? (Strongly discouraged)'): + raise GenericAbort() - # Run BlockPair self checks and get total size - self.total_size = 0 - for bp in self.block_pairs: - bp.self_check() - self.resumed |= bp.resumed - self.total_size += bp.size + # Run BlockPair self checks and get total size + self.total_size = 0 + for bp in self.block_pairs: + bp.self_check() + self.resumed |= bp.resumed + self.total_size += bp.size - def set_pass_num(self): - """Set current pass based on all block-pair's progress.""" - self.current_pass = 0 - for pass_num in (2, 1, 0): - # Iterate backwards through passes - pass_done = True - for bp in self.block_pairs: - pass_done &= bp.pass_done[pass_num] - if pass_done: - # All block-pairs reported being done - # Set to next pass, unless we're on the last pass (2) - self.current_pass = min(2, pass_num + 1) - if pass_num == 2: - # Also mark overall recovery as finished if on last pass - self.finished = True - break - if self.finished: - self.current_pass_str = '- "Done"' - elif self.current_pass == 0: - self.current_pass_str = '1 "Initial Read"' - elif self.current_pass == 1: - self.current_pass_str = '2 "Trimming bad areas"' - elif self.current_pass == 2: - self.current_pass_str = '3 "Scraping bad areas"' + def set_pass_num(self): + """Set current pass based on all block-pair's progress.""" + self.current_pass = 0 + for pass_num in (2, 1, 0): + # Iterate backwards through passes + pass_done = True + for bp in self.block_pairs: + pass_done &= bp.pass_done[pass_num] + if pass_done: + # All block-pairs reported being done + # Set to next pass, unless we're on the last pass (2) + self.current_pass = min(2, pass_num + 1) + if pass_num == 2: + # Also mark overall recovery as finished if on last pass + self.finished = True + break + if self.finished: + self.current_pass_str = '- "Done"' + elif self.current_pass == 0: + self.current_pass_str = '1 "Initial Read"' + elif self.current_pass == 1: + self.current_pass_str = '2 "Trimming bad areas"' + elif self.current_pass == 2: + self.current_pass_str = '3 "Scraping bad areas"' - def update_progress(self): - """Update overall progress using block_pairs.""" - self.rescued = 0 - for bp in self.block_pairs: - self.rescued += bp.rescued - self.rescued_percent = (self.rescued / self.total_size) * 100 - self.status_percent = get_formatted_status( - label='Recovered:', data=self.rescued_percent) - self.status_amount = get_formatted_status( - label='', data=human_readable_size(self.rescued, decimals=2)) + def update_progress(self): + """Update overall progress using block_pairs.""" + self.rescued = 0 + for bp in self.block_pairs: + self.rescued += bp.rescued + self.rescued_percent = (self.rescued / self.total_size) * 100 + self.status_percent = get_formatted_status( + label='Recovered:', data=self.rescued_percent) + self.status_amount = get_formatted_status( + label='', data=human_readable_size(self.rescued, decimals=2)) # Functions def build_outer_panes(state): - """Build top and side panes.""" - state.panes['Source'] = tmux_split_window( - behind=True, vertical=True, lines=2, - text='{BLUE}Source{CLEAR}'.format(**COLORS)) - state.panes['Started'] = tmux_split_window( - lines=SIDE_PANE_WIDTH, target_pane=state.panes['Source'], - text='{BLUE}Started{CLEAR}\n{s}'.format( - s=time.strftime("%Y-%m-%d %H:%M %Z"), - **COLORS)) - state.panes['Destination'] = tmux_split_window( - percent=50, target_pane=state.panes['Source'], - text='{BLUE}Destination{CLEAR}'.format(**COLORS)) + """Build top and side panes.""" + state.panes['Source'] = tmux_split_window( + behind=True, vertical=True, lines=2, + text='{BLUE}Source{CLEAR}'.format(**COLORS)) + state.panes['Started'] = tmux_split_window( + lines=SIDE_PANE_WIDTH, target_pane=state.panes['Source'], + text='{BLUE}Started{CLEAR}\n{s}'.format( + s=time.strftime("%Y-%m-%d %H:%M %Z"), + **COLORS)) + state.panes['Destination'] = tmux_split_window( + percent=50, target_pane=state.panes['Source'], + text='{BLUE}Destination{CLEAR}'.format(**COLORS)) - # Side pane - update_sidepane(state) - state.panes['Progress'] = tmux_split_window( - lines=SIDE_PANE_WIDTH, watch=state.progress_out) + # Side pane + update_sidepane(state) + state.panes['Progress'] = tmux_split_window( + lines=SIDE_PANE_WIDTH, watch=state.progress_out) def create_path_obj(path): - """Create Dev, Dir, or Image obj based on path given.""" - obj = None - if pathlib.Path(path).is_block_device(): - obj = DevObj(path) - elif pathlib.Path(path).is_dir(): - obj = DirObj(path) - elif pathlib.Path(path).is_file(): - obj = ImageObj(path) - else: - raise GenericError('Invalid path "{}"'.format(path)) - return obj + """Create Dev, Dir, or Image obj based on path given.""" + obj = None + if pathlib.Path(path).is_block_device(): + obj = DevObj(path) + elif pathlib.Path(path).is_dir(): + obj = DirObj(path) + elif pathlib.Path(path).is_file(): + obj = ImageObj(path) + else: + raise GenericError('Invalid path "{}"'.format(path)) + return obj def double_confirm_clone(): - """Display warning and get 2nd confirmation from user, returns bool.""" - print_standard('\nSAFETY CHECK') - print_warning('All data will be DELETED from the ' - 'destination device and partition(s) listed above.') - print_warning('This is irreversible and will lead ' - 'to {CLEAR}{RED}DATA LOSS.'.format(**COLORS)) - return ask('Asking again to confirm, is this correct?') + """Display warning and get 2nd confirmation, returns bool.""" + print_standard('\nSAFETY CHECK') + print_warning('All data will be DELETED from the ' + 'destination device and partition(s) listed above.') + print_warning('This is irreversible and will lead ' + 'to {CLEAR}{RED}DATA LOSS.'.format(**COLORS)) + return ask('Asking again to confirm, is this correct?') def fix_tmux_panes(state, forced=False): - """Fix pane sizes if the winodw has been resized.""" - needs_fixed = False + """Fix pane sizes if the winodw has been resized.""" + needs_fixed = False - # Check layout - for k, v in TMUX_LAYOUT.items(): - if not v.get('Check'): - # Not concerned with the size of this pane - continue - # Get target - target = None - if k != 'Current': - if k not in state.panes: - # Skip missing panes - continue - else: - target = state.panes[k] + # Check layout + for k, v in TMUX_LAYOUT.items(): + if not v.get('Check'): + # Not concerned with the size of this pane + continue + # Get target + target = None + if k != 'Current': + if k not in state.panes: + # Skip missing panes + continue + else: + target = state.panes[k] - # Check pane size - x, y = tmux_get_pane_size(pane_id=target) - if v.get('x', False) and v['x'] != x: - needs_fixed = True - if v.get('y', False) and v['y'] != y: - needs_fixed = True + # Check pane size + x, y = tmux_get_pane_size(pane_id=target) + if v.get('x', False) and v['x'] != x: + needs_fixed = True + if v.get('y', False) and v['y'] != y: + needs_fixed = True - # Bail? - if not needs_fixed and not forced: - return + # Bail? + if not needs_fixed and not forced: + return - # Remove Destination pane (temporarily) - tmux_kill_pane(state.panes['Destination']) + # Remove Destination pane (temporarily) + tmux_kill_pane(state.panes['Destination']) - # Update layout - for k, v in TMUX_LAYOUT.items(): - # Get target - target = None - if k != 'Current': - if k not in state.panes: - # Skip missing panes - continue - else: - target = state.panes[k] + # Update layout + for k, v in TMUX_LAYOUT.items(): + # Get target + target = None + if k != 'Current': + if k not in state.panes: + # Skip missing panes + continue + else: + target = state.panes[k] - # Resize pane - tmux_resize_pane(pane_id=target, **v) + # Resize pane + tmux_resize_pane(pane_id=target, **v) - # Calc Source/Destination pane sizes - width, height = tmux_get_pane_size() - width = int(width / 2) - 1 + # Calc Source/Destination pane sizes + width, height = tmux_get_pane_size() + width = int(width / 2) - 1 - # Update Source string - source_str = state.source.name - if len(source_str) > width: - source_str = '{}...'.format(source_str[:width-3]) + # Update Source string + source_str = state.source.name + if len(source_str) > width: + source_str = '{}...'.format(source_str[:width-3]) - # Update Destination string - dest_str = state.dest.name - if len(dest_str) > width: - if state.mode == 'clone': - dest_str = '{}...'.format(dest_str[:width-3]) - else: - dest_str = '...{}'.format(dest_str[-width+3:]) + # Update Destination string + dest_str = state.dest.name + if len(dest_str) > width: + if state.mode == 'clone': + dest_str = '{}...'.format(dest_str[:width-3]) + else: + dest_str = '...{}'.format(dest_str[-width+3:]) - # Rebuild Source/Destination panes - tmux_update_pane( - pane_id=state.panes['Source'], - text='{BLUE}Source{CLEAR}\n{s}'.format( - s=source_str, **COLORS)) - state.panes['Destination'] = tmux_split_window( - percent=50, target_pane=state.panes['Source'], - text='{BLUE}Destination{CLEAR}\n{s}'.format( - s=dest_str, **COLORS)) + # Rebuild Source/Destination panes + tmux_update_pane( + pane_id=state.panes['Source'], + text='{BLUE}Source{CLEAR}\n{s}'.format( + s=source_str, **COLORS)) + state.panes['Destination'] = tmux_split_window( + percent=50, target_pane=state.panes['Source'], + text='{BLUE}Destination{CLEAR}\n{s}'.format( + s=dest_str, **COLORS)) - if 'SMART' in state.panes: - # Calc SMART/ddrescue/Journal panes sizes - ratio = [12, 22, 4] - width, height = tmux_get_pane_size(pane_id=state.panes['Progress']) - height -= 2 - total = sum(ratio) - p_ratio = [int((x/total) * height) for x in ratio] - p_ratio[1] = height - p_ratio[0] - p_ratio[2] + if 'SMART' in state.panes: + # Calc SMART/ddrescue/Journal panes sizes + ratio = [12, 22, 4] + width, height = tmux_get_pane_size(pane_id=state.panes['Progress']) + height -= 2 + total = sum(ratio) + p_ratio = [int((x/total) * height) for x in ratio] + p_ratio[1] = height - p_ratio[0] - p_ratio[2] - # Resize SMART/Journal panes - tmux_resize_pane(state.panes['SMART'], y=ratio[0]) - tmux_resize_pane(y=ratio[1]) - tmux_resize_pane(state.panes['Journal'], y=ratio[2]) + # Resize SMART/Journal panes + tmux_resize_pane(state.panes['SMART'], y=ratio[0]) + tmux_resize_pane(y=ratio[1]) + tmux_resize_pane(state.panes['Journal'], y=ratio[2]) def get_device_details(dev_path): - """Get device details via lsblk, returns JSON dict.""" - try: - cmd = ( - 'lsblk', - '--json', - '--output-all', - '--paths', - dev_path) - result = run_program(cmd) - except CalledProcessError: - # Return empty dict and let calling section deal with the issue - return {} + """Get device details via lsblk, returns JSON dict.""" + try: + cmd = ( + 'lsblk', + '--json', + '--output-all', + '--paths', + dev_path) + result = run_program(cmd) + except CalledProcessError: + # Return empty dict and let calling section deal with the issue + return {} - json_data = json.loads(result.stdout.decode()) - # Just return the first device (there should only be one) - return json_data['blockdevices'][0] + json_data = json.loads(result.stdout.decode()) + # Just return the first device (there should only be one) + return json_data['blockdevices'][0] def get_device_report(dev_path): - """Build colored device report using lsblk, returns str.""" - result = run_program([ - 'lsblk', '--nodeps', - '--output', 'NAME,TRAN,TYPE,SIZE,VENDOR,MODEL,SERIAL', - dev_path]) - lines = result.stdout.decode().strip().splitlines() - lines.append('') + """Build colored device report using lsblk, returns str.""" + result = run_program([ + 'lsblk', '--nodeps', + '--output', 'NAME,TRAN,TYPE,SIZE,VENDOR,MODEL,SERIAL', + dev_path]) + lines = result.stdout.decode().strip().splitlines() + lines.append('') - # FS details (if any) - result = run_program([ - 'lsblk', - '--output', 'NAME,SIZE,FSTYPE,LABEL,MOUNTPOINT', - dev_path]) - lines.extend(result.stdout.decode().strip().splitlines()) + # FS details (if any) + result = run_program([ + 'lsblk', + '--output', 'NAME,SIZE,FSTYPE,LABEL,MOUNTPOINT', + dev_path]) + lines.extend(result.stdout.decode().strip().splitlines()) - # Color label lines - output = [] - for line in lines: - if line[0:4] == 'NAME': - output.append('{BLUE}{line}{CLEAR}'.format(line=line, **COLORS)) - else: - output.append(line) + # Color label lines + output = [] + for line in lines: + if line[0:4] == 'NAME': + output.append('{BLUE}{line}{CLEAR}'.format(line=line, **COLORS)) + else: + output.append(line) - # Done - return '\n'.join(output) + # Done + return '\n'.join(output) def get_dir_details(dir_path): - """Get dir details via findmnt, returns JSON dict.""" - try: - result = run_program([ - 'findmnt', '-J', - '-o', 'SOURCE,TARGET,FSTYPE,OPTIONS,SIZE,AVAIL,USED', - '-T', dir_path]) - json_data = json.loads(result.stdout.decode()) - except Exception: - raise GenericError( - 'Failed to get directory details for "{}".'.format(self.path)) - else: - return json_data['filesystems'][0] + """Get dir details via findmnt, returns JSON dict.""" + try: + result = run_program([ + 'findmnt', '-J', + '-o', 'SOURCE,TARGET,FSTYPE,OPTIONS,SIZE,AVAIL,USED', + '-T', dir_path]) + json_data = json.loads(result.stdout.decode()) + except Exception: + raise GenericError( + 'Failed to get directory details for "{}".'.format(self.path)) + else: + return json_data['filesystems'][0] def get_dir_report(dir_path): - """Build colored dir report using findmnt, returns str.""" - dir_path = dir_path - output = [] - width = len(dir_path)+1 - result = run_program([ - 'findmnt', - '--output', 'SIZE,AVAIL,USED,FSTYPE,OPTIONS', - '--target', dir_path]) - for line in result.stdout.decode().splitlines(): - if 'FSTYPE' in line: - output.append('{BLUE}{label:<{width}}{line}{CLEAR}'.format( - label='PATH', - width=width, - line=line.replace('\n',''), - **COLORS)) - else: - output.append('{path:<{width}}{line}'.format( - path=dir_path, - width=width, - line=line.replace('\n',''))) + """Build colored dir report using findmnt, returns str.""" + dir_path = dir_path + output = [] + width = len(dir_path)+1 + result = run_program([ + 'findmnt', + '--output', 'SIZE,AVAIL,USED,FSTYPE,OPTIONS', + '--target', dir_path]) + for line in result.stdout.decode().splitlines(): + if 'FSTYPE' in line: + output.append('{BLUE}{label:<{width}}{line}{CLEAR}'.format( + label='PATH', + width=width, + line=line.replace('\n',''), + **COLORS)) + else: + output.append('{path:<{width}}{line}'.format( + path=dir_path, + width=width, + line=line.replace('\n',''))) - # Done - return '\n'.join(output) + # Done + return '\n'.join(output) def get_size_in_bytes(s): - """Convert size string from lsblk string to bytes, returns int.""" - s = re.sub(r'(\d+\.?\d*)\s*([KMGTB])B?', r'\1 \2B', s, re.IGNORECASE) - return convert_to_bytes(s) + """Convert size string from lsblk string to bytes, returns int.""" + s = re.sub(r'(\d+\.?\d*)\s*([KMGTB])B?', r'\1 \2B', s, re.IGNORECASE) + return convert_to_bytes(s) def get_formatted_status(label, data): - """Build status string using provided info, returns str.""" - data_width = SIDE_PANE_WIDTH - len(label) - try: - data_str = '{data:>{data_width}.2f} %'.format( - data=data, - data_width=data_width-2) - except ValueError: - # Assuming non-numeric data - data_str = '{data:>{data_width}}'.format( - data=data, - data_width=data_width) - status = '{label}{s_color}{data_str}{CLEAR}'.format( - label=label, - s_color=get_status_color(data), - data_str=data_str, - **COLORS) - return status + """Build status string using provided info, returns str.""" + data_width = SIDE_PANE_WIDTH - len(label) + try: + data_str = '{data:>{data_width}.2f} %'.format( + data=data, + data_width=data_width-2) + except ValueError: + # Assuming non-numeric data + data_str = '{data:>{data_width}}'.format( + data=data, + data_width=data_width) + status = '{label}{s_color}{data_str}{CLEAR}'.format( + label=label, + s_color=get_status_color(data), + data_str=data_str, + **COLORS) + return status def get_status_color(s, t_success=99, t_warn=90): - """Get color based on status, returns str.""" - color = COLORS['CLEAR'] - p_recovered = -1 - try: - p_recovered = float(s) - except ValueError: - # Status is either in lists below or will default to red - pass + """Get color based on status, returns str.""" + color = COLORS['CLEAR'] + p_recovered = -1 + try: + p_recovered = float(s) + except ValueError: + # Status is either in lists below or will default to red + pass - if s in ('Pending',) or str(s)[-2:] in (' b', 'Kb', 'Mb', 'Gb', 'Tb'): - color = COLORS['CLEAR'] - elif s in ('Skipped', 'Unknown'): - color = COLORS['YELLOW'] - elif p_recovered >= t_success: - color = COLORS['GREEN'] - elif p_recovered >= t_warn: - color = COLORS['YELLOW'] - else: - color = COLORS['RED'] - return color + if s in ('Pending',) or str(s)[-2:] in (' b', 'Kb', 'Mb', 'Gb', 'Tb'): + color = COLORS['CLEAR'] + elif s in ('Skipped', 'Unknown'): + color = COLORS['YELLOW'] + elif p_recovered >= t_success: + color = COLORS['GREEN'] + elif p_recovered >= t_warn: + color = COLORS['YELLOW'] + else: + color = COLORS['RED'] + return color def is_writable_dir(dir_obj): - """Check if we have read-write-execute permissions, returns bool.""" - is_ok = True - path_st_mode = os.stat(dir_obj.path).st_mode - is_ok == is_ok and path_st_mode & stat.S_IRUSR - is_ok == is_ok and path_st_mode & stat.S_IWUSR - is_ok == is_ok and path_st_mode & stat.S_IXUSR - return is_ok + """Check if we have read-write-execute permissions, returns bool.""" + is_ok = True + path_st_mode = os.stat(dir_obj.path).st_mode + is_ok == is_ok and path_st_mode & stat.S_IRUSR + is_ok == is_ok and path_st_mode & stat.S_IWUSR + is_ok == is_ok and path_st_mode & stat.S_IXUSR + return is_ok def is_writable_filesystem(dir_obj): - """Check if filesystem is mounted read-write, returns bool.""" - return 'rw' in dir_obj.details.get('options', '') + """Check if filesystem is mounted read-write, returns bool.""" + return 'rw' in dir_obj.details.get('options', '') def menu_ddrescue(source_path, dest_path, run_mode): - """ddrescue menu.""" - source = None - dest = None - if source_path: - source = create_path_obj(source_path) - else: - source = select_device('source') - source.self_check() - if dest_path: - dest = create_path_obj(dest_path) - else: - if run_mode == 'clone': - dest = select_device('destination', skip_device=source) - else: - dest = select_path(skip_device=source) - dest.self_check() - - # Build BlockPairs - state = RecoveryState(run_mode, source, dest) + """ddrescue menu.""" + source = None + dest = None + if source_path: + source = create_path_obj(source_path) + else: + source = select_device('source') + source.self_check() + if dest_path: + dest = create_path_obj(dest_path) + else: if run_mode == 'clone': - state.add_block_pair(source, dest) + dest = select_device('destination', skip_device=source) else: - for part in select_parts(source): - state.add_block_pair(part, dest) + dest = select_path(skip_device=source) + dest.self_check() - # Update state - state.self_checks() - state.set_pass_num() - state.update_progress() + # Build BlockPairs + state = RecoveryState(run_mode, source, dest) + if run_mode == 'clone': + state.add_block_pair(source, dest) + else: + for part in select_parts(source): + state.add_block_pair(part, dest) - # Confirmations - clear_screen() - show_selection_details(state) - prompt = 'Start {}?'.format(state.mode.replace('e', 'ing')) - if state.resumed: - print_info('Map data detected and loaded.') - prompt = prompt.replace('Start', 'Resume') - if not ask(prompt): - raise GenericAbort() - if state.mode == 'clone' and not double_confirm_clone(): - raise GenericAbort() + # Update state + state.self_checks() + state.set_pass_num() + state.update_progress() - # Main menu - clear_screen() - build_outer_panes(state) - fix_tmux_panes(state, forced=True) - menu_main(state) + # Confirmations + clear_screen() + show_selection_details(state) + prompt = 'Start {}?'.format(state.mode.replace('e', 'ing')) + if state.resumed: + print_info('Map data detected and loaded.') + prompt = prompt.replace('Start', 'Resume') + if not ask(prompt): + raise GenericAbort() + if state.mode == 'clone' and not double_confirm_clone(): + raise GenericAbort() - # Done - run_program(['tmux', 'kill-window']) - exit_script() + # Main menu + clear_screen() + build_outer_panes(state) + fix_tmux_panes(state, forced=True) + menu_main(state) + + # Done + run_program(['tmux', 'kill-window']) + exit_script() def menu_main(state): - """Main menu is used to set ddrescue settings.""" - title = '{GREEN}ddrescue TUI: Main Menu{CLEAR}\n\n'.format(**COLORS) - title += '{BLUE}Current pass: {CLEAR}'.format(**COLORS) + """Main menu is used to set ddrescue settings.""" + title = '{GREEN}ddrescue TUI: Main Menu{CLEAR}\n\n'.format(**COLORS) + title += '{BLUE}Current pass: {CLEAR}'.format(**COLORS) - # Build menu - main_options = [ - {'Base Name': 'Auto continue (if recovery % over threshold)', - 'Enabled': True}, - {'Base Name': 'Retry (mark non-rescued sectors "non-tried")', - 'Enabled': False}, - {'Base Name': 'Reverse direction', 'Enabled': False}, - ] - actions = [ - {'Name': 'Start', 'Letter': 'S'}, - {'Name': 'Change settings {YELLOW}(experts only){CLEAR}'.format( - **COLORS), - 'Letter': 'C'}, - {'Name': 'Quit', 'Letter': 'Q', 'CRLF': True}, - ] + # Build menu + main_options = [ + {'Base Name': 'Auto continue (if recovery % over threshold)', + 'Enabled': True}, + {'Base Name': 'Retry (mark non-rescued sectors "non-tried")', + 'Enabled': False}, + {'Base Name': 'Reverse direction', 'Enabled': False}, + ] + actions = [ + {'Name': 'Start', 'Letter': 'S'}, + {'Name': 'Change settings {YELLOW}(experts only){CLEAR}'.format( + **COLORS), + 'Letter': 'C'}, + {'Name': 'Quit', 'Letter': 'Q', 'CRLF': True}, + ] - # Show menu - while True: - # Update entries - for opt in main_options: - opt['Name'] = '{} {}'.format( - '[✓]' if opt['Enabled'] else '[ ]', - opt['Base Name']) + # Show menu + while True: + # Update entries + for opt in main_options: + opt['Name'] = '{} {}'.format( + '[✓]' if opt['Enabled'] else '[ ]', + opt['Base Name']) - selection = menu_select( - title=title+state.current_pass_str, - main_entries=main_options, - action_entries=actions) + selection = menu_select( + title=title+state.current_pass_str, + main_entries=main_options, + action_entries=actions) - if selection.isnumeric(): - # Toggle selection - index = int(selection) - 1 - main_options[index]['Enabled'] = not main_options[index]['Enabled'] - elif selection == 'S': - # Set settings for pass - pass_settings = [] - for k, v in state.settings.items(): - if not v['Enabled']: - continue - if 'Value' in v: - pass_settings.append('{}={}'.format(k, v['Value'])) - else: - pass_settings.append(k) - for opt in main_options: - if 'Auto' in opt['Base Name']: - auto_run = opt['Enabled'] - if 'Retry' in opt['Base Name'] and opt['Enabled']: - pass_settings.extend(['--retrim', '--try-again']) - state.retry_all_passes() - if 'Reverse' in opt['Base Name'] and opt['Enabled']: - pass_settings.append('--reverse') - # Disable for next pass - if 'Auto' not in opt['Base Name']: - opt['Enabled'] = False + if selection.isnumeric(): + # Toggle selection + index = int(selection) - 1 + main_options[index]['Enabled'] = not main_options[index]['Enabled'] + elif selection == 'S': + # Set settings for pass + pass_settings = [] + for k, v in state.settings.items(): + if not v['Enabled']: + continue + if 'Value' in v: + pass_settings.append('{}={}'.format(k, v['Value'])) + else: + pass_settings.append(k) + for opt in main_options: + if 'Auto' in opt['Base Name']: + auto_run = opt['Enabled'] + if 'Retry' in opt['Base Name'] and opt['Enabled']: + pass_settings.extend(['--retrim', '--try-again']) + state.retry_all_passes() + if 'Reverse' in opt['Base Name'] and opt['Enabled']: + pass_settings.append('--reverse') + # Disable for next pass + if 'Auto' not in opt['Base Name']: + opt['Enabled'] = False - # Run ddrescue - state.started = False - while auto_run or not state.started: - state.started = True - run_ddrescue(state, pass_settings) - if state.current_pass_done(): - if (state.current_pass == 0 and - state.current_pass_min() < AUTO_PASS_1_THRESHOLD): - auto_run = False - elif (state.current_pass == 1 and - state.current_pass_min() < AUTO_PASS_2_THRESHOLD): - auto_run = False - else: - auto_run = False - state.set_pass_num() - if state.finished: - break + # Run ddrescue + state.started = False + while auto_run or not state.started: + state.started = True + run_ddrescue(state, pass_settings) + if state.current_pass_done(): + if (state.current_pass == 0 and + state.current_pass_min() < AUTO_PASS_1_THRESHOLD): + auto_run = False + elif (state.current_pass == 1 and + state.current_pass_min() < AUTO_PASS_2_THRESHOLD): + auto_run = False + else: + auto_run = False + state.set_pass_num() + if state.finished: + break - elif selection == 'C': - menu_settings(state) - elif selection == 'Q': - if state.rescued_percent < 100: - print_warning('Recovery is less than 100%') - if ask('Are you sure you want to quit?'): - break - else: - break + elif selection == 'C': + menu_settings(state) + elif selection == 'Q': + if state.rescued_percent < 100: + print_warning('Recovery is less than 100%') + if ask('Are you sure you want to quit?'): + break + else: + break def menu_settings(state): - """Change advanced ddrescue settings.""" - title = '{GREEN}ddrescue TUI: Expert Settings{CLEAR}\n\n'.format(**COLORS) - title += '{YELLOW}These settings can cause {CLEAR}'.format(**COLORS) - title += '{RED}MAJOR DAMAGE{CLEAR}{YELLOW} to drives{CLEAR}\n'.format( - **COLORS) - title += 'Please read the manual before making any changes' + """Change advanced ddrescue settings.""" + title = '{GREEN}ddrescue TUI: Expert Settings{CLEAR}\n\n'.format(**COLORS) + title += '{YELLOW}These settings can cause {CLEAR}'.format(**COLORS) + title += '{RED}MAJOR DAMAGE{CLEAR}{YELLOW} to drives{CLEAR}\n'.format( + **COLORS) + title += 'Please read the manual before making any changes' - # Build menu - settings = [] - for k, v in sorted(state.settings.items()): - if not v.get('Hidden', False): - settings.append({'Base Name': k, 'Flag': k}) - actions = [{'Name': 'Main Menu', 'Letter': 'M'}] + # Build menu + settings = [] + for k, v in sorted(state.settings.items()): + if not v.get('Hidden', False): + settings.append({'Base Name': k, 'Flag': k}) + actions = [{'Name': 'Main Menu', 'Letter': 'M'}] - # Show menu - while True: - for s in settings: - s['Name'] = '{}{}{}'.format( - s['Base Name'], - ' = ' if 'Value' in state.settings[s['Flag']] else '', - state.settings[s['Flag']].get('Value', '')) - if not state.settings[s['Flag']]['Enabled']: - s['Name'] = '{YELLOW}{name} (Disabled){CLEAR}'.format( - name=s['Name'], - **COLORS) - selection = menu_select( - title=title, - main_entries=settings, - action_entries=actions) - if selection.isnumeric(): - index = int(selection) - 1 - flag = settings[index]['Flag'] - enabled = state.settings[flag]['Enabled'] - if 'Value' in state.settings[flag]: - answer = choice( - choices=['T', 'C'], - prompt='Toggle or change value for "{}"'.format(flag)) - if answer == 'T': - # Toggle - state.settings[flag]['Enabled'] = not enabled - else: - # Update value - state.settings[flag]['Value'] = get_simple_string( - prompt='Enter new value') - else: - state.settings[flag]['Enabled'] = not enabled - elif selection == 'M': - break + # Show menu + while True: + for s in settings: + s['Name'] = '{}{}{}'.format( + s['Base Name'], + ' = ' if 'Value' in state.settings[s['Flag']] else '', + state.settings[s['Flag']].get('Value', '')) + if not state.settings[s['Flag']]['Enabled']: + s['Name'] = '{YELLOW}{name} (Disabled){CLEAR}'.format( + name=s['Name'], + **COLORS) + selection = menu_select( + title=title, + main_entries=settings, + action_entries=actions) + if selection.isnumeric(): + index = int(selection) - 1 + flag = settings[index]['Flag'] + enabled = state.settings[flag]['Enabled'] + if 'Value' in state.settings[flag]: + answer = choice( + choices=['T', 'C'], + prompt='Toggle or change value for "{}"'.format(flag)) + if answer == 'T': + # Toggle + state.settings[flag]['Enabled'] = not enabled + else: + # Update value + state.settings[flag]['Value'] = get_simple_string( + prompt='Enter new value') + else: + state.settings[flag]['Enabled'] = not enabled + elif selection == 'M': + break def read_map_file(map_path): - """Read map file with ddrescuelog and return data as dict.""" - map_data = {'full recovery': False} - try: - result = run_program(['ddrescuelog', '-t', map_path]) - except CalledProcessError: - # (Grossly) assuming map_data hasn't been saved yet, return empty dict - return map_data - - # Parse output - for line in result.stdout.decode().splitlines(): - m = re.match( - r'^\s*(?P\S+):.*\(\s*(?P\d+\.?\d*)%.*', line.strip()) - if m: - try: - map_data[m.group('key')] = float(m.group('value')) - except ValueError: - raise GenericError('Failed to read map data') - m = re.match(r'.*current status:\s+(?P.*)', line.strip()) - if m: - map_data['pass completed'] = bool(m.group('status') == 'finished') - - # Check if 100% done - try: - run_program(['ddrescuelog', '-D', map_path]) - except CalledProcessError: - map_data['full recovery'] = False - else: - map_data['full recovery'] = True - + """Read map file with ddrescuelog and return data as dict.""" + map_data = {'full recovery': False} + try: + result = run_program(['ddrescuelog', '-t', map_path]) + except CalledProcessError: + # (Grossly) assuming map_data hasn't been saved yet, return empty dict return map_data + # Parse output + for line in result.stdout.decode().splitlines(): + m = re.match( + r'^\s*(?P\S+):.*\(\s*(?P\d+\.?\d*)%.*', line.strip()) + if m: + try: + map_data[m.group('key')] = float(m.group('value')) + except ValueError: + raise GenericError('Failed to read map data') + m = re.match(r'.*current status:\s+(?P.*)', line.strip()) + if m: + map_data['pass completed'] = bool(m.group('status') == 'finished') + + # Check if 100% done + try: + run_program(['ddrescuelog', '-D', map_path]) + except CalledProcessError: + map_data['full recovery'] = False + else: + map_data['full recovery'] = True + + return map_data + def run_ddrescue(state, pass_settings): - """Run ddrescue pass.""" - return_code = -1 - aborted = False + """Run ddrescue pass.""" + return_code = -1 + aborted = False - if state.finished: - clear_screen() - print_warning('Recovery already completed?') - pause('Press Enter to return to main menu...') - return + if state.finished: + clear_screen() + print_warning('Recovery already completed?') + pause('Press Enter to return to main menu...') + return - # Create SMART monitor pane - state.smart_out = '{}/smart_{}.out'.format( - global_vars['TmpDir'], state.smart_source.name) - with open(state.smart_out, 'w') as f: - f.write('Initializing...') - state.panes['SMART'] = tmux_split_window( - behind=True, lines=12, vertical=True, watch=state.smart_out) + # Create SMART monitor pane + state.smart_out = '{}/smart_{}.out'.format( + global_vars['TmpDir'], state.smart_source.name) + with open(state.smart_out, 'w') as f: + f.write('Initializing...') + state.panes['SMART'] = tmux_split_window( + behind=True, lines=12, vertical=True, watch=state.smart_out) - # Show systemd journal output - state.panes['Journal'] = tmux_split_window( - lines=4, vertical=True, - command=['sudo', 'journalctl', '-f']) + # Show systemd journal output + state.panes['Journal'] = tmux_split_window( + lines=4, vertical=True, + command=['sudo', 'journalctl', '-f']) - # Fix layout - fix_tmux_panes(state, forced=True) + # Fix layout + fix_tmux_panes(state, forced=True) - # Run pass for each block-pair - for bp in state.block_pairs: - if bp.pass_done[state.current_pass]: - # Skip to next block-pair - continue - update_sidepane(state) + # Run pass for each block-pair + for bp in state.block_pairs: + if bp.pass_done[state.current_pass]: + # Skip to next block-pair + continue + update_sidepane(state) - # Set ddrescue cmd - cmd = [ - 'ddrescue', *pass_settings, - bp.source_path, bp.dest_path, bp.map_path] - if state.mode == 'clone': - cmd.append('--force') - if state.current_pass == 0: - cmd.extend(['--no-trim', '--no-scrape']) - elif state.current_pass == 1: - # Allow trimming - cmd.append('--no-scrape') - elif state.current_pass == 2: - # Allow trimming and scraping - pass + # Set ddrescue cmd + cmd = [ + 'ddrescue', *pass_settings, + bp.source_path, bp.dest_path, bp.map_path] + if state.mode == 'clone': + cmd.append('--force') + if state.current_pass == 0: + cmd.extend(['--no-trim', '--no-scrape']) + elif state.current_pass == 1: + # Allow trimming + cmd.append('--no-scrape') + elif state.current_pass == 2: + # Allow trimming and scraping + pass - # Start ddrescue - try: - clear_screen() - print_info('Current dev: {}'.format(bp.source_path)) - ddrescue_proc = popen_program(cmd) - i = 0 - while True: - # Update SMART display (every 30 seconds) - if i % 30 == 0: - state.smart_source.get_smart_details() - with open(state.smart_out, 'w') as f: - report = state.smart_source.generate_attribute_report( - timestamp=True) - for line in report: - f.write('{}\n'.format(line)) - i += 1 + # Start ddrescue + try: + clear_screen() + print_info('Current dev: {}'.format(bp.source_path)) + ddrescue_proc = popen_program(cmd) + i = 0 + while True: + # Update SMART display (every 30 seconds) + if i % 30 == 0: + state.smart_source.get_smart_details() + with open(state.smart_out, 'w') as f: + report = state.smart_source.generate_attribute_report( + timestamp=True) + for line in report: + f.write('{}\n'.format(line)) + i += 1 - # Update progress - bp.update_progress(state.current_pass) - update_sidepane(state) - - # Fix panes - fix_tmux_panes(state) - - # Check if ddrescue has finished - try: - ddrescue_proc.wait(timeout=1) - sleep(2) - bp.update_progress(state.current_pass) - update_sidepane(state) - break - except subprocess.TimeoutExpired: - # Catch to update smart/bp/sidepane - pass - - except KeyboardInterrupt: - # Catch user abort - aborted = True - ddrescue_proc.wait(timeout=10) - - # Update progress/sidepane again + # Update progress bp.update_progress(state.current_pass) update_sidepane(state) - # Was ddrescue aborted? - return_code = ddrescue_proc.poll() - if aborted: - print_standard(' ') - print_standard(' ') - print_error('DDRESCUE PROCESS HALTED') - print_standard(' ') - print_warning('Aborted') - break - elif return_code: - # i.e. True when non-zero - print_standard(' ') - print_standard(' ') - print_error('DDRESCUE PROCESS HALTED') - print_standard(' ') - print_error('Error(s) encountered, see message above.') - break - else: - # Mark pass finished - bp.finish_pass(state.current_pass) - update_sidepane(state) + # Fix panes + fix_tmux_panes(state) - # Done - if str(return_code) != '0': - # Pause on errors - pause('Press Enter to return to main menu... ') + # Check if ddrescue has finished + try: + ddrescue_proc.wait(timeout=1) + sleep(2) + bp.update_progress(state.current_pass) + update_sidepane(state) + break + except subprocess.TimeoutExpired: + # Catch to update smart/bp/sidepane + pass - # Cleanup - tmux_kill_pane(state.panes['SMART'], state.panes['Journal']) + except KeyboardInterrupt: + # Catch user abort + aborted = True + ddrescue_proc.wait(timeout=10) + + # Update progress/sidepane again + bp.update_progress(state.current_pass) + update_sidepane(state) + + # Was ddrescue aborted? + return_code = ddrescue_proc.poll() + if aborted: + print_standard(' ') + print_standard(' ') + print_error('DDRESCUE PROCESS HALTED') + print_standard(' ') + print_warning('Aborted') + break + elif return_code: + # i.e. True when non-zero + print_standard(' ') + print_standard(' ') + print_error('DDRESCUE PROCESS HALTED') + print_standard(' ') + print_error('Error(s) encountered, see message above.') + break + else: + # Mark pass finished + bp.finish_pass(state.current_pass) + update_sidepane(state) + + # Done + if str(return_code) != '0': + # Pause on errors + pause('Press Enter to return to main menu... ') + + # Cleanup + tmux_kill_pane(state.panes['SMART'], state.panes['Journal']) def select_parts(source_device): - """Select partition(s) or whole device, returns list of DevObj()s.""" - selected_parts = [] - children = source_device.details.get('children', []) + """Select partition(s) or whole device, returns list of DevObj()s.""" + selected_parts = [] + children = source_device.details.get('children', []) - if not children: - # No partitions detected, auto-select whole device. - selected_parts = [source_device] - else: - # Build menu - dev_options = [{ - 'Base Name': '{:<14}(Whole device)'.format(source_device.path), - 'Dev': source_device, - 'Selected': True}] - for c_details in children: - dev_options.append({ - 'Base Name': '{:<14}({:>6} {})'.format( - c_details['name'], - c_details['size'], - c_details['fstype'] if c_details['fstype'] else 'Unknown'), - 'Details': c_details, - 'Dev': DevObj(c_details['name']), - 'Selected': False}) - actions = [ - {'Name': 'Proceed', 'Letter': 'P'}, - {'Name': 'Quit', 'Letter': 'Q'}] + if not children: + # No partitions detected, auto-select whole device. + selected_parts = [source_device] + else: + # Build menu + dev_options = [{ + 'Base Name': '{:<14}(Whole device)'.format(source_device.path), + 'Dev': source_device, + 'Selected': True}] + for c_details in children: + dev_options.append({ + 'Base Name': '{:<14}({:>6} {})'.format( + c_details['name'], + c_details['size'], + c_details['fstype'] if c_details['fstype'] else 'Unknown'), + 'Details': c_details, + 'Dev': DevObj(c_details['name']), + 'Selected': False}) + actions = [ + {'Name': 'Proceed', 'Letter': 'P'}, + {'Name': 'Quit', 'Letter': 'Q'}] - # Show menu - while True: - one_or_more_devs_selected = False - # Update entries - for dev in dev_options: - if dev['Selected']: - one_or_more_devs_selected = True - dev['Name'] = '* {}'.format(dev['Base Name']) - else: - dev['Name'] = ' {}'.format(dev['Base Name']) + # Show menu + while True: + one_or_more_devs_selected = False + # Update entries + for dev in dev_options: + if dev['Selected']: + one_or_more_devs_selected = True + dev['Name'] = '* {}'.format(dev['Base Name']) + else: + dev['Name'] = ' {}'.format(dev['Base Name']) - selection = menu_select( - title='Please select part(s) to image', - main_entries=dev_options, - action_entries=actions) + selection = menu_select( + title='Please select part(s) to image', + main_entries=dev_options, + action_entries=actions) - if selection.isnumeric(): - # Toggle selection - index = int(selection) - 1 - dev_options[index]['Selected'] = not dev_options[index]['Selected'] + if selection.isnumeric(): + # Toggle selection + index = int(selection) - 1 + dev_options[index]['Selected'] = not dev_options[index]['Selected'] - # Deselect whole device if child selected (this round) - if index > 0: - dev_options[0]['Selected'] = False + # Deselect whole device if child selected (this round) + if index > 0: + dev_options[0]['Selected'] = False - # Deselect all children if whole device selected - if dev_options[0]['Selected']: - for dev in dev_options[1:]: - dev['Selected'] = False - elif selection == 'P' and one_or_more_devs_selected: - break - elif selection == 'Q': - raise GenericAbort() + # Deselect all children if whole device selected + if dev_options[0]['Selected']: + for dev in dev_options[1:]: + dev['Selected'] = False + elif selection == 'P' and one_or_more_devs_selected: + break + elif selection == 'Q': + raise GenericAbort() - # Build list of selected parts - for d in dev_options: - if d['Selected']: - d['Dev'].model = source_device.model - d['Dev'].model_size = source_device.model_size - d['Dev'].update_filename_prefix() - selected_parts.append(d['Dev']) + # Build list of selected parts + for d in dev_options: + if d['Selected']: + d['Dev'].model = source_device.model + d['Dev'].model_size = source_device.model_size + d['Dev'].update_filename_prefix() + selected_parts.append(d['Dev']) - return selected_parts + return selected_parts def select_path(skip_device=None): - """Optionally mount local dev and select path, returns DirObj.""" - wd = os.path.realpath(global_vars['Env']['PWD']) - selected_path = None + """Optionally mount local dev and select path, returns DirObj.""" + wd = os.path.realpath(global_vars['Env']['PWD']) + selected_path = None - # Build menu - path_options = [ - {'Name': 'Current directory: {}'.format(wd), 'Path': wd}, - {'Name': 'Local device', 'Path': None}, - {'Name': 'Enter manually', 'Path': None}] - actions = [{'Name': 'Quit', 'Letter': 'Q'}] + # Build menu + path_options = [ + {'Name': 'Current directory: {}'.format(wd), 'Path': wd}, + {'Name': 'Local device', 'Path': None}, + {'Name': 'Enter manually', 'Path': None}] + actions = [{'Name': 'Quit', 'Letter': 'Q'}] - # Show Menu - selection = menu_select( - title='Please make a selection', - main_entries=path_options, + # Show Menu + selection = menu_select( + title='Please make a selection', + main_entries=path_options, + action_entries=actions) + + if selection == 'Q': + raise GenericAbort() + elif selection.isnumeric(): + index = int(selection) - 1 + if path_options[index]['Path'] == wd: + # Current directory + selected_path = DirObj(wd) + + elif path_options[index]['Name'] == 'Local device': + # Local device + local_device = select_device( + skip_device=skip_device) + s_path = '' + + # Mount device volume(s) + report = mount_volumes( + all_devices=False, + device_path=local_device.path, + read_write=True) + + # Select volume + vol_options = [] + for k, v in sorted(report.items()): + disabled = v['show_data']['data'] == 'Failed to mount' + if disabled: + name = '{name} (Failed to mount)'.format(**v) + else: + name = '{name} (mounted on "{mount_point}")'.format(**v) + vol_options.append({ + 'Name': name, + 'Path': v['mount_point'], + 'Disabled': disabled}) + selection = menu_select( + title='Please select a volume', + main_entries=vol_options, action_entries=actions) - - if selection == 'Q': + if selection.isnumeric(): + s_path = vol_options[int(selection)-1]['Path'] + elif selection == 'Q': raise GenericAbort() - elif selection.isnumeric(): - index = int(selection) - 1 - if path_options[index]['Path'] == wd: - # Current directory - selected_path = DirObj(wd) - elif path_options[index]['Name'] == 'Local device': - # Local device - local_device = select_device( - skip_device=skip_device) - s_path = '' + # Create folder + if ask('Create ticket folder?'): + ticket_folder = get_simple_string('Please enter folder name') + s_path = os.path.join(s_path, ticket_folder) + try: + os.makedirs(s_path, exist_ok=True) + except OSError: + raise GenericError( + 'Failed to create folder "{}"'.format(s_path)) - # Mount device volume(s) - report = mount_volumes( - all_devices=False, - device_path=local_device.path, - read_write=True) + # Create DirObj + selected_path = DirObj(s_path) - # Select volume - vol_options = [] - for k, v in sorted(report.items()): - disabled = v['show_data']['data'] == 'Failed to mount' - if disabled: - name = '{name} (Failed to mount)'.format(**v) - else: - name = '{name} (mounted on "{mount_point}")'.format(**v) - vol_options.append({ - 'Name': name, - 'Path': v['mount_point'], - 'Disabled': disabled}) - selection = menu_select( - title='Please select a volume', - main_entries=vol_options, - action_entries=actions) - if selection.isnumeric(): - s_path = vol_options[int(selection)-1]['Path'] - elif selection == 'Q': - raise GenericAbort() - - # Create folder - if ask('Create ticket folder?'): - ticket_folder = get_simple_string('Please enter folder name') - s_path = os.path.join(s_path, ticket_folder) - try: - os.makedirs(s_path, exist_ok=True) - except OSError: - raise GenericError( - 'Failed to create folder "{}"'.format(s_path)) - - # Create DirObj - selected_path = DirObj(s_path) - - elif path_options[index]['Name'] == 'Enter manually': - # Manual entry - while not selected_path: - manual_path = input('Please enter path: ').strip() - if manual_path and pathlib.Path(manual_path).is_dir(): - selected_path = DirObj(manual_path) - elif manual_path and pathlib.Path(manual_path).is_file(): - print_error('File "{}" exists'.format(manual_path)) - else: - print_error('Invalid path "{}"'.format(manual_path)) - return selected_path + elif path_options[index]['Name'] == 'Enter manually': + # Manual entry + while not selected_path: + manual_path = input('Please enter path: ').strip() + if manual_path and pathlib.Path(manual_path).is_dir(): + selected_path = DirObj(manual_path) + elif manual_path and pathlib.Path(manual_path).is_file(): + print_error('File "{}" exists'.format(manual_path)) + else: + print_error('Invalid path "{}"'.format(manual_path)) + return selected_path def select_device(description='device', skip_device=None): - """Select device via a menu, returns DevObj.""" - cmd = ( - 'lsblk', - '--json', - '--nodeps', - '--output-all', - '--paths') - result = run_program(cmd) - json_data = json.loads(result.stdout.decode()) - skip_names = [] - if skip_device: - skip_names.append(skip_device.path) - if skip_device.parent: - skip_names.append(skip_device.parent) + """Select device via a menu, returns DevObj.""" + cmd = ( + 'lsblk', + '--json', + '--nodeps', + '--output-all', + '--paths') + result = run_program(cmd) + json_data = json.loads(result.stdout.decode()) + skip_names = [] + if skip_device: + skip_names.append(skip_device.path) + if skip_device.parent: + skip_names.append(skip_device.parent) - # Build menu - dev_options = [] - for dev in json_data['blockdevices']: - # Disable dev if in skip_names - disabled = dev['name'] in skip_names or dev['pkname'] in skip_names + # Build menu + dev_options = [] + for dev in json_data['blockdevices']: + # Disable dev if in skip_names + disabled = dev['name'] in skip_names or dev['pkname'] in skip_names - # Add to options - dev_options.append({ - 'Name': '{name:12} {tran:5} {size:6} {model} {serial}'.format( - name=dev['name'], - tran=dev['tran'] if dev['tran'] else '', - size=dev['size'] if dev['size'] else '', - model=dev['model'] if dev['model'] else '', - serial=dev['serial'] if dev['serial'] else ''), - 'Dev': DevObj(dev['name']), - 'Disabled': disabled}) - dev_options = sorted(dev_options, key=itemgetter('Name')) - if not dev_options: - raise GenericError('No devices available.') + # Add to options + dev_options.append({ + 'Name': '{name:12} {tran:5} {size:6} {model} {serial}'.format( + name=dev['name'], + tran=dev['tran'] if dev['tran'] else '', + size=dev['size'] if dev['size'] else '', + model=dev['model'] if dev['model'] else '', + serial=dev['serial'] if dev['serial'] else ''), + 'Dev': DevObj(dev['name']), + 'Disabled': disabled}) + dev_options = sorted(dev_options, key=itemgetter('Name')) + if not dev_options: + raise GenericError('No devices available.') - # Show Menu - actions = [{'Name': 'Quit', 'Letter': 'Q'}] - selection = menu_select( - title='Please select the {} device'.format(description), - main_entries=dev_options, - action_entries=actions, - disabled_label='ALREADY SELECTED') + # Show Menu + actions = [{'Name': 'Quit', 'Letter': 'Q'}] + selection = menu_select( + title='Please select the {} device'.format(description), + main_entries=dev_options, + action_entries=actions, + disabled_label='ALREADY SELECTED') - if selection.isnumeric(): - return dev_options[int(selection)-1]['Dev'] - elif selection == 'Q': - raise GenericAbort() + if selection.isnumeric(): + return dev_options[int(selection)-1]['Dev'] + elif selection == 'Q': + raise GenericAbort() def setup_loopback_device(source_path): - """Setup a loopback device for source_path, returns dev_path as str.""" - cmd = ( - 'losetup', - '--find', - '--partscan', - '--show', - source_path) - try: - out = run_program(cmd, check=True) - dev_path = out.stdout.decode().strip() - sleep(1) - except CalledProcessError: - raise GenericError('Failed to setup loopback device for source.') - else: - return dev_path + """Setup loopback device for source_path, returns dev_path as str.""" + cmd = ( + 'losetup', + '--find', + '--partscan', + '--show', + source_path) + try: + out = run_program(cmd, check=True) + dev_path = out.stdout.decode().strip() + sleep(1) + except CalledProcessError: + raise GenericError('Failed to setup loopback device for source.') + else: + return dev_path def show_selection_details(state): - """Show selection details.""" - # Source - print_success('Source') - print_standard(state.source.report) - print_standard(' ') + """Show selection details.""" + # Source + print_success('Source') + print_standard(state.source.report) + print_standard(' ') - # Destination - if state.mode == 'clone': - print_success('Destination ', end='') - print_error('(ALL DATA WILL BE DELETED)', timestamp=False) - else: - print_success('Destination') - print_standard(state.dest.report) - print_standard(' ') + # Destination + if state.mode == 'clone': + print_success('Destination ', end='') + print_error('(ALL DATA WILL BE DELETED)', timestamp=False) + else: + print_success('Destination') + print_standard(state.dest.report) + print_standard(' ') def show_usage(script_name): - print_info('Usage:') - print_standard(USAGE.format(script_name=script_name)) - pause() + print_info('Usage:') + print_standard(USAGE.format(script_name=script_name)) + pause() def update_sidepane(state): - """Update progress file for side pane.""" - output = [] - state.update_progress() - if state.mode == 'clone': - output.append(' {BLUE}Cloning Status{CLEAR}'.format(**COLORS)) + """Update progress file for side pane.""" + output = [] + state.update_progress() + if state.mode == 'clone': + output.append(' {BLUE}Cloning Status{CLEAR}'.format(**COLORS)) + else: + output.append(' {BLUE}Imaging Status{CLEAR}'.format(**COLORS)) + output.append('─────────────────────') + + # Overall progress + output.append('{BLUE}Overall Progress{CLEAR}'.format(**COLORS)) + output.append(state.status_percent) + output.append(state.status_amount) + output.append('─────────────────────') + + # Source(s) progress + for bp in state.block_pairs: + if state.source.is_image(): + output.append('{BLUE}Image File{CLEAR}'.format(**COLORS)) else: - output.append(' {BLUE}Imaging Status{CLEAR}'.format(**COLORS)) - output.append('─────────────────────') + output.append('{BLUE}{source}{CLEAR}'.format( + source=bp.source_path, + **COLORS)) + output.extend(bp.status) + output.append(' ') - # Overall progress - output.append('{BLUE}Overall Progress{CLEAR}'.format(**COLORS)) - output.append(state.status_percent) - output.append(state.status_amount) - output.append('─────────────────────') + # Add line-endings + output = ['{}\n'.format(line) for line in output] - # Source(s) progress - for bp in state.block_pairs: - if state.source.is_image(): - output.append('{BLUE}Image File{CLEAR}'.format(**COLORS)) - else: - output.append('{BLUE}{source}{CLEAR}'.format( - source=bp.source_path, - **COLORS)) - output.extend(bp.status) - output.append(' ') - - # Add line-endings - output = ['{}\n'.format(line) for line in output] - - with open(state.progress_out, 'w') as f: - f.writelines(output) + with open(state.progress_out, 'w') as f: + f.writelines(output) if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") -# vim: sts=4 sw=4 ts=4 +# vim: sts=2 sw=2 ts=2 From 0a899539c933beecde2db7f8225eaa8981d3fbc7 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 19:52:18 -0700 Subject: [PATCH 161/265] Updated diags.py --- .bin/Scripts/functions/diags.py | 300 ++++++++++++++++---------------- 1 file changed, 151 insertions(+), 149 deletions(-) diff --git a/.bin/Scripts/functions/diags.py b/.bin/Scripts/functions/diags.py index e55f5b12..317f2b4f 100644 --- a/.bin/Scripts/functions/diags.py +++ b/.bin/Scripts/functions/diags.py @@ -6,184 +6,186 @@ from functions.common import * # STATIC VARIABLES AUTORUNS_SETTINGS = { - r'Software\Sysinternals\AutoRuns': { - 'checkvirustotal': 1, - 'EulaAccepted': 1, - 'shownomicrosoft': 1, - 'shownowindows': 1, - 'showonlyvirustotal': 1, - 'submitvirustotal': 0, - 'verifysignatures': 1, - }, - r'Software\Sysinternals\AutoRuns\SigCheck': { - 'EulaAccepted': 1, - }, - r'Software\Sysinternals\AutoRuns\Streams': { - 'EulaAccepted': 1, - }, - r'Software\Sysinternals\AutoRuns\VirusTotal': { - 'VirusTotalTermsAccepted': 1, - }, - } + r'Software\Sysinternals\AutoRuns': { + 'checkvirustotal': 1, + 'EulaAccepted': 1, + 'shownomicrosoft': 1, + 'shownowindows': 1, + 'showonlyvirustotal': 1, + 'submitvirustotal': 0, + 'verifysignatures': 1, + }, + r'Software\Sysinternals\AutoRuns\SigCheck': { + 'EulaAccepted': 1, + }, + r'Software\Sysinternals\AutoRuns\Streams': { + 'EulaAccepted': 1, + }, + r'Software\Sysinternals\AutoRuns\VirusTotal': { + 'VirusTotalTermsAccepted': 1, + }, + } def check_connection(): - """Check if the system is online and optionally abort the script.""" - while True: - result = try_and_print(message='Ping test...', function=ping, cs='OK') - if result['CS']: - break - if not ask('ERROR: System appears offline, try again?'): - if ask('Continue anyway?'): - break - else: - abort() + """Check if the system is online and optionally abort the script.""" + while True: + result = try_and_print(message='Ping test...', function=ping, cs='OK') + if result['CS']: + break + if not ask('ERROR: System appears offline, try again?'): + if ask('Continue anyway?'): + break + else: + abort() def check_secure_boot_status(show_alert=False): - """Checks UEFI Secure Boot status via PowerShell.""" - boot_mode = get_boot_mode() - cmd = ['PowerShell', '-Command', 'Confirm-SecureBootUEFI'] - result = run_program(cmd, check=False) + """Checks UEFI Secure Boot status via PowerShell.""" + boot_mode = get_boot_mode() + cmd = ['PowerShell', '-Command', 'Confirm-SecureBootUEFI'] + result = run_program(cmd, check=False) - # Check results - if result.returncode == 0: - out = result.stdout.decode() - if 'True' in out: - # It's on, do nothing - return - elif 'False' in out: - if show_alert: - show_alert_box('Secure Boot DISABLED') - raise SecureBootDisabledError - else: - if show_alert: - show_alert_box('Secure Boot status UNKNOWN') - raise SecureBootUnknownError + # Check results + if result.returncode == 0: + out = result.stdout.decode() + if 'True' in out: + # It's on, do nothing + return + elif 'False' in out: + if show_alert: + show_alert_box('Secure Boot DISABLED') + raise SecureBootDisabledError else: - if boot_mode != 'UEFI': - if (show_alert and - global_vars['OS']['Version'] in ('8', '8.1', '10')): - # OS supports Secure Boot - show_alert_box('Secure Boot DISABLED\n\nOS installed LEGACY') - raise OSInstalledLegacyError - else: - # Check error message - err = result.stderr.decode() - if 'Cmdlet not supported' in err: - if show_alert: - show_alert_box('Secure Boot UNAVAILABLE?') - raise SecureBootNotAvailError - else: - if show_alert: - show_alert_box('Secure Boot ERROR') - raise GenericError + if show_alert: + show_alert_box('Secure Boot status UNKNOWN') + raise SecureBootUnknownError + else: + if boot_mode != 'UEFI': + if (show_alert and + global_vars['OS']['Version'] in ('8', '8.1', '10')): + # OS supports Secure Boot + show_alert_box('Secure Boot DISABLED\n\nOS installed LEGACY') + raise OSInstalledLegacyError + else: + # Check error message + err = result.stderr.decode() + if 'Cmdlet not supported' in err: + if show_alert: + show_alert_box('Secure Boot UNAVAILABLE?') + raise SecureBootNotAvailError + else: + if show_alert: + show_alert_box('Secure Boot ERROR') + raise GenericError def get_boot_mode(): - """Check if Windows is booted in UEFI or Legacy mode, returns str.""" - kernel = ctypes.windll.kernel32 - firmware_type = ctypes.c_uint() + """Check if Windows is booted in UEFI or Legacy mode, returns str.""" + kernel = ctypes.windll.kernel32 + firmware_type = ctypes.c_uint() - # Get value from kernel32 API - try: - kernel.GetFirmwareType(ctypes.byref(firmware_type)) - except: - # Just set to zero - firmware_type = ctypes.c_uint(0) + # Get value from kernel32 API + try: + kernel.GetFirmwareType(ctypes.byref(firmware_type)) + except: + # Just set to zero + firmware_type = ctypes.c_uint(0) - # Set return value - type_str = 'Unknown' - if firmware_type.value == 1: - type_str = 'Legacy' - elif firmware_type.value == 2: - type_str = 'UEFI' + # Set return value + type_str = 'Unknown' + if firmware_type.value == 1: + type_str = 'Legacy' + elif firmware_type.value == 2: + type_str = 'UEFI' - return type_str + return type_str def run_autoruns(): - """Run AutoRuns in the background with VirusTotal checks enabled.""" - extract_item('Autoruns', filter='autoruns*', silent=True) - # Update AutoRuns settings before running - for path, settings in AUTORUNS_SETTINGS.items(): - winreg.CreateKey(HKCU, path) - with winreg.OpenKey(HKCU, path, access=winreg.KEY_WRITE) as key: - for name, value in settings.items(): - winreg.SetValueEx(key, name, 0, winreg.REG_DWORD, value) - popen_program(global_vars['Tools']['AutoRuns'], minimized=True) + """Run AutoRuns in the background with VirusTotal checks enabled.""" + extract_item('Autoruns', filter='autoruns*', silent=True) + # Update AutoRuns settings before running + for path, settings in AUTORUNS_SETTINGS.items(): + winreg.CreateKey(HKCU, path) + with winreg.OpenKey(HKCU, path, access=winreg.KEY_WRITE) as key: + for name, value in settings.items(): + winreg.SetValueEx(key, name, 0, winreg.REG_DWORD, value) + popen_program(global_vars['Tools']['AutoRuns'], minimized=True) def run_hwinfo_sensors(): - """Run HWiNFO sensors.""" - path = r'{BinDir}\HWiNFO'.format(**global_vars) - for bit in [32, 64]: - # Configure - source = r'{}\general.ini'.format(path) - dest = r'{}\HWiNFO{}.ini'.format(path, bit) - shutil.copy(source, dest) - with open(dest, 'a') as f: - f.write('SensorsOnly=1\n') - f.write('SummaryOnly=0\n') - popen_program(global_vars['Tools']['HWiNFO']) + """Run HWiNFO sensors.""" + path = r'{BinDir}\HWiNFO'.format(**global_vars) + for bit in [32, 64]: + # Configure + source = r'{}\general.ini'.format(path) + dest = r'{}\HWiNFO{}.ini'.format(path, bit) + shutil.copy(source, dest) + with open(dest, 'a') as f: + f.write('SensorsOnly=1\n') + f.write('SummaryOnly=0\n') + popen_program(global_vars['Tools']['HWiNFO']) def run_nircmd(*cmd): - """Run custom NirCmd.""" - extract_item('NirCmd', silent=True) - cmd = [global_vars['Tools']['NirCmd'], *cmd] - run_program(cmd, check=False) + """Run custom NirCmd.""" + extract_item('NirCmd', silent=True) + cmd = [global_vars['Tools']['NirCmd'], *cmd] + run_program(cmd, check=False) def run_xmplay(): - """Run XMPlay to test audio.""" - extract_item('XMPlay', silent=True) - cmd = [global_vars['Tools']['XMPlay'], - r'{BinDir}\XMPlay\music.7z'.format(**global_vars)] + """Run XMPlay to test audio.""" + extract_item('XMPlay', silent=True) + cmd = [global_vars['Tools']['XMPlay'], + r'{BinDir}\XMPlay\music.7z'.format(**global_vars)] - # Unmute audio first - extract_item('NirCmd', silent=True) - run_nircmd('mutesysvolume', '0') + # Unmute audio first + extract_item('NirCmd', silent=True) + run_nircmd('mutesysvolume', '0') - # Open XMPlay - popen_program(cmd) + # Open XMPlay + popen_program(cmd) def run_hitmanpro(): - """Run HitmanPro in the background.""" - extract_item('HitmanPro', silent=True) - cmd = [ - global_vars['Tools']['HitmanPro'], - '/quiet', '/noinstall', '/noupload', - r'/log={LogDir}\Tools\HitmanPro.txt'.format(**global_vars)] - popen_program(cmd) + """Run HitmanPro in the background.""" + extract_item('HitmanPro', silent=True) + cmd = [ + global_vars['Tools']['HitmanPro'], + '/quiet', '/noinstall', '/noupload', + r'/log={LogDir}\Tools\HitmanPro.txt'.format(**global_vars)] + popen_program(cmd) def run_process_killer(): - """Kill most running processes skipping those in the whitelist.txt.""" - # borrowed from TronScript (reddit.com/r/TronScript) - # credit to /u/cuddlychops06 - prev_dir = os.getcwd() - extract_item('ProcessKiller', silent=True) - os.chdir(r'{BinDir}\ProcessKiller'.format(**global_vars)) - run_program(['ProcessKiller.exe', '/silent'], check=False) - os.chdir(prev_dir) + """Kill most running processes skipping those in the whitelist.txt.""" + # borrowed from TronScript (reddit.com/r/TronScript) + # credit to /u/cuddlychops06 + prev_dir = os.getcwd() + extract_item('ProcessKiller', silent=True) + os.chdir(r'{BinDir}\ProcessKiller'.format(**global_vars)) + run_program(['ProcessKiller.exe', '/silent'], check=False) + os.chdir(prev_dir) def run_rkill(): - """Run RKill and cleanup afterwards.""" - extract_item('RKill', silent=True) - cmd = [ - global_vars['Tools']['RKill'], - '-s', '-l', r'{LogDir}\Tools\RKill.log'.format(**global_vars), - '-new_console:n', '-new_console:s33V'] - run_program(cmd, check=False) - wait_for_process('RKill') + """Run RKill and cleanup afterwards.""" + extract_item('RKill', silent=True) + cmd = [ + global_vars['Tools']['RKill'], + '-s', '-l', r'{LogDir}\Tools\RKill.log'.format(**global_vars), + '-new_console:n', '-new_console:s33V'] + run_program(cmd, check=False) + wait_for_process('RKill') - # RKill cleanup - desktop_path = r'{USERPROFILE}\Desktop'.format(**global_vars['Env']) - if os.path.exists(desktop_path): - for item in os.scandir(desktop_path): - if re.search(r'^RKill', item.name, re.IGNORECASE): - dest = r'{LogDir}\Tools\{name}'.format( - name=dest, **global_vars) - dest = non_clobber_rename(dest) - shutil.move(item.path, dest) + # RKill cleanup + desktop_path = r'{USERPROFILE}\Desktop'.format(**global_vars['Env']) + if os.path.exists(desktop_path): + for item in os.scandir(desktop_path): + if re.search(r'^RKill', item.name, re.IGNORECASE): + dest = r'{LogDir}\Tools\{name}'.format( + name=dest, **global_vars) + dest = non_clobber_rename(dest) + shutil.move(item.path, dest) def show_alert_box(message, title='Wizard Kit Warning'): - """Show Windows alert box with message.""" - message_box = ctypes.windll.user32.MessageBoxW - message_box(None, message, title, 0x00001030) + """Show Windows alert box with message.""" + message_box = ctypes.windll.user32.MessageBoxW + message_box(None, message, title, 0x00001030) if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From ffd07e07fd308e17ef1c6b7f1038708d977d385f Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 19:53:58 -0700 Subject: [PATCH 162/265] Renamed diags.py to sw_diags.py * Avoid confusion with hw_diags.py --- .bin/Scripts/functions/{diags.py => sw_diags.py} | 0 .bin/Scripts/system_checklist.py | 2 +- .bin/Scripts/system_diagnostics.py | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename .bin/Scripts/functions/{diags.py => sw_diags.py} (100%) diff --git a/.bin/Scripts/functions/diags.py b/.bin/Scripts/functions/sw_diags.py similarity index 100% rename from .bin/Scripts/functions/diags.py rename to .bin/Scripts/functions/sw_diags.py diff --git a/.bin/Scripts/system_checklist.py b/.bin/Scripts/system_checklist.py index a76433ee..52720438 100644 --- a/.bin/Scripts/system_checklist.py +++ b/.bin/Scripts/system_checklist.py @@ -8,10 +8,10 @@ os.chdir(os.path.dirname(os.path.realpath(__file__))) sys.path.append(os.getcwd()) from functions.activation import * from functions.cleanup import * -from functions.diags import * from functions.info import * from functions.product_keys import * from functions.setup import * +from functions.sw_diags import * init_global_vars() os.system('title {}: System Checklist Tool'.format(KIT_NAME_FULL)) set_log_file('System Checklist.log') diff --git a/.bin/Scripts/system_diagnostics.py b/.bin/Scripts/system_diagnostics.py index bbeb2d11..ffa28079 100644 --- a/.bin/Scripts/system_diagnostics.py +++ b/.bin/Scripts/system_diagnostics.py @@ -7,10 +7,10 @@ import sys os.chdir(os.path.dirname(os.path.realpath(__file__))) sys.path.append(os.getcwd()) from functions.browsers import * -from functions.diags import * from functions.info import * from functions.product_keys import * from functions.repairs import * +from functions.sw_diags import * init_global_vars() os.system('title {}: System Diagnostics Tool'.format(KIT_NAME_FULL)) set_log_file('System Diagnostics.log') From 166a293864a43a9fab95e14279b2a1822654d723 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 19:55:41 -0700 Subject: [PATCH 163/265] Updated hw_diags.py --- .bin/Scripts/functions/hw_diags.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index a4184689..210ae870 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -1320,7 +1320,8 @@ def run_mprime_test(state, test): if re.search(r'(error|fail)', line, re.IGNORECASE): test.failed = True test.update_status('NS') - test.report.append(' {YELLOW}{line}{CLEAR}'.format(line=line, **COLORS)) + test.report.append( + ' {YELLOW}{line}{CLEAR}'.format(line=line, **COLORS)) # prime.log (CS check) if log == 'prime.log': @@ -1349,7 +1350,8 @@ def run_mprime_test(state, test): for line in sorted(_tmp['Pass'].keys()): test.report.append(' {}'.format(line)) for line in sorted(_tmp['Warn'].keys()): - test.report.append(' {YELLOW}{line}{CLEAR}'.format(line=line, **COLORS)) + test.report.append( + ' {YELLOW}{line}{CLEAR}'.format(line=line, **COLORS)) # Unknown result if not (test.aborted or test.failed or test.passed): From 097fae866a51e527d32d26754a2e44a87954c85e Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 19:57:39 -0700 Subject: [PATCH 164/265] Updated info.py --- .bin/Scripts/functions/info.py | 868 +++++++++++++++++---------------- 1 file changed, 437 insertions(+), 431 deletions(-) diff --git a/.bin/Scripts/functions/info.py b/.bin/Scripts/functions/info.py index 7630a766..4c691e3c 100644 --- a/.bin/Scripts/functions/info.py +++ b/.bin/Scripts/functions/info.py @@ -8,513 +8,519 @@ from functions.activation import * # Regex REGEX_OFFICE = re.compile( - r'(Microsoft (Office\s+' - r'(365|Enterprise|Home|Pro(\s|fessional)' - r'|Single|Small|Standard|Starter|Ultimate|system)' - r'|Works[-\s\d]+\d)' - r'|(Libre|Open|Star)\s*Office' - r'|WordPerfect|Gnumeric|Abiword)', - re.IGNORECASE) + r'(Microsoft (Office\s+' + r'(365|Enterprise|Home|Pro(\s|fessional)' + r'|Single|Small|Standard|Starter|Ultimate|system)' + r'|Works[-\s\d]+\d)' + r'|(Libre|Open|Star)\s*Office' + r'|WordPerfect|Gnumeric|Abiword)', + re.IGNORECASE) # STATIC VARIABLES REG_PROFILE_LIST = r'SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList' REG_SHELL_FOLDERS = r'Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders' TMP_HIVE_PATH = 'TEMP_HIVE_MOUNT' EXTRA_FOLDERS = [ - 'Dropbox', - 'Google Drive', - 'OneDrive', - 'SkyDrive', + 'Dropbox', + 'Google Drive', + 'OneDrive', + 'SkyDrive', ] SHELL_FOLDERS = { - #GUIDs from: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx - 'Desktop': ( - '{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}', - ), - 'Documents': ( - 'Personal', - '{FDD39AD0-238F-46AF-ADB4-6C85480369C7}', - ), - 'Downloads': ( - '{374DE290-123F-4565-9164-39C4925E467B}', - ), - 'Favorites': ( - '{1777F761-68AD-4D8A-87BD-30B759FA33DD}', - ), - 'Music': ( - 'My Music', - '{4BD8D571-6D19-48D3-BE97-422220080E43}', - ), - 'Pictures': ( - 'My Pictures', - '{33E28130-4E1E-4676-835A-98395C3BC3BB}', - ), - 'Videos': ( - 'My Video', - '{18989B1D-99B5-455B-841C-AB7C74E4DDFC}', - ), + #GUIDs from: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx + 'Desktop': ( + '{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}', + ), + 'Documents': ( + 'Personal', + '{FDD39AD0-238F-46AF-ADB4-6C85480369C7}', + ), + 'Downloads': ( + '{374DE290-123F-4565-9164-39C4925E467B}', + ), + 'Favorites': ( + '{1777F761-68AD-4D8A-87BD-30B759FA33DD}', + ), + 'Music': ( + 'My Music', + '{4BD8D571-6D19-48D3-BE97-422220080E43}', + ), + 'Pictures': ( + 'My Pictures', + '{33E28130-4E1E-4676-835A-98395C3BC3BB}', + ), + 'Videos': ( + 'My Video', + '{18989B1D-99B5-455B-841C-AB7C74E4DDFC}', + ), } def backup_file_list(): - """Export current file listing for the system.""" - extract_item('Everything', silent=True) - cmd = [ - global_vars['Tools']['Everything'], - '-nodb', - '-create-filelist', - r'{LogDir}\File List.txt'.format(**global_vars), - global_vars['Env']['SYSTEMDRIVE']] - run_program(cmd) + """Export current file listing for the system.""" + extract_item('Everything', silent=True) + cmd = [ + global_vars['Tools']['Everything'], + '-nodb', + '-create-filelist', + r'{LogDir}\File List.txt'.format(**global_vars), + global_vars['Env']['SYSTEMDRIVE']] + run_program(cmd) def backup_power_plans(): - """Export current power plans.""" - os.makedirs(r'{BackupDir}\Power Plans\{Date}'.format( - **global_vars), exist_ok=True) - plans = run_program(['powercfg', '/L']) - plans = plans.stdout.decode().splitlines() - plans = [p for p in plans if re.search(r'^Power Scheme', p)] - for p in plans: - guid = re.sub(r'Power Scheme GUID:\s+([0-9a-f\-]+).*', r'\1', p) - name = re.sub( - r'Power Scheme GUID:\s+[0-9a-f\-]+\s+\(([^\)]+)\).*', r'\1', p) - out = r'{BackupDir}\Power Plans\{Date}\{name}.pow'.format( - name=name, **global_vars) - if not os.path.exists(out): - cmd = ['powercfg', '-export', out, guid] - run_program(cmd, check=False) + """Export current power plans.""" + os.makedirs(r'{BackupDir}\Power Plans\{Date}'.format( + **global_vars), exist_ok=True) + plans = run_program(['powercfg', '/L']) + plans = plans.stdout.decode().splitlines() + plans = [p for p in plans if re.search(r'^Power Scheme', p)] + for p in plans: + guid = re.sub(r'Power Scheme GUID:\s+([0-9a-f\-]+).*', r'\1', p) + name = re.sub( + r'Power Scheme GUID:\s+[0-9a-f\-]+\s+\(([^\)]+)\).*', r'\1', p) + out = r'{BackupDir}\Power Plans\{Date}\{name}.pow'.format( + name=name, **global_vars) + if not os.path.exists(out): + cmd = ['powercfg', '-export', out, guid] + run_program(cmd, check=False) def backup_registry(overwrite=False): - """Backup registry including user hives.""" - extract_item('erunt', silent=True) - cmd = [ - global_vars['Tools']['ERUNT'], - r'{BackupDir}\Registry\{Date}'.format(**global_vars), - 'sysreg', - 'curuser', - 'otherusers', - '/noprogresswindow'] - if overwrite: - cmd.append('/noconfirmdelete') - run_program(cmd) + """Backup registry including user hives.""" + extract_item('erunt', silent=True) + cmd = [ + global_vars['Tools']['ERUNT'], + r'{BackupDir}\Registry\{Date}'.format(**global_vars), + 'sysreg', + 'curuser', + 'otherusers', + '/noprogresswindow'] + if overwrite: + cmd.append('/noconfirmdelete') + run_program(cmd) def get_folder_size(path): - """Get (human-readable) size of folder passed, returns str.""" - size = 'Unknown' - cmd = [global_vars['Tools']['Du'], '-c', '-nobanner', '-q', path] + """Get (human-readable) size of folder passed, returns str.""" + size = 'Unknown' + cmd = [global_vars['Tools']['Du'], '-c', '-nobanner', '-q', path] + try: + out = run_program(cmd) + except FileNotFoundError: + # Failed to find folder + pass + except subprocess.CalledProcessError: + # Failed to get folder size + pass + else: try: - out = run_program(cmd) - except FileNotFoundError: - # Failed to find folder - pass - except subprocess.CalledProcessError: - # Failed to get folder size - pass + size = out.stdout.decode().split(',')[-2] + except IndexError: + # Failed to parse csv data + pass else: - try: - size = out.stdout.decode().split(',')[-2] - except IndexError: - # Failed to parse csv data - pass - else: - size = human_readable_size(size) - return size + size = human_readable_size(size) + return size def get_installed_antivirus(): - """Get list of installed Antivirus programs.""" - programs = [] + """Get list of installed Antivirus programs.""" + programs = [] + cmd = ['WMIC', r'/namespace:\\root\SecurityCenter2', + 'path', 'AntivirusProduct', + 'get', 'displayName', '/value'] + out = run_program(cmd) + out = out.stdout.decode().strip() + products = out.splitlines() + products = [p.split('=')[1] for p in products if p] + for prod in sorted(products): + # Get product state and check if it's enabled + # credit: https://jdhitsolutions.com/blog/powershell/5187/get-antivirus-product-status-with-powershell/ cmd = ['WMIC', r'/namespace:\\root\SecurityCenter2', - 'path', 'AntivirusProduct', - 'get', 'displayName', '/value'] + 'path', 'AntivirusProduct', + 'where', 'displayName="{}"'.format(prod), + 'get', 'productState', '/value'] out = run_program(cmd) out = out.stdout.decode().strip() - products = out.splitlines() - products = [p.split('=')[1] for p in products if p] - for prod in sorted(products): - # Get product state and check if it's enabled - # credit: https://jdhitsolutions.com/blog/powershell/5187/get-antivirus-product-status-with-powershell/ - cmd = ['WMIC', r'/namespace:\\root\SecurityCenter2', - 'path', 'AntivirusProduct', - 'where', 'displayName="{}"'.format(prod), - 'get', 'productState', '/value'] - out = run_program(cmd) - out = out.stdout.decode().strip() - state = out.split('=')[1] - state = hex(int(state)) - if str(state)[3:5] != '10': - programs.append('[Disabled] {}'.format(prod)) - else: - programs.append(prod) + state = out.split('=')[1] + state = hex(int(state)) + if str(state)[3:5] != '10': + programs.append('[Disabled] {}'.format(prod)) + else: + programs.append(prod) - if len(programs) == 0: - programs = ['No programs found'] - return programs + if len(programs) == 0: + programs = ['No programs found'] + return programs def get_installed_office(): - """Get list of installed Office programs.""" - programs = [] - log_file = r'{LogDir}\Installed Program List (AIDA64).txt'.format( - **global_vars) - with open (log_file, 'r') as f: - for line in sorted(f.readlines()): - if REGEX_OFFICE.search(line): - programs.append(line[4:82].strip()) + """Get list of installed Office programs.""" + programs = [] + log_file = r'{LogDir}\Installed Program List (AIDA64).txt'.format( + **global_vars) + with open (log_file, 'r') as f: + for line in sorted(f.readlines()): + if REGEX_OFFICE.search(line): + programs.append(line[4:82].strip()) - if len(programs) == 0: - programs = ['No programs found'] - return programs + if len(programs) == 0: + programs = ['No programs found'] + return programs def get_shell_path(folder, user='current'): - """Get shell path using SHGetKnownFolderPath via knownpaths, returns str. + """Get shell path using SHGetKnownFolderPath via knownpaths, returns str. - NOTE: Only works for the current user. - Code based on https://gist.github.com/mkropat/7550097 - """ - path = None - folderid = None - if user.lower() == 'public': - user = 'common' + NOTE: Only works for the current user. + Code based on https://gist.github.com/mkropat/7550097 + """ + path = None + folderid = None + if user.lower() == 'public': + user = 'common' + try: + folderid = getattr(knownpaths.FOLDERID, folder) + except AttributeError: + # Unknown folder ID, ignore and return None + pass + + if folderid: try: - folderid = getattr(knownpaths.FOLDERID, folder) - except AttributeError: - # Unknown folder ID, ignore and return None - pass + path = knownpaths.get_path( + folderid, getattr(knownpaths.UserHandle, user)) + except PathNotFoundError: + # Folder not found, ignore and return None + pass - if folderid: - try: - path = knownpaths.get_path(folderid, getattr(knownpaths.UserHandle, user)) - except PathNotFoundError: - # Folder not found, ignore and return None - pass - - return path + return path def get_user_data_paths(user): - """Get user data paths for provided user, returns dict.""" - hive_path = user['SID'] - paths = { - 'Profile': { - 'Path': None, - }, - 'Shell Folders': {}, - 'Extra Folders': {}, - } - unload_hive = False + """Get user data paths for provided user, returns dict.""" + hive_path = user['SID'] + paths = { + 'Profile': { + 'Path': None, + }, + 'Shell Folders': {}, + 'Extra Folders': {}, + } + unload_hive = False - if user['Name'] == global_vars['Env']['USERNAME']: - # We can use SHGetKnownFolderPath for the current user - paths['Profile']['Path'] = get_shell_path('Profile') - paths['Shell Folders'] = {f: {'Path': get_shell_path(f)} - for f in SHELL_FOLDERS.keys()} - else: - # We have to use the NTUSER.dat hives which isn't recommended by MS - try: - key_path = r'{}\{}'.format(REG_PROFILE_LIST, user['SID']) - with winreg.OpenKey(HKLM, key_path) as key: - paths['Profile']['Path'] = winreg.QueryValueEx( - key, 'ProfileImagePath')[0] - except Exception: - # Profile path not found, leaving as None. - pass + if user['Name'] == global_vars['Env']['USERNAME']: + # We can use SHGetKnownFolderPath for the current user + paths['Profile']['Path'] = get_shell_path('Profile') + paths['Shell Folders'] = {f: {'Path': get_shell_path(f)} + for f in SHELL_FOLDERS.keys()} + else: + # We have to use the NTUSER.dat hives which isn't recommended by MS + try: + key_path = r'{}\{}'.format(REG_PROFILE_LIST, user['SID']) + with winreg.OpenKey(HKLM, key_path) as key: + paths['Profile']['Path'] = winreg.QueryValueEx( + key, 'ProfileImagePath')[0] + except Exception: + # Profile path not found, leaving as None. + pass - # Shell folders (Prep) - if not reg_path_exists(HKU, hive_path) and paths['Profile']['Path']: - # User not logged-in, loading hive - # Also setting unload_hive so it will be unloaded later. - hive_path = TMP_HIVE_PATH - cmd = ['reg', 'load', r'HKU\{}'.format(TMP_HIVE_PATH), - r'{}\NTUSER.DAT'.format(paths['Profile']['Path'])] - unload_hive = True + # Shell folders (Prep) + if not reg_path_exists(HKU, hive_path) and paths['Profile']['Path']: + # User not logged-in, loading hive + # Also setting unload_hive so it will be unloaded later. + hive_path = TMP_HIVE_PATH + cmd = ['reg', 'load', r'HKU\{}'.format(TMP_HIVE_PATH), + r'{}\NTUSER.DAT'.format(paths['Profile']['Path'])] + unload_hive = True + try: + run_program(cmd) + except subprocess.CalledProcessError: + # Failed to load user hive + pass + + # Shell folders + shell_folders = r'{}\{}'.format(hive_path, REG_SHELL_FOLDERS) + if (reg_path_exists(HKU, hive_path) + and reg_path_exists(HKU, shell_folders)): + with winreg.OpenKey(HKU, shell_folders) as key: + for folder, values in SHELL_FOLDERS.items(): + for value in values: try: - run_program(cmd) - except subprocess.CalledProcessError: - # Failed to load user hive - pass + path = winreg.QueryValueEx(key, value)[0] + except FileNotFoundError: + # Skip missing values + pass + else: + paths['Shell Folders'][folder] = {'Path': path} + # Stop checking values for this folder + break - # Shell folders - shell_folders = r'{}\{}'.format(hive_path, REG_SHELL_FOLDERS) - if (reg_path_exists(HKU, hive_path) - and reg_path_exists(HKU, shell_folders)): - with winreg.OpenKey(HKU, shell_folders) as key: - for folder, values in SHELL_FOLDERS.items(): - for value in values: - try: - path = winreg.QueryValueEx(key, value)[0] - except FileNotFoundError: - # Skip missing values - pass - else: - paths['Shell Folders'][folder] = {'Path': path} - # Stop checking values for this folder - break - - # Shell folder (extra check) - if paths['Profile']['Path']: - for folder in SHELL_FOLDERS.keys(): - folder_path = r'{Path}\{folder}'.format( - folder=folder, **paths['Profile']) - if (folder not in paths['Shell Folders'] - and os.path.exists(folder_path)): - paths['Shell Folders'][folder] = {'Path': folder_path} - - # Extra folders + # Shell folder (extra check) if paths['Profile']['Path']: - for folder in EXTRA_FOLDERS: - folder_path = r'{Path}\{folder}'.format( - folder=folder, **paths['Profile']) - if os.path.exists(folder_path): - paths['Extra Folders'][folder] = {'Path': folder_path} + for folder in SHELL_FOLDERS.keys(): + folder_path = r'{Path}\{folder}'.format( + folder=folder, **paths['Profile']) + if (folder not in paths['Shell Folders'] + and os.path.exists(folder_path)): + paths['Shell Folders'][folder] = {'Path': folder_path} - # Shell folders (cleanup) - if unload_hive: - cmd = ['reg', 'unload', r'HKU\{}'.format(TMP_HIVE_PATH)] - run_program(cmd, check=False) + # Extra folders + if paths['Profile']['Path']: + for folder in EXTRA_FOLDERS: + folder_path = r'{Path}\{folder}'.format( + folder=folder, **paths['Profile']) + if os.path.exists(folder_path): + paths['Extra Folders'][folder] = {'Path': folder_path} - # Done - return paths + # Shell folders (cleanup) + if unload_hive: + cmd = ['reg', 'unload', r'HKU\{}'.format(TMP_HIVE_PATH)] + run_program(cmd, check=False) + + # Done + return paths def get_user_folder_sizes(users): - """Update list(users) to include folder paths and sizes.""" - extract_item('du', filter='du*', silent=True) - # Configure Du - winreg.CreateKey(HKCU, r'Software\Sysinternals\Du') - with winreg.OpenKey(HKCU, - r'Software\Sysinternals\Du', access=winreg.KEY_WRITE) as key: - winreg.SetValueEx(key, 'EulaAccepted', 0, winreg.REG_DWORD, 1) + """Update list(users) to include folder paths and sizes.""" + extract_item('du', filter='du*', silent=True) + # Configure Du + winreg.CreateKey(HKCU, r'Software\Sysinternals\Du') + with winreg.OpenKey(HKCU, + r'Software\Sysinternals\Du', access=winreg.KEY_WRITE) as key: + winreg.SetValueEx(key, 'EulaAccepted', 0, winreg.REG_DWORD, 1) - for u in users: - u.update(get_user_data_paths(u)) - if u['Profile']['Path']: - u['Profile']['Size'] = get_folder_size(u['Profile']['Path']) - for folder in u['Shell Folders'].keys(): - u['Shell Folders'][folder]['Size'] = get_folder_size( - u['Shell Folders'][folder]['Path']) - for folder in u['Extra Folders'].keys(): - u['Extra Folders'][folder]['Size'] = get_folder_size( - u['Extra Folders'][folder]['Path']) + for u in users: + u.update(get_user_data_paths(u)) + if u['Profile']['Path']: + u['Profile']['Size'] = get_folder_size(u['Profile']['Path']) + for folder in u['Shell Folders'].keys(): + u['Shell Folders'][folder]['Size'] = get_folder_size( + u['Shell Folders'][folder]['Path']) + for folder in u['Extra Folders'].keys(): + u['Extra Folders'][folder]['Size'] = get_folder_size( + u['Extra Folders'][folder]['Path']) def get_user_list(): - """Get user list via WMIC, returns list of dicts.""" - users = [] + """Get user list via WMIC, returns list of dicts.""" + users = [] - # Get user info from WMI - cmd = ['wmic', 'useraccount', 'get', '/format:csv'] - try: - out = run_program(cmd) - except subprocess.CalledProcessError: - # Meh, return empty list to avoid a full crash - return users - - entries = out.stdout.decode().splitlines() - entries = [e.strip().split(',') for e in entries if e.strip()] - - # Add user(s) to dict - keys = entries[0] - for e in entries[1:]: - # Create dict using 1st line (keys) - e = dict(zip(keys, e)) - # Set Active status via 'Disabled' TRUE/FALSE str - e['Active'] = bool(e['Disabled'].upper() == 'FALSE') - # Assume SIDs ending with 1000+ are "Standard" and others are "System" - e['Type'] = 'Standard' if re.search(r'-1\d+$', e['SID']) else 'System' - users.append(e) - - # Sort list - users.sort(key=itemgetter('Name')) - - # Done + # Get user info from WMI + cmd = ['wmic', 'useraccount', 'get', '/format:csv'] + try: + out = run_program(cmd) + except subprocess.CalledProcessError: + # Meh, return empty list to avoid a full crash return users + entries = out.stdout.decode().splitlines() + entries = [e.strip().split(',') for e in entries if e.strip()] + + # Add user(s) to dict + keys = entries[0] + for e in entries[1:]: + # Create dict using 1st line (keys) + e = dict(zip(keys, e)) + # Set Active status via 'Disabled' TRUE/FALSE str + e['Active'] = bool(e['Disabled'].upper() == 'FALSE') + # Assume SIDs ending with 1000+ are "Standard" and others are "System" + e['Type'] = 'Standard' if re.search(r'-1\d+$', e['SID']) else 'System' + users.append(e) + + # Sort list + users.sort(key=itemgetter('Name')) + + # Done + return users + def reg_path_exists(hive, path): - """Test if specified path exists, returns bool.""" - try: - winreg.QueryValue(hive, path) - except FileNotFoundError: - return False - else: - return True + """Test if specified path exists, returns bool.""" + try: + winreg.QueryValue(hive, path) + except FileNotFoundError: + return False + else: + return True def run_aida64(): - """Run AIDA64 to save system reports.""" - extract_item('AIDA64', silent=True) - # All system info - config = r'{BinDir}\AIDA64\full.rpf'.format(**global_vars) - report_file = r'{LogDir}\System Information (AIDA64).html'.format( - **global_vars) - if not os.path.exists(report_file): - cmd = [ - global_vars['Tools']['AIDA64'], - '/R', report_file, - '/CUSTOM', config, - '/HTML', '/SILENT', '/SAFEST'] - run_program(cmd, check=False) + """Run AIDA64 to save system reports.""" + extract_item('AIDA64', silent=True) + # All system info + config = r'{BinDir}\AIDA64\full.rpf'.format(**global_vars) + report_file = r'{LogDir}\System Information (AIDA64).html'.format( + **global_vars) + if not os.path.exists(report_file): + cmd = [ + global_vars['Tools']['AIDA64'], + '/R', report_file, + '/CUSTOM', config, + '/HTML', '/SILENT', '/SAFEST'] + run_program(cmd, check=False) - # Installed Programs - config = r'{BinDir}\AIDA64\installed_programs.rpf'.format(**global_vars) - report_file = r'{LogDir}\Installed Program List (AIDA64).txt'.format( - **global_vars) - if not os.path.exists(report_file): - cmd = [ - global_vars['Tools']['AIDA64'], - '/R', report_file, - '/CUSTOM', config, - '/TEXT', '/SILENT', '/SAFEST'] - run_program(cmd, check=False) + # Installed Programs + config = r'{BinDir}\AIDA64\installed_programs.rpf'.format(**global_vars) + report_file = r'{LogDir}\Installed Program List (AIDA64).txt'.format( + **global_vars) + if not os.path.exists(report_file): + cmd = [ + global_vars['Tools']['AIDA64'], + '/R', report_file, + '/CUSTOM', config, + '/TEXT', '/SILENT', '/SAFEST'] + run_program(cmd, check=False) - # Product Keys - config = r'{BinDir}\AIDA64\licenses.rpf'.format(**global_vars) - report_file = r'{LogDir}\Product Keys (AIDA64).txt'.format(**global_vars) - if not os.path.exists(report_file): - cmd = [ - global_vars['Tools']['AIDA64'], - '/R', report_file, - '/CUSTOM', config, - '/TEXT', '/SILENT', '/SAFEST'] - run_program(cmd, check=False) + # Product Keys + config = r'{BinDir}\AIDA64\licenses.rpf'.format(**global_vars) + report_file = r'{LogDir}\Product Keys (AIDA64).txt'.format(**global_vars) + if not os.path.exists(report_file): + cmd = [ + global_vars['Tools']['AIDA64'], + '/R', report_file, + '/CUSTOM', config, + '/TEXT', '/SILENT', '/SAFEST'] + run_program(cmd, check=False) def run_bleachbit(cleaners=None, preview=True): - """Run BleachBit preview and save log. + """Run BleachBit preview and save log. - If preview is True then no files should be deleted.""" - error_path = r'{}\Tools\BleachBit.err'.format(global_vars['LogDir']) - log_path = error_path.replace('err', 'log') - extract_item('BleachBit', silent=True) + If preview is True then no files should be deleted.""" + error_path = r'{}\Tools\BleachBit.err'.format(global_vars['LogDir']) + log_path = error_path.replace('err', 'log') + extract_item('BleachBit', silent=True) - # Safety check - if not cleaners: - # Disable cleaning and use preset config - cleaners = ['--preset'] - preview = True + # Safety check + if not cleaners: + # Disable cleaning and use preset config + cleaners = ['--preset'] + preview = True - # Run - cmd = [ - global_vars['Tools']['BleachBit'], - '--preview' if preview else '--clean'] - cmd.extend(cleaners) - out = run_program(cmd, check=False) + # Run + cmd = [ + global_vars['Tools']['BleachBit'], + '--preview' if preview else '--clean'] + cmd.extend(cleaners) + out = run_program(cmd, check=False) - # Save stderr - if out.stderr.decode().splitlines(): - with open(error_path, 'a', encoding='utf-8') as f: - for line in out.stderr.decode().splitlines(): - f.write(line.strip() + '\n') + # Save stderr + if out.stderr.decode().splitlines(): + with open(error_path, 'a', encoding='utf-8') as f: + for line in out.stderr.decode().splitlines(): + f.write(line.strip() + '\n') - # Save stdout - with open(log_path, 'a', encoding='utf-8') as f: - for line in out.stdout.decode().splitlines(): - f.write(line.strip() + '\n') + # Save stdout + with open(log_path, 'a', encoding='utf-8') as f: + for line in out.stdout.decode().splitlines(): + f.write(line.strip() + '\n') def show_disk_usage(disk): - """Show free and used space for a specified disk.""" - print_standard('{:5}'.format(disk.device.replace('/', ' ')), - end='', flush=True, timestamp=False) - try: - usage = psutil.disk_usage(disk.device) - display_string = '{percent:>5.2f}% Free ({free} / {total})'.format( - percent = 100 - usage.percent, - free = human_readable_size(usage.free, 2), - total = human_readable_size(usage.total, 2)) - if usage.percent > 85: - print_error(display_string, timestamp=False) - elif usage.percent > 75: - print_warning(display_string, timestamp=False) - else: - print_standard(display_string, timestamp=False) - except Exception: - print_warning('Unknown', timestamp=False) + """Show free and used space for a specified disk.""" + print_standard('{:5}'.format(disk.device.replace('/', ' ')), + end='', flush=True, timestamp=False) + try: + usage = psutil.disk_usage(disk.device) + display_string = '{percent:>5.2f}% Free ({free} / {total})'.format( + percent = 100 - usage.percent, + free = human_readable_size(usage.free, 2), + total = human_readable_size(usage.total, 2)) + if usage.percent > 85: + print_error(display_string, timestamp=False) + elif usage.percent > 75: + print_warning(display_string, timestamp=False) + else: + print_standard(display_string, timestamp=False) + except Exception: + print_warning('Unknown', timestamp=False) def show_free_space(indent=8, width=32): - """Show free space info for all fixed disks.""" - message = 'Free Space:' - for disk in psutil.disk_partitions(): - try: - if 'fixed' in disk.opts: - try_and_print(message=message, function=show_disk_usage, - ns='Unknown', silent_function=False, - indent=indent, width=width, disk=disk) - message = '' - except Exception: - pass + """Show free space info for all fixed disks.""" + message = 'Free Space:' + for disk in psutil.disk_partitions(): + try: + if 'fixed' in disk.opts: + try_and_print(message=message, function=show_disk_usage, + ns='Unknown', silent_function=False, + indent=indent, width=width, disk=disk) + message = '' + except Exception: + pass def show_installed_ram(): - """Show installed RAM.""" - mem = psutil.virtual_memory() - if mem.total > 5905580032: - # > 5.5 Gb so 6Gb or greater - print_standard(human_readable_size(mem.total).strip(), timestamp=False) - elif mem.total > 3758096384: - # > 3.5 Gb so 4Gb or greater - print_warning(human_readable_size(mem.total).strip(), timestamp=False) - else: - print_error(human_readable_size(mem.total).strip(), timestamp=False) + """Show installed RAM.""" + mem = psutil.virtual_memory() + if mem.total > 5905580032: + # > 5.5 Gb so 6Gb or greater + print_standard(human_readable_size(mem.total).strip(), timestamp=False) + elif mem.total > 3758096384: + # > 3.5 Gb so 4Gb or greater + print_warning(human_readable_size(mem.total).strip(), timestamp=False) + else: + print_error(human_readable_size(mem.total).strip(), timestamp=False) def show_os_activation(): - """Show OS activation info.""" - act_str = get_activation_string() - if windows_is_activated(): - print_standard(act_str, timestamp=False) - elif re.search(r'unavailable', act_str, re.IGNORECASE): - print_warning(act_str, timestamp=False) - else: - print_error(act_str, timestamp=False) + """Show OS activation info.""" + act_str = get_activation_string() + if windows_is_activated(): + print_standard(act_str, timestamp=False) + elif re.search(r'unavailable', act_str, re.IGNORECASE): + print_warning(act_str, timestamp=False) + else: + print_error(act_str, timestamp=False) def show_os_name(): - """Show extended OS name (including warnings).""" - os_name = global_vars['OS']['DisplayName'] - if global_vars['OS']['Arch'] == 32: - # Show all 32-bit installs as an error message - print_error(os_name, timestamp=False) + """Show extended OS name (including warnings).""" + os_name = global_vars['OS']['DisplayName'] + if global_vars['OS']['Arch'] == 32: + # Show all 32-bit installs as an error message + print_error(os_name, timestamp=False) + else: + if re.search( + r'(preview build|unrecognized|unsupported)', + os_name, + re.IGNORECASE): + print_error(os_name, timestamp=False) + elif re.search(r'outdated', os_name, re.IGNORECASE): + print_warning(os_name, timestamp=False) else: - if re.search(r'(preview build|unrecognized|unsupported)', os_name, re.IGNORECASE): - print_error(os_name, timestamp=False) - elif re.search(r'outdated', os_name, re.IGNORECASE): - print_warning(os_name, timestamp=False) - else: - print_standard(os_name, timestamp=False) + print_standard(os_name, timestamp=False) def show_temp_files_size(): - """Show total size of temp files identified by BleachBit.""" - size = None - with open(r'{LogDir}\Tools\BleachBit.log'.format(**global_vars), 'r') as f: - for line in f.readlines(): - if re.search(r'^disk space to be recovered:', line, re.IGNORECASE): - size = re.sub(r'.*: ', '', line.strip()) - size = re.sub(r'(\w)iB$', r' \1b', size) - if size is None: - print_warning(size, timestamp=False) - else: - print_standard(size, timestamp=False) + """Show total size of temp files identified by BleachBit.""" + size = None + with open(r'{LogDir}\Tools\BleachBit.log'.format(**global_vars), 'r') as f: + for line in f.readlines(): + if re.search(r'^disk space to be recovered:', line, re.IGNORECASE): + size = re.sub(r'.*: ', '', line.strip()) + size = re.sub(r'(\w)iB$', r' \1b', size) + if size is None: + print_warning(size, timestamp=False) + else: + print_standard(size, timestamp=False) def show_user_data_summary(indent=8, width=32): - """Print user data folder sizes for all users.""" - users = get_user_list() - users = [u for u in users if u['Active']] - get_user_folder_sizes(users) - for user in users: - if ('Size' not in user['Profile'] - and not any(user['Shell Folders']) - and not any(user['Extra Folders'])): - # Skip empty users - continue - print_success('{indent}User: {user}'.format( - indent = ' '*int(indent/2), - user = user['Name'])) - for section in ['Profile', None, 'Shell Folders', 'Extra Folders']: - folders = [] - if section is None: - # Divider - print_standard('{}{}'.format(' '*indent, '-'*(width+6))) - elif section == 'Profile': - folders = {'Profile': user['Profile']} - else: - folders = user[section] - for folder in folders: - print_standard( - '{indent}{folder:<{width}}{size:>6} ({path})'.format( - indent = ' ' * indent, - width = width, - folder = folder, - size = folders[folder].get('Size', 'Unknown'), - path = folders[folder].get('Path', 'Unknown'))) + """Print user data folder sizes for all users.""" + users = get_user_list() + users = [u for u in users if u['Active']] + get_user_folder_sizes(users) + for user in users: + if ('Size' not in user['Profile'] + and not any(user['Shell Folders']) + and not any(user['Extra Folders'])): + # Skip empty users + continue + print_success('{indent}User: {user}'.format( + indent = ' '*int(indent/2), + user = user['Name'])) + for section in ['Profile', None, 'Shell Folders', 'Extra Folders']: + folders = [] + if section is None: + # Divider + print_standard('{}{}'.format(' '*indent, '-'*(width+6))) + elif section == 'Profile': + folders = {'Profile': user['Profile']} + else: + folders = user[section] + for folder in folders: + print_standard( + '{indent}{folder:<{width}}{size:>6} ({path})'.format( + indent = ' ' * indent, + width = width, + folder = folder, + size = folders[folder].get('Size', 'Unknown'), + path = folders[folder].get('Path', 'Unknown'))) if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From 018aba2fe6f1b4e34e007dc24beea9c3ac544c49 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 19:58:06 -0700 Subject: [PATCH 165/265] Updated network.py --- .bin/Scripts/functions/network.py | 89 ++++++++++++++++--------------- 1 file changed, 45 insertions(+), 44 deletions(-) diff --git a/.bin/Scripts/functions/network.py b/.bin/Scripts/functions/network.py index 5735c486..80935506 100644 --- a/.bin/Scripts/functions/network.py +++ b/.bin/Scripts/functions/network.py @@ -13,60 +13,61 @@ from functions.common import * # REGEX REGEX_VALID_IP = re.compile( - r'(10.\d+.\d+.\d+' - r'|172.(1[6-9]|2\d|3[0-1])' - r'|192.168.\d+.\d+)', - re.IGNORECASE) + r'(10.\d+.\d+.\d+' + r'|172.(1[6-9]|2\d|3[0-1])' + r'|192.168.\d+.\d+)', + re.IGNORECASE) def connect_to_network(): - """Connect to network if not already connected.""" - net_ifs = psutil.net_if_addrs() - net_ifs = [i[:2] for i in net_ifs.keys()] + """Connect to network if not already connected.""" + net_ifs = psutil.net_if_addrs() + net_ifs = [i[:2] for i in net_ifs.keys()] - # Bail if currently connected - if is_connected(): - return + # Bail if currently connected + if is_connected(): + return - # WiFi - if 'wl' in net_ifs: - cmd = [ - 'nmcli', 'dev', 'wifi', - 'connect', WIFI_SSID, - 'password', WIFI_PASSWORD] - try_and_print( - message = 'Connecting to {}...'.format(WIFI_SSID), - function = run_program, - cmd = cmd) + # WiFi + if 'wl' in net_ifs: + cmd = [ + 'nmcli', 'dev', 'wifi', + 'connect', WIFI_SSID, + 'password', WIFI_PASSWORD] + try_and_print( + message = 'Connecting to {}...'.format(WIFI_SSID), + function = run_program, + cmd = cmd) def is_connected(): - """Check for a valid private IP.""" - devs = psutil.net_if_addrs() - for dev in devs.values(): - for family in dev: - if REGEX_VALID_IP.search(family.address): - # Valid IP found - return True - # Else - return False + """Check for a valid private IP.""" + devs = psutil.net_if_addrs() + for dev in devs.values(): + for family in dev: + if REGEX_VALID_IP.search(family.address): + # Valid IP found + return True + # Else + return False def show_valid_addresses(): - """Show all valid private IP addresses assigned to the system.""" - devs = psutil.net_if_addrs() - for dev, families in sorted(devs.items()): - for family in families: - if REGEX_VALID_IP.search(family.address): - # Valid IP found - show_data(message=dev, data=family.address) + """Show all valid private IP addresses assigned to the system.""" + devs = psutil.net_if_addrs() + for dev, families in sorted(devs.items()): + for family in families: + if REGEX_VALID_IP.search(family.address): + # Valid IP found + show_data(message=dev, data=family.address) def speedtest(): - """Run a network speedtest using speedtest-cli.""" - result = run_program(['speedtest-cli', '--simple']) - output = [line.strip() for line in result.stdout.decode().splitlines() - if line.strip()] - output = [line.split() for line in output] - output = [(a, float(b), c) for a, b, c in output] - return ['{:10}{:6.2f} {}'.format(*line) for line in output] + """Run a network speedtest using speedtest-cli.""" + result = run_program(['speedtest-cli', '--simple']) + output = [line.strip() for line in result.stdout.decode().splitlines() + if line.strip()] + output = [line.split() for line in output] + output = [(a, float(b), c) for a, b, c in output] + return ['{:10}{:6.2f} {}'.format(*line) for line in output] if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") +# vim: sts=2 sw=2 ts=2 From 07e43307c5bfc97e53692f5846762cd3bd1187df Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 20:04:29 -0700 Subject: [PATCH 166/265] Moved partiton_uids.py to settings --- .bin/Scripts/functions/disk.py | 4 +- .bin/Scripts/functions/partition_uids.py | 326 ----------------------- .bin/Scripts/settings/partition_uids.py | 325 ++++++++++++++++++++++ 3 files changed, 327 insertions(+), 328 deletions(-) delete mode 100644 .bin/Scripts/functions/partition_uids.py create mode 100644 .bin/Scripts/settings/partition_uids.py diff --git a/.bin/Scripts/functions/disk.py b/.bin/Scripts/functions/disk.py index 75879ff8..257f21b0 100644 --- a/.bin/Scripts/functions/disk.py +++ b/.bin/Scripts/functions/disk.py @@ -1,7 +1,7 @@ # Wizard Kit: Functions - Disk from functions.common import * -from functions import partition_uids +from settings.partition_uids import * # Regex REGEX_BAD_PARTITION = re.compile(r'(RAW|Unknown)', re.IGNORECASE) @@ -113,7 +113,7 @@ def get_partition_details(disk, partition): details.update({key.strip(): value.strip() for (key, value) in tmp}) # Get MBR type / GPT GUID for extra details on "Unknown" partitions - guid = partition_uids.lookup_guid(details.get('Type')) + guid = PARTITION_UIDS.get(details.get('Type').upper(), {}) if guid: details.update({ 'Description': guid.get('Description', '')[:29], diff --git a/.bin/Scripts/functions/partition_uids.py b/.bin/Scripts/functions/partition_uids.py deleted file mode 100644 index 38fba0db..00000000 --- a/.bin/Scripts/functions/partition_uids.py +++ /dev/null @@ -1,326 +0,0 @@ -# Wizard Kit: Functions - PARTITION UIDs -# sources: https://en.wikipedia.org/wiki/GUID_Partition_Table -# https://en.wikipedia.org/wiki/Partition_type -# NOTE: Info has been trimmed for brevity. As such, there may be some inaccuracy. - -PARTITION_UIDS = { - '00': {'OS': 'All','Description': 'Empty partition entry'}, - '01': {'OS': 'DOS','Description': 'FAT12 as primary partition'}, - '02': {'OS': 'XENIX','Description': 'XENIX root'}, - '03': {'OS': 'XENIX','Description': 'XENIX usr'}, - '04': {'OS': 'DOS','Description': 'FAT16 with less than 32 MB'}, - '05': {'OS': 'DOS / SpeedStor','Description': 'Extended partition'}, - '06': {'OS': 'DOS1+','Description': 'FAT16B [over 65K sectors]'}, - '07': {'OS': 'Windows / OS/2 / QNX 2','Description': 'NTFS/exFAT/HPFS/IFS/QNX'}, - '08': {'OS': 'CBM / DOS / OS/2 / AIX /QNX','Description': 'FAT12-16/AIX/QNY/SplitDrive'}, - '09': {'OS': 'AIX / QNX / Coherent / OS-9','Description': 'AIX/QNZ/Coherent/RBF'}, - '0A': {'OS': 'OS/2 / Coherent','Description': 'Boot Manager / Swap'}, - '0B': {'OS': 'DOS','Description': 'FAT32 with CHS addressing'}, - '0C': {'OS': 'DOS','Description': 'FAT32 with LBA'}, - '0D': {'OS': 'Silicon Safe','Description': 'Reserved'}, - '0E': {'OS': 'DOS','Description': 'FAT16B with LBA'}, - '0F': {'OS': 'DOS','Description': 'Extended partition with LBA'}, - '10': {'OS': 'OPUS','Description': 'Unknown'}, - '11': {'OS': 'Leading Edge MS-DOS / OS/2','Description': 'FAT12/FAT16'}, - '12': {'OS': 'Compaq Contura','Description': 'conf/diag/hiber/rescue/serv'}, - '14': {'OS': 'AST DOS / OS/2 / MaverickOS','Description': 'FAT12/FAT16/Omega'}, - '15': {'OS': 'OS/2 / Maverick OS','Description': 'Hidden extended / Swap'}, - '16': {'OS': 'OS/2 Boot Manager','Description': 'Hidden FAT16B'}, - '17': {'OS': 'OS/2 Boot Manager','Description': 'Hidden IFS/HPFS/NTFS/exFAT'}, - '18': {'OS': 'AST Windows','Description': '0-Volt Suspend/SmartSleep'}, - '19': {'OS': 'Willowtech Photon coS','Description': 'Willowtech Photon coS'}, - '1B': {'OS': 'OS/2 Boot Manager','Description': 'Hidden FAT32'}, - '1C': {'OS': 'OS/2 Boot Manager','Description': 'Hidden FAT32 with LBA'}, - '1E': {'OS': 'OS/2 Boot Manager','Description': 'Hidden FAT16 with LBA'}, - '1F': {'OS': 'OS/2 Boot Manager','Description': 'Hidden extended with LBA'}, - '20': {'OS': 'Windows Mobile','Description': 'update XIP/Willowsoft OFS1'}, - '21': {'OS': 'Oxygen','Description': 'SpeedStor / FSo2'}, - '22': {'OS': 'Oxygen','Description': 'Oxygen Extended Partition'}, - '23': {'OS': 'Windows Mobile','Description': 'Reserved / boot XIP'}, - '24': {'OS': 'NEC MS-DOS0','Description': 'Logical FAT12 or FAT16'}, - '25': {'OS': 'Windows Mobile','Description': 'IMGFS[citation needed]'}, - '26': {'OS': 'Microsoft, IBM','Description': 'Reserved'}, - '27': {'OS': 'Win/PQserv/MirOS/RooterBOOT','Description': 'WinRE/Rescue/MirOS/RooterBOOT'}, - '2A': {'OS': 'AtheOS','Description': 'AthFS/AFS/Reserved'}, - '2B': {'OS': 'SyllableOS','Description': 'SyllableSecure (SylStor)'}, - '31': {'OS': 'Microsoft, IBM','Description': 'Reserved'}, - '32': {'OS': 'NOS','Description': 'Unknown'}, - '33': {'OS': 'Microsoft, IBM','Description': 'Reserved'}, - '34': {'OS': 'Microsoft, IBM','Description': 'Reserved'}, - '35': {'OS': 'OS/2 Server /eComStation','Description': 'JFS'}, - '36': {'OS': 'Microsoft, IBM','Description': 'Reserved'}, - '38': {'OS': 'THEOS','Description': 'THEOS version 3.2, 2 GB'}, - '39': {'OS': 'Plan 9 / THEOS','Description': 'Plan 9 edition 3 / THEOS v4'}, - '3A': {'OS': 'THEOS','Description': 'THEOS v4, 4 GB'}, - '3B': {'OS': 'THEOS','Description': 'THEOS v4 extended'}, - '3C': {'OS': 'PartitionMagic','Description': 'PqRP (image in progress)'}, - '3D': {'OS': 'PartitionMagic','Description': 'Hidden NetWare'}, - '3F': {'OS': 'OS/32','Description': 'Unknown'}, - '40': {'OS': 'PICK / Venix','Description': 'PICK R83 / Venix 80286'}, - '41': {'OS': 'RISC / Linux / PowerPC','Description': 'Boot / Old Linux/Minix'}, - '42': {'OS': 'SFS / Linux / Win2K/XP/etc','Description': 'SFS / Old Linux Swap'}, - '43': {'OS': 'Linux','Description': 'Old Linux native'}, - '44': {'OS': 'GoBack','Description': 'Norton/WildFire/Adaptec/Roxio'}, - '45': {'OS': 'Boot-US / EUMEL/ELAN','Description': 'Priam/Boot/EUMEL/ELAN (L2)'}, - '46': {'OS': 'EUMEL/ELAN','Description': 'EUMEL/ELAN (L2)'}, - '47': {'OS': 'EUMEL/ELAN','Description': 'EUMEL/ELAN (L2)'}, - '48': {'OS': 'EUMEL/ELAN','Description': 'EUMEL/ELAN (L2), ERGOS L3'}, - '4A': {'OS': 'AdaOS / ALFS/THIN','Description': 'Aquila / ALFS/THIN'}, - '4C': {'OS': 'ETH Oberon','Description': 'Aos (A2) file system (76)'}, - '4D': {'OS': 'QNX Neutrino','Description': 'Primary QNX POSIX volume'}, - '4E': {'OS': 'QNX Neutrino','Description': 'Secondary QNX POSIX volume'}, - '4F': {'OS': 'QNX Neutrino / ETH Oberon','Description': '3rd QNX POSIX/Boot/Native'}, - '50': {'OS': 'DiskMan4/ETH/LynxOS/Novell','Description': 'Alt FS/Read-only/Lynx RTOS'}, - '51': {'OS': 'Disk Manager 4-6','Description': 'R/W partition (Aux 1)'}, - '52': {'OS': 'CP/M-80/ System V/AT, V/386','Description': 'CP/M-80'}, - '53': {'OS': 'Disk Manager 6','Description': 'Auxiliary 3 (WO)'}, - '54': {'OS': 'Disk Manager 6','Description': 'Dynamic Drive Overlay (DDO)'}, - '55': {'OS': 'EZ-Drive','Description': 'Maxtor/MaxBlast/DriveGuide'}, - '56': {'OS': 'AT&T DOS/EZ-Drive/VFeature','Description': 'FAT12~16/EZ-BIOS/VFeature'}, - '57': {'OS': 'DrivePro','Description': 'VNDI partition'}, - '5C': {'OS': 'EDISK','Description': 'Priam EDisk Volume'}, - '61': {'OS': 'SpeedStor','Description': 'Unknown'}, - '63': {'OS': 'Unix','Description': 'Unix,ISC,SysV,ix,BSD,HURD'}, - '64': {'OS': 'SpeedStor / NetWare','Description': 'NetWare FS 286/2,PC-ARMOUR'}, - '65': {'OS': 'NetWare','Description': 'NetWare File System 386'}, - '66': {'OS': 'NetWare / NetWare','Description': 'NetWare FS 386 / SMS'}, - '67': {'OS': 'NetWare','Description': 'Wolf Mountain'}, - '68': {'OS': 'NetWare','Description': 'Unknown'}, - '69': {'OS': 'NetWare 5 / NetWare','Description': 'Novell Storage Services'}, - '6E': {'Description': 'Unknown'}, - '70': {'OS': 'DiskSecure','Description': 'DiskSecure multiboot'}, - '71': {'OS': 'Microsoft, IBM','Description': 'Reserved'}, - '72': {'OS': 'APTI systems / Unix V7/x86','Description': 'APTI altFAT12 / V7 / x86'}, - '73': {'OS': 'Microsoft, IBM','Description': 'Reserved'}, - '74': {'OS': 'Microsoft, IBM','Description': 'Reserved / Scramdisk'}, - '75': {'OS': 'PC/IX','Description': 'Unknown'}, - '76': {'OS': 'Microsoft, IBM','Description': 'Reserved'}, - '77': {'OS': 'Novell','Description': 'VNDI, M2FS, M2CS'}, - '78': {'OS': 'Geurt Vos','Description': 'XOSL bootloader file system'}, - '79': {'OS': 'APTI conformant systems','Description': 'APTI altFAT16 (CHS, SFN)'}, - '7A': {'OS': 'APTI conformant systems','Description': 'APTI altFAT16 (LBA, SFN)'}, - '7B': {'OS': 'APTI conformant systems','Description': 'APTI altFAT16B (CHS, SFN)'}, - '7C': {'OS': 'APTI conformant systems','Description': 'APTI altFAT32 (LBA, SFN)'}, - '7D': {'OS': 'APTI conformant systems','Description': 'APTI altFAT32 (CHS, SFN)'}, - '7E': {'OS': 'F.I.X. (claim) / PrimoCache','Description': 'Level 2 cache'}, - '7F': {'OS': 'Varies','Description': 'AltOS DevPartition Standard'}, - '80': {'OS': 'Minix 1.1-1.4a','Description': 'Minix file system (old)'}, - '81': {'OS': 'Minix 1.4b+ / Linux','Description': 'MINIX FS/Mitac AdvDiskManager'}, - '82': {'OS': 'Linux / Sun Microsystems','Description': 'Swap / Solaris x86 / Prime'}, - '83': {'OS': 'GNU/Linux','Description': 'Any native Linux FS'}, - '84': {'OS': 'OS/2 / Windows 7','Description': 'Hibernat/HiddenC/RapidStart'}, - '85': {'OS': 'GNU/Linux','Description': 'Linux extended'}, - '86': {'OS': 'Windows NT 4 Server / Linux','Description': 'FAT16B mirror/LinuxRAID-old'}, - '87': {'OS': 'Windows NT 4 Server','Description': 'HPFS/NTFS mirrored volume'}, - '88': {'OS': 'GNU/Linux','Description': 'Plaintext partition table'}, - '8A': {'OS': 'AiR-BOOT','Description': 'Linux kernel image'}, - '8B': {'OS': 'Windows NT 4 Server','Description': 'FAT32 mirrored volume set'}, - '8C': {'OS': 'Windows NT 4 Server','Description': 'FAT32 mirrored volume set'}, - '8D': {'OS': 'Free FDISK','Description': 'Hidden FAT12'}, - '8E': {'OS': 'Linux','Description': 'Linux LVM'}, - '90': {'OS': 'Free FDISK','Description': 'Hidden FAT16'}, - '91': {'OS': 'Free FDISK','Description': 'Hidden extended partition'}, - '92': {'OS': 'Free FDISK','Description': 'Hidden FAT16B'}, - '93': {'OS': 'Amoeba / Linux','Description': 'Amoeba native/Hidden Linux'}, - '94': {'OS': 'Amoeba','Description': 'Amoeba bad block table'}, - '95': {'OS': 'EXOPC','Description': 'EXOPC native'}, - '96': {'OS': 'CHRP','Description': 'ISO-9660 file system'}, - '97': {'OS': 'Free FDISK','Description': 'Hidden FAT32'}, - '98': {'OS': 'Free FDISK / ROM-DOS','Description': 'Hidden FAT32 / service part'}, - '99': {'OS': 'early Unix','Description': 'Unknown'}, - '9A': {'OS': 'Free FDISK','Description': 'Hidden FAT16'}, - '9B': {'OS': 'Free FDISK','Description': 'Hidden extended partition'}, - '9E': {'OS': 'VSTA / ForthOS','Description': 'ForthOS (eForth port)'}, - '9F': {'OS': 'BSD/OS 3.0+, BSDI','Description': 'Unknown'}, - 'A0': {'OS': 'HP/Phoenix/IBM/Toshiba/Sony','Description': 'Diagnostic for HP/Hibernate'}, - 'A1': {'OS': 'HP / Phoenix, NEC','Description': 'HP Vol Expansion/Hibernate'}, - 'A2': {'OS': 'Cyclone V','Description': 'Hard Processor System (HPS)'}, - 'A3': {'OS': 'HP','Description': 'HP Vol Expansion(SpeedStor)'}, - 'A4': {'OS': 'HP','Description': 'HP Vol Expansion(SpeedStor)'}, - 'A5': {'OS': 'BSD','Description': 'BSD slice'}, - 'A6': {'OS': 'OpenBSD','Description': 'HP Vol Expansion/BSD slice'}, - 'A7': {'OS': 'NeXT','Description': 'NeXTSTEP'}, - 'A8': {'OS': 'Darwin, Mac OS X','Description': 'Apple Darwin, Mac OS X UFS'}, - 'A9': {'OS': 'NetBSD','Description': 'NetBSD slice'}, - 'AA': {'OS': 'MS-DOS','Description': 'Olivetti DOS FAT12(1.44 MB)'}, - 'AB': {'OS': 'Darwin, Mac OS X / GO! OS','Description': 'Apple Darwin/OS X boot/GO!'}, - 'AD': {'OS': 'RISC OS','Description': 'ADFS / FileCore format'}, - 'AE': {'OS': 'ShagOS','Description': 'ShagOS file system'}, - 'AF': {'OS': 'ShagOS','Description': 'OS X HFS & HFS+/ShagOS Swap'}, - 'B0': {'OS': 'Boot-Star','Description': 'Boot-Star dummy partition'}, - 'B1': {'OS': 'QNX 6.x','Description': 'HPVolExpansion/QNX Neutrino'}, - 'B2': {'OS': 'QNX 6.x','Description': 'QNX Neutrino power-safe FS'}, - 'B3': {'OS': 'QNX 6.x','Description': 'HPVolExpansion/QNX Neutrino'}, - 'B4': {'OS': 'HP','Description': 'HP Vol Expansion(SpeedStor)'}, - 'B6': {'OS': 'Windows NT 4 Server','Description': 'HPVolExpansion/FAT16Bmirror'}, - 'B7': {'OS': 'BSDI / Windows NT 4 Server','Description': 'BSDI,Swap,HPFS/NTFS mirror'}, - 'B8': {'OS': 'BSDI (before 3.0)','Description': 'BSDI Swap / native FS'}, - 'BB': {'OS': 'Acronis/BootWizard/WinNT 4','Description': 'BootWizard/OEM/FAT32 mirror'}, - 'BC': {'OS': 'Acronis/WinNT/BackupCapsule','Description': 'FAT32RAID/SecureZone/Backup'}, - 'BD': {'OS': 'BonnyDOS/286','Description': 'Unknown'}, - 'BE': {'OS': 'Solaris 8','Description': 'Solaris 8 boot'}, - 'BF': {'OS': 'Solaris','Description': 'Solaris x86'}, - 'C0': {'OS': 'DR-DOS,MultiuserDOS,REAL/32','Description': 'Secured FAT (under 32 MB)'}, - 'C1': {'OS': 'DR DOS','Description': 'Secured FAT12'}, - 'C2': {'OS': 'Power Boot','Description': 'Hidden Linux native FS'}, - 'C3': {'OS': 'Power Boot','Description': 'Hidden Linux Swap'}, - 'C4': {'OS': 'DR DOS','Description': 'Secured FAT16'}, - 'C5': {'OS': 'DR DOS','Description': 'Secured extended partition'}, - 'C6': {'OS': 'DR DOS / WinNT 4 Server','Description': 'Secured FAT16B/FAT16Bmirror'}, - 'C7': {'OS': 'Syrinx / WinNT 4 Server','Description': 'Syrinx boot/HPFS/NTFSmirror'}, - 'C8': {'Description': "DR-DOS Reserved (since '97)"}, - 'C9': {'Description': "DR-DOS Reserved (since '97)"}, - 'CA': {'Description': "DR-DOS Reserved (since '97)"}, - 'CB': {'OS': 'DR-DOSx / WinNT 4 Server','Description': 'Secured FAT32/FAT32 mirror'}, - 'CC': {'OS': 'DR-DOSx / WinNT 4 Server','Description': 'Secured FAT32/FAT32 mirror'}, - 'CD': {'OS': 'CTOS','Description': 'Memory dump'}, - 'CE': {'OS': 'DR-DOSx','Description': 'Secured FAT16B'}, - 'CF': {'OS': 'DR-DOSx','Description': 'Secured extended partition'}, - 'D0': {'OS': 'Multiuser DOS, REAL/32','Description': 'Secured FAT (over 32 MB)'}, - 'D1': {'OS': 'Multiuser DOS','Description': 'Secured FAT12'}, - 'D4': {'OS': 'Multiuser DOS','Description': 'Secured FAT16'}, - 'D5': {'OS': 'Multiuser DOS','Description': 'Secured extended partition'}, - 'D6': {'OS': 'Multiuser DOS','Description': 'Secured FAT16B'}, - 'D8': {'OS': 'Digital Research','Description': 'CP/M-86 [citation needed]'}, - 'DA': {'OS': 'Powercopy Backup','Description': 'Non-FS data / Shielded disk'}, - 'DB': {'OS': 'CP/M-86/CDOS/CTOS/D800/DRMK','Description': 'CP/M-86/ConcDOS/Boot/FAT32'}, - 'DD': {'OS': 'CTOS','Description': 'Hidden memory dump'}, - 'DE': {'OS': 'Dell','Description': 'FAT16 utility/diagnostic'}, - 'DF': {'OS': 'DG/UX / BootIt / Aviion','Description': 'DG/UX Virt DiskMan / EMBRM'}, - 'E0': {'OS': 'STMicroelectronics','Description': 'ST AVFS'}, - 'E1': {'OS': 'SpeedStor','Description': 'ExtendedFAT12 >1023cylinder'}, - 'E2': {'Description': 'DOS read-only (XFDISK)'}, - 'E3': {'OS': 'SpeedStor','Description': 'DOS read-only'}, - 'E4': {'OS': 'SpeedStor','Description': 'ExtendedFAT16 <1024cylinder'}, - 'E5': {'OS': 'Tandy MS-DOS','Description': 'Logical FAT12 or FAT16'}, - 'E6': {'OS': 'SpeedStor','Description': 'Unknown'}, - 'E8': {'OS': 'LUKS','Description': 'Linux Unified Key Setup'}, - 'EB': {'OS': 'BeOS, Haiku','Description': 'BFS'}, - 'EC': {'OS': 'SkyOS','Description': 'SkyFS'}, - 'ED': {'OS': 'Sprytix / EDD 4','Description': 'EDC loader / GPT hybrid MBR'}, - 'EE': {'OS': 'EFI','Description': 'GPT protective MBR'}, - 'EF': {'OS': 'EFI','Description': 'EFI system partition'}, - 'F0': {'OS': 'Linux / OS/32','Description': 'PA-RISC Linux boot loader.'}, - 'F1': {'OS': 'SpeedStor','Description': 'Unknown'}, - 'F2': {'OS': 'SperryIT DOS/Unisys DOS','Description': 'Logical FAT12/FAT16'}, - 'F3': {'OS': 'SpeedStor','Description': 'Unknown'}, - 'F4': {'OS': 'SpeedStor / Prologue','Description': '"large"DOS part/NGF/TwinFS'}, - 'F5': {'OS': 'Prologue','Description': 'MD0-MD9 part for NGF/TwinFS'}, - 'F6': {'OS': 'SpeedStor','Description': 'Unknown'}, - 'F7': {'OS': 'O.S.G. / X1','Description': 'EFAT / Solid State FS'}, - 'F9': {'OS': 'Linux','Description': 'pCache ext2/ext3 cache'}, - 'FA': {'OS': 'Bochs','Description': 'x86 emulator'}, - 'FB': {'OS': 'VMware','Description': 'VMware VMFS partition'}, - 'FC': {'OS': 'VMware','Description': 'Swap / VMKCORE kernel dump'}, - 'FD': {'OS': 'Linux / FreeDOS','Description': 'LinuxRAID/Reserved4FreeDOS'}, - 'FE': {'OS': 'SpeedStor/LANstep/NT/Linux','Description': 'PS/2/DiskAdmin/old LinuxLVM'}, - 'FF': {'OS': 'XENIX','Description': 'XENIX bad block table'}, - '00000000-0000-0000-0000-000000000000': {'Description': 'Unused entry'}, - '024DEE41-33E7-11D3-9D69-0008C781F39F': {'Description': 'MBR partition scheme'}, - 'C12A7328-F81F-11D2-BA4B-00A0C93EC93B': {'Description': 'EFI System partition'}, - '21686148-6449-6E6F-744E-656564454649': {'Description': 'BIOS Boot partition'}, - 'D3BFE2DE-3DAF-11DF-BA40-E3A556D89593': {'Description': 'Intel Fast Flash (iFFS) partition (for Intel Rapid Start technology)'}, - 'F4019732-066E-4E12-8273-346C5641494F': {'Description': 'Sony boot partition'}, - 'BFBFAFE7-A34F-448A-9A5B-6213EB736C22': {'Description': 'Lenovo boot partition'}, - 'E3C9E316-0B5C-4DB8-817D-F92DF00215AE': {'OS': 'Windows', 'Description': 'Microsoft Reserved Partition (MSR)'}, - 'EBD0A0A2-B9E5-4433-87C0-68B6B72699C7': {'OS': 'Windows', 'Description': 'Basic data partition'}, - '5808C8AA-7E8F-42E0-85D2-E1E90434CFB3': {'OS': 'Windows', 'Description': 'Logical Disk Manager (LDM) metadata partition'}, - 'AF9B60A0-1431-4F62-BC68-3311714A69AD': {'OS': 'Windows', 'Description': 'Logical Disk Manager data partition'}, - 'DE94BBA4-06D1-4D40-A16A-BFD50179D6AC': {'OS': 'Windows', 'Description': 'Windows Recovery Environment'}, - '37AFFC90-EF7D-4E96-91C3-2D7AE055B174': {'OS': 'Windows', 'Description': 'IBM General Parallel File System (GPFS) partition'}, - 'E75CAF8F-F680-4CEE-AFA3-B001E56EFC2D': {'OS': 'Windows', 'Description': 'Storage Spaces partition'}, - '75894C1E-3AEB-11D3-B7C1-7B03A0000000': {'OS': 'HP-UX', 'Description': 'Data partition'}, - 'E2A1E728-32E3-11D6-A682-7B03A0000000': {'OS': 'HP-UX', 'Description': 'Service Partition'}, - '0FC63DAF-8483-4772-8E79-3D69D8477DE4': {'OS': 'Linux', 'Description': 'Linux filesystem data'}, - 'A19D880F-05FC-4D3B-A006-743F0F84911E': {'OS': 'Linux', 'Description': 'RAID partition'}, - '44479540-F297-41B2-9AF7-D131D5F0458A': {'OS': 'Linux', 'Description': 'Root partition (x86)'}, - '4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709': {'OS': 'Linux', 'Description': 'Root partition (x86-64)'}, - '69DAD710-2CE4-4E3C-B16C-21A1D49ABED3': {'OS': 'Linux', 'Description': 'Root partition (32-bit ARM)'}, - 'B921B045-1DF0-41C3-AF44-4C6F280D3FAE': {'OS': 'Linux', 'Description': 'Root partition (64-bit ARM)/AArch64)'}, - '0657FD6D-A4AB-43C4-84E5-0933C84B4F4F': {'OS': 'Linux', 'Description': 'Swap partition'}, - 'E6D6D379-F507-44C2-A23C-238F2A3DF928': {'OS': 'Linux', 'Description': 'Logical Volume Manager (LVM) partition'}, - '933AC7E1-2EB4-4F13-B844-0E14E2AEF915': {'OS': 'Linux', 'Description': '/home partition'}, - '3B8F8425-20E0-4F3B-907F-1A25A76F98E8': {'OS': 'Linux', 'Description': '/srv (server data) partition'}, - '7FFEC5C9-2D00-49B7-8941-3EA10A5586B7': {'OS': 'Linux', 'Description': 'Plain dm-crypt partition'}, - 'CA7D7CCB-63ED-4C53-861C-1742536059CC': {'OS': 'Linux', 'Description': 'LUKS partition'}, - '8DA63339-0007-60C0-C436-083AC8230908': {'OS': 'Linux', 'Description': 'Reserved'}, - '83BD6B9D-7F41-11DC-BE0B-001560B84F0F': {'OS': 'FreeBSD', 'Description': 'Boot partition'}, - '516E7CB4-6ECF-11D6-8FF8-00022D09712B': {'OS': 'FreeBSD', 'Description': 'Data partition'}, - '516E7CB5-6ECF-11D6-8FF8-00022D09712B': {'OS': 'FreeBSD', 'Description': 'Swap partition'}, - '516E7CB6-6ECF-11D6-8FF8-00022D09712B': {'OS': 'FreeBSD', 'Description': 'Unix File System (UFS) partition'}, - '516E7CB8-6ECF-11D6-8FF8-00022D09712B': {'OS': 'FreeBSD', 'Description': 'Vinum volume manager partition'}, - '516E7CBA-6ECF-11D6-8FF8-00022D09712B': {'OS': 'FreeBSD', 'Description': 'ZFS partition'}, - '48465300-0000-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Hierarchical File System Plus (HFS+) partition'}, - '55465300-0000-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple UFS'}, - '6A898CC3-1DD2-11B2-99A6-080020736631': {'OS': 'OS X Darwin', 'Description': 'ZFS'}, - '52414944-0000-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple RAID partition'}, - '52414944-5F4F-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple RAID partition, offline'}, - '426F6F74-0000-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple Boot partition (Recovery HD)'}, - '4C616265-6C00-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple Label'}, - '5265636F-7665-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple TV Recovery partition'}, - '53746F72-6167-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple Core Storage (i.e. Lion FileVault) partition'}, - '6A82CB45-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Boot partition'}, - '6A85CF4D-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Root partition'}, - '6A87C46F-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Swap partition'}, - '6A8B642B-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Backup partition'}, - '6A898CC3-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': '/usr partition'}, - '6A8EF2E9-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': '/var partition'}, - '6A90BA39-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': '/home partition'}, - '6A9283A5-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Alternate sector'}, - '6A945A3B-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Reserved partition'}, - '6A9630D1-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos'}, - '6A980767-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos'}, - '6A96237F-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos'}, - '6A8D2AC7-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos'}, - '49F48D32-B10E-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'Swap partition'}, - '49F48D5A-B10E-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'FFS partition'}, - '49F48D82-B10E-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'LFS partition'}, - '49F48DAA-B10E-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'RAID partition'}, - '2DB519C4-B10F-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'Concatenated partition'}, - '2DB519EC-B10F-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'Encrypted partition'}, - 'FE3A2A5D-4F32-41A7-B725-ACCC3285A309': {'OS': 'ChromeOS', 'Description': 'ChromeOS kernel'}, - '3CB8E202-3B7E-47DD-8A3C-7FF2A13CFCEC': {'OS': 'ChromeOS', 'Description': 'ChromeOS rootfs'}, - '2E0A753D-9E48-43B0-8337-B15192CB1B5E': {'OS': 'ChromeOS', 'Description': 'ChromeOS future use'}, - '42465331-3BA3-10F1-802A-4861696B7521': {'OS': 'Haiku', 'Description': 'Haiku BFS'}, - '85D5E45E-237C-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'Boot partition'}, - '85D5E45A-237C-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'Data partition'}, - '85D5E45B-237C-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'Swap partition'}, - '0394EF8B-237E-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'Unix File System (UFS) partition'}, - '85D5E45C-237C-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'Vinum volume manager partition'}, - '85D5E45D-237C-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'ZFS partition'}, - '45B0969E-9B03-4F30-B4C6-B4B80CEFF106': {'OS': 'Ceph', 'Description': 'Ceph Journal'}, - '45B0969E-9B03-4F30-B4C6-5EC00CEFF106': {'OS': 'Ceph', 'Description': 'Ceph dm-crypt Encrypted Journal'}, - '4FBD7E29-9D25-41B8-AFD0-062C0CEFF05D': {'OS': 'Ceph', 'Description': 'Ceph OSD'}, - '4FBD7E29-9D25-41B8-AFD0-5EC00CEFF05D': {'OS': 'Ceph', 'Description': 'Ceph dm-crypt OSD'}, - '89C57F98-2FE5-4DC0-89C1-F3AD0CEFF2BE': {'OS': 'Ceph', 'Description': 'Ceph disk in creation'}, - '89C57F98-2FE5-4DC0-89C1-5EC00CEFF2BE': {'OS': 'Ceph', 'Description': 'Ceph dm-crypt disk in creation'}, - '824CC7A0-36A8-11E3-890A-952519AD3F61': {'OS': 'OpenBSD', 'Description': 'Data partition'}, - 'CEF5A9AD-73BC-4601-89F3-CDEEEEE321A1': {'OS': 'QNX', 'Description': 'Power-safe (QNX6) file system'}, - 'C91818F9-8025-47AF-89D2-F030D7000C2C': {'OS': 'Plan 9', 'Description': 'Plan 9 partition'}, - '9D275380-40AD-11DB-BF97-000C2911D1B8': {'OS': 'VMware ESX', 'Description': 'vmkcore (coredump partition)'}, - 'AA31E02A-400F-11DB-9590-000C2911D1B8': {'OS': 'VMware ESX', 'Description': 'VMFS filesystem partition'}, - '9198EFFC-31C0-11DB-8F78-000C2911D1B8': {'OS': 'VMware ESX', 'Description': 'VMware Reserved'}, - '2568845D-2332-4675-BC39-8FA5A4748D15': {'OS': 'Android-IA', 'Description': 'Bootloader'}, - '114EAFFE-1552-4022-B26E-9B053604CF84': {'OS': 'Android-IA', 'Description': 'Bootloader2'}, - '49A4D17F-93A3-45C1-A0DE-F50B2EBE2599': {'OS': 'Android-IA', 'Description': 'Boot'}, - '4177C722-9E92-4AAB-8644-43502BFD5506': {'OS': 'Android-IA', 'Description': 'Recovery'}, - 'EF32A33B-A409-486C-9141-9FFB711F6266': {'OS': 'Android-IA', 'Description': 'Misc'}, - '20AC26BE-20B7-11E3-84C5-6CFDB94711E9': {'OS': 'Android-IA', 'Description': 'Metadata'}, - '38F428E6-D326-425D-9140-6E0EA133647C': {'OS': 'Android-IA', 'Description': 'System'}, - 'A893EF21-E428-470A-9E55-0668FD91A2D9': {'OS': 'Android-IA', 'Description': 'Cache'}, - 'DC76DDA9-5AC1-491C-AF42-A82591580C0D': {'OS': 'Android-IA', 'Description': 'Data'}, - 'EBC597D0-2053-4B15-8B64-E0AAC75F4DB1': {'OS': 'Android-IA', 'Description': 'Persistent'}, - '8F68CC74-C5E5-48DA-BE91-A0C8C15E9C80': {'OS': 'Android-IA', 'Description': 'Factory'}, - '767941D0-2085-11E3-AD3B-6CFDB94711E9': {'OS': 'Android-IA', 'Description': 'Fastboot / Tertiary'}, - 'AC6D7924-EB71-4DF8-B48D-E267B27148FF': {'OS': 'Android-IA', 'Description': 'OEM'}, - '7412F7D5-A156-4B13-81DC-867174929325': {'OS': 'ONIE', 'Description': 'Boot'}, - 'D4E6E2CD-4469-46F3-B5CB-1BFF57AFC149': {'OS': 'ONIE', 'Description': 'Config'}, - '9E1A2D38-C612-4316-AA26-8B49521E5A8B': {'OS': 'PowerPC', 'Description': 'PReP boot'}, - 'BC13C2FF-59E6-4262-A352-B275FD6F7172': {'OS': 'Freedesktop', 'Description': 'Extended Boot Partition ($BOOT)'}, -} - -def lookup_guid(guid): - return PARTITION_UIDS.get(guid.upper(), {}) - -if __name__ == '__main__': - print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/settings/partition_uids.py b/.bin/Scripts/settings/partition_uids.py new file mode 100644 index 00000000..f4b21df0 --- /dev/null +++ b/.bin/Scripts/settings/partition_uids.py @@ -0,0 +1,325 @@ +# Wizard Kit: Settings - Partition UIDs +# sources: https://en.wikipedia.org/wiki/GUID_Partition_Table +# https://en.wikipedia.org/wiki/Partition_type +# NOTE: Info has been trimmed for brevity. As such, there may be some inaccuracy. + +PARTITION_UIDS = { + '00': {'OS': 'All','Description': 'Empty partition entry'}, + '01': {'OS': 'DOS','Description': 'FAT12 as primary partition'}, + '02': {'OS': 'XENIX','Description': 'XENIX root'}, + '03': {'OS': 'XENIX','Description': 'XENIX usr'}, + '04': {'OS': 'DOS','Description': 'FAT16 with less than 32 MB'}, + '05': {'OS': 'DOS / SpeedStor','Description': 'Extended partition'}, + '06': {'OS': 'DOS1+','Description': 'FAT16B [over 65K sectors]'}, + '07': {'OS': 'Windows / OS/2 / QNX 2','Description': 'NTFS/exFAT/HPFS/IFS/QNX'}, + '08': {'OS': 'CBM / DOS / OS/2 / AIX /QNX','Description': 'FAT12-16/AIX/QNY/SplitDrive'}, + '09': {'OS': 'AIX / QNX / Coherent / OS-9','Description': 'AIX/QNZ/Coherent/RBF'}, + '0A': {'OS': 'OS/2 / Coherent','Description': 'Boot Manager / Swap'}, + '0B': {'OS': 'DOS','Description': 'FAT32 with CHS addressing'}, + '0C': {'OS': 'DOS','Description': 'FAT32 with LBA'}, + '0D': {'OS': 'Silicon Safe','Description': 'Reserved'}, + '0E': {'OS': 'DOS','Description': 'FAT16B with LBA'}, + '0F': {'OS': 'DOS','Description': 'Extended partition with LBA'}, + '10': {'OS': 'OPUS','Description': 'Unknown'}, + '11': {'OS': 'Leading Edge MS-DOS / OS/2','Description': 'FAT12/FAT16'}, + '12': {'OS': 'Compaq Contura','Description': 'conf/diag/hiber/rescue/serv'}, + '14': {'OS': 'AST DOS / OS/2 / MaverickOS','Description': 'FAT12/FAT16/Omega'}, + '15': {'OS': 'OS/2 / Maverick OS','Description': 'Hidden extended / Swap'}, + '16': {'OS': 'OS/2 Boot Manager','Description': 'Hidden FAT16B'}, + '17': {'OS': 'OS/2 Boot Manager','Description': 'Hidden IFS/HPFS/NTFS/exFAT'}, + '18': {'OS': 'AST Windows','Description': '0-Volt Suspend/SmartSleep'}, + '19': {'OS': 'Willowtech Photon coS','Description': 'Willowtech Photon coS'}, + '1B': {'OS': 'OS/2 Boot Manager','Description': 'Hidden FAT32'}, + '1C': {'OS': 'OS/2 Boot Manager','Description': 'Hidden FAT32 with LBA'}, + '1E': {'OS': 'OS/2 Boot Manager','Description': 'Hidden FAT16 with LBA'}, + '1F': {'OS': 'OS/2 Boot Manager','Description': 'Hidden extended with LBA'}, + '20': {'OS': 'Windows Mobile','Description': 'update XIP/Willowsoft OFS1'}, + '21': {'OS': 'Oxygen','Description': 'SpeedStor / FSo2'}, + '22': {'OS': 'Oxygen','Description': 'Oxygen Extended Partition'}, + '23': {'OS': 'Windows Mobile','Description': 'Reserved / boot XIP'}, + '24': {'OS': 'NEC MS-DOS0','Description': 'Logical FAT12 or FAT16'}, + '25': {'OS': 'Windows Mobile','Description': 'IMGFS[citation needed]'}, + '26': {'OS': 'Microsoft, IBM','Description': 'Reserved'}, + '27': {'OS': 'Win/PQserv/MirOS/RooterBOOT','Description': 'WinRE/Rescue/MirOS/RooterBOOT'}, + '2A': {'OS': 'AtheOS','Description': 'AthFS/AFS/Reserved'}, + '2B': {'OS': 'SyllableOS','Description': 'SyllableSecure (SylStor)'}, + '31': {'OS': 'Microsoft, IBM','Description': 'Reserved'}, + '32': {'OS': 'NOS','Description': 'Unknown'}, + '33': {'OS': 'Microsoft, IBM','Description': 'Reserved'}, + '34': {'OS': 'Microsoft, IBM','Description': 'Reserved'}, + '35': {'OS': 'OS/2 Server /eComStation','Description': 'JFS'}, + '36': {'OS': 'Microsoft, IBM','Description': 'Reserved'}, + '38': {'OS': 'THEOS','Description': 'THEOS version 3.2, 2 GB'}, + '39': {'OS': 'Plan 9 / THEOS','Description': 'Plan 9 edition 3 / THEOS v4'}, + '3A': {'OS': 'THEOS','Description': 'THEOS v4, 4 GB'}, + '3B': {'OS': 'THEOS','Description': 'THEOS v4 extended'}, + '3C': {'OS': 'PartitionMagic','Description': 'PqRP (image in progress)'}, + '3D': {'OS': 'PartitionMagic','Description': 'Hidden NetWare'}, + '3F': {'OS': 'OS/32','Description': 'Unknown'}, + '40': {'OS': 'PICK / Venix','Description': 'PICK R83 / Venix 80286'}, + '41': {'OS': 'RISC / Linux / PowerPC','Description': 'Boot / Old Linux/Minix'}, + '42': {'OS': 'SFS / Linux / Win2K/XP/etc','Description': 'SFS / Old Linux Swap'}, + '43': {'OS': 'Linux','Description': 'Old Linux native'}, + '44': {'OS': 'GoBack','Description': 'Norton/WildFire/Adaptec/Roxio'}, + '45': {'OS': 'Boot-US / EUMEL/ELAN','Description': 'Priam/Boot/EUMEL/ELAN (L2)'}, + '46': {'OS': 'EUMEL/ELAN','Description': 'EUMEL/ELAN (L2)'}, + '47': {'OS': 'EUMEL/ELAN','Description': 'EUMEL/ELAN (L2)'}, + '48': {'OS': 'EUMEL/ELAN','Description': 'EUMEL/ELAN (L2), ERGOS L3'}, + '4A': {'OS': 'AdaOS / ALFS/THIN','Description': 'Aquila / ALFS/THIN'}, + '4C': {'OS': 'ETH Oberon','Description': 'Aos (A2) file system (76)'}, + '4D': {'OS': 'QNX Neutrino','Description': 'Primary QNX POSIX volume'}, + '4E': {'OS': 'QNX Neutrino','Description': 'Secondary QNX POSIX volume'}, + '4F': {'OS': 'QNX Neutrino / ETH Oberon','Description': '3rd QNX POSIX/Boot/Native'}, + '50': {'OS': 'DiskMan4/ETH/LynxOS/Novell','Description': 'Alt FS/Read-only/Lynx RTOS'}, + '51': {'OS': 'Disk Manager 4-6','Description': 'R/W partition (Aux 1)'}, + '52': {'OS': 'CP/M-80/ System V/AT, V/386','Description': 'CP/M-80'}, + '53': {'OS': 'Disk Manager 6','Description': 'Auxiliary 3 (WO)'}, + '54': {'OS': 'Disk Manager 6','Description': 'Dynamic Drive Overlay (DDO)'}, + '55': {'OS': 'EZ-Drive','Description': 'Maxtor/MaxBlast/DriveGuide'}, + '56': {'OS': 'AT&T DOS/EZ-Drive/VFeature','Description': 'FAT12 16/EZ-BIOS/VFeature'}, + '57': {'OS': 'DrivePro','Description': 'VNDI partition'}, + '5C': {'OS': 'EDISK','Description': 'Priam EDisk Volume'}, + '61': {'OS': 'SpeedStor','Description': 'Unknown'}, + '63': {'OS': 'Unix','Description': 'Unix,ISC,SysV,ix,BSD,HURD'}, + '64': {'OS': 'SpeedStor / NetWare','Description': 'NetWare FS 286/2,PC-ARMOUR'}, + '65': {'OS': 'NetWare','Description': 'NetWare File System 386'}, + '66': {'OS': 'NetWare / NetWare','Description': 'NetWare FS 386 / SMS'}, + '67': {'OS': 'NetWare','Description': 'Wolf Mountain'}, + '68': {'OS': 'NetWare','Description': 'Unknown'}, + '69': {'OS': 'NetWare 5 / NetWare','Description': 'Novell Storage Services'}, + '6E': {'Description': 'Unknown'}, + '70': {'OS': 'DiskSecure','Description': 'DiskSecure multiboot'}, + '71': {'OS': 'Microsoft, IBM','Description': 'Reserved'}, + '72': {'OS': 'APTI systems / Unix V7/x86','Description': 'APTI altFAT12 / V7 / x86'}, + '73': {'OS': 'Microsoft, IBM','Description': 'Reserved'}, + '74': {'OS': 'Microsoft, IBM','Description': 'Reserved / Scramdisk'}, + '75': {'OS': 'PC/IX','Description': 'Unknown'}, + '76': {'OS': 'Microsoft, IBM','Description': 'Reserved'}, + '77': {'OS': 'Novell','Description': 'VNDI, M2FS, M2CS'}, + '78': {'OS': 'Geurt Vos','Description': 'XOSL bootloader file system'}, + '79': {'OS': 'APTI conformant systems','Description': 'APTI altFAT16 (CHS, SFN)'}, + '7A': {'OS': 'APTI conformant systems','Description': 'APTI altFAT16 (LBA, SFN)'}, + '7B': {'OS': 'APTI conformant systems','Description': 'APTI altFAT16B (CHS, SFN)'}, + '7C': {'OS': 'APTI conformant systems','Description': 'APTI altFAT32 (LBA, SFN)'}, + '7D': {'OS': 'APTI conformant systems','Description': 'APTI altFAT32 (CHS, SFN)'}, + '7E': {'OS': 'F.I.X. (claim) / PrimoCache','Description': 'Level 2 cache'}, + '7F': {'OS': 'Varies','Description': 'AltOS DevPartition Standard'}, + '80': {'OS': 'Minix 1.1-1.4a','Description': 'Minix file system (old)'}, + '81': {'OS': 'Minix 1.4b+ / Linux','Description': 'MINIX FS/Mitac AdvDiskManager'}, + '82': {'OS': 'Linux / Sun Microsystems','Description': 'Swap / Solaris x86 / Prime'}, + '83': {'OS': 'GNU/Linux','Description': 'Any native Linux FS'}, + '84': {'OS': 'OS/2 / Windows 7','Description': 'Hibernat/HiddenC/RapidStart'}, + '85': {'OS': 'GNU/Linux','Description': 'Linux extended'}, + '86': {'OS': 'Windows NT 4 Server / Linux','Description': 'FAT16B mirror/LinuxRAID-old'}, + '87': {'OS': 'Windows NT 4 Server','Description': 'HPFS/NTFS mirrored volume'}, + '88': {'OS': 'GNU/Linux','Description': 'Plaintext partition table'}, + '8A': {'OS': 'AiR-BOOT','Description': 'Linux kernel image'}, + '8B': {'OS': 'Windows NT 4 Server','Description': 'FAT32 mirrored volume set'}, + '8C': {'OS': 'Windows NT 4 Server','Description': 'FAT32 mirrored volume set'}, + '8D': {'OS': 'Free FDISK','Description': 'Hidden FAT12'}, + '8E': {'OS': 'Linux','Description': 'Linux LVM'}, + '90': {'OS': 'Free FDISK','Description': 'Hidden FAT16'}, + '91': {'OS': 'Free FDISK','Description': 'Hidden extended partition'}, + '92': {'OS': 'Free FDISK','Description': 'Hidden FAT16B'}, + '93': {'OS': 'Amoeba / Linux','Description': 'Amoeba native/Hidden Linux'}, + '94': {'OS': 'Amoeba','Description': 'Amoeba bad block table'}, + '95': {'OS': 'EXOPC','Description': 'EXOPC native'}, + '96': {'OS': 'CHRP','Description': 'ISO-9660 file system'}, + '97': {'OS': 'Free FDISK','Description': 'Hidden FAT32'}, + '98': {'OS': 'Free FDISK / ROM-DOS','Description': 'Hidden FAT32 / service part'}, + '99': {'OS': 'early Unix','Description': 'Unknown'}, + '9A': {'OS': 'Free FDISK','Description': 'Hidden FAT16'}, + '9B': {'OS': 'Free FDISK','Description': 'Hidden extended partition'}, + '9E': {'OS': 'VSTA / ForthOS','Description': 'ForthOS (eForth port)'}, + '9F': {'OS': 'BSD/OS 3.0+, BSDI','Description': 'Unknown'}, + 'A0': {'OS': 'HP/Phoenix/IBM/Toshiba/Sony','Description': 'Diagnostic for HP/Hibernate'}, + 'A1': {'OS': 'HP / Phoenix, NEC','Description': 'HP Vol Expansion/Hibernate'}, + 'A2': {'OS': 'Cyclone V','Description': 'Hard Processor System (HPS)'}, + 'A3': {'OS': 'HP','Description': 'HP Vol Expansion(SpeedStor)'}, + 'A4': {'OS': 'HP','Description': 'HP Vol Expansion(SpeedStor)'}, + 'A5': {'OS': 'BSD','Description': 'BSD slice'}, + 'A6': {'OS': 'OpenBSD','Description': 'HP Vol Expansion/BSD slice'}, + 'A7': {'OS': 'NeXT','Description': 'NeXTSTEP'}, + 'A8': {'OS': 'Darwin, Mac OS X','Description': 'Apple Darwin, Mac OS X UFS'}, + 'A9': {'OS': 'NetBSD','Description': 'NetBSD slice'}, + 'AA': {'OS': 'MS-DOS','Description': 'Olivetti DOS FAT12(1.44 MB)'}, + 'AB': {'OS': 'Darwin, Mac OS X / GO! OS','Description': 'Apple Darwin/OS X boot/GO!'}, + 'AD': {'OS': 'RISC OS','Description': 'ADFS / FileCore format'}, + 'AE': {'OS': 'ShagOS','Description': 'ShagOS file system'}, + 'AF': {'OS': 'ShagOS','Description': 'OS X HFS & HFS+/ShagOS Swap'}, + 'B0': {'OS': 'Boot-Star','Description': 'Boot-Star dummy partition'}, + 'B1': {'OS': 'QNX 6.x','Description': 'HPVolExpansion/QNX Neutrino'}, + 'B2': {'OS': 'QNX 6.x','Description': 'QNX Neutrino power-safe FS'}, + 'B3': {'OS': 'QNX 6.x','Description': 'HPVolExpansion/QNX Neutrino'}, + 'B4': {'OS': 'HP','Description': 'HP Vol Expansion(SpeedStor)'}, + 'B6': {'OS': 'Windows NT 4 Server','Description': 'HPVolExpansion/FAT16Bmirror'}, + 'B7': {'OS': 'BSDI / Windows NT 4 Server','Description': 'BSDI,Swap,HPFS/NTFS mirror'}, + 'B8': {'OS': 'BSDI (before 3.0)','Description': 'BSDI Swap / native FS'}, + 'BB': {'OS': 'Acronis/BootWizard/WinNT 4','Description': 'BootWizard/OEM/FAT32 mirror'}, + 'BC': {'OS': 'Acronis/WinNT/BackupCapsule','Description': 'FAT32RAID/SecureZone/Backup'}, + 'BD': {'OS': 'BonnyDOS/286','Description': 'Unknown'}, + 'BE': {'OS': 'Solaris 8','Description': 'Solaris 8 boot'}, + 'BF': {'OS': 'Solaris','Description': 'Solaris x86'}, + 'C0': {'OS': 'DR-DOS,MultiuserDOS,REAL/32','Description': 'Secured FAT (under 32 MB)'}, + 'C1': {'OS': 'DR DOS','Description': 'Secured FAT12'}, + 'C2': {'OS': 'Power Boot','Description': 'Hidden Linux native FS'}, + 'C3': {'OS': 'Power Boot','Description': 'Hidden Linux Swap'}, + 'C4': {'OS': 'DR DOS','Description': 'Secured FAT16'}, + 'C5': {'OS': 'DR DOS','Description': 'Secured extended partition'}, + 'C6': {'OS': 'DR DOS / WinNT 4 Server','Description': 'Secured FAT16B/FAT16Bmirror'}, + 'C7': {'OS': 'Syrinx / WinNT 4 Server','Description': 'Syrinx boot/HPFS/NTFSmirror'}, + 'C8': {'Description': "DR-DOS Reserved (since '97)"}, + 'C9': {'Description': "DR-DOS Reserved (since '97)"}, + 'CA': {'Description': "DR-DOS Reserved (since '97)"}, + 'CB': {'OS': 'DR-DOSx / WinNT 4 Server','Description': 'Secured FAT32/FAT32 mirror'}, + 'CC': {'OS': 'DR-DOSx / WinNT 4 Server','Description': 'Secured FAT32/FAT32 mirror'}, + 'CD': {'OS': 'CTOS','Description': 'Memory dump'}, + 'CE': {'OS': 'DR-DOSx','Description': 'Secured FAT16B'}, + 'CF': {'OS': 'DR-DOSx','Description': 'Secured extended partition'}, + 'D0': {'OS': 'Multiuser DOS, REAL/32','Description': 'Secured FAT (over 32 MB)'}, + 'D1': {'OS': 'Multiuser DOS','Description': 'Secured FAT12'}, + 'D4': {'OS': 'Multiuser DOS','Description': 'Secured FAT16'}, + 'D5': {'OS': 'Multiuser DOS','Description': 'Secured extended partition'}, + 'D6': {'OS': 'Multiuser DOS','Description': 'Secured FAT16B'}, + 'D8': {'OS': 'Digital Research','Description': 'CP/M-86 [citation needed]'}, + 'DA': {'OS': 'Powercopy Backup','Description': 'Non-FS data / Shielded disk'}, + 'DB': {'OS': 'CP/M-86/CDOS/CTOS/D800/DRMK','Description': 'CP/M-86/ConcDOS/Boot/FAT32'}, + 'DD': {'OS': 'CTOS','Description': 'Hidden memory dump'}, + 'DE': {'OS': 'Dell','Description': 'FAT16 utility/diagnostic'}, + 'DF': {'OS': 'DG/UX / BootIt / Aviion','Description': 'DG/UX Virt DiskMan / EMBRM'}, + 'E0': {'OS': 'STMicroelectronics','Description': 'ST AVFS'}, + 'E1': {'OS': 'SpeedStor','Description': 'ExtendedFAT12 >1023cylinder'}, + 'E2': {'Description': 'DOS read-only (XFDISK)'}, + 'E3': {'OS': 'SpeedStor','Description': 'DOS read-only'}, + 'E4': {'OS': 'SpeedStor','Description': 'ExtendedFAT16 <1024cylinder'}, + 'E5': {'OS': 'Tandy MS-DOS','Description': 'Logical FAT12 or FAT16'}, + 'E6': {'OS': 'SpeedStor','Description': 'Unknown'}, + 'E8': {'OS': 'LUKS','Description': 'Linux Unified Key Setup'}, + 'EB': {'OS': 'BeOS, Haiku','Description': 'BFS'}, + 'EC': {'OS': 'SkyOS','Description': 'SkyFS'}, + 'ED': {'OS': 'Sprytix / EDD 4','Description': 'EDC loader / GPT hybrid MBR'}, + 'EE': {'OS': 'EFI','Description': 'GPT protective MBR'}, + 'EF': {'OS': 'EFI','Description': 'EFI system partition'}, + 'F0': {'OS': 'Linux / OS/32','Description': 'PA-RISC Linux boot loader.'}, + 'F1': {'OS': 'SpeedStor','Description': 'Unknown'}, + 'F2': {'OS': 'SperryIT DOS/Unisys DOS','Description': 'Logical FAT12/FAT16'}, + 'F3': {'OS': 'SpeedStor','Description': 'Unknown'}, + 'F4': {'OS': 'SpeedStor / Prologue','Description': '"large"DOS part/NGF/TwinFS'}, + 'F5': {'OS': 'Prologue','Description': 'MD0-MD9 part for NGF/TwinFS'}, + 'F6': {'OS': 'SpeedStor','Description': 'Unknown'}, + 'F7': {'OS': 'O.S.G. / X1','Description': 'EFAT / Solid State FS'}, + 'F9': {'OS': 'Linux','Description': 'pCache ext2/ext3 cache'}, + 'FA': {'OS': 'Bochs','Description': 'x86 emulator'}, + 'FB': {'OS': 'VMware','Description': 'VMware VMFS partition'}, + 'FC': {'OS': 'VMware','Description': 'Swap / VMKCORE kernel dump'}, + 'FD': {'OS': 'Linux / FreeDOS','Description': 'LinuxRAID/Reserved4FreeDOS'}, + 'FE': {'OS': 'SpeedStor/LANstep/NT/Linux','Description': 'PS/2/DiskAdmin/old LinuxLVM'}, + 'FF': {'OS': 'XENIX','Description': 'XENIX bad block table'}, + '00000000-0000-0000-0000-000000000000': {'Description': 'Unused entry'}, + '024DEE41-33E7-11D3-9D69-0008C781F39F': {'Description': 'MBR partition scheme'}, + 'C12A7328-F81F-11D2-BA4B-00A0C93EC93B': {'Description': 'EFI System partition'}, + '21686148-6449-6E6F-744E-656564454649': {'Description': 'BIOS Boot partition'}, + 'D3BFE2DE-3DAF-11DF-BA40-E3A556D89593': {'Description': 'Intel Fast Flash (iFFS) partition (for Intel Rapid Start technology)'}, + 'F4019732-066E-4E12-8273-346C5641494F': {'Description': 'Sony boot partition'}, + 'BFBFAFE7-A34F-448A-9A5B-6213EB736C22': {'Description': 'Lenovo boot partition'}, + 'E3C9E316-0B5C-4DB8-817D-F92DF00215AE': {'OS': 'Windows', 'Description': 'Microsoft Reserved Partition (MSR)'}, + 'EBD0A0A2-B9E5-4433-87C0-68B6B72699C7': {'OS': 'Windows', 'Description': 'Basic data partition'}, + '5808C8AA-7E8F-42E0-85D2-E1E90434CFB3': {'OS': 'Windows', 'Description': 'Logical Disk Manager (LDM) metadata partition'}, + 'AF9B60A0-1431-4F62-BC68-3311714A69AD': {'OS': 'Windows', 'Description': 'Logical Disk Manager data partition'}, + 'DE94BBA4-06D1-4D40-A16A-BFD50179D6AC': {'OS': 'Windows', 'Description': 'Windows Recovery Environment'}, + '37AFFC90-EF7D-4E96-91C3-2D7AE055B174': {'OS': 'Windows', 'Description': 'IBM General Parallel File System (GPFS) partition'}, + 'E75CAF8F-F680-4CEE-AFA3-B001E56EFC2D': {'OS': 'Windows', 'Description': 'Storage Spaces partition'}, + '75894C1E-3AEB-11D3-B7C1-7B03A0000000': {'OS': 'HP-UX', 'Description': 'Data partition'}, + 'E2A1E728-32E3-11D6-A682-7B03A0000000': {'OS': 'HP-UX', 'Description': 'Service Partition'}, + '0FC63DAF-8483-4772-8E79-3D69D8477DE4': {'OS': 'Linux', 'Description': 'Linux filesystem data'}, + 'A19D880F-05FC-4D3B-A006-743F0F84911E': {'OS': 'Linux', 'Description': 'RAID partition'}, + '44479540-F297-41B2-9AF7-D131D5F0458A': {'OS': 'Linux', 'Description': 'Root partition (x86)'}, + '4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709': {'OS': 'Linux', 'Description': 'Root partition (x86-64)'}, + '69DAD710-2CE4-4E3C-B16C-21A1D49ABED3': {'OS': 'Linux', 'Description': 'Root partition (32-bit ARM)'}, + 'B921B045-1DF0-41C3-AF44-4C6F280D3FAE': {'OS': 'Linux', 'Description': 'Root partition (64-bit ARM)/AArch64)'}, + '0657FD6D-A4AB-43C4-84E5-0933C84B4F4F': {'OS': 'Linux', 'Description': 'Swap partition'}, + 'E6D6D379-F507-44C2-A23C-238F2A3DF928': {'OS': 'Linux', 'Description': 'Logical Volume Manager (LVM) partition'}, + '933AC7E1-2EB4-4F13-B844-0E14E2AEF915': {'OS': 'Linux', 'Description': '/home partition'}, + '3B8F8425-20E0-4F3B-907F-1A25A76F98E8': {'OS': 'Linux', 'Description': '/srv (server data) partition'}, + '7FFEC5C9-2D00-49B7-8941-3EA10A5586B7': {'OS': 'Linux', 'Description': 'Plain dm-crypt partition'}, + 'CA7D7CCB-63ED-4C53-861C-1742536059CC': {'OS': 'Linux', 'Description': 'LUKS partition'}, + '8DA63339-0007-60C0-C436-083AC8230908': {'OS': 'Linux', 'Description': 'Reserved'}, + '83BD6B9D-7F41-11DC-BE0B-001560B84F0F': {'OS': 'FreeBSD', 'Description': 'Boot partition'}, + '516E7CB4-6ECF-11D6-8FF8-00022D09712B': {'OS': 'FreeBSD', 'Description': 'Data partition'}, + '516E7CB5-6ECF-11D6-8FF8-00022D09712B': {'OS': 'FreeBSD', 'Description': 'Swap partition'}, + '516E7CB6-6ECF-11D6-8FF8-00022D09712B': {'OS': 'FreeBSD', 'Description': 'Unix File System (UFS) partition'}, + '516E7CB8-6ECF-11D6-8FF8-00022D09712B': {'OS': 'FreeBSD', 'Description': 'Vinum volume manager partition'}, + '516E7CBA-6ECF-11D6-8FF8-00022D09712B': {'OS': 'FreeBSD', 'Description': 'ZFS partition'}, + '48465300-0000-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Hierarchical File System Plus (HFS+) partition'}, + '55465300-0000-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple UFS'}, + '6A898CC3-1DD2-11B2-99A6-080020736631': {'OS': 'OS X Darwin', 'Description': 'ZFS'}, + '52414944-0000-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple RAID partition'}, + '52414944-5F4F-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple RAID partition, offline'}, + '426F6F74-0000-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple Boot partition (Recovery HD)'}, + '4C616265-6C00-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple Label'}, + '5265636F-7665-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple TV Recovery partition'}, + '53746F72-6167-11AA-AA11-00306543ECAC': {'OS': 'OS X Darwin', 'Description': 'Apple Core Storage (i.e. Lion FileVault) partition'}, + '6A82CB45-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Boot partition'}, + '6A85CF4D-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Root partition'}, + '6A87C46F-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Swap partition'}, + '6A8B642B-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Backup partition'}, + '6A898CC3-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': '/usr partition'}, + '6A8EF2E9-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': '/var partition'}, + '6A90BA39-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': '/home partition'}, + '6A9283A5-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Alternate sector'}, + '6A945A3B-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos', 'Description': 'Reserved partition'}, + '6A9630D1-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos'}, + '6A980767-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos'}, + '6A96237F-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos'}, + '6A8D2AC7-1DD2-11B2-99A6-080020736631': {'OS': 'Solaris illumos'}, + '49F48D32-B10E-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'Swap partition'}, + '49F48D5A-B10E-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'FFS partition'}, + '49F48D82-B10E-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'LFS partition'}, + '49F48DAA-B10E-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'RAID partition'}, + '2DB519C4-B10F-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'Concatenated partition'}, + '2DB519EC-B10F-11DC-B99B-0019D1879648': {'OS': 'NetBSD', 'Description': 'Encrypted partition'}, + 'FE3A2A5D-4F32-41A7-B725-ACCC3285A309': {'OS': 'ChromeOS', 'Description': 'ChromeOS kernel'}, + '3CB8E202-3B7E-47DD-8A3C-7FF2A13CFCEC': {'OS': 'ChromeOS', 'Description': 'ChromeOS rootfs'}, + '2E0A753D-9E48-43B0-8337-B15192CB1B5E': {'OS': 'ChromeOS', 'Description': 'ChromeOS future use'}, + '42465331-3BA3-10F1-802A-4861696B7521': {'OS': 'Haiku', 'Description': 'Haiku BFS'}, + '85D5E45E-237C-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'Boot partition'}, + '85D5E45A-237C-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'Data partition'}, + '85D5E45B-237C-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'Swap partition'}, + '0394EF8B-237E-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'Unix File System (UFS) partition'}, + '85D5E45C-237C-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'Vinum volume manager partition'}, + '85D5E45D-237C-11E1-B4B3-E89A8F7FC3A7': {'OS': 'MidnightBSD', 'Description': 'ZFS partition'}, + '45B0969E-9B03-4F30-B4C6-B4B80CEFF106': {'OS': 'Ceph', 'Description': 'Ceph Journal'}, + '45B0969E-9B03-4F30-B4C6-5EC00CEFF106': {'OS': 'Ceph', 'Description': 'Ceph dm-crypt Encrypted Journal'}, + '4FBD7E29-9D25-41B8-AFD0-062C0CEFF05D': {'OS': 'Ceph', 'Description': 'Ceph OSD'}, + '4FBD7E29-9D25-41B8-AFD0-5EC00CEFF05D': {'OS': 'Ceph', 'Description': 'Ceph dm-crypt OSD'}, + '89C57F98-2FE5-4DC0-89C1-F3AD0CEFF2BE': {'OS': 'Ceph', 'Description': 'Ceph disk in creation'}, + '89C57F98-2FE5-4DC0-89C1-5EC00CEFF2BE': {'OS': 'Ceph', 'Description': 'Ceph dm-crypt disk in creation'}, + '824CC7A0-36A8-11E3-890A-952519AD3F61': {'OS': 'OpenBSD', 'Description': 'Data partition'}, + 'CEF5A9AD-73BC-4601-89F3-CDEEEEE321A1': {'OS': 'QNX', 'Description': 'Power-safe (QNX6) file system'}, + 'C91818F9-8025-47AF-89D2-F030D7000C2C': {'OS': 'Plan 9', 'Description': 'Plan 9 partition'}, + '9D275380-40AD-11DB-BF97-000C2911D1B8': {'OS': 'VMware ESX', 'Description': 'vmkcore (coredump partition)'}, + 'AA31E02A-400F-11DB-9590-000C2911D1B8': {'OS': 'VMware ESX', 'Description': 'VMFS filesystem partition'}, + '9198EFFC-31C0-11DB-8F78-000C2911D1B8': {'OS': 'VMware ESX', 'Description': 'VMware Reserved'}, + '2568845D-2332-4675-BC39-8FA5A4748D15': {'OS': 'Android-IA', 'Description': 'Bootloader'}, + '114EAFFE-1552-4022-B26E-9B053604CF84': {'OS': 'Android-IA', 'Description': 'Bootloader2'}, + '49A4D17F-93A3-45C1-A0DE-F50B2EBE2599': {'OS': 'Android-IA', 'Description': 'Boot'}, + '4177C722-9E92-4AAB-8644-43502BFD5506': {'OS': 'Android-IA', 'Description': 'Recovery'}, + 'EF32A33B-A409-486C-9141-9FFB711F6266': {'OS': 'Android-IA', 'Description': 'Misc'}, + '20AC26BE-20B7-11E3-84C5-6CFDB94711E9': {'OS': 'Android-IA', 'Description': 'Metadata'}, + '38F428E6-D326-425D-9140-6E0EA133647C': {'OS': 'Android-IA', 'Description': 'System'}, + 'A893EF21-E428-470A-9E55-0668FD91A2D9': {'OS': 'Android-IA', 'Description': 'Cache'}, + 'DC76DDA9-5AC1-491C-AF42-A82591580C0D': {'OS': 'Android-IA', 'Description': 'Data'}, + 'EBC597D0-2053-4B15-8B64-E0AAC75F4DB1': {'OS': 'Android-IA', 'Description': 'Persistent'}, + '8F68CC74-C5E5-48DA-BE91-A0C8C15E9C80': {'OS': 'Android-IA', 'Description': 'Factory'}, + '767941D0-2085-11E3-AD3B-6CFDB94711E9': {'OS': 'Android-IA', 'Description': 'Fastboot / Tertiary'}, + 'AC6D7924-EB71-4DF8-B48D-E267B27148FF': {'OS': 'Android-IA', 'Description': 'OEM'}, + '7412F7D5-A156-4B13-81DC-867174929325': {'OS': 'ONIE', 'Description': 'Boot'}, + 'D4E6E2CD-4469-46F3-B5CB-1BFF57AFC149': {'OS': 'ONIE', 'Description': 'Config'}, + '9E1A2D38-C612-4316-AA26-8B49521E5A8B': {'OS': 'PowerPC', 'Description': 'PReP boot'}, + 'BC13C2FF-59E6-4262-A352-B275FD6F7172': {'OS': 'Freedesktop', 'Description': 'Extended Boot Partition ($BOOT)'}, +} + +if __name__ == '__main__': + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From 72eac47524f33fbc3b1b6a7aff0d36fc4ce31901 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 20:05:53 -0700 Subject: [PATCH 167/265] Updated disk.py --- .bin/Scripts/functions/disk.py | 636 +++++++++++++++++---------------- 1 file changed, 319 insertions(+), 317 deletions(-) diff --git a/.bin/Scripts/functions/disk.py b/.bin/Scripts/functions/disk.py index 257f21b0..88b26155 100644 --- a/.bin/Scripts/functions/disk.py +++ b/.bin/Scripts/functions/disk.py @@ -6,390 +6,392 @@ from settings.partition_uids import * # Regex REGEX_BAD_PARTITION = re.compile(r'(RAW|Unknown)', re.IGNORECASE) REGEX_DISK_GPT = re.compile( - r'Disk ID: {[A-Z0-9]+-[A-Z0-9]+-[A-Z0-9]+-[A-Z0-9]+-[A-Z0-9]+}', - re.IGNORECASE) + r'Disk ID: {[A-Z0-9]+-[A-Z0-9]+-[A-Z0-9]+-[A-Z0-9]+-[A-Z0-9]+}', + re.IGNORECASE) REGEX_DISK_MBR = re.compile(r'Disk ID: [A-Z0-9]+', re.IGNORECASE) REGEX_DISK_RAW = re.compile(r'Disk ID: 00000000', re.IGNORECASE) def assign_volume_letters(): - """Assign a volume letter to all available volumes.""" - remove_volume_letters() + """Assign a volume letter to all available volumes.""" + remove_volume_letters() - # Write script - script = [] - for vol in get_volumes(): - script.append('select volume {}'.format(vol['Number'])) - script.append('assign') + # Write script + script = [] + for vol in get_volumes(): + script.append('select volume {}'.format(vol['Number'])) + script.append('assign') - # Run - run_diskpart(script) + # Run + run_diskpart(script) def get_boot_mode(): - """Check if the boot mode was UEFI or legacy.""" - boot_mode = 'Legacy' - try: - reg_key = winreg.OpenKey( - winreg.HKEY_LOCAL_MACHINE, r'System\CurrentControlSet\Control') - reg_value = winreg.QueryValueEx(reg_key, 'PEFirmwareType')[0] - if reg_value == 2: - boot_mode = 'UEFI' - except: - boot_mode = 'Unknown' + """Check if the boot mode was UEFI or legacy.""" + boot_mode = 'Legacy' + try: + reg_key = winreg.OpenKey( + winreg.HKEY_LOCAL_MACHINE, r'System\CurrentControlSet\Control') + reg_value = winreg.QueryValueEx(reg_key, 'PEFirmwareType')[0] + if reg_value == 2: + boot_mode = 'UEFI' + except: + boot_mode = 'Unknown' - return boot_mode + return boot_mode def get_disk_details(disk): - """Get disk details using DiskPart.""" - details = {} - script = [ - 'select disk {}'.format(disk['Number']), - 'detail disk'] + """Get disk details using DiskPart.""" + details = {} + script = [ + 'select disk {}'.format(disk['Number']), + 'detail disk'] - # Run - try: - result = run_diskpart(script) - except subprocess.CalledProcessError: - pass - else: - output = result.stdout.decode().strip() - # Remove empty lines - tmp = [s.strip() for s in output.splitlines() if s.strip() != ''] - # Set disk name - details['Name'] = tmp[4] - # Split each line on ':' skipping those without ':' - tmp = [s.split(':') for s in tmp if ':' in s] - # Add key/value pairs to the details variable and return dict - details.update({key.strip(): value.strip() for (key, value) in tmp}) + # Run + try: + result = run_diskpart(script) + except subprocess.CalledProcessError: + pass + else: + output = result.stdout.decode().strip() + # Remove empty lines + tmp = [s.strip() for s in output.splitlines() if s.strip() != ''] + # Set disk name + details['Name'] = tmp[4] + # Split each line on ':' skipping those without ':' + tmp = [s.split(':') for s in tmp if ':' in s] + # Add key/value pairs to the details variable and return dict + details.update({key.strip(): value.strip() for (key, value) in tmp}) - return details + return details def get_disks(): - """Get list of attached disks using DiskPart.""" - disks = [] + """Get list of attached disks using DiskPart.""" + disks = [] - try: - # Run script - result = run_diskpart(['list disk']) - except subprocess.CalledProcessError: - pass - else: - # Append disk numbers - output = result.stdout.decode().strip() - for tmp in re.findall(r'Disk (\d+)\s+\w+\s+(\d+\s+\w+)', output): - num = tmp[0] - size = human_readable_size(tmp[1]) - disks.append({'Number': num, 'Size': size}) + try: + # Run script + result = run_diskpart(['list disk']) + except subprocess.CalledProcessError: + pass + else: + # Append disk numbers + output = result.stdout.decode().strip() + for tmp in re.findall(r'Disk (\d+)\s+\w+\s+(\d+\s+\w+)', output): + num = tmp[0] + size = human_readable_size(tmp[1]) + disks.append({'Number': num, 'Size': size}) - return disks + return disks def get_partition_details(disk, partition): - """Get partition details using DiskPart and fsutil.""" - details = {} - script = [ - 'select disk {}'.format(disk['Number']), - 'select partition {}'.format(partition['Number']), - 'detail partition'] + """Get partition details using DiskPart and fsutil.""" + details = {} + script = [ + 'select disk {}'.format(disk['Number']), + 'select partition {}'.format(partition['Number']), + 'detail partition'] - # Diskpart details + # Diskpart details + try: + # Run script + result = run_diskpart(script) + except subprocess.CalledProcessError: + pass + else: + # Get volume letter or RAW status + output = result.stdout.decode().strip() + tmp = re.search(r'Volume\s+\d+\s+(\w|RAW)\s+', output) + if tmp: + if tmp.group(1).upper() == 'RAW': + details['FileSystem'] = RAW + else: + details['Letter'] = tmp.group(1) + # Remove empty lines from output + tmp = [s.strip() for s in output.splitlines() if s.strip() != ''] + # Split each line on ':' skipping those without ':' + tmp = [s.split(':') for s in tmp if ':' in s] + # Add key/value pairs to the details variable and return dict + details.update({key.strip(): value.strip() for (key, value) in tmp}) + + # Get MBR type / GPT GUID for extra details on "Unknown" partitions + guid = PARTITION_UIDS.get(details.get('Type').upper(), {}) + if guid: + details.update({ + 'Description': guid.get('Description', '')[:29], + 'OS': guid.get('OS', 'Unknown')[:27]}) + + if 'Letter' in details: + # Disk usage try: - # Run script - result = run_diskpart(script) - except subprocess.CalledProcessError: - pass + tmp = psutil.disk_usage('{}:\\'.format(details['Letter'])) + except OSError as err: + details['FileSystem'] = 'Unknown' + details['Error'] = err.strerror else: - # Get volume letter or RAW status - output = result.stdout.decode().strip() - tmp = re.search(r'Volume\s+\d+\s+(\w|RAW)\s+', output) - if tmp: - if tmp.group(1).upper() == 'RAW': - details['FileSystem'] = RAW - else: - details['Letter'] = tmp.group(1) - # Remove empty lines from output - tmp = [s.strip() for s in output.splitlines() if s.strip() != ''] - # Split each line on ':' skipping those without ':' - tmp = [s.split(':') for s in tmp if ':' in s] - # Add key/value pairs to the details variable and return dict - details.update({key.strip(): value.strip() for (key, value) in tmp}) + details['Used Space'] = human_readable_size(tmp.used) - # Get MBR type / GPT GUID for extra details on "Unknown" partitions - guid = PARTITION_UIDS.get(details.get('Type').upper(), {}) - if guid: - details.update({ - 'Description': guid.get('Description', '')[:29], - 'OS': guid.get('OS', 'Unknown')[:27]}) + # fsutil details + cmd = [ + 'fsutil', + 'fsinfo', + 'volumeinfo', + '{}:'.format(details['Letter']) + ] + try: + result = run_program(cmd) + except subprocess.CalledProcessError: + pass + else: + output = result.stdout.decode().strip() + # Remove empty lines from output + tmp = [s.strip() for s in output.splitlines() if s.strip() != ''] + # Add "Feature" lines + details['File System Features'] = [s.strip() for s in tmp + if ':' not in s] + # Split each line on ':' skipping those without ':' + tmp = [s.split(':') for s in tmp if ':' in s] + # Add key/value pairs to the details variable and return dict + details.update({key.strip(): value.strip() for (key, value) in tmp}) - if 'Letter' in details: - # Disk usage - try: - tmp = psutil.disk_usage('{}:\\'.format(details['Letter'])) - except OSError as err: - details['FileSystem'] = 'Unknown' - details['Error'] = err.strerror - else: - details['Used Space'] = human_readable_size(tmp.used) + # Set Volume Name + details['Name'] = details.get('Volume Name', '') - # fsutil details - cmd = [ - 'fsutil', - 'fsinfo', - 'volumeinfo', - '{}:'.format(details['Letter']) - ] - try: - result = run_program(cmd) - except subprocess.CalledProcessError: - pass - else: - output = result.stdout.decode().strip() - # Remove empty lines from output - tmp = [s.strip() for s in output.splitlines() if s.strip() != ''] - # Add "Feature" lines - details['File System Features'] = [s.strip() for s in tmp - if ':' not in s] - # Split each line on ':' skipping those without ':' - tmp = [s.split(':') for s in tmp if ':' in s] - # Add key/value pairs to the details variable and return dict - details.update({key.strip(): value.strip() for (key, value) in tmp}) + # Set FileSystem Type + if details.get('FileSystem', '') not in ['RAW', 'Unknown']: + details['FileSystem'] = details.get('File System Name', 'Unknown') - # Set Volume Name - details['Name'] = details.get('Volume Name', '') - - # Set FileSystem Type - if details.get('FileSystem', '') not in ['RAW', 'Unknown']: - details['FileSystem'] = details.get('File System Name', 'Unknown') - - return details + return details def get_partitions(disk): - """Get list of partition using DiskPart.""" - partitions = [] - script = [ - 'select disk {}'.format(disk['Number']), - 'list partition'] + """Get list of partition using DiskPart.""" + partitions = [] + script = [ + 'select disk {}'.format(disk['Number']), + 'list partition'] - try: - # Run script - result = run_diskpart(script) - except subprocess.CalledProcessError: - pass - else: - # Append partition numbers - output = result.stdout.decode().strip() - regex = r'Partition\s+(\d+)\s+\w+\s+(\d+\s+\w+)\s+' - for tmp in re.findall(regex, output, re.IGNORECASE): - num = tmp[0] - size = human_readable_size(tmp[1]) - partitions.append({'Number': num, 'Size': size}) + try: + # Run script + result = run_diskpart(script) + except subprocess.CalledProcessError: + pass + else: + # Append partition numbers + output = result.stdout.decode().strip() + regex = r'Partition\s+(\d+)\s+\w+\s+(\d+\s+\w+)\s+' + for tmp in re.findall(regex, output, re.IGNORECASE): + num = tmp[0] + size = human_readable_size(tmp[1]) + partitions.append({'Number': num, 'Size': size}) - return partitions + return partitions def get_table_type(disk): - """Get disk partition table type using DiskPart.""" - part_type = 'Unknown' - script = [ - 'select disk {}'.format(disk['Number']), - 'uniqueid disk'] + """Get disk partition table type using DiskPart.""" + part_type = 'Unknown' + script = [ + 'select disk {}'.format(disk['Number']), + 'uniqueid disk'] - try: - result = run_diskpart(script) - except subprocess.CalledProcessError: - pass - else: - output = result.stdout.decode().strip() - if REGEX_DISK_GPT.search(output): - part_type = 'GPT' - elif REGEX_DISK_MBR.search(output): - part_type = 'MBR' - elif REGEX_DISK_RAW.search(output): - part_type = 'RAW' + try: + result = run_diskpart(script) + except subprocess.CalledProcessError: + pass + else: + output = result.stdout.decode().strip() + if REGEX_DISK_GPT.search(output): + part_type = 'GPT' + elif REGEX_DISK_MBR.search(output): + part_type = 'MBR' + elif REGEX_DISK_RAW.search(output): + part_type = 'RAW' - return part_type + return part_type def get_volumes(): - """Get list of volumes using DiskPart.""" - vols = [] - try: - result = run_diskpart(['list volume']) - except subprocess.CalledProcessError: - pass - else: - # Append volume numbers - output = result.stdout.decode().strip() - for tmp in re.findall(r'Volume (\d+)\s+([A-Za-z]?)\s+', output): - vols.append({'Number': tmp[0], 'Letter': tmp[1]}) + """Get list of volumes using DiskPart.""" + vols = [] + try: + result = run_diskpart(['list volume']) + except subprocess.CalledProcessError: + pass + else: + # Append volume numbers + output = result.stdout.decode().strip() + for tmp in re.findall(r'Volume (\d+)\s+([A-Za-z]?)\s+', output): + vols.append({'Number': tmp[0], 'Letter': tmp[1]}) - return vols + return vols def is_bad_partition(par): - """Check if the partition is accessible.""" - return 'Letter' not in par or REGEX_BAD_PARTITION.search(par['FileSystem']) + """Check if the partition is accessible.""" + return 'Letter' not in par or REGEX_BAD_PARTITION.search(par['FileSystem']) def prep_disk_for_formatting(disk=None): - """Gather details about the disk and its partitions.""" - disk['Format Warnings'] = '\n' - width = len(str(len(disk['Partitions']))) + """Gather details about the disk and its partitions.""" + disk['Format Warnings'] = '\n' + width = len(str(len(disk['Partitions']))) - # Bail early - if disk is None: - raise Exception('Disk not provided.') + # Bail early + if disk is None: + raise Exception('Disk not provided.') - # Set boot method and partition table type - disk['Use GPT'] = True - if (get_boot_mode() == 'UEFI'): - if (not ask("Setup Windows to use UEFI booting?")): - disk['Use GPT'] = False + # Set boot method and partition table type + disk['Use GPT'] = True + if (get_boot_mode() == 'UEFI'): + if (not ask("Setup Windows to use UEFI booting?")): + disk['Use GPT'] = False + else: + if (ask("Setup Windows to use BIOS/Legacy booting?")): + disk['Use GPT'] = False + + # Set Display and Warning Strings + if len(disk['Partitions']) == 0: + disk['Format Warnings'] += 'No partitions found\n' + for partition in disk['Partitions']: + display = '{size} {fs}'.format( + num = partition['Number'], + width = width, + size = partition['Size'], + fs = partition['FileSystem']) + + if is_bad_partition(partition): + # Set display string using partition description & OS type + display += '\t\t{q}{name}{q}\t{desc} ({os})'.format( + display = display, + q = '"' if partition['Name'] != '' else '', + name = partition['Name'], + desc = partition['Description'], + os = partition['OS']) else: - if (ask("Setup Windows to use BIOS/Legacy booting?")): - disk['Use GPT'] = False - - # Set Display and Warning Strings - if len(disk['Partitions']) == 0: - disk['Format Warnings'] += 'No partitions found\n' - for partition in disk['Partitions']: - display = '{size} {fs}'.format( - num = partition['Number'], - width = width, - size = partition['Size'], - fs = partition['FileSystem']) - - if is_bad_partition(partition): - # Set display string using partition description & OS type - display += '\t\t{q}{name}{q}\t{desc} ({os})'.format( - display = display, - q = '"' if partition['Name'] != '' else '', - name = partition['Name'], - desc = partition['Description'], - os = partition['OS']) - else: - # List space used instead of partition description & OS type - display += ' (Used: {used})\t{q}{name}{q}'.format( - used = partition['Used Space'], - q = '"' if partition['Name'] != '' else '', - name = partition['Name']) - # For all partitions - partition['Display String'] = display + # List space used instead of partition description & OS type + display += ' (Used: {used})\t{q}{name}{q}'.format( + used = partition['Used Space'], + q = '"' if partition['Name'] != '' else '', + name = partition['Name']) + # For all partitions + partition['Display String'] = display def reassign_volume_letter(letter, new_letter='I'): - """Assign a new letter to a volume using DiskPart.""" - if not letter: - # Ignore - return None - script = [ - 'select volume {}'.format(letter), - 'remove noerr', - 'assign letter={}'.format(new_letter)] - try: - run_diskpart(script) - except subprocess.CalledProcessError: - pass - else: - return new_letter + """Assign a new letter to a volume using DiskPart.""" + if not letter: + # Ignore + return None + script = [ + 'select volume {}'.format(letter), + 'remove noerr', + 'assign letter={}'.format(new_letter)] + try: + run_diskpart(script) + except subprocess.CalledProcessError: + pass + else: + return new_letter def remove_volume_letters(keep=None): - """Remove all assigned volume letters using DiskPart.""" - if not keep: - keep = '' + """Remove all assigned volume letters using DiskPart.""" + if not keep: + keep = '' - script = [] - for vol in get_volumes(): - if vol['Letter'].upper() != keep.upper(): - script.append('select volume {}'.format(vol['Number'])) - script.append('remove noerr') + script = [] + for vol in get_volumes(): + if vol['Letter'].upper() != keep.upper(): + script.append('select volume {}'.format(vol['Number'])) + script.append('remove noerr') - # Run script - try: - run_diskpart(script) - except subprocess.CalledProcessError: - pass + # Run script + try: + run_diskpart(script) + except subprocess.CalledProcessError: + pass def run_diskpart(script): - """Run DiskPart script.""" - tempfile = r'{}\diskpart.script'.format(global_vars['Env']['TMP']) + """Run DiskPart script.""" + tempfile = r'{}\diskpart.script'.format(global_vars['Env']['TMP']) - # Write script - with open(tempfile, 'w') as f: - for line in script: - f.write('{}\n'.format(line)) + # Write script + with open(tempfile, 'w') as f: + for line in script: + f.write('{}\n'.format(line)) - # Run script - cmd = [ - r'{}\Windows\System32\diskpart.exe'.format( - global_vars['Env']['SYSTEMDRIVE']), - '/s', tempfile] - result = run_program(cmd) - sleep(2) - return result + # Run script + cmd = [ + r'{}\Windows\System32\diskpart.exe'.format( + global_vars['Env']['SYSTEMDRIVE']), + '/s', tempfile] + result = run_program(cmd) + sleep(2) + return result def scan_disks(): - """Get details about the attached disks""" - disks = get_disks() + """Get details about the attached disks""" + disks = get_disks() - # Get disk details - for disk in disks: - # Get partition style - disk['Table'] = get_table_type(disk) + # Get disk details + for disk in disks: + # Get partition style + disk['Table'] = get_table_type(disk) - # Get disk name/model and physical details - disk.update(get_disk_details(disk)) + # Get disk name/model and physical details + disk.update(get_disk_details(disk)) - # Get partition info for disk - disk['Partitions'] = get_partitions(disk) + # Get partition info for disk + disk['Partitions'] = get_partitions(disk) - for partition in disk['Partitions']: - # Get partition details - partition.update(get_partition_details(disk, partition)) + for partition in disk['Partitions']: + # Get partition details + partition.update(get_partition_details(disk, partition)) - # Done - return disks + # Done + return disks def select_disk(title='Which disk?', disks=[]): - """Select a disk from the attached disks""" - # Build menu - disk_options = [] - for disk in disks: - display_name = '{}\t[{}] ({}) {}'.format( - disk.get('Size', ''), - disk.get('Table', ''), - disk.get('Type', ''), - disk.get('Name', 'Unknown'), - ) - pwidth=len(str(len(disk['Partitions']))) - for partition in disk['Partitions']: - # Main text - p_name = 'Partition {num:>{width}}: {size} ({fs})'.format( - num = partition['Number'], - width = pwidth, - size = partition['Size'], - fs = partition['FileSystem']) - if partition['Name']: - p_name += '\t"{}"'.format(partition['Name']) + """Select a disk from the attached disks""" + # Build menu + disk_options = [] + for disk in disks: + display_name = '{}\t[{}] ({}) {}'.format( + disk.get('Size', ''), + disk.get('Table', ''), + disk.get('Type', ''), + disk.get('Name', 'Unknown'), + ) + pwidth=len(str(len(disk['Partitions']))) + for partition in disk['Partitions']: + # Main text + p_name = 'Partition {num:>{width}}: {size} ({fs})'.format( + num = partition['Number'], + width = pwidth, + size = partition['Size'], + fs = partition['FileSystem']) + if partition['Name']: + p_name += '\t"{}"'.format(partition['Name']) - # Show unsupported partition(s) - if is_bad_partition(partition): - p_name = '{YELLOW}{p_name}{CLEAR}'.format( - p_name=p_name, **COLORS) + # Show unsupported partition(s) + if is_bad_partition(partition): + p_name = '{YELLOW}{p_name}{CLEAR}'.format( + p_name=p_name, **COLORS) - display_name += '\n\t\t\t{}'.format(p_name) - if not disk['Partitions']: - display_name += '\n\t\t\t{}No partitions found.{}'.format( - COLORS['YELLOW'], COLORS['CLEAR']) + display_name += '\n\t\t\t{}'.format(p_name) + if not disk['Partitions']: + display_name += '\n\t\t\t{}No partitions found.{}'.format( + COLORS['YELLOW'], COLORS['CLEAR']) - disk_options.append({'Name': display_name, 'Disk': disk}) - actions = [ - {'Name': 'Main Menu', 'Letter': 'M'}, - ] + disk_options.append({'Name': display_name, 'Disk': disk}) + actions = [ + {'Name': 'Main Menu', 'Letter': 'M'}, + ] - # Menu loop - selection = menu_select( - title = title, - main_entries = disk_options, - action_entries = actions) + # Menu loop + selection = menu_select( + title = title, + main_entries = disk_options, + action_entries = actions) - if (selection.isnumeric()): - return disk_options[int(selection)-1]['Disk'] - elif (selection == 'M'): - raise GenericAbort + if (selection.isnumeric()): + return disk_options[int(selection)-1]['Disk'] + elif (selection == 'M'): + raise GenericAbort if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From 82a2d6b74d5399791aedaa058eccf71ec13d9569 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 20:07:18 -0700 Subject: [PATCH 168/265] Updated product_keys.py --- .bin/Scripts/functions/product_keys.py | 174 +++++++++++++------------ 1 file changed, 88 insertions(+), 86 deletions(-) diff --git a/.bin/Scripts/functions/product_keys.py b/.bin/Scripts/functions/product_keys.py index 988d36fd..1d96ec0b 100644 --- a/.bin/Scripts/functions/product_keys.py +++ b/.bin/Scripts/functions/product_keys.py @@ -4,108 +4,110 @@ from functions.common import * # Regex REGEX_REGISTRY_DIRS = re.compile( - r'^(config$|RegBack$|System32$|Transfer|Win)', - re.IGNORECASE) + r'^(config$|RegBack$|System32$|Transfer|Win)', + re.IGNORECASE) REGEX_SOFTWARE_HIVE = re.compile(r'^Software$', re.IGNORECASE) def extract_keys(): - """Extract keys from provided hives and return a dict.""" - keys = {} + """Extract keys from provided hives and return a dict.""" + keys = {} - # Extract keys - extract_item('ProduKey', silent=True) - for hive in find_software_hives(): - cmd = [ - global_vars['Tools']['ProduKey'], - '/IEKeys', '0', - '/WindowsKeys', '1', - '/OfficeKeys', '1', - '/ExtractEdition', '1', - '/nosavereg', - '/regfile', hive, - '/scomma', ''] - try: - out = run_program(cmd) - except subprocess.CalledProcessError: - # Ignore and return empty dict - pass - else: - for line in out.stdout.decode().splitlines(): - # Add key to keys under product only if unique - tmp = line.split(',') - product = tmp[0] - key = tmp[2] - if product not in keys: - keys[product] = [] - if key not in keys[product]: - keys[product].append(key) + # Extract keys + extract_item('ProduKey', silent=True) + for hive in find_software_hives(): + cmd = [ + global_vars['Tools']['ProduKey'], + '/IEKeys', '0', + '/WindowsKeys', '1', + '/OfficeKeys', '1', + '/ExtractEdition', '1', + '/nosavereg', + '/regfile', hive, + '/scomma', ''] + try: + out = run_program(cmd) + except subprocess.CalledProcessError: + # Ignore and return empty dict + pass + else: + for line in out.stdout.decode().splitlines(): + # Add key to keys under product only if unique + tmp = line.split(',') + product = tmp[0] + key = tmp[2] + if product not in keys: + keys[product] = [] + if key not in keys[product]: + keys[product].append(key) - # Done - return keys + # Done + return keys def list_clientdir_keys(): - """List product keys found in hives inside the ClientDir.""" - keys = extract_keys() - key_list = [] - if keys: - for product in sorted(keys): - key_list.append(product) - for key in sorted(keys[product]): - key_list.append(' {key}'.format(key=key)) - else: - key_list.append('No keys found.') + """List product keys found in hives inside the ClientDir.""" + keys = extract_keys() + key_list = [] + if keys: + for product in sorted(keys): + key_list.append(product) + for key in sorted(keys[product]): + key_list.append(' {key}'.format(key=key)) + else: + key_list.append('No keys found.') - return key_list + return key_list def find_software_hives(): - """Search for transferred SW hives and return a list.""" - hives = [] - search_paths = [global_vars['ClientDir']] + """Search for transferred SW hives and return a list.""" + hives = [] + search_paths = [global_vars['ClientDir']] - while len(search_paths) > 0: - for item in os.scandir(search_paths.pop(0)): - if item.is_dir() and REGEX_REGISTRY_DIRS.search(item.name): - search_paths.append(item.path) - if item.is_file() and REGEX_SOFTWARE_HIVE.search(item.name): - hives.append(item.path) + while len(search_paths) > 0: + for item in os.scandir(search_paths.pop(0)): + if item.is_dir() and REGEX_REGISTRY_DIRS.search(item.name): + search_paths.append(item.path) + if item.is_file() and REGEX_SOFTWARE_HIVE.search(item.name): + hives.append(item.path) - return hives + return hives def get_product_keys(): - """List product keys from saved report.""" - keys = [] - log_file = r'{LogDir}\Product Keys (ProduKey).txt'.format(**global_vars) - with open (log_file, 'r') as f: - for line in f.readlines(): - if re.search(r'^Product Name', line): - line = re.sub(r'^Product Name\s+:\s+(.*)', r'\1', line.strip()) - keys.append(line) + """List product keys from saved report.""" + keys = [] + log_file = r'{LogDir}\Product Keys (ProduKey).txt'.format(**global_vars) + with open (log_file, 'r') as f: + for line in f.readlines(): + if re.search(r'^Product Name', line): + line = re.sub(r'^Product Name\s+:\s+(.*)', r'\1', line.strip()) + keys.append(line) - if keys: - return keys - else: - return ['No product keys found'] + if keys: + return keys + else: + return ['No product keys found'] def run_produkey(): - """Run ProduKey and save report in the ClientDir.""" - extract_item('ProduKey', silent=True) - log_file = r'{LogDir}\Product Keys (ProduKey).txt'.format(**global_vars) - if not os.path.exists(log_file): - # Clear current configuration - for config in ['ProduKey.cfg', 'ProduKey64.cfg']: - config = r'{BinDir}\ProduKey\{config}'.format( - config=config, **global_vars) - try: - if os.path.exists(config): - os.remove(config) - except Exception: - pass - cmd = [ - global_vars['Tools']['ProduKey'], - '/nosavereg', - '/stext', - log_file] - run_program(cmd, check=False) + """Run ProduKey and save report in the ClientDir.""" + extract_item('ProduKey', silent=True) + log_file = r'{LogDir}\Product Keys (ProduKey).txt'.format(**global_vars) + if not os.path.exists(log_file): + # Clear current configuration + for config in ['ProduKey.cfg', 'ProduKey64.cfg']: + config = r'{BinDir}\ProduKey\{config}'.format( + config=config, **global_vars) + try: + if os.path.exists(config): + os.remove(config) + except Exception: + pass + cmd = [ + global_vars['Tools']['ProduKey'], + '/nosavereg', + '/stext', + log_file] + run_program(cmd, check=False) if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From deb9d9add18737af36e64d18331cf1296426bf56 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 20:08:56 -0700 Subject: [PATCH 169/265] Updated repairs.py --- .bin/Scripts/functions/repairs.py | 212 +++++++++++++++--------------- 1 file changed, 107 insertions(+), 105 deletions(-) diff --git a/.bin/Scripts/functions/repairs.py b/.bin/Scripts/functions/repairs.py index 589dccc3..bcaa5bbf 100644 --- a/.bin/Scripts/functions/repairs.py +++ b/.bin/Scripts/functions/repairs.py @@ -3,124 +3,126 @@ from functions.common import * def run_chkdsk(repair=False): - """Run CHKDSK scan or schedule offline repairs.""" - if repair: - run_chkdsk_offline() - else: - run_chkdsk_scan() + """Run CHKDSK scan or schedule offline repairs.""" + if repair: + run_chkdsk_offline() + else: + run_chkdsk_scan() def run_chkdsk_scan(): - """Run CHKDSK in a "split window" and report errors.""" - if global_vars['OS']['Version'] in ('8', '8.1', '10'): - cmd = ['chkdsk', global_vars['Env']['SYSTEMDRIVE'], '/scan', '/perf'] - else: - cmd = ['chkdsk', global_vars['Env']['SYSTEMDRIVE']] - out = run_program(cmd, check=False) - # retcode == 0: no issues - # retcode == 1: fixed issues (also happens when chkdsk.exe is killed?) - # retcode == 2: issues - if int(out.returncode) > 0: - # print_error(' ERROR: CHKDSK encountered errors') - raise GenericError + """Run CHKDSK in a "split window" and report errors.""" + if global_vars['OS']['Version'] in ('8', '8.1', '10'): + cmd = ['chkdsk', global_vars['Env']['SYSTEMDRIVE'], '/scan', '/perf'] + else: + cmd = ['chkdsk', global_vars['Env']['SYSTEMDRIVE']] + out = run_program(cmd, check=False) + # retcode == 0: no issues + # retcode == 1: fixed issues (also happens when chkdsk.exe is killed?) + # retcode == 2: issues + if int(out.returncode) > 0: + # print_error(' ERROR: CHKDSK encountered errors') + raise GenericError - # Save stderr - with open(r'{LogDir}\Tools\CHKDSK.err'.format(**global_vars), 'a') as f: - for line in out.stderr.decode().splitlines(): - f.write(line.strip() + '\n') - # Save stdout - with open(r'{LogDir}\Tools\CHKDSK.log'.format(**global_vars), 'a') as f: - for line in out.stdout.decode().splitlines(): - f.write(line.strip() + '\n') + # Save stderr + with open(r'{LogDir}\Tools\CHKDSK.err'.format(**global_vars), 'a') as f: + for line in out.stderr.decode().splitlines(): + f.write(line.strip() + '\n') + # Save stdout + with open(r'{LogDir}\Tools\CHKDSK.log'.format(**global_vars), 'a') as f: + for line in out.stdout.decode().splitlines(): + f.write(line.strip() + '\n') def run_chkdsk_offline(): - """Set filesystem 'dirty bit' to force a chkdsk during next boot.""" - cmd = [ - 'fsutil', 'dirty', - 'set', - global_vars['Env']['SYSTEMDRIVE']] - out = run_program(cmd, check=False) - if int(out.returncode) > 0: - raise GenericError + """Set filesystem 'dirty bit' to force a chkdsk during next boot.""" + cmd = [ + 'fsutil', 'dirty', + 'set', + global_vars['Env']['SYSTEMDRIVE']] + out = run_program(cmd, check=False) + if int(out.returncode) > 0: + raise GenericError def run_dism(repair=False): - """Run DISM /RestoreHealth, then /CheckHealth, and then report errors.""" - if global_vars['OS']['Version'] in ('8', '8.1', '10'): - if repair: - # Restore Health - cmd = [ - 'DISM', '/Online', - '/Cleanup-Image', '/RestoreHealth', - r'/LogPath:"{LogDir}\Tools\DISM_RestoreHealth.log"'.format( - **global_vars), - '-new_console:n', '-new_console:s33V'] - else: - # Scan Health - cmd = [ - 'DISM', '/Online', - '/Cleanup-Image', '/ScanHealth', - r'/LogPath:"{LogDir}\Tools\DISM_ScanHealth.log"'.format( - **global_vars), - '-new_console:n', '-new_console:s33V'] - run_program(cmd, pipe=False, check=False, shell=True) - wait_for_process('dism') - # Now check health - cmd = [ - 'DISM', '/Online', - '/Cleanup-Image', '/CheckHealth', - r'/LogPath:"{LogDir}\Tools\DISM_CheckHealth.log"'.format(**global_vars)] - result = run_program(cmd, shell=True).stdout.decode() - # Check result - if 'no component store corruption detected' not in result.lower(): - raise GenericError + """Run DISM /RestoreHealth, then /CheckHealth, and then report errors.""" + if global_vars['OS']['Version'] in ('8', '8.1', '10'): + if repair: + # Restore Health + cmd = [ + 'DISM', '/Online', + '/Cleanup-Image', '/RestoreHealth', + r'/LogPath:"{LogDir}\Tools\DISM_RestoreHealth.log"'.format( + **global_vars), + '-new_console:n', '-new_console:s33V'] else: - raise UnsupportedOSError + # Scan Health + cmd = [ + 'DISM', '/Online', + '/Cleanup-Image', '/ScanHealth', + r'/LogPath:"{LogDir}\Tools\DISM_ScanHealth.log"'.format( + **global_vars), + '-new_console:n', '-new_console:s33V'] + run_program(cmd, pipe=False, check=False, shell=True) + wait_for_process('dism') + # Now check health + cmd = [ + 'DISM', '/Online', + '/Cleanup-Image', '/CheckHealth', + r'/LogPath:"{LogDir}\Tools\DISM_CheckHealth.log"'.format(**global_vars)] + result = run_program(cmd, shell=True).stdout.decode() + # Check result + if 'no component store corruption detected' not in result.lower(): + raise GenericError + else: + raise UnsupportedOSError def run_kvrt(): - """Run KVRT.""" - extract_item('KVRT', silent=True) - os.makedirs(global_vars['QuarantineDir'], exist_ok=True) - cmd = [ - global_vars['Tools']['KVRT'], - '-accepteula', '-dontcryptsupportinfo', '-fixednames', - '-d', global_vars['QuarantineDir'], - '-processlevel', '3'] - popen_program(cmd, pipe=False) + """Run KVRT.""" + extract_item('KVRT', silent=True) + os.makedirs(global_vars['QuarantineDir'], exist_ok=True) + cmd = [ + global_vars['Tools']['KVRT'], + '-accepteula', '-dontcryptsupportinfo', '-fixednames', + '-d', global_vars['QuarantineDir'], + '-processlevel', '3'] + popen_program(cmd, pipe=False) def run_sfc_scan(): - """Run SFC in a "split window" and report errors.""" - cmd = [ - r'{SYSTEMROOT}\System32\sfc.exe'.format(**global_vars['Env']), - '/scannow'] - out = run_program(cmd, check=False) - # Save stderr - with open(r'{LogDir}\Tools\SFC.err'.format(**global_vars), 'a') as f: - for line in out.stderr.decode('utf-8', 'ignore').splitlines(): - f.write(line.strip() + '\n') - # Save stdout - with open(r'{LogDir}\Tools\SFC.log'.format(**global_vars), 'a') as f: - for line in out.stdout.decode('utf-8', 'ignore').splitlines(): - f.write(line.strip() + '\n') - # Check result - log_text = out.stdout.decode('utf-8', 'ignore').replace('\0', '') - if re.findall(r'did\s+not\s+find\s+any\s+integrity\s+violations', log_text): - pass - elif re.findall(r'successfully\s+repaired\s+them', log_text): - raise GenericRepair - else: - raise GenericError + """Run SFC in a "split window" and report errors.""" + cmd = [ + r'{SYSTEMROOT}\System32\sfc.exe'.format(**global_vars['Env']), + '/scannow'] + out = run_program(cmd, check=False) + # Save stderr + with open(r'{LogDir}\Tools\SFC.err'.format(**global_vars), 'a') as f: + for line in out.stderr.decode('utf-8', 'ignore').splitlines(): + f.write(line.strip() + '\n') + # Save stdout + with open(r'{LogDir}\Tools\SFC.log'.format(**global_vars), 'a') as f: + for line in out.stdout.decode('utf-8', 'ignore').splitlines(): + f.write(line.strip() + '\n') + # Check result + log_text = out.stdout.decode('utf-8', 'ignore').replace('\0', '') + if re.findall(r'did\s+not\s+find\s+any\s+integrity\s+violations', log_text): + pass + elif re.findall(r'successfully\s+repaired\s+them', log_text): + raise GenericRepair + else: + raise GenericError def run_tdsskiller(): - """Run TDSSKiller.""" - extract_item('TDSSKiller', silent=True) - os.makedirs(r'{QuarantineDir}\TDSSKiller'.format( - **global_vars), exist_ok=True) - cmd = [ - global_vars['Tools']['TDSSKiller'], - '-l', r'{LogDir}\Tools\TDSSKiller.log'.format(**global_vars), - '-qpath', r'{QuarantineDir}\TDSSKiller'.format(**global_vars), - '-accepteula', '-accepteulaksn', - '-dcexact', '-tdlfs'] - run_program(cmd, pipe=False) + """Run TDSSKiller.""" + extract_item('TDSSKiller', silent=True) + os.makedirs(r'{QuarantineDir}\TDSSKiller'.format( + **global_vars), exist_ok=True) + cmd = [ + global_vars['Tools']['TDSSKiller'], + '-l', r'{LogDir}\Tools\TDSSKiller.log'.format(**global_vars), + '-qpath', r'{QuarantineDir}\TDSSKiller'.format(**global_vars), + '-accepteula', '-accepteulaksn', + '-dcexact', '-tdlfs'] + run_program(cmd, pipe=False) if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From cfd4eebcd426b48dbcdd6474afd86cc5e262e542 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 20:09:26 -0700 Subject: [PATCH 170/265] Updated safemode.py --- .bin/Scripts/functions/safemode.py | 38 ++++++++++++++++-------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/.bin/Scripts/functions/safemode.py b/.bin/Scripts/functions/safemode.py index 9f44aa04..837b14e8 100644 --- a/.bin/Scripts/functions/safemode.py +++ b/.bin/Scripts/functions/safemode.py @@ -6,31 +6,33 @@ from functions.common import * REG_MSISERVER = r'HKLM\SYSTEM\CurrentControlSet\Control\SafeBoot\Network\MSIServer' def disable_safemode_msi(): - """Disable MSI access under safemode.""" - cmd = ['reg', 'delete', REG_MSISERVER, '/f'] - run_program(cmd) + """Disable MSI access under safemode.""" + cmd = ['reg', 'delete', REG_MSISERVER, '/f'] + run_program(cmd) def disable_safemode(): - """Edit BCD to remove safeboot value.""" - cmd = ['bcdedit', '/deletevalue', '{default}', 'safeboot'] - run_program(cmd) + """Edit BCD to remove safeboot value.""" + cmd = ['bcdedit', '/deletevalue', '{default}', 'safeboot'] + run_program(cmd) def enable_safemode_msi(): - """Enable MSI access under safemode.""" - cmd = ['reg', 'add', REG_MSISERVER, '/f'] - run_program(cmd) - cmd = ['reg', 'add', REG_MSISERVER, '/ve', - '/t', 'REG_SZ', '/d', 'Service', '/f'] - run_program(cmd) + """Enable MSI access under safemode.""" + cmd = ['reg', 'add', REG_MSISERVER, '/f'] + run_program(cmd) + cmd = ['reg', 'add', REG_MSISERVER, '/ve', + '/t', 'REG_SZ', '/d', 'Service', '/f'] + run_program(cmd) def enable_safemode(): - """Edit BCD to set safeboot as default.""" - cmd = ['bcdedit', '/set', '{default}', 'safeboot', 'network'] - run_program(cmd) + """Edit BCD to set safeboot as default.""" + cmd = ['bcdedit', '/set', '{default}', 'safeboot', 'network'] + run_program(cmd) def reboot(delay=3): - cmd = ['shutdown', '-r', '-t', '{}'.format(delay)] - run_program(cmd, check=False) + cmd = ['shutdown', '-r', '-t', '{}'.format(delay)] + run_program(cmd, check=False) if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From a47707447c5bab3e071e96c678b716cc4630346c Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 20:10:49 -0700 Subject: [PATCH 171/265] Updated setup.py --- .bin/Scripts/functions/setup.py | 522 ++++++++++++++++---------------- 1 file changed, 262 insertions(+), 260 deletions(-) diff --git a/.bin/Scripts/functions/setup.py b/.bin/Scripts/functions/setup.py index 4e1e2ee7..4254a16a 100644 --- a/.bin/Scripts/functions/setup.py +++ b/.bin/Scripts/functions/setup.py @@ -9,313 +9,315 @@ HKCR = winreg.HKEY_CLASSES_ROOT HKCU = winreg.HKEY_CURRENT_USER HKLM = winreg.HKEY_LOCAL_MACHINE MOZILLA_FIREFOX_UBO_PATH = r'{}\{}\ublock_origin.xpi'.format( - os.environ.get('PROGRAMFILES'), - r'Mozilla Firefox\distribution\extensions') + os.environ.get('PROGRAMFILES'), + r'Mozilla Firefox\distribution\extensions') OTHER_RESULTS = { - 'Error': { - 'CalledProcessError': 'Unknown Error', - 'FileNotFoundError': 'File not found', - }, - 'Warning': {}} + 'Error': { + 'CalledProcessError': 'Unknown Error', + 'FileNotFoundError': 'File not found', + }, + 'Warning': {}} SETTINGS_CLASSIC_START = { - r'Software\IvoSoft\ClassicShell\Settings': {}, - r'Software\IvoSoft\ClassicStartMenu': { - 'DWORD Items': {'ShowedStyle2': 1}, - }, - r'Software\IvoSoft\ClassicStartMenu\MRU': {}, - r'Software\IvoSoft\ClassicStartMenu\Settings': { - 'DWORD Items': {'SkipMetro': 1}, - 'SZ Items': { - 'MenuStyle': 'Win7', - 'RecentPrograms': 'Recent', - }, - }, - } + r'Software\IvoSoft\ClassicShell\Settings': {}, + r'Software\IvoSoft\ClassicStartMenu': { + 'DWORD Items': {'ShowedStyle2': 1}, + }, + r'Software\IvoSoft\ClassicStartMenu\MRU': {}, + r'Software\IvoSoft\ClassicStartMenu\Settings': { + 'DWORD Items': {'SkipMetro': 1}, + 'SZ Items': { + 'MenuStyle': 'Win7', + 'RecentPrograms': 'Recent', + }, + }, + } SETTINGS_EXPLORER_SYSTEM = { - # Disable Location Tracking - r'Software\Microsoft\Windows NT\CurrentVersion\Sensor\Overrides\{BFA794E4-F964-4FDB-90F6-51056BFE4B44}': { - 'DWORD Items': {'SensorPermissionState': 0}, - }, - r'System\CurrentControlSet\Services\lfsvc\Service\Configuration': { - 'Status': {'Value': 0}, - }, - # Disable Telemetry - r'Software\Microsoft\Windows\CurrentVersion\Policies\DataCollection': { - 'DWORD Items': {'AllowTelemetry': 0}, - }, - r'Software\Microsoft\Windows\CurrentVersion\Policies\DataCollection': { - 'DWORD Items': {'AllowTelemetry': 0}, - 'WOW64_32': True, - }, - r'Software\Policies\Microsoft\Windows\DataCollection': { - 'DWORD Items': {'AllowTelemetry': 0}, - }, - # Disable Wi-Fi Sense - r'Software\Microsoft\PolicyManager\default\WiFi\AllowWiFiHotSpotReporting': { - 'DWORD Items': {'Value': 0}, - }, - r'Software\Microsoft\PolicyManager\default\WiFi\AllowAutoConnectToWiFiSenseHotspots': { - 'DWORD Items': {'Value': 0}, - }, - } + # Disable Location Tracking + r'Software\Microsoft\Windows NT\CurrentVersion\Sensor\Overrides\{BFA794E4-F964-4FDB-90F6-51056BFE4B44}': { + 'DWORD Items': {'SensorPermissionState': 0}, + }, + r'System\CurrentControlSet\Services\lfsvc\Service\Configuration': { + 'Status': {'Value': 0}, + }, + # Disable Telemetry + r'Software\Microsoft\Windows\CurrentVersion\Policies\DataCollection': { + 'DWORD Items': {'AllowTelemetry': 0}, + }, + r'Software\Microsoft\Windows\CurrentVersion\Policies\DataCollection': { + 'DWORD Items': {'AllowTelemetry': 0}, + 'WOW64_32': True, + }, + r'Software\Policies\Microsoft\Windows\DataCollection': { + 'DWORD Items': {'AllowTelemetry': 0}, + }, + # Disable Wi-Fi Sense + r'Software\Microsoft\PolicyManager\default\WiFi\AllowWiFiHotSpotReporting': { + 'DWORD Items': {'Value': 0}, + }, + r'Software\Microsoft\PolicyManager\default\WiFi\AllowAutoConnectToWiFiSenseHotspots': { + 'DWORD Items': {'Value': 0}, + }, + } SETTINGS_EXPLORER_USER = { - # Disable silently installed apps - r'Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager': { - 'DWORD Items': {'SilentInstalledAppsEnabled': 0}, - }, - # Disable Tips and Tricks - r'Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager': { - 'DWORD Items': {'SoftLandingEnabled ': 0}, - }, - # Hide People bar - r'Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\People': { - 'DWORD Items': {'PeopleBand': 0}, - }, - # Hide Search button / box - r'Software\Microsoft\Windows\CurrentVersion\Search': { - 'DWORD Items': {'SearchboxTaskbarMode': 0}, - }, - # Change default Explorer view to "Computer" - r'Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced': { - 'DWORD Items': {'LaunchTo': 1}, - }, - } + # Disable silently installed apps + r'Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager': { + 'DWORD Items': {'SilentInstalledAppsEnabled': 0}, + }, + # Disable Tips and Tricks + r'Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager': { + 'DWORD Items': {'SoftLandingEnabled ': 0}, + }, + # Hide People bar + r'Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\People': { + 'DWORD Items': {'PeopleBand': 0}, + }, + # Hide Search button / box + r'Software\Microsoft\Windows\CurrentVersion\Search': { + 'DWORD Items': {'SearchboxTaskbarMode': 0}, + }, + # Change default Explorer view to "Computer" + r'Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced': { + 'DWORD Items': {'LaunchTo': 1}, + }, + } SETTINGS_GOOGLE_CHROME = { - r'Software\Google\Chrome\Extensions\cjpalhdlnbpafiamejdnhcphjbkeiagm': { - 'SZ Items': { - 'update_url': 'https://clients2.google.com/service/update2/crx'}, - 'WOW64_32': True, - }, - r'Software\Google\Chrome\Extensions\pgdnlhfefecpicbbihgmbmffkjpaplco': { - 'SZ Items': { - 'update_url': 'https://clients2.google.com/service/update2/crx'}, - 'WOW64_32': True, - }, - } + r'Software\Google\Chrome\Extensions\cjpalhdlnbpafiamejdnhcphjbkeiagm': { + 'SZ Items': { + 'update_url': 'https://clients2.google.com/service/update2/crx'}, + 'WOW64_32': True, + }, + r'Software\Google\Chrome\Extensions\pgdnlhfefecpicbbihgmbmffkjpaplco': { + 'SZ Items': { + 'update_url': 'https://clients2.google.com/service/update2/crx'}, + 'WOW64_32': True, + }, + } SETTINGS_MOZILLA_FIREFOX_32 = { - r'Software\Mozilla\Firefox\Extensions': { - 'SZ Items': { - 'uBlock0@raymondhill.net': MOZILLA_FIREFOX_UBO_PATH}, - 'WOW64_32': True, - }, - } + r'Software\Mozilla\Firefox\Extensions': { + 'SZ Items': { + 'uBlock0@raymondhill.net': MOZILLA_FIREFOX_UBO_PATH}, + 'WOW64_32': True, + }, + } SETTINGS_MOZILLA_FIREFOX_64 = { - r'Software\Mozilla\Firefox\Extensions': { - 'SZ Items': { - 'uBlock0@raymondhill.net': MOZILLA_FIREFOX_UBO_PATH}, - }, - } + r'Software\Mozilla\Firefox\Extensions': { + 'SZ Items': { + 'uBlock0@raymondhill.net': MOZILLA_FIREFOX_UBO_PATH}, + }, + } VCR_REDISTS = [ - {'Name': 'Visual C++ 2010 x32...', - 'Cmd': [r'2010sp1\x32\vcredist.exe', '/passive', '/norestart']}, - {'Name': 'Visual C++ 2010 x64...', - 'Cmd': [r'2010sp1\x64\vcredist.exe', '/passive', '/norestart']}, - {'Name': 'Visual C++ 2012 Update 4 x32...', - 'Cmd': [r'2012u4\x32\vcredist.exe', '/passive', '/norestart']}, - {'Name': 'Visual C++ 2012 Update 4 x64...', - 'Cmd': [r'2012u4\x64\vcredist.exe', '/passive', '/norestart']}, - {'Name': 'Visual C++ 2013 x32...', - 'Cmd': [r'2013\x32\vcredist.exe', '/install', - '/passive', '/norestart']}, - {'Name': 'Visual C++ 2013 x64...', - 'Cmd': [r'2013\x64\vcredist.exe', '/install', - '/passive', '/norestart']}, - {'Name': 'Visual C++ 2017 x32...', - 'Cmd': [r'2017\x32\vcredist.exe', '/install', - '/passive', '/norestart']}, - {'Name': 'Visual C++ 2017 x64...', - 'Cmd': [r'2017\x64\vcredist.exe', '/install', - '/passive', '/norestart']}, - ] + {'Name': 'Visual C++ 2010 x32...', + 'Cmd': [r'2010sp1\x32\vcredist.exe', '/passive', '/norestart']}, + {'Name': 'Visual C++ 2010 x64...', + 'Cmd': [r'2010sp1\x64\vcredist.exe', '/passive', '/norestart']}, + {'Name': 'Visual C++ 2012 Update 4 x32...', + 'Cmd': [r'2012u4\x32\vcredist.exe', '/passive', '/norestart']}, + {'Name': 'Visual C++ 2012 Update 4 x64...', + 'Cmd': [r'2012u4\x64\vcredist.exe', '/passive', '/norestart']}, + {'Name': 'Visual C++ 2013 x32...', + 'Cmd': [r'2013\x32\vcredist.exe', '/install', + '/passive', '/norestart']}, + {'Name': 'Visual C++ 2013 x64...', + 'Cmd': [r'2013\x64\vcredist.exe', '/install', + '/passive', '/norestart']}, + {'Name': 'Visual C++ 2017 x32...', + 'Cmd': [r'2017\x32\vcredist.exe', '/install', + '/passive', '/norestart']}, + {'Name': 'Visual C++ 2017 x64...', + 'Cmd': [r'2017\x64\vcredist.exe', '/install', + '/passive', '/norestart']}, + ] def config_classicstart(): - """Configure ClassicStart.""" - # User level, not system level - cs_exe = r'{PROGRAMFILES}\Classic Shell\ClassicStartMenu.exe'.format( - **global_vars['Env']) - skin = r'{PROGRAMFILES}\Classic Shell\Skins\Metro-Win10-Black.skin7'.format( - **global_vars['Env']) - extract_item('ClassicStartSkin', silent=True) + """Configure ClassicStart.""" + # User level, not system level + cs_exe = r'{PROGRAMFILES}\Classic Shell\ClassicStartMenu.exe'.format( + **global_vars['Env']) + skin = r'{PROGRAMFILES}\Classic Shell\Skins\Metro-Win10-Black.skin7'.format( + **global_vars['Env']) + extract_item('ClassicStartSkin', silent=True) - # Stop Classic Start - run_program([cs_exe, '-exit'], check=False) - sleep(1) - kill_process('ClassicStartMenu.exe') + # Stop Classic Start + run_program([cs_exe, '-exit'], check=False) + sleep(1) + kill_process('ClassicStartMenu.exe') - # Configure - write_registry_settings(SETTINGS_CLASSIC_START, all_users=False) - if global_vars['OS']['Version'] == '10' and os.path.exists(skin): - # Enable Win10 theme if on Win10 - key_path = r'Software\IvoSoft\ClassicStartMenu\Settings' - with winreg.OpenKey(HKCU, key_path, access=winreg.KEY_WRITE) as key: - winreg.SetValueEx( - key, 'SkinW7', 0, winreg.REG_SZ, 'Metro-Win10-Black') - winreg.SetValueEx(key, 'SkinVariationW7', 0, winreg.REG_SZ, '') + # Configure + write_registry_settings(SETTINGS_CLASSIC_START, all_users=False) + if global_vars['OS']['Version'] == '10' and os.path.exists(skin): + # Enable Win10 theme if on Win10 + key_path = r'Software\IvoSoft\ClassicStartMenu\Settings' + with winreg.OpenKey(HKCU, key_path, access=winreg.KEY_WRITE) as key: + winreg.SetValueEx( + key, 'SkinW7', 0, winreg.REG_SZ, 'Metro-Win10-Black') + winreg.SetValueEx(key, 'SkinVariationW7', 0, winreg.REG_SZ, '') - # Pin Browser to Start Menu (Classic) - firefox = r'{PROGRAMDATA}\Start Menu\Programs\Mozilla Firefox.lnk'.format( - **global_vars['Env']) - chrome = r'{PROGRAMDATA}\Start Menu\Programs\Google Chrome.lnk'.format( - **global_vars['Env']) - dest_path = r'{APPDATA}\ClassicShell\Pinned'.format(**global_vars['Env']) - source = None - dest = None - if os.path.exists(firefox): - source = firefox - dest = r'{}\Mozilla Firefox.lnk'.format(dest_path) - elif os.path.exists(chrome): - source = chrome - dest = r'{}\Google Chrome.lnk'.format(dest_path) - if source: - try: - os.makedirs(dest_path, exist_ok=True) - shutil.copy(source, dest) - except Exception: - pass # Meh, it's fine without + # Pin Browser to Start Menu (Classic) + firefox = r'{PROGRAMDATA}\Start Menu\Programs\Mozilla Firefox.lnk'.format( + **global_vars['Env']) + chrome = r'{PROGRAMDATA}\Start Menu\Programs\Google Chrome.lnk'.format( + **global_vars['Env']) + dest_path = r'{APPDATA}\ClassicShell\Pinned'.format(**global_vars['Env']) + source = None + dest = None + if os.path.exists(firefox): + source = firefox + dest = r'{}\Mozilla Firefox.lnk'.format(dest_path) + elif os.path.exists(chrome): + source = chrome + dest = r'{}\Google Chrome.lnk'.format(dest_path) + if source: + try: + os.makedirs(dest_path, exist_ok=True) + shutil.copy(source, dest) + except Exception: + pass # Meh, it's fine without - # (Re)start Classic Start - run_program([cs_exe, '-exit'], check=False) - sleep(1) - kill_process('ClassicStartMenu.exe') - sleep(1) - popen_program(cs_exe) + # (Re)start Classic Start + run_program([cs_exe, '-exit'], check=False) + sleep(1) + kill_process('ClassicStartMenu.exe') + sleep(1) + popen_program(cs_exe) def config_explorer_system(): - """Configure Windows Explorer for all users via Registry settings.""" - write_registry_settings(SETTINGS_EXPLORER_SYSTEM, all_users=True) + """Configure Windows Explorer for all users via Registry settings.""" + write_registry_settings(SETTINGS_EXPLORER_SYSTEM, all_users=True) def config_explorer_user(): - """Configure Windows Explorer for current user via Registry settings.""" - write_registry_settings(SETTINGS_EXPLORER_USER, all_users=False) + """Configure Windows Explorer for current user via Registry settings.""" + write_registry_settings(SETTINGS_EXPLORER_USER, all_users=False) def disable_windows_telemetry(): - """Disable Windows 10 telemetry settings with O&O ShutUp10.""" - extract_item('ShutUp10', silent=True) - cmd = [ - r'{BinDir}\ShutUp10\OOSU10.exe'.format(**global_vars), - r'{BinDir}\ShutUp10\1201.cfg'.format(**global_vars), - '/quiet'] - run_program(cmd) + """Disable Windows 10 telemetry settings with O&O ShutUp10.""" + extract_item('ShutUp10', silent=True) + cmd = [ + r'{BinDir}\ShutUp10\OOSU10.exe'.format(**global_vars), + r'{BinDir}\ShutUp10\1201.cfg'.format(**global_vars), + '/quiet'] + run_program(cmd) def update_clock(): - """Set Timezone and sync clock.""" - run_program(['tzutil' ,'/s', WINDOWS_TIME_ZONE], check=False) - run_program(['net', 'stop', 'w32ime'], check=False) - run_program( - ['w32tm', '/config', '/syncfromflags:manual', - '/manualpeerlist:"us.pool.ntp.org time.nist.gov time.windows.com"', - ], - check=False) - run_program(['net', 'start', 'w32ime'], check=False) - run_program(['w32tm', '/resync', '/nowait'], check=False) + """Set Timezone and sync clock.""" + run_program(['tzutil' ,'/s', WINDOWS_TIME_ZONE], check=False) + run_program(['net', 'stop', 'w32ime'], check=False) + run_program( + ['w32tm', '/config', '/syncfromflags:manual', + '/manualpeerlist:"us.pool.ntp.org time.nist.gov time.windows.com"', + ], + check=False) + run_program(['net', 'start', 'w32ime'], check=False) + run_program(['w32tm', '/resync', '/nowait'], check=False) def write_registry_settings(settings, all_users=False): - """Write registry values from custom dict of dicts.""" - hive = HKCU - if all_users: - hive = HKLM - for k, v in settings.items(): - # CreateKey - access = winreg.KEY_WRITE - if 'WOW64_32' in v: - access = access | winreg.KEY_WOW64_32KEY - winreg.CreateKeyEx(hive, k, 0, access) + """Write registry values from custom dict of dicts.""" + hive = HKCU + if all_users: + hive = HKLM + for k, v in settings.items(): + # CreateKey + access = winreg.KEY_WRITE + if 'WOW64_32' in v: + access = access | winreg.KEY_WOW64_32KEY + winreg.CreateKeyEx(hive, k, 0, access) - # Create values - with winreg.OpenKeyEx(hive, k, 0, access) as key: - for name, value in v.get('DWORD Items', {}).items(): - winreg.SetValueEx(key, name, 0, winreg.REG_DWORD, value) - for name, value in v.get('SZ Items', {}).items(): - winreg.SetValueEx(key, name, 0, winreg.REG_SZ, value) + # Create values + with winreg.OpenKeyEx(hive, k, 0, access) as key: + for name, value in v.get('DWORD Items', {}).items(): + winreg.SetValueEx(key, name, 0, winreg.REG_DWORD, value) + for name, value in v.get('SZ Items', {}).items(): + winreg.SetValueEx(key, name, 0, winreg.REG_SZ, value) # Installations def install_adobe_reader(): - """Install Adobe Reader.""" - cmd = [ - r'{BaseDir}\Installers\Extras\Office\Adobe Reader DC.exe'.format( - **global_vars), - '/sAll', - '/msi', '/norestart', '/quiet', - 'ALLUSERS=1', - 'EULA_ACCEPT=YES'] - run_program(cmd) + """Install Adobe Reader.""" + cmd = [ + r'{BaseDir}\Installers\Extras\Office\Adobe Reader DC.exe'.format( + **global_vars), + '/sAll', + '/msi', '/norestart', '/quiet', + 'ALLUSERS=1', + 'EULA_ACCEPT=YES'] + run_program(cmd) def install_chrome_extensions(): - """Update registry to install Google Chrome extensions for all users.""" - write_registry_settings(SETTINGS_GOOGLE_CHROME, all_users=True) + """Update registry to install Google Chrome extensions for all users.""" + write_registry_settings(SETTINGS_GOOGLE_CHROME, all_users=True) def install_classicstart_skin(): - """Extract ClassicStart skin to installation folder.""" - if global_vars['OS']['Version'] not in ('8', '8.1', '10'): - raise UnsupportedOSError - extract_item('ClassicStartSkin', silent=True) - source = r'{BinDir}\ClassicStartSkin\Metro-Win10-Black.skin7'.format( - **global_vars) - dest_path = r'{PROGRAMFILES}\Classic Shell\Skins'.format( - **global_vars['Env']) - dest = r'{}\Metro-Win10-Black.skin7'.format(dest_path) - os.makedirs(dest_path, exist_ok=True) - shutil.copy(source, dest) + """Extract ClassicStart skin to installation folder.""" + if global_vars['OS']['Version'] not in ('8', '8.1', '10'): + raise UnsupportedOSError + extract_item('ClassicStartSkin', silent=True) + source = r'{BinDir}\ClassicStartSkin\Metro-Win10-Black.skin7'.format( + **global_vars) + dest_path = r'{PROGRAMFILES}\Classic Shell\Skins'.format( + **global_vars['Env']) + dest = r'{}\Metro-Win10-Black.skin7'.format(dest_path) + os.makedirs(dest_path, exist_ok=True) + shutil.copy(source, dest) def install_firefox_extensions(): - """Update registry to install Firefox extensions for all users.""" - dist_path = r'{PROGRAMFILES}\Mozilla Firefox\distribution\extensions'.format( - **global_vars['Env']) - source_path = r'{CBinDir}\FirefoxExtensions.7z'.format(**global_vars) - if not os.path.exists(source_path): - raise FileNotFoundError + """Update registry to install Firefox extensions for all users.""" + dist_path = r'{PROGRAMFILES}\Mozilla Firefox\distribution\extensions'.format( + **global_vars['Env']) + source_path = r'{CBinDir}\FirefoxExtensions.7z'.format(**global_vars) + if not os.path.exists(source_path): + raise FileNotFoundError - # Update registry - write_registry_settings(SETTINGS_MOZILLA_FIREFOX_32, all_users=True) - write_registry_settings(SETTINGS_MOZILLA_FIREFOX_64, all_users=True) + # Update registry + write_registry_settings(SETTINGS_MOZILLA_FIREFOX_32, all_users=True) + write_registry_settings(SETTINGS_MOZILLA_FIREFOX_64, all_users=True) - # Extract extension(s) to distribution folder - cmd = [ - global_vars['Tools']['SevenZip'], 'e', '-aos', '-bso0', '-bse0', - '-p{ArchivePassword}'.format(**global_vars), - '-o{dist_path}'.format(dist_path=dist_path), - source_path] - run_program(cmd) + # Extract extension(s) to distribution folder + cmd = [ + global_vars['Tools']['SevenZip'], 'e', '-aos', '-bso0', '-bse0', + '-p{ArchivePassword}'.format(**global_vars), + '-o{dist_path}'.format(dist_path=dist_path), + source_path] + run_program(cmd) def install_ninite_bundle(mse=False): - """Run Ninite file(s) based on OS version.""" - if global_vars['OS']['Version'] in ('8', '8.1', '10'): - # Modern selection - popen_program(r'{BaseDir}\Installers\Extras\Bundles\Modern.exe'.format( - **global_vars)) - else: - # Legacy selection - if mse: - cmd = r'{BaseDir}\Installers\Extras\Security'.format(**global_vars) - cmd += r'\Microsoft Security Essentials.exe' - popen_program(cmd) - popen_program(r'{BaseDir}\Installers\Extras\Bundles\Legacy.exe'.format( - **global_vars)) + """Run Ninite file(s) based on OS version.""" + if global_vars['OS']['Version'] in ('8', '8.1', '10'): + # Modern selection + popen_program(r'{BaseDir}\Installers\Extras\Bundles\Modern.exe'.format( + **global_vars)) + else: + # Legacy selection + if mse: + cmd = r'{BaseDir}\Installers\Extras\Security'.format(**global_vars) + cmd += r'\Microsoft Security Essentials.exe' + popen_program(cmd) + popen_program(r'{BaseDir}\Installers\Extras\Bundles\Legacy.exe'.format( + **global_vars)) def install_vcredists(): - """Install all supported Visual C++ runtimes.""" - extract_item('_vcredists', silent=True) - prev_dir = os.getcwd() - try: - os.chdir(r'{BinDir}\_vcredists'.format(**global_vars)) - except FileNotFoundError: - # Ignored since the loop below will report the errors - pass - for vcr in VCR_REDISTS: - try_and_print(message=vcr['Name'], function=run_program, - cmd=vcr['Cmd'], other_results=OTHER_RESULTS) + """Install all supported Visual C++ runtimes.""" + extract_item('_vcredists', silent=True) + prev_dir = os.getcwd() + try: + os.chdir(r'{BinDir}\_vcredists'.format(**global_vars)) + except FileNotFoundError: + # Ignored since the loop below will report the errors + pass + for vcr in VCR_REDISTS: + try_and_print(message=vcr['Name'], function=run_program, + cmd=vcr['Cmd'], other_results=OTHER_RESULTS) - os.chdir(prev_dir) + os.chdir(prev_dir) # Misc def open_device_manager(): - popen_program(['mmc', 'devmgmt.msc']) + popen_program(['mmc', 'devmgmt.msc']) def open_windows_activation(): - popen_program(['slui']) + popen_program(['slui']) def open_windows_updates(): - popen_program(['control', '/name', 'Microsoft.WindowsUpdate']) + popen_program(['control', '/name', 'Microsoft.WindowsUpdate']) if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From fa424a4576169998aa91a5a4eeff11db27aa451f Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 20:13:32 -0700 Subject: [PATCH 172/265] Updated update.py --- .bin/Scripts/functions/update.py | 1427 +++++++++++++++--------------- 1 file changed, 716 insertions(+), 711 deletions(-) diff --git a/.bin/Scripts/functions/update.py b/.bin/Scripts/functions/update.py index b4068c22..21d2acee 100644 --- a/.bin/Scripts/functions/update.py +++ b/.bin/Scripts/functions/update.py @@ -9,947 +9,952 @@ from settings.music import * from settings.sources import * def compress_and_remove_item(item): - """Compress and delete an item unless an error is encountered.""" - try: - compress_item(item) - except: - raise GenericError - else: - remove_item(item.path) + """Compress and delete an item unless an error is encountered.""" + try: + compress_item(item) + except: + raise GenericError + else: + remove_item(item.path) def compress_item(item): - """Compress an item in a 7-Zip archive using the ARCHIVE_PASSWORD.""" - # Prep - prev_dir = os.getcwd() - dest = '{}.7z'.format(item.path) - wd = item.path - include_str = '*' - if os.path.isfile(wd): - wd = os.path.abspath(r'{}\{}'.format(wd, os.path.pardir)) - include_str = item.name - os.chdir(wd) + """Compress an item in a 7-Zip archive using the ARCHIVE_PASSWORD.""" + # Prep + prev_dir = os.getcwd() + dest = '{}.7z'.format(item.path) + wd = item.path + include_str = '*' + if os.path.isfile(wd): + wd = os.path.abspath(r'{}\{}'.format(wd, os.path.pardir)) + include_str = item.name + os.chdir(wd) - # Compress - cmd = [ - global_vars['Tools']['SevenZip'], - 'a', dest, - '-t7z', '-mx=7', '-myx=7', '-ms=on', '-mhe', '-bso0', '-bse0', - '-p{}'.format(ARCHIVE_PASSWORD), - include_str, - ] - run_program(cmd) + # Compress + cmd = [ + global_vars['Tools']['SevenZip'], + 'a', dest, + '-t7z', '-mx=7', '-myx=7', '-ms=on', '-mhe', '-bso0', '-bse0', + '-p{}'.format(ARCHIVE_PASSWORD), + include_str, + ] + run_program(cmd) - # Done - os.chdir(prev_dir) + # Done + os.chdir(prev_dir) def download_generic(out_dir, out_name, source_url): - """Downloads a file using requests.""" - ## Code based on this Q&A: https://stackoverflow.com/q/16694907 - ### Asked by: https://stackoverflow.com/users/427457/roman-podlinov - ### Edited by: https://stackoverflow.com/users/657427/christophe-roussy - ### Using answer: https://stackoverflow.com/a/39217788 - ### Answer from: https://stackoverflow.com/users/4323/john-zwinck - os.makedirs(out_dir, exist_ok=True) - out_path = '{}/{}'.format(out_dir, out_name) - try: - r = requests.get(source_url, stream=True) - with open(out_path, 'wb') as f: - shutil.copyfileobj(r.raw, f) - r.close() - except: - raise GenericError('Failed to download file.') + """Downloads a file using requests.""" + ## Code based on this Q&A: https://stackoverflow.com/q/16694907 + ### Asked by: https://stackoverflow.com/users/427457/roman-podlinov + ### Edited by: https://stackoverflow.com/users/657427/christophe-roussy + ### Using answer: https://stackoverflow.com/a/39217788 + ### Answer from: https://stackoverflow.com/users/4323/john-zwinck + os.makedirs(out_dir, exist_ok=True) + out_path = '{}/{}'.format(out_dir, out_name) + try: + r = requests.get(source_url, stream=True) + with open(out_path, 'wb') as f: + shutil.copyfileobj(r.raw, f) + r.close() + except: + raise GenericError('Failed to download file.') def download_to_temp(out_name, source_url): - """Download a file to the TmpDir.""" - download_generic(global_vars['TmpDir'], out_name, source_url) + """Download a file to the TmpDir.""" + download_generic(global_vars['TmpDir'], out_name, source_url) def extract_generic(source, dest, mode='x', sz_args=[]): - """Extract a file to a destination.""" - cmd = [ - global_vars['Tools']['SevenZip'], - mode, source, r'-o{}'.format(dest), - '-aoa', '-bso0', '-bse0', - ] - cmd.extend(sz_args) - run_program(cmd) + """Extract a file to a destination.""" + cmd = [ + global_vars['Tools']['SevenZip'], + mode, source, r'-o{}'.format(dest), + '-aoa', '-bso0', '-bse0', + ] + cmd.extend(sz_args) + run_program(cmd) def extract_temp_to_bin(source, item, mode='x', sz_args=[]): - """Extract a file to the .bin folder.""" - source = r'{}\{}'.format(global_vars['TmpDir'], source) - dest = r'{}\{}'.format(global_vars['BinDir'], item) - extract_generic(source, dest, mode, sz_args) + """Extract a file to the .bin folder.""" + source = r'{}\{}'.format(global_vars['TmpDir'], source) + dest = r'{}\{}'.format(global_vars['BinDir'], item) + extract_generic(source, dest, mode, sz_args) def extract_temp_to_cbin(source, item, mode='x', sz_args=[]): - """Extract a file to the .cbin folder.""" - source = r'{}\{}'.format(global_vars['TmpDir'], source) - dest = r'{}\{}'.format(global_vars['CBinDir'], item) - include_path = r'{}\_include\{}'.format(global_vars['CBinDir'], item) - if os.path.exists(include_path): - shutil.copytree(include_path, dest) - extract_generic(source, dest, mode, sz_args) + """Extract a file to the .cbin folder.""" + source = r'{}\{}'.format(global_vars['TmpDir'], source) + dest = r'{}\{}'.format(global_vars['CBinDir'], item) + include_path = r'{}\_include\{}'.format(global_vars['CBinDir'], item) + if os.path.exists(include_path): + shutil.copytree(include_path, dest) + extract_generic(source, dest, mode, sz_args) def generate_launcher(section, name, options): - """Generate a launcher script.""" - # Prep - dest = r'{}\{}'.format(global_vars['BaseDir'], section) - if section == '(Root)': - dest = global_vars['BaseDir'] - full_path = r'{}\{}.cmd'.format(dest, name) - template = r'{}\Scripts\Launcher_Template.cmd'.format(global_vars['BinDir']) + """Generate a launcher script.""" + # Prep + dest = r'{}\{}'.format(global_vars['BaseDir'], section) + if section == '(Root)': + dest = global_vars['BaseDir'] + full_path = r'{}\{}.cmd'.format(dest, name) + template = r'{}\Scripts\Launcher_Template.cmd'.format(global_vars['BinDir']) - # Format options - f_options = {} - for opt in options.keys(): - # Values need to be a list to support the multi-line extra code sections - if opt == 'Extra Code': - f_options['rem EXTRA_CODE'] = options['Extra Code'] - elif re.search(r'^L_\w+', opt, re.IGNORECASE): - new_opt = 'set {}='.format(opt) - f_options[new_opt] = ['set {}={}'.format(opt, options[opt])] + # Format options + f_options = {} + for opt in options.keys(): + # Values need to be a list to support the multi-line extra code sections + if opt == 'Extra Code': + f_options['rem EXTRA_CODE'] = options['Extra Code'] + elif re.search(r'^L_\w+', opt, re.IGNORECASE): + new_opt = 'set {}='.format(opt) + f_options[new_opt] = ['set {}={}'.format(opt, options[opt])] - # Read template and update using f_options - out_text = [] - with open(template, 'r') as f: - for line in f.readlines(): - # Strip all lines to let Python handle/correct the CRLF endings - line = line.strip() - if line in f_options: - # Extend instead of append to support extra code sections - out_text.extend(f_options[line]) - else: - out_text.append(line) + # Read template and update using f_options + out_text = [] + with open(template, 'r') as f: + for line in f.readlines(): + # Strip all lines to let Python handle/correct the CRLF endings + line = line.strip() + if line in f_options: + # Extend instead of append to support extra code sections + out_text.extend(f_options[line]) + else: + out_text.append(line) - # Write file - os.makedirs(dest, exist_ok=True) - with open(full_path, 'w') as f: - # f.writelines(out_text) - f.write('\n'.join(out_text)) + # Write file + os.makedirs(dest, exist_ok=True) + with open(full_path, 'w') as f: + # f.writelines(out_text) + f.write('\n'.join(out_text)) def remove_item(item_path): - """Delete a file or folder.""" - if os.path.exists(item_path): - if os.path.isdir(item_path): - shutil.rmtree(item_path, ignore_errors=True) - else: - os.remove(item_path) + """Delete a file or folder.""" + if os.path.exists(item_path): + if os.path.isdir(item_path): + shutil.rmtree(item_path, ignore_errors=True) + else: + os.remove(item_path) def remove_from_kit(item): - """Delete a file or folder from the .bin/.cbin folders.""" - item_locations = [] - for p in [global_vars['BinDir'], global_vars['CBinDir']]: - item_locations.append(r'{}\{}'.format(p, item)) - item_locations.append(r'{}\{}.7z'.format(p, item)) - item_locations.append(r'{}\_Drivers\{}'.format(p, item)) - item_locations.append(r'{}\_Drivers\{}.7z'.format(p, item)) - for item_path in item_locations: - remove_item(item_path) - -def remove_from_temp(item): - """Delete a file or folder from the TmpDir folder.""" - item_path = r'{}\{}'.format(global_vars['TmpDir'], item) + """Delete a file or folder from the .bin/.cbin folders.""" + item_locations = [] + for p in [global_vars['BinDir'], global_vars['CBinDir']]: + item_locations.append(r'{}\{}'.format(p, item)) + item_locations.append(r'{}\{}.7z'.format(p, item)) + item_locations.append(r'{}\_Drivers\{}'.format(p, item)) + item_locations.append(r'{}\_Drivers\{}.7z'.format(p, item)) + for item_path in item_locations: remove_item(item_path) +def remove_from_temp(item): + """Delete a file or folder from the TmpDir folder.""" + item_path = r'{}\{}'.format(global_vars['TmpDir'], item) + remove_item(item_path) + def resolve_dynamic_url(source_url, regex): - """Scan source_url for a url using the regex provided; returns str.""" - # Load the download page - try: - download_page = requests.get(source_url) - except Exception: - # "Fail silently as the download_to_temp() function will catch it - return None + """Scan source_url for a url using the regex provided; returns str.""" + # Load the download page + try: + download_page = requests.get(source_url) + except Exception: + # "Fail silently as the download_to_temp() function will catch it + return None - # Scan for the url using the regex provided - url = None - for line in download_page.content.decode().splitlines(): - if re.search(regex, line): - url = line.strip() - url = re.sub(r'.*(a |)href="([^"]+)".*', r'\2', url) - url = re.sub(r".*(a |)href='([^']+)'.*", r'\2', url) - break + # Scan for the url using the regex provided + url = None + for line in download_page.content.decode().splitlines(): + if re.search(regex, line): + url = line.strip() + url = re.sub(r'.*(a |)href="([^"]+)".*', r'\2', url) + url = re.sub(r".*(a |)href='([^']+)'.*", r'\2', url) + break - # Return - return url + # Return + return url def scan_for_net_installers(server, family_name, min_year): - """Scan network shares for installers.""" - if not server['Mounted']: - mount_network_share(server) + """Scan network shares for installers.""" + if not server['Mounted']: + mount_network_share(server) - if server['Mounted']: - for year in os.scandir(r'\\{IP}\{Share}'.format(**server)): - try: - year_ok = int(year.name) < min_year - except ValueError: - year_ok = False # Skip non-year items - if year_ok: - # Don't support outdated installers - continue - for version in os.scandir(year.path): - section = r'Installers\Extras\{}\{}'.format( - family_name, year.name) - if section not in LAUNCHERS: - LAUNCHERS[section] = {} - name = version.name - if re.search(r'(exe|msi)$', name, re.IGNORECASE): - name = name[:-4] - if name not in LAUNCHERS[section]: - LAUNCHERS[section][name] = { - 'L_TYPE': family_name, - 'L_PATH': year.name, - 'L_ITEM': version.name, - } - umount_network_share(server) + if server['Mounted']: + for year in os.scandir(r'\\{IP}\{Share}'.format(**server)): + try: + year_ok = int(year.name) < min_year + except ValueError: + year_ok = False # Skip non-year items + if year_ok: + # Don't support outdated installers + continue + for version in os.scandir(year.path): + section = r'Installers\Extras\{}\{}'.format( + family_name, year.name) + if section not in LAUNCHERS: + LAUNCHERS[section] = {} + name = version.name + if re.search(r'(exe|msi)$', name, re.IGNORECASE): + name = name[:-4] + if name not in LAUNCHERS[section]: + LAUNCHERS[section][name] = { + 'L_TYPE': family_name, + 'L_PATH': year.name, + 'L_ITEM': version.name, + } + umount_network_share(server) ## Data Recovery ## def update_testdisk(): - # Stop running processes - for exe in ['fidentify_win.exe', 'photorec_win.exe', - 'qphotorec_win.exe', 'testdisk_win.exe']: - kill_process(exe) + # Stop running processes + for exe in ['fidentify_win.exe', 'photorec_win.exe', + 'qphotorec_win.exe', 'testdisk_win.exe']: + kill_process(exe) - # Remove existing folders - remove_from_kit('TestDisk') + # Remove existing folders + remove_from_kit('TestDisk') - # Download - download_to_temp('testdisk_wip.zip', SOURCE_URLS['TestDisk']) + # Download + download_to_temp('testdisk_wip.zip', SOURCE_URLS['TestDisk']) - # Extract files - extract_temp_to_cbin('testdisk_wip.zip', 'TestDisk') - dest = r'{}\TestDisk'.format(global_vars['CBinDir']) - for item in os.scandir(r'{}\testdisk-7.1-WIP'.format(dest)): - dest_item = '{}\{}'.format(dest, item.name) - if not os.path.exists(dest_item): - shutil.move(item.path, dest_item) - shutil.rmtree( - r'{}\TestDisk\testdisk-7.1-WIP'.format(global_vars['CBinDir'])) + # Extract files + extract_temp_to_cbin('testdisk_wip.zip', 'TestDisk') + dest = r'{}\TestDisk'.format(global_vars['CBinDir']) + for item in os.scandir(r'{}\testdisk-7.1-WIP'.format(dest)): + dest_item = '{}\{}'.format(dest, item.name) + if not os.path.exists(dest_item): + shutil.move(item.path, dest_item) + shutil.rmtree( + r'{}\TestDisk\testdisk-7.1-WIP'.format(global_vars['CBinDir'])) - # Cleanup - remove_from_temp('testdisk_wip.zip') + # Cleanup + remove_from_temp('testdisk_wip.zip') ## Data Transfers ## def update_fastcopy(): - ## NOTE: Lives in .bin uncompressed - # Stop running processes - for process in ['FastCopy.exe', 'FastCopy64.exe']: - kill_process(process) + ## NOTE: Lives in .bin uncompressed + # Stop running processes + for process in ['FastCopy.exe', 'FastCopy64.exe']: + kill_process(process) - # Remove existing folders - remove_from_kit('FastCopy') + # Remove existing folders + remove_from_kit('FastCopy') - # Download - download_to_temp('FastCopy.zip', SOURCE_URLS['FastCopy']) + # Download + download_to_temp('FastCopy.zip', SOURCE_URLS['FastCopy']) - # Extract installer - extract_temp_to_bin('FastCopy.zip', 'FastCopy') - _path = r'{}\FastCopy'.format(global_vars['BinDir']) - _installer = 'FastCopy354_installer.exe' + # Extract installer + extract_temp_to_bin('FastCopy.zip', 'FastCopy') + _path = r'{}\FastCopy'.format(global_vars['BinDir']) + _installer = 'FastCopy354_installer.exe' - # Extract 64-bit - cmd = [ - r'{}\{}'.format(_path, _installer), - '/NOSUBDIR', '/DIR={}'.format(_path), - '/EXTRACT64'] - run_program(cmd) - shutil.move( - r'{}\FastCopy\FastCopy.exe'.format(global_vars['BinDir']), - r'{}\FastCopy\FastCopy64.exe'.format(global_vars['BinDir'])) + # Extract 64-bit + cmd = [ + r'{}\{}'.format(_path, _installer), + '/NOSUBDIR', '/DIR={}'.format(_path), + '/EXTRACT64'] + run_program(cmd) + shutil.move( + r'{}\FastCopy\FastCopy.exe'.format(global_vars['BinDir']), + r'{}\FastCopy\FastCopy64.exe'.format(global_vars['BinDir'])) - # Extract 32-bit - cmd = [ - r'{}\{}'.format(_path, _installer), - '/NOSUBDIR', '/DIR={}'.format(_path), - '/EXTRACT32'] - run_program(cmd) + # Extract 32-bit + cmd = [ + r'{}\{}'.format(_path, _installer), + '/NOSUBDIR', '/DIR={}'.format(_path), + '/EXTRACT32'] + run_program(cmd) - # Cleanup - os.remove(r'{}\{}'.format(_path, _installer)) - os.remove(r'{}\setup.exe'.format(_path, _installer)) - remove_from_temp('FastCopy.zip') + # Cleanup + os.remove(r'{}\{}'.format(_path, _installer)) + os.remove(r'{}\setup.exe'.format(_path, _installer)) + remove_from_temp('FastCopy.zip') def update_wimlib(): - # Stop running processes - kill_process('wimlib-imagex.exe') + # Stop running processes + kill_process('wimlib-imagex.exe') - # Remove existing folders - remove_from_kit('wimlib') + # Remove existing folders + remove_from_kit('wimlib') - # Download - download_to_temp('wimlib32.zip', SOURCE_URLS['wimlib32']) - download_to_temp('wimlib64.zip', SOURCE_URLS['wimlib64']) + # Download + download_to_temp('wimlib32.zip', SOURCE_URLS['wimlib32']) + download_to_temp('wimlib64.zip', SOURCE_URLS['wimlib64']) - # Extract - extract_generic( - r'{}\wimlib32.zip'.format(global_vars['TmpDir']), - r'{}\wimlib\x32'.format(global_vars['CBinDir'])) - extract_generic( - r'{}\wimlib64.zip'.format(global_vars['TmpDir']), - r'{}\wimlib\x64'.format(global_vars['CBinDir'])) + # Extract + extract_generic( + r'{}\wimlib32.zip'.format(global_vars['TmpDir']), + r'{}\wimlib\x32'.format(global_vars['CBinDir'])) + extract_generic( + r'{}\wimlib64.zip'.format(global_vars['TmpDir']), + r'{}\wimlib\x64'.format(global_vars['CBinDir'])) - # Cleanup - remove_from_temp('wimlib32.zip') - remove_from_temp('wimlib64.zip') + # Cleanup + remove_from_temp('wimlib32.zip') + remove_from_temp('wimlib64.zip') def update_xyplorer(): - # Stop running processes - kill_process('XYplorerFree.exe') + # Stop running processes + kill_process('XYplorerFree.exe') - # Remove existing folders - remove_from_kit('XYplorerFree') + # Remove existing folders + remove_from_kit('XYplorerFree') - # Download - download_to_temp('xyplorer_free.zip', SOURCE_URLS['XYplorerFree']) + # Download + download_to_temp('xyplorer_free.zip', SOURCE_URLS['XYplorerFree']) - # Extract files - extract_temp_to_cbin('xyplorer_free.zip', 'XYplorerFree') + # Extract files + extract_temp_to_cbin('xyplorer_free.zip', 'XYplorerFree') - # Cleanup - remove_from_temp('xyplorer_free.zip') + # Cleanup + remove_from_temp('xyplorer_free.zip') ## Diagnostics ## def update_aida64(): - # Stop running processes - kill_process('notepadplusplus.exe') + # Stop running processes + kill_process('notepadplusplus.exe') - # Remove existing folders - remove_from_kit('AIDA64') + # Remove existing folders + remove_from_kit('AIDA64') - # Download - download_to_temp('aida64.zip', SOURCE_URLS['AIDA64']) + # Download + download_to_temp('aida64.zip', SOURCE_URLS['AIDA64']) - # Extract files - extract_temp_to_cbin('aida64.zip', 'AIDA64') + # Extract files + extract_temp_to_cbin('aida64.zip', 'AIDA64') - # Cleanup - remove_from_temp('aida64.zip') + # Cleanup + remove_from_temp('aida64.zip') def update_autoruns(): - # Stop running processes - kill_process('Autoruns.exe') - kill_process('Autoruns64.exe') + # Stop running processes + kill_process('Autoruns.exe') + kill_process('Autoruns64.exe') - # Remove existing folders - remove_from_kit('Autoruns') + # Remove existing folders + remove_from_kit('Autoruns') - # Download - download_to_temp('Autoruns.zip', SOURCE_URLS['Autoruns']) + # Download + download_to_temp('Autoruns.zip', SOURCE_URLS['Autoruns']) - # Extract files - extract_temp_to_cbin('Autoruns.zip', 'Autoruns') + # Extract files + extract_temp_to_cbin('Autoruns.zip', 'Autoruns') - # Cleanup - remove_from_temp('Autoruns.zip') + # Cleanup + remove_from_temp('Autoruns.zip') def update_bleachbit(): - # Stop running processes - kill_process('bleachbit.exe') + # Stop running processes + kill_process('bleachbit.exe') - # Remove existing folders - remove_from_kit('BleachBit') + # Remove existing folders + remove_from_kit('BleachBit') - # Download - download_to_temp('bleachbit.zip', SOURCE_URLS['BleachBit']) - download_to_temp('Winapp2.zip', SOURCE_URLS['Winapp2']) + # Download + download_to_temp('bleachbit.zip', SOURCE_URLS['BleachBit']) + download_to_temp('Winapp2.zip', SOURCE_URLS['Winapp2']) - # Extract files - extract_temp_to_cbin('bleachbit.zip', 'BleachBit') - extract_generic( - r'{}\Winapp2.zip'.format(global_vars['TmpDir']), - r'{}\BleachBit\cleaners'.format(global_vars['CBinDir']), - mode='e', sz_args=[r'Winapp2-master\Non-CCleaner\Winapp2.ini']) + # Extract files + extract_temp_to_cbin('bleachbit.zip', 'BleachBit') + extract_generic( + r'{}\Winapp2.zip'.format(global_vars['TmpDir']), + r'{}\BleachBit\cleaners'.format(global_vars['CBinDir']), + mode='e', sz_args=[r'Winapp2-master\Non-CCleaner\Winapp2.ini']) - # Move files into place - dest = r'{}\BleachBit'.format(global_vars['CBinDir']) - for item in os.scandir(r'{}\BleachBit-Portable'.format(dest)): - dest_item = '{}\{}'.format(dest, item.name) - if not os.path.exists(dest_item): - shutil.move(item.path, dest_item) - shutil.rmtree( - r'{}\BleachBit\BleachBit-Portable'.format(global_vars['CBinDir'])) + # Move files into place + dest = r'{}\BleachBit'.format(global_vars['CBinDir']) + for item in os.scandir(r'{}\BleachBit-Portable'.format(dest)): + dest_item = '{}\{}'.format(dest, item.name) + if not os.path.exists(dest_item): + shutil.move(item.path, dest_item) + shutil.rmtree( + r'{}\BleachBit\BleachBit-Portable'.format(global_vars['CBinDir'])) - # Cleanup - remove_from_temp('bleachbit.zip') - remove_from_temp('Winapp2.zip') + # Cleanup + remove_from_temp('bleachbit.zip') + remove_from_temp('Winapp2.zip') def update_bluescreenview(): - # Stop running processes - for exe in ['BlueScreenView.exe', 'BlueScreenView64.exe']: - kill_process(exe) + # Stop running processes + for exe in ['BlueScreenView.exe', 'BlueScreenView64.exe']: + kill_process(exe) - # Remove existing folders - remove_from_kit('BlueScreenView') + # Remove existing folders + remove_from_kit('BlueScreenView') - # Download - download_to_temp('bluescreenview32.zip', SOURCE_URLS['BlueScreenView32']) - download_to_temp('bluescreenview64.zip', SOURCE_URLS['BlueScreenView64']) + # Download + download_to_temp('bluescreenview32.zip', SOURCE_URLS['BlueScreenView32']) + download_to_temp('bluescreenview64.zip', SOURCE_URLS['BlueScreenView64']) - # Extract files - extract_temp_to_cbin('bluescreenview64.zip', 'BlueScreenView', sz_args=['BlueScreenView.exe']) - shutil.move( - r'{}\BlueScreenView\BlueScreenView.exe'.format(global_vars['CBinDir']), - r'{}\BlueScreenView\BlueScreenView64.exe'.format(global_vars['CBinDir'])) - extract_temp_to_cbin('bluescreenview32.zip', 'BlueScreenView') + # Extract files + extract_temp_to_cbin( + 'bluescreenview64.zip', 'BlueScreenView', sz_args=['BlueScreenView.exe']) + shutil.move( + r'{}\BlueScreenView\BlueScreenView.exe'.format(global_vars['CBinDir']), + r'{}\BlueScreenView\BlueScreenView64.exe'.format(global_vars['CBinDir'])) + extract_temp_to_cbin('bluescreenview32.zip', 'BlueScreenView') - # Cleanup - remove_from_temp('bluescreenview32.zip') - remove_from_temp('bluescreenview64.zip') + # Cleanup + remove_from_temp('bluescreenview32.zip') + remove_from_temp('bluescreenview64.zip') def update_erunt(): - # Stop running processes - kill_process('ERUNT.EXE') + # Stop running processes + kill_process('ERUNT.EXE') - # Remove existing folders - remove_from_kit('ERUNT') + # Remove existing folders + remove_from_kit('ERUNT') - # Download - download_to_temp('erunt.zip', SOURCE_URLS['ERUNT']) + # Download + download_to_temp('erunt.zip', SOURCE_URLS['ERUNT']) - # Extract files - extract_temp_to_cbin('erunt.zip', 'ERUNT') + # Extract files + extract_temp_to_cbin('erunt.zip', 'ERUNT') - # Cleanup - remove_from_temp('erunt.zip') + # Cleanup + remove_from_temp('erunt.zip') def update_hitmanpro(): - # Stop running processes - for exe in ['HitmanPro.exe', 'HitmanPro64.exe']: - kill_process(exe) + # Stop running processes + for exe in ['HitmanPro.exe', 'HitmanPro64.exe']: + kill_process(exe) - # Remove existing folders - remove_from_kit('HitmanPro') + # Remove existing folders + remove_from_kit('HitmanPro') - # Download - dest = r'{}\HitmanPro'.format(global_vars['CBinDir']) - download_generic(dest, 'HitmanPro.exe', SOURCE_URLS['HitmanPro32']) - download_generic(dest, 'HitmanPro64.exe', SOURCE_URLS['HitmanPro64']) + # Download + dest = r'{}\HitmanPro'.format(global_vars['CBinDir']) + download_generic(dest, 'HitmanPro.exe', SOURCE_URLS['HitmanPro32']) + download_generic(dest, 'HitmanPro64.exe', SOURCE_URLS['HitmanPro64']) def update_hwinfo(): - ## NOTE: Lives in .bin uncompressed - # Stop running processes - for exe in ['HWiNFO32.exe', 'HWiNFO64.exe']: - kill_process(exe) + ## NOTE: Lives in .bin uncompressed + # Stop running processes + for exe in ['HWiNFO32.exe', 'HWiNFO64.exe']: + kill_process(exe) - # Download - download_to_temp('HWiNFO.zip', SOURCE_URLS['HWiNFO']) + # Download + download_to_temp('HWiNFO.zip', SOURCE_URLS['HWiNFO']) - # Extract files - extract_temp_to_bin('HWiNFO.zip', 'HWiNFO') + # Extract files + extract_temp_to_bin('HWiNFO.zip', 'HWiNFO') - # Cleanup - remove_from_temp('HWiNFO.zip') + # Cleanup + remove_from_temp('HWiNFO.zip') def update_nircmd(): - # Stop running processes - for exe in ['nircmdc.exe', 'nircmdc64.exe']: - kill_process(exe) + # Stop running processes + for exe in ['nircmdc.exe', 'nircmdc64.exe']: + kill_process(exe) - # Remove existing folders - remove_from_kit('NirCmd') + # Remove existing folders + remove_from_kit('NirCmd') - # Download - download_to_temp('nircmd32.zip', SOURCE_URLS['NirCmd32']) - download_to_temp('nircmd64.zip', SOURCE_URLS['NirCmd64']) + # Download + download_to_temp('nircmd32.zip', SOURCE_URLS['NirCmd32']) + download_to_temp('nircmd64.zip', SOURCE_URLS['NirCmd64']) - # Extract files - extract_temp_to_cbin('nircmd64.zip', 'NirCmd', sz_args=['nircmdc.exe']) - shutil.move( - r'{}\NirCmd\nircmdc.exe'.format(global_vars['CBinDir']), - r'{}\NirCmd\nircmdc64.exe'.format(global_vars['CBinDir'])) - extract_temp_to_cbin('nircmd32.zip', 'NirCmd', sz_args=['nircmdc.exe']) + # Extract files + extract_temp_to_cbin('nircmd64.zip', 'NirCmd', sz_args=['nircmdc.exe']) + shutil.move( + r'{}\NirCmd\nircmdc.exe'.format(global_vars['CBinDir']), + r'{}\NirCmd\nircmdc64.exe'.format(global_vars['CBinDir'])) + extract_temp_to_cbin('nircmd32.zip', 'NirCmd', sz_args=['nircmdc.exe']) - # Cleanup - remove_from_temp('nircmd32.zip') - remove_from_temp('nircmd64.zip') + # Cleanup + remove_from_temp('nircmd32.zip') + remove_from_temp('nircmd64.zip') def update_produkey(): - # Stop running processes - for exe in ['ProduKey.exe', 'ProduKey64.exe']: - kill_process(exe) + # Stop running processes + for exe in ['ProduKey.exe', 'ProduKey64.exe']: + kill_process(exe) - # Remove existing folders - remove_from_kit('ProduKey') + # Remove existing folders + remove_from_kit('ProduKey') - # Download - download_to_temp('produkey32.zip', SOURCE_URLS['ProduKey32']) - download_to_temp('produkey64.zip', SOURCE_URLS['ProduKey64']) + # Download + download_to_temp('produkey32.zip', SOURCE_URLS['ProduKey32']) + download_to_temp('produkey64.zip', SOURCE_URLS['ProduKey64']) - # Extract files - extract_temp_to_cbin('produkey64.zip', 'ProduKey', sz_args=['ProduKey.exe']) - shutil.move( - r'{}\ProduKey\ProduKey.exe'.format(global_vars['CBinDir']), - r'{}\ProduKey\ProduKey64.exe'.format(global_vars['CBinDir'])) - extract_temp_to_cbin('produkey32.zip', 'ProduKey') + # Extract files + extract_temp_to_cbin('produkey64.zip', 'ProduKey', sz_args=['ProduKey.exe']) + shutil.move( + r'{}\ProduKey\ProduKey.exe'.format(global_vars['CBinDir']), + r'{}\ProduKey\ProduKey64.exe'.format(global_vars['CBinDir'])) + extract_temp_to_cbin('produkey32.zip', 'ProduKey') - # Cleanup - remove_from_temp('produkey32.zip') - remove_from_temp('produkey64.zip') + # Cleanup + remove_from_temp('produkey32.zip') + remove_from_temp('produkey64.zip') ## Drivers ## def update_intel_rst(): - # Remove existing folders - remove_from_kit('Intel RST') + # Remove existing folders + remove_from_kit('Intel RST') - # Prep - dest = r'{}\_Drivers\Intel RST'.format(global_vars['CBinDir']) - include_path = r'{}\_include\_Drivers\Intel RST'.format( - global_vars['CBinDir']) - if os.path.exists(include_path): - shutil.copytree(include_path, dest) + # Prep + dest = r'{}\_Drivers\Intel RST'.format(global_vars['CBinDir']) + include_path = r'{}\_include\_Drivers\Intel RST'.format( + global_vars['CBinDir']) + if os.path.exists(include_path): + shutil.copytree(include_path, dest) - # Download - for name, url in RST_SOURCES.items(): - download_generic(dest, name, url) + # Download + for name, url in RST_SOURCES.items(): + download_generic(dest, name, url) def update_intel_ssd_toolbox(): - # Remove existing folders - remove_from_kit('Intel SSD Toolbox.exe') + # Remove existing folders + remove_from_kit('Intel SSD Toolbox.exe') - # Download - download_generic( - r'{}\_Drivers\Intel SSD Toolbox'.format(global_vars['CBinDir']), - 'Intel SSD Toolbox.exe', - SOURCE_URLS['Intel SSD Toolbox']) + # Download + download_generic( + r'{}\_Drivers\Intel SSD Toolbox'.format(global_vars['CBinDir']), + 'Intel SSD Toolbox.exe', + SOURCE_URLS['Intel SSD Toolbox']) def update_samsung_magician(): - # Remove existing folders - remove_from_kit('Samsung Magician.exe') + # Remove existing folders + remove_from_kit('Samsung Magician.exe') - # Download - download_to_temp('Samsung Magician.zip', SOURCE_URLS['Samsung Magician']) + # Download + download_to_temp('Samsung Magician.zip', SOURCE_URLS['Samsung Magician']) - # Extract - extract_temp_to_cbin('Samsung Magician.zip', '_Drivers\Samsung Magician') - shutil.move( - r'{}\_Drivers\Samsung Magician\Samsung_Magician_Installer.exe'.format( - global_vars['CBinDir']), - r'{}\_Drivers\Samsung Magician\Samsung Magician.exe'.format( - global_vars['CBinDir'])) + # Extract + extract_temp_to_cbin('Samsung Magician.zip', '_Drivers\Samsung Magician') + shutil.move( + r'{}\_Drivers\Samsung Magician\Samsung_Magician_Installer.exe'.format( + global_vars['CBinDir']), + r'{}\_Drivers\Samsung Magician\Samsung Magician.exe'.format( + global_vars['CBinDir'])) - # Cleanup - remove_from_temp('Samsung Magician.zip') + # Cleanup + remove_from_temp('Samsung Magician.zip') def update_sdi_origin(): - # Download aria2 - download_to_temp('aria2.zip', SOURCE_URLS['aria2']) - aria_source = r'{}\aria2.zip'.format(global_vars['TmpDir']) - aria_dest = r'{}\aria2'.format(global_vars['TmpDir']) - aria = r'{}\aria2c.exe'.format(aria_dest) - extract_generic(aria_source, aria_dest, mode='e') + # Download aria2 + download_to_temp('aria2.zip', SOURCE_URLS['aria2']) + aria_source = r'{}\aria2.zip'.format(global_vars['TmpDir']) + aria_dest = r'{}\aria2'.format(global_vars['TmpDir']) + aria = r'{}\aria2c.exe'.format(aria_dest) + extract_generic(aria_source, aria_dest, mode='e') - # Prep for torrent download - download_to_temp('sdio.torrent', SOURCE_URLS['SDIO Torrent']) - sdio_torrent = r'{}\sdio.torrent'.format(global_vars['TmpDir']) - out = run_program([aria, sdio_torrent, '-S']) - indexes = [] - for line in out.stdout.decode().splitlines(): - r = re.search(r'^\s*(\d+)\|(.*)', line) - if r and not re.search(r'(\.(bat|inf)|Video|Server|Printer|XP)', line, re.IGNORECASE): - indexes.append(int(r.group(1))) - indexes = [str(i) for i in sorted(indexes)] + # Prep for torrent download + download_to_temp('sdio.torrent', SOURCE_URLS['SDIO Torrent']) + sdio_torrent = r'{}\sdio.torrent'.format(global_vars['TmpDir']) + out = run_program([aria, sdio_torrent, '-S']) + indexes = [] + for line in out.stdout.decode().splitlines(): + r = re.search(r'^\s*(\d+)\|(.*)', line) + if (r and not re.search( + r'(\.(bat|inf)|Video|Server|Printer|XP)', line, re.IGNORECASE)): + indexes.append(int(r.group(1))) + indexes = [str(i) for i in sorted(indexes)] - # Download SDI Origin - cmd = [ - aria, - '--select-file={}'.format(','.join(indexes)), - '-d', aria_dest, - '--seed-time=0', - sdio_torrent, - '-new_console:n', '-new_console:s33V', - ] - run_program(cmd, pipe=False, check=False, shell=True) - sleep(1) - wait_for_process('aria2c') + # Download SDI Origin + cmd = [ + aria, + '--select-file={}'.format(','.join(indexes)), + '-d', aria_dest, + '--seed-time=0', + sdio_torrent, + '-new_console:n', '-new_console:s33V', + ] + run_program(cmd, pipe=False, check=False, shell=True) + sleep(1) + wait_for_process('aria2c') - # Download SDI Origin extra themes - download_to_temp('sdio_themes.zip', SOURCE_URLS['SDIO Themes']) - theme_source = r'{}\sdio_themes.zip'.format(global_vars['TmpDir']) - theme_dest = r'{}\SDIO_Update\tools\SDI\themes'.format(aria_dest) - extract_generic(theme_source, theme_dest) + # Download SDI Origin extra themes + download_to_temp('sdio_themes.zip', SOURCE_URLS['SDIO Themes']) + theme_source = r'{}\sdio_themes.zip'.format(global_vars['TmpDir']) + theme_dest = r'{}\SDIO_Update\tools\SDI\themes'.format(aria_dest) + extract_generic(theme_source, theme_dest) - # Move files into place - for item in os.scandir(r'{}\SDIO_Update'.format(aria_dest)): - dest_item = '{}\_Drivers\SDIO\{}'.format( - global_vars['BinDir'], item.name) - r = re.search(r'^SDIO_x?(64|)_?R.*exe$', item.name, re.IGNORECASE) - if r: - dest_item = dest_item.replace(item.name, 'SDIO{}.exe'.format( - r.group(1))) - if (not os.path.exists(dest_item) - and not re.search(r'\.(inf|bat)$', item.name, re.IGNORECASE)): - shutil.move(item.path, dest_item) + # Move files into place + for item in os.scandir(r'{}\SDIO_Update'.format(aria_dest)): + dest_item = '{}\_Drivers\SDIO\{}'.format( + global_vars['BinDir'], item.name) + r = re.search(r'^SDIO_x?(64|)_?R.*exe$', item.name, re.IGNORECASE) + if r: + dest_item = dest_item.replace(item.name, 'SDIO{}.exe'.format( + r.group(1))) + if (not os.path.exists(dest_item) + and not re.search(r'\.(inf|bat)$', item.name, re.IGNORECASE)): + shutil.move(item.path, dest_item) - # Cleanup - remove_from_temp('aria2') - remove_from_temp('aria2.zip') - remove_from_temp('sdio.torrent') - remove_from_temp('sdio_themes.zip') + # Cleanup + remove_from_temp('aria2') + remove_from_temp('aria2.zip') + remove_from_temp('sdio.torrent') + remove_from_temp('sdio_themes.zip') ## Installers ## def update_adobe_reader_dc(): - # Prep - dest = r'{}\Installers\Extras\Office'.format( - global_vars['BaseDir']) + # Prep + dest = r'{}\Installers\Extras\Office'.format( + global_vars['BaseDir']) - # Remove existing installer - try: - os.remove(r'{}\Adobe Reader DC.exe'.format(dest)) - except FileNotFoundError: - pass + # Remove existing installer + try: + os.remove(r'{}\Adobe Reader DC.exe'.format(dest)) + except FileNotFoundError: + pass - # Download - download_generic( - dest, 'Adobe Reader DC.exe', SOURCE_URLS['Adobe Reader DC']) + # Download + download_generic( + dest, 'Adobe Reader DC.exe', SOURCE_URLS['Adobe Reader DC']) def update_macs_fan_control(): - # Prep - dest = r'{}\Installers'.format( - global_vars['BaseDir']) + # Prep + dest = r'{}\Installers'.format( + global_vars['BaseDir']) - # Remove existing installer - try: - os.remove(r'{}\Macs Fan Control.exe'.format(dest)) - except FileNotFoundError: - pass + # Remove existing installer + try: + os.remove(r'{}\Macs Fan Control.exe'.format(dest)) + except FileNotFoundError: + pass - # Download - download_generic( - dest, 'Macs Fan Control.exe', SOURCE_URLS['Macs Fan Control']) + # Download + download_generic( + dest, 'Macs Fan Control.exe', SOURCE_URLS['Macs Fan Control']) def update_office(): - # Remove existing folders - remove_from_kit('_Office') + # Remove existing folders + remove_from_kit('_Office') - # Prep - dest = r'{}\_Office'.format(global_vars['CBinDir']) - include_path = r'{}\_include\_Office'.format(global_vars['CBinDir']) - if os.path.exists(include_path): - shutil.copytree(include_path, dest) + # Prep + dest = r'{}\_Office'.format(global_vars['CBinDir']) + include_path = r'{}\_include\_Office'.format(global_vars['CBinDir']) + if os.path.exists(include_path): + shutil.copytree(include_path, dest) - for year in ['2016']: - # Download and extract - name = 'odt{}.exe'.format(year) - url = 'Office Deployment Tool {}'.format(year) - download_to_temp(name, SOURCE_URLS[url]) - cmd = [ - r'{}\odt{}.exe'.format(global_vars['TmpDir'], year), - r'/extract:{}\{}'.format(global_vars['TmpDir'], year), - '/quiet', - ] - run_program(cmd) - shutil.move( - r'{}\{}'.format(global_vars['TmpDir'], year), - r'{}\_Office\{}'.format(global_vars['CBinDir'], year)) + for year in ['2016']: + # Download and extract + name = 'odt{}.exe'.format(year) + url = 'Office Deployment Tool {}'.format(year) + download_to_temp(name, SOURCE_URLS[url]) + cmd = [ + r'{}\odt{}.exe'.format(global_vars['TmpDir'], year), + r'/extract:{}\{}'.format(global_vars['TmpDir'], year), + '/quiet', + ] + run_program(cmd) + shutil.move( + r'{}\{}'.format(global_vars['TmpDir'], year), + r'{}\_Office\{}'.format(global_vars['CBinDir'], year)) - # Cleanup - remove_from_temp('odt{}.exe'.format(year)) + # Cleanup + remove_from_temp('odt{}.exe'.format(year)) def update_classic_start_skin(): - # Remove existing folders - remove_from_kit('ClassicStartSkin') + # Remove existing folders + remove_from_kit('ClassicStartSkin') - # Download - download_generic( - r'{}\ClassicStartSkin'.format(global_vars['CBinDir']), - 'Metro-Win10-Black.skin7', - SOURCE_URLS['ClassicStartSkin']) + # Download + download_generic( + r'{}\ClassicStartSkin'.format(global_vars['CBinDir']), + 'Metro-Win10-Black.skin7', + SOURCE_URLS['ClassicStartSkin']) def update_vcredists(): - # Remove existing folders - remove_from_kit('_vcredists') + # Remove existing folders + remove_from_kit('_vcredists') - # Prep - dest = r'{}\_vcredists'.format(global_vars['CBinDir']) - include_path = r'{}\_include\_vcredists'.format(global_vars['CBinDir']) - if os.path.exists(include_path): - shutil.copytree(include_path, dest) + # Prep + dest = r'{}\_vcredists'.format(global_vars['CBinDir']) + include_path = r'{}\_include\_vcredists'.format(global_vars['CBinDir']) + if os.path.exists(include_path): + shutil.copytree(include_path, dest) - # Download - for year in VCREDIST_SOURCES.keys(): - for bit in ['32', '64']: - dest = r'{}\_vcredists\{}\x{}'.format( - global_vars['CBinDir'], year, bit) - download_generic( - dest, - 'vcredist.exe', - VCREDIST_SOURCES[year][bit]) + # Download + for year in VCREDIST_SOURCES.keys(): + for bit in ['32', '64']: + dest = r'{}\_vcredists\{}\x{}'.format( + global_vars['CBinDir'], year, bit) + download_generic( + dest, + 'vcredist.exe', + VCREDIST_SOURCES[year][bit]) def update_one_ninite(section, dest, name, url, indent=8, width=40): - # Prep - url = 'https://ninite.com/{}/ninite.exe'.format(url) + # Prep + url = 'https://ninite.com/{}/ninite.exe'.format(url) - # Download - download_generic(out_dir=dest, out_name=name, source_url=url) + # Download + download_generic(out_dir=dest, out_name=name, source_url=url) - # Copy to Installers folder - installer_parent = r'{}\Installers\Extras\{}'.format( - global_vars['BaseDir'], section) - installer_dest = r'{}\{}'.format(installer_parent, name) - os.makedirs(installer_parent, exist_ok=True) - if os.path.exists(installer_dest): - remove_item(installer_dest) - shutil.copy(r'{}\{}'.format(dest, name), installer_dest) + # Copy to Installers folder + installer_parent = r'{}\Installers\Extras\{}'.format( + global_vars['BaseDir'], section) + installer_dest = r'{}\{}'.format(installer_parent, name) + os.makedirs(installer_parent, exist_ok=True) + if os.path.exists(installer_dest): + remove_item(installer_dest) + shutil.copy(r'{}\{}'.format(dest, name), installer_dest) def update_all_ninite(indent=8, width=40, other_results={}): - print_info('{}Ninite'.format(' '*int(indent/2))) - for section in sorted(NINITE_SOURCES.keys()): - print_success('{}{}'.format(' '*int(indent/4*3), section)) - dest = r'{}\_Ninite\{}'.format(global_vars['CBinDir'], section) - for name, url in sorted(NINITE_SOURCES[section].items()): - try_and_print(message=name, function=update_one_ninite, - other_results=other_results, indent=indent, width=width, - section=section, dest=dest, name=name, url=url) + print_info('{}Ninite'.format(' '*int(indent/2))) + for section in sorted(NINITE_SOURCES.keys()): + print_success('{}{}'.format(' '*int(indent/4*3), section)) + dest = r'{}\_Ninite\{}'.format(global_vars['CBinDir'], section) + for name, url in sorted(NINITE_SOURCES[section].items()): + try_and_print(message=name, function=update_one_ninite, + other_results=other_results, indent=indent, width=width, + section=section, dest=dest, name=name, url=url) ## Misc ## def update_caffeine(): - # Stop running processes - kill_process('caffeine.exe') + # Stop running processes + kill_process('caffeine.exe') - # Remove existing folders - remove_from_kit('Caffeine') + # Remove existing folders + remove_from_kit('Caffeine') - # Download - download_to_temp('caffeine.zip', SOURCE_URLS['Caffeine']) + # Download + download_to_temp('caffeine.zip', SOURCE_URLS['Caffeine']) - # Extract files - extract_temp_to_cbin('caffeine.zip', 'Caffeine') + # Extract files + extract_temp_to_cbin('caffeine.zip', 'Caffeine') - # Cleanup - remove_from_temp('caffeine.zip') + # Cleanup + remove_from_temp('caffeine.zip') def update_du(): - # Stop running processes - kill_process('du.exe') - kill_process('du64.exe') + # Stop running processes + kill_process('du.exe') + kill_process('du64.exe') - # Remove existing folders - remove_from_kit('Du') + # Remove existing folders + remove_from_kit('Du') - # Download - download_to_temp('du.zip', SOURCE_URLS['Du']) + # Download + download_to_temp('du.zip', SOURCE_URLS['Du']) - # Extract files - extract_temp_to_cbin('du.zip', 'Du') + # Extract files + extract_temp_to_cbin('du.zip', 'Du') - # Cleanup - remove_from_temp('du.zip') + # Cleanup + remove_from_temp('du.zip') def update_everything(): - # Stop running processes - for exe in ['Everything.exe', 'Everything64.exe']: - kill_process(exe) + # Stop running processes + for exe in ['Everything.exe', 'Everything64.exe']: + kill_process(exe) - # Remove existing folders - remove_from_kit('Everything') + # Remove existing folders + remove_from_kit('Everything') - # Download - download_to_temp('everything32.zip', SOURCE_URLS['Everything32']) - download_to_temp('everything64.zip', SOURCE_URLS['Everything64']) + # Download + download_to_temp('everything32.zip', SOURCE_URLS['Everything32']) + download_to_temp('everything64.zip', SOURCE_URLS['Everything64']) - # Extract files - extract_temp_to_cbin('everything64.zip', 'Everything', sz_args=['Everything.exe']) - shutil.move( - r'{}\Everything\Everything.exe'.format(global_vars['CBinDir']), - r'{}\Everything\Everything64.exe'.format(global_vars['CBinDir'])) - extract_temp_to_cbin('everything32.zip', 'Everything') + # Extract files + extract_temp_to_cbin( + 'everything64.zip', 'Everything', sz_args=['Everything.exe']) + shutil.move( + r'{}\Everything\Everything.exe'.format(global_vars['CBinDir']), + r'{}\Everything\Everything64.exe'.format(global_vars['CBinDir'])) + extract_temp_to_cbin('everything32.zip', 'Everything') - # Cleanup - remove_from_temp('everything32.zip') - remove_from_temp('everything64.zip') + # Cleanup + remove_from_temp('everything32.zip') + remove_from_temp('everything64.zip') def update_firefox_ublock_origin(): - # Remove existing folders - remove_from_kit('FirefoxExtensions') + # Remove existing folders + remove_from_kit('FirefoxExtensions') - # Download - download_generic( - r'{}\FirefoxExtensions'.format(global_vars['CBinDir']), - 'ublock_origin.xpi', - SOURCE_URLS['Firefox uBO']) + # Download + download_generic( + r'{}\FirefoxExtensions'.format(global_vars['CBinDir']), + 'ublock_origin.xpi', + SOURCE_URLS['Firefox uBO']) def update_notepadplusplus(): - # Stop running processes - kill_process('notepadplusplus.exe') + # Stop running processes + kill_process('notepadplusplus.exe') - # Remove existing folders - remove_from_kit('NotepadPlusPlus') + # Remove existing folders + remove_from_kit('NotepadPlusPlus') - # Download - download_to_temp('npp.7z', SOURCE_URLS['NotepadPlusPlus']) + # Download + download_to_temp('npp.7z', SOURCE_URLS['NotepadPlusPlus']) - # Extract files - extract_temp_to_cbin('npp.7z', 'NotepadPlusPlus') - shutil.move( - r'{}\NotepadPlusPlus\notepad++.exe'.format(global_vars['CBinDir']), - r'{}\NotepadPlusPlus\notepadplusplus.exe'.format(global_vars['CBinDir']) - ) + # Extract files + extract_temp_to_cbin('npp.7z', 'NotepadPlusPlus') + shutil.move( + r'{}\NotepadPlusPlus\notepad++.exe'.format(global_vars['CBinDir']), + r'{}\NotepadPlusPlus\notepadplusplus.exe'.format(global_vars['CBinDir']) + ) - # Cleanup - remove_from_temp('npp.7z') + # Cleanup + remove_from_temp('npp.7z') def update_putty(): - # Stop running processes - kill_process('PUTTY.EXE') + # Stop running processes + kill_process('PUTTY.EXE') - # Remove existing folders - remove_from_kit('PuTTY') + # Remove existing folders + remove_from_kit('PuTTY') - # Download - download_to_temp('putty.zip', SOURCE_URLS['PuTTY']) + # Download + download_to_temp('putty.zip', SOURCE_URLS['PuTTY']) - # Extract files - extract_temp_to_cbin('putty.zip', 'PuTTY') + # Extract files + extract_temp_to_cbin('putty.zip', 'PuTTY') - # Cleanup - remove_from_temp('putty.zip') + # Cleanup + remove_from_temp('putty.zip') def update_wiztree(): - # Stop running processes - for process in ['WizTree.exe', 'WizTree64.exe']: - kill_process(process) + # Stop running processes + for process in ['WizTree.exe', 'WizTree64.exe']: + kill_process(process) - # Remove existing folders - remove_from_kit('WizTree') + # Remove existing folders + remove_from_kit('WizTree') - # Download - download_to_temp( - 'wiztree.zip', SOURCE_URLS['WizTree']) + # Download + download_to_temp( + 'wiztree.zip', SOURCE_URLS['WizTree']) - # Extract files - extract_temp_to_cbin('wiztree.zip', 'WizTree') + # Extract files + extract_temp_to_cbin('wiztree.zip', 'WizTree') - # Cleanup - remove_from_temp('wiztree.zip') + # Cleanup + remove_from_temp('wiztree.zip') def update_xmplay(): - # Stop running processes - kill_process('xmplay.exe') + # Stop running processes + kill_process('xmplay.exe') - # Remove existing folders - remove_from_kit('XMPlay') + # Remove existing folders + remove_from_kit('XMPlay') - # Download - download_to_temp('xmplay.zip', SOURCE_URLS['XMPlay']) - download_to_temp('xmp-7z.zip', SOURCE_URLS['XMPlay 7z']) - download_to_temp('xmp-gme.zip', SOURCE_URLS['XMPlay Game']) - download_to_temp('xmp-rar.zip', SOURCE_URLS['XMPlay RAR']) - download_to_temp('WAModern.zip', SOURCE_URLS['XMPlay WAModern']) + # Download + download_to_temp('xmplay.zip', SOURCE_URLS['XMPlay']) + download_to_temp('xmp-7z.zip', SOURCE_URLS['XMPlay 7z']) + download_to_temp('xmp-gme.zip', SOURCE_URLS['XMPlay Game']) + download_to_temp('xmp-rar.zip', SOURCE_URLS['XMPlay RAR']) + download_to_temp('WAModern.zip', SOURCE_URLS['XMPlay WAModern']) - # Extract files - extract_temp_to_cbin('xmplay.zip', 'XMPlay', - mode='e', sz_args=['xmplay.exe', 'xmplay.txt']) - for item in ['xmp-7z', 'xmp-gme', 'xmp-rar', 'WAModern']: - filter = [] - if item == 'WAModern': - filter.append('WAModern NightVision.xmpskin') - extract_generic( - r'{}\{}.zip'.format(global_vars['TmpDir'], item), - r'{}\XMPlay\plugins'.format(global_vars['CBinDir']), - mode='e', sz_args=filter) + # Extract files + extract_temp_to_cbin('xmplay.zip', 'XMPlay', + mode='e', sz_args=['xmplay.exe', 'xmplay.txt']) + for item in ['xmp-7z', 'xmp-gme', 'xmp-rar', 'WAModern']: + filter = [] + if item == 'WAModern': + filter.append('WAModern NightVision.xmpskin') + extract_generic( + r'{}\{}.zip'.format(global_vars['TmpDir'], item), + r'{}\XMPlay\plugins'.format(global_vars['CBinDir']), + mode='e', sz_args=filter) - # Download Music - dest = r'{}\XMPlay\music_tmp\MOD'.format(global_vars['CBinDir']) - for mod in MUSIC_MOD: - name = mod.split('#')[-1] - url = 'https://api.modarchive.org/downloads.php?moduleid={}'.format(mod) - download_generic(dest, name, url) - dest = r'{}\XMPlay\music_tmp\SNES'.format(global_vars['CBinDir']) - for game in MUSIC_SNES: - name = '{}.rsn'.format(game) - url = 'http://snesmusic.org/v2/download.php?spcNow={}'.format(game) - download_generic(dest, name, url) + # Download Music + dest = r'{}\XMPlay\music_tmp\MOD'.format(global_vars['CBinDir']) + for mod in MUSIC_MOD: + name = mod.split('#')[-1] + url = 'https://api.modarchive.org/downloads.php?moduleid={}'.format(mod) + download_generic(dest, name, url) + dest = r'{}\XMPlay\music_tmp\SNES'.format(global_vars['CBinDir']) + for game in MUSIC_SNES: + name = '{}.rsn'.format(game) + url = 'http://snesmusic.org/v2/download.php?spcNow={}'.format(game) + download_generic(dest, name, url) - # Compress Music - cmd = [ - global_vars['Tools']['SevenZip'], - 'a', r'{}\XMPlay\music.7z'.format(global_vars['CBinDir']), - '-t7z', '-mx=9', '-bso0', '-bse0', - r'{}\XMPlay\music_tmp\*'.format(global_vars['CBinDir']), - ] - run_program(cmd) + # Compress Music + cmd = [ + global_vars['Tools']['SevenZip'], + 'a', r'{}\XMPlay\music.7z'.format(global_vars['CBinDir']), + '-t7z', '-mx=9', '-bso0', '-bse0', + r'{}\XMPlay\music_tmp\*'.format(global_vars['CBinDir']), + ] + run_program(cmd) - # Cleanup - remove_item(r'{}\XMPlay\music_tmp'.format(global_vars['CBinDir'])) - remove_from_temp('xmplay.zip') - remove_from_temp('xmp-7z.zip') - remove_from_temp('xmp-gme.zip') - remove_from_temp('xmp-rar.zip') - remove_from_temp('WAModern.zip') + # Cleanup + remove_item(r'{}\XMPlay\music_tmp'.format(global_vars['CBinDir'])) + remove_from_temp('xmplay.zip') + remove_from_temp('xmp-7z.zip') + remove_from_temp('xmp-gme.zip') + remove_from_temp('xmp-rar.zip') + remove_from_temp('WAModern.zip') ## Repairs ## def update_adwcleaner(): - # Stop running processes - kill_process('AdwCleaner.exe') + # Stop running processes + kill_process('AdwCleaner.exe') - # Remove existing folders - remove_from_kit('AdwCleaner') + # Remove existing folders + remove_from_kit('AdwCleaner') - # Download - download_generic( - r'{}\AdwCleaner'.format(global_vars['CBinDir']), - 'AdwCleaner.exe', - SOURCE_URLS['AdwCleaner']) + # Download + download_generic( + r'{}\AdwCleaner'.format(global_vars['CBinDir']), + 'AdwCleaner.exe', + SOURCE_URLS['AdwCleaner']) def update_kvrt(): - # Stop running processes - kill_process('KVRT.exe') + # Stop running processes + kill_process('KVRT.exe') - # Remove existing folders - remove_from_kit('KVRT') + # Remove existing folders + remove_from_kit('KVRT') - # Download - download_generic( - r'{}\KVRT'.format(global_vars['CBinDir']), - 'KVRT.exe', - SOURCE_URLS['KVRT']) + # Download + download_generic( + r'{}\KVRT'.format(global_vars['CBinDir']), + 'KVRT.exe', + SOURCE_URLS['KVRT']) def update_rkill(): - # Stop running processes - kill_process('RKill.exe') + # Stop running processes + kill_process('RKill.exe') - # Remove existing folders - remove_from_kit('RKill') + # Remove existing folders + remove_from_kit('RKill') - # Download - url = resolve_dynamic_url( - SOURCE_URLS['RKill'], - 'href.*rkill\.exe') - download_generic( - r'{}\RKill'.format(global_vars['CBinDir']), 'RKill.exe', url) + # Download + url = resolve_dynamic_url( + SOURCE_URLS['RKill'], + 'href.*rkill\.exe') + download_generic( + r'{}\RKill'.format(global_vars['CBinDir']), 'RKill.exe', url) def update_tdsskiller(): - # Stop running processes - kill_process('TDSSKiller.exe') + # Stop running processes + kill_process('TDSSKiller.exe') - # Remove existing folders - remove_from_kit('TDSSKiller') + # Remove existing folders + remove_from_kit('TDSSKiller') - # Download - download_generic( - r'{}\TDSSKiller'.format(global_vars['CBinDir']), - 'TDSSKiller.exe', - SOURCE_URLS['TDSSKiller']) + # Download + download_generic( + r'{}\TDSSKiller'.format(global_vars['CBinDir']), + 'TDSSKiller.exe', + SOURCE_URLS['TDSSKiller']) ## Uninstallers ## def update_iobit_uninstaller(): - # Stop running processes - kill_process('IObitUninstallerPortable.exe') + # Stop running processes + kill_process('IObitUninstallerPortable.exe') - # Remove existing folders - remove_from_kit('IObitUninstallerPortable') + # Remove existing folders + remove_from_kit('IObitUninstallerPortable') - # Download - download_generic( - global_vars['CBinDir'], - 'IObitUninstallerPortable.exe', - SOURCE_URLS['IOBit_Uninstaller']) + # Download + download_generic( + global_vars['CBinDir'], + 'IObitUninstallerPortable.exe', + SOURCE_URLS['IOBit_Uninstaller']) - # "Install" - cmd = r'{}\IObitUninstallerPortable.exe'.format(global_vars['CBinDir']) - popen_program(cmd) - sleep(1) - wait_for_process('IObitUninstallerPortable') + # "Install" + cmd = r'{}\IObitUninstallerPortable.exe'.format(global_vars['CBinDir']) + popen_program(cmd) + sleep(1) + wait_for_process('IObitUninstallerPortable') - # Cleanup - remove_from_kit('IObitUninstallerPortable.exe') + # Cleanup + remove_from_kit('IObitUninstallerPortable.exe') if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From ec0341027e2575400fb4e3cc93e7f6b41b1d09a0 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 20:14:29 -0700 Subject: [PATCH 173/265] Updated windows_setup.py --- .bin/Scripts/functions/windows_setup.py | 380 ++++++++++++------------ 1 file changed, 191 insertions(+), 189 deletions(-) diff --git a/.bin/Scripts/functions/windows_setup.py b/.bin/Scripts/functions/windows_setup.py index 0952e64d..228e43e2 100644 --- a/.bin/Scripts/functions/windows_setup.py +++ b/.bin/Scripts/functions/windows_setup.py @@ -5,234 +5,236 @@ from functions.disk import * # STATIC VARIABLES WINDOWS_VERSIONS = [ - {'Name': 'Windows 7 Home Basic', - 'Image File': 'Win7', - 'Image Name': 'Windows 7 HOMEBASIC'}, - {'Name': 'Windows 7 Home Premium', - 'Image File': 'Win7', - 'Image Name': 'Windows 7 HOMEPREMIUM'}, - {'Name': 'Windows 7 Professional', - 'Image File': 'Win7', - 'Image Name': 'Windows 7 PROFESSIONAL'}, - {'Name': 'Windows 7 Ultimate', - 'Image File': 'Win7', - 'Image Name': 'Windows 7 ULTIMATE'}, + {'Name': 'Windows 7 Home Basic', + 'Image File': 'Win7', + 'Image Name': 'Windows 7 HOMEBASIC'}, + {'Name': 'Windows 7 Home Premium', + 'Image File': 'Win7', + 'Image Name': 'Windows 7 HOMEPREMIUM'}, + {'Name': 'Windows 7 Professional', + 'Image File': 'Win7', + 'Image Name': 'Windows 7 PROFESSIONAL'}, + {'Name': 'Windows 7 Ultimate', + 'Image File': 'Win7', + 'Image Name': 'Windows 7 ULTIMATE'}, - {'Name': 'Windows 8.1', - 'Image File': 'Win8', - 'Image Name': 'Windows 8.1', - 'CRLF': True}, - {'Name': 'Windows 8.1 Pro', - 'Image File': 'Win8', - 'Image Name': 'Windows 8.1 Pro'}, + {'Name': 'Windows 8.1', + 'Image File': 'Win8', + 'Image Name': 'Windows 8.1', + 'CRLF': True}, + {'Name': 'Windows 8.1 Pro', + 'Image File': 'Win8', + 'Image Name': 'Windows 8.1 Pro'}, - {'Name': 'Windows 10 Home', - 'Image File': 'Win10', - 'Image Name': 'Windows 10 Home', - 'CRLF': True}, - {'Name': 'Windows 10 Pro', - 'Image File': 'Win10', - 'Image Name': 'Windows 10 Pro'}, - ] + {'Name': 'Windows 10 Home', + 'Image File': 'Win10', + 'Image Name': 'Windows 10 Home', + 'CRLF': True}, + {'Name': 'Windows 10 Pro', + 'Image File': 'Win10', + 'Image Name': 'Windows 10 Pro'}, + ] def find_windows_image(windows_version): - """Search for a Windows source image file, returns dict. + """Search for a Windows source image file, returns dict. - Searches on local disks and then the WINDOWS_SERVER share.""" - image = {} - imagefile = windows_version['Image File'] - imagename = windows_version['Image Name'] + Searches on local disks and then the WINDOWS_SERVER share.""" + image = {} + imagefile = windows_version['Image File'] + imagename = windows_version['Image Name'] - # Search local source - set_thread_error_mode(silent=True) # Prevents "No disk" popups - for d in psutil.disk_partitions(): - for ext in ['esd', 'wim', 'swm']: - path = '{}images\{}.{}'.format(d.mountpoint, imagefile, ext) - if os.path.isfile(path) and wim_contains_image(path, imagename): - image['Path'] = path - image['Letter'] = d.mountpoint[:1].upper() - image['Local'] = True - if ext == 'swm': - image['Glob'] = '--ref="{}*.swm"'.format(image['Path'][:-4]) - break - set_thread_error_mode(silent=False) # Return to normal + # Search local source + set_thread_error_mode(silent=True) # Prevents "No disk" popups + for d in psutil.disk_partitions(): + for ext in ['esd', 'wim', 'swm']: + path = '{}images\{}.{}'.format(d.mountpoint, imagefile, ext) + if os.path.isfile(path) and wim_contains_image(path, imagename): + image['Path'] = path + image['Letter'] = d.mountpoint[:1].upper() + image['Local'] = True + if ext == 'swm': + image['Glob'] = '--ref="{}*.swm"'.format(image['Path'][:-4]) + break + set_thread_error_mode(silent=False) # Return to normal - # Check for network source - if not image: - mount_windows_share() - if WINDOWS_SERVER['Mounted']: - for ext in ['esd', 'wim', 'swm']: - path = r'\\{}\{}\images\{}.{}'.format( - WINDOWS_SERVER['IP'], - WINDOWS_SERVER['Share'], - imagefile, - ext) - if os.path.isfile(path) and wim_contains_image(path, imagename): - image['Path'] = path - image['Letter'] = None - image['Local'] = False - if ext == 'swm': - image['Glob'] = '--ref="{}*.swm"'.format( - image['Path'][:-4]) - break + # Check for network source + if not image: + mount_windows_share() + if WINDOWS_SERVER['Mounted']: + for ext in ['esd', 'wim', 'swm']: + path = r'\\{}\{}\images\{}.{}'.format( + WINDOWS_SERVER['IP'], + WINDOWS_SERVER['Share'], + imagefile, + ext) + if os.path.isfile(path) and wim_contains_image(path, imagename): + image['Path'] = path + image['Letter'] = None + image['Local'] = False + if ext == 'swm': + image['Glob'] = '--ref="{}*.swm"'.format( + image['Path'][:-4]) + break - # Display image to be used (if any) and return - if image: - print_info('Using image: {}'.format(image['Path'])) - return image - else: - print_error('Failed to find Windows source image for {}'.format( - windows_version['Name'])) - raise GenericAbort + # Display image to be used (if any) and return + if image: + print_info('Using image: {}'.format(image['Path'])) + return image + else: + print_error('Failed to find Windows source image for {}'.format( + windows_version['Name'])) + raise GenericAbort def format_disk(disk, use_gpt): - """Format disk for use as a Windows OS disk.""" - if use_gpt: - format_gpt(disk) - else: - format_mbr(disk) + """Format disk for use as a Windows OS disk.""" + if use_gpt: + format_gpt(disk) + else: + format_mbr(disk) def format_gpt(disk): - """Format disk for use as a Windows OS disk using the GPT layout.""" - script = [ - # Partition table - 'select disk {}'.format(disk['Number']), - 'clean', - 'convert gpt', + """Format disk for use as a Windows OS disk using the GPT layout.""" + script = [ + # Partition table + 'select disk {}'.format(disk['Number']), + 'clean', + 'convert gpt', - # System partition - # NOTE: ESP needs to be >= 260 for Advanced Format 4K disks - 'create partition efi size=500', - 'format quick fs=fat32 label="System"', - 'assign letter="S"', + # System partition + # NOTE: ESP needs to be >= 260 for Advanced Format 4K disks + 'create partition efi size=500', + 'format quick fs=fat32 label="System"', + 'assign letter="S"', - # Microsoft Reserved (MSR) partition - 'create partition msr size=128', + # Microsoft Reserved (MSR) partition + 'create partition msr size=128', - # Windows partition - 'create partition primary', - 'format quick fs=ntfs label="Windows"', - 'assign letter="W"', + # Windows partition + 'create partition primary', + 'format quick fs=ntfs label="Windows"', + 'assign letter="W"', - # Recovery Tools partition - 'shrink minimum=500', - 'create partition primary', - 'format quick fs=ntfs label="Recovery Tools"', - 'assign letter="T"', - 'set id="de94bba4-06d1-4d40-a16a-bfd50179d6ac"', - 'gpt attributes=0x8000000000000001', - ] + # Recovery Tools partition + 'shrink minimum=500', + 'create partition primary', + 'format quick fs=ntfs label="Recovery Tools"', + 'assign letter="T"', + 'set id="de94bba4-06d1-4d40-a16a-bfd50179d6ac"', + 'gpt attributes=0x8000000000000001', + ] - # Run - run_diskpart(script) + # Run + run_diskpart(script) def format_mbr(disk): - """Format disk for use as a Windows OS disk using the MBR layout.""" - script = [ - # Partition table - 'select disk {}'.format(disk['Number']), - 'clean', + """Format disk for use as a Windows OS disk using the MBR layout.""" + script = [ + # Partition table + 'select disk {}'.format(disk['Number']), + 'clean', - # System partition - 'create partition primary size=100', - 'format fs=ntfs quick label="System Reserved"', - 'active', - 'assign letter="S"', + # System partition + 'create partition primary size=100', + 'format fs=ntfs quick label="System Reserved"', + 'active', + 'assign letter="S"', - # Windows partition - 'create partition primary', - 'format fs=ntfs quick label="Windows"', - 'assign letter="W"', + # Windows partition + 'create partition primary', + 'format fs=ntfs quick label="Windows"', + 'assign letter="W"', - # Recovery Tools partition - 'shrink minimum=500', - 'create partition primary', - 'format quick fs=ntfs label="Recovery"', - 'assign letter="T"', - 'set id=27', - ] + # Recovery Tools partition + 'shrink minimum=500', + 'create partition primary', + 'format quick fs=ntfs label="Recovery"', + 'assign letter="T"', + 'set id=27', + ] - # Run - run_diskpart(script) + # Run + run_diskpart(script) def mount_windows_share(): - """Mount the Windows images share unless labeled as already mounted.""" - if not WINDOWS_SERVER['Mounted']: - # Mounting read-write in case a backup was done in the same session - # and the server was left mounted read-write. This avoids throwing an - # error by trying to mount the same server with multiple credentials. - mount_network_share(WINDOWS_SERVER, read_write=True) + """Mount the Windows images share unless labeled as already mounted.""" + if not WINDOWS_SERVER['Mounted']: + # Mounting read-write in case a backup was done in the same session + # and the server was left mounted read-write. This avoids throwing an + # error by trying to mount the same server with multiple credentials. + mount_network_share(WINDOWS_SERVER, read_write=True) def select_windows_version(): - """Select Windows version from a menu, returns dict.""" - actions = [ - {'Name': 'Main Menu', 'Letter': 'M'}, - ] + """Select Windows version from a menu, returns dict.""" + actions = [ + {'Name': 'Main Menu', 'Letter': 'M'}, + ] - # Menu loop - selection = menu_select( - title = 'Which version of Windows are we installing?', - main_entries = WINDOWS_VERSIONS, - action_entries = actions) + # Menu loop + selection = menu_select( + title = 'Which version of Windows are we installing?', + main_entries = WINDOWS_VERSIONS, + action_entries = actions) - if selection.isnumeric(): - return WINDOWS_VERSIONS[int(selection)-1] - elif selection == 'M': - raise GenericAbort + if selection.isnumeric(): + return WINDOWS_VERSIONS[int(selection)-1] + elif selection == 'M': + raise GenericAbort def setup_windows(windows_image, windows_version): - """Apply a Windows image to W:""" - cmd = [ - global_vars['Tools']['wimlib-imagex'], - 'apply', - windows_image['Path'], - windows_version['Image Name'], - 'W:\\'] - if 'Glob' in windows_image: - cmd.extend(windows_image['Glob']) - run_program(cmd) + """Apply a Windows image to W:""" + cmd = [ + global_vars['Tools']['wimlib-imagex'], + 'apply', + windows_image['Path'], + windows_version['Image Name'], + 'W:\\'] + if 'Glob' in windows_image: + cmd.extend(windows_image['Glob']) + run_program(cmd) def setup_windows_re(windows_version, windows_letter='W', tools_letter='T'): - """Setup the WinRE partition.""" - win = r'{}:\Windows'.format(windows_letter) - winre = r'{}\System32\Recovery\WinRE.wim'.format(win) - dest = r'{}:\Recovery\WindowsRE'.format(tools_letter) + """Setup the WinRE partition.""" + win = r'{}:\Windows'.format(windows_letter) + winre = r'{}\System32\Recovery\WinRE.wim'.format(win) + dest = r'{}:\Recovery\WindowsRE'.format(tools_letter) - # Copy WinRE.wim - os.makedirs(dest, exist_ok=True) - shutil.copy(winre, r'{}\WinRE.wim'.format(dest)) + # Copy WinRE.wim + os.makedirs(dest, exist_ok=True) + shutil.copy(winre, r'{}\WinRE.wim'.format(dest)) - # Set location - cmd = [ - r'{}\System32\ReAgentc.exe'.format(win), - '/setreimage', - '/path', dest, - '/target', win] - run_program(cmd) + # Set location + cmd = [ + r'{}\System32\ReAgentc.exe'.format(win), + '/setreimage', + '/path', dest, + '/target', win] + run_program(cmd) def update_boot_partition(system_letter='S', windows_letter='W', mode='ALL'): - """Setup the Windows boot partition.""" - cmd = [ - r'{}\Windows\System32\bcdboot.exe'.format( - global_vars['Env']['SYSTEMDRIVE']), - r'{}:\Windows'.format(windows_letter), - '/s', '{}:'.format(system_letter), - '/f', mode] - run_program(cmd) + """Setup the Windows boot partition.""" + cmd = [ + r'{}\Windows\System32\bcdboot.exe'.format( + global_vars['Env']['SYSTEMDRIVE']), + r'{}:\Windows'.format(windows_letter), + '/s', '{}:'.format(system_letter), + '/f', mode] + run_program(cmd) def wim_contains_image(filename, imagename): - """Check if an ESD/WIM contains the specified image, returns bool.""" - cmd = [ - global_vars['Tools']['wimlib-imagex'], - 'info', - filename, - imagename] - try: - run_program(cmd) - except subprocess.CalledProcessError: - return False + """Check if an ESD/WIM contains the specified image, returns bool.""" + cmd = [ + global_vars['Tools']['wimlib-imagex'], + 'info', + filename, + imagename] + try: + run_program(cmd) + except subprocess.CalledProcessError: + return False - return True + return True if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From c3ca58879cb7ea4a07e9771d0d89f1bc70e9dfab Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 20:15:02 -0700 Subject: [PATCH 174/265] Updated winpe_menus.py --- .bin/Scripts/functions/winpe_menus.py | 830 +++++++++++++------------- 1 file changed, 416 insertions(+), 414 deletions(-) diff --git a/.bin/Scripts/functions/winpe_menus.py b/.bin/Scripts/functions/winpe_menus.py index 1c732eca..e20a3f3a 100644 --- a/.bin/Scripts/functions/winpe_menus.py +++ b/.bin/Scripts/functions/winpe_menus.py @@ -6,466 +6,468 @@ from functions.windows_setup import * # STATIC VARIABLES FAST_COPY_PE_ARGS = [ - '/cmd=noexist_only', - '/utf8', - '/skip_empty_dir', - '/linkdest', - '/no_ui', - '/auto_close', - '/exclude={}'.format(';'.join(FAST_COPY_EXCLUDES)), - ] + '/cmd=noexist_only', + '/utf8', + '/skip_empty_dir', + '/linkdest', + '/no_ui', + '/auto_close', + '/exclude={}'.format(';'.join(FAST_COPY_EXCLUDES)), + ] PE_TOOLS = { - 'BlueScreenView': { - 'Path': r'BlueScreenView\BlueScreenView.exe', - }, - 'FastCopy': { - 'Path': r'FastCopy\FastCopy.exe', - 'Args': FAST_COPY_PE_ARGS, - }, - 'HWiNFO': { - 'Path': r'HWiNFO\HWiNFO.exe', - }, - 'NT Password Editor': { - 'Path': r'NT Password Editor\ntpwedit.exe', - }, - 'Notepad++': { - 'Path': r'NotepadPlusPlus\NotepadPlusPlus.exe', - }, - 'PhotoRec': { - 'Path': r'TestDisk\photorec_win.exe', - 'Args': ['-new_console:n'], - }, - 'Prime95': { - 'Path': r'Prime95\prime95.exe', - }, - 'ProduKey': { - 'Path': r'ProduKey\ProduKey.exe', - }, - 'Q-Dir': { - 'Path': r'Q-Dir\Q-Dir.exe', - }, - 'TestDisk': { - 'Path': r'TestDisk\testdisk_win.exe', - 'Args': ['-new_console:n'], - }, - } + 'BlueScreenView': { + 'Path': r'BlueScreenView\BlueScreenView.exe', + }, + 'FastCopy': { + 'Path': r'FastCopy\FastCopy.exe', + 'Args': FAST_COPY_PE_ARGS, + }, + 'HWiNFO': { + 'Path': r'HWiNFO\HWiNFO.exe', + }, + 'NT Password Editor': { + 'Path': r'NT Password Editor\ntpwedit.exe', + }, + 'Notepad++': { + 'Path': r'NotepadPlusPlus\NotepadPlusPlus.exe', + }, + 'PhotoRec': { + 'Path': r'TestDisk\photorec_win.exe', + 'Args': ['-new_console:n'], + }, + 'Prime95': { + 'Path': r'Prime95\prime95.exe', + }, + 'ProduKey': { + 'Path': r'ProduKey\ProduKey.exe', + }, + 'Q-Dir': { + 'Path': r'Q-Dir\Q-Dir.exe', + }, + 'TestDisk': { + 'Path': r'TestDisk\testdisk_win.exe', + 'Args': ['-new_console:n'], + }, + } def check_pe_tools(): - """Fix tool paths for WinPE layout.""" - for k in PE_TOOLS.keys(): - PE_TOOLS[k]['Path'] = r'{}\{}'.format( - global_vars['BinDir'], PE_TOOLS[k]['Path']) - global_vars['Tools']['wimlib-imagex'] = re.sub( - r'\\x(32|64)', - r'', - global_vars['Tools']['wimlib-imagex'], - re.IGNORECASE) + """Fix tool paths for WinPE layout.""" + for k in PE_TOOLS.keys(): + PE_TOOLS[k]['Path'] = r'{}\{}'.format( + global_vars['BinDir'], PE_TOOLS[k]['Path']) + global_vars['Tools']['wimlib-imagex'] = re.sub( + r'\\x(32|64)', + r'', + global_vars['Tools']['wimlib-imagex'], + re.IGNORECASE) def menu_backup(): - """Take backup images of partition(s) in the WIM format.""" - errors = False - other_results = { - 'Error': { - 'CalledProcessError': 'Unknown Error', - 'PathNotFoundError': 'Missing', - }, - 'Warning': { - 'GenericAbort': 'Skipped', - 'GenericRepair': 'Repaired', - }} - set_title('{}: Backup Menu'.format(KIT_NAME_FULL)) + """Take backup images of partition(s) in the WIM format.""" + errors = False + other_results = { + 'Error': { + 'CalledProcessError': 'Unknown Error', + 'PathNotFoundError': 'Missing', + }, + 'Warning': { + 'GenericAbort': 'Skipped', + 'GenericRepair': 'Repaired', + }} + set_title('{}: Backup Menu'.format(KIT_NAME_FULL)) - # Set backup prefix - clear_screen() - print_standard('{}\n'.format(global_vars['Title'])) - ticket_number = get_ticket_number() - if ENABLED_TICKET_NUMBERS: - backup_prefix = ticket_number + # Set backup prefix + clear_screen() + print_standard('{}\n'.format(global_vars['Title'])) + ticket_number = get_ticket_number() + if ENABLED_TICKET_NUMBERS: + backup_prefix = ticket_number + else: + backup_prefix = get_simple_string(prompt='Enter backup name prefix') + backup_prefix = backup_prefix.replace(' ', '_') + + # Assign drive letters + try_and_print( + message = 'Assigning letters...', + function = assign_volume_letters, + other_results = other_results) + + # Mount backup shares + mount_backup_shares(read_write=True) + + # Select destination + destination = select_backup_destination(auto_select=False) + + # Scan disks + result = try_and_print( + message = 'Getting disk info...', + function = scan_disks, + other_results = other_results) + if result['CS']: + disks = result['Out'] + else: + print_error('ERROR: No disks found.') + raise GenericAbort + + # Select disk to backup + disk = select_disk('For which disk are we creating backups?', disks) + if not disk: + raise GenericAbort + + # "Prep" disk + prep_disk_for_backup(destination, disk, backup_prefix) + + # Display details for backup task + clear_screen() + print_info('Create Backup - Details:\n') + if ENABLED_TICKET_NUMBERS: + show_data(message='Ticket:', data=ticket_number) + show_data( + message = 'Source:', + data = '[{}] ({}) {} {}'.format( + disk.get('Table', ''), + disk.get('Type', ''), + disk.get('Name', 'Unknown'), + disk.get('Size', ''), + ), + ) + show_data( + message = 'Destination:', + data = destination.get('Display Name', destination['Name']), + ) + for par in disk['Partitions']: + message = 'Partition {}:'.format(par['Number']) + data = par['Display String'] + if par['Number'] in disk['Bad Partitions']: + show_data(message=message, data=data, width=30, warning=True) + if 'Error' in par: + show_data(message='', data=par['Error'], error=True) + elif par['Image Exists']: + show_data(message=message, data=data, width=30, info=True) else: - backup_prefix = get_simple_string(prompt='Enter backup name prefix') - backup_prefix = backup_prefix.replace(' ', '_') + show_data(message=message, data=data, width=30) + print_standard(disk['Backup Warnings']) - # Assign drive letters - try_and_print( - message = 'Assigning letters...', - function = assign_volume_letters, - other_results = other_results) + # Ask to proceed + if (not ask('Proceed with backup?')): + raise GenericAbort - # Mount backup shares - mount_backup_shares(read_write=True) - - # Select destination - destination = select_backup_destination(auto_select=False) - - # Scan disks + # Backup partition(s) + print_info('\n\nStarting task.\n') + for par in disk['Partitions']: result = try_and_print( - message = 'Getting disk info...', - function = scan_disks, - other_results = other_results) - if result['CS']: - disks = result['Out'] - else: - print_error('ERROR: No disks found.') - raise GenericAbort + message = 'Partition {} Backup...'.format(par['Number']), + function = backup_partition, + other_results = other_results, + disk = disk, + par = par) + if not result['CS'] and not isinstance(result['Error'], GenericAbort): + errors = True + par['Error'] = result['Error'] - # Select disk to backup - disk = select_disk('For which disk are we creating backups?', disks) - if not disk: - raise GenericAbort - - # "Prep" disk - prep_disk_for_backup(destination, disk, backup_prefix) - - # Display details for backup task - clear_screen() - print_info('Create Backup - Details:\n') - if ENABLED_TICKET_NUMBERS: - show_data(message='Ticket:', data=ticket_number) - show_data( - message = 'Source:', - data = '[{}] ({}) {} {}'.format( - disk.get('Table', ''), - disk.get('Type', ''), - disk.get('Name', 'Unknown'), - disk.get('Size', ''), - ), - ) - show_data( - message = 'Destination:', - data = destination.get('Display Name', destination['Name']), - ) + # Verify backup(s) + if disk['Valid Partitions']: + print_info('\n\nVerifying backup images(s)\n') for par in disk['Partitions']: - message = 'Partition {}:'.format(par['Number']) - data = par['Display String'] - if par['Number'] in disk['Bad Partitions']: - show_data(message=message, data=data, width=30, warning=True) - if 'Error' in par: - show_data(message='', data=par['Error'], error=True) - elif par['Image Exists']: - show_data(message=message, data=data, width=30, info=True) - else: - show_data(message=message, data=data, width=30) - print_standard(disk['Backup Warnings']) + if par['Number'] in disk['Bad Partitions']: + continue # Skip verification + result = try_and_print( + message = 'Partition {} Image...'.format(par['Number']), + function = verify_wim_backup, + other_results = other_results, + partition = par) + if not result['CS']: + errors = True + par['Error'] = result['Error'] - # Ask to proceed - if (not ask('Proceed with backup?')): - raise GenericAbort - - # Backup partition(s) - print_info('\n\nStarting task.\n') - for par in disk['Partitions']: - result = try_and_print( - message = 'Partition {} Backup...'.format(par['Number']), - function = backup_partition, - other_results = other_results, - disk = disk, - par = par) - if not result['CS'] and not isinstance(result['Error'], GenericAbort): - errors = True - par['Error'] = result['Error'] - - # Verify backup(s) - if disk['Valid Partitions']: - print_info('\n\nVerifying backup images(s)\n') - for par in disk['Partitions']: - if par['Number'] in disk['Bad Partitions']: - continue # Skip verification - result = try_and_print( - message = 'Partition {} Image...'.format(par['Number']), - function = verify_wim_backup, - other_results = other_results, - partition = par) - if not result['CS']: - errors = True - par['Error'] = result['Error'] - - # Print summary - if errors: - print_warning('\nErrors were encountered and are detailed below.') - for par in [p for p in disk['Partitions'] if 'Error' in p]: - print_standard(' Partition {} Error:'.format(par['Number'])) - if hasattr(par['Error'], 'stderr'): - try: - par['Error'] = par['Error'].stderr.decode() - except: - # Deal with badly formatted error message - pass - try: - par['Error'] = par['Error'].splitlines() - par['Error'] = [line.strip() for line in par['Error']] - par['Error'] = [line for line in par['Error'] if line] - for line in par['Error']: - print_error('\t{}'.format(line)) - except: - print_error('\t{}'.format(par['Error'])) - else: - print_success('\nNo errors were encountered during imaging.') - if 'LogFile' in global_vars and ask('\nReview log?'): - cmd = [ - global_vars['Tools']['NotepadPlusPlus'], - global_vars['LogFile']] + # Print summary + if errors: + print_warning('\nErrors were encountered and are detailed below.') + for par in [p for p in disk['Partitions'] if 'Error' in p]: + print_standard(' Partition {} Error:'.format(par['Number'])) + if hasattr(par['Error'], 'stderr'): try: - popen_program(cmd) - except Exception: - print_error('ERROR: Failed to open log.') - sleep(30) - pause('\nPress Enter to return to main menu... ') + par['Error'] = par['Error'].stderr.decode() + except: + # Deal with badly formatted error message + pass + try: + par['Error'] = par['Error'].splitlines() + par['Error'] = [line.strip() for line in par['Error']] + par['Error'] = [line for line in par['Error'] if line] + for line in par['Error']: + print_error('\t{}'.format(line)) + except: + print_error('\t{}'.format(par['Error'])) + else: + print_success('\nNo errors were encountered during imaging.') + if 'LogFile' in global_vars and ask('\nReview log?'): + cmd = [ + global_vars['Tools']['NotepadPlusPlus'], + global_vars['LogFile']] + try: + popen_program(cmd) + except Exception: + print_error('ERROR: Failed to open log.') + sleep(30) + pause('\nPress Enter to return to main menu... ') def menu_root(): - """Main WinPE menu.""" - check_pe_tools() - menus = [ - {'Name': 'Create Backups', 'Menu': menu_backup}, - {'Name': 'Setup Windows', 'Menu': menu_setup}, - {'Name': 'Misc Tools', 'Menu': menu_tools}, - ] - actions = [ - {'Name': 'Command Prompt', 'Letter': 'C'}, - {'Name': 'Reboot', 'Letter': 'R'}, - {'Name': 'Shutdown', 'Letter': 'S'}, - ] + """Main WinPE menu.""" + check_pe_tools() + menus = [ + {'Name': 'Create Backups', 'Menu': menu_backup}, + {'Name': 'Setup Windows', 'Menu': menu_setup}, + {'Name': 'Misc Tools', 'Menu': menu_tools}, + ] + actions = [ + {'Name': 'Command Prompt', 'Letter': 'C'}, + {'Name': 'Reboot', 'Letter': 'R'}, + {'Name': 'Shutdown', 'Letter': 'S'}, + ] - # Main loop - while True: - set_title(KIT_NAME_FULL) - selection = menu_select( - title = 'Main Menu', - main_entries = menus, - action_entries = actions, - secret_exit = True) + # Main loop + while True: + set_title(KIT_NAME_FULL) + selection = menu_select( + title = 'Main Menu', + main_entries = menus, + action_entries = actions, + secret_exit = True) - if (selection.isnumeric()): - try: - menus[int(selection)-1]['Menu']() - except GenericAbort: - print_warning('\nAborted\n') - pause('Press Enter to return to main menu... ') - elif (selection == 'C'): - run_program(['cmd', '-new_console:n'], check=False) - elif (selection == 'R'): - run_program(['wpeutil', 'reboot']) - elif (selection == 'S'): - run_program(['wpeutil', 'shutdown']) - else: - sys.exit() + if (selection.isnumeric()): + try: + menus[int(selection)-1]['Menu']() + except GenericAbort: + print_warning('\nAborted\n') + pause('Press Enter to return to main menu... ') + elif (selection == 'C'): + run_program(['cmd', '-new_console:n'], check=False) + elif (selection == 'R'): + run_program(['wpeutil', 'reboot']) + elif (selection == 'S'): + run_program(['wpeutil', 'shutdown']) + else: + sys.exit() def menu_setup(): - """Format a disk (MBR/GPT), apply a Windows image, and setup boot files.""" - errors = False - other_results = { - 'Error': { - 'CalledProcessError': 'Unknown Error', - 'PathNotFoundError': 'Missing', - }, - 'Warning': { - 'GenericAbort': 'Skipped', - 'GenericRepair': 'Repaired', - }} - set_title('{}: Setup Menu'.format(KIT_NAME_FULL)) + """Format a disk (MBR/GPT), apply a Windows image, and setup boot files.""" + errors = False + other_results = { + 'Error': { + 'CalledProcessError': 'Unknown Error', + 'PathNotFoundError': 'Missing', + }, + 'Warning': { + 'GenericAbort': 'Skipped', + 'GenericRepair': 'Repaired', + }} + set_title('{}: Setup Menu'.format(KIT_NAME_FULL)) - # Set ticket ID - clear_screen() - print_standard('{}\n'.format(global_vars['Title'])) - ticket_number = get_ticket_number() + # Set ticket ID + clear_screen() + print_standard('{}\n'.format(global_vars['Title'])) + ticket_number = get_ticket_number() - # Select the version of Windows to apply - windows_version = select_windows_version() + # Select the version of Windows to apply + windows_version = select_windows_version() - # Find Windows image - # NOTE: Reassign volume letters to ensure all devices are scanned - try_and_print( - message = 'Assigning volume letters...', - function = assign_volume_letters, - other_results = other_results) - windows_image = find_windows_image(windows_version) + # Find Windows image + # NOTE: Reassign volume letters to ensure all devices are scanned + try_and_print( + message = 'Assigning volume letters...', + function = assign_volume_letters, + other_results = other_results) + windows_image = find_windows_image(windows_version) - # Scan disks - result = try_and_print( - message = 'Getting disk info...', - function = scan_disks, - other_results = other_results) - if result['CS']: - disks = result['Out'] - else: - print_error('ERROR: No disks found.') - raise GenericAbort + # Scan disks + result = try_and_print( + message = 'Getting disk info...', + function = scan_disks, + other_results = other_results) + if result['CS']: + disks = result['Out'] + else: + print_error('ERROR: No disks found.') + raise GenericAbort - # Select disk to use as the OS disk - dest_disk = select_disk('To which disk are we installing Windows?', disks) - if not dest_disk: - raise GenericAbort + # Select disk to use as the OS disk + dest_disk = select_disk('To which disk are we installing Windows?', disks) + if not dest_disk: + raise GenericAbort - # "Prep" disk - prep_disk_for_formatting(dest_disk) + # "Prep" disk + prep_disk_for_formatting(dest_disk) - # Display details for setup task - clear_screen() - print_info('Setup Windows - Details:\n') - if ENABLED_TICKET_NUMBERS: - show_data(message='Ticket:', data=ticket_number) - show_data(message='Installing:', data=windows_version['Name']) + # Display details for setup task + clear_screen() + print_info('Setup Windows - Details:\n') + if ENABLED_TICKET_NUMBERS: + show_data(message='Ticket:', data=ticket_number) + show_data(message='Installing:', data=windows_version['Name']) + show_data( + message = 'Boot Method:', + data = 'UEFI (GPT)' if dest_disk['Use GPT'] else 'Legacy (MBR)') + show_data(message='Using Image:', data=windows_image['Path']) + show_data( + message = 'ERASING:', + data = '[{}] ({}) {} {}\n'.format( + dest_disk.get('Table', ''), + dest_disk.get('Type', ''), + dest_disk.get('Name', 'Unknown'), + dest_disk.get('Size', ''), + ), + warning = True) + for par in dest_disk['Partitions']: show_data( - message = 'Boot Method:', - data = 'UEFI (GPT)' if dest_disk['Use GPT'] else 'Legacy (MBR)') - show_data(message='Using Image:', data=windows_image['Path']) - show_data( - message = 'ERASING:', - data = '[{}] ({}) {} {}\n'.format( - dest_disk.get('Table', ''), - dest_disk.get('Type', ''), - dest_disk.get('Name', 'Unknown'), - dest_disk.get('Size', ''), - ), - warning = True) - for par in dest_disk['Partitions']: - show_data( - message = 'Partition {}:'.format(par['Number']), - data = par['Display String'], - warning = True) - print_warning(dest_disk['Format Warnings']) + message = 'Partition {}:'.format(par['Number']), + data = par['Display String'], + warning = True) + print_warning(dest_disk['Format Warnings']) - if (not ask('Is this correct?')): - raise GenericAbort + if (not ask('Is this correct?')): + raise GenericAbort - # Safety check - print_standard('\nSAFETY CHECK') - print_warning('All data will be DELETED from the ' - 'disk and partition(s) listed above.') - print_warning('This is irreversible and will lead ' - 'to {CLEAR}{RED}DATA LOSS.'.format(**COLORS)) - if (not ask('Asking again to confirm, is this correct?')): - raise GenericAbort + # Safety check + print_standard('\nSAFETY CHECK') + print_warning('All data will be DELETED from the ' + 'disk and partition(s) listed above.') + print_warning('This is irreversible and will lead ' + 'to {CLEAR}{RED}DATA LOSS.'.format(**COLORS)) + if (not ask('Asking again to confirm, is this correct?')): + raise GenericAbort - # Remove volume letters so S, T, & W can be used below - try_and_print( - message = 'Removing volume letters...', - function = remove_volume_letters, - other_results = other_results, - keep=windows_image['Letter']) + # Remove volume letters so S, T, & W can be used below + try_and_print( + message = 'Removing volume letters...', + function = remove_volume_letters, + other_results = other_results, + keep=windows_image['Letter']) - # Assign new letter for local source if necessary - if windows_image['Local'] and windows_image['Letter'] in ['S', 'T', 'W']: - new_letter = try_and_print( - message = 'Reassigning source volume letter...', - function = reassign_volume_letter, - other_results = other_results, - letter=windows_image['Letter']) - windows_image['Path'] = '{}{}'.format( - new_letter, windows_image['Path'][1:]) - windows_image['Letter'] = new_letter + # Assign new letter for local source if necessary + if windows_image['Local'] and windows_image['Letter'] in ['S', 'T', 'W']: + new_letter = try_and_print( + message = 'Reassigning source volume letter...', + function = reassign_volume_letter, + other_results = other_results, + letter=windows_image['Letter']) + windows_image['Path'] = '{}{}'.format( + new_letter, windows_image['Path'][1:]) + windows_image['Letter'] = new_letter - # Format and partition disk - result = try_and_print( - message = 'Formatting disk...', - function = format_disk, - other_results = other_results, - disk = dest_disk, - use_gpt = dest_disk['Use GPT']) - if not result['CS']: - # We need to crash as the disk is in an unknown state - print_error('ERROR: Failed to format disk.') - raise GenericAbort + # Format and partition disk + result = try_and_print( + message = 'Formatting disk...', + function = format_disk, + other_results = other_results, + disk = dest_disk, + use_gpt = dest_disk['Use GPT']) + if not result['CS']: + # We need to crash as the disk is in an unknown state + print_error('ERROR: Failed to format disk.') + raise GenericAbort - # Apply Image - result = try_and_print( - message = 'Applying image...', - function = setup_windows, - other_results = other_results, - windows_image = windows_image, - windows_version = windows_version) - if not result['CS']: - # We need to crash as the disk is in an unknown state - print_error('ERROR: Failed to apply image.') - raise GenericAbort + # Apply Image + result = try_and_print( + message = 'Applying image...', + function = setup_windows, + other_results = other_results, + windows_image = windows_image, + windows_version = windows_version) + if not result['CS']: + # We need to crash as the disk is in an unknown state + print_error('ERROR: Failed to apply image.') + raise GenericAbort - # Create Boot files - try_and_print( - message = 'Updating boot files...', - function = update_boot_partition, - other_results = other_results) + # Create Boot files + try_and_print( + message = 'Updating boot files...', + function = update_boot_partition, + other_results = other_results) - # Setup WinRE - try_and_print( - message = 'Updating recovery tools...', - function = setup_windows_re, - other_results = other_results, - windows_version = windows_version) + # Setup WinRE + try_and_print( + message = 'Updating recovery tools...', + function = setup_windows_re, + other_results = other_results, + windows_version = windows_version) - # Copy WinPE log(s) - source = r'{}\Logs'.format(global_vars['ClientDir']) - dest = r'W:\{}\Logs\WinPE'.format(KIT_NAME_SHORT) - shutil.copytree(source, dest) + # Copy WinPE log(s) + source = r'{}\Logs'.format(global_vars['ClientDir']) + dest = r'W:\{}\Logs\WinPE'.format(KIT_NAME_SHORT) + shutil.copytree(source, dest) - # Print summary - print_standard('\nDone.') - if 'LogFile' in global_vars and ask('\nReview log?'): - cmd = [ - global_vars['Tools']['NotepadPlusPlus'], - global_vars['LogFile']] - try: - popen_program(cmd) - except Exception: - print_error('ERROR: Failed to open log.') - sleep(30) - pause('\nPress Enter to return to main menu... ') + # Print summary + print_standard('\nDone.') + if 'LogFile' in global_vars and ask('\nReview log?'): + cmd = [ + global_vars['Tools']['NotepadPlusPlus'], + global_vars['LogFile']] + try: + popen_program(cmd) + except Exception: + print_error('ERROR: Failed to open log.') + sleep(30) + pause('\nPress Enter to return to main menu... ') def menu_tools(): - """Tool launcher menu.""" - tools = [{'Name': k} for k in sorted(PE_TOOLS.keys())] - actions = [{'Name': 'Main Menu', 'Letter': 'M'},] - set_title(KIT_NAME_FULL) + """Tool launcher menu.""" + tools = [{'Name': k} for k in sorted(PE_TOOLS.keys())] + actions = [{'Name': 'Main Menu', 'Letter': 'M'},] + set_title(KIT_NAME_FULL) - # Menu loop - while True: - selection = menu_select( - title = 'Tools Menu', - main_entries = tools, - action_entries = actions) - if (selection.isnumeric()): - name = tools[int(selection)-1]['Name'] - cmd = [PE_TOOLS[name]['Path']] + PE_TOOLS[name].get('Args', []) - if name == 'Blue Screen View': - # Select path to scan - minidump_path = select_minidump_path() - if minidump_path: - cmd.extend(['/MiniDumpFolder', minidump_path]) - try: - popen_program(cmd) - except Exception: - print_error('Failed to run {}'.format(name)) - sleep(2) - pause() - elif (selection == 'M'): - break + # Menu loop + while True: + selection = menu_select( + title = 'Tools Menu', + main_entries = tools, + action_entries = actions) + if (selection.isnumeric()): + name = tools[int(selection)-1]['Name'] + cmd = [PE_TOOLS[name]['Path']] + PE_TOOLS[name].get('Args', []) + if name == 'Blue Screen View': + # Select path to scan + minidump_path = select_minidump_path() + if minidump_path: + cmd.extend(['/MiniDumpFolder', minidump_path]) + try: + popen_program(cmd) + except Exception: + print_error('Failed to run {}'.format(name)) + sleep(2) + pause() + elif (selection == 'M'): + break def select_minidump_path(): - """Select BSOD minidump path from a menu.""" - dumps = [] + """Select BSOD minidump path from a menu.""" + dumps = [] - # Assign volume letters first - assign_volume_letters() + # Assign volume letters first + assign_volume_letters() - # Search for minidumps - set_thread_error_mode(silent=True) # Prevents "No disk" popups - for d in psutil.disk_partitions(): - if global_vars['Env']['SYSTEMDRIVE'].upper() in d.mountpoint: - # Skip RAMDisk - continue - if os.path.exists(r'{}Windows\MiniDump'.format(d.mountpoint)): - dumps.append({'Name': r'{}Windows\MiniDump'.format(d.mountpoint)}) - set_thread_error_mode(silent=False) # Return to normal + # Search for minidumps + set_thread_error_mode(silent=True) # Prevents "No disk" popups + for d in psutil.disk_partitions(): + if global_vars['Env']['SYSTEMDRIVE'].upper() in d.mountpoint: + # Skip RAMDisk + continue + if os.path.exists(r'{}Windows\MiniDump'.format(d.mountpoint)): + dumps.append({'Name': r'{}Windows\MiniDump'.format(d.mountpoint)}) + set_thread_error_mode(silent=False) # Return to normal - # Check results before showing menu - if len(dumps) == 0: - print_error('ERROR: No BSoD / MiniDump paths found') - sleep(2) - return None + # Check results before showing menu + if len(dumps) == 0: + print_error('ERROR: No BSoD / MiniDump paths found') + sleep(2) + return None - # Menu - selection = menu_select( - title = 'Which BSoD / MiniDump path are we scanning?', - main_entries = dumps) - return dumps[int(selection) - 1]['Name'] + # Menu + selection = menu_select( + title = 'Which BSoD / MiniDump path are we scanning?', + main_entries = dumps) + return dumps[int(selection) - 1]['Name'] if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From 5664765f6ed3febc875ffcde731aa2829ecb2ab9 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 20:27:44 -0700 Subject: [PATCH 175/265] Updated connect-to-network --- .bin/Scripts/connect-to-network | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/.bin/Scripts/connect-to-network b/.bin/Scripts/connect-to-network index 0475c15c..e5100303 100755 --- a/.bin/Scripts/connect-to-network +++ b/.bin/Scripts/connect-to-network @@ -12,19 +12,20 @@ from functions.network import * init_global_vars() if __name__ == '__main__': - try: - # Prep - clear_screen() + try: + # Prep + clear_screen() - # Connect - connect_to_network() - - # Done - print_standard('\nDone.') - #pause("Press Enter to exit...") - exit_script() - except SystemExit: - pass - except: - major_exception() + # Connect + connect_to_network() + + # Done + print_standard('\nDone.') + #pause("Press Enter to exit...") + exit_script() + except SystemExit: + pass + except: + major_exception() +# vim: sts=2 sw=2 ts=2 From 25bacb9892bd66a7453e56fbd567fdfd17c8a533 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 20:27:55 -0700 Subject: [PATCH 176/265] Updated ddrescue-tui-menu --- .bin/Scripts/ddrescue-tui-menu | 88 +++++++++++++++++----------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/.bin/Scripts/ddrescue-tui-menu b/.bin/Scripts/ddrescue-tui-menu index 4bec6230..48cf66a4 100755 --- a/.bin/Scripts/ddrescue-tui-menu +++ b/.bin/Scripts/ddrescue-tui-menu @@ -13,51 +13,51 @@ from functions.hw_diags import * init_global_vars() if __name__ == '__main__': + try: + # Prep + clear_screen() + args = list(sys.argv) + run_mode = '' + source_path = None + dest_path = None + + # Parse args try: - # Prep - clear_screen() - args = list(sys.argv) - run_mode = '' - source_path = None - dest_path = None + script_name = os.path.basename(args.pop(0)) + run_mode = str(args.pop(0)).lower() + source_path = args.pop(0) + dest_path = args.pop(0) + except IndexError: + # We'll set the missing paths later + pass - # Parse args - try: - script_name = os.path.basename(args.pop(0)) - run_mode = str(args.pop(0)).lower() - source_path = args.pop(0) - dest_path = args.pop(0) - except IndexError: - # We'll set the missing paths later - pass + # Show usage + if re.search(r'-+(h|help)', str(sys.argv), re.IGNORECASE): + show_usage(script_name) + exit_script() - # Show usage - if re.search(r'-+(h|help)', str(sys.argv), re.IGNORECASE): - show_usage(script_name) - exit_script() + # Start cloning/imaging + if run_mode in ('clone', 'image'): + menu_ddrescue(source_path, dest_path, run_mode) + else: + if not re.search(r'^-*(h|help\?)', run_mode, re.IGNORECASE): + print_error('Invalid mode.') + + # Done + print_standard('\nDone.') + pause("Press Enter to exit...") + exit_script() + except GenericAbort: + abort() + except GenericError as ge: + msg = 'Generic Error' + if str(ge): + msg = str(ge) + print_error(msg) + abort() + except SystemExit: + pass + except: + major_exception() - # Start cloning/imaging - if run_mode in ('clone', 'image'): - menu_ddrescue(source_path, dest_path, run_mode) - else: - if not re.search(r'^-*(h|help\?)', run_mode, re.IGNORECASE): - print_error('Invalid mode.') - - # Done - print_standard('\nDone.') - pause("Press Enter to exit...") - exit_script() - except GenericAbort: - abort() - except GenericError as ge: - msg = 'Generic Error' - if str(ge): - msg = str(ge) - print_error(msg) - abort() - except SystemExit: - pass - except: - major_exception() - -# vim: sts=4 sw=4 ts=4 +# vim: sts=2 sw=2 ts=2 From a9ebeee7487a5d363af0376800f790209afcd18c Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 20:28:14 -0700 Subject: [PATCH 177/265] Updated mount-all-volumes --- .bin/Scripts/mount-all-volumes | 41 +++++++++++++++++----------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/.bin/Scripts/mount-all-volumes b/.bin/Scripts/mount-all-volumes index 9e5de0ea..2c0a6621 100755 --- a/.bin/Scripts/mount-all-volumes +++ b/.bin/Scripts/mount-all-volumes @@ -12,27 +12,28 @@ from functions.data import * init_global_vars() if __name__ == '__main__': - try: - # Prep - clear_screen() - print_standard('{}: Volume mount tool'.format(KIT_NAME_FULL)) + try: + # Prep + clear_screen() + print_standard('{}: Volume mount tool'.format(KIT_NAME_FULL)) - # Mount volumes - report = mount_volumes(all_devices=True) + # Mount volumes + report = mount_volumes(all_devices=True) - # Print report - print_info('\nResults') - for vol_name, vol_data in sorted(report.items()): - show_data(indent=4, width=20, **vol_data['show_data']) + # Print report + print_info('\nResults') + for vol_name, vol_data in sorted(report.items()): + show_data(indent=4, width=20, **vol_data['show_data']) - # Done - print_standard('\nDone.') - if 'gui' in sys.argv: - pause("Press Enter to exit...") - popen_program(['nohup', 'thunar', '/media'], pipe=True) - exit_script() - except SystemExit: - pass - except: - major_exception() + # Done + print_standard('\nDone.') + if 'gui' in sys.argv: + pause("Press Enter to exit...") + popen_program(['nohup', 'thunar', '/media'], pipe=True) + exit_script() + except SystemExit: + pass + except: + major_exception() +# vim: sts=2 sw=2 ts=2 From 4ddce7cfbee2f8548ec0bed238afb927e2b76cbc Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 20:28:26 -0700 Subject: [PATCH 178/265] Updated mount-backup-shares --- .bin/Scripts/mount-backup-shares | 41 ++++++++++++++++---------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/.bin/Scripts/mount-backup-shares b/.bin/Scripts/mount-backup-shares index 9f3612b6..6605a81c 100755 --- a/.bin/Scripts/mount-backup-shares +++ b/.bin/Scripts/mount-backup-shares @@ -13,26 +13,27 @@ from functions.network import * init_global_vars() if __name__ == '__main__': - try: - # Prep - clear_screen() + try: + # Prep + clear_screen() - # Connect - connect_to_network() + # Connect + connect_to_network() - # Mount - if is_connected(): - mount_backup_shares(read_write=True) - else: - # Couldn't connect - print_error('ERROR: No network connectivity.') - - # Done - print_standard('\nDone.') - #pause("Press Enter to exit...") - exit_script() - except SystemExit: - pass - except: - major_exception() + # Mount + if is_connected(): + mount_backup_shares(read_write=True) + else: + # Couldn't connect + print_error('ERROR: No network connectivity.') + + # Done + print_standard('\nDone.') + #pause("Press Enter to exit...") + exit_script() + except SystemExit: + pass + except: + major_exception() +# vim: sts=2 sw=2 ts=2 From 387062074a536621ea59f903bcec05194b67fc29 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 20:30:40 -0700 Subject: [PATCH 179/265] Updated msword-search --- .bin/Scripts/msword-search | 107 +++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 53 deletions(-) diff --git a/.bin/Scripts/msword-search b/.bin/Scripts/msword-search index 3e2c175c..380c6ed5 100755 --- a/.bin/Scripts/msword-search +++ b/.bin/Scripts/msword-search @@ -9,10 +9,10 @@ import sys # STATIC VARIABLES SCANDIR = os.getcwd() USAGE = '''Usage: {script} ... - e.g. {script} "Book Title" "Keyword" "etc" + e.g. {script} "Book Title" "Keyword" "etc" - This script will search all doc/docx files below the current directory for - the search-terms provided (case-insensitive).'''.format(script=__file__) + This script will search all doc/docx files below the current directory for + the search-terms provided (case-insensitive).'''.format(script=__file__) # Init os.chdir(os.path.dirname(os.path.realpath(__file__))) @@ -23,59 +23,60 @@ init_global_vars() REGEX_DOC_FILES = re.compile(r'\.docx?$', re.IGNORECASE) def scan_for_docs(path): - for entry in os.scandir(path): - if entry.is_dir(follow_symlinks=False): - yield from scantree(entry.path) - elif entry.is_file and REGEX_DOC_FILES.search(entry.name): - yield entry + for entry in os.scandir(path): + if entry.is_dir(follow_symlinks=False): + yield from scan_for_docs(entry.path) + elif entry.is_file and REGEX_DOC_FILES.search(entry.name): + yield entry def scan_file(file_path, search): - match = False - try: - if entry.name.lower().endswith('.docx'): - result = run_program(['unzip', '-p', entry.path]) - else: - # Assuming .doc - result = run_program(['antiword', entry.path]) - out = result.stdout.decode() - match = re.search(search, out, re.IGNORECASE) - except Exception: - # Ignore errors since files may be corrupted - pass - - return entry.path if match else None + match = False + try: + if entry.name.lower().endswith('.docx'): + result = run_program(['unzip', '-p', entry.path]) + else: + # Assuming .doc + result = run_program(['antiword', entry.path]) + out = result.stdout.decode() + match = re.search(search, out, re.IGNORECASE) + except Exception: + # Ignore errors since files may be corrupted + pass + + return entry.path if match else None if __name__ == '__main__': - try: - # Prep - clear_screen() - terms = [re.sub(r'\s+', r'\s*', t) for t in sys.argv[1:]] - search = '({})'.format('|'.join(terms)) + try: + # Prep + clear_screen() + terms = [re.sub(r'\s+', r'\s*', t) for t in sys.argv[1:]] + search = '({})'.format('|'.join(terms)) - if len(sys.argv) == 1: - # Print usage - print_standard(USAGE) - else: - matches = [] - for entry in scan_for_docs(SCANDIR): - matches.append(scan_file(entry.path, search)) - # Strip None values (i.e. non-matching entries) - matches = [m for m in matches if m] - if matches: - print_success('Found {} {}:'.format( - len(matches), - 'Matches' if len(matches) > 1 else 'Match')) - for match in matches: - print_standard(match) - else: - print_error('No matches found.') - - # Done - print_standard('\nDone.') - #pause("Press Enter to exit...") - exit_script() - except SystemExit: - pass - except: - major_exception() + if len(sys.argv) == 1: + # Print usage + print_standard(USAGE) + else: + matches = [] + for entry in scan_for_docs(SCANDIR): + matches.append(scan_file(entry.path, search)) + # Strip None values (i.e. non-matching entries) + matches = [m for m in matches if m] + if matches: + print_success('Found {} {}:'.format( + len(matches), + 'Matches' if len(matches) > 1 else 'Match')) + for match in matches: + print_standard(match) + else: + print_error('No matches found.') + + # Done + print_standard('\nDone.') + #pause("Press Enter to exit...") + exit_script() + except SystemExit: + pass + except: + major_exception() +# vim: sts=2 sw=2 ts=2 From c501c8b23f6cb139ec7842379332bcf1698bd4b2 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 20:51:56 -0700 Subject: [PATCH 180/265] Updated docstrings longer than 72 characters --- .bin/Scripts/functions/browsers.py | 18 +++++++++++++++--- .bin/Scripts/functions/common.py | 6 +++--- .bin/Scripts/functions/data.py | 4 ++-- .bin/Scripts/functions/ddrescue.py | 2 +- .bin/Scripts/functions/info.py | 2 +- .bin/Scripts/functions/repairs.py | 2 +- .bin/Scripts/functions/sensors.py | 2 +- .bin/Scripts/functions/setup.py | 8 ++++---- .bin/Scripts/functions/windows_setup.py | 2 +- .bin/Scripts/functions/winpe_menus.py | 2 +- 10 files changed, 30 insertions(+), 18 deletions(-) diff --git a/.bin/Scripts/functions/browsers.py b/.bin/Scripts/functions/browsers.py index 750f8af7..6c93b8cb 100644 --- a/.bin/Scripts/functions/browsers.py +++ b/.bin/Scripts/functions/browsers.py @@ -170,7 +170,13 @@ def backup_browsers(): function=archive_browser, name=name) def clean_chromium_profile(profile): - """Renames profile, creates a new folder, and copies the user data to it.""" + """Recreate profile with only the essential user data. + + This is done by renaming the existing profile, creating a new folder + with the original name, then copying the essential files from the + backup folder. This way the original state is preserved in case + something goes wrong. + """ if profile is None: raise Exception backup_path = '{path}_{Date}.bak'.format( @@ -203,7 +209,13 @@ def clean_internet_explorer(**kwargs): pass def clean_mozilla_profile(profile): - """Renames profile, creates a new folder, and copies the user data to it.""" + """Recreate profile with only the essential user data. + + This is done by renaming the existing profile, creating a new folder + with the original name, then copying the essential files from the + backup folder. This way the original state is preserved in case + something goes wrong. + """ if profile is None: raise Exception backup_path = '{path}_{Date}.bak'.format( @@ -229,7 +241,7 @@ def clean_mozilla_profile(profile): f.write('user_pref("{}", {});\n'.format(k, v)) def get_browser_details(name): - """Get install status and profile details for all supported browsers.""" + """Get installation and profile details for all supported browsers.""" browser = SUPPORTED_BROWSERS[name].copy() # Update user_data_path diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index 24f8c1d5..b82a8918 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -94,7 +94,7 @@ def abort(): exit_script() def ask(prompt='Kotaero!'): - """Prompt the user with a Y/N question, log answer, and return a bool.""" + """Prompt the user with a Y/N question, returns bool.""" answer = None prompt = '{} [Y/N]: '.format(prompt) while answer is None: @@ -110,7 +110,7 @@ def ask(prompt='Kotaero!'): return answer def choice(choices, prompt='Kotaero!'): - """Prompt the user with a choice question, log answer, and returns str.""" + """Prompt the user with a choice question, returns str.""" answer = None choices = [str(c) for c in choices] choices_short = {c[:1].upper(): c for c in choices} @@ -252,7 +252,7 @@ def get_ticket_number(): return ticket_number def human_readable_size(size, decimals=0): - """Convert size in bytes to a human-readable format and return a str.""" + """Convert size from bytes to a human-readable format, returns str.""" # Prep string formatting width = 3+decimals if decimals > 0: diff --git a/.bin/Scripts/functions/data.py b/.bin/Scripts/functions/data.py index ed4bfa9e..d6c4ad9b 100644 --- a/.bin/Scripts/functions/data.py +++ b/.bin/Scripts/functions/data.py @@ -117,7 +117,7 @@ SEM_NOOPENFILEERRORBOX = 0x8000 SEM_FAIL = SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS def cleanup_transfer(dest_path): - """Fix attributes and move extraneous items outside the Transfer folder.""" + """Fix attributes and move excluded items to separate folder.""" try: # Remove dest_path if empty os.rmdir(dest_path) @@ -221,7 +221,7 @@ def fix_path_sep(path_str): return re.sub(r'(\\|/)+', lambda s: os.sep, path_str) def is_valid_wim_file(item): - """Checks if the provided os.DirEntry is a valid WIM file, returns bool.""" + """Checks if the item is a valid WIM file, returns bool.""" valid = bool(item.is_file() and REGEX_WIM_FILE.search(item.name)) if valid: extract_item('wimlib', silent=True) diff --git a/.bin/Scripts/functions/ddrescue.py b/.bin/Scripts/functions/ddrescue.py index 7e3a06df..e15c0c71 100644 --- a/.bin/Scripts/functions/ddrescue.py +++ b/.bin/Scripts/functions/ddrescue.py @@ -255,7 +255,7 @@ class ImageObj(BaseObj): self.path)) def set_details(self): - """Setup loopback device, set details via lsblk, then detach device.""" + """Set details using a temp loopback device.""" self.type = 'image' self.loop_dev = setup_loopback_device(self.path) self.details = get_device_details(self.loop_dev) diff --git a/.bin/Scripts/functions/info.py b/.bin/Scripts/functions/info.py index 4c691e3c..70d1062a 100644 --- a/.bin/Scripts/functions/info.py +++ b/.bin/Scripts/functions/info.py @@ -164,7 +164,7 @@ def get_installed_office(): return programs def get_shell_path(folder, user='current'): - """Get shell path using SHGetKnownFolderPath via knownpaths, returns str. + """Get shell path using knownpaths, returns str. NOTE: Only works for the current user. Code based on https://gist.github.com/mkropat/7550097 diff --git a/.bin/Scripts/functions/repairs.py b/.bin/Scripts/functions/repairs.py index bcaa5bbf..a964220c 100644 --- a/.bin/Scripts/functions/repairs.py +++ b/.bin/Scripts/functions/repairs.py @@ -43,7 +43,7 @@ def run_chkdsk_offline(): raise GenericError def run_dism(repair=False): - """Run DISM /RestoreHealth, then /CheckHealth, and then report errors.""" + """Run DISM to either scan or repair component store health.""" if global_vars['OS']['Version'] in ('8', '8.1', '10'): if repair: # Restore Health diff --git a/.bin/Scripts/functions/sensors.py b/.bin/Scripts/functions/sensors.py index eeb98922..2fde69c4 100644 --- a/.bin/Scripts/functions/sensors.py +++ b/.bin/Scripts/functions/sensors.py @@ -167,7 +167,7 @@ def monitor_sensors(monitor_pane, monitor_file): break def save_average_temp(sensor_data, temp_label, seconds=10): - """Calculate average temps and record under temp_label, returns dict.""" + """Save average temps under temp_label, returns dict.""" clear_temps(sensor_data) # Get temps diff --git a/.bin/Scripts/functions/setup.py b/.bin/Scripts/functions/setup.py index 4254a16a..17cc37fa 100644 --- a/.bin/Scripts/functions/setup.py +++ b/.bin/Scripts/functions/setup.py @@ -181,11 +181,11 @@ def config_classicstart(): popen_program(cs_exe) def config_explorer_system(): - """Configure Windows Explorer for all users via Registry settings.""" + """Configure Windows Explorer for all users.""" write_registry_settings(SETTINGS_EXPLORER_SYSTEM, all_users=True) def config_explorer_user(): - """Configure Windows Explorer for current user via Registry settings.""" + """Configure Windows Explorer for current user.""" write_registry_settings(SETTINGS_EXPLORER_USER, all_users=False) def disable_windows_telemetry(): @@ -241,7 +241,7 @@ def install_adobe_reader(): run_program(cmd) def install_chrome_extensions(): - """Update registry to install Google Chrome extensions for all users.""" + """Install Google Chrome extensions for all users.""" write_registry_settings(SETTINGS_GOOGLE_CHROME, all_users=True) def install_classicstart_skin(): @@ -258,7 +258,7 @@ def install_classicstart_skin(): shutil.copy(source, dest) def install_firefox_extensions(): - """Update registry to install Firefox extensions for all users.""" + """Install Firefox extensions for all users.""" dist_path = r'{PROGRAMFILES}\Mozilla Firefox\distribution\extensions'.format( **global_vars['Env']) source_path = r'{CBinDir}\FirefoxExtensions.7z'.format(**global_vars) diff --git a/.bin/Scripts/functions/windows_setup.py b/.bin/Scripts/functions/windows_setup.py index 228e43e2..d23dce4c 100644 --- a/.bin/Scripts/functions/windows_setup.py +++ b/.bin/Scripts/functions/windows_setup.py @@ -156,7 +156,7 @@ def format_mbr(disk): run_diskpart(script) def mount_windows_share(): - """Mount the Windows images share unless labeled as already mounted.""" + """Mount the Windows images share unless already mounted.""" if not WINDOWS_SERVER['Mounted']: # Mounting read-write in case a backup was done in the same session # and the server was left mounted read-write. This avoids throwing an diff --git a/.bin/Scripts/functions/winpe_menus.py b/.bin/Scripts/functions/winpe_menus.py index e20a3f3a..f42a6144 100644 --- a/.bin/Scripts/functions/winpe_menus.py +++ b/.bin/Scripts/functions/winpe_menus.py @@ -250,7 +250,7 @@ def menu_root(): sys.exit() def menu_setup(): - """Format a disk (MBR/GPT), apply a Windows image, and setup boot files.""" + """Format a disk, apply a Windows image, and create boot files.""" errors = False other_results = { 'Error': { From b1786e088caa239043839fb9dbac34f00bd8bf44 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 20:58:26 -0700 Subject: [PATCH 181/265] Updated hw-diags-audio --- .bin/Scripts/hw-diags-audio | 53 +++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/.bin/Scripts/hw-diags-audio b/.bin/Scripts/hw-diags-audio index 88168263..d1b09694 100755 --- a/.bin/Scripts/hw-diags-audio +++ b/.bin/Scripts/hw-diags-audio @@ -12,31 +12,32 @@ from functions.common import * init_global_vars() if __name__ == '__main__': + try: + # Prep + clear_screen() + print_standard('Hardware Diagnostics: Audio\n') + + # Set volume try: - # Prep - clear_screen() - print_standard('Hardware Diagnostics: Audio\n') - - # Set volume - try: - run_program('amixer -q set "Master" 80% unmute'.split()) - run_program('amixer -q set "PCM" 90% unmute'.split()) - except subprocess.CalledProcessError: - print_error('Failed to set volume') - - # Run tests - for mode in ['pink', 'wav']: - run_program( - cmd = 'speaker-test -c 2 -l 1 -t {}'.format(mode).split(), - check = False, - pipe = False) - - # Done - #print_standard('\nDone.') - #pause("Press Enter to exit...") - exit_script() - except SystemExit: - pass - except: - major_exception() + run_program('amixer -q set "Master" 80% unmute'.split()) + run_program('amixer -q set "PCM" 90% unmute'.split()) + except subprocess.CalledProcessError: + print_error('Failed to set volume') + + # Run tests + for mode in ['pink', 'wav']: + run_program( + cmd = 'speaker-test -c 2 -l 1 -t {}'.format(mode).split(), + check = False, + pipe = False) + + # Done + #print_standard('\nDone.') + #pause("Press Enter to exit...") + exit_script() + except SystemExit: + pass + except: + major_exception() +# vim: sts=2 sw=2 ts=2 From c7706a115f57f18ddf88811e69363df6fa7ef746 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 20:58:37 -0700 Subject: [PATCH 182/265] Updated hw-diags-network --- .bin/Scripts/hw-diags-network | 57 ++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/.bin/Scripts/hw-diags-network b/.bin/Scripts/hw-diags-network index 5fdd26a4..7e0b0bed 100755 --- a/.bin/Scripts/hw-diags-network +++ b/.bin/Scripts/hw-diags-network @@ -11,36 +11,37 @@ sys.path.append(os.getcwd()) from functions.network import * def check_connection(): - if not is_connected(): - # Raise to cause NS in try_and_print() - raise Exception + if not is_connected(): + # Raise to cause NS in try_and_print() + raise Exception if __name__ == '__main__': - try: - # Prep - clear_screen() - print_standard('Hardware Diagnostics: Network\n') + try: + # Prep + clear_screen() + print_standard('Hardware Diagnostics: Network\n') - # Connect - print_standard('Initializing...') - connect_to_network() + # Connect + print_standard('Initializing...') + connect_to_network() - # Tests - try_and_print( - message='Network connection:', function=check_connection, cs='OK') - show_valid_addresses() - try_and_print(message='Internet connection:', function=ping, - addr='8.8.8.8', cs='OK') - try_and_print(message='DNS Resolution:', function=ping, cs='OK') - try_and_print(message='Speedtest:', function=speedtest, - print_return=True) - - # Done - print_standard('\nDone.') - #pause("Press Enter to exit...") - exit_script() - except SystemExit: - pass - except: - major_exception() + # Tests + try_and_print( + message='Network connection:', function=check_connection, cs='OK') + show_valid_addresses() + try_and_print(message='Internet connection:', function=ping, + addr='8.8.8.8', cs='OK') + try_and_print(message='DNS Resolution:', function=ping, cs='OK') + try_and_print(message='Speedtest:', function=speedtest, + print_return=True) + + # Done + print_standard('\nDone.') + #pause("Press Enter to exit...") + exit_script() + except SystemExit: + pass + except: + major_exception() +# vim: sts=2 sw=2 ts=2 From 3b4668e61ba2a289d2007c722998accfabb7419c Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 21:02:04 -0700 Subject: [PATCH 183/265] Adjusted init section --- .bin/Scripts/ddrescue-tui-menu | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.bin/Scripts/ddrescue-tui-menu b/.bin/Scripts/ddrescue-tui-menu index 48cf66a4..66ed058a 100755 --- a/.bin/Scripts/ddrescue-tui-menu +++ b/.bin/Scripts/ddrescue-tui-menu @@ -6,8 +6,8 @@ import os import sys # Init -sys.path.append(os.path.dirname(os.path.realpath(__file__))) - +os.chdir(os.path.dirname(os.path.realpath(__file__))) +sys.path.append(os.getcwd()) from functions.ddrescue import * from functions.hw_diags import * init_global_vars() From d0c49240d8d24f9f5a8922923c07225c1cd80eaa Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 21:33:37 -0700 Subject: [PATCH 184/265] Added extra line break after classes/functions/etc * Also reordered some class/regex/static sections --- .bin/Scripts/functions/activation.py | 7 +- .bin/Scripts/functions/backup.py | 8 ++ .bin/Scripts/functions/browsers.py | 51 +++++++--- .bin/Scripts/functions/cleanup.py | 7 ++ .bin/Scripts/functions/common.py | 59 +++++++++-- .bin/Scripts/functions/data.py | 128 ++++++++++++++---------- .bin/Scripts/functions/ddrescue.py | 2 + .bin/Scripts/functions/disk.py | 17 ++++ .bin/Scripts/functions/hw_diags.py | 29 ++++++ .bin/Scripts/functions/info.py | 41 ++++++-- .bin/Scripts/functions/network.py | 6 ++ .bin/Scripts/functions/product_keys.py | 7 ++ .bin/Scripts/functions/repairs.py | 8 ++ .bin/Scripts/functions/safemode.py | 7 ++ .bin/Scripts/functions/sensors.py | 14 +++ .bin/Scripts/functions/setup.py | 17 ++++ .bin/Scripts/functions/sw_diags.py | 13 +++ .bin/Scripts/functions/tmux.py | 9 ++ .bin/Scripts/functions/update.py | 67 +++++++++++-- .bin/Scripts/functions/windows_setup.py | 12 +++ .bin/Scripts/functions/winpe_menus.py | 8 ++ .bin/Scripts/hw-diags-network | 2 + .bin/Scripts/msword-search | 3 + 23 files changed, 430 insertions(+), 92 deletions(-) diff --git a/.bin/Scripts/functions/activation.py b/.bin/Scripts/functions/activation.py index e10d088c..52ea8ecd 100644 --- a/.bin/Scripts/functions/activation.py +++ b/.bin/Scripts/functions/activation.py @@ -6,9 +6,11 @@ from borrowed import acpi from functions.common import * from os import environ -# Variables + +# STATIC VARIABLES SLMGR = r'{}\System32\slmgr.vbs'.format(environ.get('SYSTEMROOT')) + def activate_with_bios(): """Attempt to activate Windows with a key stored in the BIOS.""" # Code borrowed from https://github.com/aeruder/get_win8key @@ -43,6 +45,7 @@ def activate_with_bios(): if not windows_is_activated(): raise Exception('Activation Failed') + def get_activation_string(): """Get activation status, returns str.""" act_str = subprocess.run( @@ -53,6 +56,7 @@ def get_activation_string(): act_str = act_str[1].strip() return act_str + def windows_is_activated(): """Check if Windows is activated via slmgr.vbs and return bool.""" activation_string = subprocess.run( @@ -62,6 +66,7 @@ def windows_is_activated(): return bool(activation_string and 'permanent' in activation_string) + if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/functions/backup.py b/.bin/Scripts/functions/backup.py index f7679db2..ad03f822 100644 --- a/.bin/Scripts/functions/backup.py +++ b/.bin/Scripts/functions/backup.py @@ -4,6 +4,7 @@ import ctypes from functions.disk import * + # Regex REGEX_BAD_PATH_NAMES = re.compile( r'([<>:"/\|\?\*]' @@ -12,6 +13,7 @@ REGEX_BAD_PATH_NAMES = re.compile( r'|[\s\.]+$', re.IGNORECASE) + def backup_partition(disk, par): """Create a backup image of a partition.""" if (par.get('Image Exists', False) @@ -31,6 +33,7 @@ def backup_partition(disk, par): os.makedirs(dest_dir, exist_ok=True) run_program(cmd) + def fix_path(path): """Replace invalid filename characters with underscores.""" local_drive = path[1:2] == ':' @@ -39,6 +42,7 @@ def fix_path(path): new_path = '{}:{}'.format(new_path[0:1], new_path[2:]) return new_path + def get_volume_display_name(mountpoint): """Get display name from volume mountpoint and label, returns str.""" name = mountpoint @@ -67,6 +71,7 @@ def get_volume_display_name(mountpoint): return name + def prep_disk_for_backup(destination, disk, backup_prefix): """Gather details about the disk and its partitions. @@ -143,6 +148,7 @@ def prep_disk_for_backup(destination, disk, backup_prefix): COLORS['YELLOW'], COLORS['CLEAR']) disk['Backup Warnings'] = warnings + def select_backup_destination(auto_select=True): """Select a backup destination from a menu, returns server dict.""" destinations = [s for s in BACKUP_SERVERS if s['Mounted']] @@ -193,6 +199,7 @@ def select_backup_destination(auto_select=True): else: return destinations[int(selection)-1] + def verify_wim_backup(partition): """Verify WIM integrity.""" if not os.path.exists(partition['Image Path']): @@ -205,6 +212,7 @@ def verify_wim_backup(partition): ] run_program(cmd) + if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/functions/browsers.py b/.bin/Scripts/functions/browsers.py index 6c93b8cb..e73399bc 100644 --- a/.bin/Scripts/functions/browsers.py +++ b/.bin/Scripts/functions/browsers.py @@ -4,6 +4,7 @@ from functions.common import * from operator import itemgetter + # Define other_results for later try_and_print browser_data = {} other_results = { @@ -16,22 +17,6 @@ other_results = { } } -# Regex -REGEX_BACKUP = re.compile( - r'\.\w*bak.*', - re.IGNORECASE) -REGEX_CHROMIUM_PROFILE = re.compile( - r'^(Default|Profile)', - re.IGNORECASE) -REGEX_CHROMIUM_ITEMS = re.compile( - r'^(Bookmarks|Cookies|Favicons|Google Profile' - r'|History|Login Data|Top Sites|TransportSecurity' - r'|Visited Links|Web Data)', - re.IGNORECASE) -REGEX_MOZILLA = re.compile( - r'^(bookmarkbackups|(cookies|formhistory|places).sqlite' - r'|key3.db|logins.json|persdict.dat)$', - re.IGNORECASE) # STATIC VARIABLES DEFAULT_HOMEPAGE = 'https://www.google.com/' @@ -103,6 +88,25 @@ SUPPORTED_BROWSERS = { }, } + +# Regex +REGEX_BACKUP = re.compile( + r'\.\w*bak.*', + re.IGNORECASE) +REGEX_CHROMIUM_PROFILE = re.compile( + r'^(Default|Profile)', + re.IGNORECASE) +REGEX_CHROMIUM_ITEMS = re.compile( + r'^(Bookmarks|Cookies|Favicons|Google Profile' + r'|History|Login Data|Top Sites|TransportSecurity' + r'|Visited Links|Web Data)', + re.IGNORECASE) +REGEX_MOZILLA = re.compile( + r'^(bookmarkbackups|(cookies|formhistory|places).sqlite' + r'|key3.db|logins.json|persdict.dat)$', + re.IGNORECASE) + + def archive_all_users(): """Create backups for all browsers for all users.""" users_root = r'{}\Users'.format(global_vars['Env']['SYSTEMDRIVE']) @@ -149,6 +153,7 @@ def archive_all_users(): function=run_program, cmd=cmd) print_standard(' ') + def archive_browser(name): """Create backup of Browser saved in the BackupDir.""" source = '{}*'.format(browser_data[name]['user_data_path']) @@ -163,12 +168,14 @@ def archive_browser(name): archive, source] run_program(cmd) + def backup_browsers(): """Create backup of all detected browser profiles.""" for name in [k for k, v in sorted(browser_data.items()) if v['profiles']]: try_and_print(message='{}...'.format(name), function=archive_browser, name=name) + def clean_chromium_profile(profile): """Recreate profile with only the essential user data. @@ -191,6 +198,7 @@ def clean_chromium_profile(profile): shutil.copy(entry.path, r'{}\{}'.format( profile['path'], entry.name)) + def clean_internet_explorer(**kwargs): """Uses the built-in function to reset IE and sets the homepage. @@ -208,6 +216,7 @@ def clean_internet_explorer(**kwargs): except FileNotFoundError: pass + def clean_mozilla_profile(profile): """Recreate profile with only the essential user data. @@ -240,6 +249,7 @@ def clean_mozilla_profile(profile): for k, v in MOZILLA_PREFS.items(): f.write('user_pref("{}", {});\n'.format(k, v)) + def get_browser_details(name): """Get installation and profile details for all supported browsers.""" browser = SUPPORTED_BROWSERS[name].copy() @@ -314,6 +324,7 @@ def get_browser_details(name): elif num_installs > 1 and browser['base'] != 'ie': raise MultipleInstallationsError + def get_chromium_profiles(search_path): """Find any chromium-style profiles and return as a list of dicts.""" profiles = [] @@ -330,6 +341,7 @@ def get_chromium_profiles(search_path): return profiles + def get_ie_homepages(): """Read homepages from the registry and return as a list.""" homepages = [] @@ -354,6 +366,7 @@ def get_ie_homepages(): homepages = [h.replace('{', '').replace('}', '') for h in homepages] return homepages + def get_mozilla_homepages(prefs_path): """Read homepages from prefs.js and return as a list.""" homepages = [] @@ -369,6 +382,7 @@ def get_mozilla_homepages(prefs_path): return homepages + def get_mozilla_profiles(search_path, dev=False): """Find any mozilla-style profiles and return as a list of dicts.""" profiles = [] @@ -393,6 +407,7 @@ def get_mozilla_profiles(search_path, dev=False): return profiles + def install_adblock(indent=8, width=32, just_firefox=False): """Install adblock for all supported browsers.""" for browser in sorted(browser_data): @@ -461,6 +476,7 @@ def install_adblock(indent=8, width=32, just_firefox=False): cs='Done', function=function, cmd=[exe_path, *urls], check=False) + def list_homepages(indent=8, width=32): """List current homepages for reference.""" browser_list = [k for k, v in sorted(browser_data.items()) if v['exe_path']] @@ -491,6 +507,7 @@ def list_homepages(indent=8, width=32): print_standard('{indent}{name:<{width}}{page}'.format( indent=' '*indent, width=width, name=name, page=page)) + def reset_browsers(indent=8, width=32): """Reset all detected browsers to safe defaults.""" browser_list = [k for k, v in sorted(browser_data.items()) if v['profiles']] @@ -508,6 +525,7 @@ def reset_browsers(indent=8, width=32): indent=indent, width=width, function=function, other_results=other_results, profile=profile) + def scan_for_browsers(just_firefox=False): """Scan system for any supported browsers.""" for name, details in sorted(SUPPORTED_BROWSERS.items()): @@ -517,6 +535,7 @@ def scan_for_browsers(just_firefox=False): function=get_browser_details, cs='Detected', other_results=other_results, name=name) + if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/functions/cleanup.py b/.bin/Scripts/functions/cleanup.py index 80ffd879..5ee20be1 100644 --- a/.bin/Scripts/functions/cleanup.py +++ b/.bin/Scripts/functions/cleanup.py @@ -2,6 +2,7 @@ from functions.common import * + def cleanup_adwcleaner(): """Move AdwCleaner folders into the ClientDir.""" source_path = r'{SYSTEMDRIVE}\AdwCleaner'.format(**global_vars['Env']) @@ -26,6 +27,7 @@ def cleanup_adwcleaner(): dest_name = non_clobber_rename(dest_name) shutil.move(source_path, dest_name) + def cleanup_cbs(dest_folder): """Safely cleanup a known CBS archive bug under Windows 7. @@ -65,6 +67,7 @@ def cleanup_cbs(dest_folder): r'{}\CbsPersist*'.format(temp_folder)] run_program(cmd) + def cleanup_desktop(): """Move known backup files and reports into the ClientDir.""" dest_folder = r'{LogDir}\Tools'.format(**global_vars) @@ -81,6 +84,7 @@ def cleanup_desktop(): # Remove dir if empty delete_empty_folders(dest_folder) + def delete_empty_folders(folder_path): """Delete all empty folders in path (depth first).""" if not os.path.exists(folder_path) or not os.path.isdir(folder_path): @@ -98,6 +102,7 @@ def delete_empty_folders(folder_path): except OSError: pass + def delete_registry_key(hive, key, recurse=False): """Delete a registry key and all it's subkeys.""" access = winreg.KEY_ALL_ACCESS @@ -117,12 +122,14 @@ def delete_registry_key(hive, key, recurse=False): # Ignore pass + def delete_registry_value(hive, key, value): """Delete a registry value.""" access = winreg.KEY_ALL_ACCESS with winreg.OpenKeyEx(hive, key, 0, access) as k: winreg.DeleteValue(k, value) + if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index b82a8918..a0a87b76 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -20,9 +20,11 @@ from settings.main import * from settings.tools import * from settings.windows_builds import * + # Global variables global_vars = {} + # STATIC VARIABLES COLORS = { 'CLEAR': '\033[0m', @@ -42,6 +44,7 @@ except NameError: if psutil.WINDOWS: raise + # Error Classes class BIOSKeyNotFoundError(Exception): pass @@ -85,6 +88,7 @@ class SecureBootNotAvailError(Exception): class SecureBootUnknownError(Exception): pass + # General functions def abort(): """Abort script.""" @@ -93,6 +97,7 @@ def abort(): pause(prompt='Press Enter to exit... ') exit_script() + def ask(prompt='Kotaero!'): """Prompt the user with a Y/N question, returns bool.""" answer = None @@ -109,6 +114,7 @@ def ask(prompt='Kotaero!'): print_log(message=message) return answer + def choice(choices, prompt='Kotaero!'): """Prompt the user with a choice question, returns str.""" answer = None @@ -137,6 +143,7 @@ def choice(choices, prompt='Kotaero!'): # Done return answer + def clear_screen(): """Simple wrapper for cls/clear.""" if psutil.WINDOWS: @@ -144,6 +151,7 @@ def clear_screen(): else: os.system('clear') + def convert_to_bytes(size): """Convert human-readable size str to bytes and return an int.""" size = str(size) @@ -165,6 +173,7 @@ def convert_to_bytes(size): return size + def exit_script(return_value=0): """Exits the script after some cleanup and opens the log (if set).""" # Remove dirs (if empty) @@ -192,6 +201,7 @@ def exit_script(return_value=0): # Exit sys.exit(return_value) + def extract_item(item, filter='', silent=False): """Extract item from .cbin into .bin.""" cmd = [ @@ -211,6 +221,7 @@ def extract_item(item, filter='', silent=False): if not silent: print_warning('WARNING: Errors encountered while exctracting data') + def get_process(name=None): """Get process by name, returns psutil.Process obj.""" proc = None @@ -226,6 +237,7 @@ def get_process(name=None): pass return proc + def get_simple_string(prompt='Enter string'): """Get string from user (restricted character set), returns str.""" simple_string = None @@ -235,6 +247,7 @@ def get_simple_string(prompt='Enter string'): simple_string = _input.strip() return simple_string + def get_ticket_number(): """Get TicketNumber from user, save in LogDir, and return as str.""" if not ENABLED_TICKET_NUMBERS: @@ -251,6 +264,7 @@ def get_ticket_number(): f.write(ticket_number) return ticket_number + def human_readable_size(size, decimals=0): """Convert size from bytes to a human-readable format, returns str.""" # Prep string formatting @@ -290,12 +304,14 @@ def human_readable_size(size, decimals=0): return '{size:>{width}.{decimals}f} {units}'.format( size=size, width=width, decimals=decimals, units=units) + def kill_process(name): """Kill any running caffeine.exe processes.""" for proc in psutil.process_iter(): if proc.name() == name: proc.kill() + def major_exception(): """Display traceback and exit""" print_error('Major exception') @@ -319,6 +335,7 @@ def major_exception(): pause('Press Enter to exit...') exit_script(1) + def menu_select( title='[Untitled Menu]', prompt='Please make a selection', secret_actions=[], secret_exit=False, @@ -382,6 +399,7 @@ def menu_select( return answer.upper() + def non_clobber_rename(full_path): """Append suffix to path, if necessary, to avoid clobbering path""" new_path = full_path @@ -392,10 +410,12 @@ def non_clobber_rename(full_path): return new_path + def pause(prompt='Press Enter to continue... '): """Simple pause implementation.""" input(prompt) + def ping(addr='google.com'): """Attempt to ping addr.""" cmd = [ @@ -405,6 +425,7 @@ def ping(addr='google.com'): addr] run_program(cmd) + def popen_program(cmd, pipe=False, minimized=False, shell=False, **kwargs): """Run program and return a subprocess.Popen object.""" cmd_kwargs = {'args': cmd, 'shell': shell} @@ -426,14 +447,17 @@ def popen_program(cmd, pipe=False, minimized=False, shell=False, **kwargs): return subprocess.Popen(**cmd_kwargs) + def print_error(*args, **kwargs): """Prints message to screen in RED.""" print_standard(*args, color=COLORS['RED'], **kwargs) + def print_info(*args, **kwargs): """Prints message to screen in BLUE.""" print_standard(*args, color=COLORS['BLUE'], **kwargs) + def print_standard(message='Generic info', color=None, end='\n', timestamp=True, **kwargs): """Prints message to screen and log (if set).""" @@ -444,14 +468,17 @@ def print_standard(message='Generic info', print(display_message.format(**COLORS), end=end, **kwargs) print_log(message, end, timestamp) + def print_success(*args, **kwargs): """Prints message to screen in GREEN.""" print_standard(*args, color=COLORS['GREEN'], **kwargs) + def print_warning(*args, **kwargs): """Prints message to screen in YELLOW.""" print_standard(*args, color=COLORS['YELLOW'], **kwargs) + def print_log(message='', end='\n', timestamp=True): """Writes message to a log if LogFile is set.""" time_str = time.strftime("%Y-%m-%d %H%M%z: ") if timestamp else '' @@ -463,6 +490,7 @@ def print_log(message='', end='\n', timestamp=True): line = line, end = end)) + def run_program(cmd, args=[], check=True, pipe=True, shell=False, **kwargs): """Run program and return a subprocess.CompletedProcess object.""" if args: @@ -486,6 +514,7 @@ def run_program(cmd, args=[], check=True, pipe=True, shell=False, **kwargs): return subprocess.run(**cmd_kwargs) + def set_title(title='[Some Title]'): """Set title. @@ -493,6 +522,7 @@ def set_title(title='[Some Title]'): global_vars['Title'] = title os.system('title {}'.format(title)) + def show_data( message='[Some message]', data='[Some data]', indent=8, width=32, @@ -509,10 +539,12 @@ def show_data( else: print_standard(message) + def sleep(seconds=2): """Wait for a while.""" time.sleep(seconds) + def stay_awake(): """Prevent the system from sleeping or hibernating.""" # DISABLED due to VCR2008 dependency @@ -529,12 +561,14 @@ def stay_awake(): print_error('ERROR: No caffeine available.') print_warning('Please set the power setting to High Performance.') + def strip_colors(s): """Remove all ASCII color escapes from string, returns str.""" for c in COLORS.values(): s = s.replace(c, '') return s + def get_exception(s): """Get exception by name, returns Exception object.""" try: @@ -544,6 +578,7 @@ def get_exception(s): obj = getattr(sys.modules['builtins'], s) return obj + def try_and_print(message='Trying...', function=None, cs='CS', ns='NS', other_results={}, catch_all=True, print_return=False, silent_function=True, @@ -600,6 +635,7 @@ def try_and_print(message='Trying...', else: return {'CS': not bool(err), 'Error': err, 'Out': out} + def upload_crash_details(): """Upload log and runtime data to the CRASH_SERVER. @@ -611,13 +647,11 @@ def upload_crash_details(): if 'LogFile' in global_vars and global_vars['LogFile']: if ask('Upload crash details to {}?'.format(CRASH_SERVER['Name'])): with open(global_vars['LogFile']) as f: - data = '''{} -############################# -Runtime Details: - -sys.argv: {} - -global_vars: {}'''.format(f.read(), sys.argv, global_vars) + data = '{}\n'.format(f.read()) + data += '#############################\n' + data += 'Runtime Details:\n\n' + data += 'sys.argv: {}\n\n'.format(sys.argv) + data += 'global_vars: {}\n'.format(global_vars) filename = global_vars.get('LogFile', 'Unknown') filename = re.sub(r'.*(\\|/)', '', filename) filename += '.txt' @@ -639,6 +673,7 @@ global_vars: {}'''.format(f.read(), sys.argv, global_vars) # No LogFile defined (or invalid LogFile) raise GenericError + def wait_for_process(name, poll_rate=3): """Wait for process by name.""" running = True @@ -654,6 +689,7 @@ def wait_for_process(name, poll_rate=3): pass sleep(1) + # global_vars functions def init_global_vars(silent=False): """Sets global variables based on system info.""" @@ -687,6 +723,7 @@ def init_global_vars(silent=False): except: major_exception() + def check_os(): """Set OS specific variables.""" tmp = {} @@ -749,6 +786,7 @@ def check_os(): global_vars['OS'] = tmp + def check_tools(): """Set tool variables based on OS bit-depth and tool availability.""" if global_vars['OS'].get('Arch', 32) == 64: @@ -761,6 +799,7 @@ def check_tools(): global_vars['Tools'] = {k: os.path.join(global_vars['BinDir'], v) for (k, v) in global_vars['Tools'].items()} + def clean_env_vars(): """Remove conflicting global_vars and env variables. @@ -769,6 +808,7 @@ def clean_env_vars(): for key in global_vars.keys(): global_vars['Env'].pop(key, None) + def find_bin(): """Find .bin folder in the cwd or it's parents.""" wd = os.getcwd() @@ -785,6 +825,7 @@ def find_bin(): raise BinNotFoundError global_vars['BaseDir'] = base + def make_tmp_dirs(): """Make temp directories.""" os.makedirs(global_vars['BackupDir'], exist_ok=True) @@ -794,6 +835,7 @@ def make_tmp_dirs(): os.makedirs(r'{}\Tools'.format(global_vars['LogDir']), exist_ok=True) os.makedirs(global_vars['TmpDir'], exist_ok=True) + def set_common_vars(): """Set common variables.""" global_vars['Date'] = time.strftime("%Y-%m-%d") @@ -816,6 +858,7 @@ def set_common_vars(): global_vars['TmpDir'] = r'{BinDir}\tmp'.format( **global_vars) + def set_linux_vars(): """Set common variables in a Linux environment. @@ -832,6 +875,7 @@ def set_linux_vars(): 'SevenZip': '7z', } + def set_log_file(log_name): """Sets global var LogFile and creates path as needed.""" folder_path = r'{}\{}'.format(global_vars['LogDir'], KIT_NAME_FULL) @@ -839,6 +883,7 @@ def set_log_file(log_name): os.makedirs(folder_path, exist_ok=True) global_vars['LogFile'] = log_file + if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/functions/data.py b/.bin/Scripts/functions/data.py index d6c4ad9b..a151b24c 100644 --- a/.bin/Scripts/functions/data.py +++ b/.bin/Scripts/functions/data.py @@ -7,57 +7,6 @@ from operator import itemgetter from functions.common import * -# Classes -class LocalDisk(): - def __init__(self, disk): - self.disk = disk - self.name = disk.mountpoint.upper() - self.path = self.name - def is_dir(self): - # Should always be true - return True - def is_file(self): - # Should always be false - return False - -class SourceItem(): - def __init__(self, name, path): - self.name = name - self.path = path - -# Regex -REGEX_EXCL_ITEMS = re.compile( - r'^(\.(AppleDB|AppleDesktop|AppleDouble' - r'|com\.apple\.timemachine\.supported|dbfseventsd' - r'|DocumentRevisions-V100.*|DS_Store|fseventsd|PKInstallSandboxManager' - r'|Spotlight.*|SymAV.*|symSchedScanLockxz|TemporaryItems|Trash.*' - r'|vol|VolumeIcon\.icns)|desktop\.(ini|.*DB|.*DF)' - r'|(hiberfil|pagefile)\.sys|lost\+found|Network\.*Trash\.*Folder' - r'|Recycle[dr]|System\.*Volume\.*Information|Temporary\.*Items' - r'|Thumbs\.db)$', - re.IGNORECASE) -REGEX_EXCL_ROOT_ITEMS = re.compile( - r'^(boot(mgr|nxt)$|Config.msi' - r'|(eula|globdata|install|vc_?red)' - r'|.*.sys$|System Volume Information|RECYCLER?|\$Recycle\.bin' - r'|\$?Win(dows(.old.*|\. BT|)$|RE_)|\$GetCurrent|Windows10Upgrade' - r'|PerfLogs|Program Files|SYSTEM.SAV' - r'|.*\.(esd|swm|wim|dd|map|dmg|image)$)', - re.IGNORECASE) -REGEX_INCL_ROOT_ITEMS = re.compile( - r'^(AdwCleaner|(My\s*|)(Doc(uments?( and Settings|)|s?)|Downloads' - r'|Media|Music|Pic(ture|)s?|Vid(eo|)s?)' - r'|{prefix}(-?Info|-?Transfer|)' - r'|(ProgramData|Recovery|Temp.*|Users)$' - r'|.*\.(log|txt|rtf|qb\w*|avi|m4a|m4v|mp4|mkv|jpg|png|tiff?)$)' - r''.format(prefix=KIT_NAME_SHORT), - re.IGNORECASE) -REGEX_WIM_FILE = re.compile( - r'\.wim$', - re.IGNORECASE) -REGEX_WINDOWS_OLD = re.compile( - r'^Win(dows|)\.old', - re.IGNORECASE) # STATIC VARIABLES FAST_COPY_EXCLUDES = [ @@ -116,6 +65,63 @@ SEM_FAILCRITICALERRORS = 1 SEM_NOOPENFILEERRORBOX = 0x8000 SEM_FAIL = SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS + +# Regex +REGEX_EXCL_ITEMS = re.compile( + r'^(\.(AppleDB|AppleDesktop|AppleDouble' + r'|com\.apple\.timemachine\.supported|dbfseventsd' + r'|DocumentRevisions-V100.*|DS_Store|fseventsd|PKInstallSandboxManager' + r'|Spotlight.*|SymAV.*|symSchedScanLockxz|TemporaryItems|Trash.*' + r'|vol|VolumeIcon\.icns)|desktop\.(ini|.*DB|.*DF)' + r'|(hiberfil|pagefile)\.sys|lost\+found|Network\.*Trash\.*Folder' + r'|Recycle[dr]|System\.*Volume\.*Information|Temporary\.*Items' + r'|Thumbs\.db)$', + re.IGNORECASE) +REGEX_EXCL_ROOT_ITEMS = re.compile( + r'^(boot(mgr|nxt)$|Config.msi' + r'|(eula|globdata|install|vc_?red)' + r'|.*.sys$|System Volume Information|RECYCLER?|\$Recycle\.bin' + r'|\$?Win(dows(.old.*|\. BT|)$|RE_)|\$GetCurrent|Windows10Upgrade' + r'|PerfLogs|Program Files|SYSTEM.SAV' + r'|.*\.(esd|swm|wim|dd|map|dmg|image)$)', + re.IGNORECASE) +REGEX_INCL_ROOT_ITEMS = re.compile( + r'^(AdwCleaner|(My\s*|)(Doc(uments?( and Settings|)|s?)|Downloads' + r'|Media|Music|Pic(ture|)s?|Vid(eo|)s?)' + r'|{prefix}(-?Info|-?Transfer|)' + r'|(ProgramData|Recovery|Temp.*|Users)$' + r'|.*\.(log|txt|rtf|qb\w*|avi|m4a|m4v|mp4|mkv|jpg|png|tiff?)$)' + r''.format(prefix=KIT_NAME_SHORT), + re.IGNORECASE) +REGEX_WIM_FILE = re.compile( + r'\.wim$', + re.IGNORECASE) +REGEX_WINDOWS_OLD = re.compile( + r'^Win(dows|)\.old', + re.IGNORECASE) + + +# Classes +class LocalDisk(): + def __init__(self, disk): + self.disk = disk + self.name = disk.mountpoint.upper() + self.path = self.name + def is_dir(self): + # Should always be true + return True + def is_file(self): + # Should always be false + return False + + +class SourceItem(): + def __init__(self, name, path): + self.name = name + self.path = path + + +# Functions def cleanup_transfer(dest_path): """Fix attributes and move excluded items to separate folder.""" try: @@ -153,6 +159,7 @@ def cleanup_transfer(dest_path): except Exception: pass + def find_core_storage_volumes(device_path=None): """Try to create block devices for any Apple CoreStorage volumes.""" corestorage_uuid = '53746f72-6167-11aa-aa11-00306543ecac' @@ -216,10 +223,12 @@ def find_core_storage_volumes(device_path=None): cmd = ['sudo', 'dmsetup', 'create', name, dmsetup_cmd_file] run_program(cmd, check=False) + def fix_path_sep(path_str): """Replace non-native and duplicate dir separators, returns str.""" return re.sub(r'(\\|/)+', lambda s: os.sep, path_str) + def is_valid_wim_file(item): """Checks if the item is a valid WIM file, returns bool.""" valid = bool(item.is_file() and REGEX_WIM_FILE.search(item.name)) @@ -233,6 +242,7 @@ def is_valid_wim_file(item): print_log('WARNING: Image "{}" damaged.'.format(item.name)) return valid + def get_mounted_volumes(): """Get mounted volumes, returns dict.""" cmd = [ @@ -250,6 +260,7 @@ def get_mounted_volumes(): mounted_volumes.extend(item.get('children', [])) return {item['source']: item for item in mounted_volumes} + def mount_volumes( all_devices=True, device_path=None, read_write=False, core_storage=True): @@ -342,6 +353,7 @@ def mount_volumes( return report + def mount_backup_shares(read_write=False): """Mount the backup shares unless labeled as already mounted.""" if psutil.LINUX: @@ -363,6 +375,7 @@ def mount_backup_shares(read_write=False): mount_network_share(server, read_write) + def mount_network_share(server, read_write=False): """Mount a network share defined by server.""" if read_write: @@ -415,6 +428,7 @@ def mount_network_share(server, read_write=False): print_info(success) server['Mounted'] = True + def run_fast_copy(items, dest): """Copy items to dest using FastCopy.""" if not items: @@ -427,6 +441,7 @@ def run_fast_copy(items, dest): run_program(cmd) + def run_wimextract(source, items, dest): """Extract items from source WIM to dest folder.""" if not items: @@ -452,6 +467,7 @@ def run_wimextract(source, items, dest): '--nullglob'] run_program(cmd) + def list_source_items(source_obj, rel_path=None): """List items in a dir or WIM, returns list of SourceItem objects.""" items = [] @@ -489,6 +505,7 @@ def list_source_items(source_obj, rel_path=None): # Done return items + def scan_source(source_obj, dest_path, rel_path='', interactive=True): """Scan source for files/folders to transfer, returns list. @@ -572,6 +589,7 @@ def scan_source(source_obj, dest_path, rel_path='', interactive=True): # Done return selected_items + def get_source_item_obj(source_obj, rel_path, item_path): """Check if the item exists, returns SourceItem object or None.""" item_obj = None @@ -611,6 +629,7 @@ def get_source_item_obj(source_obj, rel_path, item_path): item_path)) return item_obj + def select_destination(folder_path, prompt='Select destination'): """Select destination drive, returns path as string.""" disk = select_volume(prompt) @@ -627,6 +646,7 @@ def select_destination(folder_path, prompt='Select destination'): return path + def select_source(backup_prefix): """Select matching backup from BACKUP_SERVERS, returns obj.""" selected_source = None @@ -792,6 +812,7 @@ def select_source(backup_prefix): # Done return selected_source + def select_volume(title='Select disk', auto_select=True): """Select disk from attached disks. returns dict.""" actions = [{'Name': 'Quit', 'Letter': 'Q'}] @@ -829,6 +850,7 @@ def select_volume(title='Select disk', auto_select=True): else: return disks[int(selection)-1] + def set_thread_error_mode(silent=True): """Disable or Enable Windows error message dialogs. @@ -842,6 +864,7 @@ def set_thread_error_mode(silent=True): else: kernel32.SetThreadErrorMode(SEM_NORMAL, ctypes.byref(SEM_NORMAL)) + def transfer_source(source_obj, dest_path, selected_items): """Transfer, or extract, files/folders from source to destination.""" if source_obj.is_dir(): @@ -864,11 +887,13 @@ def transfer_source(source_obj, dest_path, selected_items): print_error('ERROR: Unsupported image: {}'.format(source_obj.path)) raise GenericError + def umount_backup_shares(): """Unmount the backup shares regardless of current status.""" for server in BACKUP_SERVERS: umount_network_share(server) + def umount_network_share(server): """Unmount a network share defined by server.""" cmd = r'net use \\{IP}\{Share} /delete'.format(**server) @@ -882,6 +907,7 @@ def umount_network_share(server): print_info('Umounted {Name}'.format(**server)) server['Mounted'] = False + if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/functions/ddrescue.py b/.bin/Scripts/functions/ddrescue.py index e15c0c71..e6def7f2 100644 --- a/.bin/Scripts/functions/ddrescue.py +++ b/.bin/Scripts/functions/ddrescue.py @@ -15,6 +15,7 @@ from functions.hw_diags import * from functions.tmux import * from operator import itemgetter + # STATIC VARIABLES AUTO_PASS_1_THRESHOLD = 95 AUTO_PASS_2_THRESHOLD = 98 @@ -778,6 +779,7 @@ def menu_ddrescue(source_path, dest_path, run_mode): run_program(['tmux', 'kill-window']) exit_script() + def menu_main(state): """Main menu is used to set ddrescue settings.""" title = '{GREEN}ddrescue TUI: Main Menu{CLEAR}\n\n'.format(**COLORS) diff --git a/.bin/Scripts/functions/disk.py b/.bin/Scripts/functions/disk.py index 88b26155..31fe577d 100644 --- a/.bin/Scripts/functions/disk.py +++ b/.bin/Scripts/functions/disk.py @@ -3,6 +3,7 @@ from functions.common import * from settings.partition_uids import * + # Regex REGEX_BAD_PARTITION = re.compile(r'(RAW|Unknown)', re.IGNORECASE) REGEX_DISK_GPT = re.compile( @@ -11,6 +12,7 @@ REGEX_DISK_GPT = re.compile( REGEX_DISK_MBR = re.compile(r'Disk ID: [A-Z0-9]+', re.IGNORECASE) REGEX_DISK_RAW = re.compile(r'Disk ID: 00000000', re.IGNORECASE) + def assign_volume_letters(): """Assign a volume letter to all available volumes.""" remove_volume_letters() @@ -24,6 +26,7 @@ def assign_volume_letters(): # Run run_diskpart(script) + def get_boot_mode(): """Check if the boot mode was UEFI or legacy.""" boot_mode = 'Legacy' @@ -38,6 +41,7 @@ def get_boot_mode(): return boot_mode + def get_disk_details(disk): """Get disk details using DiskPart.""" details = {} @@ -63,6 +67,7 @@ def get_disk_details(disk): return details + def get_disks(): """Get list of attached disks using DiskPart.""" disks = [] @@ -82,6 +87,7 @@ def get_disks(): return disks + def get_partition_details(disk, partition): """Get partition details using DiskPart and fsutil.""" details = {} @@ -161,6 +167,7 @@ def get_partition_details(disk, partition): return details + def get_partitions(disk): """Get list of partition using DiskPart.""" partitions = [] @@ -184,6 +191,7 @@ def get_partitions(disk): return partitions + def get_table_type(disk): """Get disk partition table type using DiskPart.""" part_type = 'Unknown' @@ -206,6 +214,7 @@ def get_table_type(disk): return part_type + def get_volumes(): """Get list of volumes using DiskPart.""" vols = [] @@ -221,10 +230,12 @@ def get_volumes(): return vols + def is_bad_partition(par): """Check if the partition is accessible.""" return 'Letter' not in par or REGEX_BAD_PARTITION.search(par['FileSystem']) + def prep_disk_for_formatting(disk=None): """Gather details about the disk and its partitions.""" disk['Format Warnings'] = '\n' @@ -270,6 +281,7 @@ def prep_disk_for_formatting(disk=None): # For all partitions partition['Display String'] = display + def reassign_volume_letter(letter, new_letter='I'): """Assign a new letter to a volume using DiskPart.""" if not letter: @@ -286,6 +298,7 @@ def reassign_volume_letter(letter, new_letter='I'): else: return new_letter + def remove_volume_letters(keep=None): """Remove all assigned volume letters using DiskPart.""" if not keep: @@ -303,6 +316,7 @@ def remove_volume_letters(keep=None): except subprocess.CalledProcessError: pass + def run_diskpart(script): """Run DiskPart script.""" tempfile = r'{}\diskpart.script'.format(global_vars['Env']['TMP']) @@ -321,6 +335,7 @@ def run_diskpart(script): sleep(2) return result + def scan_disks(): """Get details about the attached disks""" disks = get_disks() @@ -343,6 +358,7 @@ def scan_disks(): # Done return disks + def select_disk(title='Which disk?', disks=[]): """Select a disk from the attached disks""" # Build menu @@ -391,6 +407,7 @@ def select_disk(title='Which disk?', disks=[]): elif (selection == 'M'): raise GenericAbort + if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 210ae870..155031ec 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -8,6 +8,7 @@ from collections import OrderedDict from functions.sensors import * from functions.tmux import * + # STATIC VARIABLES ATTRIBUTES = { 'NVMe': { @@ -83,13 +84,16 @@ TMUX_LAYOUT = OrderedDict({ 'Progress': {'x': SIDE_PANE_WIDTH, 'Check': True}, }) + # Regex REGEX_ERROR_STATUS = re.compile('|'.join(STATUSES['RED'])) + # Error Classes class DeviceTooSmallError(Exception): pass + # Classes class CpuObj(): """Object for tracking CPU specific data.""" @@ -130,6 +134,7 @@ class CpuObj(): return report + class DiskObj(): """Object for tracking disk specific data.""" def __init__(self, disk_path): @@ -487,6 +492,7 @@ class DiskObj(): for t in ['badblocks', 'I/O Benchmark']: self.disable_test(t, 'Denied') + class State(): """Object to track device objects and overall state.""" def __init__(self): @@ -559,6 +565,7 @@ class State(): if not skip_disk: self.disks.append(disk_obj) + class TestObj(): """Object to track test data.""" def __init__(self, dev, label=None, info_label=False): @@ -589,6 +596,7 @@ class TestObj(): self.status = build_status_string( self.label, 'Working', self.info_label) + # Functions def build_outer_panes(state): """Build top and side panes.""" @@ -611,6 +619,7 @@ def build_outer_panes(state): lines=SIDE_PANE_WIDTH, watch=state.progress_out) + def build_status_string(label, status, info_label=False): """Build status string with appropriate colors.""" status_color = COLORS['CLEAR'] @@ -626,6 +635,7 @@ def build_status_string(label, status, info_label=False): s_w=SIDE_PANE_WIDTH-len(label), **COLORS) + def fix_tmux_panes(state, tmux_layout): """Fix pane sizes if the window has been resized.""" needs_fixed = False @@ -669,6 +679,7 @@ def fix_tmux_panes(state, tmux_layout): # Resize pane tmux_resize_pane(pane_id=target, **v) + def generate_horizontal_graph(rates, oneline=False): """Generate horizontal graph from rates, returns list.""" graph = ['', '', '', ''] @@ -714,6 +725,7 @@ def generate_horizontal_graph(rates, oneline=False): else: return graph + def get_graph_step(rate, scale=16): """Get graph step based on rate and scale, returns int.""" m_rate = rate / (1024**2) @@ -726,6 +738,7 @@ def get_graph_step(rate, scale=16): break return step + def get_read_rate(s): """Get read rate in bytes/s from dd progress output.""" real_rate = None @@ -734,6 +747,7 @@ def get_read_rate(s): real_rate = convert_to_bytes(human_rate) return real_rate + def menu_diags(state, args): """Main menu to select and run HW tests.""" args = [a.lower() for a in args] @@ -840,12 +854,14 @@ def menu_diags(state, args): elif selection == 'S': run_hw_tests(state) + def run_audio_test(): """Run audio test.""" clear_screen() run_program(['hw-diags-audio'], check=False, pipe=False) pause('Press Enter to return to main menu... ') + def run_badblocks_test(state, test): """Run a read-only surface scan with badblocks.""" # Bail early @@ -939,6 +955,7 @@ def run_badblocks_test(state, test): # Cleanup tmux_kill_pane(state.panes['badblocks']) + def run_hw_tests(state): """Run enabled hardware tests.""" print_standard('Scanning devices...') @@ -1016,6 +1033,7 @@ def run_hw_tests(state): # Cleanup tmux_kill_pane(*state.panes.values()) + def run_io_benchmark(state, test): """Run a read-only I/O benchmark using dd.""" # Bail early @@ -1173,11 +1191,13 @@ def run_io_benchmark(state, test): # Cleanup tmux_kill_pane(state.panes['io_benchmark']) + def run_keyboard_test(): """Run keyboard test.""" clear_screen() run_program(['xev', '-event', 'keyboard'], check=False, pipe=False) + def run_mprime_test(state, test): """Test CPU with Prime95 and track temps.""" # Bail early @@ -1371,12 +1391,14 @@ def run_mprime_test(state, test): tmux_kill_pane(state.panes['mprime'], state.panes['Temps']) test.monitor_proc.kill() + def run_network_test(): """Run network test.""" clear_screen() run_program(['hw-diags-network'], check=False, pipe=False) pause('Press Enter to return to main menu... ') + def run_nvme_smart_tests(state, test): """Run NVMe or SMART test for test.dev.""" # Bail early @@ -1520,6 +1542,7 @@ def run_nvme_smart_tests(state, test): # Done update_progress_pane(state) + def secret_screensaver(screensaver=None): """Show screensaver.""" if screensaver == 'matrix': @@ -1530,6 +1553,7 @@ def secret_screensaver(screensaver=None): raise Exception('Invalid screensaver') run_program(cmd, check=False, pipe=False) + def show_report(report, log_report=False): """Show report on screen and optionally save to log w/out color.""" for line in report: @@ -1537,6 +1561,7 @@ def show_report(report, log_report=False): if log_report: print_log(strip_colors(line)) + def show_results(state): """Show results for all tests.""" clear_screen() @@ -1564,6 +1589,7 @@ def show_results(state): show_report(disk.generate_disk_report(), log_report=True) print_standard(' ') + def update_main_options(state, selection, main_options): """Update menu and state based on selection.""" index = int(selection) - 1 @@ -1607,6 +1633,7 @@ def update_main_options(state, selection, main_options): # Done return main_options + def update_io_progress(percent, rate, progress_file): """Update I/O progress file.""" bar_color = COLORS['CLEAR'] @@ -1631,6 +1658,7 @@ def update_io_progress(percent, rate, progress_file): with open(progress_file, 'a') as f: f.write(line) + def update_progress_pane(state): """Update progress file for side pane.""" output = [] @@ -1658,6 +1686,7 @@ def update_progress_pane(state): with open(state.progress_out, 'w') as f: f.writelines(output) + if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/functions/info.py b/.bin/Scripts/functions/info.py index 70d1062a..adee5f80 100644 --- a/.bin/Scripts/functions/info.py +++ b/.bin/Scripts/functions/info.py @@ -6,15 +6,6 @@ from operator import itemgetter from functions.common import * from functions.activation import * -# Regex -REGEX_OFFICE = re.compile( - r'(Microsoft (Office\s+' - r'(365|Enterprise|Home|Pro(\s|fessional)' - r'|Single|Small|Standard|Starter|Ultimate|system)' - r'|Works[-\s\d]+\d)' - r'|(Libre|Open|Star)\s*Office' - r'|WordPerfect|Gnumeric|Abiword)', - re.IGNORECASE) # STATIC VARIABLES REG_PROFILE_LIST = r'SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList' @@ -55,6 +46,18 @@ SHELL_FOLDERS = { ), } + +# Regex +REGEX_OFFICE = re.compile( + r'(Microsoft (Office\s+' + r'(365|Enterprise|Home|Pro(\s|fessional)' + r'|Single|Small|Standard|Starter|Ultimate|system)' + r'|Works[-\s\d]+\d)' + r'|(Libre|Open|Star)\s*Office' + r'|WordPerfect|Gnumeric|Abiword)', + re.IGNORECASE) + + def backup_file_list(): """Export current file listing for the system.""" extract_item('Everything', silent=True) @@ -66,6 +69,7 @@ def backup_file_list(): global_vars['Env']['SYSTEMDRIVE']] run_program(cmd) + def backup_power_plans(): """Export current power plans.""" os.makedirs(r'{BackupDir}\Power Plans\{Date}'.format( @@ -83,6 +87,7 @@ def backup_power_plans(): cmd = ['powercfg', '-export', out, guid] run_program(cmd, check=False) + def backup_registry(overwrite=False): """Backup registry including user hives.""" extract_item('erunt', silent=True) @@ -97,6 +102,7 @@ def backup_registry(overwrite=False): cmd.append('/noconfirmdelete') run_program(cmd) + def get_folder_size(path): """Get (human-readable) size of folder passed, returns str.""" size = 'Unknown' @@ -119,6 +125,7 @@ def get_folder_size(path): size = human_readable_size(size) return size + def get_installed_antivirus(): """Get list of installed Antivirus programs.""" programs = [] @@ -149,6 +156,7 @@ def get_installed_antivirus(): programs = ['No programs found'] return programs + def get_installed_office(): """Get list of installed Office programs.""" programs = [] @@ -163,6 +171,7 @@ def get_installed_office(): programs = ['No programs found'] return programs + def get_shell_path(folder, user='current'): """Get shell path using knownpaths, returns str. @@ -189,6 +198,7 @@ def get_shell_path(folder, user='current'): return path + def get_user_data_paths(user): """Get user data paths for provided user, returns dict.""" hive_path = user['SID'] @@ -273,6 +283,7 @@ def get_user_data_paths(user): # Done return paths + def get_user_folder_sizes(users): """Update list(users) to include folder paths and sizes.""" extract_item('du', filter='du*', silent=True) @@ -293,6 +304,7 @@ def get_user_folder_sizes(users): u['Extra Folders'][folder]['Size'] = get_folder_size( u['Extra Folders'][folder]['Path']) + def get_user_list(): """Get user list via WMIC, returns list of dicts.""" users = [] @@ -325,6 +337,7 @@ def get_user_list(): # Done return users + def reg_path_exists(hive, path): """Test if specified path exists, returns bool.""" try: @@ -334,6 +347,7 @@ def reg_path_exists(hive, path): else: return True + def run_aida64(): """Run AIDA64 to save system reports.""" extract_item('AIDA64', silent=True) @@ -372,6 +386,7 @@ def run_aida64(): '/TEXT', '/SILENT', '/SAFEST'] run_program(cmd, check=False) + def run_bleachbit(cleaners=None, preview=True): """Run BleachBit preview and save log. @@ -404,6 +419,7 @@ def run_bleachbit(cleaners=None, preview=True): for line in out.stdout.decode().splitlines(): f.write(line.strip() + '\n') + def show_disk_usage(disk): """Show free and used space for a specified disk.""" print_standard('{:5}'.format(disk.device.replace('/', ' ')), @@ -423,6 +439,7 @@ def show_disk_usage(disk): except Exception: print_warning('Unknown', timestamp=False) + def show_free_space(indent=8, width=32): """Show free space info for all fixed disks.""" message = 'Free Space:' @@ -436,6 +453,7 @@ def show_free_space(indent=8, width=32): except Exception: pass + def show_installed_ram(): """Show installed RAM.""" mem = psutil.virtual_memory() @@ -448,6 +466,7 @@ def show_installed_ram(): else: print_error(human_readable_size(mem.total).strip(), timestamp=False) + def show_os_activation(): """Show OS activation info.""" act_str = get_activation_string() @@ -458,6 +477,7 @@ def show_os_activation(): else: print_error(act_str, timestamp=False) + def show_os_name(): """Show extended OS name (including warnings).""" os_name = global_vars['OS']['DisplayName'] @@ -475,6 +495,7 @@ def show_os_name(): else: print_standard(os_name, timestamp=False) + def show_temp_files_size(): """Show total size of temp files identified by BleachBit.""" size = None @@ -488,6 +509,7 @@ def show_temp_files_size(): else: print_standard(size, timestamp=False) + def show_user_data_summary(indent=8, width=32): """Print user data folder sizes for all users.""" users = get_user_list() @@ -520,6 +542,7 @@ def show_user_data_summary(indent=8, width=32): size = folders[folder].get('Size', 'Unknown'), path = folders[folder].get('Path', 'Unknown'))) + if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/functions/network.py b/.bin/Scripts/functions/network.py index 80935506..9d9b7af1 100644 --- a/.bin/Scripts/functions/network.py +++ b/.bin/Scripts/functions/network.py @@ -11,6 +11,7 @@ os.chdir(os.path.dirname(os.path.realpath(__file__))) sys.path.append(os.getcwd()) from functions.common import * + # REGEX REGEX_VALID_IP = re.compile( r'(10.\d+.\d+.\d+' @@ -18,6 +19,7 @@ REGEX_VALID_IP = re.compile( r'|192.168.\d+.\d+)', re.IGNORECASE) + def connect_to_network(): """Connect to network if not already connected.""" net_ifs = psutil.net_if_addrs() @@ -38,6 +40,7 @@ def connect_to_network(): function = run_program, cmd = cmd) + def is_connected(): """Check for a valid private IP.""" devs = psutil.net_if_addrs() @@ -49,6 +52,7 @@ def is_connected(): # Else return False + def show_valid_addresses(): """Show all valid private IP addresses assigned to the system.""" devs = psutil.net_if_addrs() @@ -58,6 +62,7 @@ def show_valid_addresses(): # Valid IP found show_data(message=dev, data=family.address) + def speedtest(): """Run a network speedtest using speedtest-cli.""" result = run_program(['speedtest-cli', '--simple']) @@ -67,6 +72,7 @@ def speedtest(): output = [(a, float(b), c) for a, b, c in output] return ['{:10}{:6.2f} {}'.format(*line) for line in output] + if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/functions/product_keys.py b/.bin/Scripts/functions/product_keys.py index 1d96ec0b..950e509b 100644 --- a/.bin/Scripts/functions/product_keys.py +++ b/.bin/Scripts/functions/product_keys.py @@ -2,12 +2,14 @@ from functions.common import * + # Regex REGEX_REGISTRY_DIRS = re.compile( r'^(config$|RegBack$|System32$|Transfer|Win)', re.IGNORECASE) REGEX_SOFTWARE_HIVE = re.compile(r'^Software$', re.IGNORECASE) + def extract_keys(): """Extract keys from provided hives and return a dict.""" keys = {} @@ -43,6 +45,7 @@ def extract_keys(): # Done return keys + def list_clientdir_keys(): """List product keys found in hives inside the ClientDir.""" keys = extract_keys() @@ -57,6 +60,7 @@ def list_clientdir_keys(): return key_list + def find_software_hives(): """Search for transferred SW hives and return a list.""" hives = [] @@ -71,6 +75,7 @@ def find_software_hives(): return hives + def get_product_keys(): """List product keys from saved report.""" keys = [] @@ -86,6 +91,7 @@ def get_product_keys(): else: return ['No product keys found'] + def run_produkey(): """Run ProduKey and save report in the ClientDir.""" extract_item('ProduKey', silent=True) @@ -107,6 +113,7 @@ def run_produkey(): log_file] run_program(cmd, check=False) + if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/functions/repairs.py b/.bin/Scripts/functions/repairs.py index a964220c..f1e10a4a 100644 --- a/.bin/Scripts/functions/repairs.py +++ b/.bin/Scripts/functions/repairs.py @@ -2,6 +2,7 @@ from functions.common import * + def run_chkdsk(repair=False): """Run CHKDSK scan or schedule offline repairs.""" if repair: @@ -9,6 +10,7 @@ def run_chkdsk(repair=False): else: run_chkdsk_scan() + def run_chkdsk_scan(): """Run CHKDSK in a "split window" and report errors.""" if global_vars['OS']['Version'] in ('8', '8.1', '10'): @@ -32,6 +34,7 @@ def run_chkdsk_scan(): for line in out.stdout.decode().splitlines(): f.write(line.strip() + '\n') + def run_chkdsk_offline(): """Set filesystem 'dirty bit' to force a chkdsk during next boot.""" cmd = [ @@ -42,6 +45,7 @@ def run_chkdsk_offline(): if int(out.returncode) > 0: raise GenericError + def run_dism(repair=False): """Run DISM to either scan or repair component store health.""" if global_vars['OS']['Version'] in ('8', '8.1', '10'): @@ -75,6 +79,7 @@ def run_dism(repair=False): else: raise UnsupportedOSError + def run_kvrt(): """Run KVRT.""" extract_item('KVRT', silent=True) @@ -86,6 +91,7 @@ def run_kvrt(): '-processlevel', '3'] popen_program(cmd, pipe=False) + def run_sfc_scan(): """Run SFC in a "split window" and report errors.""" cmd = [ @@ -109,6 +115,7 @@ def run_sfc_scan(): else: raise GenericError + def run_tdsskiller(): """Run TDSSKiller.""" extract_item('TDSSKiller', silent=True) @@ -122,6 +129,7 @@ def run_tdsskiller(): '-dcexact', '-tdlfs'] run_program(cmd, pipe=False) + if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/functions/safemode.py b/.bin/Scripts/functions/safemode.py index 837b14e8..041cd506 100644 --- a/.bin/Scripts/functions/safemode.py +++ b/.bin/Scripts/functions/safemode.py @@ -2,19 +2,23 @@ from functions.common import * + # STATIC VARIABLES REG_MSISERVER = r'HKLM\SYSTEM\CurrentControlSet\Control\SafeBoot\Network\MSIServer' + def disable_safemode_msi(): """Disable MSI access under safemode.""" cmd = ['reg', 'delete', REG_MSISERVER, '/f'] run_program(cmd) + def disable_safemode(): """Edit BCD to remove safeboot value.""" cmd = ['bcdedit', '/deletevalue', '{default}', 'safeboot'] run_program(cmd) + def enable_safemode_msi(): """Enable MSI access under safemode.""" cmd = ['reg', 'add', REG_MSISERVER, '/f'] @@ -23,15 +27,18 @@ def enable_safemode_msi(): '/t', 'REG_SZ', '/d', 'Service', '/f'] run_program(cmd) + def enable_safemode(): """Edit BCD to set safeboot as default.""" cmd = ['bcdedit', '/set', '{default}', 'safeboot', 'network'] run_program(cmd) + def reboot(delay=3): cmd = ['shutdown', '-r', '-t', '{}'.format(delay)] run_program(cmd, check=False) + if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/functions/sensors.py b/.bin/Scripts/functions/sensors.py index 2fde69c4..a50f8941 100644 --- a/.bin/Scripts/functions/sensors.py +++ b/.bin/Scripts/functions/sensors.py @@ -5,6 +5,7 @@ import re from functions.tmux import * + # STATIC VARIABLES TEMP_LIMITS = { 'GREEN': 60, @@ -13,9 +14,11 @@ TEMP_LIMITS = { 'RED': 90, } + # REGEX REGEX_COLORS = re.compile(r'\033\[\d+;?1?m') + def clear_temps(sensor_data): """Clear saved temps but keep structure, returns dict.""" for _section, _adapters in sensor_data.items(): @@ -23,6 +26,7 @@ def clear_temps(sensor_data): for _source, _data in _sources.items(): _data['Temps'] = [] + def fix_sensor_str(s): """Cleanup string and return str.""" s = re.sub(r'^(\w+)-(\w+)-(\w+)', r'\1 (\2 \3)', s, re.IGNORECASE) @@ -36,6 +40,7 @@ def fix_sensor_str(s): s = s.replace(' ', ' ') return s + def generate_sensor_report( sensor_data, *temp_labels, colors=True, core_only=False): @@ -73,6 +78,7 @@ def generate_sensor_report( # Done return report + def get_colored_temp_str(temp): """Get colored string based on temp, returns str.""" try: @@ -97,6 +103,7 @@ def get_colored_temp_str(temp): temp = temp, **COLORS) + def get_raw_sensor_data(): """Read sensor data and return dict.""" data = {} @@ -110,6 +117,7 @@ def get_raw_sensor_data(): return data + def get_sensor_data(): """Parse raw sensor data and return new dict.""" json_data = get_raw_sensor_data() @@ -141,6 +149,7 @@ def get_sensor_data(): # Done return sensor_data + def get_temp_str(temp, colors=True): """Get temp string, returns str.""" if colors: @@ -154,6 +163,7 @@ def get_temp_str(temp, colors=True): '-' if temp < 0 else '', temp) + def monitor_sensors(monitor_pane, monitor_file): """Continually update sensor data and report to screen.""" sensor_data = get_sensor_data() @@ -166,6 +176,7 @@ def monitor_sensors(monitor_pane, monitor_file): if monitor_pane and not tmux_poll_pane(monitor_pane): break + def save_average_temp(sensor_data, temp_label, seconds=10): """Save average temps under temp_label, returns dict.""" clear_temps(sensor_data) @@ -181,6 +192,7 @@ def save_average_temp(sensor_data, temp_label, seconds=10): for _source, _data in _sources.items(): _data[temp_label] = sum(_data['Temps']) / len(_data['Temps']) + def update_sensor_data(sensor_data): """Read sensors and update existing sensor_data, returns dict.""" json_data = get_raw_sensor_data() @@ -193,12 +205,14 @@ def update_sensor_data(sensor_data): _data['Max'] = max(_temp, _data['Max']) _data['Temps'].append(_temp) + def join_columns(column1, column2, width=55): return '{:<{}}{}'.format( column1, 55+len(column1)-len(REGEX_COLORS.sub('', column1)), column2) + if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/functions/setup.py b/.bin/Scripts/functions/setup.py index 17cc37fa..749058e3 100644 --- a/.bin/Scripts/functions/setup.py +++ b/.bin/Scripts/functions/setup.py @@ -3,6 +3,7 @@ from functions.common import * from functions.update import * + # STATIC VARIABLES HKU = winreg.HKEY_USERS HKCR = winreg.HKEY_CLASSES_ROOT @@ -128,6 +129,7 @@ VCR_REDISTS = [ '/passive', '/norestart']}, ] + def config_classicstart(): """Configure ClassicStart.""" # User level, not system level @@ -180,14 +182,17 @@ def config_classicstart(): sleep(1) popen_program(cs_exe) + def config_explorer_system(): """Configure Windows Explorer for all users.""" write_registry_settings(SETTINGS_EXPLORER_SYSTEM, all_users=True) + def config_explorer_user(): """Configure Windows Explorer for current user.""" write_registry_settings(SETTINGS_EXPLORER_USER, all_users=False) + def disable_windows_telemetry(): """Disable Windows 10 telemetry settings with O&O ShutUp10.""" extract_item('ShutUp10', silent=True) @@ -197,6 +202,7 @@ def disable_windows_telemetry(): '/quiet'] run_program(cmd) + def update_clock(): """Set Timezone and sync clock.""" run_program(['tzutil' ,'/s', WINDOWS_TIME_ZONE], check=False) @@ -209,6 +215,7 @@ def update_clock(): run_program(['net', 'start', 'w32ime'], check=False) run_program(['w32tm', '/resync', '/nowait'], check=False) + def write_registry_settings(settings, all_users=False): """Write registry values from custom dict of dicts.""" hive = HKCU @@ -228,6 +235,7 @@ def write_registry_settings(settings, all_users=False): for name, value in v.get('SZ Items', {}).items(): winreg.SetValueEx(key, name, 0, winreg.REG_SZ, value) + # Installations def install_adobe_reader(): """Install Adobe Reader.""" @@ -240,10 +248,12 @@ def install_adobe_reader(): 'EULA_ACCEPT=YES'] run_program(cmd) + def install_chrome_extensions(): """Install Google Chrome extensions for all users.""" write_registry_settings(SETTINGS_GOOGLE_CHROME, all_users=True) + def install_classicstart_skin(): """Extract ClassicStart skin to installation folder.""" if global_vars['OS']['Version'] not in ('8', '8.1', '10'): @@ -257,6 +267,7 @@ def install_classicstart_skin(): os.makedirs(dest_path, exist_ok=True) shutil.copy(source, dest) + def install_firefox_extensions(): """Install Firefox extensions for all users.""" dist_path = r'{PROGRAMFILES}\Mozilla Firefox\distribution\extensions'.format( @@ -277,6 +288,7 @@ def install_firefox_extensions(): source_path] run_program(cmd) + def install_ninite_bundle(mse=False): """Run Ninite file(s) based on OS version.""" if global_vars['OS']['Version'] in ('8', '8.1', '10'): @@ -292,6 +304,7 @@ def install_ninite_bundle(mse=False): popen_program(r'{BaseDir}\Installers\Extras\Bundles\Legacy.exe'.format( **global_vars)) + def install_vcredists(): """Install all supported Visual C++ runtimes.""" extract_item('_vcredists', silent=True) @@ -307,16 +320,20 @@ def install_vcredists(): os.chdir(prev_dir) + # Misc def open_device_manager(): popen_program(['mmc', 'devmgmt.msc']) + def open_windows_activation(): popen_program(['slui']) + def open_windows_updates(): popen_program(['control', '/name', 'Microsoft.WindowsUpdate']) + if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/functions/sw_diags.py b/.bin/Scripts/functions/sw_diags.py index 317f2b4f..8faa25b7 100644 --- a/.bin/Scripts/functions/sw_diags.py +++ b/.bin/Scripts/functions/sw_diags.py @@ -4,6 +4,7 @@ import ctypes from functions.common import * + # STATIC VARIABLES AUTORUNS_SETTINGS = { r'Software\Sysinternals\AutoRuns': { @@ -26,6 +27,7 @@ AUTORUNS_SETTINGS = { }, } + def check_connection(): """Check if the system is online and optionally abort the script.""" while True: @@ -38,6 +40,7 @@ def check_connection(): else: abort() + def check_secure_boot_status(show_alert=False): """Checks UEFI Secure Boot status via PowerShell.""" boot_mode = get_boot_mode() @@ -77,6 +80,7 @@ def check_secure_boot_status(show_alert=False): show_alert_box('Secure Boot ERROR') raise GenericError + def get_boot_mode(): """Check if Windows is booted in UEFI or Legacy mode, returns str.""" kernel = ctypes.windll.kernel32 @@ -98,6 +102,7 @@ def get_boot_mode(): return type_str + def run_autoruns(): """Run AutoRuns in the background with VirusTotal checks enabled.""" extract_item('Autoruns', filter='autoruns*', silent=True) @@ -109,6 +114,7 @@ def run_autoruns(): winreg.SetValueEx(key, name, 0, winreg.REG_DWORD, value) popen_program(global_vars['Tools']['AutoRuns'], minimized=True) + def run_hwinfo_sensors(): """Run HWiNFO sensors.""" path = r'{BinDir}\HWiNFO'.format(**global_vars) @@ -122,12 +128,14 @@ def run_hwinfo_sensors(): f.write('SummaryOnly=0\n') popen_program(global_vars['Tools']['HWiNFO']) + def run_nircmd(*cmd): """Run custom NirCmd.""" extract_item('NirCmd', silent=True) cmd = [global_vars['Tools']['NirCmd'], *cmd] run_program(cmd, check=False) + def run_xmplay(): """Run XMPlay to test audio.""" extract_item('XMPlay', silent=True) @@ -141,6 +149,7 @@ def run_xmplay(): # Open XMPlay popen_program(cmd) + def run_hitmanpro(): """Run HitmanPro in the background.""" extract_item('HitmanPro', silent=True) @@ -150,6 +159,7 @@ def run_hitmanpro(): r'/log={LogDir}\Tools\HitmanPro.txt'.format(**global_vars)] popen_program(cmd) + def run_process_killer(): """Kill most running processes skipping those in the whitelist.txt.""" # borrowed from TronScript (reddit.com/r/TronScript) @@ -160,6 +170,7 @@ def run_process_killer(): run_program(['ProcessKiller.exe', '/silent'], check=False) os.chdir(prev_dir) + def run_rkill(): """Run RKill and cleanup afterwards.""" extract_item('RKill', silent=True) @@ -180,11 +191,13 @@ def run_rkill(): dest = non_clobber_rename(dest) shutil.move(item.path, dest) + def show_alert_box(message, title='Wizard Kit Warning'): """Show Windows alert box with message.""" message_box = ctypes.windll.user32.MessageBoxW message_box(None, message, title, 0x00001030) + if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/functions/tmux.py b/.bin/Scripts/functions/tmux.py index 84046d0b..a11560bc 100644 --- a/.bin/Scripts/functions/tmux.py +++ b/.bin/Scripts/functions/tmux.py @@ -2,12 +2,14 @@ from functions.common import * + def create_file(filepath): """Create file if it doesn't exist.""" if not os.path.exists(filepath): with open(filepath, 'w') as f: f.write('') + def tmux_get_pane_size(pane_id=None): """Get target, or current, pane size, returns tuple.""" x = -1 @@ -29,6 +31,7 @@ def tmux_get_pane_size(pane_id=None): return (x, y) + def tmux_kill_all_panes(pane_id=None): """Kill all tmux panes except the active pane or pane_id if specified.""" cmd = ['tmux', 'kill-pane', '-a'] @@ -36,12 +39,14 @@ def tmux_kill_all_panes(pane_id=None): cmd.extend(['-t', pane_id]) run_program(cmd, check=False) + def tmux_kill_pane(*panes): """Kill tmux pane by id.""" cmd = ['tmux', 'kill-pane', '-t'] for pane_id in panes: run_program(cmd+[pane_id], check=False) + def tmux_poll_pane(pane_id): """Check if pane exists, returns bool.""" cmd = ['tmux', 'list-panes', '-F', '#D'] @@ -49,6 +54,7 @@ def tmux_poll_pane(pane_id): panes = result.stdout.decode().splitlines() return pane_id in panes + def tmux_resize_pane(pane_id=None, x=None, y=None, **kwargs): """Resize pane to specific hieght or width.""" if not x and not y: @@ -65,6 +71,7 @@ def tmux_resize_pane(pane_id=None, x=None, y=None, **kwargs): run_program(cmd, check=False) + def tmux_split_window( lines=None, percent=None, behind=False, vertical=False, @@ -115,6 +122,7 @@ def tmux_split_window( result = run_program(cmd) return result.stdout.decode().strip() + def tmux_update_pane( pane_id, command=None, working_dir=None, text=None, watch=None, watch_cmd='cat'): @@ -142,6 +150,7 @@ def tmux_update_pane( run_program(cmd) + if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/functions/update.py b/.bin/Scripts/functions/update.py index 21d2acee..439bb6bf 100644 --- a/.bin/Scripts/functions/update.py +++ b/.bin/Scripts/functions/update.py @@ -8,6 +8,7 @@ from settings.launchers import * from settings.music import * from settings.sources import * + def compress_and_remove_item(item): """Compress and delete an item unless an error is encountered.""" try: @@ -17,6 +18,7 @@ def compress_and_remove_item(item): else: remove_item(item.path) + def compress_item(item): """Compress an item in a 7-Zip archive using the ARCHIVE_PASSWORD.""" # Prep @@ -42,6 +44,7 @@ def compress_item(item): # Done os.chdir(prev_dir) + def download_generic(out_dir, out_name, source_url): """Downloads a file using requests.""" ## Code based on this Q&A: https://stackoverflow.com/q/16694907 @@ -59,10 +62,12 @@ def download_generic(out_dir, out_name, source_url): except: raise GenericError('Failed to download file.') + def download_to_temp(out_name, source_url): """Download a file to the TmpDir.""" download_generic(global_vars['TmpDir'], out_name, source_url) + def extract_generic(source, dest, mode='x', sz_args=[]): """Extract a file to a destination.""" cmd = [ @@ -73,12 +78,14 @@ def extract_generic(source, dest, mode='x', sz_args=[]): cmd.extend(sz_args) run_program(cmd) + def extract_temp_to_bin(source, item, mode='x', sz_args=[]): """Extract a file to the .bin folder.""" source = r'{}\{}'.format(global_vars['TmpDir'], source) dest = r'{}\{}'.format(global_vars['BinDir'], item) extract_generic(source, dest, mode, sz_args) + def extract_temp_to_cbin(source, item, mode='x', sz_args=[]): """Extract a file to the .cbin folder.""" source = r'{}\{}'.format(global_vars['TmpDir'], source) @@ -88,6 +95,7 @@ def extract_temp_to_cbin(source, item, mode='x', sz_args=[]): shutil.copytree(include_path, dest) extract_generic(source, dest, mode, sz_args) + def generate_launcher(section, name, options): """Generate a launcher script.""" # Prep @@ -125,6 +133,7 @@ def generate_launcher(section, name, options): # f.writelines(out_text) f.write('\n'.join(out_text)) + def remove_item(item_path): """Delete a file or folder.""" if os.path.exists(item_path): @@ -133,6 +142,7 @@ def remove_item(item_path): else: os.remove(item_path) + def remove_from_kit(item): """Delete a file or folder from the .bin/.cbin folders.""" item_locations = [] @@ -144,11 +154,13 @@ def remove_from_kit(item): for item_path in item_locations: remove_item(item_path) + def remove_from_temp(item): """Delete a file or folder from the TmpDir folder.""" item_path = r'{}\{}'.format(global_vars['TmpDir'], item) remove_item(item_path) + def resolve_dynamic_url(source_url, regex): """Scan source_url for a url using the regex provided; returns str.""" # Load the download page @@ -170,6 +182,7 @@ def resolve_dynamic_url(source_url, regex): # Return return url + def scan_for_net_installers(server, family_name, min_year): """Scan network shares for installers.""" if not server['Mounted']: @@ -200,7 +213,8 @@ def scan_for_net_installers(server, family_name, min_year): } umount_network_share(server) -## Data Recovery ## + +# Data Recovery def update_testdisk(): # Stop running processes for exe in ['fidentify_win.exe', 'photorec_win.exe', @@ -226,7 +240,8 @@ def update_testdisk(): # Cleanup remove_from_temp('testdisk_wip.zip') -## Data Transfers ## + +# Data Transfers def update_fastcopy(): ## NOTE: Lives in .bin uncompressed # Stop running processes @@ -266,6 +281,7 @@ def update_fastcopy(): os.remove(r'{}\setup.exe'.format(_path, _installer)) remove_from_temp('FastCopy.zip') + def update_wimlib(): # Stop running processes kill_process('wimlib-imagex.exe') @@ -289,6 +305,7 @@ def update_wimlib(): remove_from_temp('wimlib32.zip') remove_from_temp('wimlib64.zip') + def update_xyplorer(): # Stop running processes kill_process('XYplorerFree.exe') @@ -305,7 +322,8 @@ def update_xyplorer(): # Cleanup remove_from_temp('xyplorer_free.zip') -## Diagnostics ## + +# Diagnostics def update_aida64(): # Stop running processes kill_process('notepadplusplus.exe') @@ -322,6 +340,7 @@ def update_aida64(): # Cleanup remove_from_temp('aida64.zip') + def update_autoruns(): # Stop running processes kill_process('Autoruns.exe') @@ -339,6 +358,7 @@ def update_autoruns(): # Cleanup remove_from_temp('Autoruns.zip') + def update_bleachbit(): # Stop running processes kill_process('bleachbit.exe') @@ -370,6 +390,7 @@ def update_bleachbit(): remove_from_temp('bleachbit.zip') remove_from_temp('Winapp2.zip') + def update_bluescreenview(): # Stop running processes for exe in ['BlueScreenView.exe', 'BlueScreenView64.exe']: @@ -394,6 +415,7 @@ def update_bluescreenview(): remove_from_temp('bluescreenview32.zip') remove_from_temp('bluescreenview64.zip') + def update_erunt(): # Stop running processes kill_process('ERUNT.EXE') @@ -410,6 +432,7 @@ def update_erunt(): # Cleanup remove_from_temp('erunt.zip') + def update_hitmanpro(): # Stop running processes for exe in ['HitmanPro.exe', 'HitmanPro64.exe']: @@ -423,6 +446,7 @@ def update_hitmanpro(): download_generic(dest, 'HitmanPro.exe', SOURCE_URLS['HitmanPro32']) download_generic(dest, 'HitmanPro64.exe', SOURCE_URLS['HitmanPro64']) + def update_hwinfo(): ## NOTE: Lives in .bin uncompressed # Stop running processes @@ -438,6 +462,7 @@ def update_hwinfo(): # Cleanup remove_from_temp('HWiNFO.zip') + def update_nircmd(): # Stop running processes for exe in ['nircmdc.exe', 'nircmdc64.exe']: @@ -461,6 +486,7 @@ def update_nircmd(): remove_from_temp('nircmd32.zip') remove_from_temp('nircmd64.zip') + def update_produkey(): # Stop running processes for exe in ['ProduKey.exe', 'ProduKey64.exe']: @@ -484,7 +510,8 @@ def update_produkey(): remove_from_temp('produkey32.zip') remove_from_temp('produkey64.zip') -## Drivers ## + +# Drivers def update_intel_rst(): # Remove existing folders remove_from_kit('Intel RST') @@ -500,6 +527,7 @@ def update_intel_rst(): for name, url in RST_SOURCES.items(): download_generic(dest, name, url) + def update_intel_ssd_toolbox(): # Remove existing folders remove_from_kit('Intel SSD Toolbox.exe') @@ -510,6 +538,7 @@ def update_intel_ssd_toolbox(): 'Intel SSD Toolbox.exe', SOURCE_URLS['Intel SSD Toolbox']) + def update_samsung_magician(): # Remove existing folders remove_from_kit('Samsung Magician.exe') @@ -528,6 +557,7 @@ def update_samsung_magician(): # Cleanup remove_from_temp('Samsung Magician.zip') + def update_sdi_origin(): # Download aria2 download_to_temp('aria2.zip', SOURCE_URLS['aria2']) @@ -585,7 +615,8 @@ def update_sdi_origin(): remove_from_temp('sdio.torrent') remove_from_temp('sdio_themes.zip') -## Installers ## + +# Installers def update_adobe_reader_dc(): # Prep dest = r'{}\Installers\Extras\Office'.format( @@ -601,6 +632,7 @@ def update_adobe_reader_dc(): download_generic( dest, 'Adobe Reader DC.exe', SOURCE_URLS['Adobe Reader DC']) + def update_macs_fan_control(): # Prep dest = r'{}\Installers'.format( @@ -616,6 +648,7 @@ def update_macs_fan_control(): download_generic( dest, 'Macs Fan Control.exe', SOURCE_URLS['Macs Fan Control']) + def update_office(): # Remove existing folders remove_from_kit('_Office') @@ -644,6 +677,7 @@ def update_office(): # Cleanup remove_from_temp('odt{}.exe'.format(year)) + def update_classic_start_skin(): # Remove existing folders remove_from_kit('ClassicStartSkin') @@ -654,6 +688,7 @@ def update_classic_start_skin(): 'Metro-Win10-Black.skin7', SOURCE_URLS['ClassicStartSkin']) + def update_vcredists(): # Remove existing folders remove_from_kit('_vcredists') @@ -674,6 +709,7 @@ def update_vcredists(): 'vcredist.exe', VCREDIST_SOURCES[year][bit]) + def update_one_ninite(section, dest, name, url, indent=8, width=40): # Prep url = 'https://ninite.com/{}/ninite.exe'.format(url) @@ -690,6 +726,7 @@ def update_one_ninite(section, dest, name, url, indent=8, width=40): remove_item(installer_dest) shutil.copy(r'{}\{}'.format(dest, name), installer_dest) + def update_all_ninite(indent=8, width=40, other_results={}): print_info('{}Ninite'.format(' '*int(indent/2))) for section in sorted(NINITE_SOURCES.keys()): @@ -700,7 +737,8 @@ def update_all_ninite(indent=8, width=40, other_results={}): other_results=other_results, indent=indent, width=width, section=section, dest=dest, name=name, url=url) -## Misc ## + +# Misc def update_caffeine(): # Stop running processes kill_process('caffeine.exe') @@ -717,6 +755,7 @@ def update_caffeine(): # Cleanup remove_from_temp('caffeine.zip') + def update_du(): # Stop running processes kill_process('du.exe') @@ -734,6 +773,7 @@ def update_du(): # Cleanup remove_from_temp('du.zip') + def update_everything(): # Stop running processes for exe in ['Everything.exe', 'Everything64.exe']: @@ -758,6 +798,7 @@ def update_everything(): remove_from_temp('everything32.zip') remove_from_temp('everything64.zip') + def update_firefox_ublock_origin(): # Remove existing folders remove_from_kit('FirefoxExtensions') @@ -768,6 +809,7 @@ def update_firefox_ublock_origin(): 'ublock_origin.xpi', SOURCE_URLS['Firefox uBO']) + def update_notepadplusplus(): # Stop running processes kill_process('notepadplusplus.exe') @@ -788,6 +830,7 @@ def update_notepadplusplus(): # Cleanup remove_from_temp('npp.7z') + def update_putty(): # Stop running processes kill_process('PUTTY.EXE') @@ -804,6 +847,7 @@ def update_putty(): # Cleanup remove_from_temp('putty.zip') + def update_wiztree(): # Stop running processes for process in ['WizTree.exe', 'WizTree64.exe']: @@ -822,6 +866,7 @@ def update_wiztree(): # Cleanup remove_from_temp('wiztree.zip') + def update_xmplay(): # Stop running processes kill_process('xmplay.exe') @@ -877,7 +922,8 @@ def update_xmplay(): remove_from_temp('xmp-rar.zip') remove_from_temp('WAModern.zip') -## Repairs ## + +# Repairs def update_adwcleaner(): # Stop running processes kill_process('AdwCleaner.exe') @@ -891,6 +937,7 @@ def update_adwcleaner(): 'AdwCleaner.exe', SOURCE_URLS['AdwCleaner']) + def update_kvrt(): # Stop running processes kill_process('KVRT.exe') @@ -904,6 +951,7 @@ def update_kvrt(): 'KVRT.exe', SOURCE_URLS['KVRT']) + def update_rkill(): # Stop running processes kill_process('RKill.exe') @@ -918,6 +966,7 @@ def update_rkill(): download_generic( r'{}\RKill'.format(global_vars['CBinDir']), 'RKill.exe', url) + def update_tdsskiller(): # Stop running processes kill_process('TDSSKiller.exe') @@ -931,7 +980,8 @@ def update_tdsskiller(): 'TDSSKiller.exe', SOURCE_URLS['TDSSKiller']) -## Uninstallers ## + +# Uninstallers def update_iobit_uninstaller(): # Stop running processes kill_process('IObitUninstallerPortable.exe') @@ -954,6 +1004,7 @@ def update_iobit_uninstaller(): # Cleanup remove_from_kit('IObitUninstallerPortable.exe') + if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/functions/windows_setup.py b/.bin/Scripts/functions/windows_setup.py index d23dce4c..82120843 100644 --- a/.bin/Scripts/functions/windows_setup.py +++ b/.bin/Scripts/functions/windows_setup.py @@ -3,6 +3,7 @@ from functions.data import * from functions.disk import * + # STATIC VARIABLES WINDOWS_VERSIONS = [ {'Name': 'Windows 7 Home Basic', @@ -35,6 +36,7 @@ WINDOWS_VERSIONS = [ 'Image Name': 'Windows 10 Pro'}, ] + def find_windows_image(windows_version): """Search for a Windows source image file, returns dict. @@ -85,6 +87,7 @@ def find_windows_image(windows_version): windows_version['Name'])) raise GenericAbort + def format_disk(disk, use_gpt): """Format disk for use as a Windows OS disk.""" if use_gpt: @@ -92,6 +95,7 @@ def format_disk(disk, use_gpt): else: format_mbr(disk) + def format_gpt(disk): """Format disk for use as a Windows OS disk using the GPT layout.""" script = [ @@ -126,6 +130,7 @@ def format_gpt(disk): # Run run_diskpart(script) + def format_mbr(disk): """Format disk for use as a Windows OS disk using the MBR layout.""" script = [ @@ -155,6 +160,7 @@ def format_mbr(disk): # Run run_diskpart(script) + def mount_windows_share(): """Mount the Windows images share unless already mounted.""" if not WINDOWS_SERVER['Mounted']: @@ -163,6 +169,7 @@ def mount_windows_share(): # error by trying to mount the same server with multiple credentials. mount_network_share(WINDOWS_SERVER, read_write=True) + def select_windows_version(): """Select Windows version from a menu, returns dict.""" actions = [ @@ -180,6 +187,7 @@ def select_windows_version(): elif selection == 'M': raise GenericAbort + def setup_windows(windows_image, windows_version): """Apply a Windows image to W:""" cmd = [ @@ -192,6 +200,7 @@ def setup_windows(windows_image, windows_version): cmd.extend(windows_image['Glob']) run_program(cmd) + def setup_windows_re(windows_version, windows_letter='W', tools_letter='T'): """Setup the WinRE partition.""" win = r'{}:\Windows'.format(windows_letter) @@ -210,6 +219,7 @@ def setup_windows_re(windows_version, windows_letter='W', tools_letter='T'): '/target', win] run_program(cmd) + def update_boot_partition(system_letter='S', windows_letter='W', mode='ALL'): """Setup the Windows boot partition.""" cmd = [ @@ -220,6 +230,7 @@ def update_boot_partition(system_letter='S', windows_letter='W', mode='ALL'): '/f', mode] run_program(cmd) + def wim_contains_image(filename, imagename): """Check if an ESD/WIM contains the specified image, returns bool.""" cmd = [ @@ -234,6 +245,7 @@ def wim_contains_image(filename, imagename): return True + if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/functions/winpe_menus.py b/.bin/Scripts/functions/winpe_menus.py index f42a6144..22df7449 100644 --- a/.bin/Scripts/functions/winpe_menus.py +++ b/.bin/Scripts/functions/winpe_menus.py @@ -4,6 +4,7 @@ from functions.backup import * from functions.disk import * from functions.windows_setup import * + # STATIC VARIABLES FAST_COPY_PE_ARGS = [ '/cmd=noexist_only', @@ -50,6 +51,7 @@ PE_TOOLS = { }, } + def check_pe_tools(): """Fix tool paths for WinPE layout.""" for k in PE_TOOLS.keys(): @@ -61,6 +63,7 @@ def check_pe_tools(): global_vars['Tools']['wimlib-imagex'], re.IGNORECASE) + def menu_backup(): """Take backup images of partition(s) in the WIM format.""" errors = False @@ -211,6 +214,7 @@ def menu_backup(): sleep(30) pause('\nPress Enter to return to main menu... ') + def menu_root(): """Main WinPE menu.""" check_pe_tools() @@ -249,6 +253,7 @@ def menu_root(): else: sys.exit() + def menu_setup(): """Format a disk, apply a Windows image, and create boot files.""" errors = False @@ -409,6 +414,7 @@ def menu_setup(): sleep(30) pause('\nPress Enter to return to main menu... ') + def menu_tools(): """Tool launcher menu.""" tools = [{'Name': k} for k in sorted(PE_TOOLS.keys())] @@ -438,6 +444,7 @@ def menu_tools(): elif (selection == 'M'): break + def select_minidump_path(): """Select BSOD minidump path from a menu.""" dumps = [] @@ -467,6 +474,7 @@ def select_minidump_path(): main_entries = dumps) return dumps[int(selection) - 1]['Name'] + if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/hw-diags-network b/.bin/Scripts/hw-diags-network index 7e0b0bed..3caa7adb 100755 --- a/.bin/Scripts/hw-diags-network +++ b/.bin/Scripts/hw-diags-network @@ -10,11 +10,13 @@ os.chdir(os.path.dirname(os.path.realpath(__file__))) sys.path.append(os.getcwd()) from functions.network import * + def check_connection(): if not is_connected(): # Raise to cause NS in try_and_print() raise Exception + if __name__ == '__main__': try: # Prep diff --git a/.bin/Scripts/msword-search b/.bin/Scripts/msword-search index 380c6ed5..19bbe688 100755 --- a/.bin/Scripts/msword-search +++ b/.bin/Scripts/msword-search @@ -22,6 +22,7 @@ init_global_vars() REGEX_DOC_FILES = re.compile(r'\.docx?$', re.IGNORECASE) + def scan_for_docs(path): for entry in os.scandir(path): if entry.is_dir(follow_symlinks=False): @@ -29,6 +30,7 @@ def scan_for_docs(path): elif entry.is_file and REGEX_DOC_FILES.search(entry.name): yield entry + def scan_file(file_path, search): match = False try: @@ -45,6 +47,7 @@ def scan_file(file_path, search): return entry.path if match else None + if __name__ == '__main__': try: # Prep From c96e2f252c80166acc2863a8df0e3e9ef6316858 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 21:38:25 -0700 Subject: [PATCH 185/265] Cleaned up imports --- .bin/Scripts/functions/browsers.py | 1 - .bin/Scripts/functions/common.py | 3 +-- .bin/Scripts/functions/data.py | 3 +-- .bin/Scripts/functions/ddrescue.py | 1 - .bin/Scripts/functions/info.py | 4 +--- .bin/Scripts/functions/network.py | 3 --- .bin/Scripts/functions/setup.py | 1 - .bin/Scripts/functions/update.py | 1 - 8 files changed, 3 insertions(+), 14 deletions(-) diff --git a/.bin/Scripts/functions/browsers.py b/.bin/Scripts/functions/browsers.py index e73399bc..34c0252f 100644 --- a/.bin/Scripts/functions/browsers.py +++ b/.bin/Scripts/functions/browsers.py @@ -1,7 +1,6 @@ # Wizard Kit: Functions - Browsers from functions.common import * - from operator import itemgetter diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index a0a87b76..368ce687 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -14,11 +14,10 @@ except ModuleNotFoundError: if psutil.WINDOWS: raise -from subprocess import CalledProcessError - from settings.main import * from settings.tools import * from settings.windows_builds import * +from subprocess import CalledProcessError # Global variables diff --git a/.bin/Scripts/functions/data.py b/.bin/Scripts/functions/data.py index a151b24c..7dcee3cf 100644 --- a/.bin/Scripts/functions/data.py +++ b/.bin/Scripts/functions/data.py @@ -3,9 +3,8 @@ import ctypes import json -from operator import itemgetter - from functions.common import * +from operator import itemgetter # STATIC VARIABLES diff --git a/.bin/Scripts/functions/ddrescue.py b/.bin/Scripts/functions/ddrescue.py index e6def7f2..a2b27e5e 100644 --- a/.bin/Scripts/functions/ddrescue.py +++ b/.bin/Scripts/functions/ddrescue.py @@ -9,7 +9,6 @@ import stat import time from collections import OrderedDict -from functions.common import * from functions.data import * from functions.hw_diags import * from functions.tmux import * diff --git a/.bin/Scripts/functions/info.py b/.bin/Scripts/functions/info.py index adee5f80..ad71bce7 100644 --- a/.bin/Scripts/functions/info.py +++ b/.bin/Scripts/functions/info.py @@ -1,10 +1,8 @@ # Wizard Kit: Functions - Information from borrowed import knownpaths -from operator import itemgetter - -from functions.common import * from functions.activation import * +from operator import itemgetter # STATIC VARIABLES diff --git a/.bin/Scripts/functions/network.py b/.bin/Scripts/functions/network.py index 9d9b7af1..f210a2b0 100644 --- a/.bin/Scripts/functions/network.py +++ b/.bin/Scripts/functions/network.py @@ -6,9 +6,6 @@ import os import shutil import sys -# Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) from functions.common import * diff --git a/.bin/Scripts/functions/setup.py b/.bin/Scripts/functions/setup.py index 749058e3..85943d2e 100644 --- a/.bin/Scripts/functions/setup.py +++ b/.bin/Scripts/functions/setup.py @@ -1,6 +1,5 @@ # Wizard Kit: Functions - Setup -from functions.common import * from functions.update import * diff --git a/.bin/Scripts/functions/update.py b/.bin/Scripts/functions/update.py index 439bb6bf..b4aa3f7e 100644 --- a/.bin/Scripts/functions/update.py +++ b/.bin/Scripts/functions/update.py @@ -2,7 +2,6 @@ import requests -from functions.common import * from functions.data import * from settings.launchers import * from settings.music import * From 5af0996259e4bd6353c78926843c83bf5f1c3359 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 21:42:00 -0700 Subject: [PATCH 186/265] Removed whitespace on empty lines --- .bin/Scripts/connect-to-network | 2 +- .bin/Scripts/ddrescue-tui-menu | 2 +- .bin/Scripts/hw-diags-audio | 4 ++-- .bin/Scripts/hw-diags-network | 2 +- .bin/Scripts/mount-backup-shares | 2 +- .bin/Scripts/msword-search | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.bin/Scripts/connect-to-network b/.bin/Scripts/connect-to-network index e5100303..5e04e903 100755 --- a/.bin/Scripts/connect-to-network +++ b/.bin/Scripts/connect-to-network @@ -18,7 +18,7 @@ if __name__ == '__main__': # Connect connect_to_network() - + # Done print_standard('\nDone.') #pause("Press Enter to exit...") diff --git a/.bin/Scripts/ddrescue-tui-menu b/.bin/Scripts/ddrescue-tui-menu index 66ed058a..f1f3b08c 100755 --- a/.bin/Scripts/ddrescue-tui-menu +++ b/.bin/Scripts/ddrescue-tui-menu @@ -42,7 +42,7 @@ if __name__ == '__main__': else: if not re.search(r'^-*(h|help\?)', run_mode, re.IGNORECASE): print_error('Invalid mode.') - + # Done print_standard('\nDone.') pause("Press Enter to exit...") diff --git a/.bin/Scripts/hw-diags-audio b/.bin/Scripts/hw-diags-audio index d1b09694..2c52c467 100755 --- a/.bin/Scripts/hw-diags-audio +++ b/.bin/Scripts/hw-diags-audio @@ -23,14 +23,14 @@ if __name__ == '__main__': run_program('amixer -q set "PCM" 90% unmute'.split()) except subprocess.CalledProcessError: print_error('Failed to set volume') - + # Run tests for mode in ['pink', 'wav']: run_program( cmd = 'speaker-test -c 2 -l 1 -t {}'.format(mode).split(), check = False, pipe = False) - + # Done #print_standard('\nDone.') #pause("Press Enter to exit...") diff --git a/.bin/Scripts/hw-diags-network b/.bin/Scripts/hw-diags-network index 3caa7adb..2ae0e263 100755 --- a/.bin/Scripts/hw-diags-network +++ b/.bin/Scripts/hw-diags-network @@ -36,7 +36,7 @@ if __name__ == '__main__': try_and_print(message='DNS Resolution:', function=ping, cs='OK') try_and_print(message='Speedtest:', function=speedtest, print_return=True) - + # Done print_standard('\nDone.') #pause("Press Enter to exit...") diff --git a/.bin/Scripts/mount-backup-shares b/.bin/Scripts/mount-backup-shares index 6605a81c..69374a9b 100755 --- a/.bin/Scripts/mount-backup-shares +++ b/.bin/Scripts/mount-backup-shares @@ -26,7 +26,7 @@ if __name__ == '__main__': else: # Couldn't connect print_error('ERROR: No network connectivity.') - + # Done print_standard('\nDone.') #pause("Press Enter to exit...") diff --git a/.bin/Scripts/msword-search b/.bin/Scripts/msword-search index 19bbe688..c0461dda 100755 --- a/.bin/Scripts/msword-search +++ b/.bin/Scripts/msword-search @@ -44,7 +44,7 @@ def scan_file(file_path, search): except Exception: # Ignore errors since files may be corrupted pass - + return entry.path if match else None @@ -72,7 +72,7 @@ if __name__ == '__main__': print_standard(match) else: print_error('No matches found.') - + # Done print_standard('\nDone.') #pause("Press Enter to exit...") From 922d632afb49a7090686e5eac92c2bb6e9e71a2b Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 21:44:46 -0700 Subject: [PATCH 187/265] Removed trailing whitespace --- .bin/Scripts/functions/update.py | 2 +- .bin/Scripts/functions/windows_setup.py | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.bin/Scripts/functions/update.py b/.bin/Scripts/functions/update.py index b4aa3f7e..a9c7811f 100644 --- a/.bin/Scripts/functions/update.py +++ b/.bin/Scripts/functions/update.py @@ -883,7 +883,7 @@ def update_xmplay(): # Extract files extract_temp_to_cbin('xmplay.zip', 'XMPlay', mode='e', sz_args=['xmplay.exe', 'xmplay.txt']) - for item in ['xmp-7z', 'xmp-gme', 'xmp-rar', 'WAModern']: + for item in ['xmp-7z', 'xmp-gme', 'xmp-rar', 'WAModern']: filter = [] if item == 'WAModern': filter.append('WAModern NightVision.xmpskin') diff --git a/.bin/Scripts/functions/windows_setup.py b/.bin/Scripts/functions/windows_setup.py index 82120843..e790a4b6 100644 --- a/.bin/Scripts/functions/windows_setup.py +++ b/.bin/Scripts/functions/windows_setup.py @@ -12,27 +12,27 @@ WINDOWS_VERSIONS = [ {'Name': 'Windows 7 Home Premium', 'Image File': 'Win7', 'Image Name': 'Windows 7 HOMEPREMIUM'}, - {'Name': 'Windows 7 Professional', - 'Image File': 'Win7', + {'Name': 'Windows 7 Professional', + 'Image File': 'Win7', 'Image Name': 'Windows 7 PROFESSIONAL'}, - {'Name': 'Windows 7 Ultimate', - 'Image File': 'Win7', + {'Name': 'Windows 7 Ultimate', + 'Image File': 'Win7', 'Image Name': 'Windows 7 ULTIMATE'}, - {'Name': 'Windows 8.1', - 'Image File': 'Win8', + {'Name': 'Windows 8.1', + 'Image File': 'Win8', 'Image Name': 'Windows 8.1', 'CRLF': True}, - {'Name': 'Windows 8.1 Pro', - 'Image File': 'Win8', + {'Name': 'Windows 8.1 Pro', + 'Image File': 'Win8', 'Image Name': 'Windows 8.1 Pro'}, - {'Name': 'Windows 10 Home', - 'Image File': 'Win10', + {'Name': 'Windows 10 Home', + 'Image File': 'Win10', 'Image Name': 'Windows 10 Home', 'CRLF': True}, - {'Name': 'Windows 10 Pro', - 'Image File': 'Win10', + {'Name': 'Windows 10 Pro', + 'Image File': 'Win10', 'Image Name': 'Windows 10 Pro'}, ] From e2fcacf579854c3c1419ea9c1ddaf09f9ac63041 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 22:11:09 -0700 Subject: [PATCH 188/265] Added extra line breaks to match upstream code --- .bin/Scripts/functions/io_graph.py | 4 ++++ .bin/Scripts/functions/osticket.py | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/.bin/Scripts/functions/io_graph.py b/.bin/Scripts/functions/io_graph.py index fb909c9f..7a96d8aa 100644 --- a/.bin/Scripts/functions/io_graph.py +++ b/.bin/Scripts/functions/io_graph.py @@ -8,6 +8,7 @@ import requests from functions.common import * + # Functions def export_io_graph(disk): """Exports PNG graph using gnuplot, returns file path as str.""" @@ -49,6 +50,7 @@ def export_io_graph(disk): return out_path + def upload_to_imgur(image_path): """Upload image to Imgur and return image url as str.""" image_data = None @@ -80,6 +82,7 @@ def upload_to_imgur(image_path): image_link = json_data['data']['link'] return image_link + def upload_to_nextcloud(image_path, ticket_number, dev_name): """Upload image to Nextcloud server and return folder url as str.""" image_data = None @@ -107,6 +110,7 @@ def upload_to_nextcloud(image_path, ticket_number, dev_name): # Return folder link return BENCHMARK_SERVER['Short Url'] + if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/functions/osticket.py b/.bin/Scripts/functions/osticket.py index 13490e92..bbf78353 100644 --- a/.bin/Scripts/functions/osticket.py +++ b/.bin/Scripts/functions/osticket.py @@ -6,15 +6,18 @@ from functions.data import * from functions.io_graph import * from settings.osticket import * + # STATIC VARIABLES KNOWN_DEV_TYPES = ('CPU', 'Disk') + # Regex REGEX_BLOCK_GRAPH = re.compile(r'(▁|▂|▃|▄|▅|▆|▇|█)') REGEX_NVME_SMART_ATTRIBUTES = re.compile(r'^\s*(\d+) / (\w+): (.{28})(.*)$') REGEX_TEMPS = re.compile(r'^\s*(.*?)\s+(idle.*)$') REGEX_SENSOR = re.compile(r'^(.*?)(\s*)$') + # Classes class osTicket(): """Class to track osTicket data and functions.""" @@ -469,6 +472,7 @@ class osTicket(): # Done self.disconnect() + # Functions def pad_with_dots(s, pad_right=False): """Replace space padding with dots, returns str.""" @@ -480,6 +484,7 @@ def pad_with_dots(s, pad_right=False): s = '.' + s return s + if __name__ == '__main__': print("This file is not meant to be called directly.") From 3e733e65e94545bab96222b21fecd186906299f3 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 22:17:23 -0700 Subject: [PATCH 189/265] Updated network.py --- .bin/Scripts/functions/network.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.bin/Scripts/functions/network.py b/.bin/Scripts/functions/network.py index f210a2b0..492ba16f 100644 --- a/.bin/Scripts/functions/network.py +++ b/.bin/Scripts/functions/network.py @@ -1,6 +1,4 @@ -#!/bin/python3 -# -## Wizard Kit: Functions - Network +# Wizard Kit: Functions - Network import os import shutil From 279ebcf9881bfa1ec59e5b6014cb98479dcf8e10 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 22:26:34 -0700 Subject: [PATCH 190/265] Updated some files to prep for upcoming PEP8 merge --- .bin/Scripts/install_eset_nod32_av.py | 26 +-- .bin/Scripts/install_sw_bundle.py | 94 +++++----- .bin/Scripts/install_vcredists.py | 38 ++-- .bin/Scripts/system_checklist.py | 240 +++++++++++++------------- .bin/Scripts/system_checklist_hw.py | 194 ++++++++++----------- .bin/Scripts/user_checklist.py | 142 +++++++-------- 6 files changed, 370 insertions(+), 364 deletions(-) diff --git a/.bin/Scripts/install_eset_nod32_av.py b/.bin/Scripts/install_eset_nod32_av.py index b53adfb6..ecdd9da6 100644 --- a/.bin/Scripts/install_eset_nod32_av.py +++ b/.bin/Scripts/install_eset_nod32_av.py @@ -12,15 +12,17 @@ os.system('title {}: Install ESET NOD32 AV'.format(KIT_NAME_FULL)) set_log_file('Install ESET NOD32 AV.log') if __name__ == '__main__': - try: - stay_awake() - clear_screen() - print_info('{}: Install ESET NOD32 AV\n'.format(KIT_NAME_FULL)) - scan_pups = ask('Enable PUP scans in ESET?') - install_eset_nod32_av(scan_pups) - print_standard('\nDone.') - exit_script() - except SystemExit: - pass - except: - major_exception() + try: + stay_awake() + clear_screen() + print_info('{}: Install ESET NOD32 AV\n'.format(KIT_NAME_FULL)) + scan_pups = ask('Enable PUP scans in ESET?') + install_eset_nod32_av(scan_pups) + print_standard('\nDone.') + exit_script() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/install_sw_bundle.py b/.bin/Scripts/install_sw_bundle.py index e04ea88a..73024195 100644 --- a/.bin/Scripts/install_sw_bundle.py +++ b/.bin/Scripts/install_sw_bundle.py @@ -13,52 +13,52 @@ set_log_file('Install SW Bundle.log') D7_MODE = 'd7mode' in sys.argv if __name__ == '__main__': - try: - stay_awake() - clear_screen() - print_info('{}: SW Bundle Tool\n'.format(KIT_NAME_FULL)) - other_results = { - 'Error': { - 'CalledProcessError': 'Unknown Error', - 'FileNotFoundError': 'File not found', - }, - 'Warning': { - 'GenericRepair': 'Repaired', - 'UnsupportedOSError': 'Unsupported OS', - }} - answer_extensions = D7_MODE or ask('Install Extensions?') - answer_vcr = D7_MODE or ask('Install Visual C++ Runtimes?') - answer_ninite = D7_MODE or ask('Install Ninite Bundle?') - if not D7_MODE and ( - answer_ninite and global_vars['OS']['Version'] in ['7']): - # Vista is dead, not going to check for it - answer_mse = ask('Install MSE?') - else: - answer_mse = False + try: + stay_awake() + clear_screen() + print_info('{}: SW Bundle Tool\n'.format(KIT_NAME_FULL)) + other_results = { + 'Error': { + 'CalledProcessError': 'Unknown Error', + 'FileNotFoundError': 'File not found', + }, + 'Warning': { + 'GenericRepair': 'Repaired', + 'UnsupportedOSError': 'Unsupported OS', + }} + answer_extensions = D7_MODE or ask('Install Extensions?') + answer_vcr = D7_MODE or ask('Install Visual C++ Runtimes?') + answer_ninite = D7_MODE or ask('Install Ninite Bundle?') + if not D7_MODE and ( + answer_ninite and global_vars['OS']['Version'] in ['7']): + # Vista is dead, not going to check for it + answer_mse = ask('Install MSE?') + else: + answer_mse = False - print_info('Installing Programs') - if answer_vcr: - install_vcredists() - if answer_ninite: - try_and_print(message='Ninite bundle...', - function=install_ninite_bundle, cs='Started', - mse=answer_mse, other_results=other_results) - if answer_extensions: - wait_for_process('ninite.exe') - print_info('Installing Extensions') - try_and_print(message='Classic Shell skin...', - function=install_classicstart_skin, - other_results=other_results) - try_and_print(message='Google Chrome extensions...', - function=install_chrome_extensions) - try_and_print(message='Mozilla Firefox extensions...', - function=install_firefox_extensions, - other_results=other_results) - print_standard('\nDone.') - exit_script() - except SystemExit: - pass - except: - major_exception() + print_info('Installing Programs') + if answer_vcr: + install_vcredists() + if answer_ninite: + try_and_print(message='Ninite bundle...', + function=install_ninite_bundle, cs='Started', + mse=answer_mse, other_results=other_results) + if answer_extensions: + wait_for_process('ninite.exe') + print_info('Installing Extensions') + try_and_print(message='Classic Shell skin...', + function=install_classicstart_skin, + other_results=other_results) + try_and_print(message='Google Chrome extensions...', + function=install_chrome_extensions) + try_and_print(message='Mozilla Firefox extensions...', + function=install_firefox_extensions, + other_results=other_results) + print_standard('\nDone.') + exit_script() + except SystemExit: + pass + except: + major_exception() -# vim: sts=4 sw=4 ts=4 +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/install_vcredists.py b/.bin/Scripts/install_vcredists.py index fd953551..1a722bf9 100644 --- a/.bin/Scripts/install_vcredists.py +++ b/.bin/Scripts/install_vcredists.py @@ -12,23 +12,25 @@ os.system('title {}: Install Visual C++ Runtimes'.format(KIT_NAME_FULL)) set_log_file('Install Visual C++ Runtimes.log') if __name__ == '__main__': - try: - stay_awake() - clear_screen() - print_info('{}: Install Visual C++ Runtimes\n'.format(KIT_NAME_FULL)) - other_results = { - 'Error': { - 'CalledProcessError': 'Unknown Error', - }} + try: + stay_awake() + clear_screen() + print_info('{}: Install Visual C++ Runtimes\n'.format(KIT_NAME_FULL)) + other_results = { + 'Error': { + 'CalledProcessError': 'Unknown Error', + }} - if ask('Install Visual C++ Runtimes?'): - install_vcredists() - else: - abort() + if ask('Install Visual C++ Runtimes?'): + install_vcredists() + else: + abort() - print_standard('\nDone.') - exit_script() - except SystemExit: - pass - except: - major_exception() + print_standard('\nDone.') + exit_script() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/system_checklist.py b/.bin/Scripts/system_checklist.py index c555136a..3fdf6ac9 100644 --- a/.bin/Scripts/system_checklist.py +++ b/.bin/Scripts/system_checklist.py @@ -18,126 +18,126 @@ set_log_file('System Checklist.log') D7_MODE = 'd7mode' in sys.argv if __name__ == '__main__': + try: + stay_awake() + clear_screen() + print_info('{}: System Checklist Tool\n'.format(KIT_NAME_FULL)) + ticket_number = get_ticket_number() + other_results = { + 'Error': { + 'BIOSKeyNotFoundError': 'BIOS key not found', + 'CalledProcessError': 'Unknown Error', + 'FileNotFoundError': 'File not found', + 'GenericError': 'Unknown Error', + 'SecureBootDisabledError': 'Disabled', + }, + 'Warning': { + 'OSInstalledLegacyError': 'OS installed Legacy', + 'SecureBootNotAvailError': 'Not available', + 'SecureBootUnknownError': 'Unknown', + }} + if ENABLED_TICKET_NUMBERS: + print_info('Starting System Checklist for Ticket #{}\n'.format( + ticket_number)) + + # Configure + print_info('Configure') + if global_vars['OS']['Version'] == '10': + try_and_print(message='Explorer...', + function=config_explorer_system, cs='Done') + try_and_print(message='Disabling telemetry...', + function=disable_windows_telemetry, cs='Done') + try_and_print(message='Enabling RegBack...', + function=enable_regback, cs='Done') + try_and_print(message='Enabling System Restore...', + function=enable_system_restore, cs='Done') + try_and_print(message='Updating Clock...', + function=update_clock, cs='Done') + + # Cleanup + print_info('Cleanup') + try_and_print(message='AdwCleaner...', + function=cleanup_adwcleaner, cs='Done', other_results=other_results) + try_and_print(message='Desktop...', + function=cleanup_desktop, cs='Done') + try_and_print(message='Emsisoft a2cmd...', + function=cleanup_emsisoft, cs='Done') + try_and_print(message='Registry Backup(s)...', + function=cleanup_regbackups, cs='Done') + try_and_print(message='{}...'.format(KIT_NAME_FULL), + function=delete_empty_folders, cs='Done', + folder_path=global_vars['ClientDir']) + + # Export system info + if not D7_MODE: + print_info('Backup System Information') + try_and_print(message='AIDA64 reports...', + function=run_aida64, cs='Done', other_results=other_results) + try_and_print(message='File listing...', + function=backup_file_list, cs='Done', other_results=other_results) + try_and_print(message='Power plans...', + function=backup_power_plans, cs='Done') + try_and_print(message='Product Keys...', other_results=other_results, + function=run_produkey, cs='Done') + try_and_print(message='Registry...', + function=backup_registry, cs='Done', other_results=other_results) + + # User data + print_info('User Data') + show_user_data_summary() + + # Summary + print_info('Summary') + try_and_print(message='Operating System:', + function=show_os_name, ns='Unknown', silent_function=False) + try_and_print(message='Activation:', + function=show_os_activation, ns='Unknown', silent_function=False) + if (not windows_is_activated() + and global_vars['OS']['Version'] in ('8', '8.1', '10')): + try_and_print(message='BIOS Activation:', + function=activate_with_bios, + other_results=other_results) + try_and_print(message='Secure Boot Status:', + function=check_secure_boot_status, other_results=other_results) + try_and_print(message='Installed RAM:', + function=show_installed_ram, ns='Unknown', silent_function=False) + show_free_space() + try_and_print(message='Installed Antivirus:', + function=get_installed_antivirus, ns='Unknown', + other_results=other_results, print_return=True) + try_and_print(message='Installed Office:', + function=get_installed_office, ns='Unknown', + other_results=other_results, print_return=True) + if D7_MODE: + try_and_print(message='Product Keys:', + function=get_product_keys, ns='Unknown', print_return=True) + + # Play audio, show devices, open Windows updates, and open Activation + try_and_print(message='Opening Device Manager...', + function=open_device_manager, cs='Started') + try_and_print(message='Opening HWiNFO (Sensors)...', + function=run_hwinfo_sensors, cs='Started', other_results=other_results) + try_and_print(message='Opening Windows Updates...', + function=open_windows_updates, cs='Started') + if not windows_is_activated(): + try_and_print(message='Opening Windows Activation...', + function=open_windows_activation, cs='Started') + sleep(3) + try_and_print(message='Running XMPlay...', + function=run_xmplay, cs='Started', other_results=other_results) try: - stay_awake() - clear_screen() - print_info('{}: System Checklist Tool\n'.format(KIT_NAME_FULL)) - ticket_number = get_ticket_number() - other_results = { - 'Error': { - 'BIOSKeyNotFoundError': 'BIOS key not found', - 'CalledProcessError': 'Unknown Error', - 'FileNotFoundError': 'File not found', - 'GenericError': 'Unknown Error', - 'SecureBootDisabledError': 'Disabled', - }, - 'Warning': { - 'OSInstalledLegacyError': 'OS installed Legacy', - 'SecureBootNotAvailError': 'Not available', - 'SecureBootUnknownError': 'Unknown', - }} - if ENABLED_TICKET_NUMBERS: - print_info('Starting System Checklist for Ticket #{}\n'.format( - ticket_number)) - - # Configure - print_info('Configure') - if global_vars['OS']['Version'] == '10': - try_and_print(message='Explorer...', - function=config_explorer_system, cs='Done') - try_and_print(message='Disabling telemetry...', - function=disable_windows_telemetry, cs='Done') - try_and_print(message='Enabling RegBack...', - function=enable_regback, cs='Done') - try_and_print(message='Enabling System Restore...', - function=enable_system_restore, cs='Done') - try_and_print(message='Updating Clock...', - function=update_clock, cs='Done') - - # Cleanup - print_info('Cleanup') - try_and_print(message='AdwCleaner...', - function=cleanup_adwcleaner, cs='Done', other_results=other_results) - try_and_print(message='Desktop...', - function=cleanup_desktop, cs='Done') - try_and_print(message='Emsisoft a2cmd...', - function=cleanup_emsisoft, cs='Done') - try_and_print(message='Registry Backup(s)...', - function=cleanup_regbackups, cs='Done') - try_and_print(message='{}...'.format(KIT_NAME_FULL), - function=delete_empty_folders, cs='Done', - folder_path=global_vars['ClientDir']) - - # Export system info - if not D7_MODE: - print_info('Backup System Information') - try_and_print(message='AIDA64 reports...', - function=run_aida64, cs='Done', other_results=other_results) - try_and_print(message='File listing...', - function=backup_file_list, cs='Done', other_results=other_results) - try_and_print(message='Power plans...', - function=backup_power_plans, cs='Done') - try_and_print(message='Product Keys...', other_results=other_results, - function=run_produkey, cs='Done') - try_and_print(message='Registry...', - function=backup_registry, cs='Done', other_results=other_results) - - # User data - print_info('User Data') - show_user_data_summary() - - # Summary - print_info('Summary') - try_and_print(message='Operating System:', - function=show_os_name, ns='Unknown', silent_function=False) - try_and_print(message='Activation:', - function=show_os_activation, ns='Unknown', silent_function=False) - if (not windows_is_activated() - and global_vars['OS']['Version'] in ('8', '8.1', '10')): - try_and_print(message='BIOS Activation:', - function=activate_with_bios, - other_results=other_results) - try_and_print(message='Secure Boot Status:', - function=check_secure_boot_status, other_results=other_results) - try_and_print(message='Installed RAM:', - function=show_installed_ram, ns='Unknown', silent_function=False) - show_free_space() - try_and_print(message='Installed Antivirus:', - function=get_installed_antivirus, ns='Unknown', - other_results=other_results, print_return=True) - try_and_print(message='Installed Office:', - function=get_installed_office, ns='Unknown', - other_results=other_results, print_return=True) - if D7_MODE: - try_and_print(message='Product Keys:', - function=get_product_keys, ns='Unknown', print_return=True) - - # Play audio, show devices, open Windows updates, and open Activation - try_and_print(message='Opening Device Manager...', - function=open_device_manager, cs='Started') - try_and_print(message='Opening HWiNFO (Sensors)...', - function=run_hwinfo_sensors, cs='Started', other_results=other_results) - try_and_print(message='Opening Windows Updates...', - function=open_windows_updates, cs='Started') - if not windows_is_activated(): - try_and_print(message='Opening Windows Activation...', - function=open_windows_activation, cs='Started') - sleep(3) - try_and_print(message='Running XMPlay...', - function=run_xmplay, cs='Started', other_results=other_results) - try: - check_secure_boot_status(show_alert=True) - except: - # Only trying to open alert message boxes - pass - - # Done - print_standard('\nDone.') - pause('Press Enter exit...') - exit_script() - except SystemExit: - pass + check_secure_boot_status(show_alert=True) except: - major_exception() + # Only trying to open alert message boxes + pass -# vim: sts=4 sw=4 ts=4 + # Done + print_standard('\nDone.') + pause('Press Enter exit...') + exit_script() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/system_checklist_hw.py b/.bin/Scripts/system_checklist_hw.py index 01d6d551..bac5f2dd 100644 --- a/.bin/Scripts/system_checklist_hw.py +++ b/.bin/Scripts/system_checklist_hw.py @@ -17,101 +17,103 @@ os.system('title {}: System HW Checklist Tool'.format(KIT_NAME_FULL)) set_log_file('System HW Checklist.log') if __name__ == '__main__': + try: + stay_awake() + clear_screen() + print_info('{}: System HW Checklist Tool\n'.format(KIT_NAME_FULL)) + ticket_number = get_ticket_number() + other_results = { + 'Error': { + 'BIOSKeyNotFoundError': 'BIOS key not found', + 'CalledProcessError': 'Unknown Error', + 'FileNotFoundError': 'File not found', + 'GenericError': 'Unknown Error', + 'SecureBootDisabledError': 'Disabled', + }, + 'Warning': { + 'OSInstalledLegacyError': 'OS installed Legacy', + 'SecureBootNotAvailError': 'Not available', + 'SecureBootUnknownError': 'Unknown', + }} + if ENABLED_TICKET_NUMBERS: + print_info('Starting System Checklist for Ticket #{}\n'.format( + ticket_number)) + + # Configure + print_info('Configure') + if global_vars['OS']['Version'] == '10': + try_and_print(message='Enabling RegBack...', + function=enable_regback, cs='Done') + try_and_print(message='Enabling System Restore...', + function=enable_system_restore, cs='Done') + + # Export system info + print_info('Backup System Information') + try_and_print(message='AIDA64 reports...', + function=run_aida64, cs='Done', other_results=other_results) + try_and_print(message='File listing...', + function=backup_file_list, cs='Done', other_results=other_results) + try_and_print(message='Power plans...', + function=backup_power_plans, cs='Done') + try_and_print(message='Product Keys...', other_results=other_results, + function=run_produkey, cs='Done') + try_and_print(message='Registry...', + function=backup_registry, cs='Done', other_results=other_results) + + # Cleanup + print_info('Cleanup') + try_and_print(message='{}...'.format(KIT_NAME_FULL), + function=delete_empty_folders, cs='Done', + folder_path=global_vars['ClientDir']) + + # User data + print_info('User Data') + show_user_data_summary() + + # Summary + print_info('Summary') + try_and_print(message='Operating System:', + function=show_os_name, ns='Unknown', silent_function=False) + try_and_print(message='Activation:', + function=show_os_activation, ns='Unknown', silent_function=False) + try_and_print(message='Secure Boot Status:', + function=check_secure_boot_status, other_results=other_results) + try_and_print(message='Installed RAM:', + function=show_installed_ram, ns='Unknown', silent_function=False) + show_free_space() + try_and_print(message='Installed Antivirus:', + function=get_installed_antivirus, ns='Unknown', + other_results=other_results, print_return=True) + try_and_print(message='Installed Office:', + function=get_installed_office, ns='Unknown', + other_results=other_results, print_return=True) + + # Play audio, show devices, open Windows updates, and open Activation + try_and_print(message='Opening Device Manager...', + function=open_device_manager, cs='Started') + try_and_print(message='Opening HWiNFO (Sensors)...', + function=run_hwinfo_sensors, cs='Started', other_results=other_results) + try_and_print(message='Opening Windows Updates...', + function=open_windows_updates, cs='Started') + if not windows_is_activated(): + try_and_print(message='Opening Windows Activation...', + function=open_windows_activation, cs='Started') + sleep(3) + try_and_print(message='Running XMPlay...', + function=run_xmplay, cs='Started', other_results=other_results) try: - stay_awake() - clear_screen() - print_info('{}: System HW Checklist Tool\n'.format(KIT_NAME_FULL)) - ticket_number = get_ticket_number() - other_results = { - 'Error': { - 'BIOSKeyNotFoundError': 'BIOS key not found', - 'CalledProcessError': 'Unknown Error', - 'FileNotFoundError': 'File not found', - 'GenericError': 'Unknown Error', - 'SecureBootDisabledError': 'Disabled', - }, - 'Warning': { - 'OSInstalledLegacyError': 'OS installed Legacy', - 'SecureBootNotAvailError': 'Not available', - 'SecureBootUnknownError': 'Unknown', - }} - if ENABLED_TICKET_NUMBERS: - print_info('Starting System Checklist for Ticket #{}\n'.format( - ticket_number)) - - # Configure - print_info('Configure') - if global_vars['OS']['Version'] == '10': - try_and_print(message='Enabling RegBack...', - function=enable_regback, cs='Done') - try_and_print(message='Enabling System Restore...', - function=enable_system_restore, cs='Done') - - # Export system info - print_info('Backup System Information') - try_and_print(message='AIDA64 reports...', - function=run_aida64, cs='Done', other_results=other_results) - try_and_print(message='File listing...', - function=backup_file_list, cs='Done', other_results=other_results) - try_and_print(message='Power plans...', - function=backup_power_plans, cs='Done') - try_and_print(message='Product Keys...', other_results=other_results, - function=run_produkey, cs='Done') - try_and_print(message='Registry...', - function=backup_registry, cs='Done', other_results=other_results) - - # Cleanup - print_info('Cleanup') - try_and_print(message='{}...'.format(KIT_NAME_FULL), - function=delete_empty_folders, cs='Done', - folder_path=global_vars['ClientDir']) - - # User data - print_info('User Data') - show_user_data_summary() - - # Summary - print_info('Summary') - try_and_print(message='Operating System:', - function=show_os_name, ns='Unknown', silent_function=False) - try_and_print(message='Activation:', - function=show_os_activation, ns='Unknown', silent_function=False) - try_and_print(message='Secure Boot Status:', - function=check_secure_boot_status, other_results=other_results) - try_and_print(message='Installed RAM:', - function=show_installed_ram, ns='Unknown', silent_function=False) - show_free_space() - try_and_print(message='Installed Antivirus:', - function=get_installed_antivirus, ns='Unknown', - other_results=other_results, print_return=True) - try_and_print(message='Installed Office:', - function=get_installed_office, ns='Unknown', - other_results=other_results, print_return=True) - - # Play audio, show devices, open Windows updates, and open Activation - try_and_print(message='Opening Device Manager...', - function=open_device_manager, cs='Started') - try_and_print(message='Opening HWiNFO (Sensors)...', - function=run_hwinfo_sensors, cs='Started', other_results=other_results) - try_and_print(message='Opening Windows Updates...', - function=open_windows_updates, cs='Started') - if not windows_is_activated(): - try_and_print(message='Opening Windows Activation...', - function=open_windows_activation, cs='Started') - sleep(3) - try_and_print(message='Running XMPlay...', - function=run_xmplay, cs='Started', other_results=other_results) - try: - check_secure_boot_status(show_alert=True) - except: - # Only trying to open alert message boxes - pass - - # Done - print_standard('\nDone.') - pause('Press Enter exit...') - exit_script() - except SystemExit: - pass + check_secure_boot_status(show_alert=True) except: - major_exception() + # Only trying to open alert message boxes + pass + + # Done + print_standard('\nDone.') + pause('Press Enter exit...') + exit_script() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/user_checklist.py b/.bin/Scripts/user_checklist.py index 56ae7241..59690370 100644 --- a/.bin/Scripts/user_checklist.py +++ b/.bin/Scripts/user_checklist.py @@ -15,83 +15,83 @@ set_log_file('User Checklist ({USERNAME}).log'.format(**global_vars['Env'])) D7_MODE = 'd7mode' in sys.argv if __name__ == '__main__': - try: - stay_awake() - clear_screen() - print_info('{}: User Checklist\n'.format(KIT_NAME_FULL)) - other_results = { - 'Warning': { - 'NotInstalledError': 'Not installed', - 'NoProfilesError': 'No profiles found', - }} - #answer_config_browsers = ask('Install adblock?') - answer_config_browsers = True - if answer_config_browsers: - if D7_MODE: - # This is handled by another script option in d7ii - answer_reset_browsers = False - else: - answer_reset_browsers = ask( - 'Reset browsers to safe defaults first?') - if global_vars['OS']['Version'] == '10': - answer_config_classicshell = True - answer_config_explorer_user = True + try: + stay_awake() + clear_screen() + print_info('{}: User Checklist\n'.format(KIT_NAME_FULL)) + other_results = { + 'Warning': { + 'NotInstalledError': 'Not installed', + 'NoProfilesError': 'No profiles found', + }} + #answer_config_browsers = ask('Install adblock?') + answer_config_browsers = True + if answer_config_browsers: + if D7_MODE: + # This is handled by another script option in d7ii + answer_reset_browsers = False + else: + answer_reset_browsers = ask( + 'Reset browsers to safe defaults first?') + if global_vars['OS']['Version'] == '10': + answer_config_classicshell = True + answer_config_explorer_user = True - # Cleanup - print_info('Cleanup') - try_and_print(message='Desktop...', - function=cleanup_desktop, cs='Done') + # Cleanup + print_info('Cleanup') + try_and_print(message='Desktop...', + function=cleanup_desktop, cs='Done') - # Scan for supported browsers - print_info('Scanning for browsers') - scan_for_browsers() + # Scan for supported browsers + print_info('Scanning for browsers') + scan_for_browsers() - # Homepages - if not D7_MODE: - print_info('Current homepages') - list_homepages() + # Homepages + if not D7_MODE: + print_info('Current homepages') + list_homepages() - # Backup - if not D7_MODE: - # Done during system_diagnostics - print_info('Backing up browsers') - backup_browsers() + # Backup + if not D7_MODE: + # Done during system_diagnostics + print_info('Backing up browsers') + backup_browsers() - # Reset - if answer_config_browsers and answer_reset_browsers: - print_info('Resetting browsers') - reset_browsers() + # Reset + if answer_config_browsers and answer_reset_browsers: + print_info('Resetting browsers') + reset_browsers() - # Configure - print_info('Configuring programs') - if answer_config_browsers: - install_adblock() - if global_vars['OS']['Version'] == '10': - if answer_config_classicshell: - try_and_print(message='ClassicStart...', - function=config_classicstart, cs='Done') - if answer_config_explorer_user: - try_and_print(message='Explorer...', - function=config_explorer_user, cs='Done') - if (not answer_config_browsers - and not answer_config_classicshell - and not answer_config_explorer_user): - print_warning(' Skipped') - else: - if not answer_config_browsers: - print_warning(' Skipped') + # Configure + print_info('Configuring programs') + if answer_config_browsers: + install_adblock() + if global_vars['OS']['Version'] == '10': + if answer_config_classicshell: + try_and_print(message='ClassicStart...', + function=config_classicstart, cs='Done') + if answer_config_explorer_user: + try_and_print(message='Explorer...', + function=config_explorer_user, cs='Done') + if (not answer_config_browsers + and not answer_config_classicshell + and not answer_config_explorer_user): + print_warning(' Skipped') + else: + if not answer_config_browsers: + print_warning(' Skipped') - # Run speedtest - popen_program(['start', '', 'https://fast.com'], shell=True) + # Run speedtest + popen_program(['start', '', 'https://fast.com'], shell=True) - # Done - if not D7_MODE: - print_standard('\nDone.') - pause('Press Enter to exit...') - exit_script() - except SystemExit: - pass - except: - major_exception() + # Done + if not D7_MODE: + print_standard('\nDone.') + pause('Press Enter to exit...') + exit_script() + except SystemExit: + pass + except: + major_exception() -# vim: sts=4 sw=4 ts=4 +# vim: sts=2 sw=2 ts=2 From f321dee54fca9b0c8a4f5d556102ad207a224682 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 22:28:17 -0700 Subject: [PATCH 191/265] Switched indents to 2 spaces --- .bin/Scripts/activate.py | 92 ++++----- .bin/Scripts/cbs_fix.py | 50 ++--- .bin/Scripts/check_disk.py | 84 ++++---- .bin/Scripts/dism.py | 86 +++++---- .bin/Scripts/install_sw_bundle.py | 100 +++++----- .bin/Scripts/install_vcredists.py | 38 ++-- .bin/Scripts/safemode_enter.py | 46 ++--- .bin/Scripts/safemode_exit.py | 46 ++--- .bin/Scripts/sfc_scan.py | 50 ++--- .bin/Scripts/system_checklist.py | 212 ++++++++++---------- .bin/Scripts/system_diagnostics.py | 298 ++++++++++++++--------------- .bin/Scripts/transferred_keys.py | 28 +-- .bin/Scripts/update_kit.py | 234 +++++++++++----------- .bin/Scripts/user_checklist.py | 124 ++++++------ .bin/Scripts/user_data_transfer.py | 90 ++++----- .bin/Scripts/winpe_root_menu.py | 14 +- 16 files changed, 808 insertions(+), 784 deletions(-) diff --git a/.bin/Scripts/activate.py b/.bin/Scripts/activate.py index 642e5edd..cf17263f 100644 --- a/.bin/Scripts/activate.py +++ b/.bin/Scripts/activate.py @@ -11,52 +11,54 @@ init_global_vars() os.system('title {}: Windows Activation Tool'.format(KIT_NAME_FULL)) if __name__ == '__main__': - try: - stay_awake() - clear_screen() - print_info('{}: Windows Activation Tool\n'.format(KIT_NAME_FULL)) - # Bail early if already activated - if windows_is_activated(): - print_info('This system is already activated') - sleep(5) - exit_script() - other_results = { - 'Error': { - 'BIOSKeyNotFoundError': 'BIOS key not found.', - }} + try: + stay_awake() + clear_screen() + print_info('{}: Windows Activation Tool\n'.format(KIT_NAME_FULL)) + # Bail early if already activated + if windows_is_activated(): + print_info('This system is already activated') + sleep(5) + exit_script() + other_results = { + 'Error': { + 'BIOSKeyNotFoundError': 'BIOS key not found.', + }} - # Determine activation method - activation_methods = [ - {'Name': 'Activate with BIOS key', 'Function': activate_with_bios}, - ] - if global_vars['OS']['Version'] not in ('8', '8.1', '10'): - activation_methods[0]['Disabled'] = True - actions = [ - {'Name': 'Quit', 'Letter': 'Q'}, - ] + # Determine activation method + activation_methods = [ + {'Name': 'Activate with BIOS key', 'Function': activate_with_bios}, + ] + if global_vars['OS']['Version'] not in ('8', '8.1', '10'): + activation_methods[0]['Disabled'] = True + actions = [ + {'Name': 'Quit', 'Letter': 'Q'}, + ] - while True: - selection = menu_select( - '{}: Windows Activation Menu'.format(KIT_NAME_FULL), - main_entries=activation_methods, action_entries=actions) + while True: + selection = menu_select( + '{}: Windows Activation Menu'.format(KIT_NAME_FULL), + main_entries=activation_methods, action_entries=actions) - if (selection.isnumeric()): - result = try_and_print( - message = activation_methods[int(selection)-1]['Name'], - function = activation_methods[int(selection)-1]['Function'], - other_results=other_results) - if result['CS']: - break - else: - sleep(2) - elif selection == 'Q': - exit_script() - - # Done - print_success('\nDone.') - pause("Press Enter to exit...") + if (selection.isnumeric()): + result = try_and_print( + message = activation_methods[int(selection)-1]['Name'], + function = activation_methods[int(selection)-1]['Function'], + other_results=other_results) + if result['CS']: + break + else: + sleep(2) + elif selection == 'Q': exit_script() - except SystemExit: - pass - except: - major_exception() + + # Done + print_success('\nDone.') + pause("Press Enter to exit...") + exit_script() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/cbs_fix.py b/.bin/Scripts/cbs_fix.py index 9a8ff10c..460a32a5 100644 --- a/.bin/Scripts/cbs_fix.py +++ b/.bin/Scripts/cbs_fix.py @@ -13,30 +13,32 @@ os.system('title {}: CBS Cleanup'.format(KIT_NAME_FULL)) set_log_file('CBS Cleanup.log') if __name__ == '__main__': - try: - # Prep - stay_awake() - clear_screen() - folder_path = r'{}\Backups'.format(KIT_NAME_SHORT) - dest = select_destination(folder_path=folder_path, - prompt='Which disk are we using for temp data and backup?') + try: + # Prep + stay_awake() + clear_screen() + folder_path = r'{}\Backups'.format(KIT_NAME_SHORT) + dest = select_destination(folder_path=folder_path, + prompt='Which disk are we using for temp data and backup?') - # Show details - print_info('{}: CBS Cleanup Tool\n'.format(KIT_NAME_FULL)) - show_data('Backup / Temp path:', dest) - print_standard('\n') - if (not ask('Proceed with CBS cleanup?')): - abort() + # Show details + print_info('{}: CBS Cleanup Tool\n'.format(KIT_NAME_FULL)) + show_data('Backup / Temp path:', dest) + print_standard('\n') + if (not ask('Proceed with CBS cleanup?')): + abort() - # Run Cleanup - try_and_print(message='Running cleanup...', function=cleanup_cbs, - cs='Done', dest_folder=dest) + # Run Cleanup + try_and_print(message='Running cleanup...', function=cleanup_cbs, + cs='Done', dest_folder=dest) - # Done - print_standard('\nDone.') - pause("Press Enter to exit...") - exit_script() - except SystemExit: - pass - except: - major_exception() + # Done + print_standard('\nDone.') + pause("Press Enter to exit...") + exit_script() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/check_disk.py b/.bin/Scripts/check_disk.py index 7e59fb2b..1140f4fc 100644 --- a/.bin/Scripts/check_disk.py +++ b/.bin/Scripts/check_disk.py @@ -12,45 +12,47 @@ os.system('title {}: Check Disk Tool'.format(KIT_NAME_FULL)) set_log_file('Check Disk.log') if __name__ == '__main__': - try: - stay_awake() - clear_screen() - other_results = { - 'Error': { - 'CalledProcessError': 'Unknown Error', - }, - 'Warning': { - 'GenericRepair': 'Repaired', - 'UnsupportedOSError': 'Unsupported OS', - }} - options = [ - {'Name': 'Run CHKDSK scan (read-only)', 'Repair': False}, - {'Name': 'Schedule CHKDSK scan (offline repair)', 'Repair': True}] - actions = [{'Name': 'Quit', 'Letter': 'Q'}] - selection = menu_select( - '{}: Check Disk Menu\n'.format(KIT_NAME_FULL), - main_entries=options, - action_entries=actions) - print_info('{}: Check Disk Menu\n'.format(KIT_NAME_FULL)) - if selection == 'Q': - abort() - elif selection.isnumeric(): - repair = options[int(selection)-1]['Repair'] - if repair: - cs = 'Scheduled' - else: - cs = 'CS' - message = 'CHKDSK ({SYSTEMDRIVE})...'.format(**global_vars['Env']) - try_and_print(message=message, function=run_chkdsk, - cs=cs, other_results=other_results, repair=repair) - else: - abort() + try: + stay_awake() + clear_screen() + other_results = { + 'Error': { + 'CalledProcessError': 'Unknown Error', + }, + 'Warning': { + 'GenericRepair': 'Repaired', + 'UnsupportedOSError': 'Unsupported OS', + }} + options = [ + {'Name': 'Run CHKDSK scan (read-only)', 'Repair': False}, + {'Name': 'Schedule CHKDSK scan (offline repair)', 'Repair': True}] + actions = [{'Name': 'Quit', 'Letter': 'Q'}] + selection = menu_select( + '{}: Check Disk Menu\n'.format(KIT_NAME_FULL), + main_entries=options, + action_entries=actions) + print_info('{}: Check Disk Menu\n'.format(KIT_NAME_FULL)) + if selection == 'Q': + abort() + elif selection.isnumeric(): + repair = options[int(selection)-1]['Repair'] + if repair: + cs = 'Scheduled' + else: + cs = 'CS' + message = 'CHKDSK ({SYSTEMDRIVE})...'.format(**global_vars['Env']) + try_and_print(message=message, function=run_chkdsk, + cs=cs, other_results=other_results, repair=repair) + else: + abort() - # Done - print_success('Done.') - pause("Press Enter to exit...") - exit_script() - except SystemExit: - pass - except: - major_exception() + # Done + print_success('Done.') + pause("Press Enter to exit...") + exit_script() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/dism.py b/.bin/Scripts/dism.py index e49a9512..8b227da2 100644 --- a/.bin/Scripts/dism.py +++ b/.bin/Scripts/dism.py @@ -12,46 +12,48 @@ os.system('title {}: DISM helper Tool'.format(KIT_NAME_FULL)) set_log_file('DISM Helper.log') if __name__ == '__main__': - try: - stay_awake() - clear_screen() - other_results = { - 'Error': { - 'CalledProcessError': 'Unknown Error', - }, - 'Warning': { - 'GenericRepair': 'Repaired', - 'UnsupportedOSError': 'Unsupported OS', - }} - disabled = bool(global_vars['OS']['Version'] not in ('8', '8.1', '10')) - options = [ - {'Name': 'Check Health', 'Repair': False, 'Disabled': disabled}, - {'Name': 'Restore Health', 'Repair': True, 'Disabled': disabled}] - actions = [{'Name': 'Quit', 'Letter': 'Q'}] - selection = menu_select( - '{}: DISM Menu\n'.format(KIT_NAME_FULL), - main_entries=options, - action_entries=actions) - print_info('{}: DISM Menu\n'.format(KIT_NAME_FULL)) - if selection == 'Q': - abort() - elif selection.isnumeric(): - repair = options[int(selection)-1]['Repair'] - if repair: - message='DISM RestoreHealth...' - else: - message='DISM ScanHealth...' - try_and_print(message=message, function=run_dism, - cs='No corruption', ns='Corruption detected', - other_results=other_results, repair=repair) - else: - abort() + try: + stay_awake() + clear_screen() + other_results = { + 'Error': { + 'CalledProcessError': 'Unknown Error', + }, + 'Warning': { + 'GenericRepair': 'Repaired', + 'UnsupportedOSError': 'Unsupported OS', + }} + disabled = bool(global_vars['OS']['Version'] not in ('8', '8.1', '10')) + options = [ + {'Name': 'Check Health', 'Repair': False, 'Disabled': disabled}, + {'Name': 'Restore Health', 'Repair': True, 'Disabled': disabled}] + actions = [{'Name': 'Quit', 'Letter': 'Q'}] + selection = menu_select( + '{}: DISM Menu\n'.format(KIT_NAME_FULL), + main_entries=options, + action_entries=actions) + print_info('{}: DISM Menu\n'.format(KIT_NAME_FULL)) + if selection == 'Q': + abort() + elif selection.isnumeric(): + repair = options[int(selection)-1]['Repair'] + if repair: + message='DISM RestoreHealth...' + else: + message='DISM ScanHealth...' + try_and_print(message=message, function=run_dism, + cs='No corruption', ns='Corruption detected', + other_results=other_results, repair=repair) + else: + abort() - # Done - print_success('Done.') - pause("Press Enter to exit...") - exit_script() - except SystemExit: - pass - except: - major_exception() + # Done + print_success('Done.') + pause("Press Enter to exit...") + exit_script() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/install_sw_bundle.py b/.bin/Scripts/install_sw_bundle.py index 5ee1a8f3..4386bfb0 100644 --- a/.bin/Scripts/install_sw_bundle.py +++ b/.bin/Scripts/install_sw_bundle.py @@ -12,55 +12,55 @@ os.system('title {}: SW Bundle Tool'.format(KIT_NAME_FULL)) set_log_file('Install SW Bundle.log') if __name__ == '__main__': - try: - stay_awake() - clear_screen() - print_info('{}: SW Bundle Tool\n'.format(KIT_NAME_FULL)) - other_results = { - 'Error': { - 'CalledProcessError': 'Unknown Error', - 'FileNotFoundError': 'File not found', - }, - 'Warning': { - 'GenericRepair': 'Repaired', - 'UnsupportedOSError': 'Unsupported OS', - }} - answer_extensions = ask('Install Extensions?') - answer_adobe_reader = ask('Install Adobe Reader?') - answer_vcr = ask('Install Visual C++ Runtimes?') - answer_ninite = ask('Install Ninite Bundle?') - if answer_ninite and global_vars['OS']['Version'] in ['7']: - # Vista is dead, not going to check for it - answer_mse = ask('Install MSE?') - else: - answer_mse = False + try: + stay_awake() + clear_screen() + print_info('{}: SW Bundle Tool\n'.format(KIT_NAME_FULL)) + other_results = { + 'Error': { + 'CalledProcessError': 'Unknown Error', + 'FileNotFoundError': 'File not found', + }, + 'Warning': { + 'GenericRepair': 'Repaired', + 'UnsupportedOSError': 'Unsupported OS', + }} + answer_extensions = ask('Install Extensions?') + answer_adobe_reader = ask('Install Adobe Reader?') + answer_vcr = ask('Install Visual C++ Runtimes?') + answer_ninite = ask('Install Ninite Bundle?') + if answer_ninite and global_vars['OS']['Version'] in ['7']: + # Vista is dead, not going to check for it + answer_mse = ask('Install MSE?') + else: + answer_mse = False - print_info('Installing Programs') - if answer_adobe_reader: - try_and_print(message='Adobe Reader DC...', - function=install_adobe_reader, other_results=other_results) - if answer_vcr: - install_vcredists() - if answer_ninite: - try_and_print(message='Ninite bundle...', - function=install_ninite_bundle, cs='Started', - mse=answer_mse, other_results=other_results) - if answer_extensions: - wait_for_process('ninite.exe') - print_info('Installing Extensions') - try_and_print(message='Classic Shell skin...', - function=install_classicstart_skin, - other_results=other_results) - try_and_print(message='Google Chrome extensions...', - function=install_chrome_extensions) - try_and_print(message='Mozilla Firefox extensions...', - function=install_firefox_extensions, - other_results=other_results) - print_standard('\nDone.') - exit_script() - except SystemExit: - pass - except: - major_exception() + print_info('Installing Programs') + if answer_adobe_reader: + try_and_print(message='Adobe Reader DC...', + function=install_adobe_reader, other_results=other_results) + if answer_vcr: + install_vcredists() + if answer_ninite: + try_and_print(message='Ninite bundle...', + function=install_ninite_bundle, cs='Started', + mse=answer_mse, other_results=other_results) + if answer_extensions: + wait_for_process('ninite.exe') + print_info('Installing Extensions') + try_and_print(message='Classic Shell skin...', + function=install_classicstart_skin, + other_results=other_results) + try_and_print(message='Google Chrome extensions...', + function=install_chrome_extensions) + try_and_print(message='Mozilla Firefox extensions...', + function=install_firefox_extensions, + other_results=other_results) + print_standard('\nDone.') + exit_script() + except SystemExit: + pass + except: + major_exception() -# vim: sts=4 sw=4 ts=4 +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/install_vcredists.py b/.bin/Scripts/install_vcredists.py index fd953551..1a722bf9 100644 --- a/.bin/Scripts/install_vcredists.py +++ b/.bin/Scripts/install_vcredists.py @@ -12,23 +12,25 @@ os.system('title {}: Install Visual C++ Runtimes'.format(KIT_NAME_FULL)) set_log_file('Install Visual C++ Runtimes.log') if __name__ == '__main__': - try: - stay_awake() - clear_screen() - print_info('{}: Install Visual C++ Runtimes\n'.format(KIT_NAME_FULL)) - other_results = { - 'Error': { - 'CalledProcessError': 'Unknown Error', - }} + try: + stay_awake() + clear_screen() + print_info('{}: Install Visual C++ Runtimes\n'.format(KIT_NAME_FULL)) + other_results = { + 'Error': { + 'CalledProcessError': 'Unknown Error', + }} - if ask('Install Visual C++ Runtimes?'): - install_vcredists() - else: - abort() + if ask('Install Visual C++ Runtimes?'): + install_vcredists() + else: + abort() - print_standard('\nDone.') - exit_script() - except SystemExit: - pass - except: - major_exception() + print_standard('\nDone.') + exit_script() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/safemode_enter.py b/.bin/Scripts/safemode_enter.py index cce7e28a..027f4987 100644 --- a/.bin/Scripts/safemode_enter.py +++ b/.bin/Scripts/safemode_enter.py @@ -11,28 +11,30 @@ init_global_vars() os.system('title {}: SafeMode Tool'.format(KIT_NAME_FULL)) if __name__ == '__main__': - try: - clear_screen() - print_info('{}: SafeMode Tool\n'.format(KIT_NAME_FULL)) - other_results = { - 'Error': {'CalledProcessError': 'Unknown Error'}, - 'Warning': {}} + try: + clear_screen() + print_info('{}: SafeMode Tool\n'.format(KIT_NAME_FULL)) + other_results = { + 'Error': {'CalledProcessError': 'Unknown Error'}, + 'Warning': {}} - if not ask('Enable booting to SafeMode (with Networking)?'): - abort() + if not ask('Enable booting to SafeMode (with Networking)?'): + abort() - # Configure SafeMode - try_and_print(message='Set BCD option...', - function=enable_safemode, other_results=other_results) - try_and_print(message='Enable MSI in SafeMode...', - function=enable_safemode_msi, other_results=other_results) + # Configure SafeMode + try_and_print(message='Set BCD option...', + function=enable_safemode, other_results=other_results) + try_and_print(message='Enable MSI in SafeMode...', + function=enable_safemode_msi, other_results=other_results) - # Done - print_standard('\nDone.') - pause('Press Enter to reboot...') - reboot() - exit_script() - except SystemExit: - pass - except: - major_exception() + # Done + print_standard('\nDone.') + pause('Press Enter to reboot...') + reboot() + exit_script() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/safemode_exit.py b/.bin/Scripts/safemode_exit.py index af66222e..85376d51 100644 --- a/.bin/Scripts/safemode_exit.py +++ b/.bin/Scripts/safemode_exit.py @@ -11,28 +11,30 @@ init_global_vars() os.system('title {}: SafeMode Tool'.format(KIT_NAME_FULL)) if __name__ == '__main__': - try: - clear_screen() - print_info('{}: SafeMode Tool\n'.format(KIT_NAME_FULL)) - other_results = { - 'Error': {'CalledProcessError': 'Unknown Error'}, - 'Warning': {}} + try: + clear_screen() + print_info('{}: SafeMode Tool\n'.format(KIT_NAME_FULL)) + other_results = { + 'Error': {'CalledProcessError': 'Unknown Error'}, + 'Warning': {}} - if not ask('Disable booting to SafeMode?'): - abort() + if not ask('Disable booting to SafeMode?'): + abort() - # Configure SafeMode - try_and_print(message='Remove BCD option...', - function=disable_safemode, other_results=other_results) - try_and_print(message='Disable MSI in SafeMode...', - function=disable_safemode_msi, other_results=other_results) + # Configure SafeMode + try_and_print(message='Remove BCD option...', + function=disable_safemode, other_results=other_results) + try_and_print(message='Disable MSI in SafeMode...', + function=disable_safemode_msi, other_results=other_results) - # Done - print_standard('\nDone.') - pause('Press Enter to reboot...') - reboot() - exit_script() - except SystemExit: - pass - except: - major_exception() + # Done + print_standard('\nDone.') + pause('Press Enter to reboot...') + reboot() + exit_script() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/sfc_scan.py b/.bin/Scripts/sfc_scan.py index d7a3d3fc..9864306a 100644 --- a/.bin/Scripts/sfc_scan.py +++ b/.bin/Scripts/sfc_scan.py @@ -12,28 +12,30 @@ os.system('title {}: SFC Tool'.format(KIT_NAME_FULL)) set_log_file('SFC Tool.log') if __name__ == '__main__': - try: - stay_awake() - clear_screen() - print_info('{}: SFC Tool\n'.format(KIT_NAME_FULL)) - other_results = { - 'Error': { - 'CalledProcessError': 'Unknown Error', - }, - 'Warning': { - 'GenericRepair': 'Repaired', - }} - if ask('Run a SFC scan now?'): - try_and_print(message='SFC scan...', - function=run_sfc_scan, other_results=other_results) - else: - abort() + try: + stay_awake() + clear_screen() + print_info('{}: SFC Tool\n'.format(KIT_NAME_FULL)) + other_results = { + 'Error': { + 'CalledProcessError': 'Unknown Error', + }, + 'Warning': { + 'GenericRepair': 'Repaired', + }} + if ask('Run a SFC scan now?'): + try_and_print(message='SFC scan...', + function=run_sfc_scan, other_results=other_results) + else: + abort() - # Done - print_standard('\nDone.') - pause('Press Enter to exit...') - exit_script() - except SystemExit: - pass - except: - major_exception() + # Done + print_standard('\nDone.') + pause('Press Enter to exit...') + exit_script() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/system_checklist.py b/.bin/Scripts/system_checklist.py index 52720438..1aa95d3e 100644 --- a/.bin/Scripts/system_checklist.py +++ b/.bin/Scripts/system_checklist.py @@ -17,112 +17,112 @@ os.system('title {}: System Checklist Tool'.format(KIT_NAME_FULL)) set_log_file('System Checklist.log') if __name__ == '__main__': + try: + stay_awake() + clear_screen() + print_info('{}: System Checklist Tool\n'.format(KIT_NAME_FULL)) + ticket_number = get_ticket_number() + other_results = { + 'Error': { + 'BIOSKeyNotFoundError': 'BIOS key not found', + 'CalledProcessError': 'Unknown Error', + 'FileNotFoundError': 'File not found', + 'GenericError': 'Unknown Error', + 'SecureBootDisabledError': 'Disabled', + }, + 'Warning': { + 'OSInstalledLegacyError': 'OS installed Legacy', + 'SecureBootNotAvailError': 'Not available', + 'SecureBootUnknownError': 'Unknown', + }} + if ENABLED_TICKET_NUMBERS: + print_info('Starting System Checklist for Ticket #{}\n'.format( + ticket_number)) + + # Configure + print_info('Configure') + if global_vars['OS']['Version'] == '10': + try_and_print(message='Explorer...', + function=config_explorer_system, cs='Done') + try_and_print(message='Updating Clock...', + function=update_clock, cs='Done') + + # Cleanup + print_info('Cleanup') + try_and_print(message='AdwCleaner...', + function=cleanup_adwcleaner, cs='Done', other_results=other_results) + try_and_print(message='Desktop...', + function=cleanup_desktop, cs='Done') + try_and_print(message='{}...'.format(KIT_NAME_FULL), + function=delete_empty_folders, cs='Done', + folder_path=global_vars['ClientDir']) + + # Export system info + print_info('Backup System Information') + try_and_print(message='AIDA64 reports...', + function=run_aida64, cs='Done', other_results=other_results) + try_and_print(message='File listing...', + function=backup_file_list, cs='Done', other_results=other_results) + try_and_print(message='Power plans...', + function=backup_power_plans, cs='Done') + try_and_print(message='Product Keys...', other_results=other_results, + function=run_produkey, cs='Done') + try_and_print(message='Registry...', + function=backup_registry, cs='Done', other_results=other_results) + + # User data + print_info('User Data') + show_user_data_summary() + + # Summary + print_info('Summary') + try_and_print(message='Operating System:', + function=show_os_name, ns='Unknown', silent_function=False) + try_and_print(message='Activation:', + function=show_os_activation, ns='Unknown', silent_function=False) + if (not windows_is_activated() + and global_vars['OS']['Version'] in ('8', '8.1', '10')): + try_and_print(message='BIOS Activation:', + function=activate_with_bios, + other_results=other_results) + try_and_print(message='Secure Boot Status:', + function=check_secure_boot_status, other_results=other_results) + try_and_print(message='Installed RAM:', + function=show_installed_ram, ns='Unknown', silent_function=False) + show_free_space() + try_and_print(message='Installed Antivirus:', + function=get_installed_antivirus, ns='Unknown', + other_results=other_results, print_return=True) + try_and_print(message='Installed Office:', + function=get_installed_office, ns='Unknown', + other_results=other_results, print_return=True) + + # Play audio, show devices, open Windows updates, and open Activation + try_and_print(message='Opening Device Manager...', + function=open_device_manager, cs='Started') + try_and_print(message='Opening HWiNFO (Sensors)...', + function=run_hwinfo_sensors, cs='Started', other_results=other_results) + try_and_print(message='Opening Windows Updates...', + function=open_windows_updates, cs='Started') + if not windows_is_activated(): + try_and_print(message='Opening Windows Activation...', + function=open_windows_activation, cs='Started') + sleep(3) + try_and_print(message='Running XMPlay...', + function=run_xmplay, cs='Started', other_results=other_results) try: - stay_awake() - clear_screen() - print_info('{}: System Checklist Tool\n'.format(KIT_NAME_FULL)) - ticket_number = get_ticket_number() - other_results = { - 'Error': { - 'BIOSKeyNotFoundError': 'BIOS key not found', - 'CalledProcessError': 'Unknown Error', - 'FileNotFoundError': 'File not found', - 'GenericError': 'Unknown Error', - 'SecureBootDisabledError': 'Disabled', - }, - 'Warning': { - 'OSInstalledLegacyError': 'OS installed Legacy', - 'SecureBootNotAvailError': 'Not available', - 'SecureBootUnknownError': 'Unknown', - }} - if ENABLED_TICKET_NUMBERS: - print_info('Starting System Checklist for Ticket #{}\n'.format( - ticket_number)) - - # Configure - print_info('Configure') - if global_vars['OS']['Version'] == '10': - try_and_print(message='Explorer...', - function=config_explorer_system, cs='Done') - try_and_print(message='Updating Clock...', - function=update_clock, cs='Done') - - # Cleanup - print_info('Cleanup') - try_and_print(message='AdwCleaner...', - function=cleanup_adwcleaner, cs='Done', other_results=other_results) - try_and_print(message='Desktop...', - function=cleanup_desktop, cs='Done') - try_and_print(message='{}...'.format(KIT_NAME_FULL), - function=delete_empty_folders, cs='Done', - folder_path=global_vars['ClientDir']) - - # Export system info - print_info('Backup System Information') - try_and_print(message='AIDA64 reports...', - function=run_aida64, cs='Done', other_results=other_results) - try_and_print(message='File listing...', - function=backup_file_list, cs='Done', other_results=other_results) - try_and_print(message='Power plans...', - function=backup_power_plans, cs='Done') - try_and_print(message='Product Keys...', other_results=other_results, - function=run_produkey, cs='Done') - try_and_print(message='Registry...', - function=backup_registry, cs='Done', other_results=other_results) - - # User data - print_info('User Data') - show_user_data_summary() - - # Summary - print_info('Summary') - try_and_print(message='Operating System:', - function=show_os_name, ns='Unknown', silent_function=False) - try_and_print(message='Activation:', - function=show_os_activation, ns='Unknown', silent_function=False) - if (not windows_is_activated() - and global_vars['OS']['Version'] in ('8', '8.1', '10')): - try_and_print(message='BIOS Activation:', - function=activate_with_bios, - other_results=other_results) - try_and_print(message='Secure Boot Status:', - function=check_secure_boot_status, other_results=other_results) - try_and_print(message='Installed RAM:', - function=show_installed_ram, ns='Unknown', silent_function=False) - show_free_space() - try_and_print(message='Installed Antivirus:', - function=get_installed_antivirus, ns='Unknown', - other_results=other_results, print_return=True) - try_and_print(message='Installed Office:', - function=get_installed_office, ns='Unknown', - other_results=other_results, print_return=True) - - # Play audio, show devices, open Windows updates, and open Activation - try_and_print(message='Opening Device Manager...', - function=open_device_manager, cs='Started') - try_and_print(message='Opening HWiNFO (Sensors)...', - function=run_hwinfo_sensors, cs='Started', other_results=other_results) - try_and_print(message='Opening Windows Updates...', - function=open_windows_updates, cs='Started') - if not windows_is_activated(): - try_and_print(message='Opening Windows Activation...', - function=open_windows_activation, cs='Started') - sleep(3) - try_and_print(message='Running XMPlay...', - function=run_xmplay, cs='Started', other_results=other_results) - try: - check_secure_boot_status(show_alert=True) - except: - # Only trying to open alert message boxes - pass - - # Done - print_standard('\nDone.') - pause('Press Enter exit...') - exit_script() - except SystemExit: - pass + check_secure_boot_status(show_alert=True) except: - major_exception() + # Only trying to open alert message boxes + pass -# vim: sts=4 sw=4 ts=4 + # Done + print_standard('\nDone.') + pause('Press Enter exit...') + exit_script() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/system_diagnostics.py b/.bin/Scripts/system_diagnostics.py index ffa28079..c7b363d8 100644 --- a/.bin/Scripts/system_diagnostics.py +++ b/.bin/Scripts/system_diagnostics.py @@ -17,158 +17,158 @@ set_log_file('System Diagnostics.log') # Static Variables BLEACH_BIT_CLEANERS = { - 'Applications': ( - 'adobe_reader.cache', - 'adobe_reader.tmp', - 'amule.tmp', - 'flash.cache', - 'gimp.tmp', - 'hippo_opensim_viewer.cache', - 'java.cache', - 'libreoffice.cache', - 'liferea.cache', - 'miro.cache', - 'openofficeorg.cache', - 'pidgin.cache', - 'secondlife_viewer.Cache', - 'thunderbird.cache', - 'vuze.backup_files', - 'vuze.cache', - 'vuze.tmp', - 'yahoo_messenger.cache', - ), - 'Browsers': ( - 'chromium.cache', - 'chromium.current_session', - 'firefox.cache', - 'firefox.session_restore', - 'google_chrome.cache', - 'google_chrome.session', - 'google_earth.temporary_files', - 'internet_explorer.temporary_files', - 'opera.cache', - 'opera.current_session', - 'safari.cache', - 'seamonkey.cache', - ), - 'System': ( - 'system.clipboard', - 'system.tmp', - 'winapp2_windows.jump_lists', - 'winapp2_windows.ms_search', - 'windows_explorer.run', - 'windows_explorer.search_history', - 'windows_explorer.thumbnails', - ), + 'Applications': ( + 'adobe_reader.cache', + 'adobe_reader.tmp', + 'amule.tmp', + 'flash.cache', + 'gimp.tmp', + 'hippo_opensim_viewer.cache', + 'java.cache', + 'libreoffice.cache', + 'liferea.cache', + 'miro.cache', + 'openofficeorg.cache', + 'pidgin.cache', + 'secondlife_viewer.Cache', + 'thunderbird.cache', + 'vuze.backup_files', + 'vuze.cache', + 'vuze.tmp', + 'yahoo_messenger.cache', + ), + 'Browsers': ( + 'chromium.cache', + 'chromium.current_session', + 'firefox.cache', + 'firefox.session_restore', + 'google_chrome.cache', + 'google_chrome.session', + 'google_earth.temporary_files', + 'internet_explorer.temporary_files', + 'opera.cache', + 'opera.current_session', + 'safari.cache', + 'seamonkey.cache', + ), + 'System': ( + 'system.clipboard', + 'system.tmp', + 'winapp2_windows.jump_lists', + 'winapp2_windows.ms_search', + 'windows_explorer.run', + 'windows_explorer.search_history', + 'windows_explorer.thumbnails', + ), } if __name__ == '__main__': + try: + stay_awake() + clear_screen() + print_info('{}: System Diagnostics Tool\n'.format(KIT_NAME_FULL)) + ticket_number = get_ticket_number() + other_results = { + 'Error': { + 'CalledProcessError': 'Unknown Error', + 'FileNotFoundError': 'File not found', + }, + 'Warning': { + 'GenericRepair': 'Repaired', + 'UnsupportedOSError': 'Unsupported OS', + }} + if ENABLED_TICKET_NUMBERS: + print_info('Starting System Diagnostics for Ticket #{}\n'.format( + ticket_number)) + + # Sanitize Environment + print_info('Sanitizing Environment') + try_and_print(message='Running RKill...', + function=run_rkill, cs='Done', other_results=other_results) + try_and_print(message='Running TDSSKiller...', + function=run_tdsskiller, cs='Done', other_results=other_results) + + # Re-run if earlier process was stopped. + stay_awake() + + # Start diags + print_info('Starting Background Scans') + check_connection() + try_and_print(message='Running HitmanPro...', + function=run_hitmanpro, cs='Started', other_results=other_results) + try_and_print(message='Running Autoruns...', + function=run_autoruns, cs='Started', other_results=other_results) + + # OS Health Checks + print_info('OS Health Checks') + try_and_print( + message='CHKDSK ({SYSTEMDRIVE})...'.format(**global_vars['Env']), + function=run_chkdsk, other_results=other_results) + try_and_print(message='SFC scan...', + function=run_sfc_scan, other_results=other_results) + try_and_print(message='DISM CheckHealth...', + function=run_dism, other_results=other_results, repair=False) + + # Scan for supported browsers + print_info('Scanning for browsers') + scan_for_browsers() + + # Run BleachBit cleaners + print_info('BleachBit Cleanup') + for k, v in sorted(BLEACH_BIT_CLEANERS.items()): + try_and_print(message=' {}...'.format(k), + function=run_bleachbit, + cs='Done', other_results=other_results, + cleaners=v, preview=True) + + # Export system info + print_info('Backup System Information') + try_and_print(message='AIDA64 reports...', + function=run_aida64, cs='Done', other_results=other_results) + backup_browsers() + try_and_print(message='File listing...', + function=backup_file_list, cs='Done', other_results=other_results) + try_and_print(message='Power plans...', + function=backup_power_plans, cs='Done') + try_and_print(message='Product Keys...', + function=run_produkey, cs='Done', other_results=other_results) + try_and_print(message='Registry...', + function=backup_registry, cs='Done', other_results=other_results) + + # Summary + print_info('Summary') + try_and_print(message='Operating System:', + function=show_os_name, ns='Unknown', silent_function=False) + try_and_print(message='Activation:', + function=show_os_activation, ns='Unknown', silent_function=False) + try_and_print(message='Installed RAM:', + function=show_installed_ram, ns='Unknown', silent_function=False) + show_free_space() + try_and_print(message='Temp Size:', + function=show_temp_files_size, silent_function=False) + try_and_print(message='Installed Antivirus:', + function=get_installed_antivirus, ns='Unknown', + other_results=other_results, print_return=True) + try_and_print(message='Installed Office:', + function=get_installed_office, ns='Unknown', + other_results=other_results, print_return=True) + try_and_print(message='Product Keys:', + function=get_product_keys, ns='Unknown', print_return=True) + + # User data + print_info('User Data') try: - stay_awake() - clear_screen() - print_info('{}: System Diagnostics Tool\n'.format(KIT_NAME_FULL)) - ticket_number = get_ticket_number() - other_results = { - 'Error': { - 'CalledProcessError': 'Unknown Error', - 'FileNotFoundError': 'File not found', - }, - 'Warning': { - 'GenericRepair': 'Repaired', - 'UnsupportedOSError': 'Unsupported OS', - }} - if ENABLED_TICKET_NUMBERS: - print_info('Starting System Diagnostics for Ticket #{}\n'.format( - ticket_number)) + show_user_data_summary() + except Exception: + print_error(' Unknown error.') - # Sanitize Environment - print_info('Sanitizing Environment') - try_and_print(message='Running RKill...', - function=run_rkill, cs='Done', other_results=other_results) - try_and_print(message='Running TDSSKiller...', - function=run_tdsskiller, cs='Done', other_results=other_results) + # Done + print_standard('\nDone.') + pause('Press Enter to exit...') + exit_script() + except SystemExit: + pass + except: + major_exception() - # Re-run if earlier process was stopped. - stay_awake() - - # Start diags - print_info('Starting Background Scans') - check_connection() - try_and_print(message='Running HitmanPro...', - function=run_hitmanpro, cs='Started', other_results=other_results) - try_and_print(message='Running Autoruns...', - function=run_autoruns, cs='Started', other_results=other_results) - - # OS Health Checks - print_info('OS Health Checks') - try_and_print( - message='CHKDSK ({SYSTEMDRIVE})...'.format(**global_vars['Env']), - function=run_chkdsk, other_results=other_results) - try_and_print(message='SFC scan...', - function=run_sfc_scan, other_results=other_results) - try_and_print(message='DISM CheckHealth...', - function=run_dism, other_results=other_results, repair=False) - - # Scan for supported browsers - print_info('Scanning for browsers') - scan_for_browsers() - - # Run BleachBit cleaners - print_info('BleachBit Cleanup') - for k, v in sorted(BLEACH_BIT_CLEANERS.items()): - try_and_print(message=' {}...'.format(k), - function=run_bleachbit, - cs='Done', other_results=other_results, - cleaners=v, preview=True) - - # Export system info - print_info('Backup System Information') - try_and_print(message='AIDA64 reports...', - function=run_aida64, cs='Done', other_results=other_results) - backup_browsers() - try_and_print(message='File listing...', - function=backup_file_list, cs='Done', other_results=other_results) - try_and_print(message='Power plans...', - function=backup_power_plans, cs='Done') - try_and_print(message='Product Keys...', - function=run_produkey, cs='Done', other_results=other_results) - try_and_print(message='Registry...', - function=backup_registry, cs='Done', other_results=other_results) - - # Summary - print_info('Summary') - try_and_print(message='Operating System:', - function=show_os_name, ns='Unknown', silent_function=False) - try_and_print(message='Activation:', - function=show_os_activation, ns='Unknown', silent_function=False) - try_and_print(message='Installed RAM:', - function=show_installed_ram, ns='Unknown', silent_function=False) - show_free_space() - try_and_print(message='Temp Size:', - function=show_temp_files_size, silent_function=False) - try_and_print(message='Installed Antivirus:', - function=get_installed_antivirus, ns='Unknown', - other_results=other_results, print_return=True) - try_and_print(message='Installed Office:', - function=get_installed_office, ns='Unknown', - other_results=other_results, print_return=True) - try_and_print(message='Product Keys:', - function=get_product_keys, ns='Unknown', print_return=True) - - # User data - print_info('User Data') - try: - show_user_data_summary() - except Exception: - print_error(' Unknown error.') - - # Done - print_standard('\nDone.') - pause('Press Enter to exit...') - exit_script() - except SystemExit: - pass - except: - major_exception() - -# vim: sts=4 sw=4 ts=4 +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/transferred_keys.py b/.bin/Scripts/transferred_keys.py index b95ff3c9..3308844c 100644 --- a/.bin/Scripts/transferred_keys.py +++ b/.bin/Scripts/transferred_keys.py @@ -12,17 +12,19 @@ os.system('title {}: Transferred Key Finder'.format(KIT_NAME_FULL)) set_log_file('Transferred Keys.log') if __name__ == '__main__': - try: - stay_awake() - clear_screen() - print_info('{}: Transferred Key Finder\n'.format(KIT_NAME_FULL)) - try_and_print(message='Searching for keys...', - function=list_clientdir_keys, print_return=True) + try: + stay_awake() + clear_screen() + print_info('{}: Transferred Key Finder\n'.format(KIT_NAME_FULL)) + try_and_print(message='Searching for keys...', + function=list_clientdir_keys, print_return=True) - # Done - print_standard('\nDone.') - exit_script() - except SystemExit: - pass - except: - major_exception() + # Done + print_standard('\nDone.') + exit_script() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/update_kit.py b/.bin/Scripts/update_kit.py index 67949d93..e02acc73 100644 --- a/.bin/Scripts/update_kit.py +++ b/.bin/Scripts/update_kit.py @@ -11,135 +11,137 @@ init_global_vars() os.system('title {}: Kit Update Tool'.format(KIT_NAME_FULL)) if __name__ == '__main__': - try: - clear_screen() - print_info('{}: Kit Update Tool\n'.format(KIT_NAME_FULL)) - other_results = { - 'Error': { - 'CalledProcessError': 'Unknown Error', - }} + try: + clear_screen() + print_info('{}: Kit Update Tool\n'.format(KIT_NAME_FULL)) + other_results = { + 'Error': { + 'CalledProcessError': 'Unknown Error', + }} - ## Prep ## - update_sdio = ask('Update SDI Origin?') + ## Prep ## + update_sdio = ask('Update SDI Origin?') - ## Download ## - print_success('Downloading tools') + ## Download ## + print_success('Downloading tools') - # Data Recovery - print_info(' Data Recovery') - try_and_print(message='TestDisk / PhotoRec...', function=update_testdisk, other_results=other_results, width=40) + # Data Recovery + print_info(' Data Recovery') + try_and_print(message='TestDisk / PhotoRec...', function=update_testdisk, other_results=other_results, width=40) - # Data Transfers - print_info(' Data Transfers') - try_and_print(message='FastCopy...', function=update_fastcopy, other_results=other_results, width=40) - try_and_print(message='wimlib...', function=update_wimlib, other_results=other_results, width=40) - try_and_print(message='XYplorer...', function=update_xyplorer, other_results=other_results, width=40) + # Data Transfers + print_info(' Data Transfers') + try_and_print(message='FastCopy...', function=update_fastcopy, other_results=other_results, width=40) + try_and_print(message='wimlib...', function=update_wimlib, other_results=other_results, width=40) + try_and_print(message='XYplorer...', function=update_xyplorer, other_results=other_results, width=40) - # Diagnostics - print_info(' Diagnostics') - try_and_print(message='AIDA64...', function=update_aida64, other_results=other_results, width=40) - try_and_print(message='Autoruns...', function=update_autoruns, other_results=other_results, width=40) - try_and_print(message='BleachBit...', function=update_bleachbit, other_results=other_results, width=40) - try_and_print(message='Blue Screen View...', function=update_bluescreenview, other_results=other_results, width=40) - try_and_print(message='ERUNT...', function=update_erunt, other_results=other_results, width=40) - try_and_print(message='Hitman Pro...', function=update_hitmanpro, other_results=other_results, width=40) - try_and_print(message='HWiNFO...', function=update_hwinfo, other_results=other_results, width=40) - try_and_print(message='NirCmd...', function=update_nircmd, other_results=other_results, width=40) - try_and_print(message='ProduKey...', function=update_produkey, other_results=other_results, width=40) + # Diagnostics + print_info(' Diagnostics') + try_and_print(message='AIDA64...', function=update_aida64, other_results=other_results, width=40) + try_and_print(message='Autoruns...', function=update_autoruns, other_results=other_results, width=40) + try_and_print(message='BleachBit...', function=update_bleachbit, other_results=other_results, width=40) + try_and_print(message='Blue Screen View...', function=update_bluescreenview, other_results=other_results, width=40) + try_and_print(message='ERUNT...', function=update_erunt, other_results=other_results, width=40) + try_and_print(message='Hitman Pro...', function=update_hitmanpro, other_results=other_results, width=40) + try_and_print(message='HWiNFO...', function=update_hwinfo, other_results=other_results, width=40) + try_and_print(message='NirCmd...', function=update_nircmd, other_results=other_results, width=40) + try_and_print(message='ProduKey...', function=update_produkey, other_results=other_results, width=40) - # Drivers - print_info(' Drivers') - try_and_print(message='Intel RST...', function=update_intel_rst, other_results=other_results, width=40) - try_and_print(message='Intel SSD Toolbox...', function=update_intel_ssd_toolbox, other_results=other_results, width=40) - try_and_print(message='Samsing Magician...', function=update_samsung_magician, other_results=other_results, width=40) - if update_sdio: - try_and_print(message='Snappy Driver Installer Origin...', function=update_sdi_origin, other_results=other_results, width=40) + # Drivers + print_info(' Drivers') + try_and_print(message='Intel RST...', function=update_intel_rst, other_results=other_results, width=40) + try_and_print(message='Intel SSD Toolbox...', function=update_intel_ssd_toolbox, other_results=other_results, width=40) + try_and_print(message='Samsing Magician...', function=update_samsung_magician, other_results=other_results, width=40) + if update_sdio: + try_and_print(message='Snappy Driver Installer Origin...', function=update_sdi_origin, other_results=other_results, width=40) - # Installers - print_info(' Installers') - try_and_print(message='Adobe Reader DC...', function=update_adobe_reader_dc, other_results=other_results, width=40) - try_and_print(message='Macs Fan Control...', function=update_macs_fan_control, other_results=other_results, width=40) - try_and_print(message='MS Office...', function=update_office, other_results=other_results, width=40) - try_and_print(message='Visual C++ Runtimes...', function=update_vcredists, other_results=other_results, width=40) - update_all_ninite(other_results=other_results, width=40) + # Installers + print_info(' Installers') + try_and_print(message='Adobe Reader DC...', function=update_adobe_reader_dc, other_results=other_results, width=40) + try_and_print(message='Macs Fan Control...', function=update_macs_fan_control, other_results=other_results, width=40) + try_and_print(message='MS Office...', function=update_office, other_results=other_results, width=40) + try_and_print(message='Visual C++ Runtimes...', function=update_vcredists, other_results=other_results, width=40) + update_all_ninite(other_results=other_results, width=40) - # Misc - print_info(' Misc') - try_and_print(message='Caffeine...', function=update_caffeine, other_results=other_results, width=40) - try_and_print(message='Classic Start Skin...', function=update_classic_start_skin, other_results=other_results, width=40) - try_and_print(message='Du...', function=update_du, other_results=other_results, width=40) - try_and_print(message='Everything...', function=update_everything, other_results=other_results, width=40) - try_and_print(message='Firefox Extensions...', function=update_firefox_ublock_origin, other_results=other_results, width=40) - try_and_print(message='PuTTY...', function=update_putty, other_results=other_results, width=40) - try_and_print(message='Notepad++...', function=update_notepadplusplus, other_results=other_results, width=40) - try_and_print(message='WizTree...', function=update_wiztree, other_results=other_results, width=40) - try_and_print(message='XMPlay...', function=update_xmplay, other_results=other_results, width=40) + # Misc + print_info(' Misc') + try_and_print(message='Caffeine...', function=update_caffeine, other_results=other_results, width=40) + try_and_print(message='Classic Start Skin...', function=update_classic_start_skin, other_results=other_results, width=40) + try_and_print(message='Du...', function=update_du, other_results=other_results, width=40) + try_and_print(message='Everything...', function=update_everything, other_results=other_results, width=40) + try_and_print(message='Firefox Extensions...', function=update_firefox_ublock_origin, other_results=other_results, width=40) + try_and_print(message='PuTTY...', function=update_putty, other_results=other_results, width=40) + try_and_print(message='Notepad++...', function=update_notepadplusplus, other_results=other_results, width=40) + try_and_print(message='WizTree...', function=update_wiztree, other_results=other_results, width=40) + try_and_print(message='XMPlay...', function=update_xmplay, other_results=other_results, width=40) - # Repairs - print_info(' Repairs') - try_and_print(message='AdwCleaner...', function=update_adwcleaner, other_results=other_results, width=40) - try_and_print(message='KVRT...', function=update_kvrt, other_results=other_results, width=40) - try_and_print(message='RKill...', function=update_rkill, other_results=other_results, width=40) - try_and_print(message='TDSS Killer...', function=update_tdsskiller, other_results=other_results, width=40) + # Repairs + print_info(' Repairs') + try_and_print(message='AdwCleaner...', function=update_adwcleaner, other_results=other_results, width=40) + try_and_print(message='KVRT...', function=update_kvrt, other_results=other_results, width=40) + try_and_print(message='RKill...', function=update_rkill, other_results=other_results, width=40) + try_and_print(message='TDSS Killer...', function=update_tdsskiller, other_results=other_results, width=40) - # Uninstallers - print_info(' Uninstallers') - try_and_print(message='IObit Uninstaller...', function=update_iobit_uninstaller, other_results=other_results, width=40) + # Uninstallers + print_info(' Uninstallers') + try_and_print(message='IObit Uninstaller...', function=update_iobit_uninstaller, other_results=other_results, width=40) - ## Review ## - print_standard('Please review the results and download/extract any missing items to .cbin') - pause('Press Enter to compress the .cbin items') + ## Review ## + print_standard('Please review the results and download/extract any missing items to .cbin') + pause('Press Enter to compress the .cbin items') - ## Compress ## - print_success('Compressing tools') - print_info(' _Drivers') - for item in os.scandir(r'{}\_Drivers'.format(global_vars['CBinDir'])): - if not re.search(r'^(_Drivers|.*7z)$', item.name, re.IGNORECASE): - try_and_print( - message='{}...'.format(item.name), - function=compress_and_remove_item, - other_results = other_results, - width=40, - item = item) - print_info(' .cbin') - for item in os.scandir(global_vars['CBinDir']): - if not re.search(r'^(_Drivers|_include|.*7z)$', item.name, re.IGNORECASE): - try_and_print( - message='{}...'.format(item.name), - function=compress_and_remove_item, - other_results = other_results, - width=40, - item = item) + ## Compress ## + print_success('Compressing tools') + print_info(' _Drivers') + for item in os.scandir(r'{}\_Drivers'.format(global_vars['CBinDir'])): + if not re.search(r'^(_Drivers|.*7z)$', item.name, re.IGNORECASE): + try_and_print( + message='{}...'.format(item.name), + function=compress_and_remove_item, + other_results = other_results, + width=40, + item = item) + print_info(' .cbin') + for item in os.scandir(global_vars['CBinDir']): + if not re.search(r'^(_Drivers|_include|.*7z)$', item.name, re.IGNORECASE): + try_and_print( + message='{}...'.format(item.name), + function=compress_and_remove_item, + other_results = other_results, + width=40, + item = item) - ## Search for network Office/QuickBooks installers & add to LAUNCHERS - print_success('Scanning for network installers') - scan_for_net_installers(OFFICE_SERVER, 'Office', min_year=2010) - scan_for_net_installers(QUICKBOOKS_SERVER, 'QuickBooks', min_year=2015) + ## Search for network Office/QuickBooks installers & add to LAUNCHERS + print_success('Scanning for network installers') + scan_for_net_installers(OFFICE_SERVER, 'Office', min_year=2010) + scan_for_net_installers(QUICKBOOKS_SERVER, 'QuickBooks', min_year=2015) - ## Generate Launchers - print_success('Generating launchers') - for section in sorted(LAUNCHERS.keys()): - print_info(' {}'.format(section)) - for name, options in sorted(LAUNCHERS[section].items()): - try_and_print(message=name, function=generate_launcher, - section=section, name=name, options=options, - other_results=other_results, width=40) + ## Generate Launchers + print_success('Generating launchers') + for section in sorted(LAUNCHERS.keys()): + print_info(' {}'.format(section)) + for name, options in sorted(LAUNCHERS[section].items()): + try_and_print(message=name, function=generate_launcher, + section=section, name=name, options=options, + other_results=other_results, width=40) - # Rename "Copy WizardKit.cmd" (if necessary) - source = r'{}\Scripts\Copy WizardKit.cmd'.format(global_vars['BinDir']) - dest = r'{}\Copy {}.cmd'.format(global_vars['BaseDir'], KIT_NAME_FULL) - if os.path.exists(source): - try: - shutil.move(source, dest) - except Exception: - print_error(' Failed to rename "{}.cmd" to "{}.cmd"'.format( - 'Copy WizardKit', KIT_NAME_FULL)) + # Rename "Copy WizardKit.cmd" (if necessary) + source = r'{}\Scripts\Copy WizardKit.cmd'.format(global_vars['BinDir']) + dest = r'{}\Copy {}.cmd'.format(global_vars['BaseDir'], KIT_NAME_FULL) + if os.path.exists(source): + try: + shutil.move(source, dest) + except Exception: + print_error(' Failed to rename "{}.cmd" to "{}.cmd"'.format( + 'Copy WizardKit', KIT_NAME_FULL)) - # Done - print_standard('\nDone.') - pause("Press Enter to exit...") - exit_script() - except SystemExit: - pass - except: - major_exception() + # Done + print_standard('\nDone.') + pause("Press Enter to exit...") + exit_script() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/user_checklist.py b/.bin/Scripts/user_checklist.py index fd348dec..b57e8b29 100644 --- a/.bin/Scripts/user_checklist.py +++ b/.bin/Scripts/user_checklist.py @@ -14,74 +14,74 @@ os.system('title {}: User Checklist Tool'.format(KIT_NAME_FULL)) set_log_file('User Checklist ({USERNAME}).log'.format(**global_vars['Env'])) if __name__ == '__main__': - try: - stay_awake() - clear_screen() - print_info('{}: User Checklist\n'.format(KIT_NAME_FULL)) - other_results = { - 'Warning': { - 'NotInstalledError': 'Not installed', - 'NoProfilesError': 'No profiles found', - }} - answer_config_browsers = ask('Install adblock?') - if answer_config_browsers: - answer_reset_browsers = ask( - 'Reset browsers to safe defaults first?') - if global_vars['OS']['Version'] == '10': - answer_config_classicshell = ask('Configure ClassicShell?') - answer_config_explorer_user = ask('Configure Explorer?') + try: + stay_awake() + clear_screen() + print_info('{}: User Checklist\n'.format(KIT_NAME_FULL)) + other_results = { + 'Warning': { + 'NotInstalledError': 'Not installed', + 'NoProfilesError': 'No profiles found', + }} + answer_config_browsers = ask('Install adblock?') + if answer_config_browsers: + answer_reset_browsers = ask( + 'Reset browsers to safe defaults first?') + if global_vars['OS']['Version'] == '10': + answer_config_classicshell = ask('Configure ClassicShell?') + answer_config_explorer_user = ask('Configure Explorer?') - # Cleanup - print_info('Cleanup') - try_and_print(message='Desktop...', - function=cleanup_desktop, cs='Done') + # Cleanup + print_info('Cleanup') + try_and_print(message='Desktop...', + function=cleanup_desktop, cs='Done') - # Scan for supported browsers - print_info('Scanning for browsers') - scan_for_browsers() + # Scan for supported browsers + print_info('Scanning for browsers') + scan_for_browsers() - # Homepages - print_info('Current homepages') - list_homepages() + # Homepages + print_info('Current homepages') + list_homepages() - # Backup - print_info('Backing up browsers') - backup_browsers() + # Backup + print_info('Backing up browsers') + backup_browsers() - # Reset - if answer_config_browsers and answer_reset_browsers: - print_info('Resetting browsers') - reset_browsers() + # Reset + if answer_config_browsers and answer_reset_browsers: + print_info('Resetting browsers') + reset_browsers() - # Configure - print_info('Configuring programs') - if answer_config_browsers: - install_adblock() - if global_vars['OS']['Version'] == '10': - if answer_config_classicshell: - try_and_print(message='ClassicStart...', - function=config_classicstart, cs='Done') - if answer_config_explorer_user: - try_and_print(message='Explorer...', - function=config_explorer_user, cs='Done') - if (not answer_config_browsers - and not answer_config_classicshell - and not answer_config_explorer_user): - print_warning(' Skipped') - else: - if not answer_config_browsers: - print_warning(' Skipped') + # Configure + print_info('Configuring programs') + if answer_config_browsers: + install_adblock() + if global_vars['OS']['Version'] == '10': + if answer_config_classicshell: + try_and_print(message='ClassicStart...', + function=config_classicstart, cs='Done') + if answer_config_explorer_user: + try_and_print(message='Explorer...', + function=config_explorer_user, cs='Done') + if (not answer_config_browsers + and not answer_config_classicshell + and not answer_config_explorer_user): + print_warning(' Skipped') + else: + if not answer_config_browsers: + print_warning(' Skipped') - # Run speedtest - popen_program(['start', '', 'https://fast.com'], shell=True) + # Run speedtest + popen_program(['start', '', 'https://fast.com'], shell=True) - # Done - print_standard('\nDone.') - pause('Press Enter to exit...') - exit_script() - except SystemExit: - pass - except: - major_exception() + # Done + print_standard('\nDone.') + pause('Press Enter to exit...') + exit_script() + except SystemExit: + pass + except: + major_exception() -# vim: sts=4 sw=4 ts=4 +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/user_data_transfer.py b/.bin/Scripts/user_data_transfer.py index 981e235a..1fa06256 100644 --- a/.bin/Scripts/user_data_transfer.py +++ b/.bin/Scripts/user_data_transfer.py @@ -13,54 +13,56 @@ os.system('title {}: User Data Transfer Tool'.format(KIT_NAME_FULL)) set_log_file('User Data Transfer.log') if __name__ == '__main__': - try: - # Prep - stay_awake() - clear_screen() - print_info('{}: User Data Transfer Tool\n'.format(KIT_NAME_FULL)) + try: + # Prep + stay_awake() + clear_screen() + print_info('{}: User Data Transfer Tool\n'.format(KIT_NAME_FULL)) - # Get backup name prefix - ticket_number = get_ticket_number() - if ENABLED_TICKET_NUMBERS: - backup_prefix = ticket_number - else: - backup_prefix = get_simple_string(prompt='Enter backup name prefix') - backup_prefix = backup_prefix.replace(' ', '_') + # Get backup name prefix + ticket_number = get_ticket_number() + if ENABLED_TICKET_NUMBERS: + backup_prefix = ticket_number + else: + backup_prefix = get_simple_string(prompt='Enter backup name prefix') + backup_prefix = backup_prefix.replace(' ', '_') - # Set destination - folder_path = r'{}\Transfer'.format(KIT_NAME_SHORT) - dest = select_destination(folder_path=folder_path, - prompt='Which disk are we transferring to?') + # Set destination + folder_path = r'{}\Transfer'.format(KIT_NAME_SHORT) + dest = select_destination(folder_path=folder_path, + prompt='Which disk are we transferring to?') - # Set source items - source = select_source(backup_prefix) - items = scan_source(source, dest) + # Set source items + source = select_source(backup_prefix) + items = scan_source(source, dest) - # Transfer - clear_screen() - print_info('Transfer Details:\n') - if ENABLED_TICKET_NUMBERS: - show_data('Ticket:', ticket_number) - show_data('Source:', source.path) - show_data('Destination:', dest) + # Transfer + clear_screen() + print_info('Transfer Details:\n') + if ENABLED_TICKET_NUMBERS: + show_data('Ticket:', ticket_number) + show_data('Source:', source.path) + show_data('Destination:', dest) - if (not ask('Proceed with transfer?')): - umount_backup_shares() - abort() + if (not ask('Proceed with transfer?')): + umount_backup_shares() + abort() - print_info('Transferring Data') - transfer_source(source, dest, items) - try_and_print(message='Removing extra files...', - function=cleanup_transfer, cs='Done', dest_path=dest) - umount_backup_shares() + print_info('Transferring Data') + transfer_source(source, dest, items) + try_and_print(message='Removing extra files...', + function=cleanup_transfer, cs='Done', dest_path=dest) + umount_backup_shares() - # Done - try_and_print(message='Running KVRT...', - function=run_kvrt, cs='Started') - print_standard('\nDone.') - pause("Press Enter to exit...") - exit_script() - except SystemExit: - pass - except: - major_exception() + # Done + try_and_print(message='Running KVRT...', + function=run_kvrt, cs='Started') + print_standard('\nDone.') + pause("Press Enter to exit...") + exit_script() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/winpe_root_menu.py b/.bin/Scripts/winpe_root_menu.py index 743d987b..5a1f0f8b 100644 --- a/.bin/Scripts/winpe_root_menu.py +++ b/.bin/Scripts/winpe_root_menu.py @@ -14,9 +14,11 @@ set_title('{}: Root Menu'.format(KIT_NAME_FULL)) set_log_file('WinPE.log') if __name__ == '__main__': - try: - menu_root() - except SystemExit: - pass - except: - major_exception() + try: + menu_root() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 From 6df88ec021227c970adeeedd60d6ff3f5b238a90 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 22:42:42 -0700 Subject: [PATCH 192/265] Updated settings files --- .bin/Scripts/settings/launchers.py | 1118 ++++++++++++----------- .bin/Scripts/settings/main.py | 106 +-- .bin/Scripts/settings/music.py | 128 +-- .bin/Scripts/settings/sources.py | 386 ++++---- .bin/Scripts/settings/tools.py | 104 +-- .bin/Scripts/settings/windows_builds.py | 368 ++++---- 6 files changed, 1110 insertions(+), 1100 deletions(-) diff --git a/.bin/Scripts/settings/launchers.py b/.bin/Scripts/settings/launchers.py index 5135ec08..3b378aca 100644 --- a/.bin/Scripts/settings/launchers.py +++ b/.bin/Scripts/settings/launchers.py @@ -1,563 +1,565 @@ # Wizard Kit: Settings - Launchers LAUNCHERS = { - r'(Root)': { - 'Activate Windows': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'activate.py', - 'L_ELEV': 'True', - }, - 'System Checklist': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'system_checklist.py', - 'L_ELEV': 'True', - }, - 'System Diagnostics': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'system_diagnostics.py', - 'L_ELEV': 'True', - }, - 'User Checklist': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'user_checklist.py', - }, - }, - r'Data Recovery': { - 'PhotoRec (CLI)': { - 'L_TYPE': 'Executable', - 'L_PATH': 'TestDisk', - 'L_ITEM': 'photorec_win.exe', - 'L_ELEV': 'True', - 'L__CLI': 'True', - }, - 'PhotoRec': { - 'L_TYPE': 'Executable', - 'L_PATH': 'TestDisk', - 'L_ITEM': 'qphotorec_win.exe', - 'L_ELEV': 'True', - }, - 'TestDisk': { - 'L_TYPE': 'Executable', - 'L_PATH': 'TestDisk', - 'L_ITEM': 'testdisk_win.exe', - 'L_ELEV': 'True', - 'L__CLI': 'True', - }, - }, - r'Data Transfers': { - 'FastCopy (as ADMIN)': { - 'L_TYPE': 'Executable', - 'L_PATH': 'FastCopy', - 'L_ITEM': 'FastCopy.exe', - 'L_ARGS': ( - r' /logfile=%log_dir%\Tools\FastCopy.log' - r' /cmd=noexist_only' - r' /utf8' - r' /skip_empty_dir' - r' /linkdest' - r' /exclude=' - r'$RECYCLE.BIN;' - r'$Recycle.Bin;' - r'.AppleDB;' - r'.AppleDesktop;' - r'.AppleDouble;' - r'.com.apple.timemachine.supported;' - r'.dbfseventsd;' - r'.DocumentRevisions-V100*;' - r'.DS_Store;' - r'.fseventsd;' - r'.PKInstallSandboxManager;' - r'.Spotlight*;' - r'.SymAV*;' - r'.symSchedScanLockxz;' - r'.TemporaryItems;' - r'.Trash*;' - r'.vol;' - r'.VolumeIcon.icns;' - r'desktop.ini;' - r'Desktop?DB;' - r'Desktop?DF;' - r'hiberfil.sys;' - r'lost+found;' - r'Network?Trash?Folder;' - r'pagefile.sys;' - r'Recycled;' - r'RECYCLER;' - r'System?Volume?Information;' - r'Temporary?Items;' - r'Thumbs.db' - r' /to=%client_dir%\Transfer_%iso_date%\ ' - ), - 'L_ELEV': 'True', - 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Logs /Transfer', - ], - }, - 'FastCopy': { - 'L_TYPE': 'Executable', - 'L_PATH': 'FastCopy', - 'L_ITEM': 'FastCopy.exe', - 'L_ARGS': ( - r' /logfile=%log_dir%\Tools\FastCopy.log' - r' /cmd=noexist_only' - r' /utf8' - r' /skip_empty_dir' - r' /linkdest' - r' /exclude=' - r'$RECYCLE.BIN;' - r'$Recycle.Bin;' - r'.AppleDB;' - r'.AppleDesktop;' - r'.AppleDouble;' - r'.com.apple.timemachine.supported;' - r'.dbfseventsd;' - r'.DocumentRevisions-V100*;' - r'.DS_Store;' - r'.fseventsd;' - r'.PKInstallSandboxManager;' - r'.Spotlight*;' - r'.SymAV*;' - r'.symSchedScanLockxz;' - r'.TemporaryItems;' - r'.Trash*;' - r'.vol;' - r'.VolumeIcon.icns;' - r'desktop.ini;' - r'Desktop?DB;' - r'Desktop?DF;' - r'hiberfil.sys;' - r'lost+found;' - r'Network?Trash?Folder;' - r'pagefile.sys;' - r'Recycled;' - r'RECYCLER;' - r'System?Volume?Information;' - r'Temporary?Items;' - r'Thumbs.db' - r' /to=%client_dir%\Transfer_%iso_date%\ ' - ), - 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Logs /Transfer', - ], - }, - 'KVRT': { - 'L_TYPE': 'Executable', - 'L_PATH': 'KVRT', - 'L_ITEM': 'KVRT.exe', - 'L_ARGS': ( - r' -accepteula' - r' -d %q_dir%' - r' -processlevel 3' - r' -dontcryptsupportinfo' - r' -fixednames' - ), - 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Quarantine', - r'set "q_dir=%client_dir%\Quarantine\KVRT"', - r'mkdir "%q_dir%">nul 2>&1', - ], - }, - 'Transferred Keys': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'transferred_keys.py', - 'L_ELEV': 'True', - }, - 'User Data Transfer': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'user_data_transfer.py', - 'L_ELEV': 'True', - }, - 'XYplorer (as ADMIN)': { - 'L_TYPE': 'Executable', - 'L_PATH': 'XYplorerFree', - 'L_ITEM': 'XYplorerFree.exe', - 'L_ARGS': r'/exp /win=max %userprofile%', - 'L_ELEV': 'True', - }, - 'XYplorer': { - 'L_TYPE': 'Executable', - 'L_PATH': 'XYplorerFree', - 'L_ITEM': 'XYplorerFree.exe', - 'L_ARGS': r'/exp /win=max %userprofile%', - }, - }, - r'Diagnostics': { - 'HWiNFO': { - 'L_TYPE': 'Executable', - 'L_PATH': 'HWiNFO', - 'L_ITEM': 'HWiNFO.exe', - 'Extra Code': [ - r'for %%a in (32 64) do (', - r' copy /y "%bin%\HWiNFO\general.ini" "%bin%\HWiNFO\HWiNFO%%a.ini"', - r' (echo SensorsOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', - r' (echo SummaryOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', - r')', - ], - }, - 'ProduKey': { - 'L_TYPE': 'Executable', - 'L_PATH': 'ProduKey', - 'L_ITEM': 'ProduKey.exe', - 'L_ELEV': 'True', - 'Extra Code': [ - r'if exist "%bin%\ProduKey" (', - r' del "%bin%\ProduKey\ProduKey.cfg" 2>nul', - r' del "%bin%\ProduKey\ProduKey64.cfg" 2>nul', - r')', - ], - }, - }, - r'Diagnostics\Extras': { - 'AIDA64': { - 'L_TYPE': 'Executable', - 'L_PATH': 'AIDA64', - 'L_ITEM': 'aida64.exe', - }, - 'Autoruns (with VirusTotal Scan)': { - 'L_TYPE': 'Executable', - 'L_PATH': 'Autoruns', - 'L_ITEM': 'Autoruns.exe', - 'L_ARGS': '-e', - 'Extra Code': [ - r'reg add HKCU\Software\Sysinternals\AutoRuns /v checkvirustotal /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v EulaAccepted /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v shownomicrosoft /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v shownowindows /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v showonlyvirustotal /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v submitvirustotal /t REG_DWORD /d 0 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v verifysignatures /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns\SigCheck /v EulaAccepted /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns\Streams /v EulaAccepted /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns\VirusTotal /v VirusTotalTermsAccepted /t REG_DWORD /d 1 /f >nul', - ], - }, - 'BleachBit': { - 'L_TYPE': 'Executable', - 'L_PATH': 'BleachBit', - 'L_ITEM': 'bleachbit.exe', - }, - 'BlueScreenView': { - 'L_TYPE': 'Executable', - 'L_PATH': 'BlueScreenView', - 'L_ITEM': 'BlueScreenView.exe', - }, - 'ERUNT': { - 'L_TYPE': 'Executable', - 'L_PATH': 'erunt', - 'L_ITEM': 'ERUNT.EXE', - 'L_ARGS': '%client_dir%\Backups\Registry\%iso_date% sysreg curuser otherusers', - 'L_ELEV': 'True', - 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Logs', - ], - }, - 'HitmanPro': { - 'L_TYPE': 'Executable', - 'L_PATH': 'HitmanPro', - 'L_ITEM': 'HitmanPro.exe', - 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Logs', - ], - }, - 'HWiNFO (Sensors)': { - 'L_TYPE': 'Executable', - 'L_PATH': 'HWiNFO', - 'L_ITEM': 'HWiNFO.exe', - 'Extra Code': [ - r'for %%a in (32 64) do (', - r' copy /y "%bin%\HWiNFO\general.ini" "%bin%\HWiNFO\HWiNFO%%a.ini"', - r' (echo SensorsOnly=1)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', - r' (echo SummaryOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', - r')', - ], - }, - }, - r'Drivers': { - 'Intel RST (Current Release)': { - 'L_TYPE': 'Executable', - 'L_PATH': '_Drivers\Intel RST', - 'L_ITEM': 'SetupRST_16.5.exe', - 'L_7ZIP': 'SetupRST_16.5.exe', - }, - 'Intel RST (Previous Releases)': { - 'L_TYPE': 'Folder', - 'L_PATH': '_Drivers\Intel RST', - 'L_ITEM': '.', - 'L_NCMD': 'True', - }, - 'Intel SSD Toolbox': { - 'L_TYPE': 'Executable', - 'L_PATH': r'_Drivers\Intel SSD Toolbox', - 'L_ITEM': 'Intel SSD Toolbox.exe', - }, - 'Samsing Magician': { - 'L_TYPE': 'Executable', - 'L_PATH': r'_Drivers\Samsung Magician', - 'L_ITEM': 'Samsung Magician.exe', - }, - 'Snappy Driver Installer Origin': { - 'L_TYPE': 'Executable', - 'L_PATH': '_Drivers\SDIO', - 'L_ITEM': 'SDIO.exe', - }, - }, - r'Drivers\Extras': { - 'Acer': { - 'L_TYPE': 'Executable', - 'L_PATH': 'HWiNFO', - 'L_ITEM': 'HWiNFO.exe', - 'Extra Code': [ - r'for %%a in (32 64) do (', - r' copy /y "%bin%\HWiNFO\general.ini" "%bin%\HWiNFO\HWiNFO%%a.ini"', - r' (echo SensorsOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', - r' (echo SummaryOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', - r')', - r'start "" "http://us.acer.com/ac/en/US/content/drivers"', - ], - }, - 'Lenovo': { - 'L_TYPE': 'Executable', - 'L_PATH': 'HWiNFO', - 'L_ITEM': 'HWiNFO.exe', - 'Extra Code': [ - r'for %%a in (32 64) do (', - r' copy /y "%bin%\HWiNFO\general.ini" "%bin%\HWiNFO\HWiNFO%%a.ini"', - r' (echo SensorsOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', - r' (echo SummaryOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', - r')', - r'start "" "https://pcsupport.lenovo.com/us/en/"', - ], - }, - 'Toshiba': { - 'L_TYPE': 'Executable', - 'L_PATH': 'HWiNFO', - 'L_ITEM': 'HWiNFO.exe', - 'Extra Code': [ - r'for %%a in (32 64) do (', - r' copy /y "%bin%\HWiNFO\general.ini" "%bin%\HWiNFO\HWiNFO%%a.ini"', - r' (echo SensorsOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', - r' (echo SummaryOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', - r')', - r'start "" "http://support.toshiba.com/drivers"', - ], - }, - }, - r'Installers': { - 'SW Bundle': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'install_sw_bundle.py', - 'L_ELEV': 'True', - }, - }, - r'Installers\Extras\Office\2016': { - 'Home and Business 2016 (x32)': { - 'L_TYPE': 'Office', - 'L_PATH': '2016', - 'L_ITEM': 'hb_32.xml', - 'L_NCMD': 'True', - }, - 'Home and Business 2016 (x64)': { - 'L_TYPE': 'Office', - 'L_PATH': '2016', - 'L_ITEM': 'hb_64.xml', - 'L_NCMD': 'True', - }, - 'Home and Student 2016 (x32)': { - 'L_TYPE': 'Office', - 'L_PATH': '2016', - 'L_ITEM': 'hs_32.xml', - 'L_NCMD': 'True', - }, - 'Home and Student 2016 (x64)': { - 'L_TYPE': 'Office', - 'L_PATH': '2016', - 'L_ITEM': 'hs_64.xml', - 'L_NCMD': 'True', - }, - 'Office 365 2016 (x32)': { - 'L_TYPE': 'Office', - 'L_PATH': '2016', - 'L_ITEM': '365_32.xml', - 'L_NCMD': 'True', - }, - 'Office 365 2016 (x64)': { - 'L_TYPE': 'Office', - 'L_PATH': '2016', - 'L_ITEM': '365_64.xml', - 'L_NCMD': 'True', - }, - }, - r'Installers\Extras\Runtimes': { - 'Visual C++ Runtimes': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'install_vcredists.py', - 'L_ELEV': 'True', - }, - }, - r'Misc': { - 'Cleanup CBS Temp Files': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'cbs_fix.py', - 'L_ELEV': 'True', - }, - 'ConEmu (as ADMIN)': { - 'L_TYPE': 'Executable', - 'L_PATH': 'ConEmu', - 'L_ITEM': 'ConEmu.exe', - 'L_ELEV': 'True', - }, - 'ConEmu': { - 'L_TYPE': 'Executable', - 'L_PATH': 'ConEmu', - 'L_ITEM': 'ConEmu.exe', - }, - 'Enter SafeMode': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'safemode_enter.py', - 'L_ELEV': 'True', - }, - 'Everything': { - 'L_TYPE': 'Executable', - 'L_PATH': 'Everything', - 'L_ITEM': 'Everything.exe', - 'L_ARGS': '-nodb', - 'L_ELEV': 'True', - }, - 'Exit SafeMode': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'safemode_exit.py', - 'L_ELEV': 'True', - }, - 'Notepad++': { - 'L_TYPE': 'Executable', - 'L_PATH': 'notepadplusplus', - 'L_ITEM': 'notepadplusplus.exe', - }, - 'PuTTY': { - 'L_TYPE': 'Executable', - 'L_PATH': 'PuTTY', - 'L_ITEM': 'PUTTY.EXE', - }, - 'WizTree': { - 'L_TYPE': 'Executable', - 'L_PATH': 'WizTree', - 'L_ITEM': 'WizTree.exe', - 'L_ELEV': 'True', - }, - 'XMPlay': { - 'L_TYPE': 'Executable', - 'L_PATH': 'XMPlay', - 'L_ITEM': 'xmplay.exe', - 'L_ARGS': '"%bin%\XMPlay\music.7z"', - }, - }, - r'Repairs': { - 'AdwCleaner': { - 'L_TYPE': 'Executable', - 'L_PATH': 'AdwCleaner', - 'L_ITEM': 'AdwCleaner.exe', - }, - 'Autoruns': { - 'L_TYPE': 'Executable', - 'L_PATH': 'Autoruns', - 'L_ITEM': 'Autoruns.exe', - 'L_ARGS': '-e', - 'Extra Code': [ - r'reg add HKCU\Software\Sysinternals\AutoRuns /v checkvirustotal /t REG_DWORD /d 0 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v EulaAccepted /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v shownomicrosoft /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v shownowindows /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v showonlyvirustotal /t REG_DWORD /d 0 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v submitvirustotal /t REG_DWORD /d 0 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v verifysignatures /t REG_DWORD /d 0 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns\SigCheck /v EulaAccepted /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns\Streams /v EulaAccepted /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns\VirusTotal /v VirusTotalTermsAccepted /t REG_DWORD /d 1 /f >nul', - ], - }, - 'CHKDSK': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'check_disk.py', - 'L_ELEV': 'True', - }, - 'DISM': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'dism.py', - 'L_ELEV': 'True', - }, - 'KVRT': { - 'L_TYPE': 'Executable', - 'L_PATH': 'KVRT', - 'L_ITEM': 'KVRT.exe', - 'L_ARGS': ( - r' -accepteula' - r' -d %q_dir%' - r' -processlevel 3' - r' -dontcryptsupportinfo' - r' -fixednames' - ), - 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Quarantine', - r'set "q_dir=%client_dir%\Quarantine\KVRT"', - r'mkdir "%q_dir%">nul 2>&1', - ], - }, - 'RKill': { - 'L_TYPE': 'Executable', - 'L_PATH': 'RKill', - 'L_ITEM': 'RKill.exe', - 'L_ARGS': '-s -l %log_dir%\Tools\RKill.log', - 'L_ELEV': 'True', - 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Logs', - ], - }, - 'SFC Scan': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'sfc_scan.py', - 'L_ELEV': 'True', - }, - 'TDSSKiller': { - 'L_TYPE': 'Executable', - 'L_PATH': 'TDSSKiller', - 'L_ITEM': 'TDSSKiller.exe', - 'L_ARGS': ( - r' -l %log_dir%\Tools\TDSSKiller.log' - r' -qpath %q_dir%' - r' -accepteula' - r' -accepteulaksn' - r' -dcexact' - r' -tdlfs' - ), - 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Quarantine', - r'set "q_dir=%client_dir%\Quarantine\TDSSKiller"', - r'mkdir "%q_dir%">nul 2>&1', - ], - }, - }, - r'Uninstallers': { - 'IObit Uninstaller': { - 'L_TYPE': 'Executable', - 'L_PATH': 'IObitUninstallerPortable', - 'L_ITEM': 'IObitUninstallerPortable.exe', - }, - }, - } + r'(Root)': { + 'Activate Windows': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'activate.py', + 'L_ELEV': 'True', + }, + 'System Checklist': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'system_checklist.py', + 'L_ELEV': 'True', + }, + 'System Diagnostics': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'system_diagnostics.py', + 'L_ELEV': 'True', + }, + 'User Checklist': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'user_checklist.py', + }, + }, + r'Data Recovery': { + 'PhotoRec (CLI)': { + 'L_TYPE': 'Executable', + 'L_PATH': 'TestDisk', + 'L_ITEM': 'photorec_win.exe', + 'L_ELEV': 'True', + 'L__CLI': 'True', + }, + 'PhotoRec': { + 'L_TYPE': 'Executable', + 'L_PATH': 'TestDisk', + 'L_ITEM': 'qphotorec_win.exe', + 'L_ELEV': 'True', + }, + 'TestDisk': { + 'L_TYPE': 'Executable', + 'L_PATH': 'TestDisk', + 'L_ITEM': 'testdisk_win.exe', + 'L_ELEV': 'True', + 'L__CLI': 'True', + }, + }, + r'Data Transfers': { + 'FastCopy (as ADMIN)': { + 'L_TYPE': 'Executable', + 'L_PATH': 'FastCopy', + 'L_ITEM': 'FastCopy.exe', + 'L_ARGS': ( + r' /logfile=%log_dir%\Tools\FastCopy.log' + r' /cmd=noexist_only' + r' /utf8' + r' /skip_empty_dir' + r' /linkdest' + r' /exclude=' + r'$RECYCLE.BIN;' + r'$Recycle.Bin;' + r'.AppleDB;' + r'.AppleDesktop;' + r'.AppleDouble;' + r'.com.apple.timemachine.supported;' + r'.dbfseventsd;' + r'.DocumentRevisions-V100*;' + r'.DS_Store;' + r'.fseventsd;' + r'.PKInstallSandboxManager;' + r'.Spotlight*;' + r'.SymAV*;' + r'.symSchedScanLockxz;' + r'.TemporaryItems;' + r'.Trash*;' + r'.vol;' + r'.VolumeIcon.icns;' + r'desktop.ini;' + r'Desktop?DB;' + r'Desktop?DF;' + r'hiberfil.sys;' + r'lost+found;' + r'Network?Trash?Folder;' + r'pagefile.sys;' + r'Recycled;' + r'RECYCLER;' + r'System?Volume?Information;' + r'Temporary?Items;' + r'Thumbs.db' + r' /to=%client_dir%\Transfer_%iso_date%\ ' + ), + 'L_ELEV': 'True', + 'Extra Code': [ + r'call "%bin%\Scripts\init_client_dir.cmd" /Logs /Transfer', + ], + }, + 'FastCopy': { + 'L_TYPE': 'Executable', + 'L_PATH': 'FastCopy', + 'L_ITEM': 'FastCopy.exe', + 'L_ARGS': ( + r' /logfile=%log_dir%\Tools\FastCopy.log' + r' /cmd=noexist_only' + r' /utf8' + r' /skip_empty_dir' + r' /linkdest' + r' /exclude=' + r'$RECYCLE.BIN;' + r'$Recycle.Bin;' + r'.AppleDB;' + r'.AppleDesktop;' + r'.AppleDouble;' + r'.com.apple.timemachine.supported;' + r'.dbfseventsd;' + r'.DocumentRevisions-V100*;' + r'.DS_Store;' + r'.fseventsd;' + r'.PKInstallSandboxManager;' + r'.Spotlight*;' + r'.SymAV*;' + r'.symSchedScanLockxz;' + r'.TemporaryItems;' + r'.Trash*;' + r'.vol;' + r'.VolumeIcon.icns;' + r'desktop.ini;' + r'Desktop?DB;' + r'Desktop?DF;' + r'hiberfil.sys;' + r'lost+found;' + r'Network?Trash?Folder;' + r'pagefile.sys;' + r'Recycled;' + r'RECYCLER;' + r'System?Volume?Information;' + r'Temporary?Items;' + r'Thumbs.db' + r' /to=%client_dir%\Transfer_%iso_date%\ ' + ), + 'Extra Code': [ + r'call "%bin%\Scripts\init_client_dir.cmd" /Logs /Transfer', + ], + }, + 'KVRT': { + 'L_TYPE': 'Executable', + 'L_PATH': 'KVRT', + 'L_ITEM': 'KVRT.exe', + 'L_ARGS': ( + r' -accepteula' + r' -d %q_dir%' + r' -processlevel 3' + r' -dontcryptsupportinfo' + r' -fixednames' + ), + 'Extra Code': [ + r'call "%bin%\Scripts\init_client_dir.cmd" /Quarantine', + r'set "q_dir=%client_dir%\Quarantine\KVRT"', + r'mkdir "%q_dir%">nul 2>&1', + ], + }, + 'Transferred Keys': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'transferred_keys.py', + 'L_ELEV': 'True', + }, + 'User Data Transfer': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'user_data_transfer.py', + 'L_ELEV': 'True', + }, + 'XYplorer (as ADMIN)': { + 'L_TYPE': 'Executable', + 'L_PATH': 'XYplorerFree', + 'L_ITEM': 'XYplorerFree.exe', + 'L_ARGS': r'/exp /win=max %userprofile%', + 'L_ELEV': 'True', + }, + 'XYplorer': { + 'L_TYPE': 'Executable', + 'L_PATH': 'XYplorerFree', + 'L_ITEM': 'XYplorerFree.exe', + 'L_ARGS': r'/exp /win=max %userprofile%', + }, + }, + r'Diagnostics': { + 'HWiNFO': { + 'L_TYPE': 'Executable', + 'L_PATH': 'HWiNFO', + 'L_ITEM': 'HWiNFO.exe', + 'Extra Code': [ + r'for %%a in (32 64) do (', + r' copy /y "%bin%\HWiNFO\general.ini" "%bin%\HWiNFO\HWiNFO%%a.ini"', + r' (echo SensorsOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', + r' (echo SummaryOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', + r')', + ], + }, + 'ProduKey': { + 'L_TYPE': 'Executable', + 'L_PATH': 'ProduKey', + 'L_ITEM': 'ProduKey.exe', + 'L_ELEV': 'True', + 'Extra Code': [ + r'if exist "%bin%\ProduKey" (', + r' del "%bin%\ProduKey\ProduKey.cfg" 2>nul', + r' del "%bin%\ProduKey\ProduKey64.cfg" 2>nul', + r')', + ], + }, + }, + r'Diagnostics\Extras': { + 'AIDA64': { + 'L_TYPE': 'Executable', + 'L_PATH': 'AIDA64', + 'L_ITEM': 'aida64.exe', + }, + 'Autoruns (with VirusTotal Scan)': { + 'L_TYPE': 'Executable', + 'L_PATH': 'Autoruns', + 'L_ITEM': 'Autoruns.exe', + 'L_ARGS': '-e', + 'Extra Code': [ + r'reg add HKCU\Software\Sysinternals\AutoRuns /v checkvirustotal /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v EulaAccepted /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v shownomicrosoft /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v shownowindows /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v showonlyvirustotal /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v submitvirustotal /t REG_DWORD /d 0 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v verifysignatures /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns\SigCheck /v EulaAccepted /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns\Streams /v EulaAccepted /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns\VirusTotal /v VirusTotalTermsAccepted /t REG_DWORD /d 1 /f >nul', + ], + }, + 'BleachBit': { + 'L_TYPE': 'Executable', + 'L_PATH': 'BleachBit', + 'L_ITEM': 'bleachbit.exe', + }, + 'BlueScreenView': { + 'L_TYPE': 'Executable', + 'L_PATH': 'BlueScreenView', + 'L_ITEM': 'BlueScreenView.exe', + }, + 'ERUNT': { + 'L_TYPE': 'Executable', + 'L_PATH': 'erunt', + 'L_ITEM': 'ERUNT.EXE', + 'L_ARGS': '%client_dir%\Backups\Registry\%iso_date% sysreg curuser otherusers', + 'L_ELEV': 'True', + 'Extra Code': [ + r'call "%bin%\Scripts\init_client_dir.cmd" /Logs', + ], + }, + 'HitmanPro': { + 'L_TYPE': 'Executable', + 'L_PATH': 'HitmanPro', + 'L_ITEM': 'HitmanPro.exe', + 'Extra Code': [ + r'call "%bin%\Scripts\init_client_dir.cmd" /Logs', + ], + }, + 'HWiNFO (Sensors)': { + 'L_TYPE': 'Executable', + 'L_PATH': 'HWiNFO', + 'L_ITEM': 'HWiNFO.exe', + 'Extra Code': [ + r'for %%a in (32 64) do (', + r' copy /y "%bin%\HWiNFO\general.ini" "%bin%\HWiNFO\HWiNFO%%a.ini"', + r' (echo SensorsOnly=1)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', + r' (echo SummaryOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', + r')', + ], + }, + }, + r'Drivers': { + 'Intel RST (Current Release)': { + 'L_TYPE': 'Executable', + 'L_PATH': '_Drivers\Intel RST', + 'L_ITEM': 'SetupRST_16.5.exe', + 'L_7ZIP': 'SetupRST_16.5.exe', + }, + 'Intel RST (Previous Releases)': { + 'L_TYPE': 'Folder', + 'L_PATH': '_Drivers\Intel RST', + 'L_ITEM': '.', + 'L_NCMD': 'True', + }, + 'Intel SSD Toolbox': { + 'L_TYPE': 'Executable', + 'L_PATH': r'_Drivers\Intel SSD Toolbox', + 'L_ITEM': 'Intel SSD Toolbox.exe', + }, + 'Samsing Magician': { + 'L_TYPE': 'Executable', + 'L_PATH': r'_Drivers\Samsung Magician', + 'L_ITEM': 'Samsung Magician.exe', + }, + 'Snappy Driver Installer Origin': { + 'L_TYPE': 'Executable', + 'L_PATH': '_Drivers\SDIO', + 'L_ITEM': 'SDIO.exe', + }, + }, + r'Drivers\Extras': { + 'Acer': { + 'L_TYPE': 'Executable', + 'L_PATH': 'HWiNFO', + 'L_ITEM': 'HWiNFO.exe', + 'Extra Code': [ + r'for %%a in (32 64) do (', + r' copy /y "%bin%\HWiNFO\general.ini" "%bin%\HWiNFO\HWiNFO%%a.ini"', + r' (echo SensorsOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', + r' (echo SummaryOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', + r')', + r'start "" "http://us.acer.com/ac/en/US/content/drivers"', + ], + }, + 'Lenovo': { + 'L_TYPE': 'Executable', + 'L_PATH': 'HWiNFO', + 'L_ITEM': 'HWiNFO.exe', + 'Extra Code': [ + r'for %%a in (32 64) do (', + r' copy /y "%bin%\HWiNFO\general.ini" "%bin%\HWiNFO\HWiNFO%%a.ini"', + r' (echo SensorsOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', + r' (echo SummaryOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', + r')', + r'start "" "https://pcsupport.lenovo.com/us/en/"', + ], + }, + 'Toshiba': { + 'L_TYPE': 'Executable', + 'L_PATH': 'HWiNFO', + 'L_ITEM': 'HWiNFO.exe', + 'Extra Code': [ + r'for %%a in (32 64) do (', + r' copy /y "%bin%\HWiNFO\general.ini" "%bin%\HWiNFO\HWiNFO%%a.ini"', + r' (echo SensorsOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', + r' (echo SummaryOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', + r')', + r'start "" "http://support.toshiba.com/drivers"', + ], + }, + }, + r'Installers': { + 'SW Bundle': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'install_sw_bundle.py', + 'L_ELEV': 'True', + }, + }, + r'Installers\Extras\Office\2016': { + 'Home and Business 2016 (x32)': { + 'L_TYPE': 'Office', + 'L_PATH': '2016', + 'L_ITEM': 'hb_32.xml', + 'L_NCMD': 'True', + }, + 'Home and Business 2016 (x64)': { + 'L_TYPE': 'Office', + 'L_PATH': '2016', + 'L_ITEM': 'hb_64.xml', + 'L_NCMD': 'True', + }, + 'Home and Student 2016 (x32)': { + 'L_TYPE': 'Office', + 'L_PATH': '2016', + 'L_ITEM': 'hs_32.xml', + 'L_NCMD': 'True', + }, + 'Home and Student 2016 (x64)': { + 'L_TYPE': 'Office', + 'L_PATH': '2016', + 'L_ITEM': 'hs_64.xml', + 'L_NCMD': 'True', + }, + 'Office 365 2016 (x32)': { + 'L_TYPE': 'Office', + 'L_PATH': '2016', + 'L_ITEM': '365_32.xml', + 'L_NCMD': 'True', + }, + 'Office 365 2016 (x64)': { + 'L_TYPE': 'Office', + 'L_PATH': '2016', + 'L_ITEM': '365_64.xml', + 'L_NCMD': 'True', + }, + }, + r'Installers\Extras\Runtimes': { + 'Visual C++ Runtimes': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'install_vcredists.py', + 'L_ELEV': 'True', + }, + }, + r'Misc': { + 'Cleanup CBS Temp Files': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'cbs_fix.py', + 'L_ELEV': 'True', + }, + 'ConEmu (as ADMIN)': { + 'L_TYPE': 'Executable', + 'L_PATH': 'ConEmu', + 'L_ITEM': 'ConEmu.exe', + 'L_ELEV': 'True', + }, + 'ConEmu': { + 'L_TYPE': 'Executable', + 'L_PATH': 'ConEmu', + 'L_ITEM': 'ConEmu.exe', + }, + 'Enter SafeMode': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'safemode_enter.py', + 'L_ELEV': 'True', + }, + 'Everything': { + 'L_TYPE': 'Executable', + 'L_PATH': 'Everything', + 'L_ITEM': 'Everything.exe', + 'L_ARGS': '-nodb', + 'L_ELEV': 'True', + }, + 'Exit SafeMode': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'safemode_exit.py', + 'L_ELEV': 'True', + }, + 'Notepad++': { + 'L_TYPE': 'Executable', + 'L_PATH': 'notepadplusplus', + 'L_ITEM': 'notepadplusplus.exe', + }, + 'PuTTY': { + 'L_TYPE': 'Executable', + 'L_PATH': 'PuTTY', + 'L_ITEM': 'PUTTY.EXE', + }, + 'WizTree': { + 'L_TYPE': 'Executable', + 'L_PATH': 'WizTree', + 'L_ITEM': 'WizTree.exe', + 'L_ELEV': 'True', + }, + 'XMPlay': { + 'L_TYPE': 'Executable', + 'L_PATH': 'XMPlay', + 'L_ITEM': 'xmplay.exe', + 'L_ARGS': '"%bin%\XMPlay\music.7z"', + }, + }, + r'Repairs': { + 'AdwCleaner': { + 'L_TYPE': 'Executable', + 'L_PATH': 'AdwCleaner', + 'L_ITEM': 'AdwCleaner.exe', + }, + 'Autoruns': { + 'L_TYPE': 'Executable', + 'L_PATH': 'Autoruns', + 'L_ITEM': 'Autoruns.exe', + 'L_ARGS': '-e', + 'Extra Code': [ + r'reg add HKCU\Software\Sysinternals\AutoRuns /v checkvirustotal /t REG_DWORD /d 0 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v EulaAccepted /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v shownomicrosoft /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v shownowindows /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v showonlyvirustotal /t REG_DWORD /d 0 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v submitvirustotal /t REG_DWORD /d 0 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v verifysignatures /t REG_DWORD /d 0 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns\SigCheck /v EulaAccepted /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns\Streams /v EulaAccepted /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns\VirusTotal /v VirusTotalTermsAccepted /t REG_DWORD /d 1 /f >nul', + ], + }, + 'CHKDSK': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'check_disk.py', + 'L_ELEV': 'True', + }, + 'DISM': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'dism.py', + 'L_ELEV': 'True', + }, + 'KVRT': { + 'L_TYPE': 'Executable', + 'L_PATH': 'KVRT', + 'L_ITEM': 'KVRT.exe', + 'L_ARGS': ( + r' -accepteula' + r' -d %q_dir%' + r' -processlevel 3' + r' -dontcryptsupportinfo' + r' -fixednames' + ), + 'Extra Code': [ + r'call "%bin%\Scripts\init_client_dir.cmd" /Quarantine', + r'set "q_dir=%client_dir%\Quarantine\KVRT"', + r'mkdir "%q_dir%">nul 2>&1', + ], + }, + 'RKill': { + 'L_TYPE': 'Executable', + 'L_PATH': 'RKill', + 'L_ITEM': 'RKill.exe', + 'L_ARGS': '-s -l %log_dir%\Tools\RKill.log', + 'L_ELEV': 'True', + 'Extra Code': [ + r'call "%bin%\Scripts\init_client_dir.cmd" /Logs', + ], + }, + 'SFC Scan': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'sfc_scan.py', + 'L_ELEV': 'True', + }, + 'TDSSKiller': { + 'L_TYPE': 'Executable', + 'L_PATH': 'TDSSKiller', + 'L_ITEM': 'TDSSKiller.exe', + 'L_ARGS': ( + r' -l %log_dir%\Tools\TDSSKiller.log' + r' -qpath %q_dir%' + r' -accepteula' + r' -accepteulaksn' + r' -dcexact' + r' -tdlfs' + ), + 'Extra Code': [ + r'call "%bin%\Scripts\init_client_dir.cmd" /Quarantine', + r'set "q_dir=%client_dir%\Quarantine\TDSSKiller"', + r'mkdir "%q_dir%">nul 2>&1', + ], + }, + }, + r'Uninstallers': { + 'IObit Uninstaller': { + 'L_TYPE': 'Executable', + 'L_PATH': 'IObitUninstallerPortable', + 'L_ITEM': 'IObitUninstallerPortable.exe', + }, + }, + } if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/settings/main.py b/.bin/Scripts/settings/main.py index 9d32b3ef..98f867fe 100644 --- a/.bin/Scripts/settings/main.py +++ b/.bin/Scripts/settings/main.py @@ -5,7 +5,7 @@ ENABLED_OPEN_LOGS = False ENABLED_TICKET_NUMBERS = False ENABLED_UPLOAD_DATA = False HW_OVERRIDES_FORCED = False -HW_OVERRIDES_LIMITED = True # If True this disables HW_OVERRIDE_FORCED +HW_OVERRIDES_LIMITED = True # If True this disables HW_OVERRIDE_FORCED # STATIC VARIABLES (also used by BASH and BATCH files) ## NOTE: There are no spaces around the = for easier parsing in BASH and BATCH @@ -15,14 +15,14 @@ KIT_NAME_FULL='WizardKit' KIT_NAME_SHORT='WK' SUPPORT_MESSAGE='Please let 2Shirt know by opening an issue on GitHub' # Live Linux -MPRIME_LIMIT='7' # of minutes to run Prime95 during hw-diags +MPRIME_LIMIT='7' # of minutes to run Prime95 during hw-diags ROOT_PASSWORD='Abracadabra' TECH_PASSWORD='Abracadabra' # Server IP addresses OFFICE_SERVER_IP='10.0.0.10' QUICKBOOKS_SERVER_IP='10.0.0.10' # Time Zones -LINUX_TIME_ZONE='America/Denver' # See 'timedatectl list-timezones' for valid values +LINUX_TIME_ZONE='America/Denver' # See 'timedatectl list-timezones' for valid values WINDOWS_TIME_ZONE='Mountain Standard Time' # See 'tzutil /l' for valid values # WiFi WIFI_SSID='SomeWiFi' @@ -30,64 +30,66 @@ WIFI_PASSWORD='Abracadabra' # SERVER VARIABLES ## NOTE: Windows can only use one user per server. This means that if -## one server serves multiple shares then you have to use the same -## user/password for all of those shares. +## one server serves multiple shares then you have to use the same +## user/password for all of those shares. BACKUP_SERVERS = [ - { 'IP': '10.0.0.10', - 'Name': 'ServerOne', - 'Mounted': False, - 'Share': 'Backups', - 'User': 'restore', - 'Pass': 'Abracadabra', - 'RW-User': 'backup', - 'RW-Pass': 'Abracadabra', - }, - { 'IP': '10.0.0.11', - 'Name': 'ServerTwo', - 'Mounted': False, - 'Share': 'Backups', - 'User': 'restore', - 'Pass': 'Abracadabra', - 'RW-User': 'backup', - 'RW-Pass': 'Abracadabra', - }, + { 'IP': '10.0.0.10', + 'Name': 'ServerOne', + 'Mounted': False, + 'Share': 'Backups', + 'User': 'restore', + 'Pass': 'Abracadabra', + 'RW-User': 'backup', + 'RW-Pass': 'Abracadabra', + }, + { 'IP': '10.0.0.11', + 'Name': 'ServerTwo', + 'Mounted': False, + 'Share': 'Backups', + 'User': 'restore', + 'Pass': 'Abracadabra', + 'RW-User': 'backup', + 'RW-Pass': 'Abracadabra', + }, ] CRASH_SERVER = { - 'Name': 'CrashServer', - 'Url': '', - 'User': '', - 'Pass': '', + 'Name': 'CrashServer', + 'Url': '', + 'User': '', + 'Pass': '', } OFFICE_SERVER = { - 'IP': OFFICE_SERVER_IP, - 'Name': 'ServerOne', - 'Mounted': False, - 'Share': 'Office', - 'User': 'restore', - 'Pass': 'Abracadabra', - 'RW-User': 'backup', - 'RW-Pass': 'Abracadabra', + 'IP': OFFICE_SERVER_IP, + 'Name': 'ServerOne', + 'Mounted': False, + 'Share': 'Office', + 'User': 'restore', + 'Pass': 'Abracadabra', + 'RW-User': 'backup', + 'RW-Pass': 'Abracadabra', } QUICKBOOKS_SERVER = { - 'IP': QUICKBOOKS_SERVER_IP, - 'Name': 'ServerOne', - 'Mounted': False, - 'Share': 'QuickBooks', - 'User': 'restore', - 'Pass': 'Abracadabra', - 'RW-User': 'backup', - 'RW-Pass': 'Abracadabra', + 'IP': QUICKBOOKS_SERVER_IP, + 'Name': 'ServerOne', + 'Mounted': False, + 'Share': 'QuickBooks', + 'User': 'restore', + 'Pass': 'Abracadabra', + 'RW-User': 'backup', + 'RW-Pass': 'Abracadabra', } WINDOWS_SERVER = { - 'IP': '10.0.0.10', - 'Name': 'ServerOne', - 'Mounted': False, - 'Share': 'Windows', - 'User': 'restore', - 'Pass': 'Abracadabra', - 'RW-User': 'backup', - 'RW-Pass': 'Abracadabra', + 'IP': '10.0.0.10', + 'Name': 'ServerOne', + 'Mounted': False, + 'Share': 'Windows', + 'User': 'restore', + 'Pass': 'Abracadabra', + 'RW-User': 'backup', + 'RW-Pass': 'Abracadabra', } if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/settings/music.py b/.bin/Scripts/settings/music.py index a2d49f31..37f5d178 100644 --- a/.bin/Scripts/settings/music.py +++ b/.bin/Scripts/settings/music.py @@ -1,70 +1,72 @@ # Wizard Kit: Settings - Music MUSIC_MOD = [ - '104208#banana_boat.mod', - '114971#tilbury_fair.mod', - '132563#ufo_tune.mod', - '135906#magnetik_girl.xm', - '140628#autumn_in_budapest.xm', - '143198#summer_memories_3.xm', - '144405#hillbilly_billyboy.xm', - '154795#4mat_-_eternity.xm', - '155845#bookworm.mo3', - '155914#battleofsteel.xm', - '158975#1_channel_moog.it', - '165495#trans.s3m', - '168513#necros_-_introspection.s3m', - '169628#radix_-_feng_shui_schematics.xm', - '175238#unknown48_-_twilight.mod', - '33432#ambrozia.xm', - '33460#amigatre.mod', - '34594#CHARIOT.S3M', - '34596#BUTTERFL.XM', - '34654#CTGOBLIN.S3M', - '35151#bananasplit.mod', - '35280#DEADLOCK.XM', - '38591#compo_liam.xm', - '39987#crystald.s3m', - '40475#ELYSIUM.MOD', - '42146#enigma.mod', - '42519#GHOST2.MOD', - '42560#GSLINGER.MOD', - '42872#existing.xm', - '50427#nf-stven.xm', - '51549#overture.mod', - '54250#SATELL.S3M', - '54313#realmk.s3m', - '55789#scrambld.mod', - '57934#spacedeb.mod', - '59344#stardstm.mod', - '60395#2ND_PM.S3M', - '66187#external.xm', - '66343#beek-substitutionology.it', - '67561#radix-unreal_superhero.xm', - '70829#inside_out.s3m', - '83779#beyond_music.mod', - ] + '104208#banana_boat.mod', + '114971#tilbury_fair.mod', + '132563#ufo_tune.mod', + '135906#magnetik_girl.xm', + '140628#autumn_in_budapest.xm', + '143198#summer_memories_3.xm', + '144405#hillbilly_billyboy.xm', + '154795#4mat_-_eternity.xm', + '155845#bookworm.mo3', + '155914#battleofsteel.xm', + '158975#1_channel_moog.it', + '165495#trans.s3m', + '168513#necros_-_introspection.s3m', + '169628#radix_-_feng_shui_schematics.xm', + '175238#unknown48_-_twilight.mod', + '33432#ambrozia.xm', + '33460#amigatre.mod', + '34594#CHARIOT.S3M', + '34596#BUTTERFL.XM', + '34654#CTGOBLIN.S3M', + '35151#bananasplit.mod', + '35280#DEADLOCK.XM', + '38591#compo_liam.xm', + '39987#crystald.s3m', + '40475#ELYSIUM.MOD', + '42146#enigma.mod', + '42519#GHOST2.MOD', + '42560#GSLINGER.MOD', + '42872#existing.xm', + '50427#nf-stven.xm', + '51549#overture.mod', + '54250#SATELL.S3M', + '54313#realmk.s3m', + '55789#scrambld.mod', + '57934#spacedeb.mod', + '59344#stardstm.mod', + '60395#2ND_PM.S3M', + '66187#external.xm', + '66343#beek-substitutionology.it', + '67561#radix-unreal_superhero.xm', + '70829#inside_out.s3m', + '83779#beyond_music.mod', + ] MUSIC_SNES = [ - 'actr', - 'crock', - 'ct', - 'dkc', - 'dkq', - 'ff6', - 'fz', - 'loz3', - 'mmx', - 'ptws', - 'scv4', - 'sf', - 'sf2', - 'sgng', - 'smk', - 'smw', - 'yi', - 'zamn' - ] + 'actr', + 'crock', + 'ct', + 'dkc', + 'dkq', + 'ff6', + 'fz', + 'loz3', + 'mmx', + 'ptws', + 'scv4', + 'sf', + 'sf2', + 'sgng', + 'smk', + 'smw', + 'yi', + 'zamn' + ] if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/settings/sources.py b/.bin/Scripts/settings/sources.py index 9f4350db..9a57e8f7 100644 --- a/.bin/Scripts/settings/sources.py +++ b/.bin/Scripts/settings/sources.py @@ -1,202 +1,202 @@ # Wizard Kit: Settings - Sources SOURCE_URLS = { - 'Adobe Reader DC': 'http://ardownload.adobe.com/pub/adobe/reader/win/AcrobatDC/1801120058/AcroRdrDC1801120058_en_US.exe', - 'AdwCleaner': 'https://downloads.malwarebytes.com/file/adwcleaner', - 'AIDA64': 'http://download.aida64.com/aida64engineer597.zip', - 'aria2': 'https://github.com/aria2/aria2/releases/download/release-1.34.0/aria2-1.34.0-win-32bit-build1.zip', - 'Autoruns': 'https://download.sysinternals.com/files/Autoruns.zip', - 'BleachBit': 'https://download.bleachbit.org/BleachBit-2.0-portable.zip', - 'BlueScreenView32': 'http://www.nirsoft.net/utils/bluescreenview.zip', - 'BlueScreenView64': 'http://www.nirsoft.net/utils/bluescreenview-x64.zip', - 'Caffeine': 'http://www.zhornsoftware.co.uk/caffeine/caffeine.zip', - 'ClassicStartSkin': 'http://www.classicshell.net/forum/download/file.php?id=3001&sid=9a195960d98fd754867dcb63d9315335', - 'Du': 'https://download.sysinternals.com/files/DU.zip', - 'ERUNT': 'http://www.aumha.org/downloads/erunt.zip', - 'Everything32': 'https://www.voidtools.com/Everything-1.4.1.895.x86.zip', - 'Everything64': 'https://www.voidtools.com/Everything-1.4.1.895.x64.zip', - 'FastCopy': 'http://ftp.vector.co.jp/70/64/2323/FastCopy354_installer.zip', - 'Firefox uBO': 'https://addons.mozilla.org/firefox/downloads/file/1056733/ublock_origin-1.16.20-an+fx.xpi', - 'HitmanPro32': 'https://dl.surfright.nl/HitmanPro.exe', - 'HitmanPro64': 'https://dl.surfright.nl/HitmanPro_x64.exe', - 'HWiNFO': 'http://app.oldfoss.com:81/download/HWiNFO/hwi_588.zip', - 'Intel SSD Toolbox': r'https://downloadmirror.intel.com/27656/eng/Intel%20SSD%20Toolbox%20-%20v3.5.2.exe', - 'IOBit_Uninstaller': 'https://portableapps.duckduckgo.com/IObitUninstallerPortable_7.5.0.7.paf.exe', - 'KVRT': 'http://devbuilds.kaspersky-labs.com/devbuilds/KVRT/latest/full/KVRT.exe', - 'Macs Fan Control': 'https://www.crystalidea.com/downloads/macsfancontrol_setup.exe', - 'NirCmd32': 'https://www.nirsoft.net/utils/nircmd.zip', - 'NirCmd64': 'https://www.nirsoft.net/utils/nircmd-x64.zip', - 'NotepadPlusPlus': 'https://notepad-plus-plus.org/repository/7.x/7.5.8/npp.7.5.8.bin.minimalist.7z', - 'Office Deployment Tool 2016': 'https://download.microsoft.com/download/2/7/A/27AF1BE6-DD20-4CB4-B154-EBAB8A7D4A7E/officedeploymenttool_10810.33603.exe', - 'ProduKey32': 'http://www.nirsoft.net/utils/produkey.zip', - 'ProduKey64': 'http://www.nirsoft.net/utils/produkey-x64.zip', - 'PuTTY': 'https://the.earth.li/~sgtatham/putty/latest/w32/putty.zip', - 'RKill': 'https://www.bleepingcomputer.com/download/rkill/dl/10/', - 'Samsung Magician': 'https://s3.ap-northeast-2.amazonaws.com/global.semi.static/SAMSUNG_SSD_v5_2_1_180523/CD0CFAC4675B9E502899B41BE00525C3909ECE3AD57CC1A2FB6B74A766B2A1EA/Samsung_Magician_Installer.zip', - 'SDIO Themes': 'http://snappy-driver-installer.org/downloads/SDIO_Themes.zip', - 'SDIO Torrent': 'http://snappy-driver-installer.org/downloads/SDIO_Update.torrent', - 'TDSSKiller': 'https://media.kaspersky.com/utilities/VirusUtilities/EN/tdsskiller.exe', - 'TestDisk': 'https://www.cgsecurity.org/testdisk-7.1-WIP.win.zip', - 'wimlib32': 'https://wimlib.net/downloads/wimlib-1.12.0-windows-i686-bin.zip', - 'wimlib64': 'https://wimlib.net/downloads/wimlib-1.12.0-windows-x86_64-bin.zip', - 'Winapp2': 'https://github.com/MoscaDotTo/Winapp2/archive/master.zip', - 'WizTree': 'https://antibody-software.com/files/wiztree_3_26_portable.zip', - 'XMPlay 7z': 'https://support.xmplay.com/files/16/xmp-7z.zip?v=800962', - 'XMPlay Game': 'https://support.xmplay.com/files/12/xmp-gme.zip?v=515637', - 'XMPlay RAR': 'https://support.xmplay.com/files/16/xmp-rar.zip?v=409646', - 'XMPlay WAModern': 'https://support.xmplay.com/files/10/WAModern.zip?v=207099', - 'XMPlay': 'https://support.xmplay.com/files/20/xmplay383.zip?v=298195', - 'XYplorerFree': 'https://www.xyplorer.com/download/xyplorer_free_noinstall.zip', - } + 'Adobe Reader DC': 'http://ardownload.adobe.com/pub/adobe/reader/win/AcrobatDC/1801120058/AcroRdrDC1801120058_en_US.exe', + 'AdwCleaner': 'https://downloads.malwarebytes.com/file/adwcleaner', + 'AIDA64': 'http://download.aida64.com/aida64engineer597.zip', + 'aria2': 'https://github.com/aria2/aria2/releases/download/release-1.34.0/aria2-1.34.0-win-32bit-build1.zip', + 'Autoruns': 'https://download.sysinternals.com/files/Autoruns.zip', + 'BleachBit': 'https://download.bleachbit.org/BleachBit-2.0-portable.zip', + 'BlueScreenView32': 'http://www.nirsoft.net/utils/bluescreenview.zip', + 'BlueScreenView64': 'http://www.nirsoft.net/utils/bluescreenview-x64.zip', + 'Caffeine': 'http://www.zhornsoftware.co.uk/caffeine/caffeine.zip', + 'ClassicStartSkin': 'http://www.classicshell.net/forum/download/file.php?id=3001&sid=9a195960d98fd754867dcb63d9315335', + 'Du': 'https://download.sysinternals.com/files/DU.zip', + 'ERUNT': 'http://www.aumha.org/downloads/erunt.zip', + 'Everything32': 'https://www.voidtools.com/Everything-1.4.1.895.x86.zip', + 'Everything64': 'https://www.voidtools.com/Everything-1.4.1.895.x64.zip', + 'FastCopy': 'http://ftp.vector.co.jp/70/64/2323/FastCopy354_installer.zip', + 'Firefox uBO': 'https://addons.mozilla.org/firefox/downloads/file/1056733/ublock_origin-1.16.20-an+fx.xpi', + 'HitmanPro32': 'https://dl.surfright.nl/HitmanPro.exe', + 'HitmanPro64': 'https://dl.surfright.nl/HitmanPro_x64.exe', + 'HWiNFO': 'http://app.oldfoss.com:81/download/HWiNFO/hwi_588.zip', + 'Intel SSD Toolbox': r'https://downloadmirror.intel.com/27656/eng/Intel%20SSD%20Toolbox%20-%20v3.5.2.exe', + 'IOBit_Uninstaller': 'https://portableapps.duckduckgo.com/IObitUninstallerPortable_7.5.0.7.paf.exe', + 'KVRT': 'http://devbuilds.kaspersky-labs.com/devbuilds/KVRT/latest/full/KVRT.exe', + 'Macs Fan Control': 'https://www.crystalidea.com/downloads/macsfancontrol_setup.exe', + 'NirCmd32': 'https://www.nirsoft.net/utils/nircmd.zip', + 'NirCmd64': 'https://www.nirsoft.net/utils/nircmd-x64.zip', + 'NotepadPlusPlus': 'https://notepad-plus-plus.org/repository/7.x/7.5.8/npp.7.5.8.bin.minimalist.7z', + 'Office Deployment Tool 2016': 'https://download.microsoft.com/download/2/7/A/27AF1BE6-DD20-4CB4-B154-EBAB8A7D4A7E/officedeploymenttool_10810.33603.exe', + 'ProduKey32': 'http://www.nirsoft.net/utils/produkey.zip', + 'ProduKey64': 'http://www.nirsoft.net/utils/produkey-x64.zip', + 'PuTTY': 'https://the.earth.li/ sgtatham/putty/latest/w32/putty.zip', + 'RKill': 'https://www.bleepingcomputer.com/download/rkill/dl/10/', + 'Samsung Magician': 'https://s3.ap-northeast-2.amazonaws.com/global.semi.static/SAMSUNG_SSD_v5_2_1_180523/CD0CFAC4675B9E502899B41BE00525C3909ECE3AD57CC1A2FB6B74A766B2A1EA/Samsung_Magician_Installer.zip', + 'SDIO Themes': 'http://snappy-driver-installer.org/downloads/SDIO_Themes.zip', + 'SDIO Torrent': 'http://snappy-driver-installer.org/downloads/SDIO_Update.torrent', + 'TDSSKiller': 'https://media.kaspersky.com/utilities/VirusUtilities/EN/tdsskiller.exe', + 'TestDisk': 'https://www.cgsecurity.org/testdisk-7.1-WIP.win.zip', + 'wimlib32': 'https://wimlib.net/downloads/wimlib-1.12.0-windows-i686-bin.zip', + 'wimlib64': 'https://wimlib.net/downloads/wimlib-1.12.0-windows-x86_64-bin.zip', + 'Winapp2': 'https://github.com/MoscaDotTo/Winapp2/archive/master.zip', + 'WizTree': 'https://antibody-software.com/files/wiztree_3_26_portable.zip', + 'XMPlay 7z': 'https://support.xmplay.com/files/16/xmp-7z.zip?v=800962', + 'XMPlay Game': 'https://support.xmplay.com/files/12/xmp-gme.zip?v=515637', + 'XMPlay RAR': 'https://support.xmplay.com/files/16/xmp-rar.zip?v=409646', + 'XMPlay WAModern': 'https://support.xmplay.com/files/10/WAModern.zip?v=207099', + 'XMPlay': 'https://support.xmplay.com/files/20/xmplay383.zip?v=298195', + 'XYplorerFree': 'https://www.xyplorer.com/download/xyplorer_free_noinstall.zip', + } VCREDIST_SOURCES = { - '2010sp1': { - '32': 'https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x86.exe', - '64': 'https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x64.exe', - }, - '2012u4': { - '32': 'https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x86.exe', - '64': 'https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x64.exe', - }, - '2013': { - '32': 'https://download.microsoft.com/download/0/5/6/056dcda9-d667-4e27-8001-8a0c6971d6b1/vcredist_x86.exe', - '64': 'https://download.microsoft.com/download/0/5/6/056dcda9-d667-4e27-8001-8a0c6971d6b1/vcredist_x64.exe', - }, - '2017': { - '32': 'https://aka.ms/vs/15/release/vc_redist.x86.exe', - '64': 'https://aka.ms/vs/15/release/vc_redist.x64.exe', - }, - } + '2010sp1': { + '32': 'https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x86.exe', + '64': 'https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x64.exe', + }, + '2012u4': { + '32': 'https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x86.exe', + '64': 'https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x64.exe', + }, + '2013': { + '32': 'https://download.microsoft.com/download/0/5/6/056dcda9-d667-4e27-8001-8a0c6971d6b1/vcredist_x86.exe', + '64': 'https://download.microsoft.com/download/0/5/6/056dcda9-d667-4e27-8001-8a0c6971d6b1/vcredist_x64.exe', + }, + '2017': { + '32': 'https://aka.ms/vs/15/release/vc_redist.x86.exe', + '64': 'https://aka.ms/vs/15/release/vc_redist.x64.exe', + }, + } NINITE_SOURCES = { - 'Bundles': { - 'Legacy.exe': '.net4.7.2-7zip-chrome-firefox-vlc', - 'Modern.exe': '.net4.7.2-7zip-chrome-classicstart-firefox-vlc', - }, - 'Audio-Video': { - 'AIMP.exe': 'aimp', - 'Audacity.exe': 'audacity', - 'CCCP.exe': 'cccp', - 'Foobar2000.exe': 'foobar', - 'GOM.exe': 'gom', - 'HandBrake.exe': 'handbrake', - 'iTunes.exe': 'itunes', - 'K-Lite Codecs.exe': 'klitecodecs', - 'MediaMonkey.exe': 'mediamonkey', - 'MusicBee.exe': 'musicbee', - 'Spotify.exe': 'spotify', - 'VLC.exe': 'vlc', - 'Winamp.exe': 'winamp', - }, - 'Cloud Storage': { - 'Dropbox.exe': 'dropbox', - 'Google Backup & Sync.exe': 'googlebackupandsync', - 'Mozy.exe': 'mozy', - 'OneDrive.exe': 'onedrive', - 'SugarSync.exe': 'sugarsync', - }, - 'Communication': { - 'Discord': 'discord', - 'Pidgin.exe': 'pidgin', - 'Skype.exe': 'skype', - 'Trillian.exe': 'trillian', - }, - 'Compression': { - '7-Zip.exe': '7zip', - 'PeaZip.exe': 'peazip', - 'WinRAR.exe': 'winrar', - }, - 'Developer': { - 'Eclipse.exe': 'eclipse', - 'JDK 8.exe': 'jdk8', - 'JDK 8 (x64).exe': 'jdkx8', - 'Notepad++.exe': 'notepadplusplus', - 'PuTTY.exe': 'putty', - 'Python 2.exe': 'python', - 'Visual Studio Code.exe': 'vscode', - 'WinMerge.exe': 'winmerge', - 'WinSCP.exe': 'winscp', - }, - 'File Sharing': { - 'qBittorrent.exe': 'qbittorrent', - }, - 'Image-Photo': { - 'Blender.exe': 'blender', - 'FastStone.exe': 'faststone', - 'GIMP.exe': 'gimp', - 'Greenshot.exe': 'greenshot', - 'Inkscape.exe': 'inkscape', - 'IrfanView.exe': 'irfanview', - 'Krita.exe': 'krita', - 'Paint.NET.exe': 'paint.net', - 'ShareX.exe': 'sharex', - 'XnView.exe': 'xnview', - }, - 'Misc': { - 'Evernote.exe': 'evernote', - 'Everything.exe': 'everything', - 'KeePass 2.exe': 'keepass2', - 'Google Earth.exe': 'googleearth', - 'NV Access.exe': 'nvda', - 'Steam.exe': 'steam', - }, - 'Office': { - 'CutePDF.exe': 'cutepdf', - 'Foxit Reader.exe': 'foxit', - 'LibreOffice.exe': 'libreoffice', - 'OpenOffice.exe': 'openoffice', - 'PDFCreator.exe': 'pdfcreator', - 'SumatraPDF.exe': 'sumatrapdf', - 'Thunderbird.exe': 'thunderbird', - }, - 'Runtimes': { - 'Adobe Air.exe': 'air', - 'dotNET.exe': '.net4.7.2', - 'Java 8.exe': 'java8', - 'Shockwave.exe': 'shockwave', - 'Silverlight.exe': 'silverlight', - }, - 'Security': { - 'Avast.exe': 'avast', - 'AVG.exe': 'avg', - 'Avira.exe': 'avira', - 'Microsoft Security Essentials.exe': 'essentials', - 'Malwarebytes Anti-Malware.exe': 'malwarebytes', - 'Spybot 2.exe': 'spybot2', - 'SUPERAntiSpyware.exe': 'super', - }, - 'Utilities': { - 'CDBurnerXP.exe': 'cdburnerxp', - 'Classic Start.exe': 'classicstart', - 'Glary Utilities.exe': 'glary', - 'ImgBurn.exe': 'imgburn', - 'InfraRecorder.exe': 'infrarecorder', - 'Launchy.exe': 'launchy', - 'RealVNC.exe': 'realvnc', - 'Revo Uninstaller.exe': 'revo', - 'TeamViewer 13.exe': 'teamviewer13', - 'TeraCopy.exe': 'teracopy', - 'WinDirStat.exe': 'windirstat', - }, - 'Web Browsers': { - 'Google Chrome.exe': 'chrome', - 'Mozilla Firefox.exe': 'firefox', - 'Opera Chromium.exe': 'operaChromium', - }, - } + 'Bundles': { + 'Legacy.exe': '.net4.7.2-7zip-chrome-firefox-vlc', + 'Modern.exe': '.net4.7.2-7zip-chrome-classicstart-firefox-vlc', + }, + 'Audio-Video': { + 'AIMP.exe': 'aimp', + 'Audacity.exe': 'audacity', + 'CCCP.exe': 'cccp', + 'Foobar2000.exe': 'foobar', + 'GOM.exe': 'gom', + 'HandBrake.exe': 'handbrake', + 'iTunes.exe': 'itunes', + 'K-Lite Codecs.exe': 'klitecodecs', + 'MediaMonkey.exe': 'mediamonkey', + 'MusicBee.exe': 'musicbee', + 'Spotify.exe': 'spotify', + 'VLC.exe': 'vlc', + 'Winamp.exe': 'winamp', + }, + 'Cloud Storage': { + 'Dropbox.exe': 'dropbox', + 'Google Backup & Sync.exe': 'googlebackupandsync', + 'Mozy.exe': 'mozy', + 'OneDrive.exe': 'onedrive', + 'SugarSync.exe': 'sugarsync', + }, + 'Communication': { + 'Discord': 'discord', + 'Pidgin.exe': 'pidgin', + 'Skype.exe': 'skype', + 'Trillian.exe': 'trillian', + }, + 'Compression': { + '7-Zip.exe': '7zip', + 'PeaZip.exe': 'peazip', + 'WinRAR.exe': 'winrar', + }, + 'Developer': { + 'Eclipse.exe': 'eclipse', + 'JDK 8.exe': 'jdk8', + 'JDK 8 (x64).exe': 'jdkx8', + 'Notepad++.exe': 'notepadplusplus', + 'PuTTY.exe': 'putty', + 'Python 2.exe': 'python', + 'Visual Studio Code.exe': 'vscode', + 'WinMerge.exe': 'winmerge', + 'WinSCP.exe': 'winscp', + }, + 'File Sharing': { + 'qBittorrent.exe': 'qbittorrent', + }, + 'Image-Photo': { + 'Blender.exe': 'blender', + 'FastStone.exe': 'faststone', + 'GIMP.exe': 'gimp', + 'Greenshot.exe': 'greenshot', + 'Inkscape.exe': 'inkscape', + 'IrfanView.exe': 'irfanview', + 'Krita.exe': 'krita', + 'Paint.NET.exe': 'paint.net', + 'ShareX.exe': 'sharex', + 'XnView.exe': 'xnview', + }, + 'Misc': { + 'Evernote.exe': 'evernote', + 'Everything.exe': 'everything', + 'KeePass 2.exe': 'keepass2', + 'Google Earth.exe': 'googleearth', + 'NV Access.exe': 'nvda', + 'Steam.exe': 'steam', + }, + 'Office': { + 'CutePDF.exe': 'cutepdf', + 'Foxit Reader.exe': 'foxit', + 'LibreOffice.exe': 'libreoffice', + 'OpenOffice.exe': 'openoffice', + 'PDFCreator.exe': 'pdfcreator', + 'SumatraPDF.exe': 'sumatrapdf', + 'Thunderbird.exe': 'thunderbird', + }, + 'Runtimes': { + 'Adobe Air.exe': 'air', + 'dotNET.exe': '.net4.7.2', + 'Java 8.exe': 'java8', + 'Shockwave.exe': 'shockwave', + 'Silverlight.exe': 'silverlight', + }, + 'Security': { + 'Avast.exe': 'avast', + 'AVG.exe': 'avg', + 'Avira.exe': 'avira', + 'Microsoft Security Essentials.exe': 'essentials', + 'Malwarebytes Anti-Malware.exe': 'malwarebytes', + 'Spybot 2.exe': 'spybot2', + 'SUPERAntiSpyware.exe': 'super', + }, + 'Utilities': { + 'CDBurnerXP.exe': 'cdburnerxp', + 'Classic Start.exe': 'classicstart', + 'Glary Utilities.exe': 'glary', + 'ImgBurn.exe': 'imgburn', + 'InfraRecorder.exe': 'infrarecorder', + 'Launchy.exe': 'launchy', + 'RealVNC.exe': 'realvnc', + 'Revo Uninstaller.exe': 'revo', + 'TeamViewer 13.exe': 'teamviewer13', + 'TeraCopy.exe': 'teracopy', + 'WinDirStat.exe': 'windirstat', + }, + 'Web Browsers': { + 'Google Chrome.exe': 'chrome', + 'Mozilla Firefox.exe': 'firefox', + 'Opera Chromium.exe': 'operaChromium', + }, + } RST_SOURCES = { - #SetupRST_12.0.exe : Removed from download center? - #SetupRST_12.5.exe : Removed from download center? - #SetupRST_12.8.exe : Removed from download center? - 'SetupRST_12.9.exe': 'https://downloadmirror.intel.com/23496/eng/SetupRST.exe', - #SetupRST_13.x.exe : Broken, doesn't support > .NET 4.5 - 'SetupRST_14.0.exe': 'https://downloadmirror.intel.com/25091/eng/SetupRST.exe', - 'SetupRST_14.8.exe': 'https://downloadmirror.intel.com/26759/eng/setuprst.exe', - 'SetupRST_15.8.exe': 'https://downloadmirror.intel.com/27442/eng/SetupRST.exe', - 'SetupRST_15.9.exe': 'https://downloadmirror.intel.com/27400/eng/SetupRST.exe', - 'SetupRST_16.0.exe': 'https://downloadmirror.intel.com/27681/eng/SetupRST.exe', - 'SetupRST_16.5.exe': 'https://downloadmirror.intel.com/27984/eng/SetupRST.exe', - } + #SetupRST_12.0.exe : Removed from download center? + #SetupRST_12.5.exe : Removed from download center? + #SetupRST_12.8.exe : Removed from download center? + 'SetupRST_12.9.exe': 'https://downloadmirror.intel.com/23496/eng/SetupRST.exe', + #SetupRST_13.x.exe : Broken, doesn't support > .NET 4.5 + 'SetupRST_14.0.exe': 'https://downloadmirror.intel.com/25091/eng/SetupRST.exe', + 'SetupRST_14.8.exe': 'https://downloadmirror.intel.com/26759/eng/setuprst.exe', + 'SetupRST_15.8.exe': 'https://downloadmirror.intel.com/27442/eng/SetupRST.exe', + 'SetupRST_15.9.exe': 'https://downloadmirror.intel.com/27400/eng/SetupRST.exe', + 'SetupRST_16.0.exe': 'https://downloadmirror.intel.com/27681/eng/SetupRST.exe', + 'SetupRST_16.5.exe': 'https://downloadmirror.intel.com/27984/eng/SetupRST.exe', + } if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") -# vim: sts=4 sw=4 ts=4 tw=0 nowrap +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/settings/tools.py b/.bin/Scripts/settings/tools.py index b470603c..0ee74dec 100644 --- a/.bin/Scripts/settings/tools.py +++ b/.bin/Scripts/settings/tools.py @@ -1,56 +1,58 @@ # Wizard Kit: Settings - Tools TOOLS = { - # NOTE: BinDir will be prepended to these paths at runtime - 'AIDA64': { - '32': r'AIDA64\aida64.exe'}, - 'AutoRuns': { - '32': r'Autoruns\autoruns.exe', - '64': r'Autoruns\autoruns64.exe'}, - 'BleachBit': { - '32': r'BleachBit\bleachbit_console.exe'}, - 'Caffeine': { - '32': r'Caffeine\caffeine.exe'}, - 'Du': { - '32': r'Du\du.exe', - '64': r'Du\du64.exe'}, - 'ERUNT': { - '32': r'ERUNT\ERUNT.EXE'}, - 'Everything': { - '32': r'Everything\Everything.exe', - '64': r'Everything\Everything64.exe'}, - 'FastCopy': { - '32': r'FastCopy\FastCopy.exe', - '64': r'FastCopy\FastCopy64.exe'}, - 'HitmanPro': { - '32': r'HitmanPro\HitmanPro.exe', - '64': r'HitmanPro\HitmanPro64.exe'}, - 'HWiNFO': { - '32': r'HWiNFO\HWiNFO.exe', - '64': r'HWiNFO\HWiNFO64.exe'}, - 'KVRT': { - '32': r'KVRT\KVRT.exe'}, - 'NirCmd': { - '32': r'NirCmd\nircmdc.exe', - '64': r'NirCmd\nircmdc64.exe'}, - 'NotepadPlusPlus': { - '32': r'NotepadPlusPlus\notepadplusplus.exe'}, - 'ProduKey': { - '32': r'ProduKey\ProduKey.exe', - '64': r'ProduKey\ProduKey64.exe'}, - 'RKill': { - '32': r'RKill\RKill.exe'}, - 'SevenZip': { - '32': r'7-Zip\7za.exe', - '64': r'7-Zip\7za64.exe'}, - 'TDSSKiller': { - '32': r'TDSSKiller\TDSSKiller.exe'}, - 'wimlib-imagex': { - '32': r'wimlib\x32\wimlib-imagex.exe', - '64': r'wimlib\x64\wimlib-imagex.exe'}, - 'XMPlay': { - '32': r'XMPlay\xmplay.exe'}, - } + # NOTE: BinDir will be prepended to these paths at runtime + 'AIDA64': { + '32': r'AIDA64\aida64.exe'}, + 'AutoRuns': { + '32': r'Autoruns\autoruns.exe', + '64': r'Autoruns\autoruns64.exe'}, + 'BleachBit': { + '32': r'BleachBit\bleachbit_console.exe'}, + 'Caffeine': { + '32': r'Caffeine\caffeine.exe'}, + 'Du': { + '32': r'Du\du.exe', + '64': r'Du\du64.exe'}, + 'ERUNT': { + '32': r'ERUNT\ERUNT.EXE'}, + 'Everything': { + '32': r'Everything\Everything.exe', + '64': r'Everything\Everything64.exe'}, + 'FastCopy': { + '32': r'FastCopy\FastCopy.exe', + '64': r'FastCopy\FastCopy64.exe'}, + 'HitmanPro': { + '32': r'HitmanPro\HitmanPro.exe', + '64': r'HitmanPro\HitmanPro64.exe'}, + 'HWiNFO': { + '32': r'HWiNFO\HWiNFO.exe', + '64': r'HWiNFO\HWiNFO64.exe'}, + 'KVRT': { + '32': r'KVRT\KVRT.exe'}, + 'NirCmd': { + '32': r'NirCmd\nircmdc.exe', + '64': r'NirCmd\nircmdc64.exe'}, + 'NotepadPlusPlus': { + '32': r'NotepadPlusPlus\notepadplusplus.exe'}, + 'ProduKey': { + '32': r'ProduKey\ProduKey.exe', + '64': r'ProduKey\ProduKey64.exe'}, + 'RKill': { + '32': r'RKill\RKill.exe'}, + 'SevenZip': { + '32': r'7-Zip\7za.exe', + '64': r'7-Zip\7za64.exe'}, + 'TDSSKiller': { + '32': r'TDSSKiller\TDSSKiller.exe'}, + 'wimlib-imagex': { + '32': r'wimlib\x32\wimlib-imagex.exe', + '64': r'wimlib\x64\wimlib-imagex.exe'}, + 'XMPlay': { + '32': r'XMPlay\xmplay.exe'}, + } if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/settings/windows_builds.py b/.bin/Scripts/settings/windows_builds.py index 2817979a..216be21f 100644 --- a/.bin/Scripts/settings/windows_builds.py +++ b/.bin/Scripts/settings/windows_builds.py @@ -1,193 +1,195 @@ # Wizard Kit: Settings - Windows Builds WINDOWS_BUILDS = { -# Build Version Release Codename Marketing Name Notes - '6000': ( 'Vista', 'RTM', 'Longhorn', None, 'unsupported'), - '6000': ( 'Vista', 'RTM', 'Longhorn', None, 'unsupported'), - '6001': ( 'Vista', 'SP1', 'Longhorn', None, 'unsupported'), - '6002': ( 'Vista', 'SP2', 'Longhorn', None, 'unsupported'), + # Build, Version, Release, Codename, Marketing Name, Notes + '6000': ('Vista', 'RTM', 'Longhorn', None, 'unsupported'), + '6000': ('Vista', 'RTM', 'Longhorn', None, 'unsupported'), + '6001': ('Vista', 'SP1', 'Longhorn', None, 'unsupported'), + '6002': ('Vista', 'SP2', 'Longhorn', None, 'unsupported'), - '7600': ( '7', 'RTM', 'Vienna', None, 'unsupported'), - '7601': ( '7', 'SP1', 'Vienna', None, 'outdated'), + '7600': ('7', 'RTM', 'Vienna', None, 'unsupported'), + '7601': ('7', 'SP1', 'Vienna', None, 'outdated'), - #9199 is a fake build since Win 8 is 6.2.9200 but that collides with Win 8.1 (6.3.9200) - '9199': ( '8', 'RTM', None, None, 'unsupported'), + #9199 is a fake build since Win 8 is 6.2.9200 but that collides with Win 8.1 (6.3.9200) + '9199': ('8', 'RTM', None, None, 'unsupported'), - '9200': ( '8.1', None, 'Blue', None, 'outdated'), - '9600': ( '8.1', None, 'Update', None, None), + '9200': ('8.1', None, 'Blue', None, 'outdated'), + '9600': ('8.1', None, 'Update', None, None), - '9841': ( '10', None, 'Threshold 1', None, 'preview build'), - '9860': ( '10', None, 'Threshold 1', None, 'preview build'), - '9879': ( '10', None, 'Threshold 1', None, 'preview build'), - '9926': ( '10', None, 'Threshold 1', None, 'preview build'), - '10041': ( '10', None, 'Threshold 1', None, 'preview build'), - '10049': ( '10', None, 'Threshold 1', None, 'preview build'), - '10061': ( '10', None, 'Threshold 1', None, 'preview build'), - '10074': ( '10', None, 'Threshold 1', None, 'preview build'), - '10122': ( '10', None, 'Threshold 1', None, 'preview build'), - '10130': ( '10', None, 'Threshold 1', None, 'preview build'), - '10158': ( '10', None, 'Threshold 1', None, 'preview build'), - '10159': ( '10', None, 'Threshold 1', None, 'preview build'), - '10162': ( '10', None, 'Threshold 1', None, 'preview build'), - '10166': ( '10', None, 'Threshold 1', None, 'preview build'), - '10240': ( '10', 'v1507', 'Threshold 1', None, 'unsupported'), - '10525': ( '10', None, 'Threshold 2', None, 'preview build'), - '10532': ( '10', None, 'Threshold 2', None, 'preview build'), - '10547': ( '10', None, 'Threshold 2', None, 'preview build'), - '10565': ( '10', None, 'Threshold 2', None, 'preview build'), - '10576': ( '10', None, 'Threshold 2', None, 'preview build'), - '10586': ( '10', 'v1511', 'Threshold 2', 'November Update', 'unsupported'), - '11082': ( '10', None, 'Redstone 1', None, 'preview build'), - '11099': ( '10', None, 'Redstone 1', None, 'preview build'), - '11102': ( '10', None, 'Redstone 1', None, 'preview build'), - '14251': ( '10', None, 'Redstone 1', None, 'preview build'), - '14257': ( '10', None, 'Redstone 1', None, 'preview build'), - '14271': ( '10', None, 'Redstone 1', None, 'preview build'), - '14279': ( '10', None, 'Redstone 1', None, 'preview build'), - '14291': ( '10', None, 'Redstone 1', None, 'preview build'), - '14295': ( '10', None, 'Redstone 1', None, 'preview build'), - '14316': ( '10', None, 'Redstone 1', None, 'preview build'), - '14328': ( '10', None, 'Redstone 1', None, 'preview build'), - '14332': ( '10', None, 'Redstone 1', None, 'preview build'), - '14342': ( '10', None, 'Redstone 1', None, 'preview build'), - '14352': ( '10', None, 'Redstone 1', None, 'preview build'), - '14361': ( '10', None, 'Redstone 1', None, 'preview build'), - '14366': ( '10', None, 'Redstone 1', None, 'preview build'), - '14367': ( '10', None, 'Redstone 1', None, 'preview build'), - '14371': ( '10', None, 'Redstone 1', None, 'preview build'), - '14372': ( '10', None, 'Redstone 1', None, 'preview build'), - '14376': ( '10', None, 'Redstone 1', None, 'preview build'), - '14379': ( '10', None, 'Redstone 1', None, 'preview build'), - '14383': ( '10', None, 'Redstone 1', None, 'preview build'), - '14385': ( '10', None, 'Redstone 1', None, 'preview build'), - '14388': ( '10', None, 'Redstone 1', None, 'preview build'), - '14390': ( '10', None, 'Redstone 1', None, 'preview build'), - '14393': ( '10', 'v1607', 'Redstone 1', 'Anniversary Update', 'unsupported'), - '14901': ( '10', None, 'Redstone 2', None, 'preview build'), - '14905': ( '10', None, 'Redstone 2', None, 'preview build'), - '14915': ( '10', None, 'Redstone 2', None, 'preview build'), - '14926': ( '10', None, 'Redstone 2', None, 'preview build'), - '14931': ( '10', None, 'Redstone 2', None, 'preview build'), - '14936': ( '10', None, 'Redstone 2', None, 'preview build'), - '14942': ( '10', None, 'Redstone 2', None, 'preview build'), - '14946': ( '10', None, 'Redstone 2', None, 'preview build'), - '14951': ( '10', None, 'Redstone 2', None, 'preview build'), - '14955': ( '10', None, 'Redstone 2', None, 'preview build'), - '14959': ( '10', None, 'Redstone 2', None, 'preview build'), - '14965': ( '10', None, 'Redstone 2', None, 'preview build'), - '14971': ( '10', None, 'Redstone 2', None, 'preview build'), - '14986': ( '10', None, 'Redstone 2', None, 'preview build'), - '15002': ( '10', None, 'Redstone 2', None, 'preview build'), - '15007': ( '10', None, 'Redstone 2', None, 'preview build'), - '15014': ( '10', None, 'Redstone 2', None, 'preview build'), - '15019': ( '10', None, 'Redstone 2', None, 'preview build'), - '15025': ( '10', None, 'Redstone 2', None, 'preview build'), - '15031': ( '10', None, 'Redstone 2', None, 'preview build'), - '15042': ( '10', None, 'Redstone 2', None, 'preview build'), - '15046': ( '10', None, 'Redstone 2', None, 'preview build'), - '15048': ( '10', None, 'Redstone 2', None, 'preview build'), - '15055': ( '10', None, 'Redstone 2', None, 'preview build'), - '15058': ( '10', None, 'Redstone 2', None, 'preview build'), - '15060': ( '10', None, 'Redstone 2', None, 'preview build'), - '15061': ( '10', None, 'Redstone 2', None, 'preview build'), - '15063': ( '10', 'v1703', 'Redstone 2', 'Creators Update', 'outdated'), - '16170': ( '10', None, 'Redstone 3', None, 'preview build'), - '16176': ( '10', None, 'Redstone 3', None, 'preview build'), - '16179': ( '10', None, 'Redstone 3', None, 'preview build'), - '16184': ( '10', None, 'Redstone 3', None, 'preview build'), - '16188': ( '10', None, 'Redstone 3', None, 'preview build'), - '16193': ( '10', None, 'Redstone 3', None, 'preview build'), - '16199': ( '10', None, 'Redstone 3', None, 'preview build'), - '16212': ( '10', None, 'Redstone 3', None, 'preview build'), - '16215': ( '10', None, 'Redstone 3', None, 'preview build'), - '16226': ( '10', None, 'Redstone 3', None, 'preview build'), - '16232': ( '10', None, 'Redstone 3', None, 'preview build'), - '16237': ( '10', None, 'Redstone 3', None, 'preview build'), - '16241': ( '10', None, 'Redstone 3', None, 'preview build'), - '16251': ( '10', None, 'Redstone 3', None, 'preview build'), - '16257': ( '10', None, 'Redstone 3', None, 'preview build'), - '16273': ( '10', None, 'Redstone 3', None, 'preview build'), - '16275': ( '10', None, 'Redstone 3', None, 'preview build'), - '16278': ( '10', None, 'Redstone 3', None, 'preview build'), - '16281': ( '10', None, 'Redstone 3', None, 'preview build'), - '16288': ( '10', None, 'Redstone 3', None, 'preview build'), - '16291': ( '10', None, 'Redstone 3', None, 'preview build'), - '16294': ( '10', None, 'Redstone 3', None, 'preview build'), - '16296': ( '10', None, 'Redstone 3', None, 'preview build'), - '16299': ( '10', 'v1709', 'Redstone 3', 'Fall Creators Update', 'outdated'), - '16353': ( '10', None, 'Redstone 4', None, 'preview build'), - '16362': ( '10', None, 'Redstone 4', None, 'preview build'), - '17004': ( '10', None, 'Redstone 4', None, 'preview build'), - '17017': ( '10', None, 'Redstone 4', None, 'preview build'), - '17025': ( '10', None, 'Redstone 4', None, 'preview build'), - '17035': ( '10', None, 'Redstone 4', None, 'preview build'), - '17040': ( '10', None, 'Redstone 4', None, 'preview build'), - '17046': ( '10', None, 'Redstone 4', None, 'preview build'), - '17063': ( '10', None, 'Redstone 4', None, 'preview build'), - '17074': ( '10', None, 'Redstone 4', None, 'preview build'), - '17083': ( '10', None, 'Redstone 4', None, 'preview build'), - '17093': ( '10', None, 'Redstone 4', None, 'preview build'), - '17101': ( '10', None, 'Redstone 4', None, 'preview build'), - '17107': ( '10', None, 'Redstone 4', None, 'preview build'), - '17110': ( '10', None, 'Redstone 4', None, 'preview build'), - '17112': ( '10', None, 'Redstone 4', None, 'preview build'), - '17115': ( '10', None, 'Redstone 4', None, 'preview build'), - '17120': ( '10', None, 'Redstone 4', None, 'preview build'), - '17123': ( '10', None, 'Redstone 4', None, 'preview build'), - '17127': ( '10', None, 'Redstone 4', None, 'preview build'), - '17128': ( '10', None, 'Redstone 4', None, 'preview build'), - '17133': ( '10', None, 'Redstone 4', None, 'preview build'), - '17134': ( '10', 'v1803', 'Redstone 4', 'April 2018 Update', None), - '17604': ( '10', None, 'Redstone 5', None, 'preview build'), - '17618': ( '10', None, 'Redstone 5', None, 'preview build'), - '17623': ( '10', None, 'Redstone 5', None, 'preview build'), - '17627': ( '10', None, 'Redstone 5', None, 'preview build'), - '17634': ( '10', None, 'Redstone 5', None, 'preview build'), - '17639': ( '10', None, 'Redstone 5', None, 'preview build'), - '17643': ( '10', None, 'Redstone 5', None, 'preview build'), - '17650': ( '10', None, 'Redstone 5', None, 'preview build'), - '17655': ( '10', None, 'Redstone 5', None, 'preview build'), - '17661': ( '10', None, 'Redstone 5', None, 'preview build'), - '17666': ( '10', None, 'Redstone 5', None, 'preview build'), - '17677': ( '10', None, 'Redstone 5', None, 'preview build'), - '17682': ( '10', None, 'Redstone 5', None, 'preview build'), - '17686': ( '10', None, 'Redstone 5', None, 'preview build'), - '17692': ( '10', None, 'Redstone 5', None, 'preview build'), - '17704': ( '10', None, 'Redstone 5', None, 'preview build'), - '17711': ( '10', None, 'Redstone 5', None, 'preview build'), - '17713': ( '10', None, 'Redstone 5', None, 'preview build'), - '17723': ( '10', None, 'Redstone 5', None, 'preview build'), - '17728': ( '10', None, 'Redstone 5', None, 'preview build'), - '17730': ( '10', None, 'Redstone 5', None, 'preview build'), - '17733': ( '10', None, 'Redstone 5', None, 'preview build'), - '17735': ( '10', None, 'Redstone 5', None, 'preview build'), - '17738': ( '10', None, 'Redstone 5', None, 'preview build'), - '17741': ( '10', None, 'Redstone 5', None, 'preview build'), - '17744': ( '10', None, 'Redstone 5', None, 'preview build'), - '17746': ( '10', None, 'Redstone 5', None, 'preview build'), - '17751': ( '10', None, 'Redstone 5', None, 'preview build'), - '17754': ( '10', None, 'Redstone 5', None, 'preview build'), - '17755': ( '10', None, 'Redstone 5', None, 'preview build'), - '17758': ( '10', None, 'Redstone 5', None, 'preview build'), - '17760': ( '10', None, 'Redstone 5', None, 'preview build'), - '17763': ( '10', 'v1809', 'Redstone 5', 'October 2018 Update', None), - '18204': ( '10', None, '19H1', None, 'preview build'), - '18214': ( '10', None, '19H1', None, 'preview build'), - '18219': ( '10', None, '19H1', None, 'preview build'), - '18234': ( '10', None, '19H1', None, 'preview build'), - '18237': ( '10', None, '19H1', None, 'preview build'), - '18242': ( '10', None, '19H1', None, 'preview build'), - '18247': ( '10', None, '19H1', None, 'preview build'), - '18252': ( '10', None, '19H1', None, 'preview build'), - '18262': ( '10', None, '19H1', None, 'preview build'), - '18267': ( '10', None, '19H1', None, 'preview build'), - '18272': ( '10', None, '19H1', None, 'preview build'), - '18277': ( '10', None, '19H1', None, 'preview build'), - '18282': ( '10', None, '19H1', None, 'preview build'), - '18290': ( '10', None, '19H1', None, 'preview build'), - '18298': ( '10', None, '19H1', None, 'preview build'), - '18305': ( '10', None, '19H1', None, 'preview build'), + '9841': ('10', None, 'Threshold 1', None, 'preview build'), + '9860': ('10', None, 'Threshold 1', None, 'preview build'), + '9879': ('10', None, 'Threshold 1', None, 'preview build'), + '9926': ('10', None, 'Threshold 1', None, 'preview build'), + '10041': ('10', None, 'Threshold 1', None, 'preview build'), + '10049': ('10', None, 'Threshold 1', None, 'preview build'), + '10061': ('10', None, 'Threshold 1', None, 'preview build'), + '10074': ('10', None, 'Threshold 1', None, 'preview build'), + '10122': ('10', None, 'Threshold 1', None, 'preview build'), + '10130': ('10', None, 'Threshold 1', None, 'preview build'), + '10158': ('10', None, 'Threshold 1', None, 'preview build'), + '10159': ('10', None, 'Threshold 1', None, 'preview build'), + '10162': ('10', None, 'Threshold 1', None, 'preview build'), + '10166': ('10', None, 'Threshold 1', None, 'preview build'), + '10240': ('10', 'v1507', 'Threshold 1', None, 'unsupported'), + '10525': ('10', None, 'Threshold 2', None, 'preview build'), + '10532': ('10', None, 'Threshold 2', None, 'preview build'), + '10547': ('10', None, 'Threshold 2', None, 'preview build'), + '10565': ('10', None, 'Threshold 2', None, 'preview build'), + '10576': ('10', None, 'Threshold 2', None, 'preview build'), + '10586': ('10', 'v1511', 'Threshold 2', 'November Update', 'unsupported'), + '11082': ('10', None, 'Redstone 1', None, 'preview build'), + '11099': ('10', None, 'Redstone 1', None, 'preview build'), + '11102': ('10', None, 'Redstone 1', None, 'preview build'), + '14251': ('10', None, 'Redstone 1', None, 'preview build'), + '14257': ('10', None, 'Redstone 1', None, 'preview build'), + '14271': ('10', None, 'Redstone 1', None, 'preview build'), + '14279': ('10', None, 'Redstone 1', None, 'preview build'), + '14291': ('10', None, 'Redstone 1', None, 'preview build'), + '14295': ('10', None, 'Redstone 1', None, 'preview build'), + '14316': ('10', None, 'Redstone 1', None, 'preview build'), + '14328': ('10', None, 'Redstone 1', None, 'preview build'), + '14332': ('10', None, 'Redstone 1', None, 'preview build'), + '14342': ('10', None, 'Redstone 1', None, 'preview build'), + '14352': ('10', None, 'Redstone 1', None, 'preview build'), + '14361': ('10', None, 'Redstone 1', None, 'preview build'), + '14366': ('10', None, 'Redstone 1', None, 'preview build'), + '14367': ('10', None, 'Redstone 1', None, 'preview build'), + '14371': ('10', None, 'Redstone 1', None, 'preview build'), + '14372': ('10', None, 'Redstone 1', None, 'preview build'), + '14376': ('10', None, 'Redstone 1', None, 'preview build'), + '14379': ('10', None, 'Redstone 1', None, 'preview build'), + '14383': ('10', None, 'Redstone 1', None, 'preview build'), + '14385': ('10', None, 'Redstone 1', None, 'preview build'), + '14388': ('10', None, 'Redstone 1', None, 'preview build'), + '14390': ('10', None, 'Redstone 1', None, 'preview build'), + '14393': ('10', 'v1607', 'Redstone 1', 'Anniversary Update', 'unsupported'), + '14901': ('10', None, 'Redstone 2', None, 'preview build'), + '14905': ('10', None, 'Redstone 2', None, 'preview build'), + '14915': ('10', None, 'Redstone 2', None, 'preview build'), + '14926': ('10', None, 'Redstone 2', None, 'preview build'), + '14931': ('10', None, 'Redstone 2', None, 'preview build'), + '14936': ('10', None, 'Redstone 2', None, 'preview build'), + '14942': ('10', None, 'Redstone 2', None, 'preview build'), + '14946': ('10', None, 'Redstone 2', None, 'preview build'), + '14951': ('10', None, 'Redstone 2', None, 'preview build'), + '14955': ('10', None, 'Redstone 2', None, 'preview build'), + '14959': ('10', None, 'Redstone 2', None, 'preview build'), + '14965': ('10', None, 'Redstone 2', None, 'preview build'), + '14971': ('10', None, 'Redstone 2', None, 'preview build'), + '14986': ('10', None, 'Redstone 2', None, 'preview build'), + '15002': ('10', None, 'Redstone 2', None, 'preview build'), + '15007': ('10', None, 'Redstone 2', None, 'preview build'), + '15014': ('10', None, 'Redstone 2', None, 'preview build'), + '15019': ('10', None, 'Redstone 2', None, 'preview build'), + '15025': ('10', None, 'Redstone 2', None, 'preview build'), + '15031': ('10', None, 'Redstone 2', None, 'preview build'), + '15042': ('10', None, 'Redstone 2', None, 'preview build'), + '15046': ('10', None, 'Redstone 2', None, 'preview build'), + '15048': ('10', None, 'Redstone 2', None, 'preview build'), + '15055': ('10', None, 'Redstone 2', None, 'preview build'), + '15058': ('10', None, 'Redstone 2', None, 'preview build'), + '15060': ('10', None, 'Redstone 2', None, 'preview build'), + '15061': ('10', None, 'Redstone 2', None, 'preview build'), + '15063': ('10', 'v1703', 'Redstone 2', 'Creators Update', 'unsupported'), + '16170': ('10', None, 'Redstone 3', None, 'preview build'), + '16176': ('10', None, 'Redstone 3', None, 'preview build'), + '16179': ('10', None, 'Redstone 3', None, 'preview build'), + '16184': ('10', None, 'Redstone 3', None, 'preview build'), + '16188': ('10', None, 'Redstone 3', None, 'preview build'), + '16193': ('10', None, 'Redstone 3', None, 'preview build'), + '16199': ('10', None, 'Redstone 3', None, 'preview build'), + '16212': ('10', None, 'Redstone 3', None, 'preview build'), + '16215': ('10', None, 'Redstone 3', None, 'preview build'), + '16226': ('10', None, 'Redstone 3', None, 'preview build'), + '16232': ('10', None, 'Redstone 3', None, 'preview build'), + '16237': ('10', None, 'Redstone 3', None, 'preview build'), + '16241': ('10', None, 'Redstone 3', None, 'preview build'), + '16251': ('10', None, 'Redstone 3', None, 'preview build'), + '16257': ('10', None, 'Redstone 3', None, 'preview build'), + '16273': ('10', None, 'Redstone 3', None, 'preview build'), + '16275': ('10', None, 'Redstone 3', None, 'preview build'), + '16278': ('10', None, 'Redstone 3', None, 'preview build'), + '16281': ('10', None, 'Redstone 3', None, 'preview build'), + '16288': ('10', None, 'Redstone 3', None, 'preview build'), + '16291': ('10', None, 'Redstone 3', None, 'preview build'), + '16294': ('10', None, 'Redstone 3', None, 'preview build'), + '16296': ('10', None, 'Redstone 3', None, 'preview build'), + '16299': ('10', 'v1709', 'Redstone 3', 'Fall Creators Update', 'outdated'), + '16353': ('10', None, 'Redstone 4', None, 'preview build'), + '16362': ('10', None, 'Redstone 4', None, 'preview build'), + '17004': ('10', None, 'Redstone 4', None, 'preview build'), + '17017': ('10', None, 'Redstone 4', None, 'preview build'), + '17025': ('10', None, 'Redstone 4', None, 'preview build'), + '17035': ('10', None, 'Redstone 4', None, 'preview build'), + '17040': ('10', None, 'Redstone 4', None, 'preview build'), + '17046': ('10', None, 'Redstone 4', None, 'preview build'), + '17063': ('10', None, 'Redstone 4', None, 'preview build'), + '17074': ('10', None, 'Redstone 4', None, 'preview build'), + '17083': ('10', None, 'Redstone 4', None, 'preview build'), + '17093': ('10', None, 'Redstone 4', None, 'preview build'), + '17101': ('10', None, 'Redstone 4', None, 'preview build'), + '17107': ('10', None, 'Redstone 4', None, 'preview build'), + '17110': ('10', None, 'Redstone 4', None, 'preview build'), + '17112': ('10', None, 'Redstone 4', None, 'preview build'), + '17115': ('10', None, 'Redstone 4', None, 'preview build'), + '17120': ('10', None, 'Redstone 4', None, 'preview build'), + '17123': ('10', None, 'Redstone 4', None, 'preview build'), + '17127': ('10', None, 'Redstone 4', None, 'preview build'), + '17128': ('10', None, 'Redstone 4', None, 'preview build'), + '17133': ('10', None, 'Redstone 4', None, 'preview build'), + '17134': ('10', 'v1803', 'Redstone 4', 'April 2018 Update', 'outdated'), + '17604': ('10', None, 'Redstone 5', None, 'preview build'), + '17618': ('10', None, 'Redstone 5', None, 'preview build'), + '17623': ('10', None, 'Redstone 5', None, 'preview build'), + '17627': ('10', None, 'Redstone 5', None, 'preview build'), + '17634': ('10', None, 'Redstone 5', None, 'preview build'), + '17639': ('10', None, 'Redstone 5', None, 'preview build'), + '17643': ('10', None, 'Redstone 5', None, 'preview build'), + '17650': ('10', None, 'Redstone 5', None, 'preview build'), + '17655': ('10', None, 'Redstone 5', None, 'preview build'), + '17661': ('10', None, 'Redstone 5', None, 'preview build'), + '17666': ('10', None, 'Redstone 5', None, 'preview build'), + '17677': ('10', None, 'Redstone 5', None, 'preview build'), + '17682': ('10', None, 'Redstone 5', None, 'preview build'), + '17686': ('10', None, 'Redstone 5', None, 'preview build'), + '17692': ('10', None, 'Redstone 5', None, 'preview build'), + '17704': ('10', None, 'Redstone 5', None, 'preview build'), + '17711': ('10', None, 'Redstone 5', None, 'preview build'), + '17713': ('10', None, 'Redstone 5', None, 'preview build'), + '17723': ('10', None, 'Redstone 5', None, 'preview build'), + '17728': ('10', None, 'Redstone 5', None, 'preview build'), + '17730': ('10', None, 'Redstone 5', None, 'preview build'), + '17733': ('10', None, 'Redstone 5', None, 'preview build'), + '17735': ('10', None, 'Redstone 5', None, 'preview build'), + '17738': ('10', None, 'Redstone 5', None, 'preview build'), + '17741': ('10', None, 'Redstone 5', None, 'preview build'), + '17744': ('10', None, 'Redstone 5', None, 'preview build'), + '17746': ('10', None, 'Redstone 5', None, 'preview build'), + '17751': ('10', None, 'Redstone 5', None, 'preview build'), + '17754': ('10', None, 'Redstone 5', None, 'preview build'), + '17755': ('10', None, 'Redstone 5', None, 'preview build'), + '17758': ('10', None, 'Redstone 5', None, 'preview build'), + '17760': ('10', None, 'Redstone 5', None, 'preview build'), + '17763': ('10', 'v1809', 'Redstone 5', 'October 2018 Update', None), + '18204': ('10', None, '19H1', None, 'preview build'), + '18214': ('10', None, '19H1', None, 'preview build'), + '18219': ('10', None, '19H1', None, 'preview build'), + '18234': ('10', None, '19H1', None, 'preview build'), + '18237': ('10', None, '19H1', None, 'preview build'), + '18242': ('10', None, '19H1', None, 'preview build'), + '18247': ('10', None, '19H1', None, 'preview build'), + '18252': ('10', None, '19H1', None, 'preview build'), + '18262': ('10', None, '19H1', None, 'preview build'), + '18267': ('10', None, '19H1', None, 'preview build'), + '18272': ('10', None, '19H1', None, 'preview build'), + '18277': ('10', None, '19H1', None, 'preview build'), + '18282': ('10', None, '19H1', None, 'preview build'), + '18290': ('10', None, '19H1', None, 'preview build'), + '18298': ('10', None, '19H1', None, 'preview build'), + '18305': ('10', None, '19H1', None, 'preview build'), } if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From b6e9e447c5868b06b839cf7cd9b659844ae697f7 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 22:45:49 -0700 Subject: [PATCH 193/265] Fixed main.py --- .bin/Scripts/settings/main.py | 62 +++++++++++++++++------------------ 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/.bin/Scripts/settings/main.py b/.bin/Scripts/settings/main.py index 98f867fe..3ea1fa2b 100644 --- a/.bin/Scripts/settings/main.py +++ b/.bin/Scripts/settings/main.py @@ -5,7 +5,7 @@ ENABLED_OPEN_LOGS = False ENABLED_TICKET_NUMBERS = False ENABLED_UPLOAD_DATA = False HW_OVERRIDES_FORCED = False -HW_OVERRIDES_LIMITED = True # If True this disables HW_OVERRIDE_FORCED +HW_OVERRIDES_LIMITED = True # If True this disables HW_OVERRIDE_FORCED # STATIC VARIABLES (also used by BASH and BATCH files) ## NOTE: There are no spaces around the = for easier parsing in BASH and BATCH @@ -15,15 +15,15 @@ KIT_NAME_FULL='WizardKit' KIT_NAME_SHORT='WK' SUPPORT_MESSAGE='Please let 2Shirt know by opening an issue on GitHub' # Live Linux -MPRIME_LIMIT='7' # of minutes to run Prime95 during hw-diags +MPRIME_LIMIT='7' # of minutes to run Prime95 during hw-diags ROOT_PASSWORD='Abracadabra' TECH_PASSWORD='Abracadabra' # Server IP addresses OFFICE_SERVER_IP='10.0.0.10' QUICKBOOKS_SERVER_IP='10.0.0.10' # Time Zones -LINUX_TIME_ZONE='America/Denver' # See 'timedatectl list-timezones' for valid values -WINDOWS_TIME_ZONE='Mountain Standard Time' # See 'tzutil /l' for valid values +LINUX_TIME_ZONE='America/Denver' # See 'timedatectl list-timezones' for valid values +WINDOWS_TIME_ZONE='Mountain Standard Time' # See 'tzutil /l' for valid values # WiFi WIFI_SSID='SomeWiFi' WIFI_PASSWORD='Abracadabra' @@ -34,57 +34,57 @@ WIFI_PASSWORD='Abracadabra' ## user/password for all of those shares. BACKUP_SERVERS = [ { 'IP': '10.0.0.10', - 'Name': 'ServerOne', + 'Name': 'ServerOne', 'Mounted': False, - 'Share': 'Backups', - 'User': 'restore', - 'Pass': 'Abracadabra', + 'Share': 'Backups', + 'User': 'restore', + 'Pass': 'Abracadabra', 'RW-User': 'backup', 'RW-Pass': 'Abracadabra', }, { 'IP': '10.0.0.11', - 'Name': 'ServerTwo', + 'Name': 'ServerTwo', 'Mounted': False, - 'Share': 'Backups', - 'User': 'restore', - 'Pass': 'Abracadabra', + 'Share': 'Backups', + 'User': 'restore', + 'Pass': 'Abracadabra', 'RW-User': 'backup', 'RW-Pass': 'Abracadabra', }, ] CRASH_SERVER = { - 'Name': 'CrashServer', - 'Url': '', - 'User': '', - 'Pass': '', + 'Name': 'CrashServer', + 'Url': '', + 'User': '', + 'Pass': '', } OFFICE_SERVER = { - 'IP': OFFICE_SERVER_IP, - 'Name': 'ServerOne', + 'IP': OFFICE_SERVER_IP, + 'Name': 'ServerOne', 'Mounted': False, - 'Share': 'Office', - 'User': 'restore', - 'Pass': 'Abracadabra', + 'Share': 'Office', + 'User': 'restore', + 'Pass': 'Abracadabra', 'RW-User': 'backup', 'RW-Pass': 'Abracadabra', } QUICKBOOKS_SERVER = { - 'IP': QUICKBOOKS_SERVER_IP, - 'Name': 'ServerOne', + 'IP': QUICKBOOKS_SERVER_IP, + 'Name': 'ServerOne', 'Mounted': False, - 'Share': 'QuickBooks', - 'User': 'restore', - 'Pass': 'Abracadabra', + 'Share': 'QuickBooks', + 'User': 'restore', + 'Pass': 'Abracadabra', 'RW-User': 'backup', 'RW-Pass': 'Abracadabra', } WINDOWS_SERVER = { - 'IP': '10.0.0.10', - 'Name': 'ServerOne', + 'IP': '10.0.0.10', + 'Name': 'ServerOne', 'Mounted': False, - 'Share': 'Windows', - 'User': 'restore', - 'Pass': 'Abracadabra', + 'Share': 'Windows', + 'User': 'restore', + 'Pass': 'Abracadabra', 'RW-User': 'backup', 'RW-Pass': 'Abracadabra', } From 453ce9cf44dcb51d63b38c202dc85e92ba26ee01 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 22:48:20 -0700 Subject: [PATCH 194/265] More fixes for main.py --- .bin/Scripts/settings/main.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.bin/Scripts/settings/main.py b/.bin/Scripts/settings/main.py index 3ea1fa2b..da83e830 100644 --- a/.bin/Scripts/settings/main.py +++ b/.bin/Scripts/settings/main.py @@ -30,10 +30,10 @@ WIFI_PASSWORD='Abracadabra' # SERVER VARIABLES ## NOTE: Windows can only use one user per server. This means that if -## one server serves multiple shares then you have to use the same -## user/password for all of those shares. +## one server serves multiple shares then you have to use the same +## user/password for all of those shares. BACKUP_SERVERS = [ - { 'IP': '10.0.0.10', + { 'IP': '10.0.0.10', 'Name': 'ServerOne', 'Mounted': False, 'Share': 'Backups', @@ -41,8 +41,8 @@ BACKUP_SERVERS = [ 'Pass': 'Abracadabra', 'RW-User': 'backup', 'RW-Pass': 'Abracadabra', - }, - { 'IP': '10.0.0.11', + }, + { 'IP': '10.0.0.11', 'Name': 'ServerTwo', 'Mounted': False, 'Share': 'Backups', @@ -50,14 +50,14 @@ BACKUP_SERVERS = [ 'Pass': 'Abracadabra', 'RW-User': 'backup', 'RW-Pass': 'Abracadabra', - }, -] + }, + ] CRASH_SERVER = { 'Name': 'CrashServer', 'Url': '', 'User': '', 'Pass': '', -} + } OFFICE_SERVER = { 'IP': OFFICE_SERVER_IP, 'Name': 'ServerOne', @@ -67,7 +67,7 @@ OFFICE_SERVER = { 'Pass': 'Abracadabra', 'RW-User': 'backup', 'RW-Pass': 'Abracadabra', -} + } QUICKBOOKS_SERVER = { 'IP': QUICKBOOKS_SERVER_IP, 'Name': 'ServerOne', @@ -77,7 +77,7 @@ QUICKBOOKS_SERVER = { 'Pass': 'Abracadabra', 'RW-User': 'backup', 'RW-Pass': 'Abracadabra', -} + } WINDOWS_SERVER = { 'IP': '10.0.0.10', 'Name': 'ServerOne', @@ -87,7 +87,7 @@ WINDOWS_SERVER = { 'Pass': 'Abracadabra', 'RW-User': 'backup', 'RW-Pass': 'Abracadabra', -} + } if __name__ == '__main__': print("This file is not meant to be called directly.") From 103adc076a956f946b9f4df6c3a59868acfc123d Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 22:51:38 -0700 Subject: [PATCH 195/265] Updated more files --- .bin/Scripts/settings/launchers.py | 1372 ++++++++++++++-------------- .bin/Scripts/settings/main.py | 92 +- .bin/Scripts/settings/music.py | 128 +-- .bin/Scripts/settings/osticket.py | 2 +- .bin/Scripts/settings/sources.py | 398 ++++---- .bin/Scripts/settings/tools.py | 104 +-- 6 files changed, 1052 insertions(+), 1044 deletions(-) diff --git a/.bin/Scripts/settings/launchers.py b/.bin/Scripts/settings/launchers.py index ef0f6c16..9679184e 100644 --- a/.bin/Scripts/settings/launchers.py +++ b/.bin/Scripts/settings/launchers.py @@ -1,690 +1,692 @@ # Wizard Kit: Settings - Launchers LAUNCHERS = { - r'(Root)': { - 'Activate Windows': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'activate.py', - 'L_ELEV': 'True', - }, - 'd7II': { - 'L_TYPE': 'Executable', - 'L_PATH': 'd7II', - 'L_ITEM': 'd7II.exe', - }, - 'Post-d7II Work': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'post_d7.py', - 'L_ELEV': 'True', - }, - 'System Checklist': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'system_checklist.py', - 'L_ELEV': 'True', - }, - 'System Checklist (HW)': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'system_checklist_hw.py', - 'L_ELEV': 'True', - }, - 'User Checklist': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'user_checklist.py', - }, - }, - r'.bin\Scripts\launchers_for_d7': { - 'Browser Reset': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'reset_browsers.py', - 'L_ARGS': 'd7mode', - }, - 'Install SW Bundle': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'install_sw_bundle.py', - 'L_ARGS': 'd7mode', - 'L_ELEV': 'True', - }, - 'System Checklist': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'system_checklist.py', - 'L_ARGS': 'd7mode', - 'L_ELEV': 'True', - }, - 'System Diagnostics': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'system_diagnostics.py', - 'L_ARGS': 'd7mode', - 'L_ELEV': 'True', - }, - 'User Checklist': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'user_checklist.py', - 'L_ARGS': 'd7mode', - }, - }, - r'Data Recovery': { - 'PhotoRec (CLI)': { - 'L_TYPE': 'Executable', - 'L_PATH': 'TestDisk', - 'L_ITEM': 'photorec_win.exe', - 'L_ELEV': 'True', - 'L__CLI': 'True', - }, - 'PhotoRec': { - 'L_TYPE': 'Executable', - 'L_PATH': 'TestDisk', - 'L_ITEM': 'qphotorec_win.exe', - 'L_ELEV': 'True', - }, - 'TestDisk': { - 'L_TYPE': 'Executable', - 'L_PATH': 'TestDisk', - 'L_ITEM': 'testdisk_win.exe', - 'L_ELEV': 'True', - 'L__CLI': 'True', - }, - }, - r'Data Transfers': { - "Fab's Autobackup Pro": { - 'L_TYPE': 'Executable', - 'L_PATH': 'AutoBackupPro', - 'L_ITEM': 'autobackup6pro.exe', - }, - 'FastCopy (as ADMIN)': { - 'L_TYPE': 'Executable', - 'L_PATH': 'FastCopy', - 'L_ITEM': 'FastCopy.exe', - 'L_ARGS': ( - r' /logfile=%log_dir%\Tools\FastCopy.log' - r' /cmd=noexist_only' - r' /utf8' - r' /skip_empty_dir' - r' /linkdest' - r' /exclude=' - r'$RECYCLE.BIN;' - r'$Recycle.Bin;' - r'.AppleDB;' - r'.AppleDesktop;' - r'.AppleDouble;' - r'.com.apple.timemachine.supported;' - r'.dbfseventsd;' - r'.DocumentRevisions-V100*;' - r'.DS_Store;' - r'.fseventsd;' - r'.PKInstallSandboxManager;' - r'.Spotlight*;' - r'.SymAV*;' - r'.symSchedScanLockxz;' - r'.TemporaryItems;' - r'.Trash*;' - r'.vol;' - r'.VolumeIcon.icns;' - r'desktop.ini;' - r'Desktop?DB;' - r'Desktop?DF;' - r'hiberfil.sys;' - r'lost+found;' - r'Network?Trash?Folder;' - r'pagefile.sys;' - r'Recycled;' - r'RECYCLER;' - r'System?Volume?Information;' - r'Temporary?Items;' - r'Thumbs.db' - r' /to=%client_dir%\Transfer_%iso_date%\ ' - ), - 'L_ELEV': 'True', - 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Logs /Transfer', - ], - }, - 'FastCopy': { - 'L_TYPE': 'Executable', - 'L_PATH': 'FastCopy', - 'L_ITEM': 'FastCopy.exe', - 'L_ARGS': ( - r' /logfile=%log_dir%\Tools\FastCopy.log' - r' /cmd=noexist_only' - r' /utf8' - r' /skip_empty_dir' - r' /linkdest' - r' /exclude=' - r'$RECYCLE.BIN;' - r'$Recycle.Bin;' - r'.AppleDB;' - r'.AppleDesktop;' - r'.AppleDouble;' - r'.com.apple.timemachine.supported;' - r'.dbfseventsd;' - r'.DocumentRevisions-V100*;' - r'.DS_Store;' - r'.fseventsd;' - r'.PKInstallSandboxManager;' - r'.Spotlight*;' - r'.SymAV*;' - r'.symSchedScanLockxz;' - r'.TemporaryItems;' - r'.Trash*;' - r'.vol;' - r'.VolumeIcon.icns;' - r'desktop.ini;' - r'Desktop?DB;' - r'Desktop?DF;' - r'hiberfil.sys;' - r'lost+found;' - r'Network?Trash?Folder;' - r'pagefile.sys;' - r'Recycled;' - r'RECYCLER;' - r'System?Volume?Information;' - r'Temporary?Items;' - r'Thumbs.db' - r' /to=%client_dir%\Transfer_%iso_date%\ ' - ), - 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Logs /Transfer', - ], - }, - 'KVRT': { - 'L_TYPE': 'Executable', - 'L_PATH': 'KVRT', - 'L_ITEM': 'KVRT.exe', - 'L_ARGS': ( - r' -accepteula' - r' -d %q_dir%' - r' -processlevel 3' - r' -dontcryptsupportinfo' - r' -fixednames' - ), - 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Quarantine', - r'set "q_dir=%client_dir%\Quarantine\KVRT"', - r'mkdir "%q_dir%">nul 2>&1', - ], - }, - 'Mac & Linux Reader': { - 'L_TYPE': 'Executable', - 'L_PATH': 'LinuxReader', - 'L_ITEM': 'LinuxReader.exe', - 'L_ELEV': 'True', - }, - 'Transferred Keys': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'transferred_keys.py', - 'L_ELEV': 'True', - }, - 'User Data Transfer': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'user_data_transfer.py', - 'L_ELEV': 'True', - }, - 'XYplorer (as ADMIN)': { - 'L_TYPE': 'Executable', - 'L_PATH': 'XYplorerFree', - 'L_ITEM': 'XYplorerFree.exe', - 'L_ARGS': r'/exp /win=max %userprofile%', - 'L_ELEV': 'True', - }, - 'XYplorer': { - 'L_TYPE': 'Executable', - 'L_PATH': 'XYplorerFree', - 'L_ITEM': 'XYplorerFree.exe', - 'L_ARGS': r'/exp /win=max %userprofile%', - }, - }, - r'Diagnostics': { - 'AIDA64': { - 'L_TYPE': 'Executable', - 'L_PATH': 'AIDA64', - 'L_ITEM': 'aida64.exe', - }, - 'ProduKey': { - 'L_TYPE': 'Executable', - 'L_PATH': 'ProduKey', - 'L_ITEM': 'ProduKey.exe', - 'L_ELEV': 'True', - 'Extra Code': [ - r'if exist "%bin%\ProduKey" (', - r' del "%bin%\ProduKey\ProduKey.cfg" 2>nul', - r' del "%bin%\ProduKey\ProduKey64.cfg" 2>nul', - r')', - ], - }, - 'System Diagnostics': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'system_diagnostics.py', - 'L_ELEV': 'True', - }, - }, - r'Diagnostics\Extras': { - 'Autoruns (with VirusTotal Scan)': { - 'L_TYPE': 'Executable', - 'L_PATH': 'Autoruns', - 'L_ITEM': 'Autoruns.exe', - 'L_ARGS': '-e', - 'Extra Code': [ - r'reg add HKCU\Software\Sysinternals\AutoRuns /v checkvirustotal /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v EulaAccepted /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v shownomicrosoft /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v shownowindows /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v showonlyvirustotal /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v submitvirustotal /t REG_DWORD /d 0 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v verifysignatures /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns\SigCheck /v EulaAccepted /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns\Streams /v EulaAccepted /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns\VirusTotal /v VirusTotalTermsAccepted /t REG_DWORD /d 1 /f >nul', - ], - }, - 'BleachBit': { - 'L_TYPE': 'Executable', - 'L_PATH': 'BleachBit', - 'L_ITEM': 'bleachbit.exe', - }, - 'BlueScreenView': { - 'L_TYPE': 'Executable', - 'L_PATH': 'BlueScreenView', - 'L_ITEM': 'BlueScreenView.exe', - }, - 'ERUNT': { - 'L_TYPE': 'Executable', - 'L_PATH': 'erunt', - 'L_ITEM': 'ERUNT.EXE', - 'L_ARGS': '%client_dir%\Backups\Registry\%iso_date% sysreg curuser otherusers', - 'L_ELEV': 'True', - 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Logs', - ], - }, - 'FurMark': { - 'L_TYPE': 'Executable', - 'L_PATH': 'FurMark', - 'L_ITEM': 'FurMark.exe', - }, - 'HDTune Pro': { - 'L_TYPE': 'Executable', - 'L_PATH': 'HDTunePro', - 'L_ITEM': 'HDTunePro.exe', - }, - 'HitmanPro': { - 'L_TYPE': 'Executable', - 'L_PATH': 'HitmanPro', - 'L_ITEM': 'HitmanPro.exe', - 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Logs', - ], - }, - 'HWiNFO': { - 'L_TYPE': 'Executable', - 'L_PATH': 'HWiNFO', - 'L_ITEM': 'HWiNFO.exe', - 'Extra Code': [ - r'for %%a in (32 64) do (', - r' copy /y "%bin%\HWiNFO\general.ini" "%bin%\HWiNFO\HWiNFO%%a.ini"', - r' (echo SensorsOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', - r' (echo SummaryOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', - r')', - ], - }, - 'HWiNFO (Sensors)': { - 'L_TYPE': 'Executable', - 'L_PATH': 'HWiNFO', - 'L_ITEM': 'HWiNFO.exe', - 'Extra Code': [ - r'for %%a in (32 64) do (', - r' copy /y "%bin%\HWiNFO\general.ini" "%bin%\HWiNFO\HWiNFO%%a.ini"', - r' (echo SensorsOnly=1)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', - r' (echo SummaryOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', - r')', - ], - }, - }, - r'Drivers': { - 'Intel RST (Current Release)': { - 'L_TYPE': 'Executable', - 'L_PATH': '_Drivers\Intel RST', - 'L_ITEM': 'SetupRST_16.5.exe', - 'L_7ZIP': 'SetupRST_16.5.exe', - }, - 'Intel RST (Previous Releases)': { - 'L_TYPE': 'Folder', - 'L_PATH': '_Drivers\Intel RST', - 'L_ITEM': '.', - 'L_NCMD': 'True', - }, - 'Intel SSD Toolbox': { - 'L_TYPE': 'Executable', - 'L_PATH': r'_Drivers\Intel SSD Toolbox', - 'L_ITEM': 'Intel SSD Toolbox.exe', - }, - 'Samsing Magician': { - 'L_TYPE': 'Executable', - 'L_PATH': r'_Drivers\Samsung Magician', - 'L_ITEM': 'Samsung Magician.exe', - }, - 'Snappy Driver Installer Origin': { - 'L_TYPE': 'Executable', - 'L_PATH': '_Drivers\SDIO', - 'L_ITEM': 'SDIO.exe', - }, - }, - r'Drivers\Extras': { - 'Acer': { - 'L_TYPE': 'Executable', - 'L_PATH': 'HWiNFO', - 'L_ITEM': 'HWiNFO.exe', - 'Extra Code': [ - r'for %%a in (32 64) do (', - r' copy /y "%bin%\HWiNFO\general.ini" "%bin%\HWiNFO\HWiNFO%%a.ini"', - r' (echo SensorsOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', - r' (echo SummaryOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', - r')', - r'start "" "http://us.acer.com/ac/en/US/content/drivers"', - ], - }, - 'Lenovo': { - 'L_TYPE': 'Executable', - 'L_PATH': 'HWiNFO', - 'L_ITEM': 'HWiNFO.exe', - 'Extra Code': [ - r'for %%a in (32 64) do (', - r' copy /y "%bin%\HWiNFO\general.ini" "%bin%\HWiNFO\HWiNFO%%a.ini"', - r' (echo SensorsOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', - r' (echo SummaryOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', - r')', - r'start "" "https://pcsupport.lenovo.com/us/en/"', - ], - }, - 'Toshiba': { - 'L_TYPE': 'Executable', - 'L_PATH': 'HWiNFO', - 'L_ITEM': 'HWiNFO.exe', - 'Extra Code': [ - r'for %%a in (32 64) do (', - r' copy /y "%bin%\HWiNFO\general.ini" "%bin%\HWiNFO\HWiNFO%%a.ini"', - r' (echo SensorsOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', - r' (echo SummaryOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', - r')', - r'start "" "http://support.toshiba.com/drivers"', - ], - }, - }, - r'Installers': { - 'ESET NOD32 AV': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'install_eset_nod32_av.py', - 'L_ELEV': 'True', - }, - 'SW Bundle': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'install_sw_bundle.py', - 'L_ELEV': 'True', - }, - }, - r'Installers\Extras\Office\2016': { - 'Home and Business 2016 (x32)': { - 'L_TYPE': 'Office', - 'L_PATH': '2016', - 'L_ITEM': 'hb_32.xml', - 'L_NCMD': 'True', - }, - 'Home and Business 2016 (x64)': { - 'L_TYPE': 'Office', - 'L_PATH': '2016', - 'L_ITEM': 'hb_64.xml', - 'L_NCMD': 'True', - }, - 'Home and Student 2016 (x32)': { - 'L_TYPE': 'Office', - 'L_PATH': '2016', - 'L_ITEM': 'hs_32.xml', - 'L_NCMD': 'True', - }, - 'Home and Student 2016 (x64)': { - 'L_TYPE': 'Office', - 'L_PATH': '2016', - 'L_ITEM': 'hs_64.xml', - 'L_NCMD': 'True', - }, - 'Office 365 2016 (x32)': { - 'L_TYPE': 'Office', - 'L_PATH': '2016', - 'L_ITEM': '365_32.xml', - 'L_NCMD': 'True', - }, - 'Office 365 2016 (x64)': { - 'L_TYPE': 'Office', - 'L_PATH': '2016', - 'L_ITEM': '365_64.xml', - 'L_NCMD': 'True', - }, - }, - r'Installers\Extras\Runtimes': { - 'Visual C++ Runtimes': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'install_vcredists.py', - 'L_ELEV': 'True', - }, - }, - r'Misc': { - 'Cleanup CBS Temp Files': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'cbs_fix.py', - 'L_ELEV': 'True', - }, - 'ConEmu (as ADMIN)': { - 'L_TYPE': 'Executable', - 'L_PATH': 'ConEmu', - 'L_ITEM': 'ConEmu.exe', - 'L_ELEV': 'True', - }, - 'ConEmu': { - 'L_TYPE': 'Executable', - 'L_PATH': 'ConEmu', - 'L_ITEM': 'ConEmu.exe', - }, - 'Enter SafeMode': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'safemode_enter.py', - 'L_ELEV': 'True', - }, - 'Everything': { - 'L_TYPE': 'Executable', - 'L_PATH': 'Everything', - 'L_ITEM': 'Everything.exe', - 'L_ARGS': '-nodb', - 'L_ELEV': 'True', - }, - 'Exit SafeMode': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'safemode_exit.py', - 'L_ELEV': 'True', - }, - 'Network Stability Test': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'network_stability_test.py', - }, - 'Notepad++': { - 'L_TYPE': 'Executable', - 'L_PATH': 'notepadplusplus', - 'L_ITEM': 'notepadplusplus.exe', - }, - 'PuTTY': { - 'L_TYPE': 'Executable', - 'L_PATH': 'PuTTY', - 'L_ITEM': 'PUTTY.EXE', - }, - 'ShutUp10': { - 'L_TYPE': 'Executable', - 'L_PATH': 'ShutUp10', - 'L_ITEM': 'OOSU10.exe', - }, - 'ShutUp10 (1201 Minimal Selection)': { - 'L_TYPE': 'Executable', - 'L_PATH': 'ShutUp10', - 'L_ITEM': 'OOSU10.exe', - 'L_ARGS': '1201.cfg', - }, - 'WizTree': { - 'L_TYPE': 'Executable', - 'L_PATH': 'WizTree', - 'L_ITEM': 'WizTree.exe', - 'L_ELEV': 'True', - }, - 'XMPlay': { - 'L_TYPE': 'Executable', - 'L_PATH': 'XMPlay', - 'L_ITEM': 'xmplay.exe', - 'L_ARGS': '"%bin%\XMPlay\music.7z"', - }, - }, - r'Repairs': { - 'AdwCleaner': { - 'L_TYPE': 'Executable', - 'L_PATH': 'AdwCleaner', - 'L_ITEM': 'AdwCleaner.exe', - }, - 'Autoruns': { - 'L_TYPE': 'Executable', - 'L_PATH': 'Autoruns', - 'L_ITEM': 'Autoruns.exe', - 'L_ARGS': '-e', - 'Extra Code': [ - r'reg add HKCU\Software\Sysinternals\AutoRuns /v checkvirustotal /t REG_DWORD /d 0 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v EulaAccepted /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v shownomicrosoft /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v shownowindows /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v showonlyvirustotal /t REG_DWORD /d 0 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v submitvirustotal /t REG_DWORD /d 0 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns /v verifysignatures /t REG_DWORD /d 0 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns\SigCheck /v EulaAccepted /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns\Streams /v EulaAccepted /t REG_DWORD /d 1 /f >nul', - r'reg add HKCU\Software\Sysinternals\AutoRuns\VirusTotal /v VirusTotalTermsAccepted /t REG_DWORD /d 1 /f >nul', - ], - }, - 'CHKDSK': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'check_disk.py', - 'L_ELEV': 'True', - }, - 'DISM': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'dism.py', - 'L_ELEV': 'True', - }, - 'ESET Online Scanner': { - 'L_TYPE': 'Executable', - 'L_PATH': 'ESET', - 'L_ITEM': 'ESET.exe', - }, - 'KVRT': { - 'L_TYPE': 'Executable', - 'L_PATH': 'KVRT', - 'L_ITEM': 'KVRT.exe', - 'L_ARGS': ( - r' -accepteula' - r' -d %q_dir%' - r' -processlevel 3' - r' -dontcryptsupportinfo' - r' -fixednames' - ), - 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Quarantine', - r'set "q_dir=%client_dir%\Quarantine\KVRT"', - r'mkdir "%q_dir%">nul 2>&1', - ], - }, - 'RKill': { - 'L_TYPE': 'Executable', - 'L_PATH': 'RKill', - 'L_ITEM': 'RKill.exe', - 'L_ARGS': '-s -l %log_dir%\Tools\RKill.log', - 'L_ELEV': 'True', - 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Logs', - ], - }, - 'SFC Scan': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'sfc_scan.py', - 'L_ELEV': 'True', - }, - 'TDSSKiller': { - 'L_TYPE': 'Executable', - 'L_PATH': 'TDSSKiller', - 'L_ITEM': 'TDSSKiller.exe', - 'L_ARGS': ( - r' -l %log_dir%\Tools\TDSSKiller.log' - r' -qpath %q_dir%' - r' -accepteula' - r' -accepteulaksn' - r' -dcexact' - r' -tdlfs' - ), - 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Quarantine', - r'set "q_dir=%client_dir%\Quarantine\TDSSKiller"', - r'mkdir "%q_dir%">nul 2>&1', - ], - }, - 'WinAIO Repair': { - 'L_TYPE': 'Executable', - 'L_PATH': 'WinAIORepair', - 'L_ITEM': 'Repair_Windows.exe', - 'L_ELEV': 'True', - 'Extra Code': [ - r'copy /y "%bin%\WinAIORepair\__empty.ini" "%bin%\WinAIORepair\settings.ini"', - ], - }, - 'WinAIO Repair (Fix Associations)': { - 'L_TYPE': 'Executable', - 'L_PATH': 'WinAIORepair', - 'L_ITEM': 'Repair_Windows.exe', - 'L_ELEV': 'True', - 'Extra Code': [ - r'copy /y "%bin%\WinAIORepair\__associations.ini" "%bin%\WinAIORepair\settings.ini"', - ], - }, - 'WinAIO Repair (Fix Permissions)': { - 'L_TYPE': 'Executable', - 'L_PATH': 'WinAIORepair', - 'L_ITEM': 'Repair_Windows.exe', - 'L_ELEV': 'True', - 'Extra Code': [ - r'copy /y "%bin%\WinAIORepair\__permissions.ini" "%bin%\WinAIORepair\settings.ini"', - ], - }, - }, - r'Uninstallers': { - 'IObit Uninstaller': { - 'L_TYPE': 'Executable', - 'L_PATH': 'IObitUninstallerPortable', - 'L_ITEM': 'IObitUninstallerPortable.exe', - }, - }, - } + r'(Root)': { + 'Activate Windows': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'activate.py', + 'L_ELEV': 'True', + }, + 'd7II': { + 'L_TYPE': 'Executable', + 'L_PATH': 'd7II', + 'L_ITEM': 'd7II.exe', + }, + 'Post-d7II Work': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'post_d7.py', + 'L_ELEV': 'True', + }, + 'System Checklist': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'system_checklist.py', + 'L_ELEV': 'True', + }, + 'System Checklist (HW)': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'system_checklist_hw.py', + 'L_ELEV': 'True', + }, + 'User Checklist': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'user_checklist.py', + }, + }, + r'.bin\Scripts\launchers_for_d7': { + 'Browser Reset': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'reset_browsers.py', + 'L_ARGS': 'd7mode', + }, + 'Install SW Bundle': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'install_sw_bundle.py', + 'L_ARGS': 'd7mode', + 'L_ELEV': 'True', + }, + 'System Checklist': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'system_checklist.py', + 'L_ARGS': 'd7mode', + 'L_ELEV': 'True', + }, + 'System Diagnostics': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'system_diagnostics.py', + 'L_ARGS': 'd7mode', + 'L_ELEV': 'True', + }, + 'User Checklist': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'user_checklist.py', + 'L_ARGS': 'd7mode', + }, + }, + r'Data Recovery': { + 'PhotoRec (CLI)': { + 'L_TYPE': 'Executable', + 'L_PATH': 'TestDisk', + 'L_ITEM': 'photorec_win.exe', + 'L_ELEV': 'True', + 'L__CLI': 'True', + }, + 'PhotoRec': { + 'L_TYPE': 'Executable', + 'L_PATH': 'TestDisk', + 'L_ITEM': 'qphotorec_win.exe', + 'L_ELEV': 'True', + }, + 'TestDisk': { + 'L_TYPE': 'Executable', + 'L_PATH': 'TestDisk', + 'L_ITEM': 'testdisk_win.exe', + 'L_ELEV': 'True', + 'L__CLI': 'True', + }, + }, + r'Data Transfers': { + "Fab's Autobackup Pro": { + 'L_TYPE': 'Executable', + 'L_PATH': 'AutoBackupPro', + 'L_ITEM': 'autobackup6pro.exe', + }, + 'FastCopy (as ADMIN)': { + 'L_TYPE': 'Executable', + 'L_PATH': 'FastCopy', + 'L_ITEM': 'FastCopy.exe', + 'L_ARGS': ( + r' /logfile=%log_dir%\Tools\FastCopy.log' + r' /cmd=noexist_only' + r' /utf8' + r' /skip_empty_dir' + r' /linkdest' + r' /exclude=' + r'$RECYCLE.BIN;' + r'$Recycle.Bin;' + r'.AppleDB;' + r'.AppleDesktop;' + r'.AppleDouble;' + r'.com.apple.timemachine.supported;' + r'.dbfseventsd;' + r'.DocumentRevisions-V100*;' + r'.DS_Store;' + r'.fseventsd;' + r'.PKInstallSandboxManager;' + r'.Spotlight*;' + r'.SymAV*;' + r'.symSchedScanLockxz;' + r'.TemporaryItems;' + r'.Trash*;' + r'.vol;' + r'.VolumeIcon.icns;' + r'desktop.ini;' + r'Desktop?DB;' + r'Desktop?DF;' + r'hiberfil.sys;' + r'lost+found;' + r'Network?Trash?Folder;' + r'pagefile.sys;' + r'Recycled;' + r'RECYCLER;' + r'System?Volume?Information;' + r'Temporary?Items;' + r'Thumbs.db' + r' /to=%client_dir%\Transfer_%iso_date%\ ' + ), + 'L_ELEV': 'True', + 'Extra Code': [ + r'call "%bin%\Scripts\init_client_dir.cmd" /Logs /Transfer', + ], + }, + 'FastCopy': { + 'L_TYPE': 'Executable', + 'L_PATH': 'FastCopy', + 'L_ITEM': 'FastCopy.exe', + 'L_ARGS': ( + r' /logfile=%log_dir%\Tools\FastCopy.log' + r' /cmd=noexist_only' + r' /utf8' + r' /skip_empty_dir' + r' /linkdest' + r' /exclude=' + r'$RECYCLE.BIN;' + r'$Recycle.Bin;' + r'.AppleDB;' + r'.AppleDesktop;' + r'.AppleDouble;' + r'.com.apple.timemachine.supported;' + r'.dbfseventsd;' + r'.DocumentRevisions-V100*;' + r'.DS_Store;' + r'.fseventsd;' + r'.PKInstallSandboxManager;' + r'.Spotlight*;' + r'.SymAV*;' + r'.symSchedScanLockxz;' + r'.TemporaryItems;' + r'.Trash*;' + r'.vol;' + r'.VolumeIcon.icns;' + r'desktop.ini;' + r'Desktop?DB;' + r'Desktop?DF;' + r'hiberfil.sys;' + r'lost+found;' + r'Network?Trash?Folder;' + r'pagefile.sys;' + r'Recycled;' + r'RECYCLER;' + r'System?Volume?Information;' + r'Temporary?Items;' + r'Thumbs.db' + r' /to=%client_dir%\Transfer_%iso_date%\ ' + ), + 'Extra Code': [ + r'call "%bin%\Scripts\init_client_dir.cmd" /Logs /Transfer', + ], + }, + 'KVRT': { + 'L_TYPE': 'Executable', + 'L_PATH': 'KVRT', + 'L_ITEM': 'KVRT.exe', + 'L_ARGS': ( + r' -accepteula' + r' -d %q_dir%' + r' -processlevel 3' + r' -dontcryptsupportinfo' + r' -fixednames' + ), + 'Extra Code': [ + r'call "%bin%\Scripts\init_client_dir.cmd" /Quarantine', + r'set "q_dir=%client_dir%\Quarantine\KVRT"', + r'mkdir "%q_dir%">nul 2>&1', + ], + }, + 'Mac & Linux Reader': { + 'L_TYPE': 'Executable', + 'L_PATH': 'LinuxReader', + 'L_ITEM': 'LinuxReader.exe', + 'L_ELEV': 'True', + }, + 'Transferred Keys': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'transferred_keys.py', + 'L_ELEV': 'True', + }, + 'User Data Transfer': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'user_data_transfer.py', + 'L_ELEV': 'True', + }, + 'XYplorer (as ADMIN)': { + 'L_TYPE': 'Executable', + 'L_PATH': 'XYplorerFree', + 'L_ITEM': 'XYplorerFree.exe', + 'L_ARGS': r'/exp /win=max %userprofile%', + 'L_ELEV': 'True', + }, + 'XYplorer': { + 'L_TYPE': 'Executable', + 'L_PATH': 'XYplorerFree', + 'L_ITEM': 'XYplorerFree.exe', + 'L_ARGS': r'/exp /win=max %userprofile%', + }, + }, + r'Diagnostics': { + 'AIDA64': { + 'L_TYPE': 'Executable', + 'L_PATH': 'AIDA64', + 'L_ITEM': 'aida64.exe', + }, + 'ProduKey': { + 'L_TYPE': 'Executable', + 'L_PATH': 'ProduKey', + 'L_ITEM': 'ProduKey.exe', + 'L_ELEV': 'True', + 'Extra Code': [ + r'if exist "%bin%\ProduKey" (', + r' del "%bin%\ProduKey\ProduKey.cfg" 2>nul', + r' del "%bin%\ProduKey\ProduKey64.cfg" 2>nul', + r')', + ], + }, + 'System Diagnostics': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'system_diagnostics.py', + 'L_ELEV': 'True', + }, + }, + r'Diagnostics\Extras': { + 'Autoruns (with VirusTotal Scan)': { + 'L_TYPE': 'Executable', + 'L_PATH': 'Autoruns', + 'L_ITEM': 'Autoruns.exe', + 'L_ARGS': '-e', + 'Extra Code': [ + r'reg add HKCU\Software\Sysinternals\AutoRuns /v checkvirustotal /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v EulaAccepted /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v shownomicrosoft /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v shownowindows /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v showonlyvirustotal /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v submitvirustotal /t REG_DWORD /d 0 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v verifysignatures /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns\SigCheck /v EulaAccepted /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns\Streams /v EulaAccepted /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns\VirusTotal /v VirusTotalTermsAccepted /t REG_DWORD /d 1 /f >nul', + ], + }, + 'BleachBit': { + 'L_TYPE': 'Executable', + 'L_PATH': 'BleachBit', + 'L_ITEM': 'bleachbit.exe', + }, + 'BlueScreenView': { + 'L_TYPE': 'Executable', + 'L_PATH': 'BlueScreenView', + 'L_ITEM': 'BlueScreenView.exe', + }, + 'ERUNT': { + 'L_TYPE': 'Executable', + 'L_PATH': 'erunt', + 'L_ITEM': 'ERUNT.EXE', + 'L_ARGS': '%client_dir%\Backups\Registry\%iso_date% sysreg curuser otherusers', + 'L_ELEV': 'True', + 'Extra Code': [ + r'call "%bin%\Scripts\init_client_dir.cmd" /Logs', + ], + }, + 'FurMark': { + 'L_TYPE': 'Executable', + 'L_PATH': 'FurMark', + 'L_ITEM': 'FurMark.exe', + }, + 'HDTune Pro': { + 'L_TYPE': 'Executable', + 'L_PATH': 'HDTunePro', + 'L_ITEM': 'HDTunePro.exe', + }, + 'HitmanPro': { + 'L_TYPE': 'Executable', + 'L_PATH': 'HitmanPro', + 'L_ITEM': 'HitmanPro.exe', + 'Extra Code': [ + r'call "%bin%\Scripts\init_client_dir.cmd" /Logs', + ], + }, + 'HWiNFO': { + 'L_TYPE': 'Executable', + 'L_PATH': 'HWiNFO', + 'L_ITEM': 'HWiNFO.exe', + 'Extra Code': [ + r'for %%a in (32 64) do (', + r' copy /y "%bin%\HWiNFO\general.ini" "%bin%\HWiNFO\HWiNFO%%a.ini"', + r' (echo SensorsOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', + r' (echo SummaryOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', + r')', + ], + }, + 'HWiNFO (Sensors)': { + 'L_TYPE': 'Executable', + 'L_PATH': 'HWiNFO', + 'L_ITEM': 'HWiNFO.exe', + 'Extra Code': [ + r'for %%a in (32 64) do (', + r' copy /y "%bin%\HWiNFO\general.ini" "%bin%\HWiNFO\HWiNFO%%a.ini"', + r' (echo SensorsOnly=1)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', + r' (echo SummaryOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', + r')', + ], + }, + }, + r'Drivers': { + 'Intel RST (Current Release)': { + 'L_TYPE': 'Executable', + 'L_PATH': '_Drivers\Intel RST', + 'L_ITEM': 'SetupRST_16.5.exe', + 'L_7ZIP': 'SetupRST_16.5.exe', + }, + 'Intel RST (Previous Releases)': { + 'L_TYPE': 'Folder', + 'L_PATH': '_Drivers\Intel RST', + 'L_ITEM': '.', + 'L_NCMD': 'True', + }, + 'Intel SSD Toolbox': { + 'L_TYPE': 'Executable', + 'L_PATH': r'_Drivers\Intel SSD Toolbox', + 'L_ITEM': 'Intel SSD Toolbox.exe', + }, + 'Samsing Magician': { + 'L_TYPE': 'Executable', + 'L_PATH': r'_Drivers\Samsung Magician', + 'L_ITEM': 'Samsung Magician.exe', + }, + 'Snappy Driver Installer Origin': { + 'L_TYPE': 'Executable', + 'L_PATH': '_Drivers\SDIO', + 'L_ITEM': 'SDIO.exe', + }, + }, + r'Drivers\Extras': { + 'Acer': { + 'L_TYPE': 'Executable', + 'L_PATH': 'HWiNFO', + 'L_ITEM': 'HWiNFO.exe', + 'Extra Code': [ + r'for %%a in (32 64) do (', + r' copy /y "%bin%\HWiNFO\general.ini" "%bin%\HWiNFO\HWiNFO%%a.ini"', + r' (echo SensorsOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', + r' (echo SummaryOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', + r')', + r'start "" "http://us.acer.com/ac/en/US/content/drivers"', + ], + }, + 'Lenovo': { + 'L_TYPE': 'Executable', + 'L_PATH': 'HWiNFO', + 'L_ITEM': 'HWiNFO.exe', + 'Extra Code': [ + r'for %%a in (32 64) do (', + r' copy /y "%bin%\HWiNFO\general.ini" "%bin%\HWiNFO\HWiNFO%%a.ini"', + r' (echo SensorsOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', + r' (echo SummaryOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', + r')', + r'start "" "https://pcsupport.lenovo.com/us/en/"', + ], + }, + 'Toshiba': { + 'L_TYPE': 'Executable', + 'L_PATH': 'HWiNFO', + 'L_ITEM': 'HWiNFO.exe', + 'Extra Code': [ + r'for %%a in (32 64) do (', + r' copy /y "%bin%\HWiNFO\general.ini" "%bin%\HWiNFO\HWiNFO%%a.ini"', + r' (echo SensorsOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', + r' (echo SummaryOnly=0)>>"%bin%\HWiNFO\HWiNFO%%a.ini"', + r')', + r'start "" "http://support.toshiba.com/drivers"', + ], + }, + }, + r'Installers': { + 'ESET NOD32 AV': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'install_eset_nod32_av.py', + 'L_ELEV': 'True', + }, + 'SW Bundle': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'install_sw_bundle.py', + 'L_ELEV': 'True', + }, + }, + r'Installers\Extras\Office\2016': { + 'Home and Business 2016 (x32)': { + 'L_TYPE': 'Office', + 'L_PATH': '2016', + 'L_ITEM': 'hb_32.xml', + 'L_NCMD': 'True', + }, + 'Home and Business 2016 (x64)': { + 'L_TYPE': 'Office', + 'L_PATH': '2016', + 'L_ITEM': 'hb_64.xml', + 'L_NCMD': 'True', + }, + 'Home and Student 2016 (x32)': { + 'L_TYPE': 'Office', + 'L_PATH': '2016', + 'L_ITEM': 'hs_32.xml', + 'L_NCMD': 'True', + }, + 'Home and Student 2016 (x64)': { + 'L_TYPE': 'Office', + 'L_PATH': '2016', + 'L_ITEM': 'hs_64.xml', + 'L_NCMD': 'True', + }, + 'Office 365 2016 (x32)': { + 'L_TYPE': 'Office', + 'L_PATH': '2016', + 'L_ITEM': '365_32.xml', + 'L_NCMD': 'True', + }, + 'Office 365 2016 (x64)': { + 'L_TYPE': 'Office', + 'L_PATH': '2016', + 'L_ITEM': '365_64.xml', + 'L_NCMD': 'True', + }, + }, + r'Installers\Extras\Runtimes': { + 'Visual C++ Runtimes': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'install_vcredists.py', + 'L_ELEV': 'True', + }, + }, + r'Misc': { + 'Cleanup CBS Temp Files': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'cbs_fix.py', + 'L_ELEV': 'True', + }, + 'ConEmu (as ADMIN)': { + 'L_TYPE': 'Executable', + 'L_PATH': 'ConEmu', + 'L_ITEM': 'ConEmu.exe', + 'L_ELEV': 'True', + }, + 'ConEmu': { + 'L_TYPE': 'Executable', + 'L_PATH': 'ConEmu', + 'L_ITEM': 'ConEmu.exe', + }, + 'Enter SafeMode': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'safemode_enter.py', + 'L_ELEV': 'True', + }, + 'Everything': { + 'L_TYPE': 'Executable', + 'L_PATH': 'Everything', + 'L_ITEM': 'Everything.exe', + 'L_ARGS': '-nodb', + 'L_ELEV': 'True', + }, + 'Exit SafeMode': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'safemode_exit.py', + 'L_ELEV': 'True', + }, + 'Network Stability Test': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'network_stability_test.py', + }, + 'Notepad++': { + 'L_TYPE': 'Executable', + 'L_PATH': 'notepadplusplus', + 'L_ITEM': 'notepadplusplus.exe', + }, + 'PuTTY': { + 'L_TYPE': 'Executable', + 'L_PATH': 'PuTTY', + 'L_ITEM': 'PUTTY.EXE', + }, + 'ShutUp10': { + 'L_TYPE': 'Executable', + 'L_PATH': 'ShutUp10', + 'L_ITEM': 'OOSU10.exe', + }, + 'ShutUp10 (1201 Minimal Selection)': { + 'L_TYPE': 'Executable', + 'L_PATH': 'ShutUp10', + 'L_ITEM': 'OOSU10.exe', + 'L_ARGS': '1201.cfg', + }, + 'WizTree': { + 'L_TYPE': 'Executable', + 'L_PATH': 'WizTree', + 'L_ITEM': 'WizTree.exe', + 'L_ELEV': 'True', + }, + 'XMPlay': { + 'L_TYPE': 'Executable', + 'L_PATH': 'XMPlay', + 'L_ITEM': 'xmplay.exe', + 'L_ARGS': '"%bin%\XMPlay\music.7z"', + }, + }, + r'Repairs': { + 'AdwCleaner': { + 'L_TYPE': 'Executable', + 'L_PATH': 'AdwCleaner', + 'L_ITEM': 'AdwCleaner.exe', + }, + 'Autoruns': { + 'L_TYPE': 'Executable', + 'L_PATH': 'Autoruns', + 'L_ITEM': 'Autoruns.exe', + 'L_ARGS': '-e', + 'Extra Code': [ + r'reg add HKCU\Software\Sysinternals\AutoRuns /v checkvirustotal /t REG_DWORD /d 0 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v EulaAccepted /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v shownomicrosoft /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v shownowindows /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v showonlyvirustotal /t REG_DWORD /d 0 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v submitvirustotal /t REG_DWORD /d 0 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns /v verifysignatures /t REG_DWORD /d 0 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns\SigCheck /v EulaAccepted /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns\Streams /v EulaAccepted /t REG_DWORD /d 1 /f >nul', + r'reg add HKCU\Software\Sysinternals\AutoRuns\VirusTotal /v VirusTotalTermsAccepted /t REG_DWORD /d 1 /f >nul', + ], + }, + 'CHKDSK': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'check_disk.py', + 'L_ELEV': 'True', + }, + 'DISM': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'dism.py', + 'L_ELEV': 'True', + }, + 'ESET Online Scanner': { + 'L_TYPE': 'Executable', + 'L_PATH': 'ESET', + 'L_ITEM': 'ESET.exe', + }, + 'KVRT': { + 'L_TYPE': 'Executable', + 'L_PATH': 'KVRT', + 'L_ITEM': 'KVRT.exe', + 'L_ARGS': ( + r' -accepteula' + r' -d %q_dir%' + r' -processlevel 3' + r' -dontcryptsupportinfo' + r' -fixednames' + ), + 'Extra Code': [ + r'call "%bin%\Scripts\init_client_dir.cmd" /Quarantine', + r'set "q_dir=%client_dir%\Quarantine\KVRT"', + r'mkdir "%q_dir%">nul 2>&1', + ], + }, + 'RKill': { + 'L_TYPE': 'Executable', + 'L_PATH': 'RKill', + 'L_ITEM': 'RKill.exe', + 'L_ARGS': '-s -l %log_dir%\Tools\RKill.log', + 'L_ELEV': 'True', + 'Extra Code': [ + r'call "%bin%\Scripts\init_client_dir.cmd" /Logs', + ], + }, + 'SFC Scan': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'sfc_scan.py', + 'L_ELEV': 'True', + }, + 'TDSSKiller': { + 'L_TYPE': 'Executable', + 'L_PATH': 'TDSSKiller', + 'L_ITEM': 'TDSSKiller.exe', + 'L_ARGS': ( + r' -l %log_dir%\Tools\TDSSKiller.log' + r' -qpath %q_dir%' + r' -accepteula' + r' -accepteulaksn' + r' -dcexact' + r' -tdlfs' + ), + 'Extra Code': [ + r'call "%bin%\Scripts\init_client_dir.cmd" /Quarantine', + r'set "q_dir=%client_dir%\Quarantine\TDSSKiller"', + r'mkdir "%q_dir%">nul 2>&1', + ], + }, + 'WinAIO Repair': { + 'L_TYPE': 'Executable', + 'L_PATH': 'WinAIORepair', + 'L_ITEM': 'Repair_Windows.exe', + 'L_ELEV': 'True', + 'Extra Code': [ + r'copy /y "%bin%\WinAIORepair\__empty.ini" "%bin%\WinAIORepair\settings.ini"', + ], + }, + 'WinAIO Repair (Fix Associations)': { + 'L_TYPE': 'Executable', + 'L_PATH': 'WinAIORepair', + 'L_ITEM': 'Repair_Windows.exe', + 'L_ELEV': 'True', + 'Extra Code': [ + r'copy /y "%bin%\WinAIORepair\__associations.ini" "%bin%\WinAIORepair\settings.ini"', + ], + }, + 'WinAIO Repair (Fix Permissions)': { + 'L_TYPE': 'Executable', + 'L_PATH': 'WinAIORepair', + 'L_ITEM': 'Repair_Windows.exe', + 'L_ELEV': 'True', + 'Extra Code': [ + r'copy /y "%bin%\WinAIORepair\__permissions.ini" "%bin%\WinAIORepair\settings.ini"', + ], + }, + }, + r'Uninstallers': { + 'IObit Uninstaller': { + 'L_TYPE': 'Executable', + 'L_PATH': 'IObitUninstallerPortable', + 'L_ITEM': 'IObitUninstallerPortable.exe', + }, + }, + } if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/settings/main.py b/.bin/Scripts/settings/main.py index 5e9002f5..5869580b 100644 --- a/.bin/Scripts/settings/main.py +++ b/.bin/Scripts/settings/main.py @@ -5,7 +5,7 @@ ENABLED_OPEN_LOGS = False ENABLED_TICKET_NUMBERS = False ENABLED_UPLOAD_DATA = True HW_OVERRIDES_FORCED = False -HW_OVERRIDES_LIMITED = True # If True this disables HW_OVERRIDE_FORCED +HW_OVERRIDES_LIMITED = True # If True this disables HW_OVERRIDE_FORCED # STATIC VARIABLES (also used by BASH and BATCH files) ## NOTE: There are no spaces around the = for easier parsing in BASH and BATCH @@ -17,7 +17,7 @@ SUPPORT_MESSAGE='Please let support know by opening an issue on Gogs' # imgur IMGUR_CLIENT_ID='3d1ee1d38707b85' # Live Linux -MPRIME_LIMIT='7' # of minutes to run Prime95 during hw-diags +MPRIME_LIMIT='7' # of minutes to run Prime95 during hw-diags ROOT_PASSWORD='1201 loves computers!' TECH_PASSWORD='Sorted1201' # Root Certificate Authority @@ -37,59 +37,61 @@ WIFI_PASSWORD='justintime!' ## one server serves multiple shares then you have to use the same ## user/password for all of those shares. BACKUP_SERVERS = [ - { 'IP': '10.11.1.20', - 'Name': 'Anaconda', - 'Mounted': False, - 'Share': 'Backups', - 'User': 'cx', - 'Pass': 'cx', - 'RW-User': 'backup', - 'RW-Pass': '1201 loves computers!', - }, + { 'IP': '10.11.1.20', + 'Name': 'Anaconda', + 'Mounted': False, + 'Share': 'Backups', + 'User': 'cx', + 'Pass': 'cx', + 'RW-User': 'backup', + 'RW-Pass': '1201 loves computers!', + }, ] BENCHMARK_SERVER = { - 'Name': 'Nextcloud', - 'Short Url': 'https://1201north.ddns.net:8001/index.php/f/27892', - 'Url': 'https://1201north.ddns.net:8001/public.php/webdav/Benchmarks', - 'User': 'RAE7ajRk25CBnW6', - 'Pass': '', + 'Name': 'Nextcloud', + 'Short Url': 'https://1201north.ddns.net:8001/index.php/f/27892', + 'Url': 'https://1201north.ddns.net:8001/public.php/webdav/Benchmarks', + 'User': 'RAE7ajRk25CBnW6', + 'Pass': '', } CRASH_SERVER = { - 'Name': 'Nextcloud', - 'Url': 'https://1201north.ddns.net:8001/public.php/webdav/WizardKit_Issues', - 'User': 'LoQ97J3r6CFGT2T', - 'Pass': '', + 'Name': 'Nextcloud', + 'Url': 'https://1201north.ddns.net:8001/public.php/webdav/WizardKit_Issues', + 'User': 'LoQ97J3r6CFGT2T', + 'Pass': '', } OFFICE_SERVER = { - 'IP': OFFICE_SERVER_IP, - 'Name': 'Anaconda', - 'Mounted': False, - 'Share': r'Public\Office\MS Office', - 'User': 'cx', - 'Pass': 'cx', - 'RW-User': 'backup', - 'RW-Pass': '1201 loves computers!', + 'IP': OFFICE_SERVER_IP, + 'Name': 'Anaconda', + 'Mounted': False, + 'Share': r'Public\Office\MS Office', + 'User': 'cx', + 'Pass': 'cx', + 'RW-User': 'backup', + 'RW-Pass': '1201 loves computers!', } QUICKBOOKS_SERVER = { - 'IP': QUICKBOOKS_SERVER_IP, - 'Name': 'Anaconda', - 'Mounted': False, - 'Share': r'Public\QuickBooks', - 'User': 'cx', - 'Pass': 'cx', - 'RW-User': 'backup', - 'RW-Pass': '1201 loves computers!', + 'IP': QUICKBOOKS_SERVER_IP, + 'Name': 'Anaconda', + 'Mounted': False, + 'Share': r'Public\QuickBooks', + 'User': 'cx', + 'Pass': 'cx', + 'RW-User': 'backup', + 'RW-Pass': '1201 loves computers!', } WINDOWS_SERVER = { - 'IP': '10.11.1.20', - 'Name': 'Anaconda', - 'Mounted': False, - 'Share': r'Public\Windows', - 'User': 'cx', - 'Pass': 'cx', - 'RW-User': 'backup', - 'RW-Pass': '1201 loves computers!', + 'IP': '10.11.1.20', + 'Name': 'Anaconda', + 'Mounted': False, + 'Share': r'Public\Windows', + 'User': 'cx', + 'Pass': 'cx', + 'RW-User': 'backup', + 'RW-Pass': '1201 loves computers!', } if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/settings/music.py b/.bin/Scripts/settings/music.py index a2d49f31..37f5d178 100644 --- a/.bin/Scripts/settings/music.py +++ b/.bin/Scripts/settings/music.py @@ -1,70 +1,72 @@ # Wizard Kit: Settings - Music MUSIC_MOD = [ - '104208#banana_boat.mod', - '114971#tilbury_fair.mod', - '132563#ufo_tune.mod', - '135906#magnetik_girl.xm', - '140628#autumn_in_budapest.xm', - '143198#summer_memories_3.xm', - '144405#hillbilly_billyboy.xm', - '154795#4mat_-_eternity.xm', - '155845#bookworm.mo3', - '155914#battleofsteel.xm', - '158975#1_channel_moog.it', - '165495#trans.s3m', - '168513#necros_-_introspection.s3m', - '169628#radix_-_feng_shui_schematics.xm', - '175238#unknown48_-_twilight.mod', - '33432#ambrozia.xm', - '33460#amigatre.mod', - '34594#CHARIOT.S3M', - '34596#BUTTERFL.XM', - '34654#CTGOBLIN.S3M', - '35151#bananasplit.mod', - '35280#DEADLOCK.XM', - '38591#compo_liam.xm', - '39987#crystald.s3m', - '40475#ELYSIUM.MOD', - '42146#enigma.mod', - '42519#GHOST2.MOD', - '42560#GSLINGER.MOD', - '42872#existing.xm', - '50427#nf-stven.xm', - '51549#overture.mod', - '54250#SATELL.S3M', - '54313#realmk.s3m', - '55789#scrambld.mod', - '57934#spacedeb.mod', - '59344#stardstm.mod', - '60395#2ND_PM.S3M', - '66187#external.xm', - '66343#beek-substitutionology.it', - '67561#radix-unreal_superhero.xm', - '70829#inside_out.s3m', - '83779#beyond_music.mod', - ] + '104208#banana_boat.mod', + '114971#tilbury_fair.mod', + '132563#ufo_tune.mod', + '135906#magnetik_girl.xm', + '140628#autumn_in_budapest.xm', + '143198#summer_memories_3.xm', + '144405#hillbilly_billyboy.xm', + '154795#4mat_-_eternity.xm', + '155845#bookworm.mo3', + '155914#battleofsteel.xm', + '158975#1_channel_moog.it', + '165495#trans.s3m', + '168513#necros_-_introspection.s3m', + '169628#radix_-_feng_shui_schematics.xm', + '175238#unknown48_-_twilight.mod', + '33432#ambrozia.xm', + '33460#amigatre.mod', + '34594#CHARIOT.S3M', + '34596#BUTTERFL.XM', + '34654#CTGOBLIN.S3M', + '35151#bananasplit.mod', + '35280#DEADLOCK.XM', + '38591#compo_liam.xm', + '39987#crystald.s3m', + '40475#ELYSIUM.MOD', + '42146#enigma.mod', + '42519#GHOST2.MOD', + '42560#GSLINGER.MOD', + '42872#existing.xm', + '50427#nf-stven.xm', + '51549#overture.mod', + '54250#SATELL.S3M', + '54313#realmk.s3m', + '55789#scrambld.mod', + '57934#spacedeb.mod', + '59344#stardstm.mod', + '60395#2ND_PM.S3M', + '66187#external.xm', + '66343#beek-substitutionology.it', + '67561#radix-unreal_superhero.xm', + '70829#inside_out.s3m', + '83779#beyond_music.mod', + ] MUSIC_SNES = [ - 'actr', - 'crock', - 'ct', - 'dkc', - 'dkq', - 'ff6', - 'fz', - 'loz3', - 'mmx', - 'ptws', - 'scv4', - 'sf', - 'sf2', - 'sgng', - 'smk', - 'smw', - 'yi', - 'zamn' - ] + 'actr', + 'crock', + 'ct', + 'dkc', + 'dkq', + 'ff6', + 'fz', + 'loz3', + 'mmx', + 'ptws', + 'scv4', + 'sf', + 'sf2', + 'sgng', + 'smk', + 'smw', + 'yi', + 'zamn' + ] if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/settings/osticket.py b/.bin/Scripts/settings/osticket.py index fe998eb2..6360a579 100644 --- a/.bin/Scripts/settings/osticket.py +++ b/.bin/Scripts/settings/osticket.py @@ -28,6 +28,6 @@ OSTICKET = { } if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") # vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/settings/sources.py b/.bin/Scripts/settings/sources.py index 1dc650f2..55d30e0c 100644 --- a/.bin/Scripts/settings/sources.py +++ b/.bin/Scripts/settings/sources.py @@ -1,208 +1,208 @@ # Wizard Kit: Settings - Sources SOURCE_URLS = { - 'Adobe Reader DC': 'http://ardownload.adobe.com/pub/adobe/reader/win/AcrobatDC/1801120058/AcroRdrDC1801120058_en_US.exe', - 'AdwCleaner': 'https://downloads.malwarebytes.com/file/adwcleaner', - 'AIDA64': 'http://download.aida64.com/aida64engineer597.zip', - 'aria2': 'https://github.com/aria2/aria2/releases/download/release-1.34.0/aria2-1.34.0-win-32bit-build1.zip', - 'Autoruns': 'https://download.sysinternals.com/files/Autoruns.zip', - 'BleachBit': 'https://download.bleachbit.org/BleachBit-2.0-portable.zip', - 'BlueScreenView32': 'http://www.nirsoft.net/utils/bluescreenview.zip', - 'BlueScreenView64': 'http://www.nirsoft.net/utils/bluescreenview-x64.zip', - 'Caffeine': 'http://www.zhornsoftware.co.uk/caffeine/caffeine.zip', - 'ClassicStartSkin': 'http://www.classicshell.net/forum/download/file.php?id=3001&sid=9a195960d98fd754867dcb63d9315335', - 'Du': 'https://download.sysinternals.com/files/DU.zip', - 'ERUNT': 'http://www.aumha.org/downloads/erunt.zip', - 'ESET Online Scanner': 'https://download.eset.com/com/eset/tools/online_scanner/latest/esetonlinescanner_enu.exe', - 'ESET NOD32 AV': 'https://download.eset.com/com/eset/apps/home/eav/windows/latest/eav_nt64.exe', - 'Everything32': 'https://www.voidtools.com/Everything-1.4.1.895.x86.zip', - 'Everything64': 'https://www.voidtools.com/Everything-1.4.1.895.x64.zip', - 'FastCopy': 'http://ftp.vector.co.jp/70/64/2323/FastCopy354_installer.zip', - 'FurMark': 'https://geeks3d.com/dl/get/569', - 'Firefox uBO': 'https://addons.mozilla.org/firefox/downloads/file/1056733/ublock_origin-1.16.20-an+fx.xpi', - 'HitmanPro32': 'https://dl.surfright.nl/HitmanPro.exe', - 'HitmanPro64': 'https://dl.surfright.nl/HitmanPro_x64.exe', - 'HWiNFO': 'http://app.oldfoss.com:81/download/HWiNFO/hwi_588.zip', - 'Intel SSD Toolbox': r'https://downloadmirror.intel.com/27656/eng/Intel%20SSD%20Toolbox%20-%20v3.5.2.exe', - 'IOBit_Uninstaller': 'https://portableapps.duckduckgo.com/IObitUninstallerPortable_7.5.0.7.paf.exe', - 'KVRT': 'http://devbuilds.kaspersky-labs.com/devbuilds/KVRT/latest/full/KVRT.exe', - 'Linux Reader': 'https://www.diskinternals.com/download/Linux_Reader.exe', - 'Macs Fan Control': 'https://www.crystalidea.com/downloads/macsfancontrol_setup.exe', - 'NirCmd32': 'https://www.nirsoft.net/utils/nircmd.zip', - 'NirCmd64': 'https://www.nirsoft.net/utils/nircmd-x64.zip', - 'NotepadPlusPlus': 'https://notepad-plus-plus.org/repository/7.x/7.5.8/npp.7.5.8.bin.minimalist.7z', - 'Office Deployment Tool 2016': 'https://download.microsoft.com/download/2/7/A/27AF1BE6-DD20-4CB4-B154-EBAB8A7D4A7E/officedeploymenttool_10810.33603.exe', - 'ProduKey32': 'http://www.nirsoft.net/utils/produkey.zip', - 'ProduKey64': 'http://www.nirsoft.net/utils/produkey-x64.zip', - 'PuTTY': 'https://the.earth.li/~sgtatham/putty/latest/w32/putty.zip', - 'RKill': 'https://www.bleepingcomputer.com/download/rkill/dl/10/', - 'Samsung Magician': 'https://s3.ap-northeast-2.amazonaws.com/global.semi.static/SAMSUNG_SSD_v5_2_1_180523/CD0CFAC4675B9E502899B41BE00525C3909ECE3AD57CC1A2FB6B74A766B2A1EA/Samsung_Magician_Installer.zip', - 'SDIO Themes': 'http://snappy-driver-installer.org/downloads/SDIO_Themes.zip', - 'SDIO Torrent': 'http://snappy-driver-installer.org/downloads/SDIO_Update.torrent', - 'ShutUp10': 'https://dl5.oo-software.com/files/ooshutup10/OOSU10.exe', - 'TDSSKiller': 'https://media.kaspersky.com/utilities/VirusUtilities/EN/tdsskiller.exe', - 'TestDisk': 'https://www.cgsecurity.org/testdisk-7.1-WIP.win.zip', - 'wimlib32': 'https://wimlib.net/downloads/wimlib-1.12.0-windows-i686-bin.zip', - 'wimlib64': 'https://wimlib.net/downloads/wimlib-1.12.0-windows-x86_64-bin.zip', - 'WinAIO Repair': 'http://www.tweaking.com/files/setups/tweaking.com_windows_repair_aio.zip', - 'Winapp2': 'https://github.com/MoscaDotTo/Winapp2/archive/master.zip', - 'WizTree': 'https://antibody-software.com/files/wiztree_3_26_portable.zip', - 'XMPlay 7z': 'https://support.xmplay.com/files/16/xmp-7z.zip?v=800962', - 'XMPlay Game': 'https://support.xmplay.com/files/12/xmp-gme.zip?v=515637', - 'XMPlay RAR': 'https://support.xmplay.com/files/16/xmp-rar.zip?v=409646', - 'XMPlay WAModern': 'https://support.xmplay.com/files/10/WAModern.zip?v=207099', - 'XMPlay': 'https://support.xmplay.com/files/20/xmplay383.zip?v=298195', - 'XYplorerFree': 'https://www.xyplorer.com/download/xyplorer_free_noinstall.zip', - } + 'Adobe Reader DC': 'http://ardownload.adobe.com/pub/adobe/reader/win/AcrobatDC/1801120058/AcroRdrDC1801120058_en_US.exe', + 'AdwCleaner': 'https://downloads.malwarebytes.com/file/adwcleaner', + 'AIDA64': 'http://download.aida64.com/aida64engineer597.zip', + 'aria2': 'https://github.com/aria2/aria2/releases/download/release-1.34.0/aria2-1.34.0-win-32bit-build1.zip', + 'Autoruns': 'https://download.sysinternals.com/files/Autoruns.zip', + 'BleachBit': 'https://download.bleachbit.org/BleachBit-2.0-portable.zip', + 'BlueScreenView32': 'http://www.nirsoft.net/utils/bluescreenview.zip', + 'BlueScreenView64': 'http://www.nirsoft.net/utils/bluescreenview-x64.zip', + 'Caffeine': 'http://www.zhornsoftware.co.uk/caffeine/caffeine.zip', + 'ClassicStartSkin': 'http://www.classicshell.net/forum/download/file.php?id=3001&sid=9a195960d98fd754867dcb63d9315335', + 'Du': 'https://download.sysinternals.com/files/DU.zip', + 'ERUNT': 'http://www.aumha.org/downloads/erunt.zip', + 'ESET Online Scanner': 'https://download.eset.com/com/eset/tools/online_scanner/latest/esetonlinescanner_enu.exe', + 'ESET NOD32 AV': 'https://download.eset.com/com/eset/apps/home/eav/windows/latest/eav_nt64.exe', + 'Everything32': 'https://www.voidtools.com/Everything-1.4.1.895.x86.zip', + 'Everything64': 'https://www.voidtools.com/Everything-1.4.1.895.x64.zip', + 'FastCopy': 'http://ftp.vector.co.jp/70/64/2323/FastCopy354_installer.zip', + 'FurMark': 'https://geeks3d.com/dl/get/569', + 'Firefox uBO': 'https://addons.mozilla.org/firefox/downloads/file/1056733/ublock_origin-1.16.20-an+fx.xpi', + 'HitmanPro32': 'https://dl.surfright.nl/HitmanPro.exe', + 'HitmanPro64': 'https://dl.surfright.nl/HitmanPro_x64.exe', + 'HWiNFO': 'http://app.oldfoss.com:81/download/HWiNFO/hwi_588.zip', + 'Intel SSD Toolbox': r'https://downloadmirror.intel.com/27656/eng/Intel%20SSD%20Toolbox%20-%20v3.5.2.exe', + 'IOBit_Uninstaller': 'https://portableapps.duckduckgo.com/IObitUninstallerPortable_7.5.0.7.paf.exe', + 'KVRT': 'http://devbuilds.kaspersky-labs.com/devbuilds/KVRT/latest/full/KVRT.exe', + 'Linux Reader': 'https://www.diskinternals.com/download/Linux_Reader.exe', + 'Macs Fan Control': 'https://www.crystalidea.com/downloads/macsfancontrol_setup.exe', + 'NirCmd32': 'https://www.nirsoft.net/utils/nircmd.zip', + 'NirCmd64': 'https://www.nirsoft.net/utils/nircmd-x64.zip', + 'NotepadPlusPlus': 'https://notepad-plus-plus.org/repository/7.x/7.5.8/npp.7.5.8.bin.minimalist.7z', + 'Office Deployment Tool 2016': 'https://download.microsoft.com/download/2/7/A/27AF1BE6-DD20-4CB4-B154-EBAB8A7D4A7E/officedeploymenttool_10810.33603.exe', + 'ProduKey32': 'http://www.nirsoft.net/utils/produkey.zip', + 'ProduKey64': 'http://www.nirsoft.net/utils/produkey-x64.zip', + 'PuTTY': 'https://the.earth.li/ sgtatham/putty/latest/w32/putty.zip', + 'RKill': 'https://www.bleepingcomputer.com/download/rkill/dl/10/', + 'Samsung Magician': 'https://s3.ap-northeast-2.amazonaws.com/global.semi.static/SAMSUNG_SSD_v5_2_1_180523/CD0CFAC4675B9E502899B41BE00525C3909ECE3AD57CC1A2FB6B74A766B2A1EA/Samsung_Magician_Installer.zip', + 'SDIO Themes': 'http://snappy-driver-installer.org/downloads/SDIO_Themes.zip', + 'SDIO Torrent': 'http://snappy-driver-installer.org/downloads/SDIO_Update.torrent', + 'ShutUp10': 'https://dl5.oo-software.com/files/ooshutup10/OOSU10.exe', + 'TDSSKiller': 'https://media.kaspersky.com/utilities/VirusUtilities/EN/tdsskiller.exe', + 'TestDisk': 'https://www.cgsecurity.org/testdisk-7.1-WIP.win.zip', + 'wimlib32': 'https://wimlib.net/downloads/wimlib-1.12.0-windows-i686-bin.zip', + 'wimlib64': 'https://wimlib.net/downloads/wimlib-1.12.0-windows-x86_64-bin.zip', + 'WinAIO Repair': 'http://www.tweaking.com/files/setups/tweaking.com_windows_repair_aio.zip', + 'Winapp2': 'https://github.com/MoscaDotTo/Winapp2/archive/master.zip', + 'WizTree': 'https://antibody-software.com/files/wiztree_3_26_portable.zip', + 'XMPlay 7z': 'https://support.xmplay.com/files/16/xmp-7z.zip?v=800962', + 'XMPlay Game': 'https://support.xmplay.com/files/12/xmp-gme.zip?v=515637', + 'XMPlay RAR': 'https://support.xmplay.com/files/16/xmp-rar.zip?v=409646', + 'XMPlay WAModern': 'https://support.xmplay.com/files/10/WAModern.zip?v=207099', + 'XMPlay': 'https://support.xmplay.com/files/20/xmplay383.zip?v=298195', + 'XYplorerFree': 'https://www.xyplorer.com/download/xyplorer_free_noinstall.zip', + } VCREDIST_SOURCES = { - '2010sp1': { - '32': 'https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x86.exe', - '64': 'https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x64.exe', - }, - '2012u4': { - '32': 'https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x86.exe', - '64': 'https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x64.exe', - }, - '2013': { - '32': 'https://download.microsoft.com/download/0/5/6/056dcda9-d667-4e27-8001-8a0c6971d6b1/vcredist_x86.exe', - '64': 'https://download.microsoft.com/download/0/5/6/056dcda9-d667-4e27-8001-8a0c6971d6b1/vcredist_x64.exe', - }, - '2017': { - '32': 'https://aka.ms/vs/15/release/vc_redist.x86.exe', - '64': 'https://aka.ms/vs/15/release/vc_redist.x64.exe', - }, - } + '2010sp1': { + '32': 'https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x86.exe', + '64': 'https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x64.exe', + }, + '2012u4': { + '32': 'https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x86.exe', + '64': 'https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x64.exe', + }, + '2013': { + '32': 'https://download.microsoft.com/download/0/5/6/056dcda9-d667-4e27-8001-8a0c6971d6b1/vcredist_x86.exe', + '64': 'https://download.microsoft.com/download/0/5/6/056dcda9-d667-4e27-8001-8a0c6971d6b1/vcredist_x64.exe', + }, + '2017': { + '32': 'https://aka.ms/vs/15/release/vc_redist.x86.exe', + '64': 'https://aka.ms/vs/15/release/vc_redist.x64.exe', + }, + } NINITE_SOURCES = { - 'Bundles': { - 'Legacy.exe': '.net4.7.2-7zip-chrome-firefox-sumatrapdf-vlc', - 'Modern.exe': '.net4.7.2-7zip-chrome-classicstart-firefox-sumatrapdf-vlc', - }, - 'Audio-Video': { - 'AIMP.exe': 'aimp', - 'Audacity.exe': 'audacity', - 'CCCP.exe': 'cccp', - 'Foobar2000.exe': 'foobar', - 'GOM.exe': 'gom', - 'HandBrake.exe': 'handbrake', - 'iTunes.exe': 'itunes', - 'K-Lite Codecs.exe': 'klitecodecs', - 'MediaMonkey.exe': 'mediamonkey', - 'MusicBee.exe': 'musicbee', - 'Spotify.exe': 'spotify', - 'VLC.exe': 'vlc', - 'Winamp.exe': 'winamp', - }, - 'Cloud Storage': { - 'Dropbox.exe': 'dropbox', - 'Google Backup & Sync.exe': 'googlebackupandsync', - 'Mozy.exe': 'mozy', - 'OneDrive.exe': 'onedrive', - 'SugarSync.exe': 'sugarsync', - }, - 'Communication': { - 'Discord': 'discord', - 'Pidgin.exe': 'pidgin', - 'Skype.exe': 'skype', - 'Trillian.exe': 'trillian', - }, - 'Compression': { - '7-Zip.exe': '7zip', - 'PeaZip.exe': 'peazip', - 'WinRAR.exe': 'winrar', - }, - 'Developer': { - 'Eclipse.exe': 'eclipse', - 'JDK 8.exe': 'jdk8', - 'JDK 8 (x64).exe': 'jdkx8', - 'Notepad++.exe': 'notepadplusplus', - 'PuTTY.exe': 'putty', - 'Python 2.exe': 'python', - 'Visual Studio Code.exe': 'vscode', - 'WinMerge.exe': 'winmerge', - 'WinSCP.exe': 'winscp', - }, - 'File Sharing': { - 'qBittorrent.exe': 'qbittorrent', - }, - 'Image-Photo': { - 'Blender.exe': 'blender', - 'FastStone.exe': 'faststone', - 'GIMP.exe': 'gimp', - 'Greenshot.exe': 'greenshot', - 'Inkscape.exe': 'inkscape', - 'IrfanView.exe': 'irfanview', - 'Krita.exe': 'krita', - 'Paint.NET.exe': 'paint.net', - 'ShareX.exe': 'sharex', - 'XnView.exe': 'xnview', - }, - 'Misc': { - 'Evernote.exe': 'evernote', - 'Everything.exe': 'everything', - 'KeePass 2.exe': 'keepass2', - 'Google Earth.exe': 'googleearth', - 'NV Access.exe': 'nvda', - 'Steam.exe': 'steam', - }, - 'Office': { - 'CutePDF.exe': 'cutepdf', - 'Foxit Reader.exe': 'foxit', - 'LibreOffice.exe': 'libreoffice', - 'OpenOffice.exe': 'openoffice', - 'PDFCreator.exe': 'pdfcreator', - 'SumatraPDF.exe': 'sumatrapdf', - 'Thunderbird.exe': 'thunderbird', - }, - 'Runtimes': { - 'Adobe Air.exe': 'air', - 'dotNET.exe': '.net4.7.2', - 'Java 8.exe': 'java8', - 'Shockwave.exe': 'shockwave', - 'Silverlight.exe': 'silverlight', - }, - 'Security': { - 'Avast.exe': 'avast', - 'AVG.exe': 'avg', - 'Avira.exe': 'avira', - 'Microsoft Security Essentials.exe': 'essentials', - 'Malwarebytes Anti-Malware.exe': 'malwarebytes', - 'Spybot 2.exe': 'spybot2', - 'SUPERAntiSpyware.exe': 'super', - }, - 'Utilities': { - 'CDBurnerXP.exe': 'cdburnerxp', - 'Classic Start.exe': 'classicstart', - 'Glary Utilities.exe': 'glary', - 'ImgBurn.exe': 'imgburn', - 'InfraRecorder.exe': 'infrarecorder', - 'Launchy.exe': 'launchy', - 'RealVNC.exe': 'realvnc', - 'Revo Uninstaller.exe': 'revo', - 'TeamViewer 13.exe': 'teamviewer13', - 'TeraCopy.exe': 'teracopy', - 'WinDirStat.exe': 'windirstat', - }, - 'Web Browsers': { - 'Google Chrome.exe': 'chrome', - 'Mozilla Firefox.exe': 'firefox', - 'Opera Chromium.exe': 'operaChromium', - }, - } + 'Bundles': { + 'Legacy.exe': '.net4.7.2-7zip-chrome-firefox-sumatrapdf-vlc', + 'Modern.exe': '.net4.7.2-7zip-chrome-classicstart-firefox-sumatrapdf-vlc', + }, + 'Audio-Video': { + 'AIMP.exe': 'aimp', + 'Audacity.exe': 'audacity', + 'CCCP.exe': 'cccp', + 'Foobar2000.exe': 'foobar', + 'GOM.exe': 'gom', + 'HandBrake.exe': 'handbrake', + 'iTunes.exe': 'itunes', + 'K-Lite Codecs.exe': 'klitecodecs', + 'MediaMonkey.exe': 'mediamonkey', + 'MusicBee.exe': 'musicbee', + 'Spotify.exe': 'spotify', + 'VLC.exe': 'vlc', + 'Winamp.exe': 'winamp', + }, + 'Cloud Storage': { + 'Dropbox.exe': 'dropbox', + 'Google Backup & Sync.exe': 'googlebackupandsync', + 'Mozy.exe': 'mozy', + 'OneDrive.exe': 'onedrive', + 'SugarSync.exe': 'sugarsync', + }, + 'Communication': { + 'Discord': 'discord', + 'Pidgin.exe': 'pidgin', + 'Skype.exe': 'skype', + 'Trillian.exe': 'trillian', + }, + 'Compression': { + '7-Zip.exe': '7zip', + 'PeaZip.exe': 'peazip', + 'WinRAR.exe': 'winrar', + }, + 'Developer': { + 'Eclipse.exe': 'eclipse', + 'JDK 8.exe': 'jdk8', + 'JDK 8 (x64).exe': 'jdkx8', + 'Notepad++.exe': 'notepadplusplus', + 'PuTTY.exe': 'putty', + 'Python 2.exe': 'python', + 'Visual Studio Code.exe': 'vscode', + 'WinMerge.exe': 'winmerge', + 'WinSCP.exe': 'winscp', + }, + 'File Sharing': { + 'qBittorrent.exe': 'qbittorrent', + }, + 'Image-Photo': { + 'Blender.exe': 'blender', + 'FastStone.exe': 'faststone', + 'GIMP.exe': 'gimp', + 'Greenshot.exe': 'greenshot', + 'Inkscape.exe': 'inkscape', + 'IrfanView.exe': 'irfanview', + 'Krita.exe': 'krita', + 'Paint.NET.exe': 'paint.net', + 'ShareX.exe': 'sharex', + 'XnView.exe': 'xnview', + }, + 'Misc': { + 'Evernote.exe': 'evernote', + 'Everything.exe': 'everything', + 'KeePass 2.exe': 'keepass2', + 'Google Earth.exe': 'googleearth', + 'NV Access.exe': 'nvda', + 'Steam.exe': 'steam', + }, + 'Office': { + 'CutePDF.exe': 'cutepdf', + 'Foxit Reader.exe': 'foxit', + 'LibreOffice.exe': 'libreoffice', + 'OpenOffice.exe': 'openoffice', + 'PDFCreator.exe': 'pdfcreator', + 'SumatraPDF.exe': 'sumatrapdf', + 'Thunderbird.exe': 'thunderbird', + }, + 'Runtimes': { + 'Adobe Air.exe': 'air', + 'dotNET.exe': '.net4.7.2', + 'Java 8.exe': 'java8', + 'Shockwave.exe': 'shockwave', + 'Silverlight.exe': 'silverlight', + }, + 'Security': { + 'Avast.exe': 'avast', + 'AVG.exe': 'avg', + 'Avira.exe': 'avira', + 'Microsoft Security Essentials.exe': 'essentials', + 'Malwarebytes Anti-Malware.exe': 'malwarebytes', + 'Spybot 2.exe': 'spybot2', + 'SUPERAntiSpyware.exe': 'super', + }, + 'Utilities': { + 'CDBurnerXP.exe': 'cdburnerxp', + 'Classic Start.exe': 'classicstart', + 'Glary Utilities.exe': 'glary', + 'ImgBurn.exe': 'imgburn', + 'InfraRecorder.exe': 'infrarecorder', + 'Launchy.exe': 'launchy', + 'RealVNC.exe': 'realvnc', + 'Revo Uninstaller.exe': 'revo', + 'TeamViewer 13.exe': 'teamviewer13', + 'TeraCopy.exe': 'teracopy', + 'WinDirStat.exe': 'windirstat', + }, + 'Web Browsers': { + 'Google Chrome.exe': 'chrome', + 'Mozilla Firefox.exe': 'firefox', + 'Opera Chromium.exe': 'operaChromium', + }, + } RST_SOURCES = { - #SetupRST_12.0.exe : Removed from download center? - #SetupRST_12.5.exe : Removed from download center? - #SetupRST_12.8.exe : Removed from download center? - 'SetupRST_12.9.exe': 'https://downloadmirror.intel.com/23496/eng/SetupRST.exe', - #SetupRST_13.x.exe : Broken, doesn't support > .NET 4.5 - 'SetupRST_14.0.exe': 'https://downloadmirror.intel.com/25091/eng/SetupRST.exe', - 'SetupRST_14.8.exe': 'https://downloadmirror.intel.com/26759/eng/setuprst.exe', - 'SetupRST_15.8.exe': 'https://downloadmirror.intel.com/27442/eng/SetupRST.exe', - 'SetupRST_15.9.exe': 'https://downloadmirror.intel.com/27400/eng/SetupRST.exe', - 'SetupRST_16.0.exe': 'https://downloadmirror.intel.com/27681/eng/SetupRST.exe', - 'SetupRST_16.5.exe': 'https://downloadmirror.intel.com/27984/eng/SetupRST.exe', - } + #SetupRST_12.0.exe : Removed from download center? + #SetupRST_12.5.exe : Removed from download center? + #SetupRST_12.8.exe : Removed from download center? + 'SetupRST_12.9.exe': 'https://downloadmirror.intel.com/23496/eng/SetupRST.exe', + #SetupRST_13.x.exe : Broken, doesn't support > .NET 4.5 + 'SetupRST_14.0.exe': 'https://downloadmirror.intel.com/25091/eng/SetupRST.exe', + 'SetupRST_14.8.exe': 'https://downloadmirror.intel.com/26759/eng/setuprst.exe', + 'SetupRST_15.8.exe': 'https://downloadmirror.intel.com/27442/eng/SetupRST.exe', + 'SetupRST_15.9.exe': 'https://downloadmirror.intel.com/27400/eng/SetupRST.exe', + 'SetupRST_16.0.exe': 'https://downloadmirror.intel.com/27681/eng/SetupRST.exe', + 'SetupRST_16.5.exe': 'https://downloadmirror.intel.com/27984/eng/SetupRST.exe', + } if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") -# vim: sts=4 sw=4 ts=4 tw=0 nowrap +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/settings/tools.py b/.bin/Scripts/settings/tools.py index b470603c..0ee74dec 100644 --- a/.bin/Scripts/settings/tools.py +++ b/.bin/Scripts/settings/tools.py @@ -1,56 +1,58 @@ # Wizard Kit: Settings - Tools TOOLS = { - # NOTE: BinDir will be prepended to these paths at runtime - 'AIDA64': { - '32': r'AIDA64\aida64.exe'}, - 'AutoRuns': { - '32': r'Autoruns\autoruns.exe', - '64': r'Autoruns\autoruns64.exe'}, - 'BleachBit': { - '32': r'BleachBit\bleachbit_console.exe'}, - 'Caffeine': { - '32': r'Caffeine\caffeine.exe'}, - 'Du': { - '32': r'Du\du.exe', - '64': r'Du\du64.exe'}, - 'ERUNT': { - '32': r'ERUNT\ERUNT.EXE'}, - 'Everything': { - '32': r'Everything\Everything.exe', - '64': r'Everything\Everything64.exe'}, - 'FastCopy': { - '32': r'FastCopy\FastCopy.exe', - '64': r'FastCopy\FastCopy64.exe'}, - 'HitmanPro': { - '32': r'HitmanPro\HitmanPro.exe', - '64': r'HitmanPro\HitmanPro64.exe'}, - 'HWiNFO': { - '32': r'HWiNFO\HWiNFO.exe', - '64': r'HWiNFO\HWiNFO64.exe'}, - 'KVRT': { - '32': r'KVRT\KVRT.exe'}, - 'NirCmd': { - '32': r'NirCmd\nircmdc.exe', - '64': r'NirCmd\nircmdc64.exe'}, - 'NotepadPlusPlus': { - '32': r'NotepadPlusPlus\notepadplusplus.exe'}, - 'ProduKey': { - '32': r'ProduKey\ProduKey.exe', - '64': r'ProduKey\ProduKey64.exe'}, - 'RKill': { - '32': r'RKill\RKill.exe'}, - 'SevenZip': { - '32': r'7-Zip\7za.exe', - '64': r'7-Zip\7za64.exe'}, - 'TDSSKiller': { - '32': r'TDSSKiller\TDSSKiller.exe'}, - 'wimlib-imagex': { - '32': r'wimlib\x32\wimlib-imagex.exe', - '64': r'wimlib\x64\wimlib-imagex.exe'}, - 'XMPlay': { - '32': r'XMPlay\xmplay.exe'}, - } + # NOTE: BinDir will be prepended to these paths at runtime + 'AIDA64': { + '32': r'AIDA64\aida64.exe'}, + 'AutoRuns': { + '32': r'Autoruns\autoruns.exe', + '64': r'Autoruns\autoruns64.exe'}, + 'BleachBit': { + '32': r'BleachBit\bleachbit_console.exe'}, + 'Caffeine': { + '32': r'Caffeine\caffeine.exe'}, + 'Du': { + '32': r'Du\du.exe', + '64': r'Du\du64.exe'}, + 'ERUNT': { + '32': r'ERUNT\ERUNT.EXE'}, + 'Everything': { + '32': r'Everything\Everything.exe', + '64': r'Everything\Everything64.exe'}, + 'FastCopy': { + '32': r'FastCopy\FastCopy.exe', + '64': r'FastCopy\FastCopy64.exe'}, + 'HitmanPro': { + '32': r'HitmanPro\HitmanPro.exe', + '64': r'HitmanPro\HitmanPro64.exe'}, + 'HWiNFO': { + '32': r'HWiNFO\HWiNFO.exe', + '64': r'HWiNFO\HWiNFO64.exe'}, + 'KVRT': { + '32': r'KVRT\KVRT.exe'}, + 'NirCmd': { + '32': r'NirCmd\nircmdc.exe', + '64': r'NirCmd\nircmdc64.exe'}, + 'NotepadPlusPlus': { + '32': r'NotepadPlusPlus\notepadplusplus.exe'}, + 'ProduKey': { + '32': r'ProduKey\ProduKey.exe', + '64': r'ProduKey\ProduKey64.exe'}, + 'RKill': { + '32': r'RKill\RKill.exe'}, + 'SevenZip': { + '32': r'7-Zip\7za.exe', + '64': r'7-Zip\7za64.exe'}, + 'TDSSKiller': { + '32': r'TDSSKiller\TDSSKiller.exe'}, + 'wimlib-imagex': { + '32': r'wimlib\x32\wimlib-imagex.exe', + '64': r'wimlib\x64\wimlib-imagex.exe'}, + 'XMPlay': { + '32': r'XMPlay\xmplay.exe'}, + } if __name__ == '__main__': - print("This file is not meant to be called directly.") + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From f3496ed7951feefa49597562fafa82f522c86760 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 23:28:33 -0700 Subject: [PATCH 196/265] Update 1201 sections to match upstream code --- .bin/Scripts/functions/cleanup.py | 264 +++++++++++++++--------------- .bin/Scripts/functions/setup.py | 84 +++++----- .bin/Scripts/functions/update.py | 214 ++++++++++++------------ 3 files changed, 281 insertions(+), 281 deletions(-) diff --git a/.bin/Scripts/functions/cleanup.py b/.bin/Scripts/functions/cleanup.py index a364ec9c..7caf19dc 100644 --- a/.bin/Scripts/functions/cleanup.py +++ b/.bin/Scripts/functions/cleanup.py @@ -4,46 +4,46 @@ from functions.setup import * # STATIC VARIABLES D7_HKCR_CLEANUP = { - r'batfile\shell\!!RunWithParms': {'Recurse': True}, - r'batfile\shell\{0001B4FD-9EA3-4D90-A79E-FD14BA3AB01D}': {'Recurse': True}, - r'cmdfile\shell\!!RunWithParms': {'Recurse': True}, - r'cmdfile\shell\{0001B4FD-9EA3-4D90-A79E-FD14BA3AB01D}': {'Recurse': True}, - r'exefile\shell\!!RunWithParms': {'Recurse': True}, - r'exefile\shell\ResourceHacker': {'Recurse': True}, - r'regfile\shell\!!RunWithParms': {'Recurse': True}, - r'regfile\shell\{0001B4FD-9EA3-4D90-A79E-FD14BA3AB01D}': {'Recurse': True}, - } + r'batfile\shell\!!RunWithParms': {'Recurse': True}, + r'batfile\shell\{0001B4FD-9EA3-4D90-A79E-FD14BA3AB01D}': {'Recurse': True}, + r'cmdfile\shell\!!RunWithParms': {'Recurse': True}, + r'cmdfile\shell\{0001B4FD-9EA3-4D90-A79E-FD14BA3AB01D}': {'Recurse': True}, + r'exefile\shell\!!RunWithParms': {'Recurse': True}, + r'exefile\shell\ResourceHacker': {'Recurse': True}, + r'regfile\shell\!!RunWithParms': {'Recurse': True}, + r'regfile\shell\{0001B4FD-9EA3-4D90-A79E-FD14BA3AB01D}': {'Recurse': True}, + } D7_HKCU_CLEANUP = { - r'Software\Malwarebytes': {'Recurse': False}, - } + r'Software\Malwarebytes': {'Recurse': False}, + } D7_HKLM_CLEANUP = { - r'Software\Emsisoft': {'Recurse': False}, - } + r'Software\Emsisoft': {'Recurse': False}, + } HKU = winreg.HKEY_USERS HKCR = winreg.HKEY_CLASSES_ROOT HKCU = winreg.HKEY_CURRENT_USER HKLM = winreg.HKEY_LOCAL_MACHINE UAC_DEFAULTS_WIN7 = { - r'Software\Microsoft\Windows\CurrentVersion\Policies\System': { - 'DWORD Items': { - 'ConsentPromptBehaviorAdmin': 5, - 'EnableLUA': 1, - 'PromptOnSecureDesktop': 1, - }, - }, - } + r'Software\Microsoft\Windows\CurrentVersion\Policies\System': { + 'DWORD Items': { + 'ConsentPromptBehaviorAdmin': 5, + 'EnableLUA': 1, + 'PromptOnSecureDesktop': 1, + }, + }, + } UAC_DEFAULTS_WIN10 = { - r'Software\Microsoft\Windows\CurrentVersion\Policies\System': { - 'DWORD Items': { - 'ConsentPromptBehaviorAdmin': 5, - 'ConsentPromptBehaviorUser': 3, - 'EnableInstallerDetection': 1, - 'EnableLUA': 1, - 'EnableVirtualization': 1, - 'PromptOnSecureDesktop': 1, - }, - }, - } + r'Software\Microsoft\Windows\CurrentVersion\Policies\System': { + 'DWORD Items': { + 'ConsentPromptBehaviorAdmin': 5, + 'ConsentPromptBehaviorUser': 3, + 'EnableInstallerDetection': 1, + 'EnableLUA': 1, + 'EnableVirtualization': 1, + 'PromptOnSecureDesktop': 1, + }, + }, + } def cleanup_adwcleaner(): @@ -112,81 +112,81 @@ def cleanup_cbs(dest_folder): def cleanup_d7ii(): - """Sort d7II logs and remove temp items.""" - d7_path = r'{}\d7II'.format(global_vars['ClientDir']) - d7_reports = r'{} Reports'.format(d7_path) - d7_temp = r'{}\Temp'.format(d7_path) + """Sort d7II logs and remove temp items.""" + d7_path = r'{}\d7II'.format(global_vars['ClientDir']) + d7_reports = r'{} Reports'.format(d7_path) + d7_temp = r'{}\Temp'.format(d7_path) - # Logs & Reports - if os.path.exists(d7_reports): - for entry in os.scandir(d7_reports): - r = re.match(r'(\d+)-(\d+)-(\d+)', entry.name) - d7_date = '{}-{:02d}-{:02d}'.format( - r.group(1), int(r.group(2)), int(r.group(3))) - d7_mlogs = r'{}\Malware Logs'.format(entry.path) - log_dest = r'{SYSTEMDRIVE}\{prefix}\Logs\{date}'.format( - prefix=KIT_NAME_SHORT, - date=d7_date, - **global_vars['Env']) - os.makedirs(r'{}\d7II'.format(log_dest), exist_ok=True) - os.makedirs(r'{}\Tools'.format(log_dest), exist_ok=True) + # Logs & Reports + if os.path.exists(d7_reports): + for entry in os.scandir(d7_reports): + r = re.match(r'(\d+)-(\d+)-(\d+)', entry.name) + d7_date = '{}-{:02d}-{:02d}'.format( + r.group(1), int(r.group(2)), int(r.group(3))) + d7_mlogs = r'{}\Malware Logs'.format(entry.path) + log_dest = r'{SYSTEMDRIVE}\{prefix}\Logs\{date}'.format( + prefix=KIT_NAME_SHORT, + date=d7_date, + **global_vars['Env']) + os.makedirs(r'{}\d7II'.format(log_dest), exist_ok=True) + os.makedirs(r'{}\Tools'.format(log_dest), exist_ok=True) - # Malware Logs - if os.path.exists(d7_mlogs): - m_report = 'MalwareScan_Report.txt' - for m_entry in os.scandir(d7_mlogs): - if m_entry.name == m_report: - dest_path = r'{}\d7II\{}'.format(log_dest, m_entry.name) - else: - dest_path = r'{}\Tools\{}'.format(log_dest, m_entry.name) - dest_path = non_clobber_rename(dest_path) - shutil.move(m_entry.path, dest_path) + # Malware Logs + if os.path.exists(d7_mlogs): + m_report = 'MalwareScan_Report.txt' + for m_entry in os.scandir(d7_mlogs): + if m_entry.name == m_report: + dest_path = r'{}\d7II\{}'.format(log_dest, m_entry.name) + else: + dest_path = r'{}\Tools\{}'.format(log_dest, m_entry.name) + dest_path = non_clobber_rename(dest_path) + shutil.move(m_entry.path, dest_path) - # Other items - for o_entry in os.scandir(entry.path): - dest_path = r'{log_dest}\d7II\{name}'.format( - log_dest=log_dest, - name=o_entry.name) - dest_path = non_clobber_rename(dest_path) + # Other items + for o_entry in os.scandir(entry.path): + dest_path = r'{log_dest}\d7II\{name}'.format( + log_dest=log_dest, + name=o_entry.name) + dest_path = non_clobber_rename(dest_path) - # Just remove empty folders - if o_entry.is_dir(): - try: - os.rmdir(o_entry.path) - except OSError: - pass - else: - continue - - # Move item - shutil.move(o_entry.path, dest_path) - - # Remove folder - delete_empty_folders(entry.path) - - # Registry Items - for key, settings in D7_HKCR_CLEANUP.items(): - delete_registry_key(HKCR, key, recurse=settings['Recurse']) - for key, settings in D7_HKCU_CLEANUP.items(): - delete_registry_key(HKCU, key, recurse=settings['Recurse']) - for key, settings in D7_HKLM_CLEANUP.items(): - delete_registry_key(HKLM, key, recurse=settings['Recurse']) - - # Temp items - if os.path.exists(d7_path): - if os.path.exists(d7_temp): - shutil.rmtree(d7_temp) - try: - os.rmdir(d7_path) - except OSError: + # Just remove empty folders + if o_entry.is_dir(): + try: + os.rmdir(o_entry.path) + except OSError: pass - - # Restore default UAC settings - if global_vars['OS']['Version'] == '10': - write_registry_settings(UAC_DEFAULTS_WIN10, all_users=True) - else: - # Haven't checked Win8 settings, only applying minimum set - write_registry_settings(UAC_DEFAULTS_WIN7, all_users=True) + else: + continue + + # Move item + shutil.move(o_entry.path, dest_path) + + # Remove folder + delete_empty_folders(entry.path) + + # Registry Items + for key, settings in D7_HKCR_CLEANUP.items(): + delete_registry_key(HKCR, key, recurse=settings['Recurse']) + for key, settings in D7_HKCU_CLEANUP.items(): + delete_registry_key(HKCU, key, recurse=settings['Recurse']) + for key, settings in D7_HKLM_CLEANUP.items(): + delete_registry_key(HKLM, key, recurse=settings['Recurse']) + + # Temp items + if os.path.exists(d7_path): + if os.path.exists(d7_temp): + shutil.rmtree(d7_temp) + try: + os.rmdir(d7_path) + except OSError: + pass + + # Restore default UAC settings + if global_vars['OS']['Version'] == '10': + write_registry_settings(UAC_DEFAULTS_WIN10, all_users=True) + else: + # Haven't checked Win8 settings, only applying minimum set + write_registry_settings(UAC_DEFAULTS_WIN7, all_users=True) def cleanup_desktop(): """Move known backup files and reports into the ClientDir.""" @@ -206,44 +206,44 @@ def cleanup_desktop(): def cleanup_emsisoft(): - """Remove EmsisoftCmd files from drive root.""" - source_path = r'{}\EmsisoftCmd'.format(global_vars['Env']['SYSTEMDRIVE']) - source_quarantine = r'{}\Quarantine'.format(source_path) + """Remove EmsisoftCmd files from drive root.""" + source_path = r'{}\EmsisoftCmd'.format(global_vars['Env']['SYSTEMDRIVE']) + source_quarantine = r'{}\Quarantine'.format(source_path) - # Quarantine - if os.path.exists(source_quarantine): - os.makedirs(global_vars['QuarantineDir'], exist_ok=True) - dest_name = r'{QuarantineDir}\Emsisoft_{Date-Time}'.format( - **global_vars) - dest_name = non_clobber_rename(dest_name) - shutil.move(source_quarantine, dest_name) + # Quarantine + if os.path.exists(source_quarantine): + os.makedirs(global_vars['QuarantineDir'], exist_ok=True) + dest_name = r'{QuarantineDir}\Emsisoft_{Date-Time}'.format( + **global_vars) + dest_name = non_clobber_rename(dest_name) + shutil.move(source_quarantine, dest_name) - # Remove program - if os.path.exists(source_path): - shutil.rmtree(source_path) + # Remove program + if os.path.exists(source_path): + shutil.rmtree(source_path) def cleanup_regbackups(): - """Move d7ii regbackups into backup folder.""" - source_path = r'{}\Support\RegBackups'.format( - global_vars['Env']['SYSTEMDRIVE']) + """Move d7ii regbackups into backup folder.""" + source_path = r'{}\Support\RegBackups'.format( + global_vars['Env']['SYSTEMDRIVE']) - # Bail early - if not os.path.exists(source_path): - return + # Bail early + if not os.path.exists(source_path): + return - # Make dest folder - dest_dir = r'{BackupDir}\Registry\{Date}'.format(**global_vars) - os.makedirs(dest_dir, exist_ok=True) + # Make dest folder + dest_dir = r'{BackupDir}\Registry\{Date}'.format(**global_vars) + os.makedirs(dest_dir, exist_ok=True) - # Move to backup folder - for entry in os.scandir(source_path): - dest_path = r'{dest}\{name}'.format(dest=dest_dir, name=entry.name) - dest_path = non_clobber_rename(dest_path) - shutil.move(entry.path, dest_path) + # Move to backup folder + for entry in os.scandir(source_path): + dest_path = r'{dest}\{name}'.format(dest=dest_dir, name=entry.name) + dest_path = non_clobber_rename(dest_path) + shutil.move(entry.path, dest_path) - # Delete source folders if empty - delete_empty_folders(r'{}\Support'.format( - global_vars['Env']['SYSTEMDRIVE'])) + # Delete source folders if empty + delete_empty_folders(r'{}\Support'.format( + global_vars['Env']['SYSTEMDRIVE'])) def delete_empty_folders(folder_path): """Delete all empty folders in path (depth first).""" diff --git a/.bin/Scripts/functions/setup.py b/.bin/Scripts/functions/setup.py index d7053df0..8cc3fb60 100644 --- a/.bin/Scripts/functions/setup.py +++ b/.bin/Scripts/functions/setup.py @@ -219,25 +219,25 @@ def disable_windows_telemetry(): def enable_regback(): - """Enable RegBack.""" - write_registry_settings(SETTINGS_REGBACK, all_users=True) + """Enable RegBack.""" + write_registry_settings(SETTINGS_REGBACK, all_users=True) def enable_system_restore(): - """Enable System Restore and set disk usage to 5%""" - cmd = [ - 'PowerShell', - '-Command', 'Enable-ComputerRestore', - '-Drive', '{}\\'.format(global_vars['Env']['SYSTEMDRIVE'])] - run_program(cmd) + """Enable System Restore and set disk usage to 5%""" + cmd = [ + 'PowerShell', + '-Command', 'Enable-ComputerRestore', + '-Drive', '{}\\'.format(global_vars['Env']['SYSTEMDRIVE'])] + run_program(cmd) - # Set disk usage - cmd = [ - r'{}\System32\vssadmin.exe'.format(global_vars['Env']['SYSTEMROOT']), - 'resize', 'shadowstorage', - '/on={}'.format(global_vars['Env']['SYSTEMDRIVE']), - '/for={}'.format(global_vars['Env']['SYSTEMDRIVE']), - '/maxsize=5%'] - run_program(cmd) + # Set disk usage + cmd = [ + r'{}\System32\vssadmin.exe'.format(global_vars['Env']['SYSTEMROOT']), + 'resize', 'shadowstorage', + '/on={}'.format(global_vars['Env']['SYSTEMDRIVE']), + '/for={}'.format(global_vars['Env']['SYSTEMDRIVE']), + '/maxsize=5%'] + run_program(cmd) def update_clock(): """Set Timezone and sync clock.""" @@ -305,35 +305,35 @@ def install_classicstart_skin(): def install_eset_nod32_av(scan_pups=True): - """Install ESET NOD32 AV with custom config.""" - extract_item('ESETConfigs', silent=True) - config_file = r'{BinDir}\ESETConfigs\{config_file}.xml'.format( - config_file='eset-config' if scan_pups else 'eset-config-no-pup', - **global_vars) + """Install ESET NOD32 AV with custom config.""" + extract_item('ESETConfigs', silent=True) + config_file = r'{BinDir}\ESETConfigs\{config_file}.xml'.format( + config_file='eset-config' if scan_pups else 'eset-config-no-pup', + **global_vars) - # Apply user configuration - write_registry_settings(SETTINGS_ESET, all_users=False) + # Apply user configuration + write_registry_settings(SETTINGS_ESET, all_users=False) - # Download - result = try_and_print(message='Downloading Setup...', cs='Done', - other_results=OTHER_RESULTS, function=download_generic, - out_dir=global_vars['ClientDir'], - out_name='eav_nt64.exe', - source_url=SOURCE_URLS['ESET NOD32 AV']) - installer = r'{ClientDir}\eav_nt64.exe'.format(**global_vars) - if not result['CS']: - raise GenericError('Failed to download ESET NOD32 AV') + # Download + result = try_and_print(message='Downloading Setup...', cs='Done', + other_results=OTHER_RESULTS, function=download_generic, + out_dir=global_vars['ClientDir'], + out_name='eav_nt64.exe', + source_url=SOURCE_URLS['ESET NOD32 AV']) + installer = r'{ClientDir}\eav_nt64.exe'.format(**global_vars) + if not result['CS']: + raise GenericError('Failed to download ESET NOD32 AV') - # Install - cmd = [installer, - '--silent', '--accepteula', '--msi-property', - 'PRODUCTTYPE=eav', 'PRODUCT_LANG=1033', 'PRODUCT_LANG_CODE=en-US', - 'ADMINCFG="{}"'.format(config_file)] - try_and_print(message='Installing ESET NOD32 AV...', - other_results=OTHER_RESULTS, function=run_program, cmd=cmd) - - # Delete installer - remove_item(installer) + # Install + cmd = [installer, + '--silent', '--accepteula', '--msi-property', + 'PRODUCTTYPE=eav', 'PRODUCT_LANG=1033', 'PRODUCT_LANG_CODE=en-US', + 'ADMINCFG="{}"'.format(config_file)] + try_and_print(message='Installing ESET NOD32 AV...', + other_results=OTHER_RESULTS, function=run_program, cmd=cmd) + + # Delete installer + remove_item(installer) def install_firefox_extensions(): """Install Firefox extensions for all users.""" diff --git a/.bin/Scripts/functions/update.py b/.bin/Scripts/functions/update.py index 7c349c32..ea42af0b 100644 --- a/.bin/Scripts/functions/update.py +++ b/.bin/Scripts/functions/update.py @@ -282,44 +282,44 @@ def update_fastcopy(): def update_linux_reader(): - # Stop running processes - for exe in ['LinuxReader.exe', 'LinuxReader64.exe']: - kill_process(exe) + # Stop running processes + for exe in ['LinuxReader.exe', 'LinuxReader64.exe']: + kill_process(exe) - # Remove existing folders - remove_from_kit('LinuxReader') + # Remove existing folders + remove_from_kit('LinuxReader') - # Prep - install_dir = r'{}\LinuxReaderTemp'.format(global_vars['TmpDir']) - dest = r'{}\LinuxReader'.format(global_vars['CBinDir']) - uninstaller = None + # Prep + install_dir = r'{}\LinuxReaderTemp'.format(global_vars['TmpDir']) + dest = r'{}\LinuxReader'.format(global_vars['CBinDir']) + uninstaller = None - # Download - download_to_temp('LinuxReader.exe', SOURCE_URLS['Linux Reader']) + # Download + download_to_temp('LinuxReader.exe', SOURCE_URLS['Linux Reader']) - # Install to temp - cmd = [ - r'{}\LinuxReader.exe'.format(global_vars['TmpDir']), - '/S', - '/D={}'.format(install_dir)] + # Install to temp + cmd = [ + r'{}\LinuxReader.exe'.format(global_vars['TmpDir']), + '/S', + '/D={}'.format(install_dir)] + run_program(cmd) + + # Copy files + shutil.copytree(install_dir, dest) + for item in os.scandir(dest): + r = re.search(r'^uninstall.*(dat|exe)$', item.name, re.IGNORECASE) + if r: + if 'exe' in item.name: + uninstaller = r'{}\{}'.format(install_dir, item.name) + remove_item(item.path) + + # Uninstall from temp + if uninstaller: + cmd = [uninstaller, '/S'] run_program(cmd) - # Copy files - shutil.copytree(install_dir, dest) - for item in os.scandir(dest): - r = re.search(r'^uninstall.*(dat|exe)$', item.name, re.IGNORECASE) - if r: - if 'exe' in item.name: - uninstaller = r'{}\{}'.format(install_dir, item.name) - remove_item(item.path) - - # Uninstall from temp - if uninstaller: - cmd = [uninstaller, '/S'] - run_program(cmd) - - # Cleanup - remove_from_temp('LinuxReader.exe') + # Cleanup + remove_from_temp('LinuxReader.exe') def update_wimlib(): # Stop running processes @@ -473,44 +473,44 @@ def update_erunt(): def update_furmark(): - # Stop running processes - for exe in ['cpuburner.exe', 'FurMark.exe', 'gpushark.exe', 'gpuz.exe']: - kill_process(exe) + # Stop running processes + for exe in ['cpuburner.exe', 'FurMark.exe', 'gpushark.exe', 'gpuz.exe']: + kill_process(exe) - # Remove existing folders - remove_from_kit('FurMark') + # Remove existing folders + remove_from_kit('FurMark') - # Prep - install_dir = r'{}\FurMarkTemp'.format(global_vars['TmpDir']) - dest = r'{}\FurMark'.format(global_vars['CBinDir']) - uninstaller = None + # Prep + install_dir = r'{}\FurMarkTemp'.format(global_vars['TmpDir']) + dest = r'{}\FurMark'.format(global_vars['CBinDir']) + uninstaller = None - # Download - download_to_temp('furmark_setup.exe', SOURCE_URLS['FurMark']) + # Download + download_to_temp('furmark_setup.exe', SOURCE_URLS['FurMark']) - # Install to temp - cmd = [ - r'{}\furmark_setup.exe'.format(global_vars['TmpDir']), - '/DIR={}'.format(install_dir), - '/SILENT'] + # Install to temp + cmd = [ + r'{}\furmark_setup.exe'.format(global_vars['TmpDir']), + '/DIR={}'.format(install_dir), + '/SILENT'] + run_program(cmd) + + # Copy files + shutil.copytree(install_dir, dest) + for item in os.scandir(dest): + r = re.search(r'^unins\d+\.(dat|exe)$', item.name, re.IGNORECASE) + if r: + if 'exe' in item.name: + uninstaller = r'{}\{}'.format(install_dir, item.name) + remove_item(item.path) + + # Uninstall from temp + if uninstaller: + cmd = [uninstaller, '/SILENT'] run_program(cmd) - # Copy files - shutil.copytree(install_dir, dest) - for item in os.scandir(dest): - r = re.search(r'^unins\d+\.(dat|exe)$', item.name, re.IGNORECASE) - if r: - if 'exe' in item.name: - uninstaller = r'{}\{}'.format(install_dir, item.name) - remove_item(item.path) - - # Uninstall from temp - if uninstaller: - cmd = [uninstaller, '/SILENT'] - run_program(cmd) - - # Cleanup - remove_from_temp('furmark_setup.exe') + # Cleanup + remove_from_temp('furmark_setup.exe') def update_hitmanpro(): # Stop running processes @@ -713,11 +713,11 @@ def update_adobe_reader_dc(): def update_eset_config(): - """Copy config files to .cbin before compress_item""" - dest = r'{}\ESETConfigs'.format(global_vars['CBinDir']) - include_path = r'{}\_include\ESETConfigs'.format(global_vars['CBinDir']) - if os.path.exists(include_path): - shutil.copytree(include_path, dest) + """Copy config files to .cbin before compress_item""" + dest = r'{}\ESETConfigs'.format(global_vars['CBinDir']) + include_path = r'{}\_include\ESETConfigs'.format(global_vars['CBinDir']) + if os.path.exists(include_path): + shutil.copytree(include_path, dest) def update_macs_fan_control(): # Prep @@ -935,23 +935,23 @@ def update_putty(): def update_shutup10(): - # Stop running processes - kill_process('OOSU10.exe') + # Stop running processes + kill_process('OOSU10.exe') - # Remove existing folders - remove_from_kit('ShutUp10') + # Remove existing folders + remove_from_kit('ShutUp10') - # Copy settings - dest = r'{}\ShutUp10'.format(global_vars['CBinDir']) - include_path = r'{}\_include\ShutUp10'.format(global_vars['CBinDir']) - if os.path.exists(include_path): - shutil.copytree(include_path, dest) + # Copy settings + dest = r'{}\ShutUp10'.format(global_vars['CBinDir']) + include_path = r'{}\_include\ShutUp10'.format(global_vars['CBinDir']) + if os.path.exists(include_path): + shutil.copytree(include_path, dest) - # Download - download_generic( - r'{}\ShutUp10'.format(global_vars['CBinDir']), - 'OOSU10.exe', - SOURCE_URLS['ShutUp10']) + # Download + download_generic( + r'{}\ShutUp10'.format(global_vars['CBinDir']), + 'OOSU10.exe', + SOURCE_URLS['ShutUp10']) def update_wiztree(): # Stop running processes @@ -1044,17 +1044,17 @@ def update_adwcleaner(): def update_eset_online_scanner(): - # Stop running processes - kill_process('ESET.exe') + # Stop running processes + kill_process('ESET.exe') - # Remove existing folders - remove_from_kit('ESET') + # Remove existing folders + remove_from_kit('ESET') - # Download - download_generic( - r'{}\ESET'.format(global_vars['CBinDir']), - 'ESET.exe', - SOURCE_URLS['ESET Online Scanner']) + # Download + download_generic( + r'{}\ESET'.format(global_vars['CBinDir']), + 'ESET.exe', + SOURCE_URLS['ESET Online Scanner']) def update_kvrt(): # Stop running processes @@ -1100,24 +1100,24 @@ def update_tdsskiller(): def update_winaiorepair(): - # Stop running processes - kill_process('Repair_Windows.exe') + # Stop running processes + kill_process('Repair_Windows.exe') - # Download - download_to_temp('winaio.zip', SOURCE_URLS['WinAIO Repair']) + # Download + download_to_temp('winaio.zip', SOURCE_URLS['WinAIO Repair']) - # Extract - extract_temp_to_cbin('winaio.zip', 'WinAIORepair') - dest = r'{}\WinAIORepair'.format(global_vars['CBinDir']) - for item in os.scandir(r'{}\Tweaking.com - Windows Repair'.format(dest)): - dest_item = '{}\{}'.format(dest, item.name) - if not os.path.exists(dest_item): - shutil.move(item.path, dest_item) - shutil.rmtree( - r'{}\WinAIORepair\Tweaking.com - Windows Repair'.format(global_vars['CBinDir'])) + # Extract + extract_temp_to_cbin('winaio.zip', 'WinAIORepair') + dest = r'{}\WinAIORepair'.format(global_vars['CBinDir']) + for item in os.scandir(r'{}\Tweaking.com - Windows Repair'.format(dest)): + dest_item = '{}\{}'.format(dest, item.name) + if not os.path.exists(dest_item): + shutil.move(item.path, dest_item) + shutil.rmtree( + r'{}\WinAIORepair\Tweaking.com - Windows Repair'.format(global_vars['CBinDir'])) - # Cleanup - remove_from_temp('winaio.zip') + # Cleanup + remove_from_temp('winaio.zip') # Uninstallers From 91649f5ee7277b884d61567475de47ece4c6215a Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 27 Dec 2018 23:43:35 -0700 Subject: [PATCH 197/265] Removed args from run_program * It's been deprecated for ages * Fixes issue #79 --- .bin/Scripts/functions/common.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index 368ce687..f0315aff 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -490,12 +490,8 @@ def print_log(message='', end='\n', timestamp=True): end = end)) -def run_program(cmd, args=[], check=True, pipe=True, shell=False, **kwargs): +def run_program(cmd, check=True, pipe=True, shell=False, **kwargs): """Run program and return a subprocess.CompletedProcess object.""" - if args: - # Deprecated so let's raise an exception to find & fix all occurances - print_error('ERROR: Using args is no longer supported.') - raise Exception cmd = [c for c in cmd if c] if shell: cmd = ' '.join(cmd) From 575fa174257b9d19cad8d03b1b4e62ffd674cb0c Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 28 Dec 2018 15:44:14 -0700 Subject: [PATCH 198/265] Only use Unicode checkmark if in X --- .bin/Scripts/functions/ddrescue.py | 7 +++++-- .bin/Scripts/functions/hw_diags.py | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.bin/Scripts/functions/ddrescue.py b/.bin/Scripts/functions/ddrescue.py index a2b27e5e..f6c30e0a 100644 --- a/.bin/Scripts/functions/ddrescue.py +++ b/.bin/Scripts/functions/ddrescue.py @@ -781,6 +781,9 @@ def menu_ddrescue(source_path, dest_path, run_mode): def menu_main(state): """Main menu is used to set ddrescue settings.""" + checkmark = '*' + if 'DISPLAY' in global_vars['Env']: + checkmark = '✓' title = '{GREEN}ddrescue TUI: Main Menu{CLEAR}\n\n'.format(**COLORS) title += '{BLUE}Current pass: {CLEAR}'.format(**COLORS) @@ -804,8 +807,8 @@ def menu_main(state): while True: # Update entries for opt in main_options: - opt['Name'] = '{} {}'.format( - '[✓]' if opt['Enabled'] else '[ ]', + opt['Name'] = '[{}] {}'.format( + checkmark if opt['Enabled'] else ' ', opt['Base Name']) selection = menu_select( diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 155031ec..fae78b21 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -751,6 +751,9 @@ def get_read_rate(s): def menu_diags(state, args): """Main menu to select and run HW tests.""" args = [a.lower() for a in args] + checkmark = '*' + if 'DISPLAY' in global_vars['Env']: + checkmark = '✓' title = '{}\nMain Menu'.format(TOP_PANE_TEXT) # NOTE: Changing the order of main_options will break everything main_options = [ @@ -819,8 +822,8 @@ def menu_diags(state, args): # Update checkboxes for opt in main_options: _nvme_smart = opt['Base Name'] == 'NVMe / SMART' - opt['Name'] = '{} {} {}'.format( - '[✓]' if opt['Enabled'] else '[ ]', + opt['Name'] = '[{}] {} {}'.format( + checkmark if opt['Enabled'] else ' ', opt['Base Name'], QUICK_LABEL if state.quick_mode and _nvme_smart else '') From 8f9bae9a6f5170697300f824cc25c154e1e390a4 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 28 Dec 2018 16:51:15 -0700 Subject: [PATCH 199/265] Added option to build Linux with minimal packages * All non-minimal packages/configs have been separated from the base setup * `"Build Linux" -b` will only build the full version --- .../include/airootfs/etc/skel/.zlogin | 28 +--------- .../airootfs/etc/oblogout.conf | 0 .../airootfs/etc/skel/.Xresources | 0 .../etc/skel/.config/Thunar/accels.scm | 0 .../airootfs/etc/skel/.config/Thunar/uca.xml | 0 .../airootfs/etc/skel/.config/dunst/dunstrc | 0 .../etc/skel/.config/gtk-3.0/settings.ini | 0 .../airootfs/etc/skel/.config/i3/config | 0 .../airootfs/etc/skel/.config/i3status/config | 0 .../airootfs/etc/skel/.config/mimeapps.list | 0 .../etc/skel/.config/openbox/autostart | 0 .../etc/skel/.config/openbox/environment | 0 .../etc/skel/.config/openbox/menu.xml | 0 .../airootfs/etc/skel/.config/openbox/rc.xml | 0 .../airootfs/etc/skel/.config/rofi/config | 0 .../airootfs/etc/skel/.config/tint2/tint2rc | 0 .../etc/skel/.config/volumeicon/volumeicon | 0 .../airootfs/etc/skel/.conky_start | 0 .../airootfs/etc/skel/.conkyrc | 0 .../airootfs/etc/skel/.gtkrc-2.0 | 0 .../airootfs/etc/skel/.update_conky | 0 .../airootfs/etc/skel/.update_x | 0 .../airootfs/etc/skel/.wallpaper | 0 .../airootfs/etc/skel/.xinitrc | 0 .../include_x/airootfs/etc/skel/.zlogin | 32 +++++++++++ .../applications/Hardware Diagnostics.desktop | 0 .../applications/Hardware Information.desktop | 0 .../share/applications/NetworkTest.desktop | 0 .linux_items/packages/live_add | 56 +------------------ .linux_items/packages/live_add_x | 55 ++++++++++++++++++ Build Linux | 38 +++++++++---- 31 files changed, 118 insertions(+), 91 deletions(-) rename .linux_items/{include => include_x}/airootfs/etc/oblogout.conf (100%) rename .linux_items/{include => include_x}/airootfs/etc/skel/.Xresources (100%) rename .linux_items/{include => include_x}/airootfs/etc/skel/.config/Thunar/accels.scm (100%) rename .linux_items/{include => include_x}/airootfs/etc/skel/.config/Thunar/uca.xml (100%) rename .linux_items/{include => include_x}/airootfs/etc/skel/.config/dunst/dunstrc (100%) rename .linux_items/{include => include_x}/airootfs/etc/skel/.config/gtk-3.0/settings.ini (100%) rename .linux_items/{include => include_x}/airootfs/etc/skel/.config/i3/config (100%) rename .linux_items/{include => include_x}/airootfs/etc/skel/.config/i3status/config (100%) rename .linux_items/{include => include_x}/airootfs/etc/skel/.config/mimeapps.list (100%) rename .linux_items/{include => include_x}/airootfs/etc/skel/.config/openbox/autostart (100%) rename .linux_items/{include => include_x}/airootfs/etc/skel/.config/openbox/environment (100%) rename .linux_items/{include => include_x}/airootfs/etc/skel/.config/openbox/menu.xml (100%) rename .linux_items/{include => include_x}/airootfs/etc/skel/.config/openbox/rc.xml (100%) rename .linux_items/{include => include_x}/airootfs/etc/skel/.config/rofi/config (100%) rename .linux_items/{include => include_x}/airootfs/etc/skel/.config/tint2/tint2rc (100%) rename .linux_items/{include => include_x}/airootfs/etc/skel/.config/volumeicon/volumeicon (100%) rename .linux_items/{include => include_x}/airootfs/etc/skel/.conky_start (100%) rename .linux_items/{include => include_x}/airootfs/etc/skel/.conkyrc (100%) rename .linux_items/{include => include_x}/airootfs/etc/skel/.gtkrc-2.0 (100%) rename .linux_items/{include => include_x}/airootfs/etc/skel/.update_conky (100%) rename .linux_items/{include => include_x}/airootfs/etc/skel/.update_x (100%) rename .linux_items/{include => include_x}/airootfs/etc/skel/.wallpaper (100%) rename .linux_items/{include => include_x}/airootfs/etc/skel/.xinitrc (100%) create mode 100644 .linux_items/include_x/airootfs/etc/skel/.zlogin rename .linux_items/{include => include_x}/airootfs/usr/share/applications/Hardware Diagnostics.desktop (100%) rename .linux_items/{include => include_x}/airootfs/usr/share/applications/Hardware Information.desktop (100%) rename .linux_items/{include => include_x}/airootfs/usr/share/applications/NetworkTest.desktop (100%) create mode 100644 .linux_items/packages/live_add_x diff --git a/.linux_items/include/airootfs/etc/skel/.zlogin b/.linux_items/include/airootfs/etc/skel/.zlogin index 04b1316e..68868d8e 100644 --- a/.linux_items/include/airootfs/etc/skel/.zlogin +++ b/.linux_items/include/airootfs/etc/skel/.zlogin @@ -3,30 +3,6 @@ if [ "$(fgconsole 2>/dev/null)" -eq "1" ]; then # Connect to network and update hostname $HOME/.update_network - # Update settings if using i3 - if fgrep -q "i3" /proc/cmdline; then - sed -i -r 's/#(own_window_type override)/\1/' ~/.conkyrc - sed -i -r 's/openbox-session/i3/' ~/.xinitrc - fi - - # Update Conky - $HOME/.update_conky - - # Start X or HW-diags - if ! fgrep -q "nox" /proc/cmdline; then - # Kill Xorg after 30 seconds if it doesn't fully initialize - (sleep 30s; if ! [[ -f "/tmp/x_ok" ]]; then pkill '(Xorg|startx)'; fi) & - - # Try starting X - startx >/dev/null - - # Run Hw-Diags CLI if necessary - if ! [[ -f "/tmp/x_ok" ]]; then - echo "There was an issue starting Xorg, starting CLI interface..." - sleep 2s - hw-diags --cli - fi - else - hw-diags --cli - fi + # Start HW-diags + hw-diags --cli fi diff --git a/.linux_items/include/airootfs/etc/oblogout.conf b/.linux_items/include_x/airootfs/etc/oblogout.conf similarity index 100% rename from .linux_items/include/airootfs/etc/oblogout.conf rename to .linux_items/include_x/airootfs/etc/oblogout.conf diff --git a/.linux_items/include/airootfs/etc/skel/.Xresources b/.linux_items/include_x/airootfs/etc/skel/.Xresources similarity index 100% rename from .linux_items/include/airootfs/etc/skel/.Xresources rename to .linux_items/include_x/airootfs/etc/skel/.Xresources diff --git a/.linux_items/include/airootfs/etc/skel/.config/Thunar/accels.scm b/.linux_items/include_x/airootfs/etc/skel/.config/Thunar/accels.scm similarity index 100% rename from .linux_items/include/airootfs/etc/skel/.config/Thunar/accels.scm rename to .linux_items/include_x/airootfs/etc/skel/.config/Thunar/accels.scm diff --git a/.linux_items/include/airootfs/etc/skel/.config/Thunar/uca.xml b/.linux_items/include_x/airootfs/etc/skel/.config/Thunar/uca.xml similarity index 100% rename from .linux_items/include/airootfs/etc/skel/.config/Thunar/uca.xml rename to .linux_items/include_x/airootfs/etc/skel/.config/Thunar/uca.xml diff --git a/.linux_items/include/airootfs/etc/skel/.config/dunst/dunstrc b/.linux_items/include_x/airootfs/etc/skel/.config/dunst/dunstrc similarity index 100% rename from .linux_items/include/airootfs/etc/skel/.config/dunst/dunstrc rename to .linux_items/include_x/airootfs/etc/skel/.config/dunst/dunstrc diff --git a/.linux_items/include/airootfs/etc/skel/.config/gtk-3.0/settings.ini b/.linux_items/include_x/airootfs/etc/skel/.config/gtk-3.0/settings.ini similarity index 100% rename from .linux_items/include/airootfs/etc/skel/.config/gtk-3.0/settings.ini rename to .linux_items/include_x/airootfs/etc/skel/.config/gtk-3.0/settings.ini diff --git a/.linux_items/include/airootfs/etc/skel/.config/i3/config b/.linux_items/include_x/airootfs/etc/skel/.config/i3/config similarity index 100% rename from .linux_items/include/airootfs/etc/skel/.config/i3/config rename to .linux_items/include_x/airootfs/etc/skel/.config/i3/config diff --git a/.linux_items/include/airootfs/etc/skel/.config/i3status/config b/.linux_items/include_x/airootfs/etc/skel/.config/i3status/config similarity index 100% rename from .linux_items/include/airootfs/etc/skel/.config/i3status/config rename to .linux_items/include_x/airootfs/etc/skel/.config/i3status/config diff --git a/.linux_items/include/airootfs/etc/skel/.config/mimeapps.list b/.linux_items/include_x/airootfs/etc/skel/.config/mimeapps.list similarity index 100% rename from .linux_items/include/airootfs/etc/skel/.config/mimeapps.list rename to .linux_items/include_x/airootfs/etc/skel/.config/mimeapps.list diff --git a/.linux_items/include/airootfs/etc/skel/.config/openbox/autostart b/.linux_items/include_x/airootfs/etc/skel/.config/openbox/autostart similarity index 100% rename from .linux_items/include/airootfs/etc/skel/.config/openbox/autostart rename to .linux_items/include_x/airootfs/etc/skel/.config/openbox/autostart diff --git a/.linux_items/include/airootfs/etc/skel/.config/openbox/environment b/.linux_items/include_x/airootfs/etc/skel/.config/openbox/environment similarity index 100% rename from .linux_items/include/airootfs/etc/skel/.config/openbox/environment rename to .linux_items/include_x/airootfs/etc/skel/.config/openbox/environment diff --git a/.linux_items/include/airootfs/etc/skel/.config/openbox/menu.xml b/.linux_items/include_x/airootfs/etc/skel/.config/openbox/menu.xml similarity index 100% rename from .linux_items/include/airootfs/etc/skel/.config/openbox/menu.xml rename to .linux_items/include_x/airootfs/etc/skel/.config/openbox/menu.xml diff --git a/.linux_items/include/airootfs/etc/skel/.config/openbox/rc.xml b/.linux_items/include_x/airootfs/etc/skel/.config/openbox/rc.xml similarity index 100% rename from .linux_items/include/airootfs/etc/skel/.config/openbox/rc.xml rename to .linux_items/include_x/airootfs/etc/skel/.config/openbox/rc.xml diff --git a/.linux_items/include/airootfs/etc/skel/.config/rofi/config b/.linux_items/include_x/airootfs/etc/skel/.config/rofi/config similarity index 100% rename from .linux_items/include/airootfs/etc/skel/.config/rofi/config rename to .linux_items/include_x/airootfs/etc/skel/.config/rofi/config diff --git a/.linux_items/include/airootfs/etc/skel/.config/tint2/tint2rc b/.linux_items/include_x/airootfs/etc/skel/.config/tint2/tint2rc similarity index 100% rename from .linux_items/include/airootfs/etc/skel/.config/tint2/tint2rc rename to .linux_items/include_x/airootfs/etc/skel/.config/tint2/tint2rc diff --git a/.linux_items/include/airootfs/etc/skel/.config/volumeicon/volumeicon b/.linux_items/include_x/airootfs/etc/skel/.config/volumeicon/volumeicon similarity index 100% rename from .linux_items/include/airootfs/etc/skel/.config/volumeicon/volumeicon rename to .linux_items/include_x/airootfs/etc/skel/.config/volumeicon/volumeicon diff --git a/.linux_items/include/airootfs/etc/skel/.conky_start b/.linux_items/include_x/airootfs/etc/skel/.conky_start similarity index 100% rename from .linux_items/include/airootfs/etc/skel/.conky_start rename to .linux_items/include_x/airootfs/etc/skel/.conky_start diff --git a/.linux_items/include/airootfs/etc/skel/.conkyrc b/.linux_items/include_x/airootfs/etc/skel/.conkyrc similarity index 100% rename from .linux_items/include/airootfs/etc/skel/.conkyrc rename to .linux_items/include_x/airootfs/etc/skel/.conkyrc diff --git a/.linux_items/include/airootfs/etc/skel/.gtkrc-2.0 b/.linux_items/include_x/airootfs/etc/skel/.gtkrc-2.0 similarity index 100% rename from .linux_items/include/airootfs/etc/skel/.gtkrc-2.0 rename to .linux_items/include_x/airootfs/etc/skel/.gtkrc-2.0 diff --git a/.linux_items/include/airootfs/etc/skel/.update_conky b/.linux_items/include_x/airootfs/etc/skel/.update_conky similarity index 100% rename from .linux_items/include/airootfs/etc/skel/.update_conky rename to .linux_items/include_x/airootfs/etc/skel/.update_conky diff --git a/.linux_items/include/airootfs/etc/skel/.update_x b/.linux_items/include_x/airootfs/etc/skel/.update_x similarity index 100% rename from .linux_items/include/airootfs/etc/skel/.update_x rename to .linux_items/include_x/airootfs/etc/skel/.update_x diff --git a/.linux_items/include/airootfs/etc/skel/.wallpaper b/.linux_items/include_x/airootfs/etc/skel/.wallpaper similarity index 100% rename from .linux_items/include/airootfs/etc/skel/.wallpaper rename to .linux_items/include_x/airootfs/etc/skel/.wallpaper diff --git a/.linux_items/include/airootfs/etc/skel/.xinitrc b/.linux_items/include_x/airootfs/etc/skel/.xinitrc similarity index 100% rename from .linux_items/include/airootfs/etc/skel/.xinitrc rename to .linux_items/include_x/airootfs/etc/skel/.xinitrc diff --git a/.linux_items/include_x/airootfs/etc/skel/.zlogin b/.linux_items/include_x/airootfs/etc/skel/.zlogin new file mode 100644 index 00000000..04b1316e --- /dev/null +++ b/.linux_items/include_x/airootfs/etc/skel/.zlogin @@ -0,0 +1,32 @@ +setterm -blank 0 -powerdown 0 2>/dev/null +if [ "$(fgconsole 2>/dev/null)" -eq "1" ]; then + # Connect to network and update hostname + $HOME/.update_network + + # Update settings if using i3 + if fgrep -q "i3" /proc/cmdline; then + sed -i -r 's/#(own_window_type override)/\1/' ~/.conkyrc + sed -i -r 's/openbox-session/i3/' ~/.xinitrc + fi + + # Update Conky + $HOME/.update_conky + + # Start X or HW-diags + if ! fgrep -q "nox" /proc/cmdline; then + # Kill Xorg after 30 seconds if it doesn't fully initialize + (sleep 30s; if ! [[ -f "/tmp/x_ok" ]]; then pkill '(Xorg|startx)'; fi) & + + # Try starting X + startx >/dev/null + + # Run Hw-Diags CLI if necessary + if ! [[ -f "/tmp/x_ok" ]]; then + echo "There was an issue starting Xorg, starting CLI interface..." + sleep 2s + hw-diags --cli + fi + else + hw-diags --cli + fi +fi diff --git a/.linux_items/include/airootfs/usr/share/applications/Hardware Diagnostics.desktop b/.linux_items/include_x/airootfs/usr/share/applications/Hardware Diagnostics.desktop similarity index 100% rename from .linux_items/include/airootfs/usr/share/applications/Hardware Diagnostics.desktop rename to .linux_items/include_x/airootfs/usr/share/applications/Hardware Diagnostics.desktop diff --git a/.linux_items/include/airootfs/usr/share/applications/Hardware Information.desktop b/.linux_items/include_x/airootfs/usr/share/applications/Hardware Information.desktop similarity index 100% rename from .linux_items/include/airootfs/usr/share/applications/Hardware Information.desktop rename to .linux_items/include_x/airootfs/usr/share/applications/Hardware Information.desktop diff --git a/.linux_items/include/airootfs/usr/share/applications/NetworkTest.desktop b/.linux_items/include_x/airootfs/usr/share/applications/NetworkTest.desktop similarity index 100% rename from .linux_items/include/airootfs/usr/share/applications/NetworkTest.desktop rename to .linux_items/include_x/airootfs/usr/share/applications/NetworkTest.desktop diff --git a/.linux_items/packages/live_add b/.linux_items/packages/live_add index a6da5f71..85ea5489 100644 --- a/.linux_items/packages/live_add +++ b/.linux_items/packages/live_add @@ -1,86 +1,47 @@ aic94xx-firmware alsa-utils antiword -arandr -arc-gtk-theme bash-pipes bc bluez bluez-utils -cbatticon chntpw cmatrix colordiff -compton -conky cpio curl dmidecode dos2unix -dunst e2fsprogs -evince -feh -ffmpeg -firefox -gnome-keyring -gparted -gpicview-gtk3 -gsmartcontrol -hardinfo hexedit hfsprogs htop -i3-gaps -i3lock-fancy-git -i3status ldns -leafpad lha libewf -libinput linux-firmware lm_sensors lzip mdadm mediainfo -mesa-demos -mkvtoolnix-cli mprime -mpv ncdu -network-manager-applet networkmanager -noto-fonts -noto-fonts-cjk -oblogout -openbox-patched -otf-font-awesome-4 p7zip -papirus-icon-theme progsreiserfs python python-psutil python-requests -qemu-guest-agent reiserfsprogs rfkill rng-tools -rofi -rxvt-unicode +rxvt-unicode-terminfo smartmontools-svn speedtest-cli -spice-vdagent terminus-font testdisk-wip -thunar -tigervnc -tint2 -tk tmux tree -ttf-font-awesome-4 -ttf-inconsolata udevil udisks2 ufw @@ -88,23 +49,8 @@ unarj unrar unzip util-linux -veracrypt vim -virtualbox-guest-modules-arch -virtualbox-guest-utils -volumeicon wd719x-firmware wimlib -xarchiver -xf86-input-libinput -xf86-video-amdgpu -xf86-video-fbdev -xf86-video-nouveau -xf86-video-vesa -xorg-server -xorg-xdpyinfo -xorg-xev -xorg-xinit -xorg-xinput zip zsh diff --git a/.linux_items/packages/live_add_x b/.linux_items/packages/live_add_x new file mode 100644 index 00000000..ab7d23b3 --- /dev/null +++ b/.linux_items/packages/live_add_x @@ -0,0 +1,55 @@ +arandr +arc-gtk-theme +cbatticon +compton +conky +dunst +evince +feh +ffmpeg +firefox +gnome-keyring +gparted +gpicview-gtk3 +gsmartcontrol +hardinfo +i3-gaps +i3lock-fancy-git +i3status +leafpad +libinput +mesa-demos +mkvtoolnix-cli +mpv +network-manager-applet +noto-fonts +noto-fonts-cjk +oblogout +openbox-patched +otf-font-awesome-4 +papirus-icon-theme +qemu-guest-agent +rofi +rxvt-unicode +spice-vdagent +thunar +tigervnc +tint2 +tk +ttf-font-awesome-4 +ttf-inconsolata +veracrypt +virtualbox-guest-modules-arch +virtualbox-guest-utils +volumeicon +xarchiver +xf86-input-libinput +xf86-video-amdgpu +xf86-video-fbdev +xf86-video-nouveau +xf86-video-vesa +xorg-server +xorg-xdpyinfo +xorg-xev +xorg-xinit +xorg-xinput diff --git a/Build Linux b/Build Linux index 87e93e2d..52e060d2 100755 --- a/Build Linux +++ b/Build Linux @@ -119,6 +119,9 @@ function copy_live_env() { # Add items rsync -aI "$ROOT_DIR/.linux_items/include/" "$LIVE_DIR/" + if [[ "${1:-}" != "--minimal" ]]; then + rsync -aI "$ROOT_DIR/.linux_items/include_x/" "$LIVE_DIR/" + fi mkdir -p "$LIVE_DIR/airootfs/usr/local/bin" rsync -aI "$ROOT_DIR/.bin/Scripts/" "$LIVE_DIR/airootfs/usr/local/bin/" cp -a "$BUILD_DIR/main.py" "$LIVE_DIR/airootfs/usr/local/bin/settings/" @@ -195,6 +198,9 @@ function update_live_env() { sed -i "/$p/d" "$LIVE_DIR/packages.x86_64" done < "$ROOT_DIR/.linux_items/packages/live_remove" cat "$ROOT_DIR/.linux_items/packages/live_add" >> "$LIVE_DIR/packages.x86_64" + if [[ "${1:-}" != "--minimal" ]]; then + cat "$ROOT_DIR/.linux_items/packages/live_add_x" >> "$LIVE_DIR/packages.x86_64" + fi echo "[custom]" >> "$LIVE_DIR/pacman.conf" echo "SigLevel = Optional TrustAll" >> "$LIVE_DIR/pacman.conf" echo "Server = file://$REPO_DIR" >> "$LIVE_DIR/pacman.conf" @@ -213,10 +219,12 @@ function update_live_env() { rm -Rf "$SKEL_DIR/.oh-my-zsh/.git" curl -o "$SKEL_DIR/.oh-my-zsh/themes/lean.zsh-theme" https://raw.githubusercontent.com/miekg/lean/master/prompt_lean_setup - # Openbox theme - git clone --depth=1 https://github.com/addy-dclxvi/Openbox-Theme-Collections.git "$TEMP_DIR/ob-themes" - mkdir -p "$LIVE_DIR/airootfs/usr/share/themes" - cp -a "$TEMP_DIR/ob-themes/Triste-Orange" "$LIVE_DIR/airootfs/usr/share/themes/" + if [[ "${1:-}" != "--minimal" ]]; then + # Openbox theme + git clone --depth=1 https://github.com/addy-dclxvi/Openbox-Theme-Collections.git "$TEMP_DIR/ob-themes" + mkdir -p "$LIVE_DIR/airootfs/usr/share/themes" + cp -a "$TEMP_DIR/ob-themes/Triste-Orange" "$LIVE_DIR/airootfs/usr/share/themes/" + fi # Services sed -i -r 's/^(.*pacman-init.*)$/#NOPE#\1/' "$LIVE_DIR/airootfs/root/customize_airootfs.sh" @@ -259,13 +267,15 @@ function update_live_env() { # udevil fix echo "mkdir /media" >> "$LIVE_DIR/airootfs/root/customize_airootfs.sh" - # VNC password - echo "mkdir '/home/$username/.vnc'" >> "$LIVE_DIR/airootfs/root/customize_airootfs.sh" - echo "echo '$TECH_PASSWORD' | vncpasswd -f > '/home/$username/.vnc/passwd'" >> "$LIVE_DIR/airootfs/root/customize_airootfs.sh" + if [[ "${1:-}" != "--minimal" ]]; then + # VNC password + echo "mkdir '/home/$username/.vnc'" >> "$LIVE_DIR/airootfs/root/customize_airootfs.sh" + echo "echo '$TECH_PASSWORD' | vncpasswd -f > '/home/$username/.vnc/passwd'" >> "$LIVE_DIR/airootfs/root/customize_airootfs.sh" - # Wallpaper - mkdir -p "$LIVE_DIR/airootfs/usr/share/wallpaper" - cp "$ROOT_DIR/Images/Linux.png" "$LIVE_DIR/airootfs/usr/share/wallpaper/burned.in" + # Wallpaper + mkdir -p "$LIVE_DIR/airootfs/usr/share/wallpaper" + cp "$ROOT_DIR/Images/Linux.png" "$LIVE_DIR/airootfs/usr/share/wallpaper/burned.in" + fi } function update_repo() { @@ -386,6 +396,13 @@ case ${1:-} in echo Done ;; + -m|--prep-minimal-env) + load_settings --edit + copy_live_env --minimal + update_live_env --minimal + echo Done + ;; + -o|--build-iso) load_settings build_iso @@ -414,6 +431,7 @@ case ${1:-} in echo "Advanced options:" echo " -f --fix-perms Fix folder permissions" echo " -i --install-deps Install build dependencies" + echo " -m --prep-minimal-env Prep live & airootfs folders (minimal packages)" echo " -o --build-iso Build ISO (using current setup)" echo " -p --prep-live-env Prep live & airootfs folders" echo " -u --update-repo Update custom pacman repo" From a9c5c1c27425ef88e90038bbdcd1028a20a367ab Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 28 Dec 2018 17:46:02 -0700 Subject: [PATCH 200/265] Fixed issue #80 --- .bin/Scripts/functions/hw_diags.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index fae78b21..1b1d2ae5 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -366,6 +366,8 @@ class DiskObj(): # Attributes if 'NVMe / SMART' not in self.tests: report.extend(self.generate_attribute_report()) + elif not self.tests['NVMe / SMART'].report: + report.extend(self.generate_attribute_report()) # Tests for test in self.tests.values(): @@ -1592,6 +1594,9 @@ def show_results(state): show_report(disk.generate_disk_report(), log_report=True) print_standard(' ') + # Update progress + update_progress_pane(state) + def update_main_options(state, selection, main_options): """Update menu and state based on selection.""" From dfe009c413de51aa18d9f2e23b2b44bd23f53bf1 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 28 Dec 2018 18:01:10 -0700 Subject: [PATCH 201/265] Added warning when failing to connect to osTicket * Fixes issue #34 --- .bin/Scripts/functions/osticket.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.bin/Scripts/functions/osticket.py b/.bin/Scripts/functions/osticket.py index bbf78353..3a1d20d7 100644 --- a/.bin/Scripts/functions/osticket.py +++ b/.bin/Scripts/functions/osticket.py @@ -30,7 +30,7 @@ class osTicket(): self.tests_disk = tests_disk self.tunnel_proc = None - def connect(self): + def connect(self, silent=True): """Establish connection to osTicket via a SSH tunnel.""" cmd = [ 'ssh', '-N', @@ -74,6 +74,11 @@ class osTicket(): if self.db_cursor is None: self.disabled = True self.tunnel_proc.kill() + if not silent: + print_warning('Failed to connect to osTicket') + print_standard('Integration disabled for this session') + print_standard(' ') + pause() def convert_report(self, name, test): """Convert report into an osTicket friendly format, returns list.""" @@ -354,7 +359,7 @@ class osTicket(): def get_ticket_number(self): """Get ticket number and confirm with name from osTicket DB.""" ticket_number = None - self.connect() + self.connect(silent=False) # Bail if disabled if self.disabled: @@ -369,6 +374,7 @@ class osTicket(): # No ticket ID entered if re.match(r'^\s*$', _input): if ask('Disable osTicket integration for this run?'): + self.disabled = True break # Invalid ID entered From 88dffd74327c14e1d7062a1c7fe5dc9e87960139 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 1 Jan 2019 21:06:08 -0700 Subject: [PATCH 202/265] Added New System Setup * This is a combination of the following scripts: * Install ESET AV * Install SW Bundle * User Checklist * System Checklist --- .bin/Scripts/functions/setup.py | 25 +++- .bin/Scripts/functions/sw_diags.py | 33 ++++++ .bin/Scripts/new_system_setup.py | 181 +++++++++++++++++++++++++++++ .bin/Scripts/settings/launchers.py | 6 + 4 files changed, 239 insertions(+), 6 deletions(-) create mode 100644 .bin/Scripts/new_system_setup.py diff --git a/.bin/Scripts/functions/setup.py b/.bin/Scripts/functions/setup.py index 8cc3fb60..7ca76b52 100644 --- a/.bin/Scripts/functions/setup.py +++ b/.bin/Scripts/functions/setup.py @@ -356,20 +356,33 @@ def install_firefox_extensions(): run_program(cmd) -def install_ninite_bundle(mse=False): +def install_ninite_bundle(mse=False, libreoffice=False): + """Run Ninite installer(s), returns list of Popen objects.""" """Run Ninite file(s) based on OS version.""" + popen_objects = [] if global_vars['OS']['Version'] in ('8', '8.1', '10'): # Modern selection - popen_program(r'{BaseDir}\Installers\Extras\Bundles\Modern.exe'.format( - **global_vars)) + popen_objects.append( + popen_program(r'{BaseDir}\Installers\Extras\Bundles\Modern.exe'.format( + **global_vars))) else: # Legacy selection if mse: cmd = r'{BaseDir}\Installers\Extras\Security'.format(**global_vars) cmd += r'\Microsoft Security Essentials.exe' - popen_program(cmd) - popen_program(r'{BaseDir}\Installers\Extras\Bundles\Legacy.exe'.format( - **global_vars)) + popen_objects.append(popen_program(cmd)) + popen_objects.append( + popen_program(r'{BaseDir}\Installers\Extras\Bundles\Legacy.exe'.format( + **global_vars))) + + # LibreOffice + if libreoffice: + cmd = r'{BaseDir}\Installers\Extras\Office'.format(**global_vars) + cmd += r'\LibreOffice.exe' + popen_objects.append(popen_program(cmd)) + + # Done + return popen_objects def install_vcredists(): diff --git a/.bin/Scripts/functions/sw_diags.py b/.bin/Scripts/functions/sw_diags.py index 8faa25b7..d5a74060 100644 --- a/.bin/Scripts/functions/sw_diags.py +++ b/.bin/Scripts/functions/sw_diags.py @@ -41,6 +41,39 @@ def check_connection(): abort() +def check_for_outdated_os(show_alert=False): + """Checks if the current OS is supported, returns bool. + + NOTE: Preview Builds are considered outdated even if newer than + the latest stable release. This is done for simplicity and + because preview builds are only valid for a short timeframe. + """ + msg = '' + needs_updated = False + preview_build = False + + # Check OS version/notes + os_info = global_vars['OS'].copy() + if os_info['Notes'] == 'unsupported': + needs_updated = True + elif os_info['Version'] == '10' and os_info['Notes'] == 'preview build': + preview_build = True + elif os_info['Version'] == '10' and os_info['Notes'] == 'outdated': + needs_updated = True + + # Show alert + if preview_build: + msg = 'Preview builds are not officially supported' + elif needs_updated: + msg = 'The installed version of Windows is outdated' + if msg and show_alert: + msg += '\n\nPlease consider upgrading before continuing setup.' + show_alert_box(msg) + + # Done + return needs_updated or preview_build + + def check_secure_boot_status(show_alert=False): """Checks UEFI Secure Boot status via PowerShell.""" boot_mode = get_boot_mode() diff --git a/.bin/Scripts/new_system_setup.py b/.bin/Scripts/new_system_setup.py new file mode 100644 index 00000000..42005ba9 --- /dev/null +++ b/.bin/Scripts/new_system_setup.py @@ -0,0 +1,181 @@ +# Wizard Kit: New system setup + +import os +import sys + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +sys.path.append(os.getcwd()) +from functions.activation import * +from functions.browsers import * +from functions.cleanup import * +from functions.info import * +from functions.product_keys import * +from functions.setup import * +from functions.sw_diags import * +init_global_vars() +os.system('title {}: New System Setup'.format(KIT_NAME_FULL)) +set_log_file('New System Setup.log') + +if __name__ == '__main__': + other_results = { + 'Error': { + 'BIOSKeyNotFoundError': 'BIOS key not found', + 'CalledProcessError': 'Unknown Error', + 'FileNotFoundError': 'File not found', + 'GenericError': 'Unknown Error', + 'SecureBootDisabledError': 'Disabled', + }, + 'Warning': { + 'GenericRepair': 'Repaired', + 'NoProfilesError': 'No profiles found', + 'NotInstalledError': 'Not installed', + 'OSInstalledLegacyError': 'OS installed Legacy', + 'SecureBootNotAvailError': 'Not available', + 'SecureBootUnknownError': 'Unknown', + 'UnsupportedOSError': 'Unsupported OS', + }} + try: + stay_awake() + clear_screen() + + # Check installed OS + os_needs_updated = check_for_outdated_os(show_alert=True) + if os_needs_updated: + print_warning('OS version not supported by this script') + if not ask('Continue anyway? (NOT RECOMMENDED)'): + abort() + + # Scan for supported browsers + print_info('Scanning for browsers') + scan_for_browsers() + + # Select AV software + # NOTE: Truth tuple is (ESET, ESET_PUPS, MSE) + av_options = [ + {'Name': 'ESET NOD32', + 'Truths': (True, True, False),}, + {'Name': 'ESET NOD32 (no PUP/PUW scans)', + 'Truths': (True, False, False),}, + {'Name': 'Microsoft Security Essentials', + 'Disabled': global_vars['OS']['Version'] not in ['7'], + 'Truths': (False, False, True),}, + ] + actions = [ + {'Name': 'None', 'Letter': 'N'}, + {'Name': 'Quit', 'Letter': 'Q'}, + ] + selection = menu_select( + 'Please select an option to install', + main_entries=av_options, + action_entries=actions) + if selection.isnumeric(): + index = int(selection) - 1 + answer_eset, answer_pups, answer_mse = av_options[index]['Truths'] + elif selection == 'Q': + abort() + else: + answer_eset = False + answer_pups = False + answer_mse = False + + # Install LibreOffice? + answer_libreoffice = ask('Install LibreOffice?') + + # Install software + print_info('Installing Programs') + install_vcredists() + if answer_eset: + install_eset_nod32_av(scan_pups=answer_pups) + result = try_and_print( + message='Ninite bundle...', + function=install_ninite_bundle, cs='Started', + mse=answer_mse, libreoffice=answer_libreoffice, + other_results=other_results) + for proc in result['Out']: + # Wait for all processes to finish + proc.wait() + + # Install extensions + print_info('Installing Extensions') + try_and_print(message='Classic Shell skin...', + function=install_classicstart_skin, + other_results=other_results) + try_and_print(message='Google Chrome extensions...', + function=install_chrome_extensions) + try_and_print(message='Mozilla Firefox extensions...', + function=install_firefox_extensions, + other_results=other_results) + + # Configure software + print_info('Configuring programs') + install_adblock() + if global_vars['OS']['Version'] == '10': + try_and_print(message='ClassicStart...', + function=config_classicstart, cs='Done') + try_and_print(message='Explorer...', + function=config_explorer_user, cs='Done') + + # Configure system + print_info('Configuring system') + if global_vars['OS']['Version'] == '10': + try_and_print(message='Explorer...', + function=config_explorer_system, cs='Done') + try_and_print(message='Disabling telemetry...', + function=disable_windows_telemetry, cs='Done') + try_and_print(message='Enabling RegBack...', + function=enable_regback, cs='Done') + try_and_print(message='Enabling System Restore...', + function=enable_system_restore, cs='Done') + try_and_print(message='Updating Clock...', + function=update_clock, cs='Done') + + # Summary + print_info('Summary') + try_and_print(message='Operating System:', + function=show_os_name, ns='Unknown', silent_function=False) + try_and_print(message='Activation:', + function=show_os_activation, ns='Unknown', silent_function=False) + if (not windows_is_activated() + and global_vars['OS']['Version'] in ('8', '8.1', '10')): + try_and_print(message='BIOS Activation:', + function=activate_with_bios, + other_results=other_results) + try_and_print(message='Secure Boot Status:', + function=check_secure_boot_status, other_results=other_results) + try_and_print(message='Installed RAM:', + function=show_installed_ram, ns='Unknown', silent_function=False) + show_free_space() + try_and_print(message='Installed Antivirus:', + function=get_installed_antivirus, ns='Unknown', + other_results=other_results, print_return=True) + + # Play audio, show devices, open Windows updates, and open Activation + try_and_print(message='Opening Device Manager...', + function=open_device_manager, cs='Started') + try_and_print(message='Opening HWiNFO (Sensors)...', + function=run_hwinfo_sensors, cs='Started', other_results=other_results) + try_and_print(message='Opening Windows Updates...', + function=open_windows_updates, cs='Started') + if not windows_is_activated(): + try_and_print(message='Opening Windows Activation...', + function=open_windows_activation, cs='Started') + sleep(3) + try_and_print(message='Running XMPlay...', + function=run_xmplay, cs='Started', other_results=other_results) + try: + check_secure_boot_status(show_alert=True) + except: + # Only trying to open alert message boxes + pass + + # Done + print_standard('\nDone.') + pause('Press Enter to exit...') + exit_script() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/settings/launchers.py b/.bin/Scripts/settings/launchers.py index 9679184e..a1f29683 100644 --- a/.bin/Scripts/settings/launchers.py +++ b/.bin/Scripts/settings/launchers.py @@ -13,6 +13,12 @@ LAUNCHERS = { 'L_PATH': 'd7II', 'L_ITEM': 'd7II.exe', }, + 'New System Setup': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'new_system_setup.py', + 'L_ELEV': 'True', + }, 'Post-d7II Work': { 'L_TYPE': 'PyScript', 'L_PATH': 'Scripts', From 49c1987ccfb73353397b9b318b9a6604bf37891f Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 1 Jan 2019 21:23:33 -0700 Subject: [PATCH 203/265] Adjusted unsupported OS detection --- .bin/Scripts/functions/sw_diags.py | 60 ++++++++++++++---------------- .bin/Scripts/new_system_setup.py | 3 +- 2 files changed, 28 insertions(+), 35 deletions(-) diff --git a/.bin/Scripts/functions/sw_diags.py b/.bin/Scripts/functions/sw_diags.py index d5a74060..100e5ad5 100644 --- a/.bin/Scripts/functions/sw_diags.py +++ b/.bin/Scripts/functions/sw_diags.py @@ -41,39 +41,6 @@ def check_connection(): abort() -def check_for_outdated_os(show_alert=False): - """Checks if the current OS is supported, returns bool. - - NOTE: Preview Builds are considered outdated even if newer than - the latest stable release. This is done for simplicity and - because preview builds are only valid for a short timeframe. - """ - msg = '' - needs_updated = False - preview_build = False - - # Check OS version/notes - os_info = global_vars['OS'].copy() - if os_info['Notes'] == 'unsupported': - needs_updated = True - elif os_info['Version'] == '10' and os_info['Notes'] == 'preview build': - preview_build = True - elif os_info['Version'] == '10' and os_info['Notes'] == 'outdated': - needs_updated = True - - # Show alert - if preview_build: - msg = 'Preview builds are not officially supported' - elif needs_updated: - msg = 'The installed version of Windows is outdated' - if msg and show_alert: - msg += '\n\nPlease consider upgrading before continuing setup.' - show_alert_box(msg) - - # Done - return needs_updated or preview_build - - def check_secure_boot_status(show_alert=False): """Checks UEFI Secure Boot status via PowerShell.""" boot_mode = get_boot_mode() @@ -136,6 +103,33 @@ def get_boot_mode(): return type_str +def os_is_unsupported(show_alert=False): + """Checks if the current OS is unsupported, returns bool.""" + msg = '' + unsupported = False + + # Check OS version/notes + os_info = global_vars['OS'].copy() + if os_info['Notes'] == 'unsupported': + msg = 'The installed version of Windows is no longer supported' + unsupported = True + elif os_info['Notes'] == 'preview build': + msg = 'Preview builds are not officially supported' + unsupported = True + elif os_info['Version'] == '10' and os_info['Notes'] == 'outdated': + msg = 'The installed version of Windows is outdated' + unsupported = True + if 'Preview' not in msg: + msg += '\n\nPlease consider upgrading before continuing setup.' + + # Show alert + if unsupported and show_alert: + show_alert_box(msg) + + # Done + return unsupported + + def run_autoruns(): """Run AutoRuns in the background with VirusTotal checks enabled.""" extract_item('Autoruns', filter='autoruns*', silent=True) diff --git a/.bin/Scripts/new_system_setup.py b/.bin/Scripts/new_system_setup.py index 42005ba9..597fe981 100644 --- a/.bin/Scripts/new_system_setup.py +++ b/.bin/Scripts/new_system_setup.py @@ -40,8 +40,7 @@ if __name__ == '__main__': clear_screen() # Check installed OS - os_needs_updated = check_for_outdated_os(show_alert=True) - if os_needs_updated: + if os_is_unsupported(show_alert=True): print_warning('OS version not supported by this script') if not ask('Continue anyway? (NOT RECOMMENDED)'): abort() From 6340bceb118736e8294dabfbe67b806c9d1ec89a Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 2 Jan 2019 17:05:08 -0700 Subject: [PATCH 204/265] Added warning if no disks detected. --- .bin/Scripts/functions/hw_diags.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 1b1d2ae5..202be76d 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -1010,6 +1010,10 @@ def run_hw_tests(state): f = v['Function'] for test_obj in v['Objects']: f(state, test_obj) + if not v['Objects']: + # No devices available + v['Objects'].append(TestObj(dev=None, label='')) + v['Objects'][-1].update_status('N/A') except GenericAbort: # Cleanup tmux_kill_pane(*state.panes.values()) @@ -1593,6 +1597,9 @@ def show_results(state): for disk in state.disks: show_report(disk.generate_disk_report(), log_report=True) print_standard(' ') + if not state.disks: + print_warning('No devices') + print_standard(' ') # Update progress update_progress_pane(state) From 3122a75f646252f44d11b2e86ef10d1c269e175d Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 2 Jan 2019 17:31:19 -0700 Subject: [PATCH 205/265] Skip fan RPMs * Avoids reporting fan RPMs as 6000+ *C --- .bin/Scripts/functions/sensors.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.bin/Scripts/functions/sensors.py b/.bin/Scripts/functions/sensors.py index a50f8941..8b2b8b03 100644 --- a/.bin/Scripts/functions/sensors.py +++ b/.bin/Scripts/functions/sensors.py @@ -134,6 +134,9 @@ def get_sensor_data(): ## current temp is labeled xxxx_input for _source, _labels in _sources.items(): for _label, _temp in _labels.items(): + if _label.startswith('fan'): + # Skip fan RPMs + continue if 'input' in _label: sensor_data[_section][_adapter][_source] = { 'Current': _temp, From 141fe422db805a13731e146a26f348ba0d125b7c Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 2 Jan 2019 17:55:56 -0700 Subject: [PATCH 206/265] Fix NVMe attribute handling * Addresses issue #78 --- .bin/Scripts/functions/hw_diags.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 202be76d..e966dc77 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -418,7 +418,9 @@ class DiskObj(): # Check for attributes if KEY_NVME in self.smartctl: - self.nvme_attributes.update(self.smartctl[KEY_NVME]) + self.nvme_attributes = { + k: {'name': k, 'raw': int(v), 'raw_str': str(v)} + for k, v in self.smartctl[KEY_NVME].items()} elif KEY_SMART in self.smartctl: for a in self.smartctl[KEY_SMART].get('table', {}): try: @@ -453,7 +455,7 @@ class DiskObj(): self.check_attributes(silent) # Check if a self-test is currently running - if 'remaining_percent' in self.smart_self_test['status']: + if 'remaining_percent' in self.smart_self_test.get('status', ''): _msg = 'SMART self-test in progress, all tests disabled' # Ask to abort From 3d69fe773db38b3f6582c0d96af158e4948db809 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 2 Jan 2019 18:02:24 -0700 Subject: [PATCH 207/265] Removed sensors section from hw-info * Fixes issue #81 --- .bin/Scripts/hw-info | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.bin/Scripts/hw-info b/.bin/Scripts/hw-info index 98514e3e..8321e7aa 100755 --- a/.bin/Scripts/hw-info +++ b/.bin/Scripts/hw-info @@ -105,8 +105,3 @@ echo -e "${BLUE}Drives${CLEAR}" hw-drive-info | sed 's/^/ /' echo "" -# Sensors -echo -e "${BLUE}Sensors${CLEAR}" -hw-sensors | sed 's/^/ /' -echo "" - From aa4c6a1434095e4753e169cafcab24c9c52bd5c7 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 2 Jan 2019 18:04:32 -0700 Subject: [PATCH 208/265] Fix issue #82 --- .bin/Scripts/hw-sensors-monitor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bin/Scripts/hw-sensors-monitor b/.bin/Scripts/hw-sensors-monitor index 42757748..731f415e 100755 --- a/.bin/Scripts/hw-sensors-monitor +++ b/.bin/Scripts/hw-sensors-monitor @@ -10,7 +10,7 @@ os.chdir(os.path.dirname(os.path.realpath(__file__))) sys.path.append(os.getcwd()) from functions.sensors import * from functions.tmux import * -init_global_vars() +init_global_vars(silent=True) if __name__ == '__main__': background = False From 97d0125c038eb597289ba7138435cf789277e2f8 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 2 Jan 2019 18:41:35 -0700 Subject: [PATCH 209/265] Avoid crash in I/O Benchmark with small disks --- .bin/Scripts/functions/io_graph.py | 3 +++ .bin/Scripts/functions/osticket.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.bin/Scripts/functions/io_graph.py b/.bin/Scripts/functions/io_graph.py index 7a96d8aa..57048bfd 100644 --- a/.bin/Scripts/functions/io_graph.py +++ b/.bin/Scripts/functions/io_graph.py @@ -13,6 +13,9 @@ from functions.common import * def export_io_graph(disk): """Exports PNG graph using gnuplot, returns file path as str.""" read_rates = disk.tests['I/O Benchmark'].read_rates + if not read_rates: + # No data, aborting + raise GenericError max_rate = max(read_rates) / (1024**2) max_rate = max(800, max_rate) out_path = '{}/iobenchmark-{}.png'.format( diff --git a/.bin/Scripts/functions/osticket.py b/.bin/Scripts/functions/osticket.py index 3a1d20d7..ee26bca6 100644 --- a/.bin/Scripts/functions/osticket.py +++ b/.bin/Scripts/functions/osticket.py @@ -196,6 +196,9 @@ class osTicket(): # Create PNG graph try: graph_file = export_io_graph(dev) + except GenericError: + # No data to build graph, ignoring + pass except (AttributeError, KeyError): report.append('Failed to export graph') else: From 4a04e92cafe30ff68d56ea2f4e8f03d524a7b49e Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 5 Jan 2019 15:54:05 -0700 Subject: [PATCH 210/265] Added threading.py * Will be used by hw_diags.py and ddrescue.py for * Better control over badblocks * Background the tmux pane fixes --- .bin/Scripts/functions/threading.py | 47 +++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .bin/Scripts/functions/threading.py diff --git a/.bin/Scripts/functions/threading.py b/.bin/Scripts/functions/threading.py new file mode 100644 index 00000000..dfac69c7 --- /dev/null +++ b/.bin/Scripts/functions/threading.py @@ -0,0 +1,47 @@ +# Wizard Kit: Functions - Threading + +from threading import Thread +from queue import Queue, Empty + +# Classes +class NonBlockingStreamReader(): + """Class to allow non-blocking reads from a stream.""" + # Credits: + ## https://gist.github.com/EyalAr/7915597 + ## https://stackoverflow.com/a/4896288 + + def __init__(self, stream): + self.stream = stream + self.queue = Queue() + + def populate_queue(stream, queue): + """Collect lines from stream and put them in queue.""" + while True: + line = stream.read(1) + if line: + queue.put(line) + + self.thread = start_thread( + populate_queue, + args=(self.stream, self.queue)) + + def read(self, timeout=None): + try: + return self.queue.get(block = timeout is not None, + timeout = timeout) + except Empty: + return None + + +# Functions +def start_thread(function, args=[], daemon=True): + """Run function as thread in background, returns Thread object.""" + thread = Thread(target=function, args=args, daemon=daemon) + thread.start() + return thread + + +if __name__ == '__main__': + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From e40b0b98e40b56692479a306e49bdfc51b65e0ce Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sun, 6 Jan 2019 20:57:06 -0700 Subject: [PATCH 211/265] Moved fix_tmux_panes() into a background thread --- .bin/Scripts/functions/hw_diags.py | 120 +++++++++++++++-------------- .bin/Scripts/functions/tmux.py | 3 + 2 files changed, 66 insertions(+), 57 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index e966dc77..5dba82f9 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -6,6 +6,7 @@ import time from collections import OrderedDict from functions.sensors import * +from functions.threading import * from functions.tmux import * @@ -79,9 +80,15 @@ TESTS_DISK = [ ] TOP_PANE_TEXT = '{GREEN}Hardware Diagnostics{CLEAR}'.format(**COLORS) TMUX_LAYOUT = OrderedDict({ - 'Top': {'y': 2, 'Check': True}, - 'Started': {'x': SIDE_PANE_WIDTH, 'Check': True}, - 'Progress': {'x': SIDE_PANE_WIDTH, 'Check': True}, + 'Top': {'y': 2, 'Check': True}, + 'Started': {'x': SIDE_PANE_WIDTH, 'Check': True}, + 'Progress': {'x': SIDE_PANE_WIDTH, 'Check': True}, + # Testing panes + 'Prime95': {'y': 11, 'Check': False}, + 'Temps': {'y': 1000, 'Check': False}, + 'SMART': {'y': 3, 'Check': True}, + 'badblocks': {'y': 5, 'Check': True}, + 'I/O Benchmark': {'y': 1000, 'Check': False}, }) @@ -640,12 +647,25 @@ def build_status_string(label, status, info_label=False): **COLORS) -def fix_tmux_panes(state, tmux_layout): +def fix_tmux_panes_loop(state): + while True: + try: + fix_tmux_panes(state) + sleep(1) + except AttributeError: + # tmux_layout attribute has been deleted, exit function + return + except RuntimeError: + # Assuming layout definitions changes mid-run, ignoring + pass + + +def fix_tmux_panes(state): """Fix pane sizes if the window has been resized.""" needs_fixed = False # Check layout - for k, v in tmux_layout.items(): + for k, v in state.tmux_layout.items(): if not v.get('Check'): # Not concerned with the size of this pane continue @@ -670,7 +690,7 @@ def fix_tmux_panes(state, tmux_layout): return # Update layout - for k, v in tmux_layout.items(): + for k, v in state.tmux_layout.items(): # Get target target = None if k != 'Current': @@ -886,10 +906,6 @@ def run_badblocks_test(state, test): state.panes['Top'], text='{}\n{}'.format( TOP_PANE_TEXT, test.dev.description)) - test.tmux_layout = TMUX_LAYOUT.copy() - test.tmux_layout.update({ - 'badblocks': {'y': 5, 'Check': True}, - }) # Create monitor pane test.badblocks_out = '{}/badblocks_{}.out'.format( @@ -908,14 +924,7 @@ def run_badblocks_test(state, test): test.badblocks_proc = popen_program( ['sudo', 'hw-diags-badblocks', test.dev.path, test.badblocks_out], pipe=True) - while True: - try: - test.badblocks_proc.wait(timeout=1) - except subprocess.TimeoutExpired: - fix_tmux_panes(state, test.tmux_layout) - else: - # badblocks finished, exit loop - break + test.badblocks_proc.wait() except KeyboardInterrupt: test.aborted = True @@ -960,7 +969,7 @@ def run_badblocks_test(state, test): update_progress_pane(state) # Cleanup - tmux_kill_pane(state.panes['badblocks']) + tmux_kill_pane(state.panes.pop('badblocks', None)) def run_hw_tests(state): @@ -971,6 +980,7 @@ def run_hw_tests(state): # Build Panes update_progress_pane(state) build_outer_panes(state) + start_tmux_repair_thread(state) # Show selected tests and create TestObj()s print_info('Selected Tests:') @@ -1018,11 +1028,13 @@ def run_hw_tests(state): v['Objects'][-1].update_status('N/A') except GenericAbort: # Cleanup + stop_tmux_repair_thread(state) tmux_kill_pane(*state.panes.values()) # Rebuild panes update_progress_pane(state) build_outer_panes(state) + start_tmux_repair_thread(state) # Mark unfinished tests as aborted for k, v in state.tests.items(): @@ -1036,12 +1048,14 @@ def run_hw_tests(state): # Done show_results(state) + sleep(1) if state.quick_mode: - pause('Press Enter to exit...') + pause('Press Enter to exit... ') else: pause('Press Enter to return to main menu... ') # Cleanup + stop_tmux_repair_thread(state) tmux_kill_pane(*state.panes.values()) @@ -1062,11 +1076,7 @@ def run_io_benchmark(state, test): state.panes['Top'], text='{}\n{}'.format( TOP_PANE_TEXT, test.dev.description)) - test.tmux_layout = TMUX_LAYOUT.copy() - test.tmux_layout.update({ - 'io_benchmark': {'y': 1000, 'Check': False}, - 'Current': {'y': 15, 'Check': True}, - }) + state.tmux_layout['Current'] = {'y': 15, 'Check': True} # Create monitor pane test.io_benchmark_out = '{}/io_benchmark_{}.out'.format( @@ -1123,9 +1133,6 @@ def run_io_benchmark(state, test): # Update offset offset += test.dev.dd_chunk_blocks + skip - # Fix panes - fix_tmux_panes(state, test.tmux_layout) - except DeviceTooSmallError: # Device too small, skipping test test.update_status('N/A') @@ -1200,7 +1207,8 @@ def run_io_benchmark(state, test): update_progress_pane(state) # Cleanup - tmux_kill_pane(state.panes['io_benchmark']) + state.tmux_layout.pop('Current', None) + tmux_kill_pane(state.panes.pop('io_benchmark', None)) def run_keyboard_test(): @@ -1226,12 +1234,6 @@ def run_mprime_test(state, test): tmux_update_pane( state.panes['Top'], text='{}\n{}'.format(TOP_PANE_TEXT, test.dev.name)) - test.tmux_layout = TMUX_LAYOUT.copy() - test.tmux_layout.update({ - 'Temps': {'y': 1000, 'Check': False}, - 'mprime': {'y': 11, 'Check': False}, - 'Current': {'y': 3, 'Check': True}, - }) # Start live sensor monitor test.sensors_out = '{}/sensors.out'.format(global_vars['TmpDir']) @@ -1244,11 +1246,12 @@ def run_mprime_test(state, test): pipe=True) # Create monitor and worker panes - state.panes['mprime'] = tmux_split_window( + state.panes['Prime95'] = tmux_split_window( lines=10, vertical=True, text=' ') state.panes['Temps'] = tmux_split_window( behind=True, percent=80, vertical=True, watch=test.sensors_out) tmux_resize_pane(global_vars['Env']['TMUX_PANE'], y=3) + state.tmux_layout['Current'] = {'y': 3, 'Check': True} # Get idle temps clear_screen() @@ -1263,7 +1266,7 @@ def run_mprime_test(state, test): test.abort_msg = 'If running too hot, press CTRL+c to abort the test' run_program(['apple-fans', 'max']) tmux_update_pane( - state.panes['mprime'], + state.panes['Prime95'], command=['hw-diags-prime95', global_vars['TmpDir']], working_dir=global_vars['TmpDir']) time_limit = int(MPRIME_LIMIT) * 60 @@ -1285,9 +1288,6 @@ def run_mprime_test(state, test): print('{YELLOW}{msg}{CLEAR}'.format(msg=test.abort_msg, **COLORS)) update_sensor_data(test.sensor_data) - # Fix panes - fix_tmux_panes(state, test.tmux_layout) - # Wait sleep(1) except KeyboardInterrupt: @@ -1305,7 +1305,7 @@ def run_mprime_test(state, test): # Stop Prime95 (twice for good measure) run_program(['killall', '-s', 'INT', 'mprime'], check=False) sleep(1) - tmux_kill_pane(state.panes['mprime']) + tmux_kill_pane(state.panes.pop('Prime95', None)) # Get cooldown temp run_program(['apple-fans', 'auto']) @@ -1399,7 +1399,11 @@ def run_mprime_test(state, test): update_progress_pane(state) # Cleanup - tmux_kill_pane(state.panes['mprime'], state.panes['Temps']) + state.tmux_layout.pop('Current', None) + tmux_kill_pane( + state.panes.pop('Prime95', None), + state.panes.pop('Temps', None), + ) test.monitor_proc.kill() @@ -1428,10 +1432,6 @@ def run_nvme_smart_tests(state, test): state.panes['Top'], text='{}\n{}'.format( TOP_PANE_TEXT, test.dev.description)) - test.tmux_layout = TMUX_LAYOUT.copy() - test.tmux_layout.update({ - 'smart': {'y': 3, 'Check': True}, - }) # NVMe if test.dev.nvme_attributes: @@ -1471,7 +1471,7 @@ def run_nvme_smart_tests(state, test): global_vars['LogDir'], test.dev.name) with open(test.smart_out, 'w') as f: f.write('SMART self-test status:\n Starting...') - state.panes['smart'] = tmux_split_window( + state.panes['SMART'] = tmux_split_window( lines=3, vertical=True, watch=test.smart_out) # Show attributes @@ -1486,15 +1486,8 @@ def run_nvme_smart_tests(state, test): # Monitor progress try: - for i in range(int(test.timeout*60)): - sleep(1) - - # Fix panes - fix_tmux_panes(state, test.tmux_layout) - - # Only update SMART progress every 5 seconds - if i % 5 != 0: - continue + for i in range(int(test.timeout*60/5)): + sleep(5) # Update SMART data test.dev.get_smart_details() @@ -1544,7 +1537,7 @@ def run_nvme_smart_tests(state, test): test.dev.disable_test(t, 'Denied') # Cleanup - tmux_kill_pane(state.panes['smart']) + tmux_kill_pane(state.panes.pop('SMART', None)) # Save report test.report = test.dev.generate_attribute_report( @@ -1607,6 +1600,19 @@ def show_results(state): update_progress_pane(state) +def start_tmux_repair_thread(state): + """Fix tmux panes as long as state.tmux_layout attribute exists.""" + state.tmux_layout = TMUX_LAYOUT.copy() + start_thread(fix_tmux_panes_loop, args=[state]) + + +def stop_tmux_repair_thread(state): + """Stop previous thread by causing an AttributeError in the thread.""" + if hasattr(state, 'tmux_layout'): + del state.tmux_layout + sleep(1) + + def update_main_options(state, selection, main_options): """Update menu and state based on selection.""" index = int(selection) - 1 diff --git a/.bin/Scripts/functions/tmux.py b/.bin/Scripts/functions/tmux.py index a11560bc..e2d1b333 100644 --- a/.bin/Scripts/functions/tmux.py +++ b/.bin/Scripts/functions/tmux.py @@ -44,6 +44,9 @@ def tmux_kill_pane(*panes): """Kill tmux pane by id.""" cmd = ['tmux', 'kill-pane', '-t'] for pane_id in panes: + if not pane_id: + # Skip empty strings, None values, etc + continue run_program(cmd+[pane_id], check=False) From 68bbee66d55416877fca5731e87bba2506b88efd Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sun, 6 Jan 2019 21:45:01 -0700 Subject: [PATCH 212/265] Replaced hw-diags-badblocks with threaded section * Should fix issue #83 --- .bin/Scripts/functions/hw_diags.py | 36 +++++++++++++++++++++--------- .bin/Scripts/hw-diags-badblocks | 18 --------------- 2 files changed, 26 insertions(+), 28 deletions(-) delete mode 100755 .bin/Scripts/hw-diags-badblocks diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 5dba82f9..c9ce87f7 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -895,6 +895,18 @@ def run_badblocks_test(state, test): if test.disabled: return + def _save_badblocks_output(read_all=False, timeout=0.1): + """Get badblocks output and append to both file and var.""" + _output = '' + while _output is not None: + _output = test.badblocks_nbsr.read(0.1) + if _output is not None: + test.badblocks_stderr += _output.decode() + with open(test.badblocks_out, 'a') as f: + f.write(_output.decode()) + if not read_all: + break + # Prep print_log('Starting badblocks test for {}'.format(test.dev.path)) test.started = True @@ -920,22 +932,26 @@ def run_badblocks_test(state, test): # Start badblocks print_standard('Running badblocks test...') - try: - test.badblocks_proc = popen_program( - ['sudo', 'hw-diags-badblocks', test.dev.path, test.badblocks_out], - pipe=True) - test.badblocks_proc.wait() + test.badblocks_proc = popen_program( + ['sudo', 'badblocks', '-sv', '-e', '1', test.dev.path], + pipe=True, bufsize=1) + test.badblocks_nbsr = NonBlockingStreamReader(test.badblocks_proc.stderr) + test.badblocks_stderr = '' + # Update progress loop + try: + while test.badblocks_proc.poll() is None: + _save_badblocks_output() except KeyboardInterrupt: + run_program(['killall', 'badblocks'], check=False) test.aborted = True + # Save remaining badblocks output + _save_badblocks_output(read_all=True) + # Check result and build report test.report.append('{BLUE}badblocks{CLEAR}'.format(**COLORS)) - try: - test.badblocks_out = test.badblocks_proc.stdout.read().decode() - except Exception as err: - test.badblocks_out = 'Error: {}'.format(err) - for line in test.badblocks_out.splitlines(): + for line in test.badblocks_stderr.splitlines(): line = line.strip() if not line or re.search(r'^Checking', line, re.IGNORECASE): # Skip empty and progress lines diff --git a/.bin/Scripts/hw-diags-badblocks b/.bin/Scripts/hw-diags-badblocks deleted file mode 100755 index 2d915766..00000000 --- a/.bin/Scripts/hw-diags-badblocks +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -# -## Wizard Kit: HW Diagnostics - badblocks - -function usage { - echo "Usage: $0 device log-file" - echo " e.g. $0 /dev/sda /tmp/tmp.XXXXXXX/badblocks.log" -} - -# Bail early -if [ ! -b "$1" ]; then - usage - exit 1 -fi - -# Run Badblocks -sudo badblocks -sv -e 1 "$1" 2>&1 | tee -a "$2" - From 7a9474a6a86495e1d9001605a3c18749c08bfc48 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sun, 6 Jan 2019 21:51:45 -0700 Subject: [PATCH 213/265] Try enabling SMART before checking attributes * Fixes issue #84 --- .bin/Scripts/functions/hw_diags.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index c9ce87f7..e4f193f4 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -157,6 +157,11 @@ class DiskObj(): self.smartctl = {} self.tests = OrderedDict() self.get_details() + + # Try enabling SMART + run_program(['sudo', 'smartctl', '--smart=on', self.path], check=False) + + # Get NVMe/SMART data and set description self.get_smart_details() self.description = '{size} ({tran}) {model} {serial}'.format( **self.lsblk) From 50da682d76a07c7877ac5d9b918ee12ee5353ab3 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sun, 6 Jan 2019 22:12:01 -0700 Subject: [PATCH 214/265] Fix issue #85 --- .bin/Scripts/functions/sensors.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/.bin/Scripts/functions/sensors.py b/.bin/Scripts/functions/sensors.py index 8b2b8b03..22a27ef4 100644 --- a/.bin/Scripts/functions/sensors.py +++ b/.bin/Scripts/functions/sensors.py @@ -108,14 +108,27 @@ def get_raw_sensor_data(): """Read sensor data and return dict.""" data = {} cmd = ['sensors', '-j'] + + # Get raw data try: result = run_program(cmd) - data = json.loads(result.stdout.decode()) except subprocess.CalledProcessError: # Assuming no sensors available, return empty dict below pass - return data + # Workaround for bad sensors + raw_data = [] + for line in result.stdout.decode().splitlines(): + if line.strip() == ',': + # Assuming malformatted line caused by missing data + continue + raw_data.append(line) + + # Parse JSON data + json_data = json.loads('\n'.join(raw_data)) + + # Done + return json_data def get_sensor_data(): From ae92eea76e1df16dbd19411e39f87245e2017416 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sun, 6 Jan 2019 22:43:33 -0700 Subject: [PATCH 215/265] Added macbook12-spi-driver-dkms to Minimal build --- .linux_items/packages/aur | 1 + .linux_items/packages/live_add_min | 1 + Build Linux | 6 ++++-- 3 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 .linux_items/packages/live_add_min diff --git a/.linux_items/packages/aur b/.linux_items/packages/aur index 8d752673..9588b129 100644 --- a/.linux_items/packages/aur +++ b/.linux_items/packages/aur @@ -2,6 +2,7 @@ aic94xx-firmware bash-pipes hfsprogs i3lock-fancy-git +macbook12-spi-driver-dkms mprime openbox-patched smartmontools-svn diff --git a/.linux_items/packages/live_add_min b/.linux_items/packages/live_add_min new file mode 100644 index 00000000..85653460 --- /dev/null +++ b/.linux_items/packages/live_add_min @@ -0,0 +1 @@ +macbook12-spi-driver-dkms diff --git a/Build Linux b/Build Linux index 52e060d2..4ccd1729 100755 --- a/Build Linux +++ b/Build Linux @@ -198,8 +198,10 @@ function update_live_env() { sed -i "/$p/d" "$LIVE_DIR/packages.x86_64" done < "$ROOT_DIR/.linux_items/packages/live_remove" cat "$ROOT_DIR/.linux_items/packages/live_add" >> "$LIVE_DIR/packages.x86_64" - if [[ "${1:-}" != "--minimal" ]]; then - cat "$ROOT_DIR/.linux_items/packages/live_add_x" >> "$LIVE_DIR/packages.x86_64" + if [[ "${1:-}" == "--minimal" ]]; then + cat "$ROOT_DIR/.linux_items/packages/live_add_min" >> "$LIVE_DIR/packages.x86_64" + else + cat "$ROOT_DIR/.linux_items/packages/live_add_x" >> "$LIVE_DIR/packages.x86_64" fi echo "[custom]" >> "$LIVE_DIR/pacman.conf" echo "SigLevel = Optional TrustAll" >> "$LIVE_DIR/pacman.conf" From 014da1b2247f26fefda0b72b55a448976ce3a072 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 7 Jan 2019 12:20:48 -0700 Subject: [PATCH 216/265] Fix issue #37 --- .bin/Scripts/functions/hw_diags.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 6c9de3fa..5a434a38 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -277,6 +277,8 @@ class DiskObj(): if not self.nvme_attributes and self.smart_attributes: # Re-enable for SMART short-tests self.tests['NVMe / SMART'].disabled = False + else: + self.tests['NVMe / SMART'].failed = True print_standard(' ') def disable_test(self, name, status): From ebcd38ef50b334a68bdcec5cfc4bcca2f647bed6 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 7 Jan 2019 12:53:23 -0700 Subject: [PATCH 217/265] Don't change directory during initialization * Fixes issue with ddrescue-tui --- .bin/Scripts/activate.py | 3 +-- .bin/Scripts/cbs_fix.py | 3 +-- .bin/Scripts/check_disk.py | 3 +-- .bin/Scripts/connect-to-network | 3 +-- .bin/Scripts/ddrescue-tui-menu | 3 +-- .bin/Scripts/dism.py | 3 +-- .bin/Scripts/hw-diags-audio | 3 +-- .bin/Scripts/hw-diags-menu | 3 +-- .bin/Scripts/hw-diags-network | 3 +-- .bin/Scripts/hw-sensors-monitor | 3 +-- .bin/Scripts/install_sw_bundle.py | 3 +-- .bin/Scripts/install_vcredists.py | 3 +-- .bin/Scripts/mount-all-volumes | 3 +-- .bin/Scripts/mount-backup-shares | 3 +-- .bin/Scripts/msword-search | 3 +-- .bin/Scripts/safemode_enter.py | 3 +-- .bin/Scripts/safemode_exit.py | 3 +-- .bin/Scripts/sfc_scan.py | 3 +-- .bin/Scripts/system_checklist.py | 3 +-- .bin/Scripts/system_diagnostics.py | 3 +-- .bin/Scripts/transferred_keys.py | 3 +-- .bin/Scripts/update_kit.py | 3 +-- .bin/Scripts/user_checklist.py | 3 +-- .bin/Scripts/user_data_transfer.py | 3 +-- .bin/Scripts/winpe_root_menu.py | 3 +-- 25 files changed, 25 insertions(+), 50 deletions(-) diff --git a/.bin/Scripts/activate.py b/.bin/Scripts/activate.py index cf17263f..f9a9c69d 100644 --- a/.bin/Scripts/activate.py +++ b/.bin/Scripts/activate.py @@ -4,8 +4,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.activation import * init_global_vars() os.system('title {}: Windows Activation Tool'.format(KIT_NAME_FULL)) diff --git a/.bin/Scripts/cbs_fix.py b/.bin/Scripts/cbs_fix.py index 460a32a5..36a7906f 100644 --- a/.bin/Scripts/cbs_fix.py +++ b/.bin/Scripts/cbs_fix.py @@ -4,8 +4,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.cleanup import * from functions.data import * init_global_vars() diff --git a/.bin/Scripts/check_disk.py b/.bin/Scripts/check_disk.py index 1140f4fc..5b0f3c14 100644 --- a/.bin/Scripts/check_disk.py +++ b/.bin/Scripts/check_disk.py @@ -4,8 +4,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.repairs import * init_global_vars() os.system('title {}: Check Disk Tool'.format(KIT_NAME_FULL)) diff --git a/.bin/Scripts/connect-to-network b/.bin/Scripts/connect-to-network index 5e04e903..02500b37 100755 --- a/.bin/Scripts/connect-to-network +++ b/.bin/Scripts/connect-to-network @@ -6,8 +6,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.network import * init_global_vars() diff --git a/.bin/Scripts/ddrescue-tui-menu b/.bin/Scripts/ddrescue-tui-menu index f1f3b08c..a6014d76 100755 --- a/.bin/Scripts/ddrescue-tui-menu +++ b/.bin/Scripts/ddrescue-tui-menu @@ -6,8 +6,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.ddrescue import * from functions.hw_diags import * init_global_vars() diff --git a/.bin/Scripts/dism.py b/.bin/Scripts/dism.py index 8b227da2..2ef3ff25 100644 --- a/.bin/Scripts/dism.py +++ b/.bin/Scripts/dism.py @@ -4,8 +4,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.repairs import * init_global_vars() os.system('title {}: DISM helper Tool'.format(KIT_NAME_FULL)) diff --git a/.bin/Scripts/hw-diags-audio b/.bin/Scripts/hw-diags-audio index 2c52c467..3d3a5991 100755 --- a/.bin/Scripts/hw-diags-audio +++ b/.bin/Scripts/hw-diags-audio @@ -6,8 +6,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.common import * init_global_vars() diff --git a/.bin/Scripts/hw-diags-menu b/.bin/Scripts/hw-diags-menu index 5b6f4f76..1c3cfc42 100755 --- a/.bin/Scripts/hw-diags-menu +++ b/.bin/Scripts/hw-diags-menu @@ -6,8 +6,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.hw_diags import * from functions.tmux import * init_global_vars() diff --git a/.bin/Scripts/hw-diags-network b/.bin/Scripts/hw-diags-network index 2ae0e263..3047e131 100755 --- a/.bin/Scripts/hw-diags-network +++ b/.bin/Scripts/hw-diags-network @@ -6,8 +6,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.network import * diff --git a/.bin/Scripts/hw-sensors-monitor b/.bin/Scripts/hw-sensors-monitor index 731f415e..c27d786a 100755 --- a/.bin/Scripts/hw-sensors-monitor +++ b/.bin/Scripts/hw-sensors-monitor @@ -6,8 +6,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.sensors import * from functions.tmux import * init_global_vars(silent=True) diff --git a/.bin/Scripts/install_sw_bundle.py b/.bin/Scripts/install_sw_bundle.py index 4386bfb0..b44874ae 100644 --- a/.bin/Scripts/install_sw_bundle.py +++ b/.bin/Scripts/install_sw_bundle.py @@ -4,8 +4,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.setup import * init_global_vars() os.system('title {}: SW Bundle Tool'.format(KIT_NAME_FULL)) diff --git a/.bin/Scripts/install_vcredists.py b/.bin/Scripts/install_vcredists.py index 1a722bf9..a22cc729 100644 --- a/.bin/Scripts/install_vcredists.py +++ b/.bin/Scripts/install_vcredists.py @@ -4,8 +4,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.setup import * init_global_vars() os.system('title {}: Install Visual C++ Runtimes'.format(KIT_NAME_FULL)) diff --git a/.bin/Scripts/mount-all-volumes b/.bin/Scripts/mount-all-volumes index 2c0a6621..f49439f2 100755 --- a/.bin/Scripts/mount-all-volumes +++ b/.bin/Scripts/mount-all-volumes @@ -6,8 +6,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.data import * init_global_vars() diff --git a/.bin/Scripts/mount-backup-shares b/.bin/Scripts/mount-backup-shares index 69374a9b..57fbe572 100755 --- a/.bin/Scripts/mount-backup-shares +++ b/.bin/Scripts/mount-backup-shares @@ -6,8 +6,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.data import * from functions.network import * init_global_vars() diff --git a/.bin/Scripts/msword-search b/.bin/Scripts/msword-search index c0461dda..b005c3c1 100755 --- a/.bin/Scripts/msword-search +++ b/.bin/Scripts/msword-search @@ -15,8 +15,7 @@ USAGE = '''Usage: {script} ... the search-terms provided (case-insensitive).'''.format(script=__file__) # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.network import * init_global_vars() diff --git a/.bin/Scripts/safemode_enter.py b/.bin/Scripts/safemode_enter.py index 027f4987..bc6d659d 100644 --- a/.bin/Scripts/safemode_enter.py +++ b/.bin/Scripts/safemode_enter.py @@ -4,8 +4,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.safemode import * init_global_vars() os.system('title {}: SafeMode Tool'.format(KIT_NAME_FULL)) diff --git a/.bin/Scripts/safemode_exit.py b/.bin/Scripts/safemode_exit.py index 85376d51..bbbdbcf8 100644 --- a/.bin/Scripts/safemode_exit.py +++ b/.bin/Scripts/safemode_exit.py @@ -4,8 +4,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.safemode import * init_global_vars() os.system('title {}: SafeMode Tool'.format(KIT_NAME_FULL)) diff --git a/.bin/Scripts/sfc_scan.py b/.bin/Scripts/sfc_scan.py index 9864306a..884694f5 100644 --- a/.bin/Scripts/sfc_scan.py +++ b/.bin/Scripts/sfc_scan.py @@ -4,8 +4,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.repairs import * init_global_vars() os.system('title {}: SFC Tool'.format(KIT_NAME_FULL)) diff --git a/.bin/Scripts/system_checklist.py b/.bin/Scripts/system_checklist.py index 1aa95d3e..5900ef00 100644 --- a/.bin/Scripts/system_checklist.py +++ b/.bin/Scripts/system_checklist.py @@ -4,8 +4,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.activation import * from functions.cleanup import * from functions.info import * diff --git a/.bin/Scripts/system_diagnostics.py b/.bin/Scripts/system_diagnostics.py index c7b363d8..47c35eab 100644 --- a/.bin/Scripts/system_diagnostics.py +++ b/.bin/Scripts/system_diagnostics.py @@ -4,8 +4,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.browsers import * from functions.info import * from functions.product_keys import * diff --git a/.bin/Scripts/transferred_keys.py b/.bin/Scripts/transferred_keys.py index 3308844c..6dab114d 100644 --- a/.bin/Scripts/transferred_keys.py +++ b/.bin/Scripts/transferred_keys.py @@ -4,8 +4,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.product_keys import * init_global_vars() os.system('title {}: Transferred Key Finder'.format(KIT_NAME_FULL)) diff --git a/.bin/Scripts/update_kit.py b/.bin/Scripts/update_kit.py index e02acc73..3bc31a72 100644 --- a/.bin/Scripts/update_kit.py +++ b/.bin/Scripts/update_kit.py @@ -4,8 +4,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.update import * init_global_vars() os.system('title {}: Kit Update Tool'.format(KIT_NAME_FULL)) diff --git a/.bin/Scripts/user_checklist.py b/.bin/Scripts/user_checklist.py index b57e8b29..91e5915a 100644 --- a/.bin/Scripts/user_checklist.py +++ b/.bin/Scripts/user_checklist.py @@ -4,8 +4,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.browsers import * from functions.cleanup import * from functions.setup import * diff --git a/.bin/Scripts/user_data_transfer.py b/.bin/Scripts/user_data_transfer.py index 1fa06256..e63e0d7d 100644 --- a/.bin/Scripts/user_data_transfer.py +++ b/.bin/Scripts/user_data_transfer.py @@ -4,8 +4,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.data import * from functions.repairs import * init_global_vars() diff --git a/.bin/Scripts/winpe_root_menu.py b/.bin/Scripts/winpe_root_menu.py index 5a1f0f8b..a9555e07 100644 --- a/.bin/Scripts/winpe_root_menu.py +++ b/.bin/Scripts/winpe_root_menu.py @@ -4,8 +4,7 @@ import os import sys # Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) +sys.path.append(os.path.dirname(os.path.realpath(__file__))) from functions.winpe_menus import * # Fix 7-Zip name TOOLS['SevenZip'].pop('64') From beb36dfc97a63f217d3919ec21ebed46f41696a3 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 7 Jan 2019 12:54:28 -0700 Subject: [PATCH 218/265] Adjusted window name --- .bin/Scripts/ddrescue-tui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bin/Scripts/ddrescue-tui b/.bin/Scripts/ddrescue-tui index d83b3a7e..e41c6bb1 100755 --- a/.bin/Scripts/ddrescue-tui +++ b/.bin/Scripts/ddrescue-tui @@ -3,7 +3,7 @@ ## Wizard Kit: ddrescue TUI Launcher SESSION_NAME="ddrescue-tui" -WINDOW_NAME="GNU ddrescue TUI" +WINDOW_NAME="ddrescue TUI" MENU="ddrescue-tui-menu" function ask() { From 4bd0cd1598b6403a8502493e753dbda6171f0eae Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 7 Jan 2019 15:29:33 -0700 Subject: [PATCH 219/265] Avoid crash when no sensor data available * This was broken when fixing issue #85 --- .bin/Scripts/functions/sensors.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.bin/Scripts/functions/sensors.py b/.bin/Scripts/functions/sensors.py index 22a27ef4..65a1b93e 100644 --- a/.bin/Scripts/functions/sensors.py +++ b/.bin/Scripts/functions/sensors.py @@ -112,20 +112,25 @@ def get_raw_sensor_data(): # Get raw data try: result = run_program(cmd) + result = result.stdout.decode().splitlines() except subprocess.CalledProcessError: - # Assuming no sensors available, return empty dict below - pass + # Assuming no sensors available, set to empty list + result = [] # Workaround for bad sensors raw_data = [] - for line in result.stdout.decode().splitlines(): + for line in result: if line.strip() == ',': # Assuming malformatted line caused by missing data continue raw_data.append(line) # Parse JSON data - json_data = json.loads('\n'.join(raw_data)) + try: + json_data = json.loads('\n'.join(raw_data)) + except json.JSONDecodeError: + # Still broken, just set to empty dict + json_data = {} # Done return json_data From 83e96f91359d8112584bc1dda71ff1d18af251ea Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 7 Jan 2019 16:13:24 -0700 Subject: [PATCH 220/265] Fix issue #38 --- .bin/Scripts/functions/osticket.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.bin/Scripts/functions/osticket.py b/.bin/Scripts/functions/osticket.py index ee26bca6..bc207b04 100644 --- a/.bin/Scripts/functions/osticket.py +++ b/.bin/Scripts/functions/osticket.py @@ -14,7 +14,7 @@ KNOWN_DEV_TYPES = ('CPU', 'Disk') # Regex REGEX_BLOCK_GRAPH = re.compile(r'(▁|▂|▃|▄|▅|▆|▇|█)') REGEX_NVME_SMART_ATTRIBUTES = re.compile(r'^\s*(\d+) / (\w+): (.{28})(.*)$') -REGEX_TEMPS = re.compile(r'^\s*(.*?)\s+(idle.*)$') +REGEX_TEMPS = re.compile(r'^\s*(.*?)\s+(idle:)(.*)$') REGEX_SENSOR = re.compile(r'^(.*?)(\s*)$') @@ -113,6 +113,7 @@ class osTicket(): if r: _sensor = '{:<20}'.format(r.group(1)) _temps = r.group(2) + _temps += re.sub(r'\s+(\w+:)', r' ...... \1', r.group(3)) r2 = REGEX_SENSOR.match(_sensor) _sensor = r2.group(1) _spacer = pad_with_dots(r2.group(2)) From f8adbe074d53fbdd7d4d558ea5983caacad3eb5f Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 7 Jan 2019 16:17:37 -0700 Subject: [PATCH 221/265] Added Linux headers for macbook12-spi-driver-dkms * Addresses issue #67 --- .linux_items/packages/live_add_min | 1 + 1 file changed, 1 insertion(+) diff --git a/.linux_items/packages/live_add_min b/.linux_items/packages/live_add_min index 85653460..b37bdc74 100644 --- a/.linux_items/packages/live_add_min +++ b/.linux_items/packages/live_add_min @@ -1 +1,2 @@ +linux-headers macbook12-spi-driver-dkms From 1e5f72f79af41d4d576dfc6a1bfd6ed561c1cedc Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 8 Jan 2019 15:02:56 -0700 Subject: [PATCH 222/265] Switched to PASS/FAIL instead of CS/NS by request --- .bin/Scripts/functions/common.py | 8 +++---- .bin/Scripts/functions/hw_diags.py | 34 +++++++++++++++--------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index 1aa1e1da..f5f3cb77 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -327,10 +327,10 @@ def major_exception(): # No log file or uploading disabled sleep(10) except: - print_error('Upload: NS') + print_error('Upload: Failed') sleep(10) else: - print_success('Upload: CS') + print_success('Upload: Complete') pause('Press Enter to exit...') exit_script(1) @@ -575,7 +575,7 @@ def get_exception(s): def try_and_print(message='Trying...', - function=None, cs='CS', ns='NS', other_results={}, + function=None, cs='SUCCESS', ns='FAILED', other_results={}, catch_all=True, print_return=False, silent_function=True, indent=8, width=32, *args, **kwargs): """Run function, print if successful or not, and return dict. @@ -661,7 +661,7 @@ def upload_crash_details(): headers={'X-Requested-With': 'XMLHttpRequest'}, auth=(CRASH_SERVER['User'], CRASH_SERVER['Pass']), verify=certificate_authority) - # Raise exception if upload NS + # Raise exception if upload failed if not r.ok: raise Exception else: diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index 5a434a38..7682f5cc 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -69,9 +69,9 @@ KEY_SMART = 'ata_smart_attributes' QUICK_LABEL = '{YELLOW}(Quick){CLEAR}'.format(**COLORS) SIDE_PANE_WIDTH = 20 STATUSES = { - 'RED': ['Denied', 'ERROR', 'NS', 'TimedOut'], + 'RED': ['Denied', 'ERROR', 'FAIL', 'TimedOut'], 'YELLOW': ['Aborted', 'N/A', 'OVERRIDE', 'Unknown', 'Working'], - 'GREEN': ['CS'], + 'GREEN': ['PASS'], } TESTS_CPU = ['Prime95'] TESTS_DISK = [ @@ -507,7 +507,7 @@ class DiskObj(): if not self.disk_ok: if 'NVMe / SMART' in self.tests: # NOTE: This will not overwrite the existing status if set - self.disable_test('NVMe / SMART', 'NS') + self.disable_test('NVMe / SMART', 'FAIL') if not self.tests['NVMe / SMART'].report: self.tests['NVMe / SMART'].report = self.generate_attribute_report() for t in ['badblocks', 'I/O Benchmark']: @@ -988,9 +988,9 @@ def run_badblocks_test(state, test): # Update status if test.failed: - test.update_status('NS') + test.update_status('FAIL') elif test.passed: - test.update_status('CS') + test.update_status('PASS') else: test.update_status('Unknown') @@ -1278,9 +1278,9 @@ def run_io_benchmark(state, test): # Update status if test.failed: - test.update_status('NS') + test.update_status('FAIL') elif test.passed: - test.update_status('CS') + test.update_status('PASS') elif not 'N/A' in test.status: test.update_status('Unknown') @@ -1431,7 +1431,7 @@ def run_mprime_test(state, test): line = line.strip() if re.search(r'(error|fail)', line, re.IGNORECASE): test.failed = True - test.update_status('NS') + test.update_status('FAIL') test.report.append( ' {YELLOW}{line}{CLEAR}'.format(line=line, **COLORS)) @@ -1455,10 +1455,10 @@ def run_mprime_test(state, test): # NS test.failed = True test.passed = False - test.update_status('NS') + test.update_status('FAIL') elif len(_tmp['Pass']) > 0 and not test.aborted: test.passed = True - test.update_status('CS') + test.update_status('PASS') for line in sorted(_tmp['Pass'].keys()): test.report.append(' {}'.format(line)) for line in sorted(_tmp['Warn'].keys()): @@ -1519,25 +1519,25 @@ def run_nvme_smart_tests(state, test): # NOTE: Pass/Fail is just the attribute check if test.dev.disk_ok: test.passed = True - test.update_status('CS') + test.update_status('PASS') else: # NOTE: Other test(s) should've been disabled by DiskObj.safety_check() test.failed = True - test.update_status('NS') + test.update_status('FAIL') # SMART elif test.dev.smart_attributes: # NOTE: Pass/Fail based on both attributes and SMART short self-test if not (test.dev.disk_ok or 'OVERRIDE' in test.status): test.failed = True - test.update_status('NS') + test.update_status('FAIL') elif state.quick_mode: if test.dev.disk_ok: test.passed = True - test.update_status('CS') + test.update_status('PASS') else: test.failed = True - test.update_status('NS') + test.update_status('FAIL') else: # Prep test.timeout = test.dev.smart_self_test['polling_minutes'].get( @@ -1604,10 +1604,10 @@ def run_nvme_smart_tests(state, test): if test.dev.smart_self_test['status'].get('passed', False): if 'OVERRIDE' not in test.status: test.passed = True - test.update_status('CS') + test.update_status('PASS') else: test.failed = True - test.update_status('NS') + test.update_status('FAIL') else: test.dev.smart_timeout = True test.update_status('TimedOut') From 23a88401b7e1f092d5fcf1c59cda03218ac7fef9 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 8 Jan 2019 15:11:34 -0700 Subject: [PATCH 223/265] Avoid rare crash --- .bin/Scripts/functions/common.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index f5f3cb77..d64e2e9f 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -102,7 +102,12 @@ def ask(prompt='Kotaero!'): answer = None prompt = '{} [Y/N]: '.format(prompt) while answer is None: - tmp = input(prompt) + try: + tmp = input(prompt) + except EOFError: + # Just try again? + sleep(1) + tmp = input(prompt) if re.search(r'^y(es|)$', tmp, re.IGNORECASE): answer = True elif re.search(r'^n(o|ope|)$', tmp, re.IGNORECASE): @@ -412,7 +417,12 @@ def non_clobber_rename(full_path): def pause(prompt='Press Enter to continue... '): """Simple pause implementation.""" - input(prompt) + try: + input(prompt) + except EOFError: + # Just try again? + sleep(1) + input(prompt) def ping(addr='google.com'): From c4575db44c5c32d3c1703dec5ff1dd2fa37239e1 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 8 Jan 2019 18:29:32 -0700 Subject: [PATCH 224/265] Missed a 'CS' --- .bin/Scripts/check_disk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bin/Scripts/check_disk.py b/.bin/Scripts/check_disk.py index 5b0f3c14..baee7460 100644 --- a/.bin/Scripts/check_disk.py +++ b/.bin/Scripts/check_disk.py @@ -38,7 +38,7 @@ if __name__ == '__main__': if repair: cs = 'Scheduled' else: - cs = 'CS' + cs = 'No issues' message = 'CHKDSK ({SYSTEMDRIVE})...'.format(**global_vars['Env']) try_and_print(message=message, function=run_chkdsk, cs=cs, other_results=other_results, repair=repair) From ed70d1ab1872c572191b2d0aa6a76fff31930a3c Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 8 Jan 2019 19:18:00 -0700 Subject: [PATCH 225/265] Simplified tmux repair thread handling * Just start once and let run until script is exited * Pretty sure this fixed the 100%+ CPU usage after returning to the menu --- .bin/Scripts/functions/hw_diags.py | 31 +++++++++++------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index e4f193f4..ecefa96c 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -581,6 +581,10 @@ class State(): if not skip_disk: self.disks.append(disk_obj) + # Start tmux thread + self.tmux_layout = TMUX_LAYOUT.copy() + start_thread(fix_tmux_panes_loop, args=[self]) + class TestObj(): """Object to track test data.""" @@ -657,9 +661,6 @@ def fix_tmux_panes_loop(state): try: fix_tmux_panes(state) sleep(1) - except AttributeError: - # tmux_layout attribute has been deleted, exit function - return except RuntimeError: # Assuming layout definitions changes mid-run, ignoring pass @@ -669,6 +670,10 @@ def fix_tmux_panes(state): """Fix pane sizes if the window has been resized.""" needs_fixed = False + # Bail? + if not state.panes: + return + # Check layout for k, v in state.tmux_layout.items(): if not v.get('Check'): @@ -1001,7 +1006,6 @@ def run_hw_tests(state): # Build Panes update_progress_pane(state) build_outer_panes(state) - start_tmux_repair_thread(state) # Show selected tests and create TestObj()s print_info('Selected Tests:') @@ -1049,13 +1053,13 @@ def run_hw_tests(state): v['Objects'][-1].update_status('N/A') except GenericAbort: # Cleanup - stop_tmux_repair_thread(state) tmux_kill_pane(*state.panes.values()) + state.panes.clear() + state.tmux_layout.pop('Current', None) # Rebuild panes update_progress_pane(state) build_outer_panes(state) - start_tmux_repair_thread(state) # Mark unfinished tests as aborted for k, v in state.tests.items(): @@ -1076,8 +1080,8 @@ def run_hw_tests(state): pause('Press Enter to return to main menu... ') # Cleanup - stop_tmux_repair_thread(state) tmux_kill_pane(*state.panes.values()) + state.panes.clear() def run_io_benchmark(state, test): @@ -1621,19 +1625,6 @@ def show_results(state): update_progress_pane(state) -def start_tmux_repair_thread(state): - """Fix tmux panes as long as state.tmux_layout attribute exists.""" - state.tmux_layout = TMUX_LAYOUT.copy() - start_thread(fix_tmux_panes_loop, args=[state]) - - -def stop_tmux_repair_thread(state): - """Stop previous thread by causing an AttributeError in the thread.""" - if hasattr(state, 'tmux_layout'): - del state.tmux_layout - sleep(1) - - def update_main_options(state, selection, main_options): """Update menu and state based on selection.""" index = int(selection) - 1 From ac259c9c37efca480eac65c23d13de72faaa27f1 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 8 Jan 2019 19:23:38 -0700 Subject: [PATCH 226/265] Revert "Avoid rare crash" This reverts commit 23a88401b7e1f092d5fcf1c59cda03218ac7fef9. * Didn't fix the issue, better fix available upstream --- .bin/Scripts/functions/common.py | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index d64e2e9f..f5f3cb77 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -102,12 +102,7 @@ def ask(prompt='Kotaero!'): answer = None prompt = '{} [Y/N]: '.format(prompt) while answer is None: - try: - tmp = input(prompt) - except EOFError: - # Just try again? - sleep(1) - tmp = input(prompt) + tmp = input(prompt) if re.search(r'^y(es|)$', tmp, re.IGNORECASE): answer = True elif re.search(r'^n(o|ope|)$', tmp, re.IGNORECASE): @@ -417,12 +412,7 @@ def non_clobber_rename(full_path): def pause(prompt='Press Enter to continue... '): """Simple pause implementation.""" - try: - input(prompt) - except EOFError: - # Just try again? - sleep(1) - input(prompt) + input(prompt) def ping(addr='google.com'): From 25833589633452647861c814030ebee1f5a85fbe Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 8 Jan 2019 19:34:17 -0700 Subject: [PATCH 227/265] Missed a call to stop_tmux_repair_thread() --- .bin/Scripts/functions/hw_diags.py | 1 - 1 file changed, 1 deletion(-) diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py index d11a694f..18446489 100644 --- a/.bin/Scripts/functions/hw_diags.py +++ b/.bin/Scripts/functions/hw_diags.py @@ -1140,7 +1140,6 @@ def run_hw_tests(state): # Cleanup state.ost.disconnect(full=True) - stop_tmux_repair_thread(state) tmux_kill_pane(*state.panes.values()) state.panes.clear() From 187421a29190595ef6d02fbb38672c93f7c0eab9 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 8 Jan 2019 19:52:33 -0700 Subject: [PATCH 228/265] Fixed upload_crash_details() under Linux --- .bin/Scripts/functions/common.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index f5f3cb77..9e266332 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -644,6 +644,9 @@ def upload_crash_details(): with open(global_vars['LogFile']) as f: certificate_authority = r'{}\{}'.format( global_vars['BinDir'], ROOT_CA_NAME) + if psutil.LINUX: + # Use system certificates + certificate_authority = True data = '{}\n'.format(f.read()) data += '#############################\n' data += 'Runtime Details:\n\n' From 63f9c1c193f1dd93933d61fc32d822b9541ce40d Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 8 Jan 2019 20:24:14 -0700 Subject: [PATCH 229/265] Fixed set_log_file() under Linux --- .bin/Scripts/functions/common.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index f0315aff..76a273b8 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -873,8 +873,14 @@ def set_linux_vars(): def set_log_file(log_name): """Sets global var LogFile and creates path as needed.""" - folder_path = r'{}\{}'.format(global_vars['LogDir'], KIT_NAME_FULL) - log_file = r'{}\{}'.format(folder_path, log_name) + folder_path = '{}{}{}'.format( + global_vars['LogDir'], + os.sep, + KIT_NAME_FULL) + log_file = '{}{}{}'.format( + folder_path, + os.sep, + log_name) os.makedirs(folder_path, exist_ok=True) global_vars['LogFile'] = log_file From 6ea4791dc9aac77d68f4020710aad53dce57b630 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 8 Jan 2019 20:24:43 -0700 Subject: [PATCH 230/265] Added generate_global_vars_report() * Makes crash reports more readable --- .bin/Scripts/functions/common.py | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index 76a273b8..04af1d87 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -646,7 +646,10 @@ def upload_crash_details(): data += '#############################\n' data += 'Runtime Details:\n\n' data += 'sys.argv: {}\n\n'.format(sys.argv) - data += 'global_vars: {}\n'.format(global_vars) + try: + data += generate_global_vars_report() + except Exception: + data += 'global_vars: {}\n'.format(global_vars) filename = global_vars.get('LogFile', 'Unknown') filename = re.sub(r'.*(\\|/)', '', filename) filename += '.txt' @@ -821,6 +824,32 @@ def find_bin(): global_vars['BaseDir'] = base +def generate_global_vars_report(): + """Build readable string from global_vars, returns str.""" + report = ['global_vars: {'] + for k, v in sorted(global_vars.items()): + if k == 'Env': + continue + if isinstance(v, list): + report.append(' {}:'.format(str(k))) + for item in v: + report.append(' {}'.format(str(v))) + elif isinstance(v, dict): + report.append(' {}:'.format(str(k))) + for item_k, item_v in sorted(v.items()): + report.append(' {:<15} {}'.format( + str(item_k)+':', str(item_v))) + else: + report.append(' {:<18}{}'.format(str(k)+':', str(v))) + report.append(' Env:') + for k, v in sorted(global_vars.get('Env', {}).items()): + report.append(' {:<15} {}'.format( + str(k)+':', str(v))) + report.append('}') + + return '\n'.join(report) + + def make_tmp_dirs(): """Make temp directories.""" os.makedirs(global_vars['BackupDir'], exist_ok=True) From f2bd2a6e7509dd5b43f3a7e76b8c4d004be9ddce Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 8 Jan 2019 20:33:23 -0700 Subject: [PATCH 231/265] Adjusted global_vars report --- .bin/Scripts/functions/common.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index 04af1d87..2bbb4291 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -831,14 +831,16 @@ def generate_global_vars_report(): if k == 'Env': continue if isinstance(v, list): - report.append(' {}:'.format(str(k))) + report.append(' {}: ['.format(str(k))) for item in v: report.append(' {}'.format(str(v))) + report.append(' ]') elif isinstance(v, dict): - report.append(' {}:'.format(str(k))) + report.append(' {}: {{'.format(str(k))) for item_k, item_v in sorted(v.items()): report.append(' {:<15} {}'.format( str(item_k)+':', str(item_v))) + report.append(' }') else: report.append(' {:<18}{}'.format(str(k)+':', str(v))) report.append(' Env:') From 990037e6c12f6f172465a9dae27d71cb3ce49538 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 8 Jan 2019 20:53:32 -0700 Subject: [PATCH 232/265] Added windows_updates.py --- .bin/Scripts/functions/windows_updates.py | 58 +++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 .bin/Scripts/functions/windows_updates.py diff --git a/.bin/Scripts/functions/windows_updates.py b/.bin/Scripts/functions/windows_updates.py new file mode 100644 index 00000000..07da565b --- /dev/null +++ b/.bin/Scripts/functions/windows_updates.py @@ -0,0 +1,58 @@ +# Wizard Kit: Functions - Windows updates + +from functions.common import * + + +# STATIC VARIABLES +UPDATE_FOLDERS = [ + r'{WINDIR}\SoftwareDistribution'.format(**global_vars['Env']), + r'{SYSTEMDRIVE}\$WINDOWS.~BT'.format(**global_vars['Env']), +] + + +# Functions +def disable_service(service_name): + """Set service startup to disabled.""" + run_program(['sc', 'config', service_name, 'start=', 'disabled']) + + +def disable_windows_updates(): + """Disable windows updates and clear SoftwareDistribution folder.""" + # Stop Windows update service + stop_service('wuauserv') + disable_service('wuauserv') + + # Stop Background Intelligent Transfer Service + try: + stop_service('bits') + disable_service('bits') + except Exception: + # Going to ignore these errors + pass + + # Delete update folders + for folder_path in UPDATE_FOLDERS: + if os.path.exists(folder_path): + shutil.rmtree(folder_path) + + +def enable_service(service_name): + """Set service startup to enabled.""" + run_program(['sc', 'config', service_name, 'start=', 'automatic']) + + +def enable_windows_updates(): + """Enable windows updates""" + enable_service('bits') + enable_service('wuauserv') + + +def stop_service(service_name): + """Stop service.""" + run_program(['sc', 'stop', service_name]) + + +if __name__ == '__main__': + print("This file is not meant to be called directly.") + +# vim: sts=2 sw=2 ts=2 From 8fef0a8e2f4c12a1a67adbaf2f8c84a5055ba1ef Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 8 Jan 2019 21:34:24 -0700 Subject: [PATCH 233/265] Added windows_updates.py --- .bin/Scripts/settings/launchers.py | 14 +++++++++ .bin/Scripts/windows_updates.py | 48 ++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 .bin/Scripts/windows_updates.py diff --git a/.bin/Scripts/settings/launchers.py b/.bin/Scripts/settings/launchers.py index a1f29683..ae5db2e3 100644 --- a/.bin/Scripts/settings/launchers.py +++ b/.bin/Scripts/settings/launchers.py @@ -77,6 +77,20 @@ LAUNCHERS = { 'L_ITEM': 'user_checklist.py', 'L_ARGS': 'd7mode', }, + 'Disable Windows Updates': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'windows_updates.py', + 'L_ARGS': '--disable', + 'L_ELEV': 'True', + }, + 'Enable Windows Updates': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'windows_updates.py', + 'L_ARGS': '--enable', + 'L_ELEV': 'True', + }, }, r'Data Recovery': { 'PhotoRec (CLI)': { diff --git a/.bin/Scripts/windows_updates.py b/.bin/Scripts/windows_updates.py new file mode 100644 index 00000000..53ab7172 --- /dev/null +++ b/.bin/Scripts/windows_updates.py @@ -0,0 +1,48 @@ +# Wizard Kit: Windows updates + +import os +import sys + +# Init +sys.path.append(os.path.dirname(os.path.realpath(__file__))) +from functions.windows_updates import * +init_global_vars() +os.system('title {}: Windows Updates Tool'.format(KIT_NAME_FULL)) +set_log_file('Windows Updates Tool.log') + +if __name__ == '__main__': + try: + clear_screen() + print_info('{}: Windows Updates Tool\n'.format(KIT_NAME_FULL)) + + # Check args + if '--disable' in sys.argv: + result = try_and_print( + message='Disabling Windows Updates...', + function=disable_windows_updates) + elif '--enable' in sys.argv: + result = try_and_print( + message='Enabling Windows Updates...', + function=enable_windows_updates) + else: + print_error('Bad mode.') + abort() + + # Check for errors + if not result['CS']: + for line in str(result['Error']).splitlines(): + print_standard(line) + print_standard(' ') + print_error('Error(s) encountered, see above.') + print_standard(' ') + pause('Press Enter to exit... ') + exit_script(1) + + # Done + exit_script() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 From 827981d178b3ec6f7e5049d440cb25f4eacd79f5 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 8 Jan 2019 21:58:08 -0700 Subject: [PATCH 234/265] Wait for service to stop --- .bin/Scripts/functions/windows_updates.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bin/Scripts/functions/windows_updates.py b/.bin/Scripts/functions/windows_updates.py index 07da565b..2504fdfc 100644 --- a/.bin/Scripts/functions/windows_updates.py +++ b/.bin/Scripts/functions/windows_updates.py @@ -49,7 +49,7 @@ def enable_windows_updates(): def stop_service(service_name): """Stop service.""" - run_program(['sc', 'stop', service_name]) + run_program(['net', 'stop', service_name]) if __name__ == '__main__': From 931ce84d67abd96c8558a4aa3ae27a174e7017c7 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 8 Jan 2019 22:05:16 -0700 Subject: [PATCH 235/265] Added Windows Updates items to d7II * NOTE: Still need added to default profile --- .../CustomApps/Disable Windows Updates.cfg | 34 +++++++++++++++++++ .../CustomApps/Enable Windows Updates.cfg | 34 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 .bin/d7ii/Config/CustomApps/Disable Windows Updates.cfg create mode 100644 .bin/d7ii/Config/CustomApps/Enable Windows Updates.cfg diff --git a/.bin/d7ii/Config/CustomApps/Disable Windows Updates.cfg b/.bin/d7ii/Config/CustomApps/Disable Windows Updates.cfg new file mode 100644 index 00000000..8b47cecc --- /dev/null +++ b/.bin/d7ii/Config/CustomApps/Disable Windows Updates.cfg @@ -0,0 +1,34 @@ +[Config] +LastEditDate=8/30/2018 10:49:46 AM +PostRunApp= +AppParms=.bin\Scripts\launchers_for_d7\Disable Windows Updates.cmd +UseFTPServer=0 +AlwaysAttemptDownload=0 +DLafterXdays=5 +AppWait=1 +EmailBeforeExecution=0 +PriorAlert=0 +ServiceWait=0 +AppMsgBox=1 +AppRandomize=0 +SaveConfigAfter=0 +MoveSnatchReports=0 +SnatchReportsToMalwareLogs=1 +RunInCMD=0 +SendEnter=0 +RunWithSystemAccess=0 +IsDLInstaller=0 +32=1 +64=1 +XP=1 +Vista=1 +7=1 +8=1 +Servers=1 +NonDirectURLs=0 +App=WizardKit Launcher.cmd +AutoFlag=0 +WaitOnProcesses=ConEmu.exe;ConEmuC.exe;ConEmu64.exe;ConEmuC64.exe;python.exe +AppDesc=Disable Windows Updates +LogVerbiage=Disable Windows Update services and delete update folders +AppWaitTime=30 diff --git a/.bin/d7ii/Config/CustomApps/Enable Windows Updates.cfg b/.bin/d7ii/Config/CustomApps/Enable Windows Updates.cfg new file mode 100644 index 00000000..bedccff7 --- /dev/null +++ b/.bin/d7ii/Config/CustomApps/Enable Windows Updates.cfg @@ -0,0 +1,34 @@ +[Config] +LastEditDate=8/30/2018 10:49:46 AM +PostRunApp= +AppParms=.bin\Scripts\launchers_for_d7\Enable Windows Updates.cmd +UseFTPServer=0 +AlwaysAttemptDownload=0 +DLafterXdays=5 +AppWait=1 +EmailBeforeExecution=0 +PriorAlert=0 +ServiceWait=0 +AppMsgBox=1 +AppRandomize=0 +SaveConfigAfter=0 +MoveSnatchReports=0 +SnatchReportsToMalwareLogs=1 +RunInCMD=0 +SendEnter=0 +RunWithSystemAccess=0 +IsDLInstaller=0 +32=1 +64=1 +XP=1 +Vista=1 +7=1 +8=1 +Servers=1 +NonDirectURLs=0 +App=WizardKit Launcher.cmd +AutoFlag=0 +WaitOnProcesses=ConEmu.exe;ConEmuC.exe;ConEmu64.exe;ConEmuC64.exe;python.exe +AppDesc=Enable Windows Updates +LogVerbiage=Enable Windows Update services +AppWaitTime=30 From 6068b4390a85ff4f8f5df14d67d12a9f2fbbdcee Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 8 Jan 2019 22:05:57 -0700 Subject: [PATCH 236/265] Create Restore Point during system checklists * Fixes issue #31 --- .bin/Scripts/functions/setup.py | 10 ++++++++++ .bin/Scripts/system_checklist.py | 2 ++ .bin/Scripts/system_checklist_hw.py | 2 ++ 3 files changed, 14 insertions(+) diff --git a/.bin/Scripts/functions/setup.py b/.bin/Scripts/functions/setup.py index 7ca76b52..908bd2db 100644 --- a/.bin/Scripts/functions/setup.py +++ b/.bin/Scripts/functions/setup.py @@ -208,6 +208,16 @@ def config_explorer_user(): write_registry_settings(SETTINGS_EXPLORER_USER, all_users=False) +def create_system_restore_point(): + """Create system restore point.""" + cmd = [ + 'PowerShell', + '-Command', 'Checkpoint-Computer', + '-Description', '1201 Checklist', + ] + run_program(cmd) + + def disable_windows_telemetry(): """Disable Windows 10 telemetry settings with O&O ShutUp10.""" extract_item('ShutUp10', silent=True) diff --git a/.bin/Scripts/system_checklist.py b/.bin/Scripts/system_checklist.py index a4ed9893..585a5e10 100644 --- a/.bin/Scripts/system_checklist.py +++ b/.bin/Scripts/system_checklist.py @@ -50,6 +50,8 @@ if __name__ == '__main__': function=enable_regback, cs='Done') try_and_print(message='Enabling System Restore...', function=enable_system_restore, cs='Done') + try_and_print(message='Create System Restore point...', + function=create_system_restore_point, cs='Done') try_and_print(message='Updating Clock...', function=update_clock, cs='Done') diff --git a/.bin/Scripts/system_checklist_hw.py b/.bin/Scripts/system_checklist_hw.py index bac5f2dd..aa918796 100644 --- a/.bin/Scripts/system_checklist_hw.py +++ b/.bin/Scripts/system_checklist_hw.py @@ -46,6 +46,8 @@ if __name__ == '__main__': function=enable_regback, cs='Done') try_and_print(message='Enabling System Restore...', function=enable_system_restore, cs='Done') + try_and_print(message='Create System Restore point...', + function=create_system_restore_point, cs='Done') # Export system info print_info('Backup System Information') From f20d8b5af3649625dfb2fb70bb588984a7b1adfd Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 8 Jan 2019 22:13:51 -0700 Subject: [PATCH 237/265] Enable BSoD mini dumps during system checklists * Fixes issue #33 --- .bin/Scripts/functions/setup.py | 7 +++++++ .bin/Scripts/system_checklist.py | 2 ++ .bin/Scripts/system_checklist_hw.py | 2 ++ 3 files changed, 11 insertions(+) diff --git a/.bin/Scripts/functions/setup.py b/.bin/Scripts/functions/setup.py index 908bd2db..2edfab41 100644 --- a/.bin/Scripts/functions/setup.py +++ b/.bin/Scripts/functions/setup.py @@ -232,6 +232,13 @@ def enable_regback(): """Enable RegBack.""" write_registry_settings(SETTINGS_REGBACK, all_users=True) + +def enable_mini_dumps(): + """Configure Windows to save mini dumps during BSoDs.""" + cmd = ['wmic', 'RECOVEROS', 'set', 'DebugInfoType', '=', '3'] + run_program(cmd) + + def enable_system_restore(): """Enable System Restore and set disk usage to 5%""" cmd = [ diff --git a/.bin/Scripts/system_checklist.py b/.bin/Scripts/system_checklist.py index 585a5e10..cbcde87e 100644 --- a/.bin/Scripts/system_checklist.py +++ b/.bin/Scripts/system_checklist.py @@ -48,6 +48,8 @@ if __name__ == '__main__': function=disable_windows_telemetry, cs='Done') try_and_print(message='Enabling RegBack...', function=enable_regback, cs='Done') + try_and_print(message='Enabling BSoD mini dumps...', + function=enable_mini_dumps, cs='Done') try_and_print(message='Enabling System Restore...', function=enable_system_restore, cs='Done') try_and_print(message='Create System Restore point...', diff --git a/.bin/Scripts/system_checklist_hw.py b/.bin/Scripts/system_checklist_hw.py index aa918796..fd08fe10 100644 --- a/.bin/Scripts/system_checklist_hw.py +++ b/.bin/Scripts/system_checklist_hw.py @@ -44,6 +44,8 @@ if __name__ == '__main__': if global_vars['OS']['Version'] == '10': try_and_print(message='Enabling RegBack...', function=enable_regback, cs='Done') + try_and_print(message='Enabling BSoD mini dumps...', + function=enable_mini_dumps, cs='Done') try_and_print(message='Enabling System Restore...', function=enable_system_restore, cs='Done') try_and_print(message='Create System Restore point...', From e088ba134ef00c5085ce9b89174822e16f4dd2c3 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 8 Jan 2019 23:48:50 -0700 Subject: [PATCH 238/265] Tool version bumps --- .bin/Scripts/build_kit.ps1 | 10 ++++---- .bin/Scripts/build_pe.ps1 | 20 ++++++++-------- .bin/Scripts/settings/launchers.py | 4 ++-- .bin/Scripts/settings/sources.py | 38 ++++++++++++++++-------------- 4 files changed, 37 insertions(+), 35 deletions(-) diff --git a/.bin/Scripts/build_kit.ps1 b/.bin/Scripts/build_kit.ps1 index bd213578..08a050c9 100644 --- a/.bin/Scripts/build_kit.ps1 +++ b/.bin/Scripts/build_kit.ps1 @@ -79,21 +79,21 @@ if ($MyInvocation.InvocationName -ne ".") { $Path = $Temp # 7-Zip - DownloadFile -Path $Path -Name "7z-installer.msi" -Url "https://www.7-zip.org/a/7z1805.msi" - DownloadFile -Path $Path -Name "7z-extra.7z" -Url "https://www.7-zip.org/a/7z1805-extra.7z" + DownloadFile -Path $Path -Name "7z-installer.msi" -Url "https://www.7-zip.org/a/7z1806.msi" + DownloadFile -Path $Path -Name "7z-extra.7z" -Url "https://www.7-zip.org/a/7z1806-extra.7z" # ConEmu $Url = "https://github.com/Maximus5/ConEmu/releases/download/v18.06.26/ConEmuPack.180626.7z" DownloadFile -Path $Path -Name "ConEmuPack.7z" -Url $Url # Notepad++ - $Url = "https://notepad-plus-plus.org/repository/7.x/7.5.8/npp.7.5.8.bin.minimalist.7z" + $Url = "https://notepad-plus-plus.org/repository/7.x/7.6.2/npp.7.6.2.bin.minimalist.7z" DownloadFile -Path $Path -Name "npp.7z" -Url $Url # Python - $Url = "https://www.python.org/ftp/python/3.7.0/python-3.7.0-embed-win32.zip" + $Url = "https://www.python.org/ftp/python/3.7.2/python-3.7.2.post1-embed-win32.zip" DownloadFile -Path $Path -Name "python32.zip" -Url $Url - $Url = "https://www.python.org/ftp/python/3.7.0/python-3.7.0-embed-amd64.zip" + $Url = "https://www.python.org/ftp/python/3.7.2/python-3.7.2.post1-embed-amd64.zip" DownloadFile -Path $Path -Name "python64.zip" -Url $Url # Python: psutil diff --git a/.bin/Scripts/build_pe.ps1 b/.bin/Scripts/build_pe.ps1 index 560d570d..a2dd0363 100644 --- a/.bin/Scripts/build_pe.ps1 +++ b/.bin/Scripts/build_pe.ps1 @@ -131,25 +131,25 @@ if ($MyInvocation.InvocationName -ne ".") { ## Download Tools ## $ToolSources = @( # 7-Zip - @("7z-installer.msi", "https://www.7-zip.org/a/7z1805.msi"), - @("7z-extra.7z", "https://www.7-zip.org/a/7z1805-extra.7z"), + @("7z-installer.msi", "https://www.7-zip.org/a/7z1806.msi"), + @("7z-extra.7z", "https://www.7-zip.org/a/7z1806-extra.7z"), # Blue Screen View @("bluescreenview32.zip", "http://www.nirsoft.net/utils/bluescreenview.zip"), @("bluescreenview64.zip", "http://www.nirsoft.net/utils/bluescreenview-x64.zip"), # ConEmu @("ConEmuPack.7z", "https://github.com/Maximus5/ConEmu/releases/download/v18.06.26/ConEmuPack.180626.7z"), # Fast Copy - @("fastcopy.zip", "http://ftp.vector.co.jp/70/64/2323/FastCopy354_installer.zip"), + @("fastcopy.zip", "http://ftp.vector.co.jp/70/93/2323/FastCopy361_installer.exe"), # HWiNFO - @("hwinfo.zip", "http://app.oldfoss.com:81/download/HWiNFO/hwi_588.zip"), + @("hwinfo.zip", "https://www.fosshub.com/HWiNFO.html?dwl=hwi_600.zip"), # Killer Network Drivers @( "killerinf.zip", ("http://www.killernetworking.com"+(FindDynamicUrl "http://www.killernetworking.com/driver-downloads/item/killer-drivers-inf" "Download Killer-Ethernet").replace('&', '&')) ), # Notepad++ - @("npp_x86.7z", "https://notepad-plus-plus.org/repository/7.x/7.5.8/npp.7.5.8.bin.minimalist.7z"), - @("npp_amd64.7z", "https://notepad-plus-plus.org/repository/7.x/7.5.8/npp.7.5.8.bin.minimalist.x64.7z"), + @("npp_x86.7z", "https://notepad-plus-plus.org/repository/7.x/7.6.2/npp.7.6.2.bin.minimalist.7z"), + @("npp_amd64.7z", "https://notepad-plus-plus.org/repository/7.x/7.6.2/npp.7.6.2.bin.minimalist.x64.7z"), # NT Password Editor @("ntpwed.zip", "http://cdslow.org.ru/files/ntpwedit/ntpwed07.zip"), # Prime95 @@ -159,8 +159,8 @@ if ($MyInvocation.InvocationName -ne ".") { @("produkey32.zip", "http://www.nirsoft.net/utils/produkey.zip"), @("produkey64.zip", "http://www.nirsoft.net/utils/produkey-x64.zip"), # Python - @("python32.zip", "https://www.python.org/ftp/python/3.7.0/python-3.7.0-embed-win32.zip"), - @("python64.zip", "https://www.python.org/ftp/python/3.7.0/python-3.7.0-embed-amd64.zip"), + @("python32.zip", "https://www.python.org/ftp/python/3.7.2/python-3.7.2.post1-embed-win32.zip"), + @("python64.zip", "https://www.python.org/ftp/python/3.7.2/python-3.7.2.post1-embed-amd64.zip"), # Python: psutil @( "psutil64.whl", @@ -182,8 +182,8 @@ if ($MyInvocation.InvocationName -ne ".") { @("vcredist_x86.exe", "https://aka.ms/vs/15/release/vc_redist.x86.exe"), @("vcredist_x64.exe", "https://aka.ms/vs/15/release/vc_redist.x64.exe"), # wimlib-imagex - @("wimlib32.zip", "https://wimlib.net/downloads/wimlib-1.12.0-windows-i686-bin.zip"), - @("wimlib64.zip", "https://wimlib.net/downloads/wimlib-1.12.0-windows-x86_64-bin.zip") + @("wimlib32.zip", "https://wimlib.net/downloads/wimlib-1.13.0-windows-i686-bin.zip"), + @("wimlib64.zip", "https://wimlib.net/downloads/wimlib-1.13.0-windows-x86_64-bin.zip") ) foreach ($Tool in $ToolSources) { DownloadFile -Path $Temp -Name $Tool[0] -Url $Tool[1] diff --git a/.bin/Scripts/settings/launchers.py b/.bin/Scripts/settings/launchers.py index 3b378aca..0456376d 100644 --- a/.bin/Scripts/settings/launchers.py +++ b/.bin/Scripts/settings/launchers.py @@ -282,8 +282,8 @@ LAUNCHERS = { 'Intel RST (Current Release)': { 'L_TYPE': 'Executable', 'L_PATH': '_Drivers\Intel RST', - 'L_ITEM': 'SetupRST_16.5.exe', - 'L_7ZIP': 'SetupRST_16.5.exe', + 'L_ITEM': 'SetupRST_16.8.exe', + 'L_7ZIP': 'SetupRST_16.8.exe', }, 'Intel RST (Previous Releases)': { 'L_TYPE': 'Folder', diff --git a/.bin/Scripts/settings/sources.py b/.bin/Scripts/settings/sources.py index 9a57e8f7..2644d4b6 100644 --- a/.bin/Scripts/settings/sources.py +++ b/.bin/Scripts/settings/sources.py @@ -1,9 +1,9 @@ # Wizard Kit: Settings - Sources SOURCE_URLS = { - 'Adobe Reader DC': 'http://ardownload.adobe.com/pub/adobe/reader/win/AcrobatDC/1801120058/AcroRdrDC1801120058_en_US.exe', + 'Adobe Reader DC': 'http://ardownload.adobe.com/pub/adobe/reader/win/AcrobatDC/1901020069/AcroRdrDC1901020069_en_US.exe', 'AdwCleaner': 'https://downloads.malwarebytes.com/file/adwcleaner', - 'AIDA64': 'http://download.aida64.com/aida64engineer597.zip', + 'AIDA64': 'http://download.aida64.com/aida64engineer599.zip', 'aria2': 'https://github.com/aria2/aria2/releases/download/release-1.34.0/aria2-1.34.0-win-32bit-build1.zip', 'Autoruns': 'https://download.sysinternals.com/files/Autoruns.zip', 'BleachBit': 'https://download.bleachbit.org/BleachBit-2.0-portable.zip', @@ -13,32 +13,32 @@ SOURCE_URLS = { 'ClassicStartSkin': 'http://www.classicshell.net/forum/download/file.php?id=3001&sid=9a195960d98fd754867dcb63d9315335', 'Du': 'https://download.sysinternals.com/files/DU.zip', 'ERUNT': 'http://www.aumha.org/downloads/erunt.zip', - 'Everything32': 'https://www.voidtools.com/Everything-1.4.1.895.x86.zip', - 'Everything64': 'https://www.voidtools.com/Everything-1.4.1.895.x64.zip', - 'FastCopy': 'http://ftp.vector.co.jp/70/64/2323/FastCopy354_installer.zip', - 'Firefox uBO': 'https://addons.mozilla.org/firefox/downloads/file/1056733/ublock_origin-1.16.20-an+fx.xpi', + 'Everything32': 'https://www.voidtools.com/Everything-1.4.1.924.x86.zip', + 'Everything64': 'https://www.voidtools.com/Everything-1.4.1.924.x64.zip', + 'FastCopy': 'http://ftp.vector.co.jp/70/93/2323/FastCopy361_installer.exe', + 'Firefox uBO': 'https://addons.mozilla.org/firefox/downloads/file/1166954/ublock_origin-1.17.4-an+fx.xpi', 'HitmanPro32': 'https://dl.surfright.nl/HitmanPro.exe', 'HitmanPro64': 'https://dl.surfright.nl/HitmanPro_x64.exe', - 'HWiNFO': 'http://app.oldfoss.com:81/download/HWiNFO/hwi_588.zip', - 'Intel SSD Toolbox': r'https://downloadmirror.intel.com/27656/eng/Intel%20SSD%20Toolbox%20-%20v3.5.2.exe', + 'HWiNFO': 'https://www.fosshub.com/HWiNFO.html?dwl=hwi_600.zip', + 'Intel SSD Toolbox': r'https://downloadmirror.intel.com/28447/eng/Intel%20SSD%20Toolbox%20-%20v3.5.8.exe', 'IOBit_Uninstaller': 'https://portableapps.duckduckgo.com/IObitUninstallerPortable_7.5.0.7.paf.exe', 'KVRT': 'http://devbuilds.kaspersky-labs.com/devbuilds/KVRT/latest/full/KVRT.exe', 'Macs Fan Control': 'https://www.crystalidea.com/downloads/macsfancontrol_setup.exe', 'NirCmd32': 'https://www.nirsoft.net/utils/nircmd.zip', 'NirCmd64': 'https://www.nirsoft.net/utils/nircmd-x64.zip', - 'NotepadPlusPlus': 'https://notepad-plus-plus.org/repository/7.x/7.5.8/npp.7.5.8.bin.minimalist.7z', + 'NotepadPlusPlus': 'https://notepad-plus-plus.org/repository/7.x/7.6.2/npp.7.6.2.bin.minimalist.7z', 'Office Deployment Tool 2016': 'https://download.microsoft.com/download/2/7/A/27AF1BE6-DD20-4CB4-B154-EBAB8A7D4A7E/officedeploymenttool_10810.33603.exe', 'ProduKey32': 'http://www.nirsoft.net/utils/produkey.zip', 'ProduKey64': 'http://www.nirsoft.net/utils/produkey-x64.zip', - 'PuTTY': 'https://the.earth.li/ sgtatham/putty/latest/w32/putty.zip', + 'PuTTY': 'https://the.earth.li/~sgtatham/putty/latest/w32/putty.zip', 'RKill': 'https://www.bleepingcomputer.com/download/rkill/dl/10/', - 'Samsung Magician': 'https://s3.ap-northeast-2.amazonaws.com/global.semi.static/SAMSUNG_SSD_v5_2_1_180523/CD0CFAC4675B9E502899B41BE00525C3909ECE3AD57CC1A2FB6B74A766B2A1EA/Samsung_Magician_Installer.zip', + 'Samsung Magician': 'https://s3.ap-northeast-2.amazonaws.com/global.semi.static/SAMSUNG_SSD_v5_3_0_181121/CD0C7CC1BE00525FAC4675B9E502899B41D5C3909ECE3AA2FB6B74A766B2A1EA/Samsung_Magician_Installer.zip', 'SDIO Themes': 'http://snappy-driver-installer.org/downloads/SDIO_Themes.zip', 'SDIO Torrent': 'http://snappy-driver-installer.org/downloads/SDIO_Update.torrent', 'TDSSKiller': 'https://media.kaspersky.com/utilities/VirusUtilities/EN/tdsskiller.exe', 'TestDisk': 'https://www.cgsecurity.org/testdisk-7.1-WIP.win.zip', - 'wimlib32': 'https://wimlib.net/downloads/wimlib-1.12.0-windows-i686-bin.zip', - 'wimlib64': 'https://wimlib.net/downloads/wimlib-1.12.0-windows-x86_64-bin.zip', + 'wimlib32': 'https://wimlib.net/downloads/wimlib-1.13.0-windows-i686-bin.zip', + 'wimlib64': 'https://wimlib.net/downloads/wimlib-1.13.0-windows-x86_64-bin.zip', 'Winapp2': 'https://github.com/MoscaDotTo/Winapp2/archive/master.zip', 'WizTree': 'https://antibody-software.com/files/wiztree_3_26_portable.zip', 'XMPlay 7z': 'https://support.xmplay.com/files/16/xmp-7z.zip?v=800962', @@ -172,7 +172,7 @@ NINITE_SOURCES = { 'Launchy.exe': 'launchy', 'RealVNC.exe': 'realvnc', 'Revo Uninstaller.exe': 'revo', - 'TeamViewer 13.exe': 'teamviewer13', + 'TeamViewer 14.exe': 'teamviewer14', 'TeraCopy.exe': 'teracopy', 'WinDirStat.exe': 'windirstat', }, @@ -191,12 +191,14 @@ RST_SOURCES = { 'SetupRST_14.0.exe': 'https://downloadmirror.intel.com/25091/eng/SetupRST.exe', 'SetupRST_14.8.exe': 'https://downloadmirror.intel.com/26759/eng/setuprst.exe', 'SetupRST_15.8.exe': 'https://downloadmirror.intel.com/27442/eng/SetupRST.exe', - 'SetupRST_15.9.exe': 'https://downloadmirror.intel.com/27400/eng/SetupRST.exe', - 'SetupRST_16.0.exe': 'https://downloadmirror.intel.com/27681/eng/SetupRST.exe', - 'SetupRST_16.5.exe': 'https://downloadmirror.intel.com/27984/eng/SetupRST.exe', + #SetupRST_15.9.exe : Deprecated by Intel + #SetupRST_16.0.exe : Deprecated by Intel + #SetupRST_16.5.exe : Deprecated by Intel + #SetupRST_16.7.exe : Deprecated by Intel + 'SetupRST_16.8.exe': 'https://downloadmirror.intel.com/28400/eng/SetupRST.exe', } if __name__ == '__main__': print("This file is not meant to be called directly.") -# vim: sts=2 sw=2 ts=2 +# vim: sts=2 sw=2 ts=2 tw=0 From 6488101cdc3ac21c724ca5f723452d6dc9833268 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 9 Jan 2019 16:29:18 -0700 Subject: [PATCH 239/265] Dumb workaround for Dell sensors --- .bin/Scripts/functions/sensors.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.bin/Scripts/functions/sensors.py b/.bin/Scripts/functions/sensors.py index 65a1b93e..5d2f2fae 100644 --- a/.bin/Scripts/functions/sensors.py +++ b/.bin/Scripts/functions/sensors.py @@ -220,11 +220,15 @@ def update_sensor_data(sensor_data): for _section, _adapters in sensor_data.items(): for _adapter, _sources in _adapters.items(): for _source, _data in _sources.items(): - _label = _data['Label'] - _temp = json_data[_adapter][_source][_label] - _data['Current'] = _temp - _data['Max'] = max(_temp, _data['Max']) - _data['Temps'].append(_temp) + try: + _label = _data['Label'] + _temp = json_data[_adapter][_source][_label] + _data['Current'] = _temp + _data['Max'] = max(_temp, _data['Max']) + _data['Temps'].append(_temp) + except Exception: + # Dumb workound for Dell sensors with changing source names + pass def join_columns(column1, column2, width=55): From af46962fd76c687505fc271ccda00397caabc118 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 9 Jan 2019 17:10:05 -0700 Subject: [PATCH 240/265] Finished adding Windows Updates Tool to d7II --- .bin/d7ii/Config/Profiles/Default.cfg | 2 ++ .bin/d7ii/Config/SortOrder/MalwareBox2.cfg | 2 +- .bin/d7ii/Config/SortOrder/MalwareBox3.cfg | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.bin/d7ii/Config/Profiles/Default.cfg b/.bin/d7ii/Config/Profiles/Default.cfg index ed1be24b..5f743dae 100644 --- a/.bin/d7ii/Config/Profiles/Default.cfg +++ b/.bin/d7ii/Config/Profiles/Default.cfg @@ -781,6 +781,7 @@ Windows Repair AIO (Auto)=0 WizardKit System Diagnostics=1 1=1 RKill (Auto)=1 +Disable Windows Updates=1 [Malware3] ComboFix=0 ComboFix (Uninstall)=0 @@ -830,6 +831,7 @@ WizardKit User Checklist=1 WizardKit System Checklist=1 WizardKit Browser Reset=0 Malwarebytes Download=1 +Enable Windows Updates=1 [Repair2] 49=0 48=0 diff --git a/.bin/d7ii/Config/SortOrder/MalwareBox2.cfg b/.bin/d7ii/Config/SortOrder/MalwareBox2.cfg index 6e95d5ec..3ef28f76 100644 --- a/.bin/d7ii/Config/SortOrder/MalwareBox2.cfg +++ b/.bin/d7ii/Config/SortOrder/MalwareBox2.cfg @@ -1 +1 @@ -RKill (Auto)|Kaspersky TDSSKiller (Silent)|WizardKit System Diagnostics|34|Emsisoft a2cmd Deep Scan|HitmanPro|1|98| +Disable Windows Updates|98|RKill (Auto)|Kaspersky TDSSKiller (Silent)|WizardKit System Diagnostics|34|Emsisoft a2cmd Deep Scan|HitmanPro|1|98| diff --git a/.bin/d7ii/Config/SortOrder/MalwareBox3.cfg b/.bin/d7ii/Config/SortOrder/MalwareBox3.cfg index 75da8a9d..1fbd80a5 100644 --- a/.bin/d7ii/Config/SortOrder/MalwareBox3.cfg +++ b/.bin/d7ii/Config/SortOrder/MalwareBox3.cfg @@ -1 +1 @@ -Malwarebytes Download|Malwarebytes Install|Malwarebytes Scan|Malwarebytes Uninstall|AdwCleaner (Updated)|IObit Uninstaller|Install SW Bundle|WizardKit Browser Reset|WizardKit User Checklist|WizardKit System Checklist|Bitdefender Rootkit Remover| +Malwarebytes Download|Malwarebytes Install|Malwarebytes Scan|Malwarebytes Uninstall|AdwCleaner (Updated)|IObit Uninstaller|Install SW Bundle|WizardKit Browser Reset|Enable Windows Updates|WizardKit User Checklist|WizardKit System Checklist|Bitdefender Rootkit Remover| From d8e28ce7852269c8331c46d15926060f31443db7 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 9 Jan 2019 18:25:07 -0700 Subject: [PATCH 241/265] Updated windows_updates.py --- .bin/Scripts/functions/windows_updates.py | 34 ++++++++++------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/.bin/Scripts/functions/windows_updates.py b/.bin/Scripts/functions/windows_updates.py index 2504fdfc..4257f066 100644 --- a/.bin/Scripts/functions/windows_updates.py +++ b/.bin/Scripts/functions/windows_updates.py @@ -3,13 +3,6 @@ from functions.common import * -# STATIC VARIABLES -UPDATE_FOLDERS = [ - r'{WINDIR}\SoftwareDistribution'.format(**global_vars['Env']), - r'{SYSTEMDRIVE}\$WINDOWS.~BT'.format(**global_vars['Env']), -] - - # Functions def disable_service(service_name): """Set service startup to disabled.""" @@ -18,27 +11,28 @@ def disable_service(service_name): def disable_windows_updates(): """Disable windows updates and clear SoftwareDistribution folder.""" - # Stop Windows update service - stop_service('wuauserv') - disable_service('wuauserv') + update_folders = [ + r'{WINDIR}\SoftwareDistribution'.format(**global_vars['Env']), + r'{SYSTEMDRIVE}\$WINDOWS.~BT'.format(**global_vars['Env']), + ] - # Stop Background Intelligent Transfer Service - try: - stop_service('bits') - disable_service('bits') - except Exception: - # Going to ignore these errors - pass + # Stop services + for service in ('wuauserv', 'bits'): + stop_service(service) + disable_service(service) # Delete update folders - for folder_path in UPDATE_FOLDERS: + for folder_path in update_folders: if os.path.exists(folder_path): shutil.rmtree(folder_path) def enable_service(service_name): """Set service startup to enabled.""" - run_program(['sc', 'config', service_name, 'start=', 'automatic']) + try: + run_program(['sc', 'config', service_name, 'start=', 'automatic']) + except subprocess.CalledProcessError: + run_program(['sc', 'config', service_name, 'start=', 'auto']) def enable_windows_updates(): @@ -49,7 +43,7 @@ def enable_windows_updates(): def stop_service(service_name): """Stop service.""" - run_program(['net', 'stop', service_name]) + run_program(['net', 'stop', service_name], check=False) if __name__ == '__main__': From 721a083c857ae24d572a48890cf45ebc75d21fc6 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 9 Jan 2019 18:43:20 -0700 Subject: [PATCH 242/265] Bumped System Restore max size to 8% * Per request in issue #31 --- .bin/Scripts/functions/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bin/Scripts/functions/setup.py b/.bin/Scripts/functions/setup.py index 2edfab41..c661571b 100644 --- a/.bin/Scripts/functions/setup.py +++ b/.bin/Scripts/functions/setup.py @@ -253,7 +253,7 @@ def enable_system_restore(): 'resize', 'shadowstorage', '/on={}'.format(global_vars['Env']['SYSTEMDRIVE']), '/for={}'.format(global_vars['Env']['SYSTEMDRIVE']), - '/maxsize=5%'] + '/maxsize=8%'] run_program(cmd) def update_clock(): From 957a53ad121698c730a5cdd74ec7882bc369f426 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 9 Jan 2019 18:44:02 -0700 Subject: [PATCH 243/265] Scan for browsers AFTER installing them --- .bin/Scripts/new_system_setup.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.bin/Scripts/new_system_setup.py b/.bin/Scripts/new_system_setup.py index 597fe981..5320403d 100644 --- a/.bin/Scripts/new_system_setup.py +++ b/.bin/Scripts/new_system_setup.py @@ -45,10 +45,6 @@ if __name__ == '__main__': if not ask('Continue anyway? (NOT RECOMMENDED)'): abort() - # Scan for supported browsers - print_info('Scanning for browsers') - scan_for_browsers() - # Select AV software # NOTE: Truth tuple is (ESET, ESET_PUPS, MSE) av_options = [ @@ -95,6 +91,10 @@ if __name__ == '__main__': # Wait for all processes to finish proc.wait() + # Scan for supported browsers + print_info('Scanning for browsers') + scan_for_browsers() + # Install extensions print_info('Installing Extensions') try_and_print(message='Classic Shell skin...', From b7423ae3b5b69c55ceb4afd905bf8c0335e3902b Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 9 Jan 2019 19:03:52 -0700 Subject: [PATCH 244/265] Remove space from System Restore name --- .bin/Scripts/functions/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bin/Scripts/functions/setup.py b/.bin/Scripts/functions/setup.py index c661571b..9a706a23 100644 --- a/.bin/Scripts/functions/setup.py +++ b/.bin/Scripts/functions/setup.py @@ -213,7 +213,7 @@ def create_system_restore_point(): cmd = [ 'PowerShell', '-Command', 'Checkpoint-Computer', - '-Description', '1201 Checklist', + '-Description', '1201-Checklist', ] run_program(cmd) From 7f0b53db409d70c115349e188624811146ebca97 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 9 Jan 2019 19:07:40 -0700 Subject: [PATCH 245/265] Enable Windows Updates during system checklist * Fixes issue #30 --- .bin/d7ii/Config/Profiles/Default.cfg | 1 - .bin/d7ii/Config/SortOrder/MalwareBox3.cfg | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.bin/d7ii/Config/Profiles/Default.cfg b/.bin/d7ii/Config/Profiles/Default.cfg index 5f743dae..161e77e5 100644 --- a/.bin/d7ii/Config/Profiles/Default.cfg +++ b/.bin/d7ii/Config/Profiles/Default.cfg @@ -831,7 +831,6 @@ WizardKit User Checklist=1 WizardKit System Checklist=1 WizardKit Browser Reset=0 Malwarebytes Download=1 -Enable Windows Updates=1 [Repair2] 49=0 48=0 diff --git a/.bin/d7ii/Config/SortOrder/MalwareBox3.cfg b/.bin/d7ii/Config/SortOrder/MalwareBox3.cfg index 1fbd80a5..75da8a9d 100644 --- a/.bin/d7ii/Config/SortOrder/MalwareBox3.cfg +++ b/.bin/d7ii/Config/SortOrder/MalwareBox3.cfg @@ -1 +1 @@ -Malwarebytes Download|Malwarebytes Install|Malwarebytes Scan|Malwarebytes Uninstall|AdwCleaner (Updated)|IObit Uninstaller|Install SW Bundle|WizardKit Browser Reset|Enable Windows Updates|WizardKit User Checklist|WizardKit System Checklist|Bitdefender Rootkit Remover| +Malwarebytes Download|Malwarebytes Install|Malwarebytes Scan|Malwarebytes Uninstall|AdwCleaner (Updated)|IObit Uninstaller|Install SW Bundle|WizardKit Browser Reset|WizardKit User Checklist|WizardKit System Checklist|Bitdefender Rootkit Remover| From 969011f3f5575c3f77b0f6dc3b2fc5db7b0a4979 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 9 Jan 2019 20:55:48 -0700 Subject: [PATCH 246/265] Added new_system_setup() --- .bin/Scripts/functions/setup.py | 26 +++-- .bin/Scripts/functions/sw_diags.py | 27 +++++ .bin/Scripts/new_system_setup.py | 157 +++++++++++++++++++++++++++++ 3 files changed, 203 insertions(+), 7 deletions(-) create mode 100644 .bin/Scripts/new_system_setup.py diff --git a/.bin/Scripts/functions/setup.py b/.bin/Scripts/functions/setup.py index 85943d2e..f51bf40b 100644 --- a/.bin/Scripts/functions/setup.py +++ b/.bin/Scripts/functions/setup.py @@ -288,20 +288,32 @@ def install_firefox_extensions(): run_program(cmd) -def install_ninite_bundle(mse=False): - """Run Ninite file(s) based on OS version.""" +def install_ninite_bundle(mse=False, libreoffice=False): + """Run Ninite installer(s), returns list of Popen objects.""" + popen_objects = [] if global_vars['OS']['Version'] in ('8', '8.1', '10'): # Modern selection - popen_program(r'{BaseDir}\Installers\Extras\Bundles\Modern.exe'.format( - **global_vars)) + popen_objects.append( + popen_program(r'{BaseDir}\Installers\Extras\Bundles\Modern.exe'.format( + **global_vars))) else: # Legacy selection if mse: cmd = r'{BaseDir}\Installers\Extras\Security'.format(**global_vars) cmd += r'\Microsoft Security Essentials.exe' - popen_program(cmd) - popen_program(r'{BaseDir}\Installers\Extras\Bundles\Legacy.exe'.format( - **global_vars)) + popen_objects.append(popen_program(cmd)) + popen_objects.append( + popen_program(r'{BaseDir}\Installers\Extras\Bundles\Legacy.exe'.format( + **global_vars))) + + # LibreOffice + if libreoffice: + cmd = r'{BaseDir}\Installers\Extras\Office'.format(**global_vars) + cmd += r'\LibreOffice.exe' + popen_objects.append(popen_program(cmd)) + + # Done + return popen_objects def install_vcredists(): diff --git a/.bin/Scripts/functions/sw_diags.py b/.bin/Scripts/functions/sw_diags.py index 8faa25b7..100e5ad5 100644 --- a/.bin/Scripts/functions/sw_diags.py +++ b/.bin/Scripts/functions/sw_diags.py @@ -103,6 +103,33 @@ def get_boot_mode(): return type_str +def os_is_unsupported(show_alert=False): + """Checks if the current OS is unsupported, returns bool.""" + msg = '' + unsupported = False + + # Check OS version/notes + os_info = global_vars['OS'].copy() + if os_info['Notes'] == 'unsupported': + msg = 'The installed version of Windows is no longer supported' + unsupported = True + elif os_info['Notes'] == 'preview build': + msg = 'Preview builds are not officially supported' + unsupported = True + elif os_info['Version'] == '10' and os_info['Notes'] == 'outdated': + msg = 'The installed version of Windows is outdated' + unsupported = True + if 'Preview' not in msg: + msg += '\n\nPlease consider upgrading before continuing setup.' + + # Show alert + if unsupported and show_alert: + show_alert_box(msg) + + # Done + return unsupported + + def run_autoruns(): """Run AutoRuns in the background with VirusTotal checks enabled.""" extract_item('Autoruns', filter='autoruns*', silent=True) diff --git a/.bin/Scripts/new_system_setup.py b/.bin/Scripts/new_system_setup.py new file mode 100644 index 00000000..6ab88973 --- /dev/null +++ b/.bin/Scripts/new_system_setup.py @@ -0,0 +1,157 @@ +# Wizard Kit: New system setup + +import os +import sys + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +sys.path.append(os.getcwd()) +from functions.activation import * +from functions.browsers import * +from functions.cleanup import * +from functions.info import * +from functions.product_keys import * +from functions.setup import * +from functions.sw_diags import * +init_global_vars() +os.system('title {}: New System Setup'.format(KIT_NAME_FULL)) +set_log_file('New System Setup.log') + +if __name__ == '__main__': + other_results = { + 'Error': { + 'BIOSKeyNotFoundError': 'BIOS key not found', + 'CalledProcessError': 'Unknown Error', + 'FileNotFoundError': 'File not found', + 'GenericError': 'Unknown Error', + 'SecureBootDisabledError': 'Disabled', + }, + 'Warning': { + 'GenericRepair': 'Repaired', + 'NoProfilesError': 'No profiles found', + 'NotInstalledError': 'Not installed', + 'OSInstalledLegacyError': 'OS installed Legacy', + 'SecureBootNotAvailError': 'Not available', + 'SecureBootUnknownError': 'Unknown', + 'UnsupportedOSError': 'Unsupported OS', + }} + try: + stay_awake() + clear_screen() + + # Check installed OS + if os_is_unsupported(show_alert=False): + print_warning('OS version not supported by this script') + if not ask('Continue anyway? (NOT RECOMMENDED)'): + abort() + + # Install Adobe Reader? + answer_adobe_reader = ask('Install Adobe Reader?') + + # Install LibreOffice? + answer_libreoffice = ask('Install LibreOffice?') + + # Install MSE? + if global_vars['OS']['Version'] == '7': + answer_mse = ask('Install MSE?') + else: + answer_mse = False + + # Install software + print_info('Installing Programs') + install_vcredists() + if answer_adobe_reader: + try_and_print(message='Adobe Reader DC...', + function=install_adobe_reader, other_results=other_results) + result = try_and_print( + message='Ninite bundle...', + function=install_ninite_bundle, cs='Started', + mse=answer_mse, libreoffice=answer_libreoffice, + other_results=other_results) + for proc in result['Out']: + # Wait for all processes to finish + proc.wait() + + # Scan for supported browsers + print_info('Scanning for browsers') + scan_for_browsers() + + # Install extensions + print_info('Installing Extensions') + try_and_print(message='Classic Shell skin...', + function=install_classicstart_skin, + other_results=other_results) + try_and_print(message='Google Chrome extensions...', + function=install_chrome_extensions) + try_and_print(message='Mozilla Firefox extensions...', + function=install_firefox_extensions, + other_results=other_results) + + # Configure software + print_info('Configuring programs') + install_adblock() + if global_vars['OS']['Version'] == '10': + try_and_print(message='ClassicStart...', + function=config_classicstart, cs='Done') + try_and_print(message='Explorer...', + function=config_explorer_user, cs='Done') + + # Configure system + print_info('Configuring system') + if global_vars['OS']['Version'] == '10': + try_and_print(message='Explorer...', + function=config_explorer_system, cs='Done') + try_and_print(message='Disabling telemetry...', + function=disable_windows_telemetry, cs='Done') + try_and_print(message='Updating Clock...', + function=update_clock, cs='Done') + + # Summary + print_info('Summary') + try_and_print(message='Operating System:', + function=show_os_name, ns='Unknown', silent_function=False) + try_and_print(message='Activation:', + function=show_os_activation, ns='Unknown', silent_function=False) + if (not windows_is_activated() + and global_vars['OS']['Version'] in ('8', '8.1', '10')): + try_and_print(message='BIOS Activation:', + function=activate_with_bios, + other_results=other_results) + try_and_print(message='Secure Boot Status:', + function=check_secure_boot_status, other_results=other_results) + try_and_print(message='Installed RAM:', + function=show_installed_ram, ns='Unknown', silent_function=False) + show_free_space() + try_and_print(message='Installed Antivirus:', + function=get_installed_antivirus, ns='Unknown', + other_results=other_results, print_return=True) + + # Play audio, show devices, open Windows updates, and open Activation + try_and_print(message='Opening Device Manager...', + function=open_device_manager, cs='Started') + try_and_print(message='Opening HWiNFO (Sensors)...', + function=run_hwinfo_sensors, cs='Started', other_results=other_results) + try_and_print(message='Opening Windows Updates...', + function=open_windows_updates, cs='Started') + if not windows_is_activated(): + try_and_print(message='Opening Windows Activation...', + function=open_windows_activation, cs='Started') + sleep(3) + try_and_print(message='Running XMPlay...', + function=run_xmplay, cs='Started', other_results=other_results) + try: + check_secure_boot_status(show_alert=True) + except: + # Only trying to open alert message boxes + pass + + # Done + print_standard('\nDone.') + pause('Press Enter to exit...') + exit_script() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 From c1324548ce1c058c82419467c9449af046d26579 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 9 Jan 2019 20:59:21 -0700 Subject: [PATCH 247/265] Track ninite processes directly --- .bin/Scripts/install_sw_bundle.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.bin/Scripts/install_sw_bundle.py b/.bin/Scripts/install_sw_bundle.py index b44874ae..0faec26e 100644 --- a/.bin/Scripts/install_sw_bundle.py +++ b/.bin/Scripts/install_sw_bundle.py @@ -41,11 +41,13 @@ if __name__ == '__main__': if answer_vcr: install_vcredists() if answer_ninite: - try_and_print(message='Ninite bundle...', + result = try_and_print(message='Ninite bundle...', function=install_ninite_bundle, cs='Started', mse=answer_mse, other_results=other_results) + for proc in result['Out']: + # Wait for all processes to finish + proc.wait() if answer_extensions: - wait_for_process('ninite.exe') print_info('Installing Extensions') try_and_print(message='Classic Shell skin...', function=install_classicstart_skin, From 4cb158b6b27bc10dfdb43707bd34ebae409a7be7 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 9 Jan 2019 21:08:00 -0700 Subject: [PATCH 248/265] Removed duplicate docstring --- .bin/Scripts/functions/setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/.bin/Scripts/functions/setup.py b/.bin/Scripts/functions/setup.py index 9a706a23..0acb52ad 100644 --- a/.bin/Scripts/functions/setup.py +++ b/.bin/Scripts/functions/setup.py @@ -375,7 +375,6 @@ def install_firefox_extensions(): def install_ninite_bundle(mse=False, libreoffice=False): """Run Ninite installer(s), returns list of Popen objects.""" - """Run Ninite file(s) based on OS version.""" popen_objects = [] if global_vars['OS']['Version'] in ('8', '8.1', '10'): # Modern selection From d246ea1d8636a06002dacb3de4cb594b3b8d7f8c Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 9 Jan 2019 22:00:05 -0700 Subject: [PATCH 249/265] New theme! --- Images/ConEmu.png | Bin 59425 -> 222947 bytes Images/Linux.png | Bin 56161 -> 266213 bytes Images/Pxelinux.png | Bin 16570 -> 76348 bytes Images/Syslinux.png | Bin 16570 -> 78817 bytes Images/WinPE.jpg | Bin 573035 -> 351191 bytes Images/rEFInd.png | Bin 73995 -> 258714 bytes 6 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Images/ConEmu.png b/Images/ConEmu.png index 01f23aec276e75eabcae7e7f5837d1a5d66e4431..ed9d0cab461b22daa44aa2e1fa6b1b6015423e09 100644 GIT binary patch literal 222947 zcmXt;Wmr_*+r`fe0}Ml_G((3-4$?3~OGt;LbPCc9Lr4kIT|+6tgCL#Kp@5{I7<6|x zy!=1BAI^35-sjui_u1E4zk9`MJy#}#(ZT=#Abh5xpaTF9Gys6dp;!+q^IX?u50ert zbv;G7oHb4NNwPOHa@rmU1rOnj6)`0z$(%Ko_&?md>WXp8v~T~4yqO1rr&Nujz~M7I zX)AE}Q&CY3ZOfG7f*9lXdlHh`%Ha!?@0Jw`HepeJ#50!Fi+56Azeb_71yUBQD)%3! z%yU{5($YL8i~A>;x5JXMA|PRp75Q7WV4LgRKbn*cUPjDDW9K6~*Vm3au zo~9N1LOHwYj-OFdnp}b}zi}5Yc#0uQU30*|-!mEZ+(6YG{|Pv$4s*<7RoK+@%s0c?C4^g2r%6E}f*IRlQNw~#2A(f1^eVR9{EAiHA99BF zn^vwFm#*;UtWrdbJ{B_-kaE@3u%?Kcd6BgARK`LoV}m|rNg}9CBV$wBEXBksgo_Qy zma|PyFTfi&r&qE5gjX9SDy5infHW(5ET${<{FP_n4?TGWb+?4-@9%*Bn0xIW z;Qd{@c$*-6N=h>V@E?YTPwBtkhlbDUzu$%gPZB%~9==A+Y8UTAqaMcln(wzD{$pD2 z_krMH!l+4z|1czY7!o%RXH#SoGlRy>;YLm2GbylTERzKPWkk3MAl*?&EdfEThjML- zm7I8Z;k{OQ;RyivWdD0WlYc{Q9u{%Eo@prJE`wkYW@5^NiZcL!1J4vtdVX^&9SNEy zn;rXf%viC!Ot~@d;&oF6tf{^a$3#X5Ss|EzC<^L{wF&(`L*{(di|cWjr%;THMf|{F zuiqGXD~zU2oaT_oE!Syv`|~%y@RuqNOu){l)f+;o$|6 zl(T==yw-HbDK=+kALi%J&l~p>ME^Ahau7WF`(~_9^Od*jE3;Rvl0J{d===sX6Q|8;kF|6BC%e>=w8Zp_G-cQ7VS&vaqo zTV1y3QaWm%|4CiK^ZIY~0xAgRn|(?U%6!cA%JkxBk8gNi#jsOoGv|AWSJj~YVc(7I zweBhYnEM~si=UTk|Mmv#75^CgS*x@1^=x~qXu(DD8V3w2|l?ufmv^NbH%wF&Di6OqLx;NM!c@_ww$~t^Sl* zt~}5x`Scwy*UGcOO6}!MT2$}-OPh~hgy5Wri0}pA4}PsMa4gA)>8G>;uw_JZ}*PV@Pad$an&;@hl} zd6!MAP{c*tjo5Q)8ipSr#CQVrM+TJd0o?b1ED?tO2Q3u*bg`bV0v{LdV`9--`jiim z;|T-gO1;jqFQ%qXDk}{K!&Eb)y|JgYWFhfMzW!+=($_xBiCG$ev8zPT%;?)mMZ=f z{A+PbYbD#UdMLr0n0~&23NFkp;HCXT#sIrdRR5kN01$bUX!0YGCurq^!Clucr7Mz< zgJkIRs~Myu*#^;9CL7{yrWq6#B_PC&c|EvV2{-@rG{ODmG%5j1R+s{`8h;Gc0zY}j z0Dz0YVBiU%IgJN3kkh};(3xih=7s<{{u>oRp7>-grJYx`xa>&;-9qt9aor6g5qU)u!_!6q*hevf-MWiYB1qgb1u*A!rnyg~NLlSfN zc!^L`;lRJ+SkS^7yY$|@@jh=3+6NVih36~Eq^@umzqa0tI zeHG*?c&&VMUF*eUK4vz5J@baFd&b@c=$k^=UHs{jv#=B}_R7ZY6VV!M zHelKxzo5W`I?pJ4Hsj{*{%ovJs)7$K!d`i+Kgroxbw^rcX!~>Z$B)FONs!PsBWVatN_4kw|80w~mV_H&Z|Q;M!E3~T z-S;juV-%sfE<#@eH{l;Mwpa8o>$1dmOu)F=NA!g&Z-`TKJY?&d668RK9eG1THy<$m z>z92$ah`oJE;aHUGnk}2e^?0OnPy)oZIVOXZop`MWU=WOBC5NYH}rBNHJW^Mzm+X? zDEeQi^|K3?WXdXu0XSF{UuuC#&m89BM zo|RT-zSX5bY7Rxd%f7T`Nn!}q`)Iwv;1llEQgS^?_OvvtT@J!MH+T?S5ovxD4@M&h zK2uz%oQ?ORa@fW0cbz;tgNv~iw(ucUe)+N9$&KdONjWf`i zcm!h(Db}tgCq>K~T!m$*Dz0OF$zsg;Dtg~8N}~G;1H;z)fmORv5clX5qwZefDegOA zMnF{+Qb!^kE)zv&g$IGgX_M^~KMA#g@oFU>3CYx@sLaa3BHmg2$AQ+{aml@qke$;o zUTwz2gBTfPc_Y|#lyKi;hrIs)Qo<^k(zhM&@~7LCKllvZ_%tnR-?R9+Z=IUgjL{x& zr&7n(N`1$4l7q(;JOlja7R2j*u<$eN33!}72GiYA3xX4L)9#IVyF;J;oceRTI?&p2 z=YG4qT?n8VX&f&`B#zdvIKW(WQ9K;1PvGu8i}yB-O@+=>$i%aEn)*Tq)vCa5X{hPZ zU!u&)6lps~$f;q3M1;qeBywsGrePeEBC zpz2hm#Q#dK1jWBUdR5GyeI;S;cr(=H9Nl-lfjlBQmg`l!kO`L@WDoX&6hUYeFEGH? zKww|eN#^L?SpG4VFOClx62P?S;j)R08_jb^DqVJ&ouOSoeZ*YoB+ljFbRw;#&F-n- zU^jAf03E$21cMs~-syg7kqw%+_MO|)K4r%3jo6M3|ksE`k;#4eM&eN)q3AUutyP^)9!@bK>!+eLCuCqbH%F?418NYndcW5Vo;u8mzv`noI#J3W+#9@1WnbfyUn+t8!eHU0e<)0P)LUu!&WZLK+Y zO@{l3nBI?W>Yyor?weYKXYcB}=bIqH%xF40I~;z~$C-hQoit^3?<5${@-D-2FWUS!l&Dc*5_(*&{1knIG^_~#lftWc5tei4JrFzs={q>k zRPHqA1bQ<#KpaV2Amg|2s^Y>OK_E&%D3T^gf$df0Yxf@OVwpN`BPVy$EWn`}JsD~X zaKES-xiZE9)%yp-kPxWcTIpekMnad*yM8@SA~*-h zoUC>qF$0Nw3^Q8CF%+HyyRec7lVf`W4l{x$srq9H>Ly#QGVRTUAt_R0@8SNb;x_uI zIB3fA#5CCp{Rm`Q9C0n=sJ|fVl3dGG&@-&A>_&^*i)x^5N!kLTXcL8R(_3gvK~h{6 zX*bFs9I7xjtRAU;L$Jg=80 zKXvi-{j*=OMc|lW;{7d=n5O_O-P;ndM8^=|fjG%v@Kjs%h_;lQZ=G2<=f?oFC->#P zLletmKR20lklUR*muw~W-CV?l&)kqCKEdSGH+DEnHC}dvC7(rth`5Y3_ti0Rke~C} zfNEzXctaXz{5$*j4^ZDC`7fy=v~MSTTyU3~87iYGu3N^%xik?+6j>8Kfo}-c?_mp3 z=Oo$W9-i;A&D^LcO=KtK=&WQR@@#u7$A<{*>vxKgh8rNAZfpg^tSa_-(Iv&oiz!P` z|6Py$N4q0TbbEeHggpSN9Ic9lWKN}Gfw-GKm3XbpOhSu-z{iohyK&GSe)3?wb7gTX zDqLf*3Kyo0D{Kk>o#kL`2t-TFR0EU@kpo4N{?va9IH|H-4HUlPFOU)Y7bf5dN3VTb z9nN>6a z-FBdGT^Mg2=c|{AXM89-`Mi_LKFudUMH#+}Bse()2_dz}(_R>}{1_=!(CF~3%|iaO ze1ateL%sS<=hZV!yx;v+GVC~Y+{zU9X_SALw3E^}iS%hv8F^V&%IklqZZ>X6!?F^k z;G`ls^l-XM@^T7k{kA9V6<{Iz#Y#Wf29aRL+JWrl_aKi~rL4hurjCvTe_v4jwIF~C zg=vAhHQ)}$oTCh_|0&AG7goSxcsJTK?0c*i-xbxC1Rbeg*n~FYRZ~tgM4yww1g93(~t*zEIBPZ9h$8HviZ~sF=pWd7r zZsS1939(kxqVhJjb)D(hB4=N5+pr0b@BLCC_u|uGyI1t{F+4} zT_pX){qbL-i+6;U^LkKHL_$+6em9-sUmR1CyAYvUya;*H+AYW+p2aF4{0`1Fc4pY!*d_hyz^WA zRjY=E_{HwGeEo*ys$|(g>~Lglp6DB^oGqC|KHuJ1TpMYGhk^lHqZ+A=L%yWlZ+qle zN21PQQvQSS=r*%hn$9bc!iRDFBQB!6k_(qmy2gHlI>*b?vsug?K!Vw?p7R$lauSyZ z;Zuxj$qy2OFqKW;R)3j?&dOCU8yn6lXd1e?X?l*ye%S_V*IH5`H%~3T6kN_7;{L!= z?QODUw8WyWwS#rQi3UFPhOJ+G4tstYpbt#!m%FeB>c2Yp^w+!S{rwkJjIWNkBqNI8 zS4`OIxb~>9YSg%wv=baX7D7mFm6dxg(ZT&e_yKGpe6jtri05ssG3?fPA z-8vr#n=gub>5GR9?lf}ZnwOxFA;-m@K0y$;Jouu|95^Y^t{Tz?A&46NjvB8_Tj)V= zt(d$#gQ%+)?Pz&#N67suKH(}~sAgR#6ol~fdDZ)0NF?q_U3KSO@B8F8hTWj7Uq6w5 zYOY8>jeE~1xhTpixt2hiT@zX1o(ng{tDoYY-^aD(27t!13hQwJgm%|f)0ww?3ye}sPmz|r~5 zO~715=;ZeOcH;Lt{wQ!QN41b?s>;CFz%;vG77H=dx^DCpV8a*o4-d&NhsUs1^f42EFr~^^IFwca9}JR1 ztv^k^tyO^^k8;r1Ipb_)lQ5(ms)Cfkl9v9P$paJb6JK-6Z#^ihP=2ZCh_xbNEp-R*qP zt%TTY#)2xK1or3RQBlK(uP+>>;_Lbso;AyXx_b@00qNkYlZD%B47%XS2H@1JP9xkw zc4aU-(t{mcV&60WXUA;=3_H#1(D3@qg^9K6tU!+}y`j~`6IaM5Fr_GbNWP3{^25NhOy!Lu%> z@a=(8Z> zc<{-FZW=A5n)DqFpyg(GtYCQjOOuDC=ETr`aoECM58DQZWcJ?0YAcw~y)Fu`c9c-4 z_;B@+A(FoVXXAbhrjq@JYwD0Bs(*YJMT(H#ouEdMM3f<~{jlOOoeL@jRwLW${wZH| zzR|ob;$XRNayV@_9D&wSiu09_wD#aHIkRs!8clLwv+-y)z03MPXB#%hF%D{`7=KLr?coB3+6zY;Na&o3&VVQj)hFm zr;b%vLM|hh>ljsiw^3O?8K(_` zJD%B;b7K{{{8z#h`SpU<^W}rGzON<#SG?LPpA96iM&wT&W- z9`f}i0kBAk+?9vMxgWfFpZF=lisOp<`*Gt3)vZb&uw!Ys5d@EjVU}TC(ugiWdxneD zAx*V#EH&ksDw6{R<%mZl<+u<&oJ6IIr6;~@^X*=1+vtq2*#oJ6*2@|?kaM*b#WxcC zyyPpH#_c-MyYo}+XT?Mq!S=R_DVuF4TdEyLdJ;s){Wo>P-Wo8xfylw9#@X^C2$&WC z(GJeX7yWGGqbGb7a9sUxqsU}C+)ZvoHTfa8-!H9uUxF2^Dyh?}q!YmbBH*D@(L9AS zdPsoa9i;Frk_`F9C`L70U~@G-V~aK6l(8rr@q`vC5b2lnBB?$_SFIsEg`M*`e{ZYZ_dpIC+lno;6uWBBsunsi z=hjLdTj1I5`E4=~bTRQAAM9wlQ-X)h#_|c2a}yyE^Io(tQ)lh_(TWiJZ`@Ya(!ihL z9J}&92xqw3*he5K9R8K5^|w7i87Gi0E+&dVOw$f@J^q6TakXqN@-Dh3w1(m4jB6}M z<$ZRH8YJN@@C&&57T#-FLzhO ztl_ym1~AB1tK>7Gp0z4A5e!1h@2H^;mG_7k9p;-KY-+%j~M&Gx#Gvy}Be1 zdXCK&I5z=>O&AGDP+N*9ZAr85X8B|-30$UUQP6eNTdRICB~v?tv#wc}>NYHn;hWyXA2 z1Hiv&SyMGl%DSm7Y9g~H1d%}6rzo5ADI7TtRhzWY1CgbWYke|Nf|CL&|_ZH(p^;KS&q)hfiq$mAo3VxS+AFJ2Z-W3il~un zVJ=c|h4H2I$9L=?Oxakq$2?AumlgDB8>0F3E1!?}eZ+ZXpJMr-{pPr3)&a+EcZ<%0 zv*`DljCglYm#p-+4d3h;>a6pU=1YkL8+8Bu!8xn=y2N1*q)j9nMP)M{S)aY8_J(0ZqFI}F!ilTKMnE>*O&)mI`QGbPxYrliy5Et z0xZH3QTIfPAnfUYK8A1s{cFFDhONRhM*mm`{KE(y6+{jX<=E9TAGNv{XVt9Qt(=*x zsa**xD=TabVV`d-vDsvH8$bGFkU7wDw)o@RZigmeUkXz%g9$^nE5Ocv(kWdUa zKGC0Q;!JxGQg$qh0L~oI2pZ4%kEn-F&^ff7Jti>yK{2kcYX-PMv>ILxuaaS@n~g;j zGLY6Cnc^hTSE9sA0b0}r)u~bmBeVyQbHLUJe5aUiUJdO7uSk^;uRvhCnxo5{pZ$Y6 z&=N66+Qk+gnSqfJyfhr#sI)fD}`D>z^QW9!-Hx-Oj zdg0Zi;zmPlg7$G+=EK}fDp8i%v5vlR!ebm@l_o*V>swmOp{P14DW zda2(?V`C$x`d?fWVY3iBW8A^xJ3U}31x>`%B><0v4e8*n1ay>`GVVCuu~{F53jO|$ z8aep6A%ZC8M)B`DZjwK+4rx*(zcA!Cx#5tRBB<&h@EJPCjAk6Hg0*FWuwzxi6-Yv)Hhp8}8#$!#uZDs;a+D8i*g)`{Q!o>hTgpAy}@NL^bcN~nR)2jx|4v* z|NQp0jk2m?1dm$?Q(>Q+y8JraH`||-Va#Qq`eC9WoPDDd6@>!|pP3*`sWu^h8M^O@ zp5*_CuP@c}8|R<=K>Zm*^!PqyXgJFIIP%WaCpFrNB6iX5!GPybl|BD#t<6aPiautz z81zB3%yQTWZhJ*rb;V4>Mw%unuM#_$R*R{R>6xSmTTSRQDkCj@3DPy96fYjeQo>ehvI4ju2MGjk3au{+@6Do~+-5RW z*$GkVkN>XjK{Dm!IZUw2zPUZzMhFhoLalM{+UK5LWH#b8NQ8Op$uT>xL_3*8eCFgV z=k1&r-N2Zu(-+V60Z+qYV`FnRz8@U5Ww;ir@e1$eIu(?dmQ!y8`3saDT zg{$a@eFd}7V@%BnT7nh_m-x;?4)k}hV)bZU!#Y-gN*N1Hg!sG4M}URI-MKiXpd6>X zC!1w1*h;Ii_KYA}8an`ompA;01GZWhZ~>9~%5>aP^qu=sTf9Kfh;E)QTuX^|0v`6M z+I;;aXigoIe^J-;KSK*_lqtP5+DLh_*4)~p1hkwJAiq%}plmpgul;CgSo%MvBT#Uj z1Rn_v7?dm0TkiRO5P?iTis3b`Dqep|^}@3I$6BXfW`uJ7ijdXE@3g6GhA{tqFDzyZ z&xW!ITY{FA9<@xwtMbba&46mV)-OC~>2=bHC1g)l+Vy1D-%zrhCfX5xQ7tC7K4~X{ z^T1k#b9OlBHrAj>hf;D0kH1TE`f#k$Auf@QJlq5mw`QQt0Y}j>9|LrB$>ktb}jsNmfD>@rVyNJeqY0fo5oB$Ih{i5mtd1hfo3!J zgzB3}1`^GLH{^H(y;nIaTr>IVnAG!Xf>AGKG%Y=Y9N;apQEd2)Xi$8lrlG(&xT@iU z{n}kRV`t}OXVo@Yj9Lg1^w(J8de1O-n@7aSBue!Mk}H%1IqRlbwR9o$ACYQxl{;HT za{rIE8QH|io2CG9QX}J*ozAuAov&|+X(U?Yo*H`Dd%7y_H2*PJU7m|rtH#t)%X5Q; zRy6y+owBU{*1dLrMO*>b2tZBeGV}97wuvUtC;1^L`Ia4w@OYwxqu65Ab2^3#9 z^A)j+KFYC7gtySvJ~mJ&Y5w5R=r6nOQYh@u8p*Nx0t*kSAKQ7-HJoyDq*O^k=iyj4 zEtBJVQ*#KMU5w~J9f`by&K0eZ4C)uviXzf-bY3sDeR)o8BlR?meQ~ ztw2ujVp?sR*gxJVDa?{b8!>3f=M%XQONnGdpTr04k=c>jqQQ0R< zJ!s*gAo=V6idwJ#N^p@=wJGf``@L0+kcHl>Aquh_j^n!TTB6H#&qbx=B+*i| zj-{yV7k~1sTB%qV6s!7~Utf7e@QQUlk~i}GM>}_$KKc-C_7W{*dnT^iZ4+FAR#qP7 z;Bxq=&UT^SrPxuB00w2#x?gwyhdbZ$iiJ`33WPK)r)WjtYOP~+Y9T%4J9<~~Ny0mx z&Q5vW|H+%5p9=DsS{S4Kvd_N_B4JQN z#3|j_Rwz@P2$E1}VQXQoa=N!B3{@v&r|pUyT`nE;)>$7DHXIA>yP9%b+Xr48pyEjE zhM=@4a55euoQajG2}4u==Znv0h|Jr6>GtMXIj{* z;R}y8sCHWsJ^l^epmbyT573gy9j(Ky`i*>@IXbf|`=@z-BR3(MNU}}@+ftJ7ALhEf z5^Y!CX5?j(hmodf|Exjjr2!oE!wV)=F`+sv*hooF%b*ZgvT*vN^vM@_2XR7NAGqL3T9iQ1b%ZdJ^?W<6ygvm8E}1hFZlSi;Yk6;wWu z9Y_(uxZGQ2!(uOFqaO|SE`IS7BfUQu(9AE?1I;{H%i+07T&E{Ga1!GbpCs6|xvpJG$LuDC(bW#8@y} zL>KwCf1EI25jB39X%Jo>!p{HU5o^vrM`x+4HO>2rS866^KDdt^1{-zpSOBfhz&?v7 z?)o=IjnJn9i7%W z^i%V3M^|FwBn7bqoq(9ie37D%NW7}T}ggAaNiL&{kj=zcGxQg|-fyxZGT zk(|N$dvnngE;YnVnjA*d^DK6lWv)m4)&?JIXdw{ouqtiP^aBfU)?QT~>nH9$0KE^Z{w#FuzI`|p> z_emm=A>jCfY{>D!UD7o+i@+@?oFC94y>$pMsT!)!bmj-yXv?|=lIVZg!oMp2#JJ6qc%l^_kv zmHz67fTAOIr!)I-I`YM8CWVKL!b9M31}Rt+*;gF+=Y&?cchDr6K<$M|CtAXMQKD}7 zzilSgU2oI#(097YMP50(I(x=%fXRj0#4js0yZmZ<9vdmL55W-I@xhH- z%t09czlh9_hKy#+JAWN;Nh2Y~2B3OgDfkN*g^VXz|5xr>3^_^olasSz`y270!b1g? zL&VL=Kq2|!*f15I7baXr<1qD>cnt~aPL#CcpC>7kH{?G@gud=Uef-?r^6OJ<`lyc;A7Fl?IJhl3?8?H;;OR%gq`+mBRUSdG(d;Tw}8Xr{K48Oi4?$i_7 zEF_C9oY4NF`?Dl5N0W%aOVo;#L^Us$l~t5fGIbb1;1F4_i7#r0`9pJ=RcAe%RiV7> zK!#VZ9t}*pf|H=#;}Le)6w1JD_=T<#%M-q{BK+IM^}~bcCZC~RtnlY&g*V=nh$3us z<3Aaoo`%==i6!)@a3svZZsV>`-Fdst-Y_RO*Ub&ODpyA;?5Kr&*S%J-rpb87h8gkn zLsAL$J)vn<5An3#k{GaVLP5Gw&(faT^9-hR7z4W%T>=Ss{)T6_jls$$?}9VSXw97! z&P?BS)pDVcIMRHur2n{79X_0$r^m@8z<}8F5!VL71{{19B};6-+4p%}m~!)H@y8}5 z1)BlQ4o$+XliE>w@hO&MC{R`88i^q`9($y2-m}&VnCaWgW+OiW0x)5HPoo#(iB<@V z&k}nPYhj%%Xpv0ep@05g4O)!wEQ{JEJSh&Y2*IYHWNTA%5k8bVQ%HQgM*NZSV;Djn zG*Qw;EZyKJ`a`-XuB#H^L>Krq8Tpftiuw2YS|RfK4;w{8lQN5y5Xt#~XV(uI4~iw> zotdub7m_B(w9XGxe0xt|T!B}8BBR^>F3I)L2{W?|&NxlXCs#rA_r7axh;!DH^QZOiJjr&rUv9nv zv<7F0IJ}ltzTRC#m~VnMCA;siNE9sSq#l#X)oknPR#xgZbzZwtc3@68E@${FasM^w z!dzxqL;Dhc{J0-XW_4@)(J?OMr_NtO4p|orWO=*?yJ_|)?ha}KYU3AwGM^mLjKztC zyD(-RL&|Si$}E2g|6sO?8_~630zrPrE36d-NhN@V|E)YvkQ7cret~1FPk$kD$R&={ z!lF!8JaFT;sS|&Op+sRQyO|WmVYJB1q3G}7K(S;|IBW&$qkC2tNoZF4Mv@Mx89UM2 z0P&j?n2G@-t#+nMGyE&LG#{;ce{^z;tVJ!yVncq_I_OwLS^x%f@Q0|7z1aIAE~l+` zJyh!g&Q*YbBImSsc$=6QP>>?|J_Q!m94AWuB-GNZ9!TM52;eRfRV zOnWzyoyx>PHHZTK^6(?_Om?ttBDrz4B}wjU+Ix|3G9+iHtmJtZFiz-GB}q)6fe^Jg z@HJ~TzyU^s1uk}e-NqJVx7dG}086};wy?UD+=9<;_pT0CUw)K3oS?;W$h=a1TI=fa z$@b~7uJiVWvV}4}RK|5|zCez&{tLHr$$5^(x9X2Zq&9^x-QeNPhS>3n+IYHl;=WIvZI-+V^&b8MY!v)sgj^U}2x8*fz{3-+qm3vosW|3s zXVR#D;gBM=&YmuICgJAQPM2A5IBE0GIq)XSh9t#qWjS|vmlTaxJ+M##H;xB6wBi;v zjVHa!AgvFZ<5n9`68X??bTxj?-$Vzn+#$Vw%+I@5GT~y~iZhz$dA=OG>TwQ!D+kh6 z9$4o=OGru%@?OLaf@E)RnItlzxZcVJTB{KVw#A)Bk>7nPTJ+do7@3^Z+HSeN!wcQs zoDwF$B&Y{y7~tBOR*y+YXj;2utR)<@Q6XtE3~0?Z7)W{G=X$gX5aWDRdHORC zNYeHy4?NG3Tw=|XoBrBrzKJRLc=L;X39{AT?!OJC6Ic&>mUlGFh+Lsgf+r5slFxHN z4=nlU=7Jr3Ym7DOHSzjlko}yI%>VHg;3jpMh`f0dJ8=uZb%>A6U#4b2E-=vW=&KZ6 zoA&(D;C60!W&vkvG_ERE7!rRKN>LPk5#82e6o5^B?3YMW!;5r)`K3{!jGk^Afckcd z0_#Y4xM0vj@?tJty%(gV-i{C;&NHB-b353vRc)w4%mvbv|>vx9g_Z%_k}!$jCI&D2Va;QB8!hGyWNuc5gkpQbQbf%a4~|^qstq+f`Gos3;SKI`{NDvG3Lr(famM|5x$m-)nL?K97+5)hd7aCWxTPI3svqbcQ4HLLm-Bhj7i69TN0$qFn z%z6zc<&tWQbK%GW_)F6 zFjXuA>thOq99Qk1QLJ#|aj@0;I-}1w&03b?o^{s?GTW|FnySa}Y@9&+%;JG%2l-c z%tFvy6+!UL(|~}k&vo{1!Q9HXzEfpM&0l_~yOkdX=exVB>k{48*LTZ9$@c*(bxbuP z3fLXLT|kv!co6!YJ6cpjFl%%!;Cnj^VdPD$`I-}8{$gWxa(2^A1v^29YrekbZa;|3 z>f7dk@;(oP{|YW*XN`eta!>x8oMb$7U{@ct-fs5|efBtg&M$;TUrkr%k23l0*OHKU z7WOV$m1)kk=F{yI$y`HHwhMXA504<(wn+yOY2=fNBu9hqx#pVcJO*EfDk-;pML*xd$HrwD-er{?P*pI6%>0F(w{te+n-wJc zls?A~n0&(ey3LNTo= zCMEN(E!`eiH2ZJum%e(M#bB|+-p)CYoW7&tUQG@{|FqDgX3y-NN(_;cEeJ2|rcJo!=g zvwvTJeozFr@ULp@mhat06L(zZj=c*yvCGF_$8IreIIvgjPUH$1pkeq$f5mdp$Yad8 zx!{05B7y5E5>Gdr-Ce>1_Z?457afo2G>>6Qk&@yRR2Dm;EabAz>|p6S!l_w=`Mw1i zzph^Nnk;c-pGE;CY~w>%J7MPzCOmKY6>i9{e#V1?B*vVBk;ReYWI}9&-X^Bs!XOoW zn*Wem29&4@pobU>l}CsL!-j=bD984~@8SZ)u{3Wc(mv^uiKocm1gLY-rhilZ_gxKS z^F#u{@56bXZKIijOZTlK{OiEiT(~=}_*Kd=iQp$EHwz`~NOJ@w_FuY|Sr)RFfA0T< zxOw=u#DR<5>8E38m9V`8zKAs;W+kQC4&L@XQ21WZT)vyT09(QA90=qP&zPhrET@A-jGeX-Gf%s&$uWp0#Rq4IB* z0>lUwE$nf*;ftUu`!fYl75>cvCnkbK;^AOAJL0}xj(Q{eh#&#Xpfuttp4iWi=zOvW zDfRAF{$9%QrTx8MmSw!Gf1*Y{?Bmj3qm8t|wlu?EdykKBt<(W1{b{azAUf*Kn`ac+ z(&BnZ7S^@K(a=?!8|<9u)B}pp?qzc3@PgNEZ}?b9q?vV4U$R8?kNmbie72O?iiHQK z6xh(kFy)zKI9am}aVyQ1b#U$8P0xpP_lbUe9Y;5hZhJGF+Bky{~n5{ zV3vQnr~#@prw{2|n^OEIU;*2?#3k{Pqr>qky}9T2)TgpboAu2~3F+U;-(-9QllE3Z zUnyV{PQU97&-l0u*0tDW3!B?-h`<5wXelDHk*T}GyH9}t`IFvIKOx?z)PzL-lkcNX zPy~$vGt;6`jx`@*BVOMdW8oU~WC^^v|hab z`FB1xjb5pQV)sgQBl+FOEyg z-Bd)XdY~~0Llb(cJ4dlg0)YwBnogmx54dHj?4~8%yVe)@Ki_r3SaC?^dcSK;jHH^* zWXKS}pTY4XU;|~WDjQ6QB7BlL`{ ze?ph`FQejA+9hrJAHj@Vr3~>Qx!;^ZU&**8pXlsj!i>2dY0}29)CB5*`Yfuz@TXx{ z+z-Sp;nl6x&xt_GPm9LA`~x`x#P<}_#CE;Lf&FQOgM@jwe|<5vuniko1xq*ayKV^P z-S_XIj;H5{>-CNGbsT#f5E6eD=k_PzzT4jA>i!*rVV`UdLaaQa+TK0s*Y7Os-zxT# z*?(t{hD53FTi3m{{h`Ev1Y{dpjC})7&!)Fdw|}zTPp-XgK69m%iY-jnVs=aT%NU(! zK`-r5O1M;)z8k>*e*o1$D!&AQOaf>{F{2+NbwK~bAQCHDSwkLBE*Pw>B#|c)8s2k| zH-V|`UR;=L+;j&Tb7HK1;O>c@K3CIN`T_P}vu6nHXs=Ui!_j3L_p7G7DXfroLIhT7 zOJWsKR8tCt=E+DZ@NX;xoX&zTS1@a!tc5&+Ke=2r02vH=ED1y&5Nn`9fc_+V02w|s z4?7|PX=FxgvgJbOj>Z2`vtA|RRO2eZ8%@Nq2Pb`$n*Qgow21p!gg%9^(L1OC=dds&+ z(*S_RZ0exn2%z83(of%V=qAus=fYAChG4zajS2vI_H1GJ1OJtS&wxz+-V+VDBHl#~ zP5KXxVfc~pEqJNt9cl)9aRZ17iMZ>O$3fF-c6#r zB7v|F5g6o61-xhuC8=%0>6Jeh!_68vG7Nhrd_JcWU{rYQvl568x6M}qC}&2{W4MSt zz@W#>AU2`#14FPv3SdiwThmqzO!cXe(0*@Sj(S{$g5i!wA$U> z9%-M(HjD@$M|8N0azm;>Y!?U`X~C({EolB=9M&=-;e$s3&>5b|nqURgU#1cuG?8x| z#25>=VkE+#gyNTn#A==LgUV^FG6p+|g^1+_RRZ1G>g@dRT2If+%*+r12wmuBtqa$> z{B!5d-JkLM=dQ!)HD3S#AOJ~3K~y1tKmwsNLlM~Jt*Zwy1iSv|MIx|_G0&`G3@gxQ zQ}6#+pPJhI?)rDPzq`Jg-y|bw&BU5Vdtm`tXFc0u@3{=11@S z^an1>{`blagw^!VimVF)HBu~~6zbk!8%{wW zN~+QLFrRNe>I9|Yd+aMd&K30_ET;o#MNNSz3Mk9q(Fr8@^Vk%F2?l}s359eED`aCu zJJ}4PsgJCHDC;gAXhZlY%f3uChb7TwT9QFmsW$S++}CvXG;S6|31m`0ocfAz`iszl z1HEd~o8 z7!Su6dWRfrE#KH0|5el7%5l(f2*Kk0KSTgI6aaN@b>8^hL{HZYkmp*Nnla8ToC5&0 zVlNm1=)wf$ypRX3hqL8bO!QB1kH(`%yLNyK5%ee{)sM{uoPtQ~yX#YRb*r~Q1m)Ky ze=2zMD7`0hfT~siJ-0Agwax@`hn%747vKBln~x6LF9cKg55Iqz!64MzYPCly> zDQ6;3R#8BRp5kLOfOHL1psXDk=^_2Hu6~UQ5rhar(Ua24osV1OPbGhpF8A#fPz8O2 z_d_PM2*6BhO@Te_(<1-AEOYBZ0kx9~lKt`bTJDWZk{h(lhP0s1vKc_EfSw8fomkMp zagg?0P!?=#JQ44h8=9jC4D(ujHVUXIfrUWvw@~INd3ew>oeK?J6EjO7friTth`}1p zl}{}B2U}Y~0ZsUOuhFjfv;1xc0AbVXLG*xrMq|a+GcTM4QySiF00eB>$WCpnPEjCs ziRLBRr^6ooebgYD+QF1`e4e8)XZ@$|eRQPJovv62W+u=|6#|+39_-b`9tG?n7hO_8 zJsS@U%9*y0n#><7f#``;J3(Rhn9QG|A$f}WebB0WDm0KTf_S(E4^Q+4Fj+76s?rE) z49QCMqu8&ZBS`#sln{k%fagxmkrk+xCuf3?Dt@f|kvizH5rLTi6p~R`tN;k&Y*;8% zoj^`u1Oa|hQKJt|vqoI}dC9^b=FaodhwBfCK(typ*=<^Engsqt6c)h+;wQ2!8s4cb z3rR2YVOF*M|JRJl)#b+STKq``sWbAaZ~ob~rAN zZ*4sQ0QGzVZ+YC!v)e{gH3wF06PVa%xS3B+ZDN=F>gx5WskQY?RR#1a=OFIFp3aAk zMduHFdgREF-xRjxk82z0V;pj$v#}8SKDnY`O^{YW(B>_-O(=$wzpTNR_(T^#mEMn% z@(L>Mj}SaXGJw=_Adw7<>FzB@R8HoPH%09jAcGE1^N#0e6f1%}$t1Rn$q61#4#J{R zLB+6lY@RBGL@z~-A!Nv)oK7Gc{$wS7YzQPJP=R?veHrpt2qYGt2@RB@)gPdMQhFn* zQu>3LzLKTG@ux_j#YFt`rQV?>j=?%R$H(s4NT4``U?))l zIW8ywn%%kqKj{GSpaLp4;8v1iL(%oll*D&V5i>`PEkZ^l~7U{#vhjou0 zcS%8H?jiMA#xKXz;et+D)9eNGcyT@%Mmd0>>1hpnF(@sDl4v>-X|LxL8PX~g3*c0H zE^EXg)F^>MVzObbU{ygoTtuJ(-^~0Gd9Z?*%u#Vn2on5piewlsA3AQfq197T092dv zT%mg?@x>dxm_JE%p$-~Ciu~zTFhqCMlp&%on$9uF$uQ79_r!2|@`frDkiwrcxF4*6 zs|auPhasv$6Z&a9o=Aj01ai#D+Me-W*#ZdogC;b@V2TYr+X(;~>UGQw4h~(TL_GW& z%)*~;eRghmaAK%D^TFA(KPSzy4k4K12G&~7kS4-P=w0`LsR}5)UQGd!H-uTTwS0bU z3ftsqU?PrkeMtb?Q{Ys5?#|U8ibnVS$B}Qo`Sb_Y#&;b*uI3$=gR11(VL3=X+hWLUP}uQX!0J$Wmps>k5vIl2%YK2<$;t08$R*ta1(W6 zU98@dAkG&nTmaELiUbAvYtpv#Bs);|+33BHOMR&nR z04lOC^cVK0eMPrOi0R!Ge{~0gCILkECI?7WKm?kgPnSXB6+;N=)^o9{7o<#kr={@( zAg8w!4G0m`Htng`F#Jl^*8_f%(}1A*q^G2@3Zf~mPH)Ofv&>KeiRN`ekU}7~c^>tAddR!5JvHrm;gkF=+${@259Vc(UbSMZ56M5cl9H8qp}LR0f6|O zgNDlA`e7K50`$Rl)II>viD3ZHoanI_Z>l6vQ={UI=s<#M9v1EkUK; zAyz>5pDmngEtma0U335N`oo8>|15(+*u#$UW!%9!)I+^snat*{{2zrqnY1kbspwX_0>(96GT1p)VI31x4Tf&d)9<%6MZOZ@=Ad!H=ql zR<`wm)OkPv7ywNc6i_USsd+4t_7xaKsELFC`m0;?SrpwC3tC=EwR2GwKt)6MNDX9U zy?kchCup{zP5ChC1qnYI2M95Nyc&dE_1rCw5Q-!{$;QZG&!`8hqcuu;2ZV_f@M7XV zrUQt_X-EcfW=jCb%%8`44bWq*fMx*s6amBoIRu0Xl_F?f5kXEykVu6I9|*hpQz{Z@`^bfxUn#$l~N)=i+buKjqOArEt!lEff|uX$r40oILy^6dNkn2 z_It5UgPa=1kTipeWbFW29@8of9Az&D2t$V0EJWsNRr1_=>vu4aZaNkkYJDq z#8Oe31R2$|>H^4A{8M$(q3CrVO>)OqH^GOoLytrqRzJz^YG;`V6ya&ljTn5P4K3+2 zc~4$PaXQD*krA3tFBA|DB0D1|B1#qX6tnPigM)*(+?@avNB+clJ1WFr5p9f3IjCu^gkLVF?H{B%(3`(6zal3$L}#K07!3yTP6rT$gd>_23EtsN(^S9HPBE zBu{ohAZrs??W^E3n=~<~ZZ)45jcDn$&3s<>gI*$l_Cf&xXR^oI8xK33UoUB4NwJ*le`@-j{y?Grn|kd9*rN52J$CK7^IimtV6U zyVE^Np3lH&_q1v{PfrU4gpPE#x#rL|@@njstrZb@uf$*|e_9Yg5QdGkOt#z`88J+t zeF}WU9jl-Z&y{B#R|W@F1%xqJ-*`Cwc^UXKB;oRJCo2IImvunGeeRfL0L?b^&JE2B zHaOTG;+Bl1q1I>RR!qqE;I!x^|G)p2U;Yd|pj$Y@>|am;r8gA(ynq6#T>x>Yg)OQ$ zE?QPUW0rn%?f)G)Ft;l-UGIE9Q2#|^+YcK5`0amu`@RUl@^0&`b^@))NDMfTD~c!# z+cXeD1r$MC*<-DLHuEP}aTC6eZvPlTnCU#(9zUpn$OjT4NTiNGn^-G>StQ zKztVp?L;6P)#wxuVhKd6sHub-&7i2bDh|jw0U->)Y(lW^=_C)DXBDI-y-5BfyQd>? z7fEjC`tSpJ&g44_1a&K=K9u~rhj%R_BSaulLKX!imorNnI=t24C^yU@W=`~n!%Y-| zf&4kR7!LoL6i_d3I4z%wkB=vw#uITm2jcO>Q>p{%R~1kP0|=ng3ld29M;wCnHo!x} zvvWWszkhD{+6NO$Lvs)FYoLH=^H`~A1Kz>#rlhSJ8adIC z`Xo*;^I(grC&|omQnVwQG-A{>%GEn4U>H2`!Ou-OFE0O)$*+PUfMoiMe@SSkGf!?1 zppOycBo#yyqJv(L1Q0<(p7YWI@|Z%e>CtHsb;-QDUhxB8NU{K;YD0ifWZEw9 z0`N5A6b|aX&@alschh!4!-hud89Tzzhz9vXN=R2gs`xo0dQtH-^`9s=pa625I!P1h zMH=it_-X$wV8);TkmFQ;VsU(NocTku5EDF={w*tjPF=>d{2aw#4hbN5WvF4e+zJ4i z^-naEuMGl#dWXMqJzU^1uCpKXOnkB_wk$sve=G^G?Ez$Me<#O!b8{-6Ur%r1j6@ok zPqHXKwFd}#sYQsoznpjH9?v%(`Si%qPv3j*qoV~eBhey*o)bRClpj<=1)OMF;Nd|9 zebr4->^`=;>=aPZob(Ec$v?%4sH?b>0*Z;~NoXKY3{?M&8VDm6?odr}QIJPNWd!d| zPZDCVNH-8@)RWSZr6^6qh@#mWb(&UdaK=hHIh@R@!~Xy#0FfqoY{`8YKO`%mO{ZYG z3Vyk~(b?OXjf`COUORy*+u&=~KWUK=+rZ>keqC=sB^iWE zGSm6L#VXX=1&}dsEEhWT(Kkol{N8&%dGE-+$1B43ac#?=9l(>5n=!CD5j7BR)hf`A zEvgF=L!9jcFq_h6d6PvzxhjdTozxEsANG%>5$z<`#OW0a4B=hr3~<8*h#-i=fHb8x zO^X78>PZ86sFp7(%5F63pckc$PQjoMHc+sUBQBqzfeJ?1j~PEE{bQ$h>=?gBp3_OVwxHebl(SECd_ z%VIV2vZ!~)dGwS7YiYTM5!gLeLTCfgJRz$B`uxOGr6VJJ1BJ@JaTf+DAS^_T$4@zi zhUY{vv}3k^Z2bP>{rd;U0X{$+Dv2S@@ay}5>|uSe1sqGBNU_8sFe z*Wc0rl6BAIIp+(9zy0(-?!EcZdq4T!(Kicn`_48BXb0KjHt^#{p9dFdg#x|;FZq)Q zqFAg30c5H95hy}ei1g2nrjIYCsvluMdjtB!cS?mti9x6tv{K2F@_IF%)B!3;3j|Un z4923PI{rvwPX4@&|}gkeb_kj#C7_=yPD8T8L|q)O=3u2db;qpE=P z^w+Y{iZMbK&^=_&Bx)cKM8XH!XNka0oZy+z;_hHCZ-$R2h(BYrn+MZiz1NmxF?4x6 z3EvzvmG<`h*~UviY2GSPfHv_Jm56!+%0w z9Q~i)-rM)>k#9czKac!4>rzLMJ%|1=whVuP z-7J0dmQ%I)3l$LG`Dz9bCBSf+4~I-fdn&(0rEh{RvnJ<|rKUYm2*}z>Kp7mM=ozIZ z4Y*kT@KeMSxh(WM1cJy93KWEoY$V3am*kKlehSv~mx`M@6MB?LjQr?#xW!Fp5JD9$ zN{)%3ENb?oOWJ6uWQ>5ulbqIb@R?=UxlV=D@P(qj*0FAs8pYgaiF{`BvP}KR}ywE{vKLkT{@qFbad;kf&nA z^?Y8h6WZL|bxHKA1d!Xa?~5b|HQmmn+btpGkJ1QTwzIg6;#^WG??l1NqzzD1#0dvg82fR^xM@HIgL04}A+g1Vb#OOR`zo;;1 zYBMddlYg#sSiS}YwAbVjw?Msff1~H{zW?LBpM3Pqdxz3MnO*QlS3s%<#3K@On1K&r zUlZ0v!#gd=5aMVo#}Kl5KR$EiPf>~=z2%|?04Wd>6^K4;;ZlZ@i3JnRlvBtTd}~G` zB~5g_M{#O&Dpk_hbxvuLK|~#LZ{b}lc;spGBuhNJ!-)){-KGU$)YKL9?3l&;@mW-j zuZs5rw|A;UWPIM?HVt6~Dd8A{2su=VAkces(<`ErGW^1m9L1zpl1(2@xK{xXik}G9 z{1~Or%pehTDavP=%^#gTR0@qNddU14!P9cD1vQWXAR&YLPsPKk1PTLz-U{DU8#el$ z_4OlwWRJzIw=n|`8t5Q7K(rAfffG5n5_)OLQSNwfgFDA?#A`!?!@=ND8dWb}9v+@; zKm~+WwBr;iAlm2Lxdqs|;-C1@S1z%yF!LPxCsSJ!*fz^hA2EPP2k|3v$Hi<~pUOi( zRuhF>`IqScZNGLf8!d)B?}w&;dgPn;-uuZ;JV0|6GxFFf z#>p_OljbTL8FzU!Mi6GmuskSAB8Yl8IO!c_1c^~T^Gaq+-mA(7@2eg|00rI&nW8Xr zbcPpG$f?%`S&u4&6fX!(Ac0e45UL+!j|VW6BpZlOg!Cc)RAErW)Of-8!H-6o1uep` z$##W428IAZTo2uHk4S_z&-qbsik-TKe6ff5rg-@-KCCKDhB< zoOeH$hkIxIJ_JLIsBu-yFyntR7A%KEGR!9w54%1EQSM`rJ(f(D z1WaiDo%sM^#%v1J$*&6`go~t|LJ8SoXunwokrxe@jvrKY(}*FGKPZPHq6A3Cj}<`x zpGGTwg!t)JhWxY}lQ=9k5U%T?3LwgcVLW#9=)D#r1dE?BwS~bs$sGE;|BMPC>W9bG zgiMcHj@e&7MF1VV|BMQOa3x_pG1eq2p-}-{yS&vQq0?*3C^GLsCp03}0;70{C zII(o9bL++p-u>K(0Gc5HxgI(mx;AR_fFySG9M~=u5U0MV0&#tvDuA#fOwYq_?wpW+ z`2gB!^_MI6IQo8_(|P#Y?|u5-H}Cz^Z>sLWsG;`9P66TKJ_xliACDRcd&3I8`2ejL zo%hk_K12KPB7COInOcEC8Dp8xNs1n+-qZKAb69~k_>4ldoc3_aTvWg zJ>A$CNovu6sQ%HT7fpm=dU6aRxn#19;udC=ZfCsLqNSTmFcA*L5EuE+j7*j8U1iGZc7d-Z?Mkh?sU^+DhP_G!pGoG zx0>`4F3_Y^{m`O#oD+=&K_r0i31}dxfX>7}jO){YR0Wji@8}ooX~K{2fyMFg$rB78 z=>cI3Hh%xg;{9<^jF@O@lFg_WmKv}RUIM6LsaGG+VT|hN*t*f{_alHD1fa{E54IjK zf6xOOn(68JGP9X}IQ%f3S$mEquoqWA>PTp;g3eD(5r1SJo>)}F$^MP-L$f&w&i&5) z(}&v{kACmdBOkr@Pi?Mh0w}*r1%#70urXsE(?UgrkgqUL|Kkr-3KT?L5b7Vv9}Knd zLr5M;AYUythcQv|qd$q!E*@G5hTC{}uPF9&slz!^R0$*tXfzMClT%VlE8!aX`cY~f zBP&QvX4Bv@=}V(u1oUZR5kyXqtP$kCcD^b3F1uK&sseHXQ$nUFtd0<*%OZK|oD8A& z=Q%sZN=RYQey2hpiYG@sC8H`Djjd_8d35r0*OLU|BMGG1&$!%_S1h;d-j8@>%V$yt z&!k2D@Ccwuwt}b_THGBq6woOyK~$3Pn0oJj`|9|Z2|x+NOouY*dG>8mKzpFVhc zOQgY?nwt7QwgyK%KA6O!O>~0xA!6H2{!k^E{eB@O@oZ z{5_wf*ESwre(1_ZNMIFh&# z`Og3VAOJ~3K~xAL5u$gt>z0qb?^9<|J*J8uAc>Q{uB5~2gb2c;J3-0_p};$$RQesz zLi1)Bv|rmFRceAfo)VQsC#4ZYE)Ydw$s|W$5tTp@F?@_`o+GC4OTo}~ht&@fsD-zM z-BT3M$oCBZ{l5HpT&BMGJjI^W%i~*PN(6Qn00aa&p^lnAKmh7ryt3GLaB-Z9p>Z|}XZ)amHu4XzzK#lL zXa20K0Ltvt1i!x13PNQjbUwYA&4LcPgi=T!+mTn$gZJ?5`AbumvX579uV(4hDc4K# zpm!#a+d2J3^zpHyM?N}Ke=O8?^yo+b^qC%n)f|9rr+|1288E0&D24(UgHdW8YZK=| z0TtLNp{f}lrROO@#wE^0pD6puRRK`Z#(oaTu2WO+MFE)MKL-SWs1eNTop-Vi#CvX> zUT&WnMGRr?t3HAVYL7(fN3r_Zl*uM1y557|3jl)XOJf^|oFJz(V&>V8mh+w~te*L* zMbGkk0tk?KfhcnjCJh zS0(_3#}^l0GZfIRQ}HnOp&q>QEIv-<(EV|oP2Yct@?J|56AlN?A`<|bX`YZjJ1haz zaijC}%tUk7|1Ekn;M*Ut0_wy%Ajgp3-}STWpn%@`8s6$_0zlifWn^kEf!;{~3H&JE zw7H3c5-%};T;xuZ5kw$c1JdMI>)zjg?C|0GL!W*6*|A4f3+NRqAa~s{=i{97v!DFr zzc(HZ>_5Ek&5!=6-u1jW`0cY`SdSQ_867xhT@Z+N_7p+;fE<|Tp%%OW!iW1HVx)US z>Z?k$RjgwDz^@_OnQs*Uk_^HMXijc!k)@69M!=Has$h@$wSomw^Yid)=9wqJnK}x*>I8wr#jn=s z0Maw`q4~PdI{`wFu7jfcqpAG@mc*cvhar?C1%$!nsBQ&K3jj$U2rfeaHS!0+r?Fc! zo66Mtq>b-9$@_Oe0ipdoNd%gtN}v`!2pcg>=ri#X4$wfB9DFzd6i^jVQ&YHa@&4(B zVckCdJaL8;P<-pk{R89U<8dK?#?YxQ4_{mAnV37(abrv5!RC5&0NpD08vA-44E8h+ zU2Aag#<9y=@B^!FZ_aDjXIaIgiw zUt?TM%)+Q<1ze_F61& ztAI%RAbciqSD~mwly^o57XBQW@RnHsok0NU3aANgXPQn!47MN)=v(CzZ#^C3M)-sG z5kQ!TA435&*3XqcGd(>s2SCVdaVgLT&COlXz19`bjjhfb4v0nkAIzC+t}Cu25k$Vbmj%x;B8fqC^pSm zaQ(iYe)i)x4}FIY(94RyY7#*1$MyTOq5A!W{re8JX>EtU{q)E;Klu&$%_}vvU{op~ zc73D=^#2g|K0a-xS-$5h)-QJSE@M+7B^-w`PW+>>f}CWs)lG$vL{S^Hh~|!wLm&|Z zElMgZp(02jkz1jO`$pXXstk&$)s&c-LMt^pQWrb)P2y2?af^$u+q5Stl#W%SQTn?0 zSN1vQJkRq!?`u0DRW-Y|AwWpd(<46pJ>PTA_n-%j0*F;%xl7m#gU%ODK0|qxr_|_Y z*d62b7yf$b5Csk5`&SUi+V+C)zN8|@s(~&Am27&~vJu8+7hIMI@}zok>Bea0c^0&_ z0NP;TrH2(`UZ};GB%%O&90I~E4ZhvLbrF_eRE9NE0JWi<7o_2!I1VcsK`B#e$RS$y zVh@ImPJ@3hM@*ev0U?Cq97P;Jb*3O%0(;t6Qk)=5JB-gnd&GQn3ZDxp7>JS(N)Ue% zDO3E2PP`L_pOw<9iu}1JVmNT){T>P+tiXf^BqtJ;LB!**6H)%@MRghVOd}H^stLW) zc;RyfAnpO(PnS>pbo?Su0{ZQ5yI~uwdlavOjpGts^MkXDdL?qL6EqjI}M1rVnYXOB*=1ia7#N+nLo zC!-3(&nc%f5vt`rd!gW>*=Nk*pyF!)?u6Z2y$7<#>-ExF29#k6fG(aWr~AuOh@Wu| zpp|h;2?hwd@cFx+e;2upmC}iH`IGK5Tmf}61#|$W5czq+FH8mWkC3Y|0WOfEzNN(+ zKNKa{dMq~8zu0l|cKUt%O~=R-1CUTa@4R)rCEcjeYrt$;sWxU8uuKH3?)} zgMZBy>V6bZfd|vilmtucv4|x!f&waiA0^em_DS> z__%Xkv3eM`F2!FVe&UDJXHEG->I2}zGu@5lP*Aq3tQu&k&aBQ@0fn?e zIV7B*c%AHm?XX{V_%n_ik^qXE5Q5K_>I|yql)*&al2;x#6#RJf8~Oq;i2cgQ!*~RJ z`GixzCqn^1i4Z)UHR!|N@FG0qZ2*o?0S)jT7{d?=p#gNG2|&CEI}Tf+Usx2-(Z-2b z%+dur0}AN7t}YlNOn(wN_DNqO;)j9fo!`E9fN_Wmpm7=lVq9tY?R#kFj8F_~uL&TB zgT|?u0*d{#x2flM8ebK^y~~QM=h>~OFT?2LXXx?ix-Zkdrk8$%9QvA`QQ`Fy zKn0P#kq@}yJ9SBy?;o7E{`mF5&EY|3_AxDmxnG4J#q+T#pgiw?p$fwIF?>A(=jU0G z{RkC-d=jjz|9DNqTrG#vinw#h%yjpJ!!IT=YFWZAtsBS3^|3c6lN@Ra&I4UHN zg+cgOAU7InF@1r|An{5l0thW22%TrYIz#YMw!OIa;V<|CmR$fJFn=(Q6{xgI2K0bM z0g(jyB#qe{iUoAE@q$eOHI83+>+{b6K>g)o-Csn0G0K}@pnxVu*~jCgfW}Dy^RMi_ve zKI8~u&k6w1`3y-Q4xk^Re|Qb`qA--(tv>g>O+!DOey7G%kB{-E-RJw6)3@f_YG~MB z_vesI2ZaPa0}UBhcTUsQlqS3qvAfcPwsKoAsR zAZI`W#o>Ykm0Ecld@A_^&QS2uCCjN(Qa*P6R1iqoE*wIa%(Gg6o0rjL!;m9E@D)h0 zz)djTBNJEuOwXCUUq}Ig*iTzx0sZG2s_Y4eEq1hsNHxTY7Vb%i5V0WEK`<-S2^3=Q zr77KMajdC<#lDq8OsF94{1gd096{=1$0~=QAGXxFWNIL}n-Q%}Ao0+t6!V}G!e>Iq zaiEa2f>?D*?vIKf7&4R~5+)F`2!u~)03B%1L3|4Xm*OoR5KyNta=)Bb8)0XTvKlPb zs4Ae9aVCM@>grnTf~dq_M7o6s-PiZ-Z;y{Q_8k|ec|N=kX+ZraJ38LQndUt>H3o5H zAbO7Ru6*wz`>cOzZ|YI+$p;YzAW%REppnSl1owadK)=3w7XftSFOv^1pGE@JLeN*+ z3V>c4!?C}|_BL)|;0SaT4~TuOU}S#ADlb-k-D=NhTKiR|f;tQKQtf*cTG=-&z6$D# zn(a9^T#hLk(WI_98GZ&ghlkf19=}rl2m{FG0b%dUZB77j1!T=TWM$YA3SJLVhanbLb;(d!l+`y>l8Fo#LXbNp#|??Fp>!1q7V-PlN4)l@hh!%K^xw189*Qd z1e7$R>%aiQvTMf#4nb#U$I2vfhEN18T~iiRUCC$|jUZ1=1fc@b!HrJoyf2mz{rCj! z!aEs@L;>csxXy|KVhkDp>QLP!xPxn8d==H^0dX7Xr#2UQW##Dj#8{(hLa#JVd_M7c zFP31R9EaukM$Vt(zy0pOXyf=O${+TE60AO5f4!;W9o(r{7XYfq$)5-T2tyG^rlv;T z>1}!ccKJ$uxgQkJ-d=ZutcU}efg$Kp)zA)?Pxk?SuKq(i6G6WA`Kvxxt|A%n|AXCAu6%?A1TN6y zV$#?FT-5mkvjIN?&~)qI@bpr{E94KUqr8+nqV7`QV-{i3gwD&HLvW&(Fg8$Zxf6bh zk~bFgaNWZRB(_X1RpC!H0*Ue~PRpT|2Shw) zQOsGbpgNN|oIg93kBX`zO(MwX6pI;L14U8bMQbofhn*96C-9@|x=J8WKtP~S1%Xfk z(M!ZVLl?}u8p7i1o@jp2Ix0_Ql^&1?1nT<)YcN@XK?2zUWeyRSF-9jof9uhGD4{;= z>;B~UMd3mBz56b%VDJhI6wssZzWeRTrjF}lQUN(QfYN)Bege=Udp|Yu;iKO77wgmI zD~v~xiII`mR2cyj8!4j#0u$)`-LdttBY!!4`Rv2V$;m$egQ_41Mx`ysz>qUPO#jH~ zpPAfD6%ABs$QGhZ@c8shrhRUH{*R16YtwVSy8YrO`(p!03Lr9}-JQA~EVzsLC7(VY z_&{r&Zk?YV9G-1>&E{!d8T?TdkXu$}$RBs*$qR-cSjs>vI*uoM__o*1A!{9Gzj&eC zVy}UpDh|*gv-ypOj%|-5oEM}!@!SS7;Nq$23gOehW%*`P%#aFVKZIHc_cY)E1)1)# zmSPe>L@rPq%1)M<+{3g-ARIQN4nmsa{CY=I)AfJcQ%bO2MFG|K_H;S=%OfKrj}|xJI0g&?MVQdp8!1Pi zaGQvfzx(cO2A~cGAXb8X#uU&;9j8xEo}PrqE@zN3n#gLhryqT)D46X&;n7-2Zv(E?z6L51zR+ z=hdj;zdHZ*K`6tFh8o_p&3YEYK8gaOhns&OJ?LkcJN67Gf8vLp!2mSO+vSUt7p=Sw z6~*hBb>5(SCm4f_!n$1V&hjToZf1_m7->dXUzL_{mL!q|Te(1`~@Xq){J z5(q0VU`~jGhMPVE_oVI_uyw)Ai-ez)l{VO!qq6W)im=hqix(Gr;atW~`?`PH$H#z< z_Z|Q4-M(?bA5uW|-+kBH!~k@h6i}LdrQQmlo*t%v?vIQ_(u-Y-^$?&43W(KUk$x({ z(&g{C0y=;G2r8h5XPZu+z6$_)iU{H=h z4Q`$$o#dNXd<>^q5XgX3#Xw-0H_eu?&{|qLCw!x3(kreoX&{4?5XN-G&5=VS(4Wzj zwlIj^Nj$0Zh&-h%8U`C0_`{x65R_sF(y1+tU-vIY6$SJbcEALH zz9?e}#sJhp3TPeYfVv1kxE&7#8Qf`(oQOQ?x`JEs0H874Tuo1~3XG|yx4(P)dJ9uP z=UE9B`|QYH&Yx|1c$z()k_f`FAVAPA%AXh8+1*c@&OXgjH{L#>_&p6EbLJU~Fr^iS zf60t*&FRzD+MWKW%Qrv0#wawWox=g>!jD~o?MwSu8el-50)PYDO_$4X1yXGXHvvGK z=mO;)=d0jH)LB*q1Q(ax^7c7RLrd{v^5-W!aRXMlSyi;e$gxA=h>|_eECR?{g<;@3 zZ^2`QW#tc5T0t>+sGRJo{$M}V%Miq|%#+IS^JPfXfaoAhhc*a6;g_)R_0lqCh`Gw_ zXVS?Kgg=WorKqQ1ttu=6gKpg5S@ygnOY(bN22YC@LTK3tyWnR(3WP}-O0cSRja`vR zK|m1p&6K`;ylx+lI23S(Vgk8DCk!FP{u2k_#U25|Pk?{m_fRE9E)W%BW-*4Nh#`97 z%Nf%6_zy`SFV6m~a^$ErmlZzNNoeyXs?vpDSvhL2z*gWq>Inz*%fEoVi;Le11++dP z0E8tNDxi0v1nU?zJ)n9z29`zzy zU%cMY@$fWPKm?$>?8WOaUWx6Npb}#kVhZS^r`2Z^zn2F3%HsD-=4L7m#Jg^_`?Pki z#vW^HYxDE$o#q;<7#M2!F?wKcAb?B-#9r}e;F=N0I5VsS)BbvM_$I5tZu;ESZZE$| z0sVx7#}q(lJm>S&{IWcm3c>;moSYTrDv&pD-Q5M^$`x26ML}gksgc1){pf+c+mU#;)6R) zOah?-I{Sa0ZMuA#9#2mz2qHTuyZa*hwCOUB;gFK227$KUm_SSdmBjLCi5FOP+L}{i z1OoQVP0!uBIzQL$ud8w!>_?w{F1+f+^-m5y%EdjJ&+ueInT)IGZ=c>A9EMi>bP*d~ zxmvrYc{%K?dO#dOd>7TOekh59zwl^ba0&S!oFCQyDOQd?#}5@R1?3rb{wt(hfFs1G z4%uhY{n^ihu7W`~%pkRs#4S{~aAD9yB0daIKtv$OpI<=RnZ1R$0}V?Av+xP~AN^S< z$;b@4!73H{iRHLTCdGI((8nbrq?4QjFJ0l6ftTzDo`JwcWtz;-p#4#Uam`3toNTJZ zI?)bVs+d2lvuh%3gI!y?)@fKhAXgYxQ=_&jOe!GR4fBHxf|eK@uI32Bj+l<)KnXK)aARuoX)R6u#zg17TW`px;BXRz?T1bOvKl#^KTs^CwYL=Yb+jMGj- z9Lujbb-CiI{c~wQ1i}Ma&CsJl`2+gLpfrtUz8;3^WI4P5yQsQ{fCKIKd$Z7gzlV)@ z$m;OU4tU|`j(tAMo(UcA8B)iZ{ow`rN#D>Z&+JXjec4AO2BA33f&edJKB0g5 z`YxCin5lq%{@V^FUeE)It>1?OV0aESJvB9w#(>tv4a###bK+^q@4)h^AeuM;~D}`_d3r2i#GWyl@ z5k7PURpMw1@#fd1*R;KAsvv`A1(8C@W)~zJ!VfzV&&NP+?igC1eO zlXMvhp-`xJ0>V6!N~qJg#vN&BaIv?#B^5w%lRos@LB^kJ=gedvtiZzbMD{>8J`hIy zRM5w?f^^XhBMh^8#nSz( z1cU7jN4cwOWAUx)4?6yqDWJW*6IT`=G<|gUJV>DP=mY_S{vZkTg zh=M?`;g4zc;GeKks1iSK03ax}K=@E?1oO+dQ;LgUa2FN65Lj@|GRXrD4}c`G5HLL; zsLMPH9&lj+L9+uI)neG94~5VafoUOK_opbuUTo4Q>D-tQMVKMP-h1%JKkN#VFmW+n zxy;i+>|dteuoy(0AcJT)sEQJ@RA9&-5Km-5%RW3g(831_z*JDw2%yi#O%v$Dv;zS21)PDG z2s&_Kv{C_m_ijf^M@L^wdO+p+zgc9siB0h~n7j@4sEaG0egM!2`z5wF7ICmLZLzEC zzx?+4SyDievZJNxEGQtRfv^li2%Y}J?UbozClv;EeZv%OvOt}zt(UFU|jW@Iw-e@y-L1`6m<4j12{ z5w=q-1~jKr^Zqpeh)JMfUCA~?3)+-CRt01cKuQIsn9pvv9A-}@MKC6CIe<2gCjblZ>}T!e0t%nm*?SmA z_A;=Lu&<7@5(~OuUU-C11_5#eh@4LEEbh?LPwj%vR1^GI!+vX&P~_qq!ZY;&Y>K;< z!3!b~QN$UJL9!qHuuI4yQwCi#ItfFn5`w3?237}&^>rYa%w#hByP`=VPm~cSz_CLg zM57*iA%^&YH&{YRnS~hCU@5f6xCDZiw1Mv7N%d3 zMmZ5Z-uFqrqZbDeP5ktAGXRz&>QXFolCcWf*c>37^|I{Sz7B!N%^u{U@>iA}L1{rzA5`f_1+ z_XS=u-7VDw&>Q#QO&_{Y%FRG5Yk_g7mG- z4R4%{_`12DN(YFcD87}4Laf1^%f*BFpv&2|`Zd63kUfUya=FUn=PC-QQUJO6e1 z8iEncwM zYZ(FLqCx8b5(ZsiI<5(A$ z!C(`EN3_;EL^wy}5&sAP6pNJ^fMPNDo()!mJ$TS^76uVx6OnTL$)=Ca^9Pns z(9oCZ+ke&3^yw}(#ehHH)L8h#&FJm#%O6D048?P76|x^g?d4sxv&!wu94~e{5w0nr0YU;?ah} z`jKKs;)m~A*f2z=PM;|wh^F@0;RG@#o{Poc(ji~m#2*tQ zJjeC>$RDxwW$=n<8B4Gv7FG+~$XQ@&D1e=?1h=6<-sq5$2;wJ!-FOIY1-OK;6~<(c zPNDT6cyweCE70Jpx=v0ulw}kvL=_MY7%>Qe3zP&Vfew0!mJC&8Q9w~LpeF(%Zpf~K zq!_wpEWv-Ncn~9QEY-pG26#oC_`6VlxzGS2{lobaX4DA)bp(5&QVJn`0p&_zQApcu^hu)oH^16m{X^%3a- z;YIj8D8U%87B_ksfPM|TU}FqGjt=et(Hln)s-Vf!cfTy({_h=4XFuNMt$AcnNpXW@ zGwg>vW(shma1v$`U8H~JrswC^wD$S=x%u`eBhapSlNq~ZJaZ#!*G6vuAgk}wun+Mg zBv3BTZRY&7KxVbAZF+F?>$d6PVFsX^PU!*V)qD+Q)Y&cb#8d(F408?zbjbI~*(O@@&1fY`y31U59-&)w_*6G174pi}||5_MEZ_hwlg$21cC4Z7}h-U}$nW*(G1 zt}y(AeCsS4MyKhehg@O41H%60s3edJV|{E8Vw^!+D2R1g5X&>`kyMI>mi{xhok8J5 zx$cRYC07)X!x6+A@~DDP_gSnUos1wXJUNKC1VRhiOVNi)4-7Ss7a7FJb9kVQ5s1$6 ztO);EDj<4{TgHHne$FLOWUeQ2Uik;?e(3j=k{qIdp zO?S=tAXGsw@F^6~_jiEI<2;lDT`EMKnzOxqZF+vK-RJYK&COq3)1og9psKC|G z_sgd*?8o{k*!kmbC>C>Wob}1)Jlg8v)`P8^t!-@w2blu8d2|D z41&nuvxBgP0s03mXI7@YT%dlu9%iN2OMV@U5okfD%u+@g_A_>MVAktQdEhHIZa~Kf zY-&cJZ`j+w>^(?Ubdp&F0Hc2@!1F!=Sb9bIG$4MN!csBp1H_hxylTN97vjXQ)nwQ3 z?b>6zfM2eKd4vyy_z^}B@P{Cs-~0XT8Y%ACrhxjS1q1-3Ps+zGBFL_Qe(zn*Vv_j=n}H>WolfLINN63CV? zCgSEz=E$}?Em~03bx7^I?jD1-g1F&TuL@ypABFw|!hlL)6IPzhmUUiXvt>>arJ%{Sl7 z;*2x|dNC=)en3O_u0kbtb=En16-dM$Ob@YAMvPd$q#+zsJmE0eFALN>L*;`%`U&_~ z;HxiTvWWU+F1$8qN08`uS;dcws~_P#2UM3?EMWwM`^?A#m6_~@3Hk{9s0xS>B${Cs z733uoXw{3`?^YWKWKSEaANB+k$r9|MWf160#TfKaCV@WVC0OGGDH%lp9bj)48x;ce z;bGMJ`ug&tp6ly-d+SqE>NQoaZYbEEz7&a!L?Ut!XfHCdN8i)iwNdX_?5&S5F2Pso zo0=}0)fam_6!VoU+O&lJ$*$w?JKCEU|670`C}$9inR@DC%<)vKU@0zOuOwa@!Y z&n-4k0q$lLfIu`C)bJlAfU5GR;NF>e43J?jBcrXht@`3i&aWYsZ20Ezu(Khb69a}7 z3MenVp`Vy-uVNpuv-& zA(1SJF=WeJ2Zfi#Fd*hWCwWwB_$4Y4(k|>{+B#kEqvbUap@&`;&q$>(Y^`dpIf%r&}w4$9}Wh0Ev zU`PctaG2fzLx3MtKr0eJq6Rx7TVU2P#Lqs%8jQUg<0aT}=|aOn)NfS^@d zRj%*tWm;xxYD5801Qd|?So}KD^(cZga!ifwtw%;;G297T?CR?3uU{P5V_$%Hjw>Ba zXMsEqIfTyttmUAW@X!)hB6KkxWRdwSDg>f@!$U#d2aEq8`rv6)Lsnpn zK{Wgty^0At@fY!{Vv!1eEZzmR-s}K3^fpx zVhViTOaZ;Q^pSBu`5lHHl0b2frmgBmbnf6LQ$J9G4HgSO$ypUp-Zp6{Y-focK7jbl zY`ycgJ9mC|FbleJ>KTn_FiDp%ED^rK2Y=|Ix*S7P6cDxVf0*_m>JWl>1gk&~O+_0# zo4%Rr9*X0Dp8Yat4(!&$$(|%N)S-A{Vkm{mEmGhaGi4#ResT>?4n8b}i(iL2;Bt4%QIeSre{S1P|u4+xdd z8Qy%CLqOI=jK&o(p&QRMnhGdlIzVs`^`Zixai)OM4rqg2>FU~G=&)EoFy%aEdO-ID zfKHH1>IV~uL5sd;v8&#ZEIA&Kmk=8M+(=jW!^W(t-AVt|=af!ARL9uoALAbQjD!4DetH}q^H zkDHvIoI4Ivi0<6uf6o`=$<(T*wY47Hg!+pCXxPO!;AOy}l0qgzpj8A37a9eS>it-4 zphML+zm_nP)DYb;1wC|9{g8QFRNBpOP*v?^aS2tEIr6s+p?wVQ0U5j%FH{e9<)Ic! zQY0(C(gV4O%Y1`knM`A`=Ec7X6v08mgnkNyKuE{IVE7;Z!vmm(esh%-WWR@kEQH0E zo}itwL`tm9Lo_OsMK@r!Xn_y;A$ll(5rTN&pSYnTk`f+2{wL7UwGMMj8f1`sqT%c! zFu5>&m3Q6I{ShS4I68;cc6!jVot9|9l((#3*!tMwX9B59k1RK;tTa`nuuL>Z3B` z{4B!d)2VdXVnUCJE|^e2>5-8~T@hKK#rC)d)K!mtGX|g-ekFb9?608Mk`m~DeR%$# zxfOK&{FhXMee_F`K)ejwoitsbio=CJ06^KVTp8V$S<}|qeRG?wYueuj<~Qg3Gjzg- zy$Ul!@E)`P*IHk2qU_g z=PVoi<7xnE79Ww;37Y&7d#BA@3L$v#J$HnX96>IWKr$2v#-h<9#>$MJmRLxD4MY-% zAtoi(6POe_eCwNUSUDC-;E}_7_ncyUF#$fcWDw;E;am;A^GPv*pX&=LNQu|c^~RYb ze?kvLU$RmR>Z&N-+HuJinYqY8wsSPBblrugOe>~-UQwBSb}5KF%I5*`iSFn4vAIAf z*epi07NVz@Kgfv|^FW6OXaMLie;|M?Z7`vL8dr|05~y)y{BuU2GmWT#`muQ)>9e%K zR0TBJ-TmSHa{AGuM_r2>U2y2s4j}0PjmQtCx)vjR8)F@3r{R0L`tf)eQ$Qn(W3dxV z;{5uTIR6X^=&sobV>0NUnF31pm+v$+o&A_^X-FdoG|=-B66nV(z!-ourhwY7uC;6P zn}c(jZ;c6{j~RPPxf%Avx+^#2#^4UrKtn{JhQjOkqjbG$cfcyCGgC>RAvc&n0GVJk zZX|P2@4?F3h=S`6%YA_|8@2kFDWe1YKh+ zW4?rm9s!_3v<1(v)SvNy|G_5D-xTe5l0Q;%?<}esSA^aI-8VK*LqF4~+ z6ps%I0LgSxP<+cggm+m%0HHKWiL#7LX`Iu6W;!jC;(U*bCW~m!8Q#Iy1IliNIngZk zOVQ6^WC1e^M-3%{0v-#M2w15K{s?X|Z2D9Lfe_TZVhTt!;>8LWilBex71(cV08(6N zs|kIE5eQBa!g2UUX+m27WHF)px{oseIUdzNs_$Ct8kw4)?RN!0dubCu4&DcQ#97qe zzmEKw005OGfJPXAMjYiU9khFabr=buf0h`6B(wjG0q8uR4SFiPAZY?U-~JH^^xs@g zIDtApe|2qbZgX=@o12^0w#2Xyufss6@D_XlHBo`u^4WcwKDG7FE98$E^7EJsAa~yI zM~j9LH++Zxbg*^0^&n#qbi$_V9^1!!`1lX#9~^eJ4nY%(c531$UsQ*Gip2^7!2t*e zZig(5Vh~Ts^Wj3+y(pR?95u5JDMt`dBIJ&RK!ypRpm2S}N0hw5Z}Cw5)y&u7dHp3P z|CHF(Fl~YnH~4|nzyfZ`V~GS~KzfRy!pAV* zVMJL#y4r#d2=-X`BV~|JcPa#8>IYk4_q<+<3PLZa%`C&D0y=Y40gw#juvtLh0Re!{ zuo`UqfCSKJRRshU*zqq&0XZBSizlYWM(&rb01}EQ!T?my5mfIeE7#&-7Yvr+%Z{#o zR+X)vh{Q+}bzGYiv(I`o~&-6~#+gyMRazIG2773n@mQOXvhq zyx|gUyB|XQTnZ{9&&A5E3gn6GsTn48g7UykQ1rSC#e7yj6U!N3LrV*YDlubOslZ6` zfQW$}Ii2^TwiV0^!dIb8^4!q*S=E`-B{u9253N~}g5hbHWvqvk zvh@+%kMA%4ccy@zPTrjq3_5+@+{^#~rH}mWn|J1v7$BH?CfH;fxbXwqtdD1~DZft-=#8XL#j)ifHxejk zWJ2NMj^Q^v0HDp*uctS0As!}y#Ke#40zJ#;ay)FTiUhJs9`mV`UMPO(C3fJc>4nok zOLVYi36l=|6;HM8-Rtv(yVe*H%^kRrGB@Sw(U|Eb2i2d+|(8FOrmjs*yZfEeA zL4;81#zF$4rcWiXtA-8`EW6IKpJm!|0vR+z=JJ~= zpjWeJrUrpP0p+h5JMLU((C}xpw&}s?uMf5!oQ7DkwT5Tbz#n{oZBhJJp7K9iILtqd_c8C=B6jV}I4}UY@#XMzb zf#IG7|G`h0q3_gz2Qaa}oT(?KCQuOFgQJMQPs}}fxPy$VS+pps2SkzO;dRmi zx0q4;c$9%b1`7B)GmJeMT5{vPHj+aCE8gfzNwbIn$KyBaFTXklWCM^+|B3z)G-2OxKu-MBck-@qiQo)Xhq;f8z=W z3#ze5IT9)NJJM6+{Y0in^z^4Ako~hruG<~`Y z`D4&yzkB)*Lgg?9J;6VoK60ALpVMX$hF0{}B!f_iJ@9HOE5k~=*@jZ7u#0OI&nxP& z{Q)Rj=hu9`Tl1RJ4|m}ijWmB}3D+*{YDo&9tZ<}fcopWh4AQL}` zpdya^;F>$0<1^5UhI)%iu%dZknSH#pkDXKYmn3DJGTyk5EaE1$#Ecn@Lk;+(2taM7 zkVMLBuKM7X53YkPz$6cj1bG(t8F_@!OLCNHlS^Kcz~P{8pd$~{(U9Gtr%=nVYK#5g zW*BN9VlYLg*y#X{FQJDRfVdX~(bK;t-}(m5Uc+WS=plrVt_S4C1Ow6n(rCf&QCn7I zVCz`h=~UnGMO$*5xXDzdCIg3Bepa=Tt3;3(NYwaJ7z`xxhoBEUe}iwL3s$8K_N|pa zOaPs^z!lJiF$kHDP3?`I`Sx2=1dUoOpg!n=)iVVI(grS^_K$!KeQcd}QX^Ah6?FtA z61z4w>XjO-Tz>cZ^~Eu?eC|6O1fY>LHt(4LYWlSBf*U)GEP$Z9q=W!K{Y(M<1$gu^ z+Rz{4Z%%$ZIXN>~0s!Gk*mkKvPfAv0@1F}($h3#{xr(9rob7XK^FGbDc2)EHoc^tB zmGkk1l6oZ!H4xJ)kKI{&J`nH+2cB#AJ~Mo}x!U}5&OKB0#AyzX?*M>y3}+@8H<$!k zZC~|%JvcbMIXpZccULMP_T4q{Q_BG=)-J#f;m}V}ywM2@MxSLo`VgdzFAkt!+`4qS z^vVTyu56NGwlFE(o(kzBy=UrwiOC<{iC=yte`s(g9ENoX`0@87X`?i0JyFOl9X#p> z1oA;Z(7<6_#K7Z*DHJiFN*HCBMmm*op7N!9)XS#fALx34ED@$O5CS_ts* zK^?6hreOR5YG?7P%Om|BC*y;N?s19?G5*&lbRUiLkQhs3gdkGfA&=#=DvnY{&tNmm zC#x{_zsDg<0p@MvCJ-s0-~6jA!ECe8XR3HWE8GLRu+sS1#MozJ6HK4H2f1V4RuMqs zqpSowej;6d^bP>Xk)8l>Os%KOj$^S{1%SZl`Codw@C%{_`^Vqj>DZeF}ifgr`+ z5kUYwXllB=`$7>EA^mZ;`yhcvP^#vX0W=gb7Q8ej~uP&o>1Hr}Zz<}P3vmbC#W`--q1dF!J3 z;=4uusI9OW2m{Kwf6|%C_+6>c>Z+EC`d7c69^4$fIox{Aov+LtV}IaTbpqvTNT6cT zR)Q%Ow21gA#_@d-K*PXdxR%k21{3H~Ty1_`db2gt=Alq!8<^K-QR{(1`URU?Iyus;3WFcS!&e6|-5&H0T-?$zIY`ENiQ)x4 znFRZDPEP8K{EhQ_8ZzMZPn1t^x}Izp`ba(`7GQ+(+YEcS`Le*CyznP2tz& zSfLYuM305)ys2(!XRKDVhAPP71GTXSufl{AM1f>Sl|X1whgA$hHv)h@KQJ*78*6N2 z8fawd+ix#Q1=OtyAXGpn%BX-C6R>o;zy4kXgiLH*Ex};*eWc&f_5Q}jZ3K|Gj4{>I z@!+ROtFHRR|C}yIMyPoox!=;!boQ$kFJAm%muJz#p?Jn1CWNR2iyZmr@~_T*DrzrE zO2lZOESEhqLnWLQgk)7Fiy+;wM7O@adL#a@A};Il`CuD@wv!!x`6^9S(p%MgP;()rem|Ej ze&kOI*Clw6KJAU*dyXKTLkRhSX0o10=x_FbBFv{&Vdw*CDuLRNK&lZf6wp!gGKLIf ztyDl0pZ~UZ@jhe2USs3L$jJRqYD@uv34Oe~`r z24SwM0~MZDrH|h-+ulavRc_EC03QOk8+bj4MDobS8qB9)KKU1IenVeuKA;WA9TX} zpt7>1%1}fwefanx@4#mpW`=UP0*v}70CHywHFFOOGlD<+>3_Ku{o|%tM0b8CzT{uk zRz1bI@8ERnbnE8up#IpdaezI!SK=pUW00u14l(+0`NK6&(WZU)8_Yxp>w?BPx}_eM zxzCk@KTEZ z>j5)FEQK{1)l~F8A+K0)@_1!QMi5GIF+`LCD@u2&fT`NNH-A6Hp6r)|(vH`hm`@h6 z5J<((*S`@Z7+(id?((cu+~gU5t7j3Spd%;xzWuOlJ&K`LVAuug`^7O4H-=Z61+@$Kj9k_V#Qr0HxDq2x%SZ2LL_YW-!5% z@RPfQAGnJ#DHPD5Uo|x~)eWiZ@H7d%`y3az*q;XJgM}Arp8{28-vdC|ArAtG{de#G znR9JT(>{Q|t!fvH`tj5T!$ORKq>uvwp&MP`1e#I%UfCKwuzi6?I?ywGt9^)3XvZ+3 zDcx`6^ZwT9KTS_hi#~h}#Jv8i&vuIZLFy-NF@VI57kg7(AV>#-EaRY&JeP!~JY3BP znvHkKo+Xt)%HXr1;>VCGs97EYHN<^najU(VSR|y6@ml4h0tn8kFN^*#6R-c^$$Ey1^Jw+52PAF z=m7~CR8;{f>+mZT1iCoU+q(#j^hkH#huDQz=YT9}h@*YS4@^x#oET31;57@7GY%N# zu_&O(SZwN8*T(z3@Ar$m)~+u09alCsnmT?8RU0Uv+W?@*{a7p(sfR_2yG#M?5`iH7 z8S%s3{y+eFGW1bX)31a}O%IAiEXh_E`92V7h~7`BL@v;q0SJRvU7C;mSN$_MO{hUC z>jwazLZM13G%aJ$W|$kwG~Dxo4KWLVvZmn4)|~#SKJ;9r`9%&iHn?(NE$4PVNP^?b zKJ#yG&Le=l`$Y}=T2A>$d@KOO^^XNWD1FRTQ?7uDaTz?egtgJRW&;USwDJeQ61P=b zmXFk#pP=Zz3lQ2QcOMtH`zl8ot3h2Dl^_Nu?P*~_6UWbt$VOr+* zFxQOEP6kUK4i^v{i3~q#1GmQT_ka>msfi{%P888%26f??0=j|Q>^2T@1(fon{Fdm9 z6mCnT61)MHVNXsTVMT|eEu^afhX^64%Tn~lUWtqo3}=FnDUN)ofSd%Pgq1)V2! zt1!zXw7QOZvFauU2T)fpE0LzwN4onyVbZ2sodOzF1a$~_j~;SI0?g&YDea`C9g z<1&g{tiEz?w%%&pWHs1)@wLK-RasbSS!uMR)M0>}H~?q|^bHq3MXUE?X@udU7>6W3 zJWxz>XUSG*0b9%qVMb-?W!Q9(DTk8HvKZqcNOhnMnPg$1(6SXiLjUlmXmu$8&sGIg z<$>+^0mhJ1i4@2o`03B^HocxWrBe}xw+=ZMa3nE<=vmNd3j@w<@OXII%mVoMl>{GU zf8Ed9=N@%uG$jI@Loz;9WT-l=I>-hku84e$E z-ouIlI(l>kU}NUei&UVaRTNM?0BB@y?|9$8Im*WXK%-Rw1nck@Fb5irE2DWlH3A+` zzlb@MT`&ieKl0& zzj(m_^nw!z0kq3Yu#qQqzq))^v8Yl1>}E^byR}CSOV|*@kM}vLh-DVM{66g#dudwx z+Vu2X`&JDA@ggiYgIlUOGNs*U4mFr#ir`F(O|TLuAbbfg2v}w5fX#@PRS*riY5jeM z{2wxZF!(U%a%KWagZ<<`tMh>aG}ziYIK5O=nt>2pCzsX&n9Z`bCO#ws~F06Kt zh#Uha8W0qA!DzIJ8MEkGf)|x$hCq%BM$}a8=B@MprWf;n#3FRJXt?EnC zhX{mWg`R2($gICC1Og4?9dH6uGN}~QT+UM&k~oQ!FT_{JL&}94SVldiqYt!zZF!hc zOo@fk6u$Wb@|d8)ADBqwv&<=VUyJ?gNT87Il#U3Kw;+d~JhL*0@Pmqo`dzxO>eITG z!D=uXiyn~u_%_vqKFSDWi-oT0LBmB<1|SD`&=aGhA2I-07BR*ft&hf_Vf(xQ1q4Hi`xQXDFl`8>RzoM`aX5Xx_V!!zo10px zmI7)J;j9cmIY5wvP(#)-3`7DbtGrY%NNIub>E{M~6_m+mXn@V|r{qr_I$^oMs#gyL zT=8OE;P77$4i0X%9^Bmgz`cL|*mV%Az*r3iPZBr9V$rU3Y%@UO%_Ptgwc`!0cjBt~ zV{jN5!E09XSX56Xjl|Na!JA&xAmf&FvxPtVqEFHs^$D9BsfzOxuEHMbil^w9A(*^i zN@q@KA&u2RDg6}tLIy18dtPsd^B@F=BfVZE1$xy`djWt_vz@wbfL5oO) z_gJIDur$gfGV+!VM@@*y6fI;c#hj*FtwAYev8(l063B;yvd#l(UOAD-6p&Jb0f3HL zCK1(LR4akT5kTqn*u;3_Pt&$t_zD3;c^bITE)>uRp4=I;tfev}!FmM%$RQL^S5H^H zqvMXFr2~8OFo<|8g6m=M*E#O|`tnl-AW%SnAgHExF?oLXNq_o2bitlJc_LDP#AzNd zfVQiNAMW}9ehM%VUD}@l0{yd#3aFt3sn9-c?baOJ2J;uH0!T_6T*6=kngIq;JqEKt zZqox2%kSBORROX0S%S}y9Q(0}A9MG@gb!NKJMkhhrl_y3W_+t5-S3=lorXw`>4VdQ zfyb{=K<2iE+&In4nv4O6_#+;Q&fyv;ZWTY`4QsG?90>%s9+VnNsk#*21Z(VkncEkN z58a%U4R|qwNX;;LW$Tpy3fm1J1vyFK`Gh?-4)L`Nn+EcL?wMsm2W%fEMF2XC222RC z5=@96NYTOH@SR0NPWd5%CZ+~XQIt>bF zbAEF$(C{Yu2Zx^7lVFrb{gcNp*yN9b8uM#K3x7xmEyZCH@EoEdNWt+qAdL!W$uRAo zD$KE!U^WG0Nasg<*qpR(V$@)d`7vDPg5a;Hz1~WSzPrr!@lb{HAb?y;ZP0mK7%&$u@RQYfXYt@B+8|AOV9pob?K%55+cKtAA4 z#%bxr(>RdEujwHD5Jg(Z^omd*c|)2hgrvbk#hA~^ARj0obu%9Rpa%aZYL;WkV6sBwH^j{^uA@DZ+nrWk-G%pjn$$bSZr zyWn&|@B&$p2z@tryB5Mw!Q^@k8%fNr#ip`62eosU0xD z(2hs*wuP?2Dww-7BwAV?hJS(d>u&lvC&(sDs)DpaGTQJDd=xgQVhz5&0w!g2$6m zmm>UrYRc0^Wm5zBW%!sN5bT&Cf-)I-${i<=ut}xyFK8r(XqAiabiv1(Mx~f$ZP}v+ za{3ZJ{t(T0pE?nZ2=azjC4mq@ZB_*YBB+t4LZ87NSfv8`_ISE}1KL(G1W-3wK%>-;W`I(81m~ z`Dp`#51hA9l2x}$?tdBETL%DjwRAju0po_CdtN-3cTuyoJRt0T?NTqkun+d&v(x}W z2xgvV^jmZ7TKoLm{H^(@<>INb3kHaBqXdFR7g|76iLuvEE~oUyvhM0HQbvz~K#K7L z5-0~#&_j9t;sD|g_m+O}U|T2+5z}P7!eP6duPjA9`_~Bs$P%c-CK2UzC{5iBk zj*n7vu}>I+xDhSX4k#RR{HH2@Fncw~2Z9(S@ZME$Nf9z;#82(Q%M!dH$AFr7w~K#f z+Re4lvn+e=QuPpQ0u%)u_PoRkf?+dDl`Eh?rS)^8N;Axp()oVr)x!g@pTU0iSNTAW z_wWF#&U8wZ215p2X^nQZXlWg`#rP;-Lhe6MRy^OxkQ5S0VyXs8`EbfGb4m^E0egnp zR7jl=u?XAdFu}u*TxecuWPv)XQjH;OQ1%E8`7Gf;2p}i?g<=|!J!v1q0wC~$@w!aEhHZZW$#V|8O>IbSYY{FCV1z5=i{y5$0gua(MUo?XG&iGbRYlAGH&0!?a z;PkNGP#rz^EZXcJ8+{~$#FrK0$1Z=U=u%o>@EPC2SmJICUd?D0RhXHwVXMF@E3RhS zXZ)CY(p@6en!R~juJAGf8c0<$NSVHpP+ND~v$oIu(NfX9L$u?Ke4 zJ_t14eIIuxs053_MV{(icq+g!Rvv>pc)A#5Jddy{%2I-XpyCSXj^noYVizM&{mGLA zpmJ}I1Q0~BmK{AOuOD&SlI6e3zHt9bYyuQeZ*NP-*GpGZ_fB1YCy>b)tb+2a9&T+#0u8qQ4@l$) zxN|l6WAmRGfnEb3v+t$)Kcep?hM*;Ycsq=aWr$vSkm@jw5=zzxR_LEf7pO`P%-jR3 z!5_RK0g=iGAV!`j_1y7n>C5m-e$J1K-tYnsQ5A{K7CKdHf!)9b(gnGifwqoQ=g$T8!*aj7EY-X(VV(0ssW5VY2JI2qFggJ-QV^z6>o} z*zTBObQoYEB#sF}%Uly$h=7Cwh}OD7WC(dJtuYQZ91rsOcwuH)Oa&VV5w|J;F%CuOooQEQ?^{<`i^e<7iCyKNSFibuJr#@c2&p%AKY=rUI&8 zyxzOmd*x(D&ut!&$Ro-q%6_AT0my#aqV(K-Y;0l*0d%LS<6%~U=lQ+_5M~51`oM&= zwP9a)#os@Dfsn$Ow(lu}tW*q&K*mSr(EgumES5J{gI9G6ye$AtGoFQI?93c|{Z z-nnyYH;4adpuLle`&L(zxqLCO+BQEuJ%}x^uUm(Qr3X}vKUM-2tKvs8NOZw$wH7^v z>wKta_Tb~n#|ln@$x2JvQh~jKJXCz~#S3#a-ac`tB8YFc<0TuOKNjE$C_r%0tyqzv zhyp!<8$tx#P>+xLaU+$dh*6I`MO`f??MZpP?E@$Ytv6*L37Z{68XshwK}T-hq6w zF~}*%>N;ry@kB&0o6pz)L1Ks~*^i@$5>_`5XilSu^xCUpJ#Ef0DGgP`V-s-(;J@Us}A>A`BRiua}5G<1gREtQJMIOOIN6h z1OfoDIt=#044OYwbWAd7y{}`6rD`M+{Ao7B%4&K)bUZZ5YcHkO1sB_2Ds3#vU4?{s z$fgfqBoBvBp!&6A4-X|w!S*{{Qspc1bOS@D&eJL`$>ZoB4FHl6>?I#sqmI?@#e86h zrx;R%Jmeq-*e?Mf4ll%L9iB#o{K~#W2AXd+38c}=y2dpR-yFTiD=x3sYkpN}q;sQ+ z*J7HoJ%)pd5<$8`AogAK4@m;eN(Dp`XoX%d1TFYuYr}W*3TzA%(1md`5Aou+5JCpA ztPsr6_uhypfuI9#Dj*wx9B328V)x7GuBN7@lX88Y0qFXoV3vM(+Nv9vy z!PY*gPM<3J2M2s$1_)FTD4>4_0J#fQ9x8xl+zm6P_OUA{O`&mQIhUEusdAvF5!IHISo zo4xgYQT`;R07y|l@Sy^ra!kmY{`WgT0;Rd!aV%c%>Fv6`(Qz_e=7&@HoeUUST==Ox^b(3xde|$-(=a@?c*vv^G5s^%tYjPF=jXlXqpb zQ0D4Ew4gT!hc`C|Z!!gxtH2K#&=t?hhv<7*zF_B%{DS=>y6gRZ=(fK&j9gdpAwJM3i$0s!GA zDx(dALxUhvB#`Ht#t!vk5N zC8kzdImW%*5XJ*ReO5srVL+qnTq%H{1RHXz^Z_~KHZrRL0iaxNC!dddv`iq-3I{PZ zhuOQq&1wn=0Ay;Qo!96e@uq%JQ8&C8Q}-{5Rco*~w!o6-uneOkgyt$&SXDPQiZ9c7 z7RWJ@^7@6VYW)=^0$J)Wlt9?!3UG-NAPT`}FL^G!hr*O=_q=G2l1Gu1y{0S(D&bprQ z@n!ZZMVQko0-S5$r}`trn_{vt=CgP}q<}K&T9{J{$r6k@@!ASC-$4Rhq$7oAP_wB@2K^DBWjJx$>WyIyTZ& zZh^>o(7TvU-|0yATP}s+)b!%XmW|%U{{u!5IeWeW#FYO1%L&L^eAER1`W14A__NRL zcKSBqCaEoJi`+gj6jSaTi24hKXY(!vvs-^_%nF( z=CGc9R$)J*0rXk`sq@XU8OFcFe`^OIqw=R{;SYVXgl|FI$`BJkOS}!=Y$p6vpeJb5 zP(Vh7`f*ire`w~1BZ%e=UFa+)u?xm8mxiMr8hHkf8JFQ9{ym^m)~UExXvNP0-tS_+ zPoad|`AwKBqKOm)fMMoFB9Vbxs$PBp)rplD9}t8RNr`TS#dI0ej0y;HIQ(D)0fJ~j zKH#TNL{$Q1Xi?otAY=mey}Tm7P$AI3z`!aVHWk+eD^(B;5t(I}kH4pq1F071CjE!C#Rq}w2_i+VuyzlsN2t!_&q`ji-8 z*o$$3Oz1}^dPo7mSNCZE(LnUJ*>=Yx%8=9wzp!F#s8pKCl|Tt)Eq4d4q0bE;2R_&; zRMS6P0~OG8Zm3>qHE^WN*g`vqP8hUd^L`|Nl=hc=3{fjAo(urTKsdkVia2D*-qjgK zU0pG-+J10){vb>t4zmL6=3vxq?|k9NGheW%-S`p)keT+weW0CUF>XGk`&_IO;-_fU zKcW@SO0T$KxDX#p(3$79GXTY9u5cxJ(0tH3^eiM2Uw2mqfLyf+#PH){?_6L+hdqQN zPuM)&&iB3OOT6v1Aa1DRxj+yl3pV?Q7il!EgCVQf#qwe)23MRhsSr&Q1}F9@%qPw| zGZ;pH$_Wk-cBeEE+KNBKUW_nv`h*68;2+*}4+zwt6O=+tq$nVto`C3ky9Xq1xrahp zg$1-Kj|x_Uk5ZelKMN=`t1$tfjL$lah%?djue9MnG%6qtAbt|;3<1a@frv{Vmdoie zaE-@T#`nh1gH{itLN4^TXax0r5h;J7_>Oq*001BWNklkm|Jl-Ur$+@)Yyu+fyB?gZ-&pKzY5M5lcX1gkPZwV?W&4OBIoP|GCte>5l&d;HEQI0&TLqU>0vJqcr2?DC9#o~2KD1*$lyE*zp0_Yr} z#0=SJwrZbb#o(c&j~zbCt}q0Z$w!n|U}6DP-Mfg2ndh+3L?Zl@oFFHKHY@b;r|_%< zy2VcYhPG=!_5iIHe@OU$AFZ37`*s`emoUn-9L@ILIT+V1YI!4#_u+o zT5#?e4`VRKfC;qGa_7#5>H$&9zNe?YtGBDCr|E3R*@s^}-(@Oj=HripN2V};=+UDd z$KN$|WJwt9Qvq2QPIqxEno($SrnHrtoY`U@Y%v_MLab2O%~nxBG99Q!eZ}B`n_O8w zQwWx`q)!9?(A^;1=0c8l-xY?rMK`R91gedneC|+G4-~O0zjdh7xaPW+cO_lz)6j(< z9&BwL9~!afzQgsGvCY*2s%_$nq7=Q_V!mXURSia(o0;#ELq2&Q3Juws-fs0 z!!m4WDj>7#B^XpudM&%e(pMPq!;3Lk084r-A&0Pm5e<9Hy;Do4i_9QYHu9Fbtg;x0 z{D}nSh^6QnkIzX*zbN<_SK{e54uezM;ctFJjV@YIUG=U48k}N42wY$4HTi_vf#?k# zX+u3PAFsp$_?e=Bm;lP8GL`rtZiyB@z`BOole6BWuKmtX>0HB>*JdlaT<6ApMyv{o~yxI2kAS{C2 z93FJ#%;F0GL`{^p_y!w*N`-)ET-_n6%ho%hVW&ng*2p)mlH@+bdS%rmns1Se+usH za0SG#5^?}hD5AOww)Y<94X$5UX&kFiKqP|38GAqiF%i^#eDuOZ?DYVOp#n-f99KGM z>JS!Q%l-8|4|?m!Ij(fUG?SL8vvkRWlLKh1A?BsJ+=oP(0A9n zI+{A%Fb1?g0fbgIeCMv1dFBH@&%xUsVsDd$(iVfo*34F2sURBg4VIf<1eu0xtqCAY z$9)KQFF1kRg({}BK+Q}}{j9nOvJU^)_>=odZf6G_=q>-M9*r7B!==w{u0@^me>yn5 zxyb-DzmzlGXLaLZM>xu_6hM~63W*vq5)IBzu_(XIMxHv=2I}PRgPj1Ha}q&8o;4Pf z4l``dGaclDk6rQ_VHNsV_~Rl0#1)V$Z2CW<1miCeeHg|4_b9dF!vUIlRug#4tPO@C zep^uI_mFk5utn)Scq4}xlz@bK4ExE*<`zHIjtd%xzXlnEIJinb;n)Zx3B=d1%usl7 zww+{;Q@y1lPgck=!I}?^3~AGd9uOkPB7YD*vkZ~5ZTxpsFNpBywOBzur`-n9kW?Dj zKwj(~#eKkm~0*n05lxm?{E z^x>fucB@YHpDh5g^GAs}RPbY6?E+Is!4AkD@_H%=R43{$S%!56$p!)=$c3#iNuHpp zfx^q|7ieF(sJ&%WSkILem^ zG}twe1uslbVJKn_350XdLpjwf5)^{(ll556=0nr3uknELTg6;%C+LDYD`!OG(Oa#p z?a_R`xCZO+(2BpBtL{GADlb(9#d%ewcF{=znZrI(Bo&MCYR@{MiaM2%pV}p-v?H#-z z-g-}PzlT;)#pra3pI=WoWm_zP8}M)`2Lwm1BtGlRy(y zsxZ3(T4zXd-03-a^7d`Ki`oSeDDCK>(ktyaxzUenV^D!%3AWhNvq_-oG zXC`MpK6m#?KTKUa9zA;Wu7d&S)6$bC*;jf%U&-eCa}0y7z41<+u`FD5{_~%QU@)`xKm&@A650$4CK#VtxEdoGda;LHm0}Yg`1Q2IXtw+J4fr|NDou|!T$3RsV z&(#HPwYD)D)&0XT2%y26H`f~S`JGpHz7AR2UsPdLDj;h?X13p}K9N9m7V^l&cxZvq z%~azY#j_ff5MtoLLJCSNsKhGN4}4j*pveG|8Ypb0uG0JuPe7#37j0#D~W6nP>=(@btB}%mfbi*1QZ1oMFefclU94)(WL zbyR%vMg-YlQl?n(T=#CX^{q|BR zSGQ}=->7B^QL*;_a`ryHO{Q7Cr}eIXA>Z0cT4bcG6C6{3Wh+()Xqy3y%e7G@iX6?o zSSSTpagaO_L?J09#8TLihfp^?DyoBHCDYPH^u3_gQW|N=ok&wtquPo5Y8(fk`NQ{o&pF>?5>Djdj>j4{xQ1-hBFcL^@)~)x4auMU9nu)#|WB~*e!s|I6JYOgVbUL472mHnZ zu7#evp1V|DhKn{o<$W&OjZ$^Ci#%r+^~gKn%RT69q)$+15cT344|(YVNT7!!ox1=* zS$Jnd5ca}2IZ+=C(mrx2!#fTDlH-R0KqFEI!H?T1rS;jslNS?Do+>{FB~kma*^y}| z!rBoPF;9(qLD(tpXtfTOND%dAL9GE9YBTr<79HgE@wTYJyeNEb zixEU`h5%IHh{Y1!4NFs%h6(o9-6#LsedNN)C$kj4c)jFZ{bjxT_{Fb3{sBXS-ZTEJ zc2y7G6Z<2C(9WF6*A@S0d&XnG2+HNBI`%!!QU!5z}IvEdgY;<*_28GVH34 zE^j>qtX#b+?I2`9^vw-9nEYJZ#1h-*4=o0%(_BGuJkTfF`KNuI58(R;ovxsBQg97J zo$Xh2d<`36(umd%yGsaVl@8KGP^a{PT(bOfIZYq|AWZ>jhfzo5di<4c6)TLDeJP6o0CxOaZsSz)V{h7vke%3*X+wn>?Ge3g$1qhd<54kFmEm*sxk^ zkNO$p&l4CDx=JF*z{emJVuN&mnai*Mon{UsPMxxi8J4w(M7bc3-~7r85(x6^!pGkr zgRHq{Is0RYpEhYibI6Yv{gK=`f;|{J77_^J%cZ}j*+ZWHk#;a2Ien<1M|H|HTjn9= zhH?0zWJPCZ*Bf$ykUr7p_(FdWRS3Ge1`xT*$CB5AQUIynjXZcjRuW~Zp0>pp1{S5Gbp4#4u9YrJ2z#$3H-hIk~P}u`3|e2ICey0BGvPlNa4n zBR`9k(qkxq+K&z3cTa&k(^n=(CdFnv0f;6MQ3p-8PoftM#n|wL{v!aC&nH(h8=0hZ zmg_eOFB@EfxxLBcqFn*~g-}4=q}T0*dTi<9SBD>;oZ|E|+$M7afUpER`O*6`5QPG2 zmiBz8NgwMH7p9)k>e5t@PlYklJ&K^5Hl&Su5I)%~il52@ zgpjgi=yT-Kdhn_iUntL5s1!siK@3Gtv=xCm(UAsR#pPt8tJCLl+|qC<{D`3=mzsZe zn9wqn^~%WPi>Zn3C)5365@&!k4*=*2aLD09gA6(=$ACsBr>AKm5g(U^evY&NP$8f1 zPlEbMuJCbYs||L0L(BzvxeebZJ)jj(KqYpIlF4*>;@riH%O9V7@=hoquQz$K`}lDv z!G8Go$dwBcK*E6jkO~Yb^wA+-7BuIoMW+UGc+E8G)2M$~@c?s3_vCOU(S#pi?M0q+ z4H=YU1w{V{W%=Y9@beEx^2fH40bli1*}vv`z7`v7+q|`~Ft)Hc_GtI~EdbEY@81KU z|4r{??dkrr6F_3Ioo?+|03sX6;cgq^SNJ!f=X0vebBKVR@*o}Ju@H31fgo$+>zddz z^^*b;i1FJ8e{9M}vFBQwjX!5%?D~Y&!WX4*$e3lj0+Ri(kl@cld8(9#eyI5+8(=*A z^J|Si98ucmu!KX?4P)$bsVM7`!9Rv@Blyyc)iEzoIAE~hSx6pKckOlN) zF#vymi%K3}r;JLqGBZ3{o~qOK(-MToMa5uxGNW-2X!O{0`}El% zNuc4O3#|bZDPfKE&>Czshq!?&J!Q5uH0~7O^#eUa6-U7;g)D+QtLE zZx$Z)jBWO8MWYJ0-@Uhohheg0k(RBJi)tV`yGICUiRRt~xMzkVk zk^&M0!Y-K@5vn%pfiZC2CxCDGz5K? zDzM4PAq_zDrB(on^k>pZ6%&mBT5)3=Y-2-uKoUUtLIex4d_(}~OZUx8dV&D-y-+}f zy7zO6WIg`Hzy0v!yN`du%(8#^$#w_c@_&w&KzjR2eTSviAqgB@ldsYt9Xh8&(Lq`X zmOB8x92D)j8)mI$7TM&nI3WpSR*Tk$IWdQ5wdWm0nDzS|@X57m%O}?U4g+M?T&{0J zGi$pG9UTiOfNuH!p-JOiS3nKsvlBqZpmU`?VF!^=PN;#f-Xtdo(Ifj{{2QR~!g(K* zK_ZJRpsePm+0R&i`LA)>VSrXEaLmvTH1RWsbOQPHLQIYQSWhNTn?C&Gob|Cj@TkU@ z!jDJ36V8vOfSNq62G>{vu?(Wr#AX`Er`b8#E^Kl?hY}1boh-iOEAZO4CXp#049#O~ zV?pJW-QT{O-Os|KD|>f4OH)KHIU`74U0(C@uyxd6M%w~9fGsz=I&avEuS%B$kYxt( z_NvQ16{KeZSv8ntLgOxmD#4~zC?fpm?TZ)PFFq;M3w;F;Aj9oIpbK@!9MIe8E3AOd z(k?0xXcGHk7JmRh?&bhmj})M0k_3uGuGhVpBpyli-sCpCH+j?TMgT?f{e{)cMm;YT z5c@&t^u6Ps{`<*Eset~tGJyd4tC^FafcVzC5J3NIAAf!yeh#(oWfx4CJ%`-BDw;WQ zMx#j6L5Pj-)uaz@j?s{_rhjS%7hYm1Rg3`Tm^uc@9e@vdLOE4w2?iA%1(<5w=iZ}! zqy!rDJdcBB?x}cU;ndo~*cg;yckbL7E535Jz-oKiBA9dT$2kH7{Ar?oZ2TeAC=Fzi z3?lXzvThST&|o=1>?ud^EoK?IS=jHTlflFT3^$ zD-EPpE@GPe5fX@!5Y?d`jXTl00}fTbbY<=-6aIj)ApxB z0H8@t0Zop`lVIEh!#a#C=(Ey<9(vru140)lnO;hZ=+!=qoxiz)lR$O;DYtv&_6F5m z`NdLUbz{X_C|t_Ra?PE|Q2f}kQb4OGPOMCz0{ZupPrloO;;Hx(UJd)_?|1$gDDsmf zfc{{k&tdZx*hhzsVdg_Q>qABmm0@#-#Y5ywj?a1>@~7dpg=x^wu^0XEPR_)?@=b&F zjYQBZ!3VU5G&KYt=A`?KMs=x3hQe?jwLYv)OnjP5J1pcv3*>sIpJ(jcHLq$^`0szykme zXcwLtREbtp5k^2nml`32l~~+bl6P5YK`wnI-eprjdK?GG0FehY4FKwXHc%>H+D`A# z6#&qs#m9CBNS+1bIYg+yKmqYShJ5t51W;dLC4&JQ3?K~DaBn2t-lTMfytmW0+4xzE z1fZw=0eOLc4Zef;X@ol3>BePl&kQ2HF#JHs751# z8VGb$@x=hb5g&A%Yovmt2m%=-D=>+m1ORBfEL2a5M-OQ+HKlwXp@6ROJ2HR*{7zWU zXIKHn=sO(svF4t|o0$9&(nmXmK@-s22*XEAF1_2lXODGzoj#K579qBJ+KzO7MB|<4 zvlgVeLyu^JU$vE7DyGL`5QUjS750F4)KUI)z1iBXY*qHVFibHH^5_AoB!1on^xVCR zHQ0VU8-LIl?|dLI;Ie0@dRYJPJF3Li#QK;RTlQ&%nAk~;X1Uq|@I-|S5)udrl;zJ6 z4SAO+!#Xty0NkrKS69Nbn(A%fz0ZpF;1q5(F06o2O zcClZRKSQH$6@W&EECn6Nv2nlJZ(r;b2@V!0aP#Ld)+G; zZ@ypw2sgu)mhOG=m8O6`Kk<1t0LXuG>bu{Y<{VZ`=FY!TJM1SBkoX4;Kuz>d3te=m z2LGpjd+S@*w-t~=@LU+XGiFrx5I`cxkRGONl{apZ zHt@%2f*-k6!JlAY+Po;kjG7`4b;K+J8K=qy;%B@pFY=5B5{#d+Oy^Jx@>3Odjf*g` zhRU{&{~Ce^WRO)~#Z>!U;0I@ZuAQ;NM|p=_ zez5xTp!&Ir1Q1u3brB?m0^h}8J>t=o{Os>+asOsDRGmE|^w=P0QP;Vi0i%!#Fer zboM9(^sWzpBPM%50g=_6PNzZHpc%c0Yhh4=VYj|ih}1U_Kw>1CjOZ2k-2df&{^Jj# z3$_Xh=#M8Rj(_?sRAuY;4~qYaXT5Uh1^ooY5;nhZrRz`x{~Z3|@O#omhhjA7du{4a z+#USBA!9>YK}DKlCN~H*POdn|8tCI4zHo?=#w2BgcmM&EGU@YcxKm%GfO_JI?8xWD zkPv_fUaU+SQ#sZAS;fZ0pPdFUIr?8*ukD$8A^4ju^yt>DvE9l7E~0MUy0f{X>mOD? zwx@(m&C!D26JyLRB~SvO!dmi+t82ci@|Lm1pR0EB$EWw$Rbb)iPD*g@?0QYu!EQLV#a>6_`|#p_ zb9aAx`&ZlBP=9Sp6Z(Pc0qCD#P#ZSXC6Ew7S1krvdt!2X-KPN5XR8u~CQWD^gl4 zlDZ{_Y=t5OYAE1Ab1NSUG<2tK}c2roJmGrFFa)QM+}re1SNj0QW;k@<%go-t-zBLT@wH@6@d&W zz~Eb=oCpXXT5u;t_H&9wkl)fkvKX`MXEps3qiAP5cZvi;6e;s32JhMcLSefC;!TXU zSPTPzlC86?ABy73(*i$M+sNnBy6gP(@p+pEK!E-1 z4FVC>WCVlkexK%YFd0)b>CGx< zz4b^06i{9O2!CJXy6l4`Ge3OyKP7;WJ||9OE`Az3`Cn(JzD_NdQ)TmTt~h5H%jVqN z0lYWy!r!T^4R!U)fWNiRtmqY9tUKK9+)i?QN;SF@nu7NICz8wl;ELg$)B>Q!7Kt{Ki;g# zFNXih353=umO#>emftaM`~p4xYoZSG%lm_leTy*88McuQ0wok<28oSR_>j;O6YpYl z2bDxmOx0R8?Er~HVe4Q?R zGFsGPEP^U*K=V_K3W+}r4iLq)(P)=L09jqI5t2KCKvyJxp5nUuvlka9rbl}Vn6}e9 z+KwxzmllV#HH^1cEDwkx5zk@`hF$n$tbiuZ4%xc!i!WdH_s`EqR76=a?Up7qM?XjE z-oHp@y1UaLf=V}UC+qo0e?5XHR0%+Rc+00Q!#gtd@9r;J0D1xJ`t+~9`pxgA2EH?v zQz<|W(8pLVvh^@`_*2n5EY20NeN_c*wDXf%`1+oI@RK^jd`OM3!)7Izh)K-h{IZfg z@M^{tF!Fs&bcRsaKyiWefxqFAKJW(m#?Y2a87;ILMio}EY8n=S@FhzGDq6)FBj=Tz z5o!vcS8@Y`pS3_NxE2d%#~#hNzIpV`ZXDz2Z`~QAbE)DM;VUwL%sqbAOiKsBA7al? z0BSn-tPG%2oGm|i$~cv<5r`V^HJb#&e~k2j43a=)BO&_mi592dulbb(@&_yn+BWRt zr%qQ`>vP4dg?C%$Jtpu&@QD$Jtd6^rKpx%xc^J~lFw#934Bu+-hnw$~`Vj`SP(Z#` z_@O|0)jVPVA%W;@SSQXSzGmvMCh4M&_uqg3>Od8=y>*us*2#zQaZHCt?VmD#))aPv z+C%PUsE#~eaOQ|uHh5G(kSf5s$O+O16Y&${9Db-jlnW#k5Ccf&v0i!l)aC(oPkb`a zOA075iXPC@$;F{j%>rs~w>+RBVM0$@3TSBZ*sy&J=mG-h<>Og->LLl8p(F5|(YoIE zF5>nkGwJSgP@B0oHjZM5idNPyAtm0C}tQc(cdI3Q0lP3kt)}aE+OiZMI^VL@; zXWvbIS6)W+0EK` zJA;1ErzsZA1CusP5hBE&6n4N&+8`_L87afyOYnRHBga%>PnrO9fcU|lbq#7aK_JYr zr?oK~a*EZK1fp9Q{4fLIwzcQ}SmjZ0=D#oOR-(@zQ4RJjVU15Qv;WLkfTvc6)oOz^ z!%#EOt-YTFuYuu4yDoqTFlGL(CK)6Ugg=%F$e>RP@F4UlVL#hfG5l%^j4U9QMVbQg zi*-|Wfvzc)b1mkWdluCfk%jORYopPhrqLVWHhtpID!lY3HNsjxuJUtDHNHIZC4RLv zeDsqQq6RxHZkS>X_Mq!Qw3AA&E=`c22VCje+TPlNN^Bp06+7Y_Ag2i8HvEXS4zDSoPk0boDxen=PbPcU z-}M#T{RE))>B!5G5j6&F0ceu4p?MVgtRfI7pyA$|8i7jl!;$`%!}B6#u@?X&6_C7V z*cZ78tm*Dv!R-0l$wg24?{I)IhiavYPEo@~siY202_4#x z@u1mb(z?9Jbgq(|Nil#7;{f?&;*Sk+97FWNa@K-Hk$w-724AM=2N`Vt;L2EyR8-FL zr*p*?4iGi!Wzq*4!7*Pf6%3_9m4%+DE4n~unP>RxK#gYc2Stz|k!3~KYKDsQX$l}K z)fx9m%hXmUA{lZktW1Va%@RR1;X~KNND%x_M6LJ)>7TMdP|D6AzkFU33dlNp>bFJ? z<+t!PmOC+cgmK|Z7G*;Iw2?Gw)fh2>~=PG+f&7>I&#WfA9Q-mwY#)4;>%3 z&6eirpufo6>)vqJ7n3X4BP+Q#dLzk|+nGEnAbDdRGwk6vi!)?>2%w3j^wOtafAyaS z-c8*H_9POdeh!xLRctKdnZe?68Gd|F{1-g6lK_=8S1cQc%pX&vYG8$CiZ!pprUIzh z1HM2RJ6zR|R85AKj|qPULljoV9(<7U$5IC-VWuWp@;R~M&gC0bKx_gT@cRK=dsrLs zyfhI9L<dWE+?QPMYLh{GZ zJ!pH`Wt`IUoD7w5dRloXqAY%?4$= zfl5DL=h#7O|Biq@*@71*PjpzGkQ#|H)_tUf%BERP&G`MOi3X`I z%T?_mt3^uaz-r5slf$Hf2%&}$H3$rLfO5@hFXaMJ6<9T5QJ>$x7W947Q;9xWpeR;& ze5-y3{Norw^p7Mq&`$^nWEd($qlp1jPH2gSWtwP)H`YLw4k{b+QQM=pnk9i)1aT(} zTk%XFKu}8S!gI|f$DjSzL?7NShkyi#KL&Y@RT_4-3y(KC$Quqy3Dui8&T8 z!dCYkV>dz}9y|=`&X4Eek(HNdyyM&2)u2=Tc#af5VhPNiqNA20Txv`GO=X|LI;{41 z6d42ps8ZQ_EtOFxMR^DW!Jj9@e{LmzINsHP9-9cVj2rQfj*B|1Q`BHt);%;66cxJ~ zT%kpU3hLC?MdG>wvN91ljZ8=&0MJ_~!k$b_w7;BuGBEk_f&kEyW0nQot^sJ2cEL~s z@k$sgpvln-z25ZAl3R4HN{`6{8hA2rtd9uf1W+Fu-bpCJmd>k z=@kHSmon~NnOF@9Xk}$0Gm*aMEzG_f_^!OXeDH6-`Ar!e=s7f?59ds(xd=l*pOgVg z2tJrQ{Jv7D8azBgk+Nh)v}KpimiTST+(V ze;5!{1_pr;pfPAZFvwLITF*!T+?wLX7dFo5k48V{_E=4L(79%{mwFn0Kl~E{uFCUR z%vD*~+>LK_^o(H=89Y)&jwDh5s-pYzdsFep86>6yDBl_4IWZI3js7Pd-B2r zA`M7e8Su38r;PfCBoO@8rXDmGT>b##$1l_9{nz|@1ew};S0_(V>6{_{09j&U>77P? z!s^7AWju$&+W9Xox#Y$55YGIB>{0VA)sMDqy5mp#B4RS-f*@<-k<^|^vtn7u_E>(A7*3JW?3w3yKR4iEmMd0uq}Tat>MmXap3{vyltaPoK75dO6B5tkai7A70zTfX6hjh9eP4 z1}OkdzAU+K-_|{#{>Ss90H7yRWJH6AaR3OfynBLumD?+M(mL|I zkGuY58Y-|^l1)^CotVg^z2~~;r~0P8_Q(Feua_o%fcWmkky)uW~g>75NQcmE3_hO`byBlR`+25}UFKmeb)Q`(Cp6GS-5F zW-Yw?CK~n!JH|FUD&O=h^zGC#x_&U(myrL24V%oAsWrQVB>5*pGuq> zKUJ1$###+aXaEwmm@2^pf3Q*$3mK=HHo>^*PBGA&KV}<5l;QNE>28ffljcFL;7>7l zgz*y&t9nbl3x~C?S6J+Oh1wpX3=+1FI=16^pZt-r@oReN71RXK)uS#2HhbD8a>U(? z?Ec;TN+-=DM)_!07xBjeQm2T?IPD_HcpS%jct(gR)JPy(9cEp3M~1|O^2$bO4U82K zFNM*PDsPA3XT|9c5EossIIqmBF(A1NCi7T7u@unA^s^Vw-p(U{hK5Heixp60_2H*= z0=<=ytY@uV)X8Z8Q2q8fs|K4Ne*73D)#SkRz_D52iF>8qpnxK!Rc~hLUYZn85>NJ& zPIz(sy+FUN+F*P!TDaFxg8lJDIy13)``&!t?9|sYGhZ#iyCM7sr%KVB8)u#H>t>%c-LHW#d2rNR3G6R67iv9Mh(Tp!f=}#f+4z zr>7?y^7|GRcDH*L9#I(dojZSC%yF+?gcF(aPthoVYJ?3e#T-6#g2^+^`Ujpy8QvvW z%Ag;Onh4z>BVfp07k(wQf(#8ngM=XQ`^st*u^EN%feeEB%CF(aw)K7{W-VS&>mBW9 zGMCR_%@yXULt!^d1r)Y8Bo&e9ywmaZHeLF(X*17ljmC4(%7|wHB%VtDcv{lOrSN0V zFctl4R6x%i1nTS}+{AB0)zusjAB_Sis?LfD85EKgr0|10Exl-;+9VS;jw+<6`peQ& z`9D~URn&*kcosEMJl-jEkW^1r7Yx_oc^Rxx0ll4i_RF^~2|)9#fZE&7{yZYv@H&9n zr@8hzOXmqCfZ7LsE`7Oi?xs>ekB48rgbEB0^kiTF2;^RIdO+{`@`ZdUxpXn@j;tnG z0RfS4M7q#d$XoZt+%hnlR>4;P_{Tr4EKQ_O0Dz|6O|7~Y7n4gXneL0-;h<**9$_TS z3}VOcp9%ZJD0tw9_)}1S9aM4XXAX^`18kBV%%Ou^r1O9@awtt{`TW2K6=4_k=h z!!x_vmEBF8gGT<086R`{nfc0mCBCGo0m#+|6S8H`XgUZqF7=Nxfk4WfN|gC0SpAHb zu^~oZV^E9)nN|TdsJTF*6`u&Se)xey$Qi$lK_YMCj3AKScqfa8i!h=PZJXluyHG&k zaM&h?@J(1hZ6tp@*5Z5Xs12v_qXdxDJp`ek-T=GWMEW=oD&N&|R;E2h$a`y5U3$m$IXMmIz`DwW5yzklZ8n`5K*|8z^#!Ks=5__^HswepafW zC@CQ-!XCs$7vEAqw2EOVAUlA5@$46q!vLTw7hXyQbnItk0$s5KNSr1Vw=oz%qw^eb zC?Ahs4!@iqKm|071nMg#tz}gCC=~LMWcuDYZzL%I6v>wmK>1l*#^}>#s|$iz@N)p5 z%u;&d^9@iyIIVcS{$+A0-F>|K?*TsW00QB6zYPV0zs4T|5K#Y=(Fro~(#|2b&*v!k zd8Y_}D+7zr7N*il;jjE!T&A^a%8C7CF-#7Gd20o4rcQO4hT ziX_nZQT##b!2gnGNCjyUNZ3DTg#DwQSbW6m_eN!c6vI6y_X(V`Til8guxM;WAUI!EKm1L6`) zDWFemCD_Q+i>c8eR6rMocopO6)6xDWV?YQXT0s@3dE_AU^yGZW?M_<&>L32y%i)1( z&_BSRfq`RF$z4}xk zljr(p-%a)6bmR5^8x;^#JEU@E!ha9{xrKsZ{C=iP+9$PKtR5CIX5;%qi!nLe8Y61Z z0JX{PPEl)peGrCtKVG!pO(TJ00oVe=(LQQSqbW_}L1L@4Xfu^_GWM`2kg{i(wqKFo z3+2L7HUuk$rEw$VdL9hN#si_d9hKefZ`gvqmD)l3M>Nb>SBY&{tr^ei2j4VGGpT3s-7p~YQ{1_d-S^~-_Dp-HH`hKAnK9MIFJ z(=UgbwZYn_CwUZl)KWlaC)+3c7wftU{djnIcpeL|$w?y6z<*8lI!iE+K&v;?-QC{E z>V}sUPz1h8CKD+{B6bBt_D^5my9mXRWnN@Xtgc=MNcHuCXsXu%K*zh6;gS0KlPP5HLddwZkp5`tPx6Mr>HBNJh#w+Xq z(TW(nLa|9-rKB-o2-U3GE9c-0`PR<(Rn@%!vT`U|1IjS&hk*hLq!l3^pvC^-3qPNoL=$L0h@jQ}ejrN30?@nlLZ5d90F*4PdXoY`AcIyi^*jRT zo&Cf!4FT2b7>78qa^eK&9stn0d;vHGH5e$Me=M5I2PfCR#-V6@94s$mQ8u#-_^ASb zxW9fV`|QLa%2lo6*z|#Muq+0W4@_##f6!c_?H&)_GR)yf5KjDZxg$h{iKUncbrw${ zR<#8%TZxsUU@}8&uIj-Yh#7+ijPa#iGp!=bGy@4E2yYE9gjuLr1m01bR;E(#K~t!Ci73D9Yyw z<2T~GgHEPzmX<^%foNyzb(B}vNd(~|{#?{iE<74fMo>uZ%i^Egrw=Il9L|(J(#%Fs zv@>p-$fj|iiUlC*%x5c6C55m|)8~Ll0bQ{vpid-#o*kPU9RUELF7&k0<}9# zpdrqsmwour$@bC5wA8NJVEq?{Uk*&eQz7W_<9Q&E#veQyznVb>R9a240xIR9ph|9d z^QF~yvo;09C0M>*$3SS{&j~NXY#nW(>t6JL{&9J^y!=Dt{s92PKs>+V1emhS?(=eS z?hpWUDDQe5GJY_o0~8U(&12*Scfe^lXql2TihrUDgv%cIzA9SjEO$(EkS7d50;LYB zxuV!OC52Ek%~y_MEGNRs6f~6n85F+-0W^p-Qw^=E5irKbfj^zkpSvo%=X=Bm5DB0v zdq3Kz>yz=m0{{RZ07*naRQz!~nLm44n5rT9BYN%R--x&JDMAoP8UAVb^b`;Xmrluw z9wb?13JFBtbO|(`;6Sn?Y@lla0UVJ<=KotideS!ja2-aiFHYPLn#aTLPdFTIvrQg` z#MF;{>&uqA;c?CY*>^5Hw(=`T_eyPJhb@K=^*id)Z?;Pxe1}`AD2^`_ZNlnZn!fwPE-mYpz);-D!+gbke~MEacJR+xy~;FHT}0*S_#n29C@ zUZ& z=CbI@Tl*RMLqsRi$Idw*hXP^%y&ahxn4AOv!AGOih9?tfbf~!kI;#|rFrg=>r>8H_ zr7xQTntbwPa(aLP^km@Y$McW-FZI3CG*DsHn@OMR_5yeqKqb6};a%}YN|7lX1adb3 zsD5H;BD0cNSy^?10;1ud^_81nW-cDT_ubsiKmOp3d{+hfTwVtJ_+vB6#PtCfOrSsigT&A8W#_(;Kzcc5;-70z9IUrO$A>s7=I&5#e)0-uG=*_Wm+SarLyXp~rCFQ29dF);H)>xm9q!=<6udEivUXn@jT`omF|!^M!?+_xnL%Rw zFxcde>GJ6{Sf@+wh2VG(sh}wOJRpFwJQVE!kp9p;AdY0!Js_okCV@XA(^uZ&6?mzD z+HvJ#vat=ODImEEKRw-k3C~+70HFs23TT?yLkbA^Gv7bkXUU&;v+I#BajnZ;FRhlu zal$+v$?!&c(ci&}i>81UOXBzSf<6KPG%+!;g6G39*yG*1U!*fD-N%n#{BGx`lkmyk z<#LJTzeXcEF_SQJ%f{Rs5r}#7lXfmut+*drJugA3KWz%AN(uGV9A^j7D!WOjz z8@n~O@CXkwn>$ke?3p(EM?;RDiDq(fcc3PAtON}!cEi#zD2xC&u(>GRw{ps0&tm!sT{CjkU( zxl1Z2OE!$yiQv>A5g|tEBuee`c-)1z4v|2>AhD;R{`htsk-=W=*wp^nR@`Bliz>$L&;tG&iHHNi%-A$?cXQ<8kEr7TyAdeCvJYR#8LQBDP-U8 z$i|pHfB3=tsVW6T$1!qM=_%#-;Er&CK*XeCGoTR+oPJ4gMvl=GKxEbGQ`1`Y!Z^`T zQr#Oj{AAI3WtHaEvMNdch%(r{ycC;+L#OdPQgQ-n5HP&bTYpEVoDI3aKf3R!Vu+=Ayebz4gYIXmx;O)8Z;){H@oYZsdDgUUpSp9Tqp z?4em87tI;+dOYnwM6uc-A10gay4%Gg((!!)&})40%UK){EnN?2LI(prT*07yCQ&M( zHQj->+dxtV+1E3q3Th4@;?J(W3wA|QKn@RR5}sIpjVKQY-rkO!eLU2-4rVDJ;Xxlm z1wg_pWU7y0R8aYNkrNGgyH}6`0+1ZEzdzE1_YYR?aWC9 zv?K0hz{h_;0mN@R9~{PUG=NA4?NGxXyJ2*#r>epafh)0?KZUQgnLt1)pjvYRnba`a z!?~h^J)GTxPakLBnlEc;bPD(}^kpp+FoN6P&=v+>;~B#%(K46N+_Mo#u7eSNau$IO znPyx~QmqC4bA`nZVR6veHAFY8^v0Kq7Jwpk?@e$0I>-O?t>gGK6lAkpgGJo+mCT8i30(g2mh#j{E3Bq* z5c>G>B$R4}se!Nm`m3+tM_>H&+~vz(-OuF^K~RN}4}B;#&YwQ&e1!RIh5hhV!5!LP z$95R|LBjDdj8r%l_Loy+t&a06TpkMB6PsGEgbO6rQYl*q0F(+)Z=XyfO~w44dSLKn zuL05mwM6H_c0AiNwz+xh)}xt2wfAa$(8K@|W;O-2VoW3F`N&)!`$(c;L5Qtp;r|SZ zCu*8Opov8<6K8>>1gbd*gc@j^tFV?3!a|Jafp99C?H{3laP&|}AdK7q_QYax^d}tF zwom~;Vab@V^nirz9O4oz#QO@ZhMx5otOg*pb1H)ml>iDh>woE)8yx!MqYju$mp`YS z`bT6Gs*^c!90RIUWbs2YfYJTRHl3_^O%>Vxer12FQn8jaxM?yBepax<9SsoBn zVQ+`#BSHje3TTqVh|gZLp22mo|*(b@$A09j42C&wPo|I;jdG$rE5@Z0}LChIHd zbfzS4!J`S3uVYTV08jxpR15jSEbr8p7Tw8}7bh}H-RHV*FGld_YX0$RCY|oSc>MUy z`eI~i{mFg*#or)+{^9c6*MIf(TrNidnme3h@@Qq2HR^o$9~3_rO<&ayD(4h|c!eEP zqk%u;2^x>azn$S#l)`EPbOJ_o2y6I&)eargsQv>oYY%_&0Pl<9k5c}WcuhNNsVWGd zz#zOr;aB|e^U>%xw{D>g6s*?7z6A~s?a72xYZcY{2{GhoDw$#f(4hUapstJRaD0Mx1q6S;_T9$K{H{e1a?^T-r{*N86^@-jKF9ARUS{HtxfBxr7@Zpr=4?I?J>@c0_E#Ogl z;X+4x-SANX7r**Q^W-nB7iRmWs0-#^Os-%g>peiwml5PoKEImDOb~!dSh)3l{l!I8 zK!5WOmoNY3_*Zk6=Pu{w@QGHC&FN`!4{XOC2mK!QNU5U$#6Pqo&<+Pie`6jvo;v}-cKw`Wc2qfV3?b+Ur zRzUp#g1*5o&1oB${cJR8dg;cHh%Ur`AYp^Xt$8(UPc3#0Ht~jJON<+0JQIzV25p~t zK%?8u2t-vFiJ+7iN^BO*Djq-@`d%)gsv3-94`XfNM)t4-^5D)Fb=f_#^b)g&OrB8l zw$~B-(Z~~QY=Nz{#E;8mm0&#fqm)H+2U;737Tcyb@GvQ#=6WLm1ZwC_5;(&!*1-tN)N-&E+ zKNtQ9OR!^o@2pll;3WwFiWC4P@Pr=%QX%OL+u02B~bUiiWfV1Cd{3M-pE5w2KO z<2(351>H30EWt#8Vju>8wfhYt=|0CO9&06p> zWkVw9Mx5ip(0*|^FMyw|^ShNdTOC_~BLI+^4(fUxl~Jl$D4ZT-U7hj$Z{sd?GS#9G z4@kQl4z$Ava;dI7g#d{qdENcl0`-FhSjU!2PC;WB$J3{JBBHGXn-pHqTT21Kb5cJ} z*nUMSAj+mcdzKHQPLl=1C73j!OY=Mkt(Raw&p$>04M+fqK0BU%?*-IMk)fQA5 z1fV@&R5^iv!((32V5*F}tHyzqwt-;qpP8XyW8KQB8L^p~F&=&xd>Hc&#C-y$uo-`3 z*Gs>+bJebS8oTcf``IT4fKJN;ghv6$#vh(A#7X2V9mlXC=*`yl`SaUQd~H{{UgJA~ z21?GLwivC?qiE@jXR~*+aq^ti$sTJ$am{7~b!rsqv%E^-BSVaTC?j?MR9qEc+? zokbw1sl1s?a&f(Hol>9?L3ujLoad_;`96RQdqA@sQ3eX=m&we%?%U^X_v0@?36@^U zoI7_9)6iD?rt)9^^{1eKK1Be1$^gQLrGgMbdb7Q`1UgjHiSHRdEIREURzN$vS5Y(( zK&ga5E$;FRym)5(ArArw{whzQ?Q?+j7rffwFLzK#DX7pAserPlt5q>Y?T@8s$XJ;+ z@Y69@+xWG_Oki-_Gy|@V%Jb-U2jw7c2FyKKdm%+BcI2CA zAjgVEoVMg?ELur1ls{O4ZKDFBSs%%tRtkvVWA}jC@tv-KxCj%4*z~0EpwA+JqzPU3 zx>*ACzq~L!Zv)VifyeWgp4b2cl4m`F%kQftAjzyiQlYS;Td(btF*#Y~L(S zF0umpd^L0LVrBysQ2ud&0F=&jFI~qHY$|{MGc=(u{-?{IeGLG*e_0V|Zcdm%f{tvg}X$l&f@dg$o0d!=b;z|ki!(I^b2L9fM`U}6Gp$yj;dPJC{m?9-2 z`I891i!OyP>pcrV37;z#TMN{v5cAyah{kt&XaxFJ2z3>vcI@E`zJ|d)%!~sO|06cu zWf%ty0ZEgFG8w5jJ7^F(EeRw?d(h7*qnt^UwcmE20jTK%yZHF8XUQOVo6&9)axOI5 z&=gSSC*y}8BrXpM^qgq`P)NodiryD#pOEhRd{FgenYBL6eZCrO0U(!C{3vJF=Kp*k zfaDGa%AXrrBnAycS7;yzM9=p2E(o9P^Btr{&;_D-A^3QITf*T-ltDBj4b<4ZtL_OZ zDdf@oXh$?qLtBgoqvL`<9L_-!hye5>3ZM?xC;R~Rd}1wwH386wC4t^fzP-Z1(6;;V zZ>P}`!c1t~{o>>7#_u^N5&5^%z>pRW)Pz48gS4<`{021PPyn0! zIS||NPW+%7joeBo4V0ou#FQ$+L=49no`vQrEUcPfVjERJNJEfK0P$N`L53J~HPmYN zw845-H;ruyXiXddY&HF3S3l_c@Z$UF4Kq?OSwwbOkgtg3!UEgm@Bca`G$>0kHyV7YaxSpwj#>0BCaZNfZ7I z$YJO{UT;q(S4#Ov9-ZcV={hK$Kci}_K#TFz76bk~Mh~cuW9mzvpE$A6eQ_fFpH~Zo zb-+{pW@aUs$)vs4OH*8?r2#R05ZmTat2>^$Qr*N_miL$2*+kbbUpkWW+AMN>&`bumE$!Gjyc@JE`HgN zcav@Cpumg+g_aCD%5!cFpT-Lk*7EyWg936jn9rK}k?zlj zN*~?*;gxs$BQ6+}tq1}!WGZhuENke^U0JDZZ*Q?16nzcf-QC`nS+2BeF9OUOf}+)x z(?j39^U(Mia{uS=qMO|_jXb(gRuof z9*}%QpaQciAe}+lI#?eL{Up7Sd<5fJDX}b)T*Vvp=tl$479%8c-c7Ly!~ptZa;5uX z`lfqTD4=BWCID#3?T++aB9-*NeoEx|FQ9-JK%XfcG{+)Hxj{JvphHXle24+vTmkV) zSe4HSQt+Xv3J?67Kj3HP#KH(5yxM~&G-8w^D*|PaN8&Z)pW*&96g2p9q)H8HGxHVm z$1n#$MY*1@g@VtYKaW2eTX?jvdF$4KA2084#+ZmXOr62=92m7|lP!b%Cxbs&O(wnK zB3MEV94QA|1CSChm?K#;9d6Eeg8Eu1Klb>VC?N5^$#NJ5x{?e^C4fM>6C^bd_rIB@NgN75HU-pwVVHJN2aZxec$#n>cQM?_JT<@SZahL5NhVkO3YZB!ML(M_tQY!b zF9Clj5V2lg{p07!mGs4P-cp21w}^Mei@h{=y%&&%3h4j*n~Q&Q^5n_?9Td=i0{UnS z!mhj=49e+-v~`Gwe^fkt?+}p9`>_-d_rDN7oP0=HB4^T7VqBF11fjYizQAAi@S3B` z9VxuzgJ*-vGgxi;;WMCM10{sl#SlLDxie)HGlrNQ0&#`2MQb5nbhjh^yko56n}xBl zu~1P8ffjnwWzrcftHPQHDz#KH%Jj5NbnvcH=31o>G-tWTQ4AL*O zu;KX4wOUOoAk*mxNfCtn(FinS)nH;6NEBkRFk8?>Al5+6hd4Q?`9IdySHmN81b%|{ z2#cUkcc9mrn$K3;p>4J5xoxDT;o*ul`ahCCSrIhW@Zgj(A$acM`HT(#&^AB-E3r3f zTXbuC>-_mg=eM@DcClL9MH+z`!hJFkWk~gyFX$56@`6G3LQI=fBpWMEDhN#_DS>DS zV|&XEAO)iL0Ei+vkT)aKI)Dg1Lv)r<$RN=MlM1M$08~N&)LH>e$w=09jQ`mH2~+~k zL?T{HL-YbpHdZ6`NZ&g8&VBg;M*iR!5Fm&=pwbDDJn4Jg$vTN6K+w%(^2=m;rC!g^ zvQeE}T3Xtu*EhHX`^>3=&<)C&xtw&QsWq=JqBiKCV)OkkA%pA!NVLClYyycz2hK^v zb`;vqTzBD2bV`T>yx3P>rum;Te1t!rBCX_4&ENtV5r}*eBQ=BL(rgTceSZghN`$t@ zHg|V7Z}n6*Z!NgQ)n`598NN`;(DaY^ZqQayi5r5#l-X8{+|(lOnrD~1x8swVga=+ zEHi(^(nXsEouH>7>#zxccx8(0A6~Xt^Q}4X z@&^fYRs}+zm2LR;WB+6U=)w>X=;wjv9?$@9RiFT>FP7X`f|YOp+U*4el-x*0yqV0+ zdWrADi=r=(x_7oIVGw>2+{?PE> z-ho-;Jm@`In=;|mSe}_7u@s|}`v845-q@f|GZLYm%?@8IHSXKIHMY4qc4usNVeH!j zI<~qe!=nwl%>g7UbIGKOnnBx05B}O7FRc%1RO(j`ser@-7C;9LZZxQ%aU4rb1QM)*QVs+u9|#IDy1PuF^b`v1< zqr%3TInQG4OKxAt<#9WJY`#y!=7o#SuDhO}){d_`W5=xAABX&505uvwQ5Dgw&bGg) zVD;5i*+Rr@v*`>R0OrsG=<^L|ARti3*4B?d;?#6c$2JEURZ1t|YygrF0Tk!1~a4hPvzeJ2THbD*yl> z07*naRMtP-1@i)cHdeYXBDU5GG&v0l2mmCG7xu!Zq|^8nNCAEQ*=P3=K=(h>38WZA zrI=`n%~?KBBYzwM2!j*l#IwBzrt6=gLJ=MZOkkIqgIKkM4cbFB_o^7rDlUbYvH_LA zu|;}a;Y-dxgFUhGOp4Qj48QA}g-0P*Di&YZTo_yE85`>vdz7fkc|)Vd4Se`#mQhL> z*1&VE`A{KUurTB;k5&WBykb`4Iie_)=$L>d}pVY@ue+&(a%J+>1SO4kptAi0AdG-)>3&M5tlMLwg~~1ElD2u1`qz= z5qty~`pb@vZTQ*qqKkGHo|P<;1jAR^cJ{ff$RGtEk3}HDDdq)HU^D_qFlc*g7fU>s zg`THu1Bo~J9BHC}CfS9a)&>!k4&o4wvv?Upg^{5MIyN-iTVGr()felL;Y-8AVjI3u z09hswUw%(+xFeBB$zA7Mdhg20#?n$6>ai01Y+qj_-v=Z@6MAZD3X%2s>Z&`LJa^Gs zkE|C2fHuC|NGJ2_xVnLXT$Sx$ zI22op!+%W+yWfBgT1e#R3p0Ok1Q8G40DxjMW$xh9U5!>V&3h*O>VcvL>!q5bh7#vn zZ6RkmM9Ku96o4a<7<3LI$|D&EqK9TS3L%m~vL8koDAlYA6N_NsusF?Q_n|qCmG~15 z@d{W-KepUvcYajaW#2gUXueNSxj(^X&3BibKJwTFVaF#II)$`oR6tP`Ii`GP3qNsf z{7}<9Jbok3bcs2fE&-tP=TU)dv-IhJnhV7a@CU%t(IX#Njlp}|A=^ib2no~`&vI`K z8T5c_NZ%S(U2FKSfYXZbzh}_*=h|w9Tu+S?4aG_rRbkB(knP!|1RI%T2{dx$t!)8OL7@I(pN(LWKO9eDEG#u&eEtM8~d$9x~0BLiGdJRT>uuJP~TYFdBtEEUDv`{jM zC7gHV_ELA6E;(N>VWYl)`iH*JD#ogJ6@FLx;zqrn0hGU&lm@-8nTI9|mrg`~3hQ zPZ<9e=lP%*I?5(|9Q!sn^V@Lnd1axerxM@YytO%#vmL#_DM)H*ms7E_$T+K+MoR*5 zU9~6MSJJOG8#?gXpIjnHXGj7Ew*vtx!5S5isVSirgF#q+BFCr>BLqnT(L8j_A6DyN zVzM*F6CqewEfnyJ@VPs`0|h~(#m_bZC!Bcp^!g5jX&1eV_WW_ z$bPmHNGrk|`00|zlKK9PGnNPIpKSzC2UbJywng3#R9xo?OOJY}6hjKZ1N-w(HgWT; zflP}2%bnLq_PmFiAryb%f{b0;@ePy~5z zE_E+uL_;3{lt=aufTl{<>!r^DKy~-V#oHyJfPh_IEWy^V8~3w-M;%)o=h1g2IfUA0f%pSI+3~Aw`Ydg? zEK4N9d+$6bE#@hM$R8w-PhU=@iy78H5RU|49#De7Y5j zUZ~C&?x^qIqky;tuj`+pBW+%UFE{W<`&H-T0AI^c%7EB`*IW<@6prD+dwdZZVW_{p z`6eFk7~AX_+uU8a3?Npbl!LSGea>+7myQu=wYp~{XK&*hK?GDiNTdci)@r)0GjnYL_ zT8^J?f6_iV3;>$P^{xKimzNMglatLWFlhp>Garu<_X>=7k|QF0+m&ss<4=v?54AIZKQPm;0yt1k#T{NJqtiQ z^CW}qt!5ZXHi~Jb9eIZfWLTXrnJQv5nF^xcnn(!#q-K-`IwMq1hzKJpu$aSwR*f+1 zgRuY#X#i^G00kSy4u$Qr7Nj>heJGuuV9VGI@$qRnxrYs~)~U~(GVw5OYrpGnU3Tqb zJuC7~s#?VAQXqP>wJjCRu2@pvevP)!j~%3qwooD=f$-6RLyN$uZ3^_+-n|Qg=oHDLInMX70}zsQ8^G~c|eGs*+0V+4oZb4 z{WFP=_Gv7^hUX)TrT+d11E{3};%%^5RzPky)LoH$#7!Nsl}xgJ-JM+O<`QhN^sZ21 z4~QCJ0HD%!R6t*D-0OBnrrvQ029M;5yTB%p1)w?&MBi_!fasgECx++Yr6E+DBV|*x z^}(97y>tmwb@sp<{ITmH4M1kA#~`{m7#@T#CHnszn_)BlSm-(EA6@aU0R@ywjblkvP8p_^(R$#F%^)5mQUVqS3P7oVB#?A}D3vWA-X zzw8L|__W$9Cc>Ml%{q_Fg{@(dZLl-V+ z+whalNuYP{tjo*pMkbvEL3Q!?@vrRUaahteAtWF~BZ{gXD;Bi`X_a-DtLlXpjsI8x zDmE%0?ZP|NEV==76n|=XfIUS7q7^bfz0PL*e;W=)p9h2Sp0R~W#~9G(*4U$Voq`-yq1WF+-CAw*3hN_&nOu}`1e;_3Ybin^2Ij%PO_)yiZfiQO@ zB}5GO;uAIrR5Nr9B&LEIj)!40Y#afUpuI552cjOlW9pfy4&e?+?rJs;-J5r@CD!9&aQ(bg7xM=yTGo!)a3{&Y1hz$#I76}j1YoGprG-ThJW z2MM%|h1hxYr+dzCp+^KNXo0Ngj@P?{E1Y4(Ha;NeF0hElrL%Xll-|MnVj=pUln4~J z{fo(7m`F*i{D}$(cj2|?TSp0oI2xM$<*3Mn9-W*#M%)=1x+K1T9Ck$rpb$8!$ z_hTJb;H`O(QD{Q<^%Yi=#4-2vOd0_6#s94O};Ib}{!w&iuKH6QaA5-@%eeN4h2TF-S1{fI|LKg~x^ruD zb2C^br2wRYB5j6VtqBgDW&ja`@I_5KWz=xzNkT*4=Q`LE#7ULy5k3k0$~cV8qf0r$ z4=Es>K&BEwsTu!FSqxexoNMu>YKQ6Jjt9b$b~r%^wV2@#q?8d&V~95TuqmXTR!7V- zq1!^L64Q;J#@R!w@h;WRTC+={7IW|l_6-@;BGD!YUM zoo#U%aBFu4rsa?r9y0zo+jB%&?XY*yq4 z;Z+T?)|f#0zZnk%@pe2*u|LHF5^JcFZ)p{El-uz-fZ7o|$9_3GB>V6@3#2{f`{#!q z_y2t9!qD*VMxV4YfhgbkU0o_5ZzP{DA#l7KZf|A-1WX#!eMkWvdl$K$2lS8$)Ypf@ zL2dz{jR>xXfdsnF03r{1z2IGeudTyQ6(UL$h z@m}+Sq*J6RAn5`%-TPAd$D<8A6MNR0-Vk-3yKwftd=0%XYX-;_w@(3a(<|PRKaCow zLZ=5SGy~M^Fc*rRH@FwdPV}yPZmCsu3@^j244PHMqHGs;RDbNiuKg|vA#|>{@RxeF zE8Efw!r4U8Tnq+<3*BkOB=T6aOiBDO1*G{uBcq}O8yUr@dRrU5odP+2@$7e_Jcu|t zc~%@p#m5DBzI;4Cd;t~Eh2hp75amMm6(oRG+`akLUS?4es;6XfCDVOQwBe_w9$$}K zqD>6!-skh;enzSL-pvRpsX|_?!O|FFA-{rE9F%qS%o4WYkuU5!-?u~P>*ifCnH!`E zF+dQCpj^v0LQrw1IvB_`F?-$%pceEIVW}7wjdF%_+qnhpas}zXfsU=a9h<*KPtBA8d5LkAl-MAG912KSLH3TAn2SaP@jR10jp(01|r00ucQ# z6PB6K0zg4elY1AU5s%i7Z%rS34z>zCwA>%zJ(KeBHR-;q6dji{bOZU*Y4NAo#zjN> zt8xT>_%sggdy$^m6?X!OKtIy5IzHjoa3_NXhTsDX65IW8tK-KXK^;-BGkzWpPxpXY zf}$!b+-Q(MzlHzcq!I0kYyEgZplF;jLO$37dVA&Rh*g2nGW@7x5PJFwg>cNi_%qr{ z#kdM?4x0_rV^kG<#uZDh`MCnbOi_1*%A zA7BtJr;3WJ?oMC4*-!Chl4Oe7OY zh5lgx(Y|ff%qak+5-5QNi6Hzw(J&G11dwSux8!vKITR2d2|E)DhntSGN8Ve+~(RJME94TBH53yOk)5AeKPC zrB;{@Ss4}0tEnHZfRI8M!>ai|!ics1Z zkB(440HD5iy$q7NJ5!IqgFGMiMluQfNNy~3Z+wYRiGcKZTraQy!u9z4x&#oEU_4MH zr4-=j(t2S%lg_NrTE}(FCA)l?ORW3&o|RCeDSg>#28q5r%b=pD#O9hRpt&9OVT9(lrH4=pZx*kuidg1@H!Ld28| z5C;!u#8P-&gOWZli)cJ$^~_`|Y`jbhvk3r>e}>gg3X>Rdfj<`WpvuBOiioVXG>`)$ zP{O5*G60Bds6?}HL@|KaZ1lh)klK(>h_$d8jX*KKHU`wdAFUP(IVXW^<3R5LknS)C zTgN_Y=XTWIh4YMrJxsaNx-!b0uRoDLN&z(k(6-nBqXKJpn|vT*&=#dN|F|nRC5SiY z&u{%mf{4DOIid6LJpl=4i8?Ut9&~SeW(XC z$!B};HvC%=NG4-|v=VHZ+F*Zt@k_o7Ha#lnbC#6Q@bJ*k{NoG51R(5!wU~rv6Np`A zx7VGyjsRkaBv)24X^=rn-M32$K#O_Wg+~tvBcgeL`kVtmr4nVi7V;VR0(GyqRQE1j zyr@FykwJ){)`4} zMgSSdAxO$F3L}6hMugOpu7Rpe0fa78Le4NI{(suu$G6S%%oZfLq)08>O%;>{2r4Dn z-h@L!ES)Rdabq(oz1BpqTnubA&?+G!bwLMnHKM*kYPjp!9f`tSYdgv)l*gI^6Ii;F z>1{cfUJEhywzKHM5DN>mwS|Sbf!BipE?E65`#wM3U*GqUqTCKC%d!*8c48i%=RD_} zCuqYE+kw<|A>+qdLJ-M7B`8T;fRWNbpm(VjDC2Pe8H%)`K;|YsjGM5O%YkTT-?jG# zqu@r>m|c44Ie6hdAK}KIg28_ZcIv$+{P^KdUk1d@8w!Ht!7kE&Py@m@L>)1H!C3a} znRo|$Xp{6H`iHPHL$z9br}$L0!%C$9=QNTy^o#$%gh0mOFpWQ8iXMCmcApQ2y`V6v zjDhLHV6!h+h5qe_e~2RV;^M3%Ko_v0b?Vy1i~s!5wQCP9UcAtk0WF;>320(yW&^^g zJdZt`fp%wDgUulTEiEloyJMGN2lgKY1v)L_u?&GX0)VP3biNtzsCl{q!uCP^6g~lc z=IgJ$^}h=c`K2{nUAg>c>wnf8gp8y{8ywOCf{+M7XbfI(2K&)|A3~t{d7A;vy96M^ z_|pe`+SaKq)lc|NDVlmcm)nizQ#AmfPWmwZ=n)uzB4AQXW|EoAU%~{IRI49=A}BSZ zKPBSt?@W|U!}y}4s>QN_LGM5pSd5n5<*1X-W118a`BB`iW$4cw9=I=oSgm(qQp9P? zu!o>5B~-!RkuXBjlxq{_0id88fyfU8mgo{5Pa|lwNl+$lEWBLyAY%qImFRHFy@@vf zNSl9H{z=MuLkotC?1j6i%XQJ%m;ZQFXo*3vL-NVIy9Tg+4Cn}4(4F`eY`6e|Fcptg z&BruY5dab40X>@P3#qjO7Gj7%$c}&j0rbR)19gsTwMwnhDu5SA{7Kl$8=(yTohnBV zv;z&Q0lgpw1Y?+FKrS01Fd(?fJiGF0VlqdL}}Z!2=l33YOa= zl)+sw(1Ysrotc>(l$VC?+%;&8#ey*2OvF&J*A-tj{cSMfn4sh-LQCZqyo94M;{y?-v0gvA8cj7)>Fo? zSQ10Z7}iiPM2KyIgD3?P8aCobBJ_gfMzr!>JOYGWVnOjDkCNbo%5@Y2?XfanB!y4& z6+)mGbyG_OQreGlHI_@L0hM_RPaH_VlJqhf0Axr(K`#Ii2P(^DeAxn^DBlRn8{m_2 z!4IdwGHMB*N|{a|Pxmv`P25Zx0(2yzZWaezrDIm*kJ^0o#vixz!|+p3_tv@R*$;kn z_Ny{#B9Na11RSR$xD13&5m1gh$Im(>J+lOT#J9VS@qk4f-O=a=!jydcNInscU=j8) zeXdUD5Kf8(lIV)f=l5XkA@5|!FY;p8=(#i?2|)lp9t{WqXheMVlb`K?3=Jamum+&1 zi#UW`{OF&>Bz93CP+taAJZ(w_G%>M}ZD!RsuR|M9=pm(1v)N(6fHpRoD>Q)#xGC0g zc57Z23tMgeIW9^%E)3P@tjjcgQKDZVknZ83${s9S438{-^~?WWaw22BFo*DuNcoG9Z|kKrbp|tNvY_ z!D6um-4WE5@mTxVv=0FBDh#e%m&-B7qCj%6)4KvDu)79-d-F?U_N2sG&0#WS{GOW4|j%Ja~~&{(xA zMQF-#%|JkG4uoZ7K+TP@B6*>)@~|mI=r{4o^HN>lPZ7HlPnTd#FThLu;1E)}A*Yh#8P2{H)1rLcjHUFc?jJnyYm8-ylgr$8i~7=ZHXMkYHd3=HR`uaygIH@KLU1Bof3{#MQM` z2|;39DuW*z?8@-7IQe%SN`?W3yyLS93n~B#`XSI=2|=DQj1kCCoB>`lQjj+p&{r}k ze+1G1L}eRvAIp~jspLh#qCOE{1t?)oUpXp0w1=;P?K^}oM1g!65QC1IzeW$wcpOps zLZFZUk1dvV4xi!FCGqE(T!E1_Q9@80yAx>wdv?T4((sSq(`?2&5`pNyzt^WYO+IBmlZFd+Bd~3k>Lj0YJkeEJ9Bq|G9P`|yHDM-T{)^0NfDFpK1k1>2P0Qs)IAla~B-Ff$55SGMK z^%pFaGP~jMF8l${-A>>B0PKfb8KOp|D4y_x?k{{2^9c_9EdT%@07*naRKN~JJoZB; z#!^Wh!y@or{Bem$0E!CedV`W0cWK6<*LRE*BHUcvjgmB7_dgZ>|Gmp~adGW?FLCX? zWo29=yU57iM5qw5UDuYlRz~95iXwTFy|;3$QdCApC^LI}@Arq#zwmmzUeDJ#&*yob zQ^81KzGSAsuZgj`{Lk{=Hv8F8x*;&K*gp$&8_I+l(ZF|!1(&ZoT`?HlTOOSjb4ha! zu{Nk!m74W`_m8qzFNuVTQ-4)=BfVG)8N4H!cd(RpaQ-21EphuRnzM8I7mJCYF!91N^6pjw%;YM;plIYqwBJLW*iw64*7JpZR5X1L;yq@A8vlqRsdge&u_KN) z*{`a;c7YkHOwghUu|4RyHQNQ(GsFfXFCSQqb^ggHo`D_C6}2aO2fN1>+B;|;H$$p} zVfb72>$Sk*i~8XFih98xpOtH11e@2&=EW;#{Zq86pvNakxy{jHj*J*cDX- z&tUYmyUdC*J;qSS+e_Iwe6RRyR=pKIyz9w1Z0)MzXo&(Bu?BkSE$hlUOD}a(SW;m% z-fG)D*pz6Tkr$rSsBvf6S;GaH>s&)CJVbhnH!}>`C552z242+5?zy83Za9-4KHO$N zbIwj?P@Fx?EvWAG53TBpuRa&)+t;D|4oB)7UJpCn7QMKO4F?H86im(rr|{xx_J@b{ zg_%<3IfudaI71}xU*-Pp@t|LT&N6f>?^bj!;Mz456Ov|fch|MbG$oUoufxL-YyD;t z#IH<+I1S|7{GfY|bZk66F+&c=Ox_4D$uiLxugmsV0&3WD(k*~c>Y zZ1luYw!b9x_F8A;zVLc;m_Cfn(vA*3A1@Ohyd+32EiesO4#GzY$y$?dC%GhQEJ20hpdT zcl9EDPFilfg~M*pKHqO$T*qgAi^~)&TA5skxI}uSA+ZFa_%?DiK$4zwa8->-d2Fz2I982v_lHy-#%xzK2B)0BF}Kzl+HEb{&adpRxXYj}_oq(i%-p z%(5(0Uuz7(6Xid;*ra#(Hw)63V)+;n6G`E71iam!1aK}r*O};e%i+sCYfuzqPb~3C zYhK(Fv)0z;dFNC4t&R@K3Q6fjKwy$MPLXlBK*TDTI9dmp3nNrsyG>r}#86dbF6AIS zu>s8asj2UT6D8m4Cdqw=d;DRvY6hX;BrT2qfLY~gt3A%tT=iknp# z_~vy=)9jiD;uI%Ad@YJ5Uw>h@Uz_9_I1@Nu-noWFNAhvJco%F>AwFKxdSZ;NRu9_r z>I;*cP6IB^&L;PjKEjf|Yv^|VW>8LE8gpxS6sO|b?Igb{Jz5)=e!CWJv+ zrOsaGc1alJ@yooj>9=VR9l#SRF~~)F_73b%`O&>!y+@OnR9q|}O^oW3;Tpiaf_~ihiUd3% z9RCdr<0m74|1iOCQGq1?vwqd+hwFLUn-|fK%U+i#wVYYMHfOwg;`-|Q_|9Q>scw_{ z@#S6W@}k!ACoA7qGpJwdOy~~%$1bf@PzHt74buKl7k7&bRnYqjTBtHj zSi|X4KS&%Nb2Ko8Y#tyhTi4lA_3JEX?6|e)^JI*A@fFW#6axO?lI`o|om;{t?nZxW z&Cu4wxN;rFH}W!4GmHBC zM@?2V%9_$bYAD?z!huNYBP!)-C1!0peMEy~m9)`@`r0(k2X#s@M8aX)QrXNCo1Dx< z)x%gGF`)qvGDfq*Eo!AW^?o^(!q}8g?L`P>U8DK#3czoU-H?64+4Ia?o`-riglT(^ zK!0b1^yTL%6VPNvIm);(sY6GsDPf!&lPE{D{9rQXrUB8EfNii_*>}2}FimiN*P-N0 zv+p>5TzDKO78+$UqWhaAhn_OyM5XS9ImQ>+dF|?1@RKmnv462UUXT-%31y0k^i7xx zjk_3=*wmAxFZ}oVs(SeId>VMtr3B>`+KRfe;4^LaOhN`)74C%i@Nli9!?#_c;o1dM zCq~2h>|dDwEv_g75x;heOJU;EcWQKEGAG?7LCrnL2gY|)C3_8w@HK(Cj3xUcmzf4% z)jX$Y9~^;B+`FqF-!Npa`@3@=0s?IVM?de}MPXs`w*Yaqh zh0bO)3SD7XKP^zkBfoNrYr7cvPYL0Z+KD?K78jj?P0nGzEZiX?WG{L{FKnXv(N9*w zzB~^?UaJ$~_zo%;CIWyxbXk`=FTYt8JHU_h#`cnr-ltow*g0vTB=13d{3;)KBmPHG za|e?qphtYxz_0vMQ(p5&&Pik!PV=J@6tkdxOpN^emqf?hu14N6yqf;F@}C833=H>; z)D_y?-g04Rmew(^Ue3*_VK)+k)E1`YT5M)J7(3#@ZVdIY{UI{xNhI!WJ~Tg1n`gOt z+}p~a5w%1L&3y~m`|}@$?dDXTIY21bT@su6v~jX4W}#2|dh>ft(Z@7-=JnBMCwwRd z3oM+?exg(7ua?4p3+^Jc@{1|hw=aYThZW_jx?Q7t?H@`O2hM{krFMtk>3;^^e3g=| zZIkqzP%1>=7(1_!3b^;f9srlfdu-((zHBdT-V1h1)_hLw7F^5=1?)1oSS~;A`_DHA zmgQTDaPLqV{GkCJ5ng`WlLM4KNZDB83c{FDnndkP7*lsVKHo$&c{}|Dg)#u~eZ5ar zcg@|5zd6_gorh#LmURpg!g8xI2^FIxuZP zK>y~pykb&QDPvrt@4DS|TU8(4<1(@F) zl8*H*?<}K(PUm6a122@iO{LcBWer8;9APxi{a7dmyeVf*;O94&EcYME-3<~ar(%lE z9-24UoE*0XNP!gzrEJbdQDU$R_`0a@QEzJOE7Q-33<;K?hVSjp*<3aRS0h~qjcbhs znIqH_D2-gDONZPXnq~;Za0p!DSokQ=Wa>{g6k&9v>dL#;J$P{wM6|vedzTEi0$6;4 zlZ8leD=Y48$r|Tt`3oAo@7cm+i7Xi@FQ)lFk3GZ&UyBA;|K`GHhiH0Z4TY|{oC|rl z4(@}%Eou|yfIi^6htGdK`0(sh4Mh6sb5)w84$!G%DaF&eX)Nqox7SFoj}+NktIriA z+L*lfGZ9ns!&)F@o-zuk14>U&ji$Vz5w^tgY~3SHVVX*SH3XiR0eaT0jThCTv$ zbMyA)cPrG?)?Tb%O^qVrTPX94{!&CUGl06yw_gyOv|4)tQ~fCO%1Dia`#W2rQ0nwNQe0RbZf(XKw<_(A8inHHF z*>H;I4`nbSpc43Nbo;ME(NA0kT7=LPUeJWI$GH>7eZ&R(f=`*JRpdBFuT^}cFf>*c znTykl@1Q@T>b!x6!>%ROUIyicW8q}NI6B&EmP3NZ0s`Wp=4(A`;Ay;k{jIIM1QcA) z#Bsmq8&MvLDeUF~H^jS#WlL_+HcEkDEItk;Xo807yk0duhfs`^qlN zy^$d`%FI(%>Wf`%yM*vBN37vLMylL1k(eWxdP^` zDJ*`cq~XeWsVCKM3{+_EHcfF}@;6o1J10H%#QtnxNQ6qp0NdN!j`4ED{;!r-K@?3+ zUJzRc&b;<`HOwz;7cQRs7P1vu1pt8*5zbI;vGs_=_w=;-TnH6Q#itq_T0rbAC#)1+ z*dkH#6>D>y&uUsa@Zxu8c-|u$q+o|HD=#d6jnc@R8vj|+@#|lOBzp}2HR#;#p0I2kX6W|e|~q+MB5kb3f*F&CueW{CNRa^*sKP7IxD7^`}u zK%{&emJd>%Q9w9qrF{encZFS?4r~9~d>XgNMogV+N&>x{BxB*^lne{Y+x&oN z=)vO4?FehvROxsi!%~JcW7*;#|G9OEO-hYT%g3=4ECIfKI4XD4-x4w;8aw2 z?D`J#Wp7f3l>q?}cMquwi-*jzuLpiw`-y9}LK1oC!_IVYZBxT~yh&`B?@LogW|wDxq)XFEW3A}}*?Z~nzYNA?C|25U zxjDa4oI6Mul#vv z8@&4Abo^|Z=Smr4y1QJjP6C!9)BJ2YT$#bf%DuuZbMx#FztG(fXE;+ zFDQUqg0x5x-8k0HO?T`Lly`P67Atx0I=~+1ganY7pJ(U;(5ONlHaYPg2`a!w2=j7g zML#b8sHN|TFSJ)>gYJUHm3;`u2Y3ge%{$s?-&8;M9iqX0EjjmHEk0Jk1K(Wm7G2L~ z`?->|V)6BTvK(wc3P%jlN|7%kvOlDT9D3&VOe1x~*8Pe+Y#o+F6L_QX$KZc2?6lj) z%vy{1br!E)9n<_(j5wR14%)$&z*U zjzXhTjwE}54o9%T3xpn>u1~wZJP}P>az>cxa?(*6cyO(IL4H)tNpac?8Gaf>@(>po zth4%BuDyAyt%Y*663k7-n48&iXKE%Hxo8#()B;gg9fT2!E(kk4TB`TVCws<(I@ayri>C1?ngbm!}YXa}BCiw4)4aF|AHr~r05QxD_I%x6g z51-Dj3nW1U_sI!+#1Lo%g~-nCRExsY{2^dkJ!uS?F*=Y(W>cK-#3xQfB$u2Y>T>}Y z;AKE9cd)~K#crZoi|~vSMief+`f;+TB?+dsuq+b{)y2(5o$h=pip<*@W%=-o_p7%XqQr!kP)-UNwN<=Fq@uf_qxjhG$#92_qn@B#{TaW`z2 zwx7RAvmFjU*>(M3b2@z#DFgSRkvI=YaLl05^K+VJ&_d7i#CBl9pYJqi%T-(?0f`F2 z^$ffvT@&w~Fhl~9_jd5HmPHF{OEc(bb?4b2`m4XKa=*3TX}r^Ry&!^m%-M1wmu^xy9NZNOjP>1g>Mk1CW7Y=h9goorB`m zW6>waauY>!O<)p&iRKiF6`O&^v z`|((ccxv!2pW;Tq6Bn1aHv%qtAJuU0dG3U~?R@r=mpieXc-S_BcGDu!{!G*{nIbwI zFY{`uJJ^TuI0;cGVyFD895sDP{fitcbzhY`^$=?egT|WOdlH+z_t#ohIR5l+R zH-liMJKO5%>5DK`4Zw(%8bf*hQiMyM>knySn-BLuh+g^!KUerCIv}10{4m02vOljV z8&9`!8pGBY<(;Cr`*_Ys9EMgZ{w#P`FgQ(aQ03pk%a1sRf+8Rl0RJMEZJLac$Rpwd zV3P3G#-6_ zRxXJpVrBdV&euz0ws4KBZ|yWAFvLoy?;Km*5yv~f0mG8)xKzGF%q55QIGx0s1yWqt z;YONTGB6zyan_hooCit2dAgn(OPnrjxtn2dAp!UNoCdr_1wGJ|!fNwSYI&Lfm{gquB4FTrYNqT;t9s0R*+jTP$%U`eCdf&v>I_lJCF?zM?0@=JX z1cWb!X4#9n zOg}Nopbm0^dtcw_*OSc^1NY{8-j9rZV2L5P>Gd!}7hb9i0KbeL-%P80^lua#%^?}+ zCNwwDK1st*tMKPAh`stR?HijVW7G==cY?ZC{PN5l^Acr%WMm{UtBKvFnSpmtM5oW} zYPtO)+XUK&7d}TGBsjxT665TQ$#CHZN_Fhz7jW5*E-39D_NA-jHVSuv)I!o=hj5em z(C-2ebh#VU=vzoZ%eWI36!fVYcfGbxNl6WcgyK92saJ; zY{6@#m*QkKuzT;iZ67NJ-DLzl&^`KlOJyFoI7ETH$@q#Tr{(C`U|P|5=iZ2@qeIx< zuTjU#y$z9cs3TGwg?Z^$S?~w6 z@Xnc>&C_~x7bAJMQKS!S#q&k?BK=Qw9V|?krsPEBIc0FFvSge(BW`jjMn9IQe^32> zoCX%3+Rq^n=>gG*)$n-OP3}z`Ibol^XNLCrhxX$n#3VWuBP?u+E1AJE1*9*LGXELD ze!Yj<=4ZMkpb#|bp-}exZd8rUxIc{Zhxj#)=~tmOKiUL2Z^+UM2JwMK_PUR^Mqc^7 zmV)T!NBygI{Fo%!c{-rbaa0+#e{^N>RDCRJ{m1XuB^ou5H=5YeTduP#-gK>tc#P3# z=5^^05zP^Wx+eDEl`wg|kZ-G0{~RDyWkJRRm>#ipiOz0AGc3VL=)-HgH9Wp9&ML_Y zF@I|CM}UgbQ_R5h(M?6o$5v2Dw9BwCzy#u83hbcb|1+r=oBc|JfdLjeZrUa=s{0=U zV2*(SSeME0+?h{7!-wzrAQvOQ{WohY+kd99RhYz=KgrsuP`Kc2tFh4feJ z_Zf3@e#E1GruF8r<9K8U@2bc5jzMY9uoO^kN#IgR&?m>)Ims6nRi92KdLQoe*$tYvARdVBtb)ctjW@TMM(|#!Jc5hUW1!u}yZQ|xS@#&QbR}THf@NX)y^!+2X z*1sJ^x);B@BYmibjL($@VNfTz+b(iCW`d74<7OW);xDQC);TP)sUUkEy){ z6u}5kBF%f=(cVf?y=XW?=r7RccmAwe3*&p0muSLUx>1R1V<7<8k`ognZXF{MkpA-X zm8Zv=cc3SB?9=xbxgVO|?_Yk>0$@@+NX_PE;F8h=`X>UKMdsCA9{{)x?k=5I8nK#I z;#ZKLK-vrrSjk?sImInl*;<{XK161hy7 z+yCaDQz{{x5Dh0zYsDG3V3(vjw$}bn*wW%O7j-i5RCRuoj0f3Lg$y*{+Zx+N3)l}S z^qZ3!c{zG{pl1D8s24G(C zz3uhI0d^Tp$xSR6NDDG~B+DVU_$Y(A+$Q4STpG&6<8rsgAGx~?AIO_6vr^+TwLe%Yi!)Zs-E zz_7QA*-43><=$d#*RKW|7@vb3ZEm+4mgUKOc#LS==bJl=9>-RAzt)%jNEF;a!RC!Y zDgTdN2l2S?$2i8itTY!pqo$N>zZQ|4rocZW`9gd5OrCJVm+87j13$A|mGDNQCdmk) zF&ugK2oY{vi}jKz`MbTYVWi+Y3$~&MnLB~Zt8#~H@d}|D*WK2j7$bM#`sEe%j?cXs zI|(gO(}?F#Z$w)W#}VA6>ZYr6M5;B3Ol2Pvf1n9%jA?)dl^g#F{dl7XjfDj`|1#4n zHQ*xkzjD`zdR}`fL#+9G+g{oJ^{3|R7!U@If4O%+fvP+G&Glz&jAQy;W=F^)7=s=V zLD{unmd|U|L`6I0SnJ|?K_`QuP#cTB`!D-QkdU5m^H}5{Z~?`Y>H&FHk~+?^6|T?7 zEg_~Q?0N0LGq?W~PcrkS9Y7-(i>{hF4_%KD3^6Xjq=qs&-5uMLw;*CG4ZrkQ*5BtZ zRX9Pt8*5f652N~bX7Y8r7yy}YJ_u!UnF(D5x?k#TpD8G6fuXzeV3;oJ)F58Ls9qNK zWdnJdOww_@Mr+Ot5i@?HQ*LtK!V45b6kz?$bZKQ&qD1G9Nsud(sjx0qd&fMjamLuU zZr@a(&ru>hCLMs;_Yf==)QqW!$C%@$5fzxBhr00GCsb!rM9r?3?Y_N)yfc3WqSn!V zK`$FyT41Vj`@f=nFycS%4Pl>fnMl!3@WkhPOM*G*8|sIz_AgH zP7(k-gU>D_&v=b;GBAR}ECXndXU@eIxvN9vDgd4}!7W*Tx^ak9VmzE?xG%@>Uu_f& zpv}pp5iRf+1!(9~ke-LbB;GjuJV9%##ovQ~Ph~ay3vKhJug3u1WFS;KsV&C0o;_q2 zwlGY&%s5|&*Czh^C%QRF_DkCQ-AIk`CUfLhuGaofE;S=sTwO^`J!R|n2iVOl@RBsjD?=0Y2LvSTRjS=THVoaKu@ipH-1;s)K@SQfX)s(T zw_PARMlh)P8`qU$a_td_?@;5u{7*FnpVp(%_GMlRx}CP|rprRfgg&@oc=zZtF>fDqCo z3_*)N^Y!g2QMs3N*Qtvw>on$PPXa~*qTpM^L$5oTL>0~MslmuYlmK}!vM^iRiJ>#A z1dZwAFNi^+iW#{WM#716Q11!!WGQ}840Zpy6X7uuCo=*SA_!yFjo+Ahvh*24Y~s;r*TWI~und&!WO&UDw6dbHVaOoaE?U=s2SINa{1~zIk?&B5%Ep#~ zT%Oo;jKeA8|zZ8U4OOj(a&a`KcxYi1*O!<|FHLOjaY|BKaJPe zQC_{c=h74v^s;Ff3Y&r!KE(Rce>XAe5`qm+K%4Ua*4=;zDa`q2paC|R;a`Kp)#<0P zPwis%X8g1;fZoGyp>KX06vUT#^!@O=Hvy+BIYqYU112%3O{u2{)GQqagiR=?q)PKb zA2>dTx#ic_;5DO5$U>jqBXn!z%f%PA#`8%MQ3g zM&kjV#j$kjS-C}h-pT{3dB|+4JGUs?8mZ&7aT1PXQ>pkac4T)?E|e*%DNX*DFoffW zTQNn)z?1tfG;)2TiluU%Ji0JX+U^L*Au~D~dh2>a7UlOF6xVOA4-Pz5J85&42T8bP zEl|=@m)(>7jW5Bq*~R}6erF&u?(?Tu*f5VAu0YMcCe3&8HTxdMl1W!{p9m6McoiqQ zI38hgNlu=eZoOJ+b)4?@yWC3pmCqyw_A+RThLr0X?;E7dPc-EGeEznX6Hqn^=tTN} zYuWt|+SR&>o-~}sH0X943s=Ap$Mnv~upEI*l~mWdG{Nrp86xcHzJ5e0iv|_Uu?EPE%&^|_jIv9`g(N=R1VoB_))_Z!5eR@X z38KVO z$H|T}H*Eb8g{qc3u_B#Q?w4TBvUberP*h4)(c*8nO=AgXTRSWNvEK(=)1*cBTRB|t zx%2S$uet>6$33yGrx47i*7Aff!iDa5Hry8ZPpAAp$7(7xc*F9TXya{ZLeAMtuxFVLmk6!Av)OfJ&=R% zLg@T==_T`NNR-{4@ya|Ppe&Q^Az1|5ROl~{A9iLP`n)4AzQi%c zEus=fm{YNsB&Cf$p?}$nH1vQ(1SLX<%2aOAIQBcK?w>(M4jLfDr1R5PW)f70xSP-% z45OxLobojHii^h;GVLPxgeLT05HFm7{e2enFhKD0zDNf{MYS0n%b)64YA|9ZpzCq# zA5Bap$3G3sihf^JYY*yr62BQIi*m*`>2BKfDr(cl*%{_I<+Ft&`%&tTM>!%&h%#hnl?s`Th#GEfU@^Pho;CyOM`wYGg zdP>R%+Q;&EI$=kPPET=nTU1d5L-5GMfX!r}{p&CE5b(EVT~?lGb$SN88}l-=wr89= zDlGML}ae5iMBjX7WBS9v{d$63Byew-Cy%3#-CO8F?K z$cgXQ3Nl&6S;F?#&4q8WCrKIe_Q@@yAM3=_o}JmAot+5^(ne#S;V{UddKdRSeOz$NqI8EU{WhwDB43VL!xJjtUSIMj7l_)HzO;; zOpEm<2dTt$r90udWc$s#bzYa5QVW9VQy{`1NX}*#Otj;oJb0&mHnFh$wQKMe{XzN} zL?`O(y>_8r$ql`jhsD$pPj8nk$rlPEzGO+$^YCrd0wdlZvHC!~e&?tj^TyY*aY6%} zwZWv4Zk&p3-D3H(Xe6nxk3Rosb)!Z@@+CFkbyUPXkEOzTwjM16krbWcGKK;KIDtw3 zioKZfl`biE?|r=8dsfFqp6A03f>|<93&{_c@rKD0o3Tm?5A~?axIM2aA+U%KczjN` ze$&Nt99EJ>eI)dl&Juw7;jzguwI{1jl0LByXXIRy?r_8UW+=QUZSF((QUYNGSgWbj z>JzD#FR%l#uC&34UAG(9^#ur^^cIc**GaV% z(t5#{^O`)`9Eq-|<2dKF#)7U%k7L~FgKjYfy=o1ANNd+^ZNu0?5WAcd=1RGKu{;`S z^28IAUy==lu&BF0W5kgl(%Dik)q=e8S$wui+nX5m{635;qpU~mV<(g0s_#O@JMc$A$A;bX z1yoae^o*EfXEDU7lWaKZiL+kpka_MBU0917>@{Kfktem`YYrVw)#)m2CP)0KXN3XK zB+zOl`$Q6G9IXf9_UIHS6cog1f#Ukk`C%rY&--05hoa&&#kWUJ?@P0E8!wTJSympj zCHL$q&dl& zxt$u|GqE!u!AY?SVr?sR51WIH?Kl8z5_2L@q!BEdfUMX2=+#7htffmnMt5f#D6bXl zI>rf$#`VD({X#bs@Nq%+1mf%aaD_1-xkr_YYk5~S!k`9&+n8Ip)j4mK*pE&8R2h$F zm4izkRmJ7*3H$(vqeqk>mo=14hS=CfiyBidHFffI@de@`K=XJJ5dM_{D-$BJo1mt% zknSR<{?3W>Msexeo#$=*@wMSj^2j?MWi3nU>7?2JX!xk1m99SnsmX|!Gq{V%;9{X+HBH9`cTvxl4Xu6+T<|?$|pp!x;}RiYs~o8PWeMX zK1)oF*fS_aDD@RdAot(ELttaJcTZNV`T-h&`tMGqHjK%+5e+#Og;j#smEN?&f z7XR_Rq;#S~5t&ck)3FFY>2&j6lB09koMhwEdB?akver`C)ah%-L59=7 zwhlpuf~+NGB*ewI9K?8#M2^+)_DDv#d5kRUqrrV|Or}s=u^V;!bA@3Ki?a2rm z*}JART~! zU}`;TzGB!}A^!pM`7C{Yl!*DM>?|xu>?ijh?!I)(oQPTD`4vr-@q>PEsR7Q8Wa(G; z5jgs{-IJ#dKdp_)!5+QVtVdY)vD!vY{CZcqYlqd3cGC(&83EI8H08T9lni}9PMMR3L3J< z?r}fuk4q1@w7J$jD|lqA^#m%Vy2A^Q9Wh^o9g@?Wn~=N{tu|~UU950b(w&nCE5WjJ z)jXjiJ72sy)adNUw9hEbtQu6%(LK3VLC`WPa2B9-ya?$26+!y8gYX08!C6O^$i;tOAjx&Fxw^ynLfY^ADmFVUo`qXYI&S0AHhw%EC?eYvRFb{y| z(Cjn&JLDpLs)O&Hr$PiDiGTp~cQ2+GQ8W?s4k%ALU~ggo#Pn&{98bzt=i>Q0NZ;fM%?Sr zEs;YKS>*C3e3@P^qR?_Jm=7#-oc0v>@r7WHrMPs9csAx0g`a)i!&_x(2z(;Nn`Pvo z4E^@;%Ik~We`>P8rHZ#!`n8>Q@7bg<%F7%UZz_IJ(m4~gVzv`3ylO%|5qKckX!3dj zh)Q@WV+M7=Re#onxI0%Hcw4^dm)4jI8Ne;szhU&`vso&76x3A;qd9dGnPjXz))B>G z*Sa*c64(_=>i={2v(%JsWopYVg)xs7G7-o;d(G2lF`fR)yHLNL_Ylfer_4WdSB?9o z=Q0}Vtq!uL4jpy4vs-)TY{#kJ|Ei!r%5JChQO8kNQE3jkYhZccpkEfrgJ=_6*PjZb zi4r)8nY%A>i-XGq+;VmJlwq3{?utCRK$)o1dQxu;;V2?n)?KiMGk?3#CKqxyy^KgwcY)8% zt23N??3WE_S-ttpfUtPgP)Di$6~s7=;Hnd&8{8_F`$Sn_Xqxdn!z6_vk#@qxciG)R zAbaB4GXa>ND5^>GP!Ox%ptEVA!o)Sxm+o|~qzyF}=3uRJEyN5yP^*D&L>#WDdvv8O z0+f|=F2PhZG?4@P=f#M&XzZ^zd1KbSn8Uqguoo5&I*}rBQXg2ONz5xN;~m|Qmh?yLH9=^z^hY&~BXO%DY8c6oCkPxf31#{yTOd&0XxW1l{x^&FR|`~B3K>pnq9^F;nFEY$Cd)nUVm!0&n0^CpTJDfe-=#;TEk!+jNL%(##to}i>Jtz z5M`BnAkfDLN*Xpg&%7T*@y1c&oqCI$6x3SQD$g)V?4*)hLf5SmLw0mCFj+67DN$X^ z2Y5`%{VpUcU3IiT<|65aWXmG|H%(p_0NM^5t2z`V^6XBu`imDt^+ylC4^Y8_oX-zX{iW1fn)20x*TuVOu7J7xgI81QG7pMM9$*hic^Y+;V6__&X9G>t({Vw^NAO;Y3axAsQwW1qaDvysR*y9irxW3H>5 z3^op*Rbl`%G&c)djaN)YL&O;qrwsUPvOir8Ed( zzd`<87h3jG6YGDXuMIhMY-?ubl3~*es^=(0X1x*D-ERoD!YgH!J_|NH0-ghxHVUC` zh*D>d@VYooQ@f1Zvc#_^;b>E_en$YP-~ugFTL==!fsPmhioGmkrr&*tr5#EG{?jD7 zLoi-of2HC)&;{gMwAyvLeJK#FrMS<~Tk|mS?)a9OauEb3TEmsSsKAA%^h1U_ZIzN- z-^**1m7K78Kou%K9lrjhQ=1-vWLRO5y4_LRV(G{V2K}?fBHA1+(1gFySZ-K3CZn|S zAJ15*Lc7{6fca9kmGB39e-texOEKG6+wbogG|?mI=-{gr4UAHZl3qB61XK*)%|2TZUa7c!aGE*!F-+B#u7v|0fbk+rV)%z8X3O48~Q#b5;Glvb}{#!QT9W; z_V%Y<4v|2}=iJ4i+_JUv!7>Hxnc<)WF=BUF|`1`Yb1fIB;(ul&_6NQ<;(_Q zb}KOYcR%j$nJngghJ{CWF6d)qXrT3=G&9)7A87K3N{A1jhamGU*Cp}M@1#I}P+Wd7 zp@a6346%e}CP+ZaR{daSv-4OIf6_Jg+VFBBC85*3rX%>!g>|~{2{(dck&2PN$Nff< z#(;!_D}q40KR;rqs%L+=L8%oJm;;oDHs(S6-v`OhWsxEH zGUOY(ar03JEKFGiBBabW`aUa+oThOb+QSui(f$PxRJb|1Jdof3)Ki6@DE;l{TBbc2 z|FvBP{O61vefr)k6#7_}=$(TF)XQPCF*(1cGJ$cLCK5pyn8{tNN#j?aNIby2%(zbD zOYb=V#`(F@i%yk;2kT&DS>?h0`6*}ZYi;Z-#|?d^4s={pCjKJ)3$ zA!YOvZD%_s)+1#GVs z{7-BCtAbU>ZOv=0v0|gnbk!9?GW1hy*K@P^AQO3YNay9qHCtP|KG*I&-03q7v-rIvNuvxL0rZ*kx|^Wt(EY8!o@t)Y{mN)T}EAC&0lf~5{! zx=*W-e1U*HGd=`h&VT4*s}8!*q#?3PifQyc)%(HoF-b?3Cla~kKx_HFNVq3VGF;r9 zAM7PBO`e1M+XQ|Q;0#6)L@nY4e{nO(?>@EQ!%|0**fD6U9IL2%?Rh6`ey>zAo_>B9fC0M(%CU*`j488Sh;uXNO*%$T)u5n;m*r$hedI)+c0{XAk{&3L&*{Z$H_38x}J zh^b>Z)lEOj8U?WOUZ+yktwg_vONnLxt!{#TR2kI-TlB){uQF8s@r4(bHyA>W-~ww( zmKcJ2sNm;HA6N6>dI;jP*SHsAGQ`yZtH(ZXttp@lrk3iVT9}b|E^aw~)rXHYBWFU`ZDnjVt(2dWyHujmc{8U`uGeqssRs1YZ&2T#++TdzP`Rnt`a^Ae9mGRk%48;GHAs_5fR zF5~C|)#$XaJ?MDRaBFVy%||lR@V64A0YHM`1C%Of50iUEc_;=&Ep8m)6$H|UXobkg zVw%Q&w6T70Iz+D!c<@c60Ep$M1lN25&0t34$D4aE zu%~UjhYnid!%fgB5`%5{!LzU9YRk`t*qF@Tbb`RHd0oAimR%=Y+vN=~D$^md&MH}Q zu}f8n%7n84v^eU7133dzG*l9*93k1D-`vZBBM%aHToQOA7&bBqmZ=ZIO>l;*y zHOQ*i_}H-&3h)snyF?Q+CVV!8_`Kdtzp_tbr*9`HhiGasP8o84MuVdyrMNxb_%8RQ zSQgw!zjb&}BYyGIxmErc_SWv$i#6R zLqRhbZi_5LO7jC=!lL(#%fpOiiBPw_6=BW zDv)A>U}Pg?V>3K8P8$>sPc1`QvX<$-X{dw}LfNSd238DPKAN`{?CK?EG>9svn1`KHpoEKF9hobiCnSd|Tm69;mMp z?5f&l4~ShEN01N*5}XZnStMo!9U0(3d1UCUgCntF#B+T(w>C%oa*G_b6LT*V@8r4U zm-r&Z^4p!4slQBY@spv^Pa?*@oqZ?4t}`-?;_Jn_B0QuiRh+lMPqeH zncOqrL_$N?FRR<2VAn%n+$rV=4*;r7qdi6RF@90rC}!_-;%DBg}#| zq=6R)rLW4%e||08>cN-vI}fD zAa%ms*+QO<}K5fn#m<8awPLSze>f;$VK`Zej`|H~zj-uK% z)45Gt#?{EYW>Al~l{%4Zan$e{DAto1GS0X?IX%sK4T9bG{h1Bl&rFe8tD;|iR5n_ zZ*i3c#lt;}9-Nexu&i9nW|Dj|8w~mQo9n!tbKN}4dLoJ3X-j9wrsMuK*HF|5uvP)^ z+vgI2AX5la-nFo_-X3IpX+Gh1zrbRYy4sNV~f)GQCI0j5f6qu*w;VR zlihCUcAu0TH)p(}QY?osuM&bO*S%h29!zWD;dXmN=5h&~pVkxK<@b00onldp;oo_n ziU(WLQ)WpccrucUtRM$!&%mRnF4D*;k}{a7;9}R$nwX43(Zwf^WJ9jfMU*WFygLd0 z4P-hWwxY4f z0~WKf>PmiOlz@##SFv-vnx#&zfI=exl^1@MUmi4CTNO3r{}@-kYH#_IiM5GvrAKJ zT^C1wdDDXDwBW?iq}F@12>MU@Dj@RP1WV@rS{)v1457MkP7}vE!gJINz;l^}Z-Yg) zb)zXP7wK*$x5$!PCbfIv7U!-_Q0(96p(CQd$F~Q3xi`w0pvlT^F*A&SuJ+6UvUzCv z#?LF+4jwu*p<`U-OFMaflWv+nb(MRpoGz9>FEYhS%MChKwUUZQRb4C#)DC%q{P#VcajQ9}yzvi+r z^Q?#uuCfdL!Z+OJ*kWb=03JQ?1a%ah>+Q zQ|=!V0^4zxs#m|-_I>zJBhQ6iY-TQOB1D45NnB%!IiXGZxp0SusxDSE`kFcthA5vwb$cU5dV3rdi2r47cznfHo}(>Z%R{?1sh zozA95UA1*we7>RMTsj-G?l>>ly=>UH??FEP>sQc8kn~f3bA94&+ztEw{T>F$y89FN z93cCIlTwdN-QxkO337M{9JO!JISt%d>3h&qPvgCjZKQH%M&r2;apRtv?FAvyXvBAs zP-Rm9xTv;el>{|Y{hq;JfTY`z@A~7uM;b7(%;S%WR+yC=e;bc#`Zp`&%pII*;-Y{# zB2EV85<>e@eh>O#e@ZPNBb+K$bsZZY<3Q9|emqJZo~H=1KJRoy&CdPCoDQv~8HYNY z2`bNB_L&_L+jPoba*SAgVlmCd25_%F6pnjGj=oRy8J)b>aX}}nJ!Br5pmd>s zriEz==!c9X7mL6)HL)wJk=He0MfI0Ux49xi)|$UAo{OloA0F<@d>$w}XaD-G;k4`x zj7{O|ZWGodknTkR$;<6NEFbCSYv6o34QJ=yf6MA1ZzT1&)w+{ADutc&Gi+Qqud`l5 zs%;v7h7GU;5p1F$O-JR1#52y5U-l|uv#)J`@Cmn213XQRB>q^pMX-gFM&2R)3G~f? z4Rskt{P;7)tO}n9Cy8XclY}tQ7SKcl#dXkD9xB~&7{MZFFcXt#u%eYml$vb9O%a@-UWBR?)A4vP(;s-fy{xcOIX5^>590JZsuC?Fs+! zVr(_`8U1PZoA}M=eay31#MP`o+bgVPl0RA9~ODQCCan*mkAF$4iWBU?b87HzX9lq zp{rj8cydCLNx5A*S`L5l?~0WsEZs4M$%1hk=ZyL?7+LNJpc9hyws;Ey6m)Ml7iXZu zr?;t5t0XIOt;?t%Z_F1yHdM}PlDS)|0|Fw>ladHG@7|yEetV*KUosd6rO~6ZOC^qg zX^(+O)dai#$_ux>e|e&?cF1Zb-JG%}p=n7{UJ^DjlR^t!t~VIZmRIj}!)EB?uuxWa;N~MuJK~uNj||fy9*#qcKw649kW6e`eK= z9>L@-w!9w>H>t3uJ=8&#ppBBZ)`WQsOYIe3`EzFs#V=>(dcILL9tqUpd>GNBTt~jN zA<5`c4;0-f1(E*uuRGw6YU=RMdHDJ%K@0D)OFoi@;<^cCCJwH1`4Q{NnfTpHO$Si6 zz=rN40L$BSqBP)h0{kiViJ{^O@#<5Qa`kn3jp~lNh2ryLN#rCJ@gn)s?Kc(xi|Tzv4RAA21x#PQ{WRFL&zVaXtR58rBMne=0eXsHB|AitxO{K@?dH9$X*8#&UrLxR&-Z4z+0J8R}@OW*}yiM0gSCJ)@fYslO3^{d>NwEuderjHAlHB5}s9Lr&Ma@$Wn`e;^v$O7!Ni2}2HtBi(I)bIYG zycNek635gTB{{TjPrBAP%9@BO4bikTazn+~u5+{`eYMy}@R0YVqJ^Y>^sY1Ce18)1 z=U9Tfw953Jjza3sOk^biH)q@F2Q@>vvBT8*gMv>$^0)u)N!W#LA<=?&lNlU*P9?HZ8mw1Wbdsa4oj;4#|{oE8=P|H?N zlPW0bjEaZI&iWYmX+VNnEON^+MKq$TPN-s2g`@8jYULMxGo3}2`cdzH@C{n$KSCpp zOC8Fc)4m`=I{p)xS4ot2HrwDGXf&9e(E@Xn5fhW3rXizwC*a8o3r0Qj71s2gqY&^x!F_P^PWO-!kYBZP@&E@=r;O zEh)d=`y71{aI_S2XS5S@NYC=G^N%Z;m)y~ zK|bXFoWFcYsYL%`-4^`Hsq#^eE|0PJ$yxhd$_cf0n_8@(bIGgYj(gfEVU30NlElh^|NFU#7-zr6qge;GWS)#eWw41xx|Rz_o`5 zoZq7JhIYH?R~olnK*j=nsh9@e)9x$32`=?BT^EEu-Y(J60@;vn$hW*H1t55Q(kKD; zdkP(494iKjk?5Bf_X{FSF{h#td|4r?#Q=TBuB|=0J)&z#V(UZp?1w^VF8Z1 z1^Zm-wXejJxJzwEAHDmL=KlV|`eoZI!hfprLn)1l+8t$d%A@eXU@}ovC8fXGY-zgB zo)Onxq5?PpmTwk9K{KEw4yVlR<+4aZNkZB?M`sXk{gmj6RH{?w&!-^ zf%K6gW|RMGF%dB5u{8hN{1N+nx{IE=%8M7Lzx=*136F=-r)Jq`$msv!KOMgZ7RqUA zT1S;47bUr#r&b2rP#Hk!N^{s>IVLEl50kMMtb6+e_nU~sLAvS7f3r0z(Jh5@93HN` zj9Ns3L7z)igtbubautkwzevWLSr)C7R@Ff&N8(VZovytLUYl<;`n2;&gRjG-Q3E|q zW|=`=%0)mTrY1g(7R>R|wQ`pqu7QMw-CL7D;3Utl|7lvM^u>hwZ!|4zKb@($dH8P1 zgEUoXxJc2>aaO*Vf4>?R}Ma(r$y83Pm=h#Cba`3&=`e@s?V2r2cHGajwGJL_yKZ&&H z{O-hUT%6VMzIklX+1k#GWwavm+2p=Ni3V+=&_?~|u11;W3UC=sV)s5_)=O3;hR?2~ z?RlDpLI%L@6M9d^#}T2%9{%$AlFegwXH=(G`36bot(U%LwKq=xs7Vp)rb1Aoq;nfq z)5ZB7vR*x`8=)e`&93RWiQ9o%fjx@@_`n<==FfGm(Q^k+EM`WhdhrcWJQ3eVYzqlM}rds3gqbKQiBS)}ZbXSsu#8bhFm%WR>M*nZ@wmO)zeA9j2Kt2(s^6!m_r0 zb#jEp@PKj1q^ao=8M7DUw0xVL|IP%zCet-zr%pY-vTmH3aiPf0PelH?={zuWLTW3~1op zAG@R~xEh`?bn}FBSq8ZJv-P(^70sw2z4s;iu!ZI_EZX&ABkL2l)s~Rm611O}J#!{XDpoP23Bmd`mAekmPmYsdL92gHq-1+qq8nw6n`O(cF zaOCIhdo80!sn?X@#pT(YlZNrePxc3Nims<}-#Io--#ttOJ!GGF5%Gue}yVaQ%$$xOw(LO4NWj1k8%)r0k+ze%cD0RZ713({W>B z4UDp~dLDmmxAm*8UCBc8TEB+1*Z&^rjynp4o%Am{&OLuRbm)m%3Rj}Uya-Qp2D9CJ zPAGM66lUp10D>lLdcKg=Mgrg%BEyjNl?I#gC(dE%rdm<44Gk@K6x)gLsn-YbX0GUy zB2%H52li{#eL3b)5ZRkK2$H=A4k_Ch&v#3Nz~&iElr=fwClk@QEC>+z_8tOBaFajA zfTeZbupQ-W`kppY=-wg!PHm6ulVg7@kG`Tb)0tKAspq*Mbz=Y5Viw zHN#BK`677PCKy3jKTYTc1GxVL{r7Jv9bglAC#rerVt-$3U$I5I&h@X}Tp9O` zp1iE5!_Q*+R)30_1mIZ#|D~#T*LmO1T#03$QwmAki#=ZVMksSn=VK67ZIamVHJGD6 zH76yv$fnoH;I^X|Q%s%3<_AD{ftC0FQ_6`iVt~82{uWME{#2`Z%;1hfnC?^o&43Br zT=&jvr7II}*VMa(`F$QuSf~QkQbQMJpKB@3O`R;xXUY!ppdHiOoz%`Kg$R^5;?J3? zjbyz`a36VY+CJ1zc~+>fZw2Ie`S(BMYEqHGYb)$9XFuCX_y#pU`f6gp=Su(V0+Dp( zh=hlLE5)$tn7y92TG?hOCJ+RC37p-NE76Gi?+%hM>t11HdU{wGep4tKo7T#SaG8AQ z_&8S?J-zs)R^VM^-P=qCAncawExAiFv*7o|{4B(oA^lB#YD)D%JoW3|(3a?MtKE89 zym2et2S6p=&Dp-g)%eo+?xr)~Vkz=+Dn07FuBiK)$(7r>zSs?cUVcM~B>wmy6#56M zsM@&pcoBC@)gv)J>2|99-w+*m;-V%yK@faC6a&pAvNJ%Sh?Z_Ac9u5If6Z*t&83u~#ObD|>Tj}(zquE{ zlW@rR^n0W*;_gqQ!cLW;#~^Mh!K0<9-x04p##0ueNU5vt3TwE?g~!;}i2bfahti-m z9RT$B|HQ3tZwKKeDtHvlh;cp_?KQr&cqB=*sjl-Rt-Sm}f0uR2&EP0I=WqNsj^>Ei zR`5;!Bc)d&Zk)W5T*mRAdPQH6KiEQO5)U`QqCIKq18w`dAjDC<^N5Bte(b~b-@7NH ze{J5eh2AVCH2frKP2AvBKjl745JP#&Bsu*DO8J$Bwuv&MbLQ%HQ5T5H6`Q-dhQm1D zjbP#6mg@bruD%qeA*wrYjFA++h52=L>rS_J3lUUrT{G`xCyD0|Bo+kb*eg{lW|S{c zh>-mGmQ_vAwB(kE5X}OL7;^dE(Xb!J-l-RErG^v&*&Ys#pyPzQCQt0Cea!Vn`f%mVRI*~alF=F~cU%zEZbi3VEKuH_GP}5Mw%_M(bon#q^Ih-c?pyzt z1t{=@_H&z)L=j>!fyf;6PG3|a=uBkXL)GunU{g;-v?eQ@tAdm#15nIosqLcD40yy| z%|{}phv42<=)h|%lW%VO22%l}b=Y$Lv4)Vh?DHmR?n(i6HcOd=ec)NNx$@AT|6{btM&QtLmJCOgSd^}R z72rxy>#>uDIx|ja?!l|Xn@#JebL#g0@&9cP{W&xW`1TV{O_bFX0R=BeKi_=zBoZ6b z=49r0f_Wwxw^w3{RIt2NiZPTO`jYR=)Kx2s0-BlcII=ybhF$-X%T2!381LI1Y|%-y z!g{9$Q(Gllq64gw`@HF-;vYL%0(EATP4T8yo~U*}SrWB8pz2O*t&^SHdxr?C{~mwX zKehYxfu8Rw5ujeitPfv!MCr_L4sFqx>wcGuEgF9<6cmFVEZ1VB(yk~yunS@>A`dH( zUsY67kYIK}gq@UFUEdNZ_85moTD&*-X;P@7&Um8~cuj72CdguCPQ3_9Y0Aoc-gHD0 zhT*qmm>XDgq|}+pWA0z^N5_GotV}kt`43X9bZ(_h^rwsDaM8fqbm?JPtdh~BkIuTX znz-M*Y`_9O%u+j4abQ=^7hLFFQF!G(wTy-$Ms7@{Y%4D24a0snpgU=Y#!nhM0iQls2|H^ z)AphKcj?U;=2z|msST$PT+|F1SLiX~{%Sk*5xp8Jo zU-AWf_V4;!%Ts*LpK#T6Y=9F6;~aG9fLGJkjEM3(}_zdQRI^&w{A!$=G6EcLCD$P)FRE z7EGS9$tLK9^Hwh^NjpmZ_#8eXr5s@jUI?^K-#L@U!|OVX&Rr-_VI+-QV_gYnHS~6c zlHwUW+l1F}M@_*x+X~B0M@?M)&2PL9OMM#WW3@%rr6qbkOc1^7=ESpS6VHaz@pl&R zsM_vr9AncL>9@+MT{P2;kTFTJ38XB?qYO_UGMKU`9~}Jlv9kqo=i)-{H6|Yasu#J$ z!EBVr@g;8X!{euSHlV(H-jQ3J{Vz}VV-jR;-+o-bOVonUtY2__mgr=I3;7fRrxZGn zB+mta80j>&#-me5f((jr8xEOXg2w)@e#Bc26Z2?!g=+cELXmCP!_IZrd;lBb19jv#}8`eoL(_QDX*l*jl}v2`IpJwB^NH^_Re6 zfS9$Tk9}K%FnQCg!*{gRA*sbZ;OC7b^#JfU0Z3Dwpj6v4hp&7vh*SV~$pL&g& z4*ln=t>l8HH!TYMQJNzsLgCVBx5hyw$v;;mFSbE=7^!uCLfN~o zU#cWy=G}_{2z`TBK|ECWZ0xEZrlv*1WObY*je3|S{v7Jlj2%|q-vdP<4!44-Nu;UK zpP4g0MJrT@ze{UY2a|<#ft887y!0b)t-JeS7>4(0Jn!FRO1uz-y&5a3al2%QEh6^M zV@LW}kc70#Q&`6`-+QJXfv;3A6&H37ayP#XqUfI1gnN$@gDv<=`*J4W0vjNzks#@& zGJ{?%dvP9%(8>ZBv(_d&dl9FIbz&pG{&A+jQ+ z&a7;A^cHA~muJPddmoV{X2rX@lqPL|p;4t0RCao#qX1Tf)Q34FDiw>nj`7Fxa}I7kmV2JML+)zj3hr&>sw~8NyEP zpMHFVo*JgON1giLvr98uiDjrI_L@NsS%ymaB2Kez-i0kMZz8{%xEWvkeDnTE;e1J| zczGo+y`&>2`lUSI?YZUWsQB_E_MzmJO1$Z=O>~K}Vp2cY-BgkUjqFQ&n&|(EZ)>?%4?#}1Tte2kDjZ5hY zcCUJ$erhT_uJuqYq9dh6X4^M>odQL(#;N!fcsZ!NHfRj7FFna=@XYZfnZ*A}u!-)H z6oKP>DxR(+817qe=ZKiA1sTv4w7vvda(t>aREUb2LPx7fT04f!M}hd<@iK`h@}U11 zn7PxZi~kuxre%Hs(T}H5@zt%5>WQ0Y{cz^c_2q<>2PmAuM_Rjqbe5-@pUE|E#?L0T zsy2GL`mn7F4r?#lOPPMGj|==W%XBSeB-M};GIC=+>G3}WRX5VeY6z14E54(!H@)cl zp^vxIwC32Zo?p?lJWc;3%AZkZTitwfbU;ztz~@O7qz`_2#w=Tr&VQZwwTO%=R>*AR z`{&$wFAvn7S{S3G7M3ROy}w($ew5-rqoIB2oFyOF0ZcgXcJU~Uw$A??n^)AgPCbqi4;`QDa*@P;GP2ND?~G!OmKG&Of%@6UyBXw@zCUv|T|W0<=IvGe4LnrfU9 zq?%oO3s0C0quP21v8Vz|BFoh}tlu%^-+bSe-FiJTAyWdcImTRWNU>zJ%d6FkQ>V>&ouyjm6o=O0+0@*C%QUc~6f zDqg;8VB;LI1^BA68$}`VeyoI_mQnO+?7gU`Rb&@t@ISt+9B3uo^qXU^80If1^4R3} zESWjTXE%9pp_Zcg(ElK-O1RFt_G*65|CIO_O$;N{KjkL1bI6G_O4X49&$vnTeo^0# zLKN@Op-*Mj;?xTcu*S8(dAr6bgILB7DN}@-(BOj!UOyhSQ2Kjl7%d#rR%kph6(CeA zVLuDtGko1&#kQ9aXH}>J+7i#e(#odhD-TQXvz}?(d+1`!vY+fP1I}kQEq(iA&jl5x zkk+@$HFsG-2bhs1slIZllI7Jkq5Pq1>?}z&L>(I5w0?V-Sqy3~pb2;XOWIzeX?SiRJ1r>N!Q zb-=@RvY`{2=c>!F%dF#7zEn&8@yS`2eYHj1gDH_kl8iyD09Z0eUU1#yK*m2#O$K8M zOZcP~FRI;@z_$d{;QJ5|%SX~Z4y$EOV3~Y>D(Ks#UXU!MIOMALFwp9#LLdI7sz&lX z|H^i}J^wBkNf%8IXg)q7l}6r+)Gpl_xiTjWdr%>>d&_O)s#MLMg2r^q! z6$x`Z_42NN0FhaC-#T7PY? z^0u%6vtiGxlT%CB7fC@S%vkV?6QB!w!WPl*&4usC(>;02RD0LcLJZK7bW1Wd^WRIx zLo;#w!#_XB9)!9>4O9c(v(XWyR9;j`8r` zECd_2g%5QQo=#k57^?!zz3N5*u(dDOsff64{-Q%BfH)TWI zYsYfk(Q@;k!+x%|s~=dTaq6NOB1nb6f@AxSJPv#g6W2pT$A z32=u89V*4D9kkwMp@rxBRN~`u^qAgY$(gi8jJxs<6+S{5s2vr0^QhR*^`qJLOpjsu zhg3!B0>GUk-G{g}!|_6%e=kz*p8OmlR*kEG+$1=?a|Vf1AS+*cMq7)x$eW61AZ)qR zQ{J@yg|nek`y#f~WLRXjB}vBb?_G?{!l)Hmy}LuXUu>eH$qQ(~gWnq`{4TJpR7Et> z$iE#m1rBPxG%QajzL^LTG@S9Bmkct>}5;vuYBn48s^uEAfu7L4qDRP=Dd z1Gc;3B@L4UV)KIrVk98M}Y*un>M2t`xNA^L6$PA&gPAa5hrn`#sU93DT zq{f|bz(q?++aN8`%1sWoi?ckKdHs0$ezosjVRG?T zFzg9c`OP5UsZ=*oCNA~;&Pec&^Zb_-uBa$>F2YQTO3G$0J_j0-UK;}e^AOfDp(EJd z;~?eR1$YArK%%lUgT8CE06-2Sti#T>Kci^mM}PPCfmt+pPOHFJykos+7&F?0{9^rtzn?lwZ>l*Jh$ zD?1%)*gaN4h6)nMppbjXA07?CgjjkhpA^Zf{%gN=^#qh$=R$+5A>DOH6|R?VHX?rT z!_vaZHkel^!~cC*wR;|;;rFF0ui_($l@ZD3^)?JwOdk!(jHAI!DI%YruD|ogQi}|h zogBV-Aws&Od;KBp*<#M?|T);k&pSV1qCUsmfiM{QlvMr#OwGU>Cu`8}O< z#u9}{F6S%MRDcKrbt23A*h5|BJ@;^Z*(NzO|#s1k5kU>`|@xO+6IYDi;?bldf2>G8OrdQ=lE>JUslWA2-LGqRf)<3Y+^~ zP-cL(X>5s^&E;%O@ksaA_`h;smu#zQibw(BRtbOv5ZV|J91(CZb9_8h;Z_Hn`TCVN zGl*fWV-s{2;kPn%7Q$1ghx+gZgcnH-nJK19;bOpEvvZKai5w=m2zn;)a8w^rC|wm& zM2X_sHiLSPuZKr08*owZp#(^~sgW@+cyRP%t<#4ItTm`tzr5~YRrZKs^cM4$U+|g_ znS;@4quTLYYNu$rJVZA_O^QUiMjFDqtOiqlP4-AdfrNF>{Un{}s(*SQR(U;nmhflB zS7EUYk=TTnbfO7=+C;z7g> zR&Iqx;Eng#ciM8J32CU=e;3uTn1K%;A`fC(Pcz%>y4E{xw$5{IRp3MPZtkWzRk~HW zNK*|iToau&cOyyy?HY@eMx*|y7&NNCC%!d~`V_2xlro!;UUu>)H+tql?lXBvzqI=; zZWDUt`Tmto7IT9KFAb)~`qys<_B+-qD^pYu3!l|5zYSChlLx-IRkng%IbM@*XcFgP zA!~G@@%HYKU z$@n1MI$-m|FYC{OC{~>7Un)yyJUC(~xhYcJ-1FHj@=MQXL+EUCS&V{K~jfDm4jdkP#7#7LBO0NyO9`0iQYVslAZD&>vW0?$B(+4dE zhzQkx8hN;Ujm1bFq0Cpi^!x;MF5+VSKoK-qK017Tstn)co;;R+8k%% zAtcXC#+uWzQ&?M*{>dKTouxfN2qN2plrot-5q*V?nF7y*uB{VUCn)8G>sg2mFE z=?9_SqjEfZ3h_Lq!m0u$==3Y;%ATsagw*-dvO+4uKYCEs59T-{6WQHvLQ=wux(oFu zKOd34yEw>THk(&F{=#(qb#|5+Kl%+IA83Kqww$Z}FIvidkE;tSeF8}}%Gj>;l6-b^ z`lw6o>S&b}A;8luyZQ3gLoU-*OGGpRYXykLQ+KF&O5%^n0U3DI#<9kGzve~HWd8PVPq$TP(0N@M>$__{-gsFf|a^HiG&`coNh8Dv5 z;bh@<;EcPw$4zF1$n*i67guWtS;cW<@maJn-U!>Wbf;yCpB3{*C_J|W$}3-@%}Gcv z+WpcqU&fIysBw1TNKpMsBywg3oYJS9$>m{Q_(1B>ElrC+A+XM?465&)#;RCqabD73 zh`cDVKdxbVx1}m&;sm%dIPdSM%!)7jho~6MJ8Dc}vCF{f3%Q%OguiK)7#2iH8SBB> zQhJ@e2z;WQ(-}C-)ve24I?Qra%squR#&KW2q#{+BeCZv1J(8&_oSNQdCFHGys9jIw zY<*o*knm~0zP2ti|6&>I#Z+t`%WX$U6_|L4Q!ovjh3ggGcZr0rKcOmB-?x`^Md8t5 zlK33mhWc6q1`PiJj8>_Ul5ql#QKoDXRAm{mnhbgRmeeekqf0y_v4S{lWj1wEre0jz zFnFB>wPmjH?TkU&4Q?w_Sd8ET)^w6 z2-#o3pY9Rh-kpS;ywGxV1Fe7`p59fuu(+6VOBj~Dmz(AV_A2ycB}}R8nq%eWV=4!z zln2K}(F5V<4y6URBtl6cYT}*U0qH8CSU+EU6NSLNRAXA5Rg8^Ba$8zj5HQ2GNmGmbli_SG4MSmR}K2$Cb~q8GQ9u z*}p=K7G2SOv*-zn5;wAbr0iwh^>EL^0snWs$cSfSpZ*O<=LwgW$O}D`tDdCh2M$+` zSvQ$q$$2mk@hrs4kV98gIo*00D?$co7Cq#2I_1u@!uP%l3rO-HhS;&g^V>lYSHcLq z@^eSi$HW?WKTUFZG$5zqm#5$LoDLp@D8dP~6C}Zmy`?>``<>*TKB_VBV}i%ac>|nZ z{@hQp$dF8=`k4qR$`7^r*dw6z4N~TyCyartVm@MM(s{8AEB#;!k<1B? zi9W1yak|O_19mSSM1hBR@6=x}vb_3^xs?2Ht(Pv+J zqn$%*Q_7fPKs4`B8Pv%Wd-afn;XmPx-Gg`a!hYey<^Hs~Ru$0Oah1V7YO z10wT^@;$(z|7w)l$YT63-cJ<}B2b=xt+2>H$_$Qy@qkf4(1Vdx)FOQSx5p?+xA^7D zTQ%ZbK_@fTZfxFi7t6qtE^I7Q9P`??T{0W4`7(9l>uX4is;)D(|5SWQL_4Yj(Z;kZPc%5L?NA^}u?9{T!nBGH& z_yKG8horRlyd*U#-D9~0mPjK~*rNs+z6sh@;R368M(y_^Sx!RwVo&_Q{AAG@?p&ft zh$9yAS-ikn@_jJcn3>1hQ`Hk4cLL_@AAQ-ur%1&3{Nt1ps zIYY^Wz_sVoeBmUExU{)`WD10+z@t?zfeywjq}O~unNbhP<%25!ySAp+E0=c~(N0r! zoTwZQ8_T$=pdbx3W~Juf#8i=dVn)2mwRW)5An3~>2Q|Z=yqO{UuLOn_dt+m=OY4h1SY(hPbl1IQeaApEzDg1#EI7#I>uD?9DD&ufV@{4p{ktf@3_Y(eBu1Ui0I#)7X>*MgYqi30HOLW#wGv& z*&fXtuW!6={_HLh%f}5t#JY3+qd_%E8U1sLR($Z_^lkw320SaT z82h5kOg@SUr6cYbpZrT{AGVm)3x^E6AXID!mn9D&s|Jt0eykbs^(&WbQeIQO`K&b^wH17O<$d2lD#{ zK-4#eD9U_8Nes|ttR#1kw0C}->m#e9!apyCD+WxPX9C2yc{hPVlug&2AGG05am`s` zC@~uJ_^*&0@#6erj=RBEcf)-0ocf(?!iu*!KCRdez#f}#*G?UA5W}Uy_?7yP!_C>& zZu{}|E#DogNd-!2sBMojoSwV358NaxjHD@DdqJZAk6Q_wuN4O3KrNhmD|Ds`m_e^y zDpBUedG=jT&kbOT2t7?FmPZ(c9?aDp8hG3%9y27L0B^EC@-Z;h;BL!YmsQwVFqq;8cHzR>{=BCkTFuE$% zaOm9aJM3CviSpjxb^oV6mXbEv?~w~s)b8siRz=pm=RbeuY}q8(;ody9!5>Bt1K>0u`jBi-{`0b%22{9Fy^ z2}P@(JJp(Tk<=>#rjWbvN<$J^CWq(X*w;+qE#+FASSCD5NUx_fm3`}l+?M!?3hO=W zx8*~)`X*D98chk}PzHW{xuKd!i}8hz+c4eDvBnSXumV(GMU^+A3i?ZOl|k?o8! zr^UjaV03aG|C3~o?XhJC;YbM2_^7h^j7pRRW2Xi619s=1a~eanS-2C~mY3cava0~M zl`@c>(}{d#>B8S)uHCftv}5AK1EX5=q@78sj;e~kdjgQC%c3`~g{oLG(paI$&TiYUk-_ZN?2*SahHgLZwY7`3 zf1g!v(DgrHl}3|NvcjY8Hz+%wMZdH#8GN=-PeGcYkkO+HuJI9H65P-87ieshmKHGm zj~~;)&;LkusbtE^s1Y;;JlR9SUBXjT9vEy^FP;~$N1Oxn&H=ZunCpb4HHx1EK47YY zN-h|C;t@zyKa7RMzl@;;5l^4e`I^Qg@S1w`bBr1&&q#ig%0ayrk(PtpEG0+$)BBTM z6|Qo()z`%S8tK*&$j%bD$Oz6X2$Eq9QfZvq0)2nd8-XHzlhnBOaDxU;lH=~!f@5y9 zrT~o{toU;YB+u$wjkAc)q|?A+rhdtQBFZ(c(5Bo-2VB$g+i>QZw~<&O+8}}!KZ2%P zO((=1ki43%rae2Cu1@Av@Q=Y((o?F`m-W$E!TmdOk?@)h#*#os~-iMUBp@lQMGPf0!-S*iRSN9GEGv@Q~A)CQ)IoH=hWj&?efF$H&k3 zFNn{~Bt|k4ARit?p;AT-Ue4D+jRN}b6vDov5Ypx{7D-s3rv9>+L>)&in!~u3rfVgi z0<-u`{C>}iVI)1Q;c(gIqLS+Qt%llr)__Q^DEZ!3K|b*YP`+x(xZ-y}cL^jmiR{!J zQ~P8)=F}5|zQ7{-M_>;~jpc-OCso?=Zxvbe_cG>mP{4b#`qF*^!;vT za`qyS(VlZt1{TsLDPX_uR~sA^QOKXoY`(i%S8R4{=sXFrmwJ0`gxgGA67&w5{VXlS zz(bQ|c#9(}E{?DSJAEDM|AbGN0-1qM{iihEOio{YqMN3*Bx;g$L-QiEL~flgyyAMo zXdihUS5K5Oj4C_y9E)>Tjr3qbY^J=XKI}cxO4PPHi}6q3;kQl%Qh54a6iG?snOf~` zJ$KCH_%9^va?cvoukvEPzf0N{OA_=LT`kH1ZKqaWXn^S+A54C0V-3`!CRzC@p_y-$ zXr)okx5H-=Eq%ULJEv>OtqUVT#)`mgd6Qh(G*9?BVqK0Qw5 zj!Q5KUb2dT+;KTqjf&Kph?~t zLz+LUMQ_WPXSWBZw?B&grEH{50OI>Sl_4bPJpXl#9; zd7*W5`j9|$n{zRGmYSY>c}?2@qo53IqbT^}njyA$r9WftEAID#=4RmzS9#Sg!i!A^1yjAd-(nFof0DT}||f0{^C= zv_|81-6Riri4Io+8cHZD)SBkVoC6bi0BcrziT`MwhCoctpEU|*TQA1yLg!Q;YIC~d zUt@@A)+!CJG5)75`ItvR?(N}n^XD#oX3=7Ic}7)|)SM6a?jybvqs!C)utpS!f)xj( z_BsjBF;3+-p0@@g#T~@8q!XU+D1}h^M(^pCy=ZOg7odhQj2sbYQ}44=qJ8u*T1zTy?)8-aqaM8LT8`-=RrD?e9-9Swiz0e_gzDTN zMJYQ=Lbc4MoiL^&PsBb6&=YA5b25O8JaHIMd*~zCz)mMXO{Rz?nw9kxQLh`z8d}R4 zQR2U(B%J(;>6djWPXKd{#6{T7u`8!u;-#Z!J>eFvO!`%aFBr?Z`&N!ZxP zcXn8G9Wvt(``o@)rFKh>0s)RIOIcN%Ew{JZX=Pbrh4l7ngu3i{*l&EmQb7(+=1BCh(sM_bpO=ehjQ!zU)h>t^8&ju|jya$exbOfI*i5b*gMp-!p{>eqv80cMP@ zove(tWPGD%{)M_=Ca(3R^R_l$i3?_B%4^NtBgvr4Tni`5h+j&(W|f%e$8K*~kGMSB z4P^ooT}9uK0r9CCtpc&d!9i$^L)K3;1s&ng$Fn9L3#>~OU&;$yCGh^&Fr5j)ndfm& zUt~I|&^W!&E5C8JMx_~Ja;Z_PI!7LlZV=_U5)y|=ksC^V+UQKv;1DAXO)4Cj9ZUQ6 zH1ArlJV>J1Q|ir%_(;BhcuX-_3}(>!;i`{*pKg1|mojG-7sSM4Oee!s{B`EaV`Xe7 z>R7c?h^A2AR=4t}0wk?VTzI3F@0XKP@g_M;-ap5HLRs!GF#xgcPt3udBLk^W=oI`$Ma{)IY;3|LGc)&r5 zWvgFq1&FLFi`%0xXg362(mQ=XE{EQW1?a9G&W->4`IGD~L`4^2q|O6gH#Z?H8WrTT zg*-mIY1X}7@`3$|)z!B{?@bSI&r1-(3f#wJLv0%L!OkFDP`e5-Vj zp%YO&_aIA6ztrsK_GdN`Bp7LlUrU72$W=3FJAL?R=ToIQMnKi0e>`H0cRK&N*oV*v zJwY`P2b^c;e_m8>{3};*Y(F@A^Y-J!h0*Ch7yN8RwPa>Ycg{+)0Oktt;HdKgMf7UJ zVP1ePJpkaaf5z$hVWm`!@AK_(&LQ4i^{_Zbo6k|SbL7&n2k3p0L^P|1&ih>I*?&W% z@@LO8n~9#YQ*6Ds2vITL8AZtFU3VFJbYMR&t4>r@9Y-)CZf6Y1zw7kerinY68K5%WfLs zE{{XT$utiPp_R-621pcAFSM_m2`dy+I`Qc67gvBGhT|cjZuXvt47v-lRISdoAzpzh zaaDsyeVBY(A|sG6CFXwbIj_{eCBkt0;Ny_ER1Zw?TWOr;Lh8+9TI${>$_cb7yg@p& zJ@Cq*`(YbGL0uTmEH#*r#Nej`i#v~$R^WA}A^~!~#E|*o6Xj_=pRD!y?Ajd3M-B@H zql4l$$;pje@(VuSG`?e>^+m6MPDwjvO7GZLS8_J7uFwO4*ddQ{MA9qbLXA!tZ$sXM zl1?;a1E*_aKjuXH7RVuS*yDH13^Mx!m^h$@nR{Crfay|&c2GK7)g_00DPXImeQo-h zw$tO!1vnxvnR`8)m#lfL6ttp#nw|k&`clLSHltwMJ=$L`F6K%$6#wwJUo#~o<@fh$ zgD++Q_g5#e4iTD~Lkvm+dM5lAX4(7znBME~a9?i+mEgZqpMoXT6))zOzq!rK%6m%3 zaV=p6}(h@=o6HX3b07jZR?=sRnQLzlc)z*dp=i}5H z=MPm(rCLV$>_R~7uh+DSkY&4b#~aVs5}Mw$u{k=n2YM7H&hNN|@F$2hJs1(~+6t*A z*9iVjbKxgX_#Km)WG{ub`BwkFd3^&6f(*Q?dBAHO354}Y4#=U>$9cE=vA1{0b4`V* zVI>>RbZ{paQzVYIBI9Eurer)V{I5nOZ)V|n70sgAY`Pd(Gt)S>mL*_UzELA!wR*)O z$iTEAcr4u?u!Uk1kJ1m>(++b&vhG_~kfM~2fiz^IdmA!u6*fYm01~iRXwKR)Cg2($mlf4pd*={`S85 zH2H9A_TqeS?q_wMeazqelqc>(Os$w-T|?kXh+HnPLk^rQd_WOwo{-Ur4M>fHkch26yp_upGWuz9v#I zXK{fZ0(+m{$F_^Fi%MI+>hGuJv=x#UQjxpPzx^ti0{o9R$%li<`MbI*IP7%9Z3K&c zws_!KM<4b?-v3D$nL?K;qA3bb#^KB-8cHyT`N1?GBxAiVM|lS+W$DXDsuVwhQoFzu z$*UXyOY^FFTkIpzN&1g4v&8~ZD8{`bE`xA}<4S3!Uq?oNirvQkrCvXLJ6)U|8&;a* zZ7*Kc*Dk1Xp#9mKXw6?@bccY^CSVlbHgMgEHUqLoq=v7*=zx6=^|;Ce5Dqar>D)o@dHPeI>|}yZ zSqP6h`*0f1wqpBncp&i9c8dQjcD$bZuFb$GFZY1UWy?K~#^@5c=(8vkI67fsM@=6N zlOz23mg6%-1qi!*ix}z%?O`Y(wFh)pLQoyq-K@6Z_)FX0j-00&_MN8VE~;wJ(Q8r0 z87vw8O0cM!wvX-1Ful*ZL>i@clv3dfxGq@0P32y*&c8FluYf^kYe0_yV+G z-dQ_BuAa=Lya$|RTQYnpxN?JoQDCqDNkOG7JxNlR531A45i~s{oT#`54)7IoY?fTQV3 zSRUon1bS1Nc~h*)s(jz}^H0M(k4q@Hk*Ku+R;Ac&Q?|Aq`eFwBwQ1&8&> z=sc%+3rxZ!9k}Ib%x)^g{;EG^OyT%*tu3E3alK$(SH}sW3ikYBs7IiS($#X9A`f2R z^UDi(7EIQN-2w~?b7D8^vpsw%zVM=jo=?yr?wV_6&^Wc5GWr4q2!h%EYcn4$iK%_%Ci4?z9g< z^y4wPsr9m=4YDPfq*J3s&GfNlH`{VO7hq}M>_ktR zri0`7;Ag(yc@<@7dEa!`M=7?~k3R1}I3_@NWlpm}W2se6f9OXQ-tnzb`ZG@h)+liB z&Jm-CUM>S`x+2<|>Sa=5q@oW-?b3HB@nKKEri0UGf=_+q;H)S8q+t{Pr$Q@7m zs4{S3uagF*!y(?Vp?$daePo{@*8R0;ex zCFYV@I4W)s_Z1r61H@KErg?tIPj6vd8vfc1)x8$BmQg5a0_sJ?5*Qmpf7~uk zoL41x7Kjxl3N@1yCc5+0_5!3A9h-ADw6=GV*d5jcayfRkF)7YBuW{Dcls@XU=)Ngb zDJ7K0F7538QkJeKR;Uru)Cvd`ni%+yLWGJo+8I316t|mp=sw(9lzQFFcoTLX?nwdj zj1-l~FNiJ)B`WyQkLoshNRRSyC33CX0)PrX1C|1wmq{+ijP#rg}vXl9zUft(ipuenPEP~M!591 z!jMC8bbz$+dg>RHItpv-Zy!if_R|6aiJ80)q%v`uu2^B1p>oZ*R0d~X_aw})1o>xH zT;o+j)Vw5e$W0qG+6CJvYL=Cnt{?cVt?1~uymlZ zk1?BEvlJZpw`l6m?{D*^E-b;T8%-7!D>5M#WUOo(9oP!0qkUN^w0X?uzi)x_o|ZN= zL;T~vz5<|-Qq*B!^KGKNR8!94uMkf5rx1*L0u*v9doeNX5rm*U?lexMIFJjN*Ck+} zkefEx3tq!IP8N-_`97)-qko8;+nm##>wVqCQW>C<`b&kbb^jAmNArF! zBPd2&?^d-~uyHXqivD429iBayZ993+42S&Oa~XnS0$6cAopvE%sEtvwSh`L5>z+7{ zNKCnDDQROw3mXg%eJ|=MZPO@*LVg)aP62XLiHx|5yl~2b+b4C?KlO~?BM(8?*RkD* z${lwok+A79YJK}UBHyVp!VwAJi2BF2!yO`UL!KpS+$AhJ>^poc-y&Mz$fEuz>adB~ zo;Y?)r;E40J9Ro=GEGfC{@)rul(tanavl-jX|?MD^InI;o2*q=4aVnnjf|7Mr+2<6wZCWc zm=#=SECreu{VwsGYHdvugO?*W&p#NA-zrtv(zTkdW3y(8IvuNBnSt(RM7cYjDBmGB zlJ7(%HvyrJd%v(I55T#L~e}~sE{Hqtth{uc{g`E;HGtPEO*e<>N0liSlawlaiyDD_{ z8{YY+L-;ALj2~bnQ9NiqyvKtdIkgsl@^Z^?N{Urzg8rFaUN8dDF}li8NVah_pS5&p z!!%olzDnc@but04FPNED6eZ~a(;tEQkI^Du^7q$cfITmF1L(-{<0vY1Q{=U;EN2&wwwWL!Cj!tG#{6C={l$krjdD{W=VpqE;`F^!4A%&p9Fphv%G5M z!HhncmGvukHRpk#(`Q=9&x^&Gg9G`h6~KR0j7-XCzS2qq1PbUif5l^BB@Z6OioUbA z%?Dy0!4bZjnO(cjZ@d8>9{nh4X_)W=5CcpAw>#OVXf~2Bn`D(t-eZYS^qhuD9NcIA zG4nvZeM~6WtpC;ZqMCTC^M7QF6G}aP`X?E1ea=tviLX6YFyaHE-XDdAubjA;z0o)o zQBGi7D))c8eOv*IWq_n9Ym%TKUh|#I)<-!%hc`jq5&tq&YffGT&lp(NULR(^>2s{2 z+l(U{f4K!XhlC$tffr>b;jT+F46n$VGsHHDaBD{ zIIu0%OG*yY?nS+f_hgu5E&f+Sf~-zZ|94T|mKQ9M?$F{b@VpeIg@9 zETpdEw8sgP_19lD^SX83!o!x>lV@2bhsz3kZZ7ZojXhYhp31&2XHhb3Phr^7;>vR= z;YDnb^n{Lvhvxy-&Xh?h!zm22nHua>n|rTw6N!C> z!1z;ocXLH%D*L2V{<^ozG8&!Q8B9&WW98EUuNpiiJlW3vJ&GXRSZ6NhTQ5{qlU%#< z<23!RGa#>lu3B&Mq8pGx7Y0Sw&2y)NqUjC{*RE2gx~Ajc0@)JehgI97&wthj0ZbekhYs>4Dc5)j7Ru6(5fSG zyn^+lYsf14LirX)PpqfZ5@`0~OfMhow=G+Zc{eN>eIWfpVuPkt5&XqU6?>xr?4oDo zoKFUXi2IrTjG>h921k~5M_3|_|n-QDf-WxWMnw;yknBa!J1 zsrxgi<4$D7Xx)?E<1A0=6)Dz(nVbcgu$wHS|#b^f50I=_bsdcrkZ(xE~)qOR%8y!Sij>>h~M3uSU8AleS>kQD6gL#%e%|F1T zCFcP3tBF_NsH}Vj;*V?AtIN7pkCjes4K!ZtS_GhpsRp>Ph&yewolFrFjP5;HBLM49 zQ&qZfrbDOJM@JJ@TOpZP1)G`~^d?YFixMJ$jw5s?Cguah#e5y?+WsSkM?M!O*7eaM z8#D){dSb_)jc+z2_Spel)i_p-dYYE`83|Iyq#R!Bk05-0N8O$v1N)bZ2d%~VhVPb3 zl&PnIY#(n)kppm?)G5?E^ThFSakyk`@IQ6-IAl>gyR2ar&ENQc@A-W>;?Vlfps{8i zfazfZ`0~ULJ-egY8nsLx=#dh=`t@ECWi%fkEf3zm7X5^@*{O{T^QVR}{i_M{z*JX@ zTG!*rFP+HDg~FexEc9TN@VuFCUklc=$M^fJsYnx&w82%d-A-Ic0g!9~aWEe_mY8?$ z#rFE<@6^Ls`7(_vQ1vHl`N{!TbD0z=L`N~keuT6Wby9scd|TeTxwK7(*Gct`g^|~f z7Pj}ilFtc=icJvuj{0JmA}&r&5o#DvA2WP7XnY&@axbX^mkW8c_Fw7;Cu$*A37$ay z$1kxUzZ2BTRh;$-@;SYePWTslG+q)I!|L5FoAP~Jd-(pIa``cD`l=+$D`jhJEk0+8G7+rgn7OcsI;aYtmP-Ys>J3+`iTu!P)1mJI@Nf zjTD2*w(UOuOBen6K-N{3AUy#gl^@}Qr4ZFfIH~Yxp=#V;AE;taVD6{i`%lY)?>_hY zLJ2q9INc3XzDyIog-ZR239@Q4GH6|Wpne|7%NkNj2hm`^g+MI|rLr+eiOb_5m81vu z>HHG$GOB4ch--{}uUegk3(p0eE`C%lq(u+@Lap`!`IZM8bTEF7_s)1E6kS}R#Tqdx z!5Jj&1E-h0tew@U*R|~jM;!gTvJc@S zah$0~$-R?SXzGYro469ZAh`ltVD>prw+Du#_hi~h~imD81Onm#0#d@D=z#h$JVd5Qyf zabdl!G=<&rb>MK!@01+IMQIe$4!65^rw)3MKPzOD17AC+B1IBN|8dIDqpdxwMh{}L zRa6O7{yg%M0DTptF~IK2S&GlTseGYixeAXNS>h@i4dDG^9P4cBaqYOjwE+6QCPTE) zZ^w{Oq#G!U?+i+3uxM8=eond#0@e z=2=K54P9iOftg~(CA(gPJizR*vK|B|kg;Zl7i2)vXwqn;_jg?_C9NA2!O0vSAq6pO zMRn5gRXl_@5QdHK*i0ty!kh0^;IU#5o7)GLZZ11c$%pR0z-+$C>yp(FZGflVM;V)d zX&D0~ZE-jY`?SzD^YlCiM0=EZG1ThQpQQ7+OEu{PFxzTDV7p8zD2R^CYu+6S{feQC84FR%_Ahy;y4f1dub^^PbC|;p<^|ey zni{DhT9DDC|Q zISx&VBw@3qUn#b03CgdC-8d{+F`#>~f&hJ^8B5APePM(1!LT$!Ox$~mo&g$OrK`$r zE{0my?-y_hZ`TVRw|@h;2LsHE|8eO-^1Nf_{gjbpmw7;nBo(KI{5}QH-zMobEDQ5a zq+`R~y%v=-+b?u&>@V(0C-j5(TAUatBFD)^7ksC5L8C2o%IWa_!Du{?r6nv-H?QW4 zu4>Y-bh_?^!EU0S6ah|E3Aw|Y_yG*y*LF-`0N$2$;(igWg@Y%FNP#1h7(Z-Y<$Q$1 z6|R8;wYoq>;Ux^jM~+Z4u8~zqIbvE$U~TzV8?+QsWv%kf-&RDawC%ov~mlo^*+a zURpP0*YTb2rYJp|FUDwp`rsmfrtzb0T+Dy+dqdI&z^Y(o5QY=lIFHO4_K9Lc)$=Drx2W`8xU#n@&my-_Dpjmw3}YD@DK&$6JA2$BxHiH&b*K-)cc zGNBJdpJrSLdf*V>AMzOh20paX?B^b7vh9%*%i~j?rz}uMBgVeD)v>n(Z@d^S_U&v7 zMU`qKadym!q`r%)HX1QqDxucS=foLI)caoFdP$0NXg^PBKjFIGm(;i-SGvA*lwg4D zzJ5koDKi=T*KJ4jn#u8`LO3&%J~(Xos&0oRlil6shwIwjsB3wl&37YL z^)Vrv{_#$2Dzi7#(o_8V;}Cswf<&?;dqO!)MCR|k{u`)mm{({$*I0D&`T6;y61g)5 z;hLJXjHeh9H48%3OkTn8@B(*!nf=gB+89>)ppQ&B>?AgE;U0+_!OXd` z=(k6&NVBQO&PmbYcMFNWf;Jz7?#-w8b{ryoC6n1S)X&BH$w{KQSun|}sa68HOZwFt z5ll(=kFYpiCtIH{r69{r%9?vgO)XAlPn)K0Fo_|`xYOhwMP%Q3(Uqx}=uP&%I&zUu>hVCkT60l4oC|3ioL z?pfPt@mq$n&;nz90D#L60K#z*Thxzw+S+wRgBUz0?^a;_pL;UGWQWJWf3S$ZdJc({ zn~6vvl0}H0LxO-G!;+MiB^n8UxJnEW@=vn8;_Ck9T&s>m*RJ*%dzQv=H-86A<29eG z7JBc)WktyFOdt1HWam>m*L?D+AB}d7$sg~0BF&Z;0!dC{3S{^K^;p#R#@0RKg^u_0 zIwkq<%Kly`02TKx?)sSuc0ccup& zI&^YB-x)hXsoqU}%)tt%4{{w3bz$pDm`yZDexPd5b&<>MU!PN3%+^ z+h=kqCsx7m7QlhieXeg1>hby^xg0Lt1(u*p+z3<&#ol#ykS=l5v@j+JY1a3ZN|s8W9&O|2nS@z1i2fhS=D))Ge>%9z zZk}yci-yfnU{F$@({Wnl__rrZ}Lv8Cj;i;p4FtBWb%s>5RwP+q;fLE_ut1zsyr=n)3%$oFcqoO z>p|>GSa;WMbp`My1F~7KT4S9x4EczeE-5vilF;x0X2vb#q+5d zg&nn8xn%?7TzW78%x&N+G`Yy0j~1r*c4gpTCoaJW5G#zN>E1zJ?yX0EZFTz)Vb+zV z`-=PR0!f#Zb{dK)TxN>_l1|`*TDUAIv`ACAh;l=wo2BP2{am?$P(yEB{TQ5Bs(Rl{ zNkRT_EUO+=$_>{g)D1`NNThJGZ8uPsmLBINr7K<+ujKqb$Wa71JAF1LMWwk{Z!Kx) z7O+dh%-8S2_QzLW{(W>6e(9zgQx$z1+TcmjW`nTn8>VDrVRJ!RyxO#*M^DE{umX|Y8qk$^(((LSCq4h>}*`lKBl=Ol8^Xt*p;lxpQvzT|& znml~!nyfKFPF=rCNWiBPL<>SO>krGEZqWB&MrRhzNsga~IZ(nIwtq_S1YN>IRA6HcxSVZ@{t@lrPsw@Wc#`?c9&1J zpeP{o8U@13Xp&Dvs{tx*a)dYnGEcyZRr$csIfP8HLS*CT*%@a32~986Cs|b&zR)EI zp=LNC8d<4f#|+4NH-3kZl=qF+JQPFvmmgCnFoVMq=)QMi*{^3G503vN+rJc=a5LTM zs9<5V9VEj9!6N||=yM!e7>T$hjR;sIoG_#=> z^#LlIcOBaP!XUf*#Fx_cghmdq|*Wzenpw6UJt)d#tA8otJt zO5T-3hMrrKh;#>xfL_xdh1Q3F^*D?_eU$*_1;sF92Q6BY`2%v47F$BD0QPJF^mlV> zCQbq{Bu`{CO}XEAg+Mn6Z{2tO8t$IWLOfe7p){=Zf+Rnn1~y|9{k2_~;bItC1ohhP z+7e^#S8NsO;&;HYZvI9^^vgP_zwGr?obj5(DlKjS_B9$De3&%d%L3h)1aE($6$mx+ z$SD63L_9Tujb`N~{m{)FEg*F(V-7_a08i9ZuqO)~GfGvUh$3FjIo?S6O(d*f20xhp zOHO;&vs*dx?n~}$SYg_3dMKh^`jSyW(2O>vtXZu6C14a7-5UVCsskp`!Uk$-b{7YL znehJVvoEPSx`aks97hN(Ar*IH*HdHi#yHbX(yhgzVnFpB1bte96XI!z$}{^*m6>!B zBU7CTy#JK%uDolflRPR3QvtrIhBAxOge7)DC@G*>Lc4{oIS8R&>cCse|1{wh3;HR# zZh`l*oUYGGxwcp))Bk|&>qivV9=@eIF&DD@nLQ3i6XC*|Nt&u5zN{%Sj~Qw_lnAdl zb&Rh5GDS5}-RZHdi=Wx}M)i@K)-T{n#tXxtghZ6n_|&nvXB9Z>$Bx~ni%o*`sCh|+ zI{q7p`GNwy-qMhEf&EG?K?G+2w=y8pmB&3BA@D0%lXpcgl`sPDSlTd&oHZ2R?=h2Vv98)7Z*A1TEC zFWsi*gIB<{kF<$UOG3*_GVnZki&NIOd7mz>GD_0NA5=E5*Yzm-R>C4`<+?nA+v-22 zqwbFekg%Q4RP9%KAD))4&=q>=?$^6fjIl(!?qH~Ovr$t{QiUTpKs@B)-X9hlF>ZwC z0NZ69v1I>D!e?@*94{ds@DC3yM~v0`fxqyDC-T^o9nr^4{eHK0sWj>PryXn zN6=f2B&^1{!iD$4?colQJ|W#c_a6TQ;F_sLjAlHeUfZG$XIo0*SrIwdE)ROd`(wl- z2T|c9g=X!kh=neZUh!#C3SNgb9COPHK*8&=R{s{5yZ`O!f+^Rj?(98$h!2%P&p_^MyaN^7 z1U=CIsT1G8U@0PgTYk*@1(Wi#SR5>lAaF}7ncRH8{x(4z`91@3FQL74_%{Lb{?9il z>Y%^3C7*N#a!y=gE+!%!-|&&ZCja}2D!hhu^Xc8CT~=GK@QhFEJp-TZw?Yf;oG2r- zbQuDf1=jG&mp6XiL^udzCXZ5io%(7zPQa#neGh@2h6jEmuxzSVg-0O!y`H7i@VxJ1 zOo5%blT?=O5RBfgwQA6>>a@78A+2+Lx`it3S2HNH2c&+{)?UibxD?b-7-g3}9^ToX z*#9Wx9*twC-247|S;AI=9rFtw3iq#;*xLeVE9X|R?8z&&XPSp;CuA%jhC0AZO3@i5EzaK{R4 zXS?;2JnJT9+)W#Gj{mxpC{u5EYsbku|AbmTCeP$Z0aCQS2lP)3lVIMnV$>Be-oix{ zw|}x!48Jq}ZbH$Y*KW5#iFIYcJ!bz7;8qLn$kxAY_IDDXg+wFOcxYpKTZQ@_i?w-Z zlKMr>)gDnQD#h2(gTwu;_&@(v!=!0x4eLnf!!mlSEqWz&v!@i^&5wG!DP3?s6D&-S zM!U)}1-yYA_MJs$p_6!?8ywh#3Sa#7)*eMIna4yb|D?dmfd}?()IC$LTU;c5Dxyu@5}{CH)Sj3Bc@rWFrW24Xpwb8Y!N33$78TJQj01EFM`t-9hf#(A8^P z{zv)W&IhW-u(Ls{A|rQg@O@C$pvgN^%9G09MY`_`Uxn24@MISt9_-3eiWW>s0{ z?3Y0-|I;(y%JlYVaf&cxESK?Acc6EYuRV-apQgqQR2de&gm;=pbZpWVlgtUAN{uDfaG&Cgs92&@C-KBlXXcP1KOXb53 zoC5R{W9@umKk_^Vg?;dgpWgPj+^^v^`qyN}#R$8``4;MVDG@0Pu*{EX067m3$&d2` z=rO}9)-VLXX(DaKwClltEJ%7ZDtjokla(tAhm48}-Ux1g&MtH-@`eA689YmmpVli8 zZ+mw@YDm*_Rg5W*=7j;qRBaoq?w3B0;+uSVB12d$dIfx2=wQ3`o(lSV6^1eWEe{sy ze~Y5s(qgzMPiB*Dy}9Nhh2BlPgIMf!s{wQ?U5t-Ayw`Afi%fCMod^)b{0>w5uqx5w zR4)q!n3MJPyJVtON+{U?3UX$i$*LV@^pBHv$^G2j&EJ4ML>JzDLHkPlTd0&YIUH7L z_@nqD185(ksZ(?##3dV)?EbK0sb0VJh1VH&auj z;<(5#EUuW!buMiulm50BA&9cQ?Qh?r;hCzdCb|Gf^ts&L~8vXK;}Xj#U!H(LzkH#d|= zw@ODFE02yZC-233zKj1D=DdQ8NIOOzK^D>@A``RFRh|a!X z+;$WdrzqB~L=hIOFEP9K1|wNEo6+87LG{^5>)wrz7i1{fJm3@WsLH83<~ZsRqwxxM zDzA420X#9ZEu~K+N_05Le^VqU_v(k;azx}=yItC*w}VgrDu9OFvGZ5UOj}&+J9fCn zzBxpU5Z*Id`6PW_vz7emFrSj)Dfyh6k(KkGu$^xPEq@cKWB;MIlN7mgDHfkL+>WC2 z`PD}iw5}^CMxZJ~ArrJTcKWap!o;fAnlrnL>oE_le;1jU)RzC=@TjFUs={RGJ6r^r z#~z7wcC?K=A%mWGu-*_|I2W{eZ(Dgb9|vH%B4v zWpZ~H3QFlp&jDF3B{XbEW{%Atk_zJ7?!WWT_KDal$3x~F1!yJ^Fx@LL{z=wNA{Kfu zbxBYd-xeilTeSDs%}u2m%EX`Eel~VTM;Sb}(;2MG5sctaDGR_pdxOztj_Q_98vYLq zT`77o0~{Mro_A|?p}`j&5`h>K(1U%h!6>ItvbnU+=0*`u`3U=80Ybxg@h8|qNK3By z2{)xq$ZLJmR@rlDHfQ@2tdrt;`Ovv6+7}dP=U*hjg3K-6ur3$eFx~i@OdIcRhSp(; zpc(#uEkKDs!m$eyX9TRdi_B)wSL zKy&U=H236zfPcAj(&-3`)6!^WGRntVUeJRGqR$B$$^g+Y5tMT>d#JJxb6wcja7FW^ zV8}ql{j*xSa6;hvM8ZuVhCWF%PGhi``_sjjVaoc%Kl0#(>D?IMpd=bR z8F5T9jskB0DIYZ;n-E{a~4)C+F`??wqKN5PD%CwkXFQ+`#yD0t@Cyk6QLq)|z zVv?`iTZ?}eZ;N5z7hOn@j@kD~4Su_tY(_R?hqmy?iJRfG^UYb!E8R$*X zol!W7U(15I=4BegPgu{gez#$q#G>bl=R(EQmQbz+*b^JL`T(;~P-7Jz8QC87ch+l6 zELTrmVR7o)NLPs&Ib3AW#sRGX(1Jp~wHG95o#;dK=gb3Q;?Qf~*nkha99~Iz#Exl* z_>SC4T@J`WGrH4z)_prx72s(Lx7|rk)Ey_VMUFmo=4TqY5OlRGPE)C&f>Rn=m$0X# zKXK^kI&kYw*4l(dvBQNF3j>8PpG;0H)YbwmFXP$u7ypl@^YEwo@xS=pu6^yzHM94g z*WP<%XJ-}}+3t0XYYUYTE;7nULJ_i8$yNA}Naj^$AzA(I zQEQ1qw3!T;i87oJY*njpyb+bKy+aI2GcW?IY|h1+3&`&QkVTgeQd#8i5LvwPN?s$d zR)XK^KX!sK8({}6)T0X?Ecc+T<1akvCiSWHKOMxY+0&(Fzblm)J*K34C&?PY^tRl< z9CI*6hQ_OHd7)Z*+0t27!cV_(A@qjp{cMrF98C<=rR55HxWvobXc2@Ctp}|%auBb- zg(?71PeAmNsD(YHkyLs;5&PS>j#m%>`K0|{V$;yqtI)0ZXg0$w6&C-{Xn%=ABy0qM z-S8T;eovP0WZ9!9*HUZ-6M$lmGVlQzKBghM7W^73Kx;_^Vu0YuNK16)*s2yO3mCw| znLMpGNB>fW9EHl^gCZY6w}XkSR1J45vCtrt zRAmv6%aYWR(J?t}25?0Zzd39O8)#b$@slU>wnp$tv05#@h6KrXQ*Q_Z#7=y}eibN2jozFZuII0vkSJ*)O~Qz?j8!eNts2T?q6fGYdo=dCMTf z8O0aKo7o8OE2F$fRFGk5(#gm7L=c~*fIRvpUowZVTjh4_v>MY&kJbC=`KFv;S`Ev( znfu^+y%~72`F<_kU}OaS#D4KpD!UJOBAUo9D6rr4TO~G7f&a!#t03$U8G!TS-jD(; z3c#xxjA=cn3gA9O0u2*UC5hVK(=#T9EgSa~SRS*f@+0|g5CO|`$9?`i3Hk29|3MQg z$qae(%FpvdL#nRZ+BD-U{4?o;8&upzTr!=W5wC!AddP`L>3=s$f+9JwN;{T6SNqj~ zMmp0N?7v;Z92x1#8s;~*LlsE_v+P|ry@6Lv>Nut&tBLKO$5v$g5qy|+R!|~4DnYt^ zj1dz|p;sO8r6+d;{ewnC*byAN_m_rh{8q{q{fEyP#e#6zRm1)%0f1Gk+oh6uS{7-V^VusXkf&yN2|Kvz`ppzrl{@H=dg7lY5;H$}N5AlpYpPq)v ze&8g)Kc?*qYnwuJfVhn5en@~eC{2hHu@NEgg+#^Z{C-zlYWm;h*IyxCsK?W;4ot;T zWapv3pG=^?GWsK0v{@+VsN3{-KGV+bbq-1og$BUVFDyRJEEx@xf%qoI^3?d*7{;J@kg9V-ut&}WBK^%ZX`nvq zS@j6*-8baL0psWI^)YYwA6c+MgjW>6_bihm{ZP|dl;B@OmG;{LFdc$wAc`K%X8<&? zcXYq(YupK_A>Zm^Q*hTL2g?G5X;p0&N60e6`I#%W- zwL$cWfqk9$PuWk*_Rw13%zx5g`ujjFL30co4Qm!`0BYiEZF`ksAHQ?&i=dHpf&$#S zn;hi2x@<|3D2PptnNTOQ2s;2B~`Af&=YkCzE< zr8rBWzcMU%fS~W^az%K$XpL{A363P0t*J>PNqzFkJ zhjB$U?`4=zFdf+@GO-R2#*Kcpbn=}0qi8Ozsc_%NcrZ^6`6W=Q@N-lPxBQ^eE*puA z2O{P*b>YbL$2PV*SA-GJK>S4d3Lhwvh8*);nRc3%8EisA6Zjie>VfZ_4s{cgW9B?a zk)fK9aa-_YGAIRNba`LD&48WkZPm|=XfA_6zRl!3I5jabS{BwGVuCVq(J+zz?|EzA zt?Atdr&yQuk(dC>J9qaNZ7ya|kSyr`-| zE=68;VaNrA_Xg!)FwwEzVZm(~%CSR*N`n*yMV2N@sd}N!XbIZyQ+SlF{m(FCfOEMz zfH3>RM7+$|#)6C3J0q@#w$F4;RuFJI=x)Z%0CrMU#oo6CQ~06CcZVyDz|Yk#4!IQY zk1Lb>U>h%hB~(Oh$Ql}fUVYc>aq|5EaE>8^pTZ!UF@EVVXXv&cDy;O|??Yh8x74eb zqp3;Fp0ZXUmV5{vavg;=oxmIemK|-m3Z#$HkouYBvkfnl71o?em~DIwrOSPF=9UHY zMD_{~#0Dr`Zk5R0-q-r?8TG$W7Oe|HSMBYoHB_$d$O0oTAwx#kfczxNVXY{_&_#QO z+eSVYnn(&Ea3g8#$^mB%uutm>+yh0OgpGIRA7bQ zF!f$7@AkK&km^8bAI*%jFgC)3Jo2V^kRkPWBlT&54F25KALB{gDcLCfkSxU-7s;+W zb^iMMh{RD7JAw}RnARx1b9bdR;`_fX(1$RhoWexj>1mN@Nc;W?vQb9%Ac|b%Qp8wj zqaUfCWHOt3H&DjEn)J5{9;FRD4ik!Cr6Qj0#aPFa!&0uI?USu}R$jy7-n1Te_aede zcfF!%l)?xtL9M;6%vLK6C z8m#nhX8=547I6PC^Pa`R*E7!jIUp45C5O)y?l*$#9F?3+C#Avc{uuf0;eoxUUv>_( z!F)XVBD&$iY*F98S6rtG>fY`;sqj5tA3_5bIF{w`f>MCY`i=G;2DFWZRq}&b%BFv3 z+#q3xv?rU6Q(yQkd8WoYG?@VbGKvS-K#bykFDpUq z_1&R6TfRUPrIMZk%&qmNYe*a|to^Xc+i;p)H-9%NhD%R48QE@@U=?piZQxquhtA8MgNK7vo&EQRdE9cpgDoa+uSBEV z))?nqTC*tg$vQXe7#heu!Px-e+|TvYJD^OLo6h$Kdf-+p89t{-)_1d1Ml;BAobbn_ zp3BQWgXmpNRu95?jd5V|0~)(|)0kNYs+A8U66UOOyKZ8#+)l3oQUE0)MJ*g@7dAC3 z|7hjH8gY5}Y@*bxtS&BI$Z4Jh+iWE7IcWJU<+wzr}f;$B~Rc!?70bxDq6U6IW5^ zffC_yAzA0SE(D;u7I^1f>>2ap(f0I|;E`Ytqs z^5^}5Rr-9!d0!UEu5V9=BOfeJxv>_ZMqdZSA&3_qC~m|sNduz@nycq6(KNSrWJee^ z3q3U>HqC*43lDVrp+rIzq*P3#^CQpKHtpEPa~aUmeB%%3X8V2GzPPi%hZWfVjGp>n zoBW0su~8dj>mTw9h&EMnm$8wHN|hMR%kJS+vJhS_??}d`e8J&D94kes7u8`QQTAwGlJkj zE_G9Gb}RK;79lsKWx^(`le;bs!=m4ge!IATW9ev=XHjh3BB9x#FvD-liyDmm3O;@% z7*8O|c~I9*KBE#HHu*}oMx zeJxi<$Id^)K@=OPN>3JuIrR_G-IUuVI*6s}p|65N1b>F)L3iqxQkxOQQWTz48uWO9 zMZ_Fy&%Y`XVjTDdqeYLQ`En6*mt2@Nar7$*Tc~w~1`-e9d?BKLO}Gw18=HojX=s05 z0$mG#mDZ8eiB5?&6m2dZnygGkIcw63*0{q+fuhL1g1Q<>8Zs#Q(5sTKzE=HK> z94-vWcF?rHaC)G#QD*SFx075L$k3z zG$1Eu0` zyf9+=(MY%eAIHR-CAk8H7cC#b+kz|aX}R;825B|N-WOc1T27#Ysg3MhKi9zpGKZVG zI5YkMRi0;3-dNBAon^d6lBfs~2SvsSp zf9kf`vctbMe7{qK42t8eH~0zt<#{*U zszCS0GYKKxAK~-PRDIeCB(Lh>(VC{>b$c^g>lL;Eh;rFmxA$nfN@au#+5X#Nu&EM@ zIdaEPqU*))MAOmeM{jdaa}q2sj1-rcB-!qIedt7It!xOqZh}>6F;J6g#G2~cDyJIJ zAf^UW>IOBKz>UJip+((an}cJYA;lJ&bQ-exr(yH-oL%<i_;r+y1k$!lm~5@b|3r4nXR^vvHVn0E5O`PP9cur5Z9uge|s z_*7q@(C=Ppicl|QD*!pw0bfU8-*k4eVE4y1)Lp|E*pUgFpatI53ni6oX=vF%QVb+f>&MK)wA6U$>4&}3Q^eadeTqKvfj&NjtWG7Zu zE2**eirbrW$-^l5p31Fr@YnihiRzqODq!P9e&8GM(fLk~Eb?GBqyliejy9pRZ4$&2Ak3`2oHsgWvUWmcvJ!zs@+O zOTDM8fQ%XDAzIh+Ia+nabHW7T+$oYKEtc}|s3pl85uzO-f|JGo=X2_h9tN_zI9J;4*}di=2@7HrwkX=!hy_t zRIW7*MEy}b^<3d&fc%@cQM@7kDCJa9fPW&l9`PLvwxNrG&F$qtJy6(36nm0`X>8GH z%Tuk-M2_{x>ZlNWIsz9?hsyez+xbq#sZ%x*KFlGqRUhu;7?-9DPCph#m3ey^n5^N_ z1%_pO3>X{Vor|w-y#?Qb+ymvSU}ieVz5q47pOeD`h}_)PSr6Zz_YU2C+7yo)-;*0o zB)v_AV9kC!1Q!<&!I%}H&c?KmR0m68I0_I1VkSJkxPU*M*$PtvL~S_@|6{k>BseA4 zK2dPwf45hfX2}(DgGPfDvGMu-4DLpjC+&YO3W7%OQk1x#-hN9kjq6!&O}jKiT2TWV zQq&tpo1>qZ@=KK>P8QHXdPA42H(A%}sJyg;0wuBMUf3Y1J`&#T1uvB|fDk!=W`=;z zLs?1>Gyi>6O1EH3!c%`!Q{GL(E0BTN=cP&AIo38J7(rn^6V2k6YpyL~(B*AgG&E_G z#}MgSDxaJ7j4O>s5hA_O)wS42WtzLRWW}}0pWAym`{MeSFY3YooY?qQ$WaKpIuvpi z=gsC=HW`)?epjQPXA{bhObpSNVvY8p`Zd9d5J4TElG?~c(c_>bc4}d@94sq+()>U! zk$|S4qeSbGJ3M=8F^GNwX!psB;TqlZHDQ|Ty)TC!`a?2n^x}5!w*-t;Mcn9Xe|>w8 z$@{Z>d>r*^+K(5X#4~4J9hZC&|Dki(@rCNK9|HqJ?J8J}YV(($KBA4 zVq+z!%i>pFkQ}D(s%1ay$IW?!Ug^mp-HLfvmFbLh^0T1k)HZtQ8K_Xo@GLIA%6b7V zFZUYO2Su5TB%-|K!a8;hH5KWw)D@$c^? zeKGqiZ+&wYVrJ;imn=(%JtMBfK)t<#EhcgwTOe|ot+St0_!UXxYaXtvwDqGFIaVSb z2ib3K+8Hvbo8SN|G-8E?JxX+R-%I(G|1E(9Xn zC95ZsbjiShy5M^tLRZlH!B$JI(nk+_N6~NiE&zJSRQZ3#`*oV(a!BcaFC)9Ig_{{G z7YB@I-L2w1X{kn&>goXZ5SWSwGwrTFSGn0{eL8s4Ez^f4b~Q{wN8ga*9XC*JWoJZ# z?}7iFrkzyY2e1=Z!W)1O@sv^9uMgyHDw!a>;2-y7@f?9C%PP6Eh6L z-TI2ozXnHHL;X>`hDEI5BYm)HQ(f`&1J?%WaZPTn`8L~-omBdmJI;KB9eRm66G)(P z(!vu!!lnR<`MO<)w6?jvfQ0cBB@O?L2u-FnqGp)B{B3#tcYhh@2DSmocMiytZ7{PE zD$0NvuOoj&uPcAt7Ju@ixTJ)sem&G5C540ao+*7o+dQY_F%$aEBft~!0T^Z^M~6gI z@jrY`B9U+aFwk}vNSh^BH7vqCLXH$=e6?Jw<@`L?Q0bc98o4DU{F9JR`&W39Lk045 z;nUM6V9?jnLE4!3qrBL%Yc}hei4$wC=!i>CHQsFLB2Hppi0zywsV4I00Ow41T%SRx zh+~ycO>f2PIHcd9ZZNGuDdh@)ZKjF(kHRU=)5u`HZ{Rgm{svr7t@tb&4zv_k3NP#E zI{4n~%z!K%&|+|`>L_aUW$V}tLx!>~T*B_1j2ZVIpXgJQQ!PVUa3+bJqOGHlaTvsGFq*1m`4x)HdN*HD%nr+RL#SWe7oddCR-KR2w#HZqy9O5?N?D_ zs4OW@4JxP_1EMC_Sipm1T9-;B2g7$Q-&=f$)Z_=C<^Ys-FC|Q)HD1PL;$1DwXCX=s zWDYcvMZS=9yrP|M&C&N|U2$S6`DG$-jy2n2v7J^Hn`3San-J1q_(%7G>=AaytMGBf zjs;KBtdi2|CR`?p@Z8UJTqEy?a@`$NwU*wul<3q^p*<9lxd2xt!);ylCS z^BQYT82cx*z?pyLZ{<7DwEFAPR>_Uh7X$tR4^l67AqHH(WHiWW)l?(S9<;rx)w&-Y z;&&FzDV#l-|HQUuhdrmxc{gIBlc7@}K^dOpz8+wRe4^KQ!^_P$`{b}QQv09Jc`;QlZrC5iW)&zAlTE-XWnKVaQ|+T@Bt=Ju089Tuu+;N0zls+QcGphpuQ}_?Qab{}HU|iwDZ}uJ0?44+(>OR-Mnc z;s~0OYhEY|7k?-UlSJ!>JC9QP@|oe>Bae%h+zNWUe!I}jiIB%s%WYpY!AO1N6qsmk zVd9YTZM^hGwI|=T$?<)tAY4jaGUr_0K%+1>C+F3l6_+H-x)Wt-VxXssHwuG&a!VTj zN&C*n%2E2=w0hq5c|!M5<6rOqx|>}ZKMLRYM6#x85 zzg7aX>$CmK5xS2wWC3wE%rwy1+)kMiG9U>$%H;K=^6o(CM(DRJtkxR&s#YKXPLAjz zyq*W@@;kU=d4^l53KC(PB9h5eY+J_pUyfQIVbbSs*QtJ($K53fPynTvwJbQIKNrBg zhGGHa*8vw{bY*f#W%u}-)Z?Q4!=4WQOlC7$Bj~T}@&PCVXdT@WDXI`y0!u%1WcDpG zE!Iz5A3*Oa6hl!%{|4@z0S}8oYkY6rO?H8};!7wB*wMK_Q|iOn5i#IEdPmz%9~Qdj z>Qd=HcGRqv8Z_pm_~dcpKVt)#k7}3xSNuQ}f%@XXJWZk7-@(@07qvX~EYP#FDjr%Y z;>Wwop!Siw6bNWuA;C=*piqO#IZBW7Tqv4m+@&&-8f@yIh}@1IWbi&e?i$YRVj_- z)EtOXrkon}HkfT^L{^~eY8`(ok|L~YPfwFyk>ogn03cauB#XxiRYQjgQUuWZCMxOg zbtwaS{>vwH1cbsMj9I3X6owMWp?OdNPG+Y95cgQE=9`>hC}sdu$M4bE12RC^U;zaA zH<63^jSfX#pb>R5ZH@(LH_YUQ>z5Uj*xr1Uno4J9YA#}XF7o_ylM~;6nduIhGR@Tq zF~6jAmD{46v`U{`lF&>RXgtr6UOr6c=D(~KAQY8yI=y+hLk}iJC#dlx5?}5{K19G+ zt(?tOmZlxptUwR(kWa{Aycus{s29Rn*7e#mzsBwrPy);LcN0H5@oyCiY zNTFmmP3mYL=Jrj70znz{!2xqYEEQ$9TyX&*(h~5dkV{^kSP>n59=^YZUbNMO`NZo> z&a8Bgl#tQtDy!Oi7UD*I>pqO;nsX6sLlzh-kh8l3Ko0`{`6A0yS`8c+K+oPV{rdf% zzXY2Sdm)1$_WT@RZM7aIS+rC|__6J=Al37Me4u{7L~RIlL!e*CLbda5T1o1@!|Wjh zIn+g&#%C4c5#b+Ur#R?&;n|=lFP~|P!NI5Dp^zzHoi05sc64_3X&U{#1Fn>9gh!^s z|Fi(6Kl`&KHQpYNjb8XRBx!vH;+C;>b|zme<3DAfx-uxP}QK!hprGd;ta7{E%XY5*aF{8e`F>Ue#g@;S{n=q>s? z+;uXz)L?o@dIP>oTSGq3yGC9+S0$Aw}QIC578>H(Sz#YHoX)_4iI z%BIzWeGi#owp+#HR3+Qbp|o{1B3(3(0x6b)o`j}$ilmIZz*#p&+b)JkQF4eK; zf5QI<$Bd4!UCz5<-IU4NgLRSIy7E~+c(5-^?2u!e2pnOCR6RRppmJuqrUL{M>4M7l zX^&w~$%fy%NyCko`^>yUTOTSs9SuucW!1N%FNRnhW*K*Fw^R=xN>~-@irle2MEc{e zF_Pm6mvLR|M`O3Una%Zr%fmt@%m46aN(YWpLJE*6A%DNv*8<5QeKz!fq6!9iqggMH zu_NI>zWe1I2Zs(l;oscy@j5p>ucJg>8^@2QYM;(*3*n3C>SM)~NjxU`C&e#$^SSTO z%<%qvo}1?QdA}-8Fs)f4r*%49*KCcpxM&By0YJhHp<+b)RqYm6J2A?phZ1MnF2GTK z97DmS8Q}VBsv0#076%2CXq!bL0c$Vt9RJ{)LRzU%Lew z53M>0FYlH5AWBQ)J1xwkC6})ktf18&-#K&GzWildNPT#_y!$8_)XZ@0di5ZsvJpHK zOAbqj_8-z!H(&?)&uAsBe~e`6Gut^RPK@oaLciUUnxT7XO}?cNy^zi2yOI1{8A|U< z!4CP`z~=Wj>Uu7(wO!)3g0zG;b4rLzg1V8^$VWi3LwQ$&B4lu0O|YtOzxNG!njniV z!j~Qd2GRQ{d_TI=s^pR_@G=_C+{hXVlqDQsK)^F2@7qHQw9HsWv(Ktvld74I_r4mC z%Ky~I&JXB(&{eBGHICxt1(g;_bKTORMD~=GAj@m@yCE zqCp}ERTpquDQ4$&pjF5gIZEHWR>B2fM-%){?Ms3kFc$1s6q)H9+@7XJUxS}e_fA-p zWseg|trU62Tj+X8X_L1g&Tg3WRqV7)MTjdkg7UvK2>i>@!9btr{UKs<>cS~g$c;Z} zc|5)1+CaYe77HN4jZ+m0>JGQ}lYU1j`Kin?ugkh2>vV0WrT00NJnt5X|6vHxF`+pB zFS%^!koO=XwV7+K)vV~W z>b_`y97j^UP^+@$V_u2HOrWbbPN|>(QG2_7mND7BYtxVJ<7bJy3EXa(JFj(wj9? zx*z$b#aPh4IY#z*Jq*%`+GP_{h}ln`LFCV;)+ddbXvEUIB7{T?aPrAvvw{Olw*4A- z0Xu{Fl4R7M7bN%zzC8t&FxPV!3Yk2C8iZN;c<|{3G}ty-zyH{i&~(0-bY8>RIcoXb zqBu>)|Is3!!ML+mVz zT;{v9XDUb6GBQDAtA?*)9-Z-3|;1SH?n(D{cPDDTgro%fSPV8>TH z?#g5l=4B~~0}z}e;X{JsITFx4-vUe7CqPi23Lb8uBeY`mF?dL0`UfwULc#;Uakm|V z+Yhw|@l4_5zqiluKb`@108d|51$w-~7GTxlPZx^c%UVUFH;|gDBhahCI@g#F^W|T^ z;xYOvpZ%#_C>`Wu0!(uBwQSGiCeGwGq1v|U49kC4R9}pR8#bNpJiZB9>!F7u0JXGu zh-rNiCs-}l6^dQ*qKLf{(c4Tvby%pa0N-YO z>zJ?EHjJzn*l1@B!YO!mQQdWU8~Q`@l0EkDW$ez_zR9k4DyrUD#Q<@96QZY>?(lrv zp#;*ks}egsoT2d&_8~oCEdN?qYM6W?i8W@Q;;Xi?^Am60_|N@s8^pc)klSJcU`fu= zqe;pykbidixYI`xkWYe0Yit)={%-P=A`s8=?e1fs2-7(<3~9h)ot*JD?5O-eX)5hj z&7&~op#h>keZYR6&?n5EOA9Z2pBz3KLj9Mi`Y0l(*xdh~vB6;4NhhWXRwA@V!J zN`d(k%d>x4sTz$7bMMo(6oD{e*ZrUzoyR6SZdTQwuRKh?C57hiC$a#IHvLgo`j=$6 zd;8!dc2+CkLtaYk8_?41`_|XN*}hNiwFCGl(E=RzTKOm)1Zq{eeH{KO%~xT zjr32cypTg-{aR$Mx}uuRVMQi`NgZrdbxi?8d_~6dPA33bbS}RtYQR}+fE|D!R|lYu z@w>dFOjqjM{zKuu7l!Eu=?%a5o{AvZ-Gt!h54&ePGP?cdcc*6!pNxIDhXB2=HFk-e z=J_Xl;Xd8}Xy^yVy0|A(CZhAZ!r8!T#h?D3is<})yyrjy2vhK_QkO1PhMKQEX{NHQ zi~%4Z+8VLXRStB6(w(OX_Yp6pmhxBSUT3hW2gl!?a~#fSPNw2g7tLcJ3nw z#eVXP_96%7)n+or($9Kb9{+j5C$D4Gs?8$4s0xmqfq~l)@JuO;&U&;G_@N`1Hh+sf zA5gCBE#U%z#84{;n$yiGvdZGy9$dbX#v3_-@&}k47RgaDWMI*s@Z)UGxN(e=D}>%@ z8-2Uw2Ke(Pu*3^^>Um(UUB}XSFyNJ)C8{E+A;O{=>P>Z6AI|01B5|%;RxeFHTsWhC zF&?Jr{1oOv$ny!D&T|j>#tgUXzBi)9(l5z6?1kdc+{)txiyFh8vUreOw!nmv)B5{w zDQ@c93!(f9Tm4@B3}pE^%YNo+uks8UWZOsJqcOgmhz<@!fClI+03YGPlkh{}rAomM znfU%Zwiw1ua??eXUA!{D>{uss>yYl+<9Ym$uJNZga?=2TR{wyxrSA1$dwXwY@&dP* z1>CoLhG-x(R(0U&#oKoDQG`wgib0s+0e$=Ol`o!CHVlJ8({%J#&m_n_HAa0jdy%PA z>CebjxPG*Lg$$UE186H!`%~-TeWhUXrqG4pAa=r^Tdr?OX7Q<))bA8?iMogsd4E5@ zlJ}$)1)>2pfoIo&f6B~Mpa}Vl{?JAz`#VGqX|ALBGDcsFbU*)uZp&e{>T_5#?Wy+-o#e%QWnFSy#4KZwq)mms||i`G}}0?qsyZ!UL+d)u|+$Sx2l|G zXB2X?8JG~B%F7jYJr8|m-S7(4$AhsiLG?_1U#bQ$d>DIoF>(Pyn~al`77*}{1C|r} z^JU4o^nVf=1e}IKSeNqxWAH@fl8=5jB|n1l^tb4O?k#(nXQ}2A(j6XZWjQwnscFf4 z#hHiC3K0v~|IC#6TMbb;Qea|Dxo3|_^pVqQO;yf`(MwJ}?o^HMt*>vl-z;UlKY}Ko z@qAo=^XBqC7e&gfE8&r{1iO4g8S1@|`qRNzAP7QlQf~g%{nuMRLH>GO9zr8;Q`HWo zA&g2YAq4+?u5p@)ezfpuW7|vZAJc6?Y}^+f7o_s>D#uis1>7AIvPjPI)9jkz8Y1lj*ZXTL`uM>h?qYMD!c01|aq;V(&n?jSRhu424)txD2)Vb^t{ zk!bw=iw97Yf1NO#raw=atW(A`+eEgTF1Uem@8Ip3IAe6Ek%uMb`|ZyZ8=ygsQ7qw)K>~ak>48h+=|fY|*%x@xJ@3EvN>U%g>qd*;qyl-3)7UM| zDhI}oOSrIhB!U#o{E(AG$IQ8shL}^`2?=@J=h`o>!(YU77cb6$4D-I@!Ld>XwEsYz zMbLK4R;KcT2>#vSho#s=r3?Dp;${_0x0hXTtSq=Uqbgk$i6bj( zyMAgxW4!4>#pHpr%$c06_#%8eZO-6GPK$lHkBj7*lgM3I1Nm#WQXl-O_f}a*%lpeK z&~Y(yLYvh1>&d|A?hku34@RrQ+&cO1=e3%tL3?r?H~DH@Q@WNU{!WfI8|Pw=6aFjJ z*a)aPc^l`Y-8d>v1Id%6NRy4Ahos7V=Q=`AN*mz0bh3t+L&-2OB4Nzt7w^h!J|yRj zr@t{wO=@vZtyOXzR#Iyk^l)K*F$k)yNLA1)t&)bjV6mi&&A&9Gx{e6G_>J=5wQFVv zXj3vBnX0q%UGoP@0c8xpFv#zIV_Dc~L_f8NSw4l1R)`KDYYmkb-X=Z{*QVyATmMPNgs*`GZ}7w4huBq%A4nW-AwWpbJ_ zG+qSu!H?AT-5+;QGFxdxuRqRZ(f{@C5;(<9zh^B{htosh>KH9%ecYk^5E(krY_u>n z!kGP`{Spx|ob8Ng&46(czX1f2Z2Fuk@Bx&QN=A=~;&f}@KWkpyd@KrHWSB3A9i z2*%wAZL0k8#xtTQvp@7=VDX3%@4PA=^Y@wLd}gWm$0dOP|4;nH)m}6n;)%czXxyI( zEs^u=h02VMS=d6HK?IeajQsVtIHfAXbh(=q8m@*0yM8U+rg}N67J?HmoKsn84Da@8 z>hcmJYwV@>_M%4_Fa<)uk6jXSopJ4Ls`M>I(@b zb~pmAjn)jkfPF;j658xjYuCnFjQ#N__k`#JQbK7^73J1FJw{G{&JH45H|Y93Z~*f3zjjy&&~fCwAs!bSe&Jmz#FRZK4}O7OP)(t~p{k-&a{erY-mA6i;) zPgd84qCEAlaak|$-fRvH{a6fPXV&0yqI;QfXdcr=mjGxngrdw6s+YpbgNK zj^aD?4w?x#l`N=mv>ezj;xeQ~&sgQW-T2Sh82}S7GTU+Ay`qm8_@tsW?=g;sTus!H zghI+g9D3-M{}1MkxloLkS);Y8*6~D#8FH0Dp_(_@?hzl!l_+o*0_|S%x>PLnkFGlcM)&b!XD#rOBd|A#d98b36ezV7-XT1(u#j}^wrERbhj~yr-H?D!x}LBc-n-3t3C3EWawg1l>b2L;QT0Z}#Fsaj|DN30 z2G8URqjZeWtst@6-~WqZ6l*mRG}%o*{jMZBlb;2=a*i5kz1s9aaoion9_8eetWxc^ zm<0I7fPHVru{4>J#{bt|DCr2{2FnM-Jk)4BD&vV^a-2jUYDT$xt_>s+67*YpNmdkK z1rehANqle3WcFKvWN$$~w7M{x9J(O}ab^qiQoM1B= z6QJJk`80a`-lK!|-SU9$(98sy+MlAJam1gq3&~e^sMGc|1NZXQtTu#O67d`0A98S$ zel+Y*XRqsKK>q9eGaUVH(j!2O2cyx~;eJ|w8leA80D=-F49qai$$PiZ*DEai8Ng2f z3{bDkTmh1;%*#{E5xbeLJXa2RPRf$jqm9&pC(D2o$xQlqY4_}##1nK*9sKx9If>6SO2ZR> zeKC3P?UGw^M(G{PAwQl>lGh6bip<h49LT!h#1J7%65z;qH+wKR+kiI!r?8c>J`a*ZF^lu-+)pXn!xgNL){q zzh#&nwBd}V4t>h5oHmMUz(%Z5i=00vdgJv>A(VNqjZp^5Z2u+&8Mh*g#KMeV%WgQ!!}37Cnu7 zC1uHo%an%kCa&WCyo`w^CdjyQTue$Be_M9PIeb?NV~cG+Y;aBeoKK3$i32wPQ(5Ei z#~@$>{R?G%{I{}aMQnmh4Qmr5;8Nkym9pN^E)UC`FyW|a(^#uU)pJi8&my%_00aW8 zY0Xybb?ybSDrwrX1fd4-Y$GQwJ5YgeYugwXY1S?ZpKmW5`1@0_z@S4^L~WSPk*zCOfLtgTeCs+ z69HBa=al((<8i-laz#@4@v4UsFr&CyG8d4!EVgww=>ElQj=zFe*m2Z%! zqnvfT=m6wf##r7niZbhGtP=al9rMtjr$8Xtd6a7)stEd&evJRYWlV*lL8&ZWAS78N zF1P>_%x-06P_y-F;bM|yLR^=$j&PxBpa9sBQU$)_TMYmZ1f$ACnmT#@!!8O=V%)w0 zDU(?KeRM~={(W23<$&M#a|)=RO-!1=SHiEw7epfBrqRs<{9zxBmni^HtEwE<4|4qS z&N2B8t73;g?|R|2Wj~uRSJ}^Z*TnKhC8OlNnaGFptI$iF39U}dNF?ZB2M2hnM9$!f)rp?_W79ueY0 zh~sP!k_%(@TY%ho?n{NCe2)U0n#obLVGG?9sSB$BCk86}J7NQnjFF*Gb2qvS z$SHtLl^&Inf$z&rG5N3ChSqi9Xy_{jsg2Pez?vkw!cE8Sy}Z8Wc}%EQh`O@A`8Yy% zSmbt58PImiTDC1sH0X_4+l0>z;6tV@F|dLO^7~FAlU06DQzE^qg=vbK1hk*TAxTTctjL>**Nd4O5J2U&f!YTLQ{x#y=NC^|UXvDGDd#S&E3pWxm?jmIU8BC!Y z6puU_bnCB@{{R33DOMs;KWCx_Ox6d$6H}XCC`{%z6hR9%>r6^PPs?28=!EMZ1muoY!zS6_goH_P6+gL4=vYHvSuY2h2 zjgki2DGrN7TYk#s1Cayh@B0au@)8O6n;I}s6prQ-tHff+K^2!mO9 zA9X&n9jnJ%fv38p2?Yt=;n#$tR z`z>qp9^2^y1eR3FNk7(jv}jdDTXC_etm#Q`mcgNy_PyLP=A=FCUaGeL|f) z)3`-Ko!#qRy6Xtlzqwu-@qj-A zJoeFf9cat)Q}?g+t>hc2{*E{^x@TWS^Dnb)b0W-L-%P0{E&Y2_zwP-4^N-gCA9pp3 ziJGOHYIM!e&E#N#`Ovpq965at`72KO65~uYM4-9;8-7wf_}mRBZfJ z@+vl zEpRsQn+d0d)|USQ{%W}NZd=TPW+pn{*KT&kS_hCE5*^&fKnlhFZdo6G)zxKqB~34( zY$3k&uJ^CHZtz-6+9>qMCAhu>7?7U*91$wVS569F1Z9Am`{Fe#H*;r|@c6M!3V{4` z%QD*(I$my9z2O-@=CWyv^>1%4q9(pch_>!y_s8&1^KV&n0FCa%?U?yY zNNO}yAa(#|P+Q;&0MT_9C}IAjWc#!YHhQG_qKm&R-7Lg$lfZ^knV?|Zek%%%s{j1f zj#j_iQ@?&Og=P;#nPKK5m`YQL&_)_c@+YoA!{|ge85MegX?@m@Gk@|ZCHcE_ri<3+*uZR+#xEh;1D!6gww5f{3SogOKocz-@RvdMsd_RYGc z$xn}(R)@^Cy#CUg*=os03!x1T99#v;dZ>sP50B5cScq5vgb}`t7{RKz8c%JWUwl@s zA?9hAeCy*q-2NM`ofLJbks+y0&I7b^Mt|gWh)PH>xm6AQcsLH9=WfKiHnkMkt*OnP z(X-qwxFkjDFfx)&`kZ+_hVX{8bT_iWd^O+g{U1$d8Q0|dw(%8Xz<|+X)F?ruOX<fYzR?(;g% z)jmu6`!s5Jmq#F@T}CwGe4B-R_lyR*p}sX$@uux^24hTHlD8O{@FVGg7qOB6Nf2;M z17nxZeD1vN;h3-drIdt`1_-d|g%8-NXz)JlgRoZo^19u1FZPqjyto_5QuGnj8xw`W z-LP_Wp%Gu}g%5aBUDi5&<0!F<6%=Qya$@NGI4TvD-nq|%?*352q1Tn$A+d`PvXHDi zQS=iSz2GszhuridFObX6YBwTtFf*72X(UB`YWmh*MDWG_W-ZHow0$j&{`e8!>Jth| zY3Jh)pj*Bj*WA2R6|DZ+!N0h&KZ5EfZB40;zD$f@-C7PFS!rHI5+a*VN~>jScP+E) zs3TIl3pg)pG@8I1DXYg&>+af+$DDvHLdn@crt1}7!JiE@L)VgsmQmO_aM=WfBv39Z zu5uaVmYjZe|caGdH*pjpWX5f!u-JFX3Q8nuGq&yUM zDA%d}mwW4P#nM(v)$xhIU>4deRQsu&fB0y+Y2^Ktm`1JSYVp6$h0adqWW73)ovC>0 zhhSPbY|5CD+pUB%gyeo_f--%$%BszMGWAo9VAc)nYvbD>8Zbx~cXy75EB`MG%Xj|w zm3zamdpc!VE~`hg7k>6c{=%n^Ky9i9Ur*;?3qy?s3XOzxPP0Fm{8M&?ujBg3-7#)V z9*(wYMO=B~OfR7sqlvUSSKQfmdSJx11m-6RN>t>IKqIx*_TI<&HvXgJNp$N+9~g0= z5-~U9x#5k>Qq@+2^zvyldH{zx;t!Kgicrcl)Yt9N_YjIP&>3Rqf&qlB2a7ICDvN4A zbcCIYAtE%04Q;W;Uum0Oq;;8)3y6lLe6=Ii|wj2MS>-{ zfN=#sjXl}|UM~eJzDvtDaYua}(xMU#&+x&kszXU|N3u%ItT}8o~GORrfG5_^b7N|cGMM|oTS*Yq|>IV2vDgjVN8Nu^S)hu z=_F&w4e2nyc2B~;q~z6*V@~6h-RU1`ObU>F@LAkgqEqS3Q>a&MmUfmM2yg|Vul$5v7{KDgw;mIh z)k5UhIw4>hw)z$v_Dulo_9a?Y6fFgoe78Azsab<@qbts%AP7Tw{)M_VMe106kZOr7 z@O@GPd|~8i_8Ob>_lH}9knP%FS_@nR3QA18Ho-N(A~ATr(f_>VNi*oWNo5^s7k)Bb zpEL?MBf@baCl)i)B&_|mDj)y5g#xSwjoby@+P~XVuX}PrtJoCKq~>;_zw|vv;Eqmh zYRH+}5JeO@Bl&-VhuSAJka$Ba+6?~9%p8L#s&SBRPne$HxzFdD702BkL&NX;;q(xg z&xY!xF!ypT1{P1VX4v~wZ%wjZY&{26@*YbZm;$^d?%8t++CDr9)9G|*q)ROqYWluzT z$X`#P2o!m+A8k;c2c1dE8)Kdqmd#S?Hq-`!pj?DqGbs%bsvp9Ka{o2~7Fn15D?F)+2k?)d+aE z`?V-=p~1LT?Z&y^v8xZKmJ=%P*rbJE0e!1tF#}3#fm=I zQs*}OhC9*V%z5RC#HeN05MqWDJqqL-&z{yr%Yi`bj%&qp0+bWj_~;`%*ZNhQv~Xl1OHIW~waFu29-y+^bdm$&3!F zhLTKH>1ryo&?EUMoKprQ%Sjan3*-*#h*ICBg5m%jdflqvain=9Ct4re8Si>jv2t5C z>^>;%F34sGJ9WyAjHGVp)G)qSIg^`x+Aa~NSP(d!$WcPZ9ATipAPNnkl88eq+G=m; z3}Ii$1m~pu*OBN!^K_lv=G){q{kCCAKX|E_rsnEG}ihiF`w8SyPVb~QD>$_zVY z-W~3=4sW9I;s56!i25wfPH`1*jA3CJ$7*quLs#V1m9UuVBgj$7ii+>IE4w= zG+;be((YC`aF2pqQc>~Gf+U&@^XwgvhIs8lm0QDiw8X;jATP42SFapRDYZ1{%1RDX z9~Y`}uJ>c>0;aHfN8h-|^+4jg|L*i)JzBIKF%e4|BYVEA!$>3PuouGD2I16kSMn3T zonwe@qcUL-8YNZv-Z?l~;lbDgRNY4ZNLrSt8=hn`4kCj(C>4~AL`U^;GvH7*vAPeQ z|5+u!r}T$W-W~G}2~$pdr`}$Cy)*q+Cgl*iB^1wg^77l4*#a^>6W<;9y@nT38!tw%g7DjYF|8;xGu-6Y>%DJagBsA}40#aYje5a=iB%}D5t zsS9^%B$8g9IbdeJMWAMy(5M(zb7?gvhzhiO5U;^&n^eNcmc;TEMxSxLOOzi)q549e z9av|VbC=is2YuMLLjSDXG0X6V;INp|4tiLDF3siD+x!i3k1z4i?v#^NMG6XU{<)2h zPG(T_1(OTZ>6d=#coIlCz$r4NE*U5TedaNX$*LGqy~=@mmJu zW7nuzJ50EKXK}BZ?LJP4eh`95edpt@k*aK&4ZH%I^BPCV4*QF&qx_pC@oY> zU1irH*RUDwjjL<0rQWsGg6a>WZs z?lU_MJu&nT5$-vj5>s%ezQ1qu6w)aAEjliq$d`1Dk|c{m8VP(_ihx3>PJftK=0($b z_?}(tHQW7wtiAm4%(kTf8in++&9F;xs_TDAWiLhXW`~WxnBbdZ;O1-zL1UQf%-hA*Q~^OLs*gy$62nN?WyUDe`hMEu zTsn>0kU%Gh8cZdm=2Q66d$8E|SR}YqW6F{loUT?1A)n|=bE>~y@LO7l865ncy0O0g z^=KwJUNx;Ks5WR7IBh%n@+6>&$=*`dLM3oDl8$?>gjcvsT@#|Fsp$XKMbn*ud3Q{t zmZu>qoLTp)enWeaL`!>Qy+j8Q)g{5vKcKx-R|d3?j6vCXklSQ}F_@@6GFYx%k6nf9 zFeivcpsa~P<22ioc8;jezs3WED4;wr>dNBYZ}rd<(Cdyx6R^t9FG`C013XD}P&3J$ zelxHV+6kjPm<;B)4@YB+pVJwUBlaSMFidUi42D=}gV8f8O!7Uw$!md11}4xYIrL`$ z@|F1@;V<9kI=YNX3+K!BsmKSagc07P#6wL+JG10TSE}4C>gQ}J6X?U0b`dkITO)f; zdSUU#(`VrwFPEub@@qhDZVL$jA|7^v3&}c7necgJ3TX#7QPiDsKAlMc2WB#nTM zQpJ8TR_L_Z=G~p*5Vn8m2Xl9f)nlWr{C5F+)%^zh*@q)!WWy0M?k*8{e&got_c-wU z=wxjn_D^$B@NvJe@3)!*DWQFi)AK~#o7YLnSMtv^;%KKVj6QIl)G$~&O~eXvHJpg) zClRYsQ?x~HKhAY>{S>Xdjv1X!E782oOzl!U_!Ua8qA9)|(INhD7H4OMC^kL?3Tb87 z1u(#4a_HasmEs30&6Ds@3<@kOeNaB*=;C~zS7IJX(946z-J<#SZ~j}z2N|>jW>8{n z#Hi-6xK^dcvBq-CD-J@_2Vx{d^4@er;JXF z?8L>bB@Wi;^lnQH8RyA2^rc|<0s6F;{$jX9va~AY2^iNX=c;DiWv4K52u(|6znRh& zYFz)R-E7a?l-||OhegUYjO-5W2S}F@98hF}lA8Zw!{4zl14En?LN68f3K5cqXqz`bmeAofJQy7EW@|(fX92Wg3xXN{U>1B2o?{b z<8c)t%3H1gjHfv6fDT|2v?GHCVmcmc@~<3=nc!Yr%d?1zI1%yp+&%T=7_3UndwTRI zN@}>4yqZF}^|K1#8}kE!0sC7abu~uRPEt}VN8h!v6-G>`EYsNc66mzz@|^$p0d-?V z{S*Wjo3gFSo%PrXlGGligwcDKf<_w*Lf>6DHH~fB1I8Oe>PGnkt{CHo$WN+frSn^=wIxXikpu)G!|tDa8m}aYP)Vmd_fX+ zHJC|hxYfCX#K0yU@&MH|+o;?(s$kF%6OxBNP5I{1xt2&$V~J{Zv8lEa<^D=tVx?G; zJ1=Uer@EYSkxq9((>GucwoEPUjGwkR5avcp`bb76SXLffz|#S}$n8#>;ftIq%0x-+V zmdJ&+KPST6lx=Q1Ch*SoQ>OM9LN0~=>oEFlu;gWP)i6@&;>lvxWk4d6+yCd*>_g#CVm!J8))rTK#p6JU#SDG5I zMK`?B=zi?=mJG<~E%N;X7I#b?C9x>W2^#e}E~YjdK<@UdUmgSi!Nrik7leG_f>3GZCs|%o@MZgwpr+N;X&zJ=0%}~6&Us_mpT%VQyyrX*(kZA zJjRMy3Kqn%z{-0|&A^HLCFG~p_suy1UK-RrJ=abklwU_i0-#4Qa~ zTuO^5;@hsL(}PuP34b%xjfKZ6J=dQ@8ubXNSiv{-pHup+WKWy8uYLcXMSd~`*ZTAB zX2t3W212yQRBZvGt}8Wo((evwq{R7B@*^`k?9^|iJhG_?ob0a5KURn1fdH9YyNye; zlP?+mk|Z#Fc?`ZPcj~kJt43!yhC}Z?$ivNTpe>5M}41=IK5R+dVYv^(!{s9?uyl$LZ|H zUEWx}G<|qf9ha`FLM>$1KHU27Mu7zL`LgJ0pfP&x<=7Y^RFXAaqt?l4;kSCMk&d5A znkCokNj@3=DxFwY3~n+ku#L|mFitIwC^Q7xaU#K73JhQEb97uWERQCzDwz%yk11gQ zSL#h_qzb9a**6Jrpt886IPP2PS=Z-$FfBlB2Y<=4dbF$YsSS-ZYRmoE{1BX8PxwXV zl-ty8(jb8*Vw{IbCeY-$LejGur%)V8SIdlMUrnQE#enA5+)sebma2F{JGM-5l~qIy z_mYp&4H$0bbM6tt zh@fro4eg$gs5vD2BBKk}h@ej{h%qjImuAXrSG?F~^qyCGVnG1~h_~`u?pg>sf6H5f z@4y0I9;u6T70S7Z3sLvY`JQ%i47Pr?Q!P~i)BaeAR`vCkcr@9*{A0RWqKEF9&0?qs zIV+fm@n3oTL*QNH5t{3n15%?gqN1Ys)5>EKXGW26>>}Rt;%*uY`X~5#bK~7E1^>H% zPp>I%q2s!Yzj>AbrC6ghRwWF0bCQ9>-N}LNam%a(%Sa+x3L^+45qhA8eXFCDKu8gO z=nG84*o~=3FTJIl!jt*ZT&a!hP<%~(Gi377Wh=EOR+7LE#9soR*=t=D8&zkyU_CUP zKD~4&0eg4*{|zZ%#a_>^7syfLNgJR3$B{xc`Kz^?jSn25Rd_>XW&HpR<8IXok9y86 zxj za`)I}m8({m&q40QqAOz^$i_0@a2m=o6=WKa_o09YGXmbyo-jj#B6vOSqUWby0^HsF zQO61anO?5l%e0pUBm^OF&Y>6q=Cx-_zDyo_p@e>H7E#V);e>6*(|d*Z&Z>e1WY@7K z9%@j(_Z~6_?}6r6;48&H_W@=nayCpcNs_@$+kad}Ewy=?ICLj$vl2UkKO(rb-^Bm@oWJ_w){W z)jC{OFF{GBvp}-!B*QLzf}@#1H`~{7K7^#vW8I&EzoRB~eHNgL_^0jKlU?!cM+;g> zaeV40&_5;R*HbXo_?DO22N&iJV*GyZdD?9xec^so$iwu4!jytSF6EMuHk|37>&#eT zK(59uCsH)*cmKmF0$hnKs3o=0@gR!Bw_?A}zkdsY=kck%FoOVcO705R| z){&qfR?J)HtuSb2hp?>;HR9z@L%isyXn=DFupGn^UbE}b+{s9wsi;BnXc^J$-OB-) zr}v=ga2lvIEbi_t0xo&&pOa1?MHMHc6}TDyy#S8?XkEiJ@Onsr{0DJF1rtIvnLM5` z_cq)q_GpWPy6HFD-DV~)i!(CD7)!qObVwr(+;fgoqxCOM(FmXFIVjHK?aF?R=HE&; z<}dfnt0bPNoK{u=KYn1p`VnXa@+oHx$x_o|w8cbZ{2jfMs{m2JH-`M10vM=GYp@xx zx>4&j^TTNYl14jF4vm>ZH?Bt=z_*I={(Sjw>x*WQX$%!-niB?q*;0uV z&S49^^tkA99Mnva5(o{B;_glX@4{pRT?B(O$PznuU3Z`J1^Z|jMrZdL_;rfwxNJPH zZ=To22DU@v4(>650h{%;Z1R$%b&wUKGMs6VaH~yQKjQqVOm~GeCc}ur)WnV=fFzkv z`nd-OZBP^<)0QQzjC}Br9Lt|ADn)h0S7pUDu1_@X00E!6uvwA5*Y%`^!x0)J58qfm zt)W=A!(#PvfB) z=LtyrbklRCIfAa^)=d7lF&4|fhLgKny>uzl^siDb+sOSV(0hfNnkxb2!Cu;4g@Zu4 zNt1B@n&QbR)#S5FhSnXRtX{%HmpGO--nL~$} ziua-(>dXfIg#vm$`R90E4Be$5?4;o#l@kKvcYiWFo4}r8f2Tvybv*JL2C!`wWLIzr zlXO!okc^B=78O_BWeqtkC!MYii&GFK{kL-V01TBx3xkz7+Jw-g@D1Ae|9JtB2#;L`7s%{p^EQ_Tq+O@cV}OrJ_6U{vP~W zz>+99t+j+0>103MSSQ+ApGJoWw`{r7gkvCehoo^vIYWp2Z00y>iyqbBPTe*a#4;>e3P2grB1jG%B9Bz(-A$S zf9v(uKiOuWaiC5uyOZPNyUh{OT1SML1Db5%WZ|kQE&5G}E;xa}vL>HCs+m;zCYfA* zfKUIPz_J_oZ+Vo`FBoKvKzzh-Ej7<7;5+}|Tg*(qXPQ9h1m_q_zO8YrqL5%C{_FOP(CeropE!R?fL>>BaEY28ppU)1x}hU9(M7 z?;JGkanc-3TsnC?@IUYaKo|ym8DRt~C3}Ay$nl-t-oR_$7%n(aXf4dYxq|ZeOMXIl zaqTHWg2z=yHwLk8U6KCrO1a0!H#Dlkc?+Rc!)X$p(s>9>(xX60N{fr1iSI$t=|x9v z8^r*krnNc<2={?SSY1D4doz^M-pYOQEBhqwY&C!r{ya_}X+EG4v3+kAU5`ZM-aQ-B zDM*U)L>m8?uKm*5`krmxykpsLME|u2jRcos0=B|Vqu!!sOqNO1$*!5LGyqSkk>$kc zpbB~`2&ESvJ4c4@luNfr;rzvf7jus61isiiV%%?QY1(K!yPuhSS=~V_muYde4(9}a zU4Ph%0p!|OHSQKrR*wRIfAXloC3O+aX!B3TjF%(Ah4((C>-l*B@naM%d5>#nxHJh8LsKA|Jg-b}Fy&>zjvT)!(TBp*7=f0ihp<8v{ zETkl3+X1K_<%0$NUmlTTS_%&;VyFsky*^O5k)& zU#Hr82aM0Vo9Wp1bP+3~hKy#cbnpz|Zi7A=bXOPXaCY8>yEZ0kZ{C7$&Lt)i;m)?s zv%N&7ya*8y_%g7h!)PKmCcbs#Z3wp%*u??2Wv%*xJ=dINjkAOXtN zjRy-~LWu;$*1zT~;{|tjiMt#b(ZewK5+lLnJ8#knSBZhPZ!02>u_sJWs$0kV-*PIl z+0Vj7>B9f7&h2TAouZ&Gv#zkYDmll;?-raq_CzwfgEP_qYQ=|dxWC`-(zQTNSV|7&5~s0(zOj;!8XOb z*HN&$FJMb4tW5xvm`?y$0txv{SL#?Pu36e zRWkr)lugLA?zi?<(wtV_l^2aU!AO=Cs`IuO zXaxn9y^ee#5{1yg+#Jrj6p=Y8Lr`FR_#MW_j_rwnmlzwAOmu9yTzQnL(eGrKbCd_n ztsY)XQ#`tYbTD-GfD0e|QL(wFlsr(Q*$05`jhhM1k#BT&Z@#Q4JqvyG=wTB8 z>m(_l&slfdC(|=rWl9+&Dfk#GgV zJ+tk?D|SwoNzJ4PTcWoIT)RX)yhb!Wt)#X`+^$#JCgSZB^F00;ImPdlzKbT9ffLn2 z9M>kV9D$g;0&)IG!Y5KzFl#jU$%wsw{P6mDEWTI#O z)VPp<$an$qU?ibH&M)*2Gj@1(YKGZ?0PCc7n}a#)!rVaNfMA0j5^4w+hLfMr+X=I= z-~UAynA{%}ESMs;|P;0nnFk{~);17mcrrJFpJZ{_#z{cHZgj<=dx$@*FRhhFizS+~}sQRP$lJF&E} zBKnU4r33oC8Ur?+olPnVeYgl83b%q%_u)s^0v3(qxxKPEpDI#Mg5kdtE||J-BBbr~ zs1O{p@74B09w?-c;GMb-q3zlCbmK*4lFolS;RXyV%M6p0iHr8opj%fX zB2O4U0$v-@Yf!?p5q31vJrGE8^pe7%;rTr@tnLj7IDK?PDHz5@INg~(Km(Es3JN$O z$z(Oax8W;p?S&Hltcon9o9$v>mt72LQthn5Jm809&)rD}C5=b58A*PTZ)Hwem7e;u zs-2|ee^zAxhmour+cY7=euxXu;=VHI_01nL0%}2?X^aa|K&fMJ!ZS#10p&#SGwIdu z&r3K@JmkML%9mDD6Ir`UHz_uv`rsEMK%vow9_%j-x55o<3lgzE-|;ONB5#b1Xt0S; z|JfVg_o8Ay`@zu$+FkONG9Reu-oLd--E5?9p+1OK!5tV`IX*O;a_AhA?kiVTHno!Q zY3@Td08@>U(eW1H_0?4{9BdZRH*WC@&DE!Lu?aKQl80Or8*g=W4}@ER zBKETdI&kcH-<_O+82-By5Y)WvJS{rvITvp8WOp}D0`o?qE|TxU_%lq+Ws@l^W>ZRB zjDdE)k!QSg1vni< z#E1PN>8pmBGvz`f13ESO5`h6%qmO^l+;E584r3xBmFxLSrMJWUedDR3*vOQGk-1+H zSovk7Ixl9dzc>DQiEqbmG6dGyZ4z;tXlb2lH8*X``4bghKuvE;Y`R zSkLV52PXn3_XA=xkT%3S_V8#c7`N2@@hO)^|n%Q9B1~Y-+|=xf+&rzXW+dd9U=>t93Q82h+-qz0SEnH{N+P&oRI6ois=}48CUV zUiU5XkXA>N(v7p5YVP)_6hzHIR8eYAXzxMzktw5m4^?9(*)_NyQg@Nz*uK8w+C5pA z-`Z!0W49jLu3>Pew+wc^v>%n1B|1wY8nbB&-@xKc+jS01+tFUJpAUB*Shadkg+WIN ze_9V$?)K$$tINl8fM0^RqL)rtn&O^)>8b9Oed_eftYGsSBl~}Wav$__Gf!>(C*2$& z72{;i#V>_e7ZZWSyv#O6sa5yv@o%6FUM=6g-zh-Qa40D*G9kLlDkVC8{}Rk{%z{QW zI!TnE+@paZH*;1#9a9bF@C~#ihH&BavkVw81XN#>BrE)U)px8HZt`EthO~U00a9}m zRM^muHIN5xMzyRDSK#C|Cfkd^L4y>?SJQ^!?-_sfF#WT?@Z$(R?09QK9=NW?vCuFX z$sjfUp*%wc!aEad`r4D)8q9gQGb;9$8YH$1G_%izK&ZFx!J_^s%lK>G?ALf3Jhi(9 zY()9`6|qV;s`+4yib8I8m1ljEOwCV%>ck%!M>N|!zx=_&MTh26I(DLT<-0mY|2yQw zjOe8HMD```vIl~c1>Hu2;X?gYOaCR!?PocI->PG~8DHRpfcHS*g=bV}261#L(;(Gu z%J$JW-DsfU^I}JY@p_(EiHgtJ>fSI!LR3}*y;q|c_28Cn-_PN~IuBt;IPhybxIVf93}w4~*z81X-#c_9>(S}}Bu z(D|Jb$BiR$9$_A=)d=|cJn#ELr_K!3 zVyQjX;^jKizdNjJ0o#_^cCtkL2b$x6LULd2XrttjX;S1Le-)XPYP(+W#VX|dNwCB8 zGy?h#x942!nFLEfL;_gMR04v!em#I^o?w^jUL!Eq4bm15z59};$T+!5`(yua4?n48 zu_ddb!otwwWaWyIy)O_D2c!g4TRr_eI+Pa2MGF^)KWmRFb%1|F}&D`T9h!-6Kio%|FW0Z_)FN4 zFex5mx<1_zQVw~fRDf}g5+2qH?*7vXyRG#U3!!`(0=DHR7cX# zoT3Eob>nVYJtIydTn4-NZQHTi1W*@tJ&_sV+X312$Z4ROnqwu1iKFkS+k+um1dcpD z$tmmSOwasiQLHk=yuh$-O)nhAM}$ub>B`|^;97~@Y0Y-Zp3JI6Q5ttIysV&^8Y z@~znJgMv6`a-Jr0#q`mlL?!d9+kFY?e3T^0Yig5rZq`T73iW6EQ@CVA!NZl^x|n?* z_>GU-{t08#kfBoBIp>>~X+ek{yiUOvy6+5{av$wD_CilgUqqJK_=k&$eTwQRC3IsM z!`FW4;MGUD0hAWr&8jCP-o)7iF8QGy5h_c|Mz$3*(-F6(SC{rBq)sAgh;#u#69Wj~ z*;9t6A99D3`fZ*)-=GIYvOB^IM|D0=QGpq>2t+Rt68bpp_H5}+I&hW>sBG08e&5(j zQNb#t^%6z1`3c_!ka*;1K*B}+GybcdJn%O&Cn7EXQB3W#Hk!Ua!*^R9`RV!%sj03{ z%4uT*`CuE@GyuHiaNt#?(ABu>0CxMM7&?l*suOa^Gpu1F`WbrCE5B$5ZTRe^=ZN7~ ztA{p>3OkJm&s_K?!Z%|F_xw6?#n2GkTW>0SF_h;eda=uuK=NT8Y1Az_ z1k^QiZBzFYO+2T^d*oPLI>}i5{;F`;{B3%YB~NQjXw1h=8;K%+spIGRD2mUj`@tWD z36Z<8&-Y^si`o7&hLf*RJaeg>u1uype748BAk2p0U&&NA3%L3s^CRLdcf$>ZQXC;? z8vHuJt|*7S%rg-6E+%}A;YJx~?R)l| z&;ktGVv@YzX4PZ8GqxD>+|-1Vjwjuu5#NW;?U21)PxHiPyS8lLeDpBMkHK3?KX_fu zBVOs%Cx}!21e4Q{s-S$zj&*>^kUN3@ayhlpY5bMlY#4Z2N&R9N#39qoF-h)Dw0SYX^A5kW zsD-cAXWjWXwh$7TmOfIfcVN+9;d6&U?o1Ns2K5qcSA1)w@WYx~ zXvSSt=eG&~@zGX9BAC>C`+XqIQbEov2Dgabus~(?o0|hu!&kn&DN&~w&itfoG5G|H z?ss=RwITX5rulQ3$CsxyNdTuqr81<^v~{G?77^1QS0 z<<=@QDVhLF2xK7hxteTiNgll8?raO?q~%lL&*DzDuG@de*S2s@6KX{~@*!{$gT=L! zgm!+>O(U1!?g&wks*-PmCQfzfu)NuRQ&SZ8eSv89_o0D7T!9L;v1uvFu#;jt3^O0N z^A^$sH)#&aGJh*$76arO12>&17R-Rqo!_GrU0Q8DPZfW2xx4@U&t_HL?=zI-@?=pR z5~xED6OK$L)0bZey#B&}S})Dia?7)(kr|Q7>7XSqSl&B4<<}8MbldKg!t`m=81(tu zHN?^T5gj(7GbnHg*N}Sn+*X8*w>R!0nt05MRLG!Z$O`=U2~?C?z8zfZ67$YvS*P6} z;=GCt6)ZV$GaDBQW>wB_*q?}1PPTKzD48UC#mkxw|J?k@^(17Wj4*N;teO`qScv<~= ztmM*Bv6WK4=I76+`=&bcMyGGG%hgDC#@z0J(Q(Uok>ZU2ng3FC4!~czYqWHe4x?MC z!ZoNN0EM!~>8__Y4Gq82v>HHi$a4rl45Yw3h9!O}5ec+#mIJJ`ixo_!-TNM!QGvgQ zzMd!;v>y4e;gq5A0O;7bKKM?AcZ&wCR`V9UxwUMn#tGnDRy8cDQUhX>DqnlE5Sd`f zz|67C$zCj+59|N~t((S6+`ONm(W1rSyE#zcKsr(x^_FO5tTUxn0_HnjDV5X(PwD(d zC3Wdp4-JjsZkMflJw;iG@w7aW@Q4D102w88kRCL_>W$H(GB^jGJ5T3nidi7X$dm^E zQEm|dvF``P6=$V1H6aEVf@W5q#3URm|I=a&3fmx+LA*4JIfl_f2JwIXsJ)VPr_!u5 zzJt=!?QIXL5ny49&~^3Sd}2-|(pV0_2~MXq^66T|EK`QSs|E%KgT5c#^%}=M|4R|L&;XV8R*E~# z&K#0ZT$Cls&;z%8v zD~-mB9u~>b@CKSc>j3W@T`oYB7`lo=s{`cRTgSvnSbj{4=8&ocqAB3}#$#JoK5Z_6 z*VV7+Eer?==UTQYx$u|=*R0^CRAO>pwe3S_KejJD6X06R4#WO-+c&=155M@;kzG^) zxisjwLgVqJR-`&QD-9hZ%ekD{wX^x^4 zc33kKOsH)%+_z>qJkFCS9VR!=d6|rUo^79E;P-3u@RYf3@k^+DEsvKQS+= z;)6yaVzX#$BXh)$NQ+Gre)%@PV)>XY;@*6^-SiXkuEm_|PR}Tx`sSevb+_&A3VA$1 z<_DI2TlYxe4nXc6gML+I6=M#*-A?5&X&Vzv^SaVZIgLYQ+@9e_V_gGKx(DD)5p!*%Q9WA4n&?n3^P;ND9wHtHI2u$M}7~ z&|d^BEHv!~cI-&(TXhWKl>7T|go=jjdtuUGybeze?9?oHNs171ZH1 zr8v$^{l%g&>h1PW2Ft27a!bwwp&*iCS=p;G=G3oqa5yqDVn{@L*!sS(GvwP+MJ}s` z#!Cg6)MrgfNPd+$+4iMe2v0FmJu z0o<#4O)h*LTCLS=!g2vHE0q!+-2I+L`6lBI30rpSKW$F_2;By%q6g_&m}1qXk-jre zl$y0N&E-*oH!p)~Kv}tCa|Yq+S8qy#x*A8ygqY>ijbV|rut(p@G@7F^AM_$5VYDzc zS@EH>WiHKwo%qET^ww-U>y`2ic#|4yAVMh)dVN{ju1OG^H+l(0Zl%oNig8jC zkT?+uV#G}eOY4J|Fw)<>lR`^me+fKW^(tJmG8k@~y>|=RZ~(wL;=e?AF~d_4K4D*e z3+DiE&%!PmZEB>lnKctp1Pz+oX>Al))B}pak5Ki2ZWtQbIeW}vk~V-4kQaO5ZJ0#S zmca7edyjcTGda#UR=?hWl`Y!v^RvH9 z0oOIn^K5AYEBJd1$&HnF3+c|1R#cj!IIJ_U^1saI&vU_YtlcW zyBO=9n(6;9K#}DFbe$i@1L9Gv?V)gvoMFkkxSefZsd{r#9=RHO!ejLmj&ZwPtH;xa zrzPRKHofo58bbBXQAa{Y8OjLq zvyaO&f$*q$G%IiVMT&}GX9oW>2m#J-^o&qieZ4aAt;huM_Q1T4h#juYjz>*N`joRz zb05Sb!l5U$EY3rTu7`;FAh(&SYEF)dkJRs*{Fk}szi2A$ACQ80wDj#>eYNxU4)sJB z15EbGG383JAMCDvH7h;%LBjGV@3WYd;@O%_5^9agqI`&!D@fx7kHaRH0{M}PYkgQ= z1DDn|A>frMX1iV#KPtXgH;S^4V-zciI@ok|`g_y5ckXwtMgGIl51Ouhq(E%s^FnU+ z%iWzJO8lBnTPb#n@12=?d@Zu@#uUOg?-+Y2@S-4sE+F;d`2AmB0@7_B?lKvj*FVY+ zS~R%}P&OnD`goiemxk{*=sswytlxV&jrAdR(IC@)!c}!Q)9jxRZ)_)GYT+tgu=u+r z&H_!wwetP>j+i5!qnOs#PpzNm4FG%3y4R#B9;T+6aqJ^o%KF&+-NLNCaCx`&Y93L@)0mPoz9 zHAoyyV0gGfA5ZNxH&ZL-qmLzOqwlJPJ@@l)=$zuDyWj=%3CaQR9wHqTmMnSzquDZ` zwo;wZh@120AB^Sf(_B;wJGj~}A`km}x?@~+b|N;gYC zYw=zy@LLQxC$}Ue0|b_Tz}=SX^FxP+!e&R((u3Sktu%m>Uxw_~-vt`2Qv>EK*OapK zeyvd$GDhFHnS!?WB7MlxH1oG2!AgMirt$PE`IGMukV3#l!G^svrt;rmE%^+$a^ItH zV}{1dxt9QtzLvVnVYzML#@PNj^#Qp7k3Y4WQa9H18+)L`!)yf-R$5zfhqEmHjyjy+ zT}KRs*$W!L7{Af%di+DmVwlP(d#Xu^;fbNV}!I4*<#cBC>p(XLUaLnAxm zN`;rXRy+PpLd35Bw|W4>9zCSQGB|#y2)b4H!LolpxYAIT`^8L0VcG>8>$aKtKsaVl+s9 zK}EV7=@3ymrMvm>_u~I{*WPT`^IYdS=f2P9hT_j@6T3e%dziX=@VIELb}jnVh!LJI z;-<VmoXy8m;PS0C@qi?~H(TYH+M063W&Y+V>w}i9}lA6RN_~=%){hc3Wl2f{~ zAVlAm*{m^A>b$De&*yDK$Yc-{b-yDc?|AzWr%Ku2h4Mjve(NtZKZyFw!I2q9V|>Dm z`9qlL{*@XdL2l8$nltQYAuAvR|0b9V9cl^~<0C{efun%2`i@x2@O^vtt?7H7vNPT|TMP5eR7)2-)mA*k7=k?(%vX6&OQ?k;*!gUJeqjVOIG-=O=r!_MvYvs$TC^ZGV&u z{#nQ}y<->tCtRam8=AD2p@9=FfjeKMHiNjm+)g?K=t{#<7I zfdWy`Et^v|g*n)&8Z#S?AY^I>tjZ7RWm}Js#CBqiV;?_n&Z4Ag17UlS(c)WC(fcP7 zhJzwEc^>|jNLQ60c-~_m%?|A9X#nIgLolW0IEoTdc!`?(*J6n<76M)ORJ^K@`AY07 zm``jWyYML*D5@Jr{YoJ0k@uq+JjyPW{H8sE7^^JO(9}mVeTW?UnAdY^H(~e7)ekXY zS**$TT58~9Wf|e_fZNMHQX>L`yCdOzIY0MT(jN!?p?0fuc+f7^cw!T~o5-PN|k#~!?u z(NLWJvJQc-q#cc^|6P9qV)=J}b<#%-xCa>2(o_b`m}E;NCw&T3&AS5@Q2ZJxC+9`OGl<%X z8!PgOde~K}@1TUFraZsY6y{EHk;FE`IujEcH4uGS&il2H$+K{!CSWoqETODDwcFka zefQPkiY$fUw8L-uz#X0@B!SvqSeD9iWPywnv)&$lwaTqA)qBFj3ixvqd_>evZTJG= zuF#}TG3=`EWfHDny`NQp0kum;9 zGBKzsL-e^bayqo8#9UQhBf5cG#=j>~x6s%-Q)9z#)-I76HFL%_M#K(I5K0oTwRl-` z^gq)QD6U&y3SX z<=SSEzIqfl?EqA&m^4X@AS6}gzDw3}s_gw=Gajs)HrW^s_@s}n&7e1|TF~ijRr?t5 z09i>`dRl*PW#!><1ZR*w;5TEryvl6((Oe${#s7~8R^QYHMu8&^`ZSuFs(l~oLz=xm zg_E*z_9bMyFn8HxbUl^ZrvilP?gbvtN5oM<7fazjm?lqHy&3zsP)> z$byXaxNcl?UyIiH_2wZ=mct4mBcy#8RvUX*{@N1!7eOm`9^ST;&x4>F1_;u^b&i^x zzM3jeZ^kYB9@Y!nPhS63M_=dlK;c?nWPBmZZ)C81(lbi*@sdZQhVp#fQHC3+o7bV3 zC-}5h_lKeTllajPfGu+hX{nX@Ay=|n=fArsdb3hv7>%)T_}#{V^mXUYLsy9bzc9R| zV<*3i<-P;+TEC1|^XtIRPI zlf1KDOFb(^;|*9{iUU+DaDpIW7>ZUZwhCa%c> z!Wmj-3r132i_xvQ3p-WdcheM;1ZLkFjnI7Nf%s@C28^Exd$9uLL34HEW%Q<<6p=+U z_MO5fv^vyV8WvISAKNB(yb+}h$w2^QstoF;+pc%Ha~FdT2uE^c$=HZ?jKOk)OZJW^E(R?*|mdqJJp9kGXZbI4YY=+sy}>DA>1BTWdKEMHxBD;6SI@Ch-b zeYrLOOm&-VZ-pRF0UzimLs%nm4|N1xX%WoFe5KrwADBMZ_G*P0nj;&<55ofj{Nql+ z)V~25#@EKRzh6@s`pY+G^)1E4zHjkB1w5#iZf`7)-5jXK{UyqvfyK&FowK}kf8D1& zl*F8v*wG+9;bd~nbl;g;fGvkjx5gcxgmJfBVA zV%+i&h)xagb_}&d^^DoMQnPqruzsHVyoMWk%514nu7>(sznF>yNjefiD9?cdBc;}G z7d*%QdT8v51YZs|GeIT)SY_MxwG%{X^>6_l%g*H_%zc}Zs4E)^{VK{tJ7;G9Kr1|B zkR4d#RIWIG`zh$uA$9+-#U@+p?nBt<5TCbL#Lb0FrsMI?nXP5_IJKngoz*Xsyseu= zxA|p1A3C)W5XqI_;p81PYTQ0aK$v1)5bkq5rA_?;v@E8+AM9BfG3XG_LS6o!rC;9H ztAHM2oH2pQ@Rs5+2?TDxYB&NXvtJv4wv0Uu(M8Mq^wh*qnGv-+y!-C=T~0>U?(pQF zP1YMZNJ79_)19GOD4d1-`D2J+?tfo4rz4WgS4%FPDqRDNukXCv9xO$07;H3I22?%#iU|1M3In*;%7mwR%uv_#^je!u6^CmA4hIc2cj&npSSy0O)zB z=is{MHf_7MsQ{*iwBPi3zb+mPdu|3WyMzd$f@z_pP3{b5ZM1w^V=`@83ylp)hsu>a zWeWe8o99Bvt;lF2;y*Qzt4B+&R~Mn(+$%Z!2&?-K3QDH}Rj8?@Z}XN*oln(G9R5D+ z{K)2&^=llhHHW=he!xi?I_T2wh$3UHX9`m}A=X~w`sBYEjpR3kZo}1PCpv4vtk)0tk&;5xloU)F?DzxlCR~5TQ0{Y)bAM~nU%HJ) z`MS#l31RpBe!HN%tIJlYsX&=uB1QKDWe4arvtZ9)$zCi}rvX%g8)Qpc8m|y!CkC0~ zsq=DMIH>2?@b;%SVQ{xg*LZ!eOPd|LXV2*&i;%k?9!BMhV(M;CmUQ>FuiXNPxgtyj z*Q`77iSfUfonP#BJ7YJ~=ypaA8OE}rngsxZc*~%SJ?{+`ZDFTBboWwK|1jza)GZfP zgW+6nv)k>hdL8jY1qNg2ul@!dgw{G!m-~LZW*#`>tm^H1U-cro`4V5rVWD$3w6TXnY`>(_W(#vn29GEU^=mL7o@TrR#Q@^qDy3*u^=t`ui1h;9UNfG177CtlW^as*Y}#YPjg+zl0QwHtn!WTj1f& z*%OtwbE@t;{Jdm%SHBkJ{1DMy2?cTv5n^@IP8rh<-fcB##i!dsXD2TO$eVso{|Fk` z{+nU(gNH%M`|57;rBNr5=W*%rN>4nFJZx{k|L)7yT%U6j} z`vcLFUAFUHIIRwC!Xsgyomp6rgMraL`4w3ivmPeTL&XI?T`WKEa^jH8}opJCzf*4F5fSi^SYu$V)@J!a8s>hX=8;k z(YRV$L1|3|DO(*xfd48?C9>as8pGpKa5jplWquq?5{f|*_!dsTz(GY4hAiJF(uYf2 z(WAB62h=Z5S}lFkanNzZ`)RCurDw3;yryY~5-xMy}vClF!w=LH0P| zwnhO%u-v_B5F^?BBZVQRZ%Miv5eS+*l&Pfxp-+b704#G^+hYHI+v@ATEv^R% zAV7!;2YkT%5zqT3gC!*5)w+gDg#6W z<7IRlkjBozd5KQ^b9b$MiAuMZG%8DPC_jhWmU)y=7?GuAXqa4bBs~kB%Dv-M%A0BU zB^`Cm?Qhxk2lfx|raWZd&-~7&WZ}i^F@g*qN!tA~wTy_=>nMb$T^d3;fl?AV?cIgO zO291QJ;vGo$CdOYj*TCquA(ZKMo_!dVt@kIGr=pn@aLY& z09XWvN@2IrKk5iEHO1l43Dc9%5xKCn9P z-)&w_xmpwWo)L6XD224}x2uoGS2c%0vF~h|kw9HwSxlNGHiV3l%**gfw#L+2lIi+T z)c5D9nakIv#GW95ZaM%$(_4mHpCpGHim#8s-KAk+Lu>)k>;q^UU-hj8nM?e9!xwrJ z1jyD7^ZniY@IL#G90<^UZ8b44c-s7?Blo$?1ex2{=BPyyk=jsb_!qNw1Ij zffqYG7AwoSXTKLmr}N3ssvRXk_gs+Zyeo$gStp25LzpabeVv^>FP=qBIZok2x?^4? zXc1jBZ~}F_7DSqThV?!MSVk5w(SF(@+WI4ez%BK91f~l+23q)DM;?ddEad$OxAgC| zypYBBBvCpat%~{+cmB*~%`y4IIva>sAv*C*HLK>Fb(px7G4IuFH{ytb zZkfN1cSd%*k5Ra`s5MRC=?9Hl#)_h+En!e%x@6PK+&e&_V=A70ZJO9z6p;mi>l$JA zKwFaf@qPJS3~7d6#?oz}9`y@>`<$`$*8BC`bUq97g3wJu9Zq z{n`f^TQf^WK9J!8IGm7E(Th6pvEC`VG1AtraGFs$qF%(&+ON0lNU~QoUk%#+yf6Rs z+1VP3mG&gX2Wd-2x$Ur9i0u^u_46skgqXpQB5`^vwLKe2G=@Z4Yw`zRYU zBpRzdhazi#!UdwAp;_0kSqBJ9Sl4>>ol#`FO)u*HNoe?a=&PbBd3EWQ!S5M?ED=U% zQ4)AcZL1X&AAnC{+fnM3hM!4hPf5SFNnsnyi`X`+*4^oy&$-6Dl zDk~CI53Xff5h3jlRyTiV>>$={l~wYU-jefZ8McVDzP1P2^tj)bJ9-e=o|PIr*Q7uR zjXGHp{;Yf+&-F+L(Gb=0vV7uKGndwQDWV-2hd>I4v?1=LdS$MBd|YnEs+N>c2WHR< zQOt({Xl#bfqyT2gPT?z&F9ZUvvvhT5eI$UpigYo$2Z=J7DlT z)XhJM@yza)9bO`g-Pi2QjTqH7y&T23<;*xnE}k>KOO@@|?d0r^lx^su5OJtD1r26y z{_~M-^4ja;w0zkd@d>S6Ez+Ie2TG8t7(LMe)JN>PHrMQ+vgYJ@A;bh};JpxdjVm}LE$my|v9F1-D z`7dlIzw^TS{Cf)n15}Z`yGw#Z8qf%CTC(W;Mzn7qs(ka;LT1iT>@b!A6S5E>FUU}j zxtcx;neX!zmL-RgK!NAy!CcS&0YTn&7;H>-+%Wx zK>Kn)*xj);L8ui`jF&LNf>{;||CWfyZWg>qKRIL}!+%*7TEa1=y4`MXO{+sH zvgPp}KXOoe^5LPeD7)86`IXC1tR1p)t3}E*bNtg+<_9(!4A9o0k@8}1Ay0Bwcm+vW z9T>wYtys+BAMHN5ZLa|0zMtjP#`mroKj(KS`_spxu%Lgv#{DjG`7Hx61qrWNMD33` z7+?)O3M+I}2{$5uxS3_%&np1F=w=&S29L`S3LzR5zK_AL;jn(>Qdx6LaFBcr<~Qjw zk`63Uf8+GsiF*Gor*QqvcmEssI^}M2fqJA@QN|UFOPz<`@dfCDUGdq)(lp5THt<1` zyRVPGOp4TJu6)%=y!Tc!3Qj2R8w-5p-;nfc6xKdSlhe9F-+FElaOI)j^#5J}Q+x}r zOi=FW%t3n}snWzr-|V`?+`VdF1>ul5t(}AE{GD7dcxWRE-15q$ZnKF&T56^sUqsau z)YXplN7C8gIa3nOb(JVw`}%IXj^j=YEM*3P>MKqUIsB18yU24P4ashENh#-;*T&&3 z^u$~ZpOO&{+{`*z5O2@_-jCr%z%cgZyuYF>*l06TF`7^i4guG*2nb+eXQWZ`Emd23 zvJA-a%pj6f*G}VNWyTzS_EXc~Usx}rRC4Ok8ff0rV{^cM=M9ld+>y^v!zzx70Ja=) zh%-z7IPXa6Mlo0-XG5ENyR_w@jkUucdtEDftB!c|yYtG|B70kB$HzNXh<4Gyi3X@A zH?awUFSZu(d3Ru}OO3$BHO!*Z_=1Q-UZK+K=O~~cxUtq97qfAmNKf=ViH15f9;}8Q zJ64GL@^GAYyUL0EUY z!$U_OWy8tRb#+_!uKmeP?7b9!D~Z_E>=*2A5jN~fgSyMr5+!zHeI!KUzwD%-mW$U| zrwxlRiqH^{?d@hZ3nsj>{wV(t!%rG#!AC7toA|r~C}Q zNwR^`?r*Dm;5zIwr*S>X3Q6+7Gl)rEEmiJGZyQ=IvX5C~*Os@%IOODwD8^#g7-S7C zO-qf%52^9}MWi%*iLdkM1;}J%li~uqi%#dglV_ix#Q>n4;yk&5wM-u!efCSZKBc&@ zS(Pf3VK(dfcu6X;6MV?#7NN_TkPkf=s|a#9xVhs#K;KQM!U6flw=IWLnu*C82@++Em-($^;9`LDQ~79q#pz%W7xfMHu|_++!+*K zhM{PLcrfzm`vjtZuNuI885vCGji)SsnSin@yyZ1nyBpv8bo5@`kL?=dF8;+8LF+M@ z*eUrOE{cU{R*LL01!SI{PiXW8!!OMi+eoC;n1jKETLpK0qKxIdobPcy>14SwMT#OC zD4^X-IKRC@^Kqb6bmx4aUfAz|9{XR_pz-ig-Ns&7u)G|Kxm8QUw|io}?e17W8!~m* z7SjF!4f}c?1Dl!u;CNz6@H_ikexB+ZyM0}DYto4S+VPY=ovz&r>H}~t1-lW^WZ;}u z8gZ5;)0!Fnhe5$!C|NE3m{Lz7U6~xnGwzYurij$pD zt|QOy_`#AtA4=U2GQ!Mwpc83D;dc&AU& zVC{U_hbdvlA6W<6Zv>9_R-%rG2RFMk9n{{!J22#Ly5Vt3N`eVMbB9QGCavFUBw$( zeQvVQbkD`*V;!E_edPBn!pd^-H^Dw<1Qlo3yP(#HyB$OE)XPCqWZde3x-JMA=YSswl2uqGwON`HAN zo{b9iR$C95Vpjg5=9FlXffN|G70t)XBVl}U6{gU!`OVzuHr;QCPjPNeV?|QFCQjm8 z%TKr)Z+OdwA`v-eL~Lzr>rbc14>zCiz;bEoNDja8ew-`3c(K)L*73XOn07*^a?xK z4|_S3ZIKCWg`x<-dMfC5${8K-7eSJ4EhzM@igEvIfPR3-P#@|G-=lP6yfhVVBQ(bf zY=O5IHN0;FWtX~l^71$`eI2Y=6}UNRmGLam{92MMF8wK;;8I}DM7E2V6$IKVELMbE z(-$W)KGZ>`Q;Rn~d1U+S$0-s^~TJl3*{)!X)w)SY_m&aD|2@Df`GyqI+^ zCAIAXBB2R^F4er+Q2Y`;*(TrT2|v7`KRnjUpNPYcess=}mWX_Jt63Fu`2O8(kvgQ1 z2(J+MYWWWbkH?Zm{>Blr7_qT)zXuYB+sLo>e>=&sz+~r?>R+rZu^}R8!h{)Xq;ti8 z{>lFZ18nQaSrcu_iCg@wt|Q`+#lJ%CO&i=Y+$gcC_pMY4aZCNuhy*@6dEdGNdHr6? z$@>;*J1V1D=%{7s=TFaZ5bYiYKi^P`$(^dOZOuEjg`}=CTC??BZhla+tq zESd$G{?-5BGmV3i_awfg4tly2T<-DCwqJ^g2|{K`1Exs>iLfj9zL5 zUH-dJTKr-z-q5BY^eCdZNpktywIg5pZnsRsjzA{G^v{QP=|OpIhx19ZvQ5`%sYw|! z;J{Lb429Hakj}ZrfvMtj#<8&W`iOSZe#+U%%8J{!da|vbY*@~)Iw-#kN+j-BtDU%y zzSaA%dK{0J9>$yW6CZZtm?4On;(^943QdajXm?oN#`rI^c6g}iFe?>Qvm6=Mg3D0# zJk82OYA85NW|r5epCPwfy#~Yz^JMYw;nLaSGs9^QYiNF;xVTSd&YakgyWRqdwZT_* z`Rj&c7yE9<@9&+@*@lMdVXN22?xFo`%touh4LC%?m~b;vIVsT2&~#)WP!QhAP{Di^BVz2PVAFHr} zI*k&^G;!XFXb40GeoB|A|8$+4XU;k6=uchol9>ab6U;*G@h>xGDdL`NAFdnWD(n_m;@ff-UV!c;Mv#ptJ+9g$vZ7i|0B7%AXK9^T%%jiJe4efAhYjpb3T8 z3PVz5trtCYXsIchEK^hs#By^$fVjH*^9i?>zcGFT6#F>!3v)AkP+s^>>_m0b}eoZ;IU!?|AcK1($1(?^UMG zgY-)PzFo&YZ)mM@_(^>bENiTROOsD1RQK0}xd=C9rrO^;G!=Fk!z)*7WEgcQz&L;+ zjDOpucBdy`(q)vqyU5QUk9Pj_7q2^@l)8L((d*-WQd(FfI1*rc8~~;0Bx`$KMVpZ_ z+Z_5eX)MAEUJd_!B;#dvycl}fMel`&*uqRr^L=c_K6(pix={T9#y-?_4)v6U%rYm} zw0S6`+o@(Eke0Ip5UDOrY=TU-2AeDnXnv()ivvC%k51Y{@3l)iNrOzB30bF3MKE)Y zQ#0`U1OU=f*`rE#v~Yr(Km^*2?9YxFKMgs?X5T)@dY}CkNDrBb1)INBl5BT`%0>@Y_$oUt`Z<| zF7+OnMP>(ZYdHbhpL$O3<>4{u*U2BGe|UcM-*L)8%lhlHTbh`k?JrdAR=a&W@KOH6 z8*`5;>`CsU?lO}vixwUe@7jk2{CXHl`#dVg?R3(YJMP$?I`fafYK}(7paK;3pG=e|}`IDc6P%IRV!dw~;MEJa5e|OI% zl^mYz(ta~@jG>TJ2RX?T4{fREguulUfBg}9HGOf#N+s>NhUf*NzSQ1p~!-T zsHY5Q;OmkCCT@`W4}LgSOk0sf^eaRnNpia6X7p|4svx>6|1}OM#Q=+VUlKzdvMF zJ{d?AKQ6u{s`n-KqkF zbX1n*TIn=#bYiS7@FASXBi&XB@Ax%ro^%rXW*P$21Tgr3`7iWdIGBz}qMj3wjvqIm zk+K8D(~D~TF^h?Yzq3xB?MpL8s-d^|UsIW7ezdP9A|A!l4}PohlS{5~+~0$mxW5n8 zn%J<@$_;qe_(Ka$5sw5&{{k(1P!Agz=`4OAt@sU8qeMk~o%{Ft<+mUS z+{4is$J}>7;#(;G6M>f?N$k$3Mi_56aM>i`OtUz$2=0l90#;V1KE1ONc`Qr?${gY` zQex`+`;!h%hArto=>PshD?1>0YgkDjKK$Iv) zSxLZ8@(@aL^tNV68Hq=y1#80fbdko`@aB$NZMYwDlW5t-5Pg()S@BpT?|B$~g~Vyl zXFgmL@P~?AZ;tt;1oJKeXeq@$`lxl*ftxtijYHEKX)X8#j8TJtCoPN8&JsV^V{pqj z;8KGM=ixT5*B9ubx|Auv;PwzA!DHVv8`G^q0J4@IM;$=i;k^+r`b$sA`sT<>L5TUgc-L~Cw3U*n{%=-u+)Xd z`WEEaVhK$AxPVwA($mi1J`w2F1~yGscd|4_YE+C|6p;ja#+;0hXMuE^(;oVb_++kn zbUJOcvl~!I%jeO#jJaHkBAg=D6#7eb9i5_QhX^j3I>xgNoQTGcr>_6wdQy&@q6khI%!aZj8i6R*I7zJEERH95fe5 z&c#Zq|AC$9WEMm{=UqnNv2+TUoI@VJF=;h6v%#P7w_pIBA7mhfpqBBv#GX@L`9LXi zN4=e(GMtP~hwXKU-edjbi!o}uW4dGIGO#!r=qdQ9S~3|yF1UtWcuj`_MBm=$i8a3nCnGi)wd9v2N9CIw%4Nh0gdSCk zZ0~U`Hf^OGd((wwN4K#szagCL=7otgeTyqgh~*xiU*0A%L|& z4x`GBuiMet@HNU@g=h!!Y6sOkD@zWDmwHb zw#L^1@*YO#z_DO_nCvSRpN>GbuSAdRJM3N~L)svPS-J4IEk%sIn>u|0PMYB$Cy*Jt z^(5=7Mf=CWD3`LBN@2Pv~F6tQDORH?qTV1${dr+ z^~B{l#}vxs>Kz$Ac~{a-FQPHYY3(0lL6Wd-FwdTdT!?qyl8Z@wAj$J6BxcSskflJ{ zaj!=_tw&jj@d;HQ%FM&f8Lr+t$YW4{rL>h&1C(di@%07!sDZ4N8CSjjqmxqY=#o)x z2yW4t8$LFkyqq3RhTGbeXMwIt1b5k<_?SZq*Z)m~id7S8D*7CYI8nP$mI2oxg&98w zQHMTKbu)Z%RAry;pP{fp>ejHxNjN9ROAsqWKYE7d=DVN__O~+PdutIpNJ7>oQI{gz z7@a2zxX$tv33nc-C9zGq4ILU90 z)T2_JDML&HN*du_(caaE zKURVkiHVm>kUpB}sWU|V5dK?Y4M69p*Fw5zHeRA0lU8+5(&_9E(~UVbWj&5KZ8niD zbgc2kM(#{lmSz2#lQ8DL5=ERM?BI~+Qz%v?#G=SfmI&s9qbNc|A;<Y1nP&S=m^A3Za`Y0hDRk$M97!$@WSLH2EH>pRfs zpPs^U6hBE2oj=BT>j=oEQxG0&GaWpv`jjU;iJ!1}467Hpf|-=rUxJaO_BKdk?Et%2 z6V1kdOCtI~OUhv~Z-=y=Zc%1E#|;+~CnZ;};rY(8@{UP_L((pdw7=xti}Xv-3Nx9` z{cobhpMcb^4M%%v!P0)s7wXUKaDK$ueX-ioY_|V6h#^ZI5KcChiGg z>^V81_G0Sv^hGELIHY!XaL@&+hBG!2AdDFfl=_8N=zuh5XNBb%MB-=1^h73reeCwS zVlu6nK=U}JRxMbcm+5}Oj*d!FvBg7L?)o;LctVIeuS)0)^ykY=@^Bov7i)b{%lN>4 zj#W&WQ?S*K{JFO{h;zn#L$xmWShRK--PmDOaoqT{eu4Gqu!)O`sVz+fy)6{PYDoe`i3E2#2}kdjGwI z!@QS`33>rsSn03Yt-^KUysDPOhS$ysk~@ zyGFmwaa6Ri(vP^DXIGp~EK+aYSp{8Wxs1VT45O#DCf0#u!sB#f{YyNtY_QQ{>^Yd8 z{>W$aW1&}P>z;WCUeKH#z~)p#@hseuvLMxXQR3)gxdV_0I%Rk^5(LfPZ{qR4tvt^PJs0YR{&G;x0KRpj3Jzo zSncnIwHgHhaBRgZRHLqz4z@r{>Fn;3y-bSike7FmW-9)uuYR=smb<`^kbt$8(}3s; zlRxk*3;5LiI}YvJSmdq~ksjfOc1XlT#8V(l`BT!5JnDs*9j-55fIvVv{#swIW683i z)Vh#XM6HHYL@G<&b#E@768RXxlj&47hfzH6Gx@e*F#QpQ2<9_ZAHXv5nGipQ`)FKAgyk34{*U>tyhhX<~t_iT3gUk$kSMTB3BJkVtaa!@0_8(AjLD z8l_(`wO~Z@{9k2Ti5~oscy$D>M0Zg0U+#~2ZIK`L=AotkO*@^V%8}SBz=(3$=q?}k z)RPuhvwyyYewtF1=SCDYvN?&=@z@G#hKh`4ec||~@?piO7W||xW^WsbGuE!5q%VSC ziuPB5)Hj-NX9%QHJ$hkk^wriN0$Q4ADmY_UgGX(R-1VXL?7zo>V@Ib?+=PO5%>@8& zZIC&TsZ??uTXyFsi``F~fFR69007_1^y@TrY2SkBIMJ7<(2bhpT*oE0vOQ7gK{Eri z0JW+BL%Am^rdIwWKqLn;(&$6j6$}fGRIgGg^ODS_GI>={6>J=&4p-WgG#=w@vQCt8>4q0Bn)N{>;F0BHOhU5tdXvZCvnr%LW^bd@uI~k z>{ea9CUvXv%{!O}9-fmdz)pg0|3p3i&+;YFMK_02mVq9Z4pYQamd_OYf(Vh1spgAE zJj^AGvhT@+iPD8t{yI(3!eMy%FFw7`qg|=6+Y085=lhroOk+vWe1Xu$b|;n9yS8Ha zz%526qzFk{hNIl-+3dSq;OkUFCj{**Dj#RSBtSsCJ^H=fKQnR|K!@a0B3FkBna=xi zVZv1AQF#y=n|ABXuJVFL4otPZ>)tuKPC_ZzqjSe$1t=Kj02Ec|^MIdm=6}Rpt>gn> z3QV~Hj#ZR-dSGPhB5m|2>H`V{6T(!)nZ@iwx21#OkpK4r@V!d;v#XB_ti5ygLH^No z7D&y^e)C-&gT~iKQkt$AbY1?KYNvYbdik4c(JJUCOKJg8LWs|v%XIn4en==kSiVPV zD5&tOJ|uh8Z?NW>--6(p?!nZ*yTIcy=>(1V^6-)oty0K|Fe3O<9Pk<86kms|f0o*v z4UzVIS6XP_C`v0Cr?R>N>t2dw`E7M@hwVgn-v>w+o}e0NOd?rSygQ7D zXFz0)cq-i|f*6nT{ik`Wfd10D7*%I!QJi%wmC|4RO7Q-}$G;hS7kt@))9$#@Hrh^S z6uRgl-IZFi3?a*ZSh;U1a?kSJY&zlJ3rEpy?mH+N;-uI2{Gw>o{z-@1U`- z`kumJqlGbq(EG|m3ZJick1)VA0dkL3+q*(amoB$dTHy8TD}E#hXBp2R;z%~Q0Xwy< zz}}-ZDMI0qk9_b5MospA*%`n*!ffY(VI?po*peB3!@p1O^FCpt9hI*U3d_$G%0i95 zwWf}m-M@JBE32${`8YB=@pxuDfUs5S&D~KKTmVrSO((MdG_eS2uAL(+oIvbJM7-6> zY)p>IA-PIdeDmV=9=#hE_RvyeuQBzQy68oZo3XgFn>9=%6wd+a|If;osJXwmQ(9@j zQBoQ-pi)heb&rQR9Ge|)O(6D)8IGcC984U~v85bOBz17Qd;>$RG5^}ItdFZ>dQ|!H zl~OErPMF@o|K{>Coi12g`=#F(lW>nY+R05xAN;LPp5eXerv+avITOZ(6Lcd}td1R56>{O$(X-gu(H^g|De!jVDERTg>BMj@>{!6zu(dJkkP_7%I z8lcR>sn01WO@OWBJE%rdy0J?J*P7b~=#YQ!2U?wwM{Pc_Ku4=(&eH~yS5cWS3VgDU z&8}L1?^$2`_?*2_Q};^viAN0G)UL3i+Ci<8s%rgKY6^mg-O(&!c^%RDUjIcY@6!bJ zzm6BUe2=|->Ig>$jc@x&oKRls|fEzIcnQ0jasiDG ztkezh4-Wq}>y%qD7E}3hO>T7TVX|1s;rzX^RrL_(TS#QQpgT*jT}X%+@z#pz7|Pe- zsZ&#nFT5qK#>_wzQA;PQ7>-P#gMkq40dKN%%88Ty({j!NAZ@RNcFsOki4UXd`!@{r zQx=JLDD1?p#($jvX0V(=YGB2xchh#hJzKM!1#I}bhM`#s*pp&y>RXT37y z?b27T%ort5TQ>6yPw$Qci1MeG{j1VKpm(uyv$tahL&F)r*jZ$W)sClBCrM^sVMZM+ zFPTnw0eRGWlNE}z_7yY4w)!A2n^QLh-i~}S7o`Qh0v8Soj&dDF?Dc=0<sj!HX|++gpZ`hI?{6=+>bU)x6ze*@&w-=&2-|;kf&?N636o6 zttMV-KADS(@#|IN9UVXg3!9Y?K>JHaPc`yIFnMAeIKR4WcXw$?KCr>EE}Sm81QEvO zMR|4aBvwI)*K|BZ12WM@HC7bEo<1IDicpDFs=+xKy^#vGS`T3ZyFTd{hqLf;ZRp_QK zz}J{0+lE!B34t~4Qi0mM{LdIp7)OtM<{vl50C3SKd6gt1-YYZdWnD;pQe$+yc+T?s zkpv8KDSM^b@pv#QFEyLGl@6=)4+goT=~_Y^aL4bt6Z-I@^^* zBvS+9ymB9mNefSnqbb5GUdNGM9-5QO3h4J9hwLy+pOlNXr8GM`i?cLvBd`k zdf7|N)LJFQC@7bJlegGI^s;O|9WRFKJ3?w@Ke8El`j?<2cz~%K!gJG|lo^&?SKnw* zKd;Wo`!_AOgKN>8_=&yaNHX<30%Kj@28%by!p#d{;lkCvo8Q@7Ayj%QiaB?lMEIab{M(0e%|zA5IT%po8GuzN-HM0 ziECS5G{FeFIxYoGOl?gNkNE%dF7LAD-Ycf6<>WCi-!@t?yHB)19y&U9XHxD_&!M#$ zaJ(LGpvA?21!c2MEyRBK0SI*`hu!?==_~+3kFW@L|4~;z?}EmG3@Sep%E$t|-hlDV zGX7-g^`m(&r5(#9EQp+@xrNyP=ur_n-bLqonK|2=x6vHxk$A3eG`gAtxfAc>yuC5B00B<}&M0=Ilpe`=%fd-NE zT3|mM;)(HAR0n^~{LIh`;rx9DhqNM``t$0%e&C#I9tci&d2@c*uNkFQlmgV#3l~4C zWhQhMC_eE*iWum#PJjovDjO0}n{(w6J#a<9scS>aL_>h9IXehTnPtmn0{-erGV-czhOL-bUJ;Ps`*22Au5O#5FGrF? zq14x7jnp36Fm$l3`ER_=-$KvUk8(dO(7>sLs$ndjZ}mSVd$!4_AZXkPt{mVPk|&h& z0k8A=V=(e{uHuLr@~bG$xi_^&kn`38TXEsev0oi9RNvxkv5=Z)Td~NQXyk~;SAs3s zsW>FrG2ed;StIMOpuq{SR8HLLr905nw!P(t&c}5e^q89&)F4CKHT6iH9N<8Gjsz%^ z5{<6=1qq!=qY^l`d?$W4M2TSPGq`e=1dW@gGXH$}Sek9wcf3TSpkf}eteg=u7Gyk9 z6U=uH(HAw4$B{D1lOBUN^!HG#sR(5;=)nb?^7K1YlU>#V5Af!v zu!p5$FGQRJ^sVrGq0kzP=uIjWxJ<}EOgIN1=Qwz< zXgo}s<`#O&l>Aw%2;v4JoCIDNK=6>RA_h? zmk{j9#kLnnpR20_Sz-WVmB2c_L7V9yq)k{APIzFI$ngmAAw-{5zK={3`FU1!uJG~K zLDSIK)B**rAiwuH$hPv6`MW>Oeeq^Kt_cG(Hc~0rk`SSxyeAn5-(@|q^f}C-==cQO zhOiDBOvAyYH+(4N^E#PD%>xFA*66J0hz%Z3W+@#8G?x78;R6u#kBPA@Ul_dQ9-J6E z`1<>kO%~HC4sNLITtxkp5k8&eeo#=bJNmB8;&pW8dK#G2yVTPCf)Fr9mIvRQ ztVLzHIy^WI>Xm*2-+JGVb?EYG-?gd$W3GgjCaZ8YtwMYih^qb`&IG}ElAL&4J3w}T z$c*dOInGgAdXI$^fAv3T24T%{IzUoP{o;FPLI=oenOSD5A+{=$7kA7rpMIKzVSk9{ zk}*Knl|N+O*fjzRD!J9*X;h?d-+DJ&65bYHo`TRXD5~WlL!CBc7QEl~O)ry1`)BjX zjhBGU>q9rLKa=0RQHRfR<|FJ%+4y}cL})DG2`QhAvsl5Jp6^u(j)b8!I8e2zE#wRP<0 z+4XAV?FyK!kp)(0#Bc1NwUm|k-i{Wat(hUI2CRViQkzEh>hz3cZi3u0|@W4|!@ct{&iQ+en3??yzo$=BWd$uKI(#f2`xxW=Q0C5qmR zeo+XD8%9D!fQoVgYk4utu>Mt@R7*~4wb#6$l`VyBE zY)2utgXjf6f8bNZZE5zKxK=q4=olDI7~S*e8L5k-&wpvS>^QHb8!3 zx@t#jc3vk64~F?2_{^hW-{M11HR16xum67R6f?F>jz1~A84-BL(UbmdAVT1+b|l_V z4$83+nb_}Ur;;PUGEJHtU@nfTRe_EzykbUEgjrL74?q9|8^S$gF(VYh^+N2q^XBDh zAY^N=5s$D&!6sCne%Nu@pC5*q#F|}v-BKm|J%Vt5#~|3h0h*8;{-n~X2??J4sn^Jx zaP~BBWba3&%@`V9pkj+WWN{lF+&0J?BX1orxp_y$A-5g6#Tf&O-z|lOoG6}8p7=^D zErn}AUxm9GI|`8h?$N$7EPN>t1AvDyy-;983FHBQxG9q$rk{_q zPSq)&_m8}r3dYT<;W4_ff?kT?+1c3rCq|5&17#RNt>}v)B^3OLUkVoxy_cXP*%PTH z+Tj3HL7wf9yF-u~)uo{K3sDffrr0;??JX{=QiAVZ72rGA;P1U5M;2oRvZ5#^1WvGH*<#^E=f5{k})hqso z@-};amqmn11qLxvK!=!MWBn@;G()i)rj0lF!*sfiQHJ4}^Hn+O>e*85^gTyvh>!o3 zJ2z05MrD&W(v(KopSUDiKil=OH2{b!f$ad|0k|Msw8wCqBNB(KNC8K8+Q3Lijrz`C zMD*LL0MnlTfrp$%R8x8XjT8!3xV4_0Qb%sLZ4vg9-aKF+!b zn(&scJc;eogr1$DXM{WcmKXp}WT<}lTd5Eay-{(=4Of4(FJ404%?D|u=_cq@PyP@f z{C2zGX?wPyQ5rCeZl^R5h4;J*Lf#TM4}EKsfU95aB{MyXnuo~`9R)GX+i(~gGPGZ?^4AxoTM6vfhX2JJ+izFXhrxgRDBB)qjbyi@(&mZ*3q*#*TzkZL+04EYJ*6glLh+xqc= z3ECi!-kfYMBzg5tQ#5UVGK1Y;mRUe=fK7lHt@){ft;W04$V4yU=q^Ru>u`&^ARD1$)WzL$@NaR?bZn4MD<^}pY_6jGgoxj&%wEt8l-74@Sv9Sr7Eg;5 zS}L1~U*nAt`M#LxIvo)+wsJs9mF$y;LFpGHal6~RgKGMmbLbg7M8nqV8_IQp-* zRLx=dun1hUoCo4tvS5=ARAPPZN(bSTz~rA_0*h^{<>G{2Jik6apQaFvNDU2z}&cB0q{N(18B+LX7qw#vMB8d+EBo zOjDaaHG=>5-Pnyve}pK$IN#6=ZD?m%1c%;qZs~Mc@(~^ylZmBQ##Oe|vVk^%v%1 zV37KdE;CqJs>F8UY1E1g8$e|18}5YD`}ssi9X{r-gm7>M8dV%n?-K*GL^0&uE^IwH zIFQth&pH~0p`{yjU*w7Whp}jo|S(~ zcflVs(M5k$Oq>{}0uJy`v~7YahL~4Zr($9lxL;wOiP2UoQ{%~$G>O0GPZMqa@k%E| z`85x%Ssc&{cNa^IDtZ!09z}USZa_*miFV+>;3VDSGz7~KfYTYVILBlXXZpZeN@;8| z#4#20Bb2N7U)qxN1r#6OG7Nrfi#v**1ykHyTl#48v`7{pFp(h{b&u7;nVAHUcEl4| zDoQ7+!G>PrfPClP5d%5IPrBmx^2G{0@pJ~W zMb6~IPvt+D*c?Xz@BuC~Hps~E>Ei&XhrmcpTl(mjni!_1cCd;hs}HSxZi8Hx!^Mv> z(Mqo~+UyS3ya!;Axnlwx1D;)FlnWu524Z-38%#-t$BdL;glMLqUPO+|Te~wNOwEZ*8oK0d_%5wda4gzo#VX?0_n%biqy{Y2 z?jrY4zRYT2qHk^f<@(GIfX}gOQZIkRH;HVp{DLe|imz+ZH4%jcA5dcEca)ykN!%U* z8Z^TzfNyy@Qu!uk3{!uv4(9zebL)8tNca_T`N|LsVirvb4e?9;8NZ=pZ2LY2gX|E# zja$SqYN#=s5InbwAe=*o%L60Bm7#lfaX^+|Ln4?^#m$!xl5JqLb3Y#5JOkKmiW+Tk z4!|h!h8rbbqh|f$h;^+06Xbrvqs7yOzi>IxAp>qH=u)>Njxo510MZhhZ0RfGY-s=$ ze2Z0tPPxs9C;eKk{{!VxZ4YJ0};{q=hdXJjP<2K2_m_#uVxN>2l7gW=F zg8?iqO*@IuG33I2K-si)V?^4^aE9$|W^$*iV7xhAsq96`R>;JaEZ0S!-ZR za{})IsZ@VDpsGRvwu$8Uvw*uHjxVbm_Af$?z~?X5l>Vv|JDft}DE6#GF-7O|6N=vp zxG24dNqKW|4!2|Gq?|U~PQ4rnBqdy{lvq@4I{&ynnrXwvuK1VIh1V)BAojPg3m_pH z(`nI!x3y#?v>c;8ne0~cWi(>$8YELZNDBjC)0(n0fZSxrUzArhUIH;(oi@L5X&`Zc zgHMP&8Jc;f5-ef1NB!~PVb9OpyiRt&hMPG*6sg7J=Hb{yu!*5>Gd-zeqKt-QW*FHV zxCa&kDDk!JkhhTm?{Qra$|vv_F;>B*j3{yN#v#uN(GSMvKfBTiX;SJQVD!?sT-7j* zZHH~ZBj(A0a4O}D;ct|M=O~LElQ)zFj9E6c0-E80>H?*Y((8hj(*zEh8RJyz5z3X1 zz%zQgx9L6wJ@o^-d{00M#a<>__U?dNz7v--^r2{{|X}xUl>zI{^VPd$#E*GKFMV3 z#m`H`!r`u-aZ047kLYZ570pi5q&sH(YPo)FjZ5Ex&I1Iu;Tv2|)BQ$e5bK>#tgEFRrY9fGUmHe9tJfND=>g!9ZIBdX^4i`IIw_QT}4YvS%%Q z+A{tdnELKb!l|cA>VSyzn`2YRB+`ybl7QMakJ*UtN9?l-{dMJaDvHo71hprv&moQa zv6UEHRAu*8!c6}PXCR9d0=fM93yFAq_i=wcfokTIJT6E@JR+<)19s&CT6I~m`B>Gs z0!4j>esnjH271?tr$VV^{*99~7HV%(rSo+e4*4-7owor-}Fr>E%fuNQLcC zlH_Oc{o)^tYjTX!GT!k((!R@k!$%FZRopql{NiuqF^$F?#j!j*7H_pV<^$6f8t`Vf z)PrpFOte)grAy|wo@v1(76Ip`$zocabVeW3q?L!z1wM}egsTqhYWu0aA6~M#dc$9e z7C1d-cYek5HF8WimFrg+c5jk0Ow;A;!|)nos;}~HFo4tIBqkMY7bC(ghH-w$22Pkp z^U`|RLrC{_^xj_TN|WsDBAZ1q-n}eK3H^(9ahfI!Bs6x&&53Vm6aSY5*m=eXo~c_G3E9C(IdF4`<(CJYqfz5^$v23%_WcH*|Kq+?9yDL5<- zht9|+)j$q#IIJc+j6$GX7;bS@B}@6FBDZe2!hHVR&XXslA0>m19YNO+jUu>fisIu6Nqt90Y z=RNtz>tYtsK-c>1c&tfHWBXVr*@En%@UyrJi>h(Y`lLp3sE$tYzV7ms^i zR)I7%EH$*A3M#%QWZM4iVOgf8wf|pjVM5ZgJTD;S*j&E77J4IcEa@7Aiy4fY3l{^U z87TAyeTaC|fL#9l6}aHm!lLszFo<<8QOpIo>xg_eVSxg>)t{>FnW*w!Jgb5X)dM~B zdNHKT;2(Z8SHbvU9i6+TT_5BViKyzb=r~J9`H1JOzhqfGAw8rLGU+gHwZGsfv`- zU(rwxsihzW)Xf8&L8?OYjr=$V==k|xx(B264scr2ERnj{1tPA&a}mTq@hpmuvGMf8 z)_yEU6%HG-pB^NFT;&3NU=Pcjc^ zBoLJcL`@>dC2Eho1fmD*)PB0U)=p`fdfVy*>$TGqbL=$8W;+$dtK*+={mh)3P$_v= zmP6?dE@2eZj#AeSaw4tzVj7P+=uUpqMY0D-qN{Z-uF=1+18rur$zfXal> zd5a2Tdg$StD$_5yNJNPlbmR?oAn_`TfkJq!V6aGES0s~yLD&HTG9@eF}@`)n@yYpnsjU>;Cn)CV6^ zQ9OCRtZ&bU$`Vq6#eD4uPtcB?l8aNO%l$sw~ZnYSF7&;@gh0L2I4V|Z?Il$)cj6@vK%H_7Uk-A_dCb$mK+m8+NGV75J_%g`WC$yJ84+DFrTrCT`JvJpHCdH%2MT;fRecb?TSH!>njiaFF z#vcoSeu1*%7gC>?DR;r0`9VyRJDb!MAmm2^WJM_`Ro+$KYCiMDKB!N{QhGAzx-GJ- zi&>Q*7;BkCT(z!=b|8zD)J9^&zM&x^iV}oolmuObn^!8_duicDr^KM`A@_lC1q@Du zmvlzLCK&ON&RDb%1_@Y9cc2(xb6>uPP` z4{07cN28tIVoZ2&Q+no!bxC-Ttghd$R*UmOg2!!B0IppSeAO^1d;pzPND&T#j-^Jz z#-T1Vf;kRIp6v`5ka#DA(==kT0;uPNJY__&aTJ&1a#z(zhOa~{ljt+m@Et;AT|YAe zio{{x$+`7h^El!V+P!>iAfl#GazeG-@YfFJUPD5Hn@V~xhNfjudH3v*7JRX#Vuth0 z+>5=Cb(4pj4}}0!$x$838>cCDskfU8OH!g2Ue7gzcBQ)(w+&@+G+9%5FkZBt%36{#_*d--e!iNoK`^XGq>G)x@a;O^IEu zb2WWixfE-FUQv0@yd5pr`&0@@C4c-g!{^bIK{)Aw7s3|-rZU+}rOwl&APb)yL*vom z!>~kkPK6|3JBg)-D`en=Su_?>#*Nr;cj}<2%`F2?c92M#Ld5Ax<5LR5*kqk;H1w6O zdmQpUlF7Wk3u(`-v#4U&x)7Isr9`I68cEnn`?@#gh#!c=#_l3oNN)0Gmw8D`$Y0S# zw_#^m^0*|&GSW^lpjW9&nQ7XItKlW_?f#_VoW%3hwpRX8*84)MnYQ*k)(j5e7v=F;5{J4QV#v|8?SEOtcs zB7EHd!r8)X-SVxKW)W?fm$Ham%3v-2!*CMIL0?4KeD$`RpVV#td?Dv&&6`q-yzg1{ zCbL6-=C(dPaY;-gb5QAdJ!kfIWs2ZR`9;hAH{4c%kTw4tv!sKRIJ zZP=5}QI}B%$y}oQ!ztr*Fs{_b&m?kj^)3tNMf0_J^rPV>LouGnL@lU?qS*nVn_`R? zG&Imhcf#+ps;S}A!xKvxK8s}Nv6rXCJnqEGCf`z3XVgo5 zKIS`B6-)PRh|!1los{W)Te|P_Hls_GU}4IP6k5ng45g+f5;x$3Rt$xRKPKIa?QS3x ze@DLef{~&eSlw)67RPrEn~b+=xDDpj>2ZAVE_rn%?O3iRUejJzS7KAt>##3EP&P_~ z+XNb(X^Lc>3q_}u84!4P1K=*Y9U!q8Dzw{0JY&KW(s4A?>3i5fVN$o5>oIBkSB*Ky=0eV@djh`GGlzfaBiZwRiXcByB);5Ce7UGooo z6h$a6jH@=rLtP~1@Tmbb)|0w`ix->BP+knqwQ;HVak4v&_N3sz0Qt@ygTQAqk9OWO z_m+bx#2)x22^IMNAgV_DPtajeF}YhxRcv6ep(mb#A1A*s9O-HvVLL1LZf7`M$1lS} zX61>==()xFX-^{}XTd>*Jf3F5X&Ox$hb@CLEZK+3x$?A!VN|FF$n2nol+1&%veP&9 z&VPVk*|V%TSTlb zHx9)Oy5fQJ-v3Y2e(gMq{ykL!JXM0?a$5*|s@Fj{`AWwPS$9u%LQuq%KRK)Msjv?6 zUwiygj=xOtkbNt$HGUJSfJ0%xz8sy(@xl5B)g!^E91H7L`Zz@s7al<*&)gC-f(GNlvd5yzDWmQ{Km82~&IeTcI9Exq zKahocS7hZQBs1*Gt%mQ;`L&GyupIj`U6!gWR1x_)W>#oU^)dXxVN-Ce+N}F&a@YNT z&*wBW>PE|hgg>x)4eG|y#i$RG0}Htiq@{8J({r$DrHVzmX1*U3Gcp(}eDI!Ou$I?k z`%h;MMAJ$V7ESYwr(CRWbHM{@{(k(39zhIudRz-7NI;dsw&wGSb))1S;967svA{JW z#UrE{jS6Pv5FoBX|6v`vr1rSplE;@iud-4^tP;FEe8*(ihbMxGJ0%K093lDiE+ z9GUR+{b}@G0^ClEXh?@M^25`{A&Aqc8(n~4g)&W5MHH#UnbaQeGooERTX(A9Q`KU0 z58HCqGVQa(6{5LlpwJqUPpISE>_rFs!CT!hL1~`sra0YiDD` ztG|c4ag%z;{b`ngR)}J#iy+1_Z4lL$4GjK+H*ezTBPm)`uBc0a2CVN7z*K3-+=>r( zuWlHzvN4$8y9?Z2JrgvL{N~v|x^(Lqd+}R*!i+XJsA{Bg*+`r5{igG+Ze<=u_B z-ExfpVWsI0ce*|gB;4y2ntaJ4Z5Cr5R*OUhHm`Iwf0ww-x4KU-qv|xnk5L$M(r8re z3wtwy<4oF<-D$8NjpLX`IZ(L-!k4-oIXt-Ow+B97PZn%p+K3P#A#zQ=zA=LCglJR6 zTA;|S>$#8_4dC4y;Prntvm$UUG~yAK{X@S4eue*l_P=ykv`0E5(^Z>DCL_(u;dp@H zBAIe8vv~JD*Sjs^b#QtvDS2+neT;a(x#w-Qft}bP)!cVNK!k_F!~5bA2rbuSot|2# zT}~WVV@!D32Y}q_kr_HPcg%$sjk6&?`%I)+G$%TEV_MeL(MYZSQwidbP`F0 z^uGvpafZbqC8Q3_LqGb=ZlpQ6PTC6?8DaXY$#nSV7IdYC<>`qhPbRad5o*fSG%nb)1b)OguI%neNjHrC%MYe%wmEk|_C6|wWKN(T z0j}R*$Ix5CT~egSmupXPPyUNlB($b-mM(xJBc|51_HJhArXBbVK`yq8=NiZ&mBH$D z68?3uN`Bk$Ro9E~jyY|Dtj!ogin7*)cI?5zlu^~%WF%mu<@Lwe2fMizD;DbVBhG&7u1b-2p*fOyBO2 zOw4#Igd>n6^~Bfo-9)?@(M(Xq2M$BR6H4LF);v!Pcc?6!U_o?e1}^O$z_p!mJ;^eAB(ge;oZ*Nim$SR9Fq@NAE4>KmQnPrT7*E z)3IH2wnP4DikSCB-n%;>SAS#x*FQu6|5>*K*}?nYtEtn&`?u=`=XV=nvC zponkcD{|Ka8tT0N#u&v)5DA*rD%%gBe7=)jc6i~pNcg+p)1Q!6Y?7aFFOVm3ES5KBUxQ~a&Js(?MtM!c0d5%6U)9I?W zqxlpnuQkgPb6PgHw(a&LNs6@5=H&e1FX?oVQ~~RrFjz*J;DX?3|I{e@^XW-ZJkY>! zL78Nz7>0>W?p0$!QK~S>etE$F{ZK^k7%ZnC%oEH%A>)y86+OR$`ICVw$! zN7g$KA9JC@$luw{XJP+nl~?b9WxIR_m?CfC+u2Htzc#*Lc~O#7S9})Ze*VRz-`n3+ zF@fh6D7Mgw<)_zM2?vM9!e8Yf##0n#R8rJ4~m zD)W%p8Q}18qyNhCf4*5+*?@#y?{EA% zdUy4$t2?r8;jaj$_tF{J8*GaE!u~)rGNeXeWHmJ;1qe};M7_-XikRkoG&9%z-qiV2 z=&Mg+C8gi1SkB6)3|&MTtu41UrksXcQTVEkX~qAfsfo-6dh> z(9?aF1Rav(G=$QLdVXnY_b$*4cj=2vlAN||j3-b|6JSGY*Xyj!p;4jx9u_}_2BqAp zGXLV~H@w^n_~iP690NWWMWex!2mMu2c*sMd7Qx+3UQ5cyGeBv5T7CY9nF2&q2^R$H zQ)-zHO+e0co?yBlzFK?7@_ocMEo2qETSWS!8NU|kd%yO9gpPBP6#|W`IS77r7Uk)9 zSDktVL&^=h zVlovEyQ!HI<+MNV9sLtjbP)Am5BX(5Eh5{~>aO^fLq145oK6jGfvPbqQ{DunSL=fg zFo(P1&YRX&>7)@G(7%?{ZbSwMOZx>YCwbg%?1fj_9WU_~|H&`6i-**>23|TL+nQIMpLn* zPUv<-70joKORSHE-kOGc-6mB;vEORDS|rsAptZLid$GFFO6cART-C%+a6oM!!k4th zsM%xm`Tf%q12FYYQM9fjg?wbhjj4tWUy0vVJTI#+PGa+LfJHMXSId!4iC(Bi-iB{v zXCsLOA5rU;ZrX+h)EaIo89eZ0i>WQ8T+kgooLL{`VJkl5QFT-1S0`^un)x+AQDHLT z(ezd%aohfNV)1a{02%m+B&j2JSfkRlfn!S-o%g^Gh~;%%ZiQt{q3@1YZdk$TXolNb|dTw#mJ@LoAsIYftS zEF&Q~`@I~EL~<39l?$)1laGqA|7q%!5yX$MkxYjPdd3-XOt@k<;ra~L^G?-T*&rpR zPk69AY9Qy8FVv5=#invdJS{Ds*CfsWwdB-Tu!v50#}hn85y>wvR6|BRBEXaVyJg8^ z;*>t<)_bd3#>|>e#b(cd@Rb9p-0q*G^%l4@KITlrh{CNg-Jj;RG&{9 zso@h(*f@|m%wIOJ=Lbh!8~te2+J7?oO50`Zz(w8qK0z*UJJo@M`AbAxabF4I;E7tO z0c&a$HDciT=H2M@F)89Z($m5yJ)4Svm{S;EV;`LZ3}2~?28!TQMdf1%)kM&Yw?7%F zB7)HzY(+N-Kz2O#Yuk-TUrigRA>2k@L5UOvf5sQe8UqXofCwxpL53uS=YR&naEj^2jG zA(ht{o+_n4dHk$klphPBp>mK)F`KXrpNH;aKxP=QVD%Fkk-dQF_2 zraJuO7^S1le8BJ)*o3I+=Fkgq(866VA)J-a5s1 zYi*}pc;ZFowV|~{DmR9r0ep~VitmR^hewATL{w^l6>qtc z(v^O1&B`#c%_A5|Ey8!blo#~hg2)|(;oh8erV+si6g?K%sLkNj5 z1$Pf}n*W99Gi)SNI#ITw@f`bu$!MOsVZbHwoMG!e*+mR^Y6{5I#J}JzWq^E~3ZxWO z3{_@ru@zhvW__8%6fQ(~O)<^hpA3k<728L%76K^&X=fVhc2H+g4gn-;lA00D3n7B? zp=i--FZ&%(izJ_HO;eg6SC|>2OnO$G&3I?Cbp4k*IoTUk?8CxS@Eo#=p@dZ7F%Gz> z;{v0Iv#_HGnkW-c(Th408#>q{GN=}W@urcdlWI&<+JGotN7yUL^s4HFZF-&hKCV;& z$-#~A^u5f!Jt4AHHjL&I<^~Vc%-1i4pV_iS>8^I6YHnvK^ z-5?T}2wyuXUQHWLkl}S&1Az3|Ii8?@c)y${6K4aPAmoVB7mL{`G4%ZTD{EmiT}!OT zXXN7+E(``H4}MVGLm2e)(p@f{GJ3wntvbG62wS6l5jOBawy~JO`u3mEZFl784@gmK z?z&}NiwK_>rikL@#4R=yzti%6Spe#6RLqy)&;43ztmxuCI9Gc- zMNQo6HBSf^0XxOiDaA-H-@?PI`dEyTz=L4Zw~Wc2SntUxq-9*r@dIzFtk*W`3qD?1 z?Y!Ld#yiChPD3jLoNjoSMxI=1LlG}jludo$EHYF$99|QsdBLx}lB!NRTTevE&IEr< z(R=D2WTq-XJh zJgL#J+rLDs6c2;{(pm@qA-li*OJ23`Z)Y*=mY;>Pf1jaCcbfck_Oi0Y&b2oyek}Cr z>+Jn4!Cl<5t3MAuDc2k&q@zYgo#Rvh zYWs1<$H-w-d;Te3N8J}!QT5wa_P?*p0x5vVm4 zH&r!ro0lUOC#|AU6#)Ikk5-Gny*5W4TfW-ZOj)AHN}W)B#j{Zt{vTegK*Z{IY0G&H z0L7g4o8>3=-qIx04nYxr0e>h>qq6svI)+tC&20zvYvRH0m}@QG;NPegVvh@zY2;J~ zN#r70;ubx|I#2eQ67XL~hF2@fg$%C4-mo(;$DQ&FNBrZ{p>BFCUbcC)Pk!3|JYneS z6cVO=YV!|xoFy!zL^lMt;VzPW8iIyHp>%=`hHe^_&P`6F;mgQ*Kh!#;=c=8 z{{4mGlwM}GAJ(Ezl-`KG!Y5wmm%A;uj^#f~OdGXbgBWsi7iz*CKxdBCln$;HTMa{* zPGGOoUy!P(rN?I7pR?EDK1Wvek=aCXS7D&?3AvtZbOdY6g-ApSg}Y$?2>#z3Z@+Uh zQu>WCa6tm%$*WV2zp;!X)cX~8WdiF)&I)ieTP}H=&rI*89P%nfa0SJg*T+56wc3&0rtdY1~&HZ@3#c* zP6HBT_WKARo+9<_s$gA4lJE-SU_wYi>~DamfXny%TVhm7j2%OVUrj>;&*NkuoD+F0 zEP-XxC;CUGM5w$Tj&D`z(XxC3qkM)}W}VF*7qRigcBkIuDnBL|sR#nZKT|A>2mZUU zEW{=Nf7l5gJg){a(ygClQdFJbGm@q4W4H-@C$4d+Pl}^xam8n)rja_V!}<8_H~lHC zwi;eoj|i{lWDuStn$fd9YeZ}D^Zg9P9A|ft7p;&%Q_9!Um4P7-)Z0CdYsc%$-*S(* zOYw!?)UBq5wK#7}{dDI0n4HM%IvpJ(AJA=8`F!d zF5jY?CxGei6o4qP?m%bf$NnGLYOTCXL*_4s4QzIMp40Qp=th2CJXqe=S-o`mCDS0G z{-oEeL-)$HaEGY@-BA6NQrx!V3dH_MrLlC(FFxJ8MvgrMlY+I&xfqf>pfL^u}Omg_y ztaTV~2ErB`;BXWe_v@9!>2~~fz+h@`^OubB|FbB)J!R}Q-ro|+a=@>P7889IZz*+;_m!AMNZh*p>c&ik~IG+Rd z_~kXMzQEBmYFJOT(Z2Hq07;N2%S~+r#I`MK*L`TaI3)dR?>hO+p`*5)2u^p9Z&=vq z!<|^OYj<8k!9wI-cf~IxIXiU@g3ShofWQ(+!3TWt`YPQN=vz8dUdAkt`x z_;}z`r~3W-$Ib@xj&4;l-p;o+3n46mIL1ECGJnv3JU2AADXh|sh66w&kL>~IYGIar zepD(T2|%2JzM7L25a4))NP#$ozq+k|ur&&JNtVT-<%`z<`8^e&8FpL|6;O)zA?jC?ar?ac9ARyuJ`|zzC8g zny%iIl-@K8Tg8ACN9MnET7A!rUrR$?PnkHDYnH&h2zP$PI5(ji{69{TCE%*c9; zB{802O&-FYHU{)VD+4N&(1HR{Qu?NRWcOe|4-gCX`!6#sEB)_E3H|4^M13eIUXY&L zB1I3&TN%W=WJ=l!!^k7oUvUei)QrI~VvOicW-atS6Z;ElWXzW8@$>J#qEv4pe75gbC?wB*H*GzuoqPO=9DS>HEQ0m8r)h54NDpCY zv&r%wXz7u-NFtS49J7-bI5G!%u|>_B!Yf?6JO&}bh2BWaxV}c@A>|J0q2ImXbcjHH zWKL*ML<0z^q8Q*0bSwkX0q75|ih-2p3)cY^Re4HVf!k4o3kmuZ(TA((A~J*q<@1yH}4Pni#!aKYqk43h$m0hCF@q1Aq(I+uxBZ z5S532N;P?&QhsR8O@D|1wd;V2%BX0E2OUsTariGy2gLaEi!4p}J9$FikN^hA1JP~Z zIPOw%5`-RQL`N5!2pEqvDR@a?GLU{H2v3AP6mXMeD!y-?3D)CVQi~~@fPnol-rj#3 zs$V^~;dTh$*v4PVHjG!ID;#k~qMd)|+bQNg!KW=B8Pad@&vG~{`U(9m9DLUDJ?!{l zpWcW44&!(^Jnr1Zww&(c<-t1)*Xdiks^!vFLM~=vQN@g4V1oa*iGgj(HI2jd6yk)s z%Oht5D8gJ#M51?Z2tNQY_fytkAMF^RZSijRC#B9w91_Nh ziEp#b0+lv-zK5YG2Jn3w>|uK3H@3qw9QbTap3N4_j%PnF1YG#L?dpY4$eF0JVXr%ciDOHm#$q>Sjs=GKhQaO?fnnOW6B`3iD-vJ3P3@k0AmZrDH8^0)5Qm*aLop5_@vSP|)@i4kNnK zX9WI>uy(?@T5h+)`)y)vT#DTczv2xM0^oSdaB=31527Y>dsm9HD4m!1Jw@PJZin|j zkL8Jd6Z493X!kIhwqUollzk7ZZEF1a7VG^0g&@KvO+mvskSb0NPzmd4P-I312pNeu z>R3nu;aJ6YBm_i2h(29c63>$_B0EOu+HpM2KWMr$8zCG?l0B7-H`x`+N_? z9mW(4sTkI^b4=giSB*eOKVb4NhuiaC%8(BLP_#UF8l|3%8QkNuomG6o`EQqaA_vC- z4JOgRdt_4ckl0xQfC@!`Kp{U}2bKJYN(UWEI#eJLMb}Y|0ZcPM@v=$8uZPN{_Hh7= z=+iqr%nJ*{lfLLwD_DaL=$s7b-@j-G)UPhsFA9Wo6#D&l{LO(F0(av0ZiBf)e8?yZ zS&J4BNkRU~pl;@bIH-!F_+;F?MA-&NE|cMi5qV7vRPypQD#-Z}%c*BQ|A6bKz2cSv+& z8-br`;nHP|cr;3AvMe7J)WI5*p6enpBE;l+7_|=)0LDWnpp(G70t7k<#?7J^943*1 zXkCb<4JnzLvhIIeKQTVNDM-;3jsAq4nPLBpZiUNTS=r#BN{d7kqdI*7j zye9)H*G4_afPUdWEP#DiXF#*x1@er*KN%ApDPO`2%m7fIf#SCehytjjZ7~Pse+B7b z?OVth?AC13#N55}V2&YK_D*xx8w_pkR8U)Bl2E+;?sS(orK>bv}(0s0y?_guSl*%BFhkzc+ zF9VQcVonpvMnzdfk_2Cd)O87DkqSYLikT=ejmk%e?Eq8!(;u!2)wG5~Zwn>RYYayv z2Bg8yTPzM%Fd%S6{7C~K41vG-@pK0CKmRRz0(I$teo-J)Rsek`fae#`^xTTSGca(a zpyGif?V0k3kN^Xf3RJIiN;fPvB8`?oK#6L+1Z|UqJ($-;R`kr!tx$UKYks;!d?(ff zqUVR(?XY7^wxQDSgh|)DJE{9@(t$49AKPW;+x(&OjE^4;k1FTY(T4|-qTDg}Y}!dJ zKPUbJ)(Pn?-h&4Mh+w0M3}V}r{p%+qi@cOvH6P}fa+P672m@w0yqXn1kdlgX11FGh z2tWsXjPRcb-5trO#yTR1c{Pkr*lfY2Md!hkps z{$vL9@4x-`fBG_@0)nI<28!p~8CW`F$dV@h%;FSzPr!8<$hd|19KfCxRdVqTs>BEK zL_lH#V5EiDVIekW7)zln4SM*aO-??eEv|RZVBve#1vDqvMUK+3Y^UM`#P992*0%Lc zv}xBijd7#T#o9Y(P-&gAO-rXiXEjv@>gmy&{7yV=?y{qs1APy7A*Nl|^~c+Xp}kWY zEn*D>2d9zGF*Zspv+3z%G*O`+CFjM#8hzcwyuiHD#mqqID@Lk0R+||akZ6CtZc+l>P)4Ae5(A;;tZcBRtQe+>pkOCLupr7rF$MUbmovnwC)}&xb`=dW z$W#TM%vq_h3P&yNN+CzOYx2m7mHijhpW9)f0Ez(*w%~w$+ueq=sk~`NgON6YZp1^h zRm(=d_ybe%X#8xctzf6C8kogr*I>16&uBV3@(QWpN!_eY1`GA<26jW+>h--I*uStp zbyfvHKA>eWrfo~=^(9#8ts;C(8?e?$g{U!whXJl?q{0$T*%f61e-G6?9x8<*%Hyju zAWqK9X8cfdX7mc5MgS;}oU&P?ni2fGRw>B}(W^{>S{TsuN9I8%GawCs4l*D{qFY3s z5haTi*kcgb5Lg4=h%S4X$Uv8Yo||{T36U|SC?zO}xRX3(U3atjVw2yc8G{eI_V{|D zmvT_W2s{i06%CBm~& z*WL_=w==OJ)>PU|tJTrTdvq7I4g`{uRKf|Y!-~L^Sq(1tHO!%fyYi4TepQ+BpBsPB zIrtnPQ{p-d?>k};<9h|G_s)B%A#Eb_v#BhkUMl`{AEyX#Mo<>M*g&|6SO z|4=f7m8@W82K3|otzh3F1JYp!S`~V3XTz8>-BT$tjGmZ73TDXv4#_sLfSgK!D*FI( zfkjcGvT{c(phl%0;_T%CW-1I2`BO+U=h}WL*_FOl*vi2$E}K%OG!)`uzQDhYoQIz( z_(9ld0id$7b=zAAqviajfdj(KziJS~^5{y3px6Bn=ye^B zSiaRnF%^7LAVz$;!$g%GH(2%P0Vw24i z1JVP5u`D5X=};v@qgW3in*rA`YejxQ%QPS@?b>*%CH=sddyFRo6}7a1-Tn0E-5->b z^)+Q=m99WP5(ARV=ck6G^xd`LF&gYU$$dxw;|Fn`-ywEu1Fp-E7i{ik#=1x#z?Gel z&4e=J(zu*Oy(m*vW;|3$uaL~xnHlYouABN6tL=*HIE4-mQ@f1v{eHNtn{I1^W2Rt7 zaUR}okrrw2Q$wGvjzCnstd~_~x^hq>&Q2XQ$AdQU>{&d7l;$ICG%JVMYVMJpzq2g%UKHR1sn4-2 zDj0ZRvSe7J4dNz22t$bj=9ee!V}m(12zr8g;B5uR*2eXlPw$Fay$X#W{9e!>3I+og zMB+af4pz2;VJ=pnKtGa#AquLJBTGh!zML2Jz#(B6CN>zAbj-UVOCbP|xHJ2`vmAnrV;FZ1i5bGquvyQH z_%poK8PH5Be`aL>+V;`?G-*jRoyN4rf23G&b8jIg-hN&N^y~=Ps@3dO-b#ITBNf~o z!qt%=#EPYcbA5)}xj?AP8JnVQhv2Yi*(zR0%hpf|Ali*AmCwz`8bg?zZ@ykYK;`zD>j1B1l|!x+of&VhudlIq*qhXNV!Sa3fznUu8{_)v z+qbBHhE&iTivfR#0%1OSuFC^Vs8XA!pAP6dw!_PK4CXyUu0`rVRrHh)NTLu@KCGA$ zl35Ts0kN3>Qe{xClx<@1nWB6fYu|%Rqdri?9c^4bWdTG5om~>T@K*Sfou9`Tr#u~U zJaxkikys&-r>1(A6lkdMM`u9o?mNT2Iue{rr5UxFYW!zgg9P?jP4G=Z7{Am3 zFo(CPMy-?@=nMo%!WS6C;BSd@(tSFc6|sGw#D%R4fAKt#b z`(yRT+nYNfZs}GqjE(>CN4AF@s0;S*e>aF=0)SL;)bDP)CP&<5#1|f6{^1N=PG})dH6r9HLLm-rdlK1hFN&8|K(rTRh8QF&se0selDh!uT?WI7t@S=IGEohTER z5T}V=eAZYDi5BhpsD3$>s=Tqxfk+K>z6~Ev9s4!+$%jQCdNT(9prs60!4y$3jPAlr zUnG1TSw&WUwD*quA}v0#Awh!XYjUL)lM;$BXyKFNe%0+U*C^;{BdVxaFRCl#mNA9B z4nVh*8O9H29s7fV!G8RyUKX{H0m*;-6GXMDG9$U3)=*}GI`fs*S< zT+#t)jy}WNR`|Kq_>YD>vnGH3?GfnHsLYUlC`kWr3NF+LK;0mt`xtk!iO+;U&A@q( z>vZ;>-ghMrsxz=3vZ+;^AK4;S2(tI>(SvJNOipPM?>Ja(m|KOfkfsAtJ|~dObCq-1 zD9CjM8DRaA_u@J*j9@;HwIF4ZbYwtYYq?zU!)1J_*sIc(M0y3`@(zS7^YP;V5;TIM z8g$fHLsdL}`lC??1nfs55h|O%lQP%s%@0pgV;uw~4`uR|^pbEepSMIzbhjwvI_HoV zH8mE-Two6dR0J|%m|a%66@>=C$VFWbc~A4W$W7JaaiKhYNU7Y>W@YZvWp`HqR0>Tx z3_r2dEU0DthCP7*d74aL6{%%lIiOc^FBu0UEa#XY!09lhCwN;!juo+){2?-~5}GPZ@b=}@Ixyf+nUMWDhfcBl@bOMdZwWQ~fLMhQU52;=9uW-9|@ zj6fl4$0^Umn(tVLj(Lz#J2sgm$!DDiW9!FXl3W$7-!muo=5hPK15C~~+~y(?Bc%U|>m_hEB?I&>p}lR{S)wAGtd9!k=RKj%(I0qCTX5Xkb51jW>L8;qL|Lw73AB2Y>3a zUB!!hbt)NR<!t{Y0{6a@a2roviJ%UIAWOt;FF0ujiwkW5AYM_vl^e z?#!#I`Rm!|cjGw<4GN*p(QI8E^5gv`a0!4`g$q>)fNqYJzE+i(u$mGm9!?)d3)KG| z89)SH(~x0tM4C@qFL`eX2Gm(iXkt-#eWvsy^YuJa>;g^HNOw%kFqBY48MBGVi(2p{ z>QEms0zeWFOwRaGLC4260}uvp0rbS^%8i*Y zFd^mEBY9Afsc?-B2AJbyfc0@$r(7!iss2v*P0nTM?*;b6eRE)7aH(|m8Ft_g8r`cN zKS~U1$NQb=ztD;OqFZK9+=-eb_V=yoLt>XVM~ZxcfN1V%2c?Pslph1gFsdxomho?L#^1Gg*cDBHrfl`6SIK}Mq)+D+yFj> z*hT8+W}m}ZHRPhoeU>LC-B6RSGCOaG?%b3-e`>Bju@YLoH2zZuAk1#@nETVfsH?4B&_|Mco9Leek6e`Nef)cv3 zPU4O7PzRImgJEOIIgC{>{>L4svSWkm{7+uN!e^#V#H zf=%p+Kk-M70~ve>eYU8ciyQs9`0m^uU_Bc3nNi4v9`LTwpA)67xGjcY%F3Rq+jGM* z?0nWt8uv$`L-=z#0>#Z*pc~{s>@r?WEYNLoFVYQ^;&-=Yoz?WA5|cF!C>?<0`d3b7 zHs$n~DiV`(SV7`^>5{C4ua|;-fDgV|o>6zCzg7pCKgffqQsMOZu z@zrKy_!(s!WX{9j!TiN5{(A{uL-!@QQ;#A>(JTjfddlaTF!VrnLfwGI3B#oKpwC7v z>Ca#n6i7M#Ky|l0rZ5CioWO_bvc#?F;AiCHGpkzKhb_t<3U$97HhDZ3!4{mB7~`0a z_4d)p&rPvbYbuC_!1qcjpD$4T+#i2RTIf?PZVfURq6e`@T_dzw-E<{Ss-+RotnZ)2 zgP~Oh+m<0{R(wuYIsi{0u4%?)&;-Gbt%(p7T8c%>7cGdl-xc|4iYy;gu$5AZVuiAK z7R=WHun}b`JA1ogJr7kGEqflZX33Lr>BN8{j^vVgjf$vtO&BclW&n@|Dvrx#kLF1! z^%6TaPc#aowEFgh5*WhFm%hgFP-W9-TqY}#?L|!cZ9VJ@s83U-jb^>GO6IZbvtBm@ za1-?*W0$lYuPBF@418ZT8^FFm{E1mJ^~{l%>Qr-wu@qTHpy@qK{%ugV;@m^nldFCjvbrYm%35V-E!yP{y*j?;BpF_onn_Q-!8%MgoMkA#L2l60%rtR89FkY=oR z3i*n^3Ti3X&F4miElIbZl|GTm7O*eV@(ux-aYNWgjS4kpRh{;6eOB80HuZNCxtvNx zT0?TT1_q?LobQVhmK9hZqh~d6DgcPxVTX+dj?&sI&Kd*;yYLmVbqg{8kPlAMb}hJG zne2Bqm5mOHK+Ft7?6b^G^W2#&k8E*DZpsF#d9Vn@oWf?Wju+=-LA21L5EA7B0D9(u zN#&2%WZsezm+sKqLJkE0DIY`W-n@^u2dxj~q&}QX^-xMxMTkK2!+{nhkHgtnvOnvR z0<)hRNAsAIrW(vfLqXW>I-vM8b?pNOWK@H?`oy>QkH$D;f2%-GS;MbsgBml}wq{y- z9N+QgeB>nnnpJf|aZ9Yd7geQ87 z>o4v3bMUg0JNX{6gt?kXG#Fe(WA7Nvk}M49kz+O!AxH3*k!nu1mL$l_nu&d=X z;Vv4HY|04?N27c{EV2_E)=nb!3{`MxPiI4n$6(%b%WgmC%s*ddKp13=SX1-CT}@Z5 znO0Ag33`Tj-p3l%>=G3BfS;qn!7Ar{K;blHhn{kBfw~e%I{wtOZjbKoSr}av1sci$ z3#7es{1w7_ywCMCuQ>I5D$nZsemf=5GB5hlUeAi5z{vMdK^T$75zw-Xf#5LDp`T%$ z0Xf!Uvsr8wsqY#YBnwfGtH?W6wav~wtQd+^2~yJbNKJZ1UWF=z%Wel;nYeHw6Bt4& zjdt=r{Vxqt7q3=3xs-~X;~z|2!I>T{8O{Xv_){9 zhCB~9t(s!d&V@kDk!}YtNC~s;$+lZbkbZ8D&VgoC62vaDT|W0i_ELdA0xuASShHbq zJu*nN*rKl9X(5+I#Y9XtBtR(5SGfS57|G27!q5B1UnOP;;U1y3U2!J-{>C&g?G6vLD=%5;0!-?@eT z9IOqoWxwZbp`4iNz;nYHY@`cNn>^7T$XPzruyg)@rbv!MKos8-eyV$Ib$z^mcz#X`xU2wO=VqWFCRTtNtXzwMFi^2 z5ov(>G7oM0EOV-SPI2$#hdtuvt5DXXcE%wHVi)wAMjrH-O6W!kG}M0&n>FQNreBs$ zJ&yOW1rV~+{Se#LKf97IUhx71e=O3?Dqn2!+z0~BnD?a{czC5ZQ1O8fd6b&zUN`La;i3y8eDZNDhc)rDup85^h2Se5hy-uP)B^2 z2u)9_L3sEo75;Q(pT4P794VW`RJexh|7J<-aR6vp!JnEK#yZUUlBj!aQuHd9#>F(R z{-h}TV|TbLmRuDTSot8UfT`c|?bL@v)G~M18Y>fXDZeBvMMnV2P?)`zvIC!8DTif` zbH#&gi+y@LeiC7A4_Sd!F8cEZ-8~6K{Lciue%t^oTPZvevm4 za4{PmEb-M(3EgarzL^$v21`)_`a)c++Q(I^>F1C9S!2o$1L7%CSEt2o+IZEgf_qj% z@1!YmC7l-QMCdbDGtw%umMIVo-r=lV9;(13vc3({r$;^h==FjXR{_2 zq^X58YTmu?XON>fW@V68ROawJrl_dRK8J!d6vBb(X`7rErQZ#t^%?}64&Rhyhz;jN za+K6{RT9)xv_1ckx}Jc8!~%`>*wVA0$BC=!l;zee3!HqQ&!$>|z{7;U5?neP9?5`i z*^a4Yc|NFnJ~8|`xgXjPAu_xgo*|PIz74dJphPpi>pf1 z{Irw>QP;+mdfjQP82?%AU^7{Qmvje>1W0odiuH-m4>&@k$dX#3 zZFUc*CNjp4M2m~E6#eExEXyYAglBk!2v$_MKmv4&E6U$z?V4xFf#d!N6c_pW8kgUj zN`{EnbrQ5H)jXY6YNFng674^qW}~9|IYy4Gym>TO)$?go^KKXaG-WTF7IE=hwd8RK zkOn_P6`R~4)B14?q=GfBdRWV~9aJE1|L-}dDhSEr-1=c$_?=g^+&A|Sa~$` za>i~^{Sb{QmGHc&7SXG!f~IU2lPaMpyHIP(^!+Dv{IKxz*;)_B=oSj8=TR)e@)T2g z#Q3}Awv0dR3`mC`eZaS;RHT{5)ng#Cg^l!-VezmmW99k6s+gC2`2<;z&%a?qp^VZG z3M`RCNm<9;E2(@|HAtmzp`ty$UCMfGmpyyzUB_9o;(4D_2181su`HRfhrQ5es7YP3 z{;Hp52852Jqzx+IXV&IzcxsNP&86a%oxQt6cnO83M~n5KX%p_lzuQx^VivtoR@})6YqO z^!)MrLy;LZc3O?q&||{-c!V4SD#dzsfLtwW8G&Yn24Q&H#)b5ePhpN^o{yJJ>uKWx z3sh*o^EG8qVYcRA4kx$#4oxpAh7<_-2q6?)KZg>n?oLbZz7qhHWr8GWb-LE%RHz@e z7y77kRq*3m@sd5Nj+n-p6@Z1_YAK6ho0xSw8|oQW>zbk}Z9VJ))Y};kmwrcM{8Cub z;H5K1=<7mCTj>Iu_RU&6caesD#R+a`K8eGR(A2n>>4$DOXV*=EKhLIH&Z@ROKIQQe z^$1g5J=G%mpaR%AU~N?bBH1&?1JLnUtq+zyC{&_AGhKnnxjQM51Lu_Cw4S#zC}~*o z5js`{9y|MyKkG4ZoDPw1lL*Q`tUI^xd7mAH33 zKXGf>@`e-UE7MRcq-H{;VX~nm(JxaX#9Q#IS$HA{-aKLI~Q@gDP$|N8EO{ zCEh32R1^guwfNifwVPh_=QJcz@^LvbY}&2^x)&s2U?YeeL z;x&>xa3T#Eg!-Q6GeFCw*n{*HDgvp{eQ&?A{I-ZryMYj4;48zCfS7Vlj4Q5D;Uewv z3nWoAsV@m4S07k*V<=}$F9v5grx zj??~tHl?9LL(f9ML|hI7Pc@Z9RYb#-9+2>iBMNeBG_p4P)!PN1)=DE1F+>tN)7;rY zMB(bF4YYaChOwYmZ3zJG4LO=i@=8*c^SDJ-)1FjUfKCQ_3TPs5|~>ei*Og476j zabSTjWemarj;57ceMNyqhDQ5A5K_VPD*Y`+U6k~_5Q*V;#Bh{C(91e%vfGz@t*^9n zVdXFhtqf^D{J|<|4qU`Dsb$`7QTpty!5lW|`iDxpKVyU$wwk(zg@hz!$ z>;xQ&$?!|+&}or2qi;?QsR+UW?Buxv(UZ%e!W}6pApfVB4Y`WPdjWm0e$VPfHX0lN zwsex5_*Hy$8IP>dL}7yEEUeZrdb^18)PAX_K3eE?)y|b~mv~MIfqJ<3sBh5Id`P66 za@H=(F&4|tzFwB(u9~h!*Yva#AnJVt{aIOU#A!H&CHQF)z?Q?)3_j&p_wITO(hEg= z$Z%)`JsVD+;ik>$@>y@EH`|+1s0u%SCcY+qrZ=zO z{_y6>|M&6#`9D5B6)$b!RoEltIT@;)+0Q^3Uh_w+0HN$;WazZP{d-nJDm;2c@+ob% z!;@OPk_>bufX&%T9Zg%Xa~XKZ9`pAZS5X+|8)&IZ4#pqNfmuxpHW| z_C#lcz?G2}sgWAuh52HE>+b+-O%FZ}=BD}c`#q3#nWZGISlfqXp9cDev(N4qsWG1$ z^R8@ba|7=|iqm@0^--)0J0F;@p1-oDnBrClD?)fldo{YFIYI|Ph{JAzh4}PZ1zP~z zID4l+B4_I4E0s|fcd`&yC-)BLJzpEfwbAcv3@KA>HVXsOAV3T<)YnZQ_na9*MU^7| z9K0a@nD1Y_g29{MyCIYTce8YWnVuqg&=%Go34SOEBQqEX3=+4>=)5iIF>SG*#;Nx0 zFbrQp3mf+Argx-6pWdww?s&CXEKuT{7rR>QH->paGn_@bzuVvCc*cD$YlQ>YB(xCn zFQ!Qzk{f;;FBUxp9L^>vk50cRy`ZdP<25Dz8jlma*^%k3-(9EE)nXA3SUPPe% zN-SG2_FOfOX<);INaq9dEG;Ni#CTP&ilJ)9a|y)p*z}+Tm=}5EAw=fMO!g?Mamp& z>8F74xPnBuxkDHNX>s%Ew1{LZ`8U57FJbDqcm<-?jh43C$@lqYf#{LV=W`0V8$ez; zPfU>j1*WcTj)j}n@TFI;K7hD2NFteSuDJ4u`lom!^j^Znzj*P%47J+`)508&qaIo5 zWV|wm)BS{5KBJLd=9aIUo_S#_>GfV?Ld$3KjzZm zggP+T=5uCDkYz_p-6P(ooX-ZGcar?pl+>_i2GucEYKQ9Wlw1SGS>iEhdX-o(S$7%g zH%D0a0>Uz|AO~Vtwfua@d%)lg03bB6QLT6}F5%L}LYqK6vjhTMJ@5JV&(j*goE7#d z{v!>C@N5b5bpte$dOb?0R%}?#qmP&Ajj@wq47+A^7^#G89#mHpJ@NkibAdmBkz2qy zDB(yoe{Dp!ERionVI&EkxJ?R3oc**_I1+;SO5ouNR6P#pA<$1Q#e8yU>aGR!1Q_Ux zexPs&sK=d{oLjr&!M^QcTz>fZ{VVZ2GfP+evTIxj_<8=yB)q}OZr+Q38TmZHy4sOf zPg~c%D>I(O^Y#KNVgN)cc_ur$wm;T`EKToRm2bSWG|TwKi&uhwiRl}Z_7P}lI)kDX zW|~6&zJcCN>y0s>Yt^s#PGl4OiK;bK{miIq`HglHt=0!mcId8j%fYyiqwOi>4KGk z!nmLVA)N-5Gxa!H6d=Nj`el!ga9UCl=ZL66<(pSpw^J=>8iFv*WT{k0Ba~pGGOYI= zszhfI!w)PmVj(7yl0b=60I1MY<2mwP3c~RsU91*B`&P8A^3@$oQT)B9-)LK5{T%Y2 zg|T+s`CQP1wYm-B>{zD2zeO!Fy60XUiB;hC_Ki|Kw^VHNb*hS;Yx9S_nZ{m^8 z7K64~3ljxI0IpMM4$Om>vvvW14j~W$(DUzqw&Ju+QLg8%g8d2r0*jwElh-*)>Qoi4 z-=Yo^L@klQJBu67G1AauIfq7houp9-1FNf@GV(NQ(+|k{ye8YF;EBlq+N6)e-F= z0GSCb+8$v=s8X^Ph<~L6f2hF<$!-Xe1wa+$-@T9mR~6DnYOXxHs&)$SuCeWtr|Vi1(g?v)@Fr@c=Hedz?y#wavl?eSjr z`;LH8W1cPc%StsA=sXZ!11J?u+U1#{>Rem>@lw87j*4eP{gY{gw+uf(QH=Z!%y!GI?4n`1kAcQynVGz7 zA`bdg3pI9;3%&>vKjs4tBnv`(9XPGqks)86)exB#wm(RtAoLf3DwZ?ych4^o2+gT z+=r$gcB;UB!P($WhEbryvUtWNw|2A{ykZ?4$7=x9tbAjf|VYY3^;jO{C{?bdA2Sx z&QT($Lp%(FoQ23_wpUO=Da-?vHKYS>!63doT;R=tk)k3@8yPM0@#Tx}Mf-VeR(A=D zPDlZc>P!uE92m}G>?q*Y@$zoE0bPd}Kbcv*22ewU4fH1@t(Kb(lrE!9VD(Q+ z+V$l-g48`MSAwQIu`(V%+klsD3xh2$X>5L3^22-%+aQ5EW*w6q&UYQ1W=DAC9wUVuuSAoEc~v4aK{>6Pl8Vr zzI;h|hiGb~pkwl|XRE;0ShOTWU^j6-M9o!AiXlDrgcR~37^K91hC}Kr?5~Z$8FU@Y zz#0!*z_oRaje%UzQtZRdQT(1Fu+OI5=EPR>Wzo)^rVlxaxG1TEnI2Drp6oZPIKF^9mHy#vti2qyAsU&1q@tZIrz+K#tcV94>t!MwY^a!kpNMpw)oM23M-aUtToB-U zM3?A~*G9Qy9{4$G9mVpMb%R5F7a^;4#u1$)aqOr_OLkQnb-DmcFPdyf$0y8>)>0`3 z947>6G{hso!XtjsF?bKk!bb;~XXr=^!jzybVnbs+;t82c=B{{e?uu>xVGjIHHUo){ zJO42FQ1^K-iHI?q8MCUIRx-I9ynp}V{VPt+X0k0dAwq|;F-r+R7g3WA7n|tXl(DW( zg@pz(+v0T>6l?ta`STZSZV+TcG`JLTRmjq`J{?pxlvdztLLfk8d#Ej5Tq?jTGohC+ z{t5gCXfpPc-dh6+CrwThLI5iiWddT~KNp`)h@~K76g`misxv3Pn&ylbe9BC#!eRtU zh9hh6MhZZ~2CI!H@L(-?kZ3eW;2|0fkwWoeny+5Hdhz^cA%KgM4`rrvZPMW#)GqtO z|Ni`c{qMh^bLR9*^-dw*-K!J=jZdvDIo!ekqoKfl6#ME#9l ziqgLLKHX%4v92}_$@)PDZq-)mb-lwxBSs*E8E%>nWY2w07EwM+?8NC|Rh$XBmu7Dt2g*KZ(z}xihF3o^FZQwt!%r0kwnv2cB z!Mk$y%l0<>eZSe{cN^FTdZME`4$Pi`?(H$(tn$0XCN(md#oY{PSVaZ)=sqWnLM$4a zSSzGRe+blF3}q}w5#kE1gO?Xp`Dg@^7m#0xho0&p@aRD%gvp-QK|zHgiE17vm6xjG zsC2j0eoQF9M;k?Y0X%nVn$KOyG3!Mbi^kcxXy7y;nJ54c=#I_jWYwh*BW@_YaS zm2^7}D4WH-Oasb4&8mq53TsyEck3!i2aZLB1pJ6)pB!zZf`O)qwg<4Op|M>uAsp5$ zE~0LjIvu{Iv(`}gA_2BN{~iHo9uVl{>B34~=tu+~mlf!(>J>Artb86%WZkq8q7GIN zpy#5?bU%)6=|=R~OHVMtfdo0=_KEpINO35TMTbRtwSaoW$DRuSk~$!dlpIO*o`j7$ z4duS#nP#c1W*81YD7vF6R@@*qTl|mEv&vy?V!B}P_U3M@I}g+Vh!Mzau+<6F+r-j8 z3v%b(4u{hm!sNu5&cM$zkB96TBFC=d#7@3~&pUhNR9ZA=Ig9Ud2#eUH%!`n%RhyV> z3k&1+jBE`HH?EQ)j4-d5&Y@CGg>4pZ(@dgbIFjuJOhGuHanM%3+aM3aEmTqt4HW8E zFDaBS0HWwlKPZM0tmvUx_(sy=qewAK4-ynnMS`b>^-Zs&o0x_aVxoX=E%yB!Vu%9e zmDgxVWx2{wkws?7djZfFybmP#{4jSBhMYWyv{|5B763%q^vP1^HS|j)P5Pd0jN@x; zye)toC>|#7-@gI?WOfBQxYB5qbKXQn5O-F{D2FH|?yhtwi&(4xtp=`BAqa5^SjpgR zF~;8$Gy?+Qau6roky3-KZD3zgQn&bgT=YEcaD5L@$YN=(@aq4pz{huL>twxc4wM1vDja3JJ|Kax4J# zp>$M3=SBf4Fkch4*}BM;NJ5Dswm=G0l%7RoV1iNb5;b5+LUsxR_>WjZ+<@#-q4Yzk z58SY6mW8bpNbVyvwffOC!9$)SCANWX)=}AkA|baY?RJzLO<)0r2yws~G^Io@c}WF> zgvaV|5Eqk#OCiy%H6xZmq(#$9csA)iK%il8QJWwG6&&TGu-~ujSK!whHdt_rb;pxF zW8oN$l>&c03`}zB;*Y&}&qlYXUDApo)zKbXM!gpTfu8^K`yh1-dl|bzm`eEs&YSHF z%_EzHesCCUXvRS#3ju0T&j^+Pboqi&7t+lVKM87^@z}a1PV=tShs(?Nh(LjUjDC{?nbiD z7&s#3OoomE9!=|roN)&M=bLAo1}$uokatq4fmRA%^Vmuhjn&Ys6ec8*BjO+ng`uIk zPnsu##7ycj)VrZ7n7pmRO6PC4^C>K(wl zwMoVUDJ)m^&BQ3uy<@#`u^P+;$cl$xgmd;SaamF7uH8)vWQ6XKRK?N>zbsr$1(OoX zs+rVhqRFdyR>-><#t%SRjS)IS?Q@;r@ADMzc^G+h@}eAHWkqgKEyMUn{-g8^D40D5 z-W7V|P9q(!ykW@w;(<+lWmpu@v;NZEDX@gJv=U1%NH+))(t(@F=nBBSE&7@Ps^0tg4 z<*zx*QnH+S9q(~U41Pv1r@|%nk`?l2m`|yjooM6oX;o7FKZmGbYo(}4`izk#d=HOr zvr5Jl(la(dXJ!rcsKI&&Rwj*yQ;&|?{beln%kcIyFm{d9xr%xAcH#RNLemmmZO?Dd zA1~w(EayFCqW3c7eYE6kGRFO<83LlcHNSqUmxXWMcZJ(#aokb&3-m&Obdd}(2`|H0 ze+SMfz3GX5W2zgQsAVT|YSeF%8Cv`aFsm3Vsq$VHPrIPf;NNey2@n-$yYm{ZOva~5Et2mDNQO!wGBL~OG|fPmg_np(x_DQ=!5 z;vdlP%DxfQ36lR*dQlti<)KC5ct#iKf}3K4fBK7GEQ!T&gE!k)bc5ZZg7RbsiALO$ zRQ!1p3w0K4!Y~j^gmgs@6!_HRPY6I~Z{@Yy89EH5d^@|TKVa|@NKXdkxy(pSnPTN0 zv7ZioPoTON98Shd$ANA?M>GB0@LAoGMnIsV!QIuM?=NHYP>B19Vu>Jqo;%f($r>JA z{h8V_sGr-M>b0&#Ug9E`1)E=UE-&si*Z$)|pu1j%Ylazhf20rMxuZ2D9y7IChM(h0 zLc0K!C$DG2*DIsuIdCGjxATuU&-h0uL&+cM;dO>NRVCSlK8f_8+4aZBr*p-fPZnB& zhIp*J^ap=Kv6V~Ry7N!*VqZj1*I+maL8@V%CN+fzrT1dp;^l#PMdb;lNd_{c!StMO zr>9vulS<;~5;0ra17VgdLT&tf-0dax{E+jn7QHPK$kYn|-5do{zOOmv(i7GU9kX>*5S@7hFk;-|Y!jGuqFdAy# z{sa~91ExN4z3O4!fbnB9I2XC!Z0Poa=c1{c{emUjoR5yra`F^m4~e|L^dOVnG){_b zXZvnTm)M0K_=(){(;Lw7HLCzJy(tlVtbEi!Ej+NsA!#kg!13TmQ}J_^^A*%iV-G7T2U% zA{c0-XcjBEEjEm_bl!mn*)0lwA3zK~dY!gJ9`EzcVC=*Si7dGL=a@%kFGKqnT{st< z#1teoXb*+QCnFUhM)L$i{Y+E%hYzcnwEQt69AsoKsf|YXr=8`Ul+p1D9jq7d88S+u zWV1MJ&`bC8zY@~~%w%QFqwFu#dL)SxUcUn`yAgLk(5@7|u=-{!cD}xl4b`1e|J5AT zPIwYaPYU;^`jIzuP8vV2CTm#Afvx3!to-L6rWygWFg;6ok|w-m!XB?>k>#bT;Y(Q? z=GQ|tpW=u)R8$B*5tBN?6Lu7#3n=*BG9MX)ks>)TkExv|QI8DO^S0>$R7i$j&7d^h zdhpu?qZ(;98T4KeA6Z#CDMKG3=e6`7Izh}o$+PX4=P43Vi~JjvW=z|a3ltX$(Md9!DxvK{*I=0orAEO;2$*4JUq}o_b{M%`$#KM@(a|AT# z24jD$b%|o5rrLHb*n+mOe=_?wQUpb>f?g5MlK+xM(+n1E^~&rM`4*;k<<}GXjp&^> z2w)3p>w)zJB3S5* zq;CrBmpuO@%qfL-%zK3g6YuUyX|BqIGUeC2$Zbuuph%!_&a;-JnxLG+TVJEJ_50@u#=~}5ND<|B%5x{-1`^%+Gt;?$hS5n#jI&G|*_Y+dGDSSuB@es6 z!tCHq6Smuoaflfu6!7xBj;pz^M*X+~yOL`K9(KekH|5_Fv={e?c2-j-#D&4uV0+r;Gqik`PsPj^B6hvT$I-XHVFr}?(=>4Su+|Rwv5$2sO-LAEdnT0sZ4!AoFyysF4>GQBxk6i`7+x~dz1jv zELZvsxfBGOGP1+)<2()8ukTf!$IbP$R_V087;nS|wKuW|r4V;pfhB#fD*C&;`nbdK zT`bk9BHqNdsp-?5#db)e{g4=m4-+Jg+}w_)hbZa0`Uzyc!BRggzo+K9v!yj``Wd(sv1zN~*O&jMbJiQ4j! za|)v~X(SlqF^<23jtN8Gjs60I0rv?C+yi6Yc?cSIC+@Ldv3qthM^LTneC|;Tg#feA z-j0^0?`XYiRdE$yPK9uTSAdW_@+bL>f1fZ7!UW0<2DL0NO=(dSHwy8g!$nH z3qu4N2Rj?mDU#9Q;%0^#iP6n$cUz(w8cIr0HMJW_ViB_u0XX^?03j_C8kB+;qJ@R- z!54FAU{YRY?|5JsVeO9&d~6LVh27xO)|HV#Y(-E0%`eVyc5d38w#}7^zZQiLexhTw zSFWvt_#;9Z%_gD?Trog#Hx`h+?j-3l|1AsZ=ai5D9EKCa448+8KY`Vi5&ijaf%}or z>Tn*%#*b~CI@&NZo)%<4y_sQ2N)>usZBu-5qH}^UQ$LEMtdy9d+WAXKm(S*m@};bV(-bYo(j*sc9C*mg>jZJ)=6P zSi(PBb}j=Jj^IgowaR1-E`aiHf|pD9~3n3T1?>AnWjl4cCFG5(jifF6o7V zr66#@Hufioi$)rH;cjTwFLmR$<2PS#jH8I;KJT&1etfw=%~930I0_m#!~V%|Ng%BU@phpWF^`dS4u%Cw&MH!0dRpqEjUC7Ix*} z4Z3BSKt>pHcpb92fP_X{ zJmYalW(akwkW4>5cSj?(3VMT2%(NY$fS};|W{Gtfdg_J4Izy*x82p+7o|=w1L4Lqk zCdsLcjG@@oQ&}pm@YvJlbDCSeaNJ6`w5zuvSb6U_5+GGu9)*GQieV4k{C!ddsF z6sS?S)^@VF2CgqfAy2}$bla6BfiYD^chj3`u8mSoBLnL{D*d=Tn~@HdMWQ*_yC5EC z|A&wa+G0PLp7D|H+F0F9YsOWcw#f&7&9-#tRlr<(lW^}qBP$QQ!4FlDiRQ@p!*N49 zf=dSL0y^nrJp8dAscHES`x9toY}cks za?UymFe7g2FiuFA7uKUxK|Y-~!aIUgS6eUY`o6K*v2gNFG0ug^qdxtBMV7F#ca!G}S zW$RO=O8RRLdZL0|#m@K72tCECLrdJE(s+xzxutjrY3eZJIopHryR}Hj3Lf8W{M#ezEl} zajUuQvTxjNKX$A!Zr1y77Wwd&p}qEa%8P(coo!Z9+`m!WQuE|yI;ghcLF3U(s`7np zM*|-h)$CYl(BbJ)rAJ}y!DaJ=247A9oC7$>Zt20r(NaV*U>n?ORG_ODrdi12I*(f)ml{9BqEjjhQHQ`79jzVJ?pw_`l^ zLHQyGVao;Bw@-j(zFda{Fsy+7wA(h3cy)#@h&yHNqPhMNr7+U$Ux$T+!OZMBBwEuI zEt_k+ioY(Z3tn_-qx8hC`bAC$9;VKrCouL z)pZ;ULS32HM@JSkWcN~`_Xr6^@{`wgvQE>L5zTT6dZ8cS`IE~*Ud*4p{!L-≪EtpgEY{YyXdDq#Jk1&E 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 diff --git a/Images/Linux.png b/Images/Linux.png index b06d66c214a4cfb9f257aae56ff25e4b33ef8fda..5b4d311e8e7989255bbb5b8f297301bcf71df5ee 100644 GIT binary patch literal 266213 zcmV)9K*hg_P)T0xh7u@KI8u5sd*RcDbgtL; z7esg@rSC~})+Q-aNp#9obk{9}-4qx-IYLr0gy(5-g=v!fM^b4-bD&XKc4k^+Xjock zg`lg9k0YG-C_-ygWPcY;g$9i8*rlC6W~owTxHYBkR#I9B5i?UtSVLH+G+32=#`hF4 zT7tavH>meibj(w0$tGHl6>zi>gwhm@?HHx+!r=ERDM~3ZN+C*qR)yjSrTQWwIZ12D zV|w0KeBy_BgL7h9Eq=68N@M_x_d-HS2qshr2q_35Nn?EIN^`vs2PimMr8!b-GMV@( zQhPBeQXv>aI7x_3d!u89Tfeo*+4F0OI0JW331f zDON&EJY#Kgp)oO1XeA_hp~(m_Unz|DIXPqbyR8TaF}>&b3q@EtIa)hPlrxO) zLPBdXFV~fV?s(= zIZ9wLIcrKnS~)RKIWbxg2r(d(UJ|{|>GHN1T_S#jHD|703ZNKL_t(|+U&i% zj^oUhHJHFO=+a4mATUm%{u+aTkmdkC29Q-y0n?{ZMw;yo(AF7i+WQSTGX?<~bSYwl zFiE4*jRzRLLb0uWm5F_e*bxj$%F3+z&N=;wy6{d)Vl1w`_9Y&g?!WTjp1bB zK7Q|``Bl4J{k8A7I-=cPU4QrS*LSyT;Y1q#vFI>-YCLP#R@HM+6;)Nab)V>ro9G92 zYqz*mwrKslZiib|)vkjPH{G;uF)b}{D9Zvz-J>dT<>DE}i=sRn9)8)SvHN>?`?x>) zo-6EUam_#fe63!;=(f~!zv92Vbum75@ch`zyxq}`&wcc z&=Vla?&$CX2n$k}hUf1Z`iUE1I}V-T=WU*L;|uPm!POCW0D%CB+6M5+tvLZQ2?0U| zi#7gwiH7j!D`G%bFN=3gzyE*CU3<5$(vLSpP_T)wCk02yXm$V~qeG2dB_KkZ z>&@B`=nfL5u6Y53AsejeUWoYcwr(q$4Qm1FI5X=RX%D;{8G3fFQb4Ix4Co{OzeKuN z-Cl0aYgS8|t&8MtSutQfKc2$<;O&A#{w#r@c0W6$_uwuy>i)!@1cUUSE6=AZSIe!d zN!|57N+s;HCUH%!+1;rWz3I*U96*60Bc8uzv%>}eTFqa_ryWSqt+T^WjTY4nF$LPKbY&2Dr0q0dQ0;cWVP3}F3&KS!IOVM{4?qZBE#7Av4?Q6L zpf61r&<+p|Nzvg*J}{U7f0#4Dio*fn3$h>*-}JrYpvs$xg- zk6VXipoTOh3~oV;L9+8qa`ZE>o@Y1Du^?nb&(*^_u_y4AJO1Cu#kaMuHA`}HreyBZ z%4M2w&rJkho>nPX(~UlF@&qtwq6_`DN%>RCgL3NsX@70oUn?lu{z11$<~0iRv?c3p z2;!+Y<+;;U`6uC5yN{KD=$5@h7)&$^2PjBl2!KG%VfR%vzO*a^J^9@{b;M=>mB?*| zCKf5vh%=R&Xh;KcD~#k!1A_EimSTc|IR=qHCCEbTmamG3d&o<(rMNaZj&SpNivdkf z8|^xp#lO$f)duZP@+nfM{2aRFtVqUs`Ub`SS>||$36~K){xrZgXwkbxf{lM63NFb< z45>R^+%&ummJ9spg6ISI<5j1RigFXxN81iaUK%eogRSH&FmPWX&uK?OAhf2Qq=A7* z4Gf6((Tc0ADqfln)&^0!MJmKzwI`ZUlx4+EumXHw=ma|)i2s01_R#4cXwz!SAdok2 z-}DdPWXK&g`0v@Agw6ao5OogBZebg#bUq zzJTep7}ZlyP@>p`JM?n3f@lCV%!``o1=&&CAOP)fcF~f%z5-vn*kI29KHvvK4H|v& z5C^1xoDBZtjM7|)+-+{7K;Z@iWoITr+TBLICpu4Y=uh+oQd=xTc$%*JrNGnVuIreT zHNVFsyGk`~@{r$xMbVsJhC%mfpKFom+81b6ie&iM?XDB7J7VJ2s)5hF2uFKT0g7OZ zji5rChCS=!u4>t*E*98R*R}*QUJydFu0ih8axw;fw#a-KpdkI?x$r3&1?WG|MG3kz z1|uF0j}L1>c7+DnD8n~t8t)dFvZmgBjOr<|x}rOI6gj&JSxq7E*TT=LZLP28m3_Dw ziO{^)$l0{}n%`{{ZX<3k2K_gJQ0|v*HUM&k6;GK9dAF0>cycqpXRPVg0l=uJ!hUrd zU=jnW4|>|G>SYJ|Ps5f5ObY^m_zHVya8|M7joX)slx;*QilIiChiovIT?3mVm?6RW z8BDP90DiCoW`uzj^mur9yJGRSIG+!`=e+$mvF|ORKH1>=Yl6Tp#-L`ikw+I=POZvo zM;|KqzG>l|!SZ+0o<_rMv(faM>vHt3pg>(d0k!GU6>hh#-Hy;_(-64U>@wH1+&6cv zLN%{Vwcz=hnqBb%%^QE?`8%Ch2d75w=gCRn#d__l-ut}lX(@LN-Qk|9pfha3X z@=(Fxs>-rFmKX&Dk%`VKI{*Xv38VP;{lVLR`A;alDU5EY>{)lhFXlgMA$8rz*G=ns zqisG!b$R2$=Ejj%QpFtrn22;ay0hVq`VIEiTjSg}?%wSDHM>SDmbV(=z3s&zP#1R0 zIbaTf@V%-Gx_#)_4F?@cRJ6m93Aow#LTrbm5M)5G7g&SbV9$&*6-7l8SnbH#A_*Fj zG9W6tI3NQm%HsI=$dS+==fL?L%=g2tnp_yudNA2Z| zK?r1@X;&RvawYBDWasn8#&##pFh_zQni>&_%rr-FMmkj>Kg|`)OSat!G3@CPEvAH|?neu;JT(1sXD&nf?$!h~NhSvv(%o;$^0GjU6s zn$xU%@d_f zG#~47ebN+2$JucR;!{;(t}095B9o#stZ9Nfe&?7FT4WO}eHx!D3~z)HWS zUN5@I1Inz$js}vrm^zrH_>q?zaW*n!|rrToBWrGU;0Z- z(P?a~si*zdNilPhQ=c|u;a}~!++u9oc|6{rf68YmwQ0!z2RLv*hHe|5Cl_$rfl7JY zIf6qoS%yZpmvJQMX~!ixnyz|j3^5?M8m57QwX6dC?M&l!>qZhy(XMJR<%_aZp~bYv zs(~bXPDE|F;26PARgI(`P0dSDun2tw_$dy@(s7~3BSj&)=dpbFTSknJzE+xbD%U*> zXvKf1txjr!xC1kWl<6d98no!Z0h%tQ5;2eHy4A#V(+d{uXd}tQIcy3Rug~O*gF<6w&`vq?E^rDUO zDBhQf@f7k3Fxj-@ye{BG^dC6`>?yz>$vRIQyV7C}L<#cYboU+Y5dxrFaD?r|4-Z*h zfIH7)s7>|+aX@I6Jv#;jb;u5omvKNl%q{tAyDN?lf4j!ghYHaf7S(;iq0bRvAkp~K zBvfZwv7>}At&D|hl8+`mu|kyff~jRwvpRynLwZm4%xB7m(*#hNQZLw~H%!#4DSvM9 zfu_tCSy7&8BR^(pqPK)2Hu@wt^q`C~_mh|Dy-}tTp5p)qpn>xfrzg*{TbP)h-i-@{0aCe#O|vQ4{dC(4Hg&gsbqVF!0LYX9xiPa| zgHbf4KOb~8--%Yy>qOlzI>z1xs0amJJj^vi)7_Wxmn+iZrsyK1JbaxDF8*^ zG+0s7Myzut$6zB8I_Cw`R7y!e8|kghie+sy^DS7+vY;H9xt3*{?j-kRuAomu-Jr#_ zwQ0J1@v>{)%jx&s4$nRch7dR+LPx z(+jp()Yo7uOMo%{(WamR%ME%m^t%}~@IsReo-M5=ZVz-)o@7j^*0iQbv9l`kKE+%p z*=ULstH`G{WfBvn4I;J{lro}DlOsodu7OzIaI7fI&1hXpWKP zg^Yx&&rI(!!zLg?^yM&`x$$AlICFATq|GQX6WW^c6Xqre@_6y7D4mlQU})r&E*BQMzQkz)T|T$NyBDKCJt^U{idc z=DzA1c?LA4#$+=VmDyri-6jK?k{jkPwa3KRnOLiNns}BGU6HlvpBoUtl*TO{ezwb= z+T)?x(E*WhJt4Od%T0I`mIz`5DyZrPbo*76C^WZ?0a_$ogF!fSRgF}p{;%NULbZny z!H(#E$2#-}tV;iUczisR?ZdU$tfMyA#71h@2tZm*NVy(XbC@k=zk)iODlL1r)|XC+=R z508G99uH`tK&g?{_!a0}4iT?4JiPfcHFMd^GsKupB)&@*yP^Y%d^52dKwd0vv%Dw0qd{=x%e5 zyzsD@klba{4f5hblFS#dZYR}pyL`FiIOOXZAg+RJZq>S))_Oxuu@J#0XAlVwL0I9C zm1xD8O*O_fLAZv=$L!Io$?RY2y5Lh$0kLJroers#%~gPp5#jl z@T?5U`yLzXo0~fea}(O;MW8sIN?$Tl7ZX$!CZQ#voNsXY`JC6J@~g-+>L!dfn3S4% z3UT0XeX$J}RLUJQEJVHI;Ydz*FFtw9dFm+cyuqbZ+Ii-X z$SC@!Xt5$9kepHo5IVyEaVQh)P+?it!?7%0svHB#Sx?(JN7t>d+t{{U^msGbX{&xk zm#^Rz_O{F8P2<^Wm+MkDbGMyR0x)&k&Y#A!8Y(Et(($-Wfms z&>fn8o%h`nQ+g7*j8b&llAP?UwhsMV=z;fPLKUX3;wmo_&U`LQE=Ny&GCvoX2u9)0 zkQVmnEU}licxZ0bT)CMyebqO5l`7>*-836n&6zZ!TmF@8_t84WO|p$Vfz|Y8%7oQS z%H2HWeLhnX_NVT*ansvuXyQ=5+Ab9(qt+G=jf_m*-0H&WekK3C=nE6ROgcR~ZF={!@gx#y17lf|8x-|ttS(`m-91`u|!_6>%J(N}BL8qJIt_b0PK1_+~ zj#bt8Op(r5I;c914TmSb6u^LB5%&ep!HbaUMF2#-f&m0!FJTUNj+hr;9Niuc4|n)> zZ{Z%-ylB^v zD=_k(g}>eq?=e&4o5KxPE=zTl#E#u5au+vAI8!Vjagf-m%7IbfHu-3lsG!wT#&PtN z7tyB3hYiqD9S$!|6FAWVcWNWj2IXoD5X z9058!he{lh5_Uk}dx0f^s_F&1X5Pk{Eo-dXu&-`K!R3$<{dXVv1wX4vZP_kwRFW>7q!x8JZk4%m&2_XdJ-7iVjo** z@_q(n?oxnq;45DkQkB^7(m=ZHrEUD?L5x#E+O>eE4HG?g)u+z4z?!sSw!626RImn~ zrp@4NPrxKlwnF|R$o8}@r>tYc;B+VxjMKNEYW;Ib@rEsT4Mt_@cf8!ZR8;)OC#Xt5 z^buU|hoVFw2>J}elC0S@p*yUw>85I(3D{kQmTYJ~Z(%^Ioa}3Y(cKSevJFedciqXA z9-}m1g+8Xcre`R^F&W*S?jABMV%4nIl8b_#YsR73vWtv5%!e?b4B(iXMw$OsKw}&Q zV*0q=No*81ndqdci+z|=EZ$9<^ndDB`$(8}6n?ZyQJ!=}%FVE9a<+$J1~*~>=)$ZH z$Es;Ej_s#3V~$0_3c=+VvfUwsh~f~f{5s=}{sM)Ou!4_9YF(Ydnu6B}X(MGrKKbQd_jj^qnHkh6o72o43HBS-V z$-5}MVswS(ZrcD+WrSS)C{2NGM*imuXm0n@!1#yum&2c_nKpqfS<*;!GZ+1FmXm{* z+B8*Lx3shpHY5r0&>h%8AglN*)1U)Buq?*`5ejQUZ+O9`yS!l2MjZ4;BKEcy>@Ez- zOI2I(MN_Uapla1C86iu6GEIW)BkfPg>N#|U8*R;*y!o@uEuywR-_L;J&y)bYodIp@ z!+$6P%0epM1SV)4N_;l@AM?L!156W~XZXHNWOA;;Z2@!xgJKydFpMoCGY0=a zSq@Tz*aS3z5fzNbn%dK0hwQplUU4{Y05SB2YHyMo|H<0-yBGAqn10hsdsX778 zHT?}5P?Neqr!;phNvoT->JdaDhjRFLQ8KfqK>7M&8wnq{*Q>w+i53n_!2W_GuO;j> zx6=otfbVN$m?0Jf{Vf~pEUcvtox>u@{lbi|N~&>GN9+v4ZTNUV0}KM957qJUtzNL{ zc2w*A@4vwdrfhc;`HFAZHaQ`siPEv|e)vQ$PYgGup9yHrtPTKElbO^aHO^CNf0LY^ z{*ES3{<=H~G}8w#plu-fJt%|`Kp=;99T{RV@loGtMZ_{i0(^-h{hpT@y-+l5*CSAo zAKj{4f;h%Zce`(vq}F|$=d{iVZ+6|z^Pg$G;+Ad%nO@iv7$?1>haEMat|b5(rSDTo z$tWr4kZ}q7V}^~M*$Z|ku^zND>)*yY07`!{>Bc zv*^;)p$a^2llK~>GgIoaX+f^S=`|7 zcZYf0bsHBcy-iTWI5I$UI#Ui;6;Yfb8apNat&9|>Wguqrt^6~M=5%()n!r0&?WgO_LOqNlB- z4?|rO`hX0G3O@t=p~%AnC4wEmegps4U%>+V^l&YxG#d)CmJ6nwf^omM#>8AI;`Q%* zh*4{Dw!!9kr3<6DpSxZ9a<>;)R?wdN%_UTM@;@V^mx=gJKrvxTu$|8#gVx&+WMNyz zg&_!L7Ce*19nUl?t$jxMgx)8O55|Ps%Y5y=lq{SC8g38f#)=BESK*R#=OGy=(B#2} ztXYQ1YYa$*Po$BUGyiJI->9O%rgfhFnxrQcq$mzQD&dR8!Bp`EpHWM`bZYhCQFs(; z8@>BRqNq`RK0^GDk9`gh12xbjDrmRrx21t7o>qKaWMcsX;@;m|Qz`97y5Pa?-?2Mp zhhB#g6EhCjCm~p1=zlMP0Db!OaIb~lW#oeQnd;k-xA*G>TdYK77&NJfaR&q9jivZ% zCz+X{CQeA5-$o#nD>`-TWua?daZPo3Pk~C#crL^<{0z?yV(Ou6FQPz1a%KV~*bzev z0gmw*Vv|6l8*!`#o|7@EZS!fyP2O+SO)OI7>D&gk+=_q7q0Jix1XTL6lXVS%W4?_% zyUvqGmb|)zCE@!NoSW&N8bCdJlJhMu7)RsGL50?3Kzwz;pm|5V62RpQ)W^G*3UM-V z@5oiVGXa8vux+3e>P{8#)YezK^LS(uhuYLo&lpmc9>ai+2hfEk=qaO(7!bL@z)g0< z8DMr52k^-sP?bJ}2NVSQ^obZyVnHYHgrPV-qA2Y( zh3JZ}pwdW8t5{JT)rv2I=KEZUFcX~QZ6o>fL9==(9B90V?yX|@@&4MjokS(=bSyU< zcsEvm#hB)Xd*5k6W2XMXI_SYr^1XcbgxK{L6Chwf&m}}aKSJye#34T7a0D>=^bG+h z%6OV$3paX+KiYWJb?UB{qq+8?5;e;Dd}Ggc8dcEl@D8GwA-M-!==5gjdT!>STAb+se>p&IYRy-3)&v_fNsUwL;LD{{!Qdc+YZzyx^ImVX4gXY=a5x#(Vsm zS;bbSWiFv+<1FooE`MxQ@PAWLWC9-19z6yT`w2>mx4R$-t9_}fN|i;W);Wn^tp(51 zi)Cn%I(pc2VYh8dOQK9%Zq;q|QXl~B3>|alrc0_i4_O*?E+jxdbM6;P&`<{mH*|Pa zBIvje_F0d0yepDmMIxeU$>nd zQ+M0^@&c;~4kDcz-59#HBAuBLR=9S9;WF3_Aqy6SYG(0ygO&mtz&D4_SrlGB%wmlg zZl*Dlh`dyUBWU5w!N?)%Kn;ARCWbAf^G%*UxcQq%ie{joeNaQ5r9qpRMnvLDY!J;n zbLNd_frV}bBmf5j4gn|UEF9#H)fsa)I(1t+jZdqK4<~RCmH`FQL~JrXFi3Ge<8xn< zu!bv?F|I~{bXi77+=Wm8pPMcf^Cr9u*~#Ut1y;NHdQ>_QF(2bIWSiC#4e0{VG-6^k z&2DVl9br=K0L2)uZ$lsLpi;L}DF4nS;7MkvECEh~d1%uVaH<&{z#U60Lyzb-?po;M z0?)uSyRnMSiSpkMY=M>K5wcjz>iLN3Gs2I9okz0590B^K7?5uH8;nIY{;AQqnM`A{ zDbuoxoY5a=pZhSDi5*IFid*wmlrT@vI;Ms%DZT(3e|gfKwIL*OR|%3JzIQfsKOvN)>8D2;^MIw6d-_t|&`L~y`scE*!{fHbpzkBLJ>asmX+ zo+flL_Xwj3lLBSZV4`tt3o5z@1^>8*oVjBKwo4H>r*SJ}3BTN=b|_$YIs zH693%gP%{BlW{B`zkvpHUk!yRrV zdZY21^MwbbD3Ep>2MlUFX9!jYg3qi10S$8z27oRK2=wczph3E>)#gf!=)_&DtR@Wx zdx!&a6g^bf6H~zz438I4M%z*%$Ro9HYV}lDlw+<;tv(Yz|vx>UfdK=$YD@x z0D+L^6A&~&SG*P;)g=OI)r$DdJ~1Id==*{mO;L`DG_PS*6p~tI5KAF(rPpk1KimOHk`A9-DRNisulcdCABbpl@L}V~b2k)(z z1M$+JoYSbnFSqU z9jJipFRZ=+nDgAU&_{+F|903tWWw#YLcU@cXc#~m6hs;vkZB(f4gHHF_o3 zKe8htfJ*M@=%b-F-_2bDSW|i*B(sPvxG8{gV1j@<9qTIHY?Mw*7!-)q9N@C{U}wG9XFdK#}E%(2|&9ce1TOhvqHxk!v?PBSN4SlC6wc2Z$N= zjkV}!r;>vlWI?*qEH`4V=_z*I%pm~dGuU6q=9&tQ4>GutpfJ{_g&O{Bd9_9bXFrW@ z8;IPgx~buAcc{O?=g=Fx$l=8i;|^H?A_9c)2jkBb>CWgM8=L9?1n7BsNMJ=!A!_V` z6zR{7e1~6NW69%wF50Zg-AOZoVp8UU?jlV9lW^ol{^xEjh~{L{R2Wcp*}P@}8Yw1a zF{LVu;GD-h6XC?XK{4hHb%pJ)Ah77?pO5R0x)^_-!KVz=AlYxoQ+RDRa=lonxnm4D zzZwx38efdgj6U+GX{1zd<4eXGi4x()5b}>&?AEkGkDH@FqvsO3MucNP(9t{VKE|lP zZ(vO=Mlmwj~KDB!Hn4zS&i1no+T_LX;p#x_EXB2y!vN6@PpoL_B;00`&5i zhYUuiw`5XfMW3BXsZGiL{El03w>_i#AeP_#*%p7z!``{pwc*AJ=K7}B4_sCC@8w)3 zzO}Bez-~3aAxp7|@4Tu-wiS^daD7h{q28%LFOKZ!B1bIA;Ydtc4nA}H!46o+eT-=~ zEI*mbNd57Sh!_d8j`fTU5LgSjy4v)SZkp>;G z5IuAd@306wV4seE=^k`+`?a67%ZQwla=LUW@Ay#s`1A2LP_S=k{tdpTW;ypH!}NgwM9UV-Qcc85o9tg z7gOCUrhdecMnhBI5JO$)bMKSII2?A$WS7D)N zsBA#^lt%~w`t{@JB#yAZ$^YCn{SmVEN!2z<00lQ8O1J>U z1v~qgl>A9<91=mq{*uHV$6gEu5JK1+vYTC{Vn-#O7dG0lyM|3b<3kZa0;+)1n1(f= z3YZS5(T%snP#{0L`RynKh+Sda1w0n1e{{3TM=;4y0Qz>E1b{F^m!#2c({)}8pnr-G zKgl!hT|cw)D@RR<%GCiLZ)oW;-N^6J{GLGrrt$2?YL_l{~;$GM!H%mP$C6K$Y(vV(b%yp#jfHR7lSm8 zMpcWxG8CaOvJhyGX>=8!0(yRTctgEsl%fPtVmxPoVI9^3dccqXO<;m~FHdTu&UvGC z{s%Ct>>C-v279tUefSUk4lCOz1sVaHH$6-|q1vB~Fl@D^O^zBL`8F_afn*y4U3+a` z@NDT55C~R}{_IT=>K3Y4_4e++v9+$r+N@;cAG?}5q^QO=wJ=tOiZ|eptw8@cV;hON z)yS%oPqCYcQ8BK~jo%AS?*JW-Am)IGG-9sB4x}DHow|kPmBnRL zyWQPdbElxlR>yJYFu3WIDBd8U32-!bi6@%D$b0HKTa1$d7ghz#h%_K)YCTixeOonk z$jYZI_`|UU-bC48!ha|T8ZZfTpbA~^-;Nkh@PNc^&PS>JcC|Fp5I%&b-`daWR)4b< z+I8!Wm;Xw$VE>*H4B46PVPVKGUZc#dof-!~MQ!qH z4Illc5LcUM=?V4y7Dw zuC;M2r1nSMcvl$q{e=$uwlOaUlAyujDs0=1&yF|{~q6Ac8?!-fg%zHNlYF|xz z)lj&~eb=kqshq}|in&j3c>`EjbyMGB`?Suh8}5=qvdunE5w4!HCLb5|e%gAf#2tgwFzJ{ihxe=d%2j2d8$-E&xa4Dkl2QE{O7 zXRHF$G&M3HPCi0vY z%7M8Lt*uc&v1uV(=OVWm(A#}UcSO9|xHVoU1}3Ac`Y{u1Fu#k}JBGo&4u*zRGf<6* zR-w<;9tPTvOuy8);jTgVVCkJ@3AHxu`XvR?;S#_-S!e&lQWT4TqlPp_bb0yXOOwaLF-S>UO}(y{A6D-iyF2DjU5Oygg>tW z7V8}tk3nW&%&`J2uL_=UXV|cWCcSQ$Y9DQK4S5UfrlrJkPYN7?Io0?a0;y6a)UYif z1?x^h$%wb?y53j3Xz-TQ`X|V!=^K&R{xbDz>PstJVF^LH)0nc-9QXWSbk^oCi`>}8h3L<@MP_o`WHY8E5?`!c*5ok z2iB(M7{3pGFL0%BY|3C2qZ#=A99_Q=KD*5bUQA4x4DVhJJY=O~lkrZy^N}Gy*4}Mb z4J+GisFf9^p=nqXt1YS(&$q)|J-X&F*35wJ0AUls$$k7gzG4$QA-N#+jrpnztRTI& zy#-ybyxW?Do_b?-o1s!I`q{u8XA=Nw>$bIRc|a8(2@%;@rDHrW>PRI5565X^x69NA zYRTP)0RmBWhQlD!mQ<6>5unH2>;cGUO5W`{%0{W>ZLs)9x2r$Nt^!)F9zOXw^Ym9= zJ=ybFdASva#h#u-VXd@CT;Ci z?6q+2uZkO)7$387b@3mNi}hLK)9`jWwANv^AxH_)Va<9i=CHw)!LMuh6V9cEM)b8> z?;r!mn-LCiRCpd{Ue~ldWk7H8icy8r%HAUywS-eGh8)n%DrakDHXflUeTIRx7(jJI zU0L`Tc-G6ZB8OO8*UW%8)Q7s^aliI6MoVMw7gc+NlB{KAT0*2x-#`H}0zh3zz<6T> ziis%9RV&S|{8lTOEnn+(oM4W<;k8m!rM6c=C4x3Rne)D_ zmb>p#qY*~mX;`0aCW(F<+*|e3;~y<8C`d(-CG?1 z&fH;!!Nd#N3JpROdMaCUFrp9BW&*_7s3neL><>slN6bU5upTsIfgPvD15j|j-6#J1 z3`tsfC0G8gl&wbSu^ql=OwO9K*X}en)vjWuW|D>a++r4;+zKNk(i%+WCrEFmxp)G> zglJ!CJb>qL$6qic5d)EM9!J%@!JT)*4}ZfJi^Q7LiM7(8V_p?G(&Fth-0fltv?FX) zlU8QPSzv}u@8hk^N$#h2pM1KkVg?3o%5KHN}e!KfF7&A7zIGS3b5Bj5;ybv z@&?UK3&^b8mDc23Z1(C+B&B3o2(s&_dYkdN@vJ#PM3aaEi4|rUL$n6CY)N>H?PuLIuy3W;dLESd?QYCSWhJ3gE?Dig(iwW^Jmoh9M(mnw1?O%D`Q2WP6tdc25kD zV~dMkqkf6$Q`@k6G>%0xjj}0e_Ad0)%4@u*%}d zJzo&+ApSfG{x||On}h)cF~pcRrYV{XamoZjm=yyuxxk>S4Cv#6uQPZ!Ctq&%Z`+ja zHAgmR*K@LRk4JDH{u_zy)cd#i_n|Fjfo#j=+xSqj z3hiXJG?)wRXSV+Eb{1SpEwW5fC3_a$7+x76X~Hecb-)>74m4cHreQ0P(QfdcmBe(H zNG@0eIy5-KYK&PBp-v$8HD@Qw^*t+175B7jW9F?!R_5mL3ktEMuykX!JLA8?uRx%(`g3|l7T)!2QU{`1fgxSq zW<_!W0$lykQC>*W(cDjiMi?xu1-!`=i+`LUO|Mgi_q?qn&!Mv z+55NjfuY-WFv5=arHdU4$&bek)fJv>-r4F{m=UXL@JX~(@wr51@T}H$Kqx` zMCRJ;Z-SvM&ntKgm^BOWoK+8Bv);RK9kmJ_W)`@}rttQ0(6G)Y*G|F7(P{fe56q>6nE1*#%ku@Oql6R;BQ9l4Ujw;TCg(8<9Bdz^yTDI!NU z$wn;>RZ|>}7$$_Mh235d{!o&>wdjAxq8lYi(HsR-de!ICr%$+_$4~45J46*i9!!P; zr5fut+p#w|$b0JU{5&YlKfSRanccY1=BN+R8JjM(X(AtR`CWk5@S4`>-6-Qr@M*U3 z70yPJTp_dNUCeCy(aFtb1wqV@F=tpxn#II3LZ{f)BT>7jV=(N#GUUuR zN|;@bM!td&IWSuL==ZneoSsHb_w#p*J?G^t+un@ zb33h}gqULYt?(3gCAH}F+F?0Ao#?- zsK9DvBp0@({4TV|YQ(;sm7Y)!RE~_C@R&bxWcmXg5sn3R$oz-~*k8Ie0L`HhzM^Nx zWJ_^o!R9&w{junD*)qcH8d(V(Gb0`4} zk44mYE(&V`0?k6Y1kuFU3One7r(brDpVV@D92?je^QxA@i~e2}=;tWVaF<$rbD=Oc zfh31h#UrN08@sP-_pJtu1&S*gSV5pDd?MA$EZv&qhh6)RYP-Jqy!Fv>qcaax}S+|mRjz!*R}1`apbYCg$m_^q?>RosR-S7IXG!8+jng}g0WRn z4p>deVCaR%V$a+|Pf2cjN<;s}nAPKV1^{C2;~9|tt&=N2U0fWP zGqQv8^3H461JJA?$l-|ve|Oz*?|g11Frlh#=)5L>e$sahbaD#V)E38fGNF&o+4G~C z%C*j1LK^U=as;Ts@tivMUY*y~++D(heUkI-xGHlp7u0mYiO=G-~>`EFikt@2r#nL(!1HZvYIOmscZ zxzE);Ry()eoU*aL!`?Tw2$7>#WG2>kXpGh;EOKLm{cZ;zRx?CpzZA%%;efq*-sCRB z+U_u;O12Vx^3H?F@n#1q5CP2wwGK&F?H-fsV z=lQJ{;Oc^$F?-a8YCVW6pz=V`4M#xcxtr&Sa^U9%^lB{e%sui-f4tnsF4bM$xgTKi z-M`{uuot_|V6fpNT}@M^4F^EoNO6d*v&FEt(}L2@&;)akR~;X*>@!tGME&O(q7ljE z^$GLg5r9~Mo(ST^JbciN<&_oKSN9ja;`?l)#xh6L!6a!M>)}E-+f6BVzWNu*A!YRK zKyp#nfDd&tsf#PWIbUO!Xjlo+9z|wct{By83?Q#_Bmnu>_ds3d82XGi&{i<^DvblB z9>JDAji*$thwkoH2VKtCqUOPPW3Q(c{Tio6^-(%j&((&kq8B-~)8DNCt)qPMK|w>5 z=hb`68$xA|VHmR51#j>z2b5690WNWXn4V3v0H_0h1*S+U<(Tw)?-UN5`+u^ z$a|(4%C)vZIT|Y@KxNy22{v}KJ4j6u5IN`23syM;?Z65&dgC!umHR~n*m*ocG$M-6 z|J&oYZ=YWNVz}3G2FM3}H|JYq2!aa(TL3&aUFrsSn)IoGD=~g_E1OMzh|%t*|5F`h zj_y&u?Ou!*UZKId0enT$Owp+K1i;Kb5Ya}fq-5iwJYjAC;2{I-_4WHJJP>@0{jOxC zInt~351=M3d!*QK!aaXS()B9F*~}nMcGgTc%bxaPy{Xh&e+T!LoANWou=NUrqKCVW zNn5iK#&n;?d{d8(<9_0t)4^ubUSrpMn&A;C)E*EA#$NXmLa$ZDS4_vK_i$gwy_msT z9R^MmXfO=Q;yP3`h(vyWRfSvG>~-jm@q_^dYPCQx0VZKpAHoycwg?-o_t)b^G|}6H zB+26td{)Pb6lwsfiCB9#c>qH|yuZw(Ro(7@+&IDrY!3S)!$@cZaP<1OBXvrM#STmC z8iOhzvN`4$5L7k_F~mWJ_|xS4=B~ zpzQN?rP9o=sF9PoCt zc?Ej~Ui0uuV?9n;cXmU-YrkxmU;A0K1%GZqZk7!kumM>aV8{4UW)htPsvJZ;+{eXw z+(AGcEQ!&*P!!CAqB3T^J4(p=vPv zu;rKl?&HEyBFdBHvd@JlJs5S!{bOK9U~U9VFR;bFeLC(MFd2D3tb2%c1Qjh}*VDn5 zB0;yaF=0e&wy$!pjv(e$tPEO=Z?snYP8+?(fRgbi&51qqirb@M6Kg93NVCy?CFRHV zaATBTySHJT@WuN%1)-h=UG%H;uM$7llNil7=s3%FqrRoVu~$4P^D5utJCLTpNPD9| zp1vI0$#YD;diGb@;85>ph9CYemmW~5=kxces3?Aj42>AlzsBA7Y&Ppi-RUFLV(htI zjw7kJ8YQL#2M=Z?Y{;Of!7xmh;&$N*oVctB;)WXbo z;d`C8gDGfelJ!P~&BrptH34B}d&>a^lKYwRvE0dH)H2W??o-u*{ydSI!=kfpAH+4N z)proygG`4Dp*quwD3T?;n{?^wc?2IkxY@|vg%ruxe1=I!|QRJ`oUMTCgRb%8p zvYr?MQ_6Fs(z@xO#>5vK~xbKz-62aDBzT-BII`xpcF3{Iodf`bA;4GWx z{zBiTN2{zSsRnJNG*;bWQGji(Gv!~u-;;M4rOUF zj$Y^+f)3rY=#KRPEruD}Ro#}J)qTqv+RPpI)O95R6~+rht14wmt*{&v7Dba$=k~ZM z^moCVwGjW@vTJOt4EHQbY=$Th#q*#n%|VCQ`At(Ei0P0g9+V&Ui&qtR_)+btj@8&4 z2!J>cdTu}y!a|3&JNh)D=u?(O$wfE-jF2Lg$FewldaPa!=m|pt1Pagrz)iYz?-(E- z);ZIC_*txW%*-A_GO|t*d#57VXCvvDQ3jU}ROus^ftQ9 zawMMclp*Mh9)dV2!HR4vCI&_aqB-Nm8VroNP|HTIZZ8e}LIi|K2u_H#7V$1?<`owT z&T$jW9g|uz;?}YRr2=rmxaf=|mbten!%@s9{&+>a=%u0eq#m(T-S*m28UkSW@yG|i za#f<1oFZ~|c2o%+_LtR0g*50dF-nZ6^CoJlAiITAxh*}E%6JcKw%pPsA zS7U1kNbIQsZ(Q=l`a78kB1aH3)SVds2>k6(yk~5Ew6cx5Y7V(Otw|c%oQN0D(J4_X zq98sa6&O%U_SodiG?bu^j(u4Pgr03h-MmAOV3_|}g1to^__8dq!yN)42thoK6#nxK z;0FQ`k1a<45gX(1$cMzm(<@E?V$$~On~Ba3xESq{;hcdv{4{ff1o~z_uVPl_$W~V2 zgDFW{Wu(qYwvNxcilEQxq84)L&|Palhcr&JAOFZ^MEfJtbfsfQ?eS)zE$X64@~1I zRtQc5(&9_3-?tx@y4v$MzocQ_h(Oc_Jq_IDM3VYT9oEB-V30(T6vwxQ8cjTRp$zek zXY21Cy)O*c`!qj^YDd*_7%MI&+uBR#;}h$u_IKtkgr3$RWX5Fu(OBW9CQ)bx-#eG& zaEpKewM2jp<+ua23`{=o!V@toP~kxYf-L+JJBddJSc%=fm%j5su(`@o6M?<&ccJ33iYbv3tX}HT}zmuS5_zo%P8~6CrQw6kXf!jgt zsQ(G(avm}rpvL_U4hi47YNBm*Q|PzeAE;<(SuOR~eH{V-`ZU>u3cLphBF+==s3l5d z;>`xe@fjejCT#P_NY^cea`uc?xZy0-KJ?ua?k!jt8l@k$&>XHoLP<>s^cukn`rc*@ zK51yoDkV4$ zh&&wq^No{GKRE*QYE0}Fcf*4;$Jo^zQlFwIPoL)KGmnfHI8rB>kQ+g>$ZI|O#+gR0 zCGIz|M?_)i6P@LvK9zbD)$37_h@pg7&w`Klw6c`r9Y=DfGFAbwjnyn+608(h6=d88 zc9USuCD>xd+KX1fO~?S{`(n?zSw1C#Nm_3tr)v)P2BKXIKdh{Bx@Mq2v^r0Dsb^3s ziq)=oMuC2a`cX!}>Idz4XQp%~=qPeCSWkSyr&R>VQy^K8Fr_zGX~={AWrPyxkTzKj z<5+7~TyJ$)wL%$TK=|U6cUox4?(yo;tD{0lj_J3oAnk1Bzr$QRc1EiI-50=AcVqN} zQ4Sj`MUYDif-{6F&98BooI9m;NLdtSHbZ!`cx9@hrs&)mj|0({Gn!hC_~08=J*;UT z`*xWBBk^I=Q%tan)k1{T0WcD5 zGDkPzh`S`YjggPYJB`kvMX7(uL1n$7? zUNo5AzG`9EyH|RZ#h?m$&b+yNx!@b~oZR}DWD<{vzpy@ZVF`&pXT_N=)+#4=qPyxU9N`)>?q%Mjv`Y>NR62?Jsf(%yYp z_kJMazppN#yQWX&OM}-R3njk;CW<*RF>d_C;me@@!vij=YPq>9M2Ab zSh>-l(uZa$q$UZ-3)pipb`_TwOGj%nEB#d9b&0Yjqu^tN8&R5qhN7c!;=`F}nOA8g zvJczkMbJm3MR_gPXJyLOgD8bgZVwUCz7Y`!EoQhAy45b?i}I_d&MhCn9FSrVrW6J- z%lxDtn?-PjdEe5zK8tLoTdUIybv5Ly%26*V{{JJ>Tp7n6cK!el0EQiN0P&%|MhD(T*jvj(DG>SET7>m>j z#;??J2fG447yO0rLapn|wZs&zcRg5t;jN04WAX*sVd&|{Lk(C{eh66%hW*X0jlI)z z91LTi$YH^T8tU6_H#J5J)u2LKP=FjlLByu5x!@sfI;x~o%6C6f?L+MO0xBM&WeYTj zap%(~u7dcf_)gYh>dZC|X-)+TH<~Lb8WD3Jj(_XZwW7UUOw4)K@T1~uG~fg|M06>= zvCmdWLj`RvTDdoY5P6roxFZzja|iiuJ?kT`%oR#!cCe5^<6TPLep3ceuR)Kg$IOB? z(Tz2jgyA)&EjTX-MQStDp+gi8jeM5?pP8l<9(iF$q-Bpky%Ku{CIcQ(1~$$HK_O;6 zS9*Zo^sgfX-7yfDoX<8gy0SxzKe2*6B=(vc;A#7%L<)2$7j$;vS3jq5lb-U>c)LO- zKf~~PZdVtT`!BFlZ20Kp*nsSpD0D_yEX+=4HdjI* z*t|a3u(=QW6IYNrY5=DYT2C&Zpgj55U~bQ^KEr$9d}&qaLB!-f$SdL3>TOV01OV{e zLkJO&!Stz%-1ecKn5H^?0`0vw8L8TaW>MDj96cy4I_S{aP8&GpkRBL$I7A9jAMCLe z#CTv!SV#l{mJOwIBnAx`lwq)7#sr_k3TnW3JKGzB^3ahb2eYgx9>K>`mixio=J)kN zIy9Y^tsR=w4p3^woi+fHj4sTGJUrnW_^U2MTo7as1nPCNs}K7K=l4pfApNU%qtFd< z;KC?%P1K_vP{$m|>s3oO5=Gf!7FwDw9i>*1GrevH?x-2+a3BMkfdSRHynsB^qBg>S zAOQgSHASzN#~<+~0v&p!KA52|3?e~*N5=zMV&5L^f3RPum#hTI0DF*9GwQuJUaHiZ z4u@o|n9dpsd@Tp1xM**dZfB8>bTP`2p~kL`I)IJ*f#X2ySXd4@RO|iEXXNA%-B-YWB+9@-}Kfpdl=~(C_qW zRq<-9Gcbr-jJi>BvV3)G;2c?9xh0uiUFROdSEzVH9|s1#Q=mF z&jn(O;7gQ_`v9dGTXMir7!XGR72f>9e!xn$%0&JF?4d+>u*VKu1L)K7KQ6u_ml^sQ z4=m^bYmTx+A@7FrBQ54=ppzGuxmg!ZKk7|hQ&#U(Q;!%*-_Xo6Y!7-Gj*94kb_a?U|e81W~)pbT`_I|QoEmy>HbUl*8v zL8S2PrzT{n8HW&QU_wzL&wpTMP4)_qpx(!9A_~>#YOIIgEu?>7up8-e*h2c5no!-U z+SN-XB5;Kzi!4T4Bc12lJQQ2w!ZUF$BoFmiVs(D(&&R>R+>RVlRKqSQ0i!xRV&Uu> z0S65>i(!War@CVb2H{UxvOQK}KRhMY-v9tQa23{1#edA+l^w-A0|NqqRI8+1ros*V zY$diB7JesrRr-(dUB7T&NDLT^Z4hDn>WPQJc5X!K`;N)rbKbG$Rijl(>{`IK@q973 z)2O>C=xB6BdcY;RW-C{FCsUavrRhCXnSJ__Se_iG=@d?SL8ttkyou@KBAlp-S} zFQ2{0OrHcY@gvAUv}B2p>8z&QYhi@B%7!9%>d)>@Kkkd-Y)@xsRLg)Qs71I55Y$31 zK1_(}V1m`&4kK(LtQrY{=ucSaHzX9V_n7^`(UAToqV} z`i>R8BcOb@RQcu=rX^EpplTG<-R5gAIuh15;{+!9onEP1CUUh?0zAEYpokKWd#e(i zW^ub4of1A<6;3gW*fUVJ1?6PwU}TVEW=A`hN)8NY*QSG`Xc?IpNHpQ|L9DmQl@!kt6p&v4bN9zbRY z*pjjx74d@rkYK?1e70{IQsmK;2gYygPmeC{>F)9l7xwj1Te!`i?63fkEUhIB@-h%% z4{{vq36Y=Q2C2EW&{to5?ge{7#gUpIBd)34r)IKM4mp#Sm_bqPy<*HSaKsXpq`{5#-9SYPD!b# z9Q?!mpJHqf^$3RL5FrBESx^uiWu?>JS;xCQyn_5Se76cSBrguI1oN^bq&b*g-@%px zelXK2GJNOP5Y%J|?Hd9yp^7%zkQ+jt_{_gql;OY~=jQK1kC>U#BF`{26oS$Vn8 zmMc9s1Q0_I4#0p3?Ot%9zbH&mI-^Zz%JY&zBtf4`G!@WCSW|*3>yg!jlqdCivDTT1 z_=wBB_qfyBjXVZ1mU@jL!f9cZ9ONvX{P09AYEWByRftVB0xIG_Ep<9(t3|BWK1gqn zJ5`Lm+|hDnN(OJVF?i8GCXNv5tYq*-Qjq-&mO6WdbUpC{*UXk;+kshsRR;hf>QsHL zscYV9j|8Z!3J}N~5DYb1TbpQDbYjL*l6V{f>hKJR=QW*c)aGq7VUjb>!> zl~`bFnOT*El7t%X-@+qsc(B1TBmF8fO9$BWD>H}P-$N?oUR01-1V4RRASY3V`FUA^ z)7HCw<=)f#W_X4qcF&hWu#Zko_c<3nd4gv$fZ%enYEE%J`5?OSN`Z;Pn9plM62S*R zf*Xd#Dr6ZJ87wWvxr`^n!t)dmEy{RH4yKSu0g}ci>srm1!{LkcYVI2D*xF!vEq;PN z5Rga%su_uD=0!q9m<@robq;ajXSzCoP5?HEQ@}6Rh1LeGQ-|zdYeR7pns2a95hG9! zZhUH~1NCbL5=hjN_&)6ba>TB4>IIBNXgzKmgjwva2tj!y0t7pvAI7zPKrOT|G1*=4 zr=T(%Md*JSpy&~+9}@mNR#AmI3A*I`+`&Hhnt)mgR$eRAY?2^p0-1g#AC92NO2KeuHMc@pa9gYqsub!z5TsA3b9x@;m_ z=#qr1^|=zr87nO}lG1 z*q^>in#kBpv8g4^pKzo;^OInNKK;yv-j;wfeiOxj971_eN=Qx){1$JF!T9Bj5z&-N zFcxHWvGFAaSj|dwJ31~Tgr^qTV|g8>K(%nBs@S7D-pa4%en+6TK!R$^>OZMOLsW>( zm$_E`qYa_3EbDo?Ndx<-N9_5`u;qu$$j7DlenH3#svQI(0PU+{M2`5I&MQ_K2w$pU4CMST&bn$n{stc>9nB>)B9X zc-2aENS(A-KSRdnVZ}8fT%&U6Xby3)tcYcVI#~ualS@eCRQfIHJw6#s0Zi;u)9Ayt zR{&GrOxJNWqAmyaA`Hkgg_YQw=6a?c^3^QA^L~XdfiflUYisYa-ak{IA-KSOuBl28 z_X!AtRv=tcIXU>TtmqEs-bd|Zz2rCWC$NveMgoF_k0mw8tomedVFBAN3bRDTws`|h zP5?Jr0pq-s5Dqjh?(V)PM5&3}v;sd&c1RlXoQRQ#X;8~Hnb4*dh{ImW5uFD{c!xok zdMpb{f9)f;oK<&)VO@;BxB8Z$IXRwMO{I&h?=uOzJ$tn}XAxT7cefkJW39NZ;egKS z8vR{R2(w0DfetOok+{@IrITzgQP70eB?-@vjPb~i!((`GZy4wR`xg(R{i=X3%z5a= zTSHGMrw1c5wM$t#Q`VANnBhNB)vFM*auH0qgdK+>gm(|U9>eq~uJ$K1YnIe0-G7zZ zK7`=--0|SL_Sh=!YY~IF#7yr~g$5NutV11p8(U@>;xlZLq8y6dSh-(`%c;@WD-B4e zzNdB@feZo!3akFyAIN*Gak zp6-bp2x_z*idyU`M3zM+N$G8E>>87C1}fq`ExN@BlrSI&l=@nJb4)q2r}GF(kQ)hI zd1N)XK8`D2(vCxVUq1xA`$JV*UC9W=q1i`QTa<_B_V3o53$ZylS#A6`KrrcI5YPqp z=PnpxK<-d(Nl6A5sytsX4-5ki1%I#)j8B9=(hcgTYNk`?%HUBP2wj~I45sWMx=1a( z@SHh7g#%SM(MiwnA}$u-qrx}(oe_f)FZ)oh&qBJ?e1TO~N5wtIQ*;^{Q!c8$MNgBx zjcW6F#8KaQww@OG3V5r=JtR>CBX;QZu@el}&wPkwBE?LN{P$W92N_8d4w|te#El zo$0bvJ}PmY!&>LzjjpLgTTYx@8hkv<34%Ws39R- zF;^1uWN8!o!;X)j1ARGEY)vtkh)u;H6q{rrNC@~2%0^4;Ei+s+Qq4tOya@5#eOCJd zeE$shEb)p_6@nzW;FJNb=3OF278;>fpDspOj2FeZ zWTIDIYoEr|XShV7EDux2Ri zy)sr*et_|b)i+~zFR{3DYu$SX=3EznCVwoctuaS?%lfMGex!&RVhA%1R+Y^eLLA=^ zGv!{>=w6xgt15fsmJQqXea7pqyzH^Z-LE`ohloug6XRf$Av&`jgYZD>=}*`o2%UWR z;5`T={DOs|L~(Yc=Byw`6Ci>GK%L=iub|En%}J-1oP$2Fu7wS;)rvMg5Uo7|0)44~ z37{8jadgJkWP*)^LrjGto!LKWV638yRJ7s>z>GfQD0JArNKtBcvPqElI+X-*>rCqp zHo1#YF9GiG3za?_LOIzXVeq)}QjMEUi`T*yP1=nhqp_7n5-xgN6z$7b-)lXY?G8JpCQ$UULpj|bwashTv6&c zzFU=Q)hmBD_cRfXwmK;-<@AF}9u1{N8Rc@e87Ej#9Ugmfm;MQ6kk0I0!&zmJ_GjxCOqO=^*rMTu)FJKd5}&-b&_uR&gke1QYx8s&9P$I3*prQx4UtMwAE?MOgrK1C zuj9X0sS%MCBPc@mC=P|@bYu;vWF92SO9`JphfIE3ZEQH?EDmLt^<0( zVCsMcO`I|IMMP)xh_MU=Y-qe-z?G)egsDTQK{7mOk)^+%iHK2>6K@jv=%NzFFCY56 zZ@7g-LpHYAqsyRD61a4!$DV-#iZ%R5IUU;vlfKuP50X$Wj;Ux(!Y1!%8&qhI>TLpj zRcATnb00@zTe<4t6F|oeJs`^9?#Sm;bUz9;bxzbSPiKNCm_9A1<^019xT_y$@g;fl zW(@;NhPf;;|4^>@^VS}&qtBLJy_~bO%6s>h@D2R;KRZ*XC<4-m-ZKV^td0a}PlXmS zxCC|-M*=VclVyLg(aBk|Sr>z(o_)1C_|uK`T+a<9Ab2czC6L^` zI6S(f1@z7}hH2N}zAB5QM}rVzw;|OY%qjGzkBeOLkfTz5{kM@6=mQp#1o}e`czS%{ zm>-}7_NmQeFlS;1d?LzvgGZpYtuO_ z3P`j_9Dt1jhg4jETRNOC%NT?of*uAToL;Qbf4o8+i$R|I)B%*nuaM%postGMmG|{| zNpXB-^2+K!Ui_rW^o76hT<`0ps=3?|2}3pW+aPK74sF0Kw~!kQM=^WN@k4aMJ2vBp z45ZCsfO~%irZ!?+5LjD}CBqL2(m;N`xKWCEMnT&9;Q@bo#(u?^mz6btc~Dehev26M zE>iNVXTm9y001BWNklz7x-x*v^ja2@&jh~ z*m{59e0+j zJXt?Vb8Q{RA1WRcp%MD!nKilHxVBv@uObpL6%W3QC`P;GwN9f=;=TRGOYwEssCa}$ zMD{g+(1{QU%`(u~Noo;CXZ^K8fFb|_;R{@H#aBng>I1j~L63J-%hyJ!sOBmVAhN&8 zFD0T*!Eo~h3($uEAkTk_{#<*n!C z6o7i=RSA9;2TA?;0!+5L-wHvOZ<3w!w8qp9>)r zCN8KGJc-$ADav~|?+b(=9kJkjd^VEP09fi}8N}@v0uD&`cjk4y-#Y~I#UuweL7q2p zfLl0V4L7)&1A!2Js(rDq&UHbtJODMd74IEYn#JQI*Z+AW1B`M{A?cL-h+c{& z{6XV$sp*@M-B?Ftm(PM8yY z>BbM_Fhqe)#4b)s?6EpzIg36kd|1vmJnvgxuncTnk*gIgawl9nd!#^3Mu@Y15aucY`a2wk*zct%kneby^qo*N zN7vsObP!ID>aM~al6$=@e1)C`&LYrpjsgO_Qmyi~e8&}%-`Gpf9hJuRXOfwe{Rd0r5ruQQk>e;MAo zOyBWXl(3!UQ1o75ATZM&ANEX z`I7!E3p1d9@WHoId=80YY*0a&g9`8A0O+C5q>y@%qz`KEndhpd(fgV6%lj+o@+y3J z(2o6VhwiZ#>@0qckV=Ze6EdLSmOqm$O(#y+hEpeXUy|$hM0f-5KZFEX(VmG6g29@`?j~pdbd!Lyz(}V8;wZMC+eA$X&IQ!I#h}wkRAj^n4UFoBUZ0k%hi01%*1UWLv za#FTdSWaW^h3=d&_W8tR3Gwr^zFbb%Da(?N*jet?cZhi9j`Gud=#EA{#X3X_>=7vr6`w~6gyBD;J_7*) z9t5?2Sb$dg&;I6L{%|9}=O01+$;mD)IJSJ|>$hVn8-ZYV;t4)>Y_wbRZ({{pjQ-hS(qC zKE!lR8@RIpFw17V;2X@YC94~~$2jwmOJQd;xhDc-8C96L_;5sdX(LPmg~SU+sN<1~ zm=IWH&g5}T_^<~P7NiwLf-+t_K!mTiS>hh3Qtp>y*l|$zb@9>Pd$7XXzW07bP`&rX zfjU)Y3+uoT1M}Q@@&WLSN>+!y__*gU1qU2{k-8hO@h2=n1_`KNf1D5k_bL1=fzjP& zK!1;(_ALYwlWNfQadbg;5nW;{h~3%2+9DD%tTZ6y$daf)vVQ`0p+$rn`|@_)!4>Z# z(v1`g@@q)x9;*yM-=iLDK*K5EPuy#c>WRXJAZO8+f3VO4fy~P(f*rd}FqZRH9>v}G zbK;N}bJ=7s%R6b&Y0)?ud|;K}1I8jv_Xd{!JV7iUf9yWy%J6{U< zRb12my5BBOjiC{d)Dk=d@v!HOSK^PFA z;NTe$78L763>uOy{S*Vz94J&8B>qE@Z>%$)Br8DZ&*`e(v#gucX?Y_!ET_-sfBpA= zU9#APR@rj?z=tS6BNUMrs-smM1|ylh2>n^Y=P2+bvd_X!FbFV4M1qdT4kSaf613m` z8b3adL_w|)$VH*arjhm)5#%!=5ALo;Pysw53>*o7!0+xbucVOXuXuE{6h9;WD0Q0o zk7GJt1b+Z-sPGSuVgU|^Kc9*Fe7=T2OO64ppO-)4nWbZIS}ja$Fd}9=fJ^70&*{Dt zVsq}#A@P`zW3V<&bm%oz3EZdWMVBBv552+}MXX|b>YT8kH3RC;noMz^YajIjIz&k1 z$xo;m&kX1XJGjK7*z~o4esf&A2U_t1LW0p0TH9d!>(ST#!7S+dSKMc4 zlD-jul~#X-sm~%>?+bKqef>(??jf461TR*(|BU!U(ai-LW_v)Y{a3^qU_BuEAYc0Q zNC5Oj>K@`0!Vi$368VpVp#PODu+QhucZks2q0s#w@x0u3CV9T5Tjg5=DRux7zGoEmG^aKtQIlvhmABxXosUJ?D4hdF+Q*OufTZ^{ae||M=_m#gVdzy9_cZ8 zI?LAr55kIKD;aB87fbFXipGunuu{B&*h+9WQC~ICkU4Gq6lHvRKNnaqv|O<16eWZr z3iS>#B;`wLbN1(SmsSphyT3?gJCY^o_0LNDHEGB{{BivGs5o33$vG4eEf&}5nvZMQ zz@U@TfIc9M=b!BV{{Q~F-M<%TmbZi$)t~|S$0#z+BF=b$8o{AOfsoaFY4odt;e|C> z_w~3Z0Q#YPSYPWEN&FnO&CmP7`|Lk&;mmc0bp9H)2T2(}M1I=W=hGhL9Ke*X*p1E? z4Dz888(e3D?Jp!hh(Dk|lkMe55LDoxj!!>n{5gF_%wZ9T(1(GDzDN93;U{=_1JU^< zvJgQ*PIJoYP@!L&6>;k|T_T#3?jdo6>6BE*SM1XFoE1Ju#ZnuI%|LO^!iZ!z5nV!v z@Gxz0WGi zBKRP3u2xvi*BH=p-cAQy@(%huBceH55vc(aAyg~IuK;RTNf0&PFNfkJU%XaMEc&Lk2bs@Afq|IX_ zbD%v@pgmC__lCCK=`*k%3Wg?ws#v~~{q;q`kl@eZ3%T9p0Y(^N50!r=6axJDeA@3n zBmN)`xsRH_N3)@Q;-7!Gld<$4nErLihNO7fHsvpWp^%abv z&-y#Y5TxRQBB;`CrOyFQU4d8KK(yF{2A=8y{A5ODolqyBNBZ+dt*$4(8ImL%t~|l`N68O zjHDA5t|?4L-pMndt8oPE_mY(WexN;v!a66eT*12TNtO2c(FZc)NzEd#VyR(E4KSDq zBG5(HNf2%TF<@^C0~Z2{{XqpWkXQX+b`?mI8wh9!^Z+XPM1a2h5az?h!~k~|PWnO+ zS}2S3ltdPuZdYc`GN99P-ljP}VU~UU_y6&q|Mx%t)93R?1|nXIPdx3vq6VZ8WUN;uTEurD0WHdGNhuArcXL@Cg>= zu>vgc1(JhKgEWYN0AE47VL3NNDA|NxKZMBGvj|UwC<6ggsLITi7vKb^rFvm|(KM?U zk*CLMgp_LPIgRCnip6JK^l4JXa-}N9a^7M9h?2s1fq9pwc_gs}TW6VuL@6n;f0(`z;NbC=ta4eHD%)N-lCI z5mh4kvkyoFZ|HC*LV`wE?I_Ua|DU+``;Fwv&IGBAP+B>HCe>Vm6h&0a5_K^^iRx)t zWzlX32)eKo6Q~kHDK82Oi3Os^D6~{SqYEl$EznkPwieK63ylGm$$jZjFrC)SJoJ!_ zLR&8)K&_4Cb_ivZVd%xd7qkAAz4!dO=iZ1+veasCW->A&G9vN^Grs)JcfND3GdH_R zE~qJ`0L&szmlU9N7J;D5OYoK3{I|pEW8lFLO`$hMVEfzQ(-$pr#I1DfdoT@992faU6+d?Cc(y}t~d(h zQrAO@b4r8`R+kIbV<@1)jbM5*45b?`Ngq=iFqjs=hx{Ndxc8VOq!S9=i1KhbI~@r% zpAuG8B>!N4hbkz|s&O7I=S*s?;~OJ3#!!O3h1)@nfzRG(eBD^euwSvXKQ^GMJ*f*W!6FQ3J7#<(vH8wxCd~-9=bw2Iw6tAu0|1vWgl7% zX>=BYLV^V^0re+`Hld`A@aT0MqC!p~8dKje%&@y6(?d^*CRb{nhe3RU%-57HyZbNR zy2T9W$c#Sdu}A-40y$Qi#{(RJ!TOdfkJ~M zDsjlN=%MBWw4e^ePWJp=L<%8TWxUdY=eHpc7{htr!Vu0N1u9Gzi`m@<1VHO#00Ns& z%gH+(@&~Ph@fif7t_;7tzP`>nbcd@?=RSFBdA(&!>JV;B(32tJ7=v)g5g02&oSSzu zGfXJX#va^A`D|pS^n{~+uUHgGF6BfPbvO)mI&9)UhqTF|Y;sr*Wi7p(!xE+QiSXlY z!hlMJJOlzTMM^OoqWpqaor4-uR$jpm5~ZP9z!H^5pqfa^eUJX&& z84_-VPhHUSAV#^R3icNWq*l+RgdB7hkV(15go<;;O(@?snwft$0(9l!&mKPhXAXc) z{#ED?HLpPC6Xm`FiHCI_y_r0;$2WfLWP#M5#TL4Wp{1$Hr=K7Kg%BhRh&T=_B*tJ# z1nM^kCMf0T1d~Cng)|prL=FaAs0Z`Fe=zvUOkvlwFb)I!feKRuN*#0&*uZAUbOeAL zc)1Ad6Da>$ZXxa&L+l6P2gne-noQk<0r71ngqJB;QYu!WrwXCU`hr?}7=R21PPizd z(xGQrL~_aiT8Q(MOnT^ehr?l@ax;K6bdlxc7)Zmzq3AOwoKM#$`C*|>_A#&^IMaou zDBdGvhPzgf4QR-12q{d`7y{(T5fs&$SrMw?IM9&_Y2mExMI`7j2`bd^7Q->&;W&Dw z|#QtUW`UAB8`ZhG)>h3zS~8OlxlW6Da@s1n~z@Cqvj9 z)AJ)P0tjUcM4ke1!fu96_p(vtQTL*$G)&_a(X!?xheS^pO$2T})iCJ)9L{{oJI9=d zk&7on${HfJ5^KVOb)QlS{6rxT8vjlT0v~;%gU6WCSeWywsIyMMb`CuQDij4etmWc; zAmq0zRMz~^AERJ;CDKt5B+rXr7fJI6&&Ci@sLHAdtuKmkF%40Q;#*Brxo=|m?2TI% ze}4OB*Z33F#E|iAG9U*8Eph(rDKlbp3m)8?ApW?z3z~BtocHz?vIXb~4T>%WQTkm# zLaK}MOyYT9uWxO$Gr&3ggH!GhbW2+ zKNyA)|A9LXJf!%ncRVO{vTo;-Ptbn&iIaas_Zj>6i*+Cj3CW$9u}8@J24)%&WrE^d z4$p-_4a;6TMu3p;DvY!a)ijF1%0ToP5>?_wqCkqBHRR*N8=I033vu#{l@({`Sq+a` z6UjW7b|=aragPeP2#xp=T#CFvh1!5D)U-Std%^kBv6h=0b`*$)l*)pQPEhf|FpOT+ zP>RUW%Ol0>IPM^&qsQt!gpfE%0BXV~^E<#ndhvswK5hXB7?9yqjtTMSQJ#uX+2i+~OYEMwADdV z1Q$*WSd{_CjLV{RDawHp+^NgB4wftvp)f4NO)>bg4?8mu;6fMdJmUQU;TY?dcC@s7RxshJoY}CVufLNW6$fL*XnT z{E&pL&SPr6d{_jf5_ zpU|v6SBoMzbtghl(I^6)2M!7~6QY6Hf995jpT{5G8K;V(7=FG9@WZbW9}dD-9dL#j zZXfAb94A&=&zOW5r6?LW(#}N?bJ2!vYesS_0VI)Gibo3(`Cw{ z9?URUqLUc71m?sH6>D^nUyM=gaTwC2BovYy1Moy6n6|nt%!C09*{#R`)FAT*78-Ko-$dUx_q*WfeytIvfI8NzpA=uKrDGg3}|W-@&V@5}Qupz~l* zecu>;$~sUriqbWAky4Y0Gl?iP#H_oUqTK84ik zM1YC{m&g7d*ZN2G;+W=mbK3nd2-^<*342KOuCVq~7-$7SMA{h=b`+mB5|m2uAGj-u zlOTMH>Cf+~=!8_NktZ<<6|kI+w_b7p^zhajSF<#Zl*~jPWRyK73UExwq2dF=oa-2t zF{x2hCJPHKGF-3OPDZOa?gG$p4`rYMSuW&22m%`l!CKv}*FXeoh_Q5uwV-}Nrzi+I zMk%=fJiufOG9Gut)NO%cH=OV(6B2tXEah==6QB+Okb^LL?bPsRy+utAAqm#$_#!au z1?03J2Tl-&K^>UmLdd7&8TpsyrWJ1R{;N7@}MZGBXeg27t<)-DL3@bA-m3bVd<18H-dL08+R( zW)#xErS@ZJp_*1`=Hq|Tq0886YA-P13oML-vQn<}f-#i~5pejG@-eG31DJ1;_AbW0 zG+^9R?W$5gd}IbRQDZu5 zuR3If`MI*`RnlD%JVyzBXU@HQ{23P1GNU@A*lWnu3k*0#6*C;gUm`@(fTQ55dBvnn zf+O>zphc0FC>?HHxNzYr-|+tGor@LcxUh|Uq2=vB6mO7ziu1xx(IBdrDf@?@=xzaT zvERe3=MaA$|JhHj_Opnpn9w6!!ylvRjR`O(+$`R2G0VKHL*ODS_Tum>fFS(a%V=#z z#ix7N2->k98-ii;WmowCgazZLv0(;)w-WiEcx=eH3(%2H^vM zI>>==FHoS|v$i1ng}HdgfgB=qDCN~*>ksw=>Jau|10c-JqZqVoqq1&iefbk7{5T4< z-ZHs8V5(@Bf*=J+xR`4GLn$)%2G5-ZdzAQV(srTYv3|%&8;0u+1$0WCn+pz5Hdv?& z03=k8%3>&W?A~(2c`tB!y8-10B<`9^Jnp_ywFMTgOc`SF~>}Tf$`*Mu4v3|*}pWs^U_1OJbvre zvlr9)aVLgeO$qj3Cx6Yf{ENu9AnA1!nKL3Zi;OxHW(nhAg~&q?CBT69;ONV`@Oy%`%lP^5-(q8XwejNexmoh{GL_gi^p6Xs~Km_MsZ2i-BI( z(Jjk^xF7=u`a%yh%@Gfx@(c6n#%!o-7QrWbIf`Q4=~2H9Z4jdv{rRW)iqKJD*dAn*PpB|;U@+tU;g!dKiwN}a#={p)Ee{`t zS!NOm(i})`8P6J3g@p8ivR0(!WTG^~vL`)4f`ll6*n<Od|Z4iMB8!wiODU5>XXVMSgZ;~5V=I!=udZ5K2kfS?Q$U=YG}GvOX7r0x4cnII9D z;YP-7-NK|7avfBv$PV4&QZOufU(d)0ZMRx>xpxOYpV%O*Yl8Gwbi-9?giansMd`|B zLJm<5YyRbLkOey%eTI{wtZ5sTVGivuO5De#8esI1DKQ}2ULlWEa1~gNRcAOlKNVC& zk-Ab8KI{=~_r#yG6_-PZgU_GMF0`{;qdM_r8bvXVI)vG2>UfPI^ht}YU(epOpyPnY zT?dFkr*A*=e_Tu>?p6dwfhrQ5i*dt>C^Rb?G0~mmMHJSkO--%C#FRvOfB(fB5BYNA ziK}TU3bF~3@+P_}HCJu{_Kc0FA~ef)Zq*_VW~||7j~EXzoorD+h91c%@NyGZ%8HZ4 z_x4DK1}@ZceSe@82LRAqE9(ma0iI+e-elw|%m`KBVa_Be9T(4MiLMNipAO&|3q!EC z-3BvZT}*fpT|yIdh6w1wvJPp`EK(r`by|J&C!$S=Qt++|;yOfMa_OjwuSo3?0VoaD zDh8ApfgfLt8kJAf$~nt_JqFYyCmkwzI)b7@sWpwAMD!5eY79u@50^Rk1eI^*CFi2= za)`=w1v-nrdCjJZPW=jTtg0zH8YuL-6R&8)ivDNc{nc0R!}Y88uRQkQumAbzCSVR- zVD@y-dj_)DVUj*Vl$f)`9;PA)AB!NZ)?^qOPm9J(sKA)IDC4eaf9oX$Ko9?XEJ2tV zPrd4FQbc$%1va9*aD>1oxW%6ZU@blk1{m@l;f)K-7KHIEsBnxjWv~lE5aJFqAbXB4 zx^vl$HQ^fWpee9}atx?G$b+2vlkwR}Y=*TTBYAco)sUFt=KJW7Mx3#`k|fl{E!}}z z_F16SJjH>OF6+{W?+i>V{6IHW*CKJ9e2DnxN-$u^3j`qO{mid84Qfw`eVNopW2xpr zVR8&JVTu7wE2*&8vTR6fl>sL?BU{#lXXnv?rr_S$mrsQ+f%IG!!-A9X2tW8&uwq-( zPRB?#ZtUF^Z5p|hb(9k)zO`9;f?7Q`7vI0xo4pA_&&}S^KmYyh9~~k8LHHRU0h)dL zN|^?Jn?Q~#LLE3HHYW5E8sb|KYblySp=sN|DBVQc#p6SE!XRPxgApvv4_{y*azGwsw1T^E9{&oDB3;nVM#G zrkG&SQPNHmi>aAx>JP-*Xr_Z-wi;mx)fszcUis+{6#zjhUOQk^&Uv`#_r3sw6jNc9tpoB_5!NJE1b_zFvuPUC=e`R0&LF(JPbhV2n*dV zdTp>EBE#%EB2db)3_%dJvhc+XI@s}d5e9*)5ok~g1)VMwanRLiQC)_hb&S1murD{y z3%=kT>*1GW3?77^<#m&&ELTnJK@B`LDKntJ4J7|4ejhVI$!T*PX^cH(W7h0!z7nyZ z2>I&V$I-4J(SAmDznq){lPuU_g$(FZb|eDuRB+SIzzB)z$?_UiX-K69GeU^seTzC> zBF$S+?(>_o2r_WFJHIx6Hv%7fcXae*e;oS@BMKDaj+qujnMv@YMP5y9LVlxTpBiy7 zVzYC|t>E;7-~l`jeReg^J8)s_7d&_C*O}ZFI|coA9eIGOrU#7P`cI_C)hp zSmadLp70^9IV0dKWW2CIt6c2W>B5pd>O$8-5DF~_K$w!s`V2w9aVY!V6=?`VE2K$X zL%AbDRB}X1erX(M#W)|IQRW?=r`1OSL>vh8pN@{b&=XBOh)ch)^YeO#Yr&RT{8^ss zsM>d(eoq5{LFbQ3hXoo?odK283)&khx^%7SFx<49&Q~VHUeig{IWQ=CjZr!bQ)d7^ zC5B)~g~$TvDzB;-76RTAC6DynNmv$tQbfIhY7tgkK_3t#e=I(b`KsshU8ir~UAsO% ziU7#QVN0W5r^fq>r98p-HHAD>_Zin%Osuvv2)+ac{!T$r#uzcKlXU+6;f7cK>_!Mc zH=e!NH;Msy)n?4hM$*|jyz*p;s}X|NATvz9ERO7TCA+SYTYCsGd+#l%;7bV4o-m^Y zg+>b?{#g8RT|S%!lu`Z*dzvyvbafzx2B0nu3FyJH%NvX{Nv>z=yf;cBVjk2*i5rqr zNO;KELtUP^;I!paa~&>lm)>JYcc}mB^4z-b{`?8ipN^^ca}NX{_5USj5TjDWfV{yQ z>FG>amSx!(Zw2CXS%aopqTG9Pcn?itg4nH$Hjo={S2oxU&#K2SgO(gk3~0;>5JJ%5 zuwVkD!Yu|I<4dm^fQj=!?u;%B&bkFBoxpMd57J|_sVPWYF@?9%6#hofAkYDsFZ=H* zzUs|#(#u|cb9>%1paI`TOWVJ`m?{rV5$BE?(Irx88naDd;>n9Ito@GZ7n-}km>}TE zOu&4`MkRRcQuoa_pb>|^Jbvq^e_r;5&j_-JuSC*V{+WDWrG96}nGU){dGIHUy?BUO zkbugs%b;A;qRJjGVy6uvLcGyl=B+>uiNKeL8Ew>n`m8{=EL8Mc5+FITrrRR@IAgrY z`UqEDdC`o+nR@G)h9XjvL}SL5^VH=BNA+rn+)N%I?y!MOKbhlMGN@Mx=70%rl{z>N&cuPTH)Y zJ(0(tX@}>^vWjCckbeYFsz~-Ng5t?AGST#6ECrKnbBWwAk>sO~)ZpeTB-X(>M67Yh zfKCGj#BteRX=i)s@3sJeiYV*Uq|Y>{GAdI&Zi%om^?Vb~VI!lQ#xVmr!5FNfG#Fse z5No|u1;t5G1P(o-DKh1mf=~5AVj2)uf~`DSnW9ckLS!h$p~Yp)q$&NXCqQE_JM(MT z@191N!HNZ-rN>Nv+>rVf*(M@5N(@#V>>~Fb+g6Q;Em3kSi>)_f&x;BPkIXof0dOWY z`_J8q@#o>KpS`h_vSE#PD6+aHB$~62z=GdezKm5)O!{^iAV6GBkx2mNb6g&A1b76b z_B>Y6gBXKhDVQ7PhSKCvK+X)PgBo|9|lbylo-TB+sM=}1Ku59mYZ~tb? zq~oSscf@wa+8iU_Dk@VNn?O%-^Mw~fxz(MADihKqS)Zv)mnbm8o!oDGX7TdMtvUcb zym9NWgR>4EYt?;wOFg`C+~r@?}^Jf`G+m--ONC|@N1U}l{$ zXq{VaI0i%me{HzonnC$_3kSat_Osk+ow&wmJoK{APL{(hgqa9;8inJr zqBX{Zc_sC&F+p@DEXl+v)xZRzVG2^LfemgV7ok5Kh~YXArxAfNke>;E&{jhp8=*lcNP`$e zVHreQK#P2hMW2KmOmBtnX6%z;`hN>Fiad!eQJ{IK({=8;%9UOOKTvofWXOU~XB`_r zFQfHmd3n8KlESQpzp$A~NCujCW*R)wOxV<~%GhWhkUN8uVR=vE00R<%gheI6reqig zWoIEzc|LGz?kL@$Ui&@DdN5YUA3s3~R7anJlw`vpQmBR$ap*BtOKEm;Se_gny4y*4 zc(PX)P$m@&)L}~d@8AX^v|!EX;Pye71#>I69RO`FUFeTPZPxb&j|+DE7iO%_aAiOl zM+pvpf{(*;fy~p6v59)*Wns`CcxU_O&W(pnmm3fN{6y7I#{xsG#f*tX2U8;oIv+#6 zn{I1wK@lBFts|Uxv|(Db$Fm-yNR#Hx>{)-Zhi2jyk9Gr{cWCq*WYX0p&3EC+c`Dl8~AW(d88X(Ufg; zVobe?TCG{7{fO02^Ph2mLB53AOsN8B(r#0;_5SCd|MTDf-EaQ>@BZ%ZzyI_*ueH7g z1(kHvIuVI$3BpZ6%u2rsY=@(r>wh~^3bZT57>std-F4~0eNiXJCib9?Gab|Tbe2+n zB-13k-{-WmIMJ;VK!q0VXW5BAnW@I(n6KAL z^u(+__T*Xm5M)N00il@3KVCD#VMBwjaza|n(w-y)j#yf*$ua?FDP!+q8TP%O0zt!O zcTyR78yh;gRzppG@DHZSaad@1XF?8W3QqJ7AN%Ft?b)U6CCfpUMr%*K{_*R3WvW^! zu(LJ%iKs1yPA&O2{$Vcwpo7b|cLpjba|Fl%kc+{#`VJ0#xH9%YG&Z4qK8pNofEK`G>`a@`vO|iDJZ@&A(h5*bV&~t}r8VNrto0W2Zt9l*w1O}8f@T9D}kS(bE zyP`XbKC}waMglUg{RmZpU<#W+XM{u8Y#CaawsZ*A2^WbHWdK1yjsQCP8iQJ>6=g8c zg=8qyk64lU!__7oW<+yN@$o~Q@(6=4>Dc4LV*)>K%~2Plabr?diuM9Ks{a|!yz&>B zSLvuTA`Qd!UhUk!S4N#r6UT@^Ai|rA+x$Wd7NrulLk2XQQ1fv%@RUP&;^w4S6oFMb z5GzE8E(+C`&>QsPjI#gMYSOD&aGD-o>Gf{T5((K}I(YT9k3W9>qdmWq(m%$gR@4-@ zXVeS{HCg&q2tc>5AM6~RGW&sI)R6-p_uO0V)E-BWqC=nHlGfm5Tz9VWom6A%?LqP~ z@mU|kPevQ2SwFnod8wHJJ-qRgvYTrD;t(f=3L`h|a)&*7fbUYR0pVI-nw0wXd{i-z zbuEUtKTvxXSrQ`ghl4Foj`kLt(qPPzuvr+?dAfoys5D0(G$7D=E7pNJo)C38L6*6q zF*Feo?vR+nOR%wnBKV_`HM;0%>?a#GVc8xH?DP=jBdT zR7KQ-Nhe99@olZ#FXK#%3B-yh4Kg!CFhLk0h*1nEiPPn!ocIZ2k4J{2W}O~3xEqy< zbDr=^$X8@S3fDGxmK6RJJ}t&PXejX)>(4&=GBqN~~M_GFE|eQ6ocNGs4z0a`*4daIvOZ%$*P_TX`1 z6evk#&nC?KqK|F(S0}m*UxU?<%cl$a1sFhc zha|Mg_?Z}=GOEMod?b|xAoDV*5{c;50RSyPG9DCUMS6UgwdgI0$`rJRln6^w7sOD6 zT}<7`gdBlk^LHF@omwMy`W-J8i$l?Qfm$jphHhvG!diaZQdkkNAte=cg5Zu_h?w*u z=QC!+GD4;eOnL$K%=t)cS?Euz4gJC~0n^YUL1KmogJM&CY*O*-X9!v-uo@=&bTTK1 zN+mBM4FUAoPdxC{gd?9LLp<}i)`Send4e!uV+|E+{$c-UQa0Alh73qYVVvSBB*oAm zX_!cbWw=OB-k)`a5~#rd3fRBdwWnTx-9}-lKDVBwt4?%kOkYBCjg>O z9H+CuPY{0v!U)za2OWG_4|A1YmZ9XYQCTQy0Vh1~Dj0Iif>kOa+@#|C!N?N*Sn#HgTkeqBsmQ zy4P(%#N~P#65g=zoG~NX^CcHjoci7Zwg}2_9QZCA36oZ?7OcagA2S%N3mZ~~Af@tT z3_&dwd~r6O`ZH_b>7$75qA;a62Zb0?4g#w;HmLI|*NJpor=MlwJIiGJVfcA#J*z4@ zFY1k*CLl}fDVgLmk;zQL!54y1;@J+9qI&{PC5LH*SzZweDGf$viDE#BXGuv7f|3ad z`9$z3sUuUO;3tN$q!y4#8r~U!q8u1iaD~$Hv`c_a>B(a~m!mpb0`hYg%Z0e(_i5Sqq!R;?rPL(+t6zC-spni1NkHqAx25zL`@=d`A+j9)bElzBq zQ(TxtYBEoADD>h}T=5cEnR<}3r+feEjY){}@Xvng=k4q>fBn~2Eo1UX=V^;!h{RVV z`Vzkx-XZfMwmc$Q6vSY**+2V*NUm2t&_rrQkyIvwHB zbFd$}Bcwtf=upk?Ix(Yc8PGikI{V2!Od!HS zLc};TRDhF|JjbF@BFKfDC{T<9nWBme4{)BdOrSss3O!{FrAh&=q(N><0u{XQ5_Dui zMEv2Z(y>6#_`Fb&_Ah?kn?2FTD%7uz&c5=%d%Be;Cw)IUmr$XjVjM z%)!IO0?_u>U#3~A;fsFyi9CpG;;D=%E6gqkMHGgmdL==X=M}_yOr{R!A9hECXYOyk z5dzRpKbRf4>uC09c4=vQ`wP6-cQJc(^!7iW^!tj5F~|tPN;x(ZM&rXXjj5vlFz+F_ z6cK38F`xzKVQzWbAq8OzzVb^Xp~av}>mmhUZhe=GgnNhq>sSfTe&kMF2n_mTUQxMa`TO~96YCPnv1C-OiWWg0W(JSu%Fe7F#($0-l5dt+EY)h zU3&G^SKqaNm)0(CuN=+(!G~KXeMTIA7~wh;C$cV-s$h&GL3#J04*BwQ2=aw{>$se zSRvMJsah^JN!#x)qmICjioVvVu^3|?E^VOy2TaZwc{zP*nbBu?y_Hpo!KMvk-^jru zkB68-flv`vJclDhPPopLzT3f1Y~bg^xde{crHc|C^H_xBL5X7VN+w5LysX724q-Y-efd!xN)OLTXfJ zIz}CdLzIFeC%Pv)o^$x@Q@|^X31#2_3z&I{lJtXHvF1FxO$fAe`KhPAyu3!2%U|s5 zoSyb(|LXHu0ex`~v5{GVOleV+F`{jpi0+ zq(W1tjxII9Xc7L*F=VhN%#~q26(2!Rhbu{GJg#MEYX<%2yQ;rNhe=ST%|#ub5EH)C zArZQRzHA!z9SP7f+7K-!xoC{5-uJ3Df{rhIG~6vBKpN^X6)+$kpnw5O%SM54O=)-l zi_NkW4QM|BB*F*m!al3eA_PUkkPpy?3_Gj?c|MX1%g8wtU`?rVX^Dhwx|}}oVo!71 z)iSDyPwKii)WTcTu`pDrp-IPxK>-Dt1{JCJXVM2xUYi{ZM%z0_7JZIJkb~b@d-v5# z@4oxgQx1S$bK{lj#!L;e_7q4$uy71$5T@bnc{|{CKsQGufI~s*_K!|d!kexlKpG=b zu0}`$Wkt(9q3pt^zYzf_GdkBrT*o}f+|~5aWY}fa1W)#0>$y1R{@V|H@c6|SK;pKy zN86*NmC^CwboTgobfGI!lV>w&K<%<1n9Mw`>U0;+Wa|As(3iAmN<2|Y+?>EtmB&`%0>ig zQRDi9< zU7A7eGX%n8amSvw`;0^Tz=bFbqchrTKrS1`Vv$mWXoWXSBRfjiQdDxVBv~}!QBms+ zpRQLrQqq)TPiiv_PU)hSgeMuA3&4CDK8ArXG{WpoimaypSZ{W4yySkwmv%<(_k6|T z&(mv{cP>2z6zDZeN6f{oEKTDkHj1Xm(2{Yehscm>C$xpT1AEyfClItlR2G2I&h3A5 zf-uufeG1BCDpi#V1A;f=DMRK1nM}uIQr49k8F>>uI%%!?$9VO~0aMqx;v>$o-W)k2&BK832STGtQ_1Sm25Ujy%hM)@x6C%ZTKk+tcsbEDg^67hkpkyf3_F5@Q zSkaN2*dx89EK+qMsjpHQqP=3?G{Q$QY_I_#1ksRN6ZlU9KjE(~=o(L2Y_QB{$*~Xj z3x2S+cIoL$mv@%Fxb*H*FTDQ3-(0w`HM4ekODQPv54H+wngk(aKm*NyTm-hWBn;?y z#POHC9Nhl?Nh%>!m$-^pgGdn}4JZwGg-|1THJL(PC1!PXGb=JzUjP6g07*naRCtc+ z!lZwy?MGm_F)!AW?mzsXHv;V3CIf@Tp8>fGoVdPi<4H*BrCl0@91o>z0iN)L3`h%B zX{Nbb>SIwy%(_`?ua&hHGNeEY1UU=7Ge=k<&)uR?8o~ijX z(1bvu1a(x#OLA6S7(>HHRld0)i^?2Zbt2^9W4UcNu*tLAhE$(9bOvm=mFrZ7fpr%S zfi~7#rs7VV9$F|<6Ac{BSVXz8LS$}_|GQ#2nm$- ziT7-l7?~xEL`j@3Yg!?3oyUh^l9ZkhB_-?AdPeC*xS>kwCrYtK3`32Gb)%BfamuFz z^%nv^RTBg?(4UDRSjNfb6d91~g)v&84A{Zt%Oqu7zI6H0(|_~5U*G=6mF?{h_q?8) z2?B^@VPb=?5&Z`l&@q%;36UGQfo?)S{c^(ANSSvF z2QF#mKQMF*X4DM#m! z12*K+Vvq&HfD9=T`xFyp5Cm8ef>erdLsSMqL=yHMlthI_peYH$7-7T^DPdh1RF;Xt zExRSUT2?~AqB#n~;g0cR8lRDV&wL76A^;0O?p!$<96J`Y#5o;{L6_DpfBD62d-=yN zw^z15be@*X`)R^7d2oVcxlnIG80sYv1>bB=pW` z^b>i8-d2i@jQZeLZs;qR8q?Tk!TYYe+IIwNyW*gR**6+(&p-X(TJPEu*Wl6{4F=p} zAKvTH((G2&XF;n=FT3mQM^Sv`QOGEtQ<%I9q%go{*Fe4tl!wMu?jj#rT;TGs#VlxC z#^a}EG$6AhL?A@O;0^;MtvaaiXs(QE5K<*u16lM{mv#ye2bfGrS zfIS-a!6m^5{`LD;ECV89 z!dWmIjk&bW<+aNPUw(OeZSD5|eRTBU$pfGKO}okX={gn*30FZOuvY`@|@X3f=DX9}#7frh0uqVVPkl1>z6ElkFf8PQF< z$`9mAP8YdNH0I%<^}I{LXWfO9#TE@>gI=3CI?tE6*TtMJ$662KFcEvak+9XmD#EVV z4yCzAt8?PCpD_kc%ziZHh$>Ws%!tD? z!w@8_htY?R;TaG;3J012g~$01H%lZ#tUSZA%wSF){X&~?-V2@absRKT4i&txCXKNc z$7spWo2?Vhv=i=xTa^@MiL8^9!+Ixrr%q0935M7xQ2P5&q zo*GC&y>jA_-!8;0(A z(O9_8FrYrnbIQOilmy!;rX%S%W(7EW~QVM|@Vcmqutu-r4@bq0eOpJhv?d*+6VK-(k9iw%}60HOW_4CwNQ8Xl0*QryiROX;oh1snI`= zVSq7xxCwHB8Hi*gokO$ea3%wC05tGLwho47mpbX^o zE5Z*JZgi{#zss?dQ)57~2eBT;pt14EF$u!L9mg|3cpTkHXvXp&2QK#<>bL;RozV#> zMHZSiheUyZHzf=c5;zToq|hp#0^^X)ZB^MDrm!kfZ6pSh@~@%Ft;rhib@o6r6yj6* zK4pkH6+=)V5LB-RGc*A|P`wT;03iI{_75NH&D!hD*_)>jc5RcJ1&l10pL$_!>2zle zDhjp_zBu^ei-Vn&+1~qy{qQtqhp*9eM?aU;I(^lnQ89Wx4Zpo3_=5}x^I(<%S=RNZ z7atfO?gdw`3d0GTc2kaQeEu4+sUNr!Y0{OGH;PU1%w>maFWmxpePuNrZFJF z9*(eh*TO^^P%&2HcLD?2bSlq~^6=%51F%g@&Aam)vttP=LPLv7L!29K;*94yng9)J z#7EsK-`u_s=MMS~QS$)_x$y8KF>ny%lF%(F+{<+9+%ipqaxlRlM4*Xj zuz&^iw|X#8*G(|tSVUN1BcM})*PeRn^62#R3&(-T9=L78rC#r`ex|!rAOLh5OYHTJ zxG*3~fFR{&saBu?x$y6Fa2I@t2lLnG=PzBl^y7Z&^IXlUde^fVqqtdshK5dNIFq~T zV-O2qsyla>z&5Sk0aRqXac&00>bkv~9eqf^jiikyQq|U%SDh*3P6LS1SQE-uDIgY7 zpceK;1TT=gTacnujKFXlc^u1d@x&=V83{oy0^=Mvp8R&nopx1H88=1`hGKylM1%>` z<(wjOz0A74`;TDIx*xZThLy)o9Af!dXSrEihtP96!_te)wC1GT6hcD#utOiLxZs~) z;Xoc;v|pD|!#9#Bq6IHeOWaimB5Bz1yUZxbCs2V(%8PA6T`KS)P=v?@M05$L&ZZ+q zoM#_;Wkfr^2 z%v22WU)%nLYsY$|K#K`0m;-Y}=!;92E^psG9er`>)wM67LE;FarE5?2EQbO^|iHEU%m9bJUWWX83n$WKIN$7G)~jL zwC##`St{u=Lm``X*K{>-rQRe>2bkmoIs<@CXSXjX$l*{i6Q8wF{v{KZs|C`2H~wt9 zl#Zl$6gp}wW|RYSa&#AaZv=&4;6OwfdT)UfVS6qEW(mcf6M(7Ws#8^%T1}Gb#B{Lm zJfJ{=LS$52X9O}`)kVYO$vSDv7B;G^rAUuH8fn$*jA;;Yxw?FA@$6v8Ql!isrJ`Tn zLPL;XjqweOv1U@Q(+}_hr(7~Cv z01fLD$j4xDIzDaCXC7?z{4jyaql|4aTxWU<52KyiYnLoeSZIO=XJ@bUqX@vH2ta3C zQgK2f@fvMw24sQh$UTMYN3?T$er^7`ecpF}>_d)h0+-{gdtcH=zR1nPRoB;+M#ZMu zg{)F-S=!JL5iCaM*MNMt$0G}_-{0!9U7(LdEb~Oj^aH0hqoZk#z`9y_muM2>V1yj> z_H>~#tc&rN?ufX!Nce-SpJt z11SiamJ8#Ptbf7h-qr6l#6no!jkn8dm$!Eu{rLmXZytM4KcE7jKvhY#T``58i>Ie= z_o)Bs4*7uSEIkGQa?f~ue(m=B-vR*Xc%x3N(n-R%e<}SSQqh4`;2uyxoMh0t2n(sw zl9{kIc|ei3&21-J^p#ONU^>p8749STZuuTx##yN#+;{Ai=VXx{m#LLSfpC z>TJU+?p=t&^akiVs0mqAnrpahNUy^=tS;pYoZLfq#_BuOnBb-;#-6yab9n*;MR+r5 z;z4c9z*Xq(>k`({!VCmln`LlCPf+5WKuC1pT(=MIJKe}rB7AIFd{Kr?c zs`M5iQxfOwIov8e<&k+YSNj(E6yIt1@!-Qs(8M52JW>s3ranRY7iKl;FcRVTTu{`s zLiw=EJ9jx*HQT$=ub=j)Kr}F|Amc0Oh!jS)9GN1pU0KamAP>1V2m(h_! z^h9UK)-!Ay*724i8yahQnTCZ}}cS&g|^m&J{`x;&tY@$*_4) ze9uMT1Tq3LM#oq}kOCYsTAL0#RLXqR4UA|pki`*yuZ~u zJ=KFH%kY3SLg|hxi?B0aez~(Po84pvlr}S<*k>JvU><CUI`*RG6Qn+7Jx?E|K{XD-)P@<$Qjed zC!THv^4Ls(mO(BII@A*fT7+c$-l85Z9#dh9JOYN(e-?0D(RCPG6pVi@Q;q5Cw94Nr z$Sv8k-&EaJcb$7*Ec?tjRc`Stj8*|5-8yH@+;C&YS=dY?0h*)A)6V*w@AJ$vp;aIpXc0K-}M%{u;+9HN!9 z-91)|HWT&>?Yqoa0*QIZj146{Px4Ko>cE1;{7`v-Jlrr=;Y5~{c+Hg_!z9t|%N){x z48#HurqpOWu%sAHj=z);R7^4F*vtJ3J#W_?C>jI^^_^YgXlzv4@ogJafxh%UKqB1U5m}SDG+MYT;W=1ZX+z?o5)i zE3;UJ)<1wf6)7(y$QZB66j}(<+O%5opf%w(F5;!;i)zJXLof#|JZXX-mZ&L7Mrkt0 zlMNAAybZ|3VUVd0(Z;JaLltt#ol2ew_fho7+n^!mPI)w5RUk0gg~Ht+b&r`ZPQ(-Z zBnU{D2LlvJ8WUmsWtk!cp$3G7paV5PDPWD|BP&ZIR-|`Ej8KE#V`-r5P?c6X9qeG~ zeHa_Q_r%-q6vTj*y!Pz?2uCCXA^J9lU`?5|G!}3s$7I1HSzSP>duy~qs2_xN>7!~u zJmlhvWk5TRoro?KAV?ZN$Jy{>;xxQ~u~V3wz5+KHrKd&h5f?KACuIzD__NSq1%`SU zuD49WJX(IwIO+kX>uOQ8zteVOSx_lDjfdlvX>QbviuPNM+xU^ZRIJ9uX1E7I&L?m2 z#T|abzJuyJ-?4#LK2GJOz^miRFONQEDg>FcA*cbhYQORk0|HjF55$I4AEH9~kA)#A z#o)(WqRep~uuCIcfGz}SGT#Lf-wVnqKC)g zD9@+gj%jRE7x#T}+lfFwo|;`tLrFOb0Ml3$%FckP$NPG!asb=!5IHUR5*e9rxe_I)Y zjWUWf{EhYIlK?#80PGRqC&I7E3}}i5eaoXwW^-d;o$H1Rk10G5DS& zsD=uBg0e1(&uEU3g+XcPb!NwJ-0D(sCnQx~RH~@OnRiONWl)0vf(j->Zbq&V4+`N& zv>^JAsSs@Tw0=SR?%?KNaJ=Fu(6I}O?g~)#o(zWQDaK72P%|E2HGHo(3r|4+G#apB zcyvTV^SJc?!NL6XS1kiN0}rM$o^+C4l*Vqp`VLW0Brc&eefHL^M-0IR&=Y8BWwgD8 zNx4|%iQuvpnW5J~<4vq;`IggMn@g3T*j&st>Y$!KZd~>jDbL`Oc10M{_GiOco9C80 zCJ`#3&utT3@!OWPohCdsRf~JXzeUKyK!c#P!J}H}m`hc3y(RW$7jrpJq;XnvRkf=; z^>E|A*7_SB%>`KU4I!wQia!wpayG)vWHV_DzDgoUsxCh9xv~Ak-skEAxs>#8~%LUmI!I+o``I(dl3%)KMdUyt4W2@Hy zKVB22pa|+yxpn;M&DkIeRvdnISfucCJQXNbkpaDZ`gYG1f(>{SupJp2)gJ#Co038H z-!h=vYnT4?@cuc%s`KGd+PIib*|zbqN7sPddwbjU8rfd@^~L@qJv?lvG+FjZ>*j$l zZZjy{W0U0;=i>K*agUiE5&U4!9WJe~oTF${rwR7Ckh@G4cuLarDm;wEpdDyp$XPOp z%=CcCdhBFMaLMLx&2=_5HrCg(!i^SI6d~Lh{oM|iO!S}BS4TVM%{N1 zgCN9LpM~EHY0y1%K$CSEnfq`eMsk=<0C{nkbn+c9)9i156fm~OCOC3H7=)($+B7?7H8HTxfYE2 zEUj1)biDOIBM1+Z5vk9np5sy!sFoxP)ohOD%mad;E|zD&K*lZKDg%3CEVN{#Q%RGz z7)?yTf}#^Wn87bwT2w{b!N!SQCtVHaB&G^4%i+2W-u`5a0~NZ1DV`Nc3bhvzywD~s z=bJE~>F8rL0HFdcO|<9*Rk+;bUJ(V*nO4VA76a_;ur|fG`ZV7XwQrP>ss%LCj@{_sp?fs zkjG>Og1*p}0L{|9caC;;t^uQOS9*tH`N4*RE2c}W@ zj-)INKWWIA0-HmqTt|@AM+8FIx$FD9OVh6oxczXv99E$_S!KUS4NSu{uZ&<}Yy&cP zbwFe*^zIXZqA)s7mlkp3L%xWB5MCGWBZf zA<9I^nD!R-7KuF-L$5N0e+4G!OEd(L7bxL8Sk;^ktMeb3q*ED?g@+@|-+(fFM4ig) z#4#WV=?(#ay7tO#K$@TqAS6w{+q-4~NS<>9YL8FD(*W@!Xo_gz2RP6lZKV&)bYu7L z3_(o_(4>rM9OQfJ_6-oa?36RilQXVbKjlAosxdW~h5=#4hRR z42sOgx>P-EIFnzyG7aZ*0|Sa5Bzc;@1W9FoSqqCqNxS+^mE`Szsq%L9FUh~yc~`+@ zQL1uRyO~}1PSv)^0}M*OsH-(Cp=e-04Zvf*EeI;k&44!DWgn&`O-i?dO5z~_pOl&j zu{Ro9NrM5%GN1(XpZ!E-p`!4sjFVvXUL6e#i1eYMZxx-00cg1Q(MNlSWl)u>+E6*q44uSkpaR3RQ1cT>={QR~nN1b0gSi5xTj}Ft~ECl){LbXo9PpjsL?yD;=oyCAY zkbXe&VWP->Iy-x{-)LV-8_h~-#KO`^h*e9`%NGA&X%NGsY|#jrLM3rV|~ z#f$WebGjLR8m<-o+bUD#g}d5|MVQJ??7Gy!Twdk&0a(smVjr|5t|eMEW^!zG)}$sB zeE^m~X}=@*IX?xO(Xp1wyeClNjudErQz+0T4Uj=YW+a%J-=tH2)8P=e4r0&|P)U-Z zw*5rcp-`PtmwSbMq+xG>6u0STAAR&c(<*QQ$)QQ=sfM&Ed7vQ-vr~mUk_JmAb_i;q zL+RDY49KF*4gt^rs^kHH+>p&nAKo`Uxi-A`{L2LZ&{)e$H3)(|{&MT{YdtnU4o1j; zMt%s1BXmeFK}**8wfWnwBpH= zf`AdR2?s6GD*x_#LYEQsQ3MDtfqA-2w51x%kCvQX-1_k!zxL5d!qFP0;kkQ9!Ubvc z8rYFYEjirPjsFNpBXhm6w(r06q4#@e$qO z%ZdRNwajRkBJG#|g9D&n5&^o4&Cdn_`LYaX2Rg!926V8qy>{u{EtBd*UNI@i`~6-h zxm`VbV+ew7XAtR_p!ianwwx&4GTb4S09-IHAvJ`8P6jI zVhyxv2H6f`3(CtRE^pF07!hm}*bd*oHAoWFWOo1nAOJ~3K~y9NBKm`>5BP+J z3{cv`6Hy;Vqc{=^HjxJ`bo}=VfBL=GUVr@~+@?x~L2W(xv!%5V5+JEZO?(1OxDenF ze@s;a1nK_@X+X^YbiA^?bIkp0Mx(nZ&N!FyhxgTaZyC_VPaXcGjRuVfk{(=C17jSG za17M=Tpc+lv}HiIZ@X-~V?dhy)C0WnL}oO>Nc_!-QosE3DFV<>o)9SNfm}9#)R#|) z4FDdvD?pE@#c>I_v0{e+PH+>Bmvq3k5Yn?0IKkzcCvrsc^`MFUrq#R`VYh@B3w zTl3Om4}_28#DKcpG!5uZ%_oMF^ugAw$V@iY+73G+qFU?xK?k=j0D&E7?bWUEZU8-z zosxzDiFlAdO>=vt+r;Xzv-uAmyMJ{u|9SZMwI@ChESj|uEQ~Viq-O~-XN3VZ1y55g z0^c~k#QpLdyVm=$|F}77*ZGX|q*`sH7w0|er*WlJtxX9WR{b{eu${{pJ7`mHdVZ8i zS`Qt650{Vu0gR9WgpNZ=$+HR#7HFYAu*E&E0=d8oYU1H^#|DbPc*P6QywfR+Y~38MjLt(KNB3r28o_&hTpTnFFt+#*w$0dwoz{r%5o z{c|0G>2M_u{eS>npTB+?Mmb))v`6GBj~uUgs5eEJXH+l6GzWH&yQ_wy)cB=b?@&A4 zQ|c9c=Vwy{peK4C{FLXfo$jnGx&D$o+6dXmFWjGy;crx(&mnZB&5e>8_P6ga&ujQp zG=&T6!E<*U2@&(lx6 z{_)2jf5a9b??Eh~8daslsJm-|?x2D-DM22I!hiu`>{ZEqQAILP4qt!=(|kaR0SN#R z1NvH>>5c(?3Tb%21fWHL2DyfVoVCaYTfX8R>ftQ|ik{e^(g89cr$%31+e&j!r6SLL z5R_>Olq-JJa6!Z=a@jT)w!~L`lN9%z8`HGs-b*rA{KF>(PPe}qvdV}7J%W8ZePqtl zMB?BR%v~NThp$B&39?0kRrBbq=aCqR`&tyc1yAx-1yrkg2Zco;lsw`jLcwpF`gr&O zD0LkX;R1tP0F7}_q@W>02~c|UIyE5}8OrX_z9s54ZlMYk<|^S{8{%zNQ+W~9u-w1% z)qlGC>eKJM?)Z;L%uK3=iu=$wh>qwat}CmXtso0FlmJX{D8V=^VcfxcONmli)QX%* zznbHjl*EB=K2oHrz5-CZIbvrZS+PsHJOK zS(o1Q7w&(H9;QdUH*mM4*^4|vpkt`Fjn^lc?t7lQGN1gnx3iRY!__zf% zXh1}N7=AXv(G2`1*<_4>@QPLlAO!HE7z|yM2Re|3OMMJ=B=qYL;OHrFpE7BeZ(jN3 z&HwW1_ZD_|xOwg??)O)i1jYuQ_p1`eZl_ zZlm%FU4L*kt>*Z30iJxmxu!*0r&VF(I;(}zG1+PaK53ze&+0dezycxqcY>c94mH4! z%Yq@)pu49eE+inaNu(%1g*t+0&=JEAZ6kz8i_Bq54v3N9h7jb24dd;rAwf{Py?^Id zr>B4W^gHiB{PkHGz##1pdsbd=PT2VaS3l7tNL|{M#U1&~+HlKpLGH|S0D|F}y*-(O zqotjHyzoE?!k;~V@ggvwl>Y0+tI@g9@Bk~me)BkJ)~*@QzyqIUK)0{oh9v#b?6uD? z{v|loa(65~THcuI&-D}LQFzwikTjE0cHuSW;+3fk=vway9g#(S>9HB)*8Q`xTHiK3 zN(DfDDIf%&Ih~trI$d`;Q1S?3&N9?NB~4ipf8MJ zyXBit{<1gvKc9Z*HNc;f?^MXFDuSOOQ5_t6hv7&8P6Gj|dk`()RLL%e`GPyB{8WrW z(`&(woB$Jym4O|^Zhv_pg%c8`p3h!>{^Bpd2jsrMyPApMHfq8C^|u0F9vrgfKSBUP z1~js)VfOufORy>`kj(upH*_;fm=*@4Pzvr+AONXWeCkoxv}!hU76Uqc`vc_)8VqVZ z25veLIzNwHAV14X(3CTqEO&8jL)}YN_`r*Z;{+_3I5AVe0)eLuC7id>Qk6rjvzyh4+pL<-V}o&lAdhmv_H zgQ$3$LS!1hSEWKW!iJ$h3P?6dJ1MVz)$9G{RmPva&0(c!6CMyNz32$=%tb(YwD(85 zfE@90w@?IXTM%k%2%@>&ucueT?`$s(YS3_d{_-mi1YS}Xf?fO!G$0p)<*O#=_y^Iz z;{u$*yBBAJb8=<7o&`eyx<2n1(2@&Ydc7xeIz5aLEXx&@$w~9c0|+uk01E$zMd52? zfXc%|8E7ui%$CyoSEp(~M}wYbKw5sLdka9RsNU20Pkxr4>3sN;ac+(Hm zOE`$nSAP!@kSQiHB=H`e$-N$FGNHRzWxQ~Ft|{+QDGj3%eM4qvA~7bkBsXWpBY}G8 zJ%5Tai9AfW!%z@jsA+07WXNFUsPG*;Twz}F=3}4V?ERNl-+AXX3qK#fzV{s_Hwu3E zAOdCjdF$jSK?iiDS&&nsS1ZhNp!&R86~clcDQ3TH|1^yOow{LC2SE(spyBfM%ddRB z>p|tSi_bs*i&f_Xa=&xHesWjRv+4nWum|?IzZJDg-WCSLg$o2gYnA~~C)nBEuPnEs zpbD^qH0Wa2KItyR4j%LHRisV`U>S&BL@v=(t|=3X+EcV2g1566kbMi90r?)cToZQu z#Mb>Z_lgYPQv3eGD?Z}p@-#oI{KRdTPrR}w~IA#dW{&GZZfC%%dhdel7EVno%bG~1Ss2$kqueRR1axrO~b zzd1Xx7!^uIxn=!;;-&4KdBuQ019}-5kh4OkOmx~z!0!2hQk7r@Hs&yX6bUp zi1f{{!6}`t0X<>g!3P?E0`h}HGFk?d#{S5rP%xibl6L;|7#w0(30}F_v;c4nzwg{t zYccv@xC?aX+;dHf6f#%z@zPV$TDN%v`g{u$4LTJqReXCSrbZ%e1{L1}R z32e;a^DjUDi}(624G*U&(tXlkJp7OuF*R@2Oh2Qr6y*N}5!#hvAOo@|@NDn>96|)4 zF7)-KpY>e*$*pZ15Fx$K-S6!#i_)CH4_%D898m{$q?U5nHkAS0asYHK1fWm`8rXMo z5ilX2gcd@HJbgj;WFF9(Xc=~h?UcFP6&!pPz*CvP7R&}kEUP#zpUVdEoZ&eOS83%A zR>^_X#x(Kaa85)kF9MyeiubG3)A>iwjfFH3o&$cPD5h$jkG9Eqp7AW1+P{7#X$q?* z5FHIfm6C7DO7^H2ixNpfp@pY{WE8^&V@pAKF9D_^fGRjzyS)1Tf0}*!^x)~&UIzer z?S#ak5Y^PYh9*jbk=|S>3|fVmw)me(^AUy!5L6X01Qq7%sUg@12CNvVQmqm630r$* z7c*V(wHn$G>}9A%T{VWkce(nx4HLlkw?bYp3TnZa0a^TUJ|Jd5r#HVc>WeL3*8+^Z zq+B3C855~GfHf%xAb}zzUZPx(C=aDg+(At!;f$%vafa#N-A~s;b~)x7riUWjD_EMj=yx?p4A`~BC6kNHU3pwG+DRP z?pYep;PjWh$Eh6SrPJDQkAu;uH~X6p%RCiFcOH~31om;vh2_FxFl;P#J^TPlOi#O?I9D5PAtiL`YaUG5_kN zAOC~;P5}b~09s}G0N-~-Mvwua;&T7Z*#Ll!mUbEd=z!Aj+_Ap*6@52T_ur=9YS1ji zjOcKp&8Sira=aED_VAEb$!H*7VP3h4KdA7A&Y=N$3iLs&tPPGwqm|L|U#-o!-Z=TH zNW%J+`pA+`1qKLtJx<|wriWE0aXGEag_new>1yhc7wk1=)lKpMf`mx2^vq{_DhV;h z_d-;E@t@m&L;0t#Zk?pNB;$nOQsn;M5ZFWIlMNr2&s#EarpOg3Qgecu@tmJ1nyj!V zC!bS0fE+`=$9V`#ekUI^m=J&3WVI6pl+Q$9Q$`gK!vKPc2xi(Gb}9A(;nvV6(-lMr zK2&^5D%_hUm4mZ3TL~eNe&_R>7Jg3e-hLGYpx0j8Yln!#hYHb1C);V_dRzkg5!%Cn zmx{MYgC+=a?5ADuzlA^XGn~*CfJQn50}=Ywci;W-t`8fa7VPC!s0AzVx4O_Vg$l)J zH0YY!XcXxrO9(*Mp&FhUkkd!=s*rSz$zL)QYDj^C4RHR=ie&%Jf9>70zvRC>fB@`u3qT+J+vs=|#8e>>Vr0_j(@t3D zai3EHGwq6i2J`L};WM)!B8=of&G|>+j1bI~VvGcUXuSA$EdX%}8A>rM1N!Ve2S6$R zs-+UUdjdq?HXDMy9b|<@qiyvB(7Rm#==u(8KnOsPyo2j1#qa)H0!@^@t-Laan#(-b z(kICQ^cBig*pV|mbgNd4Cya`}p96qSPw)1A3SC)$G6=2EM|WM5$W>3sEqNqb!JMNbv7fN9U&@%_{aoIu@Vj*s)0S-wDOw=@d zR5YTz5QdR2{QFBkx0g#>Cx@)~;*l%;B)o_F4;cPGP;=H?jwr&n;A}2#EtwcHZa2^6 zD(03SC1F59YqZx}ev0K^EHGtnZC1*f$McBen4dr35bU`3eu~ZkVLEEAfB+=-ZeD$! zDP5!D&;xk^pL<@&)W7`&$dx(TRdx#?Lw2+KQvs-ljW>E&8Q=5o5TC zo_pq{mtOj_$8S7*aliDqGgK6a!>Fq5HRdK;PM`y6WLZt#eDY7+`89j`n|a89z3u|A z3cHIni$9p?B6<@SkqrXZNgP)a}u+YX;2{ zD#+58EC3P4*nj)3Wk4@K|MHj^5C#eKm@z)tLv(4^XTki~8$2?q1ZCR@K(`OJl?K!% z-@Y3nQ$rB`p0-U}#SbWDRH@o^2=ux4IO2hqct*04)e*VX+_wx!X-FK;zA(mLk zxs1IyRvD+T&Z3~{sxVUbVf&bxrg;M$tIbs;k157l1m2xIEQHJ>2=c#VvRlr$QZ#GO z>b6>EKxgLOi}tRCpBMl4mtK1O#*G_4yk#fPUClM(kdO>fk<)bAMWwNas7-~^PX*d= zf=fk0GrU8dT=?@}-h?mX3gC~uyztsbCvBC-k4Y8KDvYp5WG*nJh3R%L{Gi(h<1NpC z+7x@Wbr(c&|G=m17)5&Djf&COkd-x{qmk5#5&+F#y7bD|KD|Ev?D>n&|KdIFNGAM; z^I`0NK*^pTd+ z0G@;jwdquWGVxW*SM1w6D+I&$0d0X^`rsOGlVRHWZ|=k9@X!7C{I*AAAd@O^sgvjQ~57Nq1($F{3~@qz%*R_dJS zdCk3<2T&Q$=6WiR;S(wvRVl6}#4K8eo5~x+v{W9Degz~U{76>V6ydv-!cE0UhlB@?hKs;_65=-`{OCj%2=mT&xEl52$SXyE ze9a-ZWSsy&m~^)&v=Rc)-_EaXJzz-Lg<3FRKn{S!dPpS#y6nop>fHx#&NczisRAI& zd#>LG01^f?`;|M5@O#t70Mq#I$twRq=Y{%m>X4$!!{s81;_x9&qU^`HszZFJ)^48> zf*}B%9u2O!O#H2fPmEUX68^xzggdaX^TnmVnyJ3#Z?A?wkxfjs>sbz4w5tF~^iH@V z;}k1p0@NOR{M**zR<4uOMOd=VG;!4{Y}Mkw|BL_Ssh`93d)==+PU@>^n2TSziMERZ zX*Cz@V*)reF?3cFkfRPkRl5k1@ZRGb!qAyF8Wp3l);+vb$*^5*-g)ua=WeOyzPFya z+TLvsbx}p(lUqe1$t^GKIQ2JiIO9@Mo(&bU9d1ypzIo-ihmB9~{_U&p5d6IJQ9(H} zM`{p<+OU+gN!dZ+$I&5FcPQ{;pAV5BT+wFRPXXxTK9n{ShPL`lbN(_T#os;42efT} zuywm0rvZTv$gr^N8j?MK(J~-3A{HsRR?qfwYbZR7 zvT~RI5o$oAoxfVT;>?Jo59@O&IQ6OqC?x^63LdOf?ipRf!Gk6^zk_5@t^bCCEQ!~s zLfzY^#|!VZ({8u>UN`-EceTiy#o6h)ZQau+^Sd(TuyEIJ))s>krQ8*T!GGFnH4T1L z`a*?ixu#94j{rXv0a-P3X5Nb-$;MtU-MDe1xv6|L!c+Ta6Cp-+Arz*Bt)5_BSWM#9+U6B`|{ddnQ(>=D->* zb1wvjs)AiWY;$&JWgBkrm-AtB+)Vw_?1I?f7|_*eBcq}S?R-EoI+!CTYnNa72kuj9 zcHPLR&%gXBGoW08EnhLJrJ(%&#fWIFEFH=C#jF7xSO#QoJDi3e9e-s=j|hM8I3;FC zGWI{zK`2(_k=r*9vOtQ~!tpF{QBbRW=ZfItu3@L&T!KnP$im=LNf|jScxrEHd>{IH2D#1&RGnzpKw~`<8ivXYWc5S zU`5CH|A+~YESS+YWTXAaCfHc1G675md(luEl;BcO5}-*F1T}z5eWx=Zh|0g=7qMN$ zS+KIsd|-Whx4io7OFs-oR=IWKnLEj@=RR)JHraSEHO?vWwlEuFEJ$(^_T^M)PjWNJ zUcRm_zCU}D;+LKIr!Dk20D9rIJ?ffKA^hO6-1|u25G*p0<51wILgP>23+7&0eD)wZ;1QMc-1o5Yb)Ta{Mr*9RU%kGz> zJ}O3_0d4Pu!*&4!x_#SK!|!^z`Lm12fS?$IT1g<|*~M`vfGg#ML{JSMH2qi_1U2K} z1Dc;dxa|Ol6zb8^k1B$gDi5$HJoA(j$V~j{A{^e0PF~hA+PMg~dF;%~i@!XhACP=h zFKJHXGx30?mIci|d4HEV7;?Bar{c)$v}))P{9gqkO4}6i>kFs5{zJ+s#N+#2pEWCV z(LvBcHP=y*_6O(Xes%x88+*P;bJ4GN12>-*bWIWJP>~VY#7z=S;1@K(rnxdL=PJ)H zpqBsZKoGS7YUl2!f0sH>w9n3hwcEQ_fAHMn@wiSm9{zw*UgG9y6T@kfy%__lHaQJ} z^$^8LNP9sBgp&$5QM>rMz4hJW9*l}G7`PJDr=M~J=(X2hcxMZ6rD}tU3|bO45ku3E zr#e($QB;gWocr>*b_~UQ9xN9PNE#;XhTmT2UfYFHd8RWU2*C(|=nQfq^mSJauY2t| z0Qva6$$|Vi4#;58jNs4vj{7oD5_@^S7@<045CR539CBT>$~oUpqqvMTs_5 z&Lt01GZWO@x-gC4VCjP+5>-FH^0S8zAD^NDaS-+a)yE(4;LKvb9Jw&;_{xLbqCt!` z4btqSmm374x{Qe#&1#*{87~i{l<5EfAOJ~3K~zoWO7_kJd$CGjDbF#)Usqpz?!~R@ zFN-pLP!)lcuaBLpXA%uv`$5&l{uy&`NJMhDi*r2BuWOa;+ih%~R-?neH~5h_kLxc{ z8bpFHb0++>-@NneZ-3_CC-?&W?AbTJ#&nkyaZ%n&LN|aQul^L0YDZu~;-WwbFyy}_ zkNrunM-7l~o6j1~>)UgU)89_Ef&cy%O_JyN&f=!h8x|be%6z z0OD*B)Y1iCO)%c(koV2+Z%x;Lc4+AK!IAGCc71-$iO`+_9XbXCO`%gG%t)2MdkM&e zZ4WNa#(~}-1R!8Q*Vo{=5r7;6Qon$822@M9=m4tWJT%@@9q*!}HN9WqqSiFO^UM#= zXh=qprDH%Jy!4O&NZPFp+-Qs|$J?`y?Rp?-n_3nqFaAH?-u^YN>`WK6*;UtCC%Dj7 zKxka!I1VZTD!EBVN-He|M%E8~1FEWxe6TLG<*D?5$izcqA$2t1#4aY62}d+Bl-Iom zo!(P7@tOKzT6JLThJyp@)5BF-Lp3$s_?OxJi%S2>S?||cYuA_L9yqE}eeC+K+WXnh z`@GNlzQa+n7eTx$>9fLs`!5Vb-eCafDYoX-vyrl`fy=G zyAkLzcvByWe+a=@#O z)F(d^et0OFk5`F1E_k=~+~}p2VM{A;t{FDX3!~u&#Gi+K@RKzG*dt;;l=DjI)+Fbk z|0kCEE<`8x1;G`}z*8xh#9s;t)A8#5y`!U=v|+eAKK?F6VBh=0OoX%sAEk&#sf5*~ zm@2&pf~2@zxo*$43QQ9@Vx1=;-AAQMqtG*@{zY&qB|(frQbl?VZKb&C}C!Xh5}Yk;e3JcF%SM0wsSof7m#>7+K<@ z3M1_@g^_WX&^G>U)20}YB=*17V5BGvho2}a=;LdfTV}6)^S$hq5-R__9`n&aKll{~ zT^_`M(#y>8cq56S95xbI84#4FII{g_6sGhLiSTH4)`^a>cfMi|3*Tk}Z&}9Ls^WSv zPi&=X_z?h9d30@SQ1)VLbGq_M+L5In5_5iwQdJ~Lt5h*MQ5_~mSf7RWfJK?|YWJSE zQT?|$Qh)$~-bd;bxCan#iirndgsB*PVnHEXf-H;g!F8sIjmBbIbHQB6e4P;jHPPG=gf$@SPC9}0 zWev%}OGO6Qt+5cS$~~bQh5-@1^H;I6sC{9?-hQ}CF6vP=cwh_`Hzd2ok@!QkV6?|U z4XC(1289?6qiMY)pT#3{D8auqAzN z5Gd0oVxHegD=Bq5XWMk1($aSAX^G-O{n4L6|yN@DYZ~9z7WLP5@X6sUoE$ z7ATT1%bVTcQz<11t5~SHB5DK!QYt82nc5ndyx4lD-2Z^sA`;M@SSfN(3rP{ygRCWH zf*zV-d=rga?V6x27bQx)>}VHnu^sUyt8ON@{F7SODwz)yRxbeM`KDD z5Pm^Sfs}>khypXr9vdjaD(WagA%hcCx^Siuv0CRKsL^mC*xk8h@B#6pbut3Y{B?#~ zk~y&_%B18V>Cb^05Vp;k;MZ>SbfZQFv@%(DCV-8od(E5?Ug(+(F}b&H7W(x6M}J9vav>ewo%<=#3f6RVB zX+$X7d4+3_u)49mu~s`f3x*7+#zVZSJIg!ocQSU+i!MAfA=v*-A((4ZoDr1cgINIo zg$|ZtPh_Khfo#7NQjJ^mQrId>h3V#1E;} z1tjU^2HSD(I6ImE4M@X3*oJD`M#Gl+BLGc+4@gH2Mtg&=6p|>r{SOpOq9LjH!XQ>R z%sF%he_{VTl)F!hkh=L05lD-uUx+dzU}ezzD-8L>sYm&KsMKxdS2_OATMsw4idPoP z?RJK+u)th~;YT^%gE16xAH|HPPbo^$42K_+B0k7?BCbP#J7~**LT>`9{F~sbwD_A- z{?2ap=1(`TmDOO$$d`hc71^d`$b&rH#xWrrkYl#^-MtAIB`O|}`p(_CcY*zw{~rOr zilIo%b_^2kgK=CEyBdqY)?Xx+4JDo+l*BgvlDcpW z0byTgZr%e;>F+`ENPI&42m9KkA= z(_tsK_Qr4Q&U~}DST?^fdPFlxOa-;+o*v$%L7LmJPc`_nXX#O4Q?Mj2&u>u*cP z$J)!u_eee#U(8!gbdp%cqar5*ArEpIkIg0vKH+r*ouZfxSdH2;po$?uaI63q3K1{L zi`O>I8yvjim@lx>>z1~mS3v$8B1Ha>3*O`Oeu zW{+ypl#FV@mf!3c1d2KUEgkGgc7vb?4ncSf9nx-qnfB=8i$JT0t84$e4 zWGin?0F7$(yCzn$J5?qy%I7-+8Bmly7J7LQJ*hn7g6(|D_mdkW)-xg4c^QyDoo5Z5 zVD9rBHM+onT(6CI069~R*qL`p9Xon78AcM-Px}h4AtB2^y_M>btClNx5IqQe=(#Y2 zHyhupcFBGVX4Ah?N(={Dz!@0@rPJ6F#Zh|ne*6eabe<$df3&-rCPJN)~s@MrE_4#0kNJ7C7d6&+N_s?hw%go>FC zu_`Y83OvYRH&9}OHQNswzKV$216d%C5Uw?ZVv$!S4TSl88c==@+OpO}guXlZ>6>5h z9@~J*lV^`14gX7FKpBa?A|95P9{!+_0WkpG@@A&@F(B&$s?}zzh5=;?Jz7sBykQ6f z(loemz^&SXlHVB}xAY9^WDB@iFGOAh21&5v;`td+(HUL)N?Z&FnlKDVqE!CYC{UG& zJKk&y`~EzMi{z?-oMg@mE`v&E8@*2KR~FqvHYY zRZDtw9LFgJG$?PcK=I*?&xBtYzQxfa4%I3MNJjM1~0B|0(qliI8rJ0L-u0PONxZ~fs|DREgd+uLj zAsV3p4QD`6fy7hUv`IG4_%}yRNQ!^~ZJk>K@@B+O^nz>+84$gEMw&mv7iCZJtBUvn z9;kC!EPnS2(@HA&LKTJ#Qz9 zdV!~huckhS*Um`yG9XpRER=sn@B?aFak{Lj1XA4711XTE0X-~AB)AIE@C(EtB^s)i zcaJck%*#pj!5w?z9f1LbBmsp?gG}^wbJW_hS$s4Mc~ViCvj?fb_C|CF6?0R2vM=hO zw8y)6`FnnMa-0d!Xy`qjBKpoZ-WO>@Cku6A%|Z4Mwo&&=F_xjevtbm2*iNW=%4nCHzM z&O~i4#ke)LzILlNXeO&>QJz(^ai4@DN`h9GMy zQ_=kK{6T!fk~Jm#DIXRUt!xn9@i&s@&7M zq*K9}ay%$@x07$00y5-9XJ|kOK-GFQDc!H_eP- zjmtzFkLXz9M~Z`NV1#eGfUxjQ8IV^BFZCvkiPd(*bKhC#7R+Wy(f$xrdVOga&BTZn z5)ScchRg#QH&fNccngAAbT1Cd?9>2CV!3aJCw8Qo84@OBlHHW9vAMZzxJO1qJ-@aL zsGkHyLykRsHO~HsXc>h4MA`lWcCiQ#x*gH`=V>0y5Ahav`#qlR;Rb7T<*h zAUq3jgW^IjXE}@==aGww)uY(!NMX~@$bb-jAP9S^g57HmN1HY_uap%k)nV{De@RNG zwm3u-Mh6?;Ub~kHE4uX;li)$TeEHqWf7npMb)1|e>XE>kIIaVMA?psJi5PTWswE>U zwv~)j;$$Kjk19rKwhcwDNW-kq?b6!ONGCKvK;8|mfF`Zg`oCT6h_(|Ip1@Qdb42D7 zAIyA&*?3Vi%qoumni6Bs1C1Ea#Ms!_5CEcDFq;L#7K!iw*F_eC2KY*+mZ zNYN09DC*m}IxQmdO+)aeqX@Nffmgy<%HtVK?VJrjgBZ}M_c3eYhMu^nGq{CA7%M`L zRZYZ16$>%L=JmSZ85?5Oi82;<1YLANz=kuCG2v6hqkhPD#Lr?#DW0lK500m_rA0e_2&~fjB;n^3W`tftSh+U@qu(W+xCeSHK&|39Wi$XcT@@ZPiUQ=J{ZfSZ4EGsIUYL2=ui4=$+3; zt}0v51W_Fa-}KKq6_rPp4D5Yk@aL%Jl|R>>PtLu2`CTGF$JWjm^MhlXSHndFWSm>$ zYL9@c%lJAMo{Nw^dl- z{&-_%=K7862tZK`p6Co^yfU-}L-azIaWPcG1M4ybXzbRI*TsS}EXAk_1ImAkI5JTn zJoRme8MoyW#L(kTy?l~&gWFs_!49AfnSkh@rC=sm_-Vhn2GsSMlF`Y;(Zp&;@IlAk zEMdxS{Fo5CdR~g;|+^QdpX++>=>+IwrZuXztEKws}dp>t)Ei_5cE zS!JN`AjxpvR{{B1a9k*MT!`8#Q3FMrGS;r>!YjX^uJfKKM6}3tV5fb)VL%lWpDUHH zT)I-sj$T!^P8Tr%s|5eSzl4)!fCH7?J?ws%Qh;_00eaU!(B-%O@P3SURG#q7wPwE9 z9dPBDbRhBtp+K_#SfpkhNYbOoYCzUDBt3)hJL2oYf?@@=V72rcuB9iz=h2N^Kjg>( zNlE_V7wqpb&=Nle26TNU1`X)R%=O=AeyW`j5uwN1M9ea*hQGCD7|`JG4-3vP3x?>| zKvg>bbMrh(c4H(yYu>q$wJ9n%Orh`(Ut1x3@b*g#M;BaHDH5EC#3?}0Voy$rG@$l> zfC2SZqBw1G{$s6T7#q;Rh<gsw8t(0fRuTZ z%1jy-GrRlS*o92q@LXsd`I?BH4&+4`en4C(1?^z<><& zELAWAw)?Z<=oJONuW}$}AuK=L+W6)HZf82XF+wl`=9__hB}PP@BZi?0u^|L z_BOA^79*87Nl7wnOtVxH1nICWNL&hyJwu9&L#bq%&x>5POup?`SJ(Qt4(?BgwP1BA zh^Sd?s8*{NUqJ-}ZLipreufwjn4*CJ(GCbGyHE_vyNj7G}^-xMP&I{6@DnJdbwC~s{MxprCAp!_n3)dWR!A1zy^X0Akk z=Vw5*9u27GwL5~7iHX&=3yMgeS0sHGXucPtkdixOYy?H0jeFg4Q4QV=2W>z?+`^|O z6v8Vs7*=wV5l+wMn-FK@Vw8#O?t*_mhF}V#;Zmn;BA;wePWf6%X=0G}!PW}KyChnU zJBh*GtzHcXuPj9Dh{#y_!)sTpGv(>NUtwxD>4@VbLp2l&wkmsp?9tXCt$J#`i2C?e zI?gvcdBc*QICkaX@r4S3PmrrTnmP-APB)9YPoZ>!yo=(WCI||@85A{xRUUrf&!c<3 z165##16?)%bR6_b*vUth1^A@BqfjITmx$(qH6kpK#HfbiUfpb%1gLOkv$1R z(W?@Si>~zpkYzxKIQ3bwb=QOewQ&!LJG$f<-*YiJzowDNR#a$Zi01X;Re_%<}6hxfnRTgF5g$y-7 z6z>r8`-mY3cioivvio{x;x-?20X>w_kcz^72IK+IgVV0HJK1uK?%HaH*bBi4z7}t$ z1zv^(r(ktu$%Vx($Ra%&C`qA^3dPu_UZ5CHa*>h8uMm4I_Hm+&yXUfbM<9v5B$o5Y zPns!Q>1#`}xp{3jVZjehV~aElfFh<97}yKxW0byN-8^1S4u7_S&9cD+UL8E*`j~8% z;;^D2K_(t-XK)3f8UWInofK_-gb7JJit_ASBacO5?&#Y8sn~KMoBXla9|J&!09BS$ z`O&rP*#u}Bvh~)wh&WUUJQ@_9n-N(I**#k8_9Q$e_J9B(1G;?q4;zV}QA>KrkV+-i zL|<~Oh}3ARqUTx=Ws~_VWb=V4?E`y*wNMAXN@R|p0oD2uh$rNL2wlz3k`<_SBweBn z02!Vh(@)w2BeXd@j$i#0BCuyMG9c(x&AuZZs0^G5e8=sB{lD2R-e1Q~6$1f?TC#c! z2z@{qWk;ie1_V4vqA*;)FdL7aVRCyTr$M&|bAhipA5Z#Zo!ZI>9|u#H1hI z7V#f~p+ptDa)F?bDjrB|^`#3Q;zW7#XZVs>@8S!X1gjYQncB>rNq`Jp44xv_3BAIN zO6XY7YtkTtKYMH4!`_T*YiDwN99jXrd-<*RX9n7ir0he6kh#z+5OYvqllG!E1)?Si z$dI3!fGOaSKg@e5E6;?;rOV(17*Ia|9UdJXnE;F;uzJ1q@@1>uI69OLLHYc}FO>MR zAOwRf*vu0HJRdzK09sI1w!>Wub_Pi(&!Cgi{`&UV{qIwKLO%f2j_RlZwdxjt>fnTC z^<1HQgQlcnEM{xnRHXbafv8#Q*j0Wh-qd+Vu4pH#MGImHNJI}h$?!%5nIaQ+oV8x{ z*Me;W(xw225`DjVQ(IioHoUP`@|ax=ws23fi0Q4^@)`=P1Rwl^kRA__*gzDguF`WX z(3ESO_H3V8n4#vJreTxq0Je*QQITWJQ?oVhviyRte%XDz8x_jQZUqTZWM?_ zbnyae&|zh9>h#RN&FrIG5K7vN;0JT~M29>Y6rM96Q$eY*o+jGZhGXaM+&Cl9A2vp& z^?f>&GC(Rn+2-umfiq((4&hvqK9Qkg+_H#Aiz)6cln4XTz<_E!08~4~uEh-#3DsZj zyj)pcUS4U{v00BWptd*J7AB+4Tz~u|gAC~L6U>I$@?lbLnla_BfD*m>Nd$fx?k?M0B*M28BgY}g0Mj~|{P z0rfMW?Xk6ql(26u?d9vO`T6%*?Ilb^skjhXWmwKr4u;5sEPvy+>bZTxUdTpPBL_PR z9?qrk$LeV8dJ+!A35AUFl)}{yY+DXdeq|8CO{QoK$Vc))SfWSD3pex&Pmfb)d~uPG6k*l|CT zETH74XFgdMv(x|p>T(v$X+Xq)WF<5uR$hml(!OlrPQu+i8DEG8HeIESTx@iJ1@l3M>6o`eI1?kXp zRR_Je(@%=ZKc1NAFRX;^XnbxCBd{OMygmS_VWlGCf|QtxSP;9aK^lssUq~ul7IP0q zq(X262Gn(%zAr>$ANmFwe_U^Rs{!Fi68J?DFe1VM00`L7fdQaMeig;D>#gvFEa;1k ze;Vr!AwV*KzLx=g3xYRl`zXhP9g?bu`zUF|MlSrO2B|7ek_82qKt-^P0dU2NkTw~j zt}$PqO3KF~Mbjb^bZlJPJafhB?*~ME5{Xh`D?|h9|NqMJuksgPnKvcEtW86)6|x}b zTG|Ncj6)0$B0Y-1x{9RF9q}L`S>#=dT%NkpBPzMgKefF}Y7hglPNy_b5Zf$1N-_=_ z<=JiJaK?Th2<3D}v#w=BPG9@CMKA>qkOV|y=2)5XJ6nP|9v{nYO-&!@46YCvQ~`Lm zMFvGB!8+W8{kHr>7||lGWwQ0|l0)W70}DO0DO{-JD!V_+o}PyQEtYdn1CIh#BppU_ zbS1DX2(id9qcBJt=YnQX8a>PdzHHjx_;Ya%cNBMqo&a|HUyGxh;3 z{4}GUT}Kfp_WD@&REZ#KdbPU7X|=%sWE+y1OMAqCejX_?pT^>K@+x%@dsHM4WH6;| zHt^`{KW@Cg@%}%|e4RvWA5sfubzIP7%Jda#?GawGisJ}+SZK9b0+3xGE7dx%LwhgJj zE|Nv)0;JzJH_tiF^X>m~-9d13$vGGdQE%4B4B0WYbXeivgwn>qXH;#xoW*f&BwKPKzK zfNI@*HUF(w?B7W6Xk)uL;j-k2r!?V>x~(==S1(?C`|Y>K&Ho#3zq#@CSGeXCXcYq$ zK;w$3U8D3>sZ7^$ld-`GaTmZy>9s_!?ZHNzWpuHpfh_|}kiM7?XY;hSE zh;anOP?6#(wCOo!lJUeLkH|QUI*J?vvbRQ(;fi!RnseeX!-N&J3s#|$H$|T5&cVR` zkkFu`(00mtD!g^?M%cBpb8VhT^?-C0YiyB%<-b36^6q^zYt?q}MXS}f}hQXnzV z$9|u5okS=QCT6!J-6Ikt_u3X!dM2QlccZGe)RMAb<;CJT_EC^6TwGF>rCU|dKVrFOCHgty&m2h5ciul%!Qkla8xkNlxkH+R&@fj^ zjBH*WLNd~RlGrw!rmyf7*Md3wN-rizD$Ed{nzX4m3@Enl2?Ib_ig66tuLBc{833{h zQKAygx4B9YvseQI8U{c$3Bd^X_RQiv!+;VkPm|~%k_!KXI`fJo$Vm*H9F+Da4y)B) zeY&zTkALIuN4FJLI=f;HcUfGLu8k7!G|i3FxIwiSH@98~fVNZ1q3-|C=E9&9WwotY z&=rkCvp8I^S-Hr?U0RSJMRl}9EPnnd6M2`|4{ZZ50fIs*0<*YgS&v9d;-uErD@_-4 z)Jd)l{6@f$SZH(N3tO=;$heneIE#GbjCADNgmf>kGWcjo8c-Y7uFKBh{z{^{81M#zE|BH~4wud8pF>$ zc0$Kqi9^A!fVJ8A-gLW5SMxS$lV*iJW1mfY`_eTBc~+nC@T|ZnP|!|+wh%_p<+5Ag zhE7QR%?|3bm4TL-8GL{yymNjZt`fAVdAyCmSJ1Y=^&cFcW~}}!T!`NezMJIY+TeXd z5z#QFhH6N5Basd9V#4B~+j$`aQqZ|=gvkQm4Y0VGEB3` zECfd>uP?Pq+Ypf?SO>JwAoDdffioyf8j<}0oY2EHAgcaqhzi}1S*hp)D$t%HRscW{ zf<0R>%;(AD8#90W>x@jacj8ZyxJ-hInyYIQLp5mgBD3|$<;m78PsKpumCs*oYW!e4 z2u`d7iR`i{8wx8~u-jNaYCz2hmd-BE-_gvc68*$6=@kq=!$mjZ3|Wc?x9CMJoWIPOj-jH0XO4uii~Fv z^u3MR@(j_QU9}j$%}!_a=HPAa;k6PptGC`I!pfBFRFHBP8({gg&DEjV7uQZLlaP>$ zhjlwz-QFD9b?{m#(F{1^9g{?b)PmuhJ)}RdZ6tA1B|S5*?3w7AR{n{_33TD~eE75Z zoAT2jthhtqh!APd6~QOwL6Q|?yL8AM&uC##{?7jI-0n?w<N(3zfdC+2KqCh2us$V9CxEe6Ke>1Ba8|N+)n)Son8W3_e)13E%$K(x^KOvx`0%U= zU%<;vQMS$DgYz+<+F$@$uQ^f)Ys$TQyB{n_J0oQ=2Sry$JlytJ@I+`K0c@e6FfQ#% zltMNy3uZ&0f_M!I)_pDHs4pGXpBy7pq3G&^(zS;}RF3I#C!=j^a7yFb@QUBCk4Cm{ z5r=LWr^L%Uv+B4Mtl9UI`C?;i$d8kqy1zBGo1odk{g%A$O7=9iN)Dby*t0LO2$T3N zkNwtKq^q*Znp`*?7zg$jVJt!bh8pw|g3l7e5D^^#BEls(ah(=98D?!kmDNvvSL+2J z8pZR%fY0)z+4o=e&+3%qQC8_?@|NgFk=&fBwVm7!3NXH7m}-+Uz}iMFnN$Ar(1y$Op$)&I3S= zkpSdqa(CjpNgHhfL`w94!+<~S2_%t6U&KsQaIHhE0og*Ct#vE-s1rHOiIr<19+3^c zGLcX;4UaVP>`zXGuHB=}8p`1z(~A44 z_!+>@4IGS-DFnoT%*!TdgHI4IFvY~(c40D;YOk)?W}VUylh#(Tm_6ORwwrk+S$LiBj|%WE*|1{X`Hb}j%i{HL4~!b2xvB?Ub;3+5;gXUg0S$cd1`_{s6*I+wvhPiWMhu6_~e#C}F;Po<(nNRauw?c-mpPq1BJ7EfAc z4=`^S(Dw`g{p9~RX(k@Q!DEu}O33drp>IuzOk~#CcDuCs@YI?8vuWR(MWnT18qm5k z2yv$GsB!h{nPbEmX~Tm7m~$kXgF6ufg3VcbX)7NgQW-E&iY$~wk*^^~){tYh?TpW^ zq@R*~)`ERrcp73xAC&)gSZZ){bE=fIoeq>%cm|zjoJwwAEFFVcHB5R}YKlM2jma>6 zx&eqtk#OgwxRfsEBdHNU=pxyocf&v1dyOZXyWA@|*fc}V?aIPek+?7iO`-sZmecUqt?h#p8xcRZ*Cj|ynyRS%Gj} zX~=28gI;+tb}MpADZg5k-mQD;s54Tb+cXHIG+8br4uJiZ6Z{ft$bnlHg%Qk@C-IRGA$>J^5s;!Z3f! zlgkEw=H3T!2Br%sC2Fz!2T~LfxSSQ1x&;(qCH$38ng$gW?M=N^-1V4t-I}VQU@HZ7 zB5N70(lnfjPRVQwt9H9|762X1BK+hLfB+gA`PTCM@~?jVM_O~AP$ihhfIj>SSU>UU zZDT!pM~bII=~t^06W!Vn`I~(}b91dKyy|QX=7J#u+Gwg&^{BYftOr`h?b6}cQNub1 zAOJHQ6m|laO$Y`-n8FR75t$-6rDRt~=|hsYhytOc);V}*b1OScWX#$_3V{6ke}2Dq z=&c_BkSp`^I~z?+{fIanLzjpNVLQh{zcSPdM|3Qt7*Hy;#Yroh1-GsuzfEGn>P8u% zLw&fxaZ#kX)vnHTlEwG7M)llEIv$4_2|&g5MrKyPdW&4f}$5HX<~!e*$5 z(?ak`;j6%)w22Ic)mHjW65LmFZHkSgOBOjtv+=K0b0Jo)aF<3}+S&WV$2eM#>0RaTP6-%c> z^ucmsFj0P*5M^l1Uns1H?b5KdyO#kSiWUA(MMr-Zzr zFM!Y$tNa-eROAI^nE{IRK>4~rTtODvmbBJ%ZNn<o z^xVDOLWh!OC>M_mz#Ix$o@2{VoMxpxTepBG+@VuCqgmzFDNGH+twalVhRsK`QYF8H z@}__}wK0x(+f&?LCT5b9BmoC(X93U_Kyqn`@Mp<@4;}@IDi)1Gr$Kuzp-L#SPw13n zRr>b5i2)Ve&?d7S0rV+BAMbSwU$Qy;3lUc zD5nSLII@d`1My7*X2W}IgiSe?0l^lXZ#3$ymxu-*AR0U)0muN*A0Z27py=7}e~BYf zwM@luYN)JR?LG!%o0ZnE`U4rzGB|;#Cp5l#enWR`(YSUQpaRnXh(*5o&iYZUD)3`Y zRv-&7*ZQAAE zU8DBZqqY6I`>VF9t(BdXdVQ~!pTBG%=nrtWg^1NL4&p7jv_U?`W8#=no$~4V7?4Zu z9oj5daeKSCy^fz33*wIs_p0^hbpTtlPfmD$q!XvDYrCV0cqTGo68*aLGb(JHs7D@b z5-o~)8+_Te7s7yC|25$iwxCSzmXyooq@y#A*LFS_2|#A2Kec<@X5WsEh9Xe9BCXfb zo>D!^uYLA^L;B8N2&XP<2sZIqkT}q*CZQCKaP0KB4y{ND!4^) zY2}5pGhkQBNPy_1B9{<(mYffW>M=z8ah{*hcPNKJ(hN%b6BFz^?1{miPcH8m{8=7H z1<3CD#m5!VIwpHIi#s07D7jAmc4g!Xq-1C%1;ciQjl7AVyswIV4NsI#x(-t@hCvUR zn?SC}vkYCWLOJ(rzFKe9>oXmg%@czI2sqI78PtHx<;P$MqQr2=tfSaVnU1tZne%pk z7R)1HCIkZy=e+p>r6VHEC);Sl+6PYsPi-{`ar46son&?5-t27MMqzjvYU(e2|5kne z@*n=96KT#&BcD_p!LwnCO%1$D#NVI^sr_`ztE`_3bJtIA4lG99zCX6Mc8l=muu(fS z=ZCb)lryl;jo7sn+Xy?B2wFwbd6t^{kwg?BDT*Ucs2;+E`Xe-pGhSVpWk8V?rnPHS zCTI__vn!@-iw2fL%2WJ8a{4*qJcU~O>j-K+ig{n?RcDku!<5kN^m-TC^> z{PvkepjS#AZGKOPM11#Y;shY&4PlOK&?OgQ>F#M6Qmi7$51kD_*GkGkPh|-&4a|it ziT}svLSDH97ekak=~tjx$Y=ronS6l+Xd}|1-DOZx^|ET#M3@Q&tvGNrpHlP;OMSX@oF3*k6O}?mCdl`^u6a{TH1M`#}+{XeU zevtg@+Mz)ma5F+rwLQWi2;?rUt^NG#uc8h$e?WXT`v&$^ffa~WCR`;MeTbB5WI)+L z@mH?~v^S_4J_`tBKHL6Yx?Ja|j5wpQJT8%t+&LvUX6F`bO-x@#kpyO1rYY)Zkd-mA z0(B22r7ez@AQe(hpU6w`+u*JA&b4=@%lHK{AvuEqK~=^(WtdnwVyr!`p1391!DMAA@ zpdJzg9m(=G{sIjM%sH){m(`6AV2yf$CPX|K29${(-#|-r23QIK4_x3&hPEIgb=re! z!MakW&;Se7-1zvNIc7k$JSaM|`He3+tVec$?`RMtIv|R6;G^M5^g-w9AvQs6>=~Z1 z*Jz*^G&_s!D%Zbr+;OGj^qtx-9o&=jTi{ojcpA{F(rKFPhz}^6R)Zdl?GFMVh{MKU zT{${T@2S99X=1SC*w&X2yTzS_Xo4>1z%d$!-@JO*NWmQ=H#kj^+A#p3hAP;k4kFJ< z-`Xy}vjwG9Kz(Wb)$KDF&}nw-bg|sg&dfL%EeBwyz#=*&1)|W|=y#kJpHSwj!p70o zNB}aoZQfiwX6+|V*8)mmjx8e{SVnn8dI`tHu;519xK9T|FkNUzS4qs?ZwUM#32N*e9sS~hMX+XzkXOQW^HP%~X%oY<2g?u`MY=)8wcvbc%GotZY1sIwVR_H^s?O1aZ6xSnSNOHK5!a+E^q zL6P6bF|CiclZ)GDWuZ<_?>|b~k+sRC5<<%6dJu$!0g+83ky1-^oU0UL zb8+eEk_2Cr`C9VQUC!p?tUq4=RlMR#vf#I0wKGL)J<18Rf`%;oj@gaB@il&d+R7gET|Wa(yYk?9w~jZRt$(M+6RAicDsVlPZukg08Kez67Q(eM>K{xKOSzC zO}2;e2Fg{MX8_RVZ%Vl(Qhr$f!BVhLz(*9H(3Y7B2MT+-@t~_86y8Q4_DHlD}blH0wvI*(7@q z?KoLYLQC?%EEt07;n5)`ZIJ(bx?=u5l|ZbD4Co73rJxp`b?6TlGRS~t7Jva^Y|e9B zWcF`IgrPwikP}CC?zSKe4=RxB0y2vX2w4t(c^$`qbb*nLb?D9~_jrtbYh`(!kh2AU z^#sDk4kM!CDN~a8u*}is5^ZzncG;Jj2QeT%a|~#|*cY;`d2Nqiep7AY0P6dj(Q&EN zR$frxgiKJy_NIyV8(j6?$TUT}q zAGF~fAC%5fp$oGzI2YE(g7m;Voxda_HnP;!C{>J0*OIAo^do#&Ts(e7TUyMUo45V> z`+e5qlp_MXj5brbIbluc3*EHoArdVHZT;K@FUfK{>Hj)x<;Q6Fj?){0C%cFd)V^ zXh^eX*p*y{_V#Y=QT>2wtsOv%WrIL-FL^XGi_n;OlcX^-ASONremcN{4E`K{Vm9?d zG65|w&&`{I`7=ngvSBuxj5WfLFV>Iq+0%*PYsThkRmb-MjbcEjWBY(FP@dx$Q1-Ma zg<^i|Te#CkQv>TMFMj*LlL3{VglKwsP`2sPDq^#qjz4RMQ!b4bJC5g`%Mv1{MVeVL zbxxLgklup?T$>MzyT?uQTeLg74@U=Jl8s-je39Xlenz`F9|hNo+M5#{`8Dy}E~)2g zPXq>nROk4w&Vhzo52tpUR$-IxC-K8C<%b~&WhX2>3Pgk^?&B&n&tO0|r^`TqSpI=l ztad7ft8|x~SKx+&d68IUUSIOJEOd_eM<8mt0wnHGvb zFY6olQJ&3+4+uMw#gDIFf4q>%*j<>$(GMQ{kXvU^PiUJ7GgPJ3nq8Tjo1CAoS7#fG z_qkXA03ZNKL_t(CqdrfV=NNnko*mO_M65cf1tqIBX`}Y(aw`v>W2gojAHOsI_VE{* z)>pP`YS{<6GwOqwv7>>__Sh+3Ig0_&=}lxn<}(-^D&F+(1jp}VeAfLPH|{kj{~5kS z)!AKN|Ao{Nr@||GQ%G90wrNq75~W@Fu`{Yl4$b~+n^1GfH9xz`$qFUBT%}kLoi|DG z$+D%T)MI$jtl#a}B?22Av4Xb8PTG)PiiKI;j4 z<`NnLBqMLA7f-XapN=9N3LQQt0cd>w&fD+5$)mW~W6K-9wDNHu$Nwx2Ts)9TeR`hC zOe0Zckrb{1N+&*MxhoR0+L*S93}|RIyo`v)?Vn>I92Z}Ix$S{eTc88W1v| z7%kY^lNEHv%cmFyG!TIBjkI38Z0+1#hGuT#%g>#s5JE6*<+P|rI$%-YgXrSK1ioW* z0Oj}UCJdXKpEvQ`{J23NR-kREtZR}NTZ%{>^z5eo!LdIGeJBGmrw_)Q6Qh_KRh2!Z zQu)-U-Jkfm*%q2=dV6f|7_hL(XdWs_)+4;sE{Wok-F!GziXv=CmOTdmWgnjI#_fnQSkkA+%ehBh zWm>8$P>(iMaAu|+b_R9G|KavNNcF876l>7F(40UQr&P;ZART@dtrq5 zy;*$pG-UP1Ccr}LdKS}?Bl-Q4>LPz`hNlatGa0loeH28}Sa z2{h^(FWokz$C&Lv=B$o98a1&qj$v7O6!TB_|yFYScz9{yB$?_2wF1Ouu` zNZBCPQ{`rb)q0~^fBET~e>9s5jKKgG^b9kgykq&^9RTOzIHe()@|f&E6d~K06}-|%-{L- z*Df7EnWPj5;RY_bd7=-{_;2cA_B;$Id)g;LXC(#$22>*obg5grgm!~`{vS8K`bwAI z*}k{0u;+df+3H580Fngg@J3r&wgm{f+<8?*J+%9~%qTZ49FI2Mcm=*eTA zk;a76?Kh-l@19FKjSBf#VHa2$O zTwOyK&?Wku`!M=C-}u+kLGtMS*u*|n2{cnQ$7!Qp#XpOI&T7F8R>T{mBJXRD_>*eS z!a>AT$9@(>qBYIc`At^8BEQ(V9bwN4nY;D**5_NPmLsX}rq`gbdAb<2n?s62(tafO z1E1v#@aV5OmiN7U`x$NFk9EXhM5Iz+%DGmz!VAa02%C=yt{)rus1di%)1NeGxU(05dQ;_mqL59 zd8Nc0;KhxPDE0Y6^27N@5-Xp}Z52qQ`O5#$7JAy+9VvE@==Z5mUn2!Hsd#sxN zMmPn{;hTPzzt;xT>(7pQjERvCH`)yhpeR!(pPasT&c^UJcY}7S<(BjS^pp|rI>i$b zMI^i>(RGO|f(s)6?@^8{K$3x9l7jcpYxd)lA2{)shu$)Pi_)L^{4=z{u0aa^2Rk4` z-x;5Od*&F`qtI{T;pQ!ix|9q27lFHkO0cfyJ*fV%K8hPl+Z$<7z!4*yo-o2$WCEbV zufH@gaV7vk{TEbYkOuU!egwJsl?z|1lOQ-i1sa7Q6MDS@2J{#KNG3zet|F1?WjGOf zb%+7mjpczf7?7Yl06=$<0_8WFu2HGKHd4t6MklXU*N?b(-qx?R=D||EVp!1p{QR#A z9O#SGA}J2-vXN2(#Bt5FbFS9Z6Po`T#RtL)s1)o{?RT{<;nO}4AP}kcW+&FS?-!w> zdHp-VS2X5K_2j#}OtDQ|2-;{7jK%MT$*#y1?l6s`!PF7;LLd*ldm8Ill>jdVWTGxb z5Q(P3s_X!F=D-LH@3QszwGwIEdW7+?Ckfx{O7eUIqL*u1u$TOg?eq182Q-9KSd!{E z%5W2;+jWWPkx1`S!5=BeLJ0+yT^L>vH@%bt&(9K_;2C!NK@bX^7!=~5LhJ(+iU%n4 zkjSD_OkR*kGb-5ez`gVe}DnKY_(d@6mb$O!j^GNvtdAJ9OlUcI;Ph5HdaCzqrGZEN>qN3 z0ihD~av9S3_2oH(KzH6g#@{DMPmn^rb;;yS`49D_~U4)od6*ZRwHWVD#HnUM`Hz8D#6xt0KIW8>c0 z488C@{iliTbH2B&_pX&d@=xhG5>Rn~CBuc4sIQ*(5d^}DBsY}|XFwEyNfA8Spv_qb zlTjTMETJmouHhE_lU4|Dwom`7~l_0|nta7LD0N*P7=8g4|4YyEt~(*gLFs4-XG(d*JkJ>>t*?f4?|p;Pfl2L7Bo#W!i9*DAl(prt@|_s`DO$Dt z^!1>KWSMIvY8|7P!Spl@(S6=*-Rsm&HPy16BUoxrHYO)VHw8*JY2^%!gkRjMol-?s zCJmCl{4;e;c54w6{h?W~;v=lVSh5&I4(N0hyqKYVYjha$boda7QXn_vDyzbGYUyF> z-7Z^z=70yy?Ue9YLcy;kE-VXec`II7VqmIxK*Gc61&SEH2%N%DEvNwzV%P^)X_955 zI0sE81oJIFL)t>u5rOtl1NwBOQM=Uu26UV=j0ynfIx?W^GY1QqCs2wJEMN#`0zdi{ z{V5>$s|L;0wPA@jPPKs*5paC+&K<*pCSSC$DScB~*9M+An0Sr@P?x+(Lfp=}HNW!Q zoXtaj+&7MSwyfk6I4<-Qep$^8kd+6TNne1C_>DDdd(}g)+zS2X|J|SS&NWzgE$I;Nr{Jej6#*E ztvvSzJZTo2qVW4P^~}~I4^dEAc!TYCCh*UKUrsy zC0FmU*Q)FhfI8{N2eG^aCk&3;nK?To$>iMj#CffH7els&M|I#TcX~19ROlSm=8c!CD~r1ejHtl!C;DWcdU3H z`gAnvv-?LEn~K|AI>*xNhHn*lqLDTLQeX{PIr{@w&3P`EGr1LNh2rQdV!_Xzb ztQ&~>Aua`JB82HN|4P_arKZam2BWik1dbynd0IdyIy^#SK0IKfH8vwd9erJ4n^6m~+!+)vF zgHO!oA}i)3~+m9s+%i3-9%uwE*U`DtIswj0Dw{k)P$`;>Ear%?#8d; zPANs?!V*aGT)#bs)D_KD%&rKL+9Nd$EJw}qRLXl$Jk34;WeXHLp#5`(u0FqC{O!%+ zDB3Yq61b5jgpngOHYW6n)%k+uYhF_b`5v63Fp4$~w@%N`fqnxBlqlsGPYO~_0wVFL z%yEzB#Uu9@hIJte!>8hawplPkfPey#CmKLvNgx1kU_jstp(8|aAy@v+z3#9=rq(3? z?ac0X*H%yX;dBb@st4`3ArTRyijO%)HWGjuIFPW>rGD|PBOL1RCU^u69?xL(g$(G!-|Ncb8Pb5@S2;Kc35!?> zckkf#kSrLz4`4u`8n>2lto8Vv<+}#X>-l^MV1d?&T*`zHSQdj*=OOhaAXJ|<7nhe? z)%@&B48cy=lf@4M9D=7j!L^7e8UmD3A-$G*=e^exq2X_A@a^k+NPeU!_0m`oywjKV zXX~?j`HRhF;Q4K(GKVcns<%|Tr*NA$MjmjW=+r@sbpG>dg8K2u>q4Y#vq<|DM2wGXsj*^D9Hm{)HDdORy;xULFqIhNkDSvc@TGj(4eIvMO zyyiNIre59t{590^D<$T?Vd7^?#16x&7T>6RSBrAZ2}d%Z&C^G~f2;+X$}ntKM6WZD zhdWC>*InQGis2tmbLCI&4V$XB-~p~539HqM;xjV13KG?*uW61Mm`|ezN?>Z zz~c{QP=CJu7?NQh{@#RSH&6pY2K4dAK?oO9z0okBW|9ssy_%gQt(Ys-hd{2UqhTz`Ae2h? zo9IU&U-VJR!C9;fHck=mv2}0Tm%!QGKmanVe|c_v{PN}b_1``yx(t1 z#GafG#UBhn)8)S;?K$-557HdZ7VX$i#a+UCVEqQMC28J~TUxz0F|3)y9%?@?>R1$A zTU*UNr6&`l2^fq5!68wHmRN!cT|-7%98?%ZEYYbD0}4E8h=p^eHatU-Z;*!}|3VJN zPgyy)21KQu4I(EvFd4@30G2#P_QM(w01#+E2grZ|!-fJRLtbwazMNYf*@%(jr`Fxc zox3~Bh(Lw`Rr6PKN=#27U*N1DyVRLmRUrv46lm78) zkgE(#!N0l3mG{oOQg5%-MrhDxOWc;uEyREhyM{yT9d@yQtYJXDu+=j_jsWLmi1Chkm+WaeM0t5`G?~hR^!AfY%rE9{nPNl z=Fkf9#q+&=EcltYx0>@1ElfdN=uKetbSPBELqR9LWO)(g$||SIE2^jeE-i~&M>dT??&-?x!Y_EwQb%+wOU6b}L$d?=YwL=3whmE~i^Ce$wp18~& zrTP+A_2<fW&AgfTt5@K5Hu&#eL7Sx(HVH=s%2bvp0xS}-5s{K?r*;a z1-iCaMnsV+&zz9poWKtY2stSPVPP?vc!()C9g7!uP`Z+ z*oz@($zwo(RN>Rrq0O`|9X@|C`F!tCc5)PgEv10R;*l>n4fqqIc9_b};q`+M7*Hr) z0g;#Ji3HqwER+I7PGmv~1RBtJ7*JIh5Vxq$e|G~U<`6?K?1^YdkYPX|LPI|e*nSNF zRSW~ls9x>c{LHH(i5CWW^&P{25H?`2*CYVY)!RY94dS@w#F?HDlVDRV?N2nYfk@Rx zV9-kl22wQU$M3w2)G5b2DsT>RUY+on=!~SG(zUH~v-<7tQyRXzHslUPDHucyYV0+- z`IwKN;&QYJdy#u2ALiR64?YeI1F8hfa4MC+X2D!~Ed@VIX=AsC1!|Z3Vw}x@^5hYO zOVxaJ1AmPQ#9vsA3caBJYyl8y=KA9&=n^=XF(KH34?xzI1WL__3J_45T4tX*c^67h zt0oAWHvp8cmTspBP{7H4<@qn0xs6h3^)NrXchrDG13Jqd9yXw&Bo9VJBs+?qMgbPF zyIg8i#KMG(`^%H*hv%1o);RD9WB~~J=EJ)((bw~OW7fRSi(jd9CiujVAV~Nj z79l1DiMei;hYC;O8laWLVJAe15Iq8VWRmLVlCHH(hj})bixgv%d%y?5m4{T;Pa&9z zzrfRNc)oe(P;&PiWM~AS%a>oi_uFii?kMe!;tB)0uEHSIGLKxi*T<2pmKkVuw=bsYmD!svLZLz(zzNH_pYx?8ow*Fl}Y5SgSQZM3s)t0YI>d zRU2+jYQDN!&V^QkzD^yu%*Yfh+ z9f_QP0o4ry%5gm$|JyxM&aDwSrEaU;*+Y5COL%e*13P3uVTwLkHjRsO9LTZ0ZI+aZ z56&-ZuHRxq>iTd1s@Xo`hX6qPoT}SzcK4sRW??DYgpRuZwFFX3e+-tEf&?pEip&#nB$*XjpgMT`@xsD_vkN&lQN{JP z79Lfx{zOTAr7GME13Fs+Iz$l~BCw-b>~N9)Zsj&U`~W3rB0w|G{`yHJe0*cZ0?>>J z!3+cHH)DeceKZ_^8hZwJ%no%PlxOpDFX!iQL|FA-H*y2rl*ElgR)x&@?VdDSjhfWg zfdLWa;YYy4<%(}p9&@8~_r<`)UN3pE#lb_&(wo>ID;zw&IN*O-Lkz$R*aqX-F%x_ke)x6kZ{I*+f_O1UsdM_h6(Rghot`3k4VEb>UHnoy*fkKGt>kf0Q1O>OD)1!sB zd(u_fFrYVp=fDy7bOJ(jlB1j8Mr1!Zb^Fo7t=9w~_yB_?pzZDL`&~DeuvVLG9L+kn zWIf;7xUI-C4(4&hoD+tSfGtob)SWy>*K#5h0aMBW&p9F1M6eP%r6{L-WvA!Q$0OoP z%JL`pYnlMeZ@E#tj}`sEED!e#{CoyZAdbMk2N0D1t#o1Ilzh=OEjztZZZ@UQsm)*U zC2yH)Js7!JG)gY}LYK$lnj1&kuL(a}r<+rc9EJA#e+7N5!Fnn;Q`ax_5uj^jrazUm z08|+ec)7dq?VNaLFp>bOvJ1dZDo^)P+5`>NJ^S5#*Ko7eov7{RayH;vTC%Aro1k)+ zDuHuBhhppTtU@g2Kz7McjD^5^jHgwH)q15|Z1~jY?zUDC?$br?cg&%r= z^1HX`;U9A)JbIxG10q$L8PLIvnTmoeSidJbw>sfBlI(qP%%Hzqo|~uq)z0$V^5k8x zLf1>Tk)F^~s-89~&S;cV*yqSLERX@I$bblWghqRTevodOk^=^`yLtKz0BE2Dv`qt= z-RC^o*=K@6l`J4mh-q1G$8(}^v)ItKgCl%j6p*Yh;9$fKIs6EKySaZR_n!!AAo0c z?(*e#0fD}E^uRJ8z@Fl%=trj%gEX3ID@;{*uibG-f&yTtTiZCu=%(cI_ zN89c`@KbZi{Qqt@6;uh2A$5n9XXZGp@r2gL3l#+ccdYhlS8nB#`9}i9zp!AytrvQm zo-K-?GZ2FYkfFYStzsDv$oZZ5+9ue1X%%4KKE<5cVI4bR4eC1zzI@r=q0bT zB85;EgKV?vimL~K#g89<#0-d0$UUf%wp^1r+7;C=1!1Zb%rKyPgGW=Ovr@D5BN~&6 zje!ghe2Wrok1_rN`tz6=5TFjF;X}})D`JZ7IouxUgsuT#kdF`r&dFtHj<|yU$DdaQ z?S(u!kbE0b<<9}67=h*pfD{`$IQJn|59Rf2gXLz8{_@dlF`%_k49IM_#qI4iLwg!W zFt=k5^xMYlEDc^W1Za8X(^i>4LSdo{j{))$I^b1If#tkKe1^+0V;0&@z9#_-&xk?* zYXC+mJ`{R+Gr|N z^GyIKd!+;`gbyiw-N1sLeR;a7G7K;DRGpv#J@n7_|D=O7Pm`8Ahs1^|xzdmCrStEW z{?w4~bea6r=m-N?)=D{1eej9cu0s`GVcNYDrmE!m-cBx}c4-ViIm?m)m*^s|v-MaL z&vGq}QeP{~q(%+sOaMCEtJZO3@+^f6t=6xqSHm1Y;S7&uHXw8Z84zT_p8X!fE`v!2 z!KSY!52!g2wNbC~2T{>EGm1R2O zY4g>?fHtQd<-!rvr*Bzh(EZYPz%qDgcz4M=>ta#>Nl$klF$gC^q1V1!&OPPQ4^m@7 zSL3=Q1@T0PyzWCw?0x1wM7}>UtbBaqqfEvs)fJ&O;ui{C7EFYrrHT`NoVe{}!A7OR zYQTUR=nrJgqTYJ>^D@MGk7vk;c;otGCojdA^IC zSkXv`V@Bp%CLXK)ysV@-?%=ST=uD1AugV}H!mfJN*MM@M;pV7Iq(od?0)!hXF_6XA zVL-)O`~k*BqV2sUtlE6HA`@99ZrWrZV&adxVeyWrEO}hAKU1 z?E#j@tURo)*zeY6!A2rb1A1}5>0SerV6&#Jy!@^~f{F~pz!2=iKl>=C9L!)%7!tLa z>j%&tx~HSss4Q5`iqM7t?LZAY)@0PpB@>~T*UtY-MWy_ysgX(S)5xI+O-3VIJ&Q$Q z=mUbRHGA#F>_cVsVZc#Oh`O)YV4LOX_g-UV-e%HuI5sj)GrY$HzDM1oLlA*xd3*;! zds%VJMQ`AQaev&kpJ1Z zj@y-htEgGNa+4J3tYtvvuzty`?0YEg8wyl!y)YOw``P3VKf87Rw|FnUBl&?W1kt5M zbnx_eeAxTbx7;%WxyEePH6Xad^w4~u(%6I7r$8_?eyO*~sB_f$*&%$TWtB z93-lM$mE=DgNt~Yr8O?B7x`xvIFMmLZ%8mhS#D$rA!8A4eF>_x3HAq4=b8NJ`4GEj zGoaJ0u|xDgHM)&j)g|GvgLSo9zO7C$@?rZkF(1~JbIueE5R-&lv%x;0T*9a&k5kNi ztQp8X0PmMb)FwiTO`Fj(V4Iw;N;g4BwtvKg47Oa_tL@K1DcJMR%)!K9&+GMnn;pAJ zxKk7_G!Z9PMP{yT{;U+8L`ZIe$g2bKMt8y+j|Leey>yu9Tku9t67e52U+*`w;@s)f zbjj^0y%z8el7hi{&>#`o5ul*~*br129)pETtG{Cn8b-@uKbJ$teQG5B&=OnNXIzrj zvS~EJtr*(gL0NpO^siy zZBRF~8rR%|18DhW-dx#%F1O3|*?jdMD=KGOT<17pMS?N_lEN!0xGl_%=nunC17@S5 zNQ-yF1a@-5X>HgFNuy^A|R(F|y;X4}tlKr5+uL(Upx$F7uegF>v(^Zj^~C}jky zq(iXHzbgG@xOCpXN^e<4Wr-`uq&$_q(ceK@f5~=qu_4!f%^p$rflJ^Dg6-LaU|y|+ z5$90X2{@g_`DtZ! zn?RgD3|%?fu^2x|BKfX>^&Q42gj{7a^j<0+(U+dSSuPsh1Au}&s7NG;|B6MpcoU8{ z@xm$G)WX#Fl^M5@2o#8+bf`wLn<`#^eC)zLS8X((v zZG)s3Yz7(7Qx<_z1r|Q!Z2Vv4Ae|)hYFAuOXp9s^#~N7VkJ9sOBVTVEQWk9I?(*Hq zjW9f>EEwj%pf~;X1B9I$PXHng;D#qKBb8u54v+-Pt(qS_1whm%kW4`qfU5PobIVoi zraCz}HxFg_pOsG(my_mfQ!@4~2V~4^s@rPg-!aQ}M4DB;YPeHlwmwf;FxEXz0ypJA zY%@&bgC;Ie=kLV9-GB&y&R{@?*7}tHU&OurZ(CP(F6@9JM7HRGjtZ-`HLlAG!*=+A zcr3M=n215?7J(C!6sTUwnO6!Kr%|d=I;Do3xML^L0X)DUgkG^=bdy^~xg1xWgQ60P z89Bcw09^;wM1$ycW8~HtVTzLcSMFXPd!Kzs>eJ2}Qlcn|lK64wVp-kKF2bo zKk=2HGhdtq0$@?tP3P-lOuHd}l`fAgW9t5oPS4S z4ihAxPvy2PwVrO8w5ubK_(^RME`RZ$0D1VuxZ$YHswmoNMs->zoSGl4h{rMSQRape zg85azmTZ|^CS4D&A75>q?c6I@FYP#r_;n3S6N4WBCaei^1ZugTVZu3^{_$%Q6TU_(0?B`f{ZSN{lm=rU9%D81 zKovBgByR82F=0AbWU7VgNhA_ef0bEZFI5WoN7&%Cl!^6B3I=3jX^o#llDb@Us>{00 zITt~I?8}FWz;evu_Gds6fNRWYD`%!1V^ybxP@eMd_)6NXSnm!Bw{>8GYJzY?pR z%vM{ev%juUCcj_R2)WW>EoFWnW7`QSeR1~nJ*_T#;-#C@`2y55P1jXLOHK@4r+H^i~9}JY?F67 zl>Nx&LuYv%(^K#V#vij2J3`+ds>D%_K;njL)+|l;MxDnhI})^`Ig=a&KPx;apa_%z zjF?(8qfVo#q&uFLx}8oZ4Ps@E3+GSh!dR!8DP!%8<3YD>X1XRMLOqTL7*LH6RX!D& z;461iX_LSvIby3)E>Im%wJ-nbl=$@`OVH@X0aj#5sDuvw5=aklq2MxxV6xehKR^RY zy*1J89&6u>E*k28wzfB?kp{QEH=m-S=ye#R*k zNYK2_`i^GGtg4k+w84h=9VZBL)%9>67gHSc@1WnnlA2N0S=1f)udB9sTF^V3*cRW8 zK1xs#^e{0WNrZG=ns`u?12U|AmPOF5_aR;+{@gsbz5}PB3&n=)9lMqJv^pblYK-#u zbp~WfVgDjG*U^ut1O9kh3KFMJCD4)8Y;FH)sggF^MQ8_rpbOpwF?*dm-I$bp7|DdW zD)56T5G3JoZFW0_KQ8VA%eZFM8f7RzEU({N7grhu5rVCKck=m!KA6x{Bgc|jle+vi zDJ@n#$<|ySP75OqsAGY+)}NBR{zA~>>QUgHahI!rU_e;I?L?5oh{~GXNUZ=RDgu8R zs0NkRtJQn?>NB2k4?3{|^hC&+tVpGaU`8((P$U2aONsz-*kmFDf>G%zTi6=%g$d;Z z&APu4BPLYp>jM!e6Q06#2nipFJ$kCgZ+m_)Q3H}jgOOr5&?h!9I4CfvX8;&b0uiXL zC0)bN_$*(@dddV?4e*^fyQm zvI$!M(0jnCi5*H7hfgKGYMIRLDhBF2W5&&ZrbF|J*_bU_km-0FMr9`4bmI@(ufiP@ zr&r^vY0h9JZdwgXCA<{tX@wwYk-_u&zlJ}yy34;!c#MQN@TZKHs%2M6K~gJ|ane_A z^Ds(|71!2+5oADq%{_u%FvA%yZy0OGk6%w5k3!M}QMw zw>|UCW=jm!3`rH5$c`j8g7f&YR53(U$=iOC_0-MgO+-LjdP3t@IZeoBt7x09YSygq z;5bF*bdTXvuX8iMfAo*D)82zHpw2U!PbJ1R;lgx7k1G$>fa7l119ofIs~21tmtHs!fSr~?cFKE)#b#rnUludjdpFA2j45&-E1 zJFW8sJ!XdIEDJi;>{U3^E`ngCQ(2u&!5D$3SIFJ^9A1Hv&6`toZe#5h;Gd z-=S03l=V|-^;Iy$mYQmw0lwP6=6BLxB`r5 z4e(%%oPnSl-p>XTvR%M$Uz<&Zd}HvkHS|}K@EjNr*;EV+#A0kvpYKBvsK5VDJdd#M z1N{OioFcYBIP_@eS}*0^s~c4)XQbveTe zw1eTG{HLRCyXGG!PP~@`(I(efQ}(hxO{x0O`SV%De!R_)x9vPkYEsBMcPjBEOtiv&q^EqfWEZ0ck;e}(V#xKGj@v(@*0t9h* zaIx=F-^ITY0F>zI5ddVEuCed#3s-ywpR(865FZBlPYASG!?hk*x!Z*uO@@LTtfiwu z7=ReT2i8tsIX*>Y!H7HTdTYp*VE!qQ&^N+1`oJm_>Y%0GwVu zkWtE16C=*~fq^_Lw0RVPz>V>=3^8bz-r;xzgDG)n+Ec&HaPB>Wp;qx!5q7e=TD zY^$4g>b5pqLVH@Ww|vw!_fNBVR}4hsAr2Wq3bJ!{uIbgfz}nAJ?ZM9!47>M+C@I#i z0kKp>zZqY$M-|;!qH)Z&L?4(GZ6h8z&y}CL%d?fzVx!73T6||uRpy#UWk7eWB^(=Bn;Fykk@Dam`v zYTtHgCv>?8AL62Lv9GW1VqgAPV(ZvI&j2wXmwx5497Bd9>wEo#z--1(7Ht48o;7e_ zE<(Tg*TgAQ1#q2;)Kt%NeeL?K;{gv(9fX60T<(X2`Nxt6%%loDu!TyK$R(57X{SxJ=AYT1qJ$Te+KKPp?6GB zr&1V@Xk;Xl*${jxKRMYGv?a%9!aoX&eo5}a00H)wiBpFxsLe?N)H0N3dUp*7il0YD zoT(j|OybK?T8r>7Z274CDkecD8y4#A+`QRK=Y9`qAizc2o# zeR*y=CEzy{p3jyItl`Wqtf9`}?oJfPgJ~wy1WcV3Hv{BqlJvV+*^cAgry$xT^hsZ+$)S^>M4gka)XkDOAo)sauO0GV?KW@uHS<0Hw zu}C*=@7%0pGU0yUO2mMu%%&O}f$8ug8$FYQKYT<>&E{oi^P(1Ko0s>OJM*FG!!e+& z0v6p65p&bKF(8O7Vyc^Yhd*ir~hI*PT3 z=K`QlU*Dxmu~9CK@2L>bKsm9lvM%%(Ih$nKz&t2g^N=G zu0$*r0}*M>0riM}{}vS{e%&?dZ$CY{Haq4E`S^ugv^Z=<1>B+#j9@1}(DN!^zlaPd z42H1IZdu12zfRc`@pW|c@3;P?H{6fLMJ4FssJ@EzHG=&JrXeU$74*1A8kMls(nh+$ z)WMFQnLFg(8B*qIS_C%t{)h1oL$c+_VL()EUI7V+=ueeGu&qZNi7erX(TJ$fk_Hdz z2aGd(FI(Nk=4C9ggb`&){e>mxLfx|D`et-#TZEzBrb=PC@W!i2(s*S!cN^Z)R8}HT zF60PBoWl>1QCV}?>wWJ;;>Qnd`EccbHk}!+ z%|lAk({q9Y+0@d4{em<#*YL~YS49dqt3!*L8PJJ@X||z{jI7!ME>F9p%{sS{y!o5I zYmANj!GHTx!x)dBnfB($gp4xOPz8-;K3ED}7rzeIb066!BD)#!H8Ha^d zXUf945ORSu>`HQ;!#i4zqAQ%wh@T7#e&?% z2ez#VB}@8xWx9a+i9(bmMlc6h>?Jqav>?&w(!(W2u_Y2;M!&Sd2}p4R7X$LjsTaeF z3BkCqYY&b&^T6qftvx^;h}9;cE=j>t5|_R8+c|wa z^r78>rq9GpswpC!6(R~;x0KMOIbeiGun3@&VbvT1Aks_llNJy%p|apV7r}zBFBTiQGzCvYDaM?! zGMpX-#2xC8M48ynqta;cDsS=?5PAg%0szv?nCe=&tE^2!2ISG2dfestbow&hC=&vy z7>sowra$s2hQo#RQVnaQp$@1NMqT=UO+_LU6BYwx4UG&4La;UHQr+@@Egopy@6@bN z)rnw04e?^iYVtCcjF*uBEs9_)ye_DY0HDtW?dj>x-LSSFzP?0i~yhkVnEu_Ojp$53;?jbb?Uvt9=1MdYTL+a$MXCC z^^-W16U`0h#x}=%Ik=zWRSi)g+5u%oHcF*`AIbc7%HDNcxQtJA$V9&=>*` z6dZO;n}MNyDs?_}eoS0s&wlxk9uz(X^{gJsXP`sml45i=BawXTZFNS-JK&*Arv-+{qQXRR#f-oCW_RP? z1OP?jXT5WRJ_<_d>n@`b(v6}sr*1Io4r`|yzjpIdzK0B`C-&~K)2FA#jXL!$W79PO z&5j`(v60IV-@)wEj@BdKkws|mEY~pYL;!?wM}5axyLJBs001BWNkl=r4 z0)WnO?LPh7qY6j;T%aaGFv)-%33?H+XHk|XLU*l*iu$1yLoh(7i>|JtHJQMIKaV^{ z)>B-e_>1~7R#1Z$Xtd?W$B9YPx-$74^=~r+qJJR%D8l!m_5Z=khYUzy(0Vw$F5<3% z5`2RUD38Hd|1*F8iCwp0j<|CG(%C=y=-R|)qte&}_EW$-ShbqLT5176ptuYU_Dufp zku4=30-+_zeNYyG^?x&aSWgGc!V>^#3~27>AHM&7mJDhp&Nmt<--I0Bj0|WbHkhxD zjNHEu^-ki!z4PwY-{a$1k`HkS&q|{j1wte~m$vCUUZ4Oxqf5@BZD&9XGvdnj(zZe= z2}As2#vXx6+e<$ljfdv;kW5rardiI1Qsu_^?68JVt&JGD?D?_oG5GN1UfiaC+j3G6 z>1IGnTEsZ&gwOVpd?V%2P>1U67W_Fh2YN9+Zfm_Oayfdqo0n!GaX^7fnE>d-ykWTP z13R%Do%8T*2IRUSE;6X88oCrbtJfNh&F}v2smo`?Q^*N;&-%t7M zi=?59GBh%vO9MTVQ}uCUTy+vkH3k(MZsDf>N{{|THA++08kANdLCJu+r1n}3CPA{u$G{Q)ED!^9+8!1(wTsd6H{IAmy zWIaW!1Clb(iin^QmbUD!u1{>Oz>jNNkpYRlkSc#rZn75XWdyyF4fRfg(5&{u9a3;K)LGIn z)aUMO_-GbYMX03&wZiECr!$2f8E_5dnfcpmz`O;meR_dkC50F&_%n+z{W2 zKw=evdBNJ_sWb83~q%2odem;Kz1Cvr&Q{nKPtU3E$79M93Ki?L7hn z4NniBjYs{qG>qh$54H)AVTH7Aqm_CLyWqL^yi>su3MS%Dei_Cu_AW;bh zw1p4TvxEaQXmJ^t9y}vNC41-OL;+qs=y!x{;YpqLIA?Y z(EnG7B}HH8+1s2>u}2?0lLD(jWIz>}-Np;hfHHysP4<8Wgt41W(t!zp(8NI zP-LQ|!$^0Ho&X;J#K*AUV*-D~X>f9IBrkZ{2t2sK?~=-+cmU8GCP7Q|pn)AN*)Aam z0H~`~+v$Kl8tnlVCC;#fx8bjC>#S(|;g_SA-G!K5XU4J~)HqlKx=>0)1*wp>;Js}b zGc2AS_Cg-);X{>i+kU7$>}?k}Qygt{Nz>t%mLz3!lp%UUmjnX}x&OKMkWpADm-D@N zIZ@X*0eigdup@y-W_0)`bpb#ka+~)X8qM)*!j4jX4XFY9`6j=kYWq!|{3gDRd#s1kZtgnMx`g*BQ0I-4XL)^b%;dU=d0UFO2Ar00u2_AQKZh-X5 z`ILS&l*GwS*VUP88|o@ctm-sA0IekuDIx=swGlRDf^0pHY=1I!<<^x8pNYR>!-s#g zE~{mTkkEx-KrH$!vWTUUdfaIuBCv26XdX(z1<2kM!UdQp3=`us{VzNYurLn%CjwUlEZ6Zvhn03L*xBm%6kr0BB%+ow8tkoO=Uf zXxnxq8`t@fc+&*G*hCY@QbvQI5ojeVfdnKNkfR&KKzq^)s@=$do78@B6B&~|oK$+^Gz@p#dcTy5ENBDv3qpCtrCXYDjg-3)tbm^cs z;}5rW6`SQ=y4^;_8#vME_JMtMyw3U#ofpd>mGgG47m`66-?w>c>EXlChuh-gA^dZ} zf9N}WSP!LW#o^(@CD(=ae4My!iEAph6WQI8><4;6xs*8NvS$-@o|nc$ggAik)ZKn3 zb;W?rMh)3+X_(SE&!Bo6R((71EcNlvV ztiTm;;DI;?0H}qS+m5J#_q=c%00_7c<*Q{`zbcM}@5a%N1A`#SZhSwRAL;? zkOow$LYN~M5Q8H7Vd-J7c<~a4PQi=i)XU>ib|1{lryEUQ0mfb9kfV`U2Kq!YBUPw} zt`tiBn}4;0nLP(xT^q}i?Z(|D`G$)l!X6#n1AO!%AJEx3XSSpuNY{Qxzg)W9T0-e{ zom&_YzY1Vj(;aH=7P^IGKm>SnLogr#K%+o|kN^qPgYN~x;LW4>h4ORyr>2vuB%aM& zkv`fO&|!q=988e(P2{|Dq06St#vf`%kt7Ukps=H^?;HaKXdF^a27COP#B)3pXsNQI zIy%fDePYkbIw>=1%n)3Al=wj}>dg;gvDhGjjy&~M^L=9L>Whu!^AB*N7Q9GsBFq`d zXoj<31CzmVw~V#pS2didh}g;uWz?^lfRxB#OR<6^$DI`%16aKK_0=xerP|_$ZOq?_ z+qd2jA=riGQCm=>I$ls8A68D(xw{A%5CP_*))emoAg~n-bLmQ@QnM=JCgc~eiDxP= zJPs1=QAx01u;{nfU|`|e+VadN(rila*C7Vf9QKu^4@XV>8+6tN`3%Cnbtrv&fD8!4 zAQ6IH?7J7n7rK=Bd}_y5XzG;0+8{!w2qF7R{ozVUV?d~~2#x^^$d)7V{Oq)6^PfTt zOPoD){Ka;xJeWDRpABECu}Mx#nUVVyd^JZ#GU)tYtMvZB=6(aaCBvs*(exoYHkN<@ zxd~y*iSp|X0xc;W34Xn`IOxaw5Fl^Il`VqmMXQlj2{RrB=2Z$1b=K4Ea{xd9GI)VX z5TMaRgrtX@wgU_zHZ-bk#OpGBCKF_;o(OJBg!X&TyYD1#O{B&q@b_>0{3cp9)*YY5 zI$IP-9YgjZVhHx$*{F>n79ou^s*)3*Fq!X{(u?7cC^n0eJcYPQ@&~=xC|(vv?no>z zPG}spUS+4O(gSg>Lb=KVSRUddOq~U|o*|F`4d~Kj&ldL;vk}XVjIy*+s=A7?K**7b zhJ!#-<6qkTq=>Oj@NO4Spe0JtD%P{jA|2pTP!OOi&)$_7hJV>c?4imvOrec_HAM=H zg$&4&o`jkwG>)9^uQlWh(@Ft`>IwA0D5q2*21NBglmiO{Ry=-UK*i5ymi={S1SU)B zf&ul;0t1>L3u>xuKzB)c$&vI32to~L9W!FYfYu4`GoL56{jCWKL=zj_rfZv+q>~JY zNDu%}f9d|9h{1k1uJ*3Fru7p&wLSB5M*tuvxxRNN7$J~M!&gT#g;_wLk^7m7g}kWu zH#P^XP}|M%xB?X!l}mi$bXgrGAVQ`kjWM_DTRJ?s2$n66BaX%d0XhT^=t~xMkO0xgDAolywLh-X0lrz54z!mLaUN5p;g1l9<$PGL1dH)|P8nl+=Vqf9 zZ9*4o1#u{c!|+*wP>UljJc;mYJxoDZ7#yIrWD+o-i@<~w!;ej3j4gvB zXOAPsv($C~ZR1TV0j!0-i}KnN4CAEW8d}2N+NvTo0EXh?nyo6eMDWB215P&4-f08fZY4 zRX`I**;P+w7b8@147P|<2D>4v`JozyJ&K=r@9_AOo2^MRj)rglyE6dw->;Ui97u#< z8J;~m`xmI!Nttle2@>@{QHGqd4HM-4PsrW7!{iC+60g+x#<3#)-3_TrTn9$AfQAoRZFhZLk`F&4XC0^K+$*`+ISC& zL7@qs5|E~EpWU);`J#K=QJ6Nf1CQ=wB4YcBjkl#gXPte={YvF^?BeP&KfNQ39&y8| z!~YYn|8JB}ayO_HU_lR7WR!u2ycd`7V%$|`FAka)$r$u1Ye03|WjiVD6`V@)y4>8< z(XymAux;%)fgKL=@PR;a`E7wfpcV4x5*4g1$sl-X=fVqu0iC-mbGiPy!n*n>Z=mAY zZpV8YR8c@6P}4^AD5rRm+5r8eEzvz}b=cd|Aqaj<;IuQ}Ji@Dh!>O%C zYR{$aG+mv7a)52IX~G8_#_;jb$+@G*u>Fv-b=&YG{MwS`!=eI?!7w>tZ`<*o?V*6_B}8ol`^cdfNoHyX>GBLr$tI!H=I6BodI1$4QR`Tzh9Rh_9$J#znA-v zUn^+wE9#?EWvaBo(vYRkXrV8o2)&JU62OjZOsG=L1m1n;IxwK`FVmlw7B`p!SH~n~ z!Dd~WPo-w5WO75*%WcBVXw@vfDc~%<3`b?Xe-ilB8nvKe9v;60SGQIuB3rn-)1K}F zLo(EW6a(V_$ zz(KgH-R59H*2W zDJ`f;Cm`g;H<|k^!pbjz!lS7_@(L28f>^+?O|x@E0T)|u?FYeM7SR|Q12C)-2nK(- zLYmORUG1&HcM7{qU@T9H8pz%J2fslF*uE-+T0N730hKT$6Ab7`|br3R!c7+>ar|=<4!)BrlaI5+L6J2du8bDE@dX)mLuNLeD@Wc zNe>f;B*`z^$;(H>9|9nE8qnJ*m&O3ZB?LBAMiScC4%+YqKoS3ZTegJh=cQ4FL3GQP ziT72L+94TG3vSJY;`Ogul}4=`Q9B(o>soT#@30@6onmZ`K3w7(=_9tT_+m+4eJe2) zkK@PL?D-dAbQ#QFgO3y0?1}7K*%NP3YZ%D>j-8idYXJb%hZ@jQoh$GV+i1V3(=9}X z2!{Ol<5s<}?tnWKpnXCngfm^JIod7HWogty`FTo$2>?PVQ`!BhItCuHU@ygI8~XCc ze3#X5PbTCmn_>YMX03{xw2o0&Z||q4hl-SfkH}nDAhL!+Fn059ixO}A01F8@uX>_>(eF3c)yECBbeW-ANqJd5R zZNY%XiIlMi0@cN0{}EAmlP(NDH!Ih7Ff%bEwj>V^iSX3rxUagZT9Gp&oS|aqHSO0X zXGpE-tDX3Xqv20;0`i%AqygOw2XOC!NC`3+er;pg#nx)2C>5x$gV7%+ ze!goZz#)sGZ=6beWy|r{s+4BOjYg;r9fP|WD&%5`hl@n&qjhRpU?s%0a48hBU8p3O z-J?feKH7ft-sH$K+i6Z)-^=- zx1sn~paE$^3B#35XCk2s8feTqjfhA55p)Q+VQ=M6R-q3g!r>Ry0<9HEmtMH*@tbw- zu~kMSh6urWkpca>!+3ZyrGJ1%WIdn(0dRl@)b{{1Xc2|gvcq3APbH!lW|OrNIG6y5 zF$4pu2@VCwQ{V`UK1S#dRh2)t^q}-Rqht*;e&;A#KbmDqEOjlv=@0+wzY@8*T>z+5 z-KbD`Lq$zXo&BE2FJG}b+a>VWWkT{Dx~StTi;NQHL#_;6?IMh-OI}DObpT#G^Igu* z&~h<#*bn5~3=gxduM%gcj|xEDZ~)~F)^K&o*=?7Ud}wlH{568f#K`L05G5~sqaW>2YcY4c?$iC*2pY6urPz>MtH^s7!z$Dfv1Rr z^!8gds|9`F^lO@mfsTk2f^j=M6(W`zS+N;>(R}@E!elDLhS}n;`>*v{f&oDmtb(qt zQiEmy>L&)&xj)%75@)?fS$X8f%Fo56K~KN`lb?Lpt|}2;0h>hRsf5+I=0}7O|;1rFa58&1OU}}nzO&I9HNLfIrVS&caT#VbwA&L5g)e+ z!Mz_HZXlz+#A!Np=zsvUz+5HuaS>CrW0 zSBI)cLOX<(hDLj!HIjuO4Uf!3j%Ak9l;^Y9ZJxCn9RLU?qgE*dlK=$m@c9xZ#A;c#)SJ6A zpD<*5pB!~|t+xU8X$pN*5Jn-GU_j*0?P-}qf&?gfdHD8`m5)ZJPO$0s<5M4IZ|}l@ zD*YLYvhNCjdTW*b(^xlauzPRalnv5kRp;T7ex{Xm6ZWLw2VIf@nV^Un2Iu&=v537g zP4Wz-4$Oe4E!qhIcbq~etty2)pVYJxj3jL57U{Q- zw_rMNJ2BA_V-62L@G#HBZGT-&pHrk~hqXDta^R20;=dW4Pf4^N;q(46cZ$wJ1=J0tIU#!Wc~#W2yJ zn4YCyK2<;70w3a95eqY501}nmO50*X3*_LAxDP40oi`;yBfOKieFyv?Y-9e21V~P& zJ`e!SP2Z`j>5J-E?_{8<2*;=z;ylVzO|hI9fc{l7k5_O-TBL_+j*$U5zr${< zb@9{U4%$VpAp`pUXRsU6Mv2)X6YY~gvGt(pIv$_xr6Zpzfdt2~ERBpf)-|A5luDK~ z6Ll!dZ0~Q80R^QYqBs}LRhn72aQ6d~SB!o#=1FPsx&FTTqmUKq%Y%`aU_b*LL{;zQ zL5&Xkn!{Y&?`_U`@7y$XLB|6cPy?n3h1aF8GErXq@Gffm88vkD=wI3k8TbPpP! zf?P>{7!Y)uYj^BCjr~ovEV*EivFgmdH#P+Brh>vR1vf1j& zzeg5I`-#2vSGndsLD(T=pfmGW*ki~bjAqKH1xwMbU_cB%Qc$57(XaK1>kLRnVM|>C zfuy~PrUDVo!;)dor&igg9F=^QGR;x;t1k72-IWU$FQEpcdciz({Y7#q!_s1epOHam z19qwgCqH1;7aS~G#5IL4&6&rp{*oYr1A zjv9~@4oD|)`6S_CiVVnsoKgz_HB^9RK|cmw6EPTgo|Z}lxUyNP{Wd_Q(CknT{$$Bj zipLgC{wmpF{TR^hIhSh`8l6tSfcpCSsyGd7aNvH1s0@@Q)+QAEP)cKZ?o2$Y8DC-u zCJ0cC$PZnhcGQOqs8k);g#krx-no4=0wlJ5O{?F#4mz7kfoC$8Iy9)bT)x(oaA^a^ zNXOneZS3VC>;Sq4EGLuj@~;R0a(?1*gO#6olp#ep=0~Pkr>p>l$;6(_@v}!IKuzBm zK9lT00f_Y|L#_+1JdlC`ZoNCW=<8U&VI~sMag2wQqHZ|aW?iQL{NrE6VLG9AcLsDg z8R$gZq;=_${}3)PMOmjQdv*UYD(jPB81*_4B9WTYlF1{12nf*CE(f8wQk~=((u?cK zPaEZw>|r^N#0MRK%H%)R(C68(3IvtX7qJy=GH9^;2k^51qd;80L-mm~EYM_KSiX=Z z5@X6^P$Gl~x7_V;yP^SHzd``w5gVjW;-)8l>hUj$o0tKuke2D5vZ}$*I7BR}i3w$% zN=H@#az%xTrJ=wNCbz#z?YWuCr&DB9&D~%)BYqXsXb_=SIslM?0Mtxb9V0Llp#=b; zReRsSU{#JLtRnujRkWU%PiTJ{y5VV_E6dQVLc@SCxPlr`y8R)U3F1FTK%fcjDeMP8 z-icJB*B2txM^>p`0P+YLiB(G*@5BxF@a|nmP;zw{00>AiFd%v&rhB5W`@-YqP|na@ zC)hL0vqvRB%@iF*xq}0c>35y$JQa@;dQcVaF#rG{07*naR3^g`&BlSHKY!|M0v9|i zmbyp&Qk^kNUNP!hzsYrYGj#@Zm|XnynYckiLQOVQHu1k>y(o!j25LY`1fsLesd;2W zbwzTh`KrDoC7`ca55hz_$-^p|6le+nG?vB8OEy*0xQ~TH``Q@LBGygASe{EgJv|9q z&g-HOo5ovE8bi+E;Uc&?k(s*3G*oqpU-yx%Ly(2-o)m)lJ&ID}-Pe!-4G{oACG?7R zu(eMEAqM315C8yWDtaZff(QXT4VEhif5d6z)#}K-{6^+;OnwE}lNB3M*H*!!ED%^e zxv<)i0o}MQh{LZtCELiWy$?e$L0ftTX|9(5kZNV3{dgK~esSV*B8`LK1PuZJ5)2AT zq1A97fFQa8CX178AsE_+CoT_b9gE&0MPME55IgC#W3ywk{HktBxJLt#Oi7@7rP4n# zvR??s?_x2qB94P3)B!DAMGdI!oi^PN)bSpy8_^F8PvX>3tAHdIoH!@|Nu3;dI@W}e z8b#rtIy0*57)JcWdv|Uo(8CLCOr^SoA}7*04+-tY_}Zzty)t2kRie)(#;M|rEmci& z`(bY}0HkAei5OaDi6Dq8jfo!F3{CL;j)+%)0jbQmCJ?J2ub%u~!zy=Y!OkRG#_lij z55&2BWw!|Aq`?FO$`ADPOnzp_w5c3oMlZI9R2ak^Lpw4I8L+e3CGa%?T@*(X+NUw1J2HKNV zz;CHmsSLg|W$ZFc!F3X`*UF3txFHQD8BnKfW_JqZCV_m4-#Ka(Q10M<04PEm25~PE z*Hv$foC|DnrjJr4P>wKeTyEY7-8p+RF%Hfb3^_`0_b`^4q+~UlPl*9F=Wd*tH|lQY zsHh_+CXY$ss_yCnV>VNl#X)+5>Q=ERLT4&sI2E)1O?u8ip32U{yfTx+QaZ~I4Gn*iNmb5A`U}F2ITQ~`8C)= z1{4ggfH-X?j)Nc2_t*A0ge3!#aaM*a<6KI!>Wl{`V{rPape0$qwA=aD)is_B&+rpr zk7%+=OtufF9ls29Cb_XfM*xCSqgWqyqk;xhrNX0XwRg9}WB4`VK#~E4GnI-eKrAT~ zA}H#CIw04)N-6*vCI;kfZJFG6xAf^nOxD-|GC;Yk53K1c>jlie1F3{k=uOasHbsmZ z8$7)~07VIaAOwT5^G*PC@RN%jB~INqaw7(vCJvMan|{&o$O+`K#7XK=j;pfAkY!%5 zfX3rz-V+ZlbZ0(VA2&QwP?v@5q;}z_0HC?2r2#=f^c~O|JsMIQO5vx+eM}Z~`dwqP z{4K7_j5FW}12z(m0e`x>jJni=xq4K<9rV?MULhC|8dYRN!%bhAr#EPAUyCjJ4|T3m zA))}FDZ{{86-k4*oRwLoDU+(Esufmcz3vkoUP%bSf|26T+cV2a47S*7A3TwjISN7QojhiVq1IkDMvKpzBN`=w7p!&ddEQkgKLc>8QiB5b}4B&~n!MHA(XBGkg znQAaCo(+?xZoSo^;0Qyo(ncNtC?kl_z+knXW*3+CAoj1%M-2v`UYOevuJp4RkedKi zN+Xj}19C9PFypWBb~zmKwj2KKb+m#Rv_{@sW107atzHrE7T|>i&Aq^_7=i+ATK$9j zhhPX#$p|o@p(y0x1pp11(cR}z9pDr-z);jQ5_gWA1d{-CFb4D@cHn6>p|bK4uhpH@ z9mfyib3A%^dU|?pdOCD!J|P~j(P6|NQ6ghkCChuHTzvDye6k~I%fR=T%qanXsq-0b zKx{D(T;QvT8EsHw*2Id5%m4xn;cto`8CWI(*#U}x@Vn%vV`x|E%VoQX0CD}{ZWM?n z9fKQ3&p^))w}|jC%6M9$Ekn;D@2fnDO%Ity(bF}wQXJ~?yMJM=7>E?_4jJNZ$8R0K zq5!D#5ge5a2o=#Wt~FFyFkh-yCc;1}t)Q@b4+{h(`=mtJ_3kw^lyaBUeV0=<22nLi+w+#{Ra4?9M zdZ_E`741JW~leg}o*V(`0lEW@98 z4bxlG)6G*i6H$zUzt2t7v=cV#f}0H*8x!oHu=LXgJUYw zXnokmVRxxy5j_Ws9{+L?0LcB*RczA`0F(%j1{B-_fPjh^H)pvS75R?UkNu{!q9g+n z7n?Ooz=uH!W}zCw25ify=HL0fsmD?RqGUWyFQYMq#nq^(P0NOV8vi-3_fV~49=-ws z)2jeL`TW4(2u-)>o!GO%`gO4(nrYMc<6Z(s^2~og=DBLtGkVfX0OHkcLI=~3FdSVV@tGVg9;X9Y(5TkT_ zLNL|rDKa1!uXHD|*LpohqHW!jmFtKeCh!{BhmCMr$ERih0RoL;nHZ31kPt>?p?F8b zFQ>$R5A5m7wUqC?MJ*V5-E47U5q~8AYM(si`|b@0{OK8-GSbe91pMiYF)dRdw7Y1xOh}Zb3h`9-zkgEJA>)Vv7?9z_Yd79IF)tSG?V~qh@Dn)z z4fK)-t@Lk0m%FGQ3akWt0Yawy!i_Y)i6P#d^+jUzw<}tWO z2FIKF5o9>1G^F4{I7HetC2E)fkwDB(w&e*$KczvaW4|-7xLpUAl89XDL^0v zK(LwX0x@4JaOn?~tyF-gRI3|RoRI4HLQ5S8DNt~=W&K1i7kmUj?Y&@xKR~R20Ras4 zjgZz|%kASZGkhv8-qv*dW3dg70X?%Cwf<^V0MAHY->Z3qpcur&z<{Ls3}5E&3?C%J z(>jVTqN8;Jg$yKU#%+;}9T_Ke|uM?PkEP z+AQROXYRay^!2GKG7rLl1bn;}ci4-k!yfGExHTJz%U%Z}Luby$&GB~8G@3>Y=*dCH zMcLx=ec_Y-<{WE@ZDbj`4y}&df<=3vQ3wEnl=dFn%1C^#f!X#(cQ+-#*ny*=)&Hm} zXcdEfjE<~=0{uV#@I&*dogfVlaTY*OaE3xKxhW>skRGkv^&834w;&DnY#_O7_(g0) z)&Wrrh8j>qMPN>DM-|JVO$Gx{CA?0i8JSGwT7;2@d%~ncJ#?lDSaAKz7u71wTDw(3 z0|Uxn47QO$6=&Z~^^4HuC~Pe8a%$6}xr87@R}px`xi23Bf4E7g14{FzZ=~b%cV3@s z8{yz>CqdYKrZXVjh{HLh4tz9sc?qmAd7&BvtP&KrhDL8O-RXIJ&b|W&gf@O{9yp7Guw8)PhuLLK8rJ5Lwqz66ho)H0H|fbfUe)Va{LN0plJKw z<}Yc}xY;Y!2L>RR4r95JU^)O5U=mS=MQBXK3-GB_YQ4W7QIp|OhL+}J;>%h~1Q!3N z6Wnukdlv>&Kn8?~e#ARKlYJ8_b6>m$sW2n@gNa&2&f@{_f5C>c<6$nqaDtsyYQ(^7!p`~1{c}U*C&|)A)Vd>d2-?-loLl+syFr4 zHDmnno3JrHulW^;IPCW8r^H)7Zs^a+FfLC&Wda19hx46+;&ujfkkeWbm&yvI!S=c* zF`ya>&j>%=k^#9r5EohgK?bx4j))*a59HsSsz-NCKtvC8Rv#cjM}l+$S0HCUByd6% z+HWSV--0y!OTd8S>(${Xjv8ReN?W&&L$HzrAeG*+v``EHsGk6+MDuRo`fM*SAQXNA z0VM=+Z$?W9W+Yzs&T*q)XtNUlSz)CCkuRC}I(Co+aOWmuapM0H4&yYQehES_do&h{ zZB$2Mg9DRXh-g6Z^Lx|#7yZh~dh&uVi4-+lw)$>6)_v*`H(LP6=}V~!29)0YSdiEh z6%lu!xVnlBz>$+zuTmyHYVP`r`fk)K{b6su%NVy1sRu*TFtcACI{6(yPOXRK+z;;YfuDorL&`MfKVYA6+bU> zGkjYFW^n}&#bKZUU5Y(F(DQsg|E`WA(LGUT4`M`*x=88n2wO1tHFQZ*?kNZWB) zZc5@S%%hNCH@e!@<%#Z+@#;*X9F{HU;1^H0U~@j}02&bDc`lTl!1>2#;zt1>Bkr17 zCLZ_njn@SPA(}*=Eu+zv?>P%5);Mw3!Jgrb6P?Vnwt&0zq25 zcBaOFCVV79Bc#+)6CrjALIm36-c&HKsaTtpMsFBnFDT>96f&9GwMej7j7UpX2)>Hg zHVgjH`YKABMttu~5Hld2fQ>MesT@>Vx&8X(gkk<8PY&Xls02fT0*TMT7};?o=FiL> zVZDXe35_)%U&~mu(PapG_E23HnAD5Quko5|XG8 z{G|Egn441|p@}a4beE6^QwXS3ET9Nvn7anu#DHLEIk#Xex(%T9D(Et|!i%pT_g(Dk z8+d*|d;tJTw;Vo)KO^ggF7qN09qb4j(lq8Zx*0^50)Lpz%VNBMv8HpBhrX104;m#2h?q}^5Uf9=(I0AB+lUR8?h62#oE-daI(jN}`-?+GUlMe@ z&@4vgbi*NEx#1pbmTQ$z-h2PQe)8dgvS8XgNb8-c^#1A~gkW6v3Bnrz&`=xV?3#pk z>kT3@{@D{QO{XaiUE@SZmJRKvi3tEQj-UaF0J;OJiyh^)xQPj|=r^JPVF`9~UO)nE z;nB2$pJ@7+n^Vw|U-+YBTJaxk8-|sP@pB}&vP@~PXu31iO`C~N8#ows5i5X@0J;0X ztg!G-X&8ibGH<9K@}$gM%M1|%7fI87WpH~ijfA6^bK`fwb^NR%Jk7>OYR zdUyWv@R7DhNr3ojwow+_5^-ZhqEx6=z@7ei;=exJqYlWSJu({!4H@sWw#)JbzK3ba zp;x))0jWHs!LH6+{o3O?&gFKOmT`BQZA!i< zf@;>#T&I4C*XN->!-yK+5CigJ`4XZ9g9={Ut9#urO=C5h=>3*aPi%AJG>p}?9NyK#i0iC2&FEGy(|DoYCZ_aQB3^>iysVm=td(xJKInI8rmQL z`0S5!t#)fp3w@91y~Hh)rU8%+y^JD|(Yk@9-QkvgOzByPCkLQVO6Bo#7=MKhkWHID zga%~zhdf$psKXxeg+L(howM@^0Z@VgeIp^50L@b%G$QDjS`2oq!vYonv}{J*iytpm z1I{R6@YWH*b6Qh@qAs?S_#PZ2H7)?^Mj5Cr|F!58L6a2p3&0fjYWohpDZ#kI<;hZLYlM8MF>Nfx2W9cC4&5k_Gb zjspTA0AUsk58bs@ijkmm`s&+IGlE$#>S0Q`JY2rW$)icPN8E&dct~+?lK2w_F9}%e zrT%|C{aDMttGIy1^w2`#(xAu--hDNoOiAj;)eX2dahMINnXP1~M$(}`aCKua1|itw zWY53fK8gUXyr@H*gwJ+EU@p#3B@c!2jjYxwrdQv3TVfS>u|rtHXw^2sfkQWc+bop^ zFFlh;x9JA(3B0EmTwPt|`6E=4f$f11gI(?V$N?2xA|Si1t`^17v$8xhGlbMPjdy`0 zgv^mX4Gr4oyoCqfFa!fKq6fqv&k#kJ)Y2TC-?eBG0x?55tb7BhFcIgaF^i+4&@qP; zNp&dsyXT&pp|CeiJcwTJ=qd^+v?T{wzVoystDQF<>VTY47>i`bp*Mmt^kA<>SxP{K z{3WP`9_Z=m%Riqu4Ess9Fl6}lmjpjSZiXihLS{fxpDw~ri&Tjt_|L85FTL_gl7mhG zU|g_DNoD0ij57QoSJ68ceppqs6;olPg1gFWK$=)NAbFZFVPa*SZApNNU z6*`}FY8LnUBUuP}b2LK>4E`%TmIrO>OCnAj9J~~FH?Yw4WRhEbnN>2w%F8{$7rn#vnb6NYOHD9zbrQz|a2f$u-}+)rhCTQVRnpiucs z0YFp?ZKS2P9gVhWKJT46YpX?>91}QHyzl~tU`44H1i45^Jl(rjyXZW#{L43c zS%;X|C8OHv7vIm-&jO2}9W~6J9Q~O$Bacylb^wR)PPK>eGFdqN#XfaF7Kcy$ipS&* zcZ9%0%jgsc$}2O~*vJS1P|xNQe$zWIZ|+ zg~AAV!GeBO3{ox??g86Y@uxF4Lr(>OSOq!^12PP`(;8-nvS=9qtciyT2&=n!?ylqs zhWo`gg+H_bT}FzUb~XpWfDnkxw1SV|g=c{QDVoH2fi$EKP_bYGzZJnuhpvi{B+dAh z)&v`+0jVx9tF8S@u%d3pA1+2*WJg4zK$rS1PDS^N!pvQ&qN8x!VeuiWKS+WE(-8;G z4A_zt>1I}k;9L|T7-hj;34-z?4zdW5JuF|GK_6^9|MZzu$J$k&wabKN_D)CjIgDPS z5Hdis!#|!@a&tugbblL&JbrWcESScCX!!Hd04QAIMl}tBAP)}_7*s;{{_Kg5KQDw( z*p7nlX zz<}H>gYpt$s|c6)U~UOwFcN~6yRI&ytt_FjuSdB^#79d|j05tRh zhG4Dj%emBU0Ay{3OJrIGo~+Q1QL!r26ZYv8HHbu1xD{YWpn$qbJhu3Yw|C8gNd`nU zgd#AZcGAk>04N8{EaOHW_&eB(5t|(7>3zbZ6LBQlz=Cj+-WWzH{LO{s zndKFklEk;<&HoHdKk<<>eURO#I5pg#aNCXYW<-I8V zMHEOd@8h>_p$Pp7Z;o`rLP6N_W;h0W`|Z;y_ZS0gRc?kRQk}gDL9^g)jRH6?SMZ|J zp9%Medry<>Oshj7QA9=oxF!|?XK(M91*`RA2Un(0sr6Iu{Sg>YM(f1jl-P(M7Q}#_ zLV}jsz-p{NQx+_%5@aD6hH0^w%f^FV1gN|M{OJ!P05uwgN};p?qrocu)r9FjGHBX0 zy`Bs>wBrOEvKdfuuZxRDv~Q3E&8)0Y1OTfbE}K%G=#*+$JiVYXmOC^9!q&{d!jREX z21-(DB{D;W23!qg>~4D48uUJW1{C_)*#y=j%65#j&VbTbFcEn96#+m_phgn4xSea{ zn79feF(Wty7&>88M}>baUH||f07*naR1lOlWg7=*KxK-)ko*AQIiDKqc6XsNM^f;! zSpK*QB6Ob!!3Hkn`%W*c?w5!+JJ3Vw#J)u(*Buz~CAT&t%TBZ#*^tPo+KZ($wM^`G~bDBZ@v{svX zOi^BhU)?}}DSklh(!t0xFP>=bs{xU0(_h;}_-I(6!yO%3@TM3Lr1bBj1~l2T`4r@V z(3nMu35NoW2>=Rt-L3PXrk0WRI%U-aLNLRuQVIhF`n9w)vnqn9RV%&UNu;F?osLot zfkt3+>O=|9jPz0%lE!espcWBFC>trmwUv`IGs_Dnmlswdk;v)4{bKIPUl1hC{C1{7 zhhjhov7l}RPj-3CHscV`zOcX*&AYDp4H+63>2IXi`Cz9LbFanInot7_i0V8QCt5xC zvS2_zWjvy`4brCh?O>J)%G?SV33grew3Low4aG-^Pa6_`tj787Zl5o8o*2-g;yucY zReA!66U1QoOW+A~sju&Jq`2lhwvKX-a#%B|b_3+ZVo+8K1S!K+WX6M}M?B``2qpAL z2MPpfZrJrJ(25}#5Qjd23sja&Je`eb1p*-hYK)xn|00$&RahJX>(o zDw#^5I+Cxhhw(?fWpYK7x(}}l8Gca|`1s9_$Fln}paM+-tKb|U7y@)y5xNAVtgRIK z{zfb|Ql0FX+~57hdE-3FnKT4lT>AHew_F zv)>ULtUSO$DVB$8&`B%?g39@pk7V9rBGe<#AQf@c>IgwmK(PLqyKp`^6FBu$(nY#A z|KUO~<@6bdICX7$=_MqM@OVP?a)@iWfdb8cdm&iJJB&IswPC^sF(8V;FxFbV@bdRD z4KGvcboXQ+sNM;FI~SH0AUiG46@M51Q1W*u=dG?5i-C_Z(_wX|&il?oo$%QC?y{DK zSL0A6^zco;xCcSl0EA$D7f*{YFR9RSHwKiJDfQLj+6R8W2elrgI7Nz}ibRI^CSX8C zyn{@Q6;%j!>o@?=Ir5M`{s#Amk`ftMnZfGIuD4GM1~iuPWwAO%wgbQclxuV<(Sa}h zoCTvX86`DIOfVoV<_bm}&QG9+Rnosn^^WbwfErY{(~s&B{;%8Nxh$ObT= zCkLS1d8qr5UGP|qh<@~50-jLQ>&Vf{y#uLGNb8V4U#rl>4-tPAWKFcyZT(wpJ@v6u z)V3;_YXHGITL93v#(>283GQUn;vMB?R3<=Cs)HZ~G{eO` zG7iHjZc>QVo{2=b| z&5>g9!gY{Gga_Q6DdlHyqA+9q%%ygjy=p!zqyTK};)E3Kcb6RdAqx>lY!I zQ{gUin8D!cs*I%7tL!8i9o|U=51%bBMoPJ}{P!F^I<-z%3p z%p-JegSL!CiovKIY@qK_>@>hba<5KzIVBjUd%{sTu+?zWo&Su{MD zJ5$lN6=+HYN2L-lRl?z^$B}^2)p#rBeVe)k#KZq*7XXEJV?cPSH8zQDH4dKz(-{z5 z=`U3|1nYSU0F=^v$Vh$dPBoiNT>%O)72?pV*>>q|juqs<#Bilh)4J*lmh~N}1FR`~ z$spSwMp`}{MkIA;%07N3cF&cCpf)amLt&X9i^TuB`E*D`%F^0Ne9gl#ptSirGHAd1 z_K-U~VCP5Te+ws9?oz6VSIf7`fSNcClc0qh5gp3PNw6Qi{On&o_uK~#0Rk;gEfGmh zVS`>iiF?OP*VWG!RPqMa%gQn&jHdp1%$E&?ydj@21w%1vZPPGRBPs@8m=zN!RK9l! zY7u*$9~kI+eoDZ@YH}Bg7d`Wiy!LHo8 z^2%R6djXZp>o2@P$0X0nAsqUtU_d^>e}u8r2|8Jvw;AtQCG zlqsB!aGii060g=nM7GAS{$a1aJ?6BIGZzCw8|YqOTm6kghhPXm{W|(k9JV0<=>Dru zLj!`T(hbdv75d@14})|dudJ62sr-8<5NecgURfA(iG_;e?J7=!0pYQ|$`;%BS#&42 zWU*&J7o1#|HN zTko!5a-eHwX659`g%$F;#9StH*t|XUvCkJ0ClP+N*Z?UD4yOXhI)8qw`(va)|A-6- zM4(Ig=b=VpmrR((gVH$M3mQsMRF3>gK+pnrj=1>`IO<>Rnt_N6l%XO9X*4tgvS2V5 zOvGR>VF-5p_;sgVjdo3NvzmE3equr_9G|A~U{sL`Wm9cFh0Jvt;r<##Wc}fO1fWfF zh|XlL<9yVB)FYf-IU+}ettS33mHU~V%dT~>B(=Eu$59oIQi!NApne&M#bU8O!GNAT z4ewJ{&K7U|T)8DylY68Ue zBKs!Xy*i{)Fj1*BBLPCw*%{;mL(;n|{cSTK7)F<1Z$C05OUqhkfkVX$KRS2)mFJ#Y zmMQo(%w)1e5p-2*MP`;M%3Kacc)y?uq0ex3>f6CjQ{7{!)cI};Cli(%i*0VKDhlf! zJKxPRkoEZ`=*JL2*yQv1OQ#Er<_@ukO`k#Y;mj(e+LveU{whLQFBX9$BO(R_ zglKiGSd^*wA_CAAawL1@0&?!_w~hzYCW&e=KK+HaryzBla-8QaIpEV#6(u)f0J1j2 zI8Qi?F&TDbKtn;MRGE?n99(D~kfWNZ4i~O3T+X^$2q!vroG}A({{JD<@U0qkl5RV-Qv-O9F(K-%F$R!8_q9 zJ&vBn!%WM*bzWd>azDX0-4*n7=y`GgkHr2QO|HOzbtymaoR|3Co3 zzEtjvksC-rPuK(&L<|ORPEjj#hc|R(27>6BE)j&yS~BxaiUCHxIh$$ii@mrp;3@5Cj8RVpXW~D=8^nNW$arww)o|WA4Dvx^#0M_~79K}d9xp^9 z;`4E20j}}sF`O4p|8vgG`N5OI>ZAcx6a%uXL)HNe=PLb9GipYC2?GOq^=U95>bum9 z#KhH*46d{QjI&)G@kd1T-qNMMdw@WK2$d@30=4=8$u6vy*8k_}K#;2mWkC-ii|qFe z$o*3({|*Zx(OUMZ;vv5vHv&)s3^RUaZu)6e3j5qK^j>cl&IQYbCMJOW2q53=o&8jH zMn#6M&aAp;s8A7NkQvZQ1gl3>g}6DN{g#8U_jp)p8Z{tl90%*qBqrfsz90Z-2&HG0 zfYb`vxpxZQ(S?)CQtP8i3kRL#GW z|NYZ1y!nhcJ0GV{Kl8#1FPwh!^b603tG}6TOJ{cwp(()z0MvUF0BSa&O*Ye#gs*@t zP_>#D;c(C9?I+&w9l4lZxmqeW+}Z))K#!WLp`XQRT^t|zdk?DX)pfyvAPrV-bffcl zDIbenI`#%pb=kP62oD{>s=>l>o74!dOuci+h6uDm{iwktPJ(}G3T`gtHrUVY6?XZ2 zsZ?r=!u-$#6yDELZDar$kWxua$GL)^+1;6iAowSD`Ek60h-}6U_kghf|4-B2%W3Y| zA_nxkA|rm_+>c&52fY|Geov7?V`ocHW|p#8J-EC~Q8RT+@g?%3h26HRWr5P*laHxV5#0QIH$&HwM-?`-!DFDwMK7SFy$U?Y^hcZ0w7fua5!dM z30L|x>Z6gNjcOnG0X<e0r2+RQ>uYw+hL`oTQ&<7go!INU3Pj-Cg&$q`5rklWbam!el7{kzp<1&YQ-jY= zu0$021cGX*f&woBu`U20aD{f^javhfonTI3bocrtfj{>yUYhLbxg7bEBf14i;Gv2*f@=5pv-;N0rc$0X=&Tap{((LUXrb zB=Fb0DND_Sabr*_lxn+GP7nr1M5qxAR|+L57YoKw&5xAAy>2ekDP8mHIbOhQ);w1YspCq4IK zbbl@muzUH7d7wZd80+hML10OeRcN%MlWZuOENY%%LGEx@Oi0Uo1(*ckbe`aXKp@!z zFG8>5x2|7+rvx$A@mp73dF7R76$82;#Q|y994OCPoliKa+3E;DsP|ORHy-j}VTfxi z0*z`Ot9INgbF6_biez!vZv3J35IOmN=mV?hxOBKIm^VeOU|KV(q(GU{#*_O2`Q*Gb zZK{_FJG?p#(mXkuDlrB*u-tHNSbPu1N8dd`flBKS*2CZ{RW3kL(7GT+;X-NS*kf%= zj3_MP-qLgD&b|DsIKuzte<*Xkpd3ic_anVpx)ku#rsPk-f7R<0Y3uH>PZWWXhUoK= zr$TO58OU8ub0SXu`Z(9)vn2IanM#yEP+g6#t^fmCz$t!Lu^gJra_)S~6lnUjIJr-JZ{Xa^|MAkf3oi)(`lGJ95zR#|s8_42_Hf{*j$;ldJehC^3bF8JHy9zdOyIHH zNqEbJKR|^(7pQaZ-bHkVzSMUq-}i1{1zN(==<)-nwGaG;qCXK%l2YSEkeHAo2|3g! z=(zttp_yVwU+W5wVlF;hfb3Tx91a)Y zWOX+xe@^8R(o97=HX}fPEM?}9vknQWF)F%l&`65J$A0#h(r&ULq*Zqi( z07SZdCQfHO+y1 zLYJdhnIr(H$o2oQz|Q^XrI-KX!pnat0OSsWBW(}ybN3n=g z!>R@weg&ILUw{3-f6Sfs@rgSxKmGC_ee$u*ez^P2z4h^61b)JZ=0QFX5NKVT(iDWK z0EkPl9L&&QKuH#%*Vg7oXUn6(fV%pX8|QR4$2$&ydbS4Cd!W}gNMgJ?b=Qdj{gk>+ zHH90!esP2ri9HZ2&Njr7@agb~2;}L+q2Ozr&<9lP)h}2}QA0bzKL6Sp&|IHwlKwmo zojyqSNz>SAh)FR8K)BTQ?sc}BiUDo=ZB>D($4(pj4-^gk%P*<6)?xpf`rHHUCkc^3 zVbC%o(5N9nGVq>Cj*d>~2Nm-tcAmn zY{uwxXgS8&OP4X3`tG+>Wwp6EuG+^aV^A+e)hXB|6rYhWF$@RkExII`p7rTfYc>UOES(-YKTs2QUH`J ztR!9a-ixBZV20UhDlm-EMWqy>j zAdnunys%IJ06~Oa8*<8JvGPk3urZ+a5Z$N%MrBfnJNS%&t-v=oU15g~_1!t^a%8iYYGB?SNJ2hr7&QiwEuF<6`x1^PKk zFbEP7W@Ls(#z*gd`1HCWN-yg?b23E#r`Nt|1_U!u8dIqNAXb-&jur}FK*=(l9L5#C zuCMD~X2Mw7Z6iAnC=j4^7oIh}@h_h*=_dS!=UWxnhMfu&#vf#KG>5a<=6yWOrp{hM zM16Lt6)oQU@t1muAG?rlJbfdeKdk&{J~XZwPXLIT2ub?kCIJu?UKoL&$1pr~!G`9` z3)g5CgIZ#_g|ZpLpuyBs;@p7LXBj9go*S4J&&beTR0Qb%Mg@i^F(RTO+wOBV2VHzp zp~>JJJ05^MJq&+AAK=AO@x&tZ;W;m}IEVqk4g?M8Yh^;mwtGj-+mCQ6X_eQEW+?s< zN#_r@hNskn;_5I`-I~yT&{^Fe8iWOyz3)qmfIf9X_DL2L@p05GRe>q^S#g~*BhaiY ziQk0p6ek=sKCO2Z-Wu~S?{AmL~-}%n#ug!e(0Cf1)-~AA?VA`<765UEl zj6fG@-1N?0+?g;~!?xmJ9$tWFB2<3C0Wa1rRf6?+A;!jF6ObOpXoL~S?+y>&&vdiu zLdmQk+&g|R@ixN;Dkth{-TjM~B|$3Cftc?|&W2!NR zU@h9!7AKym4-*_Ko+}nl(T1;YFNVm^1xi?4+)}u7836P(7|?3b>yN4B5YqJO>M=U> zzLp$&ECME7(+I?m zWnPJrQ)i&-DL#x9p~gbhPhNlh7k>wMiD0st%-9Nf(k8>mno=`4j{)kOCmMq4Bog+Xn?2*L;Rjsqbjaq3_39`uO-}(C?ymY?6Moxyd8&vJ{i` zA(o)kLvIvzAku({0VPKf4@9H!NwZHO3FQ58}LKNBVR0CR7Qg7!dG>rom*~2cD1i*5m}c!a#l$ z@hK!xa-~p!f&S1N3WHb%x_I%q*-gln^xp>qRxg1;c({E0$tVB(>8IEwHZ))&Oi^JYUWN3KpeMv(_OKrCzCj*8zmOBmoeqEg!0bTvMd+ z3FF=fd#tIzXjsp+D8ky3Fk7VEWFPe$n}4ak@e=>lhs`bl5KB*xbO zlR#|0nFX8sY1{LT{DzRV=3*z(fzXRzeHCGKY=-VAWX^1F`+iifpQ|@(FHQY#Uw+As z!(;*6r*Pn;R*3j86DlOBA}b35K?xE8Fei;rMT3Aqn-ily{L!EN==X>DblO6oqZg5< zBerK!&(2Oh#}NPkAOJ~3K~x&?>QGxNBe&DVkXgeorcZqIrbnp>wvK?k^$E)~Y*LMg zDCiOl`tu+E@yj>V)6akK^B;Wge*gxAWzGNT%y*DvA;Ql1D76Vzs1HBOsC4(cPxH*X z4uqZ%(~a~fjn`CLzi9my{qCC+Z_|)Pw1`aBcx!Tn%Lpd;@Bx-#`twC?yW8ArSuXYs;@5@tDZzw8y zdJSl`cyw8s`t4#g<@Bf+oFk4u#em*`2vk!H2>3%HP>;vqJ-=C-dg<~r$hl47Y?@3u z2ZT53tV*R97?8tnC(9SjWj49CCSeE!LF!?Eht>0c{`>TA4-eDFT=K+v0#J(RSBK1# zxISZS;-E)8;id>|&mI_DeR%ab0D$7e3hvT&h#T7bZFUSvkPD2`PXnIT;e>wq{_WG^ZYVo(V-FQ>rkNiqT@leyel zE>~D^QmMj93bNS6<>hkOZJhH4yMVl79n$(%y}jKQKjJ-Ag8fwAJWkZ^@q#Z-v=5Cd z7W<|eh`nSq7c0&EtQtEhs|N#u>u~FHz)$UJ?cUWI@Mlk*1m3_j{Hcdg2l%%2L03I7 z13FCqt17`RQwc^4XuD1GU{Oz9>lq@Ki%-ob9U?!f?&8-#o&$y;)})~fSqS9df6vu; zj@L7#6#cmsxgANL>=FrHGB)wkVI;U<&%MumKzV#bV{`%A3ozOd5 z?O9DaHc11*QT+0aby_QgA*nxl`I`rz2>GG^_DnD$48%#Ts567Q;y-z_erS>WdQmv2WE{8TBCKFVT`XLZ4B@ChJ@UNjr+db3{d)}};;R!=+8 zcI){sCpIm0XH*esJdQ}eB7?`WZmtpqA7#~1UCXm&Jo41*<+6Hl@i`HKAU;yn&tV*- z0VNl%EfkUm1&K#=3M(rq$I$iV`f)bI$GTu-a*Ntc*p8avUC6zGns$#F(&9F^*uCxQ zF>QE6y~^@=o^a^J=F%ta>qa0W1w*K?D=7%NtVqz*)JuwUoZUWc31)Si?Vp*-j=5O+ zq>o!-KvQrt-0L8iwT_8+T0I9xG-tJLuMx!&vO{&3+*B`8jwVAE2P&*_4>ZR#NL^E# z&)3Dbyy{@xKF;4KAsp2s?pNSiwKyC$cB(B_EZ#*_a;P~^zHLD8(nX_Oi`s1>vtv;8vUFmtX}_)<%C}S25YeRpPdON_S6rZBp;AE%*EeAme0t)SPx{3nP zg0Qn_$Y+O}el+oyqo11St_jktlEi9Q08$ULStit@y8WTA<%`R+ghk2aWqgYIxaX)p zKYD$L&U~Yza^_nbaufi;u*ReD3j|;m0R6+c6Jk!!%x$#m86&UIR0fO37Y5TG(XDCI z1(fW%b*vWKUf(3xmI0t1tqeNp<7#!AhvD@~o_`%4RzwICNEKi&o&6dbP%PMmVb_?n zk7qS@;>Z8$=Wm>yf(V3ZFw*t6ee7zk*ZHs8R8`sbkovE!6b>91pAV?~f(+!60EB0# z(TWf``oFr6BlgSCGepstqoaQ==n)?PHu3Z+E}BinWdfT}6QyH}8fnt#H_f!ew7ndy zuN+P5b~FV7eTYQl2@zm56F?27&`DZGSoVSSu6NX#+jc@@{w)0sp-?_@W?WJ#2{DtZ zPEj@30U1SS*;Rnw@{S^TSQH=?R(S!fA(MF^x{sdH*c2ITb9DXrvAJTj7X<}6x)Q^) zS2Al2NCyKov)Rs0J+p@eVP}y~HawZ#@%+Z~o0buh@CSV?1yki zv7TkZqVnu4y*c|FX+@*gU!l`pDs^2qK?r~f2Pv0E;};g-jdBA7`iI_$$&WA-X?ta~ z%(AuRc@MyXj;X-B9yg*EnG9{u{q|TRBF4BDgGr3y+=*4q)%Jz$MY9kLKcb=-_l94s zU401}(CPPrtriFWZgaP}1UvB*)vKx`R5e(wMgWvioKgXK2A2yN1wwUrqldtU@qYvQ zxJG;?1t(DAPM}RIQ+qnf6ftE*QwX1sdUB&X&e|=Xh6BD37k~L@A@0;3!81%)z9Q}m? zAFRfR^~~~9y9f)b&>YLrAV{iB4)1j{en$Zh?MQ_esOfKPoc}SKnhE^a;(^oHY%)bv zy%rW{9eNMgc1oa0J=B(Qk77UNGjHoUM$XX%0_anj!$o4&PVr@?QD-QN17$9uLP! zrJPw%o>X#$0ErQ3xlF}=ig5@JLp;=G@rZLE15r<16=G#>zbXJK3<(3uxrzZTs4q+! z5N?40sZ;5KdaVAhiUFOAo=gCumevN}M2OZTRxkOJG2!%!FPY%;q)O+75=CZo=ZlwdNHLA@}XnaBag(6h!c^nU!dCM|>=6}d@IafK}O zwnm{izcbD^>796sZ&c|E@crt>NVKKSvk5|>gnDlIBUMHw`tZ0_;l&Nsg>I>9WJHp= z^!C^Fmw#~Qu4F=NS^*J?I)uVWU@v|>6vwfeo=eZIM!q2c(p_wt1Upa+XeE_$Qw0R3 zlv9$cOFy;3+lgP_;VGH&LU~lL)Z#r>>OVR<$~$p3dA^u{c;flrEA-LChh-p}0eM<_ z4y_4OAEj!ptg7bgt^3(p76=3(T9KpZ+h0z|$o(k8iX+g%XEt@$tVSS48PsVk1eMjD zxLsa`9z?F8i^~fxo%@E|luM^T-io1Wu+$2gVt7M6XhEIal(T#d8c?ZsQuY&YrVOpq z`%QbhUB`sj1M2B-KLmhCU2f9`pRL&OB^WK(@Pfqm*l8G09k{c2t^@{jfrA^>VLm(z z5&G(*_<8Np!vroP#7a z!fX^`C0dan^?*nY$wCySL8!oPj^xt@3+PJtQDKCr2)z-!&=|xBq!~~=xYN83Y-p_2 zP{7mRtKUk10O_ZS{zlb!oL{QvYC2wJ0IOdku(^XZ3t$tGglp=Q>skQ}m6w=7v3Rw}C9W5@8@?;)1@PGsXfMi09 z=VeA6^;t<{OQc9dsz5ite14aeHvh;<9$5)*Ui)N1l(Ot2nuu4`e5P5$jtnfy*sHfU zdfy+_`5y(%r=bupv%fV-AT%pFkRvQx9(M|wX1VvFI1sA>$=PL>rALRT5EWs>fXWVc z!5oxefFSiCRxhqCpR@!E)?j(Sk<8Zi12g)y-TqC_VALQHnuko0#{mGEJFW{xdk-xD z>a|Y}K=1)AE^d8(?ycKJk%4NT-+OiV>gCH{M+2%J*`g@X{4rrbC;mwzmlXg_O-+## zQISb32a`P;@{ds|@A5~Ci!n~U`+o`p5ZqYb7yvnL0T49K z6_`3(fVYa`L7{ObjGmXC{`%MJ6U>0L*&7RNlCTfW&Q1i&F?5#um-}!#Y@pY8G>k)Y zAi1sMSrJSR(dRz07Bbx$cfqo?%!c3Y{U!Mbp*lO<1S?SQt1OQux{Ia7GO0fVIVnwe z7?9Kl$UB{~FrZYD=?^g=lwe8M01z2T4%EXp*%snau`p||Ta7`81o z!*;KJA=7*0Wt;a60u$!mdk6!f)z4m-Uz}J2+S+<`?(p_1&wwpn-NNubjEG=Brz^o? z^#QJNzyhf$N9ncM-9({MN|zI`-T7rl*a`Eu?;#|z`w**2O6^oGxsH;^Tar!ycU89O@^qHs@)W3 zt@FpqvI(BrIxqak^X;b%do7O_s6Z4Njd$%Kb~B>@sGiyC@MSBbKIB~M`M>{C0Xgv< zxH~{{P{tF_(RUFES|<1*p3T!h>L)CN45{18s=%b$%n|>qn;Mc?FvWn>rJQtWHqlvF zfQ;bMiSs~xjd}lsA~beaVTEvA)e2N_DH4>qKz;ZO*wAmbw=&z_F@1P(_;7dXI0nR7 zAB)>TiE|nTgq;`{wk{VB-&+-{K#jtS$O-+%)ae+|YU!BYtbS?+bojq3074`F>Z@FW zZR4*PhW(9VeQ36vN~zOgifS=+mR)h!;|5X4Nfii>@DEM7Lp%i!8kBRKo6+Bo1bTBd zfSFMTQc7oIW6gLI&dERe>VmL zfA`v#ybN#C(4f0_Zru5l0f(?h(Vn~36F^8|69DLs`rM8ik^sc_ z>Lznif(Zk1QV53;5t=@doV3nRqjyphVjB=t-`D!_=^s`E}RH^c&vddj`> zkMTom^sA!FFd`t;ims93gg^{B0w9LGRG6$(S@ALGAuJ{e=93^52oiK7QKI*QJyrBK z;_q1v1Z{p*VJgKpM_!{$PZofL2i^VfLq&oh3f-Mxz!?V+0h@>m-TmZ0|Iz=WxX~y7 z+&>Mk7*MJB4KW~?pWPKjg490+CPYX<>i<+WVFeR`#aWNsE+8gQubmtxIhcyJb;;4C zIXHELk^GSGM8kIh9GrcImIQ}G9y;f)m^Yujsp=%gjT;_%GGZia2sWXnkLSC;|K%l zOZw{_ofB(6Xg^SAYLsHVwse}*(L=_aK>%b8)RX$dm}R%&`vFL2e#o0A=M@o36xw?A z-0B?Fdl#4iUAd7@HmF+67L1|!Tj{3$SyS;0M5?pa_KM?%g{;D6pg>aU63ouk;ORK%~ZD8Agh>5;6fgNVziA zKn?=V1T?ujNvgpn^g6<1VMQYrSrW%LKlzwrct$tDfUFqA@GyqyeyK`J6rc^EK~2a$ z!=0@*S(tD1!m#tOO9-K4DAm)w?i#@k>B|?k`vTiNJMEe0 z;UCU`wjlxGR`Ij|RBTfo$M%EF=Q5IkkuVxYedCQ&<^c_y0^=t9n=qizGPD!^tgCPQ z>7Ra^#=%~_ioZ)n?*h^B7RBPv4sS;ee|bB8^I3&KAg={XSSL|*g9E__O(zr3AN-To zi2gi#^AEpE-@YA8R8+z+RHDn;Vt#95xt+rTKubyJzBbX7g(gO1Uw3efI{P>2Hko3#?w!Kc<0lR z{j_zp_M_%tl1%{jX<)8hlIWZcIuHW)3x&%iewU*gYsXu0H^P z1_6@SKiV#zWeuHQ=y{kdd$66^-tG+mAn)-2h=(?$4^3&Tr_g{7&ml2ntF2u?i=qL^ zH2kUdg7N+`Z@{00e!f^y@8r9EG64EED3JQWz<{=i0R+zHh3Fo9~PYgg+JFMupquVd#n5SQIzH4G|!} z<+l<5p;klTkGhV;1NE7ah&3aWa$z9}-<;GWyiAY4Stv_`0vfb=_rsU5@P#SQCRV?o z78^H8kRm}ZKmGKLkt6@iSh4g?=+I|Ug#*QRz}=z`H+_<f}g`*R?N}sU1cG z@r8wJ*A^DY8^R(`62G5%#=|!?{}0D9p#IDob6j|4E4qaINDa2#!@;v%udC|pm^Qqu zeW$3Npafg(2cX_I3)wjTpRx-^KR)NB1+g5ptF^0BFA)VgMHejA>kW#p^}G^6PF4M= zFjbxCk^fs_K;M4j>}5>L@}4y-g_0_|hSOHn8Nrynjf}JWo84RlOJ^ZebM5~o($Q2;e@{LFomyWv>auqJd zSV&@Is_0&RJT?*^d47}ki;tQOc;pJY^WlwOQ^Oq^kbLT^B=?~?(9(smZ9mMttOUa3{MW%J$5yE{>@Yn z?UGt4ps%j!kJMWb9|1C4_S0#PL?FhI6{*mK__)ii6w=Ldc7ujWU~;<~9$p6l%JvUds9}v2>szbFn8~~{NY{R z(4e;jPh5O%o$==`UGLoZ`G?<+^dpcu9ee|3pfl=BfKKF!7JpKNNCh+v^z@T%f(0Wc zNzM#pPL!l=hUgOMDF{qYA?%AvQ|f}5)$pO%A1i`Gk(|1oL?yiP5rc?EJP;_eMMj{> zso{E*C{VBT4_BDnC@QV!j)D_Mo4eSrgfL(+gup5`NcK-Mg(E|wOlY^ZNHFVwk(T;JAtuHK+% zRvN=tv_$CJ;eZQIViyH~XhD7PbPPxlsR!PLEm_C&IW(ZFHFV)mwH2f4^#%fv=a~?W z^jvJNTJ%ov$baW&Z+sg7glVvQT!OVldVbKhzm6c#Z{IqsjNH0XE~6cfl`jq+@D9_T zobaFA`>I}}d301@5<8z~2#WWmYg7q)s+QN;fW@OOW5Aq706z_`z>Y#!y1#sjGX;{5 z8yRc)e(C$;e?MU@|D_k|m{a&dDiG2wD7q^-F-r)_Oji?ixw3bROFD%G@=27$(V31LVxQrGrqxz8;<%qBY;E}La9wPR-c$1=^{g=Lz)z+#H|>{B zxy-}RT!g`_G>cpG-q~y1>w@m%xVa&IIIi(57@r|E19B+T0Up|U|6GtI{&)byfaMuY zS>a6ykR>nAe|14Jf1ihsC*=D#6}4H2`UmimJq`moHx( zerf9LseC}Ofx-Qr=Y?ml-8r=1u7_VUBMsP zd~)UH&u&W&kE9rK4WbWT9>X^Kv8`J|B0&ttT9d4GYuHR%@Om?iY*>h zgGx>=F#y;|X)HPu^`k&9MS(^)b@HBZM5FEX>0M|-Jno1We~p|K(viKDuG6J%m5?dLz?m);9ui$ZPM^vU}LK+x9aZ+61+SsjzzjQoZQ2DVYT; z$Ph*!_Q=#Bj6Wbl{2 zM_3V}Hy=iE=5YQx#DTKG;2T^1wwVb9fLHW z;g?S71DXqdN~Q zB6G;eU47yuSOKb!OYL}98`TTUQypt}(zsr>2nMtO21KODDL4lRe!>t34`I<@7CB7S z`wGslyp6WB+oNN#c$J1z_4JoD3RZ7+LPHu+Pq80*Po_?K5QZ@n1!_hCQ|dE!hiJmE zAoZWAzjW*io$U@p{^57vK2RVICU;>5qBi_m&P};I3q}lRA;f?dC{Fl*+qc4idZz)P zzU^O3HN<4Nc%j!jZYa#laAztb(n)`Jo8J%?y^I z8z)XgTrGwvp=FlpWBTdh2>?hK(6?zG{`1AH3+)H;w=F#^1L@6Qj$Cnu>$T6Qf z5>xLV8H*;Ozf;c%KvAPLUHbmI*#gY|U*zn~a#DoiJ*n|oaG(ifUp@ES`UI?q6L)Dk z;JnRu41X>6E;Mjf#*k;Ug!}xE`(M$$+=Bh1>!N&32A%H!zsgCZ%0W_Azqt0 zU=ipVPoldH8Zbqz zAOJ~3K~%+nFddKU)NoS|ZA9mRA_rvrabzfik;m2Wv%)}hpqD|R5jG2aWR3(nUwyuQQuH~(g7ES|`$3zAuT0Zv+dFpQ;ROjs)RjtckXE$4 zZDib0LrXe8u_+84!jsU_=Ci+!o(wbS`~# z|6lNF??lo+Q=suPJn`#Qeop_)){O{$s`){XBjIDANz@AIGL^vT6Sw@e^Er-su83B!vNu69sy1UFO2>Zcd;G zdu@Pb_v9(inF9HK5ZRt|=MOL@3`GdjV2T-8A@8~ikGc6&fsBZxKo?TFx&aId}Yy>}al5>F7Z@TP3$b;S<+*8)@>}Zl`45w+G=pvXK#-WMXQVf_11)Al-F4+h+iVAFDlou~S&`Z*I4SGZZKnj5h z)HcG`y4mh+#A4|<$d7L_S2uz&46-_J`1NkHZUvT6XTF}vDEP^Ap#CTXLSL+_P>PDU zXm>4H=BRm^t`Gw>=a3c5lc~s9s$Ox#4NVr=SwvBx3#NVn8N|pj06977kSMIh??$Q^ zNtlgO5}>xm9a$qNYu^{QG~d|n9aDvQ9HO|mEr)J;V5O!RkatQ)t1uwsPZJ}1b!+wZ zZ%dblYuJi$_KlNv!HS;O8w^1G5AoIXYIXIr3}{gi(g!~3&WK(FXci?$f{y$#kQ_Pe ze^**MVbp@pTZZULFdknCLV2u9CH^P{I)U0tn((`TAz$dv7@^MzAt*Ky|B-CH7w}1` zH%1i$noSWOV*LkiOiTcPKqSZz4FLM|#t-}d2$5A)+82w(>XR+Os7K8Sl`gR#2ksb> zRul)4&ibf!0nupKb(CQAJEtVC6lsJITxNA}a(M+l9emyL(60KO6#FrIF*brV@G=3$ za~PO54IDyIaH3A9gIUzh9*%xBsnr8WjpVZA(f}{#kgi`9n zFO9Hewifa=ImAX88e=`+2`T7EE4l`wR=k^%^tt4-r7>i(3j73v7$%U_uh$8QGM%~~ z$UtbsPY&0*ss>X)G<-=RP&2bt%YHk5 zVM-O|M4pOwX3JD*ec?Dc@%`voFzwNIsSW0^%!Pzu{}KF0J9-FjtPv&72I4n=dPI`u zX^eqhAZ9=aoi9GLy}hlsVw`T(3cCjJHPD?~eD(6Z)%V^zH%x1JR0(zh4G4#OXbjam zvJNAxejc9SD<3Kb^uJIf83RyeteUP?(|R#!L~oEkG!{QlJy9Y2TthkNEU~B&+hHax!#Lcm&VSEK#2_ z7|?iXB83u6QK09ZgFtO&GXDPgKEoz;17I*K#a0g^PmTe(ngJ;=;kC>PfXEg^hnpkj zLb#h{<;Um{9imvF;jF+sO^43(*JT8i!=D9)^bX#Xh9}(~Ll~KS z5d4b^)ckUZ0Wk#<4Tv4GBuP8E{KC^v{So}foa`U?54>Zh!%Bf7{ZqbM(V(^-89TZj zjHRN|;cf9jANeTHZi5}3iUMf{gt@ZJg{|SKSBriZ!`bY;t!6t`O~>NAoL#T8StSy4s2AF#HOhqd%pWPlEI_h9 zD#F{kB9Xu!tsC(i%<&MN#%h7JTGLRS*$LFZ?cIc?KO@1%o9kn!K9 zo}xgRx^EJsu@i&bh@EDwL$esQ4yv&xeSW5^m{0@Dp#IN!$B>_7k~?BLs6!Iz%|>vj z&gG#WR*z^~!QIK9itOahPcf8>+vH|ud7xC7P0XxG63cHGhW3kD)`Sm^?0d9;#j+4Tsr`Xd^!?+Pi z{BV|acpTOqM)HRk7z@}?o~5CIvXCtq?{WhS@(%W%T_EU7^2RE5cMl8&LGsUHW}6B! z`2UOu6rxgEgf?3-s>c|NH3K50D18bB1OP(oiWahdez}G|yoqFG1{8U8iKL!yr;Gle z-5@fCkq?gNG}d+p>p&xq0R|BRK%K2-N#RYLM@WU7MD#jjft~<{B8TbzeWQ>5bpk3R zWm{SgjA^*Dro`gubSObAK%_CB+g^T4rZGT(#uWZo%tt>zHV>+t50zi?ObiJ0XEZsH zR6J-DKr}l$p$agCKo=)SmR42S+xeq^fVpB%dx0WP27=B=&@qpIfv+3@fLyi`qVibK zq7LdYXT>R`Gy`&1*ab*HMDU|y%#09JAXFGKq4d@){D!?1)sqED83_R5Dy@x74poF@ zL4goXpUrj@0DVLn^oCzos8p-f(2Z?eNy_?N!5&?ZG45yqnm(pXIc2&25Wf3WSD-x1JhG zmW>sN)n{IqVFH45fDo-lO%+nC4;6SRhPyyEAU*#MjXkHMs??i7pU`=v24n^KK!)y9 zVC{8Y7-OOiJR0*xx;{E(&nq#uw(3lci2)tgYSS9fDJW1dFrfht-xV4Vm0)Mj-5wzP zL`>T|5-=d}AMD5R74zk5&-d_B(W`d7nm1%beO6Wdqq&0>Ne?*S!+69uUnKzQbhg@6 zQwUj`0quidRqP|vU{LD*-U3IOE#daLa0u&-hiszZFUv@belWP;j5XO zLx3GF#I)&IZ^_X54>2NDR4yyn8M^LL)1D_V6a$jo;5jM53OOCs;7BAH@u0$>NY*2B zr@GXZE^r3!3fr`Q#Pd~S5AqrnXgQBst-g-`-;&~fYo&wdpf~bXo zi-4}A<-1=#d-m*bt+~~X>Ek@$Koy->YIcq4sZzjEU=orq-3QZ=BZTglGBa&{Br5+R zc`5tENgc2ueg*-;V>+s{9{@$_4`DvEYBcS%$qqUp12U!9a~H`9otkB01RA8uF_xjr z&(Rj)S@pIspaJuH>RbT?dO{jdGD)=;hz*1sRb`b)1Cld-%5@ejL@85{fiA&l;}R*f z$ra&IApp9_2d?u9ibzzh4*1N-3>-%pL;|col3_(dseopeVYLZrBlw~Fe+dz^WL*^{FYm!MXC77Gj zv(ns$KcLT6RVOo`$8Z7>m1x^JL0(@@+4h!KzW^&Qn}7@f=?5UzfDj-}3s2{~aO%*J z{Gn4l5)kpBe=s3HnXODyl{&#*Fzc|jhy&ol?i!_I9?mr$Jx{wOV88X6*u^E7$60IkIQI*)wVK44i3wQrzJvUD7Xk(q%Hi>PNDt@j)$=! zi|29Yje2kRAr2V~bw#Eji6%S7{9rMjryu-dnk=RJ!xv@HgZ2?tAEIohf0P^mKo=Q+ z=rOOD4lgiI5&jSjf>Zif29z#(L1cI234qX<(NVT>Q&1Bv1-rIfp4W^B6v3{lt|3$< zx3(bL(^I@`Np7j5G}*_1xDE9R2W$i(h!*%rBw1-JHb$tk)oo(^mu}T(cq3RhQ_m_2 zl+9-M)U`G_yc3OX>~zQ?q&O3_=w|EYm3c=Np{8_AESbPHv4E&^nr!+GRdZr^TQjMa6!13N2 z`s&HqCl)U?Go?8K0z#cJs6r7oAk&wlR}sD^5(!9_e7DHqJq18}_cHP|%mJU5TC8fJ zklD!|f})7Hd$dQf4^=}bG^pAP5g`275&8Yo6zIxtFgqgz8Z&EwH*_K3ZA7aPQ=u6Q z3W-VibhznnR*>;{nfg7?&kjPM*@+}up(ivA5@1r;vy5ReT1Gni_CqF!t#Q5oU<^9L zyDn%cAquYo`GCY4#FCGpK-Xx<3rPlgc`;dQT$X?&btj}kGeaDG<#)ObugfrjBCo+( zPjoECRv}n{WFUhZWsUm)plqgI?-CRZckXA^5i!{TovkbQ+3I!`4QlQU58vBq?O$R3 zqbo1*iEr_-)^07w=PD!521Bui<`{mjJpb+T5yP6&VO2f6Ajq;~qiD;YF9)aE@FfN1Cl$2kNt|B3 zh)D%5(aOnJ^2gL*>Oti9VvnGL|9%W;e1aH|tK-O$iUFxpJxzll>!*;?jW8gQtykDD~n*0c%lzz9<>2|g{-DbDjygFR-OHa+04fja~=4jmy zBPdEy{Y87|uoaVTI6M_kA`mg40#Bmm7=UCj9x`?Aid9HGdH|yjf!Of#!0UN-#pThQ zm)E9u44Se49}(z^5Canpy)oOALrl`r^tn4Cv50Rw9Z3 z`PR}mI|EZ)W9brlot<_yFXXA(YsC)JM~V>r4I&mC(cv6PcU4)~EE(0;C@uNm4ImFM zkKp|kXGPPOA|Sz4SLXF^qZodGf)pl@BVsy!}^-obPu5C4*O~qooEMQB#STSdAFnE7J2;Cd0sk;dtEmC_6k^>tZWUR^iXo2;+INe z(S-V-Zl{Z8Sf}gn>}7X){$J`9JgKDK#v@C?7>QCKKx@o^a;}?7F&H@ubXQK=Ue^|K zCN2+f>*}{~`OV`25L4ND??_I)Ne(lTGvY7M3Cn0JVqca$7*a+U(yC}c##N+;!Fe49 zJwNv2Mw-cdpdlWfWgCB+(<_ITWzinjFrytC954{(B#D;K&R>5bcpLd)#H`O>iI+ zA=1=^IgAW;Xu=b*Tt!;?5jT*au`nLNB4Sv1x)w=%C;U;@4Zr6_{WfOzs|q1kH48IO z28bdNEwM+;A0uy%gyi$@myO8DgVzDi@9WQF1d`~_Y2^EKtyX5I?nj?mOKRJp3}ond4!tn!`jBQog>nG^1S~3)bG#TF;}@=$ zpiMrRHYK7{_DaLv@990NA$GK^;#KhheDtIQQ)sotgh@shf{S868NP+kt=K>(wxW?@ z_A7-n;sGi~L?cg{;D<3N9rfDLUeBlVGXYR-uXAq?WiK0r>J!ax9!s7Mj>j}W@2Ab6Dvyr3&6 z-%xwK)9KrP#!IGCrp=p@CyhEODFc!zZ79B&O!CX*{LS?30Zt&^WYYFxhl9PL|LzQk zOD_&ZRGh{I(9F{kH|RhGwnHDd2Pvn#PzKfz10oGb0tk_E=_WaK&`pK`D248rll+rj ztXhqkI1ZCeul^O$5}XlUL-X`Zoz@UGxzpu0di72xli>!LIu<7H)wjB}Y%RlGvqZg1 zoiJ63!5!pxpOppiy6OVwDVTkQkgynX)Ww0g955hW5H_R$=vskuIZPmjzNMb$fB66Q zyvG!w_0xa_8Nz3zC|hI=2wUSH_yfMumH{BeZt~TQ0TI-GF@^vhtRIP{?RJ%=u!ioS z)3&WBlS>d^ZNsnAHtfz`mVzh+fVT6GgAVaA{~?#LG_|A^YrWq#pHMmqW$~ljrlRu+ z^WDke?qPsF`LOA)l22Fq7Fkr&dZ(8x^^2Qijkt!Pc%OMt2SQ7gCU_(qDQ)|qBU(3? zkCXvck%i`>KJTR>8A6r?kx84yCt&@3yLCAFP4{#^?VV>kp%RIStDm4+XM zI@jO_BIctQ5NklVx&@Ptm@_4q6k%6Jc{A$3{?mX(h5i0$bNhkhlM#53%dkg4v$d^# zJ$(#_zl~xy@5THctZJ3r4AQG6^KH+h4V^wF-B#Zed{I+K&#qcrCs zm%R01@;xY6tfHq$W$nA%9sab4!4@qm%b(3eNFQ47%j;S(!cq_Y)oggs(JrJQ-I z4L0kP^`GV+RiV`|yD^vraSNoA`iU(~iY2K5Xw{#sy7n;i25Agk7iWS+?GXq>idobtJ4{j460QIVM}*-GNVzc(hrFi5gLq4 z70&coHQ%lp?BCMA8RtCPK$th(vwYhA(}_52{gI6@1~93PX{%816Clf> z=`jiulH{VaX;!84Ru>NR^(_VQc$HE+ueyn^%uib9f`OfW322kYH$$rDQ;_lRWSXv6~@DMHAy|lNd-S=U)+{Xk{-4+34vA62U;AQ zu3+eru7DqUg#k>Sf>LjPkVZ7J-@1RlgOz*)V$np*n0I(NIsl-8YuxIh8woj`$<|sL zORCoW6&t@o*kh`+di!D)n zy1@UaG)FL#*9CEYHDV^#0!z5=y6H(06If(E^j6uCB896Jn%+#&eq-rRV=+YXKpnj_ zQMJq|73hdT=q)>mw<2~-NiYuf#L}V9BxM9FMW93Rh~;ITXh^xiKCJ_oeN=Vkz=tTa zU^t*x3XVf{milCrVFfoCIHwE9;-GPigYvT_@j!1#mmN}1&nmz);o0z;O=*PH&CFOm zbN}96r-PzkuggIllf$(lS=^)WwYPS5THT$@jyh~!Nm6gXCDbX)5ImP+DT@Fp3RGVB zLTd}A-VN1J*J~!)_QG-6zRvc3$u7Ht_rbr)}0r3G9NgoKsqZa5ZM%iuN2LNR!)rA;P zCLhBCj#PICAI^y86Eb@7!`bEzg>p0zmWVqtV^BP!QKLE}8kz3mGebI>9<1k; zHFJA(6g@BQg5lM5XQ3bflq(djuZbSCHstEHnK{FN#1@SgjoxF;VFb5?&)^o%XzDR3 zhNCtHaeHLZLX_0r_;x`szSO7 ztFKa4@uW7_Pau?C1waaZ6bN0Ky7c1Nvwr262_78M{-BlZ zcDp-zCstJ5T{*gGy(-&B^%7D8OO?!0$Jh5&%+F7eJi*G+xK)x#c}Re9RNppIwdPUP zO5eKW@Q)?YKNTiM^6m4uGR#$VgRVLz;pQ9sibWuGPARhQvRX|8dGZ27)|_nGN-_$i z7o{WmZ4j2*?~}r@B0FGo+nVDA<%l0xwX6?8VxTJFk!JAM{DY=bsZ zu`j68lT#qB8zcy{ed>vT*@#no8(34f7Rl1z0t`rmdH_&@9?~qqH?(jwR*gw-F*aD7 zwX2y*TqsAykdA7CRs{no8m%3L5cikvKLh*$1A1}l#TPT_W5%*8!A(Y-X?oR=6%cf# zCqbMs#joyvhJZjizGwWISU>6DZv}bAup&{36^N9&-Do@==1Z(+>pkj~Y9BX>TYrj& zH2ta57B}_YV}@c-=|=p|6l*~Lcqw>f2k|rNA04fNnpR;=I@G-{BS=TA>>}$~^Py0D z%tK%0yRL}ZWbia?^Fe^VTY zjL+0!!OT~E!wN^_S@?`q2Xwc#c5p9v56xi!i&Pz!L5WaPr{^ZjK+&ws5)Q=EsM>~@Tl;T4(S46& zK0d3Bo+p^&8{*?3jzVBbj3FEk30hvS6X?`w3kWZ%4!nF_q?ACl_oHzdb>K_XcG|?K z0j~ZAGwHx^Ckh6kMCg!B%lSPW9Q3}13-zo3XsNrDeHZZa?&Kv!fG(YFRUR3U6-^-b zZ(2Rki)oOcX}L$;mtd^=Afdpml~CV_zT8-JCcvJDtoEylCKDfNWk$4UgBnf0U{0h} zBt}(&rD|LgzCa>^EJV^!{)k2$8m)g+)@rp6IIHIG939XPq<?xR5P z)j<~(8+Aj!Y$(uKdWJ6lqR>ZS*QIA(_>Q*2TbpIvx7M_>CymQ?&$t z61HqJ7LT#o8?22HVM8~XkHrms4~UClEKBzlNMy5@-p#&CCD_>)U;IiP`U9Tqn~B6% z)2-dJw@87iz9$SuW2@NtaC?q9g@D zDN+>Z8Fb2lWMDWlcv}vm@jW)^7E82%k8+>Mkxaf2R(pF=;W0 z{4Q5@Fh@~CLE1fbUBkm7&cS^YOep-=-EFm&)a9A1f*&xT7uAzuKtDl%F@+e*%l@at z?(Xh1Kk?TB_Uvi~G&82YYIcdYfzBi}0FBL@;HShd_5t>3Rr|3gZndopJu=b`4tSQS z?V>C`pmU$@+kg=++GH!?qyM@yK5gESJ*X^-sRGyMU0|`eZNko5eKl*sMa)~g>O-3k zgQ#oPfL3r^x>fU#-mUMb7oAS_{&1(HYOvB+D@dAS z6}66*d`AILx0#)qtf}XWzkBnQq3g#oAgAyJWwLUYJ_oGINj%387?3yqf|@ZaD#XM%2w{f00lo4ER8y@@ki`LmHZLmOtYa#NK?~h$%k(ZOqlIE`UYJaB!tD{@*~B?ls(uuY34!< z4>}CU5CG^r%^nn}M?xu9a01B;6&=V0P$CL_mj!>SVsVi{NM4}jgJa#na>UzE=2>P-}S)d*b7yHxk+X~w7^(1pcO9PXg?}C zQvZ@smpXTN{Lq3PzrIuN)_t20`O&Bbs*Rl*B%k4|D&f$b&yZ0CW;sQF5@V&H0yAyo z?hZSHy4~TaY)8?jMzr+8(7ZIjm;!+TT@Nv!wIMU6x|SQ#0cB`|u_-b4f0g`z0O_bd zVmY24i(0-M{hN6W8%~YbwPD+XyVCgX5U!vD-rY$cHJI!(iI$((>E7@1qgkClD`VjG zbXraL(|DqDEa0TEt6o)j+i$;IAuvNEhN+BwRTl;xxe@>^Exr5h_dkF;S#nw*- zLXUMJ^g;#3FZfI0rn)0BGXelwTDt#PYlMn9RfNsNG#nX>DUpCN$t)u8UswYaQ<4X*^PyaBSDt7&WU<=n%r4rK02gY2B z^^tv#k@w!G6fWx7>gfa+^Z1FE6LViEIlsUgi+Q^OKUcw4g7NQ}Rrp%k{k;}4KLFMD{~0E=0J`MNhio^ z2*xpFGokH@3~iQ6vYQBpkA`T45Rh#HU#G1{lz6VHA5JB6P43!(qid zX{0O}#IWGUNev0yy0jG@lb*}611u>>BQf@lH6ceXf^N9zCot1}8nbQyMi$Ssft zL=>ptd=bP1fdNTDhT2Pa!PMJhjw>iFCN z?-HqzE|R+3U*bFH&>KtaCaA#i6Nwf{ED&vQFw-%OLwH0H4!&`Oru3tRemOI}ufSqo zUDb>IX;pyX=^0QUAkd31wg`V_W=8bW$Om){6CmqJGaw*Pf?)3hU%^^yIzc~EV%i@$ z0yrZ9YdaQ$W?KHkB%<)m>L5Q)HE=#wb+eEnXm}e&w}jAG0cEw9z&}>YLpChveIUptrB$T zE9tmxAgXAqW8V1^qZ91G)N<;+y z5CD-kuPn4DSqKLbCv|F&2?*tU4sOHug=Lzp+D`<4V1pI~2p2JSyLK0>aG-sNsLT$A zWP7no)9^Iswv4sT2YN2Ipan1Kis_Vq`9|9_>%dGdnN_41`atm02qN_mPLH|lOlGGu zoZZXTurKT$(pj@jVn7@H1cUWle+Q*a=YCgRTRS_o$^Ut1EfAt}+y!G@$SGL(Gvt1e z(*#I;9BDx6^|Oe}u^(3(!8eYMS!X@#q{muucc%*t09>3D0XF;z$j}AIqbe!IXIe}D zvXspd0>MH9cNXKwY=9*YU>&IlEwpEZ#H#LOfH z0#7_#hncIjK{Wco>33;aA@4kS#%7{G7)pmm-Kthrhuyoc95-=~9Xvt2p0$Gt(~f8% zzymZk7LSP|yP{VbYUk3U);*^K`73?CY=(=}BY1XUc_B1;t)sD0PAc>^gAk6=^KTBA zcu)79BmlvKNZG4sXO+1Zrrr!Zm3pF|orWt;VMt~%Tv|t1I9MSKh)Oi!M1}z!6p|(^ zK)s{oZG^k;;fA!SUZni8y3|C0ve_n?qK79D&UzM6HIq}>X0$XYf(9KUkywz^(S>iQ zc8R2%q3c3|f>8{`U<(DSKSph^HPM0G!a@PQpew(M+Ub6lxT79g(UDRjKp!Z_fS$3a za2-`(u^JgPN2VJsAvwE5b6Q`4<)}M8%TB7oXNNF`kw>@$sE&db08mJ5p`#p-pzdel zqdsWHW;rt>hOubw!nk8W(6m6${`sZ-^XK6@Jje1u0x538aNXyz0$P*w@~HG`@9_~7it zKoW|ORuqpVH2(=6+M*L;D{MR+8;e(Cv3L+dAF&2x4Ze{{)SB2&$F=zhGjjBkr_ZP6 zt)A|}a=DyL2D>=*LOheus)Ncn8x%^(&9~kev>{FdQ2R-gVD5o>BJ~+Ev_hd3${@2{ z(2}}JMHptmcp4RXK(rS=sTh#Mo^Z(`F-v(2{E!k)c^nNfeAHIFswk6!>zF~IlqKRkgv&q-UH=d9%fxrFv%%8{(VyYXm@w&fKpxJ0L^d zv9Z$eDOe2?Z_U)1Vj}hgwCB=Zy1mCq7js~I`0-!|y5q_Qk z=#~vYHucfO#X=BMPU#oZ`%-@G|IHGfC*MuX{A8N(hX6=E%LXrt0DWcGUemi_F(@Hg z_y@a$o{*$xP>79$c~5^qb`*gKr9Oy#y_Lq*epQ;480563X#l^Xr^$j2eI*?a)nakm z6;!qKXS@6gcXl_R0I>x+HYPET>1x%AD~R-K+}5_9O5S7<8Pz+HleP(k>d~&O6s69{ z9z2>8bLZU@$I?(eLK*3_oI&w~KY4S&_MON%lb`owL};it7=9-P1QVqtK+`Y84k6GV zh(H>EsOv61pri=SGCaR5V{iOc5-U>+1!o>@Yb29{`SiwOv62^VhV>DQ4Q_UA)f?*k z(V#f8?EPl926J<^wzrq9VMYuq!j4m+eYBKFh*pegxYK>ch8RV2%7s7?atb+H1|kEY$wtYDM<67BLx_GdndFmK9m=w z15HJTtnr#s!-C>w)YYoY;x;)kTquTzNVr8|9@tU+rB#_040`8uJMN z5J3i+BSCS>4o&il5vU*(CzS^pPO=r z+@Ys1tq?7i)PJNHi^0ER^PiAEnCly|2Q}f4_Wb63qCTBWQ=w1oJ}R*-q;pI*!)ma_ zPLPvWtL-7wSka$uH}hh;xJ24-VLB8Uh<{F zVqphI+6aw!qSo5oS?aQ=Gc9_u_UiE+(|FJB643~BpzbdT1qu@#bdVC_SU!)}=vYzP z+-N`}RC`Us`DYX#0hy67CTaW;Sg|UwrTz0SDCGHSM3rC~e_s6Rzv_?VZ(-xl$V_X$ zuU<3&G%X5MoVs9KKaRvJGwc*#Jdu*C4`-@28rd}H^ypKKSC3X@fw&7w5|?2*OPA)Y z8sawOJ<3+@Sx_QXOsLXEsH-A<(zGC3I$i|qRO4e~vG{=Kl)Onb%iC}88Zn)_sBVG* zaZZdhh7<=<_<}TF?$w@8pHh>p`Fd5skS-5#*`^@%c|q)S@`*$Ct+0Fr>R zB9|vPi^#~u~-y~2x9_28@5vq zqZgJY-Jr!h7!S|XyIWf%KM!{@TYK1#Iy~9IUexUH-r(jpCkl12P3-LCR1K>$I?seh zF|Iq#7p5&%DA)-f|Omh z@9?0)^z?3D!GaIk$MM<{3beG;C#FpA1AuPvQN6!=9-_-WZUBXV27v~o?y&@*k)Z6F znHhjW^sZ?}A9Y=N0SxHUyGzs4&jcC}7|`EYXlCKr$jJ15sPyVnfTsN!J*_cKEj-er zXW|2=TkS@CKm3e@m7$TZ$9;mnSlV_i2G~P+Xn0vka|}?>t_tN;3kpTz(eT{6Z)=<- z`XrvrAH$8YV$6(!Y5JpMrLE=8WwX=p&q zbPxtf+)qMhsYWCGp)f)BN`sh>z|Rq(&UC-bfCl9gH#>?1HL(kW)Sr7a9FN&ljMjHl zF_!5gKtV~CX(7w3mhE&AGJ0=vK8!%@e^wZ@h7v6Ft}nC(4F-gz8P~7)@FW5gA-R8WaqXEZ58TB6SP zCvb4cl{~tmaScCIfmP$C5f*OZr#YS@NSh9&-di^g)3*~G+8~~N2MAPvkzbV?SRy`T z67{SLQw(Y+InMjPJZ?AP6J$UViAX>ul)(1d^FDwlxsK5F?>^g-)Bs~(bzq>mv7^B_<14`Ty zGDHXjyx7I_E>%UhGyvV&H&_(nK%t&k_&(Br06|~9@WT0hVqh;UJ;P4Kcc}|zp;g~Z zMk4g9SWP=opy3_(0Dp}c63|Hl(oL}b9+*XJ2Ek8&KH+BlDVR@x6(-}Wag+W^(oa?I zHw*>F20HGalBm;$j*O?mZ%K<~f#&VbDq{S4?oaz*nQ=0Bw8q(}pD8lLeU|bDi1ca*7Hz-G)yx10u+R3QYi1SjeU3&(FnTY}E3s4rK%ECm5+P zwjf%Mf&4_oc<@#Xkf02eUfE7Zy{8L-dAN@O9eD&~?$f7Fo(Ut1D|>lhi!Rt+XsN;0 z%>Il*ZtW)3Uo<63t@XyVG`K)}W)Q$2%8sZ!3V_s+F^1cT-LKT)yl-)Y-B5|Lt79y_ z+W$a{wYZ>c+{gBot1Dzkm+g3TnpCzzAiX9^U?pTRanfumhCz|Mbl zepitnlws;=>4kS;NfIMs_{)SGjsf!YSrPH)fZ#m+)n_gA-lGbDTF`*vV*)@Sr}M}$ zF2ufa?3i${6LFww-`nYU+)7dk()VpGh!{*i1JV*uHH1G#Scq;!@qip-$Poat!anjx z0;@xFr+pBlHwDr4_8;{61mZe5g)i3@a`sZ+HHon*F!<0FIy5z}u`VkrClD3&=N$Sgc>L<0ljtXD!L8f144MV-E{56d+|g&Htab_jzq2U)Oyd zL6DI=Xtq!gqKI_CL>3A;+71ik4H4Hk2&5h#lBj?H03ZNKL_t(_+|c%HZ^t)6XL;Et z-2>r;Hi2dhI+qig4Td014x84X1?LX33#`e)R*!06&cuNXa-j3C-1m9j_xr7qtfYJG zb-GJGs#Ge;a^m{vd4G@Zix}G6e0b+&uoOU}xH=x;usi>E-GY`kTs^1x>(~Z6^-gGG z(8k_=zC0W@M$YEaWS&6dTIhK*Y*kQjz-=|Ugd41N0$e6%2x?6m-uEN+)w_wS-JIm! zMb3pXXLsS5cTsK*R1J5s)9_L-`8=RF0Xm3W_Hip&@HJokrJJp|77Tu+2p?`*Rsq!Q zstE=!G^*i0Qj6N3BnvO*bzKNw^ObzScWIm@#;|C~j3 zk_d&(wZ+%;=#zNZhPH&Qx%RLpCWL(A;K8zVSovCgQjx!GKm8RA7YnO}8`;x0Ms0j> zuIbx}i9ZaM*_2eQf@a({Pi!!XoKBKI?&+pUpr=|g4|RcA8TUw_+cz_zU7O)Al9d|2 zRVH*BX+PQt2nvWkAC*BH_gpc&rU9|kUyJ`y`lh`{-nKgeAXdM%odVh*fLKx1wgP&* zq|eyzlv8FMJN*JoWRzqoVfGTZF9ya^FNk22@wOy)du+W9Kqtj;F_H64JEmbmxj=_IYyTjpuD zI#K2-%UKri#3Fb?l`haYIL(L$?^Cw3QUuY&Sj1za>AOfxFd@*pL_9m{y7oHmr9KOB zuJSWd?=#a6U1fTVo}1OD^Hgf-DluYIr&8K*snLjPL?@>PPD^NP4AOVAPxa4c;Qn><_3Z)OYu{w zJYipl)nrpM?|a_%$si&9s-@K8> zs0aIDcwe>zKw?#e_YscY`t0E>Nu6X`kflW5zeI12J9pkp)=pV_iVVclopX6(`5E`i zr*SIu5+6{$z2Av6%{d%4JcAna_-Mb;)|Jye4nL^jk}v-jc4}A)3P||jh!iEjA`-|R zBK95=DC+)yQH+_$hqae@kKR-GI6lM*=+`bS{Q%d5X;~NN{j7)78-IaFevHjSq#UQ;=RAdBQ#$$uk}}REymm|u!3(P zRDj4Scni#J9GsZ_Ra&NhME>aC;*(?@2LW_&)AJmsMb~Van|XthmY9wF;lu5p%mULf znoZR?P34gr>p~$UPd$C=96_jI(2-$ptM_&)x0mDrx#f$v2mbBfE()gAU)ATR^xEHJ zx1zUgfk!8go`-u?%L01N&LS4kq8FN8AyIStUmic-aCwMSOUIfAt@AWCI`Gox0ifnu z`h{`FPvl9ju2$GwG})g175n`NeBeC3gaV>TR^Pl#4`(k!;nJIni<$6e^A6^AZoU}? ziwekBgISkWF~K&+>2R{cr1Wa%w0nLDwjovVA|s#g27CMv=l1>@%e#i=`*HYjy|=<3 zExII}7=m!4C}7w}GYjhmpjL~iK!TR(yTtiAd54Fv!MgPNyrbbIFPy63HQ(mq28JAN zTIp8Igue|yCHG?lKt2xuO%b&r(1Xw3{qx886DC-ywX<04-{w8@27~TJcbqP@DlPbc z0`*6?<_a-N%f!x2iB$SXRDMbF^he~+$r27F@_~dY90_FM`5L3}W_J0h@;VX`dCfW{ ztn}BL{CVZS2-9dD?Eq=(6+ye-O&m5Y@6goU|+Mu zoFn=vWA$2g&al%?ZN4Sq?RYfdi{C{7X*cKgbDe`x-G7Tpur|lUi>Rx@YyMmZ7P9%z z^R_p^s@k&^?H!LH>Nq(=lcVW`er~ORI&5ev%&K;pM?bp;$>s$br6GSXZTX*X0lQ#}G!BZ@`~T49)xO&M0;Px{>j&P5p@d1_d>D?u>)< zlgSQ(@rS47|AqHp)3Vw9f6LBmo_P&)y`M@CZD532U)JmxDb3n&R59TZ6jTCre?VAR zULgfc+8Te!IsPto?YxU7QDj+&Q@DrdjD}8HfX^hk@@!HcP=VQjE-W?qTLI*MLOAW7 zI{?+U6hK0t*~b7BB$W@*V;iV0QOX>o`EEf)2n1|X0adI%qp-Ze^e^NH&C_UUN3&li zgXS=#tx}ozqn;q^6%>=lm#u1Dg$BgF_-H8*L8RG+uA`ajNI&0J$ho8aNP2YxZTl>s z4=x4zg8}OH_WzC@&U%i)4=n`R@q;wIE2!yRKrS3l2g|+c^TLPaKA_)80X^5*9ndSV zv-bBoI$;M5!~`188Mb5FM25yN+?WdJsb&;Br$6h<IIx zha01z7|A1z!TYX(FUOb2{h2v8@)&76)-!PoKlB(*Wg*Ju=AF+VfP_K+Glow3X6r9g zKzGKz3!%KF_Kp65A^O?tMYC%zTDEsIWTjUaXaL?uK3Ku}#Cd|;88~TNwSc5nfzB8e z6!j@i(N=}$>jYlugl{OxW8rLfKar=ioZx!mwiG}Ge~!B?w{hci zFZs8Ov=F2Y452W86Fs3nTkHw#TDhXf&)kP2!|Y#!xlrsr#(#l#E%O&8xRd-qzY;*D zU*b}-r1jH|pqg*sTJwW7K9ZKG{mYWch%N!>q_UJd7E9qI6SdRieYVXBz5S6MXLFA} z_&YaP`-A$2&=i^`SUztaXyPWXoN4A0{%3pAg7mg99AABlxyJdzVpnL)17toF1K~S3qnN{T$)EA&C8ELN!?bTxr4`+73 z`x8u9^xYy;&RuC&pw5+0b6> zY#+=GuD^Yd&_lOto;v0a@?Ig`y`9FW@Mb=qqRDv?Pt6ER3Lq0laV!i1f*#thYM=B0 zEfDCpsD{^QIY(o>)s8^qO;ux8$n7R(ED=#irN5^v+Mi?N`C9>y8=s+-7pj2NB}5Mp z{z=+<)$1S43GF(hPz2%2LeqfgFdie%=M9K4_B9ow`&xG%T->Q|K74qm{vX1hO~DW9 zEQCLw)yH1+2+0&ddZhv)X70#ARzIqJf*gc?pdpqy?d0hR>aapyeL`}7z42&biO+#+ z9%fFUkn?BM+DM|Ikrn`{r$Zj80y>|D+A&qm!LHXt?ltcwp@K(jFz%SbZPcA6vxFu# zbYfu%c~1aUT6P|`ChwM&IyerUxPF5t@iSrQ-cI;)&U&;9b_UrL{D=m+e~@5T-0Za_ z1hq;MPa)0!VaK$V$)qWD)eyz}Oie75ew$@6F19R0e{ysFp&vmQQ^o>bCvjDLJYURb zBiaPi(MRZmXI2dQbJo~)TqCB_o}IHubA)cQvDuTe9X+*9Pi>$S z&N7DLPn!$j_-0c5s4doRiwX9N3Mh%6-#`JqWwab^L&OZ*sP64Q?_kmpz{1bn-s^Cd z5E@2nx--eD)8UyR^!y&<@JR1&-@E6dVEgnMnbVpINTAg|`UjOhKc~|uijPZAA%R|b zvq?J{zA@^EF7iX1XPfmqaziP^oIoFEUepa3!-km?lK*Hr^&IwxbM5#MI2j_0sj&uk9r(Sp)RZqL!ELOP`F%&Sb? z%!y?6LfmF2(Fwx^l0qA#6ON}q&&34+gvrcXTMxwq3lj!VLQw^Y6h!UcIB|JU=&$A! zkSM(K?yOO1H7qx}^cya|^M2t|9%Sj6biE)zPCg z<<5NTpt;n;?Hj2;b3UQ%+QHmG>Ym=deey+m`16Y+)j4?^;%lL>YSWoyiA3q@f&h}` zxdYJ0eL(Rr=-u{aA+0P)iMmH%p!(8m`b zkm#N|J<#8Lqh4fLv_=$op#l;e6wXD#E@$;`M%qL}U=pAW{KbWeAHD@rjs6#0OBzW_ zduNioA4Yg z*^*byab`gR(FMheOVL~9>DCfGQz^uam6Ih5H^zgN{9r;Z69F>mb1}VObH;}>!R{X< zEjhPE50KY?$xjz`wGju25U6h{gaQ&%v{ahwC6r8xZ2g}UL%$+N=w!)kL-Rn-b!ep& zvVLF*C(ywc9~D3PcfC5-Q*8NwivzELw&zlUVz)FQ_8}HbCoCs;ksj~p^r)r_y`Sbg zOa?ktU1YJarmxiS{2_wGxcRE~Hz=UrA__*uBN9mMuIfJL*&`jX>gE!&>b<(BQ-(|! zHBA9wUc4m&sSi5#0a+(S{TBeD^Mb6?)T{K9%IX)D^ozK?yQ>9D`+9hrt8;1id6G`w zcX4*4KI3~?092PdPz30>guSLdAAO@%T8q{R4|;rN|8YSDui9K!#QC~- zH$cM`h@CM1@WdNo1)G1dJOZW>-E>7QwG%pfwqxEL_#8&ZB`1^$+Xo+om0_tM_<5C< z@A34L(GGies@Ta}3v;xO!Bm%1yLtn}2f~a%q8~n`fc`qCfPSlD)Qx*EvD%P8bq zEG^Y=7XZ|zvO&962p-LZ)=We>ka<4UFTbq5z4zAjB%=>#-+6#e9ir)lK0QM%d?md& z5@RlS^~%*xyj1y<9^N0ToDtFu*R9Eyk^IGM(C~d(MLeK(cI-KnfW>Gz`PZl1nRrl@brEENC6Dh&PX* zIUa?68DlU!G|)^G(3V^=8~!u%0Tq%KSn28}cw9&<>Q0>iYQgo)4C|oPVDqB+7HJDD zUgMVce;<*#LMr*RO7*89>_ybK^7wKZT?< zmRR`#txG3v#PnKCvvvu6C2DIrJVA5!>GEms9q)DAWbvk-Z`VQIOe})1I!2$Fn?9hQ zfBrockd5T&+-pB?!v|zpLC^1XoB~2q)(!dipbLA9oHln@_=YeT;#_a5`xpYod9XT( z=a^Gq5nj{L670p?tUm2@PLC?u3TX6daZq|X*`A&yq?e9NVW{pPe%t(2c+$PRytowY z^9HGkXwWLFX+Y;PfE5ny9_qz~;b-+9w3UWj108Ry#+UU?REN;z#d!7xxElrR@2vP4 zIuSI|DZ7}SGsemK6GmAONJa?dNxI+_5Pd*YI}^+eBm+bN!O=T)yi(^6H)*n6oWo}w z)x~hz%+!rQIv&Gl)ksn)qymb+=+oR+B4U&`s~$V6H_&5C5W|)DnVAo0u=#L{3h1EV zMvcWHsNwCxWD;~_&C>!ZK?tCrk()&2?z;e;U(q{cVJZ1`X-kK0{QVTViJ+6^g{kup zIyp$xq*4VH;@M$^xc?9SFqcW8%E`8`L3Nd@g~Y`9gSi#lJO1cxNFn_>-0;e1n_A5+ zYt6VTD?xO6&3tIT!^xl~6wp&|huKzpr*;D^b9q3&Z62bIW@a}afaoh!qw16}Btlz_ zKNsok#iAaK0Uo zM#M%h{Y>dwYvoc}-3Zi&qzpg{|uz#961 z>Ovc}ohqsyhFuWI$YK)cY&vx~n!;r?p3qlaAJpqpa>py6SPnS~jdaes{5(O+Y9(|? z`dbz#IwR}_oj`RepiNakpQ#VXOCMba3CS~YZDO@kQ9lTZA&66A7wdlTF6w696+kYK|C(_8jgj)pNK`m5pY(~-Lnnn&I!v?$ABE`~y*Sc^#j)~B8_h2? zocEwA#9fFE;x^QUIh*XUil3$yFLLfLD#bf)uPPw$h$dL<|Kax2z0;dMpr4oefPTY% zK$wOqas|@`_YjBIo`{;_bPZR}+jghf76>()zPhdbl$k)Z*D#x~8rQ<({wcYSeaESl%9J|Eh9?9#3s(0FX$B|dL(XfZAg)(6A;;078ZYRl*Dorha@ z>h%lqB82-n7*=#ef(%2(xdc%viR`UIl&-k79?z3sX538V~E|bv40U>^nB#k|}OG|2vQ!so`wpTZ|p(2cgOCrJh! z)RObW)LeTK>iFd_(SB;d6kAOQp9DjeIeE0Z{ed6O6R&M@qF=>#*tKR;#M!=FwNPho zpP~3z7tsW1Qvx~jOYASQs9E^)?N8?c{nn)zZT17wHu@ddQs`>_eQ+HM z(k~MLQXf$0ecC+3Vy2a5Q)a0QGWswpav& zib)hL_=Wz{>StNP^e-kwpUlnuJDGp#WWG)n_p9kJbo3di3`)noA5FopB<9Z7YV-U_ zP~;$ioJ7)*j!QgoEkOMER_ZTTEpqUzw-hCJ^Wv?jgj^(605%eb%dPxUN8L zwt+siW=RHNB6zQJ#)8yWbH%47ffk3^-oG5jk@WPFLPeWi%6U_gR0p*ep>G{sE)41*`Z ztP7EFj(N(H(S)8LCx*ss22BZsYcQ>M&&_;lshJek5d^!KdbhRW#fcl>C!E%mQm}%$ z(=#fgI0)v@qZE=4VFuSpDP6G?frQAJk9e)lv1ipzuc0SUcyWoODFM(WqhOzH!UP+; zu)Y3T7F&-~0}$Op*EAH{M3YkWx3;>BDYLsP@y{8*RqfUZAr6hx53#|2bIiG(a zDf;A7ed|w_md*Petst~%+asHcGE4{D6F9H*C|$4#Vg=WXEUAVP&^gdD4c5T=KKLBl z>_&iD^;w}7&yhA)_}W4ZBPaA6KRvEC7c%>q35*hkeQg`m*=LK6=YRb3vP|foU%dDo zr(#rzp!V~&*is+~dTW@q1#EWO9kx_W^nY}bFm3MGsqXK=32g&?I9j#iz3{x+d&x_h zYonhN!{MD9ngCjurybm%&AbRoe^IFXl@G?oA6b3&;9>o8#_#Dnn=_^zqBI>ksKOC} zB64KUxI0r3G@EHh=YXzc@+TZ$PL)5bw%`Qi@fZe}9uOw{&&r_S34%r!w2p*8u)RWO z8xavBGr#m)ErsXs_MFKzD6PUP+#1&r1#{kIhZXZBfi&IeWPBm~LAKMD{I(X1_pa_S zCprIxSEXXfxKatywx<${o>FCX!2!LxXqv4KV+Di={0#+k|G+|Q__dsSYvSF`il2xG zYWTq!#i-jYr>KaE-7XbSqh~IlV(W$i`X%Y(i^mFT1SWvvuD`Y{b#7GQjjGg7FSSBi zV-e~~gq1#G=IbzwyE2T@t1)GK6S9L^Evb1HtgRExH>%kXc=LcK`{Zla#si%jgm~QJ z&a&FYFZbADc)qX*06K&tdVjCI^Z2wX>*J^GWE4!p@c)%PSzr84lTqpaLFcfysQH2u zs8dBzhC$;R4t49m;Q8N<; z3Gy=u9dyF`mzOU`)>38l3A{p>)-(I2ZUjOrj;?NQUW{IjofIAoTb1-^L`kF#$%H=S zOc>IkqsA0H%QIC#h9wJ}Y2m5LrJ+4xF4|!Ue;|mgAxd;URs?w4NI)}oJ|LVX2ufW{ zAzlQHB@!q&*E$EdcFsiCoZ;1H6WNByIim!Uy%&@~^6PO{Jos}aPvSO7dX6|$-n*Oy zK&F6VC-h0ldx(~4A2Y$mBf%N&2_Uh-sDR7|^x1=#d_`%Mccp{?ay6{H&!MhA(AYa# zZbaQox7?*k77a2`KshL&;0cKk31(z+vb zZb$hu@ot-g)sm$#I_;wSPdtC-`Y|3@kS#f>UL8^M8BAE#4sQbJx_aEMwr`LLjXm?C zF`j<8m*083bJ!LQblm>q$44{&K9f<^1q2zh(dpdVf4Ywmg&S3?C&5fC?K#_NCmKLD z-LxTg4ce$87n;V`TQ?C+JCej+_`GFZD#MlWm`?r}3e+}=C zLJA_BA+Qi&9c+EJ^-cW(v6}j9_`{faKJ497sc88G=LL@GU{=nI-1tCq1qIFm3!D?y zA;(R=z#dFGl^+~bN_JkSCl_iUi6u35ejwsQz+muknKwfUn6ogz{M3dhv@uLDuZy67 z&U_vtFceOwXY>V~0Y%ZYJFTBjL!}!7VL~A@z65t8*kTo93VJK4p;(F)Po=b)U{BHn zTg8_%Y>U+Z*5v3f^Z_Lm&^Pi=j8csIar-bTpjJ4a{}cIJ6u3m^pb@1&pj2NTM%_WA zPUzw?{-@G0LEchISlrHEzDu8XeIX0D>;i`MDM zck;ejcASuzXZE7JU4HHCg>OrruEec?hUphJ_Rkf+kM3W-aWtC!AP;90G_%Wu0;<<% z^pgxn0s_rG6nwMog5j!!n^)B^9LL}>e@ zBvfO%jF3+dG@)>rmG!cfGW%M&uYR$%_!Jk^xtHB$u#Kt zMfV$3K%0ny-H+L2T~?PYltENLEjKR}tzFA7%DRIteL!V8p%;`-EAC~q)V3-uwm-bF z+-R5hi*w>n<}Qo#nm>-8fYT;5%~kQExgHh;v%kTDbK_v5#%jr1TkK(m-3N&S82{3` z*ApX>_XaI=Yg|a@76o+Z2aMbLu)5#QU+-5B-DA#{+Gu~tF;s`uy=s1E?U`Vzx_6wf zEmc4-n2q@R%msUEiHJhg6yI&?oo# z1r57v3-zco098P$znCdAm{3}N3UH)b!v=~)SvUIbqKm;?-C1`w(N2ce&KVa03Cb_E zx0uUnZm`_cwfb@4t+X3YUK%oA2W@jUGu}nx7dw|K_H|wfx|69Y8~CGx79GrW#Kxw? zjXtSc6C=^wG6rICtk7l*WKGT}euPA3aFq-tqJYBjPvgm76iEu8iY6tlmOOP<6E>Od zpaBLAG#Vqv(-hDaT|n>w&1xnwAnlL?<9t^)DWvT-Dy>pq=e%Yz@A|EvoauHsGchvm zyyvA=dcS1QhEqGM2@m>5M#BG1lj2W4ZG`;_1f?7L1x5Ql-eSyxfl@WWN+)id7&|7e zn!RNlx*fNZ_AVedg4N<*z6h;WNC=@DAM;sK<~X$@3P>bRwf&Vx&{yrMm|R3s{;PKT z(ay7H`S!6$q4x`O32*CQ!ru)*fQEiG3xQ_dUOy-591jLrI;fouqX;9h2B)<|1rG=d<|AvxCD6a`jOYwwajGS4hG&sXZiHY2wwJN-{Dsp%!jhQ#oXp)M=9uYY(2^!OS1})!H zblFZ)8a(!Z*(a>drR8t2u^KvLW4l^FT8bUOA`^tn&_w@u+UQ@vket zDAIu-g{Bzanu;KI-Y195#{sVjuFlZ&9adKp1td#SnEuvL@U>s=PyccE5C6JGZY-0@ zTKNm3IL*BI_x}p_GsskoV4xqzb@cs$y~7C)&$#dl^FLnAcfvy zihW0mxXcN(=M<359BMY3b8Tobpy%HHmn{9Vz5sdG41n$*6+k*0Ow3LJ&?(UJ*J0%g zl)$@M3~gcHM3ASFdVy2}-5-TYB80%}mkh*<2^5aSwnExoeab0Zzy}84xrq_EE?X_L z-8yCuWBh{-;lnIq&YvmU6Bv%w-~o|s@?d)yxUcSpK90%&$)KCUR;FCmovHXM9#`Cj zQQ3~qU_Mw1C#75>x1X zs#8G5AXlK_V_FqBvo*bFdS2J;Bl$;G1%y(Je>3k75mCCDs;RixnJ6>`R8bu>)W$}c zcR_yw4#6yoCdEpk_JZiC#L{QAbbKRz-xu3SAZ}1F!9b(= zm9_!#FGk6Dyrx5kagO`!jrRzRXTHgEz5Wf1FcAiF%Df8&K=OyawK;X-rO_vPqKFee zyFHtF-t`mE6*qD%mpO%xkLA+KMLj%$wOr8Ajda;htb0El=QHlvhX?5?b9cS`|4f*^VC%vMH}Qi=k}$DF+RHkq~x zL{MQB$(8g`w^j=-7pYQFb+lSC1{GW|YgNvDMT)(hT%$U>=)+HiB!I0g0nmd7GsA?< zQB|!LEg*-EEkc1?Y^rZ$oRCiS~~jB#_pw37BLY1lY|z?6>-i;Mdt1c-ZQuLev#}6aP$=rRK#Zy-efWZQ9uwv8Bx(QRrvOm#^elN3{x1y z-7Y8l1gSU~k@`4al`DjUb&)7SY>}uK8K22g&*i{-*PFVR0$E#>f<)Isi!bSWhBO zvM(HgDA$RhQkXM-+@|TJa-!P)D*x!K>Q{&DFRL8Lkbm?{_#;Ps|1W?3aC7?d?+T#y zb9$kXhPZ)NhzcNi-1G{l-SlBF-OvhC*8fB3RG;p34&@?tX48)W$!qLB?n$D@(q$w^ zArZ)D{V0J(4nHmw?~SnVK5F3uUnd4DY&N?X!xJQ5)#vZV;dnah)<2VP>rLm$2?!$A zMRMY2!{%Ml@`@FZ+{!uxG~zSv*_`Pie;k=$;hTP0X(3BWG>_ai2brwkM-YUxyObPr zg#**N(%|zEfYKG&Gs&F~1V43EKn5FyPB}Gij>%DS$!uma^^7PW)kh?dFlfS+oc?ef zUFqp8$U%7tyh9Z_f2e@c^g@@s3FbUG6+8LiubRX{kFqO6^|j>&qdu5|J{GkKCaLJg z;@s!cFkl{LC5;h06BMGL{lGNy?mbjm02i6+u6YcVO1@>tC)_+Ig}IunLg9}ItIA6q zO&cyGyZs!vNjoQnM0Rna^UqEEEQI>eRHX5f3Lu?JK!2l#N;R{-!G?H#kg9bL5&=|5 z7Q-iM!6?bt3wllj`NkZDxK*MrPUVL`(N`Bvu6Dp44Pa4rVlM6H5GiQE9F?do@Y?a{^f*!c6 z2f|wHo{&I}J!ia3#STO64J<8$rzk|uD&S9rW*1E`tX+kO(x{~HDZwF}jscYFX53}q z6c9`>b!W-Z-UT+dq(D6uk_<%ZFf$XRj; zc(u9qJtu|vIqpv2B)vUu^5B6NPd>faB+$t+`LoaglKg4tAY6_fkS{r!WQ|Z~bdSUy z3xXj-rCwCgb>sRhx}jp&-queRH|y9g+&=hN&&0XvRgbd5YUN4c7%ZqJZ|Fe#xn2P2~yl zx3!*)3P?8byRzS!d6?Tz0U(`B6i4Zsi~UG!YRJ9-sM*;WS>?M$;9s~-hOexlA$xQ9 zQq=LA(0QiE_YoEghwS$AhS9Lii_0*qGb!=2&GXQlf`RoIbt8197gLsx^1F+TbzIE7 z%jP^f;6j7$+HOaaa2j#2IpFEiDg<)YPc!Nz5liSC8<<}+fCPKpot`!HE8e+RP#G1Z zU^Iz6GCjkncsf|l;XY2uW7&t@auuw|o694yv9OWih~zpCe=Q0~6h=yb1Nxj9e$Hr$ zrCk82GGcZ$PV-gJg#dEvL{~C*>Jve72YJO%9g>&f_-3jA@k1Zbn7;<2fC1PSnGt62 zkw;8V3WgW;X?isnJ^_K`S3?SAFbt>XVVcaVgkh37rT8PM_h)s9_*pG@ro^2K&C%mb zF%DF=tA&*gTt}Z1ryl5hRtwBAsjw73i7_Hp{?XEysE$CH=;Y~%0O%(jjyoCAEE57% zmbCOZiDzrnyrY?)g)I<8=6pDq8x?kt=p=pHw@^$h@Ldaj3L=pj6g}<3xk+~WCW%fD z+xy4+!k#L3A9u_JEdXji{r+E;FhOgV>KO~ z31`m6)3d1{tFH8-#e&_+A6+ImVhXIJ`1I>KRgkbQ9p)gvjI^h-BO1SJ`J2R6;(g02^UO7epZAld_YL>W}?z2qF`H^2jl`^rAh<7r!yuB zs0@Qvn~-~>N_tvHr`&N`{)a?~ougb%0CaXfWDZfGG}J_K=Wtd86`Xg z!s?>w#oLMTCBdRv(o+;G9VYuRIHi7~gW9LPKk@Xl0-ImQzIm~W@L=kuVe zd&kxMDFGz%LX;8guV-t|4m;J!zkEai{eDp}jM8COpEd@giUR8Fqr)?{@|~~Xgs%Ew zuNn{&8AHL-w8&N-ROvLW2V`6-W}3$}BvGdjdL`|lH{$6~+mgMCXThh3>HD)c_g}iK z=qE2PIBdsFI33>)Q4D&27LJBb(3CqIvl$txFvj6Uog>0N+pM#cVyGpls1h7$@zvN} z52k1G%-Muzxrrd2_$2`l1Oemc=O|;9>*Q>FX1GzJ04#hw?UGBvnyL0?&74oqGeVyf zB$FPWQUd9#)Aqv(t&w_SCg2OmQ&AADnyXjkhgTn~Uz7@@3SXmGs{?rikVe5a1waqp z6sWN9E|aMyOiq33B$gDS`03UV6}0t>;S)jOc=Ch%8_C{41ZZ0ET?tsLySi!_jZO*` z^r6*KBzuRL8TQ8{C;sTP#UB$6+VgaR-FxX(VwhTfyMxX`B(bztb zEbytTwnP3{mN?8$=8_6ed=*$so&)dhNwTPL`ygR@71$%O2D>^fH=)mgKL0+iMwsE} zl+|GSowx>dzkRw>h4Fc1^vLha|@6F}BQ<8Ax7+&cF*@{~aA0F>|8 z6y~-oy-+6*6;QM39nS0x)Qo4NCFY^!=fYsjg%$z<%2n3HzeqGh6yxju#T!&!mOZ4U#14rTbjlc=|2VLuxKlRJ-{`qE|Q<}FPc3I_x>SQ)C1hi0_Gu3iXfSMV3??h{V=Uid)g_-7?uGvJTU12S?A)z~_7btF@gNIu0l zOcyF>=vu!x4=Yqa)B455D18--r{@r3tE&Q_VZ~X2&L>r>Bp8%P(@rLA8WSK<3A=KWRsHiG!C!Pux8vH zsObQd_mj}vbNObX7)-7mbR$u>QR?Sc3H+e>#;ft=<(tdE6z2pr3U;*3CZRITeF>NQwh8fxrRE4}c<(5g@M8RL z=geQb*actE+4Qv>&v25MVpFr$QhecL8WBH}N!tIMP=(YPOt8SPbVbypE3MVoHD!tj zOu;4rG==wiN)OOEt;8)#pog4_;ZqjRT;&?&93G9)nn)g}D>E&Usn60+0y%J2Kfg$~ z(xY*ATG5#utzi&X%2i5E0>zG?f@NsO#j~Z4^io^!75#CpVW9u3w<5j92%dP9d_c!iXChp z+)i85u}-I%=>6k+BIZT(JQkyjw#aq0xdZ!a?U|g8JC#2#gTl|hCxB1}k6H|50zI#G zHmZB==f}uj>Nri)cB#H5gph0-*MfFNSk1p-tt? z-o$ko>2dv%Lzzcb48}sQ8HS&RB$8%AH$$z-T$GpmKPijS$-M6|-r>#wmXTOwPgppk5*5b{}V zB~SM&)KMsHrts;UpQ-l;6ruof5Smg9r67V*y8ZffH#MarDAPSlMf6dKjaqxc!ibR!7|NFS50;eM1A8N^|TT0*7h3I07Y;~>SvRitILWiYJTdV-iyRH>N+gmhs2HlW4`yNz^faN*|lPp+d~{c}^f` zu3s5_K{rP7#EQs0I@$j4{#5(YH#^sAfawGp+X-Lp&f^^d2+!?6{)hm|=XVkcD47WK zyE>sEfV6`lYfv%dwE7f--ScjwYul$n3q{QbvJbLdI7qxGrKb|f0J3Wbh- zeldq1gV6o^-tQv}xvvu{bmYMJJ`0d%!{Ewl!!E5endp2NLl_fZ-+H+DgO2AJu^SnU zFnXFvAbNm?s&iZhM~ElG&^;W5@c=?7ph`7?e84jCVL_;1UuNWMEfK zU(3S~XLdTMxF}OaUMDo8xS7DH%AD)_nBYmBr3f5ZrBn~So~F9z*ezELwQX+l{ShC7 zlUfgtrf>_LU1>lorWAg{h2&yeB0gL(LXOpq5T0=X|A|s;_R}6YbQ0$o2 zDQKpiT9w6t(Dqq0k-4CS8ihC}cCc&~SUd_NsfFebNn1;L)Qjg0I{=V70j~u$J00|? zmos!{ZO2<+JMaHISA}s~w|-_n#QBbhw|_GqQ0HE?{haq~Zir&kr&K`BjOuu}ST$H@ zFZKbQDu=3+Ko%9tpXL*Ru+zMYgV9U9xBqmn3JkS>{D)yO2vuledI(8$$?D{hYYwE%HM|1S_F@g?jP>0hfPyd{0MEgL z6hLQU@UhLIo&uF%JPpsxS%P|aQ9yLrzV5=e(}hHlQ!yi_T`){dgFvHTl~!pu2}aJ$ zs@Gv&G1R4+2N2;U1?!3sN_AgPGv|;%0-zL95x2I4TbVA?pr`H?s)kZmr8Jy8P(9cw zSdu+g0jpw5SLyfINEdOgx6~J;H}|O2LUy&h6I|f*tT7Nz5A^01ozNOXOKXtMs?i9c zsk(yB)gBcLjVnxr4#s2jb;P6L8HX}L=cI$cJY%aa4RO^)=t>%;GgVXof?Ne!p^{*a z<50ynh)oEg)tf9jsTC4|{A5rqt^r$sPbuzc#3V4yW<}@69J^r8!AGw)hgz@0$xVMy zGJ&#|%%9ZAT&=KtAmKrBxcot4a4KVFAGY74(2{9+8X97>XHWNVFb1g8VVCHpdZ0xD z?+JkJ-Sf?#+ZOwx_lFjj z2auJ8CEU>J9BO(mbTiHb(iOvCXyN+&$Ddy$2AGgOqxA4qc;9<{0=R*MKrdYikcuG= zDIDo|_b%Gj%xE#3Uv@X|Y-&&pE#x`Nf~?Ufn2p_G&qFpuWIf@?6wnmTpxZURe5K||rCy5w%5>#%lydoqo3O%O%R$1INREnR3wI)kL;=0mpA<~^lF5~v zJOQim1xmQ91n*mw_e|z_U(!l_Tv_2?c`v_96fw9q&4>cZbZOnP6pW=9KNPGARsB|a zp&!c3$gbrU)a#)I*+*yLcnWuPAuR`{sh|q2a9B~tw`NFI7K}pAqk^UoI7B(E7Q@T+ zW-SzH~m z*AI;^QBAL3D|QS*Da8)g!V?x_)Ca&&%I%9%ZZk>=LMobo9Yl(-pb`YZd!}TI2_|^D zlJ98r2$4gzUr0$_@*b~4OP*>xS5IiZDW^9XvcGDkq83#$;C{K}{Gv9kt?tGdU;;GJ1?2^>rQU6|n2G_U*-F3`F8JPuiLxy8ed(peZ}Nj2hbJr7_ZWr_ew_s}O|N z;c?ijJVT7VHORbfcXQT-;|!#ZI~8$w?@TQ};Xa5keyilP{@&g7fpK z#_38|lTpQ$z%sWwNg?B1|v}7>HToe47^=oqOX>E)+KQu$znwcX=*0jD7 z3drcQ#*3&M8wjcb2tFSH&_2Rq2!Zh+F~LLu{rR@D!D=6BP7B2Vdh#)-d~{y?-wL6X zdms>|GNUOpCJ@>{!dT8Y1=LLXfT(~}2Ax{V`llB5J9W3b>kFhUp;Zrc(1>4sK`@*n3uYj(KBc^ z<|HqxAN1Ez$V_Ov1TG2M+8_qZgAH2h$q_BnVC@4es0jX-l;Gzz@snXP5O5?^$sl!^ zMWa0VWvlcau%ae!001BWNkl97mfFrirSw+hEh8Y5ZPrG>MMO$dA)f3`D`k5OU}zCQ?aE zzzDxTL?9ee@O1}MjqX8!8bexeQlE$Nfe7AhtZ=m79u3VyMx5pL=J+x3jUxZ{ebB_F( z8z%$+p^`ATF{E`dMh^x(DaA#z^pMjdbP)H9zTu$Oig^Rld*Wx!=mT|=hY8bBMW9&P zY3}WJL>%!E7?g(sf)A+1D=s#qx%R{Zs8aic0J^qJ%b#jYMbNzCBkdUpBd zjhpHgFQK&t(kbuEZ4T*;9*)Pe`x<$Z=JnTDc;HaEAX@bb|2<7S>;%*J%}kUbi0 zH~gR+?4nEbkUf)dGD$QX4O|~CE$fmq{7kD4xJuCnY1?x z{vaGvT~R=#p-9s}T~5Iy1V!M5!kxLLcwidC(@g$A8h`Wvw67=9&>__EY_GOX#o~-qXhq(4~JvM4#vzA7&G(T9n z)QZ%1-TLUbXjh|gQqqpy5Jc7)M5A;k3xj)Vh53hZ6pUDT2Kew^6c0Nnqm+t3!YyCj z>zq231Rv1z9RR5IVeSG_e4QqI;E4VLOseVi!~AVwp7Rpc*!Jxk(kZ!XrPJA9FXwjW zIVO5BSl%?>PBWPY6i30DrhqysgUtC=-P>~o^ezKB?+e6qNVUqRz2m)hd+%vgO|aMk z8@_sZc?oyVOJ963vb)gm1AnqQgD7mkqOn#CurcDy7J2aSj{0-d+yZVw;ZHb4unP}R zF7K|`!6Bzs0ET*0R}!zT#N^j(I;fx-Me58MKe{d(f(Bx@l)FE6RkPI5_eZ42dpL$C zA~q(kQy-B!o+;pvT+853S>6Qq*u+~2f4b$AAxIce_Af0@`jaxmRxxPcu{_nd>I;Cb zIGP=p2__hcd`04*Ns%F_rF#N3>>~3w0YGR)=R++$rl`#1>MyqI+dLX3^Y43u8Xw z`qo6n>l4!GV6oWQncqk!s(!HjA78%yy7u+F z0k;BKgX!?}0(Iz1kA2A2_PK43Z8Vs2h~&uM}%1cyl;i*oj}*@2y`tr z*bZtjhDil9oL#(u;xX=o!?{w_z^0zSr5vJv=upQKsNa+NN8QZuMQ?4+f{}}l=8G4*4)%&Xn~$X-LKayi4ELy95+P+4hY7rZu70-@2Xe5!yJ z7ircy)3hN5RG2we1q2R;)~iHsW;m*69D1ll z*SOh++S8<^2BS5y_at(P=)KCKlFFx6rPR8ig+8&gyw?Z1hclyP$@R)TE=Rq)5!P~l zSMG6F29fR(LAhM7mn-V4T1CEIIixmP!_6A{#IT{(LhAI%!F<%-w_>fGBzj7F92K?; zM>{Mp^$G}4FF@wB)5+WZHPoke`1~`9pk^n(wsW=p0WAC4E1;VCfQCQ+JcJ1P;B5#|7yDCL4+0S;W5>@vo=br)OqPL4H*C%SqL6_XJ~Vl0xK{DcC=QD z-8&F#AEF3MmM(|xfIx6eZ#}FhChxe)u5tI`!qvM^Z2Sew2`Am|#XEFbm`9HmTv~@? z{9V)h3et_#at)IiD1SCZ2W7|(Y?tAomD5@PRD`wxZ-AUKt*$b*%Z@sVA!~Jp%a3>? zGDzMoQy!F4M`d!atjZ|jQbnhOt%&=w?>;vU5gL5WyV{?+_r=u2!q3#wR+e^WFs8j*T!V zpeHEOd?AL(i&bhLxOTRwjcz9nOc-3ZRSfA9aa_&E$;hhO*C%LwJ#VbtUSV_{@Tpdx zZzLn>2?gY9!PNM&Bt!rR(R%0RX|nz;(FXC<9^@54){>(wCRp`aFw{OxJ$W(Te?IgP zuuxq;flgTp$B-{D!!SUZRv3M&bP%Cjpo`f&gb!M&59*tDwl>GX!eB2{WM6bAt{ITB zMlG(fj?0*M$B*OCS=30oXbqcjHSmq!cjsQhc%oT^NEI}d#ZCVdb{00i;`twt($)t8M% zB)f`1Kfd5j&_n+86K^-LA3ex`KXQ8j1yqDuYBfxIQDgyxsYy%CxITbW787(cMXXQ} zsVaN_E`vB-S}nl|V|6eC)7}bnKuTLLN!^d=9Z}i8Vla>WZD~CQd@k?@w!AVbwUlIZ z5PfXYYD}sB;f5jt8g9uEJLS77c(}TY$7N9HE}uFQ@rSC=T5@?<5LO|1#|n@5y(Um70`8u8+80&jC|9XT`GAr{FP5u#J8UcffxqM zuT5h3sM$51>0H9$C>#ShDtj=6XEuXvhP@OtG{`iBKCTa#{)47IY|B&ESq^n4eCYDw z4V)R%z09^!6F1zv5utB!+y>Eme}YCshgLDi4~`D>DGY)rG8vLeITww)&{4DL=_9mA zHRJ>rc@l}(P~14Yq};utC8PMsl(VwV;;189LkgrLZn8%qppZ2z>02E+c1-#JPy+x8 zWRu`YaaF_`)Zr5JJ%Eb(ti8t($zuT8Oemo8`=BpsX<{a!|Aj?#QA@St=QXATcFCLd;`;i!y*B6GBr1Mu z_8jdqAnx0w9%?O_$5`;W)baG`WwV3e87fpNX${f@N2+@)#ATjmxqpm^SibXB{`46n z5d1!CNCR4Xb_#8DwVecyRo9=SF*FNJ0)JiwLCo!3o4d%a6IlurH8nh_p@yHHq@+~( z@WI^HwVKHzFPFHzLIWyaWm_Q5Q=Yq!HSIXZP`y7adMA5ef(ey6tn|vWeRSTOKt`cc zi-Bobd{Y&W7+|OfYwlRciybqp*N+bVqUtdXG-R>*7;YaTWk^9}BiV&3a5{_8)4gEn zi(AeYD%bwR8n@HSyKpg}WH|7G z^nq9rtOyDKpoyIDsieR;N(dcD9S|r>{A99toaKWo2_!pYGt224V1hsa2gUTs9%bdA zY@?q$iu$>zd=xbRAc2c$7O@NZvW|>99zXpUM}7VXzF$^8JKhugkstLye%2ozJm~hJ zo`Ob#cDh6@6;XXLt|FM9sQ_{aT#xuK12{$UuMo71REc#zP|{o#9ex5{`}9r)SMo#Q zr~)GUq$NLeG0+Q$CZmRw4OWlnTE5>&KdzbT?`{lEJ&wE zDk~IFS99!b(nG}A4fy*A0{d&0KW%2;-_$+jq@dAo)nKp*{(wMPIrmJG1W`6Kck*V) z7EmS&;>dc94>EQK6@q8{zH)}W??HtXKBF%uvalWXG5WX>$yTnB69@@-j>=?APIeJD zLMBfiY!gWhzC23|4F+p`Tla&u{`BC%A2Ld+h9U2W7hJ_8C7X&sj(py71Nh*04fQGk zA)sK32Z9?dI;F1qEql}oiZPS82Rq=bQa%<*&?4ERqOI8HJ)bF36S<29q86q59L0)yUs<(v%an@B6q-}o(IsJ zjn?uW>o{`Oip{eBabrYm95pK?vnMMpjQ>f$$58rKx)2dJw*)OKMxV83#vok9@(@Gp zl*vEpqu$Aj4Hj&>lxm+>UE40a@Lfr*<*2mPZ(Zc+XMns(89}YaSsI=$mf0 zK4y<7_H+&tLPtB)yCF2%))><}0is4?G(=#D9YNq-4lNGZh*ER@m!qTw#4S-k*-h0! zTR>1Ym7B=vEOMluDl1NuIVNy)b1jqIIl1NfKXf1wDE1we2}(cMG`l)9gaw%PYO2gytUfrh)jNuGpSQz8Y1 zBxMs1QX=tKW6_m2eLk@i=kW8L5Tr*033qxTe0nB;ggdy`?W}F~{z*))o-!!c+Xabs z?{WnI_0|cW@A~szA}@#R)2SZ%w&d)ygn@X|eZ{aDYWso!J@1&^gfzz7Bj_JS!<_QD zMIM5VZOQ^k5W ze@*XUh^=@}^WJ{DqoozG6DYq3plhwMrD@f1wHR6*Prak9SxxgW{?+u;Gt?rxrVpsv z)}TETn@5)4td5@{vv=U>8Fyzo^i5GCqUT~dp8Q06>L&)w6)mIi3@zc&7k+CKGqhlh z)i1i|iGiIqw7iQZ@_wF`Z>m0tFr+J@(c-34*jMP483}ZF29q-K%ThP6DLW3WnZhY&1U6Yi&6?dZgEb?M5eAVdF~I)Bi|(?g zc#SA@a#1#tTUof$z#6N5u2So2loJ85JL0RQhDoZam{$Uy_oEqx)R{W>~s!t^Z3$A~q_%YAaB5_o; z*%t4L?f_FquygtSq$W4#q^6Fwjz5L8h96kcc$C}4x0(QpRV44FHK9z6_QskaAG z=c0Qt4PBP9mPx3>nRe@folV!gM&NVN?Vfk1YJt7;7MIAPj8{E#6J=2Q1l1E@QYsMC z;9saZKZ`Brae%OxM2mH zdAJ^^?pYg%8j<@o9HF>b%hEIRkAj9lc41lT^@TpUT#o?i<-i?*g-D@XPBtQWN`T|< zbS*34kiIoP%3y_PlTW|0f*-T8A_^$0LMhTuQO-IL3G;*wf?0VM{~8Tt#1Z}l1_IwK z0VMK^Ps9N@Q#OI3#sewwFh)9$7w--7AHlgH|lmrO|djZrKo|C8c=s zhsDc;t>Z-kg-+A(ZaN)LyVKVQdx;4)sBhNg)|Cs|sh>B@38b!_To(o2OGjD_FtIc@ zfscf(rtk-BJ_h{dx^Gpa+C)c52ac*3Vu#jMIpb8xU=0B)H!wB3wgov5DXOxjX0mHZ z49S_lMf+!MKnnQ_o>Mph3)#T{UTDaZwFUfS2cm#-Wv~V+=qLw)BarBkHrevsau2-W zZm@~?DerQHH&CGA?R7m6l_dmv@TUiV_(Mj;QZH+o%Nu|2FbRMLF!p2@VL;T1u{e+& zKQ<`+1VD|z14TE2h5>1gKLOvtBwDVqE|;9HbD}01P;v4=ZhgG~M#c45Bo*Dod4PpK zedl{o!zXcvrn2DtziDx98PjW@<2C6RLGI|Y#7rua{H=@AkDWf>DAfY!g`cAs7% zDy$+5vhUVE0wM1kl1oWJgg-uDr(`)%OHzpnrGukKkDi^1_K}ql$dr(~$W@H4N1Fdb zB;~8^pSBAw#rnWapg&2w0t5o+Anun|sMQt=L40}s!QAefc3musZhHj56k9oUCYJ@# zogz||!|4~-F1RJEVW(?z4Z(|ih@(^?!Nt>QU+10o$5Tf)P7j-TJlQ@5e*{3s1dtm+ zp`vFzc7gLzBb;7z#{uJ5DtbicT=)?T??T;VAqI-Swl*;(l~=3Z{_MflbmC?T^3vVh z%EV)k-AvM`SMDFsYGA;zQ7~mVwyOt70fi@iX8{Y*Q{Pj8Cm7sIm@LvIbywbGf7JuF#5lW35ex81ctiTQ1#N2~Ft^6Z=KmZWXRZg0Gyc4qIBC$F9WF5>s$RyE9 znE`+AEPx*2Fm*VAI&O>ZaGGe?_YQuRX)IEpUk9AYvjNoAZZ;3tV0s5;|Y;M za&pV9q0VZ*#9^of56r^yU9lnjDFZm9Pmk;|`m5tbsP3w~JrL2Xehd1xgLNmQ!E9c8!G6m!n&?U+IGXvGS) zn(Qp!b{-rHnXCIo0MyAVji7+?7UWU|Bv2uWu+AS|!;h4oyIkk>qKD?M0ieBO5kSZC zu0ByG^q%E-8PBFxld_ri?yi zy*uiac{k{mQP|`EG~wUG_ixc;kp3-4iXG3M%#EvQ8C_t*2!C$LYK@bdvraf<+__G+ zsN)&RXKjTrk-HUH-x?SYz#(#u2gr`W3PbUDu$HjHZmlV5B3NCbRk&Tgl~vuN$3!`| zD1&xmPGyaAs(=RgF%SL`#vT=rzM!{g_0iK5l~*!Kr?oPTz6`wK18^*ph1P-`(_z_- zIZyaca{oQ`&iA&D614C1S;KhQPa=~<%Be5{ffCwT;8>z}fBdqSJtZ1(fqx&cUCK)H1# zl0j&l7{c9m2BqZ~>boxr=y5a060V_EGRg9w|2Qwe(d#oq&@+!Bv&o*FezlP|uaNAi z?!4b-rN@Dz57<$l{-Glz?fG&rCxvRhOxATQI*99K3keKuCps8yFB3-y!>i1Jt7lI= zJZ|Kd8Bf5@waFMUv6}e~prQ(h0_eJ3y}pJTf)l8Hn5Qr@{#@ssL+F}nDc`IfAGh0b zlk0VULi~&-qlBq73V%XueKO_f?Lg@RKTenc(3wM02GEhq0F(621wkoH^L(HRNS3YC zBp%@@&t$-z9&Tm5xD{_@%c`flp@=_v&mIc_nc#5@$!4>e1uMwyT%*JRd$vF!b**@j zvF7mOgpSId!C>tcHgCxzxe2#caKJ6TZ?7zmvTM9k0?A8n4Q|P8g*SPomy1LI?e?qH zzte7cFu+e3=s%AfA*W45wn7XcF{vyp`M$42X$WqJnT6#iKq}`B^33`8vhJxw8;xp+ z&LK6|_L1_&E|UupU+-~CAd@AAWa}=s4L@`d`2f5;$bMdg^vT|(CkV+w zSnlo?^#~_{zB2@Q?!Xw+$H*YMvGieQ=5l>C%`ADyyNKd~6Wky4g*}EHZ0*=}9z@Sh zH`=Gq%ujUstfk4+KE?3_C@KV0K!^=J0a6@aSfa00AO{QhQ3LIOtwfYSP9H68F`IN1 zt*q_1ydDLRm5-VR${$h!wNY^)EV=H$$D@q7rUK$o?LFZS5foGDkQZAEunzJ1L;8UB z+Shx>Uml|vL+jMTK&UgFYEV6xV7fR1Ud%-f=ko>6CpxQr!lA{f>6E=`qAn8Py6A(^ zopv`}{p5oO|NdFZ&oNI$B9yv{o(Q)iWlz*Qay05e2FWd#gPMVL*YXibc?1{mYduq@aP?hI#K@I zf_b#EA{+9QT(c`mtfSm+1e#=bcgv5nfDHY_f|y;3mlc5-AM8fF!Z5pw!*=;3-e!O| z=EnetggzpH{_ux?&o-PLcWa;sRl_ffC!+EIKg9jx4Ako5Z?~462q2D*BBey)BB1Gi z4|vGEJtlnI^S^2Vg2X7ZjfPMN&LW5+^$D%_sfElnbb~<-OO18bn2H3#Rna4NiXbNa zpaKIaKynch-OU+UU~@qZeMj#zc%;tgV$Xa;-$4Nt*G&Sc26E!(J12k?N8j}qplElR zr|mPT=^k>qOilz9vy?!Ki>e}rqMc{?YWtBHYWbY&%6Q<5UeT11g$PWGsZh`qk`|iP zq7~d=YwK1NAIJ_y4nlnDHdf~C-j16YsTf-MOU6abg$nI!pE#I5bR?nfIaN(_En29v zvC(WE9#RcK)?9-{*f`AV7A-C{g#g#q7J7jJMgz1F?QW_DQVFDsJdvT)G2|TSO*Y}5 z#Z}I6dPIurxv19@_~5U*@1ijMa>C^kFEm`7hT)EkGq6@5Cm?;~qU*sR_W0QP7GF)P z2i&;@U868q$$A8J1P|p3Wc~cztcfOYoIj>ON9g1$^XE{T_13wqkF95 zt>>nYD11~Wxv3v<@a$kw5Uu>2GN;XHQ?yC!ySZlGAhC0J-M%(0BYf!`syCSm=n&Uy zlwe>d2qQ=2l|dqWnvOfoYh#hT#qs{Nux|f&fA7n^PPq}P$O*&qu4XAW#MDA}46(a7 zX~4y?a2IvU=T<2J1;q40EuENT5c5SaU3PB*MO_m?Td~tw6p;K~(dyEx{=w-*{?3Fy zJ^TfWkcSA*Auf`GUlV`Fav$9gK7$xRYY8>;c;Gz9bQi;>A%eDU$sJiF0RZ;rS0v$%F zL_kHo*rbXHG@lb-vPW*;=gdICFuDFXQi%K40&TiH+5Z7~#Hrz^}rH*-L)+M@tt6B4?s)R1YDCP9K+QuJ6Y|@_se6E)rp| zTBzNaa8z>#{?ekeuoKppZQf3V&$eqTFGf4fLx#{r-t4s##uE)Dl0yZ~H6FDInEaul z#sDLm&_4u?KF?#CK+s_`p?<`o6BF#Xb9gKOI&SYBAD^O0PB2pY>U^pp_UXF`z`~NP zpw;k^ETvA@Jph5~DN879lwo!u%8o+@-GLBjKn)}S>M4JE<*h-vr|L()?)(jZJ-kBy z@GnmO+~84I2Y!m{_#P|f7SS`%pj1pEI8nG)cdexs3r#CNFQ}rR&{y5E z6Ij3k>13xmoHFv%;FdgHmWQ%m-sLe45~8f|PPfASthy(65~D=SU_QTk*RM52HML4W!K6cFAG0FrkQOl7HoWPNwnxu$o^ zD^y4LMIzm~rU2S?L}}zESbguPGsz|OkX*hurNkFRG!^9sA1Qj2qqxpVp&Ocr`IhT+ z3lT%4P@`xN67GDbcA4e}%GZsiaP^>W@9OswIvwVed^F1`kTi=SHj%)uoPY|_OZ5{H z5qr6L%#c4x5%irizI0n5^qtc~z|ZfB^jk#}Jo!hTT=E;$Jk-$9 zM>tX%*+lX%uo<%n2F)X;_OZt`H{s(T+0#1d#zu#0tX76EetcvxEC7hs(>3XHsBRyc zP1pKB^h;G)({y$h+|TVj-IQYvW$&RWo@*dTc7a!L1o0jKYPX?)+WT@jJVH`u!{rHT zPYiQ3M;!l#Mtg=F+{&VHD21XanqPIx-o?y1@eH0pS|Qql4O9a0*`o-KpTU+oo$c_ic)q0^7CP;Zqt4gK7+6viY5@ISLDW6-am>_*r+FsJ=(a zFkofAoNG0_nxu#K_6S@$K+WMH;Bwurb_6?zL=EC#+`>wplPh-)OVS@8r@mNkqnwitRY59H?adYJNuC|4Ix47%tg0TYap z2iI&F!Kj{DT?(Ghd1JYcUp|Lb!c;Q(`(0;xz5G$&53HwZh4@%gv7kZ#n`^i1NxE#5 zB9Db0TPv!3R#r52?vOR05?Zr2G-gqQ(4)gmKw(A2#^9DZUHB}73}6Bb0T`r^?7bzT z=kD&&UFZ^dp=|DAuh2#ibN4Y0#6cQcCY1mvzDSvaH|0mYbxT1c^!XE9Kz~@_nZJ8P z1!mS4KYAH5>uy=LcWpQRDPT8&s^w(hKbP~{6R;*CmHvOy-siQkG|l%s$1ubtj#pPG zuTe@z8W5chvL+~X-ng6;*c5Fcu+M5rhHyX>X`IHvY3wMHgb;?q4a)SQG9eiP>Mk76 z2?ZA>4cP;Ay{KN)re_u!$ekCph(-J@^M1e2^StkSBssGBjwDM*KP)>UQ=j-g-{;rD zxKl{%wUDP;i<#2LADk~#3!U2|t#cacGfDof3L%dn&HN8hFx1hjIjrdy z&R&v1ax=B*XR62;m7P5`()8MbpL@hmTL5&T9j+&+WjvADA17O%yhVExdJOs}5n*^a z@sv4Pj>JyZg=Qz7L582kK*tjR==#BilpWsi8v=*O%zHw(}*ary0Y8fU`*Am&|UpXg62%bC>=9JAFUeXfkfcXtx z6Fp83%?uOr&%a6lkuhnFpd>Y4B;E9PQmP+=k7x_kKJMc=NfkVae>)Kvh`02^tjZ=~ z@RetiB-LX^UJgSJQBEB3D1`!Y(Up5yPO{+85eE(7ie_3>i+`i;Q)+(&^|{1l$)fTKXq7^XmU%zQqL#nI zmn`DI>)ZmcbJagg?WsT1l008)(OTsYU2ZFyruLx$REPoOge~(D)?N$2L)x$|Be#w> zCMp)ewMNB!sBl~iobaJ+Dlkl1Buqi2gCE!GM2aW!eTF{O6*Lc~di;J3cc6F-K~~ev zTwlj`mF)C(o_fMO?b)H6S0FSw@lE!})>7tx(VyBvs<-{7ra5U|#hXSxG(9ck(6%BM z+U_TB37}Iko>85AdFOLil0pY#+zE-VQ&I=0L9DfZcSnS{u*$_!WDJh?w@mH1GVc{LsnhvV580GhdT zm8I^;eS9gCT)c!2p+f`=TYe6qQsmH|;k2ZhQlbf+NL!UVmhZs4Ocgle%h$2!6oT@}g zO%hc;=|n6b3LpR|0e{>JX*)Se;ZNYS6+^IDE^#XiZx9GpRI7FF4)ett07dW-t#hLs zS}1?j?>s7Qk6|Qr z@42(|Wb1#5U|6P%y1duO$BvV?2#A3XNGWxv{=l3w8h9-A@&w_v`8FuCI z<1fqoBNmrkb%39q`|?8Q>5}egU}ysH^pC?*Mj=uEfi-Y<`!Qjf_&MoE?D@F?jts%J z3_8*7MR&(3pw}Chl6AkM3FK{KHEvkNLkGtp=wSa4Rt~VUjYG;BM-i$S!OZqyjGJw} z+Lq_=_~GHjS93(ZL3G^k%Voy&R*mSo_B3XOAl7ABzv>TDTw^r>rk8N#eg zVx5eklFAMsDwS9ZXZOJ>Gopsn&bbTcd}c6enHjxkfl2yW8rF^XFG3_HMl^jOj?T^!a8 z>(sU+Qd5oOk<-7QJ|~T-`r7OfoM`U|IRIV%;Zo9GP(VjkxU+kQ>Oq)2?&g3%GJPWv z)g7R7prAQCBy-4}!)-g1gK$?KG5{U&h1)xVpS+^XfuLz|@Ge4bnl~+)FMO;9PEbh0 zVVMKIzQ&XKm3Zh>3LthfAPQm|&m^r!wWuDYPKxOY#tOMV<_RFeApqna)*HM9K7bAW z^zeC&A+*e+L|%YTb21tw;pvIuY!W}vILVJo{JR=N^nKk^6NS;HyfB-QK)}m{WU(8v zW=Dv&<9_U9Qp$tMsho03-W%;-@@roN08s(q?I@x6LVPEj?sMAn6R9I&E-wQWP=VwG zE05PlVGFf>7WT-E-i9De9p{-E&#jr+Lamt;UCtz17QN+CuZgzf&{{(Sk!rA*b`P^Kv@kGK$7c+rtyfOIW+J10)U@8 z1?>1hi<3L9^mZBs3psY3fjtbp!c{DX+TI+30y^pA+~+kF&@qwJ)rFk5(>^Tfe$1d) z^faD0K5jf6!ADDiwj%xGYo|Yj0($%U-!@sY?4W~E#9g1lI@Pd?Uk764i0q-PdA4t% zl~X<2r=Bo}1|B04801f<+XA4MxWO|$flI{+;Df5JSZx6!F$s}ZOp8l(D!@`v;S8)g zV?ezl6MB&%LW=@x{c4h^uFI?*jV_X`WCVqfMfs!LL3gvzrxg9;@x#M%%%{f!ptYx7 z>Ja3vf?-fstoWwMhHP40F?0HyL9D}Nk-L@xy%9Bxv-;D{_9L-V`t&N4uhV2v^1DT)D+JFK=R%&kJi6DXI9i3Pd`Kd`GEX7bCUeT}%<%$du^4`n;q90-GcR!x^>5xG6LSQ)|clOUejrFsP-0OM&iWUG6 zY91@;Pg~rBhvjJLCYDK+u!|Y4g__Kgf1kzmhl)1UPV|%(ae1SNpCVE}Z0z%t2?G)g zL+9D@%8|hh#y1uZ3yc>kbO3LGp=XXF8;(v>OiS1(+zno89n8{M7z&&NeCGE^o~aGy z@LlnS8STReBc-pbB$}~U=Xjo;wt*W4VX@)!)G42KuiZ4En_FS2egGjGn2sb^UjTC) zt(88ODv0fr9f*(ci&cvg}BY`f0zm;w3L6bAdEMIS~tZB zrvy0*J}ylaU=fD3*R^{H_K;Q!Vw}z6i_gUcqVJ3Apo2;ayLiea4%3I+4Vkl~fJUPj z62Q->mneLCkq+vq1i}}hF9#r8|NB%=13*<(hG%*q7?UV%A{lie2zm$Zvkdn0^l-mC ze??HoVF!IEuugrPs^P zMjdA8Z^eH5dlk_2_3PVn6c;+`93DN}X9*8zbZUt$GkW%c9j}1)54XL$?6|b=A#=Ac z@z=JGz)ph(0@fUQ?!cdy`?$N~JGI>ZEJ&ui|9os%2U`Znx>u5X$Fi7(B+M4NpBwk8 z7kJ!3%+YA}LL#u5l^ej&089dbE*?w44KX_d4rxA9{y_HRNQG79c*fV{ z!`Zmu>PV2{Q7}qAh!s4Cm(T)A{(l5vrTb);tB{hyor%7H;SclcAP~li=H75dkR>75 z$mt>>N{?|UaYH(Z0_sKlp#tJ8u2TOv69TA2hq$=ju*s{;g@bv^DWCy=2NxaYE!p7L zl1%wJ1ynTLns{2#tQy2Gwlw?CL|jq3hk8G)mV{p>fI2!`KN{+d&5j!z%@s$1K#RF- zku5ebaDRTYp_^+5#ZTbHd}CvdiM>t%-5?+o2b za4p3jE>B?r9qhl}a61Z=&W7zRsN|&HkaKzqT71NZ#O%dHB1R z?gZI%x4&0J1fmZ9YoUk%e<~{pawy^4W_ikP0jXMM`7n`>a%dC>WrG(rg88~eE%XJx z>Pl)1`7d=gVGayguuKdfE`EaC0eYZ+hKRcIaYdPgd+x>fE^~dG1V~38NQKp!ERz!) z7EOUoG;80qohSFd6Yx^5I@Qv=C4te*5?rE*%50KNO0$8=R6J-{Jrk2fqjZuBfM{5y zqJYw!Kp=QPy<8L!BT>HHjDwR2AS$2~sWj99Kmj2HOPm7IuGf~RphY9}DjHuRh2jRW zMK)OC%j|>PDH``f%YD&|y|A-7?0!67!A;||!5UcXxbAj->S9K(1JJ@&N;=-iw%GY} z>Ja5#_zwFZ8G%i^h0M#R?cA|t9x`7_FUlY6It$j1F({Tn(gcsou^(K|3DW&(q=AlG zrvWriz37S2V}aPyNxTBcjx`BJ3&`WA?>Ce+Fch=Mn??ObX|<2SEbfYLPNWi=OL4L` ziYoy^pvb)nGhdJ;^OQ9DY zCk2W!FgT`VF*(Z)XB^?f?ykXLriF;rxsTgl)O;DwgBPqp9Ekj>>(4K+&;c{mA9J2d z=Hw1P_$BIeN{XN?GIuD3auq~*T8@VjrXeMdkGK+uNv)dvAWFm$COS%w5Wbw9Q)%s9 zoQ~Y}h;@mNlQa|!#nnT6uWb2|NerOzY>gW(Je<(jA&5Yn@M{UCfDG}F^*JAx^nls{c!*8?oLwf2cmp%xkLO#!0aFH@AJNjp8dOhgl7BT65v9S zB+$8|Hc}SdZJS@MAsAvX7)|@91CN^)$x~rHmsC8X0F@(C2N;_A0(UnCvkk9*7PE?V z&v?~r5lt48elJE}fDg_WwRBlb=mqgJD3w6|176YI+=7a;QAZpeV@$IYeY)v|@4uVX;v*aKt zc0iyKl|DHjmY6Y=$RWZ*{icx|jv8sO-b`LDQi`PzoQ=a8BmV9Hd@|8GY=@u$2c*$6 z9^|uo^h@x6xU2&;gL9kFK>!u&Olz+8(C?OGo1R!`;)_#VTVnpixi2R~3a@lF&iy{g z!D3+BUj5Q+cP_B&aJu;W8kU==`41|3gL z0d=i35zIN+V#0na+Sl5*po<5`TcN0W$phN*{8>tc5k|>dAnzUkEIQ`=^(38i>s4h85DuoKl zC*9MB7DF%2uf=GaO1n3v@wLFUdaTBRI_qV3KHE* zFGhS)wbEocqMGPC$n%-JQY|1=K$GTo-4_5RNhmLZwqsycA~)u!Gt=Cd97^t8((iJJ zn*g9Rk55<>$`EYAtlLD&63Z+}$s=jMceEErs+Ds(qkC)#KJ%zSRVU>a+P~#PuwqTh zY#uK2mMk4A=6YMm)*(JVk9YZ~5?Mr6v)?kkh_>5Ct8TGob^g=4V&l(0$;#EvgU-#y z%?)4h!{CP-QmNRuk@e8UqWe>)xaoFfp*?n+!2+7A@|oM>pswnnsa(%JemZOL69%!` z0J7t$g6P;!MT7-HTOK;mQGcBY zv=s`0!cZVZQu0>TlK#M%@pl|o$O0fBJXGAZee+ z+jjuYojeTm+!0pn1jE-h>Zsd06Zii|i|}X_9Gvk&+P=;!Zv(M0W5D>zJutKGFA2~H zq8Sb8ssgKU!SEeXKu@TFPy|>@5GEAKN|h;^i!bH#S(d3UMZ{65^+6Rvl}V~S8;Mj6 zdwP}FUlZ3i2C|fK!L)mkmKP^#fQJ&uh$x{XaK(cbQ)-1X9|n-tGnSReCjpR)$;K7_ z%!yPgCX${r^3Yk2J)mS3@B{QP)5cMOkV1Grlp^nvLh~5!N#N(C>o{r_u-0!}{LIT4LR&9F%>G>R~E%0T^ zZHe6b{L}PZ7rJQS=z|w6-Z3ca&fhsL^RDXv4RTFQTt4ZbKDHUZgdXL)Mv)T3Oeaa zB#)X_p9s{qmwi_(!A&yluqu3Mi<2<8B^af$YKOhtUeIfrQe0)p;@L^z2j zeJF|tO{bvD9l9{~@vvYDI%i+{Nt59l|AEJSmYk5lsfc)Q~@z@7b>Bf3Mkj@eYw;}GYglo1K&M9qYI7h zj0OFl^E{JL)s>X=MAostD(2F*W%1P)`&s*(_ubs2|v_4SLXB_`z7*`0+KIT zTG-)`?c3JitbJb(yuZ`VgX)Q*ur9~ount;e&#^{dEK(E_na#7}Mz0nD`Cg2Z#$pX$ z2>q#K!QNiqZgL7x8?hA8vwJ7=dk*gOq>1 z8d(P%fOleTjCdXLD5gGqvXZw(UMsd zE}o0^Blr;slq?OyaP%qDh(e`$Kh_ZTO3M*n;kX<}?HX~!ghIsS551?+tLWNpnvJXO z>hVP{vY#42w6|j_y!i%FAh`}$z0rLINF)2bdl7)d$d+IVsVqif;SV(OyR!HD5KK7v?yN<^hN{WDzcv5CXA9A>}}v?t4SqN8mz*L!SrH zmyG>eP)G0PR6s=+d!Z%#>csn_DTlO8qw9_7EAJs(HO&`|M^4Y?ClPuAgXS{e_@Ab&GkS^q1lSzqAnR%CmF7Vc59G6m9=i!(?WBxsO;W4e-IPDPI9DucUtY74*-49lvsqzv`8^edW$QzC>8?if2I( z??yOymHHQjYY)1phbwKGKxO!Le;1yT*h*=TUJ@RL&i$x0l z4n3f`#c1X=`^=Xw^J%Htv2}(^-ZLXGlRy5vkS_-x3&`-m4XS(|qRXNfpt^@1&$RQ- zIP}g*Ab{$o=q~6{ck~%|K?Z(`CHD?Ttc(r>LjIo~P)iCSJ6aLsFVc3=oi?K|@tvTRS0NS$B#DF26k?&hi zhEK;g>ZMPb0*E*9hOz%ehXK(8k|nISE(qhqu{+w(qzy}fyaTPC4r-po&5{1EeW`&y zJhaw#={VgEz3}!x=tl*7&_k3=W`jvgB-b}$!lbvlK3+%^eOq#?-4D)&wm@2Jpk#|xO|1)1P7T? zsN+d6>eWtL^a43v#SQflcFGXuu>k~yKxy4`ze$oVza)sEGEDg>qt;pEz{ZuRm(r6D zM=Eqy+hh~UsNPZtmWNb6mRzN|d)G25?jGqxM1UxGKx2um1VL7aNFl_Q`bma@M^!-L zJkRi7M+lS;{4n_?0>xfX(K3xAP4Zb*$#ZivenjjHb;=KyUlhZZp$Dhdd^PjV^ZI_uXZRDxZx-xBG{|;Lps0IRHH%8m2$NTt*7aNuUKIFyRv!)WQ66);YO_ zV(Q_()CX!4n97$RV^IF1Z~=30AKmY4fe)~W?uE9Da60@?FAx9Ip?v=-UYp7arcCB= zV6-qB+NHsiSmDZUDxG{F&&s9(-DsiR@*J5;06j(m8S*Es_0wF#RK2(u`Ooev(Jv4< zJ$}7{>iKU@VSqmAE8&mCVrANZiG$h5CVMQ!QDrQ73`LUfml0+)%XUVOle*LqXr-j~ zOR104cau`1x)GUiK#@aG#2zn!?hC<^Uc-e}?p8jwbi^nnw-$Rq;$4qu2E`uGOwVAB zWV>Y0P|hAyG{b{D;sMFL#dFO0XS@7NrfIODB3r32^m%pPKL(>W z`OGRaoCu-PE0H}t-bkzk)dRJI2h;(2WfMDMQIqsodAL@*_;W@)WqQfrK9NCCWwrZ7 zGV9Bq$V-e>nQEm}>ZQwx<@3woY|H}f73bQL_T?&oMhy>1Uyw)gsbsw+02CCEyq$E7 zgb-|Iz@f_{(x(zNl(7##V~eU}-s$|b5S(QLAAIQ;`PpJg0$FNHbMTgvudrcNpfnFc zX>JL3FM;M-a5z*GsOkUU^X^-}&Mnt9PzkgU-GfC3bcc#Ay=td`iXUElKL1JaLl8-| za=~xJwgfPMg+hqK=5T!$Xc+7AQ0(Wq3L(8WXKA+I)~az>S6esW08N?0cQGHrJvD-? z2FUs@ur|CKZ6%c3D|3tR#Qc1govj}UeY(>+?nlh&M?$E3BQ*-viW zKiJX7{k2odK4m~gD;m)GZL}dn3lZO9582Hg!J~u1PL~2FPn`>Q{hUYc=J4>JPsx^3 zQ0Mu+uok zmUIkRS&44q+R931lz~5(x5_bNwLn14mr*Tt24gUZn1Gp{phu&y68Q0Uv_4G!G=e3D zbmW^DO86ILIxlYBK*4SSe;=U$5L;-G^LIr1vFFHGxOy@GmFS3$%IZ2l+L-|pToYe z#H$~_Sa6nR_xF(oNn{Gh57jUcH0M%yCxC`d2+6P?U-{F(kBsgiTh2rAq2%Aa9AZf3 zXwt$hipcc6Kgb%h7>pV;(1{mH2u^|F!gLY>f@ulNZ?KUm-bG!*VFx`c$;&!&ek z1g+4`KoW>`{gmmcy3*4|4A%Ew{rHOf>3c6a+#Ul!9k8(|21{0STSKtyon+Vgaavzc zHkX}y3$uWh6i_6DVmL)Pvg2q*>q&DkSz{>B$)~;!=&gvL+qZ8AJ6_qWJDpO;96G!R zHlTfYfBQK-AORM~05u#TGldT2i;j^_BXfYl0~1~Sroora8bjE{_>2BDydZhbed%ik zd=}3zBFjmp8mn?kZ1g4>YQ_->A~5%l`4fr371z2(2Tn@R_Djh8%OgN){HIYtx%_Ebk#oX<{=SJDHK&h_stga+=wcIXidXzU(h9Q#e<+N z1Zz)BOGUnt-F9{TOm`i8A~V_^I9};Pjb|vHEKf%aMzr`qP62&m1j0W0O;JEP)p?t0 zMZ^sCjYM2B;*b!570uDkhm!Ylmy2ybiOkN_ITw6TzAz5R6xKej(uM6R#d6Y_ZZ5SJ z3p1aQ8M7U6@|>R=t?MgmGlv|0ID4bUI7Aizan1QCc>))xY{p8jB+bs@he9M7P!{ng z;3vayS24B|4)!2@&}>mEV#>fQPJtCh)$&v(HW1x$zJ9{4w5*n&p-Kor9(?o~urs?k zOY`A)HuMUpfgv67QT|MUkT;`OBoP!)R6Z?Rc~GvD#3Nay{zu&(!w&*y=sS+4Z!BG9 zAF2R|bL9j??iE-#eSYtNGB1S|*=D_n<1@V~eDg+Q=AkbSlEKf#T)pSahO7n(q2L4c zJj{MMJtTvDVEeeE#lwf$3rzi4ph_8*&YbbloE;W0hXAT#-ffXGT}gN0098Ig_Si2` zbV4l1JbV$Bvv#dSu_F;!Xp8riKv$kXF?O0n>T7)vv+*}Y@o)Gorqi=!1>|^iTESDA zzQgsq_`UE}-Gwar?Dp?HZCT&gmLbRzVpk+531sz%;{V8iAoPO0`NcQal81kL zdp$TimGsv3sX5SW{0iu}I8?23dclcer-y8hzmV~Wr~BK?v?EKl&Dk5;#)>EKuzV{k zf#NYA*+Qy)2Gt8K2=dF5Wi`NG&C5M&O$sP(7|@ zp%sIh#&SuzLjl2qM(^G-6T>WoP!W<6k$4I^)f%JTH?tagG zj75wl8U`)Hy1~0s?YKC6$*N{F#iRLxwAr?z#nVs>ed@bfPwg>ugXwq=7B8k)Ejury zt4kMvEu_Co8@>jM!9z|15*l#~qM<5dcSg=4#7t+@GgK>eH2sKG(RJ+v(BmiK0{P6i zCr~qcuGKb1q_VacNmLLCg3)Gb++-vU^o*B4-rq^B0Znd7NrZ7^1}bqf)<&B8F*h2K zBaEg}UMBFUXaS9@Rj;Ra-=NoKem;a?O8{~~SQ*t4SvCxone?NI0@4ELisFYtNYi0# zx|sPn9AftHf~6aqrhGE7ez4yeJMYh90Ig#YX1Xr!^NHpyD@-gz4GpymRX4(8;qp0L z!-u#ShO*4o?NkfKYGMdWJ{z`4?}UZCc_wlb>?wOOluDt=8ar+UF_Et^q49_HohHY z-zk80T78c+M<4lSxpfg36yeRr&AeG1^m7 z?PLZ1s*9GN&KsR((rY@9sbhl~S}tbnN*!=i2Rb%nTMv50YG@(v3JHKNMk0Zd#C?wb z_~ar9UUA5omuZwmN5jKX;!A@q*gj^&G%ek#=T&B%JAOp>4?Lho>01Drl`FwmMldmQ;c4Dv;=rJpy zXPAH})zDR5SyKj&B>|tyFnWUz5?}b!CYgHAgG^WL^sBTDddWsi0y z4mhXn(>AVnaC$j=r@E>G^@CWu^UUWs9>gWRfuFs%j?p+DD#3en0!Zsd`=%v2mHj?%!XQf;8x-dW|B zB<*cX5fH%FuzpBch%)HeQ0jn6tHXXJ-K&WJ=#@9tUs=ycZzTjP%Vi|VzL1r5LL*sZ zrV41towB|g%p-`sV5)%fSpKl;87mm6btDGkV6s_;-PK9D@Z6cTC{`p+%8fFEBugRy z&F+VhjRcxE&xOv7#sVG=SJ3~L*v32~VTQ6RjF~C-FWH6@D1*=IdZSf%+Xfpj)V`5* z8X4A2JGji66^{+GS((*pbz~$OmLTGXz=SS3^P*`$`}j-7lTDRFuyj_(0>!zpP^xIb z+3}U&36a@xXO^A2|4ipRf19HxSh+J5{bM)pc)lTiFj~Kvq5rT9I+niGW3PbvaR_!C z6-7r&QgukH1JIjad?yMBi7<3z>>sfqbypfv@4V#E-Y_r((-ZGrK0vPF)yk%+ zdpwEmd<4c04$(n}FBMaiNNp#9ZWi56u_S$L`09XTfhr%F$?U@#kD@_iVakWAQdI$= zbO?DfcA>f(?znma0$q%1l{0C%QoIux&`~|f%KJ`1Yz|g zD{FO!vIv6IMM&#I0mYTl)lgO@rm_8FoIz#w+HTZ!J^GClekp?-SGzf6GcyzfNB36iA%2@;R8#f}ug0C72A|(k2XM!dh4`U2kTFD!@fs_Sn5QFeuf@X0DK` z2D8QN!={nRAufY&g}m8(ZuN;ne(_%Gypmmo*pDjC(ePpYuyR}&B%jvc19 z#ou!9nJOgrg#nS60ua%sijD^_9uAZ{x*z_Wa}aeFG`aIo7dAT)o#lfpmkQ~e<%rUc zdI3NBk3i7lWJU9&@zHoz`g?WSFqSo$CHSfRYWYa*_`ABvStg))DO5@>p3C1guFHaz zBuRcXoW*5IZD=gPIAa<csbo0<(^al4U*JgAI^%3< zgODZVb8cp41!BwVAH70tdQxXT{XURY$`hDCRZBAQxO$k_7!?=qB`S@obW_4K2eL_4 zEo}Yr>}Th*&O^#fPD7sE-Qk>BvKIOXQAEUIq9GAf;NLIo{(_{IWEyjEh5KL2iJjr1 zC6(4im2pW}OLuLs{&C3A%HI>%5I5xB(0bHbf-$;6u>|Ty`!T|Xp84Dt1ua3S(-1`c zXg0m}W!TL6<~EH`W+bX-8jGMCv48*|y3^BUpT_jVb`Tk4tr~t^hHP?fE}7T%R8c@* z{0JLb%AwJbaeKMHzmM&x91GNz$g6#4NaCdp4Rm*SB;D`?4s}r5w)yD%4vV=C+#|lN zj9*7DpG7mL+dDgZi+fLl!HX9jOEZhhFeIA8pd~?H(_2I~OdV*M7n;@D8is6+``4WL z9Bz21*Y|8mr&Jl6ELNpl27Mz6CSW+EOQkZi5bO5u-QRYoH8 zz2~9Or{!5hy9e2M@qXkbvvc>@c}rf$7bac-VSH{TrjYlHW-XXZ=cq2?zWBd&PBbP6 z&4<3#6_oG>H#X1>3p}LH&4<~;WZ=FhqXeUmjTLoBnN{j|;~~eKtRisaH7cLre-l5# zAfkv0Xz1^-R)Df;SlD*@P85VKZ6;J#$WMxnnlw7`a-M0l9>Zjig=beWuk7kw7<;dE zM)I1Q4Y7c3=6%{i?|4}%xL$`I4a97A;&EeSP%|M<{G5EM3wyQ@f{)j>#0r)3RBhSpC8Vltf!AEtVxyTX5LIq*WV zVv?{jlPGJ-oVr|3nn0q6NE0aq@+tdFT_BC_I9DfF(n1L~ZVTdxss}8>na5J2grAG_ z99}l$>!^U}fOiVNFKpe`uz3umAcle@T8Ym3UIz7J;nRt?Zuk^i_~v&Oftdv)3MkYW zt(#xAx>w8sF)L8?R`f}{r!WlYfC>HMn~%T0ww8?Rw}03>*uQIw1|m(`cL#!zwt#0> zDfH|JWI3Ytxx*w^-Q_IbWH4%*WfV+kOf6#!b|4!Mp@7mtxzo~iIGtLzE-NP2P8ZeK zk|8S$2hzSes1Sp(Zkmnp?$G^{T_>Z*+M4?K;tBsbPt}+SGRQ9ZIO;tm2bvy_6&2QN z;NxShh8!wQ>SU!q@Fo&lNAgPdl-a=8TE?RZFYyAOp<&2?B$q;NK*kv#Dl|NE z=X3WzjJp}ISfE-sI$^DACW*6(?*dq%nYJbQeuQ*|*ILw3YWrwafc!j0XkgNi{uD_C zPY5Y8B*Z#a4bY6kybfyYYmURQ_$KTq?CbW_t7%jJMBg2g%rsCTLm~x0ls@mGVx#^i z{YLw0Jj|Y&CsalYh18ZlUb8a(wg7c6TGPif( zL$B642+;&G2~=}fE4DKabXmOAMXOp#X+%3sF+w;2CpukXPx#c9br?QY+lGsnC=MNY z!}W;>wERGHn1)0cH?)cbq8pA`)G{kyQ*O2Pf~7wEOUp`B%fszO}Q;i``n4ti_bHARtu}$H|N!PE+LqGwY(TI(_0`kTtd+>=F^a98n*Ho z0HoycYRO^H9XZxiX!k)kS~gPv=?IY_^vnzZBH&a{iCLuWX*MZM-y5;o(7mu|Nvx*I z36Wc8*b({E60fM!@nc%o>}+lvPMak0YYVSzZK3Qfyqd-qk_;SbtUdG~a$(tx)`c&+ zQH5fE`iTp~+&N;VI`0R8ypi)-!3!1e7O`9lPeLXHsa z%gfU?=5=6bv?B?gJdzmf2x>>dHd`sLuh6qxiJye80}zP-!pqxKK$oeb&%8TF9l5l_ zu|Qr_QHytr28tMiaYVfiYn2*k1Y`KuO6;FZ%{|x>ssI2W07*naROmcM7EHZpae!`QD{Ho!;m0P4 zZjP2>?3|lh=>bJDCssg9u~r~x1SP+QDDxp0x5UN^G;CpzEmHja0_HvRSR$*+NE`mS z{mleYXka{0Dlm3RtsB+dCJsVm3hg3*$7-iP=Kzw=^(SiNRT+TJtNfe^e+>ID1kHlp zS{RAURdSSxT3bkWmD6ZU)kt0t=|m@}PI5kX9+e6uQrd*3S5TKfd&rR`r}L1!JOs-n{wKk8j?5 z^ZNQbb%Cz0H`)j7UG8=IiV&?Vi<>{ca3|T2W;iOAbr6P1y%^{cXWbbO6G$d?WR>tI z=Vt`P%bW(}K1sBJ{&;bb*vB+$&JnZNt7HzUmXR1fAK`j9`?|(8-C&;Sq-HZby%&8o0jp3Nn^g^O7cA(4n6VC z54TyE?=$hs%#y63fDpA_AeO?fEC{0RDXWRs2PJ~B)~uO_hgiU*4vqvO*Ak2es=va~}74EM}3KYDJgGiy9h@hWK@cGvNj{*E_lm zTOs~(mzgM_S;d`lHH4DmW5z#ohCosSInLG}hRBXzvzfi!Ty&4%Xvms?`LN}&BZ|n5 zO+w8(%+7lRt=lC(T?JBbbR2>@qJgeD(HiG4;H(oaEUxan^Hq=U@Phe`PKLa(&?^=~ zpJ?dy$-M{)-5H!)e;iG1jeEmB^+ph?qu~KL4fMrdzI*L$=(o2&TtWfuws&2y1n%tZ z?SVmOduQ$aXHEiLf;>S1fmQo=2(fm3YVG^8dmG1Zf3?(ThEHdeV{E%ser8K3~`)J zFiJCDt)%*AhGN8}wo|UL;Ec2t{bO7S2bR;vwlUd{T2I&x8x)YkP-5#26Wt=@{=%3A zs|gYEhX=T^6Q(tJ9ter>2~G_**=D+_+ofB~nrRG{b7XX&kNdLkKp*Q&${a)e5$cU* z`RoIyR`hFlBo2i~#1Tap-g*c?4Miw9Y`7>LH#sZlVF#hQfb3zAS!sBeO9&Qu+xo$y1Gh44sxa6?c>-5?w(bc&9S>yQjtbDMlK3R}vUP5tfFm5L&{ZMaB6q$PUc zs=Ls}+^%BB=ixOa_U`^nd^9g8SU}CisavaVw0S@-26GDN`n9@1*RrJt@Np-CXAfUz z4n#Ybk6wPc53KCoJ=zCf5PQJ{Laop)mW%CrqespNPz0X=*9?Cwae(?wHCZZu!&=O)`HhA&y#lVEnpdLtnMvlSt97vxJWQHPoFwhcT z0}`MRSE6D@;suwaA_RMUF_M4pP4#HggUu&QZHj6lR*ef;Y6-5Oanf2fP32`!$%lnJ zX~0iHui4xqnM+3hh%Z7nJch#O{JGc{BqM?J)9;B=$uPtj`r*q)gQ_-1P(bn=3MeUnxCm^b8>BfAI-B4lJsiqsT87aZ zO=jfXriNhbP@PEwJrz)52tvhZZJV93#g(tI1!Qp(EYJV$)6jmMvTAu=LH@woq3m%A z2hm^!NtBV12qW>wQ`J+M7&7U^2WKIgGbv;*K_(2@w&Bq7ZiNV;0!EO#?Fft97ln}C zxRc7F`4WProfWIPW8++}O!HiImW}5q5}Ssudu32p`E%3pBR}4W7ahFkcgV|sqIzgu z9gyztIq64JTUS$Ia;yr-@#n`MzxfU^*mr6Ly}#Z(fO-+`Q2)r6lR%HYbV1lISmQ*G zyQM4bA~qB!3T$@C8^TDq0|_MfA#mtc!-a!IH%K zVJL-09|l)sa5BevW#!K~{hu6&sG?R0(1F7x)P^1(cLwM(=EG1Oligew!;_k!bm*duQ~}(F59)Fl>UU_Oj+0e}+1f z@G1jtGrVVwDhN=>{j!spS3qfI3TQ&KaBRIQpfrSFWY&y)ip$Yr}jiM7^MEp3( zGnA^JA@tAC7YGeI_vY!FlF0DWnMxqGls=1j^v>57DUFH&bMT9mUDw5bV2aO@?t<{O&Hb&khZsy@Uul+c|jj^5_|s z7q*EUG;WYPlBO5exh>a%9DPL2fDNjs+t{p%K^#wUdCFSovrJu{)=K8RT7=DDtbWGi z4z`~n>yEi)Gz;@gXG=qii0z{IkvbkkS2bq*i4E;%la*;>J&!D7wnS0w`H@;Eg~}pe zNyZMv_0aL9WH^>we2$H*S=?VcB`a$YS4LhC=-En><4$rW;Si3LRZlOvHpTb zu$X6Z!?B11or%clteI3j=Nb!1i#hCEoF4SklVX-n9A%o;KE-D*^ z(8zODb+h@s2_b1(eT?xRf*cpcMR?NgRw}DpteGloE2~l0lL!mN{~1an#!x3BmT{?) z-(%?A=80{nPc@Vi3`z3KoOLmQGSNLraG}{RJE^?_k}Md#p$Y4nW%7uhUdJ0mQsW})se1Z2a8*KJ=d!;nO0xavq~ z)=^0$-jGCN!;bpYA4<{F015`rRVZL=loWXqy$fa4b0onWfC_C=^%Uw)--V{I`#qr8 z_&JG}#>cCAVkhWRQ9xfX1pE5UH%|P#W*~;sH?PljF0oPiZ0G5=0}t0r<8FKV?+y>2 zVQzh!AUVYn!c#%c_9@2NAK+omw-?1@BIl{W=G4z!+}0^W?$UeOdsrD#xO{_<4g6 zBCw0cNv#oA77dB!S!X~?vxf>WK@n%(OD_foA?leRDwnH$N}V5H3wWAMrHlc+)XCC3 z73}cWaO|ix?G8|cELg@5zXIrjV@xi@s&=HBV19$+$dP6cGP%xOTPF0wf=YRR*9~4Bf|}@zQ;#fL46#T-+xF zVNNR|AC?iytYu13woPW`)hsHo9x{L%YAUW8`kdMfH%$BsU|K7ea4SM+DB=gE5XI2Y z11PvcYx84~D=l=n67H;LRmk553mO2D2(0g!!&=0ZsB8Mkdi-oHpKVvz@zxp($cJDs zp??Jz=(RgtBNBW4&D-y;|Kg`PKHZL1-S^H;x1D%7eCFi~h8#ZCqto!HU2TU4w&Ow3 zI{My^jDFhd^(L|%%uiX(?NaGX=sc6*^EG8pnd8j5KvJSs4wW)0%;ut&%~d&G0$s2g zF?MZB^=QSW4OPggO%wB%#EKlHBdl8Ai~-jvdHf{d_e??|;>3C`CaJG-mQrWYL+aTe zu@33v{5O(8Ul0xw|~ok&4?rr4V-VoIaPKi#_)Y70{yc zE8khwgSEcQa4mA3{>&?bK8i^i z_*2)K+G5fx3(j*~l?YFy<|nw;?0agnIkdj0Q2-E)3!_9CVSOQnHnRYl9~n)ARn5+> ziA<1I6Q~TI?aU9=-~d=rKoe14i7Yaek{)4>0LnB_rr)W(V1HyKG+qE`mbun5dgIAR z4sLUFoh{t7;4nVAvHocg}G zKFE6o<@3pk{OR|#*e3#zjfReLU?r z`oH3~2Z@4%v);B6$kC%G8!&iF-navPojSbmK<~**w|ja-09jxL1?9fAy_2=*K+mEn zWD5-L)x1}0p%bAOx)sB862@-81g$xPtSsZ2owO|1w48bb34uZZbfk!wp+aGgAN0de ziM7y)2q2{9eMUYmGSrf2E&zLyq`s0`YXGA-Z_RWbKgnn0l)$*skIWeUGcHX96m~Pi z1DZqwRZ|VDBoAk4cC|D@nlH8crhx296cC!|7=k?+Wm-ZFS6sCdmnYiKR0-sW8z~@u zM-Jp9z8I2hIrHe6jA;e!aDB;$SE)nFB;C=bSi_G{@kz{~Pon5c z*>loJdc`KteNh-fu#eyT_%$TZ>+fFU0x#NO=s(_`^>$qFb@p^SD4?@m+v%e1!~YEg z0yl&mjw3x=hCzwb+g7sl6f-?>pr48fy>q(FAkJIW?(wHP?fe!+KPUjYv8&<+3*fXj z3kBO=!cHTS|8z`(wZEQi#Y)%);o-G8M zNZtxrunE&&EceNx*7ty)EL8=R)avzQ%Y#%KTa+6l>LLCbu>pR}h48{2UgvAK??j7D zBLx&fusZlovGNfssGda4s972-AnY`{pa;avm89)U4ad~q7O!a{zelWqRKw)6JgSjzpMEug#8Rk-(DG}JrU-`;vg-=TkW;ryECclO)Zw2uo6ecX0K*0!Ff{;&= zb(Rn$B|`$8;SznW)@SIa%jJraAZtt(>Mm>+;ywKNWa-W)A^P&3j~YI{^!d24BW%?I zk}TL45`_IpTp$ObzrYB3e|>&tF7#76&}Y1N=5GG(*`YgcKc&O09uP?MlqfOJ`Kjc< z03SHkZFh2*d5Y`y)BR`rZS31s-Fbb4(-4g+=A+c#U3Mw%9PCYXy**LX*sFpNV-r zOopik6a)}8(dcv8D)Lwq5MM}(smAR@bNiDdnqh_^iUC0SYnr3OD_Mq^5H1N<0zvM` z^Vma%RYGIh(ptT3e|^4nP5(VJZZJ^72&R!ZjEb1C6kH{iS8PR*@1XWt)I2`88;d=!%8wPDOTuUE4b&8;a zv|^e!5r*cS-w)RrK@pM~O=Q-*A=N_Y+0bdE-G2XPQ(h|rp+m!k-wf7|+AsQB_n#bq zK6WDL$A9?fqyO=z>-VqW0!c!i1j1=&=jqe4GxT8qKB!DQYd?DCPWw)@xYPDN+0t&` z?YGyTPTR_w=!8WY_OL#2aL(O8xAOJ&R<3Tl4?gLVNe)iRpqsx+e;B8BaLG3o^O%+15R_tUGy{(ytx7y}}yAb0fd^7+W z3g}5vtBV=|=v9Osf7>flLI_t}N;+~}D#zHEIL6Ls(1@!Od#i(2M*H6k&K#;*K$A?X|ID1T%G*}CA%WKSf1!rULZvb2|-`q9D3+9cRk^6|&t!-oF) zqmO>|n?Jor9$sY7_517Bw|mlqanNQt^q$j89$ zW_ms+FF=#o?*1e4Dtymr`-cbDZ?C(YigtZ{+kN}Ci!s%=-RT3t4=JQd2)8Y35CenI z7gouD#6ixjVHInl!5_AbB88TE2(cn3!G!vY3+X)1CUu&HtdPl|(gLtFi)aF5eC)-UE+ zUeCNT5Yb~Q(F0#9t<9(-$%0)>Y)FU9Dq0mo8op1%@71-e!TVOlHNG8}@WA&ezMvK!T1sw}P;%4AWFyK98OWD zA?1;Z=~+*dCDCrL46IVxq|zHNo{uoewlPyExeu>H)I=vQuXbvcD<9)X0by}{IhMVx z+#Kz6(5qC~W8oT)O)vE#6Di1}=f}B_ zC}(zFpj0_wGb_v4Otg^Ci;cAdO}gZe1>=Y#{y&kod>JDXk|ub(3#9FDm4sO{i?YN= zQWE6^&1}WHo|*EQtt7=7sj;Q3d}p~$Z(b zK1ZDC|2%P)bdU?dzW@IFkKZ^2^wDRZ{ok+OdjS2#A?WQ7n?R5Q5I_V7?J0>a9~~VX zeR;I+?mMWUasF}_Jz?Mo@N>Bf%>&Y0;?TXzUi;{gAc#!5+}+=I}3dsb=$Lz@R4vs9=Uf8| zY!JbLb|1!`nLw|~{8cVtSWmfQA_%9^a}p>#-qUp$N~d&X+;bzqN&HOcK$FA=c3Rjo zN<(GOPLpXKL;CViBXal`Iw6cQ z0%)9TEfIcvO2aIt_k*)|Lh#TSgN-Z5Cu*O3X7rI8G`fiI;|Mh=^I;_dXc!et+gB@; zRu45ZpL>&9B$0oaJ6Aq`-$al;6h~k!Umk5YbEym(dMBtrcHUYv=F5daS9UGYR>;p^ zH75e$bc{X>i@+#=ruX-|TfvVUZ^iwl$M=h#ljS=n9zY*E0Db?(o3EV$`s|}Wc>rC% zfBpXb>py%;z0*FpbO&J2CIRF?wCf1;=*y!6KANhZz^WmH{zdqtOF zXu4iKpybI#?epCYE92e;%1R(nW@9V~8vC19skzjt*FQaVj7B~#!$(;GmGnd#d3n^s zhq^~H^gN{SX?LG;_re`qk~HY53#}Z#;Co5Hh;3aFm_JogS#5;Zc7C%=q^s%5m-HCn4J5aZv(#gmJ2mXG6eIF#x|ES{Xr zOd4qj1{bw5epRaU+kh|zWQcrk7V>I^ygQ>qTi zJ%{kOX*Q9HAiCCLrobj(4Sd@!5`lyhxIYgmav8Ax#Q5C&zxP+jgX(+8y zTuz6{SH}jMHOiwcF}B_Y>ZlDJ7$mncD9FJF0!RTg{kcu>QPYKAKiJ=jhtC^@PL_vn ztbx)A0pujm>tB5Q=Esk|{_L}V_~!llfFO7KPv_*$!GXqLn|mUKzTJZj1QoPW~>7i`I*WK#;U+uq24>%(V^7FegW@xR4Jc690Hnms;*YbrYwJBr9eb zhn?aq0OFJ~zvIh#yRwi$!-xxbKuMfhYFfW$<&IYPlL~-zA(&3eR{$A*OxT!o;3EPa z-ceN(p5Rl71ZxS;d|d9BY?AxLflQGEQGN#ijbd;t^9QHr7dT%$`R6CUd#;Z(3DtW( zdLBRi+zxp#x{x=(JHLuwWC%*rSIr;jeuG!C3)avkCz$u83tCHhXy#In8L4U7&0wVR zh@n|Ut0;1=v~ewqRFAR8FfxmREX~2jS+oEEAOJ~3K~#8or`hU&ge?LfpS>Rr1A$sv z$2j!qv*D@>ZLRatF|WO{ma&RvSq8^ZxxGet_QDJ=jzG2M*A;!kn*;zH|gS*fVEZ z5#<2%%ssp-0T{lA_O+8hdx+UCMgAaS+dpWF0^%(=ba~Fnu-AS>^)0^s(%<@Z7wYHs zR`c-yQ1Ry%kU$vS8Yb1ZiVF2WP(k(JypsLQl?;f+V6rNnVmP4;N)y&3UL=YaUjh`D z0|{0#6FDU+VYD<_Mt({5YbDdo5G=`J-el|6mnN%ANk^K!;-Y97)0mf0RO9WMKp+cu z5>_&f^jUBvF<_|#Qh@a$G|9(T=p&ec9C0{tmw�s=jp(rOT7#513It^jhp`sXKd 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 O3JVkKBl(9;h5tWKTuzGs diff --git a/Images/Pxelinux.png b/Images/Pxelinux.png index 9a3069165a794b4d6b33e922708fad04d627747a..3308d05937178ee76df530bd1eb2e7a725a0ca5e 100644 GIT binary patch literal 76348 zcmb?hRZ|-buni$V@Zb)?y=ZZlLUCGLgS)%CdvPre#VPLYURtEM6pCB%0Qb9d|H7Tw zot@pMGkYG+ti-6P$YG+9q5%K^%#ZRip8x=0FaUtC1xEa@a!;FG_g@mGrlcWjl@qC8 z;qgJknjDFnN#2r%K#GY`F1)*xlT$rrq)JfTo>x*|H`)^l;^h3~q8*t;g)YoZui*DR zSHUfkL&}5^N65V@jg3=X%_oYDQ(49?)TKPtp*Vp@NLSRvkCRiGL)qRkD}|ayltoC7 z7R)OstVb)NFZ02ef=yn~(8swfQBqjTr!JRAKvO{3nuAS6RMAva&rMj`nD?WF5Vtxx zM2v-5g_T@JSU|(RD3z8+jaSzru=T4)RgOt=C{*zCI}szVx(qgT7Zw3ceoa?0YJLU` z0k^VD7G6zC02?>2CY!p0dSH?ummasSk7Gd^6^0}|2Ja^VDK>mjT3%gVG=37$;{aa^^FCMFuB)z#6YROAqtHzt#FQB<8vg7n$9g9!ZV*_@>O$`aoG z2j2>iF~S!#8i{6Yb^74JVcXWjba#Ac)I*tl#;(->IHIjH1>+}w-Zv`XPm};Nc9Z>)-n{1JD@D>OkY1{*V zMTO5b?Ylykps_nMh;+Ux`24vlBQ7Fif8?fVE2SQ+S-VZ9kC;-)7VDyjIj4~K}emHd~ z(KG}FeRwq4_S(q>^~%1J@)lwr$^bv{Cx27f6%BZU_c-+-UUsR_Cz3l$;fPo^9k=YT zmYa=vNWgBDdA_sa4Dy=Zql0-d`t&e6jf1}6q(xq$0-qUA9w)@W0oi#SuW9J z(qoAhnRyO{wpN(LC_^Htb_a+mgzY;ga0)6V0Z5B-%&!oYGA0LGPd;T4fR=;f_`TWrKp)qfP; zq}NF8$*uX+tYdGTWB#~ZPOANqCC!1;T*%7%h~DZ1wPi}->03o@qi`NdPL${zz$O&M z+sZ~^fc!{v6Oi^t*-j`S98st(j3ilIHV)j?g<=p+Z4s{TSAAYkir3bnKVOA$Y(Jgs ztmd3Va6Pe$0RUaSfkk^2(FAX`VS9J);O6)I4@DG02WY8>VLzOdDB^^dCR30K3)R5cveITR40$&Fud zD1Za6AHy+iSe6E*Sj10LiqCZT#MtosMrffC<~dt>e4I^eLcCBcyD7@`l6zbj$CNAj zlc-QXJ2&SiTv4Gn>XuYoW$Ae(xwHTV<~*_{L$xn$WC(^-cQHOkA{JP6*95$rAgFv4 zzr4r|{4=dVfukx8ZP1bNA*;3@2bIRLTuSz*x?DI} zxTT#%m$}$(@Ah51ne{7=0noLrx%KnhH*8yKf94?1uB(!vVl?IRc82G=lv%X_Jhoj7 z8@!x#e7r=4v9JGiC{pcVx1Z0a2tM(b)8R0PGKd+4QPFrG8iBMH;sjB69K>⋘`-+ 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 z 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
-3D@DeAf)| z{u^m=I+y(&b~`Km1j;NEKN8ltqSQ^|Wc0N@G&a6*(9GcXIn2tAH_0a)C1 zL${AMT~ZlA2qc$?A6%ULN{*pjGu8y5<<+8~R4pR>DF4zO00I#A_#@@NWKRB7@Rc0U z#`l&7xwBHRAT;4$h&0ZBx%>qHc**d)?p|{SzRY#e7Ub&ka(+!1zdPXho&f{x<(pVo!Q5&~X1V=$PS3LlVyZ;w3z6nJmb&`Ufc10ke# zd;5TVH6;aCtJSh~Zwh9uz~de*pRo~MKO|)&X&@|5lb{Vo*V%DWU@9>MTwU2d_!Xxx zV*p%PK~-`Y0BMacQh4%^3JO0M+;O1E2~k#T9EAJ1sx3|Y6 z**E~kd*Ir=*Kqi<`Va_?N)V@FvW9Rya3OZ(r`EI50c8!DqOE%RtWn*qRt2Go@OO-s z(imh$rIG;El-Fo5KDWK22BZ{>`jM6X&;KsiS6G-_UcbhT$PQre`ugV5z7#OLzOwE4 zLTHf{dX)x({Sy4sH&Gv-iJ|C!jH;E`fwUr4u4D#6l#yAuQ}P0%UlI;xmhXGUj8yoL z2zdL}3K1(-iR&9nJ|$VL%y|$7wG_;fC!Tj-3Ld`=fj(p|#gcl;Mg1u&1(QBV?B338 zXNvZ4uca>UOIEjjs{4X$(>bsbMkJ@TgIO}Uvko=)XB zQI1Rl4+EfTXdV(I?oPo(E*Rx;juP|>SCELW$-Co$c_=Nn$7YWaA^mm;>9MClE5{29!`#z7VU5XZchZe#m301S{> zfPQXy(;zv?c^lHgHRNCjf;*xNyrOTH=&E-Wb^4Hitttwy88HM+uiq)4bad-4Qcool zbrt^p!pPSNeervYs^yFDQiWfq6PIWZ^uA<82_H(@ip2RsK5?XkZgaGtis4i839DFSRQNs{hTbiOEoQ$_&gb<`Otnddv z*jMm?AMAo9@RxWP<*0@DYmt8WUyMKMfg|K%RZ1ou$(ec292!>D_vFEy2N5v)#Z3rC zuCP)nL&;;BJaY)X5P+p*4Tu6c<=EV6W?;?M1{gOCR_qn349eq~h0-wtv&J>6WC~t> zN~dD&LG5_3Jt@h?)~qCn@n8TJLs#*q2>EU>AUQ!wDD>i0HF12v)*UFdToFXqwro>+z3c zU^BBu%ex>jA+ST&0RY6!3Y8`3Y8WKeyq}kX@yT{FeShRu$|gtE;Hy)xB^t)ESB@_O zX9AFja6AjlTkUrGkf?NY&qK;82P_e%uH$hTEC47e@XI&_L^0;E4E*lBF3kJ@QBVN05WP(c=IRiDG4X4P#%8>dewoiUm><9svSRg}(_MRJ`Y-it_{jMG=_N z_i$2K{atd4OhZ7j|jB@kS#YL zEu`$AN_^q!?RmãZ5186Kt9eaL${t8pDeR)L>GL*Qwnl}ahO#iJR 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ǰ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 B&Mp7| literal 16570 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�vrSw`mLa*91atli5q}4V^oVta6-LGf?!aEYbr4(k8eyV+D9N|BQTppP`v#S@pm)6F0wek>hYW8ovd%_ zd@}|g<V5)G_l zm-=_^+YDC!hJ7XdBDLaR4%w?7t;?1kJ?Nu76p}*)V++L_7{ap59{CHNH>z(mIQpp8 zF|?DvogfIqbg1oLQH2l(4uOP~rs)D$sSDJF(MbsiBcuaxnZv!j1;9GTPY-?YQ2=@h z1#8AYFBlrai`ih>^_NFL^go#p0#{KuHn&q15TnA!i=KS-3M$|aPcuaTHfW~!8C+go z+KiVii}(7u&a5p{qWWAM6s6R~2h&u1AMn)pEx*t05A&BP{#NsUVcU(Izr<`kF%fK@C1?ZCPqwb_KI zxjbmd}(ikZmmZ*(qu0@8`z%ihtz*9C2BPQxX3Re)yd3bXP zIrDOP*ZiFSCI`7CzEq$`xu0bNPr?@@X_%i$eSOu zcp%@K_50XO2|9)-vCJH`-7Q%@M1Wcapuj*8ASN4k$Q;cYrYn@Sz@s9LC2R7t%I_%~ zT-FE}0H94OBz2&<)+p(cr8>0AG|q;y!Q{9xx7o>7@8!Is+;Vu^(G)qfs;GyEzbZ_s z?k&>f2vgut6~J~*Q;j`rT?~L1Jv@N<5ZYgp%%CF@2GhN|^`^rsqfntYD}I{5p;O?+ zyZ}>L6xdWA%)$)-JUD;k+%MGwvHHyM-=p!P|1~RB`?Ho0=6j)!e3WG^tvzUdNYCJT z@T;u}QvOxEMc9W?F~;5xmapDt00L03gSU@)L-d0(p&zn~{Rf&{!*?ztH?lAhzOLqH=X-4ilKXzNY0y>y7@5qN{UbzaIveKdOJsgT zBMvj(S}bMFiAKpOh4I3E0>L+#oPz*J(8g?h9}OD2Udh%GQJ1&uAiNwQeSQQEgGxKh zzJ)~f@nJjBCDoxHS8@+ld>qp1g|M*>uEk4EVfY9n*(Qq+MK*wtuZ`g#m<~aq7XUb{ zCMRj7@1GRI6#&+eRBVlc1ZP=N(AEO!-lD*bA=&~4YXMkIbQ*I0*xJ7FBOUlXy5{Db zM&EI8B)jle*KaoZi*-LcT-l)7Q~5S`BSXq_w|?BGRv@WbC#QcA;jC;q*~}+V*30H@ zrNm;B9%VggZToz6Llc32m}CRm?%>3Z*&bNvP8f4PV%sscqj7HFzf-0Ic<^M%MEQPQ`xYB+-6s!e z3WjXcOn7HVs){?mCYg{#EyW-Y`!2S>!Y2b=D_*eRdk&L4>7F7BpUb`XzvRnzp#&5n?%&%T?0Ta znol9992GDq0=Wnb%oRw{pKf>-IuAaWoIk#4@B+uz$Fp9(#`&7#p5;L5x_KlT&-((; zkEQo0w1WnpN zqPt+dMsac5^h5xF@KW>*OY?+Jyq!za^ur0%m_+X->#RHN9SW) zX}Ts4ab|H$A_!r)34-AidTv!Uh4G9ERs^Sz3NMDRmvDe6gncwc2z1loTzldw=>i~{ zK#bt0A#4|}5O%QEHHB?uskw|yeQ?Su zl7!px^z@YJ3P{2v&OWkc3^Fa122+XLxbkvoWGgwLAqYZS2TMMtSj}?;fWqAT*s}AD z%cJP%@pyARnr|P58%-a&UvQ0}g-^;a$#4QL6H*3{gwcT;$ZZ_xU@o1f^Z9&uUM2eO zP5>G{TW{ui9K{d@Jdt1hQ?dEUU@>rV@;=NQTwJ_=0TD9p&GE~{anKX(mS0zBe-9_z z)V1>TTjD&I((7NXfIl+ns`oUy9tSw_$~X9U?aq}nWK?C-YKh$v{-v@MUYm}J*12nR zi-;2$+^fn8GjPpuRXbFQ8VbJ34;H1>3Nh_sB02g$w7wMr$^ZZ$07*naRP<^zy%;_a zjlera01ugeun~V6C1(?zfP^WQ3MVHpRJmAGi{S#=xdl|D3kVD$Il)z2!+GJ&gmg!N z!8G&~h*+t7^K(H%J(*0-&JHfV`{kEkGycusX&@RN>X$nv9e`;HjCyv|FpI>J9|bAQXrUKD)Tk zx%(`L<5$tE4WVD;KoI3S8b7;Ps6jf2+3Pe~281`lom6d%tp#8cp$$jPzmxt4C%8m{ z46*>Z&#WA&pTb37q=*QvprPRLRas<#x%Yxx^wO~lOG}KlnTawK)>GE>^;484sW5jG z9ezER^YLab^x^CCaP2UpZ+B1yW)RMBKTV&;p*P6BzM;^mS3p)1e0Dd@=`u zb6<7>Ffvp9Itr}rGQR7dQ*k{$4rG1z;rGDAF0mi)9cu6IxXQTvV&4ARPE#^}rMwG( z9cIvG$An;J>(|m6MaehPXTM()Uj|A#5qTBC<8wu&_@}cGG;} zmy2ir)fl_H@!Q0A;*VJP+POlM2CMzjGn^;K{cmA0(78jR4WTxD2O4)(F$dYo#eBF} z%=F2-x9;2r(+`VP?lis|p4l|6w>_dA5!eg*v;Ioqugv2dv*D7fw9M*6nt-k6MOM~o zeMlO001&TxfgpWT{N%k3GFUSz@s%-B0I5zRjdY9&7|qm3P9+~{Z%_o|lHxk$hVD4G zumChOpRDOXjO(1(B+ZFCFP0ST6RUT9d)wNMbm;0YcYgdVV-Hi7gW_vk!7vTebgprx z!KR^yO_6jsJYJ;3baD)h5pc&z7Oe-MLbVwEI%fCwz#6%|sJ_Rc?w&o&X2Hr3Q)$%b zIq~JLDl+Iu!>S#~8RtnR5;Ka3JHe5GZnxQ#Gaz+xp$n@Eq_FIaAijjJk88x;Jt>L07E9~G=gg~! zSZP-aG`>NYfIcwP?}kHMovy84dOie+gri)o1z?1qgm%H@(dfP|SpPT6>-!;aGoho$ zd2dtE85a+M(o1gQ9%ZM>U>l5Dcdk+EmZ7Btz5aFmLg@#Dz9VmtIiZWe%(eOw&#d{ z5Z(w0}wOe2-(3JjT^U`y7>Kk%6|1i9L>{saxpVYfI!G@Md94P0wv%i1)` zPW=;sA~cx8_!NIrq>)@A6x`(S^n0xyp`Ai5%MLP(h`LX#sDHicgzv6D+bq~<69I=F znrCTRg+Mul@3?p?J^T6$G+zo(?Hx{r7yxbnAXC1t4r zd<@F9S-(6UH^_m9-2d3_!-rLvqc8>fA8Z4zij#vmOu&(tBp@)vN}zVk1(52`3Y^E- z0Kkatg+Nx;{Q!t&FuRWl1WLPXcQ6Aa<`DjTzMlplECsZ}^rab{uyc$`tju}a7ii8ku-C1W^seWKu7U(FZSoC7=sFM)HortMCJ}cQFz^w zMP^V8MzG?gwRpsU5Wcw+vh;Hk)o|Tw-LH3&#mD1D`a$_evh8ONOI-@+mlPA2_<)En zg(0EZV6t`{8H{w%;(1OlYv<>r}OYT2I7rBsS`pr0OjY zF^ba4q$P-5OMgJzLI_ED3HRnoVXDryGAKCjEm=2C_@yh+V8?EDzx*1p4jZ43J^%Zf z>|aZ2EnH2BO?y@wJhC|`!#hc}p&OEp!K_HNB^(atz?9bJZ(5{*G~;M{n^2%|N)9;* zyJsS}I(9S)`?0!T9xU=!5rJB7F7cg(Q&WNAitBQ@EKe<$od(bCs4pGFhjopSePh7Z z@Sc&0AS3sS=x*ZD=gQ|0`jaH)kC4l@=L1}(T94IQP}Z$egHTC+u2$Jd2|uxwrsT}* znv$d(n%!dfwbD%CiS_Qc@x&bhQGX-!ra#Q?w~@!k;=R%EKirw}CZj3tsZJ*atOo%I z&R|a~aG;0jd;pY~K@nWS$r{}WKsfhfA+a5DzbqJzOy0`^mTg8QO)HarRuh0m^TM=9 zdH8}pXz5Ikt)oO1UlENCtpy;dAn*jS@vDH6eP;n%0QPhhpyWdIEGDW#Q=_&<*^tE0 z(lyvNN?6CP_{|^{e(5?MR%F+Enunss5?bT3(QszhuWP)Z^dU~AI^VKFASnOMbk zSWZpCqLesY7yhjjIcL{y{<5lk{t0NjjKG}esBUIBDMksQ0KqiOIYIFX@?Jn&H5h8U zhk9()BAM&d_W%nsRTAvG_jqp`ZcvI2-vgv2Yx{c>QMuK z#Aw$)+{mBFC!7&sgmDkGA)QsrxPGN}NB;tM})WW!;KGonT z3pBjS0fF}bU^SZJy4PJBBC1*9vQm@me%t>H1gZAXi$MloTB!^8=+RD+;8bL-Ax(-a z9EM!WO;Bo6jEtqKn#M61dXX~CTsuh|)zVLRP+&tksW;)DA}kRsJffFS9vzX^kmNiB zV1x>-_$r!M%2CXlf=$V7-+7r_>oD;3&<1@5fI4y;oq?Q-P9+A7oxrg0Xad8&1;~(V z6F5jKl=K_Uhv|Wi`{wA1=X0170e!0=@{^&xtpJf{v)Mh;-~rfd__8f4#{9W*nRfzk z;nu*!|qAUh@p`W^W6BKn(ou4oD>a#K(gDm3h%67B|^UD=pxdTA7v z1J66CbzzdECqvMvvcfD@0yUkS>2GJiNPx+uNtzB%G~hJqP}5+Dd@Kz|2m*(LSnUiz z9e!jxTR?68W>a%q?P~v4M+zJBzUI46$H((uid>sN6IB^mDtv^+qt35YWR&h}6KKiy z*d^9e?g*VcYC_bIE|MHplD1{nG=eDv;V6kf(FQhlR(gg=f&z7lgjBWLhp3DJq@SRo zpi@3nKCAk!=#Tn0CT;4SL;PnOz)p1+1V|4+B{B#?mj&~>^pFR5d1XxX*> zk^7Q@H%=FWnP?cmEdi*L;n~`0|4PhR{5c;vgK=;!HR^M-8ieh1x3@xW$6`5YRr-{R4q=HBWHXgWfhKa6iFKD zOwIO_c!EaI$A}`8nCpOS5is=gEwT^gPbuIiq}}-zS{Gb^x)8*2MwS3(Fwq!JnTh}@ z2>4>)0!}6=TEgKlU4+2R((xZG0iNkVsS%9sZ5tc}_ppF)jOfeOwU|h3U_d*m?FI+h zE6w!mD!1Bv0i=~Z2n+WepB`lYL}VB%Qu)IoQZ@WSbW^)-T0#=FOWaAZk%F94b&klWh7Etamd zDEMs^ESLao_8^d-^{Td#xE$OwTOlIxKUKeq%!qG9&XZY%-Vjqu$!#5POIh^}PwrGG z!(P>iPuuobVngIgJJJ=A+yDsHe{x~khm29l_@g!qi!E$j|1!nEI+9t~wfzH@4JL@8 zBpC!V_R%n(8^W@MB7ueI(0kBccnA^*q?B602>P-9xy1r9k|fLG{U!lFg+G&By%`sKC!3CTXk~3Qv=tPMT+S(pb+}fN&*fPq3oPIyL47?Ic zW9kDXuVBVao4^1YT`=>@PPh6x<&GRE>K3rbFq{nMDI_0rjX`bvl3|$1t329o=rC># zz&hTs8$vm-2?E3Ek=!O4IlXff>B!eU$b1=u7|XIc3n}BPtDYT+qjH~gQ*4q!S(A7H z_Z!HTMfN^Mz$@v~sP{L8fl6(z+H4tzH4-AvT}5Ufl(*^F`A}xxNFswt*7n-H`mbIo z84p6g$m}c77sW80Oi-y*BXBkvArJrSGcYif6D>#n{qUgBDF-;-d9f%k4IU=bOkmgM zelA!ea1d5ICm|r`ix?dHFX zkWZBWycVFAJJ1LmKxu9;t!Da)h9Jj+Bb+fN3D|eHpc1{0;!z8G+UT z!zFkLchFOjZzMLa?kiXIhprHRS1|)IHV599LpaW|(26CMP2gTD*SWCGIYu12zdX;4 z<8uT9w302+qSeBhT1$RX-FI zK7h)L3EA>o$t=jtvO-iVqBw?xr&6@q7VWWHN`axVfwLK4un)(kY78|omu&#z)B~oYsMM%fnnGS)>K9b@N^9}>Ql6K+ zI7bs$8dI1d3UNQ7aPuG5>smRYh&E(OF3stbGNv^(%*K)w>KgzWMO9mL@sTV}2@+Cr z$vJA^OmZHswsys2_?YLy0HmcQu93r4!+Rhwii11U@Ab`R>Es0csrIf5C^etMgn2SQ zUd*9Ef@$z@Q58tTN{^9`1$$|NSYGOI=vDrv0IcItxJxw}RZ>naA<}FqSZ;L7F(90 z2DubobsWX9BH}2JVnf91>UKQj-L0+=l_DpU2_GEK)AKp7tw87xSoS~!1pROjlRVa0 z2dRn=t12BG<(FVWIzRax0jLqUYeRTcp%v5!?1Pp;c9nNe#lR8|VR&zb+d}$x-h@96 z{wqKf%8utk<4FgGumBG5MhCzVyfIuXaZ)`laY<$jrV&QAbFP!2cB!#y#APM`?yI(I ztbb^w4>%)K6C@nTMRJsBcwVK8 zFuT(4%f48{h}ac?;Dxsv2%&hEINTwo#2SL5X@Ax^C8Dr{1Q9=ugYYmd$!?n|2w{g~ z0f42HxkO@#z5v*xMXUn1u|gmS7eS>BO=F37;rKcjLhY9Gm}kul0nar_wzD60Uoi0j zgm4VW_l#iKjB!eKw~ zR~hq@t42_e*5P2ULr{RlqPPuP8^cHQw7e(PcG_#E2xG+`AV>i0k;^53m9!DFM7IpK z)g;DHx4F8yq6&_1?KfeC|tK!^+$%ehWK zW{@w&`*Lk!w6}Y-+TX0xst=uV_roSH3x0rjv(T2ySKfS<39a{q>EGjOauw0eKRnHi zq#30vRDwX4beUh~C6%JJWy`OyHmIE~+QbqQ6UvcI<tOX$soRhH$TTX^;Pr$0Mx(Z zvVYf;%*tLiYYhnNAJOhNgnINeob{UKLphmG)K_FB3%A(bjeSYlO>VXj5N|)`1=J)C z2up$EUXBPvpn(Lvw)fly#|CO2cy-=Uf9}Is^;axN61Ec_=Typ`t zW4xajrb(ea@({E+(s|Lpf>V57=Ie_eyIa65m@)le<}s+bt{H0g8_aY<+=uD%UgIe# zf5U|^#5StGxs+tdGlwQ4fwJML-6=t(z%s`K1c%de0HD?D1vd=oahyZ5PQXn)OiFUh zP-2?bP{swYp`>jT9nXj#nEjNi+o)>MWhk*(HJsB0jWs zm$C%8Hq3@&Opry~i>WjNcTl+o%wViz!YsQ&DwiGXwtf#PdHYznQ)bMJM1{PmIN6c7 zs5K_hRUOIPA{WP=j{XX5pD=i->P{*Hgu%7Lo#er2C8F){7fypI05IrJQRUtU;fL#l z0IRdJ8Fs`5wrps>(Grhho)pQV3gW1K73a~b|C>h}>YeujU@iOi5KaYEjed}6{OOn5 z4}#dtDv7=GIV#T+w15Qf0=%%zoWDVWRv#nzFH56TfRBO9+M4 zYAcIk0y;G*4`x2O%2&w@t4H3)$h@Kg#RypiVIy^H?SrN`PlK<*Da;j-z!WG5AVaxW z1bGx;l^nIfb0HrTfaHb4T>%(q0QP#pjBC=_m84+06uhZGErn%d`HG5Ip5S*Fix#v8 zhP4GE6v;!`dzoM1RzmcykPQoh9=Pb(2cU*(-lGytZX0>HYJ}9gBQNlR3XT5Fl$s#s zFa~6Xa$A5!7?GG&BN%ywZP_w$s-c8_sBz zIh3WdD~iOa#JA+VMaHFigEng4UToYN3cUpbaA@2ISgw;78@?9=PKk z)~2C0gLRn_B?XB-)8k#6*^$PiUpBCVm(jlGKzWmIrwAVhuqM}4u7=X;_(rZRXqFGZ z;>fenwPLtZ;9+mHg&--+-a1K{ySMsS2e+zQZ7!aUrbJnyd2=ue8gm0Gv#p!M9aXTh zk{or|ykl~bCLokwq|;ak?cmg_=uY;}eF3NuxVr`HW5y3J7Toc47Du#Oh-5WZ+^$(8 zWTa21)FnC}ss&n}R-`}GV84zeF!3VO z_@zyQIm)M(Mx~2G1sgkfWo7IH%Z}L+<(kkd(4jocj?XZ)hi8-OeS8<26o*K5SRj@6 zf($uw(4!xbU@@l~t?z^JnysNdL!0iga> zro&O)p&?9>28SEdX+r!|op(*ISbkgBd_!7zif(p_->p!hHZUvm!}?HJjV1xGTQ z_4_&-M6#TY`=+x2!VF|62do!gQh|yq`+0x?}<1Tk|y>#{`R2A z9twa_24oj)lAVgu%6G2Tgh?JT#p%gE1?Q>o-{+XQc~-VAR5wWaE?1F8##h7e`KUwwl8`YCh6y-XZ>j2<> zFgtoE0BReky?x_@>N;3Zh-$?Y>vP$|tP((ZPukXJ_H5A7XJI9GcrzMLiPS zRB7l?G^);lUyo{lm}p?l5Np@5liH^zi9Hmo&;)%JDtZPpqL>P-pk%d7Ym9AX3j>$u(-taMP2V2iOg`}4NsI$U8jCX)F zz(OFTihb>i$r*Q8Kz3+@)!T88Y6fAqerMr)zTEHTUDpo>K()f3!?+PpyWCP+T%OhDPVK$-9)78hp4?BQ84z zJYDzLo@2c$8a$CX#im%IvBMZBu_1gV0_MlNHBFXr=(pay890wh&6pFSW=BhL#Y#)W zy_HKZrO|(8?PsQAz68!F0ASXKnrw(%IY1yL!}!mLzjRQtAPN3DZG#g^ikXsEkbfxc zhNJCflJ5_|AGX;j({lnPN}7c&0)qSC0RR9Ig-Jv~RJTJq?T8+Qek9gS05q~ZYF}Bi z;PpdmH}%^DA#v~anb06n#|JDH^x-ZqDFDQNosJ3x_w0IQW5O8H;26)Wn5`j`ttl|X z2vH;QDwnirkW|~G;{Cqd$|H0xRjpbaKN=#(SHMLI<@saBfuU>rkhcgPFwKFhA-#TG z#BFr_ccfvets#B6>?7-A01ic2WC`p4DFcQY49@RB!=AwC^ijQJvSRW<7&aDEhO_uG z{y|&lA0P*MwXH1a8(F~J04QwHL{PZ5I{Lx7@I)+9o(_t)?vk|vq_+gdEbOpLHc(K7 z$o$ObDuFhL0KC*OvJU^`C6oY>KjRNN>HErnMvx_-0ZC)u6X{{3{4P*y}pm!3FJzqe11=;k=Vh+Vu^a$L>^|LHIYr zW_^IcpUy?}_kJG+Ew$TaG6IZ{0XmuY)bh9C>P8}cWS5tbJ}0$jLFo+{y?p>i>h2jz z3qrw^za@#hm)uts-DO+`pq0qu0*mAwxx!zkhB`w;T$M(|!rSJeZ9~pFsJIGV+tVa|JQe>}Ror(sKkQgAKD)4{HIp7~^FaE?s5Jm_%%3)vDW%W6rUp zAtY0uv5PT`0w{}v@*PX&QR59c;m`zKky)I&L?bIbjE;QYd>8kdZr|E>Yp&-&OB z9RT9smH?>;8i7FboT53@emMjy8CsE!aDzy*MlH0oYAkd8ssP+-uWAEc+}|~HKeKNS z-Z3i)C~&FrhFxcN&nbAi+7S4RzUl6D zlC@K0h$#!^yYie%H@-|4t2EHE2q_J_6**)KHp!_i+A2Yl2m%PJH1tl92Zwqtv&B)+ zsHvh!c^#flSsZ0aFAhvb%&$2{O?I7nz;4?B!A1!Om_5uz0=fsb--cuiH2`s>8|P|4 z6=6E!zR1ef^bzbqVBM)aj$X<7hhGnXTN%J*!*TL=p-fYacaI7qnqeL7vZ0UaZ^WgB zI}V1GR_B%qy|Ot;X@q^)8c0$Sa3an!Cm6*&GuKJA%7*e*EU->P4ml_J4+~B2apkIT zSKKRwQ^s1l0X*gc(tc@L(2ApOiuAgKqYN4V?mON5#!MYlu%KiuvmjPM633YhtFI(x z9XZUrArZ5Wyi>4t;CJB~+dB#=0x16>EJwf@p0Ni8t2jd!9Io5R+bqT7NKN!>0B}14 zNDDvAA|K(p90V$wvlI~zmMwV*(+VNv1W#0ohdD^1UD605j2!w0G=AU`uKe*m1#l=TQ^e;0$oXC<5Zj=LGPu)$}YOc<*8{b z+b)PGx&J{*TV&?Sn3-I$7X!xSRcypSd;rH?$~Ex9G4Len%#x@y#19nKKJsEa?S*kT z6}J)6sCm@V-%`!-J7wC&ankK7w>0WdLA7fq8FSA+O%129@{m4C!b5^A^033zv@QIIf1Vw1wUxh`cm zcQArTt(4sGv4ok?-i5K1smakrXIwerT+*)s?jZ5=79K#I(W6a={YHvbSFD3u#dwd?5MKduI1b1uL~Qd~H#uoy@HoFyUeNTQJunDNopdH#6Tv96nJ{BW19->MD43bi4KrCnm2hF_nn3)` zi}0LlE;~fwOzZB-pcP|8V9~(LleUoD%rhp{YG^_#14Ib3&tpk3fsvI_c0`rzKiNX* z(d@B1E}Z@(B>1Dil% z?=w#@bTejEh(=Cz1MuxM7U=$#F>8A$#~p;fbSi9*MVMKl(~flzD7n{8F$*d zk|&IT;a_&+lk}_aII!hMmX^p6JX|HL&NGV)!Art2)hQ0b(1IPYLX$S~`S5xpJIQa@ zGgr{q=u_awH9%~AK<5`gH^bnNMrHd%&f>aYAH6L8*bMku1XDu?tY&dkKghB7s~Eu2 zkK#;akVbmA?033k?JGA8PDnM^%Es~}6==J3jjX+lrgGQg-Q=|-7YLqVBP zg3P|*jCVReZqOmxK_7t@Ww6e$O@ij&+vbwLn=BP1tGO;r$^B^qv! zjr3PYJBk7fw+XKeSU?*+S)D4n&u&`FEe-P&(j2dO`JRR$is~&CZx`%^nkzyJX!z zMs!#{Un~^^_}s$m43=DCF_PqVSt9j=CAE)i=!jcgF@7$uaKkdN# zdE5m`NDN??Zab;)mPW8j5Hn_gD#4aFN6V97W-Pr)LJoO{J^#DBT zbq0%B(`mQjOQ->1PDD{*soVgFaLgditw1iAx7{Jj8eZ@lcYgCT<$X*Y!D;(#_kUc$x?n)%5)820eKv6!-;TE#u`))dL!Yl`G z5Ua$Jx+cCq=UC9atxG3mxpXNEBhXh~^-GDRn{{H?+S*|6w6s{sy3>;*UKi%Cj-Yrj z>qwgEVOKr##olhbe(n}u8W9FlX;yA8B9{V%8BVgpS@g{96rM@y_L)MX%sb@v@h!b7 znBS)-j!@2T?UK?)dN<0}X#KAZ!24t%8`STYZs-VET7ZJw-7cCM<>+5IRxT>oyTqhn>)VvWTZ}2Q_YUBB?&8i=77l1n%z}^;fOO8}(gS6!;`wC9*rG;kR zwyZ9)Ly}W2_~bRS>|FL^0K(0Alks)By%c8M1kc0n*KRhJZ7SbT8!cd^ z-jWU69e`@b2(Y(>JBE7P(pH*%JLE1CFfkP&uq?aGsAKILs4hLjS)Tgw&u*s?b7Agq z#l5l%uDzr6E__|-u=JCin5%}+CXQG>PFTK-tvX3sFzjMsffNX~V7QObG@_-jEJ`aU zY^l`5*l+->n+vhG*+Tpl0eFu9aGUW>-_d|CM7i=H#l0{su=ym6=);Cow>kunK*z1c+UWRE%W|0z& zYLac`xpF@i-m$B0(`eYlPNH}uP>8>aoH~-ZoqMJLQNFD(aCedN`=`JLhHbaZSH&HB zy4EyS5Vg{yGf1&p5_I>y8`s75;&q16y6J3lozP1`y6hve|9j2|YdZ*y#@wt$7Vh~I zJ5LeAs^6ie$eXJ)a zLpbAA7bQ;4n58$48mfaDjE50Gj+`o>{F^;durgEDwUzyxGHN0zyU2xA5T6JT^ zTGwXT9L*#1suVJ+NKKSRR&Lb=KU5gFD**HI-{%nPoVwY$bgwXCQzBwjz!qIFgCIhDB)#h%8XS(_9=8+UX*y(XgKtV(kYX{ptV|zp@cq z?(T9=TQwTt_1{W6a{LBKybmUO{fGf`bhJ6%YXHzRhqG0nnpIBr=daooYl14!3gvPG zA$@7czo+7o3Wvb|CE+KAp+sqZ4bfNLBrEgK^H-{bMqc*^{{Ug&{|Be*UU0IdjWGZK N002ovPDHLkV1gRx;06Ey literal 16570 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≶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%0ADEM{#osL%lurBC!VH#r&DtILIU5rW4^5x+Q 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 MKbV#jB>ye{AF{%IS^xk5 literal 573035 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

IaM+AJwY;Z!PqmAgns3lfMAJ|Bu@T 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

L6&+q8w9pRUiCx&+Q$3gcQ=b@QIK3Mc=7q|9T} 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%0Dl8m-5rJ(vXiGi=WEzr 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

IJd07@lqow*UqcTbXKEOo?0y??xI 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�o>LCaJLS z!r9q=$hwg-Bk9n_Sh|=R6d;R7**z3djcD?{D!b!sZ4K$g#WKdiq+nGr9XXMtDnB3@i86poKMCua0e`r?fjvBlZJ%h8t1Rc;{(J!KxDfV}-(cxOh=G-#Jqs zwJ2U~`|gv6*&ae_anz;;=(syq`x?e88~BgJrjp&4xqk4n+fICF5r70WI;t2mGrrn) z`zSf!0hpMw4awFUlO~hPCxYkGx$I%zFn$nUWv9C2KgI?f@V!~S@lnJvtJY(m194cf z^h8D2(K>0|^*pXs`z7DpKnd4}63P@jj0_5RI0_9NzQ~~yLk*RvK)g6NF#jJ+kGdj} zBdM?j?tR+{SAojIhR{H=I$pl{f>ZzclH?CJWl{8i=j+tt)8xr7y{@Sz&89c1=1J^n zCRlRJck`FY1}Qu!>Y3bxltBySLr+RSNfa~~o*n%ChATGunDu^J+;BH@ubTsawK)L4 zOC27Fh3ddq_825GZ6)*zfW_Bj~vF+ZGVKiP*rS~_e* zHw=GW32D_g;x0<)qN|LEr`ggQVBqUzx5(;=lEdD~JCV~}EiO}n=9~~QN`pJrOR40A z2S+8V8#h&z|0z|%hR~vr^VG$Z5^Alfk9gK(Kbb+l5}$2anOmV(rCckx1`$=-U@w_+ zgj8+W!w?ikCF;cx&kTlmkBZoU6YMn|a12vEhV?cZS#cCKE+kYV&1hjLBbn`Bq+!^R%v9XQ+tCjFrA$ajSo;_#<bwu91P zH3qV{pbqS`SM59hATrl+#@*#KWXZ3P(~mjmI4FkpN+{G}QJFUuU8Z8lOG5ErqIem7 zd5~4s^*=W`cGPS^jJxSR)sfQ*?aL8;c!M$8+#t_fhq~NxO0fGVsJ_tlLuyNGwBca6 zeyf!BnyvONYLMI-ekp?vavv&81TQ0dO>?EGcuiV*!XZ#4~y{-k81o>5bl~%mImcF!UPWV zcRbUr!JJ|}{)x$Eznj5_j(ii-P*H+~GH@y#wflr+=t$v8VyXEeoDVJzy8(H4>U9T!O zfg(!=ab>OX)0#9ROclw5$En$japzNheviJGH9Ywif={D?Kl_%QDR&VNQ|*R)O-Eb5 z#%191Oa{+u2M)eIh2S-`Xf_aITd@70!PMs^d9&&Q%KPPuj!)q?jBO#2U=huzKR;g^ z5Mh%?{s^V)N}xU<{BEYW!h+h!&GFSZ=$jvw7+V&z6#qX6&3_@=Q~+&UpdogA{8UWm zRmCR+1oot1?8yC$F2n=}jPsw@UG%d4{x1nu}GxyAq$ z-o^}9E0F5Vhnr*{*#`Jf7Kin;2((w+MH_q{RJzG-2oW|s(#>LT!TMDHr`Rc)qN-yc zEwIbPRy)_|rr0kJCIp|kZ+4jzAkTarvCPX_hYvq_Tr$NJ`&`RSyARu|WsNsF@R@rT z?{$0*$YmY&;dM$(Zp^6g<9ZOK{niu(%yEb=#3(4E#?iN@Ms}onzSZ*He3=WQ`4c2x znaoczwEh_$3x$;~pih@DZiw)6S0Fqp#?>B9@3&7ik&MlWev6?ZHlnn%z7D~Pl(Fx8 ztL1Py`;CQ7cM3C41WJ~%!`mz73cRA(_cZxql4hnj5hEqKdqC0JVvkkwygyz_lgnZ` z3>_@A!qN0>+U_Xt$=F$QUzc9Igo`B)2J3$$DHo?nuC!3Xagq9CD}p1Cqqp5t}E1e%Z$Ped(msRog*&la42b1#JSU z#h?lw=^a>JZI73-#!eAFVcF6i_X))A2;^E&VDx^!u*+6CieV==)N)q)I-j&P2_ho~ z8%5(}$n6gy+aem?sx7-C5WtXt1cgR%(8m0IDLFQiwzeJd--_*2vp-f1&a{1EV)p49 zBR3PH@pJ)di{)YZeQ^q(baW9sOebHzMj}I%c9Y=AK-+P{b0=s$7htmbyS!-lC-vE&DuP+WHtQ_TBj%@_yT>zm!uy;dpm^TORCgcU&$AY* z$_Xfxx0l_#@GNbVVx8L-wqtH`#OH;y>BSv~UTC4#gB9o%M-pwcdX2WzH$F9Y=vv)J zlXK`D9&Q3q(`VKTsUyxmfV`Y=7fn)KrZesuJciCHPi(5u1r~QSI@*$`a{bx#*dI>i z_I{&Ck6Tnb$EW>bXpc6bvfS+flK>+7X(jB71XFFP22#h^{!*)>_xP;Nvf9!BPv7j2 zj{wjH(!E)JzJ!?I@oI9v8_;IbIWF!?FN$K=j|R23_6{3!?s@;)NDZ$UdV}$>4X<$! zckvkvelZ`<1IvPvLDrhO4xvs@iZ zv3~Wn$G*oAsaIT_vz2e=PT7CwsN@@m+lzW3Kf7{v@u3D25(+DZhSI8-48MV897H(V z35vZ_@3H%k`~4%{XnjgvMlJ&)MKKM_-&ThYHAuo8EjE{~r4vMBaHZQ`0tZq&{i0Hr z-`ER#B~!1c?_3d`QIKj zs9>@>wh4eqCLewZb}J7}ZlLDQynMm$S7MMdOtdepSdfEkj!a6J^4s;KXK`A7-7OIV zD`^zkz$J@VK6OkWr<}F|jakCO8zWA{ZYFOOzzcYN6u89pttKIk>lB*MqtwtZX|Nou%-@#38Rvs(wh4vyemK} zbtIlCF@?@TzQH!YzHUS9r&;xPx_8=BhS9{~%2245!%*rAE{ngNb#aJP^43@Kj;510 zBpz5`TCg*J?xh#0rFw&^_GkvX~|ICwKtAOZS zvyI|##jhHT|11TAgP6?eE?kzCPc;a0cGx&OD}6Ee6c8SefF~ri)x^`pqhj0qq9IKB zi*h{7>))$pdw;{?Ua}tAbt>2&j{4S$?Q!azy!t?29iOLX05PVaSs05ft*?Q0G0T7b zTbeeyLOZ5LWQDEw@g1fO|6j}axunlgSSEia9cCAc)%ZoC$hs(drUWj0FvbokCYgqd zz#b{4{=F-Ea_BUG{M>$QcfyGAtw0nOc6qfjbWAD(A`)jh!jLmN!u|9q2(%p{&&-GV z&Ev~*#o-$vycwf6BL`v(Iypa$beo$c6@bq{lCoH5{l2u}@eT7M{M!yT+Z|y>{=jc4 zlTt40Ry!(-jsy2|$ZGYQ(|#L22k(6LVXWJ(e@)})aJ+v9>J_zGHumPXqfjDnBJYi5 z7#i15g>Ou0;y^eN*|A{gt!Xg^)Ly6ie)nHPH25Mhkme*O5k}P$7vwOF?X{&e*;k#9 zuudL4WGKQw=^u%@vsAV7RnenOQVSEUS%~EzW~)bPz;TM!LH$n@0wSBGGlk8sc_5B| z^odt-@`L@}0o76B{>!B1@#7)^bw^F|Ft_or+#wbRa-pZGH}(p82U8Xy{*+HCrVPU( z?_z5X{NNY1Z$qaDvvR-flY&<42u6tK6L+Sv|AeR!$jm{g)i)<_DR1ni#3Ej&_q{zv zk^8JBmDw=;t~jztRH|sb-kma-bjQ0cT)iHnV;h6%YtI_b{KS?g=2W_JFttPEw;}NK zt38H;LxGStSwhVIjMnIa_SY7wps>!KWqpyEcO3AV;* zGg`>o@QTr5V(!1%4@K%nFbqf%QkQ~YRX{f9J)V!oE@D{1OsLX&GB{1g*r0`~BE!El zmKfL!OLd!~BZrzU#$%+fUsRm(qq1ePvEsD10PSCO0*gxQ^5x4g6ds;;FeB^7^Eb&) z+_L~|G-qA|4!3;wNxjrAosid!^HVH$X2)^GiWrIw_FlQ@^0^lqc*>=uIWZMh{_b{( zjpyxawHRI2?{1J*CHGOFR%qA$>3W!FKc2r@Q+vR!>2=XK3_uj7gTe&;V$-j#W2K@= zS_B7IEHaq*U0j|JITjEX-1UCb=_|`1Vq+O9Wy#onThEX}OrVUX_LohlyMPpgTYjlhtkvi13rOa!-ERA^WOe z6kno@`ws$m_EEU-U(&JUQpj;wrGCb`;P0~ZtT=YvekOdxSG(kBo;iNy7EHKM&yTrU zHwVmEdT9q+zWDd5p@V0xqidaKXvs6q=CKu_dHdye)kQuT8y8MaAXq+YPPy;gIVe*E za*dayyvgX^J>xd97tCt?5m@EPM=d$y&EMtO)w+Yg;rSja(;gt|40z0s+@2}ld{_k5 zoiZTSU+UV_4w2klj%8Q z`2?s@-KS($8dip45_@|VieDH?3=72lfc`36LR`B^Z6Q>e{Yrb5rHKI-$;C#Jxy0f1 z?pcmnM*&i`oy^;sFcEDru}2t-7pgET?bkJMvh6TSLVaY@UQ5rxn|sAWerY#Y`?Z>8 zmb01tMs=r9GjhyblEY*Bfwbw9hO_rRoI#d5^9#rO|9;Vrw-j@%NeGAc8zWL$opZeu zt3=aHxCf1Xbu|@>1v{2hhvRDcfiuj??YQ_M2^l}oYdPohWJWBX7Xoc!0(ZG&Z9!tQ z=XWxaiFt5r!R8HD3GU+a?2v%ZQIglwJl)+x(J7mH@Rml_qqmY0MI&NrE(}fLFtZsm1KOLj4%RJ|Xj&3G=13s|+XE_>oZe3)O>4(=}Q)4mKz~p=&rq0s! z+nzakp@3d36}8|K+oI&K6!*7=ejN9@Nxi=@-}PJ_>Jz5kn=U!}v4zamSKr3|~xC0#H&W(2A-ig15@ltZB zP^VOQkbDibyRLc6h~#4ycH40=fzi=sz#Nc?Hw~7r&za88iM?z(_<>KV7of{fL3shF zsi^(uR~%RK>o0`ZTlXBOyO(V->i`!3e89r!HQ^}YWf9s6D|#Ty)-+S#XHLhdc0 z9gE&2v}^>)(DylqM|^xsYioJf%@vr(8w82bw=wC3>dO7vapTFE>z~c#m z4ILA}4>N}jPEL-x{=E08Sli4$^;r7u%YK(}5aTWh$lr6mTd!&Jf`yz5?2PFky?VlY?S9Wp?DwTS>J5LyWzLM&ngQari}X z7vks9Ey5QvcG4l~_hzftj|T?8A!N>pT#&HKl@lCMm25EG*lUk_qs34~8E#*!Mp9P4 z*na|%>SCp_0v@RlC8y0$F-?4fjE>+955fmpfy<+U_F`^`}C zFu;yy;xHlhT>rVS0A$LR#hZk|J)H{{8^*sRco`Rgh(ao;7AVO2{RPMff1)L^lo9u9 zn+LGl?|h8u1Lk`T;1Qb|;0(f9(51B4_1t%|r!vB&P5B485EOc!(}s=uC>cx*{K`5A zlABF@v9k{oo!cL67G4;Z7shz(p(^SqyLSyOKyYy116{LEXWjKvHN0U15<8%bh#cr#j`v$jH(*Z@0A zRhr6fq{_j#UsYN?f~%?nHt)4N4z|C;i!1fIF}}9&3n0u=Pi2S_u{! z8$lGUATwIWptbE>rfS5#JP*vLUu8a$(ssh}4)(TPowBY#3?iL4LEEUO()FX>xognw zJWRh>!qF=<&gc^w1zA^INNe#Vhi?FeAtOZGXnkpA5L|0!W?9=xt-kE=^2y5?fMK=- zUi{gvkc#iL042+(Eb-!LKdugBYQ218#Z+JEP$q~NpnwG}^))Pun8y0PU3cR*ydlc+ zI=7RhDWWBfSfTR>PFXNwqdOv7AYv@`v%qnuvf{D6!9>?xRICo=sf{-075 z%JekG;lgZOI|a}L_I~4#*kpz6r)hRf87%uHg`uYjL|*a;4q>iFALo~F__YHAN)fKQ zkf&N^&Nant3s0F>~*?Hn|i__;3wIIMa1 zB&)w#n5Fi)2J9F#kdyHim*;#>PKn}JFB)6~wrT$U#RuX<&JQy!o?^u!o+ic?z9*5n z4)K4-1$|^Bitqjz-rIw0u<=w*geQ$5dOcGc7^GD!=ct6(;zwH!s`)WsDWIIKKu{g` z1+dz&A?RSzS4=x9PvdX(lFL4SgvmMaY`*9WF0Y%&9Cl z&zvUL53|5Az0tdO?+i|Gw)-dXSrV*C@%MR#Mracs6U$U?HF3Bv^6y$L`fUP}ycYpu zfT-D6FlFG$vy^;15sj@i;(NqcUml8UB@}i_Cu3~<@Wm!sMC)HIX_0ct=tbQLm)#z~ zR4KYaa~7U0pgzq|^`a-DZj`(!@yXJAb+pw*r* z(S-qF{Z9Vfo~Q|Bt~Uw{wdDIbTiy+<6?dK(-nu|?)~L`oby*+1G%48>u7L$gTZ@9{ z?qU+-EVnRO1><(m?z7og;Q4-^*qu}ietEC|y}v&P8mDcG<8R7~)V7TGg-@lb9M(0C z8stqHPQJC!9NzDXAIsmx)#o@Y$#l?nJ)#-ZI>bNvl=3!a^ ztae0HE2$=VyMF?EwFRmRi~B5q9rj&jqwQIL)C)n zt@b>yED#i(X6B&XHLst1_JW>{mUgkuh54&98`wtRWdfiguh$yRe>cJLQijpdOLo(X zxlh38=Sy4)glCNbzFUWTXMVx5n|uX+p8JCdr~kvUoilm@K5!09?7#x2bX3`1Dk@t7 zN$J3&%f*0D;T3!$q{)6?#PtI@BnV#%{je+dOkQ4V@p}i{h&5DAhxMF7PdeUMUA6w zQ|9b=yCP3!aIA5L{tBjsNaLn-L9dBCo~6NxrM|Z$YkA>Y%4eP{kRSm3wEs2oVULUz zXNL<3OEsvYYwJr>Ya`i^or2Nz#U%$1xtbi_z19Ey_lMykCKj5T;}5BB|F-B~7OAdl zom{FDMcjF3UZI~Gr`1~TbYylvELxR6Tomp3PK(7On_dH@8*IQ-ybr%_Tc7Me((6n1 z6%}gR2d#cJop5H>JWm=iRR%&;g(m+F0~TV=&d^ham%OI(gg{zCf!Sb2^M*oHX8Mv| zG+EP+T0M|qS{adyN=#F%iWdm>YIsPd(Ri6O)IcoCJZX zP-I;prD&GdlhXR#Qnkg7AgRZjcfc|sjRi$R-KDRY^4F_|*iAdijyBaB2}!OUFYZ_5 zXA5zJ><8DE)U`aq$Rxv?&CEZtcnx;8d#W1yyBStJHk?%BJ-_hc*oWfab)Js?Z?+#r z5@tM7PhG{assj!ZKX123gv~$?Mx55S4r45luCve9Th2}q$PpbgY8)?6>cs&Q?LX{x z=s2NwFi|qycu<%+I!EWSOu$pYM<)xkD)c6v^*4`W*sZ(?7<>NjUqFsF%t?3L!th#~SN(qZJUK-~Jc~0*V06IZtk<``TsbqhBb>|xHq~5R9L7SkWt?%D*kG_SbIEe3} zux$sdjM0%2yV<4;5-bXe40h6V!&AA}bF@EOX0J|Iuc68(EL3T8cpl$=RK|rmFPP=J zBgu|i=@Ud-Uy66Bx%o30Zgv)i$uZVTzQ7t2f z|K56m@yv4hp&C$KBEZo7QA`pnh>$PDjua?fk&;ogbUVL*~Q;AgY=Fh`Krw|VwU z{SBma8otO5CQ^#*zp}+G}~Ne!8?eYRmX}A;aSo5_omL@W`zj>YOK2!}GXwy`rl@2~n551^F*&Er{R2=8Sj9U|QO+2Xu@) zc*8j8a##iVY|g&)rd{4rP`<-Azs5qPw0ED5BL9H%Rao(JxKJ7bob!VNiX@nokXXm@ zs)Qe7lVU@cgt9K)wJicsMYuyRfpF&axB6i@`38QS_cuGw%#M5c~8 z;U+Plo}$o`BtLP;>q6ZGN}+6RwOmH8M-JpAw7%H(ecgv`y9U4sB*Mk5Olh^CyOc|6 z?ReD!5#p%wsno)Eg7-j}O-TPLhtvEGoUq6}W9>UQzGOHU3q$M9|Imknk6sf{NIZlV z{xc;F-+&rUppH85O>@|=;+{0XQxNT-y)~E$&Vp57W<^|i(MSp>?lby?#_(UVNDJP3 zz@%fnWRcc7A0at>8j*{GEiXiY>SGeZ*Yy|`GIOHAkWMkMk9d(`R)w^LcHA=OA)nDP z8WSZy{J0qIljA7%JpR^+im&H9VLg<>M5l?0fP50Ir5e|YSDQ;-m$gVBKKvC?<_Clb z`Fi4G^w;IIbTXuW5Ij4Bo5qBf+|WMGnbvk#L`<=U6xn$;B~|BAax#_-!f-bvpUp8= zNoX>4B?!KHC4R+0TiMO|AsVz1mV#52ojejg{A+2{Gt`5GYDDP!Jl)?oZgZ zD`->I<5~2hqJ_7qq{M=JoHIbgFFZc~a+=IrAtT{#d+odwDg!FXq2`lugbt_z$MyHg zk0IgOEzsHx)e*%0I302z>*dZVE{Cps`$7N~f>|zrI{ii_2f!JQicjzB*vy})qAoWV;4~hp69e~Fyj)Dl!A*>0hcK8yg z5~_m6f3$zMRxkh%QT5>HVG-#MY^<-`*Vj+xd;HggSVhyLkM4#}2@gfdZB#wHxIQ0& zhNzKDCXERjHhl+DD*@Kf)LnHc<^FJ#_SdXBl+ZGAzVIsx9GJrwrh2({FBw5@C2O&0 zucPG*$g9X~du?+$7D=VGpwVg%4?)|+b$@k{+^GYT**JfN$~*rT z`NJ4Gei#i^+VUi!L4e{e1|nTlN&$l@mPtSr0}NSs-6x;KxBIkSf-@(tJNm-x2 zz?>Ik(3Y4%T*o|QXw9zc8`onK_L5547AKhRg?MQya(UH98PsKHsGnUnBwT08_xVrJ zd3kmVd(P|%=}GeP^WEi6*kn}^(M9kFPxLtS`3<&;YpBz+?XV3FPcw!1%tBWVi|9}9 z8yn3oNZ#Y7|Bdg~vEkg~NEQ&GjB)BKjnwhucvZ$m7D~jiArahLcOuI%VJ>>bbLn8y znfAl2*-qMQRdA%?-PsVFG-9xGN^Y_!N~k9?X=axaBqdGlXBEEVDC+ubRQ<`c^bj2`Dp zs`l*dv04-EmhK*->o|kET9dt7-@wEiT@w*HhXI)_2HP9s1SowO=r8F^YNGW8Xz+- z*?VT!;RW9?Z1g;-nW>&UnV+F0eHJTZ=WleM#x#XrJ4wY!f7yYKin#NptVOwd6Ck9L zSjO#(`SV7(&=4ye{YkM*qFw=yUiBNO0z?<#jl8j zzkI{>W#oV)(%nZ5o8OSxn^b?7kJ$Lw)JCOol6Hca$b-^qZ}dNa2+HN*hTn}vJClPq z6?V~2=;(2WWbP;Tiya%)>Y#P(b~k+k_vf1Eec~qxQ1sEA0;XZ?;pcap$p`1ezUP#U zbWCg2#mci~pZK2y3AlUAuCiZA`c$lD4_iAC696>NuVX4Hm*bN|8BOd6%s_eyAmd;a zOOG=Dg&n;#?f7tM*k<(6=B|3(H|#)%R`raL%~VobKp`gk(nuThe(e|Iw?M0oy}Qo} zI6)b(0fBbQ0htOwa+9$yBBj;n$>Bqb7C=zl^hMBZPn)gSBqi(HP_G|UWGmq zk(0d^3#$HloXOfGNn|F22IU74VuI3VB0vJqjF^HgL4ZhL1PM0+6Kn;=Qdeey2@NvH zEcO%e6Jmn3`UvTPwWJY;NHYZ%=+eoz)bb!h1$FQc%>7x_rPN1EQ+Ne|kdeVaI$ zVorDMv5mx#0?l87Ou*(B78ipAJg1s$W6X84Bc8RFcUIq+@<*Mhe)fxC{Of z#9Gx&brbbHivsywzRA3r6P&VXlh)WZF+-+1xWZf<{w5bR*QL-3pMLzE5}k@*#_ za~;x6k8-MP)tQ#Ue?^49%!vr)r-=d=fx%#vA6?X5Iq_DKolF_7;(rqQBw-DP> zY{j_p!g*R4I+dc_1w_@Vv361+2ZSsM$OLhC$enU8X9jKJqIeRsZrk@9j50hTe}PCN z?gtb9=B&#KOnVw074krwZx6Z8M^0$@r4}xugM|(w;ivt}yEzQD4x&jgpVnfyLo z|ArX9CsC(##~{&nAcrXeS`-eI8tR>e;!htwZ8-nJefEL&lVv17N3&Po5 z=e(@5Qhp?*{rn7IYF68kLB{M@d*y=ujfH#41900uwFv>@Yk|!}N$?veyiz- ze)N|V-~2){nup}yKC`9YmQB6RqgA1qsPoo#nF9rj*q)EY8kV-bIX61K56*=8!0 z;EnZ1I0{q3ds9ioK_wy31GI?_O>lngOuL3iLX%dps*)tv`vSIJ0qHf}ud^pY)Oe^R zFsYQ+=L<-p95?2%F=T?Jg|%(=H7JWRu)H}%VevGuQEP}|kvr0m@ID@bT;oSA4Lnp) zHeNGYg9jyDXtCYDZVIEI*<2A0GgNa>s#9`)+v#^!N2}fp&4r_1{Z>({PJxJ$UP-YA z$sh^Yi;7(q(Redo^>nZ`ZU+?@ew^yVj%6lTW!8_YY{c5prE?w*6Zg}Eb0a;E_G+rP z9^6p;4?)ie`ac%ed*RKDht1xOci?#K7JIL(pJq1IUh+MS>-;}Vy#-X1`}@T^bjJYF z-7O_8IdlprozmS6QqtW>H;9tb-Q5aGcPI@iAo9E4@%-<)cOB1K#yHNrGxN^7pS}0z zkzgqI%vS^EF}QwtAO)X&^?WorAFf9N^+=8#(c`tBi=Z$GhF=x9x6A)EbbPq(;kgI$ zd9Wh_e?ranFu?T=$+GyH&mw z+ugz81_2G(CmSud!DtsxO7$1KBzJz;tl-Eb^9*yaUx$6(nygHv)+>65n6W{C`W5Yw zlBIH~5}0+zS{A*gNGnT@CLxiFB4`sTM?B$jmoW7T@Xe-J#L14{tqbA*dr8~wO0f)& zG9)FS@oy>shh0~A92Zx%CnAnFpI?Tg?mj)x5#eY|AXk6}yJ#!5AH=9z!auZ;mEVim zKMr&2Z=iD~{L!k>$7%DxNcc8qcZtpj1zs`L$Esb$km*v(9kJ!#toYXGGtSh8^O=1# zuQ>js8}FxTN71^xFnWD-^ZtG(%}o6I6=HLF47fEAU(a&gdi;{=;N{97DmEY_ruj><57oRW^h{cXpeC|1N2P zzrRQ2iCyspWU8yHGn$5~pul1Q1-eX426yvq3e9*DYH?lBB+;;pw1{1b#4mp*h}jnI zvWntuiON$dK(Y7t^2?O6j4j>*B;c}67-Z8lvU_?VTl~vGJpc4M`KjI2PUo#=KN;9- z>5y{uXThR!BGW~d?i&pN-x#@75%>(&Q?>NfyL7F5auKTmCc~y{M9V`wV|rMO@CBS2*;$p?U1mQtV8;8Pi67ZJD9bu<(d+>rMh0Hdz)3yw}&Qky!v0Z;r$L*u^-V|&2xetvuV+ZB6TN=nL=zF#K_rCAsUELf=bfP z`kdn}kx~8x!=ZYF-ZxDQ_%!2> zcega8;eP~A|BIX^VgG)f5#B>hA&GR0gdUM4Qqje)dExz&GJ*JVi! z9CUu~{#!6Q@tKYVIrNB8a1FWk+xJ~KNPT}9P3qfe^chtJp_suXF9$%ySi3c)`(ere z5V_Z%t^r}2828pUP=aXswvc4)x7~g3o6Bx&S^;BM*|d5$D*24?w4|&G4MVORZ1u47 zH@44VD{0f0h6zWis;Yzy#=E_cq3Ip+z}ol^6XzSn!Fca%O-l+lSjJ<|l72A9 zzPm5U^6xze+_U3$X}?7G+r@|ToVSDvrI*`4Hd{ViW$SY9PzWtKX!FSuVkDqVp+1Z< ze}S7$*x?D|8|8ADe?^W7DW7`bQb4WkCnt{Z*2g8}S0rRVnoNs^A4My6X8amq#q-TLYYQYoy=C5j`b4^x=vkvLTq)>H(PyiQv}g#ee>6)=|1QvG z8SMVjE!_RPK$XRtec06UHs?ityV~j!xlx>Z_ZymQX}?)0Yo z;hG8y#s|t%@v(^@)im9A@zV9o=lvw;uKcoKGJ&zUtHrJKQmQzj;6BF~= z|C~(j!zsP>CC-zh4sT(jUv*Ds?@IUH>p%-)|ic{a0@v8FWE!>3z^|??T>fR}l4rryw_lye?Ng91KCe3k>7IsYLJjtT+6t zoqT+ghQ@qY7#=16JU2`xJ`GMTo4D$?+P5V+kR`YK;GbTr9&ffTOFKN|X-pD9=i{RN zhiDJ2)urTR1x=`aWyxoxm7#S!MECjO>VGUA$M)c@3Ead1M zUiJ|t9}t}V^flFT%Qhq=0)a4FJ26^#FDP1G6M-v)n0HYK3<4uaZqapk4F`O z2l)zw6<&hq1O!r|lr9tV_Jd&tyz=?1J^d4}?5Q8X+x+}b;wiDB^B^OfYxxzCqLH=Nz1*)z!A(@N{?I8X;*JqYn#1?sRSZ0+>R*%-K z9Dz{92un^F8fiTH1Mi8>;WH(=oGlM1eglP4)jI1h;8`Ci_4j7bb>2(VH1_HsmyHt& zGSjLeh{v9rZsg)ZI6{RPuZVAjG64gRgkaabH(A@|4aW`8u9{}Z$dC|h z1VPMSji`)cMHo!U9wh=fs(+@nJRZ{^Rmk%4`{40|YejYtevG*qD_xR9o805!Ec$|f zsnP`?5TE5LVF;{bn)B3)=@Rk_){8hkQQzyF?%4_U^%Tu>>&@ooxlx7^_1c-q&vXB= zjS$+yg}1&fM7z_{$rN+Sdsn1Hs7UB-<#mXd>*a>LqWyqt;32w1q1K|ePxUjl+LNoy z+4mhwYKawu&#^{z)nLtsIDLqYPc_ls5urrdn1@30+0nPhdS9=hA(C*|sF}_5$#;ic z0rU!bii?F;gkOTu~<}e?MUYLQsE%PmnkdyCTKkK)8w;$Bmb%xVj@znijc! z=H6$`%+HS;%o(&!J}n-gGNwd0vo$GR?2imAhNdq{Gq=5^`2eX*L$YO`7^Sa^P#2RJ}V&QUV9H6*I5bT%m99d-TQ+O#kK*yP{4_e?qam zQ*jF4v1Un8F5n0Zd}}-qVFOPKpj)+v&F%R(;T7k3s&cycY66@ro{ff}nl8zgw)~VU zbQ2-(o?zG>+Oq`nXSX0k8d+fVmxdI@r&$${&&|VhEUdYOuZ#g6@6-cV;%93=xZE4J zF67@n>fh6K8m}C>{Zx^2@%?s|>lxr37Nz zAhH74ns=>Duk=m~gn(4>zrZzc@7&1zi)9x^50o*?1)R1%S{cj)lLTRn`@dsXc zX2E{o+Vq6aK@a1`+(1&MAyX}RH*&ivNX&hIc|B1Km047E{F)^m29F1jKOW?z)#?lG zLereM%X~LcwYQw?A7`TXX~QEM4HM$pbU{+Tl64OqZ0pq!>cC`0&-K;&3o;9h&0K=G21Fs8Qu`#2^ zf4y=u{Cww&8YviQErDeJC?`2yma2kvQisqIULKlm*x%2Lyxz@uur=PA@y0!@e{5a! z8BnU9P!iy5GIaVLq>rFack47$I+M2$RyhGcWmpbWmvBW`rq*NX1-c2}bsn8R^7#4B zDVaTe4}^U1SFOi=jA}u#^zk5B@YNhBQT_EZpFIEYc_rv78;Mx2NMfH_BJq+%Zhh+p zun%Ok&q981irNcl>RvBuPg+b(c^C_UNpFhkaS=K)B~-Om%%Hca1cP>Zp2S5tM`);Y zGMYF^)M3DqmI#Z$1e(YM-W0BQ>QM}X!y*nY@VMk+2g`RW!5jpArFXxz51Q=8N6S*9j6qRlE*Xp? z19YlcI2Z7_$Xqmt^z zBOuD|P*hdsD&DM&BP82| zqJvNA(D0?GZ;*cvE9>j3@1HlLf81@eAxB8YEZ@@fp%x~k%mLWPrjM@?H9YoE`o8mE zHeBrB6pXu+yp0QR|1@^YBt<+>OP~!rGu-n6BQP-N*uD9Cw14eDV;qdMs4l6o(G4I< z;@x)eRK*o_$2=&WfB69V#clUT7U1q8aWy23)j`7&0i-D|$(ulK4D$Q=yWHFsygu8t z+XU0>`SDF0+dC?a7`UOg(fU8g7_wumzKL;CQ`j+}=rnodn_>!|tddXpw%aIuzD&IY z^0nn)QBs4rG=TfOKmFhi%~;Y0Uds4L!>cjm1xGs#c`iA^Jw;vV`Q7j(FRuz;|HSwI z-Oeb;(_;tpCgv|%0Se{%T_I92c-UZE*8!$;mlWFuJ>jK;2AzVVA!$H|hX)9rwRf65 zyhg+eeXycV4F4a*fAvlj-BYY!_V#@&#$hi08_ARdbhTYY|9OQ}x>&uB3d|VFpU=sv zi2L>ks0ndGqg{9dWe^B4;&BDU_ANuljCNf4iQnlmU2RU)DD#I~EYyB&yQS&e%{y#|U-Bf%ctJ+Q? zGEeAUhMibk+~v?@PXXmBj3PR4Xkxqh7!GP?o0ZO+-leR7rP`Ddq18 zq>!m%RJpPIL9!?q{gl`+3eP|WgExE4=fYir#xoh>YY9#ni4;eQ)kwo#>^q^isYJuA z&9(5lLgm}**1-4T56Dk$fBG%q@2$QO{l9$DkEptJHSEi(>$zS2p!R>sC;%>ERRk4r zyK?$IQwMMmLT?(1*QK;7iHqqCzUmG}R8 z=t$v=>jw+9cm<5VxUuZrWIxjtWn_W?Qr+GH*Yno}3ao5|Lz}H-2jxeljM^$##W$8))itI|3yrOoRV9TkhKp`rb_Jxdz{`wGDHS2pC2w`Ha(~NYgR_Xg z6@5S$TgWaxBx4mSR4TECsoR)pwW+`j!D2zSz@s{?bUD!q^cNn$5H_0kUg2EYl%vH4 zuebK1H@*BW53)EjR=S9*3>lxR0^co64xS=gY-);X$qVQEjZEQBRL?ATI1}ZL!N^Eb zcBjkmSnpOkaNb>q7-L#8iUJIQL5_UuH{}l9nT-I3CNs zG@P@$B@o+!kWsot#qr??eraNg0F2|< z4^uL!rKVef^a3CmV4C;Yp~>;~YMi_DeGfxj(){haKisoufnOhxdtTQ?FFEhG0?5Lx ztIr6CS`UKG*Kt}8k>$0(nZGZX+>rz7?MN^KOW?CxnkfRo!g7snmy7Ezs*B71#GkF2 zm)?`L8j_|MI&R*R+owxjZ*WphXgt>c2O(w>W%VpGkP*UXs!RBU*U_86-vQX)qP(RR zg~@%`@u(zhG3f7E3hK=JT~RR+<)khZ1m?f}58_PMnA6q&q;$Rg)yRv9mZ9Gsvg5TS zmR+JMokM06axdn;Z85sD3n$uBW7wozE=bh{Ho0L8meq4Y zY_}U8wB!8^n4+g|2&9-oR8k>KoDfR%54m4G9RQF1W%p;EW@IcOdY3$hak9<|WS&_z zj23gxD2Sf?VT_{nXJvwmKEYrC?2;VhR#Yo)qzriXA~U{tch%n~{ChVOCL(y60~Y!( ztD0LUF_Rl22AJ<(oR1RYX^ylQr}JI}O`Hck`99jVuOc{P=mvC9GG~Lef{$Wq^%mZ z6*Fj04X&}^!Hacrsor)jq)L#?^`}{T!N4t_a+UMT)7H?z3z#tJMW{QsU3*3oV%jSHqssq;-R}gJarQ}(DaG`-!6Rx*htCG|+$Ln4vW*e8 zk4h9BAR(NA-xC3H1RGb&kz_C7=3`KZ*-zhjdUK{1fe`?btq@b>bbt7B=#rU!&1)fX zRNWXH8kEa+hyPq-_-6Rp<9Y`UBgn2!)1lGcNMp;IeXdOfXZ7>-*LSO4a98;;^>1 z6Cl@%q(_+YiM{|L?Wz7p^LF2u`ZoEPtk1+uT-X>MJF#DFQX-hQ(6xHNU68 zqGV;Y$-H^5JVd2eL1ykQ&dUAuX~|;w?0!;4N}_=3iuwE~=F3`TS!~86iXQ?`--^h} zMPbOGSY%mtn*8Hc0o^}e!eJ*dsICE2KGylq4+@Arw+2A;T5p8+f)6JR_&7-FL{2|; z@yZbvg{ICZZ8MW=o7pFGly)PR=$X2BR+`=G;4wrVX7Gq7 z;gy4b|Mi*%_K>w8+#5!i@K(crdgZt5CvhYq*ENwaxxAX3NJX?g+?KN!LM`9GnNMWjsa&5Hrna~;j|8sIYc z1LnmVj&*vy2*JK%NU^j&A4*azIFtE6=-mP@6DH1CHbMqeum>>5`Glw8M?JAEhI!1F z0mn_SKgW?I(Py!dGAd;xCRbH7T&5S%I1r{3ksW74uDYN%U#V1#%NN!KMi`wc=pFQVAm=PV675!~+v%ZRG~yLI zC>7J-c`OdtOxZsu?8q{zv>ZGzjWibo92_RBZ9+8yzg>Wi^41-mF~DO}vvr=G0@{$I zn&`|&YP{s1AA&r`H!(qp1H|h9ss|*DJ_-lsi-9`PbkYNIhk9gNV7@6qD;|13oU)BP zx!@&mSBOWI>)oMVnZSBhT4TWHcW*y__@hc)%p-qNVxnz~$Y~aGx)&PmKY722Y{U6mcpYrSB>$sU;^E(tA%Z9O^tp@4q zOZIOVh4eX2XD--z{Ccc?|5>6akQ;jR%%PTy*KtyJ>a1r0LUU;_xpB6TEkSsR95}mi z6^IAXwUdGRtzna7elUDwvau;$S?hay8VO7?KV+%xZm`8*joi%m4S?{e4i5WNU6=Yw zkMeu2Z6ufFz>;(8O0YeR^LY-1Upt84VKi>Z-9fHj(b ziV-J=d!fjt+dtt)CLGmO$M5t1@4tl)(`&P!lMBB8!2jy*SOPR(FPiAu$=&EpdebzX z;}S`Z%`@#SE66k<1+0Ho=_^(3xAs|K6PS&0z9=Q2^()g(IW6Th9Iph*xnhKNb!=A*4kxGuTVJHGg8vFg zS6^KaFe;HWD{@sqL;30?baWh&G3i0mA67uFVS>ov2JygZ`_4hz7b%^6`|(EpIa#sO z@C0^MgFUG#$s~(HQtkBwTl&;R^sWht<{SwbqzDRS>t@G8uD9je9-((?CZ7pApU|{| zVJYN81MtI$a^QE3qmVB#eS3xLA&ee3O&Kt?ra;@^Ri`08+gpNJIT~F7s0V}Z@sb|X z%^KbOUVUa7)|9r z(AYn2hu1$cfX1Y8Mvy4TB7(A(&-214WAgVc>bJMM2ckcO#=cvhg8fqv>zYEDA%OQN z1u=%kvkR6ne>h0t!6+xFKI_BxWvg#nNy$Gi=v_R%?UH{6mtU97uW5mIO~nGIh}A{n zNzWV4+9ZL01ZaFzQt^af1?}_ie~-a>l-wP!gY(X=U{HpDqjN#&E3Jq864+k-n>cU+ zlkZ=!RKZ5|?=!$YyX!PYlh3}ttzHM{QADNR>xHp3^hqEHY_+~qGV8IdzTbLbx7u>B ztP%eioSmwvr<-n{Ol|Tmg7pD551I)SI?Usz8gNo5t$64bi`)#BNt`cws=KP!{&U$ z5MsYf!pldrw=L?5ZtmSRDW`0h2v+Gl*_ML=pT2iCaNsiXcRm^Wl`gm6$4dfjNq*Cy zTpPvM*h(+~SGLcYweikmw%u*aj$j~GJHy-{5Z_; zg9u>L0KKcVwOk`ZBST~~z=d5T5`Q=R+;qI+a|5MF&DgJbVP2o^2XRpHNmn5cpGJNy zBpd5uI#yO$iKYU{ZXNQYbT*Y z?^(!h`#MSEA7db8P}1nVQRfXDvk;YM>TIB3+qfp|KNm~ysQl|&Pefu#DH?%rLi2f5 zky-0^oSPGDgx7Su_U1~FzwHcqww^|sq5GBLnd9oIFn-1|J2%21+6hkd)LAqH4NEYg6>-o*2J^d&~kh1Q0A_iTu5&=eUAa z?~cUIy%JmYdNrgd6_L4NHdKSi?n;sr7c^eaesqM#C@cG zNriYZfgeKxCJhWLT0a3>`-;t=0j9#*%o7v&JMh?C*TRs1k<14G-bzCt{PA&pjWf^w zCQ#4a4Ub0JB*Qew;V(;$|HrPXW4gCkVIWl7w0(Ma=sbi=5%&~APeS!kdtdJLYY%6H z9HEk;FwPIc6yZ+KIK$Rw>*RW?<$uMqFS`!$erTH)$=6vLrYtOGBG_^h) zse#Le^AnZy+i+GY=(Ax6jPR`zX3OhRzMA78i+I5sU~o|Iw3XcI&|SPAqw7^yOb4sl zQR+};@>Pk}Cl!y0c-E$%XP>xHw0?z*yJT7X3D7=4dpVFl5I`apJjG3D z`jcwG84FMk;q((Y)iB6*{J;*RQx*?Imq8j&7p~5~dH+}f$UxJ)IgcIra5y&G1<&GS z^$DOPD*Oi`<_4W9UH?_%R-vsEQAZ%v*LD9(v}o_W*}1Z`F^DjRvS9S6Cr};J2IcR` zl^DM)SvfImOMzOt=HqOhJs-kCt{-a6EImpQXHVG9|Iz(R_tS2Vs|JAu*Qok{N;+q~ zvJNCeH}+G3IVokFrRq~0q!)X(ji#(Z!R#8aOT{p$R1xT^Mi9f#4Qt;;sIzF~Q>uy` z3=YPDEP)ctaof;A@p9(7kXVJ3r53acl~%h*8{&nYk&vnc=5`V~juyU5L}sq|WnYO; zB@(LoA0?l(B-+HsBlmM6Aq=DihtQqmPvMHshL04x6}shP?12pj>Rz z3Li@`|D5}}S@l~Wt6qdWek1ciQUKL)T70&RVpsI@_sS5PZzeKQ@+^t(wr1Wa$r)&bB|)!(K|=NKJcctG z$yq7a)hR$j@JX3tUbu22W@8QI_B-(#(u^;ThevIGzWKds+cwBSh*N34sUSjSOXobO zsX1;Y-v=G2FcZS(S;P5`$+ntQE<)v5d>j)!vHHck+Ln{5je@e8MPxgliXq_1kbo3l z`}cin+Zz83_ zyD2}*QDtAFdh|EI4|=VG&RKjc1gr*Z&WKGm#|j;Dn;)~5a>c<%;wX&lTw2+NG-9Zr z(Hq?@G?b9@b*3yO3>5Q(sWxH7+Zq3^7Z4t2UH3qF|D2tkhp5Ri6x+&#`92D2XZ6(u zqwl=zYeX@l3U{Jzf@-omEJTTHWJT@IOdfSHyfx;pSxonbIb28oBV|}JQ9OaKu3zwv z4blQb^euUp(o7U;*O-4}AjrpP0X7b1So?K31vy~hSY^H7F~D3mmyd}?F0xd3WRyw> z{nDok%3J5d-+{M&%fa5Q2gx1Cm0s-Xqs5R5>G%qw^SWo^mCr-6+tcKezOwaVYofD8 z$7_967tj#lxWhpxGGdj`R)MC65VT=F${KM#zxgve75|PAichZ?0kdRCZ5Is5byQ-N z83dJs>Wd9Pu>*vOC4Iq7`lIyhe8D#egZZjHN%>&iQATu_CJW9d(45A&ib3HYhDk+C z*r_;rRefe7FhWTUtET99`NmH^rM^lu5<)t~Fls`J`dmv2Wf7k*2LBnrT{kva_j9HS z4L{V}B{1@V=)=C{wH?Y*>lg4d^D}Y}l$`_10 zkJFNG+2+I`-*SnDR5?}QbdtX-iJo&*%^{Z}M?_Lx1y0~Ef@jJL4Y=q<1vHQ1kT6IL zJ*kVKtxuagM8y+j9qSWwU%yPKi%2Wu%eb}`l8D05=>iop2N)ldU0q>pLr)Ho~&CqS=?kFJkN*;?#)6_)$~6{-^2?G z-fV@$Y7U_=58MuD`LJ*VJ3GBO%C4CW$$X1!wkU`I{b+on!?zn;#}2l(P-^+qCIl+x z1CYkE&!0n~^eoGYJ7L`48;7#?-$CyUiMbo${5~N77%2jiwJ^pov-BzosTw9!;mA8X zM2%114*v(C6n$nrS7}L_DIvS8;{mQ&133|AU_Ig2#HP|)fj^r<0)IE_@btfw z0@r-04G?c>SYG8xXoU4JRCK^WAGg!ElPw)!ivw9TSQTLlQlfCW5lCnzVS)-Vz}{lY2i)d^`; z%J2HiIHyend-K}e>|BKB+UVL&IA@jKFMn4^5(^^1boxD11>$#K3L4(F<2=LcnZ^a3 zu4?fgkz>28jY6s`+Gp);RFY_|VO$G8BsM0(xBYA=f`t5KlB(vK?U_dG{3dJk#({WSUom zh2NQrCJW}R-!lBpMg82qZ-56-lji;V2@>|5F&e8+o}Jd@(`N{NUzYM{#Na8(#)3P? zK4vDuCy;fTig))WeZ2*|Bvz=AyuQDtC#Q}vi9HB?<7;MvfSpBiDkJD8()Du)b3GNl zISM;Xn$e$E8~e*xMvY{!!vD;fpOKgQ*Ph({30`KUH#z9rO#wG-f1?Ah7$gbH`Hc z>M0><)=W>#491ZSY&VpChWfOoLvkH$ZYXb}kOd?xkeRBty-BA8>)!TUj|!R-ii1C1 z@x!C4nYtlgbP5fgka<3IF$|8PDGn^$H@DuJW8$j{StTKqXJjT;tmU(5Kq-3=dZNfY z-xA+7c_U%;d|gA-3d8g}cq{QZ3fIKTQRMWGJ8!TybXM-x!bOPC8+-J@ls$mL5UeJy z^as1a66+W0U0-k)64qTxhCeq1!!Mel{S0f415prg4yFup=yAM7Ydon1VVJ34ffT&> zi=2Ch|6}ohY|EKHJmbIRCBablcFOELGCMHe0Bm{zbGAxy@{a!tUtbo`kIRGb=B0gS zx6|dq%ODn+&ZSMnKn0C{8NM^aHwf|10GN9c#9#(=frWL;YJuBSQwPL4aIAsD(y+jP zM}@nZJE$inc>ah6U4D&$=f3)Z2I&?Vk?c}3?u0Dpq?3ch5qRS*aFE&}h@Io!I>70I zf10%6=cHhUmp0P#+n4YwWa)V@5Pk$>* zy1JPU?~%NFrF%gy#G^FY3pw7&&hl7PKWw@XRx;K9@>!hPq=zLIc-(!k3h;yx0q$rg z@rdYvDt>@;__UaV?~5VGx{rtVgNM;fYm!qSXweRJY zB8$dg6#jzQ6faZc+Xd^CYul9F>pAG!vV{Sk~1E zlpe72uPGtfmI#Ly*!Qc09ocU0R5rytAyWOx$ zJ{kezfp+ReDGfR?zb;PIH=i4QstO?>U?z0JGup*=6-m73(_NKj z5|e(PoI=;knq}w04p;7TM)br?Jn^}UAj6Z6@ZnA~2E0!5$$mFLrh^>=n#e9TJ8xnrJQY+GqMCTgV&jTfwQ*j{cE2|sCeW_mxu&Q#E27`yKru+o}8PiG~zLm%g zJxwceEmgqPpV_dOM`t%3FSp2BohpINFuyhK6e*&BVmUEa!VENx>rUb8d(g;Q?qADg z_75b5GV@WAZ7Nn(7p+Z$CkDqWen%=y>PQk@)6rRgc$kh~Z@>cpA@sqfIvx>j*-V7U z{SNPZq4-3}mtXSs6ldPXjpc1<=sw@jc={)09WfoqYZmOrt>RZr ziAsMC&drRHJGzoRWtnfn7ZLCh=Y}~Y6cV~vX zuj=w|%E~i4b@c##!fb%-AVOy`hp-?^;&(|sN)92M++&-*-AI*-hN=|$MUf!P3=L-M zM^rK%=HVasHvuBcV6dVx=H{`V|32^&BZSpahHmS3t-|2hhfr3-3MnhORn0}jz*1?B zy~}B5)e`}y^r#m35+yb=)GsbCuoCU;F>pT_YumF-Mq?OWkR z8dDMg@$WbP`F$~J{DErK5S$?Tz@2ueSLBHQ6<7PX>TU{|t6ZEs5U6CjPl7 z@Wt%3n|c#xR>FX7!v7KfSjHTElIJ6D5QmC0piDfOpSY~mWXS87$~GalL$~B?iI630 z2RL!5KX@yJEVfPMc-G$sEt6Y&W9SHJ2aAID-OPTf+Jar)?9688-DNaS(~wnJuSAz2 zsOb8=Q1=CdW|nLbon|f-X%094Ir-HadrXj^oKKsA^FZ`n^L{P!ms=I2bY}R`=U6y5 zlA4fn3wqiBLz0z|yT83b>vOBK^CrtuSyP$Za6N-NVOmIS|II=SGN-(uQs=4+tvfNn ze%o2u*w^Tj_Bq*XR82#1oONm6`NMRpj@U54GVy5vOD1xDuw|r$FKb)NWAHUxvYVK{ z$z#J`jSR~MK6U11T;F{~+M zdXnTide#)&v9{pfQTm>wyFG_=)joLunnZFi)+o|@J(bx zJ1Zzy)iR7J>&Q>4sp$5H^c}>z-o2pd!#0!ld+oo;Zx+^OMj=UasV+sVOe1>cvhj8% zpiUsMT9a{1U;!#`C-HEM2zjZ81#egM$-bpYiqf*oCfjkY%Zt(dg?U4WZfXu!O`8e< z{*V`LSoB6JOs;-%Oj_e~5wEE5nxSbpFk_77eBY&WmY^r;b>62Th(zEv6M7f{WmdzL z9>G;%GHWp~F^QE|5CdOXO3)S8H3~~?Vxo*{R~hFe2=h)$0HAbGgph6%w!n`3he5A& z{6Py-luF0oW{Au#3b>L+hp>M@S!WF1bqj?J5@x@C@~}^DkF@fWHVj#wwY$QTmwNfvkzUI7c9O2AXClMl=aqtc;qx*_d0!OK+wE^ zi%cA>-7FgW;b&6gxNZQdxH)C@@Io3hAl%lES$aOyH!^JmvEQ0tz%WYU-tZ->|im zHhtOJ?=obifUq1uy?neX|LE7C&Wy?|ASITMPJkWSC`2JJ&w$T1GgyJYjBP~_F~FOx zb`t=)5W_>+yYdzm7D{kh%^WLjsT)sj`ZZ1s{s+W*%qtd!nrAuj(fF+x!YRUFAmGoy z>Pq&G3At}It>}Q6csUg#1{F$e`C@JsJ!=e*`d@a>iSV-VqB6RSgS$I27G>hgCyM0E z!2cxwTdhKo7)lEBOHm{T3<<33|7S#RG@)g^?<-mLvjHccGqh<|!s}0o| z;|7lII1~Xh>%x31KoFiW1@1K5>azZNskSSrfj9Q}!sP#}P*2CsE&?Kkf#>$mzrF^6 zc+tl|@|M<0bO0U(*yX{0a{)GYkc$E?rhcd3;iGh;jCHtz)0rVW8;X`y`{A#^X}jd^ zwV1>6qsUM%A6n|bI}72NICvY*VG&_yQ#?X)+Fw6s0(*Ze-MRkEKspfN0yyTt2@0%c;qSzGP z=_DsSExTq{Xin(>=qi5}Z*(x9Z`Ociyh@I2Y7er`KS7T%==lD}Q%6co<0m)s{vU5R z4Vq2yc?GsCD;p4jdiuxc?7nOC!iRM>izFjY0FY+zW!6_*wr1?p;VU)A7zUka0&ksf($1_vGJz!&Y?ElJ?+ zV8TbYxEYx-FT7f>_u*Wbtiy*2BZ1q*jNHZA$VdGBw1MYB|DHM!lqqDb8ZV{Q?@Z^3 zjWR9_mNOR|H|w5{^;=Q)BQGzH`mkcqjCV?h*({}El9uo8i=?lJHj}Grqn^)d&YQFy0t7^$hcyGLDsT=Y=nd_G5D=z0S6j_d-@I7YbAh!NJI1QFOfz0R<33)=v~opMz%n5{dlSuV%z8S5o+xT(f+hkD{6 z!-jkWkmDlZj{@g6q7pxQz#ypt0JNz}>wpRKh%l?rz>aj6V4Cu|uKnclqr>x7mZ%~C z8?Zc2%)Wo*v7?RH2JQgx*v1cyp&*XGtI`xiGHLfg>rJ<24B&Xxjqi1GT z;AAv!^MO_hA5u?@NiXe#Gn4w@z5p-h!MznCZFGrzzL=wN2%;OO)qIguJR*b^5kku0n0N`Uhu1K^zZ*P-l7Qn-J`V30z3W1>4GGZALEGdI3Big%I1jHe; zekex;d=qCjcAGZ9&4>gZVPUX

;GV;uLgvvHOi@pHhVCSau3e*)=HT=|CXc5Ox^~ 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%0AJR@fEDd@lN56~ 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

^l5x;4+JlU7qDAL0GtYRv`DPWS3ni)@>^dU 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 z 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

2BkIZ3(_$Vo?ctH>fEhIlxJqqeH4&5qn@p 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 xnP8Y^iUYW diff --git a/Images/rEFInd.png b/Images/rEFInd.png index c36919a1ab4290e782ff6aa6e13d80f4b82ee13c..0e9ef5d12b157c66f9d6b7fa31d95cd481e02cb3 100644 GIT binary patch literal 258714 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

o!_lGUhbX7R#S{#3 z$-6;jTdE6#FY3Wa?9jC+188k=77+Deth_NQ#PQ{T&S4(@bO(VGAdl2(Uo9NBgS{BM z1siR!g&FgGx4d9^jbcwzgqNqjjNi`kzrsU)AQVkajbmt+(#kXFm^=5@b*Y>5N8F&vqXMPAm5kbfR2CV450Bbp1*EB(iR>sK|s<92KWRf6CQwGxAe=X ze#Vb^WelX9?{($M(EG0MVuSj>+RgE+nOH`j1O9iihv1K{ z|AY7kZm+M_G{j7S1^kaLEL69ms^uewd{=N3X>n%KU zK$R;{TQIBwt#CkULxSDyjvF@G*c|A(Mh-OHB5W+3HM#%0Q?fpC-+sHHUYqoY%ZVJR zp8&KIag1{^MeNiIbAUgLa}w%Mriqm#Sti(rlxd6hUauE^-i_o*%a$LG5-&-E&s^pt zYAnK>xhI^qFn^{E=BG^tsOkqhG4YRNA(9qavp~!Q3HCWMP>|t=Khe{sRr1eunm&ku zyg8jX5}Qt7+=Kzs82O)Rhbf>UeWLwpG|Oi>oFOSu0&WF8*QFW*sSF_MLKSrBG0LMq^LL=<%>Tzl}x(D+K~XL8DR7QP{_#K6o^^ zpAVXWZ>bza)c?}VA^(@BFXX6E72Rnz;SmgfxY6yzL8iB0@#ZN{Im6|TvKJLmfiTdB zfx=|Hm@~gz<^Z+E(t?T;>4tb|VS#uThG(HyuZ5cDxzhfX`zdZ*7W~6WWvGj`$Qw34 ztt9_^2Ol)P{&nEm=I#p>&8Q>?%##IK0p~BbbOE~hUrGN`LO^K-2neRn#YKN?cYMzy zb|26a=G=u*G)&GG!1LT@#s^gnl<^Ugw4#@A(jCpPt7>M7->9Jt`cp|^bOc{m|{G)UHcdNE` z?rn#2+%%-_gp7D*ct0u{Y4?TM4ftBZymRUGYAIG3V>QYgA!>(#6G|SfdoWur&$0g< z5e}dqWTiwk6yv{lN(!KBt^X-!Pxq?agQ+}3_Mmo8i2vy-{6kH*wJr3sr3WGer00*? z!yEVq+jx`*jG8cpfPjV>YoHPTV2>8}IftLB+|S_-_fujT^^)h$ang0L-vc%Y(4Q0>haqn0KD9Y&YmoF9xxW zDJ!8J%>hXYeH3Xgd_G(+2Dk$&IiO!Jk5`y#*g7UQ==kFezeGJWZox>6$eS)tb3T>K zALaLYJymx(g^bP&9k&*Zf9%y{>TdU}lAA|d@HDaHDd|tE<#oiCmdQz5l&Y0MZ z0zyKmfAJrlbdHbXt+sgCgb4$Lt;`w$y?fIOU$%n% zuXw>s?nhnC*^IpFvC;u4Es(>E2rZRR%O1dp=x79__g_QgXfjGyED_H(^4Y~eG@6S`#+>o9>cb$Jqo2t` ztux@DtOa1~(E~#eIbvm~7JZR3y4o_+%>L- z9MJgJ+T|?sUP*WDS%`cJ(m4nClCTe-vlI*H>RaS8K2C89hFwB{fWpq0@>X_f|7bwIhePoe3*>o~6lsBD_w5x#c0{m&?6FhzMtp zZ#VYm`=}FE@)G1m@0INM5znQ05FzfObdQ*wu%euPsqjDBIw0kT@A3`|F401t)K1j) zoiNau;2<@5YUK{B!T}j4uri55*q;Q>V3@?A+L#IZ42c8c6PO^N9G=B63O)4>asWF@6Pc-sEO5^vAC)Kg-+#TT<7Qp0%1=b`y7c4_?b- zJ&r5;3oGKZ`Vqd%Q?)(Jf8VN>cg z&L86pR(ir}M>Xk%=QOhA!7c_eI3Q|{Ck{waK<~FWpq>04XR{|cRWX;iSt>%zbj5?V zXn$sz|0dQ+Xci?E^rN=&m7DN8jpv1^oK=={&nKm`y4l432qsF(`SZLzeKZQnRk}X! zerN!{KtR7IHo`O-x*_Yp4b-ZkIBV$5S7iciHN&49UNF^%al+^abIB0@94Ss(@j#{` z5nnD(TCLTfLF0bvLjV9E07*naR2WEUq7?%)MqefB?HK>8dH zS;HeP-^3}OzFflxR(j#pwAopKjT||Fr8{k?ysLWLZMyiRCy23=r|F?T`jb{6#_?B} zLOD(#{@B=HfkZVOr-gGnnG}>74JZhn(@{(5;65h|+>uK@N;vr=Cc?*r8y^Mo-Kv8qIn0`F$I7e$JYIrF(E;HZEaz5ug9C!ISPnnA%mK~ddz_8f z?q8!Ch$qllMGFLv*|S3(=h z1wtO^sLTYaZR>yxJ&-~`E5m_WNB>t#+L#xZ1I-*zHk|q)>wiME18YVx>VSj;a^v_Z zD)N&5Q9dv}i5Y%)Q~&cv$}V3AcWCh^GYd#*e?IN{zf4!fC!GVts7Pf(lMn2x@IH?) zeTwucW{=q8BY&L91wA@Nv7SsG9$*IHo(#Vpnx$^g%z~8mqVyadAqQ{U{(XG-P#M+LQFP!h*_L32mv0kypG${N=% zF9rLM66oXcaldb8)^UryU{%hCaL)X7tM6Um8Rmidr^l~#-iD3qr~NJL!+7Ylf`j_% z*YQtBYnnSzfY>K%M)Lg*U*O*Xj{~*sqDMu94C_lo|8s%xLFxKG$N(V^G{^J2Js;1l z#hhGq^TFV`weA51s-4w-E4$+FN+w#VfZo0PvfD@ai^&0*I%wj6-Xj9S{GYw~J(z0B z(i{1U1x_3I@vP{5AFe zvS|k=5~duIDpB0_Bk8O!Gl{g~2vN}J59XhV18Q$`Kv!=hv$7A2lt9$2)Fmg_0iDN| zyE>p{nb08|&}y)Pxr5i3++V2wfeXD(tO25=E^^(%wIWbVLVVx?&s$9hujs2C4N*v$mb)DO44 z&pCC;V+N3e&+N@6F&hEiXU&d%e@_XC8^=QYvmzZd{_^YHd9z6|hpz}z%GjIo%c>PKb#(*~P*a=UWK! z0iE(0?DX|?ApZEeXoYlV{B|#f^k<-KaBg?9#gKJA=xq<&nZi4OD0tV!`>rT@2_tx4 z9`HGgccbt~NuADrF8F?t!K0^RTa*tCXInoDf1lcGKWcZG1=`j_*O-T{m5mt7xAG9* zzyJBayp=EW5a0i|_GXSVUY%La-Ylnj0+ZeZ>SxDPjoe3H1@2~O>$RxrebjXM##GU` z=UMR3#OUyv7#tA%&LXj?OS9u=%ml5IMRo7~ZH;pSK+s6}?hC!++ejKC>mW&+?G78) zeDb=i@;|#?Ftvg2o}38#ywtgfHI)mk_~%_M5Z``kjn&SJu@7<3dppH;0q> zL+}s{3)K2N;P)NzP0l;69FR`V40M2~hp{p1f9N?XXyR0YkFhTp0o`1zgJ_mvDeD}y zKycbX#1syT_DQYFED&R$pJf|=qH zZhGT{5uH>PgmaQTtWR%?@o6-Y{WECtCNDktf3&?1Q{vjTJ&Lt)do>NDhz;Z-Nb2rq zQVj`dTdZ?B7TY|u;1R3&b8KqEX}YC+rQiP>yfx=sYh@(_bf5csq#}s6ZMQNr=9puS zp-k)H{YTilK;N-`-?IG2<=faN;k;4oxtO);#i?gXZRPHXA*hfP{c~f>3$eld$Qo)g zs`O^%2WWxToQ)RvNAZTvp(aS|f)&~82D*q1Zosq0hO%Ekx)%%T5Ax5Dh2hBg7aTS) zs5T%2L_m2jBJ^#RW9@5l*Xv~)|40rf;4`o^3$5ZHFU$*MBeuQvB@;?bBJQZhyI^Sq zBpGSoe(dt%_I@~jp)Gk&Ee^K{==%;Gy594y5V;_EM-8RhOwFicLvyJiKpar>@G#SXjQ&gkvI_^Sqg=3S&SGK1jyv?+?An7JcqGSM zF5;iaUX2{&g2W9zgJDP0Eb01aZ1%su;wHxV_dcuWr2!(W&PLNm&Ison&rP_t=4xpz z5ceiqCv?!;_~*|LFas02@PEa-s0;z^@^L0qZ=zpHxRu)_9ekqEiuEcBi>k{q#yAPh zPa4Z)ogy1&sqjQQGc0HyirtE|O|g~dzV8NmB)Eh2!t*W?Nn;!l1&&{-bd~v6cZ>h2 zCH#QaVh+Y9@U#yP-axGW)Oa@P`e-XBUY&xmzN>{>@3{TWome}DkDI8N_3-%o_)Jsy z9%`T+#6avSRe~L`g|`^H3%t(RZrSr(8+WS^1JTxx$!iOFBF6Nyssj=V%usp&CH;S{ zVlPCFfXHKqw!OAIq4RtXEarEv_~%PiH0OZguZ2^w8D*$Owmls#r@#cw!bJ(T<5>lM z09=E<^{m2lv?_q3@+3Fvqc_j3^RxR?qtx#|W8O|v@;?SDb0!o1{^V83LreW>6gvFBAx?0YTu`5RUe zS*J_hjj{h7Y@O{5&GS-E zI^?6y4&;A~0cCZg5A=Y%{csPyuUAO}#Q7gg!gfm$YFJne0#9$#%Lk?%s6Iex{s(nX zX&n#)fBAg=D*uM}^OZ6Q!)-41Hq58@Gp>Xp2wwBsm?#uZL9=kDqkZ0ESMUW)c+4{U z*2-fY99H`xGahqL+ZBe19@uBKw3f1m(ZOALRM?Q45O6@%I2)C9TCkH*R&y}~0y2M= z%^v1~VOAURK;Qv1&|2IR`Xbie!32trreC-@}eV3-__izLw&EKodO? z{7;Zs)tpWwB#-HVPE+;;`Z+ta`{%~fcJ}i&`MgW0e#R^G$mH5*uKsaKUT9Vy z9<-{fpEtiZ83Ou#xQNE~1AU(@-KjoLIvS?Mv)}%cHfs4rO3xkTgxw*I&*gCC6!6bl zML?ns$z6DGgpN6&k2^RZc}A3(l1dKrxHq%MJ?eunvao^(9pU3{c6nEQStibk^wP-g zu8J8Mr|-i+vF8ugAjeJl!P39U^(&1;=T*t@0qTmH6W5-0Tk4>>ABWflLoHC!iDR1s zIspy{>kZ7|TZDgT2Lm}E?!!Sdcn4AliT@$|<1$R=xzOjsKA0K3ki$;Q{fHVA?|^xd zb&e4b=?C}a?Wi0O;v>L4`JHYYf+q@Nlp}EwM?qdZL*pM0`H7zw0273|x-xhZIQnEW z0Jl|ON+E}*b6PW49|l^)Nsck`aTQ1a;W!9z@Bqlk^z+^vp(lkek(phpnaDpaC!9=75TI2&(u^ioU zv?eh?=Y4kdg3VS;1+pB=M^!X~K$VLwI0K!i7)Ws^%N>1C5s<YcfE`{mr3Vn* zA8HQkzzkL=u0J=crZae@EHBXQFu2sI>ZLyW=38p+SKM6{&S@u=-JjFrEf4y_Ay+v& zeS5K(vi}Eg-JLoN*NjuphiKj}=G7x3GyOv3IZ27+0<=)kr)po4@P(4Qa44>3kSJNO@9pzX}? zc7}aS$9aZKd76fWkyBTBABFE(?(C=Jepf>8Q`yJ+3^UGm^FE^DG$aP zK~yuFGdwio3ZU7x7j(=3ah*?odp}HM!N;?*#NHRoq5@CwLffAca@}%Z(p8^b;a}iA zi#Q(tk#^ua&DP^&l5mC=-2Fr#Amo4`O@5YtLJnwFUZ58h<-!L6?!kkSllH|U+Jxto z=J?ux4b4I8_~JS~u8*6!6QlZUu=>G%X1SbE?Q5~eGvu{@K5fDj&hBe5_rtTmu=4^R zFx-QH8UTF|`7;+{ALv(hHJWJ8=x2zy2PR$9-m159_|MuUlw;DtH9w|$M9RnT&%pEx z?g9B#{X>R-Uca9|mK|qdQx@4|LJ$3wXJp)+-hKGDvWc3) zKQM*=s^r4&5Z^`4gR_b}wk9c}SH>W-JM=zWUs?aI)11M? zvwgeHv416d z&+TtEu%kM`Jg|X=nLJuz28O=S3^zy)NbBoWt!iGy*{G16i*qpQ!?+F_RX{(ZzOQu* z%o=2GuZ*|vdu6vx}CemM=mQYc3}2=zD@C%W|xP>ee?EViuV!y);o@6qSIQYy`A@H zfD|4m%`Phy<|18jl-jd3c~`5B@J1AysHBI^aSrG-$MXr38Da4*#wTQ*H^BRG{)evP z$p7Fbs!j;Va{83TT#{4x66z2=msKD1K#UgNO!&Mj98i$RgHLXzdNPM+SgS?g##*~o zE6FUKj!N3YZ55$fMHD7zrf8jkfu>BJP&$$&G(cPTVTimd@LLSG%-~hC!Sv*Efqa+|^NvE+Yn z1EYC;|9hq1DIBA-536um6EomB*V8(@{^Q<&r0J^OYAX9%I3*)rAc29Jn9YU0V8lhk zEDTaCrnuon89J^zrCFD|#q(^Pk;(zVDRt1Snz@{phE!v3VUGsq&1OHUTBXQFnSkcF zR;x)lsjw5qF%Tep?hJIt^WyKI2HoGKy*QLy)ISjc#hG9V0!nj04k>`D7DFyhIjaCE z-iT(e<2zP7+1jN8`Wv_ZxF)IiXSkpHQEN~7{kQQCbYG1|Ru$Ubhd+@U@uwUGt)&j= zAa}G*9l3VLA7JW*L_q914zDr|()Az<6@3up_AQ@)fg3kF+_4FriqPi;UOqw(w+#JH zG8HUwVug9C4R6@}?eI3`cbJWU^6&8_OLb^hVtXUMqjF{3VCEX(+$VYo^JTNIwJ-}F zxM;juw^|baa8Ja6L_nHGvoqaB%@XBeM3}ivyI{OabzPo^(SLq^HX!reXrcmWAUuHL z^WwU2eDX(E?;D5cEXJS?t1Oe(7T^D380b3JMfszy$vKwv3{z)dfPY>K=e+-d`U9-b za~1r2aO)%j%_UTk`Pk)J=2+9bb&k{TN07GV;*5f3Www}$q3>7TbNc0%lBPSR14`_c z<~ln2C$uI$Zu~L~RB7UGKfAu>QaljDK`#2y-E`@!rda;*@fa1go zcID_jD%hvKT|?B(QgxQT&HpU-^F9^%c$w*}c%2NUd1 znCT6aPw+x%{wJY}o+;C@Z4M}uTo7oxr|kO8@BlhFI~G?hhzyJ^PiW$R5COrV69S@b zFi0cg-B+9m20Cb(hxH$=M}u`==f^w+Yyb*GntNR!3L>Ax&-WciZ@&KD*T;I_>AZ@a z_gBv0w6KSnOb!z>umW*Bh<}=ddEhude#NEG0{iZtpZnA46!ku!?OH?tdnD5XSWxmm zX})LcSwuXb5pomwh)>SSL5SBEQ`0*Axq}>#<~TlNWcWN=WU^#+xZ7o280}<0PMGQt zegFI24*c_hIR}IgiO7rx%23Ub`}dC&mCUkYBIw-}fr+)cq9q>wn_9 zl*##s{L4F1r7exZexAjs=1XFj>aTq!-+dpufk`W35x@;ke?BnQN|Ga}HwKtE!Fmc3kJs7Es<;1$qO zIB1mvLLCtLeN9k3REjq}kOK<%3=DCP$yyuo0vhZ3^8~X54c482TLx>QIQBsgMC5`B z=ZD>|r`1w_(mFPL_QhMYLqQX-R*Sq=h5komdhuPa!bEUDfPP+y2ZHLOp$3_CUhFCZ z`8j}m7>04Chm5cc7uiD!5i9sUS6m19nbeU+c&i5S>6{5Z?{z&L-l`+(mj z+Sq~bo4Q)f-yqZ9yr^^=-7cSoDLG;H_h0Y0Gsi&&2Er-W*AK!E`s1Ix0R06dbeaPy z*&~aUmB*sB2;;o=lotp0Ml`LW)f3bA$E;ni;hUPDVxq$AWqt_fWH8C^nSWK1xF=?K zc2t^p?k;++ZgK}zFwnB^s*xwO*ujwb%z}TG-iT>eGNB1-cQnL5;Kw27Uzlyad2C4y z5YFKHpa25ogSwwZG>1GZ4|KzGn^dtuK48ChQ?y=iqq*GwO7>x1l9zr7Qyo`+$1Fat z?v`e6ekHds5*rri%5jyC{h_z2kIDgs^1!OG0KW-#g4Z+aIUTIl#$oh0TI}m-2G|4uOEVB zQR|l`=*MC3xq2F`t7o zEIX6`5pz(RHc(eEuaD?+)4UPv>@3QoLvS&h6wbe2ZyXIZ*t+9vP*2G*5IZp=Drg7xz{U>z{seQ_DZnIDaM?kga(WYZ z-l})oyItK*SJRa(+~yOQ2WLRaQTCKouP2YH(bH8J?wx{N<@4`EKay$Yl`EWWvq*by zP=i<%1>6U&H>`IE%WieDmC4MxAPqU7s*aA!TnVIC^IQi6-md|ALcd5yXcN4E@R9S} ze{Nx}a~FX0y`HPOj*6hx zE6;ovJE?_2LHM%b4hHCOnz&;D8Izcu3@RTJy$vYW&17xVKCWl1&cm<^!%fna>)PsE zOy!P14>SfpAV@Pi|Ni~D+0rerE_|eGE;&_G%12oL!ebSnr zqKbCX-Bc!*oPNI>=ej32pKdn89OEAa5p_A%Npe4_9Sns7O8Ozfi3q4IJ%MoU#eIQP z{Igb4d58yU7!2zm3%!wBsGCQ>GXVbQ5%y5A24MmiX`tb%7R)1d1oNkP@Dwbb=Il0| zuH1QkF|FU?ZMA~!TP2fOao+feC%;9~0Wp8|G#uJ5z~c;uZp8P$W{F)?={Fy{9>yCK z31^_$Rm$tf2%tgPSM}naYyb5Q{H$zVf_|r zcQW-o2|mcCy)ZyN*nOp$B3pS2{=KIE{a@d|Twj0x_WhduTVa1~;yC(*d>kj}MFsP) z&a$&yeycDP)NQws2aTmrA?yFcIUps+9q++WqYl(gy>4f7 zKs>jLT`$2s(0O*v+u}~gpTDj9d9xF1qOTA2UuvHFQt8KrN&YA1eiZ&^xy45B)cqv0 zFp&G%@&bzSPg`<8$VRVg4EMk!tR^$!kGMZjiU(SM8fff_y%}sY++*VVU!VfgbPKaV zbshZI`236g%*Lo(nFkR^Kmn$m&m;D0$Jz`;K-1fsmAje;Vb;t`dO}k^JSlUC2g(oc z>o}CJ)r$E&43N}BU+we)%5Nbik8fvq`zH81cp&txU(o(Ppdi>q>}y&57v!aKB{brn z7HqCQR6{Y>$8FS5IC9{QE>{7S1BYQHpCKS{*8s0+Z2&v)u`dv15VG#90CCJ`7sjDc zcx@fu-#4qa)*^J%Vqc?mDEGg(4*FH`T789iJ3}86-|zF9iq3M;*ojcDL%dAH&GJZz?_<8Truoh0 zvUvd$`7Zn2m0Mw7zy5xQDLn@VS-$lD{z?ewPl17c+ra@jj@&AJEY@MqJt%J@Al#Ow zK;QBra?C|o2Wpr-D$zrcMichs3EUO?h8s1p+i z2oef|E4~l!MbYA?vJcOY(A-_%`wPcn9asl)EsSGufkqE9V4#nWxf?5bKp&q&B2a)% zUH||f07*naRC7}}(jT7Re{S||i~YIt>!t?%mvr-i-fJQ~4k;u473W==1@kTkdapjK zfFoz*u2w6qHH>%K-H3g{*i3UiwzBU9)2P);%E}`VKJA*RP+y;$D0P|D4GIi4IKF z0aY=@0+Gz4kD8v58Sh&{cj$ijEHY^n^Ca4Kc8tzNH_68Vi!%je*wTzN{h}6}agpW})&V z49Ej}ZBCBwJ~vAxZBl4nYlMGZCqfgX_-jmX2kfvzDrcxXPTz%}X~d4vXr;LNMCDk^ z0|*GY9?tieW5PA?=N#y|M(oc<_*EFbF>Si%C;3G21G13qu~P*%j!66R{rfp+p|1-A z%&C9X9cLhS_dBQt(sW?LASa{QWPMmS*Usg{PR8f2U+<2150>Ddr5_^jJ$wfCSIj|6 z9gtnJdw$(dCgjwu-pVb%q_^RTi-yE>kKAM2dL@N-iV2^eUA#|mx8^5#EB-BwPh*Se zNzc6+yF08#qb70Ab_T|F8gqP$H9*7yok|RZ+%wI?Q2%q9p+Q7VbQ`vf5bddhJY_NW!Yk=M z51ODEuRMt?c%g6>njcT>y?d#RQ~In~n&@_57lZm3qnA9tambD zQZ$9+bLgZ@N26JoFZiDUW;tTz!Ttde&_rL*9zH{A5oo6_v$V?P1pka4iRfJpc*wT+ysIwJ zPyIjH`C7g`_e$?}RfyM7A7`FweOm6(JpY|u>@vNTagsWq6C+<}^5$4e9_Uo=gvE~! zBm&Y{r2+1ug?mnLP)dPLj(({BaZs;SqO?<}J#gKgvA!a}8@sf-o)@s+$oc#RF;G zfinbEea!V$KLzVa;v@SfEpOT?G*I`JV5DB~rmYNH?I5N-n&DfM^%2G#YU)XZ4^Q zFMpNc3C(_9oE3t%3u~XJ>hM3^ugKV>XzbGVWbJpoy;-q`W!~vMzvV(7@1c?cv35fF zsJR3NQua}Er-`iiTuyql<~RogSO=YMaLGc% zVps6_Q+~ecIg1b~kir3_yyw+j_yul)<*%M@hflLSfuNb<#G0u!lq}Gd*!T)FcEb`* zi8GFuga%0R({FM>SbqZ6Ts~pfIh(yK7Sj^+FVhGsl5Hs}^2r8O$YK+f*B=d|356#j zA}O4_qYe>}+~mGJP2_(l5B0bJRSITi$9G@5 zlTyF`$|{Y>+!6a^!v{_VfAvx-B(6LJQ>Fj&2>X zmn!r@izL?rS)-9SF|mLS7cmg$m?qa>kOcw;sD-#^;y7BYTk81Fj@9Z+CgjXvESnYV z!P?7Zv2gu1arIo~*vCu?z2HW1n_bKbFb=h!Z%VIHNGmi9b^G(5G@g zth)gO1R0>nKx?f5b!7C~v8wEyFi#bA|gM1Oz)22Jt^|vH}Fmbip|I+SN*Z)falg*=XRzOWaQk zldo(s!2%4#v57m51ouOkCU8q?pviN7R39l^5vYbR=_^vXpVVQKUnZp>yu-l#Z@OwDr!&S@x)KiP`InsN#pwC2@Ea6dVTe^{jvEKp74qH--zS`S1%(G5UA z7V^-~8sc5_0OA@TL_mGSK)eFku;~Tt&zyH&GY_1Zf7V*9W(&N1nyra5eTMWM@c#h>M4cDt2ak~jLR}(0I)?j#k^6kIDM3olt8{j5 zV)f~lrZjCwKj#J2jfk+1a!SRr>f%huMq(S#`m7u?o@qt6mxH(lKPUAyCGSJ06S+TN zlLvn0i#{l?Cxb_sPH(x6CVZ<43=fTTz&_v&1QwkP0WCofU9m=XJ@@tgb8TroR!|## zbQfbE!2x~zzf=VD?<4~9iTmLg2zJ2gn9YtAXk*If@`&n*jo-=pcw>3T~z0Y!o4zZGrb#~()UUe>|7O1_00U|$W&H?2pt9hO1#Uu{| zw;Vckbb$kU01l{M)%DE)9cZ|Q7t$a=14IlE=(gCkll`hvfc6Jxy7M{sV+N+v z@53~RA1&AspL~ZdORzuOPyU?xv8HhCfcLM@&kqY{U%%;N2SE^dLASJiA8L-n^AsWV zQ{=Qq3I?M4q>rJh-Qn!=SmAi6gCp!i><&IZPV+w|-HRi_{5aRdpE-j;_JgJm4$oha z_31lRE#6&YcnEUB&>vcx;8q4|fi60F$*SFdy*nNHdgBy%Ag)IIGxmi3KpfBq?uRIK zKp&9<%2E%CYVz2_wF@t0$;vR0MZSTR$6egdGUcoKF5S=H()y(4UX8|kG(Xw8LV4_& zdqECH77Ns9#~Ppn2ec*}wC28u>r?3sP5#hgCxh1^s6Y)L5+C%9WtIAlMLEpK|7fHD z!aWSpgSj*V!@Muh?y^_o%!9nY8RV|RUKqPVMxHn22}f- ziScUpxB2`&4hZICilg(c{%f|CqCp5KG^-HnJq}_XXp8%q$$hZA?7&cOiL*aUIkl&K z*@wLZK?(XWQvL}1Lo+aZ&*8a*poPXWSa46oXb$tRMd0?I`xB@Hf4cj{4lmSqE2*>4Nf05!pa`S3vqgQGY~Dh<-#{ zJL{a|AvZDf=ivKZ#0y~>rQ~@8=QDP<`5#v(6&=7pa7KuIOO^&soZrteQ3(8?Tap9P zoYFI3pUDK@b~;Ulfi5cD_DQ!>_1pJfKi3+)Qs?L%b%{w0;s1SZQvCH?yog)T?ZzPa@qy z;dZWMeky#fN4uz3Pft(f(vRwo(zx_fnTKuhJ_#fglG-T}bUW&Zg0d@INz4T#W!n0n zg&897|0y&;d=^#;Q7I5&K71Lc@jRU{aBcGi-JttA=4$|dbKKJOo?U7o+A*;Dw9x;s zfKxC;J(L?3-=7~gzug~IN_M|B(5jSTfsTeSpF(c}mvv9X^TZg3^f>|nr7#fadZ0qt zu)W3KH^siYifaUm6!Sg`=22&0Snurd+%&6AF~ z{t0M-z@IEv8R(UxulM)0ilcQgsW6w)L8BicpMrfz=zu=r7=Dj?#t^j7JOeCl!2)EZ z;hMQ{eD0PyOnCk*WyV+WE$(N@&!NOWJ8@8V7yr}Pfqvd~BV5Dxy6ADL&T!60ct3Ax zfYym!upH-rFc+S*KegBsI;ZeISckClqI}z_VvS?;i~k5`bm@efJ8og76-)Y&kQ^sY5!y%%xAzSVa_tw^Rd@D^r7fh z1_-F7>VP!R0rf*Ztz#7%IiO%J{8$kIfxf86^L-9m*Ik1lPp4#%<~hbc2E#uv{Q~53 zPPwW02#@ct&CC1KM{}{5I@5)_n3JOzc;uSsH{|wKF~XTsQYqC2?5|);OJW?pyG4Fv z67Se9se{;KC+2%3_Y);}pD5bqgYfUdyo|?x!4!FC9y`_I3BKCQGq-F-z@vIGb8VJjD2bpv7rDAU7`PH>&4{LFGW+Z7Rd zv6%Cz{~zOiiYceD9aSmePr3)&?$0Fe)5!7x+U9}K4e2SS%0Gy-i9RKKXrUTC4ORQr-=Wg3HNm&T5883L5Vg1Qp zg;;?Q0Xc3ynBU$^-J2+QdBYD#+}_atWczc7T`+U0u1F+(@%!PhSStNs2fL<+ zDhsr4AB=Zkbg+N5=+45x=3CXcAI2(DRRbR z-)9|IYXDkmqj|B>`qh$k2=gu0k+ohGT_MiFL~iQ&Iqk^9tn9Vf(mJ)FTb`8{3(AG0 zv{myb>UzqoKQ4)!E@YyAjydKTbDy4Zde;j)4EY>v%()+%Fi-;DxKiV@|6E{2gDF33 z!=o=g_<_8FAEFgGqz9V3PFht!L*Q-HX<=8(>hfc!(gcs_T-&I2*0_oBt$Cr0z_vLc z@@D-DwLsDjaSH(n{SVX*%Pm88`pecXyqt%zDg@5Zst$U&bLVTgd(K|`yWG#-ZHjlJ zpGI=8D~)|5?^BCEw!?$9EtQA-JVEAJWTPhb!4zkD(nZs*JZOR%v~Qt-+mG(!3?5!H zK3=yq^de&zs3dfVE_%*;<$1t)Xr8hK_j4~Fx~tw62ejCUe}rdQn8n?^>9ZmHHG&Kd zh`gX@G4n$kVBk4Dtd0Qzl}s@QOKN`Nxmf)CjG>=JFsBx5hV>^TjWp<&r||y+`5-?* z6{I8Xu`m?_{wG_M4p#QK4v3Bb^w78y4?09vBiw%f85tm8puvm#xo>sAeFHj`NsIH) zujmwnoDXDbfkV(S;UCtib+n!{oerNF?g6AqnH#WeFL|HQ)Dhf|>x@=h`?D}*@09lV zvA0h-(-J!A5@8{Q_mP~CG9QbSuK_ryJo*mF%-5L80SIWKkNPdK!>^6VBT+a5VNzI= zA)q$k{idd!+<*T1`TpqQ_*3i$lte&ZcOamT905IM?XpAtL8Z@2f&(hYwm@afCNz6~ zWv}vQnd$fQP9}PoHH~k)_t>jC%=Y+sWA`F!6Qd#b;1gOP&H_=r;oi_|OP9eNX@zB{^5Mi*?EG+Nk<$f4x0I5UsYWEHJxBLJ^SC04U_v(PypNCg- z2;5KXQ}z=!yU@3u5{jn4{c=P!D$41V_Z?cS1ds-viaBGMQld2vnj<6ZTPaxvr*F?!ST(`m)f?+J*m@!kl!_rF)sXU;(j1;R~jyS9a`u{k_f7ch0>UTkLWpoB7Gs z^dx(%n)rA-g?VD`hu_!QHJN*nJQXjXw)6rLC+5TFq#qDwW8~Dw{5U;oOdc%q-C(HK zNBs{epr2_52FR$?r|gok%^9Eob1#4a@(=?(dBg|JJa@V(=Ya#dxkUto+cUd5F_|0h z<*yR%VY93Ea6laE@Qkmd4u~@2r6&;g0>VA}TD9ajBlhp9mRz2Rm`~)$XYfFXTEb9% z92gy_CCKXpCSoA=%AW^b7|a$`oPBA}I&na_n^Be=5YE9k0s{TG%O1_#{zNB#d!zNJ zv;Xl!p*=K=?tQxt`krP1HPC|dX`(~o_iLlsd9+}woqY%Bfr@=%S=BVlxz=h$={Td? zQE#~_N;MD_Hi#(#B&=aa?do>TPW>t`{oVckhIiWiZc{AL~wERu$`nfj8T!2a*WL z6P2m<$9?rjm0kVEGz&AsQ0!%-I`_UXgJCj;);IIS zLxrRTDo3P8ECjV<1L~f1bGi2Bp?QCQe{k^a zvT%KtwF&m&?kgamzqm6;A`^piK#v)x0~p85+=LfR7^Gu3ZUnn~?jz>7|82jYcO;p< zvG4wlUH5I=lbpQot2qiD;uwgIb%Oulx$tdO2b9Ad)YCPe!!x`CYD4O_;+!zKmC9~M zjm-np9ZO?aN2eVOhJe`BTNC)l;rItN{4h@ePKWp(NKMDAb;Ljm;DDy!N+y-i;iCMq z2mcTUMA@kS;gJsl%F)%gA*44$E-iNrKve*}8SjM@vR;!gmx$drH zezr^O zKdb_uUS=PLxiJGou${y|pArkh9r%a5$->kD&wG#rf%7mMemBRuz&~2wE|>e53?}m7 zLp}xbq&Gcykxjr$h+XgXs$GK1zj0`^&}W{tW%qZ!t+$%Ejd2XDtzq~+Iyr+Ddu~TR zk?j#l?B(Dm)gO_}9&rUU_C;fO?Fjd~!oRcHj^%quwzB9zQX}uEuIoxO#VRh;u;_ z|HK>+?t=N~x?zFdr|tsU51Ai0gBe3Wo;#hgx3{;q z)7vSzOt4qk&;1;bhx@3rILAWO@x0|YpMQe6)YaA=SU#SGF_biuEOh?n{*PK67-;tX z)6MYqb`CX&_LDG?K2r-MI3Mm0#7{5e{17}}UX)-Xx|(h-Y>g*_ zg(?R``|zNHc6<6{1Nes_rmDT@h?!Txpl$Z<=OfFu4zH21JuVtP_mKzIS><`q$;UL) z+)pHCT{7E3azCcrWhZY{wX>2t7*fleI=L1o{+hHwmgJF=J7*EFP>$)DmceSz^_PEr zfm>74Hv_T7-`x0`0TaIC%gZml$mD=Nsyd(y z4v0T;U)Yra2JxU51>_zpq0yZKp9t})S_Yg{c6Mbj@AdjwO75rmmgc9C^!Hg}qF2oO zB=@~8(tBQwR6WYt!+3-H*`fVO&f?cNgU6c0=U}lWnz*1GS3xU&iFD+;`oja}cvh>W zs+fQE$puKSRv7{!{Nq3lJm-LDlY+B9zyjf(x8Q*CSAh#|9IFNHoaVi9`3(&8l29*a z>wd1b_A>a#5CL87z&}C@4g9g_^KS1y4_$JizIysK{58B?nPXst#-{Y?2=hsObf{$Y zS`S|fbazKA!EV9_Yer4o& zi7boSepjE&UH91QIm!FPSZLb=nrDKc1_-r>=)xg&Kq)QII#U^xYiz0(<_PO0r%HPS zKDmgB8GNEMb29J|!f0LeGt-a%^^Ne)moEcL>p(`?F`%Mj%`)K0 zPjGxX`|_!Q=%)cQFo<6`Xjr9-1D*gnazr}gHmtVLp0~#)RLf_8GzscL3i7Hh<+rEb?=Gl9A^Bo+J*nv-E z@ZhsgH&4p;#w-vu2yjrzlzdR8KYbbl$pfoYP`1%8v2WXf37SORXm?pr(sYOBaC{#= zL>&-zV2}%M!{!0-KR^HpXZ9w~5@dZCLq3&S+kqVmZ~&q7F64Z;#z*LzBc4|)J)Mf3J|}h0sQE#x0?v=@`-22VhKFzm$FUR6V!ZN10t1a*j-g`g6VY>`gZlyXXN1)U z-dc_`9t~KL`PbQ(v$HP+>tWMGKIoFw9YfPDzI^(|J_5(5vrm{zhzI+PKg;DBmSY?c z2XuCvg@7anEjggr5Ah>z!^hZ1aL094ODvbVEuIE1Q{i6%EKBN!7*wi-^XAUia96(9 zF6^^YT?nw9+mrPC$&Bb_fu;ppG)GOb&C5DXHI$|)}#lSihqFn z;ajQVE$4v_P#1KXJ8k%^{$TbFLqHSQ0izw%s)c!|kOxor$H5AOdtiuw79QV04I%4+ z=3rg~$rw*JzyYmRQ}X?Jp?TLrX2HkoGtI%gy(!H3>=Yf50nZRn6r?zy*dH3$siZG7 zWsNDiAFM%7x3^e>92Xe(n3IlmKs#^`^>(o~XcmHBq66-O(ZYuP_)Z7&QL90k1A2iS z_<;S7ErO{I_2+Oi(RGf0ny7$o8pn`*+G$Q6`;W`#U=Ci+uJGXO|t#xMXz)Z@IIBvy)HkmD9yn(WjHMgZ06s zx27!(Ebz-Y4_bI z7_APtsrILK@!4T`#3tR2DYzY)aYbhAuqqvY#%T;>?!-UB^U$_k_R4aq)?hQ(^c`@$ z4D4;*XUBn43NibNj~@tpFjsd(6{v4%76U@fGprb2I#tb}j*HcuOG6(Vv(h6g&_B;k zx~%(xS5)_m)uZ)6qu+009%}C3?7DDy7HgsZl#b9q_n7W%qM1=!VHb{v(uG=yZ ztQ=>=doO%5L+oe3wbRbaDyI;Z&vCTC=c)wOTpe^r>j3al{@EO(_0R{pNNEf@P!~szS0uBgMl*YsX2^|n{ zKy(T%5F((fCl{w+$N`yr7c4&G&5VWggnp|6UG1KUg^&zA%gPwcdM2O9Qccd-ArlC3 z&?;gzsN{@;Q0$zAnR%(9IwMmt5&G7&$Kt{^{r9QajCBXoMR_3kmAY1F%kMakA-(nl+0+CdtVDRzYBV$ z$aVa|;b60YtT`P=1q}XAM1aF7AT)WKtdOdT+oY$yJ3KWbnZz;*{GgSLWfbn(+LCi3THiUt3@6j zhv3NyQ+UI`%y#tqfcp}3P9<;-8)GJyQdLyfK__z6T`Z1u1ok1HX9fS@*OA&EcV*gD zhJ9LxgO)b39ewb?Fpw$vAMjswU)yB&pMg^CHKGRT(@iKJuvbjI}x5hVi)W*xAnNO zVYSBsH;xi2p^AS90WmaigUMhV0WILOU$$|O zI6Y+s_MZBq)*<$H1@mnV=t}YUAy1%uKF$bJdaoI;CB);<`%e+HVyp&@F*)1}@-lrR z+~R;}rmkp&xLzn^uUbejEIAI(N5yn_{`ryv!hEChqW|3Q9J2mPgH$l|{yFSe&%K@l zne8iQ1lZySs|S?0g;}KRwaqIHJcArDrn-+@_W4qGL;i!2a7K+8pV$XTFgD2O)Nh@t zzbOoi!^4eXIgT}G>GNRWPF2j~5F%R9Gz&T96@Sig7*-qgth##C;Vsr3zvzP-Gu<~D zj_se_9b9VG;Oy>*RTj7%d@}UTCG=K!ti^c(><=9|hJf^A-gh0HU7zO;5}wd+?ZWT# z1A=|{pp3IHx^}+cSw@e<7uG9V*3>K`PxP#Kuf8kaJ?-ham8ZSx*mL$xA>mME}xC`+^fAC`^5OCt@1wt55Z!ilApBlqfGDkl@7{2+z z`5nYNBUWoHs5(9!=rLGi^=8D5_{Qo{{c>%&KaA^R_Um@ZDhTmC3+XV2yjU4BU0!Rak%_+a zm5T4+HPu>j-e>rKXy;3GSed(D&`VWP40EOEE}WtPe^(DC(fWm97!{)kYlmf45fffN zx=J)qm9ewH(L#6CIYUiAh79dwTGWW>7}498wrIB_3U z9lKwZTNr&&h5E7wvyp{fkh@PvD9Gaoi1g5y%Hw)h0U{tu#lV?a1`lM)(~GMZV3DW4 zRe=}+f>h|)Ren2bIlj-RGa@g;%O|=p`3N-9h=W{KmrJ%uT7i5f_YC`*LPNiZz zGZa*|QeI?#gZml2gZo+T-}i#q`!dL1h1JfcGw3+*d+ZL3PN!vPP=FSjPP6-##`#@3 zpEt0Nz&dTAekRId8&Kvu>iYoJ_ra zs%tZ%Mk?k7GDus-FW66HQ^EKvWzV}^jP&$e_xAAW~I^XCo@2oO*P z|08xN>SOOkus zr6``BcJzJ^JcVeML>XMFw@xHHb|8y=MVLpNfPH}b0Y+v7UK^O3JYqc%WZ8=Bc9@5& zdS+MdwEqw~o|WI+u;1qv;-5of;A{S-<1hq-ta5xC2~CgG_ONG0meuo^JUnPF|t&N$jpI3VSj+(DzLHAUZbc74n_pbshs^xIAj z=(pWdF#LXtE?qTWXzweOq=T4`**(^Y6`g0fgRy*D_oI6L?9BJVbD5Fnl~s`{l@2I7 z@^%MM&nAN3Wcb+?jm?51pgmfjcj=tfqn+G(=h%m4Uwr1(UXu^B+yVpsrzU-Y=p@zZrj?0)ovb24y@pboM6Ga{cb zhyF}5pDX5(Y@weHOsi!u^aBXUz_X=o29}LGZUXlx=ZGIL;qvjQQ`Px}Jq>crLy3U= zk^f7aWR!S9_k(aB`361_sDV5<-+L@#&I3~7%>mlf)!OBF@F-%DR&h)CHV84^Fbz=y9Z&$+mp9oAGNfO zQ85aK3;`KN!7w(h4y!7x!{hrCDa?bYhiXreW?OaWLBy+?dr`2rKIf#x42&Tlt8w>{ zAs;wCvg0mCT~>FX8=~V%9JvE^3Z{uE*oU+0^MA%uFv$V^_VMe#w>hAXX+NN10{g%= zn2COfT!9#eV|Zm6hJi~5`)zcK6|r?X{9kZC?{IitZf&B%%`jS>js?F@Ci_t_1T+Gj ztHXY39m9tVI!`x@#v9zv$~i~7UR52p2`e4+VXSj-6#0@7g$ z20EYz;-9$+TJC{y9kfaQVW7uSI3Q$zf*I_BxvVPR^jHOgU9c$Te_r;XpwJT<8g|U< z?v=;UPZ-jkJ-YDH^yqK!L;1In&@K#47u5dE1;Gmrxld5+amGYrPJL==C}0rt640sZxWova7zY^;rMM}VoEQQUt?T@Ob- zKI(f$KJUO%H@`0H4`Cqo%rF1)>xVm58}9J-@dGhFXNIm_O4dhZfCve(d)A9pbpIH2 z(1?Jj7A1G#k?r}wbKz4Q&~G1ekINYI2u%<^S2y9ett^y>QUeV+;xD)ph8|Zhi->fH zGUF?$`&sTvcyA>F2eqmA7fxat(9t>8&4S*_WmTuqJ~}#T zSJ;2iu+lzR7kdoy5C(Ed6)3dC>>hF}T)_pwEEwlsE1C-f=OcI@yzk-s2{X+CcozBK!2#9rbvfJue zJy~}+uMGHyzt4M;A@I+n_bCd@gKs4Uvf3X7`T->L@c_}yrLP;GIPa6=cqhjn3oeMY zX;w#$-cboHIUr>h{_8de#Osf;3zl}LchU1Xx%m~6ACPzk{eajN)hbr}dcCsW^QW>W z=WEO7IaQmMjYcBRJ+4U=W5ept#=>z;f57^#R?+sZ@}7?@P{sAGJlkkC+U=}d<(-=6 zlRfySeUeCkZ^yW2oyqyES?y7B!PXoJsrZLKhA9|go{|k5kS;nf+J)yF&{$5vVh$+u z;=|)rC|uZ!`EBoZggsak$VpeY2LYM%8Qfp_X1GGv9FM1ndfW+|VvOXK5ULj10;3NDGbC=kYRxiaZS5m!WBA! zfbM_;!acCRKK`X}Kp(d_phTwfkQE?A+r$9DwNBZ7_lN_cYz&5w{H7n>{x34#Q+&^k zZ1?WAuNcEW22>g!nCF>G%+E7O5#3G^I-X9hl&ty#x+=!G@2$4Y*dUOugD(Je0q>+M18$ zvvojQdt#p0b*ITYYoY)K-A1s#5Sit0raHf7?xV4fx)p|Ta}4<`d#mS4cb&UCs#S^% zCDtnk>&i&sfk+n^5eLL73;HetadXR14a~kI2EzN1oPRL{1oa2|Fm^gCt`q`*#lCt( zUeTax@im5c28ehJ(E7l}mxUO~b?*Q83*zg{VGt>Co<`XbKcdQSC85kj;+=-!WKCNR7P~wm}pdx6c4`>tP z;QIK>U4nlW2ndkRhb;v3TY3s6*=KxYV~zsNztn8_7ji)KXio#Lh@o42w9R_97snR& z(@3UV?AZ58_^>vV^qm9~U4iPe=^S>@XWU_riyfl{)o9^2S^a5@z!}h}>~eN~r{3p8 za6LHJO6_~Cw~!Agp4S=Mr>Dus0s~2(AfW@QvJz9}dtjUcA`N1xFI9*p-vz^~16Lt> zu#dqJkUMAf2fWCj16$oL;?1uxBO{*B)PnO$l+W`LhEdN11oVQek0+d`lLtJMbOc-!TQtZ>9doxw@w+4a11G=0RKhbNsWM-#vE|ocO$6X|R54eUw`l+5ZlE z4}O~MMsZbdAGC`u>61+}-f8FiUa04BBS_JyTemPTC(HwL^$6|}`{0C}A)pPzKG6uD zbD-js;i?ctb5J9p*BtAo28BXlQ#i!=mS#PS9At-V(m2=e|M5qoQfsry#46Nr!LTgs zz!bJ;*TFfUy5wbP^2Iwc(gFP{@{fWx+5!#;YtS9u0|Gj`?C70O@gCR-VxcvjC$c7e zvigSzdUCLdaokM#0ev7p#IGM^9)_quA0-E*_{R^W1_-{hdO3tljIy^Q8?`L_fxt!g zu>xwK%75td+-U4#f!^?WZWze)FyPaRndhQWVpS(H@G}4bJzpqZ&k5dVt?HZ++ngvI z4|v|5a(?IJgmgXZSf6sopEck0BHW{9?!e<(Ev5NU&Lf@|548t#nJF`jl+dsXX4|D0 z0U-nA5C;UCU^cn|Elge~*iUJJ9FXv%XZ2?`cURM%06-8AuW&$dM!d=aLH)t6X)ee? zqHKn@bw^g6P#~Zb1|lv9ju+yELYlY1pToVb#GEWyfo2(cpL{AK-c$3zsQV*VMZ`ns zV0Jsaz2V7!W&HbQSFuM?%xqs>-P}xXmrK^=*XxxW13}AreOj-uYX@Zty^_OJ>b{9z?s?9u^8TI9SV-e0GAER z(yYE?!>;HECuAekI8PmCT>GDYoEq&MNcsT-ZG7MGSAf1OKXKy3o%23?$IBwEkDPrK ziTe>cpgQ(pF)k=tpNRWG{3AG^3r#al)}r@fm8gA!RY<`@xr2%&H^J_>4pCsBe{)CZ z)GmBB2UM4N%yo``ibLN)l=Bk4?74vo*R+Zwzc?!Q(w>LQUHR^fWtR3Q);z}^(EFU{ zVe`Gy=?s7aG8~WnmN|%riW``HEsE^AcG>88SKjR|?9+bVju-iB@SKYpM?FI4qw+w! zC*v3>t@}xwCpqGQNCSOBxnM8_Ll6XgR$s>{7;b_w`~$qSq0j65>E`D4hT)cJ68*|2}0$ZMmFIts=w4Yd}7Yb-QtK z(jNBeja+-^M(OMPvaE%KZpC9fI)(s&GG;%rqaU9y#U`>{LbA#O$>}-wt z$nXqU&0&z|xKJ1X-hqu{Cssg%o?7g)m)O@Yjq88>> zv+mj1KlxJ!XPv%(%{#E%!FBUGkP1EzP$}ksOxOhj-sYvuQ^BMcBJ70D*-K!>`mg5%0`iF8$>e|t2gzv| zV4#=Aa20wcU?M&zD=*3t`w}Zek7E2o`Y_Uu@!GZET$Q(HZm)7RVFm}Jcx=R8V)0ze zySe$bx`o*i{u{!KUhK+Sp8kFh$G`9YeOg=A=hOQ7;Amax)hj3M3aduL>G0&JaT_d9 z`xA+MFWh<`je1jtZ6Z_~mdJ}|#WBl@az_#G%mMSTKZ>)k5mX+IcnYLuX0@k^ejYZj zRBpW2)swSzoUhmZ@sH08{~Q;N4*}gk6crXfPuj0r==U0O8xnSUeFhq2F7<)57w7et0~NY4$i(6ARPWk&BQqP@b44{ z^f8kIl1%ha_2cjznt7FX6d+WDyp$n#z%v7PYZF8DHXNq+Fy5W*o{4|j9RE-U#_p@| zTL}mVb}*hHddk9LQxC54<;puUEi&g`@oqaiPq}Ob-1`6kAOJ~3K~&Cp&GRe-2c6^Z zQI*=te&69krtYJzc`rs&FphwD7FZt>QAvd;cHvb71Xv@WIhe?WhYAz{0$Qzj2L`!d z8HmTr#6Ju9s9awANs6h zmIZ8eISyAgJNO=Hnn%{is@CuS@jss%$3^z%Tb+T?d3GQ}o^w3=j$e4yMA` z5BV-wQR1UY5p_Ux`@j*x2>;;Ohm9b&$T=aG{a)U7!4v3W&VEDd+j;KkOp7hePb%MwAF-Avx#Pv& zvg3rEGW+W&i~qr$FGvAnpLvS=U)XzLR{Ux1!si@Ne;Wan6hB1H0RbKXKtc#e?t#e; zjOtJQmUUvcH%T3|7e6j5yI`im0m0j7)x(;zFl~N7CJ_7E<##~yP*ALL`~#lhzzOlc zk9Is$dL#Jzkz`|p5yR?$3|q|D=+pT%RGz!U4D18n1pAQT2%X}9`1h5V z$~$FJ`h>eMkjTX-+x4{HPbKB~vv=<+mFu;9JL44V4?l{aM1*8uQXjGc#D4citnp%X zY6b2AIs2j=x-fx&Cr}37LgouAA)E zdYmvcHZdTZx!G;{wm$iO&2CLVMAwBcaWs6A1Nu|pfW&s{4jqulHKqGo+BM29KcSd) zc%Ew&Q~RZj_u!w#PQIs-wfB|uRjmN_F^pmnYEIEF0~=`-4cG@OPTB8uk361%g? zU^{!yeT(~n;{>-Uax&xnl;^x}XI&&aDtvSjcU>X_KKlfHG{Zv-5ivBx&LhbIWg;M& z!z4O+^K!~Tz1P26_XWBD8;+qHo0X{3a zs6&F}Jj~~?7kn=bmX^WW9oeD8oNZA~^G<||0`dKXq7u#aC>Lj``Xdm~Oqp{rcKcL3Iyhj3r*Tq=o>s-@dgY`t&j(fynP>D; zhFb(1Tv32G5A@3n6FE?K{6S}flk!7We+C=PN9|!xc=Z4-LRI1j=j-4RNxEJE~ z2K&q&RhI1=R2zm{Cz{5Rfon&06#uhgQ83f3LOKbvBa@4)x5 zBQq*MNpl2rn?OLx+1F0JGiiSCq*+&u?|0SWgo`!bIbFwF6*1>?y2S$}k0ZoCtOILQ ziVe7ju1qSS5drBj0)pPFS^`Huu?;T~5X_up2PWq5PqR6wfNq2gk)fb@d588V#y<t(myZtxO zP&#QWtsNp~BG!Z6u!;f6Lq8#G`WEUB;vQgus2BUM-+#Za%~y@1v&Q3Xz1x1wvkTa$ z*l70xx8gf|XFZA_7m)p*KCyZU8bup89-3=G%_(d)Fi(H59?*x!MYj%eWJN^~LpHRD zN;_i=^GtC^%(7OvDL)#;h{uX65j}cfHK>j~7k$*K%PAPwB93-yg0KP=RRrY2Rt9@- z#6Lz1ba7a>E(ov4+m|l|P47S=^EtZ}&I_-T&Sau>CLJH~59`7%D&0p*H@KHcoSukD?$#;%>O z_Li@Ft#KjdUsQz*oP6bb>`~L`HtOuRaYdeoy;U&fSL>NZQvfu#z2cJ8l-7mrUWSzkMoU+eq_$7B#Y1b;<6ZWSF0X_7$5l~;wz!VM$ zbwKQ=^W-hi4=AAiYbH2oLO^wrLdQBFj!72gBIagHaVR<5HBM!lc(cNT{)F_F(XAz6Po0`gT3sN&Z*54K|UC3xU|PZR(oF0 z3(eQp!`H*+?cCh4`K9b&n2RJA zWJcv_Zy`A#szCT13J!?aAY`RW@qyoO)lT(_^7NF)X*}lIk$4Pj(i_|M$$a{><{4)5 z>=r~}u>Ae^|Ki*a;h@jIV-5QK_tWQIW8EGC@@e$EUSnCWvjP+p+r_aN;C8&}mPQX7 z4RB5Yj{&5{>lWZ0+)ju};`R_GIwd=DYHW1L~-Vl?U}b|AhJ0_wz$dKV)^Mz|PkR zoE>d4>9p7h2&l*~(6Xs%t&?1?eVWUC`_^PQNu_|cIiSBd2b4xYk30OJIR<*PgR)23 zvN#!|%zYAB1zNb+X%+v*+-rBfyD|f7@8y3Q$o>%DgQr1`KqJ`yVu+>~uq$F+<$$t$ zo@0Jlc>2&ya6h!$mB@Ejc%M`Cam?+A-7odTj~^lS;rBJTuaxL@3pk=wIa=3>PHBXW ztgv^1ZqQJHN^%QK=zzxY>l!mn142J?1{OR$P2~)%&N(3Q8jtY?;h?CzSeTpxN}db@ zaRh{Ti*OM7h46h4c5`iBdz70~ioa*R$8U?Now|eXaSkZXD+`8@2(I$rLO(RS%4c?A zGco1LaD2VG@`4+N1E2oi)8GGyZ=wc41-k$Jzo*5cgOf`Aw$dI3y=B*D5NJBP%{6+q zLx^Vp>4Y%T>S(@Z={Qa2jzDhgfhc?sM_5~Ys5HG5Lp!VbD8?qmdhF9Y{QqeC8m7e2 zt=m{fWQ2yKfJw+fBB|3&QVjuY8}9AFN=w<46i|R1qy}vJ)#5Gv|Nr3bkLSq;A9l|< zbIC*jY5W-3uD$l!YoSkvs564&ku@jUg^BA}HA;L6uX)Bjn;15V>!Y)`I(d)*z9XHG zz&tc3%d$r+^Dl$^(a{&wH{;9;D$r%;wW8S-s5==e1L)^9lOXhi40PQB1hldyy56$W zx&p5g1^R$m)3Q2Wl%p*#AmIr8?GOh`Q8XqB@@__Y>VDm71S8yTjfa$%EXF{Fw6C^qnF3`_SuGFDP|mC^#Sk5m1^G z&>^mHLk4I#3^*Xn1;agvM&s@{;DEaG`D}JAI3Vi5<~izpOw!}TXI)$k%x)v<&HBPv zsBN1srm3oC&Jid`rTU1DXpWr64^?ODP<@9r1L%Ik`T<|XF3qFwfLuQa|DaD}HQBYX|30sBMS@5ljJ zgn-bV5php>jVoY?dyoU_E&{DjkZloo`=p|}pHTB7uun09eTuuj&LOW8<9n23^m>7g zfcr@%lW<=lRjUhDnJ$KwUHC)fHwOmqU1%D1F<$gBp(BSG?t)=5>Jn>^bb|&wG@nxk zM(F33x-c(}dtwJ-D1myqf(z>6TnrFUyKOGvtMVOIA}(>4a;zBx6+S=nKQxSY)jbHv z_2qj!$kovfdP)`j*x`3+8D^5<*K)hbHQ+wp>l)ElH!>wwgX)PhS7v=UYC=_a`r0QEMMJ~01MqdW|#9qzu0Qh}+bt^s1 zQ}uyMp;^s0(MK`N#Q6FUazJ}G!TuqqV6B~O_yzGl3(`oMt~=_{tcA11y|#n5UUI@0 z(aCN*aIAK{e&l`eocBmAS{-oV*g`gMPf;+}9mMz?C!tVV04>~Tn$@1{BwRR)m} zb}mEtaXRBOu)q%pIiN;Pq=AVp3@VV+K?@FO6zZF|5KvCAzcjTbMw%-d?s}{TW=K5o1V>EcBREcWV*&#iVtNF^C`_oVL009*LMr z$oJqYT7F*cx%ly=|B+vxJ@C?qdhqDL`S1Hnt75o<14c5Yv4D0iF-%a zI^JFiJk)SX*Dh%zq z^J~~wqpxQ?4Zap|KqJwmh-B1o3f2wlkK}-^Ofxe3iXNikn9CP|g2e6@&BA7YfYdQo z4Pt>v52Oxo7H{I$$(J`dAT_{2ywmT}Tf{?nfyX*xVn+4vwv_Aj!mQR%9S~>(f(z-G zjt}dHLP)ft4vebLzy2>AScL!s_2E9$MBkQDM`gXe&Zcgku4<{p3@XuFPxf!GyCcc< z3rZJu2b4+Pg;ITxe3Ji75@@nc*u+L3x=@2NplFQQn=$#B4OpKy5(o8t-p+4keeFX(vL025`(gbdaX_R7A`Yk| zP>$Xf98gMdK!@}`#n`@AQ7C?P`JZhspWQ95U7ly_RFZ)=YayAk@>$J^&5oe2VT2=m zpK0C|d=!}$)!^#0%>iKr$~A-zh%nI89Ce5>9Z(cMY$G6kmA^<1hmFTYBoJRlk2Bs}Ein1^sqG5a^^oY3q;rZD|I`XMUwWX4lzT=_;ElmqtNe*LV4z za1VPsd${{P_`c- zryEB=tOjbA;Jr#djjGTBEzzwJ?h%@RpK?GmKR`aLsTB9SjDz5<#*aWeR9xg5rfPEP ztJG=>)W$s^sROu1@>lCQs9ECuvb%j%h_*1e`ura{xCUVxMw9q|E=ot37}_qEuRW+m z>)Z0}Jez9TocfN(8Z|y5j~)4*fxtk6T^?v~4Yh@{+JkH`=@S&GE9fn>ro&pF|7+A@2eGm(^U=)6?{-3BUg-IGYoz+EgZ3e?t88Ap8(xnP7W3 zAkL27;|q-!ziVeb;h^_IE{G${$`CnWxrUq74|+YX-tc?glkI+J=Y9Ju=b8J#OE3#V zA69gQX6+AiK%X}_`&ytsv>xz1we5tjaNkS#I;Y6X@G+wQ3HP}Qk@tlI+|Mr^O+8=D z+Nu-sJIwJ6Rf&6sLSY=74zfa|5ZdN|UK(BY#AvW1G}a+RKv04HM{+=NGhv$p$_eBH zwW*g2yPQB5RLYvY+>lrw{H!^uL3~@4DxY8CfH>RUSqA&4UCIdzCiV1j-ze6X#5p1V zg8xfEb!9YWiC#VVzNaVk7VIcMg@&+;^neTJSEs;GFqmOgxBY2X(kbE95 zyv-lo%MCHAVTuPanYhcN$MX)Fyk|iC6!mMA0pzvak%`|8R7217@6S)I^Ye4-9N(Vb zSNx$i%_I`j1YeK=N+SnUCk_ZJkTtdRqJsD*)of;<1DiB2&nDZcVBbPFps)h{@sB?O z4hRttepM~vfJ$3_9ES(o5H^n_dYu&!h z!q?6&s$y$I=&6Nr8aZgHKTv!45>_Cb#20U8wKDwCo$2MQcl%hrDwS8G>t?yl{10xw zd+Y<`QRWWKz@&fSAj$zre?*V5Opw(c>JqV)tI{(|oF%S{=Zn^xKszKW z5#|0M2jq!+`16TN1bewWgIkYi*MGhC2;m{h>T37*=X7~Je+3+LUUAoHW}vYLqZt@Z z;86#?u&gTja!i^{F$1ej^5@l>=)j`8V9gES5RA--AQ!fCaO7LO?|J^s=0}T$UVA z&2D^dw8`~1l4cs+eSb^^x$ZUL=`4BZSc9QKPwoHR6}91tskq8t$UkFbF(Bl5MMu=u+TwjJ>aGOv1 z9N!~ZtD^vKAx0WSE6O04fpJ~2DSu<_!ZXN6jYP#8$*M=66Fv*FM^Ja*w`XLou>xVD z5WF85Vg11h^qL+Rm4v*!PHFx{_@_R#@~DDt>dj^iE6_x#HS76mv-$DzGR^_94*DU2 zfcETy{o_wX?$x%UJP_#=^4ay$&Sqyl-UjQEJL@c4GGE|t?i>+NZ{GS#*k>30MD#uf zeSe}Uf>k{q;eF~t2b8z6<#GupB8x}THX{dgyuq4+p3sX_LG)N6*Bvns&ea3mPoM*e z@4N5hx08aIbwA3M&PVyRgLFjjT|f_3_gM!`uUIcK?ZVfs=S0vC?xA8LFYk$|j^Kcn z0s+Zv_`B#7%tJ5wQaA+*y?C}}U=38-m;u`o5xvz9Ofhk9n_x?1F<5paQmd!^z6zjm2XGawerSqJ@8+inl8*EX?7cw`9yVH)c?f_Z4umH8^HmJVi}x$6=#J|ps(_1bIlbX>RB zUe3N3>@)UX)_tPw*;D3!GLiwJ>a(g_%mGzJ{lV#Q)v}tkT65C*7;r#>cK(Vw=y)#t zE(g>O_xoEh9w>_$*)5q5#@QHvfG|Ol86l_l;;ur!pViNHzGAxPI1{~kOZQyf?!V#( zqoHyQ!%@Y&>#>YChy&UH0&4BkK0l^*y?(@d!2v}*eYX94lr3+c!msl`)Pa%Dcxx~e z{E4ZCJc`IZ4fr2NazNpx{7`a0oLhqWJj&$}$rz{uVh$+0%*_KFO1KNpJ&nB1olK4@ z6mDQ3>*IvJWO5_J5ggEPmjhA*4#+jsMX`=Nkb^Tc+N6hacDxMtHTW$&T`s2@e&oPh zYTQY|YQ%@ELIGFhm5f|3z;xngBYkDNjY$DHpa=pA>km|>_x-~4Q#PgRC2!p<&DS;k zYLv~cubL}c<}rUC{Rr^Lcg}W)zYy$+=xt#jI{2}C4(KEuQ556Q?RdsK-lpSwkj6?_ ziL*8WE+;xU!-HpTs1z6o?nm-V#9NIJ@BE;o4~M%hQiPeFN(p5q+y$WXp0Llk#c%V5 zrv>~E&cNuHQV(X)EY!|&+)MxfAOJ~3K~%e=w%dJaugZt;Px&WKtL3-2pRL)K zbd*O0P(IlIit2#$RIQC(c_r5OU>Xl{Kmq{~FT^?SN{u~KQ)#LL;bPIG#nDp24Db^rlk2lg~yd%rvd z%SEPNk?ZjMOR7W-d@Z|BfNaw2@D7GM=1G`0WHqI`%>jivXsR!pRZX+ui-)>39vEg0 zz8$mSh&_K~e0;7#Hhj7?)*Qw_sGN3voV)qqk%n{XOP8c&&aqvpk|Uv&90|n|)u6_5 z^3XrIh#?@+gZ*~G2x!yD;;+{HN?*+Z`FQhEb`HPi>p9~ea(ou-5Ai_c1?_I}KQRpC zN}fpaN30Cl3*J7d-aytMJLGQlE0ktvxkWi19p?Qd>0#|)b zS~R^;aErC(UF>B?U9;y?19ngS7gV6iz_TmN|KOQ`x|65sldrF!1DoiRaw2*?JcPWi69Er*(*h4e#oZ0N^EJ=z2#*n44P)cw>kF^vbpvTm<*UzKK_bNu-M|Zxq z*&eB7mN{PHRzYffB0KJHazJ!^vH<_Ud0NLEtN14QzJqxo)#cffioQEr91!%!cY^1^5 zJ2&oB9f=RQC(AXC%Z05TOwQp?PWtEyRJdxCYAd~T)y?XrH=EtTf;+tM5>d811V zKm5g|9A!+pfbMQIhjVF;MxN<0JI$J)5zoe?m(czraD^7RV|b77pf(Awm_ag`_&6Pc zdkQd=z)l0ZG;s0nfOux{j3HwdTpQ&^k^kr2T$q*n;@`i%X3%>B&hzs`+H=za{U8%v zAqKitPh$l_FAntBsWnp*cqP4E~(cv-e@b-iW2lwvx=gEfZVR(CbeZ}2|NsP>1?a$Z&( zD<8j9q1KcT0WG+vss^EM;#-){r~~74#>5M z2Pzk{@PK8*6=_6VZ#F*8&-^F?(x%!5PEAYKSH5a4ohe`{U(@_H_iQTmdVtn&7WVmW z)kh`tzqUKDf4%2@)QiFl{%+}jex6DtudVBVfJ&pQY-xFi&Pv$NF8MvOYft?1eS#Az z(wvUv6ThE7;eE^QQ<(YQ<$LJBEO?V@ST5?l1USc>OI(5{{adU9YYX z|3C)@$X}_RL;XoLo9Flcj_80QyYN5bfY!)l*@5d3?urOKblb&ux^0pb5d5t*ySo?fVna0F~e3e`RI^@kCaXfkmx2`&XBxym`9PkPm~Yh3S_8a7bE6} zNXaC`0o^r19T0Iq-ntz@K;9t)6v^Z<%{T{S+JGz?IkQKutlz2Nh#3>k(}|IS-}-$z zAV1)MxEkTyeoQ&9&i64Voegu60}?tQwf6otih#s4EZeL@KPCGyUyB{tqW;~<`P1oe z=|BbIk82t{C(ij45ygL>jr!5imc#IuAabF|2-MeG)XO+qzm9M~GzGH*4v6Mnyz>=sKBO?*@%!05#QqjvPlld{3S*#cz0cbx z^=N>Aa0-TfSkQoV`2x)5AcN=>VR@f;Y!~XIv~;ju^-TUeKng&Kg8HB z*e?3XMW$Xc4ro?uA;V&JbF6<3^w7j2tISA|7U)esAmV`*0B*vpd-|6-;(%xZMyemD zcF|88!){Jm!RUPPq4;3!v9Jewtq*V$RdPVD6~;f)3cmir8CZ=p(A9+1RGQ7|?iJ&K#0gnGW(%P8n51fRBoCYEw!wvWz)i3rJP+0xg6wLSa6>W}fVIPgL&I*d8>ShbK zxtuTfA*_naoXC;JJ=H~@w&DM;yoha7;Rw{f{(QXFv$xmt(QSJ<(_43gtUYhHpPsrN z)snm8~E^4v7vqo5x%v6klBjb2Yh?=kAPGOw?%>4BTBWSD=ZO?cvfcm|fWtg1DUDxjKm zqt&q=Yg*PlAfThY9MIPY2gJP>)E~V3iQDj8f6%+lZu2Z&?8Rs8c8k5nJmEryS`kD* z-Ir@DHmzlDv&%7;_s+kzcHV!c`zbQ_Qxp6Tye(ICiFmdzRud}CqtF4dmqv4qEm%=- zKqY~Bc;-ddu&;{xsTL!CKU-cu%rG;Cp=$-H=SeD2Y*Y9J{)bdV&^K41{-7GVdWuyD zTIhv~EGj462)|`#h`fq3^n-bicy$MUh_NYH<1Wwvb$J(zIG|hNfe-;5Vt|PM>F(oz z+}jd)H>3J_xm=R|*-)3JaAI}*@z~H*M{-nA4#WAr~~QEc~>;sMU<6Bd7Gs9JBFqQ~tJaa&jSd zF(UN`??g+o`R8N!ea>FrU9U=`cD8hv&91$TH(zcx*WSE~RmOe3agcLf;( zH%2h@-4L!hh$4(Vj?m2CGoYh5nY^1635CR%&X0J!P7^-gwmonqfLA_NR18K2S ztrfD+gQb0_hdIgwYBT~=@%gHVB+&cNi-YmcL;ttme(Rsy-hFPg0RfHfHn-l@pww-Y z7W3J_GiT56mw(fCpqe@9bQ-W5dLyQx?%_MSp1w)9;FdV)5Sz8=dc+=(xJyQUmUs*2 zRVs7F4&{wGBlI!IEzvz6{|Ypg=r5P!ev5W&a^x~c6?I8(Wxw5R$lfjLLc2F>cI)=B z>88Eto#r|E9%k_Jny9$0&_PoTs#M4esPzo^hrEDL1&tgKRG^h!uV>-Ls`_ft6h5Ab z@$l{UZ>$1($9>pWG5o^%!x-qRLg~~VRiNv3oCn(2yc6H%Y?T-I%i_Sx-CmAJe+UT3 z{wsT5`d{LHqG`(I@@Yi(EK!iWP7A1jbp!&!DpOwf2mw6`1e6NAehMNGnR~R*ykQ~upKjC>$P|9i%n7Nq3t~7+>aaSq7k$}(K_`(u20LJh)q@K!x;$Zji`dbvRwwY;BhX+hPYi_NceIyV|}LVmtx zsiyCG4rOgH_6hRkpH>glgZ+yy?*;zp69DSpe*WCRWEb!FcHw!YtGnf@H1lv*e6U&6 z7p)E8fy(m~Q{AEB;CoDXuRK?7;7FrS^c3DtZ=RtVJ@YL%p5eY0-4Bn!Y~@7aCXeTH z;wFJ79F(k4$)}xRn*Ig;n<+d4A2#}3!1v0>qUD;dX8X1ar)C@Q)^Gdh*XZMBJ~`el zp{6apQfX$6gabF#ET~`&&TeW*e#vuNM)x?_mixS<>v;z{FwWKxI%t7_evfXVz6%l1JE}tO6hM*aHi;Ez-Ikg}>6(o> z%`1IC8t9i1{Fy}mu}yB7En{giOU@KgZ(+@L?Sb_3U+(^zqC0!(xx52`JAdA`BN z!3l68bCXEq(Oc&x6FoEeo70cYp$gBR5Sbf^=R7`^o`v2&*KZP)L_YaEH0tP3eZ!TE zjtakj=Ff>gkDE`ANX!-2qMn#)j<3A@)q~e1{+-v@MKF?z5#fMvBWlMH z@hNmfyxs^;Xskf9ZY-NUs)B~{;zJdYJkYKt$O&+e%abtPv%(!PF$q%->VRC8v_6hs ze4l;R1PeWeYsRo=j^rko4c{kff$R_s#W^5&l4*c|G~|9r2Q-z}jm2t7J<2ldy<|?< z@#jVn`mK`_nFhxAhbmIPfBW?LZe3ffW>0gy4L>z+T`J816VM*m%wE`lGc-zkhu3%= zQ3@P@XP_=H3JNe0R2w*-^UoQm3zeG|e6)qP6Igrd&-DuYn`cVcsKD(CCT--OZ%&gn z$Enlx3??1oV-x)RP>T|EPUJ{bFZ7{b!30(~D0!ZrCpe&%VKqEG`gV4D!?*184Sxil z2R|=8JLS0AuA9ck)bdcKhKWp`Y7J%ZWD=U|)-zHAl!$l%;U3t8H9*ax^rNpS0RmE@ zI_SU;@%J4L2#k?*H70m0*dIvdG~1Zb)b(|!I5d|ZI@zkO zud<%B1KO|qIgq&X=Im?#6u!z>CprZSJF$8c0hP#;RS^iNn5u;cNcbPda@~X7ulUZ_ zR<>!XoUg-QZ^AzxCEB4a_`n14*ZCj(S4xwWl<+o<+)C>-Z$W2AxnMNy`p%p08mnOr zazJDT)Whs-sUT@YcELCkj5aZ73YNkt|tEzbGuutA#Sfh7KkbY-ZC_8oIR!!9EylT|}T zH7$05!!(w~x#r*I1{V{CX6iF)vyH{o-p2dakmeAH3Rp3V^3 zk(*xwZ*Y?d_b@7Q7k)u|U{$MGZcb{G;)K0`00CkBi6Eem10p}fzzs-pK-htOMGhJ( z(4R^d`o+ zIt9B6bUqv|Fmd130g272Tv&IULnmORv0(@!#2J3+KJu-q;~vlfxvT?n z2F3S9tm4S!YFa&=#*S&p^~UxOu+Ljts1pAOwpU^xb+!cL(+!xPc$R!`sA}f%QxPf< z9w+i(Ki0zS-RJH~FJ)KW)uuiFd^}%Y&*#T?-N9(YIT)Vpw{6>RJtqjI06KYQE+@mB zPJ*id)EvMg+(S*_wO(f)2zsk$cuWPc3jdpDe1!bBndii*Qd3pLAoT2&I_8f-{feA` zmf*f>)py}m9zPFmX2l)@n5=RGU6z(VN~RK6+3IQP3!mxn;&FuGu-0TUwrc=3yGiNL zhpClJ=zW+;wA_I&eSl~az7pu57ZxHQ-h{6q15|7lYS@c)Ue5sm;U?I(9UV}V19}&5 zK$3_4UE%b{xjDiuyES`S69x(|!xun6%a)$CY4@w$TXOE#pp`w$_vpXm_55q~NDqB~ zB>y8FS#g&AiF80>7mN~^1p-o1DV&0BqPt$qL5I0t%3g10dF%19P$+!L!~fjYbKWY~ zkg17geVS4Rpk=Tp6!CtKUUDG<8ir0lA{idPQr^&ahCkte)bd3U zTQEd+-;L+Ars5VrlmqhLn1UJG3ZS&CNUCbGckA*gGWQDK_u!{%_Tb8G@qutpAF2akmzvkY=y zyX+*Ork^w6zr|jTE|~Cqnz&3BRX=}<`RlZI#keR#4APB!R=8nRH|n$an8aewkzWx1s)wZ(@(n2wa12Z4W)46H0TescuCm4oUS>(E#O6x7sMUdpVWhWRdS@O95D|h5m0Fn=EUnI6Sd)8 zY`(DUl8V=%HQ5 z4fz&sYpRTZ=+!k;gDe}#0eLbLLtvop%N7D+4rq2A?1GiVE||H03Ks6ci=Jyg2Sj=F zP*Vo9AL=-89WW4j6yf&O8ypbjf~l>3v93Mimc&>!0mYy@s}nfWvnQe-?YRU3!rG&4 zj3@_W6AGF__ce2toGnJVjKL*LM$JLF?lB{DTR0&E#JS8Df`PspWlNj(?HbviIn*C? zuWcMJhXViL9@X~&&YS!VV<5&L%n~E7a>Lk$nV3WxUA~PW{yz%yWK9PVjwO%GxpjJu zN9VlLxj%bQe81Cy>lS>3c;Gyp$je|wV(un!-c0*=9X`h0k|nP5nIKg_{_NY?DSfPh zKc5?ZJbj&vXYhndm(W}vanDf||KIVvOJsnh+b-^51bG;hI%mT33~a?Sc)&lH$XqL= zhykkN4(sGniSj>qZtcRq6H_qarRl(EX88R@758WfKXG)@Ze#Ky?!=3f9%zr91|XnO zOZxtlObppMP=w_0}FnIUjXC6gVi{$l!bQvd{q`&qEy0=Z!=_c68s1 z6255v{jlGUL_c)vlU|43I$h7|RYj3%#O*ZHzkGaR4(K#%r5(Z?F1)TT0wu+3VT02L;=M!t-=JSkD`c$WCVtH?B|}FmN?ZqK!P@ zm3$^IXI0@*!JkEXJjOnicsv8&n+>OuIYqx^s4=gvY(Chr(EqDroh21xV|C8yW0_aM z1xu_VF4IJ!(`l&{ymy)rwILIIY^5@W0@OJ=`Zy&lgB{pSCa5Ek$4-&w0o;Sk&sh~y zFe}l=q*dO-$k5{woCnW-&~+;ZX$38&Ve0_ob>+A1-Dvj<7;BwM({QyQ+~^eeV`QQoup z{zkgs!J1R6?P8%C?SSp!e)QONt6nYhHat2V7HA4~yn)wwWC|ASeaZcIsqs13f6?u7 zHD4b?2Ugehl*Buaav!Xq{B<6PXJ%+hR>dC7vNSQ{W^Iild^Z3A`C`%(!9Ot$$c%G9 zy>7S*Hev)+x-JP0XlCa2b3i#WNSz1~&|dzB`YuE*1L4Dgj*fU+Z+V7#7r-MjAfW^?s)jO$hC#e*04C_qiuC*4iDo}j-P zP&WXxK-D&BSjN1+y&zq7&%Ex1Qc>WzcU9!=!ZSY-U0r3 zK>i175N)R_I6EL72r-Zc2xxsx8Ly!)hn^k1y!6b_ebseNkpn8fmGypL2ds7=>nrNN zv86@C9k6U<`W4+qa>I(+{6J{TqwG7EHSOiT@!4q|#1CID?n&Kq8+@q+*Z` zi1(>^A1uxRmEPolq8KRHhc|aI&{Agdm`gH89IG;u5O0siV>Px9=5Q7&>3>lbYz&6& zV&NHgz{ZRV00cQXM|fu#q;qEMLz6$BlES#k`C7;VjcNLYoD2xw1$F~pAt+60|(cZY}>^$ z)C?+&zN`P)qy0HJZ?6UW?xg);{3DNAtr_TlPESJxu_bgs@~GBb_j*B7oM z)O_60AnMV^2B9K)WrjMSq3Z}0kjZ&{tb}d^o`}K^h#cu}uWvWuF4%q!D6ah3#{r?g zG9e&*Pb|=2?5e1{ouTsv;Tl7v5OVE_FhH#I!A;YPLN+ZYdbE|WbYvceE%x7S!a@U| z{Ct>~a(rzN+rIF9Ph`q>8=Ms13r^lRNBvLE^m09^MWlTNDn_55p8j`!ef_@;y!P}o zo6o)LySw$`x-`GLD=o6ubL_uHI47 zEwrffA{Eed#Tvvay8n=FA2WH-38>n6rTTMu6rF(`iA}I?%>BIk8qooL6)ZHmlPSF( zIjj-}LjTFNn1fLTT4d!mYA;COS?SrVekki}EBCAXt9f5lhoN6EaQHqzwyPCO4WK$JrYRVdRk)SQhR&@0uIOpLD~U(^h-I-O4~WQ(V}{0}~^ z0v+GY`O(oC&(f&#OYA-_tN(5*Ehpw&YXYxKlvAOccS z*)HJj8cx&S@ck+5cs|onKm|}W|BStST|ccAc6Z?an^Q^Ea4R1Dp-*X=cUn!P0ZWVx z=77-Y0`LT310%>xCD$@D|bowGlxX?5vRZGrl8*}+F1C3VAS)S)V! zo|EspC8`r*Agd1F)zUkc98ge&UIQM6`z=6TnwALfk8wIsai9WK&fXn$=svuWt|VUf z;U9r^rY?3`$ujoD3Be;FHbRZGg*&NY4-C3Us6F*5d(l@(1w{Na`9U)S1kZWS9CVBW z`ucm22}acj@sIT9_zGgc}pzN8XXc#_Cjc(QH$v2UQqjUDC_-@1KEKs z)HmvoOy7}=G+l3gLN`~v%AdKa!|U}F-r{Svj&+G$+Nu-|Up(nU`AMy2aJ|+~)=Kc} z)<(n=^L*ZqRSH`i5Fi~Kz>T#uGC_i~QNz=-5wxV-gsX2T)w2bmye$=@F;pF~CJ1#gcf{^^3sfDex!J!j?=SEF-MPHH{5KqvkCn0Uazh>1Ia{B0 zm;t({`UC%hreLoYbz3p4l0j_q%6p;}Uriu~ouN5aj45KobFO?lJ4b{xy}=n+zc(x5eYo~Cn269o2gP9o4Ok}oV)`jo*aX07)2ZV2j#S7hhSu!G0 z#RSZi>~lnqSbkqd+(j8^4ON?JsHI-grkBJ%cMm9Ey4jw6#m-E^T|nrm@aDRG0oA9sl zbJTGI70w0Dz{m>-`mQ3*zyt?Gdtk5UfPf}Ye;(qQ7-9w{86m+z|Bih0J5FZ)T_7Ol zflNd|m~Tc|VZlBaAfT7t%e-_j>%F|S`xREE)nCy4L@(q46ks9Fd#A^ceg|Lc$-Y92 z*rbUr@7Q$_0$TM86Zjb+0{Xn_f5R#KaXZQY33X5LAO}>C3TSv+%jcg_1N2fgH&Jv6nt3DqK8+i#in_*@HnPxm1!?K6BPr#)jF5ySq7?w5B$uGzAlv&N)rM zp#I>bVP;+4QyR_|2Lu49a{noB5S~O=1fDz4)I5rlUK14rK$)X=Uox~qfhy?0QEcCd zhc@(YDu96CG7av(8H@(_FQ<&ZXp%=$_yy)+uovP4I*jc-u-6a)MKBODK;KAlc=Yv% z@XlANI!AH}1}Nxv1wF6@54{{gLk!rx9Xhij19Ypq@c-S(?%T15P1$P)e1FPsdTm5H zFM)fC@yb(^xq^UXlC)8HadGnD0Jat8Lda6jV21M@LXvxYNtpR3i=d=;vlEjln#{stT(sCz&MWd3&?ki(TnI5sjftOhlLnmlA zsz8iyo(?bio196Sa38)=x#v!s?t#WfLa zuJU_P5y=f5->1h??hbBdBlC>gDTslFgnULKT_QJ9+v$zJ*(~Z&4AjJV*Qd+Q{m0+> zE$mI>?nr)X?B?=o8-46R}F-E&PLuXV;kCJdgoQBEU+vyVgQqj@Lw<_@8{8^DwGak;q)*OnB&5 zXb;T7`qPPVKvD+8n;2gO2lT)U5P2b@8{*e@f6^2TYY@3tFY%|3U06&B#2nBl;D7+v ztPbLxpE%G5b!A@_s_j8U;yU0DTI2cc1FFdAQmCOKVUiS;NGaj3;Hm%xsN5t+MCO2w zkFTZgPbAapkpEAJWD1;Ms-cHyJ+JFZGAVZ1{|+4x>mVPY>R2eLQLQF2(sgaj{14BM zM0evy6M6&!k{l2v);0tO6w8L+=75%e3kNh5Of>V(uH(x|7&!wOgnxX8XYIb@i`hK; zJ`Zxmi@swXFAe@!n22f^qFWO0l0$n4PojWcK8&d!P9K|EAB%m9h!pSo`PCP@gW63*aV zCr$W>r)>$ji3&X>?twx5S&1opO3dI90VSvciA;P%@Fs*Je~#jgGVhyKgC*vgRYVLX{tb5 z%oiUnu=a%Yr(Zz)(^UE=1=2+oR#bo<6#S{wHVx*0u8{*er2h$hfWnNgg1in0sCHV- zBLjpg=w{3Z=2oKXp03BoYRuf4{<>}3DY!V=BP`bQ-d@)3G<`5sD?m5r1x=J{k~z| zje`C6IQ~IB5beJE>Z0HOu0b!v9;AqWsJ|3g=PsCk^#afKp~C0n^_huBWUU zc-#xR-)|P{9wsb$gnt0|;67QJ+=P5|2YkZUfQgA-Sb-4nECB<#W+YJy)heUSre!ZS ztvc&`u=em(%4(e*>%h}QPF8nva0UePJ zI+%e$?fC+g3boM40m0u2_-jE3XvA}{!CE39!2zKqqE|np{R!~T_8d%)ve0pib9fft z{6vVSR)9-ic(|OLeE9Hzsty;QlLz=uFISt@rt;8Ns!*4ehZS)^3f!7}q$${{-!CHq zT0f!};-koWSN8Bfg{@o*;Sc@E%IDEVoj7QAfG)gw{N;_XCjMQqp&MwWl2x3z1rspU zFj$vpNF9(&%ZRFgdQ^ZyKcM3n2ejTuKg71ohW}4EASccOaXli%q{b=jq*@MdGylUF z$CYz=o_4JYhI2d;l_$EfVHm+%tVIq~s$qlu4I|7?m=_VpKs5Ur8sEA5>e1z{2iOp= zLp@p|78{n_p4jaN1f+7h4?BCL9nSEA?;WsDuIr5`BcwYTV&)Ca!Qjl%*)?4aFi?6r zwK}4gViZKI@>x>J6K_HXZmuF5UD32mho|rNJpY1ztpYg78Kt5AoZnl)1U^0kOWY{$ zp#Y($Vxoc@VOCmoBnKoPOZDgG%ey0sd7PhUfTp6#K@X-itA_Dio$?<3jplk%1$`8;2#B(H*a_$hp2$Wk+=2DD z1EYPg*?KK}S-ArP1O$IgoYfxGv$F>u>%MAAa(}mlACpL@8R@y2fP+#6rNDj(5xn!^ zAp2{Z2LcR~D&t&A z)1nCI@8f`Q4^64%t9mNynyTOYSk3Csnh{>yAPqI{2Q3j0)u0!FfL^-2yTFk?$^i*K zAV5I>g${^4qh%(l@Zs>;uQ7C?*EC~$3Pu`4o_86p>pP3GZ3-u7H_VOqeQ}%j;!$r{ zEIM3GN$pI#UJapV4zq50%>8`66Wv#ixF5tlcZ7gwUJt+7OIPz%)3awilkgmNU(*Vr zAM#U0ALcGGMlv@PQ`9+C)N51f7H4jW+%0ovZvX==>ebUrsyz|`0j|k3FHxgdm0BOG zbBfokyeL!mm(;O!&QI%8=&6=k=Mw(q{k`bHtV9$8WnN!zl#8lXAkSTwp8qwGZfkl1dPEg(Bq|kc;MwWd=c+I-o5KG%}&Q#8D7= z7HO3374Xn%z(Zpn=Ezid`VL&q|59z;SoTJ8=RN4s+=wCw>J)yjSI`v&yI$OD^`e+3 zoP~WpK7KLb?|2UWpMOTY1NSoiq0FnU=|N?~Q2UK15Rl{h04nfx3bh9j&~wG^5o6tD z445;$p-597t-X;*6on&4f2nh>-%7Vy({#RidD^jL|HX>vbHFp)X?^Mlwc)wINB6-7 zYNds|4t$%k{!lLR&h9#(n@PW7q_IcJph76~N7Yb64hZkbVEw@vywV{Cx+1nP4jvii zc;KDuYR{O~c9VEU$9>xv+$2axBy>ii{)BsA(1Vr92^uv(HHGuQC`*iVh-W)GXn}x^ z5Cch1=y&hLEAgj*B$?oOD$wQMb58~QMfAyIVP!rvfkb_>G{FbaC2ecOa z&*OgnC$)6L{c|rdzIv~~=HS_wZl3L`Js$It|Hk^UEW6s~AnYIz? zfW$6*FayKaMdJn2N@y3X7i3~IA{Rp1_&#V zV1NV*gk2aSpw^<*YO;rGxcnLjUF-`WOpqP>|2X zJ=s~ZqE49)!m~dya3jo$@I=HppC5fYgTnGEG(fMRws{W+M9&YHXXD$Hzi|WSCf(9l z0mNEqaxNnN2kXzu!c2JNTx*1XCkjh&S+f0yZ@J^T-pT%=FyyzQ!p-yyNnvD5r!|XYDpW((ZkkCP^ zhQqsFbPB$w7r{Ko5&aJ@clCNhseI;{J7uiDkU9$Lk>g^4qtIC>K={3>w5O1!PNkB- zEh-=G(MI%qU74po^hAvxjRxN6hxsG-gK~`NEny&S(^}MZi>F|prkSV;O2Qg0|KtMSsyXye7SNk05 zesp*}0e)z;T6N5L!?VTjvv53@AHpj0AdWu0-RZcZ*oPUR2V{V%AC(hEK+1>y=5vDz z5FntcKtTN(ZpF_6?`Ng3SNoHU>3@Pe49p>{BL__g=<)B`0pn9a41_u$E0rpHjhz3S zucoRt=7QlIOm(FSD4q%C1RN06kp=}uvJR*l_^}cPM9HWT4yc>U?N7(9+~> z5K&*A(Z6ATIa@Ai-Y#;L zS=%G)zs4&O2N_-GiAgh!2uR?POuuO$2V@0W={%+d zr7hgTAnza9fgRRCle^GsBCYwAL^F$yMXhv2?<;wAxfEGo^50Iy9vJO9>Ey#vlzU*c z6m7y!UPb*891yZVxPI~N-8Vu&zcUB@RcvFhBmEKAA4EW?1L_@zS|FT)Aq#Z9rV1nw zP&@b1^Rn>_F#YiEm#jefG)38Itm_Ru;)GLNldI3eUd(fHvfGh`HR!_$GS518V9Z9t zlgtPKktS&3qd6iJpe7=q_1?^P<$$kYa65&bA2(d?OLv7n2N7FoVbMCGmy^h<018^NMCnr-@_@mG?J^X-D}ssSh3h zH8NpKNH=<{Ku~F+x0uu>wHk9k)PGG-1w@-*oy&c@@W225?i+DH*n=IhGU!jnKVQC( zCn8P3sQ$bxSqnXiYN0V1EPKnlU^?%B9m)XP%KRb(l*ZRnOJil75jbs$*|IK>&q?rp zFYdXBV4n+te=hndL_oR%*9wSv`X3Z(!4_DT#U=(JAoyLL753_XLJ#OM7k8S*X68XG^V2P=lOEGCU)oMz9Np zI-suDhQIPy2ZS8Z<}YzTk=q=3N(nq75q>D^4}B#nIW!9g4*V+Vwjt3^+gHi4Y{onD z_}0)&RNHvCPv)qyLOGtfd_nz=(EO0U^PNC7Q4T1Wh4paTqL=dwci81D^y9lI`niL% zyY$+djp}l}bc!YHbP505AP1zwYtYLrp${X4&5g}T$AEu`2SPQFIbs!%z(B+b5etOx zy+LcUS}Zn;dM+7AHwzyNHZu0dAoe=R6P>!ZIiH!BO4*Io|pZZg{^^mez2lRSx z9VvCw7thQ1NoauTr~%?VuqLO0DddHS3~v?D6z#&3BRz9K-;N%H<`5Ck?~)Tj9-28I zKtEp)0Ue;-Bi|pKy&Z&%=r0lP5IIt{@e-zEoLZ;Z(Q(5`XY)od|H4aXD5AC9}J zXE&SlG#|Jk0`@trOf9Jox)k?c-iKNtJkL9STznjl%?7*C-(R9zw&Udds0#;A;;mEc zxr9qcCUep;0v!<8bcibd5I5Q!1n4rsmPyOLUbYKrb zm3foCVzDJbE4+APU|?0D&4tJ=Sd0Vm0^ZqE#r6f$K#YK#O}Su89RYs*M!KbGn6Ij; zz>tkM+mJug$@% z*5RBljHJVoZYQn)A^E_A+AJkprUzNF{rG6#e_kLQU=n73~8R7`4t=;KRwm0j4a z=^{}10Jy36&LZwrCitN6m_W(7xG0Y`r;+a5-``IK9L+lWc6Ki`iCBLmK01hjE}NQ9eu?MJiI%?M`x76Pv}4fcW*&$q z@Ka09z*ce(jCIh(NsZlDu>%uR_!tL7YZuay^=kwHK`nv~jFOpg3KsNWypKv+#6f!< z-A7#$0z%xQ>wEOh`#leJz0RAJwo|OF$Yxm+c+SJxyTVHt6R-H zo%cJNZ`j5~5Q-%B-mO_%)lO_}&7xKjo7Uc2Vyo6DY7_KpwYJvYimKVFReOf2y+`uq z{o#F&BY!}W`+lDLy07!RKBpXl)9^oYRhc+m#0a2e68jpXc84Yd5Vs*Zgu&%^l3@M- zB+%UZj>`GR++r*PDe2k7dI~XhCu`2gmKXgu+j(Q)vg)9l!#j95T@kMLdL0~>Wbrav$w5Gp7w0Rd=y_eKP<%G?h?s#9L2!q#(pC`po-yd)Dg9-gL2XO&nvnZFx)RnIW3| zjr&{T?W?=Z8`$ykBN`!n(65x$n&i}zCR#iKeP6h*CK}5MG3F>kw6_&dg_Pyrmw+>+ z#u&^Ur!6f48|27Foj9gXX8Mi9R5K(Wz}|)u8-6EHro`vwbp#TMqItdGa%0^RMktYW zclg1ENP9V~AD;M6OapG6R7-Os*^B=--RkLE6`SdI5KU%x((41G3h4Bb z9@OX~p=zjJQ{Yq%OBI-n7zGF%(=NTK@HUJaKRNPxB=5dKz)-s_`I|#$?^z4}*qTrl z{U)uz#W}D3E|7aH=$=1|5&9D;$bR1&Za_5kXpSlzLn=kP6&b^-kB(!9NR9NbL_O}0 zWXftYooxs4wu2v&N1bG?c7D|pVG*S)x@!6J>58nSF!oeYZM?7OH5}A83p)6_7<28U zK!DRObYsXb+YySYX|{e5mZ+dnCUupw`@-Q`p(=j8)bC_Zq31;Lkw$t`tO(rXIWSr= zYbD&1efqzDV!vKynx7XZ4GQ>7lx1FhXm!=$_7Sh3X;m8?e{cdvqQZq`EEY&n(XhXo2mx28+X$!yt`BjK4X=I{c}wo7kPdLMGxOzD$P}cTeEYR4MRhD z`=7qxJrd83Db&}HTLM|ZH`GcsPr9FPB+PzJWnfxs(2WMZ+3&@1N%l;nsRrL?PnF0i z!*BW2;Nr<29f(ouV*2?nGc14Hzgyy$_gb(X($$t$7dCk^_o4i8bcB&OhfkL{{OYip(1pK;uG`8W_U12gs%~NOVoouyXfghny2H|WeF-a44 z&s8FfurLe~Q*NVwJ2<#8tPx=>9_1Z-DfymVwwK&F6S!+5IG$*a3MI&4<|<)0V|mGD2VWXgT3Uj599*~xZ$_y&6t zz%$sQ(MVkOPrJu`?EQ5>UYk>YfgqCg%Q0R7^;g*trU*Qh5)PGFnj+AVbb10CA^Z{l zxprjKp<(~BJw^|2N=+SV7*Zw2^OrWl#AuZM>$X@!HczK=%vpi8rn#rM*r`B7q?mYP zcn_^MeuN_`dvViSz>+EzEs>S=-j88L=$a=M%h9eiH?%&g^T|n|LvIuM*>_rO3 zyrN%67R#aC*qw8My)e4YhFr?8aX@daTUA+Wch|Nl6QElI%U-B#?&n2Qxqic3m49z% z`Bnmpa|+jmDf;P10{$rWG3K-bdB4B_B)gs6*{V24mfy*$sL=(N4(oFOz^t9?UIsrZ zgD?1r9*uicC&_b8>R;<{;$WL)fFwhHw87&6x^i{K@)$ad($Pc>bGX%I`ZpOgK5utU z7I$8Q7YnyrUzz(D8##2v-XEzI&)=AtUh~=f2 zY(y_je474p$NDvmU=ffF%E`GpB+i27(-c}Mn)wKPbH)B)*&kh_4xKP{R3^?8=Zn@` z>Q?gbfrriGa!z6TqS8;Qm=z@Ja(}IlE4uMg=~wEo>aX%KqZbv$6ueaagOxD>!k*q$ zwINo$KB8AhcmLQ)WSC^%QOzN2dADK{7*)?V5;lr^aoG!r`pWCCH3Q!ph$NT8Sx`t7 zuyZEp&A-Uix4ZHVu&x+nY&(b}IF;)sS}|}{=iq1bGs+WPwlbrW$-i^r2?6wmHJ(d! zg9?Ln?TG~|vBA6!?`)T1J{xzW0E?NYzOgC?V3aR5DHVT5)f7Ea)X`<-cr~6bs2`IG zZFvdhre2tcmk2dIiIU-qqa*z?X(8d_C(Ne7_~JQv!iiIPHa=7EveQMb5)p{dbY<$Aa#br)5L?U7%Dl{WwFY+ zbM3cYaO>-woFx0iI``|dPTQ0%0|_`LCaVU|MG!gerrkpF_QUPiNtBlVChwvguH z)EVoDyjEpRF-ZJG!4Xb{<0RzX;`@y|M7o;RP3N5?opS%zw=Cw7&`^`M94;?_2AAh6 zU~mu5U~B#chYERQII5KIE=q1ZguQN;U3#EX{vgh5#TRaCCdEc>3j?&~&bpvP44Ov{ z{oe}GYL@2uzaK#gAA!B=WLVKyx&D8yfhT-&oW_?C`;LA1ol?EmGw{;OvGOqR!wsTx z_G<0dWFqq}B>Q3~CV0DTUG)~SC>j>FA|1>w*CJm@qlgMsp-}r%Trx-Sdz=fm-s*=b zCI7H%9yBiqe@9+|CdKwNxceGF-Z69M1$3+!Z4K{jsY#F=4EsD7wh6P6TMF=){o3HS zK=G-h>9%F+&Xul;FR zdWMd++PNO54lE}D5UNDv)~Ue_uyLoI^BZNi<3;3SOJ`dftEwE~@LnLZ=viFC#Z|L1 zaXfUwoDMmjxc`qKB0t^n-Hg@36(svv1n@FPZ zTTAh&jXjL+q)~v5^@?SC`hO|F1NZ)Z`g?^D^@I!FKyYt?%-*7oL=RJv&7xH3+=jk~ zri=rZ``rxwNgT^2eaa8;8~b_Cg7<$NhRDQI$?{DlVX`#S20DI%Dnj>)!&Nv--yTZlya!Ld*+!*uNa3|qo2~+j ziwh3XrH6ky8XzFvC9C&@b2#pFn;p4~Gthdl8e6oKwxi&J=B( zT}(hJl(1JZa0VfIt!z)S^~`Tg%sgtM>NF;W=%Dv;qCYoKDWA{k-C{(x%oY}dzHoENO!2T0xBEDAMSf4q;-PSQk++YI zF=zIrw(}jCvf;0;{Dq&=MY^lz-_a10D$TiApo@K`kIYADHLRLsIY~vr}UQkp=(>v92^LjU`!34R`Hy6){0mffnMNl`8 zLQ}?!;Q|j&_bk2?uM{rM9K&RywgS2H4?ZwZ94w5%*c8{vw;E3myCzdt9rRqt{rkd? zt+HX2$C_)|q0FFuUZSu58NQ3rYV{=waT?O_K?TL9+PrC_D~T zNG_rx2;NN0@)S%u{zxp*eZeOa9}-#-t-Fp?kxgE+sy*C%L1A=Xhp(8)PrA?DF?1je zG|~fWqS<77!FJpdQZSM}J`k+)%Tr$}g5boIMtZXoLU&5DQ`qIhG288ZOLA(Wm-m63 z;`AdzVhZR}#zZS8U8>FaAS%B{ibWi{#@P$&ewNI-RuUWUCB_rUo1!l3uuKJ{e4|26 zba&)=)nTRC^^Z8eL!KB{-cTOl&G2t)GWTAU!o(Yc8Us$-^h~ZRX8DudF1()(PU(GlI7OLy-pzJ`9+SN)Y$-O%6-9nuZlh#&wO9I!j;A(&tD z_B9}r&=6ogBK-*r_iO`DbbR={61k!sTPC*G9~kGxc%UXZ8zG@Oxs%9el?5xBQdwu; z3&;JHP$M#Wa)xyKJ7+`c+!fcF!ZZkztOgM3k}?+UUv6I)t`p%@%^Vcv`shC#g#C5iI7F@+hHqKWz@_g=4%qU9vA+by&51j2a67V-_s6z@#0B z4_{({_2D1LIucOaY|x=Il#Qty$m#j9K&78^E#hJ9*D`1OOH#`K4smhBgpFO5a_bkx;U* zN?%4owjIg4ipGFb*}@-pQHzJg5gE@>Nn)GS$H;h~;Nc5DV^CE&^cNJmb2%}7)t9@} zJTVsPh57}OLHn}lr}CiHczq|YW$_L*eU$kMP5$8&iN@Wq@F%TsRnZUop*f{~y0+Xc zHwU)Rt&w^6zj1+jrhV7bN4;u3;!aQ{!TL*{e)eEiwrh_|Dp;X~UPGP->Ov z<{ z@zQLv>k}PG7gl|9Uf-+_t+!}I z;`s(0@cm#d4q%~ZkOcY>yP_>2gbHL7O_Q}wZ(hAAH?BAvv*@354=ZcXj%a2PQe?=Z z4qgj+mpykcB;|?dQF7^0w7Jwjv5O}hqa$)3Mah>K_>#;Hthc~3Sv=9)YPR)ubK?Sx zq>5}UrQlsM>7YYFM6{zEOCWl`-t{qxEl8j^0&=d~121Nz$_w^^SdBI1n>?8VCp3b1HJ>q*WO1Q+2(W5bX9-gK z<$P_+izjqJg9pshnfg!AHo;#5`CbX7e;$9;2wLcMA+MxiE?q0e?|Nv1=wh|(**C+=@yneRsRj|nrNV~s{N_7jLiNCgeC5) z@SGf(oQ}6ieCo{0_92qmVAaoE8&c{FOFUDsl71L*dr6;+_z@~nge$t;HsUZf+rg^% zlbE9U8cYUXUN5L#se}1X5*fTSQYaSt1?F5iZ8uKvk5O@^S+mgkV+G@Wxef6A zRK3eYt5lQbTvVt;4s4d?K;KSqZ^(Q|#Ueg+fgOW#_lTiWz5h#7>5}H0+b%f#q95$; z=R;k8brRva=RiWwKL9{UPzBhW#X;<(1?a=WbZ!Et2=K8!1<~=cJeOCG)YQ_e;{%?9 z)aKa#UVXRGLBK}g%nG}C$*Ua4C}kFnY$rg*pII`G&k1ej%U%zlUSr%4@fcw6$rdCj z>T+F2Bd^G2{+Byd=Z6)L{A-0Y=2R}UajHkpe$!^^gK^th;!g@xCkoH@mJ`SYv$7Yh zw<8eXBAUMaq}BLM2ZoH>TY@BnnVRAdxkI10Q9?%?k10E|I4u}s&;xg27gLkX8Uu7# z`n%Np;(T;!(4vhevBm=5Z`bmiVvx;G+n`6V_;B+V;;~`6M^9~#{VuLFxbDHkG{JwJx^}J3 zsVx0n0deY?`4=x^`w)D@xn524p8{sPa^B@`y#Jb6LCfsVB3KCaP6q86lro)e$@J+% zm1uwpG4C`CS8{aYx^cBT;D`EkLtBYMs|313^%E>Fh{D$FuNPGoWll?bMfN_d#>xQu z$87@mvTwCTug|T}k{@4ReUW#*|2BBln704UI>$fY)}i{Zl2O*vJfg{ytY}h8M*nUf z8PdB6e}w`e+CgP>3wRbMey0G2-13=n@ZRFh(|PuX`8WVY zKUCj=<1s=~omj1v^LD67<7V@g;|q=US>Hj@pDdEbXAaSc`>U!qBtMaz`}IYJ8Ww`C zt4xHE7u2l!ABl$*c<~mHuY6Itf#)-fDCXc~Q}i)xnp{I0>L~i*>0W52N2ZMVeR`8k zq?)A7+ZZr0A+?#D1Pv*4LROGU7StFogHG2*FRvh9?!?6@nxbB3+y_nF6Hd-?r=I1z zY97;Qu}eLVs|Du*zPbEbsBdPIO^M>YQ>kOpzU7g4s&~E5eM2DiB&i(7RyH(-;(cy#LAG{WpRx zt@kh#h@?48)5l^{MGpmj~ zpi1e7r+hnlfDgW2y5feWwA-^oeX|jdvxqC=XOn}!-7$9jxj3j{e#6rFJ~E>9i71JD ztC5@q6zbyS^lx#-i9lU4etSaoUN&WAio*j*_Yx+GF-wj?G!e6i|D2aA!;;@I^_?e} zzpI1%Az$hUcq~r(pKAhfrLU}f)fVpd1xMB`uIIvraym5h);@r$EJCR%ZvfA4POzu|*(4_c?cHN3 zd*EH4FKpiz;Cgk%|6AtVnU}xJmI5y){%dY zY}=DFX9FlR#sacbzI`|T%@ptIoPes2j+nU7AcIH6L`<6#?4tyTDBM-U~RT*ZmMTdHc3G(`5-pim@SA~ z4*_7*2HQ@fD>g@7v%--9T$^FZ0GdKFM=tb@9XahVE-XX#!1p$I&bPQ{vL z8+kvVq1dX{rvD2m*cr+VB5L`(&5*cxB|%}AJ@GBGbu}Uu$xk^c2n9)TIVsE#cooWf zNGKXtXR?>Em~%R}^N(~ItbY?D#!)mZ*EM8^fwX%rz%6ynz$oFYB(nj%_QJ*53mXzP z&iy9{bkxH7WnUNecA|;~WHi%FC4JnGM{H}o%ssBjYFaNuA;aaA5K>2md&4ECLc0MZ zCt4D_xj)Soahz>~?viNzZe`4fb;+pJ{G#!T&(AJtPGN6QE=2gJ&hlsSkAxJbuJ_x- zc6ptt9}GOvQ_)^dU~*~Y8pBOJ1KbSvFzs16a&5IhD6RvgWLsu$ZAdYq#-RJZOzq@r zACujl@Xkk85s^eH&QewsiD#a@kdpEcgIip2^s6m~?VWuZ@PpfOIAUo5>USd?zoqc$ z$=!eqSwg|Da~8vYU#61*D7|>j2?#J-{3c`fec=Mx@Xf~0?9G34q$6@}TnQD$DSZ3I zpnF5n$%!Ft5?$lO%G?uFqa1B^^sGDI%H6*czVA3B1lZ6|KoTMjDM<3cwV$JIYSzM@f6kC%Hhveo@>K_>SdqMCQ*7&9*GmO+FYe!MJIWSS6FwTA!93C^!P_b$84Lv7JejVUR|*C7y6G)C+YZ!Y|Dn zBWBVCEQ;qDv~v@5J=h_EsikUlHMW$iNN~B_-~HnkwI;g}{dWYq>F(|doshYUuL0Id z+c~Kzl;|VjaLoou#`5U;@vE0_7_{%QD>sXhD|4?#%6PX3ADxyNICXg&#TsTUAnt&y zP^Tg{6tYq(>|VR|v+sm!r2KFF5#_2czcnFzN!pZ&8rwPlw+wj+qAm4=f46#@&`y&^ z`U~&Dc!CApo~Y-@*Hz8@h3ZG%pnlD`ZqeFYY<_n)5*-fT3K6@dlLp>Hv*TW5#gDjp zkC1iHV(;>X0q&jP{skr;`pAnPEszN8-*NGJ_#SfxBVlE3x}h&+I|iyKx|j3DpMB0m zOR#bc@syF&4822ijF4B}zWQ2Hj^4R1J+5H$Q)Hx2UMYeWYsQ~=BylL+xVX;q>tfXJ zT|;NAvucL|O3tz18A(z#GJwKh_p|rR!;F}K`S!Kt)YnJX#Oc&$lyitmNw!WR(*)VF7jz> zB{1iKd&BYjbJULW$zkOqLrsNZc1Ich40aeJxGTUqsY24@Zg-wG{p2K;%IobmoS<&C zT_R5&uhGZ5%pw}N*Iv9*XRGXBe2mxk$?hJ`saw=$%5a`h4NGB&NOIKfIp?UR^Z>?A zD(ZbMi2ktVD$Iy3J-=9AtYzp;2^(xyO${2la8VUa#f^x>DlSCIMzKNt{vKAZX3PH4 zNjtEZ3$R|t5PY=~BxFub9*j=#WH>Lf+|F^1Mee5PL&9KI>0|c-hyBE9oRLgyvoD9n z?Fn(+r`eIBB@F1tBT4vt;OKo0f2I*(f2w#{+PT;5T{4~8Q<)j3QbYyp2{{_!Nq zJqd#?M=s_ss9TAtz}snD@eqjBLPpRAYPTUiDey3Av3ZtiIqe_g#ZAV|({}Q=>jnEH zSXsP}K@de5_Ocg*$j%r=PF$#_Tlg zdx2OCknlkMK)J*DA!l-YTfnLxIA?6m&aqyAC@tP{Z_-{1#4g(&k3*5Ey_~qDjDokc ze&yBM9U@@Y!W7v+q&FTy&+RD!ZH02>XL&?BKlBsm%$c}chwUolqQEzoiv2KKhGp25 zltdzB?#-H;id=M-R!Cdn{a}DcRFVRP}{Vi|QV>_@#t2sjs0QIWLwN z^-1vh%g6b7tsZ3sa=H0lASk`Cg#7JI_m;E?xJsS(^!s;fD#A6^iM|>yxDaH!U42pE zu>ovW*p@S#@Q*7(cTgFB&GWlYC_x9-S}?w|2?$}>9n`v@>4P0g9!J*IsA=xrcuFt9<&t$hP|}!dk6Pp6Fgzt7(KU{%i zIA1*>c7u0zc&w3)B%D9(B^Eu>dkc(|LjQin==VxJq?W~>!~)4vkl+0w@mq_` za`onBdpq(+LBNobUf(qCcgS_am8*0f$*ps5^0;FK<+gAZjN$+a9_M2`Dhk&+)@D zj)ieY2BbE-t=sWWKJ+yUUv`|H|0CDmUJ@?-1RZ~NN<^I1o_sb}M4WuJ*{ztN%k9^l z?6Tmyb@cxTr;aC;Uv>Mb+;DJy)v*TrVb4!q*X#3%hsgJMX0?k(4h>tvTiXF)LD|5_ zaN;ECvd2|Bly&fTu`)5nQ~rUS?~+eoEUfxvO~imy_UnrFNkHMeX4Vv-4$wdTU&e>a zrA`hGid0A|l{0ApR2AiWyd~AGH{0qmkwR}d-0D6lW znRD62B&1c2M%j!tEYvU7R&?vTRPb=f+j__ytTp39VqFf{PK;uKK%>8bA<;ZdM%1e{K7EK2wJ@IzD4p_qxN**5|o)66D|-M)z2bi0mlr@4F z2jLTz)-xs1##m4d=(M!k(rlqSz&8*UF5fw1<)q3G7#&jUSbM;6a0gJFsRKSdj`-Gr z5KLAzFYpcy*6UmhS4&qbY)Bio$G*n$@kqRpxZ2m2S@j}O=55?l+ssQ`8#oMPUwhMB z_<0CO9UkaU=)*9CyHx`9FIT2%`k~Bg-#t~=z%LN~!SV&yQ-Gokx$dlv2yQI z!(4^QCmQRx4>SG7gKgD24YsB=4s86F%%*pNPmHj41ZfEwOPep zn;B-|Ya48IZq*W9dL4k@`3?SjKMAOSMi~}j=Wm<7a-)lSyP@p1lB836f%kwE8wEHY zIdsAb>P_C&>RcsD*0xkqlo63{j&YeWD-ETnNVwK=W~R4K~LlS-sMnFN_)_1+l%w-HHudD1~0m(>}OE59u_lQp-&)C2jNSVAoB=a(?&O z1zAVOrye642#Mvc|0pBZA6xW6V^@O@sk{C{{5y^L?*&%*(OYt+ebS;UO|c%UKlisv z=00L(zH)K?)Uk7va+Zm**a!AK><==z?uG(TG)nVJHLuYvMjeOpneid)(s>AL{J|ZG zthJ~dGBitwDG?WkAut$_SV_ zJAF)~U_0$6F0MdqY?AYO)c&{vs$-ObPRZa1MBzJBN=ylqS{H67yF|3qrY_1+vi+~1!BHYRn4Ll zId%f%sbUkzixbnAar}*MCfEmfC;s_B+ABg*GJ!PwX#%6>l+y7zqaB@=QDrha>2rVN z&sE>yIoST9q}ua4G2g(>r2vlKPiL`bGn<=E3;8JC;EygX`|+a!@ik3!!Upd`*5^LT zFeRTRY%aTb!_7B1`V?WIcZ3%AQ*G#N<&RNE4>^CgkwjEqJ()`AkwrTnds3V_rU8TT z_h^OH&XX0|Sk_)+;IAF!#Q5CHn_+rkTW@wYF2Y@})3jLRh(~Zhz=g>p_{#+TMzT#y z>5$peIpUKLd9|f&_Pj%n)g!OGZsyHE+)Zp+NBi&P7;P`!rk>5cTY3=fqP$AT)Kb~G z>24fOgHg*9UX`%h3nh*Bjb|T(tAO5R$EQ?<_?)cA78Me|tnvl(hoXRMElw&RsZ`xS z8QhcbSl$sALG0WxpyM;Sobd?~@9YqVR-$5O)Mu=-*a`y(isMHg&gYiQm&^@L8O8oXMdI zDcf;Kz(n~Q8j!clbr!jrC8N1W$@s$>tHgHuN`|+Vg(3hz_Fo1lbTu2V!}o%wUEe4K z=O_hbtACZID2l4iFV_{@kI8J{|3;2;1Of~+A8#WAHQW2Z?LQi}B_|=g7l;Zu&I}xt z9A}%-x_s>%FQ`9Upy3e^WA_lqk3t3Vgf@LYglMy41KTXZt@0uiXVn#mlGj>O5dALhKp-@Bc__VzIKaEGbMC*fMg-(>iYS+#9fa8gjZRL{&lSxVdaP=?f2Bc0B zUxXI6s?7pE)B#0n>pz=|0-Q5x;CovO!Qc465eL^&VZE++1PqI01QFc=Gt-ZM8>tY_)G-ix26;M^`J4EJ85TOoa8X|N2G#Df+A) zi)7bmrOOGhkl{>K?qA{t8tpEqQqL)RsJZ=k$hm^tvQ)kN4R!jx#SJmYYopFbOiryf zY(HZLsqvRL7oR*dQ5AK7K`N*!81}H+L9CW)@O&ep{+J2kj=SKyam`1$QSFR~cpSeY z^ZMj*{!~O3kFG1?Tr&%Am|;JXunk|ZZ2djMuzD&2}Xt2|93&VKWNCJ zpQ!t(2-GQ$qKGKl%smT^vyKkiJ+oq)odNeN!!qAx&RwZw-QZf`|f$hqS6C2bw`0p*QSzK8+c;pc#-@u)2{ z#w%~m^~Ix%*Cf^dvO_uA*ijuwrMG6kvuo$P<1B3-QA%Z=k8Oe<4o_q5u~bnCXU=@; z7We3TZ2tIhj+wfTJm|j2Mg#&f9)|e32UO)S4PW{<_DmyvuO~NqJt#hvK?%P!)TCOI z07^Khe-0}U?Cc5oDpO)V{gHtu10Wag12_FUqxBnLVDidunw2jAF<7@4!i*OONps00 z?O3G*N!Bt$H-@idmeZ)@JzF5p&i(FS?VGN45g$U!pnp(aY{hymQNtAVw4$a|C+H`D ze-0o|d6THWfBypHBNm%oweondX3g$ii3}sf+G;{Ez{rq!6%$pV{)S9vg(zsXxc-&G0`oT=incNAz&=!pe^|Z8RIX1(7nVGx0b&3D&m_EHdd~W2_z1+#sb1 zM(0H$lei+9fR?7xx#k^Z@QCR%dYi|SDF!cNRHC%zIr#ijIM*eKC zWG}L5-T(95*s&A$Hs>FoaRso0R<84R$lf4HNLSH}-;{B^{BmcK@^T zC(-f0g&E-vGKDD=G-3IcFyb2+P_fNj#abxGT>XR`M;mN7R^r8i}SpS{JHE z-X~Y&!^-w54GXjH-PN6TXWE&;Hz_$x_sa^ZNAv<*YFd1FCZl@5B#A zjDuhC1h#)4^~ICE)9SyCcds%O^<x|O}h;ub{iULz#zy0*b{^~V) z1U5qA&@WxJCIMJ`!BOuqx$?k;zCpK@`8mNmoHD*m==z~w8sIJF)j|9%L-*MXK$fw&< zjGHe+9l6-sEsr@v>U{w~ENo_V_dup;rw5Zgn%Hg6*s=MV`D_Am z^ojE7v-&HL&te6g3u;B2jWovA029fG?Map!AD?2Hb}A{66}tSo=eE?KY%yDdCsCs( z4{QIB$(0lCUd%+WB{S(tC?}e#5*bBxCHs4S*F~%ZH);BX^&|9jSRyJ-s){Ys+DC%f zwgYt8Pfa}GuUTp#``zhEVl66GtU z;`bimq<#=6KHN9BrWn5_t@QP2$q& z_-=8xUt*pOtC8|QU51XlJA-%W8wlF-Ws+mH+K>Y1=mou`^u@=@yJwan+aH(l(>`w&}m%sOQ7 z&?^?H#7YPnbuamtv0Es)r)B7=-RIoRu`eYbefk~X=%~!|ULMsUU(nF0mvC}r)&IG_ zSPkxq4ejH-D%w=I2c71e;%y#2y<9P9U=RO#vdouee6)%3 zyW?lqg$$zKuU(bWlf{Ypopdxd!)62QagkOTHD7 z#Sf>@wkAb|h|ZceXhIaz6ch}(9MzMOrH(76%qMIC!Ba2ul zIuLtA(_e0MVxOEd3QnF6L^#S3ThC~`9;FM$3_%9qdhvK~k=HoENn}6S!+wAiU3S9W zOg>2;Y`iJIV6H>qCtoRd>Y< ztOv|4rA%_#leyCMi~YFdl_?RM{)olb4|)0wGMwYLWFUJ_JS*8o%7G&b6U|3tKSc43 zd3;S@mUHrHa}VH~-vk+0>kux~=|;h2Oz>P*i<}J>#dbH9JkR?;$_w6LD$?-=>0Nmq z#JU}6C6nl8%T9O0&xlE!QqEitI}|X3w^;u@xyGBdlTiMbzOJw$QZ0LcPCW2EMT)(B z|0$J{tI-f8yp34KIpvJRPzGklT}kEmeiD|5C-;sct?SL5x#MjRrPGtkhj}tteaiBIxi2dMptR{f z##4Z6!*C5z-3|r!O+f_Y@#66!LFnT zC0^M=x8(K3yeVeQV27eR0h$X#-R)3m`S$R%?bVK>d)V&}un{Znd{F2ZyR|es!{-mJ z#0}{WRg;`ZRP{dx&H=E@x#9)J?T(tD5t7DUB9Ofsf6=-O>51JNmF>{cj#6>a8NJdc zIUv_R`HT2RZi_s*Rc!W_>m0c3D)jFTl@au@YvMY}m z%e(?ph*5bfr%?EYhBj+jMs|-le;GMyHmqWKfJq793^-!eHCrendMb+%V=%`Ecg_=u? z2~)LuB2n%ox`Deup%M!!Sxj{YJuB2d(tv)@+7^g|t|J4b*Ej@7ozsBanztzm6|>5J zZDEYHa9aqy7hH6+uGfh0;4=J4jr$~ki&sK&ea3;HV@-`$EcN=b-XdH(uwz&t7&8;{ zHGJmcft-{?_DD%0F- z>}30UAouC7S3P8+ZN?{Qr2$J{@%BxSZz~(%Th7YdtrsgtF33RG_59;`SyGPE@;yJy zV>$|{y_M9M@K>4tQD4`MP)z_#h%%U0&}Tk88|7)PP#&WM3Hx!PD|@F8qMpd$&(_q>^l|WnDH(k9vV0ZQ;x4F6-eo z9v$2E-^Qn47wx0h)PuTBp76ODA9%q^ME%Ssv1lI?KxuNsR_>PYa>!(IzPpKs+4$LY zxoQ|=JW?*_yx&t*9Rqm+5%&4+9gi9qY!N}c<#j8)4hb>$d1>QAAT=3F4{g)fnGlk( zqZ9)Uy=Nqax)`i+oO_6S3dqlUFMQhksqQD$NS||YaX@aQ6fkqr{w8j}{ydQaAPto3f_ zrpK1l8OQ%$uGqK4r=+BkX2v*^FM?32S2RwbnjymLOKWW&IK1-bRX|H24!fkh%vflb zop&qS6>xkOsSuUGu5xPA$W2#_A!^uIFyLU`Hlfcp%ZX9Lr<>{8{CAFe z59+@W<1C>|qZ(ZI*U{yefA^=Q)XV{tmMSjMNRJh;Ij8V^_I7UPTQR1W(eydF6#A;) zCla2>zXiEj@aV)Y$nMI1J0z1fm(EXh)k;ck?e@p+8Ucf2U&rRqyL}cPX$MTO*PbF(6}`LgFfZJN+)UY_kwL(foUlEhTj;vPSh2X?=A-`it5hv|z1Lz_)A+o^VaKgDj28b)f(#Yle=H^E!_6;(#Wd?^yLK zoSwP`DL`_{c5Mi6P`xj@+10>(Z`s4_iwN=fy@7)>8$^n z?jAPo7%;lKLrPk@M;kOKh_nbuNOx^?N{G@hPzj|Zq+>MP#1N3~8Xco!d-nYB{TufB z?3{DO`{Mii&?ZkUpA1wZF|nXw>0FZ)UM*zq!r&qw?D&L7#Hup4HxfQXa3?*5K!6bi ziDbM3y0i15%(@h5M)lnIy(gmT$93 z`uSde!mC70u-zUt&^K-_Qq9|uLckw_j|+69Klt@XvbPS8^zP}*>AuvuX%fFT=+9e7 zfDf{}Yz-Ikq=3?wd6}^l0x@U$RIgKRPT=CtWtf(}0R`4}-A#$+1l$>-(&CA0A zrtII84I_7AX9&Xa_RBxA%*FKR>Q3}13da5?V6F51_itdLH~5WCG+R}%4#$+5f-6qG zra2P(6*u7tChJt;Jf(i(qyb*p+ejf-`4138dDpwL60-TU{O;Ga)&V9OBt-vUHK@dg zU9^>jJ-O;`yCICsq+~06EbYkFs3%!cC&ClzpfL82^0q5 zt`ur^si33sj^n}$aJrQAEslE-V{U!@8ZddC$ForQePDOg&4h7jr4Lk<7qpT9Wjcjf z&I2zUQ~sQ!e*W#~-asq}IRMZ~MrUnhL-C#UqbQ=BLkTrwwKBUBI4wSI{D2Zt|p5VU^H9OwH^W`X z9sF9;j9`2G8a5;No7#-}cSz3rEbQFoseS<0>xV!h%U_!JF99WlU!;Knc>lpOtn_u&aELy-Il z$?LF;R&@TN-d(&m_|*}fi>EL`0}1=0MIyL~WoHt^6~Yr%3%ec@3a**HaQtz4Rl2~` z?`K(BItS0*ecLlxxLznphTO`3NMxa~LzNR>gS>C^oxeHnt$LGdrCm1DV1@9Yu2=D{ zY}3#6OQCuMt$NybZp(Nv+2D6Y`0`FE17DmC5*RoXlL0tq3QUqxnOZp$ClJ(`f$ys% z#nUXzft6I%vUR(^rgHtyXumo7$%Yf}uP>$J6IPb3$vDuf^C(AJ#Z)@P^dwI?w5pE^r9oBv0$^{eO37^$cz zGeNU&g$+MBrk(-!+y@Rm*EBeSKJ0I|YL719Y-`o-WFh-jlcOpJ6FGelwmKk_$7E&5 zd@Fj>Yx%>|#D`Wc;^ab!r71E276Ze_z=@?NR(!Ru)Grm^lKn_=`Aqs^52DAtglI@- z{O+aFQ+NuF3&)>~4tFS^Mci2_ZQSeg&Hwp^A=bBKZKY|IJS_jd#;8kfgA;GTVH0-k z(6R9FR3y7m`a}g4);Y8+J-6_&*V>QoTMDz|{ zhsFRm**-;48$3%IK2vE*T=b{pD`}qEgE^@jEc&%^;EyPB9ecoBMxQzKX0lJ3WCW*} z)vQkoJ-7Wv9S89KF{nN*_Iltos}DAbK|o;Xf6YYrLeKyQN`-AFSalO$uJc-Xfqy&H zyh#G!;GUa==`yYVy0qDKtXX_l3~CVamD@5EmuX(HhYl0wkL&fK`70#v-el@J`?VZr zO*;|u%5o6b!DN`k|H^WtP#|9Lhda^#iAb4n{4-W+Xrv*2p@D@_ok#}{{~j0629xEc z{Hu0AyS_`Fs{dEHBfk8HQeN1)GXg#RWQ1e#0I%taD1!uM=#CplAQ|t+O3gz7nw!1& zlv$PXM4O8|jHq-T{eDR%L}xwl=P1Tcs13V)%Ge>XuDgyfpJd-gAB zG(*t8w#~dBt%{GxAHI>C!Q-9JsR`Wd-YMAi2#Tt3vQL>k#9 zrlwIr)io|TwC2<-tq$g0&*=$_U2}B(I$-@xf*}BIUg<0RXGwoKgNKlSpcZoENh}(I zHA)<+e~>5rvGKzkZ62K%U?T@)B#f|d_dgNsfgEVZ&)E3w53;yYE)fDi5xqKZ?UQ?y zYHPbDd2%-5j_0%ViG-AkfRXk)w%8WTd=B88nFaB76OwUX=q18~xuGqn9zeSB&arlm z>i-#H6u1)`!5gxlUvil2AIZ!{Pr(#5s(@a_R^7UySsG6@vq@S1j=3Py*vzfE)HWPf zEQDaWe8V=nNC;Jj*kwohAEFfKWRrYu&>X$K`5euPsn4){@`Jgb0=dRDNWvjD(qm0h zr*NZCa6l4R^#IS^FAxuB+t!Z?BOv`fr_uRy8i+)e*L!k@d-#}?A4sLN1V1$7-xxUT z2nR18e16H=1p8QmviM0zHaIJx)axB5Xlj)~C}|_Hf;lws%S~@;G=velE78M3O#50NN$)~ z8FwyfCUVr_!rb<^;R*puYG;Y}+>&|T$agfQH}%W!k^Ra^+o7fofG;<6Y?H9Su=;sI zKQ9JPaHa()l<}|&Yq`yK19;kO>Vbk)_VjLvya>hy>N5@4sMYn zU=|M2zG&I85k-c=B?QCKYFqcJX8R6C@o}&@u zBpa*Qs&TdV@HhV{uH=`ufoT+Ox`x6Uglw~X;nN;0F6)bz@=7CCe{9hRnwnELYl#Qk zyT}|^%UI~iYOlFEy;l2Jp#2bFw<$Nr+HdZ&jvn3E6?XZg?D_kR9GX;Tz9M`gCws(; z0Q}ZtHcxhj7O|%&k#Y*DY$;)dz%JrW>X$&O9dS)idowT?hmZ3-IX~5gX!mB&J!%yXg zFO)2m$Qdi9AIT9FJS4G<_u+Yf4_q~u%8X}nv}V9<^m-+qx6U4D)zyV(nxhx@Ry*Du z=Pwd!lFDlzA2`EoNcMh~Ri2JpgXr;t$6OlZkFbf(mm4e;0%eCi3YBC-wGn*%jNWIk zaiLD$@T#V5IrJNKBCej)#<=hRI)jqYI+z?z4)b0iiBesvu}@YS^K}{Rt34Py){W*# z1{$#mmII4NWWZo75vCsRb2~%zUjWue=%Y;C(|JFMT&TFSK2c$}MqmhVecp@_<7Uix z^kDQo!CTkIUHUe&C$8%M!~z1eP7+Aogvp<08sitbYSP{ozILH1r>NABxZeg|Nxmsq z;S;ty@OJk=*AV)!p*65gHK+|vIm2LXOWxgS?GtjJTX{16RyfE_DVenIxvMOxrEDMo zW9(soS$yaHcr}af6Z8c4Us1}3i9nqi@a?mXX)UI_pIs=t>w%9o>$JHs#ah+09NW6W_~+(NTTA!Nw|Z)=8I5)J|C*g^>ayN?@J*@#@3h?` z(|f6+)b%7+cH(2=!U?Jk?o1C)&rUwMKu&P6f)*nfeBsoICsNDM>76eAt0=s2=#F5N z5($egDZ;hR42-_(npeYHDtO0Tlmm;)w~2$GUvP1h$Fr;&F;9x|Fo!p|T2W)gQ26Sw+sLer4Nizg90vM@S5Sef^Z zWbnKE_1-45C+S)LeYLFTwP^e%v_+)8fFb&CRPb*P<-2jboVMTZls)TY@B-6KS#4D zeBq|D+QP98@sOTg!^M9d7dsU*+;7;Kz z;_l&G@e@52Cf^oSu{Y~xd?S~Dx+vqU8s@S%pYsD8-u~q)sI2RXJ`7VDEwZL z;pUqddxu6D{wP1ie|cHcTn+kBaWcUu9rO~nm-RH{iY*Y%`+`pkoBm$M*Qrq!G*YWe zu^(UQbVThu^!3g4*@-v&IRXFvB-WA0{v^1@WqdmtSf{X6KCd<6OsEb&*px`uC=T9~0rQ9l#>TIX3Ne`-q8Ts6Ghb=@i- z@Ip;w{zf`K59%NQ;SFxywfn5W1#76qn_SIO=Ay?})QXG!XLy+cC3r?XB7t`5^|Rz- zY@a_nHX)@Dh+935<0oh^#=3=B9pNtjv6>Z7P}l=TXX4q!rJ;J*2-()$M3GJMLTK*q9g{t1d9qL0~3sj=FSDRP|^AD*A_#l z3kGa+BYG7+ji6pvoZ2xY(-{U)dn6oky^BVw^S+46=|h?cLs7eMs|oOrQsB)5 zYts1VZ<=M^9J4r#OXPKriHv2+RBu358(LnONT1Hp9=5er?|gh!NLy?@+mF}&-5X5^ zk`($Ql&NbysKJGy-(7rSH zkz({t$T6dQ`dR}H+llChq=XRa{;MRTS7_Gyv6nOPS%v>3`=8Y{PHuex*2N#Wo4S%& z?&j-_hyM$1;iVjkU(5B95NXjpmMHslVG+0M64l;BuZ#NaMjs%fFZv3)jg_>Z6xnfoM-cBBnMtfOi0&S9mfjsEE zFb-&LD}%-4;^6jntboWf^6<7*P$*MKpb8WL zI1T)6i%;R9Y7RP*Ux`{{)ny4NENpcS4jz;{j+g8`ZF-CRvR$Ym(|TF=sX%O1fdc58 zl)lFOsmFpW58MWzy%qh6z(VF1^%GIx8ts_IgHhVmLOLC;ZcWpp>GPld3&iKEaslR_ zU3@HaWgZ}f{jNozzZz8Q*0PqV&!^A+ISRqu2SbCw%Z6^L|@-%J;OLE&J(;c zjjh1$g^AM1t=^n&?DzSm-#y=eaQq0$diVi)7^+S*&Qn<(^fkbEzgOOee;!omU1ZV( z_6DyhNb^G;GZ~r0W7UyjxhV3G>i!#c#m`cV*a_qm!D%a-<4_S_^ROM<+?*LCL8Pn3 zw`DFmf}NDUIVa*b$oK!bQTD@MdV!B*@-zc}7dFl=xW`45kN`uy8PJ6HU08=R`zd53 zu*z9W*M<=o1G*5!TzuTo+ob=bl~YV>xAN9|p+b%87jH&9)ym1rPSuAn;)f2)&(Fss zgT+=Dm;ddWEZAOo{}S6j^xrwG$^)-PRr?6~VSgQ7gLGg^MqpfK8Z-LoG%*&-`50|$ zDvO1$`l`o+%c45yQGB1msTRiphh6;SPMt=zg(LQ$N-rs*{6&2Uh+numhP&Fb3=Eqy zUY-Y5AN8jPBH|!yUMz$H7W!`_gW&n!l;}^CWP|PGiT8G5X8z`=vN0`)X?4XD(MaZG zBh#=o=$auwgEVhWT|oBkYKg=BnWb{zl@CfJVFlJYsp^uF3aUg3Fb6)&1+~I8(#Ilf;$uunnJC>R+ z5>O_aVjW||A?o6ApCb8`=$x^u6A;pF97?+uKT zgD+!w7T@vZ;ea6_j%)(ll`kh3<`x1kkaxom6XTaQxRLzSEmQHF9G_9D*m&yjLjmxB zmWd{Fq5Wns~O(5^T1$H>e%uz>^x&T-P9GZZ=9ud>)5G!?MSmKAoL6g zQ^2;>c6kH4W*LRP4g*>g*P*gFwYk#mDe@eP{W318-JXi*?{{H4&kGwA8>gz_2NN8V zBz2SxPqqQ}zv**3KCU!R5})X~G@Erx3+a+>a^cw34FYh_Nz*9WW}ZGcQs*4)Q zNwi1!nR17cg_2Ke*GI0%5jt^8bCFVrYXHyzrZ{B$tIwnN&eu9B!(jAkh2CJTDc09@ z6WNAuC&?)5V23}yWxCEnw{~fy$7`+@P|fF=mG31uxnP~NtQ4D^Rzyd!Oiu{_p>qel z*ZLM9$*!XT_>;X@^3nwQgV(-x-<^thKp6u76Hd`tV~e}IUiH+0)A9GcCmHK4Ma9Ui$4&S5i9cq|LSB+cE#8g-r^jE{xI< zri*ywN%rhKLhdQOxf8@Z!8-pWF=v#i8$V2HlX1*uL>6?h)_3PkZU(!OjFiQfC+A+~ zg98BQ?DgKM7wW&%Im5-T3qo`H_9jA8JV~UX?^pdMjYbb$E{yCa`76Y zZ^p?sG3T@Qh9)Xd*~rt@NQLVJOW~|^-`Cgdtr=sA$K{MHx|<=lnbv0qjV`rsUZ2o) zQU5k(u;T#w+2%w)PdnRJ-qJI+%gH2_UQ^w#KtkfEy%?7PEVx&+Xn8aV`oC_8JQ3eZ z8C*%P=5IipVhJ;0FIzCHgdG{FW`#>Oy~d2iBpe_*X7QW319W_plx=)|d?3k6vFc4) zuX0ZN%O}ry;FJ8?2N1q;O->0fp(m?>^#tb=tLtYe&lr%7@*G*<8U<+YXIi)QL|Bwx zm52!|Lhw|d`LC>e8Ey`tj58BRGIxuXeeYLLV3->dCr&~wN5+s!@ zo@W)MOz^a{vw4o=1vFXh#D67O`m27>Iu-7Ien25wU-f~Tx}GHu@N`tIfe97yoUBZ0 zEgtbXK3$V{Y2Oo`AS{Jn5z}~;{E&M_h*GJ3LD~g{lX-y2>x!ej!#42oYSeU&N!LJ z!jiH}mWer8!Y+ZA9iES>ZqZ&3}@Ik$yn9miQa|H%Cb1&>sJ$ zLJSJo?^RAJsqFKjIep;)&d}zqgFMCw!pe>h+G~(rp81qP(#}VRgLlh!44|dt9o2yV zn6wx8&>_0b=D_vEUg58LrP&H|C={iJe}3e?8%~33A|l9oQoeMQoiSFe6SEUTcp2-h zuAr##JC3AWvO5E;&u;B6AF9Ns6kdY?CMpvXcOZ2U9as zH1bLrYS5ZE%wB1ve3nnO2Yo?_7I==$ROVe_Nri1H?soVT_G)#{&zn~sB$t&wj{PL- z0rN>8z$J||BxrDlz^UZPpIaJy7RxT^cI6s!L;s1Y~hnALlM6_!$6?_JA*Ooo~}hPE@i=1H5J@h}lAx?ltd4 zuJ0!#007PWBj;twTz?+KV_T-;&=rpnD)}`-poxe#8Ns9(wcNB3sP}Z7r=SZ>(dsV^ zML+wGb72hdo6uxag1{F%#+bVcfo$Ri1(Nf!XY~Wf>z=e9*NqalGjtAN+ML;vQQ4*? zD%!(r1+XmRoQ!zlZlxK=bCcC8fO81d&68o5OrI^pd;a7<^UwGptCepm`~N}$L>U?= z6ZDc~K{OvP?MPxvDRJaS^_Eb%-t;-yqF=Fge7A@d4CWX{^itQQPwUrLBq&nm`c94o zknix8mjzDN4|-)ep$8B;cOxpIY44( zd2+!|N$FtNNF2}1V^Zgo2YlMQ5C?RAL1IsQ|IH#;s!Q!=Y2%x7!x!HMWoIZ!7x?70 z9;Sh46&de<&*N<0uv(4=Yr@Poah zsiUJ~7RaZt8}Q>)1q*!#R&u~hR2YIy*p#Wza}OXri(CTa;g+i6j^nRO?Te0=cn0SX z+(LbAUB6ll5gH}h93K?nC&y81dXsPoG1%1M_q=gJfG0jds7(~~{u#&wX7Y4QT`&;* z#Gm_Ve>ayvxFYn4UONCeOP|;$=ejaJN1d+=t7gGllRLOkOa|JmG(_6|qgJwSf(q8c zsk@u^X__3X=WW=V(6?({LS}FEj7WG$xD_QCq6q1nnu-XE?~^^4Vh((R*XfAbFzxUY z@`CmP`HL=#8i}v25%jn0IvhPLPjhPw$}?6WRD0?Z9qLL^OT3N{j_AlXo8Vxr?dzV2 zq%5aiunVN+;LwWp4M&QSwna?1(96w9dQLZzAVpD&-*;SSN5UaQ>a@6~NX|Q$02jxg zaI2FLe21K2Fnny4PUmRN#RmsSkKgY%8?bF!D~~KVmYzcqn`wllUm2Q;vPVA&&iAfZ z{kU;qc#;7{0_zSJB5q8IShEHrdHL?=5mbwYy@10(9prza;$(3-hHwyOOOrK~ui5D= zA`mMOG-V7Cy+B?G$ipg0DCETBqW^8|?OfBjUXHSb-^WTo(z7eJOt&%i=|8*kEsm%p zEDWQk7X`l5xPs}AA^J=x2sO1{Ii=#e-7fTn!r}zJc z&z$JgPJ5`Y?2vw(Raw2cq0+aNagE9A+?m`_+JTO_8=XN00o$q|#u;ud;;E;m5t09h zAq``le{_!}^P@Z1$lBn}3=f904Z75<56$gdl4`lHG(x*DG)%LYSB}@98ohCUp=u-& zYbzV9%Uhi|X2iu}8M{MYSyH?2H10%~3H!tHChuS`?5UA%lX>DKCf%R)YpNovG9Jde z|MXASH+Z;bg!JxSm3#kIjAW}BB$r+jl9~Yl$ht!nZ+mL=zl@ej7#MQnpFMmdvRBh) z05;OjMgvG{bV*W6HlJ?zPnC)W`bb6=C$)_Zk2_>EK1!}=sC*NbftMW05CqpCYx(a^ z%$_eKAtomn-piQegGeAkuH=3Gio#xr9*XuL_}7+^nX#ekYew5?P;AI(3ZTh?P*nqE z&?{1SflrVlQE11nwRnODKpgqyqX^6owwgxfnE{J!Sl$Tw`84p01kuLlo<)a|k7FTw zM^f;2q`@M(NV}KUIc8LEN2OMRhn6A(3il2BEY{g}n0Bc4iEvtSMt?efiX2x^1H&Sq z0-L<;3|#Ox+qX40>i6U2NY4TGIYN>#o1Hl5N4>gb)1WSv;{5w`kCZ(;Z{f|nx;2d& zuyA5%xP9orMhEe@hBSZcV)!LjcyKRJH52bdc@nzm7qgbaUVbw^G4SYB6DP9p?bn`D z{hklV#`ZC!U+;-Ng)H%<5_ODf9*~Qz?A^*dllb_Lw@~O46>LuRmcawOgl0KXw&Ms` z8DkH3+N+Cb!o)y!;r7|?VCTsE?r9j&h?9QQgcuO^R>?-r*~cZV`u zN~v2h2D=Bst0WX7l~znch5&#V2knOzD}}bjZ00s*oobh2sUEuL36~$MzJmfTW;Y3Y zD|=X1m-xX8S{dTs&*Y?*V?Fg1#5zs8S%9Mx#bRRLma=oY1``6?RWNJ$)`NsmiWKUqJCmf=Sp!>2is1x-xPH<< z<&E&C_zl#ul?~q%P6k}!D{{x4>2ECs^c)t5si~1*>LLEI?8M5F6t^XFlfi>%#oYs+ z;f@#4c4huF>}Kc6TrjF9uve`0!+;N)AeSc$Wu1ZX)Nc+?{)^pqeLdLXTNQ^-Vj?4n z$7($3GUU2z=eS<%G4+)b(!e9YYQ%p;PXt?9$?r$1sS_vW@1wW_AjPN$3F z$Ko2p7wECp&VTrRk-v{~gF+HN6^5iYPvTteM7FXi^$zT%+R&XW7G20s+>eCq+zQ|A zEftfM8BhDRE)@Ky#kSYeWu{JSZ05Q{v3$fN;lK{`L%Pgj-=yr-$Op?kk@>U99v*gT{J& zlm_oC)IQph>08RG3t0E}2U7po_;CMjv#;D!cb6AkG+>!TUwka2_Ad^qlV6)AMs64Y zw-?19fng2*Vj$OLY$HRWv@p4)+43mq31TMzKT=|5W~X{0^4@lbE4jc0l3?}q?qw|J zX!~pU+3ejoUK*Js2d)njUB%@7^|qy)nPsqyaW_~prMqZ0@cra%XRZ1%ud5v7Chx0+ zXGq~$ctH&`HZ=b};zJG|-?{GuNYoeHB|GynKWoQw4dOZmm`f+7VoA-DmgeFFD!Fy8WyN>CNHI=*Cpa;TMdl~D=`(hkTc$9 zx0e!T@gw?G&x}VcPIh1@2lNRDoCE!+=Vau#X?LK|`w4Z?fH9X-ZJNafaOrxa`kk+6 zvrt^Gx~Bny92_m)Hi->;;rO}*8>{qoG#1g*%5uzM>sP%hTv7<^o_O|iQCZk4&u8rn zoa*2#5N^8-R*{=u83y#RAvJl(oF1ddjVTQTu1>?FFwZ$)IxXZn6L{~Nwr|8IKZbwo z78LLrg@LJqh2|sUVr@20f_XGo8uXBBZbf+O?OqmmQG8-Wl%_1Ff62+I%Tm{4un$!7 z!nuOs9{~p>xD0Wl5at}PD}E6^@=YJOEK%8ickW%9y3~tD!&SToJFeThLQc&8EXA`E zf{0JYem2M}>B3b?*Y(A(#b14ZWzvHC#7Oe%)c(s^-=#iHAzRefC)a|GZ<9avHYudt z{D!2GBe#D?Mlo)$y9HUlj`aq=U^l}yupa?g*}16?_s2={adRla3(iC5$dr-BlwuGt zfMX)_$r0hA2i4uSmc)k_tc{o#xejRWNmL7ma|AtqrrppPtgt z>JKsJ(S)RiQ&M!H^#8DcCM1?yi+>e5P_f5)ZtKI1pTh|&$=}4*i_fn(^Wiq=1C0;h za1D7F2oCrW0DnD|B^fNg$t#=|vBI$(yS#A?x-yr(UHCC32frW? zqFG6-99ro?-;rGvC){|ysx;!298gVTuE0}yBF`}dT$6%1JRiHar^GYRj z@0iHFm|L z$CMeB(pdmFC#K$2z3uwr4TdD26)H>R-m!WyrAU6WM-==Au29buu1TTX5;5!D|4iMuT|<7LJEpheI3wkr3NnWe<%K^ z3tez<^PG?ck3A#HcNM}!ax?O?k}kg^A_!X!uki7iyO3lx7^*oWC3DhW3o{`rTj|_) z*${mn;%2i#_v+WH9gEe;N3#9_(pxG=pN+4uu%W zBJe2|WAJ>}?$jvlgkQugUyqs3tdlC{nzO%a*E2x*H{zZ=!Oq@k&5pog9n<@ zVy&;dukvKYD*eS@cJd9tD9K)2(Bm7VjCBqD0l69&_yu%^r6hV??jGO-GJa8a zCoS3+POFfSN&=_L%DZ&@TP&l7nuTK9)8kNI?(34!pQD3;fy+{dA5pq|-0*9TBk|cz z0u_HK{?{EKbDCa(3$!@jlnCGG@)Y0q)jG?@^7O6K<4zGQ+( z{-3)37)Q!DdzVTc9+jh52v)HSf<2)WryDgf1QWz0?n)_V1Y*&fC3wHJW=c-PF3j^3eAd zUQF`Of0*vT(p+@U4>t-qkeGoG&H+0@AYIAkaxZouSU$MNb7In^vN|_x-&c4R8Tt;sE_L2(Ij&ce4yG3lclcAI&w6XHFK+6b1nfqcL8{p=(${gh$q3S=UU2u6 zxotpl+P62y3W9Ilj zujZZ+$ZMDwz}4N8W*^lmw6L9seX246@LaWS#_*Au7Z*MQ=`tX_xXHz{L65~#XCak{ zc;__cq=&{ zJ!bB+HJtbwMZ`1sZ))OW@Jr7Z7>r62YX5mbl+D$=qjfEpQ|m3z)?q|^fJL1ra&94; z!DFQE0RutveFfUFA*+Gq$}I!rW3$A&lXe{n1`V-$I!Zt4mEF_hvPFE z6Z|SF%;V}O-{%?_XyHT}{}qhMTa|Vl`jzayci_8s$7ggR%RoB!JQ=E@9Qu$Z6I1rf*Oem5bs-X@|=H5^sXPy@~xq9JCUIVfF@NN5D#UpWV+~s&A+{ zoWMyA8ac=}_GCx_hwBg=lBfdv>NaZqW}Bvgh`W=Xe_B3Z$@r87;N%VaL62E%9D|dt zLg|mcS7xjR;bi`yuQ)lJ{xIAqqQdC+a}vvh9;>kZRAwZd{BDmDQ=gGv znS2ux@>IZWn08ELP%`52G2((C_?%`3%BUDxc>R$j0myZ)K3)2q0m+;UY>5xTxw*4W zg7hbV?D$L^EC#iKf~m0#akLZGk;)a_x#dW@WJLoS48IhG9CyzCfv%iOvWGxJ@57sa z2b!TUpvvoTHtE~b4xaUZJmCGi1?l5FL?;`g^`r&(eZj^KPp`_Tl#fk6SMfvq7KCmc z&%{yGDVeyq;%Y>M6_KVwjB+P$+5Og) zaMH?gD7$ZNR!`Ct1dBQH$~qCTf^0b^eP5p3>hM%uvKbA>H{ASlvR@86oNXyb3)VjG zmv`#@L~yZ69@utBgNiY{Y83l;*RY_eh3!?cAR>`4TG02y?m9t=@xFCRgE*ktgT$p( zJB!lg1H|=CU=~lX-vey>K)zI}@X+=bum#vYn8o{6?frB%JOCuL3cbX`z&dISo|VQQ z@4h&+byL!BG^%hPtLf(}93ti|ZjQL_jP_L~XIlB@VEFarm0*t7p3F(U_Yg^Ssv0{}RW5yGpa%F2yo! z%*Qv2b)TT=@8$<;@U`M;(%Q#2g!s;vvitXUJl4HrslUh-EF+Kfu5xCY*yT^I8eJC} zQZcre->-kY@*1^sGuUIJ*IoG7EIfrHb==TGy#|?rD(DJWf+|nJ-GKK-VN6-;kdS{j zm+SuqR2u1b=o`u7HN@Y>YSSY_ZF2B`xx&!)_;NjEEtK81) z4p|e@)aZdQHJ09I$PdrzYB*u4-vad{0=kp}%JXUxz2DJqljZwH71de}AaEs9 zEoU9x2H%Z#cDMp5`}EXCjsB)YAD)yweF0)@QB3llI>^3uNB65g+@c}Hx!gi+e_N{u zoB$>BTU8fAIBxAv-&I^Y`ON%aI^Xj8g)a~e8{W#yY#ski;gl4f=f)sQ6xrD$Yf43H zFv)VP21c($;)0KxRg520uSgT`Wh`_sdvsXQO2DsW8)hvbIJ8Sfa@X}W0 zseLh!W$K5V+2j?T8X3Wf>}!s^NGW^1q$Q*;8B*uxgd7)a&sW&R!lHi7H?n}^Bv^Qv zE~N75P2pAKebWGdKI2Y&-98{6bjx{AmlHLiUzJp@eDG51l~a7F?wj7Y@Ig`zYaVv8 zbN#sY5H#y!8pE=pcWk!{A~opEnM8-q!lRjFMH(1R=_z;sF?$&T#_Y$iZuoRo zaWFb%tZO7tnhx+FjONRWq+Eksb{f9WD_t7%-ufWD57(QK-||*M-wXBy#Q8)Ljk?~9 zNQJba=zcvwt=HaUURNa?y=f|pf8iKo{WjME%7EAW`aXN_e;>Slx%=1h@4uAfTXyEYu1My_X0sJ$;*ANjmL-5q;d9e7vFj0; z{aZGMr)4Me2lR=)@=X{jp^WkWNJuCs>@q_N+95Uj&Vmo9$ZLSDbVzO>N13X2ygum1 z=;^yg;)_zNP8crH8YnuJ&68-8+)h}FJ39(KkSmPa+ekUhwV4!_nn=M7<1+#({boZB z6|@jf_603|kyL9-Eu!8RwJmfL`mTb-auG2behI5ku`}8io?_u&Ds?8($~~F)eZ7^i z=CY&>Hf6%OJ&f!JQWDeT64Ggbt1AG*Tdz-;*bV37-jRp0B7Pr4XnL*D?tDY3*peXw zMxX5j3!w$Re5$@uLFcnvKNL1k3f^ygCT=i~#7MiRs zeVe`)4junG|AyD*sbgW>%J^fCWicF4Wc)G6&4@H%E_TPBt@18{n_d?`_?2R+&8IHv zQ@w55Z>J>2e~O6TiQMjYJ{i#pe+U|nkIoeRm6<6_^8K&auuKWuTeb|$^Eva?f1kb1 z99dG0ZhDV8zLm6)@Gtb;Fkxpq!p*A!Ed<~E;5~vc>h{!I%=bdZLsWX>*eOmYZZ_sO zo*#aHeU}gnK6&9fli-%)<*BCl{>ML5lJW$--(6qLKj^4*c#HJOqO!&+n;^$VCee z-V=T?`0+PXJXBSl{e}8yT<+A{?G}lW<;;` zDo&y)E9LS6+}=ugiWme6iv@bEOkrh1u1sF_DD&QYJU8&o%viB9!>^R&sr~+@@z#Gh%P7kVnUW2hTPKmI z@YjJSIqW{4>kJYbsFn4qh-W<5@@Vu1D>-$mhr&w#xi_YKdU{Sh?oDO;4b4%3I*hi1 zUi$@mYNap-hg--bC#RJjM;vP_iSu39pGn*Hihne*p)YYbT}R|hdgVx+M_R?zu{>e; z@KNi{X$R9hC!14ztF8VY7r8fezAJ|%_JXv@gHIJ4Y{IF@Rc|gl)2az0n1k3a?oO<# zWcIH{UbX!%3-AH1QcsBa7k8TeQPSk0dH$}3{y%^?8xcxHoQ1-3{M?yWyKL((+~Ruf z?5}aN;xQ6Z%mjk~xp1eZEs7d_!9M~q8=Y{>0Y>PH!B~%bAhmh^)MLca_s2T|v{URs zubv)%KJ^CfMMOxtyLZwPD_u6XC0PeY{N!eEVuP{EBT*(DOGh&>_Y*$byb+-S`*q@c z(rp`=d6tTUQx-OVxESb_gY9!S(UBRTDo?k_$b_RUEf#K%wz+`g&4Q+u<$n&JuH+vdSP!%lH*^oZz(v~MWxt4=A5Ior5K1h^lL;UBp(<}qFp(2QE+9PJ| znai_tBw0T*`qz!LNu ztZ)4_Ye?f~uR}tkQEql4=7G|+wBy4(EU8-)X&zw}*Y_MK$FbavTq#j|!QB8#h3h6^ z_pp_5!&m?ynyDf;m0mGW6cWUUJRN-dC7<@atD&PcS61 zW$~TP#tHc)`$JE-0#JDma4tRzK>5RObr;u-f)5zSZoXz`vea($Em)G?JeQOmP%3u+ z=sMbAf7BOvJX(_Cm!pLU-Zl2$?fiEWawn9pr})jm+vca7nF%Or2>I##kXDv7h+2ii zXbmUfJzW`n0C5Zj;^pys4QGxWf!U!)2i(E7)@VFhq;(h`Q2@uBgl@||RUo%RUBUG5 zW&gR1N9zUk7x$38w~Qv8yp&tQtaRj!6gtlwRl$eoshNYFPWpYV_b-c7%@;; zVW8ZM`*gQDq&+n3-vH5+Y%v+Lg7}m=c~BE@VCL8YhBr(((DSk4fJ_p#W7Edyo@SiA zMFHx?O|6OzQ?srU)u+?zp+gd852upH9*JIbDtyUBv&<)gazxM5NV zZI5?Pt#;oyI$T@(lf!{qkCiOQ2xQ>O9xE3M!7K)3`T=<;t@r-{NPGyhLJ6m5m$xAi zOf+X;lF^NY^kMadvQ`QTckqSEQ65x4*--&_z=}&_gu{Ad{hdJEF-Kr@H1^|uQsL4V zs)~QO;_gNF?5=9p5MBssF$?tYwP}J;D-KwkOs-=Yv>Y6!$EUY&^U;jh@=V6i{V``! zdr^a2)|r-xP$~z98yWANX}eYWxWZDWQy^^`UGSMfF0z7@5$!UbL&aj{VFM0_FH z*ZTWrt@{4}Awk~0l^l(e!A4lr6FT`mAEdb-j%I**FcreN!Td$QKc-=B%vQaYwa`lo zYS5sRwOW$_^kdCf4oDCXrk2)gU-3901XLjW^WJf-;Uq#zDEsYGH9`-}{&}0{VCVII z^&G0wIVEO193d`FE#4M{cQY1sqvLU~6OZ@hADl0XoDX3j(f;s#xy+tHH|!RK80d>u ze{cr2Bu41VlWmHlJiTrvsZ3-W;(v3bv}`cV!wUM+H^4v_M}&Y9os(OxKlPMyD3Zh% z&SGeg4m!a-Sd;_$EntDf3n-!lQV0n7pPtO%%b1AjIhW9cu|^!~&v2u1!L~S{PKX0a z`xq$D0TsJOlmnXk_ju(me)_n(<2w9z^*=NqJN)#={%w8<)Pv$#Sdg zYlUKFVaf1bypMepFVypJ`^(H)WlF!uvimcp)0oCdp_N-g2iDzeOcys$*8{)uL^z-Y z?ST=BJ&JHZ`gy?jC)(!+u^0*O3xE6$w?5Co`scT}?oFy7n%A@U3hgQ9Qw@Xs0Frl- zjV;b(Tq0 z_$rFOPXk#X;@az{vI(E)->Q8w-Y3Eh_zO%_4fZgu0v(XP3w9N_knQGxkbzdJHr&c_ z02|M|FVK+!7<4oa=s1Q0isOGM8NRM|!6+Lw9{*q^DwW#*(fzNFem5plu-lZcZT4>y zg?hx>nUwBtDSvnCP1F6n1+G7l%!@bP>uN@74ZE!Rj=Wkug6fk$J55)i{`hC7U!0g` zz|*rL$ku(K{e6tAzZY+n!?Q4dmg)P_s|qAM5S^nJ;(_40LV1Nj4Z0Nkg9zv@%tTWn zSgD-6;R=*<9Pic3mdCcy3t^>g9gxmUN7c}GaHVrf=>E+757Z!dry>3sn61Z8$K|qX z4qSL%EXPGhMC!X7)ZlG(37dp4?g|=U;p)c zy1`l??8F2CwXp}|eLh4$G*2xt3pCQgNk)<_qWI^h8}jA|jvV`PkY5l!g3oR8k|tju zR064v>}hC|FOut8+0rD{(9z0&=7{XCVzL;`*cPc2;GkP_0=n&EO~M`lD^GQgW?p;M z>Ny>Pe*y#);eeVSOhVaM11 z$XRRW)i!(^b1}4v;~yp?plNacV+;ed|4FLOr=9#y9Qyg_^FLgF{@716Gverz(Kw(t zark-Dd7g}};}QJR(0rVE=ajVYm}AoP9W^FlhB@GV`0J?mf!foqbxsBMJkyRb-UC(~ zlv+}Oa2Kql@j!gyW5<%53`_YV1{jF7w9nCDaJTqJ4JNZ?+^|T{D zLW}52t~>N`h*Pj9%2Tpjcj5kzYg`^knE(Dy zHSap0dULhMx2u5v(ftq=3-p`9KdSP4{A+6)9`*b=+Jwj5I%{RE;Oe>rw7!8x%yDd6 zJfXP<^L^=eUG05ezF3 zYNFvi1&x!nE+sXL^f{gb3KCNT?+wHYJ+Eh#%6IE}R52ESV55P%N+vZ8U z%~Sa)Zl?~vIOG$6uLc);uvBF8{qJ%EV-*o=xFTp;_5wYjrNdN4i3+obPYu55R zAM0ddGUNUHD5^SiAmw#>exC0(s?u#8_?Rc=_@LdBAL5mGalA8s|3?S`sjbEy%7_ChUj1kGzdq{RkJ`jI{P-tl zSEM+ZG$m&ylkrnVVy0V-$aSW{zPkb6yoGU8=VfYHOoq{H)-mHYs68S6C!J3BYxRNV z)h4cpCFMz`e1Ss8jW!SSF%Wu_Arq7gkVfDTtsS_Rfez_k9PGm?UwTk#z914BUUL6+ zcc)<>!Z>9+hj-&L;xKf`fIr)9mU9WJ{>L;8V_*)T z18YGA+LXGT4m_1D%$b>>CJ{bHs!&tv5Tn`r1PahsxG;W24k(yz1sqWLvHrPsGDFP> zNI0M~;egH*2C5SajR_O96PB5HoV}RSd7y|xz4P>4G|Y zd%_ORtn+Lz1;mb)l!+3ar)xZqp(PE9_9vh3_tTVXDD~$#f_~D8(|)^Xz`M^3Y7lCH zhLjPX4fH^Aa}_SKB(aB?AfAQwXe*4j!2}8Q*eO~#AjJoHt0iI}Ok%iPAu@3)8}7yg z{}2-$ARs$?M|GrE#<9xyA2CY| zu@Y1^c#`a)`#+JNrdb@{O9yqEG7w3EQ=wgz; z(Cf_(40IsphnQV>)&cSS>#r^LIgEf_NzVqa-(1r-CwBmi>r<|sHJkxyNZg+LR+LFxSl{cb4g=ZAxV<9UB z1LbHZBgz3uN*L6gp3eh8A2wrE^wSG|-)e|xXgGXYVf8^TGo1%Yma^o(@j2OJ-yT3f zCBw*ObIA|}3V5J#GQqz7N(yfvyPk>&cE;}+`u`Ydra6f5DP&S0{mmF z*Kr&WZg!<68QkZa;4TqdC<3)B2p~7t5-0IW|tgrqGQ!iqS?+$#OU172QmUhtDp*abYqW zJC27sGCVjzXUv0htUs%G;#}*YaZ2@PuRTef(|jvnf5I4Ok808fAOHBds45dxVIajs zZ_mM`0FeuaB%yU%q9-{i4c&=hOdbZsIO=6MDUMrK&lJtLcxh~gk}y1 zey#9t@IN1a!u|N?;WsQl8ScF>r#-sQ)zJ32v}=d_Gyy9$x$laZwMSJyCZW3dWL<1` zP7~z#8bv)m_TjVNhXREEAGrdt76^48;tS+v*&Rsyp<^)+?;R;`V%h;42Yaaj2GY7P zs6dz-|MX?KL6KFv5U9#5`3 zGgX1eKL}k&;cM2+g72}s8UAh~f2#v3kck_E3v*F_*f|H&>I|xM$bnpOJ92Qh#kHqe z={g`nKXC0t4gq(;Rt`KNtK1U0 z(II=Z*-x#(Msz@d4!R%5Lx(sZrG+L0WXz))Xw{9iZbNgg{g482|9_RtgEi>7A?X%x z+t??vNX%`Stk&gzVCKVi-D9DqT$+dk`H-AUlYE6Vv0?-QJ-{d$}0mT3q} zU*hUh(ssgpXELZmR*=`j%H*&=5bvY%PFQ#=Lmj=bU?2}`&~k>pL93@r+CBp8@2wF3 z+>xJ$;2OI$R@G(flsLI`Gcj>4m(w!AKF8o4evWWx2$Bz8CW;f*@oUN+zX>~P`s%69!jjSwGAizP3 zO?Saq=WT038&sc%w@A&=4$N}r`jb%AXOHizjmDXPoQp~3G_ea3u zP`n?sAfO%{DihvYuDp>4W$5W?bGcbkZtS$O@%_k@2C<{+&q-7R6wv_{F&S)bgb|SG z>wus+OZb`}-Dj0`KHC-O)B8DK(erS>kx6O(C9&D1TUQX8mr3<8xj$H&QS9S;YRsAY znKbK1{nPX_bj*N#4idiBXBYlSr`!Evm;QtntDyk{wGac9h?^z6<7%pC#6`iLm}6x_ z6M5o+FneM=_V?oT&G^tXj8xI^O6m;Lb zA5acY82@NGAXWioGSCNQ6bDo&Z0VhUodY`XIiRZ2A@)g&$R3Hv1u+KV?LVA}=2P`G zK0`0PQ5myR%j9Ik%(8Psm}2RwyM=Osdc$}}oo6`XBK=@h@2BV<5KuKibtQ2zIjSoD=N;tZb3kDP zr2L?L4ro^@7!)APK}GhGW+(uIp!J%0q(_9xV^b=I-D+(H_gj8I!8TZW3j@`H8Q5`@ z12QEeOyht)hG$=g``3@RkBP$d_1~R=9Y!A=9$r0A-xc=p;i+UJ6Pwi0z^{D&QB#%lTPW-9TnP$G{xvDsz=<$s9u!d>+b9mu@OsYKr4iYn?vNcsDL_nB@;d4OE z?s`qmw(RZJoTQ-m=Xn?Gv6C+NyiegB9Z)>~6L3JMl)qHZ9MPGFvr#|d9_&I`pv>Ds z{G&|jbH`Lw$QPQ>O~5V_`}~9$=!R-iSDu4SI$8A0nY~8=g3z%CVjcruiYV1JFs0AJNy^iUFcj zlzFKXQ9!E$9+%8SuyM+_>yt0Nv_zb2lr%HfhOI2|1^9{cNz<%d!vc}A$k0^N+-wWe3ta^-y`~;4efvt2gLmIT6iGV zKsTd1sQK=I>ePZ=CK-!%Yc=#C3pgOCKMDf{TIet?isyh>2Xr zV+7P_h%*r4pu9~z>&VaKK_6VKG@kRFF_1$EdsEJccbt)YAD~!Gvxwe6Wwon1<9iF; z0vyN2!|kg4F03}f^N@B2u}&j|d4kGwcFLHC>W;?yh>xmPQ_cYa(ZuV+SvPfFJ)rt> z;Ggg4fiwgZ@!^nU_`i1RfJi?=en78y4=8!m!=#kek{BRV17R*0vC#Emco*LHKz!El z4?M0Fj|Bn2eQ^@qg(vQ3?oZ_VA5{h7WQ@oE>7iT%aX{;K|L|uRXlwGNI8d^bU>J0Q?|^K_4To2lxda8(e``Yn!K#YIF9M83;caGBmN#{lgsE^pHnF>{) zJWs;NL8w7H3mI|-%4F8Lp5zpgPZRkMIAsg-zpw(~$C>k;y0Gsy@<3%lI5(;Sp&kf( zGRH#xx=i>9Rqu|4??R|Pwq3GKtUz!a*E7N~KRl?qb8-Ga#|3db(rs0PgKmj{b@p+O zk7ugqb;UuS3kMx{(>b6Inhxkg6#M8b^i_xh(pYG6M1U4^8)?pX%|6tW3H_*k6oaTmfs z{0MoVRkAmO*Z7yEa)Q8f=3}6wm-MqzlePoDlZAPKL#&FVWA2F}T2l^bneTUkfqEma z>}6Z7T|W70nqJZq{L@19At?~K+7QptA_fTgpfx6847T>bx&lv|!RB4}B+vmB2>+af zuuehS|2o*>eS&+%0i9#T=}P^6A%*D`i>r;QIaJZv5id zmOY!!pmyL1&+gQ&00yG3;1(a|t)cIzh4;J_hUmz4*eM7-gWxNeie*os{7m5(w(cq6 z13j-VsP>#IymKa1NBS&0Ps5m}Dr|G4mR$KW^=jkdT)uYJtyg`_bD(j}J1~&qov#=H z`CdR*!3@mDKz~IL5aJ))0fXlPbtE&#!(1L~Rd&AEI1wCHhC_EVP}$72N9D&+tA+4S zP4!~w^hv+il}wC0CxeA|!9um@yU~|)FFdXjo19!Rv&62Lb*@0~dmzTT(sKp6df1f< zpypqhH^26nL3JU{C+?(q)!Z=h`5IOqNj#)_Qhk<_a1Sy+>4c{H@sCrv@7MCpNxs=c zoMo)LU8+5<&jqttufA{4j!78($&7!pqkr_P~t5lcOs$fOW6|Gs%BtKcL!Uf!uvgB3#e)yV{=^ z4hVx&CaHB7&J>;9NxpsNtAQTsjW_WHqy)JcRs2z|{Mw^zz24Zt9n|j*vp(PL?|4q9 zQ@p>q$*J+>j4+SoYlP67A9v(Xape$;ZBH?$0Pv69DotD6W6B$<7wf|D5au}xSmtxu zq)@o$wpwMKk6(j$=DwwGM%dFp@iTHh)%K)u{yzQ*>Q}G__F;PlcIE4UKE%(#5}byL z{kiirflw%=#?WyL(@EIL`G~bPY zu=X_90DVpq2Xyl*5F;S%{(TH|nm#>k=du2f7P@70yIn({7EVj9f7s#}ZAy(|6r{Gp zga?AxwI>ybm}tyPl_?mXk-ad^%XsaLXdcEqG&IT?$A7zN=_ZZz_|8Sb`2?K=5t%yY>lrVqnEM*6P5#Q}8}{v%2j0PMO> zKAe52IHv*L3H4iBI-f+i@^CHrptR1_^Tv6C`>JXlbB|mTj+@RJ_jVXVsYJ~RLkxf z`5*QKDpLA+DUJgYPu6|hTIU&9!66F6l07kaXO?oyll{ZLq5t{#QR)vf(bo^Dt!*!1 zf_w*OGote`-#LwD^QfIp?;S|p(W=h#vtM%%13jnHu^iAT)t=MSv$M0d`qK#sG}m22 z?ZtCShVn^duSBUof`VjU%*x(`GBa{Le;Tg%=O_=vKGD3VI-8A>P=JsPf{$L3su7@| z;nG1hVzL)(WxzGP_nDm*aU%>J>PefF8*481F+32~pPZB3p!?5F8K+=S!Cb~aaQ=M` z$k!rHGPH$(H7H+0Kj;p5LZcgfVb{Lb&aW%QB62{#e>y)pyEr>LR|mY)`*a`dgdqm1 zi!&M2plpwyX?Q>VK$rEK8|w-BE8&2k5>2ren@y*5T^A1M250RS`nDqXj0sFodz>d5 zO3kz~s8HVpN2?+gsD<97fPQW%@8j$|+;dg8x#j@(B;U5j68^p5pE&-fbJ~IW(l5j~?gWS3 zjXiX^vswOpQz06{+G|OoZZS!n5coE2G!rhYcrDR*j++@& z5*zUj@;_KrW_Vvgudx|Vxg52tir0GVzIfhc52u&Y3Ra*g-iG7|*qRPoYut%~3e<1o zaog_4VxB*Daz5|Y6F@*!!9=I|#`#_d|L7dh!FwE#o`rFx*yn%fTIeVTgwroTK$ypK z>CDEMj?v4NXMlm0OUoJFZ#IB{1`!S@q5-M__Gvj#(V=1pS3>*E>tn<~Ypy-a{mi4C z*mtA9uV!E$ua|fgfy)EDaxoDYs@dGg<~BML{Yxt7Lw^p298jhaWR{YTYAU78+RZ@E z6XtsK&*9@bUq_8IPuqFojtEF*?}&eB?)97wxS!{=w)dsjA3{Ls{^{9i|42>Kn17lZ zehblXv18JwgWr_<5r$5miA; zXK3SG{tNsMFR~W~zf!hk`wJdf!U0)0owLR}^w8M1;bb+JEwxHK(*XozA_6ja7UBLo z9MB-52gT>@SmS^I3&rSt3R_=`Vj}SaDt!9m_dfzZpfhc%eWvy?E;!YPGco{yW%3i7 z`F7Mm@E(}O`e)*Q9O8c9oPGxk^j+wdOy5OdH}lLP@Byi>Dwb3j+&OpGl*AUXb9At0Q; zV~@V_9DC`BA_)0;2T-_O*}zRYFyVlF21xCIp$C1w1?c@XOB@NhjM=!Sog3L*Z#s zw^Au5wUzatTEjE;$_m64VVb8WpZ}qQFc9vAA>T7oF0H7xBfU=+@DHBYZA}OGuETf z{=vt2b6e}UonGXY^lV38x5#~&nul4sCK0U-1OttA3>5YU^0m=3r;KjV4sy)BrM={A z7#kU(6}xlb&+^8R`ZBUcIod_DB+oQk)_327JRkgC#6Py1wP@Z0|JT>r+{}3;7JzTe zkPe6{5bcA#%KB9-9=E0E-ZA^r*cfKGxLSgqJ?A!^Cl zWvE^7K0t)-y^=y?Y!C7i+O;%I<~rsY2Q(KBh&M1k7FND`g>>lN4G}N!QcLe2?%MzQ z7|;Fq2&f_RE^^hF1Q}hS`(3P0GgWMN(lqT#gpOy8|3TdkVxPo8*zbAg{Hp`Crvp`~ zlSe)8f_R;U!PsWO9hPfyW^?pbG6^XVe?qEhnvTi7ywU{Wwj=J>ylR=LJ>QdA&kLh- z?95gkS+9(s^A%^l%O_}uM^8(%=yLVxi-HAL>uPU+b`w zPj&B4f2;JDIG=-%4hR>)SOtXWrk}Z}Zu371^ThB#{_H)H2^R9;h`~RIfS?ES;PT|< zR?FoGQ|>SwESFn-S*{$aKSM@9=msRaV9`X>_VJ)R_A|h9#0BAm#=?or=bSqz2{ROS zBohwEEQ%xa$NhRw6eP@_CO?nM@P>1y^>}2^IgVUN48e7-kVXdFT{`^LVONpGR3wHp1-k_%m&D zk)t8hp_`J``y9nUh<|YZ9q}9et#ErbYke(33ud|E0l*!l?1KHW4rtPZn$%oVz6l(d z?-uBQNDm#O_9^V(eztVcnkRJF4=BU~wP_=xPFJ>ix{a^yEa{=|MoQO1^DpFZzDo!8 zeTw}U)gqfK5FVI5X(97G#TnQQpe5A&OsUdf{h1D?)Ol5ox&E~1^W%1#Dp32B>Q5q` z`QdKt`JLI9x}7y15`vAY_4-Bi9qvc(;bbS?&xMcSfZ`EQpaTN*<9N=@^DZ||j<@3R zb%Rr|C&E9-LSrp{Jl>vx5d&1rw}Lqfc|br-BfcVggWJ~Dd@kI^*3p8-tgl>v62m~h z+oMSiyf@4_bOQDLXbS2s?N9i|en9A?8u4*%MxErj^9qm<&ASSk&WAZ4nQ?Ld1wFRU z|L`Op`RU01d$9YZcVdWv68${6ZqXD@)gS-fYa(z5~Yd>&bD z*7qzbxmJ(oUI7dAISGG`2k$I+XCfvb{~tj>*2diCfN%$1aX_>Wzl#G>en8@eNC!>9 zd@WFobs1B%l5pv-W>~j`!=8(Pk`dg#=ZDMAZrZK|jb2MXJ zGwOey9O}62Cv3g=L<|Hq$Y#W2(}}nTzDoQLeoi?M$JlpODlM!#fPHWmp@Lt7$Nz$p zFc4m17tG-+T0f(AH%skffwRgao}h^cs=Hk%h~UUE#Ru~d7KmU!~9Q}g)W(O z;ef9DUNWd*_`8(p0-sAJ@2{dRt^VXbyp^GA5UC!0N~Go!J*z_BkyS&}!7PX#d7pKCP0y)dsymmtRIufo9Vic7aaj zZ1P>~!JkH%rWRE`Uym3}!7yzXeOGb9lNATD>|@QC=Nw7_Q#v52MTB^MjRV4*jHbc( zC&hbOHQ5EDov>Q04k(Ou3it|sJn5VSZ1u^uC$xV^7p6EN;h|*`c6-n^-AN{8({oDx z8Q)p|jLM&uR33FhhFPmThGWWx{Lb> zSEIzP`4@g3Y{Gv41oSf@jSI#0|T7uU$yjEL=On3107OFsVvnD#j zZ?{W@e#Tsfyc@z%<(~@b!tz zm<<#L;`b(e&KRiW`kHCw6;xKcVdylM^Ld~i>7wt(!7R+5hn1bt%M3R%oF1jaJS~^R z01bzj&VXL6qo?VLv_5x9fI@Wdu?|R(key4)Rv2l5$n|5?LoLPZ#$)eQQg0Iia!lcX zC=KlIazK*>VOZ$S$c=+|ya)$$65)V+oa6ff6*|H99)$QH+6C(aw#pwhj_PnU2? zW?oorDsmhTs3WUX{I4Je!d&|fW1v_E`S*2%TDA_9)IU{Eb#~OK{u=%{2u;D%CRl_6 zLjGqzeixoNpc!;v!{y2wZZ;nJ^`kE$siW;pYYERDyaEvc9Y_3tGzuth1=uGUc=3_% z?JKSZ0|qLQW1zX!ht0p6ZB8cKPxJ>pxpE2u%9SnqJCw1T`|B9?$Hzb)cc~E(1Ks*Q z@n+P+M}Lf1Vq7-Py*)k4`yM!JO%ENzI|n!7 zs5XIi+jmm5X(A>`V!mH=?p4D;V_h2^%F0NNU+$N z%6-aAGVTjJvoDf_O8V#TJX1&g4^GlsZi^8RqN5v{kJ-}_?YhGQ#7g*it3}MubRZQ- zVW5g|(sElD``ClQ>nY%X5{)2N>ut*+q@z zfO<4sg$|p6OAd5OiV@4*DS4mBr7#G#6H$#A7GcZW@Gp7L!4f?oFKuGEKcEX(}Q3 zg#B5ROhKPN{m=(cDc)ZiL~V3h%bDkAXe|+9ExkSN1GqpV2=N6EHRTP4#?Q%fEL67MHwI?w7W+;@lga+D`;8p*V{Q@Cp+*GeD5dn0}7^W{!tGzK;##F zo44Gz2g+MPf9QG^EBYw#LL?1zYdS>yQ$a?jg)<#MKvTjx)Oq2S1)W%TT7Z9ASb5gW z_aOFBC-Fe^h>yXbO$eyp?s^7FwXXb14^V)7kht;15ya+Dmn|(bU^=z zpMxb(0km9hpb6V-?w4iBNrg^qfT!@v=46uXjkELH{llFzuuu((o`;7CbWEM7?b2=D zhq&i%zJ1E`uArK*-e*rVKYKec(X-M(r=$E&I)?v2_8Dhjr>E6^KOg8F2NO*R;F_^F zy&r37TeB@X=d`hk8Z34xBe&KYl^M3J2^tFzBrMQp+7pAHc`u9m0L~1q0PwoNtqgb# z!274=u8@g_;$oRS-yg`y@*JMLIm91P@joM|KfEKGr37YlKXl!ahJZ{{_XBDX1BA}U zItPTcwz&>-K&orj6Cu0A|A-C<&d!c~FPVRJI**8xI$s$FQ5U9IB0@kl>h8ivJ%oSG z$(G|FVU`z-#-c$vD*4R1jMw53`l|{CvTq#1K$SJ_QwRstLd-K|+{67Bo$yw3Y3mD7 z4pt%Ie}a>gL0F0C^W#CWM)jw5dYVw17hxV~@0T#pd86Tjp7VU>HgOd@`wG{s4AK%&k(m9}n zWan`G3Fo$x?glq35aApk$D?a~i2D%+nz*1uf$GqK)FZ7X1^OTDV>;@8NEIl-Rp_+S zZW;^i=n@k&Krd2%7KZ0Q>e9euy)^MYhGa&d9>{1J3I$C|{H_rjB?H=pY9F zU=J4ThOr+|KgCnFW;d0BvpeZFQ}t8D0jadY#_iP~dE2f(pvoTWPd+o0xgu+UY})^N zLiVRp!TI|XS)j_)-!l#H&vfbzr-KbtdzWTlgMb6lQP0=oua)CLa1@aTIt3hb`fDuE zL2SNql{zryfX-5Z4*KfnUO;$U1su>-EC-}vpe+uF+@F`Yam3P?B*F z4;Y9hfZIAC>BQQu@Axq8g)q?g6{!eMz>y^wD0GzO#x>2r68-*dzdiK-{~ojrp2b^a z#r?1!$H%yxjCfc2TfsSV*|iEfFig#fYO;Gaz5mpucJmI)2LsBXJCke-l~5kOwTyt9&Cbt7l(H2 zG>@O}#6ROC4D~>2B1Vos$N^1>1A?mup3_aMh5FK#QvZZGpn>0o@vVZLTDx=Gp-wFE z9HRmHH4f;!&Iky;Bau(lt3Sm*>in>!15&y0+Z@n8^hvzpfJWGX-EU~;>vHIMGekf= z_6J&$A2ja5-#^|TSBk;`MRh=l_OYW759*&a3^evI&$rA7sP~E$XdXsErde7a5Czny ziDKQ;{A+qRiHH7aUjKCX(;WEN+aH90f@}*T*t|fc4>~yq)Apa7J8M#~0~W^taTmt; zr^<79{MZ)$VnG=+#G^I`s0lJ<9;Wd?hG?XX;Me$l8Su5#$Fwk0qvY?$)12I*-7wsd z9|;QTNhLx(P_PjuRlhf~pFDWn!`bL+Mv9=}WefEfmCNPq<<2o@n$!HNWm`*+lkCx_ z-s21)>c5cvnX&$vx~~=-)6!#iQtH_olXG|o3E2+iWnlU_Wnz#A&|t9GNG{kG2LwkK zbwC-(1w$QBEsB6T*9Vb(FkkC@(%HgGC&BlS68e_&z&MlV>`ZpSWFmj&b3hjt2cL@8 zH1mH@55&48b432o=ua@aL7g+;ALwB(ZQccYLKV<-$kiunDo^Qp6HSo8c74#>|%a=AJk2QuEALyRs z^*qkyZg9Dsd7ZJfwULS(&;eAE{Y1amM+`LdG1Rz+@0zj;HLAEDB=qdsNsZxvuuZ!a zowL7JMw|MRe7ke{%(HcEr>mfyL7(*#{>R5d@!4OY9We3%>cf3Mj~lT~(L^$>+H9`< zp397I(S9GMDiH0{A{X55KIvhZVUe58sv7nMycnD7Z4yI zqm|8;IaSdsYlr2UlnaI!D9iy(0ynZ0BOt&YM?R)e`(P*A{y(zsg%kK1b3pi7#+ljU ziP8!k9N;eM^@Y*_o%!zWK{~3>0bM*iTzq!oT2#I3VPl3Hc!Y z!F@3D_OVe5ouvvyT#$5QCEUT7vJN_y0}>wSSaCpviHaT6mO&LtL^+_uuVJ8SLDE9dfn%xI`U{_na@E>+?K>vv2fS}GiT~;=a_m7W{$VGcg;(@%;lCFIlRDuj1 zp#ux)5PdHoi_S5hZo-f=&Ic87RV%#=- zyPMy5f?JSVcr9DGfCpk;NakZWQ`h+)^13JhzWH_w|3e69u6z7w`&|jeF7MR%gnF&?P7RRe1GKdRMicj72cGXw(Tf#x#Z&pF;2)?h z6Y@kHg!bdjs6U8aM`^ocZLp`B$}3Zv4EyD!r|)}t*^)(jsTSvQlxY{LjOrhmf6>0IWSid~ujg*h zM*SpnKra1@=Mz4NnIm=g_i}H^I_Pa35IjP57`dNJunVSgF?=2c+ zfznDlUFZ}}K7BfE>w92lVJ{$sfgb4YuLILEDa|{RN})@mNtn_jKWFq{g^E10ORNQ& ze&>#BD*7Mhe)zssqB^8@-lweisrXpu*#C@c(DB;;`eTQf=zjnCJq^&V@+6teT$8Gq z`o(sw()Yijv#<|a9FX6MU8!tBSHti1NCdl_{W{rYh5FY9FXZU2Q&k4Branr>q4O*=78XN+EiKt z(HkBs7U)>RKYTC-!p{*O)cZW+IDLNpm0hrd&@O3}?C7PooYhGOeWiIp@4e>-y?6ED zDzb+f=79boldxD8D6xds)&?rjJ@#OmOStkqjgSNSVlOSn9@@*N%csiy@c{jRzA^$T zhWFvqh=7id4A0jT-ib2+$`dxZUGC> zr;i^$zRN}L;DAtpZKR54Y25D$@jL~YfE8lSU*mv+98{$NisygCgY1;NfU2i?Qkftp zj;SxW-)(dO(F_bsU+6X`TkMaaXVePQqC+&iJ6x_nmoEGrmtPnIsm-q(dIF*MLGG299O8s*p1q5gKI0$k z4T~qmxtf9@2jrS3wRLGShx&yK5q>9a{I5+j=g15!ssrk-iG`kI{2nZmI-*@LjRUHk zJl1Nm0bkJf!6-2UYt>_rWr#JY;O~q5p>4xQF;JKTI;VxO>qOJ?ti{_A`urj%Wvo!! zFtS^f))&lME{{gIgR1R>kwd+YeO$j21DpgEi25($fTm&nk2d{+zDw`ID#v|ffo{`? zfqt$7N<Iw0nNPB06j_?SP+7Y9Sf?)7|4bW|HH`slH3`V0`i$4YDT z+PG%?Q|)gE0gZdJ8}i!gd8H{LpkL^=ViC}OpXXhjM6ll#(fh<65e$U}ZFF_~Lky9jpTq?jMhd%;NjKG8cPHzK zuiIly&>T>ZJM_IeupU^{A+g_qt_un@(WD82!m^^huqir{p@$9b;~)bB$6zwRIy565 zh;!dR_i~(DHp4W7GNPU(Is3VA{lfGwo`3P-cCTx$zGrILW<|V^Xr;kT598gWXp~Ly_1>}Z^_X*`_6bim~^dD*p zrt;v=_0v~E%QhH%V>Lg|dhSD`@s>yLm&}p-(p$Z(o+?XpJ#=Q?$e9jk2W(0cG4gtj z=zx#|8ln~mb+MYYJvqHBH0$3G?J zf6&{p^_Yk6Wc*{0>ulk=_}!R$ITQZ-5vNJ3N76ci{azj0+77WiIs1)@q`9jv=h@d{h&0JsdkiUxgf@Kj_Y6 zlFXyD&{`GxZ$v;(o5#xI<1KPPn<07wFCCh}uW~DAc!`c=8>l|Ki$O!MwyHj9KNGCY z31IbNzPPq~x{l{g^9kZvSXn&YNdrUKALwl;h;gYxz5wOGPTBD3~-PrgVv;up3bMl1ljD=f$~I3gF&Al zp2_!QH%!gK$jye;KFb3)n9^yP_#S{JUU%&r;e$==)l4Gmy@;RWh+j>0( z@BT%7Flb&pJk%f1pD2^b44_M0jlA;I0Sq)F&W9=xZNtOy1YMZU0AZI42l7CGgP;dv z3^WL|&?}6W?dUhcxR*j3qHW&0E z!U0`f#b#pcMnEeYcQ76wi%3Eb;paMAdLwcv_eQJbutmAdmCEM6avb&pl1vQoq(2r6 zbbNF?uzG4Ap8OGe+I$Rm!m^qtH0xdZ`-l72h=2O0!~v;Yc&qu4nV?IC?1JfeJRjpc zpksEyK3*LV?^6hQI2Y8OsZ^KU+|Qmr11m)NpR~-sp5OO?PMq@mt0NpxwSU_**iqE~ zIDq=mGSpreyqXLR`xvnt5V1gA;*V0o1tETDF&mA#MD$vc{4k{p%3@N$wk9Y!9`|}d zW*BXzj#f7_)FZ-sV+r_&=MhlfS{t}3!F35RP|}~q=PY(+MO_P33c^0*zhTq8%)pQZ zl58_mJbFtfpE`hmayfG{;Dl;GM)gjoWWGWn#Ecf&O~l-FtTvdvj_P{SdEandEoDn{ zm5Om99MB2rd`@`JE8+)q!n+t>sREtwM=d`d{W$(O!X5Zje$s8`C%*GpU2)I!5fRV= zrw5Z}9d1y4DD{Ao%51FXBkaF$1`oIf8D^LK<)xRHun%CEgr3q9-B^YCa~3$co*gwLAs(F;&(9l_|B4yZskigJkRPT#e45(!}nPSRP!^z zxCf&ocsP&SN0^Y|`vY0%l@~g4t~f*c@1#Byk^^kP68$s@5d}N-oMvW%uTiu8@ssZW zbof&bps*j%vv?X7bT8+>!~dv#Fs&xZ+{@ShJip@s9p!(j{nUbapC&1Jc>f!F3sD3$ zn|XYU8lY|d$I$Q)prtP0C47IR;2PMR+(SiTO%P4Q5CzdZ%=LRQPQ>$2Y5L0A=uwCV zqACPGfDznQv%AkD8&$iM6NXi1-5kK{;j#iXh@27?4}@9oh=FX%ueX;jW0jVxPBY+v zcuq(6q=PPg>dfcF0ntAEeG70<{-g#!_8aotr#v)yz4%V_fwvRyqOR{_@lQ=*9DNsz zd7*=oKm(-dpz-^V1EMKGDsmo$718a-#lX0q44RFLi-%iusYi!Is#RV4W%SacYzLdT z9mG6{fDi)_4w{Dc;IZ!-y37N?$sJcq=X_-HC0_~o1g-I0GzZ6htTKN_DiC}Que!wU zj4;4F=RVV1JrC?ytJMom^^{CK$qhT$IRT66fd2Az(7O>3>OD4_`^RD(S}?fI!RH=s z5yEu_oyw-<$GWMsqylj&SSOr`idty8DIB!6$BOsyEL{^sU&|UnLLnXLzYh1mwTS`h z-#Tn@PC%AQpqsqrM|c!9!59d4}W%kJa`rkr?Bnjyo2BQ3HPJVzMg|T_#Hc7 z#Qmg&`#J4bPq6`;a0Q}C*hIRjAnTz?v!B@cm;XKdE9g^$j0oya5Ce55n46A{t=Q46 z=PF~vRvBW1fkYV{!9YP)24-U*A3ge<%(Y53Y7%YoMR3=|L07N~yR1yVya*43p<(0# zZfDi(i?gKFy^nv~7SF$w9}u9S)^!@NS}!+6eIE=8LV(}lIFP>XQ%=ON*8p^G;%GK72~;!)HP~P#qIDjb^@nRHu|e z=)f9{hdSz^Cnfu4L>LIU{Fbd|UgVC*U6^g#5e}$C{7;Efzy_$kn+gZi8pQKJ>=4a2 zW4&(Q{)yQbw||~jtAF0&`DbEdl2|G6#hFsLs;!00GfHytBmF2XtVS`#=YTiXFv2 z69<$|*NS=nc3jLKb%!J6&8jrff{EbOUgnK3ah5Pkt@OvkPuCrCcdI_m_9ah) znhkiaaPB1G9z`XpjU!dv3;_-76O;Wk2^P!Mk?3~+|FUK+*yx^gFkQ~2L?X&WqnbsS z$@O>04EA!vV{nh%SFN@a2N4QV9?^x6{||h<5Im+S*zdm|O*Fq(<;QWPPr>SW!*Dm< zdY!j6;3INCP=k)vfI3aXLjRA!i^X1(5M2T|7uGxPRmC@ zS_M*-NpyFpS%IHZ{|D*%z3%#$>{VHc?#CVqB9+>~xIdou{^h~*DoaoueNS<(} zQ9X#x!88u&H@)tJcEQ3N&~IS`gxeR(;f5$6=V^(VP|nP;Fi&^ou}bJ3p9M)K47(ww zxeldi4#pUWZpGt4IpCtlky)5E*Y+{y^LdAr(8K{fj>S!;l$vBRZZcWo?82S7gg@he z2mvt%#Li;D&Q~Fn@3o5qO6=AErTrbS=fsW-Fu^`@R&T5AJUfZP$9$?eF+%%bsEHikSrYLFRkq2r`CMKaDu0pNK<>l&5CGd=~!=nmBofx?vsyUdeV<43YPq|>OVU|t` z6B7`SN%dr~MlHhqaTmL?Ecb5w{peb@fcF}7rGqZAW|KAZG?+BmEE3iU>44;9turYN zY2Hp+X#R||;6*3oXJpV6te>g_mZ@iO){ib5!~-44UMkfe)NZ+M9xBhn1Jxj`L~jp` z#>9laabj4gh8{V#a-)|T+rn=U%d_To3-1~(FNVp|98V zcD`%r`X8Bxu|B$&C3G!Hpn0o}1t>u}p#Da_ueXGET&mQ2brAuzW!C;{`(N=K(61jl z21+O%I#!p+nP5A85EBsvG<@DKGOEYf6>Vam{%3*rtOdgTZ}rh!7%jm(>Ih>XoW-*i zudB{U9(8&XIPs%GLS}0Y=mTm3xhB$nD(}em#;>m<;(^ArlOaqH@zC%yfcmq{F3A_+ zaye`@CxgqcfQR8!w=XYA@dnCK&B^i{OlDxN(gA5&AXD>$#(*hNOj4;h7TH}B)7p#3D zO6XhCK*MK}3wC>(xX2sb`jP1lZXalG{(<(wpc>ViZfOd*&doY6tC!X6NjRP-O2bfY z9Ha@-y?`_hXov|t*sHZFEmXnaInejO6!P&oYB&K;KQxY@7~ewW`SYCWP!)PHsy%W$ z|FgKOq8%_VQ6guY6O3yN;YD^(Ehg~@!Y=eR8g+HniBVxUuZc?MP? z?-r;%mvC*`Pz4f2G;gF52gExVjEA_BazhwM>44y0K?P_&esxN=1;`tnsB%`;MZI*B z=7Z3UY6>9UhhHOqrtN|q*R)KG=y^gPYmX=F`cv4I4}TEW0ipkoWMTL!MBa&iNF4M{ zV{ma^FS!fM#vnm7-Z%25OHP&%LwzAkY`CfJppO&H3>_-_pXIpoKRI_UfR%S*@0 zdCN;@Wv$B00bw#cyxIm8wjh?GFmeYKB@RDX_+20r;LYM|chSRR$_dEkDG z2CM6Py7!6Qd z23R$~J$zRCojiLDr>)@QMm4A@vq2YH?d*OVKd=SpW z2m$d_jP}mwQ+>~(2Jk=)0lh={-VLft3L>>q+kT-??i}Jz<11&d`W(y}^#0duH zlfQ#w*(E_gS)T)f6ZxB|hJZG-iApngZ~9(kBqRudquMfJ` zg7na5tcPQ5{&y~UiF z#shIkiCuFrzxN6%&s8`TY}<_k3Xrq8L`Sm6$47U0x$%0lHcx0lBgPG6!um(u&#RI}oJE=4a>k9{zzI_y5A+PyndVqth z(u6j=>)$x{>*M?WKRY;}XF)v5`-ks&D=hI79ngCiNbP{dYJjBroFe||<5|5u?N{3= z-u_CZWCsj=0NIbMIl<~fQ?bc{SRB$N3OCfmZTYC5EOJ2;@eU0R=7lDV6KJo45L0We zlIHDF$?`FfOvA*rK6xhyC=yMPKSzTMX z<0}<(JO|{84#+U?uTSQLh>ak*WNv0>BNNpvxCI}ROxSJmE*Sd(W%8l|+TwobYpjVz z)$=3i5B-!>t~!2Jyd30+*l5(x^*yk2t^3da>TGx9hiX01|2ohC8Rf?ZX3cJrDH;^;^jC)H4l4Ks@u(j}+FRi}R}V zU_a-8L<58s=$i(9{#(-mArAWQgoBeWd`X==4y~uB<;YtONrebCXh!p~!4TC8lFVGJ z>A7HZrg0yvQ_Kqs6!1VroBim09;oN3&wFSLWU4-b3J|sffA_1APsaK@lUgxVXtB0fN&30 z*q<(^KrjwcK0)h+(h3RoVGp5=$~P00Ts;p6D39KN`8?0W@)P*|*Z6zgD<+8cImF_8>x;S3&q5i6UoP=OvRUn^fpp<20Ijxi@JnH)j= zSw=Y^*Yz17;y6$PL=!DO2Il7a`aAj?O@hr6Y`yKF(bXzXUFE`ey9>lWxOdLG=k%}t zIR_N+|4|#LN+Wa-q{R~lbX31M>uZi=w~QG8Rop(D|8?Cp>-~q*!~K#yxKP=t7j^U% zFjN;Apo|>2h(--QojvTK^w$@4}xpc6ATqHi`o>Mnw(^ zi7iB%fC>T;DD+p;(l|JY$53GW04=_xLzuC@|2KHgzMP{Yz=?C||3xEn@nsSRHfyiF z_F8bvI&@9<3!TC`_TkSJIvrq*VjR$}@`GmnN5em-Pu1qd)2BKY{d@gmV$xo-qDcWAv?jCVS3V^56%w!T&sYs1E2p4D(GKP?Q69NFG4o3%%|E zbQs$Mt5z8QgeCCs@jTC78ht}_UEqp{IS;rQ5Bu6=;>qQV|M%9n}v;Tc%O0bwA9WP@lgjB${-_3m}GZw@nM zg_vM>!~rekQdHd~dI4b-GIji8;1)c2A{s$yfip1724io;MfF1!?>`gB=ZJAomGsdI z#6lmi7Nx}TOlpN-PWJLoe|p_XCrfcZAbd?X$&vM4BFMO{R{HcfbzL6g*EL%%)E`q+ zPVa68f3SYKe@0p$2VD;V@thTFY7Rz^upgq&dtlnxD@q>7Iip@n&cx0dFQ(%D3OYA| ze_FHuo3&wU^B=Aqpb;Vi2+a*zlI;hrG2=`_@zHT07v zHBcehQV2+LKpF;$`*Fx^)IG#Mr;L8~p8gXskU0MXw*&@ynh*eJ)qb;DO-E3H<}h=8 zQ=8{6@?BJM0{^pW7c~S#I-pcEg9jZDV4!4#fNZ;jXR#jBK;LQ#>3X)TUPU?JfKsFC zO75X%;MsXzcFK8QJW&M#TD+2eK(D{-1N~VY(AS>ZYf@^R{fX^>r8Fk`P&$%T1Of^T zz(0_(VB-cUyrw+BE}l)<3zBPHD*mU>zU=6J2#@qp0W{V)YL8u!kprSj8nIA-EH})< za6=5dTZ@qCLrJO`pB==&FB+y{bs~apvq<>fSSz~&A( z6(Jyd3iU_ST6czeX!vt2C%?>pxfn#w&y>uA9T@mRtBv>``vD>L;oDLZBoF|w(1?Gi z{uIwh9fY;WM!X~H56t5_o`3z1o9E@l-Ew?JOhfM zp?UCRs|WO}hjBo<)@MiE{<06y{ru03)B$bgfXSIV-3lfD0~*ANOVci+kM)NfeNYd? z*ahC#m+(k~d7iN;bI?7-2Q6jJE9!-yihERl=x5lxw?xVntaGAw!VNL-a*As+YcJJB^ctsb|F8!Iz0qkSUed&Ezle_SYfY=w2YEd!L1j%Wc<6~MO z49&3iP*sABzkaa9+cxx5$modk|I!T${-p)x9lN#wKX8u48My93T#0UM)Y0ba0@=X! zh{8i@QMU>@0=g>@PJ*xNAOcG4Y~+HSYC7oH9$3T!(XIc)e1V7qnq0P5Z{E~uuoXXD z%|+iYI{sQ7bcld}E&*{D^(k10en2VqgHACAB>wGERh|FAqZIg>4oG(h!U~k9dkl_RQ8AXA7&N7ZE-m_^J_3Jf2!~vxq$ozbc1G>it`raH2-h)q6_#yoU#W0k4)0t@x2=FjcxJO;x#>!85urI!Y-KWIXh!tGS2DoB|A+#P_Nw+ z*Yax>K5A2zYLT{B#pf+jxd)9izk&5raG$hy&V{9FW?B-{64cKK$|4WYpSxvRX~vOlou3 zJe|O%BC9b5*#XQy@bBLs9neDa1By7H6ra^2yQCH}fCCb>sG;wH>B;dp4a@ZVeergf zd;aX#Id6}hWV56cax&NEum?KmYjdRYKd&Cl|7_!c9+LU~Sq+fV|Hv$O$^zR=0jtvP z7tg;S4WmS=epCR_9(><4`f|#J>@=!^^b2u6{n#n@Fiq(N4HaxjomVoA*K~NKPNZFe zB~R}y$pnFK^tsv$%d$rqr555Q#?L1g{s0{l>)E1N^g*+F2@ZAb6=NXWQx??+Fi=rc zpud0`2(?CVAQz;z!C3#}M0;RG%!MynV_5gQEhDequw*8DgLRZ1a6nrS5FsBrFdw5& zC=#@aaM*#nFS?I~l^QA8$ zd8hb%X80u3!;g!f;Q()O=9vA4Q}kv90e$YoN9d7ev-GkTq-O`P$x{DzmRsqHMA7Y__Q_?C>4FBw$Zs>rtN_2(TXD_A$iu{0{CTieGk6NI~ zC8*76wRt{!F=qsHfx8%O(Q!_>{%DT$&!Szhs(9Z=Omsvnv<(hHIq`1nX6ldhoeT~C zz~Pvp4JZ$4-FoCFozG)!vN8k9bk3~4;|Ks0+X4HU%j0*c@8N$wlLPj7{KFj>%)bsH z2UQ$llBxnbt3w|K>O)UCbC`kQsogM|kByfyn-6Z|HE)tdRjAJxD2eJT_{g_y=7qp_ zdP!6MDNMxRRo^4mX#ZUDK=mvrqHiJ7O&o-P>Un=4aH*(DnPtPrl!D84`weYly!bHv zFcs)$MK}ob8eLpV6{RLa2#ELNk^iCD*UFOnU{-HTneepLm6`kK>4>@T0<$#)_Gtvj z0|n$kFXvx41H->p)M*MFluqOOUVyK+0N?i+4~Z(23%`tllqM*wzJB?q!;adzATQ`v zDKG)S!B6!}yO~JY;_Y*3R4NU>4F$EgvO9>AKv4{R4Nm9MMPPw`sVOZG@IYItBteGN?bGqNe`q9uDYqlLI>5rU6>h0g3lD zP(x29{$v2!=Sxf{6wk@-pnOpVZ+fW%lKAIH_d`rE2b8*j8dQn4Qj@>}*+E`sfz~|| zPfmDKOtC-pN9X5tXyWFmmST4Ba$;P)Q1oV_6MIh8^M5*Kf<_*^0en%AKMfh*7j=zt)d1$wYH?V?8g*E6m@%mJmC z2ZE!NL+qmtmnu+vFRZ@ilSq$u^K(S|nSA{Ow6G3pN`3R{$sdSqe)Vt#bcBGezIGE# z%L2P^FIDkB8ye^v$^T#$Joadae?%=R;e;Hu3I$udqVV+uQ+QEz#4`o>9q}pF1es=> z`GI{g@QfZKE`llrE;ydbdiCt2n}o9<4)H!lNJtz!9W%TDF%ab)PgxVxCOuFdI_^4V zX4G%HCxn5zm~I7W@sA$OhsD7~_kyx=FVP#35Rf<*`{DpUai~Fl`S$0()XPQ3@s%H0 zhO|IM$_67ZAkqPW2cp%0jj&;_K0$OgE>0U`+Wl(4A^yBUvD~9wFol0$AI#+ni+Uic zv%q-;bQ1O<{3CuV*ngDpRuZv5sT5MW%VwS`dP2XfgrWsg98e+gE@4lD@Nl;T^KsW5 zwJIaQ8Z zq5NjNgoOgttQlb*rS;**bqoaTb_e!04*#~Z6K%tPK?ig!_fSut-lu}5T(HUHLOie9 zZ=nCeJdBIU8{mY>;(3{ee3rAb7zcC|?ZfLcuoSwJrBX+cGZ41$hIH1JM16ZF2azL>hFqHw8+L{ADs#H>~ zLxF)1{ZtM+HqX5bfmRHxAfEIElKWsh9UHUSS+PTEUrg~p{WTuQG|~lueOyqr((6oO zpuTOeXJVwfws0QCp3yahf$FFU;@s4eE;+Pz^Ywb!@1jd9U?3m7$=WcP0OT_z9JDX$ z4=55>JwMBeXmkdGeXtB^fqK##+LFFN7O4@%pJiy4yAI_Nk^czbAF9d4{iA8QtgzFT^<@@Hj&Lr$rrDVmk-4cOM57!#~Ow zQH$jPv&|Kvo=FW{$Y2guo2*1fFX}Bk-*6Ly5RkqLrfYzJ1G*9TN1P>Bn}Pusl(bh_ z=?A@*nNeTELRlw+&YMmd^1z(Aco(S8pFMu{wH`pRRE*uP;D8QdIT+IW=bn1BssD)| zA?l$kl_TJP4l6FQ&%{E576|9TNyeAf*MpuUG%&= zzqq_a76@7B2>*P5k1syJmVB?5KY5h*S$&v^`vLWoCnD~{_mBgEofBuCEmG|v4yZ8| zzZ1xa56s-N(s>Q=(AXvo5cXKa0i_iOgjgehSt9cu@<8lEJxEd=o#>-@1$Igux0D1- zR87G?{Ogym-9o1$)rYucQ91roV%4*oJ1?80tRNVz5pwuYAm#ajG-_c2`@4a)=nm$@yi|R8%4Q2&r z@LTi2)-%CQV_ra4Tz&Sq@;r`D!6x8!2USSm>kHgZ6i{3IM#Q83-v<{k2Llf1o?O%z z{{z?T%b_&Uzy<9WwaHh6flhQh1iMI&>gO5s{>?b~^WMYg32! z?^!BGEXhC<2c+r`sDTWDe{6w!sQbcKSHVsa3naQcYF>Nyg9Lf$v!58!}cP7j@$ z4c9L9Y;>(o-YFB+t5iaswp5tO`olcXto81to$0x)-FKz)m3TciCDQ2>ZeFL(d!1&b z#VSR1Cxb~CskO~6>Y=Y|z~>C0vns+y*!6($%(=idFb|`tmk(LCwR~Bgknsp8$$uky zwmkS@!@t$J*)NPbs9+ZFYP7SC^+)`D$La_mEs^7B%y2hdG?{v|zt5-GU{f7n9)Ck)f%U;~~R z;Q8!||YR*!0VVQc5xvt{W6UR7c;2DU%D+nCFfxHiMKsL?T zW7+Ve2XYO`ve{I5;A0wn#i;(^z36M{q-<44(~&$HR3FSmjq<=|hp&&l^0?J{+|2Ys zfq=peIU(X^Sg|~o=%+=Nt)$FBjF$8!zlaOClhypenK)q@b_pCbq+ruQ6^IT%K4ru{ z=QYGXhxEKj31M>=d}ekaMs; zsAKT|&FG4JqfO}-T`uP(0;*@V+-Af;gnc9inwKZQM7Q6ZNj>z7DWRYJ7mF7w(RF1q zJ@Mmc2Q0o7FL&W-5-%{237)JC@#n~A8y5MiN+qjyqc6&0P zcL(4HHMkhm2x|)zB9*-9F39BVu$5`p$t0#T zB%6?C1$YzX1A&}4uAN|M#-tnah8vTIiY)k&fl_f==lOfogE23ZW=zAqRa$o|NyofPU}r*pt&P2F34MT?qqrAPt2KN5 zc$8U{I`*p9X^j~F09F#<=$%;`cMj2O2X{4Q9ri~o80n?>KRQ1@`nmq|&p&r@_C5f- z14t;3*amXV=As0_ZVb%42>qP%=LYI)YJTw&_xH+Uz$?@_6a8tQ+#*=~LgGuPT>50g>J4@oHzt1&-B#Q_QYBQU{{Yp)}q z94sCTGucO5IiQnl7az@t?&}1$P&4Ioh+<)%peM=&@yU~~(f`Capxp;^K%d(IyNP_D zx9xz%+~?5)5h_nJY>KmlDO1S%7+8Ox5{PFE-uJL4Lv7HKxFDtXk!-Wa=h9OdV6p>K zS|F%Gz(bcXNzdh3d>W_K;7x-WR{?Ivdws$hCU_DOO38@#T%5%t4|H3PHp3YC$Uf|s z?%)D>!%NUZ(?;qC?!p>A>wf@MaW)w3rHU$t95l_na1RxA(4awt8Cbo?dm`jVVn)tm zkh$lS$4lD8KxHq^x$ray=R`YUaxW}WNFzs-wzbc%pZL|_&;*Kwbb%_+1_lCXBkGJF zjK}^8+;kKIYRw9}FPps#^gE>z&&LYfgB9Rs+x=o4IfxTvmh;Fk4}kkeK8KINd08E` zJVXbS@ytMFItRt*MXe1O=-k8lgFRCE&MR7oTEw6K4tV&n>!AWVz#T9%ApU1m75HZq zOc(ebiq$6(h8=JplT$D|JuBR$BLp;q{!750MC)&A2VTQGYaGx$I-pbTzpmgGPvPSn z5bc0XrYnI7vlkcQJ+Lbr;61F zuEQoAC8_|(#{{TDgiV3~HdhSfc*M2G2*o9of+wXB!yW?iMwo#b@Ym@W2zJAucQaf> zKj6^^RfuL`uF@l-Cfa6aiz)a`qbjE-ndt7E(=s44>}P!z)`bIi!hR9&O&6E#H$_w< z5(_j11eE*m!siTAzwJ*{CI;n#6?-d<|6vRSu13YF=mzIq&IB{Z0{cw8DSRXjs1XF? zp5%aV#w9r*+WIHVqjNy|ju_~p*FJyWiP#8cCT>$^!Z$Szs8wke-n~4s8V#o%z~?(N zu0PF|n|S@wD5A=H8Z2Cef8e|m_|q&pwfZlhbQ=uH^Z9_aKWET`W$A=`SDe1%DS9#R ztjy1WeXe0I>-#W!KfCm68Bu=<(KgrA^oadg8Xndjn*9L=0xynz+W!(2ClNNzin+wq z!LCF=Bk>I3y)a;plCzoS3pAT`5d9?7{^{E6Yi$?o>OKzWsm4J6ew_sp1xTQu#jm2B zpR{XT(SeEgz}q_P!o&P)f=+ln#X?ICDDr|<_=mAjDHof9VOFYmpNEYl;DJsa>6)NN zwE3RLywss3-hIm%6Ou0TdB-$^(&4G5KKx4kkK%w5H#aw5$pL+42kbE7fHwFant+8> zP(HKz2M|!J*-2Bj3+!R2DLlDy*ytH%2EYdyh)+DJ2_ifcQ1^w1X{>Upc%F|Hi1gBZ z3l>!EC{Gv=P$B6S(%gZ8Uo^2zOF}@VSwubtC-J-)ukXgo?D&WWA{-?8u=(F70vW?B z3|Ju00SOE=g*}n1?)~kpt?h+n-^8c>a|xFjpV+jWqITxQU@-ph~iG{L(agy#{NYU7CWy zz1^3)o@I&OsZ*QxJjDUQSEN15&sgRhy#l)V!N)-txS#yT!F5giu7TgleuR{gZnvC2 zk5EuvUNYwyWQYb(qx?(L0PQkuup5v?zcip~r17}}-jQ6RQU3!Ks6_goQDRZNF7ERf zUfdS|C~{*JKP&A%1hgEMPaehf(75|p&zylysBBrH z4?dX>AyGJ=ADZqc6<)>tf1Z332lQihz!F=0fM^C5>7Kb0tA@lq;|6M_(yAmG_aFj- z_o;w+pukAl$pE}Va~*}gXnPO z0h6tW<6)E+anW$No2<{;fs=Zu)igbV-!1g7q5_3Y-4A-y3}>(ZbYS*YrB+j58>~N2 zrvMGLjvptjKzx_y49erq|IIkNP*ft<0+(nrPkEbpoM8#fgV+YpPdDnqVAciLr%X7A zcp&7VyMs*cT71vovfmPFfm{Rk*o}T4|McEi?!mbW*nn>|T%5kA5{X>#%+JXV zER_mjjyGeq4`yD>B>KVWm)3c0(f&l4V4w8^I;L~$76uid)k?gVwWr|A3R5ug_J_Fy zVMXBK#4DMKM5^+=QBHChg&(Ibrp2wumu>X*{q-sH2G{8 zp7iWN478;AmyK>@tk%Ig$Up{6mY8F7vVTV#E?FW)CkwZNK?iYmS?^YxX)KIF!~=KYKah;@h>10666P1#`Tlun6~8zKZ0p(I;r zhiLYW^LJ29lc$pSRoZqTorLPW#skf6UcUA$w}c8H%pjD`^@qEOrDr#rhiR)kF|j*C zbkuTf6Y7tX7td|XZ_IbG(tOOL0vZwL$1EaGc)ZM+_hr;SL*>aM4>b7bJ2m(U$DPeI z(X-@>?+n8nL-!?~JyHRbL;Z8Z$`SraC64ybiUH#vcy*OJat{m;l$?Rd={rr{6Hyj? z#QmJE-`+dDe-|vi1x8G?UVy-l><#)tPipgdw|fhzC@=@Re6yOM|9Csj0m)1rodb$^ zpwh+!tduL+_7YqmOsjnID9T8EG{@YY^3bW*#YfA@Waf2;oI^$ZNrct#>hX7TK*w6b z*8{WQ4{i=X6RqigWKG(MWuQv_C!y*ZlWv90R!eobYQ_);GXFcxgW+qHu67HxOV)8JysqYh<%6y0xeKFy)ofR z)882X&TIIGzS@;@u{3i;{QE~0(b6+qH(7$Li!e&#X`&xc;@EXdVTY4Yq5mqN8{*-+ z^r|5~)v?WSvCtVw7PKDoZmhKtcmf1{g2`f_WEm&}D&x&d>96 zo`Z=BM;VK1CL21YXdku+dluyz>m7x7B^of*sKF zSG>AL1+_tTS04WE0000W07*naR4@w22jN~TY+k4wc~x&tk@1OiK;rsJ&A*;<9>y96 zbQ-xqZ^b{T1A4QXPB4-=e^G`>2+Y9-^IGl2s$CQ~yGR+0+c_YW&4V~d^keQO0?N6$ z0DQ-WqPIHNcH-H0<9sL{yv$pY2fwlx9Hqb`di40ot8e6fpo0f$fAm^& zaBmJ6Y@FVtVm{EJbl(t_hj34;f;;eG>#$@{ekb(k2G$I!KH!W1*ckY?`W z9i$xrpN1FZl?&t}Ix*$!R^(Uj$K(|?P zNPHwSQ@d+CP`BF^80by=jobW6%iUF>0Gc6*fOh)5)e3&6!FYzd@VE_TG{E`D$>jaM zoi;H)t)7*52lyXRUp}%O(?{;bK>vdr5V1grhd!R4`_6f`X7ScnG^>)%&f>Ra!wwjz zTF0OTA}8o@(J1Dsh<`u+)nawoo&x?E3%)&uszu*-)jSYvAkmP)BzuoQHa2RD!pwy6Rt zAqNDwrf=od4t)I_ZiDmKTzoW#*{q+bXDKbrK1$KXe*Vn>R?X=zPbS3k)j$E#ODj}IaClQ zQNbyGri~hBEfa&cOlMJ67`l$h?6AbK2k6f1P2EmMW~6ouWZ4D&vEX;V^l=~Z_I4oW z?(j~}H6QN-2ZR`iru74?K*0PA@;$4TEt_}fJVuG_TseS220ln`z)CC35~gJXfoTe_&Un;PMWAT2yQD{+V@n>om?apB{@t!#@!&+WX8dnA}8-+z_|u zfTqxbfiH9y^1?w2J3wC`P)LK@ou&hdD$x2aSQYkB6F1dO{Da4Gh)#Us-JmOz3iIb# zn1bbpj<{bFALq{bNgh3-gOKab=!$nxze5Lf@a&5m(3i5{Z=x*t?R#L%0aaxE!5P?L zD{LONN(SK{Jo~nWX>1MKcwB3!@<`4nN&{602oqJQ@)&A23^O$t`$Qjyd`6FP4jcYU zP$m-aF_=~e!R`Y0!)v3CbFhz^9{N`8g-JHLE200 zRpx!IyE}L6PLcZ&$l8t^Si|a~=;uQ5JjMO5gniZ!w?|c2409=ghkjPUST50?OtL?T z$oFSY`aYkoYk(f$2c$BZkGJJA(=M2J4lSnQoeXq{kQAPUDF>=uNox-r(2HrL1KPp? zA^#&@p9e?V@J|joAnXr7^hz_ZYz8xW>Sb{9><-O5YN0bls6Qp($e>DB4_-ad=3n1} zfZjbo1+;|&N^I679s6w0LnSBHCf1@R&c7;6-2Q@&fY=}LJmgF(WS_A#opo4~@B988 z1BS##NvEI)sC36h^F|R6q@+<&>8@=w0s;a`GeA-#1nHCzlnz0dQjzy@ly~{>~=e#lWUe^pjJ6z5^1=Gl4yhW zT5R&ZKowM|gB?1r(srK7F924#r__L_5vG_onhG2(Mys21E*$ z?9ck5|7_a>q2U5K&ZMtlC3{qrby?DEznu{`+-2b#1(w~(Ue*F~c}36K(F?}%GE|Elx! zXhCSdE$k7VJAJ%~+2fguD|uB}iP=L;$;%b!%<)zy7W+x7G2-EHw>~h<#2gi(JfTcQ z?UM)9;vD0#9+CXm_mqyqM7DG7Yd@eM`lkaZh+U576!B0cbMQ`lLxANEJf_>tWmWGB zNN|d$r9r0)kuQ*!zb0UCaXr8KrcoxT; zYuevd<(PXG#6&O7?&iX1mtGYKf{|FZuZ1SK&ylrWOM{)_$+ZvR#pe&N*b{*t+L`a7 zO3I+aB{a|a$hR8iKa=TzC{MIsF_a}`%q`5+rt}kRE)|xfGa{lX>-T|$-INRkT!E~1 zob>t4(ZNbjHK$u8njn=@E_8At-yi$J3NJmZG(Sok`aa(NbYo$J@}pZgxIxc!9af!p4fDP)0F|sHgX4%(6ugR%N6=NzjG26k~?JT@( zFMn&E4P+;Ht9l4;XEJ|F#-t#IX9z*s~#*1r#UF^qe-;S7h;Z5>v&HlI!y47+Y z_|D?6Lp{3qis+;Q{BTFx6E@C~uz+aTMdVdj)|8^R5!jt`vMaz>8`jE?#EfnTMmcpZ zewy@KrdYaTD|ov^=Lm;DuGkA@&W`{t;?v-~JjuTAM@Aca$zDI*+SqE_*>IN_!G2bh z9Ofaq1EH)aRH$%QyC%YJF^R#)(LoZ=jVVp3ONlh%kYf zI3vTD(m^7PIt(-%l7~^2Q*#FmdK?Y;24-aeUuz(%+)pN9*%SWCC@^(9B;udXAcuYz zGZJA@Z8ZG)zL9rH+d5+tyDWvJ$!(y%h=W#R^D;?&+Qak@`<#CTqjK+`4tY@QPpTvU zcgsm?M{PGix?Jp><}zPbc)4BI81a^0%*xt=ozX#$L;8J(>ullMpG?SGq?QY|v|0>e zD98htu4782|sPtnOdMhIB)qGolzw<1b!dpIQX z4?p8}cZ=EkMS#0MRrJiKNy)3hJY;q$F+&VQ$SFJ&=%8vqvvQ6Z?%YmPn!U6X)#t66 zW2hl=WwgPLXDHS4c@1RzJ7H}NAe5&M5ao#noj`6<;)2pzV}Pe9ptt_Iz1elkbG0o_ z;U^CsWUKJMD#R0?V*?g0j)-8}5po}%JG~jHKVDxPu-FieF>%1;#=$0*-?1HQoqPxA`l25^BFekpzab{0~VF^V( zl4`T>^U(8IHm`>IP|qC3VGt_3kBSnqjGmMJXGweg!4|i=XmmneY{8#)lPu9CN!=T$ z7z;-b{VdL1$bxM$JtNxCVi?H@SkdX<-<%ub-+4;Z(j0p=f1CHfRn+rkTCih)prXkl1jyC(-pL$u&JJkEJ^oSaAMd&FG z{nn03yA*?6GC5kA{kcUGKpj1>#kWrERakaBQr-&Yp??~z8RS=b-&PUeeVg@zvMqIG z!LLpV2DjQj6oCY#6w}I_@_@I#y+^F?~|LQ|?SEK?zi^CRgDq6}M$g+&?qm z_wItV>uqYjdd70W(rbW`k-SSkyPIct?%BbX`lQ8F$xDP<^^w#Q!XHYRc8cSG;w-{+ zBzEnTo~lnq)e{)j!_N04dX@EGjO4@;<&OS5Z{h zGpcW}NH{{vj&$nqJI;@Ta4!0!+H|AW(6h?8>00W}EhlAe8MeIb4w6~iU97|l3a1th zrQhiS=70KBzX-?$ul|U8ys>dJWcpxd^TU5(m1$2~dc_3_j)dYI1&ml{(Ih3Hro4}` zt4FdGFl_Yl{_c0E zR2TGa?~7}5Se%fD_y!rPn?nb+x+!hcW$-iizvTzZhfM; z^%8rnWzD*M1(BesMIz={;^g}%>#x4&GGCP{h>UKfWEe1!W0?h?(5d?eKC$y8wXk&mQQBNEpLhGby!lJ?-Jj{(PQWw zm_-l~ODOjMhmf@+9ss$-^y|okWL8{~UwmvLW2MXhu#@jm@5~uDHs&HyCqBd+@_iJC zq4z^p#YuI?d?RBj-)hGu@t&%I{k?iEUw#%UBo!+L-4LBKzJE*gWFf2wo+QB(P0xZN z;Q^2ra^J$iEr2Y*WFYaZ!z|ku^bYv^Ohh!l`tTFZX8HZ5HD-W7i~nmf@&z;XdNqwo zNPjMhmH7pa9m*5D+$|J^h4ApKd~kM;(o>h_Y#uJW1{f4~yF?HghMB0s%?*NV_pWk7 zJB04h48ukgkua2)#JsoZ*o!{Lh9Rn>h}2e_)H3a?9nE%*9# z<6(Hay?c-QKRA8d74^fEu3;Hpj{XlBgJf*}s}S3XwZ%Z5|HVBpzpha5yfaqePmVbP9}!W+_3&fJ8LTO)!Q~@m_ul)qWeJvQ}LmyJ0YEy#%&mu_o{jEn3HM-rgGdz}kM}+MSC^L*x;L>;N5!w~&PFz|9eZ~(+#hQhX&G=N zyn;0hCT3!6;Hql^KDHL(3{T$B06SxwZT&?@_2t;QK(#kp=Xm=g9|f7uXsc3U7J`y7 zhkoTvWur|83}%X)`+n)tlBKFM8)Eg+;5nowL1P1Pd5?s0J(ESSLRBVXI5l1jy5Gk; zg1929RFZ{# zwOqrU2yGpdnxZ;xr;Zu&hfWvGC-G`RXmSzuwmK_OBg-)nWVe(#yMG?=#++TEI+p5r z(*M6-S3je2kTe7g@z=WbM_&jxf9K3|sM=P{Hs8?Dt?qYW1v$;p*USMt;#3DKhh(c< zT9e8zC*tj+Fx)u+a;sQh&qc%|HwOeyJaPC!R8z69y`47pA_}tYxT7Z@%3w00wXGolBB&>v0q2_7uRzpU1Q-I zznk_5>$3eDZyrT(6#%;Yhek60$zMd)aWaq5%cP!P9R zP=!ls^@o14^qcy7uw5C6i7vB@J8z7u)tdt@HWra~i04fr0?Nu^*E)fBJ8m3E&qcux zYV&~PrRRXT|K60?(h?Gyt%rqf2u8D1+sC3We$>BO@bsZs2>7WB*a)O9kG3DC)P1Ws zA>^tog-X73+Wc1mgcr&*@K-;)=Em)>`WocSbgBTnG9ce-Ze^-{-F0dl9T^=(a?96U zb>w_HnYnY#v@#=cc>GTPFLs;u$fOrXF%;1V0N!yvR4%?|7DV>8TGk#-Z6U(?4Tk{s zV4`qT(sT4*3G1e;#l%%hg8%lk@sFfa_1q-($4ifYyb}CNSM1o^mbBgW;rOosNOm*X z!Ae(C@wDX*G1x#>V#xJsD|yRiKkLDysCi6Xu0VBrZL^2Me>SnAb)2bd1tjD5AKsJn zF{2vJ+U|xOM4nWIRIlpeSl2fdc+ypaT!IS25QMr7_&%%$_E~vI3}5hl(oUiA_l4Fu zliPUyk5LIWu92==xp6lPpIAvF2u`f5X0O`D3Z z0PHMow-v;vI6h`60{PPTq@Y6-Z*O=tM=C!6?;dSY0O@puIJip{**oC<@0^Y;OY-7E zzF@qE0MXZ<P9fqr!C+bh3p7z#o2XQR`!+8!wWq2D~#9Q*l^`b-2t@br{K|U@00O!oe zpXe)quCXb+#BdImRk=j50!%6U{(`;25VNoQhPg6`ag=l&D5lSnjZ81B(@TIr{day? z&~jWpHje+PP?XkB&<1NGiU#7>iT2WO|9v)$W7h@NBN1c1={GexQHB{1;W%UZUD8)Z z;movt=2gE+5ju7(^qeON!fRprXAw6%A*5T5UgYGhx@(yMB|ggNT(v$jn(A`HJu}6l zA4VHek7!?=hhTS>3HUR(N6f{WrV%}R9qB112K;_roYI9kNG9z}0vT*P0jyRg*CxF=ABx7q`lhi?Mw}dXqoEoF&UM#v{!Nl6uLeHsunf8~5Rv zzrr`J0^z*`TH3oT>^Uk!`Gc&n?TD6M0`;aiZ?=4O)wIYvcKe##(kaf2z~?fXf&O*p zoNhV2C!-`&F&_xsG&L@@O*Z5dR(glC?%9Q)mygrI=2H@rZx1+@_HOEmR`WP@aYU}B zJ{rM~#`?4aCpqc1-j)#yk%~mQq13_nX`PUqG}n$URmX!TdEp0Jf3UK$H0dWvvTo0Z z7tHTxC;}ZIm8)~MyyV|h_OZL?E{wZZG3ZrKUaM*q>pnnx4}OPN9)(dvthh71?*3v~ zqxK?{1!RjSYre(FnClB)cdAnZ-vLsM_y8H>X~!~7gT~FLVSS9E z+8%DS3{!kyHtFZ=Yk%sqBy#uLc$4+uZIn(B>ib9bvZbHjvbMU(9wy#fGPAib6YWn4 zoe6gxE0cT|B&I08=G}|F1xYiyBdC7BON?fXpw+JroQw0&t1I?Yx3HK0aN@j!)ivxysckvn+5BV=4;xJPFUwnwk7nQ#Wj&hmlu<@1OPlDkCDnR-|$M;={ zX@n@NdjToe*0&G4{F03EBrfA+Y{p5NZru+^s9s6l$m#*X6h1e(y|xx;22YqGFyawa zJ6oUWcCakZi-&S*D)F~18aqz?_&^>x2KGUp8t^oaO<^}~NEcL-jQf+UI$)!B z0@tm9V}Ne*wl3wXs>5G~MtPpWZ63@CVVb7#OJ4Wx?yHq5-a@B&5o7sC!EES`G67-U zyYyFDcez)*v*`YqDXgBDZQPzp2`FQ2<@QwHb^In!A3vhvPnH*{q8UTRKW4pKLm(C+ zB*5u!bN~3=e}F@SsGXS+avG1=m@p*7?wx8M zJ(-iI6eL?Z=PZI)(7V;W6EIp|kQct6ma zApg5S^eJlsUFw{X-bmj&kGRT@==~U!X8s$%M;*BoQ-9RQ6}$QNP-zpPgi}Jqn_#ctqvd)^~Q`6uCt*;t`q8aAe%oNq<8}JTRozKom7Y zSuU+-BY2ktHJVEMW)ea(fOdykFLLO-NA8U9ywRZSdmo){UQ}kMqHK!{5<|+6k_)j& z`IO~v#R1v0F9UDoEtqL*jc)3FV+GdvcNN9dybI_s6)y5{j6GEewnlEi^{I+aJ1fKq zp=ch)l~m4w0VICp`@6Np6q!Mb`EzyL-$_N2#%+`yF|-2h=S!H@zH@E{*3RzY{$jK# zMLKn$N+~hi-F1iUP*0uj(qFr)?M-I@@_pqT2VQ&1R1RRz-Rl_1;6Yh^29>)+dXbT^ zfisI1WQPixtz8PWZoAOZVIt*0pIycpJz-z0lEY@36Q^Msv@xW#5Tm96u&NwZ@{nL6M7o;A;O(8J7zeEL5Y zz`}m>lW;P4+y6LC%k6xxdco8A4#hKO;jx#>C`y&aD9)LIbOHC4$*R`*Udl+e?e}F* z;_1GPyQWsX@5ih-zNDYj4vSUz=1^KBs;}jk*z~ffT5C(ipLi=@^JMu}!k#CViH=^k zQMobxeS_xT`&_&()QU%BwTx4t-Zk~&0=T|G?dOzJD0|f(a1Qh;>>2bd|8#y9`+hVz zOiYuJDws36kreA)X3MGUPrJG=O7IQ|;+RqX`F987Z7_2(%5<*~24ns{r#h9tU^my1 z10)Zplw=(e_%c{5(jqqgT@81A%=?S%i`V_O(}-x+**bOKM-V=FIsi@X+E{%9r=MW& zqKLd(Q_RyI-47IC)H4RUg%0`-PLWn7(YOp)5S5H(8mjUtA0@NoMqAmuw$ zr>~9dXu&@q*oM* z%(zUgl%0>{gro{zzY1R_10<`LRaUfQvLWeCSya0)_Wq|C$Hn0pUuK^m!JUPWlS5b z@4=bi9^#U#5ZFR=4SN$X8}Ox@%TzSC>Q^CtLu9ii-r%<$mhIUO*zHB0|2eH(ab;{E zDo|<*B>+{<>n#`{(pgEo2{iNG5sZWOWX?#v6@04u-JQAlj-t7E z1n0XB0QFYeQJNhoW6v^M7(+GRF1&2F4z7%eq?}?$_uCsdhxNJCjn#~7=XU87>6xZ% zi#6f?saNQMl5&=C!MRot|z{|N*ka@RlJ<*EthmT`llZc1Iylah(!2w*9>An z48p~D(8Xv5T!(Y^ap0{N%+JQ}RNq_4pRBz9<00^A>K^-GPj)OJ&Xvd}-5VR-Sz3C3 z4rmd{7ubvqxRGLckkbCZ+G0g>*F~(I!>3LZl+AO4d^IKW>7dRp0eJV0oz69HIJ2a` zoR%L4THO)W6q*Vw#Q0TJoG8C2jso|55m=6b-vWfrb7h1wCUzMRL*rGV?Y4VS;#suCa2!y*Zk+g+YH~o{7ikc$G$r{ z7P&OegFS1m4({p>N&UN?$vUJmT-(&9fvpQ`3--O(n;(}z2CO8{c<|Ss>4YR4#w0{( zvT+q2CQLzdKL=DwejqY2XtJMWtd{nVU9eqwu2U&l+hw5jH0sTQ9%G+|&)Hv8Rmgn$ zMG8fNOl~IgwHYN@HuPGq^R%AD_&<+$aHeyl-shQq3A!EBaxu=3CL_6Mq^1PMeRuzhWI3fdA=^5hoMu-yMZPX z+c1$|g`n(Mp^X`rPsDNim;R0tp!tl7KyqA%L8c=81^@S4(QK9{Ib;1|v_cG@R(=$S z>T3tvB*&-7-ig|}kU53E1I`5|L&p3#Y5#mQs&~~&;Sy+J` zrqYk5epI$&L$ANxAT8nsP4i@Tz!jxqMog@$)*Cx%u4T_VY}xF4__lUdx9G;UTH6X1 zf~0h(|EhrQ3yr-rKq|L~;&XOKUIr?|skxa(wa{Gog%Z5_`XuhIre#s46z`wKErYqkLnbTwr(b~BVEQaIhpj4Zsl z`cw#3apCoXi7;_{{fb||-w(Jq0FhS-i!Bb8EE^$k;}(n4mBfvI}WsamOkZV z1I@J8mA|uUGjc`>m>Th$Hnd z4tm1C^(^lnu4dtq0G=D6F4)fJE19o7{8o&p$HMd~KndFE2lh+DJQ&yhw$a?vN4?&1 z_jDa-uVGt6uHFs{DLbck!wem$U)vVCOIVyM^B?86=YCmie|rVGZ~gOUsaT$tiR#g* z@+=XjWWH7j%scpF{Dt|8Uo-g~3T*QIw>}!DxF_6Z+vJ`wt>#_g32mg?iPG3?D{O%U zRL_~h$F;jfdt~GpQyh+kc&Z$Aq+{Y_QB$~Jt5)kJAj9mIW)SRm7!@>}++a1IuF1U% zZ!+mnop;Yo&xWgff$(iQ;rC`Rnxpawf5-NS#8bm&j<84ILb>(@HcW}VQ)cMUDvYLl z!W7O4V#L++7V#`m@na>p_|SY6PmSP4|E?oVwf9CfNg&-Oia*1sJd>KfE;>Fuzy0i0 zw0VFk=+8!T8w|P~W@>j>%DR(l-?HVPm|6PYv#~be=;ksqU-hc5AEdHQ7M?ov^+OJNS{urf7OHiE%sVhYWR5=M#J^v=%TXV)K3{h zNwlL4gMDQ9eS2?Fp}obw>b3djP@+jk{PZp{7sr!$RYiw;CWjsBxWFW-*ge|myKyo6 zOhNAjtf~&7n)HzIg3+I!M_6T1DesZTVeyhGHOtc2X6sLCN3q* zxIDwiYhg77V!}QVPzU}ajaW0-XiAg2l!`e4>PaSF#95dj5RrH1W(4AGE zfx@yLO&U<`FZlo$lPGxX_20#QzyT*W0e>}U*smH~dLlQ=<%$fW07-%fYA21=1sFZu zsiHup2gJj#t5jz+MVVM=?FgV4wwU{2{`krt`e8s|0w4$;sIPoX> zdpDVi$V{W%;Yd%lD)bq(T&?EyZz+D`P@dq9q`|Y2tO>Xhi19i*^8^mhfCtLs1FKz< zTiOzRU)>Z4jbkp%C0lOhrv<8%5K-sDw@bo6)JRT zd-K?14au;4Rw}kt0S+bq>5~3sE-Bd6>%~?cArB7n^6+^lqj_cgrf|RYS;wQ89mM0u zkH4L{wLccpf9vHbRyIsVl2zG7LwB6C>=q$azuk2>30UMnkZaqZDmFxsk z!JXMNP&+&sC#IA&XKsM2<*ESA^#e3yV_A3-3C%%xJTay3E!`pV7gTPK2 zDob9bIabbHQ>Xe8z&q*nz5~h|#fWER^k^R8?d!5i-}hcdCwrQYCZ6&UCZC)0=rTz5 zBpCX?$;h}4n^zii=qJBcsyb)~l!xuSVZpEIj-Zl-iSL7i4-`RIBt}{`x4M8fb zVaK-B(AK}pjR~~t+miyzH|p7PNe*)e`c7DOsL!LV1@K z67if53GYZETql5?&`2{Inb<&WjJGM^aoL=r9TUZ6m+C@{0Jtpk@+SJg&g#<-Sek~@ z18$yErqr3p;0be$@Ofu#CD3A>qa1YK%X)fSPPS<4t?1UAEjOeoqbDriPvm^(leY+- zHB1*ye(}}OtoC}wTS&PxnEOROdM|w|^-ubs+FF5L(4(~=el7;nZFfY(9|!xdbbR>+ zrR8UeYaCL4lhSi`ra3zJ&h*pWCGB~19;7jdU&%=nQ-#kD;B5W@bnCCc8EUI}A#*Ij z4%PeT)KcEdKkzGWbAru`m;Z%GqKcjz#`=1D5#os|Q~snMANF$1q5;^XfS^kn9c9jg zHx{3XU)D~jlJX`;f;|itjJ{FXBNkO0VXFM*2g7_I2 z*{b76_JT5gDq=iBh%vcDBLbh_F;+DRpi-_c=oknUG1>GJY_n$(lO#>we19^U>(_GC zbg+ax)jtf8gRZopo1&=%BW+x*PIYC2k4kB>I^&^X%0`o|rhU8OAHCb~~-#OG|3b~5MNK8Sg5~gG3 zHiPU9;9U)LAN-%$FN_|xkZALKG*nlPjkr9w*pxB>|5HzT&xt+?*N}Bugp?_c&O9ax z5$D~mhhKddjd$@eV7lWJM%1wH_b{_3I`hqu#izw~0Tyex>tV2aFTIf?U%g@TeqH<^ zM$`?+(WVR@Jsln&w(bb~3? z(}Tl{U*sw+rdo{-&hCPIxIy*BB==laVAkwDdN5#n))YCj=xw0V`NlWt@@r+i?h?66 zV36@^&g54JH&c+0;olATRCB%ZPr%<|UlAuAQcM`-_Vgi9U#d$S#HP-cX$fxRyPrQa zDub0hjSMw<$`@I*>vb8$>6}yCe|*@{%Vf_9vZEmp_mpkGAq`L~tJ`zVKp zp8t0B3gdq~SYTzz8SN9Z>?BHS&SX;{zJ$B zdW~4C0d8b{f@Wq!`i3Dhl7t_fF^-q%@R$vFC3g>ij^tFG%&VNFonV18P|9p^(%x>D z?(76XLOpgWF_x8MzX{e`=(=TH=au@Z4e-Eb$6&^5(vAJr6|r7int{`l@yg7ldo4*mg)g zx(+AT=G+Dv#nq3=2rm54exW)CBzjqu84Q20MaP}l($F4y{8#li)*jU=wG{KL)g#7x zTA^p*_{WvCCrn8bCZaLDL&FL%c#XQT*SSb4u7#@Y#dyFRA`yA;T0GY6rT=9Z&7H-V zSV@k^^lgS|zFC*tc3+j-{F5CSXDRH5v9Ut6iqvKiSy>TZl<%w)2RsrHK{dKuWjui> zRt5af;RAweE-*{ux)g!z7j8vhO4A5cdvN;agoHDZ31}-yNPOQ%`YPB8(D23hv`S1#jy$VYqq_MH~EtVsj(`8a9+nOjybn%@kN zJ9*i?Mlq1~{yYU7D=x}IC57aAwfu#UvSq)P4IKr%B`WTDm##&ppBB@nFiYC;c;IcR z8M*B4yObYwe^ZqtoW5}%stZtaAbPYqrDFb*;Cr;R(`K92xc=Z%9)S~7A86*(WOt*!cUg6n z#KHx8OZ>hu7Iuad7w_ax-`9NomaBRzx`4^EgqTe-bNnVjSYKtAR^eSlG*?`mp*IcGUCk!Kc9Fx?MK!7+NHBRrv8Dxeu<1tNP(8MxqN9{9LZg96vMT z4J#$u;k11JFZk{|u)~Yxca&3_CaCyp4&mgZ#@CN$?WjOL5mjTO+m$V%z=(%NGF1^B z`9N_&;XAanE%)z{-p~zf{bP{N50QcJ(~fm_4}UsaIV#uMfHiEArBxt~>dyHYqy+b8 z3(?{al=QDP4T|9NUb0CO(&7R-yjSY6PYf_nLG!|-Z_Mc5uG=B=gmHoPWZz1 z2|!jaOd$y?rx!OLLCkMiR(8zsI1+xy-zXUouDz>PCTFsDlW&-4ul#xuQpB@^=`r87 z+=PeafVHRC#$AW^1PbvBf4U2N#dqv9&ABeuL~wRQ%g!p#Y~R%=ty!745X+zL{6*nwIt9QMWAg=^95?7;9bw=Fq}% zL}F`ZYi1_Xbx3tsmhyxsZB_@X$wvAA)B)mJk1Am&e{mRD@|z^%fTf>8$qM~9d;|*w z;iloGP~yVpUy(^uvEr%vTVb=9zb{(ynSvWe3Ug_`LpH^!Xo#_-;j+*U(fG5m6e`+{ zA9o263N|V|Fnnq6^-(3k_JVgiKanMxLCN_Qg74?HFVhkulNGc38++K;2Q>wl6d1!@FG^G(a zHSv`R7Fj{8q|I)D>7%HkK2rr-_cnw)>Xa}FoiKaI@UUdw?2JTy?=62s_kMiZXy~c3 zVrs6<(ZRf4o!%PfO{%SxJsZ}K^ql8X%fV2HoTxqbXF>&UI?T7!5hxV-1u%5vs*I6g zG@JA;`taMGRHF?FxekWnuowhfNSs0K?JFByB!|)AaLqFf1zQ81jA$e!}W=8yN06nOR;x+F@c1teNgK^YJqk~b493RA39d>HFODnXmk4(Uui>pmLk z<-VpSnRxCWln@5P4CU5t19vb`+*v6Udkuj{|K`RYPrel3lQ5IH{K3@=_)qH_1t4^d z@_Z6f1?!yuMYm%p>2#}rF7k#iKQ$-M8T>lv{!p?yr&qScOK@|8k38jgvah{$<_+(vxkotRX(NV^F4Dj{(mZ$F8xk#DpkXHPM zBFAt5hz9HJWOxXE^Zp0E#iwYw0%wqwPlDpAR3O1na2&ElUwpNI90k+FeYe_52-yLB ze!>3peK!YhYz3+ zRdEvx=3C)quI!#Vo5| zuzywjlB;w1Kt9)nV!3u?=IVoyzo=p}cuv^9e!L4oSqw2~qj)Ac!lHrZhsuHUflz`h zc>9hAOa|=*^Z9zv%`F7prd4>@rMQAim<7>`+8lA>3IKpao|xt|2V9cl!?%Bt7rxZ$ z9m-<3r1&c>PiWNnV#L|whIKAYdG6}!nQOjZC6!!3|35Zq@^^-;nlhokLS;IGfe+kwri%R9$g zL&}|7U7bq_V~{IlB2c|wZ!R&2sjrc7?UO~ZuqTEPqlLuqAf=6eSgMnxDFU%=*n$V8 z4v!Pe$}0*8Y;QB+JM+hqp36k))(7l_d5mSEKEK7O|B(4%epKMhE2~k}17r{>196T| z4lIKn{AQMniUC*p^oCW^;fZ*5S;WZOo4e9!kg*2A4BUH1tLnf@{H_)+YIGYBAfVg< zY{-svwB`p3?~@o6Q#<&mFlsT>Q3&(C(T$yXxFz}H1Jsq(_gZQ(_6Q zyc)?o9lnxIOscy%xOR_U?H~2XSvy-^f|^)wLAS6fPu3CopY{X&2XLs%W`Pdz)MiZF z-g`w9Bsloc@YjaS4nmd{IIT(0+Z(-qxA5_hZ#hXO`{>gr*CykRefcfR=v!3CLq<`C zse=04$FotYL+Mt}`UlG2l=z9u_c92Qzx)O>jd5aq;K&ieAjD$;segsK+9jj?(< zm)0p^PMW*W0mkojA1PU<46tr++NaS0iKrGztHUmuy&_kUR zy!}muL;t<+Sg+bT_Q@%$} zpSNt#HDN$q^cSoTAJ0LnR;6_Z)|Ku6aseCjj2iA(8Gy+J5&d*WYBOXjp`?c@_bRtf zhG`)A?kyHj!a?KmlBN3z+0BcPHJp?QHHbcgfHn4x^Rr=dF!(4u(h;q;SzG-z-)En1 zRBx-7WGBans+Y zCp3^1>+~Lo>{p%ZCXCz|Yf8ooC=pA){K+;#l_F{o?z{1g(64>-KgfR;0a1`J)@Oc& zV?9`ihsOfsl@n!AhD06U(Am<+eS9D>J1*H$R9%7jY%b(|dJOHD;ul%eZ3jDj&_^mh zPTJQ$e#)Zg&y+mzF&@eOg!>uWBOgJLCRTV4@V1!TUAN_f$p2#j+_n&+aiYISB3jZa zU~hF(1SB!HR)eVmYK$xP_49dT#0}tzr!;3yN5VYSVxv}D2#YGk4>(@z`h6w0-7SVBO`V~&)UTCKlR{O z=zN*?&=7g8s=+yr=OM}D1NCJ$+MLN7h%i|y9D?m!Z?k~LokI)ulJ&_+btqc;bWiNf z_*asc@*ru3a~q^>YcHALNOMGpUQG41x|@@x0(*eq@%xG!=onrB^M2L0{PX$f1mT+J z6dH*|gVCN6e+cT6)ttiw54}TQ9 ztKQ%U_D7bp6WWvC4HlH{sj3*hD^M-e5KB>`B8M={yg$@1_IK`gO5D_86L9{Hxob9w zCBSQzw~q7Pkr>np;D$jaefISB8>?YQTgupgE6lH>?b|QS~QLeUtF|gWAS?Bv3wUoQk;3d+qJhH`>H7fk-*a z-_C~HO4Kdtl-;ak0>dA*Ed~Df$Y|Z) z{i{fq5C?Y$4@k7xRM4zLpb>EZpFW0x+v!XLo5+p9htY5Lvwq#@PcsmfzZ@0cS+FyC zZK*Lf@n~c&04%|2f1jBYO2r14PHr{0hUx%~@YIu9yKwoOTWK2DNhD239{T8;p4!vz zp~Hk%)8L1zND&Uj|3qPSB$k|u6a5mz+$K>Vh|~=GiF+&#fa8JwVEpmO^y1qE^77bs z5O6}e_H;XYB(WU$oWn=MlgJ;1ll`;U_yvyKkYmR;Vo%3&Wb-$CD}AHui2Lz#%+se5 z&ZxlC8jKIa->pR}3FdCSPZ3IG;6hX{{z;&LE%_?AlDZ9o;&FgK_qVRp{e!7=UG|FV zGajkyCcQ2Z#H=pIDD3Et{`rHJ`4Z@%bN{@E(YG3KB zah@SINN>c~NxylH%oFFT-VhO5eJ2-WfAwtQu?2tLf3iiOfUGg8z+qEwEom-F03@o< zj#ZjAqX(cMK0$skzQOvyx?)#flb~S9+zXY7IP-pq%os1N=32{V^S4>S$}I=ynq_zu z#hs};BlL>~D0|PPujc)1{I?J_H24o~HUltjagdK+Nt?|^6tQbCW1t|K4J09rL|b?( zLLO|F>@!VCo~~{0(h;9%n3<7tu`7b-dhE}=&9l$dpP!tDuy;Ud~f#5ZnG>gaO2F%&c<`}a?OgAgZrFF z>Q7!P{gLMx77R4LUtinvW3g5CN$l;NSVAtt6Lx;Q;?bk0JS{2Ulk>TwPa$yC-@6Yv zXa$irM}FPT93do_BD9SplAgkeo`LZWYi8Md%9D=_kWvXPm!$q|$$&p3FQU7C^wQ=Y z9hhal-lzKFxo2Xs1DRY`k=H9SYA)0{+z~a6%&0o8C6!Is-o+`hMrtqH7_|`7}Pz4ihOiWUyD4=Z0WLlBAE6xLKC~* z+=O9sUrZ4kKP-JcrXtdF9_Z(JvnS>HRSAf>YV?M!(+ua$%LHz-Vp-gEA=t0z9aD<* z*ymK7$xL&;0-i9BZ(f>xDe1F7r6McE9rS09+*t_yPcOE(eAeC{UAQud3`MnqL(nYu zG17qi%Q@V)i6Cr$)yYE`88(wQu{2q=*``r9Dz?r+$aSI(*wn?>U0c;np)pcl&M`PJ6^$lrIOxTA4S#`J_uY5l_IW849G={Z0C>FKpc z{iWhWc6vS4+d8`!3_HPGFUdmxaTw^Gnm`jdpafQr9J{N1RCH!SKa>7E=8KRhLRAL( z!SFOD_0L_Yg2w#k&$j-@+<#>-|GB31KO@9Hs(U$W=%8&5=*dx%0RmM}f&I-vPoM_E2&-R1$y?5)tRl<}PPI?>3!K z?Y+eLD`Xu|6k17$I*&}U(B!;;U3}n9b$tE$Nt}A#p<4M@NGUwNwz|P$KOS>>`AX4j zFiBIq@T&72PG2EupX2dqB3^<69`O|XikTed?#sWO`HR4#=DM^U2IIOd#Z-aSs+iV$$TF>Dw+N6Wx`Y{0LhBAj9`UoV&UKYk(;Kxd;2N zitgV*{o#%2|1vYoU<1E!>kXM>)eB#s9@Hb#`DN*TvX8+5efY4og-$SI3noy};fJ%c zt@jcE5eH;+Vpuxpo9xp}hY(PZk_jD@o4GDO<4s0DkHi7pr1L+lO#~fuhF&7qZ1FyP zZFXcA{4VDI^a9|1BHFiyPPrV0GJ~TGiHM=hg0}O=YRCcQ(DhDzUz4(aPW;nP|HJ{L z5s>1FuI0JwB<98p)b{k*_vP~?JH$>>vVdZh1tgyJ!TS|i=P%PA=1~?v*8xSq-e7*=$QeoPqI*yLW4Qu6!yO4{ zvv7!bnh_B4Kir!q*=L#mES@9L|Fu7=nH#Xd-kRi@&GS`)0|Lxa7~6qmk7N^=nFCFX zk*Nck3kOuKUVeCgd3Fe?(0B?%{BwACwgO7%tu}B#+dP3}9uVgtBKz|+eV}2*(^t{i~JAi z@trbFqKJMql|WVwP?0@gfzkDz&H)Le5xjf%4%B|)jlV-mp*FZb``>5(i`)@0L}DWS z;~)R{O<)}8_JVyner-|gD|TkWiOIu%Maa`9PQyr24aE4zm%A^Rfnx~huC2|aKT2kD z%$CaWPzErb|T`4wqTID zq0_(O3BB$f*hR1D?GidinJc=!5Ra;7*RlHjegC)r7PpvUTm#NvsEtD2i%ragcFB3+ zp!V7GP9~&voN%{1Z~NnV?4@^O+#wBGazIH0^eCx7>GaRrE1Adfg_Bt&2jouQWvP>s zxYvz6?)^BR392JcozZyqxo&p|$wUD(2%`cho6W9XvHy$qUn8YY0{kQ0rv*M=P2hkE z2S=$%&$9D9UHfA;^~`|-f&}`ls+c;E1q3gd1L8#1`g6GjOXGm#4haxYju24Jx`-31 z46QTo7zY$)tQ^BRazGhN2c&yYrsJ>H3!KmXvF zfGxhrP=r1<4wfb%AZWdyyrM{-zLK98Tkj>NC$<{G;#u@RQ#c^)2m5mW3G_BqA2bX8 zQ4G*UsuwI(vu1KQaf)AThRai0Av%$o`Xet+a72uXV*DNo%-R)?s6fo2Jh4BRKeli7 zX$%DZSzB9}>4qCG#Q{+#*c0V{FC;mjNAZG*6WA8q5%-*7Cm8F1E`b9&Ar1%;P^FjT zfS?opsd#KZ&94&zO2Es9y0_~j&Fdwu|9vJAP)r~5 z00I32v5N0G$Y8?d`X~L-=%)*v6=Y{YyV&~`hD!S^uuaMok+Ui0Zh7jAPs2d*tvpaV z2V}9(e+UQk_U$K)e`pIY&S1BB!N&O>{`}$n@K01JgKEqf`xA$50w2XZp*Syu(zJ&# zh{{d!#Y6tjsKy#4fq(X2uW4_^m4SiAIH033wKJ-MuCj@bWQ}eN$pIaWdBN_f0}^xQ z@~pLWdHCZQyk1=)CK}!FpaZHa78(&yPwRkgFqi)64Y=Xg%aw}O0WtHVbU>A8>bdxO zm{HhgKHLvAs_rZuuimVtb3jJkGd95YID2f3H9_m^n|aEf7yrYEe!y|zl=1uzCosrm zpe-2jJ~)v;k2r)0guYZfg>eTw+`};T4Gpt@4;TFZ_WOP7v#(E1ez|U2e-h_7FaPkv z^0j}RzB5;kpxfCSOMyM|6LJ!2uOAwh!!xa}f(hKZex)WXC!T zkJ59YC*=V>nI#YC5YAv#0d|P@x!eM82H>Bwtq)u1!~ic?1-D>y0)tMB3}7J20U{1} zUFQHv517dZmEEa2p!sn?MxMt8>VQ@=R{s}sLacAr4X8bsM;(QKp!@x1t;3o`fq%r| z3+4@E{=nG_@(*G9bTMxX&Rku&2V*~cSD(K|>^?1Dc-p%qc^!#mX6^opuVX9gIkq#& zlqSe8{qWC!F2@rXXm+Dh@|btq^tcDdd`m05y$6$Lus^^L_SWd?;R!_eCmcgSb+;bZ zXFxOc+mTa}ONug_0Q%xMxW9%-=4%0N63>Q|%;^NM|I*VTiG4VOjONLB(zDD4IuQcRzd;feS)p8B(!k{^_krI_H4qMnQ( zUTnHE|M{s}qS%!!M|@HfKcl&36LL5*kSeoqWNub(CmiH}o~{d= z6O8G9ls~>ab-OS}4#+r(Z7eNsEZR;m-Tfuo6yarNf&A{ss&fY_GDDC`4;)Yrc3&=L zRt&|t(&^$3tczL=(g1Z)kBImOd7wlm*huc*+nUdb(>R`aU7!nkxBSC9LmzE(JBU8K zIOSt$*DMHV_D--Q0&)#U*dH)|82!NhOY=Wof&+4g_3hujA3opS9uD1GaFD&f!n{Ow z=!BTpE8gSA7EW@@y{qG^%vJU(6T}ZtQ_H=b;oGm{-fRdc9UIQ@JhrxwQ4JU>6FSB3 zUQh_AaHJE1WG1xqfGw~`Y$^vtbLVyrXa#p(E09ay5~r~D?+-t~8LV}-0to1r_Nx=( zfUp;}Y4pP9Z}1ee${bK{f(D2#KtR(tpl(LxAkL2ig4=OY^^?81;haNA+>rej#0SAS zOmRZ%q<|LZuk~i=;{1sS1L2vAbU>{CVMbb_AGmcR=>?-q4oE?Cyt^QnyQTpp-;RI% z^~YZ)s(@xVdEE^G-ID{7$z*yL|Ln0&VQ-C&)SsjW3^dT1?bSb%gnzbw+lI+88y`gY z16$Qb%F_g#+rY z&PDelv&<9%+Q?=U`(t{+ZV2iTqeO(T zDTOSQI_P0&;vXZIjJ)vWVom%MjxI(Q;5mwoy;Two#WQq&d3V4>@r1qBB=yf9%K?!q z6+7Z3273KW^>@v23cWS@P}TMwUGV7~Oq`<0nausTQE2(($9vu#$I|u~D#Hg}9;3H7 zRvUXr^#(L%A|!aefo`E_KcP{STu@<57gU&ZQcG|^g$Hp!XNS0Tzx?{@1292bmzN*T zF3;Y-`sM7yR=fSntFK?JJj8X<0ig%%DRMxdgMJDKC^w!3Ewh144k$$d8h7Wagx--H z(1xu8LJyeiJf&t=+>6oM_|^h@z&epEHJm;yZ1~9(uk?rXJ3b1M+DTrZLbL zIfcHcIizk6m_=gxa67#C8`ymT`sXn8%q(9!m4}HOXOwI;O}>u*-^Ix29rIl8 zVOk^eim(6cuYdjP`gH`d)Ze1(r&xpHsr?vU;`z?^u6C9V78a5|)g#XAAWkT&bU=j^ z9gs?>Pi25+;(+W-XzJmCcIK7K_rIK>0%+^~*RSII1qkR>-9SKue`x9iw>weXC2Uz(gBIDFWCXFa(+7byi7pMbhz(=I#7FnetLx4T;)C07zn1$&>{VE z1U?;_I;01}JVbmc?q%J?Z1#26j3(Xy)yve!&Uwi=H`-d$W9oYnna?)w<5`Iu@uUs> z9T^~*`#N_HD3(oe%ma}k(ZE5^#N3cG=stKzJP_0HPar4IR0ljdd!t)C^5X0@8kkw~ z_AFBQiTM8=rM2Qsb%@=*2g8%tHH0Pr0ulr0?=JPD#0K9~C-1BqG&YtN!}d31#M2ft3)xeWWS8&CkP5f22r zF4(zu*!K<%gy1`Ec6GXV9cJHQGHnh!EPVUh#7C6zvV4=>okcq;~SKxbRv z0(<{_>+({}pXz1%`TzXV0tCdJ7?em)J`Bo(rW_#B0o`<(mhMMhmFDd_pcu;G=gI*! zGzWCd+)pNxT@^2h``PS}4@~KRGVBK<-ef) zCGk;Ky`DAD&w}cSp9cp78PL!Lb_i_r`>*d;wpwS^Gck)^2^`dJ*JUTh=XIl%2QU!! z@^H^Yez!7_10nrndG8sZ;n!`S5H!`)p- z-6)52W|T?6TJ7bUcqnp}C(I3pG>ME}RQAI|CQwbbz>k;>Dr%;Zun_(n*G9}0QTJxi z8C`JO`~~PqT;I--*1Z|t6iv~?IUvuIywgMkbhlpk1U^z22&d3bbpMIZW8*mJ86p~+ z8%p(kfg9y*68}j4$Bn!RU0}r5{ze1nzo&6EQPIXZ={G{Y;tI!-f3*HOnHMyBzK~8U z(tA7f*{OdIyd50#Bjacxp@Ys^Jz?^FX7*1Z{cNThyAzu`EO}e{ymkc8d;Zo(QO+IiQWDE1CV1$)e6D z%Xu3aLj}ZIAauTWb~~G$^=345HU80;#zFG+iyiA7g0@eK{Z1G!r&grv)GpzCeT|vWu?rZAO88nGN-S8V*W==Am^ux5#pb8euwwku0lXl@JDF$ zWJn}iGw^NA+{rt$WJr7W+JXV*QD}%a@salM3wVU?GgPT8TKV#m=Zc|*Hj{#qna~qB zpeHkPKrdMf4Jl;r+wUQv{%q^RhqDjWHhST=%}jdk1S2PWMoyudd^0ze1x=k`gp2?I zO*z8~1T^OyAjtt`r3&!|6UV^k1@w>f#ou5C5Z{RZ>8+R5?#nZAkCB)u?nA!hX>90r zU6Tpwl0Q|?AnJk-hz|&giA_mylw=X8cgmbsj<_yBOXN_CRdRQxbHj}8um?^d@o%n2 zL8Vuzd=ELYo`rhM*B-zDnLLm}K|vA+Sg$~X%k7c8Y0>?L)AK||`+`_@)fyns!Z>cse&bkG& zKv$$Etn5zX_v7;16A@VpeJuB1!0=Ft_l=yJ$`f{z;cTEzuZNjqQa^E_IG_uKfe8Po z`>-p1?S^n|N0f^wH9?jejPihLwNV-ds*RFAy-7t$ZKV050b(NHi2_GYqL@AQx;I1O zpcG%%to)DL-423Y{wkB{^~z!b#ojoh{a_A=)O2;1ePM`#E>I=-6LZo(NlyBiJ%g@z z@?7!t4z5qesf>&rpOX5YAe@^2LwScW)+^(Ad)gK%bVh2+Rg;O#dJ|S->_gLM{LgZS zbj7ZbmNdK*7v!1Tk>OkO^uHyzT3S{ffyKleDNJUVWh#(N0V=RJEX(=OlQ^I!ck_aQ z8$(Q?v#r+q{ucIxkr$qo(A%T~vN#~@gkM!BnNB6m117uT;q_>m=7Bh%`SL#viGZ+g z5EvfXg24`K?S|5KrtSa$AOJ~3K~($~nEi8u+92eAn(L(e(a%C|!f&V)L7{bNZd#nh zhO()dy9$8?vb8|YI7cvc*YD@gQLW#+O&dsDpIzF-Hhk{)8_*54|QOqb1Inp ze;u>G>sCKjL^*JyqP6{k*Bn$phm3vF^PzD96NB8nz&4)njv64Tb5>c4l40VH`);tf z#0gnT5&>lm9kj^-WmS)}p@g2!0o~mTW(}a1gn?dOUcUcux%Cy)KvhWQz(m&fuj*e@ zPGC>D4^_2z#)dE98G<`VV6vF?|&FAru7n&CYrc zd>8gP+@)mjBoCChBH)4`V-Q|S3?%npzX=)wuj zhKoM83+nsHolai@|5U{MITi@05`^1cDnC634v2YQ!`FR56DU+?F@=QGhF+=_Q|A!e z-aIq1Hw^yyw)|%=c=q|}=VzZkTgiu0obb@S9O4XeVh+9FRA6 z4oLCPJ6ZO>W5Nbx&V%YXPuvgb5hVxI+pLs_svmqD1G{7C2ksEB5a*M*qj!*zhNc(V z$rp7mSkc~=)RNDc#iWXacPPc=e5%R!7xno}xsDu%Cy^V+39Zl_I3c$y{?|L08Ik#n z^Cy;i=oAF>03DELY=k_GffOr!fv$DUOiQKE7m0^7Ci=qDM&qN`%KH^S`p<>Vf1bp% zfT$0I#s9jNE~8rD9>mJVfMx3U}jxpaK6)jDKVg;Q}z`$VD%x zY()4t>Y(sIAoDt*MdocS~^WF_FBI1Go|7_#zLH@bSI>ew>0}NCv)(repOIh01 zCMkz23Z2Am3~uM<{DFD%T1_6rJ8Bw{_kz7&!Nd;Ky23N4Di*i@y4KG`-gpL& ztwp}KpM5*X9Pc#r&;AC;_uYGX#N^kCBZ#)~xP7IchO98lpQ z9MC&bLL&?GdkcN2t;^~eI5Q5<&<+1eH^YBkuSgyAQ_TT^3R=vfO(Xx==3ZzptDFb1zP&Lw8L3BeBq( zIiTC{k@hc1o>wtK)_#n3WauCJg16W33%~wF4yr&-9>6}x{>cC1@$PowW6)Pc2uOX5 zzslJ1jE(DY?&#qHoKrboRI`D9b{BgO^N8W*i}6o4GxpfHGI<~Qdcop=7E*9ecGAo$ z%!LE`9d}>Vtu5+BHMd}#$BGR(Js=c2hJ!mM^{%P33@s#d-O_lJ6q^NB6+X z&I@`UDx+b)Bb`64(jM!{LpVtCJz5v7uWii(4M`hxfqSqn=K^sqG%!H5T(LHK*sYeP z8%o`+fwEC<&g3@Op~s*rxn9OcW89AK*WHV5^SoE7bhlGJ8ZYt(-uc%@iM))eT>st^=xE+1$-NwLkXn=S*nWc>(v6 z6;LS4`9GvO6z}MC)+@AiKt_jfk2fuMGogo8dLX_JUG2)i4)w2ogT=Wl19bz43E8Xv&L@J9lD;<`l$YSQwQ{*JfJCTkejAcl+3gkxjzlQ zeEc#{_mATK1%LfW@8`Y?o;>uwGv;D2{ZyXptcb7ara$HkB-=lV9+2TY)-&e0SIo~S z_u^tEjN^y?x%krekXmh6kCR4Y`MdFK=z`JToE_^v%}zVBJ-inT<_%^dZXIG4^dauS zUAB9&$cGsul>jp&*!^2|XVK)EMW14gdjB4jE{n z$rrXs4tPLwom|(2j`S#U^wl-h_eBV39o_Gp{CZ{R;=URA5!Kb{ z_6Y}h@dW(iB{?98g%lSwq>RMS)B>qZ*aKOhbX+tedNSq|Cxpn|Sde$Fy)OaJ@NY_)w0trNBMPTwF*`#RLCr@7g_YET!eF69UR+CUZb`2YhzC&oF_3 z3J>Ri00EuRK1{WOoxLXx=(*8K2v+zG;~&x!XCM`5z1%EM?uAEAD4Oa8Bc;^b`Y<#C zI_9sFJ@I*(K#;g0{vnkvPLVDo#}9{-&tGHvFyKvwd;#_eH3mW+Xd4-5;DIh68|Xs0 zG0NZudpHX;8bdp^TQE~nQKWmsYleQ8W>nxfGGomRJx|RabpneY+4&myP( zHh%xb&(uhu$`NAA0AGg}@HYSZ0w;{z$$Fo7j4|<+mw$l!rxNsmS(`3wqr_{D3=n(` z!4>Sl0Q+R}phAni2Xjo3_!D6Jo_a12Z!M$FFxeG0!3$QHn#6He9neG$2r_{#Ast%0 zT3tCj#9mZ^fRF={Uiga4L%dN*i0H?-=~T)_2Uz+woSF$;xiV(;JUO5vPTa_o7U*Uj zbLM;EU$VLWedG?K?$C*bw0-xCl;ZUBft%C=ZS&(H!nuTcpoqPyGOdGHAlihX7P@As zdLADE)eLW$`T1ssjq;sojQ}ZoK~F@?EbqPi1P2t)lLMM?XFT94#T{H-$|zCn8#X0{ zIQIb`jVR^Ko#?BI$KQ^Z|B1JEzs8nN-PKNsx$r+`OSKzTdYR1Xc`qo7?{TdC?GO2T z1dMAQn|n3maj`Sb0cDjINc-T^?vKm?9bRHOqUM0M6bA%e_+C;6#9nxDZL;OUc&5Ce;R_D6B0}yh=^PBYWb{Hf(g8X{W2qPazys)v(sbgq&#%t``NY>H zyvs!UGVB>+Z*I6Mb~B4FY*)74f-Ns6_UaS-U^4gl595FY7W!TK;w1;9TEP+=5b)4> znFo~b@wRKy1;0+`fSQX-56=T?r09TP{gtPF9lV3%bhFbGh>YAbUP4i)bST;>=}pr^ z6F$e+LxF{e1KO6_=qTiq80G^x!o$^e7S=C4ELi+WL>P)}OM`jUx&(!F5g8Lf}Y0Ufdy z=q0{XI-twpYzY@`lk^5`~YuBVck z4PBnf0eOCNQT4jtFZ-vVymk$Xh0flnJRt1-Le*j9GT#H8vRV?gXBD#q7O2% zn`d(*L}7#o2%YND-ME=K>3k+!{^>iMKmYu}zb*gSN=}@mBMkUwd@xPc)Fly+nFo}$ z`cMnAa6l%%Ff5Clu=a>_rN%y?ks|@Sn$9bC&kV^bBS{e-g*|WGHiGwVpW8J^HKcgnv z$O;;g76=-|%4OcemjiZ${aFx@rMapxCpp zrZ=?%edyZx1ViNp)|W&$^m+(68F&`MMlRD$Gd*MZk?-EGOm;7y%z$amNECVd^raj` z-<|$gYAi3)7VK6XwCn;K=YM2J*n_=b+=`*_kGxe^$O|vdU?1YOTTwgM1;#pP zOe3pk|5v&eD4eQU=q;x5ICtZI8i_0*+`?mbeI6#z&F1>|L)k9j*^PT~THd;S>(Al? z)Ep7;L9D+WcCkklv!RQCfocJwpIYtDfqz0)(u|^YMTr_&|`5sGhgwScX)eyi%$$58DGS}Sbn$sZsgzQHA6j% zU&$;^e;nPy0gZD#Q~95{c)<>t{~;W7NLd_&fXEI1eZ}N}I?{t7God?`N>gE;+=PCx z;ZzQ&*?2eyq;V%BpcflUS@HF8;`2ImllkiTH_?%<*a|Os_DbL%Lld-(ybpWD#LxFv zwHMnKSO}RQr3a!O)xZ(>2RP^;SFWY%nZJD;l$O@W`sy0BdITfV5;?N{RVo~08rcLL zkQYznfLzw)VBX)*wYeX@Jm!I-P;CjQNs`;WBt~*?)#kX5jDg(vSAl87H67E`!I}Sw zz|s$ccm`}1$GydkCFAjsVvYm^B+ps5V4(YQK$CPpPtrM{mESQF$mW2mA1-ME)wh3s zKGusWPGL95|KJ?j1r9oxzyV2aD4faxAp*L8_D@6UfD8sm%%EdxZ|$sCx{zq>`-*4K zKBm~jKC#_kbDLwpHL`2?{?+{o{E+w6bvZA(8*xH(B-KE;3k&X`VE%TnkJKuvT*hP~ za?MCjLyic1_#tk?U9G0kEoU?8fF^Fmlm8PblO)zj?Nf7r{-_JtCVIxZmH#>YM11uR zKV9F-1BsvI-V^aKkdJ}JWDY1hkpntP@9Vh}2lV7#9FW34h=2?Z=x5CVJ=Gi#^?`v7 z`e{$~e=*-P){i0HH=H`TdyR)?|1?Y`5crFimtHLGz}MO7b+==sSn<5%=H0W{QEw6k zy1=<&@Ic}j_ky@*#6;VOdw>Jl_7MMwx4NJS;+~AM>euMAf}%X3Y28gy^)SO37xR*b#PxeA9FWF1d>b0x;Td_L$L4^%p*y_wD6&NHOVK|6`#2y^X?AY;JoqeeqWx(w80n0|3Eg_W7hKK4p{8&^ z3ziNjYk0vH{!k8x@sHF22?X^1)$>F%{8L0g8Qsd90Ucs9usNU`nIAlMDKtCa9kN&{+-K*CFn=Rt^1i7HfKOLu}+N4e+o2S-igucf_-UzDHr9em#MMz7hiJ*TuOCdbzeyS5$ZDjCJAF`|x|<`S}8OVQ_UF z%111B#XJ_beR0nfbEE&nTe9_Rz$}sUogr(jvMIfI{M752EVJZ;Tth3QHefa%6k*X9 z?B=2<`lEOtb1L2=-}zS663rj)^YM!r&kzCu-Av(tvdRaR#6PAF>~;?5iNyiYifF3HB%LEY_EeHhndn`pf|J=`}AL ziIchGx_$YPA!>cP^tkCu&%m}GWI|i#FvS6VH<<%6wa{7zM4cEvKR4&k(+>Bkg9e)NfOebZ z=420;yh3YoN8)EJiGUh+);;eK_Ibg&XNa@BYHWzNUu?j&ys@gb>~QLK;2Ab_{dzpc z`}l2Bh1l2ZvzRab2|okZk^3QpbP*0dz8(b8SA5@BeE(N>I|RLRIV9exE~XE#K|yWr z<6f>T713e>V{$lkV58kS>40KQ0o85%6LNnb z-T}KlmdYocTk`J86PXisGPVNmSBTrMhM7Y%IW?U)potjB?17)w7j}0J=)0vSw{k!$ zlm}EjgmijffUp-8@({HONNvDa1(aV``kyooNM51QU*tu_QOyYr9Z&j{GF z&-18AiH&f2>UO_(H8nqz>piMnDHM>VUA7@YO5TiJ|5X<{_d6Xccup z`DQbx`5*CXE)4^r7tA&AkM#_c;DB!9ftdSgTrFNL65_$B)400IEV2d~@XrfCKwe$* zJYMJowVLCSS1Fcftr$DiPt;3;69UetEk1|&AHX?~N({Lg;yIKyUWkak;%=i3Td*)! z%LRdSg%$S)dxIL}0u4hrpXk_ip%=4G2Evh9PXaVH<1CH#L zzwdhN1ExM=KJ!ZSv#nBdIVUJWhderH!Mnyu9qwZwAV`~+Xe$_nch^?C?)AGLepr5X z?M-BXsK;#RyG`!ZnDI7|1Inr_=p&^A%BE<5Yz`n6$=e}z2q{|KA=g&pNgY6F`dd)d|ZQM?gnGPz0xGx!VP&X&yWq7KzL44nHX{dAFgYMbK2v(Z zEDQwwU@5(*$N^Ep=}jiHihg)NK$S|;1D2c00Xe|k+S!9W)S(ZO`RfEiz!9dKQ zy0+Yo0l1c>)6r)c)!O!QSgnpWb}@DCW?h*hP=nc1V4N-683L#0+za z#nFEt{+Wi1YKF^fVCael31ozCL+4p-Um&89BcA1861l_Sw#-FQr>~(oe<&xB=a9oE zu{rL%Je)qxh_h`W^&oKW?l1Fxg#q;Tx;_d2!08_s=-#4+IkP8pzT?j8IOEV(qgdPD&#Yc$^5@6Q2yHZWc6OdtILBD4pJ4=zxZO!| zKa)|AIJ1R3eLmtHUJi=lBo%snbMo}@Mi@x^O>P(jAI0YbW(q>cqM?+;VKf9^80di_ zorX!{|L`T&XlKk%2HW?_>WtiJLwdHCmnY`|B^w9}DIT!fbkIo- z2q(~i%A-%^fK2>@_p=XYTLuRdNDgTI1~?$)16$2N&qSv}X+YEqmc{{z`4dzk{%P&W>?6hyDX%XYh8>Wi;&G=RDDae%#95$2t{7f}~>T>T5w2-U?DI_Y2V z6sq@6#MSS=@}L_mjLP8!ZfDRRKg9M_+Jy1+$ra20ksOdYJtk?YM~e9|(Gj`PYPFj6 zeG5=c#C>Owa^g@55S-BDH)P%{P-rn)0k&fgM$vteo&9Ma7r4&r zH8!SZq9-v>V~G&ZQJNRNz^F#@I!6;Zprbo-KnFJNc`*S2$=l&dwR+atDnT=RJ(0$N z9FUO(bi*gGvg&{*{FBrI1!aem{=L}YbGOL>Wf~Kb#deJMo4V)5)p_T9b@l2v6F?#} zKeq*$>`r52=lF9uwi44-ZZW3Q;5JMg-(tViC;TJtgnX{W`%8Wtg=OG<1YYwrBP4N; z&v>UVKSJmSI3s+!&F{krMO^7Hf_$K1}9V!I$XWnHMEp^XG_G{FV+0>7rB+_3& zv6j>kvF{AeTI@fQy&ss5DEIZ#I=DRVZkf#VvmD9&Ud{X-xp(f3S3UG8{bl%A^1aN# z9dvWN2b;_RnH{LfMxHxzKm~mcBNU|YPs$qprFFkVCx)0m9|QvW1$96_(+P~4;h*M7 zeYnbJ*$>e*P%;M7W($4W}<$DC$ z;?X?X-^=tW+XBg4mrhHqQmI{{t5oup*17GAiA7uV60kof@+2l^2I8MmyAKCN@r){v z56=~wXCAxP;V$OWNn6aGe!qRvhnM1guqkuDdfVX1fW9!`p&jW9!wIA~jz8lbYuqcA z?5DT?ee=S5wJCa{fwf!HeME9DmZLbXTRlI#*B|R5yB`7?BsY2jnT7LE6q)b${qX8; z&dD8C0VQ-mM`=7z!Qz3E{a^*&mL)l$BZC97GodB-bC9ltw)23h0s+ZH=%{p#l_>*^Us__J_3FRpiCA19ei7<{#vb;B*HjG*8GfhY6)r(S}Z1YlY-|>N6HgX;zcH8`1C90BOyht+2VDg(JZ!;!`HEQ_pTC!h&^P1+!~Iv5bU+=M1%y{H&j0ZH9qHq7 zoRpcKG0@LdW&k+({QPQhQs(oE##Mf`*EvSD;m!u&pw*@e9bSC85~rs2Y3uZ~D(_Xi zTCGwGbU$JWd0`PaV$dbFOL%e;NJ*T$#KftiW1<{}Vipm-3|b()>w>A%XVwQeAFuxk zc%MFDpMJaDuER7UR74JW%!?KnDBK=)havJnU5D79VD#tAMyzSIvT++EbUyaEs5bVQ z^Vpizrr;`DWhA>jYKe_ofc^~Rq$BP>o77P;18x!6*!%<A$+Q?>%%3g*R&6Jfr99p&m2% zIWMm+EzP9;SxV^ZQaPZ4>VYrlGnlmlo81dm7~_DL0ZR440|Giszw}s!SoZm!Mbt_k2|n91pyIGJXoM-uC>C#+S<{RF@B#|>EqQ-rn9=p zdY{GB^=|CTv_p3^_&9J3zt;)nZEjW$g$?UY+5)&fCNf(4}yA9X}PG;2JdfxTND4FwS^}e-zgTz^!hFy zpNn~Tz6kSY=lFBivod^~j~@r2XY9Syjb{-48{vN1_Yf}u3Iac>Ku;ghz?$VJRJc|`HE|@3AUJ+N=2y?LXEVmGKY+Gd*X0Tq%gbYVs>SW*Y1H9*P>#c8 z6nM2Grcb9*KT(O!^%(qI4*1l)6U06->VKrp2lUSEQmc9jb4Uy#IFDUKquPL6*Pwa+ zIEcKGKtCnksF&n~sr#C3mfQEbjeXjTete07`t4W!I;SLVb8i^vgSx6G1Mf=r`zLd> zqn^sf9fK5)yX2y4W4o*QZQ#=X%z?p4)lyK9Y-h9m_%%wf9;uU= z-*^wd^`3Ol+>6>{1oRXz5O!h!270;+(}g@>#P!H7urhN$>Ls0lJ+M$E&(azJE$&8s zwELv+dVger5fBfiJ z*r%kqAh?%KOX4~uEc9!&P>+p(6OG#78ChUO-ID z|KNtd4QI4ArJB)C;}Eq#luXl�(;Tz@Jh_xZez%G1Orq9*2DHq(7d(49!PJoz4N- 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

K#t1uaUoyF;Yb5VKmjZ72#9ne-5 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

H{|ipeTjjV|-MX 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 LNkvXXu0mjf-YRax literal 73995 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 From a419d4e80884b7beb2e46c13b47a513d4ccc99de Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 10 Jan 2019 20:55:50 -0700 Subject: [PATCH 250/265] Added find_user_wallpapers.py * Fixes issue #16 --- .bin/Scripts/find_user_wallpapers.py | 81 ++++++++++++++++++++++++++++ .bin/Scripts/settings/launchers.py | 5 ++ 2 files changed, 86 insertions(+) create mode 100644 .bin/Scripts/find_user_wallpapers.py diff --git a/.bin/Scripts/find_user_wallpapers.py b/.bin/Scripts/find_user_wallpapers.py new file mode 100644 index 00000000..3ea182f5 --- /dev/null +++ b/.bin/Scripts/find_user_wallpapers.py @@ -0,0 +1,81 @@ +# Wizard Kit: Find user wallpaper(s) + +import os +import sys + +# STATIC VARIABLES +EXPLORER_LOCATIONS = [ + r'{APPDATA}\Microsoft\Internet Explorer\Internet Explorer Wallpaper.bmp', + r'{APPDATA}\Microsoft\Windows\Themes\TranscodedWallpaper.jpg', + r'{APPDATA}\Mozilla\Firefox\Desktop Background.bmp', + ] +REG_HKCU_LOCATIONS = { + r'Control Panel\Desktop': 'Wallpaper', + r'Software\Microsoft\Internet Explorer\Desktop\General': 'WallpaperSource', + } + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +sys.path.append(os.getcwd()) +from functions.cleanup import * +init_global_vars() +os.system('title {}: Find user wallpaper(s)'.format(KIT_NAME_FULL)) + +if __name__ == '__main__': + try: + stay_awake() + clear_screen() + + # Build list of wallpaper paths + wall_paths = [s.format(**global_vars['Env']) for s in EXPLORER_LOCATIONS] + for k, v in REG_HKCU_LOCATIONS.items(): + with winreg.OpenKey(HKCU, k) as key: + try: + _path = winreg.QueryValueEx(key, v)[0] + except Exception: + # Meh, ignore + pass + else: + wall_paths.append(_path) + + # Copy files into ClientDir + dest_folder = r'{}\{}\Wallpapers'.format( + global_vars['BackupDir'], + global_vars['Env']['USERNAME'], + ) + os.makedirs(dest_folder, exist_ok=True) + for source_path in wall_paths: + if os.path.exists(source_path): + dest_path = '{}\{}'.format( + dest_folder, + re.sub(r'^.*\\', '', source_path), + ) + dest_path = non_clobber_rename(dest_path) + try: + shutil.copy(source_path, dest_path) + except Exception: + # Meh, ignore + pass + + # Open folder if wallpapers were copied or report error + delete_empty_folders(dest_folder.replace(r'\Wallpaper', '')) + if os.path.exists(dest_folder): + popen_program(['explorer', dest_folder]) + else: + print_warning('No wallpapers found.') + pause('Press Enter to exit...') + + # TODO: DELETEME + print('Wall paths:') + for p in wall_paths: + print(' ', p) + pause('Meh?') + + # Done + exit_script() + except SystemExit: + pass + except: + major_exception() + +# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/settings/launchers.py b/.bin/Scripts/settings/launchers.py index 80b199c2..ae78c3f5 100644 --- a/.bin/Scripts/settings/launchers.py +++ b/.bin/Scripts/settings/launchers.py @@ -215,6 +215,11 @@ LAUNCHERS = { r'call "%bin%\Scripts\init_client_dir.cmd" /Logs /Transfer', ], }, + 'Find User Wallpapers': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'find_user_wallpapers.py', + }, 'KVRT': { 'L_TYPE': 'Executable', 'L_PATH': 'KVRT', From 624639389445edcc042410274cd7a0bdec6378a1 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 11 Jan 2019 12:31:08 -0700 Subject: [PATCH 251/265] Fixed update_fastcopy() --- .bin/Scripts/functions/update.py | 42 +++++++++++++++----------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/.bin/Scripts/functions/update.py b/.bin/Scripts/functions/update.py index a9c7811f..2331a604 100644 --- a/.bin/Scripts/functions/update.py +++ b/.bin/Scripts/functions/update.py @@ -250,35 +250,33 @@ def update_fastcopy(): # Remove existing folders remove_from_kit('FastCopy') - # Download - download_to_temp('FastCopy.zip', SOURCE_URLS['FastCopy']) - - # Extract installer - extract_temp_to_bin('FastCopy.zip', 'FastCopy') - _path = r'{}\FastCopy'.format(global_vars['BinDir']) - _installer = 'FastCopy354_installer.exe' - - # Extract 64-bit - cmd = [ - r'{}\{}'.format(_path, _installer), - '/NOSUBDIR', '/DIR={}'.format(_path), - '/EXTRACT64'] - run_program(cmd) - shutil.move( - r'{}\FastCopy\FastCopy.exe'.format(global_vars['BinDir']), - r'{}\FastCopy\FastCopy64.exe'.format(global_vars['BinDir'])) + # Download installer + download_to_temp('FastCopy.exe', SOURCE_URLS['FastCopy']) + _installer = r'{}\FastCopy.exe'.format(global_vars['TmpDir']) # Extract 32-bit + _path32 = r'{}\FastCopy'.format(global_vars['BinDir']) cmd = [ - r'{}\{}'.format(_path, _installer), - '/NOSUBDIR', '/DIR={}'.format(_path), + _installer, + '/NOSUBDIR', '/DIR={}'.format(_path32), '/EXTRACT32'] run_program(cmd) + # Extract 64-bit + _path64 = r'{}\FastCopyTmp'.format(global_vars['TmpDir']) + cmd = [ + _installer, + '/NOSUBDIR', '/DIR={}'.format(_path64), + '/EXTRACT64'] + run_program(cmd) + shutil.move( + r'{}\FastCopy.exe'.format(_path64), + r'{}\FastCopy64.exe'.format(_path32)) + # Cleanup - os.remove(r'{}\{}'.format(_path, _installer)) - os.remove(r'{}\setup.exe'.format(_path, _installer)) - remove_from_temp('FastCopy.zip') + remove_item(r'{}\setup.exe'.format(_path32)) + remove_item(_path64) + remove_from_temp('FastCopy.exe') def update_wimlib(): From ad1d7d71f2ae2d9dec059199d6780ad71dcbd688 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 11 Jan 2019 12:59:12 -0700 Subject: [PATCH 252/265] Fixed ODT sections * Fixes issue #86 --- .bin/Scripts/Launch.cmd | 3 +- .bin/Scripts/functions/update.py | 31 +++++++------- .bin/Scripts/settings/launchers.py | 40 +++++++++++++++---- .bin/Scripts/settings/sources.py | 2 +- .../_Office/{hb_32.xml => 2016_hb_32.xml} | 0 .../_Office/{hb_64.xml => 2016_hb_64.xml} | 0 .../_Office/{hs_32.xml => 2016_hs_32.xml} | 0 .../_Office/{hs_64.xml => 2016_hs_64.xml} | 0 .cbin/_include/_Office/2019_hb_32.xml | 7 ++++ .cbin/_include/_Office/2019_hb_64.xml | 7 ++++ .cbin/_include/_Office/2019_hs_32.xml | 7 ++++ .cbin/_include/_Office/2019_hs_64.xml | 7 ++++ 12 files changed, 78 insertions(+), 26 deletions(-) rename .cbin/_include/_Office/{hb_32.xml => 2016_hb_32.xml} (100%) rename .cbin/_include/_Office/{hb_64.xml => 2016_hb_64.xml} (100%) rename .cbin/_include/_Office/{hs_32.xml => 2016_hs_32.xml} (100%) rename .cbin/_include/_Office/{hs_64.xml => 2016_hs_64.xml} (100%) create mode 100644 .cbin/_include/_Office/2019_hb_32.xml create mode 100644 .cbin/_include/_Office/2019_hb_64.xml create mode 100644 .cbin/_include/_Office/2019_hs_32.xml create mode 100644 .cbin/_include/_Office/2019_hs_64.xml diff --git a/.bin/Scripts/Launch.cmd b/.bin/Scripts/Launch.cmd index 0a0330c6..3a3ed6a5 100644 --- a/.bin/Scripts/Launch.cmd +++ b/.bin/Scripts/Launch.cmd @@ -151,6 +151,7 @@ goto Exit call "%bin%\Scripts\init_client_dir.cmd" /Office set "_odt=False" if %L_PATH% equ 2016 (set "_odt=True") +if %L_PATH% equ 2019 (set "_odt=True") if "%_odt%" == "True" ( goto LaunchOfficeODT ) else ( @@ -161,7 +162,7 @@ if "%_odt%" == "True" ( rem Prep set "args=-aoa -bso0 -bse0 -bsp0 -p%ARCHIVE_PASSWORD%" set "config=%L_ITEM%" -set "dest=%client_dir%\Office\%L_PATH%" +set "dest=%client_dir%\Office\ODT" set "odt_exe=%L_PATH%\setup.exe" set "source=%cbin%\_Office.7z" diff --git a/.bin/Scripts/functions/update.py b/.bin/Scripts/functions/update.py index 2331a604..e1cd277d 100644 --- a/.bin/Scripts/functions/update.py +++ b/.bin/Scripts/functions/update.py @@ -656,23 +656,22 @@ def update_office(): if os.path.exists(include_path): shutil.copytree(include_path, dest) - for year in ['2016']: - # Download and extract - name = 'odt{}.exe'.format(year) - url = 'Office Deployment Tool {}'.format(year) - download_to_temp(name, SOURCE_URLS[url]) - cmd = [ - r'{}\odt{}.exe'.format(global_vars['TmpDir'], year), - r'/extract:{}\{}'.format(global_vars['TmpDir'], year), - '/quiet', - ] - run_program(cmd) - shutil.move( - r'{}\{}'.format(global_vars['TmpDir'], year), - r'{}\_Office\{}'.format(global_vars['CBinDir'], year)) + # Download and extract + _odt = 'odt.exe' + _out_path = r'{}\odt' + download_to_temp('odt.exe', SOURCE_URLS['Office Deployment Tool']) + cmd = [ + odt, + r'/extract:{}\odt'.format(global_vars['TmpDir']), + '/quiet', + ] + run_program(cmd) + shutil.move( + _out_path, + r'{}\_Office'.format(global_vars['CBinDir'])) - # Cleanup - remove_from_temp('odt{}.exe'.format(year)) + # Cleanup + remove_from_temp(odt.exe) def update_classic_start_skin(): diff --git a/.bin/Scripts/settings/launchers.py b/.bin/Scripts/settings/launchers.py index 0456376d..73dc14d1 100644 --- a/.bin/Scripts/settings/launchers.py +++ b/.bin/Scripts/settings/launchers.py @@ -360,36 +360,60 @@ LAUNCHERS = { 'Home and Business 2016 (x32)': { 'L_TYPE': 'Office', 'L_PATH': '2016', - 'L_ITEM': 'hb_32.xml', + 'L_ITEM': '2016_hb_32.xml', 'L_NCMD': 'True', }, 'Home and Business 2016 (x64)': { 'L_TYPE': 'Office', 'L_PATH': '2016', - 'L_ITEM': 'hb_64.xml', + 'L_ITEM': '2016_hb_64.xml', 'L_NCMD': 'True', }, 'Home and Student 2016 (x32)': { 'L_TYPE': 'Office', 'L_PATH': '2016', - 'L_ITEM': 'hs_32.xml', + 'L_ITEM': '2016_hs_32.xml', 'L_NCMD': 'True', }, 'Home and Student 2016 (x64)': { 'L_TYPE': 'Office', 'L_PATH': '2016', - 'L_ITEM': 'hs_64.xml', + 'L_ITEM': '2016_hs_64.xml', 'L_NCMD': 'True', }, - 'Office 365 2016 (x32)': { + 'Home and Business 2019 (x32)': { 'L_TYPE': 'Office', - 'L_PATH': '2016', + 'L_PATH': '2019', + 'L_ITEM': '2019_hb_32.xml', + 'L_NCMD': 'True', + }, + 'Home and Business 2019 (x64)': { + 'L_TYPE': 'Office', + 'L_PATH': '2019', + 'L_ITEM': '2019_hb_64.xml', + 'L_NCMD': 'True', + }, + 'Home and Student 2019 (x32)': { + 'L_TYPE': 'Office', + 'L_PATH': '2019', + 'L_ITEM': '2019_hs_32.xml', + 'L_NCMD': 'True', + }, + 'Home and Student 2019 (x64)': { + 'L_TYPE': 'Office', + 'L_PATH': '2019', + 'L_ITEM': '2019_hs_64.xml', + 'L_NCMD': 'True', + }, + 'Office 365 2019 (x32)': { + 'L_TYPE': 'Office', + 'L_PATH': '2019', 'L_ITEM': '365_32.xml', 'L_NCMD': 'True', }, - 'Office 365 2016 (x64)': { + 'Office 365 2019 (x64)': { 'L_TYPE': 'Office', - 'L_PATH': '2016', + 'L_PATH': '2019', 'L_ITEM': '365_64.xml', 'L_NCMD': 'True', }, diff --git a/.bin/Scripts/settings/sources.py b/.bin/Scripts/settings/sources.py index 2644d4b6..236ba1a8 100644 --- a/.bin/Scripts/settings/sources.py +++ b/.bin/Scripts/settings/sources.py @@ -27,7 +27,7 @@ SOURCE_URLS = { 'NirCmd32': 'https://www.nirsoft.net/utils/nircmd.zip', 'NirCmd64': 'https://www.nirsoft.net/utils/nircmd-x64.zip', 'NotepadPlusPlus': 'https://notepad-plus-plus.org/repository/7.x/7.6.2/npp.7.6.2.bin.minimalist.7z', - 'Office Deployment Tool 2016': 'https://download.microsoft.com/download/2/7/A/27AF1BE6-DD20-4CB4-B154-EBAB8A7D4A7E/officedeploymenttool_10810.33603.exe', + 'Office Deployment Tool': 'https://download.microsoft.com/download/2/7/A/27AF1BE6-DD20-4CB4-B154-EBAB8A7D4A7E/officedeploymenttool_11107-33602.exe', 'ProduKey32': 'http://www.nirsoft.net/utils/produkey.zip', 'ProduKey64': 'http://www.nirsoft.net/utils/produkey-x64.zip', 'PuTTY': 'https://the.earth.li/~sgtatham/putty/latest/w32/putty.zip', diff --git a/.cbin/_include/_Office/hb_32.xml b/.cbin/_include/_Office/2016_hb_32.xml similarity index 100% rename from .cbin/_include/_Office/hb_32.xml rename to .cbin/_include/_Office/2016_hb_32.xml diff --git a/.cbin/_include/_Office/hb_64.xml b/.cbin/_include/_Office/2016_hb_64.xml similarity index 100% rename from .cbin/_include/_Office/hb_64.xml rename to .cbin/_include/_Office/2016_hb_64.xml diff --git a/.cbin/_include/_Office/hs_32.xml b/.cbin/_include/_Office/2016_hs_32.xml similarity index 100% rename from .cbin/_include/_Office/hs_32.xml rename to .cbin/_include/_Office/2016_hs_32.xml diff --git a/.cbin/_include/_Office/hs_64.xml b/.cbin/_include/_Office/2016_hs_64.xml similarity index 100% rename from .cbin/_include/_Office/hs_64.xml rename to .cbin/_include/_Office/2016_hs_64.xml diff --git a/.cbin/_include/_Office/2019_hb_32.xml b/.cbin/_include/_Office/2019_hb_32.xml new file mode 100644 index 00000000..d98dd66a --- /dev/null +++ b/.cbin/_include/_Office/2019_hb_32.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.cbin/_include/_Office/2019_hb_64.xml b/.cbin/_include/_Office/2019_hb_64.xml new file mode 100644 index 00000000..29e10c4f --- /dev/null +++ b/.cbin/_include/_Office/2019_hb_64.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.cbin/_include/_Office/2019_hs_32.xml b/.cbin/_include/_Office/2019_hs_32.xml new file mode 100644 index 00000000..3fc1606a --- /dev/null +++ b/.cbin/_include/_Office/2019_hs_32.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.cbin/_include/_Office/2019_hs_64.xml b/.cbin/_include/_Office/2019_hs_64.xml new file mode 100644 index 00000000..3d2956fd --- /dev/null +++ b/.cbin/_include/_Office/2019_hs_64.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file From 4a96736592fadc6e28eaf4cc9886dd495b7c0fbc Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 11 Jan 2019 13:17:25 -0700 Subject: [PATCH 253/265] Removed network installers --- .bin/Scripts/functions/update.py | 31 ------------------------------- .bin/Scripts/update_kit.py | 5 ----- 2 files changed, 36 deletions(-) diff --git a/.bin/Scripts/functions/update.py b/.bin/Scripts/functions/update.py index e1cd277d..c703bf71 100644 --- a/.bin/Scripts/functions/update.py +++ b/.bin/Scripts/functions/update.py @@ -182,37 +182,6 @@ def resolve_dynamic_url(source_url, regex): return url -def scan_for_net_installers(server, family_name, min_year): - """Scan network shares for installers.""" - if not server['Mounted']: - mount_network_share(server) - - if server['Mounted']: - for year in os.scandir(r'\\{IP}\{Share}'.format(**server)): - try: - year_ok = int(year.name) < min_year - except ValueError: - year_ok = False # Skip non-year items - if year_ok: - # Don't support outdated installers - continue - for version in os.scandir(year.path): - section = r'Installers\Extras\{}\{}'.format( - family_name, year.name) - if section not in LAUNCHERS: - LAUNCHERS[section] = {} - name = version.name - if re.search(r'(exe|msi)$', name, re.IGNORECASE): - name = name[:-4] - if name not in LAUNCHERS[section]: - LAUNCHERS[section][name] = { - 'L_TYPE': family_name, - 'L_PATH': year.name, - 'L_ITEM': version.name, - } - umount_network_share(server) - - # Data Recovery def update_testdisk(): # Stop running processes diff --git a/.bin/Scripts/update_kit.py b/.bin/Scripts/update_kit.py index 3bc31a72..18bbb69e 100644 --- a/.bin/Scripts/update_kit.py +++ b/.bin/Scripts/update_kit.py @@ -110,11 +110,6 @@ if __name__ == '__main__': width=40, item = item) - ## Search for network Office/QuickBooks installers & add to LAUNCHERS - print_success('Scanning for network installers') - scan_for_net_installers(OFFICE_SERVER, 'Office', min_year=2010) - scan_for_net_installers(QUICKBOOKS_SERVER, 'QuickBooks', min_year=2015) - ## Generate Launchers print_success('Generating launchers') for section in sorted(LAUNCHERS.keys()): From cb072366e0659ca2d7339ab1eee978654ca8852b Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 11 Jan 2019 13:25:33 -0700 Subject: [PATCH 254/265] Bugfix Office sections * Addresses issue #86 --- .bin/Scripts/Launch.cmd | 2 +- .bin/Scripts/functions/update.py | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.bin/Scripts/Launch.cmd b/.bin/Scripts/Launch.cmd index 3a3ed6a5..18c304f2 100644 --- a/.bin/Scripts/Launch.cmd +++ b/.bin/Scripts/Launch.cmd @@ -163,7 +163,7 @@ rem Prep set "args=-aoa -bso0 -bse0 -bsp0 -p%ARCHIVE_PASSWORD%" set "config=%L_ITEM%" set "dest=%client_dir%\Office\ODT" -set "odt_exe=%L_PATH%\setup.exe" +set "odt_exe=setup.exe" set "source=%cbin%\_Office.7z" rem Extract diff --git a/.bin/Scripts/functions/update.py b/.bin/Scripts/functions/update.py index c703bf71..07fe6e8f 100644 --- a/.bin/Scripts/functions/update.py +++ b/.bin/Scripts/functions/update.py @@ -626,21 +626,21 @@ def update_office(): shutil.copytree(include_path, dest) # Download and extract - _odt = 'odt.exe' - _out_path = r'{}\odt' + _out_path = r'{}\odt'.format(global_vars['TmpDir']) download_to_temp('odt.exe', SOURCE_URLS['Office Deployment Tool']) cmd = [ - odt, - r'/extract:{}\odt'.format(global_vars['TmpDir']), + r'{}\odt.exe'.format(global_vars['TmpDir']), + r'/extract:{}\odt'.format(_out_path), '/quiet', ] run_program(cmd) shutil.move( - _out_path, + r'{}\setup.exe'.format(_out_path), r'{}\_Office'.format(global_vars['CBinDir'])) # Cleanup - remove_from_temp(odt.exe) + remove_from_temp('odt') + remove_from_temp('odt.exe') def update_classic_start_skin(): From fd8358a8995df02e449f2b702cf296fca18cb4b8 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 11 Jan 2019 14:17:41 -0700 Subject: [PATCH 255/265] Fix ODT path --- .bin/Scripts/functions/update.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bin/Scripts/functions/update.py b/.bin/Scripts/functions/update.py index 07fe6e8f..adb26c6d 100644 --- a/.bin/Scripts/functions/update.py +++ b/.bin/Scripts/functions/update.py @@ -630,7 +630,7 @@ def update_office(): download_to_temp('odt.exe', SOURCE_URLS['Office Deployment Tool']) cmd = [ r'{}\odt.exe'.format(global_vars['TmpDir']), - r'/extract:{}\odt'.format(_out_path), + r'/extract:{}'.format(_out_path), '/quiet', ] run_program(cmd) From 6c47650c2dc1eb97c1e46d36b7295af1cd82fb9e Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 11 Jan 2019 14:18:01 -0700 Subject: [PATCH 256/265] Updated IOBit Uninstaller --- .bin/Scripts/settings/sources.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bin/Scripts/settings/sources.py b/.bin/Scripts/settings/sources.py index 236ba1a8..2dbd8a91 100644 --- a/.bin/Scripts/settings/sources.py +++ b/.bin/Scripts/settings/sources.py @@ -21,7 +21,7 @@ SOURCE_URLS = { 'HitmanPro64': 'https://dl.surfright.nl/HitmanPro_x64.exe', 'HWiNFO': 'https://www.fosshub.com/HWiNFO.html?dwl=hwi_600.zip', 'Intel SSD Toolbox': r'https://downloadmirror.intel.com/28447/eng/Intel%20SSD%20Toolbox%20-%20v3.5.8.exe', - 'IOBit_Uninstaller': 'https://portableapps.duckduckgo.com/IObitUninstallerPortable_7.5.0.7.paf.exe', + 'IOBit_Uninstaller': r'https://portableapps.com/redirect/?a=IObitUninstallerPortable&s=s&d=pa&f=IObitUninstallerPortable_7.5.0.7.paf.exe', 'KVRT': 'http://devbuilds.kaspersky-labs.com/devbuilds/KVRT/latest/full/KVRT.exe', 'Macs Fan Control': 'https://www.crystalidea.com/downloads/macsfancontrol_setup.exe', 'NirCmd32': 'https://www.nirsoft.net/utils/nircmd.zip', From bece9837b245580b8da7988737098c41be87679a Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 11 Jan 2019 14:42:18 -0700 Subject: [PATCH 257/265] Moved Office 2019 installers to their own folder --- .bin/Scripts/settings/launchers.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/.bin/Scripts/settings/launchers.py b/.bin/Scripts/settings/launchers.py index 73dc14d1..2e88f058 100644 --- a/.bin/Scripts/settings/launchers.py +++ b/.bin/Scripts/settings/launchers.py @@ -357,61 +357,63 @@ LAUNCHERS = { }, }, r'Installers\Extras\Office\2016': { - 'Home and Business 2016 (x32)': { + 'Home and Business (x32)': { 'L_TYPE': 'Office', 'L_PATH': '2016', 'L_ITEM': '2016_hb_32.xml', 'L_NCMD': 'True', }, - 'Home and Business 2016 (x64)': { + 'Home and Business (x64)': { 'L_TYPE': 'Office', 'L_PATH': '2016', 'L_ITEM': '2016_hb_64.xml', 'L_NCMD': 'True', }, - 'Home and Student 2016 (x32)': { + 'Home and Student (x32)': { 'L_TYPE': 'Office', 'L_PATH': '2016', 'L_ITEM': '2016_hs_32.xml', 'L_NCMD': 'True', }, - 'Home and Student 2016 (x64)': { + 'Home and Student (x64)': { 'L_TYPE': 'Office', 'L_PATH': '2016', 'L_ITEM': '2016_hs_64.xml', 'L_NCMD': 'True', }, - 'Home and Business 2019 (x32)': { + }, + r'Installers\Extras\Office\2019': { + 'Home and Business (x32)': { 'L_TYPE': 'Office', 'L_PATH': '2019', 'L_ITEM': '2019_hb_32.xml', 'L_NCMD': 'True', }, - 'Home and Business 2019 (x64)': { + 'Home and Business (x64)': { 'L_TYPE': 'Office', 'L_PATH': '2019', 'L_ITEM': '2019_hb_64.xml', 'L_NCMD': 'True', }, - 'Home and Student 2019 (x32)': { + 'Home and Student (x32)': { 'L_TYPE': 'Office', 'L_PATH': '2019', 'L_ITEM': '2019_hs_32.xml', 'L_NCMD': 'True', }, - 'Home and Student 2019 (x64)': { + 'Home and Student (x64)': { 'L_TYPE': 'Office', 'L_PATH': '2019', 'L_ITEM': '2019_hs_64.xml', 'L_NCMD': 'True', }, - 'Office 365 2019 (x32)': { + 'Office 365 (x32)': { 'L_TYPE': 'Office', 'L_PATH': '2019', 'L_ITEM': '365_32.xml', 'L_NCMD': 'True', }, - 'Office 365 2019 (x64)': { + 'Office 365 (x64)': { 'L_TYPE': 'Office', 'L_PATH': '2019', 'L_ITEM': '365_64.xml', From eec4d01ddfc91b49b16d7914264acdf953a1656f Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 11 Jan 2019 14:56:02 -0700 Subject: [PATCH 258/265] Added more SSH keys --- .linux_items/authorized_keys | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.linux_items/authorized_keys b/.linux_items/authorized_keys index e8b34ed3..2f293acb 100644 --- a/.linux_items/authorized_keys +++ b/.linux_items/authorized_keys @@ -1,6 +1,7 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDY12S71BKYLYkVG+D5kXl+Ce76t5Taw35yifV/nYfzYpWEUgEpASsLOfmBIo/rRX6DfESuA1KEqlto0MEdF47WAISIYDGak9U6HTGrpLdGiOa7iLuZL3lDoJW5SR5RmvMGCmukyxnB3H7qAzzMAhJJAM0NkDwfHVDCVwIAcEdgsyFK+d1j2BjbYWKKAXunsJjdigrCPYfrdJnXU6wn9d8DqdPYjpIEay76amhCNiYgBbtFIrKfRNNDfXdDEP2o1APbgq46RswSlTmZ4kStvGhI+gKBfHiWEUIvW8bOCm3PYzvBKWRkLetvzSN7/8M+o8gJ7G41PPISd+mbrp55bGRpwjVGS2qlut6gvDsEJmGOi1XQxMDNqf5N7oCJcMGOwkeaSIR+vQSsRULEz3AWfcMxjGXHoxAfU2Tt3hCCRhsHKxkTV5rmjdIqFeh2pA2aEfEDgfFdHWrNnoccYeiTyhj+62wB83iBUNd7DZ2O5+jUGWyN/yxy7GX/VNsfMJlmEWnjyWX9fLgIJzSzqrLDisskxCWbMh9o7SmLo9zeWRUGs5PVa1QrP9dUGenm9qXBRmcrK3XfLfpFuQnpLutHZWS4SbOHHPGHbnLF/Psoi07O1JxY+reaLUVYAIedQwVYxS49m/ryc0BoLjkOlgv6kCsPC+Fys4sK+0xHO1PMEEUv8Q== twoshirt@dinraal.2shirt.work +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC7MHLxoozeHOmFpjIGaXi8m0LuHZb4eUjX6x50XUlP81oVHbl4iAqw/N4r4j+Lg+lga7xcTeBMNWsa/tGxYkAfF8TP8M0S8XEMOR04r9iA4V6wQ8nGhv99y24NZMJPfiseNjDEwoPYPP5+zpCNfvxeMXxz3EhLFwzSp1dz+f1tBcDd8OtxDAGPn1cIM4Ms9gmIv3/HxOinW4IHxEbsZUWtKGPumsuIYwObfBYZPK0WtK23LPYqtReLYbzQmsf5SPpJAx20mwtZm8Y+LBXAKuxWEKzlF4l/ubqjTfMff5t+8FPEyCgRwm8VcMqxA1b04Pkcuq08AuooJuLKHOJ+aSyDWGXrSf3RlUAx8GafYOpZrcMEhQ0Q1a0XqZNTUXrf13qVPBqnKV8asOXrYIP56Z3zp8qoHasT8t5PbYrwvtV7weW/X61cQf/nn1B/BJbJr/rrOOxdqRCsH44OlElrhjwHsuzQbMc4U4wwoazlMmfNKsKUaoBmLPDTfmMBwnCuBrngNY9JsSB778fqwxsyLSfDTcIDW2kGuQ4P/4u5cKNw/q8Zo15Ghw2327kyTK9e4EGPCpBk+s5832FWS0uJLV269R5aZ5dYzYU13djfVOw2ypZTdr55nTlIH/31iSmJS0PBKyRLa2a7YxErt37W3f2U1eUt+j91LeaP5cMKHkWAsw== twoshirt@naydra.2shirt.work ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC593iDKb9EPKHs98Zr+w0+JJZUgQ6fk4EFLQ2dB6Tro26a3tGeNQhgFuic1M04J/W/dHb+tHONHil8abmIfUEw34if/iQdhZDAkSTda6j+8oVrKXKGYRqtt15kAXZ7JxuLmvcrHwyzVfo/YHEpliYVaSU4dp8LJxJPjwiZ3/9SLcphmHqzkiDsGk1J8D2z0rFyPXv0w1sXWSX2JJ/p+viwy0lX9Yj+e1e2ulay0nICbVCoqLDDmzOZBY3SPNAq8pflz9QkXE1jhN3DCjzTox/6O0w1OSHehaRGfU4ob0Uz1kS+TMFB2/xvsvvDl9BLi8UVRZej1anJLb9KhTf3x0VtdavN1T086xCNndQ204HW785upjF9LHSqdFQF7i+tN/Ui56aBJ3v+ONYvfKSylMYaRGIvhyhFGTpMRpwfWJh2LCUGnpEHRbO9Z2f2QpPB7ko2tm0wnjK/9xat1JKM2Q/NeAGfDDTbPm7OGnG1NKBxbNXQpdqTh95d8aRbcXi1jFKlJki1bqKE6UlfiXBvhu+ORtXB3oVPBCQxLPdUvnB44Lfr5j8J+0y/PNTOhz+RlXmLeDHbXtNXhBmm6Jq9x7JwaVC6GFqbfhElerhrCMxK4DZiS0xxPZtnOez4MIPkUfKo7K1gYeFUpV/sn2q1P3jLAEeVKsOGc/aME6xIE11FHw== twoshirt@paya ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDaJkYcxi7eSpRE7i0n2N2q4CHebPqxYc5eLQ2mDbrLpAIRUSdVjqe8RiVLJ5LKejkGMnWbaiDZ59cLWJhDTfqZFCRexVQkA9v8MVHUWINzxqfJFOnz7dKXP0PmggDbuKMIUkY65KtOLC2Cnqs3epmysQxrSf33W3IqPwL2XjJQXRbFLd4UG1bSZtBAAF3C/i7hBzb2iQPIpr1v1rCrW6gVhrgyoN7ZTfMqcKHnTPsUn95Qtyp6NUYKh4ctrPmTcTHFfwmgQiAYQ6jMcH8bNBf1XDmJuEIwaILYVzzrWOXlx84rqaEUdeRbvd4S/G9FcRt9eO3o+jD4hupdyvIDCttP3ct6yeWQVotreZE/5OVwfxr0BNXPBmTiyF2c6cRrMlXpQMoRQyjnD5Eua0VEUJzj2ows5APGmciJudDw4rXoRLOZRX/nDuXqgNJJ6q+MgRx3hor/etbV2mXcmSMdoI8DuybFzHuEb9GRwYhLxzDdDe+zmevx0rl01W8EJImqgrTwMblADbM4VHpC974d5w2s9uoXJg1NY4UVkSjJdK0De0kyGh8hK2pqTqCBh1OznB43Yla5PwM+05JIMySVRuivvZ1+tBh8ZURzIbFFIrdgNiZIooI4hA/m8qz4CTWIxKWstXR08eOufIbjV+R6VJjEssvLmgYw93rUJ4WbQNbaiw== twoshirt@anaconda.1201.com -ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAgEAlnTlZGWMLjyJ2iBwc62m3+ZgfsXMCaCiQox+lbbKDzYwTdr2a0UU4293z4DHEbG/wgBXl1FB17ac/XGfLeJIBjLhQy7FRgbQ/z8PNttyNDvrb48ld2zq5C0ZhTxEn2v63mPzxsyEKVKd+YgaUrSvJHtw+3HgJpXruc5zcKCZf9BNjPW1Bq4lCt5gDc95DTWFsuLIfc0Kk1KntqMNgyuprp7zPIrolTR4FvPCoZyvcp5mXhM+Q1SNVs+XgvGKVW1fZrwvUoRrriqctnfFKPXIo9ChgRfvhbmsOx1MirShNHP7/5qbG1C3Ju0eEEiV8YLndvkLgprkyG8RYJG6CnXBjI3no7bxhHPfRnAcflPEaGpuvGnDzE5V8K8mhVk+kFI13nPQcuuvJajX2hAiz4xaJD5JUsAv64Gpj6J6cc1/8rOT1wlWzA0r3QYjD6A5dheMwAzdIO1p4TGO2XlUkvM/Hs4LOHG1BodsCpDr5GIEnKawms+9CLV4VeBhnik6W45ZkY1dqp/Qhfjju2pWXYyisrsinUHB2TPuTTQHxjEjqlJQJ8i6wjiB4p0ruyIups24kXXENiwCRjCqhm5WRXdr5h79uzYZMUJCejY9Dn9o953410XjzwFLY4Q6w5FjQb+MjoKACUnYaHPCpK2qxzQN9CR2GUPqDi3dRKMw8TgblV0= Ryokou\2Shirt ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAgEAhF5u/wn04dSDI1mg6HlbDhmM3orJtu2kZdOTBd+/kvCxdC4h+AuwRSWjbIhGi9s8R3iq64gC6TJ2dX4skJ5fMeYqHMZieGgfXderRiPgMURCDWONLZCWyowBun5qGaXkYQo5VbLUNGXua9+RMXaxoJSCOhxq/6CzdleD6pkNNgL5a1ZarD3wLCNRsS50OmyGytXsYTClAY+F9lTd4VXjKuZpjqGfhA5Xz09Rad3Me2Tsd07cdO3LxDNlr969Q/hEwfZ/g+ePaIO0Z/zFHIO4J6Mnt8POTU1fM99tgqUQHWZRP2A+9OYx7nApdA4IFWVUhNfsVkrgcgYdCLD8U16Cdfwm1i1RiBhlYBfzA+EDjD6cbegaaMCKhsCZMZKQB4LyJTDgjvCrk1Q7dE0Nc1Nq8qD/BMbZkIKQcQH8xrX1hONayUMdOPnpDpi6IP2NIYFTbdJD70JQ8ru+gIDRQJR6g0AwnjMoJYNRKgAtWlcbKQ8YQW/FNREtyUhh8tquCyFbofGUiJxmTbWki7u7VJxRLNSnp+NQhPNT4FUbWy1vPrJi0l3MxuXdG3nZ0Brnggn72tnGcAUOmRTPubNlkhFStqcCM+tAVTHeLwHobdMewKQMWGPt6UXLtEJINqW9nCh1SAOA3cjsZ3ugXLRQQc82rEgTfTp2RtuN+NSf/vgoDbk= 1201 PuTTY Key ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDGZqPA7/T3zw8YipngM6vKpxX+IMpwqm2jad+NcJWxC0Hh09oVUalgbO/eWRloQlNgxHTosdIkSp++xnyeEHI3vL0pbko/c0OJbs6vEsHp8ljzt61HKKsscVADCI/ogGwHkPIHENgbiXkBPutEBLYFPtMcJQw6GBIkagW+dTyqEw/8c1cDmTq7AM74tHqgrpYjJy35Nne0K+zGIeqzTJdtg3fkRCN9JH24c3VbYoeIpMlgfxxgRG44DC/o0BRoMr3wWiS/sTrutlluB03vaQWe+4o8p789wq+fDqKhBTisH96RQ1Y1D5eZcf0DngBJtnCLWPG+z6YP0DFW5DYeQRoYNneRkR10RUqN0Eufok/UMNnxWcW+TztTxO5JSucXt0MYpLsWO1U7B22MR1W7oVlbznUrVENSQGRqyOS4PdqmI4faF0vEKis68S7NaXg88zwBr612HwFBianXvvxhkyEKv8ECbeXSvHcIajepdzbGLwaussDQiNv8vyX/8o3K7Si/ktdgIK4UzfaMq7G0vX1KEvuKAfMPYn4z0zuc/ahxTTfvHqfO+cnYgH8Pnzi1DGziRveeKIFT4OKOP5C3wHntsfv1CStK/LXhH3j4PNRuet0Fm5+jUJ22DQqlXtFiwFz4E+Bt+67exhm4Out4rAUqCzjDW5+mw0WU2P7u01cT+Q== admin@anaconda.1201.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCatoW5AZa8JlvA7WZD3GkB3IMXtCClxGEtpeEb2q/6Ltd8+/EngGgfjm2buBdHsRY4y+8Q/dZnMXbD1kfSw8pv7q4WUy2RHccM6xNpkhhioRzLebWc3m8C3ySFx0uTipZCgAG0IBGINeHHl3zeWo5M21WSPNAjZsUUX24z1TszXP/nkDMh24593OGbyqDydXIz6xWPtZOo0Ot8Y4yplXipO6yJUjGianSJ1DVQCwFj5G2XgDdqHJDTsKXcHDAVZU4WyB7br6ONZLj8How4FX15o68Zu/9m5EVuoR1vf7iBZev6sE9/1rub5IIW7f3ADXf+z4N2cuhOJSwoKxxf669U2Fm3ZegQdn3+P5yONuPzI2w3f5FZtyQE22NBLMzqRv+9WZxILPq4ocGojMck9rbvYXEaDYTOYBbjWjVZK9qhCFilUwSzv9mtBN6/3thHumCod7PVuVcldd2BJutIEwJ+lRqTKsuHkj9ybSo+kh3ycDtZhpERLNE5EAaJEnXTGraSz8MgKaI9FsCDFVwdJDKz897vgjd8WyFgGSEKI8pmqZcpGK4243yCZ5Xuqe73i18sPZrQtg6nfyYR0GksH7qBW9zbmgw4D0Zmctxvg8imsMrfHGIhipHS8OozEuabbxAqgCIWzjcVSMWAnontu7DcLOzQ3GW+mFVd/aItXsnfQw== admin@management-1 From 5b9e91f8affc99ecf749b10fa0ecd3871f256593 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sun, 13 Jan 2019 14:51:53 -0700 Subject: [PATCH 259/265] Updated Killer Network drivers source --- .bin/Scripts/build_pe.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bin/Scripts/build_pe.ps1 b/.bin/Scripts/build_pe.ps1 index a2dd0363..00405a12 100644 --- a/.bin/Scripts/build_pe.ps1 +++ b/.bin/Scripts/build_pe.ps1 @@ -145,7 +145,7 @@ if ($MyInvocation.InvocationName -ne ".") { # Killer Network Drivers @( "killerinf.zip", - ("http://www.killernetworking.com"+(FindDynamicUrl "http://www.killernetworking.com/driver-downloads/item/killer-drivers-inf" "Download Killer-Ethernet").replace('&', '&')) + ("https://www.killernetworking.com"+(FindDynamicUrl "https://www.killernetworking.com/killersupport/category/other-downloads" "Download Killer-Ethernet").replace('&', '&')) ), # Notepad++ @("npp_x86.7z", "https://notepad-plus-plus.org/repository/7.x/7.6.2/npp.7.6.2.bin.minimalist.7z"), From fcd8d67f51c5e4c31eb5f2ace45037e4010b4800 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sun, 13 Jan 2019 14:52:31 -0700 Subject: [PATCH 260/265] Bumped year in LICENSE.txt --- LICENSE.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index d02f5a6e..f29c29e6 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,7 +1,7 @@ -Copyright (c) 2018 Alan Mason +Copyright (c) 2019 Alan Mason Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. From 07a92d2a8e3f3cdacb449e07d078efbea8bb674d Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sun, 13 Jan 2019 17:15:17 -0700 Subject: [PATCH 261/265] Downgraded to HDC5 --- .../include/EFI/boot/icons/1201_hdclone.png | Bin 3133 -> 26624 bytes .linux_items/include/EFI/boot/refind.conf | 2 +- .../include/syslinux/1201_hdclone.cfg | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.linux_items/include/EFI/boot/icons/1201_hdclone.png b/.linux_items/include/EFI/boot/icons/1201_hdclone.png index 997ffe5d3a0f49527d69546de5312e4cc63ac2f4..3c4a5f35cd545e0e93ca6f24a19b8455ddd018a7 100644 GIT binary patch literal 26624 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 Date: Sun, 13 Jan 2019 17:21:24 -0700 Subject: [PATCH 262/265] Enable Windows Updates during checklist --- .bin/Scripts/system_checklist.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.bin/Scripts/system_checklist.py b/.bin/Scripts/system_checklist.py index cbcde87e..41be9d27 100644 --- a/.bin/Scripts/system_checklist.py +++ b/.bin/Scripts/system_checklist.py @@ -54,6 +54,8 @@ if __name__ == '__main__': function=enable_system_restore, cs='Done') try_and_print(message='Create System Restore point...', function=create_system_restore_point, cs='Done') + try_and_print(message='Enabling Windows Updates...', + function=enable_windows_updates, cs='Done') try_and_print(message='Updating Clock...', function=update_clock, cs='Done') From a8536bf0d550dc9bdef54483c19206ac3b7a6b47 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sun, 13 Jan 2019 17:22:24 -0700 Subject: [PATCH 263/265] Forgot to include functions/windows_updates.py --- .bin/Scripts/system_checklist.py | 1 + 1 file changed, 1 insertion(+) diff --git a/.bin/Scripts/system_checklist.py b/.bin/Scripts/system_checklist.py index 41be9d27..7474a07c 100644 --- a/.bin/Scripts/system_checklist.py +++ b/.bin/Scripts/system_checklist.py @@ -11,6 +11,7 @@ from functions.info import * from functions.product_keys import * from functions.setup import * from functions.sw_diags import * +from functions.windows_updates import * init_global_vars() os.system('title {}: System Checklist Tool'.format(KIT_NAME_FULL)) set_log_file('System Checklist.log') From 814ada0ac044750dec3f414abfc2f68de22d1f31 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sun, 13 Jan 2019 17:59:06 -0700 Subject: [PATCH 264/265] Updated HWiNFO url --- .bin/Scripts/settings/sources.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bin/Scripts/settings/sources.py b/.bin/Scripts/settings/sources.py index 2dbd8a91..8a35895e 100644 --- a/.bin/Scripts/settings/sources.py +++ b/.bin/Scripts/settings/sources.py @@ -19,7 +19,7 @@ SOURCE_URLS = { 'Firefox uBO': 'https://addons.mozilla.org/firefox/downloads/file/1166954/ublock_origin-1.17.4-an+fx.xpi', 'HitmanPro32': 'https://dl.surfright.nl/HitmanPro.exe', 'HitmanPro64': 'https://dl.surfright.nl/HitmanPro_x64.exe', - 'HWiNFO': 'https://www.fosshub.com/HWiNFO.html?dwl=hwi_600.zip', + 'HWiNFO': 'http://files2.majorgeeks.com/caae8849cf31a8d77c51283b720e60e49ce1dc78/systeminfo/hwi_600.zip', 'Intel SSD Toolbox': r'https://downloadmirror.intel.com/28447/eng/Intel%20SSD%20Toolbox%20-%20v3.5.8.exe', 'IOBit_Uninstaller': r'https://portableapps.com/redirect/?a=IObitUninstallerPortable&s=s&d=pa&f=IObitUninstallerPortable_7.5.0.7.paf.exe', 'KVRT': 'http://devbuilds.kaspersky-labs.com/devbuilds/KVRT/latest/full/KVRT.exe', From a47579ab79dcc29f207e2cba9bc64102dd3174f5 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 14 Jan 2019 13:18:01 -0700 Subject: [PATCH 265/265] Disabled Ninite in d7II per request --- .bin/Scripts/install_sw_bundle.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.bin/Scripts/install_sw_bundle.py b/.bin/Scripts/install_sw_bundle.py index e544dde4..9b51c432 100644 --- a/.bin/Scripts/install_sw_bundle.py +++ b/.bin/Scripts/install_sw_bundle.py @@ -27,13 +27,14 @@ if __name__ == '__main__': }} answer_extensions = D7_MODE or ask('Install Extensions?') answer_vcr = D7_MODE or ask('Install Visual C++ Runtimes?') - answer_ninite = D7_MODE or ask('Install Ninite Bundle?') - if not D7_MODE and ( - answer_ninite and global_vars['OS']['Version'] in ['7']): - # Vista is dead, not going to check for it - answer_mse = ask('Install MSE?') - else: + if D7_MODE: + answer_ninite = False answer_mse = False + else: + answer_ninite = ask('Install Ninite Bundle?') + if answer_ninite and global_vars['OS']['Version'] in ['7']: + # Vista is dead, not going to check for it + answer_mse = ask('Install MSE?') print_info('Installing Programs') if answer_vcr: