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 +2 -1
- copyparty/__version__.py +2 -2
- copyparty/ftpd.py +1 -0
- copyparty/httpcli.py +55 -23
- copyparty/th_srv.py +33 -1
- copyparty/u2idx.py +8 -7
- copyparty/up2k.py +5 -2
- copyparty/web/browser.css.gz +0 -0
- copyparty/web/browser.html +1 -0
- copyparty/web/browser.js.gz +0 -0
- copyparty/web/svcs.html +3 -3
- copyparty/web/util.js.gz +0 -0
- {copyparty-1.6.8.data → copyparty-1.6.10.data}/data/share/doc/copyparty/README.md +62 -22
- {copyparty-1.6.8.dist-info → copyparty-1.6.10.dist-info}/METADATA +63 -23
- {copyparty-1.6.8.dist-info → copyparty-1.6.10.dist-info}/RECORD +22 -22
- {copyparty-1.6.8.data → copyparty-1.6.10.data}/data/share/doc/copyparty/LICENSE +0 -0
- {copyparty-1.6.8.data → copyparty-1.6.10.data}/scripts/partyfuse.py +0 -0
- {copyparty-1.6.8.data → copyparty-1.6.10.data}/scripts/up2k.py +0 -0
- {copyparty-1.6.8.dist-info → copyparty-1.6.10.dist-info}/LICENSE +0 -0
- {copyparty-1.6.8.dist-info → copyparty-1.6.10.dist-info}/WHEEL +0 -0
- {copyparty-1.6.8.dist-info → copyparty-1.6.10.dist-info}/entry_points.txt +0 -0
- {copyparty-1.6.8.dist-info → copyparty-1.6.10.dist-info}/top_level.txt +0 -0
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
copyparty/ftpd.py
CHANGED
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 "
|
778
|
-
return self.
|
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
|
-
|
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 (
|
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
|
-
|
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
|
-
|
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
|
2896
|
-
v =
|
2897
|
-
|
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"
|
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
|
-
|
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
|
-
|
1256
|
-
if not
|
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
|
|
copyparty/web/browser.css.gz
CHANGED
Binary file
|
copyparty/web/browser.html
CHANGED
copyparty/web/browser.js.gz
CHANGED
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=
|
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=
|
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
|
-
|
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
|
-
|
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`
|
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](
|
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.
|
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
|
-
|
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
|
-
|
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`
|
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](
|
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=
|
3
|
-
copyparty/__version__.py,sha256=
|
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=
|
13
|
-
copyparty/httpcli.py,sha256=
|
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=
|
29
|
-
copyparty/u2idx.py,sha256=
|
30
|
-
copyparty/up2k.py,sha256=
|
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=
|
54
|
-
copyparty/web/browser.html,sha256=
|
55
|
-
copyparty/web/browser.js.gz,sha256=
|
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=
|
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=
|
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.
|
101
|
-
copyparty-1.6.
|
102
|
-
copyparty-1.6.
|
103
|
-
copyparty-1.6.
|
104
|
-
copyparty-1.6.
|
105
|
-
copyparty-1.6.
|
106
|
-
copyparty-1.6.
|
107
|
-
copyparty-1.6.
|
108
|
-
copyparty-1.6.
|
109
|
-
copyparty-1.6.
|
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,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|