diff --git a/README.md b/README.md index f2880af0..28e38b9f 100644 --- a/README.md +++ b/README.md @@ -196,6 +196,26 @@ copyparty can invoke external programs to collect additional metadata for files `python copyparty-sfx.py -v /mnt/nas/music:/music:r -e2dsa -e2ts -mtp .bpm=f,audio-bpm.py -mtp key=f,audio-key.py` +# browser support + +| feature | ie6 | ie9 | ie10 | ie11 | ff 52+ | chr 49+ | +| --------------- | --- | --- | ---- | ---- | ------ | ------- | +| browse files | yep | yep | yep | yep | yep | yep | +| basic uploader | yep | yep | yep | yep | yep | yep | +| zip selection | - | yep | yep | yep | yep | yep | +| directory tree | - | - | `*1` | yep | yep | yep | +| up2k | - | - | yep | yep | yep | yep | +| icons work | - | - | yep | yep | yep | yep | +| markdown editor | - | - | yep | yep | yep | yep | +| markdown viewer | - | - | yep | yep | yep | yep | +| play mp3/mp4 | - | yep | yep | yep | yep | yep | +| play ogg/opus | - | - | - | - | yep | yep | + +* internet explorer 6 to 8 (and netscape 4.0) behave the same +* firefox 52 and chrome 49 are the last winxp versions +* `*1` only public folders (login session is dropped) and no history / back-button + + # client examples * javascript: dump some state into a file (two separate examples) diff --git a/copyparty/authsrv.py b/copyparty/authsrv.py index 485ee2f9..00ff3f4b 100644 --- a/copyparty/authsrv.py +++ b/copyparty/authsrv.py @@ -168,8 +168,13 @@ class VFS(object): for vpath, apath, files, rd, vd in self.walk("", vrem, uname, dots, scandir): if flt: files = [x for x in files if x[0] in flt] - rd = [x for x in rd if x[0] in flt] - vd = {x: y for x, y in vd.items() if x in flt} + + rm = [x for x in rd if x[0] not in flt] + [rd.remove(x) for x in rm] + + rm = [x for x in vd.keys() if x not in flt] + [vd.pop(x) for x in rm] + flt = None # print(repr([vpath, apath, [x[0] for x in files]])) diff --git a/copyparty/web/browser.js b/copyparty/web/browser.js index 86a57575..c5daf6ae 100644 --- a/copyparty/web/browser.js +++ b/copyparty/web/browser.js @@ -500,7 +500,7 @@ function play(tid, call_depth) { setclass(oid, 'play act'); var trs = ebi('files').getElementsByTagName('tbody')[0].getElementsByTagName('tr'); for (var a = 0, aa = trs.length; a < aa; a++) { - trs[a].className = trs[a].className.replace(/ *play */, ""); + clmod(trs[a], 'play'); } ebi(oid).parentElement.parentElement.className += ' play'; @@ -649,10 +649,10 @@ function tree_up() { document.onkeydown = function (e) { - if (document.activeElement != document.body && document.activeElement.nodeName.toLowerCase() != 'a') + if (!document.activeElement || document.activeElement != document.body && document.activeElement.nodeName.toLowerCase() != 'a') return; - var k = e.code, pos = -1; + var k = (e.code + ''), pos = -1; if (k.indexOf('Digit') === 0) pos = parseInt(k.slice(-1)) * 0.1; @@ -772,6 +772,7 @@ document.onkeydown = function (e) { // ebi('srch_q').textContent = JSON.stringify(params, null, 4); var xhr = new XMLHttpRequest(); xhr.open('POST', '/?srch', true); + xhr.setRequestHeader('Content-Type', 'text/plain'); xhr.onreadystatechange = xhr_search_results; xhr.ts = new Date().getTime(); xhr.send(JSON.stringify(params)); @@ -997,8 +998,6 @@ var treectl = (function () { var o = links[a].parentNode; if (!o.getElementsByTagName('li').length) o.innerHTML = html; - //else - // links[a].previousSibling.textContent = '-'; } } } @@ -1282,7 +1281,7 @@ function find_file_col(txt) { function mk_files_header(taglist) { var html = [ - '', + '', 'c', 'File Name', 'Size' @@ -1301,7 +1300,7 @@ function mk_files_header(taglist) { html = html.concat([ 'T', 'Date', - '', + '', ]); return html; } @@ -1335,13 +1334,13 @@ var filecols = (function () { continue; var name = span[0].textContent, - cls = ''; + cls = false; if (has(hidden, name)) { ohidden.push(a); - cls = ' min'; + cls = true; } - ths[a].className = ths[a].className.replace(/ *min */, " ") + cls; + clmod(ths[a], 'min', cls) } for (var a = 0; a < ncols; a++) { var cls = has(ohidden, a) ? 'min' : ''; @@ -1512,12 +1511,12 @@ var mukey = (function () { function addcrc() { var links = document.querySelectorAll( - '#files>tbody>tr>td:nth-child(2)>' + ( + '#files>tbody>tr>td:first-child+td>' + ( ebi('unsearch') ? 'div>a:last-child' : 'a')); for (var a = 0, aa = links.length; a < aa; a++) if (!links[a].getAttribute('id')) - links[a].setAttribute('id', 'f-' + crc32(links[a].textContent)); + links[a].setAttribute('id', 'f-' + crc32(links[a].textContent || links[a].innerText)); } @@ -1620,27 +1619,26 @@ var msel = (function () { return names; } function selui() { - var fun = getsel().length ? "add" : "remove"; - ebi('wtoggle').classList[fun]('sel'); + clmod(ebi('wtoggle'), 'sel', getsel().length); } function seltgl(e) { ev(e); var tr = this.parentNode; - tr.classList.toggle('sel'); + clmod(tr, 'sel', 't'); selui(); } function evsel(e, fun) { ev(e); var trs = document.querySelectorAll('#files tbody tr'); for (var a = 0, aa = trs.length; a < aa; a++) - trs[a].classList[fun]('sel'); + clmod(trs[a], 'sel', fun); selui(); } ebi('selall').onclick = function (e) { evsel(e, "add"); }; ebi('selinv').onclick = function (e) { - evsel(e, "toggle"); + evsel(e, "t"); }; ebi('selzip').onclick = function (e) { ev(e); diff --git a/copyparty/web/up2k.js b/copyparty/web/up2k.js index 08df414b..30e1f412 100644 --- a/copyparty/web/up2k.js +++ b/copyparty/web/up2k.js @@ -979,7 +979,9 @@ function up2k_init(have_crypto) { xhr.setRequestHeader("X-Up2k-Hash", t.hash[npart]); xhr.setRequestHeader("X-Up2k-Wark", t.wark); xhr.setRequestHeader('Content-Type', 'application/octet-stream'); - xhr.overrideMimeType('Content-Type', 'application/octet-stream'); + if (xhr.overrideMimeType) + xhr.overrideMimeType('Content-Type', 'application/octet-stream'); + xhr.responseType = 'text'; xhr.send(e.target.result); }; diff --git a/copyparty/web/util.js b/copyparty/web/util.js index 2343280b..a8088f4a 100644 --- a/copyparty/web/util.js +++ b/copyparty/web/util.js @@ -1,5 +1,11 @@ "use strict"; +if (!window['console']) + window['console'] = { + "log": function (msg) { } + }; + + // error handler for mobile devices function hcroak(msg) { document.body.innerHTML = msg; @@ -113,6 +119,15 @@ function crc32(str) { }; +function clmod(obj, cls, add) { + var re = new RegExp('\\s*\\b' + cls + '\\s*\\b', 'g'); + if (add == 't') + add = !re.test(obj.className); + + obj.className = obj.className.replace(re, ' ') + (add ? ' ' + cls : ''); +} + + function sortfiles(nodes) { var sopts = jread('fsort', [["lead", -1, ""], ["href", 1, ""]]); @@ -149,7 +164,7 @@ function sortfiles(nodes) { } } - var onodes = nodes.map((x) => x); + var onodes = nodes.map(function (x) { return x; }); nodes.sort(function (n1, n2) { var v1 = n1._sv, v2 = n2._sv; @@ -280,16 +295,16 @@ function opclick(e) { function goto(dest) { var obj = document.querySelectorAll('.opview.act'); for (var a = obj.length - 1; a >= 0; a--) - obj[a].classList.remove('act'); + clmod(obj[a], 'act'); obj = document.querySelectorAll('#ops>a'); for (var a = obj.length - 1; a >= 0; a--) - obj[a].classList.remove('act'); + clmod(obj[a], 'act'); if (dest) { var ui = ebi('op_' + dest); - ui.classList.add('act'); - document.querySelector('#ops>a[data-dest=' + dest + ']').classList.add('act'); + clmod(ui, 'act', true); + document.querySelector('#ops>a[data-dest=' + dest + ']').className += " act"; var fn = window['goto_' + dest]; if (fn) @@ -476,8 +491,7 @@ function bcfg_upd_ui(name, val) { if (o.getAttribute('type') == 'checkbox') o.checked = val; else if (o) { - var fun = val ? 'add' : 'remove'; - o.classList[fun]('on'); + clmod(o, 'on', val); } }