feat: plist operations

This commit is contained in:
zx
2024-09-08 18:48:05 -04:00
parent 00cd5447b1
commit 5c0363b5a9
5 changed files with 100 additions and 13 deletions

View File

@@ -35,7 +35,7 @@ then finally, to install or update cyan, just `pip install --force-reinstall git
[x] refactor: dont prepare, just copy and fix as you go
[2] feat: plist operations (-n, -v, -b, -m, -l, -r)
[x] feat: plist operations (-l and -r wont be implemented)
[x] feat: remove watch app

View File

@@ -26,6 +26,22 @@ def main() -> None:
"-f", metavar="file", nargs="+",
help="a tweak to inject/item to be added to the bundle"
)
parser.add_argument(
"-n", metavar="name",
help="modify the app's name"
)
parser.add_argument(
"-v", metavar="version",
help="modify the app's version"
)
parser.add_argument(
"-b", metavar="bundle id",
help="modify the app's bundle id"
)
parser.add_argument(
"-m", metavar="minimum",
help="modify the app's minimum OS version"
)
parser.add_argument(
"-u", "--remove-supported-devices", action="store_true",
@@ -71,7 +87,7 @@ def main() -> None:
)
parser.add_argument(
"-v", "--version", action="version", version="cyan v1.0"
"--version", action="version", version="cyan v1.0"
)
from cyan import logic

View File

@@ -47,6 +47,14 @@ def main(parser: ArgumentParser) -> None:
if args.f is not None:
app.executable.inject(args.f, tmpdir)
if args.n is not None:
app.plist.change_name(args.n)
if args.v is not None:
app.plist.change_version(args.v)
if args.b is not None:
app.plist.change_bundle_id(args.b)
if args.m is not None:
app.plist.change_minimum_version(args.m)
if args.remove_supported_devices:
app.plist.remove_uisd()

View File

@@ -9,7 +9,7 @@ from .plist import Plist
class AppBundle:
def __init__(self, path: str):
self.path = path
self.plist = Plist(f"{path}/Info.plist")
self.plist = Plist(f"{path}/Info.plist", path)
self.executable = Executable(
f"{path}/{self.plist['CFBundleExecutable']}",

View File

@@ -1,16 +1,23 @@
import sys
import plistlib
from typing import Any
from glob import glob
from typing import Optional, Any
class Plist:
def __init__(self, path: str):
def __init__(
self, path: str, app_path: Optional[str] = None, throw: bool = True
):
try:
with open(path, "rb") as f:
self.data: dict[str, Any] = plistlib.load(f)
except Exception:
if throw:
sys.exit(f"[!] couldn't read {path}")
else:
return None
self.path = path
self.app_path = app_path
def __getitem__(self, key: str) -> Any:
return self.data.get(key, None)
@@ -25,33 +32,89 @@ class Plist:
def remove(self, key: str) -> bool:
try:
del self.data[key]
self.save()
return True
except KeyError:
return False
def change(self, key: str, val: Any) -> bool:
def change(self, val: Any, *keys: str) -> bool:
try:
if self[key] == val:
if all(self[key] == val for key in keys):
return False
except KeyError:
for key in keys:
self[key] = val
self.save()
return True
def remove_uisd(self) -> None:
if self.remove("UISupportedDevices"):
self.save()
print("[*] removed UISupportedDevices")
else:
print("[?] no UISupportedDevices")
def enable_documents(self) -> None:
c1 = self.change("UISupportsDocumentBrowser", True)
c2 = self.change("UIFileSharingEnabled", True)
c1 = self.change(True, "UISupportsDocumentBrowser")
c2 = self.change(True, "UIFileSharingEnabled")
if c1 or c2:
self.save()
print("[*] enabled documents support")
else:
print("[?] documents support was already enabled")
def change_name(self, name: str) -> None:
if self.change("CFBundleName", "CFBundleDisplayName", name):
print(f"[*] changed name to \"{name}\"")
changed = 0
for lproj in glob(f"{self.app_path}/*.lproj"):
try:
pl = Plist(f"{lproj}/InfoPlist.strings", None, False)
pl["CFBundleDisplayName"] = name
pl["CFBundleName"] = name
pl.save()
changed += 1
except Exception:
pass # file might not exist
if changed != 0:
print(f"[*] changed \033[96m{changed}\033[0m localized names")
else:
print(f"[?] name was already \"{name}\"")
def change_version(self, version: str) -> None:
if self.change("CFBundleVersion", "CFBundleShortVersionString", version):
print(f"[*] changed version to \"{version}\"")
else:
print(f"[?] version was already \"{version}\"")
def change_bundle_id(self, bundle_id: str) -> None:
orig = self["CFBundleIdentifier"]
if self.change("CFBundleIdentifier", bundle_id):
print(f"[*] changed bundle id to \"{bundle_id}\"")
changed = 0
# change all other bundle ids
for ext in glob(f"{self.app_path}/*/*.appex"):
try:
pl = Plist(f"{ext}/Info.plist", None, False)
current = pl["CFBundleIdentifier"]
pl["CFBundleIdentifier"] = current.replace(orig, bundle_id)
pl.save()
changed += 1
except Exception:
pass # how tf would it not exist? idk
if changed != 0:
print(f"[*] changed \033[96m{changed}\033[0m other bundle ids")
else:
print(f"[?] bundle id was already \"{bundle_id}\"")
def change_minimum_version(self, minimum: str) -> None:
if self.change("MinimumOSVersion", minimum):
print(f"[*] changed minimum version to \"{minimum}\"")
else:
print(f"[?] minimum version was already \"{minimum}\"")