copyparty 1.13.6__tar.gz → 1.13.8__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.13.6 → copyparty-1.13.8}/PKG-INFO +56 -6
- {copyparty-1.13.6 → copyparty-1.13.8}/README.md +55 -5
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/__main__.py +25 -7
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/__version__.py +2 -2
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/authsrv.py +9 -6
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/cert.py +1 -1
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/fsutil.py +3 -3
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/ftpd.py +15 -2
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/httpcli.py +224 -81
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/httpconn.py +3 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/httpsrv.py +38 -11
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/ico.py +1 -1
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/mtag.py +15 -6
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/pwhash.py +10 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/smbd.py +20 -2
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/ssdp.py +3 -3
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/stolen/dnslib/dns.py +6 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/stolen/ifaddr/__init__.py +15 -1
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/stolen/ifaddr/_shared.py +1 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/stolen/qrcodegen.py +6 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/sutil.py +1 -1
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/svchub.py +72 -3
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/szip.py +1 -3
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/tcpsrv.py +63 -8
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/tftpd.py +30 -4
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/th_srv.py +22 -1
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/u2idx.py +4 -1
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/up2k.py +221 -93
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/util.py +166 -31
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/a/u2c.py +10 -3
- copyparty-1.13.8/copyparty/web/browser.css.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/browser2.html +0 -1
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/md.html +3 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/mde.html +3 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/msg.html +3 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/splash.html +3 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/svcs.html +3 -0
- copyparty-1.13.8/copyparty/web/up2k.js.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty.egg-info/PKG-INFO +56 -6
- copyparty-1.13.6/copyparty/web/browser.css.gz +0 -0
- copyparty-1.13.6/copyparty/web/up2k.js.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/LICENSE +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/__init__.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/bos/__init__.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/bos/bos.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/bos/path.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/broker_mp.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/broker_mpw.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/broker_thr.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/broker_util.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/cfg.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/dxml.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/mdns.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/metrics.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/multicast.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/res/COPYING.txt +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/res/__init__.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/res/insecure.pem +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/star.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/stolen/__init__.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/stolen/dnslib/__init__.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/stolen/dnslib/bimap.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/stolen/dnslib/bit.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/stolen/dnslib/buffer.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/stolen/dnslib/label.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/stolen/dnslib/lex.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/stolen/dnslib/ranges.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/stolen/ifaddr/_posix.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/stolen/ifaddr/_win32.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/stolen/surrogateescape.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/th_cli.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/a/__init__.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/a/partyfuse.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/a/webdav-cfg.bat +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/baguettebox.js.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/browser.html +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/browser.js.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/cf.html +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/dbg-audio.js.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/dd/2.png +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/dd/3.png +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/dd/4.png +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/dd/5.png +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/dd/__init__.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/deps/__init__.py +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/deps/busy.mp3.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/deps/easymde.css.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/deps/easymde.js.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/deps/marked.js.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/deps/mini-fa.css.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/deps/mini-fa.woff +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/deps/prism.css.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/deps/prism.js.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/deps/prismd.css.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/deps/scp.woff2 +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/deps/sha512.ac.js.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/deps/sha512.hw.js.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/md.css.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/md.js.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/md2.css.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/md2.js.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/mde.css.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/mde.js.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/msg.css.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/splash.css.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/splash.js.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/svcs.js.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/ui.css.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/util.js.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty/web/w.hash.js.gz +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty.egg-info/SOURCES.txt +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty.egg-info/dependency_links.txt +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty.egg-info/entry_points.txt +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty.egg-info/requires.txt +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/copyparty.egg-info/top_level.txt +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/pyproject.toml +0 -0
- {copyparty-1.13.6 → copyparty-1.13.8}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: copyparty
|
3
|
-
Version: 1.13.
|
3
|
+
Version: 1.13.8
|
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
|
@@ -139,6 +139,7 @@ turn almost any device into a file server with resumable uploads/downloads using
|
|
139
139
|
* [prometheus](#prometheus) - metrics/stats can be enabled
|
140
140
|
* [other extremely specific features](#other-extremely-specific-features) - you'll never find a use for these
|
141
141
|
* [custom mimetypes](#custom-mimetypes) - change the association of a file extension
|
142
|
+
* [feature chickenbits](#feature-chickenbits) - buggy feature? rip it out
|
142
143
|
* [packages](#packages) - the party might be closer than you think
|
143
144
|
* [arch package](#arch-package) - now [available on aur](https://aur.archlinux.org/packages/copyparty) maintained by [@icxes](https://github.com/icxes)
|
144
145
|
* [fedora package](#fedora-package) - does not exist yet
|
@@ -165,6 +166,7 @@ turn almost any device into a file server with resumable uploads/downloads using
|
|
165
166
|
* [HTTP API](#HTTP-API) - see [devnotes](./docs/devnotes.md#http-api)
|
166
167
|
* [dependencies](#dependencies) - mandatory deps
|
167
168
|
* [optional dependencies](#optional-dependencies) - install these to enable bonus features
|
169
|
+
* [dependency chickenbits](#dependency-chickenbits) - prevent loading an optional dependency
|
168
170
|
* [optional gpl stuff](#optional-gpl-stuff)
|
169
171
|
* [sfx](#sfx) - the self-contained "binary" (recommended!)
|
170
172
|
* [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+)
|
@@ -178,7 +180,7 @@ turn almost any device into a file server with resumable uploads/downloads using
|
|
178
180
|
|
179
181
|
just run **[copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/download/copyparty-sfx.py)** -- that's it! 🎉
|
180
182
|
|
181
|
-
* or install through pypi: `python3 -m pip install --user -U copyparty`
|
183
|
+
* or install through [pypi](https://pypi.org/project/copyparty/): `python3 -m pip install --user -U copyparty`
|
182
184
|
* or if you cannot install python, you can use [copyparty.exe](#copypartyexe) instead
|
183
185
|
* or install [on arch](#arch-package) ╱ [on NixOS](#nixos-module) ╱ [through nix](#nix-package)
|
184
186
|
* or if you are on android, [install copyparty in termux](#install-on-android)
|
@@ -248,7 +250,7 @@ firewall-cmd --reload
|
|
248
250
|
also see [comparison to similar software](./docs/versus.md)
|
249
251
|
|
250
252
|
* backend stuff
|
251
|
-
* ☑ IPv6
|
253
|
+
* ☑ IPv6 + unix-sockets
|
252
254
|
* ☑ [multiprocessing](#performance) (actual multithreading)
|
253
255
|
* ☑ volumes (mountpoints)
|
254
256
|
* ☑ [accounts](#accounts-and-volumes)
|
@@ -633,9 +635,6 @@ images with the following names (see `--th-covers`) become the thumbnail of the
|
|
633
635
|
* the order is significant, so if both `cover.png` and `folder.jpg` exist in a folder, it will pick the first matching `--th-covers` entry (`folder.jpg`)
|
634
636
|
* and, if you enable [file indexing](#file-indexing), it will also try those names as dotfiles (`.folder.jpg` and so), and then fallback on the first picture in the folder (if it has any pictures at all)
|
635
637
|
|
636
|
-
in the grid/thumbnail view, if the audio player panel is open, songs will start playing when clicked
|
637
|
-
* indicated by the audio files having the ▶ icon instead of 💾
|
638
|
-
|
639
638
|
enabling `multiselect` lets you click files to select them, and then shift-click another file for range-select
|
640
639
|
* `multiselect` is mostly intended for phones/tablets, but the `sel` option in the `[⚙️] settings` tab is better suited for desktop use, allowing selection by CTRL-clicking and range-selection with SHIFT-click, all without affecting regular clicking
|
641
640
|
* the `sel` option can be made default globally with `--gsel` or per-volume with volflag `gsel`
|
@@ -1514,6 +1513,8 @@ some reverse proxies (such as [Caddy](https://caddyserver.com/)) can automatical
|
|
1514
1513
|
* **warning:** nginx-QUIC (HTTP/3) is still experimental and can make uploads much slower, so HTTP/1.1 is recommended for now
|
1515
1514
|
* depending on server/client, HTTP/1.1 can also be 5x faster than HTTP/2
|
1516
1515
|
|
1516
|
+
for improved security (and a tiny performance boost) consider listening on a unix-socket with `-i /tmp/party.sock` instead of `-i 127.0.0.1`
|
1517
|
+
|
1517
1518
|
example webserver configs:
|
1518
1519
|
|
1519
1520
|
* [nginx config](contrib/nginx/copyparty.conf) -- entire domain/subdomain
|
@@ -1614,6 +1615,23 @@ in a config-file, this is the same as:
|
|
1614
1615
|
run copyparty with `--mimes` to list all the default mappings
|
1615
1616
|
|
1616
1617
|
|
1618
|
+
### feature chickenbits
|
1619
|
+
|
1620
|
+
buggy feature? rip it out by setting any of the following environment variables to disable its associated bell or whistle,
|
1621
|
+
|
1622
|
+
| env-var | what it does |
|
1623
|
+
| -------------------- | ------------ |
|
1624
|
+
| `PRTY_NO_IFADDR` | disable ip/nic discovery by poking into your OS with ctypes |
|
1625
|
+
| `PRTY_NO_IPV6` | disable some ipv6 support (should not be necessary since windows 2000) |
|
1626
|
+
| `PRTY_NO_LZMA` | disable streaming xz compression of incoming uploads |
|
1627
|
+
| `PRTY_NO_MP` | disable all use of the python `multiprocessing` module (actual multithreading, cpu-count for parsers/thumbnailers) |
|
1628
|
+
| `PRTY_NO_SQLITE` | disable all database-related functionality (file indexing, metadata indexing, most file deduplication logic) |
|
1629
|
+
| `PRTY_NO_TLS` | disable native HTTPS support; if you still want to accept HTTPS connections then TLS must now be terminated by a reverse-proxy |
|
1630
|
+
| `PRTY_NO_TPOKE` | disable systemd-tmpfilesd avoider |
|
1631
|
+
|
1632
|
+
example: `PRTY_NO_IFADDR=1 python3 copyparty-sfx.py`
|
1633
|
+
|
1634
|
+
|
1617
1635
|
# packages
|
1618
1636
|
|
1619
1637
|
the party might be closer than you think
|
@@ -1936,6 +1954,7 @@ some notes on hardening
|
|
1936
1954
|
* cors doesn't work right otherwise
|
1937
1955
|
* if you allow anonymous uploads or otherwise don't trust the contents of a volume, you can prevent XSS with volflag `nohtml`
|
1938
1956
|
* this returns html documents as plaintext, and also disables markdown rendering
|
1957
|
+
* when running behind a reverse-proxy, listen on a unix-socket with `-i /tmp/party.sock` instead of `-i 127.0.0.1` for tighter access control (plus you get a tiny performance boost for free)
|
1939
1958
|
|
1940
1959
|
safety profiles:
|
1941
1960
|
|
@@ -2100,6 +2119,37 @@ enable [smb](#smb-server) support (**not** recommended):
|
|
2100
2119
|
`pyvips` gives higher quality thumbnails than `Pillow` and is 320% faster, using 270% more ram: `sudo apt install libvips42 && python3 -m pip install --user -U pyvips`
|
2101
2120
|
|
2102
2121
|
|
2122
|
+
### dependency chickenbits
|
2123
|
+
|
2124
|
+
prevent loading an optional dependency , for example if:
|
2125
|
+
|
2126
|
+
* you have an incompatible version installed and it causes problems
|
2127
|
+
* you just don't want copyparty to use it, maybe to save ram
|
2128
|
+
|
2129
|
+
set any of the following environment variables to disable its associated optional feature,
|
2130
|
+
|
2131
|
+
| env-var | what it does |
|
2132
|
+
| -------------------- | ------------ |
|
2133
|
+
| `PRTY_NO_ARGON2` | disable argon2-cffi password hashing |
|
2134
|
+
| `PRTY_NO_CFSSL` | never attempt to generate self-signed certificates using [cfssl](https://github.com/cloudflare/cfssl) |
|
2135
|
+
| `PRTY_NO_FFMPEG` | **audio transcoding** goes byebye, **thumbnailing** must be handled by Pillow/libvips |
|
2136
|
+
| `PRTY_NO_FFPROBE` | **audio transcoding** goes byebye, **thumbnailing** must be handled by Pillow/libvips, **metadata-scanning** must be handled by mutagen |
|
2137
|
+
| `PRTY_NO_MUTAGEN` | do not use [mutagen](https://pypi.org/project/mutagen/) for reading metadata from media files; will fallback to ffprobe |
|
2138
|
+
| `PRTY_NO_PIL` | disable all [Pillow](https://pypi.org/project/pillow/)-based thumbnail support; will fallback to libvips or ffmpeg |
|
2139
|
+
| `PRTY_NO_PILF` | disable Pillow `ImageFont` text rendering, used for folder thumbnails |
|
2140
|
+
| `PRTY_NO_PIL_AVIF` | disable 3rd-party Pillow plugin for [AVIF support](https://pypi.org/project/pillow-avif-plugin/) |
|
2141
|
+
| `PRTY_NO_PIL_HEIF` | disable 3rd-party Pillow plugin for [HEIF support](https://pypi.org/project/pyheif-pillow-opener/) |
|
2142
|
+
| `PRTY_NO_PIL_WEBP` | disable use of native webp support in Pillow |
|
2143
|
+
| `PRTY_NO_PSUTIL` | do not use [psutil](https://pypi.org/project/psutil/) for reaping stuck hooks and plugins on Windows |
|
2144
|
+
| `PRTY_NO_VIPS` | disable all [libvips](https://pypi.org/project/pyvips/)-based thumbnail support; will fallback to Pillow or ffmpeg |
|
2145
|
+
|
2146
|
+
example: `PRTY_NO_PIL=1 python3 copyparty-sfx.py`
|
2147
|
+
|
2148
|
+
* `PRTY_NO_PIL` saves ram
|
2149
|
+
* `PRTY_NO_VIPS` saves ram and startup time
|
2150
|
+
* python2.7 on windows: `PRTY_NO_FFMPEG` + `PRTY_NO_FFPROBE` saves startup time
|
2151
|
+
|
2152
|
+
|
2103
2153
|
## optional gpl stuff
|
2104
2154
|
|
2105
2155
|
some bundled tools have copyleft dependencies, see [./bin/#mtag](bin/#mtag)
|
@@ -85,6 +85,7 @@ turn almost any device into a file server with resumable uploads/downloads using
|
|
85
85
|
* [prometheus](#prometheus) - metrics/stats can be enabled
|
86
86
|
* [other extremely specific features](#other-extremely-specific-features) - you'll never find a use for these
|
87
87
|
* [custom mimetypes](#custom-mimetypes) - change the association of a file extension
|
88
|
+
* [feature chickenbits](#feature-chickenbits) - buggy feature? rip it out
|
88
89
|
* [packages](#packages) - the party might be closer than you think
|
89
90
|
* [arch package](#arch-package) - now [available on aur](https://aur.archlinux.org/packages/copyparty) maintained by [@icxes](https://github.com/icxes)
|
90
91
|
* [fedora package](#fedora-package) - does not exist yet
|
@@ -111,6 +112,7 @@ turn almost any device into a file server with resumable uploads/downloads using
|
|
111
112
|
* [HTTP API](#HTTP-API) - see [devnotes](./docs/devnotes.md#http-api)
|
112
113
|
* [dependencies](#dependencies) - mandatory deps
|
113
114
|
* [optional dependencies](#optional-dependencies) - install these to enable bonus features
|
115
|
+
* [dependency chickenbits](#dependency-chickenbits) - prevent loading an optional dependency
|
114
116
|
* [optional gpl stuff](#optional-gpl-stuff)
|
115
117
|
* [sfx](#sfx) - the self-contained "binary" (recommended!)
|
116
118
|
* [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+)
|
@@ -124,7 +126,7 @@ turn almost any device into a file server with resumable uploads/downloads using
|
|
124
126
|
|
125
127
|
just run **[copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/download/copyparty-sfx.py)** -- that's it! 🎉
|
126
128
|
|
127
|
-
* or install through pypi: `python3 -m pip install --user -U copyparty`
|
129
|
+
* or install through [pypi](https://pypi.org/project/copyparty/): `python3 -m pip install --user -U copyparty`
|
128
130
|
* or if you cannot install python, you can use [copyparty.exe](#copypartyexe) instead
|
129
131
|
* or install [on arch](#arch-package) ╱ [on NixOS](#nixos-module) ╱ [through nix](#nix-package)
|
130
132
|
* or if you are on android, [install copyparty in termux](#install-on-android)
|
@@ -194,7 +196,7 @@ firewall-cmd --reload
|
|
194
196
|
also see [comparison to similar software](./docs/versus.md)
|
195
197
|
|
196
198
|
* backend stuff
|
197
|
-
* ☑ IPv6
|
199
|
+
* ☑ IPv6 + unix-sockets
|
198
200
|
* ☑ [multiprocessing](#performance) (actual multithreading)
|
199
201
|
* ☑ volumes (mountpoints)
|
200
202
|
* ☑ [accounts](#accounts-and-volumes)
|
@@ -579,9 +581,6 @@ images with the following names (see `--th-covers`) become the thumbnail of the
|
|
579
581
|
* the order is significant, so if both `cover.png` and `folder.jpg` exist in a folder, it will pick the first matching `--th-covers` entry (`folder.jpg`)
|
580
582
|
* and, if you enable [file indexing](#file-indexing), it will also try those names as dotfiles (`.folder.jpg` and so), and then fallback on the first picture in the folder (if it has any pictures at all)
|
581
583
|
|
582
|
-
in the grid/thumbnail view, if the audio player panel is open, songs will start playing when clicked
|
583
|
-
* indicated by the audio files having the ▶ icon instead of 💾
|
584
|
-
|
585
584
|
enabling `multiselect` lets you click files to select them, and then shift-click another file for range-select
|
586
585
|
* `multiselect` is mostly intended for phones/tablets, but the `sel` option in the `[⚙️] settings` tab is better suited for desktop use, allowing selection by CTRL-clicking and range-selection with SHIFT-click, all without affecting regular clicking
|
587
586
|
* the `sel` option can be made default globally with `--gsel` or per-volume with volflag `gsel`
|
@@ -1460,6 +1459,8 @@ some reverse proxies (such as [Caddy](https://caddyserver.com/)) can automatical
|
|
1460
1459
|
* **warning:** nginx-QUIC (HTTP/3) is still experimental and can make uploads much slower, so HTTP/1.1 is recommended for now
|
1461
1460
|
* depending on server/client, HTTP/1.1 can also be 5x faster than HTTP/2
|
1462
1461
|
|
1462
|
+
for improved security (and a tiny performance boost) consider listening on a unix-socket with `-i /tmp/party.sock` instead of `-i 127.0.0.1`
|
1463
|
+
|
1463
1464
|
example webserver configs:
|
1464
1465
|
|
1465
1466
|
* [nginx config](contrib/nginx/copyparty.conf) -- entire domain/subdomain
|
@@ -1560,6 +1561,23 @@ in a config-file, this is the same as:
|
|
1560
1561
|
run copyparty with `--mimes` to list all the default mappings
|
1561
1562
|
|
1562
1563
|
|
1564
|
+
### feature chickenbits
|
1565
|
+
|
1566
|
+
buggy feature? rip it out by setting any of the following environment variables to disable its associated bell or whistle,
|
1567
|
+
|
1568
|
+
| env-var | what it does |
|
1569
|
+
| -------------------- | ------------ |
|
1570
|
+
| `PRTY_NO_IFADDR` | disable ip/nic discovery by poking into your OS with ctypes |
|
1571
|
+
| `PRTY_NO_IPV6` | disable some ipv6 support (should not be necessary since windows 2000) |
|
1572
|
+
| `PRTY_NO_LZMA` | disable streaming xz compression of incoming uploads |
|
1573
|
+
| `PRTY_NO_MP` | disable all use of the python `multiprocessing` module (actual multithreading, cpu-count for parsers/thumbnailers) |
|
1574
|
+
| `PRTY_NO_SQLITE` | disable all database-related functionality (file indexing, metadata indexing, most file deduplication logic) |
|
1575
|
+
| `PRTY_NO_TLS` | disable native HTTPS support; if you still want to accept HTTPS connections then TLS must now be terminated by a reverse-proxy |
|
1576
|
+
| `PRTY_NO_TPOKE` | disable systemd-tmpfilesd avoider |
|
1577
|
+
|
1578
|
+
example: `PRTY_NO_IFADDR=1 python3 copyparty-sfx.py`
|
1579
|
+
|
1580
|
+
|
1563
1581
|
# packages
|
1564
1582
|
|
1565
1583
|
the party might be closer than you think
|
@@ -1882,6 +1900,7 @@ some notes on hardening
|
|
1882
1900
|
* cors doesn't work right otherwise
|
1883
1901
|
* if you allow anonymous uploads or otherwise don't trust the contents of a volume, you can prevent XSS with volflag `nohtml`
|
1884
1902
|
* this returns html documents as plaintext, and also disables markdown rendering
|
1903
|
+
* when running behind a reverse-proxy, listen on a unix-socket with `-i /tmp/party.sock` instead of `-i 127.0.0.1` for tighter access control (plus you get a tiny performance boost for free)
|
1885
1904
|
|
1886
1905
|
safety profiles:
|
1887
1906
|
|
@@ -2046,6 +2065,37 @@ enable [smb](#smb-server) support (**not** recommended):
|
|
2046
2065
|
`pyvips` gives higher quality thumbnails than `Pillow` and is 320% faster, using 270% more ram: `sudo apt install libvips42 && python3 -m pip install --user -U pyvips`
|
2047
2066
|
|
2048
2067
|
|
2068
|
+
### dependency chickenbits
|
2069
|
+
|
2070
|
+
prevent loading an optional dependency , for example if:
|
2071
|
+
|
2072
|
+
* you have an incompatible version installed and it causes problems
|
2073
|
+
* you just don't want copyparty to use it, maybe to save ram
|
2074
|
+
|
2075
|
+
set any of the following environment variables to disable its associated optional feature,
|
2076
|
+
|
2077
|
+
| env-var | what it does |
|
2078
|
+
| -------------------- | ------------ |
|
2079
|
+
| `PRTY_NO_ARGON2` | disable argon2-cffi password hashing |
|
2080
|
+
| `PRTY_NO_CFSSL` | never attempt to generate self-signed certificates using [cfssl](https://github.com/cloudflare/cfssl) |
|
2081
|
+
| `PRTY_NO_FFMPEG` | **audio transcoding** goes byebye, **thumbnailing** must be handled by Pillow/libvips |
|
2082
|
+
| `PRTY_NO_FFPROBE` | **audio transcoding** goes byebye, **thumbnailing** must be handled by Pillow/libvips, **metadata-scanning** must be handled by mutagen |
|
2083
|
+
| `PRTY_NO_MUTAGEN` | do not use [mutagen](https://pypi.org/project/mutagen/) for reading metadata from media files; will fallback to ffprobe |
|
2084
|
+
| `PRTY_NO_PIL` | disable all [Pillow](https://pypi.org/project/pillow/)-based thumbnail support; will fallback to libvips or ffmpeg |
|
2085
|
+
| `PRTY_NO_PILF` | disable Pillow `ImageFont` text rendering, used for folder thumbnails |
|
2086
|
+
| `PRTY_NO_PIL_AVIF` | disable 3rd-party Pillow plugin for [AVIF support](https://pypi.org/project/pillow-avif-plugin/) |
|
2087
|
+
| `PRTY_NO_PIL_HEIF` | disable 3rd-party Pillow plugin for [HEIF support](https://pypi.org/project/pyheif-pillow-opener/) |
|
2088
|
+
| `PRTY_NO_PIL_WEBP` | disable use of native webp support in Pillow |
|
2089
|
+
| `PRTY_NO_PSUTIL` | do not use [psutil](https://pypi.org/project/psutil/) for reaping stuck hooks and plugins on Windows |
|
2090
|
+
| `PRTY_NO_VIPS` | disable all [libvips](https://pypi.org/project/pyvips/)-based thumbnail support; will fallback to Pillow or ffmpeg |
|
2091
|
+
|
2092
|
+
example: `PRTY_NO_PIL=1 python3 copyparty-sfx.py`
|
2093
|
+
|
2094
|
+
* `PRTY_NO_PIL` saves ram
|
2095
|
+
* `PRTY_NO_VIPS` saves ram and startup time
|
2096
|
+
* python2.7 on windows: `PRTY_NO_FFMPEG` + `PRTY_NO_FFPROBE` saves startup time
|
2097
|
+
|
2098
|
+
|
2049
2099
|
## optional gpl stuff
|
2050
2100
|
|
2051
2101
|
some bundled tools have copyleft dependencies, see [./bin/#mtag](bin/#mtag)
|
@@ -61,7 +61,13 @@ from .util import (
|
|
61
61
|
wrap,
|
62
62
|
)
|
63
63
|
|
64
|
+
if PY2:
|
65
|
+
range = xrange # type: ignore
|
66
|
+
|
64
67
|
try:
|
68
|
+
if os.environ.get("PRTY_NO_TLS"):
|
69
|
+
raise Exception()
|
70
|
+
|
65
71
|
HAVE_SSL = True
|
66
72
|
import ssl
|
67
73
|
except:
|
@@ -338,7 +344,7 @@ def configure_ssl_ver(al ) :
|
|
338
344
|
# oh man i love openssl
|
339
345
|
# check this out
|
340
346
|
# hold my beer
|
341
|
-
assert ssl
|
347
|
+
assert ssl # type: ignore
|
342
348
|
ptn = re.compile(r"^OP_NO_(TLS|SSL)v")
|
343
349
|
sslver = terse_sslver(al.ssl_ver).split(",")
|
344
350
|
flags = [k for k in ssl.__dict__ if ptn.match(k)]
|
@@ -372,7 +378,7 @@ def configure_ssl_ver(al ) :
|
|
372
378
|
|
373
379
|
|
374
380
|
def configure_ssl_ciphers(al ) :
|
375
|
-
assert ssl
|
381
|
+
assert ssl # type: ignore
|
376
382
|
ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
377
383
|
if al.ssl_ver:
|
378
384
|
ctx.options &= ~al.ssl_flags_en
|
@@ -485,6 +491,9 @@ def disable_quickedit() :
|
|
485
491
|
|
486
492
|
|
487
493
|
def sfx_tpoke(top ):
|
494
|
+
if os.environ.get("PRTY_NO_TPOKE"):
|
495
|
+
return
|
496
|
+
|
488
497
|
files = [top] + [
|
489
498
|
os.path.join(dp, p) for dp, dd, df in os.walk(top) for p in dd + df
|
490
499
|
]
|
@@ -689,6 +698,11 @@ def get_sects():
|
|
689
698
|
\033[36mxban\033[0m can be used to overrule / cancel a user ban event;
|
690
699
|
if the program returns 0 (true/OK) then the ban will NOT happen
|
691
700
|
|
701
|
+
effects can be used to redirect uploads into other
|
702
|
+
locations, and to delete or index other files based
|
703
|
+
on new uploads, but with certain limitations. See
|
704
|
+
bin/hooks/reloc* and docs/devnotes.md#hook-effects
|
705
|
+
|
692
706
|
except for \033[36mxm\033[0m, only one hook / one action can run at a time,
|
693
707
|
so it's recommended to use the \033[36mf\033[0m flag unless you really need
|
694
708
|
to wait for the hook to finish before continuing (without \033[36mf\033[0m
|
@@ -949,8 +963,8 @@ def add_upload(ap):
|
|
949
963
|
|
950
964
|
def add_network(ap):
|
951
965
|
ap2 = ap.add_argument_group('network options')
|
952
|
-
ap2.add_argument("-i", metavar="IP", type=u, default="::", help="ip to bind (comma-sep.), default: all IPv4 and IPv6")
|
953
|
-
ap2.add_argument("-p", metavar="PORT", type=u, default="3923", help="ports to bind (comma/range)")
|
966
|
+
ap2.add_argument("-i", metavar="IP", type=u, default="::", help="ip to bind (comma-sep.) and/or [\033[32munix:/tmp/a.sock\033[0m], default: all IPv4 and IPv6")
|
967
|
+
ap2.add_argument("-p", metavar="PORT", type=u, default="3923", help="ports to bind (comma/range); ignored for unix-sockets")
|
954
968
|
ap2.add_argument("--ll", action="store_true", help="include link-local IPv4/IPv6 in mDNS replies, even if the NIC has routable IPs (breaks some mDNS clients)")
|
955
969
|
ap2.add_argument("--rproxy", metavar="DEPTH", type=int, default=1, help="which ip to associate clients with; [\033[32m0\033[0m]=tcp, [\033[32m1\033[0m]=origin (first x-fwd, unsafe), [\033[32m2\033[0m]=outermost-proxy, [\033[32m3\033[0m]=second-proxy, [\033[32m-1\033[0m]=closest-proxy")
|
956
970
|
ap2.add_argument("--xff-hdr", metavar="NAME", type=u, default="x-forwarded-for", help="if reverse-proxied, which http header to read the client's real ip from")
|
@@ -1117,6 +1131,7 @@ def add_hooks(ap):
|
|
1117
1131
|
ap2.add_argument("--xad", metavar="CMD", type=u, action="append", help="execute \033[33mCMD\033[0m after a file delete")
|
1118
1132
|
ap2.add_argument("--xm", metavar="CMD", type=u, action="append", help="execute \033[33mCMD\033[0m on message")
|
1119
1133
|
ap2.add_argument("--xban", metavar="CMD", type=u, action="append", help="execute \033[33mCMD\033[0m if someone gets banned (pw/404/403/url)")
|
1134
|
+
ap2.add_argument("--hook-v", action="store_true", help="verbose hooks")
|
1120
1135
|
|
1121
1136
|
|
1122
1137
|
def add_stats(ap):
|
@@ -1345,9 +1360,10 @@ def add_ui(ap, retry):
|
|
1345
1360
|
ap2.add_argument("--unlist", metavar="REGEX", type=u, default="", help="don't show files matching \033[33mREGEX\033[0m in file list. Purely cosmetic! Does not affect API calls, just the browser. Example: [\033[32m\\.(js|css)$\033[0m] (volflag=unlist)")
|
1346
1361
|
ap2.add_argument("--favico", metavar="TXT", type=u, default="c 000 none" if retry else "🎉 000 none", help="\033[33mfavicon-text\033[0m [ \033[33mforeground\033[0m [ \033[33mbackground\033[0m ] ], set blank to disable")
|
1347
1362
|
ap2.add_argument("--mpmc", metavar="URL", type=u, default="", help="change the mediaplayer-toggle mouse cursor; URL to a folder with {2..5}.png inside (or disable with [\033[32m.\033[0m])")
|
1348
|
-
ap2.add_argument("--
|
1349
|
-
ap2.add_argument("--
|
1350
|
-
ap2.add_argument("--
|
1363
|
+
ap2.add_argument("--css-browser", metavar="L", type=u, default="", help="URL to additional CSS to include in the filebrowser html")
|
1364
|
+
ap2.add_argument("--js-browser", metavar="L", type=u, default="", help="URL to additional JS to include in the filebrowser html")
|
1365
|
+
ap2.add_argument("--js-other", metavar="L", type=u, default="", help="URL to additional JS to include in all other pages")
|
1366
|
+
ap2.add_argument("--html-head", metavar="TXT", type=u, default="", help="text to append to the <head> of all HTML pages (except for basic-browser); can be @PATH to send the contents of a file at PATH, and/or begin with %% to render as jinja2 template (volflag=html_head)")
|
1351
1367
|
ap2.add_argument("--ih", action="store_true", help="if a folder contains index.html, show that instead of the directory listing by default (can be changed in the client settings UI, or add ?v to URL for override)")
|
1352
1368
|
ap2.add_argument("--textfiles", metavar="CSV", type=u, default="txt,nfo,diz,cue,readme", help="file extensions to present as plaintext")
|
1353
1369
|
ap2.add_argument("--txt-max", metavar="KiB", type=int, default=64, help="max size of embedded textfiles on ?doc= (anything bigger will be lazy-loaded by JS)")
|
@@ -1366,12 +1382,14 @@ def add_debug(ap):
|
|
1366
1382
|
ap2 = ap.add_argument_group('debug options')
|
1367
1383
|
ap2.add_argument("--vc", action="store_true", help="verbose config file parser (explain config)")
|
1368
1384
|
ap2.add_argument("--cgen", action="store_true", help="generate config file from current config (best-effort; probably buggy)")
|
1385
|
+
ap2.add_argument("--deps", action="store_true", help="list information about detected optional dependencies")
|
1369
1386
|
if hasattr(select, "poll"):
|
1370
1387
|
ap2.add_argument("--no-poll", action="store_true", help="kernel-bug workaround: disable poll; use select instead (limits max num clients to ~700)")
|
1371
1388
|
ap2.add_argument("--no-sendfile", action="store_true", help="kernel-bug workaround: disable sendfile; do a safe and slow read-send-loop instead")
|
1372
1389
|
ap2.add_argument("--no-scandir", action="store_true", help="kernel-bug workaround: disable scandir; do a listdir + stat on each file instead")
|
1373
1390
|
ap2.add_argument("--no-fastboot", action="store_true", help="wait for initial filesystem indexing before accepting client requests")
|
1374
1391
|
ap2.add_argument("--no-htp", action="store_true", help="disable httpserver threadpool, create threads as-needed instead")
|
1392
|
+
ap2.add_argument("--rm-sck", action="store_true", help="when listening on unix-sockets, do a basic delete+bind instead of the default atomic bind")
|
1375
1393
|
ap2.add_argument("--srch-dbg", action="store_true", help="explain search processing, and do some extra expensive sanity checks")
|
1376
1394
|
ap2.add_argument("--rclone-mdns", action="store_true", help="use mdns-domain instead of server-ip on /?hc")
|
1377
1395
|
ap2.add_argument("--stackmon", metavar="P,S", type=u, default="", help="write stacktrace to \033[33mP\033[0math every \033[33mS\033[0m second, for example --stackmon=\033[32m./st/%%Y-%%m/%%d/%%H%%M.xz,60")
|
@@ -12,7 +12,7 @@ import threading
|
|
12
12
|
import time
|
13
13
|
from datetime import datetime
|
14
14
|
|
15
|
-
from .__init__ import ANYWIN, TYPE_CHECKING, WINDOWS, E
|
15
|
+
from .__init__ import ANYWIN, PY2, TYPE_CHECKING, WINDOWS, E
|
16
16
|
from .bos import bos
|
17
17
|
from .cfg import flagdescs, permdescs, vf_bmap, vf_cmap, vf_vmap
|
18
18
|
from .pwhash import PWHash
|
@@ -49,6 +49,9 @@ if TYPE_CHECKING:
|
|
49
49
|
# Vflags: TypeAlias = dict[str, Any]
|
50
50
|
# Mflags: TypeAlias = dict[str, Vflags]
|
51
51
|
|
52
|
+
if PY2:
|
53
|
+
range = xrange # type: ignore
|
54
|
+
|
52
55
|
|
53
56
|
LEELOO_DALLAS = "leeloo_dallas"
|
54
57
|
|
@@ -434,7 +437,7 @@ class VFS(object):
|
|
434
437
|
|
435
438
|
def _find(self, vpath ) :
|
436
439
|
"""return [vfs,remainder]"""
|
437
|
-
if vpath
|
440
|
+
if not vpath:
|
438
441
|
return self, ""
|
439
442
|
|
440
443
|
if "/" in vpath:
|
@@ -444,7 +447,7 @@ class VFS(object):
|
|
444
447
|
rem = ""
|
445
448
|
|
446
449
|
if name in self.nodes:
|
447
|
-
return self.nodes[name]._find(
|
450
|
+
return self.nodes[name]._find(rem)
|
448
451
|
|
449
452
|
return self, vpath
|
450
453
|
|
@@ -511,8 +514,8 @@ class VFS(object):
|
|
511
514
|
t = "{} has no {} in [{}] => [{}] => [{}]"
|
512
515
|
self.log("vfs", t.format(uname, msg, vpath, cvpath, ap), 6)
|
513
516
|
|
514
|
-
t = 'you don\'t have %s-access in "/%s"'
|
515
|
-
raise Pebkac(err, t % (msg, cvpath))
|
517
|
+
t = 'you don\'t have %s-access in "/%s" or below "/%s"'
|
518
|
+
raise Pebkac(err, t % (msg, cvpath, vn.vpath))
|
516
519
|
|
517
520
|
return vn, rem
|
518
521
|
|
@@ -1888,7 +1891,7 @@ class AuthSrv(object):
|
|
1888
1891
|
self.log(t.format(vol.vpath), 1)
|
1889
1892
|
del vol.flags["lifetime"]
|
1890
1893
|
|
1891
|
-
needs_e2d = [x for x in hooks if x
|
1894
|
+
needs_e2d = [x for x in hooks if x in ("xau", "xiu")]
|
1892
1895
|
drop = [x for x in needs_e2d if vol.flags.get(x)]
|
1893
1896
|
if drop:
|
1894
1897
|
t = 'removing [{}] from volume "/{}" because e2d is disabled'
|
@@ -9,7 +9,7 @@ import time
|
|
9
9
|
from .__init__ import ANYWIN, MACOS
|
10
10
|
from .authsrv import AXS, VFS
|
11
11
|
from .bos import bos
|
12
|
-
from .util import chkcmd, min_ex
|
12
|
+
from .util import chkcmd, min_ex, undot
|
13
13
|
|
14
14
|
class Fstab(object):
|
15
15
|
def __init__(self, log , args ):
|
@@ -46,7 +46,7 @@ class Fstab(object):
|
|
46
46
|
self.log(msg.format(path, fs, min_ex()), 3)
|
47
47
|
return fs
|
48
48
|
|
49
|
-
path = path
|
49
|
+
path = undot(path)
|
50
50
|
try:
|
51
51
|
return self.cache[path]
|
52
52
|
except:
|
@@ -118,7 +118,7 @@ class Fstab(object):
|
|
118
118
|
if ANYWIN:
|
119
119
|
path = self._winpath(path)
|
120
120
|
|
121
|
-
path = path
|
121
|
+
path = undot(path)
|
122
122
|
ptn = re.compile(r"^[^\\/]*")
|
123
123
|
vn, rem = self.tab._find(path)
|
124
124
|
if not self.trusted:
|
@@ -37,6 +37,10 @@ from .util import (
|
|
37
37
|
if TYPE_CHECKING:
|
38
38
|
from .svchub import SvcHub
|
39
39
|
|
40
|
+
if PY2:
|
41
|
+
range = xrange # type: ignore
|
42
|
+
|
43
|
+
|
40
44
|
class FSE(FilesystemError):
|
41
45
|
def __init__(self, msg , severity = 0) :
|
42
46
|
super(FilesystemError, self).__init__(msg)
|
@@ -345,7 +349,7 @@ class FtpFs(AbstractedFS):
|
|
345
349
|
svp = join(self.cwd, src).lstrip("/")
|
346
350
|
dvp = join(self.cwd, dst).lstrip("/")
|
347
351
|
try:
|
348
|
-
self.hub.up2k.handle_mv(self.uname, svp, dvp)
|
352
|
+
self.hub.up2k.handle_mv(self.uname, self.h.cli_ip, svp, dvp)
|
349
353
|
except Exception as ex:
|
350
354
|
raise FSE(str(ex))
|
351
355
|
|
@@ -463,6 +467,9 @@ class FtpHandler(FTPHandler):
|
|
463
467
|
xbu = vfs.flags.get("xbu")
|
464
468
|
if xbu and not runhook(
|
465
469
|
None,
|
470
|
+
None,
|
471
|
+
self.hub.up2k,
|
472
|
+
"xbu.ftpd",
|
466
473
|
xbu,
|
467
474
|
ap,
|
468
475
|
vp,
|
@@ -472,7 +479,7 @@ class FtpHandler(FTPHandler):
|
|
472
479
|
0,
|
473
480
|
0,
|
474
481
|
self.cli_ip,
|
475
|
-
|
482
|
+
time.time(),
|
476
483
|
"",
|
477
484
|
):
|
478
485
|
raise FSE("Upload blocked by xbu server config")
|
@@ -575,9 +582,15 @@ class Ftpd(object):
|
|
575
582
|
if "::" in ips:
|
576
583
|
ips.append("0.0.0.0")
|
577
584
|
|
585
|
+
ips = [x for x in ips if "unix:" not in x]
|
586
|
+
|
578
587
|
if self.args.ftp4:
|
579
588
|
ips = [x for x in ips if ":" not in x]
|
580
589
|
|
590
|
+
if not ips:
|
591
|
+
lgr.fatal("cannot start ftp-server; no compatible IPs in -i")
|
592
|
+
return
|
593
|
+
|
581
594
|
ips = list(ODict.fromkeys(ips)) # dedup
|
582
595
|
|
583
596
|
ioloop = IOLoop()
|