copyparty 1.15.10__py3-none-any.whl → 1.16.1__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/__init__.py +1 -0
- copyparty/__main__.py +17 -6
- copyparty/__version__.py +3 -3
- copyparty/authsrv.py +47 -21
- copyparty/broker_mp.py +40 -5
- copyparty/broker_mpw.py +20 -19
- copyparty/broker_thr.py +2 -2
- copyparty/cfg.py +4 -0
- copyparty/ftpd.py +1 -0
- copyparty/httpcli.py +159 -9
- copyparty/httpsrv.py +39 -0
- copyparty/metrics.py +3 -0
- copyparty/mtag.py +29 -0
- copyparty/pwhash.py +10 -8
- copyparty/svchub.py +16 -30
- copyparty/szip.py +1 -1
- copyparty/tcpsrv.py +2 -2
- copyparty/tftpd.py +1 -0
- copyparty/th_srv.py +10 -3
- copyparty/up2k.py +333 -64
- copyparty/util.py +45 -5
- copyparty/web/a/partyfuse.py +2 -1
- copyparty/web/a/u2c.py +20 -5
- copyparty/web/baguettebox.js.gz +0 -0
- copyparty/web/browser.css.gz +0 -0
- copyparty/web/browser.js.gz +0 -0
- copyparty/web/shares.js.gz +0 -0
- copyparty/web/splash.css.gz +0 -0
- copyparty/web/splash.html +12 -0
- copyparty/web/splash.js.gz +0 -0
- copyparty/web/ui.css.gz +0 -0
- copyparty/web/util.js.gz +0 -0
- {copyparty-1.15.10.dist-info → copyparty-1.16.1.dist-info}/METADATA +8 -4
- {copyparty-1.15.10.dist-info → copyparty-1.16.1.dist-info}/RECORD +38 -38
- {copyparty-1.15.10.dist-info → copyparty-1.16.1.dist-info}/WHEEL +1 -1
- {copyparty-1.15.10.dist-info → copyparty-1.16.1.dist-info}/LICENSE +0 -0
- {copyparty-1.15.10.dist-info → copyparty-1.16.1.dist-info}/entry_points.txt +0 -0
- {copyparty-1.15.10.dist-info → copyparty-1.16.1.dist-info}/top_level.txt +0 -0
copyparty/__init__.py
CHANGED
copyparty/__main__.py
CHANGED
@@ -50,6 +50,8 @@ from .util import (
|
|
50
50
|
PARTFTPY_VER,
|
51
51
|
PY_DESC,
|
52
52
|
PYFTPD_VER,
|
53
|
+
RAM_AVAIL,
|
54
|
+
RAM_TOTAL,
|
53
55
|
SQLITE_VER,
|
54
56
|
UNPLICATIONS,
|
55
57
|
Daemon,
|
@@ -676,6 +678,8 @@ def get_sects():
|
|
676
678
|
\033[36mxbu\033[35m executes CMD before a file upload starts
|
677
679
|
\033[36mxau\033[35m executes CMD after a file upload finishes
|
678
680
|
\033[36mxiu\033[35m executes CMD after all uploads finish and volume is idle
|
681
|
+
\033[36mxbc\033[35m executes CMD before a file copy
|
682
|
+
\033[36mxac\033[35m executes CMD after a file copy
|
679
683
|
\033[36mxbr\033[35m executes CMD before a file rename/move
|
680
684
|
\033[36mxar\033[35m executes CMD after a file rename/move
|
681
685
|
\033[36mxbd\033[35m executes CMD before a file delete
|
@@ -866,8 +870,9 @@ def get_sects():
|
|
866
870
|
use argon2id with timecost 3, 256 MiB, 4 threads, version 19 (0x13/v1.3)
|
867
871
|
|
868
872
|
\033[36m--ah-alg scrypt\033[0m # which is the same as:
|
869
|
-
\033[36m--ah-alg scrypt,13,2,8,4\033[0m
|
870
|
-
use scrypt with cost 2**13, 2 iterations, blocksize 8, 4 threads
|
873
|
+
\033[36m--ah-alg scrypt,13,2,8,4,32\033[0m
|
874
|
+
use scrypt with cost 2**13, 2 iterations, blocksize 8, 4 threads,
|
875
|
+
and allow using up to 32 MiB RAM (ram=cost*blksz roughly)
|
871
876
|
|
872
877
|
\033[36m--ah-alg sha2\033[0m # which is the same as:
|
873
878
|
\033[36m--ah-alg sha2,424242\033[0m
|
@@ -1193,6 +1198,8 @@ def add_hooks(ap):
|
|
1193
1198
|
ap2.add_argument("--xbu", metavar="CMD", type=u, action="append", help="execute \033[33mCMD\033[0m before a file upload starts")
|
1194
1199
|
ap2.add_argument("--xau", metavar="CMD", type=u, action="append", help="execute \033[33mCMD\033[0m after a file upload finishes")
|
1195
1200
|
ap2.add_argument("--xiu", metavar="CMD", type=u, action="append", help="execute \033[33mCMD\033[0m after all uploads finish and volume is idle")
|
1201
|
+
ap2.add_argument("--xbc", metavar="CMD", type=u, action="append", help="execute \033[33mCMD\033[0m before a file copy")
|
1202
|
+
ap2.add_argument("--xac", metavar="CMD", type=u, action="append", help="execute \033[33mCMD\033[0m after a file copy")
|
1196
1203
|
ap2.add_argument("--xbr", metavar="CMD", type=u, action="append", help="execute \033[33mCMD\033[0m before a file move/rename")
|
1197
1204
|
ap2.add_argument("--xar", metavar="CMD", type=u, action="append", help="execute \033[33mCMD\033[0m after a file move/rename")
|
1198
1205
|
ap2.add_argument("--xbd", metavar="CMD", type=u, action="append", help="execute \033[33mCMD\033[0m before a file delete")
|
@@ -1225,6 +1232,7 @@ def add_optouts(ap):
|
|
1225
1232
|
ap2.add_argument("--no-dav", action="store_true", help="disable webdav support")
|
1226
1233
|
ap2.add_argument("--no-del", action="store_true", help="disable delete operations")
|
1227
1234
|
ap2.add_argument("--no-mv", action="store_true", help="disable move/rename operations")
|
1235
|
+
ap2.add_argument("--no-cp", action="store_true", help="disable copy operations")
|
1228
1236
|
ap2.add_argument("-nth", action="store_true", help="no title hostname; don't show \033[33m--name\033[0m in <title>")
|
1229
1237
|
ap2.add_argument("-nih", action="store_true", help="no info hostname -- don't show in UI")
|
1230
1238
|
ap2.add_argument("-nid", action="store_true", help="no info disk-usage -- don't show in UI")
|
@@ -1308,9 +1316,12 @@ def add_admin(ap):
|
|
1308
1316
|
ap2.add_argument("--no-reload", action="store_true", help="disable ?reload=cfg (reload users/volumes/volflags from config file)")
|
1309
1317
|
ap2.add_argument("--no-rescan", action="store_true", help="disable ?scan (volume reindexing)")
|
1310
1318
|
ap2.add_argument("--no-stack", action="store_true", help="disable ?stack (list all stacks)")
|
1319
|
+
ap2.add_argument("--dl-list", metavar="LVL", type=int, default=2, help="who can see active downloads in the controlpanel? [\033[32m0\033[0m]=nobody, [\033[32m1\033[0m]=admins, [\033[32m2\033[0m]=everyone")
|
1311
1320
|
|
1312
1321
|
|
1313
1322
|
def add_thumbnail(ap):
|
1323
|
+
th_ram = (RAM_AVAIL or RAM_TOTAL or 9) * 0.6
|
1324
|
+
th_ram = int(max(min(th_ram, 6), 1) * 10) / 10
|
1314
1325
|
ap2 = ap.add_argument_group('thumbnail options')
|
1315
1326
|
ap2.add_argument("--no-thumb", action="store_true", help="disable all thumbnails (volflag=dthumb)")
|
1316
1327
|
ap2.add_argument("--no-vthumb", action="store_true", help="disable video thumbnails (volflag=dvthumb)")
|
@@ -1318,7 +1329,7 @@ def add_thumbnail(ap):
|
|
1318
1329
|
ap2.add_argument("--th-size", metavar="WxH", default="320x256", help="thumbnail res (volflag=thsize)")
|
1319
1330
|
ap2.add_argument("--th-mt", metavar="CORES", type=int, default=CORES, help="num cpu cores to use for generating thumbnails")
|
1320
1331
|
ap2.add_argument("--th-convt", metavar="SEC", type=float, default=60.0, help="conversion timeout in seconds (volflag=convt)")
|
1321
|
-
ap2.add_argument("--th-ram-max", metavar="GB", type=float, default=
|
1332
|
+
ap2.add_argument("--th-ram-max", metavar="GB", type=float, default=th_ram, help="max memory usage (GiB) permitted by thumbnailer; not very accurate")
|
1322
1333
|
ap2.add_argument("--th-crop", metavar="TXT", type=u, default="y", help="crop thumbnails to 4:3 or keep dynamic height; client can override in UI unless force. [\033[32my\033[0m]=crop, [\033[32mn\033[0m]=nocrop, [\033[32mfy\033[0m]=force-y, [\033[32mfn\033[0m]=force-n (volflag=crop)")
|
1323
1334
|
ap2.add_argument("--th-x3", metavar="TXT", type=u, default="n", help="show thumbs at 3x resolution; client can override in UI unless force. [\033[32my\033[0m]=yes, [\033[32mn\033[0m]=no, [\033[32mfy\033[0m]=force-yes, [\033[32mfn\033[0m]=force-no (volflag=th3x)")
|
1324
1335
|
ap2.add_argument("--th-dec", metavar="LIBS", default="vips,pil,ff", help="image decoders, in order of preference")
|
@@ -1333,12 +1344,12 @@ def add_thumbnail(ap):
|
|
1333
1344
|
# https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html
|
1334
1345
|
# https://github.com/libvips/libvips
|
1335
1346
|
# ffmpeg -hide_banner -demuxers | awk '/^ D /{print$2}' | while IFS= read -r x; do ffmpeg -hide_banner -h demuxer=$x; done | grep -E '^Demuxer |extensions:'
|
1336
|
-
ap2.add_argument("--th-r-pil", metavar="T,T", type=u, default="avif,avifs,blp,bmp,dcx,dds,dib,emf,eps,fits,flc,fli,fpx,gif,heic,heics,heif,heifs,icns,ico,im,j2p,j2k,jp2,jpeg,jpg,jpx,pbm,pcx,pgm,png,pnm,ppm,psd,qoi,sgi,spi,tga,tif,tiff,webp,wmf,xbm,xpm", help="image formats to decode using pillow")
|
1347
|
+
ap2.add_argument("--th-r-pil", metavar="T,T", type=u, default="avif,avifs,blp,bmp,cbz,dcx,dds,dib,emf,eps,fits,flc,fli,fpx,gif,heic,heics,heif,heifs,icns,ico,im,j2p,j2k,jp2,jpeg,jpg,jpx,pbm,pcx,pgm,png,pnm,ppm,psd,qoi,sgi,spi,tga,tif,tiff,webp,wmf,xbm,xpm", help="image formats to decode using pillow")
|
1337
1348
|
ap2.add_argument("--th-r-vips", metavar="T,T", type=u, default="avif,exr,fit,fits,fts,gif,hdr,heic,jp2,jpeg,jpg,jpx,jxl,nii,pfm,pgm,png,ppm,svg,tif,tiff,webp", help="image formats to decode using pyvips")
|
1338
|
-
ap2.add_argument("--th-r-ffi", metavar="T,T", type=u, default="apng,avif,avifs,bmp,dds,dib,fit,fits,fts,gif,hdr,heic,heics,heif,heifs,icns,ico,jp2,jpeg,jpg,jpx,jxl,pbm,pcx,pfm,pgm,png,pnm,ppm,psd,qoi,sgi,tga,tif,tiff,webp,xbm,xpm", help="image formats to decode using ffmpeg")
|
1349
|
+
ap2.add_argument("--th-r-ffi", metavar="T,T", type=u, default="apng,avif,avifs,bmp,cbz,dds,dib,fit,fits,fts,gif,hdr,heic,heics,heif,heifs,icns,ico,jp2,jpeg,jpg,jpx,jxl,pbm,pcx,pfm,pgm,png,pnm,ppm,psd,qoi,sgi,tga,tif,tiff,webp,xbm,xpm", help="image formats to decode using ffmpeg")
|
1339
1350
|
ap2.add_argument("--th-r-ffv", metavar="T,T", type=u, default="3gp,asf,av1,avc,avi,flv,h264,h265,hevc,m4v,mjpeg,mjpg,mkv,mov,mp4,mpeg,mpeg2,mpegts,mpg,mpg2,mts,nut,ogm,ogv,rm,ts,vob,webm,wmv", help="video formats to decode using ffmpeg")
|
1340
1351
|
ap2.add_argument("--th-r-ffa", metavar="T,T", type=u, default="aac,ac3,aif,aiff,alac,alaw,amr,apac,ape,au,bonk,dfpwm,dts,flac,gsm,ilbc,it,itgz,itxz,itz,m4a,mdgz,mdxz,mdz,mo3,mod,mp2,mp3,mpc,mptm,mt2,mulaw,ogg,okt,opus,ra,s3m,s3gz,s3xz,s3z,tak,tta,ulaw,wav,wma,wv,xm,xmgz,xmxz,xmz,xpk", help="audio formats to decode using ffmpeg")
|
1341
|
-
ap2.add_argument("--au-unpk", metavar="E=F.C", type=u, default="mdz=mod.zip, mdgz=mod.gz, mdxz=mod.xz, s3z=s3m.zip, s3gz=s3m.gz, s3xz=s3m.xz, xmz=xm.zip, xmgz=xm.gz, xmxz=xm.xz, itz=it.zip, itgz=it.gz, itxz=it.xz", help="audio formats to decompress before passing to ffmpeg")
|
1352
|
+
ap2.add_argument("--au-unpk", metavar="E=F.C", type=u, default="mdz=mod.zip, mdgz=mod.gz, mdxz=mod.xz, s3z=s3m.zip, s3gz=s3m.gz, s3xz=s3m.xz, xmz=xm.zip, xmgz=xm.gz, xmxz=xm.xz, itz=it.zip, itgz=it.gz, itxz=it.xz, cbz=jpg.cbz", help="audio/image formats to decompress before passing to ffmpeg")
|
1342
1353
|
|
1343
1354
|
|
1344
1355
|
def add_transcoding(ap):
|
copyparty/__version__.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
-
VERSION = (1,
|
4
|
-
CODENAME = "
|
5
|
-
BUILD_DT = (2024,
|
3
|
+
VERSION = (1, 16, 1)
|
4
|
+
CODENAME = "COPYparty"
|
5
|
+
BUILD_DT = (2024, 11, 15)
|
6
6
|
|
7
7
|
S_VERSION = ".".join(map(str, VERSION))
|
8
8
|
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
|
copyparty/authsrv.py
CHANGED
@@ -360,18 +360,19 @@ class VFS(object):
|
|
360
360
|
self.ahtml = {}
|
361
361
|
self.aadmin = {}
|
362
362
|
self.adot = {}
|
363
|
-
self.all_vols = {}
|
364
363
|
|
365
364
|
if realpath:
|
366
365
|
rp = realpath + ("" if realpath.endswith(os.sep) else os.sep)
|
367
366
|
vp = vpath + ("/" if vpath else "")
|
368
367
|
self.histpath = os.path.join(realpath, ".hist") # db / thumbcache
|
369
368
|
self.all_vols = {vpath: self} # flattened recursive
|
369
|
+
self.all_nodes = {vpath: self} # also jumpvols
|
370
370
|
self.all_aps = [(rp, self)]
|
371
371
|
self.all_vps = [(vp, self)]
|
372
372
|
else:
|
373
373
|
self.histpath = ""
|
374
374
|
self.all_vols = {}
|
375
|
+
self.all_nodes = {}
|
375
376
|
self.all_aps = []
|
376
377
|
self.all_vps = []
|
377
378
|
|
@@ -389,9 +390,11 @@ class VFS(object):
|
|
389
390
|
def get_all_vols(
|
390
391
|
self,
|
391
392
|
vols ,
|
393
|
+
nodes ,
|
392
394
|
aps ,
|
393
395
|
vps ,
|
394
396
|
) :
|
397
|
+
nodes[self.vpath] = self
|
395
398
|
if self.realpath:
|
396
399
|
vols[self.vpath] = self
|
397
400
|
rp = self.realpath
|
@@ -401,7 +404,7 @@ class VFS(object):
|
|
401
404
|
vps.append((vp, self))
|
402
405
|
|
403
406
|
for v in self.nodes.values():
|
404
|
-
v.get_all_vols(vols, aps, vps)
|
407
|
+
v.get_all_vols(vols, nodes, aps, vps)
|
405
408
|
|
406
409
|
def add(self, src , dst ) :
|
407
410
|
"""get existing, or add new path to the vfs"""
|
@@ -584,10 +587,11 @@ class VFS(object):
|
|
584
587
|
scandir ,
|
585
588
|
permsets ,
|
586
589
|
lstat = False,
|
590
|
+
throw = False,
|
587
591
|
) :
|
588
592
|
"""replaces _ls for certain shares (single-file, or file selection)"""
|
589
593
|
vn, rem = self.shr_src # type: ignore
|
590
|
-
abspath, real, _ = vn.ls(rem, "\n", scandir, permsets, lstat)
|
594
|
+
abspath, real, _ = vn.ls(rem, "\n", scandir, permsets, lstat, throw)
|
591
595
|
real = [x for x in real if os.path.basename(x[0]) in self.shr_files]
|
592
596
|
return abspath, real, {}
|
593
597
|
|
@@ -598,11 +602,12 @@ class VFS(object):
|
|
598
602
|
scandir ,
|
599
603
|
permsets ,
|
600
604
|
lstat = False,
|
605
|
+
throw = False,
|
601
606
|
) :
|
602
607
|
"""return user-readable [fsdir,real,virt] items at vpath"""
|
603
608
|
virt_vis = {} # nodes readable by user
|
604
609
|
abspath = self.canonical(rem)
|
605
|
-
real = list(statdir(self.log, scandir, lstat, abspath))
|
610
|
+
real = list(statdir(self.log, scandir, lstat, abspath, throw))
|
606
611
|
real.sort()
|
607
612
|
if not rem:
|
608
613
|
# no vfs nodes in the list of real inodes
|
@@ -664,6 +669,10 @@ class VFS(object):
|
|
664
669
|
"""
|
665
670
|
recursively yields from ./rem;
|
666
671
|
rel is a unix-style user-defined vpath (not vfs-related)
|
672
|
+
|
673
|
+
NOTE: don't invoke this function from a dbv; subvols are only
|
674
|
+
descended into if rem is blank due to the _ls `if not rem:`
|
675
|
+
which intention is to prevent unintended access to subvols
|
667
676
|
"""
|
668
677
|
|
669
678
|
fsroot, vfs_ls, vfs_virt = self.ls(rem, uname, scandir, permsets, lstat=lstat)
|
@@ -904,7 +913,7 @@ class AuthSrv(object):
|
|
904
913
|
self._reload()
|
905
914
|
return True
|
906
915
|
|
907
|
-
broker.ask("
|
916
|
+
broker.ask("reload", False, True).get()
|
908
917
|
return True
|
909
918
|
|
910
919
|
def _map_volume_idp(
|
@@ -1374,7 +1383,7 @@ class AuthSrv(object):
|
|
1374
1383
|
flags[name] = True
|
1375
1384
|
return
|
1376
1385
|
|
1377
|
-
zs = "mtp on403 on404 xbu xau xiu xbr xar xbd xad xm xban"
|
1386
|
+
zs = "mtp on403 on404 xbu xau xiu xbc xac xbr xar xbd xad xm xban"
|
1378
1387
|
if name not in zs.split():
|
1379
1388
|
if value is True:
|
1380
1389
|
t = "└─add volflag [{}] = {} ({})"
|
@@ -1522,10 +1531,11 @@ class AuthSrv(object):
|
|
1522
1531
|
|
1523
1532
|
assert vfs # type: ignore
|
1524
1533
|
vfs.all_vols = {}
|
1534
|
+
vfs.all_nodes = {}
|
1525
1535
|
vfs.all_aps = []
|
1526
1536
|
vfs.all_vps = []
|
1527
|
-
vfs.get_all_vols(vfs.all_vols, vfs.all_aps, vfs.all_vps)
|
1528
|
-
for vol in vfs.
|
1537
|
+
vfs.get_all_vols(vfs.all_vols, vfs.all_nodes, vfs.all_aps, vfs.all_vps)
|
1538
|
+
for vol in vfs.all_nodes.values():
|
1529
1539
|
vol.all_aps.sort(key=lambda x: len(x[0]), reverse=True)
|
1530
1540
|
vol.all_vps.sort(key=lambda x: len(x[0]), reverse=True)
|
1531
1541
|
vol.root = vfs
|
@@ -1576,7 +1586,7 @@ class AuthSrv(object):
|
|
1576
1586
|
|
1577
1587
|
vfs.nodes[shr] = vfs.all_vols[shr] = shv
|
1578
1588
|
for vol in shv.nodes.values():
|
1579
|
-
vfs.all_vols[vol.vpath] = vol
|
1589
|
+
vfs.all_vols[vol.vpath] = vfs.all_nodes[vol.vpath] = vol
|
1580
1590
|
vol.get_dbv = vol._get_share_src
|
1581
1591
|
vol.ls = vol._ls_nope
|
1582
1592
|
|
@@ -1719,7 +1729,19 @@ class AuthSrv(object):
|
|
1719
1729
|
|
1720
1730
|
self.log("\n\n".join(ta) + "\n", c=3)
|
1721
1731
|
|
1722
|
-
|
1732
|
+
rhisttab = {}
|
1733
|
+
vfs.histtab = {}
|
1734
|
+
for zv in vfs.all_vols.values():
|
1735
|
+
histp = zv.histpath
|
1736
|
+
is_shr = shr and zv.vpath.split("/")[0] == shr
|
1737
|
+
if histp and not is_shr and histp in rhisttab:
|
1738
|
+
zv2 = rhisttab[histp]
|
1739
|
+
t = "invalid config; multiple volumes share the same histpath (database location):\n histpath: %s\n volume 1: /%s [%s]\n volume 2: %s [%s]"
|
1740
|
+
t = t % (histp, zv2.vpath, zv2.realpath, zv.vpath, zv.realpath)
|
1741
|
+
self.log(t, 1)
|
1742
|
+
raise Exception(t)
|
1743
|
+
rhisttab[histp] = zv
|
1744
|
+
vfs.histtab[zv.realpath] = histp
|
1723
1745
|
|
1724
1746
|
for vol in vfs.all_vols.values():
|
1725
1747
|
lim = Lim(self.log_func)
|
@@ -1778,12 +1800,12 @@ class AuthSrv(object):
|
|
1778
1800
|
vol.lim = lim
|
1779
1801
|
|
1780
1802
|
if self.args.no_robots:
|
1781
|
-
for vol in vfs.
|
1803
|
+
for vol in vfs.all_nodes.values():
|
1782
1804
|
# volflag "robots" overrides global "norobots", allowing indexing by search engines for this vol
|
1783
1805
|
if not vol.flags.get("robots"):
|
1784
1806
|
vol.flags["norobots"] = True
|
1785
1807
|
|
1786
|
-
for vol in vfs.
|
1808
|
+
for vol in vfs.all_nodes.values():
|
1787
1809
|
if self.args.no_vthumb:
|
1788
1810
|
vol.flags["dvthumb"] = True
|
1789
1811
|
if self.args.no_athumb:
|
@@ -1795,7 +1817,7 @@ class AuthSrv(object):
|
|
1795
1817
|
vol.flags["dithumb"] = True
|
1796
1818
|
|
1797
1819
|
have_fk = False
|
1798
|
-
for vol in vfs.
|
1820
|
+
for vol in vfs.all_nodes.values():
|
1799
1821
|
fk = vol.flags.get("fk")
|
1800
1822
|
fka = vol.flags.get("fka")
|
1801
1823
|
if fka and not fk:
|
@@ -1827,7 +1849,7 @@ class AuthSrv(object):
|
|
1827
1849
|
zs = os.path.join(E.cfg, "fk-salt.txt")
|
1828
1850
|
self.log(t % (fk_len, 16, zs), 3)
|
1829
1851
|
|
1830
|
-
for vol in vfs.
|
1852
|
+
for vol in vfs.all_nodes.values():
|
1831
1853
|
if "pk" in vol.flags and "gz" not in vol.flags and "xz" not in vol.flags:
|
1832
1854
|
vol.flags["gz"] = False # def.pk
|
1833
1855
|
|
@@ -1838,7 +1860,7 @@ class AuthSrv(object):
|
|
1838
1860
|
|
1839
1861
|
all_mte = {}
|
1840
1862
|
errors = False
|
1841
|
-
for vol in vfs.
|
1863
|
+
for vol in vfs.all_nodes.values():
|
1842
1864
|
if (self.args.e2ds and vol.axs.uwrite) or self.args.e2dsa:
|
1843
1865
|
vol.flags["e2ds"] = True
|
1844
1866
|
|
@@ -1929,7 +1951,7 @@ class AuthSrv(object):
|
|
1929
1951
|
vol.flags[k] = odfusion(getattr(self.args, k), vol.flags[k])
|
1930
1952
|
|
1931
1953
|
# append additive args from argv to volflags
|
1932
|
-
hooks = "xbu xau xiu xbr xar xbd xad xm xban".split()
|
1954
|
+
hooks = "xbu xau xiu xbc xac xbr xar xbd xad xm xban".split()
|
1933
1955
|
for name in "mtp on404 on403".split() + hooks:
|
1934
1956
|
self._read_volflag(vol.flags, name, getattr(self.args, name), True)
|
1935
1957
|
|
@@ -2056,7 +2078,7 @@ class AuthSrv(object):
|
|
2056
2078
|
errors = True
|
2057
2079
|
|
2058
2080
|
have_daw = False
|
2059
|
-
for vol in vfs.
|
2081
|
+
for vol in vfs.all_nodes.values():
|
2060
2082
|
daw = vol.flags.get("daw") or self.args.daw
|
2061
2083
|
if daw:
|
2062
2084
|
vol.flags["daw"] = True
|
@@ -2071,13 +2093,12 @@ class AuthSrv(object):
|
|
2071
2093
|
self.log("--smb can only be used when --ah-alg is none", 1)
|
2072
2094
|
errors = True
|
2073
2095
|
|
2074
|
-
for vol in vfs.
|
2096
|
+
for vol in vfs.all_nodes.values():
|
2075
2097
|
for k in list(vol.flags.keys()):
|
2076
2098
|
if re.match("^-[^-]+$", k):
|
2077
2099
|
vol.flags.pop(k[1:], None)
|
2078
2100
|
vol.flags.pop(k)
|
2079
2101
|
|
2080
|
-
for vol in vfs.all_vols.values():
|
2081
2102
|
if vol.flags.get("dots"):
|
2082
2103
|
for name in vol.axs.uread:
|
2083
2104
|
vol.axs.udot.add(name)
|
@@ -2219,6 +2240,11 @@ class AuthSrv(object):
|
|
2219
2240
|
for x, y in vfs.all_vols.items()
|
2220
2241
|
if x != shr and not x.startswith(shrs)
|
2221
2242
|
}
|
2243
|
+
vfs.all_nodes = {
|
2244
|
+
x: y
|
2245
|
+
for x, y in vfs.all_nodes.items()
|
2246
|
+
if x != shr and not x.startswith(shrs)
|
2247
|
+
}
|
2222
2248
|
|
2223
2249
|
assert db and cur and cur2 and shv # type: ignore
|
2224
2250
|
for row in cur.execute("select * from sh"):
|
@@ -2380,7 +2406,7 @@ class AuthSrv(object):
|
|
2380
2406
|
self._reload()
|
2381
2407
|
return True, "new password OK"
|
2382
2408
|
|
2383
|
-
broker.ask("
|
2409
|
+
broker.ask("reload", False, False).get()
|
2384
2410
|
return True, "new password OK"
|
2385
2411
|
|
2386
2412
|
def setup_chpw(self, acct ) :
|
@@ -2632,7 +2658,7 @@ class AuthSrv(object):
|
|
2632
2658
|
]
|
2633
2659
|
|
2634
2660
|
csv = set("i p th_covers zm_on zm_off zs_on zs_off".split())
|
2635
|
-
zs = "c ihead ohead mtm mtp on403 on404 xad xar xau xiu xban xbd xbr xbu xm"
|
2661
|
+
zs = "c ihead ohead mtm mtp on403 on404 xac xad xar xau xiu xban xbc xbd xbr xbu xm"
|
2636
2662
|
lst = set(zs.split())
|
2637
2663
|
askip = set("a v c vc cgen exp_lg exp_md theme".split())
|
2638
2664
|
fskip = set("exp_lg exp_md mv_re_r mv_re_t rm_re_r rm_re_t".split())
|
copyparty/broker_mp.py
CHANGED
@@ -39,6 +39,9 @@ class BrokerMp(object):
|
|
39
39
|
self.procs = []
|
40
40
|
self.mutex = threading.Lock()
|
41
41
|
|
42
|
+
self.retpend = {}
|
43
|
+
self.retpend_mutex = threading.Lock()
|
44
|
+
|
42
45
|
self.num_workers = self.args.j or CORES
|
43
46
|
self.log("broker", "booting {} subprocesses".format(self.num_workers))
|
44
47
|
for n in range(1, self.num_workers + 1):
|
@@ -50,6 +53,8 @@ class BrokerMp(object):
|
|
50
53
|
self.procs.append(proc)
|
51
54
|
proc.start()
|
52
55
|
|
56
|
+
Daemon(self.periodic, "mp-periodic")
|
57
|
+
|
53
58
|
def shutdown(self) :
|
54
59
|
self.log("broker", "shutting down")
|
55
60
|
for n, proc in enumerate(self.procs):
|
@@ -86,8 +91,10 @@ class BrokerMp(object):
|
|
86
91
|
self.log(*args)
|
87
92
|
|
88
93
|
elif dest == "retq":
|
89
|
-
|
90
|
-
|
94
|
+
with self.retpend_mutex:
|
95
|
+
retq = self.retpend.pop(retq_id)
|
96
|
+
|
97
|
+
retq.put(args[0])
|
91
98
|
|
92
99
|
else:
|
93
100
|
# new ipc invoking managed service in hub
|
@@ -105,7 +112,6 @@ class BrokerMp(object):
|
|
105
112
|
proc.q_pend.put((retq_id, "retq", rv))
|
106
113
|
|
107
114
|
def ask(self, dest , *args ) :
|
108
|
-
|
109
115
|
# new non-ipc invoking managed service in hub
|
110
116
|
obj = self.hub
|
111
117
|
for node in dest.split("."):
|
@@ -117,17 +123,30 @@ class BrokerMp(object):
|
|
117
123
|
retq.put(rv)
|
118
124
|
return retq
|
119
125
|
|
126
|
+
def wask(self, dest , *args ) :
|
127
|
+
# call from hub to workers
|
128
|
+
ret = []
|
129
|
+
for p in self.procs:
|
130
|
+
retq = ExceptionalQueue(1)
|
131
|
+
retq_id = id(retq)
|
132
|
+
with self.retpend_mutex:
|
133
|
+
self.retpend[retq_id] = retq
|
134
|
+
|
135
|
+
p.q_pend.put((retq_id, dest, list(args)))
|
136
|
+
ret.append(retq)
|
137
|
+
return ret
|
138
|
+
|
120
139
|
def say(self, dest , *args ) :
|
121
140
|
"""
|
122
141
|
send message to non-hub component in other process,
|
123
142
|
returns a Queue object which eventually contains the response if want_retval
|
124
143
|
(not-impl here since nothing uses it yet)
|
125
144
|
"""
|
126
|
-
if dest == "listen":
|
145
|
+
if dest == "httpsrv.listen":
|
127
146
|
for p in self.procs:
|
128
147
|
p.q_pend.put((0, dest, [args[0], len(self.procs)]))
|
129
148
|
|
130
|
-
elif dest == "set_netdevs":
|
149
|
+
elif dest == "httpsrv.set_netdevs":
|
131
150
|
for p in self.procs:
|
132
151
|
p.q_pend.put((0, dest, list(args)))
|
133
152
|
|
@@ -136,3 +155,19 @@ class BrokerMp(object):
|
|
136
155
|
|
137
156
|
else:
|
138
157
|
raise Exception("what is " + str(dest))
|
158
|
+
|
159
|
+
def periodic(self) :
|
160
|
+
while True:
|
161
|
+
time.sleep(1)
|
162
|
+
|
163
|
+
tdli = {}
|
164
|
+
tdls = {}
|
165
|
+
qs = self.wask("httpsrv.read_dls")
|
166
|
+
for q in qs:
|
167
|
+
qr = q.get()
|
168
|
+
dli, dls = qr
|
169
|
+
tdli.update(dli)
|
170
|
+
tdls.update(dls)
|
171
|
+
tdl = (tdli, tdls)
|
172
|
+
for p in self.procs:
|
173
|
+
p.q_pend.put((0, "httpsrv.write_dls", tdl))
|
copyparty/broker_mpw.py
CHANGED
@@ -76,37 +76,38 @@ class MpWorker(BrokerCli):
|
|
76
76
|
while True:
|
77
77
|
retq_id, dest, args = self.q_pend.get()
|
78
78
|
|
79
|
-
|
79
|
+
if dest == "retq":
|
80
|
+
# response from previous ipc call
|
81
|
+
with self.retpend_mutex:
|
82
|
+
retq = self.retpend.pop(retq_id)
|
83
|
+
|
84
|
+
retq.put(args)
|
85
|
+
continue
|
86
|
+
|
80
87
|
if dest == "shutdown":
|
81
88
|
self.httpsrv.shutdown()
|
82
89
|
self.logw("ok bye")
|
83
90
|
sys.exit(0)
|
84
91
|
return
|
85
92
|
|
86
|
-
|
93
|
+
if dest == "reload":
|
87
94
|
self.logw("mpw.asrv reloading")
|
88
95
|
self.asrv.reload()
|
89
96
|
self.logw("mpw.asrv reloaded")
|
97
|
+
continue
|
90
98
|
|
91
|
-
|
99
|
+
if dest == "reload_sessions":
|
92
100
|
with self.asrv.mutex:
|
93
101
|
self.asrv.load_sessions()
|
102
|
+
continue
|
94
103
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
elif dest == "set_netdevs":
|
99
|
-
self.httpsrv.set_netdevs(args[0])
|
104
|
+
obj = self
|
105
|
+
for node in dest.split("."):
|
106
|
+
obj = getattr(obj, node)
|
100
107
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
retq = self.retpend.pop(retq_id)
|
105
|
-
|
106
|
-
retq.put(args)
|
107
|
-
|
108
|
-
else:
|
109
|
-
raise Exception("what is " + str(dest))
|
108
|
+
rv = obj(*args) # type: ignore
|
109
|
+
if retq_id:
|
110
|
+
self.say("retq", rv, retq_id=retq_id)
|
110
111
|
|
111
112
|
def ask(self, dest , *args ) :
|
112
113
|
retq = ExceptionalQueue(1)
|
@@ -117,5 +118,5 @@ class MpWorker(BrokerCli):
|
|
117
118
|
self.q_yield.put((retq_id, dest, list(args)))
|
118
119
|
return retq
|
119
120
|
|
120
|
-
def say(self, dest , *args ) :
|
121
|
-
self.q_yield.put((
|
121
|
+
def say(self, dest , *args , retq_id=0) :
|
122
|
+
self.q_yield.put((retq_id, dest, list(args)))
|
copyparty/broker_thr.py
CHANGED
@@ -49,11 +49,11 @@ class BrokerThr(BrokerCli):
|
|
49
49
|
return NotExQueue(obj(*args)) # type: ignore
|
50
50
|
|
51
51
|
def say(self, dest , *args ) :
|
52
|
-
if dest == "listen":
|
52
|
+
if dest == "httpsrv.listen":
|
53
53
|
self.httpsrv.listen(args[0], 1)
|
54
54
|
return
|
55
55
|
|
56
|
-
if dest == "set_netdevs":
|
56
|
+
if dest == "httpsrv.set_netdevs":
|
57
57
|
self.httpsrv.set_netdevs(args[0])
|
58
58
|
return
|
59
59
|
|
copyparty/cfg.py
CHANGED
@@ -103,10 +103,12 @@ def vf_cmap() :
|
|
103
103
|
"mte",
|
104
104
|
"mth",
|
105
105
|
"mtp",
|
106
|
+
"xac",
|
106
107
|
"xad",
|
107
108
|
"xar",
|
108
109
|
"xau",
|
109
110
|
"xban",
|
111
|
+
"xbc",
|
110
112
|
"xbd",
|
111
113
|
"xbr",
|
112
114
|
"xbu",
|
@@ -212,6 +214,8 @@ flagcats = {
|
|
212
214
|
"xbu=CMD": "execute CMD before a file upload starts",
|
213
215
|
"xau=CMD": "execute CMD after a file upload finishes",
|
214
216
|
"xiu=CMD": "execute CMD after all uploads finish and volume is idle",
|
217
|
+
"xbc=CMD": "execute CMD before a file copy",
|
218
|
+
"xac=CMD": "execute CMD after a file copy",
|
215
219
|
"xbr=CMD": "execute CMD before a file rename/move",
|
216
220
|
"xar=CMD": "execute CMD after a file rename/move",
|
217
221
|
"xbd=CMD": "execute CMD before a file delete",
|