copyparty 1.15.5__py3-none-any.whl → 1.15.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 +7 -4
- copyparty/__version__.py +2 -2
- copyparty/authsrv.py +1 -1
- copyparty/cfg.py +3 -1
- copyparty/ftpd.py +4 -0
- copyparty/httpcli.py +77 -26
- copyparty/httpconn.py +2 -0
- copyparty/httpsrv.py +6 -0
- copyparty/mtag.py +1 -1
- copyparty/ssdp.py +1 -1
- copyparty/svchub.py +6 -0
- copyparty/tcpsrv.py +1 -1
- copyparty/up2k.py +76 -35
- copyparty/util.py +35 -4
- copyparty/web/a/u2c.py +30 -12
- copyparty/web/browser.css.gz +0 -0
- copyparty/web/browser.js.gz +0 -0
- {copyparty-1.15.5.dist-info → copyparty-1.15.7.dist-info}/METADATA +78 -23
- {copyparty-1.15.5.dist-info → copyparty-1.15.7.dist-info}/RECORD +23 -23
- {copyparty-1.15.5.dist-info → copyparty-1.15.7.dist-info}/LICENSE +0 -0
- {copyparty-1.15.5.dist-info → copyparty-1.15.7.dist-info}/WHEEL +0 -0
- {copyparty-1.15.5.dist-info → copyparty-1.15.7.dist-info}/entry_points.txt +0 -0
- {copyparty-1.15.5.dist-info → copyparty-1.15.7.dist-info}/top_level.txt +0 -0
copyparty/__main__.py
CHANGED
@@ -772,7 +772,7 @@ def get_sects():
|
|
772
772
|
dedent(
|
773
773
|
"""
|
774
774
|
specify --exp or the "exp" volflag to enable placeholder expansions
|
775
|
-
in README.md / .prologue.html / .epilogue.html
|
775
|
+
in README.md / PREADME.md / .prologue.html / .epilogue.html
|
776
776
|
|
777
777
|
--exp-md (volflag exp_md) holds the list of placeholders which can be
|
778
778
|
expanded in READMEs, and --exp-lg (volflag exp_lg) likewise for logues;
|
@@ -888,7 +888,7 @@ def get_sects():
|
|
888
888
|
dedent(
|
889
889
|
"""
|
890
890
|
the mDNS protocol is multicast-based, which means there are thousands
|
891
|
-
of fun and
|
891
|
+
of fun and interesting ways for it to break unexpectedly
|
892
892
|
|
893
893
|
things to check if it does not work at all:
|
894
894
|
|
@@ -997,6 +997,7 @@ def add_upload(ap):
|
|
997
997
|
ap2.add_argument("--hardlink", action="store_true", help="enable hardlink-based dedup; will fallback on symlinks when that is impossible (across filesystems) (volflag=hardlink)")
|
998
998
|
ap2.add_argument("--hardlink-only", action="store_true", help="do not fallback to symlinks when a hardlink cannot be made (volflag=hardlinkonly)")
|
999
999
|
ap2.add_argument("--no-dupe", action="store_true", help="reject duplicate files during upload; only matches within the same volume (volflag=nodupe)")
|
1000
|
+
ap2.add_argument("--no-clone", action="store_true", help="do not use existing data on disk to satisfy dupe uploads; reduces server HDD reads in exchange for much more network load (volflag=noclone)")
|
1000
1001
|
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")
|
1001
1002
|
ap2.add_argument("--snap-wri", metavar="SEC", type=int, default=300, help="write upload state to ./hist/up2k.snap every \033[33mSEC\033[0m seconds; allows resuming incomplete uploads after a server crash")
|
1002
1003
|
ap2.add_argument("--snap-drop", metavar="MIN", type=float, default=1440.0, help="forget unfinished uploads after \033[33mMIN\033[0m minutes; impossible to resume them after that (360=6h, 1440=24h)")
|
@@ -1078,6 +1079,7 @@ def add_auth(ap):
|
|
1078
1079
|
ap2.add_argument("--ses-db", metavar="PATH", type=u, default=ses_db, help="where to store the sessions database (if you run multiple copyparty instances, make sure they use different DBs)")
|
1079
1080
|
ap2.add_argument("--ses-len", metavar="CHARS", type=int, default=20, help="session key length; default is 120 bits ((20//4)*4*6)")
|
1080
1081
|
ap2.add_argument("--no-ses", action="store_true", help="disable sessions; use plaintext passwords in cookies")
|
1082
|
+
ap2.add_argument("--ipu", metavar="CIDR=USR", type=u, action="append", help="users with IP matching \033[33mCIDR\033[0m are auto-authenticated as username \033[33mUSR\033[0m; example: [\033[32m172.16.24.0/24=dave]")
|
1081
1083
|
|
1082
1084
|
|
1083
1085
|
def add_chpw(ap):
|
@@ -1246,7 +1248,7 @@ def add_safety(ap):
|
|
1246
1248
|
ap2.add_argument("--no-dot-mv", action="store_true", help="disallow moving dotfiles; makes it impossible to move folders containing dotfiles")
|
1247
1249
|
ap2.add_argument("--no-dot-ren", action="store_true", help="disallow renaming dotfiles; makes it impossible to turn something into a dotfile")
|
1248
1250
|
ap2.add_argument("--no-logues", action="store_true", help="disable rendering .prologue/.epilogue.html into directory listings")
|
1249
|
-
ap2.add_argument("--no-readme", action="store_true", help="disable rendering readme.md into directory listings")
|
1251
|
+
ap2.add_argument("--no-readme", action="store_true", help="disable rendering readme/preadme.md into directory listings")
|
1250
1252
|
ap2.add_argument("--vague-403", action="store_true", help="send 404 instead of 403 (security through ambiguity, very enterprise)")
|
1251
1253
|
ap2.add_argument("--force-js", action="store_true", help="don't send folder listings as HTML, force clients to use the embedded json instead -- slight protection against misbehaving search engines which ignore \033[33m--no-robots\033[0m")
|
1252
1254
|
ap2.add_argument("--no-robots", action="store_true", help="adds http and html headers asking search engines to not index anything (volflag=norobots)")
|
@@ -1444,7 +1446,7 @@ def add_ui(ap, retry):
|
|
1444
1446
|
ap2.add_argument("--k304", metavar="NUM", type=int, default=0, help="configure the option to enable/disable k304 on the controlpanel (workaround for buggy reverse-proxies); [\033[32m0\033[0m] = hidden and default-off, [\033[32m1\033[0m] = visible and default-off, [\033[32m2\033[0m] = visible and default-on")
|
1445
1447
|
ap2.add_argument("--md-sbf", metavar="FLAGS", type=u, default="downloads forms popups scripts top-navigation-by-user-activation", help="list of capabilities to ALLOW for README.md docs (volflag=md_sbf); see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox")
|
1446
1448
|
ap2.add_argument("--lg-sbf", metavar="FLAGS", type=u, default="downloads forms popups scripts top-navigation-by-user-activation", help="list of capabilities to ALLOW for prologue/epilogue docs (volflag=lg_sbf)")
|
1447
|
-
ap2.add_argument("--no-sb-md", action="store_true", help="don't sandbox README.md documents (volflags: no_sb_md | sb_md)")
|
1449
|
+
ap2.add_argument("--no-sb-md", action="store_true", help="don't sandbox README/PREADME.md documents (volflags: no_sb_md | sb_md)")
|
1448
1450
|
ap2.add_argument("--no-sb-lg", action="store_true", help="don't sandbox prologue/epilogue docs (volflags: no_sb_lg | sb_lg); enables non-js support")
|
1449
1451
|
|
1450
1452
|
|
@@ -1468,6 +1470,7 @@ def add_debug(ap):
|
|
1468
1470
|
ap2.add_argument("--bak-flips", action="store_true", help="[up2k] if a client uploads a bitflipped/corrupted chunk, store a copy according to \033[33m--bf-nc\033[0m and \033[33m--bf-dir\033[0m")
|
1469
1471
|
ap2.add_argument("--bf-nc", metavar="NUM", type=int, default=200, help="bak-flips: stop if there's more than \033[33mNUM\033[0m files at \033[33m--kf-dir\033[0m already; default: 6.3 GiB max (200*32M)")
|
1470
1472
|
ap2.add_argument("--bf-dir", metavar="PATH", type=u, default="bf", help="bak-flips: store corrupted chunks at \033[33mPATH\033[0m; default: folder named 'bf' wherever copyparty was started")
|
1473
|
+
ap2.add_argument("--bf-log", metavar="PATH", type=u, default="", help="bak-flips: log corruption info to a textfile at \033[33mPATH\033[0m")
|
1471
1474
|
|
1472
1475
|
|
1473
1476
|
# fmt: on
|
copyparty/__version__.py
CHANGED
copyparty/authsrv.py
CHANGED
@@ -917,7 +917,7 @@ class AuthSrv(object):
|
|
917
917
|
|
918
918
|
for un, gn in un_gn:
|
919
919
|
# if ap/vp has a user/group placeholder, make sure to keep
|
920
|
-
# track so the same user/
|
920
|
+
# track so the same user/group is mapped when setting perms;
|
921
921
|
# otherwise clear un/gn to indicate it's a regular volume
|
922
922
|
|
923
923
|
src1 = src0.replace("${u}", un or "\n")
|
copyparty/cfg.py
CHANGED
@@ -13,6 +13,7 @@ def vf_bmap() :
|
|
13
13
|
"dav_rt": "davrt",
|
14
14
|
"ed": "dots",
|
15
15
|
"hardlink_only": "hardlinkonly",
|
16
|
+
"no_clone": "noclone",
|
16
17
|
"no_dirsz": "nodirsz",
|
17
18
|
"no_dupe": "nodupe",
|
18
19
|
"no_forget": "noforget",
|
@@ -135,7 +136,8 @@ flagcats = {
|
|
135
136
|
"hardlink": "enable hardlink-based file deduplication,\nwith fallback on symlinks when that is impossible",
|
136
137
|
"hardlinkonly": "dedup with hardlink only, never symlink;\nmake a full copy if hardlink is impossible",
|
137
138
|
"safededup": "verify on-disk data before using it for dedup",
|
138
|
-
"
|
139
|
+
"noclone": "take dupe data from clients, even if available on HDD",
|
140
|
+
"nodupe": "rejects existing files (instead of linking/cloning them)",
|
139
141
|
"sparse": "force use of sparse files, mainly for s3-backed storage",
|
140
142
|
"daw": "enable full WebDAV write support (dangerous);\nPUT-operations will now \033[1;31mOVERWRITE\033[0;35m existing files",
|
141
143
|
"nosub": "forces all uploads into the top folder of the vfs",
|
copyparty/ftpd.py
CHANGED
@@ -72,6 +72,7 @@ class FtpAuth(DummyAuthorizer):
|
|
72
72
|
else:
|
73
73
|
raise AuthenticationFailed("banned")
|
74
74
|
|
75
|
+
args = self.hub.args
|
75
76
|
asrv = self.hub.asrv
|
76
77
|
uname = "*"
|
77
78
|
if username != "anonymous":
|
@@ -82,6 +83,9 @@ class FtpAuth(DummyAuthorizer):
|
|
82
83
|
uname = zs
|
83
84
|
break
|
84
85
|
|
86
|
+
if args.ipu and uname == "*":
|
87
|
+
uname = args.ipu_iu[args.ipu_nm.map(ip)]
|
88
|
+
|
85
89
|
if not uname or not (asrv.vfs.aread.get(uname) or asrv.vfs.awrite.get(uname)):
|
86
90
|
g = self.hub.gpwd
|
87
91
|
if g.lim:
|
copyparty/httpcli.py
CHANGED
@@ -123,6 +123,10 @@ _ = (argparse, threading)
|
|
123
123
|
|
124
124
|
NO_CACHE = {"Cache-Control": "no-cache"}
|
125
125
|
|
126
|
+
LOGUES = [[0, ".prologue.html"], [1, ".epilogue.html"]]
|
127
|
+
|
128
|
+
READMES = [[0, ["preadme.md", "PREADME.md"]], [1, ["readme.md", "README.md"]]]
|
129
|
+
|
126
130
|
|
127
131
|
class HttpCli(object):
|
128
132
|
"""
|
@@ -580,6 +584,9 @@ class HttpCli(object):
|
|
580
584
|
or "*"
|
581
585
|
)
|
582
586
|
|
587
|
+
if self.args.ipu and self.uname == "*":
|
588
|
+
self.uname = self.conn.ipu_iu[self.conn.ipu_nm.map(self.ip)]
|
589
|
+
|
583
590
|
self.rvol = self.asrv.vfs.aread[self.uname]
|
584
591
|
self.wvol = self.asrv.vfs.awrite[self.uname]
|
585
592
|
self.avol = self.asrv.vfs.aadmin[self.uname]
|
@@ -2019,13 +2026,32 @@ class HttpCli(object):
|
|
2019
2026
|
return True
|
2020
2027
|
|
2021
2028
|
def bakflip(
|
2022
|
-
self,
|
2029
|
+
self,
|
2030
|
+
f ,
|
2031
|
+
ap ,
|
2032
|
+
ofs ,
|
2033
|
+
sz ,
|
2034
|
+
good_sha ,
|
2035
|
+
bad_sha ,
|
2036
|
+
flags ,
|
2023
2037
|
) :
|
2038
|
+
now = time.time()
|
2039
|
+
t = "bad-chunk: %.3f %s %s %d %s %s %s"
|
2040
|
+
t = t % (now, bad_sha, good_sha, ofs, self.ip, self.uname, ap)
|
2041
|
+
self.log(t, 5)
|
2042
|
+
|
2043
|
+
if self.args.bf_log:
|
2044
|
+
try:
|
2045
|
+
with open(self.args.bf_log, "ab+") as f2:
|
2046
|
+
f2.write((t + "\n").encode("utf-8", "replace"))
|
2047
|
+
except Exception as ex:
|
2048
|
+
self.log("append %s failed: %r" % (self.args.bf_log, ex))
|
2049
|
+
|
2024
2050
|
if not self.args.bak_flips or self.args.nw:
|
2025
2051
|
return
|
2026
2052
|
|
2027
2053
|
sdir = self.args.bf_dir
|
2028
|
-
fp = os.path.join(sdir,
|
2054
|
+
fp = os.path.join(sdir, bad_sha)
|
2029
2055
|
if bos.path.exists(fp):
|
2030
2056
|
return self.log("no bakflip; have it", 6)
|
2031
2057
|
|
@@ -2145,11 +2171,17 @@ class HttpCli(object):
|
|
2145
2171
|
except UnrecvEOF:
|
2146
2172
|
raise Pebkac(422, "client disconnected while posting JSON")
|
2147
2173
|
|
2148
|
-
self.log("decoding {} bytes of {} json".format(len(json_buf), enc))
|
2149
2174
|
try:
|
2150
2175
|
body = json.loads(json_buf.decode(enc, "replace"))
|
2176
|
+
try:
|
2177
|
+
zds = {k: v for k, v in body.items()}
|
2178
|
+
zds["hash"] = "%d chunks" % (len(body["hash"]))
|
2179
|
+
except:
|
2180
|
+
zds = body
|
2181
|
+
t = "POST len=%d type=%s ip=%s user=%s req=%r json=%s"
|
2182
|
+
self.log(t % (len(json_buf), enc, self.ip, self.uname, self.req, zds))
|
2151
2183
|
except:
|
2152
|
-
raise Pebkac(422, "you POSTed invalid json")
|
2184
|
+
raise Pebkac(422, "you POSTed %d bytes of invalid json" % (len(json_buf),))
|
2153
2185
|
|
2154
2186
|
# self.reply(b"cloudflare", 503)
|
2155
2187
|
# return True
|
@@ -2347,7 +2379,9 @@ class HttpCli(object):
|
|
2347
2379
|
|
2348
2380
|
if sha_b64 != chash:
|
2349
2381
|
try:
|
2350
|
-
self.bakflip(
|
2382
|
+
self.bakflip(
|
2383
|
+
f, path, cstart[0], post_sz, chash, sha_b64, vfs.flags
|
2384
|
+
)
|
2351
2385
|
except:
|
2352
2386
|
self.log("bakflip failed: " + min_ex())
|
2353
2387
|
|
@@ -2404,13 +2438,13 @@ class HttpCli(object):
|
|
2404
2438
|
finally:
|
2405
2439
|
if locked:
|
2406
2440
|
# now block until all chunks released+confirmed
|
2407
|
-
x = broker.ask("up2k.confirm_chunks", ptop, wark, locked)
|
2441
|
+
x = broker.ask("up2k.confirm_chunks", ptop, wark, written, locked)
|
2408
2442
|
num_left, t = x.get()
|
2409
2443
|
if num_left < 0:
|
2410
2444
|
self.loud_reply(t, status=500)
|
2411
2445
|
return False
|
2412
2446
|
t = "got %d more chunks, %d left"
|
2413
|
-
self.log(t % (len(
|
2447
|
+
self.log(t % (len(written), num_left), 6)
|
2414
2448
|
|
2415
2449
|
if num_left < 0:
|
2416
2450
|
raise Pebkac(500, "unconfirmed; see serverlog")
|
@@ -3022,7 +3056,7 @@ class HttpCli(object):
|
|
3022
3056
|
if ex.errno != errno.ENOENT:
|
3023
3057
|
raise
|
3024
3058
|
|
3025
|
-
# if file exists,
|
3059
|
+
# if file exists, check that timestamp matches the client's
|
3026
3060
|
if srv_lastmod >= 0:
|
3027
3061
|
same_lastmod = cli_lastmod3 in [-1, srv_lastmod3]
|
3028
3062
|
if not same_lastmod:
|
@@ -3233,7 +3267,7 @@ class HttpCli(object):
|
|
3233
3267
|
) :
|
3234
3268
|
logues = ["", ""]
|
3235
3269
|
if not self.args.no_logues:
|
3236
|
-
for n, fn in
|
3270
|
+
for n, fn in LOGUES:
|
3237
3271
|
if lnames is not None and fn not in lnames:
|
3238
3272
|
continue
|
3239
3273
|
fn = "%s/%s" % (abspath, fn)
|
@@ -3245,25 +3279,31 @@ class HttpCli(object):
|
|
3245
3279
|
logues[n], vn.flags.get("exp_lg") or []
|
3246
3280
|
)
|
3247
3281
|
|
3248
|
-
|
3249
|
-
if
|
3250
|
-
if
|
3251
|
-
|
3252
|
-
elif
|
3253
|
-
|
3282
|
+
readmes = ["", ""]
|
3283
|
+
for n, fns in [] if self.args.no_readme else READMES:
|
3284
|
+
if logues[n]:
|
3285
|
+
continue
|
3286
|
+
elif lnames is None:
|
3287
|
+
pass
|
3288
|
+
elif fns[0] in lnames:
|
3289
|
+
fns = [lnames[fns[0]]]
|
3254
3290
|
else:
|
3255
3291
|
fns = []
|
3256
3292
|
|
3293
|
+
txt = ""
|
3257
3294
|
for fn in fns:
|
3258
3295
|
fn = "%s/%s" % (abspath, fn)
|
3259
3296
|
if bos.path.isfile(fn):
|
3260
3297
|
with open(fsenc(fn), "rb") as f:
|
3261
|
-
|
3298
|
+
txt = f.read().decode("utf-8")
|
3262
3299
|
break
|
3263
|
-
if readme and "exp" in vn.flags:
|
3264
|
-
readme = self._expand(readme, vn.flags.get("exp_md") or [])
|
3265
3300
|
|
3266
|
-
|
3301
|
+
if txt and "exp" in vn.flags:
|
3302
|
+
txt = self._expand(txt, vn.flags.get("exp_md") or [])
|
3303
|
+
|
3304
|
+
readmes[n] = txt
|
3305
|
+
|
3306
|
+
return logues, readmes
|
3267
3307
|
|
3268
3308
|
def _expand(self, txt , phs ) :
|
3269
3309
|
for ph in phs:
|
@@ -4763,7 +4803,7 @@ class HttpCli(object):
|
|
4763
4803
|
|
4764
4804
|
fmt = fmt.format(len(nfmt.format(biggest)))
|
4765
4805
|
retl = [
|
4766
|
-
"#
|
4806
|
+
("# %s: %s" % (x, ls[x])).replace(r"</span> // <span>", " // ")
|
4767
4807
|
for x in ["acct", "perms", "srvinf"]
|
4768
4808
|
if x in ls
|
4769
4809
|
]
|
@@ -5116,9 +5156,9 @@ class HttpCli(object):
|
|
5116
5156
|
j2a["no_prism"] = True
|
5117
5157
|
|
5118
5158
|
if not self.can_read and not is_dk:
|
5119
|
-
logues,
|
5159
|
+
logues, readmes = self._add_logues(vn, abspath, None)
|
5120
5160
|
ls_ret["logues"] = j2a["logues"] = logues
|
5121
|
-
ls_ret["
|
5161
|
+
ls_ret["readmes"] = cgv["readmes"] = readmes
|
5122
5162
|
|
5123
5163
|
if is_ls:
|
5124
5164
|
return self.tx_ls(ls_ret)
|
@@ -5374,11 +5414,18 @@ class HttpCli(object):
|
|
5374
5414
|
else:
|
5375
5415
|
taglist = list(tagset)
|
5376
5416
|
|
5377
|
-
logues,
|
5417
|
+
logues, readmes = self._add_logues(vn, abspath, lnames)
|
5378
5418
|
ls_ret["logues"] = j2a["logues"] = logues
|
5379
|
-
ls_ret["
|
5419
|
+
ls_ret["readmes"] = cgv["readmes"] = readmes
|
5380
5420
|
|
5381
|
-
if
|
5421
|
+
if (
|
5422
|
+
not files
|
5423
|
+
and not dirs
|
5424
|
+
and not readmes[0]
|
5425
|
+
and not readmes[1]
|
5426
|
+
and not logues[0]
|
5427
|
+
and not logues[1]
|
5428
|
+
):
|
5382
5429
|
logues[1] = "this folder is empty"
|
5383
5430
|
|
5384
5431
|
if "descript.ion" in lnames and os.path.isfile(
|
@@ -5423,7 +5470,11 @@ class HttpCli(object):
|
|
5423
5470
|
if doc:
|
5424
5471
|
j2a["docname"] = doc
|
5425
5472
|
doctxt = None
|
5426
|
-
|
5473
|
+
dfn = lnames.get(doc.lower())
|
5474
|
+
if dfn and dfn != doc:
|
5475
|
+
# found Foo but want FOO
|
5476
|
+
dfn = next((x for x in files if x["name"] == doc), None)
|
5477
|
+
if dfn:
|
5427
5478
|
docpath = os.path.join(abspath, doc)
|
5428
5479
|
sz = bos.path.getsize(docpath)
|
5429
5480
|
if sz < 1024 * self.args.txt_max:
|
copyparty/httpconn.py
CHANGED
@@ -56,6 +56,8 @@ class HttpConn(object):
|
|
56
56
|
self.asrv = hsrv.asrv # mypy404
|
57
57
|
self.u2fh = hsrv.u2fh # mypy404
|
58
58
|
self.pipes = hsrv.pipes # mypy404
|
59
|
+
self.ipu_iu = hsrv.ipu_iu
|
60
|
+
self.ipu_nm = hsrv.ipu_nm
|
59
61
|
self.ipa_nm = hsrv.ipa_nm
|
60
62
|
self.xff_nm = hsrv.xff_nm
|
61
63
|
self.xff_lan = hsrv.xff_lan # type: ignore
|
copyparty/httpsrv.py
CHANGED
@@ -69,6 +69,7 @@ from .util import (
|
|
69
69
|
build_netmap,
|
70
70
|
has_resource,
|
71
71
|
ipnorm,
|
72
|
+
load_ipu,
|
72
73
|
load_resource,
|
73
74
|
min_ex,
|
74
75
|
shut_socket,
|
@@ -171,6 +172,11 @@ class HttpSrv(object):
|
|
171
172
|
self.j2 = {x: env.get_template(x + ".html") for x in jn}
|
172
173
|
self.prism = has_resource(self.E, "web/deps/prism.js.gz")
|
173
174
|
|
175
|
+
if self.args.ipu:
|
176
|
+
self.ipu_iu, self.ipu_nm = load_ipu(self.log, self.args.ipu)
|
177
|
+
else:
|
178
|
+
self.ipu_iu = self.ipu_nm = None
|
179
|
+
|
174
180
|
self.ipa_nm = build_netmap(self.args.ipa)
|
175
181
|
self.xff_nm = build_netmap(self.args.xff_src)
|
176
182
|
self.xff_lan = build_netmap("lan")
|
copyparty/mtag.py
CHANGED
@@ -467,7 +467,7 @@ class MTag(object):
|
|
467
467
|
sv = str(zv).split("/")[0].strip().lstrip("0")
|
468
468
|
ret[sk] = sv or 0
|
469
469
|
|
470
|
-
# normalize key notation to
|
470
|
+
# normalize key notation to rekobo
|
471
471
|
okey = ret.get("key")
|
472
472
|
if okey:
|
473
473
|
key = str(okey).replace(" ", "").replace("maj", "").replace("min", "m")
|
copyparty/ssdp.py
CHANGED
@@ -80,7 +80,7 @@ class SSDPr(object):
|
|
80
80
|
name = self.args.doctitle
|
81
81
|
zs = zs.strip().format(c(ubase), c(url), c(name), c(self.args.zsid))
|
82
82
|
hc.reply(zs.encode("utf-8", "replace"))
|
83
|
-
return False # close
|
83
|
+
return False # close connection
|
84
84
|
|
85
85
|
|
86
86
|
class SSDPd(MCast):
|
copyparty/svchub.py
CHANGED
@@ -54,6 +54,7 @@ from .util import (
|
|
54
54
|
alltrace,
|
55
55
|
ansi_re,
|
56
56
|
build_netmap,
|
57
|
+
load_ipu,
|
57
58
|
min_ex,
|
58
59
|
mp,
|
59
60
|
odfusion,
|
@@ -215,6 +216,11 @@ class SvcHub(object):
|
|
215
216
|
noch.update([x for x in zsl if x])
|
216
217
|
args.chpw_no = noch
|
217
218
|
|
219
|
+
if args.ipu:
|
220
|
+
iu, nm = load_ipu(self.log, args.ipu)
|
221
|
+
setattr(args, "ipu_iu", iu)
|
222
|
+
setattr(args, "ipu_nm", nm)
|
223
|
+
|
218
224
|
if not self.args.no_ses:
|
219
225
|
self.setup_session_db()
|
220
226
|
|