copyparty 1.13.6__py3-none-any.whl → 1.13.8__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 +224 -81
- copyparty/httpconn.py +3 -0
- copyparty/httpsrv.py +38 -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 +63 -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.8.dist-info}/METADATA +64 -14
- {copyparty-1.13.6.dist-info → copyparty-1.13.8.dist-info}/RECORD +42 -42
- {copyparty-1.13.6.dist-info → copyparty-1.13.8.dist-info}/LICENSE +0 -0
- {copyparty-1.13.6.dist-info → copyparty-1.13.8.dist-info}/WHEEL +0 -0
- {copyparty-1.13.6.dist-info → copyparty-1.13.8.dist-info}/entry_points.txt +0 -0
- {copyparty-1.13.6.dist-info → copyparty-1.13.8.dist-info}/top_level.txt +0 -0
copyparty/httpcli.py
CHANGED
@@ -13,18 +13,22 @@ import json
|
|
13
13
|
import os
|
14
14
|
import random
|
15
15
|
import re
|
16
|
+
import socket
|
16
17
|
import stat
|
17
18
|
import string
|
18
19
|
import threading # typechk
|
19
20
|
import time
|
20
21
|
import uuid
|
21
22
|
from datetime import datetime
|
22
|
-
from email.utils import
|
23
|
+
from email.utils import parsedate
|
23
24
|
from operator import itemgetter
|
24
25
|
|
25
26
|
import jinja2 # typechk
|
26
27
|
|
27
28
|
try:
|
29
|
+
if os.environ.get("PRTY_NO_LZMA"):
|
30
|
+
raise Exception()
|
31
|
+
|
28
32
|
import lzma
|
29
33
|
except:
|
30
34
|
pass
|
@@ -54,6 +58,7 @@ from .util import (
|
|
54
58
|
alltrace,
|
55
59
|
atomic_move,
|
56
60
|
exclude_dotfiles,
|
61
|
+
formatdate,
|
57
62
|
fsenc,
|
58
63
|
gen_filekey,
|
59
64
|
gen_filekey_dbg,
|
@@ -69,7 +74,9 @@ from .util import (
|
|
69
74
|
humansize,
|
70
75
|
ipnorm,
|
71
76
|
loadpy,
|
77
|
+
log_reloc,
|
72
78
|
min_ex,
|
79
|
+
pathmod,
|
73
80
|
quotep,
|
74
81
|
rand_name,
|
75
82
|
read_header,
|
@@ -101,6 +108,9 @@ from .util import (
|
|
101
108
|
if TYPE_CHECKING:
|
102
109
|
from .httpconn import HttpConn
|
103
110
|
|
111
|
+
if not hasattr(socket, "AF_UNIX"):
|
112
|
+
setattr(socket, "AF_UNIX", -9001)
|
113
|
+
|
104
114
|
_ = (argparse, threading)
|
105
115
|
|
106
116
|
NO_CACHE = {"Cache-Control": "no-cache"}
|
@@ -218,6 +228,11 @@ class HttpCli(object):
|
|
218
228
|
ka["s_doctitle"] = self.args.doctitle
|
219
229
|
ka["tcolor"] = self.vn.flags["tcolor"]
|
220
230
|
|
231
|
+
if self.args.js_other and "js" not in ka:
|
232
|
+
zs = self.args.js_other
|
233
|
+
zs += "&" if "?" in zs else "?"
|
234
|
+
ka["js"] = zs
|
235
|
+
|
221
236
|
zso = self.vn.flags.get("html_head")
|
222
237
|
if zso:
|
223
238
|
ka["this"] = self
|
@@ -299,8 +314,11 @@ class HttpCli(object):
|
|
299
314
|
)
|
300
315
|
self.host = self.headers.get("host") or ""
|
301
316
|
if not self.host:
|
302
|
-
|
303
|
-
|
317
|
+
if self.s.family == socket.AF_UNIX:
|
318
|
+
self.host = self.args.name
|
319
|
+
else:
|
320
|
+
zs = "%s:%s" % self.s.getsockname()[:2]
|
321
|
+
self.host = zs[7:] if zs.startswith("::ffff:") else zs
|
304
322
|
|
305
323
|
trusted_xff = False
|
306
324
|
n = self.args.rproxy
|
@@ -687,6 +705,9 @@ class HttpCli(object):
|
|
687
705
|
xban = self.vn.flags.get("xban")
|
688
706
|
if not xban or not runhook(
|
689
707
|
self.log,
|
708
|
+
self.conn.hsrv.broker,
|
709
|
+
None,
|
710
|
+
"xban",
|
690
711
|
xban,
|
691
712
|
self.vn.canonical(self.rem),
|
692
713
|
self.vpath,
|
@@ -783,7 +804,7 @@ class HttpCli(object):
|
|
783
804
|
|
784
805
|
# close if unknown length, otherwise take client's preference
|
785
806
|
response.append("Connection: " + ("Keep-Alive" if self.keepalive else "Close"))
|
786
|
-
response.append("Date: " + formatdate(
|
807
|
+
response.append("Date: " + formatdate())
|
787
808
|
|
788
809
|
# headers{} overrides anything set previously
|
789
810
|
if headers:
|
@@ -807,9 +828,9 @@ class HttpCli(object):
|
|
807
828
|
self.cbonk(self.conn.hsrv.gmal, zs, "cc_hdr", "Cc in out-hdr")
|
808
829
|
raise Pebkac(999)
|
809
830
|
|
831
|
+
response.append("\r\n")
|
810
832
|
try:
|
811
|
-
|
812
|
-
self.s.sendall("\r\n".join(response).encode("utf-8") + b"\r\n\r\n")
|
833
|
+
self.s.sendall("\r\n".join(response).encode("utf-8"))
|
813
834
|
except:
|
814
835
|
raise Pebkac(400, "client d/c while replying headers")
|
815
836
|
|
@@ -1142,7 +1163,7 @@ class HttpCli(object):
|
|
1142
1163
|
return self.tx_mounts()
|
1143
1164
|
|
1144
1165
|
# conditional redirect to single volumes
|
1145
|
-
if self.vpath
|
1166
|
+
if not self.vpath and not self.ouparam:
|
1146
1167
|
nread = len(self.rvol)
|
1147
1168
|
nwrite = len(self.wvol)
|
1148
1169
|
if nread + nwrite == 1 or (self.rvol == self.wvol and nread == 1):
|
@@ -1164,7 +1185,8 @@ class HttpCli(object):
|
|
1164
1185
|
if self.args.no_dav:
|
1165
1186
|
raise Pebkac(405, "WebDAV is disabled in server config")
|
1166
1187
|
|
1167
|
-
vn
|
1188
|
+
vn = self.vn
|
1189
|
+
rem = self.rem
|
1168
1190
|
tap = vn.canonical(rem)
|
1169
1191
|
|
1170
1192
|
if "davauth" in vn.flags and self.uname == "*":
|
@@ -1301,7 +1323,7 @@ class HttpCli(object):
|
|
1301
1323
|
|
1302
1324
|
pvs = {
|
1303
1325
|
"displayname": html_escape(rp.split("/")[-1]),
|
1304
|
-
"getlastmodified": formatdate(mtime
|
1326
|
+
"getlastmodified": formatdate(mtime),
|
1305
1327
|
"resourcetype": '<D:collection xmlns:D="DAV:"/>' if isdir else "",
|
1306
1328
|
"supportedlock": '<D:lockentry xmlns:D="DAV:"><D:lockscope><D:exclusive/></D:lockscope><D:locktype><D:write/></D:locktype></D:lockentry>',
|
1307
1329
|
}
|
@@ -1548,8 +1570,8 @@ class HttpCli(object):
|
|
1548
1570
|
self.log("PUT %s @%s" % (self.req, self.uname))
|
1549
1571
|
|
1550
1572
|
if not self.can_write:
|
1551
|
-
t = "user
|
1552
|
-
raise Pebkac(403, t
|
1573
|
+
t = "user %s does not have write-access under /%s"
|
1574
|
+
raise Pebkac(403, t % (self.uname, self.vn.vpath))
|
1553
1575
|
|
1554
1576
|
if not self.args.no_dav and self._applesan():
|
1555
1577
|
return self.headers.get("content-length") == "0"
|
@@ -1624,6 +1646,9 @@ class HttpCli(object):
|
|
1624
1646
|
if xm:
|
1625
1647
|
runhook(
|
1626
1648
|
self.log,
|
1649
|
+
self.conn.hsrv.broker,
|
1650
|
+
None,
|
1651
|
+
"xm",
|
1627
1652
|
xm,
|
1628
1653
|
self.vn.canonical(self.rem),
|
1629
1654
|
self.vpath,
|
@@ -1772,11 +1797,15 @@ class HttpCli(object):
|
|
1772
1797
|
|
1773
1798
|
if xbu:
|
1774
1799
|
at = time.time() - lifetime
|
1775
|
-
if
|
1800
|
+
vp = vjoin(self.vpath, fn) if nameless else self.vpath
|
1801
|
+
hr = runhook(
|
1776
1802
|
self.log,
|
1803
|
+
self.conn.hsrv.broker,
|
1804
|
+
None,
|
1805
|
+
"xbu.http.dump",
|
1777
1806
|
xbu,
|
1778
1807
|
path,
|
1779
|
-
|
1808
|
+
vp,
|
1780
1809
|
self.host,
|
1781
1810
|
self.uname,
|
1782
1811
|
self.asrv.vfs.get_perms(self.vpath, self.uname),
|
@@ -1785,10 +1814,25 @@ class HttpCli(object):
|
|
1785
1814
|
self.ip,
|
1786
1815
|
at,
|
1787
1816
|
"",
|
1788
|
-
)
|
1817
|
+
)
|
1818
|
+
if not hr:
|
1789
1819
|
t = "upload blocked by xbu server config"
|
1790
1820
|
self.log(t, 1)
|
1791
1821
|
raise Pebkac(403, t)
|
1822
|
+
if hr.get("reloc"):
|
1823
|
+
x = pathmod(self.asrv.vfs, path, vp, hr["reloc"])
|
1824
|
+
if x:
|
1825
|
+
if self.args.hook_v:
|
1826
|
+
log_reloc(self.log, hr["reloc"], x, path, vp, fn, vfs, rem)
|
1827
|
+
fdir, self.vpath, fn, (vfs, rem) = x
|
1828
|
+
if self.args.nw:
|
1829
|
+
fn = os.devnull
|
1830
|
+
else:
|
1831
|
+
bos.makedirs(fdir)
|
1832
|
+
path = os.path.join(fdir, fn)
|
1833
|
+
if not nameless:
|
1834
|
+
self.vpath = vjoin(self.vpath, fn)
|
1835
|
+
params["fdir"] = fdir
|
1792
1836
|
|
1793
1837
|
if is_put and not (self.args.no_dav or self.args.nw) and bos.path.exists(path):
|
1794
1838
|
# allow overwrite if...
|
@@ -1863,24 +1907,45 @@ class HttpCli(object):
|
|
1863
1907
|
fn = fn2
|
1864
1908
|
path = path2
|
1865
1909
|
|
1866
|
-
if xau
|
1867
|
-
self.
|
1868
|
-
|
1869
|
-
|
1870
|
-
|
1871
|
-
|
1872
|
-
|
1873
|
-
|
1874
|
-
|
1875
|
-
|
1876
|
-
|
1877
|
-
|
1878
|
-
|
1879
|
-
|
1880
|
-
|
1881
|
-
|
1882
|
-
|
1883
|
-
|
1910
|
+
if xau:
|
1911
|
+
vp = vjoin(self.vpath, fn) if nameless else self.vpath
|
1912
|
+
hr = runhook(
|
1913
|
+
self.log,
|
1914
|
+
self.conn.hsrv.broker,
|
1915
|
+
None,
|
1916
|
+
"xau.http.dump",
|
1917
|
+
xau,
|
1918
|
+
path,
|
1919
|
+
vp,
|
1920
|
+
self.host,
|
1921
|
+
self.uname,
|
1922
|
+
self.asrv.vfs.get_perms(self.vpath, self.uname),
|
1923
|
+
mt,
|
1924
|
+
post_sz,
|
1925
|
+
self.ip,
|
1926
|
+
at,
|
1927
|
+
"",
|
1928
|
+
)
|
1929
|
+
if not hr:
|
1930
|
+
t = "upload blocked by xau server config"
|
1931
|
+
self.log(t, 1)
|
1932
|
+
wunlink(self.log, path, vfs.flags)
|
1933
|
+
raise Pebkac(403, t)
|
1934
|
+
if hr.get("reloc"):
|
1935
|
+
x = pathmod(self.asrv.vfs, path, vp, hr["reloc"])
|
1936
|
+
if x:
|
1937
|
+
if self.args.hook_v:
|
1938
|
+
log_reloc(self.log, hr["reloc"], x, path, vp, fn, vfs, rem)
|
1939
|
+
fdir, self.vpath, fn, (vfs, rem) = x
|
1940
|
+
bos.makedirs(fdir)
|
1941
|
+
path2 = os.path.join(fdir, fn)
|
1942
|
+
atomic_move(self.log, path, path2, vfs.flags)
|
1943
|
+
path = path2
|
1944
|
+
if not nameless:
|
1945
|
+
self.vpath = vjoin(self.vpath, fn)
|
1946
|
+
sz = bos.path.getsize(path)
|
1947
|
+
else:
|
1948
|
+
sz = post_sz
|
1884
1949
|
|
1885
1950
|
vfs, rem = vfs.get_dbv(rem)
|
1886
1951
|
self.conn.hsrv.broker.say(
|
@@ -1903,7 +1968,7 @@ class HttpCli(object):
|
|
1903
1968
|
alg,
|
1904
1969
|
self.args.fk_salt,
|
1905
1970
|
path,
|
1906
|
-
|
1971
|
+
sz,
|
1907
1972
|
0 if ANYWIN else bos.stat(path).st_ino,
|
1908
1973
|
)[: vfs.flags["fk"]]
|
1909
1974
|
|
@@ -2206,13 +2271,21 @@ class HttpCli(object):
|
|
2206
2271
|
raise Pebkac(400, "need hash and wark headers for binary POST")
|
2207
2272
|
|
2208
2273
|
chashes = [x.strip() for x in chashes]
|
2274
|
+
if len(chashes) == 3 and len(chashes[1]) == 1:
|
2275
|
+
# the first hash, then length of consecutive hashes,
|
2276
|
+
# then a list of stitched hashes as one long string
|
2277
|
+
clen = int(chashes[1])
|
2278
|
+
siblings = chashes[2]
|
2279
|
+
chashes = [chashes[0]]
|
2280
|
+
for n in range(0, len(siblings), clen):
|
2281
|
+
chashes.append(siblings[n : n + clen])
|
2209
2282
|
|
2210
2283
|
vfs, _ = self.asrv.vfs.get(self.vpath, self.uname, False, True)
|
2211
2284
|
ptop = (vfs.dbv or vfs).realpath
|
2212
2285
|
|
2213
2286
|
x = self.conn.hsrv.broker.ask("up2k.handle_chunks", ptop, wark, chashes)
|
2214
2287
|
response = x.get()
|
2215
|
-
chunksize, cstarts, path, lastmod, sprs = response
|
2288
|
+
chashes, chunksize, cstarts, path, lastmod, sprs = response
|
2216
2289
|
maxsize = chunksize * len(chashes)
|
2217
2290
|
cstart0 = cstarts[0]
|
2218
2291
|
|
@@ -2520,18 +2593,15 @@ class HttpCli(object):
|
|
2520
2593
|
fname = sanitize_fn(
|
2521
2594
|
p_file or "", "", [".prologue.html", ".epilogue.html"]
|
2522
2595
|
)
|
2596
|
+
abspath = os.path.join(fdir, fname)
|
2597
|
+
suffix = "-%.6f-%s" % (time.time(), dip)
|
2523
2598
|
if p_file and not nullwrite:
|
2524
2599
|
if rnd:
|
2525
2600
|
fname = rand_name(fdir, fname, rnd)
|
2526
2601
|
|
2527
|
-
if not bos.path.isdir(fdir):
|
2528
|
-
raise Pebkac(404, "that folder does not exist")
|
2529
|
-
|
2530
|
-
suffix = "-{:.6f}-{}".format(time.time(), dip)
|
2531
2602
|
open_args = {"fdir": fdir, "suffix": suffix}
|
2532
2603
|
|
2533
2604
|
if "replace" in self.uparam:
|
2534
|
-
abspath = os.path.join(fdir, fname)
|
2535
2605
|
if not self.can_delete:
|
2536
2606
|
self.log("user not allowed to overwrite with ?replace")
|
2537
2607
|
elif bos.path.exists(abspath):
|
@@ -2541,16 +2611,6 @@ class HttpCli(object):
|
|
2541
2611
|
except:
|
2542
2612
|
t = "toctou while deleting for ?replace: %s"
|
2543
2613
|
self.log(t % (abspath,))
|
2544
|
-
|
2545
|
-
# reserve destination filename
|
2546
|
-
with ren_open(fname, "wb", fdir=fdir, suffix=suffix) as zfw:
|
2547
|
-
fname = zfw["orz"][1]
|
2548
|
-
|
2549
|
-
tnam = fname + ".PARTIAL"
|
2550
|
-
if self.args.dotpart:
|
2551
|
-
tnam = "." + tnam
|
2552
|
-
|
2553
|
-
abspath = os.path.join(fdir, fname)
|
2554
2614
|
else:
|
2555
2615
|
open_args = {}
|
2556
2616
|
tnam = fname = os.devnull
|
@@ -2558,23 +2618,65 @@ class HttpCli(object):
|
|
2558
2618
|
|
2559
2619
|
if xbu:
|
2560
2620
|
at = time.time() - lifetime
|
2561
|
-
|
2621
|
+
hr = runhook(
|
2562
2622
|
self.log,
|
2623
|
+
self.conn.hsrv.broker,
|
2624
|
+
None,
|
2625
|
+
"xbu.http.bup",
|
2563
2626
|
xbu,
|
2564
2627
|
abspath,
|
2565
|
-
|
2628
|
+
vjoin(upload_vpath, fname),
|
2566
2629
|
self.host,
|
2567
2630
|
self.uname,
|
2568
|
-
self.asrv.vfs.get_perms(
|
2631
|
+
self.asrv.vfs.get_perms(upload_vpath, self.uname),
|
2569
2632
|
at,
|
2570
2633
|
0,
|
2571
2634
|
self.ip,
|
2572
2635
|
at,
|
2573
2636
|
"",
|
2574
|
-
)
|
2637
|
+
)
|
2638
|
+
if not hr:
|
2575
2639
|
t = "upload blocked by xbu server config"
|
2576
2640
|
self.log(t, 1)
|
2577
2641
|
raise Pebkac(403, t)
|
2642
|
+
if hr.get("reloc"):
|
2643
|
+
zs = vjoin(upload_vpath, fname)
|
2644
|
+
x = pathmod(self.asrv.vfs, abspath, zs, hr["reloc"])
|
2645
|
+
if x:
|
2646
|
+
if self.args.hook_v:
|
2647
|
+
log_reloc(
|
2648
|
+
self.log,
|
2649
|
+
hr["reloc"],
|
2650
|
+
x,
|
2651
|
+
abspath,
|
2652
|
+
zs,
|
2653
|
+
fname,
|
2654
|
+
vfs,
|
2655
|
+
rem,
|
2656
|
+
)
|
2657
|
+
fdir, upload_vpath, fname, (vfs, rem) = x
|
2658
|
+
abspath = os.path.join(fdir, fname)
|
2659
|
+
if nullwrite:
|
2660
|
+
fdir = abspath = ""
|
2661
|
+
else:
|
2662
|
+
open_args["fdir"] = fdir
|
2663
|
+
|
2664
|
+
if p_file and not nullwrite:
|
2665
|
+
bos.makedirs(fdir)
|
2666
|
+
|
2667
|
+
# reserve destination filename
|
2668
|
+
with ren_open(fname, "wb", fdir=fdir, suffix=suffix) as zfw:
|
2669
|
+
fname = zfw["orz"][1]
|
2670
|
+
|
2671
|
+
tnam = fname + ".PARTIAL"
|
2672
|
+
if self.args.dotpart:
|
2673
|
+
tnam = "." + tnam
|
2674
|
+
|
2675
|
+
abspath = os.path.join(fdir, fname)
|
2676
|
+
else:
|
2677
|
+
open_args = {}
|
2678
|
+
tnam = fname = os.devnull
|
2679
|
+
fdir = abspath = ""
|
2578
2680
|
|
2579
2681
|
if lim:
|
2580
2682
|
lim.chk_bup(self.ip)
|
@@ -2618,29 +2720,58 @@ class HttpCli(object):
|
|
2618
2720
|
|
2619
2721
|
tabspath = ""
|
2620
2722
|
|
2723
|
+
at = time.time() - lifetime
|
2724
|
+
if xau:
|
2725
|
+
hr = runhook(
|
2726
|
+
self.log,
|
2727
|
+
self.conn.hsrv.broker,
|
2728
|
+
None,
|
2729
|
+
"xau.http.bup",
|
2730
|
+
xau,
|
2731
|
+
abspath,
|
2732
|
+
vjoin(upload_vpath, fname),
|
2733
|
+
self.host,
|
2734
|
+
self.uname,
|
2735
|
+
self.asrv.vfs.get_perms(upload_vpath, self.uname),
|
2736
|
+
at,
|
2737
|
+
sz,
|
2738
|
+
self.ip,
|
2739
|
+
at,
|
2740
|
+
"",
|
2741
|
+
)
|
2742
|
+
if not hr:
|
2743
|
+
t = "upload blocked by xau server config"
|
2744
|
+
self.log(t, 1)
|
2745
|
+
wunlink(self.log, abspath, vfs.flags)
|
2746
|
+
raise Pebkac(403, t)
|
2747
|
+
if hr.get("reloc"):
|
2748
|
+
zs = vjoin(upload_vpath, fname)
|
2749
|
+
x = pathmod(self.asrv.vfs, abspath, zs, hr["reloc"])
|
2750
|
+
if x:
|
2751
|
+
if self.args.hook_v:
|
2752
|
+
log_reloc(
|
2753
|
+
self.log,
|
2754
|
+
hr["reloc"],
|
2755
|
+
x,
|
2756
|
+
abspath,
|
2757
|
+
zs,
|
2758
|
+
fname,
|
2759
|
+
vfs,
|
2760
|
+
rem,
|
2761
|
+
)
|
2762
|
+
fdir, upload_vpath, fname, (vfs, rem) = x
|
2763
|
+
ap2 = os.path.join(fdir, fname)
|
2764
|
+
if nullwrite:
|
2765
|
+
fdir = ap2 = ""
|
2766
|
+
else:
|
2767
|
+
bos.makedirs(fdir)
|
2768
|
+
atomic_move(self.log, abspath, ap2, vfs.flags)
|
2769
|
+
abspath = ap2
|
2770
|
+
sz = bos.path.getsize(abspath)
|
2771
|
+
|
2621
2772
|
files.append(
|
2622
2773
|
(sz, sha_hex, sha_b64, p_file or "(discarded)", fname, abspath)
|
2623
2774
|
)
|
2624
|
-
at = time.time() - lifetime
|
2625
|
-
if xau and not runhook(
|
2626
|
-
self.log,
|
2627
|
-
xau,
|
2628
|
-
abspath,
|
2629
|
-
self.vpath,
|
2630
|
-
self.host,
|
2631
|
-
self.uname,
|
2632
|
-
self.asrv.vfs.get_perms(self.vpath, self.uname),
|
2633
|
-
at,
|
2634
|
-
sz,
|
2635
|
-
self.ip,
|
2636
|
-
at,
|
2637
|
-
"",
|
2638
|
-
):
|
2639
|
-
t = "upload blocked by xau server config"
|
2640
|
-
self.log(t, 1)
|
2641
|
-
wunlink(self.log, abspath, vfs.flags)
|
2642
|
-
raise Pebkac(403, t)
|
2643
|
-
|
2644
2775
|
dbv, vrem = vfs.get_dbv(rem)
|
2645
2776
|
self.conn.hsrv.broker.say(
|
2646
2777
|
"up2k.hash_file",
|
@@ -2696,13 +2827,14 @@ class HttpCli(object):
|
|
2696
2827
|
for sz, sha_hex, sha_b64, ofn, lfn, ap in files:
|
2697
2828
|
vsuf = ""
|
2698
2829
|
if (self.can_read or self.can_upget) and "fk" in vfs.flags:
|
2830
|
+
st = bos.stat(ap)
|
2699
2831
|
alg = 2 if "fka" in vfs.flags else 1
|
2700
2832
|
vsuf = "?k=" + self.gen_fk(
|
2701
2833
|
alg,
|
2702
2834
|
self.args.fk_salt,
|
2703
2835
|
ap,
|
2704
|
-
|
2705
|
-
0 if ANYWIN or not ap else
|
2836
|
+
st.st_size,
|
2837
|
+
0 if ANYWIN or not ap else st.st_ino,
|
2706
2838
|
)[: vfs.flags["fk"]]
|
2707
2839
|
|
2708
2840
|
if "media" in self.uparam or "medialinks" in vfs.flags:
|
@@ -2869,6 +3001,9 @@ class HttpCli(object):
|
|
2869
3001
|
if xbu:
|
2870
3002
|
if not runhook(
|
2871
3003
|
self.log,
|
3004
|
+
self.conn.hsrv.broker,
|
3005
|
+
None,
|
3006
|
+
"xbu.http.txt",
|
2872
3007
|
xbu,
|
2873
3008
|
fp,
|
2874
3009
|
self.vpath,
|
@@ -2908,6 +3043,9 @@ class HttpCli(object):
|
|
2908
3043
|
xau = vfs.flags.get("xau")
|
2909
3044
|
if xau and not runhook(
|
2910
3045
|
self.log,
|
3046
|
+
self.conn.hsrv.broker,
|
3047
|
+
None,
|
3048
|
+
"xau.http.txt",
|
2911
3049
|
xau,
|
2912
3050
|
fp,
|
2913
3051
|
self.vpath,
|
@@ -2948,7 +3086,7 @@ class HttpCli(object):
|
|
2948
3086
|
return True
|
2949
3087
|
|
2950
3088
|
def _chk_lastmod(self, file_ts ) :
|
2951
|
-
file_lastmod = formatdate(file_ts
|
3089
|
+
file_lastmod = formatdate(file_ts)
|
2952
3090
|
cli_lastmod = self.headers.get("if-modified-since")
|
2953
3091
|
if cli_lastmod:
|
2954
3092
|
try:
|
@@ -3030,8 +3168,8 @@ class HttpCli(object):
|
|
3030
3168
|
for n, fn in enumerate([".prologue.html", ".epilogue.html"]):
|
3031
3169
|
if lnames is not None and fn not in lnames:
|
3032
3170
|
continue
|
3033
|
-
fn =
|
3034
|
-
if bos.path.
|
3171
|
+
fn = "%s/%s" % (abspath, fn)
|
3172
|
+
if bos.path.isfile(fn):
|
3035
3173
|
with open(fsenc(fn), "rb") as f:
|
3036
3174
|
logues[n] = f.read().decode("utf-8")
|
3037
3175
|
if "exp" in vn.flags:
|
@@ -3049,7 +3187,7 @@ class HttpCli(object):
|
|
3049
3187
|
fns = []
|
3050
3188
|
|
3051
3189
|
for fn in fns:
|
3052
|
-
fn =
|
3190
|
+
fn = "%s/%s" % (abspath, fn)
|
3053
3191
|
if bos.path.isfile(fn):
|
3054
3192
|
with open(fsenc(fn), "rb") as f:
|
3055
3193
|
readme = f.read().decode("utf-8")
|
@@ -3584,7 +3722,7 @@ class HttpCli(object):
|
|
3584
3722
|
# (useragent-sniffing kinshi due to caching proxies)
|
3585
3723
|
mime, ico = self.ico.get(txt, not small, "raster" in self.uparam)
|
3586
3724
|
|
3587
|
-
lm = formatdate(self.E.t0
|
3725
|
+
lm = formatdate(self.E.t0)
|
3588
3726
|
self.reply(ico, mime=mime, headers={"Last-Modified": lm})
|
3589
3727
|
return True
|
3590
3728
|
|
@@ -3663,6 +3801,11 @@ class HttpCli(object):
|
|
3663
3801
|
"arg_base": arg_base,
|
3664
3802
|
}
|
3665
3803
|
|
3804
|
+
if self.args.js_other and "js" not in targs:
|
3805
|
+
zs = self.args.js_other
|
3806
|
+
zs += "&" if "?" in zs else "?"
|
3807
|
+
targs["js"] = zs
|
3808
|
+
|
3666
3809
|
zfv = self.vn.flags.get("html_head")
|
3667
3810
|
if zfv:
|
3668
3811
|
targs["this"] = self
|
@@ -4140,7 +4283,7 @@ class HttpCli(object):
|
|
4140
4283
|
if self.args.no_mv:
|
4141
4284
|
raise Pebkac(403, "the rename/move feature is disabled in server config")
|
4142
4285
|
|
4143
|
-
x = self.conn.hsrv.broker.ask("up2k.handle_mv", self.uname, vsrc, vdst)
|
4286
|
+
x = self.conn.hsrv.broker.ask("up2k.handle_mv", self.uname, self.ip, vsrc, vdst)
|
4144
4287
|
self.loud_reply(x.get(), status=201)
|
4145
4288
|
return True
|
4146
4289
|
|
copyparty/httpconn.py
CHANGED
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, unicode
|
15
|
+
from .__init__ import ANYWIN, CORES, EXE, MACOS, PY2, TYPE_CHECKING, EnvParams, unicode
|
16
16
|
|
17
17
|
try:
|
18
18
|
MNFE = ModuleNotFoundError
|
@@ -81,6 +81,13 @@ if TYPE_CHECKING:
|
|
81
81
|
from .broker_util import BrokerCli
|
82
82
|
from .ssdp import SSDPr
|
83
83
|
|
84
|
+
if PY2:
|
85
|
+
range = xrange # type: ignore
|
86
|
+
|
87
|
+
if not hasattr(socket, "AF_UNIX"):
|
88
|
+
setattr(socket, "AF_UNIX", -9001)
|
89
|
+
|
90
|
+
|
84
91
|
class HttpSrv(object):
|
85
92
|
"""
|
86
93
|
handles incoming connections using HttpConn to process http,
|
@@ -236,15 +243,24 @@ class HttpSrv(object):
|
|
236
243
|
return
|
237
244
|
|
238
245
|
def listen(self, sck , nlisteners ) :
|
246
|
+
tcp = sck.family != socket.AF_UNIX
|
247
|
+
|
239
248
|
if self.args.j != 1:
|
240
249
|
# lost in the pickle; redefine
|
241
250
|
if not ANYWIN or self.args.reuseaddr:
|
242
251
|
sck.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
243
252
|
|
244
|
-
|
253
|
+
if tcp:
|
254
|
+
sck.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
255
|
+
|
245
256
|
sck.settimeout(None) # < does not inherit, ^ opts above do
|
246
257
|
|
247
|
-
|
258
|
+
if tcp:
|
259
|
+
ip, port = sck.getsockname()[:2]
|
260
|
+
else:
|
261
|
+
ip = re.sub(r"\.[0-9]+$", "", sck.getsockname().split("/")[-1])
|
262
|
+
port = 0
|
263
|
+
|
248
264
|
self.srvs.append(sck)
|
249
265
|
self.bound.add((ip, port))
|
250
266
|
self.nclimax = math.ceil(self.args.nc * 1.0 / nlisteners)
|
@@ -256,10 +272,19 @@ class HttpSrv(object):
|
|
256
272
|
|
257
273
|
def thr_listen(self, srv_sck ) :
|
258
274
|
"""listens on a shared tcp server"""
|
259
|
-
ip, port = srv_sck.getsockname()[:2]
|
260
275
|
fno = srv_sck.fileno()
|
261
|
-
|
262
|
-
|
276
|
+
if srv_sck.family == socket.AF_UNIX:
|
277
|
+
ip = re.sub(r"\.[0-9]+$", "", srv_sck.getsockname())
|
278
|
+
msg = "subscribed @ %s f%d p%d" % (ip, fno, os.getpid())
|
279
|
+
ip = ip.split("/")[-1]
|
280
|
+
port = 0
|
281
|
+
tcp = False
|
282
|
+
else:
|
283
|
+
tcp = True
|
284
|
+
ip, port = srv_sck.getsockname()[:2]
|
285
|
+
hip = "[%s]" % (ip,) if ":" in ip else ip
|
286
|
+
msg = "subscribed @ %s:%d f%d p%d" % (hip, port, fno, os.getpid())
|
287
|
+
|
263
288
|
self.log(self.name, msg)
|
264
289
|
|
265
290
|
Daemon(self.broker.say, "sig-hsrv-up1", ("cb_httpsrv_up",))
|
@@ -331,11 +356,13 @@ class HttpSrv(object):
|
|
331
356
|
|
332
357
|
try:
|
333
358
|
sck, saddr = srv_sck.accept()
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
359
|
+
if tcp:
|
360
|
+
cip = unicode(saddr[0])
|
361
|
+
if cip.startswith("::ffff:"):
|
362
|
+
cip = cip[7:]
|
363
|
+
addr = (cip, saddr[1])
|
364
|
+
else:
|
365
|
+
addr = (ip, sck.fileno())
|
339
366
|
except (OSError, socket.error) as ex:
|
340
367
|
if self.stopping:
|
341
368
|
break
|