copyparty 1.19.15__tar.gz → 1.19.17__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.19.15 → copyparty-1.19.17}/PKG-INFO +47 -2
 - {copyparty-1.19.15 → copyparty-1.19.17}/README.md +46 -1
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/__init__.py +19 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/__main__.py +47 -11
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/__version__.py +2 -2
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/authsrv.py +45 -9
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/bos/bos.py +5 -1
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/cfg.py +20 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/ftpd.py +5 -3
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/httpcli.py +114 -27
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/mdns.py +53 -18
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/mtag.py +18 -4
 - copyparty-1.19.17/copyparty/qrkode.py +107 -0
 - copyparty-1.19.17/copyparty/res/COPYING.txt +223 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/smbd.py +1 -1
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/stolen/qrcodegen.py +1 -64
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/svchub.py +13 -2
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/tcpsrv.py +6 -7
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/tftpd.py +1 -1
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/th_srv.py +11 -5
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/up2k.py +40 -16
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/util.py +63 -16
 - copyparty-1.19.17/copyparty/web/baguettebox.js.gz +0 -0
 - copyparty-1.19.17/copyparty/web/browser.css.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/browser.html +3 -1
 - copyparty-1.19.17/copyparty/web/browser.js.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/splash.html +3 -0
 - copyparty-1.19.17/copyparty/web/splash.js.gz +0 -0
 - copyparty-1.19.17/copyparty/web/tl/chi.js.gz +0 -0
 - copyparty-1.19.17/copyparty/web/tl/cze.js.gz +0 -0
 - copyparty-1.19.17/copyparty/web/tl/deu.js.gz +0 -0
 - copyparty-1.19.17/copyparty/web/tl/epo.js.gz +0 -0
 - copyparty-1.19.17/copyparty/web/tl/fin.js.gz +0 -0
 - copyparty-1.19.17/copyparty/web/tl/fra.js.gz +0 -0
 - copyparty-1.19.17/copyparty/web/tl/grc.js.gz +0 -0
 - copyparty-1.19.17/copyparty/web/tl/ita.js.gz +0 -0
 - copyparty-1.19.17/copyparty/web/tl/kor.js.gz +0 -0
 - copyparty-1.19.17/copyparty/web/tl/nld.js.gz +0 -0
 - copyparty-1.19.17/copyparty/web/tl/nno.js.gz +0 -0
 - copyparty-1.19.17/copyparty/web/tl/nor.js.gz +0 -0
 - copyparty-1.19.17/copyparty/web/tl/pol.js.gz +0 -0
 - copyparty-1.19.17/copyparty/web/tl/por.js.gz +0 -0
 - copyparty-1.19.17/copyparty/web/tl/rus.js.gz +0 -0
 - copyparty-1.19.17/copyparty/web/tl/spa.js.gz +0 -0
 - copyparty-1.19.17/copyparty/web/tl/swe.js.gz +0 -0
 - copyparty-1.19.17/copyparty/web/tl/tur.js.gz +0 -0
 - copyparty-1.19.17/copyparty/web/tl/ukr.js.gz +0 -0
 - copyparty-1.19.17/copyparty/web/util.js.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty.egg-info/PKG-INFO +47 -2
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty.egg-info/SOURCES.txt +21 -1
 - {copyparty-1.19.15 → copyparty-1.19.17}/pyproject.toml +2 -0
 - copyparty-1.19.15/copyparty/res/COPYING.txt +0 -152
 - copyparty-1.19.15/copyparty/web/baguettebox.js.gz +0 -0
 - copyparty-1.19.15/copyparty/web/browser.css.gz +0 -0
 - copyparty-1.19.15/copyparty/web/browser.js.gz +0 -0
 - copyparty-1.19.15/copyparty/web/splash.js.gz +0 -0
 - copyparty-1.19.15/copyparty/web/util.js.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/LICENSE +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/bos/__init__.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/bos/path.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/broker_mp.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/broker_mpw.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/broker_thr.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/broker_util.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/cert.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/dxml.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/fsutil.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/httpconn.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/httpsrv.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/ico.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/metrics.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/multicast.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/pwhash.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/res/__init__.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/res/insecure.pem +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/ssdp.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/star.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/stolen/__init__.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/stolen/dnslib/__init__.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/stolen/dnslib/bimap.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/stolen/dnslib/bit.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/stolen/dnslib/buffer.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/stolen/dnslib/dns.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/stolen/dnslib/label.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/stolen/dnslib/lex.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/stolen/dnslib/ranges.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/stolen/ifaddr/__init__.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/stolen/ifaddr/_posix.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/stolen/ifaddr/_shared.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/stolen/ifaddr/_win32.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/stolen/surrogateescape.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/sutil.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/szip.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/th_cli.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/u2idx.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/a/__init__.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/a/partyfuse.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/a/u2c.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/a/webdav-cfg.bat +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/browser2.html +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/cf.html +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/dbg-audio.js.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/deps/__init__.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/deps/busy.mp3.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/deps/easymde.css.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/deps/easymde.js.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/deps/fuse.py +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/deps/marked.js.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/deps/mini-fa.css.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/deps/mini-fa.woff +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/deps/prism.css.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/deps/prism.js.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/deps/prismd.css.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/deps/scp.woff2 +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/deps/sha512.ac.js.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/deps/sha512.hw.js.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/idp.html +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/md.css.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/md.html +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/md.js.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/md2.css.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/md2.js.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/mde.css.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/mde.html +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/mde.js.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/msg.css.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/msg.html +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/opds.xml +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/rups.css.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/rups.html +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/rups.js.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/shares.css.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/shares.html +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/shares.js.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/splash.css.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/svcs.html +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/svcs.js.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/ui.css.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/up2k.js.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty/web/w.hash.js.gz +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty.egg-info/dependency_links.txt +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty.egg-info/entry_points.txt +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty.egg-info/requires.txt +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/copyparty.egg-info/top_level.txt +0 -0
 - {copyparty-1.19.15 → copyparty-1.19.17}/setup.cfg +0 -0
 
| 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            Metadata-Version: 2.4
         
     | 
| 
       2 
2 
     | 
    
         
             
            Name: copyparty
         
     | 
| 
       3 
     | 
    
         
            -
            Version: 1.19. 
     | 
| 
      
 3 
     | 
    
         
            +
            Version: 1.19.17
         
     | 
| 
       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
         
     | 
| 
         @@ -203,6 +203,7 @@ made in Norway 🇳🇴 
     | 
|
| 
       203 
203 
     | 
    
         
             
            * [dependencies](#dependencies) - mandatory deps
         
     | 
| 
       204 
204 
     | 
    
         
             
                * [optional dependencies](#optional-dependencies) - install these to enable bonus features
         
     | 
| 
       205 
205 
     | 
    
         
             
                    * [dependency chickenbits](#dependency-chickenbits) - prevent loading an optional dependency
         
     | 
| 
      
 206 
     | 
    
         
            +
                    * [dependency unvendoring](#dependency-unvendoring) - force use of system modules
         
     | 
| 
       206 
207 
     | 
    
         
             
                * [optional gpl stuff](#optional-gpl-stuff)
         
     | 
| 
       207 
208 
     | 
    
         
             
            * [sfx](#sfx) - the self-contained "binary" (recommended!)
         
     | 
| 
       208 
209 
     | 
    
         
             
                * [copyparty.exe](#copypartyexe) - download [copyparty.exe](https://github.com/9001/copyparty/releases/latest/download/copyparty.exe) (win8+) or [copyparty32.exe](https://github.com/9001/copyparty/releases/latest/download/copyparty32.exe) (win7+)
         
     | 
| 
         @@ -278,6 +279,7 @@ you may also want these, especially on servers: 
     | 
|
| 
       278 
279 
     | 
    
         | 
| 
       279 
280 
     | 
    
         
             
            * [contrib/systemd/copyparty.service](contrib/systemd/copyparty.service) to run copyparty as a systemd service (see guide inside)
         
     | 
| 
       280 
281 
     | 
    
         
             
            * [contrib/systemd/prisonparty.service](contrib/systemd/prisonparty.service) to run it in a chroot (for extra security)
         
     | 
| 
      
 282 
     | 
    
         
            +
            * [contrib/podman-systemd/](contrib/podman-systemd/) to run copyparty in a Podman container as a systemd service (see guide inside)
         
     | 
| 
       281 
283 
     | 
    
         
             
            * [contrib/openrc/copyparty](contrib/openrc/copyparty) to run copyparty on Alpine / Gentoo
         
     | 
| 
       282 
284 
     | 
    
         
             
            * [contrib/rc/copyparty](contrib/rc/copyparty) to run copyparty on FreeBSD
         
     | 
| 
       283 
285 
     | 
    
         
             
            * [nixos module](#nixos-module) to run copyparty on NixOS hosts
         
     | 
| 
         @@ -586,6 +588,9 @@ examples: 
     | 
|
| 
       586 
588 
     | 
    
         | 
| 
       587 
589 
     | 
    
         
             
            if you want to grant access to all users who are logged in, the group `acct` will always contain all known users, so for example `-v /mnt/music:music:r,@acct`
         
     | 
| 
       588 
590 
     | 
    
         | 
| 
      
 591 
     | 
    
         
            +
            * to do the opposite, granting access to everyone who is NOT logged in. `*,-@acct` does the trick, for example `-v /srv/welcome:welcome:r,*,-@acct`
         
     | 
| 
      
 592 
     | 
    
         
            +
            * single users can also be subtracted from a group: `@admins,-james`
         
     | 
| 
      
 593 
     | 
    
         
            +
             
     | 
| 
       589 
594 
     | 
    
         
             
            anyone trying to bruteforce a password gets banned according to `--ban-pw`; default is 24h ban for 9 failed attempts in 1 hour
         
     | 
| 
       590 
595 
     | 
    
         | 
| 
       591 
596 
     | 
    
         
             
            and if you want to use config files instead of commandline args (good!) then here's the same examples as a configfile; save it as `foobar.conf` and use it like this: `python copyparty-sfx.py -c foobar.conf`
         
     | 
| 
         @@ -794,6 +799,10 @@ to show `/icons/exe.png` and `/icons/elf.gif` as the thumbnail for all `.exe` an 
     | 
|
| 
       794 
799 
     | 
    
         
             
            * the supported image formats are [jpg, png, gif, webp, ico](https://developer.mozilla.org/en-US/docs/Web/Media/Guides/Formats/Image_types)
         
     | 
| 
       795 
800 
     | 
    
         
             
              * 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
         
     | 
| 
       796 
801 
     | 
    
         | 
| 
      
 802 
     | 
    
         
            +
            note:
         
     | 
| 
      
 803 
     | 
    
         
            +
            * heif/heifs/heic/heics images usually require the `libvips` [optional dependency](#optional-dependencies) (available in the `iv` docker image, `withFastThumbnails` in nixos)
         
     | 
| 
      
 804 
     | 
    
         
            +
              * technical trivia: FFmpeg has basic support for tiled heic as of v7.0; need `-show_stream_groups` for correct resolution
         
     | 
| 
      
 805 
     | 
    
         
            +
             
     | 
| 
       797 
806 
     | 
    
         
             
            config file example:
         
     | 
| 
       798 
807 
     | 
    
         | 
| 
       799 
808 
     | 
    
         
             
            ```yaml
         
     | 
| 
         @@ -1062,6 +1071,8 @@ available functions: 
     | 
|
| 
       1062 
1071 
     | 
    
         
             
            * `$lpad(text, length, pad_char)`
         
     | 
| 
       1063 
1072 
     | 
    
         
             
            * `$rpad(text, length, pad_char)`
         
     | 
| 
       1064 
1073 
     | 
    
         | 
| 
      
 1074 
     | 
    
         
            +
            two counters are available; `.n.s` is the nth file in the selection, and `.n.d` the nth file in the folder, for example rename-output `file(.n.d).(ext)` gives `file5.bin`, and `beach-$lpad((.n.s),3,0).(ext)` is `beach-017.jpg` and the initial value of each counter can be set in the textboxes underneath the preset dropdown
         
     | 
| 
      
 1075 
     | 
    
         
            +
             
     | 
| 
       1065 
1076 
     | 
    
         
             
            so,
         
     | 
| 
       1066 
1077 
     | 
    
         | 
| 
       1067 
1078 
     | 
    
         
             
            say you have a file named [`meganeko - Eclipse - 07 Sirius A.mp3`](https://www.youtube.com/watch?v=-dtb0vDPruI) (absolutely fantastic album btw) and the tags are: `Album:Eclipse`, `Artist:meganeko`, `Title:Sirius A`, `tn:7`
         
     | 
| 
         @@ -1097,6 +1108,8 @@ url parameters: 
     | 
|
| 
       1097 
1108 
     | 
    
         | 
| 
       1098 
1109 
     | 
    
         
             
            * `pw=hunter2` for password auth
         
     | 
| 
       1099 
1110 
     | 
    
         
             
              * if you enabled `--usernames` then do `pw=username:password` instead
         
     | 
| 
      
 1111 
     | 
    
         
            +
            * `nopw` disables embedding the password (if provided) into item-URLs in the feed
         
     | 
| 
      
 1112 
     | 
    
         
            +
            * `nopw=a` disables mentioning the password anywhere at all in the feed; may break some readers
         
     | 
| 
       1100 
1113 
     | 
    
         
             
            * `recursive` to also include subfolders
         
     | 
| 
       1101 
1114 
     | 
    
         
             
            * `title=foo` changes the feed title (default: folder name)
         
     | 
| 
       1102 
1115 
     | 
    
         
             
            * `fext=mp3,opus` only include mp3 and opus files (default: all)
         
     | 
| 
         @@ -1163,6 +1176,7 @@ some highlights: 
     | 
|
| 
       1163 
1176 
     | 
    
         
             
            * shows the audio waveform in the seekbar
         
     | 
| 
       1164 
1177 
     | 
    
         
             
            * not perfectly gapless but can get really close (see settings + eq below); good enough to enjoy gapless albums as intended
         
     | 
| 
       1165 
1178 
     | 
    
         
             
            * videos can be played as audio, without wasting bandwidth on the video
         
     | 
| 
      
 1179 
     | 
    
         
            +
            * adding `?v` to the end of an audio/video/image link will make it open in the mediaplayer
         
     | 
| 
       1166 
1180 
     | 
    
         | 
| 
       1167 
1181 
     | 
    
         
             
            click the `play` link next to an audio file, or copy the link target to [share it](https://a.ocv.me/pub/demo/music/Ubiktune%20-%20SOUNDSHOCK%202%20-%20FM%20FUNK%20TERRROR!!/#af-1fbfba61&t=18) (optionally with a timestamp to start playing from, like that example does)
         
     | 
| 
       1168 
1182 
     | 
    
         | 
| 
         @@ -1547,7 +1561,12 @@ tweaking the ui 
     | 
|
| 
       1547 
1561 
     | 
    
         
             
              * to sort in music order (album, track, artist, title) with filename as fallback, you could `--sort tags/Circle,tags/.tn,tags/Artist,tags/Title,href`
         
     | 
| 
       1548 
1562 
     | 
    
         
             
              * to sort by upload date, first enable showing the upload date in the listing with `-e2d -mte +.up_at` and then `--sort tags/.up_at`
         
     | 
| 
       1549 
1563 
     | 
    
         | 
| 
       1550 
     | 
    
         
            -
            see [./docs/rice](./docs/rice) for more, including 
     | 
| 
      
 1564 
     | 
    
         
            +
            see [./docs/rice](./docs/rice) for more, including:
         
     | 
| 
      
 1565 
     | 
    
         
            +
            * how to [hide ui-elements](./docs/rice/README.md#hide-ui-elements)
         
     | 
| 
      
 1566 
     | 
    
         
            +
            * [custom fonts](./docs/rice/README.md#custom-fonts)
         
     | 
| 
      
 1567 
     | 
    
         
            +
            * [custom loading-spinner](./docs/rice/README.md#boring-loader-spinner)
         
     | 
| 
      
 1568 
     | 
    
         
            +
            * adding stuff (css/`<meta>`/...) [to the html `<head>` tag](./docs/rice/README.md#head)
         
     | 
| 
      
 1569 
     | 
    
         
            +
            * [adding your own translation](./docs/rice/README.md#translations)
         
     | 
| 
       1551 
1570 
     | 
    
         | 
| 
       1552 
1571 
     | 
    
         | 
| 
       1553 
1572 
     | 
    
         
             
            ## opengraph
         
     | 
| 
         @@ -2530,6 +2549,10 @@ copyparty on NixOS is configured via `services.copyparty` options, for example: 
     | 
|
| 
       2530 
2549 
     | 
    
         
             
            ```nix
         
     | 
| 
       2531 
2550 
     | 
    
         
             
            services.copyparty = {
         
     | 
| 
       2532 
2551 
     | 
    
         
             
              enable = true;
         
     | 
| 
      
 2552 
     | 
    
         
            +
              # the user to run the service as
         
     | 
| 
      
 2553 
     | 
    
         
            +
              user = "copyparty"; 
         
     | 
| 
      
 2554 
     | 
    
         
            +
              # the group to run the service as
         
     | 
| 
      
 2555 
     | 
    
         
            +
              group = "copyparty"; 
         
     | 
| 
       2533 
2556 
     | 
    
         
             
              # directly maps to values in the [global] section of the copyparty config.
         
     | 
| 
       2534 
2557 
     | 
    
         
             
              # see `copyparty --help` for available options
         
     | 
| 
       2535 
2558 
     | 
    
         
             
              settings = {
         
     | 
| 
         @@ -2554,6 +2577,12 @@ services.copyparty = { 
     | 
|
| 
       2554 
2577 
     | 
    
         
             
                k.passwordFile = "/run/keys/copyparty/k_password";
         
     | 
| 
       2555 
2578 
     | 
    
         
             
              };
         
     | 
| 
       2556 
2579 
     | 
    
         | 
| 
      
 2580 
     | 
    
         
            +
              # create a group
         
     | 
| 
      
 2581 
     | 
    
         
            +
              groups = {
         
     | 
| 
      
 2582 
     | 
    
         
            +
                # users "ed" and "k" are part of the group g1
         
     | 
| 
      
 2583 
     | 
    
         
            +
                g1 = [ "ed" "k" ];
         
     | 
| 
      
 2584 
     | 
    
         
            +
              };
         
     | 
| 
      
 2585 
     | 
    
         
            +
             
     | 
| 
       2557 
2586 
     | 
    
         
             
              # create a volume
         
     | 
| 
       2558 
2587 
     | 
    
         
             
              volumes = {
         
     | 
| 
       2559 
2588 
     | 
    
         
             
                # create a volume at "/" (the webroot), which will
         
     | 
| 
         @@ -3043,6 +3072,20 @@ example: `PRTY_NO_PIL=1 python3 copyparty-sfx.py` 
     | 
|
| 
       3043 
3072 
     | 
    
         
             
            * python2.7 on windows: `PRTY_NO_FFMPEG` + `PRTY_NO_FFPROBE` saves startup time
         
     | 
| 
       3044 
3073 
     | 
    
         | 
| 
       3045 
3074 
     | 
    
         | 
| 
      
 3075 
     | 
    
         
            +
            ### dependency unvendoring
         
     | 
| 
      
 3076 
     | 
    
         
            +
             
     | 
| 
      
 3077 
     | 
    
         
            +
            force use of system modules  instead of the vendored versions:
         
     | 
| 
      
 3078 
     | 
    
         
            +
             
     | 
| 
      
 3079 
     | 
    
         
            +
            | env-var              | what it does |
         
     | 
| 
      
 3080 
     | 
    
         
            +
            | -------------------- | ------------ |
         
     | 
| 
      
 3081 
     | 
    
         
            +
            | `PRTY_SYS_ALL`       | all of the below |
         
     | 
| 
      
 3082 
     | 
    
         
            +
            | `PRTY_SYS_DNSLIB`    | replace [stolen/dnslib](./copyparty/stolen/dnslib) with [upstream](https://pypi.org/project/dnslib/) |
         
     | 
| 
      
 3083 
     | 
    
         
            +
            | `PRTY_SYS_IFADDR`    | replace [stolen/ifaddr](./copyparty/stolen/ifaddr) with [upstream](https://pypi.org/project/ifaddr/) |
         
     | 
| 
      
 3084 
     | 
    
         
            +
            | `PRTY_SYS_QRCG`      | replace [stolen/qrcodegen.py](./copyparty/stolen/qrcodegen.py) with [upstream](https://github.com/nayuki/QR-Code-generator/blob/master/python/qrcodegen.py) |
         
     | 
| 
      
 3085 
     | 
    
         
            +
             
     | 
| 
      
 3086 
     | 
    
         
            +
            to debug, run copyparty with `PRTY_MODSPEC=1` to see where it's getting each module from
         
     | 
| 
      
 3087 
     | 
    
         
            +
             
     | 
| 
      
 3088 
     | 
    
         
            +
             
     | 
| 
       3046 
3089 
     | 
    
         
             
            ## optional gpl stuff
         
     | 
| 
       3047 
3090 
     | 
    
         | 
| 
       3048 
3091 
     | 
    
         
             
            some bundled tools have copyleft dependencies, see [./bin/#mtag](bin/#mtag)
         
     | 
| 
         @@ -3105,6 +3148,8 @@ if you want thumbnails (photos+videos) and you're okay with spending another 132 
     | 
|
| 
       3105 
3148 
     | 
    
         | 
| 
       3106 
3149 
     | 
    
         
             
            * or if you want to use `vips` for photo-thumbs instead, `pkg install libvips && python -m pip install --user -U wheel && python -m pip install --user -U pyvips && (cd /data/data/com.termux/files/usr/lib/; ln -s libgobject-2.0.so{,.0}; ln -s libvips.so{,.42})`
         
     | 
| 
       3107 
3150 
     | 
    
         | 
| 
      
 3151 
     | 
    
         
            +
            if you are suddenly unable to access storage (permission issues), try forcequitting termux, revoke all of its permissions in android settings, and run the command `termux-setup-storage`
         
     | 
| 
      
 3152 
     | 
    
         
            +
             
     | 
| 
       3108 
3153 
     | 
    
         | 
| 
       3109 
3154 
     | 
    
         
             
            # install on iOS
         
     | 
| 
       3110 
3155 
     | 
    
         | 
| 
         @@ -138,6 +138,7 @@ made in Norway 🇳🇴 
     | 
|
| 
       138 
138 
     | 
    
         
             
            * [dependencies](#dependencies) - mandatory deps
         
     | 
| 
       139 
139 
     | 
    
         
             
                * [optional dependencies](#optional-dependencies) - install these to enable bonus features
         
     | 
| 
       140 
140 
     | 
    
         
             
                    * [dependency chickenbits](#dependency-chickenbits) - prevent loading an optional dependency
         
     | 
| 
      
 141 
     | 
    
         
            +
                    * [dependency unvendoring](#dependency-unvendoring) - force use of system modules
         
     | 
| 
       141 
142 
     | 
    
         
             
                * [optional gpl stuff](#optional-gpl-stuff)
         
     | 
| 
       142 
143 
     | 
    
         
             
            * [sfx](#sfx) - the self-contained "binary" (recommended!)
         
     | 
| 
       143 
144 
     | 
    
         
             
                * [copyparty.exe](#copypartyexe) - download [copyparty.exe](https://github.com/9001/copyparty/releases/latest/download/copyparty.exe) (win8+) or [copyparty32.exe](https://github.com/9001/copyparty/releases/latest/download/copyparty32.exe) (win7+)
         
     | 
| 
         @@ -213,6 +214,7 @@ you may also want these, especially on servers: 
     | 
|
| 
       213 
214 
     | 
    
         | 
| 
       214 
215 
     | 
    
         
             
            * [contrib/systemd/copyparty.service](contrib/systemd/copyparty.service) to run copyparty as a systemd service (see guide inside)
         
     | 
| 
       215 
216 
     | 
    
         
             
            * [contrib/systemd/prisonparty.service](contrib/systemd/prisonparty.service) to run it in a chroot (for extra security)
         
     | 
| 
      
 217 
     | 
    
         
            +
            * [contrib/podman-systemd/](contrib/podman-systemd/) to run copyparty in a Podman container as a systemd service (see guide inside)
         
     | 
| 
       216 
218 
     | 
    
         
             
            * [contrib/openrc/copyparty](contrib/openrc/copyparty) to run copyparty on Alpine / Gentoo
         
     | 
| 
       217 
219 
     | 
    
         
             
            * [contrib/rc/copyparty](contrib/rc/copyparty) to run copyparty on FreeBSD
         
     | 
| 
       218 
220 
     | 
    
         
             
            * [nixos module](#nixos-module) to run copyparty on NixOS hosts
         
     | 
| 
         @@ -521,6 +523,9 @@ examples: 
     | 
|
| 
       521 
523 
     | 
    
         | 
| 
       522 
524 
     | 
    
         
             
            if you want to grant access to all users who are logged in, the group `acct` will always contain all known users, so for example `-v /mnt/music:music:r,@acct`
         
     | 
| 
       523 
525 
     | 
    
         | 
| 
      
 526 
     | 
    
         
            +
            * to do the opposite, granting access to everyone who is NOT logged in. `*,-@acct` does the trick, for example `-v /srv/welcome:welcome:r,*,-@acct`
         
     | 
| 
      
 527 
     | 
    
         
            +
            * single users can also be subtracted from a group: `@admins,-james`
         
     | 
| 
      
 528 
     | 
    
         
            +
             
     | 
| 
       524 
529 
     | 
    
         
             
            anyone trying to bruteforce a password gets banned according to `--ban-pw`; default is 24h ban for 9 failed attempts in 1 hour
         
     | 
| 
       525 
530 
     | 
    
         | 
| 
       526 
531 
     | 
    
         
             
            and if you want to use config files instead of commandline args (good!) then here's the same examples as a configfile; save it as `foobar.conf` and use it like this: `python copyparty-sfx.py -c foobar.conf`
         
     | 
| 
         @@ -729,6 +734,10 @@ to show `/icons/exe.png` and `/icons/elf.gif` as the thumbnail for all `.exe` an 
     | 
|
| 
       729 
734 
     | 
    
         
             
            * the supported image formats are [jpg, png, gif, webp, ico](https://developer.mozilla.org/en-US/docs/Web/Media/Guides/Formats/Image_types)
         
     | 
| 
       730 
735 
     | 
    
         
             
              * 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
         
     | 
| 
       731 
736 
     | 
    
         | 
| 
      
 737 
     | 
    
         
            +
            note:
         
     | 
| 
      
 738 
     | 
    
         
            +
            * heif/heifs/heic/heics images usually require the `libvips` [optional dependency](#optional-dependencies) (available in the `iv` docker image, `withFastThumbnails` in nixos)
         
     | 
| 
      
 739 
     | 
    
         
            +
              * technical trivia: FFmpeg has basic support for tiled heic as of v7.0; need `-show_stream_groups` for correct resolution
         
     | 
| 
      
 740 
     | 
    
         
            +
             
     | 
| 
       732 
741 
     | 
    
         
             
            config file example:
         
     | 
| 
       733 
742 
     | 
    
         | 
| 
       734 
743 
     | 
    
         
             
            ```yaml
         
     | 
| 
         @@ -997,6 +1006,8 @@ available functions: 
     | 
|
| 
       997 
1006 
     | 
    
         
             
            * `$lpad(text, length, pad_char)`
         
     | 
| 
       998 
1007 
     | 
    
         
             
            * `$rpad(text, length, pad_char)`
         
     | 
| 
       999 
1008 
     | 
    
         | 
| 
      
 1009 
     | 
    
         
            +
            two counters are available; `.n.s` is the nth file in the selection, and `.n.d` the nth file in the folder, for example rename-output `file(.n.d).(ext)` gives `file5.bin`, and `beach-$lpad((.n.s),3,0).(ext)` is `beach-017.jpg` and the initial value of each counter can be set in the textboxes underneath the preset dropdown
         
     | 
| 
      
 1010 
     | 
    
         
            +
             
     | 
| 
       1000 
1011 
     | 
    
         
             
            so,
         
     | 
| 
       1001 
1012 
     | 
    
         | 
| 
       1002 
1013 
     | 
    
         
             
            say you have a file named [`meganeko - Eclipse - 07 Sirius A.mp3`](https://www.youtube.com/watch?v=-dtb0vDPruI) (absolutely fantastic album btw) and the tags are: `Album:Eclipse`, `Artist:meganeko`, `Title:Sirius A`, `tn:7`
         
     | 
| 
         @@ -1032,6 +1043,8 @@ url parameters: 
     | 
|
| 
       1032 
1043 
     | 
    
         | 
| 
       1033 
1044 
     | 
    
         
             
            * `pw=hunter2` for password auth
         
     | 
| 
       1034 
1045 
     | 
    
         
             
              * if you enabled `--usernames` then do `pw=username:password` instead
         
     | 
| 
      
 1046 
     | 
    
         
            +
            * `nopw` disables embedding the password (if provided) into item-URLs in the feed
         
     | 
| 
      
 1047 
     | 
    
         
            +
            * `nopw=a` disables mentioning the password anywhere at all in the feed; may break some readers
         
     | 
| 
       1035 
1048 
     | 
    
         
             
            * `recursive` to also include subfolders
         
     | 
| 
       1036 
1049 
     | 
    
         
             
            * `title=foo` changes the feed title (default: folder name)
         
     | 
| 
       1037 
1050 
     | 
    
         
             
            * `fext=mp3,opus` only include mp3 and opus files (default: all)
         
     | 
| 
         @@ -1098,6 +1111,7 @@ some highlights: 
     | 
|
| 
       1098 
1111 
     | 
    
         
             
            * shows the audio waveform in the seekbar
         
     | 
| 
       1099 
1112 
     | 
    
         
             
            * not perfectly gapless but can get really close (see settings + eq below); good enough to enjoy gapless albums as intended
         
     | 
| 
       1100 
1113 
     | 
    
         
             
            * videos can be played as audio, without wasting bandwidth on the video
         
     | 
| 
      
 1114 
     | 
    
         
            +
            * adding `?v` to the end of an audio/video/image link will make it open in the mediaplayer
         
     | 
| 
       1101 
1115 
     | 
    
         | 
| 
       1102 
1116 
     | 
    
         
             
            click the `play` link next to an audio file, or copy the link target to [share it](https://a.ocv.me/pub/demo/music/Ubiktune%20-%20SOUNDSHOCK%202%20-%20FM%20FUNK%20TERRROR!!/#af-1fbfba61&t=18) (optionally with a timestamp to start playing from, like that example does)
         
     | 
| 
       1103 
1117 
     | 
    
         | 
| 
         @@ -1482,7 +1496,12 @@ tweaking the ui 
     | 
|
| 
       1482 
1496 
     | 
    
         
             
              * to sort in music order (album, track, artist, title) with filename as fallback, you could `--sort tags/Circle,tags/.tn,tags/Artist,tags/Title,href`
         
     | 
| 
       1483 
1497 
     | 
    
         
             
              * to sort by upload date, first enable showing the upload date in the listing with `-e2d -mte +.up_at` and then `--sort tags/.up_at`
         
     | 
| 
       1484 
1498 
     | 
    
         | 
| 
       1485 
     | 
    
         
            -
            see [./docs/rice](./docs/rice) for more, including 
     | 
| 
      
 1499 
     | 
    
         
            +
            see [./docs/rice](./docs/rice) for more, including:
         
     | 
| 
      
 1500 
     | 
    
         
            +
            * how to [hide ui-elements](./docs/rice/README.md#hide-ui-elements)
         
     | 
| 
      
 1501 
     | 
    
         
            +
            * [custom fonts](./docs/rice/README.md#custom-fonts)
         
     | 
| 
      
 1502 
     | 
    
         
            +
            * [custom loading-spinner](./docs/rice/README.md#boring-loader-spinner)
         
     | 
| 
      
 1503 
     | 
    
         
            +
            * adding stuff (css/`<meta>`/...) [to the html `<head>` tag](./docs/rice/README.md#head)
         
     | 
| 
      
 1504 
     | 
    
         
            +
            * [adding your own translation](./docs/rice/README.md#translations)
         
     | 
| 
       1486 
1505 
     | 
    
         | 
| 
       1487 
1506 
     | 
    
         | 
| 
       1488 
1507 
     | 
    
         
             
            ## opengraph
         
     | 
| 
         @@ -2465,6 +2484,10 @@ copyparty on NixOS is configured via `services.copyparty` options, for example: 
     | 
|
| 
       2465 
2484 
     | 
    
         
             
            ```nix
         
     | 
| 
       2466 
2485 
     | 
    
         
             
            services.copyparty = {
         
     | 
| 
       2467 
2486 
     | 
    
         
             
              enable = true;
         
     | 
| 
      
 2487 
     | 
    
         
            +
              # the user to run the service as
         
     | 
| 
      
 2488 
     | 
    
         
            +
              user = "copyparty"; 
         
     | 
| 
      
 2489 
     | 
    
         
            +
              # the group to run the service as
         
     | 
| 
      
 2490 
     | 
    
         
            +
              group = "copyparty"; 
         
     | 
| 
       2468 
2491 
     | 
    
         
             
              # directly maps to values in the [global] section of the copyparty config.
         
     | 
| 
       2469 
2492 
     | 
    
         
             
              # see `copyparty --help` for available options
         
     | 
| 
       2470 
2493 
     | 
    
         
             
              settings = {
         
     | 
| 
         @@ -2489,6 +2512,12 @@ services.copyparty = { 
     | 
|
| 
       2489 
2512 
     | 
    
         
             
                k.passwordFile = "/run/keys/copyparty/k_password";
         
     | 
| 
       2490 
2513 
     | 
    
         
             
              };
         
     | 
| 
       2491 
2514 
     | 
    
         | 
| 
      
 2515 
     | 
    
         
            +
              # create a group
         
     | 
| 
      
 2516 
     | 
    
         
            +
              groups = {
         
     | 
| 
      
 2517 
     | 
    
         
            +
                # users "ed" and "k" are part of the group g1
         
     | 
| 
      
 2518 
     | 
    
         
            +
                g1 = [ "ed" "k" ];
         
     | 
| 
      
 2519 
     | 
    
         
            +
              };
         
     | 
| 
      
 2520 
     | 
    
         
            +
             
     | 
| 
       2492 
2521 
     | 
    
         
             
              # create a volume
         
     | 
| 
       2493 
2522 
     | 
    
         
             
              volumes = {
         
     | 
| 
       2494 
2523 
     | 
    
         
             
                # create a volume at "/" (the webroot), which will
         
     | 
| 
         @@ -2978,6 +3007,20 @@ example: `PRTY_NO_PIL=1 python3 copyparty-sfx.py` 
     | 
|
| 
       2978 
3007 
     | 
    
         
             
            * python2.7 on windows: `PRTY_NO_FFMPEG` + `PRTY_NO_FFPROBE` saves startup time
         
     | 
| 
       2979 
3008 
     | 
    
         | 
| 
       2980 
3009 
     | 
    
         | 
| 
      
 3010 
     | 
    
         
            +
            ### dependency unvendoring
         
     | 
| 
      
 3011 
     | 
    
         
            +
             
     | 
| 
      
 3012 
     | 
    
         
            +
            force use of system modules  instead of the vendored versions:
         
     | 
| 
      
 3013 
     | 
    
         
            +
             
     | 
| 
      
 3014 
     | 
    
         
            +
            | env-var              | what it does |
         
     | 
| 
      
 3015 
     | 
    
         
            +
            | -------------------- | ------------ |
         
     | 
| 
      
 3016 
     | 
    
         
            +
            | `PRTY_SYS_ALL`       | all of the below |
         
     | 
| 
      
 3017 
     | 
    
         
            +
            | `PRTY_SYS_DNSLIB`    | replace [stolen/dnslib](./copyparty/stolen/dnslib) with [upstream](https://pypi.org/project/dnslib/) |
         
     | 
| 
      
 3018 
     | 
    
         
            +
            | `PRTY_SYS_IFADDR`    | replace [stolen/ifaddr](./copyparty/stolen/ifaddr) with [upstream](https://pypi.org/project/ifaddr/) |
         
     | 
| 
      
 3019 
     | 
    
         
            +
            | `PRTY_SYS_QRCG`      | replace [stolen/qrcodegen.py](./copyparty/stolen/qrcodegen.py) with [upstream](https://github.com/nayuki/QR-Code-generator/blob/master/python/qrcodegen.py) |
         
     | 
| 
      
 3020 
     | 
    
         
            +
             
     | 
| 
      
 3021 
     | 
    
         
            +
            to debug, run copyparty with `PRTY_MODSPEC=1` to see where it's getting each module from
         
     | 
| 
      
 3022 
     | 
    
         
            +
             
     | 
| 
      
 3023 
     | 
    
         
            +
             
     | 
| 
       2981 
3024 
     | 
    
         
             
            ## optional gpl stuff
         
     | 
| 
       2982 
3025 
     | 
    
         | 
| 
       2983 
3026 
     | 
    
         
             
            some bundled tools have copyleft dependencies, see [./bin/#mtag](bin/#mtag)
         
     | 
| 
         @@ -3040,6 +3083,8 @@ if you want thumbnails (photos+videos) and you're okay with spending another 132 
     | 
|
| 
       3040 
3083 
     | 
    
         | 
| 
       3041 
3084 
     | 
    
         
             
            * or if you want to use `vips` for photo-thumbs instead, `pkg install libvips && python -m pip install --user -U wheel && python -m pip install --user -U pyvips && (cd /data/data/com.termux/files/usr/lib/; ln -s libgobject-2.0.so{,.0}; ln -s libvips.so{,.42})`
         
     | 
| 
       3042 
3085 
     | 
    
         | 
| 
      
 3086 
     | 
    
         
            +
            if you are suddenly unable to access storage (permission issues), try forcequitting termux, revoke all of its permissions in android settings, and run the command `termux-setup-storage`
         
     | 
| 
      
 3087 
     | 
    
         
            +
             
     | 
| 
       3043 
3088 
     | 
    
         | 
| 
       3044 
3089 
     | 
    
         
             
            # install on iOS
         
     | 
| 
       3045 
3090 
     | 
    
         | 
| 
         @@ -97,6 +97,25 @@ web/splash.html 
     | 
|
| 
       97 
97 
     | 
    
         
             
            web/splash.js
         
     | 
| 
       98 
98 
     | 
    
         
             
            web/svcs.html
         
     | 
| 
       99 
99 
     | 
    
         
             
            web/svcs.js
         
     | 
| 
      
 100 
     | 
    
         
            +
            web/tl/chi.js
         
     | 
| 
      
 101 
     | 
    
         
            +
            web/tl/cze.js
         
     | 
| 
      
 102 
     | 
    
         
            +
            web/tl/deu.js
         
     | 
| 
      
 103 
     | 
    
         
            +
            web/tl/epo.js
         
     | 
| 
      
 104 
     | 
    
         
            +
            web/tl/fin.js
         
     | 
| 
      
 105 
     | 
    
         
            +
            web/tl/fra.js
         
     | 
| 
      
 106 
     | 
    
         
            +
            web/tl/grc.js
         
     | 
| 
      
 107 
     | 
    
         
            +
            web/tl/ita.js
         
     | 
| 
      
 108 
     | 
    
         
            +
            web/tl/kor.js
         
     | 
| 
      
 109 
     | 
    
         
            +
            web/tl/nld.js
         
     | 
| 
      
 110 
     | 
    
         
            +
            web/tl/nno.js
         
     | 
| 
      
 111 
     | 
    
         
            +
            web/tl/nor.js
         
     | 
| 
      
 112 
     | 
    
         
            +
            web/tl/pol.js
         
     | 
| 
      
 113 
     | 
    
         
            +
            web/tl/por.js
         
     | 
| 
      
 114 
     | 
    
         
            +
            web/tl/rus.js
         
     | 
| 
      
 115 
     | 
    
         
            +
            web/tl/spa.js
         
     | 
| 
      
 116 
     | 
    
         
            +
            web/tl/swe.js
         
     | 
| 
      
 117 
     | 
    
         
            +
            web/tl/tur.js
         
     | 
| 
      
 118 
     | 
    
         
            +
            web/tl/ukr.js
         
     | 
| 
       100 
119 
     | 
    
         
             
            web/ui.css
         
     | 
| 
       101 
120 
     | 
    
         
             
            web/up2k.js
         
     | 
| 
       102 
121 
     | 
    
         
             
            web/util.js
         
     | 
| 
         @@ -641,8 +641,11 @@ def get_sects(): 
     | 
|
| 
       641 
641 
     | 
    
         
             
                        if no accounts or volumes are configured,
         
     | 
| 
       642 
642 
     | 
    
         
             
                        current folder will be read/write for everyone
         
     | 
| 
       643 
643 
     | 
    
         | 
| 
       644 
     | 
    
         
            -
                        the group @acct will always have every user with an account
         
     | 
| 
       645 
     | 
    
         
            -
                        (the name of that group can be changed with --grp-all)
         
     | 
| 
      
 644 
     | 
    
         
            +
                        the group \033[33m@acct\033[0m will always have every user with an account
         
     | 
| 
      
 645 
     | 
    
         
            +
                        (the name of that group can be changed with \033[32m--grp-all\033[0m)
         
     | 
| 
      
 646 
     | 
    
         
            +
             
     | 
| 
      
 647 
     | 
    
         
            +
                        to hide a volume from authenticated users, specify \033[33m*,-@acct\033[0m
         
     | 
| 
      
 648 
     | 
    
         
            +
                        to subtract \033[33m@acct\033[0m from \033[33m*\033[0m (can subtract users from groups too)
         
     | 
| 
       646 
649 
     | 
    
         | 
| 
       647 
650 
     | 
    
         
             
                        consider the config file for more flexible account/volume management,
         
     | 
| 
       648 
651 
     | 
    
         
             
                        including dynamic reload at runtime (and being more readable w)
         
     | 
| 
         @@ -664,12 +667,12 @@ def get_sects(): 
     | 
|
| 
       664 
667 
     | 
    
         | 
| 
       665 
668 
     | 
    
         
             
                        send the password in the '\033[36mPW\033[0m' http-header:
         
     | 
| 
       666 
669 
     | 
    
         
             
                          \033[36mPW: \033[35mhunter2\033[0m
         
     | 
| 
       667 
     | 
    
         
            -
                        or if you have \033[33m-- 
     | 
| 
      
 670 
     | 
    
         
            +
                        or if you have \033[33m--usernames\033[0m enabled,
         
     | 
| 
       668 
671 
     | 
    
         
             
                          \033[36mPW: \033[35med:hunter2\033[0m
         
     | 
| 
       669 
672 
     | 
    
         | 
| 
       670 
673 
     | 
    
         
             
                        send the password in the URL itself:
         
     | 
| 
       671 
674 
     | 
    
         
             
                          \033[36mhttp://127.0.0.1:3923/\033[35m?pw=hunter2\033[0m
         
     | 
| 
       672 
     | 
    
         
            -
                        or if you have \033[33m-- 
     | 
| 
      
 675 
     | 
    
         
            +
                        or if you have \033[33m--usernames\033[0m enabled,
         
     | 
| 
       673 
676 
     | 
    
         
             
                          \033[36mhttp://127.0.0.1:3923/\033[35m?pw=ed:hunter2\033[0m
         
     | 
| 
       674 
677 
     | 
    
         | 
| 
       675 
678 
     | 
    
         
             
                        use basic-authentication:
         
     | 
| 
         @@ -805,9 +808,11 @@ def get_sects(): 
     | 
|
| 
       805 
808 
     | 
    
         
             
                         \033[36mf\033[35m forks the process, doesn't wait for completion
         
     | 
| 
       806 
809 
     | 
    
         
             
                         \033[36mc\033[35m checks return code, blocks the action if non-zero
         
     | 
| 
       807 
810 
     | 
    
         
             
                         \033[36mj\033[35m provides json with info as 1st arg instead of filepath
         
     | 
| 
      
 811 
     | 
    
         
            +
                         \033[36ms\033[35m provides input data on stdin (instead of 1st arg)
         
     | 
| 
       808 
812 
     | 
    
         
             
                         \033[36mwN\033[35m waits N sec after command has been started before continuing
         
     | 
| 
       809 
813 
     | 
    
         
             
                         \033[36mtN\033[35m sets an N sec timeout before the command is abandoned
         
     | 
| 
       810 
814 
     | 
    
         
             
                         \033[36miN\033[35m xiu only: volume must be idle for N sec (default = 5)
         
     | 
| 
      
 815 
     | 
    
         
            +
                         \033[36mI\033[35m import and run as module, not as subprocess
         
     | 
| 
       811 
816 
     | 
    
         | 
| 
       812 
817 
     | 
    
         
             
                         \033[36mar\033[35m only run hook if user has read-access
         
     | 
| 
       813 
818 
     | 
    
         
             
                         \033[36marw\033[35m only run hook if user has read-write-access
         
     | 
| 
         @@ -837,6 +842,9 @@ def get_sects(): 
     | 
|
| 
       837 
842 
     | 
    
         
             
                          the \033[33m--\033[35m stops notify-send from reading the message as args
         
     | 
| 
       838 
843 
     | 
    
         
             
                          and the alert will be "hey" followed by the messagetext
         
     | 
| 
       839 
844 
     | 
    
         | 
| 
      
 845 
     | 
    
         
            +
                         \033[36m--xm s,,tee,-a,log.txt\033[35m appends each msg to log.txt;
         
     | 
| 
      
 846 
     | 
    
         
            +
                         \033[36m--xm s,j,,tee,-a,log.txt\033[35m writes it as json instead
         
     | 
| 
      
 847 
     | 
    
         
            +
             
     | 
| 
       840 
848 
     | 
    
         
             
                         \033[36m--xau zmq:pub:tcp://*:5556\033[35m announces uploads on zeromq;
         
     | 
| 
       841 
849 
     | 
    
         
             
                         \033[36m--xau t3,zmq:push:tcp://*:5557\033[35m also works, and you can
         
     | 
| 
       842 
850 
     | 
    
         
             
                         \033[36m--xau t3,j,zmq:req:tcp://localhost:5555\033[35m too for example
         
     | 
| 
         @@ -846,7 +854,8 @@ def get_sects(): 
     | 
|
| 
       846 
854 
     | 
    
         
             
                        as soon as the volume has been idle for iN seconds (5 by default)
         
     | 
| 
       847 
855 
     | 
    
         | 
| 
       848 
856 
     | 
    
         
             
                        \033[36mxiu\033[0m is also unique in that it will pass the metadata to the
         
     | 
| 
       849 
     | 
    
         
            -
                        executed program on STDIN instead of as argv arguments 
     | 
| 
      
 857 
     | 
    
         
            +
                        executed program on STDIN instead of as argv arguments (so
         
     | 
| 
      
 858 
     | 
    
         
            +
                        just like the \033[36ms\033[0m option does for the other hook types), and
         
     | 
| 
       850 
859 
     | 
    
         
             
                        it also includes the wark (file-id/hash) as a json property
         
     | 
| 
       851 
860 
     | 
    
         | 
| 
       852 
861 
     | 
    
         
             
                        \033[36mxban\033[0m can be used to overrule / cancel a user ban event;
         
     | 
| 
         @@ -857,6 +866,12 @@ def get_sects(): 
     | 
|
| 
       857 
866 
     | 
    
         
             
                        on new uploads, but with certain limitations. See
         
     | 
| 
       858 
867 
     | 
    
         
             
                        bin/hooks/reloc* and docs/devnotes.md#hook-effects
         
     | 
| 
       859 
868 
     | 
    
         | 
| 
      
 869 
     | 
    
         
            +
                        the \033[36mI\033[0m option will override most other options, because
         
     | 
| 
      
 870 
     | 
    
         
            +
                        it entirely hands over control to the hook, which is
         
     | 
| 
      
 871 
     | 
    
         
            +
                        then able to tamper with copyparty's internal memory
         
     | 
| 
      
 872 
     | 
    
         
            +
                        and wreck havoc if it wants to -- but this is worh it
         
     | 
| 
      
 873 
     | 
    
         
            +
                        because it makes the hook 140x faster
         
     | 
| 
      
 874 
     | 
    
         
            +
             
     | 
| 
       860 
875 
     | 
    
         
             
                        except for \033[36mxm\033[0m, only one hook / one action can run at a time,
         
     | 
| 
       861 
876 
     | 
    
         
             
                        so it's recommended to use the \033[36mf\033[0m flag unless you really need
         
     | 
| 
       862 
877 
     | 
    
         
             
                        to wait for the hook to finish before continuing (without \033[36mf\033[0m
         
     | 
| 
         @@ -1147,11 +1162,14 @@ def add_general(ap, nc, srvname): 
     | 
|
| 
       1147 
1162 
     | 
    
         
             
                ap2.add_argument("--urlform", metavar="MODE", type=u, default="print,xm", help="how to handle url-form POSTs; see \033[33m--help-urlform\033[0m")
         
     | 
| 
       1148 
1163 
     | 
    
         
             
                ap2.add_argument("--wintitle", metavar="TXT", type=u, default="cpp @ $pub", help="server terminal title, for example [\033[32m$ip-10.1.2.\033[0m] or [\033[32m$ip-]")
         
     | 
| 
       1149 
1164 
     | 
    
         
             
                ap2.add_argument("--name", metavar="TXT", type=u, default=srvname, help="server name (displayed topleft in browser and in mDNS)")
         
     | 
| 
      
 1165 
     | 
    
         
            +
                ap2.add_argument("--name-url", metavar="TXT", type=u, help="URL for server name hyperlink (displayed topleft in browser)")
         
     | 
| 
      
 1166 
     | 
    
         
            +
                ap2.add_argument("--name-html", type=u, help=argparse.SUPPRESS)
         
     | 
| 
       1150 
1167 
     | 
    
         
             
                ap2.add_argument("--mime", metavar="EXT=MIME", type=u, action="append", help="\033[34mREPEATABLE:\033[0m map file \033[33mEXT\033[0mension to \033[33mMIME\033[0mtype, for example [\033[32mjpg=image/jpeg\033[0m]")
         
     | 
| 
       1151 
1168 
     | 
    
         
             
                ap2.add_argument("--mimes", action="store_true", help="list default mimetype mapping and exit")
         
     | 
| 
       1152 
1169 
     | 
    
         
             
                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)")
         
     | 
| 
       1153 
1170 
     | 
    
         
             
                ap2.add_argument("--license", action="store_true", help="show licenses and exit")
         
     | 
| 
       1154 
1171 
     | 
    
         
             
                ap2.add_argument("--version", action="store_true", help="show versions and exit")
         
     | 
| 
      
 1172 
     | 
    
         
            +
                ap2.add_argument("--versionb", action="store_true", help="show version and exit")
         
     | 
| 
       1155 
1173 
     | 
    
         | 
| 
       1156 
1174 
     | 
    
         | 
| 
       1157 
1175 
     | 
    
         
             
            def add_qr(ap, tty):
         
     | 
| 
         @@ -1219,6 +1237,7 @@ def add_upload(ap): 
     | 
|
| 
       1219 
1237 
     | 
    
         
             
                ap2.add_argument("--hardlink-only", action="store_true", help="do not fallback to symlinks when a hardlink cannot be made (volflag=hardlinkonly)")
         
     | 
| 
       1220 
1238 
     | 
    
         
             
                ap2.add_argument("--reflink", action="store_true", help="enable reflink-based dedup; will fallback on full copies when that is impossible (non-CoW filesystem) (volflag=reflink)")
         
     | 
| 
       1221 
1239 
     | 
    
         
             
                ap2.add_argument("--no-dupe", action="store_true", help="reject duplicate files during upload; only matches within the same volume (volflag=nodupe)")
         
     | 
| 
      
 1240 
     | 
    
         
            +
                ap2.add_argument("--no-dupe-m", action="store_true", help="also reject dupes when moving a file into another volume (volflag=nodupem)")
         
     | 
| 
       1222 
1241 
     | 
    
         
             
                ap2.add_argument("--no-clone", action="store_true", help="do not use existing data on disk to satisfy dupe uploads; reduces server HDD reads in exchange for much more network load (volflag=noclone)")
         
     | 
| 
       1223 
1242 
     | 
    
         
             
                ap2.add_argument("--no-snap", action="store_true", help="disable snapshots -- forget unfinished uploads on shutdown; don't create .hist/up2k.snap files -- abandoned/interrupted uploads must be cleaned up manually")
         
     | 
| 
       1224 
1243 
     | 
    
         
             
                ap2.add_argument("--snap-wri", metavar="SEC", type=int, default=300, help="write upload state to ./hist/up2k.snap every \033[33mSEC\033[0m seconds; allows resuming incomplete uploads after a server crash")
         
     | 
| 
         @@ -1506,6 +1525,7 @@ def add_optouts(ap): 
     | 
|
| 
       1506 
1525 
     | 
    
         
             
                ap2.add_argument("--no-pipe", action="store_true", help="disable race-the-beam (lockstep download of files which are currently being uploaded) (volflag=nopipe)")
         
     | 
| 
       1507 
1526 
     | 
    
         
             
                ap2.add_argument("--no-tail", action="store_true", help="disable streaming a growing files with ?tail (volflag=notail)")
         
     | 
| 
       1508 
1527 
     | 
    
         
             
                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)")
         
     | 
| 
      
 1528 
     | 
    
         
            +
                ap2.add_argument("--no-zls", action="store_true", help="disable browsing the contents of zip/cbz files, does not affect thumbnails")
         
     | 
| 
       1509 
1529 
     | 
    
         | 
| 
       1510 
1530 
     | 
    
         | 
| 
       1511 
1531 
     | 
    
         
             
            def add_safety(ap):
         
     | 
| 
         @@ -1524,6 +1544,7 @@ def add_safety(ap): 
     | 
|
| 
       1524 
1544 
     | 
    
         
             
                ap2.add_argument("--force-js", action="store_true", help="don't send folder listings as HTML, force clients to use the embedded json instead -- slight protection against misbehaving search engines which ignore \033[33m--no-robots\033[0m")
         
     | 
| 
       1525 
1545 
     | 
    
         
             
                ap2.add_argument("--no-robots", action="store_true", help="adds http and html headers asking search engines to not index anything (volflag=norobots)")
         
     | 
| 
       1526 
1546 
     | 
    
         
             
                ap2.add_argument("--logout", metavar="H", type=float, default=8086.0, help="logout clients after \033[33mH\033[0m hours of inactivity; [\033[32m0.0028\033[0m]=10sec, [\033[32m0.1\033[0m]=6min, [\033[32m24\033[0m]=day, [\033[32m168\033[0m]=week, [\033[32m720\033[0m]=month, [\033[32m8760\033[0m]=year)")
         
     | 
| 
      
 1547 
     | 
    
         
            +
                ap2.add_argument("--dont-ban", metavar="TXT", type=u, default="no", help="anyone at this accesslevel or above will not get banned: [\033[32mav\033[0m]=admin-in-volume, [\033[32maa\033[0m]=has-admin-anywhere, [\033[32mrw\033[0m]=read-write, [\033[32mauth\033[0m]=authenticated, [\033[32many\033[0m]=disable-all-bans, [\033[32mno\033[0m]=anyone-can-get-banned")
         
     | 
| 
       1527 
1548 
     | 
    
         
             
                ap2.add_argument("--ban-pw", metavar="N,W,B", type=u, default="9,60,1440", help="more than \033[33mN\033[0m wrong passwords in \033[33mW\033[0m minutes = ban for \033[33mB\033[0m minutes; disable with [\033[32mno\033[0m]")
         
     | 
| 
       1528 
1549 
     | 
    
         
             
                ap2.add_argument("--ban-pwc", metavar="N,W,B", type=u, default="5,60,1440", help="more than \033[33mN\033[0m password-changes in \033[33mW\033[0m minutes = ban for \033[33mB\033[0m minutes; disable with [\033[32mno\033[0m]")
         
     | 
| 
       1529 
1550 
     | 
    
         
             
                ap2.add_argument("--ban-404", metavar="N,W,B", type=u, default="50,60,1440", help="hitting more than \033[33mN\033[0m 404's in \033[33mW\033[0m minutes = ban for \033[33mB\033[0m minutes; only affects users who cannot see directory listings because their access is either g/G/h")
         
     | 
| 
         @@ -1531,7 +1552,7 @@ def add_safety(ap): 
     | 
|
| 
       1531 
1552 
     | 
    
         
             
                ap2.add_argument("--ban-422", metavar="N,W,B", type=u, default="9,2,1440", help="hitting more than \033[33mN\033[0m 422's in \033[33mW\033[0m minutes = ban for \033[33mB\033[0m minutes (invalid requests, attempted exploits ++)")
         
     | 
| 
       1532 
1553 
     | 
    
         
             
                ap2.add_argument("--ban-url", metavar="N,W,B", type=u, default="9,2,1440", help="hitting more than \033[33mN\033[0m sus URL's in \033[33mW\033[0m minutes = ban for \033[33mB\033[0m minutes; applies only to permissions g/G/h (decent replacement for \033[33m--ban-404\033[0m if that can't be used)")
         
     | 
| 
       1533 
1554 
     | 
    
         
             
                ap2.add_argument("--sus-urls", metavar="R", type=u, default=r"\.php$|(^|/)wp-(admin|content|includes)/", help="URLs which are considered sus / eligible for banning; disable with blank or [\033[32mno\033[0m]")
         
     | 
| 
       1534 
     | 
    
         
            -
                ap2.add_argument("--nonsus-urls", metavar="R", type=u, default=r"^(favicon 
     | 
| 
      
 1555 
     | 
    
         
            +
                ap2.add_argument("--nonsus-urls", metavar="R", type=u, default=r"^(favicon\..{3}|robots\.txt)$|^apple-touch-icon|^\.well-known", help="harmless URLs ignored from 403/404-bans; disable with blank or [\033[32mno\033[0m]")
         
     | 
| 
       1535 
1556 
     | 
    
         
             
                ap2.add_argument("--early-ban", action="store_true", help="if a client is banned, reject its connection as soon as possible; not a good idea to enable when proxied behind cloudflare since it could ban your reverse-proxy")
         
     | 
| 
       1536 
1557 
     | 
    
         
             
                ap2.add_argument("--cookie-nmax", metavar="N", type=int, default=50, help="reject HTTP-request from client if they send more than N cookies")
         
     | 
| 
       1537 
1558 
     | 
    
         
             
                ap2.add_argument("--cookie-cmax", metavar="N", type=int, default=8192, help="reject HTTP-request from client if more than N characters in Cookie header")
         
     | 
| 
         @@ -1588,12 +1609,14 @@ def add_admin(ap): 
     | 
|
| 
       1588 
1609 
     | 
    
         
             
                ap2 = ap.add_argument_group("admin panel options")
         
     | 
| 
       1589 
1610 
     | 
    
         
             
                ap2.add_argument("--no-reload", action="store_true", help="disable ?reload=cfg (reload users/volumes/volflags from config file)")
         
     | 
| 
       1590 
1611 
     | 
    
         
             
                ap2.add_argument("--no-rescan", action="store_true", help="disable ?scan (volume reindexing)")
         
     | 
| 
       1591 
     | 
    
         
            -
                ap2.add_argument("--no-stack", action="store_true", help="disable ?stack (list all stacks)")
         
     | 
| 
      
 1612 
     | 
    
         
            +
                ap2.add_argument("--no-stack", action="store_true", help="disable ?stack (list all stacks); same as --stack-who=no")
         
     | 
| 
       1592 
1613 
     | 
    
         
             
                ap2.add_argument("--no-ups-page", action="store_true", help="disable ?ru (list of recent uploads)")
         
     | 
| 
       1593 
1614 
     | 
    
         
             
                ap2.add_argument("--no-up-list", action="store_true", help="don't show list of incoming files in controlpanel")
         
     | 
| 
       1594 
1615 
     | 
    
         
             
                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")
         
     | 
| 
       1595 
1616 
     | 
    
         
             
                ap2.add_argument("--ups-who", metavar="LVL", type=int, default=2, help="who can see recent uploads on the ?ru page? [\033[32m0\033[0m]=nobody, [\033[32m1\033[0m]=admins, [\033[32m2\033[0m]=everyone (volflag=ups_who)")
         
     | 
| 
       1596 
1617 
     | 
    
         
             
                ap2.add_argument("--ups-when", action="store_true", help="let everyone see upload timestamps on the ?ru page, not just admins")
         
     | 
| 
      
 1618 
     | 
    
         
            +
                ap2.add_argument("--stack-who", metavar="LVL", type=u, default="a", help="who can see the ?stack page (list of threads)? [\033[32mno\033[0m]=nobody, [\033[32ma\033[0m]=admins, [\033[32mrw\033[0m]=read+write, [\033[32mall\033[0m]=everyone")
         
     | 
| 
      
 1619 
     | 
    
         
            +
                ap2.add_argument("--stack-v", action="store_true", help="verbose ?stack")
         
     | 
| 
       1597 
1620 
     | 
    
         | 
| 
       1598 
1621 
     | 
    
         | 
| 
       1599 
1622 
     | 
    
         
             
            def add_thumbnail(ap):
         
     | 
| 
         @@ -1791,6 +1814,15 @@ def add_ui(ap, retry ): 
     | 
|
| 
       1791 
1814 
     | 
    
         
             
                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")
         
     | 
| 
       1792 
1815 
     | 
    
         
             
                ap2.add_argument("--no-sb-md", action="store_true", help="don't sandbox README/PREADME.md documents (volflags: no_sb_md | sb_md)")
         
     | 
| 
       1793 
1816 
     | 
    
         
             
                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")
         
     | 
| 
      
 1817 
     | 
    
         
            +
                ap2.add_argument("--ui-nombar", action="store_true", help="hide top-menu in the UI (volflag=ui_nombar)")
         
     | 
| 
      
 1818 
     | 
    
         
            +
                ap2.add_argument("--ui-noacci", action="store_true", help="hide account-info in the UI (volflag=ui_noacci)")
         
     | 
| 
      
 1819 
     | 
    
         
            +
                ap2.add_argument("--ui-nosrvi", action="store_true", help="hide server-info in the UI (volflag=ui_nosrvi)")
         
     | 
| 
      
 1820 
     | 
    
         
            +
                ap2.add_argument("--ui-nonav", action="store_true", help="hide navpane+breadcrumbs (volflag=ui_nonav)")
         
     | 
| 
      
 1821 
     | 
    
         
            +
                ap2.add_argument("--ui-notree", action="store_true", help="hide navpane in the UI (volflag=ui_nonav)")
         
     | 
| 
      
 1822 
     | 
    
         
            +
                ap2.add_argument("--ui-nocpla", action="store_true", help="hide cpanel-link in the UI (volflag=ui_nocpla)")
         
     | 
| 
      
 1823 
     | 
    
         
            +
                ap2.add_argument("--ui-nolbar", action="store_true", help="hide link-bar in the UI (volflag=ui_nolbar)")
         
     | 
| 
      
 1824 
     | 
    
         
            +
                ap2.add_argument("--ui-noctxb", action="store_true", help="hide context-buttons in the UI (volflag=ui_noctxb)")
         
     | 
| 
      
 1825 
     | 
    
         
            +
                ap2.add_argument("--ui-norepl", action="store_true", help="hide repl-button in the UI (volflag=ui_norepl)")
         
     | 
| 
       1794 
1826 
     | 
    
         
             
                ap2.add_argument("--have-unlistc", action="store_true", help=argparse.SUPPRESS)
         
     | 
| 
       1795 
1827 
     | 
    
         | 
| 
       1796 
1828 
     | 
    
         | 
| 
         @@ -1918,15 +1950,19 @@ def run_argparse( 
     | 
|
| 
       1918 
1950 
     | 
    
         | 
| 
       1919 
1951 
     | 
    
         | 
| 
       1920 
1952 
     | 
    
         
             
            def main(argv  = None)  :
         
     | 
| 
      
 1953 
     | 
    
         
            +
                if argv is None:
         
     | 
| 
      
 1954 
     | 
    
         
            +
                    argv = sys.argv
         
     | 
| 
      
 1955 
     | 
    
         
            +
             
     | 
| 
      
 1956 
     | 
    
         
            +
                if "--versionb" in argv:
         
     | 
| 
      
 1957 
     | 
    
         
            +
                    print(S_VERSION)
         
     | 
| 
      
 1958 
     | 
    
         
            +
                    sys.exit(0)
         
     | 
| 
      
 1959 
     | 
    
         
            +
             
     | 
| 
       1921 
1960 
     | 
    
         
             
                time.strptime("19970815", "%Y%m%d")  # python#7980
         
     | 
| 
       1922 
1961 
     | 
    
         
             
                if WINDOWS:
         
     | 
| 
       1923 
1962 
     | 
    
         
             
                    os.system("rem")  # enables colors
         
     | 
| 
       1924 
1963 
     | 
    
         | 
| 
       1925 
1964 
     | 
    
         
             
                init_E(E)
         
     | 
| 
       1926 
1965 
     | 
    
         | 
| 
       1927 
     | 
    
         
            -
                if argv is None:
         
     | 
| 
       1928 
     | 
    
         
            -
                    argv = sys.argv
         
     | 
| 
       1929 
     | 
    
         
            -
             
     | 
| 
       1930 
1966 
     | 
    
         
             
                f = '\033[36mcopyparty v{} "\033[35m{}\033[36m" ({})\n{}\033[0;36m\n   sqlite {} | jinja {} | pyftpd {} | tftp {}\n\033[0m'
         
     | 
| 
       1931 
1967 
     | 
    
         
             
                f = f.format(
         
     | 
| 
       1932 
1968 
     | 
    
         
             
                    S_VERSION,
         
     | 
| 
         @@ -2053,7 +2089,7 @@ def main(argv  = None)  : 
     | 
|
| 
       2053 
2089 
     | 
    
         | 
| 
       2054 
2090 
     | 
    
         
             
                # propagate implications
         
     | 
| 
       2055 
2091 
     | 
    
         
             
                for k1, k2 in IMPLICATIONS:
         
     | 
| 
       2056 
     | 
    
         
            -
                    if getattr(al, k1):
         
     | 
| 
      
 2092 
     | 
    
         
            +
                    if getattr(al, k1, None):
         
     | 
| 
       2057 
2093 
     | 
    
         
             
                        setattr(al, k2, True)
         
     | 
| 
       2058 
2094 
     | 
    
         | 
| 
       2059 
2095 
     | 
    
         
             
                # propagate unplications
         
     | 
| 
         @@ -1961,9 +1961,18 @@ class AuthSrv(object): 
     | 
|
| 
       1961 
1961 
     | 
    
         
             
                        axs_key = "u" + perm
         
     | 
| 
       1962 
1962 
     | 
    
         
             
                        for vp, vol in vfs.all_vols.items():
         
     | 
| 
       1963 
1963 
     | 
    
         
             
                            zx = getattr(vol.axs, axs_key)
         
     | 
| 
       1964 
     | 
    
         
            -
                            if "*" in zx:
         
     | 
| 
      
 1964 
     | 
    
         
            +
                            if "*" in zx and "-@acct" not in zx:
         
     | 
| 
       1965 
1965 
     | 
    
         
             
                                for usr in unames:
         
     | 
| 
       1966 
1966 
     | 
    
         
             
                                    zx.add(usr)
         
     | 
| 
      
 1967 
     | 
    
         
            +
                            for zs in list(zx):
         
     | 
| 
      
 1968 
     | 
    
         
            +
                                if zs.startswith("-"):
         
     | 
| 
      
 1969 
     | 
    
         
            +
                                    zx.discard(zs)
         
     | 
| 
      
 1970 
     | 
    
         
            +
                                    zs = zs[1:]
         
     | 
| 
      
 1971 
     | 
    
         
            +
                                    zx.discard(zs)
         
     | 
| 
      
 1972 
     | 
    
         
            +
                                    if zs.startswith("@"):
         
     | 
| 
      
 1973 
     | 
    
         
            +
                                        zs = zs[1:]
         
     | 
| 
      
 1974 
     | 
    
         
            +
                                        for zs in grps.get(zs) or []:
         
     | 
| 
      
 1975 
     | 
    
         
            +
                                            zx.discard(zs)
         
     | 
| 
       1967 
1976 
     | 
    
         | 
| 
       1968 
1977 
     | 
    
         
             
                        # aread,... = dict[uname, list[volnames] or []]
         
     | 
| 
       1969 
1978 
     | 
    
         
             
                        umap   = {x: [] for x in unames}
         
     | 
| 
         @@ -2503,13 +2512,17 @@ class AuthSrv(object): 
     | 
|
| 
       2503 
2512 
     | 
    
         | 
| 
       2504 
2513 
     | 
    
         
             
                        ico_url = vol.flags.get("ufavico")
         
     | 
| 
       2505 
2514 
     | 
    
         
             
                        if ico_url:
         
     | 
| 
      
 2515 
     | 
    
         
            +
                            ico_h = ""
         
     | 
| 
       2506 
2516 
     | 
    
         
             
                            ico_ext = ico_url.split("?")[0].split(".")[-1].lower()
         
     | 
| 
       2507 
2517 
     | 
    
         
             
                            if ico_ext in FAVICON_MIMES:
         
     | 
| 
       2508 
2518 
     | 
    
         
             
                                zs = '<link rel="icon" type="%s" href="%s">\n'
         
     | 
| 
       2509 
     | 
    
         
            -
                                 
     | 
| 
      
 2519 
     | 
    
         
            +
                                ico_h = zs % (FAVICON_MIMES[ico_ext], ico_url)
         
     | 
| 
       2510 
2520 
     | 
    
         
             
                            elif ico_ext == "ico":
         
     | 
| 
       2511 
2521 
     | 
    
         
             
                                zs = '<link rel="shortcut icon" href="%s">\n'
         
     | 
| 
       2512 
     | 
    
         
            -
                                 
     | 
| 
      
 2522 
     | 
    
         
            +
                                ico_h = zs % (ico_url,)
         
     | 
| 
      
 2523 
     | 
    
         
            +
                            if ico_h:
         
     | 
| 
      
 2524 
     | 
    
         
            +
                                vol.flags["ufavico_h"] = ico_h
         
     | 
| 
      
 2525 
     | 
    
         
            +
                                head_s += ico_h
         
     | 
| 
       2513 
2526 
     | 
    
         | 
| 
       2514 
2527 
     | 
    
         
             
                        if head_s:
         
     | 
| 
       2515 
2528 
     | 
    
         
             
                            vol.flags["html_head_s"] = head_s
         
     | 
| 
         @@ -2573,6 +2586,15 @@ class AuthSrv(object): 
     | 
|
| 
       2573 
2586 
     | 
    
         
             
                                for x in drop:
         
     | 
| 
       2574 
2587 
     | 
    
         
             
                                    vol.flags.pop(x)
         
     | 
| 
       2575 
2588 
     | 
    
         | 
| 
      
 2589 
     | 
    
         
            +
                        zi = vol.flags.get("lifetime") or 0
         
     | 
| 
      
 2590 
     | 
    
         
            +
                        zi2 = time.time() // (86400 * 365)
         
     | 
| 
      
 2591 
     | 
    
         
            +
                        zi3 = zi2 * 86400 * 365
         
     | 
| 
      
 2592 
     | 
    
         
            +
                        if zi < 0 or zi > zi3:
         
     | 
| 
      
 2593 
     | 
    
         
            +
                            t = "the lifetime of volume [/%s] (%d) exceeds max value (%d years; %d)"
         
     | 
| 
      
 2594 
     | 
    
         
            +
                            t = t % (vol.vpath, zi, zi2, zi3)
         
     | 
| 
      
 2595 
     | 
    
         
            +
                            self.log(t, 1)
         
     | 
| 
      
 2596 
     | 
    
         
            +
                            raise Exception(t)
         
     | 
| 
      
 2597 
     | 
    
         
            +
             
     | 
| 
       2576 
2598 
     | 
    
         
             
                        # verify tags mentioned by -mt[mp] are used by -mte
         
     | 
| 
       2577 
2599 
     | 
    
         
             
                        local_mtp = {}
         
     | 
| 
       2578 
2600 
     | 
    
         
             
                        local_only_mtp = {}
         
     | 
| 
         @@ -2739,9 +2761,13 @@ class AuthSrv(object): 
     | 
|
| 
       2739 
2761 
     | 
    
         
             
                            ["uadmin", "uadmin"],
         
     | 
| 
       2740 
2762 
     | 
    
         
             
                        ]:
         
     | 
| 
       2741 
2763 
     | 
    
         
             
                            u = list(sorted(getattr(zv.axs, attr)))
         
     | 
| 
       2742 
     | 
    
         
            -
                            u  
     | 
| 
       2743 
     | 
    
         
            -
             
     | 
| 
       2744 
     | 
    
         
            -
                             
     | 
| 
      
 2764 
     | 
    
         
            +
                            if u == ["*"] and acct:
         
     | 
| 
      
 2765 
     | 
    
         
            +
                                u = ["\033[35monly-anonymous\033[0m"]
         
     | 
| 
      
 2766 
     | 
    
         
            +
                            elif "*" in u:
         
     | 
| 
      
 2767 
     | 
    
         
            +
                                u = ["\033[35meverybody\033[0m"]
         
     | 
| 
      
 2768 
     | 
    
         
            +
                            if not u:
         
     | 
| 
      
 2769 
     | 
    
         
            +
                                u = ["\033[36m--none--\033[0m"]
         
     | 
| 
      
 2770 
     | 
    
         
            +
                            u = ", ".join(u)
         
     | 
| 
       2745 
2771 
     | 
    
         
             
                            t += "\n|  {}:  {}".format(txt, u)
         
     | 
| 
       2746 
2772 
     | 
    
         | 
| 
       2747 
2773 
     | 
    
         
             
                        if "e2d" in zv.flags:
         
     | 
| 
         @@ -2853,8 +2879,6 @@ class AuthSrv(object): 
     | 
|
| 
       2853 
2879 
     | 
    
         | 
| 
       2854 
2880 
     | 
    
         
             
                    if have_reflink:
         
     | 
| 
       2855 
2881 
     | 
    
         
             
                        t = "WARNING: Reflink-based dedup was requested, but %s. This will not work; files will be full copies instead."
         
     | 
| 
       2856 
     | 
    
         
            -
                        if sys.version_info < (3, 14):
         
     | 
| 
       2857 
     | 
    
         
            -
                            self.log(t % "your python version is not new enough", 1)
         
     | 
| 
       2858 
2882 
     | 
    
         
             
                        if not sys.platform.startswith("linux"):
         
     | 
| 
       2859 
2883 
     | 
    
         
             
                            self.log(t % "your OS is not Linux", 1)
         
     | 
| 
       2860 
2884 
     | 
    
         | 
| 
         @@ -2931,6 +2955,11 @@ class AuthSrv(object): 
     | 
|
| 
       2931 
2955 
     | 
    
         
             
                            shn.shr_src = (s_vfs, s_rem)
         
     | 
| 
       2932 
2956 
     | 
    
         
             
                            shn.realpath = s_vfs.canonical(s_rem)
         
     | 
| 
       2933 
2957 
     | 
    
         | 
| 
      
 2958 
     | 
    
         
            +
                            o_vn, _ = shn._get_share_src("")
         
     | 
| 
      
 2959 
     | 
    
         
            +
                            shn.flags = o_vn.flags.copy()
         
     | 
| 
      
 2960 
     | 
    
         
            +
                            shn.dbpath = o_vn.dbpath
         
     | 
| 
      
 2961 
     | 
    
         
            +
                            shn.histpath = o_vn.histpath
         
     | 
| 
      
 2962 
     | 
    
         
            +
             
     | 
| 
       2934 
2963 
     | 
    
         
             
                            # root.all_aps doesn't include any shares, so make a copy where the
         
     | 
| 
       2935 
2964 
     | 
    
         
             
                            # share appears in all abspaths it can provide (for example for chk_ap)
         
     | 
| 
       2936 
2965 
     | 
    
         
             
                            ap = shn.realpath
         
     | 
| 
         @@ -2994,6 +3023,8 @@ class AuthSrv(object): 
     | 
|
| 
       2994 
3023 
     | 
    
         
             
                            "unlist": vf.get("unlist") or "",
         
     | 
| 
       2995 
3024 
     | 
    
         
             
                            "sb_lg": "" if "no_sb_lg" in vf else (vf.get("lg_sbf") or "y"),
         
     | 
| 
       2996 
3025 
     | 
    
         
             
                        }
         
     | 
| 
      
 3026 
     | 
    
         
            +
                        if "ufavico_h" in vf:
         
     | 
| 
      
 3027 
     | 
    
         
            +
                            vn.js_ls["ufavico"] = vf["ufavico_h"]
         
     | 
| 
       2997 
3028 
     | 
    
         
             
                        js_htm = {
         
     | 
| 
       2998 
3029 
     | 
    
         
             
                            "SPINNER": self.args.spinner,
         
     | 
| 
       2999 
3030 
     | 
    
         
             
                            "s_name": self.args.bname,
         
     | 
| 
         @@ -3005,6 +3036,7 @@ class AuthSrv(object): 
     | 
|
| 
       3005 
3036 
     | 
    
         
             
                            "have_shr": self.args.shr,
         
     | 
| 
       3006 
3037 
     | 
    
         
             
                            "shr_who": vf["shr_who"],
         
     | 
| 
       3007 
3038 
     | 
    
         
             
                            "have_zip": not self.args.no_zip,
         
     | 
| 
      
 3039 
     | 
    
         
            +
                            "have_zls": not self.args.no_zls,
         
     | 
| 
       3008 
3040 
     | 
    
         
             
                            "have_mv": not self.args.no_mv,
         
     | 
| 
       3009 
3041 
     | 
    
         
             
                            "have_del": not self.args.no_del,
         
     | 
| 
       3010 
3042 
     | 
    
         
             
                            "have_unpost": int(self.args.unpost),
         
     | 
| 
         @@ -3029,7 +3061,7 @@ class AuthSrv(object): 
     | 
|
| 
       3029 
3061 
     | 
    
         
             
                            "dvol": self.args.au_vol,
         
     | 
| 
       3030 
3062 
     | 
    
         
             
                            "idxh": int(self.args.ih),
         
     | 
| 
       3031 
3063 
     | 
    
         
             
                            "dutc": not self.args.localtime,
         
     | 
| 
       3032 
     | 
    
         
            -
                            "dfszf": self.args.ui_filesz,
         
     | 
| 
      
 3064 
     | 
    
         
            +
                            "dfszf": self.args.ui_filesz.strip("-"),
         
     | 
| 
       3033 
3065 
     | 
    
         
             
                            "themes": self.args.themes,
         
     | 
| 
       3034 
3066 
     | 
    
         
             
                            "turbolvl": self.args.turbo,
         
     | 
| 
       3035 
3067 
     | 
    
         
             
                            "nosubtle": self.args.nosubtle,
         
     | 
| 
         @@ -3041,6 +3073,10 @@ class AuthSrv(object): 
     | 
|
| 
       3041 
3073 
     | 
    
         
             
                            "lifetime": vn.js_ls["lifetime"],
         
     | 
| 
       3042 
3074 
     | 
    
         
             
                            "u2sort": self.args.u2sort,
         
     | 
| 
       3043 
3075 
     | 
    
         
             
                        }
         
     | 
| 
      
 3076 
     | 
    
         
            +
                        zs = "ui_noacci ui_nocpla ui_noctxb ui_nolbar ui_nombar ui_nonav ui_notree ui_norepl ui_nosrvi"
         
     | 
| 
      
 3077 
     | 
    
         
            +
                        for zs in zs.split():
         
     | 
| 
      
 3078 
     | 
    
         
            +
                            if vf.get(zs):
         
     | 
| 
      
 3079 
     | 
    
         
            +
                                js_htm[zs] = 1
         
     | 
| 
       3044 
3080 
     | 
    
         
             
                        vn.js_htm = json_hesc(json.dumps(js_htm))
         
     | 
| 
       3045 
3081 
     | 
    
         | 
| 
       3046 
3082 
     | 
    
         
             
                    vols = list(vfs.all_nodes.values())
         
     |