copyparty 1.10.0__py3-none-any.whl → 1.10.2__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 +4 -1
- copyparty/__version__.py +2 -2
- copyparty/authsrv.py +1 -1
- copyparty/cfg.py +4 -2
- copyparty/ftpd.py +3 -0
- copyparty/httpcli.py +24 -9
- copyparty/ico.py +3 -4
- copyparty/tftpd.py +129 -9
- copyparty/th_cli.py +27 -9
- copyparty/th_srv.py +17 -12
- copyparty/up2k.py +18 -11
- copyparty/util.py +1 -1
- copyparty/web/a/u2c.py +7 -7
- copyparty/web/baguettebox.js.gz +0 -0
- copyparty/web/browser.css.gz +0 -0
- copyparty/web/browser.html +1 -0
- copyparty/web/browser.js.gz +0 -0
- copyparty/web/browser2.html +1 -0
- copyparty/web/cf.html +1 -0
- copyparty/web/deps/marked.js.gz +0 -0
- copyparty/web/md.html +1 -0
- copyparty/web/mde.html +1 -0
- copyparty/web/msg.html +2 -1
- copyparty/web/splash.html +1 -0
- copyparty/web/svcs.html +1 -0
- copyparty/web/ui.css.gz +0 -0
- {copyparty-1.10.0.dist-info → copyparty-1.10.2.dist-info}/METADATA +14 -7
- {copyparty-1.10.0.dist-info → copyparty-1.10.2.dist-info}/RECORD +32 -32
- {copyparty-1.10.0.dist-info → copyparty-1.10.2.dist-info}/LICENSE +0 -0
- {copyparty-1.10.0.dist-info → copyparty-1.10.2.dist-info}/WHEEL +0 -0
- {copyparty-1.10.0.dist-info → copyparty-1.10.2.dist-info}/entry_points.txt +0 -0
- {copyparty-1.10.0.dist-info → copyparty-1.10.2.dist-info}/top_level.txt +0 -0
copyparty/__main__.py
CHANGED
@@ -1013,6 +1013,7 @@ def add_tftp(ap):
|
|
1013
1013
|
ap2.add_argument("--tftp", metavar="PORT", type=int, help="enable TFTP server on \033[33mPORT\033[0m, for example \033[32m69 \033[0mor \033[32m3969")
|
1014
1014
|
ap2.add_argument("--tftpv", action="store_true", help="verbose")
|
1015
1015
|
ap2.add_argument("--tftpvv", action="store_true", help="verboser")
|
1016
|
+
ap2.add_argument("--tftp-no-fast", action="store_true", help="debug: disable optimizations")
|
1016
1017
|
ap2.add_argument("--tftp-lsf", metavar="PTN", type=u, default="\\.?(dir|ls)(\\.txt)?", help="return a directory listing if a file with this name is requested and it does not exist; defaults matches .ls, dir, .dir.txt, ls.txt, ...")
|
1017
1018
|
ap2.add_argument("--tftp-nols", action="store_true", help="if someone tries to download a directory, return an error instead of showing its directory listing")
|
1018
1019
|
ap2.add_argument("--tftp-ipa", metavar="PFX", type=u, default="", help="only accept connections from IP-addresses starting with \033[33mPFX\033[0m; specify [\033[32many\033[0m] to disable inheriting \033[33m--ipa\033[0m. Example: [\033[32m127., 10.89., 192.168.\033[0m]")
|
@@ -1163,7 +1164,8 @@ def add_thumbnail(ap):
|
|
1163
1164
|
ap2.add_argument("--th-mt", metavar="CORES", type=int, default=CORES, help="num cpu cores to use for generating thumbnails")
|
1164
1165
|
ap2.add_argument("--th-convt", metavar="SEC", type=float, default=60, help="conversion timeout in seconds (volflag=convt)")
|
1165
1166
|
ap2.add_argument("--th-ram-max", metavar="GB", type=float, default=6, help="max memory usage (GiB) permitted by thumbnailer; not very accurate")
|
1166
|
-
ap2.add_argument("--th-
|
1167
|
+
ap2.add_argument("--th-crop", metavar="TXT", type=u, default="y", help="crop thumbnails to 4:3 or keep dynamic height; client can override in UI unless force. [\033[32mfy\033[0m]=crop, [\033[32mfn\033[0m]=nocrop, [\033[32mfy\033[0m]=force-y, [\033[32mfn\033[0m]=force-n (volflag=crop)")
|
1168
|
+
ap2.add_argument("--th-x3", metavar="TXT", type=u, default="n", help="show thumbs at 3x resolution; client can override in UI unless force. [\033[32mfy\033[0m]=yes, [\033[32mfn\033[0m]=no, [\033[32mfy\033[0m]=force-yes, [\033[32mfn\033[0m]=force-no (volflag=th3x)")
|
1167
1169
|
ap2.add_argument("--th-dec", metavar="LIBS", default="vips,pil,ff", help="image decoders, in order of preference")
|
1168
1170
|
ap2.add_argument("--th-no-jpg", action="store_true", help="disable jpg output")
|
1169
1171
|
ap2.add_argument("--th-no-webp", action="store_true", help="disable webp output")
|
@@ -1423,6 +1425,7 @@ def main(argv = None) :
|
|
1423
1425
|
deprecated = [
|
1424
1426
|
("--salt", "--warksalt"),
|
1425
1427
|
("--hdr-au-usr", "--idp-h-usr"),
|
1428
|
+
("--th-no-crop", "--th-crop=n"),
|
1426
1429
|
]
|
1427
1430
|
for dk, nk in deprecated:
|
1428
1431
|
idx = -1
|
copyparty/__version__.py
CHANGED
copyparty/authsrv.py
CHANGED
@@ -186,7 +186,7 @@ class Lim(object):
|
|
186
186
|
self.dft = int(time.time()) + 300
|
187
187
|
self.dfv = get_df(abspath)[0] or 0
|
188
188
|
for j in list(self.reg.values()) if self.reg else []:
|
189
|
-
self.dfv -= int(j["size"] / len(j["hash"]) * len(j["need"]))
|
189
|
+
self.dfv -= int(j["size"] / (len(j["hash"]) or 999) * len(j["need"]))
|
190
190
|
|
191
191
|
if already_written:
|
192
192
|
sz = 0
|
copyparty/cfg.py
CHANGED
@@ -20,7 +20,6 @@ def vf_bmap() :
|
|
20
20
|
"no_thumb": "dthumb",
|
21
21
|
"no_vthumb": "dvthumb",
|
22
22
|
"no_athumb": "dathumb",
|
23
|
-
"th_no_crop": "nocrop",
|
24
23
|
}
|
25
24
|
for k in (
|
26
25
|
"dotsrch",
|
@@ -56,6 +55,8 @@ def vf_vmap() :
|
|
56
55
|
"re_maxage": "scan",
|
57
56
|
"th_convt": "convt",
|
58
57
|
"th_size": "thsize",
|
58
|
+
"th_crop": "crop",
|
59
|
+
"th_x3": "th3x",
|
59
60
|
}
|
60
61
|
for k in (
|
61
62
|
"dbd",
|
@@ -172,7 +173,8 @@ flagcats = {
|
|
172
173
|
"dathumb": "disables audio thumbnails (spectrograms)",
|
173
174
|
"dithumb": "disables image thumbnails",
|
174
175
|
"thsize": "thumbnail res; WxH",
|
175
|
-
"
|
176
|
+
"crop": "center-cropping (y/n/fy/fn)",
|
177
|
+
"th3x": "3x resolution (y/n/fy/fn)",
|
176
178
|
"convt": "conversion timeout in seconds",
|
177
179
|
},
|
178
180
|
"handlers\n(better explained in --help-handlers)": {
|
copyparty/ftpd.py
CHANGED
@@ -20,6 +20,7 @@ from .authsrv import VFS
|
|
20
20
|
from .bos import bos
|
21
21
|
from .util import (
|
22
22
|
Daemon,
|
23
|
+
ODict,
|
23
24
|
Pebkac,
|
24
25
|
exclude_dotfiles,
|
25
26
|
fsenc,
|
@@ -540,6 +541,8 @@ class Ftpd(object):
|
|
540
541
|
if self.args.ftp4:
|
541
542
|
ips = [x for x in ips if ":" not in x]
|
542
543
|
|
544
|
+
ips = list(ODict.fromkeys(ips)) # dedup
|
545
|
+
|
543
546
|
ioloop = IOLoop()
|
544
547
|
for ip in ips:
|
545
548
|
for h, lp in hs:
|
copyparty/httpcli.py
CHANGED
@@ -3135,11 +3135,15 @@ class HttpCli(object):
|
|
3135
3135
|
|
3136
3136
|
ext = ext.rstrip(".") or "unk"
|
3137
3137
|
if len(ext) > 11:
|
3138
|
-
ext = "
|
3138
|
+
ext = "~" + ext[-9:]
|
3139
3139
|
|
3140
|
+
return self.tx_svg(ext, exact)
|
3141
|
+
|
3142
|
+
def tx_svg(self, txt , small = False) :
|
3140
3143
|
# chrome cannot handle more than ~2000 unique SVGs
|
3141
|
-
|
3142
|
-
|
3144
|
+
# so url-param "raster" returns a png/webp instead
|
3145
|
+
# (useragent-sniffing kinshi due to caching proxies)
|
3146
|
+
mime, ico = self.ico.get(txt, not small, "raster" in self.uparam)
|
3143
3147
|
|
3144
3148
|
lm = formatdate(self.E.t0, usegmt=True)
|
3145
3149
|
self.reply(ico, mime=mime, headers={"Last-Modified": lm})
|
@@ -3403,6 +3407,9 @@ class HttpCli(object):
|
|
3403
3407
|
self.reply(pt.encode("utf-8"), status=rc)
|
3404
3408
|
return True
|
3405
3409
|
|
3410
|
+
if "th" in self.ouparam:
|
3411
|
+
return self.tx_svg("e" + pt[:3])
|
3412
|
+
|
3406
3413
|
t = t.format(self.args.SR)
|
3407
3414
|
qv = quotep(self.vpaths) + self.ourlq()
|
3408
3415
|
html = self.j2s("splash", this=self, qvpath=qv, msg=t)
|
@@ -3783,12 +3790,15 @@ class HttpCli(object):
|
|
3783
3790
|
if idx and hasattr(idx, "p_end"):
|
3784
3791
|
icur = idx.get_cur(dbv.realpath)
|
3785
3792
|
|
3793
|
+
th_fmt = self.uparam.get("th")
|
3786
3794
|
if self.can_read:
|
3787
|
-
th_fmt = self.uparam.get("th")
|
3788
3795
|
if th_fmt is not None:
|
3796
|
+
nothumb = "dthumb" in dbv.flags
|
3789
3797
|
if is_dir:
|
3790
3798
|
vrem = vrem.rstrip("/")
|
3791
|
-
if
|
3799
|
+
if nothumb:
|
3800
|
+
pass
|
3801
|
+
elif icur and vrem:
|
3792
3802
|
q = "select fn from cv where rd=? and dn=?"
|
3793
3803
|
crd, cdn = vrem.rsplit("/", 1) if "/" in vrem else ("", vrem)
|
3794
3804
|
# no mojibake support:
|
@@ -3811,10 +3821,10 @@ class HttpCli(object):
|
|
3811
3821
|
break
|
3812
3822
|
|
3813
3823
|
if is_dir:
|
3814
|
-
return self.
|
3824
|
+
return self.tx_svg("folder")
|
3815
3825
|
|
3816
3826
|
thp = None
|
3817
|
-
if self.thumbcli:
|
3827
|
+
if self.thumbcli and not nothumb:
|
3818
3828
|
thp = self.thumbcli.get(dbv, vrem, int(st.st_mtime), th_fmt)
|
3819
3829
|
|
3820
3830
|
if thp:
|
@@ -3825,6 +3835,9 @@ class HttpCli(object):
|
|
3825
3835
|
|
3826
3836
|
return self.tx_ico(rem)
|
3827
3837
|
|
3838
|
+
elif self.can_write and th_fmt is not None:
|
3839
|
+
return self.tx_svg("upload\nonly")
|
3840
|
+
|
3828
3841
|
elif self.can_get and self.avn:
|
3829
3842
|
axs = self.avn.axs
|
3830
3843
|
if self.uname not in axs.uhtml:
|
@@ -3969,7 +3982,8 @@ class HttpCli(object):
|
|
3969
3982
|
"idx": e2d,
|
3970
3983
|
"itag": e2t,
|
3971
3984
|
"dsort": vf["sort"],
|
3972
|
-
"
|
3985
|
+
"dcrop": vf["crop"],
|
3986
|
+
"dth3x": vf["th3x"],
|
3973
3987
|
"u2ts": vf["u2ts"],
|
3974
3988
|
"lifetime": vn.flags.get("lifetime") or 0,
|
3975
3989
|
"frand": bool(vn.flags.get("rand")),
|
@@ -3996,8 +4010,9 @@ class HttpCli(object):
|
|
3996
4010
|
"sb_md": "" if "no_sb_md" in vf else (vf.get("md_sbf") or "y"),
|
3997
4011
|
"readme": readme,
|
3998
4012
|
"dgrid": "grid" in vf,
|
3999
|
-
"dfull": "nocrop" in vf,
|
4000
4013
|
"dsort": vf["sort"],
|
4014
|
+
"dcrop": vf["crop"],
|
4015
|
+
"dth3x": vf["th3x"],
|
4001
4016
|
"themes": self.args.themes,
|
4002
4017
|
"turbolvl": self.args.turbo,
|
4003
4018
|
"u2j": self.args.u2j,
|
copyparty/ico.py
CHANGED
@@ -8,7 +8,7 @@ import re
|
|
8
8
|
|
9
9
|
from .__init__ import PY2
|
10
10
|
from .th_srv import HAVE_PIL, HAVE_PILF
|
11
|
-
from .util import BytesIO # type: ignore
|
11
|
+
from .util import BytesIO, html_escape # type: ignore
|
12
12
|
|
13
13
|
|
14
14
|
class Ico(object):
|
@@ -31,10 +31,9 @@ class Ico(object):
|
|
31
31
|
|
32
32
|
w = 100
|
33
33
|
h = 30
|
34
|
-
if
|
34
|
+
if as_thumb:
|
35
35
|
sw, sh = self.args.th_size.split("x")
|
36
36
|
h = int(100.0 / (float(sw) / float(sh)))
|
37
|
-
w = 100
|
38
37
|
|
39
38
|
if chrome:
|
40
39
|
# cannot handle more than ~2000 unique SVGs
|
@@ -99,6 +98,6 @@ class Ico(object):
|
|
99
98
|
fill="#{}" font-family="monospace" font-size="14px" style="letter-spacing:.5px">{}</text>
|
100
99
|
</g></svg>
|
101
100
|
"""
|
102
|
-
svg = svg.format(h, c[:6], c[6:], ext)
|
101
|
+
svg = svg.format(h, c[:6], c[6:], html_escape(ext, True))
|
103
102
|
|
104
103
|
return "image/svg+xml", svg.encode("utf-8")
|
copyparty/tftpd.py
CHANGED
@@ -10,19 +10,33 @@ except:
|
|
10
10
|
self.__dict__.update(attr)
|
11
11
|
|
12
12
|
|
13
|
-
import inspect
|
14
13
|
import logging
|
15
14
|
import os
|
15
|
+
import re
|
16
|
+
import socket
|
16
17
|
import stat
|
18
|
+
import threading
|
19
|
+
import time
|
17
20
|
from datetime import datetime
|
18
21
|
|
19
|
-
|
22
|
+
try:
|
23
|
+
import inspect
|
24
|
+
except:
|
25
|
+
pass
|
26
|
+
|
27
|
+
from partftpy import (
|
28
|
+
TftpContexts,
|
29
|
+
TftpPacketFactory,
|
30
|
+
TftpPacketTypes,
|
31
|
+
TftpServer,
|
32
|
+
TftpStates,
|
33
|
+
)
|
20
34
|
from partftpy.TftpShared import TftpException
|
21
35
|
|
22
|
-
from .__init__ import
|
36
|
+
from .__init__ import EXE, TYPE_CHECKING
|
23
37
|
from .authsrv import VFS
|
24
38
|
from .bos import bos
|
25
|
-
from .util import BytesIO, Daemon, exclude_dotfiles, runhook, undot
|
39
|
+
from .util import BytesIO, Daemon, ODict, exclude_dotfiles, min_ex, runhook, undot
|
26
40
|
|
27
41
|
if TYPE_CHECKING:
|
28
42
|
from .svchub import SvcHub
|
@@ -32,6 +46,10 @@ lg = logging.getLogger("tftp")
|
|
32
46
|
debug, info, warning, error = (lg.debug, lg.info, lg.warning, lg.error)
|
33
47
|
|
34
48
|
|
49
|
+
def noop(*a, **ka) :
|
50
|
+
pass
|
51
|
+
|
52
|
+
|
35
53
|
def _serverInitial(self, pkt , raddress , rport ) :
|
36
54
|
info("connection from %s:%s", raddress, rport)
|
37
55
|
ret = _orig_serverInitial(self, pkt, raddress, rport)
|
@@ -53,6 +71,7 @@ class Tftpd(object):
|
|
53
71
|
self.args = hub.args
|
54
72
|
self.asrv = hub.asrv
|
55
73
|
self.log = hub.log
|
74
|
+
self.mutex = threading.Lock()
|
56
75
|
|
57
76
|
_hub[:] = []
|
58
77
|
_hub.append(hub)
|
@@ -62,6 +81,38 @@ class Tftpd(object):
|
|
62
81
|
lgr = logging.getLogger(x)
|
63
82
|
lgr.setLevel(logging.DEBUG if self.args.tftpv else logging.INFO)
|
64
83
|
|
84
|
+
if not self.args.tftpv and not self.args.tftpvv:
|
85
|
+
# contexts -> states -> packettypes -> shared
|
86
|
+
# contexts -> packetfactory
|
87
|
+
# packetfactory -> packettypes
|
88
|
+
Cs = [
|
89
|
+
TftpPacketTypes,
|
90
|
+
TftpPacketFactory,
|
91
|
+
TftpStates,
|
92
|
+
TftpContexts,
|
93
|
+
TftpServer,
|
94
|
+
]
|
95
|
+
cbak = []
|
96
|
+
if not self.args.tftp_no_fast and not EXE:
|
97
|
+
try:
|
98
|
+
import inspect
|
99
|
+
|
100
|
+
ptn = re.compile(r"(^\s*)log\.debug\(.*\)$")
|
101
|
+
for C in Cs:
|
102
|
+
cbak.append(C.__dict__)
|
103
|
+
src1 = inspect.getsource(C).split("\n")
|
104
|
+
src2 = "\n".join([ptn.sub("\\1pass", ln) for ln in src1])
|
105
|
+
cfn = C.__spec__.origin
|
106
|
+
exec (compile(src2, filename=cfn, mode="exec"), C.__dict__)
|
107
|
+
except Exception:
|
108
|
+
t = "failed to optimize tftp code; run with --tftp-noopt if there are issues:\n"
|
109
|
+
self.log("tftp", t + min_ex(), 3)
|
110
|
+
for n, zd in enumerate(cbak):
|
111
|
+
Cs[n].__dict__ = zd
|
112
|
+
|
113
|
+
for C in Cs:
|
114
|
+
C.log.debug = noop
|
115
|
+
|
65
116
|
# patch vfs into partftpy
|
66
117
|
TftpContexts.open = self._open
|
67
118
|
TftpStates.open = self._open
|
@@ -99,21 +150,90 @@ class Tftpd(object):
|
|
99
150
|
self.log("tftp", "IPv6 not supported for tftp; listening on 0.0.0.0", 3)
|
100
151
|
ip = "0.0.0.0"
|
101
152
|
|
102
|
-
self.ip = ip
|
103
153
|
self.port = int(self.args.tftp)
|
104
|
-
self.srv =
|
105
|
-
self.
|
154
|
+
self.srv = []
|
155
|
+
self.ips = []
|
106
156
|
|
107
157
|
ports = []
|
108
158
|
if self.args.tftp_pr:
|
109
159
|
p1, p2 = [int(x) for x in self.args.tftp_pr.split("-")]
|
110
160
|
ports = list(range(p1, p2 + 1))
|
111
161
|
|
112
|
-
|
162
|
+
ips = self.args.i
|
163
|
+
if "::" in ips:
|
164
|
+
ips.append("0.0.0.0")
|
165
|
+
|
166
|
+
if self.args.ftp4:
|
167
|
+
ips = [x for x in ips if ":" not in x]
|
168
|
+
|
169
|
+
ips = list(ODict.fromkeys(ips)) # dedup
|
170
|
+
|
171
|
+
for ip in ips:
|
172
|
+
name = "tftp_%s" % (ip,)
|
173
|
+
Daemon(self._start, name, [ip, ports])
|
174
|
+
time.sleep(0.2) # give dualstack a chance
|
113
175
|
|
114
176
|
def nlog(self, msg , c = 0) :
|
115
177
|
self.log("tftp", msg, c)
|
116
178
|
|
179
|
+
def _start(self, ip, ports):
|
180
|
+
fam = socket.AF_INET6 if ":" in ip else socket.AF_INET
|
181
|
+
have_been_alive = False
|
182
|
+
while True:
|
183
|
+
srv = TftpServer.TftpServer("/", self._ls)
|
184
|
+
with self.mutex:
|
185
|
+
self.srv.append(srv)
|
186
|
+
self.ips.append(ip)
|
187
|
+
|
188
|
+
try:
|
189
|
+
# this is the listen loop; it should block forever
|
190
|
+
srv.listen(ip, self.port, af_family=fam, ports=ports)
|
191
|
+
except:
|
192
|
+
with self.mutex:
|
193
|
+
self.srv.remove(srv)
|
194
|
+
self.ips.remove(ip)
|
195
|
+
|
196
|
+
try:
|
197
|
+
srv.sock.close()
|
198
|
+
except:
|
199
|
+
pass
|
200
|
+
|
201
|
+
try:
|
202
|
+
bound = bool(srv.listenport)
|
203
|
+
except:
|
204
|
+
bound = False
|
205
|
+
|
206
|
+
if bound:
|
207
|
+
# this instance has managed to bind at least once
|
208
|
+
have_been_alive = True
|
209
|
+
|
210
|
+
if have_been_alive:
|
211
|
+
t = "tftp server [%s]:%d crashed; restarting in 3 sec:\n%s"
|
212
|
+
error(t, ip, self.port, min_ex())
|
213
|
+
time.sleep(3)
|
214
|
+
continue
|
215
|
+
|
216
|
+
# server failed to start; could be due to dualstack (ipv6 managed to bind and this is ipv4)
|
217
|
+
if ip != "0.0.0.0" or "::" not in self.ips:
|
218
|
+
# nope, it's fatal
|
219
|
+
t = "tftp server [%s]:%d failed to start:\n%s"
|
220
|
+
error(t, ip, self.port, min_ex())
|
221
|
+
|
222
|
+
# yep; ignore
|
223
|
+
# (TODO: move the "listening @ ..." infolog in partftpy to
|
224
|
+
# after the bind attempt so it doesn't print twice)
|
225
|
+
return
|
226
|
+
|
227
|
+
info("tftp server [%s]:%d terminated", ip, self.port)
|
228
|
+
break
|
229
|
+
|
230
|
+
def stop(self):
|
231
|
+
with self.mutex:
|
232
|
+
srvs = self.srv[:]
|
233
|
+
|
234
|
+
for srv in srvs:
|
235
|
+
srv.stop()
|
236
|
+
|
117
237
|
def _v2a(self, caller , vpath , perms , *a ) :
|
118
238
|
vpath = vpath.replace("\\", "/").lstrip("/")
|
119
239
|
if not perms:
|
@@ -187,7 +307,7 @@ class Tftpd(object):
|
|
187
307
|
retl = ["# permissions: %s" % (", ".join(perms),)]
|
188
308
|
retl += [fmt.format(*x) for x in ls]
|
189
309
|
ret = "\n".join(retl).encode("utf-8", "replace")
|
190
|
-
return BytesIO(ret)
|
310
|
+
return BytesIO(ret + b"\n")
|
191
311
|
|
192
312
|
def _open(self, vpath , mode , *a , **ka ) :
|
193
313
|
rd = wr = False
|
copyparty/th_cli.py
CHANGED
@@ -75,16 +75,34 @@ class ThumbCli(object):
|
|
75
75
|
if rem.startswith(".hist/th/") and rem.split(".")[-1] in ["webp", "jpg", "png"]:
|
76
76
|
return os.path.join(ptop, rem)
|
77
77
|
|
78
|
-
if fmt
|
79
|
-
|
78
|
+
if fmt[:1] in "jw":
|
79
|
+
sfmt = fmt[:1]
|
80
80
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
81
|
+
if sfmt == "j" and self.args.th_no_jpg:
|
82
|
+
sfmt = "w"
|
83
|
+
|
84
|
+
if sfmt == "w":
|
85
|
+
if (
|
86
|
+
self.args.th_no_webp
|
87
|
+
or (is_img and not self.can_webp)
|
88
|
+
or (self.args.th_ff_jpg and (not is_img or preferred == "ff"))
|
89
|
+
):
|
90
|
+
sfmt = "j"
|
91
|
+
|
92
|
+
vf_crop = dbv.flags["crop"]
|
93
|
+
vf_th3x = dbv.flags["th3x"]
|
94
|
+
|
95
|
+
if "f" in vf_crop:
|
96
|
+
sfmt += "f" if "n" in vf_crop else ""
|
97
|
+
else:
|
98
|
+
sfmt += "f" if "f" in fmt else ""
|
99
|
+
|
100
|
+
if "f" in vf_th3x:
|
101
|
+
sfmt += "3" if "y" in vf_th3x else ""
|
102
|
+
else:
|
103
|
+
sfmt += "3" if "3" in fmt else ""
|
104
|
+
|
105
|
+
fmt = sfmt
|
88
106
|
|
89
107
|
histpath = self.asrv.vfs.histtab.get(ptop)
|
90
108
|
if not histpath:
|
copyparty/th_srv.py
CHANGED
@@ -94,8 +94,8 @@ def thumb_path(histpath , rem , mtime , fmt , ffa ) :
|
|
94
94
|
|
95
95
|
# spectrograms are never cropped; strip fullsize flag
|
96
96
|
ext = rem.split(".")[-1].lower()
|
97
|
-
if ext in ffa and fmt in ("wf", "jf"):
|
98
|
-
fmt = fmt
|
97
|
+
if ext in ffa and fmt[:2] in ("wf", "jf"):
|
98
|
+
fmt = fmt.replace("f", "")
|
99
99
|
|
100
100
|
rd += "\n" + fmt
|
101
101
|
h = hashlib.sha512(afsenc(rd)).digest()
|
@@ -197,9 +197,10 @@ class ThumbSrv(object):
|
|
197
197
|
with self.mutex:
|
198
198
|
return not self.nthr
|
199
199
|
|
200
|
-
def getres(self, vn ) :
|
200
|
+
def getres(self, vn , fmt ) :
|
201
|
+
mul = 3 if "3" in fmt else 1
|
201
202
|
w, h = vn.flags["thsize"].split("x")
|
202
|
-
return int(w), int(h)
|
203
|
+
return int(w) * mul, int(h) * mul
|
203
204
|
|
204
205
|
def get(self, ptop , rem , mtime , fmt ) :
|
205
206
|
histpath = self.asrv.vfs.histtab.get(ptop)
|
@@ -361,7 +362,7 @@ class ThumbSrv(object):
|
|
361
362
|
|
362
363
|
def fancy_pillow(self, im , fmt , vn ) :
|
363
364
|
# exif_transpose is expensive (loads full image + unconditional copy)
|
364
|
-
res = self.getres(vn)
|
365
|
+
res = self.getres(vn, fmt)
|
365
366
|
r = max(*res) * 2
|
366
367
|
im.thumbnail((r, r), resample=Image.LANCZOS)
|
367
368
|
try:
|
@@ -376,7 +377,7 @@ class ThumbSrv(object):
|
|
376
377
|
if rot in rots:
|
377
378
|
im = im.transpose(rots[rot])
|
378
379
|
|
379
|
-
if
|
380
|
+
if "f" in fmt:
|
380
381
|
im.thumbnail(res, resample=Image.LANCZOS)
|
381
382
|
else:
|
382
383
|
iw, ih = im.size
|
@@ -393,7 +394,7 @@ class ThumbSrv(object):
|
|
393
394
|
im = self.fancy_pillow(im, fmt, vn)
|
394
395
|
except Exception as ex:
|
395
396
|
self.log("fancy_pillow {}".format(ex), "90")
|
396
|
-
im.thumbnail(self.getres(vn))
|
397
|
+
im.thumbnail(self.getres(vn, fmt))
|
397
398
|
|
398
399
|
fmts = ["RGB", "L"]
|
399
400
|
args = {"quality": 40}
|
@@ -419,10 +420,10 @@ class ThumbSrv(object):
|
|
419
420
|
def conv_vips(self, abspath , tpath , fmt , vn ) :
|
420
421
|
self.wait4ram(0.2, tpath)
|
421
422
|
crops = ["centre", "none"]
|
422
|
-
if
|
423
|
+
if "f" in fmt:
|
423
424
|
crops = ["none"]
|
424
425
|
|
425
|
-
w, h = self.getres(vn)
|
426
|
+
w, h = self.getres(vn, fmt)
|
426
427
|
kw = {"height": h, "size": "down", "intent": "relative"}
|
427
428
|
|
428
429
|
for c in crops:
|
@@ -451,12 +452,12 @@ class ThumbSrv(object):
|
|
451
452
|
seek = [b"-ss", "{:.0f}".format(dur / 3).encode("utf-8")]
|
452
453
|
|
453
454
|
scale = "scale={0}:{1}:force_original_aspect_ratio="
|
454
|
-
if
|
455
|
+
if "f" in fmt:
|
455
456
|
scale += "decrease,setsar=1:1"
|
456
457
|
else:
|
457
458
|
scale += "increase,crop={0}:{1},setsar=1:1"
|
458
459
|
|
459
|
-
res = self.getres(vn)
|
460
|
+
res = self.getres(vn, fmt)
|
460
461
|
bscale = scale.format(*list(res)).encode("utf-8")
|
461
462
|
# fmt: off
|
462
463
|
cmd = [
|
@@ -591,7 +592,11 @@ class ThumbSrv(object):
|
|
591
592
|
need = 0.2 + dur / coeff
|
592
593
|
self.wait4ram(need, tpath)
|
593
594
|
|
594
|
-
fc = "[0:a:0]aresample=48000{},showspectrumpic=s=
|
595
|
+
fc = "[0:a:0]aresample=48000{},showspectrumpic=s="
|
596
|
+
if "3" in fmt:
|
597
|
+
fc += "1280x1024,crop=1420:1056:70:48[o]"
|
598
|
+
else:
|
599
|
+
fc += "640x512,crop=780:544:70:48[o]"
|
595
600
|
|
596
601
|
if self.args.th_ff_swr:
|
597
602
|
fco = ":filter_size=128:cutoff=0.877"
|
copyparty/up2k.py
CHANGED
@@ -151,7 +151,7 @@ class Up2k(object):
|
|
151
151
|
self.hashq = Queue()
|
152
152
|
|
153
153
|
|
154
|
-
self.tagq
|
154
|
+
self.tagq = Queue()
|
155
155
|
self.tag_event = threading.Condition()
|
156
156
|
self.hashq_mutex = threading.Lock()
|
157
157
|
self.n_hashq = 0
|
@@ -549,7 +549,7 @@ class Up2k(object):
|
|
549
549
|
runihook(self.log, cmd, vol, ups)
|
550
550
|
|
551
551
|
def _vis_job_progress(self, job ) :
|
552
|
-
perc = 100 - (len(job["need"]) * 100.0 / len(job["hash"]))
|
552
|
+
perc = 100 - (len(job["need"]) * 100.0 / (len(job["hash"]) or 1))
|
553
553
|
path = djoin(job["ptop"], job["prel"], job["name"])
|
554
554
|
return "{:5.1f}% {}".format(perc, path)
|
555
555
|
|
@@ -2052,12 +2052,13 @@ class Up2k(object):
|
|
2052
2052
|
return
|
2053
2053
|
|
2054
2054
|
try:
|
2055
|
+
st = bos.stat(qe.abspath)
|
2055
2056
|
if not qe.mtp:
|
2056
2057
|
if self.args.mtag_vv:
|
2057
2058
|
t = "tag-thr: {}({})"
|
2058
2059
|
self.log(t.format(self.mtag.backend, qe.abspath), "90")
|
2059
2060
|
|
2060
|
-
tags = self.mtag.get(qe.abspath)
|
2061
|
+
tags = self.mtag.get(qe.abspath) if st.st_size else {}
|
2061
2062
|
else:
|
2062
2063
|
if self.args.mtag_vv:
|
2063
2064
|
t = "tag-thr: {}({})"
|
@@ -2098,11 +2099,16 @@ class Up2k(object):
|
|
2098
2099
|
"""will mutex"""
|
2099
2100
|
assert self.mtag
|
2100
2101
|
|
2101
|
-
|
2102
|
+
try:
|
2103
|
+
st = bos.stat(abspath)
|
2104
|
+
except:
|
2105
|
+
return 0
|
2106
|
+
|
2107
|
+
if not stat.S_ISREG(st.st_mode):
|
2102
2108
|
return 0
|
2103
2109
|
|
2104
2110
|
try:
|
2105
|
-
tags = self.mtag.get(abspath)
|
2111
|
+
tags = self.mtag.get(abspath) if st.st_size else {}
|
2106
2112
|
except Exception as ex:
|
2107
2113
|
self._log_tag_err("", abspath, ex)
|
2108
2114
|
return 0
|
@@ -3095,7 +3101,7 @@ class Up2k(object):
|
|
3095
3101
|
raise
|
3096
3102
|
|
3097
3103
|
if "e2t" in self.flags[ptop]:
|
3098
|
-
self.tagq.put((ptop, wark, rd, fn, ip, at))
|
3104
|
+
self.tagq.put((ptop, wark, rd, fn, sz, ip, at))
|
3099
3105
|
self.n_tagq += 1
|
3100
3106
|
|
3101
3107
|
return True
|
@@ -3677,9 +3683,10 @@ class Up2k(object):
|
|
3677
3683
|
)
|
3678
3684
|
job = reg.get(wark) if wark else None
|
3679
3685
|
if job:
|
3680
|
-
|
3681
|
-
|
3682
|
-
|
3686
|
+
if job["need"]:
|
3687
|
+
t = "forgetting partial upload {} ({})"
|
3688
|
+
p = self._vis_job_progress(job)
|
3689
|
+
self.log(t.format(wark, p))
|
3683
3690
|
assert wark
|
3684
3691
|
del reg[wark]
|
3685
3692
|
|
@@ -4052,14 +4059,14 @@ class Up2k(object):
|
|
4052
4059
|
with self.mutex:
|
4053
4060
|
self.n_tagq -= 1
|
4054
4061
|
|
4055
|
-
ptop, wark, rd, fn, ip, at = self.tagq.get()
|
4062
|
+
ptop, wark, rd, fn, sz, ip, at = self.tagq.get()
|
4056
4063
|
if "e2t" not in self.flags[ptop]:
|
4057
4064
|
continue
|
4058
4065
|
|
4059
4066
|
# self.log("\n " + repr([ptop, rd, fn]))
|
4060
4067
|
abspath = djoin(ptop, rd, fn)
|
4061
4068
|
try:
|
4062
|
-
tags = self.mtag.get(abspath)
|
4069
|
+
tags = self.mtag.get(abspath) if sz else {}
|
4063
4070
|
ntags1 = len(tags)
|
4064
4071
|
parsers = self._get_parsers(ptop, tags, abspath)
|
4065
4072
|
if self.args.mtag_vv:
|
copyparty/util.py
CHANGED
@@ -1747,7 +1747,7 @@ def get_spd(nbyte , t0 , t = None) :
|
|
1747
1747
|
if t is None:
|
1748
1748
|
t = time.time()
|
1749
1749
|
|
1750
|
-
bps = nbyte / ((t - t0)
|
1750
|
+
bps = nbyte / ((t - t0) or 0.001)
|
1751
1751
|
s1 = humansize(nbyte).replace(" ", "\033[33m").replace("iB", "")
|
1752
1752
|
s2 = humansize(bps).replace(" ", "\033[35m").replace("iB", "")
|
1753
1753
|
return "%s \033[0m%s/s\033[0m" % (s1, s2)
|
copyparty/web/a/u2c.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
2
|
from __future__ import print_function, unicode_literals
|
3
3
|
|
4
|
-
S_VERSION = "1.
|
5
|
-
S_BUILD_DT = "2024-
|
4
|
+
S_VERSION = "1.15"
|
5
|
+
S_BUILD_DT = "2024-02-18"
|
6
6
|
|
7
7
|
"""
|
8
8
|
u2c.py: upload to copyparty
|
@@ -29,7 +29,7 @@ import platform
|
|
29
29
|
import threading
|
30
30
|
import datetime
|
31
31
|
|
32
|
-
EXE = sys
|
32
|
+
EXE = bool(getattr(sys, "frozen", False))
|
33
33
|
|
34
34
|
try:
|
35
35
|
import argparse
|
@@ -846,12 +846,12 @@ class Ctl(object):
|
|
846
846
|
txt = " "
|
847
847
|
|
848
848
|
if not self.up_br:
|
849
|
-
spd = self.hash_b / (time.time() - self.t0)
|
850
|
-
eta = (self.nbytes - self.hash_b) / (spd
|
849
|
+
spd = self.hash_b / ((time.time() - self.t0) or 1)
|
850
|
+
eta = (self.nbytes - self.hash_b) / (spd or 1)
|
851
851
|
else:
|
852
|
-
spd = self.up_br / (time.time() - self.t0_up)
|
852
|
+
spd = self.up_br / ((time.time() - self.t0_up) or 1)
|
853
853
|
spd = self.spd = (self.spd or spd) * 0.9 + spd * 0.1
|
854
|
-
eta = (self.nbytes - self.up_b) / (spd
|
854
|
+
eta = (self.nbytes - self.up_b) / (spd or 1)
|
855
855
|
|
856
856
|
spd = humansize(spd)
|
857
857
|
self.eta = str(datetime.timedelta(seconds=int(eta)))
|
copyparty/web/baguettebox.js.gz
CHANGED
Binary file
|
copyparty/web/browser.css.gz
CHANGED
Binary file
|
copyparty/web/browser.html
CHANGED
copyparty/web/browser.js.gz
CHANGED
Binary file
|
copyparty/web/browser2.html
CHANGED
copyparty/web/cf.html
CHANGED
copyparty/web/deps/marked.js.gz
CHANGED
Binary file
|
copyparty/web/md.html
CHANGED
copyparty/web/mde.html
CHANGED
copyparty/web/msg.html
CHANGED
copyparty/web/splash.html
CHANGED
copyparty/web/svcs.html
CHANGED
copyparty/web/ui.css.gz
CHANGED
Binary file
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: copyparty
|
3
|
-
Version: 1.10.
|
3
|
+
Version: 1.10.2
|
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
|
@@ -46,7 +46,7 @@ Requires-Dist: pyopenssl ; extra == 'ftps'
|
|
46
46
|
Provides-Extra: pwhash
|
47
47
|
Requires-Dist: argon2-cffi ; extra == 'pwhash'
|
48
48
|
Provides-Extra: tftpd
|
49
|
-
Requires-Dist: partftpy >=0.
|
49
|
+
Requires-Dist: partftpy >=0.3.0 ; extra == 'tftpd'
|
50
50
|
Provides-Extra: thumbnails
|
51
51
|
Requires-Dist: Pillow ; extra == 'thumbnails'
|
52
52
|
Provides-Extra: thumbnails2
|
@@ -1008,17 +1008,24 @@ a TFTP server (read/write) can be started using `--tftp 3969` (you probably wan
|
|
1008
1008
|
* based on [partftpy](https://github.com/9001/partftpy)
|
1009
1009
|
* no accounts; read from world-readable folders, write to world-writable, overwrite in world-deletable
|
1010
1010
|
* needs a dedicated port (cannot share with the HTTP/HTTPS API)
|
1011
|
-
* run as root to use the spec-recommended port `69` (nice)
|
1011
|
+
* run as root (or see below) to use the spec-recommended port `69` (nice)
|
1012
1012
|
* can reply from a predefined portrange (good for firewalls)
|
1013
1013
|
* only supports the binary/octet/image transfer mode (no netascii)
|
1014
1014
|
* [RFC 7440](https://datatracker.ietf.org/doc/html/rfc7440) is **not** supported, so will be extremely slow over WAN
|
1015
|
-
* expect 1100 KiB/s over
|
1015
|
+
* assuming default blksize (512), expect 1100 KiB/s over 100BASE-T, 400-500 KiB/s over wifi, 200 on bad wifi
|
1016
|
+
|
1017
|
+
most clients expect to find TFTP on port 69, but on linux and macos you need to be root to listen on that. Alternatively, listen on 3969 and use NAT on the server to forward 69 to that port;
|
1018
|
+
* on linux: `iptables -t nat -A PREROUTING -i eth0 -p udp --dport 69 -j REDIRECT --to-port 3969`
|
1016
1019
|
|
1017
1020
|
some recommended TFTP clients:
|
1021
|
+
* curl (cross-platform, read/write)
|
1022
|
+
* get: `curl --tftp-blksize 1428 tftp://127.0.0.1:3969/firmware.bin`
|
1023
|
+
* put: `curl --tftp-blksize 1428 -T firmware.bin tftp://127.0.0.1:3969/`
|
1018
1024
|
* windows: `tftp.exe` (you probably already have it)
|
1025
|
+
* `tftp -i 127.0.0.1 put firmware.bin`
|
1019
1026
|
* linux: `tftp-hpa`, `atftp`
|
1020
|
-
* `
|
1021
|
-
* `
|
1027
|
+
* `atftp --option "blksize 1428" 127.0.0.1 3969 -p -l firmware.bin -r firmware.bin`
|
1028
|
+
* `tftp -v -m binary 127.0.0.1 3969 -c put firmware.bin`
|
1022
1029
|
|
1023
1030
|
|
1024
1031
|
## smb server
|
@@ -1051,7 +1058,7 @@ known client bugs:
|
|
1051
1058
|
* however smb1 is buggy and is not enabled by default on win10 onwards
|
1052
1059
|
* windows cannot access folders which contain filenames with invalid unicode or forbidden characters (`<>:"/\|?*`), or names ending with `.`
|
1053
1060
|
|
1054
|
-
the smb protocol listens on TCP port 445, which is a privileged port on linux and macos, which would require running copyparty as root. However, this can be avoided by listening on another port using `--smb-port 3945` and then using NAT to forward the traffic from 445 to there;
|
1061
|
+
the smb protocol listens on TCP port 445, which is a privileged port on linux and macos, which would require running copyparty as root. However, this can be avoided by listening on another port using `--smb-port 3945` and then using NAT on the server to forward the traffic from 445 to there;
|
1055
1062
|
* on linux: `iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 445 -j REDIRECT --to-port 3945`
|
1056
1063
|
|
1057
1064
|
authenticate with one of the following:
|
@@ -1,20 +1,20 @@
|
|
1
1
|
copyparty/__init__.py,sha256=34xcU8AoRRQscgVSx2gC6DeUyu7ZLmEVlXjttdQgXnI,1752
|
2
|
-
copyparty/__main__.py,sha256=
|
3
|
-
copyparty/__version__.py,sha256=
|
4
|
-
copyparty/authsrv.py,sha256=
|
2
|
+
copyparty/__main__.py,sha256=wK7Fop32aq7LUKmBCQcp3A6bJ2abdpj3em9IigFyniI,91595
|
3
|
+
copyparty/__version__.py,sha256=z7G2R3a_jwf2rpKu1PpKRwOFSv86M6MOa1nRTzu_t9I,246
|
4
|
+
copyparty/authsrv.py,sha256=BzJwPbYhTr9etW50DMY0UXRHBdNOKdnSdTuZ4qXlNvs,73470
|
5
5
|
copyparty/broker_mp.py,sha256=4mEZC5tiHUazJMgYuwInNo2dxS7jrbzrGb1qs2UBt9k,3948
|
6
6
|
copyparty/broker_mpw.py,sha256=4ZI7bJYOwUibeAJVv9_FPGNmHrr9eOtkj_Kz0JEppTU,3197
|
7
7
|
copyparty/broker_thr.py,sha256=eKr--HJGig5zqvNGwH9UoBG9Nvi9mT2axrRmJwknd0s,1759
|
8
8
|
copyparty/broker_util.py,sha256=CnX_LAhQQqouONcDLtVkVlcBX3Z6pWuKDQDmmbHGEg4,1489
|
9
9
|
copyparty/cert.py,sha256=bt1n-629-Gtez1C_CroXq53gXEmUsVjkTbkQ6Gu2Zfc,7323
|
10
|
-
copyparty/cfg.py,sha256=
|
10
|
+
copyparty/cfg.py,sha256=XMqgS5JMcTe4vCmAnUkSXrKBPTzn0zHYsBenXcZNK_s,9000
|
11
11
|
copyparty/dxml.py,sha256=lZpg-kn-kQsXRtNY1n6fRaS-b7uXzMCyv8ovKnhZcZc,1548
|
12
12
|
copyparty/fsutil.py,sha256=c4fTvmclKbVABNsjU4rGddsjCgRwi9YExAyo-06ATc8,3932
|
13
|
-
copyparty/ftpd.py,sha256=
|
14
|
-
copyparty/httpcli.py,sha256=
|
13
|
+
copyparty/ftpd.py,sha256=BqxH4j-mLrjRvxW3Lnz-qrR4_ETv3OnmIRNifSf_3Fk,15939
|
14
|
+
copyparty/httpcli.py,sha256=YoumInsa3mzoJXQHjznsPpDYuKuzx0DoLXgx6vy8Oew,142323
|
15
15
|
copyparty/httpconn.py,sha256=XyFv6yIsyq0InrqulwovsmAcqziEq_O2zsI41K8bJWs,6698
|
16
16
|
copyparty/httpsrv.py,sha256=q0z4RuoTMiZz_QbUSCFikIDbKHm9_JT1uGTGuDvOdO0,16218
|
17
|
-
copyparty/ico.py,sha256=
|
17
|
+
copyparty/ico.py,sha256=AYHdK6NlYBfBgafVYXia3jHQ9XHZdUL1D8WftLMAzIU,3545
|
18
18
|
copyparty/mdns.py,sha256=CcraggbDxTT1ntYzD8Ebgqmw5Q4HkyZcfh5ymtCV_ak,17469
|
19
19
|
copyparty/metrics.py,sha256=glBeNYGWMF4zEK9__aKks7qKnSwwJuWAzPx6ljRYt4k,8754
|
20
20
|
copyparty/mtag.py,sha256=OZM6cVJafOe_LZ4bPJzVJbORA_omzewwJh-N11u3nak,16855
|
@@ -27,12 +27,12 @@ copyparty/sutil.py,sha256=dZhDAzVAp02i6YmGqcedy4LaYVffnJCSp3F6WEwfz7c,2967
|
|
27
27
|
copyparty/svchub.py,sha256=LyhbfI4pYga-X7VSsbyzx3xM5kn2e4Z6bSObU4cRU0w,29036
|
28
28
|
copyparty/szip.py,sha256=SJg5nzN_5oaIsIYXlRvcLHVTqngLAOPfe4_WVsuhSkw,8520
|
29
29
|
copyparty/tcpsrv.py,sha256=2LGUqOBAIrsmL-1pwrbsPXR71gutHccqRp-hjzt91Us,17289
|
30
|
-
copyparty/tftpd.py,sha256=
|
31
|
-
copyparty/th_cli.py,sha256=
|
32
|
-
copyparty/th_srv.py,sha256=
|
30
|
+
copyparty/tftpd.py,sha256=yM_byDfFI2c7TwgDbTtw9xt3LWJ3PBBHfIsMsB6MDow,13028
|
31
|
+
copyparty/th_cli.py,sha256=e2FF-wVY4qcwAO8hrtTlwn3EJIOHyZt5sYhl0N8eudk,4378
|
32
|
+
copyparty/th_srv.py,sha256=HBw6mq0RrJkAJupJpwFAjCMNS67Y9hda6sv7gFSzRwk,25764
|
33
33
|
copyparty/u2idx.py,sha256=JBEqKX1ZM8GIvQrDYb5VQ_5QiFNFsjWF6H9drHlPVEY,12709
|
34
|
-
copyparty/up2k.py,sha256=
|
35
|
-
copyparty/util.py,sha256=
|
34
|
+
copyparty/up2k.py,sha256=zWPrcddZyxwy2rEfjJEOm-bQgt6ydzDSSOtVcYCnWYA,137144
|
35
|
+
copyparty/util.py,sha256=9WQ9itm24ZP1n5qB9lsWpiQqSB2IKdHPxl3y6RIgQAM,79683
|
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
|
@@ -54,35 +54,35 @@ copyparty/stolen/ifaddr/__init__.py,sha256=_BUN7eM5oD2Jgib6B22tEFSb20fD9urNPPaAl
|
|
54
54
|
copyparty/stolen/ifaddr/_posix.py,sha256=-67NdfGrCktfQPakT2fLbjl2U00QMvyBGkSvrUuTOrU,2626
|
55
55
|
copyparty/stolen/ifaddr/_shared.py,sha256=cJACl8cOxQ-HSYphZTzKMAjAx_TAFyJwUPjfD102Xqw,6111
|
56
56
|
copyparty/stolen/ifaddr/_win32.py,sha256=EE-QyoBgeB7lYQ6z62VjXNaRozaYfCkaJBHGNA8QtZM,4026
|
57
|
-
copyparty/web/baguettebox.js.gz,sha256=
|
58
|
-
copyparty/web/browser.css.gz,sha256=
|
59
|
-
copyparty/web/browser.html,sha256=
|
60
|
-
copyparty/web/browser.js.gz,sha256=
|
61
|
-
copyparty/web/browser2.html,sha256=
|
62
|
-
copyparty/web/cf.html,sha256=
|
57
|
+
copyparty/web/baguettebox.js.gz,sha256=BxwvSjky72hZprWofueRrlskiIeRrgGERUpKiZXQ5C8,7671
|
58
|
+
copyparty/web/browser.css.gz,sha256=_C5z5xYMkKGnwT_y_dmQzbQBkXbYn6h0KWGdiMv_7yQ,11380
|
59
|
+
copyparty/web/browser.html,sha256=72E2Q6grz_MtkmFVIXE_0rOVzliyQo-XwuawkJsB-qY,4873
|
60
|
+
copyparty/web/browser.js.gz,sha256=NdOb9VBrO_ETpDt6LBhoUPPhiehYEckDCzVZndfpmG0,66579
|
61
|
+
copyparty/web/browser2.html,sha256=AtGRGtb_rsyu-gWXEuXDMg9WqbjJFcDDJXel3ScG-4c,1605
|
62
|
+
copyparty/web/cf.html,sha256=lJThtNFNAQT1ClCHHlivAkDGE0LutedwopXD62Z8Nys,589
|
63
63
|
copyparty/web/dbg-audio.js.gz,sha256=Ma-KZtK8LnmiwNvNKFKXMPYl_Nn_3U7GsJ6-DRWC2HE,688
|
64
64
|
copyparty/web/md.css.gz,sha256=DadSn01UeCBE47AKqCjmrc7x2ZLZMwl4f__RhGCDzS4,2011
|
65
|
-
copyparty/web/md.html,sha256=
|
65
|
+
copyparty/web/md.html,sha256=QdrN1-58IgdXj6QnT9w3_nbT825A6UWknj6WOKxn69I,4110
|
66
66
|
copyparty/web/md.js.gz,sha256=7uNDAB8ctTLm4vr3ui-hfqusn7rORDOJfydonOFEWCU,4277
|
67
67
|
copyparty/web/md2.css.gz,sha256=bM_1hsegXnEig1b6OQ28yWWUlMPje6u9M58VZ1Z-C9g,681
|
68
68
|
copyparty/web/md2.js.gz,sha256=P47IdvqfOaDSnAxKk-0K8au9yUkH3be6t4YZ8AosDtI,8343
|
69
69
|
copyparty/web/mde.css.gz,sha256=L6YhxnYBoqT5bSwD99rx8ALXDh8d_1-sCvbc_p3MoAU,929
|
70
|
-
copyparty/web/mde.html,sha256=
|
70
|
+
copyparty/web/mde.html,sha256=1KPTKGFxTTuJ9Zp9OBdmm1DREtSvijqnlsZoNTpv7q0,1678
|
71
71
|
copyparty/web/mde.js.gz,sha256=eo-UjMKIbRcPL6LR8BDl4IkCGcpJyFK0mhYte7WgqLc,2219
|
72
72
|
copyparty/web/msg.css.gz,sha256=-wOmwxU0_Xg2W53rIAjKA2TeFAVQNJeT8ZMtmiJiviY,252
|
73
|
-
copyparty/web/msg.html,sha256
|
73
|
+
copyparty/web/msg.html,sha256=-MPzXZnHzQNuX04-aSn_fA7L15GASOHnCyeS1eVCYUI,896
|
74
74
|
copyparty/web/splash.css.gz,sha256=ZJ1E7wWGYBVl50ytkxdYkLsLDhRJtGwP2-YdMUo7MgI,927
|
75
|
-
copyparty/web/splash.html,sha256=
|
75
|
+
copyparty/web/splash.html,sha256=4ZgHc7v1C9ABwzde4UvlsyTCtkmIwKVMXm-3rHcFXsM,3782
|
76
76
|
copyparty/web/splash.js.gz,sha256=3PMKsMLwEsHP8eonBmtvonm9yeNq69xjMi8ZqnVeKcA,1255
|
77
|
-
copyparty/web/svcs.html,sha256=
|
77
|
+
copyparty/web/svcs.html,sha256=Jn-G2QMF09oc01C_tmJwGZAdjFzbeu4unLSs6dowluM,11702
|
78
78
|
copyparty/web/svcs.js.gz,sha256=k81ZvZ3I-f4fMHKrNGGOgOlvXnCBz0mVjD-8mieoWCA,520
|
79
|
-
copyparty/web/ui.css.gz,sha256=
|
79
|
+
copyparty/web/ui.css.gz,sha256=oyrc_sf0u-KycOUV7FoRI7uF6oK6ruQ13Qzyz-7rad8,2567
|
80
80
|
copyparty/web/up2k.js.gz,sha256=mT9u6jZFWjTTVgNodHrMvmuQ-sp7N4S6AtJHlrbOqoE,22027
|
81
81
|
copyparty/web/util.js.gz,sha256=ig-Cs_fMqw4yZ0psAPTagr_0GkKQNXH2iCEprmfB9W4,14283
|
82
82
|
copyparty/web/w.hash.js.gz,sha256=__hBMd5oZWfTrb8ZCJNT21isoSqyrxKE6qdaKGQVAhc,1060
|
83
83
|
copyparty/web/a/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
84
84
|
copyparty/web/a/partyfuse.py,sha256=MuRkaSuYsdfWfBFMOkbPwDXqSvNTw3sd7QhhlKCDZ8I,32311
|
85
|
-
copyparty/web/a/u2c.py,sha256=
|
85
|
+
copyparty/web/a/u2c.py,sha256=Yo_zsjBg1Op53sPFhzcbAkd-VZlm6nZ4DMVN_s0Yu2k,38469
|
86
86
|
copyparty/web/a/webdav-cfg.bat,sha256=Y4NoGZlksAIg4cBMb7KdJrpKC6Nx97onaTl6yMjaimk,1449
|
87
87
|
copyparty/web/dd/2.png,sha256=gJ14XFPzaw95L6z92fSq9eMPikSQyu-03P1lgiGe0_I,258
|
88
88
|
copyparty/web/dd/3.png,sha256=4lho8Koz5tV7jJ4ODo6GMTScZfkqsT05yp48EDFIlyg,252
|
@@ -90,7 +90,7 @@ copyparty/web/dd/4.png,sha256=fIwEVmtZNZtloZuVEKPKnkx3SELwRJmB3US61y7t2lI,248
|
|
90
90
|
copyparty/web/dd/5.png,sha256=Lfpu8-yOlhONuoMbygloKqQVPXSm9gjxH2gUYn5QQAE,250
|
91
91
|
copyparty/web/dd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
92
92
|
copyparty/web/deps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
93
|
-
copyparty/web/deps/marked.js.gz,sha256=
|
93
|
+
copyparty/web/deps/marked.js.gz,sha256=WhUw0LPWs5cxqORQmW-zajQiUc5rSRkcvf3eT3-XSZc,22372
|
94
94
|
copyparty/web/deps/mini-fa.css.gz,sha256=CTPrNaH8OTVmxajrGP88E2MkjadY9_81TBVnd9sw9Y8,572
|
95
95
|
copyparty/web/deps/mini-fa.woff,sha256=L9DNncV2TIyvsrspMbJouvnnt7F068Hbn7YZYvN76AU,2784
|
96
96
|
copyparty/web/deps/prism.css.gz,sha256=Z_A6rJ3MN5KWnjvXaV787aTW_5DT-xjFd0YZ7_W-Krk,1468
|
@@ -99,9 +99,9 @@ copyparty/web/deps/prismd.css.gz,sha256=ObUlksQVr-OuYlTz-I4B23TeBg2QDVVGRnWBz8cV
|
|
99
99
|
copyparty/web/deps/scp.woff2,sha256=w99BDU5i8MukkMEL-iW0YO9H4vFFZSPWxbkH70ytaAg,8612
|
100
100
|
copyparty/web/deps/sha512.ac.js.gz,sha256=lFZaCLumgWxrvEuDr4bqdKHsqjX82AbVAb7_F45Yk88,7033
|
101
101
|
copyparty/web/deps/sha512.hw.js.gz,sha256=vqoXeracj-99Z5MfY3jK2N4WiSzYQdfjy0RnUlQDhSU,8110
|
102
|
-
copyparty-1.10.
|
103
|
-
copyparty-1.10.
|
104
|
-
copyparty-1.10.
|
105
|
-
copyparty-1.10.
|
106
|
-
copyparty-1.10.
|
107
|
-
copyparty-1.10.
|
102
|
+
copyparty-1.10.2.dist-info/LICENSE,sha256=gOr4h33pCsBEg9uIy9AYmb7qlocL4V9t2uPJS5wllr0,1072
|
103
|
+
copyparty-1.10.2.dist-info/METADATA,sha256=VztHHVGSLDK0ZRVxlGhBN2WuBCO3fpz6rbK0iVROAYY,112378
|
104
|
+
copyparty-1.10.2.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
105
|
+
copyparty-1.10.2.dist-info/entry_points.txt,sha256=4zw6a3rqASywQomiYLObjjlxybaI65LYYOTJwgKz7b0,128
|
106
|
+
copyparty-1.10.2.dist-info/top_level.txt,sha256=LnYUPsDyk-8kFgM6YJLG4h820DQekn81cObKSu9g-sI,10
|
107
|
+
copyparty-1.10.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|