copyparty 1.6.8__py2.py3-none-any.whl → 1.6.10__py2.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 CHANGED
@@ -752,7 +752,7 @@ def add_ftp(ap):
752
752
 
753
753
  def add_webdav(ap):
754
754
  ap2 = ap.add_argument_group('WebDAV options')
755
- ap2.add_argument("--daw", action="store_true", help="enable full write support. \033[1;31mWARNING:\033[0m This has side-effects -- PUT-operations will now \033[1;31mOVERWRITE\033[0m existing files, rather than inventing new filenames to avoid loss of data. You might want to instead set this as a volflag where needed. By not setting this flag, uploaded files can get written to a filename which the client does not expect (which might be okay, depending on client)")
755
+ ap2.add_argument("--daw", action="store_true", help="enable full write support, even if client may not be webdav. \033[1;31mWARNING:\033[0m This has side-effects -- PUT-operations will now \033[1;31mOVERWRITE\033[0m existing files, rather than inventing new filenames to avoid loss of data. You might want to instead set this as a volflag where needed. By not setting this flag, uploaded files can get written to a filename which the client does not expect (which might be okay, depending on client)")
756
756
  ap2.add_argument("--dav-inf", action="store_true", help="allow depth:infinite requests (recursive file listing); extremely server-heavy but required for spec compliance -- luckily few clients rely on this")
757
757
  ap2.add_argument("--dav-mac", action="store_true", help="disable apple-garbage filter -- allow macos to create junk files (._* and .DS_Store, .Spotlight-*, .fseventsd, .Trashes, .AppleDouble, __MACOS)")
758
758
 
@@ -940,6 +940,7 @@ def add_ui(ap, retry):
940
940
  ap2.add_argument("--js-browser", metavar="L", type=u, help="URL to additional JS to include")
941
941
  ap2.add_argument("--css-browser", metavar="L", type=u, help="URL to additional CSS to include")
942
942
  ap2.add_argument("--html-head", metavar="TXT", type=u, default="", help="text to append to the <head> of all HTML pages")
943
+ ap2.add_argument("--ih", action="store_true", help="if a folder contains index.html, show that instead of the directory listing by default (can be changed in the client settings UI)")
943
944
  ap2.add_argument("--textfiles", metavar="CSV", type=u, default="txt,nfo,diz,cue,readme", help="file extensions to present as plaintext")
944
945
  ap2.add_argument("--txt-max", metavar="KiB", type=int, default=64, help="max size of embedded textfiles on ?doc= (anything bigger will be lazy-loaded by JS)")
945
946
  ap2.add_argument("--doctitle", metavar="TXT", type=u, default="copyparty", help="title / service-name to show in html documents")
copyparty/__version__.py CHANGED
@@ -1,8 +1,8 @@
1
1
  # coding: utf-8
2
2
 
3
- VERSION = (1, 6, 8)
3
+ VERSION = (1, 6, 10)
4
4
  CODENAME = "cors k"
5
- BUILD_DT = (2023, 3, 12)
5
+ BUILD_DT = (2023, 3, 20)
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/ftpd.py CHANGED
@@ -124,6 +124,7 @@ class FtpFs(AbstractedFS):
124
124
 
125
125
  def die(self, msg):
126
126
  self.h.die(msg)
127
+ raise Exception()
127
128
 
128
129
  def v2a(
129
130
  self,
copyparty/httpcli.py CHANGED
@@ -774,8 +774,8 @@ class HttpCli(object):
774
774
  if "k304" in self.uparam:
775
775
  return self.set_k304()
776
776
 
777
- if "am_js" in self.uparam:
778
- return self.set_am_js()
777
+ if "setck" in self.uparam:
778
+ return self.setck()
779
779
 
780
780
  if "reset" in self.uparam:
781
781
  return self.set_cfg_reset()
@@ -861,7 +861,17 @@ class HttpCli(object):
861
861
  vn, rem = self.asrv.vfs.get(self.vpath, self.uname, True, False, err=401)
862
862
  depth = self.headers.get("depth", "infinity").lower()
863
863
 
864
- if depth == "infinity":
864
+ try:
865
+ topdir = {"vp": "", "st": bos.stat(vn.canonical(rem))}
866
+ except OSError as ex:
867
+ if ex.errno != errno.ENOENT:
868
+ raise
869
+ raise Pebkac(404)
870
+
871
+ if not stat.S_ISDIR(topdir["st"].st_mode):
872
+ fgen = []
873
+
874
+ elif depth == "infinity":
865
875
  if not self.args.dav_inf:
866
876
  self.log("client wants --dav-inf", 3)
867
877
  zb = b'<?xml version="1.0" encoding="utf-8"?>\n<D:error xmlns:D="DAV:"><D:propfind-finite-depth/></D:error>'
@@ -900,13 +910,6 @@ class HttpCli(object):
900
910
  t2 = " or 'infinity'" if self.args.dav_inf else ""
901
911
  raise Pebkac(412, t.format(depth, t2))
902
912
 
903
- try:
904
- topdir = {"vp": "", "st": os.stat(vn.canonical(rem))}
905
- except OSError as ex:
906
- if ex.errno != errno.ENOENT:
907
- raise
908
- raise Pebkac(404)
909
-
910
913
  fgen = itertools.chain([topdir], fgen) # type: ignore
911
914
  vtop = vjoin(self.args.R, vjoin(vn.vpath, rem))
912
915
 
@@ -1422,9 +1425,9 @@ class HttpCli(object):
1422
1425
  self.log(t, 1)
1423
1426
  raise Pebkac(403, t)
1424
1427
 
1425
- if is_put and not (self.args.no_dav or self.args.nw):
1428
+ if is_put and not (self.args.no_dav or self.args.nw) and bos.path.exists(path):
1426
1429
  # allow overwrite if...
1427
- # * volflag 'daw' is set
1430
+ # * volflag 'daw' is set, or client is definitely webdav
1428
1431
  # * and account has delete-access
1429
1432
  # or...
1430
1433
  # * file exists, is empty, sufficiently new
@@ -1434,9 +1437,11 @@ class HttpCli(object):
1434
1437
  if self.args.dotpart:
1435
1438
  tnam = "." + tnam
1436
1439
 
1437
- if (vfs.flags.get("daw") and self.can_delete) or (
1440
+ if (
1441
+ self.can_delete
1442
+ and (vfs.flags.get("daw") or "x-oc-mtime" in self.headers)
1443
+ ) or (
1438
1444
  not bos.path.exists(os.path.join(fdir, tnam))
1439
- and bos.path.exists(path)
1440
1445
  and not bos.path.getsize(path)
1441
1446
  and bos.path.getmtime(path) >= time.time() - self.args.blank_wt
1442
1447
  ):
@@ -1460,6 +1465,16 @@ class HttpCli(object):
1460
1465
  if self.args.nw:
1461
1466
  return post_sz, sha_hex, sha_b64, remains, path, ""
1462
1467
 
1468
+ at = mt = time.time() - lifetime
1469
+ cli_mt = self.headers.get("x-oc-mtime")
1470
+ if cli_mt:
1471
+ try:
1472
+ mt = int(cli_mt)
1473
+ times = (int(time.time()), mt)
1474
+ bos.utime(path, times, False)
1475
+ except:
1476
+ pass
1477
+
1463
1478
  if nameless and "magic" in vfs.flags:
1464
1479
  try:
1465
1480
  ext = self.conn.hsrv.magician.ext(path)
@@ -1482,7 +1497,6 @@ class HttpCli(object):
1482
1497
  fn = fn2
1483
1498
  path = path2
1484
1499
 
1485
- at = time.time() - lifetime
1486
1500
  if xau and not runhook(
1487
1501
  self.log,
1488
1502
  xau,
@@ -1490,7 +1504,7 @@ class HttpCli(object):
1490
1504
  self.vpath,
1491
1505
  self.host,
1492
1506
  self.uname,
1493
- at,
1507
+ mt,
1494
1508
  post_sz,
1495
1509
  self.ip,
1496
1510
  at,
@@ -1753,12 +1767,13 @@ class HttpCli(object):
1753
1767
  hits = idx.fsearch(vols, body)
1754
1768
  msg = repr(hits)
1755
1769
  taglist = []
1770
+ trunc = False
1756
1771
  else:
1757
1772
  # search by query params
1758
1773
  q = body["q"]
1759
1774
  n = body.get("n", self.args.srch_hits)
1760
1775
  self.log("qj: {} |{}|".format(q, n))
1761
- hits, taglist = idx.search(vols, q, n)
1776
+ hits, taglist, trunc = idx.search(vols, q, n)
1762
1777
  msg = len(hits)
1763
1778
 
1764
1779
  idx.p_end = time.time()
@@ -1778,7 +1793,8 @@ class HttpCli(object):
1778
1793
  for hit in hits:
1779
1794
  hit["rp"] = self.args.RS + hit["rp"]
1780
1795
 
1781
- r = json.dumps({"hits": hits, "tag_order": order}).encode("utf-8")
1796
+ rj = {"hits": hits, "tag_order": order, "trunc": trunc}
1797
+ r = json.dumps(rj).encode("utf-8")
1782
1798
  self.reply(r, mime="application/json")
1783
1799
  return True
1784
1800
 
@@ -2892,15 +2908,16 @@ class HttpCli(object):
2892
2908
  self.redirect("", "?h#cc")
2893
2909
  return True
2894
2910
 
2895
- def set_am_js(self) :
2896
- v = "n" if self.uparam["am_js"] == "n" else "y"
2897
- ck = gencookie("js", v, self.args.R, False, 86400 * 299)
2911
+ def setck(self) :
2912
+ k, v = self.uparam["setck"].split("=", 1)
2913
+ t = None if v == "" else 86400 * 299
2914
+ ck = gencookie(k, v, self.args.R, False, t)
2898
2915
  self.out_headerlist.append(("Set-Cookie", ck))
2899
- self.reply(b"promoted\n")
2916
+ self.reply(b"o7\n")
2900
2917
  return True
2901
2918
 
2902
2919
  def set_cfg_reset(self) :
2903
- for k in ("k304", "js", "cppwd", "cppws"):
2920
+ for k in ("k304", "js", "idxh", "cppwd", "cppws"):
2904
2921
  cookie = gencookie(k, "x", self.args.R, False, None)
2905
2922
  self.out_headerlist.append(("Set-Cookie", cookie))
2906
2923
 
@@ -3429,6 +3446,7 @@ class HttpCli(object):
3429
3446
  "dtheme": self.args.theme,
3430
3447
  "themes": self.args.themes,
3431
3448
  "turbolvl": self.args.turbo,
3449
+ "idxh": int(self.args.ih),
3432
3450
  "u2sort": self.args.u2sort,
3433
3451
  }
3434
3452
 
@@ -3562,6 +3580,20 @@ class HttpCli(object):
3562
3580
  files.append(item)
3563
3581
  item["rd"] = rem
3564
3582
 
3583
+ if (
3584
+ self.cookies.get("idxh") == "y"
3585
+ and "ls" not in self.uparam
3586
+ and "v" not in self.uparam
3587
+ ):
3588
+ idx_html = set(["index.htm", "index.html"])
3589
+ for item in files:
3590
+ if item["name"] in idx_html:
3591
+ # do full resolve in case of shadowed file
3592
+ vp = vjoin(self.vpath.split("?")[0], item["name"])
3593
+ vn, rem = self.asrv.vfs.get(vp, self.uname, True, False)
3594
+ ap = vn.canonical(rem)
3595
+ return self.tx_file(ap) # is no-cache
3596
+
3565
3597
  tagset = set()
3566
3598
  for fe in files:
3567
3599
  fn = fe["name"]
copyparty/th_srv.py CHANGED
@@ -558,12 +558,19 @@ class ThumbSrv(object):
558
558
  if "ac" not in ret:
559
559
  raise Exception("not audio")
560
560
 
561
+ try:
562
+ dur = ret[".dur"][1]
563
+ except:
564
+ dur = 0
565
+
561
566
  src_opus = abspath.lower().endswith(".opus") or ret["ac"][1] == "opus"
562
567
  want_caf = tpath.endswith(".caf")
563
568
  tmp_opus = tpath
564
569
  if want_caf:
565
570
  tmp_opus = tpath.rsplit(".", 1)[0] + ".opus"
566
571
 
572
+ caf_src = abspath if src_opus else tmp_opus
573
+
567
574
  if not want_caf or (not src_opus and not bos.path.isfile(tmp_opus)):
568
575
  # fmt: off
569
576
  cmd = [
@@ -581,7 +588,32 @@ class ThumbSrv(object):
581
588
  # fmt: on
582
589
  self._run_ff(cmd)
583
590
 
584
- if want_caf:
591
+ # iOS fails to play some "insufficiently complex" files
592
+ # (average file shorter than 8 seconds), so of course we
593
+ # fix that by mixing in some inaudible pink noise :^)
594
+ # 6.3 sec seems like the cutoff so lets do 7, and
595
+ # 7 sec of psyqui-musou.opus @ 3:50 is 174 KiB
596
+ if want_caf and (dur < 20 or bos.path.getsize(caf_src) < 256 * 1024):
597
+ # fmt: off
598
+ cmd = [
599
+ b"ffmpeg",
600
+ b"-nostdin",
601
+ b"-v", b"error",
602
+ b"-hide_banner",
603
+ b"-i", fsenc(abspath),
604
+ b"-filter_complex", b"anoisesrc=a=0.001:d=7:c=pink,asplit[l][r]; [l][r]amerge[s]; [0:a:0][s]amix",
605
+ b"-map_metadata", b"-1",
606
+ b"-ac", b"2",
607
+ b"-c:a", b"libopus",
608
+ b"-b:a", b"128k",
609
+ b"-f", b"caf",
610
+ fsenc(tpath)
611
+ ]
612
+ # fmt: on
613
+ self._run_ff(cmd)
614
+
615
+ elif want_caf:
616
+ # simple remux should be safe
585
617
  # fmt: off
586
618
  cmd = [
587
619
  b"ffmpeg",
copyparty/u2idx.py CHANGED
@@ -117,10 +117,10 @@ class U2idx(object):
117
117
 
118
118
  def search(
119
119
  self, vols , uq , lim
120
- ) :
120
+ ) :
121
121
  """search by query params"""
122
122
  if not HAVE_SQLITE3:
123
- return [], []
123
+ return [], [], False
124
124
 
125
125
  q = ""
126
126
  v = ""
@@ -272,7 +272,7 @@ class U2idx(object):
272
272
  have_up ,
273
273
  have_mt ,
274
274
  lim ,
275
- ) :
275
+ ) :
276
276
  done_flag = []
277
277
  self.active_id = "{:.6f}_{}".format(
278
278
  time.time(), threading.current_thread().ident
@@ -313,9 +313,6 @@ class U2idx(object):
313
313
  c = cur.execute(uq, tuple(vuv))
314
314
  for hit in c:
315
315
  w, ts, sz, rd, fn, ip, at = hit[:7]
316
- lim -= 1
317
- if lim < 0:
318
- break
319
316
 
320
317
  if rd.startswith("//") or fn.startswith("//"):
321
318
  rd, fn = s3dec(rd, fn)
@@ -343,6 +340,10 @@ class U2idx(object):
343
340
  )[:fk]
344
341
  )
345
342
 
343
+ lim -= 1
344
+ if lim < 0:
345
+ break
346
+
346
347
  seen_rps.add(rp)
347
348
  sret.append({"ts": int(ts), "sz": sz, "rp": rp + suf, "w": w[:16]})
348
349
 
@@ -365,7 +366,7 @@ class U2idx(object):
365
366
 
366
367
  ret.sort(key=itemgetter("rp"))
367
368
 
368
- return ret, list(taglist.keys())
369
+ return ret, list(taglist.keys()), lim < 0
369
370
 
370
371
  def terminator(self, identifier , done_flag ) :
371
372
  for _ in range(self.timeout):
copyparty/up2k.py CHANGED
@@ -1248,12 +1248,15 @@ class Up2k(object):
1248
1248
  if n_rm2:
1249
1249
  self.log("forgetting {} shadowed deleted files".format(n_rm2))
1250
1250
 
1251
+ c2.connection.commit()
1252
+
1251
1253
  # then covers
1252
1254
  n_rm3 = 0
1255
+ qu = "select 1 from up where rd=? and +fn=? limit 1"
1253
1256
  q = "delete from cv where rd=? and dn=? and +fn=?"
1254
1257
  for crd, cdn, fn in cur.execute("select * from cv"):
1255
- ap = os.path.join(top, crd, cdn, fn)
1256
- if not bos.path.exists(ap):
1258
+ urd = vjoin(crd, cdn)
1259
+ if not c2.execute(qu, (urd, fn)).fetchone():
1257
1260
  c2.execute(q, (crd, cdn, fn))
1258
1261
  n_rm3 += 1
1259
1262
 
Binary file
@@ -155,6 +155,7 @@
155
155
  sb_lg = "{{ sb_lg }}",
156
156
  lifetime = {{ lifetime }},
157
157
  turbolvl = {{ turbolvl }},
158
+ idxh = {{ idxh }},
158
159
  frand = {{ frand|tojson }},
159
160
  u2sort = "{{ u2sort }}",
160
161
  have_emp = {{ have_emp|tojson }},
Binary file
copyparty/web/svcs.html CHANGED
@@ -46,7 +46,7 @@
46
46
  <p><em>note: rclone-FTP is a bit faster, so {% if args.ftp or args.ftps %}try that first{% else %}consider enabling FTP in server settings{% endif %}</em></p>
47
47
  <p>if you can, install <a href="https://winfsp.dev/rel/">winfsp</a>+<a href="https://downloads.rclone.org/rclone-current-windows-amd64.zip">rclone</a> and then paste this in cmd:</p>
48
48
  <pre>
49
- rclone config create {{ aname }}-dav webdav url=http{{ s }}://{{ rip }}{{ hport }} vendor=other{% if accs %} user=k pass=<b>{{ pw }}</b>{% endif %}
49
+ rclone config create {{ aname }}-dav webdav url=http{{ s }}://{{ rip }}{{ hport }} vendor=owncloud{% if accs %} user=k pass=<b>{{ pw }}</b>{% endif %}
50
50
  rclone mount --vfs-cache-mode writes --dir-cache-time 5s {{ aname }}-dav:{{ rvp }} <b>W:</b>
51
51
  </pre>
52
52
  {% if s %}
@@ -69,9 +69,9 @@
69
69
  printf '%s\n' "http{{ s }}://{{ ep }}/{{ rvp }} <b>{{ pw }}</b> k" >> /etc/davfs2/secrets
70
70
  printf '%s\n' "http{{ s }}://{{ ep }}/{{ rvp }} <b>mp</b> davfs rw,user,uid=1000,noauto 0 0" >> /etc/fstab
71
71
  </pre>
72
- <p>or you can use rclone instead, which is much slower but doesn't require root:</p>
72
+ <p>or you can use rclone instead, which is much slower but doesn't require root (plus it keeps lastmodified on upload):</p>
73
73
  <pre>
74
- rclone config create {{ aname }}-dav webdav url=http{{ s }}://{{ rip }}{{ hport }} vendor=other{% if accs %} user=k pass=<b>{{ pw }}</b>{% endif %}
74
+ rclone config create {{ aname }}-dav webdav url=http{{ s }}://{{ rip }}{{ hport }} vendor=owncloud{% if accs %} user=k pass=<b>{{ pw }}</b>{% endif %}
75
75
  rclone mount --vfs-cache-mode writes --dir-cache-time 5s {{ aname }}-dav:{{ rvp }} <b>mp</b>
76
76
  </pre>
77
77
  {% if s %}
copyparty/web/util.js.gz CHANGED
Binary file
@@ -1,29 +1,16 @@
1
1
  # 💾🎉 copyparty
2
2
 
3
- * portable file sharing hub (py2/py3) [(on PyPI)](https://pypi.org/project/copyparty/)
4
- * MIT-Licensed, 2019-05-26, ed @ irc.rizon.net
3
+ turn almost any device into a file server with resumable uploads/downloads using [*any*](#browser-support) web browser
5
4
 
5
+ * server only needs Python (2 or 3), all dependencies optional
6
+ * 🔌 protocols: [http](#the-browser) // [ftp](#ftp-server) // [webdav](#webdav-server) // [smb/cifs](#smb-server)
7
+ * 📱 [android app](#android-app) // [iPhone shortcuts](#ios-shortcuts)
6
8
 
7
- ## summary
8
-
9
- turn your phone or raspi into a portable file server with resumable uploads/downloads using *any* web browser
10
-
11
- * server only needs Python (`2.7` or `3.3+`), all dependencies optional
12
- * browse/upload with [IE4](#browser-support) / netscape4.0 on win3.11 (heh)
13
- * protocols: [http](#the-browser) // [ftp](#ftp-server) // [webdav](#webdav-server) // [smb/cifs](#smb-server)
14
-
15
- try the **[read-only demo server](https://a.ocv.me/pub/demo/)** 👀 running from a basement in finland
9
+ 👉 **[Get started](#quickstart)!** or visit the **[read-only demo server](https://a.ocv.me/pub/demo/)** 👀 running from a basement in finland
16
10
 
17
11
  📷 **screenshots:** [browser](#the-browser) // [upload](#uploading) // [unpost](#unpost) // [thumbnails](#thumbnails) // [search](#searching) // [fsearch](#file-search) // [zip-DL](#zip-downloads) // [md-viewer](#markdown-viewer)
18
12
 
19
13
 
20
- ## get the app
21
-
22
- <a href="https://f-droid.org/packages/me.ocv.partyup/"><img src="https://ocv.me/fdroid.png" alt="Get it on F-Droid" height="50" /> '' <img src="https://img.shields.io/f-droid/v/me.ocv.partyup.svg" alt="f-droid version info" /></a> '' <a href="https://github.com/9001/party-up"><img src="https://img.shields.io/github/release/9001/party-up.svg?logo=github" alt="github version info" /></a>
23
-
24
- (the app is **NOT** the full copyparty server! just a basic upload client, nothing fancy yet)
25
-
26
-
27
14
  ## readme toc
28
15
 
29
16
  * top
@@ -82,12 +69,16 @@ try the **[read-only demo server](https://a.ocv.me/pub/demo/)** 👀 running fro
82
69
  * [reverse-proxy](#reverse-proxy) - running copyparty next to other websites
83
70
  * [browser support](#browser-support) - TLDR: yes
84
71
  * [client examples](#client-examples) - interact with copyparty using non-browser clients
72
+ * [folder sync](#folder-sync) - sync folders to/from copyparty
85
73
  * [mount as drive](#mount-as-drive) - a remote copyparty server as a local filesystem
74
+ * [android app](#android-app) - upload to copyparty with one tap
75
+ * [iOS shortcuts](#iOS-shortcuts) - there is no iPhone app, but
86
76
  * [performance](#performance) - defaults are usually fine - expect `8 GiB/s` download, `1 GiB/s` upload
87
77
  * [client-side](#client-side) - when uploading files
88
78
  * [security](#security) - some notes on hardening
89
79
  * [gotchas](#gotchas) - behavior that might be unexpected
90
80
  * [cors](#cors) - cross-site request config
81
+ * [https](#https) - both HTTP and HTTPS are accepted
91
82
  * [recovering from crashes](#recovering-from-crashes)
92
83
  * [client crashes](#client-crashes)
93
84
  * [frefox wsod](#frefox-wsod) - firefox 87 can crash during uploads
@@ -108,6 +99,7 @@ just run **[copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/
108
99
 
109
100
  * or install through pypi (python3 only): `python3 -m pip install --user -U copyparty`
110
101
  * or if you cannot install python, you can use [copyparty.exe](#copypartyexe) instead
102
+ * or if you are on android, [install copyparty in termux](#install-on-android)
111
103
  * or if you prefer to [use docker](./scripts/docker/) 🐋 you can do that too
112
104
  * docker has all deps built-in, so skip this step:
113
105
 
@@ -165,11 +157,15 @@ firewall-cmd --reload
165
157
  * ☑ [smb/cifs server](#smb-server)
166
158
  * ☑ [qr-code](#qr-code) for quick access
167
159
  * ☑ [upnp / zeroconf / mdns / ssdp](#zeroconf)
160
+ * ☑ [event hooks](#event-hooks) / script runner
161
+ * ☑ [reverse-proxy support](https://github.com/9001/copyparty#reverse-proxy)
168
162
  * upload
169
163
  * ☑ basic: plain multipart, ie6 support
170
164
  * ☑ [up2k](#uploading): js, resumable, multithreaded
171
165
  * unaffected by cloudflare's max-upload-size (100 MiB)
172
166
  * ☑ stash: simple PUT filedropper
167
+ * ☑ filename randomizer
168
+ * ☑ write-only folders
173
169
  * ☑ [unpost](#unpost): undo/delete accidental uploads
174
170
  * ☑ [self-destruct](#self-destruct) (specified server-side or client-side)
175
171
  * ☑ symlink/discard existing files (content-matching)
@@ -193,10 +189,15 @@ firewall-cmd --reload
193
189
  * ☑ [locate files by contents](#file-search)
194
190
  * ☑ search by name/path/date/size
195
191
  * ☑ [search by ID3-tags etc.](#searching)
192
+ * client support
193
+ * ☑ [folder sync](#folder-sync)
194
+ * ☑ [curl-friendly](https://user-images.githubusercontent.com/241032/215322619-ea5fd606-3654-40ad-94ee-2bc058647bb2.png)
196
195
  * markdown
197
196
  * ☑ [viewer](#markdown-viewer)
198
197
  * ☑ editor (sure why not)
199
198
 
199
+ PS: something missing? post any crazy ideas you've got as a [feature request](https://github.com/9001/copyparty/issues/new?assignees=9001&labels=enhancement&template=feature_request.md) or [discussion](https://github.com/9001/copyparty/discussions/new?category=ideas) 🤙
200
+
200
201
 
201
202
  ## testimonials
202
203
 
@@ -268,7 +269,7 @@ server notes:
268
269
 
269
270
  * iPhones: the volume control doesn't work because [apple doesn't want it to](https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html#//apple_ref/doc/uid/TP40009523-CH5-SW11)
270
271
  * *future workaround:* enable the equalizer, make it all-zero, and set a negative boost to reduce the volume
271
- * "future" because `AudioContext` is broken in the current iOS version (15.1), maybe one day...
272
+ * "future" because `AudioContext` can't maintain a stable playback speed in the current iOS version (15.7), maybe one day...
272
273
 
273
274
  * Windows: folders cannot be accessed if the name ends with `.`
274
275
  * python or windows bug
@@ -1092,13 +1093,15 @@ see the top of [./copyparty/web/browser.css](./copyparty/web/browser.css) where
1092
1093
 
1093
1094
  ## reverse-proxy
1094
1095
 
1095
- running copyparty next to other websites hosted on an existing webserver such as nginx or apache
1096
+ running copyparty next to other websites hosted on an existing webserver such as nginx, caddy, or apache
1096
1097
 
1097
1098
  you can either:
1098
1099
  * give copyparty its own domain or subdomain (recommended)
1099
1100
  * or do location-based proxying, using `--rp-loc=/stuff` to tell copyparty where it is mounted -- has a slight performance cost and higher chance of bugs
1100
1101
  * if copyparty says `incorrect --rp-loc or webserver config; expected vpath starting with [...]` it's likely because the webserver is stripping away the proxy location from the request URLs -- see the `ProxyPass` in the apache example below
1101
1102
 
1103
+ some reverse proxies (such as [Caddy](https://caddyserver.com/)) can automatically obtain a valid https/tls certificate for you, and some support HTTP/2 and QUIC which could be a nice speed boost
1104
+
1102
1105
  example webserver configs:
1103
1106
 
1104
1107
  * [nginx config](contrib/nginx/copyparty.conf) -- entire domain/subdomain
@@ -1176,7 +1179,7 @@ interact with copyparty using non-browser clients
1176
1179
  * `(printf 'PUT / HTTP/1.1\r\n\r\n'; cat movie.mkv) >/dev/tcp/127.0.0.1/3923`
1177
1180
 
1178
1181
  * python: [up2k.py](https://github.com/9001/copyparty/blob/hovudstraum/bin/up2k.py) is a command-line up2k client [(webm)](https://ocv.me/stuff/u2cli.webm)
1179
- * file uploads, file-search, folder sync, autoresume of aborted/broken uploads
1182
+ * file uploads, file-search, [folder sync](#folder-sync), autoresume of aborted/broken uploads
1180
1183
  * can be downloaded from copyparty: controlpanel -> connect -> [up2k.py](http://127.0.0.1:3923/.cpr/a/up2k.py)
1181
1184
  * see [./bin/README.md#up2kpy](bin/README.md#up2kpy)
1182
1185
 
@@ -1197,6 +1200,15 @@ you can provide passwords using header `PW: hunter2`, cookie `cppwd=hunter2`, ur
1197
1200
  NOTE: curl will not send the original filename if you use `-T` combined with url-params! Also, make sure to always leave a trailing slash in URLs unless you want to override the filename
1198
1201
 
1199
1202
 
1203
+ ## folder sync
1204
+
1205
+ sync folders to/from copyparty
1206
+
1207
+ the commandline uploader [up2k.py](https://github.com/9001/copyparty/tree/hovudstraum/bin#up2kpy) with `--dr` is the best way to sync a folder to copyparty; verifies checksums and does files in parallel, and deletes unexpected files on the server after upload has finished which makes file-renames really cheap (it'll rename serverside and skip uploading)
1208
+
1209
+ alternatively there is [rclone](./docs/rclone.md) which allows for bidirectional sync and is *way* more flexible (stream files straight from sftp/s3/gcs to copyparty for instance), although syncing to copyparty is about 5x slower than up2k.py if you have many small files in particular
1210
+
1211
+
1200
1212
  ## mount as drive
1201
1213
 
1202
1214
  a remote copyparty server as a local filesystem; go to the control-panel and click `connect` to see a list of commands to do that
@@ -1215,6 +1227,27 @@ alternatively, some alternatives roughly sorted by speed (unreproducible benchma
1215
1227
  most clients will fail to mount the root of a copyparty server unless there is a root volume (so you get the admin-panel instead of a browser when accessing it) -- in that case, mount a specific volume instead
1216
1228
 
1217
1229
 
1230
+ # android app
1231
+
1232
+ upload to copyparty with one tap
1233
+
1234
+ <a href="https://f-droid.org/packages/me.ocv.partyup/"><img src="https://ocv.me/fdroid.png" alt="Get it on F-Droid" height="50" /> '' <img src="https://img.shields.io/f-droid/v/me.ocv.partyup.svg" alt="f-droid version info" /></a> '' <a href="https://github.com/9001/party-up"><img src="https://img.shields.io/github/release/9001/party-up.svg?logo=github" alt="github version info" /></a>
1235
+
1236
+ the app is **NOT** the full copyparty server! just a basic upload client, nothing fancy yet
1237
+
1238
+ if you want to run the copyparty server on your android device, see [install on android](#install-on-android)
1239
+
1240
+
1241
+ # iOS shortcuts
1242
+
1243
+ there is no iPhone app, but the following shortcuts are almost as good:
1244
+
1245
+ * [upload to copyparty](https://www.icloud.com/shortcuts/41e98dd985cb4d3bb433222bc1e9e770) ([offline](https://github.com/9001/copyparty/raw/hovudstraum/contrib/ios/upload-to-copyparty.shortcut)) ([png](https://user-images.githubusercontent.com/241032/226118053-78623554-b0ed-482e-98e4-6d57ada58ea4.png)) based on the [original](https://www.icloud.com/shortcuts/ab415d5b4de3467b9ce6f151b439a5d7) by [Daedren](https://github.com/Daedren) (thx!)
1246
+ * can strip exif, upload files, pics, vids, links, clipboard
1247
+ * can download links and rehost the target file on copyparty (see first comment inside the shortcut)
1248
+ * pics become lowres if you share from gallery to shortcut, so better to launch the shortcut and pick stuff from there
1249
+
1250
+
1218
1251
  # performance
1219
1252
 
1220
1253
  defaults are usually fine - expect `8 GiB/s` download, `1 GiB/s` upload
@@ -1310,6 +1343,13 @@ by default, except for `GET` and `HEAD` operations, all requests must either:
1310
1343
  cors can be configured with `--acao` and `--acam`, or the protections entirely disabled with `--allow-csrf`
1311
1344
 
1312
1345
 
1346
+ ## https
1347
+
1348
+ both HTTP and HTTPS are accepted by default, but letting a [reverse proxy](#reverse-proxy) handle the https/tls/ssl would be better (probably more secure by default)
1349
+
1350
+ copyparty doesn't speak HTTP/2 or QUIC, so using a reverse proxy would solve that as well
1351
+
1352
+
1313
1353
  # recovering from crashes
1314
1354
 
1315
1355
  ## client crashes
@@ -1377,7 +1417,7 @@ these are standalone programs and will never be imported / evaluated by copypart
1377
1417
 
1378
1418
  the self-contained "binary" [copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/download/copyparty-sfx.py) will unpack itself and run copyparty, assuming you have python installed of course
1379
1419
 
1380
- you can reduce the sfx size by repacking it; see [./docs/devnotes.md#sfx-repack](#./docs/devnotes.md#sfx-repack)
1420
+ you can reduce the sfx size by repacking it; see [./docs/devnotes.md#sfx-repack](./docs/devnotes.md#sfx-repack)
1381
1421
 
1382
1422
 
1383
1423
  ## copyparty.exe
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: copyparty
3
- Version: 1.6.8
3
+ Version: 1.6.10
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
  Home-page: https://github.com/9001/copyparty
6
6
  Author: ed
@@ -47,30 +47,17 @@ Requires-Dist: pyvips ; extra == 'thumbnails2'
47
47
 
48
48
  # 💾🎉 copyparty
49
49
 
50
- * portable file sharing hub (py2/py3) [(on PyPI)](https://pypi.org/project/copyparty/)
51
- * MIT-Licensed, 2019-05-26, ed @ irc.rizon.net
50
+ turn almost any device into a file server with resumable uploads/downloads using [*any*](#browser-support) web browser
52
51
 
52
+ * server only needs Python (2 or 3), all dependencies optional
53
+ * 🔌 protocols: [http](#the-browser) // [ftp](#ftp-server) // [webdav](#webdav-server) // [smb/cifs](#smb-server)
54
+ * 📱 [android app](#android-app) // [iPhone shortcuts](#ios-shortcuts)
53
55
 
54
- ## summary
55
-
56
- turn your phone or raspi into a portable file server with resumable uploads/downloads using *any* web browser
57
-
58
- * server only needs Python (`2.7` or `3.3+`), all dependencies optional
59
- * browse/upload with [IE4](#browser-support) / netscape4.0 on win3.11 (heh)
60
- * protocols: [http](#the-browser) // [ftp](#ftp-server) // [webdav](#webdav-server) // [smb/cifs](#smb-server)
61
-
62
- try the **[read-only demo server](https://a.ocv.me/pub/demo/)** 👀 running from a basement in finland
56
+ 👉 **[Get started](#quickstart)!** or visit the **[read-only demo server](https://a.ocv.me/pub/demo/)** 👀 running from a basement in finland
63
57
 
64
58
  📷 **screenshots:** [browser](#the-browser) // [upload](#uploading) // [unpost](#unpost) // [thumbnails](#thumbnails) // [search](#searching) // [fsearch](#file-search) // [zip-DL](#zip-downloads) // [md-viewer](#markdown-viewer)
65
59
 
66
60
 
67
- ## get the app
68
-
69
- <a href="https://f-droid.org/packages/me.ocv.partyup/"><img src="https://ocv.me/fdroid.png" alt="Get it on F-Droid" height="50" /> '' <img src="https://img.shields.io/f-droid/v/me.ocv.partyup.svg" alt="f-droid version info" /></a> '' <a href="https://github.com/9001/party-up"><img src="https://img.shields.io/github/release/9001/party-up.svg?logo=github" alt="github version info" /></a>
70
-
71
- (the app is **NOT** the full copyparty server! just a basic upload client, nothing fancy yet)
72
-
73
-
74
61
  ## readme toc
75
62
 
76
63
  * top
@@ -129,12 +116,16 @@ try the **[read-only demo server](https://a.ocv.me/pub/demo/)** 👀 running fro
129
116
  * [reverse-proxy](#reverse-proxy) - running copyparty next to other websites
130
117
  * [browser support](#browser-support) - TLDR: yes
131
118
  * [client examples](#client-examples) - interact with copyparty using non-browser clients
119
+ * [folder sync](#folder-sync) - sync folders to/from copyparty
132
120
  * [mount as drive](#mount-as-drive) - a remote copyparty server as a local filesystem
121
+ * [android app](#android-app) - upload to copyparty with one tap
122
+ * [iOS shortcuts](#iOS-shortcuts) - there is no iPhone app, but
133
123
  * [performance](#performance) - defaults are usually fine - expect `8 GiB/s` download, `1 GiB/s` upload
134
124
  * [client-side](#client-side) - when uploading files
135
125
  * [security](#security) - some notes on hardening
136
126
  * [gotchas](#gotchas) - behavior that might be unexpected
137
127
  * [cors](#cors) - cross-site request config
128
+ * [https](#https) - both HTTP and HTTPS are accepted
138
129
  * [recovering from crashes](#recovering-from-crashes)
139
130
  * [client crashes](#client-crashes)
140
131
  * [frefox wsod](#frefox-wsod) - firefox 87 can crash during uploads
@@ -155,6 +146,7 @@ just run **[copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/
155
146
 
156
147
  * or install through pypi (python3 only): `python3 -m pip install --user -U copyparty`
157
148
  * or if you cannot install python, you can use [copyparty.exe](#copypartyexe) instead
149
+ * or if you are on android, [install copyparty in termux](#install-on-android)
158
150
  * or if you prefer to [use docker](./scripts/docker/) 🐋 you can do that too
159
151
  * docker has all deps built-in, so skip this step:
160
152
 
@@ -212,11 +204,15 @@ firewall-cmd --reload
212
204
  * ☑ [smb/cifs server](#smb-server)
213
205
  * ☑ [qr-code](#qr-code) for quick access
214
206
  * ☑ [upnp / zeroconf / mdns / ssdp](#zeroconf)
207
+ * ☑ [event hooks](#event-hooks) / script runner
208
+ * ☑ [reverse-proxy support](https://github.com/9001/copyparty#reverse-proxy)
215
209
  * upload
216
210
  * ☑ basic: plain multipart, ie6 support
217
211
  * ☑ [up2k](#uploading): js, resumable, multithreaded
218
212
  * unaffected by cloudflare's max-upload-size (100 MiB)
219
213
  * ☑ stash: simple PUT filedropper
214
+ * ☑ filename randomizer
215
+ * ☑ write-only folders
220
216
  * ☑ [unpost](#unpost): undo/delete accidental uploads
221
217
  * ☑ [self-destruct](#self-destruct) (specified server-side or client-side)
222
218
  * ☑ symlink/discard existing files (content-matching)
@@ -240,10 +236,15 @@ firewall-cmd --reload
240
236
  * ☑ [locate files by contents](#file-search)
241
237
  * ☑ search by name/path/date/size
242
238
  * ☑ [search by ID3-tags etc.](#searching)
239
+ * client support
240
+ * ☑ [folder sync](#folder-sync)
241
+ * ☑ [curl-friendly](https://user-images.githubusercontent.com/241032/215322619-ea5fd606-3654-40ad-94ee-2bc058647bb2.png)
243
242
  * markdown
244
243
  * ☑ [viewer](#markdown-viewer)
245
244
  * ☑ editor (sure why not)
246
245
 
246
+ PS: something missing? post any crazy ideas you've got as a [feature request](https://github.com/9001/copyparty/issues/new?assignees=9001&labels=enhancement&template=feature_request.md) or [discussion](https://github.com/9001/copyparty/discussions/new?category=ideas) 🤙
247
+
247
248
 
248
249
  ## testimonials
249
250
 
@@ -315,7 +316,7 @@ server notes:
315
316
 
316
317
  * iPhones: the volume control doesn't work because [apple doesn't want it to](https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html#//apple_ref/doc/uid/TP40009523-CH5-SW11)
317
318
  * *future workaround:* enable the equalizer, make it all-zero, and set a negative boost to reduce the volume
318
- * "future" because `AudioContext` is broken in the current iOS version (15.1), maybe one day...
319
+ * "future" because `AudioContext` can't maintain a stable playback speed in the current iOS version (15.7), maybe one day...
319
320
 
320
321
  * Windows: folders cannot be accessed if the name ends with `.`
321
322
  * python or windows bug
@@ -1139,13 +1140,15 @@ see the top of [./copyparty/web/browser.css](./copyparty/web/browser.css) where
1139
1140
 
1140
1141
  ## reverse-proxy
1141
1142
 
1142
- running copyparty next to other websites hosted on an existing webserver such as nginx or apache
1143
+ running copyparty next to other websites hosted on an existing webserver such as nginx, caddy, or apache
1143
1144
 
1144
1145
  you can either:
1145
1146
  * give copyparty its own domain or subdomain (recommended)
1146
1147
  * or do location-based proxying, using `--rp-loc=/stuff` to tell copyparty where it is mounted -- has a slight performance cost and higher chance of bugs
1147
1148
  * if copyparty says `incorrect --rp-loc or webserver config; expected vpath starting with [...]` it's likely because the webserver is stripping away the proxy location from the request URLs -- see the `ProxyPass` in the apache example below
1148
1149
 
1150
+ some reverse proxies (such as [Caddy](https://caddyserver.com/)) can automatically obtain a valid https/tls certificate for you, and some support HTTP/2 and QUIC which could be a nice speed boost
1151
+
1149
1152
  example webserver configs:
1150
1153
 
1151
1154
  * [nginx config](contrib/nginx/copyparty.conf) -- entire domain/subdomain
@@ -1223,7 +1226,7 @@ interact with copyparty using non-browser clients
1223
1226
  * `(printf 'PUT / HTTP/1.1\r\n\r\n'; cat movie.mkv) >/dev/tcp/127.0.0.1/3923`
1224
1227
 
1225
1228
  * python: [up2k.py](https://github.com/9001/copyparty/blob/hovudstraum/bin/up2k.py) is a command-line up2k client [(webm)](https://ocv.me/stuff/u2cli.webm)
1226
- * file uploads, file-search, folder sync, autoresume of aborted/broken uploads
1229
+ * file uploads, file-search, [folder sync](#folder-sync), autoresume of aborted/broken uploads
1227
1230
  * can be downloaded from copyparty: controlpanel -> connect -> [up2k.py](http://127.0.0.1:3923/.cpr/a/up2k.py)
1228
1231
  * see [./bin/README.md#up2kpy](bin/README.md#up2kpy)
1229
1232
 
@@ -1244,6 +1247,15 @@ you can provide passwords using header `PW: hunter2`, cookie `cppwd=hunter2`, ur
1244
1247
  NOTE: curl will not send the original filename if you use `-T` combined with url-params! Also, make sure to always leave a trailing slash in URLs unless you want to override the filename
1245
1248
 
1246
1249
 
1250
+ ## folder sync
1251
+
1252
+ sync folders to/from copyparty
1253
+
1254
+ the commandline uploader [up2k.py](https://github.com/9001/copyparty/tree/hovudstraum/bin#up2kpy) with `--dr` is the best way to sync a folder to copyparty; verifies checksums and does files in parallel, and deletes unexpected files on the server after upload has finished which makes file-renames really cheap (it'll rename serverside and skip uploading)
1255
+
1256
+ alternatively there is [rclone](./docs/rclone.md) which allows for bidirectional sync and is *way* more flexible (stream files straight from sftp/s3/gcs to copyparty for instance), although syncing to copyparty is about 5x slower than up2k.py if you have many small files in particular
1257
+
1258
+
1247
1259
  ## mount as drive
1248
1260
 
1249
1261
  a remote copyparty server as a local filesystem; go to the control-panel and click `connect` to see a list of commands to do that
@@ -1262,6 +1274,27 @@ alternatively, some alternatives roughly sorted by speed (unreproducible benchma
1262
1274
  most clients will fail to mount the root of a copyparty server unless there is a root volume (so you get the admin-panel instead of a browser when accessing it) -- in that case, mount a specific volume instead
1263
1275
 
1264
1276
 
1277
+ # android app
1278
+
1279
+ upload to copyparty with one tap
1280
+
1281
+ <a href="https://f-droid.org/packages/me.ocv.partyup/"><img src="https://ocv.me/fdroid.png" alt="Get it on F-Droid" height="50" /> '' <img src="https://img.shields.io/f-droid/v/me.ocv.partyup.svg" alt="f-droid version info" /></a> '' <a href="https://github.com/9001/party-up"><img src="https://img.shields.io/github/release/9001/party-up.svg?logo=github" alt="github version info" /></a>
1282
+
1283
+ the app is **NOT** the full copyparty server! just a basic upload client, nothing fancy yet
1284
+
1285
+ if you want to run the copyparty server on your android device, see [install on android](#install-on-android)
1286
+
1287
+
1288
+ # iOS shortcuts
1289
+
1290
+ there is no iPhone app, but the following shortcuts are almost as good:
1291
+
1292
+ * [upload to copyparty](https://www.icloud.com/shortcuts/41e98dd985cb4d3bb433222bc1e9e770) ([offline](https://github.com/9001/copyparty/raw/hovudstraum/contrib/ios/upload-to-copyparty.shortcut)) ([png](https://user-images.githubusercontent.com/241032/226118053-78623554-b0ed-482e-98e4-6d57ada58ea4.png)) based on the [original](https://www.icloud.com/shortcuts/ab415d5b4de3467b9ce6f151b439a5d7) by [Daedren](https://github.com/Daedren) (thx!)
1293
+ * can strip exif, upload files, pics, vids, links, clipboard
1294
+ * can download links and rehost the target file on copyparty (see first comment inside the shortcut)
1295
+ * pics become lowres if you share from gallery to shortcut, so better to launch the shortcut and pick stuff from there
1296
+
1297
+
1265
1298
  # performance
1266
1299
 
1267
1300
  defaults are usually fine - expect `8 GiB/s` download, `1 GiB/s` upload
@@ -1357,6 +1390,13 @@ by default, except for `GET` and `HEAD` operations, all requests must either:
1357
1390
  cors can be configured with `--acao` and `--acam`, or the protections entirely disabled with `--allow-csrf`
1358
1391
 
1359
1392
 
1393
+ ## https
1394
+
1395
+ both HTTP and HTTPS are accepted by default, but letting a [reverse proxy](#reverse-proxy) handle the https/tls/ssl would be better (probably more secure by default)
1396
+
1397
+ copyparty doesn't speak HTTP/2 or QUIC, so using a reverse proxy would solve that as well
1398
+
1399
+
1360
1400
  # recovering from crashes
1361
1401
 
1362
1402
  ## client crashes
@@ -1424,7 +1464,7 @@ these are standalone programs and will never be imported / evaluated by copypart
1424
1464
 
1425
1465
  the self-contained "binary" [copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/download/copyparty-sfx.py) will unpack itself and run copyparty, assuming you have python installed of course
1426
1466
 
1427
- you can reduce the sfx size by repacking it; see [./docs/devnotes.md#sfx-repack](#./docs/devnotes.md#sfx-repack)
1467
+ you can reduce the sfx size by repacking it; see [./docs/devnotes.md#sfx-repack](./docs/devnotes.md#sfx-repack)
1428
1468
 
1429
1469
 
1430
1470
  ## copyparty.exe
@@ -1,6 +1,6 @@
1
1
  copyparty/__init__.py,sha256=ZIYqHdNC97NeoBTkFDSZ6E8aAma1tfjLhbax9oQHl4U,1063
2
- copyparty/__main__.py,sha256=jAqX8JQUOR7gM3abRxBN6APX9jWbJhfzqviL6WQNHgU,66703
3
- copyparty/__version__.py,sha256=dHw4-LYVR58RwnOJ89WisiPIIMddmfJP8G-OvoBI1qI,247
2
+ copyparty/__main__.py,sha256=NeG2cQHE4uRQ02zHZ7gv-NAlRgmTWmVSslPH5Uk84NI,66925
3
+ copyparty/__version__.py,sha256=wp65Vl0D_UcBkVaU9A6sBpd0yYrElMXJHqgAUtnqjDM,248
4
4
  copyparty/authsrv.py,sha256=Sh793NWnpklcz1ZEj-pt0FISjx-_BZJ8fkWm5rbWKrA,62030
5
5
  copyparty/broker_mp.py,sha256=SEJT7qIH7L0YH0e1yHucsUuYJE5m3DKymO57070_UCs,3590
6
6
  copyparty/broker_mpw.py,sha256=GlSn4PRd_OqqeG39FiXgNvPzXVQW6UCiAcqmBSr2q6g,3200
@@ -9,8 +9,8 @@ copyparty/broker_util.py,sha256=CnX_LAhQQqouONcDLtVkVlcBX3Z6pWuKDQDmmbHGEg4,1489
9
9
  copyparty/cfg.py,sha256=ukauOEs_WKxzkt4MzIfLAU9eKGq9ZGcyIKSFMScc8xg,6436
10
10
  copyparty/dxml.py,sha256=lZpg-kn-kQsXRtNY1n6fRaS-b7uXzMCyv8ovKnhZcZc,1548
11
11
  copyparty/fsutil.py,sha256=c4fTvmclKbVABNsjU4rGddsjCgRwi9YExAyo-06ATc8,3932
12
- copyparty/ftpd.py,sha256=BiJd3eQfxr7Fdspmt3-829cox62IqCzmwzqT4l-3X_M,13815
13
- copyparty/httpcli.py,sha256=OcI0Vt0mulgSpwVIzOiKx8nqRIv_TswCl8pJnLqgZSs,119171
12
+ copyparty/ftpd.py,sha256=pPLkQTNmqfZRGfzALzZApEj6N8l3yo24RqDGDqISeyE,13841
13
+ copyparty/httpcli.py,sha256=uU13dj9SzBpfdzfEceuqIYkxhm7IqUd_n3BdacVaUzI,120318
14
14
  copyparty/httpconn.py,sha256=LXyJphs-FtyhFeDF-YUGVXKGf9KvHA86UzVx4FvRZo0,6674
15
15
  copyparty/httpsrv.py,sha256=EQsGZgKvN_D_eZ-XbFPZgFXTQc2Y2EXCo2qQhfWbf_4,14143
16
16
  copyparty/ico.py,sha256=eP_FGZEsnCLr6Q1ypITp7kbMKtQiDeROv0ydrbEKfIY,2643
@@ -25,9 +25,9 @@ copyparty/svchub.py,sha256=gqrIWzUT7Cz4Fd_lK0DKd5dLvNQuM0_YhJzpgXeUE78,22903
25
25
  copyparty/szip.py,sha256=o8NzYcqUUjg2MPvESa4VnAaANqD_JofBSr7Sb7eWu4I,8166
26
26
  copyparty/tcpsrv.py,sha256=ccUXnAa7IeRPWaaTAuOVcSgdBetlHVoJozsTrZcFx8Q,16633
27
27
  copyparty/th_cli.py,sha256=hcb-GGN7krnHF3LIp3tDix_OYwXnCRoTpsiO0TaDqOg,3826
28
- copyparty/th_srv.py,sha256=Y1Z51K91D6lBqq810sSu1wltQnruPvhJnhliX5rAj6k,20969
29
- copyparty/u2idx.py,sha256=MeP1PQih-tmM6dRkHIzl02M1LLiPaJXZM_4i8v_gwtM,10474
30
- copyparty/up2k.py,sha256=JUz1_QC4SlVjkchpL2B004JfiZzGHcpNXqudymhWuh0,121053
28
+ copyparty/th_srv.py,sha256=O7SJDLBx6pcRUiOR4G6Rqpi7FGthekedGTK3CXIFi_E,22119
29
+ copyparty/u2idx.py,sha256=n3DSFc67tIk-Jn8-Z5EEG8Xb_qv48KomJFYvoXlmV-U,10493
30
+ copyparty/up2k.py,sha256=0I-YREZDULliJTuxyqhz2j1XT2QnM3da1ojc31ZY_0Y,121148
31
31
  copyparty/util.py,sha256=hAZ4AN5rMQgDPYKiRdA3Qh-dZ0cBsaODR-mNrSuNwzw,71782
32
32
  copyparty/bos/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
33
  copyparty/bos/bos.py,sha256=Md2RwMauEdOS7SfK5aiHby8T1KgQoTaoEjVCYU98_4I,1560
@@ -50,9 +50,9 @@ copyparty/stolen/ifaddr/_posix.py,sha256=-67NdfGrCktfQPakT2fLbjl2U00QMvyBGkSvrUu
50
50
  copyparty/stolen/ifaddr/_shared.py,sha256=cJACl8cOxQ-HSYphZTzKMAjAx_TAFyJwUPjfD102Xqw,6111
51
51
  copyparty/stolen/ifaddr/_win32.py,sha256=EE-QyoBgeB7lYQ6z62VjXNaRozaYfCkaJBHGNA8QtZM,4026
52
52
  copyparty/web/baguettebox.js.gz,sha256=Irf0YDki85Pgke63z_TZws92UiGtrzpyg-39eguYAho,7282
53
- copyparty/web/browser.css.gz,sha256=qCx-jnalAyQsQsztp_B9ZsY3zxxUwlq-W2oRq2HX9Es,10896
54
- copyparty/web/browser.html,sha256=kk3Hro8vOMa4oxVrw1bZC9KJT9w7aDy-Bu8pHhFvXQY,5264
55
- copyparty/web/browser.js.gz,sha256=eRC7Wr3jQJBSs6CwhUnsB25_NuUeXri_C0cf4CbOqcg,57106
53
+ copyparty/web/browser.css.gz,sha256=k6iCbhvebd54n3NMGLPtltG9Ude8QyomZKI1bgRjQNc,10925
54
+ copyparty/web/browser.html,sha256=561cy72h48x7g6_ZHXsAS3xYqnNwrXB1KK9VBVBqio8,5286
55
+ copyparty/web/browser.js.gz,sha256=CLCD-X_N1K7_7ljSwD5jno-_-NpjuWP0ChzFAUeMyfc,57351
56
56
  copyparty/web/browser2.html,sha256=3kR3QiDXYqtAo7gOoBtdTP3eRvibUCZHVVAbmAfaAVU,1604
57
57
  copyparty/web/cf.html,sha256=AQSPDFq1-Ww-9SyVLZtjVPfl054aqXs6svi5cQBlAdA,585
58
58
  copyparty/web/copyparty.gif,sha256=S1YS9GrKPbueEob_yTeWqzDcDoRXU_Z209BJ4YF-9pQ,126
@@ -70,11 +70,11 @@ copyparty/web/msg.html,sha256=JQFDP-jOhBM4pln5bOyncC9lJ6YpN2TMIyNn-bLNSqE,898
70
70
  copyparty/web/splash.css.gz,sha256=dVMI8zrGO2glmPDS0QKhVmBgExe3p-QdUUIJ5EUWdrA,927
71
71
  copyparty/web/splash.html,sha256=tqCewuM2HMkkR7MH8ijgtAM1LHqlawqJgTGvG7NzECY,3741
72
72
  copyparty/web/splash.js.gz,sha256=2VuxIx4y0hyW9I5NWG83Bcabk5NJDftQt7a_j9Gb5nY,1235
73
- copyparty/web/svcs.html,sha256=yf-2pYOKa7EEmFbY_SGjnAjhzCH4DlynbcRHe6GicqY,9354
73
+ copyparty/web/svcs.html,sha256=B49Z5EiMrDqREbfJwqUTehRo1aht7h0uLMkHBA1w2wo,9399
74
74
  copyparty/web/svcs.js.gz,sha256=SSVKYYgZkEKMdDLjekvcXB00v-rCVJXh2GD_YtCvu7c,519
75
75
  copyparty/web/ui.css.gz,sha256=kU3LGyd2MpBzbp1_7Dy1_11V9Nw7QPuNQlpLB_z0uEk,2377
76
76
  copyparty/web/up2k.js.gz,sha256=fGYvDuq34kVz16occIYU9KUQZF9ZemcQLI57o2_DmK4,21538
77
- copyparty/web/util.js.gz,sha256=fPwQAR-A6Wuqk-OOLougKta7vYHJxrp3An0sPh4u1UI,12555
77
+ copyparty/web/util.js.gz,sha256=zDKTUnRffdMaJx4WJd-GYK0S_4OpbcWOMjSOB_mVNYs,12616
78
78
  copyparty/web/w.hash.js.gz,sha256=07eXr3ktdGNmFBLpqWCp6LsAx8AqIyy1KDNz2-r3p8U,1059
79
79
  copyparty/web/a/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
80
80
  copyparty/web/a/partyfuse.py,sha256=mJKqR8LjX19P4Knqa02ob5ogwPVtJXSqxkEEGZU0r60,32276
@@ -97,13 +97,13 @@ copyparty/web/deps/prismd.css.gz,sha256=hzzspI_ptCygzmsIp9rKsf1M4yU12Ma7TfE-wyoX
97
97
  copyparty/web/deps/scp.woff2,sha256=w99BDU5i8MukkMEL-iW0YO9H4vFFZSPWxbkH70ytaAg,8612
98
98
  copyparty/web/deps/sha512.ac.js.gz,sha256=IzAmZIkSyMbnn7GK3k5PW085PNcZxtk_u4UW_E1d6ek,7043
99
99
  copyparty/web/deps/sha512.hw.js.gz,sha256=0xJaw75Tghoblu72C2h4YoU1izSR99mBtDMoGqZ3xvs,8119
100
- copyparty-1.6.8.data/data/share/doc/copyparty/LICENSE,sha256=yyzj1id78vWoLs8zbMRJY7xkkLz0lv-9dfyeIauqdfM,1059
101
- copyparty-1.6.8.data/data/share/doc/copyparty/README.md,sha256=XatPvJdgIlQm40TuFE0bWAlMoS5vthbPlW1OlNm5EAk,80081
102
- copyparty-1.6.8.data/scripts/partyfuse.py,sha256=zhVQm5m-pWcUyo4aOvzZveOMeLJSY7gB2UGFYXp10XM,32262
103
- copyparty-1.6.8.data/scripts/up2k.py,sha256=6J3zq9wZPgRTti32p2d7kg5YHfZvlu4ZZiElU3492bU,35116
104
- copyparty-1.6.8.dist-info/LICENSE,sha256=yyzj1id78vWoLs8zbMRJY7xkkLz0lv-9dfyeIauqdfM,1059
105
- copyparty-1.6.8.dist-info/METADATA,sha256=Ifz6caHfQ9Ztdibmb5gQi37HHdX4Y4Us9NNFllobnCk,82167
106
- copyparty-1.6.8.dist-info/WHEEL,sha256=bb2Ot9scclHKMOLDEHY6B2sicWOgugjFKaJsT7vwMQo,110
107
- copyparty-1.6.8.dist-info/entry_points.txt,sha256=v3KsE-NQ_WGZkl78BlR8lZ4oHWhGbtjaEw3-iGXLfLQ,54
108
- copyparty-1.6.8.dist-info/top_level.txt,sha256=LnYUPsDyk-8kFgM6YJLG4h820DQekn81cObKSu9g-sI,10
109
- copyparty-1.6.8.dist-info/RECORD,,
100
+ copyparty-1.6.10.data/data/share/doc/copyparty/LICENSE,sha256=yyzj1id78vWoLs8zbMRJY7xkkLz0lv-9dfyeIauqdfM,1059
101
+ copyparty-1.6.10.data/data/share/doc/copyparty/README.md,sha256=y3QDX75CclBacxOCdR9dju63UNk4AjxjXsP9rz_auKg,83126
102
+ copyparty-1.6.10.data/scripts/partyfuse.py,sha256=zhVQm5m-pWcUyo4aOvzZveOMeLJSY7gB2UGFYXp10XM,32262
103
+ copyparty-1.6.10.data/scripts/up2k.py,sha256=6J3zq9wZPgRTti32p2d7kg5YHfZvlu4ZZiElU3492bU,35116
104
+ copyparty-1.6.10.dist-info/LICENSE,sha256=yyzj1id78vWoLs8zbMRJY7xkkLz0lv-9dfyeIauqdfM,1059
105
+ copyparty-1.6.10.dist-info/METADATA,sha256=7TfK1Wjh9RlVFpRP1C9sS1UHNtoFw_yMCnDPsWGPbhU,85213
106
+ copyparty-1.6.10.dist-info/WHEEL,sha256=bb2Ot9scclHKMOLDEHY6B2sicWOgugjFKaJsT7vwMQo,110
107
+ copyparty-1.6.10.dist-info/entry_points.txt,sha256=v3KsE-NQ_WGZkl78BlR8lZ4oHWhGbtjaEw3-iGXLfLQ,54
108
+ copyparty-1.6.10.dist-info/top_level.txt,sha256=LnYUPsDyk-8kFgM6YJLG4h820DQekn81cObKSu9g-sI,10
109
+ copyparty-1.6.10.dist-info/RECORD,,