copyparty 1.13.6__py3-none-any.whl → 1.13.7__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 +25 -7
- copyparty/__version__.py +2 -2
- copyparty/authsrv.py +9 -6
- copyparty/cert.py +1 -1
- copyparty/fsutil.py +3 -3
- copyparty/ftpd.py +15 -2
- copyparty/httpcli.py +221 -81
- copyparty/httpconn.py +3 -0
- copyparty/httpsrv.py +35 -11
- copyparty/ico.py +1 -1
- copyparty/mtag.py +15 -6
- copyparty/pwhash.py +10 -0
- copyparty/smbd.py +20 -2
- copyparty/ssdp.py +3 -3
- copyparty/stolen/dnslib/dns.py +6 -0
- copyparty/stolen/ifaddr/__init__.py +15 -1
- copyparty/stolen/ifaddr/_shared.py +1 -0
- copyparty/stolen/qrcodegen.py +6 -0
- copyparty/sutil.py +1 -1
- copyparty/svchub.py +72 -3
- copyparty/szip.py +1 -3
- copyparty/tcpsrv.py +60 -8
- copyparty/tftpd.py +30 -4
- copyparty/th_srv.py +22 -1
- copyparty/u2idx.py +4 -1
- copyparty/up2k.py +221 -93
- copyparty/util.py +166 -31
- copyparty/web/a/u2c.py +10 -3
- copyparty/web/browser.css.gz +0 -0
- copyparty/web/browser2.html +0 -1
- copyparty/web/md.html +3 -0
- copyparty/web/mde.html +3 -0
- copyparty/web/msg.html +3 -0
- copyparty/web/splash.html +3 -0
- copyparty/web/svcs.html +3 -0
- copyparty/web/up2k.js.gz +0 -0
- {copyparty-1.13.6.dist-info → copyparty-1.13.7.dist-info}/METADATA +64 -14
- {copyparty-1.13.6.dist-info → copyparty-1.13.7.dist-info}/RECORD +42 -42
- {copyparty-1.13.6.dist-info → copyparty-1.13.7.dist-info}/LICENSE +0 -0
- {copyparty-1.13.6.dist-info → copyparty-1.13.7.dist-info}/WHEEL +0 -0
- {copyparty-1.13.6.dist-info → copyparty-1.13.7.dist-info}/entry_points.txt +0 -0
- {copyparty-1.13.6.dist-info → copyparty-1.13.7.dist-info}/top_level.txt +0 -0
copyparty/mtag.py
CHANGED
@@ -26,6 +26,17 @@ from .util import (
|
|
26
26
|
wunlink,
|
27
27
|
)
|
28
28
|
|
29
|
+
try:
|
30
|
+
if os.environ.get("PRTY_NO_MUTAGEN"):
|
31
|
+
raise Exception()
|
32
|
+
|
33
|
+
from mutagen import version # noqa: F401
|
34
|
+
|
35
|
+
HAVE_MUTAGEN = True
|
36
|
+
except:
|
37
|
+
HAVE_MUTAGEN = False
|
38
|
+
|
39
|
+
|
29
40
|
def have_ff(scmd ) :
|
30
41
|
if ANYWIN:
|
31
42
|
scmd += ".exe"
|
@@ -42,8 +53,8 @@ def have_ff(scmd ) :
|
|
42
53
|
return bool(shutil.which(scmd))
|
43
54
|
|
44
55
|
|
45
|
-
HAVE_FFMPEG = have_ff("ffmpeg")
|
46
|
-
HAVE_FFPROBE = have_ff("ffprobe")
|
56
|
+
HAVE_FFMPEG = not os.environ.get("PRTY_NO_FFMPEG") and have_ff("ffmpeg")
|
57
|
+
HAVE_FFPROBE = not os.environ.get("PRTY_NO_FFPROBE") and have_ff("ffprobe")
|
47
58
|
|
48
59
|
|
49
60
|
class MParser(object):
|
@@ -330,9 +341,7 @@ class MTag(object):
|
|
330
341
|
|
331
342
|
if self.backend == "mutagen":
|
332
343
|
self._get = self.get_mutagen
|
333
|
-
|
334
|
-
from mutagen import version # noqa: F401
|
335
|
-
except:
|
344
|
+
if not HAVE_MUTAGEN:
|
336
345
|
self.log("could not load Mutagen, trying FFprobe instead", c=3)
|
337
346
|
self.backend = "ffprobe"
|
338
347
|
|
@@ -572,7 +581,7 @@ class MTag(object):
|
|
572
581
|
continue
|
573
582
|
|
574
583
|
if k == ".aq":
|
575
|
-
v /= 1000
|
584
|
+
v /= 1000 # type: ignore
|
576
585
|
|
577
586
|
if k == "ac" and v.startswith("mp4a.40."):
|
578
587
|
v = "aac"
|
copyparty/pwhash.py
CHANGED
@@ -4,11 +4,21 @@ from __future__ import print_function, unicode_literals
|
|
4
4
|
import argparse
|
5
5
|
import base64
|
6
6
|
import hashlib
|
7
|
+
import os
|
7
8
|
import sys
|
8
9
|
import threading
|
9
10
|
|
10
11
|
from .__init__ import unicode
|
11
12
|
|
13
|
+
try:
|
14
|
+
if os.environ.get("PRTY_NO_ARGON2"):
|
15
|
+
raise Exception()
|
16
|
+
|
17
|
+
HAVE_ARGON2 = True
|
18
|
+
from argon2 import __version__ as argon2ver
|
19
|
+
except:
|
20
|
+
HAVE_ARGON2 = False
|
21
|
+
|
12
22
|
|
13
23
|
class PWHash(object):
|
14
24
|
def __init__(self, args ):
|
copyparty/smbd.py
CHANGED
@@ -184,6 +184,8 @@ class SMB(object):
|
|
184
184
|
|
185
185
|
debug('%s("%s", %s) %s @%s\033[K\033[0m', caller, vpath, str(a), perms, uname)
|
186
186
|
vfs, rem = self.asrv.vfs.get(vpath, uname, *perms)
|
187
|
+
if not vfs.realpath:
|
188
|
+
raise Exception("unmapped vfs")
|
187
189
|
return vfs, vfs.canonical(rem)
|
188
190
|
|
189
191
|
def _listdir(self, vpath , *a , **ka ) :
|
@@ -192,6 +194,8 @@ class SMB(object):
|
|
192
194
|
uname = self._uname()
|
193
195
|
# debug('listdir("%s", %s) @%s\033[K\033[0m', vpath, str(a), uname)
|
194
196
|
vfs, rem = self.asrv.vfs.get(vpath, uname, False, False)
|
197
|
+
if not vfs.realpath:
|
198
|
+
raise Exception("unmapped vfs")
|
195
199
|
_, vfs_ls, vfs_virt = vfs.ls(
|
196
200
|
rem, uname, not self.args.no_scandir, [[False, False]]
|
197
201
|
)
|
@@ -237,7 +241,21 @@ class SMB(object):
|
|
237
241
|
|
238
242
|
xbu = vfs.flags.get("xbu")
|
239
243
|
if xbu and not runhook(
|
240
|
-
self.nlog,
|
244
|
+
self.nlog,
|
245
|
+
None,
|
246
|
+
self.hub.up2k,
|
247
|
+
"xbu.smb",
|
248
|
+
xbu,
|
249
|
+
ap,
|
250
|
+
vpath,
|
251
|
+
"",
|
252
|
+
"",
|
253
|
+
"",
|
254
|
+
0,
|
255
|
+
0,
|
256
|
+
"1.7.6.2",
|
257
|
+
time.time(),
|
258
|
+
"",
|
241
259
|
):
|
242
260
|
yeet("blocked by xbu server config: " + vpath)
|
243
261
|
|
@@ -294,7 +312,7 @@ class SMB(object):
|
|
294
312
|
t = "blocked rename (no-move-acc %s): /%s @%s"
|
295
313
|
yeet(t % (vfs1.axs.umove, vp1, uname))
|
296
314
|
|
297
|
-
self.hub.up2k.handle_mv(uname, vp1, vp2)
|
315
|
+
self.hub.up2k.handle_mv(uname, "1.7.6.2", vp1, vp2)
|
298
316
|
try:
|
299
317
|
bos.makedirs(ap2)
|
300
318
|
except:
|
copyparty/ssdp.py
CHANGED
@@ -5,11 +5,11 @@ import errno
|
|
5
5
|
import re
|
6
6
|
import select
|
7
7
|
import socket
|
8
|
-
|
8
|
+
import time
|
9
9
|
|
10
10
|
from .__init__ import TYPE_CHECKING
|
11
11
|
from .multicast import MC_Sck, MCast
|
12
|
-
from .util import CachedSet, html_escape, min_ex
|
12
|
+
from .util import CachedSet, formatdate, html_escape, min_ex
|
13
13
|
|
14
14
|
if TYPE_CHECKING:
|
15
15
|
from .broker_util import BrokerCli
|
@@ -225,7 +225,7 @@ CONFIGID.UPNP.ORG: 1
|
|
225
225
|
|
226
226
|
"""
|
227
227
|
v4 = srv.ip.replace("::ffff:", "")
|
228
|
-
zs = zs.format(formatdate(
|
228
|
+
zs = zs.format(formatdate(), v4, srv.hport, self.args.zsid)
|
229
229
|
zb = zs[1:].replace("\n", "\r\n").encode("utf-8", "replace")
|
230
230
|
srv.sck.sendto(zb, addr[:2])
|
231
231
|
|
copyparty/stolen/dnslib/dns.py
CHANGED
@@ -11,7 +11,21 @@ import os
|
|
11
11
|
|
12
12
|
from ._shared import IP, Adapter
|
13
13
|
|
14
|
-
|
14
|
+
|
15
|
+
def nope(include_unconfigured=False):
|
16
|
+
return []
|
17
|
+
|
18
|
+
|
19
|
+
try:
|
20
|
+
S390X = os.uname().machine == "s390x"
|
21
|
+
except:
|
22
|
+
S390X = False
|
23
|
+
|
24
|
+
|
25
|
+
if os.environ.get("PRTY_NO_IFADDR") or S390X:
|
26
|
+
# s390x deadlocks at libc.getifaddrs
|
27
|
+
get_adapters = nope
|
28
|
+
elif os.name == "nt":
|
15
29
|
from ._win32 import get_adapters
|
16
30
|
elif os.name == "posix":
|
17
31
|
from ._posix import get_adapters
|
copyparty/stolen/qrcodegen.py
CHANGED
copyparty/sutil.py
CHANGED
copyparty/svchub.py
CHANGED
@@ -22,18 +22,30 @@ from datetime import datetime, timedelta
|
|
22
22
|
# print(currentframe().f_lineno)
|
23
23
|
|
24
24
|
|
25
|
-
from .__init__ import ANYWIN, EXE, MACOS, TYPE_CHECKING, E, EnvParams, unicode
|
25
|
+
from .__init__ import ANYWIN, EXE, MACOS, PY2, TYPE_CHECKING, E, EnvParams, unicode
|
26
26
|
from .authsrv import BAD_CFG, AuthSrv
|
27
27
|
from .cert import ensure_cert
|
28
|
-
from .mtag import HAVE_FFMPEG, HAVE_FFPROBE
|
28
|
+
from .mtag import HAVE_FFMPEG, HAVE_FFPROBE, HAVE_MUTAGEN
|
29
|
+
from .pwhash import HAVE_ARGON2
|
29
30
|
from .tcpsrv import TcpSrv
|
30
|
-
from .th_srv import
|
31
|
+
from .th_srv import (
|
32
|
+
HAVE_AVIF,
|
33
|
+
HAVE_FFMPEG,
|
34
|
+
HAVE_FFPROBE,
|
35
|
+
HAVE_HEIF,
|
36
|
+
HAVE_PIL,
|
37
|
+
HAVE_VIPS,
|
38
|
+
HAVE_WEBP,
|
39
|
+
ThumbSrv,
|
40
|
+
)
|
31
41
|
from .up2k import Up2k
|
32
42
|
from .util import (
|
33
43
|
DEF_EXP,
|
34
44
|
DEF_MTE,
|
35
45
|
DEF_MTH,
|
36
46
|
FFMPEG_URL,
|
47
|
+
HAVE_PSUTIL,
|
48
|
+
HAVE_SQLITE3,
|
37
49
|
UTC,
|
38
50
|
VERSIONS,
|
39
51
|
Daemon,
|
@@ -59,6 +71,9 @@ if TYPE_CHECKING:
|
|
59
71
|
except:
|
60
72
|
pass
|
61
73
|
|
74
|
+
if PY2:
|
75
|
+
range = xrange # type: ignore
|
76
|
+
|
62
77
|
|
63
78
|
class SvcHub(object):
|
64
79
|
"""
|
@@ -226,6 +241,8 @@ class SvcHub(object):
|
|
226
241
|
|
227
242
|
self.up2k = Up2k(self)
|
228
243
|
|
244
|
+
self._feature_test()
|
245
|
+
|
229
246
|
decs = {k: 1 for k in self.args.th_dec.split(",")}
|
230
247
|
if not HAVE_VIPS:
|
231
248
|
decs.pop("vips", None)
|
@@ -414,6 +431,58 @@ class SvcHub(object):
|
|
414
431
|
|
415
432
|
Daemon(self.sd_notify, "sd-notify")
|
416
433
|
|
434
|
+
def _feature_test(self) :
|
435
|
+
fok = []
|
436
|
+
fng = []
|
437
|
+
t_ff = "transcode audio, create spectrograms, video thumbnails"
|
438
|
+
to_check = [
|
439
|
+
(HAVE_SQLITE3, "sqlite", "file and media indexing"),
|
440
|
+
(HAVE_PIL, "pillow", "image thumbnails (plenty fast)"),
|
441
|
+
(HAVE_VIPS, "vips", "image thumbnails (faster, eats more ram)"),
|
442
|
+
(HAVE_WEBP, "pillow-webp", "create thumbnails as webp files"),
|
443
|
+
(HAVE_FFMPEG, "ffmpeg", t_ff + ", good-but-slow image thumbnails"),
|
444
|
+
(HAVE_FFPROBE, "ffprobe", t_ff + ", read audio/media tags"),
|
445
|
+
(HAVE_MUTAGEN, "mutagen", "read audio tags (ffprobe is better but slower)"),
|
446
|
+
(HAVE_ARGON2, "argon2", "secure password hashing (advanced users only)"),
|
447
|
+
(HAVE_HEIF, "pillow-heif", "read .heif images with pillow (rarely useful)"),
|
448
|
+
(HAVE_AVIF, "pillow-avif", "read .avif images with pillow (rarely useful)"),
|
449
|
+
]
|
450
|
+
if ANYWIN:
|
451
|
+
to_check += [
|
452
|
+
(HAVE_PSUTIL, "psutil", "improved plugin cleanup (rarely useful)")
|
453
|
+
]
|
454
|
+
|
455
|
+
verbose = self.args.deps
|
456
|
+
if verbose:
|
457
|
+
self.log("dependencies", "")
|
458
|
+
|
459
|
+
for have, feat, what in to_check:
|
460
|
+
lst = fok if have else fng
|
461
|
+
lst.append((feat, what))
|
462
|
+
if verbose:
|
463
|
+
zi = 2 if have else 5
|
464
|
+
sgot = "found" if have else "missing"
|
465
|
+
t = "%7s: %s \033[36m(%s)"
|
466
|
+
self.log("dependencies", t % (sgot, feat, what), zi)
|
467
|
+
|
468
|
+
if verbose:
|
469
|
+
self.log("dependencies", "")
|
470
|
+
return
|
471
|
+
|
472
|
+
sok = ", ".join(x[0] for x in fok)
|
473
|
+
sng = ", ".join(x[0] for x in fng)
|
474
|
+
|
475
|
+
t = ""
|
476
|
+
if sok:
|
477
|
+
t += "OK: \033[32m" + sok
|
478
|
+
if sng:
|
479
|
+
if t:
|
480
|
+
t += ", "
|
481
|
+
t += "\033[0mNG: \033[35m" + sng
|
482
|
+
|
483
|
+
t += "\033[0m, see --deps"
|
484
|
+
self.log("dependencies", t, 6)
|
485
|
+
|
417
486
|
def _check_env(self) :
|
418
487
|
try:
|
419
488
|
files = os.listdir(E.cfg)
|
copyparty/szip.py
CHANGED
@@ -31,9 +31,7 @@ def dostime2unix(buf ) :
|
|
31
31
|
|
32
32
|
|
33
33
|
def unixtime2dos(ts ) :
|
34
|
-
|
35
|
-
dy, dm, dd, th, tm, ts = list(tt)[:6]
|
36
|
-
|
34
|
+
dy, dm, dd, th, tm, ts, _, _, _ = time.gmtime(ts + 1)
|
37
35
|
bd = ((dy - 1980) << 9) + (dm << 5) + dd
|
38
36
|
bt = (th << 11) + (tm << 5) + ts // 2
|
39
37
|
try:
|
copyparty/tcpsrv.py
CHANGED
@@ -17,7 +17,9 @@ from .util import (
|
|
17
17
|
E_UNREACH,
|
18
18
|
HAVE_IPV6,
|
19
19
|
IP6ALL,
|
20
|
+
VF_CAREFUL,
|
20
21
|
Netdev,
|
22
|
+
atomic_move,
|
21
23
|
min_ex,
|
22
24
|
sunpack,
|
23
25
|
termsize,
|
@@ -214,14 +216,29 @@ class TcpSrv(object):
|
|
214
216
|
if self.args.qr or self.args.qrs:
|
215
217
|
self.qr = self._qr(qr1, qr2)
|
216
218
|
|
219
|
+
def nlog(self, msg , c = 0) :
|
220
|
+
self.log("tcpsrv", msg, c)
|
221
|
+
|
217
222
|
def _listen(self, ip , port ) :
|
218
|
-
|
223
|
+
if "unix:" in ip:
|
224
|
+
tcp = False
|
225
|
+
ipv = socket.AF_UNIX
|
226
|
+
ip = ip.split("unix:")[1]
|
227
|
+
elif ":" in ip:
|
228
|
+
tcp = True
|
229
|
+
ipv = socket.AF_INET6
|
230
|
+
else:
|
231
|
+
tcp = True
|
232
|
+
ipv = socket.AF_INET
|
233
|
+
|
219
234
|
srv = socket.socket(ipv, socket.SOCK_STREAM)
|
220
235
|
|
221
236
|
if not ANYWIN or self.args.reuseaddr:
|
222
237
|
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
223
238
|
|
224
|
-
|
239
|
+
if tcp:
|
240
|
+
srv.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
241
|
+
|
225
242
|
srv.settimeout(None) # < does not inherit, ^ opts above do
|
226
243
|
|
227
244
|
try:
|
@@ -233,8 +250,19 @@ class TcpSrv(object):
|
|
233
250
|
srv.setsockopt(socket.SOL_IP, socket.IP_FREEBIND, 1)
|
234
251
|
|
235
252
|
try:
|
236
|
-
|
237
|
-
|
253
|
+
if tcp:
|
254
|
+
srv.bind((ip, port))
|
255
|
+
else:
|
256
|
+
if ANYWIN or self.args.rm_sck:
|
257
|
+
if os.path.exists(ip):
|
258
|
+
os.unlink(ip)
|
259
|
+
srv.bind(ip)
|
260
|
+
else:
|
261
|
+
tf = "%s.%d" % (ip, os.getpid())
|
262
|
+
srv.bind(tf)
|
263
|
+
atomic_move(self.nlog, tf, ip, VF_CAREFUL)
|
264
|
+
|
265
|
+
sport = srv.getsockname()[1] if tcp else port
|
238
266
|
if port != sport:
|
239
267
|
# linux 6.0.16 lets you bind a port which is in use
|
240
268
|
# except it just gives you a random port instead
|
@@ -246,12 +274,23 @@ class TcpSrv(object):
|
|
246
274
|
except:
|
247
275
|
pass
|
248
276
|
|
277
|
+
e = ""
|
249
278
|
if ex.errno in E_ADDR_IN_USE:
|
250
279
|
e = "\033[1;31mport {} is busy on interface {}\033[0m".format(port, ip)
|
280
|
+
if not tcp:
|
281
|
+
e = "\033[1;31munix-socket {} is busy\033[0m".format(ip)
|
251
282
|
elif ex.errno in E_ADDR_NOT_AVAIL:
|
252
283
|
e = "\033[1;31minterface {} does not exist\033[0m".format(ip)
|
253
|
-
|
284
|
+
|
285
|
+
if not e:
|
286
|
+
if not tcp:
|
287
|
+
t = "\n\n\n NOTE: this crash may be due to a unix-socket bug; try --rm-sck\n"
|
288
|
+
self.log("tcpsrv", t, 2)
|
254
289
|
raise
|
290
|
+
|
291
|
+
if not tcp and not self.args.rm_sck:
|
292
|
+
e += "; maybe this is a bug? try --rm-sck"
|
293
|
+
|
255
294
|
raise Exception(e)
|
256
295
|
|
257
296
|
def run(self) :
|
@@ -259,7 +298,14 @@ class TcpSrv(object):
|
|
259
298
|
bound = []
|
260
299
|
srvs = []
|
261
300
|
for srv in self.srv:
|
262
|
-
|
301
|
+
if srv.family == socket.AF_UNIX:
|
302
|
+
tcp = False
|
303
|
+
ip = re.sub(r"\.[0-9]+$", "", srv.getsockname())
|
304
|
+
port = 0
|
305
|
+
else:
|
306
|
+
tcp = True
|
307
|
+
ip, port = srv.getsockname()[:2]
|
308
|
+
|
263
309
|
if ip == IP6ALL:
|
264
310
|
ip = "::" # jython
|
265
311
|
|
@@ -291,8 +337,12 @@ class TcpSrv(object):
|
|
291
337
|
bound.append((ip, port))
|
292
338
|
srvs.append(srv)
|
293
339
|
fno = srv.fileno()
|
294
|
-
|
295
|
-
|
340
|
+
if tcp:
|
341
|
+
hip = "[{}]".format(ip) if ":" in ip else ip
|
342
|
+
msg = "listening @ {}:{} f{} p{}".format(hip, port, fno, os.getpid())
|
343
|
+
else:
|
344
|
+
msg = "listening @ {} f{} p{}".format(ip, fno, os.getpid())
|
345
|
+
|
296
346
|
self.log("tcpsrv", msg)
|
297
347
|
if self.args.q:
|
298
348
|
print(msg)
|
@@ -345,6 +395,8 @@ class TcpSrv(object):
|
|
345
395
|
def detect_interfaces(self, listen_ips ) :
|
346
396
|
from .stolen.ifaddr import get_adapters
|
347
397
|
|
398
|
+
listen_ips = [x for x in listen_ips if "unix:" not in x]
|
399
|
+
|
348
400
|
nics = get_adapters(True)
|
349
401
|
eps = {}
|
350
402
|
for nic in nics:
|
copyparty/tftpd.py
CHANGED
@@ -36,11 +36,14 @@ from partftpy.TftpShared import TftpException
|
|
36
36
|
from .__init__ import EXE, PY2, TYPE_CHECKING
|
37
37
|
from .authsrv import VFS
|
38
38
|
from .bos import bos
|
39
|
-
from .util import BytesIO, Daemon, ODict, exclude_dotfiles, min_ex, runhook, undot
|
39
|
+
from .util import UTC, BytesIO, Daemon, ODict, exclude_dotfiles, min_ex, runhook, undot
|
40
40
|
|
41
41
|
if TYPE_CHECKING:
|
42
42
|
from .svchub import SvcHub
|
43
43
|
|
44
|
+
if PY2:
|
45
|
+
range = xrange # type: ignore
|
46
|
+
|
44
47
|
|
45
48
|
lg = logging.getLogger("tftp")
|
46
49
|
debug, info, warning, error = (lg.debug, lg.info, lg.warning, lg.error)
|
@@ -160,9 +163,16 @@ class Tftpd(object):
|
|
160
163
|
if "::" in ips:
|
161
164
|
ips.append("0.0.0.0")
|
162
165
|
|
166
|
+
ips = [x for x in ips if "unix:" not in x]
|
167
|
+
|
163
168
|
if self.args.tftp4:
|
164
169
|
ips = [x for x in ips if ":" not in x]
|
165
170
|
|
171
|
+
if not ips:
|
172
|
+
t = "cannot start tftp-server; no compatible IPs in -i"
|
173
|
+
self.nlog(t, 1)
|
174
|
+
return
|
175
|
+
|
166
176
|
ips = list(ODict.fromkeys(ips)) # dedup
|
167
177
|
|
168
178
|
for ip in ips:
|
@@ -238,6 +248,8 @@ class Tftpd(object):
|
|
238
248
|
|
239
249
|
debug('%s("%s", %s) %s\033[K\033[0m', caller, vpath, str(a), perms)
|
240
250
|
vfs, rem = self.asrv.vfs.get(vpath, "*", *perms)
|
251
|
+
if not vfs.realpath:
|
252
|
+
raise Exception("unmapped vfs")
|
241
253
|
return vfs, vfs.canonical(rem)
|
242
254
|
|
243
255
|
def _ls(self, vpath , raddress , rport , force=False) :
|
@@ -259,7 +271,7 @@ class Tftpd(object):
|
|
259
271
|
dirs1 = [(v.st_mtime, v.st_size, k + "/") for k, v in vfs_ls if k in dnames]
|
260
272
|
fils1 = [(v.st_mtime, v.st_size, k) for k, v in vfs_ls if k not in dnames]
|
261
273
|
real1 = dirs1 + fils1
|
262
|
-
realt = [(datetime.fromtimestamp(mt), sz, fn) for mt, sz, fn in real1]
|
274
|
+
realt = [(datetime.fromtimestamp(mt, UTC), sz, fn) for mt, sz, fn in real1]
|
263
275
|
reals = [
|
264
276
|
(
|
265
277
|
"%04d-%02d-%02d %02d:%02d:%02d"
|
@@ -325,7 +337,21 @@ class Tftpd(object):
|
|
325
337
|
|
326
338
|
xbu = vfs.flags.get("xbu")
|
327
339
|
if xbu and not runhook(
|
328
|
-
self.nlog,
|
340
|
+
self.nlog,
|
341
|
+
None,
|
342
|
+
self.hub.up2k,
|
343
|
+
"xbu.tftpd",
|
344
|
+
xbu,
|
345
|
+
ap,
|
346
|
+
vpath,
|
347
|
+
"",
|
348
|
+
"",
|
349
|
+
"",
|
350
|
+
0,
|
351
|
+
0,
|
352
|
+
"8.3.8.7",
|
353
|
+
time.time(),
|
354
|
+
"",
|
329
355
|
):
|
330
356
|
yeet("blocked by xbu server config: " + vpath)
|
331
357
|
|
@@ -333,7 +359,7 @@ class Tftpd(object):
|
|
333
359
|
return self._ls(vpath, "", 0, True)
|
334
360
|
|
335
361
|
if not a:
|
336
|
-
a =
|
362
|
+
a = (self.args.iobuf,)
|
337
363
|
|
338
364
|
return open(ap, mode, *a, **ka)
|
339
365
|
|
copyparty/th_srv.py
CHANGED
@@ -12,7 +12,7 @@ import time
|
|
12
12
|
|
13
13
|
from queue import Queue
|
14
14
|
|
15
|
-
from .__init__ import ANYWIN, TYPE_CHECKING
|
15
|
+
from .__init__ import ANYWIN, PY2, TYPE_CHECKING
|
16
16
|
from .authsrv import VFS
|
17
17
|
from .bos import bos
|
18
18
|
from .mtag import HAVE_FFMPEG, HAVE_FFPROBE, au_unpk, ffprobe
|
@@ -35,6 +35,9 @@ from .util import (
|
|
35
35
|
if TYPE_CHECKING:
|
36
36
|
from .svchub import SvcHub
|
37
37
|
|
38
|
+
if PY2:
|
39
|
+
range = xrange # type: ignore
|
40
|
+
|
38
41
|
HAVE_PIL = False
|
39
42
|
HAVE_PILF = False
|
40
43
|
HAVE_HEIF = False
|
@@ -42,22 +45,34 @@ HAVE_AVIF = False
|
|
42
45
|
HAVE_WEBP = False
|
43
46
|
|
44
47
|
try:
|
48
|
+
if os.environ.get("PRTY_NO_PIL"):
|
49
|
+
raise Exception()
|
50
|
+
|
45
51
|
from PIL import ExifTags, Image, ImageFont, ImageOps
|
46
52
|
|
47
53
|
HAVE_PIL = True
|
48
54
|
try:
|
55
|
+
if os.environ.get("PRTY_NO_PILF"):
|
56
|
+
raise Exception()
|
57
|
+
|
49
58
|
ImageFont.load_default(size=16)
|
50
59
|
HAVE_PILF = True
|
51
60
|
except:
|
52
61
|
pass
|
53
62
|
|
54
63
|
try:
|
64
|
+
if os.environ.get("PRTY_NO_PIL_WEBP"):
|
65
|
+
raise Exception()
|
66
|
+
|
55
67
|
Image.new("RGB", (2, 2)).save(BytesIO(), format="webp")
|
56
68
|
HAVE_WEBP = True
|
57
69
|
except:
|
58
70
|
pass
|
59
71
|
|
60
72
|
try:
|
73
|
+
if os.environ.get("PRTY_NO_PIL_HEIF"):
|
74
|
+
raise Exception()
|
75
|
+
|
61
76
|
from pyheif_pillow_opener import register_heif_opener
|
62
77
|
|
63
78
|
register_heif_opener()
|
@@ -66,6 +81,9 @@ try:
|
|
66
81
|
pass
|
67
82
|
|
68
83
|
try:
|
84
|
+
if os.environ.get("PRTY_NO_PIL_AVIF"):
|
85
|
+
raise Exception()
|
86
|
+
|
69
87
|
import pillow_avif # noqa: F401 # pylint: disable=unused-import
|
70
88
|
|
71
89
|
HAVE_AVIF = True
|
@@ -77,6 +95,9 @@ except:
|
|
77
95
|
pass
|
78
96
|
|
79
97
|
try:
|
98
|
+
if os.environ.get("PRTY_NO_VIPS"):
|
99
|
+
raise Exception()
|
100
|
+
|
80
101
|
HAVE_VIPS = True
|
81
102
|
import pyvips
|
82
103
|
|
copyparty/u2idx.py
CHANGED
@@ -8,7 +8,7 @@ import threading
|
|
8
8
|
import time
|
9
9
|
from operator import itemgetter
|
10
10
|
|
11
|
-
from .__init__ import ANYWIN, TYPE_CHECKING, unicode
|
11
|
+
from .__init__ import ANYWIN, PY2, TYPE_CHECKING, unicode
|
12
12
|
from .authsrv import LEELOO_DALLAS, VFS
|
13
13
|
from .bos import bos
|
14
14
|
from .up2k import up2k_wark_from_hashlist
|
@@ -35,6 +35,9 @@ except:
|
|
35
35
|
if TYPE_CHECKING:
|
36
36
|
from .httpsrv import HttpSrv
|
37
37
|
|
38
|
+
if PY2:
|
39
|
+
range = xrange # type: ignore
|
40
|
+
|
38
41
|
|
39
42
|
class U2idx(object):
|
40
43
|
def __init__(self, hsrv ) :
|