copyparty 1.12.0__py3-none-any.whl → 1.12.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- copyparty/__main__.py +3 -0
- copyparty/__version__.py +2 -2
- copyparty/authsrv.py +8 -7
- copyparty/cert.py +17 -6
- copyparty/cfg.py +2 -0
- copyparty/httpcli.py +14 -7
- copyparty/multicast.py +1 -0
- copyparty/svchub.py +13 -0
- copyparty/th_srv.py +2 -1
- copyparty/up2k.py +9 -8
- copyparty/util.py +64 -26
- copyparty/web/baguettebox.js.gz +0 -0
- copyparty/web/browser.css.gz +0 -0
- copyparty/web/browser.js.gz +0 -0
- copyparty/web/splash.css.gz +0 -0
- copyparty/web/splash.html +1 -1
- copyparty/web/util.js.gz +0 -0
- {copyparty-1.12.0.dist-info → copyparty-1.12.2.dist-info}/METADATA +15 -1
- {copyparty-1.12.0.dist-info → copyparty-1.12.2.dist-info}/RECORD +23 -23
- {copyparty-1.12.0.dist-info → copyparty-1.12.2.dist-info}/LICENSE +0 -0
- {copyparty-1.12.0.dist-info → copyparty-1.12.2.dist-info}/WHEEL +0 -0
- {copyparty-1.12.0.dist-info → copyparty-1.12.2.dist-info}/entry_points.txt +0 -0
- {copyparty-1.12.0.dist-info → copyparty-1.12.2.dist-info}/top_level.txt +0 -0
copyparty/__main__.py
CHANGED
@@ -852,6 +852,7 @@ def add_fs(ap):
|
|
852
852
|
ap2 = ap.add_argument_group("filesystem options")
|
853
853
|
rm_re_def = "5/0.1" if ANYWIN else "0/0"
|
854
854
|
ap2.add_argument("--rm-retry", metavar="T/R", type=u, default=rm_re_def, help="if a file cannot be deleted because it is busy, continue trying for \033[33mT\033[0m seconds, retry every \033[33mR\033[0m seconds; disable with 0/0 (volflag=rm_retry)")
|
855
|
+
ap2.add_argument("--mv-retry", metavar="T/R", type=u, default=rm_re_def, help="if a file cannot be renamed because it is busy, continue trying for \033[33mT\033[0m seconds, retry every \033[33mR\033[0m seconds; disable with 0/0 (volflag=mv_retry)")
|
855
856
|
ap2.add_argument("--iobuf", metavar="BYTES", type=int, default=256*1024, help="file I/O buffer-size; if your volumes are on a network drive, try increasing to \033[32m524288\033[0m or even \033[32m4194304\033[0m (and let me know if that improves your performance)")
|
856
857
|
|
857
858
|
|
@@ -943,6 +944,8 @@ def add_auth(ap):
|
|
943
944
|
ap2.add_argument("--idp-h-grp", metavar="HN", type=u, default="", help="assume the request-header \033[33mHN\033[0m contains the groupname of the requesting user; can be referenced in config files for group-based access control")
|
944
945
|
ap2.add_argument("--idp-h-key", metavar="HN", type=u, default="", help="optional but recommended safeguard; your reverse-proxy will insert a secret header named \033[33mHN\033[0m into all requests, and the other IdP headers will be ignored if this header is not present")
|
945
946
|
ap2.add_argument("--idp-gsep", metavar="RE", type=u, default="|:;+,", help="if there are multiple groups in \033[33m--idp-h-grp\033[0m, they are separated by one of the characters in \033[33mRE\033[0m")
|
947
|
+
ap2.add_argument("--no-bauth", action="store_true", help="disable basic-authentication support; do not accept passwords from the 'Authenticate' header at all. NOTE: This breaks support for the android app")
|
948
|
+
ap2.add_argument("--bauth-last", action="store_true", help="keeps basic-authentication enabled, but only as a last-resort; if a cookie is also provided then the cookie wins")
|
946
949
|
|
947
950
|
|
948
951
|
def add_zeroconf(ap):
|
copyparty/__version__.py
CHANGED
copyparty/authsrv.py
CHANGED
@@ -1757,13 +1757,14 @@ class AuthSrv(object):
|
|
1757
1757
|
if k in vol.flags:
|
1758
1758
|
vol.flags[k] = float(vol.flags[k])
|
1759
1759
|
|
1760
|
-
|
1761
|
-
|
1762
|
-
|
1763
|
-
|
1764
|
-
|
1765
|
-
|
1766
|
-
|
1760
|
+
for k in ("mv_re", "rm_re"):
|
1761
|
+
try:
|
1762
|
+
zs1, zs2 = vol.flags[k + "try"].split("/")
|
1763
|
+
vol.flags[k + "_t"] = float(zs1)
|
1764
|
+
vol.flags[k + "_r"] = float(zs2)
|
1765
|
+
except:
|
1766
|
+
t = 'volume "/%s" has invalid %stry [%s]'
|
1767
|
+
raise Exception(t % (vol.vpath, k, vol.flags.get(k + "try")))
|
1767
1768
|
|
1768
1769
|
for k1, k2 in IMPLICATIONS:
|
1769
1770
|
if k1 in vol.flags:
|
copyparty/cert.py
CHANGED
@@ -6,10 +6,17 @@ import os
|
|
6
6
|
import shutil
|
7
7
|
import time
|
8
8
|
|
9
|
-
from .
|
9
|
+
from .__init__ import ANYWIN
|
10
|
+
from .util import Netdev, runcmd, wrename, wunlink
|
10
11
|
|
11
12
|
HAVE_CFSSL = True
|
12
13
|
|
14
|
+
if ANYWIN:
|
15
|
+
VF = {"mv_re_t": 5, "rm_re_t": 5, "mv_re_r": 0.1, "rm_re_r": 0.1}
|
16
|
+
else:
|
17
|
+
VF = {"mv_re_t": 0, "rm_re_t": 0}
|
18
|
+
|
19
|
+
|
13
20
|
def ensure_cert(log , args) :
|
14
21
|
"""
|
15
22
|
the default cert (and the entire TLS support) is only here to enable the
|
@@ -101,8 +108,12 @@ def _gen_ca(log , args):
|
|
101
108
|
raise Exception("failed to translate ca-cert: {}, {}".format(rc, se), 3)
|
102
109
|
|
103
110
|
bname = os.path.join(args.crt_dir, "ca")
|
104
|
-
|
105
|
-
|
111
|
+
try:
|
112
|
+
wunlink(log, bname + ".key", VF)
|
113
|
+
except:
|
114
|
+
pass
|
115
|
+
wrename(log, bname + "-key.pem", bname + ".key", VF)
|
116
|
+
wunlink(log, bname + ".csr", VF)
|
106
117
|
|
107
118
|
log("cert", "new ca OK", 2)
|
108
119
|
|
@@ -181,11 +192,11 @@ def _gen_srv(log , args, netdevs ):
|
|
181
192
|
|
182
193
|
bname = os.path.join(args.crt_dir, "srv")
|
183
194
|
try:
|
184
|
-
|
195
|
+
wunlink(log, bname + ".key", VF)
|
185
196
|
except:
|
186
197
|
pass
|
187
|
-
|
188
|
-
|
198
|
+
wrename(log, bname + "-key.pem", bname + ".key", VF)
|
199
|
+
wunlink(log, bname + ".csr", VF)
|
189
200
|
|
190
201
|
with open(os.path.join(args.crt_dir, "ca.pem"), "rb") as f:
|
191
202
|
ca = f.read()
|
copyparty/cfg.py
CHANGED
@@ -63,6 +63,7 @@ def vf_vmap() :
|
|
63
63
|
"lg_sbf",
|
64
64
|
"md_sbf",
|
65
65
|
"nrand",
|
66
|
+
"mv_retry",
|
66
67
|
"rm_retry",
|
67
68
|
"sort",
|
68
69
|
"unlist",
|
@@ -214,6 +215,7 @@ flagcats = {
|
|
214
215
|
"dots": "allow all users with read-access to\nenable the option to show dotfiles in listings",
|
215
216
|
"fk=8": 'generates per-file accesskeys,\nwhich are then required at the "g" permission;\nkeys are invalidated if filesize or inode changes',
|
216
217
|
"fka=8": 'generates slightly weaker per-file accesskeys,\nwhich are then required at the "g" permission;\nnot affected by filesize or inode numbers',
|
218
|
+
"mv_retry": "ms-windows: timeout for renaming busy files",
|
217
219
|
"rm_retry": "ms-windows: timeout for deleting busy files",
|
218
220
|
"davauth": "ask webdav clients to login for all folders",
|
219
221
|
"davrt": "show lastmod time of symlink destination, not the link itself\n(note: this option is always enabled for recursive listings)",
|
copyparty/httpcli.py
CHANGED
@@ -89,6 +89,7 @@ from .util import (
|
|
89
89
|
vjoin,
|
90
90
|
vol_san,
|
91
91
|
vsplit,
|
92
|
+
wrename,
|
92
93
|
wunlink,
|
93
94
|
yieldfile,
|
94
95
|
)
|
@@ -439,7 +440,11 @@ class HttpCli(object):
|
|
439
440
|
|
440
441
|
zso = self.headers.get("authorization")
|
441
442
|
bauth = ""
|
442
|
-
if
|
443
|
+
if (
|
444
|
+
zso
|
445
|
+
and not self.args.no_bauth
|
446
|
+
and (not cookie_pw or not self.args.bauth_last)
|
447
|
+
):
|
443
448
|
try:
|
444
449
|
zb = zso.split(" ")[1].encode("ascii")
|
445
450
|
zs = base64.b64decode(zb).decode("utf-8")
|
@@ -1796,7 +1801,7 @@ class HttpCli(object):
|
|
1796
1801
|
f, fn = zfw["orz"]
|
1797
1802
|
|
1798
1803
|
path2 = os.path.join(fdir, fn2)
|
1799
|
-
atomic_move(path, path2)
|
1804
|
+
atomic_move(self.log, path, path2, vfs.flags)
|
1800
1805
|
fn = fn2
|
1801
1806
|
path = path2
|
1802
1807
|
|
@@ -1877,7 +1882,9 @@ class HttpCli(object):
|
|
1877
1882
|
self.reply(t.encode("utf-8"), 201, headers=h)
|
1878
1883
|
return True
|
1879
1884
|
|
1880
|
-
def bakflip(
|
1885
|
+
def bakflip(
|
1886
|
+
self, f , ofs , sz , sha , flags
|
1887
|
+
) :
|
1881
1888
|
if not self.args.bak_flips or self.args.nw:
|
1882
1889
|
return
|
1883
1890
|
|
@@ -1905,7 +1912,7 @@ class HttpCli(object):
|
|
1905
1912
|
|
1906
1913
|
if nrem:
|
1907
1914
|
self.log("bakflip truncated; {} remains".format(nrem), 1)
|
1908
|
-
atomic_move(fp, fp + ".trunc")
|
1915
|
+
atomic_move(self.log, fp, fp + ".trunc", flags)
|
1909
1916
|
else:
|
1910
1917
|
self.log("bakflip ok", 2)
|
1911
1918
|
|
@@ -2171,7 +2178,7 @@ class HttpCli(object):
|
|
2171
2178
|
|
2172
2179
|
if sha_b64 != chash:
|
2173
2180
|
try:
|
2174
|
-
self.bakflip(f, cstart[0], post_sz, sha_b64)
|
2181
|
+
self.bakflip(f, cstart[0], post_sz, sha_b64, vfs.flags)
|
2175
2182
|
except:
|
2176
2183
|
self.log("bakflip failed: " + min_ex())
|
2177
2184
|
|
@@ -2523,7 +2530,7 @@ class HttpCli(object):
|
|
2523
2530
|
raise
|
2524
2531
|
|
2525
2532
|
if not nullwrite:
|
2526
|
-
atomic_move(tabspath, abspath)
|
2533
|
+
atomic_move(self.log, tabspath, abspath, vfs.flags)
|
2527
2534
|
|
2528
2535
|
tabspath = ""
|
2529
2536
|
|
@@ -2763,7 +2770,7 @@ class HttpCli(object):
|
|
2763
2770
|
hidedir(dp)
|
2764
2771
|
except:
|
2765
2772
|
pass
|
2766
|
-
|
2773
|
+
wrename(self.log, fp, os.path.join(mdir, ".hist", mfile2), vfs.flags)
|
2767
2774
|
|
2768
2775
|
assert self.parser.gen
|
2769
2776
|
p_field, _, p_data = next(self.parser.gen)
|
copyparty/multicast.py
CHANGED
copyparty/svchub.py
CHANGED
@@ -418,6 +418,12 @@ class SvcHub(object):
|
|
418
418
|
t = "WARNING: found config files in [%s]: %s\n config files are not expected here, and will NOT be loaded (unless your setup is intentionally hella funky)"
|
419
419
|
self.log("root", t % (E.cfg, ", ".join(hits)), 3)
|
420
420
|
|
421
|
+
if self.args.no_bauth:
|
422
|
+
t = "WARNING: --no-bauth disables support for the Android app; you may want to use --bauth-last instead"
|
423
|
+
self.log("root", t, 3)
|
424
|
+
if self.args.bauth_last:
|
425
|
+
self.log("root", "WARNING: ignoring --bauth-last due to --no-bauth", 3)
|
426
|
+
|
421
427
|
def _process_config(self) :
|
422
428
|
al = self.args
|
423
429
|
|
@@ -538,6 +544,13 @@ class SvcHub(object):
|
|
538
544
|
except:
|
539
545
|
raise Exception("invalid --rm-retry [%s]" % (self.args.rm_retry,))
|
540
546
|
|
547
|
+
try:
|
548
|
+
zf1, zf2 = self.args.mv_retry.split("/")
|
549
|
+
self.args.mv_re_t = float(zf1)
|
550
|
+
self.args.mv_re_r = float(zf2)
|
551
|
+
except:
|
552
|
+
raise Exception("invalid --mv-retry [%s]" % (self.args.mv_retry,))
|
553
|
+
|
541
554
|
return True
|
542
555
|
|
543
556
|
def _ipa2re(self, txt) :
|
copyparty/th_srv.py
CHANGED
@@ -28,6 +28,7 @@ from .util import (
|
|
28
28
|
runcmd,
|
29
29
|
statdir,
|
30
30
|
vsplit,
|
31
|
+
wrename,
|
31
32
|
wunlink,
|
32
33
|
)
|
33
34
|
|
@@ -343,7 +344,7 @@ class ThumbSrv(object):
|
|
343
344
|
pass
|
344
345
|
|
345
346
|
try:
|
346
|
-
|
347
|
+
wrename(self.log, ttpath, tpath, vn.flags)
|
347
348
|
except:
|
348
349
|
pass
|
349
350
|
|
copyparty/up2k.py
CHANGED
@@ -88,6 +88,9 @@ CV_EXTS = set(zsg.split(","))
|
|
88
88
|
HINT_HISTPATH = "you could try moving the database to another location (preferably an SSD or NVME drive) using either the --hist argument (global option for all volumes), or the hist volflag (just for this volume)"
|
89
89
|
|
90
90
|
|
91
|
+
VF_CAREFUL = {"mv_re_t": 5, "rm_re_t": 5, "mv_re_r": 0.1, "rm_re_r": 0.1}
|
92
|
+
|
93
|
+
|
91
94
|
class Dbw(object):
|
92
95
|
def __init__(self, c , n , t ) :
|
93
96
|
self.c = c
|
@@ -866,7 +869,7 @@ class Up2k(object):
|
|
866
869
|
ft = "\033[0;32m{}{:.0}"
|
867
870
|
ff = "\033[0;35m{}{:.0}"
|
868
871
|
fv = "\033[0;36m{}:\033[90m{}"
|
869
|
-
fx = set(("html_head", "rm_re_t", "rm_re_r"))
|
872
|
+
fx = set(("html_head", "rm_re_t", "rm_re_r", "mv_re_t", "mv_re_r"))
|
870
873
|
fd = vf_bmap()
|
871
874
|
fd.update(vf_cmap())
|
872
875
|
fd.update(vf_vmap())
|
@@ -3041,12 +3044,11 @@ class Up2k(object):
|
|
3041
3044
|
t = "finish_upload {} with remaining chunks {}"
|
3042
3045
|
raise Pebkac(500, t.format(wark, job["need"]))
|
3043
3046
|
|
3044
|
-
# self.log("--- " + wark + " " + dst + " finish_upload atomic " + dst, 4)
|
3045
|
-
atomic_move(src, dst)
|
3046
|
-
|
3047
3047
|
upt = job.get("at") or time.time()
|
3048
3048
|
vflags = self.flags[ptop]
|
3049
3049
|
|
3050
|
+
atomic_move(self.log, src, dst, vflags)
|
3051
|
+
|
3050
3052
|
times = (int(time.time()), int(job["lmod"]))
|
3051
3053
|
self.log(
|
3052
3054
|
"no more chunks, setting times {} ({}) on {}".format(
|
@@ -3650,7 +3652,7 @@ class Up2k(object):
|
|
3650
3652
|
self._symlink(dlink, dabs, dvn.flags, lmod=ftime)
|
3651
3653
|
wunlink(self.log, sabs, svn.flags)
|
3652
3654
|
else:
|
3653
|
-
atomic_move(sabs, dabs)
|
3655
|
+
atomic_move(self.log, sabs, dabs, svn.flags)
|
3654
3656
|
|
3655
3657
|
except OSError as ex:
|
3656
3658
|
if ex.errno != errno.EXDEV:
|
@@ -3827,8 +3829,7 @@ class Up2k(object):
|
|
3827
3829
|
self.log("linkswap [{}] and [{}]".format(sabs, slabs))
|
3828
3830
|
mt = bos.path.getmtime(slabs, False)
|
3829
3831
|
flags = self.flags.get(ptop) or {}
|
3830
|
-
|
3831
|
-
bos.rename(sabs, slabs)
|
3832
|
+
atomic_move(self.log, sabs, slabs, flags)
|
3832
3833
|
bos.utime(slabs, (int(time.time()), int(mt)), False)
|
3833
3834
|
self._symlink(slabs, sabs, flags, False)
|
3834
3835
|
full[slabs] = (ptop, rem)
|
@@ -4139,7 +4140,7 @@ class Up2k(object):
|
|
4139
4140
|
with gzip.GzipFile(path2, "wb") as f:
|
4140
4141
|
f.write(j)
|
4141
4142
|
|
4142
|
-
atomic_move(path2, path)
|
4143
|
+
atomic_move(self.log, path2, path, VF_CAREFUL)
|
4143
4144
|
|
4144
4145
|
self.log("snap: {} |{}|".format(path, len(reg.keys())))
|
4145
4146
|
self.snap_prev[ptop] = etag
|
copyparty/util.py
CHANGED
@@ -2104,26 +2104,29 @@ def lsof(log , abspath ) :
|
|
2104
2104
|
log("lsof failed; " + min_ex(), 3)
|
2105
2105
|
|
2106
2106
|
|
2107
|
-
def
|
2108
|
-
src
|
2109
|
-
|
2110
|
-
|
2111
|
-
|
2107
|
+
def _fs_mvrm(
|
2108
|
+
log , src , dst , atomic , flags
|
2109
|
+
) :
|
2110
|
+
bsrc = fsenc(src)
|
2111
|
+
bdst = fsenc(dst)
|
2112
|
+
if atomic:
|
2113
|
+
k = "mv_re_"
|
2114
|
+
act = "atomic-rename"
|
2115
|
+
osfun = os.replace
|
2116
|
+
args = [bsrc, bdst]
|
2117
|
+
elif dst:
|
2118
|
+
k = "mv_re_"
|
2119
|
+
act = "rename"
|
2120
|
+
osfun = os.rename
|
2121
|
+
args = [bsrc, bdst]
|
2112
2122
|
else:
|
2113
|
-
|
2114
|
-
|
2115
|
-
|
2116
|
-
|
2117
|
-
|
2118
|
-
|
2119
|
-
def wunlink(log , abspath , flags ) :
|
2120
|
-
maxtime = flags.get("rm_re_t", 0.0)
|
2121
|
-
bpath = fsenc(abspath)
|
2122
|
-
if not maxtime:
|
2123
|
-
os.unlink(bpath)
|
2124
|
-
return True
|
2123
|
+
k = "rm_re_"
|
2124
|
+
act = "delete"
|
2125
|
+
osfun = os.unlink
|
2126
|
+
args = [bsrc]
|
2125
2127
|
|
2126
|
-
|
2128
|
+
maxtime = flags.get(k + "t", 0.0)
|
2129
|
+
chill = flags.get(k + "r", 0.0)
|
2127
2130
|
if chill < 0.001:
|
2128
2131
|
chill = 0.1
|
2129
2132
|
|
@@ -2131,14 +2134,19 @@ def wunlink(log , abspath , flags ) :
|
|
2131
2134
|
t0 = now = time.time()
|
2132
2135
|
for attempt in range(90210):
|
2133
2136
|
try:
|
2134
|
-
if ino and os.stat(
|
2135
|
-
|
2137
|
+
if ino and os.stat(bsrc).st_ino != ino:
|
2138
|
+
t = "src inode changed; aborting %s %s"
|
2139
|
+
log(t % (act, src), 1)
|
2136
2140
|
return False
|
2137
|
-
os.
|
2141
|
+
if (dst and not atomic) and os.path.exists(bdst):
|
2142
|
+
t = "something appeared at dst; aborting rename [%s] ==> [%s]"
|
2143
|
+
log(t % (src, dst), 1)
|
2144
|
+
return False
|
2145
|
+
osfun(*args)
|
2138
2146
|
if attempt:
|
2139
2147
|
now = time.time()
|
2140
|
-
t = "
|
2141
|
-
log(t % (now - t0, attempt + 1))
|
2148
|
+
t = "%sd in %.2f sec, attempt %d: %s"
|
2149
|
+
log(t % (act, now - t0, attempt + 1, src))
|
2142
2150
|
return True
|
2143
2151
|
except OSError as ex:
|
2144
2152
|
now = time.time()
|
@@ -2148,15 +2156,45 @@ def wunlink(log , abspath , flags ) :
|
|
2148
2156
|
raise
|
2149
2157
|
if not attempt:
|
2150
2158
|
if not PY2:
|
2151
|
-
ino = os.stat(
|
2152
|
-
t = "
|
2153
|
-
log(t % (ex.errno, maxtime + 0.99,
|
2159
|
+
ino = os.stat(bsrc).st_ino
|
2160
|
+
t = "%s failed (err.%d); retrying for %d sec: [%s]"
|
2161
|
+
log(t % (act, ex.errno, maxtime + 0.99, src))
|
2154
2162
|
|
2155
2163
|
time.sleep(chill)
|
2156
2164
|
|
2157
2165
|
return False # makes pylance happy
|
2158
2166
|
|
2159
2167
|
|
2168
|
+
def atomic_move(log , src , dst , flags ) :
|
2169
|
+
bsrc = fsenc(src)
|
2170
|
+
bdst = fsenc(dst)
|
2171
|
+
if PY2:
|
2172
|
+
if os.path.exists(bdst):
|
2173
|
+
_fs_mvrm(log, dst, "", False, flags) # unlink
|
2174
|
+
|
2175
|
+
_fs_mvrm(log, src, dst, False, flags) # rename
|
2176
|
+
elif flags.get("mv_re_t"):
|
2177
|
+
_fs_mvrm(log, src, dst, True, flags)
|
2178
|
+
else:
|
2179
|
+
os.replace(bsrc, bdst)
|
2180
|
+
|
2181
|
+
|
2182
|
+
def wrename(log , src , dst , flags ) :
|
2183
|
+
if not flags.get("mv_re_t"):
|
2184
|
+
os.rename(fsenc(src), fsenc(dst))
|
2185
|
+
return True
|
2186
|
+
|
2187
|
+
return _fs_mvrm(log, src, dst, False, flags)
|
2188
|
+
|
2189
|
+
|
2190
|
+
def wunlink(log , abspath , flags ) :
|
2191
|
+
if not flags.get("rm_re_t"):
|
2192
|
+
os.unlink(fsenc(abspath))
|
2193
|
+
return True
|
2194
|
+
|
2195
|
+
return _fs_mvrm(log, abspath, "", False, flags)
|
2196
|
+
|
2197
|
+
|
2160
2198
|
def get_df(abspath ) :
|
2161
2199
|
try:
|
2162
2200
|
# some fuses misbehave
|
copyparty/web/baguettebox.js.gz
CHANGED
Binary file
|
copyparty/web/browser.css.gz
CHANGED
Binary file
|
copyparty/web/browser.js.gz
CHANGED
Binary file
|
copyparty/web/splash.css.gz
CHANGED
Binary file
|
copyparty/web/splash.html
CHANGED
@@ -94,7 +94,7 @@
|
|
94
94
|
<div>
|
95
95
|
<form method="post" enctype="multipart/form-data" action="{{ r }}/{{ qvpath }}">
|
96
96
|
<input type="hidden" name="act" value="login" />
|
97
|
-
<input type="password" name="cppwd" />
|
97
|
+
<input type="password" name="cppwd" placeholder=" password" />
|
98
98
|
<input type="submit" value="Login" />
|
99
99
|
{% if ahttps %}
|
100
100
|
<a id="w" href="{{ ahttps }}">switch to https</a>
|
copyparty/web/util.js.gz
CHANGED
Binary file
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: copyparty
|
3
|
-
Version: 1.12.
|
3
|
+
Version: 1.12.2
|
4
4
|
Summary: Portable file server with accelerated resumable uploads, deduplication, WebDAV, FTP, zeroconf, media indexer, video thumbnails, audio transcoding, and write-only folders
|
5
5
|
Author-email: ed <copyparty@ocv.me>
|
6
6
|
License: MIT
|
@@ -69,6 +69,7 @@ turn almost any device into a file server with resumable uploads/downloads using
|
|
69
69
|
|
70
70
|
* top
|
71
71
|
* [quickstart](#quickstart) - just run **[copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/download/copyparty-sfx.py)** -- that's it! 🎉
|
72
|
+
* [at home](#at-home) - make it accessible over the internet
|
72
73
|
* [on servers](#on-servers) - you may also want these, especially on servers
|
73
74
|
* [features](#features)
|
74
75
|
* [testimonials](#testimonials) - small collection of user feedback
|
@@ -201,6 +202,17 @@ some recommended options:
|
|
201
202
|
* see [accounts and volumes](#accounts-and-volumes) (or `--help-accounts`) for the syntax and other permissions
|
202
203
|
|
203
204
|
|
205
|
+
### at home
|
206
|
+
|
207
|
+
make it accessible over the internet by starting a [cloudflare quicktunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/do-more-with-tunnels/trycloudflare/) like so:
|
208
|
+
|
209
|
+
first download [cloudflared](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/) and then start the tunnel with `cloudflared tunnel --url http://127.0.0.1:3923`
|
210
|
+
|
211
|
+
as the tunnel starts, it will show a URL which you can share to let anyone browse your stash or upload files to you
|
212
|
+
|
213
|
+
since people will be connecting through cloudflare, run copyparty with `--xff-hdr cf-connecting-ip` to detect client IPs correctly
|
214
|
+
|
215
|
+
|
204
216
|
### on servers
|
205
217
|
|
206
218
|
you may also want these, especially on servers:
|
@@ -1096,6 +1108,8 @@ tweaking the ui
|
|
1096
1108
|
* to sort in music order (album, track, artist, title) with filename as fallback, you could `--sort tags/Cirle,tags/.tn,tags/Artist,tags/Title,href`
|
1097
1109
|
* to sort by upload date, first enable showing the upload date in the listing with `-e2d -mte +.up_at` and then `--sort tags/.up_at`
|
1098
1110
|
|
1111
|
+
see [./docs/rice](./docs/rice) for more
|
1112
|
+
|
1099
1113
|
|
1100
1114
|
## file indexing
|
1101
1115
|
|
@@ -1,38 +1,38 @@
|
|
1
1
|
copyparty/__init__.py,sha256=fUINM1abqDGzCCH_JcXdOnLdKOV-SrTI2Xo2QgQW2P4,1703
|
2
|
-
copyparty/__main__.py,sha256=
|
3
|
-
copyparty/__version__.py,sha256=
|
4
|
-
copyparty/authsrv.py,sha256
|
2
|
+
copyparty/__main__.py,sha256=S4Q3vX1OcxDX4jdiaUmJ6ISxI4zmWEqmuNmgycEuFng,95106
|
3
|
+
copyparty/__version__.py,sha256=M_tUfeuxrcHAVaa7MIyCrvu8zP98hSnRNS-1cY7Bqxw,251
|
4
|
+
copyparty/authsrv.py,sha256=-MZQnSsrEGD8cTtR90qT5-xoc9xD8PP8cjvBL75HMKo,84501
|
5
5
|
copyparty/broker_mp.py,sha256=4mEZC5tiHUazJMgYuwInNo2dxS7jrbzrGb1qs2UBt9k,3948
|
6
6
|
copyparty/broker_mpw.py,sha256=4ZI7bJYOwUibeAJVv9_FPGNmHrr9eOtkj_Kz0JEppTU,3197
|
7
7
|
copyparty/broker_thr.py,sha256=eKr--HJGig5zqvNGwH9UoBG9Nvi9mT2axrRmJwknd0s,1759
|
8
8
|
copyparty/broker_util.py,sha256=CnX_LAhQQqouONcDLtVkVlcBX3Z6pWuKDQDmmbHGEg4,1489
|
9
|
-
copyparty/cert.py,sha256=
|
10
|
-
copyparty/cfg.py,sha256=
|
9
|
+
copyparty/cert.py,sha256=nCeDdzcCpvjPPUcxT4Oh7wvL_8zvddu4oXtbA-zOb8g,7607
|
10
|
+
copyparty/cfg.py,sha256=6r2-UQ7ule18evBOAxa4wMVyIag2ce32JwMh6TcibXU,9276
|
11
11
|
copyparty/dxml.py,sha256=lZpg-kn-kQsXRtNY1n6fRaS-b7uXzMCyv8ovKnhZcZc,1548
|
12
12
|
copyparty/fsutil.py,sha256=c4fTvmclKbVABNsjU4rGddsjCgRwi9YExAyo-06ATc8,3932
|
13
13
|
copyparty/ftpd.py,sha256=OIExjfqOEw-Y_ygez6cIZUQec4SFOmoxEH_WOVvw-aE,15961
|
14
|
-
copyparty/httpcli.py,sha256=
|
14
|
+
copyparty/httpcli.py,sha256=q4yGtOJ_2v7KjRbk6grn0nqhI75hojZvqS3VrWGwT0M,148982
|
15
15
|
copyparty/httpconn.py,sha256=gLOURB2Nb1w6n2ihGBspEnzEfUND9Osa4klzYuAbgzI,6829
|
16
16
|
copyparty/httpsrv.py,sha256=af6LdApfj-Q4mWC5mVQjhnyrFzNy8_bXK3VUe0xKkeY,16368
|
17
17
|
copyparty/ico.py,sha256=AYHdK6NlYBfBgafVYXia3jHQ9XHZdUL1D8WftLMAzIU,3545
|
18
18
|
copyparty/mdns.py,sha256=CcraggbDxTT1ntYzD8Ebgqmw5Q4HkyZcfh5ymtCV_ak,17469
|
19
19
|
copyparty/metrics.py,sha256=OqXFkAuoVhayGAGd_Sv-OQ9SVmdXYV8M7CxitkzE3lo,8854
|
20
20
|
copyparty/mtag.py,sha256=wiXd26ZSYgOu4lkRDn4KLaqo6H2V7cpqUMepTHTCfKE,16851
|
21
|
-
copyparty/multicast.py,sha256=
|
21
|
+
copyparty/multicast.py,sha256=Ha27l2oATEa-Qo2WOzkeRgjAm6G_YDCfbVJWR-ao2UE,12319
|
22
22
|
copyparty/pwhash.py,sha256=D82y8emnwpHDQq7Cr8lNuppHshbNA9ptcR2XsGOOk6E,3937
|
23
23
|
copyparty/smbd.py,sha256=iACj5pbiKsX7bVu20BK3ebPQLB_qA7WS2l-ytrSfT3Y,14054
|
24
24
|
copyparty/ssdp.py,sha256=H6ZftXttydcnBxcg2-Prm4P-XiybgT3xiJRUXU1pbrE,6343
|
25
25
|
copyparty/star.py,sha256=K4NuzyfT4956uoW6GJSQ2II-JsSV57apQZwRZ4mjFoo,3790
|
26
26
|
copyparty/sutil.py,sha256=_G4TM0YFa1vXzhRypHJ88QBdZWtYgDbom4CZjGvGIwc,3074
|
27
|
-
copyparty/svchub.py,sha256=
|
27
|
+
copyparty/svchub.py,sha256=FiX6B70K5XVhCDuQDty8ZXhujThfkFcH3brp1rsEr-A,32258
|
28
28
|
copyparty/szip.py,sha256=631TsEwGKV22yAnusJtvE-9fGFWr61HPGBinu-jk1QA,8591
|
29
29
|
copyparty/tcpsrv.py,sha256=2LGUqOBAIrsmL-1pwrbsPXR71gutHccqRp-hjzt91Us,17289
|
30
30
|
copyparty/tftpd.py,sha256=7EHAZ9LnjAXupwRNIENJ2eA8Q0lFynnwwbziV3fyzns,13157
|
31
31
|
copyparty/th_cli.py,sha256=eSW7sBiaZAsh_XffXFzb035CTSbS3J3Q0G-BMzQGuSY,4385
|
32
|
-
copyparty/th_srv.py,sha256=
|
32
|
+
copyparty/th_srv.py,sha256=C2ZBE6ddINCuYDympRQQmhj0ULdlD6HOM6qNK-UB4so,27191
|
33
33
|
copyparty/u2idx.py,sha256=JBEqKX1ZM8GIvQrDYb5VQ_5QiFNFsjWF6H9drHlPVEY,12709
|
34
|
-
copyparty/up2k.py,sha256=
|
35
|
-
copyparty/util.py,sha256=
|
34
|
+
copyparty/up2k.py,sha256=SnLU_60EZymqESqo13ayVGYewyf0BgZaCoPlpAOGZlQ,140773
|
35
|
+
copyparty/util.py,sha256=br6SQFXLu2Ol6gSpVX498G_ig3M2ZtKP9USMxuWE0qk,82089
|
36
36
|
copyparty/bos/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
37
37
|
copyparty/bos/bos.py,sha256=Wb7eWsXJgR5AFlBR9ZOyKrLTwy-Kct9RrGiOu4Jo37Y,1622
|
38
38
|
copyparty/bos/path.py,sha256=yEjCq2ki9CvxA5sCT8pS0keEXwugs0ZeUyUhdBziOCI,777
|
@@ -54,10 +54,10 @@ copyparty/stolen/ifaddr/__init__.py,sha256=_BUN7eM5oD2Jgib6B22tEFSb20fD9urNPPaAl
|
|
54
54
|
copyparty/stolen/ifaddr/_posix.py,sha256=-67NdfGrCktfQPakT2fLbjl2U00QMvyBGkSvrUuTOrU,2626
|
55
55
|
copyparty/stolen/ifaddr/_shared.py,sha256=cJACl8cOxQ-HSYphZTzKMAjAx_TAFyJwUPjfD102Xqw,6111
|
56
56
|
copyparty/stolen/ifaddr/_win32.py,sha256=EE-QyoBgeB7lYQ6z62VjXNaRozaYfCkaJBHGNA8QtZM,4026
|
57
|
-
copyparty/web/baguettebox.js.gz,sha256=
|
58
|
-
copyparty/web/browser.css.gz,sha256=
|
57
|
+
copyparty/web/baguettebox.js.gz,sha256=Qcx5ZJWWCU4S1J0ULVXuVKWnm_SuCiEknMlt_uwIkJ8,7830
|
58
|
+
copyparty/web/browser.css.gz,sha256=ufB8EMVUJPnHl-NJN-GI3-HFJElJisgB6p0nexNtzrU,11431
|
59
59
|
copyparty/web/browser.html,sha256=uAejLJd11rV_tQx3h2nHnJ1XY6zn1JV-meIAv74Lc8o,4873
|
60
|
-
copyparty/web/browser.js.gz,sha256=
|
60
|
+
copyparty/web/browser.js.gz,sha256=k7COxnPofd9GOMRkk72sdQAJJVRZ1sJfgXXwE247Nkk,67298
|
61
61
|
copyparty/web/browser2.html,sha256=ciQlgr9GWuIapdsRBFNRvRFvN5T_5n920LqDMbsj5-g,1605
|
62
62
|
copyparty/web/cf.html,sha256=lJThtNFNAQT1ClCHHlivAkDGE0LutedwopXD62Z8Nys,589
|
63
63
|
copyparty/web/dbg-audio.js.gz,sha256=Ma-KZtK8LnmiwNvNKFKXMPYl_Nn_3U7GsJ6-DRWC2HE,688
|
@@ -71,14 +71,14 @@ copyparty/web/mde.html,sha256=FMMq4ySXoOrQV5E836KmQCry3COOhMu0DSstAdJZL_g,1678
|
|
71
71
|
copyparty/web/mde.js.gz,sha256=kN2eUSvr4mFuksfK4-4LimJmWdwsao39Sea2lWtu8L0,2224
|
72
72
|
copyparty/web/msg.css.gz,sha256=u90fXYAVrMD-jqwf5XFVC1ptSpSHZUe8Mez6PX101P8,300
|
73
73
|
copyparty/web/msg.html,sha256=XDg51WLO7RruZnoFnKpeJ33k47-tBHP3bR7l55Jwre4,896
|
74
|
-
copyparty/web/splash.css.gz,sha256=
|
75
|
-
copyparty/web/splash.html,sha256=
|
74
|
+
copyparty/web/splash.css.gz,sha256=zgDs-SY3VrInsXeARRPcGHziVOUs-1hUtSObzybwD1g,1006
|
75
|
+
copyparty/web/splash.html,sha256=mPhMBTO3BMaie5lGJGloS6b8HhoujUzDZYAosfDX8fg,3846
|
76
76
|
copyparty/web/splash.js.gz,sha256=2R8UYlAN8WpIABg8clgWckWqgD8nKtz3eGZFu2y1g88,1420
|
77
77
|
copyparty/web/svcs.html,sha256=s7vUSrCrELC3iTemksodRBhQpssO7s4xW1vA-CX6vU8,11702
|
78
78
|
copyparty/web/svcs.js.gz,sha256=k81ZvZ3I-f4fMHKrNGGOgOlvXnCBz0mVjD-8mieoWCA,520
|
79
79
|
copyparty/web/ui.css.gz,sha256=skuzZHqTU0ag5hButpQmKI9wM7ro-UJ2PnpTodTWYF4,2616
|
80
80
|
copyparty/web/up2k.js.gz,sha256=ZuxLQW8mJSvLu_Aa8fDT3F9rptuAzNDmaOLd0MeMrd8,22114
|
81
|
-
copyparty/web/util.js.gz,sha256=
|
81
|
+
copyparty/web/util.js.gz,sha256=3Ys57MotfGguhuCdDhj3afyX8wlz3ZgG5ZrnY4_Zqcw,14377
|
82
82
|
copyparty/web/w.hash.js.gz,sha256=__hBMd5oZWfTrb8ZCJNT21isoSqyrxKE6qdaKGQVAhc,1060
|
83
83
|
copyparty/web/a/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
84
84
|
copyparty/web/a/partyfuse.py,sha256=MuRkaSuYsdfWfBFMOkbPwDXqSvNTw3sd7QhhlKCDZ8I,32311
|
@@ -102,9 +102,9 @@ copyparty/web/deps/prismd.css.gz,sha256=ObUlksQVr-OuYlTz-I4B23TeBg2QDVVGRnWBz8cV
|
|
102
102
|
copyparty/web/deps/scp.woff2,sha256=w99BDU5i8MukkMEL-iW0YO9H4vFFZSPWxbkH70ytaAg,8612
|
103
103
|
copyparty/web/deps/sha512.ac.js.gz,sha256=lFZaCLumgWxrvEuDr4bqdKHsqjX82AbVAb7_F45Yk88,7033
|
104
104
|
copyparty/web/deps/sha512.hw.js.gz,sha256=vqoXeracj-99Z5MfY3jK2N4WiSzYQdfjy0RnUlQDhSU,8110
|
105
|
-
copyparty-1.12.
|
106
|
-
copyparty-1.12.
|
107
|
-
copyparty-1.12.
|
108
|
-
copyparty-1.12.
|
109
|
-
copyparty-1.12.
|
110
|
-
copyparty-1.12.
|
105
|
+
copyparty-1.12.2.dist-info/LICENSE,sha256=gOr4h33pCsBEg9uIy9AYmb7qlocL4V9t2uPJS5wllr0,1072
|
106
|
+
copyparty-1.12.2.dist-info/METADATA,sha256=CXx9dAVjA9andahLVjyqMzqKeOVzLch9fj3D5GfyQP0,118373
|
107
|
+
copyparty-1.12.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
108
|
+
copyparty-1.12.2.dist-info/entry_points.txt,sha256=4zw6a3rqASywQomiYLObjjlxybaI65LYYOTJwgKz7b0,128
|
109
|
+
copyparty-1.12.2.dist-info/top_level.txt,sha256=LnYUPsDyk-8kFgM6YJLG4h820DQekn81cObKSu9g-sI,10
|
110
|
+
copyparty-1.12.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|