diff --git a/copyparty/httpcli.py b/copyparty/httpcli.py index b29b9398..fc3d170e 100644 --- a/copyparty/httpcli.py +++ b/copyparty/httpcli.py @@ -77,6 +77,8 @@ class HttpCli(object): self.loud_reply(str(ex), status=ex.code) return self.keepalive + # time.sleep(0.4) + # normalize incoming headers to lowercase; # outgoing headers however are Correct-Case for header_line in headerlines[1:]: @@ -1267,9 +1269,16 @@ class HttpCli(object): srv_info = " /// ".join(srv_info) + perms = [] + if self.readable: + perms.append("read") + if self.writable: + perms.append("write") + if is_ls: [x.pop(k) for k in ["name", "dt"] for y in [dirs, files] for x in y] - ret = json.dumps({"dirs": dirs, "files": files, "srvinf": srv_info}) + ret = {"dirs": dirs, "files": files, "srvinf": srv_info, "perms": perms} + ret = json.dumps(ret) self.reply(ret.encode("utf-8", "replace"), mime="application/json") return True @@ -1289,10 +1298,9 @@ class HttpCli(object): vdir=quotep(self.vpath), vpnodes=vpnodes, files=dirs, - can_upload=self.writable, - can_read=self.readable, - have_up2k_idx=self.args.e2d, ts=ts, + perms=json.dumps(perms), + have_up2k_idx=self.args.e2d, prologue=logues[0], epilogue=logues[1], title=html_escape(self.vpath), diff --git a/copyparty/up2k.py b/copyparty/up2k.py index 4d5cf16e..c2ce4225 100644 --- a/copyparty/up2k.py +++ b/copyparty/up2k.py @@ -730,6 +730,11 @@ class Up2k(object): if etag == prev.get(k, None): return + try: + os.mkdir(os.path.join(k, ".hist")) + except: + pass + path2 = "{}.{}".format(path, os.getpid()) j = json.dumps(reg, indent=2, sort_keys=True).encode("utf-8") with gzip.GzipFile(path2, "wb") as f: diff --git a/copyparty/web/browser.css b/copyparty/web/browser.css index 3c44df6b..4b23b1bc 100644 --- a/copyparty/web/browser.css +++ b/copyparty/web/browser.css @@ -336,7 +336,6 @@ a, box-shadow: 0 0 1em #222 inset; } #ops { - display: none; background: #333; margin: 1.7em 1.5em 0 1.5em; padding: .3em .6em; @@ -426,6 +425,7 @@ input[type="checkbox"]:checked+label { padding: .3em .5em; font-size: 1.5em; display: inline-block; + min-width: 12em; width: 100%; } #treefiles #files tbody { @@ -434,9 +434,6 @@ input[type="checkbox"]:checked+label { #treefiles #files thead th:nth-child(1) { border-radius: .7em 0 0 0; } -#tree li { - list-style: none; -} #tree ul, #tree li { padding: 0; @@ -447,6 +444,8 @@ input[type="checkbox"]:checked+label { } #tree li { margin-left: 1em; + list-style: none; + white-space: nowrap; } #tree a.hl { color: #400; @@ -454,9 +453,6 @@ input[type="checkbox"]:checked+label { border-radius: .3em; text-shadow: none; } -#tree li { - white-space: nowrap; -} #tree a { display: inline-block; } @@ -497,4 +493,6 @@ input[type="checkbox"]:checked+label { padding: 0 1.2em 0 0; font-size: 4em; animation: spin 1s linear infinite; + position: absolute; + z-index: 9; } diff --git a/copyparty/web/browser.html b/copyparty/web/browser.html index c473306b..57e36ad2 100644 --- a/copyparty/web/browser.html +++ b/copyparty/web/browser.html @@ -7,36 +7,29 @@ - {%- if can_upload %} - {%- endif %}
--- - {%- if can_read %} - 🔎 - {%- endif %} - {%- if can_upload %} + 🔎 + {%- if have_up2k_idx %} 🚀 - 🎈 - 📂 - 📝 - 📟 + {%- else %} + 🚀 {%- endif %} + 🎈 + 📂 + 📝 + 📟
- {%- if can_read %} - {%- endif %} - - {%- if can_upload %} {%- include 'upload.html' %} - {%- endif %}

🌲 @@ -45,7 +38,6 @@ {%- endfor %}

- {%- if can_read %} {%- if prologue %}
{{ prologue }}
{%- endif %} @@ -54,9 +46,7 @@ 🍞... - + @@ -84,7 +74,6 @@ {%- if epilogue %}
{{ epilogue }}
{%- endif %} - {%- endif %}

control-panel

@@ -103,14 +92,11 @@ - - {%- if can_read %} - {%- endif %} - - {%- if can_upload %} - {%- endif %} + diff --git a/copyparty/web/browser.js b/copyparty/web/browser.js index f20c19c7..c49e1cea 100644 --- a/copyparty/web/browser.js +++ b/copyparty/web/browser.js @@ -732,6 +732,7 @@ function autoplay_blocked() { xhr.open('GET', dst + '?tree=' + top, true); xhr.onreadystatechange = recvtree; xhr.send(); + enspin('#tree'); } function recvtree() { @@ -776,6 +777,7 @@ function autoplay_blocked() { } } document.querySelector('#treeul>li>a+a').textContent = '[root]'; + despin('#tree'); reload_tree(); var q = '#tree'; @@ -817,6 +819,7 @@ function autoplay_blocked() { xhr.onreadystatechange = recvls; xhr.send(); get_tree('.', xhr.top); + enspin('#files'); } function treegrow(e) { @@ -865,6 +868,8 @@ function autoplay_blocked() { html = html.join('\n'); ebi('files').tBodies[0].innerHTML = html; history.pushState(html, this.top, this.top); + apply_perms(res.perms); + despin('#files'); var o = ebi('pro'); if (o) o.parentNode.removeChild(o); @@ -946,6 +951,51 @@ function autoplay_blocked() { })(); +function enspin(sel) { + despin(sel); + var d = document.createElement('div'); + d.setAttribute('class', 'dumb_loader_thing'); + d.innerHTML = '🌲'; + var tgt = document.querySelector(sel); + tgt.insertBefore(d, tgt.childNodes[0]); +} + + +function despin(sel) { + var o = document.querySelectorAll(sel + '>.dumb_loader_thing'); + for (var a = o.length - 1; a >= 0; a--) + o[a].parentNode.removeChild(o[a]); +} + + +function apply_perms(perms) { + var o = document.querySelectorAll('#ops>a[data-perm]'); + for (var a = 0; a < o.length; a++) + o[a].style.display = 'none'; + + for (var a = 0; a < perms.length; a++) { + o = document.querySelectorAll('#ops>a[data-perm="' + perms[a] + '"]'); + for (var b = 0; b < o.length; b++) + o[b].style.display = 'inline'; + } + + var act = document.querySelector('#ops>a.act'); + var areq = act.getAttribute('data-perm'); + if (areq && !has(perms, areq)) + goto(); + + var have_write = has(perms, "write"); + var tds = document.querySelectorAll('#u2conf td'); + for (var a = 0; a < tds.length; a++) { + tds[a].style.display = + (have_write || tds[a].getAttribute('data-perm') == 'read') ? + 'table-cell' : 'none'; + } + if (!have_write) + up2k.set_fsearch(); +} + + function reload_browser(not_mp) { makeSortable(ebi('files')); diff --git a/copyparty/web/up2k.js b/copyparty/web/up2k.js index 224594ba..13420c4d 100644 --- a/copyparty/web/up2k.js +++ b/copyparty/web/up2k.js @@ -1049,6 +1049,11 @@ function up2k_init(have_crypto) { ebi('u2tab').setAttribute('class', fsearch ? 'srch' : ''); } + function set_fsearch() { + if (!fsearch) + tgl_fsearch(); + } + function tgl_flag_en() { flag_en = !flag_en; bcfg_set('flag_en', flag_en); @@ -1099,5 +1104,9 @@ function up2k_init(have_crypto) { bumpthread({ "target": 1 }) - return { "init_deps": init_deps } + return { "init_deps": init_deps, "set_fsearch": set_fsearch } } + + +if (document.querySelector('#op_up2k.act')) + goto_up2k(); diff --git a/copyparty/web/upload.html b/copyparty/web/upload.html index aa9d9bb4..86da6bf6 100644 --- a/copyparty/web/upload.html +++ b/copyparty/web/upload.html @@ -50,12 +50,12 @@ {%- if have_up2k_idx %} - + {%- endif %} - + diff --git a/copyparty/web/util.js b/copyparty/web/util.js index 86dfa1c0..c3e49c7a 100644 --- a/copyparty/web/util.js +++ b/copyparty/web/util.js @@ -172,7 +172,6 @@ function goto(dest) { if (op !== null && op !== '.') goto(op); } - ebi('ops').style.display = 'block'; })(); @@ -223,4 +222,13 @@ function get_vpath() { function unix2iso(ts) { return new Date(ts * 1000).toISOString().replace("T", " ").slice(0, -5); -} \ No newline at end of file +} + + +function has(haystack, needle) { + for (var a = 0; a < haystack.length; a++) + if (haystack[a] == needle) + return true; + + return false; +}