From a1c7a095ee83bbda5b68c4b1a2796ed409ab345d Mon Sep 17 00:00:00 2001 From: ed Date: Thu, 19 Jun 2025 17:07:06 +0000 Subject: [PATCH] textfile-streaming fixes; * give up on disconnect * block scrapers from tailing * prism throws on window-resize if riced object has poofed * fix prism-init race --- copyparty/__main__.py | 2 +- copyparty/httpcli.py | 4 ++++ copyparty/web/browser.js | 25 ++++++++++++++++++------- copyparty/web/util.js | 2 +- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/copyparty/__main__.py b/copyparty/__main__.py index 4d6417bc..c707033c 100644 --- a/copyparty/__main__.py +++ b/copyparty/__main__.py @@ -1600,7 +1600,6 @@ def run_argparse( add_db_metadata(ap) add_thumbnail(ap) add_transcoding(ap) - add_tail(ap) add_rss(ap) add_ftp(ap) add_webdav(ap) @@ -1615,6 +1614,7 @@ def run_argparse( add_hooks(ap) add_stats(ap) add_txt(ap) + add_tail(ap) add_og(ap) add_ui(ap, retry) add_admin(ap) diff --git a/copyparty/httpcli.py b/copyparty/httpcli.py index b35fb695..d490f19c 100644 --- a/copyparty/httpcli.py +++ b/copyparty/httpcli.py @@ -3815,6 +3815,10 @@ class HttpCli(object): return txt def _can_tail(self, volflags: dict[str, Any]) -> bool: + zp = self.args.ua_nodoc + if zp and zp.search(self.ua): + t = "this URL contains no valuable information for bots/crawlers" + raise Pebkac(403, t) lvl = volflags["tail_who"] if "notail" in volflags or not lvl: raise Pebkac(400, "tail is disabled in server config") diff --git a/copyparty/web/browser.js b/copyparty/web/browser.js index 0f82436c..35fc6707 100644 --- a/copyparty/web/browser.js +++ b/copyparty/web/browser.js @@ -5817,7 +5817,9 @@ var fileman = (function () { var showfile = (function () { - var r = {}; + var r = { + 'nrend': 0, + }; r.map = { '.ahk': 'autohotkey', '.bas': 'basic', @@ -5956,10 +5958,10 @@ var showfile = (function () { ro.read().then(function(v) { if (r.tail_id != me) return; - v = v.value; - if (v == '\x00') + var vt = v.done ? '\n*** lost connection to copyparty ***' : v.value; + if (vt == '\x00') return rf(); - txt += v; + txt += vt; var ofs = txt.length - r.tailnb; if (ofs > 0) { var ofs2 = txt.indexOf('\n', ofs); @@ -5973,7 +5975,8 @@ var showfile = (function () { edoc.innerHTML = html; if (r.tail2end) window.scrollTo(0, wfp.offsetTop - window.innerHeight); - rf(); + if (!v.done) + rf(); }); }; if (r.tail_id == me) @@ -6036,6 +6039,7 @@ var showfile = (function () { function render(doc, no_push) { r.q = null; + r.nrend++; var url = r.url = doc[0], lnh = doc[1], txt = doc[2], @@ -6050,9 +6054,13 @@ var showfile = (function () { ebi('editdoc').style.display = (has(perms, 'write') && (is_md || has(perms, 'delete'))) ? '' : 'none'; var wr = ebi('bdoc'), + nrend = r.nrend, defer = !Prism.highlightElement; var fun = function (el) { + if (r.nrend != nrend) + return; + try { if (lnh.slice(0, 5) == '#doc.') sethash(lnh.slice(1)); @@ -6065,8 +6073,11 @@ var showfile = (function () { catch (ex) { } } - if (!txt || txt.length > 1024 * 256) + var skip_prism = !txt || txt.length > 1024 * 256; + if (skip_prism) { fun = function (el) { }; + is_md = false; + } qsr('#doc'); var el = mknod('pre', 'doc'); @@ -6078,7 +6089,7 @@ var showfile = (function () { else { el.textContent = txt; el.innerHTML = '' + el.innerHTML + ''; - if (!window.no_prism) { + if (!window.no_prism && !skip_prism) { if ((lang == 'conf' || lang == 'cfg') && ('\n' + txt).indexOf('\n# -*- mode: yaml -*-') + 1) lang = 'yaml'; diff --git a/copyparty/web/util.js b/copyparty/web/util.js index 0ee7c637..ae4590ed 100644 --- a/copyparty/web/util.js +++ b/copyparty/web/util.js @@ -183,7 +183,7 @@ function vis_exh(msg, url, lineNo, columnNo, error) { if (url.indexOf(' > eval') + 1 && !evalex_fatal) return; // md timer - if (IE && url.indexOf('prism.js') + 1) + if (url.indexOf('prism.js') + 1) return; if (url.indexOf('easymde.js') + 1)