diff --git a/copyparty/__main__.py b/copyparty/__main__.py
index 6c2d3fe3..08ad18f5 100644
--- a/copyparty/__main__.py
+++ b/copyparty/__main__.py
@@ -775,11 +775,22 @@ def get_sects():
values for --urlform:
\033[36mstash\033[35m dumps the data to file and returns length + checksum
\033[36msave,get\033[35m dumps to file and returns the page like a GET
- \033[36mprint,get\033[35m prints the data in the log and returns GET
- (leave out the ",get" to return an error instead)\033[0m
+ \033[36mprint \033[35m prints the data to log and returns an error
+ \033[36mprint,xm \033[35m prints the data to log and returns --xm output
+ \033[36mprint,get\033[35m prints the data to log and returns GET\033[0m
- note that the \033[35m--xm\033[0m hook will only run if \033[35m--urlform\033[0m
- is either \033[36mprint\033[0m or the default \033[36mprint,get\033[0m
+ note that the \033[35m--xm\033[0m hook will only run if \033[35m--urlform\033[0m is
+ either \033[36mprint\033[0m or \033[36mprint,get\033[0m or the default \033[36mprint,xm\033[0m
+
+ if an \033[35m--xm\033[0m hook returns text, then
+ the response code will be HTTP 202;
+ http/get responses will be HTTP 200
+
+ if there are multiple \033[35m--xm\033[0m hooks defined, then
+ the first hook that produced output is returned
+
+ if there are no \033[35m--xm\033[0m hooks defined, then the default
+ \033[36mprint,xm\033[0m behaves like \033[36mprint,get\033[0m (returning html)
"""
),
],
@@ -960,7 +971,7 @@ def add_general(ap, nc, srvname):
ap2.add_argument("-v", metavar="VOL", type=u, action="append", help="add volume, \033[33mSRC\033[0m:\033[33mDST\033[0m:\033[33mFLAG\033[0m; examples [\033[32m.::r\033[0m], [\033[32m/mnt/nas/music:/music:r:aed\033[0m], see --help-accounts")
ap2.add_argument("--grp", metavar="G:N,N", type=u, action="append", help="add group, \033[33mNAME\033[0m:\033[33mUSER1\033[0m,\033[33mUSER2\033[0m,\033[33m...\033[0m; example [\033[32madmins:ed,foo,bar\033[0m]")
ap2.add_argument("-ed", action="store_true", help="enable the ?dots url parameter / client option which allows clients to see dotfiles / hidden files (volflag=dots)")
- ap2.add_argument("--urlform", metavar="MODE", type=u, default="print,get", help="how to handle url-form POSTs; see \033[33m--help-urlform\033[0m")
+ ap2.add_argument("--urlform", metavar="MODE", type=u, default="print,xm", help="how to handle url-form POSTs; see \033[33m--help-urlform\033[0m")
ap2.add_argument("--wintitle", metavar="TXT", type=u, default="cpp @ $pub", help="server terminal title, for example [\033[32m$ip-10.1.2.\033[0m] or [\033[32m$ip-]")
ap2.add_argument("--name", metavar="TXT", type=u, default=srvname, help="server name (displayed topleft in browser and in mDNS)")
ap2.add_argument("--mime", metavar="EXT=MIME", type=u, action="append", help="map file \033[33mEXT\033[0mension to \033[33mMIME\033[0mtype, for example [\033[32mjpg=image/jpeg\033[0m]")
diff --git a/copyparty/httpcli.py b/copyparty/httpcli.py
index 5dd35164..2a5a86fc 100644
--- a/copyparty/httpcli.py
+++ b/copyparty/httpcli.py
@@ -1899,6 +1899,9 @@ class HttpCli(object):
if "stash" in opt:
return self.handle_stash(False)
+ xm = []
+ xm_rsp = {}
+
if "save" in opt:
post_sz, _, _, _, _, path, _ = self.dump_to_file(False)
self.log("urlform: %d bytes, %r" % (post_sz, path))
@@ -1921,7 +1924,7 @@ class HttpCli(object):
plain = plain[4:]
xm = self.vn.flags.get("xm")
if xm:
- runhook(
+ xm_rsp = runhook(
self.log,
self.conn.hsrv.broker,
None,
@@ -1945,6 +1948,13 @@ class HttpCli(object):
except Exception as ex:
self.log(repr(ex))
+ if "xm" in opt:
+ if xm:
+ self.loud_reply(xm_rsp.get("stdout") or "", status=202)
+ return True
+ else:
+ return self.handle_get()
+
if "get" in opt:
return self.handle_get()
diff --git a/copyparty/util.py b/copyparty/util.py
index a7d0fbbe..7ab92976 100644
--- a/copyparty/util.py
+++ b/copyparty/util.py
@@ -243,6 +243,7 @@ URL_BUG = URL_PRJ + "/issues/new?labels=bug&template=bug_report.md"
HTTPCODE = {
200: "OK",
201: "Created",
+ 202: "Accepted",
204: "No Content",
206: "Partial Content",
207: "Multi-Status",
@@ -3697,6 +3698,8 @@ def runhook(
elif k in ret:
if k == "rc" and v:
ret[k] = v
+ elif k == "stdout" and v and not ret[k]:
+ ret[k] = v
else:
ret[k] = v
except Exception as ex:
diff --git a/copyparty/web/browser.js b/copyparty/web/browser.js
index 9f1bef1a..9b80be9f 100644
--- a/copyparty/web/browser.js
+++ b/copyparty/web/browser.js
@@ -9127,14 +9127,18 @@ var msel = (function () {
function cb() {
xhrchk(this, L.fsm_xe1, L.fsm_xe2);
- if (this.status < 200 || this.status > 201) {
+ if (this.status < 200 || this.status > 202) {
sf.textContent = 'error: ' + hunpre(this.responseText);
return;
}
tb.value = '';
clmod(sf, 'vis');
- sf.textContent = 'sent: "' + this.msg + '"';
+ var txt = 'sent: ' + esc(this.msg) + '
';
+ if (this.status == 202)
+ txt += '
got: ' + esc(this.responseText) + '
';
+
+ sf.innerHTML = txt;
setTimeout(function () {
treectl.goto();
}, 100);