copyparty 1.13.0__tar.gz → 1.13.1__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.0 → copyparty-1.13.1}/PKG-INFO +50 -6
- {copyparty-1.13.0 → copyparty-1.13.1}/README.md +49 -5
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/__main__.py +27 -2
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/__version__.py +2 -2
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/authsrv.py +14 -2
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/cfg.py +15 -2
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/fsutil.py +25 -5
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/httpcli.py +263 -19
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/metrics.py +1 -1
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/svchub.py +5 -1
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/tcpsrv.py +6 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/u2idx.py +18 -3
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/up2k.py +13 -1
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/util.py +12 -0
- copyparty-1.13.1/copyparty/web/baguettebox.js.gz +0 -0
- copyparty-1.13.1/copyparty/web/browser.css.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/browser.html +1 -1
- copyparty-1.13.1/copyparty/web/browser.js.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/md.html +1 -1
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/mde.html +1 -1
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/msg.html +1 -1
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/splash.html +2 -1
- copyparty-1.13.1/copyparty/web/splash.js.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/svcs.html +1 -1
- copyparty-1.13.1/copyparty/web/util.js.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty.egg-info/PKG-INFO +50 -6
- copyparty-1.13.0/copyparty/web/baguettebox.js.gz +0 -0
- copyparty-1.13.0/copyparty/web/browser.css.gz +0 -0
- copyparty-1.13.0/copyparty/web/browser.js.gz +0 -0
- copyparty-1.13.0/copyparty/web/splash.js.gz +0 -0
- copyparty-1.13.0/copyparty/web/util.js.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/LICENSE +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/__init__.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/bos/__init__.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/bos/bos.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/bos/path.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/broker_mp.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/broker_mpw.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/broker_thr.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/broker_util.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/cert.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/dxml.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/ftpd.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/httpconn.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/httpsrv.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/ico.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/mdns.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/mtag.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/multicast.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/pwhash.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/res/COPYING.txt +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/res/__init__.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/res/insecure.pem +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/smbd.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/ssdp.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/star.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/stolen/__init__.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/stolen/dnslib/__init__.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/stolen/dnslib/bimap.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/stolen/dnslib/bit.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/stolen/dnslib/buffer.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/stolen/dnslib/dns.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/stolen/dnslib/label.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/stolen/dnslib/lex.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/stolen/dnslib/ranges.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/stolen/ifaddr/__init__.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/stolen/ifaddr/_posix.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/stolen/ifaddr/_shared.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/stolen/ifaddr/_win32.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/stolen/qrcodegen.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/stolen/surrogateescape.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/sutil.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/szip.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/tftpd.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/th_cli.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/th_srv.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/a/__init__.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/a/partyfuse.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/a/u2c.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/a/webdav-cfg.bat +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/browser2.html +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/cf.html +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/dbg-audio.js.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/dd/2.png +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/dd/3.png +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/dd/4.png +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/dd/5.png +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/dd/__init__.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/deps/__init__.py +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/deps/busy.mp3.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/deps/easymde.css.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/deps/easymde.js.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/deps/marked.js.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/deps/mini-fa.css.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/deps/mini-fa.woff +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/deps/prism.css.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/deps/prism.js.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/deps/prismd.css.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/deps/scp.woff2 +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/deps/sha512.ac.js.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/deps/sha512.hw.js.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/md.css.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/md.js.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/md2.css.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/md2.js.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/mde.css.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/mde.js.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/msg.css.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/splash.css.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/svcs.js.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/ui.css.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/up2k.js.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty/web/w.hash.js.gz +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty.egg-info/SOURCES.txt +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty.egg-info/dependency_links.txt +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty.egg-info/entry_points.txt +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty.egg-info/requires.txt +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/copyparty.egg-info/top_level.txt +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/pyproject.toml +0 -0
- {copyparty-1.13.0 → copyparty-1.13.1}/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.1
|
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
|
@@ -101,6 +101,7 @@ turn almost any device into a file server with resumable uploads/downloads using
|
|
101
101
|
* [audio equalizer](#audio-equalizer) - and [dynamic range compressor](https://en.wikipedia.org/wiki/Dynamic_range_compression)
|
102
102
|
* [fix unreliable playback on android](#fix-unreliable-playback-on-android) - due to phone / app settings
|
103
103
|
* [markdown viewer](#markdown-viewer) - and there are *two* editors
|
104
|
+
* [markdown vars](#markdown-vars) - dynamic docs with serverside variable expansion
|
104
105
|
* [other tricks](#other-tricks)
|
105
106
|
* [searching](#searching) - search by size, date, path/name, mp3-tags, ...
|
106
107
|
* [server config](#server-config) - using arguments or config files, or a mix of both
|
@@ -114,6 +115,7 @@ turn almost any device into a file server with resumable uploads/downloads using
|
|
114
115
|
* [tftp server](#tftp-server) - a TFTP server (read/write) can be started using `--tftp 3969`
|
115
116
|
* [smb server](#smb-server) - unsafe, slow, not recommended for wan
|
116
117
|
* [browser ux](#browser-ux) - tweaking the ui
|
118
|
+
* [opengraph](#opengraph) - discord and social-media embeds
|
117
119
|
* [file indexing](#file-indexing) - enables dedup and music search ++
|
118
120
|
* [exclude-patterns](#exclude-patterns) - to save some time
|
119
121
|
* [filesystem guards](#filesystem-guards) - avoid traversing into other filesystems
|
@@ -162,8 +164,9 @@ turn almost any device into a file server with resumable uploads/downloads using
|
|
162
164
|
* [dependencies](#dependencies) - mandatory deps
|
163
165
|
* [optional dependencies](#optional-dependencies) - install these to enable bonus features
|
164
166
|
* [optional gpl stuff](#optional-gpl-stuff)
|
165
|
-
* [sfx](#sfx) - the self-contained "binary"
|
167
|
+
* [sfx](#sfx) - the self-contained "binary" (recommended!)
|
166
168
|
* [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+)
|
169
|
+
* [zipapp](#zipapp) - another emergency alternative, [copyparty.pyz](https://github.com/9001/copyparty/releases/latest/download/copyparty.pyz)
|
167
170
|
* [install on android](#install-on-android)
|
168
171
|
* [reporting bugs](#reporting-bugs) - ideas for context to include, and where to submit them
|
169
172
|
* [devnotes](#devnotes) - for build instructions etc, see [./docs/devnotes.md](./docs/devnotes.md)
|
@@ -177,6 +180,7 @@ just run **[copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/
|
|
177
180
|
* or if you cannot install python, you can use [copyparty.exe](#copypartyexe) instead
|
178
181
|
* or install [on arch](#arch-package) ╱ [on NixOS](#nixos-module) ╱ [through nix](#nix-package)
|
179
182
|
* or if you are on android, [install copyparty in termux](#install-on-android)
|
183
|
+
* or if your computer is messed up and nothing else works, [try the pyz](#zipapp)
|
180
184
|
* or if you prefer to [use docker](./scripts/docker/) 🐋 you can do that too
|
181
185
|
* docker has all deps built-in, so skip this step:
|
182
186
|
|
@@ -288,9 +292,11 @@ also see [comparison to similar software](./docs/versus.md)
|
|
288
292
|
* client support
|
289
293
|
* ☑ [folder sync](#folder-sync)
|
290
294
|
* ☑ [curl-friendly](https://user-images.githubusercontent.com/241032/215322619-ea5fd606-3654-40ad-94ee-2bc058647bb2.png)
|
295
|
+
* ☑ [opengraph](#opengraph) (discord embeds)
|
291
296
|
* markdown
|
292
297
|
* ☑ [viewer](#markdown-viewer)
|
293
298
|
* ☑ editor (sure why not)
|
299
|
+
* ☑ [variables](#markdown-vars)
|
294
300
|
|
295
301
|
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) 🤙
|
296
302
|
|
@@ -668,9 +674,15 @@ cool trick: download a folder by appending url-params `?tar&opus` or `?tar&mp3`
|
|
668
674
|
|
669
675
|
## uploading
|
670
676
|
|
671
|
-
drag files/folders into the web-browser to upload
|
677
|
+
drag files/folders into the web-browser to upload
|
672
678
|
|
673
|
-
|
679
|
+
dragdrop is the recommended way, but you may also:
|
680
|
+
|
681
|
+
* select some files (not folders) in your file explorer and press CTRL-V inside the browser window
|
682
|
+
* use the [command-line uploader](https://github.com/9001/copyparty/tree/hovudstraum/bin#u2cpy)
|
683
|
+
* upload using [curl or sharex](#client-examples)
|
684
|
+
|
685
|
+
when uploading files through dragdrop or CTRL-V, this initiates an upload using `up2k`; there are two browser-based uploaders available:
|
674
686
|
* `[🎈] bup`, the basic uploader, supports almost every browser since netscape 4.0
|
675
687
|
* `[🚀] up2k`, the good / fancy one
|
676
688
|
|
@@ -897,6 +909,13 @@ other notes,
|
|
897
909
|
* the document preview has a max-width which is the same as an A4 paper when printed
|
898
910
|
|
899
911
|
|
912
|
+
### markdown vars
|
913
|
+
|
914
|
+
dynamic docs with serverside variable expansion to replace stuff like `{{self.ip}}` with the client's IP, or `{{srv.htime}}` with the current time on the server
|
915
|
+
|
916
|
+
see [./srv/expand/](./srv/expand/) for usage and examples
|
917
|
+
|
918
|
+
|
900
919
|
## other tricks
|
901
920
|
|
902
921
|
* you can link a particular timestamp in an audio file by adding it to the URL, such as `&20` / `&20s` / `&1m20` / `&t=1:20` after the `.../#af-c8960dab`
|
@@ -1121,7 +1140,22 @@ tweaking the ui
|
|
1121
1140
|
* to sort in music order (album, track, artist, title) with filename as fallback, you could `--sort tags/Cirle,tags/.tn,tags/Artist,tags/Title,href`
|
1122
1141
|
* to sort by upload date, first enable showing the upload date in the listing with `-e2d -mte +.up_at` and then `--sort tags/.up_at`
|
1123
1142
|
|
1124
|
-
see [./docs/rice](./docs/rice) for more
|
1143
|
+
see [./docs/rice](./docs/rice) for more, including how to add stuff (css/`<meta>`/...) to the html `<head>` tag
|
1144
|
+
|
1145
|
+
|
1146
|
+
## opengraph
|
1147
|
+
|
1148
|
+
discord and social-media embeds
|
1149
|
+
|
1150
|
+
can be enabled globally with `--og` or per-volume with volflag `og`
|
1151
|
+
|
1152
|
+
note that this disables hotlinking because the opengraph spec demands it; to sneak past this intentional limitation, you can enable opengraph selectively by user-agent, for example `--og-ua '(Discord|Twitter|Slack)bot'` (or volflag `og_ua`)
|
1153
|
+
|
1154
|
+
you can also hotlink files regardless by appending `?raw` to the url
|
1155
|
+
|
1156
|
+
NOTE: because discord (and maybe others) strip query args such as `?raw` in opengraph tags, any links which require a filekey or dirkey will not work
|
1157
|
+
|
1158
|
+
if you want to entirely replace the copyparty response with your own jinja2 template, give the template filepath to `--og-tpl` or volflag `og_tpl` (all members of `HttpCli` are available through the `this` object)
|
1125
1159
|
|
1126
1160
|
|
1127
1161
|
## file indexing
|
@@ -2035,7 +2069,7 @@ these are standalone programs and will never be imported / evaluated by copypart
|
|
2035
2069
|
|
2036
2070
|
# sfx
|
2037
2071
|
|
2038
|
-
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
|
2072
|
+
the self-contained "binary" (recommended!) [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
|
2039
2073
|
|
2040
2074
|
you can reduce the sfx size by repacking it; see [./docs/devnotes.md#sfx-repack](./docs/devnotes.md#sfx-repack)
|
2041
2075
|
|
@@ -2062,6 +2096,16 @@ meanwhile [copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/d
|
|
2062
2096
|
then again, if you are already into downloading shady binaries from the internet, you may also want my [minimal builds](./scripts/pyinstaller#ffmpeg) of [ffmpeg](https://ocv.me/stuff/bin/ffmpeg.exe) and [ffprobe](https://ocv.me/stuff/bin/ffprobe.exe) which enables copyparty to extract multimedia-info, do audio-transcoding, and thumbnails/spectrograms/waveforms, however it's much better to instead grab a [recent official build](https://www.gyan.dev/ffmpeg/builds/ffmpeg-git-full.7z) every once ina while if you can afford the size
|
2063
2097
|
|
2064
2098
|
|
2099
|
+
## zipapp
|
2100
|
+
|
2101
|
+
another emergency alternative, [copyparty.pyz](https://github.com/9001/copyparty/releases/latest/download/copyparty.pyz) has less features, requires python 3.7 or newer, worse compression, and more importantly is unable to benefit from more recent versions of jinja2 and such (which makes it less secure)... lots of drawbacks with this one really -- but it *may* just work if the regular sfx fails to start because the computer is messed up in certain funky ways, so it's worth a shot if all else fails
|
2102
|
+
|
2103
|
+
run it by doubleclicking it, or try typing `python copyparty.pyz` in your terminal/console/commandline/telex if that fails
|
2104
|
+
|
2105
|
+
it is a python [zipapp](https://docs.python.org/3/library/zipapp.html) meaning it doesn't have to unpack its own python code anywhere to run, so if the filesystem is busted it has a better chance of getting somewhere
|
2106
|
+
* but note that it currently still needs to extract the web-resources somewhere (they'll land in the default TEMP-folder of your OS)
|
2107
|
+
|
2108
|
+
|
2065
2109
|
# install on android
|
2066
2110
|
|
2067
2111
|
install [Termux](https://termux.com/) + its companion app `Termux:API` (see [ocv.me/termux](https://ocv.me/termux/)) and then copy-paste this into Termux (long-tap) all at once:
|
@@ -47,6 +47,7 @@ turn almost any device into a file server with resumable uploads/downloads using
|
|
47
47
|
* [audio equalizer](#audio-equalizer) - and [dynamic range compressor](https://en.wikipedia.org/wiki/Dynamic_range_compression)
|
48
48
|
* [fix unreliable playback on android](#fix-unreliable-playback-on-android) - due to phone / app settings
|
49
49
|
* [markdown viewer](#markdown-viewer) - and there are *two* editors
|
50
|
+
* [markdown vars](#markdown-vars) - dynamic docs with serverside variable expansion
|
50
51
|
* [other tricks](#other-tricks)
|
51
52
|
* [searching](#searching) - search by size, date, path/name, mp3-tags, ...
|
52
53
|
* [server config](#server-config) - using arguments or config files, or a mix of both
|
@@ -60,6 +61,7 @@ turn almost any device into a file server with resumable uploads/downloads using
|
|
60
61
|
* [tftp server](#tftp-server) - a TFTP server (read/write) can be started using `--tftp 3969`
|
61
62
|
* [smb server](#smb-server) - unsafe, slow, not recommended for wan
|
62
63
|
* [browser ux](#browser-ux) - tweaking the ui
|
64
|
+
* [opengraph](#opengraph) - discord and social-media embeds
|
63
65
|
* [file indexing](#file-indexing) - enables dedup and music search ++
|
64
66
|
* [exclude-patterns](#exclude-patterns) - to save some time
|
65
67
|
* [filesystem guards](#filesystem-guards) - avoid traversing into other filesystems
|
@@ -108,8 +110,9 @@ turn almost any device into a file server with resumable uploads/downloads using
|
|
108
110
|
* [dependencies](#dependencies) - mandatory deps
|
109
111
|
* [optional dependencies](#optional-dependencies) - install these to enable bonus features
|
110
112
|
* [optional gpl stuff](#optional-gpl-stuff)
|
111
|
-
* [sfx](#sfx) - the self-contained "binary"
|
113
|
+
* [sfx](#sfx) - the self-contained "binary" (recommended!)
|
112
114
|
* [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+)
|
115
|
+
* [zipapp](#zipapp) - another emergency alternative, [copyparty.pyz](https://github.com/9001/copyparty/releases/latest/download/copyparty.pyz)
|
113
116
|
* [install on android](#install-on-android)
|
114
117
|
* [reporting bugs](#reporting-bugs) - ideas for context to include, and where to submit them
|
115
118
|
* [devnotes](#devnotes) - for build instructions etc, see [./docs/devnotes.md](./docs/devnotes.md)
|
@@ -123,6 +126,7 @@ just run **[copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/
|
|
123
126
|
* or if you cannot install python, you can use [copyparty.exe](#copypartyexe) instead
|
124
127
|
* or install [on arch](#arch-package) ╱ [on NixOS](#nixos-module) ╱ [through nix](#nix-package)
|
125
128
|
* or if you are on android, [install copyparty in termux](#install-on-android)
|
129
|
+
* or if your computer is messed up and nothing else works, [try the pyz](#zipapp)
|
126
130
|
* or if you prefer to [use docker](./scripts/docker/) 🐋 you can do that too
|
127
131
|
* docker has all deps built-in, so skip this step:
|
128
132
|
|
@@ -234,9 +238,11 @@ also see [comparison to similar software](./docs/versus.md)
|
|
234
238
|
* client support
|
235
239
|
* ☑ [folder sync](#folder-sync)
|
236
240
|
* ☑ [curl-friendly](https://user-images.githubusercontent.com/241032/215322619-ea5fd606-3654-40ad-94ee-2bc058647bb2.png)
|
241
|
+
* ☑ [opengraph](#opengraph) (discord embeds)
|
237
242
|
* markdown
|
238
243
|
* ☑ [viewer](#markdown-viewer)
|
239
244
|
* ☑ editor (sure why not)
|
245
|
+
* ☑ [variables](#markdown-vars)
|
240
246
|
|
241
247
|
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) 🤙
|
242
248
|
|
@@ -614,9 +620,15 @@ cool trick: download a folder by appending url-params `?tar&opus` or `?tar&mp3`
|
|
614
620
|
|
615
621
|
## uploading
|
616
622
|
|
617
|
-
drag files/folders into the web-browser to upload
|
623
|
+
drag files/folders into the web-browser to upload
|
618
624
|
|
619
|
-
|
625
|
+
dragdrop is the recommended way, but you may also:
|
626
|
+
|
627
|
+
* select some files (not folders) in your file explorer and press CTRL-V inside the browser window
|
628
|
+
* use the [command-line uploader](https://github.com/9001/copyparty/tree/hovudstraum/bin#u2cpy)
|
629
|
+
* upload using [curl or sharex](#client-examples)
|
630
|
+
|
631
|
+
when uploading files through dragdrop or CTRL-V, this initiates an upload using `up2k`; there are two browser-based uploaders available:
|
620
632
|
* `[🎈] bup`, the basic uploader, supports almost every browser since netscape 4.0
|
621
633
|
* `[🚀] up2k`, the good / fancy one
|
622
634
|
|
@@ -843,6 +855,13 @@ other notes,
|
|
843
855
|
* the document preview has a max-width which is the same as an A4 paper when printed
|
844
856
|
|
845
857
|
|
858
|
+
### markdown vars
|
859
|
+
|
860
|
+
dynamic docs with serverside variable expansion to replace stuff like `{{self.ip}}` with the client's IP, or `{{srv.htime}}` with the current time on the server
|
861
|
+
|
862
|
+
see [./srv/expand/](./srv/expand/) for usage and examples
|
863
|
+
|
864
|
+
|
846
865
|
## other tricks
|
847
866
|
|
848
867
|
* you can link a particular timestamp in an audio file by adding it to the URL, such as `&20` / `&20s` / `&1m20` / `&t=1:20` after the `.../#af-c8960dab`
|
@@ -1067,7 +1086,22 @@ tweaking the ui
|
|
1067
1086
|
* to sort in music order (album, track, artist, title) with filename as fallback, you could `--sort tags/Cirle,tags/.tn,tags/Artist,tags/Title,href`
|
1068
1087
|
* to sort by upload date, first enable showing the upload date in the listing with `-e2d -mte +.up_at` and then `--sort tags/.up_at`
|
1069
1088
|
|
1070
|
-
see [./docs/rice](./docs/rice) for more
|
1089
|
+
see [./docs/rice](./docs/rice) for more, including how to add stuff (css/`<meta>`/...) to the html `<head>` tag
|
1090
|
+
|
1091
|
+
|
1092
|
+
## opengraph
|
1093
|
+
|
1094
|
+
discord and social-media embeds
|
1095
|
+
|
1096
|
+
can be enabled globally with `--og` or per-volume with volflag `og`
|
1097
|
+
|
1098
|
+
note that this disables hotlinking because the opengraph spec demands it; to sneak past this intentional limitation, you can enable opengraph selectively by user-agent, for example `--og-ua '(Discord|Twitter|Slack)bot'` (or volflag `og_ua`)
|
1099
|
+
|
1100
|
+
you can also hotlink files regardless by appending `?raw` to the url
|
1101
|
+
|
1102
|
+
NOTE: because discord (and maybe others) strip query args such as `?raw` in opengraph tags, any links which require a filekey or dirkey will not work
|
1103
|
+
|
1104
|
+
if you want to entirely replace the copyparty response with your own jinja2 template, give the template filepath to `--og-tpl` or volflag `og_tpl` (all members of `HttpCli` are available through the `this` object)
|
1071
1105
|
|
1072
1106
|
|
1073
1107
|
## file indexing
|
@@ -1981,7 +2015,7 @@ these are standalone programs and will never be imported / evaluated by copypart
|
|
1981
2015
|
|
1982
2016
|
# sfx
|
1983
2017
|
|
1984
|
-
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
|
2018
|
+
the self-contained "binary" (recommended!) [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
|
1985
2019
|
|
1986
2020
|
you can reduce the sfx size by repacking it; see [./docs/devnotes.md#sfx-repack](./docs/devnotes.md#sfx-repack)
|
1987
2021
|
|
@@ -2008,6 +2042,16 @@ meanwhile [copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/d
|
|
2008
2042
|
then again, if you are already into downloading shady binaries from the internet, you may also want my [minimal builds](./scripts/pyinstaller#ffmpeg) of [ffmpeg](https://ocv.me/stuff/bin/ffmpeg.exe) and [ffprobe](https://ocv.me/stuff/bin/ffprobe.exe) which enables copyparty to extract multimedia-info, do audio-transcoding, and thumbnails/spectrograms/waveforms, however it's much better to instead grab a [recent official build](https://www.gyan.dev/ffmpeg/builds/ffmpeg-git-full.7z) every once ina while if you can afford the size
|
2009
2043
|
|
2010
2044
|
|
2045
|
+
## zipapp
|
2046
|
+
|
2047
|
+
another emergency alternative, [copyparty.pyz](https://github.com/9001/copyparty/releases/latest/download/copyparty.pyz) has less features, requires python 3.7 or newer, worse compression, and more importantly is unable to benefit from more recent versions of jinja2 and such (which makes it less secure)... lots of drawbacks with this one really -- but it *may* just work if the regular sfx fails to start because the computer is messed up in certain funky ways, so it's worth a shot if all else fails
|
2048
|
+
|
2049
|
+
run it by doubleclicking it, or try typing `python copyparty.pyz` in your terminal/console/commandline/telex if that fails
|
2050
|
+
|
2051
|
+
it is a python [zipapp](https://docs.python.org/3/library/zipapp.html) meaning it doesn't have to unpack its own python code anywhere to run, so if the filesystem is busted it has a better chance of getting somewhere
|
2052
|
+
* but note that it currently still needs to extract the web-resources somewhere (they'll land in the default TEMP-folder of your OS)
|
2053
|
+
|
2054
|
+
|
2011
2055
|
# install on android
|
2012
2056
|
|
2013
2057
|
install [Termux](https://termux.com/) + its companion app `Termux:API` (see [ocv.me/termux](https://ocv.me/termux/)) and then copy-paste this into Termux (long-tap) all at once:
|
@@ -854,6 +854,7 @@ def add_fs(ap):
|
|
854
854
|
ap2.add_argument("--rm-retry", metavar="T/R", type=u, default=rm_re_def, help="if a file cannot be deleted because it is busy, continue trying for \033[33mT\033[0m seconds, retry every \033[33mR\033[0m seconds; disable with 0/0 (volflag=rm_retry)")
|
855
855
|
ap2.add_argument("--mv-retry", metavar="T/R", type=u, default=rm_re_def, help="if a file cannot be renamed because it is busy, continue trying for \033[33mT\033[0m seconds, retry every \033[33mR\033[0m seconds; disable with 0/0 (volflag=mv_retry)")
|
856
856
|
ap2.add_argument("--iobuf", metavar="BYTES", type=int, default=256*1024, help="file I/O buffer-size; if your volumes are on a network drive, try increasing to \033[32m524288\033[0m or even \033[32m4194304\033[0m (and let me know if that improves your performance)")
|
857
|
+
ap2.add_argument("--mtab-age", metavar="SEC", type=int, default=60, help="rebuild mountpoint cache every \033[33mSEC\033[0m to keep track of sparse-files support; keep low on servers with removable media")
|
857
858
|
|
858
859
|
|
859
860
|
def add_upload(ap):
|
@@ -1250,19 +1251,38 @@ def add_txt(ap):
|
|
1250
1251
|
ap2.add_argument("--exp-lg", metavar="V,V,V", type=u, default=DEF_EXP, help="comma/space-separated list of placeholders to expand in prologue/epilogue files (volflag=exp_lg)")
|
1251
1252
|
|
1252
1253
|
|
1254
|
+
def add_og(ap):
|
1255
|
+
ap2 = ap.add_argument_group('og / open graph / discord-embed options')
|
1256
|
+
ap2.add_argument("--og", action="store_true", help="disable hotlinking and return an html document instead; this is required by open-graph, but can also be useful on its own (volflag=og)")
|
1257
|
+
ap2.add_argument("--og-ua", metavar="RE", type=u, default="", help="only disable hotlinking / engage OG behavior if the useragent matches regex \033[33mRE\033[0m (volflag=og_ua)")
|
1258
|
+
ap2.add_argument("--og-tpl", metavar="PATH", type=u, default="", help="do not return the regular copyparty html, but instead load the jinja2 template at \033[33mPATH\033[0m (if path contains 'EXT' then EXT will be replaced with the requested file's extension) (volflag=og_tpl)")
|
1259
|
+
ap2.add_argument("--og-no-head", action="store_true", help="do not automatically add OG entries into <head> (useful if you're doing this yourself in a template or such) (volflag=og_no_head)")
|
1260
|
+
ap2.add_argument("--og-th", metavar="FMT", type=u, default="jf3", help="thumbnail format; j=jpeg, jf=jpeg-uncropped, jf3=jpeg-uncropped-large, w=webm, ... (volflag=og_th)")
|
1261
|
+
ap2.add_argument("--og-title", metavar="TXT", type=u, default="", help="fallback title if there is nothing in the \033[33m-e2t\033[0m database (volflag=og_title)")
|
1262
|
+
ap2.add_argument("--og-title-a", metavar="T", type=u, default="🎵 {{ artist }} - {{ title }}", help="audio title format; takes any metadata key (volflag=og_title_a)")
|
1263
|
+
ap2.add_argument("--og-title-v", metavar="T", type=u, default="{{ title }}", help="video title format; takes any metadata key (volflag=og_title_v)")
|
1264
|
+
ap2.add_argument("--og-title-i", metavar="T", type=u, default="{{ title }}", help="image title format; takes any metadata key (volflag=og_title_i)")
|
1265
|
+
ap2.add_argument("--og-s-title", action="store_true", help="force default title; do not read from tags (volflag=og_s_title)")
|
1266
|
+
ap2.add_argument("--og-desc", metavar="TXT", type=u, default="", help="description text; same for all files, disable with [\033[32m-\033[0m] (volflag=og_desc)")
|
1267
|
+
ap2.add_argument("--og-site", metavar="TXT", type=u, default="", help="sitename; defaults to \033[33m--name\033[0m, disable with [\033[32m-\033[0m] (volflag=og_site)")
|
1268
|
+
ap2.add_argument("--tcolor", metavar="RGB", type=u, default="333", help="accent color (3 or 6 hex digits); may also affect safari and/or android-chrome (volflag=tcolor)")
|
1269
|
+
ap2.add_argument("--uqe", action="store_true", help="query-string parceling; translate a request for \033[33m/foo/.uqe/BASE64\033[0m into \033[33m/foo?TEXT\033[0m, or \033[33m/foo/?TEXT\033[0m if the first character in \033[33mTEXT\033[0m is a slash. Automatically enabled for \033[33m--og\033[0m")
|
1270
|
+
|
1271
|
+
|
1253
1272
|
def add_ui(ap, retry):
|
1254
1273
|
ap2 = ap.add_argument_group('ui options')
|
1255
1274
|
ap2.add_argument("--grid", action="store_true", help="show grid/thumbnails by default (volflag=grid)")
|
1256
1275
|
ap2.add_argument("--lang", metavar="LANG", type=u, default="eng", help="language; one of the following: \033[32meng nor\033[0m")
|
1257
1276
|
ap2.add_argument("--theme", metavar="NUM", type=int, default=0, help="default theme to use (0..7)")
|
1258
1277
|
ap2.add_argument("--themes", metavar="NUM", type=int, default=8, help="number of themes installed")
|
1278
|
+
ap2.add_argument("--au-vol", metavar="0-100", type=int, default=50, choices=range(0, 101), help="default audio/video volume percent")
|
1259
1279
|
ap2.add_argument("--sort", metavar="C,C,C", type=u, default="href", help="default sort order, comma-separated column IDs (see header tooltips), prefix with '-' for descending. Examples: \033[32mhref -href ext sz ts tags/Album tags/.tn\033[0m (volflag=sort)")
|
1260
1280
|
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)")
|
1261
1281
|
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")
|
1262
1282
|
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])")
|
1263
1283
|
ap2.add_argument("--js-browser", metavar="L", type=u, help="URL to additional JS to include")
|
1264
1284
|
ap2.add_argument("--css-browser", metavar="L", type=u, help="URL to additional CSS to include")
|
1265
|
-
ap2.add_argument("--html-head", metavar="TXT", type=u, default="", help="text to append to the <head> of all HTML pages")
|
1285
|
+
ap2.add_argument("--html-head", metavar="TXT", type=u, default="", help="text to append to the <head> of all HTML pages; can be @PATH to send the contents of a file at PATH, and/or begin with %% to render as jinja2 template (volflag=html_head)")
|
1266
1286
|
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)")
|
1267
1287
|
ap2.add_argument("--textfiles", metavar="CSV", type=u, default="txt,nfo,diz,cue,readme", help="file extensions to present as plaintext")
|
1268
1288
|
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)")
|
@@ -1350,6 +1370,7 @@ def run_argparse(
|
|
1350
1370
|
add_hooks(ap)
|
1351
1371
|
add_stats(ap)
|
1352
1372
|
add_txt(ap)
|
1373
|
+
add_og(ap)
|
1353
1374
|
add_ui(ap, retry)
|
1354
1375
|
add_admin(ap)
|
1355
1376
|
add_logging(ap)
|
@@ -1384,12 +1405,16 @@ def run_argparse(
|
|
1384
1405
|
return ret
|
1385
1406
|
|
1386
1407
|
|
1387
|
-
def main(argv = None) :
|
1408
|
+
def main(argv = None, rsrc = None) :
|
1388
1409
|
time.strptime("19970815", "%Y%m%d") # python#7980
|
1389
1410
|
if WINDOWS:
|
1390
1411
|
os.system("rem") # enables colors
|
1391
1412
|
|
1392
1413
|
init_E(E)
|
1414
|
+
|
1415
|
+
if rsrc: # pyz
|
1416
|
+
E.mod = rsrc
|
1417
|
+
|
1393
1418
|
if argv is None:
|
1394
1419
|
argv = sys.argv
|
1395
1420
|
|
@@ -1435,6 +1435,7 @@ class AuthSrv(object):
|
|
1435
1435
|
elif "" not in mount:
|
1436
1436
|
# there's volumes but no root; make root inaccessible
|
1437
1437
|
vfs = VFS(self.log_func, "", "", AXS(), {})
|
1438
|
+
vfs.flags["tcolor"] = self.args.tcolor
|
1438
1439
|
vfs.flags["d2d"] = True
|
1439
1440
|
|
1440
1441
|
maxdepth = 0
|
@@ -1720,7 +1721,11 @@ class AuthSrv(object):
|
|
1720
1721
|
if self.args.e2d or "e2ds" in vol.flags:
|
1721
1722
|
vol.flags["e2d"] = True
|
1722
1723
|
|
1723
|
-
for ga, vf in [
|
1724
|
+
for ga, vf in [
|
1725
|
+
["no_hash", "nohash"],
|
1726
|
+
["no_idx", "noidx"],
|
1727
|
+
["og_ua", "og_ua"],
|
1728
|
+
]:
|
1724
1729
|
if vf in vol.flags:
|
1725
1730
|
ptn = re.compile(vol.flags.pop(vf))
|
1726
1731
|
else:
|
@@ -1766,6 +1771,13 @@ class AuthSrv(object):
|
|
1766
1771
|
t = 'volume "/%s" has invalid %stry [%s]'
|
1767
1772
|
raise Exception(t % (vol.vpath, k, vol.flags.get(k + "try")))
|
1768
1773
|
|
1774
|
+
if vol.flags.get("og"):
|
1775
|
+
self.args.uqe = True
|
1776
|
+
|
1777
|
+
zs = str(vol.flags.get("tcolor", "")).lstrip("#")
|
1778
|
+
if len(zs) == 3: # fc5 => ffcc55
|
1779
|
+
vol.flags["tcolor"] = "".join([x * 2 for x in zs])
|
1780
|
+
|
1769
1781
|
for k1, k2 in IMPLICATIONS:
|
1770
1782
|
if k1 in vol.flags:
|
1771
1783
|
vol.flags[k2] = True
|
@@ -2403,7 +2415,7 @@ def expand_config_file(
|
|
2403
2415
|
if not cnames:
|
2404
2416
|
t = "warning: tried to read config-files from folder '%s' but it does not contain any "
|
2405
2417
|
if names:
|
2406
|
-
t += ".conf files; the following files were ignored: %s"
|
2418
|
+
t += ".conf files; the following files/subfolders were ignored: %s"
|
2407
2419
|
t = t % (fp, ", ".join(names[:8]))
|
2408
2420
|
else:
|
2409
2421
|
t += "files at all"
|
@@ -39,6 +39,9 @@ def vf_bmap() :
|
|
39
39
|
"magic",
|
40
40
|
"no_sb_md",
|
41
41
|
"no_sb_lg",
|
42
|
+
"og",
|
43
|
+
"og_no_head",
|
44
|
+
"og_s_title",
|
42
45
|
"rand",
|
43
46
|
"xdev",
|
44
47
|
"xlink",
|
@@ -61,12 +64,23 @@ def vf_vmap() :
|
|
61
64
|
}
|
62
65
|
for k in (
|
63
66
|
"dbd",
|
67
|
+
"html_head",
|
64
68
|
"lg_sbf",
|
65
69
|
"md_sbf",
|
66
70
|
"nrand",
|
71
|
+
"og_desc",
|
72
|
+
"og_site",
|
73
|
+
"og_th",
|
74
|
+
"og_title",
|
75
|
+
"og_title_a",
|
76
|
+
"og_title_v",
|
77
|
+
"og_title_i",
|
78
|
+
"og_tpl",
|
79
|
+
"og_ua",
|
67
80
|
"mv_retry",
|
68
81
|
"rm_retry",
|
69
82
|
"sort",
|
83
|
+
"tcolor",
|
70
84
|
"unlist",
|
71
85
|
"u2abort",
|
72
86
|
"u2ts",
|
@@ -81,7 +95,6 @@ def vf_cmap() :
|
|
81
95
|
for k in (
|
82
96
|
"exp_lg",
|
83
97
|
"exp_md",
|
84
|
-
"html_head",
|
85
98
|
"mte",
|
86
99
|
"mth",
|
87
100
|
"mtp",
|
@@ -201,7 +214,7 @@ flagcats = {
|
|
201
214
|
"grid": "show grid/thumbnails by default",
|
202
215
|
"sort": "default sort order",
|
203
216
|
"unlist": "dont list files matching REGEX",
|
204
|
-
"html_head=TXT": "includes TXT in the <head
|
217
|
+
"html_head=TXT": "includes TXT in the <head>, or @PATH for file at PATH",
|
205
218
|
"robots": "allows indexing by search engines (default)",
|
206
219
|
"norobots": "kindly asks search engines to leave",
|
207
220
|
"no_sb_md": "disable js sandbox for markdown files",
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
from __future__ import print_function, unicode_literals
|
3
3
|
|
4
|
+
import argparse
|
4
5
|
import os
|
5
6
|
import re
|
6
7
|
import time
|
@@ -11,20 +12,26 @@ from .bos import bos
|
|
11
12
|
from .util import chkcmd, min_ex
|
12
13
|
|
13
14
|
class Fstab(object):
|
14
|
-
def __init__(self, log ):
|
15
|
+
def __init__(self, log , args ):
|
15
16
|
self.log_func = log
|
16
17
|
|
18
|
+
self.warned = False
|
17
19
|
self.trusted = False
|
18
20
|
self.tab = None
|
21
|
+
self.oldtab = None
|
22
|
+
self.srctab = "a"
|
19
23
|
self.cache = {}
|
20
24
|
self.age = 0.0
|
25
|
+
self.maxage = args.mtab_age
|
21
26
|
|
22
27
|
def log(self, msg , c = 0) :
|
23
28
|
self.log_func("fstab", msg, c)
|
24
29
|
|
25
30
|
def get(self, path ) :
|
26
|
-
|
27
|
-
|
31
|
+
now = time.time()
|
32
|
+
if now - self.age > self.maxage or len(self.cache) > 9000:
|
33
|
+
self.age = now
|
34
|
+
self.oldtab = self.tab or self.oldtab
|
28
35
|
self.tab = None
|
29
36
|
self.cache = {}
|
30
37
|
|
@@ -69,7 +76,7 @@ class Fstab(object):
|
|
69
76
|
self.trusted = False
|
70
77
|
|
71
78
|
def build_tab(self) :
|
72
|
-
self.log("
|
79
|
+
self.log("inspecting mtab for changes")
|
73
80
|
|
74
81
|
sptn = r"^.*? on (.*) type ([^ ]+) \(.*"
|
75
82
|
if MACOS:
|
@@ -78,6 +85,7 @@ class Fstab(object):
|
|
78
85
|
ptn = re.compile(sptn)
|
79
86
|
so, _ = chkcmd(["mount"])
|
80
87
|
tab1 = []
|
88
|
+
atab = []
|
81
89
|
for ln in so.split("\n"):
|
82
90
|
m = ptn.match(ln)
|
83
91
|
if not m:
|
@@ -85,6 +93,15 @@ class Fstab(object):
|
|
85
93
|
|
86
94
|
zs1, zs2 = m.groups()
|
87
95
|
tab1.append((str(zs1), str(zs2)))
|
96
|
+
atab.append(ln)
|
97
|
+
|
98
|
+
# keep empirically-correct values if mounttab unchanged
|
99
|
+
srctab = "\n".join(sorted(atab))
|
100
|
+
if srctab == self.srctab:
|
101
|
+
self.tab = self.oldtab
|
102
|
+
return
|
103
|
+
|
104
|
+
self.log("mtab has changed; reevaluating support for sparse files")
|
88
105
|
|
89
106
|
tab1.sort(key=lambda x: (len(x[0]), x[0]))
|
90
107
|
path1, fs1 = tab1[0]
|
@@ -93,6 +110,7 @@ class Fstab(object):
|
|
93
110
|
tab.add(fs, path.lstrip("/"))
|
94
111
|
|
95
112
|
self.tab = tab
|
113
|
+
self.srctab = srctab
|
96
114
|
|
97
115
|
def relabel(self, path , nval ) :
|
98
116
|
assert self.tab
|
@@ -127,7 +145,9 @@ class Fstab(object):
|
|
127
145
|
self.trusted = True
|
128
146
|
except:
|
129
147
|
# prisonparty or other restrictive environment
|
130
|
-
|
148
|
+
if not self.warned:
|
149
|
+
self.warned = True
|
150
|
+
self.log("failed to build tab:\n{}".format(min_ex()), 3)
|
131
151
|
self.build_fallback()
|
132
152
|
|
133
153
|
assert self.tab
|