copyparty 1.16.19__tar.gz → 1.16.21__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 (125) hide show
  1. {copyparty-1.16.19 → copyparty-1.16.21}/PKG-INFO +6 -1
  2. {copyparty-1.16.19 → copyparty-1.16.21}/README.md +5 -0
  3. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/__main__.py +1 -0
  4. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/__version__.py +2 -2
  5. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/httpcli.py +6 -6
  6. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/svchub.py +16 -0
  7. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/szip.py +10 -6
  8. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/tcpsrv.py +1 -1
  9. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/th_srv.py +46 -4
  10. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/browser.css.gz +0 -0
  11. copyparty-1.16.21/copyparty/web/browser.js.gz +0 -0
  12. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/splash.html +1 -1
  13. copyparty-1.16.21/copyparty/web/up2k.js.gz +0 -0
  14. copyparty-1.16.21/copyparty/web/util.js.gz +0 -0
  15. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty.egg-info/PKG-INFO +6 -1
  16. copyparty-1.16.19/copyparty/web/browser.js.gz +0 -0
  17. copyparty-1.16.19/copyparty/web/up2k.js.gz +0 -0
  18. copyparty-1.16.19/copyparty/web/util.js.gz +0 -0
  19. {copyparty-1.16.19 → copyparty-1.16.21}/LICENSE +0 -0
  20. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/__init__.py +0 -0
  21. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/authsrv.py +0 -0
  22. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/bos/__init__.py +0 -0
  23. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/bos/bos.py +0 -0
  24. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/bos/path.py +0 -0
  25. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/broker_mp.py +0 -0
  26. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/broker_mpw.py +0 -0
  27. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/broker_thr.py +0 -0
  28. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/broker_util.py +0 -0
  29. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/cert.py +0 -0
  30. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/cfg.py +0 -0
  31. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/dxml.py +0 -0
  32. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/fsutil.py +0 -0
  33. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/ftpd.py +0 -0
  34. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/httpconn.py +0 -0
  35. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/httpsrv.py +0 -0
  36. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/ico.py +0 -0
  37. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/mdns.py +0 -0
  38. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/metrics.py +0 -0
  39. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/mtag.py +0 -0
  40. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/multicast.py +0 -0
  41. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/pwhash.py +0 -0
  42. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/res/COPYING.txt +0 -0
  43. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/res/__init__.py +0 -0
  44. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/res/insecure.pem +0 -0
  45. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/smbd.py +0 -0
  46. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/ssdp.py +0 -0
  47. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/star.py +0 -0
  48. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/stolen/__init__.py +0 -0
  49. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/stolen/dnslib/__init__.py +0 -0
  50. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/stolen/dnslib/bimap.py +0 -0
  51. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/stolen/dnslib/bit.py +0 -0
  52. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/stolen/dnslib/buffer.py +0 -0
  53. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/stolen/dnslib/dns.py +0 -0
  54. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/stolen/dnslib/label.py +0 -0
  55. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/stolen/dnslib/lex.py +0 -0
  56. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/stolen/dnslib/ranges.py +0 -0
  57. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/stolen/ifaddr/__init__.py +0 -0
  58. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/stolen/ifaddr/_posix.py +0 -0
  59. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/stolen/ifaddr/_shared.py +0 -0
  60. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/stolen/ifaddr/_win32.py +0 -0
  61. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/stolen/qrcodegen.py +0 -0
  62. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/stolen/surrogateescape.py +0 -0
  63. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/sutil.py +0 -0
  64. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/tftpd.py +0 -0
  65. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/th_cli.py +0 -0
  66. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/u2idx.py +0 -0
  67. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/up2k.py +0 -0
  68. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/util.py +0 -0
  69. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/a/__init__.py +0 -0
  70. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/a/partyfuse.py +0 -0
  71. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/a/u2c.py +0 -0
  72. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/a/webdav-cfg.bat +0 -0
  73. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/baguettebox.js.gz +0 -0
  74. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/browser.html +0 -0
  75. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/browser2.html +0 -0
  76. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/cf.html +0 -0
  77. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/dbg-audio.js.gz +0 -0
  78. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/dd/2.png +0 -0
  79. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/dd/3.png +0 -0
  80. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/dd/4.png +0 -0
  81. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/dd/5.png +0 -0
  82. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/dd/__init__.py +0 -0
  83. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/deps/__init__.py +0 -0
  84. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/deps/busy.mp3.gz +0 -0
  85. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/deps/easymde.css.gz +0 -0
  86. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/deps/easymde.js.gz +0 -0
  87. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/deps/fuse.py +0 -0
  88. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/deps/marked.js.gz +0 -0
  89. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/deps/mini-fa.css.gz +0 -0
  90. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/deps/mini-fa.woff +0 -0
  91. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/deps/prism.css.gz +0 -0
  92. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/deps/prism.js.gz +0 -0
  93. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/deps/prismd.css.gz +0 -0
  94. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/deps/scp.woff2 +0 -0
  95. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/deps/sha512.ac.js.gz +0 -0
  96. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/deps/sha512.hw.js.gz +0 -0
  97. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/md.css.gz +0 -0
  98. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/md.html +0 -0
  99. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/md.js.gz +0 -0
  100. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/md2.css.gz +0 -0
  101. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/md2.js.gz +0 -0
  102. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/mde.css.gz +0 -0
  103. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/mde.html +0 -0
  104. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/mde.js.gz +0 -0
  105. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/msg.css.gz +0 -0
  106. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/msg.html +0 -0
  107. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/rups.css.gz +0 -0
  108. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/rups.html +0 -0
  109. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/rups.js.gz +0 -0
  110. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/shares.css.gz +0 -0
  111. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/shares.html +0 -0
  112. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/shares.js.gz +0 -0
  113. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/splash.css.gz +0 -0
  114. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/splash.js.gz +0 -0
  115. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/svcs.html +0 -0
  116. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/svcs.js.gz +0 -0
  117. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/ui.css.gz +0 -0
  118. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty/web/w.hash.js.gz +0 -0
  119. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty.egg-info/SOURCES.txt +0 -0
  120. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty.egg-info/dependency_links.txt +0 -0
  121. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty.egg-info/entry_points.txt +0 -0
  122. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty.egg-info/requires.txt +0 -0
  123. {copyparty-1.16.19 → copyparty-1.16.21}/copyparty.egg-info/top_level.txt +0 -0
  124. {copyparty-1.16.19 → copyparty-1.16.21}/pyproject.toml +0 -0
  125. {copyparty-1.16.19 → copyparty-1.16.21}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: copyparty
3
- Version: 1.16.19
3
+ Version: 1.16.21
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
@@ -205,6 +205,7 @@ just run **[copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/
205
205
  * or if you are on android, [install copyparty in termux](#install-on-android)
206
206
  * or maybe you have a [synology nas / dsm](./docs/synology-dsm.md)
207
207
  * or if your computer is messed up and nothing else works, [try the pyz](#zipapp)
208
+ * or if your OS is dead, give the [bootable flashdrive / cd-rom](https://a.ocv.me/pub/stuff/edcd001/enterprise-edition/) a spin
208
209
  * or if you don't trust copyparty yet and want to isolate it a little, then...
209
210
  * ...maybe [prisonparty](./bin/prisonparty.sh) to create a tiny [chroot](https://wiki.archlinux.org/title/Chroot) (very portable),
210
211
  * ...or [bubbleparty](./bin/bubbleparty.sh) to wrap it in [bubblewrap](https://github.com/containers/bubblewrap) (much better)
@@ -360,6 +361,8 @@ project goals / philosophy
360
361
  * adaptable, malleable, hackable
361
362
  * no build steps; modify the js/python without needing node.js or anything like that
362
363
 
364
+ becoming rich is specifically *not* a motivation, but if you wanna donate then see my [github profile](https://github.com/9001) regarding donations for my FOSS stuff in general (also THANKS!)
365
+
363
366
 
364
367
  ## notes
365
368
 
@@ -788,6 +791,7 @@ select which type of archive you want in the `[⚙️] config` tab:
788
791
  * `up2k.db` and `dir.txt` is always excluded
789
792
  * bsdtar supports streaming unzipping: `curl foo?zip | bsdtar -xv`
790
793
  * good, because copyparty's zip is faster than tar on small files
794
+ * but `?tar` is better for large files, especially if the total exceeds 4 GiB
791
795
  * `zip_crc` will take longer to download since the server has to read each file twice
792
796
  * this is only to support MS-DOS PKZIP v2.04g (october 1993) and older
793
797
  * how are you accessing copyparty actually
@@ -1092,6 +1096,7 @@ click the `play` link next to an audio file, or copy the link target to [share i
1092
1096
 
1093
1097
  open the `[🎺]` media-player-settings tab to configure it,
1094
1098
  * "switches":
1099
+ * `[🔁]` repeats one single song forever
1095
1100
  * `[🔀]` shuffles the files inside each folder
1096
1101
  * `[preload]` starts loading the next track when it's about to end, reduces the silence between songs
1097
1102
  * `[full]` does a full preload by downloading the entire next file; good for unreliable connections, bad for slow connections
@@ -147,6 +147,7 @@ just run **[copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/
147
147
  * or if you are on android, [install copyparty in termux](#install-on-android)
148
148
  * or maybe you have a [synology nas / dsm](./docs/synology-dsm.md)
149
149
  * or if your computer is messed up and nothing else works, [try the pyz](#zipapp)
150
+ * or if your OS is dead, give the [bootable flashdrive / cd-rom](https://a.ocv.me/pub/stuff/edcd001/enterprise-edition/) a spin
150
151
  * or if you don't trust copyparty yet and want to isolate it a little, then...
151
152
  * ...maybe [prisonparty](./bin/prisonparty.sh) to create a tiny [chroot](https://wiki.archlinux.org/title/Chroot) (very portable),
152
153
  * ...or [bubbleparty](./bin/bubbleparty.sh) to wrap it in [bubblewrap](https://github.com/containers/bubblewrap) (much better)
@@ -302,6 +303,8 @@ project goals / philosophy
302
303
  * adaptable, malleable, hackable
303
304
  * no build steps; modify the js/python without needing node.js or anything like that
304
305
 
306
+ becoming rich is specifically *not* a motivation, but if you wanna donate then see my [github profile](https://github.com/9001) regarding donations for my FOSS stuff in general (also THANKS!)
307
+
305
308
 
306
309
  ## notes
307
310
 
@@ -730,6 +733,7 @@ select which type of archive you want in the `[⚙️] config` tab:
730
733
  * `up2k.db` and `dir.txt` is always excluded
731
734
  * bsdtar supports streaming unzipping: `curl foo?zip | bsdtar -xv`
732
735
  * good, because copyparty's zip is faster than tar on small files
736
+ * but `?tar` is better for large files, especially if the total exceeds 4 GiB
733
737
  * `zip_crc` will take longer to download since the server has to read each file twice
734
738
  * this is only to support MS-DOS PKZIP v2.04g (october 1993) and older
735
739
  * how are you accessing copyparty actually
@@ -1034,6 +1038,7 @@ click the `play` link next to an audio file, or copy the link target to [share i
1034
1038
 
1035
1039
  open the `[🎺]` media-player-settings tab to configure it,
1036
1040
  * "switches":
1041
+ * `[🔁]` repeats one single song forever
1037
1042
  * `[🔀]` shuffles the files inside each folder
1038
1043
  * `[preload]` starts loading the next track when it's about to end, reduces the silence between songs
1039
1044
  * `[full]` does a full preload by downloading the entire next file; good for unreliable connections, bad for slow connections
@@ -1369,6 +1369,7 @@ def add_thumbnail(ap):
1369
1369
  ap2.add_argument("--th-r-ffi", metavar="T,T", type=u, default="apng,avif,avifs,bmp,cbz,dds,dib,fit,fits,fts,gif,hdr,heic,heics,heif,heifs,icns,ico,jp2,jpeg,jpg,jpx,jxl,pbm,pcx,pfm,pgm,png,pnm,ppm,psd,qoi,sgi,tga,tif,tiff,webp,xbm,xpm", help="image formats to decode using ffmpeg")
1370
1370
  ap2.add_argument("--th-r-ffv", metavar="T,T", type=u, default="3gp,asf,av1,avc,avi,flv,h264,h265,hevc,m4v,mjpeg,mjpg,mkv,mov,mp4,mpeg,mpeg2,mpegts,mpg,mpg2,mts,nut,ogm,ogv,rm,ts,vob,webm,wmv", help="video formats to decode using ffmpeg")
1371
1371
  ap2.add_argument("--th-r-ffa", metavar="T,T", type=u, default="aac,ac3,aif,aiff,alac,alaw,amr,apac,ape,au,bonk,dfpwm,dts,flac,gsm,ilbc,it,itgz,itxz,itz,m4a,mdgz,mdxz,mdz,mo3,mod,mp2,mp3,mpc,mptm,mt2,mulaw,ogg,okt,opus,ra,s3m,s3gz,s3xz,s3z,tak,tta,ulaw,wav,wma,wv,xm,xmgz,xmxz,xmz,xpk", help="audio formats to decode using ffmpeg")
1372
+ ap2.add_argument("--th-spec-cnv", metavar="T,T", type=u, default="it,itgz,itxz,itz,mdgz,mdxz,mdz,mo3,mod,s3m,s3gz,s3xz,s3z,xm,xmgz,xmxz,xmz,xpk", help="audio formats which provoke https://trac.ffmpeg.org/ticket/10797 (huge ram usage for s3xmodit spectrograms)")
1372
1373
  ap2.add_argument("--au-unpk", metavar="E=F.C", type=u, default="mdz=mod.zip, mdgz=mod.gz, mdxz=mod.xz, s3z=s3m.zip, s3gz=s3m.gz, s3xz=s3m.xz, xmz=xm.zip, xmgz=xm.gz, xmxz=xm.xz, itz=it.zip, itgz=it.gz, itxz=it.xz, cbz=jpg.cbz", help="audio/image formats to decompress before passing to ffmpeg")
1373
1374
 
1374
1375
 
@@ -1,8 +1,8 @@
1
1
  # coding: utf-8
2
2
 
3
- VERSION = (1, 16, 19)
3
+ VERSION = (1, 16, 21)
4
4
  CODENAME = "COPYparty"
5
- BUILD_DT = (2025, 4, 8)
5
+ BUILD_DT = (2025, 4, 20)
6
6
 
7
7
  S_VERSION = ".".join(map(str, VERSION))
8
8
  S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
@@ -1201,11 +1201,6 @@ class HttpCli(object):
1201
1201
  else:
1202
1202
  return self.tx_res(res_path)
1203
1203
 
1204
- if res_path != undot(res_path):
1205
- t = "malicious user; attempted path traversal; req(%r) vp(%r) => %r"
1206
- self.log(t % (self.req, "/" + self.vpath, res_path), 1)
1207
- self.cbonk(self.conn.hsrv.gmal, self.req, "trav", "path traversal")
1208
-
1209
1204
  self.tx_404()
1210
1205
  return False
1211
1206
 
@@ -4231,6 +4226,7 @@ class HttpCli(object):
4231
4226
  self.log(t % (data_end / M, lower / M, upper / M), 6)
4232
4227
  with self.u2mutex:
4233
4228
  if data_end > self.u2fh.aps.get(ap_data, data_end):
4229
+ fhs = None
4234
4230
  try:
4235
4231
  fhs = self.u2fh.cache[ap_data].all_fhs
4236
4232
  for fh in fhs:
@@ -4238,7 +4234,11 @@ class HttpCli(object):
4238
4234
  self.u2fh.aps[ap_data] = data_end
4239
4235
  self.log("pipe: flushed %d up2k-FDs" % (len(fhs),))
4240
4236
  except Exception as ex:
4241
- self.log("pipe: u2fh flush failed: %r" % (ex,))
4237
+ if fhs is None:
4238
+ err = "file is not being written to right now"
4239
+ else:
4240
+ err = repr(ex)
4241
+ self.log("pipe: u2fh flush failed: " + err)
4242
4242
 
4243
4243
  if lower >= data_end:
4244
4244
  if data_end:
@@ -760,6 +760,7 @@ class SvcHub(object):
760
760
  self.log("optional-dependencies", t, 6)
761
761
 
762
762
  def _check_env(self) :
763
+ al = self.args
763
764
  try:
764
765
  files = os.listdir(E.cfg)
765
766
  except:
@@ -776,6 +777,21 @@ class SvcHub(object):
776
777
  if self.args.bauth_last:
777
778
  self.log("root", "WARNING: ignoring --bauth-last due to --no-bauth", 3)
778
779
 
780
+ have_tcp = False
781
+ for zs in al.i:
782
+ if not zs.startswith("unix:"):
783
+ have_tcp = True
784
+ if not have_tcp:
785
+ zb = False
786
+ zs = "z zm zm4 zm6 zmv zmvv zs zsv zv"
787
+ for zs in zs.split():
788
+ if getattr(al, zs, False):
789
+ setattr(al, zs, False)
790
+ zb = True
791
+ if zb:
792
+ t = "only listening on unix-sockets; cannot enable zeroconf/mdns/ssdp as requested"
793
+ self.log("root", t, 3)
794
+
779
795
  if not self.args.no_dav:
780
796
  from .dxml import DXML_OK
781
797
 
@@ -48,6 +48,7 @@ def gen_fdesc(sz , crc32 , z64 ) :
48
48
 
49
49
  def gen_hdr(
50
50
  h_pos ,
51
+ z64 ,
51
52
  fn ,
52
53
  sz ,
53
54
  lastmod ,
@@ -64,7 +65,6 @@ def gen_hdr(
64
65
  # appnote 4.5 / zip 3.0 (2008) / unzip 6.0 (2009) says to add z64
65
66
  # extinfo for values which exceed H, but that becomes an off-by-one
66
67
  # (can't tell if it was clamped or exactly maxval), make it obvious
67
- z64 = sz >= 0xFFFFFFFF
68
68
  z64v = [sz, sz] if z64 else []
69
69
  if h_pos and h_pos >= 0xFFFFFFFF:
70
70
  # central, also consider ptr to original header
@@ -238,6 +238,7 @@ class StreamZip(StreamArc):
238
238
 
239
239
  sz = st.st_size
240
240
  ts = st.st_mtime
241
+ h_pos = self.pos
241
242
 
242
243
  crc = 0
243
244
  if self.pre_crc:
@@ -246,8 +247,12 @@ class StreamZip(StreamArc):
246
247
 
247
248
  crc &= 0xFFFFFFFF
248
249
 
249
- h_pos = self.pos
250
- buf = gen_hdr(None, name, sz, ts, self.utf8, crc, self.pre_crc)
250
+ # some unzip-programs expect a 64bit data-descriptor
251
+ # even if the only 32bit-exceeding value is the offset,
252
+ # so force that by placeholdering the filesize too
253
+ z64 = h_pos >= 0xFFFFFFFF or sz >= 0xFFFFFFFF
254
+
255
+ buf = gen_hdr(None, z64, name, sz, ts, self.utf8, crc, self.pre_crc)
251
256
  yield self._ct(buf)
252
257
 
253
258
  for buf in yieldfile(src, self.args.iobuf):
@@ -260,8 +265,6 @@ class StreamZip(StreamArc):
260
265
 
261
266
  self.items.append((name, sz, ts, crc, h_pos))
262
267
 
263
- z64 = sz >= 4 * 1024 * 1024 * 1024
264
-
265
268
  if z64 or not self.pre_crc:
266
269
  buf = gen_fdesc(sz, crc, z64)
267
270
  yield self._ct(buf)
@@ -300,7 +303,8 @@ class StreamZip(StreamArc):
300
303
 
301
304
  cdir_pos = self.pos
302
305
  for name, sz, ts, crc, h_pos in self.items:
303
- buf = gen_hdr(h_pos, name, sz, ts, self.utf8, crc, self.pre_crc)
306
+ z64 = h_pos >= 0xFFFFFFFF or sz >= 0xFFFFFFFF
307
+ buf = gen_hdr(h_pos, z64, name, sz, ts, self.utf8, crc, self.pre_crc)
304
308
  mbuf += self._ct(buf)
305
309
  if len(mbuf) >= 16384:
306
310
  yield mbuf
@@ -563,7 +563,7 @@ class TcpSrv(object):
563
563
  ip = None
564
564
  ips = list(t1) + list(t2)
565
565
  qri = self.args.qri
566
- if self.args.zm and not qri:
566
+ if self.args.zm and not qri and ips:
567
567
  name = self.args.name + ".local"
568
568
  t1[name] = next(v for v in (t1 or t2).values())
569
569
  ips = [name] + ips
@@ -7,6 +7,7 @@ import os
7
7
  import re
8
8
  import shutil
9
9
  import subprocess as sp
10
+ import tempfile
10
11
  import threading
11
12
  import time
12
13
 
@@ -19,6 +20,7 @@ from .mtag import HAVE_FFMPEG, HAVE_FFPROBE, au_unpk, ffprobe
19
20
  from .util import BytesIO # type: ignore
20
21
  from .util import (
21
22
  FFMPEG_URL,
23
+ VF_CAREFUL,
22
24
  Cooldown,
23
25
  Daemon,
24
26
  afsenc,
@@ -46,6 +48,7 @@ HAVE_WEBP = False
46
48
 
47
49
  EXTS_TH = set(["jpg", "webp", "png"])
48
50
  EXTS_AC = set(["opus", "owa", "caf", "mp3"])
51
+ EXTS_SPEC_SAFE = set("aif aiff flac mp3 opus wav".split())
49
52
 
50
53
  PTN_TS = re.compile("^-?[0-9a-f]{8,10}$")
51
54
 
@@ -164,12 +167,15 @@ class ThumbSrv(object):
164
167
 
165
168
  self.mutex = threading.Lock()
166
169
  self.busy = {}
170
+ self.untemp = {}
167
171
  self.ram = {}
168
172
  self.memcond = threading.Condition(self.mutex)
169
173
  self.stopping = False
170
174
  self.rm_nullthumbs = True # forget failed conversions on startup
171
175
  self.nthr = max(1, self.args.th_mt)
172
176
 
177
+ self.exts_spec_unsafe = set(self.args.th_spec_cnv.split(","))
178
+
173
179
  self.q = Queue(self.nthr * 4)
174
180
  for n in range(self.nthr):
175
181
  Daemon(self.worker, "thumb-{}-{}".format(n, self.nthr))
@@ -410,10 +416,18 @@ class ThumbSrv(object):
410
416
  self.log(t % (ttpath, tpath, ex), 3)
411
417
  pass
412
418
 
419
+ untemp = []
413
420
  with self.mutex:
414
421
  subs = self.busy[tpath]
415
422
  del self.busy[tpath]
416
423
  self.ram.pop(ttpath, None)
424
+ untemp = self.untemp.pop(ttpath, None) or []
425
+
426
+ for ap in untemp:
427
+ try:
428
+ wunlink(self.log, ap, VF_CAREFUL)
429
+ except:
430
+ pass
417
431
 
418
432
  for x in subs:
419
433
  with x:
@@ -666,15 +680,43 @@ class ThumbSrv(object):
666
680
  if "ac" not in ret:
667
681
  raise Exception("not audio")
668
682
 
683
+ fext = abspath.split(".")[-1].lower()
684
+
669
685
  # https://trac.ffmpeg.org/ticket/10797
670
686
  # expect 1 GiB every 600 seconds when duration is tricky;
671
687
  # simple filetypes are generally safer so let's special-case those
672
- safe = ("flac", "wav", "aif", "aiff", "opus")
673
- coeff = 1800 if abspath.split(".")[-1].lower() in safe else 600
674
- dur = ret[".dur"][1] if ".dur" in ret else 300
688
+ coeff = 1800 if fext in EXTS_SPEC_SAFE else 600
689
+ dur = ret[".dur"][1] if ".dur" in ret else 900
675
690
  need = 0.2 + dur / coeff
676
691
  self.wait4ram(need, tpath)
677
692
 
693
+ infile = abspath
694
+ if dur >= 900 or fext in self.exts_spec_unsafe:
695
+ with tempfile.NamedTemporaryFile(suffix=".spec.flac", delete=False) as f:
696
+ f.write(b"h")
697
+ infile = f.name
698
+ try:
699
+ self.untemp[tpath].append(infile)
700
+ except:
701
+ self.untemp[tpath] = [infile]
702
+
703
+ # fmt: off
704
+ cmd = [
705
+ b"ffmpeg",
706
+ b"-nostdin",
707
+ b"-v", b"error",
708
+ b"-hide_banner",
709
+ b"-i", fsenc(abspath),
710
+ b"-map", b"0:a:0",
711
+ b"-ac", b"1",
712
+ b"-ar", b"48000",
713
+ b"-sample_fmt", b"s16",
714
+ b"-t", b"900",
715
+ b"-y", fsenc(infile),
716
+ ]
717
+ # fmt: on
718
+ self._run_ff(cmd, vn)
719
+
678
720
  fc = "[0:a:0]aresample=48000{},showspectrumpic=s="
679
721
  if "3" in fmt:
680
722
  fc += "1280x1024,crop=1420:1056:70:48[o]"
@@ -694,7 +736,7 @@ class ThumbSrv(object):
694
736
  b"-nostdin",
695
737
  b"-v", b"error",
696
738
  b"-hide_banner",
697
- b"-i", fsenc(abspath),
739
+ b"-i", fsenc(infile),
698
740
  b"-filter_complex", fc.encode("utf-8"),
699
741
  b"-map", b"[o]",
700
742
  b"-frames:v", b"1",
@@ -122,7 +122,7 @@
122
122
  <input type="hidden" id="la" name="act" value="login" />
123
123
  <input type="password" id="lp" name="cppwd" placeholder=" password" />
124
124
  <input type="hidden" name="uhash" id="uhash" value="x" />
125
- <input type="submit" id="ls" value="Login" />
125
+ <input type="submit" id="ls" value="login" />
126
126
  {% if chpw %}
127
127
  <a id="x" href="#">change password</a>
128
128
  {% endif %}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: copyparty
3
- Version: 1.16.19
3
+ Version: 1.16.21
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
@@ -205,6 +205,7 @@ just run **[copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/
205
205
  * or if you are on android, [install copyparty in termux](#install-on-android)
206
206
  * or maybe you have a [synology nas / dsm](./docs/synology-dsm.md)
207
207
  * or if your computer is messed up and nothing else works, [try the pyz](#zipapp)
208
+ * or if your OS is dead, give the [bootable flashdrive / cd-rom](https://a.ocv.me/pub/stuff/edcd001/enterprise-edition/) a spin
208
209
  * or if you don't trust copyparty yet and want to isolate it a little, then...
209
210
  * ...maybe [prisonparty](./bin/prisonparty.sh) to create a tiny [chroot](https://wiki.archlinux.org/title/Chroot) (very portable),
210
211
  * ...or [bubbleparty](./bin/bubbleparty.sh) to wrap it in [bubblewrap](https://github.com/containers/bubblewrap) (much better)
@@ -360,6 +361,8 @@ project goals / philosophy
360
361
  * adaptable, malleable, hackable
361
362
  * no build steps; modify the js/python without needing node.js or anything like that
362
363
 
364
+ becoming rich is specifically *not* a motivation, but if you wanna donate then see my [github profile](https://github.com/9001) regarding donations for my FOSS stuff in general (also THANKS!)
365
+
363
366
 
364
367
  ## notes
365
368
 
@@ -788,6 +791,7 @@ select which type of archive you want in the `[⚙️] config` tab:
788
791
  * `up2k.db` and `dir.txt` is always excluded
789
792
  * bsdtar supports streaming unzipping: `curl foo?zip | bsdtar -xv`
790
793
  * good, because copyparty's zip is faster than tar on small files
794
+ * but `?tar` is better for large files, especially if the total exceeds 4 GiB
791
795
  * `zip_crc` will take longer to download since the server has to read each file twice
792
796
  * this is only to support MS-DOS PKZIP v2.04g (october 1993) and older
793
797
  * how are you accessing copyparty actually
@@ -1092,6 +1096,7 @@ click the `play` link next to an audio file, or copy the link target to [share i
1092
1096
 
1093
1097
  open the `[🎺]` media-player-settings tab to configure it,
1094
1098
  * "switches":
1099
+ * `[🔁]` repeats one single song forever
1095
1100
  * `[🔀]` shuffles the files inside each folder
1096
1101
  * `[preload]` starts loading the next track when it's about to end, reduces the silence between songs
1097
1102
  * `[full]` does a full preload by downloading the entire next file; good for unreliable connections, bad for slow connections
Binary file
Binary file
File without changes
File without changes
File without changes