mirror of
https://github.com/dortania/OpenCore-Legacy-Patcher.git
synced 2026-04-22 11:00:16 +10:00
gui.py: Resolve Root Volume Support
This commit is contained in:
327
gui/gui_main.py
327
gui/gui_main.py
@@ -7,8 +7,10 @@ import sys
|
|||||||
import webbrowser
|
import webbrowser
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
|
import os
|
||||||
|
import wx.adv
|
||||||
|
|
||||||
from resources import constants, defaults, build, install, installer, utilities, sys_patch_detect
|
from resources import constants, defaults, build, install, installer, utilities, sys_patch_detect, sys_patch, run
|
||||||
from data import model_array, os_data, smbios_data
|
from data import model_array, os_data, smbios_data
|
||||||
from gui import menu_redirect
|
from gui import menu_redirect
|
||||||
|
|
||||||
@@ -21,6 +23,7 @@ class wx_python_gui:
|
|||||||
|
|
||||||
# Backup stdout for usage with wxPython
|
# Backup stdout for usage with wxPython
|
||||||
self.stock_stdout = sys.stdout
|
self.stock_stdout = sys.stdout
|
||||||
|
self.stock_stderr = sys.stderr
|
||||||
|
|
||||||
# Define Window Size
|
# Define Window Size
|
||||||
self.WINDOW_WIDTH_MAIN = 350
|
self.WINDOW_WIDTH_MAIN = 350
|
||||||
@@ -56,9 +59,94 @@ class wx_python_gui:
|
|||||||
self.frame.DestroyChildren()
|
self.frame.DestroyChildren()
|
||||||
self.frame.SetSize(self.WINDOW_WIDTH_MAIN, self.WINDOW_HEIGHT_MAIN)
|
self.frame.SetSize(self.WINDOW_WIDTH_MAIN, self.WINDOW_HEIGHT_MAIN)
|
||||||
sys.stdout = self.stock_stdout
|
sys.stdout = self.stock_stdout
|
||||||
|
sys.stderr = self.stock_stderr
|
||||||
|
|
||||||
def print_test(self, text):
|
def relaunch_as_root(self, event=None):
|
||||||
print(text)
|
|
||||||
|
# Add Dialog Box asking if it's ok to relaunch as root
|
||||||
|
# If yes, relaunch as root
|
||||||
|
# If no, do nothing
|
||||||
|
|
||||||
|
# Create Dialog Box
|
||||||
|
self.dialog = wx.MessageDialog(
|
||||||
|
self.frame,
|
||||||
|
"OpenCore Legacy Patcher needs to relaunch as admin to continue. You will be prompted to enter your password.",
|
||||||
|
"Relaunch as root?",
|
||||||
|
wx.YES_NO | wx.ICON_QUESTION
|
||||||
|
)
|
||||||
|
|
||||||
|
# Show Dialog Box
|
||||||
|
if self.dialog.ShowModal() == wx.ID_YES:
|
||||||
|
print("Relaunching as root")
|
||||||
|
if self.constants.launcher_script is None:
|
||||||
|
args_string = f"{self.constants.launcher_binary}"""
|
||||||
|
else:
|
||||||
|
args_string = f"{self.constants.launcher_binary} {self.constants.launcher_script}"
|
||||||
|
|
||||||
|
args = [
|
||||||
|
"osascript",
|
||||||
|
"-e",
|
||||||
|
f'''do shell script "{args_string}"'''
|
||||||
|
' with prompt "OpenCore Legacy Patcher needs administrator privileges to mount your EFI."'
|
||||||
|
" with administrator privileges"
|
||||||
|
" without altering line endings",
|
||||||
|
]
|
||||||
|
|
||||||
|
self.frame.DestroyChildren()
|
||||||
|
self.frame.SetSize(self.WINDOW_WIDTH_MAIN, self.WINDOW_HEIGHT_MAIN)
|
||||||
|
|
||||||
|
# Header
|
||||||
|
self.header = wx.StaticText(self.frame, label="Relaunching as root")
|
||||||
|
self.header.SetFont(wx.Font(18, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
|
||||||
|
self.header.Centre(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Add count down label
|
||||||
|
self.countdown_label = wx.StaticText(self.frame, label="Closing old process in 15 seconds")
|
||||||
|
self.countdown_label.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
|
||||||
|
# Set below header
|
||||||
|
self.countdown_label.SetPosition(
|
||||||
|
(
|
||||||
|
self.header.GetPosition().x + 3,
|
||||||
|
self.header.GetPosition().y + self.header.GetSize().height + 3
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.countdown_label.Centre(wx.HORIZONTAL)
|
||||||
|
# Label: You can close this window if app finished relaunching
|
||||||
|
self.countdown_label2 = wx.StaticText(self.frame, label="You can close this window if app finished relaunching")
|
||||||
|
self.countdown_label2.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
|
||||||
|
# Set below countdown label
|
||||||
|
self.countdown_label2.SetPosition(
|
||||||
|
(
|
||||||
|
self.countdown_label.GetPosition().x,
|
||||||
|
self.countdown_label.GetPosition().y + self.countdown_label.GetSize().height + 3
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.countdown_label2.Centre(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Set frame right below countdown label
|
||||||
|
self.frame.SetSize(
|
||||||
|
(
|
||||||
|
-1,
|
||||||
|
self.countdown_label2.GetPosition().y + self.countdown_label2.GetSize().height + 40
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
wx.GetApp().Yield()
|
||||||
|
subprocess.Popen(
|
||||||
|
args,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT
|
||||||
|
)
|
||||||
|
timer_val = 15
|
||||||
|
while True:
|
||||||
|
wx.GetApp().Yield()
|
||||||
|
self.countdown_label.SetLabel(f"Closing old process in {timer_val} seconds")
|
||||||
|
time.sleep(1)
|
||||||
|
timer_val -= 1
|
||||||
|
if timer_val == 0:
|
||||||
|
break
|
||||||
|
# Close Current Application
|
||||||
|
self.frame.Close()
|
||||||
|
|
||||||
def not_yet_implemented_menu(self, event=None):
|
def not_yet_implemented_menu(self, event=None):
|
||||||
self.frame.DestroyChildren()
|
self.frame.DestroyChildren()
|
||||||
@@ -263,6 +351,8 @@ class wx_python_gui:
|
|||||||
# Reset Data in the event of re-run
|
# Reset Data in the event of re-run
|
||||||
self.reset_window()
|
self.reset_window()
|
||||||
|
|
||||||
|
# Set header text
|
||||||
|
self.frame.SetTitle(f"OpenCore Legacy Patcher v{self.constants.patcher_version}")
|
||||||
# Header
|
# Header
|
||||||
self.header = wx.StaticText(self.frame, label=f"OpenCore Legacy Patcher v{self.constants.patcher_version}")
|
self.header = wx.StaticText(self.frame, label=f"OpenCore Legacy Patcher v{self.constants.patcher_version}")
|
||||||
self.header.SetFont(wx.Font(18, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
|
self.header.SetFont(wx.Font(18, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
|
||||||
@@ -499,6 +589,7 @@ class wx_python_gui:
|
|||||||
self.stdout_text.Centre(wx.HORIZONTAL)
|
self.stdout_text.Centre(wx.HORIZONTAL)
|
||||||
self.stdout_text.SetValue("")
|
self.stdout_text.SetValue("")
|
||||||
sys.stdout=menu_redirect.RedirectText(self.stdout_text)
|
sys.stdout=menu_redirect.RedirectText(self.stdout_text)
|
||||||
|
sys.stderr=menu_redirect.RedirectText(self.stdout_text)
|
||||||
|
|
||||||
# Return to Main Menu
|
# Return to Main Menu
|
||||||
self.return_to_main_menu = wx.Button(self.frame, label="Return to Main Menu")
|
self.return_to_main_menu = wx.Button(self.frame, label="Return to Main Menu")
|
||||||
@@ -519,6 +610,7 @@ class wx_python_gui:
|
|||||||
|
|
||||||
# Reset stdout
|
# Reset stdout
|
||||||
sys.stdout = self.stock_stdout
|
sys.stdout = self.stock_stdout
|
||||||
|
sys.stderr = self.stock_stderr
|
||||||
|
|
||||||
def install_menu(self, event=None):
|
def install_menu(self, event=None):
|
||||||
self.frame.DestroyChildren()
|
self.frame.DestroyChildren()
|
||||||
@@ -666,6 +758,7 @@ class wx_python_gui:
|
|||||||
self.stdout_text.Centre(wx.HORIZONTAL)
|
self.stdout_text.Centre(wx.HORIZONTAL)
|
||||||
self.stdout_text.SetValue("")
|
self.stdout_text.SetValue("")
|
||||||
sys.stdout=menu_redirect.RedirectText(self.stdout_text)
|
sys.stdout=menu_redirect.RedirectText(self.stdout_text)
|
||||||
|
sys.stderr=menu_redirect.RedirectText(self.stdout_text)
|
||||||
|
|
||||||
# Update frame height to right below
|
# Update frame height to right below
|
||||||
self.frame.SetSize(self.WINDOW_WIDTH_BUILD, self.stdout_text.GetPosition().y + self.stdout_text.GetSize().height + 40)
|
self.frame.SetSize(self.WINDOW_WIDTH_BUILD, self.stdout_text.GetPosition().y + self.stdout_text.GetSize().height + 40)
|
||||||
@@ -700,7 +793,7 @@ class wx_python_gui:
|
|||||||
self.frame.DestroyChildren()
|
self.frame.DestroyChildren()
|
||||||
|
|
||||||
# Header
|
# Header
|
||||||
self.header = wx.StaticText(self.frame, label="Post-Install Menu")
|
self.header = wx.StaticText(self.frame, label=f"Post-Install Menu")
|
||||||
self.header.SetFont(wx.Font(18, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
|
self.header.SetFont(wx.Font(18, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
|
||||||
self.header.Centre(wx.HORIZONTAL)
|
self.header.Centre(wx.HORIZONTAL)
|
||||||
|
|
||||||
@@ -755,7 +848,12 @@ class wx_python_gui:
|
|||||||
self.patch_label.GetPosition().y + self.patch_label.GetSize().height + 10
|
self.patch_label.GetPosition().y + self.patch_label.GetSize().height + 10
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.start_root_patching.Bind(wx.EVT_BUTTON, self.not_yet_implemented_menu)
|
uid = os.geteuid()
|
||||||
|
print(f"Effective UID: {uid}")
|
||||||
|
if uid == 0:
|
||||||
|
self.start_root_patching.Bind(wx.EVT_BUTTON, self.root_patch_start)
|
||||||
|
else:
|
||||||
|
self.start_root_patching.Bind(wx.EVT_BUTTON, self.relaunch_as_root)
|
||||||
self.start_root_patching.Centre(wx.HORIZONTAL)
|
self.start_root_patching.Centre(wx.HORIZONTAL)
|
||||||
if not patches:
|
if not patches:
|
||||||
self.start_root_patching.Disable()
|
self.start_root_patching.Disable()
|
||||||
@@ -768,7 +866,10 @@ class wx_python_gui:
|
|||||||
self.start_root_patching.GetPosition().y + self.start_root_patching.GetSize().height + 3
|
self.start_root_patching.GetPosition().y + self.start_root_patching.GetSize().height + 3
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.revert_root_patches.Bind(wx.EVT_BUTTON, self.root_patch_revert)
|
if uid == 0:
|
||||||
|
self.revert_root_patches.Bind(wx.EVT_BUTTON, self.root_patch_revert)
|
||||||
|
else:
|
||||||
|
self.revert_root_patches.Bind(wx.EVT_BUTTON, self.relaunch_as_root)
|
||||||
self.revert_root_patches.Centre(wx.HORIZONTAL)
|
self.revert_root_patches.Centre(wx.HORIZONTAL)
|
||||||
if self.constants.detected_os < os_data.os_data.big_sur:
|
if self.constants.detected_os < os_data.os_data.big_sur:
|
||||||
self.revert_root_patches.Disable()
|
self.revert_root_patches.Disable()
|
||||||
@@ -808,7 +909,7 @@ class wx_python_gui:
|
|||||||
)
|
)
|
||||||
self.subheader.Centre(wx.HORIZONTAL)
|
self.subheader.Centre(wx.HORIZONTAL)
|
||||||
|
|
||||||
self.developer_note = wx.StaticText(self.frame, label="Developer Note: OCLP-CLI output will print after finishing")
|
self.developer_note = wx.StaticText(self.frame, label="Starting shortly")
|
||||||
self.developer_note.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
|
self.developer_note.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
|
||||||
self.developer_note.SetPosition(
|
self.developer_note.SetPosition(
|
||||||
wx.Point(
|
wx.Point(
|
||||||
@@ -830,7 +931,7 @@ class wx_python_gui:
|
|||||||
self.text_box.SetSize(
|
self.text_box.SetSize(
|
||||||
wx.Size(
|
wx.Size(
|
||||||
self.frame.GetSize().width - 10,
|
self.frame.GetSize().width - 10,
|
||||||
self.frame.GetSize().height - self.text_box.GetPosition().y + 40
|
self.frame.GetSize().height + self.text_box.GetPosition().y + 80
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.text_box.Centre(wx.HORIZONTAL)
|
self.text_box.Centre(wx.HORIZONTAL)
|
||||||
@@ -850,27 +951,16 @@ class wx_python_gui:
|
|||||||
self.frame.SetSize(-1, self.return_to_main_menu.GetPosition().y + self.return_to_main_menu.GetSize().height + 40)
|
self.frame.SetSize(-1, self.return_to_main_menu.GetPosition().y + self.return_to_main_menu.GetSize().height + 40)
|
||||||
|
|
||||||
wx.GetApp().Yield()
|
wx.GetApp().Yield()
|
||||||
if self.constants.launcher_script is None:
|
|
||||||
self.text_box.AppendText("- Starting OCLP-CLI via Binary\n")
|
sys.stdout = menu_redirect.RedirectText(self.text_box)
|
||||||
args = [self.constants.oclp_helper_path, self.constants.launcher_binary, "--patch_sys_vol"]
|
sys.stderr = menu_redirect.RedirectText(self.text_box)
|
||||||
else:
|
wx.GetApp().Yield()
|
||||||
self.text_box.AppendText("- Starting OCLP-CLI via Python\n")
|
self.frame.Show()
|
||||||
args = [self.constants.oclp_helper_path, self.constants.launcher_binary, self.constants.launcher_script, "--patch_sys_vol"]
|
sys_patch.PatchSysVolume(self.constants.custom_model or self.constants.computer.real_model, self.constants).start_patch()
|
||||||
process = subprocess.Popen(
|
sys.stdout = self.stock_stdout
|
||||||
args,
|
sys.stderr = self.stock_stderr
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
stderr=subprocess.STDOUT
|
|
||||||
)
|
|
||||||
wx.GetApp().Yield()
|
wx.GetApp().Yield()
|
||||||
while True:
|
|
||||||
line = process.stdout.readline()
|
|
||||||
wx.GetApp().Yield()
|
|
||||||
if line.strip() == "":
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
self.text_box.AppendText(line)
|
|
||||||
if not line: break
|
|
||||||
process.wait()
|
|
||||||
|
|
||||||
def root_patch_revert(self, event=None):
|
def root_patch_revert(self, event=None):
|
||||||
self.frame.DestroyChildren()
|
self.frame.DestroyChildren()
|
||||||
@@ -896,7 +986,7 @@ class wx_python_gui:
|
|||||||
)
|
)
|
||||||
self.subheader.Centre(wx.HORIZONTAL)
|
self.subheader.Centre(wx.HORIZONTAL)
|
||||||
|
|
||||||
self.developer_note = wx.StaticText(self.frame, label="Developer Note: OCLP-CLI output will print after finishing")
|
self.developer_note = wx.StaticText(self.frame, label="Starting shortly")
|
||||||
self.developer_note.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
|
self.developer_note.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
|
||||||
self.developer_note.SetPosition(
|
self.developer_note.SetPosition(
|
||||||
wx.Point(
|
wx.Point(
|
||||||
@@ -918,7 +1008,7 @@ class wx_python_gui:
|
|||||||
self.text_box.SetSize(
|
self.text_box.SetSize(
|
||||||
wx.Size(
|
wx.Size(
|
||||||
self.frame.GetSize().width - 10,
|
self.frame.GetSize().width - 10,
|
||||||
self.frame.GetSize().height - self.text_box.GetPosition().y + 40
|
self.frame.GetSize().height + self.text_box.GetPosition().y + 80
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.text_box.Centre(wx.HORIZONTAL)
|
self.text_box.Centre(wx.HORIZONTAL)
|
||||||
@@ -938,31 +1028,14 @@ class wx_python_gui:
|
|||||||
self.frame.SetSize(-1, self.return_to_main_menu.GetPosition().y + self.return_to_main_menu.GetSize().height + 40)
|
self.frame.SetSize(-1, self.return_to_main_menu.GetPosition().y + self.return_to_main_menu.GetSize().height + 40)
|
||||||
|
|
||||||
# Start reverting root patches
|
# Start reverting root patches
|
||||||
# Grab binary path, launch second instance as CLI
|
sys.stdout = menu_redirect.RedirectText(self.text_box)
|
||||||
# This is the cleanest way to implement admin root patching without either seperating OCLP or including duplicate code
|
sys.stderr = menu_redirect.RedirectText(self.text_box)
|
||||||
wx.GetApp().Yield()
|
wx.GetApp().Yield()
|
||||||
if self.constants.launcher_script is None:
|
sys_patch.PatchSysVolume(self.constants.custom_model or self.constants.computer.real_model, self.constants).start_unpatch()
|
||||||
self.text_box.AppendText("- Starting OCLP-CLI via Binary\n")
|
sys.stdout = self.stock_stdout
|
||||||
args = [self.constants.oclp_helper_path, self.constants.launcher_binary, "--unpatch_sys_vol"]
|
sys.stderr = self.stock_stderr
|
||||||
else:
|
|
||||||
self.text_box.AppendText("- Starting OCLP-CLI via Python\n")
|
|
||||||
args = [self.constants.oclp_helper_path, self.constants.launcher_binary, self.constants.launcher_script, "--unpatch_sys_vol"]
|
|
||||||
process = subprocess.Popen(
|
|
||||||
args,
|
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
stderr=subprocess.STDOUT
|
|
||||||
)
|
|
||||||
wx.GetApp().Yield()
|
wx.GetApp().Yield()
|
||||||
while True:
|
|
||||||
line = process.stdout.readline()
|
|
||||||
wx.GetApp().Yield()
|
|
||||||
if line.strip() == "":
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
self.text_box.AppendText(line)
|
|
||||||
if not line: break
|
|
||||||
|
|
||||||
process.wait()
|
|
||||||
|
|
||||||
def create_macos_menu(self, event=None):
|
def create_macos_menu(self, event=None):
|
||||||
# Define Menu
|
# Define Menu
|
||||||
@@ -1162,8 +1235,10 @@ class wx_python_gui:
|
|||||||
|
|
||||||
# Update Label:
|
# Update Label:
|
||||||
sys.stdout=menu_redirect.RedirectLabelAll(self.download_label)
|
sys.stdout=menu_redirect.RedirectLabelAll(self.download_label)
|
||||||
|
sys.stderr=menu_redirect.RedirectLabelAll(self.download_label)
|
||||||
installer.install_macOS_installer(self.constants.payload_path)
|
installer.install_macOS_installer(self.constants.payload_path)
|
||||||
sys.stdout = self.stock_stdout
|
sys.stdout = self.stock_stdout
|
||||||
|
sys.stderr = self.stock_stderr
|
||||||
# Update Label:
|
# Update Label:
|
||||||
self.download_label.SetLabel(f"Finished Installing {installer_name}")
|
self.download_label.SetLabel(f"Finished Installing {installer_name}")
|
||||||
self.download_label.Centre(wx.HORIZONTAL)
|
self.download_label.Centre(wx.HORIZONTAL)
|
||||||
@@ -1383,34 +1458,14 @@ class wx_python_gui:
|
|||||||
print("- Starting creation script as admin")
|
print("- Starting creation script as admin")
|
||||||
wx.GetApp().Yield()
|
wx.GetApp().Yield()
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
sys.stdout=menu_redirect.RedirectText(self.stdout_text)
|
args = [self.constants.oclp_helper_path, "/bin/sh", self.constants.installer_sh_path]
|
||||||
cim_start = subprocess.Popen(
|
sys.stdout = menu_redirect.RedirectText(self.stdout_text)
|
||||||
[self.constants.oclp_helper_path, "/bin/sh", self.constants.installer_sh_path],
|
sys.stderr = menu_redirect.RedirectText(self.stdout_text)
|
||||||
stdout=subprocess.PIPE,
|
run.Run()._stream_output(comm=args)
|
||||||
stderr=subprocess.STDOUT
|
|
||||||
)
|
|
||||||
|
|
||||||
wx.GetApp().Yield()
|
|
||||||
while True:
|
|
||||||
line = cim_start.stdout.readline()
|
|
||||||
wx.GetApp().Yield()
|
|
||||||
if line.strip() == "":
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
self.stdout_text.AppendText(line)
|
|
||||||
if not line: break
|
|
||||||
|
|
||||||
cim_start.wait()
|
|
||||||
|
|
||||||
if cim_start.returncode == 0:
|
|
||||||
print("Installer created successfully!")
|
|
||||||
else:
|
|
||||||
print("Installer creation failed")
|
|
||||||
print(f"Return Code {cim_start.returncode}")
|
|
||||||
sys.stdout = self.stock_stdout
|
|
||||||
else:
|
else:
|
||||||
print("- Failed to create installer script")
|
print("- Failed to create installer script")
|
||||||
sys.stdout = self.stock_stdout
|
sys.stdout = self.stock_stdout
|
||||||
|
sys.stderr = self.stock_stderr
|
||||||
|
|
||||||
|
|
||||||
def settings_menu(self, event=None):
|
def settings_menu(self, event=None):
|
||||||
@@ -1430,7 +1485,7 @@ class wx_python_gui:
|
|||||||
|
|
||||||
self.frame.DestroyChildren()
|
self.frame.DestroyChildren()
|
||||||
self.frame.SetSize(self.WINDOW_SETTINGS_WIDTH, self.WINDOW_SETTINGS_HEIGHT)
|
self.frame.SetSize(self.WINDOW_SETTINGS_WIDTH, self.WINDOW_SETTINGS_HEIGHT)
|
||||||
self.frame.SetLabel("Settings")
|
self.frame.SetTitle("Settings")
|
||||||
|
|
||||||
# Header
|
# Header
|
||||||
self.header = wx.StaticText(self.frame, label="Settings")
|
self.header = wx.StaticText(self.frame, label="Settings")
|
||||||
@@ -1769,12 +1824,20 @@ class wx_python_gui:
|
|||||||
self.apple_alc_checkbox.GetPosition().x,
|
self.apple_alc_checkbox.GetPosition().x,
|
||||||
self.apple_alc_checkbox.GetPosition().y + self.apple_alc_checkbox.GetSize().height))
|
self.apple_alc_checkbox.GetPosition().y + self.apple_alc_checkbox.GetSize().height))
|
||||||
|
|
||||||
|
# Button: Developer Debug Info
|
||||||
|
self.debug_button = wx.Button(self.frame, label="Developer Debug Info")
|
||||||
|
self.debug_button.Bind(wx.EVT_BUTTON, self.additional_info_menu)
|
||||||
|
self.debug_button.SetPosition(wx.Point(
|
||||||
|
self.set_writeflash_checkbox.GetPosition().x,
|
||||||
|
self.set_writeflash_checkbox.GetPosition().y + self.set_writeflash_checkbox.GetSize().height))
|
||||||
|
self.debug_button.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
# Button: return to main menu
|
# Button: return to main menu
|
||||||
self.return_to_main_menu_button = wx.Button(self.frame, label="Return to Main Menu")
|
self.return_to_main_menu_button = wx.Button(self.frame, label="Return to Main Menu")
|
||||||
self.return_to_main_menu_button.Bind(wx.EVT_BUTTON, self.main_menu)
|
self.return_to_main_menu_button.Bind(wx.EVT_BUTTON, self.main_menu)
|
||||||
self.return_to_main_menu_button.SetPosition(wx.Point(
|
self.return_to_main_menu_button.SetPosition(wx.Point(
|
||||||
self.set_writeflash_checkbox.GetPosition().x,
|
self.debug_button.GetPosition().x,
|
||||||
self.set_writeflash_checkbox.GetPosition().y + self.set_writeflash_checkbox.GetSize().height + 10))
|
self.debug_button.GetPosition().y + self.debug_button.GetSize().height + 10))
|
||||||
self.return_to_main_menu_button.Center(wx.HORIZONTAL)
|
self.return_to_main_menu_button.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
# set frame size below return to main menu button
|
# set frame size below return to main menu button
|
||||||
@@ -1973,3 +2036,103 @@ class wx_python_gui:
|
|||||||
selection = self.smbios_model_dropdown.GetStringSelection()
|
selection = self.smbios_model_dropdown.GetStringSelection()
|
||||||
print(f"SMBIOS Spoof Model: {selection}")
|
print(f"SMBIOS Spoof Model: {selection}")
|
||||||
self.constants.override_smbios = selection
|
self.constants.override_smbios = selection
|
||||||
|
|
||||||
|
def additional_info_menu(self, event=None):
|
||||||
|
# Define Menu:
|
||||||
|
|
||||||
|
# Header: Additional Info
|
||||||
|
# Label: Model Dump
|
||||||
|
# Textbox: Model Dump
|
||||||
|
# Label: Real User ID
|
||||||
|
# Label: Effective User ID
|
||||||
|
# Label: Launcher Binary
|
||||||
|
# Textbox: Launcher Binary
|
||||||
|
# Label: Launcher Script
|
||||||
|
# Textbox: Launcher Script
|
||||||
|
|
||||||
|
self.frame.DestroyChildren()
|
||||||
|
|
||||||
|
# Header: Additional Info
|
||||||
|
self.additional_info_header = wx.StaticText(self.frame, label="Developer Debug Info", pos=wx.Point(10, 10))
|
||||||
|
self.additional_info_header.SetFont(wx.Font(16, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
|
||||||
|
self.additional_info_header.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Label: Real User ID
|
||||||
|
self.real_user_id_label = wx.StaticText(self.frame, label=f"Current UID: {os.getuid()} - ({os.geteuid()})")
|
||||||
|
self.real_user_id_label.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
|
||||||
|
self.real_user_id_label.SetPosition(
|
||||||
|
wx.Point(self.additional_info_header.GetPosition().x, self.additional_info_header.GetPosition().y + self.additional_info_header.GetSize().height + 10)
|
||||||
|
)
|
||||||
|
self.real_user_id_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Label: Model Dump
|
||||||
|
self.model_dump_label = wx.StaticText(self.frame, label="Model Dump")
|
||||||
|
self.model_dump_label.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
|
||||||
|
self.model_dump_label.SetPosition(
|
||||||
|
wx.Point(self.real_user_id_label.GetPosition().x, self.real_user_id_label.GetPosition().y + self.real_user_id_label.GetSize().height + 10)
|
||||||
|
)
|
||||||
|
self.model_dump_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Textbox: Model Dump
|
||||||
|
self.model_dump_textbox = wx.TextCtrl(self.frame, style=wx.TE_MULTILINE, pos=wx.Point(self.model_dump_label.GetPosition().x, self.model_dump_label.GetPosition().y + self.model_dump_label.GetSize().height + 10))
|
||||||
|
self.model_dump_textbox.SetValue(str(self.constants.computer))
|
||||||
|
self.model_dump_textbox.SetPosition(
|
||||||
|
wx.Point(self.model_dump_label.GetPosition().x, self.model_dump_label.GetPosition().y + self.model_dump_label.GetSize().height + 10)
|
||||||
|
)
|
||||||
|
self.model_dump_textbox.SetSize(
|
||||||
|
wx.Size(
|
||||||
|
self.frame.GetSize().width - 5,
|
||||||
|
self.model_dump_textbox.GetSize().height + self.model_dump_textbox.GetSize().height
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.model_dump_textbox.Center(wx.HORIZONTAL)
|
||||||
|
self.model_dump_textbox.SetEditable(False)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Label: Launcher Binary
|
||||||
|
self.launcher_binary_label = wx.StaticText(self.frame, label="Launcher Binary")
|
||||||
|
self.launcher_binary_label.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
|
||||||
|
self.launcher_binary_label.SetPosition(
|
||||||
|
wx.Point(self.model_dump_textbox.GetPosition().x, self.model_dump_textbox.GetPosition().y + self.model_dump_textbox.GetSize().height + 10)
|
||||||
|
)
|
||||||
|
self.launcher_binary_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Textbox: Launcher Binary
|
||||||
|
self.launcher_binary_textbox = wx.TextCtrl(self.frame, style=wx.TE_MULTILINE, pos=wx.Point(self.launcher_binary_label.GetPosition().x, self.launcher_binary_label.GetPosition().y + self.launcher_binary_label.GetSize().height + 10))
|
||||||
|
self.launcher_binary_textbox.SetValue(self.constants.launcher_binary)
|
||||||
|
self.launcher_binary_textbox.SetPosition(
|
||||||
|
wx.Point(self.launcher_binary_label.GetPosition().x, self.launcher_binary_label.GetPosition().y + self.launcher_binary_label.GetSize().height + 10)
|
||||||
|
)
|
||||||
|
self.launcher_binary_textbox.SetSize(wx.Size(self.frame.GetSize().width - 5, 50))
|
||||||
|
self.launcher_binary_textbox.Center(wx.HORIZONTAL)
|
||||||
|
self.launcher_binary_textbox.SetEditable(False)
|
||||||
|
|
||||||
|
# Label: Launcher Script
|
||||||
|
self.launcher_script_label = wx.StaticText(self.frame, label="Launcher Script")
|
||||||
|
self.launcher_script_label.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
|
||||||
|
self.launcher_script_label.SetPosition(
|
||||||
|
wx.Point(self.launcher_binary_textbox.GetPosition().x, self.launcher_binary_textbox.GetPosition().y + self.launcher_binary_textbox.GetSize().height + 10)
|
||||||
|
)
|
||||||
|
self.launcher_script_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Textbox: Launcher Script
|
||||||
|
self.launcher_script_textbox = wx.TextCtrl(self.frame, style=wx.TE_MULTILINE, pos=wx.Point(self.launcher_script_label.GetPosition().x, self.launcher_script_label.GetPosition().y + self.launcher_script_label.GetSize().height + 10))
|
||||||
|
self.launcher_script_textbox.SetValue(str(self.constants.launcher_script))
|
||||||
|
self.launcher_script_textbox.SetPosition(
|
||||||
|
wx.Point(self.launcher_script_label.GetPosition().x, self.launcher_script_label.GetPosition().y + self.launcher_script_label.GetSize().height + 10)
|
||||||
|
)
|
||||||
|
self.launcher_script_textbox.SetSize(wx.Size(self.frame.GetSize().width - 5, 60))
|
||||||
|
self.launcher_script_textbox.Center(wx.HORIZONTAL)
|
||||||
|
self.launcher_script_textbox.SetEditable(False)
|
||||||
|
|
||||||
|
# Return to Main Menu Button
|
||||||
|
self.return_to_main_menu_button = wx.Button(self.frame, label="Return to Main Menu")
|
||||||
|
self.return_to_main_menu_button.SetPosition(
|
||||||
|
wx.Point(self.launcher_script_textbox.GetPosition().x, self.launcher_script_textbox.GetPosition().y + self.launcher_script_textbox.GetSize().height + 10)
|
||||||
|
)
|
||||||
|
self.return_to_main_menu_button.Bind(wx.EVT_BUTTON, self.main_menu)
|
||||||
|
self.return_to_main_menu_button.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Set frame below return to main menu button
|
||||||
|
self.frame.SetSize(wx.Size(-1, self.return_to_main_menu_button.GetPosition().y + self.return_to_main_menu_button.GetSize().height + 40))
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import wx
|
import wx
|
||||||
|
import time
|
||||||
|
|
||||||
class RedirectText(object):
|
class RedirectText(object):
|
||||||
def __init__(self,aWxTextCtrl):
|
def __init__(self,aWxTextCtrl):
|
||||||
@@ -7,6 +8,7 @@ class RedirectText(object):
|
|||||||
def write(self,string):
|
def write(self,string):
|
||||||
self.out.WriteText(string)
|
self.out.WriteText(string)
|
||||||
wx.GetApp().Yield()
|
wx.GetApp().Yield()
|
||||||
|
time.sleep(0.01)
|
||||||
|
|
||||||
def fileno(self):
|
def fileno(self):
|
||||||
return 1
|
return 1
|
||||||
@@ -23,6 +25,7 @@ class RedirectLabel(object):
|
|||||||
self.out.SetLabel(string)
|
self.out.SetLabel(string)
|
||||||
self.out.Centre(wx.HORIZONTAL)
|
self.out.Centre(wx.HORIZONTAL)
|
||||||
wx.GetApp().Yield()
|
wx.GetApp().Yield()
|
||||||
|
time.sleep(0.01)
|
||||||
|
|
||||||
def flush(self):
|
def flush(self):
|
||||||
pass
|
pass
|
||||||
@@ -34,4 +37,5 @@ class RedirectLabelAll(object):
|
|||||||
def write(self,string):
|
def write(self,string):
|
||||||
self.out.SetLabel(string)
|
self.out.SetLabel(string)
|
||||||
self.out.Centre(wx.HORIZONTAL)
|
self.out.Centre(wx.HORIZONTAL)
|
||||||
wx.GetApp().Yield()
|
wx.GetApp().Yield()
|
||||||
|
time.sleep(0.01)
|
||||||
155
resources/run.py
Normal file
155
resources/run.py
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
# Module for running processes with real time output
|
||||||
|
# Written by CorpNewt
|
||||||
|
# Source: https://github.com/corpnewt/pymodules/blob/884c3de15b6a2570afde52fe8a14a3e946ffb18a/run.py
|
||||||
|
|
||||||
|
import sys, subprocess, time, threading, shlex
|
||||||
|
try:
|
||||||
|
from Queue import Queue, Empty
|
||||||
|
except:
|
||||||
|
from queue import Queue, Empty
|
||||||
|
|
||||||
|
ON_POSIX = 'posix' in sys.builtin_module_names
|
||||||
|
|
||||||
|
class Run:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
return
|
||||||
|
|
||||||
|
def _read_output(self, pipe, q):
|
||||||
|
try:
|
||||||
|
for line in iter(lambda: pipe.read(1), b''):
|
||||||
|
q.put(line)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
pipe.close()
|
||||||
|
|
||||||
|
def _create_thread(self, output):
|
||||||
|
# Creates a new queue and thread object to watch based on the output pipe sent
|
||||||
|
q = Queue()
|
||||||
|
t = threading.Thread(target=self._read_output, args=(output, q))
|
||||||
|
t.daemon = True
|
||||||
|
return (q,t)
|
||||||
|
|
||||||
|
def _stream_output(self, comm, shell = False):
|
||||||
|
output = error = ""
|
||||||
|
p = None
|
||||||
|
try:
|
||||||
|
if shell and type(comm) is list:
|
||||||
|
comm = " ".join(shlex.quote(x) for x in comm)
|
||||||
|
if not shell and type(comm) is str:
|
||||||
|
comm = shlex.split(comm)
|
||||||
|
p = subprocess.Popen(comm, shell=shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=0, universal_newlines=True, close_fds=ON_POSIX)
|
||||||
|
# Setup the stdout thread/queue
|
||||||
|
q,t = self._create_thread(p.stdout)
|
||||||
|
qe,te = self._create_thread(p.stderr)
|
||||||
|
# Start both threads
|
||||||
|
t.start()
|
||||||
|
te.start()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
c = z = ""
|
||||||
|
try: c = q.get_nowait()
|
||||||
|
except Empty: pass
|
||||||
|
else:
|
||||||
|
sys.stdout.write(c)
|
||||||
|
output += c
|
||||||
|
sys.stdout.flush()
|
||||||
|
try: z = qe.get_nowait()
|
||||||
|
except Empty: pass
|
||||||
|
else:
|
||||||
|
sys.stderr.write(z)
|
||||||
|
error += z
|
||||||
|
sys.stderr.flush()
|
||||||
|
if not c==z=="": continue # Keep going until empty
|
||||||
|
# No output - see if still running
|
||||||
|
p.poll()
|
||||||
|
if p.returncode != None:
|
||||||
|
# Subprocess ended
|
||||||
|
break
|
||||||
|
# No output, but subprocess still running - stall for 20ms
|
||||||
|
time.sleep(0.02)
|
||||||
|
|
||||||
|
o, e = p.communicate()
|
||||||
|
return (output+o, error+e, p.returncode)
|
||||||
|
except:
|
||||||
|
if p:
|
||||||
|
try: o, e = p.communicate()
|
||||||
|
except: o = e = ""
|
||||||
|
return (output+o, error+e, p.returncode)
|
||||||
|
return ("", "Command not found!", 1)
|
||||||
|
|
||||||
|
def _decode(self, value, encoding="utf-8", errors="ignore"):
|
||||||
|
# Helper method to only decode if bytes type
|
||||||
|
if sys.version_info >= (3,0) and isinstance(value, bytes):
|
||||||
|
return value.decode(encoding,errors)
|
||||||
|
return value
|
||||||
|
|
||||||
|
def _run_command(self, comm, shell = False):
|
||||||
|
c = None
|
||||||
|
try:
|
||||||
|
if shell and type(comm) is list:
|
||||||
|
comm = " ".join(shlex.quote(x) for x in comm)
|
||||||
|
if not shell and type(comm) is str:
|
||||||
|
comm = shlex.split(comm)
|
||||||
|
p = subprocess.Popen(comm, shell=shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
c = p.communicate()
|
||||||
|
except:
|
||||||
|
if c == None:
|
||||||
|
return ("", "Command not found!", 1)
|
||||||
|
return (self._decode(c[0]), self._decode(c[1]), p.returncode)
|
||||||
|
|
||||||
|
def run(self, command_list, leave_on_fail = False):
|
||||||
|
# Command list should be an array of dicts
|
||||||
|
if type(command_list) is dict:
|
||||||
|
# We only have one command
|
||||||
|
command_list = [command_list]
|
||||||
|
output_list = []
|
||||||
|
for comm in command_list:
|
||||||
|
args = comm.get("args", [])
|
||||||
|
shell = comm.get("shell", False)
|
||||||
|
stream = comm.get("stream", False)
|
||||||
|
sudo = comm.get("sudo", False)
|
||||||
|
stdout = comm.get("stdout", False)
|
||||||
|
stderr = comm.get("stderr", False)
|
||||||
|
mess = comm.get("message", None)
|
||||||
|
show = comm.get("show", False)
|
||||||
|
|
||||||
|
if not mess == None:
|
||||||
|
print(mess)
|
||||||
|
|
||||||
|
if not len(args):
|
||||||
|
# nothing to process
|
||||||
|
continue
|
||||||
|
if sudo:
|
||||||
|
# Check if we have sudo
|
||||||
|
out = self._run_command(["which", "sudo"])
|
||||||
|
if "sudo" in out[0]:
|
||||||
|
# Can sudo
|
||||||
|
if type(args) is list:
|
||||||
|
args.insert(0, out[0].replace("\n", "")) # add to start of list
|
||||||
|
elif type(args) is str:
|
||||||
|
args = out[0].replace("\n", "") + " " + args # add to start of string
|
||||||
|
|
||||||
|
if show:
|
||||||
|
print(" ".join(args))
|
||||||
|
|
||||||
|
if stream:
|
||||||
|
# Stream it!
|
||||||
|
out = self._stream_output(args, shell)
|
||||||
|
else:
|
||||||
|
# Just run and gather output
|
||||||
|
out = self._run_command(args, shell)
|
||||||
|
if stdout and len(out[0]):
|
||||||
|
print(out[0])
|
||||||
|
if stderr and len(out[1]):
|
||||||
|
print(out[1])
|
||||||
|
# Append output
|
||||||
|
output_list.append(out)
|
||||||
|
# Check for errors
|
||||||
|
if leave_on_fail and out[2] != 0:
|
||||||
|
# Got an error - leave
|
||||||
|
break
|
||||||
|
if len(output_list) == 1:
|
||||||
|
# We only ran one command - just return that output
|
||||||
|
return output_list[0]
|
||||||
|
return output_list
|
||||||
@@ -83,9 +83,12 @@ class PatchSysVolume:
|
|||||||
self.unpatch_root_vol()
|
self.unpatch_root_vol()
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
|
print(f"User ID: {os.getuid()} - {os.geteuid()}")
|
||||||
if self.constants.detected_os > os_data.os_data.catalina:
|
if self.constants.detected_os > os_data.os_data.catalina:
|
||||||
print("- Mounting APFS Snapshot as writable")
|
print("- Mounting APFS Snapshot as writable")
|
||||||
utilities.elevated(["mount", "-o", "nobrowse", "-t", "apfs", f"/dev/{self.root_mount_path}", self.mount_location], stdout=subprocess.PIPE).stdout.decode().strip().encode()
|
result = utilities.elevated(["mount", "-o", "nobrowse", "-t", "apfs", f"/dev/{self.root_mount_path}", self.mount_location], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
|
if result.returncode == 0:
|
||||||
|
print(f"- Mounted APFS Snapshot as writable at: {self.mount_location}")
|
||||||
if Path(self.mount_extensions).exists():
|
if Path(self.mount_extensions).exists():
|
||||||
print("- Successfully mounted the Root Volume")
|
print("- Successfully mounted the Root Volume")
|
||||||
if patch is True:
|
if patch is True:
|
||||||
@@ -272,7 +275,7 @@ class PatchSysVolume:
|
|||||||
print(bless.stdout.decode())
|
print(bless.stdout.decode())
|
||||||
if "Can't use last-sealed-snapshot or create-snapshot on non system volume" in bless.stdout.decode():
|
if "Can't use last-sealed-snapshot or create-snapshot on non system volume" in bless.stdout.decode():
|
||||||
print("- This is an APFS bug with Monterey! Perform a clean installation to ensure your APFS volume is built correctly")
|
print("- This is an APFS bug with Monterey! Perform a clean installation to ensure your APFS volume is built correctly")
|
||||||
sys.exit(1)
|
return
|
||||||
else:
|
else:
|
||||||
self.unmount_drive()
|
self.unmount_drive()
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user