windows: fix download-as-zip;

zipfiles generated on windows were flattened
(slash was substituted with fullwidth)
This commit is contained in:
ed 2025-12-23 10:52:50 +00:00
parent c82a3cb226
commit 2d1d295a4d
5 changed files with 27 additions and 25 deletions

View file

@ -174,7 +174,7 @@ class FtpFs(AbstractedFS):
t = "Unsupported characters in [{}]" t = "Unsupported characters in [{}]"
raise FSE(t.format(vpath), 1) raise FSE(t.format(vpath), 1)
fn = sanitize_fn(fn or "", "") fn = sanitize_fn(fn or "")
vpath = vjoin(rd, fn) vpath = vjoin(rd, fn)
vfs, rem = self.hub.asrv.vfs.get(vpath, self.uname, r, w, m, d) vfs, rem = self.hub.asrv.vfs.get(vpath, self.uname, r, w, m, d)
if ( if (

View file

@ -2419,7 +2419,7 @@ class HttpCli(object):
if rnd: if rnd:
fn = rand_name(fdir, fn, rnd) fn = rand_name(fdir, fn, rnd)
fn = sanitize_fn(fn or "", "") fn = sanitize_fn(fn or "")
path = os.path.join(fdir, fn) path = os.path.join(fdir, fn)
@ -2857,7 +2857,7 @@ class HttpCli(object):
name = name.translate(tl) name = name.translate(tl)
dbv, vrem = vfs.get_dbv(rem) dbv, vrem = vfs.get_dbv(rem)
name = sanitize_fn(name, "") name = sanitize_fn(name)
if ( if (
not self.can_read not self.can_read
and self.can_write and self.can_write
@ -3353,7 +3353,7 @@ class HttpCli(object):
if "nosub" in vfs.flags: if "nosub" in vfs.flags:
raise Pebkac(403, "mkdir is forbidden below this folder") raise Pebkac(403, "mkdir is forbidden below this folder")
rem = sanitize_vpath(rem, "/") rem = sanitize_vpath(rem)
fn = vfs.canonical(rem) fn = vfs.canonical(rem)
if not nullwrite: if not nullwrite:
@ -3397,7 +3397,7 @@ class HttpCli(object):
t = "you can only create .md files because you don't have the delete-permission" t = "you can only create .md files because you don't have the delete-permission"
raise Pebkac(400, t) raise Pebkac(400, t)
sanitized = sanitize_fn(new_file, "") sanitized = sanitize_fn(new_file)
fdir = vfs.canonical(rem) fdir = vfs.canonical(rem)
fn = os.path.join(fdir, sanitized) fn = os.path.join(fdir, sanitized)
@ -3549,7 +3549,7 @@ class HttpCli(object):
# fallthrough # fallthrough
fdir = fdir_base fdir = fdir_base
fname = sanitize_fn(p_file or "", "") fname = sanitize_fn(p_file or "")
abspath = os.path.join(fdir, fname) abspath = os.path.join(fdir, fname)
suffix = "-%.6f-%s" % (time.time(), dip) suffix = "-%.6f-%s" % (time.time(), dip)
if p_file and not nullwrite: if p_file and not nullwrite:

View file

@ -8,7 +8,7 @@ import time
from .authsrv import AuthSrv from .authsrv import AuthSrv
from .bos import bos from .bos import bos
from .sutil import StreamArc, errdesc from .sutil import StreamArc, errdesc
from .util import min_ex, sanitize_fn, spack, sunpack, yieldfile, zlib from .util import VPTL_WIN, min_ex, sanitize_to, spack, sunpack, yieldfile, zlib
if True: # pylint: disable=using-constant-test if True: # pylint: disable=using-constant-test
from typing import Any, Generator, Optional from typing import Any, Generator, Optional
@ -104,7 +104,7 @@ def gen_hdr(
ret += spack(b"<LL", vsz, vsz) ret += spack(b"<LL", vsz, vsz)
# windows support (the "?" replace below too) # windows support (the "?" replace below too)
fn = sanitize_fn(fn, "/") fn = sanitize_to(fn, VPTL_WIN)
bfn = fn.encode("utf-8" if utf8 else "cp437", "replace").replace(b"?", b"_") bfn = fn.encode("utf-8" if utf8 else "cp437", "replace").replace(b"?", b"_")
# add ntfs (0x24) and/or unix (0x10) extrafields for utc, add z64 if requested # add ntfs (0x24) and/or unix (0x10) extrafields for utc, add z64 if requested

View file

@ -3323,7 +3323,7 @@ class Up2k(object):
job["ptop"] = vfs.realpath job["ptop"] = vfs.realpath
job["vtop"] = vfs.vpath job["vtop"] = vfs.vpath
job["prel"] = rem job["prel"] = rem
job["name"] = sanitize_fn(job["name"], "") job["name"] = sanitize_fn(job["name"])
ud2 = (vfs.vpath, job["prel"], job["name"]) ud2 = (vfs.vpath, job["prel"], job["name"])
if ud1 != ud2: if ud1 != ud2:
# print(json.dumps(job, sort_keys=True, indent=4)) # print(json.dumps(job, sort_keys=True, indent=4))
@ -5186,7 +5186,7 @@ class Up2k(object):
job["ptop"] = vfs.realpath job["ptop"] = vfs.realpath
job["vtop"] = vfs.vpath job["vtop"] = vfs.vpath
job["prel"] = rem job["prel"] = rem
job["name"] = sanitize_fn(job["name"], "") job["name"] = sanitize_fn(job["name"])
ud2 = (vfs.vpath, job["prel"], job["name"]) ud2 = (vfs.vpath, job["prel"], job["name"])
if ud1 != ud2: if ud1 != ud2:
self.log("xbu reloc2:%d..." % (depth,), 6) self.log("xbu reloc2:%d..." % (depth,), 6)

View file

@ -2245,12 +2245,15 @@ def undot(path: str) -> str:
return "/".join(ret) return "/".join(ret)
def sanitize_fn(fn: str, ok: str) -> str: def sanitize_fn(fn: str) -> str:
if "/" not in ok:
fn = fn.replace("\\", "/").split("/")[-1] fn = fn.replace("\\", "/").split("/")[-1]
if APTL_OS: if APTL_OS:
fn = fn.translate(APTL_OS) fn = sanitize_to(fn, APTL_OS)
return fn.strip()
def sanitize_to(fn: str, tl: dict[int, int]) -> str:
fn = fn.translate(tl)
if ANYWIN: if ANYWIN:
bad = ["con", "prn", "aux", "nul"] bad = ["con", "prn", "aux", "nul"]
for n in range(1, 10): for n in range(1, 10):
@ -2258,15 +2261,14 @@ def sanitize_fn(fn: str, ok: str) -> str:
if fn.lower().split(".")[0] in bad: if fn.lower().split(".")[0] in bad:
fn = "_" + fn fn = "_" + fn
return fn
return fn.strip()
def sanitize_vpath(vp: str, ok: str) -> str: def sanitize_vpath(vp: str) -> str:
if not FNTL_OS: if not FNTL_OS:
return vp return vp
parts = vp.replace(os.sep, "/").split("/") parts = vp.replace(os.sep, "/").split("/")
ret = [sanitize_fn(x, ok) for x in parts] ret = [sanitize_to(x, APTL_OS) for x in parts]
return "/".join(ret) return "/".join(ret)