copyparty 1.18.1__tar.gz → 1.18.3__tar.gz
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-1.18.1 → copyparty-1.18.3}/PKG-INFO +3 -1
- {copyparty-1.18.1 → copyparty-1.18.3}/README.md +2 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/__main__.py +41 -1
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/__version__.py +2 -2
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/authsrv.py +75 -12
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/bos/bos.py +18 -6
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/cfg.py +6 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/ftpd.py +9 -4
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/httpcli.py +36 -16
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/smbd.py +2 -2
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/svchub.py +5 -1
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/tcpsrv.py +1 -1
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/tftpd.py +6 -2
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/th_srv.py +3 -2
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/up2k.py +36 -11
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/util.py +9 -2
- copyparty-1.18.3/copyparty/web/baguettebox.js.gz +0 -0
- copyparty-1.18.3/copyparty/web/browser.css.gz +0 -0
- copyparty-1.18.3/copyparty/web/browser.js.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty.egg-info/PKG-INFO +3 -1
- copyparty-1.18.1/copyparty/web/baguettebox.js.gz +0 -0
- copyparty-1.18.1/copyparty/web/browser.css.gz +0 -0
- copyparty-1.18.1/copyparty/web/browser.js.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/LICENSE +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/__init__.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/bos/__init__.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/bos/path.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/broker_mp.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/broker_mpw.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/broker_thr.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/broker_util.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/cert.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/dxml.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/fsutil.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/httpconn.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/httpsrv.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/ico.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/mdns.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/metrics.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/mtag.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/multicast.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/pwhash.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/res/COPYING.txt +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/res/__init__.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/res/insecure.pem +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/ssdp.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/star.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/stolen/__init__.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/stolen/dnslib/__init__.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/stolen/dnslib/bimap.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/stolen/dnslib/bit.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/stolen/dnslib/buffer.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/stolen/dnslib/dns.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/stolen/dnslib/label.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/stolen/dnslib/lex.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/stolen/dnslib/ranges.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/stolen/ifaddr/__init__.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/stolen/ifaddr/_posix.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/stolen/ifaddr/_shared.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/stolen/ifaddr/_win32.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/stolen/qrcodegen.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/stolen/surrogateescape.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/sutil.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/szip.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/th_cli.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/u2idx.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/a/__init__.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/a/partyfuse.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/a/u2c.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/a/webdav-cfg.bat +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/browser.html +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/browser2.html +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/cf.html +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/dbg-audio.js.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/dd/2.png +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/dd/3.png +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/dd/4.png +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/dd/5.png +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/dd/__init__.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/deps/__init__.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/deps/busy.mp3.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/deps/easymde.css.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/deps/easymde.js.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/deps/fuse.py +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/deps/marked.js.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/deps/mini-fa.css.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/deps/mini-fa.woff +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/deps/prism.css.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/deps/prism.js.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/deps/prismd.css.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/deps/scp.woff2 +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/deps/sha512.ac.js.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/deps/sha512.hw.js.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/idp.html +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/md.css.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/md.html +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/md.js.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/md2.css.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/md2.js.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/mde.css.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/mde.html +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/mde.js.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/msg.css.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/msg.html +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/rups.css.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/rups.html +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/rups.js.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/shares.css.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/shares.html +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/shares.js.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/splash.css.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/splash.html +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/splash.js.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/svcs.html +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/svcs.js.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/ui.css.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/up2k.js.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/util.js.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty/web/w.hash.js.gz +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty.egg-info/SOURCES.txt +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty.egg-info/dependency_links.txt +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty.egg-info/entry_points.txt +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty.egg-info/requires.txt +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/copyparty.egg-info/top_level.txt +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/pyproject.toml +0 -0
- {copyparty-1.18.1 → copyparty-1.18.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: copyparty
|
3
|
-
Version: 1.18.
|
3
|
+
Version: 1.18.3
|
4
4
|
Summary: Portable file server with accelerated resumable uploads, deduplication, WebDAV, FTP, zeroconf, media indexer, video thumbnails, audio transcoding, and write-only folders
|
5
5
|
Author-email: ed <copyparty@ocv.me>
|
6
6
|
License: MIT
|
@@ -2422,8 +2422,10 @@ TLDR: yes
|
|
2422
2422
|
| send message | yep | yep | yep | yep | yep | yep | yep | yep |
|
2423
2423
|
| set sort order | - | yep | yep | yep | yep | yep | yep | yep |
|
2424
2424
|
| zip selection | - | yep | yep | yep | yep | yep | yep | yep |
|
2425
|
+
| file search | - | yep | yep | yep | yep | yep | yep | yep |
|
2425
2426
|
| file rename | - | yep | yep | yep | yep | yep | yep | yep |
|
2426
2427
|
| file cut/paste | - | yep | yep | yep | yep | yep | yep | yep |
|
2428
|
+
| unpost uploads | - | - | yep | yep | yep | yep | yep | yep |
|
2427
2429
|
| navpane | - | yep | yep | yep | yep | yep | yep | yep |
|
2428
2430
|
| image viewer | - | yep | yep | yep | yep | yep | yep | yep |
|
2429
2431
|
| video player | - | yep | yep | yep | yep | yep | yep | yep |
|
@@ -2364,8 +2364,10 @@ TLDR: yes
|
|
2364
2364
|
| send message | yep | yep | yep | yep | yep | yep | yep | yep |
|
2365
2365
|
| set sort order | - | yep | yep | yep | yep | yep | yep | yep |
|
2366
2366
|
| zip selection | - | yep | yep | yep | yep | yep | yep | yep |
|
2367
|
+
| file search | - | yep | yep | yep | yep | yep | yep | yep |
|
2367
2368
|
| file rename | - | yep | yep | yep | yep | yep | yep | yep |
|
2368
2369
|
| file cut/paste | - | yep | yep | yep | yep | yep | yep | yep |
|
2370
|
+
| unpost uploads | - | - | yep | yep | yep | yep | yep | yep |
|
2369
2371
|
| navpane | - | yep | yep | yep | yep | yep | yep | yep |
|
2370
2372
|
| image viewer | - | yep | yep | yep | yep | yep | yep | yep |
|
2371
2373
|
| video player | - | yep | yep | yep | yep | yep | yep | yep |
|
@@ -855,6 +855,43 @@ def get_sects():
|
|
855
855
|
"""
|
856
856
|
),
|
857
857
|
],
|
858
|
+
[
|
859
|
+
"chmod",
|
860
|
+
"file/folder permissions",
|
861
|
+
dedent(
|
862
|
+
"""
|
863
|
+
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
|
864
|
+
|
865
|
+
similarly, \033[33m--chmod-d\033[0m and \033[33mchmod_d\033[0m sets the directory/folder perm
|
866
|
+
|
867
|
+
the value is a three-digit octal number such as 755, 750, 644, etc.
|
868
|
+
|
869
|
+
first digit = "User"; permission for the unix-user
|
870
|
+
second digit = "Group"; permission for the unix-group
|
871
|
+
third digit = "Other"; permission for all other users/groups
|
872
|
+
|
873
|
+
for files:
|
874
|
+
0 = --- = no access
|
875
|
+
1 = --x = can execute the file as a program
|
876
|
+
2 = -w- = can write
|
877
|
+
3 = -wx = can write and execute
|
878
|
+
4 = r-- = can read
|
879
|
+
5 = r-x = can read and execute
|
880
|
+
6 = rw- = can read and write
|
881
|
+
7 = rwx = can read, write, execute
|
882
|
+
|
883
|
+
for directories/folders:
|
884
|
+
0 = --- = no access
|
885
|
+
1 = --x = can read files in folder but not list contents
|
886
|
+
2 = -w- = n/a
|
887
|
+
3 = -wx = can create files but not list
|
888
|
+
4 = r-- = can list, but not read/write
|
889
|
+
5 = r-x = can list and read files
|
890
|
+
6 = rw- = n/a
|
891
|
+
7 = rwx = can read, write, list
|
892
|
+
"""
|
893
|
+
),
|
894
|
+
],
|
858
895
|
[
|
859
896
|
"pwhash",
|
860
897
|
"password hashing",
|
@@ -1005,6 +1042,8 @@ def add_upload(ap):
|
|
1005
1042
|
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")
|
1006
1043
|
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)")
|
1007
1044
|
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, ...)")
|
1045
|
+
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)")
|
1046
|
+
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)")
|
1008
1047
|
ap2.add_argument("--dedup", action="store_true", help="enable symlink-based upload deduplication (volflag=dedup)")
|
1009
1048
|
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)")
|
1010
1049
|
ap2.add_argument("--hardlink", action="store_true", help="enable hardlink-based dedup; will fallback on symlinks when that is impossible (across filesystems) (volflag=hardlink)")
|
@@ -1041,7 +1080,7 @@ def add_network(ap):
|
|
1041
1080
|
ap2.add_argument("--rp-loc", metavar="PATH", type=u, default="", help="if reverse-proxying on a location instead of a dedicated domain/subdomain, provide the base location here; example: [\033[32m/foo/bar\033[0m]")
|
1042
1081
|
if ANYWIN:
|
1043
1082
|
ap2.add_argument("--reuseaddr", action="store_true", help="set reuseaddr on listening sockets on windows; allows rapid restart of copyparty at the expense of being able to accidentally start multiple instances")
|
1044
|
-
|
1083
|
+
elif not MACOS:
|
1045
1084
|
ap2.add_argument("--freebind", action="store_true", help="allow listening on IPs which do not yet exist, for example if the network interfaces haven't finished going up. Only makes sense for IPs other than '0.0.0.0', '127.0.0.1', '::', and '::1'. May require running as root (unless net.ipv6.ip_nonlocal_bind)")
|
1046
1085
|
ap2.add_argument("--wr-h-eps", metavar="PATH", type=u, default="", help="write list of listening-on ip:port to textfile at \033[33mPATH\033[0m when http-servers have started")
|
1047
1086
|
ap2.add_argument("--wr-h-aon", metavar="PATH", type=u, default="", help="write list of accessible-on ip:port to textfile at \033[33mPATH\033[0m when http-servers have started")
|
@@ -1527,6 +1566,7 @@ def add_ui(ap, retry):
|
|
1527
1566
|
ap2.add_argument("--lg-sba", metavar="TXT", type=u, default="", help="the value of the iframe 'allow' attribute for prologue/epilogue docs (volflag=lg_sba); see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Permissions-Policy#iframes")
|
1528
1567
|
ap2.add_argument("--no-sb-md", action="store_true", help="don't sandbox README/PREADME.md documents (volflags: no_sb_md | sb_md)")
|
1529
1568
|
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")
|
1569
|
+
ap2.add_argument("--have-unlistc", action="store_true", help=argparse.SUPPRESS)
|
1530
1570
|
|
1531
1571
|
|
1532
1572
|
def add_debug(ap):
|
@@ -113,6 +113,8 @@ class Lim(object):
|
|
113
113
|
|
114
114
|
self.reg = None # up2k registry
|
115
115
|
|
116
|
+
self.chmod_d = 0o755
|
117
|
+
|
116
118
|
self.nups = {} # num tracker
|
117
119
|
self.bups = {} # byte tracker list
|
118
120
|
self.bupc = {} # byte tracker cache
|
@@ -273,7 +275,7 @@ class Lim(object):
|
|
273
275
|
if not dirs:
|
274
276
|
# no branches yet; make one
|
275
277
|
sub = os.path.join(path, "0")
|
276
|
-
bos.mkdir(sub)
|
278
|
+
bos.mkdir(sub, self.chmod_d)
|
277
279
|
else:
|
278
280
|
# try newest branch only
|
279
281
|
sub = os.path.join(path, str(dirs[-1]))
|
@@ -288,7 +290,7 @@ class Lim(object):
|
|
288
290
|
|
289
291
|
# make a branch
|
290
292
|
sub = os.path.join(path, str(dirs[-1] + 1))
|
291
|
-
bos.mkdir(sub)
|
293
|
+
bos.mkdir(sub, self.chmod_d)
|
292
294
|
ret = self.dive(sub, lvs - 1)
|
293
295
|
if ret is None:
|
294
296
|
raise Pebkac(500, "rotation bug")
|
@@ -365,6 +367,7 @@ class VFS(object):
|
|
365
367
|
self.shr_src = None # source vfs+rem of a share
|
366
368
|
self.shr_files = set() # filenames to include from shr_src
|
367
369
|
self.shr_owner = "" # uname
|
370
|
+
self.shr_all_aps = []
|
368
371
|
self.aread = {}
|
369
372
|
self.awrite = {}
|
370
373
|
self.amove = {}
|
@@ -384,7 +387,7 @@ class VFS(object):
|
|
384
387
|
self.dbpath = self.histpath
|
385
388
|
self.all_vols = {vpath: self} # flattened recursive
|
386
389
|
self.all_nodes = {vpath: self} # also jumpvols/shares
|
387
|
-
self.all_aps = [(rp, self)]
|
390
|
+
self.all_aps = [(rp, [self])]
|
388
391
|
self.all_vps = [(vp, self)]
|
389
392
|
else:
|
390
393
|
self.histpath = self.dbpath = ""
|
@@ -417,7 +420,11 @@ class VFS(object):
|
|
417
420
|
rp = self.realpath
|
418
421
|
rp += "" if rp.endswith(os.sep) else os.sep
|
419
422
|
vp = self.vpath + ("/" if self.vpath else "")
|
420
|
-
|
423
|
+
hit = next((x[1] for x in aps if x[0] == rp), None)
|
424
|
+
if hit:
|
425
|
+
hit.append(self)
|
426
|
+
else:
|
427
|
+
aps.append((rp, [self]))
|
421
428
|
vps.append((vp, self))
|
422
429
|
|
423
430
|
for v in self.nodes.values():
|
@@ -841,9 +848,11 @@ class VFS(object):
|
|
841
848
|
return None
|
842
849
|
|
843
850
|
if "xvol" in self.flags:
|
844
|
-
|
851
|
+
all_aps = self.shr_all_aps or self.root.all_aps
|
852
|
+
|
853
|
+
for vap, vns in all_aps:
|
845
854
|
if aps.startswith(vap):
|
846
|
-
return
|
855
|
+
return self if self in vns else vns[0]
|
847
856
|
|
848
857
|
if self.log:
|
849
858
|
self.log("vfs", "xvol: %r" % (ap,), 3)
|
@@ -915,6 +924,9 @@ class AuthSrv(object):
|
|
915
924
|
|
916
925
|
yield prev, True
|
917
926
|
|
927
|
+
def vf0(self):
|
928
|
+
return {"d2d": True, "tcolor": self.args.tcolor}
|
929
|
+
|
918
930
|
def idp_checkin(
|
919
931
|
self, broker , uname , gname
|
920
932
|
) :
|
@@ -1620,13 +1632,12 @@ class AuthSrv(object):
|
|
1620
1632
|
t = "Read-access has been disabled due to failsafe: No volumes were defined by the config-file. This failsafe is to prevent unintended access if this is due to accidental loss of config. You can override this safeguard and allow read/write to the working-directory by adding the following arguments: -v .::rw"
|
1621
1633
|
self.log(t, 1)
|
1622
1634
|
axs = AXS()
|
1623
|
-
vfs = VFS(self.log_func, absreal("."), "", "", axs,
|
1635
|
+
vfs = VFS(self.log_func, absreal("."), "", "", axs, self.vf0())
|
1624
1636
|
if not axs.uread:
|
1625
1637
|
self.badcfg1 = True
|
1626
1638
|
elif "" not in mount:
|
1627
1639
|
# there's volumes but no root; make root inaccessible
|
1628
|
-
|
1629
|
-
vfs = VFS(self.log_func, "", "", "", AXS(), zsd)
|
1640
|
+
vfs = VFS(self.log_func, "", "", "", AXS(), self.vf0())
|
1630
1641
|
|
1631
1642
|
maxdepth = 0
|
1632
1643
|
for dst in sorted(mount.keys(), key=lambda x: (x.count("/"), len(x))):
|
@@ -1674,8 +1685,7 @@ class AuthSrv(object):
|
|
1674
1685
|
shrs = enshare[1:]
|
1675
1686
|
if enshare:
|
1676
1687
|
|
1677
|
-
|
1678
|
-
shv = VFS(self.log_func, "", shr, shr, AXS(), zsd)
|
1688
|
+
shv = VFS(self.log_func, "", shr, shr, AXS(), self.vf0())
|
1679
1689
|
|
1680
1690
|
db_path = self.args.shr_db
|
1681
1691
|
db = sqlite3.connect(db_path)
|
@@ -2053,8 +2063,11 @@ class AuthSrv(object):
|
|
2053
2063
|
elif self.args.re_maxage:
|
2054
2064
|
vol.flags["scan"] = self.args.re_maxage
|
2055
2065
|
|
2066
|
+
self.args.have_unlistc = False
|
2067
|
+
|
2056
2068
|
all_mte = {}
|
2057
2069
|
errors = False
|
2070
|
+
free_umask = False
|
2058
2071
|
for vol in vfs.all_nodes.values():
|
2059
2072
|
if (self.args.e2ds and vol.axs.uwrite) or self.args.e2dsa:
|
2060
2073
|
vol.flags["e2ds"] = True
|
@@ -2111,9 +2124,33 @@ class AuthSrv(object):
|
|
2111
2124
|
t = 'volume "/%s" has invalid %stry [%s]'
|
2112
2125
|
raise Exception(t % (vol.vpath, k, vol.flags.get(k + "try")))
|
2113
2126
|
|
2127
|
+
for k in ("chmod_d", "chmod_f"):
|
2128
|
+
is_d = k == "chmod_d"
|
2129
|
+
zs = vol.flags.get(k, "")
|
2130
|
+
if not zs and is_d:
|
2131
|
+
zs = "755"
|
2132
|
+
if not zs:
|
2133
|
+
vol.flags.pop(k, None)
|
2134
|
+
continue
|
2135
|
+
if not re.match("^[0-7]{3}$", zs):
|
2136
|
+
t = "config-option '%s' must be a three-digit octal value such as [755] or [644] but the value was [%s]"
|
2137
|
+
t = t % (k, zs)
|
2138
|
+
self.log(t, 1)
|
2139
|
+
raise Exception(t)
|
2140
|
+
zi = int(zs, 8)
|
2141
|
+
vol.flags[k] = zi
|
2142
|
+
if (is_d and zi != 0o755) or not is_d:
|
2143
|
+
free_umask = True
|
2144
|
+
|
2145
|
+
if vol.lim:
|
2146
|
+
vol.lim.chmod_d = vol.flags["chmod_d"]
|
2147
|
+
|
2114
2148
|
if vol.flags.get("og"):
|
2115
2149
|
self.args.uqe = True
|
2116
2150
|
|
2151
|
+
if "unlistcr" in vol.flags or "unlistcw" in vol.flags:
|
2152
|
+
self.args.have_unlistc = True
|
2153
|
+
|
2117
2154
|
zs = str(vol.flags.get("tcolor", "")).lstrip("#")
|
2118
2155
|
if len(zs) == 3: # fc5 => ffcc55
|
2119
2156
|
vol.flags["tcolor"] = "".join([x * 2 for x in zs])
|
@@ -2337,6 +2374,10 @@ class AuthSrv(object):
|
|
2337
2374
|
if errors:
|
2338
2375
|
sys.exit(1)
|
2339
2376
|
|
2377
|
+
setattr(self.args, "free_umask", free_umask)
|
2378
|
+
if free_umask:
|
2379
|
+
os.umask(0)
|
2380
|
+
|
2340
2381
|
vfs.bubble_flags()
|
2341
2382
|
|
2342
2383
|
have_e2d = False
|
@@ -2539,6 +2580,28 @@ class AuthSrv(object):
|
|
2539
2580
|
shn.shr_src = (s_vfs, s_rem)
|
2540
2581
|
shn.realpath = s_vfs.canonical(s_rem)
|
2541
2582
|
|
2583
|
+
# root.all_aps doesn't include any shares, so make a copy where the
|
2584
|
+
# share appears in all abspaths it can provide (for example for chk_ap)
|
2585
|
+
ap = shn.realpath
|
2586
|
+
if not ap.endswith(os.sep):
|
2587
|
+
ap += os.sep
|
2588
|
+
shn.shr_all_aps = [(x, y[:]) for x, y in vfs.all_aps]
|
2589
|
+
exact = False
|
2590
|
+
for ap2, vns in shn.shr_all_aps:
|
2591
|
+
if ap == ap2:
|
2592
|
+
exact = True
|
2593
|
+
if ap2.startswith(ap):
|
2594
|
+
try:
|
2595
|
+
vp2 = vjoin(s_rem, ap2[len(ap) :])
|
2596
|
+
vn2, _ = s_vfs.get(vp2, "*", False, False)
|
2597
|
+
if vn2 == s_vfs or vn2.dbv == s_vfs:
|
2598
|
+
vns.append(shn)
|
2599
|
+
except:
|
2600
|
+
pass
|
2601
|
+
if not exact:
|
2602
|
+
shn.shr_all_aps.append((ap, [shn]))
|
2603
|
+
shn.shr_all_aps.sort(key=lambda x: len(x[0]), reverse=True)
|
2604
|
+
|
2542
2605
|
if self.args.shr_v:
|
2543
2606
|
t = "mapped %s share [%s] by [%s] => [%s] => [%s]"
|
2544
2607
|
self.log(t % (s_pr, s_k, s_un, s_vp, shn.realpath))
|
@@ -2553,7 +2616,7 @@ class AuthSrv(object):
|
|
2553
2616
|
continue # also fine
|
2554
2617
|
for zs in svn.nodes.keys():
|
2555
2618
|
# hide subvolume
|
2556
|
-
vn.nodes[zs] = VFS(self.log_func, "", "", "", AXS(),
|
2619
|
+
vn.nodes[zs] = VFS(self.log_func, "", "", "", AXS(), self.vf0())
|
2557
2620
|
|
2558
2621
|
cur2.close()
|
2559
2622
|
cur.close()
|
@@ -22,14 +22,26 @@ def listdir(p = ".") :
|
|
22
22
|
|
23
23
|
|
24
24
|
def makedirs(name , mode = 0o755, exist_ok = True) :
|
25
|
+
# os.makedirs does 777 for all but leaf; this does mode on all
|
26
|
+
todo = []
|
25
27
|
bname = fsenc(name)
|
26
|
-
|
27
|
-
os.
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
while bname:
|
29
|
+
if os.path.isdir(bname):
|
30
|
+
break
|
31
|
+
todo.append(bname)
|
32
|
+
bname = os.path.dirname(bname)
|
33
|
+
if not todo:
|
34
|
+
if not exist_ok:
|
35
|
+
os.mkdir(bname) # to throw
|
32
36
|
return False
|
37
|
+
for zb in todo[::-1]:
|
38
|
+
try:
|
39
|
+
os.mkdir(zb, mode)
|
40
|
+
except:
|
41
|
+
if os.path.isdir(zb):
|
42
|
+
continue
|
43
|
+
raise
|
44
|
+
return True
|
33
45
|
|
34
46
|
|
35
47
|
def mkdir(p , mode = 0o755) :
|
@@ -78,6 +78,8 @@ def vf_vmap() :
|
|
78
78
|
}
|
79
79
|
for k in (
|
80
80
|
"bup_ck",
|
81
|
+
"chmod_d",
|
82
|
+
"chmod_f",
|
81
83
|
"dbd",
|
82
84
|
"forget_ip",
|
83
85
|
"hsortn",
|
@@ -169,6 +171,8 @@ flagcats = {
|
|
169
171
|
"safededup": "verify on-disk data before using it for dedup",
|
170
172
|
"noclone": "take dupe data from clients, even if available on HDD",
|
171
173
|
"nodupe": "rejects existing files (instead of linking/cloning them)",
|
174
|
+
"chmod_d=755": "unix-permission for new dirs/folders",
|
175
|
+
"chmod_f=644": "unix-permission for new files",
|
172
176
|
"sparse": "force use of sparse files, mainly for s3-backed storage",
|
173
177
|
"nosparse": "deny use of sparse files, mainly for slow storage",
|
174
178
|
"daw": "enable full WebDAV write support (dangerous);\nPUT-operations will now \033[1;31mOVERWRITE\033[0;35m existing files",
|
@@ -280,6 +284,8 @@ flagcats = {
|
|
280
284
|
"nodirsz": "don't show total folder size",
|
281
285
|
"robots": "allows indexing by search engines (default)",
|
282
286
|
"norobots": "kindly asks search engines to leave",
|
287
|
+
"unlistcr": "don't list read-access in controlpanel",
|
288
|
+
"unlistcw": "don't list write-access in controlpanel",
|
283
289
|
"no_sb_md": "disable js sandbox for markdown files",
|
284
290
|
"no_sb_lg": "disable js sandbox for prologue/epilogue",
|
285
291
|
"sb_md": "enable js sandbox for markdown files (default)",
|
@@ -225,7 +225,7 @@ class FtpFs(AbstractedFS):
|
|
225
225
|
r = "r" in mode
|
226
226
|
w = "w" in mode or "a" in mode or "+" in mode
|
227
227
|
|
228
|
-
ap = self.rv2a(filename, r, w)
|
228
|
+
ap, vfs, _ = self.rv2a(filename, r, w)
|
229
229
|
self.validpath(ap)
|
230
230
|
if w:
|
231
231
|
try:
|
@@ -257,7 +257,11 @@ class FtpFs(AbstractedFS):
|
|
257
257
|
|
258
258
|
wunlink(self.log, ap, VF_CAREFUL)
|
259
259
|
|
260
|
-
|
260
|
+
ret = open(fsenc(ap), mode, self.args.iobuf)
|
261
|
+
if w and "chmod_f" in vfs.flags:
|
262
|
+
os.fchmod(ret.fileno(), vfs.flags["chmod_f"])
|
263
|
+
|
264
|
+
return ret
|
261
265
|
|
262
266
|
def chdir(self, path ) :
|
263
267
|
nwd = join(self.cwd, path)
|
@@ -288,8 +292,9 @@ class FtpFs(AbstractedFS):
|
|
288
292
|
) = avfs.can_access("", self.h.uname)
|
289
293
|
|
290
294
|
def mkdir(self, path ) :
|
291
|
-
ap = self.rv2a(path, w=True)
|
292
|
-
|
295
|
+
ap, vfs, _ = self.rv2a(path, w=True)
|
296
|
+
chmod = vfs.flags["chmod_d"]
|
297
|
+
bos.makedirs(ap, chmod) # filezilla expects this
|
293
298
|
|
294
299
|
def listdir(self, path ) :
|
295
300
|
vpath = join(self.cwd, path)
|
@@ -45,6 +45,7 @@ from .util import (
|
|
45
45
|
APPLESAN_RE,
|
46
46
|
BITNESS,
|
47
47
|
DAV_ALLPROPS,
|
48
|
+
E_SCK_WR,
|
48
49
|
FN_EMB,
|
49
50
|
HAVE_SQLITE3,
|
50
51
|
HTTPCODE,
|
@@ -1369,12 +1370,13 @@ class HttpCli(object):
|
|
1369
1370
|
title = self.uparam.get("title") or self.vpath.split("/")[-1]
|
1370
1371
|
etitle = html_escape(title, True, True)
|
1371
1372
|
|
1372
|
-
baseurl = "%s://%s
|
1373
|
+
baseurl = "%s://%s/" % (
|
1373
1374
|
"https" if self.is_https else "http",
|
1374
1375
|
self.host,
|
1375
|
-
self.args.SRS,
|
1376
1376
|
)
|
1377
|
-
feed =
|
1377
|
+
feed = baseurl + self.req[1:]
|
1378
|
+
if self.is_vproxied:
|
1379
|
+
baseurl += self.args.RS
|
1378
1380
|
efeed = html_escape(feed, True, True)
|
1379
1381
|
edirlink = efeed.split("?")[0] + q_pw
|
1380
1382
|
|
@@ -1387,7 +1389,7 @@ class HttpCli(object):
|
|
1387
1389
|
\t\t<title>%s</title>
|
1388
1390
|
\t\t<description></description>
|
1389
1391
|
\t\t<link>%s</link>
|
1390
|
-
\t\t<generator>copyparty-
|
1392
|
+
\t\t<generator>copyparty-2</generator>
|
1391
1393
|
"""
|
1392
1394
|
% (efeed, etitle, edirlink)
|
1393
1395
|
]
|
@@ -2058,7 +2060,7 @@ class HttpCli(object):
|
|
2058
2060
|
fdir, fn = os.path.split(fdir)
|
2059
2061
|
rem, _ = vsplit(rem)
|
2060
2062
|
|
2061
|
-
bos.makedirs(fdir)
|
2063
|
+
bos.makedirs(fdir, vfs.flags["chmod_d"])
|
2062
2064
|
|
2063
2065
|
open_ka = {"fun": open}
|
2064
2066
|
open_a = ["wb", self.args.iobuf]
|
@@ -2116,6 +2118,8 @@ class HttpCli(object):
|
|
2116
2118
|
fn = vfs.flags["put_name2"].format(now=time.time(), cip=self.dip())
|
2117
2119
|
|
2118
2120
|
params = {"suffix": suffix, "fdir": fdir}
|
2121
|
+
if "chmod_f" in vfs.flags:
|
2122
|
+
params["chmod"] = vfs.flags["chmod_f"]
|
2119
2123
|
if self.args.nw:
|
2120
2124
|
params = {}
|
2121
2125
|
fn = os.devnull
|
@@ -2163,7 +2167,7 @@ class HttpCli(object):
|
|
2163
2167
|
if self.args.nw:
|
2164
2168
|
fn = os.devnull
|
2165
2169
|
else:
|
2166
|
-
bos.makedirs(fdir)
|
2170
|
+
bos.makedirs(fdir, vfs.flags["chmod_d"])
|
2167
2171
|
path = os.path.join(fdir, fn)
|
2168
2172
|
if not nameless:
|
2169
2173
|
self.vpath = vjoin(self.vpath, fn)
|
@@ -2295,7 +2299,7 @@ class HttpCli(object):
|
|
2295
2299
|
if self.args.hook_v:
|
2296
2300
|
log_reloc(self.log, hr["reloc"], x, path, vp, fn, vfs, rem)
|
2297
2301
|
fdir, self.vpath, fn, (vfs, rem) = x
|
2298
|
-
bos.makedirs(fdir)
|
2302
|
+
bos.makedirs(fdir, vfs.flags["chmod_d"])
|
2299
2303
|
path2 = os.path.join(fdir, fn)
|
2300
2304
|
atomic_move(self.log, path, path2, vfs.flags)
|
2301
2305
|
path = path2
|
@@ -2580,7 +2584,7 @@ class HttpCli(object):
|
|
2580
2584
|
dst = vfs.canonical(rem)
|
2581
2585
|
try:
|
2582
2586
|
if not bos.path.isdir(dst):
|
2583
|
-
bos.makedirs(dst)
|
2587
|
+
bos.makedirs(dst, vfs.flags["chmod_d"])
|
2584
2588
|
except OSError as ex:
|
2585
2589
|
self.log("makedirs failed %r" % (dst,))
|
2586
2590
|
if not bos.path.isdir(dst):
|
@@ -3011,7 +3015,7 @@ class HttpCli(object):
|
|
3011
3015
|
raise Pebkac(405, 'folder "/%s" already exists' % (vpath,))
|
3012
3016
|
|
3013
3017
|
try:
|
3014
|
-
bos.makedirs(fn)
|
3018
|
+
bos.makedirs(fn, vfs.flags["chmod_d"])
|
3015
3019
|
except OSError as ex:
|
3016
3020
|
if ex.errno == errno.EACCES:
|
3017
3021
|
raise Pebkac(500, "the server OS denied write-access")
|
@@ -3052,6 +3056,8 @@ class HttpCli(object):
|
|
3052
3056
|
|
3053
3057
|
with open(fsenc(fn), "wb") as f:
|
3054
3058
|
f.write(b"`GRUNNUR`\n")
|
3059
|
+
if "chmod_f" in vfs.flags:
|
3060
|
+
os.fchmod(f.fileno(), vfs.flags["chmod_f"])
|
3055
3061
|
|
3056
3062
|
vpath = "{}/{}".format(self.vpath, sanitized).lstrip("/")
|
3057
3063
|
self.redirect(vpath, "?edit")
|
@@ -3125,7 +3131,7 @@ class HttpCli(object):
|
|
3125
3131
|
)
|
3126
3132
|
upload_vpath = "{}/{}".format(vfs.vpath, rem).strip("/")
|
3127
3133
|
if not nullwrite:
|
3128
|
-
bos.makedirs(fdir_base)
|
3134
|
+
bos.makedirs(fdir_base, vfs.flags["chmod_d"])
|
3129
3135
|
|
3130
3136
|
rnd, lifetime, xbu, xau = self.upload_flags(vfs)
|
3131
3137
|
zs = self.uparam.get("want") or self.headers.get("accept") or ""
|
@@ -3220,8 +3226,11 @@ class HttpCli(object):
|
|
3220
3226
|
else:
|
3221
3227
|
open_args["fdir"] = fdir
|
3222
3228
|
|
3229
|
+
if "chmod_f" in vfs.flags:
|
3230
|
+
open_args["chmod"] = vfs.flags["chmod_f"]
|
3231
|
+
|
3223
3232
|
if p_file and not nullwrite:
|
3224
|
-
bos.makedirs(fdir)
|
3233
|
+
bos.makedirs(fdir, vfs.flags["chmod_d"])
|
3225
3234
|
|
3226
3235
|
# reserve destination filename
|
3227
3236
|
f, fname = ren_open(fname, "wb", fdir=fdir, suffix=suffix)
|
@@ -3325,7 +3334,7 @@ class HttpCli(object):
|
|
3325
3334
|
if nullwrite:
|
3326
3335
|
fdir = ap2 = ""
|
3327
3336
|
else:
|
3328
|
-
bos.makedirs(fdir)
|
3337
|
+
bos.makedirs(fdir, vfs.flags["chmod_d"])
|
3329
3338
|
atomic_move(self.log, abspath, ap2, vfs.flags)
|
3330
3339
|
abspath = ap2
|
3331
3340
|
sz = bos.path.getsize(abspath)
|
@@ -3446,6 +3455,8 @@ class HttpCli(object):
|
|
3446
3455
|
ft = "{}:{}".format(self.ip, self.addr[1])
|
3447
3456
|
ft = "{}\n{}\n{}\n".format(ft, msg.rstrip(), errmsg)
|
3448
3457
|
f.write(ft.encode("utf-8"))
|
3458
|
+
if "chmod_f" in vfs.flags:
|
3459
|
+
os.fchmod(f.fileno(), vfs.flags["chmod_f"])
|
3449
3460
|
except Exception as ex:
|
3450
3461
|
suf = "\nfailed to write the upload report: {}".format(ex)
|
3451
3462
|
|
@@ -3495,7 +3506,7 @@ class HttpCli(object):
|
|
3495
3506
|
lim = vfs.get_dbv(rem)[0].lim
|
3496
3507
|
if lim:
|
3497
3508
|
fp, rp = lim.all(self.ip, rp, clen, vfs.realpath, fp, self.conn.hsrv.broker)
|
3498
|
-
bos.makedirs(fp)
|
3509
|
+
bos.makedirs(fp, vfs.flags["chmod_d"])
|
3499
3510
|
|
3500
3511
|
fp = os.path.join(fp, fn)
|
3501
3512
|
rem = "{}/{}".format(rp, fn).strip("/")
|
@@ -3563,13 +3574,15 @@ class HttpCli(object):
|
|
3563
3574
|
zs = ub64enc(zb).decode("ascii")[:24].lower()
|
3564
3575
|
dp = "%s/md/%s/%s/%s" % (dbv.histpath, zs[:2], zs[2:4], zs)
|
3565
3576
|
self.log("moving old version to %s/%s" % (dp, mfile2))
|
3566
|
-
if bos.makedirs(dp):
|
3577
|
+
if bos.makedirs(dp, vfs.flags["chmod_d"]):
|
3567
3578
|
with open(os.path.join(dp, "dir.txt"), "wb") as f:
|
3568
3579
|
f.write(afsenc(vrd))
|
3580
|
+
if "chmod_f" in vfs.flags:
|
3581
|
+
os.fchmod(f.fileno(), vfs.flags["chmod_f"])
|
3569
3582
|
elif hist_cfg == "s":
|
3570
3583
|
dp = os.path.join(mdir, ".hist")
|
3571
3584
|
try:
|
3572
|
-
bos.mkdir(dp)
|
3585
|
+
bos.mkdir(dp, vfs.flags["chmod_d"])
|
3573
3586
|
hidedir(dp)
|
3574
3587
|
except:
|
3575
3588
|
pass
|
@@ -3607,6 +3620,8 @@ class HttpCli(object):
|
|
3607
3620
|
wunlink(self.log, fp, vfs.flags)
|
3608
3621
|
|
3609
3622
|
with open(fsenc(fp), "wb", self.args.iobuf) as f:
|
3623
|
+
if "chmod_f" in vfs.flags:
|
3624
|
+
os.fchmod(f.fileno(), vfs.flags["chmod_f"])
|
3610
3625
|
sz, sha512, _ = hashcopy(p_data, f, None, 0, self.args.s_wr_slp)
|
3611
3626
|
|
3612
3627
|
if lim:
|
@@ -4342,7 +4357,7 @@ class HttpCli(object):
|
|
4342
4357
|
self.log("file deleted; disconnecting")
|
4343
4358
|
break
|
4344
4359
|
except IOError as ex:
|
4345
|
-
if ex.errno not in
|
4360
|
+
if ex.errno not in E_SCK_WR:
|
4346
4361
|
raise
|
4347
4362
|
finally:
|
4348
4363
|
if f:
|
@@ -4926,6 +4941,11 @@ class HttpCli(object):
|
|
4926
4941
|
fn = html_escape(fn) if fn else self.conn.hsrv.iiam
|
4927
4942
|
dls.append((perc, hsent, spd, eta, idle, usr, erd, rds, fn))
|
4928
4943
|
|
4944
|
+
if self.args.have_unlistc:
|
4945
|
+
allvols = self.asrv.vfs.all_vols
|
4946
|
+
rvol = [x for x in rvol if "unlistcr" not in allvols[x[1:-1]].flags]
|
4947
|
+
wvol = [x for x in wvol if "unlistcw" not in allvols[x[1:-1]].flags]
|
4948
|
+
|
4929
4949
|
fmt = self.uparam.get("ls", "")
|
4930
4950
|
if not fmt and (self.ua.startswith("curl/") or self.ua.startswith("fetch")):
|
4931
4951
|
fmt = "v"
|
@@ -317,7 +317,7 @@ class SMB(object):
|
|
317
317
|
|
318
318
|
self.hub.up2k.handle_mv(uname, "1.7.6.2", vp1, vp2)
|
319
319
|
try:
|
320
|
-
bos.makedirs(ap2)
|
320
|
+
bos.makedirs(ap2, vfs2.flags["chmod_d"])
|
321
321
|
except:
|
322
322
|
pass
|
323
323
|
|
@@ -331,7 +331,7 @@ class SMB(object):
|
|
331
331
|
t = "blocked mkdir (no-write-acc %s): /%s @%s"
|
332
332
|
yeet(t % (vfs.axs.uwrite, vpath, uname))
|
333
333
|
|
334
|
-
return bos.mkdir(ap)
|
334
|
+
return bos.mkdir(ap, vfs.flags["chmod_d"])
|
335
335
|
|
336
336
|
def _stat(self, vpath , *a , **ka ) :
|
337
337
|
try:
|
@@ -21,6 +21,7 @@ from datetime import datetime
|
|
21
21
|
|
22
22
|
from .__init__ import ANYWIN, EXE, MACOS, PY2, TYPE_CHECKING, E, EnvParams, unicode
|
23
23
|
from .authsrv import BAD_CFG, AuthSrv
|
24
|
+
from .bos import bos
|
24
25
|
from .cert import ensure_cert
|
25
26
|
from .mtag import HAVE_FFMPEG, HAVE_FFPROBE, HAVE_MUTAGEN
|
26
27
|
from .pwhash import HAVE_ARGON2
|
@@ -1108,7 +1109,7 @@ class SvcHub(object):
|
|
1108
1109
|
|
1109
1110
|
fn = sel_fn
|
1110
1111
|
try:
|
1111
|
-
|
1112
|
+
bos.makedirs(os.path.dirname(fn))
|
1112
1113
|
except:
|
1113
1114
|
pass
|
1114
1115
|
|
@@ -1125,6 +1126,9 @@ class SvcHub(object):
|
|
1125
1126
|
|
1126
1127
|
lh = codecs.open(fn, "w", encoding="utf-8", errors="replace")
|
1127
1128
|
|
1129
|
+
if getattr(self.args, "free_umask", False):
|
1130
|
+
os.fchmod(lh.fileno(), 0o644)
|
1131
|
+
|
1128
1132
|
argv = [pybin] + self.argv
|
1129
1133
|
if hasattr(shlex, "quote"):
|
1130
1134
|
argv = [shlex.quote(x) for x in argv]
|