copyparty 1.17.1__tar.gz → 1.18.0__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.17.1 → copyparty-1.18.0}/PKG-INFO +37 -4
- {copyparty-1.17.1 → copyparty-1.18.0}/README.md +36 -3
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/__main__.py +15 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/__version__.py +3 -3
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/authsrv.py +49 -19
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/cfg.py +14 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/httpcli.py +189 -17
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/util.py +21 -5
- copyparty-1.18.0/copyparty/web/browser.css.gz +0 -0
- copyparty-1.18.0/copyparty/web/browser.js.gz +0 -0
- copyparty-1.18.0/copyparty/web/deps/marked.js.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/splash.js.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/ui.css.gz +0 -0
- copyparty-1.18.0/copyparty/web/up2k.js.gz +0 -0
- copyparty-1.18.0/copyparty/web/util.js.gz +0 -0
- copyparty-1.18.0/copyparty/web/w.hash.js.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty.egg-info/PKG-INFO +37 -4
- copyparty-1.17.1/copyparty/web/browser.css.gz +0 -0
- copyparty-1.17.1/copyparty/web/browser.js.gz +0 -0
- copyparty-1.17.1/copyparty/web/deps/marked.js.gz +0 -0
- copyparty-1.17.1/copyparty/web/up2k.js.gz +0 -0
- copyparty-1.17.1/copyparty/web/util.js.gz +0 -0
- copyparty-1.17.1/copyparty/web/w.hash.js.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/LICENSE +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/__init__.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/bos/__init__.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/bos/bos.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/bos/path.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/broker_mp.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/broker_mpw.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/broker_thr.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/broker_util.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/cert.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/dxml.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/fsutil.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/ftpd.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/httpconn.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/httpsrv.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/ico.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/mdns.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/metrics.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/mtag.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/multicast.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/pwhash.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/res/COPYING.txt +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/res/__init__.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/res/insecure.pem +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/smbd.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/ssdp.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/star.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/stolen/__init__.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/stolen/dnslib/__init__.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/stolen/dnslib/bimap.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/stolen/dnslib/bit.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/stolen/dnslib/buffer.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/stolen/dnslib/dns.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/stolen/dnslib/label.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/stolen/dnslib/lex.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/stolen/dnslib/ranges.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/stolen/ifaddr/__init__.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/stolen/ifaddr/_posix.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/stolen/ifaddr/_shared.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/stolen/ifaddr/_win32.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/stolen/qrcodegen.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/stolen/surrogateescape.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/sutil.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/svchub.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/szip.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/tcpsrv.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/tftpd.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/th_cli.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/th_srv.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/u2idx.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/up2k.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/a/__init__.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/a/partyfuse.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/a/u2c.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/a/webdav-cfg.bat +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/baguettebox.js.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/browser.html +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/browser2.html +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/cf.html +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/dbg-audio.js.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/dd/2.png +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/dd/3.png +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/dd/4.png +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/dd/5.png +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/dd/__init__.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/deps/__init__.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/deps/busy.mp3.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/deps/easymde.css.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/deps/easymde.js.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/deps/fuse.py +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/deps/mini-fa.css.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/deps/mini-fa.woff +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/deps/prism.css.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/deps/prism.js.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/deps/prismd.css.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/deps/scp.woff2 +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/deps/sha512.ac.js.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/deps/sha512.hw.js.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/md.css.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/md.html +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/md.js.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/md2.css.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/md2.js.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/mde.css.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/mde.html +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/mde.js.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/msg.css.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/msg.html +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/rups.css.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/rups.html +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/rups.js.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/shares.css.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/shares.html +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/shares.js.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/splash.css.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/splash.html +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/svcs.html +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty/web/svcs.js.gz +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty.egg-info/SOURCES.txt +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty.egg-info/dependency_links.txt +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty.egg-info/entry_points.txt +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty.egg-info/requires.txt +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/copyparty.egg-info/top_level.txt +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/pyproject.toml +0 -0
- {copyparty-1.17.1 → copyparty-1.18.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: copyparty
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.18.0
|
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
|
@@ -66,12 +66,14 @@ turn almost any device into a file server with resumable uploads/downloads using
|
|
66
66
|
* 🔌 protocols: [http](#the-browser) // [webdav](#webdav-server) // [ftp](#ftp-server) // [tftp](#tftp-server) // [smb/cifs](#smb-server)
|
67
67
|
* 📱 [android app](#android-app) // [iPhone shortcuts](#ios-shortcuts)
|
68
68
|
|
69
|
-
👉 **[Get started](#quickstart)!** or visit the **[read-only demo server](https://a.ocv.me/pub/demo/)** 👀 running
|
69
|
+
👉 **[Get started](#quickstart)!** or visit the **[read-only demo server](https://a.ocv.me/pub/demo/)** 👀 running on a nuc in my basement
|
70
70
|
|
71
71
|
📷 **screenshots:** [browser](#the-browser) // [upload](#uploading) // [unpost](#unpost) // [thumbnails](#thumbnails) // [search](#searching) // [fsearch](#file-search) // [zip-DL](#zip-downloads) // [md-viewer](#markdown-viewer)
|
72
72
|
|
73
73
|
🎬 **videos:** [upload](https://a.ocv.me/pub/demo/pics-vids/up2k.webm) // [cli-upload](https://a.ocv.me/pub/demo/pics-vids/u2cli.webm) // [race-the-beam](https://a.ocv.me/pub/g/nerd-stuff/cpp/2024-0418-race-the-beam.webm)
|
74
74
|
|
75
|
+
made in Norway 🇳🇴
|
76
|
+
|
75
77
|
|
76
78
|
## readme toc
|
77
79
|
|
@@ -112,6 +114,7 @@ turn almost any device into a file server with resumable uploads/downloads using
|
|
112
114
|
* [creating a playlist](#creating-a-playlist) - with a standalone mediaplayer or copyparty
|
113
115
|
* [audio equalizer](#audio-equalizer) - and [dynamic range compressor](https://en.wikipedia.org/wiki/Dynamic_range_compression)
|
114
116
|
* [fix unreliable playback on android](#fix-unreliable-playback-on-android) - due to phone / app settings
|
117
|
+
* [textfile viewer](#textfile-viewer) - with realtime streaming of logfiles and such ([demo](https://a.ocv.me/pub/demo/logtail/))
|
115
118
|
* [markdown viewer](#markdown-viewer) - and there are *two* editors
|
116
119
|
* [markdown vars](#markdown-vars) - dynamic docs with serverside variable expansion
|
117
120
|
* [other tricks](#other-tricks)
|
@@ -313,7 +316,8 @@ also see [comparison to similar software](./docs/versus.md)
|
|
313
316
|
* ☑ play video files as audio (converted on server)
|
314
317
|
* ☑ create and play [m3u8 playlists](#playlists)
|
315
318
|
* ☑ image gallery with webm player
|
316
|
-
* ☑ textfile browser with syntax hilighting
|
319
|
+
* ☑ [textfile browser](#textfile-viewer) with syntax hilighting
|
320
|
+
* ☑ realtime streaming of growing files (logfiles and such)
|
317
321
|
* ☑ [thumbnails](#thumbnails)
|
318
322
|
* ☑ ...of images using Pillow, pyvips, or FFmpeg
|
319
323
|
* ☑ ...of videos using FFmpeg
|
@@ -617,6 +621,8 @@ a client can request to see dotfiles in directory listings if global option `-ed
|
|
617
621
|
|
618
622
|
dotfiles do not appear in search results unless one of the above is true, **and** the global option / volflag `dotsrch` is set
|
619
623
|
|
624
|
+
> even if user has permission to see dotfiles, they are default-hidden unless `--see-dots` is set, and/or user has enabled the `dotfiles` option in the settings tab
|
625
|
+
|
620
626
|
config file example, where the same permission to see dotfiles is given in two different ways just for reference:
|
621
627
|
|
622
628
|
```yaml
|
@@ -753,7 +759,10 @@ enabling `multiselect` lets you click files to select them, and then shift-click
|
|
753
759
|
* `multiselect` is mostly intended for phones/tablets, but the `sel` option in the `[⚙️] settings` tab is better suited for desktop use, allowing selection by CTRL-clicking and range-selection with SHIFT-click, all without affecting regular clicking
|
754
760
|
* the `sel` option can be made default globally with `--gsel` or per-volume with volflag `gsel`
|
755
761
|
|
756
|
-
to show `/icons/exe.png` as the thumbnail for all
|
762
|
+
to show `/icons/exe.png` and `/icons/elf.gif` as the thumbnail for all `.exe` and `.elf` files respectively, do this: `--ext-th=exe=/icons/exe.png --ext-th=elf=/icons/elf.gif`
|
763
|
+
* optionally as separate volflags for each mapping; see config file example below
|
764
|
+
* the supported image formats are [jpg, png, gif, webp, ico](https://developer.mozilla.org/en-US/docs/Web/Media/Guides/Formats/Image_types)
|
765
|
+
* be careful with svg; chrome will crash if you have too many unique svg files showing on the same page (the limit is 250 or so) -- showing the same handful of svg files thousands of times is ok however
|
757
766
|
|
758
767
|
config file example:
|
759
768
|
|
@@ -770,6 +779,7 @@ config file example:
|
|
770
779
|
dthumb # disable ALL thumbnails and audio transcoding
|
771
780
|
dvthumb # only disable video thumbnails
|
772
781
|
ext-th: exe=/ico/exe.png # /ico/exe.png is the thumbnail of *.exe
|
782
|
+
ext-th: elf=/ico/elf.gif # ...and /ico/elf.gif is used for *.elf
|
773
783
|
th-covers: folder.png,folder.jpg,cover.png,cover.jpg # the default
|
774
784
|
```
|
775
785
|
|
@@ -1177,6 +1187,18 @@ not available on iPhones / iPads because AudioContext currently breaks backgroun
|
|
1177
1187
|
due to phone / app settings, android phones may randomly stop playing music when the power saver kicks in, especially at the end of an album -- you can fix it by [disabling power saving](https://user-images.githubusercontent.com/241032/235262123-c328cca9-3930-4948-bd18-3949b9fd3fcf.png) in the [app settings](https://user-images.githubusercontent.com/241032/235262121-2ffc51ae-7821-4310-a322-c3b7a507890c.png) of the browser you use for music streaming (preferably a dedicated one)
|
1178
1188
|
|
1179
1189
|
|
1190
|
+
## textfile viewer
|
1191
|
+
|
1192
|
+
with realtime streaming of logfiles and such ([demo](https://a.ocv.me/pub/demo/logtail/)) , and terminal colors work too
|
1193
|
+
|
1194
|
+
click `-txt-` next to a textfile to open the viewer, which has the following toolbar buttons:
|
1195
|
+
|
1196
|
+
* `✏️ edit` opens the textfile editor
|
1197
|
+
* `📡 follow` starts monitoring the file for changes, streaming new lines in realtime
|
1198
|
+
* similar to `tail -f`
|
1199
|
+
* [link directly](https://a.ocv.me/pub/demo/logtail/?doc=lipsum.txt&tail) to a file with tailing enabled by adding `&tail` to the textviewer URL
|
1200
|
+
|
1201
|
+
|
1180
1202
|
## markdown viewer
|
1181
1203
|
|
1182
1204
|
and there are *two* editors
|
@@ -2475,6 +2497,9 @@ interact with copyparty using non-browser clients
|
|
2475
2497
|
* and for screenshots on macos, see [./contrib/ishare.iscu](./contrib/#ishareiscu)
|
2476
2498
|
* and for screenshots on linux, see [./contrib/flameshot.sh](./contrib/flameshot.sh)
|
2477
2499
|
|
2500
|
+
* [Custom Uploader](https://f-droid.org/en/packages/com.nyx.custom_uploader/) (an Android app) as an alternative to copyparty's own [PartyUP!](#android-app)
|
2501
|
+
* works if you set UploadURL to `https://your.com/foo/?want=url&pw=hunter2` and FormDataName `f`
|
2502
|
+
|
2478
2503
|
* contextlet (web browser integration); see [contrib contextlet](contrib/#send-to-cppcontextletjson)
|
2479
2504
|
|
2480
2505
|
* [igloo irc](https://iglooirc.com/): Method: `post` Host: `https://you.com/up/?want=url&pw=hunter2` Multipart: `yes` File parameter: `f`
|
@@ -2576,6 +2601,11 @@ below are some tweaks roughly ordered by usefulness:
|
|
2576
2601
|
|
2577
2602
|
when uploading files,
|
2578
2603
|
|
2604
|
+
* when uploading from very fast storage (NVMe SSD) with chrome/firefox, enable `[wasm]` in the `[⚙️] settings` tab to more effectively use all CPU-cores for hashing
|
2605
|
+
* don't do this on Safari (runs faster without)
|
2606
|
+
* don't do this on older browsers; likely to provoke browser-bugs (browser eats all RAM and crashes)
|
2607
|
+
* can be made default-enabled serverside with `--nosubtle 137` (chrome v137+) or `--nosubtle 2` (chrome+firefox)
|
2608
|
+
|
2579
2609
|
* chrome is recommended (unfortunately), at least compared to firefox:
|
2580
2610
|
* up to 90% faster when hashing, especially on SSDs
|
2581
2611
|
* up to 40% faster when uploading over extremely fast internets
|
@@ -2783,6 +2813,7 @@ set any of the following environment variables to disable its associated optiona
|
|
2783
2813
|
| `PRTY_NO_CFSSL` | never attempt to generate self-signed certificates using [cfssl](https://github.com/cloudflare/cfssl) |
|
2784
2814
|
| `PRTY_NO_FFMPEG` | **audio transcoding** goes byebye, **thumbnailing** must be handled by Pillow/libvips |
|
2785
2815
|
| `PRTY_NO_FFPROBE` | **audio transcoding** goes byebye, **thumbnailing** must be handled by Pillow/libvips, **metadata-scanning** must be handled by mutagen |
|
2816
|
+
| `PRTY_NO_MAGIC` | do not use [magic](https://pypi.org/project/python-magic/) for filetype detection |
|
2786
2817
|
| `PRTY_NO_MUTAGEN` | do not use [mutagen](https://pypi.org/project/mutagen/) for reading metadata from media files; will fallback to ffprobe |
|
2787
2818
|
| `PRTY_NO_PIL` | disable all [Pillow](https://pypi.org/project/pillow/)-based thumbnail support; will fallback to libvips or ffmpeg |
|
2788
2819
|
| `PRTY_NO_PILF` | disable Pillow `ImageFont` text rendering, used for folder thumbnails |
|
@@ -2883,5 +2914,7 @@ if there's a wall of base64 in the log (thread stacks) then please include that,
|
|
2883
2914
|
|
2884
2915
|
for build instructions etc, see [./docs/devnotes.md](./docs/devnotes.md)
|
2885
2916
|
|
2917
|
+
specifically you may want to [build the sfx](https://github.com/9001/copyparty/blob/hovudstraum/docs/devnotes.md#just-the-sfx) or [build from scratch](https://github.com/9001/copyparty/blob/hovudstraum/docs/devnotes.md#build-from-scratch)
|
2918
|
+
|
2886
2919
|
see [./docs/TODO.md](./docs/TODO.md) for planned features / fixes / changes
|
2887
2920
|
|
@@ -8,12 +8,14 @@ turn almost any device into a file server with resumable uploads/downloads using
|
|
8
8
|
* 🔌 protocols: [http](#the-browser) // [webdav](#webdav-server) // [ftp](#ftp-server) // [tftp](#tftp-server) // [smb/cifs](#smb-server)
|
9
9
|
* 📱 [android app](#android-app) // [iPhone shortcuts](#ios-shortcuts)
|
10
10
|
|
11
|
-
👉 **[Get started](#quickstart)!** or visit the **[read-only demo server](https://a.ocv.me/pub/demo/)** 👀 running
|
11
|
+
👉 **[Get started](#quickstart)!** or visit the **[read-only demo server](https://a.ocv.me/pub/demo/)** 👀 running on a nuc in my basement
|
12
12
|
|
13
13
|
📷 **screenshots:** [browser](#the-browser) // [upload](#uploading) // [unpost](#unpost) // [thumbnails](#thumbnails) // [search](#searching) // [fsearch](#file-search) // [zip-DL](#zip-downloads) // [md-viewer](#markdown-viewer)
|
14
14
|
|
15
15
|
🎬 **videos:** [upload](https://a.ocv.me/pub/demo/pics-vids/up2k.webm) // [cli-upload](https://a.ocv.me/pub/demo/pics-vids/u2cli.webm) // [race-the-beam](https://a.ocv.me/pub/g/nerd-stuff/cpp/2024-0418-race-the-beam.webm)
|
16
16
|
|
17
|
+
made in Norway 🇳🇴
|
18
|
+
|
17
19
|
|
18
20
|
## readme toc
|
19
21
|
|
@@ -54,6 +56,7 @@ turn almost any device into a file server with resumable uploads/downloads using
|
|
54
56
|
* [creating a playlist](#creating-a-playlist) - with a standalone mediaplayer or copyparty
|
55
57
|
* [audio equalizer](#audio-equalizer) - and [dynamic range compressor](https://en.wikipedia.org/wiki/Dynamic_range_compression)
|
56
58
|
* [fix unreliable playback on android](#fix-unreliable-playback-on-android) - due to phone / app settings
|
59
|
+
* [textfile viewer](#textfile-viewer) - with realtime streaming of logfiles and such ([demo](https://a.ocv.me/pub/demo/logtail/))
|
57
60
|
* [markdown viewer](#markdown-viewer) - and there are *two* editors
|
58
61
|
* [markdown vars](#markdown-vars) - dynamic docs with serverside variable expansion
|
59
62
|
* [other tricks](#other-tricks)
|
@@ -255,7 +258,8 @@ also see [comparison to similar software](./docs/versus.md)
|
|
255
258
|
* ☑ play video files as audio (converted on server)
|
256
259
|
* ☑ create and play [m3u8 playlists](#playlists)
|
257
260
|
* ☑ image gallery with webm player
|
258
|
-
* ☑ textfile browser with syntax hilighting
|
261
|
+
* ☑ [textfile browser](#textfile-viewer) with syntax hilighting
|
262
|
+
* ☑ realtime streaming of growing files (logfiles and such)
|
259
263
|
* ☑ [thumbnails](#thumbnails)
|
260
264
|
* ☑ ...of images using Pillow, pyvips, or FFmpeg
|
261
265
|
* ☑ ...of videos using FFmpeg
|
@@ -559,6 +563,8 @@ a client can request to see dotfiles in directory listings if global option `-ed
|
|
559
563
|
|
560
564
|
dotfiles do not appear in search results unless one of the above is true, **and** the global option / volflag `dotsrch` is set
|
561
565
|
|
566
|
+
> even if user has permission to see dotfiles, they are default-hidden unless `--see-dots` is set, and/or user has enabled the `dotfiles` option in the settings tab
|
567
|
+
|
562
568
|
config file example, where the same permission to see dotfiles is given in two different ways just for reference:
|
563
569
|
|
564
570
|
```yaml
|
@@ -695,7 +701,10 @@ enabling `multiselect` lets you click files to select them, and then shift-click
|
|
695
701
|
* `multiselect` is mostly intended for phones/tablets, but the `sel` option in the `[⚙️] settings` tab is better suited for desktop use, allowing selection by CTRL-clicking and range-selection with SHIFT-click, all without affecting regular clicking
|
696
702
|
* the `sel` option can be made default globally with `--gsel` or per-volume with volflag `gsel`
|
697
703
|
|
698
|
-
to show `/icons/exe.png` as the thumbnail for all
|
704
|
+
to show `/icons/exe.png` and `/icons/elf.gif` as the thumbnail for all `.exe` and `.elf` files respectively, do this: `--ext-th=exe=/icons/exe.png --ext-th=elf=/icons/elf.gif`
|
705
|
+
* optionally as separate volflags for each mapping; see config file example below
|
706
|
+
* the supported image formats are [jpg, png, gif, webp, ico](https://developer.mozilla.org/en-US/docs/Web/Media/Guides/Formats/Image_types)
|
707
|
+
* be careful with svg; chrome will crash if you have too many unique svg files showing on the same page (the limit is 250 or so) -- showing the same handful of svg files thousands of times is ok however
|
699
708
|
|
700
709
|
config file example:
|
701
710
|
|
@@ -712,6 +721,7 @@ config file example:
|
|
712
721
|
dthumb # disable ALL thumbnails and audio transcoding
|
713
722
|
dvthumb # only disable video thumbnails
|
714
723
|
ext-th: exe=/ico/exe.png # /ico/exe.png is the thumbnail of *.exe
|
724
|
+
ext-th: elf=/ico/elf.gif # ...and /ico/elf.gif is used for *.elf
|
715
725
|
th-covers: folder.png,folder.jpg,cover.png,cover.jpg # the default
|
716
726
|
```
|
717
727
|
|
@@ -1119,6 +1129,18 @@ not available on iPhones / iPads because AudioContext currently breaks backgroun
|
|
1119
1129
|
due to phone / app settings, android phones may randomly stop playing music when the power saver kicks in, especially at the end of an album -- you can fix it by [disabling power saving](https://user-images.githubusercontent.com/241032/235262123-c328cca9-3930-4948-bd18-3949b9fd3fcf.png) in the [app settings](https://user-images.githubusercontent.com/241032/235262121-2ffc51ae-7821-4310-a322-c3b7a507890c.png) of the browser you use for music streaming (preferably a dedicated one)
|
1120
1130
|
|
1121
1131
|
|
1132
|
+
## textfile viewer
|
1133
|
+
|
1134
|
+
with realtime streaming of logfiles and such ([demo](https://a.ocv.me/pub/demo/logtail/)) , and terminal colors work too
|
1135
|
+
|
1136
|
+
click `-txt-` next to a textfile to open the viewer, which has the following toolbar buttons:
|
1137
|
+
|
1138
|
+
* `✏️ edit` opens the textfile editor
|
1139
|
+
* `📡 follow` starts monitoring the file for changes, streaming new lines in realtime
|
1140
|
+
* similar to `tail -f`
|
1141
|
+
* [link directly](https://a.ocv.me/pub/demo/logtail/?doc=lipsum.txt&tail) to a file with tailing enabled by adding `&tail` to the textviewer URL
|
1142
|
+
|
1143
|
+
|
1122
1144
|
## markdown viewer
|
1123
1145
|
|
1124
1146
|
and there are *two* editors
|
@@ -2417,6 +2439,9 @@ interact with copyparty using non-browser clients
|
|
2417
2439
|
* and for screenshots on macos, see [./contrib/ishare.iscu](./contrib/#ishareiscu)
|
2418
2440
|
* and for screenshots on linux, see [./contrib/flameshot.sh](./contrib/flameshot.sh)
|
2419
2441
|
|
2442
|
+
* [Custom Uploader](https://f-droid.org/en/packages/com.nyx.custom_uploader/) (an Android app) as an alternative to copyparty's own [PartyUP!](#android-app)
|
2443
|
+
* works if you set UploadURL to `https://your.com/foo/?want=url&pw=hunter2` and FormDataName `f`
|
2444
|
+
|
2420
2445
|
* contextlet (web browser integration); see [contrib contextlet](contrib/#send-to-cppcontextletjson)
|
2421
2446
|
|
2422
2447
|
* [igloo irc](https://iglooirc.com/): Method: `post` Host: `https://you.com/up/?want=url&pw=hunter2` Multipart: `yes` File parameter: `f`
|
@@ -2518,6 +2543,11 @@ below are some tweaks roughly ordered by usefulness:
|
|
2518
2543
|
|
2519
2544
|
when uploading files,
|
2520
2545
|
|
2546
|
+
* when uploading from very fast storage (NVMe SSD) with chrome/firefox, enable `[wasm]` in the `[⚙️] settings` tab to more effectively use all CPU-cores for hashing
|
2547
|
+
* don't do this on Safari (runs faster without)
|
2548
|
+
* don't do this on older browsers; likely to provoke browser-bugs (browser eats all RAM and crashes)
|
2549
|
+
* can be made default-enabled serverside with `--nosubtle 137` (chrome v137+) or `--nosubtle 2` (chrome+firefox)
|
2550
|
+
|
2521
2551
|
* chrome is recommended (unfortunately), at least compared to firefox:
|
2522
2552
|
* up to 90% faster when hashing, especially on SSDs
|
2523
2553
|
* up to 40% faster when uploading over extremely fast internets
|
@@ -2725,6 +2755,7 @@ set any of the following environment variables to disable its associated optiona
|
|
2725
2755
|
| `PRTY_NO_CFSSL` | never attempt to generate self-signed certificates using [cfssl](https://github.com/cloudflare/cfssl) |
|
2726
2756
|
| `PRTY_NO_FFMPEG` | **audio transcoding** goes byebye, **thumbnailing** must be handled by Pillow/libvips |
|
2727
2757
|
| `PRTY_NO_FFPROBE` | **audio transcoding** goes byebye, **thumbnailing** must be handled by Pillow/libvips, **metadata-scanning** must be handled by mutagen |
|
2758
|
+
| `PRTY_NO_MAGIC` | do not use [magic](https://pypi.org/project/python-magic/) for filetype detection |
|
2728
2759
|
| `PRTY_NO_MUTAGEN` | do not use [mutagen](https://pypi.org/project/mutagen/) for reading metadata from media files; will fallback to ffprobe |
|
2729
2760
|
| `PRTY_NO_PIL` | disable all [Pillow](https://pypi.org/project/pillow/)-based thumbnail support; will fallback to libvips or ffmpeg |
|
2730
2761
|
| `PRTY_NO_PILF` | disable Pillow `ImageFont` text rendering, used for folder thumbnails |
|
@@ -2825,5 +2856,7 @@ if there's a wall of base64 in the log (thread stacks) then please include that,
|
|
2825
2856
|
|
2826
2857
|
for build instructions etc, see [./docs/devnotes.md](./docs/devnotes.md)
|
2827
2858
|
|
2859
|
+
specifically you may want to [build the sfx](https://github.com/9001/copyparty/blob/hovudstraum/docs/devnotes.md#just-the-sfx) or [build from scratch](https://github.com/9001/copyparty/blob/hovudstraum/docs/devnotes.md#build-from-scratch)
|
2860
|
+
|
2828
2861
|
see [./docs/TODO.md](./docs/TODO.md) for planned features / fixes / changes
|
2829
2862
|
|
@@ -956,6 +956,7 @@ def add_general(ap, nc, srvname):
|
|
956
956
|
ap2.add_argument("--name", metavar="TXT", type=u, default=srvname, help="server name (displayed topleft in browser and in mDNS)")
|
957
957
|
ap2.add_argument("--mime", metavar="EXT=MIME", type=u, action="append", help="map file \033[33mEXT\033[0mension to \033[33mMIME\033[0mtype, for example [\033[32mjpg=image/jpeg\033[0m]")
|
958
958
|
ap2.add_argument("--mimes", action="store_true", help="list default mimetype mapping and exit")
|
959
|
+
ap2.add_argument("--rmagic", action="store_true", help="do expensive analysis to improve accuracy of returned mimetypes; will make file-downloads, rss, and webdav slower (volflag=rmagic)")
|
959
960
|
ap2.add_argument("--license", action="store_true", help="show licenses and exit")
|
960
961
|
ap2.add_argument("--version", action="store_true", help="show versions and exit")
|
961
962
|
|
@@ -1020,6 +1021,7 @@ def add_upload(ap):
|
|
1020
1021
|
ap2.add_argument("--df", metavar="GiB", type=u, default="0", help="ensure \033[33mGiB\033[0m free disk space by rejecting upload requests; assumes gigabytes unless a unit suffix is given: [\033[32m256m\033[0m], [\033[32m4\033[0m], [\033[32m2T\033[0m] (volflag=df)")
|
1021
1022
|
ap2.add_argument("--sparse", metavar="MiB", type=int, default=4, help="windows-only: minimum size of incoming uploads through up2k before they are made into sparse files")
|
1022
1023
|
ap2.add_argument("--turbo", metavar="LVL", type=int, default=0, help="configure turbo-mode in up2k client; [\033[32m-1\033[0m] = forbidden/always-off, [\033[32m0\033[0m] = default-off and warn if enabled, [\033[32m1\033[0m] = default-off, [\033[32m2\033[0m] = on, [\033[32m3\033[0m] = on and disable datecheck")
|
1024
|
+
ap2.add_argument("--nosubtle", metavar="N", type=int, default=0, help="when to use a wasm-hasher instead of the browser's builtin; faster on chrome, but buggy in older chrome versions. [\033[32m0\033[0m] = only when necessary (non-https), [\033[32m1\033[0m] = always (all browsers), [\033[32m2\033[0m] = always on chrome/firefox, [\033[32m3\033[0m] = always on chrome, [\033[32mN\033[0m] = chrome-version N and newer (recommendation: 137)")
|
1023
1025
|
ap2.add_argument("--u2j", metavar="JOBS", type=int, default=2, help="web-client: number of file chunks to upload in parallel; 1 or 2 is good when latency is low (same-country), 2~4 for android-clients, 2~6 for cross-atlantic. Max is 6 in most browsers. Big values increase network-speed but may reduce HDD-speed")
|
1024
1026
|
ap2.add_argument("--u2sz", metavar="N,N,N", type=u, default="1,64,96", help="web-client: default upload chunksize (MiB); sets \033[33mmin,default,max\033[0m in the settings gui. Each HTTP POST will aim for \033[33mdefault\033[0m, and never exceed \033[33mmax\033[0m. Cloudflare max is 96. Big values are good for cross-atlantic but may increase HDD fragmentation on some FS. Disable this optimization with [\033[32m1,1,1\033[0m]")
|
1025
1027
|
ap2.add_argument("--u2ow", metavar="NUM", type=int, default=0, help="web-client: default setting for when to replace/overwrite existing files; [\033[32m0\033[0m]=never, [\033[32m1\033[0m]=if-client-newer, [\033[32m2\033[0m]=always (volflag=u2ow)")
|
@@ -1261,6 +1263,7 @@ def add_optouts(ap):
|
|
1261
1263
|
ap2.add_argument("--no-tarcmp", action="store_true", help="disable download as compressed tar (?tar=gz, ?tar=bz2, ?tar=xz, ?tar=gz:9, ...)")
|
1262
1264
|
ap2.add_argument("--no-lifetime", action="store_true", help="do not allow clients (or server config) to schedule an upload to be deleted after a given time")
|
1263
1265
|
ap2.add_argument("--no-pipe", action="store_true", help="disable race-the-beam (lockstep download of files which are currently being uploaded) (volflag=nopipe)")
|
1266
|
+
ap2.add_argument("--no-tail", action="store_true", help="disable streaming a growing files with ?tail (volflag=notail)")
|
1264
1267
|
ap2.add_argument("--no-db-ip", action="store_true", help="do not write uploader-IP into the database; will also disable unpost, you may want \033[32m--forget-ip\033[0m instead (volflag=no_db_ip)")
|
1265
1268
|
|
1266
1269
|
|
@@ -1390,6 +1393,16 @@ def add_transcoding(ap):
|
|
1390
1393
|
ap2.add_argument("--ac-maxage", metavar="SEC", type=int, default=86400, help="delete cached transcode output after \033[33mSEC\033[0m seconds")
|
1391
1394
|
|
1392
1395
|
|
1396
|
+
def add_tail(ap):
|
1397
|
+
ap2 = ap.add_argument_group('tailing options (realtime streaming of a growing file)')
|
1398
|
+
ap2.add_argument("--tail-who", metavar="LVL", type=int, default=2, help="who can tail? [\033[32m0\033[0m]=nobody, [\033[32m1\033[0m]=admins, [\033[32m2\033[0m]=authenticated-with-read-access, [\033[32m3\033[0m]=everyone-with-read-access (volflag=tail_who)")
|
1399
|
+
ap2.add_argument("--tail-cmax", metavar="N", type=int, default=64, help="do not allow starting a new tail if more than \033[33mN\033[0m active downloads")
|
1400
|
+
ap2.add_argument("--tail-tmax", metavar="SEC", type=float, default=0, help="terminate connection after \033[33mSEC\033[0m seconds; [\033[32m0\033[0m]=never (volflag=tail_tmax)")
|
1401
|
+
ap2.add_argument("--tail-rate", metavar="SEC", type=float, default=0.2, help="check for new data every \033[33mSEC\033[0m seconds (volflag=tail_rate)")
|
1402
|
+
ap2.add_argument("--tail-ka", metavar="SEC", type=float, default=3.0, help="send a zerobyte if connection is idle for \033[33mSEC\033[0m seconds to prevent disconnect")
|
1403
|
+
ap2.add_argument("--tail-fd", metavar="SEC", type=float, default=1.0, help="check if file was replaced (new fd) if idle for \033[33mSEC\033[0m seconds (volflag=tail_fd)")
|
1404
|
+
|
1405
|
+
|
1393
1406
|
def add_rss(ap):
|
1394
1407
|
ap2 = ap.add_argument_group('RSS options')
|
1395
1408
|
ap2.add_argument("--rss", action="store_true", help="enable RSS output (experimental) (volflag=rss)")
|
@@ -1485,6 +1498,7 @@ def add_ui(ap, retry):
|
|
1485
1498
|
ap2.add_argument("--sort", metavar="C,C,C", type=u, default="href", help="default sort order, comma-separated column IDs (see header tooltips), prefix with '-' for descending. Examples: \033[32mhref -href ext sz ts tags/Album tags/.tn\033[0m (volflag=sort)")
|
1486
1499
|
ap2.add_argument("--nsort", action="store_true", help="default-enable natural sort of filenames with leading numbers (volflag=nsort)")
|
1487
1500
|
ap2.add_argument("--hsortn", metavar="N", type=int, default=2, help="number of sorting rules to include in media URLs by default (volflag=hsortn)")
|
1501
|
+
ap2.add_argument("--see-dots", action="store_true", help="default-enable seeing dotfiles; only takes effect if user has the necessary permissions")
|
1488
1502
|
ap2.add_argument("--unlist", metavar="REGEX", type=u, default="", help="don't show files matching \033[33mREGEX\033[0m in file list. Purely cosmetic! Does not affect API calls, just the browser. Example: [\033[32m\\.(js|css)$\033[0m] (volflag=unlist)")
|
1489
1503
|
ap2.add_argument("--favico", metavar="TXT", type=u, default="c 000 none" if retry else "🎉 000 none", help="\033[33mfavicon-text\033[0m [ \033[33mforeground\033[0m [ \033[33mbackground\033[0m ] ], set blank to disable")
|
1490
1504
|
ap2.add_argument("--ext-th", metavar="E=VP", type=u, action="append", help="use thumbnail-image \033[33mVP\033[0m for file-extension \033[33mE\033[0m, example: [\033[32mexe=/.res/exe.png\033[0m] (volflag=ext_th)")
|
@@ -1594,6 +1608,7 @@ def run_argparse(
|
|
1594
1608
|
add_hooks(ap)
|
1595
1609
|
add_stats(ap)
|
1596
1610
|
add_txt(ap)
|
1611
|
+
add_tail(ap)
|
1597
1612
|
add_og(ap)
|
1598
1613
|
add_ui(ap, retry)
|
1599
1614
|
add_admin(ap)
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
-
VERSION = (1,
|
4
|
-
CODENAME = "
|
5
|
-
BUILD_DT = (2025,
|
3
|
+
VERSION = (1, 18, 0)
|
4
|
+
CODENAME = "logtail"
|
5
|
+
BUILD_DT = (2025, 6, 22)
|
6
6
|
|
7
7
|
S_VERSION = ".".join(map(str, VERSION))
|
8
8
|
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
|
@@ -65,7 +65,9 @@ SSEELOG = " ({})".format(SEE_LOG)
|
|
65
65
|
BAD_CFG = "invalid config; {}".format(SEE_LOG)
|
66
66
|
SBADCFG = " ({})".format(BAD_CFG)
|
67
67
|
|
68
|
-
PTN_U_GRP = re.compile(r"\$\{u%
|
68
|
+
PTN_U_GRP = re.compile(r"\$\{u(%[+-][^}]+)\}")
|
69
|
+
PTN_G_GRP = re.compile(r"\$\{g(%[+-][^}]+)\}")
|
70
|
+
PTN_SIGIL = re.compile(r"(\${[ug][}%])")
|
69
71
|
|
70
72
|
|
71
73
|
class CfgEx(Exception):
|
@@ -350,7 +352,6 @@ class VFS(object):
|
|
350
352
|
self.flags = flags # config options
|
351
353
|
self.root = self
|
352
354
|
self.dev = 0 # st_dev
|
353
|
-
self.badcfg1 = False
|
354
355
|
self.nodes = {} # child nodes
|
355
356
|
self.histtab = {} # all realpath->histpath
|
356
357
|
self.dbpaths = {} # all realpath->dbpath
|
@@ -870,6 +871,7 @@ class AuthSrv(object):
|
|
870
871
|
self.warn_anonwrite = warn_anonwrite
|
871
872
|
self.line_ctr = 0
|
872
873
|
self.indent = ""
|
874
|
+
self.is_lxc = args.c == ["/z/initcfg"]
|
873
875
|
|
874
876
|
# fwd-decl
|
875
877
|
self.vfs = VFS(log_func, "", "", "", AXS(), {})
|
@@ -880,6 +882,8 @@ class AuthSrv(object):
|
|
880
882
|
self.defpw = {}
|
881
883
|
self.grps = {}
|
882
884
|
self.re_pwd = None
|
885
|
+
self.cfg_files_loaded = []
|
886
|
+
self.badcfg1 = False
|
883
887
|
|
884
888
|
# all volumes observed since last restart
|
885
889
|
self.idp_vols = {} # vpath->abspath
|
@@ -956,15 +960,27 @@ class AuthSrv(object):
|
|
956
960
|
un_gn = [("", "")]
|
957
961
|
|
958
962
|
for un, gn in un_gn:
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
if req == "+":
|
964
|
-
if not hit:
|
965
|
-
continue
|
966
|
-
elif hit:
|
963
|
+
rejected = False
|
964
|
+
for ptn in [PTN_U_GRP, PTN_G_GRP]:
|
965
|
+
m = ptn.search(dst0)
|
966
|
+
if not m:
|
967
967
|
continue
|
968
|
+
zs = m.group(1)
|
969
|
+
zs = zs.replace(",%+", "\n%+")
|
970
|
+
zs = zs.replace(",%-", "\n%-")
|
971
|
+
for rule in zs.split("\n"):
|
972
|
+
gnc = rule[2:]
|
973
|
+
if ptn == PTN_U_GRP:
|
974
|
+
# is user member of group?
|
975
|
+
hit = gnc in (un_gns.get(un) or [])
|
976
|
+
else:
|
977
|
+
# is it this specific group?
|
978
|
+
hit = gn == gnc
|
979
|
+
|
980
|
+
if rule.startswith("%+") != hit:
|
981
|
+
rejected = True
|
982
|
+
if rejected:
|
983
|
+
continue
|
968
984
|
|
969
985
|
# if ap/vp has a user/group placeholder, make sure to keep
|
970
986
|
# track so the same user/group is mapped when setting perms;
|
@@ -979,6 +995,8 @@ class AuthSrv(object):
|
|
979
995
|
|
980
996
|
src = src1.replace("${g}", gn or "\n")
|
981
997
|
dst = dst1.replace("${g}", gn or "\n")
|
998
|
+
src = PTN_G_GRP.sub(gn or "\n", src)
|
999
|
+
dst = PTN_G_GRP.sub(gn or "\n", dst)
|
982
1000
|
if src == src1 and dst == dst1:
|
983
1001
|
gn = ""
|
984
1002
|
|
@@ -1475,8 +1493,10 @@ class AuthSrv(object):
|
|
1475
1493
|
daxs = {}
|
1476
1494
|
mflags = {} # vpath:flags
|
1477
1495
|
mount = {} # dst:src (vp:(ap,vp0))
|
1496
|
+
cfg_files_loaded = []
|
1478
1497
|
|
1479
1498
|
self.idp_vols = {} # yolo
|
1499
|
+
self.badcfg1 = False
|
1480
1500
|
|
1481
1501
|
if self.args.a:
|
1482
1502
|
# list of username:password
|
@@ -1537,6 +1557,7 @@ class AuthSrv(object):
|
|
1537
1557
|
zst = [(max(0, len(x) - 2) * " ") + "└" + x[-1] for x in zstt]
|
1538
1558
|
t = "loaded {} config files:\n{}"
|
1539
1559
|
self.log(t.format(len(zst), "\n".join(zst)))
|
1560
|
+
cfg_files_loaded = zst
|
1540
1561
|
|
1541
1562
|
except:
|
1542
1563
|
lns = lns[: self.line_ctr]
|
@@ -1561,9 +1582,14 @@ class AuthSrv(object):
|
|
1561
1582
|
if not mount and not self.args.idp_h_usr:
|
1562
1583
|
# -h says our defaults are CWD at root and read/write for everyone
|
1563
1584
|
axs = AXS(["*"], ["*"], None, None)
|
1564
|
-
if
|
1565
|
-
t = "Read-access has been disabled due to failsafe: Docker detected, but
|
1566
|
-
|
1585
|
+
if self.is_lxc:
|
1586
|
+
t = "Read-access has been disabled due to failsafe: Docker detected, but %s. 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 all of /w/ by adding the following arguments to the docker container: -v .::rw"
|
1587
|
+
if len(cfg_files_loaded) == 1:
|
1588
|
+
self.log(t % ("no config-file was provided",), 1)
|
1589
|
+
t = "it is strongly recommended to add a config-file instead, for example based on https://github.com/9001/copyparty/blob/hovudstraum/docs/examples/docker/basic-docker-compose/copyparty.conf"
|
1590
|
+
self.log(t, 3)
|
1591
|
+
else:
|
1592
|
+
self.log(t % ("the config does not define any volumes",), 1)
|
1567
1593
|
axs = AXS()
|
1568
1594
|
elif self.args.c:
|
1569
1595
|
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"
|
@@ -1571,7 +1597,7 @@ class AuthSrv(object):
|
|
1571
1597
|
axs = AXS()
|
1572
1598
|
vfs = VFS(self.log_func, absreal("."), "", "", axs, {})
|
1573
1599
|
if not axs.uread:
|
1574
|
-
|
1600
|
+
self.badcfg1 = True
|
1575
1601
|
elif "" not in mount:
|
1576
1602
|
# there's volumes but no root; make root inaccessible
|
1577
1603
|
zsd = {"d2d": True, "tcolor": self.args.tcolor}
|
@@ -1845,7 +1871,7 @@ class AuthSrv(object):
|
|
1845
1871
|
is_shr = shr and zv.vpath.split("/")[0] == shr
|
1846
1872
|
if histp and not is_shr and histp in rhisttab:
|
1847
1873
|
zv2 = rhisttab[histp]
|
1848
|
-
t = "invalid config; multiple volumes share the same histpath (database+thumbnails location):\n histpath: %s\n volume 1: /%s [%s]\n volume 2:
|
1874
|
+
t = "invalid config; multiple volumes share the same histpath (database+thumbnails location):\n histpath: %s\n volume 1: /%s [%s]\n volume 2: /%s [%s]"
|
1849
1875
|
t = t % (histp, zv2.vpath, zv2.realpath, zv.vpath, zv.realpath)
|
1850
1876
|
self.log(t, 1)
|
1851
1877
|
raise Exception(t)
|
@@ -1859,7 +1885,7 @@ class AuthSrv(object):
|
|
1859
1885
|
is_shr = shr and zv.vpath.split("/")[0] == shr
|
1860
1886
|
if dbp and not is_shr and dbp in rdbpaths:
|
1861
1887
|
zv2 = rdbpaths[dbp]
|
1862
|
-
t = "invalid config; multiple volumes share the same dbpath (database location):\n dbpath: %s\n volume 1: /%s [%s]\n volume 2:
|
1888
|
+
t = "invalid config; multiple volumes share the same dbpath (database location):\n dbpath: %s\n volume 1: /%s [%s]\n volume 2: /%s [%s]"
|
1863
1889
|
t = t % (dbp, zv2.vpath, zv2.realpath, zv.vpath, zv.realpath)
|
1864
1890
|
self.log(t, 1)
|
1865
1891
|
raise Exception(t)
|
@@ -2042,12 +2068,13 @@ class AuthSrv(object):
|
|
2042
2068
|
if vf not in vol.flags:
|
2043
2069
|
vol.flags[vf] = getattr(self.args, ga)
|
2044
2070
|
|
2045
|
-
zs = "forget_ip nrand u2abort u2ow ups_who zip_who"
|
2071
|
+
zs = "forget_ip nrand tail_who u2abort u2ow ups_who zip_who"
|
2046
2072
|
for k in zs.split():
|
2047
2073
|
if k in vol.flags:
|
2048
2074
|
vol.flags[k] = int(vol.flags[k])
|
2049
2075
|
|
2050
|
-
|
2076
|
+
zs = "convt tail_fd tail_rate tail_tmax"
|
2077
|
+
for k in zs.split():
|
2051
2078
|
if k in vol.flags:
|
2052
2079
|
vol.flags[k] = float(vol.flags[k])
|
2053
2080
|
|
@@ -2376,7 +2403,7 @@ class AuthSrv(object):
|
|
2376
2403
|
idp_vn, _ = vfs.get(idp_vp, "*", False, False)
|
2377
2404
|
idp_vp0 = idp_vn.vpath0
|
2378
2405
|
|
2379
|
-
sigils = set(
|
2406
|
+
sigils = set(PTN_SIGIL.findall(idp_vp0))
|
2380
2407
|
if len(sigils) > 1:
|
2381
2408
|
t = '\nWARNING: IdP-volume "/%s" created by "/%s" has multiple IdP placeholders: %s'
|
2382
2409
|
self.idp_warn.append(t % (idp_vp, idp_vp0, list(sigils)))
|
@@ -2426,6 +2453,7 @@ class AuthSrv(object):
|
|
2426
2453
|
self.defpw = defpw
|
2427
2454
|
self.grps = grps
|
2428
2455
|
self.iacct = {v: k for k, v in acct.items()}
|
2456
|
+
self.cfg_files_loaded = cfg_files_loaded
|
2429
2457
|
|
2430
2458
|
self.load_sessions()
|
2431
2459
|
|
@@ -2545,6 +2573,7 @@ class AuthSrv(object):
|
|
2545
2573
|
"txt_ext": self.args.textfiles.replace(",", " "),
|
2546
2574
|
"def_hcols": list(vf.get("mth") or []),
|
2547
2575
|
"unlist0": vf.get("unlist") or "",
|
2576
|
+
"see_dots": self.args.see_dots,
|
2548
2577
|
"dgrid": "grid" in vf,
|
2549
2578
|
"dgsel": "gsel" in vf,
|
2550
2579
|
"dnsort": "nsort" in vf,
|
@@ -2556,6 +2585,7 @@ class AuthSrv(object):
|
|
2556
2585
|
"idxh": int(self.args.ih),
|
2557
2586
|
"themes": self.args.themes,
|
2558
2587
|
"turbolvl": self.args.turbo,
|
2588
|
+
"nosubtle": self.args.nosubtle,
|
2559
2589
|
"u2j": self.args.u2j,
|
2560
2590
|
"u2sz": self.args.u2sz,
|
2561
2591
|
"u2ts": vf["u2ts"],
|
@@ -22,6 +22,7 @@ def vf_bmap() :
|
|
22
22
|
"no_forget": "noforget",
|
23
23
|
"no_pipe": "nopipe",
|
24
24
|
"no_robots": "norobots",
|
25
|
+
"no_tail": "notail",
|
25
26
|
"no_thumb": "dthumb",
|
26
27
|
"no_vthumb": "dvthumb",
|
27
28
|
"no_athumb": "dathumb",
|
@@ -51,6 +52,7 @@ def vf_bmap() :
|
|
51
52
|
"og_no_head",
|
52
53
|
"og_s_title",
|
53
54
|
"rand",
|
55
|
+
"rmagic",
|
54
56
|
"rss",
|
55
57
|
"wo_up_readme",
|
56
58
|
"xdev",
|
@@ -101,6 +103,10 @@ def vf_vmap() :
|
|
101
103
|
"mv_retry",
|
102
104
|
"rm_retry",
|
103
105
|
"sort",
|
106
|
+
"tail_fd",
|
107
|
+
"tail_rate",
|
108
|
+
"tail_tmax",
|
109
|
+
"tail_who",
|
104
110
|
"tcolor",
|
105
111
|
"unlist",
|
106
112
|
"u2abort",
|
@@ -304,6 +310,13 @@ flagcats = {
|
|
304
310
|
"exp_md": "placeholders to expand in markdown files; see --help",
|
305
311
|
"exp_lg": "placeholders to expand in prologue/epilogue; see --help",
|
306
312
|
},
|
313
|
+
"tailing": {
|
314
|
+
"notail": "disable ?tail (download a growing file continuously)",
|
315
|
+
"tail_fd=1": "check if file was replaced (new fd) every 1 sec",
|
316
|
+
"tail_rate=0.2": "check for new data every 0.2 sec",
|
317
|
+
"tail_tmax=30": "kill connection after 30 sec",
|
318
|
+
"tail_who=2": "restrict ?tail access (1=admins,2=authed,3=everyone)",
|
319
|
+
},
|
307
320
|
"others": {
|
308
321
|
"dots": "allow all users with read-access to\nenable the option to show dotfiles in listings",
|
309
322
|
"fk=8": 'generates per-file accesskeys,\nwhich are then required at the "g" permission;\nkeys are invalidated if filesize or inode changes',
|
@@ -312,6 +325,7 @@ flagcats = {
|
|
312
325
|
"dks": "per-directory accesskeys allow browsing into subdirs",
|
313
326
|
"dky": 'allow seeing files (not folders) inside a specific folder\nwith "g" perm, and does not require a valid dirkey to do so',
|
314
327
|
"rss": "allow '?rss' URL suffix (experimental)",
|
328
|
+
"rmagic": "expensive analysis for mimetype accuracy",
|
315
329
|
"ups_who=2": "restrict viewing the list of recent uploads",
|
316
330
|
"zip_who=2": "restrict access to download-as-zip/tar",
|
317
331
|
"zipmaxn=9k": "reject download-as-zip if more than 9000 files",
|