From ffbff5c78dd71ef6c08272f714d904ef4c3d7b45 Mon Sep 17 00:00:00 2001 From: zx Date: Sat, 1 Feb 2025 21:38:15 -0500 Subject: [PATCH] feat: use multiple cyans --- README.md | 2 + cyan/__main__.py | 9 +++-- cyan/logic.py | 2 +- cyan/tbhtypes/main_executable.py | 5 +++ cyan/tbhutils.py | 63 +++++++++++++++++--------------- 5 files changed, 47 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index d4f0f2d..9b0c6e7 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ a rewrite of [pyzule](https://github.com/asdfzxcvbn/pyzule) that doesn't (completely) suck !! +wouldn't a go rewrite be really cool? (or in rust or something, adding features to this makes me realize PYTHONM FUCKING SUCKS SOMEONE PLEASE REWRITE IN LIKE ANY COMPILED AND STATICALLY TYPED LANGUAGE PLEASE!!!!!!! + ## features you can open an issue to request a feature :D !! also see my [recommended flags](https://github.com/asdfzxcvbn/pyzule-rw/wiki/recommended-flags) diff --git a/cyan/__main__.py b/cyan/__main__.py index b6b97e8..4ac931a 100755 --- a/cyan/__main__.py +++ b/cyan/__main__.py @@ -21,15 +21,16 @@ def main() -> None: "-o", "--output", metavar="output", help="if unspecified, overwrites input" ) - parser.add_argument( - "-z", "--cyan", metavar="cyan", - help="the .cyan file to use" - ) + parser.add_argument( + "-z", "--cyan", metavar="cyan", nargs="+", + help="the .cyan file(s) to use" + ) parser.add_argument( "-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" diff --git a/cyan/logic.py b/cyan/logic.py index 2d3929f..8838e15 100644 --- a/cyan/logic.py +++ b/cyan/logic.py @@ -45,7 +45,7 @@ def main(parser: ArgumentParser) -> None: if args.cyan is not None: changing = vars(args) - tbhutils.parse_cyan(changing, tmpdir) + tbhutils.parse_cyans(changing, tmpdir) # this goes before injection, # since user might inject their own extensions diff --git a/cyan/tbhtypes/main_executable.py b/cyan/tbhtypes/main_executable.py index 6ce13dc..caa8ddd 100644 --- a/cyan/tbhtypes/main_executable.py +++ b/cyan/tbhtypes/main_executable.py @@ -61,6 +61,9 @@ class MainExecutable(Executable): # inject/fix user things for bn, path in tweaks.items(): + if os.path.islink(path): + continue # symlinks can potentially have some security implications + if bn.endswith(".appex"): fpath = f"{PLUGINS_DIR}/{bn}" existed = tbhutils.delete_if_exists(fpath, bn) @@ -94,6 +97,8 @@ class MainExecutable(Executable): # orion has a *weak* dependency to substrate, # but will still crash without it. nice !!!!!!!!!!! + ## edit: actually, maybe this is in case someone uses Internal backend? + ## someone test it pls!!! if "orion." in needed: needed.add("substrate.") diff --git a/cyan/tbhutils.py b/cyan/tbhutils.py index 90524ba..bae53eb 100644 --- a/cyan/tbhutils.py +++ b/cyan/tbhutils.py @@ -70,8 +70,10 @@ def validate_inputs(args: Namespace) -> Optional[str]: if args.l is not None and not os.path.isfile(args.l): sys.exit(f"[!] {args.l} does not exist") - if args.cyan is not None and not os.path.isfile(args.cyan): - sys.exit(f"[!] {args.cyan} does not exist") + if args.cyan is not None: + for cyan in args.cyan: + if not os.path.isfile(cyan): + sys.exit(f"[!] {cyan} does not exist") if args.x is not None: if not os.path.isfile(args.x): @@ -189,7 +191,7 @@ def extract_deb(deb: str, tweaks: dict[str, str], tmpdir: str) -> None: glob(f"{t2}/**/*.framework", recursive=True) ), []): # type: ignore if ( - os.path.islink(hi) # symlinks are broken iirc + os.path.islink(hi) # symlinks are broken iirc, also for security or hi.count(".bundle") > 1 # prevent sub-bundle detection (rip) or hi.count(".framework") > 1 ): @@ -232,34 +234,37 @@ def make_ipa(tmpdir: str, output: str, level: int) -> None: print(f"[?] was unable to zip {weird} file(s) due to timestamps") -def parse_cyan(args: dict[str, Any], tmpdir: str) -> None: - print("[*] parsing .cyan file..") - with zipfile.ZipFile(args["cyan"]) as zf: - DOT_PATH = f"{tmpdir}/cyan" - os.mkdir(DOT_PATH) +def parse_cyans(args: dict[str, Any], tmpdir: str) -> None: + for ind, cyan in enumerate(args["cyan"]): + print(f"[*] parsing {os.path.basename(cyan)} ..") - with zf.open("config.json") as f: - config = json.load(f) + with zipfile.ZipFile(cyan) as zf: + DOT_PATH = f"{tmpdir}/cyan-{ind}" + os.mkdir(DOT_PATH) - if "f" in config: - NAMES = [n for n in zf.namelist() if n.startswith("inject/")] - zf.extractall(DOT_PATH, NAMES) + with zf.open("config.json") as f: + config = json.load(f) - # ensure not None - args["f"] = args["f"] if args["f"] is not None else {} - for e in os.scandir(f"{DOT_PATH}/inject"): - args["f"][e.name] = e.path - del config["f"] - if "k" in config: - args["k"] = zf.extract("icon.idk", DOT_PATH) - del config["k"] - if "l" in config: - args["l"] = zf.extract("merge.plist", DOT_PATH) - del config["l"] - if "x" in config: - args["x"] = zf.extract("new.entitlements", DOT_PATH) - del config["x"] + if "f" in config: + NAMES = [n for n in zf.namelist() if n.startswith("inject/")] + zf.extractall(DOT_PATH, NAMES) - for k, v in config.items(): - args[k] = v + # ensure not None + args["f"] = args["f"] if args["f"] is not None else {} + for e in os.scandir(f"{DOT_PATH}/inject"): + args["f"][e.name] = e.path + del config["f"] + if "k" in config: + args["k"] = zf.extract("icon.idk", DOT_PATH) + del config["k"] + if "l" in config: + args["l"] = zf.extract("merge.plist", DOT_PATH) + del config["l"] + if "x" in config: + args["x"] = zf.extract("new.entitlements", DOT_PATH) + del config["x"] + + # the rest of the config (not the ones above, we `del` them) + for k, v in config.items(): + args[k] = v