copyparty 1.15.1__py3-none-any.whl → 1.15.3__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/__init__.py +1 -0
- copyparty/__main__.py +16 -12
- copyparty/__version__.py +2 -2
- copyparty/authsrv.py +11 -6
- copyparty/broker_mp.py +2 -2
- copyparty/broker_mpw.py +2 -2
- copyparty/broker_thr.py +4 -9
- copyparty/broker_util.py +13 -1
- copyparty/cfg.py +1 -0
- copyparty/fsutil.py +0 -3
- copyparty/httpcli.py +105 -60
- copyparty/httpconn.py +0 -1
- copyparty/httpsrv.py +3 -5
- copyparty/svchub.py +2 -6
- copyparty/th_srv.py +15 -7
- copyparty/u2idx.py +0 -3
- copyparty/up2k.py +206 -98
- copyparty/util.py +116 -63
- copyparty/web/browser.js.gz +0 -0
- copyparty/web/splash.css.gz +0 -0
- copyparty/web/splash.html +12 -0
- copyparty/web/splash.js.gz +0 -0
- {copyparty-1.15.1.dist-info → copyparty-1.15.3.dist-info}/METADATA +15 -3
- {copyparty-1.15.1.dist-info → copyparty-1.15.3.dist-info}/RECORD +28 -28
- {copyparty-1.15.1.dist-info → copyparty-1.15.3.dist-info}/WHEEL +1 -1
- {copyparty-1.15.1.dist-info → copyparty-1.15.3.dist-info}/LICENSE +0 -0
- {copyparty-1.15.1.dist-info → copyparty-1.15.3.dist-info}/entry_points.txt +0 -0
- {copyparty-1.15.1.dist-info → copyparty-1.15.3.dist-info}/top_level.txt +0 -0
copyparty/__init__.py
CHANGED
copyparty/__main__.py
CHANGED
@@ -27,6 +27,7 @@ from .__init__ import (
|
|
27
27
|
EXE,
|
28
28
|
MACOS,
|
29
29
|
PY2,
|
30
|
+
PY36,
|
30
31
|
VT100,
|
31
32
|
WINDOWS,
|
32
33
|
E,
|
@@ -54,6 +55,7 @@ from .util import (
|
|
54
55
|
Daemon,
|
55
56
|
align_tab,
|
56
57
|
ansi_re,
|
58
|
+
b64enc,
|
57
59
|
dedent,
|
58
60
|
min_ex,
|
59
61
|
pybin,
|
@@ -198,7 +200,7 @@ def init_E(EE ) :
|
|
198
200
|
errs.append("Using [%s] instead" % (p,))
|
199
201
|
|
200
202
|
if errs:
|
201
|
-
|
203
|
+
warn(". ".join(errs))
|
202
204
|
|
203
205
|
return p # type: ignore
|
204
206
|
except Exception as ex:
|
@@ -228,7 +230,7 @@ def init_E(EE ) :
|
|
228
230
|
raise
|
229
231
|
|
230
232
|
|
231
|
-
def get_srvname() :
|
233
|
+
def get_srvname(verbose) :
|
232
234
|
try:
|
233
235
|
ret = unicode(socket.gethostname()).split(".")[0]
|
234
236
|
except:
|
@@ -238,7 +240,8 @@ def get_srvname() :
|
|
238
240
|
return ret
|
239
241
|
|
240
242
|
fp = os.path.join(E.cfg, "name.txt")
|
241
|
-
|
243
|
+
if verbose:
|
244
|
+
lprint("using hostname from {}\n".format(fp))
|
242
245
|
try:
|
243
246
|
with open(fp, "rb") as f:
|
244
247
|
ret = f.read().decode("utf-8", "replace").strip()
|
@@ -260,7 +263,7 @@ def get_fk_salt() :
|
|
260
263
|
with open(fp, "rb") as f:
|
261
264
|
ret = f.read().strip()
|
262
265
|
except:
|
263
|
-
ret =
|
266
|
+
ret = b64enc(os.urandom(18))
|
264
267
|
with open(fp, "wb") as f:
|
265
268
|
f.write(ret + b"\n")
|
266
269
|
|
@@ -273,7 +276,7 @@ def get_dk_salt() :
|
|
273
276
|
with open(fp, "rb") as f:
|
274
277
|
ret = f.read().strip()
|
275
278
|
except:
|
276
|
-
ret =
|
279
|
+
ret = b64enc(os.urandom(30))
|
277
280
|
with open(fp, "wb") as f:
|
278
281
|
f.write(ret + b"\n")
|
279
282
|
|
@@ -286,7 +289,7 @@ def get_ah_salt() :
|
|
286
289
|
with open(fp, "rb") as f:
|
287
290
|
ret = f.read().strip()
|
288
291
|
except:
|
289
|
-
ret =
|
292
|
+
ret = b64enc(os.urandom(18))
|
290
293
|
with open(fp, "wb") as f:
|
291
294
|
f.write(ret + b"\n")
|
292
295
|
|
@@ -344,7 +347,6 @@ def configure_ssl_ver(al ) :
|
|
344
347
|
# oh man i love openssl
|
345
348
|
# check this out
|
346
349
|
# hold my beer
|
347
|
-
assert ssl # type: ignore
|
348
350
|
ptn = re.compile(r"^OP_NO_(TLS|SSL)v")
|
349
351
|
sslver = terse_sslver(al.ssl_ver).split(",")
|
350
352
|
flags = [k for k in ssl.__dict__ if ptn.match(k)]
|
@@ -378,7 +380,6 @@ def configure_ssl_ver(al ) :
|
|
378
380
|
|
379
381
|
|
380
382
|
def configure_ssl_ciphers(al ) :
|
381
|
-
assert ssl # type: ignore
|
382
383
|
ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
383
384
|
if al.ssl_ver:
|
384
385
|
ctx.options &= ~al.ssl_flags_en
|
@@ -1224,6 +1225,7 @@ def add_optouts(ap):
|
|
1224
1225
|
ap2.add_argument("--no-zip", action="store_true", help="disable download as zip/tar")
|
1225
1226
|
ap2.add_argument("--no-tarcmp", action="store_true", help="disable download as compressed tar (?tar=gz, ?tar=bz2, ?tar=xz, ?tar=gz:9, ...)")
|
1226
1227
|
ap2.add_argument("--no-lifetime", action="store_true", help="do not allow clients (or server config) to schedule an upload to be deleted after a given time")
|
1228
|
+
ap2.add_argument("--no-up-list", action="store_true", help="don't show list of incoming files in controlpanel")
|
1227
1229
|
ap2.add_argument("--no-pipe", action="store_true", help="disable race-the-beam (lockstep download of files which are currently being uploaded) (volflag=nopipe)")
|
1228
1230
|
ap2.add_argument("--no-db-ip", action="store_true", help="do not write uploader IPs into the database")
|
1229
1231
|
|
@@ -1352,6 +1354,8 @@ def add_db_general(ap, hcores):
|
|
1352
1354
|
ap2.add_argument("--hist", metavar="PATH", type=u, default="", help="where to store volume data (db, thumbs); default is a folder named \".hist\" inside each volume (volflag=hist)")
|
1353
1355
|
ap2.add_argument("--no-hash", metavar="PTN", type=u, default="", help="regex: disable hashing of matching absolute-filesystem-paths during e2ds folder scans (volflag=nohash)")
|
1354
1356
|
ap2.add_argument("--no-idx", metavar="PTN", type=u, default=noidx, help="regex: disable indexing of matching absolute-filesystem-paths during e2ds folder scans (volflag=noidx)")
|
1357
|
+
ap2.add_argument("--no-dirsz", action="store_true", help="do not show total recursive size of folders in listings, show inode size instead; slightly faster (volflag=nodirsz)")
|
1358
|
+
ap2.add_argument("--re-dirsz", action="store_true", help="if the directory-sizes in the UI are bonkers, use this along with \033[33m-e2dsa\033[0m to rebuild the index from scratch")
|
1355
1359
|
ap2.add_argument("--no-dhash", action="store_true", help="disable rescan acceleration; do full database integrity check -- makes the db ~5%% smaller and bootup/rescans 3~10x slower")
|
1356
1360
|
ap2.add_argument("--re-dhash", action="store_true", help="force a cache rebuild on startup; enable this once if it gets out of sync (should never be necessary)")
|
1357
1361
|
ap2.add_argument("--no-forget", action="store_true", help="never forget indexed files, even when deleted from disk -- makes it impossible to ever upload the same file twice -- only useful for offloading uploads to a cloud service or something (volflag=noforget)")
|
@@ -1465,7 +1469,7 @@ def add_debug(ap):
|
|
1465
1469
|
|
1466
1470
|
|
1467
1471
|
def run_argparse(
|
1468
|
-
argv , formatter , retry , nc
|
1472
|
+
argv , formatter , retry , nc , verbose=True
|
1469
1473
|
) :
|
1470
1474
|
ap = argparse.ArgumentParser(
|
1471
1475
|
formatter_class=formatter,
|
@@ -1487,7 +1491,7 @@ def run_argparse(
|
|
1487
1491
|
|
1488
1492
|
tty = os.environ.get("TERM", "").lower() == "linux"
|
1489
1493
|
|
1490
|
-
srvname = get_srvname()
|
1494
|
+
srvname = get_srvname(verbose)
|
1491
1495
|
|
1492
1496
|
add_general(ap, nc, srvname)
|
1493
1497
|
add_network(ap)
|
@@ -1667,7 +1671,7 @@ def main(argv = None, rsrc = None) :
|
|
1667
1671
|
for fmtr in [RiceFormatter, RiceFormatter, Dodge11874, BasicDodge11874]:
|
1668
1672
|
try:
|
1669
1673
|
al = run_argparse(argv, fmtr, retry, nc)
|
1670
|
-
dal = run_argparse([], fmtr, retry, nc)
|
1674
|
+
dal = run_argparse([], fmtr, retry, nc, False)
|
1671
1675
|
break
|
1672
1676
|
except SystemExit:
|
1673
1677
|
raise
|
@@ -1751,7 +1755,7 @@ def main(argv = None, rsrc = None) :
|
|
1751
1755
|
print("error: python2 cannot --smb")
|
1752
1756
|
return
|
1753
1757
|
|
1754
|
-
if
|
1758
|
+
if not PY36:
|
1755
1759
|
al.no_scandir = True
|
1756
1760
|
|
1757
1761
|
if not hasattr(os, "sendfile"):
|
copyparty/__version__.py
CHANGED
copyparty/authsrv.py
CHANGED
@@ -848,6 +848,7 @@ class AuthSrv(object):
|
|
848
848
|
self.idp_accs = {} # username->groupnames
|
849
849
|
self.idp_usr_gh = {} # username->group-header-value (cache)
|
850
850
|
|
851
|
+
self.hid_cache = {}
|
851
852
|
self.mutex = threading.Lock()
|
852
853
|
self.reload()
|
853
854
|
|
@@ -1524,7 +1525,7 @@ class AuthSrv(object):
|
|
1524
1525
|
if enshare:
|
1525
1526
|
import sqlite3
|
1526
1527
|
|
1527
|
-
shv = VFS(self.log_func, "", shr, AXS(), {
|
1528
|
+
shv = VFS(self.log_func, "", shr, AXS(), {})
|
1528
1529
|
|
1529
1530
|
db_path = self.args.shr_db
|
1530
1531
|
db = sqlite3.connect(db_path)
|
@@ -1543,8 +1544,8 @@ class AuthSrv(object):
|
|
1543
1544
|
if s_pw:
|
1544
1545
|
# gotta reuse the "account" for all shares with this pw,
|
1545
1546
|
# so do a light scramble as this appears in the web-ui
|
1546
|
-
|
1547
|
-
sun = "s_%s" % (
|
1547
|
+
zb = hashlib.sha512(s_pw.encode("utf-8")).digest()
|
1548
|
+
sun = "s_%s" % (ub64enc(zb)[4:16].decode("ascii"),)
|
1548
1549
|
acct[sun] = s_pw
|
1549
1550
|
else:
|
1550
1551
|
sun = "*"
|
@@ -1649,8 +1650,12 @@ class AuthSrv(object):
|
|
1649
1650
|
promote = []
|
1650
1651
|
demote = []
|
1651
1652
|
for vol in vfs.all_vols.values():
|
1652
|
-
|
1653
|
-
|
1653
|
+
hid = self.hid_cache.get(vol.realpath)
|
1654
|
+
if not hid:
|
1655
|
+
zb = hashlib.sha512(afsenc(vol.realpath)).digest()
|
1656
|
+
hid = base64.b32encode(zb).decode("ascii").lower()
|
1657
|
+
self.hid_cache[vol.realpath] = hid
|
1658
|
+
|
1654
1659
|
vflag = vol.flags.get("hist")
|
1655
1660
|
if vflag == "-":
|
1656
1661
|
pass
|
@@ -2279,7 +2284,7 @@ class AuthSrv(object):
|
|
2279
2284
|
q = "insert into us values (?,?,?)"
|
2280
2285
|
for uname in self.acct:
|
2281
2286
|
if uname not in ases:
|
2282
|
-
sid = ub64enc(os.urandom(blen)).decode("
|
2287
|
+
sid = ub64enc(os.urandom(blen)).decode("ascii")
|
2283
2288
|
cur.execute(q, (uname, sid, int(time.time())))
|
2284
2289
|
ases[uname] = sid
|
2285
2290
|
n.append(uname)
|
copyparty/broker_mp.py
CHANGED
@@ -9,7 +9,7 @@ import queue
|
|
9
9
|
|
10
10
|
from .__init__ import CORES, TYPE_CHECKING
|
11
11
|
from .broker_mpw import MpWorker
|
12
|
-
from .broker_util import ExceptionalQueue, try_exec
|
12
|
+
from .broker_util import ExceptionalQueue, NotExQueue, try_exec
|
13
13
|
from .util import Daemon, mp
|
14
14
|
|
15
15
|
if TYPE_CHECKING:
|
@@ -104,7 +104,7 @@ class BrokerMp(object):
|
|
104
104
|
if retq_id:
|
105
105
|
proc.q_pend.put((retq_id, "retq", rv))
|
106
106
|
|
107
|
-
def ask(self, dest , *args )
|
107
|
+
def ask(self, dest , *args ) :
|
108
108
|
|
109
109
|
# new non-ipc invoking managed service in hub
|
110
110
|
obj = self.hub
|
copyparty/broker_mpw.py
CHANGED
@@ -11,7 +11,7 @@ import queue
|
|
11
11
|
|
12
12
|
from .__init__ import ANYWIN
|
13
13
|
from .authsrv import AuthSrv
|
14
|
-
from .broker_util import BrokerCli, ExceptionalQueue
|
14
|
+
from .broker_util import BrokerCli, ExceptionalQueue, NotExQueue
|
15
15
|
from .httpsrv import HttpSrv
|
16
16
|
from .util import FAKE_MP, Daemon, HMaccas
|
17
17
|
|
@@ -108,7 +108,7 @@ class MpWorker(BrokerCli):
|
|
108
108
|
else:
|
109
109
|
raise Exception("what is " + str(dest))
|
110
110
|
|
111
|
-
def ask(self, dest , *args )
|
111
|
+
def ask(self, dest , *args ) :
|
112
112
|
retq = ExceptionalQueue(1)
|
113
113
|
retq_id = id(retq)
|
114
114
|
with self.retpend_mutex:
|
copyparty/broker_thr.py
CHANGED
@@ -5,7 +5,7 @@ import os
|
|
5
5
|
import threading
|
6
6
|
|
7
7
|
from .__init__ import TYPE_CHECKING
|
8
|
-
from .broker_util import BrokerCli, ExceptionalQueue,
|
8
|
+
from .broker_util import BrokerCli, ExceptionalQueue, NotExQueue
|
9
9
|
from .httpsrv import HttpSrv
|
10
10
|
from .util import HMaccas
|
11
11
|
|
@@ -39,19 +39,14 @@ class BrokerThr(BrokerCli):
|
|
39
39
|
def noop(self) :
|
40
40
|
pass
|
41
41
|
|
42
|
-
def ask(self, dest , *args )
|
42
|
+
def ask(self, dest , *args ) :
|
43
43
|
|
44
44
|
# new ipc invoking managed service in hub
|
45
45
|
obj = self.hub
|
46
46
|
for node in dest.split("."):
|
47
47
|
obj = getattr(obj, node)
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
# pretend we're broker_mp
|
52
|
-
retq = ExceptionalQueue(1)
|
53
|
-
retq.put(rv)
|
54
|
-
return retq
|
49
|
+
return NotExQueue(obj(*args)) # type: ignore
|
55
50
|
|
56
51
|
def say(self, dest , *args ) :
|
57
52
|
if dest == "listen":
|
@@ -67,4 +62,4 @@ class BrokerThr(BrokerCli):
|
|
67
62
|
for node in dest.split("."):
|
68
63
|
obj = getattr(obj, node)
|
69
64
|
|
70
|
-
|
65
|
+
obj(*args) # type: ignore
|
copyparty/broker_util.py
CHANGED
@@ -28,6 +28,18 @@ class ExceptionalQueue(Queue, object):
|
|
28
28
|
return rv
|
29
29
|
|
30
30
|
|
31
|
+
class NotExQueue(object):
|
32
|
+
"""
|
33
|
+
BrokerThr uses this instead of ExceptionalQueue; 7x faster
|
34
|
+
"""
|
35
|
+
|
36
|
+
def __init__(self, rv ) :
|
37
|
+
self.rv = rv
|
38
|
+
|
39
|
+
def get(self) :
|
40
|
+
return self.rv
|
41
|
+
|
42
|
+
|
31
43
|
class BrokerCli(object):
|
32
44
|
"""
|
33
45
|
helps mypy understand httpsrv.broker but still fails a few levels deeper,
|
@@ -43,7 +55,7 @@ class BrokerCli(object):
|
|
43
55
|
def __init__(self) :
|
44
56
|
pass
|
45
57
|
|
46
|
-
def ask(self, dest , *args )
|
58
|
+
def ask(self, dest , *args ) :
|
47
59
|
return ExceptionalQueue(1)
|
48
60
|
|
49
61
|
def say(self, dest , *args ) :
|
copyparty/cfg.py
CHANGED
copyparty/fsutil.py
CHANGED
@@ -113,7 +113,6 @@ class Fstab(object):
|
|
113
113
|
self.srctab = srctab
|
114
114
|
|
115
115
|
def relabel(self, path , nval ) :
|
116
|
-
assert self.tab
|
117
116
|
self.cache = {}
|
118
117
|
if ANYWIN:
|
119
118
|
path = self._winpath(path)
|
@@ -150,7 +149,6 @@ class Fstab(object):
|
|
150
149
|
self.log("failed to build tab:\n{}".format(min_ex()), 3)
|
151
150
|
self.build_fallback()
|
152
151
|
|
153
|
-
assert self.tab
|
154
152
|
ret = self.tab._find(path)[0]
|
155
153
|
if self.trusted or path == ret.vpath:
|
156
154
|
return ret.realpath.split("/")[0]
|
@@ -161,6 +159,5 @@ class Fstab(object):
|
|
161
159
|
if not self.tab:
|
162
160
|
self.build_fallback()
|
163
161
|
|
164
|
-
assert self.tab
|
165
162
|
ret = self.tab._find(path)[0]
|
166
163
|
return ret.realpath
|