diff --git a/bin/mtag/very-bad-idea.py b/bin/mtag/very-bad-idea.py index eb161906..0885f54e 100755 --- a/bin/mtag/very-bad-idea.py +++ b/bin/mtag/very-bad-idea.py @@ -16,7 +16,7 @@ goes without saying, but this is HELLA DANGEROUS, GIVES RCE TO ANYONE WHO HAVE UPLOAD PERMISSIONS example copyparty config to use this: - --urlform save,get -v.::w:c,e2d,e2t,mte=+a1:c,mtp=a1=ad,bin/mtag/very-bad-idea.py + --urlform save,get -v.::w:c,e2d,e2t,mte=+a1:c,mtp=a1=ad,kn,bin/mtag/very-bad-idea.py recommended deps: apt install xdotool libnotify-bin @@ -64,7 +64,7 @@ EOF chmod 755 /usr/local/bin/chromium-browser # start the server (note: replace `-v.::rw:` with `-v.::w:` to disallow retrieving uploaded stuff) -cd ~/Downloads; python3 copyparty-sfx.py --urlform save,get -v.::rw:c,e2d,e2t,mte=+a1:c,mtp=a1=ad,very-bad-idea.py +cd ~/Downloads; python3 copyparty-sfx.py --urlform save,get -v.::rw:c,e2d,e2t,mte=+a1:c,mtp=a1=ad,kn,very-bad-idea.py """ diff --git a/copyparty/mtag.py b/copyparty/mtag.py index 1b7a44e9..100f8406 100644 --- a/copyparty/mtag.py +++ b/copyparty/mtag.py @@ -10,7 +10,7 @@ import sys from .__init__ import PY2, WINDOWS, unicode from .bos import bos -from .util import REKOBO_LKEY, fsenc, retchk, runcmd, uncyg +from .util import REKOBO_LKEY, fsenc, retchk, runcmd, uncyg, min_ex try: from typing import Any, Union @@ -44,6 +44,7 @@ class MParser(object): self.timeout = 30 self.force = False + self.kill = "t" # tree; all children recursively self.audio = "y" self.ext = [] @@ -66,6 +67,10 @@ class MParser(object): self.audio = arg[1:] # [r]equire [n]ot [d]ontcare continue + if arg.startswith("k"): + self.kill = arg[1:] # [t]ree [m]ain [n]one + continue + if arg == "f": self.force = True continue @@ -499,7 +504,7 @@ class MTag(object): if parser.bin.endswith(".py"): cmd = [sys.executable] + cmd - args = {"env": env, "timeout": parser.timeout} + args = {"env": env, "timeout": parser.timeout, "kill": parser.kill} if WINDOWS: args["creationflags"] = 0x4000 @@ -521,6 +526,8 @@ class MTag(object): if tag and tag in zj: ret[tag] = zj[tag] except: - pass + if self.args.mtag_v: + t = "mtag error: tagname {}, parser {}, file {} => {}" + self.log(t.format(tagname, parser.bin, abspath, min_ex())) return ret diff --git a/copyparty/util.py b/copyparty/util.py index d7c4a782..5ad8db44 100644 --- a/copyparty/util.py +++ b/copyparty/util.py @@ -1565,6 +1565,7 @@ def killtree(root: int) -> None: def runcmd( argv: Union[list[bytes], list[str]], timeout: Optional[int] = None, **ka: Any ) -> tuple[int, str, str]: + kill = ka.pop("kill", "t") # [t]ree [m]ain [n]one p = sp.Popen(argv, stdout=sp.PIPE, stderr=sp.PIPE, **ka) if not timeout or PY2: stdout, stderr = p.communicate() @@ -1572,12 +1573,27 @@ def runcmd( try: stdout, stderr = p.communicate(timeout=timeout) except sp.TimeoutExpired: - killtree(p.pid) - stdout, stderr = p.communicate() + if kill == "n": + return -18, "", "" # SIGCONT; leave it be + elif kill == "m": + p.kill() + else: + killtree(p.pid) + + try: + stdout, stderr = p.communicate(timeout=1) + except: + stdout = b"" + stderr = b"" stdout = stdout.decode("utf-8", "replace") stderr = stderr.decode("utf-8", "replace") - return p.returncode, stdout, stderr + + rc = p.returncode + if rc is None: + rc = -14 # SIGALRM; failed to kill + + return rc, stdout, stderr def chkcmd(argv: Union[list[bytes], list[str]], **ka: Any) -> tuple[str, str]: