From 9921c43e3a9ea5d0d45e823e028c78a25669d8e9 Mon Sep 17 00:00:00 2001 From: ed Date: Mon, 21 Jul 2025 22:46:28 +0000 Subject: [PATCH] add options to set default chmod (#181) the unix-permissions of new files/folders can now be changed * global-option --chmod-f, volflag chmod_f for files * global-option --chmod-d, volflag chmod_d for directories the expected value is a standard three-digit octal value (User/Group/Other) such as 755, 750, 644, 640, etc --- copyparty/__main__.py | 39 +++++++++++++++++++++++++++++++++++ copyparty/authsrv.py | 32 +++++++++++++++++++++++++++-- copyparty/bos/bos.py | 19 +++++++++++------ copyparty/cfg.py | 4 ++++ copyparty/ftpd.py | 13 ++++++++---- copyparty/httpcli.py | 35 ++++++++++++++++++++++---------- copyparty/smbd.py | 4 ++-- copyparty/svchub.py | 6 +++++- copyparty/tftpd.py | 8 ++++++-- copyparty/th_srv.py | 3 ++- copyparty/up2k.py | 47 +++++++++++++++++++++++++++++++++---------- copyparty/util.py | 6 ++++++ scripts/help2html.py | 2 +- scripts/help2txt.sh | 2 +- tests/util.py | 3 ++- 15 files changed, 180 insertions(+), 43 deletions(-) diff --git a/copyparty/__main__.py b/copyparty/__main__.py index df491c67..fd25c7b8 100644 --- a/copyparty/__main__.py +++ b/copyparty/__main__.py @@ -863,6 +863,43 @@ def get_sects(): """ ), ], + [ + "chmod", + "file/folder permissions", + dedent( + """ + global-option \033[33m--chmod-f\033[0m and volflag \033[33mchmod_f\033[0m specifies the unix-permission to use when creating a new file + + similarly, \033[33m--chmod-d\033[0m and \033[33mchmod_d\033[0m sets the directory/folder perm + + the value is a three-digit octal number such as 755, 750, 644, etc. + + first digit = "User"; permission for the unix-user + second digit = "Group"; permission for the unix-group + third digit = "Other"; permission for all other users/groups + + for files: + 0 = --- = no access + 1 = --x = can execute the file as a program + 2 = -w- = can write + 3 = -wx = can write and execute + 4 = r-- = can read + 5 = r-x = can read and execute + 6 = rw- = can read and write + 7 = rwx = can read, write, execute + + for directories/folders: + 0 = --- = no access + 1 = --x = can read files in folder but not list contents + 2 = -w- = n/a + 3 = -wx = can create files but not list + 4 = r-- = can list, but not read/write + 5 = r-x = can list and read files + 6 = rw- = n/a + 7 = rwx = can read, write, list + """ + ), + ], [ "pwhash", "password hashing", @@ -1013,6 +1050,8 @@ def add_upload(ap): ap2.add_argument("--reg-cap", metavar="N", type=int, default=38400, help="max number of uploads to keep in memory when running without \033[33m-e2d\033[0m; roughly 1 MiB RAM per 600") ap2.add_argument("--no-fpool", action="store_true", help="disable file-handle pooling -- instead, repeatedly close and reopen files during upload (bad idea to enable this on windows and/or cow filesystems)") ap2.add_argument("--use-fpool", action="store_true", help="force file-handle pooling, even when it might be dangerous (multiprocessing, filesystems lacking sparse-files support, ...)") + ap2.add_argument("--chmod-f", metavar="UGO", type=u, default="", help="unix file permissions to use when creating files; default is probably 644 (OS-decided), see --help-chmod. Examples: [\033[32m644\033[0m] = owner-RW + all-R, [\033[32m755\033[0m] = owner-RWX + all-RX, [\033[32m777\033[0m] = full-yolo (volflag=chmod_f)") + ap2.add_argument("--chmod-d", metavar="UGO", type=u, default="755", help="unix file permissions to use when creating directories; see --help-chmod. Examples: [\033[32m755\033[0m] = owner-RW + all-R, [\033[32m777\033[0m] = full-yolo (volflag=chmod_d)") ap2.add_argument("--dedup", action="store_true", help="enable symlink-based upload deduplication (volflag=dedup)") ap2.add_argument("--safe-dedup", metavar="N", type=int, default=50, help="how careful to be when deduplicating files; [\033[32m1\033[0m] = just verify the filesize, [\033[32m50\033[0m] = verify file contents have not been altered (volflag=safededup)") ap2.add_argument("--hardlink", action="store_true", help="enable hardlink-based dedup; will fallback on symlinks when that is impossible (across filesystems) (volflag=hardlink)") diff --git a/copyparty/authsrv.py b/copyparty/authsrv.py index 1468df26..a1d49bcf 100644 --- a/copyparty/authsrv.py +++ b/copyparty/authsrv.py @@ -120,6 +120,8 @@ class Lim(object): self.reg: Optional[dict[str, dict[str, Any]]] = None # up2k registry + self.chmod_d = 0o755 + self.nups: dict[str, list[float]] = {} # num tracker self.bups: dict[str, list[tuple[float, int]]] = {} # byte tracker list self.bupc: dict[str, int] = {} # byte tracker cache @@ -280,7 +282,7 @@ class Lim(object): if not dirs: # no branches yet; make one sub = os.path.join(path, "0") - bos.mkdir(sub) + bos.mkdir(sub, self.chmod_d) else: # try newest branch only sub = os.path.join(path, str(dirs[-1])) @@ -295,7 +297,7 @@ class Lim(object): # make a branch sub = os.path.join(path, str(dirs[-1] + 1)) - bos.mkdir(sub) + bos.mkdir(sub, self.chmod_d) ret = self.dive(sub, lvs - 1) if ret is None: raise Pebkac(500, "rotation bug") @@ -2074,6 +2076,7 @@ class AuthSrv(object): all_mte = {} errors = False + free_umask = False for vol in vfs.all_nodes.values(): if (self.args.e2ds and vol.axs.uwrite) or self.args.e2dsa: vol.flags["e2ds"] = True @@ -2130,6 +2133,27 @@ class AuthSrv(object): t = 'volume "/%s" has invalid %stry [%s]' raise Exception(t % (vol.vpath, k, vol.flags.get(k + "try"))) + for k in ("chmod_d", "chmod_f"): + is_d = k == "chmod_d" + zs = vol.flags.get(k, "") + if not zs and is_d: + zs = "755" + if not zs: + vol.flags.pop(k, None) + continue + if not re.match("^[0-7]{3}$", zs): + t = "config-option '%s' must be a three-digit octal value such as [755] or [644] but the value was [%s]" + t = t % (k, zs) + self.log(t, 1) + raise Exception(t) + zi = int(zs, 8) + vol.flags[k] = zi + if (is_d and zi != 0o755) or not is_d: + free_umask = True + + if vol.lim: + vol.lim.chmod_d = vol.flags["chmod_d"] + if vol.flags.get("og"): self.args.uqe = True @@ -2359,6 +2383,10 @@ class AuthSrv(object): if errors: sys.exit(1) + setattr(self.args, "free_umask", free_umask) + if free_umask: + os.umask(0) + vfs.bubble_flags() have_e2d = False diff --git a/copyparty/bos/bos.py b/copyparty/bos/bos.py index c1128008..51335388 100644 --- a/copyparty/bos/bos.py +++ b/copyparty/bos/bos.py @@ -25,14 +25,21 @@ def listdir(p: str = ".") -> list[str]: def makedirs(name: str, mode: int = 0o755, exist_ok: bool = True) -> bool: + # os.makedirs does 777 for all but leaf; this does mode on all + todo = [] bname = fsenc(name) - try: - os.makedirs(bname, mode) - return True - except: - if not exist_ok or not os.path.isdir(bname): - raise + while bname: + if os.path.isdir(bname): + break + todo.append(bname) + bname = os.path.dirname(bname) + if not todo: + if not exist_ok: + os.mkdir(bname) # to throw return False + for zb in todo[::-1]: + os.mkdir(zb, mode) + return True def mkdir(p: str, mode: int = 0o755) -> None: diff --git a/copyparty/cfg.py b/copyparty/cfg.py index 26505e8f..24f748bc 100644 --- a/copyparty/cfg.py +++ b/copyparty/cfg.py @@ -78,6 +78,8 @@ def vf_vmap() -> dict[str, str]: } for k in ( "bup_ck", + "chmod_d", + "chmod_f", "dbd", "forget_ip", "hsortn", @@ -169,6 +171,8 @@ flagcats = { "safededup": "verify on-disk data before using it for dedup", "noclone": "take dupe data from clients, even if available on HDD", "nodupe": "rejects existing files (instead of linking/cloning them)", + "chmod_d=755": "unix-permission for new dirs/folders", + "chmod_f=644": "unix-permission for new files", "sparse": "force use of sparse files, mainly for s3-backed storage", "nosparse": "deny use of sparse files, mainly for slow storage", "daw": "enable full WebDAV write support (dangerous);\nPUT-operations will now \033[1;31mOVERWRITE\033[0;35m existing files", diff --git a/copyparty/ftpd.py b/copyparty/ftpd.py index b77a2d42..c464450e 100644 --- a/copyparty/ftpd.py +++ b/copyparty/ftpd.py @@ -229,7 +229,7 @@ class FtpFs(AbstractedFS): r = "r" in mode w = "w" in mode or "a" in mode or "+" in mode - ap = self.rv2a(filename, r, w)[0] + ap, vfs, _ = self.rv2a(filename, r, w) self.validpath(ap) if w: try: @@ -261,7 +261,11 @@ class FtpFs(AbstractedFS): wunlink(self.log, ap, VF_CAREFUL) - return open(fsenc(ap), mode, self.args.iobuf) + ret = open(fsenc(ap), mode, self.args.iobuf) + if w and "chmod_f" in vfs.flags: + os.fchmod(ret.fileno(), vfs.flags["chmod_f"]) + + return ret def chdir(self, path: str) -> None: nwd = join(self.cwd, path) @@ -292,8 +296,9 @@ class FtpFs(AbstractedFS): ) = avfs.can_access("", self.h.uname) def mkdir(self, path: str) -> None: - ap = self.rv2a(path, w=True)[0] - bos.makedirs(ap) # filezilla expects this + ap, vfs, _ = self.rv2a(path, w=True) + chmod = vfs.flags["chmod_d"] + bos.makedirs(ap, chmod) # filezilla expects this def listdir(self, path: str) -> list[str]: vpath = join(self.cwd, path) diff --git a/copyparty/httpcli.py b/copyparty/httpcli.py index d2378413..f4c493a0 100644 --- a/copyparty/httpcli.py +++ b/copyparty/httpcli.py @@ -2068,7 +2068,7 @@ class HttpCli(object): fdir, fn = os.path.split(fdir) rem, _ = vsplit(rem) - bos.makedirs(fdir) + bos.makedirs(fdir, vfs.flags["chmod_d"]) open_ka: dict[str, Any] = {"fun": open} open_a = ["wb", self.args.iobuf] @@ -2127,6 +2127,8 @@ class HttpCli(object): fn = vfs.flags["put_name2"].format(now=time.time(), cip=self.dip()) params = {"suffix": suffix, "fdir": fdir} + if "chmod_f" in vfs.flags: + params["chmod"] = vfs.flags["chmod_f"] if self.args.nw: params = {} fn = os.devnull @@ -2175,7 +2177,7 @@ class HttpCli(object): if self.args.nw: fn = os.devnull else: - bos.makedirs(fdir) + bos.makedirs(fdir, vfs.flags["chmod_d"]) path = os.path.join(fdir, fn) if not nameless: self.vpath = vjoin(self.vpath, fn) @@ -2307,7 +2309,7 @@ class HttpCli(object): if self.args.hook_v: log_reloc(self.log, hr["reloc"], x, path, vp, fn, vfs, rem) fdir, self.vpath, fn, (vfs, rem) = x - bos.makedirs(fdir) + bos.makedirs(fdir, vfs.flags["chmod_d"]) path2 = os.path.join(fdir, fn) atomic_move(self.log, path, path2, vfs.flags) path = path2 @@ -2593,7 +2595,7 @@ class HttpCli(object): dst = vfs.canonical(rem) try: if not bos.path.isdir(dst): - bos.makedirs(dst) + bos.makedirs(dst, vfs.flags["chmod_d"]) except OSError as ex: self.log("makedirs failed %r" % (dst,)) if not bos.path.isdir(dst): @@ -3028,7 +3030,7 @@ class HttpCli(object): raise Pebkac(405, 'folder "/%s" already exists' % (vpath,)) try: - bos.makedirs(fn) + bos.makedirs(fn, vfs.flags["chmod_d"]) except OSError as ex: if ex.errno == errno.EACCES: raise Pebkac(500, "the server OS denied write-access") @@ -3070,6 +3072,8 @@ class HttpCli(object): with open(fsenc(fn), "wb") as f: f.write(b"`GRUNNUR`\n") + if "chmod_f" in vfs.flags: + os.fchmod(f.fileno(), vfs.flags["chmod_f"]) vpath = "{}/{}".format(self.vpath, sanitized).lstrip("/") self.redirect(vpath, "?edit") @@ -3143,7 +3147,7 @@ class HttpCli(object): ) upload_vpath = "{}/{}".format(vfs.vpath, rem).strip("/") if not nullwrite: - bos.makedirs(fdir_base) + bos.makedirs(fdir_base, vfs.flags["chmod_d"]) rnd, lifetime, xbu, xau = self.upload_flags(vfs) zs = self.uparam.get("want") or self.headers.get("accept") or "" @@ -3238,8 +3242,11 @@ class HttpCli(object): else: open_args["fdir"] = fdir + if "chmod_f" in vfs.flags: + open_args["chmod"] = vfs.flags["chmod_f"] + if p_file and not nullwrite: - bos.makedirs(fdir) + bos.makedirs(fdir, vfs.flags["chmod_d"]) # reserve destination filename f, fname = ren_open(fname, "wb", fdir=fdir, suffix=suffix) @@ -3343,7 +3350,7 @@ class HttpCli(object): if nullwrite: fdir = ap2 = "" else: - bos.makedirs(fdir) + bos.makedirs(fdir, vfs.flags["chmod_d"]) atomic_move(self.log, abspath, ap2, vfs.flags) abspath = ap2 sz = bos.path.getsize(abspath) @@ -3464,6 +3471,8 @@ class HttpCli(object): ft = "{}:{}".format(self.ip, self.addr[1]) ft = "{}\n{}\n{}\n".format(ft, msg.rstrip(), errmsg) f.write(ft.encode("utf-8")) + if "chmod_f" in vfs.flags: + os.fchmod(f.fileno(), vfs.flags["chmod_f"]) except Exception as ex: suf = "\nfailed to write the upload report: {}".format(ex) @@ -3514,7 +3523,7 @@ class HttpCli(object): lim = vfs.get_dbv(rem)[0].lim if lim: fp, rp = lim.all(self.ip, rp, clen, vfs.realpath, fp, self.conn.hsrv.broker) - bos.makedirs(fp) + bos.makedirs(fp, vfs.flags["chmod_d"]) fp = os.path.join(fp, fn) rem = "{}/{}".format(rp, fn).strip("/") @@ -3582,13 +3591,15 @@ class HttpCli(object): zs = ub64enc(zb).decode("ascii")[:24].lower() dp = "%s/md/%s/%s/%s" % (dbv.histpath, zs[:2], zs[2:4], zs) self.log("moving old version to %s/%s" % (dp, mfile2)) - if bos.makedirs(dp): + if bos.makedirs(dp, vfs.flags["chmod_d"]): with open(os.path.join(dp, "dir.txt"), "wb") as f: f.write(afsenc(vrd)) + if "chmod_f" in vfs.flags: + os.fchmod(f.fileno(), vfs.flags["chmod_f"]) elif hist_cfg == "s": dp = os.path.join(mdir, ".hist") try: - bos.mkdir(dp) + bos.mkdir(dp, vfs.flags["chmod_d"]) hidedir(dp) except: pass @@ -3627,6 +3638,8 @@ class HttpCli(object): wunlink(self.log, fp, vfs.flags) with open(fsenc(fp), "wb", self.args.iobuf) as f: + if "chmod_f" in vfs.flags: + os.fchmod(f.fileno(), vfs.flags["chmod_f"]) sz, sha512, _ = hashcopy(p_data, f, None, 0, self.args.s_wr_slp) if lim: diff --git a/copyparty/smbd.py b/copyparty/smbd.py index b138ffdb..d5098de5 100644 --- a/copyparty/smbd.py +++ b/copyparty/smbd.py @@ -320,7 +320,7 @@ class SMB(object): self.hub.up2k.handle_mv(uname, "1.7.6.2", vp1, vp2) try: - bos.makedirs(ap2) + bos.makedirs(ap2, vfs2.flags["chmod_d"]) except: pass @@ -334,7 +334,7 @@ class SMB(object): t = "blocked mkdir (no-write-acc %s): /%s @%s" yeet(t % (vfs.axs.uwrite, vpath, uname)) - return bos.mkdir(ap) + return bos.mkdir(ap, vfs.flags["chmod_d"]) def _stat(self, vpath: str, *a: Any, **ka: Any) -> os.stat_result: try: diff --git a/copyparty/svchub.py b/copyparty/svchub.py index b498afe2..e7c293cc 100644 --- a/copyparty/svchub.py +++ b/copyparty/svchub.py @@ -27,6 +27,7 @@ if True: # pylint: disable=using-constant-test from .__init__ import ANYWIN, EXE, MACOS, PY2, TYPE_CHECKING, E, EnvParams, unicode from .authsrv import BAD_CFG, AuthSrv +from .bos import bos from .cert import ensure_cert from .mtag import HAVE_FFMPEG, HAVE_FFPROBE, HAVE_MUTAGEN from .pwhash import HAVE_ARGON2 @@ -1118,7 +1119,7 @@ class SvcHub(object): fn = sel_fn try: - os.makedirs(os.path.dirname(fn)) + bos.makedirs(os.path.dirname(fn)) except: pass @@ -1135,6 +1136,9 @@ class SvcHub(object): lh = codecs.open(fn, "w", encoding="utf-8", errors="replace") + if getattr(self.args, "free_umask", False): + os.fchmod(lh.fileno(), 0o644) + argv = [pybin] + self.argv if hasattr(shlex, "quote"): argv = [shlex.quote(x) for x in argv] diff --git a/copyparty/tftpd.py b/copyparty/tftpd.py index d8e06755..82ef3726 100644 --- a/copyparty/tftpd.py +++ b/copyparty/tftpd.py @@ -387,14 +387,18 @@ class Tftpd(object): if not a: a = (self.args.iobuf,) - return open(ap, mode, *a, **ka) + ret = open(ap, mode, *a, **ka) + if wr and "chmod_f" in vfs.flags: + os.fchmod(ret.fileno(), vfs.flags["chmod_f"]) + + return ret def _mkdir(self, vpath: str, *a) -> None: vfs, _, ap = self._v2a("mkdir", vpath, [False, True]) if "*" not in vfs.axs.uwrite: yeet("blocked mkdir; folder not world-writable: /%s" % (vpath,)) - return bos.mkdir(ap) + return bos.mkdir(ap, vfs.flags["chmod_d"]) def _unlink(self, vpath: str) -> None: # return bos.unlink(self._v2a("stat", vpath, *a)[1]) diff --git a/copyparty/th_srv.py b/copyparty/th_srv.py index c6b4a94f..e00c04e9 100644 --- a/copyparty/th_srv.py +++ b/copyparty/th_srv.py @@ -269,7 +269,8 @@ class ThumbSrv(object): self.log("joined waiting room for %r" % (tpath,)) except: thdir = os.path.dirname(tpath) - bos.makedirs(os.path.join(thdir, "w")) + chmod = 0o700 if self.args.free_umask else 0o755 + bos.makedirs(os.path.join(thdir, "w"), chmod) inf_path = os.path.join(thdir, "dir.txt") if not bos.path.exists(inf_path): diff --git a/copyparty/up2k.py b/copyparty/up2k.py index a55006ce..78b83389 100644 --- a/copyparty/up2k.py +++ b/copyparty/up2k.py @@ -915,7 +915,8 @@ class Up2k(object): # only need to protect register_vpath but all in one go feels right for vol in vols: try: - bos.makedirs(vol.realpath) # gonna happen at snap anyways + # mkdir gonna happen at snap anyways; + bos.makedirs(vol.realpath, vol.flags["chmod_d"]) dir_is_empty(self.log_func, not self.args.no_scandir, vol.realpath) except Exception as ex: self.volstate[vol.vpath] = "OFFLINE (cannot access folder)" @@ -1141,6 +1142,20 @@ class Up2k(object): del fl[k1] else: fl[k1] = ",".join(x for x in fl[k1]) + + if fl["chmod_d"] == int(self.args.chmod_d, 8): + fl.pop("chmod_d") + try: + if fl["chmod_f"] == int(self.args.chmod_f or "-1", 8): + fl.pop("chmod_f") + except: + pass + for k in ("chmod_f", "chmod_d"): + try: + fl[k] = "%o" % (fl[k]) + except: + pass + a = [ (ft if v is True else ff if v is False else fv).format(k, str(v)) for k, v in fl.items() @@ -3290,7 +3305,7 @@ class Up2k(object): reg, "up2k._get_volsize", ) - bos.makedirs(ap2) + bos.makedirs(ap2, vfs.flags["chmod_d"]) vfs.lim.nup(cj["addr"]) vfs.lim.bup(cj["addr"], cj["size"]) @@ -3397,11 +3412,11 @@ class Up2k(object): self.log(t % (mts - mtc, mts, mtc, fp)) ow = False + ptop = job["ptop"] + vf = self.flags.get(ptop) or {} if ow: self.log("replacing existing file at %r" % (fp,)) cur = None - ptop = job["ptop"] - vf = self.flags.get(ptop) or {} st = bos.stat(fp) try: vrel = vjoin(job["prel"], fname) @@ -3421,8 +3436,13 @@ class Up2k(object): else: dip = self.hub.iphash.s(ip) - suffix = "-%.6f-%s" % (ts, dip) - f, ret = ren_open(fname, "wb", fdir=fdir, suffix=suffix) + f, ret = ren_open( + fname, + "wb", + fdir=fdir, + suffix="-%.6f-%s" % (ts, dip), + chmod=vf.get("chmod_f", -1), + ) f.close() return ret @@ -4277,7 +4297,7 @@ class Up2k(object): self.log(t, 1) raise Pebkac(405, t) - bos.makedirs(os.path.dirname(dabs)) + bos.makedirs(os.path.dirname(dabs), dvn.flags["chmod_d"]) c1, w, ftime_, fsize_, ip, at = self._find_from_vpath( svn_dbv.realpath, srem_dbv @@ -4453,7 +4473,7 @@ class Up2k(object): vp = vjoin(dvp, rem) try: dvn, drem = self.vfs.get(vp, uname, False, True) - bos.mkdir(dvn.canonical(drem)) + bos.mkdir(dvn.canonical(drem), dvn.flags["chmod_d"]) except: pass @@ -4523,7 +4543,7 @@ class Up2k(object): is_xvol = svn.realpath != dvn.realpath - bos.makedirs(os.path.dirname(dabs)) + bos.makedirs(os.path.dirname(dabs), dvn.flags["chmod_d"]) if is_dirlink: dlabs = absreal(sabs) @@ -5030,8 +5050,13 @@ class Up2k(object): else: dip = self.hub.iphash.s(job["addr"]) - suffix = "-%.6f-%s" % (job["t0"], dip) - f, job["tnam"] = ren_open(tnam, "wb", fdir=pdir, suffix=suffix) + f, job["tnam"] = ren_open( + tnam, + "wb", + fdir=pdir, + suffix="-%.6f-%s" % (job["t0"], dip), + chmod=vf.get("chmod_f", -1), + ) try: abspath = djoin(pdir, job["tnam"]) sprs = job["sprs"] diff --git a/copyparty/util.py b/copyparty/util.py index 64be2d13..493fe407 100644 --- a/copyparty/util.py +++ b/copyparty/util.py @@ -1585,6 +1585,7 @@ def ren_open(fname: str, *args: Any, **kwargs: Any) -> tuple[typing.IO[Any], str fun = kwargs.pop("fun", open) fdir = kwargs.pop("fdir", None) suffix = kwargs.pop("suffix", None) + chmod = kwargs.pop("chmod", -1) if fname == os.devnull: return fun(fname, *args, **kwargs), fname @@ -1628,6 +1629,11 @@ def ren_open(fname: str, *args: Any, **kwargs: Any) -> tuple[typing.IO[Any], str fp2 = os.path.join(fdir, fp2) with open(fsenc(fp2), "wb") as f2: f2.write(orig_name.encode("utf-8")) + if chmod >= 0: + os.fchmod(f2.fileno(), chmod) + + if chmod >= 0: + os.fchmod(f.fileno(), chmod) return f, fname diff --git a/scripts/help2html.py b/scripts/help2html.py index ad6023e4..540091ec 100755 --- a/scripts/help2html.py +++ b/scripts/help2html.py @@ -7,7 +7,7 @@ import subprocess as sp # to convert the copyparty --help to html, run this in xfce4-terminal @ 140x43: _ = r"""" -echo; for a in '' -bind -accounts -flags -handlers -hooks -urlform -exp -ls -dbd -pwhash -zm; do +echo; for a in '' -bind -accounts -flags -handlers -hooks -urlform -exp -ls -dbd -chmod -pwhash -zm; do ./copyparty-sfx.py --help$a 2>/dev/null; printf '\n\n\n%0139d\n\n\n'; done # xfce4-terminal @ 140x43 """ # click [edit] => [select all] diff --git a/scripts/help2txt.sh b/scripts/help2txt.sh index 3345a885..f5a12565 100755 --- a/scripts/help2txt.sh +++ b/scripts/help2txt.sh @@ -23,7 +23,7 @@ exit 0 # first open an infinitely wide console (this is why you own an ultrawide) and copypaste this into it: -for a in '' -bind -accounts -flags -handlers -hooks -urlform -exp -ls -dbd -pwhash -zm; do +for a in '' -bind -accounts -flags -handlers -hooks -urlform -exp -ls -dbd -chmod -pwhash -zm; do ./copyparty-sfx.py --help$a 2>/dev/null; printf '\n\n\n%0255d\n\n\n'; done # then copypaste all of the output by pressing ctrl-shift-a, ctrl-shift-c diff --git a/tests/util.py b/tests/util.py index 12277adf..d6ac2f24 100644 --- a/tests/util.py +++ b/tests/util.py @@ -161,7 +161,7 @@ class Cfg(Namespace): ex = "db_act forget_ip idp_store k304 loris no304 nosubtle re_maxage rproxy rsp_jtr rsp_slp s_wr_slp snap_wri theme themes turbo u2ow zipmaxn zipmaxs" ka.update(**{k: 0 for k in ex.split()}) - ex = "ah_alg bname chpw_db doctitle df exit favico idp_h_usr ipa html_head lg_sba lg_sbf log_fk md_sba md_sbf name og_desc og_site og_th og_title og_title_a og_title_v og_title_i shr tcolor textfiles unlist vname xff_src zipmaxt R RS SR" + ex = "ah_alg bname chmod_f chpw_db doctitle df exit favico idp_h_usr ipa html_head lg_sba lg_sbf log_fk md_sba md_sbf name og_desc og_site og_th og_title og_title_a og_title_v og_title_i shr tcolor textfiles unlist vname xff_src zipmaxt R RS SR" ka.update(**{k: "" for k in ex.split()}) ex = "ban_403 ban_404 ban_422 ban_pw ban_url spinner" @@ -181,6 +181,7 @@ class Cfg(Namespace): c=c, E=E, bup_ck="sha512", + chmod_d="755", dbd="wal", dk_salt="b" * 16, fk_salt="a" * 16,