copyparty 1.13.3__py3-none-any.whl → 1.13.5__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 +80 -41
- copyparty/__version__.py +2 -2
- copyparty/authsrv.py +68 -9
- copyparty/broker_util.py +3 -3
- copyparty/cert.py +10 -6
- copyparty/cfg.py +3 -0
- copyparty/ftpd.py +44 -7
- copyparty/httpcli.py +224 -96
- 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/th_cli.py +3 -2
- copyparty/th_srv.py +16 -8
- copyparty/up2k.py +124 -40
- copyparty/util.py +45 -15
- copyparty/web/a/u2c.py +117 -38
- copyparty/web/baguettebox.js.gz +0 -0
- copyparty/web/browser.js.gz +0 -0
- copyparty/web/deps/marked.js.gz +0 -0
- copyparty/web/svcs.html +11 -10
- copyparty/web/ui.css.gz +0 -0
- copyparty/web/up2k.js.gz +0 -0
- copyparty/web/util.js.gz +0 -0
- copyparty/web/w.hash.js.gz +0 -0
- {copyparty-1.13.3.dist-info → copyparty-1.13.5.dist-info}/METADATA +45 -10
- {copyparty-1.13.3.dist-info → copyparty-1.13.5.dist-info}/RECORD +35 -35
- {copyparty-1.13.3.dist-info → copyparty-1.13.5.dist-info}/WHEEL +1 -1
- {copyparty-1.13.3.dist-info → copyparty-1.13.5.dist-info}/LICENSE +0 -0
- {copyparty-1.13.3.dist-info → copyparty-1.13.5.dist-info}/entry_points.txt +0 -0
- {copyparty-1.13.3.dist-info → copyparty-1.13.5.dist-info}/top_level.txt +0 -0
copyparty/httpcli.py
CHANGED
@@ -644,6 +644,7 @@ class HttpCli(object):
|
|
644
644
|
|
645
645
|
em = str(ex)
|
646
646
|
msg = em if pex is ex else min_ex()
|
647
|
+
|
647
648
|
if pex.code != 404 or self.do_log:
|
648
649
|
self.log(
|
649
650
|
"%s\033[0m, %s" % (msg, self.vpath),
|
@@ -691,6 +692,7 @@ class HttpCli(object):
|
|
691
692
|
self.vpath,
|
692
693
|
self.host,
|
693
694
|
self.uname,
|
695
|
+
"",
|
694
696
|
time.time(),
|
695
697
|
0,
|
696
698
|
self.ip,
|
@@ -1627,6 +1629,7 @@ class HttpCli(object):
|
|
1627
1629
|
self.vpath,
|
1628
1630
|
self.host,
|
1629
1631
|
self.uname,
|
1632
|
+
self.asrv.vfs.get_perms(self.vpath, self.uname),
|
1630
1633
|
time.time(),
|
1631
1634
|
len(buf),
|
1632
1635
|
self.ip,
|
@@ -1670,6 +1673,8 @@ class HttpCli(object):
|
|
1670
1673
|
remains = int(self.headers.get("content-length", -1))
|
1671
1674
|
if remains == -1:
|
1672
1675
|
self.keepalive = False
|
1676
|
+
self.in_hdr_recv = True
|
1677
|
+
self.s.settimeout(max(self.args.s_tbody // 20, 1))
|
1673
1678
|
return read_socket_unbounded(self.sr, bufsz), remains
|
1674
1679
|
else:
|
1675
1680
|
return read_socket(self.sr, bufsz, remains), remains
|
@@ -1774,6 +1779,7 @@ class HttpCli(object):
|
|
1774
1779
|
self.vpath,
|
1775
1780
|
self.host,
|
1776
1781
|
self.uname,
|
1782
|
+
self.asrv.vfs.get_perms(self.vpath, self.uname),
|
1777
1783
|
at,
|
1778
1784
|
remains,
|
1779
1785
|
self.ip,
|
@@ -1864,6 +1870,7 @@ class HttpCli(object):
|
|
1864
1870
|
self.vpath,
|
1865
1871
|
self.host,
|
1866
1872
|
self.uname,
|
1873
|
+
self.asrv.vfs.get_perms(self.vpath, self.uname),
|
1867
1874
|
mt,
|
1868
1875
|
post_sz,
|
1869
1876
|
self.ip,
|
@@ -1900,6 +1907,9 @@ class HttpCli(object):
|
|
1900
1907
|
0 if ANYWIN else bos.stat(path).st_ino,
|
1901
1908
|
)[: vfs.flags["fk"]]
|
1902
1909
|
|
1910
|
+
if "media" in self.uparam or "medialinks" in vfs.flags:
|
1911
|
+
vsuf += "&v" if vsuf else "?v"
|
1912
|
+
|
1903
1913
|
vpath = "/".join([x for x in [vfs.vpath, rem, fn] if x])
|
1904
1914
|
vpath = quotep(vpath)
|
1905
1915
|
|
@@ -2021,7 +2031,7 @@ class HttpCli(object):
|
|
2021
2031
|
|
2022
2032
|
v = self.uparam[k]
|
2023
2033
|
|
2024
|
-
if self._use_dirkey():
|
2034
|
+
if self._use_dirkey(self.vn, ""):
|
2025
2035
|
vn = self.vn
|
2026
2036
|
rem = self.rem
|
2027
2037
|
else:
|
@@ -2185,33 +2195,39 @@ class HttpCli(object):
|
|
2185
2195
|
|
2186
2196
|
def handle_post_binary(self) :
|
2187
2197
|
try:
|
2188
|
-
remains = int(self.headers["content-length"])
|
2198
|
+
postsize = remains = int(self.headers["content-length"])
|
2189
2199
|
except:
|
2190
2200
|
raise Pebkac(400, "you must supply a content-length for binary POST")
|
2191
2201
|
|
2192
2202
|
try:
|
2193
|
-
|
2203
|
+
chashes = self.headers["x-up2k-hash"].split(",")
|
2194
2204
|
wark = self.headers["x-up2k-wark"]
|
2195
2205
|
except KeyError:
|
2196
2206
|
raise Pebkac(400, "need hash and wark headers for binary POST")
|
2197
2207
|
|
2208
|
+
chashes = [x.strip() for x in chashes]
|
2209
|
+
|
2198
2210
|
vfs, _ = self.asrv.vfs.get(self.vpath, self.uname, False, True)
|
2199
2211
|
ptop = (vfs.dbv or vfs).realpath
|
2200
2212
|
|
2201
|
-
x = self.conn.hsrv.broker.ask("up2k.
|
2213
|
+
x = self.conn.hsrv.broker.ask("up2k.handle_chunks", ptop, wark, chashes)
|
2202
2214
|
response = x.get()
|
2203
|
-
chunksize,
|
2215
|
+
chunksize, cstarts, path, lastmod, sprs = response
|
2216
|
+
maxsize = chunksize * len(chashes)
|
2217
|
+
cstart0 = cstarts[0]
|
2204
2218
|
|
2205
2219
|
try:
|
2206
2220
|
if self.args.nw:
|
2207
2221
|
path = os.devnull
|
2208
2222
|
|
2209
|
-
if remains >
|
2210
|
-
|
2211
|
-
|
2212
|
-
self.log("writing {} #{} @{} len {}".format(path, chash, cstart, remains))
|
2223
|
+
if remains > maxsize:
|
2224
|
+
t = "your client is sending %d bytes which is too much (server expected %d bytes at most)"
|
2225
|
+
raise Pebkac(400, t % (remains, maxsize))
|
2213
2226
|
|
2214
|
-
|
2227
|
+
t = "writing %s %s+%d #%d+%d %s"
|
2228
|
+
chunkno = cstart0[0] // chunksize
|
2229
|
+
zs = " ".join([chashes[0][:15]] + [x[:9] for x in chashes[1:]])
|
2230
|
+
self.log(t % (path, cstart0, remains, chunkno, len(chashes), zs))
|
2215
2231
|
|
2216
2232
|
f = None
|
2217
2233
|
fpool = not self.args.no_fpool and sprs
|
@@ -2225,37 +2241,43 @@ class HttpCli(object):
|
|
2225
2241
|
f = f or open(fsenc(path), "rb+", self.args.iobuf)
|
2226
2242
|
|
2227
2243
|
try:
|
2228
|
-
|
2229
|
-
|
2244
|
+
for chash, cstart in zip(chashes, cstarts):
|
2245
|
+
f.seek(cstart[0])
|
2246
|
+
reader = read_socket(
|
2247
|
+
self.sr, self.args.s_rd_sz, min(remains, chunksize)
|
2248
|
+
)
|
2249
|
+
post_sz, _, sha_b64 = hashcopy(reader, f, self.args.s_wr_slp)
|
2230
2250
|
|
2231
|
-
|
2232
|
-
|
2233
|
-
|
2234
|
-
|
2235
|
-
|
2251
|
+
if sha_b64 != chash:
|
2252
|
+
try:
|
2253
|
+
self.bakflip(f, cstart[0], post_sz, sha_b64, vfs.flags)
|
2254
|
+
except:
|
2255
|
+
self.log("bakflip failed: " + min_ex())
|
2236
2256
|
|
2237
|
-
|
2238
|
-
|
2257
|
+
t = "your chunk got corrupted somehow (received {} bytes); expected vs received hash:\n{}\n{}"
|
2258
|
+
raise Pebkac(400, t.format(post_sz, chash, sha_b64))
|
2239
2259
|
|
2240
|
-
|
2241
|
-
|
2242
|
-
|
2243
|
-
|
2260
|
+
remains -= chunksize
|
2261
|
+
|
2262
|
+
if len(cstart) > 1 and path != os.devnull:
|
2263
|
+
self.log(
|
2264
|
+
"clone {} to {}".format(
|
2265
|
+
cstart[0], " & ".join(unicode(x) for x in cstart[1:])
|
2266
|
+
)
|
2244
2267
|
)
|
2245
|
-
|
2246
|
-
|
2247
|
-
|
2248
|
-
|
2249
|
-
|
2250
|
-
|
2251
|
-
|
2252
|
-
|
2253
|
-
|
2254
|
-
f.write(buf)
|
2268
|
+
ofs = 0
|
2269
|
+
while ofs < chunksize:
|
2270
|
+
bufsz = max(4 * 1024 * 1024, self.args.iobuf)
|
2271
|
+
bufsz = min(chunksize - ofs, bufsz)
|
2272
|
+
f.seek(cstart[0] + ofs)
|
2273
|
+
buf = f.read(bufsz)
|
2274
|
+
for wofs in cstart[1:]:
|
2275
|
+
f.seek(wofs + ofs)
|
2276
|
+
f.write(buf)
|
2255
2277
|
|
2256
|
-
|
2278
|
+
ofs += len(buf)
|
2257
2279
|
|
2258
|
-
|
2280
|
+
self.log("clone {} done".format(cstart[0]))
|
2259
2281
|
|
2260
2282
|
if not fpool:
|
2261
2283
|
f.close()
|
@@ -2267,10 +2289,10 @@ class HttpCli(object):
|
|
2267
2289
|
f.close()
|
2268
2290
|
raise
|
2269
2291
|
finally:
|
2270
|
-
x = self.conn.hsrv.broker.ask("up2k.
|
2292
|
+
x = self.conn.hsrv.broker.ask("up2k.release_chunks", ptop, wark, chashes)
|
2271
2293
|
x.get() # block client until released
|
2272
2294
|
|
2273
|
-
x = self.conn.hsrv.broker.ask("up2k.
|
2295
|
+
x = self.conn.hsrv.broker.ask("up2k.confirm_chunks", ptop, wark, chashes)
|
2274
2296
|
ztis = x.get()
|
2275
2297
|
try:
|
2276
2298
|
num_left, fin_path = ztis
|
@@ -2289,7 +2311,7 @@ class HttpCli(object):
|
|
2289
2311
|
|
2290
2312
|
cinf = self.headers.get("x-up2k-stat", "")
|
2291
2313
|
|
2292
|
-
spd = self._spd(
|
2314
|
+
spd = self._spd(postsize)
|
2293
2315
|
self.log("{:70} thank {}".format(spd, cinf))
|
2294
2316
|
self.reply(b"thank")
|
2295
2317
|
return True
|
@@ -2543,6 +2565,7 @@ class HttpCli(object):
|
|
2543
2565
|
self.vpath,
|
2544
2566
|
self.host,
|
2545
2567
|
self.uname,
|
2568
|
+
self.asrv.vfs.get_perms(self.vpath, self.uname),
|
2546
2569
|
at,
|
2547
2570
|
0,
|
2548
2571
|
self.ip,
|
@@ -2606,6 +2629,7 @@ class HttpCli(object):
|
|
2606
2629
|
self.vpath,
|
2607
2630
|
self.host,
|
2608
2631
|
self.uname,
|
2632
|
+
self.asrv.vfs.get_perms(self.vpath, self.uname),
|
2609
2633
|
at,
|
2610
2634
|
sz,
|
2611
2635
|
self.ip,
|
@@ -2681,6 +2705,9 @@ class HttpCli(object):
|
|
2681
2705
|
0 if ANYWIN or not ap else bos.stat(ap).st_ino,
|
2682
2706
|
)[: vfs.flags["fk"]]
|
2683
2707
|
|
2708
|
+
if "media" in self.uparam or "medialinks" in vfs.flags:
|
2709
|
+
vsuf += "&v" if vsuf else "?v"
|
2710
|
+
|
2684
2711
|
vpath = "{}/{}".format(upload_vpath, lfn).strip("/")
|
2685
2712
|
rel_url = quotep(self.args.RS + vpath) + vsuf
|
2686
2713
|
msg += 'sha512: {} // {} // {} bytes // <a href="/{}">{}</a> {}\n'.format(
|
@@ -2847,6 +2874,7 @@ class HttpCli(object):
|
|
2847
2874
|
self.vpath,
|
2848
2875
|
self.host,
|
2849
2876
|
self.uname,
|
2877
|
+
self.asrv.vfs.get_perms(self.vpath, self.uname),
|
2850
2878
|
time.time(),
|
2851
2879
|
0,
|
2852
2880
|
self.ip,
|
@@ -2885,6 +2913,7 @@ class HttpCli(object):
|
|
2885
2913
|
self.vpath,
|
2886
2914
|
self.host,
|
2887
2915
|
self.uname,
|
2916
|
+
self.asrv.vfs.get_perms(self.vpath, self.uname),
|
2888
2917
|
new_lastmod,
|
2889
2918
|
sz,
|
2890
2919
|
self.ip,
|
@@ -2939,22 +2968,24 @@ class HttpCli(object):
|
|
2939
2968
|
|
2940
2969
|
return file_lastmod, True
|
2941
2970
|
|
2942
|
-
def _use_dirkey(self, ap
|
2971
|
+
def _use_dirkey(self, vn , ap ) :
|
2943
2972
|
if self.can_read or not self.can_get:
|
2944
2973
|
return False
|
2945
2974
|
|
2946
|
-
if
|
2975
|
+
if vn.flags.get("dky"):
|
2947
2976
|
return True
|
2948
2977
|
|
2949
2978
|
req = self.uparam.get("k") or ""
|
2950
2979
|
if not req:
|
2951
2980
|
return False
|
2952
2981
|
|
2953
|
-
dk_len =
|
2982
|
+
dk_len = vn.flags.get("dk")
|
2954
2983
|
if not dk_len:
|
2955
2984
|
return False
|
2956
2985
|
|
2957
|
-
|
2986
|
+
if not ap:
|
2987
|
+
ap = vn.canonical(self.rem)
|
2988
|
+
|
2958
2989
|
zs = self.gen_fk(2, self.args.dk_salt, ap, 0, 0)[:dk_len]
|
2959
2990
|
if req == zs:
|
2960
2991
|
return True
|
@@ -2963,6 +2994,71 @@ class HttpCli(object):
|
|
2963
2994
|
self.log(t % (zs, req, self.req, ap), 6)
|
2964
2995
|
return False
|
2965
2996
|
|
2997
|
+
def _use_filekey(self, vn , ap , st ) :
|
2998
|
+
if self.can_read or not self.can_get:
|
2999
|
+
return False
|
3000
|
+
|
3001
|
+
req = self.uparam.get("k") or ""
|
3002
|
+
if not req:
|
3003
|
+
return False
|
3004
|
+
|
3005
|
+
fk_len = vn.flags.get("fk")
|
3006
|
+
if not fk_len:
|
3007
|
+
return False
|
3008
|
+
|
3009
|
+
if not ap:
|
3010
|
+
ap = self.vn.canonical(self.rem)
|
3011
|
+
|
3012
|
+
alg = 2 if "fka" in vn.flags else 1
|
3013
|
+
|
3014
|
+
zs = self.gen_fk(
|
3015
|
+
alg, self.args.fk_salt, ap, st.st_size, 0 if ANYWIN else st.st_ino
|
3016
|
+
)[:fk_len]
|
3017
|
+
|
3018
|
+
if req == zs:
|
3019
|
+
return True
|
3020
|
+
|
3021
|
+
t = "wrong filekey, want %s, got %s\n vp: %s\n ap: %s"
|
3022
|
+
self.log(t % (zs, req, self.req, ap), 6)
|
3023
|
+
return False
|
3024
|
+
|
3025
|
+
def _add_logues(
|
3026
|
+
self, vn , abspath , lnames
|
3027
|
+
) :
|
3028
|
+
logues = ["", ""]
|
3029
|
+
if not self.args.no_logues:
|
3030
|
+
for n, fn in enumerate([".prologue.html", ".epilogue.html"]):
|
3031
|
+
if lnames is not None and fn not in lnames:
|
3032
|
+
continue
|
3033
|
+
fn = os.path.join(abspath, fn)
|
3034
|
+
if bos.path.exists(fn):
|
3035
|
+
with open(fsenc(fn), "rb") as f:
|
3036
|
+
logues[n] = f.read().decode("utf-8")
|
3037
|
+
if "exp" in vn.flags:
|
3038
|
+
logues[n] = self._expand(
|
3039
|
+
logues[n], vn.flags.get("exp_lg") or []
|
3040
|
+
)
|
3041
|
+
|
3042
|
+
readme = ""
|
3043
|
+
if not self.args.no_readme and not logues[1]:
|
3044
|
+
if lnames is None:
|
3045
|
+
fns = ["README.md", "readme.md"]
|
3046
|
+
elif "readme.md" in lnames:
|
3047
|
+
fns = [lnames["readme.md"]]
|
3048
|
+
else:
|
3049
|
+
fns = []
|
3050
|
+
|
3051
|
+
for fn in fns:
|
3052
|
+
fn = os.path.join(abspath, fn)
|
3053
|
+
if bos.path.isfile(fn):
|
3054
|
+
with open(fsenc(fn), "rb") as f:
|
3055
|
+
readme = f.read().decode("utf-8")
|
3056
|
+
break
|
3057
|
+
if readme and "exp" in vn.flags:
|
3058
|
+
readme = self._expand(readme, vn.flags.get("exp_md") or [])
|
3059
|
+
|
3060
|
+
return logues, readme
|
3061
|
+
|
2966
3062
|
def _expand(self, txt , phs ) :
|
2967
3063
|
for ph in phs:
|
2968
3064
|
if ph.startswith("hdr."):
|
@@ -2992,6 +3088,7 @@ class HttpCli(object):
|
|
2992
3088
|
logtail = ""
|
2993
3089
|
|
2994
3090
|
if ptop is not None:
|
3091
|
+
ap_data = "<%s>" % (req_path,)
|
2995
3092
|
try:
|
2996
3093
|
dp, fn = os.path.split(req_path)
|
2997
3094
|
tnam = fn + ".PARTIAL"
|
@@ -3338,7 +3435,16 @@ class HttpCli(object):
|
|
3338
3435
|
|
3339
3436
|
if lower < upper and not broken:
|
3340
3437
|
with open(req_path, "rb") as f:
|
3341
|
-
remains = sendfile_py(
|
3438
|
+
remains = sendfile_py(
|
3439
|
+
self.log,
|
3440
|
+
lower,
|
3441
|
+
upper,
|
3442
|
+
f,
|
3443
|
+
self.s,
|
3444
|
+
wr_sz,
|
3445
|
+
wr_slp,
|
3446
|
+
not self.args.no_poll,
|
3447
|
+
)
|
3342
3448
|
|
3343
3449
|
spd = self._spd((upper - lower) - remains)
|
3344
3450
|
if self.do_log:
|
@@ -3850,7 +3956,7 @@ class HttpCli(object):
|
|
3850
3956
|
dk_sz = False
|
3851
3957
|
if dk:
|
3852
3958
|
vn, rem = vfs.get(top, self.uname, False, False)
|
3853
|
-
if vn.flags.get("dks") and self._use_dirkey(vn.canonical(rem)):
|
3959
|
+
if vn.flags.get("dks") and self._use_dirkey(vn, vn.canonical(rem)):
|
3854
3960
|
dk_sz = vn.flags.get("dk")
|
3855
3961
|
|
3856
3962
|
dots = False
|
@@ -4159,6 +4265,9 @@ class HttpCli(object):
|
|
4159
4265
|
add_og = True
|
4160
4266
|
og_fn = ""
|
4161
4267
|
|
4268
|
+
if "v" in self.uparam:
|
4269
|
+
add_og = og_ua = True
|
4270
|
+
|
4162
4271
|
if "b" in self.uparam:
|
4163
4272
|
self.out_headers["X-Robots-Tag"] = "noindex, nofollow"
|
4164
4273
|
|
@@ -4171,9 +4280,20 @@ class HttpCli(object):
|
|
4171
4280
|
if idx and hasattr(idx, "p_end"):
|
4172
4281
|
icur = idx.get_cur(dbv)
|
4173
4282
|
|
4283
|
+
if "k" in self.uparam or "dky" in vn.flags:
|
4284
|
+
if is_dir:
|
4285
|
+
use_dirkey = self._use_dirkey(vn, abspath)
|
4286
|
+
use_filekey = False
|
4287
|
+
else:
|
4288
|
+
use_filekey = self._use_filekey(vn, abspath, st)
|
4289
|
+
use_dirkey = False
|
4290
|
+
else:
|
4291
|
+
use_dirkey = use_filekey = False
|
4292
|
+
|
4174
4293
|
th_fmt = self.uparam.get("th")
|
4175
4294
|
if self.can_read or (
|
4176
|
-
self.can_get
|
4295
|
+
self.can_get
|
4296
|
+
and (use_filekey or use_dirkey or (not is_dir and "fk" not in vn.flags))
|
4177
4297
|
):
|
4178
4298
|
if th_fmt is not None:
|
4179
4299
|
nothumb = "dthumb" in dbv.flags
|
@@ -4190,18 +4310,21 @@ class HttpCli(object):
|
|
4190
4310
|
if cfn:
|
4191
4311
|
fn = cfn[0]
|
4192
4312
|
fp = os.path.join(abspath, fn)
|
4193
|
-
|
4194
|
-
|
4195
|
-
|
4313
|
+
st = bos.stat(fp)
|
4314
|
+
vrem = "{}/{}".format(vrem, fn).strip("/")
|
4315
|
+
is_dir = False
|
4196
4316
|
except:
|
4197
4317
|
pass
|
4198
4318
|
else:
|
4199
4319
|
for fn in self.args.th_covers:
|
4200
4320
|
fp = os.path.join(abspath, fn)
|
4201
|
-
|
4321
|
+
try:
|
4322
|
+
st = bos.stat(fp)
|
4202
4323
|
vrem = "{}/{}".format(vrem, fn).strip("/")
|
4203
4324
|
is_dir = False
|
4204
4325
|
break
|
4326
|
+
except:
|
4327
|
+
pass
|
4205
4328
|
|
4206
4329
|
if is_dir:
|
4207
4330
|
return self.tx_svg("folder")
|
@@ -4253,21 +4376,10 @@ class HttpCli(object):
|
|
4253
4376
|
|
4254
4377
|
if not is_dir and (self.can_read or self.can_get):
|
4255
4378
|
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)
|
4379
|
+
if not use_filekey:
|
4268
4380
|
return self.tx_404()
|
4269
4381
|
|
4270
|
-
if add_og:
|
4382
|
+
if add_og and not abspath.lower().endswith(".md"):
|
4271
4383
|
if og_ua or self.host not in self.headers.get("referer", ""):
|
4272
4384
|
self.vpath, og_fn = vsplit(self.vpath)
|
4273
4385
|
vpath = self.vpath
|
@@ -4282,7 +4394,7 @@ class HttpCli(object):
|
|
4282
4394
|
(abspath.endswith(".md") or self.can_delete)
|
4283
4395
|
and "nohtml" not in vn.flags
|
4284
4396
|
and (
|
4285
|
-
"v" in self.uparam
|
4397
|
+
("v" in self.uparam and abspath.endswith(".md"))
|
4286
4398
|
or "edit" in self.uparam
|
4287
4399
|
or "edit2" in self.uparam
|
4288
4400
|
)
|
@@ -4295,7 +4407,7 @@ class HttpCli(object):
|
|
4295
4407
|
)
|
4296
4408
|
|
4297
4409
|
elif is_dir and not self.can_read:
|
4298
|
-
if
|
4410
|
+
if use_dirkey:
|
4299
4411
|
is_dk = True
|
4300
4412
|
elif not self.can_write:
|
4301
4413
|
return self.tx_404(True)
|
@@ -4352,29 +4464,6 @@ class HttpCli(object):
|
|
4352
4464
|
tpl = "browser2"
|
4353
4465
|
is_js = False
|
4354
4466
|
|
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
4467
|
vf = vn.flags
|
4379
4468
|
unlist = vf.get("unlist", "")
|
4380
4469
|
ls_ret = {
|
@@ -4393,8 +4482,6 @@ class HttpCli(object):
|
|
4393
4482
|
"frand": bool(vn.flags.get("rand")),
|
4394
4483
|
"unlist": unlist,
|
4395
4484
|
"perms": perms,
|
4396
|
-
"logues": logues,
|
4397
|
-
"readme": readme,
|
4398
4485
|
}
|
4399
4486
|
cgv = {
|
4400
4487
|
"ls0": None,
|
@@ -4412,8 +4499,8 @@ class HttpCli(object):
|
|
4412
4499
|
"have_zip": (not self.args.no_zip),
|
4413
4500
|
"have_unpost": int(self.args.unpost),
|
4414
4501
|
"sb_md": "" if "no_sb_md" in vf else (vf.get("md_sbf") or "y"),
|
4415
|
-
"readme": readme,
|
4416
4502
|
"dgrid": "grid" in vf,
|
4503
|
+
"dgsel": "gsel" in vf,
|
4417
4504
|
"dsort": vf["sort"],
|
4418
4505
|
"dcrop": vf["crop"],
|
4419
4506
|
"dth3x": vf["th3x"],
|
@@ -4421,6 +4508,7 @@ class HttpCli(object):
|
|
4421
4508
|
"themes": self.args.themes,
|
4422
4509
|
"turbolvl": self.args.turbo,
|
4423
4510
|
"u2j": self.args.u2j,
|
4511
|
+
"u2sz": self.args.u2sz,
|
4424
4512
|
"idxh": int(self.args.ih),
|
4425
4513
|
"u2sort": self.args.u2sort,
|
4426
4514
|
}
|
@@ -4434,7 +4522,6 @@ class HttpCli(object):
|
|
4434
4522
|
"have_b_u": (self.can_write and self.uparam.get("b") == "u"),
|
4435
4523
|
"sb_lg": "" if "no_sb_lg" in vf else (vf.get("lg_sbf") or "y"),
|
4436
4524
|
"url_suf": url_suf,
|
4437
|
-
"logues": logues,
|
4438
4525
|
"title": html_escape("%s %s" % (self.args.bname, self.vpath), crlf=True),
|
4439
4526
|
"srv_info": srv_infot,
|
4440
4527
|
"dtheme": self.args.theme,
|
@@ -4454,6 +4541,10 @@ class HttpCli(object):
|
|
4454
4541
|
j2a["no_prism"] = True
|
4455
4542
|
|
4456
4543
|
if not self.can_read and not is_dk:
|
4544
|
+
logues, readme = self._add_logues(vn, abspath, None)
|
4545
|
+
ls_ret["logues"] = j2a["logues"] = logues
|
4546
|
+
ls_ret["readme"] = cgv["readme"] = readme
|
4547
|
+
|
4457
4548
|
if is_ls:
|
4458
4549
|
return self.tx_ls(ls_ret)
|
4459
4550
|
|
@@ -4510,6 +4601,8 @@ class HttpCli(object):
|
|
4510
4601
|
):
|
4511
4602
|
ls_names = exclude_dotfiles(ls_names)
|
4512
4603
|
|
4604
|
+
lnames = {x.lower(): x for x in ls_names}
|
4605
|
+
|
4513
4606
|
add_dk = vf.get("dk")
|
4514
4607
|
add_fk = vf.get("fk")
|
4515
4608
|
fk_alg = 2 if "fka" in vf else 1
|
@@ -4699,9 +4792,45 @@ class HttpCli(object):
|
|
4699
4792
|
else:
|
4700
4793
|
taglist = list(tagset)
|
4701
4794
|
|
4795
|
+
logues, readme = self._add_logues(vn, abspath, lnames)
|
4796
|
+
ls_ret["logues"] = j2a["logues"] = logues
|
4797
|
+
ls_ret["readme"] = cgv["readme"] = readme
|
4798
|
+
|
4702
4799
|
if not files and not dirs and not readme and not logues[0] and not logues[1]:
|
4703
4800
|
logues[1] = "this folder is empty"
|
4704
4801
|
|
4802
|
+
if "descript.ion" in lnames and os.path.isfile(
|
4803
|
+
os.path.join(abspath, lnames["descript.ion"])
|
4804
|
+
):
|
4805
|
+
rem = []
|
4806
|
+
with open(os.path.join(abspath, lnames["descript.ion"]), "rb") as f:
|
4807
|
+
for bln in [x.strip() for x in f]:
|
4808
|
+
try:
|
4809
|
+
if bln.endswith(b"\x04\xc2"):
|
4810
|
+
# multiline comment; replace literal r"\n" with " // "
|
4811
|
+
bln = bln.replace(br"\\n", b" // ")[:-2]
|
4812
|
+
ln = bln.decode("utf-8", "replace")
|
4813
|
+
if ln.startswith('"'):
|
4814
|
+
fn, desc = ln.split('" ', 1)
|
4815
|
+
fn = fn[1:]
|
4816
|
+
else:
|
4817
|
+
fn, desc = ln.split(" ", 1)
|
4818
|
+
fe = next(
|
4819
|
+
(x for x in files if x["name"].lower() == fn.lower()), None
|
4820
|
+
)
|
4821
|
+
if fe:
|
4822
|
+
fe["tags"]["descript.ion"] = desc
|
4823
|
+
else:
|
4824
|
+
t = "<li><code>%s</code> %s</li>"
|
4825
|
+
rem.append(t % (html_escape(fn), html_escape(desc)))
|
4826
|
+
except:
|
4827
|
+
pass
|
4828
|
+
if "descript.ion" not in taglist:
|
4829
|
+
taglist.insert(0, "descript.ion")
|
4830
|
+
if rem and not logues[1]:
|
4831
|
+
t = "<h3>descript.ion</h3><ul>\n"
|
4832
|
+
logues[1] = t + "\n".join(rem) + "</ul>"
|
4833
|
+
|
4705
4834
|
if is_ls:
|
4706
4835
|
ls_ret["dirs"] = dirs
|
4707
4836
|
ls_ret["files"] = files
|
@@ -4771,14 +4900,13 @@ class HttpCli(object):
|
|
4771
4900
|
self.conn.hsrv.j2[tpl] = j2env.get_template(tname)
|
4772
4901
|
thumb = ""
|
4773
4902
|
is_pic = is_vid = is_au = False
|
4774
|
-
|
4775
|
-
|
4776
|
-
|
4777
|
-
thumb = fn
|
4903
|
+
for fn in self.args.th_coversd:
|
4904
|
+
if fn in lnames:
|
4905
|
+
thumb = lnames[fn]
|
4778
4906
|
break
|
4779
4907
|
if og_fn:
|
4780
4908
|
ext = og_fn.split(".")[-1].lower()
|
4781
|
-
if ext in self.thumbcli.thumbable:
|
4909
|
+
if self.thumbcli and ext in self.thumbcli.thumbable:
|
4782
4910
|
is_pic = (
|
4783
4911
|
ext in self.thumbcli.fmt_pil
|
4784
4912
|
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
|
|