diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 4aa5943..ae817c1 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,3 +1,3 @@ # These are supported funding model platforms - +github: mrhaydendp ko_fi: mrhaydendp diff --git a/Changelog.md b/Changelog.md index 51e3ac0..493c999 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,19 +1,13 @@ -## Updated main.py, identify, version 05/01/2024 -- Version bump (24.05) -- Updated & cleaned up code comments -- Removed parenthesis from platform names -- Removed `window.columnconfigure` as it's implied and not needed -- Added shell variable to determine which scripts to install during updates -- Added Fire OS version, Fire Tools version, and platform output to terminal -- Made update tool more resilient to internet issues -- Update tool now uses `with` context manager to ensure files are fully downloaded and written before closing -- Cached "ft-identifying-fire-tablets.html" is now deleted during updates -- "requirements.txt" will now get updated -- Remade update tool and it now tells you which files are being updated and can now add or remove files in future updates -- Simplified folder deletion during failed package extraction -- Sped up package list generation by pre-formatting list on device -- Made package list bigger and scaled the scrollable frame better -- Temporary "packagelist" files are now deleted when application closes -- Cleaned up code by using some suggestions from Pylint -- Made custom disable/enable/extract terminal output cleaner by adding a blank line at the end -- Disable DNS will now remove "private_dns_specifier" key from device +## Updated main.py, requirements.txt, version 06/01/2024 +- Version bump (24.06) +- Updated "requests" version requirent to `2.32.0` because of CVE-2024-35195 +- Fixed some formatting inconsistancies (blank spaces, single quotes, command format) +- Updated code comments +- Added Play Store crashing fix by re-installing after initial Gapps install +- Replaced `os.system` & `os.popen` commands with `subprocess` equivalents since they are deprecated +- Update tool now uses Python's `os.chmod` instead of running chmod as a shell command +- Appinstaller function can now accept individual applications instead of installing all apps in a folder +- Simplified "customlauncher" function by only calling appinstaller script once +- Custom DNS check now uses try/except instead of Bash/Posix operators inside ADB shell +- xdg-open/open -e commands now use try/except instead of Bash/Posix operators +- Enabled/disabled packages on the UI are now generated by enabled & disabled list (might be easier to update lists on the fly) diff --git a/Fire-Tools/main.py b/Fire-Tools/main.py index 48a8d0e..fe4c0c1 100644 --- a/Fire-Tools/main.py +++ b/Fire-Tools/main.py @@ -1,10 +1,11 @@ import glob import os import requests +import subprocess import customtkinter as ctk # Platform & Device Variables -version = "24.05" +version = "24.06" platform = "Linux/macOS" path = f"{os.getcwd()}/Scripts/Posix/" extension = ".sh" @@ -16,7 +17,7 @@ shell = "PowerShell" # Get Device Name & Fire OS Version from identify Script, then Print Fire Tools Version, Platform, Device Name, and Software Version -device = os.popen(f"{path}identify{extension}").read().splitlines() +device = subprocess.check_output(f"{path}identify{extension}".split(), universal_newlines=True).splitlines() print(f"Fire Tools Version: {version}\nPlatform: {platform}\nDevice: {device[0]}\nSoftware: {device[1]}\n") # Window Config @@ -24,7 +25,23 @@ window.title(f"Fire Tools v{version} - ({platform}) | {device[0]}") window.geometry("980x550") -# On Update, Delete 'ft-identifying-tablet-devices.html', Update Modules, and Make Scripts Executable (Linux/macOS) +# Run Debloat with Disable/Enable Option & Package Name +def debloat(option, package=""): + cmdlist = f"{path}debloat{extension} {option}".split() + if package: + cmdlist.append(package) + subprocess.run(cmdlist) + +# Pass Folder or .apk(m) to Appinstaller Script for Installation +def appinstaller(folder): + cmdlist = f"{path}appinstaller{extension}".split() + search = f"{os.getcwd()}/{folder}*.apk*" + for app in glob.iglob(search): + cmdlist.append(app) + subprocess.run(cmdlist) + cmdlist.remove(app) + +# On Update, Delete "ft-identifying-tablet-devices.html", Update Modules, and Make Scripts Executable (Linux/macOS) def update_tool(): print("Checking for Updates...\n") try: @@ -41,38 +58,42 @@ def update_tool(): with open(f"{module}", "wb") as file: file.write(requests.get(f"https://github.com/mrhaydendp/Fire-Tools/raw/main/Fire-Tools/{module}", timeout=10).content) if platform == "Linux/macOS": - os.popen("chmod +x Scripts/Posix/*.sh") + for script in glob.glob(f"{os.getcwd()}/Scripts/Posix/*.sh"): + os.chmod(script, 0o775 ) print("\nUpdates Complete, Please Re-launch Application") quit() else: print("No Update Needed\n") -# Run Debloat with Disable/Enable Option & Package Name -def debloat(option,package): - os.system(f"{path}debloat{extension} {option} {package}") - # Open Debloat.txt in Preferred Text Editor def editfile(): if platform != "Windows": - os.system("xdg-open Debloat.txt >/dev/null 2>&1 || open -e Debloat.txt") + try: + subprocess.run(["xdg-open", "Debloat.txt"], check=True, stderr=subprocess.PIPE) + except subprocess.CalledProcessError: + subprocess.run(["open", "-e", "Debloat.txt"], check=True, stderr=subprocess.PIPE) else: - os.startfile('Debloat.txt') + os.startfile("Debloat.txt") # Set DNS Mode to Hostname, then Set Selected Provider as Private DNS def set_dns(): dnsprovider = customdns.get() if dnsprovider == "None": - os.system("adb shell \"settings put global private_dns_mode off && printf 'Disabled Private DNS\\n\\n'\"") - os.system("adb shell settings delete global private_dns_specifier") + subprocess.run(["adb", "shell", "settings", "put", "global", "private_dns_mode", "off"]) + subprocess.run(["adb", "shell", "settings", "delete", "global", "private_dns_specifier"], stdout=subprocess.PIPE) + print("Disabled Private DNS\n") elif dnsprovider != "Select or Enter DNS Server": - os.system("adb shell settings put global private_dns_mode hostname") - os.system(f"adb shell \"settings put global private_dns_specifier {dnsprovider} && printf 'Successfully Set Private DNS to: {dnsprovider}\\n\\n'\"") - -# Get all .apk(m) Files from Selected Folder & Pass to AppInstaller Script -def appinstaller(folder): - search = f"{os.getcwd()}{folder}/*.apk*" - for app in glob.iglob(search): - os.system(f"{path}appinstaller{extension} \"{app}\"") + try: + subprocess.check_output(["adb", "shell", "settings", "put", "global", "private_dns_mode", "hostname"], stderr=subprocess.PIPE) + subprocess.check_output(["adb", "shell", "settings", "put", "global", "private_dns_specifier", dnsprovider]) + print(f"Successfully Set DNS Provider to: {dnsprovider}\n") + except subprocess.CalledProcessError: + print("Failed to Set Private DNS\n") + +# Install Gapps in Gapps Folder then Re-install Play Store +def install_gapps(): + appinstaller("Gapps/") + appinstaller("Gapps/Google Play Store") # Attempt to Disable OTA Packages def disableota(): @@ -84,33 +105,37 @@ def disableota(): def set_launcher(): if customlauncher.get() == "Custom": launcher = ctk.filedialog.askopenfilename(title="Select Launcher .apk(m) File",filetypes=(("APK","*.apk"),("Split APK","*.apkm"),("all files","*.*"))) - if launcher: - os.system(f"{path}appinstaller{extension} \"{launcher}\" Launcher") + if not launcher: + return elif customlauncher.get() != "Select Launcher": - search = f"{os.getcwd()}/{customlauncher.get()}*.apk" - for launcher in glob.iglob(search): - os.system(f"{path}appinstaller{extension} \"{launcher}\" Launcher") + for app in glob.iglob(f"{os.getcwd()}/{customlauncher.get()}*.apk"): + launcher = app + cmdlist = f"{path}appinstaller{extension}".split() + cmdlist.append(launcher) + cmdlist.append("Launcher") + subprocess.run(cmdlist) # Extract Selected Package to Extracted/{package} If not Already Present def extract(package): if not os.path.exists(f"Extracted/{package}"): print("Extracting:", package) os.mkdir(f"Extracted/{package}") - for packagelocation in os.popen(f"adb shell \"pm path {package} | cut -f2 -d:\"").read().splitlines(): - os.system(f"adb pull {packagelocation} ./Extracted/{package}") + for packagelocation in subprocess.check_output(["adb", "shell", "pm", "path", package], universal_newlines=True).splitlines(): + subprocess.run(["adb", "pull", packagelocation.replace("package:",""), f"./Extracted/{package}"]) if not os.listdir(f"Extracted/{package}"): os.rmdir(f"Extracted/{package}") + print("") else: print(f"Found at: /Extracted/{package}") -# Add Selected Packages to 'customlist' & Remove if Package is Already Found +# Add Selected Packages to "customlist" & Remove if Package is Already Found def add_package(package): if package in customlist: customlist.remove(package) else: customlist.append(package) -# Read Packages from 'customlist' & Pass to Debloat or Extract Function +# Read Packages from "customlist" & Pass to Debloat or Extract Function def custom(option): for package in customlist: if option == "Extract": @@ -131,10 +156,10 @@ def switch(option): label = ctk.CTkLabel(window, text="Debloat", font=("default",25)) label.grid(row=0, column=0, padx=60, pady=15) -disable = ctk.CTkButton(window, text="Debloat", width=200, height=50, command=lambda: debloat("Disable","")) +disable = ctk.CTkButton(window, text="Debloat", width=200, height=50, command=lambda: debloat("Disable")) disable.grid(row=1, column=0, padx=60, pady=15) -undo = ctk.CTkButton(window, text="Undo", width=200, height=50, command=lambda: debloat("Enable","")) +undo = ctk.CTkButton(window, text="Undo", width=200, height=50, command=lambda: debloat("Enable")) undo.grid(row=2, column=0, padx=60, pady=15) edit = ctk.CTkButton(window, text="Edit", width=200, height=50, command=editfile) @@ -154,10 +179,10 @@ def switch(option): label2 = ctk.CTkLabel(window, text="Utilities", font=("default",25)) label2.grid(row=0, column=1, padx=60, pady=15) -googleservices = ctk.CTkButton(window, text="Install Google Services", width=200, height=50, command=lambda: appinstaller("/Gapps")) +googleservices = ctk.CTkButton(window, text="Install Google Services", width=200, height=50, command=install_gapps) googleservices.grid(row=1, column=1, padx=60, pady=15) -batchinstall = ctk.CTkButton(window, text="Batch Install", width=200, height=50, command=lambda: appinstaller("/Batch")) +batchinstall = ctk.CTkButton(window, text="Batch Install", width=200, height=50, command=lambda: appinstaller("Batch/")) batchinstall.grid(row=2, column=1, padx=60, pady=15) ota = ctk.CTkButton(window, text="Disable OTA", width=200, height=50, command=disableota) @@ -198,10 +223,12 @@ def switch(option): customlist = [] if device[0] != "Unknown/Undetected": - for enabled_package in os.popen("adb shell \"pm list packages -e | cut -f2 -d:\"").read().splitlines(): - checkbox = ctk.CTkCheckBox(enabled_list, text=enabled_package, command = lambda param = enabled_package: add_package(param)).pack() - for disabled_package in os.popen("adb shell \"pm list packages -d | cut -f2 -d:\"").read().splitlines(): - checkbox = ctk.CTkCheckBox(disabled_list, text=disabled_package, command = lambda param = disabled_package: add_package(param)).pack() + enabled = [package.replace("package:","") for package in subprocess.check_output(["adb", "shell", "pm", "list", "packages", "-e"], universal_newlines=True).splitlines()] + disabled = [package.replace("package:","") for package in subprocess.check_output(["adb", "shell", "pm", "list", "packages", "-d"], universal_newlines=True).splitlines()] + for package in enabled: + checkbox = ctk.CTkCheckBox(enabled_list, text=package, command = lambda param = package: add_package(param)).pack() + for package in disabled: + checkbox = ctk.CTkCheckBox(disabled_list, text=package, command = lambda param = package: add_package(param)).pack() window.mainloop() diff --git a/Fire-Tools/requirements.txt b/Fire-Tools/requirements.txt index f3327a2..36c63f4 100644 --- a/Fire-Tools/requirements.txt +++ b/Fire-Tools/requirements.txt @@ -3,5 +3,5 @@ charset-normalizer==3.3.2 customtkinter==5.2.2 darkdetect==0.8.0 packaging==24.0 -requests==2.31.0 +requests==2.32.0 urllib3==2.2.1 diff --git a/Fire-Tools/version b/Fire-Tools/version index 0312909..7d9d1a1 100644 --- a/Fire-Tools/version +++ b/Fire-Tools/version @@ -1 +1 @@ -24.05 +24.06 diff --git a/Screenshot.png b/Screenshot.png index 0016cd7..72e1513 100644 Binary files a/Screenshot.png and b/Screenshot.png differ