copyparty 1.15.6__tar.gz → 1.15.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {copyparty-1.15.6 → copyparty-1.15.8}/PKG-INFO +22 -3
- {copyparty-1.15.6 → copyparty-1.15.8}/README.md +21 -2
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/__main__.py +3 -1
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/__version__.py +2 -2
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/authsrv.py +1 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/ftpd.py +4 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/httpcli.py +81 -10
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/httpconn.py +2 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/httpsrv.py +8 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/svchub.py +6 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/up2k.py +56 -32
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/util.py +39 -6
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/a/u2c.py +128 -42
- copyparty-1.15.8/copyparty/web/baguettebox.js.gz +0 -0
- copyparty-1.15.8/copyparty/web/browser.js.gz +0 -0
- copyparty-1.15.8/copyparty/web/ui.css.gz +0 -0
- copyparty-1.15.8/copyparty/web/up2k.js.gz +0 -0
- copyparty-1.15.8/copyparty/web/util.js.gz +0 -0
- copyparty-1.15.8/copyparty/web/w.hash.js.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty.egg-info/PKG-INFO +22 -3
- copyparty-1.15.6/copyparty/web/baguettebox.js.gz +0 -0
- copyparty-1.15.6/copyparty/web/browser.js.gz +0 -0
- copyparty-1.15.6/copyparty/web/ui.css.gz +0 -0
- copyparty-1.15.6/copyparty/web/up2k.js.gz +0 -0
- copyparty-1.15.6/copyparty/web/util.js.gz +0 -0
- copyparty-1.15.6/copyparty/web/w.hash.js.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/LICENSE +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/__init__.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/bos/__init__.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/bos/bos.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/bos/path.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/broker_mp.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/broker_mpw.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/broker_thr.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/broker_util.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/cert.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/cfg.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/dxml.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/fsutil.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/ico.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/mdns.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/metrics.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/mtag.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/multicast.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/pwhash.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/res/COPYING.txt +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/res/__init__.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/res/insecure.pem +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/smbd.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/ssdp.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/star.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/stolen/__init__.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/stolen/dnslib/__init__.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/stolen/dnslib/bimap.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/stolen/dnslib/bit.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/stolen/dnslib/buffer.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/stolen/dnslib/dns.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/stolen/dnslib/label.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/stolen/dnslib/lex.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/stolen/dnslib/ranges.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/stolen/ifaddr/__init__.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/stolen/ifaddr/_posix.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/stolen/ifaddr/_shared.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/stolen/ifaddr/_win32.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/stolen/qrcodegen.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/stolen/surrogateescape.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/sutil.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/szip.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/tcpsrv.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/tftpd.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/th_cli.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/th_srv.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/u2idx.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/a/__init__.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/a/partyfuse.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/a/webdav-cfg.bat +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/browser.css.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/browser.html +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/browser2.html +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/cf.html +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/dbg-audio.js.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/dd/2.png +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/dd/3.png +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/dd/4.png +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/dd/5.png +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/dd/__init__.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/deps/__init__.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/deps/busy.mp3.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/deps/easymde.css.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/deps/easymde.js.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/deps/fuse.py +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/deps/marked.js.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/deps/mini-fa.css.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/deps/mini-fa.woff +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/deps/prism.css.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/deps/prism.js.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/deps/prismd.css.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/deps/scp.woff2 +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/deps/sha512.ac.js.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/deps/sha512.hw.js.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/md.css.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/md.html +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/md.js.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/md2.css.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/md2.js.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/mde.css.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/mde.html +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/mde.js.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/msg.css.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/msg.html +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/shares.css.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/shares.html +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/shares.js.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/splash.css.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/splash.html +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/splash.js.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/svcs.html +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty/web/svcs.js.gz +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty.egg-info/SOURCES.txt +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty.egg-info/dependency_links.txt +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty.egg-info/entry_points.txt +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty.egg-info/requires.txt +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/copyparty.egg-info/top_level.txt +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/pyproject.toml +0 -0
- {copyparty-1.15.6 → copyparty-1.15.8}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: copyparty
|
3
|
-
Version: 1.15.
|
3
|
+
Version: 1.15.8
|
4
4
|
Summary: Portable file server with accelerated resumable uploads, deduplication, WebDAV, FTP, zeroconf, media indexer, video thumbnails, audio transcoding, and write-only folders
|
5
5
|
Author-email: ed <copyparty@ocv.me>
|
6
6
|
License: MIT
|
@@ -134,6 +134,7 @@ turn almost any device into a file server with resumable uploads/downloads using
|
|
134
134
|
* [event hooks](#event-hooks) - trigger a program on uploads, renames etc ([examples](./bin/hooks/))
|
135
135
|
* [upload events](#upload-events) - the older, more powerful approach ([examples](./bin/mtag/))
|
136
136
|
* [handlers](#handlers) - redefine behavior with plugins ([examples](./bin/handlers/))
|
137
|
+
* [ip auth](#ip-auth) - autologin based on IP range (CIDR)
|
137
138
|
* [identity providers](#identity-providers) - replace copyparty passwords with oauth and such
|
138
139
|
* [user-changeable passwords](#user-changeable-passwords) - if permitted, users can change their own passwords
|
139
140
|
* [using the cloud as storage](#using-the-cloud-as-storage) - connecting to an aws s3 bucket and similar
|
@@ -272,7 +273,7 @@ also see [comparison to similar software](./docs/versus.md)
|
|
272
273
|
* upload
|
273
274
|
* ☑ basic: plain multipart, ie6 support
|
274
275
|
* ☑ [up2k](#uploading): js, resumable, multithreaded
|
275
|
-
* **no filesize limit!**
|
276
|
+
* **no filesize limit!** even on Cloudflare
|
276
277
|
* ☑ stash: simple PUT filedropper
|
277
278
|
* ☑ filename randomizer
|
278
279
|
* ☑ write-only folders
|
@@ -707,7 +708,7 @@ up2k has several advantages:
|
|
707
708
|
* uploads resume if you reboot your browser or pc, just upload the same files again
|
708
709
|
* server detects any corruption; the client reuploads affected chunks
|
709
710
|
* the client doesn't upload anything that already exists on the server
|
710
|
-
* no filesize limit
|
711
|
+
* no filesize limit, even when a proxy limits the request size (for example Cloudflare)
|
711
712
|
* much higher speeds than ftp/scp/tarpipe on some internet connections (mainly american ones) thanks to parallel connections
|
712
713
|
* the last-modified timestamp of the file is preserved
|
713
714
|
|
@@ -743,6 +744,8 @@ note that since up2k has to read each file twice, `[🎈] bup` can *theoreticall
|
|
743
744
|
|
744
745
|
if you are resuming a massive upload and want to skip hashing the files which already finished, you can enable `turbo` in the `[⚙️] config` tab, but please read the tooltip on that button
|
745
746
|
|
747
|
+
if the server is behind a proxy which imposes a request-size limit, you can configure up2k to sneak below the limit with server-option `--u2sz` (the default is 96 MiB to support Cloudflare)
|
748
|
+
|
746
749
|
|
747
750
|
### file-search
|
748
751
|
|
@@ -1486,6 +1489,22 @@ redefine behavior with plugins ([examples](./bin/handlers/))
|
|
1486
1489
|
replace 404 and 403 errors with something completely different (that's it for now)
|
1487
1490
|
|
1488
1491
|
|
1492
|
+
## ip auth
|
1493
|
+
|
1494
|
+
autologin based on IP range (CIDR) , using the global-option `--ipu`
|
1495
|
+
|
1496
|
+
for example, if everyone with an IP that starts with `192.168.123` should automatically log in as the user `spartacus`, then you can either specify `--ipu=192.168.123.0/24=spartacus` as a commandline option, or put this in a config file:
|
1497
|
+
|
1498
|
+
```yaml
|
1499
|
+
[global]
|
1500
|
+
ipu: 192.168.123.0/24=spartacus
|
1501
|
+
```
|
1502
|
+
|
1503
|
+
repeat the option to map additional subnets
|
1504
|
+
|
1505
|
+
**be careful with this one!** if you have a reverseproxy, then you definitely want to make sure you have [real-ip](#real-ip) configured correctly, and it's probably a good idea to nullmap the reverseproxy's IP just in case; so if your reverseproxy is sending requests from `172.24.27.9` then that would be `--ipu=172.24.27.9/32=`
|
1506
|
+
|
1507
|
+
|
1489
1508
|
## identity providers
|
1490
1509
|
|
1491
1510
|
replace copyparty passwords with oauth and such
|
@@ -80,6 +80,7 @@ turn almost any device into a file server with resumable uploads/downloads using
|
|
80
80
|
* [event hooks](#event-hooks) - trigger a program on uploads, renames etc ([examples](./bin/hooks/))
|
81
81
|
* [upload events](#upload-events) - the older, more powerful approach ([examples](./bin/mtag/))
|
82
82
|
* [handlers](#handlers) - redefine behavior with plugins ([examples](./bin/handlers/))
|
83
|
+
* [ip auth](#ip-auth) - autologin based on IP range (CIDR)
|
83
84
|
* [identity providers](#identity-providers) - replace copyparty passwords with oauth and such
|
84
85
|
* [user-changeable passwords](#user-changeable-passwords) - if permitted, users can change their own passwords
|
85
86
|
* [using the cloud as storage](#using-the-cloud-as-storage) - connecting to an aws s3 bucket and similar
|
@@ -218,7 +219,7 @@ also see [comparison to similar software](./docs/versus.md)
|
|
218
219
|
* upload
|
219
220
|
* ☑ basic: plain multipart, ie6 support
|
220
221
|
* ☑ [up2k](#uploading): js, resumable, multithreaded
|
221
|
-
* **no filesize limit!**
|
222
|
+
* **no filesize limit!** even on Cloudflare
|
222
223
|
* ☑ stash: simple PUT filedropper
|
223
224
|
* ☑ filename randomizer
|
224
225
|
* ☑ write-only folders
|
@@ -653,7 +654,7 @@ up2k has several advantages:
|
|
653
654
|
* uploads resume if you reboot your browser or pc, just upload the same files again
|
654
655
|
* server detects any corruption; the client reuploads affected chunks
|
655
656
|
* the client doesn't upload anything that already exists on the server
|
656
|
-
* no filesize limit
|
657
|
+
* no filesize limit, even when a proxy limits the request size (for example Cloudflare)
|
657
658
|
* much higher speeds than ftp/scp/tarpipe on some internet connections (mainly american ones) thanks to parallel connections
|
658
659
|
* the last-modified timestamp of the file is preserved
|
659
660
|
|
@@ -689,6 +690,8 @@ note that since up2k has to read each file twice, `[🎈] bup` can *theoreticall
|
|
689
690
|
|
690
691
|
if you are resuming a massive upload and want to skip hashing the files which already finished, you can enable `turbo` in the `[⚙️] config` tab, but please read the tooltip on that button
|
691
692
|
|
693
|
+
if the server is behind a proxy which imposes a request-size limit, you can configure up2k to sneak below the limit with server-option `--u2sz` (the default is 96 MiB to support Cloudflare)
|
694
|
+
|
692
695
|
|
693
696
|
### file-search
|
694
697
|
|
@@ -1432,6 +1435,22 @@ redefine behavior with plugins ([examples](./bin/handlers/))
|
|
1432
1435
|
replace 404 and 403 errors with something completely different (that's it for now)
|
1433
1436
|
|
1434
1437
|
|
1438
|
+
## ip auth
|
1439
|
+
|
1440
|
+
autologin based on IP range (CIDR) , using the global-option `--ipu`
|
1441
|
+
|
1442
|
+
for example, if everyone with an IP that starts with `192.168.123` should automatically log in as the user `spartacus`, then you can either specify `--ipu=192.168.123.0/24=spartacus` as a commandline option, or put this in a config file:
|
1443
|
+
|
1444
|
+
```yaml
|
1445
|
+
[global]
|
1446
|
+
ipu: 192.168.123.0/24=spartacus
|
1447
|
+
```
|
1448
|
+
|
1449
|
+
repeat the option to map additional subnets
|
1450
|
+
|
1451
|
+
**be careful with this one!** if you have a reverseproxy, then you definitely want to make sure you have [real-ip](#real-ip) configured correctly, and it's probably a good idea to nullmap the reverseproxy's IP just in case; so if your reverseproxy is sending requests from `172.24.27.9` then that would be `--ipu=172.24.27.9/32=`
|
1452
|
+
|
1453
|
+
|
1435
1454
|
## identity providers
|
1436
1455
|
|
1437
1456
|
replace copyparty passwords with oauth and such
|
@@ -1009,7 +1009,7 @@ def add_upload(ap):
|
|
1009
1009
|
ap2.add_argument("--sparse", metavar="MiB", type=int, default=4, help="windows-only: minimum size of incoming uploads through up2k before they are made into sparse files")
|
1010
1010
|
ap2.add_argument("--turbo", metavar="LVL", type=int, default=0, help="configure turbo-mode in up2k client; [\033[32m-1\033[0m] = forbidden/always-off, [\033[32m0\033[0m] = default-off and warn if enabled, [\033[32m1\033[0m] = default-off, [\033[32m2\033[0m] = on, [\033[32m3\033[0m] = on and disable datecheck")
|
1011
1011
|
ap2.add_argument("--u2j", metavar="JOBS", type=int, default=2, help="web-client: number of file chunks to upload in parallel; 1 or 2 is good for low-latency (same-country) connections, 4-8 for android clients, 16 for cross-atlantic (max=64)")
|
1012
|
-
ap2.add_argument("--u2sz", metavar="N,N,N", type=u, default="1,64,96", help="web-client: default upload chunksize (MiB); sets \033[33mmin,default,max\033[0m in the settings gui. Each HTTP POST will aim for
|
1012
|
+
ap2.add_argument("--u2sz", metavar="N,N,N", type=u, default="1,64,96", help="web-client: default upload chunksize (MiB); sets \033[33mmin,default,max\033[0m in the settings gui. Each HTTP POST will aim for \033[33mdefault\033[0m, and never exceed \033[33mmax\033[0m. Cloudflare max is 96. Big values are good for cross-atlantic but may increase HDD fragmentation on some FS. Disable this optimization with [\033[32m1,1,1\033[0m]")
|
1013
1013
|
ap2.add_argument("--u2sort", metavar="TXT", type=u, default="s", help="upload order; [\033[32ms\033[0m]=smallest-first, [\033[32mn\033[0m]=alphabetical, [\033[32mfs\033[0m]=force-s, [\033[32mfn\033[0m]=force-n -- alphabetical is a bit slower on fiber/LAN but makes it easier to eyeball if everything went fine")
|
1014
1014
|
ap2.add_argument("--write-uplog", action="store_true", help="write POST reports to textfiles in working-directory")
|
1015
1015
|
|
@@ -1079,6 +1079,7 @@ def add_auth(ap):
|
|
1079
1079
|
ap2.add_argument("--ses-db", metavar="PATH", type=u, default=ses_db, help="where to store the sessions database (if you run multiple copyparty instances, make sure they use different DBs)")
|
1080
1080
|
ap2.add_argument("--ses-len", metavar="CHARS", type=int, default=20, help="session key length; default is 120 bits ((20//4)*4*6)")
|
1081
1081
|
ap2.add_argument("--no-ses", action="store_true", help="disable sessions; use plaintext passwords in cookies")
|
1082
|
+
ap2.add_argument("--ipu", metavar="CIDR=USR", type=u, action="append", help="users with IP matching \033[33mCIDR\033[0m are auto-authenticated as username \033[33mUSR\033[0m; example: [\033[32m172.16.24.0/24=dave]")
|
1082
1083
|
|
1083
1084
|
|
1084
1085
|
def add_chpw(ap):
|
@@ -1469,6 +1470,7 @@ def add_debug(ap):
|
|
1469
1470
|
ap2.add_argument("--bak-flips", action="store_true", help="[up2k] if a client uploads a bitflipped/corrupted chunk, store a copy according to \033[33m--bf-nc\033[0m and \033[33m--bf-dir\033[0m")
|
1470
1471
|
ap2.add_argument("--bf-nc", metavar="NUM", type=int, default=200, help="bak-flips: stop if there's more than \033[33mNUM\033[0m files at \033[33m--kf-dir\033[0m already; default: 6.3 GiB max (200*32M)")
|
1471
1472
|
ap2.add_argument("--bf-dir", metavar="PATH", type=u, default="bf", help="bak-flips: store corrupted chunks at \033[33mPATH\033[0m; default: folder named 'bf' wherever copyparty was started")
|
1473
|
+
ap2.add_argument("--bf-log", metavar="PATH", type=u, default="", help="bak-flips: log corruption info to a textfile at \033[33mPATH\033[0m")
|
1472
1474
|
|
1473
1475
|
|
1474
1476
|
# fmt: on
|
@@ -72,6 +72,7 @@ class FtpAuth(DummyAuthorizer):
|
|
72
72
|
else:
|
73
73
|
raise AuthenticationFailed("banned")
|
74
74
|
|
75
|
+
args = self.hub.args
|
75
76
|
asrv = self.hub.asrv
|
76
77
|
uname = "*"
|
77
78
|
if username != "anonymous":
|
@@ -82,6 +83,9 @@ class FtpAuth(DummyAuthorizer):
|
|
82
83
|
uname = zs
|
83
84
|
break
|
84
85
|
|
86
|
+
if args.ipu and uname == "*":
|
87
|
+
uname = args.ipu_iu[args.ipu_nm.map(ip)]
|
88
|
+
|
85
89
|
if not uname or not (asrv.vfs.aread.get(uname) or asrv.vfs.awrite.get(uname)):
|
86
90
|
g = self.hub.gpwd
|
87
91
|
if g.lim:
|
@@ -584,6 +584,9 @@ class HttpCli(object):
|
|
584
584
|
or "*"
|
585
585
|
)
|
586
586
|
|
587
|
+
if self.args.ipu and self.uname == "*":
|
588
|
+
self.uname = self.conn.ipu_iu[self.conn.ipu_nm.map(self.ip)]
|
589
|
+
|
587
590
|
self.rvol = self.asrv.vfs.aread[self.uname]
|
588
591
|
self.wvol = self.asrv.vfs.awrite[self.uname]
|
589
592
|
self.avol = self.asrv.vfs.aadmin[self.uname]
|
@@ -1871,7 +1874,7 @@ class HttpCli(object):
|
|
1871
1874
|
f, fn = ren_open(fn, *open_a, **params)
|
1872
1875
|
try:
|
1873
1876
|
path = os.path.join(fdir, fn)
|
1874
|
-
post_sz, sha_hex, sha_b64 = hashcopy(reader, f, self.args.s_wr_slp)
|
1877
|
+
post_sz, sha_hex, sha_b64 = hashcopy(reader, f, None, 0, self.args.s_wr_slp)
|
1875
1878
|
finally:
|
1876
1879
|
f.close()
|
1877
1880
|
|
@@ -2023,13 +2026,32 @@ class HttpCli(object):
|
|
2023
2026
|
return True
|
2024
2027
|
|
2025
2028
|
def bakflip(
|
2026
|
-
self,
|
2029
|
+
self,
|
2030
|
+
f ,
|
2031
|
+
ap ,
|
2032
|
+
ofs ,
|
2033
|
+
sz ,
|
2034
|
+
good_sha ,
|
2035
|
+
bad_sha ,
|
2036
|
+
flags ,
|
2027
2037
|
) :
|
2038
|
+
now = time.time()
|
2039
|
+
t = "bad-chunk: %.3f %s %s %d %s %s %s"
|
2040
|
+
t = t % (now, bad_sha, good_sha, ofs, self.ip, self.uname, ap)
|
2041
|
+
self.log(t, 5)
|
2042
|
+
|
2043
|
+
if self.args.bf_log:
|
2044
|
+
try:
|
2045
|
+
with open(self.args.bf_log, "ab+") as f2:
|
2046
|
+
f2.write((t + "\n").encode("utf-8", "replace"))
|
2047
|
+
except Exception as ex:
|
2048
|
+
self.log("append %s failed: %r" % (self.args.bf_log, ex))
|
2049
|
+
|
2028
2050
|
if not self.args.bak_flips or self.args.nw:
|
2029
2051
|
return
|
2030
2052
|
|
2031
2053
|
sdir = self.args.bf_dir
|
2032
|
-
fp = os.path.join(sdir,
|
2054
|
+
fp = os.path.join(sdir, bad_sha)
|
2033
2055
|
if bos.path.exists(fp):
|
2034
2056
|
return self.log("no bakflip; have it", 6)
|
2035
2057
|
|
@@ -2315,7 +2337,7 @@ class HttpCli(object):
|
|
2315
2337
|
broker = self.conn.hsrv.broker
|
2316
2338
|
x = broker.ask("up2k.handle_chunks", ptop, wark, chashes)
|
2317
2339
|
response = x.get()
|
2318
|
-
chashes, chunksize, cstarts, path, lastmod, sprs = response
|
2340
|
+
chashes, chunksize, cstarts, path, lastmod, fsize, sprs = response
|
2319
2341
|
maxsize = chunksize * len(chashes)
|
2320
2342
|
cstart0 = cstarts[0]
|
2321
2343
|
locked = chashes # remaining chunks to be received in this request
|
@@ -2323,6 +2345,50 @@ class HttpCli(object):
|
|
2323
2345
|
num_left = -1 # num chunks left according to most recent up2k release
|
2324
2346
|
treport = time.time() # ratelimit up2k reporting to reduce overhead
|
2325
2347
|
|
2348
|
+
if "x-up2k-subc" in self.headers:
|
2349
|
+
sc_ofs = int(self.headers["x-up2k-subc"])
|
2350
|
+
chash = chashes[0]
|
2351
|
+
|
2352
|
+
u2sc = self.conn.hsrv.u2sc
|
2353
|
+
try:
|
2354
|
+
sc_pofs, hasher = u2sc[chash]
|
2355
|
+
if not sc_ofs:
|
2356
|
+
t = "client restarted the chunk; forgetting subchunk offset %d"
|
2357
|
+
self.log(t % (sc_pofs,))
|
2358
|
+
raise Exception()
|
2359
|
+
except:
|
2360
|
+
sc_pofs = 0
|
2361
|
+
hasher = hashlib.sha512()
|
2362
|
+
|
2363
|
+
et = "subchunk protocol error; resetting chunk "
|
2364
|
+
if sc_pofs != sc_ofs:
|
2365
|
+
u2sc.pop(chash, None)
|
2366
|
+
t = "%s[%s]: the expected resume-point was %d, not %d"
|
2367
|
+
raise Pebkac(400, t % (et, chash, sc_pofs, sc_ofs))
|
2368
|
+
if len(cstarts) > 1:
|
2369
|
+
u2sc.pop(chash, None)
|
2370
|
+
t = "%s[%s]: only a single subchunk can be uploaded in one request; you are sending %d chunks"
|
2371
|
+
raise Pebkac(400, t % (et, chash, len(cstarts)))
|
2372
|
+
csize = min(chunksize, fsize - cstart0[0])
|
2373
|
+
cstart0[0] += sc_ofs # also sets cstarts[0][0]
|
2374
|
+
sc_next_ofs = sc_ofs + postsize
|
2375
|
+
if sc_next_ofs > csize:
|
2376
|
+
u2sc.pop(chash, None)
|
2377
|
+
t = "%s[%s]: subchunk offset (%d) plus postsize (%d) exceeds chunksize (%d)"
|
2378
|
+
raise Pebkac(400, t % (et, chash, sc_ofs, postsize, csize))
|
2379
|
+
else:
|
2380
|
+
final_subchunk = sc_next_ofs == csize
|
2381
|
+
t = "subchunk %s %d:%d/%d %s"
|
2382
|
+
zs = "END" if final_subchunk else ""
|
2383
|
+
self.log(t % (chash[:15], sc_ofs, sc_next_ofs, csize, zs), 6)
|
2384
|
+
if final_subchunk:
|
2385
|
+
u2sc.pop(chash, None)
|
2386
|
+
else:
|
2387
|
+
u2sc[chash] = (sc_next_ofs, hasher)
|
2388
|
+
else:
|
2389
|
+
hasher = None
|
2390
|
+
final_subchunk = True
|
2391
|
+
|
2326
2392
|
try:
|
2327
2393
|
if self.args.nw:
|
2328
2394
|
path = os.devnull
|
@@ -2353,11 +2419,15 @@ class HttpCli(object):
|
|
2353
2419
|
reader = read_socket(
|
2354
2420
|
self.sr, self.args.s_rd_sz, min(remains, chunksize)
|
2355
2421
|
)
|
2356
|
-
post_sz, _, sha_b64 = hashcopy(
|
2422
|
+
post_sz, _, sha_b64 = hashcopy(
|
2423
|
+
reader, f, hasher, 0, self.args.s_wr_slp
|
2424
|
+
)
|
2357
2425
|
|
2358
|
-
if sha_b64 != chash:
|
2426
|
+
if sha_b64 != chash and final_subchunk:
|
2359
2427
|
try:
|
2360
|
-
self.bakflip(
|
2428
|
+
self.bakflip(
|
2429
|
+
f, path, cstart[0], post_sz, chash, sha_b64, vfs.flags
|
2430
|
+
)
|
2361
2431
|
except:
|
2362
2432
|
self.log("bakflip failed: " + min_ex())
|
2363
2433
|
|
@@ -2385,7 +2455,8 @@ class HttpCli(object):
|
|
2385
2455
|
|
2386
2456
|
# be quick to keep the tcp winsize scale;
|
2387
2457
|
# if we can't confirm rn then that's fine
|
2388
|
-
|
2458
|
+
if final_subchunk:
|
2459
|
+
written.append(chash)
|
2389
2460
|
now = time.time()
|
2390
2461
|
if now - treport < 1:
|
2391
2462
|
continue
|
@@ -2773,7 +2844,7 @@ class HttpCli(object):
|
|
2773
2844
|
tabspath = os.path.join(fdir, tnam)
|
2774
2845
|
self.log("writing to {}".format(tabspath))
|
2775
2846
|
sz, sha_hex, sha_b64 = hashcopy(
|
2776
|
-
p_data, f, self.args.s_wr_slp
|
2847
|
+
p_data, f, None, max_sz, self.args.s_wr_slp
|
2777
2848
|
)
|
2778
2849
|
if sz == 0:
|
2779
2850
|
raise Pebkac(400, "empty files in post")
|
@@ -3103,7 +3174,7 @@ class HttpCli(object):
|
|
3103
3174
|
wunlink(self.log, fp, vfs.flags)
|
3104
3175
|
|
3105
3176
|
with open(fsenc(fp), "wb", self.args.iobuf) as f:
|
3106
|
-
sz, sha512, _ = hashcopy(p_data, f, self.args.s_wr_slp)
|
3177
|
+
sz, sha512, _ = hashcopy(p_data, f, None, 0, self.args.s_wr_slp)
|
3107
3178
|
|
3108
3179
|
if lim:
|
3109
3180
|
lim.nup(self.ip)
|
@@ -56,6 +56,8 @@ class HttpConn(object):
|
|
56
56
|
self.asrv = hsrv.asrv # mypy404
|
57
57
|
self.u2fh = hsrv.u2fh # mypy404
|
58
58
|
self.pipes = hsrv.pipes # mypy404
|
59
|
+
self.ipu_iu = hsrv.ipu_iu
|
60
|
+
self.ipu_nm = hsrv.ipu_nm
|
59
61
|
self.ipa_nm = hsrv.ipa_nm
|
60
62
|
self.xff_nm = hsrv.xff_nm
|
61
63
|
self.xff_lan = hsrv.xff_lan # type: ignore
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
from __future__ import print_function, unicode_literals
|
3
3
|
|
4
|
+
import hashlib
|
4
5
|
import math
|
5
6
|
import os
|
6
7
|
import re
|
@@ -69,6 +70,7 @@ from .util import (
|
|
69
70
|
build_netmap,
|
70
71
|
has_resource,
|
71
72
|
ipnorm,
|
73
|
+
load_ipu,
|
72
74
|
load_resource,
|
73
75
|
min_ex,
|
74
76
|
shut_socket,
|
@@ -140,6 +142,7 @@ class HttpSrv(object):
|
|
140
142
|
self.t_periodic = None
|
141
143
|
|
142
144
|
self.u2fh = FHC()
|
145
|
+
self.u2sc = {}
|
143
146
|
self.pipes = CachedDict(0.2)
|
144
147
|
self.metrics = Metrics(self)
|
145
148
|
self.nreq = 0
|
@@ -171,6 +174,11 @@ class HttpSrv(object):
|
|
171
174
|
self.j2 = {x: env.get_template(x + ".html") for x in jn}
|
172
175
|
self.prism = has_resource(self.E, "web/deps/prism.js.gz")
|
173
176
|
|
177
|
+
if self.args.ipu:
|
178
|
+
self.ipu_iu, self.ipu_nm = load_ipu(self.log, self.args.ipu)
|
179
|
+
else:
|
180
|
+
self.ipu_iu = self.ipu_nm = None
|
181
|
+
|
174
182
|
self.ipa_nm = build_netmap(self.args.ipa)
|
175
183
|
self.xff_nm = build_netmap(self.args.xff_src)
|
176
184
|
self.xff_lan = build_netmap("lan")
|
@@ -54,6 +54,7 @@ from .util import (
|
|
54
54
|
alltrace,
|
55
55
|
ansi_re,
|
56
56
|
build_netmap,
|
57
|
+
load_ipu,
|
57
58
|
min_ex,
|
58
59
|
mp,
|
59
60
|
odfusion,
|
@@ -215,6 +216,11 @@ class SvcHub(object):
|
|
215
216
|
noch.update([x for x in zsl if x])
|
216
217
|
args.chpw_no = noch
|
217
218
|
|
219
|
+
if args.ipu:
|
220
|
+
iu, nm = load_ipu(self.log, args.ipu)
|
221
|
+
setattr(args, "ipu_iu", iu)
|
222
|
+
setattr(args, "ipu_nm", nm)
|
223
|
+
|
218
224
|
if not self.args.no_ses:
|
219
225
|
self.setup_session_db()
|
220
226
|
|