copyparty 1.6.9__tar.gz → 1.6.11__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.6.9/copyparty.egg-info → copyparty-1.6.11}/PKG-INFO +61 -30
- {copyparty-1.6.9 → copyparty-1.6.11}/README.md +60 -29
- {copyparty-1.6.9 → copyparty-1.6.11}/bin/up2k.py +5 -7
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/__main__.py +1 -1
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/__version__.py +2 -2
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/httpcli.py +48 -17
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/th_srv.py +33 -1
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/up2k.py +13 -6
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/a/up2k.py +5 -7
- copyparty-1.6.11/copyparty/web/baguettebox.js.gz +0 -0
- copyparty-1.6.11/copyparty/web/browser.css.gz +0 -0
- copyparty-1.6.11/copyparty/web/browser.js.gz +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/deps/easymde.css.gz +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/deps/easymde.js.gz +0 -0
- copyparty-1.6.11/copyparty/web/deps/marked.js.gz +0 -0
- copyparty-1.6.11/copyparty/web/deps/mini-fa.css.gz +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/deps/sha512.ac.js.gz +0 -0
- copyparty-1.6.11/copyparty/web/md.js.gz +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/svcs.html +3 -4
- copyparty-1.6.11/copyparty/web/ui.css.gz +0 -0
- copyparty-1.6.11/copyparty/web/util.js.gz +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11/copyparty.egg-info}/PKG-INFO +61 -30
- copyparty-1.6.9/copyparty/web/baguettebox.js.gz +0 -0
- copyparty-1.6.9/copyparty/web/browser.css.gz +0 -0
- copyparty-1.6.9/copyparty/web/browser.js.gz +0 -0
- copyparty-1.6.9/copyparty/web/deps/marked.js.gz +0 -0
- copyparty-1.6.9/copyparty/web/deps/mini-fa.css.gz +0 -0
- copyparty-1.6.9/copyparty/web/md.js.gz +0 -0
- copyparty-1.6.9/copyparty/web/ui.css.gz +0 -0
- copyparty-1.6.9/copyparty/web/util.js.gz +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/LICENSE +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/MANIFEST.in +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/bin/partyfuse.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/__init__.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/authsrv.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/bos/__init__.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/bos/bos.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/bos/path.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/broker_mp.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/broker_mpw.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/broker_thr.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/broker_util.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/cfg.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/dxml.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/fsutil.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/ftpd.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/httpconn.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/httpsrv.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/ico.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/mdns.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/mtag.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/multicast.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/res/COPYING.txt +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/res/insecure.pem +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/smbd.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/ssdp.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/star.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/stolen/__init__.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/stolen/dnslib/__init__.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/stolen/dnslib/bimap.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/stolen/dnslib/bit.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/stolen/dnslib/buffer.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/stolen/dnslib/dns.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/stolen/dnslib/label.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/stolen/dnslib/lex.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/stolen/dnslib/ranges.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/stolen/ifaddr/__init__.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/stolen/ifaddr/_posix.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/stolen/ifaddr/_shared.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/stolen/ifaddr/_win32.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/stolen/qrcodegen.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/stolen/surrogateescape.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/sutil.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/svchub.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/szip.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/tcpsrv.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/th_cli.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/u2idx.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/util.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/a/__init__.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/a/partyfuse.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/a/webdav-cfg.bat +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/browser.html +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/browser2.html +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/cf.html +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/copyparty.gif +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/dbg-audio.js.gz +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/dd/2.png +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/dd/3.png +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/dd/4.png +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/dd/5.png +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/dd/__init__.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/deps/__init__.py +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/deps/mini-fa.woff +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/deps/prism.css.gz +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/deps/prism.js.gz +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/deps/prismd.css.gz +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/deps/scp.woff2 +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/deps/sha512.hw.js.gz +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/md.css.gz +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/md.html +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/md2.css.gz +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/md2.js.gz +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/mde.css.gz +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/mde.html +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/mde.js.gz +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/msg.css.gz +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/msg.html +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/splash.css.gz +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/splash.html +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/splash.js.gz +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/svcs.js.gz +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/up2k.js.gz +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty/web/w.hash.js.gz +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty.egg-info/SOURCES.txt +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty.egg-info/dependency_links.txt +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty.egg-info/entry_points.txt +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty.egg-info/requires.txt +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/copyparty.egg-info/top_level.txt +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/setup.cfg +0 -0
- {copyparty-1.6.9 → copyparty-1.6.11}/setup.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: copyparty
|
3
|
-
Version: 1.6.
|
3
|
+
Version: 1.6.11
|
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
|
Home-page: https://github.com/9001/copyparty
|
6
6
|
Author: ed
|
@@ -40,30 +40,17 @@ License-File: LICENSE
|
|
40
40
|
|
41
41
|
# 💾🎉 copyparty
|
42
42
|
|
43
|
-
|
44
|
-
* MIT-Licensed, 2019-05-26, ed @ irc.rizon.net
|
43
|
+
turn almost any device into a file server with resumable uploads/downloads using [*any*](#browser-support) web browser
|
45
44
|
|
45
|
+
* server only needs Python (2 or 3), all dependencies optional
|
46
|
+
* 🔌 protocols: [http](#the-browser) // [ftp](#ftp-server) // [webdav](#webdav-server) // [smb/cifs](#smb-server)
|
47
|
+
* 📱 [android app](#android-app) // [iPhone shortcuts](#ios-shortcuts)
|
46
48
|
|
47
|
-
|
48
|
-
|
49
|
-
turn your phone or raspi into a portable file server with resumable uploads/downloads using *any* web browser
|
50
|
-
|
51
|
-
* server only needs Python (`2.7` or `3.3+`), all dependencies optional
|
52
|
-
* browse/upload with [IE4](#browser-support) / netscape4.0 on win3.11 (heh)
|
53
|
-
* protocols: [http](#the-browser) // [ftp](#ftp-server) // [webdav](#webdav-server) // [smb/cifs](#smb-server)
|
54
|
-
|
55
|
-
**[Get started](#quickstart)!** or visit the **[read-only demo server](https://a.ocv.me/pub/demo/)** 👀 running from a basement in finland
|
49
|
+
👉 **[Get started](#quickstart)!** or visit the **[read-only demo server](https://a.ocv.me/pub/demo/)** 👀 running from a basement in finland
|
56
50
|
|
57
51
|
📷 **screenshots:** [browser](#the-browser) // [upload](#uploading) // [unpost](#unpost) // [thumbnails](#thumbnails) // [search](#searching) // [fsearch](#file-search) // [zip-DL](#zip-downloads) // [md-viewer](#markdown-viewer)
|
58
52
|
|
59
53
|
|
60
|
-
## get the app
|
61
|
-
|
62
|
-
<a href="https://f-droid.org/packages/me.ocv.partyup/"><img src="https://ocv.me/fdroid.png" alt="Get it on F-Droid" height="50" /> '' <img src="https://img.shields.io/f-droid/v/me.ocv.partyup.svg" alt="f-droid version info" /></a> '' <a href="https://github.com/9001/party-up"><img src="https://img.shields.io/github/release/9001/party-up.svg?logo=github" alt="github version info" /></a>
|
63
|
-
|
64
|
-
(the app is **NOT** the full copyparty server! just a basic upload client, nothing fancy yet)
|
65
|
-
|
66
|
-
|
67
54
|
## readme toc
|
68
55
|
|
69
56
|
* top
|
@@ -122,12 +109,16 @@ turn your phone or raspi into a portable file server with resumable uploads/down
|
|
122
109
|
* [reverse-proxy](#reverse-proxy) - running copyparty next to other websites
|
123
110
|
* [browser support](#browser-support) - TLDR: yes
|
124
111
|
* [client examples](#client-examples) - interact with copyparty using non-browser clients
|
112
|
+
* [folder sync](#folder-sync) - sync folders to/from copyparty
|
125
113
|
* [mount as drive](#mount-as-drive) - a remote copyparty server as a local filesystem
|
114
|
+
* [android app](#android-app) - upload to copyparty with one tap
|
115
|
+
* [iOS shortcuts](#iOS-shortcuts) - there is no iPhone app, but
|
126
116
|
* [performance](#performance) - defaults are usually fine - expect `8 GiB/s` download, `1 GiB/s` upload
|
127
117
|
* [client-side](#client-side) - when uploading files
|
128
118
|
* [security](#security) - some notes on hardening
|
129
119
|
* [gotchas](#gotchas) - behavior that might be unexpected
|
130
120
|
* [cors](#cors) - cross-site request config
|
121
|
+
* [https](#https) - both HTTP and HTTPS are accepted
|
131
122
|
* [recovering from crashes](#recovering-from-crashes)
|
132
123
|
* [client crashes](#client-crashes)
|
133
124
|
* [frefox wsod](#frefox-wsod) - firefox 87 can crash during uploads
|
@@ -179,7 +170,7 @@ some recommended options:
|
|
179
170
|
|
180
171
|
you may also want these, especially on servers:
|
181
172
|
|
182
|
-
* [contrib/systemd/copyparty.service](contrib/systemd/copyparty.service) to run copyparty as a systemd service
|
173
|
+
* [contrib/systemd/copyparty.service](contrib/systemd/copyparty.service) to run copyparty as a systemd service (see guide inside)
|
183
174
|
* [contrib/systemd/prisonparty.service](contrib/systemd/prisonparty.service) to run it in a chroot (for extra security)
|
184
175
|
* [contrib/rc/copyparty](contrib/rc/copyparty) to run copyparty on FreeBSD
|
185
176
|
* [contrib/nginx/copyparty.conf](contrib/nginx/copyparty.conf) to [reverse-proxy](#reverse-proxy) behind nginx (for better https)
|
@@ -217,7 +208,7 @@ firewall-cmd --reload
|
|
217
208
|
* ☑ write-only folders
|
218
209
|
* ☑ [unpost](#unpost): undo/delete accidental uploads
|
219
210
|
* ☑ [self-destruct](#self-destruct) (specified server-side or client-side)
|
220
|
-
* ☑ symlink/discard
|
211
|
+
* ☑ symlink/discard duplicates (content-matching)
|
221
212
|
* download
|
222
213
|
* ☑ single files in browser
|
223
214
|
* ☑ [folders as zip / tar files](#zip-downloads)
|
@@ -239,7 +230,7 @@ firewall-cmd --reload
|
|
239
230
|
* ☑ search by name/path/date/size
|
240
231
|
* ☑ [search by ID3-tags etc.](#searching)
|
241
232
|
* client support
|
242
|
-
* ☑ [
|
233
|
+
* ☑ [folder sync](#folder-sync)
|
243
234
|
* ☑ [curl-friendly](https://user-images.githubusercontent.com/241032/215322619-ea5fd606-3654-40ad-94ee-2bc058647bb2.png)
|
244
235
|
* markdown
|
245
236
|
* ☑ [viewer](#markdown-viewer)
|
@@ -318,7 +309,7 @@ server notes:
|
|
318
309
|
|
319
310
|
* iPhones: the volume control doesn't work because [apple doesn't want it to](https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html#//apple_ref/doc/uid/TP40009523-CH5-SW11)
|
320
311
|
* *future workaround:* enable the equalizer, make it all-zero, and set a negative boost to reduce the volume
|
321
|
-
* "future" because `AudioContext`
|
312
|
+
* "future" because `AudioContext` can't maintain a stable playback speed in the current iOS version (15.7), maybe one day...
|
322
313
|
|
323
314
|
* Windows: folders cannot be accessed if the name ends with `.`
|
324
315
|
* python or windows bug
|
@@ -1142,13 +1133,15 @@ see the top of [./copyparty/web/browser.css](./copyparty/web/browser.css) where
|
|
1142
1133
|
|
1143
1134
|
## reverse-proxy
|
1144
1135
|
|
1145
|
-
running copyparty next to other websites hosted on an existing webserver such as nginx or apache
|
1136
|
+
running copyparty next to other websites hosted on an existing webserver such as nginx, caddy, or apache
|
1146
1137
|
|
1147
1138
|
you can either:
|
1148
1139
|
* give copyparty its own domain or subdomain (recommended)
|
1149
1140
|
* or do location-based proxying, using `--rp-loc=/stuff` to tell copyparty where it is mounted -- has a slight performance cost and higher chance of bugs
|
1150
1141
|
* if copyparty says `incorrect --rp-loc or webserver config; expected vpath starting with [...]` it's likely because the webserver is stripping away the proxy location from the request URLs -- see the `ProxyPass` in the apache example below
|
1151
1142
|
|
1143
|
+
some reverse proxies (such as [Caddy](https://caddyserver.com/)) can automatically obtain a valid https/tls certificate for you, and some support HTTP/2 and QUIC which could be a nice speed boost
|
1144
|
+
|
1152
1145
|
example webserver configs:
|
1153
1146
|
|
1154
1147
|
* [nginx config](contrib/nginx/copyparty.conf) -- entire domain/subdomain
|
@@ -1226,7 +1219,7 @@ interact with copyparty using non-browser clients
|
|
1226
1219
|
* `(printf 'PUT / HTTP/1.1\r\n\r\n'; cat movie.mkv) >/dev/tcp/127.0.0.1/3923`
|
1227
1220
|
|
1228
1221
|
* python: [up2k.py](https://github.com/9001/copyparty/blob/hovudstraum/bin/up2k.py) is a command-line up2k client [(webm)](https://ocv.me/stuff/u2cli.webm)
|
1229
|
-
* file uploads, file-search, folder sync, autoresume of aborted/broken uploads
|
1222
|
+
* file uploads, file-search, [folder sync](#folder-sync), autoresume of aborted/broken uploads
|
1230
1223
|
* can be downloaded from copyparty: controlpanel -> connect -> [up2k.py](http://127.0.0.1:3923/.cpr/a/up2k.py)
|
1231
1224
|
* see [./bin/README.md#up2kpy](bin/README.md#up2kpy)
|
1232
1225
|
|
@@ -1247,17 +1240,27 @@ you can provide passwords using header `PW: hunter2`, cookie `cppwd=hunter2`, ur
|
|
1247
1240
|
NOTE: curl will not send the original filename if you use `-T` combined with url-params! Also, make sure to always leave a trailing slash in URLs unless you want to override the filename
|
1248
1241
|
|
1249
1242
|
|
1243
|
+
## folder sync
|
1244
|
+
|
1245
|
+
sync folders to/from copyparty
|
1246
|
+
|
1247
|
+
the commandline uploader [up2k.py](https://github.com/9001/copyparty/tree/hovudstraum/bin#up2kpy) with `--dr` is the best way to sync a folder to copyparty; verifies checksums and does files in parallel, and deletes unexpected files on the server after upload has finished which makes file-renames really cheap (it'll rename serverside and skip uploading)
|
1248
|
+
|
1249
|
+
alternatively there is [rclone](./docs/rclone.md) which allows for bidirectional sync and is *way* more flexible (stream files straight from sftp/s3/gcs to copyparty, ...), although there is no integrity check and it won't work with files over 100 MiB if copyparty is behind cloudflare
|
1250
|
+
|
1251
|
+
* starting from rclone v1.63 (currently [in beta](https://beta.rclone.org/?filter=latest)), rclone will also be faster than up2k.py
|
1252
|
+
|
1253
|
+
|
1250
1254
|
## mount as drive
|
1251
1255
|
|
1252
1256
|
a remote copyparty server as a local filesystem; go to the control-panel and click `connect` to see a list of commands to do that
|
1253
1257
|
|
1254
1258
|
alternatively, some alternatives roughly sorted by speed (unreproducible benchmark), best first:
|
1255
1259
|
|
1256
|
-
* [rclone-
|
1260
|
+
* [rclone-webdav](./docs/rclone.md) (25s), read/WRITE ([v1.63-beta](https://beta.rclone.org/?filter=latest))
|
1261
|
+
* [rclone-http](./docs/rclone.md) (26s), read-only
|
1262
|
+
* [partyfuse.py](./bin/#partyfusepy) (35s), read-only
|
1257
1263
|
* [rclone-ftp](./docs/rclone.md) (47s), read/WRITE
|
1258
|
-
* [rclone-webdav](./docs/rclone.md) (51s), read/WRITE
|
1259
|
-
* copyparty-1.5.0's webdav server is faster than rclone-1.60.0 (69s)
|
1260
|
-
* [partyfuse.py](./bin/#partyfusepy) (71s), read-only
|
1261
1264
|
* davfs2 (103s), read/WRITE, *very fast* on small files
|
1262
1265
|
* [win10-webdav](#webdav-server) (138s), read/WRITE
|
1263
1266
|
* [win10-smb2](#smb-server) (387s), read/WRITE
|
@@ -1265,6 +1268,27 @@ alternatively, some alternatives roughly sorted by speed (unreproducible benchma
|
|
1265
1268
|
most clients will fail to mount the root of a copyparty server unless there is a root volume (so you get the admin-panel instead of a browser when accessing it) -- in that case, mount a specific volume instead
|
1266
1269
|
|
1267
1270
|
|
1271
|
+
# android app
|
1272
|
+
|
1273
|
+
upload to copyparty with one tap
|
1274
|
+
|
1275
|
+
<a href="https://f-droid.org/packages/me.ocv.partyup/"><img src="https://ocv.me/fdroid.png" alt="Get it on F-Droid" height="50" /> '' <img src="https://img.shields.io/f-droid/v/me.ocv.partyup.svg" alt="f-droid version info" /></a> '' <a href="https://github.com/9001/party-up"><img src="https://img.shields.io/github/release/9001/party-up.svg?logo=github" alt="github version info" /></a>
|
1276
|
+
|
1277
|
+
the app is **NOT** the full copyparty server! just a basic upload client, nothing fancy yet
|
1278
|
+
|
1279
|
+
if you want to run the copyparty server on your android device, see [install on android](#install-on-android)
|
1280
|
+
|
1281
|
+
|
1282
|
+
# iOS shortcuts
|
1283
|
+
|
1284
|
+
there is no iPhone app, but the following shortcuts are almost as good:
|
1285
|
+
|
1286
|
+
* [upload to copyparty](https://www.icloud.com/shortcuts/41e98dd985cb4d3bb433222bc1e9e770) ([offline](https://github.com/9001/copyparty/raw/hovudstraum/contrib/ios/upload-to-copyparty.shortcut)) ([png](https://user-images.githubusercontent.com/241032/226118053-78623554-b0ed-482e-98e4-6d57ada58ea4.png)) based on the [original](https://www.icloud.com/shortcuts/ab415d5b4de3467b9ce6f151b439a5d7) by [Daedren](https://github.com/Daedren) (thx!)
|
1287
|
+
* can strip exif, upload files, pics, vids, links, clipboard
|
1288
|
+
* can download links and rehost the target file on copyparty (see first comment inside the shortcut)
|
1289
|
+
* pics become lowres if you share from gallery to shortcut, so better to launch the shortcut and pick stuff from there
|
1290
|
+
|
1291
|
+
|
1268
1292
|
# performance
|
1269
1293
|
|
1270
1294
|
defaults are usually fine - expect `8 GiB/s` download, `1 GiB/s` upload
|
@@ -1360,6 +1384,13 @@ by default, except for `GET` and `HEAD` operations, all requests must either:
|
|
1360
1384
|
cors can be configured with `--acao` and `--acam`, or the protections entirely disabled with `--allow-csrf`
|
1361
1385
|
|
1362
1386
|
|
1387
|
+
## https
|
1388
|
+
|
1389
|
+
both HTTP and HTTPS are accepted by default, but letting a [reverse proxy](#reverse-proxy) handle the https/tls/ssl would be better (probably more secure by default)
|
1390
|
+
|
1391
|
+
copyparty doesn't speak HTTP/2 or QUIC, so using a reverse proxy would solve that as well
|
1392
|
+
|
1393
|
+
|
1363
1394
|
# recovering from crashes
|
1364
1395
|
|
1365
1396
|
## client crashes
|
@@ -1427,7 +1458,7 @@ these are standalone programs and will never be imported / evaluated by copypart
|
|
1427
1458
|
|
1428
1459
|
the self-contained "binary" [copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/download/copyparty-sfx.py) will unpack itself and run copyparty, assuming you have python installed of course
|
1429
1460
|
|
1430
|
-
you can reduce the sfx size by repacking it; see [./docs/devnotes.md#sfx-repack](
|
1461
|
+
you can reduce the sfx size by repacking it; see [./docs/devnotes.md#sfx-repack](./docs/devnotes.md#sfx-repack)
|
1431
1462
|
|
1432
1463
|
|
1433
1464
|
## copyparty.exe
|
@@ -1,29 +1,16 @@
|
|
1
1
|
# 💾🎉 copyparty
|
2
2
|
|
3
|
-
|
4
|
-
* MIT-Licensed, 2019-05-26, ed @ irc.rizon.net
|
3
|
+
turn almost any device into a file server with resumable uploads/downloads using [*any*](#browser-support) web browser
|
5
4
|
|
5
|
+
* server only needs Python (2 or 3), all dependencies optional
|
6
|
+
* 🔌 protocols: [http](#the-browser) // [ftp](#ftp-server) // [webdav](#webdav-server) // [smb/cifs](#smb-server)
|
7
|
+
* 📱 [android app](#android-app) // [iPhone shortcuts](#ios-shortcuts)
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
turn your phone or raspi into a portable file server with resumable uploads/downloads using *any* web browser
|
10
|
-
|
11
|
-
* server only needs Python (`2.7` or `3.3+`), all dependencies optional
|
12
|
-
* browse/upload with [IE4](#browser-support) / netscape4.0 on win3.11 (heh)
|
13
|
-
* protocols: [http](#the-browser) // [ftp](#ftp-server) // [webdav](#webdav-server) // [smb/cifs](#smb-server)
|
14
|
-
|
15
|
-
**[Get started](#quickstart)!** or visit the **[read-only demo server](https://a.ocv.me/pub/demo/)** 👀 running from a basement in finland
|
9
|
+
👉 **[Get started](#quickstart)!** or visit the **[read-only demo server](https://a.ocv.me/pub/demo/)** 👀 running from a basement in finland
|
16
10
|
|
17
11
|
📷 **screenshots:** [browser](#the-browser) // [upload](#uploading) // [unpost](#unpost) // [thumbnails](#thumbnails) // [search](#searching) // [fsearch](#file-search) // [zip-DL](#zip-downloads) // [md-viewer](#markdown-viewer)
|
18
12
|
|
19
13
|
|
20
|
-
## get the app
|
21
|
-
|
22
|
-
<a href="https://f-droid.org/packages/me.ocv.partyup/"><img src="https://ocv.me/fdroid.png" alt="Get it on F-Droid" height="50" /> '' <img src="https://img.shields.io/f-droid/v/me.ocv.partyup.svg" alt="f-droid version info" /></a> '' <a href="https://github.com/9001/party-up"><img src="https://img.shields.io/github/release/9001/party-up.svg?logo=github" alt="github version info" /></a>
|
23
|
-
|
24
|
-
(the app is **NOT** the full copyparty server! just a basic upload client, nothing fancy yet)
|
25
|
-
|
26
|
-
|
27
14
|
## readme toc
|
28
15
|
|
29
16
|
* top
|
@@ -82,12 +69,16 @@ turn your phone or raspi into a portable file server with resumable uploads/down
|
|
82
69
|
* [reverse-proxy](#reverse-proxy) - running copyparty next to other websites
|
83
70
|
* [browser support](#browser-support) - TLDR: yes
|
84
71
|
* [client examples](#client-examples) - interact with copyparty using non-browser clients
|
72
|
+
* [folder sync](#folder-sync) - sync folders to/from copyparty
|
85
73
|
* [mount as drive](#mount-as-drive) - a remote copyparty server as a local filesystem
|
74
|
+
* [android app](#android-app) - upload to copyparty with one tap
|
75
|
+
* [iOS shortcuts](#iOS-shortcuts) - there is no iPhone app, but
|
86
76
|
* [performance](#performance) - defaults are usually fine - expect `8 GiB/s` download, `1 GiB/s` upload
|
87
77
|
* [client-side](#client-side) - when uploading files
|
88
78
|
* [security](#security) - some notes on hardening
|
89
79
|
* [gotchas](#gotchas) - behavior that might be unexpected
|
90
80
|
* [cors](#cors) - cross-site request config
|
81
|
+
* [https](#https) - both HTTP and HTTPS are accepted
|
91
82
|
* [recovering from crashes](#recovering-from-crashes)
|
92
83
|
* [client crashes](#client-crashes)
|
93
84
|
* [frefox wsod](#frefox-wsod) - firefox 87 can crash during uploads
|
@@ -139,7 +130,7 @@ some recommended options:
|
|
139
130
|
|
140
131
|
you may also want these, especially on servers:
|
141
132
|
|
142
|
-
* [contrib/systemd/copyparty.service](contrib/systemd/copyparty.service) to run copyparty as a systemd service
|
133
|
+
* [contrib/systemd/copyparty.service](contrib/systemd/copyparty.service) to run copyparty as a systemd service (see guide inside)
|
143
134
|
* [contrib/systemd/prisonparty.service](contrib/systemd/prisonparty.service) to run it in a chroot (for extra security)
|
144
135
|
* [contrib/rc/copyparty](contrib/rc/copyparty) to run copyparty on FreeBSD
|
145
136
|
* [contrib/nginx/copyparty.conf](contrib/nginx/copyparty.conf) to [reverse-proxy](#reverse-proxy) behind nginx (for better https)
|
@@ -177,7 +168,7 @@ firewall-cmd --reload
|
|
177
168
|
* ☑ write-only folders
|
178
169
|
* ☑ [unpost](#unpost): undo/delete accidental uploads
|
179
170
|
* ☑ [self-destruct](#self-destruct) (specified server-side or client-side)
|
180
|
-
* ☑ symlink/discard
|
171
|
+
* ☑ symlink/discard duplicates (content-matching)
|
181
172
|
* download
|
182
173
|
* ☑ single files in browser
|
183
174
|
* ☑ [folders as zip / tar files](#zip-downloads)
|
@@ -199,7 +190,7 @@ firewall-cmd --reload
|
|
199
190
|
* ☑ search by name/path/date/size
|
200
191
|
* ☑ [search by ID3-tags etc.](#searching)
|
201
192
|
* client support
|
202
|
-
* ☑ [
|
193
|
+
* ☑ [folder sync](#folder-sync)
|
203
194
|
* ☑ [curl-friendly](https://user-images.githubusercontent.com/241032/215322619-ea5fd606-3654-40ad-94ee-2bc058647bb2.png)
|
204
195
|
* markdown
|
205
196
|
* ☑ [viewer](#markdown-viewer)
|
@@ -278,7 +269,7 @@ server notes:
|
|
278
269
|
|
279
270
|
* iPhones: the volume control doesn't work because [apple doesn't want it to](https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html#//apple_ref/doc/uid/TP40009523-CH5-SW11)
|
280
271
|
* *future workaround:* enable the equalizer, make it all-zero, and set a negative boost to reduce the volume
|
281
|
-
* "future" because `AudioContext`
|
272
|
+
* "future" because `AudioContext` can't maintain a stable playback speed in the current iOS version (15.7), maybe one day...
|
282
273
|
|
283
274
|
* Windows: folders cannot be accessed if the name ends with `.`
|
284
275
|
* python or windows bug
|
@@ -1102,13 +1093,15 @@ see the top of [./copyparty/web/browser.css](./copyparty/web/browser.css) where
|
|
1102
1093
|
|
1103
1094
|
## reverse-proxy
|
1104
1095
|
|
1105
|
-
running copyparty next to other websites hosted on an existing webserver such as nginx or apache
|
1096
|
+
running copyparty next to other websites hosted on an existing webserver such as nginx, caddy, or apache
|
1106
1097
|
|
1107
1098
|
you can either:
|
1108
1099
|
* give copyparty its own domain or subdomain (recommended)
|
1109
1100
|
* or do location-based proxying, using `--rp-loc=/stuff` to tell copyparty where it is mounted -- has a slight performance cost and higher chance of bugs
|
1110
1101
|
* if copyparty says `incorrect --rp-loc or webserver config; expected vpath starting with [...]` it's likely because the webserver is stripping away the proxy location from the request URLs -- see the `ProxyPass` in the apache example below
|
1111
1102
|
|
1103
|
+
some reverse proxies (such as [Caddy](https://caddyserver.com/)) can automatically obtain a valid https/tls certificate for you, and some support HTTP/2 and QUIC which could be a nice speed boost
|
1104
|
+
|
1112
1105
|
example webserver configs:
|
1113
1106
|
|
1114
1107
|
* [nginx config](contrib/nginx/copyparty.conf) -- entire domain/subdomain
|
@@ -1186,7 +1179,7 @@ interact with copyparty using non-browser clients
|
|
1186
1179
|
* `(printf 'PUT / HTTP/1.1\r\n\r\n'; cat movie.mkv) >/dev/tcp/127.0.0.1/3923`
|
1187
1180
|
|
1188
1181
|
* python: [up2k.py](https://github.com/9001/copyparty/blob/hovudstraum/bin/up2k.py) is a command-line up2k client [(webm)](https://ocv.me/stuff/u2cli.webm)
|
1189
|
-
* file uploads, file-search, folder sync, autoresume of aborted/broken uploads
|
1182
|
+
* file uploads, file-search, [folder sync](#folder-sync), autoresume of aborted/broken uploads
|
1190
1183
|
* can be downloaded from copyparty: controlpanel -> connect -> [up2k.py](http://127.0.0.1:3923/.cpr/a/up2k.py)
|
1191
1184
|
* see [./bin/README.md#up2kpy](bin/README.md#up2kpy)
|
1192
1185
|
|
@@ -1207,17 +1200,27 @@ you can provide passwords using header `PW: hunter2`, cookie `cppwd=hunter2`, ur
|
|
1207
1200
|
NOTE: curl will not send the original filename if you use `-T` combined with url-params! Also, make sure to always leave a trailing slash in URLs unless you want to override the filename
|
1208
1201
|
|
1209
1202
|
|
1203
|
+
## folder sync
|
1204
|
+
|
1205
|
+
sync folders to/from copyparty
|
1206
|
+
|
1207
|
+
the commandline uploader [up2k.py](https://github.com/9001/copyparty/tree/hovudstraum/bin#up2kpy) with `--dr` is the best way to sync a folder to copyparty; verifies checksums and does files in parallel, and deletes unexpected files on the server after upload has finished which makes file-renames really cheap (it'll rename serverside and skip uploading)
|
1208
|
+
|
1209
|
+
alternatively there is [rclone](./docs/rclone.md) which allows for bidirectional sync and is *way* more flexible (stream files straight from sftp/s3/gcs to copyparty, ...), although there is no integrity check and it won't work with files over 100 MiB if copyparty is behind cloudflare
|
1210
|
+
|
1211
|
+
* starting from rclone v1.63 (currently [in beta](https://beta.rclone.org/?filter=latest)), rclone will also be faster than up2k.py
|
1212
|
+
|
1213
|
+
|
1210
1214
|
## mount as drive
|
1211
1215
|
|
1212
1216
|
a remote copyparty server as a local filesystem; go to the control-panel and click `connect` to see a list of commands to do that
|
1213
1217
|
|
1214
1218
|
alternatively, some alternatives roughly sorted by speed (unreproducible benchmark), best first:
|
1215
1219
|
|
1216
|
-
* [rclone-
|
1220
|
+
* [rclone-webdav](./docs/rclone.md) (25s), read/WRITE ([v1.63-beta](https://beta.rclone.org/?filter=latest))
|
1221
|
+
* [rclone-http](./docs/rclone.md) (26s), read-only
|
1222
|
+
* [partyfuse.py](./bin/#partyfusepy) (35s), read-only
|
1217
1223
|
* [rclone-ftp](./docs/rclone.md) (47s), read/WRITE
|
1218
|
-
* [rclone-webdav](./docs/rclone.md) (51s), read/WRITE
|
1219
|
-
* copyparty-1.5.0's webdav server is faster than rclone-1.60.0 (69s)
|
1220
|
-
* [partyfuse.py](./bin/#partyfusepy) (71s), read-only
|
1221
1224
|
* davfs2 (103s), read/WRITE, *very fast* on small files
|
1222
1225
|
* [win10-webdav](#webdav-server) (138s), read/WRITE
|
1223
1226
|
* [win10-smb2](#smb-server) (387s), read/WRITE
|
@@ -1225,6 +1228,27 @@ alternatively, some alternatives roughly sorted by speed (unreproducible benchma
|
|
1225
1228
|
most clients will fail to mount the root of a copyparty server unless there is a root volume (so you get the admin-panel instead of a browser when accessing it) -- in that case, mount a specific volume instead
|
1226
1229
|
|
1227
1230
|
|
1231
|
+
# android app
|
1232
|
+
|
1233
|
+
upload to copyparty with one tap
|
1234
|
+
|
1235
|
+
<a href="https://f-droid.org/packages/me.ocv.partyup/"><img src="https://ocv.me/fdroid.png" alt="Get it on F-Droid" height="50" /> '' <img src="https://img.shields.io/f-droid/v/me.ocv.partyup.svg" alt="f-droid version info" /></a> '' <a href="https://github.com/9001/party-up"><img src="https://img.shields.io/github/release/9001/party-up.svg?logo=github" alt="github version info" /></a>
|
1236
|
+
|
1237
|
+
the app is **NOT** the full copyparty server! just a basic upload client, nothing fancy yet
|
1238
|
+
|
1239
|
+
if you want to run the copyparty server on your android device, see [install on android](#install-on-android)
|
1240
|
+
|
1241
|
+
|
1242
|
+
# iOS shortcuts
|
1243
|
+
|
1244
|
+
there is no iPhone app, but the following shortcuts are almost as good:
|
1245
|
+
|
1246
|
+
* [upload to copyparty](https://www.icloud.com/shortcuts/41e98dd985cb4d3bb433222bc1e9e770) ([offline](https://github.com/9001/copyparty/raw/hovudstraum/contrib/ios/upload-to-copyparty.shortcut)) ([png](https://user-images.githubusercontent.com/241032/226118053-78623554-b0ed-482e-98e4-6d57ada58ea4.png)) based on the [original](https://www.icloud.com/shortcuts/ab415d5b4de3467b9ce6f151b439a5d7) by [Daedren](https://github.com/Daedren) (thx!)
|
1247
|
+
* can strip exif, upload files, pics, vids, links, clipboard
|
1248
|
+
* can download links and rehost the target file on copyparty (see first comment inside the shortcut)
|
1249
|
+
* pics become lowres if you share from gallery to shortcut, so better to launch the shortcut and pick stuff from there
|
1250
|
+
|
1251
|
+
|
1228
1252
|
# performance
|
1229
1253
|
|
1230
1254
|
defaults are usually fine - expect `8 GiB/s` download, `1 GiB/s` upload
|
@@ -1320,6 +1344,13 @@ by default, except for `GET` and `HEAD` operations, all requests must either:
|
|
1320
1344
|
cors can be configured with `--acao` and `--acam`, or the protections entirely disabled with `--allow-csrf`
|
1321
1345
|
|
1322
1346
|
|
1347
|
+
## https
|
1348
|
+
|
1349
|
+
both HTTP and HTTPS are accepted by default, but letting a [reverse proxy](#reverse-proxy) handle the https/tls/ssl would be better (probably more secure by default)
|
1350
|
+
|
1351
|
+
copyparty doesn't speak HTTP/2 or QUIC, so using a reverse proxy would solve that as well
|
1352
|
+
|
1353
|
+
|
1323
1354
|
# recovering from crashes
|
1324
1355
|
|
1325
1356
|
## client crashes
|
@@ -1387,7 +1418,7 @@ these are standalone programs and will never be imported / evaluated by copypart
|
|
1387
1418
|
|
1388
1419
|
the self-contained "binary" [copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/download/copyparty-sfx.py) will unpack itself and run copyparty, assuming you have python installed of course
|
1389
1420
|
|
1390
|
-
you can reduce the sfx size by repacking it; see [./docs/devnotes.md#sfx-repack](
|
1421
|
+
you can reduce the sfx size by repacking it; see [./docs/devnotes.md#sfx-repack](./docs/devnotes.md#sfx-repack)
|
1391
1422
|
|
1392
1423
|
|
1393
1424
|
## copyparty.exe
|
@@ -1009,8 +1009,9 @@ class Ctl(object):
|
|
1009
1009
|
file, cid = task
|
1010
1010
|
try:
|
1011
1011
|
upload(file, cid, self.ar.a, stats)
|
1012
|
-
except:
|
1013
|
-
|
1012
|
+
except Exception as ex:
|
1013
|
+
t = "upload failed, retrying: {0} #{1} ({2})\n"
|
1014
|
+
eprint(t.format(file.name, cid[:8], ex))
|
1014
1015
|
# handshake will fix it
|
1015
1016
|
|
1016
1017
|
with self.mutex:
|
@@ -1049,6 +1050,8 @@ def main():
|
|
1049
1050
|
print(ver)
|
1050
1051
|
return
|
1051
1052
|
|
1053
|
+
sys.argv = [x for x in sys.argv if x != "--ws"]
|
1054
|
+
|
1052
1055
|
# fmt: off
|
1053
1056
|
ap = app = argparse.ArgumentParser(formatter_class=APF, description="copyparty up2k uploader / filesearch tool, " + ver, epilog="""
|
1054
1057
|
NOTE:
|
@@ -1067,7 +1070,6 @@ source file/folder selection uses rsync syntax, meaning that:
|
|
1067
1070
|
|
1068
1071
|
ap = app.add_argument_group("compatibility")
|
1069
1072
|
ap.add_argument("--cls", action="store_true", help="clear screen before start")
|
1070
|
-
ap.add_argument("--ws", action="store_true", help="copyparty is running on windows; wait before deleting files after uploading")
|
1071
1073
|
|
1072
1074
|
ap = app.add_argument_group("folder sync")
|
1073
1075
|
ap.add_argument("--dl", action="store_true", help="delete local files after uploading")
|
@@ -1131,10 +1133,6 @@ source file/folder selection uses rsync syntax, meaning that:
|
|
1131
1133
|
|
1132
1134
|
if ar.dr and not ar.drd:
|
1133
1135
|
print("\npass 2/2: delete")
|
1134
|
-
if getattr(ctl, "up_br") and ar.ws:
|
1135
|
-
# wait for up2k to mtime if there was uploads
|
1136
|
-
time.sleep(4)
|
1137
|
-
|
1138
1136
|
ar.drd = True
|
1139
1137
|
ar.z = True
|
1140
1138
|
Ctl(ar, ctl.stats)
|
@@ -752,7 +752,7 @@ def add_ftp(ap):
|
|
752
752
|
|
753
753
|
def add_webdav(ap):
|
754
754
|
ap2 = ap.add_argument_group('WebDAV options')
|
755
|
-
ap2.add_argument("--daw", action="store_true", help="enable full write support. \033[1;31mWARNING:\033[0m This has side-effects -- PUT-operations will now \033[1;31mOVERWRITE\033[0m existing files, rather than inventing new filenames to avoid loss of data. You might want to instead set this as a volflag where needed. By not setting this flag, uploaded files can get written to a filename which the client does not expect (which might be okay, depending on client)")
|
755
|
+
ap2.add_argument("--daw", action="store_true", help="enable full write support, even if client may not be webdav. \033[1;31mWARNING:\033[0m This has side-effects -- PUT-operations will now \033[1;31mOVERWRITE\033[0m existing files, rather than inventing new filenames to avoid loss of data. You might want to instead set this as a volflag where needed. By not setting this flag, uploaded files can get written to a filename which the client does not expect (which might be okay, depending on client)")
|
756
756
|
ap2.add_argument("--dav-inf", action="store_true", help="allow depth:infinite requests (recursive file listing); extremely server-heavy but required for spec compliance -- luckily few clients rely on this")
|
757
757
|
ap2.add_argument("--dav-mac", action="store_true", help="disable apple-garbage filter -- allow macos to create junk files (._* and .DS_Store, .Spotlight-*, .fseventsd, .Trashes, .AppleDouble, __MACOS)")
|
758
758
|
|
@@ -861,7 +861,17 @@ class HttpCli(object):
|
|
861
861
|
vn, rem = self.asrv.vfs.get(self.vpath, self.uname, True, False, err=401)
|
862
862
|
depth = self.headers.get("depth", "infinity").lower()
|
863
863
|
|
864
|
-
|
864
|
+
try:
|
865
|
+
topdir = {"vp": "", "st": bos.stat(vn.canonical(rem))}
|
866
|
+
except OSError as ex:
|
867
|
+
if ex.errno != errno.ENOENT:
|
868
|
+
raise
|
869
|
+
raise Pebkac(404)
|
870
|
+
|
871
|
+
if not stat.S_ISDIR(topdir["st"].st_mode):
|
872
|
+
fgen = []
|
873
|
+
|
874
|
+
elif depth == "infinity":
|
865
875
|
if not self.args.dav_inf:
|
866
876
|
self.log("client wants --dav-inf", 3)
|
867
877
|
zb = b'<?xml version="1.0" encoding="utf-8"?>\n<D:error xmlns:D="DAV:"><D:propfind-finite-depth/></D:error>'
|
@@ -900,13 +910,6 @@ class HttpCli(object):
|
|
900
910
|
t2 = " or 'infinity'" if self.args.dav_inf else ""
|
901
911
|
raise Pebkac(412, t.format(depth, t2))
|
902
912
|
|
903
|
-
try:
|
904
|
-
topdir = {"vp": "", "st": os.stat(vn.canonical(rem))}
|
905
|
-
except OSError as ex:
|
906
|
-
if ex.errno != errno.ENOENT:
|
907
|
-
raise
|
908
|
-
raise Pebkac(404)
|
909
|
-
|
910
913
|
fgen = itertools.chain([topdir], fgen) # type: ignore
|
911
914
|
vtop = vjoin(self.args.R, vjoin(vn.vpath, rem))
|
912
915
|
|
@@ -1108,7 +1111,14 @@ class HttpCli(object):
|
|
1108
1111
|
if self.do_log:
|
1109
1112
|
self.log("MKCOL " + self.req)
|
1110
1113
|
|
1111
|
-
|
1114
|
+
try:
|
1115
|
+
return self._mkdir(self.vpath, True)
|
1116
|
+
except Pebkac as ex:
|
1117
|
+
if ex.code >= 500:
|
1118
|
+
raise
|
1119
|
+
|
1120
|
+
self.reply(b"", ex.code)
|
1121
|
+
return True
|
1112
1122
|
|
1113
1123
|
def handle_move(self) :
|
1114
1124
|
dst = self.headers["destination"]
|
@@ -1422,9 +1432,9 @@ class HttpCli(object):
|
|
1422
1432
|
self.log(t, 1)
|
1423
1433
|
raise Pebkac(403, t)
|
1424
1434
|
|
1425
|
-
if is_put and not (self.args.no_dav or self.args.nw):
|
1435
|
+
if is_put and not (self.args.no_dav or self.args.nw) and bos.path.exists(path):
|
1426
1436
|
# allow overwrite if...
|
1427
|
-
# * volflag 'daw' is set
|
1437
|
+
# * volflag 'daw' is set, or client is definitely webdav
|
1428
1438
|
# * and account has delete-access
|
1429
1439
|
# or...
|
1430
1440
|
# * file exists, is empty, sufficiently new
|
@@ -1434,9 +1444,11 @@ class HttpCli(object):
|
|
1434
1444
|
if self.args.dotpart:
|
1435
1445
|
tnam = "." + tnam
|
1436
1446
|
|
1437
|
-
if (
|
1447
|
+
if (
|
1448
|
+
self.can_delete
|
1449
|
+
and (vfs.flags.get("daw") or "x-oc-mtime" in self.headers)
|
1450
|
+
) or (
|
1438
1451
|
not bos.path.exists(os.path.join(fdir, tnam))
|
1439
|
-
and bos.path.exists(path)
|
1440
1452
|
and not bos.path.getsize(path)
|
1441
1453
|
and bos.path.getmtime(path) >= time.time() - self.args.blank_wt
|
1442
1454
|
):
|
@@ -1460,6 +1472,16 @@ class HttpCli(object):
|
|
1460
1472
|
if self.args.nw:
|
1461
1473
|
return post_sz, sha_hex, sha_b64, remains, path, ""
|
1462
1474
|
|
1475
|
+
at = mt = time.time() - lifetime
|
1476
|
+
cli_mt = self.headers.get("x-oc-mtime")
|
1477
|
+
if cli_mt:
|
1478
|
+
try:
|
1479
|
+
mt = int(cli_mt)
|
1480
|
+
times = (int(time.time()), mt)
|
1481
|
+
bos.utime(path, times, False)
|
1482
|
+
except:
|
1483
|
+
pass
|
1484
|
+
|
1463
1485
|
if nameless and "magic" in vfs.flags:
|
1464
1486
|
try:
|
1465
1487
|
ext = self.conn.hsrv.magician.ext(path)
|
@@ -1482,7 +1504,6 @@ class HttpCli(object):
|
|
1482
1504
|
fn = fn2
|
1483
1505
|
path = path2
|
1484
1506
|
|
1485
|
-
at = time.time() - lifetime
|
1486
1507
|
if xau and not runhook(
|
1487
1508
|
self.log,
|
1488
1509
|
xau,
|
@@ -1490,7 +1511,7 @@ class HttpCli(object):
|
|
1490
1511
|
self.vpath,
|
1491
1512
|
self.host,
|
1492
1513
|
self.uname,
|
1493
|
-
|
1514
|
+
mt,
|
1494
1515
|
post_sz,
|
1495
1516
|
self.ip,
|
1496
1517
|
at,
|
@@ -1550,6 +1571,11 @@ class HttpCli(object):
|
|
1550
1571
|
t = "{}\n{}\n{}\n{}\n".format(post_sz, sha_b64, sha_hex[:56], url)
|
1551
1572
|
|
1552
1573
|
h = {"Location": url} if is_put and url else {}
|
1574
|
+
|
1575
|
+
if "x-oc-mtime" in self.headers:
|
1576
|
+
h["X-OC-MTime"] = "accepted"
|
1577
|
+
t = "" # some webdav clients expect/prefer this
|
1578
|
+
|
1553
1579
|
self.reply(t.encode("utf-8"), 201, headers=h)
|
1554
1580
|
return True
|
1555
1581
|
|
@@ -1950,7 +1976,7 @@ class HttpCli(object):
|
|
1950
1976
|
sanitized = sanitize_fn(new_dir, "", [])
|
1951
1977
|
return self._mkdir(vjoin(self.vpath, sanitized))
|
1952
1978
|
|
1953
|
-
def _mkdir(self, vpath ) :
|
1979
|
+
def _mkdir(self, vpath , dav = False) :
|
1954
1980
|
nullwrite = self.args.nw
|
1955
1981
|
vfs, rem = self.asrv.vfs.get(vpath, self.uname, False, True)
|
1956
1982
|
self._assert_safe_rem(rem)
|
@@ -1976,7 +2002,12 @@ class HttpCli(object):
|
|
1976
2002
|
raise Pebkac(500, min_ex())
|
1977
2003
|
|
1978
2004
|
self.out_headers["X-New-Dir"] = quotep(vpath.split("/")[-1])
|
1979
|
-
|
2005
|
+
|
2006
|
+
if dav:
|
2007
|
+
self.reply(b"", 201)
|
2008
|
+
else:
|
2009
|
+
self.redirect(vpath, status=201)
|
2010
|
+
|
1980
2011
|
return True
|
1981
2012
|
|
1982
2013
|
def handle_new_md(self) :
|
@@ -558,12 +558,19 @@ class ThumbSrv(object):
|
|
558
558
|
if "ac" not in ret:
|
559
559
|
raise Exception("not audio")
|
560
560
|
|
561
|
+
try:
|
562
|
+
dur = ret[".dur"][1]
|
563
|
+
except:
|
564
|
+
dur = 0
|
565
|
+
|
561
566
|
src_opus = abspath.lower().endswith(".opus") or ret["ac"][1] == "opus"
|
562
567
|
want_caf = tpath.endswith(".caf")
|
563
568
|
tmp_opus = tpath
|
564
569
|
if want_caf:
|
565
570
|
tmp_opus = tpath.rsplit(".", 1)[0] + ".opus"
|
566
571
|
|
572
|
+
caf_src = abspath if src_opus else tmp_opus
|
573
|
+
|
567
574
|
if not want_caf or (not src_opus and not bos.path.isfile(tmp_opus)):
|
568
575
|
# fmt: off
|
569
576
|
cmd = [
|
@@ -581,7 +588,32 @@ class ThumbSrv(object):
|
|
581
588
|
# fmt: on
|
582
589
|
self._run_ff(cmd)
|
583
590
|
|
584
|
-
|
591
|
+
# iOS fails to play some "insufficiently complex" files
|
592
|
+
# (average file shorter than 8 seconds), so of course we
|
593
|
+
# fix that by mixing in some inaudible pink noise :^)
|
594
|
+
# 6.3 sec seems like the cutoff so lets do 7, and
|
595
|
+
# 7 sec of psyqui-musou.opus @ 3:50 is 174 KiB
|
596
|
+
if want_caf and (dur < 20 or bos.path.getsize(caf_src) < 256 * 1024):
|
597
|
+
# fmt: off
|
598
|
+
cmd = [
|
599
|
+
b"ffmpeg",
|
600
|
+
b"-nostdin",
|
601
|
+
b"-v", b"error",
|
602
|
+
b"-hide_banner",
|
603
|
+
b"-i", fsenc(abspath),
|
604
|
+
b"-filter_complex", b"anoisesrc=a=0.001:d=7:c=pink,asplit[l][r]; [l][r]amerge[s]; [0:a:0][s]amix",
|
605
|
+
b"-map_metadata", b"-1",
|
606
|
+
b"-ac", b"2",
|
607
|
+
b"-c:a", b"libopus",
|
608
|
+
b"-b:a", b"128k",
|
609
|
+
b"-f", b"caf",
|
610
|
+
fsenc(tpath)
|
611
|
+
]
|
612
|
+
# fmt: on
|
613
|
+
self._run_ff(cmd)
|
614
|
+
|
615
|
+
elif want_caf:
|
616
|
+
# simple remux should be safe
|
585
617
|
# fmt: off
|
586
618
|
cmd = [
|
587
619
|
b"ffmpeg",
|