From a33a54c5e6c55e9c53e764e159b594d0f64b8b77 Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Sun, 17 Dec 2017 21:22:53 -0700
Subject: [PATCH 01/42] Started python conversion
---
.../usr/local/bin => .bin/Scripts}/apple_fans | 6 +-
.bin/Scripts/connect_to_network | 31 +++++++++
.bin/Scripts/functions/common.py | 68 +++++++++++++-----
.bin/Scripts/functions/network.py | 65 +++++++++++++++++
.../bin => .bin/Scripts/linux-old}/hw-diags | 2 +-
.../Scripts/linux-old}/hw-diags-audio | 2 +-
.../Scripts/linux-old}/hw-diags-badblocks | 2 +-
.../Scripts/linux-old}/hw-diags-inner | 18 ++---
.../Scripts/linux-old}/hw-diags-network | 2 +-
.../Scripts/linux-old}/hw-diags-prime95 | 2 +-
.../Scripts/linux-old}/hw-diags-progress | 2 +-
.../Scripts/linux-old}/hw-diags-sensors | 2 +-
.../Scripts/linux-old}/mount-all-volumes | 4 +-
.../Scripts/linux-old}/mount-all-volumes-foh | 0
.../Scripts/linux-old}/mount-backup-shares | 12 ++--
.../Scripts/linux-old}/msword-search | 5 +-
.../usr/local/bin => .bin/Scripts}/remount-rw | 3 +-
.../airootfs/usr/local/bin/connect-to-network | 69 -------------------
.../live/airootfs/usr/local/bin/wifi.conf | 2 -
19 files changed, 178 insertions(+), 119 deletions(-)
rename {.linux_items/include/live/airootfs/usr/local/bin => .bin/Scripts}/apple_fans (84%)
create mode 100755 .bin/Scripts/connect_to_network
create mode 100644 .bin/Scripts/functions/network.py
rename {.linux_items/include/live/airootfs/usr/local/bin => .bin/Scripts/linux-old}/hw-diags (99%)
rename {.linux_items/include/live/airootfs/usr/local/bin => .bin/Scripts/linux-old}/hw-diags-audio (84%)
rename {.linux_items/include/live/airootfs/usr/local/bin => .bin/Scripts/linux-old}/hw-diags-badblocks (90%)
rename {.linux_items/include/live/airootfs/usr/local/bin => .bin/Scripts/linux-old}/hw-diags-inner (97%)
rename {.linux_items/include/live/airootfs/usr/local/bin => .bin/Scripts/linux-old}/hw-diags-network (97%)
rename {.linux_items/include/live/airootfs/usr/local/bin => .bin/Scripts/linux-old}/hw-diags-prime95 (86%)
rename {.linux_items/include/live/airootfs/usr/local/bin => .bin/Scripts/linux-old}/hw-diags-progress (70%)
rename {.linux_items/include/live/airootfs/usr/local/bin => .bin/Scripts/linux-old}/hw-diags-sensors (97%)
rename {.linux_items/include/live/airootfs/usr/local/bin => .bin/Scripts/linux-old}/mount-all-volumes (94%)
rename {.linux_items/include/live/airootfs/usr/local/bin => .bin/Scripts/linux-old}/mount-all-volumes-foh (100%)
rename {.linux_items/include/live/airootfs/usr/local/bin => .bin/Scripts/linux-old}/mount-backup-shares (83%)
rename {.linux_items/include/live/airootfs/usr/local/bin => .bin/Scripts/linux-old}/msword-search (94%)
rename {.linux_items/include/live/airootfs/usr/local/bin => .bin/Scripts}/remount-rw (83%)
delete mode 100755 .linux_items/include/live/airootfs/usr/local/bin/connect-to-network
delete mode 100644 .linux_items/include/live/airootfs/usr/local/bin/wifi.conf
diff --git a/.linux_items/include/live/airootfs/usr/local/bin/apple_fans b/.bin/Scripts/apple_fans
similarity index 84%
rename from .linux_items/include/live/airootfs/usr/local/bin/apple_fans
rename to .bin/Scripts/apple_fans
index 3bf21b42..de8e56e6 100755
--- a/.linux_items/include/live/airootfs/usr/local/bin/apple_fans
+++ b/.bin/Scripts/apple_fans
@@ -1,13 +1,13 @@
#!/bin/bash
#
-## HW diagnostics - Prime95
+## Wizard Kit: Apple fan speed tool
SMCPATH="/sys/devices/platform/applesmc.768"
SET_MAX="True"
function usage {
- echo "Usage: $0 auto|max"
- echo " e.g. $0 max"
+ echo "Usage: $(basename "$0") auto|max"
+ echo " e.g. $(basename "$0") max"
}
# Set mode
diff --git a/.bin/Scripts/connect_to_network b/.bin/Scripts/connect_to_network
new file mode 100755
index 00000000..9f388581
--- /dev/null
+++ b/.bin/Scripts/connect_to_network
@@ -0,0 +1,31 @@
+#!/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
+ if not is_connected():
+ 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/functions/common.py b/.bin/Scripts/functions/common.py
index 4f03205a..ebe4697d 100644
--- a/.bin/Scripts/functions/common.py
+++ b/.bin/Scripts/functions/common.py
@@ -8,7 +8,11 @@ import subprocess
import sys
import time
import traceback
-import winreg
+try:
+ import winreg
+except ModuleNotFoundError:
+ if psutil.WINDOWS:
+ raise
from subprocess import CalledProcessError
@@ -26,9 +30,13 @@ COLORS = {
'YELLOW': '\033[33m',
'BLUE': '\033[34m'
}
-HKU = winreg.HKEY_USERS
-HKCU = winreg.HKEY_CURRENT_USER
-HKLM = winreg.HKEY_LOCAL_MACHINE
+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):
@@ -86,8 +94,11 @@ def ask(prompt='Kotaero!'):
return answer
def clear_screen():
- """Simple wrapper for cls."""
- os.system('cls')
+ """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."""
@@ -160,8 +171,10 @@ def get_ticket_number():
_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:
+ 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
@@ -272,7 +285,7 @@ def menu_select(title='~ Untitled Menu ~',
answer = ''
while (answer.upper() not in valid_answers):
- os.system('cls')
+ clear_screen()
print(menu_splash)
answer = input('{}: '.format(prompt))
@@ -294,7 +307,11 @@ def pause(prompt='Press Enter to continue... '):
def ping(addr='google.com'):
"""Attempt to ping addr."""
- cmd = ['ping', '-n', '2', 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):
@@ -535,14 +552,20 @@ 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],
- ]
+ 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(
@@ -713,5 +736,14 @@ def set_common_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/network.py b/.bin/Scripts/functions/network.py
new file mode 100644
index 00000000..aa5b608c
--- /dev/null
+++ b/.bin/Scripts/functions/network.py
@@ -0,0 +1,65 @@
+#!/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 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/.linux_items/include/live/airootfs/usr/local/bin/hw-diags b/.bin/Scripts/linux-old/hw-diags
similarity index 99%
rename from .linux_items/include/live/airootfs/usr/local/bin/hw-diags
rename to .bin/Scripts/linux-old/hw-diags
index ff0f2fe7..730458f3 100755
--- a/.linux_items/include/live/airootfs/usr/local/bin/hw-diags
+++ b/.bin/Scripts/linux-old/hw-diags
@@ -1,6 +1,6 @@
#!/bin/bash
#
-## WK HW diagnostics - Launcher
+## Wizard Kit: HW Diagnostics - Menu
MODE="$1"
SHOW_MENU="True"
diff --git a/.linux_items/include/live/airootfs/usr/local/bin/hw-diags-audio b/.bin/Scripts/linux-old/hw-diags-audio
similarity index 84%
rename from .linux_items/include/live/airootfs/usr/local/bin/hw-diags-audio
rename to .bin/Scripts/linux-old/hw-diags-audio
index f46135fb..814eaf3a 100755
--- a/.linux_items/include/live/airootfs/usr/local/bin/hw-diags-audio
+++ b/.bin/Scripts/linux-old/hw-diags-audio
@@ -1,6 +1,6 @@
#!/bin/bash
#
-## WK HW diagnostics - Audio (Stereo)
+## Wizard Kit: HW Diagnostics - Audio
# Unmute and set volume
amixer -q set "Master" 80% unmute
diff --git a/.linux_items/include/live/airootfs/usr/local/bin/hw-diags-badblocks b/.bin/Scripts/linux-old/hw-diags-badblocks
similarity index 90%
rename from .linux_items/include/live/airootfs/usr/local/bin/hw-diags-badblocks
rename to .bin/Scripts/linux-old/hw-diags-badblocks
index 817996d3..cfff7c4d 100755
--- a/.linux_items/include/live/airootfs/usr/local/bin/hw-diags-badblocks
+++ b/.bin/Scripts/linux-old/hw-diags-badblocks
@@ -1,6 +1,6 @@
#!/bin/bash
#
-## WK HW diagnostics - badblocks
+## Wizard Kit: HW Diagnostics - badblocks
function usage {
echo "Usage: $0 log-dir device"
diff --git a/.linux_items/include/live/airootfs/usr/local/bin/hw-diags-inner b/.bin/Scripts/linux-old/hw-diags-inner
similarity index 97%
rename from .linux_items/include/live/airootfs/usr/local/bin/hw-diags-inner
rename to .bin/Scripts/linux-old/hw-diags-inner
index 45f83a9a..dcb08c8b 100755
--- a/.linux_items/include/live/airootfs/usr/local/bin/hw-diags-inner
+++ b/.bin/Scripts/linux-old/hw-diags-inner
@@ -1,6 +1,6 @@
#!/bin/bash
#
-## WK HW Diagnostics - Main script
+## Wizard Kit: HW Diagnostics - Main script
die () {
echo "$0:" "$@" >&2
@@ -8,16 +8,16 @@ die () {
}
# Load settings
-if [[ -f "/run/archiso/bootmnt/arch/arch.conf" ]]; then
- source "/run/archiso/bootmnt/arch/arch.conf" || \
- die "ERROR: failed to load arch.conf (from /run/archiso/bootmnt/arch/)"
+if [[ -f "/run/archiso/bootmnt/arch/main.conf" ]]; then
+ source "/run/archiso/bootmnt/arch/main.conf" || \
+ die "ERROR: failed to load main.conf (from /run/archiso/bootmnt/arch/)"
else
- source "/usr/local/bin/arch.conf" || \
- die "ERROR: failed to load arch.conf (from /usr/local/bin/)"
+ source "/usr/local/bin/main.conf" || \
+ die "ERROR: failed to load main.conf (from /usr/local/bin/)"
fi
# Get TICKET
-## Inital SKIP_UPLOAD value loaded from arch.conf
+## Inital SKIP_UPLOAD value loaded from main.conf
SKIP_UPLOAD="${SKIP_UPLOAD}"
TICKET=""
while [[ "$TICKET" == "" ]]; do
@@ -37,7 +37,7 @@ while [[ "$TICKET" == "" ]]; do
done
# Init
-## Tautologies left to show which settings are coming from arch.conf
+## Tautologies left to show which settings are coming from main.conf
DIAG_DATE="$(date "+%F_%H%M")"
DIAG_SERVER_AVAIL="False"
DIAG_SERVER="${DIAG_SERVER}"
@@ -234,7 +234,7 @@ esac
if [[ "$TEST_CPU" == "False" ]] && \
[[ "$TEST_SMART" == "False" ]] && \
[[ "$TEST_BADBLOCKS" == "False" ]]; then
- echo -e "${YELLOW}Aborting HW diagnostics${CLEAR}"
+ echo -e "${YELLOW}Aborting HW Diagnostics${CLEAR}"
exit 1
fi
diff --git a/.linux_items/include/live/airootfs/usr/local/bin/hw-diags-network b/.bin/Scripts/linux-old/hw-diags-network
similarity index 97%
rename from .linux_items/include/live/airootfs/usr/local/bin/hw-diags-network
rename to .bin/Scripts/linux-old/hw-diags-network
index b1ba805d..997a8f0c 100755
--- a/.linux_items/include/live/airootfs/usr/local/bin/hw-diags-network
+++ b/.bin/Scripts/linux-old/hw-diags-network
@@ -1,6 +1,6 @@
#!/bin/bash
#
-## WK HW diagnostics - Network
+## Wizard Kit: HW Diagnostics - Network
function test_connection() {
cmd="a"
diff --git a/.linux_items/include/live/airootfs/usr/local/bin/hw-diags-prime95 b/.bin/Scripts/linux-old/hw-diags-prime95
similarity index 86%
rename from .linux_items/include/live/airootfs/usr/local/bin/hw-diags-prime95
rename to .bin/Scripts/linux-old/hw-diags-prime95
index 4152a6a2..c19a913c 100755
--- a/.linux_items/include/live/airootfs/usr/local/bin/hw-diags-prime95
+++ b/.bin/Scripts/linux-old/hw-diags-prime95
@@ -1,6 +1,6 @@
#!/bin/bash
#
-## HW diagnostics - Prime95
+## Wizard Kit: HW Diagnostics - Prime95
function usage {
echo "Usage: $0 log-dir"
diff --git a/.linux_items/include/live/airootfs/usr/local/bin/hw-diags-progress b/.bin/Scripts/linux-old/hw-diags-progress
similarity index 70%
rename from .linux_items/include/live/airootfs/usr/local/bin/hw-diags-progress
rename to .bin/Scripts/linux-old/hw-diags-progress
index 83505276..97eb03a5 100755
--- a/.linux_items/include/live/airootfs/usr/local/bin/hw-diags-progress
+++ b/.bin/Scripts/linux-old/hw-diags-progress
@@ -1,6 +1,6 @@
#!/bin/bash
#
-## WK HW diagnostics - Progress
+## Wizard Kit: HW Diagnostics - Progress
# Loop forever
while :; do
diff --git a/.linux_items/include/live/airootfs/usr/local/bin/hw-diags-sensors b/.bin/Scripts/linux-old/hw-diags-sensors
similarity index 97%
rename from .linux_items/include/live/airootfs/usr/local/bin/hw-diags-sensors
rename to .bin/Scripts/linux-old/hw-diags-sensors
index 649601a8..5f4f494d 100755
--- a/.linux_items/include/live/airootfs/usr/local/bin/hw-diags-sensors
+++ b/.bin/Scripts/linux-old/hw-diags-sensors
@@ -1,6 +1,6 @@
#!/bin/bash
#
-## WK HW diagnostics - Sensors
+## Wizard Kit: HW Diagnostics - Sensors
LOG_DIR="$1"
diff --git a/.linux_items/include/live/airootfs/usr/local/bin/mount-all-volumes b/.bin/Scripts/linux-old/mount-all-volumes
similarity index 94%
rename from .linux_items/include/live/airootfs/usr/local/bin/mount-all-volumes
rename to .bin/Scripts/linux-old/mount-all-volumes
index b0eed90e..e746574f 100755
--- a/.linux_items/include/live/airootfs/usr/local/bin/mount-all-volumes
+++ b/.bin/Scripts/linux-old/mount-all-volumes
@@ -1,8 +1,8 @@
#!/bin/bash
#
-## Mount all volumes read-only
+## Wizard Kit: Volume mount tool
-# Mount all volumes
+# Mount all volumes (read only)
echo "Mounting all volumes"
regex="/dev/((h|s)d[a-z]|md)[0-9]+"
for volume in $(inxi -Dopxx | grep -E "$regex" | sed -r "s#.*($regex).*#\1#" | sort); do
diff --git a/.linux_items/include/live/airootfs/usr/local/bin/mount-all-volumes-foh b/.bin/Scripts/linux-old/mount-all-volumes-foh
similarity index 100%
rename from .linux_items/include/live/airootfs/usr/local/bin/mount-all-volumes-foh
rename to .bin/Scripts/linux-old/mount-all-volumes-foh
diff --git a/.linux_items/include/live/airootfs/usr/local/bin/mount-backup-shares b/.bin/Scripts/linux-old/mount-backup-shares
similarity index 83%
rename from .linux_items/include/live/airootfs/usr/local/bin/mount-backup-shares
rename to .bin/Scripts/linux-old/mount-backup-shares
index 9c6e9fad..1a9085b9 100755
--- a/.linux_items/include/live/airootfs/usr/local/bin/mount-backup-shares
+++ b/.bin/Scripts/linux-old/mount-backup-shares
@@ -1,6 +1,6 @@
#!/bin/bash
#
-## Mount NAS backup shares
+## Wizard Kit: Backup share mount tool
die () {
echo "$0:" "$@" >&2
@@ -8,12 +8,12 @@ die () {
}
# Load settings
-if [[ -f "/run/archiso/bootmnt/arch/arch.conf" ]]; then
- source "/run/archiso/bootmnt/arch/arch.conf" || \
- die "ERROR: failed to load arch.conf (from /run/archiso/bootmnt/arch/)"
+if [[ -f "/run/archiso/bootmnt/arch/main.conf" ]]; then
+ source "/run/archiso/bootmnt/arch/main.conf" || \
+ die "ERROR: failed to load main.conf (from /run/archiso/bootmnt/arch/)"
else
- source "/usr/local/bin/arch.conf" || \
- die "ERROR: failed to load arch.conf (from /usr/local/bin/)"
+ source "/usr/local/bin/main.conf" || \
+ die "ERROR: failed to load main.conf (from /usr/local/bin/)"
fi
# Connect to a network
diff --git a/.linux_items/include/live/airootfs/usr/local/bin/msword-search b/.bin/Scripts/linux-old/msword-search
similarity index 94%
rename from .linux_items/include/live/airootfs/usr/local/bin/msword-search
rename to .bin/Scripts/linux-old/msword-search
index 5917d660..def215b6 100755
--- a/.linux_items/include/live/airootfs/usr/local/bin/msword-search
+++ b/.bin/Scripts/linux-old/msword-search
@@ -1,5 +1,6 @@
#!/bin/bash
-
+#
+## Wizard Kit: MS Word content search tool
TMP_FILE="$(mktemp)"
IFS=$'\n'
@@ -35,4 +36,4 @@ rm "$TMP_FILE"
if [[ -s "$HOME/msword-matches.txt" ]]; then
echo "Found $(wc -l "$HOME/msword-matches.txt") possible matches"
echo "The results have been saved to $HOME"
-fi
\ No newline at end of file
+fi
diff --git a/.linux_items/include/live/airootfs/usr/local/bin/remount-rw b/.bin/Scripts/remount-rw
similarity index 83%
rename from .linux_items/include/live/airootfs/usr/local/bin/remount-rw
rename to .bin/Scripts/remount-rw
index 270f2287..4a0b833e 100755
--- a/.linux_items/include/live/airootfs/usr/local/bin/remount-rw
+++ b/.bin/Scripts/remount-rw
@@ -1,6 +1,6 @@
#!/bin/bash
#
-## Remount volume read-write
+## Wizard Kit: Volume remount tool
if ! mount | grep -q "$1"; then
echo "ERROR: Can't remount $1"
@@ -10,6 +10,7 @@ fi
DEVICE=$(mount | grep "$1" | cut -d' ' -f1)
+# Remount read-write
echo "Remounting: $DEVICE"
udevil umount $DEVICE
if udevil mount $DEVICE; then
diff --git a/.linux_items/include/live/airootfs/usr/local/bin/connect-to-network b/.linux_items/include/live/airootfs/usr/local/bin/connect-to-network
deleted file mode 100755
index 375fb4c2..00000000
--- a/.linux_items/include/live/airootfs/usr/local/bin/connect-to-network
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/bin/bash
-#
-## Get connected to a network
-
-# 1. Checks if already online; skips if so
-# 2. If no wired devices are present then reload kernel modules
-# 3. If wireless devices are present, and we're still offline, then connect to WiFi
-
-die () {
- echo "$0:" "$@" >&2
- exit 1
-}
-
-function test_connection() {
- # Check for a valid private IP
- if ip a | grep -Eq '10.[0-9]+.[0-9]+.[0-9]+'; then
- return 0 # Class A
- elif ip a | grep -Eq '172.(1[6-9]|2[0-9]|3[0-1]).[0-9]+.[0-9]+'; then
- return 0 # Class B
- elif ip a | grep -Eq '192.168.[0-9]+.[0-9]+'; then
- return 0 # Class C
- else
- return 1 # Invalid private IP
- fi
-}
-
-# Load settings
-if [[ -f "/run/archiso/bootmnt/arch/wifi.conf" ]]; then
- source "/run/archiso/bootmnt/arch/wifi.conf" || \
- die "ERROR: failed to load wifi.conf (from /run/archiso/bootmnt/arch/)"
-else
- source "/usr/local/bin/wifi.conf" || \
- die "ERROR: failed to load wifi.conf (from /usr/local/bin/)"
-fi
-
-# Init
-WIFI_SSID="${WIFI_SSID}"
-WIFI_PASSWORD="${WIFI_PASSWORD}"
-
-# Connect to network
-if ! test_connection; then
- # LAN
- if ! ip l | grep -Eq '[0-9]+: +en'; then
- ## Reload the tg3/broadcom driver (known fix for some Dell systems)
- echo "No wired network adapters found; reloading drivers..."
- sudo modprobe -r tg3
- sudo modprobe broadcom
- sudo modprobe tg3
- sleep 5s
- fi
-
- # WiFi
- if ip l | grep -Eq '[0-9]+: +wl'; then
- ## Skip if we're already connected (i.e. the code above worked)
- if ! test_connection; then
- echo "Attempting to connect to ${WIFI_SSID}..."
- nmcli dev wifi connect "${WIFI_SSID}" password "${WIFI_PASSWORD}"
- sleep 5s
- fi
- fi
-fi
-
-# Done
-if test_connection; then
- exit 0
-else
- exit 1
-fi
-
diff --git a/.linux_items/include/live/airootfs/usr/local/bin/wifi.conf b/.linux_items/include/live/airootfs/usr/local/bin/wifi.conf
deleted file mode 100644
index 2e8924e6..00000000
--- a/.linux_items/include/live/airootfs/usr/local/bin/wifi.conf
+++ /dev/null
@@ -1,2 +0,0 @@
-# Wizard Kit: Settings - WiFi
-
From 5ea03da0a446d35736034ee2e8106debe78a4d2d Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Mon, 18 Dec 2017 00:47:47 -0700
Subject: [PATCH 02/42] Converted all python scripts to LF/UNIX
---
.bin/Scripts/activate.py | 124 +-
.bin/Scripts/borrowed/acpi.py | 114 +-
.bin/Scripts/borrowed/knownpaths-LICENSE.txt | 42 +-
.bin/Scripts/borrowed/knownpaths.py | 328 ++--
.bin/Scripts/cbs_fix.py | 84 +-
.bin/Scripts/check_disk.py | 112 +-
.bin/Scripts/dism.py | 114 +-
.bin/Scripts/functions/activation.py | 132 +-
.bin/Scripts/functions/browsers.py | 892 ++++-----
.bin/Scripts/functions/cleanup.py | 182 +-
.bin/Scripts/functions/common.py | 1498 +++++++--------
.bin/Scripts/functions/data.py | 1256 ++++++------
.bin/Scripts/functions/diags.py | 228 +--
.bin/Scripts/functions/info.py | 934 ++++-----
.bin/Scripts/functions/network.py | 130 +-
.bin/Scripts/functions/partition_uids.py | 652 +++----
.bin/Scripts/functions/product_keys.py | 222 +--
.bin/Scripts/functions/repairs.py | 252 +--
.bin/Scripts/functions/setup.py | 544 +++---
.bin/Scripts/functions/update.py | 1790 +++++++++---------
.bin/Scripts/install_sw_bundle.py | 120 +-
.bin/Scripts/install_vcredists.py | 68 +-
.bin/Scripts/safemode_enter.py | 88 +-
.bin/Scripts/safemode_exit.py | 84 +-
.bin/Scripts/settings/launchers.py | 1172 ++++++------
.bin/Scripts/settings/music.py | 140 +-
.bin/Scripts/settings/sources.py | 406 ++--
.bin/Scripts/settings/tools.py | 110 +-
.bin/Scripts/sfc_scan.py | 78 +-
.bin/Scripts/system_checklist.py | 214 +--
.bin/Scripts/system_diagnostics.py | 248 +--
.bin/Scripts/transferred_keys.py | 56 +-
.bin/Scripts/update_kit.py | 286 +--
.bin/Scripts/user_checklist.py | 166 +-
.bin/Scripts/user_data_transfer.py | 106 +-
35 files changed, 6486 insertions(+), 6486 deletions(-)
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/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/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/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 ebe4697d..9cd52f4b 100644
--- a/.bin/Scripts/functions/common.py
+++ b/.bin/Scripts/functions/common.py
@@ -1,749 +1,749 @@
-# 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):
- 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'):
- """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):
- 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'] 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')
- 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.")
+# 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):
+ 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'):
+ """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):
+ 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'] 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')
+ 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..06ac16e7 100644
--- a/.bin/Scripts/functions/data.py
+++ b/.bin/Scripts/functions/data.py
@@ -1,628 +1,628 @@
-# 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
+
+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.")
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/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
index aa5b608c..6b8c2c3c 100644
--- a/.bin/Scripts/functions/network.py
+++ b/.bin/Scripts/functions/network.py
@@ -1,65 +1,65 @@
-#!/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 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.")
-
+#!/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 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/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/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/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 5fd133a0..1a51238f 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/28/2323/FastCopy332.zip',
- 'FastCopy64': 'http://ftp.vector.co.jp/69/28/2323/FastCopy332_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.0.2.49.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/28/2323/FastCopy332.zip',
+ 'FastCopy64': 'http://ftp.vector.co.jp/69/28/2323/FastCopy332_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.0.2.49.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()
From 3b0b103590840accddedff212ade9b19282b9dce Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Mon, 18 Dec 2017 00:49:05 -0700
Subject: [PATCH 03/42] Added CRLF checks for main.py to build script
* For consistancy between platforms
---
.linux_items/packages/dependencies | 1 +
Build Linux | 1 +
2 files changed, 2 insertions(+)
diff --git a/.linux_items/packages/dependencies b/.linux_items/packages/dependencies
index dd1a7f88..1b01cc6b 100644
--- a/.linux_items/packages/dependencies
+++ b/.linux_items/packages/dependencies
@@ -2,6 +2,7 @@ archiso
attr
base-devel
curl
+dos2unix
git
libewf
openssh
diff --git a/Build Linux b/Build Linux
index c9c578cd..23c20228 100755
--- a/Build Linux
+++ b/Build Linux
@@ -77,6 +77,7 @@ function load_settings() {
# 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"
+ unix2dos "$BUILD_DIR/main.py"
fi
# Edit settings
From 183ef78ea9ca37e4acffd184120a17f47a8ccc4b Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Mon, 18 Dec 2017 03:36:56 -0700
Subject: [PATCH 04/42] mount-all-volumes rewrite complete
* New print layout
* All inxi calls replaced with findmnt and lsblk
* Added util-linux to packages/live
---
...{connect_to_network => connect-to-network} | 0
.bin/Scripts/functions/data.py | 77 +++++++++++++++++++
.bin/Scripts/mount-all-volumes | 38 +++++++++
.linux_items/packages/live | 1 +
4 files changed, 116 insertions(+)
rename .bin/Scripts/{connect_to_network => connect-to-network} (100%)
create mode 100755 .bin/Scripts/mount-all-volumes
diff --git a/.bin/Scripts/connect_to_network b/.bin/Scripts/connect-to-network
similarity index 100%
rename from .bin/Scripts/connect_to_network
rename to .bin/Scripts/connect-to-network
diff --git a/.bin/Scripts/functions/data.py b/.bin/Scripts/functions/data.py
index 06ac16e7..c1a3b352 100644
--- a/.bin/Scripts/functions/data.py
+++ b/.bin/Scripts/functions/data.py
@@ -1,6 +1,7 @@
# Wizard Kit: Functions - Data
import ctypes
+import json
from operator import itemgetter
@@ -157,6 +158,82 @@ def is_valid_wim_file(item):
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."""
for server in BACKUP_SERVERS:
diff --git a/.bin/Scripts/mount-all-volumes b/.bin/Scripts/mount-all-volumes
new file mode 100755
index 00000000..587bc4c9
--- /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 'foh' in __file__:
+ pause("Press Enter to exit...")
+ popen_program(['thunar', '/media'])
+ exit_script()
+ except SystemExit:
+ pass
+ except:
+ major_exception()
+
diff --git a/.linux_items/packages/live b/.linux_items/packages/live
index b5300bdc..b673f686 100644
--- a/.linux_items/packages/live
+++ b/.linux_items/packages/live
@@ -75,6 +75,7 @@ udevil
udisks2
ufw
unzip
+util-linux
veracrypt
vim
virtualbox-guest-modules-arch
From 6bbc15d4f156ad651f12767ae89aaf5161cca67d Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Mon, 18 Dec 2017 03:50:15 -0700
Subject: [PATCH 05/42] Updated: mount-all-volumes
* Added switch for foh mode instead of using symlinks
* Updated i3/openbox shortcuts
---
.bin/Scripts/linux-old/mount-all-volumes | 28 -------------------
.bin/Scripts/linux-old/mount-all-volumes-foh | 1 -
.bin/Scripts/mount-all-volumes | 2 +-
.../live/airootfs/etc/skel/.config/i3/config | 2 +-
.../airootfs/etc/skel/.config/openbox/rc.xml | 2 +-
5 files changed, 3 insertions(+), 32 deletions(-)
delete mode 100755 .bin/Scripts/linux-old/mount-all-volumes
delete mode 120000 .bin/Scripts/linux-old/mount-all-volumes-foh
diff --git a/.bin/Scripts/linux-old/mount-all-volumes b/.bin/Scripts/linux-old/mount-all-volumes
deleted file mode 100755
index e746574f..00000000
--- a/.bin/Scripts/linux-old/mount-all-volumes
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/bash
-#
-## Wizard Kit: Volume mount tool
-
-# Mount all volumes (read only)
-echo "Mounting all volumes"
-regex="/dev/((h|s)d[a-z]|md)[0-9]+"
-for volume in $(inxi -Dopxx | grep -E "$regex" | sed -r "s#.*($regex).*#\1#" | sort); do
- if grep -q "$volume" /proc/mounts; then
- if ! mount | grep "/run/archiso/bootmnt" | grep -q "$volume"; then
- # Show what's already mounted except the WK_ARCH boot device
- echo "$volume: (Already) mounted $(mount | grep "$volume" | sed -r 's/^\S+ (on.*) type .*/\1/') ($(df -h "$volume" | tail -1 | awk '{print $3, $4}' | sed -r 's/(K|M|G|T|) (.*[0-9])(K|M|G|T|)$/ \1b used, \2 \3b free/'))"
- fi
- else
- if udevil mount -o ro $volume >/dev/null 2>&1; then
- echo "$volume: Mounted $(mount | grep "$volume" | sed -r 's/^\S+ (on.*) type .*/\1/') ($(df -h "$volume" | tail -1 | awk '{print $3, $4}' | sed -r 's/(K|M|G|T|) (.*[0-9])(K|M|G|T|)$/ \1b used, \2 \3b free/'))"
- else
- echo "$volume: Failed to mount"
- fi
- fi
-done
-
-# Open folder?
-if echo "$0" | grep -iq foh; then
- thunar /media
-fi
-
-echo "Done."
diff --git a/.bin/Scripts/linux-old/mount-all-volumes-foh b/.bin/Scripts/linux-old/mount-all-volumes-foh
deleted file mode 120000
index 8ac53b0c..00000000
--- a/.bin/Scripts/linux-old/mount-all-volumes-foh
+++ /dev/null
@@ -1 +0,0 @@
-mount-all-volumes
\ No newline at end of file
diff --git a/.bin/Scripts/mount-all-volumes b/.bin/Scripts/mount-all-volumes
index 587bc4c9..a183e5c3 100755
--- a/.bin/Scripts/mount-all-volumes
+++ b/.bin/Scripts/mount-all-volumes
@@ -27,7 +27,7 @@ if __name__ == '__main__':
# Done
print_standard('\nDone.')
- if 'foh' in __file__:
+ if 'foh' in sys.argv:
pause("Press Enter to exit...")
popen_program(['thunar', '/media'])
exit_script()
diff --git a/.linux_items/include/live/airootfs/etc/skel/.config/i3/config b/.linux_items/include/live/airootfs/etc/skel/.config/i3/config
index 016026d3..67423053 100644
--- a/.linux_items/include/live/airootfs/etc/skel/.config/i3/config
+++ b/.linux_items/include/live/airootfs/etc/skel/.config/i3/config
@@ -71,7 +71,7 @@ bindsym $mod+r exec "rofi -combi-modi window,drun,run -show combi -modi combi"
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"
+bindsym $mod+m exec "urxvt -title 'Mount All Volumes' -e mount-all-volumes foh"
bindsym $mod+s exec "urxvt -title 'Hardware Diagnostics' -e hw-diags foh"
bindsym $mod+t exec "urxvt"
bindsym $mod+v exec "urxvt -title 'Hardware Sensors' -e hw-diags-sensors"
diff --git a/.linux_items/include/live/airootfs/etc/skel/.config/openbox/rc.xml b/.linux_items/include/live/airootfs/etc/skel/.config/openbox/rc.xml
index a52cb7cc..c48340dd 100644
--- a/.linux_items/include/live/airootfs/etc/skel/.config/openbox/rc.xml
+++ b/.linux_items/include/live/airootfs/etc/skel/.config/openbox/rc.xml
@@ -314,7 +314,7 @@
- urxvt -title "Mount all Volumes" -e mount-all-volumes-foh
+ urxvt -title "Mount all Volumes" -e mount-all-volumes foh
From 9c04a5dc83986f255cf85065c7a11e0f11fe2134 Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Mon, 18 Dec 2017 19:37:49 -0700
Subject: [PATCH 06/42] Misc updates
---
.linux_items/include/live/airootfs/etc/hosts | 3 +++
.linux_items/include/live/airootfs/etc/motd | 2 +-
.linux_items/packages/live | 3 +++
Build Linux | 17 +++++++----------
4 files changed, 14 insertions(+), 11 deletions(-)
create mode 100644 .linux_items/include/live/airootfs/etc/hosts
diff --git a/.linux_items/include/live/airootfs/etc/hosts b/.linux_items/include/live/airootfs/etc/hosts
new file mode 100644
index 00000000..f3b39609
--- /dev/null
+++ b/.linux_items/include/live/airootfs/etc/hosts
@@ -0,0 +1,3 @@
+127.0.0.1 localhost.localdomain localhost
+::1 localhost.localdomain localhost
+
diff --git a/.linux_items/include/live/airootfs/etc/motd b/.linux_items/include/live/airootfs/etc/motd
index dfba12f7..c84d47a0 100644
--- a/.linux_items/include/live/airootfs/etc/motd
+++ b/.linux_items/include/live/airootfs/etc/motd
@@ -1,4 +1,4 @@
-Welcome to the [32mWK Linux Toolbox[0m
+Welcome to the [32m______[0m
Some common commands:
[34m%[0m hw-diags
diff --git a/.linux_items/packages/live b/.linux_items/packages/live
index b673f686..f571a768 100644
--- a/.linux_items/packages/live
+++ b/.linux_items/packages/live
@@ -54,6 +54,9 @@ pasystray
pavucontrol
progsreiserfs
pulseaudio
+python
+python-psutil
+python-requests
qemu-guest-agent
reiserfsprogs
rfkill
diff --git a/Build Linux b/Build Linux
index 23c20228..ace7f581 100755
--- a/Build Linux
+++ b/Build Linux
@@ -66,10 +66,7 @@ function load_settings() {
## 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 unset
- : # pass
- else
+ if [ ! -z ${KIT_NAME_FULL+x} ]; then
# KIT_NAME_FULL is set
return 0 # Skip loading settings from main.py
fi
@@ -99,6 +96,8 @@ function copy_live_env() {
# Add items
rsync -aI "$ROOT_DIR/.linux_items/include/live/" "$LIVE_DIR/"
+ mkdir -p "$LIVE_DIR/airootfs/usr/local/bin"
+ rsync -aI "$ROOT_DIR/.bin/Scripts/" "$LIVE_DIR/airootfs/usr/local/bin/"
# Remove items
rm "$LIVE_DIR/airootfs/etc/systemd/scripts/choose-mirror"
@@ -141,6 +140,7 @@ function update_live_env() {
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"
@@ -148,7 +148,7 @@ function update_live_env() {
echo "sed -i 's/#Server/Server/g' /etc/pacman.d/mirrorlist" >> "$LIVE_DIR/airootfs/root/customize_airootfs.sh"
# MOTD
- sed -i "s/WK/$KIT_NAME_SHORT/" "$LIVE_DIR/airootfs/etc/motd"
+ sed -i "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"
@@ -157,7 +157,8 @@ function update_live_env() {
# Openbox theme
git clone --depth=1 git@github.com:addy-dclxvi/Openbox-Theme-Collections.git "$TEMP_DIR/ob-themes"
- cp -a "$TEMP_DIR/ob-themes/Triste-Orange" "$LIVE_DIR/airootfs/usr/share/themes/Triste-Orange"
+ 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"
@@ -197,10 +198,6 @@ function update_live_env() {
# Wallpaper
mkdir -p "$LIVE_DIR/airootfs/usr/share/wallpaper"
cp "$ROOT_DIR/Images/Linux.png" "$LIVE_DIR/airootfs/usr/share/wallpaper/burned.in"
-
- # WiFi
- echo "WIFI_SSID='$WIFI_SSID'" >> "$LIVE_DIR/airootfs/usr/local/bin/wifi.conf"
- echo "WIFI_PASSWORD='$WIFI_PASSWORD'" >> "$LIVE_DIR/airootfs/usr/local/bin/wifi.conf"
}
function update_repo() {
From 04656c50b1435493855dc8962e07ee839b30ea2d Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Tue, 19 Dec 2017 04:40:02 -0700
Subject: [PATCH 07/42] Updated dunst config
* Moved notifications to the left of conky
* Restart dunst after 5s
* Fixes issue where the first notifcation(s) would stay indefinitely
---
.../include/live/airootfs/etc/skel/.config/dunst/dunstrc | 2 +-
.linux_items/include/live/airootfs/etc/skel/.xinitrc | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/.linux_items/include/live/airootfs/etc/skel/.config/dunst/dunstrc b/.linux_items/include/live/airootfs/etc/skel/.config/dunst/dunstrc
index 6d56bc6f..e6339fcc 100644
--- a/.linux_items/include/live/airootfs/etc/skel/.config/dunst/dunstrc
+++ b/.linux_items/include/live/airootfs/etc/skel/.config/dunst/dunstrc
@@ -29,7 +29,7 @@
# 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-30+20"
+ geometry = "300x5-220+40"
# Show how many messages are currently hidden (because of geometry).
indicate_hidden = yes
diff --git a/.linux_items/include/live/airootfs/etc/skel/.xinitrc b/.linux_items/include/live/airootfs/etc/skel/.xinitrc
index 33e09a89..918fc507 100755
--- a/.linux_items/include/live/airootfs/etc/skel/.xinitrc
+++ b/.linux_items/include/live/airootfs/etc/skel/.xinitrc
@@ -13,6 +13,7 @@ nm-applet &
cbatticon &
pasystray &
connect-to-network &
+(sleep 5s && killall dunst) &
$HOME/.urxvt_default_res &
$HOME/.update_wallpaper &
$HOME/.update_conky &
From a230810dbca8898b57f022b660c0425aa782b216 Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Tue, 19 Dec 2017 05:10:52 -0700
Subject: [PATCH 08/42] Prevent duplicate conky entrie creation on relogin
---
.linux_items/include/live/airootfs/etc/skel/.update_conky | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/.linux_items/include/live/airootfs/etc/skel/.update_conky b/.linux_items/include/live/airootfs/etc/skel/.update_conky
index 8fba9f91..f67dc893 100755
--- a/.linux_items/include/live/airootfs/etc/skel/.update_conky
+++ b/.linux_items/include/live/airootfs/etc/skel/.update_conky
@@ -2,7 +2,7 @@
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
@@ -10,3 +10,7 @@ for i in "${IF_LIST[@]}"; do
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
+
From a84b2dfef6a2c7b3268b7016e4efdb1bc8897e93 Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Tue, 19 Dec 2017 07:06:42 -0700
Subject: [PATCH 09/42] Thunar no stays open after mount-all-volumes call
---
.bin/Scripts/mount-all-volumes | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.bin/Scripts/mount-all-volumes b/.bin/Scripts/mount-all-volumes
index a183e5c3..fbd7084b 100755
--- a/.bin/Scripts/mount-all-volumes
+++ b/.bin/Scripts/mount-all-volumes
@@ -29,7 +29,7 @@ if __name__ == '__main__':
print_standard('\nDone.')
if 'foh' in sys.argv:
pause("Press Enter to exit...")
- popen_program(['thunar', '/media'])
+ popen_program(['nohup', 'thunar', '/media'])
exit_script()
except SystemExit:
pass
From 96ef259b4ce28de15f8d145ec2521b0a0ee678a7 Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Thu, 21 Dec 2017 17:11:35 -0700
Subject: [PATCH 10/42] New HW sensors script
* Rewritten in python
* Report CoreTemps first then others
* Wrap into two columns as necessary (if the window is big enough)
---
.bin/Scripts/borrowed/sensors-README.md | 35 +++
.bin/Scripts/borrowed/sensors.py | 236 ++++++++++++++++++
.bin/Scripts/hw-sensors | 147 +++++++++++
.bin/Scripts/linux-old/hw-diags-sensors | 42 ----
.../live/airootfs/etc/skel/.config/i3/config | 2 +-
.../airootfs/etc/skel/.config/openbox/rc.xml | 2 +-
6 files changed, 420 insertions(+), 44 deletions(-)
create mode 100644 .bin/Scripts/borrowed/sensors-README.md
create mode 100644 .bin/Scripts/borrowed/sensors.py
create mode 100755 .bin/Scripts/hw-sensors
delete mode 100755 .bin/Scripts/linux-old/hw-diags-sensors
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/hw-sensors b/.bin/Scripts/hw-sensors
new file mode 100755
index 00000000..07c98460
--- /dev/null
+++ b/.bin/Scripts/hw-sensors
@@ -0,0 +1,147 @@
+#!/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}°C{CLEAR}'.format(
+ color = color,
+ prefix = '+' if temp>0 else '-',
+ temp = int(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
+ 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
+ clear_screen()
+ 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
+ for line in sensor_temps:
+ print_standard(line)
+
+ # Done
+ sensors.cleanup()
+ exit_script()
+ except SystemExit:
+ sensors.cleanup()
+ pass
+ except:
+ sensors.cleanup()
+ major_exception()
+
diff --git a/.bin/Scripts/linux-old/hw-diags-sensors b/.bin/Scripts/linux-old/hw-diags-sensors
deleted file mode 100755
index 5f4f494d..00000000
--- a/.bin/Scripts/linux-old/hw-diags-sensors
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/bash
-#
-## Wizard Kit: HW Diagnostics - Sensors
-
-LOG_DIR="$1"
-
-function usage {
- echo "Usage: $0 log-dir"
- echo " e.g. $0 /tmp/tmp.7Mh5f1RhSL9001"
-}
-
-# Create directory if necessary
-if [ ! -d "$LOG_DIR" ]; then
- LOG_DIR="$(mktemp -d)"
-fi
-
-# Run Sensor loop
-if sensors >/dev/null 2>&1; then
- while :; do
- sensors -A | grep -E -i -v '(N/A|RPM|\d+\s+V\s+|^\s*$)' > "$LOG_DIR/sensors.out" 2>/dev/null
-
- # Colorize
- # Blue: All temps (superseeded by other colors below)
- sed -i -r 's#(\+[0-9]+\.[0-9].C)#\\e[34m\1\\e[0m#g' "$LOG_DIR/sensors.out" >/dev/null 2>&1
- # Green >= 60* C
- sed -i -r 's#(\+6[0-9]\.[0-9].C)#\\e[32m\1\\e[0m#g' "$LOG_DIR/sensors.out" >/dev/null 2>&1
- # Yellow >= 70* C
- sed -i -r 's#(\+7[0-9]\.[0-9].C)#\\e[33m\1\\e[0m#g' "$LOG_DIR/sensors.out" >/dev/null 2>&1
- # Orange >= 80* C
- sed -i -r 's#(\+(8[0-9]|9[0-4])\.[0-9].C)#\\e[31\;1m\1\\e[0m#g' "$LOG_DIR/sensors.out" >/dev/null 2>&1
- # Red >= 95* C
- sed -i -r 's#(\+(9[5-9]|1[0-9][0-9])\.[0-9].C)#\\e[31m\1\\e[0m#g' "$LOG_DIR/sensors.out" >/dev/null 2>&1
-
- # Output data
- clear
- echo -e "$(cat "$LOG_DIR/sensors.out")"
- sleep 1s
- done
-else
- echo -e "\e[33mNo sensors found!\nPlease monitor temperatures manually\e[0m"
- sleep 1h
-fi
diff --git a/.linux_items/include/live/airootfs/etc/skel/.config/i3/config b/.linux_items/include/live/airootfs/etc/skel/.config/i3/config
index 67423053..59b798cf 100644
--- a/.linux_items/include/live/airootfs/etc/skel/.config/i3/config
+++ b/.linux_items/include/live/airootfs/etc/skel/.config/i3/config
@@ -74,7 +74,7 @@ bindsym $mod+i exec "hardinfo"
bindsym $mod+m exec "urxvt -title 'Mount All Volumes' -e mount-all-volumes foh"
bindsym $mod+s exec "urxvt -title 'Hardware Diagnostics' -e hw-diags foh"
bindsym $mod+t exec "urxvt"
-bindsym $mod+v exec "urxvt -title 'Hardware Sensors' -e hw-diags-sensors"
+bindsym $mod+v exec "urxvt -title 'Hardware Sensors' -e watch -c -n1 -t hw-sensors"
bindsym $mod+w exec "firefox"
focus_follows_mouse no
diff --git a/.linux_items/include/live/airootfs/etc/skel/.config/openbox/rc.xml b/.linux_items/include/live/airootfs/etc/skel/.config/openbox/rc.xml
index c48340dd..f1056533 100644
--- a/.linux_items/include/live/airootfs/etc/skel/.config/openbox/rc.xml
+++ b/.linux_items/include/live/airootfs/etc/skel/.config/openbox/rc.xml
@@ -334,7 +334,7 @@
- urxvt -title "Hardware Sensors" -e hw-diags-sensors
+ urxvt -title "Hardware Sensors" -e watch -c -n1 -t hw-sensors
From 1cfa008b8e8ad4786d5d68d10560cc9984a31ee6 Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Thu, 21 Dec 2017 22:31:21 -0700
Subject: [PATCH 11/42] New MS Word search script
---
.bin/Scripts/linux-old/msword-search | 39 --------------
.bin/Scripts/msword-search | 81 ++++++++++++++++++++++++++++
2 files changed, 81 insertions(+), 39 deletions(-)
delete mode 100755 .bin/Scripts/linux-old/msword-search
create mode 100755 .bin/Scripts/msword-search
diff --git a/.bin/Scripts/linux-old/msword-search b/.bin/Scripts/linux-old/msword-search
deleted file mode 100755
index def215b6..00000000
--- a/.bin/Scripts/linux-old/msword-search
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/bash
-#
-## Wizard Kit: MS Word content search tool
-TMP_FILE="$(mktemp)"
-
-IFS=$'\n'
-for s in $*; do
- REGEX="$s"
- REGEX=$(echo "$REGEX" | sed -r 's/\s+/\\s\*/g')
-
- # Word Doc
- for d in *doc; do
- if antiword "$d" | grep -iqsP "($REGEX)"; then
- echo "Possible match: $d"
- echo "$d" >> "$TMP_FILE"
- fi
- done
-
- # Word Docx
- for d in *docx; do
- if unzip -p "$d" word/document.xml | grep -iqsP "($REGEX)"; then
- echo "Possible match: $d"
- echo "$d" >> "$TMP_FILE"
- fi
- done
-
-done
-
-# Cleanup results
-if [[ -s "$TMP_FILE" ]]; then
- sort -u "$TMP_FILE" >> "$HOME/msword-matches.txt"
-fi
-rm "$TMP_FILE"
-
-# Done
-if [[ -s "$HOME/msword-matches.txt" ]]; then
- echo "Found $(wc -l "$HOME/msword-matches.txt") possible matches"
- echo "The results have been saved to $HOME"
-fi
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()
+
From e96d49128550f15eb0c134eb87a8ffec67da0bec Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Thu, 21 Dec 2017 23:16:50 -0700
Subject: [PATCH 12/42] New mount-backup-shares script
---
.bin/Scripts/functions/data.py | 47 ++++++++++++++++++++++++++------
.bin/Scripts/mount-backup-shares | 39 ++++++++++++++++++++++++++
2 files changed, 77 insertions(+), 9 deletions(-)
create mode 100755 .bin/Scripts/mount-backup-shares
diff --git a/.bin/Scripts/functions/data.py b/.bin/Scripts/functions/data.py
index c1a3b352..414c2fba 100644
--- a/.bin/Scripts/functions/data.py
+++ b/.bin/Scripts/functions/data.py
@@ -236,36 +236,65 @@ def mount_all_volumes():
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:
- # Blindly skip if we mounted earlier
+ 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_error(
- r'Failed to mount \\{Name}\{Share}, {IP} unreachable.'.format(
- **server))
+ print_warning(warning)
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))
+ print_error(error)
sleep(1)
else:
- print_info('Mounted {Name}'.format(**server))
+ print_info(success)
server['Mounted'] = True
def run_fast_copy(items, dest):
diff --git a/.bin/Scripts/mount-backup-shares b/.bin/Scripts/mount-backup-shares
new file mode 100755
index 00000000..1185c9b7
--- /dev/null
+++ b/.bin/Scripts/mount-backup-shares
@@ -0,0 +1,39 @@
+#!/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
+ if not is_connected():
+ 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()
+
From 374d4a1c98c93dfe0105bd50021922208b8045f2 Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Thu, 21 Dec 2017 23:17:45 -0700
Subject: [PATCH 13/42] Removed old mount-backup-shares script
---
.bin/Scripts/linux-old/mount-backup-shares | 67 ----------------------
1 file changed, 67 deletions(-)
delete mode 100755 .bin/Scripts/linux-old/mount-backup-shares
diff --git a/.bin/Scripts/linux-old/mount-backup-shares b/.bin/Scripts/linux-old/mount-backup-shares
deleted file mode 100755
index 1a9085b9..00000000
--- a/.bin/Scripts/linux-old/mount-backup-shares
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/bin/bash
-#
-## Wizard Kit: Backup share mount tool
-
-die () {
- echo "$0:" "$@" >&2
- exit 1
-}
-
-# Load settings
-if [[ -f "/run/archiso/bootmnt/arch/main.conf" ]]; then
- source "/run/archiso/bootmnt/arch/main.conf" || \
- die "ERROR: failed to load main.conf (from /run/archiso/bootmnt/arch/)"
-else
- source "/usr/local/bin/main.conf" || \
- die "ERROR: failed to load main.conf (from /usr/local/bin/)"
-fi
-
-# Connect to a network
-connect-to-network
-
-# Mount loop
-echo "Mounting NAS backup shares"
-for x in {1..4}; do
- _skip="False"
-
- # Load Backup share info
- eval "declare -a _backup=(\${BACKUP_$x[@]})"
- _name="${_backup[0]}"
- _ip="${_backup[1]}"
- _share="${_backup[2]}"
- _user="${_backup[3]}"
- _pass="${_backup[4]}"
-
- # Check backup share info
- if echo "$_name" | grep -Eq '^\s*$'; then
- _skip="True";
- fi
- if echo "$_ip" | grep -Eq '^\s*$'; then
- _skip="True";
- fi
- if echo "$_share" | grep -Eq '^\s*$'; then
- _skip="True";
- fi
- if echo "$_user" | grep -Eq '^\s*$'; then
- _skip="True";
- fi
- if echo "$_pass" | grep -Eq '^\s*$'; then
- _skip="True";
- fi
-
- # Mount
- if [[ "$_skip" == "False" ]]; then
- sudo mkdir "/Backups/$_name" -p
- if mountpoint -q "/Backups/$_name"; then
- echo "$_name: (Already) mounted at /Backups/$_name ($(df -h "/Backups/$_name" | tail -1 | awk '{print $4}' | sed -r 's/([KMGT])/ \1b/') free)"
- else
- if sudo mount "//$_ip/$_share" "/Backups/$_name" -o username=$_user,password=$_pass 2>/dev/null; then
- echo "$_name: Mounted at /Backups/$_name ($(df -h "/Backups/$_name" | tail -1 | awk '{print $4}' | sed -r 's/([KMGT])/ \1b/') free)"
- else
- rmdir "/Backups/$_name" -p 2>/dev/null
- echo "$_name: Failed to mount"
- fi
- fi
- fi
-done
-
From e19bcf1000189f90e8f3f4a01ad1e820f3b9050f Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Thu, 21 Dec 2017 23:18:52 -0700
Subject: [PATCH 14/42] Renamed apple_fans to apple-fans
* Done to match naming scheme
---
.bin/Scripts/{apple_fans => apple-fans} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename .bin/Scripts/{apple_fans => apple-fans} (100%)
diff --git a/.bin/Scripts/apple_fans b/.bin/Scripts/apple-fans
similarity index 100%
rename from .bin/Scripts/apple_fans
rename to .bin/Scripts/apple-fans
From 1760c030eff4139997445c303a58b84be86604ac Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Thu, 21 Dec 2017 23:34:56 -0700
Subject: [PATCH 15/42] New hw-diags-audio script
---
.bin/Scripts/hw-diags-audio | 39 +++++++++++++++++++++++++++
.bin/Scripts/linux-old/hw-diags-audio | 12 ---------
2 files changed, 39 insertions(+), 12 deletions(-)
create mode 100755 .bin/Scripts/hw-diags-audio
delete mode 100755 .bin/Scripts/linux-old/hw-diags-audio
diff --git a/.bin/Scripts/hw-diags-audio b/.bin/Scripts/hw-diags-audio
new file mode 100755
index 00000000..531ccb92
--- /dev/null
+++ b/.bin/Scripts/hw-diags-audio
@@ -0,0 +1,39 @@
+#!/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()
+
+ # 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
+ run_program('speaker-test -c 2 -l 1 -t pink'.split(), check=False)
+ #run_program('speaker-test -c 2 -l 1 -t sine'.split(), check=False)
+ run_program('speaker-test -c 2 -l 1 -t wav'.split(), check=False)
+
+ # Done
+ #print_standard('\nDone.')
+ #pause("Press Enter to exit...")
+ exit_script()
+ except SystemExit:
+ pass
+ except:
+ major_exception()
+
diff --git a/.bin/Scripts/linux-old/hw-diags-audio b/.bin/Scripts/linux-old/hw-diags-audio
deleted file mode 100755
index 814eaf3a..00000000
--- a/.bin/Scripts/linux-old/hw-diags-audio
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/bash
-#
-## Wizard Kit: HW Diagnostics - Audio
-
-# Unmute and set volume
-amixer -q set "Master" 80% unmute
-amixer -q set "PCM" 90% unmute
-
-speaker-test -c 2 -l 1 -t pink
-# speaker-test -c 2 -l 1 -t sine
-speaker-test -c 2 -l 1 -t wav
-
From a1b72c0aeb16f682b43c58c309b5efceb9810aed Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Fri, 22 Dec 2017 00:45:42 -0700
Subject: [PATCH 16/42] New hw-diags-network script
---
.bin/Scripts/connect-to-network | 3 +-
.bin/Scripts/functions/common.py | 9 ++-
.bin/Scripts/functions/network.py | 16 ++++++
.bin/Scripts/hw-diags-network | 45 +++++++++++++++
.bin/Scripts/linux-old/hw-diags-network | 73 -------------------------
.bin/Scripts/mount-backup-shares | 3 +-
6 files changed, 69 insertions(+), 80 deletions(-)
create mode 100755 .bin/Scripts/hw-diags-network
delete mode 100755 .bin/Scripts/linux-old/hw-diags-network
diff --git a/.bin/Scripts/connect-to-network b/.bin/Scripts/connect-to-network
index 9f388581..0475c15c 100755
--- a/.bin/Scripts/connect-to-network
+++ b/.bin/Scripts/connect-to-network
@@ -17,8 +17,7 @@ if __name__ == '__main__':
clear_screen()
# Connect
- if not is_connected():
- connect_to_network()
+ connect_to_network()
# Done
print_standard('\nDone.')
diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py
index 9cd52f4b..a58fa5ce 100644
--- a/.bin/Scripts/functions/common.py
+++ b/.bin/Scripts/functions/common.py
@@ -459,10 +459,13 @@ def try_and_print(message='Trying...',
try:
out = function(*args, **kwargs)
if print_return:
- print_standard(out[0], timestamp=False)
- for item in out[1:]:
+ 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))
+ indent=' '*(indent+width), item=item.strip()))
elif silent_function:
print_success(cs, timestamp=False)
except w_exceptions as e:
diff --git a/.bin/Scripts/functions/network.py b/.bin/Scripts/functions/network.py
index 6b8c2c3c..1f987248 100644
--- a/.bin/Scripts/functions/network.py
+++ b/.bin/Scripts/functions/network.py
@@ -53,6 +53,22 @@ def is_connected():
# 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'])
diff --git a/.bin/Scripts/hw-diags-network b/.bin/Scripts/hw-diags-network
new file mode 100755
index 00000000..b542d739
--- /dev/null
+++ b/.bin/Scripts/hw-diags-network
@@ -0,0 +1,45 @@
+#!/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()
+
+ # 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/linux-old/hw-diags-network b/.bin/Scripts/linux-old/hw-diags-network
deleted file mode 100755
index 997a8f0c..00000000
--- a/.bin/Scripts/linux-old/hw-diags-network
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/bin/bash
-#
-## Wizard Kit: HW Diagnostics - Network
-
-function test_connection() {
- cmd="a"
- if [[ -e "/sys/class/net/$1" ]]; then
- cmd="a show $1"
- fi
- if ip $cmd | grep -Eq '(10.[0-9]+|172.(1[6-9]|2[0-9]|3[0-1]).[0-9]+|192.168).[0-9]+.[0-9]+'; then
- return 0
- else
- return 1
- fi
-}
-
-
-CLEAR="\e[0m"
-RED="\e[31m"
-GREEN="\e[32m"
-YELLOW="\e[33m"
-BLUE="\e[34m"
-
-# Header
-echo "WK HW Diagnostics - Network"
-echo ""
-
-# Start Wifi if necessary
-echo "Initializing..."
-connect-to-network >/dev/null 2>&1
-
-# Check network connection
-echo -n "Network connection: "
-if test_connection; then
- echo -e "${GREEN}OK${CLEAR}"
-else
- echo -e "${RED}No access${CLEAR}"
- exit 1
-fi
-
-# Check IP addresses
-for d in /sys/class/net/*; do
- device="$(basename $d)"
- if [ "$device" != "lo" ]; then
- if test_connection $device; then
- ip="$(ip a show $device | egrep 'inet [0-9]' | sed -r 's#.*inet (.*?/[0-9]+).*#\1#')"
- echo "$device: $ip" | awk '{printf " %-16s %s\n", $1, $2}'
- fi
- fi
-done
-
-# Check internet connection
-echo -n "Internet connection: "
-if ping -c 2 -q 8.8.8.8 >/dev/null 2>&1; then
- echo -e "${GREEN}OK${CLEAR}"
-else
- echo -e "${RED}No access${CLEAR}"
- exit 1
-fi
-
-# Check DNS
-echo -n "DNS Resolution: "
-if ping -c 2 -q google.com >/dev/null 2>&1; then
- echo -e "${GREEN}OK${CLEAR}"
-else
- echo -e "${RED}Unable to resolve google.com${CLEAR}"
- exit 1
-fi
-
-# Check speed
-echo "Speedtest:"
-speedtest-cli --simple | awk '{printf " %-16s %6.2f %s\n", $1, $2, $3}'
-
diff --git a/.bin/Scripts/mount-backup-shares b/.bin/Scripts/mount-backup-shares
index 1185c9b7..9706a0a5 100755
--- a/.bin/Scripts/mount-backup-shares
+++ b/.bin/Scripts/mount-backup-shares
@@ -18,8 +18,7 @@ if __name__ == '__main__':
clear_screen()
# Connect
- if not is_connected():
- connect_to_network()
+ connect_to_network()
# Mount
if is_connected():
From a7606a4b5c85e238c786044ea44ace9c154e8649 Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Sat, 23 Dec 2017 14:24:15 -0700
Subject: [PATCH 17/42] Print script names and audio tests output
---
.bin/Scripts/hw-diags-audio | 9 ++++++---
.bin/Scripts/hw-diags-network | 1 +
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/.bin/Scripts/hw-diags-audio b/.bin/Scripts/hw-diags-audio
index 531ccb92..88168263 100755
--- a/.bin/Scripts/hw-diags-audio
+++ b/.bin/Scripts/hw-diags-audio
@@ -15,6 +15,7 @@ if __name__ == '__main__':
try:
# Prep
clear_screen()
+ print_standard('Hardware Diagnostics: Audio\n')
# Set volume
try:
@@ -24,9 +25,11 @@ if __name__ == '__main__':
print_error('Failed to set volume')
# Run tests
- run_program('speaker-test -c 2 -l 1 -t pink'.split(), check=False)
- #run_program('speaker-test -c 2 -l 1 -t sine'.split(), check=False)
- run_program('speaker-test -c 2 -l 1 -t wav'.split(), check=False)
+ 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.')
diff --git a/.bin/Scripts/hw-diags-network b/.bin/Scripts/hw-diags-network
index b542d739..5fdd26a4 100755
--- a/.bin/Scripts/hw-diags-network
+++ b/.bin/Scripts/hw-diags-network
@@ -19,6 +19,7 @@ if __name__ == '__main__':
try:
# Prep
clear_screen()
+ print_standard('Hardware Diagnostics: Network\n')
# Connect
print_standard('Initializing...')
From 5d6e138d2958a4bf8ade461806c46816d9aa5e85 Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Sat, 23 Dec 2017 19:11:50 -0700
Subject: [PATCH 18/42] Started hw-diags & hw-diags-inner rewrite
---
.bin/Scripts/functions/common.py | 14 +-
.bin/Scripts/hw-diags | 43 ++++
.bin/Scripts/hw-diags-menu | 200 ++++++++++++++++++
.../include/live/airootfs/etc/skel/.tmux.conf | 5 +
4 files changed, 256 insertions(+), 6 deletions(-)
create mode 100755 .bin/Scripts/hw-diags
create mode 100755 .bin/Scripts/hw-diags-menu
diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py
index a58fa5ce..4b9727d7 100644
--- a/.bin/Scripts/functions/common.py
+++ b/.bin/Scripts/functions/common.py
@@ -233,7 +233,8 @@ def major_exception():
def menu_select(title='~ Untitled Menu ~',
prompt='Please make a selection', secret_exit=False,
- main_entries=[], action_entries=[], disabled_label='DISABLED'):
+ 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:
@@ -244,7 +245,7 @@ def menu_select(title='~ Untitled Menu ~',
title = '{}\n\n{}'.format(global_vars['Title'], title)
# Build menu
- menu_splash = '{}\n\n'.format(title)
+ menu_splash = '{}\n{}\n'.format(title, spacer)
width = len(str(len(main_entries)))
valid_answers = []
if (secret_exit):
@@ -255,7 +256,7 @@ def menu_select(title='~ Untitled Menu ~',
entry = main_entries[i]
# Add Spacer
if ('CRLF' in entry):
- menu_splash += '\n'
+ menu_splash += '{}\n'.format(spacer)
entry_str = '{number:>{width}}: {name}'.format(
number = i+1,
width = width,
@@ -268,13 +269,13 @@ def menu_select(title='~ Untitled Menu ~',
else:
valid_answers.append(str(i+1))
menu_splash += '{}\n'.format(entry_str)
- menu_splash += '\n'
+ menu_splash += '{}\n'.format(spacer)
# Add action entries
for entry in action_entries:
# Add Spacer
if ('CRLF' in entry):
- menu_splash += '\n'
+ menu_splash += '{}\n'.format(spacer)
valid_answers.append(entry['Letter'])
menu_splash += '{letter:>{width}}: {name}\n'.format(
letter = entry['Letter'].upper(),
@@ -554,7 +555,8 @@ def wait_for_process(name, poll_rate=3):
def init_global_vars():
"""Sets global variables based on system info."""
print_info('Initializing')
- os.system('title Wizard Kit')
+ if psutil.WINDOWS:
+ os.system('title Wizard Kit')
if psutil.LINUX:
init_functions = [
['Checking environment...', set_linux_vars],
diff --git a/.bin/Scripts/hw-diags b/.bin/Scripts/hw-diags
new file mode 100755
index 00000000..4ce5afdc
--- /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-menu b/.bin/Scripts/hw-diags-menu
new file mode 100755
index 00000000..0fc19d77
--- /dev/null
+++ b/.bin/Scripts/hw-diags-menu
@@ -0,0 +1,200 @@
+#!/bin/python3
+#
+## Wizard Kit: HW Diagnostics - Menu
+
+import libtmux
+import json
+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()
+
+# STATIC VARIABLES
+sleep(1)
+TMUX = libtmux.Server()
+SESSION = TMUX.find_where({'session_name': 'hw-diags'})
+WINDOW = SESSION.windows[0] # Should be a safe assumption
+PANE = WINDOW.panes[0] # Should be a safe assumption
+PROGRESS_FILE = '{}/progress.out'.format(global_vars['LogDir'])
+TESTS = {
+ 'Prime95': {
+ 'Enabled': False,
+ 'Status': 'Pending',
+ },
+ 'SMART': {
+ 'Enabled': False,
+ 'Quick': False,
+ },
+ 'badblocks': {
+ 'Enabled': False,
+ },
+ }
+
+def get_status_color(s):
+ color = COLORS['CLEAR']
+ if s in ['NS', 'Unknown']:
+ color = COLORS['RED']
+ elif s in ['Working', 'Skipped']:
+ color = COLORS['YELLOW']
+ elif s in ['CS']:
+ color = COLORS['GREEN']
+ return color
+
+def update_progress(color=True):
+ with open(PROGRESS_FILE, 'w') as f:
+ if color:
+ f.write('{BLUE}HW Diagnostics{CLEAR}\n'.format(**COLORS))
+ f.write('───────────────\n')
+ if TESTS['Prime95']['Enabled']:
+ f.write('{BLUE}Prime95{s_color}{status:>8}{CLEAR}\n'.format(
+ s_color = get_status_color(TESTS['Prime95']['Status']),
+ status = status,
+ **COLORS))
+ if TESTS['SMART']['Enabled']:
+ f.write('{BLUE}SMART{CLEAR}\n'.format(**COLORS))
+ for dev, status in sorted(TESTS['SMART']['Devices'].items()):
+ f.write('{dev}{s_color}{status:>{pad}}{CLEAR}\n'.format(
+ dev = dev,
+ pad = 16-len(dev),
+ s_color = get_status_color(status),
+ status = status,
+ **COLORS))
+ if TESTS['badblocks']['Enabled']:
+ f.write('{BLUE}badblocks{CLEAR}\n'.format(**COLORS))
+ for dev, status in sorted(TESTS['badblocks']['Devices'].items()):
+ f.write('{dev}{s_color}{status:>{pad}}{CLEAR}\n'.format(
+ dev = dev,
+ pad = 16-len(dev),
+ s_color = get_status_color(status),
+ status = status,
+ **COLORS))
+ else:
+ f.write('HW Diagnostics\n')
+ f.write('───────────────\n')
+ if TESTS['Prime95']['Enabled']:
+ f.write('Prime95{:>8}\n'.format(TESTS['Prime95']['Status']))
+ if TESTS['SMART']['Enabled']:
+ f.write('SMART\n')
+ for dev, status in sorted(TESTS['SMART']['Devices'].items()):
+ f.write('{}{:>{}}\n'.format(dev, 16-len(dev), status))
+ if TESTS['badblocks']['Enabled']:
+ f.write('badblocks\n')
+ for dev, status in sorted(TESTS['badblocks']['Devices'].items()):
+ f.write('{}{:>{}}\n'.format(dev, 16-len(dev), status))
+
+def run_tests(tests):
+ for t in ['Prime95', 'SMART', 'badblocks']:
+ if t in tests:
+ TESTS[t]['Enabled'] = True
+ TESTS['SMART']['Quick'] = 'Quick' in tests
+
+ # Get (disk) device list
+ if TESTS['SMART']['Enabled'] or TESTS['badblocks']['Enabled']:
+ cmd = 'lsblk -J -o NAME,TYPE'.split()
+ result = run_program(cmd)
+ json_data = json.loads(result.stdout.decode())
+ devs = json_data.get('blockdevices', [])
+ devs = ['/dev/'+d['name'] for d in devs if d['type'] == 'disk']
+ devs = {d: 'Pending' for d in devs}
+ TESTS['SMART']['Devices'] = devs
+ TESTS['badblocks']['Devices'] = devs
+
+ # Initialize progress display
+ update_progress()
+
+ # Run
+ if TESTS['Prime95']['Enabled']:
+ run_mprime()
+ if TESTS['SMART']['Enabled']:
+ run_smart()
+ if TESTS['badblocks']['Enabled']:
+ run_badblocks()
+
+def run_smart():
+ pass
+
+def run_badblocks():
+ pass
+
+def run_mprime():
+ # Set Window layout
+ window = SESSION.new_window()
+ pane_sensors = window.panes[0]
+ pane_mprime = window.split_window(attach=False)
+ pane_mprime.set_height(10)
+ pane_progress = window.split_window(attach=False, vertical=False)
+ pane_progress.set_width(16)
+
+ # Start test
+ run_program(['apple-fans', 'max'])
+ pane_sensors.send_keys('watch -c -n1 -t hw-sensors')
+ pane_progress.send_keys('watch -c -n1 -t "{}"'.format(PROGRESS_FILE))
+ pane_mprime.send_keys('mprime -t')
+ #sleep(MPRIME_LIMIT*60)
+ sleep(15)
+
+ # Done
+ window.kill_window()
+
+def diags_menu():
+ diag_modes = [
+ {'Name': 'All tests', 'Tests': ['Prime95', 'SMART', 'badblocks']},
+ {'Name': 'Prime95', 'Tests': ['Prime95']},
+ {'Name': 'SMART & badblocks', 'Tests': ['SMART', 'badblocks']},
+ {'Name': 'SMART', 'Tests': ['SMART']},
+ {'Name': 'badblocks', 'Tests': ['badblocks']},
+ {'Name': 'Quick drive test', 'Tests': ['Quick', '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},
+ ]
+
+ # Show menu
+ while True:
+ selection = menu_select(
+ title = 'Hardware Diagnostics: Menu',
+ main_entries = diag_modes,
+ action_entries = actions,
+ spacer = '─────────────────────────')
+ if selection.isnumeric():
+ run_tests(diag_modes[int(selection)-1]['Tests'])
+ elif selection == 'A':
+ run_program(['hw-diags-audio'], check=False, pipe=False)
+ sleep(1)
+ elif selection == 'N':
+ run_program(['hw-diags-network'], check=False, pipe=False)
+ sleep(1)
+ 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
+
+if __name__ == '__main__':
+ try:
+ # Prep
+ clear_screen()
+
+ # Show menu
+ diags_menu()
+
+ # Done
+ #print_standard('\nDone.')
+ #pause("Press Enter to exit...")
+ exit_script()
+ except SystemExit:
+ pass
+ except:
+ major_exception()
+
diff --git a/.linux_items/include/live/airootfs/etc/skel/.tmux.conf b/.linux_items/include/live/airootfs/etc/skel/.tmux.conf
index 29cf429c..a3712835 100644
--- a/.linux_items/include/live/airootfs/etc/skel/.tmux.conf
+++ b/.linux_items/include/live/airootfs/etc/skel/.tmux.conf
@@ -1,2 +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
From 19d32dda0bc21f68d87176ad3e4e7f539dfb4a2a Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Sat, 23 Dec 2017 19:15:19 -0700
Subject: [PATCH 19/42] Reduce file opens during update_progress()
---
.bin/Scripts/hw-diags-menu | 92 ++++++++++++++++++++------------------
1 file changed, 49 insertions(+), 43 deletions(-)
diff --git a/.bin/Scripts/hw-diags-menu b/.bin/Scripts/hw-diags-menu
index 0fc19d77..52ab6f82 100755
--- a/.bin/Scripts/hw-diags-menu
+++ b/.bin/Scripts/hw-diags-menu
@@ -45,51 +45,58 @@ def get_status_color(s):
return color
def update_progress(color=True):
- with open(PROGRESS_FILE, 'w') as f:
- if color:
- f.write('{BLUE}HW Diagnostics{CLEAR}\n'.format(**COLORS))
- f.write('───────────────\n')
- if TESTS['Prime95']['Enabled']:
- f.write('{BLUE}Prime95{s_color}{status:>8}{CLEAR}\n'.format(
- s_color = get_status_color(TESTS['Prime95']['Status']),
+ output = []
+ if color:
+ output.append('{BLUE}HW Diagnostics{CLEAR}'.format(**COLORS))
+ output.append('───────────────')
+ if TESTS['Prime95']['Enabled']:
+ 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['SMART']['Enabled']:
+ output.append('{BLUE}SMART{CLEAR}'.format(**COLORS))
+ for dev, status in sorted(TESTS['SMART']['Devices'].items()):
+ output.append('{dev}{s_color}{status:>{pad}}{CLEAR}'.format(
+ dev = dev,
+ pad = 16-len(dev),
+ s_color = get_status_color(status),
status = status,
**COLORS))
- if TESTS['SMART']['Enabled']:
- f.write('{BLUE}SMART{CLEAR}\n'.format(**COLORS))
- for dev, status in sorted(TESTS['SMART']['Devices'].items()):
- f.write('{dev}{s_color}{status:>{pad}}{CLEAR}\n'.format(
- dev = dev,
- pad = 16-len(dev),
- s_color = get_status_color(status),
- status = status,
- **COLORS))
- if TESTS['badblocks']['Enabled']:
- f.write('{BLUE}badblocks{CLEAR}\n'.format(**COLORS))
- for dev, status in sorted(TESTS['badblocks']['Devices'].items()):
- f.write('{dev}{s_color}{status:>{pad}}{CLEAR}\n'.format(
- dev = dev,
- pad = 16-len(dev),
- s_color = get_status_color(status),
- status = status,
- **COLORS))
- else:
- f.write('HW Diagnostics\n')
- f.write('───────────────\n')
- if TESTS['Prime95']['Enabled']:
- f.write('Prime95{:>8}\n'.format(TESTS['Prime95']['Status']))
- if TESTS['SMART']['Enabled']:
- f.write('SMART\n')
- for dev, status in sorted(TESTS['SMART']['Devices'].items()):
- f.write('{}{:>{}}\n'.format(dev, 16-len(dev), status))
- if TESTS['badblocks']['Enabled']:
- f.write('badblocks\n')
- for dev, status in sorted(TESTS['badblocks']['Devices'].items()):
- f.write('{}{:>{}}\n'.format(dev, 16-len(dev), status))
+ if TESTS['badblocks']['Enabled']:
+ output.append('{BLUE}badblocks{CLEAR}'.format(**COLORS))
+ for dev, status in sorted(TESTS['badblocks']['Devices'].items()):
+ output.append('{dev}{s_color}{status:>{pad}}{CLEAR}'.format(
+ dev = dev,
+ pad = 16-len(dev),
+ s_color = get_status_color(status),
+ status = status,
+ **COLORS))
+ else:
+ output.append('HW Diagnostics')
+ output.append('───────────────')
+ if TESTS['Prime95']['Enabled']:
+ output.append('Prime95{:>8}'.format(TESTS['Prime95']['Status']))
+ if TESTS['SMART']['Enabled']:
+ output.append('SMART')
+ for dev, status in sorted(TESTS['SMART']['Devices'].items()):
+ output.append('{}{:>{}}'.format(dev, 16-len(dev), status))
+ if TESTS['badblocks']['Enabled']:
+ output.append('badblocks')
+ for dev, status in sorted(TESTS['badblocks']['Devices'].items()):
+ output.append('{}{:>{}}'.format(dev, 16-len(dev), status))
+
+ # Add line-endings
+ output = ['{}\n'.format(line) for line in output]
+ print(output)
+ pause()
+
+ with open(PROGRESS_FILE, 'w') as f:
+ f.writelines(output)
def run_tests(tests):
for t in ['Prime95', 'SMART', 'badblocks']:
- if t in tests:
- TESTS[t]['Enabled'] = True
+ TESTS[t]['Enabled'] = t in tests
TESTS['SMART']['Quick'] = 'Quick' in tests
# Get (disk) device list
@@ -98,8 +105,7 @@ def run_tests(tests):
result = run_program(cmd)
json_data = json.loads(result.stdout.decode())
devs = json_data.get('blockdevices', [])
- devs = ['/dev/'+d['name'] for d in devs if d['type'] == 'disk']
- devs = {d: 'Pending' for d in devs}
+ devs = {d['name']: 'Pending' for d in devs if d['type'] == 'disk'}
TESTS['SMART']['Devices'] = devs
TESTS['badblocks']['Devices'] = devs
@@ -132,7 +138,7 @@ def run_mprime():
# Start test
run_program(['apple-fans', 'max'])
pane_sensors.send_keys('watch -c -n1 -t hw-sensors')
- pane_progress.send_keys('watch -c -n1 -t "{}"'.format(PROGRESS_FILE))
+ pane_progress.send_keys('watch -c -n1 -t cat "{}"'.format(PROGRESS_FILE))
pane_mprime.send_keys('mprime -t')
#sleep(MPRIME_LIMIT*60)
sleep(15)
From 8e26e09fe69d44b2367fd9e0b90856350095d8d6 Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Sat, 23 Dec 2017 19:40:09 -0700
Subject: [PATCH 20/42] Reordered functions
---
.bin/Scripts/hw-diags-menu | 186 ++++++++++++++++++-------------------
1 file changed, 93 insertions(+), 93 deletions(-)
diff --git a/.bin/Scripts/hw-diags-menu b/.bin/Scripts/hw-diags-menu
index 52ab6f82..4d678e7d 100755
--- a/.bin/Scripts/hw-diags-menu
+++ b/.bin/Scripts/hw-diags-menu
@@ -44,6 +44,99 @@ def get_status_color(s):
color = COLORS['GREEN']
return color
+def menu_diags():
+ diag_modes = [
+ {'Name': 'All tests', 'Tests': ['Prime95', 'SMART', 'badblocks']},
+ {'Name': 'Prime95', 'Tests': ['Prime95']},
+ {'Name': 'SMART & badblocks', 'Tests': ['SMART', 'badblocks']},
+ {'Name': 'SMART', 'Tests': ['SMART']},
+ {'Name': 'badblocks', 'Tests': ['badblocks']},
+ {'Name': 'Quick drive test', 'Tests': ['Quick', '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},
+ ]
+
+ # Show menu
+ while True:
+ selection = menu_select(
+ title = 'Hardware Diagnostics: Menu',
+ main_entries = diag_modes,
+ action_entries = actions,
+ spacer = '─────────────────────────')
+ if selection.isnumeric():
+ run_tests(diag_modes[int(selection)-1]['Tests'])
+ elif selection == 'A':
+ run_program(['hw-diags-audio'], check=False, pipe=False)
+ sleep(1)
+ elif selection == 'N':
+ run_program(['hw-diags-network'], check=False, pipe=False)
+ sleep(1)
+ 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():
+ pass
+
+def run_mprime():
+ # Set Window layout
+ window = SESSION.new_window()
+ pane_sensors = window.panes[0]
+ pane_mprime = window.split_window(attach=False)
+ pane_mprime.set_height(10)
+ pane_progress = window.split_window(attach=False, vertical=False)
+ pane_progress.set_width(16)
+
+ # Start test
+ run_program(['apple-fans', 'max'])
+ pane_sensors.send_keys('watch -c -n1 -t hw-sensors')
+ pane_progress.send_keys('watch -c -n1 -t cat "{}"'.format(PROGRESS_FILE))
+ pane_mprime.send_keys('mprime -t')
+ #sleep(MPRIME_LIMIT*60)
+ sleep(15)
+
+ # Done
+ window.kill_window()
+
+def run_smart():
+ pass
+
+def run_tests(tests):
+ for t in ['Prime95', 'SMART', 'badblocks']:
+ TESTS[t]['Enabled'] = t in tests
+ TESTS['SMART']['Quick'] = 'Quick' in tests
+
+ # Get (disk) device list
+ if TESTS['SMART']['Enabled'] or TESTS['badblocks']['Enabled']:
+ cmd = 'lsblk -J -o NAME,TYPE'.split()
+ result = run_program(cmd)
+ json_data = json.loads(result.stdout.decode())
+ devs = json_data.get('blockdevices', [])
+ devs = {d['name']: 'Pending' for d in devs if d['type'] == 'disk'}
+ TESTS['SMART']['Devices'] = devs
+ TESTS['badblocks']['Devices'] = devs
+
+ # Initialize progress display
+ update_progress()
+
+ # Run
+ if TESTS['Prime95']['Enabled']:
+ run_mprime()
+ if TESTS['SMART']['Enabled']:
+ run_smart()
+ if TESTS['badblocks']['Enabled']:
+ run_badblocks()
+
def update_progress(color=True):
output = []
if color:
@@ -94,99 +187,6 @@ def update_progress(color=True):
with open(PROGRESS_FILE, 'w') as f:
f.writelines(output)
-def run_tests(tests):
- for t in ['Prime95', 'SMART', 'badblocks']:
- TESTS[t]['Enabled'] = t in tests
- TESTS['SMART']['Quick'] = 'Quick' in tests
-
- # Get (disk) device list
- if TESTS['SMART']['Enabled'] or TESTS['badblocks']['Enabled']:
- cmd = 'lsblk -J -o NAME,TYPE'.split()
- result = run_program(cmd)
- json_data = json.loads(result.stdout.decode())
- devs = json_data.get('blockdevices', [])
- devs = {d['name']: 'Pending' for d in devs if d['type'] == 'disk'}
- TESTS['SMART']['Devices'] = devs
- TESTS['badblocks']['Devices'] = devs
-
- # Initialize progress display
- update_progress()
-
- # Run
- if TESTS['Prime95']['Enabled']:
- run_mprime()
- if TESTS['SMART']['Enabled']:
- run_smart()
- if TESTS['badblocks']['Enabled']:
- run_badblocks()
-
-def run_smart():
- pass
-
-def run_badblocks():
- pass
-
-def run_mprime():
- # Set Window layout
- window = SESSION.new_window()
- pane_sensors = window.panes[0]
- pane_mprime = window.split_window(attach=False)
- pane_mprime.set_height(10)
- pane_progress = window.split_window(attach=False, vertical=False)
- pane_progress.set_width(16)
-
- # Start test
- run_program(['apple-fans', 'max'])
- pane_sensors.send_keys('watch -c -n1 -t hw-sensors')
- pane_progress.send_keys('watch -c -n1 -t cat "{}"'.format(PROGRESS_FILE))
- pane_mprime.send_keys('mprime -t')
- #sleep(MPRIME_LIMIT*60)
- sleep(15)
-
- # Done
- window.kill_window()
-
-def diags_menu():
- diag_modes = [
- {'Name': 'All tests', 'Tests': ['Prime95', 'SMART', 'badblocks']},
- {'Name': 'Prime95', 'Tests': ['Prime95']},
- {'Name': 'SMART & badblocks', 'Tests': ['SMART', 'badblocks']},
- {'Name': 'SMART', 'Tests': ['SMART']},
- {'Name': 'badblocks', 'Tests': ['badblocks']},
- {'Name': 'Quick drive test', 'Tests': ['Quick', '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},
- ]
-
- # Show menu
- while True:
- selection = menu_select(
- title = 'Hardware Diagnostics: Menu',
- main_entries = diag_modes,
- action_entries = actions,
- spacer = '─────────────────────────')
- if selection.isnumeric():
- run_tests(diag_modes[int(selection)-1]['Tests'])
- elif selection == 'A':
- run_program(['hw-diags-audio'], check=False, pipe=False)
- sleep(1)
- elif selection == 'N':
- run_program(['hw-diags-network'], check=False, pipe=False)
- sleep(1)
- 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
-
if __name__ == '__main__':
try:
# Prep
From a733af679c2672593ba35e4a3f12e039d805e05a Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Sat, 23 Dec 2017 19:41:09 -0700
Subject: [PATCH 21/42] Forgot to set apple-fans to auto after Prime95
---
.bin/Scripts/hw-diags-menu | 1 +
1 file changed, 1 insertion(+)
diff --git a/.bin/Scripts/hw-diags-menu b/.bin/Scripts/hw-diags-menu
index 4d678e7d..bcf2220f 100755
--- a/.bin/Scripts/hw-diags-menu
+++ b/.bin/Scripts/hw-diags-menu
@@ -106,6 +106,7 @@ def run_mprime():
sleep(15)
# Done
+ run_program(['apple-fans', 'auto'])
window.kill_window()
def run_smart():
From 8acb493006b2b7ade11ee14591956a0c0f3d7e92 Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Sat, 23 Dec 2017 19:53:28 -0700
Subject: [PATCH 22/42] typo
---
.bin/Scripts/hw-diags-menu | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.bin/Scripts/hw-diags-menu b/.bin/Scripts/hw-diags-menu
index bcf2220f..8fcd5c5c 100755
--- a/.bin/Scripts/hw-diags-menu
+++ b/.bin/Scripts/hw-diags-menu
@@ -194,7 +194,7 @@ if __name__ == '__main__':
clear_screen()
# Show menu
- diags_menu()
+ menu_diags()
# Done
#print_standard('\nDone.')
From 87c09c4da08650d49e94ae237a02581cc67abcd0 Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Sun, 24 Dec 2017 00:21:33 -0700
Subject: [PATCH 23/42] New method for gathering SMART/NVMe data
* Replaced smartmontools with smartmontool-svn
* Adds JSON exporting which makes parsing the data easier
* Using nvme-cli for NVMe drives instead of smartctl
* NVMe support in smartctl is still experimental and inconsistent
* New "Health OK" detection
* This is used to determine if a disk is okay to be tested
* e.g. an IDE disk w/out any SMART data now requires explicit overriding
* NVMe disks are set using the "critical_warning" attribute
* SMART disks are set using the "overall-health" attribute
---
.bin/Scripts/functions/hw_diags.py | 241 +++++++++++++++++++++++++++++
.bin/Scripts/hw-diags-menu | 179 +--------------------
.linux_items/packages/aur | 3 +
.linux_items/packages/live | 3 +
4 files changed, 248 insertions(+), 178 deletions(-)
create mode 100755 .bin/Scripts/functions/hw_diags.py
diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py
new file mode 100755
index 00000000..62725f75
--- /dev/null
+++ b/.bin/Scripts/functions/hw_diags.py
@@ -0,0 +1,241 @@
+# Wizard Kit: Functions - HW Diagnostics
+
+import libtmux
+import json
+
+from functions.common import *
+
+# STATIC VARIABLES
+TMUX = libtmux.Server()
+SESSION = TMUX.find_where({'session_name': 'hw-diags'})
+WINDOW = SESSION.windows[0] # Should be a safe assumption
+PANE = WINDOW.panes[0] # Should be a safe assumption
+TESTS = {
+ 'Prime95': {
+ 'Enabled': False,
+ 'Status': 'Pending',
+ },
+ 'SMART': {
+ 'Enabled': False,
+ 'Quick': False,
+ },
+ 'badblocks': {
+ 'Enabled': False,
+ },
+ }
+
+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 ['NS', 'Unknown']:
+ color = COLORS['RED']
+ elif s in ['Working', 'Skipped']:
+ color = COLORS['YELLOW']
+ elif s in ['CS']:
+ color = COLORS['GREEN']
+ return color
+
+def menu_diags():
+ diag_modes = [
+ {'Name': 'All tests', 'Tests': ['Prime95', 'SMART', 'badblocks']},
+ {'Name': 'Prime95', 'Tests': ['Prime95']},
+ {'Name': 'SMART & badblocks', 'Tests': ['SMART', 'badblocks']},
+ {'Name': 'SMART', 'Tests': ['SMART']},
+ {'Name': 'badblocks', 'Tests': ['badblocks']},
+ {'Name': 'Quick drive test', 'Tests': ['Quick', '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},
+ ]
+
+ # Show menu
+ while True:
+ selection = menu_select(
+ title = 'Hardware Diagnostics: Menu',
+ main_entries = diag_modes,
+ action_entries = actions,
+ spacer = '─────────────────────────')
+ if selection.isnumeric():
+ run_tests(diag_modes[int(selection)-1]['Tests'])
+ elif selection == 'A':
+ run_program(['hw-diags-audio'], check=False, pipe=False)
+ sleep(1)
+ elif selection == 'N':
+ run_program(['hw-diags-network'], check=False, pipe=False)
+ sleep(1)
+ 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():
+ pass
+
+def run_mprime():
+ # Set Window layout
+ window = SESSION.new_window()
+ pane_sensors = window.panes[0]
+ pane_mprime = window.split_window(attach=False)
+ pane_mprime.set_height(10)
+ pane_progress = window.split_window(attach=False, vertical=False)
+ pane_progress.set_width(16)
+
+ # Start test
+ run_program(['apple-fans', 'max'])
+ pane_sensors.send_keys('watch -c -n1 -t hw-sensors')
+ pane_progress.send_keys('watch -c -n1 -t cat "{}"'.format(TESTS['Progress Out']))
+ pane_mprime.send_keys('mprime -t')
+ #sleep(MPRIME_LIMIT*60)
+ sleep(15)
+
+ # Done
+ run_program(['apple-fans', 'auto'])
+ window.kill_window()
+
+def run_smart():
+ # Set Window layout
+ window = SESSION.new_window()
+ pane_sensors = window.panes[0]
+ pane_smart = window.split_window(attach=False)
+ pane_smart.set_height(10)
+ pane_progress = window.split_window(attach=False, vertical=False)
+ pane_progress.set_width(16)
+
+ # Start test
+ run_program(['apple-fans', 'max'])
+ pane_sensors.send_keys('watch -c -n1 -t hw-sensors')
+ pane_progress.send_keys('watch -c -n1 -t cat "{}"'.format(TESTS['Progress Out']))
+ pane_mprime.send_keys('mprime -t')
+ #sleep(MPRIME_LIMIT*60)
+ sleep(15)
+
+ # Done
+ run_program(['apple-fans', 'auto'])
+ window.kill_window()
+
+def run_tests(tests):
+ # Enable selected tests
+ for t in ['Prime95', 'SMART', 'badblocks']:
+ TESTS[t]['Enabled'] = t in tests
+ TESTS['SMART']['Quick'] = 'Quick' in tests
+
+ # Initialize
+ if TESTS['SMART']['Enabled'] or TESTS['badblocks']['Enabled']:
+ scan_disks()
+ update_progress()
+
+ # Run
+ if TESTS['Prime95']['Enabled']:
+ run_mprime()
+ if TESTS['SMART']['Enabled']:
+ run_smart()
+ if TESTS['badblocks']['Enabled']:
+ run_badblocks()
+
+def scan_disks():
+ clear_screen()
+
+ # Get eligible disk list
+ cmd = 'lsblk -J -o HOTPLUG,NAME,TRAN,TYPE'.split()
+ result = run_program(cmd)
+ json_data = json.loads(result.stdout.decode())
+ devs = json_data.get('blockdevices', [])
+ devs = {d['name']: {'lsblk': d, 'Status': 'Pending'} for d in devs
+ if d['type'] == 'disk' and d['hotplug'] == '0'}
+
+ for dev, data in devs.items():
+ # Get SMART attributes
+ 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'] = {}
+
+ # Set "Health OK" value
+ ## NOTE: OK == we'll check the SMART/NVMe attributes, else req override
+ wanted_smart_list = [
+ 'ata_smart_attributes',
+ 'ata_smart_data',
+ 'smart_status',
+ ]
+ if data['lsblk']['tran'] == 'nvme':
+ crit_warn = data['nvme-cli'].get('critical_warning', 1)
+ data['Health OK'] = True if crit_warn == 0 else False
+ elif set(wanted_smart_list).issubset(data['smartctl'].keys()):
+ data['Health OK'] = data.get(
+ 'smart_status', {}).get('passed', False)
+ else:
+ data['Health OK'] = False
+
+ # Ask for manual overrides if necessary
+ if not data['Health OK'] and TESTS['badblocks']['Enabled']:
+ #TODO Print disk "report" for reference
+ print_warning("WARNING: Health can't be confirmed for: {}".format(
+ '/dev/{}'.format(dev)))
+ if ask('Run badblocks for this device anyway?'):
+ data['OVERRIDE'] = True
+
+ TESTS['SMART']['Devices'] = devs
+ TESTS['badblocks']['Devices'] = devs
+
+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('{BLUE}Prime95{s_color}{status:>8}{CLEAR}'.format(
+ s_color = get_status_color(TESTS['Prime95']['Status']),
+ status = TESTS['Prime95']['Status'],
+ **COLORS))
+ if TESTS['SMART']['Enabled']:
+ output.append('{BLUE}SMART{CLEAR}'.format(**COLORS))
+ for dev, data in sorted(TESTS['SMART']['Devices'].items()):
+ output.append('{dev}{s_color}{status:>{pad}}{CLEAR}'.format(
+ dev = dev,
+ pad = 16-len(dev),
+ s_color = get_status_color(status),
+ status = data['Status'],
+ **COLORS))
+ if TESTS['badblocks']['Enabled']:
+ output.append('{BLUE}badblocks{CLEAR}'.format(**COLORS))
+ for dev, data in sorted(TESTS['badblocks']['Devices'].items()):
+ output.append('{dev}{s_color}{status:>{pad}}{CLEAR}'.format(
+ dev = dev,
+ pad = 16-len(dev),
+ s_color = get_status_color(data['Status']),
+ status = data['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/hw-diags-menu b/.bin/Scripts/hw-diags-menu
index 8fcd5c5c..cbd4b3b2 100755
--- a/.bin/Scripts/hw-diags-menu
+++ b/.bin/Scripts/hw-diags-menu
@@ -2,192 +2,15 @@
#
## Wizard Kit: HW Diagnostics - Menu
-import libtmux
-import json
import os
import sys
# Init
os.chdir(os.path.dirname(os.path.realpath(__file__)))
sys.path.append(os.getcwd())
-from functions.common import *
+from functions.hw_diags import *
init_global_vars()
-# STATIC VARIABLES
-sleep(1)
-TMUX = libtmux.Server()
-SESSION = TMUX.find_where({'session_name': 'hw-diags'})
-WINDOW = SESSION.windows[0] # Should be a safe assumption
-PANE = WINDOW.panes[0] # Should be a safe assumption
-PROGRESS_FILE = '{}/progress.out'.format(global_vars['LogDir'])
-TESTS = {
- 'Prime95': {
- 'Enabled': False,
- 'Status': 'Pending',
- },
- 'SMART': {
- 'Enabled': False,
- 'Quick': False,
- },
- 'badblocks': {
- 'Enabled': False,
- },
- }
-
-def get_status_color(s):
- color = COLORS['CLEAR']
- if s in ['NS', 'Unknown']:
- color = COLORS['RED']
- elif s in ['Working', 'Skipped']:
- color = COLORS['YELLOW']
- elif s in ['CS']:
- color = COLORS['GREEN']
- return color
-
-def menu_diags():
- diag_modes = [
- {'Name': 'All tests', 'Tests': ['Prime95', 'SMART', 'badblocks']},
- {'Name': 'Prime95', 'Tests': ['Prime95']},
- {'Name': 'SMART & badblocks', 'Tests': ['SMART', 'badblocks']},
- {'Name': 'SMART', 'Tests': ['SMART']},
- {'Name': 'badblocks', 'Tests': ['badblocks']},
- {'Name': 'Quick drive test', 'Tests': ['Quick', '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},
- ]
-
- # Show menu
- while True:
- selection = menu_select(
- title = 'Hardware Diagnostics: Menu',
- main_entries = diag_modes,
- action_entries = actions,
- spacer = '─────────────────────────')
- if selection.isnumeric():
- run_tests(diag_modes[int(selection)-1]['Tests'])
- elif selection == 'A':
- run_program(['hw-diags-audio'], check=False, pipe=False)
- sleep(1)
- elif selection == 'N':
- run_program(['hw-diags-network'], check=False, pipe=False)
- sleep(1)
- 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():
- pass
-
-def run_mprime():
- # Set Window layout
- window = SESSION.new_window()
- pane_sensors = window.panes[0]
- pane_mprime = window.split_window(attach=False)
- pane_mprime.set_height(10)
- pane_progress = window.split_window(attach=False, vertical=False)
- pane_progress.set_width(16)
-
- # Start test
- run_program(['apple-fans', 'max'])
- pane_sensors.send_keys('watch -c -n1 -t hw-sensors')
- pane_progress.send_keys('watch -c -n1 -t cat "{}"'.format(PROGRESS_FILE))
- pane_mprime.send_keys('mprime -t')
- #sleep(MPRIME_LIMIT*60)
- sleep(15)
-
- # Done
- run_program(['apple-fans', 'auto'])
- window.kill_window()
-
-def run_smart():
- pass
-
-def run_tests(tests):
- for t in ['Prime95', 'SMART', 'badblocks']:
- TESTS[t]['Enabled'] = t in tests
- TESTS['SMART']['Quick'] = 'Quick' in tests
-
- # Get (disk) device list
- if TESTS['SMART']['Enabled'] or TESTS['badblocks']['Enabled']:
- cmd = 'lsblk -J -o NAME,TYPE'.split()
- result = run_program(cmd)
- json_data = json.loads(result.stdout.decode())
- devs = json_data.get('blockdevices', [])
- devs = {d['name']: 'Pending' for d in devs if d['type'] == 'disk'}
- TESTS['SMART']['Devices'] = devs
- TESTS['badblocks']['Devices'] = devs
-
- # Initialize progress display
- update_progress()
-
- # Run
- if TESTS['Prime95']['Enabled']:
- run_mprime()
- if TESTS['SMART']['Enabled']:
- run_smart()
- if TESTS['badblocks']['Enabled']:
- run_badblocks()
-
-def update_progress(color=True):
- output = []
- if color:
- output.append('{BLUE}HW Diagnostics{CLEAR}'.format(**COLORS))
- output.append('───────────────')
- if TESTS['Prime95']['Enabled']:
- 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['SMART']['Enabled']:
- output.append('{BLUE}SMART{CLEAR}'.format(**COLORS))
- for dev, status in sorted(TESTS['SMART']['Devices'].items()):
- output.append('{dev}{s_color}{status:>{pad}}{CLEAR}'.format(
- dev = dev,
- pad = 16-len(dev),
- s_color = get_status_color(status),
- status = status,
- **COLORS))
- if TESTS['badblocks']['Enabled']:
- output.append('{BLUE}badblocks{CLEAR}'.format(**COLORS))
- for dev, status in sorted(TESTS['badblocks']['Devices'].items()):
- output.append('{dev}{s_color}{status:>{pad}}{CLEAR}'.format(
- dev = dev,
- pad = 16-len(dev),
- s_color = get_status_color(status),
- status = status,
- **COLORS))
- else:
- output.append('HW Diagnostics')
- output.append('───────────────')
- if TESTS['Prime95']['Enabled']:
- output.append('Prime95{:>8}'.format(TESTS['Prime95']['Status']))
- if TESTS['SMART']['Enabled']:
- output.append('SMART')
- for dev, status in sorted(TESTS['SMART']['Devices'].items()):
- output.append('{}{:>{}}'.format(dev, 16-len(dev), status))
- if TESTS['badblocks']['Enabled']:
- output.append('badblocks')
- for dev, status in sorted(TESTS['badblocks']['Devices'].items()):
- output.append('{}{:>{}}'.format(dev, 16-len(dev), status))
-
- # Add line-endings
- output = ['{}\n'.format(line) for line in output]
- print(output)
- pause()
-
- with open(PROGRESS_FILE, 'w') as f:
- f.writelines(output)
-
if __name__ == '__main__':
try:
# Prep
diff --git a/.linux_items/packages/aur b/.linux_items/packages/aur
index ad5acfaf..611490ef 100644
--- a/.linux_items/packages/aur
+++ b/.linux_items/packages/aur
@@ -5,9 +5,12 @@ hfsprogs
i3-gaps
i3lock-fancy-git
mprime-bin
+nvme-cli
openbox-patched
papirus-icon-theme
pasystray
+python-libtmux
+smartmontools-svn
testdisk-wip
ttf-font-awesome
wd719x-firmware
diff --git a/.linux_items/packages/live b/.linux_items/packages/live
index f571a768..75b20e0a 100644
--- a/.linux_items/packages/live
+++ b/.linux_items/packages/live
@@ -46,6 +46,7 @@ mupdf
ncdu
network-manager-applet
networkmanager
+nvme-cli
oblogout
openbox-patched
p7zip
@@ -55,6 +56,7 @@ pavucontrol
progsreiserfs
pulseaudio
python
+python-libtmux
python-psutil
python-requests
qemu-guest-agent
@@ -63,6 +65,7 @@ rfkill
rng-tools
rofi
rxvt-unicode
+smartmontools-svn
speedtest-cli
spice-vdagent
terminus-font
From 59a449e7e5cae940a63cb7fcba8461a37792e96f Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Sun, 24 Dec 2017 13:08:13 -0700
Subject: [PATCH 24/42] Cleanup
* Renamed 'Health OK' to 'Quick Health OK'
* Better implies that we're not done testing
* Renamed SMART sections to NVMe/SMART
* Dropping SMART short-tests for NVMe drives
---
.bin/Scripts/functions/hw_diags.py | 77 ++++++++++++++++++------------
1 file changed, 47 insertions(+), 30 deletions(-)
mode change 100755 => 100644 .bin/Scripts/functions/hw_diags.py
diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py
old mode 100755
new mode 100644
index 62725f75..d1ac1b5b
--- a/.bin/Scripts/functions/hw_diags.py
+++ b/.bin/Scripts/functions/hw_diags.py
@@ -15,7 +15,7 @@ TESTS = {
'Enabled': False,
'Status': 'Pending',
},
- 'SMART': {
+ 'NVMe/SMART': {
'Enabled': False,
'Quick': False,
},
@@ -45,12 +45,18 @@ def get_status_color(s):
def menu_diags():
diag_modes = [
- {'Name': 'All tests', 'Tests': ['Prime95', 'SMART', 'badblocks']},
- {'Name': 'Prime95', 'Tests': ['Prime95']},
- {'Name': 'SMART & badblocks', 'Tests': ['SMART', 'badblocks']},
- {'Name': 'SMART', 'Tests': ['SMART']},
- {'Name': 'badblocks', 'Tests': ['badblocks']},
- {'Name': 'Quick drive test', 'Tests': ['Quick', 'SMART']},
+ {'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'},
@@ -95,14 +101,14 @@ def run_mprime():
pane_mprime.set_height(10)
pane_progress = window.split_window(attach=False, vertical=False)
pane_progress.set_width(16)
-
+
# Start test
run_program(['apple-fans', 'max'])
pane_sensors.send_keys('watch -c -n1 -t hw-sensors')
pane_progress.send_keys('watch -c -n1 -t cat "{}"'.format(TESTS['Progress Out']))
+ pane_mprime.send_keys('cd "{}"'.format(global_vars['LogDir']))
pane_mprime.send_keys('mprime -t')
- #sleep(MPRIME_LIMIT*60)
- sleep(15)
+ sleep(MPRIME_LIMIT*60)
# Done
run_program(['apple-fans', 'auto'])
@@ -122,8 +128,7 @@ def run_smart():
pane_sensors.send_keys('watch -c -n1 -t hw-sensors')
pane_progress.send_keys('watch -c -n1 -t cat "{}"'.format(TESTS['Progress Out']))
pane_mprime.send_keys('mprime -t')
- #sleep(MPRIME_LIMIT*60)
- sleep(15)
+ sleep(MPRIME_LIMIT*60)
# Done
run_program(['apple-fans', 'auto'])
@@ -131,29 +136,28 @@ def run_smart():
def run_tests(tests):
# Enable selected tests
- for t in ['Prime95', 'SMART', 'badblocks']:
+ for t in ['Prime95', 'NVMe/SMART', 'badblocks']:
TESTS[t]['Enabled'] = t in tests
- TESTS['SMART']['Quick'] = 'Quick' in tests
+ TESTS['NVMe/SMART']['Quick'] = 'Quick' in tests
# Initialize
- if TESTS['SMART']['Enabled'] or TESTS['badblocks']['Enabled']:
+ if TESTS['NVMe/SMART']['Enabled'] or TESTS['badblocks']['Enabled']:
scan_disks()
update_progress()
# Run
if TESTS['Prime95']['Enabled']:
run_mprime()
- if TESTS['SMART']['Enabled']:
+ if TESTS['NVMe/SMART']['Enabled']:
run_smart()
if TESTS['badblocks']['Enabled']:
run_badblocks()
def scan_disks():
clear_screen()
-
+
# Get eligible disk list
- cmd = 'lsblk -J -o HOTPLUG,NAME,TRAN,TYPE'.split()
- result = run_program(cmd)
+ result = run_program(['lsblk', '-J', '-O'])
json_data = json.loads(result.stdout.decode())
devs = json_data.get('blockdevices', [])
devs = {d['name']: {'lsblk': d, 'Status': 'Pending'} for d in devs
@@ -172,34 +176,47 @@ def scan_disks():
except Exception:
# Let other sections deal with the missing data
data['nvme-cli'] = {}
+ data['NVMe Disk'] = True
- # Set "Health OK" value
- ## NOTE: OK == we'll check the SMART/NVMe attributes, else req override
+ # 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['lsblk']['tran'] == 'nvme':
+ if data.get('NVMe Disk', False):
crit_warn = data['nvme-cli'].get('critical_warning', 1)
- data['Health OK'] = True if crit_warn == 0 else False
+ data['Quick Health OK'] = True if crit_warn == 0 else False
elif set(wanted_smart_list).issubset(data['smartctl'].keys()):
- data['Health OK'] = data.get(
+ data['Quick Health OK'] = data.get(
'smart_status', {}).get('passed', False)
+ data['SMART Support'] = True
else:
- data['Health OK'] = False
+ data['Quick Health OK'] = False
+ data['SMART Support'] = False
# Ask for manual overrides if necessary
- if not data['Health OK'] and TESTS['badblocks']['Enabled']:
+ if not data['Quick Health OK'] and TESTS['badblocks']['Enabled']:
#TODO Print disk "report" for reference
print_warning("WARNING: Health can't be confirmed for: {}".format(
'/dev/{}'.format(dev)))
if ask('Run badblocks for this device anyway?'):
data['OVERRIDE'] = True
- TESTS['SMART']['Devices'] = devs
+ TESTS['NVMe/SMART']['Devices'] = devs
TESTS['badblocks']['Devices'] = devs
+def show_disk_details(dev):
+ # Device description
+
+ # Warnings
+
+ # Attributes
+
+ # Quick Health OK
+ pass
+
def update_progress():
if 'Progress Out' not in TESTS:
TESTS['Progress Out'] = '{}/progress.out'.format(global_vars['LogDir'])
@@ -211,9 +228,9 @@ def update_progress():
s_color = get_status_color(TESTS['Prime95']['Status']),
status = TESTS['Prime95']['Status'],
**COLORS))
- if TESTS['SMART']['Enabled']:
- output.append('{BLUE}SMART{CLEAR}'.format(**COLORS))
- for dev, data in sorted(TESTS['SMART']['Devices'].items()):
+ if TESTS['NVMe/SMART']['Enabled']:
+ output.append('{BLUE}NVMe / SMART{CLEAR}'.format(**COLORS))
+ for dev, data in sorted(TESTS['NVMe/SMART']['Devices'].items()):
output.append('{dev}{s_color}{status:>{pad}}{CLEAR}'.format(
dev = dev,
pad = 16-len(dev),
From 6f456f5c4775397f340a5eb67a4aedf7f9d8b741 Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Sun, 24 Dec 2017 15:33:39 -0700
Subject: [PATCH 25/42] Added show_disk_details()
---
.bin/Scripts/functions/hw_diags.py | 101 +++++++++++++++++++++++++++--
1 file changed, 96 insertions(+), 5 deletions(-)
diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py
index d1ac1b5b..df704578 100644
--- a/.bin/Scripts/functions/hw_diags.py
+++ b/.bin/Scripts/functions/hw_diags.py
@@ -6,10 +6,31 @@ import json
from functions.common import *
# STATIC VARIABLES
+## tmux
TMUX = libtmux.Server()
SESSION = TMUX.find_where({'session_name': 'hw-diags'})
WINDOW = SESSION.windows[0] # Should be a safe assumption
PANE = WINDOW.panes[0] # Should be a safe assumption
+## other
+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,
@@ -72,7 +93,7 @@ def menu_diags():
title = 'Hardware Diagnostics: Menu',
main_entries = diag_modes,
action_entries = actions,
- spacer = '─────────────────────────')
+ spacer = '──────────────────────────')
if selection.isnumeric():
run_tests(diag_modes[int(selection)-1]['Tests'])
elif selection == 'A':
@@ -189,8 +210,9 @@ def scan_disks():
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['Quick Health OK'] = data.get(
- 'smart_status', {}).get('passed', False)
+ 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
@@ -198,7 +220,7 @@ def scan_disks():
# Ask for manual overrides if necessary
if not data['Quick Health OK'] and TESTS['badblocks']['Enabled']:
- #TODO Print disk "report" for reference
+ show_disk_details(data)
print_warning("WARNING: Health can't be confirmed for: {}".format(
'/dev/{}'.format(dev)))
if ask('Run badblocks for this device anyway?'):
@@ -209,13 +231,82 @@ def scan_disks():
def show_disk_details(dev):
# Device description
+ print_info('Device: /dev/{}'.format(dev['lsblk']['name']))
+ for key in ['model', 'size', 'serial']:
+ print_standard(' {:8}{}'.format(key, dev['lsblk'].get(key, 'Unknown')))
+ if dev['lsblk'].get('tran', 'Unknown') == 'nvme':
+ print_standard(' {:8}{}'.format('type', 'NVMe'))
+ else:
+ print_standard(' {:8}{}'.format(
+ 'type',
+ dev['lsblk'].get('tran', 'Unknown').upper()))
# 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
+ print_info('Attributes:')
+ if dev.get('NVMe Disk', False):
+ 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['NVMe/SMART']['Status'] = '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)
+ else:
+ # SMART 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']),
+ 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['NVMe/SMART']['Status'] = '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)
# Quick Health OK
- pass
+ print_standard('Quick health assessment: ', end='', flush=True)
+ if dev['Quick Health OK']:
+ print_success('Passed.\n', timestamp=False)
+ else:
+ print_error('Failed.\n', timestamp=False)
def update_progress():
if 'Progress Out' not in TESTS:
From 57b1d246c2b6796809f9beccdcbdc950eba4af28 Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Sun, 24 Dec 2017 17:13:48 -0700
Subject: [PATCH 26/42] Going to drop libtmux and use tmux directly
---
.bin/Scripts/functions/hw_diags.py | 50 ++++++++++++++++--------------
1 file changed, 26 insertions(+), 24 deletions(-)
diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py
index df704578..ebaa2bd0 100644
--- a/.bin/Scripts/functions/hw_diags.py
+++ b/.bin/Scripts/functions/hw_diags.py
@@ -118,16 +118,17 @@ def run_mprime():
# Set Window layout
window = SESSION.new_window()
pane_sensors = window.panes[0]
- pane_mprime = window.split_window(attach=False)
- pane_mprime.set_height(10)
+ pane_smart = window.split_window(attach=False)
+ pane_smart.set_height(10)
pane_progress = window.split_window(attach=False, vertical=False)
- pane_progress.set_width(16)
-
+ pane_progress.set_width(15)
+ pane_progress.clear()
+ pane_sensors.send_keys('watch -c -n1 -t hw-sensors')
+ #pane_progress.send_keys('watch -c -n1 -t cat "{}"'.format(TESTS['Progress Out']))
+ pane_progress.send_keys('tail -f "{}"'.format(TESTS['Progress Out']))
+
# Start test
run_program(['apple-fans', 'max'])
- pane_sensors.send_keys('watch -c -n1 -t hw-sensors')
- pane_progress.send_keys('watch -c -n1 -t cat "{}"'.format(TESTS['Progress Out']))
- pane_mprime.send_keys('cd "{}"'.format(global_vars['LogDir']))
pane_mprime.send_keys('mprime -t')
sleep(MPRIME_LIMIT*60)
@@ -137,23 +138,19 @@ def run_mprime():
def run_smart():
# Set Window layout
- window = SESSION.new_window()
- pane_sensors = window.panes[0]
- pane_smart = window.split_window(attach=False)
- pane_smart.set_height(10)
- pane_progress = window.split_window(attach=False, vertical=False)
- pane_progress.set_width(16)
-
+ pane_worker = WINDOW.split_window(attach=False)
+ pane_worker.set_height(10)
+ pane_progress = WINDOW.split_window(attach=False, vertical=False)
+ pane_progress.set_width(15)
+ pane_progress.clear()
+ #pane_progress.send_keys('watch -c -n1 -t cat "{}"'.format(TESTS['Progress Out']))
+ pane_progress.send_keys('tail -f "{}"'.format(TESTS['Progress Out']))
+
# Start test
- run_program(['apple-fans', 'max'])
- pane_sensors.send_keys('watch -c -n1 -t hw-sensors')
- pane_progress.send_keys('watch -c -n1 -t cat "{}"'.format(TESTS['Progress Out']))
- pane_mprime.send_keys('mprime -t')
- sleep(MPRIME_LIMIT*60)
+ sleep(120)
# Done
- run_program(['apple-fans', 'auto'])
- window.kill_window()
+ run_program(['tmux kill-pane -a'.split()], check=False)
def run_tests(tests):
# Enable selected tests
@@ -315,25 +312,30 @@ def update_progress():
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, data in sorted(TESTS['NVMe/SMART']['Devices'].items()):
output.append('{dev}{s_color}{status:>{pad}}{CLEAR}'.format(
dev = dev,
- pad = 16-len(dev),
- s_color = get_status_color(status),
+ pad = 15-len(dev),
+ s_color = get_status_color(data['Status']),
status = data['Status'],
**COLORS))
if TESTS['badblocks']['Enabled']:
+ output.append('')
output.append('{BLUE}badblocks{CLEAR}'.format(**COLORS))
for dev, data in sorted(TESTS['badblocks']['Devices'].items()):
output.append('{dev}{s_color}{status:>{pad}}{CLEAR}'.format(
dev = dev,
- pad = 16-len(dev),
+ pad = 15-len(dev),
s_color = get_status_color(data['Status']),
status = data['Status'],
**COLORS))
From 74ba8fb7582eabb12fd3736456dfec4252bfc1bd Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Sun, 24 Dec 2017 18:46:02 -0700
Subject: [PATCH 27/42] Added hw-diags-prime95 and still removing libtmux
---
.bin/Scripts/functions/hw_diags.py | 61 +++++++++++--------
.bin/Scripts/{linux-old => }/hw-diags-prime95 | 0
2 files changed, 37 insertions(+), 24 deletions(-)
rename .bin/Scripts/{linux-old => }/hw-diags-prime95 (100%)
diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py
index ebaa2bd0..7260c466 100644
--- a/.bin/Scripts/functions/hw_diags.py
+++ b/.bin/Scripts/functions/hw_diags.py
@@ -1,17 +1,10 @@
# Wizard Kit: Functions - HW Diagnostics
-import libtmux
import json
from functions.common import *
# STATIC VARIABLES
-## tmux
-TMUX = libtmux.Server()
-SESSION = TMUX.find_where({'session_name': 'hw-diags'})
-WINDOW = SESSION.windows[0] # Should be a safe assumption
-PANE = WINDOW.panes[0] # Should be a safe assumption
-## other
ATTRIBUTES = {
'NVMe': {
'critical_warning': {'Error': 1},
@@ -58,7 +51,7 @@ def get_status_color(s):
color = COLORS['CLEAR']
if s in ['NS', 'Unknown']:
color = COLORS['RED']
- elif s in ['Working', 'Skipped']:
+ elif s in ['Aborted', 'OVERRIDE', 'Working', 'Skipped']:
color = COLORS['YELLOW']
elif s in ['CS']:
color = COLORS['GREEN']
@@ -115,26 +108,46 @@ def run_badblocks():
pass
def run_mprime():
- # Set Window layout
- window = SESSION.new_window()
- pane_sensors = window.panes[0]
- pane_smart = window.split_window(attach=False)
- pane_smart.set_height(10)
- pane_progress = window.split_window(attach=False, vertical=False)
- pane_progress.set_width(15)
- pane_progress.clear()
- pane_sensors.send_keys('watch -c -n1 -t hw-sensors')
- #pane_progress.send_keys('watch -c -n1 -t cat "{}"'.format(TESTS['Progress Out']))
- pane_progress.send_keys('tail -f "{}"'.format(TESTS['Progress Out']))
+ aborted = False
+ clear_screen()
+ 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'])
- pane_mprime.send_keys('mprime -t')
- sleep(MPRIME_LIMIT*60)
+ 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
+
+ # Stop test
+ run_program('killall -s INT mprime'.split(), check=False)
+ run_program(['apple-fans', 'auto'])
+
+ # Update status
+ if aborted:
+ TESTS['Prime95']['Status'] = 'Aborted'
+ print_warning('\nAborted.')
+ sleep(5)
+ update_progress()
+ pause('Press Enter to return to menu... ')
+ else:
+ TESTS['Prime95']['Status'] = 'CS'
+ update_progress()
# Done
- run_program(['apple-fans', 'auto'])
- window.kill_window()
+ run_program('tmux kill-pane -a'.split())
def run_smart():
# Set Window layout
@@ -144,7 +157,7 @@ def run_smart():
pane_progress.set_width(15)
pane_progress.clear()
#pane_progress.send_keys('watch -c -n1 -t cat "{}"'.format(TESTS['Progress Out']))
- pane_progress.send_keys('tail -f "{}"'.format(TESTS['Progress Out']))
+ pane_progress.send_keys(''.format(TESTS['Progress Out']))
# Start test
sleep(120)
diff --git a/.bin/Scripts/linux-old/hw-diags-prime95 b/.bin/Scripts/hw-diags-prime95
similarity index 100%
rename from .bin/Scripts/linux-old/hw-diags-prime95
rename to .bin/Scripts/hw-diags-prime95
From 03d76466858fad6dd97cf2ce9ed7481f8adc211a Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Tue, 26 Dec 2017 13:20:25 -0700
Subject: [PATCH 28/42] Enabled logging for hw-diags
---
.bin/Scripts/functions/common.py | 4 ++--
.bin/Scripts/functions/hw_diags.py | 21 +++++++++++++++++++++
2 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py
index 4b9727d7..437591cb 100644
--- a/.bin/Scripts/functions/common.py
+++ b/.bin/Scripts/functions/common.py
@@ -132,7 +132,7 @@ def exit_script(return_value=0):
# Open Log (if it exists)
log = global_vars.get('LogFile', '')
- if log and os.path.exists(log):
+ if log and os.path.exists(log) and psutil.WINDOWS:
try:
extract_item('NotepadPlusPlus', silent=True)
popen_program(
@@ -359,7 +359,7 @@ def print_warning(*args, **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:
+ 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(
diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py
index 7260c466..f0a43ecd 100644
--- a/.bin/Scripts/functions/hw_diags.py
+++ b/.bin/Scripts/functions/hw_diags.py
@@ -88,6 +88,15 @@ def menu_diags():
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)
@@ -110,6 +119,7 @@ def run_badblocks():
def run_mprime():
aborted = False
clear_screen()
+ print_log('\nStart Prime95 test')
TESTS['Prime95']['Status'] = 'Working'
update_progress()
@@ -135,6 +145,15 @@ def run_mprime():
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']))
+
# Update status
if aborted:
TESTS['Prime95']['Status'] = 'Aborted'
@@ -166,6 +185,8 @@ def run_smart():
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
From c1fe3d853889f009d53e6a8efc07a4d436dd7a50 Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Tue, 26 Dec 2017 14:35:47 -0700
Subject: [PATCH 29/42] Added --nocolor option to hw-sensors
* Going to use it to export the "final" temps before killing Prime95
---
.bin/Scripts/hw-sensors | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/.bin/Scripts/hw-sensors b/.bin/Scripts/hw-sensors
index 07c98460..da5427d0 100755
--- a/.bin/Scripts/hw-sensors
+++ b/.bin/Scripts/hw-sensors
@@ -49,10 +49,10 @@ def color_temp(temp):
color = COLORS['BLUE']
else:
color = COLORS['CLEAR']
- return '{color}{prefix}{temp:2}°C{CLEAR}'.format(
+ return '{color}{prefix}{temp:2.0f}°C{CLEAR}'.format(
color = color,
prefix = '+' if temp>0 else '-',
- temp = int(temp),
+ temp = temp,
**COLORS)
def get_feature_string(chip, feature):
@@ -74,7 +74,17 @@ def get_feature_string(chip, feature):
if 'alarm' in name:
# Skip
continue
- data[name] = color_temp(val)
+ 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:
@@ -101,7 +111,6 @@ def join_columns(column1, column2, width=55):
if __name__ == '__main__':
try:
# Prep
- clear_screen()
sensors.init()
# Get sensor data
From 8ff33547c45a3884e1b308a89eb861eea075edcb Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Tue, 26 Dec 2017 15:16:15 -0700
Subject: [PATCH 30/42] Save temps just before stopping Prime95
---
.bin/Scripts/functions/hw_diags.py | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py
index f0a43ecd..6cb50bc2 100644
--- a/.bin/Scripts/functions/hw_diags.py
+++ b/.bin/Scripts/functions/hw_diags.py
@@ -141,6 +141,20 @@ def run_mprime():
# 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'])
@@ -158,7 +172,6 @@ def run_mprime():
if aborted:
TESTS['Prime95']['Status'] = 'Aborted'
print_warning('\nAborted.')
- sleep(5)
update_progress()
pause('Press Enter to return to menu... ')
else:
From a6917fc1296c48c8cdc5a179e39ad12355f0b086 Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Tue, 26 Dec 2017 15:57:36 -0700
Subject: [PATCH 31/42] run_mprime() finished
* Results now determined from log files
---
.bin/Scripts/functions/hw_diags.py | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py
index 6cb50bc2..9ca2e526 100644
--- a/.bin/Scripts/functions/hw_diags.py
+++ b/.bin/Scripts/functions/hw_diags.py
@@ -168,6 +168,20 @@ def run_mprime():
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:
+ r = re.search(r'(error|fail)', f.read())
+ TESTS['Prime95']['NS'] = bool(r)
+ log = '{}/prime.log'.format(global_vars['LogDir'])
+ if os.path.exists(log):
+ with open(log, 'r') as f:
+ r = re.search(r'completed.*0 errors, 0 warnings', f.read())
+ TESTS['Prime95']['CS'] = bool(r)
+
# Update status
if aborted:
TESTS['Prime95']['Status'] = 'Aborted'
@@ -175,7 +189,12 @@ def run_mprime():
update_progress()
pause('Press Enter to return to menu... ')
else:
- TESTS['Prime95']['Status'] = 'CS'
+ if TESTS['Prime95']['NS']:
+ TESTS['Prime95']['Status'] = 'NS'
+ elif TESTS['Prime95']['CS']:
+ TESTS['Prime95']['Status'] = 'CS'
+ else:
+ TESTS['Prime95']['Status'] = 'Unknown'
update_progress()
# Done
From 579a747878bde5157859a4c1a58c71d24f8314fb Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Tue, 26 Dec 2017 16:24:41 -0700
Subject: [PATCH 32/42] Started work on results screen
---
.bin/Scripts/functions/hw_diags.py | 65 ++++++++++++++++++++++++++----
1 file changed, 57 insertions(+), 8 deletions(-)
diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py
index 9ca2e526..07b677d0 100644
--- a/.bin/Scripts/functions/hw_diags.py
+++ b/.bin/Scripts/functions/hw_diags.py
@@ -174,12 +174,16 @@ def run_mprime():
log = '{}/results.txt'.format(global_vars['LogDir'])
if os.path.exists(log):
with open(log, 'r') as f:
- r = re.search(r'(error|fail)', f.read())
+ 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:
- r = re.search(r'completed.*0 errors, 0 warnings', f.read())
+ 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
@@ -187,7 +191,9 @@ def run_mprime():
TESTS['Prime95']['Status'] = 'Aborted'
print_warning('\nAborted.')
update_progress()
- pause('Press Enter to return to menu... ')
+ if TESTS['NVMe/SMART']['Enabled'] or TESTS['badblocks']['Enabled']:
+ if not ask('Proceed to next test?'):
+ raise GenericError
else:
if TESTS['Prime95']['NS']:
TESTS['Prime95']['Status'] = 'NS'
@@ -230,12 +236,20 @@ def run_tests(tests):
update_progress()
# Run
+ mprime_aborted = False
if TESTS['Prime95']['Enabled']:
- run_mprime()
- if TESTS['NVMe/SMART']['Enabled']:
- run_smart()
- if TESTS['badblocks']['Enabled']:
- run_badblocks()
+ try:
+ run_mprime()
+ except GenericError:
+ mprime_aborted = True
+ if not mprime_aborted:
+ if TESTS['NVMe/SMART']['Enabled']:
+ run_smart()
+ if TESTS['badblocks']['Enabled']:
+ run_badblocks()
+
+ # Show results
+ show_results()
def scan_disks():
clear_screen()
@@ -371,6 +385,41 @@ def show_disk_details(dev):
else:
print_error('Failed.\n', timestamp=False)
+def show_results():
+ clear_screen()
+ print_standard('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
+ print_info('\nPrime95:')
+ for log, regex in [
+ ['results.txt', r'(error|fail)'],
+ ['prime.log', r'completed.*0 errors, 0 warnings']]:
+ if log in TESTS['Prime95']:
+ #print_standard(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))
+
+ # NVMe/SMART
+
+ # badblocks
+
+ # 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'])
From 24e72f2f352ac58ae0846fdab825fe016f18c4f5 Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Wed, 27 Dec 2017 01:42:04 -0700
Subject: [PATCH 33/42] SMART section finished
* The script waits for the self-test for polling-time+5min
* Unless it detects completion after 60 seconds
* Fixed missing linebreaks in progress panes
* BREAKING: TESTS data structure reworked to support per-dev status
---
.bin/Scripts/functions/hw_diags.py | 208 +++++++++++++++++++++--------
1 file changed, 152 insertions(+), 56 deletions(-)
diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py
index 07b677d0..092100ff 100644
--- a/.bin/Scripts/functions/hw_diags.py
+++ b/.bin/Scripts/functions/hw_diags.py
@@ -32,9 +32,11 @@ TESTS = {
'NVMe/SMART': {
'Enabled': False,
'Quick': False,
+ 'Status': {},
},
'badblocks': {
'Enabled': False,
+ 'Status': {},
},
}
@@ -49,9 +51,9 @@ def get_smart_details(dev):
def get_status_color(s):
color = COLORS['CLEAR']
- if s in ['NS', 'Unknown']:
+ if s in ['Denied', 'NS', 'OVERRIDE', 'Unknown']:
color = COLORS['RED']
- elif s in ['Aborted', 'OVERRIDE', 'Working', 'Skipped']:
+ elif s in ['Aborted', 'Working', 'Skipped']:
color = COLORS['YELLOW']
elif s in ['CS']:
color = COLORS['GREEN']
@@ -193,6 +195,7 @@ def run_mprime():
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']:
@@ -207,20 +210,98 @@ def run_mprime():
run_program('tmux kill-pane -a'.split())
def run_smart():
- # Set Window layout
- pane_worker = WINDOW.split_window(attach=False)
- pane_worker.set_height(10)
- pane_progress = WINDOW.split_window(attach=False, vertical=False)
- pane_progress.set_width(15)
- pane_progress.clear()
- #pane_progress.send_keys('watch -c -n1 -t cat "{}"'.format(TESTS['Progress Out']))
- pane_progress.send_keys(''.format(TESTS['Progress Out']))
+ aborted = False
+ clear_screen()
+ print_log('\nStart NVMe/SMART test(s)\n')
+ progress_file = '{}/selftest_progress.out'.format(global_vars['LogDir'])
+ update_progress()
- # Start test
- sleep(120)
+ # 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)
+ run_program('tmux kill-pane -a'.split(), check=False)
def run_tests(tests):
print_log('Starting Hardware Diagnostics')
@@ -257,12 +338,18 @@ def scan_disks():
# Get eligible disk list
result = run_program(['lsblk', '-J', '-O'])
json_data = json.loads(result.stdout.decode())
- devs = json_data.get('blockdevices', [])
- devs = {d['name']: {'lsblk': d, 'Status': 'Pending'} for d in devs
- if d['type'] == 'disk' and d['hotplug'] == '0'}
+ 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
@@ -300,13 +387,19 @@ def scan_disks():
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?'):
- data['OVERRIDE'] = True
+ TESTS['NVMe/SMART']['Status'][dev_name] = 'OVERRIDE'
+ else:
+ 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']))
for key in ['model', 'size', 'serial']:
@@ -330,8 +423,8 @@ def show_disk_details(dev):
print_error('ERROR: SMART overall-health assessment result: FAILED')
# Attributes
- print_info('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(
@@ -343,14 +436,16 @@ def show_disk_details(dev):
raw_num >= threshold.get('Error', -1)):
print_error(raw_str, timestamp=False)
if not threshold.get('Ignore', False):
- dev['NVMe/SMART']['Status'] = 'NS'
+ 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)
- else:
+ 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}
@@ -371,20 +466,14 @@ def show_disk_details(dev):
raw_num >= threshold.get('Error', -1)):
print_error(raw_str, timestamp=False)
if not threshold.get('Ignore', False):
- dev['NVMe/SMART']['Status'] = 'NS'
+ dev['Quick Health OK'] = False
+ TESTS['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)
- # Quick Health OK
- print_standard('Quick health assessment: ', end='', flush=True)
- if dev['Quick Health OK']:
- print_success('Passed.\n', timestamp=False)
- else:
- print_error('Failed.\n', timestamp=False)
-
def show_results():
clear_screen()
print_standard('Results')
@@ -395,26 +484,33 @@ def show_results():
TESTS['Progress Out']).split())
# Prime95
- print_info('\nPrime95:')
- for log, regex in [
- ['results.txt', r'(error|fail)'],
- ['prime.log', r'completed.*0 errors, 0 warnings']]:
- if log in TESTS['Prime95']:
- #print_standard(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))
+ if TESTS['Prime95']['Enabled']:
+ print_info('\nPrime95:')
+ for log, regex in [
+ ['results.txt', r'(error|fail)'],
+ ['prime.log', r'completed.*0 errors, 0 warnings']]:
+ if log in TESTS['Prime95']:
+ #print_standard(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_standard(' ')
- # NVMe/SMART
-
- # badblocks
+ # NVMe/SMART / badblocks
+ if TESTS['NVMe/SMART']['Enabled'] or TESTS['badblocks']['Enabled']:
+ for name, dev in sorted(TESTS['NVMe/SMART']['Devices'].items()):
+ show_disk_details(dev)
+ if TESTS['badblocks']['Enabled']:
+ #TODO
+ pass
+ print_standard(' ')
# Done
pause('Press Enter to return to main menu... ')
@@ -427,32 +523,32 @@ def update_progress():
output.append('{BLUE}HW Diagnostics{CLEAR}'.format(**COLORS))
output.append('───────────────')
if TESTS['Prime95']['Enabled']:
- output.append('')
+ 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(' ')
output.append('{BLUE}NVMe / SMART{CLEAR}'.format(**COLORS))
if TESTS['NVMe/SMART']['Quick']:
output.append('{YELLOW} (Quick Check){CLEAR}'.format(**COLORS))
- for dev, data in sorted(TESTS['NVMe/SMART']['Devices'].items()):
+ 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(data['Status']),
- status = data['Status'],
+ s_color = get_status_color(status),
+ status = status,
**COLORS))
if TESTS['badblocks']['Enabled']:
- output.append('')
+ output.append(' ')
output.append('{BLUE}badblocks{CLEAR}'.format(**COLORS))
- for dev, data in sorted(TESTS['badblocks']['Devices'].items()):
+ 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(data['Status']),
- status = data['Status'],
+ s_color = get_status_color(status),
+ status = status,
**COLORS))
# Add line-endings
From 0bab107e2498c581aee3ebcea6a8fd04878eb19d Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Wed, 27 Dec 2017 02:11:28 -0700
Subject: [PATCH 34/42] Updated results screen formatting
---
.bin/Scripts/functions/hw_diags.py | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py
index 092100ff..a1428dff 100644
--- a/.bin/Scripts/functions/hw_diags.py
+++ b/.bin/Scripts/functions/hw_diags.py
@@ -452,7 +452,9 @@ def show_disk_details(dev):
for attrib, threshold in sorted(ATTRIBUTES['SMART'].items()):
if attrib in s_table:
print_standard(
- ' {:>3} {:32}'.format(attrib, s_table[attrib]['name']),
+ ' {:>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)
@@ -476,7 +478,7 @@ def show_disk_details(dev):
def show_results():
clear_screen()
- print_standard('Results')
+ print_standard('Hardware Diagnostic Results')
update_progress()
# Set Window layout and show progress
@@ -485,12 +487,12 @@ def show_results():
# Prime95
if TESTS['Prime95']['Enabled']:
- print_info('\nPrime95:')
+ 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_standard(log)
+ print_info('Log: {}'.format(log))
lines = [line.strip() for line
in TESTS['Prime95'][log].splitlines()
if re.search(regex, line, re.IGNORECASE)]
@@ -505,6 +507,7 @@ def show_results():
# NVMe/SMART / badblocks
if TESTS['NVMe/SMART']['Enabled'] or TESTS['badblocks']['Enabled']:
+ print_success('\nDisks:')
for name, dev in sorted(TESTS['NVMe/SMART']['Devices'].items()):
show_disk_details(dev)
if TESTS['badblocks']['Enabled']:
From 0ea523a2cf5875bce13ebf33928db5d051e5836d Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Wed, 27 Dec 2017 02:12:32 -0700
Subject: [PATCH 35/42] Show Prime95 final temps in result screen
---
.bin/Scripts/functions/hw_diags.py | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py
index a1428dff..dc236399 100644
--- a/.bin/Scripts/functions/hw_diags.py
+++ b/.bin/Scripts/functions/hw_diags.py
@@ -503,6 +503,14 @@ def show_results():
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
From d4146c9c3537594e09ce3f2911ac8c6ded83c1f4 Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Wed, 27 Dec 2017 03:58:56 -0700
Subject: [PATCH 36/42] Added warning when no sensors are detected
---
.bin/Scripts/hw-sensors | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/.bin/Scripts/hw-sensors b/.bin/Scripts/hw-sensors
index da5427d0..bfaddc7e 100755
--- a/.bin/Scripts/hw-sensors
+++ b/.bin/Scripts/hw-sensors
@@ -141,8 +141,16 @@ if __name__ == '__main__':
sensor_temps = [join_columns(a, b) for a, b in sensor_temps]
# Print data
- for line in sensor_temps:
- print_standard(line)
+ 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()
From 7fbbde56c632212e2a304eaa24b7c2d0ad71f37c Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Wed, 27 Dec 2017 04:01:54 -0700
Subject: [PATCH 37/42] run_badblocks() working
* Re-added and updated hw-diags-badblocks
---
.bin/Scripts/functions/hw_diags.py | 71 +++++++++++++++++++++--
.bin/Scripts/hw-diags-badblocks | 18 ++++++
.bin/Scripts/hw-diags-prime95 | 1 +
.bin/Scripts/linux-old/hw-diags-badblocks | 25 --------
4 files changed, 86 insertions(+), 29 deletions(-)
create mode 100755 .bin/Scripts/hw-diags-badblocks
delete mode 100755 .bin/Scripts/linux-old/hw-diags-badblocks
diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py
index dc236399..8d9ed020 100644
--- a/.bin/Scripts/functions/hw_diags.py
+++ b/.bin/Scripts/functions/hw_diags.py
@@ -36,6 +36,7 @@ TESTS = {
},
'badblocks': {
'Enabled': False,
+ 'Results': {},
'Status': {},
},
}
@@ -116,6 +117,58 @@ def menu_diags():
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
+ print_standard(' /dev/{:11} '.format(name+'...'), end='', flush=True)
+ run_program('tmux split-window -dl 10 {} {} {}'.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'
+
+ # Remove temp file
+ os.remove(progress_file)
+ update_progress()
+
+ # Done
+ run_program('tmux kill-pane -a'.split(), check=False)
pass
def run_mprime():
@@ -255,7 +308,7 @@ def run_smart():
update_progress()
print_standard('Running SMART short self-test(s):')
print_standard(
- ' /dev/{:8}({} minutes)...'.format(name, test_length),
+ ' /dev/{:8}({} minutes)... '.format(name, test_length),
end='', flush=True)
run_program(
'sudo smartctl -t short /dev/{}'.format(name).split(),
@@ -518,9 +571,19 @@ def show_results():
print_success('\nDisks:')
for name, dev in sorted(TESTS['NVMe/SMART']['Devices'].items()):
show_disk_details(dev)
- if TESTS['badblocks']['Enabled']:
- #TODO
- pass
+ bb_status = TESTS['badblocks']['Status'].get(name, None)
+ if (TESTS['badblocks']['Enabled']
+ and bb_status not in ['Denied', 'OVERRIDE', 'Skipped']):
+ print_info('badblocks:')
+ for line in TESTS['badblocks']['Results'][name].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
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-prime95 b/.bin/Scripts/hw-diags-prime95
index c19a913c..30c6994d 100755
--- a/.bin/Scripts/hw-diags-prime95
+++ b/.bin/Scripts/hw-diags-prime95
@@ -15,3 +15,4 @@ fi
# Run Prime95
mprime -t | grep -iv --line-buffered 'stress.txt' | tee -a "$1/prime.log"
+
diff --git a/.bin/Scripts/linux-old/hw-diags-badblocks b/.bin/Scripts/linux-old/hw-diags-badblocks
deleted file mode 100755
index cfff7c4d..00000000
--- a/.bin/Scripts/linux-old/hw-diags-badblocks
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/bash
-#
-## Wizard Kit: HW Diagnostics - badblocks
-
-function usage {
- echo "Usage: $0 log-dir device"
- echo " e.g. $0 /tmp/tmp.7Mh5f1RhSL9001 /dev/sda"
-}
-
-# Bail early
-if [ ! -d "$1" ]; then
- usage
- exit 1
-fi
-if [ ! -b "$2" ]; then
- usage
- exit 1
-fi
-
-# Run Badblocks
-sudo badblocks -sv -e 1 "$2"
-tmux capture-pane
-tmux save-buffer "$1/bb_tmp.out"
-grep -Ev '^$' "$1/bb_tmp.out" > "$1/${2##*/}_badblocks.log"
-rm "$1/bb_tmp.out"
From 16c20ac6ea6da5dd1f20e5b76736984d8dfff08a Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Wed, 27 Dec 2017 04:22:02 -0700
Subject: [PATCH 38/42] Cleanup and fix results screen during abort
* Renamed run_smart to run_nvme_smart to match rest of the code
* Mark NVMe/SMART status as NS earlier in a couple more cases
* Prevent crash when all tests are run and then aborted during Prime95
---
.bin/Scripts/functions/hw_diags.py | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py
index 8d9ed020..001737eb 100644
--- a/.bin/Scripts/functions/hw_diags.py
+++ b/.bin/Scripts/functions/hw_diags.py
@@ -262,7 +262,7 @@ def run_mprime():
# Done
run_program('tmux kill-pane -a'.split())
-def run_smart():
+def run_nvme_smart():
aborted = False
clear_screen()
print_log('\nStart NVMe/SMART test(s)\n')
@@ -378,7 +378,7 @@ def run_tests(tests):
mprime_aborted = True
if not mprime_aborted:
if TESTS['NVMe/SMART']['Enabled']:
- run_smart()
+ run_nvme_smart()
if TESTS['badblocks']['Enabled']:
run_badblocks()
@@ -445,6 +445,7 @@ def scan_disks():
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
@@ -522,7 +523,7 @@ def show_disk_details(dev):
print_error(raw_str, timestamp=False)
if not threshold.get('Ignore', False):
dev['Quick Health OK'] = False
- TESTS['SMART']['Status'][dev_name] = 'NS'
+ 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)
@@ -568,14 +569,15 @@ def show_results():
# NVMe/SMART / badblocks
if TESTS['NVMe/SMART']['Enabled'] or TESTS['badblocks']['Enabled']:
- print_success('\nDisks:')
+ 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:')
- for line in TESTS['badblocks']['Results'][name].splitlines():
+ 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'',
From 62c77fb696136ef774b765d015bf1f1eeba127b2 Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Wed, 27 Dec 2017 04:27:04 -0700
Subject: [PATCH 39/42] removed remaining old, unused scripts
---
.bin/Scripts/linux-old/hw-diags | 135 ------
.bin/Scripts/linux-old/hw-diags-inner | 518 -----------------------
.bin/Scripts/linux-old/hw-diags-progress | 10 -
3 files changed, 663 deletions(-)
delete mode 100755 .bin/Scripts/linux-old/hw-diags
delete mode 100755 .bin/Scripts/linux-old/hw-diags-inner
delete mode 100755 .bin/Scripts/linux-old/hw-diags-progress
diff --git a/.bin/Scripts/linux-old/hw-diags b/.bin/Scripts/linux-old/hw-diags
deleted file mode 100755
index 730458f3..00000000
--- a/.bin/Scripts/linux-old/hw-diags
+++ /dev/null
@@ -1,135 +0,0 @@
-#!/bin/bash
-#
-## Wizard Kit: HW Diagnostics - Menu
-
-MODE="$1"
-SHOW_MENU="True"
-if [[ "$MODE" =~ ^(all|cpu|drives|foh|smart|badblocks)$ ]]; then
- SHOW_MENU="False"
-fi
-
-SHOW_POWEROPTIONS="False"
-if [[ "$MODE" =~ ^cli$ ]]; then
- SHOW_POWEROPTIONS="True"
-fi
-
-function pause() {
- # Pause to review output
- echo ""
- echo "$1"
- read
-}
-
-function menu() {
- while :; do
- if [[ "$SHOW_MENU" == "False" ]]; then
- break
- else
- clear
- echo "Hardware Diagnostics"
- echo "────────────────────"
- echo "0: Quick drive test"
- echo "1: All tests"
- echo "2: Prime95"
- echo "3: SMART & badblocks"
- echo "4: SMART"
- echo "5: badblocks"
- echo "────────────────────"
- #if [[ -n $DISPLAY ]] && [[ $(getconf LONG_BIT) -eq "64" ]]; then
- # echo "6: Graphics Test - FurMark"
- # echo "7: Graphics Test - Piano"
- # echo "8: Graphics Test - Volplosion"
- #fi
- echo "A: Speaker Test"
- if [[ -n $DISPLAY ]]; then
- echo "K: Keyboard Test"
- fi
- echo "N: Network Test"
- echo "────────────────────"
- echo "M: Screen Saver - Matrix"
- echo "P: Screen Saver - Pipes"
- echo "────────────────────"
- echo "Q: Quit"
- if [[ "$SHOW_POWEROPTIONS" =~ ^True$ ]]; then
- echo "R: Reboot"
- echo "S: Shutdown"
- fi
- echo ""
- read -r -p "Please make a selection: " MODE
-
- # Check input
- case $MODE in
- 0)
- MODE=foh
- break;;
- 1)
- MODE=all
- break;;
- 2)
- MODE=cpu
- break;;
- 3)
- MODE=drives
- break;;
- 4)
- MODE=smart
- break;;
- 5)
- MODE=badblocks
- break;;
- #6)
- # if [[ -n $DISPLAY ]] && [[ $(getconf LONG_BIT) -eq "64" ]]; then
- # gputest /fullscreen /test=fur
- # fi
- # ;;
- #7)
- # if [[ -n $DISPLAY ]] && [[ $(getconf LONG_BIT) -eq "64" ]]; then
- # gputest /fullscreen /test=pixmark_piano
- # fi
- # ;;
- #8)
- # if [[ -n $DISPLAY ]] && [[ $(getconf LONG_BIT) -eq "64" ]]; then
- # gputest /fullscreen /test=pixmark_volplosion
- # fi
- # ;;
- a|A|audio|Audio)
- clear
- hw-diags-audio
- pause "Press Enter to return to menu...";;
- k|K|keyboard|Keyboard)
- if [[ -n $DISPLAY ]]; then
- xev
- fi
- ;;
- m|M)
- cmatrix -abs
- reset
- clear;;
- n|N)
- clear
- hw-diags-network
- pause "Press Enter to return to menu...";;
- p|P)
- pipes -t 0 -t 1 -t 2 -t 3 -p 5 -R -r 4000
- reset
- clear;;
- q|Q|quit|Quit)
- exit 0;;
- r|R)
- sudo reboot;;
- s|S)
- sudo poweroff;;
- esac
- fi
- done
-}
-
-# Main Loop
-while :; do
- menu
- tmux new-session -s 'hw-session' -n 'hw-window' "hw-diags-inner $MODE"
- if [[ "$SHOW_MENU" == "False" ]]; then
- break
- fi
-done
-
diff --git a/.bin/Scripts/linux-old/hw-diags-inner b/.bin/Scripts/linux-old/hw-diags-inner
deleted file mode 100755
index dcb08c8b..00000000
--- a/.bin/Scripts/linux-old/hw-diags-inner
+++ /dev/null
@@ -1,518 +0,0 @@
-#!/bin/bash
-#
-## Wizard Kit: HW Diagnostics - Main script
-
-die () {
- echo "$0:" "$@" >&2
- exit 1
-}
-
-# Load settings
-if [[ -f "/run/archiso/bootmnt/arch/main.conf" ]]; then
- source "/run/archiso/bootmnt/arch/main.conf" || \
- die "ERROR: failed to load main.conf (from /run/archiso/bootmnt/arch/)"
-else
- source "/usr/local/bin/main.conf" || \
- die "ERROR: failed to load main.conf (from /usr/local/bin/)"
-fi
-
-# Get TICKET
-## Inital SKIP_UPLOAD value loaded from main.conf
-SKIP_UPLOAD="${SKIP_UPLOAD}"
-TICKET=""
-while [[ "$TICKET" == "" ]]; do
- if [[ "$1" == "foh" ]]; then
- TICKET="foh-consult"
- SKIP_UPLOAD="True"
- else
- echo -n "Please enter the Service Order #: "
- read -r _ticket
- if echo "$_ticket" | grep -Eq '^[1-9]+\S*$'; then
- TICKET="$_ticket"
- elif echo "$_ticket" | grep -Eq '^0'; then
- SKIP_UPLOAD="True"
- TICKET="$_ticket"
- fi
- fi
-done
-
-# Init
-## Tautologies left to show which settings are coming from main.conf
-DIAG_DATE="$(date "+%F_%H%M")"
-DIAG_SERVER_AVAIL="False"
-DIAG_SERVER="${DIAG_SERVER}"
-DIAG_SHARE="${DIAG_SHARE}"
-DIAG_DEST="${DIAG_SHARE}/${TICKET}"
-DIAG_UPLOAD_NAME="HW-Diagnostics_${DIAG_DATE}"
-DIAG_USER="${DIAG_USER}"
-TMP_DIR="$(mktemp -d)"
-ERRORS="False"
-TEST_CPU="False"
-TEST_CPU_LENGTH="${TEST_CPU_LENGTH}"
-TEST_OVER="False"
-TEST_SMART="False"
-TEST_BADBLOCKS="False"
-SKIP_SHORT_TEST="False"
-LOG="$TMP_DIR/hw-diags.log"
-OUT="$TMP_DIR/hw-diags.out"
-
-# Get list of drives to test (excluding any ARCH drives)
-
-## Some code borrowed from stackoverflow.com/a/10020397
-ARCH_DRIVES=($(ls -l /dev/disk/by-label | grep -iE 'ARCH.*[hs]d[a-z]' | sed -r 's#.*/([hs]d[a-z])[0-9]+#\1#' | sort | uniq))
-DRIVES=($(inxi -Dxx -c 0 | grep -E "ID-[0-9]+" | sed -r 's#.*/dev/([hsv]d[a-z]|nvme[0-9]n[0-9]).*#\1#' | sort))
-for d in "${ARCH_DRIVES[@]}"; do
- DRIVES=(${DRIVES[@]//*$d*})
-done
-
-# Handle testing runs
-if [[ "$SKIP_UPLOAD" != "True" ]]; then
- # Connect to network
- connect-to-network
-
- # Test connection to DIAG_SERVER
- if ip a | grep -Eq '(10.[0-9]+|172.(1[6-9]|2[0-9]|3[0-1])|192.168).[0-9]+.[0-9]+' && \
- ping -c 1 -q $DIAG_SERVER >/dev/null 2>&1; then
- DIAG_SERVER_AVAIL="True"
- ssh-add
- ssh $DIAG_USER@$DIAG_SERVER mkdir -p "$DIAG_DEST"
- ssh $DIAG_USER@$DIAG_SERVER chmod 755 "$DIAG_DEST"
- fi
-fi
-
-# Setup Env
-mkdir "$TMP_DIR" -p 2>/dev/null
-pushd "$TMP_DIR" >/dev/null
-touch "$OUT"
-rm local.txt results.txt 2>/dev/null
-
-# Functions
-CLEAR="\e[0m"
-RED="\e[31m"
-GREEN="\e[32m"
-YELLOW="\e[33m"
-BLUE="\e[34m"
-function update_progress {
- echo "HW Diagnostics" > "$LOG"
- echo "${BLUE}HW Diagnostics${CLEAR}" > "$OUT"
- echo "───────────────" >> "$LOG"
- echo "───────────────" >> "$OUT"
-
- if [[ "$TEST_CPU" == "True" ]]; then
- echo "" >> "$LOG"
- echo "" >> "$OUT"
- if [[ "$cpu_result" == "CS" ]]; then
- echo "Prime95 CS" >> "$LOG"
- echo "${BLUE}Prime95${CLEAR} ${GREEN}CS${CLEAR}" >> "$OUT"
- elif [[ "$cpu_result" == "Working" ]]; then
- echo "Prime95 Working" >> "$LOG"
- echo "${BLUE}Prime95${CLEAR} ${YELLOW}Working${CLEAR}" >> "$OUT"
- elif [[ "$cpu_result" == "Unknown" ]]; then
- echo "Prime95 Unknown" >> "$LOG"
- echo "${BLUE}Prime95${CLEAR} ${YELLOW}Unknown${CLEAR}" >> "$OUT"
- else
- echo "Prime95 NS" >> "$LOG"
- echo "${BLUE}Prime95${CLEAR} ${RED}NS${CLEAR}" >> "$OUT"
- fi
- fi
-
- if [[ "$TEST_SMART" == "True" ]]; then
- echo "" >> "$LOG"
- echo "" >> "$OUT"
- if [[ "$SKIP_SHORT_TEST" == "True" ]]; then
- echo "SMART (Quick)" >> "$LOG"
- echo "${BLUE}SMART${CLEAR} ${YELLOW}(Quick)${CLEAR}" >> "$OUT"
- else
- echo "SMART" >> "$LOG"
- echo "${BLUE}SMART${CLEAR}" >> "$OUT"
- fi
- for d in "${DRIVES[@]}"; do
- d_tmp="${d##*/}_smart_result"
- eval "d_tmp=\$$d_tmp"
- if [[ "$d_tmp" == "CS" ]]; then
- echo "${d##*/} CS" >> "$LOG"
- echo "${d##*/} ${GREEN}CS${CLEAR}" >> "$OUT"
- elif [[ "$d_tmp" == "Working" ]]; then
- echo "${d##*/} Working" >> "$LOG"
- echo "${d##*/} ${YELLOW}Working${CLEAR}" >> "$OUT"
- elif [[ "$d_tmp" == "Unknown" ]]; then
- echo "${d##*/} Unknown" >> "$LOG"
- echo "${d##*/} ${YELLOW}Unknown${CLEAR}" >> "$OUT"
- elif [[ "$d_tmp" == "NS" ]]; then
- echo "${d##*/} NS" >> "$LOG"
- echo "${d##*/} ${RED}NS${CLEAR}" >> "$OUT"
- else
- echo "${d##*/}" >> "$LOG"
- echo "${d##*/}" >> "$OUT"
- fi
- done
- fi
-
- if [[ "$TEST_BADBLOCKS" == "True" ]]; then
- echo "" >> "$LOG"
- echo "" >> "$OUT"
- echo "Badblocks" >> "$LOG"
- echo "${BLUE}Badblocks${CLEAR}" >> "$OUT"
- for d in "${DRIVES[@]}"; do
- d_tmp="${d##*/}_badblocks_result"
- eval "d_tmp=\$$d_tmp"
- if [[ "$d_tmp" == "CS" ]]; then
- echo "${d##*/} CS" >> "$LOG"
- echo "${d##*/} ${GREEN}CS${CLEAR}" >> "$OUT"
- elif [[ "$d_tmp" == "Working" ]]; then
- echo "${d##*/} Working" >> "$LOG"
- echo "${d##*/} ${YELLOW}Working${CLEAR}" >> "$OUT"
- elif [[ "$d_tmp" == "Skipped" ]]; then
- echo "${d##*/} Skipped" >> "$LOG"
- echo "${d##*/} ${RED}Skipped${CLEAR}" >> "$OUT"
- elif [[ "$d_tmp" == "NS" ]]; then
- echo "${d##*/} NS" >> "$LOG"
- echo "${d##*/} ${RED}NS${CLEAR}" >> "$OUT"
- else
- echo "${d##*/}" >> "$LOG"
- echo "${d##*/}" >> "$OUT"
- fi
- done
- fi
-
- if [[ "$TEST_OVER" == "True" ]]; then
- echo "" >> "$LOG"
- echo "" >> "$OUT"
- echo "───────────────" >> "$LOG"
- echo "───────────────" >> "$OUT"
-
- if [[ "$ERRORS" == "True" ]]; then
- echo "HW: Error(s)" >> "$LOG"
- echo "${RED}HW: Error(s)${CLEAR}" >> "$OUT"
- else
- echo "HW: Passed" >> "$LOG"
- echo "${GREEN}HW: Passed${CLEAR}" >> "$OUT"
- fi
- fi
-
- # Update Server
- if [[ "$DIAG_SERVER_AVAIL" == "True" ]]; then
- rsync -aqz --chmod=Du=rwx,Dgo=rx,Fu=rw,Fgo=r "$TMP_DIR/" $DIAG_USER@$DIAG_SERVER:"$DIAG_DEST/${DIAG_UPLOAD_NAME}/" --exclude '*.out'
- fi
-}
-
-# Select Tests
-case "$1" in
- all)
- TEST_CPU="True"
- TEST_SMART="True"
- TEST_BADBLOCKS="True"
- ;;
- cpu)
- TEST_CPU="True"
- TEST_SMART="False"
- TEST_BADBLOCKS="False"
- ;;
- drives)
- TEST_CPU="False"
- TEST_SMART="True"
- TEST_BADBLOCKS="True"
- ;;
- foh)
- TEST_CPU="False"
- TEST_SMART="True"
- TEST_BADBLOCKS="False"
- SKIP_SHORT_TEST="True"
- ;;
- smart)
- TEST_CPU="False"
- TEST_SMART="True"
- TEST_BADBLOCKS="False"
- ;;
- badblocks)
- TEST_CPU="False"
- TEST_SMART="False"
- TEST_BADBLOCKS="True"
- ;;
-esac
-
-if [[ "$TEST_CPU" == "False" ]] && \
- [[ "$TEST_SMART" == "False" ]] && \
- [[ "$TEST_BADBLOCKS" == "False" ]]; then
- echo -e "${YELLOW}Aborting HW Diagnostics${CLEAR}"
- exit 1
-fi
-
-# Configure display
-tmux split-window -d -h -l 16 "hw-diags-progress $OUT"
-update_progress
-
-# CPU
-if [[ "$TEST_CPU" == "True" ]]; then
- clear
- CPU_ERRORS="False"
- cpu_result="Working"
- update_progress
- apple_fans max
- (sleep ${TEST_CPU_LENGTH}m && killall -s INT "mprime" >>/dev/null 2>&1) &
- (sleep ${TEST_CPU_LENGTH}m && killall "hw-diags-sensors" >>/dev/null 2>&1) &
- (sleep ${TEST_CPU_LENGTH}m && apple_fans auto >>/dev/null 2>&1) &
- tmux split-window -d -v -l 10 "hw-diags-prime95 $TMP_DIR"
- hw-diags-sensors "$TMP_DIR" 2>/dev/null
- sleep 1s
- # tmux kill-pane -t 1
- if [[ -f "results.txt" ]]; then
- mv -nv results.txt "prime-results.txt"
- if grep -q -iE '(error|fail)' "prime-results.txt"; then
- cpu_result="NS"
- CPU_ERRORS="True"
- else
- cpu_result="CS"
- fi
- elif [[ -f "prime.log" ]]; then
- if grep -i 'completed' "prime.log" | grep -q -iv '0 errors, 0 warnings'; then
- cpu_result="NS"
- CPU_ERRORS="True"
- else
- cpu_result="CS"
- fi
- else
- CPU_ERRORS="True"
- cpu_result="Unknown"
- fi
-
- update_progress
-
- if [[ "$CPU_ERRORS" == "True" ]]; then
- ERRORS="True"
- fi
-fi
-
-# SMART
-if [[ "$TEST_SMART" == "True" ]]; then
- clear
- echo "Checking SMART status..."
- for d in "${DRIVES[@]}"; do
- SMART_ERRORS="False"
- tmp_device="${d##*/}"
- eval "${tmp_device}_smart_result=Working"
- inxi -Dxx | grep "/dev/${tmp_device}" | sed -r "s#.*/dev/${tmp_device} (.*)# \1#" > "${tmp_device}_report.out"
- inxi -Dxxc 0 | grep "/dev/${tmp_device}" | sed -r "s#.*/dev/${tmp_device} (.*)# \1#" > "${tmp_device}_report.log"
- update_progress
-
- # Attempt to enable SMART reporting
- if sudo smartctl -s on "/dev/${tmp_device}" | grep -q 'device lacks SMART capability'; then
- SMART_ERRORS="True"
- eval "${tmp_device}_smart_result=Unknown"
- echo " ${RED}ERROR: device lacks SMART capability${CLEAR}" >> "${tmp_device}_report.out"
- echo " ERROR: device lacks SMART capability" >> "${tmp_device}_report.log"
- sleep 1s
- fi
-
- # Save current SMART values
- sudo smartctl --all "/dev/${tmp_device}" >> "${tmp_device}-smart.log"
- sudo smartctl -l error "/dev/${tmp_device}" >> "${tmp_device}-smart-err.log"
-
- # Check specific SMART results
- sudo smartctl -A "/dev/${tmp_device}" | grep -E '^\s*(5|9|184|197|198)\s' >> "${tmp_device}-smart-attributes.log"
-
- # 5 - Reallocated Sectors
- if grep -qE '^\s*5\s' "${tmp_device}-smart-attributes.log"; then
- line="$(grep -E '^\s*5\s' "${tmp_device}-smart-attributes.log")"
- value=$(echo "$line" | sed -r 's/.*\s([0-9]+).*/\1/')
- echo " Reallocated Sectors: $value" >> "${tmp_device}_report.log"
- if [[ "$value" -gt 0 ]]; then
- SMART_ERRORS="True"
- echo " ${RED}Reallocated Sectors: $value${CLEAR}" >> "${tmp_device}_report.out"
- else
- echo " ${GREEN}Reallocated Sectors: $value${CLEAR}" >> "${tmp_device}_report.out"
- fi
- fi
-
- # 9 - Power-on Hours (Warn, but don't prevent badblock scan)
- if grep -qE '^\s*9\s' "${tmp_device}-smart-attributes.log"; then
- line="$(grep -E '^\s*9\s' "${tmp_device}-smart-attributes.log")"
- value=$(echo "$line" | sed -r 's/.*\s([0-9]+).*/\1/')
- echo " Power-on Hours: $value" >> "${tmp_device}_report.log"
- if [[ "$value" -gt 18000 ]]; then
- #SMART_ERRORS="True"
- echo " ${RED}Power-on Hours: $value (VERY OLD)${CLEAR}" >> "${tmp_device}_report.out"
- elif [[ "$value" -gt 12000 ]]; then
- echo " ${YELLOW}Power-on Hours: $value${CLEAR}" >> "${tmp_device}_report.out"
- else
- echo " ${GREEN}Power-on Hours: $value${CLEAR}" >> "${tmp_device}_report.out"
- fi
- fi
-
- # 184 - End-to-End Errors
- if grep -qE '^\s*184\s' "${tmp_device}-smart-attributes.log"; then
- line="$(grep -E '^\s*184\s' "${tmp_device}-smart-attributes.log")"
- value=$(echo "$line" | sed -r 's/.*\s([0-9]+).*/\1/')
- echo " End-to-End Errors: $value" >> "${tmp_device}_report.log"
- if [[ "$value" -gt 0 ]]; then
- SMART_ERRORS="True"
- echo " ${RED}End-to-End Errors: $value${CLEAR}" >> "${tmp_device}_report.out"
- else
- echo " ${GREEN}End-to-End Errors: $value${CLEAR}" >> "${tmp_device}_report.out"
- fi
- fi
-
- # 197 - Current Pending Sectors
- if grep -qE '^\s*197\s' "${tmp_device}-smart-attributes.log"; then
- line="$(grep -E '^\s*197\s' "${tmp_device}-smart-attributes.log")"
- value=$(echo "$line" | sed -r 's/.*\s([0-9]+).*/\1/')
- echo " Current Pending Sectors: $value" >> "${tmp_device}_report.log"
- if [[ "$value" -gt 0 ]]; then
- SMART_ERRORS="True"
- echo " ${RED}Current Pending Sectors: $value${CLEAR}" >> "${tmp_device}_report.out"
- else
- echo " ${GREEN}Current Pending Sectors: $value${CLEAR}" >> "${tmp_device}_report.out"
- fi
- fi
-
- # 198 - Offline Uncorrectable
- if grep -qE '^\s*198\s' "${tmp_device}-smart-attributes.log"; then
- line="$(grep -E '^\s*198\s' "${tmp_device}-smart-attributes.log")"
- value=$(echo "$line" | sed -r 's/.*\s([0-9]+).*/\1/')
- echo " Offline Uncorrectable: $value" >> "${tmp_device}_report.log"
- if [[ "$value" -gt 0 ]]; then
- SMART_ERRORS="True"
- echo " ${RED}Offline Uncorrectable: $value${CLEAR}" >> "${tmp_device}_report.out"
- else
- echo " ${GREEN}Offline Uncorrectable: $value${CLEAR}" >> "${tmp_device}_report.out"
- fi
- fi
-
- if [[ "$SMART_ERRORS" == "False" ]] && [[ "$SKIP_SHORT_TEST" == "False" ]]; then
- if sudo smartctl -c "/dev/${tmp_device}" >>/dev/null 2>&1; then
- # Determine short-test polling time
- wait_time=$(sudo smartctl -c "/dev/${tmp_device}" | grep -i 'polling time' | head -1 | sed -r 's/.*\( *([0-9]+)\).*/\1/')
- wait_time=$(( wait_time + 5))
-
- # Run short self-test
- echo " Running SMART short self-test ($wait_time minutes)..."
- sudo smartctl -t short "/dev/${tmp_device}" >/dev/null
- sleep ${wait_time}m
- sudo smartctl -l selftest "/dev/${tmp_device}" >> "${tmp_device}-smart-tests.log"
- if grep '^#' "${tmp_device}-smart-tests.log" | head -1 | grep -iq 'completed without error'; then
- echo " ${GREEN}Self-test: passed${CLEAR}" >> "${tmp_device}_report.out"
- echo " Self-test: passed" >> "${tmp_device}_report.log"
- else
- echo " ${RED}Self-test: failed${CLEAR}" >> "${tmp_device}_report.out"
- echo " Self-test: failed" >> "${tmp_device}_report.log"
- SMART_ERRORS="True"
- fi
- else
- echo " ${RED}ERROR: Unable to run SMART self-test.${CLEAR}" >> "${tmp_device}_report.out"
- echo " ERROR: Unable to run SMART self-test." >> "${tmp_device}_report.log"
- fi
- fi
-
- if [[ "$SMART_ERRORS" == "False" ]]; then
- eval "${tmp_device}_smart_result=CS"
- else
- ERRORS="True"
- tmp_if="${tmp_device}_smart_result"
- eval "tmp_if=\$$tmp_if"
- if [[ "$tmp_if" != "Unknown" ]]; then
- eval "${tmp_device}_smart_result=NS"
- fi
- fi
-
- update_progress
- done
-fi
-
-# Badblocks
-if [[ "$TEST_BADBLOCKS" == "True" ]]; then
- clear
- for d in "${DRIVES[@]}"; do
- # Get SMART results
- tmp_device="${d##*/}"
- d_smart="${tmp_device}_smart_result"
- eval "d_smart=\$$d_smart"
-
- # Check SMART results
- if [[ "$d_smart" == "NS" ]]; then
- echo -e "${RED}Skipping drive: $tmp_device${CLEAR}"
- eval "${tmp_device}_badblocks_result=Skipped"
- else
- eval "${tmp_device}_badblocks_result=Working"
- update_progress
- echo "Testing drive: ${tmp_device}"
-
- # Split and run
- tmux split-window -v -l 7 "hw-diags-badblocks $TMP_DIR /dev/${tmp_device}"
-
- # Wait until done
- sleep 2s
- while pgrep -G 0 -U 0 -f "badblocks.*${tmp_device}" >/dev/null 2>&1; do
- sleep 1s;
- done
- sleep 2s
-
- # Check log
- if grep -Eiq 'Pass completed.*0/0/0 errors' "${tmp_device}_badblocks.log"; then
- eval "${tmp_device}_badblocks_result=CS"
- else
- eval "${tmp_device}_badblocks_result=NS"
- fi
- update_progress
- fi
- done
-fi
-
-# Result Screen
-TEST_OVER="True"
-update_progress
-clear
-echo "─── RESULTS ───"
-if [[ "$TEST_CPU" == "True" ]]; then
- echo -e "${BLUE}CPU:${CLEAR}"
- if [[ -f "results.txt" ]]; then
- echo "results.txt"
- if grep -q -iE '(error|fail)' "prime-results.txt"; then
- echo -e "${RED}$(grep -q -iE '(error|fail)' "prime-results.txt" | sed -r 's/^/ /' | tail -4)${CLEAR}"
- else
- sed -r 's/^/ /' "prime-results.txt" 2>/dev/null | tail -4
- fi
- echo ""
- fi
- if [[ -f "prime.log" ]]; then
- echo "prime.log"
- if grep -i 'completed' "prime.log" | grep -q -iv '0 errors, 0 warnings'; then
- echo -e "${RED}$(grep -i 'completed' "prime.log" | grep -iv '0 errors, 0 warnings' | sed -r 's/^/ /' | tail -4)${CLEAR}"
- else
- grep -i 'completed' "prime.log" | grep -i '0 errors, 0 warnings' | sed -r 's/^.*(Worker #[0-9]+).*(Torture.*)/ \1 \2/' | tail -4
- fi
- fi
-fi
-if [[ "$TEST_SMART" == "True" ]] || \
- [[ "$TEST_BADBLOCKS" == "True" ]]; then
- for d in "${DRIVES[@]}"; do
- echo -e "${BLUE}Drive $d:${CLEAR}"
- if [[ -f "${d##*/}_report.out" ]]; then
- echo -e "$(cat "${d##*/}_report.out" 2>/dev/null)"
- fi
- if [[ -f "${d##*/}_badblocks.log" ]]; then
- grep 'Pass completed, ' "${d##*/}_badblocks.log" 2>/dev/null | sed -r 's/^Pass completed, / /' 2>/dev/null
- fi
- echo ""
- done
-fi
-update_progress
-
-# System info dump
-sudo inxi -CDdGlMmNopRsc 0 | grep -Ev '(/dev/ram|No RAID devices|Display Server|multisession)' > "system_info.txt"
-
-# Cleanup
-mkdir "$HOME/Tickets/$TICKET" -p 2>/dev/null
-rsync -aS --chmod=Du=rwx,Dgo=rx,Fu=rw,Fgo=r "$TMP_DIR/" "$HOME/Tickets/$TICKET/"
-popd >/dev/null
-cd "$HOME/Tickets" && tar czf "${DIAG_UPLOAD_NAME}.tgz" "$TICKET"
-
-# Update Server
-if [[ "$DIAG_SERVER_AVAIL" == "True" ]]; then
- rsync -aqz --chmod=Du=rwx,Dgo=rx,Fu=rw,Fgo=r "${DIAG_UPLOAD_NAME}.tgz" $DIAG_USER@$DIAG_SERVER:"$DIAG_DEST/"
-fi
-
-# End
-echo -n "Press Enter to exit..."
-read -r
-killall hw-diags-progress >>/dev/null 2>&1
-exit 0
diff --git a/.bin/Scripts/linux-old/hw-diags-progress b/.bin/Scripts/linux-old/hw-diags-progress
deleted file mode 100755
index 97eb03a5..00000000
--- a/.bin/Scripts/linux-old/hw-diags-progress
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-#
-## Wizard Kit: HW Diagnostics - Progress
-
-# Loop forever
-while :; do
- clear
- echo -e "$(cat "$1")"
- sleep 1s
-done
From 6ddf3fca674de1cadc565466a1699d6c500b8f53 Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Wed, 27 Dec 2017 04:45:59 -0700
Subject: [PATCH 40/42] Re-added hw-diags quick disk check function
---
.bin/Scripts/functions/hw_diags.py | 7 ++++++-
.bin/Scripts/hw-diags | 2 +-
.bin/Scripts/hw-diags-menu | 2 +-
.../include/live/airootfs/etc/skel/.config/i3/config | 2 +-
.../include/live/airootfs/etc/skel/.config/openbox/rc.xml | 2 +-
5 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/.bin/Scripts/functions/hw_diags.py b/.bin/Scripts/functions/hw_diags.py
index 001737eb..f30078d9 100644
--- a/.bin/Scripts/functions/hw_diags.py
+++ b/.bin/Scripts/functions/hw_diags.py
@@ -60,7 +60,7 @@ def get_status_color(s):
color = COLORS['GREEN']
return color
-def menu_diags():
+def menu_diags(*args):
diag_modes = [
{'Name': 'All tests',
'Tests': ['Prime95', 'NVMe/SMART', 'badblocks']},
@@ -83,6 +83,11 @@ def menu_diags():
{'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(
diff --git a/.bin/Scripts/hw-diags b/.bin/Scripts/hw-diags
index 4ce5afdc..c1d7d3ca 100755
--- a/.bin/Scripts/hw-diags
+++ b/.bin/Scripts/hw-diags
@@ -39,5 +39,5 @@ if tmux list-session | grep -q "$SESSION_NAME"; then
fi
# Start session
-tmux new-session -s "$SESSION_NAME" -n "$WINDOW_NAME" "$MENU"
+tmux new-session -s "$SESSION_NAME" -n "$WINDOW_NAME" "$MENU" $*
diff --git a/.bin/Scripts/hw-diags-menu b/.bin/Scripts/hw-diags-menu
index cbd4b3b2..f7c1739c 100755
--- a/.bin/Scripts/hw-diags-menu
+++ b/.bin/Scripts/hw-diags-menu
@@ -17,7 +17,7 @@ if __name__ == '__main__':
clear_screen()
# Show menu
- menu_diags()
+ menu_diags(*sys.argv)
# Done
#print_standard('\nDone.')
diff --git a/.linux_items/include/live/airootfs/etc/skel/.config/i3/config b/.linux_items/include/live/airootfs/etc/skel/.config/i3/config
index 59b798cf..c136b3f7 100644
--- a/.linux_items/include/live/airootfs/etc/skel/.config/i3/config
+++ b/.linux_items/include/live/airootfs/etc/skel/.config/i3/config
@@ -72,7 +72,7 @@ bindsym $mod+d exec "urxvt -title 'Hardware Diagnostics' -e hw-diags"
bindsym $mod+f exec "thunar ~"
bindsym $mod+i exec "hardinfo"
bindsym $mod+m exec "urxvt -title 'Mount All Volumes' -e mount-all-volumes foh"
-bindsym $mod+s exec "urxvt -title 'Hardware Diagnostics' -e hw-diags foh"
+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"
diff --git a/.linux_items/include/live/airootfs/etc/skel/.config/openbox/rc.xml b/.linux_items/include/live/airootfs/etc/skel/.config/openbox/rc.xml
index f1056533..6521d979 100644
--- a/.linux_items/include/live/airootfs/etc/skel/.config/openbox/rc.xml
+++ b/.linux_items/include/live/airootfs/etc/skel/.config/openbox/rc.xml
@@ -324,7 +324,7 @@
- urxvt -title "Hardware Diagnostics" -e hw-diags foh
+ urxvt -title "Hardware Diagnostics" -e hw-diags quick
From 094251b93f87c6cea5dcb2a00d1072fd03bfc527 Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Wed, 27 Dec 2017 04:47:23 -0700
Subject: [PATCH 41/42] Forgot to remove python-libtmux package references
---
.linux_items/packages/aur | 1 -
.linux_items/packages/live | 1 -
2 files changed, 2 deletions(-)
diff --git a/.linux_items/packages/aur b/.linux_items/packages/aur
index 611490ef..9de0855e 100644
--- a/.linux_items/packages/aur
+++ b/.linux_items/packages/aur
@@ -9,7 +9,6 @@ nvme-cli
openbox-patched
papirus-icon-theme
pasystray
-python-libtmux
smartmontools-svn
testdisk-wip
ttf-font-awesome
diff --git a/.linux_items/packages/live b/.linux_items/packages/live
index 75b20e0a..534a5019 100644
--- a/.linux_items/packages/live
+++ b/.linux_items/packages/live
@@ -56,7 +56,6 @@ pavucontrol
progsreiserfs
pulseaudio
python
-python-libtmux
python-psutil
python-requests
qemu-guest-agent
From 938ee7afd54a130c57e372c51cb91f0d879cb988 Mon Sep 17 00:00:00 2001
From: 2Shirt <1923621+2Shirt@users.noreply.github.com>
Date: Wed, 27 Dec 2017 04:50:18 -0700
Subject: [PATCH 42/42] Renamed mount-all-volumes foh option to gui
---
.bin/Scripts/mount-all-volumes | 2 +-
.linux_items/include/live/airootfs/etc/skel/.config/i3/config | 2 +-
.../include/live/airootfs/etc/skel/.config/openbox/rc.xml | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/.bin/Scripts/mount-all-volumes b/.bin/Scripts/mount-all-volumes
index fbd7084b..fdc76046 100755
--- a/.bin/Scripts/mount-all-volumes
+++ b/.bin/Scripts/mount-all-volumes
@@ -27,7 +27,7 @@ if __name__ == '__main__':
# Done
print_standard('\nDone.')
- if 'foh' in sys.argv:
+ if 'gui' in sys.argv:
pause("Press Enter to exit...")
popen_program(['nohup', 'thunar', '/media'])
exit_script()
diff --git a/.linux_items/include/live/airootfs/etc/skel/.config/i3/config b/.linux_items/include/live/airootfs/etc/skel/.config/i3/config
index c136b3f7..dbbdee82 100644
--- a/.linux_items/include/live/airootfs/etc/skel/.config/i3/config
+++ b/.linux_items/include/live/airootfs/etc/skel/.config/i3/config
@@ -71,7 +71,7 @@ bindsym $mod+r exec "rofi -combi-modi window,drun,run -show combi -modi combi"
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 foh"
+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"
diff --git a/.linux_items/include/live/airootfs/etc/skel/.config/openbox/rc.xml b/.linux_items/include/live/airootfs/etc/skel/.config/openbox/rc.xml
index 6521d979..5ecc2eee 100644
--- a/.linux_items/include/live/airootfs/etc/skel/.config/openbox/rc.xml
+++ b/.linux_items/include/live/airootfs/etc/skel/.config/openbox/rc.xml
@@ -314,7 +314,7 @@
- urxvt -title "Mount all Volumes" -e mount-all-volumes foh
+ urxvt -title "Mount all Volumes" -e mount-all-volumes gui