copyparty 1.6.8__tar.gz → 1.6.10__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.8/copyparty.egg-info → copyparty-1.6.10}/PKG-INFO +63 -23
- {copyparty-1.6.8 → copyparty-1.6.10}/README.md +62 -22
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/__main__.py +2 -1
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/__version__.py +2 -2
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/ftpd.py +1 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/httpcli.py +55 -23
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/th_srv.py +33 -1
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/u2idx.py +8 -7
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/up2k.py +5 -2
- copyparty-1.6.10/copyparty/web/browser.css.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/browser.html +1 -0
- copyparty-1.6.10/copyparty/web/browser.js.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/svcs.html +3 -3
- copyparty-1.6.10/copyparty/web/util.js.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10/copyparty.egg-info}/PKG-INFO +63 -23
- copyparty-1.6.8/copyparty/web/browser.css.gz +0 -0
- copyparty-1.6.8/copyparty/web/browser.js.gz +0 -0
- copyparty-1.6.8/copyparty/web/util.js.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/LICENSE +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/MANIFEST.in +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/bin/partyfuse.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/bin/up2k.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/__init__.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/authsrv.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/bos/__init__.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/bos/bos.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/bos/path.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/broker_mp.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/broker_mpw.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/broker_thr.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/broker_util.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/cfg.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/dxml.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/fsutil.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/httpconn.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/httpsrv.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/ico.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/mdns.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/mtag.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/multicast.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/res/COPYING.txt +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/res/insecure.pem +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/smbd.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/ssdp.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/star.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/stolen/__init__.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/stolen/dnslib/__init__.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/stolen/dnslib/bimap.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/stolen/dnslib/bit.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/stolen/dnslib/buffer.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/stolen/dnslib/dns.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/stolen/dnslib/label.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/stolen/dnslib/lex.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/stolen/dnslib/ranges.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/stolen/ifaddr/__init__.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/stolen/ifaddr/_posix.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/stolen/ifaddr/_shared.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/stolen/ifaddr/_win32.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/stolen/qrcodegen.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/stolen/surrogateescape.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/sutil.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/svchub.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/szip.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/tcpsrv.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/th_cli.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/util.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/a/__init__.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/a/partyfuse.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/a/up2k.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/a/webdav-cfg.bat +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/baguettebox.js.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/browser2.html +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/cf.html +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/copyparty.gif +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/dbg-audio.js.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/dd/2.png +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/dd/3.png +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/dd/4.png +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/dd/5.png +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/dd/__init__.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/deps/__init__.py +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/deps/easymde.css.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/deps/easymde.js.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/deps/marked.js.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/deps/mini-fa.css.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/deps/mini-fa.woff +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/deps/prism.css.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/deps/prism.js.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/deps/prismd.css.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/deps/scp.woff2 +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/deps/sha512.ac.js.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/deps/sha512.hw.js.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/md.css.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/md.html +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/md.js.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/md2.css.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/md2.js.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/mde.css.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/mde.html +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/mde.js.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/msg.css.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/msg.html +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/splash.css.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/splash.html +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/splash.js.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/svcs.js.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/ui.css.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/up2k.js.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty/web/w.hash.js.gz +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty.egg-info/SOURCES.txt +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty.egg-info/dependency_links.txt +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty.egg-info/entry_points.txt +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty.egg-info/requires.txt +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/copyparty.egg-info/top_level.txt +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/setup.cfg +0 -0
- {copyparty-1.6.8 → copyparty-1.6.10}/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.10
|
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
|
-
try 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 @@ try the **[read-only demo server](https://a.ocv.me/pub/demo/)** 👀 running fro
|
|
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
|
@@ -148,6 +139,7 @@ just run **[copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/
|
|
148
139
|
|
149
140
|
* or install through pypi (python3 only): `python3 -m pip install --user -U copyparty`
|
150
141
|
* or if you cannot install python, you can use [copyparty.exe](#copypartyexe) instead
|
142
|
+
* or if you are on android, [install copyparty in termux](#install-on-android)
|
151
143
|
* or if you prefer to [use docker](./scripts/docker/) 🐋 you can do that too
|
152
144
|
* docker has all deps built-in, so skip this step:
|
153
145
|
|
@@ -205,11 +197,15 @@ firewall-cmd --reload
|
|
205
197
|
* ☑ [smb/cifs server](#smb-server)
|
206
198
|
* ☑ [qr-code](#qr-code) for quick access
|
207
199
|
* ☑ [upnp / zeroconf / mdns / ssdp](#zeroconf)
|
200
|
+
* ☑ [event hooks](#event-hooks) / script runner
|
201
|
+
* ☑ [reverse-proxy support](https://github.com/9001/copyparty#reverse-proxy)
|
208
202
|
* upload
|
209
203
|
* ☑ basic: plain multipart, ie6 support
|
210
204
|
* ☑ [up2k](#uploading): js, resumable, multithreaded
|
211
205
|
* unaffected by cloudflare's max-upload-size (100 MiB)
|
212
206
|
* ☑ stash: simple PUT filedropper
|
207
|
+
* ☑ filename randomizer
|
208
|
+
* ☑ write-only folders
|
213
209
|
* ☑ [unpost](#unpost): undo/delete accidental uploads
|
214
210
|
* ☑ [self-destruct](#self-destruct) (specified server-side or client-side)
|
215
211
|
* ☑ symlink/discard existing files (content-matching)
|
@@ -233,10 +229,15 @@ firewall-cmd --reload
|
|
233
229
|
* ☑ [locate files by contents](#file-search)
|
234
230
|
* ☑ search by name/path/date/size
|
235
231
|
* ☑ [search by ID3-tags etc.](#searching)
|
232
|
+
* client support
|
233
|
+
* ☑ [folder sync](#folder-sync)
|
234
|
+
* ☑ [curl-friendly](https://user-images.githubusercontent.com/241032/215322619-ea5fd606-3654-40ad-94ee-2bc058647bb2.png)
|
236
235
|
* markdown
|
237
236
|
* ☑ [viewer](#markdown-viewer)
|
238
237
|
* ☑ editor (sure why not)
|
239
238
|
|
239
|
+
PS: something missing? post any crazy ideas you've got as a [feature request](https://github.com/9001/copyparty/issues/new?assignees=9001&labels=enhancement&template=feature_request.md) or [discussion](https://github.com/9001/copyparty/discussions/new?category=ideas) 🤙
|
240
|
+
|
240
241
|
|
241
242
|
## testimonials
|
242
243
|
|
@@ -308,7 +309,7 @@ server notes:
|
|
308
309
|
|
309
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)
|
310
311
|
* *future workaround:* enable the equalizer, make it all-zero, and set a negative boost to reduce the volume
|
311
|
-
* "future" because `AudioContext`
|
312
|
+
* "future" because `AudioContext` can't maintain a stable playback speed in the current iOS version (15.7), maybe one day...
|
312
313
|
|
313
314
|
* Windows: folders cannot be accessed if the name ends with `.`
|
314
315
|
* python or windows bug
|
@@ -1132,13 +1133,15 @@ see the top of [./copyparty/web/browser.css](./copyparty/web/browser.css) where
|
|
1132
1133
|
|
1133
1134
|
## reverse-proxy
|
1134
1135
|
|
1135
|
-
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
|
1136
1137
|
|
1137
1138
|
you can either:
|
1138
1139
|
* give copyparty its own domain or subdomain (recommended)
|
1139
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
|
1140
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
|
1141
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
|
+
|
1142
1145
|
example webserver configs:
|
1143
1146
|
|
1144
1147
|
* [nginx config](contrib/nginx/copyparty.conf) -- entire domain/subdomain
|
@@ -1216,7 +1219,7 @@ interact with copyparty using non-browser clients
|
|
1216
1219
|
* `(printf 'PUT / HTTP/1.1\r\n\r\n'; cat movie.mkv) >/dev/tcp/127.0.0.1/3923`
|
1217
1220
|
|
1218
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)
|
1219
|
-
* 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
|
1220
1223
|
* can be downloaded from copyparty: controlpanel -> connect -> [up2k.py](http://127.0.0.1:3923/.cpr/a/up2k.py)
|
1221
1224
|
* see [./bin/README.md#up2kpy](bin/README.md#up2kpy)
|
1222
1225
|
|
@@ -1237,6 +1240,15 @@ you can provide passwords using header `PW: hunter2`, cookie `cppwd=hunter2`, ur
|
|
1237
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
|
1238
1241
|
|
1239
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 for instance), although syncing to copyparty is about 5x slower than up2k.py if you have many small files in particular
|
1250
|
+
|
1251
|
+
|
1240
1252
|
## mount as drive
|
1241
1253
|
|
1242
1254
|
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
|
@@ -1255,6 +1267,27 @@ alternatively, some alternatives roughly sorted by speed (unreproducible benchma
|
|
1255
1267
|
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
|
1256
1268
|
|
1257
1269
|
|
1270
|
+
# android app
|
1271
|
+
|
1272
|
+
upload to copyparty with one tap
|
1273
|
+
|
1274
|
+
<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>
|
1275
|
+
|
1276
|
+
the app is **NOT** the full copyparty server! just a basic upload client, nothing fancy yet
|
1277
|
+
|
1278
|
+
if you want to run the copyparty server on your android device, see [install on android](#install-on-android)
|
1279
|
+
|
1280
|
+
|
1281
|
+
# iOS shortcuts
|
1282
|
+
|
1283
|
+
there is no iPhone app, but the following shortcuts are almost as good:
|
1284
|
+
|
1285
|
+
* [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!)
|
1286
|
+
* can strip exif, upload files, pics, vids, links, clipboard
|
1287
|
+
* can download links and rehost the target file on copyparty (see first comment inside the shortcut)
|
1288
|
+
* pics become lowres if you share from gallery to shortcut, so better to launch the shortcut and pick stuff from there
|
1289
|
+
|
1290
|
+
|
1258
1291
|
# performance
|
1259
1292
|
|
1260
1293
|
defaults are usually fine - expect `8 GiB/s` download, `1 GiB/s` upload
|
@@ -1350,6 +1383,13 @@ by default, except for `GET` and `HEAD` operations, all requests must either:
|
|
1350
1383
|
cors can be configured with `--acao` and `--acam`, or the protections entirely disabled with `--allow-csrf`
|
1351
1384
|
|
1352
1385
|
|
1386
|
+
## https
|
1387
|
+
|
1388
|
+
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)
|
1389
|
+
|
1390
|
+
copyparty doesn't speak HTTP/2 or QUIC, so using a reverse proxy would solve that as well
|
1391
|
+
|
1392
|
+
|
1353
1393
|
# recovering from crashes
|
1354
1394
|
|
1355
1395
|
## client crashes
|
@@ -1417,7 +1457,7 @@ these are standalone programs and will never be imported / evaluated by copypart
|
|
1417
1457
|
|
1418
1458
|
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
|
1419
1459
|
|
1420
|
-
you can reduce the sfx size by repacking it; see [./docs/devnotes.md#sfx-repack](
|
1460
|
+
you can reduce the sfx size by repacking it; see [./docs/devnotes.md#sfx-repack](./docs/devnotes.md#sfx-repack)
|
1421
1461
|
|
1422
1462
|
|
1423
1463
|
## 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
|
-
try 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 @@ try the **[read-only demo server](https://a.ocv.me/pub/demo/)** 👀 running fro
|
|
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
|
@@ -108,6 +99,7 @@ just run **[copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/
|
|
108
99
|
|
109
100
|
* or install through pypi (python3 only): `python3 -m pip install --user -U copyparty`
|
110
101
|
* or if you cannot install python, you can use [copyparty.exe](#copypartyexe) instead
|
102
|
+
* or if you are on android, [install copyparty in termux](#install-on-android)
|
111
103
|
* or if you prefer to [use docker](./scripts/docker/) 🐋 you can do that too
|
112
104
|
* docker has all deps built-in, so skip this step:
|
113
105
|
|
@@ -165,11 +157,15 @@ firewall-cmd --reload
|
|
165
157
|
* ☑ [smb/cifs server](#smb-server)
|
166
158
|
* ☑ [qr-code](#qr-code) for quick access
|
167
159
|
* ☑ [upnp / zeroconf / mdns / ssdp](#zeroconf)
|
160
|
+
* ☑ [event hooks](#event-hooks) / script runner
|
161
|
+
* ☑ [reverse-proxy support](https://github.com/9001/copyparty#reverse-proxy)
|
168
162
|
* upload
|
169
163
|
* ☑ basic: plain multipart, ie6 support
|
170
164
|
* ☑ [up2k](#uploading): js, resumable, multithreaded
|
171
165
|
* unaffected by cloudflare's max-upload-size (100 MiB)
|
172
166
|
* ☑ stash: simple PUT filedropper
|
167
|
+
* ☑ filename randomizer
|
168
|
+
* ☑ write-only folders
|
173
169
|
* ☑ [unpost](#unpost): undo/delete accidental uploads
|
174
170
|
* ☑ [self-destruct](#self-destruct) (specified server-side or client-side)
|
175
171
|
* ☑ symlink/discard existing files (content-matching)
|
@@ -193,10 +189,15 @@ firewall-cmd --reload
|
|
193
189
|
* ☑ [locate files by contents](#file-search)
|
194
190
|
* ☑ search by name/path/date/size
|
195
191
|
* ☑ [search by ID3-tags etc.](#searching)
|
192
|
+
* client support
|
193
|
+
* ☑ [folder sync](#folder-sync)
|
194
|
+
* ☑ [curl-friendly](https://user-images.githubusercontent.com/241032/215322619-ea5fd606-3654-40ad-94ee-2bc058647bb2.png)
|
196
195
|
* markdown
|
197
196
|
* ☑ [viewer](#markdown-viewer)
|
198
197
|
* ☑ editor (sure why not)
|
199
198
|
|
199
|
+
PS: something missing? post any crazy ideas you've got as a [feature request](https://github.com/9001/copyparty/issues/new?assignees=9001&labels=enhancement&template=feature_request.md) or [discussion](https://github.com/9001/copyparty/discussions/new?category=ideas) 🤙
|
200
|
+
|
200
201
|
|
201
202
|
## testimonials
|
202
203
|
|
@@ -268,7 +269,7 @@ server notes:
|
|
268
269
|
|
269
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)
|
270
271
|
* *future workaround:* enable the equalizer, make it all-zero, and set a negative boost to reduce the volume
|
271
|
-
* "future" because `AudioContext`
|
272
|
+
* "future" because `AudioContext` can't maintain a stable playback speed in the current iOS version (15.7), maybe one day...
|
272
273
|
|
273
274
|
* Windows: folders cannot be accessed if the name ends with `.`
|
274
275
|
* python or windows bug
|
@@ -1092,13 +1093,15 @@ see the top of [./copyparty/web/browser.css](./copyparty/web/browser.css) where
|
|
1092
1093
|
|
1093
1094
|
## reverse-proxy
|
1094
1095
|
|
1095
|
-
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
|
1096
1097
|
|
1097
1098
|
you can either:
|
1098
1099
|
* give copyparty its own domain or subdomain (recommended)
|
1099
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
|
1100
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
|
1101
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
|
+
|
1102
1105
|
example webserver configs:
|
1103
1106
|
|
1104
1107
|
* [nginx config](contrib/nginx/copyparty.conf) -- entire domain/subdomain
|
@@ -1176,7 +1179,7 @@ interact with copyparty using non-browser clients
|
|
1176
1179
|
* `(printf 'PUT / HTTP/1.1\r\n\r\n'; cat movie.mkv) >/dev/tcp/127.0.0.1/3923`
|
1177
1180
|
|
1178
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)
|
1179
|
-
* 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
|
1180
1183
|
* can be downloaded from copyparty: controlpanel -> connect -> [up2k.py](http://127.0.0.1:3923/.cpr/a/up2k.py)
|
1181
1184
|
* see [./bin/README.md#up2kpy](bin/README.md#up2kpy)
|
1182
1185
|
|
@@ -1197,6 +1200,15 @@ you can provide passwords using header `PW: hunter2`, cookie `cppwd=hunter2`, ur
|
|
1197
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
|
1198
1201
|
|
1199
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 for instance), although syncing to copyparty is about 5x slower than up2k.py if you have many small files in particular
|
1210
|
+
|
1211
|
+
|
1200
1212
|
## mount as drive
|
1201
1213
|
|
1202
1214
|
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
|
@@ -1215,6 +1227,27 @@ alternatively, some alternatives roughly sorted by speed (unreproducible benchma
|
|
1215
1227
|
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
|
1216
1228
|
|
1217
1229
|
|
1230
|
+
# android app
|
1231
|
+
|
1232
|
+
upload to copyparty with one tap
|
1233
|
+
|
1234
|
+
<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>
|
1235
|
+
|
1236
|
+
the app is **NOT** the full copyparty server! just a basic upload client, nothing fancy yet
|
1237
|
+
|
1238
|
+
if you want to run the copyparty server on your android device, see [install on android](#install-on-android)
|
1239
|
+
|
1240
|
+
|
1241
|
+
# iOS shortcuts
|
1242
|
+
|
1243
|
+
there is no iPhone app, but the following shortcuts are almost as good:
|
1244
|
+
|
1245
|
+
* [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!)
|
1246
|
+
* can strip exif, upload files, pics, vids, links, clipboard
|
1247
|
+
* can download links and rehost the target file on copyparty (see first comment inside the shortcut)
|
1248
|
+
* pics become lowres if you share from gallery to shortcut, so better to launch the shortcut and pick stuff from there
|
1249
|
+
|
1250
|
+
|
1218
1251
|
# performance
|
1219
1252
|
|
1220
1253
|
defaults are usually fine - expect `8 GiB/s` download, `1 GiB/s` upload
|
@@ -1310,6 +1343,13 @@ by default, except for `GET` and `HEAD` operations, all requests must either:
|
|
1310
1343
|
cors can be configured with `--acao` and `--acam`, or the protections entirely disabled with `--allow-csrf`
|
1311
1344
|
|
1312
1345
|
|
1346
|
+
## https
|
1347
|
+
|
1348
|
+
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)
|
1349
|
+
|
1350
|
+
copyparty doesn't speak HTTP/2 or QUIC, so using a reverse proxy would solve that as well
|
1351
|
+
|
1352
|
+
|
1313
1353
|
# recovering from crashes
|
1314
1354
|
|
1315
1355
|
## client crashes
|
@@ -1377,7 +1417,7 @@ these are standalone programs and will never be imported / evaluated by copypart
|
|
1377
1417
|
|
1378
1418
|
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
|
1379
1419
|
|
1380
|
-
you can reduce the sfx size by repacking it; see [./docs/devnotes.md#sfx-repack](
|
1420
|
+
you can reduce the sfx size by repacking it; see [./docs/devnotes.md#sfx-repack](./docs/devnotes.md#sfx-repack)
|
1381
1421
|
|
1382
1422
|
|
1383
1423
|
## copyparty.exe
|
@@ -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
|
|
@@ -940,6 +940,7 @@ def add_ui(ap, retry):
|
|
940
940
|
ap2.add_argument("--js-browser", metavar="L", type=u, help="URL to additional JS to include")
|
941
941
|
ap2.add_argument("--css-browser", metavar="L", type=u, help="URL to additional CSS to include")
|
942
942
|
ap2.add_argument("--html-head", metavar="TXT", type=u, default="", help="text to append to the <head> of all HTML pages")
|
943
|
+
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)")
|
943
944
|
ap2.add_argument("--textfiles", metavar="CSV", type=u, default="txt,nfo,diz,cue,readme", help="file extensions to present as plaintext")
|
944
945
|
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)")
|
945
946
|
ap2.add_argument("--doctitle", metavar="TXT", type=u, default="copyparty", help="title / service-name to show in html documents")
|
@@ -774,8 +774,8 @@ class HttpCli(object):
|
|
774
774
|
if "k304" in self.uparam:
|
775
775
|
return self.set_k304()
|
776
776
|
|
777
|
-
if "
|
778
|
-
return self.
|
777
|
+
if "setck" in self.uparam:
|
778
|
+
return self.setck()
|
779
779
|
|
780
780
|
if "reset" in self.uparam:
|
781
781
|
return self.set_cfg_reset()
|
@@ -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
|
|
@@ -1422,9 +1425,9 @@ class HttpCli(object):
|
|
1422
1425
|
self.log(t, 1)
|
1423
1426
|
raise Pebkac(403, t)
|
1424
1427
|
|
1425
|
-
if is_put and not (self.args.no_dav or self.args.nw):
|
1428
|
+
if is_put and not (self.args.no_dav or self.args.nw) and bos.path.exists(path):
|
1426
1429
|
# allow overwrite if...
|
1427
|
-
# * volflag 'daw' is set
|
1430
|
+
# * volflag 'daw' is set, or client is definitely webdav
|
1428
1431
|
# * and account has delete-access
|
1429
1432
|
# or...
|
1430
1433
|
# * file exists, is empty, sufficiently new
|
@@ -1434,9 +1437,11 @@ class HttpCli(object):
|
|
1434
1437
|
if self.args.dotpart:
|
1435
1438
|
tnam = "." + tnam
|
1436
1439
|
|
1437
|
-
if (
|
1440
|
+
if (
|
1441
|
+
self.can_delete
|
1442
|
+
and (vfs.flags.get("daw") or "x-oc-mtime" in self.headers)
|
1443
|
+
) or (
|
1438
1444
|
not bos.path.exists(os.path.join(fdir, tnam))
|
1439
|
-
and bos.path.exists(path)
|
1440
1445
|
and not bos.path.getsize(path)
|
1441
1446
|
and bos.path.getmtime(path) >= time.time() - self.args.blank_wt
|
1442
1447
|
):
|
@@ -1460,6 +1465,16 @@ class HttpCli(object):
|
|
1460
1465
|
if self.args.nw:
|
1461
1466
|
return post_sz, sha_hex, sha_b64, remains, path, ""
|
1462
1467
|
|
1468
|
+
at = mt = time.time() - lifetime
|
1469
|
+
cli_mt = self.headers.get("x-oc-mtime")
|
1470
|
+
if cli_mt:
|
1471
|
+
try:
|
1472
|
+
mt = int(cli_mt)
|
1473
|
+
times = (int(time.time()), mt)
|
1474
|
+
bos.utime(path, times, False)
|
1475
|
+
except:
|
1476
|
+
pass
|
1477
|
+
|
1463
1478
|
if nameless and "magic" in vfs.flags:
|
1464
1479
|
try:
|
1465
1480
|
ext = self.conn.hsrv.magician.ext(path)
|
@@ -1482,7 +1497,6 @@ class HttpCli(object):
|
|
1482
1497
|
fn = fn2
|
1483
1498
|
path = path2
|
1484
1499
|
|
1485
|
-
at = time.time() - lifetime
|
1486
1500
|
if xau and not runhook(
|
1487
1501
|
self.log,
|
1488
1502
|
xau,
|
@@ -1490,7 +1504,7 @@ class HttpCli(object):
|
|
1490
1504
|
self.vpath,
|
1491
1505
|
self.host,
|
1492
1506
|
self.uname,
|
1493
|
-
|
1507
|
+
mt,
|
1494
1508
|
post_sz,
|
1495
1509
|
self.ip,
|
1496
1510
|
at,
|
@@ -1753,12 +1767,13 @@ class HttpCli(object):
|
|
1753
1767
|
hits = idx.fsearch(vols, body)
|
1754
1768
|
msg = repr(hits)
|
1755
1769
|
taglist = []
|
1770
|
+
trunc = False
|
1756
1771
|
else:
|
1757
1772
|
# search by query params
|
1758
1773
|
q = body["q"]
|
1759
1774
|
n = body.get("n", self.args.srch_hits)
|
1760
1775
|
self.log("qj: {} |{}|".format(q, n))
|
1761
|
-
hits, taglist = idx.search(vols, q, n)
|
1776
|
+
hits, taglist, trunc = idx.search(vols, q, n)
|
1762
1777
|
msg = len(hits)
|
1763
1778
|
|
1764
1779
|
idx.p_end = time.time()
|
@@ -1778,7 +1793,8 @@ class HttpCli(object):
|
|
1778
1793
|
for hit in hits:
|
1779
1794
|
hit["rp"] = self.args.RS + hit["rp"]
|
1780
1795
|
|
1781
|
-
|
1796
|
+
rj = {"hits": hits, "tag_order": order, "trunc": trunc}
|
1797
|
+
r = json.dumps(rj).encode("utf-8")
|
1782
1798
|
self.reply(r, mime="application/json")
|
1783
1799
|
return True
|
1784
1800
|
|
@@ -2892,15 +2908,16 @@ class HttpCli(object):
|
|
2892
2908
|
self.redirect("", "?h#cc")
|
2893
2909
|
return True
|
2894
2910
|
|
2895
|
-
def
|
2896
|
-
v =
|
2897
|
-
|
2911
|
+
def setck(self) :
|
2912
|
+
k, v = self.uparam["setck"].split("=", 1)
|
2913
|
+
t = None if v == "" else 86400 * 299
|
2914
|
+
ck = gencookie(k, v, self.args.R, False, t)
|
2898
2915
|
self.out_headerlist.append(("Set-Cookie", ck))
|
2899
|
-
self.reply(b"
|
2916
|
+
self.reply(b"o7\n")
|
2900
2917
|
return True
|
2901
2918
|
|
2902
2919
|
def set_cfg_reset(self) :
|
2903
|
-
for k in ("k304", "js", "cppwd", "cppws"):
|
2920
|
+
for k in ("k304", "js", "idxh", "cppwd", "cppws"):
|
2904
2921
|
cookie = gencookie(k, "x", self.args.R, False, None)
|
2905
2922
|
self.out_headerlist.append(("Set-Cookie", cookie))
|
2906
2923
|
|
@@ -3429,6 +3446,7 @@ class HttpCli(object):
|
|
3429
3446
|
"dtheme": self.args.theme,
|
3430
3447
|
"themes": self.args.themes,
|
3431
3448
|
"turbolvl": self.args.turbo,
|
3449
|
+
"idxh": int(self.args.ih),
|
3432
3450
|
"u2sort": self.args.u2sort,
|
3433
3451
|
}
|
3434
3452
|
|
@@ -3562,6 +3580,20 @@ class HttpCli(object):
|
|
3562
3580
|
files.append(item)
|
3563
3581
|
item["rd"] = rem
|
3564
3582
|
|
3583
|
+
if (
|
3584
|
+
self.cookies.get("idxh") == "y"
|
3585
|
+
and "ls" not in self.uparam
|
3586
|
+
and "v" not in self.uparam
|
3587
|
+
):
|
3588
|
+
idx_html = set(["index.htm", "index.html"])
|
3589
|
+
for item in files:
|
3590
|
+
if item["name"] in idx_html:
|
3591
|
+
# do full resolve in case of shadowed file
|
3592
|
+
vp = vjoin(self.vpath.split("?")[0], item["name"])
|
3593
|
+
vn, rem = self.asrv.vfs.get(vp, self.uname, True, False)
|
3594
|
+
ap = vn.canonical(rem)
|
3595
|
+
return self.tx_file(ap) # is no-cache
|
3596
|
+
|
3565
3597
|
tagset = set()
|
3566
3598
|
for fe in files:
|
3567
3599
|
fn = fe["name"]
|