option to let mtp's keep stdout/stderr

This commit is contained in:
ed 2022-09-04 01:42:28 +02:00
parent 5fa8aaabb9
commit 788db47b95
4 changed files with 25 additions and 8 deletions

View file

@ -826,8 +826,11 @@ copyparty can invoke external programs to collect additional metadata for files
* "audio file" also means videos btw, as long as there is an audio stream * "audio file" also means videos btw, as long as there is an audio stream
* `-mtp ext=an,~/bin/file-ext.py` runs `~/bin/file-ext.py` to get the `ext` tag only if file is not audio (`an`) * `-mtp ext=an,~/bin/file-ext.py` runs `~/bin/file-ext.py` to get the `ext` tag only if file is not audio (`an`)
* `-mtp arch,built,ver,orig=an,eexe,edll,~/bin/exe.py` runs `~/bin/exe.py` to get properties about windows-binaries only if file is not audio (`an`) and file extension is exe or dll * `-mtp arch,built,ver,orig=an,eexe,edll,~/bin/exe.py` runs `~/bin/exe.py` to get properties about windows-binaries only if file is not audio (`an`) and file extension is exe or dll
* if you want to daisychain parsers, use the `p` flag to set processing order
you can control how the parser is killed if it times out with option `kt` killing the entire process tree (default), `km` just the main process, or `kn` let it continue running until copyparty is terminated * `-mtp foo=p1,~/a.py` runs before `-mtp foo=p2,~/b.py` and will forward all the tags detected so far as json to the stdin of b.py
* option `c0` disables capturing of stdout/stderr, so copyparty will not receive any tags from the process at all -- instead the invoked program is free to print whatever to the console, just using copyparty as a launcher
* `c1` captures stdout only, `c2` only stderr, and `c3` (default) captures both
* you can control how the parser is killed if it times out with option `kt` killing the entire process tree (default), `km` just the main process, or `kn` let it continue running until copyparty is terminated
if something doesn't work, try `--mtag-v` for verbose error messages if something doesn't work, try `--mtag-v` for verbose error messages
@ -846,7 +849,7 @@ that'll run the command `notify-send` with the path to the uploaded file as the
note that it will only trigger on new unique files, not dupes note that it will only trigger on new unique files, not dupes
and it will occupy the parsing threads, so fork anything expensive, or if you want to intentionally queue/singlethread you can combine it with `--mtag-mt 1` and it will occupy the parsing threads, so fork anything expensive (or set `kn` to have copyparty fork it for you) -- otoh if you want to intentionally queue/singlethread you can combine it with `--mtag-mt 1`
if this becomes popular maybe there should be a less janky way to do it actually if this becomes popular maybe there should be a less janky way to do it actually

View file

@ -16,7 +16,7 @@ goes without saying, but this is HELLA DANGEROUS,
GIVES RCE TO ANYONE WHO HAVE UPLOAD PERMISSIONS GIVES RCE TO ANYONE WHO HAVE UPLOAD PERMISSIONS
example copyparty config to use this: example copyparty config to use this:
--urlform save,get -v.::w:c,e2d,e2t,mte=+a1:c,mtp=a1=ad,kn,bin/mtag/very-bad-idea.py --urlform save,get -v.::w:c,e2d,e2t,mte=+a1:c,mtp=a1=ad,kn,c0,bin/mtag/very-bad-idea.py
recommended deps: recommended deps:
apt install xdotool libnotify-bin apt install xdotool libnotify-bin

View file

@ -45,6 +45,7 @@ class MParser(object):
self.timeout = 30 self.timeout = 30
self.force = False self.force = False
self.kill = "t" # tree; all children recursively self.kill = "t" # tree; all children recursively
self.capture = 3 # outputs to consume
self.audio = "y" self.audio = "y"
self.pri = 0 # priority; higher = later self.pri = 0 # priority; higher = later
self.ext = [] self.ext = []
@ -72,6 +73,10 @@ class MParser(object):
self.kill = arg[1:] # [t]ree [m]ain [n]one self.kill = arg[1:] # [t]ree [m]ain [n]one
continue continue
if arg.startswith("c"):
self.capture = int(arg[1:]) # 0=none 1=stdout 2=stderr 3=both
continue
if arg == "f": if arg == "f":
self.force = True self.force = True
continue continue
@ -519,7 +524,12 @@ class MTag(object):
if parser.bin.endswith(".py"): if parser.bin.endswith(".py"):
cmd = [sys.executable] + cmd cmd = [sys.executable] + cmd
args = {"env": env, "timeout": parser.timeout, "kill": parser.kill} args = {
"env": env,
"timeout": parser.timeout,
"kill": parser.kill,
"capture": parser.capture,
}
if parser.pri: if parser.pri:
zd = oth_tags.copy() zd = oth_tags.copy()

View file

@ -1862,12 +1862,16 @@ def runcmd(
argv: Union[list[bytes], list[str]], timeout: Optional[int] = None, **ka: Any argv: Union[list[bytes], list[str]], timeout: Optional[int] = None, **ka: Any
) -> tuple[int, str, str]: ) -> tuple[int, str, str]:
kill = ka.pop("kill", "t") # [t]ree [m]ain [n]one kill = ka.pop("kill", "t") # [t]ree [m]ain [n]one
capture = ka.pop("capture", 3) # 0=none 1=stdout 2=stderr 3=both
sin = ka.pop("sin", None) sin = ka.pop("sin", None)
if sin: if sin:
ka["stdin"] = sp.PIPE ka["stdin"] = sp.PIPE
p = sp.Popen(argv, stdout=sp.PIPE, stderr=sp.PIPE, **ka) cout = sp.PIPE if capture in [1, 3] else None
cerr = sp.PIPE if capture in [2, 3] else None
p = sp.Popen(argv, stdout=cout, stderr=cerr, **ka)
if not timeout or PY2: if not timeout or PY2:
stdout, stderr = p.communicate(sin) stdout, stderr = p.communicate(sin)
else: else:
@ -1887,8 +1891,8 @@ def runcmd(
stdout = b"" stdout = b""
stderr = b"" stderr = b""
stdout = stdout.decode("utf-8", "replace") stdout = stdout.decode("utf-8", "replace") if cout else b""
stderr = stderr.decode("utf-8", "replace") stderr = stderr.decode("utf-8", "replace") if cerr else b""
rc = p.returncode rc = p.returncode
if rc is None: if rc is None: