diff --git a/.bin/Scripts/activate.py b/.bin/Scripts/activate.py index 3c25b512..5d17ae2f 100644 --- a/.bin/Scripts/activate.py +++ b/.bin/Scripts/activate.py @@ -1,62 +1,62 @@ -# Wizard Kit: Activate Windows using various methods - -import os -import sys - -# Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) -from functions.activation import * -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.', - }} - - # Determine activation method - activation_methods = [ - {'Name': 'Activate with BIOS key', 'Function': activate_with_bios}, - ] - if global_vars['OS']['Version'] not in ['8', '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) - - 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...") - exit_script() - except SystemExit: - pass - except: - major_exception() +# Wizard Kit: Activate Windows using various methods + +import os +import sys + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +sys.path.append(os.getcwd()) +from functions.activation import * +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.', + }} + + # Determine activation method + activation_methods = [ + {'Name': 'Activate with BIOS key', 'Function': activate_with_bios}, + ] + if global_vars['OS']['Version'] not in ['8', '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) + + 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...") + exit_script() + except SystemExit: + pass + except: + major_exception() diff --git a/.bin/Scripts/apple-fans b/.bin/Scripts/apple-fans new file mode 100755 index 00000000..de8e56e6 --- /dev/null +++ b/.bin/Scripts/apple-fans @@ -0,0 +1,37 @@ +#!/bin/bash +# +## Wizard Kit: Apple fan speed tool + +SMCPATH="/sys/devices/platform/applesmc.768" +SET_MAX="True" + +function usage { + echo "Usage: $(basename "$0") auto|max" + echo " e.g. $(basename "$0") max" +} + +# Set mode +case $1 in + auto) + SET_MAX="False";; + max) + SET_MAX="True";; + *) + usage + exit 1;; +esac + +if [[ -e "$SMCPATH" ]]; then + if [[ "$SET_MAX" == "True" ]]; then + # Set fans to max RPM + for fan in $SMCPATH/fan*max; do + echo '1' | sudo tee ${fan:0:-4}_manual > /dev/null + cat $fan | sudo tee ${fan:0:-4}_output > /dev/null + done + else + # Set fans to auto + for fan in $SMCPATH/fan*manual; do + echo '0' | sudo tee $fan > /dev/null + done + fi +fi diff --git a/.bin/Scripts/borrowed/acpi.py b/.bin/Scripts/borrowed/acpi.py index 5b8e4dac..bb109caf 100644 --- a/.bin/Scripts/borrowed/acpi.py +++ b/.bin/Scripts/borrowed/acpi.py @@ -1,57 +1,57 @@ -import sys - -# Code borrowed from https://github.com/aeruder/get_win8key - -if sys.platform.startswith('win32'): - import ctypes - import ctypes.wintypes - - def EnumAcpiTables(): - #returns a list of the names of the ACPI tables on this system - FirmwareTableProviderSignature=ctypes.wintypes.DWORD(1094930505) - pFirmwareTableBuffer=ctypes.create_string_buffer(0) - BufferSize=ctypes.wintypes.DWORD(0) - #http://msdn.microsoft.com/en-us/library/windows/desktop/ms724259 - EnumSystemFirmwareTables=ctypes.WinDLL("Kernel32").EnumSystemFirmwareTables - ret=EnumSystemFirmwareTables(FirmwareTableProviderSignature, pFirmwareTableBuffer, BufferSize) - pFirmwareTableBuffer=None - pFirmwareTableBuffer=ctypes.create_string_buffer(ret) - BufferSize.value=ret - ret2=EnumSystemFirmwareTables(FirmwareTableProviderSignature, pFirmwareTableBuffer, BufferSize) - return [pFirmwareTableBuffer.value[i:i+4] for i in range(0, len(pFirmwareTableBuffer.value), 4)] - - def GetAcpiTable(table): - #returns raw contents of ACPI table - #http://msdn.microsoft.com/en-us/library/windows/desktop/ms724379x - tableID = 0 - for b in reversed(table): - tableID = (tableID << 8) + b - GetSystemFirmwareTable=ctypes.WinDLL("Kernel32").GetSystemFirmwareTable - FirmwareTableProviderSignature=ctypes.wintypes.DWORD(1094930505) - FirmwareTableID=ctypes.wintypes.DWORD(int(tableID)) - pFirmwareTableBuffer=ctypes.create_string_buffer(0) - BufferSize=ctypes.wintypes.DWORD(0) - ret = GetSystemFirmwareTable(FirmwareTableProviderSignature, FirmwareTableID, pFirmwareTableBuffer, BufferSize) - pFirmwareTableBuffer=None - pFirmwareTableBuffer=ctypes.create_string_buffer(ret) - BufferSize.value=ret - ret2 = GetSystemFirmwareTable(FirmwareTableProviderSignature, FirmwareTableID, pFirmwareTableBuffer, BufferSize) - return pFirmwareTableBuffer.raw -elif sys.platform.startswith('linux'): - import os - TABLE_ROOT = b'/sys/firmware/acpi/tables' - def EnumAcpiTables(): - return os.listdir(TABLE_ROOT) - def GetAcpiTable(table): - with open(os.path.join(TABLE_ROOT, table), 'rb') as o: - return o.read() -else: - raise NotImplementedError('acpi support only implemented for linux and win32') - -def FindAcpiTable(table): -#checks if specific ACPI table exists and returns True/False - tables = EnumAcpiTables() - if table in tables: - return True - else: - return False +import sys + +# Code borrowed from https://github.com/aeruder/get_win8key + +if sys.platform.startswith('win32'): + import ctypes + import ctypes.wintypes + + def EnumAcpiTables(): + #returns a list of the names of the ACPI tables on this system + FirmwareTableProviderSignature=ctypes.wintypes.DWORD(1094930505) + pFirmwareTableBuffer=ctypes.create_string_buffer(0) + BufferSize=ctypes.wintypes.DWORD(0) + #http://msdn.microsoft.com/en-us/library/windows/desktop/ms724259 + EnumSystemFirmwareTables=ctypes.WinDLL("Kernel32").EnumSystemFirmwareTables + ret=EnumSystemFirmwareTables(FirmwareTableProviderSignature, pFirmwareTableBuffer, BufferSize) + pFirmwareTableBuffer=None + pFirmwareTableBuffer=ctypes.create_string_buffer(ret) + BufferSize.value=ret + ret2=EnumSystemFirmwareTables(FirmwareTableProviderSignature, pFirmwareTableBuffer, BufferSize) + return [pFirmwareTableBuffer.value[i:i+4] for i in range(0, len(pFirmwareTableBuffer.value), 4)] + + def GetAcpiTable(table): + #returns raw contents of ACPI table + #http://msdn.microsoft.com/en-us/library/windows/desktop/ms724379x + tableID = 0 + for b in reversed(table): + tableID = (tableID << 8) + b + GetSystemFirmwareTable=ctypes.WinDLL("Kernel32").GetSystemFirmwareTable + FirmwareTableProviderSignature=ctypes.wintypes.DWORD(1094930505) + FirmwareTableID=ctypes.wintypes.DWORD(int(tableID)) + pFirmwareTableBuffer=ctypes.create_string_buffer(0) + BufferSize=ctypes.wintypes.DWORD(0) + ret = GetSystemFirmwareTable(FirmwareTableProviderSignature, FirmwareTableID, pFirmwareTableBuffer, BufferSize) + pFirmwareTableBuffer=None + pFirmwareTableBuffer=ctypes.create_string_buffer(ret) + BufferSize.value=ret + ret2 = GetSystemFirmwareTable(FirmwareTableProviderSignature, FirmwareTableID, pFirmwareTableBuffer, BufferSize) + return pFirmwareTableBuffer.raw +elif sys.platform.startswith('linux'): + import os + TABLE_ROOT = b'/sys/firmware/acpi/tables' + def EnumAcpiTables(): + return os.listdir(TABLE_ROOT) + def GetAcpiTable(table): + with open(os.path.join(TABLE_ROOT, table), 'rb') as o: + return o.read() +else: + raise NotImplementedError('acpi support only implemented for linux and win32') + +def FindAcpiTable(table): +#checks if specific ACPI table exists and returns True/False + tables = EnumAcpiTables() + if table in tables: + return True + else: + return False diff --git a/.bin/Scripts/borrowed/knownpaths-LICENSE.txt b/.bin/Scripts/borrowed/knownpaths-LICENSE.txt index d4b2f60c..19673bd6 100644 --- a/.bin/Scripts/borrowed/knownpaths-LICENSE.txt +++ b/.bin/Scripts/borrowed/knownpaths-LICENSE.txt @@ -1,21 +1,21 @@ -The MIT License (MIT) - -Copyright (c) 2014 Michael Kropat - -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. +The MIT License (MIT) + +Copyright (c) 2014 Michael Kropat + +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. diff --git a/.bin/Scripts/borrowed/knownpaths.py b/.bin/Scripts/borrowed/knownpaths.py index 53be87f9..96b1a009 100644 --- a/.bin/Scripts/borrowed/knownpaths.py +++ b/.bin/Scripts/borrowed/knownpaths.py @@ -1,164 +1,164 @@ -import ctypes, sys -from ctypes import windll, wintypes -from uuid import UUID - -class GUID(ctypes.Structure): # [1] - _fields_ = [ - ("Data1", wintypes.DWORD), - ("Data2", wintypes.WORD), - ("Data3", wintypes.WORD), - ("Data4", wintypes.BYTE * 8) - ] - - def __init__(self, uuid_): - ctypes.Structure.__init__(self) - self.Data1, self.Data2, self.Data3, self.Data4[0], self.Data4[1], rest = uuid_.fields - for i in range(2, 8): - self.Data4[i] = rest>>(8 - i - 1)*8 & 0xff - -class FOLDERID: # [2] - AccountPictures = UUID('{008ca0b1-55b4-4c56-b8a8-4de4b299d3be}') - AdminTools = UUID('{724EF170-A42D-4FEF-9F26-B60E846FBA4F}') - ApplicationShortcuts = UUID('{A3918781-E5F2-4890-B3D9-A7E54332328C}') - CameraRoll = UUID('{AB5FB87B-7CE2-4F83-915D-550846C9537B}') - CDBurning = UUID('{9E52AB10-F80D-49DF-ACB8-4330F5687855}') - CommonAdminTools = UUID('{D0384E7D-BAC3-4797-8F14-CBA229B392B5}') - CommonOEMLinks = UUID('{C1BAE2D0-10DF-4334-BEDD-7AA20B227A9D}') - CommonPrograms = UUID('{0139D44E-6AFE-49F2-8690-3DAFCAE6FFB8}') - CommonStartMenu = UUID('{A4115719-D62E-491D-AA7C-E74B8BE3B067}') - CommonStartup = UUID('{82A5EA35-D9CD-47C5-9629-E15D2F714E6E}') - CommonTemplates = UUID('{B94237E7-57AC-4347-9151-B08C6C32D1F7}') - Contacts = UUID('{56784854-C6CB-462b-8169-88E350ACB882}') - Cookies = UUID('{2B0F765D-C0E9-4171-908E-08A611B84FF6}') - Desktop = UUID('{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}') - DeviceMetadataStore = UUID('{5CE4A5E9-E4EB-479D-B89F-130C02886155}') - Documents = UUID('{FDD39AD0-238F-46AF-ADB4-6C85480369C7}') - DocumentsLibrary = UUID('{7B0DB17D-9CD2-4A93-9733-46CC89022E7C}') - Downloads = UUID('{374DE290-123F-4565-9164-39C4925E467B}') - Favorites = UUID('{1777F761-68AD-4D8A-87BD-30B759FA33DD}') - Fonts = UUID('{FD228CB7-AE11-4AE3-864C-16F3910AB8FE}') - GameTasks = UUID('{054FAE61-4DD8-4787-80B6-090220C4B700}') - History = UUID('{D9DC8A3B-B784-432E-A781-5A1130A75963}') - ImplicitAppShortcuts = UUID('{BCB5256F-79F6-4CEE-B725-DC34E402FD46}') - InternetCache = UUID('{352481E8-33BE-4251-BA85-6007CAEDCF9D}') - Libraries = UUID('{1B3EA5DC-B587-4786-B4EF-BD1DC332AEAE}') - Links = UUID('{bfb9d5e0-c6a9-404c-b2b2-ae6db6af4968}') - LocalAppData = UUID('{F1B32785-6FBA-4FCF-9D55-7B8E7F157091}') - LocalAppDataLow = UUID('{A520A1A4-1780-4FF6-BD18-167343C5AF16}') - LocalizedResourcesDir = UUID('{2A00375E-224C-49DE-B8D1-440DF7EF3DDC}') - Music = UUID('{4BD8D571-6D19-48D3-BE97-422220080E43}') - MusicLibrary = UUID('{2112AB0A-C86A-4FFE-A368-0DE96E47012E}') - NetHood = UUID('{C5ABBF53-E17F-4121-8900-86626FC2C973}') - OriginalImages = UUID('{2C36C0AA-5812-4b87-BFD0-4CD0DFB19B39}') - PhotoAlbums = UUID('{69D2CF90-FC33-4FB7-9A0C-EBB0F0FCB43C}') - PicturesLibrary = UUID('{A990AE9F-A03B-4E80-94BC-9912D7504104}') - Pictures = UUID('{33E28130-4E1E-4676-835A-98395C3BC3BB}') - Playlists = UUID('{DE92C1C7-837F-4F69-A3BB-86E631204A23}') - PrintHood = UUID('{9274BD8D-CFD1-41C3-B35E-B13F55A758F4}') - Profile = UUID('{5E6C858F-0E22-4760-9AFE-EA3317B67173}') - ProgramData = UUID('{62AB5D82-FDC1-4DC3-A9DD-070D1D495D97}') - ProgramFiles = UUID('{905e63b6-c1bf-494e-b29c-65b732d3d21a}') - ProgramFilesX64 = UUID('{6D809377-6AF0-444b-8957-A3773F02200E}') - ProgramFilesX86 = UUID('{7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E}') - ProgramFilesCommon = UUID('{F7F1ED05-9F6D-47A2-AAAE-29D317C6F066}') - ProgramFilesCommonX64 = UUID('{6365D5A7-0F0D-45E5-87F6-0DA56B6A4F7D}') - ProgramFilesCommonX86 = UUID('{DE974D24-D9C6-4D3E-BF91-F4455120B917}') - Programs = UUID('{A77F5D77-2E2B-44C3-A6A2-ABA601054A51}') - Public = UUID('{DFDF76A2-C82A-4D63-906A-5644AC457385}') - PublicDesktop = UUID('{C4AA340D-F20F-4863-AFEF-F87EF2E6BA25}') - PublicDocuments = UUID('{ED4824AF-DCE4-45A8-81E2-FC7965083634}') - PublicDownloads = UUID('{3D644C9B-1FB8-4f30-9B45-F670235F79C0}') - PublicGameTasks = UUID('{DEBF2536-E1A8-4c59-B6A2-414586476AEA}') - PublicLibraries = UUID('{48DAF80B-E6CF-4F4E-B800-0E69D84EE384}') - PublicMusic = UUID('{3214FAB5-9757-4298-BB61-92A9DEAA44FF}') - PublicPictures = UUID('{B6EBFB86-6907-413C-9AF7-4FC2ABF07CC5}') - PublicRingtones = UUID('{E555AB60-153B-4D17-9F04-A5FE99FC15EC}') - PublicUserTiles = UUID('{0482af6c-08f1-4c34-8c90-e17ec98b1e17}') - PublicVideos = UUID('{2400183A-6185-49FB-A2D8-4A392A602BA3}') - QuickLaunch = UUID('{52a4f021-7b75-48a9-9f6b-4b87a210bc8f}') - Recent = UUID('{AE50C081-EBD2-438A-8655-8A092E34987A}') - RecordedTVLibrary = UUID('{1A6FDBA2-F42D-4358-A798-B74D745926C5}') - ResourceDir = UUID('{8AD10C31-2ADB-4296-A8F7-E4701232C972}') - Ringtones = UUID('{C870044B-F49E-4126-A9C3-B52A1FF411E8}') - RoamingAppData = UUID('{3EB685DB-65F9-4CF6-A03A-E3EF65729F3D}') - RoamedTileImages = UUID('{AAA8D5A5-F1D6-4259-BAA8-78E7EF60835E}') - RoamingTiles = UUID('{00BCFC5A-ED94-4e48-96A1-3F6217F21990}') - SampleMusic = UUID('{B250C668-F57D-4EE1-A63C-290EE7D1AA1F}') - SamplePictures = UUID('{C4900540-2379-4C75-844B-64E6FAF8716B}') - SamplePlaylists = UUID('{15CA69B3-30EE-49C1-ACE1-6B5EC372AFB5}') - SampleVideos = UUID('{859EAD94-2E85-48AD-A71A-0969CB56A6CD}') - SavedGames = UUID('{4C5C32FF-BB9D-43b0-B5B4-2D72E54EAAA4}') - SavedSearches = UUID('{7d1d3a04-debb-4115-95cf-2f29da2920da}') - Screenshots = UUID('{b7bede81-df94-4682-a7d8-57a52620b86f}') - SearchHistory = UUID('{0D4C3DB6-03A3-462F-A0E6-08924C41B5D4}') - SearchTemplates = UUID('{7E636BFE-DFA9-4D5E-B456-D7B39851D8A9}') - SendTo = UUID('{8983036C-27C0-404B-8F08-102D10DCFD74}') - SidebarDefaultParts = UUID('{7B396E54-9EC5-4300-BE0A-2482EBAE1A26}') - SidebarParts = UUID('{A75D362E-50FC-4fb7-AC2C-A8BEAA314493}') - SkyDrive = UUID('{A52BBA46-E9E1-435f-B3D9-28DAA648C0F6}') - SkyDriveCameraRoll = UUID('{767E6811-49CB-4273-87C2-20F355E1085B}') - SkyDriveDocuments = UUID('{24D89E24-2F19-4534-9DDE-6A6671FBB8FE}') - SkyDrivePictures = UUID('{339719B5-8C47-4894-94C2-D8F77ADD44A6}') - StartMenu = UUID('{625B53C3-AB48-4EC1-BA1F-A1EF4146FC19}') - Startup = UUID('{B97D20BB-F46A-4C97-BA10-5E3608430854}') - System = UUID('{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}') - SystemX86 = UUID('{D65231B0-B2F1-4857-A4CE-A8E7C6EA7D27}') - Templates = UUID('{A63293E8-664E-48DB-A079-DF759E0509F7}') - UserPinned = UUID('{9E3995AB-1F9C-4F13-B827-48B24B6C7174}') - UserProfiles = UUID('{0762D272-C50A-4BB0-A382-697DCD729B80}') - UserProgramFiles = UUID('{5CD7AEE2-2219-4A67-B85D-6C9CE15660CB}') - UserProgramFilesCommon = UUID('{BCBD3057-CA5C-4622-B42D-BC56DB0AE516}') - Videos = UUID('{18989B1D-99B5-455B-841C-AB7C74E4DDFC}') - VideosLibrary = UUID('{491E922F-5643-4AF4-A7EB-4E7A138D8174}') - Windows = UUID('{F38BF404-1D43-42F2-9305-67DE0B28FC23}') - -class UserHandle: # [3] - current = wintypes.HANDLE(0) - common = wintypes.HANDLE(-1) - -_CoTaskMemFree = windll.ole32.CoTaskMemFree # [4] -_CoTaskMemFree.restype= None -_CoTaskMemFree.argtypes = [ctypes.c_void_p] - -_SHGetKnownFolderPath = windll.shell32.SHGetKnownFolderPath # [5] [3] -_SHGetKnownFolderPath.argtypes = [ - ctypes.POINTER(GUID), wintypes.DWORD, wintypes.HANDLE, ctypes.POINTER(ctypes.c_wchar_p) -] - -class PathNotFoundException(Exception): pass - -def get_path(folderid, user_handle=UserHandle.common): - fid = GUID(folderid) - pPath = ctypes.c_wchar_p() - S_OK = 0 - if _SHGetKnownFolderPath(ctypes.byref(fid), 0, user_handle, ctypes.byref(pPath)) != S_OK: - raise PathNotFoundException() - path = pPath.value - _CoTaskMemFree(pPath) - return path - -if __name__ == '__main__': - if len(sys.argv) < 2 or sys.argv[1] in ['-?', '/?']: - print('python knownpaths.py FOLDERID {current|common}') - sys.exit(0) - - try: - folderid = getattr(FOLDERID, sys.argv[1]) - except AttributeError: - print('Unknown folder id "%s"' % sys.argv[1], file=sys.stderr) - sys.exit(1) - - try: - if len(sys.argv) == 2: - print(get_path(folderid)) - else: - print(get_path(folderid, getattr(UserHandle, sys.argv[2]))) - except PathNotFoundException: - print('Folder not found "%s"' % ' '.join(sys.argv[1:]), file=sys.stderr) - sys.exit(1) - -# [1] http://msdn.microsoft.com/en-us/library/windows/desktop/aa373931.aspx -# [2] http://msdn.microsoft.com/en-us/library/windows/desktop/dd378457.aspx -# [3] http://msdn.microsoft.com/en-us/library/windows/desktop/bb762188.aspx -# [4] http://msdn.microsoft.com/en-us/library/windows/desktop/ms680722.aspx -# [5] http://www.themacaque.com/?p=954 +import ctypes, sys +from ctypes import windll, wintypes +from uuid import UUID + +class GUID(ctypes.Structure): # [1] + _fields_ = [ + ("Data1", wintypes.DWORD), + ("Data2", wintypes.WORD), + ("Data3", wintypes.WORD), + ("Data4", wintypes.BYTE * 8) + ] + + def __init__(self, uuid_): + ctypes.Structure.__init__(self) + self.Data1, self.Data2, self.Data3, self.Data4[0], self.Data4[1], rest = uuid_.fields + for i in range(2, 8): + self.Data4[i] = rest>>(8 - i - 1)*8 & 0xff + +class FOLDERID: # [2] + AccountPictures = UUID('{008ca0b1-55b4-4c56-b8a8-4de4b299d3be}') + AdminTools = UUID('{724EF170-A42D-4FEF-9F26-B60E846FBA4F}') + ApplicationShortcuts = UUID('{A3918781-E5F2-4890-B3D9-A7E54332328C}') + CameraRoll = UUID('{AB5FB87B-7CE2-4F83-915D-550846C9537B}') + CDBurning = UUID('{9E52AB10-F80D-49DF-ACB8-4330F5687855}') + CommonAdminTools = UUID('{D0384E7D-BAC3-4797-8F14-CBA229B392B5}') + CommonOEMLinks = UUID('{C1BAE2D0-10DF-4334-BEDD-7AA20B227A9D}') + CommonPrograms = UUID('{0139D44E-6AFE-49F2-8690-3DAFCAE6FFB8}') + CommonStartMenu = UUID('{A4115719-D62E-491D-AA7C-E74B8BE3B067}') + CommonStartup = UUID('{82A5EA35-D9CD-47C5-9629-E15D2F714E6E}') + CommonTemplates = UUID('{B94237E7-57AC-4347-9151-B08C6C32D1F7}') + Contacts = UUID('{56784854-C6CB-462b-8169-88E350ACB882}') + Cookies = UUID('{2B0F765D-C0E9-4171-908E-08A611B84FF6}') + Desktop = UUID('{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}') + DeviceMetadataStore = UUID('{5CE4A5E9-E4EB-479D-B89F-130C02886155}') + Documents = UUID('{FDD39AD0-238F-46AF-ADB4-6C85480369C7}') + DocumentsLibrary = UUID('{7B0DB17D-9CD2-4A93-9733-46CC89022E7C}') + Downloads = UUID('{374DE290-123F-4565-9164-39C4925E467B}') + Favorites = UUID('{1777F761-68AD-4D8A-87BD-30B759FA33DD}') + Fonts = UUID('{FD228CB7-AE11-4AE3-864C-16F3910AB8FE}') + GameTasks = UUID('{054FAE61-4DD8-4787-80B6-090220C4B700}') + History = UUID('{D9DC8A3B-B784-432E-A781-5A1130A75963}') + ImplicitAppShortcuts = UUID('{BCB5256F-79F6-4CEE-B725-DC34E402FD46}') + InternetCache = UUID('{352481E8-33BE-4251-BA85-6007CAEDCF9D}') + Libraries = UUID('{1B3EA5DC-B587-4786-B4EF-BD1DC332AEAE}') + Links = UUID('{bfb9d5e0-c6a9-404c-b2b2-ae6db6af4968}') + LocalAppData = UUID('{F1B32785-6FBA-4FCF-9D55-7B8E7F157091}') + LocalAppDataLow = UUID('{A520A1A4-1780-4FF6-BD18-167343C5AF16}') + LocalizedResourcesDir = UUID('{2A00375E-224C-49DE-B8D1-440DF7EF3DDC}') + Music = UUID('{4BD8D571-6D19-48D3-BE97-422220080E43}') + MusicLibrary = UUID('{2112AB0A-C86A-4FFE-A368-0DE96E47012E}') + NetHood = UUID('{C5ABBF53-E17F-4121-8900-86626FC2C973}') + OriginalImages = UUID('{2C36C0AA-5812-4b87-BFD0-4CD0DFB19B39}') + PhotoAlbums = UUID('{69D2CF90-FC33-4FB7-9A0C-EBB0F0FCB43C}') + PicturesLibrary = UUID('{A990AE9F-A03B-4E80-94BC-9912D7504104}') + Pictures = UUID('{33E28130-4E1E-4676-835A-98395C3BC3BB}') + Playlists = UUID('{DE92C1C7-837F-4F69-A3BB-86E631204A23}') + PrintHood = UUID('{9274BD8D-CFD1-41C3-B35E-B13F55A758F4}') + Profile = UUID('{5E6C858F-0E22-4760-9AFE-EA3317B67173}') + ProgramData = UUID('{62AB5D82-FDC1-4DC3-A9DD-070D1D495D97}') + ProgramFiles = UUID('{905e63b6-c1bf-494e-b29c-65b732d3d21a}') + ProgramFilesX64 = UUID('{6D809377-6AF0-444b-8957-A3773F02200E}') + ProgramFilesX86 = UUID('{7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E}') + ProgramFilesCommon = UUID('{F7F1ED05-9F6D-47A2-AAAE-29D317C6F066}') + ProgramFilesCommonX64 = UUID('{6365D5A7-0F0D-45E5-87F6-0DA56B6A4F7D}') + ProgramFilesCommonX86 = UUID('{DE974D24-D9C6-4D3E-BF91-F4455120B917}') + Programs = UUID('{A77F5D77-2E2B-44C3-A6A2-ABA601054A51}') + Public = UUID('{DFDF76A2-C82A-4D63-906A-5644AC457385}') + PublicDesktop = UUID('{C4AA340D-F20F-4863-AFEF-F87EF2E6BA25}') + PublicDocuments = UUID('{ED4824AF-DCE4-45A8-81E2-FC7965083634}') + PublicDownloads = UUID('{3D644C9B-1FB8-4f30-9B45-F670235F79C0}') + PublicGameTasks = UUID('{DEBF2536-E1A8-4c59-B6A2-414586476AEA}') + PublicLibraries = UUID('{48DAF80B-E6CF-4F4E-B800-0E69D84EE384}') + PublicMusic = UUID('{3214FAB5-9757-4298-BB61-92A9DEAA44FF}') + PublicPictures = UUID('{B6EBFB86-6907-413C-9AF7-4FC2ABF07CC5}') + PublicRingtones = UUID('{E555AB60-153B-4D17-9F04-A5FE99FC15EC}') + PublicUserTiles = UUID('{0482af6c-08f1-4c34-8c90-e17ec98b1e17}') + PublicVideos = UUID('{2400183A-6185-49FB-A2D8-4A392A602BA3}') + QuickLaunch = UUID('{52a4f021-7b75-48a9-9f6b-4b87a210bc8f}') + Recent = UUID('{AE50C081-EBD2-438A-8655-8A092E34987A}') + RecordedTVLibrary = UUID('{1A6FDBA2-F42D-4358-A798-B74D745926C5}') + ResourceDir = UUID('{8AD10C31-2ADB-4296-A8F7-E4701232C972}') + Ringtones = UUID('{C870044B-F49E-4126-A9C3-B52A1FF411E8}') + RoamingAppData = UUID('{3EB685DB-65F9-4CF6-A03A-E3EF65729F3D}') + RoamedTileImages = UUID('{AAA8D5A5-F1D6-4259-BAA8-78E7EF60835E}') + RoamingTiles = UUID('{00BCFC5A-ED94-4e48-96A1-3F6217F21990}') + SampleMusic = UUID('{B250C668-F57D-4EE1-A63C-290EE7D1AA1F}') + SamplePictures = UUID('{C4900540-2379-4C75-844B-64E6FAF8716B}') + SamplePlaylists = UUID('{15CA69B3-30EE-49C1-ACE1-6B5EC372AFB5}') + SampleVideos = UUID('{859EAD94-2E85-48AD-A71A-0969CB56A6CD}') + SavedGames = UUID('{4C5C32FF-BB9D-43b0-B5B4-2D72E54EAAA4}') + SavedSearches = UUID('{7d1d3a04-debb-4115-95cf-2f29da2920da}') + Screenshots = UUID('{b7bede81-df94-4682-a7d8-57a52620b86f}') + SearchHistory = UUID('{0D4C3DB6-03A3-462F-A0E6-08924C41B5D4}') + SearchTemplates = UUID('{7E636BFE-DFA9-4D5E-B456-D7B39851D8A9}') + SendTo = UUID('{8983036C-27C0-404B-8F08-102D10DCFD74}') + SidebarDefaultParts = UUID('{7B396E54-9EC5-4300-BE0A-2482EBAE1A26}') + SidebarParts = UUID('{A75D362E-50FC-4fb7-AC2C-A8BEAA314493}') + SkyDrive = UUID('{A52BBA46-E9E1-435f-B3D9-28DAA648C0F6}') + SkyDriveCameraRoll = UUID('{767E6811-49CB-4273-87C2-20F355E1085B}') + SkyDriveDocuments = UUID('{24D89E24-2F19-4534-9DDE-6A6671FBB8FE}') + SkyDrivePictures = UUID('{339719B5-8C47-4894-94C2-D8F77ADD44A6}') + StartMenu = UUID('{625B53C3-AB48-4EC1-BA1F-A1EF4146FC19}') + Startup = UUID('{B97D20BB-F46A-4C97-BA10-5E3608430854}') + System = UUID('{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}') + SystemX86 = UUID('{D65231B0-B2F1-4857-A4CE-A8E7C6EA7D27}') + Templates = UUID('{A63293E8-664E-48DB-A079-DF759E0509F7}') + UserPinned = UUID('{9E3995AB-1F9C-4F13-B827-48B24B6C7174}') + UserProfiles = UUID('{0762D272-C50A-4BB0-A382-697DCD729B80}') + UserProgramFiles = UUID('{5CD7AEE2-2219-4A67-B85D-6C9CE15660CB}') + UserProgramFilesCommon = UUID('{BCBD3057-CA5C-4622-B42D-BC56DB0AE516}') + Videos = UUID('{18989B1D-99B5-455B-841C-AB7C74E4DDFC}') + VideosLibrary = UUID('{491E922F-5643-4AF4-A7EB-4E7A138D8174}') + Windows = UUID('{F38BF404-1D43-42F2-9305-67DE0B28FC23}') + +class UserHandle: # [3] + current = wintypes.HANDLE(0) + common = wintypes.HANDLE(-1) + +_CoTaskMemFree = windll.ole32.CoTaskMemFree # [4] +_CoTaskMemFree.restype= None +_CoTaskMemFree.argtypes = [ctypes.c_void_p] + +_SHGetKnownFolderPath = windll.shell32.SHGetKnownFolderPath # [5] [3] +_SHGetKnownFolderPath.argtypes = [ + ctypes.POINTER(GUID), wintypes.DWORD, wintypes.HANDLE, ctypes.POINTER(ctypes.c_wchar_p) +] + +class PathNotFoundException(Exception): pass + +def get_path(folderid, user_handle=UserHandle.common): + fid = GUID(folderid) + pPath = ctypes.c_wchar_p() + S_OK = 0 + if _SHGetKnownFolderPath(ctypes.byref(fid), 0, user_handle, ctypes.byref(pPath)) != S_OK: + raise PathNotFoundException() + path = pPath.value + _CoTaskMemFree(pPath) + return path + +if __name__ == '__main__': + if len(sys.argv) < 2 or sys.argv[1] in ['-?', '/?']: + print('python knownpaths.py FOLDERID {current|common}') + sys.exit(0) + + try: + folderid = getattr(FOLDERID, sys.argv[1]) + except AttributeError: + print('Unknown folder id "%s"' % sys.argv[1], file=sys.stderr) + sys.exit(1) + + try: + if len(sys.argv) == 2: + print(get_path(folderid)) + else: + print(get_path(folderid, getattr(UserHandle, sys.argv[2]))) + except PathNotFoundException: + print('Folder not found "%s"' % ' '.join(sys.argv[1:]), file=sys.stderr) + sys.exit(1) + +# [1] http://msdn.microsoft.com/en-us/library/windows/desktop/aa373931.aspx +# [2] http://msdn.microsoft.com/en-us/library/windows/desktop/dd378457.aspx +# [3] http://msdn.microsoft.com/en-us/library/windows/desktop/bb762188.aspx +# [4] http://msdn.microsoft.com/en-us/library/windows/desktop/ms680722.aspx +# [5] http://www.themacaque.com/?p=954 diff --git a/.bin/Scripts/borrowed/sensors-README.md b/.bin/Scripts/borrowed/sensors-README.md new file mode 100644 index 00000000..11858382 --- /dev/null +++ b/.bin/Scripts/borrowed/sensors-README.md @@ -0,0 +1,35 @@ +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 new file mode 100644 index 00000000..847f2619 --- /dev/null +++ b/.bin/Scripts/borrowed/sensors.py @@ -0,0 +1,236 @@ +""" +@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/cbs_fix.py b/.bin/Scripts/cbs_fix.py index 7c845c34..22b6c49c 100644 --- a/.bin/Scripts/cbs_fix.py +++ b/.bin/Scripts/cbs_fix.py @@ -1,42 +1,42 @@ -# Wizard Kit: Backup CBS Logs and prep CBS temp data for deletion - -import os -import sys - -# Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) -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) - -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?') - - # Show details - print_info('{}: CBS Cleanup Tool\n'.format(KIT_NAME_FULL)) - show_info('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...") - exit_script() - except SystemExit: - pass - except: - major_exception() +# Wizard Kit: Backup CBS Logs and prep CBS temp data for deletion + +import os +import sys + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +sys.path.append(os.getcwd()) +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) + +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?') + + # Show details + print_info('{}: CBS Cleanup Tool\n'.format(KIT_NAME_FULL)) + show_info('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...") + exit_script() + except SystemExit: + pass + except: + major_exception() diff --git a/.bin/Scripts/check_disk.py b/.bin/Scripts/check_disk.py index 3091ecb5..734319f0 100644 --- a/.bin/Scripts/check_disk.py +++ b/.bin/Scripts/check_disk.py @@ -1,56 +1,56 @@ -# Wizard Kit: Check or repair the %SYSTEMDRIVE% filesystem via CHKDSK - -import os -import sys - -# Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -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) - -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() - - # Done - print_success('Done.') - pause("Press Enter to exit...") - exit_script() - except SystemExit: - pass - except: - major_exception() +# Wizard Kit: Check or repair the %SYSTEMDRIVE% filesystem via CHKDSK + +import os +import sys + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +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) + +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() + + # Done + print_success('Done.') + pause("Press Enter to exit...") + exit_script() + except SystemExit: + pass + except: + major_exception() diff --git a/.bin/Scripts/connect-to-network b/.bin/Scripts/connect-to-network new file mode 100755 index 00000000..0475c15c --- /dev/null +++ b/.bin/Scripts/connect-to-network @@ -0,0 +1,30 @@ +#!/bin/python3 +# +## Wizard Kit: Network connection tool + +import os +import sys + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +sys.path.append(os.getcwd()) +from functions.network import * +init_global_vars() + +if __name__ == '__main__': + 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() + diff --git a/.bin/Scripts/dism.py b/.bin/Scripts/dism.py index bbf2a74c..4ae2084d 100644 --- a/.bin/Scripts/dism.py +++ b/.bin/Scripts/dism.py @@ -1,57 +1,57 @@ -# Wizard Kit: Check or repair component store health via DISM - -import os -import sys - -# Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -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) - -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', '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() +# Wizard Kit: Check or repair component store health via DISM + +import os +import sys + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +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) + +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', '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() diff --git a/.bin/Scripts/functions/activation.py b/.bin/Scripts/functions/activation.py index 3eea560c..f54d1dca 100644 --- a/.bin/Scripts/functions/activation.py +++ b/.bin/Scripts/functions/activation.py @@ -1,66 +1,66 @@ -# Wizard Kit: Functions - Activation - -import subprocess - -from borrowed import acpi -from functions.common import * -from os import environ - -# 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 - ##################################################### - #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) - - # 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') - -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 - -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() - - return bool(activation_string and 'permanent' in activation_string) - -if __name__ == '__main__': - print("This file is not meant to be called directly.") +# Wizard Kit: Functions - Activation + +import subprocess + +from borrowed import acpi +from functions.common import * +from os import environ + +# 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 + ##################################################### + #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) + + # 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') + +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 + +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() + + 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/browsers.py b/.bin/Scripts/functions/browsers.py index 876bbe63..b969a59c 100644 --- a/.bin/Scripts/functions/browsers.py +++ b/.bin/Scripts/functions/browsers.py @@ -1,446 +1,446 @@ -# Wizard Kit: Functions - Browsers - -from functions.common import * - -# 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', - } - } - -# 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/' -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"', - } -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' -UBO_EXTRA_CHROME_REG = r'Software\Wow6432Node\Google\Chrome\Extensions\pgdnlhfefecpicbbihgmbmffkjpaplco' -UBO_MOZILLA = 'https://addons.mozilla.org/en-us/firefox/addon/ublock-origin/' -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', - }, - } - -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( - **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', - 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): - """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)) - -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) - 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 - -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) - - # 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)) - -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 - 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)) - - 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) - - # 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 - -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 - - 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) - 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 - - 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 - - return profiles - -def install_adblock(indent=8, width=32): - """Install adblock for all supported browsers.""" - for browser in sorted(browser_data): - 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: - urls.append(UBO_CHROME) - urls.append(UBO_EXTRA_CHROME) - - elif browser_data[browser]['base'] == 'mozilla': - # Assume UBO is not installed first and change if it is - urls.append(UBO_MOZILLA) - if browser == 'Mozilla Firefox': - ubo = browser_data[browser]['exe_path'].replace( - 'firefox.exe', - r'distribution\extensions\uBlock0@raymondhill.net') - if os.path.exists(ubo): - urls = ['about:addons'] - - 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) - -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': - 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)) - -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) - -def scan_for_browsers(): - """Scan system for any supported browsers.""" - for name in sorted(SUPPORTED_BROWSERS): - 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.") +# Wizard Kit: Functions - Browsers + +from functions.common import * + +# 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', + } + } + +# 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/' +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"', + } +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' +UBO_EXTRA_CHROME_REG = r'Software\Wow6432Node\Google\Chrome\Extensions\pgdnlhfefecpicbbihgmbmffkjpaplco' +UBO_MOZILLA = 'https://addons.mozilla.org/en-us/firefox/addon/ublock-origin/' +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', + }, + } + +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( + **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', + 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): + """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)) + +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) + 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 + +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) + + # 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)) + +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 + 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)) + + 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) + + # 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 + +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 + + 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) + 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 + + 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 + + return profiles + +def install_adblock(indent=8, width=32): + """Install adblock for all supported browsers.""" + for browser in sorted(browser_data): + 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: + urls.append(UBO_CHROME) + urls.append(UBO_EXTRA_CHROME) + + elif browser_data[browser]['base'] == 'mozilla': + # Assume UBO is not installed first and change if it is + urls.append(UBO_MOZILLA) + if browser == 'Mozilla Firefox': + ubo = browser_data[browser]['exe_path'].replace( + 'firefox.exe', + r'distribution\extensions\uBlock0@raymondhill.net') + if os.path.exists(ubo): + urls = ['about:addons'] + + 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) + +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': + 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)) + +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) + +def scan_for_browsers(): + """Scan system for any supported browsers.""" + for name in sorted(SUPPORTED_BROWSERS): + 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.") diff --git a/.bin/Scripts/functions/cleanup.py b/.bin/Scripts/functions/cleanup.py index c5562961..1bac4c6c 100644 --- a/.bin/Scripts/functions/cleanup.py +++ b/.bin/Scripts/functions/cleanup.py @@ -1,91 +1,91 @@ -# Wizard Kit: Functions - Cleanup - -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) - - # 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 - try: - os.rmdir(source_path) - except OSError: - pass - - # Main folder - if os.path.exists(source_path): - os.makedirs(global_vars['ProgBackupDir'], exist_ok=True) - dest_name = r'{ProgBackupDir}\AdwCleaner_{Date-Time}'.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. - """ - 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) - - # 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'{ProgBackupDir}\Desktop_{Date-Time}'.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) - - # Remove dir if empty - try: - os.rmdir(dest_folder) - except OSError: - pass - -if __name__ == '__main__': - print("This file is not meant to be called directly.") +# Wizard Kit: Functions - Cleanup + +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) + + # 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 + try: + os.rmdir(source_path) + except OSError: + pass + + # Main folder + if os.path.exists(source_path): + os.makedirs(global_vars['ProgBackupDir'], exist_ok=True) + dest_name = r'{ProgBackupDir}\AdwCleaner_{Date-Time}'.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. + """ + 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) + + # 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'{ProgBackupDir}\Desktop_{Date-Time}'.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) + + # Remove dir if empty + try: + os.rmdir(dest_folder) + except OSError: + pass + +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 4f03205a..437591cb 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -1,717 +1,754 @@ -# Wizard Kit: Functions - Common - -import os -import psutil -import re -import shutil -import subprocess -import sys -import time -import traceback -import winreg - -from subprocess import CalledProcessError - -from settings.main import * -from settings.tools import * - -# Global variables -global_vars = {} - -# STATIC VARIABLES -COLORS = { - 'CLEAR': '\033[0m', - 'RED': '\033[31m', - 'GREEN': '\033[32m', - 'YELLOW': '\033[33m', - 'BLUE': '\033[34m' -} -HKU = winreg.HKEY_USERS -HKCU = winreg.HKEY_CURRENT_USER -HKLM = winreg.HKEY_LOCAL_MACHINE - -# Error Classes -class BIOSKeyNotFoundError(Exception): - pass - -class BinNotFoundError(Exception): - pass - -class GenericAbort(Exception): - pass - -class GenericError(Exception): - pass - -class GenericRepair(Exception): - pass - -class MultipleInstallationsError(Exception): - pass - -class NotInstalledError(Exception): - pass - -class NoProfilesError(Exception): - pass - -class PathNotFoundError(Exception): - pass - -class UnsupportedOSError(Exception): - pass - -# General functions -def abort(): - """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 - -def clear_screen(): - """Simple wrapper for cls.""" - os.system('cls') - -def convert_to_bytes(size): - """Convert human-readable size str to bytes and return an int.""" - size = str(size) - tmp = re.search(r'(\d+)\s+([KMGT]B)', size.upper()) - if tmp: - size = int(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 - else: - return -1 - - 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: - dir = global_vars[dir] - os.rmdir(dir) - except Exception: - pass - - # Open Log (if it exists) - log = global_vars.get('LogFile', '') - if log and os.path.exists(log): - 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') - - # 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] - if not silent: - print_standard('Extracting "{item}"...'.format(item=item)) - try: - run_program(cmd) - except subprocess.CalledProcessError: - if not silent: - print_warning('WARNING: Errors encountered while exctracting data') - -def get_ticket_number(): - """Get TicketNumber from user, save in LogDir, and return as str.""" - ticket_number = None - while ticket_number is None: - _input = input('Enter ticket number: ') - if re.match(r'^([0-9]+([-_]?\w+|))$', _input): - ticket_number = _input - with open(r'{}\TicketNumber'.format(global_vars['LogDir']), '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 to int - try: - size = int(size) - except ValueError: - size = convert_to_bytes(size) - - # 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' - - # 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() - -def major_exception(): - """Display traceback and exit""" - print_error('Major exception') - print_warning(SUPPORT_MESSAGE) - print(traceback.format_exc()) - print_log(traceback.format_exc()) - sleep(30) - pause('Press Enter to exit...') - exit_script(1) - -def menu_select(title='~ Untitled Menu ~', - prompt='Please make a selection', secret_exit=False, - main_entries=[], action_entries=[], disabled_label='DISABLED'): - """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) - - # Build menu - menu_splash = '{}\n\n'.format(title) - width = len(str(len(main_entries))) - valid_answers = [] - if (secret_exit): - valid_answers.append('Q') - - # Add main entries - for i in range(len(main_entries)): - entry = main_entries[i] - # Add Spacer - if ('CRLF' in entry): - menu_splash += '\n' - 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' - - # Add action entries - for entry in action_entries: - # Add Spacer - if ('CRLF' in entry): - menu_splash += '\n' - 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']) - menu_splash += '\n' - - answer = '' - - while (answer.upper() not in valid_answers): - os.system('cls') - print(menu_splash) - answer = input('{}: '.format(prompt)) - - 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 - - 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 = ['ping', '-n', '2', addr] - run_program(cmd) - -def popen_program(cmd, pipe=False, minimized=False, shell=False, **kwargs): - """Run program and return a subprocess.Popen object.""" - startupinfo=None - if minimized: - startupinfo = subprocess.STARTUPINFO() - startupinfo.dwFlags = subprocess.STARTF_USESHOWWINDOW - startupinfo.wShowWindow = 6 - - 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) - - return popen_obj - -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).""" - 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) - -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): - time_str = time.strftime("%Y-%m-%d %H%M%z: ") if timestamp else '' - if 'LogFile' in global_vars and global_vars['LogFile'] is not None: - 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): - """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) - - 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) - - return process_return - -def set_title(title='~Some Title~'): - """Set 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, - 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) - -def show_info(message='~Some message~', info='~Some info~', indent=8, width=32): - show_data(message=message, data=info, indent=indent, width=width) - -def sleep(seconds=2): - """Wait for a while.""" - time.sleep(seconds) - -def stay_awake(): - """Prevent the system from sleeping or hibernating.""" - # 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 get_exception(s): - """Get exception by name, returns Exception object.""" - return getattr(sys.modules[__name__], s) - -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. - - 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', {}) - - # 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: - print_standard(out[0], timestamp=False) - for item in out[1:]: - print_standard('{indent}{item}'.format( - indent=' '*(indent+width), item=item)) - 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} - -def upload_data(path, file): - """Add CLIENT_INFO_SERVER to authorized connections and upload file.""" - if not ENABLED_UPLOAD_DATA: - raise GenericError('Feature disabled.') - - extract_item('PuTTY', filter='wizkit.ppk psftp.exe', silent=True) - - # Authorize connection to the server - winreg.CreateKey(HKCU, r'Software\SimonTatham\PuTTY\SshHostKeys') - with winreg.OpenKey(HKCU, r'Software\SimonTatham\PuTTY\SshHostKeys', - access=winreg.KEY_WRITE) as key: - winreg.SetValueEx(key, - 'rsa2@22:{IP}'.format(**CLIENT_INFO_SERVER), 0, - winreg.REG_SZ, CLIENT_INFO_SERVER['RegEntry']) - - # Write batch file - with open(r'{}\psftp.batch'.format(global_vars['TmpDir']), - 'w', encoding='ascii') as f: - f.write('lcd "{path}"\n'.format(path=path)) - f.write('cd "{Share}"\n'.format(**CLIENT_INFO_SERVER)) - f.write('mkdir {TicketNumber}\n'.format(**global_vars)) - f.write('cd {TicketNumber}\n'.format(**global_vars)) - f.write('put "{file}"\n'.format(file=file)) - - # Upload Info - cmd = [ - global_vars['Tools']['PuTTY-PSFTP'], - '-noagent', - '-i', r'{BinDir}\PuTTY\wizkit.ppk'.format(**global_vars), - '{User}@{IP}'.format(**CLIENT_INFO_SERVER), - '-b', r'{TmpDir}\psftp.batch'.format(**global_vars)] - run_program(cmd) - -def upload_info(): - """Upload compressed Info file to the NAS as set in settings.main.py.""" - if not ENABLED_UPLOAD_DATA: - raise GenericError('Feature disabled.') - - path = '{ClientDir}'.format(**global_vars) - file = 'Info_{Date-Time}.7z'.format(**global_vars) - upload_data(path, file) - -def compress_info(): - """Compress ClientDir info folders with 7-Zip for upload_info().""" - path = '{ClientDir}'.format(**global_vars) - file = 'Info_{Date-Time}.7z'.format(**global_vars) - _cmd = [ - global_vars['Tools']['SevenZip'], - 'a', '-t7z', '-mx=9', '-bso0', '-bse0', - r'{}\{}'.format(path, file), - r'{ClientDir}\Info'.format(**global_vars)] - run_program(_cmd) - -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(): - if re.search(r'^{}'.format(name), proc.name(), re.IGNORECASE): - running = True - sleep(1) - -# global_vars functions -def init_global_vars(): - """Sets global variables based on system info.""" - print_info('Initializing') - os.system('title Wizard Kit') - 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: - 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 = {} - - # 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' - try: - tmp['CurrentBuild'] = int(tmp['CurrentBuild']) - except ValueError: - # This should be interesting... - tmp['CurrentBuild'] = -1 - try: - tmp['CurrentVersion'] = float(tmp['CurrentVersion']) - except ValueError: - # This should also be interesting... - tmp['CurrentVersion'] = -1 - - # Check bit depth - tmp['Arch'] = 32 - if 'PROGRAMFILES(X86)' in global_vars['Env']: - tmp['Arch'] = 64 - - # Set name - tmp['Name'] = tmp['ProductName'] - if tmp['CurrentBuild'] == 7601: - tmp['Name'] += ' SP1' # Win 7 - if tmp['CurrentBuild'] == 9600: - tmp['Name'] += ' Update' # Win 8.1u - if tmp['CurrentBuild'] == 10240: - tmp['Name'] += ' Release 1507 "Threshold 1"' - if tmp['CurrentBuild'] == 10586: - tmp['Name'] += ' Release 1511 "Threshold 2"' - if tmp['CurrentBuild'] == 14393: - tmp['Name'] += ' Release 1607 "Redstone 1" / "Anniversary Update"' - if tmp['CurrentBuild'] == 15063: - tmp['Name'] += ' Release 1703 "Redstone 2" / "Creators Update"' - if tmp['CurrentBuild'] == 16299: - tmp['Name'] += ' Release 1709 "Redstone 3" / "Fall Creators Update"' - tmp['Name'] = re.sub(r'\s+', ' ', tmp['Name']) - - # Set display name - tmp['DisplayName'] = '{} x{}'.format(tmp['Name'], tmp['Arch']) - if tmp['CurrentBuild'] in [7600, 9200, 10240, 10586]: - tmp['DisplayName'] += ' (very outdated)' - elif tmp['CurrentBuild'] in [7601, 9600, 14393, 15063]: - tmp['DisplayName'] += ' (outdated)' - elif tmp['CurrentBuild'] == 16299: - pass # Current Win10 release - else: - tmp['DisplayName'] += ' (unrecognized)' - - # Set version - if tmp['CurrentVersion'] == 6.0: - tmp['Version'] = 'Vista' - elif tmp['CurrentVersion'] == 6.1: - tmp['Version'] = '7' - elif 6.2 <= tmp['CurrentVersion'] <= 6.3: - if tmp['CurrentBuild'] <= 9600: - tmp['Version'] = '8' - elif tmp['CurrentBuild'] >= 10240: - tmp['Version'] = '10' - else: - tmp['Version'] = 'Unknown' - - # == vista == - # 6.0.6000 - # 6.0.6001 # SP1 - # 6.0.6002 # SP2 - # ==== 7 ==== - # 6.1.7600 - # 6.1.7601 # SP1 - # 6.1.7602 # Umm.. where'd this come from? - # ==== 8 ==== - # 6.2.9200 - # === 8.1 === - # 6.3.9200 - # === 8.1u == - # 6.3.9600 - # === 10 v1507 "Threshold 1" == - # 6.3.10240 - # === 10 v1511 "Threshold 2" == - # 6.3.10586 - # === 10 v1607 "Redstone 1" "Anniversary Update" == - # 6.3.14393 - # === 10 v1703 "Redstone 2" "Creators Update" == - # 6.3.15063 - # === 10 v1709 "Redstone 3" "Fall Creators Update" == - # 6.3.16299 - 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()} - - # 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. - - 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 - -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(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() - - 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\{Date}'.format( - **global_vars) - global_vars['LogDir'] = r'{ClientDir}\Info\{Date}'.format( - **global_vars) - global_vars['ProgBackupDir'] = r'{ClientDir}\Backups'.format( - **global_vars) - global_vars['QuarantineDir'] = r'{ClientDir}\Quarantine'.format( - **global_vars) - global_vars['TmpDir'] = r'{BinDir}\tmp'.format( - **global_vars) - -if __name__ == '__main__': - print("This file is not meant to be called directly.") +# Wizard Kit: Functions - Common + +import os +import psutil +import re +import shutil +import subprocess +import sys +import time +import traceback +try: + import winreg +except ModuleNotFoundError: + if psutil.WINDOWS: + raise + +from subprocess import CalledProcessError + +from settings.main import * +from settings.tools import * + +# Global variables +global_vars = {} + +# STATIC VARIABLES +COLORS = { + 'CLEAR': '\033[0m', + 'RED': '\033[31m', + 'GREEN': '\033[32m', + 'YELLOW': '\033[33m', + 'BLUE': '\033[34m' +} +try: + HKU = winreg.HKEY_USERS + HKCU = winreg.HKEY_CURRENT_USER + HKLM = winreg.HKEY_LOCAL_MACHINE +except NameError: + if psutil.WINDOWS: + raise + +# Error Classes +class BIOSKeyNotFoundError(Exception): + pass + +class BinNotFoundError(Exception): + pass + +class GenericAbort(Exception): + pass + +class GenericError(Exception): + pass + +class GenericRepair(Exception): + pass + +class MultipleInstallationsError(Exception): + pass + +class NotInstalledError(Exception): + pass + +class NoProfilesError(Exception): + pass + +class PathNotFoundError(Exception): + pass + +class UnsupportedOSError(Exception): + pass + +# General functions +def abort(): + """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 + +def clear_screen(): + """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+)\s+([KMGT]B)', size.upper()) + if tmp: + size = int(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 + else: + return -1 + + 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: + dir = global_vars[dir] + os.rmdir(dir) + except Exception: + pass + + # Open Log (if it exists) + log = global_vars.get('LogFile', '') + if log and os.path.exists(log) and psutil.WINDOWS: + 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') + + # 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] + if not silent: + print_standard('Extracting "{item}"...'.format(item=item)) + try: + run_program(cmd) + except subprocess.CalledProcessError: + if not silent: + print_warning('WARNING: Errors encountered while exctracting data') + +def get_ticket_number(): + """Get TicketNumber from user, save in LogDir, and return as str.""" + 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 to int + try: + size = int(size) + except ValueError: + size = convert_to_bytes(size) + + # 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' + + # 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() + +def major_exception(): + """Display traceback and exit""" + print_error('Major exception') + print_warning(SUPPORT_MESSAGE) + print(traceback.format_exc()) + print_log(traceback.format_exc()) + sleep(30) + pause('Press Enter to exit...') + exit_script(1) + +def menu_select(title='~ Untitled Menu ~', + prompt='Please make a selection', 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") + + # 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') + + # 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']) + menu_splash += '\n' + + answer = '' + + while (answer.upper() not in valid_answers): + clear_screen() + print(menu_splash) + answer = input('{}: '.format(prompt)) + + 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 + + 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 = [ + '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.""" + startupinfo=None + if minimized: + startupinfo = subprocess.STARTUPINFO() + startupinfo.dwFlags = subprocess.STARTF_USESHOWWINDOW + startupinfo.wShowWindow = 6 + + 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) + + return popen_obj + +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).""" + 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) + +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): + 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): + """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) + + 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) + + return process_return + +def set_title(title='~Some Title~'): + """Set 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, + 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) + +def show_info(message='~Some message~', info='~Some info~', indent=8, width=32): + show_data(message=message, data=info, indent=indent, width=width) + +def sleep(seconds=2): + """Wait for a while.""" + time.sleep(seconds) + +def stay_awake(): + """Prevent the system from sleeping or hibernating.""" + # 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 get_exception(s): + """Get exception by name, returns Exception object.""" + return getattr(sys.modules[__name__], s) + +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. + + 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', {}) + + # 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} + +def upload_data(path, file): + """Add CLIENT_INFO_SERVER to authorized connections and upload file.""" + if not ENABLED_UPLOAD_DATA: + raise GenericError('Feature disabled.') + + extract_item('PuTTY', filter='wizkit.ppk psftp.exe', silent=True) + + # Authorize connection to the server + winreg.CreateKey(HKCU, r'Software\SimonTatham\PuTTY\SshHostKeys') + with winreg.OpenKey(HKCU, r'Software\SimonTatham\PuTTY\SshHostKeys', + access=winreg.KEY_WRITE) as key: + winreg.SetValueEx(key, + 'rsa2@22:{IP}'.format(**CLIENT_INFO_SERVER), 0, + winreg.REG_SZ, CLIENT_INFO_SERVER['RegEntry']) + + # Write batch file + with open(r'{}\psftp.batch'.format(global_vars['TmpDir']), + 'w', encoding='ascii') as f: + f.write('lcd "{path}"\n'.format(path=path)) + f.write('cd "{Share}"\n'.format(**CLIENT_INFO_SERVER)) + f.write('mkdir {TicketNumber}\n'.format(**global_vars)) + f.write('cd {TicketNumber}\n'.format(**global_vars)) + f.write('put "{file}"\n'.format(file=file)) + + # Upload Info + cmd = [ + global_vars['Tools']['PuTTY-PSFTP'], + '-noagent', + '-i', r'{BinDir}\PuTTY\wizkit.ppk'.format(**global_vars), + '{User}@{IP}'.format(**CLIENT_INFO_SERVER), + '-b', r'{TmpDir}\psftp.batch'.format(**global_vars)] + run_program(cmd) + +def upload_info(): + """Upload compressed Info file to the NAS as set in settings.main.py.""" + if not ENABLED_UPLOAD_DATA: + raise GenericError('Feature disabled.') + + path = '{ClientDir}'.format(**global_vars) + file = 'Info_{Date-Time}.7z'.format(**global_vars) + upload_data(path, file) + +def compress_info(): + """Compress ClientDir info folders with 7-Zip for upload_info().""" + path = '{ClientDir}'.format(**global_vars) + file = 'Info_{Date-Time}.7z'.format(**global_vars) + _cmd = [ + global_vars['Tools']['SevenZip'], + 'a', '-t7z', '-mx=9', '-bso0', '-bse0', + r'{}\{}'.format(path, file), + r'{ClientDir}\Info'.format(**global_vars)] + run_program(_cmd) + +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(): + if re.search(r'^{}'.format(name), proc.name(), re.IGNORECASE): + running = True + sleep(1) + +# global_vars functions +def init_global_vars(): + """Sets global variables based on system info.""" + 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: + 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 = {} + + # 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' + try: + tmp['CurrentBuild'] = int(tmp['CurrentBuild']) + except ValueError: + # This should be interesting... + tmp['CurrentBuild'] = -1 + try: + tmp['CurrentVersion'] = float(tmp['CurrentVersion']) + except ValueError: + # This should also be interesting... + tmp['CurrentVersion'] = -1 + + # Check bit depth + tmp['Arch'] = 32 + if 'PROGRAMFILES(X86)' in global_vars['Env']: + tmp['Arch'] = 64 + + # Set name + tmp['Name'] = tmp['ProductName'] + if tmp['CurrentBuild'] == 7601: + tmp['Name'] += ' SP1' # Win 7 + if tmp['CurrentBuild'] == 9600: + tmp['Name'] += ' Update' # Win 8.1u + if tmp['CurrentBuild'] == 10240: + tmp['Name'] += ' Release 1507 "Threshold 1"' + if tmp['CurrentBuild'] == 10586: + tmp['Name'] += ' Release 1511 "Threshold 2"' + if tmp['CurrentBuild'] == 14393: + tmp['Name'] += ' Release 1607 "Redstone 1" / "Anniversary Update"' + if tmp['CurrentBuild'] == 15063: + tmp['Name'] += ' Release 1703 "Redstone 2" / "Creators Update"' + if tmp['CurrentBuild'] == 16299: + tmp['Name'] += ' Release 1709 "Redstone 3" / "Fall Creators Update"' + tmp['Name'] = re.sub(r'\s+', ' ', tmp['Name']) + + # Set display name + tmp['DisplayName'] = '{} x{}'.format(tmp['Name'], tmp['Arch']) + if tmp['CurrentBuild'] in [7600, 9200, 10240, 10586]: + tmp['DisplayName'] += ' (very outdated)' + elif tmp['CurrentBuild'] in [7601, 9600, 14393, 15063]: + tmp['DisplayName'] += ' (outdated)' + elif tmp['CurrentBuild'] == 16299: + pass # Current Win10 release + else: + tmp['DisplayName'] += ' (unrecognized)' + + # Set version + if tmp['CurrentVersion'] == 6.0: + tmp['Version'] = 'Vista' + elif tmp['CurrentVersion'] == 6.1: + tmp['Version'] = '7' + elif 6.2 <= tmp['CurrentVersion'] <= 6.3: + if tmp['CurrentBuild'] <= 9600: + tmp['Version'] = '8' + elif tmp['CurrentBuild'] >= 10240: + tmp['Version'] = '10' + else: + tmp['Version'] = 'Unknown' + + # == vista == + # 6.0.6000 + # 6.0.6001 # SP1 + # 6.0.6002 # SP2 + # ==== 7 ==== + # 6.1.7600 + # 6.1.7601 # SP1 + # 6.1.7602 # Umm.. where'd this come from? + # ==== 8 ==== + # 6.2.9200 + # === 8.1 === + # 6.3.9200 + # === 8.1u == + # 6.3.9600 + # === 10 v1507 "Threshold 1" == + # 6.3.10240 + # === 10 v1511 "Threshold 2" == + # 6.3.10586 + # === 10 v1607 "Redstone 1" "Anniversary Update" == + # 6.3.14393 + # === 10 v1703 "Redstone 2" "Creators Update" == + # 6.3.15063 + # === 10 v1709 "Redstone 3" "Fall Creators Update" == + # 6.3.16299 + 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()} + + # 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. + + 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 + +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(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() + + 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\{Date}'.format( + **global_vars) + global_vars['LogDir'] = r'{ClientDir}\Info\{Date}'.format( + **global_vars) + global_vars['ProgBackupDir'] = r'{ClientDir}\Backups'.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(): + 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'] + +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 8703aaea..414c2fba 100644 --- a/.bin/Scripts/functions/data.py +++ b/.bin/Scripts/functions/data.py @@ -1,628 +1,734 @@ -# Wizard Kit: Functions - Data - -import ctypes - -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 - -# 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 = [ - 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)), - ] -# Code borrowed from: https://stackoverflow.com/a/29075319 -SEM_NORMAL = ctypes.c_uint() -SEM_FAILCRITICALERRORS = 1 -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: - 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 - -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 - -def mount_backup_shares(): - """Mount the backup shares unless labeled as already mounted.""" - for server in BACKUP_SERVERS: - # Blindly skip if we mounted earlier - if server['Mounted']: - continue - - mount_network_share(server) - -def mount_network_share(server): - """Mount a network share defined by server.""" - # Test connection - try: - ping(server['IP']) - except subprocess.CalledProcessError: - print_error( - r'Failed to mount \\{Name}\{Share}, {IP} unreachable.'.format( - **server)) - sleep(1) - return False - - # Mount - cmd = r'net use \\{IP}\{Share} /user:{User} {Pass}'.format(**server) - cmd = cmd.split(' ') - try: - run_program(cmd) - except Exception: - print_warning(r'Failed to mount \\{Name}\{Share} ({IP})'.format( - **server)) - sleep(1) - else: - print_info('Mounted {Name}'.format(**server)) - server['Mounted'] = True - -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.extend(items) - cmd.append('/to={}\\'.format(dest)) - - 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) - - # 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) - -def scan_source(source_obj, dest_path): - """Scan source for files/folders to transfer.""" - selected_items = [] - - if source_obj.is_dir(): - # File-Based - print_standard('Scanning source (folder): {}'.format(source_obj.path)) - selected_items = scan_source_path(source_obj.path, dest_path) - else: - # Image-Based - if REGEX_WIM_FILE.search(source_obj.name): - print_standard('Scanning source (image): {}'.format( - source_obj.path)) - selected_items = scan_source_wim(source_obj.path, dest_path) - else: - print_error('ERROR: Unsupported image: {}'.format( - source_obj.path)) - raise GenericError - - return selected_items - -def scan_source_path(source_path, dest_path, rel_path=None, interactive=True): - """Scan source folder for files/folders to transfer, returns list. - - This will scan the root and (recursively) any Windows.old folders.""" - rel_path = '\\' + rel_path if rel_path else '' - if rel_path: - dest_path = dest_path + rel_path - selected_items = [] - win_olds = [] - - # Root items - root_items = [] - for item in os.scandir(source_path): - if REGEX_INCL_ROOT_ITEMS.search(item.name): - root_items.append(item.path) - elif not REGEX_EXCL_ROOT_ITEMS.search(item.name): - if (not interactive - or ask('Copy: "{}{}" ?'.format(rel_path, item.name))): - root_items.append(item.path) - if REGEX_WINDOWS_OLD.search(item.name): - win_olds.append(item) - if root_items: - selected_items.append({ - 'Message': '{}Root Items...'.format(rel_path), - 'Items': root_items.copy(), - 'Destination': dest_path}) - - # Fonts - if os.path.exists(r'{}\Windows\Fonts'.format(source_path)): - selected_items.append({ - 'Message': '{}Fonts...'.format(rel_path), - 'Items': [r'{}\Windows\Fonts'.format(rel_path)], - 'Destination': r'{}\Windows'.format(dest_path)}) - - # Registry - registry_items = [] - for folder in ['config', 'OEM']: - folder = r'Windows\System32\{}'.format(folder) - folder = os.path.join(source_path, folder) - if os.path.exists(folder): - registry_items.append(folder) - if registry_items: - selected_items.append({ - 'Message': '{}Registry...'.format(rel_path), - 'Items': registry_items.copy(), - 'Destination': r'{}\Windows\System32'.format(dest_path)}) - - # Windows.old(s) - for old in win_olds: - selected_items.append( - scan_source_path( - old.path, dest_path, rel_path=old.name, interactive=False)) - - # Done - return selected_items - -def scan_source_wim(source_wim, dest_path, rel_path=None, interactive=True): - """Scan source WIM file for files/folders to transfer, returns list. - - This will scan the root and (recursively) any Windows.old folders.""" - rel_path = '\\' + rel_path if rel_path else '' - selected_items = [] - win_olds = [] - - # Scan source - extract_item('wimlib', silent=True) - cmd = [ - global_vars['Tools']['wimlib-imagex'], 'dir', - source_wim, '1'] - try: - file_list = run_program(cmd) - except subprocess.CalledProcessError: - print_error('ERROR: Failed to get file list.') - raise - - # Root Items - file_list = [i.strip() - for i in file_list.stdout.decode('utf-8', 'ignore').splitlines() - if i.count('\\') == 1 and i.strip() != '\\'] - root_items = [] - if rel_path: - file_list = [i.replace(rel_path, '') for i in file_list] - for item in file_list: - if REGEX_INCL_ROOT_ITEMS.search(item): - root_items.append(item) - elif not REGEX_EXCL_ROOT_ITEMS.search(item): - if (not interactive - or ask('Extract: "{}{}" ?'.format(rel_path, item))): - root_items.append('{}{}'.format(rel_path, item)) - if REGEX_WINDOWS_OLD.search(item): - win_olds.append(item) - if root_items: - selected_items.append({ - 'Message': '{}Root Items...'.format(rel_path), - 'Items': root_items.copy(), - 'Destination': dest_path}) - - # Fonts - if wim_contains(source_wim, r'{}Windows\Fonts'.format(rel_path)): - selected_items.append({ - 'Message': '{}Fonts...'.format(rel_path), - 'Items': [r'{}\Windows\Fonts'.format(rel_path)], - 'Destination': dest_path}) - - # Registry - registry_items = [] - for folder in ['config', 'OEM']: - folder = r'{}Windows\System32\{}'.format(rel_path, folder) - if wim_contains(source_wim, folder): - registry_items.append(folder) - if registry_items: - selected_items.append({ - 'Message': '{}Registry...'.format(rel_path), - 'Items': registry_items.copy(), - 'Destination': dest_path}) - - # Windows.old(s) - for old in win_olds: - scan_source_wim(source_wim, dest_path, rel_path=old, interactive=False) - - # Done - return selected_items - -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) - - # Avoid merging with existing folder - path = non_clobber_rename(path) - os.makedirs(path, exist_ok=True) - - return path - -def select_source(ticket_number): - """Select backup from those found on the BACKUP_SERVERS for the ticket.""" - selected_source = None - local_sources = [] - remote_sources = [] - sources = [] - mount_backup_shares() - - # Check for ticket 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(ticket_number.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 ticket_path in remote_sources.copy(): - for item in os.scandir(ticket_path['Source'].path): - if item.is_dir(): - # Add folder to remote_sources - remote_sources.append({ - 'Name': r'{:9}| File-Based: [DIR] {}\{}'.format( - ticket_path['Server']['Name'], # Server - ticket_path['Source'].name, # Ticket folder - item.name, # Sub-folder - ), - 'Server': ticket_path['Server'], - 'Sort': r'{}\{}'.format( - ticket_path['Source'].name, # Ticket 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( - ticket_path['Server']['Name'], # Server - size, # Size (duh) - ticket_path['Source'].name, # Ticket folder - item.name, # Sub-folder - subitem.name, # Image file - ), - 'Server': ticket_path['Server'], - 'Sort': r'{}\{}\{}'.format( - ticket_path['Source'].name, # Ticket 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( - ticket_path['Server']['Name'], # Server - size, # Size (duh) - ticket_path['Source'].name, # Ticket folder - item.name, # Image file - ), - 'Server': ticket_path['Server'], - 'Sort': r'{}\{}'.format( - ticket_path['Source'].name, # Ticket 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)}) - 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'}] - - # 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'] - else: - print_error('ERROR: No backups found for ticket: {}.'.format( - ticket_number)) - umount_backup_shares() - pause("Press Enter to exit...") - exit_script() - - # 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 = [] - - # 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() - else: - return disks[int(selection)-1] - -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: - 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']) - 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=group['Destination']) - else: - print_error('ERROR: Unsupported image: {}'.format(source_obj.path)) - raise GenericError - -def umount_backup_shares(): - """Unnount the backup shares regardless of current status.""" - for server in BACKUP_SERVERS: - umount_network_share(server) - -def umount_network_share(server): - """Unnount 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 - -def wim_contains(source_path, file_path): - """Check if the WIM contains a file or folder.""" - _cmd = [ - global_vars['Tools']['wimlib-imagex'], 'dir', - source_path, '1', - '--path={}'.format(file_path), - '--one-file-only'] - try: - run_program(_cmd) - except subprocess.CalledProcessError: - return False - else: - return True - -if __name__ == '__main__': - print("This file is not meant to be called directly.") +# Wizard Kit: Functions - Data + +import ctypes +import json + +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 + +# 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 = [ + 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)), + ] +# Code borrowed from: https://stackoverflow.com/a/29075319 +SEM_NORMAL = ctypes.c_uint() +SEM_FAILCRITICALERRORS = 1 +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: + 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 + +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 + +def get_mounted_data(): + """Get mounted volumes, returns dict.""" + cmd = [ + 'findmnt', '-J', '-b', '-i', + 't', ( + 'autofs,binfmt_misc,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_data = [] + for item in json_data.get('filesystems', []): + mounted_data.append(item) + mounted_data.extend(item.get('children', [])) + return {item['source']: item for item in mounted_data} + +def mount_all_volumes(): + """Mount all attached devices with recognized filesystems.""" + report = [] + + # Get list of block devices + cmd = ['lsblk', '-J', '-o', 'NAME,FSTYPE,LABEL,UUID,PARTTYPE,TYPE,SIZE'] + result = run_program(cmd) + json_data = json.loads(result.stdout.decode()) + devs = json_data.get('blockdevices', []) + + # Get list of mounted devices + mounted_data = get_mounted_data() + mounted_list = [m['source'] for m in mounted_data.values()] + + # Loop over devices + for dev in devs: + dev_path = '/dev/{}'.format(dev['name']) + if re.search(r'^(loop|sr)', dev['name'], re.IGNORECASE): + # Skip loopback devices and optical media + report.append([dev_path, 'Skipped']) + continue + for child in dev.get('children', []): + child_path = '/dev/{}'.format(child['name']) + if child_path in mounted_list: + report.append([child_path, 'Already Mounted']) + else: + try: + run_program(['udevil', 'mount', '-o', 'ro', child_path]) + report.append([child_path, 'CS']) + except subprocess.CalledProcessError: + report.append([child_path, 'NS']) + + # Update list of mounted devices + mounted_data = get_mounted_data() + mounted_list = [m['source'] for m in mounted_data.values()] + + # Update report lines for show_data() + for line in report: + _path = line[0] + _result = line[1] + info = {'message': '{}:'.format(_path)} + if _path in mounted_list: + info['data'] = 'Mounted on {}'.format( + mounted_data[_path]['target']) + info['data'] = '{:40} ({} used, {} free)'.format( + info['data'], + human_readable_size(mounted_data[_path]['used']), + human_readable_size(mounted_data[_path]['avail'])) + if _result == 'Already Mounted': + info['warning'] = True + elif _result == 'Skipped': + info['data'] = 'Skipped' + info['warning'] = True + else: + info['data'] = 'Failed to mount' + info['error'] = True + line.append(info) + return report + +def mount_backup_shares(): + """Mount the backup shares unless labeled as already mounted.""" + if psutil.LINUX: + mounted_data = get_mounted_data() + 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_data.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) + +def mount_network_share(server): + """Mount a network share defined by server.""" + if psutil.WINDOWS: + cmd = r'net use \\{IP}\{Share} /user:{User} {Pass}'.format(**server) + cmd = cmd.split(' ') + 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={User},password={Pass}'.format(**server)] + 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 + + # 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 + + cmd = [global_vars['Tools']['FastCopy'], *FAST_COPY_ARGS] + cmd.append(r'/logfile={}\FastCopy.log'.format(global_vars['LogDir'])) + cmd.extend(items) + cmd.append('/to={}\\'.format(dest)) + + 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) + + # 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) + +def scan_source(source_obj, dest_path): + """Scan source for files/folders to transfer.""" + selected_items = [] + + if source_obj.is_dir(): + # File-Based + print_standard('Scanning source (folder): {}'.format(source_obj.path)) + selected_items = scan_source_path(source_obj.path, dest_path) + else: + # Image-Based + if REGEX_WIM_FILE.search(source_obj.name): + print_standard('Scanning source (image): {}'.format( + source_obj.path)) + selected_items = scan_source_wim(source_obj.path, dest_path) + else: + print_error('ERROR: Unsupported image: {}'.format( + source_obj.path)) + raise GenericError + + return selected_items + +def scan_source_path(source_path, dest_path, rel_path=None, interactive=True): + """Scan source folder for files/folders to transfer, returns list. + + This will scan the root and (recursively) any Windows.old folders.""" + rel_path = '\\' + rel_path if rel_path else '' + if rel_path: + dest_path = dest_path + rel_path + selected_items = [] + win_olds = [] + + # Root items + root_items = [] + for item in os.scandir(source_path): + if REGEX_INCL_ROOT_ITEMS.search(item.name): + root_items.append(item.path) + elif not REGEX_EXCL_ROOT_ITEMS.search(item.name): + if (not interactive + or ask('Copy: "{}{}" ?'.format(rel_path, item.name))): + root_items.append(item.path) + if REGEX_WINDOWS_OLD.search(item.name): + win_olds.append(item) + if root_items: + selected_items.append({ + 'Message': '{}Root Items...'.format(rel_path), + 'Items': root_items.copy(), + 'Destination': dest_path}) + + # Fonts + if os.path.exists(r'{}\Windows\Fonts'.format(source_path)): + selected_items.append({ + 'Message': '{}Fonts...'.format(rel_path), + 'Items': [r'{}\Windows\Fonts'.format(rel_path)], + 'Destination': r'{}\Windows'.format(dest_path)}) + + # Registry + registry_items = [] + for folder in ['config', 'OEM']: + folder = r'Windows\System32\{}'.format(folder) + folder = os.path.join(source_path, folder) + if os.path.exists(folder): + registry_items.append(folder) + if registry_items: + selected_items.append({ + 'Message': '{}Registry...'.format(rel_path), + 'Items': registry_items.copy(), + 'Destination': r'{}\Windows\System32'.format(dest_path)}) + + # Windows.old(s) + for old in win_olds: + selected_items.append( + scan_source_path( + old.path, dest_path, rel_path=old.name, interactive=False)) + + # Done + return selected_items + +def scan_source_wim(source_wim, dest_path, rel_path=None, interactive=True): + """Scan source WIM file for files/folders to transfer, returns list. + + This will scan the root and (recursively) any Windows.old folders.""" + rel_path = '\\' + rel_path if rel_path else '' + selected_items = [] + win_olds = [] + + # Scan source + extract_item('wimlib', silent=True) + cmd = [ + global_vars['Tools']['wimlib-imagex'], 'dir', + source_wim, '1'] + try: + file_list = run_program(cmd) + except subprocess.CalledProcessError: + print_error('ERROR: Failed to get file list.') + raise + + # Root Items + file_list = [i.strip() + for i in file_list.stdout.decode('utf-8', 'ignore').splitlines() + if i.count('\\') == 1 and i.strip() != '\\'] + root_items = [] + if rel_path: + file_list = [i.replace(rel_path, '') for i in file_list] + for item in file_list: + if REGEX_INCL_ROOT_ITEMS.search(item): + root_items.append(item) + elif not REGEX_EXCL_ROOT_ITEMS.search(item): + if (not interactive + or ask('Extract: "{}{}" ?'.format(rel_path, item))): + root_items.append('{}{}'.format(rel_path, item)) + if REGEX_WINDOWS_OLD.search(item): + win_olds.append(item) + if root_items: + selected_items.append({ + 'Message': '{}Root Items...'.format(rel_path), + 'Items': root_items.copy(), + 'Destination': dest_path}) + + # Fonts + if wim_contains(source_wim, r'{}Windows\Fonts'.format(rel_path)): + selected_items.append({ + 'Message': '{}Fonts...'.format(rel_path), + 'Items': [r'{}\Windows\Fonts'.format(rel_path)], + 'Destination': dest_path}) + + # Registry + registry_items = [] + for folder in ['config', 'OEM']: + folder = r'{}Windows\System32\{}'.format(rel_path, folder) + if wim_contains(source_wim, folder): + registry_items.append(folder) + if registry_items: + selected_items.append({ + 'Message': '{}Registry...'.format(rel_path), + 'Items': registry_items.copy(), + 'Destination': dest_path}) + + # Windows.old(s) + for old in win_olds: + scan_source_wim(source_wim, dest_path, rel_path=old, interactive=False) + + # Done + return selected_items + +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) + + # Avoid merging with existing folder + path = non_clobber_rename(path) + os.makedirs(path, exist_ok=True) + + return path + +def select_source(ticket_number): + """Select backup from those found on the BACKUP_SERVERS for the ticket.""" + selected_source = None + local_sources = [] + remote_sources = [] + sources = [] + mount_backup_shares() + + # Check for ticket 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(ticket_number.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 ticket_path in remote_sources.copy(): + for item in os.scandir(ticket_path['Source'].path): + if item.is_dir(): + # Add folder to remote_sources + remote_sources.append({ + 'Name': r'{:9}| File-Based: [DIR] {}\{}'.format( + ticket_path['Server']['Name'], # Server + ticket_path['Source'].name, # Ticket folder + item.name, # Sub-folder + ), + 'Server': ticket_path['Server'], + 'Sort': r'{}\{}'.format( + ticket_path['Source'].name, # Ticket 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( + ticket_path['Server']['Name'], # Server + size, # Size (duh) + ticket_path['Source'].name, # Ticket folder + item.name, # Sub-folder + subitem.name, # Image file + ), + 'Server': ticket_path['Server'], + 'Sort': r'{}\{}\{}'.format( + ticket_path['Source'].name, # Ticket 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( + ticket_path['Server']['Name'], # Server + size, # Size (duh) + ticket_path['Source'].name, # Ticket folder + item.name, # Image file + ), + 'Server': ticket_path['Server'], + 'Sort': r'{}\{}'.format( + ticket_path['Source'].name, # Ticket 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)}) + 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'}] + + # 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'] + else: + print_error('ERROR: No backups found for ticket: {}.'.format( + ticket_number)) + umount_backup_shares() + pause("Press Enter to exit...") + exit_script() + + # 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 = [] + + # 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() + else: + return disks[int(selection)-1] + +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: + 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']) + 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=group['Destination']) + else: + print_error('ERROR: Unsupported image: {}'.format(source_obj.path)) + raise GenericError + +def umount_backup_shares(): + """Unnount the backup shares regardless of current status.""" + for server in BACKUP_SERVERS: + umount_network_share(server) + +def umount_network_share(server): + """Unnount 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 + +def wim_contains(source_path, file_path): + """Check if the WIM contains a file or folder.""" + _cmd = [ + global_vars['Tools']['wimlib-imagex'], 'dir', + source_path, '1', + '--path={}'.format(file_path), + '--one-file-only'] + try: + run_program(_cmd) + except subprocess.CalledProcessError: + return False + else: + return True + +if __name__ == '__main__': + print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/functions/diags.py b/.bin/Scripts/functions/diags.py index e6bc433f..220eaff3 100644 --- a/.bin/Scripts/functions/diags.py +++ b/.bin/Scripts/functions/diags.py @@ -1,114 +1,114 @@ -# Wizard Kit: Functions - Diagnostics - -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, - }, - } - -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 - else: - if not ask('ERROR: System appears offline, try again?'): - if ask('Continue anyway?'): - break - else: - abort() - -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) - -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']) - -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)] - 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}\hitman.xml'.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) - -def run_rkill(): - """Run RKill and cleanup afterwards.""" - extract_item('RKill', silent=True) - cmd = [ - global_vars['Tools']['RKill'], - '-l', r'{LogDir}\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( - name=dest, **global_vars) - dest = non_clobber_rename(dest) - shutil.move(item.path, dest) - -if __name__ == '__main__': - print("This file is not meant to be called directly.") +# Wizard Kit: Functions - Diagnostics + +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, + }, + } + +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 + else: + if not ask('ERROR: System appears offline, try again?'): + if ask('Continue anyway?'): + break + else: + abort() + +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) + +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']) + +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)] + 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}\hitman.xml'.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) + +def run_rkill(): + """Run RKill and cleanup afterwards.""" + extract_item('RKill', silent=True) + cmd = [ + global_vars['Tools']['RKill'], + '-l', r'{LogDir}\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( + name=dest, **global_vars) + dest = non_clobber_rename(dest) + shutil.move(item.path, dest) + +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 new file mode 100644 index 00000000..8b2c164e --- /dev/null +++ b/.bin/Scripts/functions/hw_diags.py @@ -0,0 +1,655 @@ +# Wizard Kit: Functions - HW Diagnostics + +import json + +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: {'Error': 1}, + 9: {'Warning': 12000, 'Error': 18000, 'Ignore': True}, + 10: {'Warning': 1}, + 184: {'Error': 1}, + 187: {'Warning': 1}, + 188: {'Warning': 1}, + 197: {'Error': 1}, + 198: {'Error': 1}, + 201: {'Warning': 1}, + }, + } +TESTS = { + 'Prime95': { + 'Enabled': False, + 'Status': 'Pending', + }, + 'NVMe/SMART': { + 'Enabled': False, + 'Quick': False, + 'Status': {}, + }, + 'badblocks': { + 'Enabled': False, + 'Results': {}, + 'Status': {}, + }, + } + +def get_smart_details(dev): + cmd = 'sudo smartctl --all --json /dev/{}'.format(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_status_color(s): + color = COLORS['CLEAR'] + if s in ['Denied', 'NS', 'OVERRIDE', 'Unknown']: + color = COLORS['RED'] + elif s in ['Aborted', 'Working', 'Skipped']: + color = COLORS['YELLOW'] + elif s in ['CS']: + color = COLORS['GREEN'] + return color + +def menu_diags(*args): + diag_modes = [ + {'Name': 'All tests', + 'Tests': ['Prime95', 'NVMe/SMART', 'badblocks']}, + {'Name': 'Prime95', + 'Tests': ['Prime95']}, + {'Name': 'NVMe/SMART & badblocks', + 'Tests': ['NVMe/SMART', 'badblocks']}, + {'Name': 'NVMe/SMART', + 'Tests': ['NVMe/SMART']}, + {'Name': 'badblocks', + 'Tests': ['badblocks']}, + {'Name': 'Quick drive test', + 'Tests': ['Quick', 'NVMe/SMART']}, + ] + actions = [ + {'Letter': 'A', 'Name': 'Audio 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}, + ] + + # 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(): + if diag_modes[int(selection)-1]['Name'] != 'Quick drive test': + # Save log for non-quick tests + ticket_number = get_ticket_number() + global_vars['LogDir'] = '{}/Tickets/{}'.format( + global_vars['Env']['HOME'], + ticket_number) + 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']) + elif selection == 'A': + run_program(['hw-diags-audio'], check=False, pipe=False) + pause('Press Enter to return to main menu... ') + 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 == 'Q': + break + +def run_badblocks(): + 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 + 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)) + update_progress() + + # Done + run_program('tmux kill-pane -a'.split(), check=False) + pass + +def run_mprime(): + aborted = False + clear_screen() + 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']) + print_standard('Running Prime95 for {} minutes'.format(MPRIME_LIMIT)) + print_warning('If running too hot, press CTL+c to abort the test') + try: + sleep(int(MPRIME_LIMIT)*60) + except KeyboardInterrupt: + # Catch CTL+C + aborted = True + + # 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 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 TESTS['Prime95']['NS']: + TESTS['Prime95']['Status'] = 'NS' + elif TESTS['Prime95']['CS']: + TESTS['Prime95']['Status'] = 'CS' + else: + TESTS['Prime95']['Status'] = 'Unknown' + update_progress() + + # Done + run_program('tmux kill-pane -a'.split()) + +def run_nvme_smart(): + 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()): + 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' + else: + TESTS['NVMe/SMART']['Status'][name] = 'NS' + update_progress() + print_standard('Done', timestamp=False) + + # Done + run_program('tmux kill-pane -a'.split(), check=False) + +def run_tests(tests): + print_log('Starting Hardware Diagnostics') + print_log('\nRunning tests: {}'.format(', '.join(tests))) + # Enable selected tests + for t in ['Prime95', 'NVMe/SMART', 'badblocks']: + TESTS[t]['Enabled'] = t in tests + TESTS['NVMe/SMART']['Quick'] = 'Quick' in tests + + # Initialize + if TESTS['NVMe/SMART']['Enabled'] or TESTS['badblocks']['Enabled']: + scan_disks() + update_progress() + + # Run + mprime_aborted = False + if TESTS['Prime95']['Enabled']: + try: + run_mprime() + except GenericError: + mprime_aborted = True + if not mprime_aborted: + if TESTS['NVMe/SMART']['Enabled']: + run_nvme_smart() + if TESTS['badblocks']['Enabled']: + run_badblocks() + + # Show results + show_results() + + # Open log + if not TESTS['NVMe/SMART']['Quick']: + try: + popen_program(['nohup', 'leafpad', global_vars['LogFile']]) + except Exception: + print_error('ERROR: Failed to open log: {}'.format( + global_vars['LogFile'])) + pause('Press Enter to exit...') + +def scan_disks(): + clear_screen() + + # Get eligible disk list + result = run_program(['lsblk', '-J', '-O']) + json_data = json.loads(result.stdout.decode()) + devs = {} + for d in json_data.get('blockdevices', []): + if d['type'] == 'disk' and d['hotplug'] == '0': + devs[d['name']] = {'lsblk': d} + TESTS['NVMe/SMART']['Status'][d['name']] = 'Pending' + TESTS['badblocks']['Status'][d['name']] = 'Pending' + + for dev, data in devs.items(): + # Get SMART attributes + run_program( + cmd = 'sudo smartctl -s on /dev/{}'.format(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() + 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) + data['Quick Health OK'] = True if crit_warn == 0 else 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 not data['Quick Health OK'] and TESTS['badblocks']['Enabled']: + show_disk_details(data) + print_warning("WARNING: Health can't be confirmed for: {}".format( + '/dev/{}'.format(dev))) + dev_name = data['lsblk']['name'] + print_standard(' ') + if ask('Run badblocks for this device anyway?'): + TESTS['NVMe/SMART']['Status'][dev_name] = 'OVERRIDE' + else: + TESTS['NVMe/SMART']['Status'][dev_name] = 'NS' + TESTS['badblocks']['Status'][dev_name] = 'Denied' + print_standard(' ') # In case there's more than one "OVERRIDE" disk + + TESTS['NVMe/SMART']['Devices'] = devs + TESTS['badblocks']['Devices'] = devs + +def show_disk_details(dev): + dev_name = dev['lsblk']['name'] + # Device description + print_info('Device: /dev/{}'.format(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): + 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 + 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(): + 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 + if TESTS['NVMe/SMART']['Enabled'] or TESTS['badblocks']['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)) + print_standard(' ') + + # Done + pause('Press Enter to return to main menu... ') + run_program('tmux kill-pane -a'.split()) + +def update_progress(): + 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)) + + # Add line-endings + output = ['{}\n'.format(line) for line in output] + + with open(TESTS['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 c636a0f7..3c882333 100644 --- a/.bin/Scripts/functions/info.py +++ b/.bin/Scripts/functions/info.py @@ -1,467 +1,467 @@ -# Wizard Kit: Functions - Information - -from borrowed import knownpaths -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' -REG_SHELL_FOLDERS = r'Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders' -TMP_HIVE_PATH = 'TEMP_HIVE_MOUNT' -EXTRA_FOLDERS = [ - '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}', - ), -} - -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) - -def backup_power_plans(): - """Export current power plans.""" - os.makedirs(r'{BackupDir}\Power Plans'.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\{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(): - """Backup registry including user hives.""" - extract_item('erunt', silent=True) - cmd = [ - global_vars['Tools']['ERUNT'], - r'{BackupDir}\Registry'.format(**global_vars), - 'sysreg', - 'curuser', - 'otherusers', - '/noprogresswindow'] - run_program(cmd) - -def get_folder_size(path): - """Get (human-readable) size of folder passed, returns str.""" - size = 'Unknown' - cmd = [global_vars['Tools']['Du'], '-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: - size = out.stdout.decode().splitlines()[4] - size = re.sub(r'Size:\s+([\d,]+)\sbytes$', r'\1', size) - size = size.replace(',', '') - size = human_readable_size(size) - return size - -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()) - - 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. - - 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: - 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): - """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 - - # 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: - 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 - 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} - - # 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) - - 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 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 - -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) - - # 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) - -def run_bleachbit(): - """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(): - 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) - -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 - -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) - -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) - -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) - else: - if re.search(r'(unrecognized|very outdated)', 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) - -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: - 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: - 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]['Size'], - path = folders[folder]['Path'])) - -if __name__ == '__main__': - print("This file is not meant to be called directly.") +# Wizard Kit: Functions - Information + +from borrowed import knownpaths +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' +REG_SHELL_FOLDERS = r'Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders' +TMP_HIVE_PATH = 'TEMP_HIVE_MOUNT' +EXTRA_FOLDERS = [ + '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}', + ), +} + +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) + +def backup_power_plans(): + """Export current power plans.""" + os.makedirs(r'{BackupDir}\Power Plans'.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\{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(): + """Backup registry including user hives.""" + extract_item('erunt', silent=True) + cmd = [ + global_vars['Tools']['ERUNT'], + r'{BackupDir}\Registry'.format(**global_vars), + 'sysreg', + 'curuser', + 'otherusers', + '/noprogresswindow'] + run_program(cmd) + +def get_folder_size(path): + """Get (human-readable) size of folder passed, returns str.""" + size = 'Unknown' + cmd = [global_vars['Tools']['Du'], '-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: + size = out.stdout.decode().splitlines()[4] + size = re.sub(r'Size:\s+([\d,]+)\sbytes$', r'\1', size) + size = size.replace(',', '') + size = human_readable_size(size) + return size + +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()) + + 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. + + 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: + 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): + """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 + + # 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: + 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 + 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} + + # 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) + + 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 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 + +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) + + # 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) + +def run_bleachbit(): + """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(): + 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) + +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 + +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) + +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) + +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) + else: + if re.search(r'(unrecognized|very outdated)', 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) + +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: + 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: + 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]['Size'], + path = folders[folder]['Path'])) + +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 new file mode 100644 index 00000000..1f987248 --- /dev/null +++ b/.bin/Scripts/functions/network.py @@ -0,0 +1,81 @@ +#!/bin/python3 +# +## Wizard Kit: Functions - Network + +import os +import sys + +# Init +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+' + 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()] + + # Bail if currently connected + if is_connected(): + return + + # LAN + if 'en' in net_ifs: + # Reload the tg3/broadcom driver (known fix for some Dell systems) + try_and_print(message='Reloading drivers...', function=reload_tg3) + + # WiFi + if not is_connected() and '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 + +def show_valid_addresses(): + 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(): + 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] + +def reload_tg3(): + """Reload tg3 module as a workaround for some Dell systems.""" + run_program(['sudo', 'modprobe', '-r', 'tg3']) + run_program(['sudo', 'modprobe', 'broadcom']) + run_program(['sudo', 'modprobe', 'tg3']) + sleep(5) + +if __name__ == '__main__': + print("This file is not meant to be called directly.") + diff --git a/.bin/Scripts/functions/partition_uids.py b/.bin/Scripts/functions/partition_uids.py index da94a18a..38fba0db 100644 --- a/.bin/Scripts/functions/partition_uids.py +++ b/.bin/Scripts/functions/partition_uids.py @@ -1,326 +1,326 @@ -# 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.") +# 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/functions/product_keys.py b/.bin/Scripts/functions/product_keys.py index 514d44fb..705f46e9 100644 --- a/.bin/Scripts/functions/product_keys.py +++ b/.bin/Scripts/functions/product_keys.py @@ -1,111 +1,111 @@ -# Wizard Kit: Functions - Product Keys - -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 = {} - - # 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 - -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.') - - return key_list - -def find_software_hives(): - """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) - - 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) - - 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) - -if __name__ == '__main__': - print("This file is not meant to be called directly.") +# Wizard Kit: Functions - Product Keys + +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 = {} + + # 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 + +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.') + + return key_list + +def find_software_hives(): + """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) + + 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) + + 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) + +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 5b9d5f16..bf9c3cdd 100644 --- a/.bin/Scripts/functions/repairs.py +++ b/.bin/Scripts/functions/repairs.py @@ -1,126 +1,126 @@ -# Wizard Kit: Functions - Repairs - -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() - -def run_chkdsk_scan(): - """Run CHKDSK in a "split window" and report errors.""" - if global_vars['OS']['Version'] in ['8', '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}\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: - 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 - -def run_dism(repair=False): - """Run DISM /RestoreHealth, then /CheckHealth, and then report errors.""" - if global_vars['OS']['Version'] in ['8', '10']: - if repair: - # Restore Health - cmd = [ - 'DISM', '/Online', - '/Cleanup-Image', '/RestoreHealth', - r'/LogPath:"{LogDir}\DISM_RestoreHealth.log"'.format( - **global_vars), - '-new_console:n', '-new_console:s33V'] - else: - # Scan Health - cmd = [ - 'DISM', '/Online', - '/Cleanup-Image', '/ScanHealth', - r'/LogPath:"{LogDir}\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}\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) - -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}\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: - 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}\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.") +# Wizard Kit: Functions - Repairs + +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() + +def run_chkdsk_scan(): + """Run CHKDSK in a "split window" and report errors.""" + if global_vars['OS']['Version'] in ['8', '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}\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: + 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 + +def run_dism(repair=False): + """Run DISM /RestoreHealth, then /CheckHealth, and then report errors.""" + if global_vars['OS']['Version'] in ['8', '10']: + if repair: + # Restore Health + cmd = [ + 'DISM', '/Online', + '/Cleanup-Image', '/RestoreHealth', + r'/LogPath:"{LogDir}\DISM_RestoreHealth.log"'.format( + **global_vars), + '-new_console:n', '-new_console:s33V'] + else: + # Scan Health + cmd = [ + 'DISM', '/Online', + '/Cleanup-Image', '/ScanHealth', + r'/LogPath:"{LogDir}\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}\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) + +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}\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: + 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}\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.") diff --git a/.bin/Scripts/functions/setup.py b/.bin/Scripts/functions/setup.py index 0d115426..41ca3340 100644 --- a/.bin/Scripts/functions/setup.py +++ b/.bin/Scripts/functions/setup.py @@ -1,272 +1,272 @@ -# Wizard Kit: Functions - Setup - -from functions.common import * - -# STATIC VARIABLES -HKCU = winreg.HKEY_CURRENT_USER -HKLM = winreg.HKEY_LOCAL_MACHINE -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', - }, - }, - } -SETTINGS_EXPLORER_SYSTEM = { - # 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}, - }, - } -SETTINGS_EXPLORER_USER = { - # Disable Cortana - r'Software\Microsoft\Personalization\Settings': { - 'DWORD Items': {'AcceptedPrivacyPolicy': 0}, - }, - r'Software\Microsoft\InputPersonalization': { - 'DWORD Items': { - 'RestrictImplicitTextCollection': 1, - 'RestrictImplicitInkCollection': 1 - }, - }, - r'Software\Microsoft\InputPersonalization\TrainedDataStore': { - 'DWORD Items': {'HarvestContacts': 1}, - }, - # 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': { - '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, - }, - } -VCR_REDISTS = [ - {'Name': 'Visual C++ 2008 SP1 x32...', - 'Cmd': [r'2008sp1\x32\vcredist.exe', '/qb! /norestart']}, - {'Name': 'Visual C++ 2008 SP1 x64...', - 'Cmd': [r'2008sp1\x64\vcredist.exe', '/qb! /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) - - # 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, '') - - # 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) - -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) - -def config_explorer_user(): - """Configure Windows Explorer for current user via Registry settings.""" - write_registry_settings(SETTINGS_EXPLORER_USER, all_users=False) - -def update_clock(): - """Set Timezone and sync clock.""" - run_program(['tzutil' ,'/s', 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) - -# 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'] - try_and_print(message='Adobe Reader DC...', function=run_program, cmd=cmd) - -def install_chrome_extensions(): - """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', '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(): - """Extract Firefox extensions to installation folder.""" - dist_path = r'{PROGRAMFILES}\Mozilla Firefox\distribution\extensions'.format( - **global_vars['Env']) - # Extract extension(s) to distribution folder - cmd = [ - global_vars['Tools']['SevenZip'], 'x', '-aos', '-bso0', '-bse0', - '-p{ArchivePassword}'.format(**global_vars), - '-o{dist_path}'.format(dist_path=dist_path), - r'{CBinDir}\FirefoxExtensions.7z'.format(**global_vars)] - run_program(cmd) - -def install_ninite_bundle(mse=False): - """Run Ninite file(s) based on OS version.""" - if global_vars['OS']['Version'] in ['8', '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() - os.chdir(r'{BinDir}\_vcredists'.format(**global_vars)) - for vcr in VCR_REDISTS: - try_and_print(message=vcr['Name'], function=run_program, cmd=vcr['Cmd']) - - os.chdir(prev_dir) - -if __name__ == '__main__': - print("This file is not meant to be called directly.") +# Wizard Kit: Functions - Setup + +from functions.common import * + +# STATIC VARIABLES +HKCU = winreg.HKEY_CURRENT_USER +HKLM = winreg.HKEY_LOCAL_MACHINE +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', + }, + }, + } +SETTINGS_EXPLORER_SYSTEM = { + # 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}, + }, + } +SETTINGS_EXPLORER_USER = { + # Disable Cortana + r'Software\Microsoft\Personalization\Settings': { + 'DWORD Items': {'AcceptedPrivacyPolicy': 0}, + }, + r'Software\Microsoft\InputPersonalization': { + 'DWORD Items': { + 'RestrictImplicitTextCollection': 1, + 'RestrictImplicitInkCollection': 1 + }, + }, + r'Software\Microsoft\InputPersonalization\TrainedDataStore': { + 'DWORD Items': {'HarvestContacts': 1}, + }, + # 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': { + '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, + }, + } +VCR_REDISTS = [ + {'Name': 'Visual C++ 2008 SP1 x32...', + 'Cmd': [r'2008sp1\x32\vcredist.exe', '/qb! /norestart']}, + {'Name': 'Visual C++ 2008 SP1 x64...', + 'Cmd': [r'2008sp1\x64\vcredist.exe', '/qb! /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) + + # 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, '') + + # 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) + +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) + +def config_explorer_user(): + """Configure Windows Explorer for current user via Registry settings.""" + write_registry_settings(SETTINGS_EXPLORER_USER, all_users=False) + +def update_clock(): + """Set Timezone and sync clock.""" + run_program(['tzutil' ,'/s', 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) + +# 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'] + try_and_print(message='Adobe Reader DC...', function=run_program, cmd=cmd) + +def install_chrome_extensions(): + """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', '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(): + """Extract Firefox extensions to installation folder.""" + dist_path = r'{PROGRAMFILES}\Mozilla Firefox\distribution\extensions'.format( + **global_vars['Env']) + # Extract extension(s) to distribution folder + cmd = [ + global_vars['Tools']['SevenZip'], 'x', '-aos', '-bso0', '-bse0', + '-p{ArchivePassword}'.format(**global_vars), + '-o{dist_path}'.format(dist_path=dist_path), + r'{CBinDir}\FirefoxExtensions.7z'.format(**global_vars)] + run_program(cmd) + +def install_ninite_bundle(mse=False): + """Run Ninite file(s) based on OS version.""" + if global_vars['OS']['Version'] in ['8', '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() + os.chdir(r'{BinDir}\_vcredists'.format(**global_vars)) + for vcr in VCR_REDISTS: + try_and_print(message=vcr['Name'], function=run_program, cmd=vcr['Cmd']) + + os.chdir(prev_dir) + +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 ad1cf00e..813e6df2 100644 --- a/.bin/Scripts/functions/update.py +++ b/.bin/Scripts/functions/update.py @@ -1,895 +1,895 @@ -# Wizard Kit: Functions - Build / Update - -import requests - -from functions.common import * -from functions.data import * -from settings.launchers import * -from settings.music import * -from settings.sources import * - -def compress_and_remove_item(item): - try: - compress_item(item) - except: - raise GenericError - else: - remove_item(item.path) - -def compress_item(item): - # 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) - - # 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.') - -def download_to_temp(out_name, source_url): - download_generic(global_vars['TmpDir'], out_name, source_url) - -def extract_generic(source, dest, mode='x', sz_args=[]): - 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=[]): - 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=[]): - 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): - # 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])] - - # 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)) - -def remove_item(item_path): - 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): - item_locations = [] - for p in [global_vars['BinDir'], global_vars['CBinDir']]: - item_locations.append(r'{}\{}'.format(p, item)) - item_locations.append(r'{}\_Drivers\{}'.format(p, item)) - for item_path in item_locations: - remove_item(item_path) - -def remove_from_temp(item): - 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 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 - -def scan_for_net_installers(server, family_name, min_year): - 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 - 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') - - # 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'])) - - # 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) - - # Remove existing folders - remove_from_kit('FastCopy') - - # Download - download_to_temp('FastCopy32.zip', SOURCE_URLS['FastCopy32']) - download_to_temp('FastCopy64.zip', SOURCE_URLS['FastCopy64']) - - # Extract - extract_temp_to_bin('FastCopy64.zip', 'FastCopy', sz_args=['FastCopy.exe']) - shutil.move( - r'{}\FastCopy\FastCopy.exe'.format(global_vars['BinDir']), - r'{}\FastCopy\FastCopy64.exe'.format(global_vars['BinDir'])) - extract_temp_to_bin('FastCopy32.zip', 'FastCopy', sz_args=[r'-x!setup.exe', r'-x!*.dll']) - - # Cleanup - remove_from_temp('FastCopy32.zip') - remove_from_temp('FastCopy64.zip') - -def update_wimlib(): - # Stop running processes - kill_process('wimlib-imagex.exe') - - # Remove existing folders - remove_from_kit('wimlib') - - # 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'])) - - # Cleanup - remove_from_temp('wimlib32.zip') - remove_from_temp('wimlib64.zip') - -def update_xyplorer(): - # Stop running processes - kill_process('XYplorerFree.exe') - - # Remove existing folders - remove_from_kit('XYplorerFree') - - # Download - download_to_temp('xyplorer_free.zip', SOURCE_URLS['XYplorerFree']) - - # Extract files - extract_temp_to_cbin('xyplorer_free.zip', 'XYplorerFree') - - # Cleanup - remove_from_temp('xyplorer_free.zip') - -## Diagnostics ## -def update_aida64(): - # Stop running processes - kill_process('notepadplusplus.exe') - - # Remove existing folders - remove_from_kit('AIDA64') - - # Download - download_to_temp('aida64.zip', SOURCE_URLS['AIDA64']) - - # Extract files - extract_temp_to_cbin('aida64.zip', 'AIDA64') - - # Cleanup - remove_from_temp('aida64.zip') - -def update_autoruns(): - # Stop running processes - kill_process('Autoruns.exe') - kill_process('Autoruns64.exe') - - # Remove existing folders - remove_from_kit('Autoruns') - - # Download - download_to_temp('Autoruns.zip', SOURCE_URLS['Autoruns']) - - # Extract files - extract_temp_to_cbin('Autoruns.zip', 'Autoruns') - - # Cleanup - remove_from_temp('Autoruns.zip') - -def update_bleachbit(): - # Stop running processes - kill_process('bleachbit.exe') - - # Remove existing folders - remove_from_kit('BleachBit') - - # 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']) - - # 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') - -def update_bluescreenview(): - # Stop running processes - for exe in ['BlueScreenView.exe', 'BlueScreenView64.exe']: - kill_process(exe) - - # Remove existing folders - remove_from_kit('BlueScreenView') - - # 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') - - # Cleanup - remove_from_temp('bluescreenview32.zip') - remove_from_temp('bluescreenview64.zip') - -def update_erunt(): - # Stop running processes - kill_process('ERUNT.EXE') - - # Remove existing folders - remove_from_kit('ERUNT') - - # Download - download_to_temp('erunt.zip', SOURCE_URLS['ERUNT']) - - # Extract files - extract_temp_to_cbin('erunt.zip', 'ERUNT') - - # Cleanup - remove_from_temp('erunt.zip') - -def update_hitmanpro(): - # Stop running processes - for exe in ['HitmanPro.exe', 'HitmanPro64.exe']: - kill_process(exe) - - # 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']) - -def update_hwinfo(): - ## NOTE: Lives in .bin uncompressed - # Stop running processes - for exe in ['HWiNFO32.exe', 'HWiNFO64.exe']: - kill_process(exe) - - # Download - download_to_temp('HWiNFO32.zip', SOURCE_URLS['HWiNFO32']) - download_to_temp('HWiNFO64.zip', SOURCE_URLS['HWiNFO64']) - - # Extract files - extract_temp_to_bin('HWiNFO32.zip', 'HWiNFO') - extract_temp_to_bin('HWiNFO64.zip', 'HWiNFO') - - # Cleanup - remove_from_temp('HWiNFO32.zip') - remove_from_temp('HWiNFO64.zip') - -def update_produkey(): - # Stop running processes - for exe in ['ProduKey.exe', 'ProduKey64.exe']: - kill_process(exe) - - # Remove existing folders - remove_from_kit('ProduKey') - - # 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') - - # Cleanup - remove_from_temp('produkey32.zip') - remove_from_temp('produkey64.zip') - -## Drivers ## -def update_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) - - # 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') - - # 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') - - # Download - download_generic( - r'{}\_Drivers\Samsung Magician'.format(global_vars['CBinDir']), - 'Samsung Magician.exe', - SOURCE_URLS['Samsung Magician']) - -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') - - # 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 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) - - # 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']) - - # 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']) - -def update_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) - - # Download and extract - for year in ['2013', '2016']: - 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('odt2013.exe') - remove_from_temp('odt2016.exe') - -def update_classic_start_skin(): - # Remove existing folders - remove_from_kit('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') - - # 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]) - -def update_one_ninite(section, dest, name, url, indent=8, width=40): - # Prep - url = 'https://ninite.com/{}/ninite.exe'.format(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) - -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) - -## Misc ## -def update_caffeine(): - # Stop running processes - kill_process('caffeine.exe') - - # Remove existing folders - remove_from_kit('Caffeine') - - # Download - download_to_temp('caffeine.zip', SOURCE_URLS['Caffeine']) - - # Extract files - extract_temp_to_cbin('caffeine.zip', 'Caffeine') - - # Cleanup - remove_from_temp('caffeine.zip') - -def update_du(): - # Stop running processes - kill_process('du.exe') - kill_process('du64.exe') - - # Remove existing folders - remove_from_kit('Du') - - # Download - download_to_temp('du.zip', SOURCE_URLS['Du']) - - # Extract files - extract_temp_to_cbin('du.zip', 'Du') - - # Cleanup - remove_from_temp('du.zip') - -def update_everything(): - # Stop running processes - for exe in ['Everything.exe', 'Everything64.exe']: - kill_process(exe) - - # Remove existing folders - remove_from_kit('Everything') - - # 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') - - # Cleanup - remove_from_temp('everything32.zip') - remove_from_temp('everything64.zip') - -def update_firefox_ublock_origin(): - # Remove existing folders - remove_from_kit('FirefoxExtensions') - - # Download - download_to_temp('ff-uBO.xpi', SOURCE_URLS['Firefox uBO']) - - # Extract files - extract_generic( - r'{}\ff-uBO.xpi'.format(global_vars['TmpDir']), - r'{}\FirefoxExtensions\uBlock0@raymondhill.net'.format( - global_vars['CBinDir'])) - - # Cleanup - remove_from_temp('ff-uBO.xpi') - -def update_notepadplusplus(): - # Stop running processes - kill_process('notepadplusplus.exe') - - # Remove existing folders - remove_from_kit('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']) - ) - - # Cleanup - remove_from_temp('npp.7z') - -def update_putty(): - # Stop running processes - kill_process('PUTTY.EXE') - - # Remove existing folders - remove_from_kit('PuTTY') - - # Download - download_to_temp('putty.zip', SOURCE_URLS['PuTTY']) - - # Extract files - extract_temp_to_cbin('putty.zip', 'PuTTY') - - # Cleanup - remove_from_temp('putty.zip') - -def update_treesizefree(): - # Stop running processes - kill_process('TreeSizeFree.exe') - - # Remove existing folders - remove_from_kit('TreeSizeFree') - - # Download - download_to_temp( - 'treesizefree.zip.gz', SOURCE_URLS['TreeSizeFree']) - - # Extract files - ## NOTE: When downloaded using requests it is a .zip.gz? - source = r'{}\treesizefree.zip.gz'.format(global_vars['TmpDir']) - extract_generic(source, global_vars['TmpDir']) - extract_temp_to_cbin('treesizefree.zip', 'TreeSizeFree') - - # Cleanup - remove_from_temp('treesizefree.zip') - remove_from_temp('treesizefree.zip.gz') - -def update_xmplay(): - # Stop running processes - kill_process('xmplay.exe') - - # 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']) - - # 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) - - # 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') - -## Repairs ## -def update_adwcleaner(): - # Stop running processes - kill_process('AdwCleaner.exe') - - # Remove existing folders - remove_from_kit('AdwCleaner') - - # Download - url = resolve_dynamic_url( - SOURCE_URLS['AdwCleaner'], - 'id="downloadLink"') - download_generic( - r'{}\AdwCleaner'.format(global_vars['CBinDir']), 'AdwCleaner.exe', url) - -def update_kvrt(): - # Stop running processes - kill_process('KVRT.exe') - - # Remove existing folders - remove_from_kit('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') - - # 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) - -def update_tdsskiller(): - # Stop running processes - kill_process('TDSSKiller.exe') - - # Remove existing folders - remove_from_kit('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') - - # Remove existing folders - remove_from_kit('IObitUninstallerPortable') - - # 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') - - # Cleanup - remove_from_kit('IObitUninstallerPortable.exe') - -if __name__ == '__main__': - print("This file is not meant to be called directly.") +# Wizard Kit: Functions - Build / Update + +import requests + +from functions.common import * +from functions.data import * +from settings.launchers import * +from settings.music import * +from settings.sources import * + +def compress_and_remove_item(item): + try: + compress_item(item) + except: + raise GenericError + else: + remove_item(item.path) + +def compress_item(item): + # 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) + + # 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.') + +def download_to_temp(out_name, source_url): + download_generic(global_vars['TmpDir'], out_name, source_url) + +def extract_generic(source, dest, mode='x', sz_args=[]): + 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=[]): + 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=[]): + 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): + # 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])] + + # 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)) + +def remove_item(item_path): + 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): + item_locations = [] + for p in [global_vars['BinDir'], global_vars['CBinDir']]: + item_locations.append(r'{}\{}'.format(p, item)) + item_locations.append(r'{}\_Drivers\{}'.format(p, item)) + for item_path in item_locations: + remove_item(item_path) + +def remove_from_temp(item): + 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 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 + +def scan_for_net_installers(server, family_name, min_year): + 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 + 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') + + # 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'])) + + # 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) + + # Remove existing folders + remove_from_kit('FastCopy') + + # Download + download_to_temp('FastCopy32.zip', SOURCE_URLS['FastCopy32']) + download_to_temp('FastCopy64.zip', SOURCE_URLS['FastCopy64']) + + # Extract + extract_temp_to_bin('FastCopy64.zip', 'FastCopy', sz_args=['FastCopy.exe']) + shutil.move( + r'{}\FastCopy\FastCopy.exe'.format(global_vars['BinDir']), + r'{}\FastCopy\FastCopy64.exe'.format(global_vars['BinDir'])) + extract_temp_to_bin('FastCopy32.zip', 'FastCopy', sz_args=[r'-x!setup.exe', r'-x!*.dll']) + + # Cleanup + remove_from_temp('FastCopy32.zip') + remove_from_temp('FastCopy64.zip') + +def update_wimlib(): + # Stop running processes + kill_process('wimlib-imagex.exe') + + # Remove existing folders + remove_from_kit('wimlib') + + # 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'])) + + # Cleanup + remove_from_temp('wimlib32.zip') + remove_from_temp('wimlib64.zip') + +def update_xyplorer(): + # Stop running processes + kill_process('XYplorerFree.exe') + + # Remove existing folders + remove_from_kit('XYplorerFree') + + # Download + download_to_temp('xyplorer_free.zip', SOURCE_URLS['XYplorerFree']) + + # Extract files + extract_temp_to_cbin('xyplorer_free.zip', 'XYplorerFree') + + # Cleanup + remove_from_temp('xyplorer_free.zip') + +## Diagnostics ## +def update_aida64(): + # Stop running processes + kill_process('notepadplusplus.exe') + + # Remove existing folders + remove_from_kit('AIDA64') + + # Download + download_to_temp('aida64.zip', SOURCE_URLS['AIDA64']) + + # Extract files + extract_temp_to_cbin('aida64.zip', 'AIDA64') + + # Cleanup + remove_from_temp('aida64.zip') + +def update_autoruns(): + # Stop running processes + kill_process('Autoruns.exe') + kill_process('Autoruns64.exe') + + # Remove existing folders + remove_from_kit('Autoruns') + + # Download + download_to_temp('Autoruns.zip', SOURCE_URLS['Autoruns']) + + # Extract files + extract_temp_to_cbin('Autoruns.zip', 'Autoruns') + + # Cleanup + remove_from_temp('Autoruns.zip') + +def update_bleachbit(): + # Stop running processes + kill_process('bleachbit.exe') + + # Remove existing folders + remove_from_kit('BleachBit') + + # 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']) + + # 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') + +def update_bluescreenview(): + # Stop running processes + for exe in ['BlueScreenView.exe', 'BlueScreenView64.exe']: + kill_process(exe) + + # Remove existing folders + remove_from_kit('BlueScreenView') + + # 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') + + # Cleanup + remove_from_temp('bluescreenview32.zip') + remove_from_temp('bluescreenview64.zip') + +def update_erunt(): + # Stop running processes + kill_process('ERUNT.EXE') + + # Remove existing folders + remove_from_kit('ERUNT') + + # Download + download_to_temp('erunt.zip', SOURCE_URLS['ERUNT']) + + # Extract files + extract_temp_to_cbin('erunt.zip', 'ERUNT') + + # Cleanup + remove_from_temp('erunt.zip') + +def update_hitmanpro(): + # Stop running processes + for exe in ['HitmanPro.exe', 'HitmanPro64.exe']: + kill_process(exe) + + # 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']) + +def update_hwinfo(): + ## NOTE: Lives in .bin uncompressed + # Stop running processes + for exe in ['HWiNFO32.exe', 'HWiNFO64.exe']: + kill_process(exe) + + # Download + download_to_temp('HWiNFO32.zip', SOURCE_URLS['HWiNFO32']) + download_to_temp('HWiNFO64.zip', SOURCE_URLS['HWiNFO64']) + + # Extract files + extract_temp_to_bin('HWiNFO32.zip', 'HWiNFO') + extract_temp_to_bin('HWiNFO64.zip', 'HWiNFO') + + # Cleanup + remove_from_temp('HWiNFO32.zip') + remove_from_temp('HWiNFO64.zip') + +def update_produkey(): + # Stop running processes + for exe in ['ProduKey.exe', 'ProduKey64.exe']: + kill_process(exe) + + # Remove existing folders + remove_from_kit('ProduKey') + + # 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') + + # Cleanup + remove_from_temp('produkey32.zip') + remove_from_temp('produkey64.zip') + +## Drivers ## +def update_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) + + # 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') + + # 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') + + # Download + download_generic( + r'{}\_Drivers\Samsung Magician'.format(global_vars['CBinDir']), + 'Samsung Magician.exe', + SOURCE_URLS['Samsung Magician']) + +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') + + # 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 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) + + # 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']) + + # 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']) + +def update_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) + + # Download and extract + for year in ['2013', '2016']: + 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('odt2013.exe') + remove_from_temp('odt2016.exe') + +def update_classic_start_skin(): + # Remove existing folders + remove_from_kit('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') + + # 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]) + +def update_one_ninite(section, dest, name, url, indent=8, width=40): + # Prep + url = 'https://ninite.com/{}/ninite.exe'.format(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) + +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) + +## Misc ## +def update_caffeine(): + # Stop running processes + kill_process('caffeine.exe') + + # Remove existing folders + remove_from_kit('Caffeine') + + # Download + download_to_temp('caffeine.zip', SOURCE_URLS['Caffeine']) + + # Extract files + extract_temp_to_cbin('caffeine.zip', 'Caffeine') + + # Cleanup + remove_from_temp('caffeine.zip') + +def update_du(): + # Stop running processes + kill_process('du.exe') + kill_process('du64.exe') + + # Remove existing folders + remove_from_kit('Du') + + # Download + download_to_temp('du.zip', SOURCE_URLS['Du']) + + # Extract files + extract_temp_to_cbin('du.zip', 'Du') + + # Cleanup + remove_from_temp('du.zip') + +def update_everything(): + # Stop running processes + for exe in ['Everything.exe', 'Everything64.exe']: + kill_process(exe) + + # Remove existing folders + remove_from_kit('Everything') + + # 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') + + # Cleanup + remove_from_temp('everything32.zip') + remove_from_temp('everything64.zip') + +def update_firefox_ublock_origin(): + # Remove existing folders + remove_from_kit('FirefoxExtensions') + + # Download + download_to_temp('ff-uBO.xpi', SOURCE_URLS['Firefox uBO']) + + # Extract files + extract_generic( + r'{}\ff-uBO.xpi'.format(global_vars['TmpDir']), + r'{}\FirefoxExtensions\uBlock0@raymondhill.net'.format( + global_vars['CBinDir'])) + + # Cleanup + remove_from_temp('ff-uBO.xpi') + +def update_notepadplusplus(): + # Stop running processes + kill_process('notepadplusplus.exe') + + # Remove existing folders + remove_from_kit('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']) + ) + + # Cleanup + remove_from_temp('npp.7z') + +def update_putty(): + # Stop running processes + kill_process('PUTTY.EXE') + + # Remove existing folders + remove_from_kit('PuTTY') + + # Download + download_to_temp('putty.zip', SOURCE_URLS['PuTTY']) + + # Extract files + extract_temp_to_cbin('putty.zip', 'PuTTY') + + # Cleanup + remove_from_temp('putty.zip') + +def update_treesizefree(): + # Stop running processes + kill_process('TreeSizeFree.exe') + + # Remove existing folders + remove_from_kit('TreeSizeFree') + + # Download + download_to_temp( + 'treesizefree.zip.gz', SOURCE_URLS['TreeSizeFree']) + + # Extract files + ## NOTE: When downloaded using requests it is a .zip.gz? + source = r'{}\treesizefree.zip.gz'.format(global_vars['TmpDir']) + extract_generic(source, global_vars['TmpDir']) + extract_temp_to_cbin('treesizefree.zip', 'TreeSizeFree') + + # Cleanup + remove_from_temp('treesizefree.zip') + remove_from_temp('treesizefree.zip.gz') + +def update_xmplay(): + # Stop running processes + kill_process('xmplay.exe') + + # 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']) + + # 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) + + # 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') + +## Repairs ## +def update_adwcleaner(): + # Stop running processes + kill_process('AdwCleaner.exe') + + # Remove existing folders + remove_from_kit('AdwCleaner') + + # Download + url = resolve_dynamic_url( + SOURCE_URLS['AdwCleaner'], + 'id="downloadLink"') + download_generic( + r'{}\AdwCleaner'.format(global_vars['CBinDir']), 'AdwCleaner.exe', url) + +def update_kvrt(): + # Stop running processes + kill_process('KVRT.exe') + + # Remove existing folders + remove_from_kit('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') + + # 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) + +def update_tdsskiller(): + # Stop running processes + kill_process('TDSSKiller.exe') + + # Remove existing folders + remove_from_kit('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') + + # Remove existing folders + remove_from_kit('IObitUninstallerPortable') + + # 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') + + # Cleanup + remove_from_kit('IObitUninstallerPortable.exe') + +if __name__ == '__main__': + print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/hw-diags b/.bin/Scripts/hw-diags new file mode 100755 index 00000000..c1d7d3ca --- /dev/null +++ b/.bin/Scripts/hw-diags @@ -0,0 +1,43 @@ +#!/bin/bash +# +## Wizard Kit: HW Diagnostics - Menu Launcher + +SESSION_NAME="hw-diags" +WINDOW_NAME="Hardware Diagnostics" +MENU="hw-diags-menu" + +function ask() { + while :; do + read -p "$1 " -r answer + if echo "$answer" | egrep -iq '^(y|yes|sure)$'; then + return 0 + elif echo "$answer" | egrep -iq '^(n|no|nope)$'; then + return 1 + fi + done +} + +die () { + echo "$0:" "$@" >&2 + exit 1 +} + +# Check for running session +if tmux list-session | grep -q "$SESSION_NAME"; then + echo "WARNING: hw-diags tmux session already exists." + echo "" + if ask "Kill current session?"; then + tmux kill-session -t "$SESSION_NAME" || \ + die "Failed to kill session: $SESSION_NAME" + else + echo "Aborted." + echo "" + echo -n "Press Enter to exit... " + read -r + exit 0 + fi +fi + +# Start session +tmux new-session -s "$SESSION_NAME" -n "$WINDOW_NAME" "$MENU" $* + diff --git a/.bin/Scripts/hw-diags-audio b/.bin/Scripts/hw-diags-audio new file mode 100755 index 00000000..88168263 --- /dev/null +++ b/.bin/Scripts/hw-diags-audio @@ -0,0 +1,42 @@ +#!/bin/python3 +# +## Wizard Kit: HW Diagnostics - Audio + +import os +import sys + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +sys.path.append(os.getcwd()) +from functions.common import * +init_global_vars() + +if __name__ == '__main__': + 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() + diff --git a/.bin/Scripts/hw-diags-badblocks b/.bin/Scripts/hw-diags-badblocks new file mode 100755 index 00000000..2d915766 --- /dev/null +++ b/.bin/Scripts/hw-diags-badblocks @@ -0,0 +1,18 @@ +#!/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" + diff --git a/.bin/Scripts/hw-diags-menu b/.bin/Scripts/hw-diags-menu new file mode 100755 index 00000000..f7c1739c --- /dev/null +++ b/.bin/Scripts/hw-diags-menu @@ -0,0 +1,30 @@ +#!/bin/python3 +# +## Wizard Kit: HW Diagnostics - Menu + +import os +import sys + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +sys.path.append(os.getcwd()) +from functions.hw_diags import * +init_global_vars() + +if __name__ == '__main__': + try: + # Prep + clear_screen() + + # Show menu + menu_diags(*sys.argv) + + # Done + #print_standard('\nDone.') + #pause("Press Enter to exit...") + exit_script() + except SystemExit: + pass + except: + major_exception() + diff --git a/.bin/Scripts/hw-diags-network b/.bin/Scripts/hw-diags-network new file mode 100755 index 00000000..5fdd26a4 --- /dev/null +++ b/.bin/Scripts/hw-diags-network @@ -0,0 +1,46 @@ +#!/bin/python3 +# +## Wizard Kit: HW Diagnostics - Network + +import os +import sys + +# Init +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 + clear_screen() + print_standard('Hardware Diagnostics: Network\n') + + # 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() + diff --git a/.bin/Scripts/hw-diags-prime95 b/.bin/Scripts/hw-diags-prime95 new file mode 100755 index 00000000..30c6994d --- /dev/null +++ b/.bin/Scripts/hw-diags-prime95 @@ -0,0 +1,18 @@ +#!/bin/bash +# +## Wizard Kit: HW Diagnostics - Prime95 + +function usage { + echo "Usage: $0 log-dir" + echo " e.g. $0 /tmp/tmp.7Mh5f1RhSL9001" +} + +# Bail early +if [ ! -d "$1" ]; then + usage + exit 1 +fi + +# Run Prime95 +mprime -t | grep -iv --line-buffered 'stress.txt' | tee -a "$1/prime.log" + diff --git a/.bin/Scripts/hw-sensors b/.bin/Scripts/hw-sensors new file mode 100755 index 00000000..bfaddc7e --- /dev/null +++ b/.bin/Scripts/hw-sensors @@ -0,0 +1,164 @@ +#!/bin/python3 +# +## Wizard Kit: Sensor monitoring tool + +import itertools +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 * +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.INTRUSION: + vals = [sensors.get_value(chip, sf.number) for sf in sfs] + # short path for INTRUSION to demonstrate type usage + status = "alarm" if int(vals[0]) == 1 else "normal" + print_standard(' {:18} {}'.format(label, status)) + return + + for sf in sfs: + name = sf.name[skipname:].decode("utf-8").strip() + val = sensors.get_value(chip, sf.number) + 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_temps[chip_name] = [chip_name] + for feature in sensors.FeatureIterator(chip): + chip_temps[chip_name].append(get_feature_string(chip, feature)) + chip_temps[chip_name].append('') + + # 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() + diff --git a/.bin/Scripts/install_sw_bundle.py b/.bin/Scripts/install_sw_bundle.py index b42d39f1..9f8594b0 100644 --- a/.bin/Scripts/install_sw_bundle.py +++ b/.bin/Scripts/install_sw_bundle.py @@ -1,60 +1,60 @@ -# Wizard Kit: Install the standard SW bundle based on the OS version - -import os -import sys - -# Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -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) - -if __name__ == '__main__': - try: - stay_awake() - clear_screen() - print_info('{}: SW Bundle Tool\n'.format(KIT_NAME_FULL)) - other_results = { - 'Error': { - 'CalledProcessError': 'Unknown Error', - }, - '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: - install_adobe_reader() - if answer_vcr: - install_vcredists() - if answer_ninite: - try_and_print(message='Ninite bundle...', - function=install_ninite_bundle, cs='Started', mse=answer_mse) - 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) - print_standard('\nDone.') - exit_script() - except SystemExit: - pass - except: - major_exception() +# Wizard Kit: Install the standard SW bundle based on the OS version + +import os +import sys + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +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) + +if __name__ == '__main__': + try: + stay_awake() + clear_screen() + print_info('{}: SW Bundle Tool\n'.format(KIT_NAME_FULL)) + other_results = { + 'Error': { + 'CalledProcessError': 'Unknown Error', + }, + '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: + install_adobe_reader() + if answer_vcr: + install_vcredists() + if answer_ninite: + try_and_print(message='Ninite bundle...', + function=install_ninite_bundle, cs='Started', mse=answer_mse) + 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) + print_standard('\nDone.') + exit_script() + except SystemExit: + pass + except: + major_exception() diff --git a/.bin/Scripts/install_vcredists.py b/.bin/Scripts/install_vcredists.py index 4e7af362..4a1f53ea 100644 --- a/.bin/Scripts/install_vcredists.py +++ b/.bin/Scripts/install_vcredists.py @@ -1,34 +1,34 @@ -# Wizard Kit: Install Visual C++ Runtimes - -import os -import sys - -# Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -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) - -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', - }} - - if ask('Install Visual C++ Runtimes?'): - install_vcredists() - else: - abort() - - print_standard('\nDone.') - exit_script() - except SystemExit: - pass - except: - major_exception() +# Wizard Kit: Install Visual C++ Runtimes + +import os +import sys + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +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) + +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', + }} + + if ask('Install Visual C++ Runtimes?'): + install_vcredists() + else: + abort() + + print_standard('\nDone.') + exit_script() + except SystemExit: + pass + except: + major_exception() diff --git a/.bin/Scripts/mount-all-volumes b/.bin/Scripts/mount-all-volumes new file mode 100755 index 00000000..fdc76046 --- /dev/null +++ b/.bin/Scripts/mount-all-volumes @@ -0,0 +1,38 @@ +#!/bin/python3 +# +## Wizard Kit: Volume mount tool + +import os +import sys + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +sys.path.append(os.getcwd()) +from functions.data import * +init_global_vars() + +if __name__ == '__main__': + try: + # Prep + clear_screen() + print_standard('{}: Volume mount tool'.format(KIT_NAME_FULL)) + + # Mount volumes + report = mount_all_volumes() + + # Print report + print_info('\nResults') + for line in report: + show_data(indent=4, width=16, **line[-1]) + + # Done + print_standard('\nDone.') + if 'gui' in sys.argv: + pause("Press Enter to exit...") + popen_program(['nohup', 'thunar', '/media']) + exit_script() + except SystemExit: + pass + except: + major_exception() + diff --git a/.bin/Scripts/mount-backup-shares b/.bin/Scripts/mount-backup-shares new file mode 100755 index 00000000..9706a0a5 --- /dev/null +++ b/.bin/Scripts/mount-backup-shares @@ -0,0 +1,38 @@ +#!/bin/python3 +# +## Wizard Kit: Backup share mount tool + +import os +import sys + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +sys.path.append(os.getcwd()) +from functions.data import * +from functions.network import * +init_global_vars() + +if __name__ == '__main__': + try: + # Prep + clear_screen() + + # Connect + connect_to_network() + + # Mount + if is_connected(): + mount_backup_shares() + 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() + diff --git a/.bin/Scripts/msword-search b/.bin/Scripts/msword-search new file mode 100755 index 00000000..3e2c175c --- /dev/null +++ b/.bin/Scripts/msword-search @@ -0,0 +1,81 @@ +#!/bin/python3 +# +## Wizard Kit: MS Word content search tool + +import os +import re +import sys + +# STATIC VARIABLES +SCANDIR = os.getcwd() +USAGE = '''Usage: {script} ... + 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__) + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +sys.path.append(os.getcwd()) +from functions.network import * +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 + +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 + +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)) + + 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() + diff --git a/.bin/Scripts/remount-rw b/.bin/Scripts/remount-rw new file mode 100755 index 00000000..4a0b833e --- /dev/null +++ b/.bin/Scripts/remount-rw @@ -0,0 +1,23 @@ +#!/bin/bash +# +## Wizard Kit: Volume remount tool + +if ! mount | grep -q "$1"; then + echo "ERROR: Can't remount $1" + sleep 2s + exit 1 +fi + +DEVICE=$(mount | grep "$1" | cut -d' ' -f1) + +# Remount read-write +echo "Remounting: $DEVICE" +udevil umount $DEVICE +if udevil mount $DEVICE; then + echo "Done" +else + echo "Failed" +fi + +sleep 2s +exit 0 diff --git a/.bin/Scripts/safemode_enter.py b/.bin/Scripts/safemode_enter.py index 032f626e..825e7352 100644 --- a/.bin/Scripts/safemode_enter.py +++ b/.bin/Scripts/safemode_enter.py @@ -1,44 +1,44 @@ -# Wizard Kit: Enter SafeMode by editing the BCD - -import os -import sys - -# STATIC VARIABLES -REG_MSISERVER = r'HKLM\SYSTEM\CurrentControlSet\Control\SafeBoot\Network\MSIServer' - -# Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) -from functions.common import * -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)) - if not ask('Enable booting to SafeMode (with Networking)?'): - abort() - - # Edit BCD to set safeboot as default - cmd = ['bcdedit', '/set', '{default}', 'safeboot', 'network'] - run_program(cmd, check=False) - - # Enable MSI access under safemode - cmd = ['reg', 'add', REG_MSISERVER, '/f'] - run_program(cmd, check=False) - cmd = ['reg', 'add', REG_MSISERVER, '/ve', - '/t', 'REG_SZ', '/d', 'Service', '/f'] - run_program(cmd, check=False) - - ## Done ## - pause('Press Enter to reboot...') - cmd = ['shutdown', '-r', '-t', '3'] - run_program(cmd, check=False) - - # Done - exit_script() - except SystemExit: - pass - except: - major_exception() +# Wizard Kit: Enter SafeMode by editing the BCD + +import os +import sys + +# STATIC VARIABLES +REG_MSISERVER = r'HKLM\SYSTEM\CurrentControlSet\Control\SafeBoot\Network\MSIServer' + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +sys.path.append(os.getcwd()) +from functions.common import * +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)) + if not ask('Enable booting to SafeMode (with Networking)?'): + abort() + + # Edit BCD to set safeboot as default + cmd = ['bcdedit', '/set', '{default}', 'safeboot', 'network'] + run_program(cmd, check=False) + + # Enable MSI access under safemode + cmd = ['reg', 'add', REG_MSISERVER, '/f'] + run_program(cmd, check=False) + cmd = ['reg', 'add', REG_MSISERVER, '/ve', + '/t', 'REG_SZ', '/d', 'Service', '/f'] + run_program(cmd, check=False) + + ## Done ## + pause('Press Enter to reboot...') + cmd = ['shutdown', '-r', '-t', '3'] + run_program(cmd, check=False) + + # Done + exit_script() + except SystemExit: + pass + except: + major_exception() diff --git a/.bin/Scripts/safemode_exit.py b/.bin/Scripts/safemode_exit.py index cbd6c8cb..267aac60 100644 --- a/.bin/Scripts/safemode_exit.py +++ b/.bin/Scripts/safemode_exit.py @@ -1,42 +1,42 @@ -# Wizard Kit: Exit SafeMode by editing the BCD - -import os -import sys - -# STATIC VARIABLES -REG_MSISERVER = r'HKLM\SYSTEM\CurrentControlSet\Control\SafeBoot\Network\MSIServer' - -# Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) -from functions.common import * -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)) - if not ask('Disable booting to SafeMode?'): - abort() - - # Edit BCD to remove safeboot value - for boot in ['{current}', '{default}']: - cmd = ['bcdedit', '/deletevalue', boot, 'safeboot'] - run_program(cmd, check=False) - - # Disable MSI access under safemode - cmd = ['reg', 'delete', REG_MSISERVER, '/f'] - run_program(cmd, check=False) - - ## Done ## - pause('Press Enter to reboot...') - cmd = ['shutdown', '-r', '-t', '3'] - run_program(cmd, check=False) - - # Done - exit_script() - except SystemExit: - pass - except: - major_exception() +# Wizard Kit: Exit SafeMode by editing the BCD + +import os +import sys + +# STATIC VARIABLES +REG_MSISERVER = r'HKLM\SYSTEM\CurrentControlSet\Control\SafeBoot\Network\MSIServer' + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +sys.path.append(os.getcwd()) +from functions.common import * +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)) + if not ask('Disable booting to SafeMode?'): + abort() + + # Edit BCD to remove safeboot value + for boot in ['{current}', '{default}']: + cmd = ['bcdedit', '/deletevalue', boot, 'safeboot'] + run_program(cmd, check=False) + + # Disable MSI access under safemode + cmd = ['reg', 'delete', REG_MSISERVER, '/f'] + run_program(cmd, check=False) + + ## Done ## + pause('Press Enter to reboot...') + cmd = ['shutdown', '-r', '-t', '3'] + run_program(cmd, check=False) + + # Done + exit_script() + except SystemExit: + pass + except: + major_exception() diff --git a/.bin/Scripts/settings/launchers.py b/.bin/Scripts/settings/launchers.py index 5c8f7242..f3e6b0a2 100644 --- a/.bin/Scripts/settings/launchers.py +++ b/.bin/Scripts/settings/launchers.py @@ -1,586 +1,586 @@ -# Wizard Kit: Settings - Launchers - -LAUNCHERS = { - r'(Root)': { - 'Activate Windows': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'activate.py', - 'L_ELEV': 'True', - }, - 'Enter SafeMode': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'safemode_enter.py', - 'L_ELEV': 'True', - }, - 'Exit SafeMode': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'safemode_exit.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%\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" /Info /Transfer', - ], - }, - 'FastCopy': { - 'L_TYPE': 'Executable', - 'L_PATH': 'FastCopy', - 'L_ITEM': 'FastCopy.exe', - 'L_ARGS': ( - r' /logfile=%log_dir%\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" /Info /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\%iso_date%\Registry sysreg curuser otherusers', - 'L_ELEV': 'True', - 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Info', - ], - }, - 'HitmanPro': { - 'L_TYPE': 'Executable', - 'L_PATH': 'HitmanPro', - 'L_ITEM': 'HitmanPro.exe', - 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Info', - ], - }, - '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_15.8.exe', - 'L_7ZIP': 'SetupRST_15.8.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\2013': { - 'Home and Business 2013 (x32)': { - 'L_TYPE': 'Office', - 'L_PATH': '2013', - 'L_ITEM': 'hb_32.xml', - 'L_NCMD': 'True', - }, - 'Home and Business 2013 (x64)': { - 'L_TYPE': 'Office', - 'L_PATH': '2013', - 'L_ITEM': 'hb_64.xml', - 'L_NCMD': 'True', - }, - 'Home and Student 2013 (x32)': { - 'L_TYPE': 'Office', - 'L_PATH': '2013', - 'L_ITEM': 'hs_32.xml', - 'L_NCMD': 'True', - }, - 'Home and Student 2013 (x64)': { - 'L_TYPE': 'Office', - 'L_PATH': '2013', - 'L_ITEM': 'hs_64.xml', - 'L_NCMD': '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': { - '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', - }, - 'Everything': { - 'L_TYPE': 'Executable', - 'L_PATH': 'Everything', - 'L_ITEM': 'Everything.exe', - 'L_ARGS': '-nodb', - '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', - }, - 'TreeSizeFree': { - 'L_TYPE': 'Executable', - 'L_PATH': 'TreeSizeFree', - 'L_ITEM': 'TreeSizeFree.exe', - 'L_ELEV': 'True', - }, - 'Update Kit': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'update_kit.py', - }, - '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', - 'Extra Code': [ - r'call "%bin%\Scripts\init_client_dir.cmd" /Info', - ], - }, - '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%\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.") +# Wizard Kit: Settings - Launchers + +LAUNCHERS = { + r'(Root)': { + 'Activate Windows': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'activate.py', + 'L_ELEV': 'True', + }, + 'Enter SafeMode': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'safemode_enter.py', + 'L_ELEV': 'True', + }, + 'Exit SafeMode': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'safemode_exit.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%\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" /Info /Transfer', + ], + }, + 'FastCopy': { + 'L_TYPE': 'Executable', + 'L_PATH': 'FastCopy', + 'L_ITEM': 'FastCopy.exe', + 'L_ARGS': ( + r' /logfile=%log_dir%\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" /Info /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\%iso_date%\Registry sysreg curuser otherusers', + 'L_ELEV': 'True', + 'Extra Code': [ + r'call "%bin%\Scripts\init_client_dir.cmd" /Info', + ], + }, + 'HitmanPro': { + 'L_TYPE': 'Executable', + 'L_PATH': 'HitmanPro', + 'L_ITEM': 'HitmanPro.exe', + 'Extra Code': [ + r'call "%bin%\Scripts\init_client_dir.cmd" /Info', + ], + }, + '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_15.8.exe', + 'L_7ZIP': 'SetupRST_15.8.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\2013': { + 'Home and Business 2013 (x32)': { + 'L_TYPE': 'Office', + 'L_PATH': '2013', + 'L_ITEM': 'hb_32.xml', + 'L_NCMD': 'True', + }, + 'Home and Business 2013 (x64)': { + 'L_TYPE': 'Office', + 'L_PATH': '2013', + 'L_ITEM': 'hb_64.xml', + 'L_NCMD': 'True', + }, + 'Home and Student 2013 (x32)': { + 'L_TYPE': 'Office', + 'L_PATH': '2013', + 'L_ITEM': 'hs_32.xml', + 'L_NCMD': 'True', + }, + 'Home and Student 2013 (x64)': { + 'L_TYPE': 'Office', + 'L_PATH': '2013', + 'L_ITEM': 'hs_64.xml', + 'L_NCMD': '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': { + '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', + }, + 'Everything': { + 'L_TYPE': 'Executable', + 'L_PATH': 'Everything', + 'L_ITEM': 'Everything.exe', + 'L_ARGS': '-nodb', + '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', + }, + 'TreeSizeFree': { + 'L_TYPE': 'Executable', + 'L_PATH': 'TreeSizeFree', + 'L_ITEM': 'TreeSizeFree.exe', + 'L_ELEV': 'True', + }, + 'Update Kit': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'update_kit.py', + }, + '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', + 'Extra Code': [ + r'call "%bin%\Scripts\init_client_dir.cmd" /Info', + ], + }, + '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%\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.") diff --git a/.bin/Scripts/settings/main.py b/.bin/Scripts/settings/main.py index fc5331a2..d48b0ba0 100644 --- a/.bin/Scripts/settings/main.py +++ b/.bin/Scripts/settings/main.py @@ -3,15 +3,30 @@ # Features ENABLED_UPLOAD_DATA = False -# STATIC VARIABLES (also used by .cmd files) -## Not using spaces aroung '=' for easier .cmd substrings +# 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_SHORT='WK' +SUPPORT_MESSAGE='Please let 2Shirt know by opening an issue on GitHub' +# Live Linux +DIAG_SHARE='/srv/ClientInfo' +DIAG_USER='wkdiag' +MPRIME_LIMIT='7' # of minutes to run Prime95 during hw-diags +ROOT_PASSWORD='Abracadabra' +SKIP_UPLOAD='False' +TECH_PASSWORD='Abracadabra' +# Server IP addresses +DIAG_SERVER='10.0.0.10' OFFICE_SERVER_IP='10.0.0.10' QUICKBOOKS_SERVER_IP='10.0.0.10' -SUPPORT_MESSAGE='Please let 2Shirt know by opening an issue on GitHub' -TIME_ZONE='Pacific Standard Time' # Always use "Standard Time" (DST is applied correctly) +# 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 +# WiFi +WIFI_SSID='SomeWifi' +WIFI_PASSWORD='Abracadabra' # SERVER VARIABLES ## NOTE: Windows can only use one user per server. This means that if diff --git a/.bin/Scripts/settings/music.py b/.bin/Scripts/settings/music.py index 80c71086..a2d49f31 100644 --- a/.bin/Scripts/settings/music.py +++ b/.bin/Scripts/settings/music.py @@ -1,70 +1,70 @@ -# 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', - ] - -MUSIC_SNES = [ - '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.") +# 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', + ] + +MUSIC_SNES = [ + '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.") diff --git a/.bin/Scripts/settings/sources.py b/.bin/Scripts/settings/sources.py index 0014a909..b9adf614 100644 --- a/.bin/Scripts/settings/sources.py +++ b/.bin/Scripts/settings/sources.py @@ -1,203 +1,203 @@ -# Wizard Kit: Settings - Sources - -SOURCE_URLS = { - 'AIDA64': 'http://download.aida64.com/aida64engineer595.zip', - 'Adobe Reader DC': 'http://ardownload.adobe.com/pub/adobe/reader/win/AcrobatDC/1800920044/AcroRdrDC1800920044_en_US.exe', - 'AdwCleaner': 'https://toolslib.net/downloads/finish/1-adwcleaner/', - 'Autoruns': 'https://download.sysinternals.com/files/Autoruns.zip', - 'BleachBit': 'https://download.bleachbit.org/beta/1.17/BleachBit-1.17-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.877.x86.zip', - 'Everything64': 'https://www.voidtools.com/Everything-1.4.1.877.x64.zip', - 'FastCopy32': 'http://ftp.vector.co.jp/69/76/2323/FastCopy340.zip', - 'FastCopy64': 'http://ftp.vector.co.jp/69/76/2323/FastCopy340_x64.zip', - 'Firefox uBO': 'https://addons.mozilla.org/firefox/downloads/file/764482/ublock_origin-1.14.18-an+fx.xpi?src=dp-btn-primary', - 'HWiNFO32': 'http://app.oldfoss.com:81/download/HWiNFO/hw32_560.zip', - 'HWiNFO64': 'http://app.oldfoss.com:81/download/HWiNFO/hw64_560.zip', - 'HitmanPro32': 'https://dl.surfright.nl/HitmanPro.exe', - 'HitmanPro64': 'https://dl.surfright.nl/HitmanPro_x64.exe', - 'IOBit_Uninstaller': 'https://portableapps.com/redirect/?a=IObitUninstallerPortable&t=http%3A%2F%2Fdownloads.portableapps.com%2Fportableapps%2Fiobituninstallerportable%2FIObitUninstallerPortable_7.2.0.11.paf.exe', - 'Intel SSD Toolbox': r'https://downloadmirror.intel.com/27330/eng/Intel%20SSD%20Toolbox%20-%20v3.4.9.exe', - 'KVRT': 'http://devbuilds.kaspersky-labs.com/devbuilds/KVRT/latest/full/KVRT.exe', - 'NotepadPlusPlus': 'https://notepad-plus-plus.org/repository/7.x/7.5.2/npp.7.5.2.bin.minimalist.7z', - 'Office Deployment Tool 2013': 'https://download.microsoft.com/download/6/2/3/6230F7A2-D8A9-478B-AC5C-57091B632FCF/officedeploymenttool_x86_4827-1000.exe', - 'Office Deployment Tool 2016': 'https://download.microsoft.com/download/2/7/A/27AF1BE6-DD20-4CB4-B154-EBAB8A7D4A7E/officedeploymenttool_8529.3600.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/', - 'SDIO Themes': 'http://snappy-driver-installer.org/downloads/SDIO_Themes.zip', - 'SDIO Torrent': 'http://snappy-driver-installer.org/downloads/SDIO_Update.torrent', - 'Samsung Magician': 'http://downloadcenter.samsung.com/content/SW/201710/20171019164455812/Samsung_Magician_Installer.exe', - 'TDSSKiller': 'https://media.kaspersky.com/utilities/VirusUtilities/EN/tdsskiller.exe', - 'TestDisk': 'https://www.cgsecurity.org/testdisk-7.1-WIP.win.zip', - 'TreeSizeFree': 'https://www.jam-software.com/treesize_free/TreeSizeFree-Portable.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', - 'XMPlay 7z': 'http://support.xmplay.com/files/16/xmp-7z.zip?v=800962', - 'XMPlay Game': 'http://support.xmplay.com/files/12/xmp-gme.zip?v=515637', - 'XMPlay RAR': 'http://support.xmplay.com/files/16/xmp-rar.zip?v=409646', - 'XMPlay WAModern': 'http://support.xmplay.com/files/10/WAModern.zip?v=207099', - 'XMPlay': 'http://support.xmplay.com/files/20/xmplay3823.zip?v=115916', - 'XYplorerFree': 'https://www.xyplorer.com/download/xyplorer_free_noinstall.zip', - 'aria2': 'https://github.com/aria2/aria2/releases/download/release-1.33.1/aria2-1.33.1-win-32bit-build1.zip', - } -VCREDIST_SOURCES = { - '2008sp1': { - '32': 'https://download.microsoft.com/download/5/D/8/5D8C65CB-C849-4025-8E95-C3966CAFD8AE/vcredist_x86.exe', - '64': 'https://download.microsoft.com/download/5/D/8/5D8C65CB-C849-4025-8E95-C3966CAFD8AE/vcredist_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://download.visualstudio.microsoft.com/download/pr/11100229/78c1e864d806e36f6035d80a0e80399e/VC_redist.x86.exe', - '64': 'https://download.visualstudio.microsoft.com/download/pr/11100230/15ccb3f02745c7b206ad10373cbca89b/VC_redist.x64.exe', - }, - } -NINITE_SOURCES = { - 'Bundles': { - 'Runtimes.exe': '.net4.7-air-java8-silverlight', - 'Legacy.exe': '.net4.7-7zip-air-chrome-firefox-java8-silverlight-vlc', - 'Modern.exe': '.net4.7-7zip-air-chrome-classicstart-firefox-java8-silverlight-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': { - 'Pidgin.exe': 'pidgin', - 'Skype.exe': 'skype', - 'Trillian.exe': 'trillian', - }, - 'Compression': { - '7-Zip.exe': '7zip', - 'PeaZip.exe': 'peazip', - 'WinRAR.exe': 'winrar', - }, - 'Developer': { - 'Eclipse.exe': 'eclipse', - 'FileZilla.exe': 'filezilla', - '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', - '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 12.exe': 'teamviewer12', - '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/27147/eng/SetupRST.exe', - } - - -if __name__ == '__main__': - print("This file is not meant to be called directly.") +# Wizard Kit: Settings - Sources + +SOURCE_URLS = { + 'AIDA64': 'http://download.aida64.com/aida64engineer595.zip', + 'Adobe Reader DC': 'http://ardownload.adobe.com/pub/adobe/reader/win/AcrobatDC/1800920044/AcroRdrDC1800920044_en_US.exe', + 'AdwCleaner': 'https://toolslib.net/downloads/finish/1-adwcleaner/', + 'Autoruns': 'https://download.sysinternals.com/files/Autoruns.zip', + 'BleachBit': 'https://download.bleachbit.org/beta/1.17/BleachBit-1.17-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.877.x86.zip', + 'Everything64': 'https://www.voidtools.com/Everything-1.4.1.877.x64.zip', + 'FastCopy32': 'http://ftp.vector.co.jp/69/76/2323/FastCopy340.zip', + 'FastCopy64': 'http://ftp.vector.co.jp/69/76/2323/FastCopy340_x64.zip', + 'Firefox uBO': 'https://addons.mozilla.org/firefox/downloads/file/764482/ublock_origin-1.14.18-an+fx.xpi?src=dp-btn-primary', + 'HWiNFO32': 'http://app.oldfoss.com:81/download/HWiNFO/hw32_560.zip', + 'HWiNFO64': 'http://app.oldfoss.com:81/download/HWiNFO/hw64_560.zip', + 'HitmanPro32': 'https://dl.surfright.nl/HitmanPro.exe', + 'HitmanPro64': 'https://dl.surfright.nl/HitmanPro_x64.exe', + 'IOBit_Uninstaller': 'https://portableapps.com/redirect/?a=IObitUninstallerPortable&t=http%3A%2F%2Fdownloads.portableapps.com%2Fportableapps%2Fiobituninstallerportable%2FIObitUninstallerPortable_7.2.0.11.paf.exe', + 'Intel SSD Toolbox': r'https://downloadmirror.intel.com/27330/eng/Intel%20SSD%20Toolbox%20-%20v3.4.9.exe', + 'KVRT': 'http://devbuilds.kaspersky-labs.com/devbuilds/KVRT/latest/full/KVRT.exe', + 'NotepadPlusPlus': 'https://notepad-plus-plus.org/repository/7.x/7.5.2/npp.7.5.2.bin.minimalist.7z', + 'Office Deployment Tool 2013': 'https://download.microsoft.com/download/6/2/3/6230F7A2-D8A9-478B-AC5C-57091B632FCF/officedeploymenttool_x86_4827-1000.exe', + 'Office Deployment Tool 2016': 'https://download.microsoft.com/download/2/7/A/27AF1BE6-DD20-4CB4-B154-EBAB8A7D4A7E/officedeploymenttool_8529.3600.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/', + 'SDIO Themes': 'http://snappy-driver-installer.org/downloads/SDIO_Themes.zip', + 'SDIO Torrent': 'http://snappy-driver-installer.org/downloads/SDIO_Update.torrent', + 'Samsung Magician': 'http://downloadcenter.samsung.com/content/SW/201710/20171019164455812/Samsung_Magician_Installer.exe', + 'TDSSKiller': 'https://media.kaspersky.com/utilities/VirusUtilities/EN/tdsskiller.exe', + 'TestDisk': 'https://www.cgsecurity.org/testdisk-7.1-WIP.win.zip', + 'TreeSizeFree': 'https://www.jam-software.com/treesize_free/TreeSizeFree-Portable.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', + 'XMPlay 7z': 'http://support.xmplay.com/files/16/xmp-7z.zip?v=800962', + 'XMPlay Game': 'http://support.xmplay.com/files/12/xmp-gme.zip?v=515637', + 'XMPlay RAR': 'http://support.xmplay.com/files/16/xmp-rar.zip?v=409646', + 'XMPlay WAModern': 'http://support.xmplay.com/files/10/WAModern.zip?v=207099', + 'XMPlay': 'http://support.xmplay.com/files/20/xmplay3823.zip?v=115916', + 'XYplorerFree': 'https://www.xyplorer.com/download/xyplorer_free_noinstall.zip', + 'aria2': 'https://github.com/aria2/aria2/releases/download/release-1.33.1/aria2-1.33.1-win-32bit-build1.zip', + } +VCREDIST_SOURCES = { + '2008sp1': { + '32': 'https://download.microsoft.com/download/5/D/8/5D8C65CB-C849-4025-8E95-C3966CAFD8AE/vcredist_x86.exe', + '64': 'https://download.microsoft.com/download/5/D/8/5D8C65CB-C849-4025-8E95-C3966CAFD8AE/vcredist_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://download.visualstudio.microsoft.com/download/pr/11100229/78c1e864d806e36f6035d80a0e80399e/VC_redist.x86.exe', + '64': 'https://download.visualstudio.microsoft.com/download/pr/11100230/15ccb3f02745c7b206ad10373cbca89b/VC_redist.x64.exe', + }, + } +NINITE_SOURCES = { + 'Bundles': { + 'Runtimes.exe': '.net4.7-air-java8-silverlight', + 'Legacy.exe': '.net4.7-7zip-air-chrome-firefox-java8-silverlight-vlc', + 'Modern.exe': '.net4.7-7zip-air-chrome-classicstart-firefox-java8-silverlight-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': { + 'Pidgin.exe': 'pidgin', + 'Skype.exe': 'skype', + 'Trillian.exe': 'trillian', + }, + 'Compression': { + '7-Zip.exe': '7zip', + 'PeaZip.exe': 'peazip', + 'WinRAR.exe': 'winrar', + }, + 'Developer': { + 'Eclipse.exe': 'eclipse', + 'FileZilla.exe': 'filezilla', + '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', + '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 12.exe': 'teamviewer12', + '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/27147/eng/SetupRST.exe', + } + + +if __name__ == '__main__': + print("This file is not meant to be called directly.") diff --git a/.bin/Scripts/settings/tools.py b/.bin/Scripts/settings/tools.py index d678027d..f8fe7737 100644 --- a/.bin/Scripts/settings/tools.py +++ b/.bin/Scripts/settings/tools.py @@ -1,55 +1,55 @@ -# 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'}, - 'NotepadPlusPlus': { - '32': r'NotepadPlusPlus\notepadplusplus.exe'}, - 'ProduKey': { - '32': r'ProduKey\ProduKey.exe', - '64': r'ProduKey\ProduKey64.exe'}, - 'PuTTY-PSFTP': { - '32': r'PuTTY\PSFTP.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.") +# 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'}, + 'NotepadPlusPlus': { + '32': r'NotepadPlusPlus\notepadplusplus.exe'}, + 'ProduKey': { + '32': r'ProduKey\ProduKey.exe', + '64': r'ProduKey\ProduKey64.exe'}, + 'PuTTY-PSFTP': { + '32': r'PuTTY\PSFTP.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.") diff --git a/.bin/Scripts/sfc_scan.py b/.bin/Scripts/sfc_scan.py index f816cd3b..81211747 100644 --- a/.bin/Scripts/sfc_scan.py +++ b/.bin/Scripts/sfc_scan.py @@ -1,39 +1,39 @@ -# Wizard Kit: Check, and possibly repair, system file health via SFC - -import os -import sys - -# Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -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) - -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() - - # Done - print_standard('\nDone.') - pause('Press Enter to exit...') - exit_script() - except SystemExit: - pass - except: - major_exception() +# Wizard Kit: Check, and possibly repair, system file health via SFC + +import os +import sys + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +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) + +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() + + # Done + print_standard('\nDone.') + pause('Press Enter to exit...') + exit_script() + except SystemExit: + pass + except: + major_exception() diff --git a/.bin/Scripts/system_checklist.py b/.bin/Scripts/system_checklist.py index 9f9686b7..4d4d34f8 100644 --- a/.bin/Scripts/system_checklist.py +++ b/.bin/Scripts/system_checklist.py @@ -1,107 +1,107 @@ -# Wizard Kit: System Checklist - -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.cleanup import * -from functions.diags import * -from functions.info import * -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) - -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': { - 'CalledProcessError': 'Unknown Error', - 'BIOSKeyNotFoundError': 'BIOS key not found', - }, - 'Warning': {}} - 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='Desktop...', - function=cleanup_desktop, cs='Done') - try_and_print(message='AdwCleaner...', - function=cleanup_adwcleaner, cs='Done') - - # Export system info - print_info('Backup System Information') - try_and_print(message='AIDA64 reports...', - function=run_aida64, cs='Done') - try_and_print(message='File listing...', - function=backup_file_list, cs='Done') - try_and_print(message='Power plans...', - function=backup_power_plans, cs='Done') - try_and_print(message='Product Keys...', - function=run_produkey, cs='Done') - try_and_print(message='Registry...', - function=backup_registry, cs='Done') - - # 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', '10')): - try_and_print(message='BIOS Activation:', - function=activate_with_bios, - other_results=other_results) - try_and_print(message='Installed Office:', - function=get_installed_office, ns='Unknown', print_return=True) - show_free_space() - try_and_print(message='Installed RAM:', - function=show_installed_ram, ns='Unknown', silent_function=False) - - # Upload info - if ENABLED_UPLOAD_DATA: - print_info('Finalizing') - try_and_print(message='Compressing Info...', - function=compress_info, cs='Done') - try_and_print(message='Uploading to NAS...', - function=upload_info, cs='Done') - - # Play audio, show devices, open Windows updates, and open Activation - popen_program(['mmc', 'devmgmt.msc']) - run_hwinfo_sensors() - popen_program(['control', '/name', 'Microsoft.WindowsUpdate']) - if not windows_is_activated(): - popen_program('slui') - sleep(3) - run_xmplay() - - # Done - print_standard('\nDone.') - pause('Press Enter exit...') - exit_script() - except SystemExit: - pass - except: - major_exception() +# Wizard Kit: System Checklist + +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.cleanup import * +from functions.diags import * +from functions.info import * +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) + +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': { + 'CalledProcessError': 'Unknown Error', + 'BIOSKeyNotFoundError': 'BIOS key not found', + }, + 'Warning': {}} + 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='Desktop...', + function=cleanup_desktop, cs='Done') + try_and_print(message='AdwCleaner...', + function=cleanup_adwcleaner, cs='Done') + + # Export system info + print_info('Backup System Information') + try_and_print(message='AIDA64 reports...', + function=run_aida64, cs='Done') + try_and_print(message='File listing...', + function=backup_file_list, cs='Done') + try_and_print(message='Power plans...', + function=backup_power_plans, cs='Done') + try_and_print(message='Product Keys...', + function=run_produkey, cs='Done') + try_and_print(message='Registry...', + function=backup_registry, cs='Done') + + # 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', '10')): + try_and_print(message='BIOS Activation:', + function=activate_with_bios, + other_results=other_results) + try_and_print(message='Installed Office:', + function=get_installed_office, ns='Unknown', print_return=True) + show_free_space() + try_and_print(message='Installed RAM:', + function=show_installed_ram, ns='Unknown', silent_function=False) + + # Upload info + if ENABLED_UPLOAD_DATA: + print_info('Finalizing') + try_and_print(message='Compressing Info...', + function=compress_info, cs='Done') + try_and_print(message='Uploading to NAS...', + function=upload_info, cs='Done') + + # Play audio, show devices, open Windows updates, and open Activation + popen_program(['mmc', 'devmgmt.msc']) + run_hwinfo_sensors() + popen_program(['control', '/name', 'Microsoft.WindowsUpdate']) + if not windows_is_activated(): + popen_program('slui') + sleep(3) + run_xmplay() + + # Done + print_standard('\nDone.') + pause('Press Enter exit...') + exit_script() + except SystemExit: + pass + except: + major_exception() diff --git a/.bin/Scripts/system_diagnostics.py b/.bin/Scripts/system_diagnostics.py index feaee0da..ad4b423e 100644 --- a/.bin/Scripts/system_diagnostics.py +++ b/.bin/Scripts/system_diagnostics.py @@ -1,124 +1,124 @@ -# Wizard Kit: System Diagnostics - -import os -import sys - -# Init -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 * -init_global_vars() -os.system('title {}: System Diagnostics Tool'.format(KIT_NAME_FULL)) -global_vars['LogFile'] = r'{LogDir}\System Diagnostics.log'.format( - **global_vars) - -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', - }, - 'Warning': { - 'GenericRepair': 'Repaired', - 'UnsupportedOSError': 'Unsupported OS', - }} - 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') - try_and_print(message='Running TDSSKiller...', - function=run_tdsskiller, cs='Done') - - # 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') - try_and_print(message='Running Autoruns...', - function=run_autoruns, cs='Started') - - # 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() - - # Export system info - print_info('Backup System Information') - try_and_print(message='AIDA64 reports...', - function=run_aida64, cs='Done') - try_and_print(message='BleachBit report...', - function=run_bleachbit, cs='Done') - backup_browsers() - try_and_print(message='File listing...', - function=backup_file_list, cs='Done') - try_and_print(message='Power plans...', - function=backup_power_plans, cs='Done') - try_and_print(message='Product Keys...', - function=run_produkey, cs='Done') - try_and_print(message='Registry...', - function=backup_registry, cs='Done') - - # Summary - print_info('Summary') - try_and_print(message='Temp Size:', - function=show_temp_files_size, silent_function=False) - show_free_space() - try_and_print(message='Installed RAM:', - function=show_installed_ram, ns='Unknown', silent_function=False) - try_and_print(message='Installed Office:', - function=get_installed_office, ns='Unknown', print_return=True) - try_and_print(message='Product Keys:', - function=get_product_keys, ns='Unknown', print_return=True) - try_and_print(message='Operating System:', - function=show_os_name, ns='Unknown', silent_function=False) - try_and_print(message='', - function=show_os_activation, ns='Unknown', silent_function=False) - - # User data - print_info('User Data') - try: - show_user_data_summary() - except Exception: - print_error(' Unknown error.') - - # Upload info - if ENABLED_UPLOAD_DATA: - print_info('Finalizing') - try_and_print(message='Compressing Info...', - function=compress_info, cs='Done') - try_and_print(message='Uploading to NAS...', - function=upload_info, cs='Done') - - # Done - print_standard('\nDone.') - pause('Press Enter to exit...') - exit_script() - except SystemExit: - pass - except: - major_exception() +# Wizard Kit: System Diagnostics + +import os +import sys + +# Init +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 * +init_global_vars() +os.system('title {}: System Diagnostics Tool'.format(KIT_NAME_FULL)) +global_vars['LogFile'] = r'{LogDir}\System Diagnostics.log'.format( + **global_vars) + +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', + }, + 'Warning': { + 'GenericRepair': 'Repaired', + 'UnsupportedOSError': 'Unsupported OS', + }} + 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') + try_and_print(message='Running TDSSKiller...', + function=run_tdsskiller, cs='Done') + + # 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') + try_and_print(message='Running Autoruns...', + function=run_autoruns, cs='Started') + + # 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() + + # Export system info + print_info('Backup System Information') + try_and_print(message='AIDA64 reports...', + function=run_aida64, cs='Done') + try_and_print(message='BleachBit report...', + function=run_bleachbit, cs='Done') + backup_browsers() + try_and_print(message='File listing...', + function=backup_file_list, cs='Done') + try_and_print(message='Power plans...', + function=backup_power_plans, cs='Done') + try_and_print(message='Product Keys...', + function=run_produkey, cs='Done') + try_and_print(message='Registry...', + function=backup_registry, cs='Done') + + # Summary + print_info('Summary') + try_and_print(message='Temp Size:', + function=show_temp_files_size, silent_function=False) + show_free_space() + try_and_print(message='Installed RAM:', + function=show_installed_ram, ns='Unknown', silent_function=False) + try_and_print(message='Installed Office:', + function=get_installed_office, ns='Unknown', print_return=True) + try_and_print(message='Product Keys:', + function=get_product_keys, ns='Unknown', print_return=True) + try_and_print(message='Operating System:', + function=show_os_name, ns='Unknown', silent_function=False) + try_and_print(message='', + function=show_os_activation, ns='Unknown', silent_function=False) + + # User data + print_info('User Data') + try: + show_user_data_summary() + except Exception: + print_error(' Unknown error.') + + # Upload info + if ENABLED_UPLOAD_DATA: + print_info('Finalizing') + try_and_print(message='Compressing Info...', + function=compress_info, cs='Done') + try_and_print(message='Uploading to NAS...', + function=upload_info, cs='Done') + + # Done + print_standard('\nDone.') + pause('Press Enter to exit...') + exit_script() + except SystemExit: + pass + except: + major_exception() diff --git a/.bin/Scripts/transferred_keys.py b/.bin/Scripts/transferred_keys.py index 0634e862..9829207e 100644 --- a/.bin/Scripts/transferred_keys.py +++ b/.bin/Scripts/transferred_keys.py @@ -1,28 +1,28 @@ -# Wizard Kit: Search for product keys in the transfer folder - -import os -import sys - -# Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -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) - -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) - - # Done - print_standard('\nDone.') - exit_script() - except SystemExit: - pass - except: - major_exception() +# Wizard Kit: Search for product keys in the transfer folder + +import os +import sys + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +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) + +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) + + # Done + print_standard('\nDone.') + exit_script() + except SystemExit: + pass + except: + major_exception() diff --git a/.bin/Scripts/update_kit.py b/.bin/Scripts/update_kit.py index 71ecaf8c..6a5cdf82 100644 --- a/.bin/Scripts/update_kit.py +++ b/.bin/Scripts/update_kit.py @@ -1,143 +1,143 @@ -# Wizard Kit: Download the latest versions of the programs in the kit - -import os -import sys - -# Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) -from functions.update import * -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', - }} - - ## Prep ## - update_sdio = ask('Update SDI Origin?') - - ## 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 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='BlueScreenView...', 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='HWiNFO...', function=update_hwinfo, 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) - - # 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='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='FirefoxExtensions...', 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='TreeSizeFree...', function=update_treesizefree, 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='TDSSKiller...', 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) - - ## 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) - - ## 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) - - # 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() +# Wizard Kit: Download the latest versions of the programs in the kit + +import os +import sys + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +sys.path.append(os.getcwd()) +from functions.update import * +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', + }} + + ## Prep ## + update_sdio = ask('Update SDI Origin?') + + ## 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 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='BlueScreenView...', 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='HWiNFO...', function=update_hwinfo, 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) + + # 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='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='FirefoxExtensions...', 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='TreeSizeFree...', function=update_treesizefree, 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='TDSSKiller...', 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) + + ## 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) + + ## 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) + + # 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() diff --git a/.bin/Scripts/user_checklist.py b/.bin/Scripts/user_checklist.py index 93d229a1..fd7e3418 100644 --- a/.bin/Scripts/user_checklist.py +++ b/.bin/Scripts/user_checklist.py @@ -1,83 +1,83 @@ -# Wizard Kit: User Checklist - -import os -import sys - -# Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) -from functions.browsers import * -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']) - -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?') - - # 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: - 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') - - # Done - print_standard('\nDone.') - pause('Press Enter to exit...') - exit_script() - except SystemExit: - pass - except: - major_exception() +# Wizard Kit: User Checklist + +import os +import sys + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +sys.path.append(os.getcwd()) +from functions.browsers import * +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']) + +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?') + + # 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: + 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') + + # Done + print_standard('\nDone.') + pause('Press Enter to exit...') + exit_script() + except SystemExit: + pass + except: + major_exception() diff --git a/.bin/Scripts/user_data_transfer.py b/.bin/Scripts/user_data_transfer.py index 40a5a63a..d3da5e46 100644 --- a/.bin/Scripts/user_data_transfer.py +++ b/.bin/Scripts/user_data_transfer.py @@ -1,53 +1,53 @@ -# Wizard Kit: Copy user data to the system from a local or network source - -import os -import sys - -# Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) -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) - -if __name__ == '__main__': - try: - # Prep - stay_awake() - clear_screen() - print_info('{}: User Data Transfer Tool\n'.format(KIT_NAME_FULL)) - ticket_number = get_ticket_number() - folder_path = r'{}\Transfer'.format(KIT_NAME_SHORT) - dest = select_destination(folder_path=folder_path, - prompt='Which disk are we transferring to?') - source = select_source(ticket_number) - items = scan_source(source, dest) - - # Transfer - clear_screen() - print_info('Transfer Details:\n') - show_info('Ticket:', ticket_number) - show_info('Source:', source.path) - show_info('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 - run_kvrt() - print_standard('\nDone.') - pause("Press Enter to exit...") - exit_script() - except SystemExit: - pass - except: - major_exception() +# Wizard Kit: Copy user data to the system from a local or network source + +import os +import sys + +# Init +os.chdir(os.path.dirname(os.path.realpath(__file__))) +sys.path.append(os.getcwd()) +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) + +if __name__ == '__main__': + try: + # Prep + stay_awake() + clear_screen() + print_info('{}: User Data Transfer Tool\n'.format(KIT_NAME_FULL)) + ticket_number = get_ticket_number() + folder_path = r'{}\Transfer'.format(KIT_NAME_SHORT) + dest = select_destination(folder_path=folder_path, + prompt='Which disk are we transferring to?') + source = select_source(ticket_number) + items = scan_source(source, dest) + + # Transfer + clear_screen() + print_info('Transfer Details:\n') + show_info('Ticket:', ticket_number) + show_info('Source:', source.path) + show_info('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 + run_kvrt() + print_standard('\nDone.') + pause("Press Enter to exit...") + exit_script() + except SystemExit: + pass + except: + major_exception() diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index dc2008ad..00000000 --- a/.gitattributes +++ /dev/null @@ -1,4 +0,0 @@ -Images/ filter=lfs diff=lfs merge=lfs -text -*.jpg filter=lfs diff=lfs merge=lfs -text -*.png filter=lfs diff=lfs merge=lfs -text -*.xcf filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore index 214d469a..bcaa6c80 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ **/__pycache__/* *.bak *.exe +*.swp .bin/7-Zip/ .bin/AIDA64/ .bin/BleachBit/ diff --git a/.linux_items/.gitignore b/.linux_items/.gitignore new file mode 100644 index 00000000..5495eced --- /dev/null +++ b/.linux_items/.gitignore @@ -0,0 +1,2 @@ +wk_tmp +wk-repo diff --git a/.linux_items/build_additions.txt b/.linux_items/build_additions.txt new file mode 100644 index 00000000..3abfa39b --- /dev/null +++ b/.linux_items/build_additions.txt @@ -0,0 +1,5 @@ +rsync -aI "${script_path}/${install_dir}/" "${work_dir}/iso/${install_dir}/" +rm "${work_dir}/iso/EFI" -R +rm "${work_dir}/iso/loader" -R +rsync -aI "${script_path}/EFI/" "${work_dir}/iso/EFI/" + diff --git a/.linux_items/include/EFI/boot/icons/wk_arch.png b/.linux_items/include/EFI/boot/icons/wk_arch.png new file mode 100644 index 00000000..f417362e Binary files /dev/null and b/.linux_items/include/EFI/boot/icons/wk_arch.png differ diff --git a/.linux_items/include/EFI/boot/icons/wk_memtest.png b/.linux_items/include/EFI/boot/icons/wk_memtest.png new file mode 100644 index 00000000..927930f9 Binary files /dev/null and b/.linux_items/include/EFI/boot/icons/wk_memtest.png differ diff --git a/.linux_items/include/EFI/boot/icons/wk_win.png b/.linux_items/include/EFI/boot/icons/wk_win.png new file mode 100644 index 00000000..d086d20c Binary files /dev/null and b/.linux_items/include/EFI/boot/icons/wk_win.png differ diff --git a/.linux_items/include/EFI/boot/refind.conf b/.linux_items/include/EFI/boot/refind.conf new file mode 100644 index 00000000..075f6e46 --- /dev/null +++ b/.linux_items/include/EFI/boot/refind.conf @@ -0,0 +1,39 @@ +# refind.conf + +timeout 0 +scanfor manual +showtools firmware,reboot,shutdown +default_selection MemTest86 +csr_values 10,77 +#use_graphics_for osx,linux,windows + +# Theme +banner rEFInd.png +banner_scale fillscreen +selection_big selection_big.png +selection_small selection_small.png +hideui arrows,badges + +# Entries +menuentry "MemTest86" { + icon /EFI/boot/icons/wk_memtest.png + loader /EFI/memtest86/memtestx64.efi +} +menuentry "Linux" { + icon /EFI/boot/icons/wk_arch.png + loader /arch/boot/x86_64/vmlinuz + initrd /arch/boot/intel_ucode.img + initrd /arch/boot/x86_64/archiso.img + options "archisobasedir=arch archisolabel=%ARCHISO_LABEL% quiet copytoram loglevel=3" + submenuentry "Linux (i3)" { + add_options "i3" + } + submenuentry "Linux (CLI)" { + add_options "nox" + } +} +menuentry "WindowsPE" { + ostype windows + icon /EFI/boot/icons/wk_win.png + loader /EFI/microsoft/bootx64.efi +} diff --git a/.linux_items/include/EFI/boot/selection_big.png b/.linux_items/include/EFI/boot/selection_big.png new file mode 100644 index 00000000..280b47b8 Binary files /dev/null and b/.linux_items/include/EFI/boot/selection_big.png differ diff --git a/.linux_items/include/EFI/boot/selection_small.png b/.linux_items/include/EFI/boot/selection_small.png new file mode 100644 index 00000000..b52c388f Binary files /dev/null and b/.linux_items/include/EFI/boot/selection_small.png differ diff --git a/.linux_items/include/airootfs/etc/default/ufw b/.linux_items/include/airootfs/etc/default/ufw new file mode 100644 index 00000000..665806f3 --- /dev/null +++ b/.linux_items/include/airootfs/etc/default/ufw @@ -0,0 +1,45 @@ +# /etc/default/ufw +# + +# Set to yes to apply rules to support IPv6 (no means only IPv6 on loopback +# accepted). You will need to 'disable' and then 'enable' the firewall for +# the changes to take affect. +IPV6=yes + +# Set the default input policy to ACCEPT, DROP, or REJECT. Please note that if +# you change this you will most likely want to adjust your rules. +DEFAULT_INPUT_POLICY="DROP" + +# Set the default output policy to ACCEPT, DROP, or REJECT. Please note that if +# you change this you will most likely want to adjust your rules. +DEFAULT_OUTPUT_POLICY="ACCEPT" + +# Set the default forward policy to ACCEPT, DROP or REJECT. Please note that +# if you change this you will most likely want to adjust your rules +DEFAULT_FORWARD_POLICY="DROP" + +# Set the default application policy to ACCEPT, DROP, REJECT or SKIP. Please +# note that setting this to ACCEPT may be a security risk. See 'man ufw' for +# details +DEFAULT_APPLICATION_POLICY="SKIP" + +# By default, ufw only touches its own chains. Set this to 'yes' to have ufw +# manage the built-in chains too. Warning: setting this to 'yes' will break +# non-ufw managed firewall rules +MANAGE_BUILTINS=no + +# +# IPT backend +# +# only enable if using iptables backend +IPT_SYSCTL=/etc/ufw/sysctl.conf + +# Extra connection tracking modules to load. Complete list can be found in +# net/netfilter/Kconfig of your kernel source. Some common modules: +# nf_conntrack_irc, nf_nat_irc: DCC (Direct Client to Client) support +# nf_conntrack_netbios_ns: NetBIOS (samba) client support +# nf_conntrack_pptp, nf_nat_pptp: PPTP over stateful firewall/NAT +# nf_conntrack_ftp, nf_nat_ftp: active FTP support +# nf_conntrack_tftp, nf_nat_tftp: TFTP support (server side) +IPT_MODULES="nf_conntrack_ftp nf_nat_ftp nf_conntrack_netbios_ns" + diff --git a/.linux_items/include/airootfs/etc/hostname b/.linux_items/include/airootfs/etc/hostname new file mode 100644 index 00000000..d0b7e4a6 --- /dev/null +++ b/.linux_items/include/airootfs/etc/hostname @@ -0,0 +1 @@ +wklinux diff --git a/.linux_items/include/airootfs/etc/hosts b/.linux_items/include/airootfs/etc/hosts new file mode 100644 index 00000000..f3b39609 --- /dev/null +++ b/.linux_items/include/airootfs/etc/hosts @@ -0,0 +1,3 @@ +127.0.0.1 localhost.localdomain localhost +::1 localhost.localdomain localhost + diff --git a/.linux_items/include/airootfs/etc/locale.conf b/.linux_items/include/airootfs/etc/locale.conf new file mode 100644 index 00000000..01ec548f --- /dev/null +++ b/.linux_items/include/airootfs/etc/locale.conf @@ -0,0 +1 @@ +LANG=en_US.UTF-8 diff --git a/.linux_items/include/airootfs/etc/locale.gen b/.linux_items/include/airootfs/etc/locale.gen new file mode 100644 index 00000000..1165d291 --- /dev/null +++ b/.linux_items/include/airootfs/etc/locale.gen @@ -0,0 +1,2 @@ +en_US.UTF-8 UTF-8 + diff --git a/.linux_items/include/airootfs/etc/motd b/.linux_items/include/airootfs/etc/motd new file mode 100644 index 00000000..c84d47a0 --- /dev/null +++ b/.linux_items/include/airootfs/etc/motd @@ -0,0 +1,9 @@ +Welcome to the ______ + +Some common commands: +% hw-diags +% hw-info +% mount-all-volumes +% mount-backup-shares +% connect-to-network + diff --git a/.linux_items/include/airootfs/etc/oblogout.conf b/.linux_items/include/airootfs/etc/oblogout.conf new file mode 100644 index 00000000..4595c766 --- /dev/null +++ b/.linux_items/include/airootfs/etc/oblogout.conf @@ -0,0 +1,20 @@ +[settings] +usehal = false + +[looks] +opacity = 70 +bgcolor = black +buttontheme = foom +#buttons = cancel, logout, restart, shutdown, suspend, hibernate, lock +buttons = restart, shutdown, logout + +[shortcuts] +cancel = Escape +shutdown = S +restart = R +logout = L + +[commands] +shutdown = systemctl poweroff +restart = systemctl reboot +logout = openbox --exit diff --git a/.linux_items/include/airootfs/etc/polkit-1/rules.d/49-nopasswd_global.rules b/.linux_items/include/airootfs/etc/polkit-1/rules.d/49-nopasswd_global.rules new file mode 100644 index 00000000..ce304018 --- /dev/null +++ b/.linux_items/include/airootfs/etc/polkit-1/rules.d/49-nopasswd_global.rules @@ -0,0 +1,5 @@ +polkit.addRule(function(action, subject) { + if (subject.isInGroup("wheel")) { + return polkit.Result.YES; + } +}); diff --git a/.linux_items/include/airootfs/etc/skel/.Xresources b/.linux_items/include/airootfs/etc/skel/.Xresources new file mode 100755 index 00000000..68054af5 --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.Xresources @@ -0,0 +1,64 @@ +! general settings +URxvt*saveline: 15000 +URxvt*termName: rxvt-256color +URxvt*iso14755: false + +! appearance +URxvt*depth: 32 +!URxvt*background: rgba:0000/0000/0000/AAAA +!URxvt*background: [80]#404552 +!URxvt*background: [100]#2f343f +!URxvt*foreground: #F8F8FF +!URxvt.underlineColor: #4682B4 +!URxvt.highlightColor: #4682B4 +!URxvt.throughColor: Blue +!URxvt*cursorColor: #dc8cc3 +!URxvt*cursorColor2: Black +URxvt*scrollBar: false +URxvt*scrollBar_right: false +URxvt*internalBorder: 0 +URxvt*externalBorder: 0 +!URxvt.colorIT: #87af5f +!URxvt.colorBD: #c5c8c6 +!URxvt.colorUL: #87afd7 +URxvt.geometry: 92x16 +URxvt.internalBorder: 8 +URxvt.shading: 10 +URxvt.transparent: true + +! Base16 Isotope +! Scheme: Jan T. Sott +!! Modified by 2Shirt + +*.foreground: #d0d0d0 +*.background: #000000 +*.cursorColor: #d0d0d0 + +*.color0: #000000 +*.color1: #ff0000 +*.color2: #33ff00 +*.color3: #ffd000 +*.color4: #0066ff +*.color5: #cc00ff +*.color6: #00ffff +*.color7: #d0d0d0 + +*.color8: #808080 +*.color9: #ff9900 +*.color10: #404040 +*.color11: #606060 +*.color12: #c0c0c0 +*.color13: #e0e0e0 +*.color14: #3300ff +*.color15: #ffffff + +! fonts +Xft.autohint: 0 +Xft.antialias: 1 +Xft.hinting: true +Xft.hintstyle: hintslight +Xft.rgba: rgb +Xft.lcdfilter: lcddefault +URxvt.font: xft:Inconsolata:size=12 +!URxvt.letterSpace: -3 + diff --git a/.linux_items/include/airootfs/etc/skel/.aliases b/.linux_items/include/airootfs/etc/skel/.aliases new file mode 100644 index 00000000..2fc314d1 --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.aliases @@ -0,0 +1,35 @@ +alias 7z0='7z a -t7z -mx=0' +alias 7z1='7z a -t7z -mx=1' +alias 7z3='7z a -t7z -mx=3' +alias 7z5='7z a -t7z -mx=5' +alias 7z7='7z a -t7z -mx=7' +alias 7z9='7z a -t7z -mx=9' +alias diff='colordiff -ur' +alias du='du -sch --apparent-size' +alias fix-perms='find -type d -exec chmod 755 "{}" \; && find -type f -exec chmod 644 "{}" \;' +alias hw-info='sudo inxi -ACDdGlMmNopRsxxc 25' +alias less='less -S' +alias ls='ls --color=auto' +alias mkdir='mkdir -p' +alias mount='sudo mount' +alias mv='mv -nv' +alias pacinit='sudo sed -i -r "s/^SigLevel.*/SigLevel = Never/" /etc/pacman.conf; sudo pacman -Sy' +alias photorec-sort='sudo photorec-sort' +alias photorec='sudo photorec' +alias q1='clear && ls -1' +alias q1a='clear && ls -1A' +alias q='clear && ls -lh' +alias qa='clear && ls -lAh' +alias qs='clear && ls' +alias qsa='clear && ls -A' +alias rm='rm -v' +alias rmdirs='find -depth -mindepth 1 -type d -exec rmdir "{}" --ignore-fail-on-non-empty \;' +alias rs='rsync -avhPS --stats --exclude-from="$HOME/.rsync_exclusions"' +alias rsz='rsync -avhzPS --stats --exclude-from="$HOME/.rsync_exclusions"' +alias sdu='sudo du -sch --apparent-size' +alias srmdirs='sudo find -depth -mindepth 1 -type d -exec rmdir "{}" --ignore-fail-on-non-empty \;' +alias srs='sudo rsync -avhPS --stats --exclude-from="$HOME/.rsync_exclusions"' +alias srsz='sudo rsync -avhzPS --stats --exclude-from="$HOME/.rsync_exclusions"' +alias testdisk='sudo testdisk' +alias umount='sudo umount' +alias unmount='sudo umount' diff --git a/.linux_items/include/airootfs/etc/skel/.bashrc b/.linux_items/include/airootfs/etc/skel/.bashrc new file mode 100644 index 00000000..cb37e84b --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.bashrc @@ -0,0 +1,14 @@ +# +# ~/.bashrc +# + +# If not running interactively, don't do anything +[[ $- != *i* ]] && return + +PS1='[\u@\h \W]\$ ' + +## Load aliases +. $HOME/.aliases + +# Update LS_COLORS +eval $(dircolors ~/.dircolors) diff --git a/.linux_items/include/airootfs/etc/skel/.config/Thunar/accels.scm b/.linux_items/include/airootfs/etc/skel/.config/Thunar/accels.scm new file mode 100644 index 00000000..45408e2a --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.config/Thunar/accels.scm @@ -0,0 +1,73 @@ +; Thunar GtkAccelMap rc-file -*- scheme -*- +; this file is an automated accelerator map dump +; +; (gtk_accel_path "/ThunarLauncher/sendto-desktop" "") +; (gtk_accel_path "/ThunarStandardView/create-folder" "n") +; (gtk_accel_path "/ThunarShortcutsPane/sendto-shortcuts" "") +; (gtk_accel_path "/ThunarWindow/view-side-pane-menu" "") +; (gtk_accel_path "/ThunarStandardView/paste-into-folder" "v") +; (gtk_accel_path "/ThunarWindow/open-home" "Home") +; (gtk_accel_path "/ThunarWindow/view-menu" "") +; (gtk_accel_path "/ThunarLauncher/open" "o") +; (gtk_accel_path "/ThunarWindow/go-menu" "") +; (gtk_accel_path "/ThunarActions/uca-action-1462127723240094-1" "") +; (gtk_accel_path "/ThunarWindow/open-file-system" "") +; (gtk_accel_path "/ThunarWindow/zoom-out" "minus") +; (gtk_accel_path "/ThunarStandardView/paste" "v") +; (gtk_accel_path "/ThunarLauncher/open-with-menu" "") +; (gtk_accel_path "/ThunarWindow/help-menu" "") +; (gtk_accel_path "/ThunarWindow/file-menu" "") +; (gtk_accel_path "/ThunarLauncher/open-with-other-in-menu" "") +; (gtk_accel_path "/ThunarWindow/detach-tab" "") +; (gtk_accel_path "/ThunarLauncher/open-in-new-tab" "p") +; (gtk_accel_path "/ThunarWindow/view-menubar" "m") +; (gtk_accel_path "/ThunarStandardView/back" "Left") +; (gtk_accel_path "/ThunarWindow/close-tab" "w") +; (gtk_accel_path "/ThunarWindow/view-as-compact-list" "3") +; (gtk_accel_path "/ThunarWindow/view-side-pane-tree" "e") +; (gtk_accel_path "/ThunarStandardView/restore" "") +; (gtk_accel_path "/ThunarWindow/open-network" "") +; (gtk_accel_path "/ThunarActions/Tap::create-archive" "") +; (gtk_accel_path "/ThunarWindow/new-tab" "t") +; (gtk_accel_path "/ThunarWindow/preferences" "") +; (gtk_accel_path "/ThunarStandardView/rename" "F2") +; (gtk_accel_path "/ThunarWindow/sendto-menu" "") +; (gtk_accel_path "/ThunarWindow/edit-menu" "") +; (gtk_accel_path "/ThunarLauncher/open-with-other" "") +; (gtk_accel_path "/ThunarWindow/view-location-selector-toolbar" "") +; (gtk_accel_path "/ThunarStandardView/invert-selection" "") +; (gtk_accel_path "/ThunarStandardView/make-link" "") +; (gtk_accel_path "/ThunarWindow/view-as-icons" "1") +; (gtk_accel_path "/ThunarWindow/new-window" "n") +; (gtk_accel_path "/ThunarStandardView/forward" "Right") +; (gtk_accel_path "/ThunarStandardView/move-to-trash" "") +; (gtk_accel_path "/ThunarStandardView/select-by-pattern" "s") +; (gtk_accel_path "/ThunarWindow/about" "") +; (gtk_accel_path "/ThunarStandardView/setup-columns" "") +; (gtk_accel_path "/ThunarWindow/contents" "F1") +; (gtk_accel_path "/ThunarWindow/open-desktop" "") +; (gtk_accel_path "/ThunarWindow/close-all-windows" "w") +; (gtk_accel_path "/ThunarWindow/zoom-in" "plus") +; (gtk_accel_path "/ThunarStandardView/duplicate" "") +; (gtk_accel_path "/ThunarWindow/open-parent" "Up") +; (gtk_accel_path "/ThunarWindow/view-side-pane-shortcuts" "b") +; (gtk_accel_path "/ThunarWindow/reload" "r") +; (gtk_accel_path "/ThunarWindow/open-templates" "") +; (gtk_accel_path "/ThunarStandardView/copy" "c") +; (gtk_accel_path "/ThunarWindow/view-location-selector-pathbar" "") +; (gtk_accel_path "/ThunarStandardView/properties" "Return") +; (gtk_accel_path "/ThunarStandardView/delete" "") +; (gtk_accel_path "/ThunarActions/Twp::setwallpaper" "") +; (gtk_accel_path "/ThunarWindow/empty-trash" "") +; (gtk_accel_path "/ThunarWindow/view-location-selector-menu" "") +; (gtk_accel_path "/ThunarLauncher/open-in-new-window" "o") +; (gtk_accel_path "/ThunarStandardView/cut" "x") +; (gtk_accel_path "/ThunarWindow/close-window" "q") +; (gtk_accel_path "/ThunarStandardView/select-all-files" "") +; (gtk_accel_path "/ThunarWindow/open-location" "l") +; (gtk_accel_path "/ThunarWindow/zoom-reset" "0") +; (gtk_accel_path "/ThunarWindow/view-statusbar" "") +; (gtk_accel_path "/ThunarWindow/show-hidden" "h") +; (gtk_accel_path "/ThunarWindow/view-as-detailed-list" "2") +; (gtk_accel_path "/ThunarActions/uca-action-1497008558378216-3" "") + diff --git a/.linux_items/include/airootfs/etc/skel/.config/Thunar/uca.xml b/.linux_items/include/airootfs/etc/skel/.config/Thunar/uca.xml new file mode 100644 index 00000000..d5eafe20 --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.config/Thunar/uca.xml @@ -0,0 +1,24 @@ + + + + utilities-terminal + Open Terminal Here + 1462127723240094-1 + exo-open --working-directory %f --launch TerminalEmulator + Example for a custom action + * + + + + + edit-redo-symbolic + Remount Read-Write + 1497008558378216-3 + urxvt -T "Mount Tool" -e remount-rw %f + Remount Read-Write + * + + + + + diff --git a/.linux_items/include/airootfs/etc/skel/.config/dunst/dunstrc b/.linux_items/include/airootfs/etc/skel/.config/dunst/dunstrc new file mode 100644 index 00000000..e6339fcc --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.config/dunst/dunstrc @@ -0,0 +1,322 @@ +[global] + ### Display ### + + # Which monitor should the notifications be displayed on. + monitor = 0 + + # Display notification on focused monitor. Possible modes are: + # mouse: follow mouse pointer + # keyboard: follow window with keyboard focus + # none: don't follow anything + # + # "keyboard" needs a window manager that exports the + # _NET_ACTIVE_WINDOW property. + # This should be the case for almost all modern window managers. + # + # If this option is set to mouse or keyboard, the monitor option + # will be ignored. + follow = mouse + + # The geometry of the window: + # [{width}]x{height}[+/-{x}+/-{y}] + # The geometry of the message window. + # The height is measured in number of notifications everything else + # in pixels. If the width is omitted but the height is given + # ("-geometry x2"), the message window expands over the whole screen + # (dmenu-like). If width is 0, the window expands to the longest + # message displayed. A positive x is measured from the left, a + # negative from the right side of the screen. Y is measured from + # the top and down respectively. + # The width can be negative. In this case the actual width is the + # screen width minus the width defined in within the geometry option. + geometry = "300x5-220+40" + + # Show how many messages are currently hidden (because of geometry). + indicate_hidden = yes + + # Shrink window if it's smaller than the width. Will be ignored if + # width is 0. + shrink = no + + # The transparency of the window. Range: [0; 100]. + # This option will only work if a compositing window manager is + # present (e.g. xcompmgr, compiz, etc.). + transparency = 20 + + # The height of the entire notification. If the height is smaller + # than the font height and padding combined, it will be raised + # to the font height and padding. + notification_height = 0 + + # Draw a line of "separator_height" pixel height between two + # notifications. + # Set to 0 to disable. + separator_height = 2 + + # Padding between text and separator. + padding = 8 + + # Horizontal padding. + horizontal_padding = 8 + + # Defines width in pixels of frame around the notification window. + # Set to 0 to disable. + frame_width = 3 + + # Defines color of the frame around the notification window. + #frame_color = "#3300ff" + + # Define a color for the separator. + # possible values are: + # * auto: dunst tries to find a color fitting to the background; + # * foreground: use the same color as the foreground; + # * frame: use the same color as the frame; + # * anything else will be interpreted as a X color. + separator_color = frame + + # Sort messages by urgency. + sort = yes + + # Don't remove messages, if the user is idle (no mouse or keyboard input) + # for longer than idle_threshold seconds. + # Set to 0 to disable. + idle_threshold = 120 + + ### Text ### + + font = Inconsolata 8 + + # The spacing between lines. If the height is smaller than the + # font height, it will get raised to the font height. + line_height = 0 + + # Possible values are: + # full: Allow a small subset of html markup in notifications: + # bold + # italic + # strikethrough + # underline + # + # For a complete reference see + # . + # + # strip: This setting is provided for compatibility with some broken + # clients that send markup even though it's not enabled on the + # server. Dunst will try to strip the markup but the parsing is + # simplistic so using this option outside of matching rules for + # specific applications *IS GREATLY DISCOURAGED*. + # + # no: Disable markup parsing, incoming notifications will be treated as + # plain text. Dunst will not advertise that it has the body-markup + # capability if this is set as a global setting. + # + # It's important to note that markup inside the format option will be parsed + # regardless of what this is set to. + markup = full + + # The format of the message. Possible variables are: + # %a appname + # %s summary + # %b body + # %i iconname (including its path) + # %I iconname (without its path) + # %p progress value if set ([ 0%] to [100%]) or nothing + # %n progress value if set without any extra characters + # Markup is allowed + format = "%s\n%b" + + # Alignment of message text. + # Possible values are "left", "center" and "right". + alignment = left + + # Show age of message if message is older than show_age_threshold + # seconds. + # Set to -1 to disable. + show_age_threshold = 60 + + # Split notifications into multiple lines if they don't fit into + # geometry. + word_wrap = yes + + # Ignore newlines '\n' in notifications. + ignore_newline = no + + # Merge multiple notifications with the same content + stack_duplicates = true + + # Hide the count of merged notifications with the same content + hide_duplicate_count = false + + # Display indicators for URLs (U) and actions (A). + show_indicators = yes + + ### Icons ### + + # Align icons left/right/off + icon_position = off + + # Scale larger icons down to this size, set to 0 to disable + max_icon_size = 32 + + # Paths to default icons. + icon_folders = /usr/share/icons/Papirus-Dark/16x16/status/:/usr/share/icons/Papirus-Dark/16x16/devices/ + + ### History ### + + # Should a notification popped up from history be sticky or timeout + # as if it would normally do. + sticky_history = yes + + # Maximum amount of notifications kept in history + history_length = 20 + + ### Misc/Advanced ### + + # dmenu path. + dmenu = /usr/bin/dmenu -p dunst: + + # Browser for opening urls in context menu. + browser = /usr/bin/firefox -new-tab + + # Always run rule-defined scripts, even if the notification is suppressed + always_run_script = true + + # Define the title of the windows spawned by dunst + title = Dunst + + # Define the class of the windows spawned by dunst + class = Dunst + + # Print a notification on startup. + # This is mainly for error detection, since dbus (re-)starts dunst + # automatically after a crash. + startup_notification = false + + ### Legacy + + # Use the Xinerama extension instead of RandR for multi-monitor support. + # This setting is provided for compatibility with older nVidia drivers that + # do not support RandR and using it on systems that support RandR is highly + # discouraged. + # + # By enabling this setting dunst will not be able to detect when a monitor + # is connected or disconnected which might break follow mode if the screen + # layout changes. + force_xinerama = false + +# Experimental features that may or may not work correctly. Do not expect them +# to have a consistent behaviour across releases. +[experimental] + # Calculate the dpi to use on a per-monitor basis. + # If this setting is enabled the Xft.dpi value will be ignored and instead + # dunst will attempt to calculate an appropriate dpi value for each monitor + # using the resolution and physical size. This might be useful in setups + # where there are multiple screens with very different dpi values. + per_monitor_dpi = false + +[shortcuts] + + # Shortcuts are specified as [modifier+][modifier+]...key + # Available modifiers are "ctrl", "mod1" (the alt-key), "mod2", + # "mod3" and "mod4" (windows-key). + # Xev might be helpful to find names for keys. + + # Close notification. + close = ctrl+space + + # Close all notifications. + close_all = ctrl+shift+space + + # Redisplay last message(s). + # On the US keyboard layout "grave" is normally above TAB and left + # of "1". Make sure this key actually exists on your keyboard layout, + # e.g. check output of 'xmodmap -pke' + history = ctrl+grave + + # Context menu. + context = ctrl+shift+period + +[urgency_low] + # IMPORTANT: colors have to be defined in quotation marks. + # Otherwise the "#" and following would be interpreted as a comment. + frame_color = "#2d3036" + background = "#222222" + foreground = "#22ee22" + timeout = 5 + # Icon for notifications with low urgency, uncomment to enable + #icon = /path/to/icon + +[urgency_normal] + frame_color = "#2d3036" + background = "#222222" + foreground = "#e6d947" + timeout = 5 + # Icon for notifications with normal urgency, uncomment to enable + #icon = /path/to/icon + +[urgency_critical] + frame_color = "#2d3036" + background = "#800000" + foreground = "#ffffff" + timeout = 0 + # Icon for notifications with critical urgency, uncomment to enable + #icon = /path/to/icon + +# Every section that isn't one of the above is interpreted as a rules to +# override settings for certain messages. +# Messages can be matched by "appname", "summary", "body", "icon", "category", +# "msg_urgency" and you can override the "timeout", "urgency", "foreground", +# "background", "new_icon" and "format". +# Shell-like globbing will get expanded. +# +# SCRIPTING +# You can specify a script that gets run when the rule matches by +# setting the "script" option. +# The script will be called as follows: +# script appname summary body icon urgency +# where urgency can be "LOW", "NORMAL" or "CRITICAL". +# +# NOTE: if you don't want a notification to be displayed, set the format +# to "". +# NOTE: It might be helpful to run dunst -print in a terminal in order +# to find fitting options for rules. + +#[espeak] +# summary = "*" +# script = dunst_espeak.sh + +#[script-test] +# summary = "*script*" +# script = dunst_test.sh + +#[ignore] +# # This notification will not be displayed +# summary = "foobar" +# format = "" + +#[history-ignore] +# # This notification will not be saved in history +# summary = "foobar" +# history_ignore = yes + +#[signed_on] +# appname = Pidgin +# summary = "*signed on*" +# urgency = low +# +#[signed_off] +# appname = Pidgin +# summary = *signed off* +# urgency = low +# +#[says] +# appname = Pidgin +# summary = *says* +# urgency = critical +# +#[twitter] +# appname = Pidgin +# summary = *twitter.com* +# urgency = normal +# +# vim: ft=cfg diff --git a/.linux_items/include/airootfs/etc/skel/.config/gtk-3.0/settings.ini b/.linux_items/include/airootfs/etc/skel/.config/gtk-3.0/settings.ini new file mode 100644 index 00000000..8ba66579 --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.config/gtk-3.0/settings.ini @@ -0,0 +1,16 @@ +[Settings] +gtk-theme-name=Arc-Dark +gtk-icon-theme-name=Papirus-Dark +gtk-font-name=Noto Sans 11 +gtk-cursor-theme-name=Adwaita +gtk-cursor-theme-size=0 +gtk-toolbar-style=GTK_TOOLBAR_BOTH +gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR +gtk-button-images=1 +gtk-menu-images=1 +gtk-enable-event-sounds=1 +gtk-enable-input-feedback-sounds=1 +gtk-xft-antialias=1 +gtk-xft-hinting=1 +gtk-xft-hintstyle=hintslight +gtk-xft-rgba=rgb diff --git a/.linux_items/include/airootfs/etc/skel/.config/i3/config b/.linux_items/include/airootfs/etc/skel/.config/i3/config new file mode 100644 index 00000000..dbbdee82 --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.config/i3/config @@ -0,0 +1,321 @@ +# This file has been auto-generated by i3-config-wizard(1). +# It will not be overwritten, so edit it as you like. +# +# Should you change your keyboard layout some time, delete +# this file and re-run i3-config-wizard(1). +# + +# i3 config file (v4) +# +# Please see http://i3wm.org/docs/userguide.html for a complete reference! + +set $mod Mod4 + +# Configure border style +new_window pixel 1 +new_float normal + +# Hide borders +hide_edge_borders none + +# Pulse Audio controls +bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume 0 +5% #increase sound volume +bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume 0 -5% #decrease sound volume +bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute 0 toggle # mute sound + +# alt+tab navi +bindsym Mod1+Tab workspace next +bindsym Mod1+Shift+Tab workspace prev + +# change borders +bindsym $mod+u border none +bindsym $mod+y border pixel 1 +bindsym $mod+n border normal + +# Font for window titles. Will also be used by the bar unless a different font +# is used in the bar {} block below. +#font Inconsolata:monospace 8 +font pango:Noto Sans Mono 10, FontAwesome 10 + +# This font is widely installed, provides lots of unicode glyphs, right-to-left +# text rendering and scalability on retina/hidpi displays (thanks to pango). +#font pango:DejaVu Sans Mono 8 + +# Before i3 v4.8, we used to recommend this one as the default: +# font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 +# The font above is very space-efficient, that is, it looks good, sharp and +# clear in small sizes. However, its unicode glyph coverage is limited, the old +# X core fonts rendering does not support right-to-left and this being a bitmap +# font, it doesn’t scale on retina/hidpi displays. + +# Use Mouse+$mod to drag floating windows to their wanted position +floating_modifier $mod + +# start a terminal +bindsym $mod+Return exec i3-sensible-terminal + +# kill focused window +bindsym $mod+Shift+q kill +bindsym $mod+q kill +bindsym Mod1+F4 kill + +# start dmenu (a program launcher) +#bindsym $mod+Shift+d exec dmenu_run +# There also is the (new) i3-dmenu-desktop which only displays applications +# shipping a .desktop file. It is a wrapper around dmenu, so you need that +# installed. +#bindsym $mod+Shift+d exec --no-startup-id i3-dmenu-desktop +bindsym $mod+r exec "rofi -combi-modi window,drun,run -show combi -modi combi" + +# misc app shortcuts +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+t exec "urxvt" +bindsym $mod+v exec "urxvt -title 'Hardware Sensors' -e watch -c -n1 -t hw-sensors" +bindsym $mod+w exec "firefox" + +focus_follows_mouse no + +# change focus +bindsym $mod+j focus left +bindsym $mod+k focus down +bindsym $mod+l focus up +bindsym $mod+semicolon focus right + +# alternatively, you can use the cursor keys: +bindsym $mod+Left focus left +bindsym $mod+Down focus down +bindsym $mod+Up focus up +bindsym $mod+Right focus right + +# move focused window +bindsym $mod+Shift+j move left +bindsym $mod+Shift+k move down +bindsym $mod+Shift+l move up +bindsym $mod+Shift+semicolon move right + +# alternatively, you can use the cursor keys: +bindsym $mod+Shift+Left move left +bindsym $mod+Shift+Down move down +bindsym $mod+Shift+Up move up +bindsym $mod+Shift+Right move right + +# workspace back and forth (with/without active container) +workspace_auto_back_and_forth yes +bindsym $mod+b workspace back_and_forth +bindsym $mod+Shift+b move container to workspace back_and_forth; workspace back_and_forth + +# split orientation +bindsym $mod+Shift+h split h +bindsym $mod+Shift+v split v + +# enter fullscreen mode for the focused container +bindsym $mod+Shift+f fullscreen toggle + +# change container layout (stacked, tabbed, toggle split) +bindsym $mod+Shift+s layout stacking +bindsym $mod+Shift+w layout tabbed +bindsym $mod+Shift+e layout toggle split + +# toggle tiling / floating +bindsym $mod+Shift+space floating toggle + +# change focus between tiling / floating windows +bindsym $mod+space focus mode_toggle + +# focus the parent container +#bindsym $mod+a focus parent + +# move the currently focused window to the scratchpad +bindsym $mod+Shift+minus move scratchpad + +# Show the next scratchpad window or hide the focused scratchpad window. +# If there are multiple scratchpad windows, this command cycles through them. +bindsym $mod+minus scratchpad show + +# focus the child container +#bindsym $mod+d focus child + +# Workspace names +set $ws1 "一" +set $ws2 "二" +set $ws3 "三" +set $ws4 "四" +set $ws5 "五" +set $ws6 "六" +set $ws7 "七" +set $ws8 "八" +set $ws9 "九" +set $ws10 "十" + +# switch to workspace +bindsym $mod+1 workspace $ws1 +bindsym $mod+2 workspace $ws2 +bindsym $mod+3 workspace $ws3 +bindsym $mod+4 workspace $ws4 +bindsym $mod+5 workspace $ws5 +bindsym $mod+6 workspace $ws6 +bindsym $mod+7 workspace $ws7 +bindsym $mod+8 workspace $ws8 +bindsym $mod+9 workspace $ws9 +bindsym $mod+0 workspace $ws10 + +# move focused container to workspace +bindsym $mod+Ctrl+1 move container to workspace $ws1 +bindsym $mod+Ctrl+2 move container to workspace $ws2 +bindsym $mod+Ctrl+3 move container to workspace $ws3 +bindsym $mod+Ctrl+4 move container to workspace $ws4 +bindsym $mod+Ctrl+5 move container to workspace $ws5 +bindsym $mod+Ctrl+6 move container to workspace $ws6 +bindsym $mod+Ctrl+7 move container to workspace $ws7 +bindsym $mod+Ctrl+8 move container to workspace $ws8 +bindsym $mod+Ctrl+9 move container to workspace $ws9 +bindsym $mod+Ctrl+0 move container to workspace $ws10 + +# move focused container to workspace and follow +bindsym $mod+Shift+1 move container to workspace $ws1; workspace $ws1 +bindsym $mod+Shift+2 move container to workspace $ws2; workspace $ws2 +bindsym $mod+Shift+3 move container to workspace $ws3; workspace $ws3 +bindsym $mod+Shift+4 move container to workspace $ws4; workspace $ws4 +bindsym $mod+Shift+5 move container to workspace $ws5; workspace $ws5 +bindsym $mod+Shift+6 move container to workspace $ws6; workspace $ws6 +bindsym $mod+Shift+7 move container to workspace $ws7; workspace $ws7 +bindsym $mod+Shift+8 move container to workspace $ws8; workspace $ws8 +bindsym $mod+Shift+9 move container to workspace $ws9; workspace $ws9 +bindsym $mod+Shift+0 move container to workspace $ws10; workspace $ws10 + +# Open specific applications in floating mode +for_window [class="Galculator"] floating enable border normal 5 +for_window [class="Nitrogen"] floating enable sticky enable border normal 5 +for_window [class="Thunar"] floating enable border normal 5 +for_window [class="mpv"] floating enable border normal 5 +for_window [title="Event Tester"] floating enable border normal 5 +for_window [title="Firefox"] floating enable border normal 5 +for_window [title="Hardware Diagnostics"] floating enable +for_window [title="Hardware Sensors"] floating enable +for_window [title="Mount All Volumes"] floating enable border normal 5 +for_window [title="Network Connections"] floating enable border normal 5 +for_window [title="Screen Layout Editor"] floating enable border normal 5 +for_window [title="Slack"] floating enable border normal 5 +for_window [title="System Information"] floating enable border normal 5 +for_window [title="Volume Control"] floating enable border normal 5 +for_window [title="Zenmap"] floating enable border normal 5 + +# switch to workspace with urgent window automatically +for_window [urgent=latest] focus + +# reload the configuration file +#bindsym $mod+Shift+c reload +# restart i3 inplace (preserves your layout/session, can be used to upgrade i3) +#bindsym $mod+Shift+r restart + +# resize window (you can also use the mouse for that) +mode "resize" { + # These bindings trigger as soon as you enter the resize mode + + # Pressing left will shrink the window’s width. + # Pressing right will grow the window’s width. + # Pressing up will shrink the window’s height. + # Pressing down will grow the window’s height. + bindsym j resize shrink width 10 px or 10 ppt + bindsym k resize grow height 10 px or 10 ppt + bindsym l resize shrink height 10 px or 10 ppt + bindsym semicolon resize grow width 10 px or 10 ppt + + # same bindings, but for the arrow keys + bindsym Left resize shrink width 10 px or 10 ppt + bindsym Down resize grow height 10 px or 10 ppt + bindsym Up resize shrink height 10 px or 10 ppt + bindsym Right resize grow width 10 px or 10 ppt + + # back to normal: Enter or Escape + bindsym Return mode "default" + bindsym Escape mode "default" +} + +bindsym $mod+Shift+r mode "resize" + +# "System" menu +bindsym $mod+x mode "$mode_system" +set $mode_system (l)ock, (e)xit, (r)eboot, (s)hutdown, (c)onfig, (i)3 +mode "$mode_system" { + bindsym l exec --no-startup-id i3lock, mode "default" + bindsym e exit, mode "default" + bindsym r exec reboot, mode "default" + bindsym s exec poweroff, mode "default" + bindsym c reload, mode "default" + bindsym i restart, mode "default" + + # exit system mode: "Enter" or "Escape" + bindsym Return mode "default" + bindsym Escape mode "default" +} + +############################# +### settings for i3-gaps: ### +############################# + +# Set inner/outer gaps +gaps inner 10 +gaps outer 4 + +# Additionally, you can issue commands with the following syntax. This is useful to bind keys to changing the gap size. +# gaps inner|outer current|all set|plus|minus +# gaps inner all set 10 +# gaps outer all plus 5 + +# Smart gaps (gaps used if only more than one container on the workspace) +smart_gaps on + +# Smart borders (draw borders around container only if it is not the only container on this workspace) +# on|no_gaps (on=always activate and no_gaps=only activate if the gap size to the edge of the screen is 0) +smart_borders on + +# Press $mod+Shift+g to enter the gap mode. Choose o or i for modifying outer/inner gaps. Press one of + / - (in-/decrement for current workspace) or 0 (remove gaps for current workspace). If you also press Shift with these keys, the change will be global for all workspaces. +set $mode_gaps Gaps: (o) outer, (i) inner +set $mode_gaps_outer Outer Gaps: +|-|0 (local), Shift + +|-|0 (global) +set $mode_gaps_inner Inner Gaps: +|-|0 (local), Shift + +|-|0 (global) +bindsym $mod+Shift+g mode "$mode_gaps" + +mode "$mode_gaps" { + bindsym o mode "$mode_gaps_outer" + bindsym i mode "$mode_gaps_inner" + bindsym Return mode "default" + bindsym Escape mode "default" +} +mode "$mode_gaps_inner" { + bindsym plus gaps inner current plus 5 + bindsym minus gaps inner current minus 5 + bindsym 0 gaps inner current set 0 + + bindsym Shift+plus gaps inner all plus 5 + bindsym Shift+minus gaps inner all minus 5 + bindsym Shift+0 gaps inner all set 0 + + bindsym Return mode "default" + bindsym Escape mode "default" +} +mode "$mode_gaps_outer" { + bindsym plus gaps outer current plus 5 + bindsym minus gaps outer current minus 5 + bindsym 0 gaps outer current set 0 + + bindsym Shift+plus gaps outer all plus 5 + bindsym Shift+minus gaps outer all minus 5 + bindsym Shift+0 gaps outer all set 0 + + bindsym Return mode "default" + bindsym Escape mode "default" +} + +# Start i3bar to display a workspace bar (plus the system information i3status +# finds out, if available) +bar { + position bottom + separator_symbol " " + status_command i3status + height 26 +} diff --git a/.linux_items/include/airootfs/etc/skel/.config/i3status/config b/.linux_items/include/airootfs/etc/skel/.config/i3status/config new file mode 100644 index 00000000..d36294a4 --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.config/i3status/config @@ -0,0 +1,76 @@ +# i3status configuration file. +# see "man i3status" for documentation. + +# It is important that this file is edited as UTF-8. +# The following line should contain a sharp s: +# ß +# If the above line is not correctly displayed, fix your editor first! + +general { + colors = true + interval = 5 +} + +#order += "disk /" +order += "wireless _first_" +order += "ethernet _first_" +order += "cpu_usage" +order += "battery all" +order += "volume master" +order += "tztime local" +#order += "tztime utc" + +cpu_usage { + format = " %usage" + max_threshold = 90 + #format_above_threshold = " %usage" + degraded_threshold = 75 + #format_above_degraded_threshold = " %usage" +} + +wireless _first_ { + format_up = " (%quality at %essid) %ip" + format_down = " Down" +} + +ethernet _first_ { + # if you use %speed, i3status requires root privileges + format_up = " %ip" + format_down = " Down" +} + +battery all { + integer_battery_capacity = true + format = "%status %percentage" + format_down = "" + status_chr = "" + status_bat = "" + status_unk = "" + status_full = "" + path = "/sys/class/power_supply/BAT%d/uevent" + low_threshold = 25 + threshold_type = percentage +} + +volume master { + format = " %volume" + format_muted = " muted" + device = "pulse" +} + +tztime local { + format = "%F %H:%M" +} + +tztime utc { + format = "%H:%M" + timezone = "UTC" +} + +load { + format = "%1min" +} + +disk "/" { + format = "%avail" +} diff --git a/.linux_items/include/airootfs/etc/skel/.config/mimeapps.list b/.linux_items/include/airootfs/etc/skel/.config/mimeapps.list new file mode 100644 index 00000000..e8beceeb --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.config/mimeapps.list @@ -0,0 +1,25 @@ +[Added Associations] +application/pdf=mupdf.desktop; +application/vnd.adobe.flash.movie=mpv.desktop; +application/vnd.ms-asf=mpv.desktop; +audio/flac=mpv.desktop; +audio/mp4=mpv.desktop; +audio/mpeg=mpv.desktop; +audio/x-vorbis+ogg=mpv.desktop; +image/bmp=ristretto.desktop; +image/gif=ristretto.desktop; +image/jpeg=ristretto.desktop; +image/png=ristretto.desktop; +image/vnd.microsoft.icon=ristretto.desktop; +inode/directory=exo-file-manager.desktop +text/plain=mousepad.desktop; +video/mp4=mpv.desktop; +video/mpeg=mpv.desktop; +video/quicktime=mpv.desktop; +video/x-flv=mpv.desktop; +video/x-matroska=mpv.desktop; +video/x-msvideo=mpv.desktop; +video/x-ms-wmv=mpv.desktop; +x-scheme-handler/http=exo-web-browser.desktop +x-scheme-handler/https=exo-web-browser.desktop +x-scheme-handler/trash=exo-file-manager.desktop diff --git a/.linux_items/include/airootfs/etc/skel/.config/openbox/autostart b/.linux_items/include/airootfs/etc/skel/.config/openbox/autostart new file mode 100644 index 00000000..21fd52e5 --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.config/openbox/autostart @@ -0,0 +1,19 @@ +# +# These things are run when an Openbox X Session is started. +# You may place a similar script in $HOME/.config/openbox/autostart +# to run user-specific things. +# + +# If you want to use GNOME config tools... +# +#if test -x /usr/lib/openbox/gnome-settings-daemon >/dev/null; then +# /usr/lib/openbox/gnome-settings-daemon & +#elif which gnome-settings-daemon >/dev/null 2>&1; then +# gnome-settings-daemon & +#fi + +# If you want to use XFCE config tools... +# +#xfce-mcs-manager & + +tint2 & diff --git a/.linux_items/include/airootfs/etc/skel/.config/openbox/environment b/.linux_items/include/airootfs/etc/skel/.config/openbox/environment new file mode 100644 index 00000000..3311bd6f --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.config/openbox/environment @@ -0,0 +1,10 @@ +# +# Set system-wide environment variables here for Openbox +# User-specific variables should be placed in $HOME/.config/openbox/environment +# + +# To set your language for displaying messages and time/date formats, use the following: +#LANG=en_CA.UTF8 + +# To set your keyboard layout, you need to modify your X config: +# http://www.google.com/search?q=how+to+set+keyboard+layout+xorg diff --git a/.linux_items/include/airootfs/etc/skel/.config/openbox/menu.xml b/.linux_items/include/airootfs/etc/skel/.config/openbox/menu.xml new file mode 100644 index 00000000..d0131dc3 --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.config/openbox/menu.xml @@ -0,0 +1,240 @@ + + + + + + + urxvt -t "Hardware Diagnostics" -e hw-diags + + + hardinfo + + + Thunar + + + gparted + + + gsmartcontrol + + + urxvt -title "Network Diagnostics" -hold -e hw-diags-network + + + firefox + + + + + + idle + + + urxvt -e python + + + urxvt -e python2.7 + + + urxvt -e tclsh8.6 + + + + + urxvt -e hexedit + + + urxvt -e nano + + + urxvt -e vi + + + urxvt -e vim + + + + + urxvt -e alsamixer + + + mpv + + + pavucontrol + + + qv4l2 + + + + + bssh + + + bvnc + + + urxvt -e elinks + + + firefox + + + urxvt -e ftp + + + urxvt -e irssi + + + urxvt -e lftp + + + urxvt -e mail + + + exo-open --launch MailReader + + + urxvt -e talk + + + urxvt -e telnet + + + urxvt -e tkvnc + + + exo-open --launch WebBrowser + + + zenmap + + + /usr/share/zenmap/su-to-zenmap.sh + + + + + urxvt -e bc + + + urxvt -e dc + + + + + urxvt -e mc + + + thunar + + + urxvt + + + urxvtc + + + urxvt-tabbed + + + uurxvt + + + + + + + nm-connection-editor + + + + thunar-settings + + + exo-preferred-applications + + + tint2conf + + + + avahi-discover + + + /usr/lib/Thunar/ThunarBulkRename + + + urxvt -e conky + + + gparted + + + gsmartcontrol_polkit + + + urxvt -e htop + + + obmenu + + + urxvt -e pstree + + + urxvt -e /usr/bin/pstree.x11 + + + urxvt -e pstree.x11 + + + hardinfo + + + tint2 + + + urxvt -e top + + + veracrypt + + + + + xfce4-about + + + compton --xrender-sync-fence + + + urxvt -e cmatrix + + + exo-open --launch FileManager + + + urxvt -e info + + + exo-open --launch TerminalEmulator + + + urxvt -e xev + + + + + + + + + + + oblogout + + + diff --git a/.linux_items/include/airootfs/etc/skel/.config/openbox/rc.xml b/.linux_items/include/airootfs/etc/skel/.config/openbox/rc.xml new file mode 100644 index 00000000..5ecc2eee --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.config/openbox/rc.xml @@ -0,0 +1,806 @@ + + + + + 10 + 20 + + + yes + + no + + yes + + no + + 200 + + no + + + + Smart + +
yes
+ + Primary + + 1 + +
+ + + 4 + Triste-Orange + NLIMC + + yes + yes + + sans + 8 + + bold + + normal + + + + sans + 8 + + bold + + normal + + + + sans + 9 + + normal + + normal + + + + sans + 9 + + normal + + normal + + + + sans + 9 + + bold + + normal + + + + sans + 9 + + bold + + normal + + + + + + 1 + 1 + + Arch + + 875 + + + + yes + Nonpixel + + Center + + + + 10 + + 10 + + + + + + 0 + 0 + 0 + 0 + + + TopLeft + + 0 + 0 + no + Above + + Vertical + + no + 300 + + 300 + + Middle + + + + C-g + + + + left + no + + + + + right + no + + + + + up + no + + + + + down + no + + + + + left + no + + + + + right + no + + + + + up + no + + + + + down + no + + + + + + + + + + + + + + client-menu + + + + + + + + + + + + + + + + + + + + + + + + yes + yes + + + + + + + + + + + right + + + + + left + + + + + up + + + + + down + + + + + + root-menu + + + + + urxvt -title "Hardware Diagnostics" -e hw-diags + + + + + thunar + + + + + hardinfo + + + + + urxvt -title "Mount all Volumes" -e mount-all-volumes gui + + + + + rofi -combi-modi window,drun,run -show combi -modi combi + + + + + urxvt -title "Hardware Diagnostics" -e hw-diags quick + + + + + urxvt + + + + + urxvt -title "Hardware Sensors" -e watch -c -n1 -t hw-sensors + + + + + firefox + + + + + oblogout + + + + + 1 + + 500 + + 400 + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + previous + + + + + next + + + + + previous + + + + + next + + + + + previous + + + + + next + + + + + + + + + + + + + no + + + + + + + + + + + yes + + + + + + + + + + + + + + + + + + + + + + + client-menu + + + + + + + top + + + + + + + left + + + + + + + right + + + + + + + bottom + + + + + + + client-menu + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + client-menu + + + + + + + client-menu + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + vertical + + + + + horizontal + + + + + + + + + + + + + + + + + previous + + + + + next + + + + + previous + + + + + next + + + + + previous + + + + + next + + + + + + + + + + + + + + + + client-list-combined-menu + + + + + root-menu + + + + + + + previous + + + + + next + + + + + previous + + + + + next + + + + + + + + menu.xml + 200 + + no + + 100 + + 400 + + yes + + yes + + + + + +
diff --git a/.linux_items/include/airootfs/etc/skel/.config/rofi/config b/.linux_items/include/airootfs/etc/skel/.config/rofi/config new file mode 100644 index 00000000..5c27c752 --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.config/rofi/config @@ -0,0 +1,11 @@ +! rofi theme +rofi.color-enabled: true +! bg border separator +rofi.color-window: argb:d02d3036, #2d3036, #d64937 +! bg fg bg-alt hl-bg hl-fg +rofi.color-normal: argb:d02d3036, #d8d8d8, argb:d02d3036, #2d3036, #d64937 +rofi.color-active: argb:d0222222, #d64937, argb:d0222222, #d64937, #d8d8d8 +rofi.color-urgent: argb:d0888888, #d8d8d8, argb:d0888888, #888888, #d64937 + +rofi.separator-style: solid +rofi.hide-scrollbar: true diff --git a/.linux_items/include/airootfs/etc/skel/.config/tint2/tint2rc b/.linux_items/include/airootfs/etc/skel/.config/tint2/tint2rc new file mode 100644 index 00000000..a0319768 --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.config/tint2/tint2rc @@ -0,0 +1,250 @@ +#---- Generated by tint2conf 2152 ---- +# See https://gitlab.com/o9000/tint2/wikis/Configure for +# full documentation of the configuration options. +#------------------------------------- +# Gradients +#------------------------------------- +# Backgrounds +# Background 1: Active task, Active taskbar, Default task, Iconified task, Inactive desktop name, Inactive taskbar, Panel, Urgent task +rounded = 0 +border_width = 0 +border_sides = TBLR +background_color = #2d3036 100 +border_color = #2d3036 100 +background_color_hover = #2d3036 100 +border_color_hover = #2d3036 100 +background_color_pressed = #2d3036 100 +border_color_pressed = #2d3036 100 + +# Background 2: +rounded = 1 +border_width = 0 +border_sides = TBLR +background_color = #d8d8d8 30 +border_color = #d8d8d8 30 +background_color_hover = #d8d8d8 30 +border_color_hover = #d8d8d8 30 +background_color_pressed = #d8d8d8 30 +border_color_pressed = #d8d8d8 30 + +# Background 3: +rounded = 1 +border_width = 0 +border_sides = TBLR +background_color = #000000 0 +border_color = #000000 0 +background_color_hover = #000000 0 +border_color_hover = #000000 0 +background_color_pressed = #000000 0 +border_color_pressed = #000000 0 + +# Background 4: +rounded = 1 +border_width = 1 +border_sides = TBLR +background_color = #888888 20 +border_color = #ed2323 60 +background_color_hover = #888888 20 +border_color_hover = #ed2323 60 +background_color_pressed = #888888 20 +border_color_pressed = #ed2323 60 + +# Background 5: +rounded = 0 +border_width = 1 +border_sides = TBLR +background_color = #000000 0 +border_color = #000000 0 +background_color_hover = #000000 0 +border_color_hover = #000000 0 +background_color_pressed = #000000 0 +border_color_pressed = #000000 0 + +# Background 6: +rounded = 0 +border_width = 1 +border_sides = TBLR +background_color = #d8d8d8 8 +border_color = #d8d8d8 0 +background_color_hover = #d8d8d8 8 +border_color_hover = #d8d8d8 0 +background_color_pressed = #d8d8d8 8 +border_color_pressed = #d8d8d8 0 + +# Background 7: Tooltip +rounded = 3 +border_width = 0 +border_sides = TBLR +background_color = #222222 90 +border_color = #222222 90 +background_color_hover = #222222 90 +border_color_hover = #222222 90 +background_color_pressed = #222222 90 +border_color_pressed = #222222 90 + +# Background 8: +rounded = 1 +border_width = 1 +border_sides = TBLR +background_color = #888888 20 +border_color = #888888 20 +background_color_hover = #888888 20 +border_color_hover = #888888 20 +background_color_pressed = #888888 20 +border_color_pressed = #888888 20 + +# Background 9: Active desktop name, Clock +rounded = 1 +border_width = 1 +border_sides = TBLR +background_color = #d64937 100 +border_color = #d64937 100 +background_color_hover = #d64937 100 +border_color_hover = #d64937 100 +gradient_id_hover = 0 +background_color_pressed = #d64937 100 +border_color_pressed = #d64937 100 + +#------------------------------------- +# Panel +panel_items = TSC +panel_size = 100% 30 +panel_margin = 0 0 +panel_padding = 0 0 0 +panel_background_id = 1 +wm_menu = 1 +panel_dock = 0 +panel_position = bottom center horizontal +panel_layer = bottom +panel_monitor = all +primary_monitor_first = 0 +panel_shrink = 0 +autohide = 0 +autohide_show_timeout = 0.3 +autohide_hide_timeout = 1.5 +autohide_height = 6 +strut_policy = follow_size +panel_window_name = tint2 +disable_transparency = 0 +mouse_effects = 0 +font_shadow = 0 +mouse_hover_icon_asb = 100 0 10 +mouse_pressed_icon_asb = 100 0 0 + +#------------------------------------- +# Taskbar +taskbar_mode = single_desktop +taskbar_hide_if_empty = 0 +taskbar_padding = 2 2 0 +taskbar_background_id = 1 +taskbar_active_background_id = 1 +taskbar_name = 1 +taskbar_hide_inactive_tasks = 0 +taskbar_hide_different_monitor = 0 +taskbar_always_show_all_desktop_tasks = 1 +taskbar_name_padding = 5 2 +taskbar_name_background_id = 1 +taskbar_name_active_background_id = 9 +taskbar_name_font = Inconsolata 10 +taskbar_name_font_color = #a9a9a9 100 +taskbar_name_active_font_color = #ffffff 100 +taskbar_distribute_size = 1 +taskbar_sort_order = title +task_align = left + +#------------------------------------- +# Task +task_text = 1 +task_icon = 0 +task_centered = 1 +urgent_nb_of_blink = 20 +task_maximum_size = 200 30 +task_padding = 2 2 2 +task_font = Inconsolata 10 +task_tooltip = 1 +task_font_color = #a8adb5 100 +task_active_font_color = #ffffff 100 +task_urgent_font_color = #a8adb5 100 +task_iconified_font_color = #a8adb5 100 +task_icon_asb = 100 0 0 +task_active_icon_asb = 100 0 0 +task_urgent_icon_asb = 100 0 0 +task_iconified_icon_asb = 80 0 0 +task_background_id = 1 +task_active_background_id = 1 +task_urgent_background_id = 1 +task_iconified_background_id = 1 +mouse_left = toggle_iconify +mouse_middle = none +mouse_right = close +mouse_scroll_up = toggle +mouse_scroll_down = iconify + +#------------------------------------- +# System tray (notification area) +systray_padding = 4 2 3 +systray_background_id = 0 +systray_sort = right2left +systray_icon_size = 24 +systray_icon_asb = 100 0 0 +systray_monitor = 1 +systray_name_filter = + +#------------------------------------- +# Launcher +launcher_padding = 8 4 4 +launcher_background_id = 0 +launcher_icon_background_id = 0 +launcher_icon_size = 0 +launcher_icon_asb = 100 0 0 +launcher_icon_theme_override = 0 +startup_notifications = 0 +launcher_tooltip = 1 + +#------------------------------------- +# Clock +#time1_format = %a, %d %B @ %H:%M +time1_format = %F %H:%M +time2_format = +time1_font = Inconsolata 10 +time1_timezone = +time2_timezone = +clock_font_color = #ffffff 100 +clock_padding = 4 4 +clock_background_id = 9 +clock_tooltip = +clock_tooltip_timezone = +clock_lclick_command = +clock_rclick_command = +clock_mclick_command = +clock_uwheel_command = +clock_dwheel_command = + +#------------------------------------- +# Battery +battery_tooltip = 1 +battery_low_status = 20 +battery_low_cmd = notify-send "battery low" +bat1_font = Inconsolata 12 +bat2_font = Inconsolata 12 +battery_font_color = #b5b5b5 100 +battery_padding = 2 0 +battery_background_id = 0 +battery_hide = 96 +battery_lclick_command = +battery_rclick_command = +battery_mclick_command = +battery_uwheel_command = +battery_dwheel_command = +ac_connected_cmd = +ac_disconnected_cmd = + +#------------------------------------- +# Tooltip +tooltip_show_timeout = 0 +tooltip_hide_timeout = 0 +tooltip_padding = 2 2 +tooltip_background_id = 7 +tooltip_font_color = #d8d8d8 100 +tooltip_font = Inconsolata 12 + diff --git a/.linux_items/include/airootfs/etc/skel/.conky_start b/.linux_items/include/airootfs/etc/skel/.conky_start new file mode 100755 index 00000000..c7230b17 --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.conky_start @@ -0,0 +1,10 @@ +#!/bin/bash + +CONKY_RC="$HOME/.conkyrc" +if [[ -f "/run/archiso/bootmnt/arch/conky.rc" ]]; then + CONKY_RC="/run/archiso/bootmnt/arch/conky.rc" +fi + +sleep 2s && conky -c "${CONKY_RC}" -dq +sleep 5s && killall conky -c "${CONKY_RC}" -dq + diff --git a/.linux_items/include/airootfs/etc/skel/.conkyrc b/.linux_items/include/airootfs/etc/skel/.conkyrc new file mode 100644 index 00000000..adfd5cbb --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.conkyrc @@ -0,0 +1,166 @@ +# For commands above TEXT check: +# http://conky.sourceforge.net/config_settings.html +# +# For commands available below TEXT check: +# http://conky.sourceforge.net/variables.html + +# Bunsen Labs Conky help threads +# http://crunchbang.org/forums/viewtopic.php?pid=371424#p371424 + +# beta tested by: smacz +# Enjoy! :) + +# pkill -xf "conky -q -c $HOME/.config/conky/BL-Default.conkyrc" & +### Begin Window Settings ##################### +own_window yes +#own_window_type override +own_window_transparent no +own_window_hints undecorated,below,skip_taskbar,skip_pager,sticky +own_window_colour 000000 +own_window_class Conky +#own_window_title Bunsen Labs Default Conky +own_window_title Default Conky + +### ARGB can be used for real transparency +### NOTE that a composite manager is required for real transparency. +### This option will not work as desired (in most cases) in conjunction with +### own_window_type normal +own_window_argb_visual yes # Options: yes or no + +### When ARGB visuals are enabled, this use this to modify the alpha value +### Use: own_window_type normal +### Use: own_window_transparent no +### Valid range is 0-255, where 0 is 0% opacity, and 255 is 100% opacity. +own_window_argb_value 224 + +minimum_size 180 0 ### width | height +maximum_width 180 + +gap_x 20 ### left | right +gap_y 45 ### up | down + +alignment tr +####################### End Window Settings ### +### Font Settings ############################# +# Use Xft (anti-aliased font and stuff) +use_xft yes +xftfont Inconsolata:bold:size=9 +#xftfont Liberation Sans:size=9 + +# Alpha of Xft font. Must be a value at or between 1 and 0 ### +xftalpha 1 +# Force UTF8? requires XFT ### +override_utf8_locale yes + +uppercase no +######################### End Font Settings ### +### Colour Settings ########################### +draw_shades no #yes +default_shade_color 000000 + +draw_outline no # amplifies text if yes +default_outline_color 000000 + +#default_color 656667 # Waldorf original colour +#default_color 7a7a7a # Flame & Bunsen Grey +#default_color 929292 # Labs Grey +default_color C0C0C0 # Silver +color0 B0E0E6 # PowderBlue +color1 778899 # LightSlateGray +color2 D8BFD8 # Thistle +color3 9ACD32 # YellowGreen +color4 FFA07A # LightSalmon +color5 FFDEAD # NavajoWhite +color6 00BFFF # DeepSkyBlue +color7 5F9EA0 # CadetBlue +color8 BDB76B # DarkKhaki +color9 CD5C5C # IndianRed +####################### End Colour Settings ### +### Borders Section ########################### +draw_borders no +# Stippled borders? +stippled_borders 5 +# border margins +border_inner_margin 5 +border_outer_margin 0 +# border width +border_width 2 +# graph borders +draw_graph_borders yes #no +#default_graph_size 15 40 +####################### End Borders Section ### +### Miscellaneous Section ##################### +# Boolean value, if true, Conky will be forked to background when started. +background yes + +# Adds spaces around certain objects to stop them from moving other things +# around, this only helps if you are using a mono font +# Options: right, left or none +use_spacer none + +# Default and Minimum size is 256 - needs more for single commands that +# "call" a lot of text IE: bash scripts +text_buffer_size 6144 + +# Subtract (file system) buffers from used memory? +no_buffers yes + +# change GiB to G and MiB to M +short_units yes + +# Like it says, ot pads the decimals on % values +# doesn't seem to work since v1.7.1 +pad_percents 2 + +# Imlib2 image cache size, in bytes. Default 4MiB Increase this value if you use +# $image lots. Set to 0 to disable the image cache. +imlib_cache_size 0 + +# Use the Xdbe extension? (eliminates flicker) +# It is highly recommended to use own window with this one +# so double buffer won't be so big. +double_buffer yes + +# Maximum size of user text buffer, i.e. layout below TEXT line in config file +# (default is 16384 bytes) +# max_user_text 16384 + +# Desired output unit of all objects displaying a temperature. Parameters are +# either "fahrenheit" or "celsius". The default unit is degree Celsius. +# temperature_unit Fahrenheit + +################# End Miscellaneous Section ### +#### ${font Monospace:bold:size=10}${alignc}${execpi 600 $HOME/.config/conky/scripts/bunsenweather.sh} +update_interval 1 + +TEXT +${color}${alignc}S Y S T E M I N F O +${hr} +Date:${alignr}${time %F} +Time:${alignr}${time %H:%M} +Uptime:${alignr}${uptime_short} + +CPU: ${if_match ${cpu cpu0}<10} ${cpu cpu0}\ +${else}${if_match ${cpu cpu0}<100} ${cpu cpu0}\ +${else}${cpu cpu0}${endif}${endif}% Used${alignr}${freq_g} GHz +${cpugraph cpu0 20,180 ${color} ${color}} +RAM: ${mem} Used${alignr}${memmax} +${memgraph 20,180 ${color} ${color}} +Disk I/O: +${diskiograph 20,180 ${color} ${color}} +Down: ${downspeed}${goto 115}Up:${alignr}${upspeed} + +#Network + +${alignc}S H O R T C U T K E Y S +${hr} +[Super] + d${alignr}HW Diagnostics +[Super] + f${alignr}File Manager +[Super] + i${alignr}HW Information +[Super] + m${alignr}Mount Volumes +[Super] + r${alignr}Run Dialog +[Super] + s${alignr}SMART Check +[Super] + t${alignr}Terminal +[Super] + v${alignr}View Temps +[Super] + w${alignr}Web Browser +[Super] + x${alignr}Logout diff --git a/.linux_items/include/airootfs/etc/skel/.dircolors b/.linux_items/include/airootfs/etc/skel/.dircolors new file mode 100644 index 00000000..ccb0d187 --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.dircolors @@ -0,0 +1,193 @@ +# Configuration file for dircolors, a utility to help you set the +# LS_COLORS environment variable used by GNU ls with the --color option. +# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# Copying and distribution of this file, with or without modification, +# are permitted provided the copyright notice and this notice are preserved. +# The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the +# slackware version of dircolors) are recognized but ignored. +# Below are TERM entries, which can be a glob patterns, to match +# against the TERM environment variable to determine if it is colorizable. +TERM Eterm +TERM ansi +TERM *color* +TERM con[0-9]*x[0-9]* +TERM cons25 +TERM console +TERM cygwin +TERM dtterm +TERM gnome +TERM hurd +TERM jfbterm +TERM konsole +TERM kterm +TERM linux +TERM linux-c +TERM mlterm +TERM putty +TERM rxvt* +TERM screen* +TERM st +TERM terminator +TERM tmux* +TERM vt100 +TERM xterm* +# Below are the color init strings for the basic file types. A color init +# string consists of one or more of the following numeric codes: +# Attribute codes: +# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed +# Text color codes: +# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white +# Background color codes: +# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white +#NORMAL 00 # no color code at all +#FILE 00 # regular file: use no color at all +RESET 0 # reset to "normal" color +DIR 01;34 # directory +LINK 01;36 # symbolic link. (If you set this to 'target' instead of a + # numerical value, the color is as for the file pointed to.) +MULTIHARDLINK 00 # regular file with more than one link +FIFO 40;33 # pipe +SOCK 01;35 # socket +DOOR 01;35 # door +BLK 40;33;01 # block device driver +CHR 40;33;01 # character device driver +ORPHAN 40;31;01 # symlink to nonexistent file, or non-stat'able file ... +MISSING 00 # ... and the files they point to +SETUID 37;41 # file that is setuid (u+s) +SETGID 30;43 # file that is setgid (g+s) +CAPABILITY 30;41 # file with capability +STICKY_OTHER_WRITABLE 40;33;01 # dir that is sticky and other-writable (+t,o+w) +OTHER_WRITABLE 40;33 # dir that is other-writable (o+w) and not sticky +STICKY 37;44 # dir with the sticky bit set (+t) and not other-writable +# This is for files with execute permission: +EXEC 01;32 +# List any file extensions like '.gz' or '.tar' that you would like ls +# to colorize below. Put the extension, a space, and the color init string. +# (and any comments you want to add after a '#') +# If you use DOS-style suffixes, you may want to uncomment the following: +#.cmd 01;32 # executables (bright green) +#.exe 01;32 +#.com 01;32 +#.btm 01;32 +#.bat 01;32 +# Or if you want to colorize scripts even if they do not have the +# executable bit actually set. +#.sh 01;32 +#.csh 01;32 + # archives or compressed (bright red) +.tar 01;31 +.tgz 01;31 +.arc 01;31 +.arj 01;31 +.taz 01;31 +.lha 01;31 +.lz4 01;31 +.lzh 01;31 +.lzma 01;31 +.tlz 01;31 +.txz 01;31 +.tzo 01;31 +.t7z 01;31 +.zip 01;31 +.z 01;31 +.Z 01;31 +.dz 01;31 +.gz 01;31 +.lrz 01;31 +.lz 01;31 +.lzo 01;31 +.xz 01;31 +.zst 01;31 +.tzst 01;31 +.bz2 01;31 +.bz 01;31 +.tbz 01;31 +.tbz2 01;31 +.tz 01;31 +.deb 01;31 +.rpm 01;31 +.jar 01;31 +.war 01;31 +.ear 01;31 +.sar 01;31 +.rar 01;31 +.alz 01;31 +.ace 01;31 +.zoo 01;31 +.cpio 01;31 +.7z 01;31 +.rz 01;31 +.cab 01;31 +.wim 01;31 +.swm 01;31 +.dwm 01;31 +.esd 01;31 +# image formats +.jpg 01;35 +.jpeg 01;35 +.mjpg 01;35 +.mjpeg 01;35 +.gif 01;35 +.bmp 01;35 +.pbm 01;35 +.pgm 01;35 +.ppm 01;35 +.tga 01;35 +.xbm 01;35 +.xpm 01;35 +.tif 01;35 +.tiff 01;35 +.png 01;35 +.svg 01;35 +.svgz 01;35 +.mng 01;35 +.pcx 01;35 +.mov 01;35 +.mpg 01;35 +.mpeg 01;35 +.m2v 01;35 +.mkv 01;35 +.webm 01;35 +.ogm 01;35 +.mp4 01;35 +.m4v 01;35 +.mp4v 01;35 +.vob 01;35 +.qt 01;35 +.nuv 01;35 +.wmv 01;35 +.asf 01;35 +.rm 01;35 +.rmvb 01;35 +.flc 01;35 +.avi 01;35 +.fli 01;35 +.flv 01;35 +.gl 01;35 +.dl 01;35 +.xcf 01;35 +.xwd 01;35 +.yuv 01;35 +.cgm 01;35 +.emf 01;35 +# https://wiki.xiph.org/MIME_Types_and_File_Extensions +.ogv 01;35 +.ogx 01;35 +# audio formats +.aac 00;36 +.au 00;36 +.flac 00;36 +.m4a 00;36 +.mid 00;36 +.midi 00;36 +.mka 00;36 +.mp3 00;36 +.mpc 00;36 +.ogg 00;36 +.ra 00;36 +.wav 00;36 +# https://wiki.xiph.org/MIME_Types_and_File_Extensions +.oga 00;36 +.opus 00;36 +.spx 00;36 +.xspf 00;36 diff --git a/.linux_items/include/airootfs/etc/skel/.gtkrc-2.0 b/.linux_items/include/airootfs/etc/skel/.gtkrc-2.0 new file mode 100644 index 00000000..b54a0f5f --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.gtkrc-2.0 @@ -0,0 +1,19 @@ +# DO NOT EDIT! This file will be overwritten by LXAppearance. +# Any customization should be done in ~/.gtkrc-2.0.mine instead. + +include "/home/wktech/.gtkrc-2.0.mine" +gtk-theme-name="Arc-Dark" +gtk-icon-theme-name="Papirus-Dark" +gtk-font-name="Noto Sans 11" +gtk-cursor-theme-name="Adwaita" +gtk-cursor-theme-size=0 +gtk-toolbar-style=GTK_TOOLBAR_BOTH +gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR +gtk-button-images=1 +gtk-menu-images=1 +gtk-enable-event-sounds=1 +gtk-enable-input-feedback-sounds=1 +gtk-xft-antialias=1 +gtk-xft-hinting=1 +gtk-xft-hintstyle="hintslight" +gtk-xft-rgba="rgb" diff --git a/.linux_items/include/airootfs/etc/skel/.rsync_exclusions b/.linux_items/include/airootfs/etc/skel/.rsync_exclusions new file mode 100644 index 00000000..a3586dc8 --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.rsync_exclusions @@ -0,0 +1,30 @@ +$RECYCLE.BIN +$Recycle.Bin +.AppleDB +.AppleDesktop +.AppleDouble +.com.apple.timemachine.supported +.dbfseventsd +.DocumentRevisions-V100* +.DS_Store +.fseventsd +.PKInstallSandboxManager +.Spotlight* +.SymAV* +.symSchedScanLockxz +.TemporaryItems +.Trash* +.vol +.VolumeIcon.icns +desktop.ini +Desktop DB +Desktop DF +hiberfil.sys +lost+found +Network Trash Folder +pagefile.sys +Recycled +RECYCLER +System Volume Information +Temporary Items +Thumbs.db \ No newline at end of file diff --git a/.linux_items/include/airootfs/etc/skel/.tmux.conf b/.linux_items/include/airootfs/etc/skel/.tmux.conf new file mode 100644 index 00000000..a3712835 --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.tmux.conf @@ -0,0 +1,7 @@ +set -g status off +set -g pane-active-border-fg white + +# Window names +set -g set-titles on +set -g set-titles-string '#W' +setw -g automatic-rename diff --git a/.linux_items/include/airootfs/etc/skel/.update_conky b/.linux_items/include/airootfs/etc/skel/.update_conky new file mode 100755 index 00000000..f67dc893 --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.update_conky @@ -0,0 +1,16 @@ +#!/bin/bash + +IF_LIST=($(ip l | egrep '^[0-9]+:\s+(eth|en|wl)' | sed -r 's/^[0-9]+:\s+(\w+):.*/\1/' | sort)) + +# Add interfaces to conkyrc +for i in "${IF_LIST[@]}"; do + if [[ "${i:0:1}" == "e" ]]; then + sed -i -r "s/#Network/Wired:\${alignr}\${addr $i}\n#Network/" ~/.conkyrc + else + sed -i -r "s/#Network/Wireless:\${alignr}\${addr $i}\n#Network/" ~/.conkyrc + fi +done + +# Remove '#Network' line to prevent duplicating lines if this script is re-run +sed -i -r "s/#Network//" ~/.conkyrc + diff --git a/.linux_items/include/airootfs/etc/skel/.update_wallpaper b/.linux_items/include/airootfs/etc/skel/.update_wallpaper new file mode 100755 index 00000000..7bffa12b --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.update_wallpaper @@ -0,0 +1,21 @@ +#!/bin/bash + +BOOT_PATH="/run/archiso/bootmnt/arch/" +BURNED_IN="/usr/share/wallpaper/burned.in" +WALLPAPER="$HOME/.wallpaper.png" + +function link_wall() { + sudo rm "$WALLPAPER" + sudo ln -s "$1" "$WALLPAPER" +} + +# Check for wallpaper +## Checks BOOT_PATH and uses the BURNED_IN file if nothing is found +for f in "$BOOT_PATH"/{Arch,arch}.{jpg,png} "$BURNED_IN"; do + if [[ -f "$f" ]]; then + link_wall "$f" + break + fi +done + +feh --bg-fill "$WALLPAPER" diff --git a/.linux_items/include/airootfs/etc/skel/.urxvt_default_res b/.linux_items/include/airootfs/etc/skel/.urxvt_default_res new file mode 100755 index 00000000..1e146090 --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.urxvt_default_res @@ -0,0 +1,10 @@ +#!/bin/bash + +XWIDTH="$(xrandr 2>/dev/null | grep '*' | sed -r 's/^\s+([0-9]+)x.*/\1/')" +XHEIGHT="$(xrandr 2>/dev/null | grep '*' | sed -r 's/^\s+[0-9]+x([0-9]+).*/\1/')" + +WIDTH="$(echo "${XWIDTH}*92/1024" | bc)" +HEIGHT="$(echo "${XHEIGHT}*32/768" | bc)" + +sed -i -r "s/(URxvt.geometry:\s+).*/\1${WIDTH}x${HEIGHT}+24+24/" ~/.Xresources +xrdb -merge ~/.Xresources diff --git a/.linux_items/include/airootfs/etc/skel/.vimrc b/.linux_items/include/airootfs/etc/skel/.vimrc new file mode 100644 index 00000000..d65c6a91 --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.vimrc @@ -0,0 +1,64 @@ +" All system-wide defaults are set in $VIMRUNTIME/debian.vim (usually just +" /usr/share/vim/vimcurrent/debian.vim) and sourced by the call to :runtime +" you can find below. If you wish to change any of those settings, you should +" do it in this file (/etc/vim/vimrc), since debian.vim will be overwritten +" everytime an upgrade of the vim packages is performed. It is recommended to +" make changes after sourcing debian.vim since it alters the value of the +" 'compatible' option. + +" This line should not be removed as it ensures that various options are +" properly set to work with the Vim-related packages available in Debian. +runtime! debian.vim + +" Uncomment the next line to make Vim more Vi-compatible +" NOTE: debian.vim sets 'nocompatible'. Setting 'compatible' changes numerous +" options, so any other options should be set AFTER setting 'compatible'. +"set compatible + +" Vim5 and later versions support syntax highlighting. Uncommenting the next +" line enables syntax highlighting by default. +syntax on + +" If using a dark background within the editing area and syntax highlighting +" turn on this option as well +set background=dark + +" Uncomment the following to have Vim jump to the last position when +" reopening a file +"if has("autocmd") +" au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif +"endif + +" Uncomment the following to have Vim load indentation rules and plugins +" according to the detected filetype. +"if has("autocmd") +" filetype plugin indent on +"endif + +" The following are commented out as they cause vim to behave a lot +" differently from regular Vi. They are highly recommended though. +"set showcmd " Show (partial) command in status line. +set showmatch " Show matching brackets. +"set ignorecase " Do case insensitive matching +"set smartcase " Do smart case matching +"set incsearch " Incremental search +"set autowrite " Automatically save before commands like :next and :make +"set hidden " Hide buffers when they are abandoned +"set mouse=a " Enable mouse usage (all modes) + +" Source a global configuration file if available +if filereadable("/etc/vim/vimrc.local") + source /etc/vim/vimrc.local +endif + +" 2Shirt Stuff +set autoindent " align the new line indent with the previous line +set expandtab " insert spaces when hitting TABs +set shiftround " round indent to multiple of 'shiftwidth' +set shiftwidth=4 " operation >> indents 4 columns; << unindents 4 columns +set softtabstop=4 " insert/delete 4 spaces when hitting a TAB/BACKSPACE +set tabstop=4 " an hard TAB displays as 4 columns + +" Python Stuff. +au FileType python set textwidth=79 " lines longer than 79 columns will be broken + diff --git a/.linux_items/include/airootfs/etc/skel/.xinitrc b/.linux_items/include/airootfs/etc/skel/.xinitrc new file mode 100755 index 00000000..918fc507 --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.xinitrc @@ -0,0 +1,20 @@ +#!/bin/sh + +dbus-update-activation-environment --systemd DISPLAY +xrdb -merge $HOME/.Xresources +xset s off +xset -dpms +eval $(ssh-agent) +export SSH_AUTH_SOCK +compton & +sleep 1s +conky -d +nm-applet & +cbatticon & +pasystray & +connect-to-network & +(sleep 5s && killall dunst) & +$HOME/.urxvt_default_res & +$HOME/.update_wallpaper & +$HOME/.update_conky & +exec openbox-session diff --git a/.linux_items/include/airootfs/etc/skel/.zlogin b/.linux_items/include/airootfs/etc/skel/.zlogin new file mode 100644 index 00000000..26463919 --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.zlogin @@ -0,0 +1,13 @@ +setterm -blank 0 -powerdown 0 +if [ "$(fgconsole 2>/dev/null)" -eq "1" ]; then + 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 + if ! fgrep -q "nox" /proc/cmdline; then + startx >/dev/null + else + hw-diags cli + fi +fi + diff --git a/.linux_items/include/airootfs/etc/skel/.zshrc b/.linux_items/include/airootfs/etc/skel/.zshrc new file mode 100644 index 00000000..59a747eb --- /dev/null +++ b/.linux_items/include/airootfs/etc/skel/.zshrc @@ -0,0 +1,11 @@ +# Oh My ZSH +export ZSH=$HOME/.oh-my-zsh +ZSH_THEME="lean" +DISABLE_AUTO_UPDATE="true" +HIST_STAMPS="yyyy-mm-dd" +plugins=(archlinux git sudo systemd tmux) +source $ZSH/oh-my-zsh.sh + +# Wizard Kit +. $HOME/.aliases +eval $(dircolors ~/.dircolors) diff --git a/.linux_items/include/airootfs/etc/systemd/system/multi-user.target.wants/NetworkManager.service b/.linux_items/include/airootfs/etc/systemd/system/multi-user.target.wants/NetworkManager.service new file mode 120000 index 00000000..e874a9b3 --- /dev/null +++ b/.linux_items/include/airootfs/etc/systemd/system/multi-user.target.wants/NetworkManager.service @@ -0,0 +1 @@ +/usr/lib/systemd/system/NetworkManager.service \ No newline at end of file diff --git a/.linux_items/include/airootfs/etc/systemd/system/multi-user.target.wants/rngd.service b/.linux_items/include/airootfs/etc/systemd/system/multi-user.target.wants/rngd.service new file mode 120000 index 00000000..5f6432cf --- /dev/null +++ b/.linux_items/include/airootfs/etc/systemd/system/multi-user.target.wants/rngd.service @@ -0,0 +1 @@ +/usr/lib/systemd/system/rngd.service \ No newline at end of file diff --git a/.linux_items/include/airootfs/etc/systemd/system/multi-user.target.wants/sshd.service b/.linux_items/include/airootfs/etc/systemd/system/multi-user.target.wants/sshd.service new file mode 120000 index 00000000..d21ebd9d --- /dev/null +++ b/.linux_items/include/airootfs/etc/systemd/system/multi-user.target.wants/sshd.service @@ -0,0 +1 @@ +/usr/lib/systemd/system/sshd.service \ No newline at end of file diff --git a/.linux_items/include/airootfs/etc/systemd/system/multi-user.target.wants/systemd-timesyncd.service b/.linux_items/include/airootfs/etc/systemd/system/multi-user.target.wants/systemd-timesyncd.service new file mode 120000 index 00000000..cd004113 --- /dev/null +++ b/.linux_items/include/airootfs/etc/systemd/system/multi-user.target.wants/systemd-timesyncd.service @@ -0,0 +1 @@ +/usr/lib/systemd/system/systemd-timesyncd.service \ No newline at end of file diff --git a/.linux_items/include/airootfs/etc/systemd/system/multi-user.target.wants/ufw.service b/.linux_items/include/airootfs/etc/systemd/system/multi-user.target.wants/ufw.service new file mode 120000 index 00000000..86a21504 --- /dev/null +++ b/.linux_items/include/airootfs/etc/systemd/system/multi-user.target.wants/ufw.service @@ -0,0 +1 @@ +/usr/lib/systemd/system/ufw.service \ No newline at end of file diff --git a/.linux_items/include/airootfs/etc/udev/rules.d/99-udisks2.rules b/.linux_items/include/airootfs/etc/udev/rules.d/99-udisks2.rules new file mode 100644 index 00000000..996e4343 --- /dev/null +++ b/.linux_items/include/airootfs/etc/udev/rules.d/99-udisks2.rules @@ -0,0 +1,5 @@ +# UDISKS_FILESYSTEM_SHARED +# ==1: mount filesystem to a shared directory (/media/VolumeName) +# ==0: mount filesystem to a private directory (/run/media/$USER/VolumeName) +# See udisks(8) +ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{UDISKS_FILESYSTEM_SHARED}="1" diff --git a/.linux_items/include/airootfs/etc/udevil/udevil.conf b/.linux_items/include/airootfs/etc/udevil/udevil.conf new file mode 100644 index 00000000..b61d2c30 --- /dev/null +++ b/.linux_items/include/airootfs/etc/udevil/udevil.conf @@ -0,0 +1,336 @@ +############################################################################## +# +# udevil configuration file /etc/udevil/udevil.conf +# +# This file controls what devices, networks, and files users may mount and +# unmount via udevil (set suid). +# +# IMPORTANT: IT IS POSSIBLE TO CREATE SERIOUS SECURITY PROBLEMS IF THIS FILE +# IS MISCONFIGURED - EDIT WITH CARE +# +# Note: For greater control for specific users, including root, copy this +# file to /etc/udevil/udevil-user-USERNAME.conf replacing USERNAME with the +# desired username (eg /etc/udevil/udevil-user-jim.conf). +# +# Format: +# OPTION = VALUE[, VALUE, ...] +# +# DO NOT USE QUOTES except literally +# Lines beginning with # are ignored +# +############################################################################## + + +# To log all uses of udevil, set log_file to a file path: +# log_file = /var/log/udevil.log + +# Approximate number of days to retain log entries (0=forever, max=60): +log_keep_days = 10 + + +# allowed_types determines what fstypes can be passed by a user to the u/mount +# program, what device filesystems may be un/mounted implicitly, and what +# network filesystems may be un/mounted. +# It may also include the 'file' keyword, indicating that the user is allowed +# to mount files (eg an ISO file). The $KNOWN_FILESYSTEMS variable may +# be included to include common local filesystems as well as those listed in +# /etc/filesystems and /proc/filesystems. +# allowed_types_USERNAME, if present, is used to override allowed_types for +# the specific user 'USERNAME'. For example, to allow user 'jim' to mount +# only vfat filesystems, add: +# allowed_types_jim = vfat +# Setting allowed_types = * does NOT allow all types, as this is a security +# risk, but does allow all recognized types. +# allowed_types = $KNOWN_FILESYSTEMS, file, cifs, smbfs, nfs, curlftpfs, ftpfs, sshfs, davfs, tmpfs, ramfs +allowed_types = $KNOWN_FILESYSTEMS, file, cifs, smbfs, nfs, hfsplus, tmpfs + + +# allowed_users is a list of users permitted to mount and unmount with udevil. +# Wildcards (* or ?) may be used in the usernames. To allow all users, +# specify "allowed_users=*". UIDs may be included using the form UID=1000. +# For example: allowed_users = carl, UID=1000, pre* +# Also note that permission to execute udevil may be limited to users belonging +# to the group that owns /usr/bin/udevil, such as 'plugdev' or 'storage', +# depending on installation. +# allowed_users_FSTYPE, if present, is used to override allowed_users when +# mounting or unmounting a specific fstype (eg nfs, ext3, file). +# Note that when mounting a file, fstype will always be 'file' regardless of +# the internal fstype of the file. +# For example, to allow only user 'bob' to mount nfs shares, add: +# allowed_users_nfs = bob +# The root user is NOT automatically allowed to use udevil in some cases unless +# listed here (except for unmounting anything or mounting fstab devices). +allowed_users = * + + +# allowed_groups is a list of groups permitted to mount and unmount with +# udevil. The user MUST belong to at least one of these groups. Wildcards +# or GIDs may NOT be used in group names, but a single * may be used to allow +# all groups. +# Also note that permission to execute udevil may be limited to users belonging +# to the group that owns /usr/bin/udevil, such as 'plugdev' or 'storage', +# depending on installation. +# allowed_groups_FSTYPE, if present, is used to override allowed_groups when +# mounting or unmounting a specific fstype (eg nfs, ext3, file). For example, +# to allow only members of the 'network' group to mount smb and nfs shares, +# use both of these lines: +# allowed_groups_smbfs = network +# allowed_groups_nfs = network +# The root user is NOT automatically allowed to use udevil in some cases unless +# listed here (except for unmounting anything or mounting fstab devices). +allowed_groups = * + + +# allowed_media_dirs specifies the media directories in which user mount points +# may be located. The first directory which exists and does not contain a +# wildcard will be used as the default media directory (normally /media or +# /media/$USER). +# The $USER variable, if included, will be replaced with the username of the +# user running udevil. Wildcards may also be used in any directory EXCEPT the +# default. Wildcards will not match a /, except a /** suffix for recursion. +# allowed_media_dirs_FSTYPE, if present, is used to override allowed_media_dirs +# when mounting or unmounting a specific fstype (eg ext2, nfs). For example, +# to cause /media/network to be used as the default media directory for +# nfs and ftpfs mounts, use these two lines: +# allowed_media_dirs_nfs = /media/network, /media, /media/$USER +# allowed_media_dirs_ftpfs = /media/network, /media, /media/$USER +# NOTE: If you want only the user who mounted a device to have access to it +# and be allowed to unmount it, specify /media/$USER as the first +# allowed media directory (only /media/$USER is created on demand). +# IMPORTANT: If an allowed file is mounted to a media directory, the user may +# be permitted to unmount its associated loop device even though internal. +# INCLUDING /MNT HERE IS NOT RECOMMENDED. ALL ALLOWED MEDIA DIRECTORIES +# SHOULD BE OWNED AND WRITABLE ONLY BY ROOT. +allowed_media_dirs = /media + + +# allowed_devices is the first criteria for what block devices users may mount +# or unmount. If a device is not listed in allowed_devices, it cannot be +# un/mounted (unless in fstab). However, even if a device is listed, other +# factors may prevent its use. For example, access to system internal devices +# will be denied to normal users even if they are included in allowed_devices. +# allowed_devices_FSTYPE, if present, is used to override allowed_devices when +# mounting or unmounting a specific fstype (eg ext3, ntfs). For example, to +# prevent all block devices containing an ext4 filesystem from being +# un/mounted use: +# allowed_devices_ext4 = +# Note: Wildcards may be used, but a wildcard will never match a /, except +# for "allowed_devices=*" which allows any device. The recommended setting is +# allowed_devices = /dev/* +# WARNING: ALLOWING USERS TO MOUNT DEVICES OUTSIDE OF /dev CAN CAUSE SERIOUS +# SECURITY PROBLEMS. DO NOT ALLOW DEVICES IN /dev/shm +allowed_devices = /dev/* + + +# allowed_internal_devices causes udevil to treat any listed block devices as +# removable, thus allowing normal users to un/mount them (providing they are +# also listed in allowed_devices). +# allowed_internal_devices_FSTYPE, if present, is used to override +# allowed_internal_devices when mounting or unmounting a specific fstype +# (eg ext3, ntfs). For example, to allow block devices containing a vfat +# filesystem to be un/mounted even if they are system internal devices, use: +# allowed_internal_devices_vfat = /dev/sdb* +# Some removable esata drives look like internal drives to udevil. To avoid +# this problem, they can be treated as removable with this setting. +# WARNING: SETTING A SYSTEM DEVICE HERE CAN CAUSE SERIOUS SECURITY PROBLEMS. +allowed_internal_devices = /dev/* + + +# allowed_internal_uuids and allowed_internal_uuids_FSTYPE work similarly to +# allowed_internal_devices, except that UUIDs are specified instead of devices. +# For example, to allow un/mounting of an internal filesystem based on UUID: +# allowed_internal_uuids = cc0c4489-8def-1e5b-a304-ab87c3cb626c0 +# WARNING: SETTING A SYSTEM DEVICE HERE CAN CAUSE SERIOUS SECURITY PROBLEMS. +# allowed_internal_uuids = + + +# forbidden_devices is used to prevent block devices from being un/mounted +# even if other settings would allow them (except devices in fstab). +# forbidden_devices_FSTYPE, if present, is used to override +# forbidden_devices when mounting or unmounting a specific fstype +# (eg ext3, ntfs). For example, to prevent device /dev/sdd1 from being +# mounted when it contains an ntfs filesystem, use: +# forbidden_devices_ntfs = /dev/sdd1 +# NOTE: device node paths are canonicalized before being tested, so forbidding +# a link to a device will have no effect. +forbidden_devices = + + +# allowed_networks determines what hosts may be un/mounted by udevil users when +# using nfs, cifs, smbfs, curlftpfs, ftpfs, or sshfs. Hosts may be specified +# using a hostname (eg myserver.com) or IP address (192.168.1.100). +# Wildcards may be used in hostnames and IP addresses, but CIDR notation +# (192.168.1.0/16) is NOT supported. IP v6 is supported. For example: +# allowed_networks = 127.0.0.1, 192.168.1.*, 10.0.0.*, localmachine, *.okay.com +# Or, to prevent un/mounting of any network shares, set: +# allowed_networks = +# allowed_networks_FSTYPE, if present, is used to override allowed_networks +# when mounting or unmounting a specific network fstype (eg nfs, cifs, sshfs, +# curlftpfs). For example, to limit nfs and samba shares to only local +# networks, use these two lines: +# allowed_networks_nfs = 192.168.1.*, 10.0.0.* +# allowed_networks_cifs = 192.168.1.*, 10.0.0.* +allowed_networks = * + + +# forbidden_networks and forbidden_networks_FSTYPE are used to specify networks +# that are never allowed, even if other settings allow them (except fstab). +# NO REVERSE LOOKUP IS PERFORMED, so including bad.com will only have an effect +# if the user uses that hostname. IP lookup is always performed, so forbidding +# an IP address will also forbid all corresponding hostnames. +forbidden_networks = + + +# allowed_files is used to determine what files in what directories may be +# un/mounted. A user must also have read permission on a file to mount it. +# Note: Wildcards may be used, but a wildcard will never match a /, except +# for "allowed_files=*" which allows any file, and a /** suffix, which matches +# all files recursively. +# For example, to allow only files in the /share directory to be mounted, use: +# allowed_files = /share/* +# To allow all files in the /share directory AND all subdirectories use: +# allowed_files = /share/** +# NOTE: Specifying allowed_files_FSTYPE will NOT work because the fstype of +# files is always 'file'. +allowed_files = * + + +# forbidden_files is used to specify files that are never allowed, even if +# other settings allow them (except fstab). Specify a full path. +# Note: Wildcards may be used, but a wildcard will never match a /, except +# for "forbidden_files = *", or a /** suffix, which matches all recursively. +# NOTE: file paths are canonicalized before being tested, so forbidding +# a link to a file will have no effect. +forbidden_files = + + +# default_options specifies what options are always included when performing +# a mount, in addition to any options the user may specify. +# Note: When a device is present in /etc/fstab, and the user does not specify +# a mount point, the device is mounted with normal user permissions using +# the fstab entry, without these options. +# default_options_FSTYPE, if present, is used to override default_options +# when mounting a specific fstype (eg ext2, nfs). +# The variables $USER, $UID, and $GID are changed to the user's username, UID, +# and GID. +# FOR GOOD SECURITY, default_options SHOULD ALWAYS INCLUDE: nosuid,noexec,nodev +# WARNING: OPTIONS PRESENT OR MISSING CAN CAUSE SERIOUS SECURITY PROBLEMS. +default_options = nosuid, noexec, nodev, noatime +default_options_file = nosuid, noexec, nodev, noatime, uid=$UID, gid=$GID, ro +# mount iso9660 with 'ro' to prevent mount read-only warning +default_options_iso9660 = nosuid, noexec, nodev, noatime, uid=$UID, gid=$GID, ro, utf8 +default_options_udf = nosuid, noexec, nodev, noatime, uid=$UID, gid=$GID +default_options_vfat = nosuid, noexec, nodev, noatime, fmask=0133, dmask=0022, uid=$UID, gid=$GID, utf8 +default_options_exfat = nosuid, noexec, nodev, noatime, umask=0077, uid=$UID, gid=$GID, iocharset=utf8, namecase=0, nonempty +default_options_hfsplus = nosuid, noexec, nodev, ro, uid=$UID, gid=$GID +default_options_msdos = nosuid, noexec, nodev, noatime, fmask=0133, dmask=0022, uid=$UID, gid=$GID +default_options_umsdos = nosuid, noexec, nodev, noatime, fmask=0133, dmask=0022, uid=$UID, gid=$GID +default_options_ntfs = nosuid, noexec, nodev, noatime, fmask=0133, uid=$UID, gid=$GID, utf8 +default_options_cifs = nosuid, noexec, nodev, uid=$UID, gid=$GID +default_options_smbfs = nosuid, noexec, nodev, uid=$UID, gid=$GID +default_options_sshfs = nosuid, noexec, nodev, noatime, uid=$UID, gid=$GID, nonempty, allow_other +default_options_curlftpfs = nosuid, noexec, nodev, noatime, uid=$UID, gid=$GID, nonempty, allow_other +default_options_ftpfs = nosuid, noexec, nodev, noatime, uid=$UID, gid=$GID +default_options_davfs = nosuid, noexec, nodev, uid=$UID, gid=$GID +default_options_tmpfs = nosuid, noexec, nodev, noatime, uid=$UID, gid=$GID +default_options_ramfs = nosuid, noexec, nodev, noatime, uid=$UID, gid=$GID + + +# allowed_options determines all options that a user may specify when mounting. +# All the options used in default_options above must be included here too, or +# they will be rejected. If the user attempts to use an option not included +# here, an error will result. Wildcards may be used. +# allowed_options_FSTYPE, if present, is used to override allowed_options +# when mounting a specific fstype (eg ext2, nfs). +# The variables $USER, $UID, and $GID are changed to the user's username, UID, +# and GID. +# If you want to forbid remounts, remove 'remount' from here. +# WARNING: OPTIONS HERE CAN CAUSE SERIOUS SECURITY PROBLEMS - CHOOSE CAREFULLY +allowed_options = nosuid, noexec, nodev, noatime, fmask=0133, dmask=0022, uid=$UID, gid=$GID, ro, rw, sync, flush, iocharset=*, utf8, remount +allowed_options_nfs = nosuid, noexec, nodev, noatime, ro, rw, sync, remount, port=*, rsize=*, wsize=*, hard, proto=*, timeo=*, retrans=* +allowed_options_cifs = nosuid, noexec, nodev, ro, rw, remount, port=*, user=*, username=*, pass=*, password=*, guest, domain=*, uid=$UID, gid=$GID, credentials=* +allowed_options_smbfs = nosuid, noexec, nodev, ro, rw, remount, port=*, user=*, username=*, pass=*, password=*, guest, domain=*, uid=$UID, gid=$GID, credentials=* +allowed_options_sshfs = nosuid, noexec, nodev, noatime, ro, rw, uid=$UID, gid=$GID, nonempty, allow_other, idmap=user, BatchMode=yes, port=* +allowed_options_curlftpfs = nosuid, noexec, nodev, noatime, ro, rw, uid=$UID, gid=$GID, nonempty, allow_other, user=* +allowed_options_ftpfs = nosuid, noexec, nodev, noatime, ro, rw, port=*, user=*, pass=*, root=*, uid=$UID, gid=$GID +allowed_options_exfat = nosuid, noexec, nodev, noatime, fmask=0133, dmask=0022, uid=$UID, gid=$GID, umask=0077, namecase=*, ro, rw, sync, flush, iocharset=*, remount, nonempty + + +# mount_point_mode, if present and set to a non-empty value, will cause udevil +# to set the mode (permissions) on the moint point after mounting If not +# specified or if left empty, the mode is not changed. Mode must be octal +# starting with a zero (0755). +# mount_point_mode_FSTYPE, if present, is used to override mount_point_mode +# when mounting a specific fstype (eg ext2, nfs). +# NOT SETTING A MODE CAN HAVE SECURITY IMPLICATIONS FOR SOME FSTYPES +mount_point_mode = 0755 +# don't set a mode for some types: +mount_point_mode_sshfs = +mount_point_mode_curlftpfs = +mount_point_mode_ftpfs = + + +# Use the settings below to change the default locations of programs used by +# udevil, or (advanced topic) to redirect commands to your scripts. +# When substituting scripts, make sure they are root-owned and accept the +# options used by udevil (for example, the mount_program must accept --fake, +# -o, -v, and other options valid to mount.) +# Be sure to specify the full path and include NO OPTIONS or other arguments. +# These programs may also be specified as configure options when building +# udevil. +# THESE PROGRAMS ARE RUN AS ROOT +# mount_program = /bin/mount +# umount_program = /bin/umount +# losetup_program = /sbin/losetup +# setfacl_program = /usr/bin/setfacl + + +# validate_exec specifies a program or script which provides additional +# validation of a mount or unmount command, beyond the checks performed by +# udevil. The program is run as a normal user (if root runs udevil, +# validate_exec will NOT be run). The program is NOT run if the user is +# mounting a device without root priviledges (a device in fstab). +# The program is passed the username, a printable description of what is +# happening, and the entire udevil command line as the first three arguments. +# The program must return an exit status of 0 to allow the mount or unmount +# to proceed. If it returns non-zero, the user will be denied permission. +# For example, validate_exec might specify a script which notifies you +# of the command being run, or performs additional steps to authenticate the +# user. +# Specify a full path to the program, with NO options or arguments. +# validate_exec = + + +# validate_rootexec works similarly to validate_exec, except that the program +# is run as root. validate_rootexec will also be run if the root user runs +# udevil. If both validate_exec and validate_rootexec are specified, +# validate_rootexec will run first, followed by validate_exec. +# The program must return an exit status of 0 to allow the mount or unmount +# to proceed. If it returns non-zero, the user will be denied permission. +# Unless you are familiar with writing root scripts, it is recommended that +# rootexec settings NOT be used, as it is easy to inadvertently open exploits. +# THIS PROGRAM IS ALWAYS RUN AS ROOT, even if the user running udevil is not. +# validate_rootexec = + + +# success_exec is run after a successful mount, remount, or unmount. The +# program is run as a normal user (if root runs udevil, success_exec +# will NOT be run). +# The program is passed the username, a printable description of what action +# was taken, and the entire udevil command line as the first three arguments. +# The program's exit status is ignored. +# For example, success_exec might run a script which informs you of what action +# was taken, and might perform further actions. +# Specify a full path to the program, with NO options or arguments. +# success_exec = + + +# success_rootexec works similarly to success_exec, except that the program is +# run as root. success_rootexec will also be run if the root user runs udevil. +# If both success_exec and success_rootexec are specified, success_rootexec +# will run first, followed by success_exec. +# Unless you are familiar with writing root scripts, it is recommended that +# rootexec settings NOT be used, as it is easy to inadvertently open exploits. +# THIS PROGRAM IS ALWAYS RUN AS ROOT, even if the user running udevil is not. +# success_rootexec = + diff --git a/.linux_items/include/airootfs/etc/ufw/ufw.conf b/.linux_items/include/airootfs/etc/ufw/ufw.conf new file mode 100644 index 00000000..28fe5341 --- /dev/null +++ b/.linux_items/include/airootfs/etc/ufw/ufw.conf @@ -0,0 +1,10 @@ +# /etc/ufw/ufw.conf +# + +# Set to yes to start on boot. If setting this remotely, be sure to add a rule +# to allow your remote connection before starting ufw. Eg: 'ufw allow 22/tcp' +ENABLED=yes + +# Please use the 'ufw' command to set the loglevel. Eg: 'ufw logging medium'. +# See 'man ufw' for details. +LOGLEVEL=low diff --git a/.linux_items/include/airootfs/etc/ufw/user.rules b/.linux_items/include/airootfs/etc/ufw/user.rules new file mode 100644 index 00000000..aa30960c --- /dev/null +++ b/.linux_items/include/airootfs/etc/ufw/user.rules @@ -0,0 +1,39 @@ +*filter +:ufw-user-input - [0:0] +:ufw-user-output - [0:0] +:ufw-user-forward - [0:0] +:ufw-before-logging-input - [0:0] +:ufw-before-logging-output - [0:0] +:ufw-before-logging-forward - [0:0] +:ufw-user-logging-input - [0:0] +:ufw-user-logging-output - [0:0] +:ufw-user-logging-forward - [0:0] +:ufw-after-logging-input - [0:0] +:ufw-after-logging-output - [0:0] +:ufw-after-logging-forward - [0:0] +:ufw-logging-deny - [0:0] +:ufw-logging-allow - [0:0] +:ufw-user-limit - [0:0] +:ufw-user-limit-accept - [0:0] +### RULES ### + +### tuple ### allow any 22 0.0.0.0/0 any 0.0.0.0/0 in +-A ufw-user-input -p tcp --dport 22 -j ACCEPT +-A ufw-user-input -p udp --dport 22 -j ACCEPT + +### END RULES ### + +### LOGGING ### +-A ufw-after-logging-input -j LOG --log-prefix "[UFW BLOCK] " -m limit --limit 3/min --limit-burst 10 +-A ufw-after-logging-forward -j LOG --log-prefix "[UFW BLOCK] " -m limit --limit 3/min --limit-burst 10 +-I ufw-logging-deny -m conntrack --ctstate INVALID -j RETURN -m limit --limit 3/min --limit-burst 10 +-A ufw-logging-deny -j LOG --log-prefix "[UFW BLOCK] " -m limit --limit 3/min --limit-burst 10 +-A ufw-logging-allow -j LOG --log-prefix "[UFW ALLOW] " -m limit --limit 3/min --limit-burst 10 +### END LOGGING ### + +### RATE LIMITING ### +-A ufw-user-limit -m limit --limit 3/minute -j LOG --log-prefix "[UFW LIMIT BLOCK] " +-A ufw-user-limit -j REJECT +-A ufw-user-limit-accept -j ACCEPT +### END RATE LIMITING ### +COMMIT diff --git a/.linux_items/include/airootfs/etc/ufw/user6.rules b/.linux_items/include/airootfs/etc/ufw/user6.rules new file mode 100644 index 00000000..47d96108 --- /dev/null +++ b/.linux_items/include/airootfs/etc/ufw/user6.rules @@ -0,0 +1,39 @@ +*filter +:ufw6-user-input - [0:0] +:ufw6-user-output - [0:0] +:ufw6-user-forward - [0:0] +:ufw6-before-logging-input - [0:0] +:ufw6-before-logging-output - [0:0] +:ufw6-before-logging-forward - [0:0] +:ufw6-user-logging-input - [0:0] +:ufw6-user-logging-output - [0:0] +:ufw6-user-logging-forward - [0:0] +:ufw6-after-logging-input - [0:0] +:ufw6-after-logging-output - [0:0] +:ufw6-after-logging-forward - [0:0] +:ufw6-logging-deny - [0:0] +:ufw6-logging-allow - [0:0] +:ufw6-user-limit - [0:0] +:ufw6-user-limit-accept - [0:0] +### RULES ### + +### tuple ### allow any 22 ::/0 any ::/0 in +-A ufw6-user-input -p tcp --dport 22 -j ACCEPT +-A ufw6-user-input -p udp --dport 22 -j ACCEPT + +### END RULES ### + +### LOGGING ### +-A ufw6-after-logging-input -j LOG --log-prefix "[UFW BLOCK] " -m limit --limit 3/min --limit-burst 10 +-A ufw6-after-logging-forward -j LOG --log-prefix "[UFW BLOCK] " -m limit --limit 3/min --limit-burst 10 +-I ufw6-logging-deny -m conntrack --ctstate INVALID -j RETURN -m limit --limit 3/min --limit-burst 10 +-A ufw6-logging-deny -j LOG --log-prefix "[UFW BLOCK] " -m limit --limit 3/min --limit-burst 10 +-A ufw6-logging-allow -j LOG --log-prefix "[UFW ALLOW] " -m limit --limit 3/min --limit-burst 10 +### END LOGGING ### + +### RATE LIMITING ### +-A ufw6-user-limit -m limit --limit 3/minute -j LOG --log-prefix "[UFW LIMIT BLOCK] " +-A ufw6-user-limit -j REJECT +-A ufw6-user-limit-accept -j ACCEPT +### END RATE LIMITING ### +COMMIT diff --git a/.linux_items/include/airootfs/etc/vconsole.conf b/.linux_items/include/airootfs/etc/vconsole.conf new file mode 100644 index 00000000..9cec5feb --- /dev/null +++ b/.linux_items/include/airootfs/etc/vconsole.conf @@ -0,0 +1,2 @@ +KEYMAP=us +FONT=ter-u16n diff --git a/.linux_items/include/airootfs/usr/share/applications/Hardware Diagnostics.desktop b/.linux_items/include/airootfs/usr/share/applications/Hardware Diagnostics.desktop new file mode 100644 index 00000000..bd3e2196 --- /dev/null +++ b/.linux_items/include/airootfs/usr/share/applications/Hardware Diagnostics.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Version=1.0 +Type=Application +Name=Hardware Diagnostics +Comment=Hardware Diagnostics +Exec=urxvt -title "Hardware Diagnostics" -e hw-diags +Icon=utilities-system-monitor +Path=/usr/local/bin +Terminal=false +StartupNotify=false diff --git a/.linux_items/include/airootfs/usr/share/applications/Hardware Information.desktop b/.linux_items/include/airootfs/usr/share/applications/Hardware Information.desktop new file mode 100644 index 00000000..5481206d --- /dev/null +++ b/.linux_items/include/airootfs/usr/share/applications/Hardware Information.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Version=1.0 +Type=Application +Name=Hardware Information +Comment=Hardware Information +Exec=hardinfo +Icon=hardinfo +Path=/usr/local/bin +Terminal=false +StartupNotify=false diff --git a/.linux_items/include/airootfs/usr/share/applications/NetworkTest.desktop b/.linux_items/include/airootfs/usr/share/applications/NetworkTest.desktop new file mode 100644 index 00000000..4889b549 --- /dev/null +++ b/.linux_items/include/airootfs/usr/share/applications/NetworkTest.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Version=1.0 +Type=Application +Name=NetworkTest +Comment=Diagnose network connectivity +Exec=urxvt -title "Network Diagnostics" -hold -e hw-diags-network +Icon=network-workgroup +Path=/usr/local/bin +Terminal=false +StartupNotify=false diff --git a/.linux_items/include/isolinux/isolinux.cfg b/.linux_items/include/isolinux/isolinux.cfg new file mode 100644 index 00000000..736fecf0 --- /dev/null +++ b/.linux_items/include/isolinux/isolinux.cfg @@ -0,0 +1,6 @@ +PATH /%INSTALL_DIR%/boot/syslinux/ +DEFAULT loadconfig + +LABEL loadconfig + CONFIG /%INSTALL_DIR%/boot/syslinux/wk.cfg + APPEND /%INSTALL_DIR%/ diff --git a/.linux_items/include/syslinux/splash.png b/.linux_items/include/syslinux/splash.png new file mode 100644 index 00000000..e69de29b diff --git a/.linux_items/include/syslinux/syslinux.cfg b/.linux_items/include/syslinux/syslinux.cfg new file mode 100644 index 00000000..2e99dd9c --- /dev/null +++ b/.linux_items/include/syslinux/syslinux.cfg @@ -0,0 +1,5 @@ +DEFAULT loadconfig + +LABEL loadconfig + CONFIG wk.cfg + APPEND ../../ diff --git a/.linux_items/include/syslinux/wk.cfg b/.linux_items/include/syslinux/wk.cfg new file mode 100644 index 00000000..b9163e25 --- /dev/null +++ b/.linux_items/include/syslinux/wk.cfg @@ -0,0 +1,11 @@ +DEFAULT select + +LABEL select +COM32 boot/syslinux/whichsys.c32 +APPEND -pxe- pxe -sys- sys -iso- sys + +LABEL pxe +CONFIG boot/syslinux/wk_pxe.cfg + +LABEL sys +CONFIG boot/syslinux/wk_sys.cfg diff --git a/.linux_items/include/syslinux/wk_hdt.cfg b/.linux_items/include/syslinux/wk_hdt.cfg new file mode 100644 index 00000000..44b6578f --- /dev/null +++ b/.linux_items/include/syslinux/wk_hdt.cfg @@ -0,0 +1,5 @@ +# http://hdt-project.org/ +LABEL hdt +MENU LABEL Hardware Information (HDT) +COM32 boot/syslinux/hdt.c32 +APPEND modules_alias=boot/syslinux/hdt/modalias.gz pciids=boot/syslinux/hdt/pciids.gz diff --git a/.linux_items/include/syslinux/wk_head.cfg b/.linux_items/include/syslinux/wk_head.cfg new file mode 100644 index 00000000..7562755a --- /dev/null +++ b/.linux_items/include/syslinux/wk_head.cfg @@ -0,0 +1,43 @@ +SERIAL 0 38400 +UI boot/syslinux/vesamenu.c32 +MENU TITLE _______ +MENU BACKGROUND syslinux.png + +MENU WIDTH 80 +MENU MARGIN 10 +MENU ROWS 15 +MENU VSHIFT 2 +MENU TABMSGROW 22 +MENU CMDLINEROW 22 +MENU HELPMSGROW 24 +MENU HELPMSGENDROW -1 +MENU TABMSG + +# Refer to http://syslinux.zytor.com/wiki/index.php/Doc/menu + +MENU COLOR screen 30;44 #a0000000 #a0000000 none +MENU COLOR border 30;44 #a0000000 #a0000000 none +MENU COLOR title 1;36;44 #9033ccff #a0000000 none +MENU COLOR sel 7;37;40 #e0ffffff #a0000000 std +MENU COLOR disabled 37;44 #50ffffff #a0000000 none +MENU COLOR unsel 37;44 #50ffffff #a0000000 none +MENU COLOR help 37;40 #c0ffffff #a0000000 none +MENU COLOR tabmsg 30;44 #a0000000 #a0000000 none +menu color cmdmark 1;36;44 #9033ccff #a0000000 none +menu color cmdline 37;40 #c0ffffff #a0000000 none +MENU COLOR timeout_msg 37;40 #80ffffff #a0000000 none +MENU COLOR timeout 1;37;40 #c0ffffff #a0000000 none +MENU COLOR msg07 37;40 #90ffffff #a0000000 none +MENU COLOR tabmsg 31;40 #30ffffff #a0000000 none + +# Start entries +MENU SEPARATOR + +# http://www.memtest.org/ +LABEL memtest +MENU LABEL Memtest86+ +TEXT HELP +Perform RAM diagnostics + * This utility is not recommended for testing DDR4 RAM +ENDTEXT +LINUX boot/memtest diff --git a/.linux_items/include/syslinux/wk_pxe.cfg b/.linux_items/include/syslinux/wk_pxe.cfg new file mode 100644 index 00000000..d5efabb4 --- /dev/null +++ b/.linux_items/include/syslinux/wk_pxe.cfg @@ -0,0 +1,8 @@ +INCLUDE boot/syslinux/wk_head.cfg +MENU BACKGROUND pxelinux.png + +INCLUDE boot/syslinux/wk_pxe_linux.cfg +INCLUDE boot/syslinux/wk_pxe_winpe.cfg +INCLUDE boot/syslinux/wk_pxe_extras_entry.cfg + +INCLUDE boot/syslinux/wk_tail.cfg diff --git a/.linux_items/include/syslinux/wk_pxe_extras.cfg b/.linux_items/include/syslinux/wk_pxe_extras.cfg new file mode 100644 index 00000000..04cd2ce1 --- /dev/null +++ b/.linux_items/include/syslinux/wk_pxe_extras.cfg @@ -0,0 +1,9 @@ +INCLUDE boot/syslinux/wk_head.cfg +MENU BACKGROUND pxelinux.png + +INCLUDE boot/syslinux/wk_pxe_linux.cfg +INCLUDE boot/syslinux/wk_pxe_linux_extras.cfg +INCLUDE boot/syslinux/wk_pxe_winpe.cfg +INCLUDE boot/syslinux/wk_hdt.cfg + +INCLUDE boot/syslinux/wk_tail.cfg diff --git a/.linux_items/include/syslinux/wk_pxe_extras_entry.cfg b/.linux_items/include/syslinux/wk_pxe_extras_entry.cfg new file mode 100644 index 00000000..ec76c263 --- /dev/null +++ b/.linux_items/include/syslinux/wk_pxe_extras_entry.cfg @@ -0,0 +1,7 @@ +LABEL wk_pxe_extras +TEXT HELP +Show extra boot options +ENDTEXT +MENU LABEL Extras +KERNEL vesamenu.c32 +APPEND boot/syslinux/wk_pxe_extras.cfg diff --git a/.linux_items/include/syslinux/wk_pxe_linux.cfg b/.linux_items/include/syslinux/wk_pxe_linux.cfg new file mode 100644 index 00000000..f7bf816d --- /dev/null +++ b/.linux_items/include/syslinux/wk_pxe_linux.cfg @@ -0,0 +1,10 @@ +LABEL wk_http_linux +TEXT HELP +A live Linux environment + * HW diagnostics, file-based backups, data recovery, etc +ENDTEXT +MENU LABEL Linux +LINUX boot/x86_64/vmlinuz +INITRD boot/intel_ucode.img,boot/x86_64/archiso.img +APPEND archisobasedir=%INSTALL_DIR% archiso_http_srv=http://${pxeserver}/ quiet +SYSAPPEND 3 diff --git a/.linux_items/include/syslinux/wk_pxe_linux_extras.cfg b/.linux_items/include/syslinux/wk_pxe_linux_extras.cfg new file mode 100644 index 00000000..f29b2724 --- /dev/null +++ b/.linux_items/include/syslinux/wk_pxe_linux_extras.cfg @@ -0,0 +1,21 @@ +LABEL wk_http_linux_i3 +TEXT HELP +A live Linux environment (i3) + * HW diagnostics, file-based backups, data recovery, etc +ENDTEXT +MENU LABEL Linux (i3) +LINUX boot/x86_64/vmlinuz +INITRD boot/intel_ucode.img,boot/x86_64/archiso.img +APPEND archisobasedir=%INSTALL_DIR% archiso_http_srv=http://${pxeserver}/ quiet i3 +SYSAPPEND 3 + +LABEL wk_http_linux_cli +TEXT HELP +A live Linux environment (CLI) + * HW diagnostics, file-based backups, data recovery, etc +ENDTEXT +MENU LABEL Linux (CLI) +LINUX boot/x86_64/vmlinuz +INITRD boot/intel_ucode.img,boot/x86_64/archiso.img +APPEND archisobasedir=%INSTALL_DIR% archiso_http_srv=http://${pxeserver}/ nox nomodeset +SYSAPPEND 3 diff --git a/.linux_items/include/syslinux/wk_pxe_winpe.cfg b/.linux_items/include/syslinux/wk_pxe_winpe.cfg new file mode 100644 index 00000000..91d615d7 --- /dev/null +++ b/.linux_items/include/syslinux/wk_pxe_winpe.cfg @@ -0,0 +1,8 @@ +LABEL wk_http_winpe +TEXT HELP +A live Windows environment + * Create partition backups, Install Windows, etc +ENDTEXT +MENU LABEL Windows PE +COM32 boot/syslinux/linux.c32 +APPEND boot/wimboot gui initrdfile=winpe/x86_64/bootmgr,winpe/x86_64/BCD,winpe/x86_64/boot.sdi,winpe/x86_64/boot.wim diff --git a/.linux_items/include/syslinux/wk_sys.cfg b/.linux_items/include/syslinux/wk_sys.cfg new file mode 100644 index 00000000..beefb77d --- /dev/null +++ b/.linux_items/include/syslinux/wk_sys.cfg @@ -0,0 +1,7 @@ +INCLUDE boot/syslinux/wk_head.cfg + +INCLUDE boot/syslinux/wk_sys_linux.cfg +INCLUDE boot/syslinux/wk_sys_winpe.cfg +INCLUDE boot/syslinux/wk_sys_extras_entry.cfg + +INCLUDE boot/syslinux/wk_tail.cfg diff --git a/.linux_items/include/syslinux/wk_sys_extras.cfg b/.linux_items/include/syslinux/wk_sys_extras.cfg new file mode 100644 index 00000000..422bd053 --- /dev/null +++ b/.linux_items/include/syslinux/wk_sys_extras.cfg @@ -0,0 +1,8 @@ +INCLUDE boot/syslinux/wk_head.cfg + +INCLUDE boot/syslinux/wk_sys_linux.cfg +INCLUDE boot/syslinux/wk_sys_linux_extras.cfg +INCLUDE boot/syslinux/wk_sys_winpe.cfg +INCLUDE boot/syslinux/wk_hdt.cfg + +INCLUDE boot/syslinux/wk_tail.cfg diff --git a/.linux_items/include/syslinux/wk_sys_extras_entry.cfg b/.linux_items/include/syslinux/wk_sys_extras_entry.cfg new file mode 100644 index 00000000..ce8fd3ac --- /dev/null +++ b/.linux_items/include/syslinux/wk_sys_extras_entry.cfg @@ -0,0 +1,7 @@ +LABEL wk_sys_extras +TEXT HELP +Show extra boot options +ENDTEXT +MENU LABEL Extras +KERNEL vesamenu.c32 +APPEND boot/syslinux/wk_sys_extras.cfg diff --git a/.linux_items/include/syslinux/wk_sys_linux.cfg b/.linux_items/include/syslinux/wk_sys_linux.cfg new file mode 100644 index 00000000..4b3b08c9 --- /dev/null +++ b/.linux_items/include/syslinux/wk_sys_linux.cfg @@ -0,0 +1,9 @@ +LABEL wk_linux +TEXT HELP +A live Linux environment + * HW diagnostics, file-based backups, data recovery, etc +ENDTEXT +MENU LABEL Linux +LINUX boot/x86_64/vmlinuz +INITRD boot/intel_ucode.img,boot/x86_64/archiso.img +APPEND archisobasedir=%INSTALL_DIR% archisolabel=%ARCHISO_LABEL% quiet copytoram loglevel=3 diff --git a/.linux_items/include/syslinux/wk_sys_linux_extras.cfg b/.linux_items/include/syslinux/wk_sys_linux_extras.cfg new file mode 100644 index 00000000..882c705e --- /dev/null +++ b/.linux_items/include/syslinux/wk_sys_linux_extras.cfg @@ -0,0 +1,21 @@ +LABEL wk_linux_i3 +TEXT HELP +A live Linux environment (i3) + * HW diagnostics, file-based backups, data recovery, etc +ENDTEXT +MENU LABEL Linux (i3) +LINUX boot/x86_64/vmlinuz +INITRD boot/intel_ucode.img,boot/x86_64/archiso.img +APPEND archisobasedir=%INSTALL_DIR% archisolabel=%ARCHISO_LABEL% quiet copytoram loglevel=3 i3 +SYSAPPEND 3 + +LABEL wk_linux_cli +TEXT HELP +A live Linux environment (CLI) + * HW diagnostics, file-based backups, data recovery, etc +ENDTEXT +MENU LABEL Linux (CLI) +LINUX boot/x86_64/vmlinuz +INITRD boot/intel_ucode.img,boot/x86_64/archiso.img +APPEND archisobasedir=%INSTALL_DIR% archisolabel=%ARCHISO_LABEL% copytoram nox nomodeset +SYSAPPEND 3 diff --git a/.linux_items/include/syslinux/wk_sys_winpe.cfg b/.linux_items/include/syslinux/wk_sys_winpe.cfg new file mode 100644 index 00000000..3c2034d9 --- /dev/null +++ b/.linux_items/include/syslinux/wk_sys_winpe.cfg @@ -0,0 +1,8 @@ +LABEL wk_winpe +TEXT HELP +A live Windows environment + * Create partition backups, Install Windows, etc +ENDTEXT +MENU LABEL Windows PE +COM32 boot/syslinux/linux.c32 +APPEND boot/wimboot gui initrdfile=../sources/bootmgr,../sources/BCD,../sources/boot.sdi,../sources/boot.wim diff --git a/.linux_items/include/syslinux/wk_tail.cfg b/.linux_items/include/syslinux/wk_tail.cfg new file mode 100644 index 00000000..29af2d63 --- /dev/null +++ b/.linux_items/include/syslinux/wk_tail.cfg @@ -0,0 +1,9 @@ +MENU SEPARATOR + +LABEL reboot +MENU LABEL Reboot +COM32 boot/syslinux/reboot.c32 + +LABEL poweroff +MENU LABEL Power Off +COM32 boot/syslinux/poweroff.c32 diff --git a/.linux_items/packages/aur b/.linux_items/packages/aur new file mode 100644 index 00000000..9de0855e --- /dev/null +++ b/.linux_items/packages/aur @@ -0,0 +1,16 @@ +aic94xx-firmware +bash-pipes +gtk-theme-arc-git +hfsprogs +i3-gaps +i3lock-fancy-git +mprime-bin +nvme-cli +openbox-patched +papirus-icon-theme +pasystray +smartmontools-svn +testdisk-wip +ttf-font-awesome +wd719x-firmware +wimlib diff --git a/.linux_items/packages/dependencies b/.linux_items/packages/dependencies new file mode 100644 index 00000000..564053e8 --- /dev/null +++ b/.linux_items/packages/dependencies @@ -0,0 +1,12 @@ +archiso +attr +base-devel +curl +dos2unix +git +libewf +openssh +p7zip +progsreiserfs +refind-efi +rsync diff --git a/.linux_items/packages/live b/.linux_items/packages/live new file mode 100644 index 00000000..efc1e1d8 --- /dev/null +++ b/.linux_items/packages/live @@ -0,0 +1,102 @@ +aic94xx-firmware +alsa-utils +antiword +bash-pipes +bc +bluez +bluez-utils +cbatticon +chntpw +cmatrix +colordiff +compton +conky +curl +dmidecode +dos2unix +dunst +e2fsprogs +feh +ffmpeg +firefox +gnome-keyring +gparted +gsmartcontrol +gtk-theme-arc-git +hardinfo +hexedit +hfsprogs +htop +i3-gaps +i3lock-fancy-git +i3status +inxi +ldns +leafpad +libewf +libinput +linux-firmware +lm_sensors +mdadm +mediainfo +mesa-demos +mkvtoolnix-cli +mprime-bin +mpv +mupdf +ncdu +network-manager-applet +networkmanager +nvme-cli +oblogout +openbox-patched +p7zip +papirus-icon-theme +pasystray +pavucontrol +progsreiserfs +pulseaudio +python +python-psutil +python-requests +qemu-guest-agent +reiserfsprogs +rfkill +rng-tools +rofi +rxvt-unicode +smartmontools-svn +speedtest-cli +spice-vdagent +terminus-font +testdisk-wip +thunar +tint2 +tk +tmux +tree +ttf-font-awesome +ttf-inconsolata +udevil +udisks2 +ufw +unzip +util-linux +veracrypt +vim +virtualbox-guest-modules-arch +virtualbox-guest-utils +wd719x-firmware +wimlib +xf86-input-libinput +xf86-video-amdgpu +xf86-video-fbdev +xf86-video-intel +xf86-video-nouveau +xf86-video-vesa +xorg-server +xorg-xdpyinfo +xorg-xev +xorg-xinit +xorg-xinput +zsh diff --git a/Build Linux b/Build Linux new file mode 100755 index 00000000..a1d6a791 --- /dev/null +++ b/Build Linux @@ -0,0 +1,373 @@ +#!/bin/bash +# +## Wizard Kit: Live Linux Build Tool + +# Prep +DATE="$(date +%F)" +DATETIME="$(date +%F_%H%M)" +ROOT_DIR="$(realpath $(dirname "$0"))" +BUILD_DIR="$ROOT_DIR/BUILD_LINUX" +LIVE_DIR="$BUILD_DIR/live" +LOG_DIR="$BUILD_DIR/logs" +OUT_DIR="$ROOT_DIR/OUT_LINUX" +REPO_DIR="$BUILD_DIR/repo" +SKEL_DIR="$LIVE_DIR/airootfs/etc/skel" +TEMP_DIR="$BUILD_DIR/temp" +MIRRORLIST_SOURCE='https://www.archlinux.org/mirrorlist/?country=US&protocol=http&protocol=https&ip_version=4&use_mirror_status=on' +if which nano >/dev/null 2>&1; then + EDITOR=nano +elif which vim >/dev/null 2>&1; then + EDITOR=vim +else + EDITOR=vi +fi +if which sudo >/dev/null 2>&1; then + REAL_USER="$SUDO_USER" +fi + +function ask() { + while :; do + read -p "$1 " -r answer + if echo "$answer" | egrep -iq '^(y|yes|sure)$'; then + return 0 + elif echo "$answer" | egrep -iq '^(n|no|nope)$'; then + return 1 + fi + done +} + +function cleanup() { + for d in "$TEMP_DIR" "$LIVE_DIR"; do + if [[ -d "$d" ]]; then + if ask "Remove: ${d}?"; then + rm -Rf "$d" + fi + fi + done + mkdir -p "$BUILD_DIR" 2>/dev/null + mkdir -p "$LOG_DIR" 2>/dev/null + mkdir -p "$OUT_DIR" 2>/dev/null + mkdir -p "$TEMP_DIR" 2>/dev/null +} + +function fix_kit_permissions() { + # GitHub zip archives don't preserve the correct permissions + for d in .bin .cbin .kit_items .linux_items .pe_items Images; do + find "$ROOT_DIR/$d" -type d -exec chmod 755 "{}" \; + done +} + +function load_settings() { + # Check if settings already loaded + ## Code based on StackOverflow Q&A + ## Question: https://stackoverflow.com/q/3601515 + ## Asked by: https://stackoverflow.com/users/260127/prosseek + ## Edited by: https://stackoverflow.com/users/3924118/nbro + ## Answer: https://stackoverflow.com/a/13864829 + ## Answer by: https://stackoverflow.com/users/1633643/lionel + ## Answer edit: https://stackoverflow.com/users/-1/community + if [ ! -z ${KIT_NAME_FULL+x} ]; then + # KIT_NAME_FULL is set + return 0 # Skip loading settings from main.py + fi + + # Copy settings + if [[ ! -e "$BUILD_DIR/main.py" ]] || ask "Overwrite main.py?"; then + cp -bv "$ROOT_DIR/.bin/Scripts/settings/main.py" "$BUILD_DIR/main.py" + dos2unix "$BUILD_DIR/main.py" + fi + + # Edit settings + read -p "Press Enter to open settings... " -r + "$EDITOR" "$BUILD_DIR/main.py" + + # Load settings + while read line; do + if echo "$line" | egrep -q "^\w+='"; then + line="$(echo "$line" | sed -r 's/[\r\n]+//')" + eval "$line" + fi + done < "$BUILD_DIR/main.py" +} + +function copy_live_env() { + echo "Copying Archlinux files..." + rsync -aI /usr/share/archiso/configs/releng/ "$LIVE_DIR/" + + # Remove items + rm "$LIVE_DIR/airootfs/etc/systemd/scripts/choose-mirror" + rmdir "$LIVE_DIR/airootfs/etc/systemd/scripts" --ignore-fail-on-non-empty + rm "$LIVE_DIR/airootfs/etc/systemd/system/choose-mirror.service" + rm "$LIVE_DIR/airootfs/etc/systemd/system/etc-pacman.d-gnupg.mount" + rm "$LIVE_DIR/airootfs/etc/systemd/system/pacman-init.service" + rm "$LIVE_DIR/airootfs/etc/udev/rules.d/81-dhcpcd.rules" + rmdir "$LIVE_DIR/airootfs/etc/udev/rules.d" --ignore-fail-on-non-empty + rmdir "$LIVE_DIR/airootfs/etc/udev" --ignore-fail-on-non-empty + rm "$LIVE_DIR/isolinux"/*.cfg + rm "$LIVE_DIR/syslinux"/*.cfg "$LIVE_DIR/syslinux"/*.png + + # Add items + rsync -aI "$ROOT_DIR/.linux_items/include/" "$LIVE_DIR/" + 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/" +} + +function run_elevated() { + prog="$1" + shift + if which sudo >/dev/null 2>&1; then + sudo "$prog" $* + else + echo -n "Root " + su -c "export REAL_USER=$USER && '$prog' $*" + fi +} + +function update_live_env() { + hostname="$(echo "${KIT_NAME_SHORT}-linux" | tr "[:upper:]" "[:lower:]")" + username="$(echo "${KIT_NAME_SHORT}tech" | tr "[:upper:]" "[:lower:]")" + label="${KIT_NAME_SHORT}_LINUX" + install_dir="$(echo "${KIT_NAME_SHORT}linux" | tr "[:upper:]" "[:lower:]")" + + # Boot config (legacy) + mkdir -p "$LIVE_DIR/$install_dir" + cp "$ROOT_DIR/Images/Pxelinux.png" "$LIVE_DIR/$install_dir/pxelinux.png" + cp "$ROOT_DIR/Images/Syslinux.png" "$LIVE_DIR/$install_dir/syslinux.png" + sed -i -r "s/_+/$KIT_NAME_FULL/" "$LIVE_DIR/syslinux/wk_head.cfg" + mkdir -p "$TEMP_DIR" 2>/dev/null + curl -Lo "$TEMP_DIR/wimboot.zip" "http://git.ipxe.org/releases/wimboot/wimboot-latest.zip" + 7z e "$TEMP_DIR/wimboot.zip" -o"$LIVE_DIR/$install_dir/boot" 'wimboot*/LICENSE.txt' 'wimboot*/README.txt' 'wimboot*/wimboot' + + # Boot config (UEFI) + mkdir -p "$LIVE_DIR/EFI/boot" + cp "/usr/share/refind/refind_x64.efi" "$LIVE_DIR/EFI/boot/bootx64.efi" + cp "$ROOT_DIR/Images/rEFInd.png" "$LIVE_DIR/EFI/boot/rEFInd.png" + rsync -aI "/usr/share/refind/drivers_x64/" "$LIVE_DIR/EFI/boot/drivers_x64/" + rsync -aI "/usr/share/refind/icons/" "$LIVE_DIR/EFI/boot/icons/" --exclude "/usr/share/refind/icons/svg" + sed -i "s/%ARCHISO_LABEL%/${label}/" "$LIVE_DIR/EFI/boot/refind.conf" + + # 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" + 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" + + # build.sh + if ! grep -iq 'wizardkit additions' "$LIVE_DIR/build.sh"; then + sed -i -r 's/^(run_once make_iso)$/# wizardkit additions\n\1/' "$LIVE_DIR/build.sh" + sed -i '/# wizardkit additions/r .linux_items/build_additions.txt' "$LIVE_DIR/build.sh" + fi + + # Hostname + echo "$hostname" > "$LIVE_DIR/airootfs/etc/hostname" + echo "127.0.1.1 $hostname.localdomain $hostname" >> "$LIVE_DIR/airootfs/etc/hosts" + + # Live packages + sed -i -r 's/^(b43|clonezilla|gpm|grml|refind|testdisk|vim)/#\1/' "$LIVE_DIR/packages.both" + cat "$ROOT_DIR/.linux_items/packages/live" >> "$LIVE_DIR/packages.both" + echo "[custom]" >> "$LIVE_DIR/pacman.conf" + echo "SigLevel = Optional TrustAll" >> "$LIVE_DIR/pacman.conf" + echo "Server = file://$REPO_DIR" >> "$LIVE_DIR/pacman.conf" + echo "" >> "$LIVE_DIR/pacman.conf" + + # Mirrors + sed -i -r 's/^(.*mirrorlist.*)$/#NOPE#\1/' "$LIVE_DIR/airootfs/root/customize_airootfs.sh" + echo "curl -o '/etc/pacman.d/mirrorlist' '$MIRRORLIST_SOURCE'" >> "$LIVE_DIR/airootfs/root/customize_airootfs.sh" + echo "sed -i 's/#Server/Server/g' /etc/pacman.d/mirrorlist" >> "$LIVE_DIR/airootfs/root/customize_airootfs.sh" + + # MOTD + sed -i -r "s/_+/$KIT_NAME_FULL Linux Environment/" "$LIVE_DIR/airootfs/etc/motd" + + # Oh My ZSH + git clone --depth=1 git://github.com/robbyrussell/oh-my-zsh.git "$SKEL_DIR/.oh-my-zsh" + 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 git@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/" + + # Services + sed -i -r 's/^(.*pacman-init.*)$/#NOPE#\1/' "$LIVE_DIR/airootfs/root/customize_airootfs.sh" + sed -i -r 's/^(.*choose-mirror.*)$/#NOPE#\1/' "$LIVE_DIR/airootfs/root/customize_airootfs.sh" + + # SSH + mkdir -p "$SKEL_DIR/.ssh" + ssh-keygen -b 4096 -C "$username@$hostname" -N "" -f "$SKEL_DIR/.ssh/id_rsa" + echo 'rm /root/.ssh/id*' >> "$LIVE_DIR/airootfs/root/customize_airootfs.sh" + echo 'rm /root/.zlogin' >> "$LIVE_DIR/airootfs/root/customize_airootfs.sh" + sed -i -r 's/^(.*PermitRootLogin.*)$/#NOPE#\1/' "$LIVE_DIR/airootfs/root/customize_airootfs.sh" + + # Root user + echo "echo 'root:$ROOT_PASSWORD' | chpasswd" >> "$LIVE_DIR/airootfs/root/customize_airootfs.sh" + + # Sudo + echo "echo '%wheel ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers" >> "$LIVE_DIR/airootfs/root/customize_airootfs.sh" + + # Tech user + echo "groupadd -r autologin" >> "$LIVE_DIR/airootfs/root/customize_airootfs.sh" + echo "useradd -m -s /bin/zsh -G autologin,power,storage,wheel -U $username" >> "$LIVE_DIR/airootfs/root/customize_airootfs.sh" + echo "echo '$username:$TECH_PASSWORD' | chpasswd" >> "$LIVE_DIR/airootfs/root/customize_airootfs.sh" + + # Tech user autologin + mkdir -p "$LIVE_DIR/airootfs/etc/systemd/system/getty@tty1.service.d" + echo "[Service]" > "$LIVE_DIR/airootfs/etc/systemd/system/getty@tty1.service.d/autologin.conf" + echo "ExecStart=" >> "$LIVE_DIR/airootfs/etc/systemd/system/getty@tty1.service.d/autologin.conf" + echo "ExecStart=-/sbin/agetty --autologin $username --noclear %I 38400 linux" >> "$LIVE_DIR/airootfs/etc/systemd/system/getty@tty1.service.d/autologin.conf" + + # Timezone + echo "ln -sf '/usr/share/zoneinfo/$LINUX_TIME_ZONE' '/etc/localtime'" >> "$LIVE_DIR/airootfs/root/customize_airootfs.sh" + echo 'sed -i "s/#FallbackNTP/NTP/" /etc/systemd/timesyncd.conf' >> "$LIVE_DIR/airootfs/root/customize_airootfs.sh" + + # udevil fix + echo "mkdir /media" >> "$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" +} + +function update_repo() { + if [[ "$EUID" -eq 0 ]]; then + echo "This section not meant to be run as root." + echo "Aborted." + exit 1 + fi + echo "Updating custom repo..." + + # Archive current files + if [[ -d "$REPO_DIR" ]]; then + mkdir "$BUILD_DIR/Archive" 2>/dev/null + archive="$BUILD_DIR/Archive/$(date "+%F_%H%M%S")" + mv -bv "$REPO_DIR" "$archive" + fi + sleep 1s + + # Build custom repo packages + mkdir "$REPO_DIR" 2>/dev/null + mkdir "$TEMP_DIR" 2>/dev/null + pushd "$TEMP_DIR" >/dev/null + while read -r p; do + echo "Building: $p" + curl -LsfO https://aur.archlinux.org/cgit/aur.git/snapshot/$p.tar.gz + tar xf $p.tar.gz + pushd $p >/dev/null + makepkg -s --noconfirm + popd >/dev/null + mv -n $p/*xz "$REPO_DIR"/ + done < "$ROOT_DIR/.linux_items/packages/aur" + popd >/dev/null + + # Build custom repo database + pushd "$REPO_DIR" >/dev/null + repo-add custom.db.tar.gz *xz + popd >/dev/null +} + +function install_deps() { + echo "Installing dependencies..." + packages= + while read -r line; do + packages="$packages $line" + done < "$ROOT_DIR/.linux_items/packages/dependencies" + run_elevated pacman -Syu --needed --noconfirm $packages +} + +function build_iso() { + if [[ "$EUID" -ne 0 ]]; then + echo "This section is meant to be run as root." + echo "Aborted." + exit 1 + fi + + # Set permissions + echo "Setting permissions..." + chown root:root "$LIVE_DIR" -R + chmod 700 "$LIVE_DIR/airootfs/etc/skel/.ssh" + chmod 600 "$LIVE_DIR/airootfs/etc/skel/.ssh/id_rsa" + + # Build ISO + prefix="$(< "$LIVE_DIR/airootfs/etc/hostname")" + label="${KIT_NAME_SHORT}_LINUX" + install_dir="$(echo "${KIT_NAME_SHORT}linux" | tr "[:upper:]" "[:lower:]")" + "$LIVE_DIR/build.sh" -N "$prefix" -V "$DATE" -L "$label" -D "$install_dir" -w "$TEMP_DIR/Linux" -o "$OUT_DIR" -v | tee -a "$LOG_DIR/$DATETIME.log" + + # Cleanup + echo "Removing temp files..." + rm "$TEMP_DIR/Linux" -Rf | tee -a "$LOG_DIR/$DATETIME.log" + + echo "Reverting permissions..." + chown $REAL_USER:$REAL_USER "$LIVE_DIR" -R +} + +function build_full() { + if [[ "$EUID" -eq 0 ]]; then + echo "This section not meant to be run as root." + echo "Aborted." + exit 1 + fi + + # Prep for build + cleanup + fix_kit_permissions + install_deps + load_settings + update_repo + copy_live_env + update_live_env + # Rerun script as root to start Archiso build process + run_elevated "$(realpath "$0")" --build-iso +} + +# Check input +case $1 in + -b|--build-full) + build_full + ;; + + -f|--fix-perms) + fix_kit_permissions + ;; + + -i|--install-deps) + install_deps + ;; + + -o|--build-iso) + load_settings + build_iso + ;; + + -p|--prep-live-env) + load_settings + copy_live_env + update_live_env + ;; + + -u|--update-repo) + update_repo + ;; + + *) + echo "Usage: $(basename "$0") [OPTIONS]" + echo "" + echo "Options:" + echo " -b --build-full Perform all tasks and build iso" + echo " -h --help Show usage" + echo "" + echo "Advanced options:" + echo " -f --fix-perms Fix folder permissions" + echo " -i --install-deps Install build dependencies" + 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" + ;; +esac + diff --git a/Images/ConEmu.png b/Images/ConEmu.png index fa17463f..52e074be 100644 Binary files a/Images/ConEmu.png and b/Images/ConEmu.png differ diff --git a/Images/Linux.png b/Images/Linux.png new file mode 100644 index 00000000..eb2fbccf Binary files /dev/null and b/Images/Linux.png differ diff --git a/Images/Pxelinux.png b/Images/Pxelinux.png new file mode 100644 index 00000000..9709836e Binary files /dev/null and b/Images/Pxelinux.png differ diff --git a/Images/Syslinux.png b/Images/Syslinux.png new file mode 100644 index 00000000..b77aaeda Binary files /dev/null and b/Images/Syslinux.png differ diff --git a/Images/WinPE.jpg b/Images/WinPE.jpg index c9836039..51eeb3c8 100644 Binary files a/Images/WinPE.jpg and b/Images/WinPE.jpg differ diff --git a/Images/WizardHat.xcf b/Images/WizardHat.xcf new file mode 100644 index 00000000..c9f35d01 Binary files /dev/null and b/Images/WizardHat.xcf differ diff --git a/Images/logo.svg b/Images/logo.svg new file mode 100644 index 00000000..69b2ca2a --- /dev/null +++ b/Images/logo.svg @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/Images/rEFInd.png b/Images/rEFInd.png new file mode 100644 index 00000000..673e2069 Binary files /dev/null and b/Images/rEFInd.png differ diff --git a/README.md b/README.md index ff5d3ca0..d3c6fe62 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,22 @@ A collection of scripts to help technicians service Windows systems. * `Repairs` * `Uninstallers` +## Live Linux ## + +### Build Requirements ### + +* Arch Linux +* 4 Gb disk space + +### Initial Setup ### + +* Replace artwork as desired +* Run `Build_Linux` which will do the following: + * Install missing dependancies with pacman + * Open `main.py` in nano for configuration + * Build the local repo for the AUR packages + * Build the live Linux environment (exported as an ISO file) + ## Windows PE ## ### Build Requirements ### @@ -49,7 +65,7 @@ A collection of scripts to help technicians service Windows systems. ### Initial Setup ### -* Replace artwork as desired (if not already done above) +* Replace artwork as desired * Run `Build PE.cmd` which will do the following: * Load the WADK environment * Open `main.py` in notepad for configuration