diff --git a/.gitignore b/.gitignore index c18dd8d..372c13e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ __pycache__/ + diff --git a/.mypy.ini b/.mypy.ini deleted file mode 100644 index 4c10470..0000000 --- a/.mypy.ini +++ /dev/null @@ -1,2 +0,0 @@ -[mypy] -python_version = 3.12.3 diff --git a/.ruff.toml b/.ruff.toml index 782b4a4..23f9b37 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -1,5 +1,7 @@ -line-length = 78 -indent-width = 4 +line-length = 79 +indent-width = 2 +target-version = "py312" [lint] -select = ["E", "F"] +select = ["W", "E", "F", "C"] + diff --git a/LICENSE b/LICENSE index fdddb29..1e9858b 100644 --- a/LICENSE +++ b/LICENSE @@ -22,3 +22,4 @@ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to + diff --git a/README.md b/README.md index 4d9c604..adc16d0 100644 --- a/README.md +++ b/README.md @@ -5,3 +5,10 @@ rewriting [pyzule](https://github.com/asdfzxcvbn/pyzule), but actually good this this is pretty much just a hobby project that i'll work on when i'm bored. pyzule in its current state is kinda ugly, but it works and i haven't really had the motivation to work on it. there really isn't any need for improvements, anyway.. `cyan` will target python v3.12 (finally!), be pep8-compliant (hopefully..), and be type-hinted! + +## plan + +- have a __main__ file ofc, this is what `cyan` command runs +- also have a cyan file, it should have the main logic of the program +- have other files for a class of the ipa/app, main executable, etc + diff --git a/cyan.py b/cyan.py deleted file mode 100755 index 32cd01c..0000000 --- a/cyan.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/python3 -# cyan, aka pyzule-rw; by zx, 2024 - -import os -import sys -import argparse - -parser = argparse.ArgumentParser( - description="cyan, an azule \"clone\" for modifying iOS apps") -parser.add_argument("-o", metavar="output", - help="if unspecified, overwrites input") -parser.add_argument("-f", metavar="file", nargs="+", - help="a tweak to inject/item to be added to the bundle") - -parser.add_argument("--overwrite", action="store_true", - help="skip overwrite confirmation") - -parser.add_argument("input", help="the app to be modified (.app/.ipa)") -args = parser.parse_args() - -INPUT = os.path.realpath(args.input) -WORKING_DIR = os.getcwd() -PZ_DIR = os.path.expanduser("~/.config/cyan") -changed = False - -if not (INPUT.endswith(".ipa") or INPUT.endswith(".app")): - sys.exit("[!] input must be a .ipa/.app") -elif not os.path.exists(INPUT): - sys.exit("[!] input does not exist") -elif not args.o and (input("[<] override your input file? [y/N] ").strip() - .lower() not in ("y", "yes")): - sys.exit("[!] not overriding input, missing -o") diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7892fdd --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +lief + diff --git a/src/__main__.py b/src/__main__.py new file mode 100755 index 0000000..d4275ca --- /dev/null +++ b/src/__main__.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +# cyan, aka pyzule-rw; by zx, 2024 + +import argparse + +import cyan + + +def main() -> None: + parser = argparse.ArgumentParser( + description="cyan, an azule \"clone\" for modifying iOS apps" + ) + + parser.add_argument( + "-i", "--input", metavar="input", required=True, + help="the app to be modified (.app/.ipa)" + ) + parser.add_argument( + "-o", "--output", metavar="output", + help="if unspecified, overwrites input" + ) + + parser.add_argument( + "-f", metavar="file", nargs="+", + help="a tweak to inject/item to be added to the bundle" + ) + + parser.add_argument( + "--overwrite", action="store_true", + help="skip overwrite confirmation" + ) + + cyan.main(parser) + +if __name__ == "__main__": + main() + +# INPUT = os.path.realpath(args.input) +# WORKING_DIR = os.getcwd() +# PZ_DIR = os.path.expanduser("~/.config/cyan") +# changed = False + +# if not (INPUT.endswith(".ipa") or INPUT.endswith(".app")): +# sys.exit("[!] input must be a .ipa/.app") +# elif not os.path.exists(INPUT): +# sys.exit("[!] input does not exist") +# elif not args.o and (input("[<] override your input file? [y/N] ").strip() +# .lower() not in ("y", "yes")): +# sys.exit("[!] not overriding input, missing -o") diff --git a/src/cyan.py b/src/cyan.py new file mode 100644 index 0000000..90530fd --- /dev/null +++ b/src/cyan.py @@ -0,0 +1,25 @@ +import os +from argparse import ArgumentParser + +import tbhutils + + +def main(parser: ArgumentParser) -> None: + args = parser.parse_args() + args.i = os.path.normpath(args.input) + + if args.output is not None: + args.o = os.path.normpath(args.output) + if not (args.o.endswith(".app") or args.o.endswith(".ipa")): + print("[?] output's file extension not specified; will create ipa") + args.o += ".ipa" + else: + args.o = args.i + + arg_err = tbhutils.validate_inputs(args) + if arg_err is not None: + parser.error(arg_err) + + # verbose notices + if args.o + diff --git a/src/tbhutils.py b/src/tbhutils.py new file mode 100644 index 0000000..6c4281d --- /dev/null +++ b/src/tbhutils.py @@ -0,0 +1,17 @@ +import os +from typing import Optional +from argparse import Namespace + + +def validate_inputs(args: Namespace) -> Optional[str]: + if not ( + args.i.endswith(".ipa") + or args.i.endswith(".app") + ): + return "the input file must be an ipa/app" + + if not os.path.exists(args.i): + return f"{args.i} does not exist" + + +