mirror of
https://github.com/9001/copyparty.git
synced 2025-08-20 02:12:20 -06:00
add markdown streaming
This commit is contained in:
parent
28c12ef3bf
commit
73c4f99687
|
@ -680,7 +680,7 @@ class HttpCli(object):
|
||||||
raise Pebkac(500, "mkdir failed, check the logs")
|
raise Pebkac(500, "mkdir failed, check the logs")
|
||||||
|
|
||||||
vpath = "{}/{}".format(self.vpath, sanitized).lstrip("/")
|
vpath = "{}/{}".format(self.vpath, sanitized).lstrip("/")
|
||||||
esc_paths = [quotep(vpath), html_escape(vpath)]
|
esc_paths = [quotep(vpath), html_escape(vpath, crlf=True)]
|
||||||
html = self.j2(
|
html = self.j2(
|
||||||
"msg",
|
"msg",
|
||||||
h2='<a href="/{}">go to /{}</a>'.format(*esc_paths),
|
h2='<a href="/{}">go to /{}</a>'.format(*esc_paths),
|
||||||
|
@ -1181,17 +1181,16 @@ class HttpCli(object):
|
||||||
template = self.j2(tpl)
|
template = self.j2(tpl)
|
||||||
|
|
||||||
st = os.stat(fsenc(fs_path))
|
st = os.stat(fsenc(fs_path))
|
||||||
# sz_md = st.st_size
|
|
||||||
ts_md = st.st_mtime
|
ts_md = st.st_mtime
|
||||||
|
|
||||||
st = os.stat(fsenc(html_path))
|
st = os.stat(fsenc(html_path))
|
||||||
ts_html = st.st_mtime
|
ts_html = st.st_mtime
|
||||||
|
|
||||||
# TODO dont load into memory ;_;
|
sz_md = 0
|
||||||
# (trivial fix, count the &'s)
|
for buf in yieldfile(fs_path):
|
||||||
with open(fsenc(fs_path), "rb") as f:
|
sz_md += len(buf)
|
||||||
md = f.read().replace(b"&", b"&")
|
for c, v in [[b"&", 4], [b"<", 3], [b">", 3]]:
|
||||||
sz_md = len(md)
|
sz_md += (len(buf) - len(buf.replace(c, b""))) * v
|
||||||
|
|
||||||
file_ts = max(ts_md, ts_html)
|
file_ts = max(ts_md, ts_html)
|
||||||
file_lastmod, do_send = self._chk_lastmod(file_ts)
|
file_lastmod, do_send = self._chk_lastmod(file_ts)
|
||||||
|
@ -1199,27 +1198,34 @@ class HttpCli(object):
|
||||||
self.out_headers["Cache-Control"] = "no-cache"
|
self.out_headers["Cache-Control"] = "no-cache"
|
||||||
status = 200 if do_send else 304
|
status = 200 if do_send else 304
|
||||||
|
|
||||||
|
boundary = "\roll\tide"
|
||||||
targs = {
|
targs = {
|
||||||
"edit": "edit" in self.uparam,
|
"edit": "edit" in self.uparam,
|
||||||
"title": html_escape(self.vpath),
|
"title": html_escape(self.vpath, crlf=True),
|
||||||
"lastmod": int(ts_md * 1000),
|
"lastmod": int(ts_md * 1000),
|
||||||
"md_plug": "true" if self.args.emp else "false",
|
"md_plug": "true" if self.args.emp else "false",
|
||||||
"md_chk_rate": self.args.mcr,
|
"md_chk_rate": self.args.mcr,
|
||||||
"md": "",
|
"md": boundary,
|
||||||
}
|
}
|
||||||
sz_html = len(template.render(**targs).encode("utf-8"))
|
html = template.render(**targs).encode("utf-8")
|
||||||
self.send_headers(sz_html + sz_md, status)
|
html = html.split(boundary.encode("utf-8"))
|
||||||
|
if len(html) != 2:
|
||||||
|
raise Exception("boundary appears in " + html_path)
|
||||||
|
|
||||||
|
self.send_headers(sz_md + len(html[0]) + len(html[1]), status)
|
||||||
|
|
||||||
logmsg += unicode(status)
|
logmsg += unicode(status)
|
||||||
if self.mode == "HEAD" or not do_send:
|
if self.mode == "HEAD" or not do_send:
|
||||||
self.log(logmsg)
|
self.log(logmsg)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# TODO jinja2 can stream this right?
|
|
||||||
targs["md"] = md.decode("utf-8", "replace")
|
|
||||||
html = template.render(**targs).encode("utf-8")
|
|
||||||
try:
|
try:
|
||||||
self.s.sendall(html)
|
self.s.sendall(html[0])
|
||||||
|
for buf in yieldfile(fs_path):
|
||||||
|
self.s.sendall(html_bescape(buf))
|
||||||
|
|
||||||
|
self.s.sendall(html[1])
|
||||||
|
|
||||||
except:
|
except:
|
||||||
self.log(logmsg + " \033[31md/c\033[0m")
|
self.log(logmsg + " \033[31md/c\033[0m")
|
||||||
return False
|
return False
|
||||||
|
@ -1300,7 +1306,7 @@ class HttpCli(object):
|
||||||
else:
|
else:
|
||||||
vpath += "/" + node
|
vpath += "/" + node
|
||||||
|
|
||||||
vpnodes.append([quotep(vpath) + "/", html_escape(node)])
|
vpnodes.append([quotep(vpath) + "/", html_escape(node, crlf=True)])
|
||||||
|
|
||||||
vn, rem = self.auth.vfs.get(
|
vn, rem = self.auth.vfs.get(
|
||||||
self.vpath, self.uname, self.readable, self.writable
|
self.vpath, self.uname, self.readable, self.writable
|
||||||
|
@ -1394,7 +1400,7 @@ class HttpCli(object):
|
||||||
margin = '<a href="{}?zip">zip</a>'.format(quotep(href))
|
margin = '<a href="{}?zip">zip</a>'.format(quotep(href))
|
||||||
elif fn in hist:
|
elif fn in hist:
|
||||||
margin = '<a href="{}.hist/{}">#{}</a>'.format(
|
margin = '<a href="{}.hist/{}">#{}</a>'.format(
|
||||||
base, html_escape(hist[fn][2], quote=True), hist[fn][0]
|
base, html_escape(hist[fn][2], quote=True, crlf=True), hist[fn][0]
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
margin = "-"
|
margin = "-"
|
||||||
|
@ -1536,7 +1542,7 @@ class HttpCli(object):
|
||||||
have_b_u=(self.writable and self.uparam.get("b") == "u"),
|
have_b_u=(self.writable and self.uparam.get("b") == "u"),
|
||||||
url_suf=url_suf,
|
url_suf=url_suf,
|
||||||
logues=logues,
|
logues=logues,
|
||||||
title=html_escape(self.vpath),
|
title=html_escape(self.vpath, crlf=True),
|
||||||
srv_info=srv_info,
|
srv_info=srv_info,
|
||||||
)
|
)
|
||||||
self.reply(html.encode("utf-8", "replace"))
|
self.reply(html.encode("utf-8", "replace"))
|
||||||
|
|
|
@ -616,17 +616,24 @@ def exclude_dotfiles(filepaths):
|
||||||
return [x for x in filepaths if not x.split("/")[-1].startswith(".")]
|
return [x for x in filepaths if not x.split("/")[-1].startswith(".")]
|
||||||
|
|
||||||
|
|
||||||
def html_escape(s, quote=False):
|
def html_escape(s, quote=False, crlf=False):
|
||||||
"""html.escape but also newlines"""
|
"""html.escape but also newlines"""
|
||||||
s = (
|
s = s.replace("&", "&").replace("<", "<").replace(">", ">")
|
||||||
s.replace("&", "&")
|
|
||||||
.replace("<", "<")
|
|
||||||
.replace(">", ">")
|
|
||||||
.replace("\r", " ")
|
|
||||||
.replace("\n", " ")
|
|
||||||
)
|
|
||||||
if quote:
|
if quote:
|
||||||
s = s.replace('"', """).replace("'", "'")
|
s = s.replace('"', """).replace("'", "'")
|
||||||
|
if crlf:
|
||||||
|
s = s.replace("\r", " ").replace("\n", " ")
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def html_bescape(s, quote=False, crlf=False):
|
||||||
|
"""html.escape but bytestrings"""
|
||||||
|
s = s.replace(b"&", b"&").replace(b"<", b"<").replace(b">", b">")
|
||||||
|
if quote:
|
||||||
|
s = s.replace(b'"', b""").replace(b"'", b"'")
|
||||||
|
if crlf:
|
||||||
|
s = s.replace(b"\r", b" ").replace(b"\n", b" ")
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue