copyparty 1.19.3__py3-none-any.whl → 1.19.5__py3-none-any.whl

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/__main__.py CHANGED
@@ -431,7 +431,7 @@ def args_from_cfg(cfg_path ) :
431
431
  def expand_cfg(argv) :
432
432
  if CFG_DEF:
433
433
  supp = args_from_cfg(CFG_DEF[0])
434
- argv = supp + argv
434
+ argv = argv[:1] + supp + argv[1:]
435
435
 
436
436
  n = 0
437
437
  while n < len(argv):
@@ -767,7 +767,7 @@ def get_sects():
767
767
  \033[36mc0\033[35m show all process output (default)
768
768
  \033[36mc1\033[35m show only stderr
769
769
  \033[36mc2\033[35m show only stdout
770
- \033[36mc3\033[35m mute all process otput
770
+ \033[36mc3\033[35m mute all process output
771
771
  \033[0m
772
772
  examples:
773
773
 
@@ -1106,6 +1106,8 @@ def add_qr(ap, tty):
1106
1106
  ap2.add_argument("--qrp", metavar="CELLS", type=int, default=4, help="padding (spec says 4 or more, but 1 is usually fine)")
1107
1107
  ap2.add_argument("--qrz", metavar="N", type=int, default=0, help="[\033[32m1\033[0m]=1x, [\033[32m2\033[0m]=2x, [\033[32m0\033[0m]=auto (try [\033[32m2\033[0m] on broken fonts)")
1108
1108
  ap2.add_argument("--qr-pin", metavar="N", type=int, default=0, help="sticky/pin the qr-code to always stay on-screen; [\033[32m0\033[0m]=disabled, [\033[32m1\033[0m]=with-url, [\033[32m2\033[0m]=just-qr")
1109
+ ap2.add_argument("--qr-wait", metavar="SEC", type=float, default=0, help="wait \033[33mSEC\033[0m before printing the qr-code to the log")
1110
+ ap2.add_argument("--qr-file", metavar="TXT", type=u, action="append", help="\033[34mREPEATABLE:\033[0m write qr-code to file.\n └─To create txt or svg, \033[33mTXT\033[0m is Filepath:Zoom:Pad, for example [\033[32mqr.txt:1:2\033[0m]\n └─To create png or gif, \033[33mTXT\033[0m is Filepath:Zoom:Pad:Foreground:Background, for example [\033[32mqr.png:8:2:333333:ffcc55\033[0m], or [\033[32mqr.png:8:2::ffcc55\033[0m] for transparent")
1109
1111
 
1110
1112
 
1111
1113
  def add_fs(ap):
copyparty/__version__.py CHANGED
@@ -1,8 +1,8 @@
1
1
  # coding: utf-8
2
2
 
3
- VERSION = (1, 19, 3)
3
+ VERSION = (1, 19, 5)
4
4
  CODENAME = "usernames"
5
- BUILD_DT = (2025, 8, 17)
5
+ BUILD_DT = (2025, 8, 21)
6
6
 
7
7
  S_VERSION = ".".join(map(str, VERSION))
8
8
  S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
copyparty/authsrv.py CHANGED
@@ -1320,6 +1320,10 @@ class AuthSrv(object):
1320
1320
  zt = split_cfg_ln(ln)
1321
1321
  for zs, za in zt.items():
1322
1322
  zs = zs.lstrip("-")
1323
+ if "=" in zs:
1324
+ t = "WARNING: found an option named [%s] in your [global] config; did you mean to say [%s: %s] instead?"
1325
+ zs1, zs2 = zs.split("=", 1)
1326
+ self.log(t % (zs, zs1, zs2), 3)
1323
1327
  if za is True:
1324
1328
  self._e("└─argument [{}]".format(zs))
1325
1329
  else:
@@ -1329,6 +1333,10 @@ class AuthSrv(object):
1329
1333
  if cat == cata:
1330
1334
  try:
1331
1335
  u, p = [zs.strip() for zs in ln.split(":", 1)]
1336
+ if "=" in u and not p:
1337
+ t = "WARNING: found username [%s] in your [accounts] config; did you mean to say [%s: %s] instead?"
1338
+ zs1, zs2 = u.split("=", 1)
1339
+ self.log(t % (u, zs1, zs2), 3)
1332
1340
  self._l(ln, 5, "account [{}], password [{}]".format(u, p))
1333
1341
  acct[u] = p
1334
1342
  except:
@@ -1399,6 +1407,10 @@ class AuthSrv(object):
1399
1407
  zd = split_cfg_ln(ln)
1400
1408
  fstr = ""
1401
1409
  for sk, sv in zd.items():
1410
+ if "=" in sk:
1411
+ t = "WARNING: found a volflag named [%s] in your config; did you mean to say [%s: %s] instead?"
1412
+ zs1, zs2 = sk.split("=", 1)
1413
+ self.log(t % (sk, zs1, zs2), 3)
1402
1414
  bad = re.sub(r"[a-z0-9_-]", "", sk).lstrip("-")
1403
1415
  if bad:
1404
1416
  err = "bad characters [{}] in volflag name [{}]; "
copyparty/ftpd.py CHANGED
@@ -64,13 +64,13 @@ class FtpAuth(DummyAuthorizer):
64
64
  if ip.startswith("::ffff:"):
65
65
  ip = ip[7:]
66
66
 
67
- ip = ipnorm(ip)
67
+ ipn = ipnorm(ip)
68
68
  bans = self.hub.bans
69
- if ip in bans:
70
- rt = bans[ip] - time.time()
69
+ if ipn in bans:
70
+ rt = bans[ipn] - time.time()
71
71
  if rt < 0:
72
72
  logging.info("client unbanned")
73
- del bans[ip]
73
+ del bans[ipn]
74
74
  else:
75
75
  raise AuthenticationFailed("banned")
76
76
 
copyparty/httpcli.py CHANGED
@@ -389,10 +389,10 @@ class HttpCli(object):
389
389
  zsl = [
390
390
  " rproxy: %d if this client's IP-address is [%s]"
391
391
  % (-1 - zd, zs.strip())
392
- for zd, zs in enumerate(zsl)
392
+ for zd, zs in enumerate(zsl[::-1])
393
393
  ]
394
- t = 'could not determine the client\'s IP-address because the global-option --rproxy has not been configured, so the request-header [%s] specified by global-option --xff-hdr cannot be used safely! Please see the "reverse-proxy" section in the readme. The best approach is to configure your reverse-proxy to give copyparty the exact IP-address to assume (perhaps in another header), but you may also try the following:'
395
- t = t % (self.args.xff_hdr,)
394
+ t = 'could not determine the client\'s IP-address because the global-option --rproxy has not been configured, so the request-header [%s] specified by global-option --xff-hdr cannot be used safely! The raw header value was [%s]. Please see the "reverse-proxy" section in the readme. The best approach is to configure your reverse-proxy to give copyparty the exact IP-address to assume (perhaps in another header), but you may also try the following:'
395
+ t = t % (self.args.xff_hdr, zso)
396
396
  self.log("%s\n\n%s\n" % (t, "\n".join(zsl)), 3)
397
397
 
398
398
  pip = self.conn.addr[0]
@@ -195,6 +195,25 @@ class QrCode(object):
195
195
 
196
196
  return "\n".join(rows)
197
197
 
198
+ def to_png(self, zoom, pad, bg, fg, ap) :
199
+ from PIL import Image
200
+
201
+ tab = self.modules
202
+ sz = self.size
203
+ psz = sz + pad * 2
204
+ if bg:
205
+ img = Image.new("RGB", (psz, psz), bg)
206
+ else:
207
+ img = Image.new("RGBA", (psz, psz), (0, 0, 0, 0))
208
+ fg = (fg[0], fg[1], fg[2], 255)
209
+ for y in range(sz):
210
+ for x in range(sz):
211
+ if tab[y][x]:
212
+ img.putpixel((x + pad, y + pad), fg)
213
+ if zoom != 1:
214
+ img = img.resize((sz * zoom, sz * zoom), Image.Resampling.NEAREST)
215
+ img.save(ap)
216
+
198
217
  def _draw_function_patterns(self) :
199
218
  # Draw horizontal and vertical timing patterns
200
219
  for i in range(self.size):
copyparty/svchub.py CHANGED
@@ -427,7 +427,7 @@ class SvcHub(object):
427
427
 
428
428
  # create netmaps early to avoid firewall gaps,
429
429
  # but the mutex blocks multiprocessing startup
430
- for zs in "ipu_iu ftp_ipa_nm tftp_ipa_nm".split():
430
+ for zs in "ipu_nm ftp_ipa_nm tftp_ipa_nm".split():
431
431
  try:
432
432
  getattr(args, zs).mutex = threading.Lock()
433
433
  except:
@@ -809,6 +809,10 @@ class SvcHub(object):
809
809
  t = "%s\033[s\033[1;%dr\033[%dH%s%s\033[u" % (t, sh - 1, sh, qr, url)
810
810
  self.pr(t, file=sys.stderr)
811
811
 
812
+ def sleepy_qr(self):
813
+ time.sleep(self.args.qr_wait)
814
+ self.log("qr-code", self.tcpsrv.qr)
815
+
812
816
  def cb_httpsrv_up(self) :
813
817
  self.httpsrv_up += 1
814
818
  if self.httpsrv_up != self.broker.num_workers:
@@ -824,7 +828,10 @@ class SvcHub(object):
824
828
  if self.args.qr_pin:
825
829
  self.sticky_qr()
826
830
  else:
827
- self.log("qr-code", self.tcpsrv.qr)
831
+ if self.args.qr_wait:
832
+ Daemon(self.sleepy_qr, "qr_w8")
833
+ else:
834
+ self.log("qr-code", self.tcpsrv.qr)
828
835
  else:
829
836
  self.log("root", "workers OK\n")
830
837
 
copyparty/tcpsrv.py CHANGED
@@ -9,7 +9,7 @@ import time
9
9
 
10
10
  from .__init__ import ANYWIN, PY2, TYPE_CHECKING, unicode
11
11
  from .cert import gencert
12
- from .stolen.qrcodegen import QrCode
12
+ from .stolen.qrcodegen import QrCode, qr2svg
13
13
  from .util import (
14
14
  E_ACCESS,
15
15
  E_ADDR_IN_USE,
@@ -618,6 +618,10 @@ class TcpSrv(object):
618
618
  pad = self.args.qrp
619
619
  zoom = self.args.qrz
620
620
  qrc = QrCode.encode_binary(btxt)
621
+
622
+ for zs in self.args.qr_file or []:
623
+ self._qr2file(qrc, zs)
624
+
621
625
  if zoom == 0:
622
626
  try:
623
627
  tw, th = termsize()
@@ -633,6 +637,8 @@ class TcpSrv(object):
633
637
  halfc = "\033[40;48;5;{0}m{1}\033[47;48;5;{2}m"
634
638
  if not fg:
635
639
  halfc = "\033[0;40m{1}\033[0;47m"
640
+ if nocolor:
641
+ halfc = "\033[0;7m{1}\033[0m"
636
642
 
637
643
  def ansify(m ) :
638
644
  return halfc.format(fg, " " * len(m.group(1)), bg)
@@ -651,3 +657,29 @@ class TcpSrv(object):
651
657
  t = t.replace("\n", "`\n`")
652
658
 
653
659
  return txt + t
660
+
661
+ def _qr2file(self, qrc , txt ):
662
+ if ".txt:" in txt or ".svg:" in txt:
663
+ ap, zs1, zs2 = txt.rsplit(":", 2)
664
+ bg = fg = ""
665
+ else:
666
+ ap, zs1, zs2, bg, fg = txt.rsplit(":", 4)
667
+ zoom = int(zs1)
668
+ pad = int(zs2)
669
+
670
+ if ap.endswith(".txt"):
671
+ if zoom not in (1, 2):
672
+ raise Exception("invalid zoom for qr.txt; must be 1 or 2")
673
+ with open(ap, "wb") as f:
674
+ f.write(qrc.render(zoom, pad).encode("utf-8"))
675
+ elif ap.endswith(".svg"):
676
+ with open(ap, "wb") as f:
677
+ f.write(qr2svg(qrc, pad).encode("utf-8"))
678
+ else:
679
+ qrc.to_png(zoom, pad, self._h2i(bg), self._h2i(fg), ap)
680
+
681
+ def _h2i(self, hs):
682
+ try:
683
+ return tuple(int(hs[i : i + 2], 16) for i in (0, 2, 4))
684
+ except:
685
+ return None
Binary file
Binary file
copyparty/web/md.js.gz CHANGED
Binary file
copyparty/web/up2k.js.gz CHANGED
Binary file
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: copyparty
3
- Version: 1.19.3
3
+ Version: 1.19.5
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
@@ -177,6 +177,7 @@ made in Norway 🇳🇴
177
177
  * [packages](#packages) - the party might be closer than you think
178
178
  * [arch package](#arch-package) - `pacman -S copyparty` (in [arch linux extra](https://archlinux.org/packages/extra/any/copyparty/))
179
179
  * [fedora package](#fedora-package) - does not exist yet
180
+ * [homebrew formulae](#homebrew-formulae) - `brew install copyparty ffmpeg`
180
181
  * [nix package](#nix-package) - `nix profile install github:9001/copyparty`
181
182
  * [nixos module](#nixos-module)
182
183
  * [browser support](#browser-support) - TLDR: yes
@@ -206,6 +207,7 @@ made in Norway 🇳🇴
206
207
  * [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+)
207
208
  * [zipapp](#zipapp) - another emergency alternative, [copyparty.pyz](https://github.com/9001/copyparty/releases/latest/download/copyparty.pyz)
208
209
  * [install on android](#install-on-android)
210
+ * [install on iOS](#install-on-iOS)
209
211
  * [reporting bugs](#reporting-bugs) - ideas for context to include, and where to submit them
210
212
  * [devnotes](#devnotes) - for build instructions etc, see [./docs/devnotes.md](./docs/devnotes.md)
211
213
 
@@ -220,6 +222,7 @@ just run **[copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/
220
222
  * or if you cannot install python, you can use [copyparty.exe](#copypartyexe) instead
221
223
  * or install [on arch](#arch-package) ╱ [on NixOS](#nixos-module) ╱ [through nix](#nix-package)
222
224
  * or if you are on android, [install copyparty in termux](#install-on-android)
225
+ * or maybe an iPhone or iPad? [install in a-Shell on iOS](#install-on-iOS)
223
226
  * or maybe you have a [synology nas / dsm](./docs/synology-dsm.md)
224
227
  * or if you have [uv](https://docs.astral.sh/uv/) installed, run `uv tool run copyparty`
225
228
  * or if your computer is messed up and nothing else works, [try the pyz](#zipapp)
@@ -306,7 +309,7 @@ also see [comparison to similar software](./docs/versus.md)
306
309
  * ☑ [upnp / zeroconf / mdns / ssdp](#zeroconf)
307
310
  * ☑ [event hooks](#event-hooks) / script runner
308
311
  * ☑ [reverse-proxy support](https://github.com/9001/copyparty#reverse-proxy)
309
- * ☑ cross-platform (Windows, Linux, Macos, Android, FreeBSD, arm32/arm64, ppc64le, s390x, risc-v/riscv64)
312
+ * ☑ cross-platform (Windows, Linux, Macos, Android, iOS, FreeBSD, arm32/arm64, ppc64le, s390x, risc-v/riscv64)
310
313
  * upload
311
314
  * ☑ basic: plain multipart, ie6 support
312
315
  * ☑ [up2k](#uploading): js, resumable, multithreaded
@@ -329,7 +332,7 @@ also see [comparison to similar software](./docs/versus.md)
329
332
  * ☑ play video files as audio (converted on server)
330
333
  * ☑ create and play [m3u8 playlists](#playlists)
331
334
  * ☑ image gallery with webm player
332
- * ☑ [textfile browser](#textfile-viewer) with syntax hilighting
335
+ * ☑ [textfile browser](#textfile-viewer) with syntax highlighting
333
336
  * ☑ realtime streaming of growing files (logfiles and such)
334
337
  * ☑ [thumbnails](#thumbnails)
335
338
  * ☑ ...of images using Pillow, pyvips, or FFmpeg
@@ -896,7 +899,7 @@ the up2k UI is the epitome of polished intuitive experiences:
896
899
  * `[🔎]` switch between upload and [file-search](#file-search) mode
897
900
  * ignore `[🔎]` if you add files by dragging them into the browser
898
901
 
899
- and then theres the tabs below it,
902
+ and then there's the tabs below it,
900
903
  * `[ok]` is the files which completed successfully
901
904
  * `[ng]` is the ones that failed / got rejected (already exists, ...)
902
905
  * `[done]` shows a combined list of `[ok]` and `[ng]`, chronological order
@@ -1128,7 +1131,7 @@ plays almost every audio format there is (if the server has FFmpeg installed fo
1128
1131
 
1129
1132
  the following audio formats are usually always playable, even without FFmpeg: `aac|flac|m4a|mp3|ogg|opus|wav`
1130
1133
 
1131
- some hilights:
1134
+ some highlights:
1132
1135
  * OS integration; control playback from your phone's lockscreen ([windows](https://user-images.githubusercontent.com/241032/233213022-298a98ba-721a-4cf1-a3d4-f62634bc53d5.png) // [iOS](https://user-images.githubusercontent.com/241032/142711926-0700be6c-3e31-47b3-9928-53722221f722.png) // [android](https://user-images.githubusercontent.com/241032/233212311-a7368590-08c7-4f9f-a1af-48ccf3f36fad.png))
1133
1136
  * shows the audio waveform in the seekbar
1134
1137
  * not perfectly gapless but can get really close (see settings + eq below); good enough to enjoy gapless albums as intended
@@ -1359,6 +1362,12 @@ print a qr-code [(screenshot)](https://user-images.githubusercontent.com/241032/
1359
1362
  * `--qrl lootbox/?pw=hunter2` appends to the url, linking to the `lootbox` folder with password `hunter2`
1360
1363
  * `--qrz 1` forces 1x zoom instead of autoscaling to fit the terminal size
1361
1364
  * 1x may render incorrectly on some terminals/fonts, but 2x should always work
1365
+ * `--qr-pin 1` makes the qr-code stick to the bottom of the console (never scrolls away)
1366
+ * `--qr-file qr.txt:1:2` writes a small qr-code to `qr.txt`
1367
+ * `--qr-file qr.txt:2:2` writes a big qr-code to `qr.txt`
1368
+ * `--qr-file qr.svg:1:2` writes a vector-graphics qr-code to `qr.svg`
1369
+ * `--qr-file qr.png:8:4:333333:ffcc55` writes an 8x-magnified yellow-on-gray `qr.png`
1370
+ * `--qr-file qr.png:8:4::ffffff` writes an 8x-magnified white-on-transparent `qr.png`
1362
1371
 
1363
1372
  it uses the server hostname if [mdns](#mdns) is enabled, otherwise it'll use your external ip (default route) unless `--qri` specifies a specific ip-prefix or domain
1364
1373
 
@@ -1383,6 +1392,14 @@ some recommended FTP / FTPS clients; `wark` = example password:
1383
1392
  * `lftp -u k,wark -p 3921 127.0.0.1 -e ls`
1384
1393
  * `lftp -u k,wark -p 3990 127.0.0.1 -e 'set ssl:verify-certificate no; ls'`
1385
1394
 
1395
+ config file example, which restricts FTP to only use ports 3921 and 12000-12099 so all of those ports must be opened in your firewall:
1396
+
1397
+ ```yaml
1398
+ [global]
1399
+ ftp: 3921
1400
+ ftp-pr: 12000-12099
1401
+ ```
1402
+
1386
1403
 
1387
1404
  ## webdav server
1388
1405
 
@@ -2225,7 +2242,7 @@ when connecting the reverse-proxy to `127.0.0.1` instead (the basic and/or old-f
2225
2242
 
2226
2243
  in summary, `haproxy > caddy > traefik > nginx > apache > lighttpd`, and use uds when possible (traefik does not support it yet)
2227
2244
 
2228
- * if these results are bullshit because my config exampels are bad, please submit corrections!
2245
+ * if these results are bullshit because my config examples are bad, please submit corrections!
2229
2246
 
2230
2247
 
2231
2248
  ## permanent cloudflare tunnel
@@ -2396,6 +2413,15 @@ after installing, start either the system service or the user service and naviga
2396
2413
  does not exist yet; there are rumours that it is being packaged! keep an eye on this space...
2397
2414
 
2398
2415
 
2416
+ ## homebrew formulae
2417
+
2418
+ `brew install copyparty ffmpeg` -- https://formulae.brew.sh/formula/copyparty
2419
+
2420
+ should work on all macs (both intel and apple silicon) and all relevant macos versions
2421
+
2422
+ the homebrew package is maintained by the homebrew team (thanks!)
2423
+
2424
+
2399
2425
  ## nix package
2400
2426
 
2401
2427
  `nix profile install github:9001/copyparty`
@@ -2409,7 +2435,7 @@ some recommended dependencies are enabled by default; [override the package](htt
2409
2435
 
2410
2436
  ## nixos module
2411
2437
 
2412
- for this setup, you will need a [flake-enabled](https://nixos.wiki/wiki/Flakes) installation of NixOS.
2438
+ for [flake-enabled](https://nixos.wiki/wiki/Flakes) installations of NixOS:
2413
2439
 
2414
2440
  ```nix
2415
2441
  {
@@ -2436,6 +2462,33 @@ for this setup, you will need a [flake-enabled](https://nixos.wiki/wiki/Flakes)
2436
2462
  }
2437
2463
  ```
2438
2464
 
2465
+ if you don't use a flake in your configuration, you can use other dependency management tools like [npins](https://github.com/andir/npins), [niv](https://github.com/nmattia/niv), or even plain [`fetchTarball`](https://nix.dev/manual/nix/stable/language/builtins#builtins-fetchTarball), like so:
2466
+
2467
+ ```nix
2468
+ { pkgs, ... }:
2469
+
2470
+ let
2471
+ # npins example, adjust for your setup. copyparty should be a path to the downloaded repo
2472
+ # for niv, just replace the npins folder import with the sources.nix file
2473
+ copyparty = (import ./npins).copyparty;
2474
+
2475
+ # or with fetchTarball:
2476
+ copyparty = fetchTarball "https://github.com/9001/copyparty/archive/hovudstraum.tar.gz";
2477
+ in
2478
+
2479
+ {
2480
+ # load the copyparty NixOS module
2481
+ imports = [ "${copyparty}/contrib/nixos/modules/copyparty.nix" ];
2482
+
2483
+ # add the copyparty overlay to expose the package to the module
2484
+ nixpkgs.overlays = [ (import "${copyparty}/contrib/package/nix/overlay.nix") ];
2485
+ # (optional) install the package globally
2486
+ environment.systemPackages = [ pkgs.copyparty ];
2487
+ # configure the copyparty module
2488
+ services.copyparty.enable = true;
2489
+ }
2490
+ ```
2491
+
2439
2492
  copyparty on NixOS is configured via `services.copyparty` options, for example:
2440
2493
  ```nix
2441
2494
  services.copyparty = {
@@ -2622,6 +2675,8 @@ sync folders to/from copyparty
2622
2675
 
2623
2676
  NOTE: full bidirectional sync, like what [nextcloud](https://docs.nextcloud.com/server/latest/user_manual/sv/files/desktop_mobile_sync.html) and [syncthing](https://syncthing.net/) does, will never be supported! Only single-direction sync (server-to-client, or client-to-server) is possible with copyparty
2624
2677
 
2678
+ * if you want bidirectional sync, then copyparty and syncthing *should* be entirely safe to combine; they should be able to collaborate on the same folders without causing any trouble for eachother. Many people do this, and there have been no issues so far. But, if you *do* encounter any problems, please [file a copyparty bug](https://github.com/9001/copyparty/issues/new/choose) and I'll try to help -- just keep in mind I've never used syncthing before :-)
2679
+
2625
2680
  the commandline uploader [u2c.py](https://github.com/9001/copyparty/tree/hovudstraum/bin#u2cpy) with `--dr` is the best way to sync a folder to copyparty; verifies checksums and does files in parallel, and deletes unexpected files on the server after upload has finished which makes file-renames really cheap (it'll rename serverside and skip uploading)
2626
2681
 
2627
2682
  alternatively there is [rclone](./docs/rclone.md) which allows for bidirectional sync and is *way* more flexible (stream files straight from sftp/s3/gcs to copyparty, ...), although there is no integrity check and it won't work with files over 100 MiB if copyparty is behind cloudflare
@@ -2668,6 +2723,8 @@ there is no iPhone app, but the following shortcuts are almost as good:
2668
2723
  * can download links and rehost the target file on copyparty (see first comment inside the shortcut)
2669
2724
  * pics become lowres if you share from gallery to shortcut, so better to launch the shortcut and pick stuff from there
2670
2725
 
2726
+ if you want to run the copyparty server on your iPhone or iPad, see [install on iOS](#install-on-iOS)
2727
+
2671
2728
 
2672
2729
  # performance
2673
2730
 
@@ -3001,6 +3058,27 @@ if you want thumbnails (photos+videos) and you're okay with spending another 132
3001
3058
  * or if you want to use `vips` for photo-thumbs instead, `pkg install libvips && python -m pip install --user -U wheel && python -m pip install --user -U pyvips && (cd /data/data/com.termux/files/usr/lib/; ln -s libgobject-2.0.so{,.0}; ln -s libvips.so{,.42})`
3002
3059
 
3003
3060
 
3061
+ # install on iOS
3062
+
3063
+ first install one of the following:
3064
+ * [a-Shell mini](https://apps.apple.com/us/app/a-shell-mini/id1543537943) gives you the essential features
3065
+ * [a-Shell](https://apps.apple.com/us/app/a-shell/id1473805438) also enables audio transcoding and better thubmnails
3066
+
3067
+ and then copypaste the following command into `a-Shell`:
3068
+
3069
+ ```sh
3070
+ curl https://github.com/9001/copyparty/raw/refs/heads/hovudstraum/contrib/setup-ashell.sh | sh
3071
+ ```
3072
+
3073
+ what this does:
3074
+ * creates a basic [config file](#accounts-and-volumes) named `cpc` which you can edit with `vim cpc`
3075
+ * adds the command `cpp` to launch copyparty with that config file
3076
+
3077
+ known issues:
3078
+ * cannot run in the background; it needs to be on-screen to accept connections / uploads / downloads
3079
+ * the best way to exit copyparty is to swipe away the app
3080
+
3081
+
3004
3082
  # reporting bugs
3005
3083
 
3006
3084
  ideas for context to include, and where to submit them
@@ -1,7 +1,7 @@
1
1
  copyparty/__init__.py,sha256=SJtQjM-9PP9K-IaoM9M3iNKvRApp0omOrAN6YtXTPNM,2599
2
- copyparty/__main__.py,sha256=lrWWnP-uLjIPvAIZISSBZXdQu6V3270JwpV9GRQISHQ,136147
3
- copyparty/__version__.py,sha256=cybY9jM60FHeG9ZzCX2LScAHCZosLA8fX15kE9_dJoI,251
4
- copyparty/authsrv.py,sha256=Xq8P1vl1bXNL9ymDJFqq9RgwE0jlfCcCcEVYC_jqry4,124770
2
+ copyparty/__main__.py,sha256=_u7Z2u3E6Aonw8m-wqGqAxbFmZFE8TvriQUQByFEEe4,136752
3
+ copyparty/__version__.py,sha256=a01oYLp_GGtSVF39k8jOpCDJ28AnfX88Sni6OfYoQEw,251
4
+ copyparty/authsrv.py,sha256=M8oeX_foEreCeftnRNxam4yvVq2hVBrI58u4rytp26c,125592
5
5
  copyparty/broker_mp.py,sha256=QdOXXvV2Xn6J0CysEqyY3GZbqxQMyWnTpnba-a5lMc0,4987
6
6
  copyparty/broker_mpw.py,sha256=PpSS4SK3pItlpfD8OwVr3QmJEPKlUgaf2nuMOozixgU,3347
7
7
  copyparty/broker_thr.py,sha256=fjoYtpSscUA7-nMl4r1n2R7UK3J9lrvLS3rUZ-iJzKQ,1721
@@ -10,8 +10,8 @@ copyparty/cert.py,sha256=pSSeVYticrDsnsrdRtfpUQN-8WRObsqrYtSRroXmgxo,7992
10
10
  copyparty/cfg.py,sha256=i5HQzxqAtMfJac6DJxulvCNKEFPdqzxZps5yYseLJt4,16108
11
11
  copyparty/dxml.py,sha256=VZADJS9z18LalENSvVfjk29ddnpaDQ-v8AVm_THwS1c,2607
12
12
  copyparty/fsutil.py,sha256=NC_CJC4TDag399vVDH9_uQfdfpTMwRFLNxERSWhlVvs,4594
13
- copyparty/ftpd.py,sha256=bQcmcTrlO9DlT69gsnc0yEFhQy2PpiOp8e3iMz5bhp8,18789
14
- copyparty/httpcli.py,sha256=yXaCO-nLR_VXtc_Kjo-3qvMD-Y6g0wxZHARUWiG2f3s,237766
13
+ copyparty/ftpd.py,sha256=K4EClq4dVk6qh0QO8ire1O1Gv_8KzMAxiPBPAM5lfek,18793
14
+ copyparty/httpcli.py,sha256=aXLSvoS4bc5SOzUIrOJ7hlDROpTd4QeEoOhiMQ1VEgU,237807
15
15
  copyparty/httpconn.py,sha256=IA9fdCjigawZ4kWhgvVN3nSiy5pb3W2qaE6rFqUYdq0,6943
16
16
  copyparty/httpsrv.py,sha256=12j76CpAlJEeZU17CbWLnoVqoAPdv4xN48prQtE0IRs,19051
17
17
  copyparty/ico.py,sha256=-7QjF_jIxnPo4Vr0oUPksQ_U_Ef0HRsSPm3s71idOz8,3879
@@ -24,9 +24,9 @@ copyparty/smbd.py,sha256=Czo8SRkkl4ndCwEUe9Cbr8v0YOnyQHzubGSguPizuTc,14651
24
24
  copyparty/ssdp.py,sha256=R1Z61GZOxBMF2Sk4RTxKWMOemogmcjEWG-CvLihd45k,7023
25
25
  copyparty/star.py,sha256=tV5BbX6AiQ7N4UU8DYtSTckNYeoeey4DBqq4LjfymbY,3818
26
26
  copyparty/sutil.py,sha256=E65jAaOzHlJYnqsOKDMPVT8kALPUVexpkSStWBdItkY,3231
27
- copyparty/svchub.py,sha256=DY-ogWcma34JdBLFc3OVYhDlNk6ELvG2kzlJDNGSbgQ,51110
27
+ copyparty/svchub.py,sha256=NKpJ4LYZz6WRVDbGkdHk7p5aJkfBXzo5ShM9gWJvsBs,51334
28
28
  copyparty/szip.py,sha256=9srQzjsTBrBadf6QMh4YRAL70rkZLevAOHqXWK5jvr8,8846
29
- copyparty/tcpsrv.py,sha256=m2yLrDQbmwC4-2ICE__yTz3yvMeayvYZkjyOhuIUlMk,20893
29
+ copyparty/tcpsrv.py,sha256=z1k8wo7xIqNbUJisuW0LH7S_2rjaSYgvZ2ACsC5bzi8,21913
30
30
  copyparty/tftpd.py,sha256=fXW0w2_fSbzKVQGTLgr4DbtxaIEfwB591bl0pYhwy6k,14272
31
31
  copyparty/th_cli.py,sha256=n3MMbnN7HTVSBHkTI2qLIjgwVvHkGsfTW7-aPJ-2o4s,5545
32
32
  copyparty/th_srv.py,sha256=iAWBHgtAaYAshXdCFrUx7IWq4y3NXrH79yzHChsy2dc,38335
@@ -40,7 +40,7 @@ copyparty/res/COPYING.txt,sha256=1LnBxkwJuC8mRBxuoMF2UIcpCjcteIzFHotSUE1Xte0,977
40
40
  copyparty/res/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
41
  copyparty/res/insecure.pem,sha256=FEt7jgrn6ZHTlFopq_LFAN027YIoaHi0HQFBbzYnEwc,2876
42
42
  copyparty/stolen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
- copyparty/stolen/qrcodegen.py,sha256=Nro-HiPGi5RFbiu78msCWnDllWeoDV4IBkzuG7WQqkU,22037
43
+ copyparty/stolen/qrcodegen.py,sha256=geqrtLSPPjXy8kB7W9Sqj6-_Y55lOEDFAc-MgKBkkNQ,22648
44
44
  copyparty/stolen/surrogateescape.py,sha256=-ZfRWrbgJrh74dXfXLNMvo_iiCVUhXbFs_anHIrWPts,5573
45
45
  copyparty/stolen/dnslib/__init__.py,sha256=SmYdaHdL5czxKxrOFGvzbfmojOthRky1GXKgmWj4QeM,159
46
46
  copyparty/stolen/dnslib/bimap.py,sha256=j_ah40P3kOw0AQT5vvMcv7XbMtS0jV6Oe9YGCh7J57s,1182
@@ -55,16 +55,16 @@ copyparty/stolen/ifaddr/_posix.py,sha256=-67NdfGrCktfQPakT2fLbjl2U00QMvyBGkSvrUu
55
55
  copyparty/stolen/ifaddr/_shared.py,sha256=uNC4SdEIgdSLKvuUzsf1aM-H1Xrc_9mpLoOT43YukGs,6206
56
56
  copyparty/stolen/ifaddr/_win32.py,sha256=EE-QyoBgeB7lYQ6z62VjXNaRozaYfCkaJBHGNA8QtZM,4026
57
57
  copyparty/web/baguettebox.js.gz,sha256=VR-MdQ11CZ1PkMW0VTv36RPLY5L1w2rDj2CY-TPfvRM,8269
58
- copyparty/web/browser.css.gz,sha256=C0dDF7J5f2NKnG4nMDhDwINxjAdNWydCHMXc_aryvZA,15657
58
+ copyparty/web/browser.css.gz,sha256=8zQ0rWJvNPUOgOOY4EMCFh20q8S3-bDhiFi4sYx135M,15661
59
59
  copyparty/web/browser.html,sha256=lhelkXI8_HGfuqo_5b6XEGzf8VNodOMXE9kbv31JtbM,4790
60
- copyparty/web/browser.js.gz,sha256=3SRaOwrSK8_4XY0T9CBLBZ-ruaTcRT5ivomBnQncpR0,300874
60
+ copyparty/web/browser.js.gz,sha256=E6jFuEeusjqb_mYo5400iDhq8asUHUlfmENSX3_IEh4,300849
61
61
  copyparty/web/browser2.html,sha256=NRUZ08GH-e2YcGXcoz0UjYg6JIVF42u4IMX4HHwWTmg,1587
62
62
  copyparty/web/cf.html,sha256=lJThtNFNAQT1ClCHHlivAkDGE0LutedwopXD62Z8Nys,589
63
63
  copyparty/web/dbg-audio.js.gz,sha256=Ma-KZtK8LnmiwNvNKFKXMPYl_Nn_3U7GsJ6-DRWC2HE,688
64
64
  copyparty/web/idp.html,sha256=qOjjvZz6fVk0W8cXiP8fXeTp5KMa_dDV7BRzJNUModo,1481
65
65
  copyparty/web/md.css.gz,sha256=UZpN0J7ubVM05CZkbZYkQRJeGgJt_GNDEzKTGSQd8h4,2032
66
66
  copyparty/web/md.html,sha256=hz-xJVfKtaeTUQn3tGh7ebIMvLbOjVKkrMhsCTr3lGM,4200
67
- copyparty/web/md.js.gz,sha256=m5dpIskZZ8FD9X-L0EWpoZP-yLOo-PCWJ7j4AFtHVRI,4163
67
+ copyparty/web/md.js.gz,sha256=94jN-dH86i5r9u1xAvvKjX9It5lzRl-8TUKRSPVL8LM,4164
68
68
  copyparty/web/md2.css.gz,sha256=uIVHKScThdbcfhXNSHgKZnALYpxbnXC-WuEzOJ20Lpc,699
69
69
  copyparty/web/md2.js.gz,sha256=Km7nX6pnZs0GWaqCj54FYu-aYrkxa73C9yCGGOcG4dE,8368
70
70
  copyparty/web/mde.css.gz,sha256=2SkAEDKIRPqywNJ8t_heQaeBQ_R73Rf-pQI_bDoKF6o,942
@@ -84,7 +84,7 @@ copyparty/web/splash.js.gz,sha256=NSTEWUqvpXMHmhdUfbJQkPsqMQzaac9euXEQEdTgwzk,15
84
84
  copyparty/web/svcs.html,sha256=wGW7bwY3EIDRpp9apzJsED_UMlHX31X2H3ZnN13tWCI,14913
85
85
  copyparty/web/svcs.js.gz,sha256=_dvatVBMVI_iy5MnYQeZumFGAnu9lAP_WKrhOA1TYxs,852
86
86
  copyparty/web/ui.css.gz,sha256=e3iIflzddmjoyPrun_1jsu9j7fbdonNQLyhEE2oKKOQ,2819
87
- copyparty/web/up2k.js.gz,sha256=GPU8gTQVifoPB0IQ8NNiy3t2QbN0F82BYrSVKm_a4FA,24989
87
+ copyparty/web/up2k.js.gz,sha256=pgj3drYXEiHOkSpcZp4ttWCqD72BpFp16cuHObl0zpo,24994
88
88
  copyparty/web/util.js.gz,sha256=A28FamE9n03YkSE09G4IOLvFaDZK-j5Mi-xl124JcC8,15569
89
89
  copyparty/web/w.hash.js.gz,sha256=cFH6Xo4YRgH9Wr7RmHMSEfpuTmmIvEmzmSvv4RLmyPU,1193
90
90
  copyparty/web/a/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -105,9 +105,9 @@ copyparty/web/deps/prismd.css.gz,sha256=ObUlksQVr-OuYlTz-I4B23TeBg2QDVVGRnWBz8cV
105
105
  copyparty/web/deps/scp.woff2,sha256=w99BDU5i8MukkMEL-iW0YO9H4vFFZSPWxbkH70ytaAg,8612
106
106
  copyparty/web/deps/sha512.ac.js.gz,sha256=lFZaCLumgWxrvEuDr4bqdKHsqjX82AbVAb7_F45Yk88,7033
107
107
  copyparty/web/deps/sha512.hw.js.gz,sha256=UAed2_ocklZCnIzcSYz2h4P1ycztlCLj-ewsRTud2lU,7939
108
- copyparty-1.19.3.dist-info/licenses/LICENSE,sha256=gOr4h33pCsBEg9uIy9AYmb7qlocL4V9t2uPJS5wllr0,1072
109
- copyparty-1.19.3.dist-info/METADATA,sha256=WhGYVevnz-FN-68bAdDMi0Wnxt4uATehyOkj9gKa3TU,172447
110
- copyparty-1.19.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
111
- copyparty-1.19.3.dist-info/entry_points.txt,sha256=4zw6a3rqASywQomiYLObjjlxybaI65LYYOTJwgKz7b0,128
112
- copyparty-1.19.3.dist-info/top_level.txt,sha256=LnYUPsDyk-8kFgM6YJLG4h820DQekn81cObKSu9g-sI,10
113
- copyparty-1.19.3.dist-info/RECORD,,
108
+ copyparty-1.19.5.dist-info/licenses/LICENSE,sha256=gOr4h33pCsBEg9uIy9AYmb7qlocL4V9t2uPJS5wllr0,1072
109
+ copyparty-1.19.5.dist-info/METADATA,sha256=3Ov6qPwDkVJlVCvBQxJLjo5KKCGfAfxYTDi7rnceBME,175971
110
+ copyparty-1.19.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
111
+ copyparty-1.19.5.dist-info/entry_points.txt,sha256=4zw6a3rqASywQomiYLObjjlxybaI65LYYOTJwgKz7b0,128
112
+ copyparty-1.19.5.dist-info/top_level.txt,sha256=LnYUPsDyk-8kFgM6YJLG4h820DQekn81cObKSu9g-sI,10
113
+ copyparty-1.19.5.dist-info/RECORD,,