diff --git a/requirements.txt b/requirements.txt index c0d9401..62d0c33 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -peewee -prompt_toolkit>=3.0.32 +peewee>=3.17.6 +prompt_toolkit>=3.0.47 requests -tinyscript>=1.28.6 +tinyscript>=1.30.15 diff --git a/src/sploitkit/base/commands/general.py b/src/sploitkit/base/commands/general.py index 61866c0..162bbed 100644 --- a/src/sploitkit/base/commands/general.py +++ b/src/sploitkit/base/commands/general.py @@ -55,7 +55,7 @@ def run(self, text): t = BorderlessTable(data, "Matching modules") print_formatted_text(t.table) n = len(data) - 2 - self.logger.info("{} match{} found".format(n, ["", "es"][n > 0])) + self.logger.info(f"{n} match{['', 'es'][n > 0]} found") class Show(Command): diff --git a/src/sploitkit/base/commands/project.py b/src/sploitkit/base/commands/project.py index eed0012..38e419a 100644 --- a/src/sploitkit/base/commands/project.py +++ b/src/sploitkit/base/commands/project.py @@ -45,22 +45,22 @@ class Archive(ProjectRootCommand): def run(self, project): projpath = Path(self.workspace).joinpath(project) folder = ProjectPath(projpath) - self.logger.debug("Archiving project '{}'...".format(project)) + self.logger.debug(f"Archiving project '{project}'...") ask = self.console.config.option("ENCRYPT_PROJECT").value try: folder.archive(ask=ask) - self.logger.success("'{}' archived".format(project)) + self.logger.success(f"'{project}' archived") except OSError as e: - logger.error(str(e)) - self.logger.failure("'{}' not archived".format(project)) + self.logger.error(str(e)) + self.logger.failure(f"'{project}' not archived") class Delete(ProjectRootCommand): """ Delete a project """ def run(self, project): - self.logger.debug("Deleting project '{}'...".format(project)) + self.logger.debug(f"Deleting project '{project}'...") self.workspace.joinpath(project).remove() - self.logger.success("'{}' deleted".format(project)) + self.logger.success(f"'{project}' deleted") class Load(ProjectRootCommand): @@ -70,16 +70,16 @@ def complete_values(self): return [x.stem for x in self.workspace.iterfiles(".zip")] def run(self, project): - self.logger.debug("Loading archive '{}'...".format(project + ".zip")) + self.logger.debug(f"Loading archive '{project}.zip'...") projpath = Path(self.workspace).joinpath(project) archive = ProjectPath(projpath.with_suffix(".zip")) ask = self.console.config.option("ENCRYPT_PROJECT").value try: archive.load(ask=ask) - self.logger.success("'{}' loaded".format(project)) + self.logger.success(f"'{project}' loaded") except Exception as e: - logger.error("Bad password" if "error -3" in str(e) else str(e)) - self.logger.failure("'{}' not loaded".format(project)) + self.logger.error("Bad password" if "error -3" in str(e) else str(e)) + self.logger.failure(f"'{project}' not loaded") def validate(self, project): if project not in self.complete_values(): @@ -100,9 +100,9 @@ def run(self, project): "do you want to load the archive instead ?"): loader.run(project) if not p.exists(): - self.logger.debug("Creating project '{}'...".format(project)) + self.logger.debug(f"Creating project '{project}'...") p.mkdir() - self.logger.success("'{}' created".format(project)) + self.logger.success(f"'{project}' created") ProjectConsole(self.console, project).start() self.config['WORKSPACE'] = str(Path(self.config['WORKSPACE']).parent) diff --git a/src/sploitkit/base/commands/recording.py b/src/sploitkit/base/commands/recording.py index d55b7df..b45b351 100644 --- a/src/sploitkit/base/commands/recording.py +++ b/src/sploitkit/base/commands/recording.py @@ -14,7 +14,7 @@ class RecordStatus(Command): values = ["status"] def run(self, status): - self.logger.info("Recording is {}".format(["disabled", "enabled"][self.recorder.enabled])) + self.logger.info(f"Recording is {['disabled', 'enabled'][self.recorder.enabled]}") # ------------------------------ ROOT-LEVEL COMMANDS --------------------------- @@ -38,7 +38,7 @@ def run(self, key, rcfile=None): elif key == "stop": self.recorder.stop() elif key == "status": - self.logger.info("Recording is {}".format(["disabled", "enabled"][self.recorder.enabled])) + self.logger.info(f"Recording is {['disabled', 'enabled'][self.recorder.enabled]}") def validate(self, key, rcfile=None): if key == "start": @@ -57,6 +57,6 @@ def complete_values(self, key=None): return [x.name for x in Path(self.workspace).iterfiles(".rc")] def run(self, rcfile): - self.logger.debug("Replaying commands from file '{}'...".format(rcfile)) + self.logger.debug(f"Replaying commands from file '{rcfile}'...") self.console.replay(rcfile) diff --git a/src/sploitkit/base/commands/utils.py b/src/sploitkit/base/commands/utils.py index a345508..32535b0 100644 --- a/src/sploitkit/base/commands/utils.py +++ b/src/sploitkit/base/commands/utils.py @@ -121,7 +121,7 @@ class State(DebugCommand): """ Display console's shared state """ def run(self): for k, v in self.console.state.items(): - print_formatted_text("\n{}:".format(k)) + print_formatted_text(f"\n{k}:") v = v or "" if len(v) == 0: continue diff --git a/src/sploitkit/base/models/organization.py b/src/sploitkit/base/models/organization.py index aecbcde..5fc5c48 100644 --- a/src/sploitkit/base/models/organization.py +++ b/src/sploitkit/base/models/organization.py @@ -23,7 +23,7 @@ class Meta: @property def fullname(self): - return "{} {} ({})".format(self.firstname, self.lastname, self.role) + return f"{self.firstname} {self.lastname} ({self.role})" class EmployeeUnit(BaseModel): diff --git a/src/sploitkit/core/command.py b/src/sploitkit/core/command.py index 29e934c..1ab5a5c 100755 --- a/src/sploitkit/core/command.py +++ b/src/sploitkit/core/command.py @@ -51,7 +51,7 @@ def __init__(self, *args): s += " [" i = [] for a, d in zip(args[len(args)-len(defs):], defs): - i.append("{}={}".format(a, d) if d is not None else a) + i.append(f"{a}={d}" if d is not None else a) s += " ".join(i) + "]" self.signature = s self.args, self.defaults = args, defs @@ -182,7 +182,7 @@ def get_help(cls, *levels, **kwargs): continue d.append([n, getattr(c, "description", "")]) if len(d) > 1: - t = BorderlessTable(d, "{} commands".format(l.capitalize())) + t = BorderlessTable(d, f"{l.capitalize()} commands") s += t.table + "\n" i += 1 return "\n" + s.strip() + "\n" if i > 0 else "" @@ -200,13 +200,13 @@ def register_command(cls, subcls): Command.commands[l][subcls.name] = subcls for alias in subcls.aliases: Command.commands[l][alias] = subcls - logger.detail("Registered command alias '{}'".format(alias)) + logger.detail(f"Registered command alias '{alias}'") @classmethod def set_style(cls, style): """ Set the style of command name. """ if style not in COMMAND_STYLES: - raise ValueError("Command style must be one of the followings: [{}]".format("|".join(COMMAND_STYLES))) + raise ValueError(f"Command style must be one of the followings: [{'|'.join(COMMAND_STYLES)}]") MetaCommand.style = style @classmethod @@ -234,7 +234,7 @@ def unregister_command(cls, subcls): for l in levels: if len(Command.commands[l]) == 0: del Command.commands[l] - logger.detail("Unregistered command '{}/{}'".format(l, n)) + logger.detail(f"Unregistered command '{l}/{n}'") @classmethod def unregister_commands(cls, *identifiers): @@ -248,7 +248,7 @@ def unregister_commands(cls, *identifiers): # apply deletions if n is None: if f not in cls._functionalities: - raise ValueError("Unknown functionality {}".format(f)) + raise ValueError(f"Unknown functionality {f}") p = Path(__file__).parent.joinpath("../base/commands/" + f + ".py").resolve() for c in PythonPath(str(p)).get_classes(Command): Command.unregister_command(c) diff --git a/src/sploitkit/core/components/files.py b/src/sploitkit/core/components/files.py index fd5f005..aafa27e 100755 --- a/src/sploitkit/core/components/files.py +++ b/src/sploitkit/core/components/files.py @@ -72,7 +72,7 @@ def get(self, locator, *args, **kwargs): with open(path, 'rb') as f: self[locator] = f.read() else: - raise ValueError("Unsupported scheme '{}'".format(scheme)) + raise ValueError(f"Unsupported scheme '{scheme}'") def page(self, *filenames): """ Page a list of files using Less. """ diff --git a/src/sploitkit/core/components/store.py b/src/sploitkit/core/components/store.py index 106fe78..41d6b8c 100755 --- a/src/sploitkit/core/components/store.py +++ b/src/sploitkit/core/components/store.py @@ -118,7 +118,7 @@ def snapshot(self, save=True): self.close() if save: self._last_snapshot += 1 - s = "{}.snapshot{}".format(self.path, self._last_snapshot) + s = f"{self.path}.snapshot{self._last_snapshot}" from shutil import copy copy(self.path, s) if save else copy(s, self.path) if not save: diff --git a/src/sploitkit/core/components/validator.py b/src/sploitkit/core/components/validator.py index 0b5d203..1181ad7 100755 --- a/src/sploitkit/core/components/validator.py +++ b/src/sploitkit/core/components/validator.py @@ -30,7 +30,7 @@ def validate(self, document): try: c._validate(*tokens[1:]) except Exception as e: - m = "Command syntax: %s{}" % c.signature.format(cmd) + m = f"Command syntax: {c.signature.format(cmd)}" e = str(e) if not e.startswith("validate() "): m = m.format([" (" + e + ")", ""][len(e) == 0]) diff --git a/src/sploitkit/core/console.py b/src/sploitkit/core/console.py index a580383..fcbe5af 100755 --- a/src/sploitkit/core/console.py +++ b/src/sploitkit/core/console.py @@ -184,7 +184,7 @@ def __init(self, **kwargs): def _close(self): """ Gracefully close the console. """ - self.logger.debug("Exiting {}[{}]".format(self.__class__.__name__, id(self))) + self.logger.debug(f"Exiting {self.__class__.__name__}[{id(self)}]") if hasattr(self, "close") and isfunction(self.close): self.close() # cleanup references for this console @@ -230,7 +230,7 @@ def _get_tokens(self, text, suffix=("", "\"", "'")): def _reset_logname(self): """ Reset logger's name according to console's attributes. """ try: - self.logger.name = "{}:{}".format(self.level, self.logname) + self.logger.name = f"{self.level}:{self.logname}" except AttributeError: self.logger.name = self.__class__.name @@ -238,7 +238,7 @@ def _run_if_defined(self, func): """ Run the given function if it is defined at the module level. """ if hasattr(self, "module") and hasattr(self.module, func) and \ not (getattr(self.module._instance, func)() is None): - self.logger.debug("{} failed".format(func)) + self.logger.debug(f"{func} failed") return False return True @@ -388,7 +388,7 @@ def start(self): """ Start looping with console's session prompt. """ reexec = None self._reset_logname() - self.logger.debug("Starting {}[{}]".format(self.__class__.__name__, id(self))) + self.logger.debug(f"Starting {self.__class__.__name__}[{id(self)}]") # execute attached module's pre-load function if relevant self._run_if_defined("preload") # now start the console loop @@ -474,7 +474,7 @@ def uptime(self): s = t.total_seconds() h, _ = divmod(s, 3600) m, s = divmod(_, 60) - return "{:02}:{:02}:{:02}".format(int(h), int(m), int(s)) + return f"{h:02}:{m:02}:{s:02}" class ConsoleDuplicate(Exception): @@ -592,7 +592,7 @@ def _set_logging(self, debug=False, to_file=True, **kwargs): # setup internal (dev) loggers with the default logging.configLogger (enhancement to logging from Tinyscript) set_logging_level(l, "core", config_func=lambda lgr, lvl: get_logger(lgr.name, p2, lvl, True, dev)) if l != "INFO" and not kwargs.get('silent', False): - self.logger.debug("Set logging to {}".format(l)) + self.logger.debug(f"Set logging to {l}") def _set_workspace(self): """ Set a new APP_FOLDER, moving an old to the new one if necessary. """ diff --git a/src/sploitkit/core/entity.py b/src/sploitkit/core/entity.py index f5ada95..3e740db 100755 --- a/src/sploitkit/core/entity.py +++ b/src/sploitkit/core/entity.py @@ -38,7 +38,7 @@ def load_entities(entities, *sources, **kwargs): for n in ENTITIES: n = n.lower() for m in kwargs.get("select", {}).get(n, [""]): - m = "../base/{}s/".format(n) + m + [".py", ""][m == ""] + m = f"../base/{n}s/" + m + [".py", ""][m == ""] p = Path(__file__).parent.joinpath(m).resolve() if p.exists(): sources.insert(0, p) @@ -292,7 +292,7 @@ def _execv(value): if check_key: for ssk, ssv in sv.items(): if ssk not in cs.keys() or cs[ssk] != ssv: - _tmp.append("{}={}".format(sk, sv)) + _tmp.append(f"{sk}={sv}") break # case 2: {None: ...} else: @@ -307,7 +307,7 @@ def _execv(value): if ref is not None and ref in values[1:]: found = True if not found: - _tmp.append("{}?{}".format(sk, ref)) + _tmp.append(f"{sk}?{ref}") elif is_dict(ssv): # e.g. {monitor:True} found = False @@ -321,15 +321,15 @@ def _execv(value): found = True break if not found: - v = ["{}:{}".format(sssk, sssv), sssv][sssv is None] - _tmp.append("{}?{}".format(sk, v)) + v = [f"{sssk}:{sssv}", sssv][sssv is None] + _tmp.append(f"{sk}?{v}") elif ssv not in cs.values(): - _tmp.append("{}?{}".format(sk, ssv)) + _tmp.append(f"{sk}?{ssv}") break # exact match between any other type than dict else: if sv != Console._state[sk]: - _tmp.append("{}={}".format(sk, sv)) + _tmp.append(f"{sk}={sv}") if len(_tmp) > 0: errors.setdefault("state", []) errors['state'].extend(_tmp) @@ -356,7 +356,7 @@ def _execv(value): errors["packages"].append((package, not_)) cls._enabled = False else: - raise ValueError("Unknown requirements type '{}'".format(k)) + raise ValueError(f"Unknown requirements type '{k}'") cls._errors = errors # check for applicability cls._applicable = True @@ -442,21 +442,21 @@ def msg(scname, key, item): if m is not None: return m.format(item) if key == "file": - return "'{}' {}found".format(item, not_s) + return f"'{item}' {not_s}found" elif key == "packages": - return "'{}' system package is {}installed".format(item, not_s) + return f"'{item}' system package is {not_s}installed" elif key == "python": - return "'{}' Python package is {}installed".format(item, not_s) + return f"'{item}' Python package is {not_s}installed" elif key == "tools": - return "'{}' tool is {}installed".format(item, not_s) + return f"'{item}' tool is {not_s}installed" elif key == "state": item = re.split(r"(\=|\?)", item, 1) if len(item) == 1: - return "'{}' state key is not defined".format(item[0]) + return f"'{item[0]}' state key is not defined" elif item[1] == "=": - return "'{}' state key does not match the expected value '{}'".format(item[0], item[2]) + return f"'{item[0]}' state key does not match the expected value '{item[2]}'" elif item[1] == "?": - return "'{}' state key is expected to have value '{}' at least once".format(item[0], item[2]) + return f"'{item[0]}' state key is expected to have value '{item[2]}' at least once" # list issues using the related class method t = "\n" d = OrderedDict() @@ -473,7 +473,7 @@ def msg(scname, key, item): for cname, scnames in names.items(): scnames = list(set(scnames)) cname += ["", "s"][len(scnames) > 1] - t += "{}: {}\n".format(cname, ", ".join(sorted(scnames))) + t += f"{cname}: {', '.join(sorted(scnames))}\n" # exception to issue messages: 'config' requirement t += "- " + "\n- ".join(msg(scname, k, e) for k, err in errors.items() for e in err if k != "config") + "\n" return "" if t.strip() == "" else t @@ -540,7 +540,7 @@ def register_subclass(cls, subcls): # manually get subclass' name because of MetaModel not having the "name" property (would be considered a # Peewee database field) n = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', re.sub(r'(.)([A-Z][a-z]+)', r'\1_\2', subcls.__name__)).lower() - logger.detail("Registered {} '{}'".format(subcls.entity, n)) + logger.detail(f"Registered {subcls.entity} '{n}'") @classmethod def unregister_subclass(cls, subcls): @@ -551,7 +551,7 @@ def unregister_subclass(cls, subcls): if cls in Entity._subclasses.keys(): try: Entity._subclasses[cls].remove(subcls) - logger.detail("Unregistered {} '{}'".format(subcls.entity, n)) + logger.detail(f"Unregistered {subcls.entity} '{n}'") except ValueError: pass @@ -563,7 +563,7 @@ def unregister_subclasses(cls, *subclss): def run(self, *args, **kwargs): """ Generic method for running Entity's logic. """ - raise NotImplementedError("{}'s run() method is not implemented".format(self.__class__.__name__)) + raise NotImplementedError(f"{self.__class__.__name__}'s run() method is not implemented") class MetaEntityBase(type): diff --git a/src/sploitkit/core/model.py b/src/sploitkit/core/model.py index 13d6b98..40c3b6c 100755 --- a/src/sploitkit/core/model.py +++ b/src/sploitkit/core/model.py @@ -23,7 +23,7 @@ def __new__(meta, name, bases, clsdict): pass # add triggers here #try: - # trigger = "{}_updated".format(subcls._meta.table_name) + # trigger = f"{subcls._meta.table_name}_updated" # subcls.add_trigger(trigger, "AFTER", "UPDATE", "UPDATE", "SET updated=CURRENT_TIMESTAMP") #except AttributeError: # pass diff --git a/src/sploitkit/core/module.py b/src/sploitkit/core/module.py index 8565a65..88c6417 100755 --- a/src/sploitkit/core/module.py +++ b/src/sploitkit/core/module.py @@ -119,7 +119,7 @@ def get_help(cls, category=None): key=lambda x: x[1].name): e = ["N", "Y"][m.enabled] d.append([m.name, m.subpath, e, m.description]) - t = BorderlessTable(d, "{} modules".format(c.capitalize())) + t = BorderlessTable(d, f"{c.capitalize()} modules") s += t.table + "\n\n" i += 1 return "\n" + s.strip() + "\n" if i > 0 else "" @@ -159,7 +159,7 @@ def get_summary(cls): mlen = max(map(len, m)) s = "\n" for line in m: - s += ("\t-=[ {: <" + str(mlen) + "} ]=-\n").format(line) + s += f"\t-=[ {line: <{mlen}} ]=-\n" return s return "" @@ -182,7 +182,7 @@ def unregister_module(cls, subcls): if p == M.path and n == M.name: Module.subclasses.remove(M) break - logger.detail("Unregistered module '{}/{}'".format(p, n)) + logger.detail(f"Unregistered module '{p}/{n}'") @classmethod def unregister_modules(cls, *subcls):