mirror of
https://github.com/9001/copyparty.git
synced 2025-11-04 13:53:18 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24a2f760b7 | ||
|
|
79bbd8fe38 | ||
|
|
35dce1e3e4 | ||
|
|
f886fdf913 | ||
|
|
4476f2f0da |
14
README.md
14
README.md
@@ -127,6 +127,7 @@ summary: all planned features work! now please enjoy the bloatening
|
|||||||
* ☑ basic: plain multipart, ie6 support
|
* ☑ basic: plain multipart, ie6 support
|
||||||
* ☑ up2k: js, resumable, multithreaded
|
* ☑ up2k: js, resumable, multithreaded
|
||||||
* ☑ stash: simple PUT filedropper
|
* ☑ stash: simple PUT filedropper
|
||||||
|
* ☑ unpost: undo/delete accidental uploads
|
||||||
* ☑ symlink/discard existing files (content-matching)
|
* ☑ symlink/discard existing files (content-matching)
|
||||||
* download
|
* download
|
||||||
* ☑ single files in browser
|
* ☑ single files in browser
|
||||||
@@ -215,10 +216,11 @@ example:
|
|||||||
## tabs
|
## tabs
|
||||||
|
|
||||||
* `[🔎]` search by size, date, path/name, mp3-tags ... see [searching](#searching)
|
* `[🔎]` search by size, date, path/name, mp3-tags ... see [searching](#searching)
|
||||||
|
* `[🧯]` unpost: undo/delete accidental uploads
|
||||||
* `[🚀]` and `[🎈]` are the uploaders, see [uploading](#uploading)
|
* `[🚀]` and `[🎈]` are the uploaders, see [uploading](#uploading)
|
||||||
* `[📂]` mkdir, create directories
|
* `[📂]` mkdir: create directories
|
||||||
* `[📝]` new-md, create a new markdown document
|
* `[📝]` new-md: create a new markdown document
|
||||||
* `[📟]` send-msg, either to server-log or into textfiles if `--urlform save`
|
* `[📟]` send-msg: either to server-log or into textfiles if `--urlform save`
|
||||||
* `[🎺]` audio-player config options
|
* `[🎺]` audio-player config options
|
||||||
* `[⚙️]` general client config options
|
* `[⚙️]` general client config options
|
||||||
|
|
||||||
@@ -312,8 +314,10 @@ you can also zip a selection of files or folders by clicking them in the browser
|
|||||||
## uploading
|
## uploading
|
||||||
|
|
||||||
two upload methods are available in the html client:
|
two upload methods are available in the html client:
|
||||||
* `🎈 bup`, the basic uploader, supports almost every browser since netscape 4.0
|
* `[🎈] bup`, the basic uploader, supports almost every browser since netscape 4.0
|
||||||
* `🚀 up2k`, the fancy one
|
* `[🚀] up2k`, the fancy one
|
||||||
|
|
||||||
|
you can undo/delete uploads using `[🧯] unpost` if the server is running with `-e2d`
|
||||||
|
|
||||||
up2k has several advantages:
|
up2k has several advantages:
|
||||||
* you can drop folders into the browser (files are added recursively)
|
* you can drop folders into the browser (files are added recursively)
|
||||||
|
|||||||
@@ -13,6 +13,10 @@
|
|||||||
# But note that journalctl will get the timestamps wrong due to
|
# But note that journalctl will get the timestamps wrong due to
|
||||||
# python disabling line-buffering, so messages are out-of-order:
|
# python disabling line-buffering, so messages are out-of-order:
|
||||||
# https://user-images.githubusercontent.com/241032/126040249-cb535cc7-c599-4931-a796-a5d9af691bad.png
|
# https://user-images.githubusercontent.com/241032/126040249-cb535cc7-c599-4931-a796-a5d9af691bad.png
|
||||||
|
#
|
||||||
|
# enable line-buffering for realtime logging (slight performance cost):
|
||||||
|
# modify ExecStart and prefix it with `/bin/stdbuf -oL` like so:
|
||||||
|
# ExecStart=/bin/stdbuf -oL /usr/bin/python3 [...]
|
||||||
|
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=copyparty file server
|
Description=copyparty file server
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
|
||||||
VERSION = (0, 12, 2)
|
VERSION = (0, 12, 5)
|
||||||
CODENAME = "fil\033[33med"
|
CODENAME = "fil\033[33med"
|
||||||
BUILD_DT = (2021, 7, 29)
|
BUILD_DT = (2021, 7, 30)
|
||||||
|
|
||||||
S_VERSION = ".".join(map(str, VERSION))
|
S_VERSION = ".".join(map(str, VERSION))
|
||||||
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
|
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
|
||||||
|
|||||||
@@ -401,17 +401,18 @@ class AuthSrv(object):
|
|||||||
if uname == "":
|
if uname == "":
|
||||||
uname = "*"
|
uname = "*"
|
||||||
|
|
||||||
|
for un in uname.split(","):
|
||||||
if "r" in lvl:
|
if "r" in lvl:
|
||||||
axs.uread[uname] = 1
|
axs.uread[un] = 1
|
||||||
|
|
||||||
if "w" in lvl:
|
if "w" in lvl:
|
||||||
axs.uwrite[uname] = 1
|
axs.uwrite[un] = 1
|
||||||
|
|
||||||
if "m" in lvl:
|
if "m" in lvl:
|
||||||
axs.umove[uname] = 1
|
axs.umove[un] = 1
|
||||||
|
|
||||||
if "d" in lvl:
|
if "d" in lvl:
|
||||||
axs.udel[uname] = 1
|
axs.udel[un] = 1
|
||||||
|
|
||||||
def _read_volflag(self, flags, name, value, is_list):
|
def _read_volflag(self, flags, name, value, is_list):
|
||||||
if name not in ["mtp"]:
|
if name not in ["mtp"]:
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ class HttpCli(object):
|
|||||||
|
|
||||||
self.uparam = uparam
|
self.uparam = uparam
|
||||||
self.cookies = cookies
|
self.cookies = cookies
|
||||||
self.vpath = unquotep(vpath)
|
self.vpath = unquotep(vpath) # not query, so + means +
|
||||||
|
|
||||||
pwd = uparam.get("pw")
|
pwd = uparam.get("pw")
|
||||||
self.uname = self.asrv.iacct.get(pwd, "*")
|
self.uname = self.asrv.iacct.get(pwd, "*")
|
||||||
@@ -346,12 +346,37 @@ class HttpCli(object):
|
|||||||
static_path = os.path.join(E.mod, "web/", self.vpath[5:])
|
static_path = os.path.join(E.mod, "web/", self.vpath[5:])
|
||||||
return self.tx_file(static_path)
|
return self.tx_file(static_path)
|
||||||
|
|
||||||
|
x = self.asrv.vfs.can_access(self.vpath, self.uname)
|
||||||
|
self.can_read, self.can_write, self.can_move, self.can_delete = x
|
||||||
|
if not self.can_read and not self.can_write:
|
||||||
|
if self.vpath:
|
||||||
|
self.log("inaccessible: [{}]".format(self.vpath))
|
||||||
|
raise Pebkac(404)
|
||||||
|
|
||||||
|
self.uparam["h"] = False
|
||||||
|
|
||||||
if "tree" in self.uparam:
|
if "tree" in self.uparam:
|
||||||
return self.tx_tree()
|
return self.tx_tree()
|
||||||
|
|
||||||
if not self.vpath and "stack" in self.uparam:
|
if "delete" in self.uparam:
|
||||||
|
return self.handle_rm()
|
||||||
|
|
||||||
|
if "move" in self.uparam:
|
||||||
|
return self.handle_mv()
|
||||||
|
|
||||||
|
if "scan" in self.uparam:
|
||||||
|
return self.scanvol()
|
||||||
|
|
||||||
|
if not self.vpath:
|
||||||
|
if "stack" in self.uparam:
|
||||||
return self.tx_stack()
|
return self.tx_stack()
|
||||||
|
|
||||||
|
if "ups" in self.uparam:
|
||||||
|
return self.tx_ups()
|
||||||
|
|
||||||
|
if "h" in self.uparam:
|
||||||
|
return self.tx_mounts()
|
||||||
|
|
||||||
# conditional redirect to single volumes
|
# conditional redirect to single volumes
|
||||||
if self.vpath == "" and not self.ouparam:
|
if self.vpath == "" and not self.ouparam:
|
||||||
nread = len(self.rvol)
|
nread = len(self.rvol)
|
||||||
@@ -366,31 +391,6 @@ class HttpCli(object):
|
|||||||
self.redirect(vpath, flavor="redirecting to", use302=True)
|
self.redirect(vpath, flavor="redirecting to", use302=True)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
x = self.asrv.vfs.can_access(self.vpath, self.uname)
|
|
||||||
self.can_read, self.can_write, self.can_move, self.can_delete = x
|
|
||||||
if not self.can_read and not self.can_write:
|
|
||||||
if self.vpath:
|
|
||||||
self.log("inaccessible: [{}]".format(self.vpath))
|
|
||||||
raise Pebkac(404)
|
|
||||||
|
|
||||||
self.uparam = {"h": False}
|
|
||||||
|
|
||||||
if "delete" in self.uparam:
|
|
||||||
return self.handle_rm()
|
|
||||||
|
|
||||||
if "move" in self.uparam:
|
|
||||||
return self.handle_mv()
|
|
||||||
|
|
||||||
if "scan" in self.uparam:
|
|
||||||
return self.scanvol()
|
|
||||||
|
|
||||||
if not self.vpath:
|
|
||||||
if "h" in self.uparam:
|
|
||||||
return self.tx_mounts()
|
|
||||||
|
|
||||||
if "ups" in self.uparam:
|
|
||||||
return self.tx_ups()
|
|
||||||
|
|
||||||
return self.tx_browser()
|
return self.tx_browser()
|
||||||
|
|
||||||
def handle_options(self):
|
def handle_options(self):
|
||||||
@@ -1310,11 +1310,9 @@ class HttpCli(object):
|
|||||||
else:
|
else:
|
||||||
fn = self.headers.get("host", "hey")
|
fn = self.headers.get("host", "hey")
|
||||||
|
|
||||||
afn = "".join(
|
safe = (string.ascii_letters + string.digits).replace("%", "")
|
||||||
[x if x in (string.ascii_letters + string.digits) else "_" for x in fn]
|
afn = "".join([x if x in safe.replace('"', "") else "_" for x in fn])
|
||||||
)
|
bascii = unicode(safe).encode("utf-8")
|
||||||
|
|
||||||
bascii = unicode(string.ascii_letters + string.digits).encode("utf-8")
|
|
||||||
ufn = fn.encode("utf-8", "xmlcharrefreplace")
|
ufn = fn.encode("utf-8", "xmlcharrefreplace")
|
||||||
if PY2:
|
if PY2:
|
||||||
ufn = [unicode(x) if x in bascii else "%{:02x}".format(ord(x)) for x in ufn]
|
ufn = [unicode(x) if x in bascii else "%{:02x}".format(ord(x)) for x in ufn]
|
||||||
@@ -1329,6 +1327,7 @@ class HttpCli(object):
|
|||||||
|
|
||||||
cdis = "attachment; filename=\"{}.{}\"; filename*=UTF-8''{}.{}"
|
cdis = "attachment; filename=\"{}.{}\"; filename*=UTF-8''{}.{}"
|
||||||
cdis = cdis.format(afn, fmt, ufn, fmt)
|
cdis = cdis.format(afn, fmt, ufn, fmt)
|
||||||
|
self.log(cdis)
|
||||||
self.send_headers(None, mime=mime, headers={"Content-Disposition": cdis})
|
self.send_headers(None, mime=mime, headers={"Content-Disposition": cdis})
|
||||||
|
|
||||||
fgen = vn.zipgen(rem, items, self.uname, dots, not self.args.no_scandir)
|
fgen = vn.zipgen(rem, items, self.uname, dots, not self.args.no_scandir)
|
||||||
@@ -1621,6 +1620,9 @@ class HttpCli(object):
|
|||||||
if not dst:
|
if not dst:
|
||||||
raise Pebkac(400, "need dst vpath")
|
raise Pebkac(400, "need dst vpath")
|
||||||
|
|
||||||
|
# x-www-form-urlencoded (url query part) uses
|
||||||
|
# either + or %20 for 0x20 so handle both
|
||||||
|
dst = unquotep(dst.replace("+", " "))
|
||||||
x = self.conn.hsrv.broker.put(
|
x = self.conn.hsrv.broker.put(
|
||||||
True, "up2k.handle_mv", self.uname, self.vpath, dst
|
True, "up2k.handle_mv", self.uname, self.vpath, dst
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1468,10 +1468,10 @@ var fileman = (function () {
|
|||||||
if (r.clip === null)
|
if (r.clip === null)
|
||||||
r.clip = jread('fman_clip', []);
|
r.clip = jread('fman_clip', []);
|
||||||
|
|
||||||
var sel = msel.getsel();
|
var nsel = msel.getsel().length;
|
||||||
clmod(bren, 'en', sel.length == 1);
|
clmod(bren, 'en', nsel == 1);
|
||||||
clmod(bdel, 'en', sel.length);
|
clmod(bdel, 'en', nsel);
|
||||||
clmod(bcut, 'en', sel.length);
|
clmod(bcut, 'en', nsel);
|
||||||
clmod(bpst, 'en', r.clip && r.clip.length);
|
clmod(bpst, 'en', r.clip && r.clip.length);
|
||||||
bren.style.display = have_mv && has(perms, 'write') && has(perms, 'move') ? '' : 'none';
|
bren.style.display = have_mv && has(perms, 'write') && has(perms, 'move') ? '' : 'none';
|
||||||
bdel.style.display = have_del && has(perms, 'delete') ? '' : 'none';
|
bdel.style.display = have_del && has(perms, 'delete') ? '' : 'none';
|
||||||
@@ -3367,8 +3367,13 @@ var msel = (function () {
|
|||||||
ev(e);
|
ev(e);
|
||||||
var names = r.getsel(),
|
var names = r.getsel(),
|
||||||
arg = ebi('selzip').getAttribute('fmt'),
|
arg = ebi('selzip').getAttribute('fmt'),
|
||||||
txt = names.join('\n'),
|
frm = mknod('form'),
|
||||||
frm = mknod('form');
|
txt = [];
|
||||||
|
|
||||||
|
for (var a = 0; a < names.length; a++)
|
||||||
|
txt.push(names[a].name);
|
||||||
|
|
||||||
|
txt = txt.join('\n');
|
||||||
|
|
||||||
frm.setAttribute('action', '?' + arg);
|
frm.setAttribute('action', '?' + arg);
|
||||||
frm.setAttribute('method', 'post');
|
frm.setAttribute('method', 'post');
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ avg() { awk 'function pr(ncsz) {if (nsmp>0) {printf "%3s %s\n", csz, sum/nsmp} c
|
|||||||
dirs=("$HOME/vfs/ほげ" "$HOME/vfs/ほげ/ぴよ" "$HOME/vfs/$(printf \\xed\\x91)" "$HOME/vfs/$(printf \\xed\\x91/\\xed\\x92)")
|
dirs=("$HOME/vfs/ほげ" "$HOME/vfs/ほげ/ぴよ" "$HOME/vfs/$(printf \\xed\\x91)" "$HOME/vfs/$(printf \\xed\\x91/\\xed\\x92)")
|
||||||
mkdir -p "${dirs[@]}"
|
mkdir -p "${dirs[@]}"
|
||||||
for dir in "${dirs[@]}"; do for fn in ふが "$(printf \\xed\\x93)" 'qwe,rty;asd fgh+jkl%zxc&vbn <qwe>"rty'"'"'uio&asd fgh'; do echo "$dir" > "$dir/$fn.html"; done; done
|
for dir in "${dirs[@]}"; do for fn in ふが "$(printf \\xed\\x93)" 'qwe,rty;asd fgh+jkl%zxc&vbn <qwe>"rty'"'"'uio&asd fgh'; do echo "$dir" > "$dir/$fn.html"; done; done
|
||||||
|
# qw er+ty%20ui%%20op<as>df&gh&jk#zx'cv"bn`m=qw*er^ty?ui@op,as.df-gh_jk
|
||||||
|
|
||||||
##
|
##
|
||||||
## upload mojibake
|
## upload mojibake
|
||||||
|
|||||||
Reference in New Issue
Block a user