mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 09:02:15 -06:00
option to let mtp's keep stdout/stderr
This commit is contained in:
parent
5fa8aaabb9
commit
788db47b95
|
@ -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
|
||||
* `-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
|
||||
|
||||
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 you want to daisychain parsers, use the `p` flag to set processing order
|
||||
* `-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
|
||||
|
||||
|
@ -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
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -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,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:
|
||||
apt install xdotool libnotify-bin
|
||||
|
|
|
@ -45,6 +45,7 @@ class MParser(object):
|
|||
self.timeout = 30
|
||||
self.force = False
|
||||
self.kill = "t" # tree; all children recursively
|
||||
self.capture = 3 # outputs to consume
|
||||
self.audio = "y"
|
||||
self.pri = 0 # priority; higher = later
|
||||
self.ext = []
|
||||
|
@ -72,6 +73,10 @@ class MParser(object):
|
|||
self.kill = arg[1:] # [t]ree [m]ain [n]one
|
||||
continue
|
||||
|
||||
if arg.startswith("c"):
|
||||
self.capture = int(arg[1:]) # 0=none 1=stdout 2=stderr 3=both
|
||||
continue
|
||||
|
||||
if arg == "f":
|
||||
self.force = True
|
||||
continue
|
||||
|
@ -519,7 +524,12 @@ class MTag(object):
|
|||
if parser.bin.endswith(".py"):
|
||||
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:
|
||||
zd = oth_tags.copy()
|
||||
|
|
|
@ -1862,12 +1862,16 @@ 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
|
||||
capture = ka.pop("capture", 3) # 0=none 1=stdout 2=stderr 3=both
|
||||
|
||||
sin = ka.pop("sin", None)
|
||||
if sin:
|
||||
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:
|
||||
stdout, stderr = p.communicate(sin)
|
||||
else:
|
||||
|
@ -1887,8 +1891,8 @@ def runcmd(
|
|||
stdout = b""
|
||||
stderr = b""
|
||||
|
||||
stdout = stdout.decode("utf-8", "replace")
|
||||
stderr = stderr.decode("utf-8", "replace")
|
||||
stdout = stdout.decode("utf-8", "replace") if cout else b""
|
||||
stderr = stderr.decode("utf-8", "replace") if cerr else b""
|
||||
|
||||
rc = p.returncode
|
||||
if rc is None:
|
||||
|
|
Loading…
Reference in a new issue