copyparty 1.13.5__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 +222 -94
- copyparty/util.py +166 -31
- copyparty/web/a/u2c.py +22 -9
- copyparty/web/baguettebox.js.gz +0 -0
- copyparty/web/browser.css.gz +0 -0
- copyparty/web/browser.js.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 +5 -2
- copyparty/web/ui.css.gz +0 -0
- copyparty/web/up2k.js.gz +0 -0
- copyparty/web/util.js.gz +0 -0
- {copyparty-1.13.5.dist-info → copyparty-1.13.7.dist-info}/METADATA +66 -14
- {copyparty-1.13.5.dist-info → copyparty-1.13.7.dist-info}/RECORD +46 -46
- {copyparty-1.13.5.dist-info → copyparty-1.13.7.dist-info}/WHEEL +1 -1
- {copyparty-1.13.5.dist-info → copyparty-1.13.7.dist-info}/LICENSE +0 -0
- {copyparty-1.13.5.dist-info → copyparty-1.13.7.dist-info}/entry_points.txt +0 -0
- {copyparty-1.13.5.dist-info → copyparty-1.13.7.dist-info}/top_level.txt +0 -0
copyparty/up2k.py
CHANGED
@@ -28,8 +28,8 @@ from .fsutil import Fstab
|
|
28
28
|
from .mtag import MParser, MTag
|
29
29
|
from .util import (
|
30
30
|
HAVE_SQLITE3,
|
31
|
-
VF_CAREFUL,
|
32
31
|
SYMTIME,
|
32
|
+
VF_CAREFUL,
|
33
33
|
Daemon,
|
34
34
|
MTHash,
|
35
35
|
Pebkac,
|
@@ -46,6 +46,7 @@ from .util import (
|
|
46
46
|
hidedir,
|
47
47
|
humansize,
|
48
48
|
min_ex,
|
49
|
+
pathmod,
|
49
50
|
quotep,
|
50
51
|
rand_name,
|
51
52
|
ren_open,
|
@@ -162,6 +163,7 @@ class Up2k(object):
|
|
162
163
|
self.xiu_ptn = re.compile(r"(?:^|,)i([0-9]+)")
|
163
164
|
self.xiu_busy = False # currently running hook
|
164
165
|
self.xiu_asleep = True # needs rescan_cond poke to schedule self
|
166
|
+
self.fx_backlog = []
|
165
167
|
|
166
168
|
self.cur = {}
|
167
169
|
self.mem_cur = None
|
@@ -542,7 +544,7 @@ class Up2k(object):
|
|
542
544
|
nrm += 1
|
543
545
|
|
544
546
|
if nrm:
|
545
|
-
self.log("
|
547
|
+
self.log("%d files graduated in /%s" % (nrm, vp))
|
546
548
|
|
547
549
|
if timeout < 10:
|
548
550
|
continue
|
@@ -2541,7 +2543,7 @@ class Up2k(object):
|
|
2541
2543
|
if self.mutex.acquire(timeout=10):
|
2542
2544
|
got_lock = True
|
2543
2545
|
with self.reg_mutex:
|
2544
|
-
|
2546
|
+
ret = self._handle_json(cj)
|
2545
2547
|
else:
|
2546
2548
|
t = "cannot receive uploads right now;\nserver busy with {}.\nPlease wait; the client will retry..."
|
2547
2549
|
raise Pebkac(503, t.format(self.blocked or "[unknown]"))
|
@@ -2549,11 +2551,16 @@ class Up2k(object):
|
|
2549
2551
|
if not PY2:
|
2550
2552
|
raise
|
2551
2553
|
with self.mutex, self.reg_mutex:
|
2552
|
-
|
2554
|
+
ret = self._handle_json(cj)
|
2553
2555
|
finally:
|
2554
2556
|
if got_lock:
|
2555
2557
|
self.mutex.release()
|
2556
2558
|
|
2559
|
+
if self.fx_backlog:
|
2560
|
+
self.do_fx_backlog()
|
2561
|
+
|
2562
|
+
return ret
|
2563
|
+
|
2557
2564
|
def _handle_json(self, cj ) :
|
2558
2565
|
ptop = cj["ptop"]
|
2559
2566
|
if not self.register_vpath(ptop, cj["vcfg"]):
|
@@ -2747,7 +2754,7 @@ class Up2k(object):
|
|
2747
2754
|
job = deepcopy(job)
|
2748
2755
|
job["wark"] = wark
|
2749
2756
|
job["at"] = cj.get("at") or time.time()
|
2750
|
-
for k in "lmod ptop vtop prel host user addr".split():
|
2757
|
+
for k in "lmod ptop vtop prel name host user addr".split():
|
2751
2758
|
job[k] = cj.get(k) or ""
|
2752
2759
|
|
2753
2760
|
pdir = djoin(cj["ptop"], cj["prel"])
|
@@ -2755,28 +2762,43 @@ class Up2k(object):
|
|
2755
2762
|
job["name"] = rand_name(
|
2756
2763
|
pdir, cj["name"], vfs.flags["nrand"]
|
2757
2764
|
)
|
2758
|
-
else:
|
2759
|
-
job["name"] = self._untaken(pdir, cj, now)
|
2760
2765
|
|
2761
2766
|
dst = djoin(job["ptop"], job["prel"], job["name"])
|
2762
2767
|
xbu = vfs.flags.get("xbu")
|
2763
|
-
if xbu
|
2764
|
-
|
2765
|
-
|
2766
|
-
|
2767
|
-
|
2768
|
-
|
2769
|
-
|
2770
|
-
|
2771
|
-
|
2772
|
-
|
2773
|
-
|
2774
|
-
|
2775
|
-
|
2776
|
-
|
2777
|
-
|
2778
|
-
|
2779
|
-
|
2768
|
+
if xbu:
|
2769
|
+
vp = djoin(job["vtop"], job["prel"], job["name"])
|
2770
|
+
hr = runhook(
|
2771
|
+
self.log,
|
2772
|
+
None,
|
2773
|
+
self,
|
2774
|
+
"xbu.up2k.dupe",
|
2775
|
+
xbu, # type: ignore
|
2776
|
+
dst,
|
2777
|
+
vp,
|
2778
|
+
job["host"],
|
2779
|
+
job["user"],
|
2780
|
+
self.asrv.vfs.get_perms(job["vtop"], job["user"]),
|
2781
|
+
job["lmod"],
|
2782
|
+
job["size"],
|
2783
|
+
job["addr"],
|
2784
|
+
job["at"],
|
2785
|
+
"",
|
2786
|
+
)
|
2787
|
+
if not hr:
|
2788
|
+
t = "upload blocked by xbu server config: %s" % (dst,)
|
2789
|
+
self.log(t, 1)
|
2790
|
+
raise Pebkac(403, t)
|
2791
|
+
if hr.get("reloc"):
|
2792
|
+
x = pathmod(self.asrv.vfs, dst, vp, hr["reloc"])
|
2793
|
+
if x:
|
2794
|
+
pdir, _, job["name"], (vfs, rem) = x
|
2795
|
+
dst = os.path.join(pdir, job["name"])
|
2796
|
+
job["ptop"] = vfs.realpath
|
2797
|
+
job["vtop"] = vfs.vpath
|
2798
|
+
job["prel"] = rem
|
2799
|
+
bos.makedirs(pdir)
|
2800
|
+
|
2801
|
+
job["name"] = self._untaken(pdir, job, now)
|
2780
2802
|
|
2781
2803
|
if not self.args.nw:
|
2782
2804
|
dvf = vfs.flags
|
@@ -2848,11 +2870,11 @@ class Up2k(object):
|
|
2848
2870
|
# one chunk may occur multiple times in a file;
|
2849
2871
|
# filter to unique values for the list of missing chunks
|
2850
2872
|
# (preserve order to reduce disk thrashing)
|
2851
|
-
lut =
|
2873
|
+
lut = set()
|
2852
2874
|
for k in cj["hash"]:
|
2853
2875
|
if k not in lut:
|
2854
2876
|
job["need"].append(k)
|
2855
|
-
lut
|
2877
|
+
lut.add(k)
|
2856
2878
|
|
2857
2879
|
try:
|
2858
2880
|
self._new_upload(job)
|
@@ -3012,7 +3034,7 @@ class Up2k(object):
|
|
3012
3034
|
|
3013
3035
|
def handle_chunks(
|
3014
3036
|
self, ptop , wark , chashes
|
3015
|
-
)
|
3037
|
+
) :
|
3016
3038
|
with self.mutex, self.reg_mutex:
|
3017
3039
|
self.db_act = self.vol_act[ptop] = time.time()
|
3018
3040
|
job = self.registry[ptop].get(wark)
|
@@ -3021,12 +3043,37 @@ class Up2k(object):
|
|
3021
3043
|
self.log("unknown wark [{}], known: {}".format(wark, known))
|
3022
3044
|
raise Pebkac(400, "unknown wark" + SSEELOG)
|
3023
3045
|
|
3046
|
+
if len(chashes) > 1 and len(chashes[1]) < 44:
|
3047
|
+
# first hash is full-length; expand remaining ones
|
3048
|
+
uniq = []
|
3049
|
+
lut = set()
|
3050
|
+
for chash in job["hash"]:
|
3051
|
+
if chash not in lut:
|
3052
|
+
uniq.append(chash)
|
3053
|
+
lut.add(chash)
|
3054
|
+
try:
|
3055
|
+
nchunk = uniq.index(chashes[0])
|
3056
|
+
except:
|
3057
|
+
raise Pebkac(400, "unknown chunk0 [%s]" % (chashes[0]))
|
3058
|
+
expanded = [chashes[0]]
|
3059
|
+
for prefix in chashes[1:]:
|
3060
|
+
nchunk += 1
|
3061
|
+
chash = uniq[nchunk]
|
3062
|
+
if not chash.startswith(prefix):
|
3063
|
+
t = "next sibling chunk does not start with expected prefix [%s]: [%s]"
|
3064
|
+
raise Pebkac(400, t % (prefix, chash))
|
3065
|
+
expanded.append(chash)
|
3066
|
+
chashes = expanded
|
3067
|
+
|
3024
3068
|
for chash in chashes:
|
3025
3069
|
if chash not in job["need"]:
|
3026
3070
|
msg = "chash = {} , need:\n".format(chash)
|
3027
3071
|
msg += "\n".join(job["need"])
|
3028
3072
|
self.log(msg)
|
3029
|
-
|
3073
|
+
t = "already got that (%s) but thanks??"
|
3074
|
+
if chash not in job["hash"]:
|
3075
|
+
t = "unknown chunk wtf: %s"
|
3076
|
+
raise Pebkac(400, t % (chash,))
|
3030
3077
|
|
3031
3078
|
if chash in job["busy"]:
|
3032
3079
|
nh = len(job["hash"])
|
@@ -3034,9 +3081,11 @@ class Up2k(object):
|
|
3034
3081
|
t = "that chunk is already being written to:\n {}\n {} {}/{}\n {}"
|
3035
3082
|
raise Pebkac(400, t.format(wark, chash, idx, nh, job["name"]))
|
3036
3083
|
|
3084
|
+
assert chash # type: ignore
|
3037
3085
|
chunksize = up2k_chunksize(job["size"])
|
3038
3086
|
|
3039
3087
|
coffsets = []
|
3088
|
+
nchunks = []
|
3040
3089
|
for chash in chashes:
|
3041
3090
|
nchunk = [n for n, v in enumerate(job["hash"]) if v == chash]
|
3042
3091
|
if not nchunk:
|
@@ -3044,6 +3093,7 @@ class Up2k(object):
|
|
3044
3093
|
|
3045
3094
|
ofs = [chunksize * x for x in nchunk]
|
3046
3095
|
coffsets.append(ofs)
|
3096
|
+
nchunks.append(nchunk)
|
3047
3097
|
|
3048
3098
|
for ofs1, ofs2 in zip(coffsets, coffsets[1:]):
|
3049
3099
|
gap = (ofs2[0] - ofs1[0]) - chunksize
|
@@ -3055,16 +3105,16 @@ class Up2k(object):
|
|
3055
3105
|
|
3056
3106
|
if not job["sprs"]:
|
3057
3107
|
cur_sz = bos.path.getsize(path)
|
3058
|
-
if
|
3108
|
+
if coffsets[0][0] > cur_sz:
|
3059
3109
|
t = "please upload sequentially using one thread;\nserver filesystem does not support sparse files.\n file: {}\n chunk: {}\n cofs: {}\n flen: {}"
|
3060
|
-
t = t.format(job["name"],
|
3110
|
+
t = t.format(job["name"], nchunks[0][0], coffsets[0][0], cur_sz)
|
3061
3111
|
raise Pebkac(400, t)
|
3062
3112
|
|
3063
3113
|
job["busy"][chash] = 1
|
3064
3114
|
|
3065
3115
|
job["poke"] = time.time()
|
3066
3116
|
|
3067
|
-
return chunksize, coffsets, path, job["lmod"], job["sprs"]
|
3117
|
+
return chashes, chunksize, coffsets, path, job["lmod"], job["sprs"]
|
3068
3118
|
|
3069
3119
|
def release_chunks(self, ptop , wark , chashes ) :
|
3070
3120
|
with self.reg_mutex:
|
@@ -3111,6 +3161,9 @@ class Up2k(object):
|
|
3111
3161
|
with self.mutex, self.reg_mutex:
|
3112
3162
|
self._finish_upload(ptop, wark)
|
3113
3163
|
|
3164
|
+
if self.fx_backlog:
|
3165
|
+
self.do_fx_backlog()
|
3166
|
+
|
3114
3167
|
def _finish_upload(self, ptop , wark ) :
|
3115
3168
|
"""mutex(main,reg) me"""
|
3116
3169
|
try:
|
@@ -3304,25 +3357,30 @@ class Up2k(object):
|
|
3304
3357
|
|
3305
3358
|
xau = False if skip_xau else vflags.get("xau")
|
3306
3359
|
dst = djoin(ptop, rd, fn)
|
3307
|
-
if xau
|
3308
|
-
|
3309
|
-
|
3310
|
-
|
3311
|
-
|
3312
|
-
|
3313
|
-
|
3314
|
-
|
3315
|
-
|
3316
|
-
|
3317
|
-
|
3318
|
-
|
3319
|
-
|
3320
|
-
|
3321
|
-
|
3322
|
-
|
3323
|
-
|
3324
|
-
|
3325
|
-
|
3360
|
+
if xau:
|
3361
|
+
hr = runhook(
|
3362
|
+
self.log,
|
3363
|
+
None,
|
3364
|
+
self,
|
3365
|
+
"xau.up2k",
|
3366
|
+
xau,
|
3367
|
+
dst,
|
3368
|
+
djoin(vtop, rd, fn),
|
3369
|
+
host,
|
3370
|
+
usr,
|
3371
|
+
self.asrv.vfs.get_perms(djoin(vtop, rd, fn), usr),
|
3372
|
+
ts,
|
3373
|
+
sz,
|
3374
|
+
ip,
|
3375
|
+
at or time.time(),
|
3376
|
+
"",
|
3377
|
+
)
|
3378
|
+
if not hr:
|
3379
|
+
t = "upload blocked by xau server config"
|
3380
|
+
self.log(t, 1)
|
3381
|
+
wunlink(self.log, dst, vflags)
|
3382
|
+
self.registry[ptop].pop(wark, None)
|
3383
|
+
raise Pebkac(403, t)
|
3326
3384
|
|
3327
3385
|
xiu = vflags.get("xiu")
|
3328
3386
|
if xiu:
|
@@ -3506,6 +3564,9 @@ class Up2k(object):
|
|
3506
3564
|
if xbd:
|
3507
3565
|
if not runhook(
|
3508
3566
|
self.log,
|
3567
|
+
None,
|
3568
|
+
self,
|
3569
|
+
"xbd",
|
3509
3570
|
xbd,
|
3510
3571
|
abspath,
|
3511
3572
|
vpath,
|
@@ -3515,7 +3576,7 @@ class Up2k(object):
|
|
3515
3576
|
stl.st_mtime,
|
3516
3577
|
st.st_size,
|
3517
3578
|
ip,
|
3518
|
-
|
3579
|
+
time.time(),
|
3519
3580
|
"",
|
3520
3581
|
):
|
3521
3582
|
t = "delete blocked by xbd server config: {}"
|
@@ -3540,6 +3601,9 @@ class Up2k(object):
|
|
3540
3601
|
if xad:
|
3541
3602
|
runhook(
|
3542
3603
|
self.log,
|
3604
|
+
None,
|
3605
|
+
self,
|
3606
|
+
"xad",
|
3543
3607
|
xad,
|
3544
3608
|
abspath,
|
3545
3609
|
vpath,
|
@@ -3549,7 +3613,7 @@ class Up2k(object):
|
|
3549
3613
|
stl.st_mtime,
|
3550
3614
|
st.st_size,
|
3551
3615
|
ip,
|
3552
|
-
|
3616
|
+
time.time(),
|
3553
3617
|
"",
|
3554
3618
|
)
|
3555
3619
|
|
@@ -3565,7 +3629,7 @@ class Up2k(object):
|
|
3565
3629
|
|
3566
3630
|
return n_files, ok + ok2, ng + ng2
|
3567
3631
|
|
3568
|
-
def handle_mv(self, uname , svp , dvp ) :
|
3632
|
+
def handle_mv(self, uname , ip , svp , dvp ) :
|
3569
3633
|
if svp == dvp or dvp.startswith(svp + "/"):
|
3570
3634
|
raise Pebkac(400, "mv: cannot move parent into subfolder")
|
3571
3635
|
|
@@ -3582,7 +3646,7 @@ class Up2k(object):
|
|
3582
3646
|
if stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode):
|
3583
3647
|
with self.mutex:
|
3584
3648
|
try:
|
3585
|
-
ret = self._mv_file(uname, svp, dvp, curs)
|
3649
|
+
ret = self._mv_file(uname, ip, svp, dvp, curs)
|
3586
3650
|
finally:
|
3587
3651
|
for v in curs:
|
3588
3652
|
v.connection.commit()
|
@@ -3615,7 +3679,7 @@ class Up2k(object):
|
|
3615
3679
|
raise Pebkac(500, "mv: bug at {}, top {}".format(svpf, svp))
|
3616
3680
|
|
3617
3681
|
dvpf = dvp + svpf[len(svp) :]
|
3618
|
-
self._mv_file(uname, svpf, dvpf, curs)
|
3682
|
+
self._mv_file(uname, ip, svpf, dvpf, curs)
|
3619
3683
|
finally:
|
3620
3684
|
for v in curs:
|
3621
3685
|
v.connection.commit()
|
@@ -3640,7 +3704,7 @@ class Up2k(object):
|
|
3640
3704
|
return "k"
|
3641
3705
|
|
3642
3706
|
def _mv_file(
|
3643
|
-
self, uname , svp , dvp , curs
|
3707
|
+
self, uname , ip , svp , dvp , curs
|
3644
3708
|
) :
|
3645
3709
|
"""mutex(main) me; will mutex(reg)"""
|
3646
3710
|
svn, srem = self.asrv.vfs.get(svp, uname, True, False, True)
|
@@ -3674,21 +3738,27 @@ class Up2k(object):
|
|
3674
3738
|
except:
|
3675
3739
|
pass # broken symlink; keep as-is
|
3676
3740
|
|
3741
|
+
ftime = stl.st_mtime
|
3742
|
+
fsize = st.st_size
|
3743
|
+
|
3677
3744
|
xbr = svn.flags.get("xbr")
|
3678
3745
|
xar = dvn.flags.get("xar")
|
3679
3746
|
if xbr:
|
3680
3747
|
if not runhook(
|
3681
3748
|
self.log,
|
3749
|
+
None,
|
3750
|
+
self,
|
3751
|
+
"xbr",
|
3682
3752
|
xbr,
|
3683
3753
|
sabs,
|
3684
3754
|
svp,
|
3685
3755
|
"",
|
3686
3756
|
uname,
|
3687
3757
|
self.asrv.vfs.get_perms(svp, uname),
|
3688
|
-
|
3689
|
-
|
3690
|
-
|
3691
|
-
|
3758
|
+
ftime,
|
3759
|
+
fsize,
|
3760
|
+
ip,
|
3761
|
+
time.time(),
|
3692
3762
|
"",
|
3693
3763
|
):
|
3694
3764
|
t = "move blocked by xbr server config: {}".format(svp)
|
@@ -3716,16 +3786,19 @@ class Up2k(object):
|
|
3716
3786
|
if xar:
|
3717
3787
|
runhook(
|
3718
3788
|
self.log,
|
3789
|
+
None,
|
3790
|
+
self,
|
3791
|
+
"xar.ln",
|
3719
3792
|
xar,
|
3720
3793
|
dabs,
|
3721
3794
|
dvp,
|
3722
3795
|
"",
|
3723
3796
|
uname,
|
3724
3797
|
self.asrv.vfs.get_perms(dvp, uname),
|
3725
|
-
|
3726
|
-
|
3727
|
-
|
3728
|
-
|
3798
|
+
ftime,
|
3799
|
+
fsize,
|
3800
|
+
ip,
|
3801
|
+
time.time(),
|
3729
3802
|
"",
|
3730
3803
|
)
|
3731
3804
|
|
@@ -3734,13 +3807,6 @@ class Up2k(object):
|
|
3734
3807
|
c1, w, ftime_, fsize_, ip, at = self._find_from_vpath(svn.realpath, srem)
|
3735
3808
|
c2 = self.cur.get(dvn.realpath)
|
3736
3809
|
|
3737
|
-
if ftime_ is None:
|
3738
|
-
ftime = stl.st_mtime
|
3739
|
-
fsize = st.st_size
|
3740
|
-
else:
|
3741
|
-
ftime = ftime_
|
3742
|
-
fsize = fsize_ or 0
|
3743
|
-
|
3744
3810
|
has_dupes = False
|
3745
3811
|
if w:
|
3746
3812
|
assert c1
|
@@ -3748,7 +3814,9 @@ class Up2k(object):
|
|
3748
3814
|
self._copy_tags(c1, c2, w)
|
3749
3815
|
|
3750
3816
|
with self.reg_mutex:
|
3751
|
-
has_dupes = self._forget_file(
|
3817
|
+
has_dupes = self._forget_file(
|
3818
|
+
svn.realpath, srem, c1, w, is_xvol, fsize_ or fsize
|
3819
|
+
)
|
3752
3820
|
|
3753
3821
|
if not is_xvol:
|
3754
3822
|
has_dupes = self._relink(w, svn.realpath, srem, dabs)
|
@@ -3818,7 +3886,7 @@ class Up2k(object):
|
|
3818
3886
|
|
3819
3887
|
if is_link:
|
3820
3888
|
try:
|
3821
|
-
times = (int(time.time()), int(
|
3889
|
+
times = (int(time.time()), int(ftime))
|
3822
3890
|
bos.utime(dabs, times, False)
|
3823
3891
|
except:
|
3824
3892
|
pass
|
@@ -3828,16 +3896,19 @@ class Up2k(object):
|
|
3828
3896
|
if xar:
|
3829
3897
|
runhook(
|
3830
3898
|
self.log,
|
3899
|
+
None,
|
3900
|
+
self,
|
3901
|
+
"xar.mv",
|
3831
3902
|
xar,
|
3832
3903
|
dabs,
|
3833
3904
|
dvp,
|
3834
3905
|
"",
|
3835
3906
|
uname,
|
3836
3907
|
self.asrv.vfs.get_perms(dvp, uname),
|
3837
|
-
|
3838
|
-
|
3839
|
-
|
3840
|
-
|
3908
|
+
ftime,
|
3909
|
+
fsize,
|
3910
|
+
ip,
|
3911
|
+
time.time(),
|
3841
3912
|
"",
|
3842
3913
|
)
|
3843
3914
|
|
@@ -4121,23 +4192,35 @@ class Up2k(object):
|
|
4121
4192
|
xbu = self.flags[job["ptop"]].get("xbu")
|
4122
4193
|
ap_chk = djoin(pdir, job["name"])
|
4123
4194
|
vp_chk = djoin(job["vtop"], job["prel"], job["name"])
|
4124
|
-
if xbu
|
4125
|
-
|
4126
|
-
|
4127
|
-
|
4128
|
-
|
4129
|
-
|
4130
|
-
|
4131
|
-
|
4132
|
-
|
4133
|
-
|
4134
|
-
|
4135
|
-
|
4136
|
-
|
4137
|
-
|
4138
|
-
|
4139
|
-
|
4140
|
-
|
4195
|
+
if xbu:
|
4196
|
+
hr = runhook(
|
4197
|
+
self.log,
|
4198
|
+
None,
|
4199
|
+
self,
|
4200
|
+
"xbu.up2k",
|
4201
|
+
xbu,
|
4202
|
+
ap_chk,
|
4203
|
+
vp_chk,
|
4204
|
+
job["host"],
|
4205
|
+
job["user"],
|
4206
|
+
self.asrv.vfs.get_perms(vp_chk, job["user"]),
|
4207
|
+
job["lmod"],
|
4208
|
+
job["size"],
|
4209
|
+
job["addr"],
|
4210
|
+
job["t0"],
|
4211
|
+
"",
|
4212
|
+
)
|
4213
|
+
if not hr:
|
4214
|
+
t = "upload blocked by xbu server config: {}".format(vp_chk)
|
4215
|
+
self.log(t, 1)
|
4216
|
+
raise Pebkac(403, t)
|
4217
|
+
if hr.get("reloc"):
|
4218
|
+
x = pathmod(self.asrv.vfs, ap_chk, vp_chk, hr["reloc"])
|
4219
|
+
if x:
|
4220
|
+
pdir, _, job["name"], (vfs, rem) = x
|
4221
|
+
job["ptop"] = vfs.realpath
|
4222
|
+
job["vtop"] = vfs.vpath
|
4223
|
+
job["prel"] = rem
|
4141
4224
|
|
4142
4225
|
tnam = job["name"] + ".PARTIAL"
|
4143
4226
|
if self.args.dotpart:
|
@@ -4411,6 +4494,9 @@ class Up2k(object):
|
|
4411
4494
|
with self.rescan_cond:
|
4412
4495
|
self.rescan_cond.notify_all()
|
4413
4496
|
|
4497
|
+
if self.fx_backlog:
|
4498
|
+
self.do_fx_backlog()
|
4499
|
+
|
4414
4500
|
return True
|
4415
4501
|
|
4416
4502
|
def hash_file(
|
@@ -4442,6 +4528,48 @@ class Up2k(object):
|
|
4442
4528
|
self.hashq.put(zt)
|
4443
4529
|
self.n_hashq += 1
|
4444
4530
|
|
4531
|
+
def do_fx_backlog(self):
|
4532
|
+
with self.mutex, self.reg_mutex:
|
4533
|
+
todo = self.fx_backlog
|
4534
|
+
self.fx_backlog = []
|
4535
|
+
for act, hr, req_vp in todo:
|
4536
|
+
self.hook_fx(act, hr, req_vp)
|
4537
|
+
|
4538
|
+
def hook_fx(self, act , hr , req_vp ) :
|
4539
|
+
bad = [k for k in hr if k != "vp"]
|
4540
|
+
if bad:
|
4541
|
+
t = "got unsupported key in %s from hook: %s"
|
4542
|
+
raise Exception(t % (act, bad))
|
4543
|
+
|
4544
|
+
for fvp in hr.get("vp") or []:
|
4545
|
+
# expect vpath including filename; either absolute
|
4546
|
+
# or relative to the client's vpath (request url)
|
4547
|
+
if fvp.startswith("/"):
|
4548
|
+
fvp, fn = vsplit(fvp[1:])
|
4549
|
+
fvp = "/" + fvp
|
4550
|
+
else:
|
4551
|
+
fvp, fn = vsplit(fvp)
|
4552
|
+
|
4553
|
+
x = pathmod(self.asrv.vfs, "", req_vp, {"vp": fvp, "fn": fn})
|
4554
|
+
if not x:
|
4555
|
+
t = "hook_fx(%s): failed to resolve %s based on %s"
|
4556
|
+
self.log(t % (act, fvp, req_vp))
|
4557
|
+
continue
|
4558
|
+
|
4559
|
+
ap, rd, fn, (vn, rem) = x
|
4560
|
+
vp = vjoin(rd, fn)
|
4561
|
+
if not vp:
|
4562
|
+
raise Exception("hook_fx: blank vp from pathmod")
|
4563
|
+
|
4564
|
+
if act == "idx":
|
4565
|
+
rd = rd[len(vn.vpath) :].strip("/")
|
4566
|
+
self.hash_file(
|
4567
|
+
vn.realpath, vn.vpath, vn.flags, rd, fn, "", time.time(), "", True
|
4568
|
+
)
|
4569
|
+
|
4570
|
+
if act == "del":
|
4571
|
+
self._handle_rm(LEELOO_DALLAS, "", vp, [], False, False)
|
4572
|
+
|
4445
4573
|
def shutdown(self) :
|
4446
4574
|
self.stop = True
|
4447
4575
|
|