copyparty 1.15.1__tar.gz → 1.15.3__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.
Files changed (121) hide show
  1. {copyparty-1.15.1 → copyparty-1.15.3}/PKG-INFO +15 -3
  2. {copyparty-1.15.1 → copyparty-1.15.3}/README.md +14 -2
  3. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/__init__.py +1 -0
  4. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/__main__.py +16 -12
  5. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/__version__.py +2 -2
  6. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/authsrv.py +11 -6
  7. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/broker_mp.py +2 -2
  8. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/broker_mpw.py +2 -2
  9. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/broker_thr.py +4 -9
  10. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/broker_util.py +13 -1
  11. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/cfg.py +1 -0
  12. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/fsutil.py +0 -3
  13. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/httpcli.py +105 -60
  14. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/httpconn.py +0 -1
  15. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/httpsrv.py +3 -5
  16. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/svchub.py +2 -6
  17. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/th_srv.py +15 -7
  18. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/u2idx.py +0 -3
  19. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/up2k.py +206 -98
  20. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/util.py +116 -63
  21. copyparty-1.15.3/copyparty/web/browser.js.gz +0 -0
  22. copyparty-1.15.3/copyparty/web/splash.css.gz +0 -0
  23. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/splash.html +12 -0
  24. copyparty-1.15.3/copyparty/web/splash.js.gz +0 -0
  25. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty.egg-info/PKG-INFO +15 -3
  26. copyparty-1.15.1/copyparty/web/browser.js.gz +0 -0
  27. copyparty-1.15.1/copyparty/web/splash.css.gz +0 -0
  28. copyparty-1.15.1/copyparty/web/splash.js.gz +0 -0
  29. {copyparty-1.15.1 → copyparty-1.15.3}/LICENSE +0 -0
  30. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/bos/__init__.py +0 -0
  31. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/bos/bos.py +0 -0
  32. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/bos/path.py +0 -0
  33. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/cert.py +0 -0
  34. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/dxml.py +0 -0
  35. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/ftpd.py +0 -0
  36. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/ico.py +0 -0
  37. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/mdns.py +0 -0
  38. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/metrics.py +0 -0
  39. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/mtag.py +0 -0
  40. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/multicast.py +0 -0
  41. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/pwhash.py +0 -0
  42. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/res/COPYING.txt +0 -0
  43. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/res/__init__.py +0 -0
  44. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/res/insecure.pem +0 -0
  45. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/smbd.py +0 -0
  46. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/ssdp.py +0 -0
  47. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/star.py +0 -0
  48. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/stolen/__init__.py +0 -0
  49. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/stolen/dnslib/__init__.py +0 -0
  50. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/stolen/dnslib/bimap.py +0 -0
  51. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/stolen/dnslib/bit.py +0 -0
  52. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/stolen/dnslib/buffer.py +0 -0
  53. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/stolen/dnslib/dns.py +0 -0
  54. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/stolen/dnslib/label.py +0 -0
  55. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/stolen/dnslib/lex.py +0 -0
  56. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/stolen/dnslib/ranges.py +0 -0
  57. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/stolen/ifaddr/__init__.py +0 -0
  58. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/stolen/ifaddr/_posix.py +0 -0
  59. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/stolen/ifaddr/_shared.py +0 -0
  60. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/stolen/ifaddr/_win32.py +0 -0
  61. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/stolen/qrcodegen.py +0 -0
  62. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/stolen/surrogateescape.py +0 -0
  63. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/sutil.py +0 -0
  64. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/szip.py +0 -0
  65. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/tcpsrv.py +0 -0
  66. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/tftpd.py +0 -0
  67. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/th_cli.py +0 -0
  68. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/a/__init__.py +0 -0
  69. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/a/partyfuse.py +0 -0
  70. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/a/u2c.py +0 -0
  71. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/a/webdav-cfg.bat +0 -0
  72. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/baguettebox.js.gz +0 -0
  73. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/browser.css.gz +0 -0
  74. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/browser.html +0 -0
  75. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/browser2.html +0 -0
  76. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/cf.html +0 -0
  77. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/dbg-audio.js.gz +0 -0
  78. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/dd/2.png +0 -0
  79. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/dd/3.png +0 -0
  80. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/dd/4.png +0 -0
  81. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/dd/5.png +0 -0
  82. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/dd/__init__.py +0 -0
  83. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/deps/__init__.py +0 -0
  84. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/deps/busy.mp3.gz +0 -0
  85. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/deps/easymde.css.gz +0 -0
  86. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/deps/easymde.js.gz +0 -0
  87. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/deps/marked.js.gz +0 -0
  88. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/deps/mini-fa.css.gz +0 -0
  89. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/deps/mini-fa.woff +0 -0
  90. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/deps/prism.css.gz +0 -0
  91. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/deps/prism.js.gz +0 -0
  92. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/deps/prismd.css.gz +0 -0
  93. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/deps/scp.woff2 +0 -0
  94. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/deps/sha512.ac.js.gz +0 -0
  95. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/deps/sha512.hw.js.gz +0 -0
  96. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/md.css.gz +0 -0
  97. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/md.html +0 -0
  98. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/md.js.gz +0 -0
  99. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/md2.css.gz +0 -0
  100. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/md2.js.gz +0 -0
  101. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/mde.css.gz +0 -0
  102. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/mde.html +0 -0
  103. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/mde.js.gz +0 -0
  104. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/msg.css.gz +0 -0
  105. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/msg.html +0 -0
  106. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/shares.css.gz +0 -0
  107. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/shares.html +0 -0
  108. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/shares.js.gz +0 -0
  109. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/svcs.html +0 -0
  110. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/svcs.js.gz +0 -0
  111. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/ui.css.gz +0 -0
  112. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/up2k.js.gz +0 -0
  113. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/util.js.gz +0 -0
  114. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty/web/w.hash.js.gz +0 -0
  115. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty.egg-info/SOURCES.txt +0 -0
  116. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty.egg-info/dependency_links.txt +0 -0
  117. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty.egg-info/entry_points.txt +0 -0
  118. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty.egg-info/requires.txt +0 -0
  119. {copyparty-1.15.1 → copyparty-1.15.3}/copyparty.egg-info/top_level.txt +0 -0
  120. {copyparty-1.15.1 → copyparty-1.15.3}/pyproject.toml +0 -0
  121. {copyparty-1.15.1 → copyparty-1.15.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: copyparty
3
- Version: 1.15.1
3
+ Version: 1.15.3
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
@@ -52,7 +52,7 @@ Requires-Dist: partftpy>=0.4.0; extra == "tftpd"
52
52
  Provides-Extra: pwhash
53
53
  Requires-Dist: argon2-cffi; extra == "pwhash"
54
54
 
55
- <img src="docs/logo.svg" width="250" align="right"/>
55
+ <img src="https://github.com/9001/copyparty/raw/hovudstraum/docs/logo.svg" width="250" align="right"/>
56
56
 
57
57
  ### 💾🎉 copyparty
58
58
 
@@ -97,6 +97,7 @@ turn almost any device into a file server with resumable uploads/downloads using
97
97
  * [unpost](#unpost) - undo/delete accidental uploads
98
98
  * [self-destruct](#self-destruct) - uploads can be given a lifetime
99
99
  * [race the beam](#race-the-beam) - download files while they're still uploading ([demo video](http://a.ocv.me/pub/g/nerd-stuff/cpp/2024-0418-race-the-beam.webm))
100
+ * [incoming files](#incoming-files) - the control-panel shows the ETA for all incoming files
100
101
  * [file manager](#file-manager) - cut/paste, rename, and delete files/folders (if you have permission)
101
102
  * [shares](#shares) - share a file or folder by creating a temporary link
102
103
  * [batch rename](#batch-rename) - select some files and press `F2` to bring up the rename UI
@@ -294,7 +295,7 @@ also see [comparison to similar software](./docs/versus.md)
294
295
  * ☑ ...of videos using FFmpeg
295
296
  * ☑ ...of audio (spectrograms) using FFmpeg
296
297
  * ☑ cache eviction (max-age; maybe max-size eventually)
297
- * ☑ multilingual UI (english, norwegian, [add your own](./docs/rice/#translations)))
298
+ * ☑ multilingual UI (english, norwegian, chinese, [add your own](./docs/rice/#translations)))
298
299
  * ☑ SPA (browse while uploading)
299
300
  * server indexing
300
301
  * ☑ [locate files by contents](#file-search)
@@ -785,6 +786,13 @@ download files while they're still uploading ([demo video](http://a.ocv.me/pub/g
785
786
  requires the file to be uploaded using up2k (which is the default drag-and-drop uploader), alternatively the command-line program
786
787
 
787
788
 
789
+ ### incoming files
790
+
791
+ the control-panel shows the ETA for all incoming files , but only for files being uploaded into volumes where you have read-access
792
+
793
+ ![copyparty-cpanel-upload-eta-or8](https://github.com/user-attachments/assets/fd275ffa-698c-4fca-a307-4d2181269a6a)
794
+
795
+
788
796
  ## file manager
789
797
 
790
798
  cut/paste, rename, and delete files/folders (if you have permission)
@@ -1603,6 +1611,8 @@ you can either:
1603
1611
  * 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
1604
1612
  * 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
1605
1613
 
1614
+ when running behind a reverse-proxy (this includes services like cloudflare), it is important to configure real-ip correctly, as many features rely on knowing the client's IP. Look out for red and yellow log messages which explain how to do this. But basically, set `--xff-hdr` to the name of the http header to read the IP from (usually `x-forwarded-for`, but cloudflare uses `cf-connecting-ip`), and then `--xff-src` to the IP of the reverse-proxy so copyparty will trust the xff-hdr. Note that `--rp-loc` in particular will not work at all unless you do this
1615
+
1606
1616
  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, depending on a lot of factors
1607
1617
  * **warning:** nginx-QUIC (HTTP/3) is still experimental and can make uploads much slower, so HTTP/1.1 is recommended for now
1608
1618
  * depending on server/client, HTTP/1.1 can also be 5x faster than HTTP/2
@@ -1933,6 +1943,7 @@ interact with copyparty using non-browser clients
1933
1943
  * [rclone](https://rclone.org/) as client can give ~5x performance, see [./docs/rclone.md](docs/rclone.md)
1934
1944
 
1935
1945
  * sharex (screenshot utility): see [./contrib/sharex.sxcu](contrib/#sharexsxcu)
1946
+ * and for screenshots on linux, see [./contrib/flameshot.sh](./contrib/flameshot.sh)
1936
1947
 
1937
1948
  * contextlet (web browser integration); see [contrib contextlet](contrib/#send-to-cppcontextletjson)
1938
1949
 
@@ -2011,6 +2022,7 @@ below are some tweaks roughly ordered by usefulness:
2011
2022
  * and also makes thumbnails load faster, regardless of e2d/e2t
2012
2023
  * `--dedup` enables deduplication and thus avoids writing to the HDD if someone uploads a dupe
2013
2024
  * `--safe-dedup 1` makes deduplication much faster during upload by skipping verification of file contents; safe if there is no other software editing/moving the files in the volumes
2025
+ * `--no-dirsz` shows the size of folder inodes instead of the total size of the contents, giving about 30% faster folder listings
2014
2026
  * `--no-hash .` when indexing a network-disk if you don't care about the actual filehashes and only want the names/tags searchable
2015
2027
  * if your volumes are on a network-disk such as NFS / SMB / s3, specifying larger values for `--iobuf` and/or `--s-rd-sz` and/or `--s-wr-sz` may help; try setting all of them to `524288` or `1048576` or `4194304`
2016
2028
  * `--no-htp --hash-mt=0 --mtag-mt=1 --th-mt=1` minimizes the number of threads; can help in some eccentric environments (like the vscode debugger)
@@ -1,4 +1,4 @@
1
- <img src="docs/logo.svg" width="250" align="right"/>
1
+ <img src="https://github.com/9001/copyparty/raw/hovudstraum/docs/logo.svg" width="250" align="right"/>
2
2
 
3
3
  ### 💾🎉 copyparty
4
4
 
@@ -43,6 +43,7 @@ turn almost any device into a file server with resumable uploads/downloads using
43
43
  * [unpost](#unpost) - undo/delete accidental uploads
44
44
  * [self-destruct](#self-destruct) - uploads can be given a lifetime
45
45
  * [race the beam](#race-the-beam) - download files while they're still uploading ([demo video](http://a.ocv.me/pub/g/nerd-stuff/cpp/2024-0418-race-the-beam.webm))
46
+ * [incoming files](#incoming-files) - the control-panel shows the ETA for all incoming files
46
47
  * [file manager](#file-manager) - cut/paste, rename, and delete files/folders (if you have permission)
47
48
  * [shares](#shares) - share a file or folder by creating a temporary link
48
49
  * [batch rename](#batch-rename) - select some files and press `F2` to bring up the rename UI
@@ -240,7 +241,7 @@ also see [comparison to similar software](./docs/versus.md)
240
241
  * ☑ ...of videos using FFmpeg
241
242
  * ☑ ...of audio (spectrograms) using FFmpeg
242
243
  * ☑ cache eviction (max-age; maybe max-size eventually)
243
- * ☑ multilingual UI (english, norwegian, [add your own](./docs/rice/#translations)))
244
+ * ☑ multilingual UI (english, norwegian, chinese, [add your own](./docs/rice/#translations)))
244
245
  * ☑ SPA (browse while uploading)
245
246
  * server indexing
246
247
  * ☑ [locate files by contents](#file-search)
@@ -731,6 +732,13 @@ download files while they're still uploading ([demo video](http://a.ocv.me/pub/g
731
732
  requires the file to be uploaded using up2k (which is the default drag-and-drop uploader), alternatively the command-line program
732
733
 
733
734
 
735
+ ### incoming files
736
+
737
+ the control-panel shows the ETA for all incoming files , but only for files being uploaded into volumes where you have read-access
738
+
739
+ ![copyparty-cpanel-upload-eta-or8](https://github.com/user-attachments/assets/fd275ffa-698c-4fca-a307-4d2181269a6a)
740
+
741
+
734
742
  ## file manager
735
743
 
736
744
  cut/paste, rename, and delete files/folders (if you have permission)
@@ -1549,6 +1557,8 @@ you can either:
1549
1557
  * 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
1550
1558
  * 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
1551
1559
 
1560
+ when running behind a reverse-proxy (this includes services like cloudflare), it is important to configure real-ip correctly, as many features rely on knowing the client's IP. Look out for red and yellow log messages which explain how to do this. But basically, set `--xff-hdr` to the name of the http header to read the IP from (usually `x-forwarded-for`, but cloudflare uses `cf-connecting-ip`), and then `--xff-src` to the IP of the reverse-proxy so copyparty will trust the xff-hdr. Note that `--rp-loc` in particular will not work at all unless you do this
1561
+
1552
1562
  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, depending on a lot of factors
1553
1563
  * **warning:** nginx-QUIC (HTTP/3) is still experimental and can make uploads much slower, so HTTP/1.1 is recommended for now
1554
1564
  * depending on server/client, HTTP/1.1 can also be 5x faster than HTTP/2
@@ -1879,6 +1889,7 @@ interact with copyparty using non-browser clients
1879
1889
  * [rclone](https://rclone.org/) as client can give ~5x performance, see [./docs/rclone.md](docs/rclone.md)
1880
1890
 
1881
1891
  * sharex (screenshot utility): see [./contrib/sharex.sxcu](contrib/#sharexsxcu)
1892
+ * and for screenshots on linux, see [./contrib/flameshot.sh](./contrib/flameshot.sh)
1882
1893
 
1883
1894
  * contextlet (web browser integration); see [contrib contextlet](contrib/#send-to-cppcontextletjson)
1884
1895
 
@@ -1957,6 +1968,7 @@ below are some tweaks roughly ordered by usefulness:
1957
1968
  * and also makes thumbnails load faster, regardless of e2d/e2t
1958
1969
  * `--dedup` enables deduplication and thus avoids writing to the HDD if someone uploads a dupe
1959
1970
  * `--safe-dedup 1` makes deduplication much faster during upload by skipping verification of file contents; safe if there is no other software editing/moving the files in the volumes
1971
+ * `--no-dirsz` shows the size of folder inodes instead of the total size of the contents, giving about 30% faster folder listings
1960
1972
  * `--no-hash .` when indexing a network-disk if you don't care about the actual filehashes and only want the names/tags searchable
1961
1973
  * if your volumes are on a network-disk such as NFS / SMB / s3, specifying larger values for `--iobuf` and/or `--s-rd-sz` and/or `--s-wr-sz` may help; try setting all of them to `524288` or `1048576` or `4194304`
1962
1974
  * `--no-htp --hash-mt=0 --mtag-mt=1 --th-mt=1` minimizes the number of threads; can help in some eccentric environments (like the vscode debugger)
@@ -16,6 +16,7 @@ except:
16
16
  TYPE_CHECKING = False
17
17
 
18
18
  PY2 = sys.version_info < (3,)
19
+ PY36 = sys.version_info > (3, 6)
19
20
  if not PY2:
20
21
  unicode = str
21
22
  else:
@@ -27,6 +27,7 @@ from .__init__ import (
27
27
  EXE,
28
28
  MACOS,
29
29
  PY2,
30
+ PY36,
30
31
  VT100,
31
32
  WINDOWS,
32
33
  E,
@@ -54,6 +55,7 @@ from .util import (
54
55
  Daemon,
55
56
  align_tab,
56
57
  ansi_re,
58
+ b64enc,
57
59
  dedent,
58
60
  min_ex,
59
61
  pybin,
@@ -198,7 +200,7 @@ def init_E(EE ) :
198
200
  errs.append("Using [%s] instead" % (p,))
199
201
 
200
202
  if errs:
201
- print("WARNING: " + ". ".join(errs))
203
+ warn(". ".join(errs))
202
204
 
203
205
  return p # type: ignore
204
206
  except Exception as ex:
@@ -228,7 +230,7 @@ def init_E(EE ) :
228
230
  raise
229
231
 
230
232
 
231
- def get_srvname() :
233
+ def get_srvname(verbose) :
232
234
  try:
233
235
  ret = unicode(socket.gethostname()).split(".")[0]
234
236
  except:
@@ -238,7 +240,8 @@ def get_srvname() :
238
240
  return ret
239
241
 
240
242
  fp = os.path.join(E.cfg, "name.txt")
241
- lprint("using hostname from {}\n".format(fp))
243
+ if verbose:
244
+ lprint("using hostname from {}\n".format(fp))
242
245
  try:
243
246
  with open(fp, "rb") as f:
244
247
  ret = f.read().decode("utf-8", "replace").strip()
@@ -260,7 +263,7 @@ def get_fk_salt() :
260
263
  with open(fp, "rb") as f:
261
264
  ret = f.read().strip()
262
265
  except:
263
- ret = base64.b64encode(os.urandom(18))
266
+ ret = b64enc(os.urandom(18))
264
267
  with open(fp, "wb") as f:
265
268
  f.write(ret + b"\n")
266
269
 
@@ -273,7 +276,7 @@ def get_dk_salt() :
273
276
  with open(fp, "rb") as f:
274
277
  ret = f.read().strip()
275
278
  except:
276
- ret = base64.b64encode(os.urandom(30))
279
+ ret = b64enc(os.urandom(30))
277
280
  with open(fp, "wb") as f:
278
281
  f.write(ret + b"\n")
279
282
 
@@ -286,7 +289,7 @@ def get_ah_salt() :
286
289
  with open(fp, "rb") as f:
287
290
  ret = f.read().strip()
288
291
  except:
289
- ret = base64.b64encode(os.urandom(18))
292
+ ret = b64enc(os.urandom(18))
290
293
  with open(fp, "wb") as f:
291
294
  f.write(ret + b"\n")
292
295
 
@@ -344,7 +347,6 @@ def configure_ssl_ver(al ) :
344
347
  # oh man i love openssl
345
348
  # check this out
346
349
  # hold my beer
347
- assert ssl # type: ignore
348
350
  ptn = re.compile(r"^OP_NO_(TLS|SSL)v")
349
351
  sslver = terse_sslver(al.ssl_ver).split(",")
350
352
  flags = [k for k in ssl.__dict__ if ptn.match(k)]
@@ -378,7 +380,6 @@ def configure_ssl_ver(al ) :
378
380
 
379
381
 
380
382
  def configure_ssl_ciphers(al ) :
381
- assert ssl # type: ignore
382
383
  ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
383
384
  if al.ssl_ver:
384
385
  ctx.options &= ~al.ssl_flags_en
@@ -1224,6 +1225,7 @@ def add_optouts(ap):
1224
1225
  ap2.add_argument("--no-zip", action="store_true", help="disable download as zip/tar")
1225
1226
  ap2.add_argument("--no-tarcmp", action="store_true", help="disable download as compressed tar (?tar=gz, ?tar=bz2, ?tar=xz, ?tar=gz:9, ...)")
1226
1227
  ap2.add_argument("--no-lifetime", action="store_true", help="do not allow clients (or server config) to schedule an upload to be deleted after a given time")
1228
+ ap2.add_argument("--no-up-list", action="store_true", help="don't show list of incoming files in controlpanel")
1227
1229
  ap2.add_argument("--no-pipe", action="store_true", help="disable race-the-beam (lockstep download of files which are currently being uploaded) (volflag=nopipe)")
1228
1230
  ap2.add_argument("--no-db-ip", action="store_true", help="do not write uploader IPs into the database")
1229
1231
 
@@ -1352,6 +1354,8 @@ def add_db_general(ap, hcores):
1352
1354
  ap2.add_argument("--hist", metavar="PATH", type=u, default="", help="where to store volume data (db, thumbs); default is a folder named \".hist\" inside each volume (volflag=hist)")
1353
1355
  ap2.add_argument("--no-hash", metavar="PTN", type=u, default="", help="regex: disable hashing of matching absolute-filesystem-paths during e2ds folder scans (volflag=nohash)")
1354
1356
  ap2.add_argument("--no-idx", metavar="PTN", type=u, default=noidx, help="regex: disable indexing of matching absolute-filesystem-paths during e2ds folder scans (volflag=noidx)")
1357
+ ap2.add_argument("--no-dirsz", action="store_true", help="do not show total recursive size of folders in listings, show inode size instead; slightly faster (volflag=nodirsz)")
1358
+ ap2.add_argument("--re-dirsz", action="store_true", help="if the directory-sizes in the UI are bonkers, use this along with \033[33m-e2dsa\033[0m to rebuild the index from scratch")
1355
1359
  ap2.add_argument("--no-dhash", action="store_true", help="disable rescan acceleration; do full database integrity check -- makes the db ~5%% smaller and bootup/rescans 3~10x slower")
1356
1360
  ap2.add_argument("--re-dhash", action="store_true", help="force a cache rebuild on startup; enable this once if it gets out of sync (should never be necessary)")
1357
1361
  ap2.add_argument("--no-forget", action="store_true", help="never forget indexed files, even when deleted from disk -- makes it impossible to ever upload the same file twice -- only useful for offloading uploads to a cloud service or something (volflag=noforget)")
@@ -1465,7 +1469,7 @@ def add_debug(ap):
1465
1469
 
1466
1470
 
1467
1471
  def run_argparse(
1468
- argv , formatter , retry , nc
1472
+ argv , formatter , retry , nc , verbose=True
1469
1473
  ) :
1470
1474
  ap = argparse.ArgumentParser(
1471
1475
  formatter_class=formatter,
@@ -1487,7 +1491,7 @@ def run_argparse(
1487
1491
 
1488
1492
  tty = os.environ.get("TERM", "").lower() == "linux"
1489
1493
 
1490
- srvname = get_srvname()
1494
+ srvname = get_srvname(verbose)
1491
1495
 
1492
1496
  add_general(ap, nc, srvname)
1493
1497
  add_network(ap)
@@ -1667,7 +1671,7 @@ def main(argv = None, rsrc = None) :
1667
1671
  for fmtr in [RiceFormatter, RiceFormatter, Dodge11874, BasicDodge11874]:
1668
1672
  try:
1669
1673
  al = run_argparse(argv, fmtr, retry, nc)
1670
- dal = run_argparse([], fmtr, retry, nc)
1674
+ dal = run_argparse([], fmtr, retry, nc, False)
1671
1675
  break
1672
1676
  except SystemExit:
1673
1677
  raise
@@ -1751,7 +1755,7 @@ def main(argv = None, rsrc = None) :
1751
1755
  print("error: python2 cannot --smb")
1752
1756
  return
1753
1757
 
1754
- if sys.version_info < (3, 6):
1758
+ if not PY36:
1755
1759
  al.no_scandir = True
1756
1760
 
1757
1761
  if not hasattr(os, "sendfile"):
@@ -1,8 +1,8 @@
1
1
  # coding: utf-8
2
2
 
3
- VERSION = (1, 15, 1)
3
+ VERSION = (1, 15, 3)
4
4
  CODENAME = "fill the drives"
5
- BUILD_DT = (2024, 9, 9)
5
+ BUILD_DT = (2024, 9, 16)
6
6
 
7
7
  S_VERSION = ".".join(map(str, VERSION))
8
8
  S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
@@ -848,6 +848,7 @@ class AuthSrv(object):
848
848
  self.idp_accs = {} # username->groupnames
849
849
  self.idp_usr_gh = {} # username->group-header-value (cache)
850
850
 
851
+ self.hid_cache = {}
851
852
  self.mutex = threading.Lock()
852
853
  self.reload()
853
854
 
@@ -1524,7 +1525,7 @@ class AuthSrv(object):
1524
1525
  if enshare:
1525
1526
  import sqlite3
1526
1527
 
1527
- shv = VFS(self.log_func, "", shr, AXS(), {"d2d": True})
1528
+ shv = VFS(self.log_func, "", shr, AXS(), {})
1528
1529
 
1529
1530
  db_path = self.args.shr_db
1530
1531
  db = sqlite3.connect(db_path)
@@ -1543,8 +1544,8 @@ class AuthSrv(object):
1543
1544
  if s_pw:
1544
1545
  # gotta reuse the "account" for all shares with this pw,
1545
1546
  # so do a light scramble as this appears in the web-ui
1546
- zs = ub64enc(hashlib.sha512(s_pw.encode("utf-8")).digest())[4:16]
1547
- sun = "s_%s" % (zs.decode("utf-8"),)
1547
+ zb = hashlib.sha512(s_pw.encode("utf-8")).digest()
1548
+ sun = "s_%s" % (ub64enc(zb)[4:16].decode("ascii"),)
1548
1549
  acct[sun] = s_pw
1549
1550
  else:
1550
1551
  sun = "*"
@@ -1649,8 +1650,12 @@ class AuthSrv(object):
1649
1650
  promote = []
1650
1651
  demote = []
1651
1652
  for vol in vfs.all_vols.values():
1652
- zb = hashlib.sha512(afsenc(vol.realpath)).digest()
1653
- hid = base64.b32encode(zb).decode("ascii").lower()
1653
+ hid = self.hid_cache.get(vol.realpath)
1654
+ if not hid:
1655
+ zb = hashlib.sha512(afsenc(vol.realpath)).digest()
1656
+ hid = base64.b32encode(zb).decode("ascii").lower()
1657
+ self.hid_cache[vol.realpath] = hid
1658
+
1654
1659
  vflag = vol.flags.get("hist")
1655
1660
  if vflag == "-":
1656
1661
  pass
@@ -2279,7 +2284,7 @@ class AuthSrv(object):
2279
2284
  q = "insert into us values (?,?,?)"
2280
2285
  for uname in self.acct:
2281
2286
  if uname not in ases:
2282
- sid = ub64enc(os.urandom(blen)).decode("utf-8")
2287
+ sid = ub64enc(os.urandom(blen)).decode("ascii")
2283
2288
  cur.execute(q, (uname, sid, int(time.time())))
2284
2289
  ases[uname] = sid
2285
2290
  n.append(uname)
@@ -9,7 +9,7 @@ import queue
9
9
 
10
10
  from .__init__ import CORES, TYPE_CHECKING
11
11
  from .broker_mpw import MpWorker
12
- from .broker_util import ExceptionalQueue, try_exec
12
+ from .broker_util import ExceptionalQueue, NotExQueue, try_exec
13
13
  from .util import Daemon, mp
14
14
 
15
15
  if TYPE_CHECKING:
@@ -104,7 +104,7 @@ class BrokerMp(object):
104
104
  if retq_id:
105
105
  proc.q_pend.put((retq_id, "retq", rv))
106
106
 
107
- def ask(self, dest , *args ) :
107
+ def ask(self, dest , *args ) :
108
108
 
109
109
  # new non-ipc invoking managed service in hub
110
110
  obj = self.hub
@@ -11,7 +11,7 @@ import queue
11
11
 
12
12
  from .__init__ import ANYWIN
13
13
  from .authsrv import AuthSrv
14
- from .broker_util import BrokerCli, ExceptionalQueue
14
+ from .broker_util import BrokerCli, ExceptionalQueue, NotExQueue
15
15
  from .httpsrv import HttpSrv
16
16
  from .util import FAKE_MP, Daemon, HMaccas
17
17
 
@@ -108,7 +108,7 @@ class MpWorker(BrokerCli):
108
108
  else:
109
109
  raise Exception("what is " + str(dest))
110
110
 
111
- def ask(self, dest , *args ) :
111
+ def ask(self, dest , *args ) :
112
112
  retq = ExceptionalQueue(1)
113
113
  retq_id = id(retq)
114
114
  with self.retpend_mutex:
@@ -5,7 +5,7 @@ import os
5
5
  import threading
6
6
 
7
7
  from .__init__ import TYPE_CHECKING
8
- from .broker_util import BrokerCli, ExceptionalQueue, try_exec
8
+ from .broker_util import BrokerCli, ExceptionalQueue, NotExQueue
9
9
  from .httpsrv import HttpSrv
10
10
  from .util import HMaccas
11
11
 
@@ -39,19 +39,14 @@ class BrokerThr(BrokerCli):
39
39
  def noop(self) :
40
40
  pass
41
41
 
42
- def ask(self, dest , *args ) :
42
+ def ask(self, dest , *args ) :
43
43
 
44
44
  # new ipc invoking managed service in hub
45
45
  obj = self.hub
46
46
  for node in dest.split("."):
47
47
  obj = getattr(obj, node)
48
48
 
49
- rv = try_exec(True, obj, *args)
50
-
51
- # pretend we're broker_mp
52
- retq = ExceptionalQueue(1)
53
- retq.put(rv)
54
- return retq
49
+ return NotExQueue(obj(*args)) # type: ignore
55
50
 
56
51
  def say(self, dest , *args ) :
57
52
  if dest == "listen":
@@ -67,4 +62,4 @@ class BrokerThr(BrokerCli):
67
62
  for node in dest.split("."):
68
63
  obj = getattr(obj, node)
69
64
 
70
- try_exec(False, obj, *args)
65
+ obj(*args) # type: ignore
@@ -28,6 +28,18 @@ class ExceptionalQueue(Queue, object):
28
28
  return rv
29
29
 
30
30
 
31
+ class NotExQueue(object):
32
+ """
33
+ BrokerThr uses this instead of ExceptionalQueue; 7x faster
34
+ """
35
+
36
+ def __init__(self, rv ) :
37
+ self.rv = rv
38
+
39
+ def get(self) :
40
+ return self.rv
41
+
42
+
31
43
  class BrokerCli(object):
32
44
  """
33
45
  helps mypy understand httpsrv.broker but still fails a few levels deeper,
@@ -43,7 +55,7 @@ class BrokerCli(object):
43
55
  def __init__(self) :
44
56
  pass
45
57
 
46
- def ask(self, dest , *args ) :
58
+ def ask(self, dest , *args ) :
47
59
  return ExceptionalQueue(1)
48
60
 
49
61
  def say(self, dest , *args ) :
@@ -13,6 +13,7 @@ def vf_bmap() :
13
13
  "dav_rt": "davrt",
14
14
  "ed": "dots",
15
15
  "hardlink_only": "hardlinkonly",
16
+ "no_dirsz": "nodirsz",
16
17
  "no_dupe": "nodupe",
17
18
  "no_forget": "noforget",
18
19
  "no_pipe": "nopipe",
@@ -113,7 +113,6 @@ class Fstab(object):
113
113
  self.srctab = srctab
114
114
 
115
115
  def relabel(self, path , nval ) :
116
- assert self.tab
117
116
  self.cache = {}
118
117
  if ANYWIN:
119
118
  path = self._winpath(path)
@@ -150,7 +149,6 @@ class Fstab(object):
150
149
  self.log("failed to build tab:\n{}".format(min_ex()), 3)
151
150
  self.build_fallback()
152
151
 
153
- assert self.tab
154
152
  ret = self.tab._find(path)[0]
155
153
  if self.trusted or path == ret.vpath:
156
154
  return ret.realpath.split("/")[0]
@@ -161,6 +159,5 @@ class Fstab(object):
161
159
  if not self.tab:
162
160
  self.build_fallback()
163
161
 
164
- assert self.tab
165
162
  ret = self.tab._find(path)[0]
166
163
  return ret.realpath