mirror of
https://github.com/corpnewt/ProperTree.git
synced 2026-08-12 22:31:30 +04:00
Add files via upload
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
@echo off
|
||||
setlocal enableDelayedExpansion
|
||||
|
||||
REM Setup initial vars
|
||||
set "script_name=%~n0.command"
|
||||
set "thisDir=%~dp0"
|
||||
|
||||
REM Check for our script first
|
||||
if not exist "!thisDir!\!script_name!" (
|
||||
echo Could not find !script_name!.
|
||||
echo Please make sure to run this script from the same directory
|
||||
echo as !script_name!.
|
||||
echo.
|
||||
echo Press [enter] to quit.
|
||||
pause > nul
|
||||
exit /b
|
||||
)
|
||||
|
||||
REM Get python location
|
||||
FOR /F "tokens=* USEBACKQ" %%F IN (`where python 2^> nul`) DO (
|
||||
SET "python=%%F"
|
||||
)
|
||||
|
||||
REM Check for py and give helpful hints!
|
||||
if /i "!python!"=="" (
|
||||
echo Python is not installed or not found in your PATH var.
|
||||
echo Please install it from https://www.python.org/downloads/windows/
|
||||
echo.
|
||||
echo Make sure you check the box labeled:
|
||||
echo.
|
||||
echo "Add Python X.X to PATH"
|
||||
echo.
|
||||
echo Where X.X is the py version you're installing.
|
||||
echo.
|
||||
echo Press [enter] to quit.
|
||||
pause > nul
|
||||
exit /b
|
||||
)
|
||||
|
||||
REM Python found
|
||||
if "%*"=="" (
|
||||
"!python!" "!thisDir!!script_name!"
|
||||
) else (
|
||||
"!python!" "!thisDir!!script_name!" %*
|
||||
)
|
||||
@@ -0,0 +1,364 @@
|
||||
#!/usr/bin/env python
|
||||
import sys, os, binascii, base64
|
||||
try:
|
||||
import Tkinter as tk
|
||||
import ttk
|
||||
import tkFileDialog as fd
|
||||
import tkMessageBox as mb
|
||||
except:
|
||||
import tkinter as tk
|
||||
import tkinter.ttk as ttk
|
||||
from tkinter import filedialog as fd
|
||||
from tkinter import messagebox as mb
|
||||
from Scripts import *
|
||||
|
||||
class ProperTree:
|
||||
def __init__(self):
|
||||
# Create the new tk object
|
||||
self.tk = tk.Tk()
|
||||
self.tk.title("Convert Values")
|
||||
self.tk.minsize(width=640,height=130)
|
||||
self.tk.resizable(False, False)
|
||||
# self.tk.columnconfigure(2,weight=1)
|
||||
# Build the Hex <--> Base64 converter
|
||||
f_label = tk.Label(self.tk, text="From:")
|
||||
f_label.grid(row=0,column=0)
|
||||
t_label = tk.Label(self.tk, text="To:")
|
||||
t_label.grid(row=1,column=0)
|
||||
# Setup the from/to option menus
|
||||
f_title = tk.StringVar(self.tk)
|
||||
t_title = tk.StringVar(self.tk)
|
||||
f_title.set("Base64")
|
||||
t_title.set("Hex")
|
||||
f_option = tk.OptionMenu(self.tk, f_title, "Ascii", "Base64", "Hex", command=self.change_from_type)
|
||||
t_option = tk.OptionMenu(self.tk, t_title, "Ascii", "Base64", "Hex", command=self.change_to_type)
|
||||
self.from_type = "Base64"
|
||||
self.to_type = "Hex"
|
||||
f_option.grid(row=0,column=1,sticky="we")
|
||||
t_option.grid(row=1,column=1,sticky="we")
|
||||
|
||||
self.f_text = tk.Entry(self.tk,width=80)
|
||||
self.f_text.delete(0,tk.END)
|
||||
self.f_text.insert(0,"")
|
||||
self.f_text.grid(row=0,column=2,sticky="we",padx=10,pady=10)
|
||||
|
||||
self.t_text = tk.Entry(self.tk,width=80)
|
||||
self.t_text.configure(state='normal')
|
||||
self.t_text.delete(0,tk.END)
|
||||
self.t_text.insert(0,"")
|
||||
self.t_text.configure(state='readonly')
|
||||
self.t_text.grid(row=1,column=2,sticky="we",padx=10,pady=10)
|
||||
|
||||
self.c_button = tk.Button(self.tk, text="Convert", command=self.convert_values)
|
||||
self.c_button.grid(row=2,column=2,sticky="e",padx=10,pady=10)
|
||||
|
||||
self.tk.bind("<Return>", self.convert_values)
|
||||
self.tk.bind("<KP_Enter>", self.convert_values)
|
||||
|
||||
self.clipboard = None
|
||||
|
||||
# Setup the menu-related keybinds - and change the app name if needed
|
||||
key="Control"
|
||||
sign = "Ctr+"
|
||||
if str(sys.platform) == "darwin":
|
||||
# Remap the quit function to our own
|
||||
self.tk.createcommand('::tk::mac::Quit', self.quit)
|
||||
# Import the needed modules to change the bundle name and force focus
|
||||
try:
|
||||
from Foundation import NSBundle
|
||||
from Cocoa import NSRunningApplication, NSApplicationActivateIgnoringOtherApps
|
||||
app = NSRunningApplication.runningApplicationWithProcessIdentifier_(os.getpid())
|
||||
app.activateWithOptions_(NSApplicationActivateIgnoringOtherApps)
|
||||
bundle = NSBundle.mainBundle()
|
||||
if bundle:
|
||||
info = bundle.localizedInfoDictionary() or bundle.infoDictionary()
|
||||
if info and info['CFBundleName'] == 'Python':
|
||||
info['CFBundleName'] = "ProperTree"
|
||||
except:
|
||||
pass
|
||||
key="Command"
|
||||
sign=key+"+"
|
||||
|
||||
self.tk.protocol("WM_DELETE_WINDOW", self.close_window)
|
||||
# Close initial window
|
||||
self.close_window(None,False)
|
||||
|
||||
# Setup the top level menu
|
||||
file_menu = tk.Menu(self.tk)
|
||||
main_menu = tk.Menu(self.tk)
|
||||
main_menu.add_cascade(label="File", menu=file_menu)
|
||||
file_menu.add_command(label="New ({}N)".format(sign), command=self.new_plist)
|
||||
file_menu.add_command(label="Open ({}O)".format(sign), command=self.open_plist)
|
||||
file_menu.add_command(label="Save ({}S)".format(sign), command=self.save_plist)
|
||||
file_menu.add_command(label="Save As ({}Shift+S)".format(sign), command=self.save_plist_as)
|
||||
file_menu.add_command(label="Duplicate ({}D)".format(sign), command=self.duplicate_plist)
|
||||
file_menu.add_separator()
|
||||
file_menu.add_command(label="Convert Window ({}T)".format(sign), command=self.show_convert)
|
||||
file_menu.add_command(label="Strip Comments ({}M)".format(sign), command=self.strip_comments)
|
||||
file_menu.add_separator()
|
||||
file_menu.add_command(label="View Data As Hex", command=lambda:self.change_data_display("hex"))
|
||||
file_menu.add_command(label="View Data As Base64", command=lambda:self.change_data_display("base64"))
|
||||
if not str(sys.platform) == "darwin":
|
||||
file_menu.add_separator()
|
||||
file_menu.add_command(label="Quit ({}Q)".format(sign), command=self.quit)
|
||||
self.tk.config(menu=main_menu)
|
||||
|
||||
# Set bindings
|
||||
self.tk.bind_all("<{}-n>".format(key), self.new_plist)
|
||||
self.tk.bind_all("<{}-o>".format(key), self.open_plist)
|
||||
self.tk.bind_all("<{}-s>".format(key), self.save_plist)
|
||||
self.tk.bind_all("<{}-S>".format(key), self.save_plist_as)
|
||||
self.tk.bind_all("<{}-d>".format(key), self.duplicate_plist)
|
||||
self.tk.bind_all("<{}-c>".format(key), self.copy_selection)
|
||||
self.tk.bind_all("<{}-v>".format(key), self.paste_selection)
|
||||
self.tk.bind_all("<{}-t>".format(key), self.show_convert)
|
||||
self.tk.bind_all("<{}-z>".format(key), self.undo)
|
||||
self.tk.bind_all("<{}-Z>".format(key), self.redo)
|
||||
self.tk.bind_all("<{}-m>".format(key), self.strip_comments)
|
||||
if not str(sys.platform) == "darwin":
|
||||
# Rewrite the default Command-Q command
|
||||
self.tk.bind_all("<{}-q>".format(key), self.quit)
|
||||
|
||||
# create a fresh plist to start
|
||||
self.start_window = self.new_plist()
|
||||
|
||||
# Start our run loop
|
||||
tk.mainloop()
|
||||
|
||||
def change_data_display(self, new_data = None):
|
||||
windows = self.stackorder(self.tk)
|
||||
if not len(windows):
|
||||
# Nothing to save
|
||||
return
|
||||
window = windows[-1] # Get the last item (most recent)
|
||||
if window == self.tk:
|
||||
return
|
||||
window.change_data_display(new_data)
|
||||
|
||||
def close_window(self, event = None, check_close = True):
|
||||
# Remove the default window that comes from it
|
||||
if str(sys.platform) == "darwin":
|
||||
self.tk.iconify()
|
||||
else:
|
||||
self.tk.withdraw()
|
||||
if check_close:
|
||||
windows = self.stackorder(self.tk)
|
||||
if not len(windows):
|
||||
# Quit if all windows are closed
|
||||
self.quit()
|
||||
|
||||
def strip_comments(self, event = None):
|
||||
windows = self.stackorder(self.tk)
|
||||
if not len(windows):
|
||||
# Nothing to save
|
||||
return
|
||||
window = windows[-1] # Get the last item (most recent)
|
||||
if window == self.tk:
|
||||
return
|
||||
window.strip_comments(event)
|
||||
|
||||
def change_to_type(self, value):
|
||||
self.to_type = value
|
||||
self.convert_values()
|
||||
|
||||
def change_from_type(self, value):
|
||||
self.from_type = value
|
||||
|
||||
def show_convert(self, event = None):
|
||||
self.tk.deiconify()
|
||||
|
||||
def convert_values(self, event = None):
|
||||
from_value = self.f_text.get()
|
||||
if not len(from_value):
|
||||
# Empty - nothing to convert
|
||||
return
|
||||
# Pre-check for hex potential issues
|
||||
if self.from_type.lower() == "hex":
|
||||
if from_value.lower().startswith("0x"):
|
||||
from_value = from_value[2:]
|
||||
from_value = from_value.replace(" ","")
|
||||
if [x for x in from_value if x.lower() not in "0123456789abcdef"]:
|
||||
self.tk.bell()
|
||||
if not mb.showerror("Invalid Hex Data","Invalid character in passed hex data.",parent=self.tk):
|
||||
return
|
||||
try:
|
||||
# Handle the from data
|
||||
if sys.version_info >= (3,0):
|
||||
# Convert to bytes
|
||||
from_value = from_value.encode("utf-8")
|
||||
if self.from_type.lower() == "base64":
|
||||
from_value = base64.b64decode(from_value)
|
||||
elif self.from_type.lower() == "hex":
|
||||
from_value = binascii.unhexlify(from_value)
|
||||
# Let's get the data converted
|
||||
to_value = from_value
|
||||
if self.to_type.lower() == "base64":
|
||||
to_value = base64.b64encode(from_value)
|
||||
elif self.to_type.lower() == "hex":
|
||||
to_value = binascii.hexlify(from_value)
|
||||
if sys.version_info >= (3,0):
|
||||
# Convert to bytes
|
||||
to_value = to_value.decode("utf-8")
|
||||
if self.to_type.lower() == "hex":
|
||||
# Capitalize it, and pad with spaces
|
||||
to_value = "{}".format(" ".join((to_value[0+i:8+i] for i in range(0, len(to_value), 8))).upper())
|
||||
# Set the text box
|
||||
self.t_text.configure(state='normal')
|
||||
self.t_text.delete(0,tk.END)
|
||||
self.t_text.insert(0,to_value)
|
||||
self.t_text.configure(state='readonly')
|
||||
except Exception as e:
|
||||
self.tk.bell()
|
||||
mb.showerror("Conversion Error",str(e),parent=self.tk)
|
||||
|
||||
### ###
|
||||
# Save/Load Plist Functions #
|
||||
### ###
|
||||
|
||||
def copy_selection(self, event = None):
|
||||
windows = self.stackorder(self.tk)
|
||||
if not len(windows):
|
||||
# Nothing to save
|
||||
return
|
||||
window = windows[-1] # Get the last item (most recent)
|
||||
if window == self.tk:
|
||||
return
|
||||
node = window._tree.focus()
|
||||
if node == "":
|
||||
# Nothing to copy
|
||||
return
|
||||
self.clipboard = window.nodes_to_values(node,{})
|
||||
|
||||
def paste_selection(self, event = None):
|
||||
if self.clipboard == None:
|
||||
return
|
||||
windows = self.stackorder(self.tk)
|
||||
if not len(windows):
|
||||
# Nothing to save
|
||||
return
|
||||
window = windows[-1] # Get the last item (most recent)
|
||||
if window == self.tk:
|
||||
return
|
||||
window.paste_selection(self.clipboard)
|
||||
|
||||
def duplicate_plist(self, event = None):
|
||||
windows = self.stackorder(self.tk)
|
||||
if not len(windows):
|
||||
# Nothing to save
|
||||
return
|
||||
window = windows[-1] # Get the last item (most recent)
|
||||
if window == self.tk:
|
||||
return
|
||||
plist_data = window.nodes_to_values()
|
||||
plistwindow.PlistWindow(self, self.tk).open_plist(None,plist_data)
|
||||
|
||||
def save_plist(self, event = None):
|
||||
windows = self.stackorder(self.tk)
|
||||
if not len(windows):
|
||||
# Nothing to save
|
||||
return
|
||||
window = windows[-1] # Get the last item (most recent)
|
||||
if window == self.tk:
|
||||
return
|
||||
window.save_plist(event)
|
||||
|
||||
def save_plist_as(self, event = None):
|
||||
windows = self.stackorder(self.tk)
|
||||
if not len(windows):
|
||||
# Nothing to save
|
||||
return
|
||||
window = windows[-1] # Get the last item (most recent)
|
||||
if window == self.tk:
|
||||
return
|
||||
window.save_plist_as(event)
|
||||
|
||||
def undo(self, event = None):
|
||||
windows = self.stackorder(self.tk)
|
||||
if not len(windows):
|
||||
# Nothing to save
|
||||
return
|
||||
window = windows[-1] # Get the last item (most recent)
|
||||
if window == self.tk:
|
||||
return
|
||||
window.reundo(event)
|
||||
|
||||
def redo(self, event = None):
|
||||
windows = self.stackorder(self.tk)
|
||||
if not len(windows):
|
||||
# Nothing to save
|
||||
return
|
||||
window = windows[-1] # Get the last item (most recent)
|
||||
if window == self.tk:
|
||||
return
|
||||
window.reundo(event,False)
|
||||
|
||||
def new_plist(self, event = None):
|
||||
# Creates a new plistwindow object
|
||||
window = plistwindow.PlistWindow(self, self.tk)
|
||||
window.focus_force()
|
||||
window.update()
|
||||
return window
|
||||
|
||||
def open_plist(self, event=None):
|
||||
# Prompt the user to open a plist, attempt to load it, and if successful,
|
||||
# set its path as our current_plist value
|
||||
current_window = None
|
||||
windows = self.stackorder(self.tk)
|
||||
if len(windows) == 1 and windows[0] == self.start_window and windows[0].edited == False and windows[0].current_plist == None:
|
||||
# Fresh window - replace the contents
|
||||
current_window = windows[0]
|
||||
path = fd.askopenfilename(title = "Select config.plist",filetypes=[("Plist files", "*.plist")],parent=current_window)
|
||||
if not len(path):
|
||||
# User cancelled - bail
|
||||
return None
|
||||
# Verify that no other window has that file selected already
|
||||
for window in windows:
|
||||
if window == self.tk:
|
||||
continue
|
||||
if window.current_plist == path:
|
||||
# found one - just make this focus instead
|
||||
window.focus_force()
|
||||
window.update()
|
||||
window.bell()
|
||||
mb.showerror("File Already Open", "{} is already open here.".format(path), parent=window)
|
||||
return
|
||||
# Let's try to load the plist
|
||||
try:
|
||||
with open(path,"rb") as f:
|
||||
plist_data = plist.load(f)
|
||||
except Exception as e:
|
||||
# Had an issue, throw up a display box
|
||||
# print("{}\a".format(str(e)))
|
||||
self.tk.bell()
|
||||
mb.showerror("An Error Occurred While Opening {}".format(os.path.basename(path)), str(e),parent=current_window)
|
||||
return None
|
||||
else:
|
||||
# Opened it correctly - let's load it, and set our values
|
||||
if current_window:
|
||||
current_window.open_plist(path,plist_data)
|
||||
else:
|
||||
# Need to create one first
|
||||
plistwindow.PlistWindow(self, self.tk).open_plist(path,plist_data)
|
||||
return True
|
||||
|
||||
def stackorder(self, root):
|
||||
"""return a list of root and toplevel windows in stacking order (topmost is last)"""
|
||||
c = root.children
|
||||
s = root.tk.eval('wm stackorder {}'.format(root))
|
||||
L = [x.lstrip('.') for x in s.split()]
|
||||
return [(c[x] if x else root) for x in L]
|
||||
|
||||
def quit(self, event=None):
|
||||
# Check if we need to save first, then quit if we didn't cancel
|
||||
for window in self.stackorder(self.tk)[::-1]:
|
||||
if window == self.tk:
|
||||
continue
|
||||
if window.check_save() == None:
|
||||
# User cancelled or we failed to save, bail
|
||||
return
|
||||
window.destroy()
|
||||
# Actually quit the tkinter session
|
||||
self.tk.destroy()
|
||||
|
||||
if __name__ == '__main__':
|
||||
p = ProperTree()
|
||||
@@ -0,0 +1,4 @@
|
||||
from os.path import dirname, basename, isfile
|
||||
import glob
|
||||
modules = glob.glob(dirname(__file__)+"/*.py")
|
||||
__all__ = [ basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')]
|
||||
@@ -0,0 +1,550 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Clover</key>
|
||||
<dict>
|
||||
<key>ACPI/DSDT/Patches</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>New Blank Entry</string>
|
||||
<key>types</key>
|
||||
<string>d/d/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Disabled</key>
|
||||
<false/>
|
||||
<key>Find</key>
|
||||
<data>
|
||||
</data>
|
||||
<key>Replace</key>
|
||||
<data>
|
||||
</data>
|
||||
</dict>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<key>OpenCore</key>
|
||||
<dict>
|
||||
<key>ACPI/Add</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>New Blank Entry</string>
|
||||
<key>types</key>
|
||||
<string>d/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>Path</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
</dict>
|
||||
</array>
|
||||
<key>ACPI/Block</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>New Blank Entry</string>
|
||||
<key>types</key>
|
||||
<string>d/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>All</key>
|
||||
<false/>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>OemTableId</key>
|
||||
<data>
|
||||
</data>
|
||||
<key>Path</key>
|
||||
<string></string>
|
||||
<key>TableLength</key>
|
||||
<integer>0</integer>
|
||||
<key>TableSignature</key>
|
||||
<data>
|
||||
</data>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Drop DMAR</string>
|
||||
<key>types</key>
|
||||
<string>d/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>All</key>
|
||||
<false/>
|
||||
<key>Comment</key>
|
||||
<string>Drop DMAR</string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>OemTableId</key>
|
||||
<data>
|
||||
</data>
|
||||
<key>Path</key>
|
||||
<string></string>
|
||||
<key>TableLength</key>
|
||||
<integer>0</integer>
|
||||
<key>TableSignature</key>
|
||||
<data>
|
||||
RE1BUg==
|
||||
</data>
|
||||
</dict>
|
||||
</dict>
|
||||
</array>
|
||||
<key>Kernel/Add</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Add Lilu kext</string>
|
||||
<key>types</key>
|
||||
<string>s/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>BundlePath</key>
|
||||
<string>Lilu.kext</string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>ExecutablePath</key>
|
||||
<string>Contents/MacOS/Lilu</string>
|
||||
<key>MatchKernel</key>
|
||||
<string></string>
|
||||
<key>PlistPath</key>
|
||||
<string>Contents/Info.plist</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Add VirtualSmc kext</string>
|
||||
<key>types</key>
|
||||
<string>s/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>BundlePath</key>
|
||||
<string>VirtualSMC.kext</string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>ExecutablePath</key>
|
||||
<string>Contents/MacOS/VirtualSMC</string>
|
||||
<key>MatchKernel</key>
|
||||
<string></string>
|
||||
<key>PlistPath</key>
|
||||
<string>Contents/Info.plist</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Add WhateverGreen kext</string>
|
||||
<key>types</key>
|
||||
<string>s/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>BundlePath</key>
|
||||
<string>WhateverGreen.kext</string>
|
||||
<key>Comment</key>
|
||||
<string>Video card</string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>ExecutablePath</key>
|
||||
<string>Contents/MacOS/WhateverGreen</string>
|
||||
<key>MatchKernel</key>
|
||||
<string></string>
|
||||
<key>PlistPath</key>
|
||||
<string>Contents/Info.plist</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Add AppleALC kext</string>
|
||||
<key>types</key>
|
||||
<string>s/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>BundlePath</key>
|
||||
<string>AppleALC.kext</string>
|
||||
<key>Comment</key>
|
||||
<string>Sound</string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>ExecutablePath</key>
|
||||
<string>Contents/MacOS/AppleALC</string>
|
||||
<key>MatchKernel</key>
|
||||
<string></string>
|
||||
<key>PlistPath</key>
|
||||
<string>Contents/Info.plist</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Add USBInjectAll kext</string>
|
||||
<key>types</key>
|
||||
<string>s/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>BundlePath</key>
|
||||
<string>USBInjectAll.kext</string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>ExecutablePath</key>
|
||||
<string>Contents/MacOS/USBInjectAll</string>
|
||||
<key>MatchKernel</key>
|
||||
<string></string>
|
||||
<key>PlistPath</key>
|
||||
<string>Contents/Info.plist</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Add VoodooPS2Controller [first to load]</string>
|
||||
<key>types</key>
|
||||
<string>s/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>BundlePath</key>
|
||||
<string>VoodooPS2Controller.kext</string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>ExecutablePath</key>
|
||||
<string>Contents/MacOS/VoodooPS2Controller</string>
|
||||
<key>MatchKernel</key>
|
||||
<string></string>
|
||||
<key>PlistPath</key>
|
||||
<string>Contents/Info.plist</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Add VoodooPS2Keyboard [Load after VPS2C]</string>
|
||||
<key>types</key>
|
||||
<string>s/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>BundlePath</key>
|
||||
<string>VoodooPS2Controller.kext/Contents/PlugIns/VoodooPS2Keyboard.kext</string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>ExecutablePath</key>
|
||||
<string>Contents/MacOS/VoodooPS2Keyboard</string>
|
||||
<key>MatchKernel</key>
|
||||
<string></string>
|
||||
<key>PlistPath</key>
|
||||
<string>Contents/Info.plist</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Add VoodooPS2Trackpad [Load after VPS2C]</string>
|
||||
<key>types</key>
|
||||
<string>s/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>BundlePath</key>
|
||||
<string>VoodooPS2Controller.kext/Contents/PlugIns/VoodooPS2Trackpad.kext</string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>ExecutablePath</key>
|
||||
<string>Contents/MacOS/VoodooPS2Trackpad</string>
|
||||
<key>MatchKernel</key>
|
||||
<string></string>
|
||||
<key>PlistPath</key>
|
||||
<string>Contents/Info.plist</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Add AirportBrcmFixup kext</string>
|
||||
<key>types</key>
|
||||
<string>s/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>BundlePath</key>
|
||||
<string>AirportBrcmFixup.kext</string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>ExecutablePath</key>
|
||||
<string>Contents/MacOS/AirportBrcmFixup</string>
|
||||
<key>MatchKernel</key>
|
||||
<string></string>
|
||||
<key>PlistPath</key>
|
||||
<string>Contents/Info.plist</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Add CPUFriend kext</string>
|
||||
<key>types</key>
|
||||
<string>s/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>BundlePath</key>
|
||||
<string>CPUFriend.kext</string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>ExecutablePath</key>
|
||||
<string>Contents/MacOS/CPUFriend</string>
|
||||
<key>MatchKernel</key>
|
||||
<string></string>
|
||||
<key>PlistPath</key>
|
||||
<string>Contents/Info.plist</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Add CPUFriend DataProvider [load after CPUFriend]</string>
|
||||
<key>types</key>
|
||||
<string>s/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>BundlePath</key>
|
||||
<string>CPUFriendDataProvider.kext</string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>ExecutablePath</key>
|
||||
<string></string>
|
||||
<key>MatchKernel</key>
|
||||
<string></string>
|
||||
<key>PlistPath</key>
|
||||
<string>Contents/Info.plist</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>VoodooI2C: Services [First to load]</string>
|
||||
<key>types</key>
|
||||
<string>s/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>BundlePath</key>
|
||||
<string>VoodooI2C.kext/Contents/PlugIns/VoodooI2CServices.kext</string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>ExecutablePath</key>
|
||||
<string>Contents/MacOS/VoodooI2CServices</string>
|
||||
<key>MatchKernel</key>
|
||||
<string></string>
|
||||
<key>PlistPath</key>
|
||||
<string>Contents/Info.plist</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>VoodooI2C: GPIO [Second to load]</string>
|
||||
<key>types</key>
|
||||
<string>s/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>BundlePath</key>
|
||||
<string>VoodooI2C.kext/Contents/PlugIns/VoodooGPIO.kext</string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>ExecutablePath</key>
|
||||
<string>Contents/MacOS/VoodooGPIO</string>
|
||||
<key>MatchKernel</key>
|
||||
<string></string>
|
||||
<key>PlistPath</key>
|
||||
<string>Contents/Info.plist</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>VoodooI2C: Main [Third to load]</string>
|
||||
<key>types</key>
|
||||
<string>s/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>BundlePath</key>
|
||||
<string>VoodooI2C.kext</string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>ExecutablePath</key>
|
||||
<string>Contents/MacOS/VoodooI2C</string>
|
||||
<key>MatchKernel</key>
|
||||
<string></string>
|
||||
<key>PlistPath</key>
|
||||
<string>Contents/Info.plist</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>VoodooI2C: HID [Last to load]</string>
|
||||
<key>types</key>
|
||||
<string>s/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>BundlePath</key>
|
||||
<string>VoodooI2CHID.kext</string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>ExecutablePath</key>
|
||||
<string>Contents/MacOS/VoodooI2CHID</string>
|
||||
<key>MatchKernel</key>
|
||||
<string></string>
|
||||
<key>PlistPath</key>
|
||||
<string>Contents/Info.plist</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Add NoTouchID kext</string>
|
||||
<key>types</key>
|
||||
<string>s/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>BundlePath</key>
|
||||
<string>NoTouchID.kext</string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>ExecutablePath</key>
|
||||
<string>Contents/MacOS/NoTouchID</string>
|
||||
<key>MatchKernel</key>
|
||||
<string></string>
|
||||
<key>PlistPath</key>
|
||||
<string>Contents/Info.plist</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Add BrcmFirmwareData kext</string>
|
||||
<key>types</key>
|
||||
<string>s/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>BundlePath</key>
|
||||
<string>BrcmFirmwareData.kext</string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>ExecutablePath</key>
|
||||
<string>Contents/MacOS/BrcmFirmwareData</string>
|
||||
<key>MatchKernel</key>
|
||||
<string></string>
|
||||
<key>PlistPath</key>
|
||||
<string>Contents/Info.plist</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Add BrcmPatchRAM2 kext</string>
|
||||
<key>types</key>
|
||||
<string>s/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>BundlePath</key>
|
||||
<string>BrcmPatchRAM2.kext</string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>ExecutablePath</key>
|
||||
<string>Contents/MacOS/BrcmPatchRAM2</string>
|
||||
<key>MatchKernel</key>
|
||||
<string></string>
|
||||
<key>PlistPath</key>
|
||||
<string>Contents/Info.plist</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Add SMCBatteryManager kext [Load after VSMC]</string>
|
||||
<key>types</key>
|
||||
<string>s/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>BundlePath</key>
|
||||
<string>SMCBatteryManager.kext</string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>ExecutablePath</key>
|
||||
<string>Contents/MacOS/SMCBatteryManager</string>
|
||||
<key>MatchKernel</key>
|
||||
<string></string>
|
||||
<key>PlistPath</key>
|
||||
<string>Contents/Info.plist</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Add SMCProcessor kext [load after VSMC]</string>
|
||||
<key>types</key>
|
||||
<string>s/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>BundlePath</key>
|
||||
<string>SMCProcessor.kext</string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>ExecutablePath</key>
|
||||
<string>Contents/MacOS/SMCProcessor</string>
|
||||
<key>MatchKernel</key>
|
||||
<string></string>
|
||||
<key>PlistPath</key>
|
||||
<string>Contents/Info.plist</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Add New Blank Entry</string>
|
||||
<key>types</key>
|
||||
<string>s/a</string>
|
||||
<key>value</key>
|
||||
<dict>
|
||||
<key>BundlePath</key>
|
||||
<string></string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Enabled</key>
|
||||
<true/>
|
||||
<key>ExecutablePath</key>
|
||||
<string></string>
|
||||
<key>MatchKernel</key>
|
||||
<string></string>
|
||||
<key>PlistPath</key>
|
||||
<string>Contents/Info.plist</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,215 @@
|
||||
### ###
|
||||
# Imports #
|
||||
### ###
|
||||
|
||||
import datetime
|
||||
from io import BytesIO
|
||||
import os
|
||||
import plistlib
|
||||
import struct
|
||||
import sys
|
||||
|
||||
if sys.version_info < (3,0):
|
||||
# Force use of StringIO instead of cStringIO as the latter
|
||||
# has issues with Unicode strings
|
||||
from StringIO import StringIO
|
||||
|
||||
try:
|
||||
FMT_XML = plistlib.FMT_XML
|
||||
except:
|
||||
FMT_XML = None
|
||||
|
||||
### ###
|
||||
# Helper Methods #
|
||||
### ###
|
||||
|
||||
def _check_py3():
|
||||
return True if sys.version_info >= (3, 0) else False
|
||||
|
||||
def _is_binary(fp):
|
||||
if isinstance(fp, _get_inst()):
|
||||
return fp.startswith(b"bplist00")
|
||||
header = fp.read(32)
|
||||
fp.seek(0)
|
||||
return header[:8] == b'bplist00'
|
||||
|
||||
def _get_inst():
|
||||
if _check_py3():
|
||||
return (str)
|
||||
else:
|
||||
return (str, unicode)
|
||||
|
||||
### ###
|
||||
# Deprecated Functions - Remapped #
|
||||
### ###
|
||||
|
||||
def readPlist(pathOrFile):
|
||||
if not isinstance(pathOrFile, _get_inst()):
|
||||
return load(pathOrFile)
|
||||
with open(pathOrFile, "rb") as f:
|
||||
return load(f)
|
||||
|
||||
def writePlist(value, pathOrFile):
|
||||
if not isinstance(pathOrFile, _get_inst()):
|
||||
return dump(value, pathOrFile, fmt=FMT_XML, sort_keys=True, skipkeys=False)
|
||||
with open(pathOrFile, "wb") as f:
|
||||
return dump(value, f, fmt=FMT_XML, sort_keys=True, skipkeys=False)
|
||||
|
||||
### ###
|
||||
# Remapped Functions #
|
||||
### ###
|
||||
|
||||
def load(fp, fmt=None, use_builtin_types=True, dict_type=dict):
|
||||
if _check_py3():
|
||||
return plistlib.load(fp, fmt=fmt, use_builtin_types=use_builtin_types, dict_type=dict_type)
|
||||
elif not _is_binary(fp):
|
||||
return plistlib.readPlist(fp)
|
||||
else:
|
||||
return readBinaryPlistFile(fp)
|
||||
|
||||
def loads(value, fmt=None, use_builtin_types=True, dict_type=dict):
|
||||
if _check_py3():
|
||||
# Requires fp to be a BytesIO wrapper around a bytes object
|
||||
if isinstance(value, _get_inst()):
|
||||
# If it's a string - encode it
|
||||
value = value.encode()
|
||||
# Load it
|
||||
return plistlib.load(BytesIO(value), fmt=fmt, use_builtin_types=use_builtin_types, dict_type=dict_type)
|
||||
else:
|
||||
if _is_binary(value):
|
||||
# Has the proper header to be a binary plist
|
||||
return readBinaryPlistFile(BytesIO(value))
|
||||
else:
|
||||
# Is not binary - assume a string - and try to load
|
||||
# We avoid using readPlistFromString() as that uses
|
||||
# cStringIO and fails when Unicode strings are detected
|
||||
# Don't subclass - keep the parser local
|
||||
from xml.parsers.expat import ParserCreate
|
||||
# Create a new PlistParser object - then we need to set up
|
||||
# the values and parse.
|
||||
p = plistlib.PlistParser()
|
||||
parser = ParserCreate()
|
||||
parser.StartElementHandler = p.handleBeginElement
|
||||
parser.EndElementHandler = p.handleEndElement
|
||||
parser.CharacterDataHandler = p.handleData
|
||||
if isinstance(value, unicode):
|
||||
# Encode unicode -> string; use utf-8 for safety
|
||||
value = value.encode("utf-8")
|
||||
# Parse the string
|
||||
parser.Parse(value, 1)
|
||||
return p.root
|
||||
|
||||
rootObject = p.parse(s)
|
||||
return rootObject
|
||||
|
||||
def dump(value, fp, fmt=FMT_XML, sort_keys=True, skipkeys=False):
|
||||
if _check_py3():
|
||||
plistlib.dump(value, fp, fmt=fmt, sort_keys=sort_keys, skipkeys=skipkeys)
|
||||
else:
|
||||
plistlib.writePlist(value, fp)
|
||||
|
||||
def dumps(value, fmt=FMT_XML, skipkeys=False):
|
||||
if _check_py3():
|
||||
return plistlib.dumps(value, fmt=fmt, skipkeys=skipkeys).decode("utf-8")
|
||||
else:
|
||||
# We avoid using writePlistToString() as that uses
|
||||
# cStringIO and fails when Unicode strings are detected
|
||||
f = StringIO()
|
||||
plistlib.writePlist(value, f)
|
||||
return f.getvalue()
|
||||
|
||||
### ###
|
||||
# Binary Plist Stuff For Py2 #
|
||||
### ###
|
||||
|
||||
# timestamp 0 of binary plists corresponds to 1/1/2001 (year of Mac OS X 10.0), instead of 1/1/1970.
|
||||
MAC_OS_X_TIME_OFFSET = (31 * 365 + 8) * 86400
|
||||
|
||||
class InvalidFileException(ValueError):
|
||||
def __str__(self):
|
||||
return "Invalid file"
|
||||
def __unicode__(self):
|
||||
return "Invalid file"
|
||||
|
||||
def readBinaryPlistFile(in_file):
|
||||
"""
|
||||
Read a binary plist file, following the description of the binary format: http://opensource.apple.com/source/CF/CF-550/CFBinaryPList.c
|
||||
Raise InvalidFileException in case of error, otherwise return the root object, as usual
|
||||
|
||||
Original patch diffed here: https://bugs.python.org/issue14455
|
||||
"""
|
||||
in_file.seek(-32, os.SEEK_END)
|
||||
trailer = in_file.read(32)
|
||||
if len(trailer) != 32:
|
||||
return InvalidFileException()
|
||||
offset_size, ref_size, num_objects, top_object, offset_table_offset = struct.unpack('>6xBB4xL4xL4xL', trailer)
|
||||
in_file.seek(offset_table_offset)
|
||||
object_offsets = []
|
||||
offset_format = '>' + {1: 'B', 2: 'H', 4: 'L', 8: 'Q', }[offset_size] * num_objects
|
||||
ref_format = {1: 'B', 2: 'H', 4: 'L', 8: 'Q', }[ref_size]
|
||||
int_format = {0: (1, '>B'), 1: (2, '>H'), 2: (4, '>L'), 3: (8, '>Q'), }
|
||||
object_offsets = struct.unpack(offset_format, in_file.read(offset_size * num_objects))
|
||||
def getSize(token_l):
|
||||
""" return the size of the next object."""
|
||||
if token_l == 0xF:
|
||||
m = ord(in_file.read(1)) & 0x3
|
||||
s, f = int_format[m]
|
||||
return struct.unpack(f, in_file.read(s))[0]
|
||||
return token_l
|
||||
def readNextObject(offset):
|
||||
""" read the object at offset. May recursively read sub-objects (content of an array/dict/set) """
|
||||
in_file.seek(offset)
|
||||
token = in_file.read(1)
|
||||
token_h, token_l = ord(token) & 0xF0, ord(token) & 0x0F #high and low parts
|
||||
if token == '\x00':
|
||||
return None
|
||||
elif token == '\x08':
|
||||
return False
|
||||
elif token == '\x09':
|
||||
return True
|
||||
elif token == '\x0f':
|
||||
return ''
|
||||
elif token_h == 0x10: #int
|
||||
result = 0
|
||||
for k in xrange((2 << token_l) - 1):
|
||||
result = (result << 8) + ord(in_file.read(1))
|
||||
return result
|
||||
elif token_h == 0x20: #real
|
||||
if token_l == 2:
|
||||
return struct.unpack('>f', in_file.read(4))[0]
|
||||
elif token_l == 3:
|
||||
return struct.unpack('>d', in_file.read(8))[0]
|
||||
elif token_h == 0x30: #date
|
||||
f = struct.unpack('>d', in_file.read(8))[0]
|
||||
return datetime.datetime.utcfromtimestamp(f + MAC_OS_X_TIME_OFFSET)
|
||||
elif token_h == 0x40: #data
|
||||
s = getSize(token_l)
|
||||
return plistlib.Data(in_file.read(s))
|
||||
elif token_h == 0x50: #ascii string
|
||||
s = getSize(token_l)
|
||||
return in_file.read(s)
|
||||
elif token_h == 0x60: #unicode string
|
||||
s = getSize(token_l)
|
||||
return in_file.read(s * 2).decode('utf-16be')
|
||||
elif token_h == 0x80: #uid
|
||||
return in_file.read(token_l + 1)
|
||||
elif token_h == 0xA0: #array
|
||||
s = getSize(token_l)
|
||||
obj_refs = struct.unpack('>' + ref_format * s, in_file.read(s * ref_size))
|
||||
return map(lambda x: readNextObject(object_offsets[x]), obj_refs)
|
||||
elif token_h == 0xC0: #set
|
||||
s = getSize(token_l)
|
||||
obj_refs = struct.unpack('>' + ref_format * s, in_file.read(s * ref_size))
|
||||
return set(map(lambda x: readNextObject(object_offsets[x]), obj_refs))
|
||||
elif token_h == 0xD0: #dict
|
||||
result = {}
|
||||
s = getSize(token_l)
|
||||
key_refs = struct.unpack('>' + ref_format * s, in_file.read(s * ref_size))
|
||||
obj_refs = struct.unpack('>' + ref_format * s, in_file.read(s * ref_size))
|
||||
for k, o in zip(key_refs, obj_refs):
|
||||
key = readNextObject(object_offsets[k])
|
||||
obj = readNextObject(object_offsets[o])
|
||||
result[key] = obj
|
||||
return result
|
||||
raise InvalidFileException()
|
||||
return readNextObject(object_offsets[top_object])
|
||||
File diff suppressed because it is too large
Load Diff
+156
@@ -0,0 +1,156 @@
|
||||
import sys
|
||||
import subprocess
|
||||
import threading
|
||||
import 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 _stream_output(self, comm, shell = False):
|
||||
output = error = ""
|
||||
p = ot = et = 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 = Queue()
|
||||
t = threading.Thread(target=self._read_output, args=(p.stdout, q))
|
||||
t.daemon = True # thread dies with the program
|
||||
# Setup the stderr thread/queue
|
||||
qe = Queue()
|
||||
te = threading.Thread(target=self._read_output, args=(p.stderr, qe))
|
||||
te.daemon = True # thread dies with the program
|
||||
# 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()
|
||||
p.poll()
|
||||
if c==z=="" and p.returncode != None:
|
||||
break
|
||||
|
||||
o, e = p.communicate()
|
||||
ot.exit()
|
||||
et.exit()
|
||||
return (output+o, error+e, p.returncode)
|
||||
except:
|
||||
if ot or et:
|
||||
try: ot.exit()
|
||||
except: pass
|
||||
try: et.exit()
|
||||
except: pass
|
||||
if p:
|
||||
return (output, error, 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
|
||||
@@ -0,0 +1,272 @@
|
||||
import sys, os, time, re, json, datetime, ctypes, subprocess
|
||||
|
||||
if os.name == "nt":
|
||||
# Windows
|
||||
import msvcrt
|
||||
else:
|
||||
# Not Windows \o/
|
||||
import select
|
||||
|
||||
class Utils:
|
||||
|
||||
def __init__(self, name = "Python Script"):
|
||||
self.name = name
|
||||
# Init our colors before we need to print anything
|
||||
cwd = os.getcwd()
|
||||
os.chdir(os.path.dirname(os.path.realpath(__file__)))
|
||||
if os.path.exists("colors.json"):
|
||||
self.colors_dict = json.load(open("colors.json"))
|
||||
else:
|
||||
self.colors_dict = {}
|
||||
os.chdir(cwd)
|
||||
|
||||
def check_admin(self):
|
||||
# Returns whether or not we're admin
|
||||
try:
|
||||
is_admin = os.getuid() == 0
|
||||
except AttributeError:
|
||||
is_admin = ctypes.windll.shell32.IsUserAnAdmin() != 0
|
||||
return is_admin
|
||||
|
||||
def elevate(self, file):
|
||||
# Runs the passed file as admin
|
||||
if self.check_admin():
|
||||
return
|
||||
if os.name == "nt":
|
||||
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, file, None, 1)
|
||||
else:
|
||||
try:
|
||||
p = subprocess.Popen(["which", "sudo"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
c = p.communicate()[0].decode("utf-8", "ignore").replace("\n", "")
|
||||
os.execv(c, [ sys.executable, 'python'] + sys.argv)
|
||||
except:
|
||||
exit(1)
|
||||
|
||||
def compare_versions(self, vers1, vers2, **kwargs):
|
||||
# Helper method to compare ##.## strings
|
||||
#
|
||||
# vers1 < vers2 = True
|
||||
# vers1 = vers2 = None
|
||||
# vers1 > vers2 = False
|
||||
|
||||
# Sanitize the pads
|
||||
pad = str(kwargs.get("pad", ""))
|
||||
sep = str(kwargs.get("separator", "."))
|
||||
|
||||
ignore_case = kwargs.get("ignore_case", True)
|
||||
|
||||
# Cast as strings
|
||||
vers1 = str(vers1)
|
||||
vers2 = str(vers2)
|
||||
|
||||
if ignore_case:
|
||||
vers1 = vers1.lower()
|
||||
vers2 = vers2.lower()
|
||||
|
||||
# Split and pad lists
|
||||
v1_parts, v2_parts = self.pad_length(vers1.split(sep), vers2.split(sep))
|
||||
|
||||
# Iterate and compare
|
||||
for i in range(len(v1_parts)):
|
||||
# Remove non-numeric
|
||||
v1 = ''.join(c.lower() for c in v1_parts[i] if c.isalnum())
|
||||
v2 = ''.join(c.lower() for c in v2_parts[i] if c.isalnum())
|
||||
# Equalize the lengths
|
||||
v1, v2 = self.pad_length(v1, v2)
|
||||
# Compare
|
||||
if str(v1) < str(v2):
|
||||
return True
|
||||
elif str(v1) > str(v2):
|
||||
return False
|
||||
# Never differed - return None, must be equal
|
||||
return None
|
||||
|
||||
def pad_length(self, var1, var2, pad = "0"):
|
||||
# Pads the vars on the left side to make them equal length
|
||||
pad = "0" if len(str(pad)) < 1 else str(pad)[0]
|
||||
if not type(var1) == type(var2):
|
||||
# Type mismatch! Just return what we got
|
||||
return (var1, var2)
|
||||
if len(var1) < len(var2):
|
||||
if type(var1) is list:
|
||||
var1.extend([str(pad) for x in range(len(var2) - len(var1))])
|
||||
else:
|
||||
var1 = "{}{}".format((pad*(len(var2)-len(var1))), var1)
|
||||
elif len(var2) < len(var1):
|
||||
if type(var2) is list:
|
||||
var2.extend([str(pad) for x in range(len(var1) - len(var2))])
|
||||
else:
|
||||
var2 = "{}{}".format((pad*(len(var1)-len(var2))), var2)
|
||||
return (var1, var2)
|
||||
|
||||
def check_path(self, path):
|
||||
# Loop until we either get a working path - or no changes
|
||||
count = 0
|
||||
while count < 100:
|
||||
count += 1
|
||||
if not len(path):
|
||||
# We uh.. stripped out everything - bail
|
||||
return None
|
||||
if os.path.exists(path):
|
||||
# Exists!
|
||||
return os.path.abspath(path)
|
||||
# Check quotes first
|
||||
if (path[0] == '"' and path[-1] == '"') or (path[0] == "'" and path[-1] == "'"):
|
||||
path = path[1:-1]
|
||||
continue
|
||||
# Check for tilde
|
||||
if path[0] == "~":
|
||||
test_path = os.path.expanduser(path)
|
||||
if test_path != path:
|
||||
# We got a change
|
||||
path = test_path
|
||||
continue
|
||||
# If we have no spaces to trim - bail
|
||||
if not (path[0] == " " or path[0] == " ") and not(path[-1] == " " or path[-1] == " "):
|
||||
return None
|
||||
# Here we try stripping spaces/tabs
|
||||
test_path = path
|
||||
t_count = 0
|
||||
while t_count < 100:
|
||||
t_count += 1
|
||||
t_path = test_path
|
||||
while len(t_path):
|
||||
if os.path.exists(t_path):
|
||||
return os.path.abspath(t_path)
|
||||
if t_path[-1] == " " or t_path[-1] == " ":
|
||||
t_path = t_path[:-1]
|
||||
continue
|
||||
break
|
||||
if test_path[0] == " " or test_path[0] == " ":
|
||||
test_path = test_path[1:]
|
||||
continue
|
||||
break
|
||||
# Escapes!
|
||||
test_path = "\\".join([x.replace("\\", "") for x in path.split("\\\\")])
|
||||
if test_path != path and not (path[0] == " " or path[0] == " "):
|
||||
path = test_path
|
||||
continue
|
||||
if path[0] == " " or path[0] == " ":
|
||||
path = path[1:]
|
||||
return None
|
||||
|
||||
def grab(self, prompt, **kwargs):
|
||||
# Takes a prompt, a default, and a timeout and shows it with that timeout
|
||||
# returning the result
|
||||
timeout = kwargs.get("timeout", 0)
|
||||
default = kwargs.get("default", None)
|
||||
# If we don't have a timeout - then skip the timed sections
|
||||
if timeout <= 0:
|
||||
if sys.version_info >= (3, 0):
|
||||
return input(prompt)
|
||||
else:
|
||||
return str(raw_input(prompt))
|
||||
# Write our prompt
|
||||
sys.stdout.write(prompt)
|
||||
sys.stdout.flush()
|
||||
if os.name == "nt":
|
||||
start_time = time.time()
|
||||
i = ''
|
||||
while True:
|
||||
if msvcrt.kbhit():
|
||||
c = msvcrt.getche()
|
||||
if ord(c) == 13: # enter_key
|
||||
break
|
||||
elif ord(c) >= 32: #space_char
|
||||
i += c
|
||||
if len(i) == 0 and (time.time() - start_time) > timeout:
|
||||
break
|
||||
else:
|
||||
i, o, e = select.select( [sys.stdin], [], [], timeout )
|
||||
if i:
|
||||
i = sys.stdin.readline().strip()
|
||||
print('') # needed to move to next line
|
||||
if len(i) > 0:
|
||||
return i
|
||||
else:
|
||||
return default
|
||||
|
||||
def cls(self):
|
||||
os.system('cls' if os.name=='nt' else 'clear')
|
||||
|
||||
def cprint(self, message, **kwargs):
|
||||
strip_colors = kwargs.get("strip_colors", False)
|
||||
if os.name == "nt":
|
||||
strip_colors = True
|
||||
reset = u"\u001b[0m"
|
||||
# Requires sys import
|
||||
for c in self.colors:
|
||||
if strip_colors:
|
||||
message = message.replace(c["find"], "")
|
||||
else:
|
||||
message = message.replace(c["find"], c["replace"])
|
||||
if strip_colors:
|
||||
return message
|
||||
sys.stdout.write(message)
|
||||
print(reset)
|
||||
|
||||
# Needs work to resize the string if color chars exist
|
||||
'''# Header drawing method
|
||||
def head(self, text = None, width = 55):
|
||||
if text == None:
|
||||
text = self.name
|
||||
self.cls()
|
||||
print(" {}".format("#"*width))
|
||||
len_text = self.cprint(text, strip_colors=True)
|
||||
mid_len = int(round(width/2-len(len_text)/2)-2)
|
||||
middle = " #{}{}{}#".format(" "*mid_len, len_text, " "*((width - mid_len - len(len_text))-2))
|
||||
if len(middle) > width+1:
|
||||
# Get the difference
|
||||
di = len(middle) - width
|
||||
# Add the padding for the ...#
|
||||
di += 3
|
||||
# Trim the string
|
||||
middle = middle[:-di]
|
||||
newlen = len(middle)
|
||||
middle += "...#"
|
||||
find_list = [ c["find"] for c in self.colors ]
|
||||
|
||||
# Translate colored string to len
|
||||
middle = middle.replace(len_text, text + self.rt_color) # always reset just in case
|
||||
self.cprint(middle)
|
||||
print("#"*width)'''
|
||||
|
||||
# Header drawing method
|
||||
def head(self, text = None, width = 55):
|
||||
if text == None:
|
||||
text = self.name
|
||||
self.cls()
|
||||
print(" {}".format("#"*width))
|
||||
mid_len = int(round(width/2-len(text)/2)-2)
|
||||
middle = " #{}{}{}#".format(" "*mid_len, text, " "*((width - mid_len - len(text))-2))
|
||||
if len(middle) > width+1:
|
||||
# Get the difference
|
||||
di = len(middle) - width
|
||||
# Add the padding for the ...#
|
||||
di += 3
|
||||
# Trim the string
|
||||
middle = middle[:-di] + "...#"
|
||||
print(middle)
|
||||
print("#"*width)
|
||||
|
||||
def resize(self, width, height):
|
||||
print('\033[8;{};{}t'.format(height, width))
|
||||
|
||||
def custom_quit(self):
|
||||
self.head()
|
||||
print("by CorpNewt\n")
|
||||
print("Thanks for testing it out, for bugs/comments/complaints")
|
||||
print("send me a message on Reddit, or check out my GitHub:\n")
|
||||
print("www.reddit.com/u/corpnewt")
|
||||
print("www.github.com/corpnewt\n")
|
||||
# Get the time and wish them a good morning, afternoon, evening, and night
|
||||
hr = datetime.datetime.now().time().hour
|
||||
if hr > 3 and hr < 12:
|
||||
print("Have a nice morning!\n\n")
|
||||
elif hr >= 12 and hr < 17:
|
||||
print("Have a nice afternoon!\n\n")
|
||||
elif hr >= 17 and hr < 21:
|
||||
print("Have a nice evening!\n\n")
|
||||
else:
|
||||
print("Have a nice night!\n\n")
|
||||
exit(0)
|
||||
Reference in New Issue
Block a user