mirror of
https://github.com/9001/copyparty.git
synced 2025-08-18 09:22:31 -06:00
zip selection
This commit is contained in:
parent
ffbfcd7e00
commit
9e850fc3ab
|
@ -161,47 +161,39 @@ class VFS(object):
|
||||||
for x in vfs.walk(wrel, "", uname, scandir, lstat):
|
for x in vfs.walk(wrel, "", uname, scandir, lstat):
|
||||||
yield x
|
yield x
|
||||||
|
|
||||||
def zipgen(self, vrem, rems, uname, dots, scandir):
|
def zipgen(self, vrem, flt, uname, dots, scandir):
|
||||||
vtops = [["", [self, vrem]]]
|
if flt:
|
||||||
if rems:
|
flt = {k: True for k in flt}
|
||||||
# list of subfolders to zip was provided,
|
|
||||||
# add all the ones uname is allowed to access
|
|
||||||
vtops = []
|
|
||||||
for rem in rems:
|
|
||||||
try:
|
|
||||||
d = rem if not vrem else vrem + "/" + rem
|
|
||||||
vn = self.get(d, uname, True, False)
|
|
||||||
vtops.append([rem, vn])
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
for rel, (vn, rem) in vtops:
|
for vpath, apath, files, rd, vd in self.walk("", vrem, uname, dots, scandir):
|
||||||
for vpath, apath, files, rd, vd in vn.walk(rel, rem, uname, dots, scandir):
|
if flt:
|
||||||
# print(repr([vpath, apath, [x[0] for x in files]]))
|
files = [x for x in files if x[0] in flt]
|
||||||
fnames = [n[0] for n in files]
|
rd = [x for x in rd if x[0] in flt]
|
||||||
vpaths = [vpath + "/" + n for n in fnames] if vpath else fnames
|
vd = {x: y for x, y in vd.items() if x in flt}
|
||||||
apaths = [os.path.join(apath, n) for n in fnames]
|
|
||||||
files = list(zip(vpaths, apaths, files))
|
|
||||||
|
|
||||||
if not dots:
|
# print(repr([vpath, apath, [x[0] for x in files]]))
|
||||||
# dotfile filtering based on vpath (intended visibility)
|
fnames = [n[0] for n in files]
|
||||||
files = [x for x in files if "/." not in "/" + x[0]]
|
vpaths = [vpath + "/" + n for n in fnames] if vpath else fnames
|
||||||
|
apaths = [os.path.join(apath, n) for n in fnames]
|
||||||
|
files = list(zip(vpaths, apaths, files))
|
||||||
|
|
||||||
rm = [x for x in rd if x[0].startswith(".")]
|
if not dots:
|
||||||
for x in rm:
|
# dotfile filtering based on vpath (intended visibility)
|
||||||
rd.remove(x)
|
files = [x for x in files if "/." not in "/" + x[0]]
|
||||||
|
|
||||||
rm = [k for k in vd.keys() if k.startswith(".")]
|
rm = [x for x in rd if x[0].startswith(".")]
|
||||||
for x in rm:
|
for x in rm:
|
||||||
del vd[x]
|
rd.remove(x)
|
||||||
|
|
||||||
# up2k filetring based on actual abspath
|
rm = [k for k in vd.keys() if k.startswith(".")]
|
||||||
files = [
|
for x in rm:
|
||||||
x for x in files if "{0}.hist{0}up2k.".format(os.sep) not in x[1]
|
del vd[x]
|
||||||
]
|
|
||||||
|
|
||||||
for f in [{"vp": v, "ap": a, "st": n[1]} for v, a, n in files]:
|
# up2k filetring based on actual abspath
|
||||||
yield f
|
files = [x for x in files if "{0}.hist{0}up2k.".format(os.sep) not in x[1]]
|
||||||
|
|
||||||
|
for f in [{"vp": v, "ap": a, "st": n[1]} for v, a, n in files]:
|
||||||
|
yield f
|
||||||
|
|
||||||
def user_tree(self, uname, readable=False, writable=False):
|
def user_tree(self, uname, readable=False, writable=False):
|
||||||
ret = []
|
ret = []
|
||||||
|
|
|
@ -161,8 +161,8 @@ class HttpCli(object):
|
||||||
try:
|
try:
|
||||||
# self.log("pebkac at httpcli.run #2: " + repr(ex))
|
# self.log("pebkac at httpcli.run #2: " + repr(ex))
|
||||||
self.keepalive = self._check_nonfatal(ex)
|
self.keepalive = self._check_nonfatal(ex)
|
||||||
self.log("{}\033[0m: {}".format(str(ex), self.vpath), 3)
|
self.log("{}\033[0m, {}".format(str(ex), self.vpath), 3)
|
||||||
msg = "<pre>{}: {}\r\n".format(str(ex), self.vpath)
|
msg = "<pre>{}\r\nURL: {}\r\n".format(str(ex), self.vpath)
|
||||||
self.reply(msg.encode("utf-8", "replace"), status=ex.code)
|
self.reply(msg.encode("utf-8", "replace"), status=ex.code)
|
||||||
return self.keepalive
|
return self.keepalive
|
||||||
except Pebkac:
|
except Pebkac:
|
||||||
|
@ -397,8 +397,29 @@ class HttpCli(object):
|
||||||
if act == "tput":
|
if act == "tput":
|
||||||
return self.handle_text_upload()
|
return self.handle_text_upload()
|
||||||
|
|
||||||
|
if act == "zip":
|
||||||
|
return self.handle_zip_post()
|
||||||
|
|
||||||
raise Pebkac(422, 'invalid action "{}"'.format(act))
|
raise Pebkac(422, 'invalid action "{}"'.format(act))
|
||||||
|
|
||||||
|
def handle_zip_post(self):
|
||||||
|
for k in ["zip", "tar"]:
|
||||||
|
v = self.uparam.get(k)
|
||||||
|
if v is not None:
|
||||||
|
break
|
||||||
|
|
||||||
|
if not v:
|
||||||
|
raise Pebkac(422, "need zip or tar keyword")
|
||||||
|
|
||||||
|
vn, rem = self.auth.vfs.get(self.vpath, self.uname, True, False)
|
||||||
|
items = self.parser.require("files", 1024 * 1024)
|
||||||
|
if not items:
|
||||||
|
raise Pebkac(422, "need files list")
|
||||||
|
|
||||||
|
items = items.replace("\r", "").split("\n")
|
||||||
|
items = [x for x in items if items]
|
||||||
|
return self.tx_zip(k, v, vn, rem, items, self.args.ed)
|
||||||
|
|
||||||
def handle_post_json(self):
|
def handle_post_json(self):
|
||||||
try:
|
try:
|
||||||
remains = int(self.headers["content-length"])
|
remains = int(self.headers["content-length"])
|
||||||
|
|
|
@ -87,7 +87,9 @@ class HttpConn(object):
|
||||||
err = "need at least 4 bytes in the first packet; got {}".format(
|
err = "need at least 4 bytes in the first packet; got {}".format(
|
||||||
len(method)
|
len(method)
|
||||||
)
|
)
|
||||||
self.log(err)
|
if method:
|
||||||
|
self.log(err)
|
||||||
|
|
||||||
self.s.send(b"HTTP/1.1 400 Bad Request\r\n\r\n" + err.encode("utf-8"))
|
self.s.send(b"HTTP/1.1 400 Bad Request\r\n\r\n" + err.encode("utf-8"))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -182,6 +182,11 @@ a, #files tbody div a:last-child {
|
||||||
color: #840;
|
color: #840;
|
||||||
text-shadow: 0 0 .3em #b80;
|
text-shadow: 0 0 .3em #b80;
|
||||||
}
|
}
|
||||||
|
#files tbody tr.sel td {
|
||||||
|
background: #80b;
|
||||||
|
color: #fff;
|
||||||
|
border-color: #a3d;
|
||||||
|
}
|
||||||
#blocked {
|
#blocked {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -268,6 +273,25 @@ a, #files tbody div a:last-child {
|
||||||
padding: .2em 0 0 .07em;
|
padding: .2em 0 0 .07em;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
#wtoggle>span {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#wtoggle.sel {
|
||||||
|
width: 4.27em;
|
||||||
|
}
|
||||||
|
#wtoggle.sel>span {
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 0;
|
||||||
|
}
|
||||||
|
#wtoggle.sel>span a {
|
||||||
|
font-size: .4em;
|
||||||
|
margin: -.3em 0;
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
#wtoggle.sel>span #selzip {
|
||||||
|
top: -.6em;
|
||||||
|
}
|
||||||
#barpos,
|
#barpos,
|
||||||
#barbuf {
|
#barbuf {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
@ -112,7 +112,14 @@
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
<div id="widget">
|
<div id="widget">
|
||||||
<div id="wtoggle">♫</div>
|
<div id="wtoggle">
|
||||||
|
<span>
|
||||||
|
<a href="#" id="selall">sel.<br />all</a>
|
||||||
|
<a href="#" id="selinv">sel.<br />inv.</a>
|
||||||
|
<a href="#" id="selzip">zip</a>
|
||||||
|
</span>
|
||||||
|
♫
|
||||||
|
</div>
|
||||||
<div id="widgeti">
|
<div id="widgeti">
|
||||||
<div id="pctl"><a href="#" id="bprev">⏮</a><a href="#" id="bplay">▶</a><a href="#" id="bnext">⏭</a></div>
|
<div id="pctl"><a href="#" id="bprev">⏮</a><a href="#" id="bplay">▶</a><a href="#" id="bnext">⏭</a></div>
|
||||||
<canvas id="pvol" width="288" height="38"></canvas>
|
<canvas id="pvol" width="288" height="38"></canvas>
|
||||||
|
|
|
@ -1595,6 +1595,8 @@ var arcfmt = (function () {
|
||||||
o.setAttribute("href", href.slice(0, ofs + 1) + arg);
|
o.setAttribute("href", href.slice(0, ofs + 1) + arg);
|
||||||
o.textContent = fmt.split('_')[0];
|
o.textContent = fmt.split('_')[0];
|
||||||
}
|
}
|
||||||
|
ebi('selzip').textContent = fmt.split('_')[0];
|
||||||
|
ebi('selzip').setAttribute('fmt', arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
function try_render() {
|
function try_render() {
|
||||||
|
@ -1624,6 +1626,69 @@ var arcfmt = (function () {
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
var msel = (function () {
|
||||||
|
function getsel() {
|
||||||
|
var names = [];
|
||||||
|
var links = document.querySelectorAll('#files tbody tr.sel td:nth-child(2) a');
|
||||||
|
for (var a = 0, aa = links.length; a < aa; a++)
|
||||||
|
names.push(links[a].getAttribute('href'));
|
||||||
|
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
function selui() {
|
||||||
|
var fun = getsel().length ? "add" : "remove";
|
||||||
|
ebi('wtoggle').classList[fun]('sel');
|
||||||
|
}
|
||||||
|
function seltgl(e) {
|
||||||
|
ev(e);
|
||||||
|
var tr = this.parentNode;
|
||||||
|
tr.classList.toggle('sel');
|
||||||
|
selui();
|
||||||
|
}
|
||||||
|
var trs = document.querySelectorAll('#files tbody tr');
|
||||||
|
ebi('selall').onclick = function (e) {
|
||||||
|
ev(e);
|
||||||
|
for (var a = 0, aa = trs.length; a < aa; a++)
|
||||||
|
trs[a].classList.add('sel');
|
||||||
|
selui();
|
||||||
|
};
|
||||||
|
ebi('selinv').onclick = function (e) {
|
||||||
|
ev(e);
|
||||||
|
for (var a = 0, aa = trs.length; a < aa; a++)
|
||||||
|
trs[a].classList.toggle('sel');
|
||||||
|
selui();
|
||||||
|
};
|
||||||
|
ebi('selzip').onclick = function (e) {
|
||||||
|
ev(e);
|
||||||
|
var names = getsel();
|
||||||
|
var arg = ebi('selzip').getAttribute('fmt');
|
||||||
|
var txt = names.join('\n');
|
||||||
|
var frm = document.createElement('form');
|
||||||
|
frm.setAttribute('action', '?' + arg);
|
||||||
|
frm.setAttribute('method', 'post');
|
||||||
|
frm.setAttribute('target', '_blank');
|
||||||
|
frm.setAttribute('enctype', 'multipart/form-data');
|
||||||
|
frm.innerHTML = '<input name="act" value="zip" />' +
|
||||||
|
'<textarea name="files" id="ziptxt"></textarea>';
|
||||||
|
frm.style.display = 'none';
|
||||||
|
|
||||||
|
var oldform = document.querySelector('#widgeti>form');
|
||||||
|
if (oldform)
|
||||||
|
oldform.parentNode.removeChild(oldform);
|
||||||
|
|
||||||
|
ebi('widgeti').appendChild(frm);
|
||||||
|
var obj = ebi('ziptxt');
|
||||||
|
obj.value = txt;
|
||||||
|
console.log(txt);
|
||||||
|
frm.submit();
|
||||||
|
};
|
||||||
|
var tds = document.querySelectorAll('#files tbody td+td+td');
|
||||||
|
for (var a = 0, aa = tds.length; a < aa; a++) {
|
||||||
|
tds[a].onclick = seltgl;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
function ev_row_tgl(e) {
|
function ev_row_tgl(e) {
|
||||||
ev(e);
|
ev(e);
|
||||||
filecols.toggle(this.parentElement.parentElement.getElementsByTagName('span')[0].textContent);
|
filecols.toggle(this.parentElement.parentElement.getElementsByTagName('span')[0].textContent);
|
||||||
|
|
Loading…
Reference in a new issue