copyparty 1.13.3__py3-none-any.whl → 1.13.4__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 +70 -38
- copyparty/__version__.py +2 -2
- copyparty/authsrv.py +68 -9
- copyparty/cert.py +10 -6
- copyparty/cfg.py +3 -0
- copyparty/ftpd.py +44 -7
- copyparty/httpcli.py +179 -61
- copyparty/httpsrv.py +3 -3
- copyparty/mdns.py +1 -1
- copyparty/mtag.py +3 -0
- copyparty/smbd.py +1 -1
- copyparty/ssdp.py +1 -1
- copyparty/svchub.py +4 -2
- copyparty/tcpsrv.py +4 -1
- copyparty/tftpd.py +5 -10
- copyparty/up2k.py +82 -14
- copyparty/util.py +44 -14
- copyparty/web/browser.js.gz +0 -0
- copyparty/web/deps/marked.js.gz +0 -0
- copyparty/web/ui.css.gz +0 -0
- copyparty/web/util.js.gz +0 -0
- {copyparty-1.13.3.dist-info → copyparty-1.13.4.dist-info}/METADATA +39 -7
- {copyparty-1.13.3.dist-info → copyparty-1.13.4.dist-info}/RECORD +27 -27
- {copyparty-1.13.3.dist-info → copyparty-1.13.4.dist-info}/WHEEL +1 -1
- {copyparty-1.13.3.dist-info → copyparty-1.13.4.dist-info}/LICENSE +0 -0
- {copyparty-1.13.3.dist-info → copyparty-1.13.4.dist-info}/entry_points.txt +0 -0
- {copyparty-1.13.3.dist-info → copyparty-1.13.4.dist-info}/top_level.txt +0 -0
copyparty/httpcli.py
CHANGED
@@ -642,8 +642,12 @@ class HttpCli(object):
|
|
642
642
|
if not self._check_nonfatal(pex, post):
|
643
643
|
self.keepalive = False
|
644
644
|
|
645
|
-
|
646
|
-
|
645
|
+
if pex is ex:
|
646
|
+
em = msg = str(ex)
|
647
|
+
else:
|
648
|
+
em = repr(ex)
|
649
|
+
msg = min_ex()
|
650
|
+
|
647
651
|
if pex.code != 404 or self.do_log:
|
648
652
|
self.log(
|
649
653
|
"%s\033[0m, %s" % (msg, self.vpath),
|
@@ -691,6 +695,7 @@ class HttpCli(object):
|
|
691
695
|
self.vpath,
|
692
696
|
self.host,
|
693
697
|
self.uname,
|
698
|
+
"",
|
694
699
|
time.time(),
|
695
700
|
0,
|
696
701
|
self.ip,
|
@@ -1627,6 +1632,7 @@ class HttpCli(object):
|
|
1627
1632
|
self.vpath,
|
1628
1633
|
self.host,
|
1629
1634
|
self.uname,
|
1635
|
+
self.asrv.vfs.get_perms(self.vpath, self.uname),
|
1630
1636
|
time.time(),
|
1631
1637
|
len(buf),
|
1632
1638
|
self.ip,
|
@@ -1670,6 +1676,8 @@ class HttpCli(object):
|
|
1670
1676
|
remains = int(self.headers.get("content-length", -1))
|
1671
1677
|
if remains == -1:
|
1672
1678
|
self.keepalive = False
|
1679
|
+
self.in_hdr_recv = True
|
1680
|
+
self.s.settimeout(max(self.args.s_tbody // 20, 1))
|
1673
1681
|
return read_socket_unbounded(self.sr, bufsz), remains
|
1674
1682
|
else:
|
1675
1683
|
return read_socket(self.sr, bufsz, remains), remains
|
@@ -1774,6 +1782,7 @@ class HttpCli(object):
|
|
1774
1782
|
self.vpath,
|
1775
1783
|
self.host,
|
1776
1784
|
self.uname,
|
1785
|
+
self.asrv.vfs.get_perms(self.vpath, self.uname),
|
1777
1786
|
at,
|
1778
1787
|
remains,
|
1779
1788
|
self.ip,
|
@@ -1864,6 +1873,7 @@ class HttpCli(object):
|
|
1864
1873
|
self.vpath,
|
1865
1874
|
self.host,
|
1866
1875
|
self.uname,
|
1876
|
+
self.asrv.vfs.get_perms(self.vpath, self.uname),
|
1867
1877
|
mt,
|
1868
1878
|
post_sz,
|
1869
1879
|
self.ip,
|
@@ -1900,6 +1910,9 @@ class HttpCli(object):
|
|
1900
1910
|
0 if ANYWIN else bos.stat(path).st_ino,
|
1901
1911
|
)[: vfs.flags["fk"]]
|
1902
1912
|
|
1913
|
+
if "media" in self.uparam or "medialinks" in vfs.flags:
|
1914
|
+
vsuf += "&v" if vsuf else "?v"
|
1915
|
+
|
1903
1916
|
vpath = "/".join([x for x in [vfs.vpath, rem, fn] if x])
|
1904
1917
|
vpath = quotep(vpath)
|
1905
1918
|
|
@@ -2021,7 +2034,7 @@ class HttpCli(object):
|
|
2021
2034
|
|
2022
2035
|
v = self.uparam[k]
|
2023
2036
|
|
2024
|
-
if self._use_dirkey():
|
2037
|
+
if self._use_dirkey(self.vn, ""):
|
2025
2038
|
vn = self.vn
|
2026
2039
|
rem = self.rem
|
2027
2040
|
else:
|
@@ -2543,6 +2556,7 @@ class HttpCli(object):
|
|
2543
2556
|
self.vpath,
|
2544
2557
|
self.host,
|
2545
2558
|
self.uname,
|
2559
|
+
self.asrv.vfs.get_perms(self.vpath, self.uname),
|
2546
2560
|
at,
|
2547
2561
|
0,
|
2548
2562
|
self.ip,
|
@@ -2606,6 +2620,7 @@ class HttpCli(object):
|
|
2606
2620
|
self.vpath,
|
2607
2621
|
self.host,
|
2608
2622
|
self.uname,
|
2623
|
+
self.asrv.vfs.get_perms(self.vpath, self.uname),
|
2609
2624
|
at,
|
2610
2625
|
sz,
|
2611
2626
|
self.ip,
|
@@ -2681,6 +2696,9 @@ class HttpCli(object):
|
|
2681
2696
|
0 if ANYWIN or not ap else bos.stat(ap).st_ino,
|
2682
2697
|
)[: vfs.flags["fk"]]
|
2683
2698
|
|
2699
|
+
if "media" in self.uparam or "medialinks" in vfs.flags:
|
2700
|
+
vsuf += "&v" if vsuf else "?v"
|
2701
|
+
|
2684
2702
|
vpath = "{}/{}".format(upload_vpath, lfn).strip("/")
|
2685
2703
|
rel_url = quotep(self.args.RS + vpath) + vsuf
|
2686
2704
|
msg += 'sha512: {} // {} // {} bytes // <a href="/{}">{}</a> {}\n'.format(
|
@@ -2847,6 +2865,7 @@ class HttpCli(object):
|
|
2847
2865
|
self.vpath,
|
2848
2866
|
self.host,
|
2849
2867
|
self.uname,
|
2868
|
+
self.asrv.vfs.get_perms(self.vpath, self.uname),
|
2850
2869
|
time.time(),
|
2851
2870
|
0,
|
2852
2871
|
self.ip,
|
@@ -2885,6 +2904,7 @@ class HttpCli(object):
|
|
2885
2904
|
self.vpath,
|
2886
2905
|
self.host,
|
2887
2906
|
self.uname,
|
2907
|
+
self.asrv.vfs.get_perms(self.vpath, self.uname),
|
2888
2908
|
new_lastmod,
|
2889
2909
|
sz,
|
2890
2910
|
self.ip,
|
@@ -2939,22 +2959,24 @@ class HttpCli(object):
|
|
2939
2959
|
|
2940
2960
|
return file_lastmod, True
|
2941
2961
|
|
2942
|
-
def _use_dirkey(self, ap
|
2962
|
+
def _use_dirkey(self, vn , ap ) :
|
2943
2963
|
if self.can_read or not self.can_get:
|
2944
2964
|
return False
|
2945
2965
|
|
2946
|
-
if
|
2966
|
+
if vn.flags.get("dky"):
|
2947
2967
|
return True
|
2948
2968
|
|
2949
2969
|
req = self.uparam.get("k") or ""
|
2950
2970
|
if not req:
|
2951
2971
|
return False
|
2952
2972
|
|
2953
|
-
dk_len =
|
2973
|
+
dk_len = vn.flags.get("dk")
|
2954
2974
|
if not dk_len:
|
2955
2975
|
return False
|
2956
2976
|
|
2957
|
-
|
2977
|
+
if not ap:
|
2978
|
+
ap = vn.canonical(self.rem)
|
2979
|
+
|
2958
2980
|
zs = self.gen_fk(2, self.args.dk_salt, ap, 0, 0)[:dk_len]
|
2959
2981
|
if req == zs:
|
2960
2982
|
return True
|
@@ -2963,6 +2985,71 @@ class HttpCli(object):
|
|
2963
2985
|
self.log(t % (zs, req, self.req, ap), 6)
|
2964
2986
|
return False
|
2965
2987
|
|
2988
|
+
def _use_filekey(self, vn , ap , st ) :
|
2989
|
+
if self.can_read or not self.can_get:
|
2990
|
+
return False
|
2991
|
+
|
2992
|
+
req = self.uparam.get("k") or ""
|
2993
|
+
if not req:
|
2994
|
+
return False
|
2995
|
+
|
2996
|
+
fk_len = vn.flags.get("fk")
|
2997
|
+
if not fk_len:
|
2998
|
+
return False
|
2999
|
+
|
3000
|
+
if not ap:
|
3001
|
+
ap = self.vn.canonical(self.rem)
|
3002
|
+
|
3003
|
+
alg = 2 if "fka" in vn.flags else 1
|
3004
|
+
|
3005
|
+
zs = self.gen_fk(
|
3006
|
+
alg, self.args.fk_salt, ap, st.st_size, 0 if ANYWIN else st.st_ino
|
3007
|
+
)[:fk_len]
|
3008
|
+
|
3009
|
+
if req == zs:
|
3010
|
+
return True
|
3011
|
+
|
3012
|
+
t = "wrong filekey, want %s, got %s\n vp: %s\n ap: %s"
|
3013
|
+
self.log(t % (zs, req, self.req, ap), 6)
|
3014
|
+
return False
|
3015
|
+
|
3016
|
+
def _add_logues(
|
3017
|
+
self, vn , abspath , lnames
|
3018
|
+
) :
|
3019
|
+
logues = ["", ""]
|
3020
|
+
if not self.args.no_logues:
|
3021
|
+
for n, fn in enumerate([".prologue.html", ".epilogue.html"]):
|
3022
|
+
if lnames is not None and fn not in lnames:
|
3023
|
+
continue
|
3024
|
+
fn = os.path.join(abspath, fn)
|
3025
|
+
if bos.path.exists(fn):
|
3026
|
+
with open(fsenc(fn), "rb") as f:
|
3027
|
+
logues[n] = f.read().decode("utf-8")
|
3028
|
+
if "exp" in vn.flags:
|
3029
|
+
logues[n] = self._expand(
|
3030
|
+
logues[n], vn.flags.get("exp_lg") or []
|
3031
|
+
)
|
3032
|
+
|
3033
|
+
readme = ""
|
3034
|
+
if not self.args.no_readme and not logues[1]:
|
3035
|
+
if lnames is None:
|
3036
|
+
fns = ["README.md", "readme.md"]
|
3037
|
+
elif "readme.md" in lnames:
|
3038
|
+
fns = [lnames["readme.md"]]
|
3039
|
+
else:
|
3040
|
+
fns = []
|
3041
|
+
|
3042
|
+
for fn in fns:
|
3043
|
+
fn = os.path.join(abspath, fn)
|
3044
|
+
if bos.path.isfile(fn):
|
3045
|
+
with open(fsenc(fn), "rb") as f:
|
3046
|
+
readme = f.read().decode("utf-8")
|
3047
|
+
break
|
3048
|
+
if readme and "exp" in vn.flags:
|
3049
|
+
readme = self._expand(readme, vn.flags.get("exp_md") or [])
|
3050
|
+
|
3051
|
+
return logues, readme
|
3052
|
+
|
2966
3053
|
def _expand(self, txt , phs ) :
|
2967
3054
|
for ph in phs:
|
2968
3055
|
if ph.startswith("hdr."):
|
@@ -2992,6 +3079,7 @@ class HttpCli(object):
|
|
2992
3079
|
logtail = ""
|
2993
3080
|
|
2994
3081
|
if ptop is not None:
|
3082
|
+
ap_data = "<%s>" % (req_path,)
|
2995
3083
|
try:
|
2996
3084
|
dp, fn = os.path.split(req_path)
|
2997
3085
|
tnam = fn + ".PARTIAL"
|
@@ -3338,7 +3426,16 @@ class HttpCli(object):
|
|
3338
3426
|
|
3339
3427
|
if lower < upper and not broken:
|
3340
3428
|
with open(req_path, "rb") as f:
|
3341
|
-
remains = sendfile_py(
|
3429
|
+
remains = sendfile_py(
|
3430
|
+
self.log,
|
3431
|
+
lower,
|
3432
|
+
upper,
|
3433
|
+
f,
|
3434
|
+
self.s,
|
3435
|
+
wr_sz,
|
3436
|
+
wr_slp,
|
3437
|
+
not self.args.no_poll,
|
3438
|
+
)
|
3342
3439
|
|
3343
3440
|
spd = self._spd((upper - lower) - remains)
|
3344
3441
|
if self.do_log:
|
@@ -3850,7 +3947,7 @@ class HttpCli(object):
|
|
3850
3947
|
dk_sz = False
|
3851
3948
|
if dk:
|
3852
3949
|
vn, rem = vfs.get(top, self.uname, False, False)
|
3853
|
-
if vn.flags.get("dks") and self._use_dirkey(vn.canonical(rem)):
|
3950
|
+
if vn.flags.get("dks") and self._use_dirkey(vn, vn.canonical(rem)):
|
3854
3951
|
dk_sz = vn.flags.get("dk")
|
3855
3952
|
|
3856
3953
|
dots = False
|
@@ -4159,6 +4256,9 @@ class HttpCli(object):
|
|
4159
4256
|
add_og = True
|
4160
4257
|
og_fn = ""
|
4161
4258
|
|
4259
|
+
if "v" in self.uparam:
|
4260
|
+
add_og = og_ua = True
|
4261
|
+
|
4162
4262
|
if "b" in self.uparam:
|
4163
4263
|
self.out_headers["X-Robots-Tag"] = "noindex, nofollow"
|
4164
4264
|
|
@@ -4171,9 +4271,20 @@ class HttpCli(object):
|
|
4171
4271
|
if idx and hasattr(idx, "p_end"):
|
4172
4272
|
icur = idx.get_cur(dbv)
|
4173
4273
|
|
4274
|
+
if "k" in self.uparam or "dky" in vn.flags:
|
4275
|
+
if is_dir:
|
4276
|
+
use_dirkey = self._use_dirkey(vn, abspath)
|
4277
|
+
use_filekey = False
|
4278
|
+
else:
|
4279
|
+
use_filekey = self._use_filekey(vn, abspath, st)
|
4280
|
+
use_dirkey = False
|
4281
|
+
else:
|
4282
|
+
use_dirkey = use_filekey = False
|
4283
|
+
|
4174
4284
|
th_fmt = self.uparam.get("th")
|
4175
4285
|
if self.can_read or (
|
4176
|
-
self.can_get
|
4286
|
+
self.can_get
|
4287
|
+
and (use_filekey or use_dirkey or (not is_dir and "fk" not in vn.flags))
|
4177
4288
|
):
|
4178
4289
|
if th_fmt is not None:
|
4179
4290
|
nothumb = "dthumb" in dbv.flags
|
@@ -4190,18 +4301,21 @@ class HttpCli(object):
|
|
4190
4301
|
if cfn:
|
4191
4302
|
fn = cfn[0]
|
4192
4303
|
fp = os.path.join(abspath, fn)
|
4193
|
-
|
4194
|
-
|
4195
|
-
|
4304
|
+
st = bos.stat(fp)
|
4305
|
+
vrem = "{}/{}".format(vrem, fn).strip("/")
|
4306
|
+
is_dir = False
|
4196
4307
|
except:
|
4197
4308
|
pass
|
4198
4309
|
else:
|
4199
4310
|
for fn in self.args.th_covers:
|
4200
4311
|
fp = os.path.join(abspath, fn)
|
4201
|
-
|
4312
|
+
try:
|
4313
|
+
st = bos.stat(fp)
|
4202
4314
|
vrem = "{}/{}".format(vrem, fn).strip("/")
|
4203
4315
|
is_dir = False
|
4204
4316
|
break
|
4317
|
+
except:
|
4318
|
+
pass
|
4205
4319
|
|
4206
4320
|
if is_dir:
|
4207
4321
|
return self.tx_svg("folder")
|
@@ -4253,21 +4367,10 @@ class HttpCli(object):
|
|
4253
4367
|
|
4254
4368
|
if not is_dir and (self.can_read or self.can_get):
|
4255
4369
|
if not self.can_read and not fk_pass and "fk" in vn.flags:
|
4256
|
-
|
4257
|
-
correct = self.gen_fk(
|
4258
|
-
alg,
|
4259
|
-
self.args.fk_salt,
|
4260
|
-
abspath,
|
4261
|
-
st.st_size,
|
4262
|
-
0 if ANYWIN else st.st_ino,
|
4263
|
-
)[: vn.flags["fk"]]
|
4264
|
-
got = self.uparam.get("k")
|
4265
|
-
if got != correct:
|
4266
|
-
t = "wrong filekey, want %s, got %s\n vp: %s\n ap: %s"
|
4267
|
-
self.log(t % (correct, got, self.req, abspath), 6)
|
4370
|
+
if not use_filekey:
|
4268
4371
|
return self.tx_404()
|
4269
4372
|
|
4270
|
-
if add_og:
|
4373
|
+
if add_og and not abspath.lower().endswith(".md"):
|
4271
4374
|
if og_ua or self.host not in self.headers.get("referer", ""):
|
4272
4375
|
self.vpath, og_fn = vsplit(self.vpath)
|
4273
4376
|
vpath = self.vpath
|
@@ -4282,7 +4385,7 @@ class HttpCli(object):
|
|
4282
4385
|
(abspath.endswith(".md") or self.can_delete)
|
4283
4386
|
and "nohtml" not in vn.flags
|
4284
4387
|
and (
|
4285
|
-
"v" in self.uparam
|
4388
|
+
("v" in self.uparam and abspath.endswith(".md"))
|
4286
4389
|
or "edit" in self.uparam
|
4287
4390
|
or "edit2" in self.uparam
|
4288
4391
|
)
|
@@ -4295,7 +4398,7 @@ class HttpCli(object):
|
|
4295
4398
|
)
|
4296
4399
|
|
4297
4400
|
elif is_dir and not self.can_read:
|
4298
|
-
if
|
4401
|
+
if use_dirkey:
|
4299
4402
|
is_dk = True
|
4300
4403
|
elif not self.can_write:
|
4301
4404
|
return self.tx_404(True)
|
@@ -4352,29 +4455,6 @@ class HttpCli(object):
|
|
4352
4455
|
tpl = "browser2"
|
4353
4456
|
is_js = False
|
4354
4457
|
|
4355
|
-
logues = ["", ""]
|
4356
|
-
if not self.args.no_logues:
|
4357
|
-
for n, fn in enumerate([".prologue.html", ".epilogue.html"]):
|
4358
|
-
fn = os.path.join(abspath, fn)
|
4359
|
-
if bos.path.exists(fn):
|
4360
|
-
with open(fsenc(fn), "rb") as f:
|
4361
|
-
logues[n] = f.read().decode("utf-8")
|
4362
|
-
if "exp" in vn.flags:
|
4363
|
-
logues[n] = self._expand(
|
4364
|
-
logues[n], vn.flags.get("exp_lg") or []
|
4365
|
-
)
|
4366
|
-
|
4367
|
-
readme = ""
|
4368
|
-
if not self.args.no_readme and not logues[1]:
|
4369
|
-
for fn in ["README.md", "readme.md"]:
|
4370
|
-
fn = os.path.join(abspath, fn)
|
4371
|
-
if bos.path.isfile(fn):
|
4372
|
-
with open(fsenc(fn), "rb") as f:
|
4373
|
-
readme = f.read().decode("utf-8")
|
4374
|
-
break
|
4375
|
-
if readme and "exp" in vn.flags:
|
4376
|
-
readme = self._expand(readme, vn.flags.get("exp_md") or [])
|
4377
|
-
|
4378
4458
|
vf = vn.flags
|
4379
4459
|
unlist = vf.get("unlist", "")
|
4380
4460
|
ls_ret = {
|
@@ -4393,8 +4473,6 @@ class HttpCli(object):
|
|
4393
4473
|
"frand": bool(vn.flags.get("rand")),
|
4394
4474
|
"unlist": unlist,
|
4395
4475
|
"perms": perms,
|
4396
|
-
"logues": logues,
|
4397
|
-
"readme": readme,
|
4398
4476
|
}
|
4399
4477
|
cgv = {
|
4400
4478
|
"ls0": None,
|
@@ -4412,8 +4490,8 @@ class HttpCli(object):
|
|
4412
4490
|
"have_zip": (not self.args.no_zip),
|
4413
4491
|
"have_unpost": int(self.args.unpost),
|
4414
4492
|
"sb_md": "" if "no_sb_md" in vf else (vf.get("md_sbf") or "y"),
|
4415
|
-
"readme": readme,
|
4416
4493
|
"dgrid": "grid" in vf,
|
4494
|
+
"dgsel": "gsel" in vf,
|
4417
4495
|
"dsort": vf["sort"],
|
4418
4496
|
"dcrop": vf["crop"],
|
4419
4497
|
"dth3x": vf["th3x"],
|
@@ -4434,7 +4512,6 @@ class HttpCli(object):
|
|
4434
4512
|
"have_b_u": (self.can_write and self.uparam.get("b") == "u"),
|
4435
4513
|
"sb_lg": "" if "no_sb_lg" in vf else (vf.get("lg_sbf") or "y"),
|
4436
4514
|
"url_suf": url_suf,
|
4437
|
-
"logues": logues,
|
4438
4515
|
"title": html_escape("%s %s" % (self.args.bname, self.vpath), crlf=True),
|
4439
4516
|
"srv_info": srv_infot,
|
4440
4517
|
"dtheme": self.args.theme,
|
@@ -4454,6 +4531,10 @@ class HttpCli(object):
|
|
4454
4531
|
j2a["no_prism"] = True
|
4455
4532
|
|
4456
4533
|
if not self.can_read and not is_dk:
|
4534
|
+
logues, readme = self._add_logues(vn, abspath, None)
|
4535
|
+
ls_ret["logues"] = j2a["logues"] = logues
|
4536
|
+
ls_ret["readme"] = cgv["readme"] = readme
|
4537
|
+
|
4457
4538
|
if is_ls:
|
4458
4539
|
return self.tx_ls(ls_ret)
|
4459
4540
|
|
@@ -4510,6 +4591,8 @@ class HttpCli(object):
|
|
4510
4591
|
):
|
4511
4592
|
ls_names = exclude_dotfiles(ls_names)
|
4512
4593
|
|
4594
|
+
lnames = {x.lower(): x for x in ls_names}
|
4595
|
+
|
4513
4596
|
add_dk = vf.get("dk")
|
4514
4597
|
add_fk = vf.get("fk")
|
4515
4598
|
fk_alg = 2 if "fka" in vf else 1
|
@@ -4699,9 +4782,45 @@ class HttpCli(object):
|
|
4699
4782
|
else:
|
4700
4783
|
taglist = list(tagset)
|
4701
4784
|
|
4785
|
+
logues, readme = self._add_logues(vn, abspath, lnames)
|
4786
|
+
ls_ret["logues"] = j2a["logues"] = logues
|
4787
|
+
ls_ret["readme"] = cgv["readme"] = readme
|
4788
|
+
|
4702
4789
|
if not files and not dirs and not readme and not logues[0] and not logues[1]:
|
4703
4790
|
logues[1] = "this folder is empty"
|
4704
4791
|
|
4792
|
+
if "descript.ion" in lnames and os.path.isfile(
|
4793
|
+
os.path.join(abspath, lnames["descript.ion"])
|
4794
|
+
):
|
4795
|
+
rem = []
|
4796
|
+
with open(os.path.join(abspath, lnames["descript.ion"]), "rb") as f:
|
4797
|
+
for bln in [x.strip() for x in f]:
|
4798
|
+
try:
|
4799
|
+
if bln.endswith(b"\x04\xc2"):
|
4800
|
+
# multiline comment; replace literal r"\n" with " // "
|
4801
|
+
bln = bln.replace(br"\\n", b" // ")[:-2]
|
4802
|
+
ln = bln.decode("utf-8", "replace")
|
4803
|
+
if ln.startswith('"'):
|
4804
|
+
fn, desc = ln.split('" ', 1)
|
4805
|
+
fn = fn[1:]
|
4806
|
+
else:
|
4807
|
+
fn, desc = ln.split(" ", 1)
|
4808
|
+
fe = next(
|
4809
|
+
(x for x in files if x["name"].lower() == fn.lower()), None
|
4810
|
+
)
|
4811
|
+
if fe:
|
4812
|
+
fe["tags"]["descript.ion"] = desc
|
4813
|
+
else:
|
4814
|
+
t = "<li><code>%s</code> %s</li>"
|
4815
|
+
rem.append(t % (html_escape(fn), html_escape(desc)))
|
4816
|
+
except:
|
4817
|
+
pass
|
4818
|
+
if "descript.ion" not in taglist:
|
4819
|
+
taglist.insert(0, "descript.ion")
|
4820
|
+
if rem and not logues[1]:
|
4821
|
+
t = "<h3>descript.ion</h3><ul>\n"
|
4822
|
+
logues[1] = t + "\n".join(rem) + "</ul>"
|
4823
|
+
|
4705
4824
|
if is_ls:
|
4706
4825
|
ls_ret["dirs"] = dirs
|
4707
4826
|
ls_ret["files"] = files
|
@@ -4771,14 +4890,13 @@ class HttpCli(object):
|
|
4771
4890
|
self.conn.hsrv.j2[tpl] = j2env.get_template(tname)
|
4772
4891
|
thumb = ""
|
4773
4892
|
is_pic = is_vid = is_au = False
|
4774
|
-
|
4775
|
-
|
4776
|
-
|
4777
|
-
thumb = fn
|
4893
|
+
for fn in self.args.th_coversd:
|
4894
|
+
if fn in lnames:
|
4895
|
+
thumb = lnames[fn]
|
4778
4896
|
break
|
4779
4897
|
if og_fn:
|
4780
4898
|
ext = og_fn.split(".")[-1].lower()
|
4781
|
-
if ext in self.thumbcli.thumbable:
|
4899
|
+
if self.thumbcli and ext in self.thumbcli.thumbable:
|
4782
4900
|
is_pic = (
|
4783
4901
|
ext in self.thumbcli.fmt_pil
|
4784
4902
|
or ext in self.thumbcli.fmt_vips
|
copyparty/httpsrv.py
CHANGED
@@ -12,7 +12,7 @@ import time
|
|
12
12
|
|
13
13
|
import queue
|
14
14
|
|
15
|
-
from .__init__ import ANYWIN, CORES, EXE, MACOS, TYPE_CHECKING, EnvParams
|
15
|
+
from .__init__ import ANYWIN, CORES, EXE, MACOS, TYPE_CHECKING, EnvParams, unicode
|
16
16
|
|
17
17
|
try:
|
18
18
|
MNFE = ModuleNotFoundError
|
@@ -331,11 +331,11 @@ class HttpSrv(object):
|
|
331
331
|
|
332
332
|
try:
|
333
333
|
sck, saddr = srv_sck.accept()
|
334
|
-
cip
|
334
|
+
cip = unicode(saddr[0])
|
335
335
|
if cip.startswith("::ffff:"):
|
336
336
|
cip = cip[7:]
|
337
337
|
|
338
|
-
addr = (cip,
|
338
|
+
addr = (cip, saddr[1])
|
339
339
|
except (OSError, socket.error) as ex:
|
340
340
|
if self.stopping:
|
341
341
|
break
|
copyparty/mdns.py
CHANGED
copyparty/mtag.py
CHANGED
@@ -133,6 +133,9 @@ def au_unpk(
|
|
133
133
|
zil = [x for x in zil if x.filename.lower().split(".")[-1] == au]
|
134
134
|
fi = zf.open(zil[0])
|
135
135
|
|
136
|
+
else:
|
137
|
+
raise Exception("unknown compression %s" % (pk,))
|
138
|
+
|
136
139
|
with os.fdopen(fd, "wb") as fo:
|
137
140
|
while True:
|
138
141
|
buf = fi.read(32768)
|
copyparty/smbd.py
CHANGED
@@ -237,7 +237,7 @@ class SMB(object):
|
|
237
237
|
|
238
238
|
xbu = vfs.flags.get("xbu")
|
239
239
|
if xbu and not runhook(
|
240
|
-
self.nlog, xbu, ap, vpath, "", "", 0, 0, "1.7.6.2", 0, ""
|
240
|
+
self.nlog, xbu, ap, vpath, "", "", "", 0, 0, "1.7.6.2", 0, ""
|
241
241
|
):
|
242
242
|
yeet("blocked by xbu server config: " + vpath)
|
243
243
|
|
copyparty/ssdp.py
CHANGED
copyparty/svchub.py
CHANGED
@@ -473,8 +473,10 @@ class SvcHub(object):
|
|
473
473
|
zsl = al.th_covers.split(",")
|
474
474
|
zsl = [x.strip() for x in zsl]
|
475
475
|
zsl = [x for x in zsl if x]
|
476
|
-
al.th_covers =
|
477
|
-
al.th_coversd =
|
476
|
+
al.th_covers = zsl
|
477
|
+
al.th_coversd = zsl + ["." + x for x in zsl]
|
478
|
+
al.th_covers_set = set(al.th_covers)
|
479
|
+
al.th_coversd_set = set(al.th_coversd)
|
478
480
|
|
479
481
|
for k in "c".split(" "):
|
480
482
|
vl = getattr(al, k)
|
copyparty/tcpsrv.py
CHANGED
@@ -15,6 +15,7 @@ from .util import (
|
|
15
15
|
E_ADDR_IN_USE,
|
16
16
|
E_ADDR_NOT_AVAIL,
|
17
17
|
E_UNREACH,
|
18
|
+
HAVE_IPV6,
|
18
19
|
IP6ALL,
|
19
20
|
Netdev,
|
20
21
|
min_ex,
|
@@ -108,8 +109,10 @@ class TcpSrv(object):
|
|
108
109
|
|
109
110
|
eps = {
|
110
111
|
"127.0.0.1": Netdev("127.0.0.1", 0, "", "local only"),
|
111
|
-
"::1": Netdev("::1", 0, "", "local only"),
|
112
112
|
}
|
113
|
+
if HAVE_IPV6:
|
114
|
+
eps["::1"] = Netdev("::1", 0, "", "local only")
|
115
|
+
|
113
116
|
nonlocals = [x for x in self.args.i if x not in [k.split("/")[0] for k in eps]]
|
114
117
|
if nonlocals:
|
115
118
|
try:
|
copyparty/tftpd.py
CHANGED
@@ -33,7 +33,7 @@ from partftpy import (
|
|
33
33
|
)
|
34
34
|
from partftpy.TftpShared import TftpException
|
35
35
|
|
36
|
-
from .__init__ import EXE, TYPE_CHECKING
|
36
|
+
from .__init__ import EXE, PY2, TYPE_CHECKING
|
37
37
|
from .authsrv import VFS
|
38
38
|
from .bos import bos
|
39
39
|
from .util import BytesIO, Daemon, ODict, exclude_dotfiles, min_ex, runhook, undot
|
@@ -92,7 +92,7 @@ class Tftpd(object):
|
|
92
92
|
TftpServer,
|
93
93
|
]
|
94
94
|
cbak = []
|
95
|
-
if not self.args.tftp_no_fast and not EXE:
|
95
|
+
if not self.args.tftp_no_fast and not EXE and not PY2:
|
96
96
|
try:
|
97
97
|
ptn = re.compile(r"(^\s*)log\.debug\(.*\)$")
|
98
98
|
for C in Cs:
|
@@ -102,7 +102,7 @@ class Tftpd(object):
|
|
102
102
|
cfn = C.__spec__.origin
|
103
103
|
exec (compile(src2, filename=cfn, mode="exec"), C.__dict__)
|
104
104
|
except Exception:
|
105
|
-
t = "failed to optimize tftp code; run with --tftp-
|
105
|
+
t = "failed to optimize tftp code; run with --tftp-no-fast if there are issues:\n"
|
106
106
|
self.log("tftp", t + min_ex(), 3)
|
107
107
|
for n, zd in enumerate(cbak):
|
108
108
|
Cs[n].__dict__ = zd
|
@@ -147,11 +147,6 @@ class Tftpd(object):
|
|
147
147
|
|
148
148
|
self._disarm(fos)
|
149
149
|
|
150
|
-
ip = next((x for x in self.args.i if ":" not in x), None)
|
151
|
-
if not ip:
|
152
|
-
self.log("tftp", "IPv6 not supported for tftp; listening on 0.0.0.0", 3)
|
153
|
-
ip = "0.0.0.0"
|
154
|
-
|
155
150
|
self.port = int(self.args.tftp)
|
156
151
|
self.srv = []
|
157
152
|
self.ips = []
|
@@ -165,7 +160,7 @@ class Tftpd(object):
|
|
165
160
|
if "::" in ips:
|
166
161
|
ips.append("0.0.0.0")
|
167
162
|
|
168
|
-
if self.args.
|
163
|
+
if self.args.tftp4:
|
169
164
|
ips = [x for x in ips if ":" not in x]
|
170
165
|
|
171
166
|
ips = list(ODict.fromkeys(ips)) # dedup
|
@@ -330,7 +325,7 @@ class Tftpd(object):
|
|
330
325
|
|
331
326
|
xbu = vfs.flags.get("xbu")
|
332
327
|
if xbu and not runhook(
|
333
|
-
self.nlog, xbu, ap, vpath, "", "", 0, 0, "8.3.8.7", 0, ""
|
328
|
+
self.nlog, xbu, ap, vpath, "", "", "", 0, 0, "8.3.8.7", 0, ""
|
334
329
|
):
|
335
330
|
yeet("blocked by xbu server config: " + vpath)
|
336
331
|
|