copyparty 1.15.9__py3-none-any.whl → 1.15.10__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 +5 -0
- copyparty/__version__.py +2 -2
- copyparty/authsrv.py +3 -4
- copyparty/httpcli.py +127 -71
- copyparty/svchub.py +31 -3
- copyparty/up2k.py +6 -5
- copyparty/util.py +34 -6
- copyparty/web/a/partyfuse.py +1 -1
- copyparty/web/browser.js.gz +0 -0
- copyparty/web/splash.html +12 -3
- copyparty/web/splash.js.gz +0 -0
- {copyparty-1.15.9.dist-info → copyparty-1.15.10.dist-info}/METADATA +5 -1
- {copyparty-1.15.9.dist-info → copyparty-1.15.10.dist-info}/RECORD +17 -17
- {copyparty-1.15.9.dist-info → copyparty-1.15.10.dist-info}/LICENSE +0 -0
- {copyparty-1.15.9.dist-info → copyparty-1.15.10.dist-info}/WHEEL +0 -0
- {copyparty-1.15.9.dist-info → copyparty-1.15.10.dist-info}/entry_points.txt +0 -0
- {copyparty-1.15.9.dist-info → copyparty-1.15.10.dist-info}/top_level.txt +0 -0
copyparty/__main__.py
CHANGED
@@ -1299,6 +1299,7 @@ def add_logging(ap):
|
|
1299
1299
|
ap2.add_argument("--log-conn", action="store_true", help="debug: print tcp-server msgs")
|
1300
1300
|
ap2.add_argument("--log-htp", action="store_true", help="debug: print http-server threadpool scaling")
|
1301
1301
|
ap2.add_argument("--ihead", metavar="HEADER", type=u, action='append', help="print request \033[33mHEADER\033[0m; [\033[32m*\033[0m]=all")
|
1302
|
+
ap2.add_argument("--ohead", metavar="HEADER", type=u, action='append', help="print response \033[33mHEADER\033[0m; [\033[32m*\033[0m]=all")
|
1302
1303
|
ap2.add_argument("--lf-url", metavar="RE", type=u, default=r"^/\.cpr/|\?th=[wj]$|/\.(_|ql_|DS_Store$|localized$)", help="dont log URLs matching regex \033[33mRE\033[0m")
|
1303
1304
|
|
1304
1305
|
|
@@ -1452,6 +1453,7 @@ def add_ui(ap, retry):
|
|
1452
1453
|
ap2.add_argument("--pb-url", metavar="URL", type=u, default="https://github.com/9001/copyparty", help="powered-by link; disable with \033[33m-np\033[0m")
|
1453
1454
|
ap2.add_argument("--ver", action="store_true", help="show version on the control panel (incompatible with \033[33m-nb\033[0m)")
|
1454
1455
|
ap2.add_argument("--k304", metavar="NUM", type=int, default=0, help="configure the option to enable/disable k304 on the controlpanel (workaround for buggy reverse-proxies); [\033[32m0\033[0m] = hidden and default-off, [\033[32m1\033[0m] = visible and default-off, [\033[32m2\033[0m] = visible and default-on")
|
1456
|
+
ap2.add_argument("--no304", metavar="NUM", type=int, default=0, help="configure the option to enable/disable no304 on the controlpanel (workaround for buggy caching in browsers); [\033[32m0\033[0m] = hidden and default-off, [\033[32m1\033[0m] = visible and default-off, [\033[32m2\033[0m] = visible and default-on")
|
1455
1457
|
ap2.add_argument("--md-sbf", metavar="FLAGS", type=u, default="downloads forms popups scripts top-navigation-by-user-activation", help="list of capabilities to ALLOW for README.md docs (volflag=md_sbf); see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox")
|
1456
1458
|
ap2.add_argument("--lg-sbf", metavar="FLAGS", type=u, default="downloads forms popups scripts top-navigation-by-user-activation", help="list of capabilities to ALLOW for prologue/epilogue docs (volflag=lg_sbf)")
|
1457
1459
|
ap2.add_argument("--no-sb-md", action="store_true", help="don't sandbox README/PREADME.md documents (volflags: no_sb_md | sb_md)")
|
@@ -1749,6 +1751,9 @@ def main(argv = None) :
|
|
1749
1751
|
if al.ihead:
|
1750
1752
|
al.ihead = [x.lower() for x in al.ihead]
|
1751
1753
|
|
1754
|
+
if al.ohead:
|
1755
|
+
al.ohead = [x.lower() for x in al.ohead]
|
1756
|
+
|
1752
1757
|
if HAVE_SSL:
|
1753
1758
|
if al.ssl_ver:
|
1754
1759
|
configure_ssl_ver(al)
|
copyparty/__version__.py
CHANGED
copyparty/authsrv.py
CHANGED
@@ -545,15 +545,14 @@ class VFS(object):
|
|
545
545
|
return self._get_dbv(vrem)
|
546
546
|
|
547
547
|
shv, srem = src
|
548
|
-
return shv
|
548
|
+
return shv._get_dbv(vjoin(srem, vrem))
|
549
549
|
|
550
550
|
def _get_dbv(self, vrem ) :
|
551
551
|
dbv = self.dbv
|
552
552
|
if not dbv:
|
553
553
|
return self, vrem
|
554
554
|
|
555
|
-
|
556
|
-
vrem = "/".join([x for x in tv if x])
|
555
|
+
vrem = vjoin(self.vpath[len(dbv.vpath) :].lstrip("/"), vrem)
|
557
556
|
return dbv, vrem
|
558
557
|
|
559
558
|
def canonical(self, rem , resolve = True) :
|
@@ -2633,7 +2632,7 @@ class AuthSrv(object):
|
|
2633
2632
|
]
|
2634
2633
|
|
2635
2634
|
csv = set("i p th_covers zm_on zm_off zs_on zs_off".split())
|
2636
|
-
zs = "c ihead mtm mtp on403 on404 xad xar xau xiu xban xbd xbr xbu xm"
|
2635
|
+
zs = "c ihead ohead mtm mtp on403 on404 xad xar xau xiu xban xbd xbr xbu xm"
|
2637
2636
|
lst = set(zs.split())
|
2638
2637
|
askip = set("a v c vc cgen exp_lg exp_md theme".split())
|
2639
2638
|
fskip = set("exp_lg exp_md mv_re_r mv_re_t rm_re_r rm_re_t".split())
|
copyparty/httpcli.py
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
from __future__ import print_function, unicode_literals
|
3
3
|
|
4
4
|
import argparse # typechk
|
5
|
-
import calendar
|
6
5
|
import copy
|
7
6
|
import errno
|
8
7
|
import gzip
|
@@ -19,7 +18,6 @@ import threading # typechk
|
|
19
18
|
import time
|
20
19
|
import uuid
|
21
20
|
from datetime import datetime
|
22
|
-
from email.utils import parsedate
|
23
21
|
from operator import itemgetter
|
24
22
|
|
25
23
|
import jinja2 # typechk
|
@@ -107,6 +105,7 @@ from .util import (
|
|
107
105
|
unquotep,
|
108
106
|
vjoin,
|
109
107
|
vol_san,
|
108
|
+
vroots,
|
110
109
|
vsplit,
|
111
110
|
wrename,
|
112
111
|
wunlink,
|
@@ -123,6 +122,11 @@ _ = (argparse, threading)
|
|
123
122
|
|
124
123
|
NO_CACHE = {"Cache-Control": "no-cache"}
|
125
124
|
|
125
|
+
ALL_COOKIES = "k304 no304 js idxh dots cppwd cppws".split()
|
126
|
+
|
127
|
+
H_CONN_KEEPALIVE = "Connection: Keep-Alive"
|
128
|
+
H_CONN_CLOSE = "Connection: Close"
|
129
|
+
|
126
130
|
LOGUES = [[0, ".prologue.html"], [1, ".epilogue.html"]]
|
127
131
|
|
128
132
|
READMES = [[0, ["preadme.md", "PREADME.md"]], [1, ["readme.md", "README.md"]]]
|
@@ -787,11 +791,11 @@ class HttpCli(object):
|
|
787
791
|
|
788
792
|
def k304(self) :
|
789
793
|
k304 = self.cookies.get("k304")
|
790
|
-
return (
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
)
|
794
|
+
return k304 == "y" or (self.args.k304 == 2 and k304 != "n")
|
795
|
+
|
796
|
+
def no304(self) :
|
797
|
+
no304 = self.cookies.get("no304")
|
798
|
+
return no304 == "y" or (self.args.no304 == 2 and no304 != "n")
|
795
799
|
|
796
800
|
def _build_html_head(self, maybe_html , kv ) :
|
797
801
|
html = str(maybe_html)
|
@@ -826,25 +830,28 @@ class HttpCli(object):
|
|
826
830
|
) :
|
827
831
|
response = ["%s %s %s" % (self.http_ver, status, HTTPCODE[status])]
|
828
832
|
|
829
|
-
if length is not None:
|
830
|
-
response.append("Content-Length: " + unicode(length))
|
831
|
-
|
832
|
-
if status == 304 and self.k304():
|
833
|
-
self.keepalive = False
|
834
|
-
|
835
|
-
# close if unknown length, otherwise take client's preference
|
836
|
-
response.append("Connection: " + ("Keep-Alive" if self.keepalive else "Close"))
|
837
|
-
response.append("Date: " + formatdate())
|
838
|
-
|
839
833
|
# headers{} overrides anything set previously
|
840
834
|
if headers:
|
841
835
|
self.out_headers.update(headers)
|
842
836
|
|
843
|
-
|
844
|
-
|
845
|
-
|
837
|
+
if status == 304:
|
838
|
+
self.out_headers.pop("Content-Length", None)
|
839
|
+
self.out_headers.pop("Content-Type", None)
|
840
|
+
self.out_headerlist.clear()
|
841
|
+
if self.k304():
|
842
|
+
self.keepalive = False
|
843
|
+
else:
|
844
|
+
if length is not None:
|
845
|
+
response.append("Content-Length: " + unicode(length))
|
846
|
+
|
847
|
+
if mime:
|
848
|
+
self.out_headers["Content-Type"] = mime
|
849
|
+
elif "Content-Type" not in self.out_headers:
|
850
|
+
self.out_headers["Content-Type"] = "text/html; charset=utf-8"
|
846
851
|
|
847
|
-
|
852
|
+
# close if unknown length, otherwise take client's preference
|
853
|
+
response.append(H_CONN_KEEPALIVE if self.keepalive else H_CONN_CLOSE)
|
854
|
+
response.append("Date: " + formatdate())
|
848
855
|
|
849
856
|
for k, zs in list(self.out_headers.items()) + self.out_headerlist:
|
850
857
|
response.append("%s: %s" % (k, zs))
|
@@ -858,6 +865,19 @@ class HttpCli(object):
|
|
858
865
|
self.cbonk(self.conn.hsrv.gmal, zs, "cc_hdr", "Cc in out-hdr")
|
859
866
|
raise Pebkac(999)
|
860
867
|
|
868
|
+
if self.args.ohead and self.do_log:
|
869
|
+
keys = self.args.ohead
|
870
|
+
if "*" in keys:
|
871
|
+
lines = response[1:]
|
872
|
+
else:
|
873
|
+
lines = []
|
874
|
+
for zs in response[1:]:
|
875
|
+
if zs.split(":")[0].lower() in keys:
|
876
|
+
lines.append(zs)
|
877
|
+
for zs in lines:
|
878
|
+
hk, hv = zs.split(": ")
|
879
|
+
self.log("[O] {}: \033[33m[{}]".format(hk, hv), 5)
|
880
|
+
|
861
881
|
response.append("\r\n")
|
862
882
|
try:
|
863
883
|
self.s.sendall("\r\n".join(response).encode("utf-8"))
|
@@ -937,13 +957,14 @@ class HttpCli(object):
|
|
937
957
|
|
938
958
|
lines = [
|
939
959
|
"%s %s %s" % (self.http_ver or "HTTP/1.1", status, HTTPCODE[status]),
|
940
|
-
|
960
|
+
H_CONN_CLOSE,
|
941
961
|
]
|
942
962
|
|
943
963
|
if body:
|
944
964
|
lines.append("Content-Length: " + unicode(len(body)))
|
945
965
|
|
946
|
-
|
966
|
+
lines.append("\r\n")
|
967
|
+
self.s.sendall("\r\n".join(lines).encode("utf-8") + body)
|
947
968
|
|
948
969
|
def urlq(self, add , rm ) :
|
949
970
|
"""
|
@@ -1177,12 +1198,6 @@ class HttpCli(object):
|
|
1177
1198
|
if "stack" in self.uparam:
|
1178
1199
|
return self.tx_stack()
|
1179
1200
|
|
1180
|
-
if "ups" in self.uparam:
|
1181
|
-
return self.tx_ups()
|
1182
|
-
|
1183
|
-
if "k304" in self.uparam:
|
1184
|
-
return self.set_k304()
|
1185
|
-
|
1186
1201
|
if "setck" in self.uparam:
|
1187
1202
|
return self.setck()
|
1188
1203
|
|
@@ -1198,6 +1213,10 @@ class HttpCli(object):
|
|
1198
1213
|
if "h" in self.uparam:
|
1199
1214
|
return self.tx_mounts()
|
1200
1215
|
|
1216
|
+
if "ups" in self.uparam:
|
1217
|
+
# vpath is used for share translation
|
1218
|
+
return self.tx_ups()
|
1219
|
+
|
1201
1220
|
if "rss" in self.uparam:
|
1202
1221
|
return self.tx_rss()
|
1203
1222
|
|
@@ -2380,6 +2399,15 @@ class HttpCli(object):
|
|
2380
2399
|
if "purl" in ret:
|
2381
2400
|
ret["purl"] = self.args.SR + ret["purl"]
|
2382
2401
|
|
2402
|
+
if self.args.shr and self.vpath.startswith(self.args.shr1):
|
2403
|
+
# strip common suffix (uploader's folder structure)
|
2404
|
+
vp_req, vp_vfs = vroots(self.vpath, vjoin(dbv.vpath, vrem))
|
2405
|
+
if not ret["purl"].startswith(vp_vfs):
|
2406
|
+
t = "share-mapping failed; req=[%s] dbv=[%s] vrem=[%s] n1=[%s] n2=[%s] purl=[%s]"
|
2407
|
+
zt = (self.vpath, dbv.vpath, vrem, vp_req, vp_vfs, ret["purl"])
|
2408
|
+
raise Pebkac(500, t % zt)
|
2409
|
+
ret["purl"] = vp_req + ret["purl"][len(vp_vfs) :]
|
2410
|
+
|
2383
2411
|
ret = json.dumps(ret)
|
2384
2412
|
self.log(ret)
|
2385
2413
|
self.reply(ret.encode("utf-8"), mime="application/json")
|
@@ -2472,7 +2500,11 @@ class HttpCli(object):
|
|
2472
2500
|
chashes.append(siblings[n : n + clen])
|
2473
2501
|
|
2474
2502
|
vfs, _ = self.asrv.vfs.get(self.vpath, self.uname, False, True)
|
2475
|
-
ptop =
|
2503
|
+
ptop = vfs.get_dbv("")[0].realpath
|
2504
|
+
# if this is a share, then get_dbv has been overridden to return
|
2505
|
+
# the dbv (which does not exist as a property). And its realpath
|
2506
|
+
# could point into the middle of its origin vfs node, meaning it
|
2507
|
+
# is not necessarily registered with up2k, so get_dbv is crucial
|
2476
2508
|
|
2477
2509
|
broker = self.conn.hsrv.broker
|
2478
2510
|
x = broker.ask("up2k.handle_chunks", ptop, wark, chashes)
|
@@ -3378,25 +3410,29 @@ class HttpCli(object):
|
|
3378
3410
|
self.reply(response.encode("utf-8"))
|
3379
3411
|
return True
|
3380
3412
|
|
3381
|
-
def _chk_lastmod(self, file_ts )
|
3413
|
+
def _chk_lastmod(self, file_ts ) :
|
3414
|
+
# ret: lastmod, do_send, can_range
|
3382
3415
|
file_lastmod = formatdate(file_ts)
|
3383
|
-
|
3384
|
-
if
|
3385
|
-
|
3386
|
-
|
3387
|
-
|
3388
|
-
|
3389
|
-
|
3390
|
-
|
3391
|
-
|
3392
|
-
|
3393
|
-
|
3394
|
-
|
3395
|
-
|
3396
|
-
|
3397
|
-
|
3416
|
+
c_ifrange = self.headers.get("if-range")
|
3417
|
+
c_lastmod = self.headers.get("if-modified-since")
|
3418
|
+
|
3419
|
+
if not c_ifrange and not c_lastmod:
|
3420
|
+
return file_lastmod, True, True
|
3421
|
+
|
3422
|
+
if c_ifrange and c_ifrange != file_lastmod:
|
3423
|
+
t = "sending entire file due to If-Range; cli(%s) file(%s)"
|
3424
|
+
self.log(t % (c_ifrange, file_lastmod), 6)
|
3425
|
+
return file_lastmod, True, False
|
3426
|
+
|
3427
|
+
do_send = c_lastmod != file_lastmod
|
3428
|
+
if do_send and c_lastmod:
|
3429
|
+
t = "sending body due to If-Modified-Since cli(%s) file(%s)"
|
3430
|
+
self.log(t % (c_lastmod, file_lastmod), 6)
|
3431
|
+
elif not do_send and self.no304():
|
3432
|
+
do_send = True
|
3433
|
+
self.log("sending body due to no304")
|
3398
3434
|
|
3399
|
-
return file_lastmod, True
|
3435
|
+
return file_lastmod, do_send, True
|
3400
3436
|
|
3401
3437
|
def _use_dirkey(self, vn , ap ) :
|
3402
3438
|
if self.can_read or not self.can_get:
|
@@ -3546,7 +3582,7 @@ class HttpCli(object):
|
|
3546
3582
|
# if-modified
|
3547
3583
|
|
3548
3584
|
if file_ts > 0:
|
3549
|
-
file_lastmod, do_send = self._chk_lastmod(int(file_ts))
|
3585
|
+
file_lastmod, do_send, _ = self._chk_lastmod(int(file_ts))
|
3550
3586
|
self.out_headers["Last-Modified"] = file_lastmod
|
3551
3587
|
if not do_send:
|
3552
3588
|
status = 304
|
@@ -3708,7 +3744,7 @@ class HttpCli(object):
|
|
3708
3744
|
#
|
3709
3745
|
# if-modified
|
3710
3746
|
|
3711
|
-
file_lastmod, do_send = self._chk_lastmod(int(file_ts))
|
3747
|
+
file_lastmod, do_send, can_range = self._chk_lastmod(int(file_ts))
|
3712
3748
|
self.out_headers["Last-Modified"] = file_lastmod
|
3713
3749
|
if not do_send:
|
3714
3750
|
status = 304
|
@@ -3752,7 +3788,14 @@ class HttpCli(object):
|
|
3752
3788
|
|
3753
3789
|
# let's not support 206 with compression
|
3754
3790
|
# and multirange / multipart is also not-impl (mostly because calculating contentlength is a pain)
|
3755
|
-
if
|
3791
|
+
if (
|
3792
|
+
do_send
|
3793
|
+
and not is_compressed
|
3794
|
+
and hrange
|
3795
|
+
and can_range
|
3796
|
+
and file_sz
|
3797
|
+
and "," not in hrange
|
3798
|
+
):
|
3756
3799
|
try:
|
3757
3800
|
if not hrange.lower().startswith("bytes"):
|
3758
3801
|
raise Exception()
|
@@ -4223,7 +4266,7 @@ class HttpCli(object):
|
|
4223
4266
|
sz_md = len(lead) + len(fullfile)
|
4224
4267
|
|
4225
4268
|
file_ts = int(max(ts_md, self.E.t0))
|
4226
|
-
file_lastmod, do_send = self._chk_lastmod(file_ts)
|
4269
|
+
file_lastmod, do_send, _ = self._chk_lastmod(file_ts)
|
4227
4270
|
self.out_headers["Last-Modified"] = file_lastmod
|
4228
4271
|
self.out_headers.update(NO_CACHE)
|
4229
4272
|
status = 200 if do_send else 304
|
@@ -4409,7 +4452,7 @@ class HttpCli(object):
|
|
4409
4452
|
rvol=rvol,
|
4410
4453
|
wvol=wvol,
|
4411
4454
|
avol=avol,
|
4412
|
-
in_shr=self.args.shr and self.vpath.startswith(self.args.
|
4455
|
+
in_shr=self.args.shr and self.vpath.startswith(self.args.shr1),
|
4413
4456
|
vstate=vstate,
|
4414
4457
|
ups=ups,
|
4415
4458
|
scanning=vs["scanning"],
|
@@ -4419,7 +4462,9 @@ class HttpCli(object):
|
|
4419
4462
|
dbwt=vs["dbwt"],
|
4420
4463
|
url_suf=suf,
|
4421
4464
|
k304=self.k304(),
|
4465
|
+
no304=self.no304(),
|
4422
4466
|
k304vis=self.args.k304 > 0,
|
4467
|
+
no304vis=self.args.no304 > 0,
|
4423
4468
|
ver=S_VERSION if self.args.ver else "",
|
4424
4469
|
chpw=self.args.chpw and self.uname != "*",
|
4425
4470
|
ahttps="" if self.is_https else "https://" + self.host + self.req,
|
@@ -4427,29 +4472,21 @@ class HttpCli(object):
|
|
4427
4472
|
self.reply(html.encode("utf-8"))
|
4428
4473
|
return True
|
4429
4474
|
|
4430
|
-
def set_k304(self) :
|
4431
|
-
v = self.uparam["k304"].lower()
|
4432
|
-
if v in "yn":
|
4433
|
-
dur = 86400 * 299
|
4434
|
-
else:
|
4435
|
-
dur = 0
|
4436
|
-
v = "x"
|
4437
|
-
|
4438
|
-
ck = gencookie("k304", v, self.args.R, False, dur)
|
4439
|
-
self.out_headerlist.append(("Set-Cookie", ck))
|
4440
|
-
self.redirect("", "?h#cc")
|
4441
|
-
return True
|
4442
|
-
|
4443
4475
|
def setck(self) :
|
4444
4476
|
k, v = self.uparam["setck"].split("=", 1)
|
4445
|
-
t = 0 if v
|
4477
|
+
t = 0 if v in ("", "x") else 86400 * 299
|
4446
4478
|
ck = gencookie(k, v, self.args.R, False, t)
|
4447
4479
|
self.out_headerlist.append(("Set-Cookie", ck))
|
4448
|
-
self.
|
4480
|
+
if "cc" in self.ouparam:
|
4481
|
+
self.redirect("", "?h#cc")
|
4482
|
+
else:
|
4483
|
+
self.reply(b"o7\n")
|
4449
4484
|
return True
|
4450
4485
|
|
4451
4486
|
def set_cfg_reset(self) :
|
4452
|
-
for k in
|
4487
|
+
for k in ALL_COOKIES:
|
4488
|
+
if k not in self.cookies:
|
4489
|
+
continue
|
4453
4490
|
cookie = gencookie(k, "x", self.args.R, False)
|
4454
4491
|
self.out_headerlist.append(("Set-Cookie", cookie))
|
4455
4492
|
|
@@ -4479,7 +4516,7 @@ class HttpCli(object):
|
|
4479
4516
|
|
4480
4517
|
t = t.format(self.args.SR)
|
4481
4518
|
qv = quotep(self.vpaths) + self.ourlq()
|
4482
|
-
in_shr = self.args.shr and self.vpath.startswith(self.args.
|
4519
|
+
in_shr = self.args.shr and self.vpath.startswith(self.args.shr1)
|
4483
4520
|
html = self.j2s("splash", this=self, qvpath=qv, in_shr=in_shr, msg=t)
|
4484
4521
|
self.reply(html.encode("utf-8"), status=rc)
|
4485
4522
|
return True
|
@@ -4642,6 +4679,11 @@ class HttpCli(object):
|
|
4642
4679
|
lm = "ups [{}]".format(filt)
|
4643
4680
|
self.log(lm)
|
4644
4681
|
|
4682
|
+
if self.args.shr and self.vpath.startswith(self.args.shr1):
|
4683
|
+
shr_dbv, shr_vrem = self.vn.get_dbv(self.rem)
|
4684
|
+
else:
|
4685
|
+
shr_dbv = None
|
4686
|
+
|
4645
4687
|
ret = []
|
4646
4688
|
t0 = time.time()
|
4647
4689
|
lim = time.time() - self.args.unpost
|
@@ -4662,7 +4704,12 @@ class HttpCli(object):
|
|
4662
4704
|
else:
|
4663
4705
|
allvols = list(self.asrv.vfs.all_vols.values())
|
4664
4706
|
|
4665
|
-
allvols = [
|
4707
|
+
allvols = [
|
4708
|
+
x
|
4709
|
+
for x in allvols
|
4710
|
+
if "e2d" in x.flags
|
4711
|
+
and ("*" in x.axs.uwrite or self.uname in x.axs.uwrite or x == shr_dbv)
|
4712
|
+
]
|
4666
4713
|
|
4667
4714
|
for vol in allvols:
|
4668
4715
|
cur = idx.get_cur(vol)
|
@@ -4712,6 +4759,15 @@ class HttpCli(object):
|
|
4712
4759
|
|
4713
4760
|
ret = ret[:2000]
|
4714
4761
|
|
4762
|
+
if shr_dbv:
|
4763
|
+
# translate vpaths from share-target to share-url
|
4764
|
+
# to satisfy access checks
|
4765
|
+
vp_shr, vp_vfs = vroots(self.vpath, vjoin(shr_dbv.vpath, shr_vrem))
|
4766
|
+
for v in ret:
|
4767
|
+
vp = v["vp"]
|
4768
|
+
if vp.startswith(vp_vfs):
|
4769
|
+
v["vp"] = vp_shr + vp[len(vp_vfs) :]
|
4770
|
+
|
4715
4771
|
if self.is_vproxied:
|
4716
4772
|
for v in ret:
|
4717
4773
|
v["vp"] = self.args.SR + v["vp"]
|
@@ -4841,7 +4897,7 @@ class HttpCli(object):
|
|
4841
4897
|
if m:
|
4842
4898
|
raise Pebkac(400, "sharekey has illegal character [%s]" % (m[1],))
|
4843
4899
|
|
4844
|
-
if vp.startswith(self.args.
|
4900
|
+
if vp.startswith(self.args.shr1):
|
4845
4901
|
raise Pebkac(400, "yo dawg...")
|
4846
4902
|
|
4847
4903
|
cur = idx.get_shr()
|
copyparty/svchub.py
CHANGED
@@ -217,13 +217,14 @@ class SvcHub(object):
|
|
217
217
|
args.chpw_no = noch
|
218
218
|
|
219
219
|
if args.ipu:
|
220
|
-
iu, nm = load_ipu(self.log, args.ipu)
|
220
|
+
iu, nm = load_ipu(self.log, args.ipu, True)
|
221
221
|
setattr(args, "ipu_iu", iu)
|
222
222
|
setattr(args, "ipu_nm", nm)
|
223
223
|
|
224
224
|
if not self.args.no_ses:
|
225
225
|
self.setup_session_db()
|
226
226
|
|
227
|
+
args.shr1 = ""
|
227
228
|
if args.shr:
|
228
229
|
self.setup_share_db()
|
229
230
|
|
@@ -372,6 +373,14 @@ class SvcHub(object):
|
|
372
373
|
|
373
374
|
self.broker = Broker(self)
|
374
375
|
|
376
|
+
# create netmaps early to avoid firewall gaps,
|
377
|
+
# but the mutex blocks multiprocessing startup
|
378
|
+
for zs in "ipu_iu ftp_ipa_nm tftp_ipa_nm".split():
|
379
|
+
try:
|
380
|
+
getattr(args, zs).mutex = threading.Lock()
|
381
|
+
except:
|
382
|
+
pass
|
383
|
+
|
375
384
|
def setup_session_db(self) :
|
376
385
|
if not HAVE_SQLITE3:
|
377
386
|
self.args.no_ses = True
|
@@ -444,6 +453,7 @@ class SvcHub(object):
|
|
444
453
|
raise Exception(t)
|
445
454
|
|
446
455
|
al.shr = "/%s/" % (al.shr,)
|
456
|
+
al.shr1 = al.shr[1:]
|
447
457
|
|
448
458
|
create = True
|
449
459
|
modified = False
|
@@ -751,8 +761,8 @@ class SvcHub(object):
|
|
751
761
|
al.idp_h_grp = al.idp_h_grp.lower()
|
752
762
|
al.idp_h_key = al.idp_h_key.lower()
|
753
763
|
|
754
|
-
al.ftp_ipa_nm = build_netmap(al.ftp_ipa or al.ipa)
|
755
|
-
al.tftp_ipa_nm = build_netmap(al.tftp_ipa or al.ipa)
|
764
|
+
al.ftp_ipa_nm = build_netmap(al.ftp_ipa or al.ipa, True)
|
765
|
+
al.tftp_ipa_nm = build_netmap(al.tftp_ipa or al.ipa, True)
|
756
766
|
|
757
767
|
mte = ODict.fromkeys(DEF_MTE.split(","), True)
|
758
768
|
al.mte = odfusion(mte, al.mte)
|
@@ -799,6 +809,24 @@ class SvcHub(object):
|
|
799
809
|
if len(al.tcolor) == 3: # fc5 => ffcc55
|
800
810
|
al.tcolor = "".join([x * 2 for x in al.tcolor])
|
801
811
|
|
812
|
+
zs = al.u2sz
|
813
|
+
zsl = zs.split(",")
|
814
|
+
if len(zsl) not in (1, 3):
|
815
|
+
t = "invalid --u2sz; must be either one number, or a comma-separated list of three numbers (min,default,max)"
|
816
|
+
raise Exception(t)
|
817
|
+
if len(zsl) < 3:
|
818
|
+
zsl = ["1", zs, zs]
|
819
|
+
zi2 = 1
|
820
|
+
for zs in zsl:
|
821
|
+
zi = int(zs)
|
822
|
+
# arbitrary constraint (anything above 2 GiB is probably unintended)
|
823
|
+
if zi < 1 or zi > 2047:
|
824
|
+
raise Exception("invalid --u2sz; minimum is 1, max is 2047")
|
825
|
+
if zi < zi2:
|
826
|
+
raise Exception("invalid --u2sz; values must be equal or ascending")
|
827
|
+
zi2 = zi
|
828
|
+
al.u2sz = ",".join(zsl)
|
829
|
+
|
802
830
|
return True
|
803
831
|
|
804
832
|
def _ipa2re(self, txt) :
|
copyparty/up2k.py
CHANGED
@@ -3886,11 +3886,9 @@ class Up2k(object):
|
|
3886
3886
|
if unpost:
|
3887
3887
|
raise Pebkac(400, "cannot unpost folders")
|
3888
3888
|
elif stat.S_ISLNK(st.st_mode) or stat.S_ISREG(st.st_mode):
|
3889
|
-
|
3890
|
-
dbv, vrem = dbv.get_dbv(vrem)
|
3891
|
-
voldir = vsplit(vrem)[0]
|
3889
|
+
voldir = vsplit(rem)[0]
|
3892
3890
|
vpath_dir = vsplit(vpath)[0]
|
3893
|
-
g = [(
|
3891
|
+
g = [(vn, voldir, vpath_dir, adir, [(fn, 0)], [], {})] # type: ignore
|
3894
3892
|
else:
|
3895
3893
|
self.log("rm: skip type-{:x} file [{}]".format(st.st_mode, atop))
|
3896
3894
|
return 0, [], []
|
@@ -3917,7 +3915,10 @@ class Up2k(object):
|
|
3917
3915
|
volpath = ("%s/%s" % (vrem, fn)).strip("/")
|
3918
3916
|
vpath = ("%s/%s" % (dbv.vpath, volpath)).strip("/")
|
3919
3917
|
self.log("rm %s\n %s" % (vpath, abspath))
|
3920
|
-
|
3918
|
+
if not unpost:
|
3919
|
+
# recursion-only sanchk
|
3920
|
+
_ = dbv.get(volpath, uname, *permsets[0])
|
3921
|
+
|
3921
3922
|
if xbd:
|
3922
3923
|
if not runhook(
|
3923
3924
|
self.log,
|
copyparty/util.py
CHANGED
@@ -647,13 +647,20 @@ class HLog(logging.Handler):
|
|
647
647
|
|
648
648
|
class NetMap(object):
|
649
649
|
def __init__(
|
650
|
-
self,
|
650
|
+
self,
|
651
|
+
ips ,
|
652
|
+
cidrs ,
|
653
|
+
keep_lo=False,
|
654
|
+
strict_cidr=False,
|
655
|
+
defer_mutex=False,
|
651
656
|
) :
|
652
657
|
"""
|
653
658
|
ips: list of plain ipv4/ipv6 IPs, not cidr
|
654
659
|
cidrs: list of cidr-notation IPs (ip/prefix)
|
655
660
|
"""
|
656
|
-
|
661
|
+
|
662
|
+
# fails multiprocessing; defer assignment
|
663
|
+
self.mutex = None if defer_mutex else threading.Lock()
|
657
664
|
|
658
665
|
if "::" in ips:
|
659
666
|
ips = [x for x in ips if x != "::"] + list(
|
@@ -692,6 +699,8 @@ class NetMap(object):
|
|
692
699
|
try:
|
693
700
|
return self.cache[ip]
|
694
701
|
except:
|
702
|
+
# intentionally crash the calling thread if unset:
|
703
|
+
|
695
704
|
with self.mutex:
|
696
705
|
return self._map(ip)
|
697
706
|
|
@@ -2109,6 +2118,23 @@ def unquotep(txt ) :
|
|
2109
2118
|
return w8dec(unq2)
|
2110
2119
|
|
2111
2120
|
|
2121
|
+
def vroots(vp1 , vp2 ) :
|
2122
|
+
"""
|
2123
|
+
input("q/w/e/r","a/s/d/e/r") output("/q/w/","/a/s/d/")
|
2124
|
+
"""
|
2125
|
+
while vp1 and vp2:
|
2126
|
+
zt1 = vp1.rsplit("/", 1) if "/" in vp1 else ("", vp1)
|
2127
|
+
zt2 = vp2.rsplit("/", 1) if "/" in vp2 else ("", vp2)
|
2128
|
+
if zt1[1] != zt2[1]:
|
2129
|
+
break
|
2130
|
+
vp1 = zt1[0]
|
2131
|
+
vp2 = zt2[0]
|
2132
|
+
return (
|
2133
|
+
"/%s/" % (vp1,) if vp1 else "/",
|
2134
|
+
"/%s/" % (vp2,) if vp2 else "/",
|
2135
|
+
)
|
2136
|
+
|
2137
|
+
|
2112
2138
|
def vsplit(vpath ) :
|
2113
2139
|
if "/" not in vpath:
|
2114
2140
|
return "", vpath
|
@@ -2568,7 +2594,7 @@ def list_ips() :
|
|
2568
2594
|
return list(ret)
|
2569
2595
|
|
2570
2596
|
|
2571
|
-
def build_netmap(csv ):
|
2597
|
+
def build_netmap(csv , defer_mutex = False):
|
2572
2598
|
csv = csv.lower().strip()
|
2573
2599
|
|
2574
2600
|
if csv in ("any", "all", "no", ",", ""):
|
@@ -2603,10 +2629,12 @@ def build_netmap(csv ):
|
|
2603
2629
|
cidrs.append(zs)
|
2604
2630
|
|
2605
2631
|
ips = [x.split("/")[0] for x in cidrs]
|
2606
|
-
return NetMap(ips, cidrs, True)
|
2632
|
+
return NetMap(ips, cidrs, True, False, defer_mutex)
|
2607
2633
|
|
2608
2634
|
|
2609
|
-
def load_ipu(
|
2635
|
+
def load_ipu(
|
2636
|
+
log , ipus , defer_mutex = False
|
2637
|
+
) :
|
2610
2638
|
ip_u = {"": "*"}
|
2611
2639
|
cidr_u = {}
|
2612
2640
|
for ipu in ipus:
|
@@ -2623,7 +2651,7 @@ def load_ipu(log , ipus ) :
|
|
2623
2651
|
cidr_u[cidr] = uname
|
2624
2652
|
ip_u[cip] = uname
|
2625
2653
|
try:
|
2626
|
-
nm = NetMap(["::"], list(cidr_u.keys()), True, True)
|
2654
|
+
nm = NetMap(["::"], list(cidr_u.keys()), True, True, defer_mutex)
|
2627
2655
|
except Exception as ex:
|
2628
2656
|
t = "failed to translate --ipu into netmap, probably due to invalid config: %r"
|
2629
2657
|
log("root", t % (ex,), 1)
|
copyparty/web/a/partyfuse.py
CHANGED
@@ -844,7 +844,7 @@ def main():
|
|
844
844
|
|
845
845
|
# dircache is always a boost,
|
846
846
|
# only want to disable it for tests etc,
|
847
|
-
cdn =
|
847
|
+
cdn = 24 # max num dirs; keep larger than max dir depth; 0=disable
|
848
848
|
cds = 1 # numsec until an entry goes stale
|
849
849
|
|
850
850
|
where = "local directory"
|
copyparty/web/browser.js.gz
CHANGED
Binary file
|
copyparty/web/splash.html
CHANGED
@@ -129,11 +129,20 @@
|
|
129
129
|
|
130
130
|
{% if k304 or k304vis %}
|
131
131
|
{% if k304 %}
|
132
|
-
<li><a id="h" href="{{ r }}/?k304=n">disable k304</a> (currently enabled)
|
132
|
+
<li><a id="h" href="{{ r }}/?cc&setck=k304=n">disable k304</a> (currently enabled)
|
133
133
|
{%- else %}
|
134
|
-
<li><a id="i" href="{{ r }}/?k304=y" class="r">enable k304</a> (currently disabled)
|
134
|
+
<li><a id="i" href="{{ r }}/?cc&setck=k304=y" class="r">enable k304</a> (currently disabled)
|
135
135
|
{% endif %}
|
136
|
-
<blockquote id="j">enabling
|
136
|
+
<blockquote id="j">enabling k304 will disconnect your client on every HTTP 304, which can prevent some buggy proxies from getting stuck (suddenly not loading pages), <em>but</em> it will also make things slower in general</blockquote></li>
|
137
|
+
{% endif %}
|
138
|
+
|
139
|
+
{% if no304 or no304vis %}
|
140
|
+
{% if no304 %}
|
141
|
+
<li><a id="ab" href="{{ r }}/?cc&setck=no304=n">disable no304</a> (currently enabled)
|
142
|
+
{%- else %}
|
143
|
+
<li><a id="ac" href="{{ r }}/?cc&setck=no304=y" class="r">enable no304</a> (currently disabled)
|
144
|
+
{% endif %}
|
145
|
+
<blockquote id="ad">enabling no304 will disable all caching; try this if k304 wasn't enough. This will waste a huge amount of network traffic!</blockquote></li>
|
137
146
|
{% endif %}
|
138
147
|
|
139
148
|
<li><a id="k" href="{{ r }}/?reset" class="r" onclick="localStorage.clear();return true">reset client settings</a></li>
|
copyparty/web/splash.js.gz
CHANGED
Binary file
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: copyparty
|
3
|
-
Version: 1.15.
|
3
|
+
Version: 1.15.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
|
Author-email: ed <copyparty@ocv.me>
|
6
6
|
License: MIT
|
@@ -21,6 +21,7 @@ Classifier: Programming Language :: Python :: 3.9
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.10
|
22
22
|
Classifier: Programming Language :: Python :: 3.11
|
23
23
|
Classifier: Programming Language :: Python :: 3.12
|
24
|
+
Classifier: Programming Language :: Python :: 3.13
|
24
25
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
25
26
|
Classifier: Programming Language :: Python :: Implementation :: Jython
|
26
27
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
@@ -1987,6 +1988,9 @@ quick summary of more eccentric web-browsers trying to view a directory index:
|
|
1987
1988
|
| **ie4** and **netscape** 4.0 | can browse, upload with `?b=u`, auth with `&pw=wark` |
|
1988
1989
|
| **ncsa mosaic** 2.7 | does not get a pass, [pic1](https://user-images.githubusercontent.com/241032/174189227-ae816026-cf6f-4be5-a26e-1b3b072c1b2f.png) - [pic2](https://user-images.githubusercontent.com/241032/174189225-5651c059-5152-46e9-ac26-7e98e497901b.png) |
|
1989
1990
|
| **SerenityOS** (7e98457) | hits a page fault, works with `?b=u`, file upload not-impl |
|
1991
|
+
| **nintendo 3ds** | can browse, upload, view thumbnails (thx bnjmn) |
|
1992
|
+
|
1993
|
+
<p align="center"><img src="https://github.com/user-attachments/assets/88deab3d-6cad-4017-8841-2f041472b853" /></p>
|
1990
1994
|
|
1991
1995
|
|
1992
1996
|
# client examples
|
@@ -1,7 +1,7 @@
|
|
1
1
|
copyparty/__init__.py,sha256=Chqw7uXX4r_-a2p6-xthrrqVHFI4aZdW45sWU7UvqeE,2597
|
2
|
-
copyparty/__main__.py,sha256=
|
3
|
-
copyparty/__version__.py,sha256=
|
4
|
-
copyparty/authsrv.py,sha256=
|
2
|
+
copyparty/__main__.py,sha256=S9jBx-HMqtUusAjpA64akmN4SKeRMGS5dNfzS4-miC4,111480
|
3
|
+
copyparty/__version__.py,sha256=fkcFvGlCD_NUIpsBFycKnSiV9ebZj5bDCWyy5H38XJw,259
|
4
|
+
copyparty/authsrv.py,sha256=FNb0l3o57R9xnYrZsqjTOqPwWkXGgP9YdX7NWx0ZMow,98955
|
5
5
|
copyparty/broker_mp.py,sha256=jsHUM2BSfRVRyZT869iPCqYEHSqedk6VkwvygZwbEZE,4017
|
6
6
|
copyparty/broker_mpw.py,sha256=PYFgQfssOCfdI6qayW1ZjO1j1-7oez094muhYMbPOz0,3339
|
7
7
|
copyparty/broker_thr.py,sha256=MXrwjusP0z1LPURUhi5jx_TL3jrXhYcDrJPDSKu6EEU,1705
|
@@ -11,7 +11,7 @@ copyparty/cfg.py,sha256=E9iBGNjIUrDAPLFRgKsVOmAknP9bDE27xh0gkmNdH1s,10127
|
|
11
11
|
copyparty/dxml.py,sha256=lZpg-kn-kQsXRtNY1n6fRaS-b7uXzMCyv8ovKnhZcZc,1548
|
12
12
|
copyparty/fsutil.py,sha256=5CshJWO7CflfaRRNOb3JxghUH7W5rmS_HWNmKfx42MM,4538
|
13
13
|
copyparty/ftpd.py,sha256=G_h1urfIikzfCWGXnW9p-rioWdNM_Je6vWYq0-QSbC8,17580
|
14
|
-
copyparty/httpcli.py,sha256=
|
14
|
+
copyparty/httpcli.py,sha256=rb-QxygFrRM7LEmTadMKn4FZ2bl5ddoPfJXsRrItKDg,201389
|
15
15
|
copyparty/httpconn.py,sha256=mQSgljh0Q-jyWjF4tQLrHbRKRe9WKl19kGqsGMsJpWo,6880
|
16
16
|
copyparty/httpsrv.py,sha256=d_UiGnQKniBoEV68lNFgnYm-byda7uj56mFf-YC7piI,17223
|
17
17
|
copyparty/ico.py,sha256=eWSxEae4wOCfheHl-m-wchYvFRAR_97kJDb4NGaB-Z8,3561
|
@@ -24,15 +24,15 @@ copyparty/smbd.py,sha256=Or7RF13cl1r3ncnpVh8BqyAGqH2Oa04O9iPZWCoB0Bo,14609
|
|
24
24
|
copyparty/ssdp.py,sha256=R1Z61GZOxBMF2Sk4RTxKWMOemogmcjEWG-CvLihd45k,7023
|
25
25
|
copyparty/star.py,sha256=tV5BbX6AiQ7N4UU8DYtSTckNYeoeey4DBqq4LjfymbY,3818
|
26
26
|
copyparty/sutil.py,sha256=JTMrQwcWH85hXB_cKG206eDZ967WZDGaP00AWvl_gB0,3214
|
27
|
-
copyparty/svchub.py,sha256=
|
27
|
+
copyparty/svchub.py,sha256=sfA_2BIXf0GP6-vNJGsttcvuVTjMek7TXWoGhYSa1bg,41178
|
28
28
|
copyparty/szip.py,sha256=sDypi1_yR6-62fIZ_3D0L9PfIzCUiK_3JqcaJCvTBCs,8601
|
29
29
|
copyparty/tcpsrv.py,sha256=l_vb9FoF0AJur0IoqHNUSBDqMgBO_MRUZeDszi1UNfY,19881
|
30
30
|
copyparty/tftpd.py,sha256=jZbf2JpeJmkuQWJErmAPG-dKhtYNvIUHbkAgodSXw9Y,13582
|
31
31
|
copyparty/th_cli.py,sha256=o6FMkerYvAXS455z3DUossVztu_nzFlYSQhs6qN6Jt8,4636
|
32
32
|
copyparty/th_srv.py,sha256=hI9wY1E_9N9Cgqvtr8zADeVqqiLGTiTdAnYAA7WFvJw,29346
|
33
33
|
copyparty/u2idx.py,sha256=HLO49L1zmpJtBcJiXgD12a6pAlQdnf2pFelHMA7habw,13462
|
34
|
-
copyparty/up2k.py,sha256=
|
35
|
-
copyparty/util.py,sha256=
|
34
|
+
copyparty/up2k.py,sha256=PYAcSuiEJAikQSDGNodyv-jXNtGxmN-KB8_hZ4989Qg,165385
|
35
|
+
copyparty/util.py,sha256=bV_zxOiG3GIxt91EkTR7r-YjvR7WOM9IIvg0zuq0s7k,93378
|
36
36
|
copyparty/bos/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
37
37
|
copyparty/bos/bos.py,sha256=Wb7eWsXJgR5AFlBR9ZOyKrLTwy-Kct9RrGiOu4Jo37Y,1622
|
38
38
|
copyparty/bos/path.py,sha256=yEjCq2ki9CvxA5sCT8pS0keEXwugs0ZeUyUhdBziOCI,777
|
@@ -57,7 +57,7 @@ copyparty/stolen/ifaddr/_win32.py,sha256=EE-QyoBgeB7lYQ6z62VjXNaRozaYfCkaJBHGNA8
|
|
57
57
|
copyparty/web/baguettebox.js.gz,sha256=YIaxFDsubJfGIdzzxA-cL6GwJVmpWZyaPhW9hHcOIIw,7964
|
58
58
|
copyparty/web/browser.css.gz,sha256=4bAS9Xkl2fflhaxRSRSVoYQcpXsg1mCWxsYjId7phbU,11610
|
59
59
|
copyparty/web/browser.html,sha256=ISpfvWEawufJCYZIqvuXiyUgiXgjmOTtScz4zrEaypI,4870
|
60
|
-
copyparty/web/browser.js.gz,sha256=
|
60
|
+
copyparty/web/browser.js.gz,sha256=yDhq0t-6R9OCv--ca_dCCsg7ZkhJjN3Y-9-PQdZPRpg,85071
|
61
61
|
copyparty/web/browser2.html,sha256=NRUZ08GH-e2YcGXcoz0UjYg6JIVF42u4IMX4HHwWTmg,1587
|
62
62
|
copyparty/web/cf.html,sha256=lJThtNFNAQT1ClCHHlivAkDGE0LutedwopXD62Z8Nys,589
|
63
63
|
copyparty/web/dbg-audio.js.gz,sha256=Ma-KZtK8LnmiwNvNKFKXMPYl_Nn_3U7GsJ6-DRWC2HE,688
|
@@ -75,8 +75,8 @@ copyparty/web/shares.css.gz,sha256=T2fSezuluDVIiNIERAuUREByhHFlIwwNyx7EBOAVVyQ,4
|
|
75
75
|
copyparty/web/shares.html,sha256=ZNHtLBM-Y4BX2qa9AGTrZzZp_IP5PLM3QvFMYKolFfM,2494
|
76
76
|
copyparty/web/shares.js.gz,sha256=814O61mxLSWs0AO2fbGJ8d4BSPB7pE9NdkKiVf1gj6E,926
|
77
77
|
copyparty/web/splash.css.gz,sha256=RjdNoIT5BSxXRFu0ldMUH4ghRNUMCTs2mGKzstrpI6o,1033
|
78
|
-
copyparty/web/splash.html,sha256=
|
79
|
-
copyparty/web/splash.js.gz,sha256=
|
78
|
+
copyparty/web/splash.html,sha256=_09d2C79S4sIyaks5pPdq1PBgabdlEFhB6Z-KiynwD8,5699
|
79
|
+
copyparty/web/splash.js.gz,sha256=f9aSzI0vw0teK52MBi8Y9FsSMURDfRdZFEvpzqNBon8,2694
|
80
80
|
copyparty/web/svcs.html,sha256=P5YZimYLeQMT0uz6u3clQSNZRc5Zs0Ok-ffcbcGSYuc,11762
|
81
81
|
copyparty/web/svcs.js.gz,sha256=k81ZvZ3I-f4fMHKrNGGOgOlvXnCBz0mVjD-8mieoWCA,520
|
82
82
|
copyparty/web/ui.css.gz,sha256=wloSacrHgP722hy4XiOvVY2GI9-V4zvfvzu84LLWS_o,2779
|
@@ -84,7 +84,7 @@ copyparty/web/up2k.js.gz,sha256=lGR1Xb0RkIZ1eHmncsSwWRuFc6FC2rZalvjo3oNTV1s,2329
|
|
84
84
|
copyparty/web/util.js.gz,sha256=NvjPYhIa0-C_NhUyW-Ra-XinUCRjj8G3pYq1zJHYWEk,14805
|
85
85
|
copyparty/web/w.hash.js.gz,sha256=l3GpSJD6mcU-1CRWkIj7PybgbjlfSr8oeO3vortIrQk,1105
|
86
86
|
copyparty/web/a/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
87
|
-
copyparty/web/a/partyfuse.py,sha256=
|
87
|
+
copyparty/web/a/partyfuse.py,sha256=efBOupuGVCaGVGylJ-mcx0kz6paqc2sk8kHIprfGUQU,27993
|
88
88
|
copyparty/web/a/u2c.py,sha256=ZmLcGuOWB66ZkAMpJBiR1Xpa75PgpzdFRTt3GGVCorc,49533
|
89
89
|
copyparty/web/a/webdav-cfg.bat,sha256=Y4NoGZlksAIg4cBMb7KdJrpKC6Nx97onaTl6yMjaimk,1449
|
90
90
|
copyparty/web/dd/2.png,sha256=gJ14XFPzaw95L6z92fSq9eMPikSQyu-03P1lgiGe0_I,258
|
@@ -106,9 +106,9 @@ copyparty/web/deps/prismd.css.gz,sha256=ObUlksQVr-OuYlTz-I4B23TeBg2QDVVGRnWBz8cV
|
|
106
106
|
copyparty/web/deps/scp.woff2,sha256=w99BDU5i8MukkMEL-iW0YO9H4vFFZSPWxbkH70ytaAg,8612
|
107
107
|
copyparty/web/deps/sha512.ac.js.gz,sha256=lFZaCLumgWxrvEuDr4bqdKHsqjX82AbVAb7_F45Yk88,7033
|
108
108
|
copyparty/web/deps/sha512.hw.js.gz,sha256=vqoXeracj-99Z5MfY3jK2N4WiSzYQdfjy0RnUlQDhSU,8110
|
109
|
-
copyparty-1.15.
|
110
|
-
copyparty-1.15.
|
111
|
-
copyparty-1.15.
|
112
|
-
copyparty-1.15.
|
113
|
-
copyparty-1.15.
|
114
|
-
copyparty-1.15.
|
109
|
+
copyparty-1.15.10.dist-info/LICENSE,sha256=gOr4h33pCsBEg9uIy9AYmb7qlocL4V9t2uPJS5wllr0,1072
|
110
|
+
copyparty-1.15.10.dist-info/METADATA,sha256=DhJZfQ1d9CPtx3LXk0ga7thnke1xWg3GJI_HlTPXZLw,140056
|
111
|
+
copyparty-1.15.10.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
|
112
|
+
copyparty-1.15.10.dist-info/entry_points.txt,sha256=4zw6a3rqASywQomiYLObjjlxybaI65LYYOTJwgKz7b0,128
|
113
|
+
copyparty-1.15.10.dist-info/top_level.txt,sha256=LnYUPsDyk-8kFgM6YJLG4h820DQekn81cObKSu9g-sI,10
|
114
|
+
copyparty-1.15.10.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|