copyparty 1.18.5__py3-none-any.whl → 1.18.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- copyparty/__main__.py +32 -27
- copyparty/__version__.py +2 -2
- copyparty/authsrv.py +48 -2
- copyparty/bos/bos.py +14 -3
- copyparty/cfg.py +6 -0
- copyparty/ftpd.py +4 -4
- copyparty/httpcli.py +75 -53
- copyparty/httpsrv.py +1 -0
- copyparty/mtag.py +3 -2
- copyparty/smbd.py +1 -1
- copyparty/svchub.py +4 -3
- copyparty/tftpd.py +6 -3
- copyparty/th_srv.py +2 -2
- copyparty/up2k.py +14 -8
- copyparty/util.py +62 -22
- copyparty/web/browser.html +2 -2
- copyparty/web/browser.js.gz +0 -0
- copyparty/web/shares.js.gz +0 -0
- copyparty/web/splash.js.gz +0 -0
- copyparty/web/svcs.html +16 -4
- copyparty/web/svcs.js.gz +0 -0
- {copyparty-1.18.5.dist-info → copyparty-1.18.7.dist-info}/METADATA +32 -5
- {copyparty-1.18.5.dist-info → copyparty-1.18.7.dist-info}/RECORD +27 -27
- {copyparty-1.18.5.dist-info → copyparty-1.18.7.dist-info}/WHEEL +0 -0
- {copyparty-1.18.5.dist-info → copyparty-1.18.7.dist-info}/entry_points.txt +0 -0
- {copyparty-1.18.5.dist-info → copyparty-1.18.7.dist-info}/licenses/LICENSE +0 -0
- {copyparty-1.18.5.dist-info → copyparty-1.18.7.dist-info}/top_level.txt +0 -0
copyparty/httpcli.py
CHANGED
@@ -33,7 +33,7 @@ except:
|
|
33
33
|
|
34
34
|
from .__init__ import ANYWIN, PY2, RES, TYPE_CHECKING, EnvParams, unicode
|
35
35
|
from .__version__ import S_VERSION
|
36
|
-
from .authsrv import VFS # typechk
|
36
|
+
from .authsrv import LEELOO_DALLAS, VFS # typechk
|
37
37
|
from .bos import bos
|
38
38
|
from .star import StreamTar
|
39
39
|
from .stolen.qrcodegen import QrCode, qr2svg
|
@@ -79,8 +79,10 @@ from .util import (
|
|
79
79
|
hidedir,
|
80
80
|
html_bescape,
|
81
81
|
html_escape,
|
82
|
+
html_sh_esc,
|
82
83
|
humansize,
|
83
84
|
ipnorm,
|
85
|
+
json_hesc,
|
84
86
|
justcopy,
|
85
87
|
load_resource,
|
86
88
|
loadpy,
|
@@ -103,6 +105,7 @@ from .util import (
|
|
103
105
|
sanitize_vpath,
|
104
106
|
sendfile_kern,
|
105
107
|
sendfile_py,
|
108
|
+
set_fperms,
|
106
109
|
stat_resource,
|
107
110
|
ub64dec,
|
108
111
|
ub64enc,
|
@@ -617,6 +620,9 @@ class HttpCli(object):
|
|
617
620
|
) or self.args.idp_h_key in self.headers
|
618
621
|
|
619
622
|
if trusted_key and trusted_xff:
|
623
|
+
if idp_usr.lower() == LEELOO_DALLAS:
|
624
|
+
self.loud_reply("send her back", status=403)
|
625
|
+
return False
|
620
626
|
self.asrv.idp_checkin(self.conn.hsrv.broker, idp_usr, idp_grp)
|
621
627
|
else:
|
622
628
|
if not trusted_key:
|
@@ -1105,15 +1111,18 @@ class HttpCli(object):
|
|
1105
1111
|
else:
|
1106
1112
|
return True
|
1107
1113
|
|
1114
|
+
host = self.host.lower()
|
1115
|
+
if host.startswith("["):
|
1116
|
+
if "]:" in host:
|
1117
|
+
host = host.split("]:")[0] + "]"
|
1118
|
+
else:
|
1119
|
+
host = host.split(":")[0]
|
1120
|
+
|
1108
1121
|
oh = self.out_headers
|
1109
1122
|
origin = origin.lower()
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
"https" if self.is_https else "http",
|
1114
|
-
self.host.lower().split(":")[0],
|
1115
|
-
)
|
1116
|
-
]
|
1123
|
+
proto = "https" if self.is_https else "http"
|
1124
|
+
good_origins = self.args.acao + ["%s://%s" % (proto, host)]
|
1125
|
+
|
1117
1126
|
if "pw" in ih or re.sub(r"(:[0-9]{1,5})?/?$", "", origin) in good_origins:
|
1118
1127
|
good_origin = True
|
1119
1128
|
bad_hdrs = ("",)
|
@@ -1570,6 +1579,18 @@ class HttpCli(object):
|
|
1570
1579
|
self.log("inaccessible: %r" % ("/" + self.vpath,))
|
1571
1580
|
raise Pebkac(401, "authenticate")
|
1572
1581
|
|
1582
|
+
if "quota-available-bytes" in props and not self.args.nid:
|
1583
|
+
bfree, btot, _ = get_df(vn.realpath, False)
|
1584
|
+
if btot:
|
1585
|
+
df = {
|
1586
|
+
"quota-available-bytes": str(bfree),
|
1587
|
+
"quota-used-bytes": str(btot - bfree),
|
1588
|
+
}
|
1589
|
+
else:
|
1590
|
+
df = {}
|
1591
|
+
else:
|
1592
|
+
df = {}
|
1593
|
+
|
1573
1594
|
fgen = itertools.chain([topdir], fgen)
|
1574
1595
|
vtop = vjoin(self.args.R, vjoin(vn.vpath, rem))
|
1575
1596
|
|
@@ -1612,6 +1633,9 @@ class HttpCli(object):
|
|
1612
1633
|
ap = os.path.join(tap, x["vp"])
|
1613
1634
|
pvs["getcontenttype"] = html_escape(guess_mime(rp, ap))
|
1614
1635
|
pvs["getcontentlength"] = str(st.st_size)
|
1636
|
+
elif df:
|
1637
|
+
pvs.update(df)
|
1638
|
+
df = {}
|
1615
1639
|
|
1616
1640
|
for k, v in pvs.items():
|
1617
1641
|
if k not in props:
|
@@ -2060,7 +2084,7 @@ class HttpCli(object):
|
|
2060
2084
|
fdir, fn = os.path.split(fdir)
|
2061
2085
|
rem, _ = vsplit(rem)
|
2062
2086
|
|
2063
|
-
bos.makedirs(fdir, vfs.flags
|
2087
|
+
bos.makedirs(fdir, vf=vfs.flags)
|
2064
2088
|
|
2065
2089
|
open_ka = {"fun": open}
|
2066
2090
|
open_a = ["wb", self.args.iobuf]
|
@@ -2117,9 +2141,7 @@ class HttpCli(object):
|
|
2117
2141
|
if nameless:
|
2118
2142
|
fn = vfs.flags["put_name2"].format(now=time.time(), cip=self.dip())
|
2119
2143
|
|
2120
|
-
params = {"suffix": suffix, "fdir": fdir}
|
2121
|
-
if "chmod_f" in vfs.flags:
|
2122
|
-
params["chmod"] = vfs.flags["chmod_f"]
|
2144
|
+
params = {"suffix": suffix, "fdir": fdir, "vf": vfs.flags}
|
2123
2145
|
if self.args.nw:
|
2124
2146
|
params = {}
|
2125
2147
|
fn = os.devnull
|
@@ -2167,7 +2189,7 @@ class HttpCli(object):
|
|
2167
2189
|
if self.args.nw:
|
2168
2190
|
fn = os.devnull
|
2169
2191
|
else:
|
2170
|
-
bos.makedirs(fdir, vfs.flags
|
2192
|
+
bos.makedirs(fdir, vf=vfs.flags)
|
2171
2193
|
path = os.path.join(fdir, fn)
|
2172
2194
|
if not nameless:
|
2173
2195
|
self.vpath = vjoin(self.vpath, fn)
|
@@ -2299,7 +2321,7 @@ class HttpCli(object):
|
|
2299
2321
|
if self.args.hook_v:
|
2300
2322
|
log_reloc(self.log, hr["reloc"], x, path, vp, fn, vfs, rem)
|
2301
2323
|
fdir, self.vpath, fn, (vfs, rem) = x
|
2302
|
-
bos.makedirs(fdir, vfs.flags
|
2324
|
+
bos.makedirs(fdir, vf=vfs.flags)
|
2303
2325
|
path2 = os.path.join(fdir, fn)
|
2304
2326
|
atomic_move(self.log, path, path2, vfs.flags)
|
2305
2327
|
path = path2
|
@@ -2584,7 +2606,7 @@ class HttpCli(object):
|
|
2584
2606
|
dst = vfs.canonical(rem)
|
2585
2607
|
try:
|
2586
2608
|
if not bos.path.isdir(dst):
|
2587
|
-
bos.makedirs(dst, vfs.flags
|
2609
|
+
bos.makedirs(dst, vf=vfs.flags)
|
2588
2610
|
except OSError as ex:
|
2589
2611
|
self.log("makedirs failed %r" % (dst,))
|
2590
2612
|
if not bos.path.isdir(dst):
|
@@ -2900,6 +2922,7 @@ class HttpCli(object):
|
|
2900
2922
|
|
2901
2923
|
ok, msg = self.asrv.chpw(self.conn.hsrv.broker, self.uname, pwd)
|
2902
2924
|
if ok:
|
2925
|
+
self.cbonk(self.conn.hsrv.gpwc, pwd, "pw", "too many password changes")
|
2903
2926
|
ok, msg = self.get_pwd_cookie(pwd)
|
2904
2927
|
if ok:
|
2905
2928
|
msg = "new password OK"
|
@@ -3010,6 +3033,9 @@ class HttpCli(object):
|
|
3010
3033
|
self.gctx = vpath
|
3011
3034
|
vpath = undot(vpath)
|
3012
3035
|
vfs, rem = self.asrv.vfs.get(vpath, self.uname, False, True)
|
3036
|
+
if "nosub" in vfs.flags:
|
3037
|
+
raise Pebkac(403, "mkdir is forbidden below this folder")
|
3038
|
+
|
3013
3039
|
rem = sanitize_vpath(rem, "/")
|
3014
3040
|
fn = vfs.canonical(rem)
|
3015
3041
|
|
@@ -3023,7 +3049,7 @@ class HttpCli(object):
|
|
3023
3049
|
raise Pebkac(405, 'folder "/%s" already exists' % (vpath,))
|
3024
3050
|
|
3025
3051
|
try:
|
3026
|
-
bos.makedirs(fn, vfs.flags
|
3052
|
+
bos.makedirs(fn, vf=vfs.flags)
|
3027
3053
|
except OSError as ex:
|
3028
3054
|
if ex.errno == errno.EACCES:
|
3029
3055
|
raise Pebkac(500, "the server OS denied write-access")
|
@@ -3064,8 +3090,8 @@ class HttpCli(object):
|
|
3064
3090
|
|
3065
3091
|
with open(fsenc(fn), "wb") as f:
|
3066
3092
|
f.write(b"`GRUNNUR`\n")
|
3067
|
-
if "
|
3068
|
-
|
3093
|
+
if "fperms" in vfs.flags:
|
3094
|
+
set_fperms(f, vfs.flags)
|
3069
3095
|
|
3070
3096
|
vpath = "{}/{}".format(self.vpath, sanitized).lstrip("/")
|
3071
3097
|
self.redirect(vpath, "?edit")
|
@@ -3139,7 +3165,7 @@ class HttpCli(object):
|
|
3139
3165
|
)
|
3140
3166
|
upload_vpath = "{}/{}".format(vfs.vpath, rem).strip("/")
|
3141
3167
|
if not nullwrite:
|
3142
|
-
bos.makedirs(fdir_base, vfs.flags
|
3168
|
+
bos.makedirs(fdir_base, vf=vfs.flags)
|
3143
3169
|
|
3144
3170
|
rnd, lifetime, xbu, xau = self.upload_flags(vfs)
|
3145
3171
|
zs = self.uparam.get("want") or self.headers.get("accept") or ""
|
@@ -3172,7 +3198,7 @@ class HttpCli(object):
|
|
3172
3198
|
if rnd:
|
3173
3199
|
fname = rand_name(fdir, fname, rnd)
|
3174
3200
|
|
3175
|
-
open_args = {"fdir": fdir, "suffix": suffix}
|
3201
|
+
open_args = {"fdir": fdir, "suffix": suffix, "vf": vfs.flags}
|
3176
3202
|
|
3177
3203
|
if "replace" in self.uparam:
|
3178
3204
|
if not self.can_delete:
|
@@ -3234,11 +3260,8 @@ class HttpCli(object):
|
|
3234
3260
|
else:
|
3235
3261
|
open_args["fdir"] = fdir
|
3236
3262
|
|
3237
|
-
if "chmod_f" in vfs.flags:
|
3238
|
-
open_args["chmod"] = vfs.flags["chmod_f"]
|
3239
|
-
|
3240
3263
|
if p_file and not nullwrite:
|
3241
|
-
bos.makedirs(fdir, vfs.flags
|
3264
|
+
bos.makedirs(fdir, vf=vfs.flags)
|
3242
3265
|
|
3243
3266
|
# reserve destination filename
|
3244
3267
|
f, fname = ren_open(fname, "wb", fdir=fdir, suffix=suffix)
|
@@ -3342,7 +3365,7 @@ class HttpCli(object):
|
|
3342
3365
|
if nullwrite:
|
3343
3366
|
fdir = ap2 = ""
|
3344
3367
|
else:
|
3345
|
-
bos.makedirs(fdir, vfs.flags
|
3368
|
+
bos.makedirs(fdir, vf=vfs.flags)
|
3346
3369
|
atomic_move(self.log, abspath, ap2, vfs.flags)
|
3347
3370
|
abspath = ap2
|
3348
3371
|
sz = bos.path.getsize(abspath)
|
@@ -3463,8 +3486,8 @@ class HttpCli(object):
|
|
3463
3486
|
ft = "{}:{}".format(self.ip, self.addr[1])
|
3464
3487
|
ft = "{}\n{}\n{}\n".format(ft, msg.rstrip(), errmsg)
|
3465
3488
|
f.write(ft.encode("utf-8"))
|
3466
|
-
if "
|
3467
|
-
|
3489
|
+
if "fperms" in vfs.flags:
|
3490
|
+
set_fperms(f, vfs.flags)
|
3468
3491
|
except Exception as ex:
|
3469
3492
|
suf = "\nfailed to write the upload report: {}".format(ex)
|
3470
3493
|
|
@@ -3514,7 +3537,7 @@ class HttpCli(object):
|
|
3514
3537
|
lim = vfs.get_dbv(rem)[0].lim
|
3515
3538
|
if lim:
|
3516
3539
|
fp, rp = lim.all(self.ip, rp, clen, vfs.realpath, fp, self.conn.hsrv.broker)
|
3517
|
-
bos.makedirs(fp, vfs.flags
|
3540
|
+
bos.makedirs(fp, vf=vfs.flags)
|
3518
3541
|
|
3519
3542
|
fp = os.path.join(fp, fn)
|
3520
3543
|
rem = "{}/{}".format(rp, fn).strip("/")
|
@@ -3582,15 +3605,17 @@ class HttpCli(object):
|
|
3582
3605
|
zs = ub64enc(zb).decode("ascii")[:24].lower()
|
3583
3606
|
dp = "%s/md/%s/%s/%s" % (dbv.histpath, zs[:2], zs[2:4], zs)
|
3584
3607
|
self.log("moving old version to %s/%s" % (dp, mfile2))
|
3585
|
-
if bos.makedirs(dp, vfs.flags
|
3608
|
+
if bos.makedirs(dp, vf=vfs.flags):
|
3586
3609
|
with open(os.path.join(dp, "dir.txt"), "wb") as f:
|
3587
3610
|
f.write(afsenc(vrd))
|
3588
|
-
if "
|
3589
|
-
|
3611
|
+
if "fperms" in vfs.flags:
|
3612
|
+
set_fperms(f, vfs.flags)
|
3590
3613
|
elif hist_cfg == "s":
|
3591
3614
|
dp = os.path.join(mdir, ".hist")
|
3592
3615
|
try:
|
3593
3616
|
bos.mkdir(dp, vfs.flags["chmod_d"])
|
3617
|
+
if "chown" in vfs.flags:
|
3618
|
+
bos.chown(dp, vfs.flags["uid"], vfs.flags["gid"])
|
3594
3619
|
hidedir(dp)
|
3595
3620
|
except:
|
3596
3621
|
pass
|
@@ -3628,8 +3653,8 @@ class HttpCli(object):
|
|
3628
3653
|
wunlink(self.log, fp, vfs.flags)
|
3629
3654
|
|
3630
3655
|
with open(fsenc(fp), "wb", self.args.iobuf) as f:
|
3631
|
-
if "
|
3632
|
-
|
3656
|
+
if "fperms" in vfs.flags:
|
3657
|
+
set_fperms(f, vfs.flags)
|
3633
3658
|
sz, sha512, _ = hashcopy(p_data, f, None, 0, self.args.s_wr_slp)
|
3634
3659
|
|
3635
3660
|
if lim:
|
@@ -4866,11 +4891,8 @@ class HttpCli(object):
|
|
4866
4891
|
else:
|
4867
4892
|
rip = host
|
4868
4893
|
|
4869
|
-
|
4870
|
-
pw =
|
4871
|
-
vp = re.sub(r"[<>&$?`\"']", "_", self.uparam["hc"] or "").lstrip("/")
|
4872
|
-
pw = pw.replace(" ", "%20")
|
4873
|
-
vp = vp.replace(" ", "%20")
|
4894
|
+
vp = (self.uparam["hc"] or "").lstrip("/")
|
4895
|
+
pw = self.pw or "hunter2"
|
4874
4896
|
if pw in self.asrv.sesa:
|
4875
4897
|
pw = "hunter2"
|
4876
4898
|
|
@@ -4879,14 +4901,14 @@ class HttpCli(object):
|
|
4879
4901
|
args=self.args,
|
4880
4902
|
accs=bool(self.asrv.acct),
|
4881
4903
|
s="s" if self.is_https else "",
|
4882
|
-
rip=rip,
|
4883
|
-
ep=ep,
|
4884
|
-
vp=vp,
|
4885
|
-
rvp=vjoin(self.args.R, vp),
|
4886
|
-
host=host,
|
4887
|
-
hport=hport,
|
4904
|
+
rip=html_sh_esc(rip),
|
4905
|
+
ep=html_sh_esc(ep),
|
4906
|
+
vp=html_sh_esc(vp),
|
4907
|
+
rvp=html_sh_esc(vjoin(self.args.R, vp)),
|
4908
|
+
host=html_sh_esc(host),
|
4909
|
+
hport=html_sh_esc(hport),
|
4888
4910
|
aname=aname,
|
4889
|
-
pw=pw,
|
4911
|
+
pw=html_sh_esc(pw),
|
4890
4912
|
)
|
4891
4913
|
self.reply(html.encode("utf-8"))
|
4892
4914
|
return True
|
@@ -5548,7 +5570,7 @@ class HttpCli(object):
|
|
5548
5570
|
self.reply(jtxt.encode("utf-8", "replace"), mime="application/json")
|
5549
5571
|
return True
|
5550
5572
|
|
5551
|
-
html = self.j2s("rups", this=self, v=jtxt)
|
5573
|
+
html = self.j2s("rups", this=self, v=json_hesc(jtxt))
|
5552
5574
|
self.reply(html.encode("utf-8"), status=200)
|
5553
5575
|
return True
|
5554
5576
|
|
@@ -5612,15 +5634,15 @@ class HttpCli(object):
|
|
5612
5634
|
raise Pebkac(500, "sqlite3 not found on server; sharing is disabled")
|
5613
5635
|
raise Pebkac(500, "server busy, cannot create share; please retry in a bit")
|
5614
5636
|
|
5637
|
+
skey = self.uparam.get("skey") or self.vpath.split("/")[-1]
|
5638
|
+
|
5615
5639
|
if self.args.shr_v:
|
5616
|
-
self.log("handle_eshare: " +
|
5640
|
+
self.log("handle_eshare: " + skey)
|
5617
5641
|
|
5618
5642
|
cur = idx.get_shr()
|
5619
5643
|
if not cur:
|
5620
5644
|
raise Pebkac(400, "huh, sharing must be disabled in the server config...")
|
5621
5645
|
|
5622
|
-
skey = self.vpath.split("/")[-1]
|
5623
|
-
|
5624
5646
|
rows = cur.execute("select un, t1 from sh where k = ?", (skey,)).fetchall()
|
5625
5647
|
un = rows[0][0] if rows and rows[0] else ""
|
5626
5648
|
|
@@ -6129,13 +6151,13 @@ class HttpCli(object):
|
|
6129
6151
|
self.log("#wow #whoa")
|
6130
6152
|
|
6131
6153
|
if not self.args.nid:
|
6132
|
-
free, total,
|
6133
|
-
if total
|
6154
|
+
free, total, zs = get_df(abspath, False)
|
6155
|
+
if total:
|
6134
6156
|
h1 = humansize(free or 0)
|
6135
6157
|
h2 = humansize(total)
|
6136
6158
|
srv_info.append("{} free of {}".format(h1, h2))
|
6137
|
-
elif
|
6138
|
-
|
6159
|
+
elif zs:
|
6160
|
+
self.log("diskfree(%r): %s" % (abspath, zs), 3)
|
6139
6161
|
|
6140
6162
|
srv_infot = "</span> // <span>".join(srv_info)
|
6141
6163
|
|
copyparty/httpsrv.py
CHANGED
@@ -120,6 +120,7 @@ class HttpSrv(object):
|
|
120
120
|
self.nm = NetMap([], [])
|
121
121
|
self.ssdp = None
|
122
122
|
self.gpwd = Garda(self.args.ban_pw)
|
123
|
+
self.gpwc = Garda(self.args.ban_pwc)
|
123
124
|
self.g404 = Garda(self.args.ban_404)
|
124
125
|
self.g403 = Garda(self.args.ban_403)
|
125
126
|
self.g422 = Garda(self.args.ban_422, False)
|
copyparty/mtag.py
CHANGED
@@ -160,12 +160,13 @@ def au_unpk(
|
|
160
160
|
znil = [x for x in znil if "cover" in x[0]] or znil
|
161
161
|
znil = [x for x in znil if CBZ_01.search(x[0])] or znil
|
162
162
|
t = "cbz: %d files, %d hits" % (nf, len(znil))
|
163
|
+
using = sorted(znil)[0][1].filename
|
163
164
|
if znil:
|
164
|
-
t += ", using " +
|
165
|
+
t += ", using " + using
|
165
166
|
log(t)
|
166
167
|
if not znil:
|
167
168
|
raise Exception("no images inside cbz")
|
168
|
-
fi = zf.open(
|
169
|
+
fi = zf.open(using)
|
169
170
|
|
170
171
|
else:
|
171
172
|
raise Exception("unknown compression %s" % (pk,))
|
copyparty/smbd.py
CHANGED
copyparty/svchub.py
CHANGED
@@ -45,6 +45,7 @@ from .util import (
|
|
45
45
|
HAVE_PSUTIL,
|
46
46
|
HAVE_SQLITE3,
|
47
47
|
HAVE_ZMQ,
|
48
|
+
RE_ANSI,
|
48
49
|
URL_BUG,
|
49
50
|
UTC,
|
50
51
|
VERSIONS,
|
@@ -54,7 +55,6 @@ from .util import (
|
|
54
55
|
HMaccas,
|
55
56
|
ODict,
|
56
57
|
alltrace,
|
57
|
-
ansi_re,
|
58
58
|
build_netmap,
|
59
59
|
expat_ver,
|
60
60
|
gzip,
|
@@ -162,6 +162,7 @@ class SvcHub(object):
|
|
162
162
|
# for non-http clients (ftp, tftp)
|
163
163
|
self.bans = {}
|
164
164
|
self.gpwd = Garda(self.args.ban_pw)
|
165
|
+
self.gpwc = Garda(self.args.ban_pwc)
|
165
166
|
self.g404 = Garda(self.args.ban_404)
|
166
167
|
self.g403 = Garda(self.args.ban_403)
|
167
168
|
self.g422 = Garda(self.args.ban_422, False)
|
@@ -1398,9 +1399,9 @@ class SvcHub(object):
|
|
1398
1399
|
if self.no_ansi:
|
1399
1400
|
fmt = "%s %-21s %s\n"
|
1400
1401
|
if "\033" in msg:
|
1401
|
-
msg =
|
1402
|
+
msg = RE_ANSI.sub("", msg)
|
1402
1403
|
if "\033" in src:
|
1403
|
-
src =
|
1404
|
+
src = RE_ANSI.sub("", src)
|
1404
1405
|
elif c:
|
1405
1406
|
if isinstance(c, int):
|
1406
1407
|
msg = "\033[3%sm%s\033[0m" % (c, msg)
|
copyparty/tftpd.py
CHANGED
@@ -45,6 +45,7 @@ from .util import (
|
|
45
45
|
exclude_dotfiles,
|
46
46
|
min_ex,
|
47
47
|
runhook,
|
48
|
+
set_fperms,
|
48
49
|
undot,
|
49
50
|
vjoin,
|
50
51
|
vsplit,
|
@@ -385,8 +386,8 @@ class Tftpd(object):
|
|
385
386
|
a = (self.args.iobuf,)
|
386
387
|
|
387
388
|
ret = open(ap, mode, *a, **ka)
|
388
|
-
if wr and "
|
389
|
-
|
389
|
+
if wr and "fperms" in vfs.flags:
|
390
|
+
set_fperms(ret, vfs.flags)
|
390
391
|
|
391
392
|
return ret
|
392
393
|
|
@@ -395,7 +396,9 @@ class Tftpd(object):
|
|
395
396
|
if "*" not in vfs.axs.uwrite:
|
396
397
|
yeet("blocked mkdir; folder not world-writable: /%s" % (vpath,))
|
397
398
|
|
398
|
-
|
399
|
+
bos.mkdir(ap, vfs.flags["chmod_d"])
|
400
|
+
if "chown" in vfs.flags:
|
401
|
+
bos.chown(ap, vfs.flags["uid"], vfs.flags["gid"])
|
399
402
|
|
400
403
|
def _unlink(self, vpath ) :
|
401
404
|
# return bos.unlink(self._v2a("stat", vpath, *a)[1])
|
copyparty/th_srv.py
CHANGED
@@ -266,8 +266,8 @@ class ThumbSrv(object):
|
|
266
266
|
self.log("joined waiting room for %r" % (tpath,))
|
267
267
|
except:
|
268
268
|
thdir = os.path.dirname(tpath)
|
269
|
-
chmod =
|
270
|
-
bos.makedirs(os.path.join(thdir, "w"), chmod)
|
269
|
+
chmod = bos.MKD_700 if self.args.free_umask else bos.MKD_755
|
270
|
+
bos.makedirs(os.path.join(thdir, "w"), vf=chmod)
|
271
271
|
|
272
272
|
inf_path = os.path.join(thdir, "dir.txt")
|
273
273
|
if not bos.path.exists(inf_path):
|
copyparty/up2k.py
CHANGED
@@ -911,7 +911,7 @@ class Up2k(object):
|
|
911
911
|
for vol in vols:
|
912
912
|
try:
|
913
913
|
# mkdir gonna happen at snap anyways;
|
914
|
-
bos.makedirs(vol.realpath, vol.flags
|
914
|
+
bos.makedirs(vol.realpath, vf=vol.flags)
|
915
915
|
dir_is_empty(self.log_func, not self.args.no_scandir, vol.realpath)
|
916
916
|
except Exception as ex:
|
917
917
|
self.volstate[vol.vpath] = "OFFLINE (cannot access folder)"
|
@@ -3293,7 +3293,7 @@ class Up2k(object):
|
|
3293
3293
|
reg,
|
3294
3294
|
"up2k._get_volsize",
|
3295
3295
|
)
|
3296
|
-
bos.makedirs(ap2, vfs.flags
|
3296
|
+
bos.makedirs(ap2, vf=vfs.flags)
|
3297
3297
|
vfs.lim.nup(cj["addr"])
|
3298
3298
|
vfs.lim.bup(cj["addr"], cj["size"])
|
3299
3299
|
|
@@ -3429,7 +3429,7 @@ class Up2k(object):
|
|
3429
3429
|
"wb",
|
3430
3430
|
fdir=fdir,
|
3431
3431
|
suffix="-%.6f-%s" % (ts, dip),
|
3432
|
-
|
3432
|
+
vf=vf,
|
3433
3433
|
)
|
3434
3434
|
f.close()
|
3435
3435
|
return ret
|
@@ -3460,6 +3460,8 @@ class Up2k(object):
|
|
3460
3460
|
|
3461
3461
|
linked = False
|
3462
3462
|
try:
|
3463
|
+
if "reflink" in flags:
|
3464
|
+
raise Exception("reflink")
|
3463
3465
|
if not is_mv and not flags.get("dedup"):
|
3464
3466
|
raise Exception("dedup is disabled in config")
|
3465
3467
|
|
@@ -3516,7 +3518,8 @@ class Up2k(object):
|
|
3516
3518
|
|
3517
3519
|
linked = True
|
3518
3520
|
except Exception as ex:
|
3519
|
-
|
3521
|
+
if str(ex) != "reflink":
|
3522
|
+
self.log("cannot link; creating copy: " + repr(ex))
|
3520
3523
|
if bos.path.isfile(src):
|
3521
3524
|
csrc = src
|
3522
3525
|
elif fsrc and bos.path.isfile(fsrc):
|
@@ -4280,7 +4283,7 @@ class Up2k(object):
|
|
4280
4283
|
self.log(t, 1)
|
4281
4284
|
raise Pebkac(405, t)
|
4282
4285
|
|
4283
|
-
bos.makedirs(os.path.dirname(dabs), dvn.flags
|
4286
|
+
bos.makedirs(os.path.dirname(dabs), vf=dvn.flags)
|
4284
4287
|
|
4285
4288
|
c1, w, ftime_, fsize_, ip, at = self._find_from_vpath(
|
4286
4289
|
svn_dbv.realpath, srem_dbv
|
@@ -4455,7 +4458,10 @@ class Up2k(object):
|
|
4455
4458
|
vp = vjoin(dvp, rem)
|
4456
4459
|
try:
|
4457
4460
|
dvn, drem = self.vfs.get(vp, uname, False, True)
|
4458
|
-
|
4461
|
+
dap = dvn.canonical(drem)
|
4462
|
+
bos.mkdir(dap, dvn.flags["chmod_d"])
|
4463
|
+
if "chown" in dvn.flags:
|
4464
|
+
bos.chown(dap, dvn.flags["uid"], dvn.flags["gid"])
|
4459
4465
|
except:
|
4460
4466
|
pass
|
4461
4467
|
|
@@ -4525,7 +4531,7 @@ class Up2k(object):
|
|
4525
4531
|
|
4526
4532
|
is_xvol = svn.realpath != dvn.realpath
|
4527
4533
|
|
4528
|
-
bos.makedirs(os.path.dirname(dabs), dvn.flags
|
4534
|
+
bos.makedirs(os.path.dirname(dabs), vf=dvn.flags)
|
4529
4535
|
|
4530
4536
|
if is_dirlink:
|
4531
4537
|
dlabs = absreal(sabs)
|
@@ -5035,7 +5041,7 @@ class Up2k(object):
|
|
5035
5041
|
"wb",
|
5036
5042
|
fdir=pdir,
|
5037
5043
|
suffix="-%.6f-%s" % (job["t0"], dip),
|
5038
|
-
|
5044
|
+
vf=vf,
|
5039
5045
|
)
|
5040
5046
|
try:
|
5041
5047
|
abspath = djoin(pdir, job["tnam"])
|