copyparty 1.16.1__py3-none-any.whl → 1.16.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/res/COPYING.txt CHANGED
@@ -75,6 +75,9 @@ Copyright (c) 2022 Fonticons, Inc.
75
75
  License: SIL OFL 1.1
76
76
 
77
77
 
78
+
79
+
80
+
78
81
  --- MIT License ---
79
82
 
80
83
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
@@ -83,14 +86,6 @@ The above copyright notice and this permission notice shall be included in all c
83
86
 
84
87
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
85
88
 
86
-
87
- --- ISC License ---
88
-
89
- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
90
-
91
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
92
-
93
-
94
89
  --- BSD 2-Clause License ---
95
90
 
96
91
  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
@@ -101,7 +96,6 @@ Redistribution and use in source and binary forms, with or without modification,
101
96
 
102
97
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
103
98
 
104
-
105
99
  --- BSD 3-Clause License ---
106
100
 
107
101
  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
@@ -114,46 +108,45 @@ Redistribution and use in source and binary forms, with or without modification,
114
108
 
115
109
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
116
110
 
117
-
118
111
  --- SIL Open Font License v1.1 ---
119
112
 
120
- PREAMBLE
113
+ PREAMBLE
121
114
 
122
- The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others.
115
+ The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others.
123
116
 
124
- The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives.
117
+ The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives.
125
118
 
126
- DEFINITIONS
119
+ DEFINITIONS
127
120
 
128
- "Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation.
121
+ "Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation.
129
122
 
130
- "Reserved Font Name" refers to any names specified as such after the copyright statement(s).
123
+ "Reserved Font Name" refers to any names specified as such after the copyright statement(s).
131
124
 
132
- "Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s).
125
+ "Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s).
133
126
 
134
- "Modified Version" refers to any derivative made by adding to, deleting, or substituting - in part or in whole - any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment.
127
+ "Modified Version" refers to any derivative made by adding to, deleting, or substituting - in part or in whole - any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment.
135
128
 
136
- "Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software.
129
+ "Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software.
137
130
 
138
- PERMISSION & CONDITIONS
131
+ PERMISSION & CONDITIONS
139
132
 
140
- Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions:
133
+ Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions:
141
134
 
142
- 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself.
135
+ 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself.
143
136
 
144
- 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user.
137
+ 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user.
145
138
 
146
- 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users.
139
+ 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users.
147
140
 
148
- 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission.
141
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission.
149
142
 
150
- 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software.
143
+ 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software.
151
144
 
152
- TERMINATION
145
+ TERMINATION
153
146
 
154
- This license becomes null and void if any of the above conditions are not met.
147
+ This license becomes null and void if any of the above conditions are not met.
155
148
 
156
- DISCLAIMER
149
+ DISCLAIMER
157
150
 
158
- THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
151
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
159
152
 
@@ -8,7 +8,7 @@ from itertools import chain
8
8
  from .bimap import Bimap, BimapError
9
9
  from .bit import get_bits, set_bits
10
10
  from .buffer import BufferError
11
- from .label import DNSBuffer, DNSLabel
11
+ from .label import DNSBuffer, DNSLabel, set_avahi_379
12
12
  from .ranges import IP4, IP6, H, I, check_bytes
13
13
 
14
14
 
@@ -426,7 +426,7 @@ class RR(object):
426
426
  if rdlength:
427
427
  rdata = RDMAP.get(QTYPE.get(rtype), RD).parse(buffer, rdlength)
428
428
  else:
429
- rdata = ""
429
+ rdata = RD(b"a")
430
430
  return cls(rname, rtype, rclass, ttl, rdata)
431
431
  except (BufferError, BimapError) as e:
432
432
  raise DNSError("Error unpacking RR [offset=%d]: %s" % (buffer.offset, e))
@@ -11,6 +11,23 @@ LDH = set(range(33, 127))
11
11
  ESCAPE = re.compile(r"\\([0-9][0-9][0-9])")
12
12
 
13
13
 
14
+ avahi_379 = 0
15
+
16
+
17
+ def set_avahi_379():
18
+ global avahi_379
19
+ avahi_379 = 1
20
+
21
+
22
+ def log_avahi_379(args):
23
+ global avahi_379
24
+ if avahi_379 == 2:
25
+ return
26
+ avahi_379 = 2
27
+ t = "Invalid pointer in DNSLabel [offset=%d,pointer=%d,length=%d];\n\033[35m NOTE: this is probably avahi-bug #379, packet corruption in Avahi's mDNS-reflection feature. Copyparty has a workaround and is OK, but other devices need either --zm4 or --zm6"
28
+ raise BufferError(t % args)
29
+
30
+
14
31
  class DNSLabelError(Exception):
15
32
  pass
16
33
 
@@ -96,8 +113,11 @@ class DNSBuffer(Buffer):
96
113
  )
97
114
  if pointer < self.offset:
98
115
  self.offset = pointer
116
+ elif avahi_379:
117
+ log_avahi_379((self.offset, pointer, len(self.data)))
118
+ label.extend(b"a")
119
+ break
99
120
  else:
100
-
101
121
  raise BufferError(
102
122
  "Invalid pointer in DNSLabel [offset=%d,pointer=%d,length=%d]"
103
123
  % (self.offset, pointer, len(self.data))
copyparty/svchub.py CHANGED
@@ -783,7 +783,7 @@ class SvcHub(object):
783
783
  al.exp_md = odfusion(exp, al.exp_md.replace(" ", ","))
784
784
  al.exp_lg = odfusion(exp, al.exp_lg.replace(" ", ","))
785
785
 
786
- for k in ["no_hash", "no_idx", "og_ua"]:
786
+ for k in ["no_hash", "no_idx", "og_ua", "srch_excl"]:
787
787
  ptn = getattr(self.args, k)
788
788
  if ptn:
789
789
  setattr(self.args, k, re.compile(ptn))
copyparty/u2idx.py CHANGED
@@ -66,6 +66,9 @@ class U2idx(object):
66
66
  self.log_func("u2idx", msg, c)
67
67
 
68
68
  def shutdown(self) :
69
+ if not HAVE_SQLITE3:
70
+ return
71
+
69
72
  for cur in self.cur.values():
70
73
  db = cur.connection
71
74
  try:
@@ -76,6 +79,12 @@ class U2idx(object):
76
79
  cur.close()
77
80
  db.close()
78
81
 
82
+ for cur in (self.mem_cur, self.sh_cur):
83
+ if cur:
84
+ db = cur.connection
85
+ cur.close()
86
+ db.close()
87
+
79
88
  def fsearch(
80
89
  self, uname , vols , body
81
90
  ) :
@@ -309,7 +318,8 @@ class U2idx(object):
309
318
  sort ,
310
319
  lim ,
311
320
  ) :
312
- if self.args.srch_dbg:
321
+ dbg = self.args.srch_dbg
322
+ if dbg:
313
323
  t = "searching across all %s volumes in which the user has 'r' (full read access):\n %s"
314
324
  zs = "\n ".join(["/%s = %s" % (x.vpath, x.realpath) for x in vols])
315
325
  self.log(t % (len(vols), zs), 5)
@@ -352,14 +362,14 @@ class U2idx(object):
352
362
  if not cur:
353
363
  continue
354
364
 
355
- excl = []
356
- for vp2 in self.asrv.vfs.all_vols.keys():
357
- if vp2.startswith((vtop + "/").lstrip("/")) and vtop != vp2:
358
- excl.append(vp2[len(vtop) :].lstrip("/"))
365
+ dots = flags.get("dotsrch") and uname in vol.axs.udot
366
+ zs = "srch_re_dots" if dots else "srch_re_nodot"
367
+ rex = flags.get(zs) # type: ignore
359
368
 
360
- if self.args.srch_dbg:
361
- t = "searching in volume /%s (%s), excludelist %s"
362
- self.log(t % (vtop, ptop, excl), 5)
369
+ if dbg:
370
+ t = "searching in volume /%s (%s), excluding %s"
371
+ self.log(t % (vtop, ptop, rex.pattern), 5)
372
+ rex_cfg = flags.get("srch_excl")
363
373
 
364
374
  self.active_cur = cur
365
375
 
@@ -372,7 +382,6 @@ class U2idx(object):
372
382
 
373
383
  sret = []
374
384
  fk = flags.get("fk")
375
- dots = flags.get("dotsrch") and uname in vol.axs.udot
376
385
  fk_alg = 2 if "fka" in flags else 1
377
386
  c = cur.execute(uq, tuple(vuv))
378
387
  for hit in c:
@@ -381,20 +390,23 @@ class U2idx(object):
381
390
  if rd.startswith("//") or fn.startswith("//"):
382
391
  rd, fn = s3dec(rd, fn)
383
392
 
384
- if rd in excl or any([x for x in excl if rd.startswith(x + "/")]):
385
- if self.args.srch_dbg:
386
- zs = vjoin(vjoin(vtop, rd), fn)
387
- t = "database inconsistency in volume '/%s'; ignoring: %s"
388
- self.log(t % (vtop, zs), 1)
389
- continue
393
+ vp = vjoin(vjoin(vtop, rd), fn)
390
394
 
391
- rp = quotep("/".join([x for x in [vtop, rd, fn] if x]))
392
- if not dots and "/." in ("/" + rp):
395
+ if vp in seen_rps:
393
396
  continue
394
397
 
395
- if rp in seen_rps:
398
+ if rex.search(vp):
399
+ if dbg:
400
+ if rex_cfg and rex_cfg.search(vp): # type: ignore
401
+ self.log("filtered by srch_excl: %s" % (vp,), 6)
402
+ elif not dots and "/." in ("/" + vp):
403
+ pass
404
+ else:
405
+ t = "database inconsistency in volume '/%s'; ignoring: %s"
406
+ self.log(t % (vtop, vp), 1)
396
407
  continue
397
408
 
409
+ rp = quotep(vp)
398
410
  if not fk:
399
411
  suf = ""
400
412
  else:
@@ -416,7 +428,7 @@ class U2idx(object):
416
428
  if lim < 0:
417
429
  break
418
430
 
419
- if self.args.srch_dbg:
431
+ if dbg:
420
432
  t = "in volume '/%s': hit: %s"
421
433
  self.log(t % (vtop, rp), 5)
422
434
 
@@ -446,7 +458,7 @@ class U2idx(object):
446
458
  ret.extend(sret)
447
459
  # print("[{}] {}".format(ptop, sret))
448
460
 
449
- if self.args.srch_dbg:
461
+ if dbg:
450
462
  t = "in volume '/%s': got %d hits, %d total so far"
451
463
  self.log(t % (vtop, len(sret), len(ret)), 5)
452
464
 
copyparty/up2k.py CHANGED
@@ -85,16 +85,23 @@ if TYPE_CHECKING:
85
85
  zsg = "avif,avifs,bmp,gif,heic,heics,heif,heifs,ico,j2p,j2k,jp2,jpeg,jpg,jpx,png,tga,tif,tiff,webp"
86
86
  CV_EXTS = set(zsg.split(","))
87
87
 
88
+ zsg = "nohash noidx xdev xvol"
89
+ VF_AFFECTS_INDEXING = set(zsg.split(" "))
90
+
88
91
 
89
92
  SBUSY = "cannot receive uploads right now;\nserver busy with %s.\nPlease wait; the client will retry..."
90
93
 
91
94
  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)"
92
95
 
93
96
 
97
+ NULLSTAT = os.stat_result((0, -1, -1, 0, 0, 0, 0, 0, 0, 0))
98
+
99
+
94
100
  class Dbw(object):
95
- def __init__(self, c , n , t ) :
101
+ def __init__(self, c , n , nf , t ) :
96
102
  self.c = c
97
103
  self.n = n
104
+ self.nf = nf
98
105
  self.t = t
99
106
 
100
107
 
@@ -1067,7 +1074,8 @@ class Up2k(object):
1067
1074
  ft = "\033[0;32m{}{:.0}"
1068
1075
  ff = "\033[0;35m{}{:.0}"
1069
1076
  fv = "\033[0;36m{}:\033[90m{}"
1070
- fx = set(("html_head", "rm_re_t", "rm_re_r", "mv_re_t", "mv_re_r"))
1077
+ zs = "html_head mv_re_r mv_re_t rm_re_r rm_re_t srch_re_dots srch_re_nodot"
1078
+ fx = set(zs.split())
1071
1079
  fd = vf_bmap()
1072
1080
  fd.update(vf_cmap())
1073
1081
  fd.update(vf_vmap())
@@ -1224,10 +1232,17 @@ class Up2k(object):
1224
1232
  def _verify_db_cache(self, cur , vpath ) :
1225
1233
  # check if list of intersecting volumes changed since last use; drop caches if so
1226
1234
  prefix = (vpath + "/").lstrip("/")
1227
- zsl = [x for x in self.vfs.all_vols if x.startswith(prefix)]
1228
- zsl = [x[len(prefix) :] for x in zsl]
1229
- zsl.sort()
1230
- zb = hashlib.sha1("\n".join(zsl).encode("utf-8", "replace")).digest()
1235
+ vps = [x for x in self.vfs.all_vols if x.startswith(prefix)]
1236
+ vps.sort()
1237
+ seed = [x[len(prefix) :] for x in vps]
1238
+
1239
+ # also consider volflags which affect indexing
1240
+ for vp in vps:
1241
+ vf = self.vfs.all_vols[vp].flags
1242
+ vf = {k: v for k, v in vf.items() if k in VF_AFFECTS_INDEXING}
1243
+ seed.append(str(sorted(vf.items())))
1244
+
1245
+ zb = hashlib.sha1("\n".join(seed).encode("utf-8", "replace")).digest()
1231
1246
  vcfg = ub64enc(zb[:18]).decode("ascii")
1232
1247
 
1233
1248
  c = cur.execute("select v from kv where k = 'volcfg'")
@@ -1259,7 +1274,7 @@ class Up2k(object):
1259
1274
 
1260
1275
  cur, db_path = reg
1261
1276
 
1262
- db = Dbw(cur, 0, time.time())
1277
+ db = Dbw(cur, 0, 0, time.time())
1263
1278
  self.pp.n = next(db.c.execute("select count(w) from up"))[0]
1264
1279
 
1265
1280
  excl = [
@@ -1311,7 +1326,7 @@ class Up2k(object):
1311
1326
  self.hub.log_stacks()
1312
1327
 
1313
1328
  if db.n:
1314
- self.log("commit {} new files".format(db.n))
1329
+ self.log("commit %d new files; %d updates" % (db.nf, db.n))
1315
1330
 
1316
1331
  if self.args.no_dhash:
1317
1332
  if db.c.execute("select d from dh").fetchone():
@@ -1612,12 +1627,13 @@ class Up2k(object):
1612
1627
  # skip upload hooks by not providing vflags
1613
1628
  self.db_add(db.c, {}, rd, fn, lmod, sz, "", "", wark, wark, "", "", ip, at)
1614
1629
  db.n += 1
1630
+ db.nf += 1
1615
1631
  tfa += 1
1616
1632
  td = time.time() - db.t
1617
1633
  if db.n >= 4096 or td >= 60:
1618
- self.log("commit {} new files".format(db.n))
1634
+ self.log("commit %d new files; %d updates" % (db.nf, db.n))
1619
1635
  db.c.connection.commit()
1620
- db.n = 0
1636
+ db.n = db.nf = 0
1621
1637
  db.t = time.time()
1622
1638
 
1623
1639
  if not self.args.no_dhash:
@@ -1630,7 +1646,7 @@ class Up2k(object):
1630
1646
  # drop shadowed folders
1631
1647
  for sh_rd in unreg:
1632
1648
  n = 0
1633
- q = "select count(w) from up where (rd=? or rd like ?||'/%') and +at == 0"
1649
+ q = "select count(w) from up where (rd=? or rd like ?||'/%')"
1634
1650
  for sh_erd in [sh_rd, "//" + w8b64enc(sh_rd)]:
1635
1651
  try:
1636
1652
  erd_erd = (sh_erd, sh_erd)
@@ -1647,7 +1663,7 @@ class Up2k(object):
1647
1663
  q = "delete from dh where (d = ? or d like ?||'/%')"
1648
1664
  db.c.execute(q, erd_erd)
1649
1665
 
1650
- q = "delete from up where (rd=? or rd like ?||'/%') and +at == 0"
1666
+ q = "delete from up where (rd=? or rd like ?||'/%')"
1651
1667
  db.c.execute(q, erd_erd)
1652
1668
  tfa += n
1653
1669
 
@@ -2914,7 +2930,7 @@ class Up2k(object):
2914
2930
  raise Exception()
2915
2931
  except Exception as ex:
2916
2932
  if n4g:
2917
- st = os.stat_result((0, -1, -1, 0, 0, 0, 0, 0, 0, 0))
2933
+ st = NULLSTAT
2918
2934
  else:
2919
2935
  lost.append((cur, dp_dir, dp_fn))
2920
2936
  continue
@@ -5273,6 +5289,11 @@ class Up2k(object):
5273
5289
  cur.close()
5274
5290
  db.close()
5275
5291
 
5292
+ if self.mem_cur:
5293
+ db = self.mem_cur.connection
5294
+ self.mem_cur.close()
5295
+ db.close()
5296
+
5276
5297
  self.registry = {}
5277
5298
 
5278
5299
 
copyparty/util.py CHANGED
@@ -2622,12 +2622,29 @@ def build_netmap(csv , defer_mutex = False):
2622
2622
  if csv in ("any", "all", "no", ",", ""):
2623
2623
  return None
2624
2624
 
2625
- if csv in ("lan", "local", "private", "prvt"):
2626
- csv = "10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fd00::/8" # lan
2627
- csv += ", 169.254.0.0/16, fe80::/10" # link-local
2628
- csv += ", 127.0.0.0/8, ::1/128" # loopback
2629
-
2630
2625
  srcs = [x.strip() for x in csv.split(",") if x.strip()]
2626
+
2627
+ expanded_shorthands = False
2628
+ for shorthand in ("lan", "local", "private", "prvt"):
2629
+ if shorthand in srcs:
2630
+ if not expanded_shorthands:
2631
+ srcs += [
2632
+ # lan:
2633
+ "10.0.0.0/8",
2634
+ "172.16.0.0/12",
2635
+ "192.168.0.0/16",
2636
+ "fd00::/8",
2637
+ # link-local:
2638
+ "169.254.0.0/16",
2639
+ "fe80::/10",
2640
+ # loopback:
2641
+ "127.0.0.0/8",
2642
+ "::1/128",
2643
+ ]
2644
+ expanded_shorthands = True
2645
+
2646
+ srcs.remove(shorthand)
2647
+
2631
2648
  if not HAVE_IPV6:
2632
2649
  srcs = [x for x in srcs if ":" not in x]
2633
2650
 
@@ -2692,6 +2709,26 @@ def yieldfile(fn , bufsz ) :
2692
2709
  yield buf
2693
2710
 
2694
2711
 
2712
+ def justcopy(
2713
+ fin ,
2714
+ fout ,
2715
+ hashobj ,
2716
+ max_sz ,
2717
+ slp ,
2718
+ ) :
2719
+ tlen = 0
2720
+ for buf in fin:
2721
+ tlen += len(buf)
2722
+ if max_sz and tlen > max_sz:
2723
+ continue
2724
+
2725
+ fout.write(buf)
2726
+ if slp:
2727
+ time.sleep(slp)
2728
+
2729
+ return tlen, "checksum-disabled", "checksum-disabled"
2730
+
2731
+
2695
2732
  def hashcopy(
2696
2733
  fin ,
2697
2734
  fout ,
@@ -3399,7 +3436,6 @@ def runhook(
3399
3436
  at ,
3400
3437
  txt ,
3401
3438
  ) :
3402
- asrv = (broker or up2k).asrv
3403
3439
  args = (broker or up2k).args
3404
3440
  vp = vp.replace("\\", "/")
3405
3441
  ret = {"rc": 0}
copyparty/web/a/u2c.py CHANGED
@@ -1088,6 +1088,8 @@ class Ctl(object):
1088
1088
 
1089
1089
  spd = humansize(spd)
1090
1090
  self.eta = str(datetime.timedelta(seconds=int(eta)))
1091
+ if eta > 2591999:
1092
+ self.eta = self.eta.split(",")[0] # truncate HH:MM:SS
1091
1093
  sleft = humansize(self.nbytes - self.up_b)
1092
1094
  nleft = self.nfiles - self.up_f
1093
1095
  tail = "\033[K\033[u" if VT100 and not self.ar.ns else "\r"
@@ -1128,7 +1130,9 @@ class Ctl(object):
1128
1130
  isdir = stat.S_ISDIR(inf.st_mode)
1129
1131
  if self.ar.z or self.ar.drd:
1130
1132
  rd = rel if isdir else os.path.dirname(rel)
1131
- srd = rd.decode("utf-8", "replace").replace("\\", "/")
1133
+ srd = rd.decode("utf-8", "replace").replace("\\", "/").rstrip("/")
1134
+ if srd:
1135
+ srd += "/"
1132
1136
  if prd != rd:
1133
1137
  prd = rd
1134
1138
  ls = {}
@@ -1163,11 +1167,11 @@ class Ctl(object):
1163
1167
  bnames = [x for x in ls if x not in lnodes and x != b".hist"]
1164
1168
  vpath = self.ar.url.split("://")[-1].split("/", 1)[-1]
1165
1169
  names = [x.decode("utf-8", WTF8) for x in bnames]
1166
- locs = [vpath + srd + "/" + x for x in names]
1170
+ locs = [vpath + srd + x for x in names]
1167
1171
  while locs:
1168
1172
  req = locs
1169
1173
  while req:
1170
- print("DELETING ~%s/#%s" % (srd, len(req)))
1174
+ print("DELETING ~%s#%s" % (srd, len(req)))
1171
1175
  body = json.dumps(req).encode("utf-8")
1172
1176
  sc, txt = web.req(
1173
1177
  "POST", self.ar.url + "?delete", {}, body, MJ
Binary file
Binary file
@@ -132,16 +132,15 @@
132
132
 
133
133
  <script>
134
134
  var SR = {{ r|tojson }},
135
+ CGV1 = {{ cgv1 }},
135
136
  CGV = {{ cgv|tojson }},
136
137
  TS = "{{ ts }}",
137
138
  dtheme = "{{ dtheme }}",
138
139
  srvinf = "{{ srv_info }}",
139
- s_name = "{{ s_name }}",
140
140
  lang = "{{ lang }}",
141
141
  dfavico = "{{ favico }}",
142
- have_tags_idx = {{ have_tags_idx|tojson }},
142
+ have_tags_idx = {{ have_tags_idx }},
143
143
  sb_lg = "{{ sb_lg }}",
144
- txt_ext = "{{ txt_ext }}",
145
144
  logues = {{ logues|tojson if sb_lg else "[]" }},
146
145
  ls0 = {{ ls0|tojson }};
147
146
 
Binary file
Binary file
Binary file
Binary file
copyparty/web/md.js.gz CHANGED
Binary file
copyparty/web/md2.js.gz CHANGED
Binary file
Binary file
Binary file
copyparty/web/ui.css.gz CHANGED
Binary file
copyparty/web/up2k.js.gz CHANGED
Binary file
copyparty/web/util.js.gz CHANGED
Binary file
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: copyparty
3
- Version: 1.16.1
4
- Summary: Portable file server with accelerated resumable uploads, deduplication, WebDAV, FTP, zeroconf, media indexer, video thumbnails, audio transcoding, and write-only folders
3
+ Version: 1.16.3
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
7
7
  Project-URL: Source Code, https://github.com/9001/copyparty
@@ -37,6 +37,10 @@ Requires-Python: >=3.3
37
37
  Description-Content-Type: text/markdown
38
38
  License-File: LICENSE
39
39
  Requires-Dist: Jinja2
40
+ Provides-Extra: thumbnails
41
+ Requires-Dist: Pillow; extra == "thumbnails"
42
+ Provides-Extra: thumbnails2
43
+ Requires-Dist: pyvips; extra == "thumbnails2"
40
44
  Provides-Extra: audiotags
41
45
  Requires-Dist: mutagen; extra == "audiotags"
42
46
  Provides-Extra: ftpd
@@ -44,14 +48,10 @@ Requires-Dist: pyftpdlib; extra == "ftpd"
44
48
  Provides-Extra: ftps
45
49
  Requires-Dist: pyftpdlib; extra == "ftps"
46
50
  Requires-Dist: pyopenssl; extra == "ftps"
47
- Provides-Extra: pwhash
48
- Requires-Dist: argon2-cffi; extra == "pwhash"
49
51
  Provides-Extra: tftpd
50
52
  Requires-Dist: partftpy>=0.4.0; extra == "tftpd"
51
- Provides-Extra: thumbnails
52
- Requires-Dist: Pillow; extra == "thumbnails"
53
- Provides-Extra: thumbnails2
54
- Requires-Dist: pyvips; extra == "thumbnails2"
53
+ Provides-Extra: pwhash
54
+ Requires-Dist: argon2-cffi; extra == "pwhash"
55
55
 
56
56
  <img src="https://github.com/9001/copyparty/raw/hovudstraum/docs/logo.svg" width="250" align="right"/>
57
57
 
@@ -1152,11 +1152,12 @@ using the GUI (winXP or later):
1152
1152
  * on winXP only, click the `Sign up for online storage` hyperlink instead and put the URL there
1153
1153
  * providing your password as the username is recommended; the password field can be anything or empty
1154
1154
 
1155
- known client bugs:
1155
+ the webdav client that's built into windows has the following list of bugs; you can avoid all of these by connecting with rclone instead:
1156
1156
  * win7+ doesn't actually send the password to the server when reauthenticating after a reboot unless you first try to login with an incorrect password and then switch to the correct password
1157
1157
  * or just type your password into the username field instead to get around it entirely
1158
1158
  * connecting to a folder which allows anonymous read will make writing impossible, as windows has decided it doesn't need to login
1159
1159
  * workaround: connect twice; first to a folder which requires auth, then to the folder you actually want, and leave both of those mounted
1160
+ * or set the server-option `--dav-auth` to force password-auth for all webdav clients
1160
1161
  * win7+ may open a new tcp connection for every file and sometimes forgets to close them, eventually needing a reboot
1161
1162
  * maybe NIC-related (??), happens with win10-ltsc on e1000e but not virtio
1162
1163
  * windows cannot access folders which contain filenames with invalid unicode or forbidden characters (`<>:"/\|?*`), or names ending with `.`
@@ -1323,7 +1324,7 @@ note:
1323
1324
 
1324
1325
  ### exclude-patterns
1325
1326
 
1326
- to save some time, you can provide a regex pattern for filepaths to only index by filename/path/size/last-modified (and not the hash of the file contents) by setting `--no-hash \.iso$` or the volflag `:c,nohash=\.iso$`, this has the following consequences:
1327
+ to save some time, you can provide a regex pattern for filepaths to only index by filename/path/size/last-modified (and not the hash of the file contents) by setting `--no-hash '\.iso$'` or the volflag `:c,nohash=\.iso$`, this has the following consequences:
1327
1328
  * initial indexing is way faster, especially when the volume is on a network disk
1328
1329
  * makes it impossible to [file-search](#file-search)
1329
1330
  * if someone uploads the same file contents, the upload will not be detected as a dupe, so it will not get symlinked or rejected
@@ -1334,6 +1335,8 @@ similarly, you can fully ignore files/folders using `--no-idx [...]` and `:c,noi
1334
1335
 
1335
1336
  if you set `--no-hash [...]` globally, you can enable hashing for specific volumes using flag `:c,nohash=`
1336
1337
 
1338
+ to exclude certain filepaths from search-results, use `--srch-excl` or volflag `srch_excl` instead of `--no-idx`, for example `--srch-excl 'password|logs/[0-9]'`
1339
+
1337
1340
  ### filesystem guards
1338
1341
 
1339
1342
  avoid traversing into other filesystems using `--xdev` / volflag `:c,xdev`, skipping any symlinks or bind-mounts to another HDD for example