copyparty 1.15.1__py3-none-any.whl → 1.15.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/__init__.py CHANGED
@@ -16,6 +16,7 @@ except:
16
16
  TYPE_CHECKING = False
17
17
 
18
18
  PY2 = sys.version_info < (3,)
19
+ PY36 = sys.version_info > (3, 6)
19
20
  if not PY2:
20
21
  unicode = str
21
22
  else:
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
- print("WARNING: " + ". ".join(errs))
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
- lprint("using hostname from {}\n".format(fp))
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 = base64.b64encode(os.urandom(18))
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 = base64.b64encode(os.urandom(30))
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 = base64.b64encode(os.urandom(18))
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 sys.version_info < (3, 6):
1758
+ if not PY36:
1755
1759
  al.no_scandir = True
1756
1760
 
1757
1761
  if not hasattr(os, "sendfile"):
copyparty/__version__.py CHANGED
@@ -1,8 +1,8 @@
1
1
  # coding: utf-8
2
2
 
3
- VERSION = (1, 15, 1)
3
+ VERSION = (1, 15, 2)
4
4
  CODENAME = "fill the drives"
5
- BUILD_DT = (2024, 9, 9)
5
+ BUILD_DT = (2024, 9, 16)
6
6
 
7
7
  S_VERSION = ".".join(map(str, VERSION))
8
8
  S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
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(), {"d2d": True})
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
- zs = ub64enc(hashlib.sha512(s_pw.encode("utf-8")).digest())[4:16]
1547
- sun = "s_%s" % (zs.decode("utf-8"),)
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
- zb = hashlib.sha512(afsenc(vol.realpath)).digest()
1653
- hid = base64.b32encode(zb).decode("ascii").lower()
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("utf-8")
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, try_exec
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
- rv = try_exec(True, obj, *args)
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
- try_exec(False, obj, *args)
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
@@ -13,6 +13,7 @@ def vf_bmap() :
13
13
  "dav_rt": "davrt",
14
14
  "ed": "dots",
15
15
  "hardlink_only": "hardlinkonly",
16
+ "no_dirsz": "nodirsz",
16
17
  "no_dupe": "nodupe",
17
18
  "no_forget": "noforget",
18
19
  "no_pipe": "nopipe",
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