up2k: add folder upload

This commit is contained in:
ed 2021-03-27 00:20:42 +01:00
parent 871dde79a9
commit c8f59fb978
5 changed files with 100 additions and 19 deletions

View file

@ -54,6 +54,7 @@ class VFS(object):
self.uwrite, self.uwrite,
self.flags, self.flags,
) )
self._trk(vn)
self.nodes[name] = vn self.nodes[name] = vn
return self._trk(vn.add(src, dst)) return self._trk(vn.add(src, dst))

View file

@ -424,15 +424,18 @@ class HttpCli(object):
if "srch" in self.uparam or "srch" in body: if "srch" in self.uparam or "srch" in body:
return self.handle_search(body) return self.handle_search(body)
# prefer this over undot; no reason to allow traversion
if "/" in body["name"]:
raise Pebkac(400, "folders verboten")
# up2k-php compat # up2k-php compat
for k in "chunkpit.php", "handshake.php": for k in "chunkpit.php", "handshake.php":
if self.vpath.endswith(k): if self.vpath.endswith(k):
self.vpath = self.vpath[: -len(k)] self.vpath = self.vpath[: -len(k)]
sub = None
name = undot(body["name"])
if "/" in name:
sub, name = name.rsplit("/", 1)
self.vpath = "/".join([self.vpath, sub]).strip("/")
body["name"] = name
vfs, rem = self.conn.auth.vfs.get(self.vpath, self.uname, False, True) vfs, rem = self.conn.auth.vfs.get(self.vpath, self.uname, False, True)
body["vtop"] = vfs.vpath body["vtop"] = vfs.vpath
@ -441,12 +444,22 @@ class HttpCli(object):
body["addr"] = self.ip body["addr"] = self.ip
body["vcfg"] = vfs.flags body["vcfg"] = vfs.flags
x = self.conn.hsrv.broker.put(True, "up2k.handle_json", body) if sub:
response = x.get() try:
response = json.dumps(response) dst = os.path.join(vfs.realpath, rem)
os.makedirs(dst)
except:
if not os.path.isdir(dst):
raise Pebkac(400, "some file got your folder name")
self.log(response) x = self.conn.hsrv.broker.put(True, "up2k.handle_json", body)
self.reply(response.encode("utf-8"), mime="application/json") ret = x.get()
if sub:
ret["name"] = "/".join([sub, ret["name"]])
ret = json.dumps(ret)
self.log(ret)
self.reply(ret.encode("utf-8"), mime="application/json")
return True return True
def handle_search(self, body): def handle_search(self, body):

View file

@ -284,12 +284,21 @@ function up2k_init(have_crypto) {
more_one_file(); more_one_file();
var bad_files = []; var bad_files = [];
var good_files = []; var good_files = [];
var dirs = [];
for (var a = 0; a < files.length; a++) { for (var a = 0; a < files.length; a++) {
var fobj = files[a]; var fobj = files[a];
if (is_itemlist) { if (is_itemlist) {
if (fobj.kind !== 'file') if (fobj.kind !== 'file')
continue; continue;
try {
var wi = fobj.webkitGetAsEntry();
if (wi.isDirectory) {
dirs.push(wi);
continue;
}
}
catch (ex) { }
fobj = fobj.getAsFile(); fobj = fobj.getAsFile();
} }
try { try {
@ -300,12 +309,69 @@ function up2k_init(have_crypto) {
bad_files.push(fobj.name); bad_files.push(fobj.name);
continue; continue;
} }
good_files.push(fobj); good_files.push([fobj, fobj.name]);
}
if (dirs) {
return read_dirs(null, [], dirs, good_files, bad_files);
}
}
function read_dirs(rd, pf, dirs, good, bad) {
if (!dirs.length) {
if (!pf.length)
return gotallfiles(good, bad);
console.log("retry pf, " + pf.length);
setTimeout(function () {
read_dirs(rd, pf, dirs, good, bad);
}, 50);
return;
} }
if (!rd)
rd = dirs[0].createReader();
rd.readEntries(function (ents) {
var ngot = 0;
ents.forEach(function (dn) {
if (dn.isDirectory) {
dirs.push(dn);
}
else {
var name = dn.fullPath;
if (name.indexOf('/') === 0)
name = name.slice(1);
pf.push(name);
dn.file(function (fobj) {
var idx = pf.indexOf(name);
pf.splice(idx, 1);
try {
if (fobj.size > 0) {
good.push([fobj, name]);
return;
}
}
catch (ex) { }
bad.push(name);
});
}
ngot += 1;
});
// console.log("ngot: " + ngot);
if (!ngot) {
dirs.shift();
rd = null;
}
return read_dirs(rd, pf, dirs, good, bad);
});
}
function gotallfiles(good_files, bad_files) {
if (bad_files.length > 0) { if (bad_files.length > 0) {
var msg = 'These {0} files (of {1} total) were skipped because they are empty:\n'.format(bad_files.length, files.length); var ntot = bad_files.length + good_files.length;
for (var a = 0; a < bad_files.length; a++) var msg = 'These {0} files (of {1} total) were skipped because they are empty:\n'.format(bad_files.length, ntot);
for (var a = 0, aa = Math.min(20, bad_files.length); a < aa; a++)
msg += '-- ' + bad_files[a] + '\n'; msg += '-- ' + bad_files[a] + '\n';
if (files.length - bad_files.length <= 1 && /(android)/i.test(navigator.userAgent)) if (files.length - bad_files.length <= 1 && /(android)/i.test(navigator.userAgent))
@ -315,21 +381,21 @@ function up2k_init(have_crypto) {
} }
var msg = ['upload these ' + good_files.length + ' files?']; var msg = ['upload these ' + good_files.length + ' files?'];
for (var a = 0; a < good_files.length; a++) for (var a = 0, aa = Math.min(20, good_files.length); a < aa; a++)
msg.push(good_files[a].name); msg.push(good_files[a][1]);
if (ask_up && !fsearch && !confirm(msg.join('\n'))) if (ask_up && !fsearch && !confirm(msg.join('\n')))
return; return;
for (var a = 0; a < good_files.length; a++) { for (var a = 0; a < good_files.length; a++) {
var fobj = good_files[a]; var fobj = good_files[a][0];
var now = new Date().getTime(); var now = new Date().getTime();
var lmod = fobj.lastModified || now; var lmod = fobj.lastModified || now;
var entry = { var entry = {
"n": parseInt(st.files.length.toString()), "n": parseInt(st.files.length.toString()),
"t0": now, // TODO remove probably "t0": now,
"fobj": fobj, "fobj": fobj,
"name": fobj.name, "name": good_files[a][1],
"size": fobj.size, "size": fobj.size,
"lmod": lmod / 1000, "lmod": lmod / 1000,
"purl": get_evpath(), "purl": get_evpath(),

View file

@ -88,7 +88,7 @@
width: 30em; width: 30em;
} }
#u2conf.has_btn { #u2conf.has_btn {
width: 46em; width: 48em;
} }
#u2conf * { #u2conf * {
text-align: center; text-align: center;

View file

@ -73,7 +73,8 @@
<div id="u2btn_ct"> <div id="u2btn_ct">
<div id="u2btn"> <div id="u2btn">
<span id="u2bm"></span><br /> <span id="u2bm"></span><br />
drop files here<br /> drag/drop files<br />
and folders here<br />
(or click me) (or click me)
</div> </div>
</div> </div>