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 os
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
_ = r"""
|
||||
relocate/redirect incoming uploads according to file extension
|
||||
relocate/redirect incoming uploads according to file extension or name
|
||||
|
||||
example usage as global config:
|
||||
--xbu j,c1,bin/hooks/reloc-by-ext.py
|
||||
|
@ -52,11 +53,19 @@ def main():
|
|||
try:
|
||||
fn, ext = fn.rsplit(".", 1)
|
||||
except:
|
||||
# no file extension; abort
|
||||
return
|
||||
# no file extension; pretend it's "bin"
|
||||
ext = "bin"
|
||||
|
||||
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
|
||||
## selecting it inside the print at the end:
|
||||
|
@ -80,11 +89,37 @@ def main():
|
|||
elif ext in MUSIC.split():
|
||||
by_category = {"vp": "/just/tunes"}
|
||||
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
|
||||
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}))
|
||||
|
||||
|
||||
|
|
|
@ -2564,7 +2564,10 @@ class Up2k(object):
|
|||
|
||||
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"]
|
||||
if not self.register_vpath(ptop, cj["vcfg"]):
|
||||
if ptop not in self.registry:
|
||||
|
@ -2794,12 +2797,16 @@ class Up2k(object):
|
|||
if hr.get("reloc"):
|
||||
x = pathmod(self.asrv.vfs, dst, vp, hr["reloc"])
|
||||
if x:
|
||||
zvfs = vfs
|
||||
pdir, _, job["name"], (vfs, rem) = x
|
||||
dst = os.path.join(pdir, job["name"])
|
||||
job["vcfg"] = vfs.flags
|
||||
job["ptop"] = vfs.realpath
|
||||
job["vtop"] = vfs.vpath
|
||||
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)
|
||||
|
||||
|
@ -2880,7 +2887,9 @@ class Up2k(object):
|
|||
lut.add(k)
|
||||
|
||||
try:
|
||||
self._new_upload(job)
|
||||
ret = self._new_upload(job, vfs, depth)
|
||||
if ret:
|
||||
return ret # xbu recursed
|
||||
except:
|
||||
self.registry[job["ptop"]].pop(job["wark"], None)
|
||||
raise
|
||||
|
@ -4176,22 +4185,17 @@ class Up2k(object):
|
|||
|
||||
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"])
|
||||
if not job["size"]:
|
||||
try:
|
||||
inf = bos.stat(djoin(pdir, job["name"]))
|
||||
if stat.S_ISREG(inf.st_mode):
|
||||
job["lmod"] = inf.st_size
|
||||
return
|
||||
return {}
|
||||
except:
|
||||
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")
|
||||
ap_chk = djoin(pdir, job["name"])
|
||||
vp_chk = djoin(job["vtop"], job["prel"], job["name"])
|
||||
|
@ -4220,10 +4224,18 @@ class Up2k(object):
|
|||
if hr.get("reloc"):
|
||||
x = pathmod(self.asrv.vfs, ap_chk, vp_chk, hr["reloc"])
|
||||
if x:
|
||||
zvfs = vfs
|
||||
pdir, _, job["name"], (vfs, rem) = x
|
||||
job["vcfg"] = vfs.flags
|
||||
job["ptop"] = vfs.realpath
|
||||
job["vtop"] = vfs.vpath
|
||||
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"
|
||||
if self.args.dotpart:
|
||||
|
@ -4233,7 +4245,7 @@ class Up2k(object):
|
|||
job["tnam"] = tnam
|
||||
if not job["hash"]:
|
||||
del self.registry[job["ptop"]][job["wark"]]
|
||||
return
|
||||
return {}
|
||||
|
||||
if self.args.plain_ip:
|
||||
dip = job["addr"].replace(":", ".")
|
||||
|
@ -4293,6 +4305,8 @@ class Up2k(object):
|
|||
if not job["hash"]:
|
||||
self._finish_upload(job["ptop"], job["wark"])
|
||||
|
||||
return {}
|
||||
|
||||
def _snapshot(self) -> None:
|
||||
slp = self.args.snap_wri
|
||||
if not slp or self.args.no_snap:
|
||||
|
|
Loading…
Reference in a new issue