copyparty 1.16.17__py3-none-any.whl → 1.16.19__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/svchub.py CHANGED
@@ -3,7 +3,6 @@ from __future__ import print_function, unicode_literals
3
3
 
4
4
  import argparse
5
5
  import errno
6
- import gzip
7
6
  import logging
8
7
  import os
9
8
  import re
@@ -57,7 +56,9 @@ from .util import (
57
56
  ansi_re,
58
57
  build_netmap,
59
58
  expat_ver,
59
+ gzip,
60
60
  load_ipu,
61
+ lock_file,
61
62
  min_ex,
62
63
  mp,
63
64
  odfusion,
@@ -67,6 +68,9 @@ from .util import (
67
68
  ub64enc,
68
69
  )
69
70
 
71
+ if HAVE_SQLITE3:
72
+ import sqlite3
73
+
70
74
  if TYPE_CHECKING:
71
75
  try:
72
76
  from .mdns import MDNS
@@ -78,6 +82,10 @@ if PY2:
78
82
  range = xrange # type: ignore
79
83
 
80
84
 
85
+ VER_SESSION_DB = 1
86
+ VER_SHARES_DB = 2
87
+
88
+
81
89
  class SvcHub(object):
82
90
  """
83
91
  Hosts all services which cannot be parallelized due to reliance on monolithic resources.
@@ -180,8 +188,14 @@ class SvcHub(object):
180
188
 
181
189
  if not args.use_fpool and args.j != 1:
182
190
  args.no_fpool = True
183
- t = "multithreading enabled with -j {}, so disabling fpool -- this can reduce upload performance on some filesystems"
184
- self.log("root", t.format(args.j))
191
+ t = "multithreading enabled with -j {}, so disabling fpool -- this can reduce upload performance on some filesystems, and make some antivirus-softwares "
192
+ c = 0
193
+ if ANYWIN:
194
+ t += "(especially Microsoft Defender) stress your CPU and HDD severely during big uploads"
195
+ c = 3
196
+ else:
197
+ t += "consume more resources (CPU/HDD) than normal"
198
+ self.log("root", t.format(args.j), c)
185
199
 
186
200
  if not args.no_fpool and args.j != 1:
187
201
  t = "WARNING: ignoring --use-fpool because multithreading (-j{}) is enabled"
@@ -400,25 +414,48 @@ class SvcHub(object):
400
414
  self.log("root", t, 3)
401
415
  return
402
416
 
403
- import sqlite3
404
417
 
405
- create = True
418
+ # policy:
419
+ # the sessions-db is whatever, if something looks broken then just nuke it
420
+
406
421
  db_path = self.args.ses_db
407
- self.log("root", "opening sessions-db %s" % (db_path,))
408
- for n in range(2):
422
+ db_lock = db_path + ".lock"
423
+ try:
424
+ create = not os.path.getsize(db_path)
425
+ except:
426
+ create = True
427
+ zs = "creating new" if create else "opening"
428
+ self.log("root", "%s sessions-db %s" % (zs, db_path))
429
+
430
+ for tries in range(2):
431
+ sver = 0
409
432
  try:
410
433
  db = sqlite3.connect(db_path)
411
434
  cur = db.cursor()
412
435
  try:
436
+ zs = "select v from kv where k='sver'"
437
+ sver = cur.execute(zs).fetchall()[0][0]
438
+ if sver > VER_SESSION_DB:
439
+ zs = "this version of copyparty only understands session-db v%d and older; the db is v%d"
440
+ raise Exception(zs % (VER_SESSION_DB, sver))
441
+
413
442
  cur.execute("select count(*) from us").fetchone()
414
- create = False
415
- break
416
443
  except:
417
- pass
444
+ if sver:
445
+ raise
446
+ sver = 1
447
+ self._create_session_db(cur)
448
+ err = self._verify_session_db(cur, sver, db_path)
449
+ if err:
450
+ tries = 99
451
+ self.args.no_ses = True
452
+ self.log("root", err, 3)
453
+ break
454
+
418
455
  except Exception as ex:
419
- if n:
456
+ if tries or sver > VER_SESSION_DB:
420
457
  raise
421
- t = "sessions-db corrupt; deleting and recreating: %r"
458
+ t = "sessions-db is unusable; deleting and recreating: %r"
422
459
  self.log("root", t % (ex,), 3)
423
460
  try:
424
461
  cur.close() # type: ignore
@@ -428,8 +465,13 @@ class SvcHub(object):
428
465
  db.close() # type: ignore
429
466
  except:
430
467
  pass
468
+ try:
469
+ os.unlink(db_lock)
470
+ except:
471
+ pass
431
472
  os.unlink(db_path)
432
473
 
474
+ def _create_session_db(self, cur ) :
433
475
  sch = [
434
476
  r"create table kv (k text, v int)",
435
477
  r"create table us (un text, si text, t0 int)",
@@ -439,15 +481,44 @@ class SvcHub(object):
439
481
  r"create index us_t0 on us(t0)",
440
482
  r"insert into kv values ('sver', 1)",
441
483
  ]
484
+ for cmd in sch:
485
+ cur.execute(cmd)
486
+ self.log("root", "created new sessions-db")
442
487
 
443
- if create:
444
- for cmd in sch:
445
- cur.execute(cmd)
446
- self.log("root", "created new sessions-db")
447
- db.commit()
488
+ def _verify_session_db(self, cur , sver , db_path ) :
489
+ # ensure writable (maybe owned by other user)
490
+ db = cur.connection
491
+
492
+ try:
493
+ zil = cur.execute("select v from kv where k='pid'").fetchall()
494
+ if len(zil) > 1:
495
+ raise Exception()
496
+ owner = zil[0][0]
497
+ except:
498
+ owner = 0
499
+
500
+ if not lock_file(db_path + ".lock"):
501
+ t = "the sessions-db [%s] is already in use by another copyparty instance (pid:%d). This is not supported; please provide another database with --ses-db or give this copyparty-instance its entirely separate config-folder by setting another path in the XDG_CONFIG_HOME env-var. You can also disable this safeguard by setting env-var PRTY_NO_DB_LOCK=1. Will now disable sessions and instead use plaintext passwords in cookies."
502
+ return t % (db_path, owner)
503
+
504
+ vars = (("pid", os.getpid()), ("ts", int(time.time() * 1000)))
505
+ if owner:
506
+ # wear-estimate: 2 cells; offsets 0x10, 0x50, 0x19720
507
+ for k, v in vars:
508
+ cur.execute("update kv set v=? where k=?", (v, k))
509
+ else:
510
+ # wear-estimate: 3~4 cells; offsets 0x10, 0x50, 0x19180, 0x19710, 0x36000, 0x360b0, 0x36b90
511
+ for k, v in vars:
512
+ cur.execute("insert into kv values(?, ?)", (k, v))
448
513
 
514
+ if sver < VER_SESSION_DB:
515
+ cur.execute("delete from kv where k='sver'")
516
+ cur.execute("insert into kv values('sver',?)", (VER_SESSION_DB,))
517
+
518
+ db.commit()
449
519
  cur.close()
450
520
  db.close()
521
+ return ""
451
522
 
452
523
  def setup_share_db(self) :
453
524
  al = self.args
@@ -456,7 +527,6 @@ class SvcHub(object):
456
527
  al.shr = ""
457
528
  return
458
529
 
459
- import sqlite3
460
530
 
461
531
  al.shr = al.shr.strip("/")
462
532
  if "/" in al.shr or not al.shr:
@@ -467,34 +537,48 @@ class SvcHub(object):
467
537
  al.shr = "/%s/" % (al.shr,)
468
538
  al.shr1 = al.shr[1:]
469
539
 
470
- create = True
471
- modified = False
540
+ # policy:
541
+ # the shares-db is important, so panic if something is wrong
542
+
472
543
  db_path = self.args.shr_db
473
- self.log("root", "opening shares-db %s" % (db_path,))
474
- for n in range(2):
475
- try:
476
- db = sqlite3.connect(db_path)
477
- cur = db.cursor()
478
- try:
479
- cur.execute("select count(*) from sh").fetchone()
480
- create = False
481
- break
482
- except:
483
- pass
484
- except Exception as ex:
485
- if n:
486
- raise
487
- t = "shares-db corrupt; deleting and recreating: %r"
488
- self.log("root", t % (ex,), 3)
489
- try:
490
- cur.close() # type: ignore
491
- except:
492
- pass
493
- try:
494
- db.close() # type: ignore
495
- except:
496
- pass
497
- os.unlink(db_path)
544
+ db_lock = db_path + ".lock"
545
+ try:
546
+ create = not os.path.getsize(db_path)
547
+ except:
548
+ create = True
549
+ zs = "creating new" if create else "opening"
550
+ self.log("root", "%s shares-db %s" % (zs, db_path))
551
+
552
+ sver = 0
553
+ try:
554
+ db = sqlite3.connect(db_path)
555
+ cur = db.cursor()
556
+ if not create:
557
+ zs = "select v from kv where k='sver'"
558
+ sver = cur.execute(zs).fetchall()[0][0]
559
+ if sver > VER_SHARES_DB:
560
+ zs = "this version of copyparty only understands shares-db v%d and older; the db is v%d"
561
+ raise Exception(zs % (VER_SHARES_DB, sver))
562
+
563
+ cur.execute("select count(*) from sh").fetchone()
564
+ except Exception as ex:
565
+ t = "could not open shares-db; will now panic...\nthe following database must be repaired or deleted before you can launch copyparty:\n%s\n\nERROR: %s\n\nadditional details:\n%s\n"
566
+ self.log("root", t % (db_path, ex, min_ex()), 1)
567
+ raise
568
+
569
+ try:
570
+ zil = cur.execute("select v from kv where k='pid'").fetchall()
571
+ if len(zil) > 1:
572
+ raise Exception()
573
+ owner = zil[0][0]
574
+ except:
575
+ owner = 0
576
+
577
+ if not lock_file(db_lock):
578
+ t = "the shares-db [%s] is already in use by another copyparty instance (pid:%d). This is not supported; please provide another database with --shr-db or give this copyparty-instance its entirely separate config-folder by setting another path in the XDG_CONFIG_HOME env-var. You can also disable this safeguard by setting env-var PRTY_NO_DB_LOCK=1. Will now panic."
579
+ t = t % (db_path, owner)
580
+ self.log("root", t, 1)
581
+ raise Exception(t)
498
582
 
499
583
  sch1 = [
500
584
  r"create table kv (k text, v int)",
@@ -506,32 +590,35 @@ class SvcHub(object):
506
590
  r"create index sf_k on sf(k)",
507
591
  r"create index sh_k on sh(k)",
508
592
  r"create index sh_t1 on sh(t1)",
593
+ r"insert into kv values ('sver', 2)",
509
594
  ]
510
595
 
511
- if create:
512
- dver = 2
513
- modified = True
596
+ if not sver:
597
+ sver = VER_SHARES_DB
514
598
  for cmd in sch1 + sch2:
515
599
  cur.execute(cmd)
516
600
  self.log("root", "created new shares-db")
517
- else:
518
- (dver,) = cur.execute("select v from kv where k = 'sver'").fetchall()[0]
519
601
 
520
- if dver == 1:
521
- modified = True
602
+ if sver == 1:
522
603
  for cmd in sch2:
523
604
  cur.execute(cmd)
524
605
  cur.execute("update sh set st = 0")
525
606
  self.log("root", "shares-db schema upgrade ok")
526
607
 
527
- if modified:
528
- for cmd in [
529
- r"delete from kv where k = 'sver'",
530
- r"insert into kv values ('sver', %d)" % (2,),
531
- ]:
532
- cur.execute(cmd)
533
- db.commit()
608
+ if sver < VER_SHARES_DB:
609
+ cur.execute("delete from kv where k='sver'")
610
+ cur.execute("insert into kv values('sver',?)", (VER_SHARES_DB,))
611
+
612
+ vars = (("pid", os.getpid()), ("ts", int(time.time() * 1000)))
613
+ if owner:
614
+ # wear-estimate: same as sessions-db
615
+ for k, v in vars:
616
+ cur.execute("update kv set v=? where k=?", (v, k))
617
+ else:
618
+ for k, v in vars:
619
+ cur.execute("insert into kv values(?, ?)", (k, v))
534
620
 
621
+ db.commit()
535
622
  cur.close()
536
623
  db.close()
537
624
 
@@ -669,8 +756,8 @@ class SvcHub(object):
669
756
  t += ", "
670
757
  t += "\033[0mNG: \033[35m" + sng
671
758
 
672
- t += "\033[0m, see --deps"
673
- self.log("dependencies", t, 6)
759
+ t += "\033[0m, see --deps (this is fine btw)"
760
+ self.log("optional-dependencies", t, 6)
674
761
 
675
762
  def _check_env(self) :
676
763
  try:
@@ -753,13 +840,14 @@ class SvcHub(object):
753
840
  vl = [os.path.expandvars(os.path.expanduser(x)) for x in vl]
754
841
  setattr(al, k, vl)
755
842
 
756
- for k in "lo hist ssl_log".split(" "):
843
+ for k in "lo hist dbpath ssl_log".split(" "):
757
844
  vs = getattr(al, k)
758
845
  if vs:
759
846
  vs = os.path.expandvars(os.path.expanduser(vs))
760
847
  setattr(al, k, vs)
761
848
 
762
- for k in "dav_ua1 sus_urls nonsus_urls".split(" "):
849
+ zs = "dav_ua1 sus_urls nonsus_urls ua_nodoc ua_nozip"
850
+ for k in zs.split(" "):
763
851
  vs = getattr(al, k)
764
852
  if not vs or vs == "no":
765
853
  setattr(al, k, None)
copyparty/szip.py CHANGED
@@ -4,12 +4,11 @@ from __future__ import print_function, unicode_literals
4
4
  import calendar
5
5
  import stat
6
6
  import time
7
- import zlib
8
7
 
9
8
  from .authsrv import AuthSrv
10
9
  from .bos import bos
11
10
  from .sutil import StreamArc, errdesc
12
- from .util import min_ex, sanitize_fn, spack, sunpack, yieldfile
11
+ from .util import min_ex, sanitize_fn, spack, sunpack, yieldfile, zlib
13
12
 
14
13
  def dostime2unix(buf ) :
15
14
  t, d = sunpack(b"<HH", buf)
copyparty/tcpsrv.py CHANGED
@@ -148,9 +148,15 @@ class TcpSrv(object):
148
148
  if just_ll or self.args.ll:
149
149
  ll_ok.add(ip.split("/")[0])
150
150
 
151
+ listening_on = []
152
+ for ip, ports in sorted(ok.items()):
153
+ for port in sorted(ports):
154
+ listening_on.append("%s %s" % (ip, port))
155
+
151
156
  qr1 = {}
152
157
  qr2 = {}
153
158
  msgs = []
159
+ accessible_on = []
154
160
  title_tab = {}
155
161
  title_vars = [x[1:] for x in self.args.wintitle.split(" ") if x.startswith("$")]
156
162
  t = "available @ {}://{}:{}/ (\033[33m{}\033[0m)"
@@ -166,6 +172,10 @@ class TcpSrv(object):
166
172
  ):
167
173
  continue
168
174
 
175
+ zs = "%s %s" % (ip, port)
176
+ if zs not in accessible_on:
177
+ accessible_on.append(zs)
178
+
169
179
  proto = " http"
170
180
  if self.args.http_only:
171
181
  pass
@@ -216,6 +226,14 @@ class TcpSrv(object):
216
226
  else:
217
227
  print("\n", end="")
218
228
 
229
+ for fn, ls in (
230
+ (self.args.wr_h_eps, listening_on),
231
+ (self.args.wr_h_aon, accessible_on),
232
+ ):
233
+ if fn:
234
+ with open(fn, "wb") as f:
235
+ f.write(("\n".join(ls)).encode("utf-8"))
236
+
219
237
  if self.args.qr or self.args.qrs:
220
238
  self.qr = self._qr(qr1, qr2)
221
239
 
copyparty/tftpd.py CHANGED
@@ -36,7 +36,19 @@ from partftpy.TftpShared import TftpException
36
36
  from .__init__ import EXE, PY2, TYPE_CHECKING
37
37
  from .authsrv import VFS
38
38
  from .bos import bos
39
- from .util import UTC, BytesIO, Daemon, ODict, exclude_dotfiles, min_ex, runhook, undot
39
+ from .util import (
40
+ FN_EMB,
41
+ UTC,
42
+ BytesIO,
43
+ Daemon,
44
+ ODict,
45
+ exclude_dotfiles,
46
+ min_ex,
47
+ runhook,
48
+ undot,
49
+ vjoin,
50
+ vsplit,
51
+ )
40
52
 
41
53
  if TYPE_CHECKING:
42
54
  from .svchub import SvcHub
@@ -241,16 +253,25 @@ class Tftpd(object):
241
253
  for srv in srvs:
242
254
  srv.stop()
243
255
 
244
- def _v2a(self, caller , vpath , perms , *a ) :
256
+ def _v2a(
257
+ self, caller , vpath , perms , *a
258
+ ) :
245
259
  vpath = vpath.replace("\\", "/").lstrip("/")
246
260
  if not perms:
247
261
  perms = [True, True]
248
262
 
249
263
  debug('%s("%s", %s) %s\033[K\033[0m', caller, vpath, str(a), perms)
250
264
  vfs, rem = self.asrv.vfs.get(vpath, "*", *perms)
265
+ if perms[1] and "*" not in vfs.axs.uread and "wo_up_readme" not in vfs.flags:
266
+ zs, fn = vsplit(vpath)
267
+ if fn.lower() in FN_EMB:
268
+ vpath = vjoin(zs, "_wo_" + fn)
269
+ vfs, rem = self.asrv.vfs.get(vpath, "*", *perms)
270
+
251
271
  if not vfs.realpath:
252
272
  raise Exception("unmapped vfs")
253
- return vfs, vfs.canonical(rem)
273
+
274
+ return vfs, vpath, vfs.canonical(rem)
254
275
 
255
276
  def _ls(self, vpath , raddress , rport , force=False) :
256
277
  # generate file listing if vpath is dir.txt and return as file object
@@ -328,7 +349,7 @@ class Tftpd(object):
328
349
  else:
329
350
  raise Exception("bad mode %s" % (mode,))
330
351
 
331
- vfs, ap = self._v2a("open", vpath, [rd, wr])
352
+ vfs, vpath, ap = self._v2a("open", vpath, [rd, wr])
332
353
  if wr:
333
354
  if "*" not in vfs.axs.uwrite:
334
355
  yeet("blocked write; folder not world-writable: /%s" % (vpath,))
@@ -365,7 +386,7 @@ class Tftpd(object):
365
386
  return open(ap, mode, *a, **ka)
366
387
 
367
388
  def _mkdir(self, vpath , *a) :
368
- vfs, ap = self._v2a("mkdir", vpath, [])
389
+ vfs, _, ap = self._v2a("mkdir", vpath, [False, True])
369
390
  if "*" not in vfs.axs.uwrite:
370
391
  yeet("blocked mkdir; folder not world-writable: /%s" % (vpath,))
371
392
 
@@ -373,7 +394,7 @@ class Tftpd(object):
373
394
 
374
395
  def _unlink(self, vpath ) :
375
396
  # return bos.unlink(self._v2a("stat", vpath, *a)[1])
376
- vfs, ap = self._v2a("delete", vpath, [True, False, False, True])
397
+ vfs, _, ap = self._v2a("delete", vpath, [True, False, False, True])
377
398
 
378
399
  try:
379
400
  inf = bos.stat(ap)
@@ -397,7 +418,7 @@ class Tftpd(object):
397
418
 
398
419
  def _p_exists(self, vpath ) :
399
420
  try:
400
- ap = self._v2a("p.exists", vpath, [False, False])[1]
421
+ ap = self._v2a("p.exists", vpath, [False, False])[2]
401
422
  bos.stat(ap)
402
423
  return True
403
424
  except:
@@ -405,7 +426,7 @@ class Tftpd(object):
405
426
 
406
427
  def _p_isdir(self, vpath ) :
407
428
  try:
408
- st = bos.stat(self._v2a("p.isdir", vpath, [False, False])[1])
429
+ st = bos.stat(self._v2a("p.isdir", vpath, [False, False])[2])
409
430
  ret = stat.S_ISDIR(st.st_mode)
410
431
  return ret
411
432
  except:
copyparty/th_cli.py CHANGED
@@ -1,18 +1,23 @@
1
1
  # coding: utf-8
2
2
  from __future__ import print_function, unicode_literals
3
3
 
4
+ import errno
4
5
  import os
6
+ import stat
5
7
 
6
8
  from .__init__ import TYPE_CHECKING
7
9
  from .authsrv import VFS
8
10
  from .bos import bos
9
11
  from .th_srv import EXTS_AC, HAVE_WEBP, thumb_path
10
- from .util import Cooldown
12
+ from .util import Cooldown, Pebkac
11
13
 
12
14
  if TYPE_CHECKING:
13
15
  from .httpsrv import HttpSrv
14
16
 
15
17
 
18
+ IOERROR = "reading the file was denied by the server os; either due to filesystem permissions, selinux, apparmor, or similar:\n%r"
19
+
20
+
16
21
  class ThumbCli(object):
17
22
  def __init__(self, hsrv ) :
18
23
  self.broker = hsrv.broker
@@ -121,7 +126,7 @@ class ThumbCli(object):
121
126
 
122
127
  tpath = thumb_path(histpath, rem, mtime, fmt, self.fmt_ffa)
123
128
  tpaths = [tpath]
124
- if fmt == "w":
129
+ if fmt[:1] == "w":
125
130
  # also check for jpg (maybe webp is unavailable)
126
131
  tpaths.append(tpath.rsplit(".", 1)[0] + ".jpg")
127
132
 
@@ -154,8 +159,22 @@ class ThumbCli(object):
154
159
  if abort:
155
160
  return None
156
161
 
157
- if not bos.path.getsize(os.path.join(ptop, rem)):
158
- return None
162
+ ap = os.path.join(ptop, rem)
163
+ try:
164
+ st = bos.stat(ap)
165
+ if not st.st_size or not stat.S_ISREG(st.st_mode):
166
+ return None
167
+
168
+ with open(ap, "rb", 4) as f:
169
+ if not f.read(4):
170
+ raise Exception()
171
+ except OSError as ex:
172
+ if ex.errno == errno.ENOENT:
173
+ raise Pebkac(404)
174
+ else:
175
+ raise Pebkac(500, IOERROR % (ex,))
176
+ except Exception as ex:
177
+ raise Pebkac(500, IOERROR % (ex,))
159
178
 
160
179
  x = self.broker.ask("thumbsrv.get", ptop, rem, mtime, fmt)
161
180
  return x.get() # type: ignore
copyparty/th_srv.py CHANGED
@@ -4,6 +4,7 @@ from __future__ import print_function, unicode_literals
4
4
  import hashlib
5
5
  import logging
6
6
  import os
7
+ import re
7
8
  import shutil
8
9
  import subprocess as sp
9
10
  import threading
@@ -46,6 +47,9 @@ HAVE_WEBP = False
46
47
  EXTS_TH = set(["jpg", "webp", "png"])
47
48
  EXTS_AC = set(["opus", "owa", "caf", "mp3"])
48
49
 
50
+ PTN_TS = re.compile("^-?[0-9a-f]{8,10}$")
51
+
52
+
49
53
  try:
50
54
  if os.environ.get("PRTY_NO_PIL"):
51
55
  raise Exception()
@@ -382,8 +386,12 @@ class ThumbSrv(object):
382
386
  self.log(msg, c)
383
387
  if getattr(ex, "returncode", 0) != 321:
384
388
  if fun == funs[-1]:
385
- with open(ttpath, "wb") as _:
386
- pass
389
+ try:
390
+ with open(ttpath, "wb") as _:
391
+ pass
392
+ except Exception as ex:
393
+ t = "failed to create the file [%s]: %r"
394
+ self.log(t % (ttpath, ex), 3)
387
395
  else:
388
396
  # ffmpeg may spawn empty files on windows
389
397
  try:
@@ -396,7 +404,10 @@ class ThumbSrv(object):
396
404
 
397
405
  try:
398
406
  wrename(self.log, ttpath, tpath, vn.flags)
399
- except:
407
+ except Exception as ex:
408
+ if not os.path.exists(tpath):
409
+ t = "failed to move [%s] to [%s]: %r"
410
+ self.log(t % (ttpath, tpath, ex), 3)
400
411
  pass
401
412
 
402
413
  with self.mutex:
@@ -987,6 +998,8 @@ class ThumbSrv(object):
987
998
  # thumb file
988
999
  try:
989
1000
  b64, ts, ext = f.split(".")
1001
+ if len(ts) > 8 and PTN_TS.match(ts):
1002
+ ts = "yeahokay"
990
1003
  if len(b64) != 24 or len(ts) != 8 or ext not in exts:
991
1004
  raise Exception()
992
1005
  except:
copyparty/u2idx.py CHANGED
@@ -128,9 +128,9 @@ class U2idx(object):
128
128
 
129
129
 
130
130
  ptop = vn.realpath
131
- histpath = self.asrv.vfs.histtab.get(ptop)
131
+ histpath = self.asrv.vfs.dbpaths.get(ptop)
132
132
  if not histpath:
133
- self.log("no histpath for %r" % (ptop,))
133
+ self.log("no dbpath for %r" % (ptop,))
134
134
  return None
135
135
 
136
136
  db_path = os.path.join(histpath, "up2k.db")