mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 09:02:15 -06:00
hook/reloc: fix up2k jank
* wark landed in the wrong registry when moved to another volume (harmless; upload would succeed on the next handshake) * dedup did not apply correctly when moved into another volume, since all the checks were done based on the previous vol; fix this by recursing the whole thing also update the reloc example after some real-world experience Reported-by: @daniiooo
This commit is contained in:
parent
00da74400c
commit
c8f4aeaefa
|
@ -2,11 +2,12 @@
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
_ = r"""
|
_ = r"""
|
||||||
relocate/redirect incoming uploads according to file extension
|
relocate/redirect incoming uploads according to file extension or name
|
||||||
|
|
||||||
example usage as global config:
|
example usage as global config:
|
||||||
--xbu j,c1,bin/hooks/reloc-by-ext.py
|
--xbu j,c1,bin/hooks/reloc-by-ext.py
|
||||||
|
@ -52,11 +53,19 @@ def main():
|
||||||
try:
|
try:
|
||||||
fn, ext = fn.rsplit(".", 1)
|
fn, ext = fn.rsplit(".", 1)
|
||||||
except:
|
except:
|
||||||
# no file extension; abort
|
# no file extension; pretend it's "bin"
|
||||||
return
|
ext = "bin"
|
||||||
|
|
||||||
ext = ext.lower()
|
ext = ext.lower()
|
||||||
|
|
||||||
|
# this function must end by printing the action to perform;
|
||||||
|
# that's handled by the print(json.dumps(... at the bottom
|
||||||
|
#
|
||||||
|
# the action can contain the following keys:
|
||||||
|
# "vp" is the folder URL to move the upload to,
|
||||||
|
# "ap" is the filesystem-path to move it to (but "vp" is safer),
|
||||||
|
# "fn" overrides the final filename to use
|
||||||
|
|
||||||
##
|
##
|
||||||
## some example actions to take; pick one by
|
## some example actions to take; pick one by
|
||||||
## selecting it inside the print at the end:
|
## selecting it inside the print at the end:
|
||||||
|
@ -80,11 +89,37 @@ def main():
|
||||||
elif ext in MUSIC.split():
|
elif ext in MUSIC.split():
|
||||||
by_category = {"vp": "/just/tunes"}
|
by_category = {"vp": "/just/tunes"}
|
||||||
else:
|
else:
|
||||||
by_category = {}
|
by_category = {} # no action
|
||||||
|
|
||||||
# now choose the effect to apply; can be any of these:
|
# now choose the default effect to apply; can be any of these:
|
||||||
# into_subfolder into_toplevel into_sibling by_category
|
# into_subfolder into_toplevel into_sibling by_category
|
||||||
effect = into_subfolder
|
effect = {"vp": "/junk"}
|
||||||
|
|
||||||
|
##
|
||||||
|
## but we can keep going, adding more speicifc rules
|
||||||
|
## which can take precedence, replacing the fallback
|
||||||
|
## effect we just specified:
|
||||||
|
##
|
||||||
|
|
||||||
|
fn = fn.lower() # lowercase filename to make this easier
|
||||||
|
|
||||||
|
if "screenshot" in fn:
|
||||||
|
effect = {"vp": "/ss"}
|
||||||
|
if "mpv_" in fn:
|
||||||
|
effect = {"vp": "/anishots"}
|
||||||
|
elif "debian" in fn or "biebian" in fn:
|
||||||
|
effect = {"vp": "/linux-ISOs"}
|
||||||
|
elif re.search(r"ep(isode |\.)?[0-9]", fn):
|
||||||
|
effect = {"vp": "/podcasts"}
|
||||||
|
|
||||||
|
# regex lets you grab a part of the matching
|
||||||
|
# text and use that in the upload path:
|
||||||
|
m = re.search(r"\b(op|ed)([^a-z]|$)", fn)
|
||||||
|
if m:
|
||||||
|
# the regex matched; use "anime-op" or "anime-ed"
|
||||||
|
effect = {"vp": "/anime-" + m[1]}
|
||||||
|
|
||||||
|
# aaand DO IT
|
||||||
print(json.dumps({"reloc": effect}))
|
print(json.dumps({"reloc": effect}))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2564,7 +2564,10 @@ class Up2k(object):
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def _handle_json(self, cj: dict[str, Any]) -> dict[str, Any]:
|
def _handle_json(self, cj: dict[str, Any], depth: int = 1) -> dict[str, Any]:
|
||||||
|
if depth > 16:
|
||||||
|
raise Pebkac(500, "too many xbu relocs, giving up")
|
||||||
|
|
||||||
ptop = cj["ptop"]
|
ptop = cj["ptop"]
|
||||||
if not self.register_vpath(ptop, cj["vcfg"]):
|
if not self.register_vpath(ptop, cj["vcfg"]):
|
||||||
if ptop not in self.registry:
|
if ptop not in self.registry:
|
||||||
|
@ -2794,12 +2797,16 @@ class Up2k(object):
|
||||||
if hr.get("reloc"):
|
if hr.get("reloc"):
|
||||||
x = pathmod(self.asrv.vfs, dst, vp, hr["reloc"])
|
x = pathmod(self.asrv.vfs, dst, vp, hr["reloc"])
|
||||||
if x:
|
if x:
|
||||||
|
zvfs = vfs
|
||||||
pdir, _, job["name"], (vfs, rem) = x
|
pdir, _, job["name"], (vfs, rem) = x
|
||||||
dst = os.path.join(pdir, job["name"])
|
dst = os.path.join(pdir, job["name"])
|
||||||
|
job["vcfg"] = vfs.flags
|
||||||
job["ptop"] = vfs.realpath
|
job["ptop"] = vfs.realpath
|
||||||
job["vtop"] = vfs.vpath
|
job["vtop"] = vfs.vpath
|
||||||
job["prel"] = rem
|
job["prel"] = rem
|
||||||
bos.makedirs(pdir)
|
if zvfs.vpath != vfs.vpath:
|
||||||
|
self.log("xbu reloc %d..." % (depth,), 6)
|
||||||
|
return self._handle_json(job, depth + 1)
|
||||||
|
|
||||||
job["name"] = self._untaken(pdir, job, now)
|
job["name"] = self._untaken(pdir, job, now)
|
||||||
|
|
||||||
|
@ -2880,7 +2887,9 @@ class Up2k(object):
|
||||||
lut.add(k)
|
lut.add(k)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._new_upload(job)
|
ret = self._new_upload(job, vfs, depth)
|
||||||
|
if ret:
|
||||||
|
return ret # xbu recursed
|
||||||
except:
|
except:
|
||||||
self.registry[job["ptop"]].pop(job["wark"], None)
|
self.registry[job["ptop"]].pop(job["wark"], None)
|
||||||
raise
|
raise
|
||||||
|
@ -4176,22 +4185,17 @@ class Up2k(object):
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def _new_upload(self, job: dict[str, Any]) -> None:
|
def _new_upload(self, job: dict[str, Any], vfs: VFS, depth: int) -> dict[str, str]:
|
||||||
pdir = djoin(job["ptop"], job["prel"])
|
pdir = djoin(job["ptop"], job["prel"])
|
||||||
if not job["size"]:
|
if not job["size"]:
|
||||||
try:
|
try:
|
||||||
inf = bos.stat(djoin(pdir, job["name"]))
|
inf = bos.stat(djoin(pdir, job["name"]))
|
||||||
if stat.S_ISREG(inf.st_mode):
|
if stat.S_ISREG(inf.st_mode):
|
||||||
job["lmod"] = inf.st_size
|
job["lmod"] = inf.st_size
|
||||||
return
|
return {}
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
self.registry[job["ptop"]][job["wark"]] = job
|
|
||||||
job["name"] = self._untaken(pdir, job, job["t0"])
|
|
||||||
# if len(job["name"].split(".")) > 8:
|
|
||||||
# raise Exception("aaa")
|
|
||||||
|
|
||||||
xbu = self.flags[job["ptop"]].get("xbu")
|
xbu = self.flags[job["ptop"]].get("xbu")
|
||||||
ap_chk = djoin(pdir, job["name"])
|
ap_chk = djoin(pdir, job["name"])
|
||||||
vp_chk = djoin(job["vtop"], job["prel"], job["name"])
|
vp_chk = djoin(job["vtop"], job["prel"], job["name"])
|
||||||
|
@ -4220,10 +4224,18 @@ class Up2k(object):
|
||||||
if hr.get("reloc"):
|
if hr.get("reloc"):
|
||||||
x = pathmod(self.asrv.vfs, ap_chk, vp_chk, hr["reloc"])
|
x = pathmod(self.asrv.vfs, ap_chk, vp_chk, hr["reloc"])
|
||||||
if x:
|
if x:
|
||||||
|
zvfs = vfs
|
||||||
pdir, _, job["name"], (vfs, rem) = x
|
pdir, _, job["name"], (vfs, rem) = x
|
||||||
|
job["vcfg"] = vfs.flags
|
||||||
job["ptop"] = vfs.realpath
|
job["ptop"] = vfs.realpath
|
||||||
job["vtop"] = vfs.vpath
|
job["vtop"] = vfs.vpath
|
||||||
job["prel"] = rem
|
job["prel"] = rem
|
||||||
|
if zvfs.vpath != vfs.vpath:
|
||||||
|
self.log("xbu reloc %d..." % (depth,), 6)
|
||||||
|
return self._handle_json(job, depth + 1)
|
||||||
|
|
||||||
|
job["name"] = self._untaken(pdir, job, job["t0"])
|
||||||
|
self.registry[job["ptop"]][job["wark"]] = job
|
||||||
|
|
||||||
tnam = job["name"] + ".PARTIAL"
|
tnam = job["name"] + ".PARTIAL"
|
||||||
if self.args.dotpart:
|
if self.args.dotpart:
|
||||||
|
@ -4233,7 +4245,7 @@ class Up2k(object):
|
||||||
job["tnam"] = tnam
|
job["tnam"] = tnam
|
||||||
if not job["hash"]:
|
if not job["hash"]:
|
||||||
del self.registry[job["ptop"]][job["wark"]]
|
del self.registry[job["ptop"]][job["wark"]]
|
||||||
return
|
return {}
|
||||||
|
|
||||||
if self.args.plain_ip:
|
if self.args.plain_ip:
|
||||||
dip = job["addr"].replace(":", ".")
|
dip = job["addr"].replace(":", ".")
|
||||||
|
@ -4293,6 +4305,8 @@ class Up2k(object):
|
||||||
if not job["hash"]:
|
if not job["hash"]:
|
||||||
self._finish_upload(job["ptop"], job["wark"])
|
self._finish_upload(job["ptop"], job["wark"])
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
def _snapshot(self) -> None:
|
def _snapshot(self) -> None:
|
||||||
slp = self.args.snap_wri
|
slp = self.args.snap_wri
|
||||||
if not slp or self.args.no_snap:
|
if not slp or self.args.no_snap:
|
||||||
|
|
Loading…
Reference in a new issue