volflag to randomize all upload filenames

This commit is contained in:
ed 2023-02-01 21:58:01 +00:00
parent 39399934ee
commit 1e20eafbe0
5 changed files with 72 additions and 39 deletions

View file

@ -510,6 +510,8 @@ def get_sects():
\033[0mupload rules:
\033[36mmaxn=250,600\033[35m max 250 uploads over 15min
\033[36mmaxb=1g,300\033[35m max 1 GiB over 5min (suffixes: b, k, m, g)
\033[36mrand\033[35m force randomized filenames, 9 chars long by default
\033[36mnrand=N\033[35m randomized filenames are N chars long
\033[36msz=1k-3m\033[35m allow filesizes between 1 KiB and 3MiB
\033[36mdf=1g\033[35m ensure 1 GiB free disk space
@ -712,6 +714,8 @@ def add_upload(ap):
ap2.add_argument("--no-dedup", action="store_true", help="disable symlink/hardlink creation; copy file contents instead (volflag=copydupes")
ap2.add_argument("--no-dupe", action="store_true", help="reject duplicate files during upload; only matches within the same volume (volflag=nodupe)")
ap2.add_argument("--no-snap", action="store_true", help="disable snapshots -- forget unfinished uploads on shutdown; don't create .hist/up2k.snap files -- abandoned/interrupted uploads must be cleaned up manually")
ap2.add_argument("--rand", action="store_true", help="force randomized filenames, --nrand chars long (volflag=rand)")
ap2.add_argument("--nrand", metavar="NUM", type=int, default=9, help="randomized filenames length (volflag=nrand)")
ap2.add_argument("--magic", action="store_true", help="enable filetype detection on nameless uploads (volflag=magic)")
ap2.add_argument("--df", metavar="GiB", type=float, default=0, help="ensure GiB free disk space by rejecting upload requests")
ap2.add_argument("--sparse", metavar="MiB", type=int, default=4, help="windows-only: minimum size of incoming uploads through up2k before they are made into sparse files")

View file

@ -1114,40 +1114,58 @@ class AuthSrv(object):
if ptn:
vol.flags[vf] = re.compile(ptn)
for k in ["e2t", "e2ts", "e2tsr", "e2v", "e2vu", "e2vp", "xdev", "xvol"]:
for k in (
"dotsrch",
"e2t",
"e2ts",
"e2tsr",
"e2v",
"e2vu",
"e2vp",
"hardlink",
"magic",
"no_sb_md",
"no_sb_lg",
"rand",
"xdev",
"xlink",
"xvol",
):
if getattr(self.args, k):
vol.flags[k] = True
for ga, vf in (
("no_sb_md", "no_sb_md"),
("no_sb_lg", "no_sb_lg"),
("no_forget", "noforget"),
("no_dupe", "nodupe"),
("hardlink", "hardlink"),
("never_symlink", "neversymlink"),
("no_dedup", "copydupes"),
("magic", "magic"),
("xlink", "xlink"),
("dotsrch", "dotsrch"),
("no_dupe", "nodupe"),
("no_forget", "noforget"),
):
if getattr(self.args, ga):
vol.flags[vf] = True
for ve, vd in (
("sb_md", "no_sb_md"),
("sb_lg", "no_sb_lg"),
("nodotsrch", "dotsrch"),
("sb_lg", "no_sb_lg"),
("sb_md", "no_sb_md"),
):
if ve in vol.flags:
vol.flags.pop(vd, None)
for ga, vf in (
("md_sbf", "md_sbf"),
("lg_sbf", "lg_sbf"),
("md_sbf", "md_sbf"),
):
if vf not in vol.flags:
vol.flags[vf] = getattr(self.args, ga)
for k in ("nrand",):
if k not in vol.flags:
vol.flags[k] = getattr(self.args, k)
for k in ("nrand",):
if k in vol.flags:
vol.flags[k] = int(vol.flags[k])
for k1, k2 in IMPLICATIONS:
if k1 in vol.flags:
vol.flags[k2] = True

View file

@ -58,6 +58,7 @@ from .util import (
ipnorm,
min_ex,
quotep,
rand_name,
read_header,
read_socket,
read_socket_chunked,
@ -1395,7 +1396,7 @@ class HttpCli(object):
if not self.args.nw:
if rnd:
fn = self.rand_name(fdir, fn, rnd)
fn = rand_name(fdir, fn, rnd)
fn = sanitize_fn(fn or "", "", [".prologue.html", ".epilogue.html"])
@ -1465,7 +1466,7 @@ class HttpCli(object):
if ext:
if rnd:
fn2 = self.rand_name(fdir, "a." + ext, rnd)
fn2 = rand_name(fdir, "a." + ext, rnd)
else:
fn2 = fn.rsplit(".", 1)[0] + "." + ext
@ -1577,27 +1578,6 @@ class HttpCli(object):
else:
self.log("bakflip ok", 2)
def rand_name(self, fdir: str, fn: str, rnd: int) -> str:
ok = False
try:
ext = "." + fn.rsplit(".", 1)[1]
except:
ext = ""
for extra in range(16):
for _ in range(16):
if ok:
break
nc = rnd + extra
nb = int((6 + 6 * nc) / 8)
zb = os.urandom(nb)
zb = base64.urlsafe_b64encode(zb)
fn = zb[:nc].decode("utf-8") + ext
ok = not bos.path.exists(os.path.join(fdir, fn))
return fn
def _spd(self, nbytes: int, add: bool = True) -> str:
if add:
self.conn.nbyte += nbytes
@ -2026,8 +2006,13 @@ class HttpCli(object):
return True
def upload_flags(self, vfs: VFS) -> tuple[int, bool, int, list[str], list[str]]:
srnd = self.uparam.get("rand", self.headers.get("rand", ""))
rnd = int(srnd) if srnd and not self.args.nw else 0
if self.args.nw:
rnd = 0
else:
rnd = int(self.uparam.get("rand") or self.headers.get("rand") or 0)
if vfs.flags.get("rand"): # force-enable
rnd = max(rnd, vfs.flags["nrand"])
ac = self.uparam.get(
"want", self.headers.get("accept", "").lower().split(";")[-1]
)
@ -2082,7 +2067,7 @@ class HttpCli(object):
)
if p_file and not nullwrite:
if rnd:
fname = self.rand_name(fdir, fname, rnd)
fname = rand_name(fdir, fname, rnd)
if not bos.path.isdir(fdir):
raise Pebkac(404, "that folder does not exist")

View file

@ -41,6 +41,7 @@ from .util import (
hidedir,
min_ex,
quotep,
rand_name,
ren_open,
rmdirs,
rmdirs_up,
@ -2184,8 +2185,11 @@ class Up2k(object):
cur.connection.commit()
if not job:
ap1 = djoin(cj["ptop"], cj["prel"])
if vfs.flags.get("rand") or cj.get("rand"):
cj["name"] = rand_name(ap1, cj["name"], vfs.flags["nrand"])
if vfs.lim:
ap1 = djoin(cj["ptop"], cj["prel"])
ap2, cj["prel"] = vfs.lim.all(
cj["addr"], cj["prel"], cj["size"], ap1, reg
)

View file

@ -1505,6 +1505,28 @@ def read_header(sr: Unrecv) -> list[str]:
return ret[:ofs].decode("utf-8", "surrogateescape").lstrip("\r\n").split("\r\n")
def rand_name(fdir: str, fn: str, rnd: int) -> str:
ok = False
try:
ext = "." + fn.rsplit(".", 1)[1]
except:
ext = ""
for extra in range(16):
for _ in range(16):
if ok:
break
nc = rnd + extra
nb = int((6 + 6 * nc) / 8)
zb = os.urandom(nb)
zb = base64.urlsafe_b64encode(zb)
fn = zb[:nc].decode("utf-8") + ext
ok = not os.path.exists(fsenc(os.path.join(fdir, fn)))
return fn
def gen_filekey(salt: str, fspath: str, fsize: int, inode: int) -> str:
return base64.urlsafe_b64encode(
hashlib.sha512(