copyparty 1.16.13__py3-none-any.whl → 1.16.14__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
@@ -1031,6 +1031,7 @@ def add_upload(ap):
1031
1031
  ap2.add_argument("--turbo", metavar="LVL", type=int, default=0, help="configure turbo-mode in up2k client; [\033[32m-1\033[0m] = forbidden/always-off, [\033[32m0\033[0m] = default-off and warn if enabled, [\033[32m1\033[0m] = default-off, [\033[32m2\033[0m] = on, [\033[32m3\033[0m] = on and disable datecheck")
1032
1032
  ap2.add_argument("--u2j", metavar="JOBS", type=int, default=2, help="web-client: number of file chunks to upload in parallel; 1 or 2 is good for low-latency (same-country) connections, 4-8 for android clients, 16 for cross-atlantic (max=64)")
1033
1033
  ap2.add_argument("--u2sz", metavar="N,N,N", type=u, default="1,64,96", help="web-client: default upload chunksize (MiB); sets \033[33mmin,default,max\033[0m in the settings gui. Each HTTP POST will aim for \033[33mdefault\033[0m, and never exceed \033[33mmax\033[0m. Cloudflare max is 96. Big values are good for cross-atlantic but may increase HDD fragmentation on some FS. Disable this optimization with [\033[32m1,1,1\033[0m]")
1034
+ ap2.add_argument("--u2ow", metavar="NUM", type=int, default=0, help="web-client: default setting for when to overwrite existing files; [\033[32m0\033[0m]=never, [\033[32m1\033[0m]=if-client-newer, [\033[32m2\033[0m]=always (volflag=u2ow)")
1034
1035
  ap2.add_argument("--u2sort", metavar="TXT", type=u, default="s", help="upload order; [\033[32ms\033[0m]=smallest-first, [\033[32mn\033[0m]=alphabetical, [\033[32mfs\033[0m]=force-s, [\033[32mfn\033[0m]=force-n -- alphabetical is a bit slower on fiber/LAN but makes it easier to eyeball if everything went fine")
1035
1036
  ap2.add_argument("--write-uplog", action="store_true", help="write POST reports to textfiles in working-directory")
1036
1037
 
@@ -1261,7 +1262,7 @@ def add_optouts(ap):
1261
1262
  ap2.add_argument("--no-tarcmp", action="store_true", help="disable download as compressed tar (?tar=gz, ?tar=bz2, ?tar=xz, ?tar=gz:9, ...)")
1262
1263
  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")
1263
1264
  ap2.add_argument("--no-pipe", action="store_true", help="disable race-the-beam (lockstep download of files which are currently being uploaded) (volflag=nopipe)")
1264
- ap2.add_argument("--no-db-ip", action="store_true", help="do not write uploader IPs into the database")
1265
+ ap2.add_argument("--no-db-ip", action="store_true", help="do not write uploader-IP into the database; will also disable unpost, you may want \033[32m--forget-ip\033[0m instead (volflag=no_db_ip)")
1265
1266
 
1266
1267
 
1267
1268
  def add_safety(ap):
@@ -1411,6 +1412,7 @@ def add_db_general(ap, hcores):
1411
1412
  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")
1412
1413
  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)")
1413
1414
  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)")
1415
+ ap2.add_argument("--forget-ip", metavar="MIN", type=int, default=0, help="remove uploader-IP from database (and make unpost impossible) \033[33mMIN\033[0m minutes after upload, for GDPR reasons. Default [\033[32m0\033[0m] is never-forget. [\033[32m1440\033[0m]=day, [\033[32m10080\033[0m]=week, [\033[32m43200\033[0m]=month. (volflag=forget_ip)")
1414
1416
  ap2.add_argument("--dbd", metavar="PROFILE", default="wal", help="database durability profile; sets the tradeoff between robustness and speed, see \033[33m--help-dbd\033[0m (volflag=dbd)")
1415
1417
  ap2.add_argument("--xlink", action="store_true", help="on upload: check all volumes for dupes, not just the target volume (probably buggy, not recommended) (volflag=xlink)")
1416
1418
  ap2.add_argument("--hash-mt", metavar="CORES", type=int, default=hcores, help="num cpu cores to use for file hashing; set 0 or 1 for single-core hashing")
copyparty/__version__.py CHANGED
@@ -1,8 +1,8 @@
1
1
  # coding: utf-8
2
2
 
3
- VERSION = (1, 16, 13)
3
+ VERSION = (1, 16, 14)
4
4
  CODENAME = "COPYparty"
5
- BUILD_DT = (2025, 2, 13)
5
+ BUILD_DT = (2025, 2, 19)
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
@@ -1382,8 +1382,16 @@ class AuthSrv(object):
1382
1382
  name = name.lower()
1383
1383
 
1384
1384
  # volflags are snake_case, but a leading dash is the removal operator
1385
- if name not in flagdescs and "-" in name[1:]:
1386
- name = name[:1] + name[1:].replace("-", "_")
1385
+ stripped = name.lstrip("-")
1386
+ zi = len(name) - len(stripped)
1387
+ if zi > 1:
1388
+ t = "WARNING: the config for volume [/%s] specified a volflag with multiple leading hyphens (%s); use one hyphen to remove, or zero hyphens to add a flag. Will now enable flag [%s]"
1389
+ self.log(t % (vpath, name, stripped), 3)
1390
+ name = stripped
1391
+ zi = 0
1392
+
1393
+ if stripped not in flagdescs and "-" in stripped:
1394
+ name = ("-" * zi) + stripped.replace("-", "_")
1387
1395
 
1388
1396
  desc = flagdescs.get(name.lstrip("-"), "?").replace("\n", " ")
1389
1397
 
@@ -1569,6 +1577,11 @@ class AuthSrv(object):
1569
1577
  for vol in vfs.all_vols.values():
1570
1578
  unknown_flags = set()
1571
1579
  for k, v in vol.flags.items():
1580
+ stripped = k.lstrip("-")
1581
+ if k != stripped and stripped not in vol.flags:
1582
+ t = "WARNING: the config for volume [/%s] tried to remove volflag [%s] by specifying [%s] but that volflag was not already set"
1583
+ self.log(t % (vol.vpath, stripped, k), 3)
1584
+ k = stripped
1572
1585
  if k not in flagdescs and k not in k_ign:
1573
1586
  unknown_flags.add(k)
1574
1587
  if unknown_flags:
@@ -1936,11 +1949,8 @@ class AuthSrv(object):
1936
1949
  if vf not in vol.flags:
1937
1950
  vol.flags[vf] = getattr(self.args, ga)
1938
1951
 
1939
- for k in ("nrand",):
1940
- if k not in vol.flags:
1941
- vol.flags[k] = getattr(self.args, k)
1942
-
1943
- for k in ("nrand", "u2abort", "ups_who", "zip_who"):
1952
+ zs = "forget_ip nrand u2abort u2ow ups_who zip_who"
1953
+ for k in zs.split():
1944
1954
  if k in vol.flags:
1945
1955
  vol.flags[k] = int(vol.flags[k])
1946
1956
 
@@ -2415,6 +2425,7 @@ class AuthSrv(object):
2415
2425
  "u2j": self.args.u2j,
2416
2426
  "u2sz": self.args.u2sz,
2417
2427
  "u2ts": vf["u2ts"],
2428
+ "u2ow": vf["u2ow"],
2418
2429
  "frand": bool(vf.get("rand")),
2419
2430
  "lifetime": vn.js_ls["lifetime"],
2420
2431
  "u2sort": self.args.u2sort,
copyparty/cfg.py CHANGED
@@ -43,6 +43,7 @@ def vf_bmap() :
43
43
  "gsel",
44
44
  "hardlink",
45
45
  "magic",
46
+ "no_db_ip",
46
47
  "no_sb_md",
47
48
  "no_sb_lg",
48
49
  "nsort",
@@ -73,6 +74,7 @@ def vf_vmap() :
73
74
  }
74
75
  for k in (
75
76
  "dbd",
77
+ "forget_ip",
76
78
  "hsortn",
77
79
  "html_head",
78
80
  "lg_sbf",
@@ -80,6 +82,7 @@ def vf_vmap() :
80
82
  "lg_sba",
81
83
  "md_sba",
82
84
  "nrand",
85
+ "u2ow",
83
86
  "og_desc",
84
87
  "og_site",
85
88
  "og_th",
@@ -156,7 +159,8 @@ flagcats = {
156
159
  "daw": "enable full WebDAV write support (dangerous);\nPUT-operations will now \033[1;31mOVERWRITE\033[0;35m existing files",
157
160
  "nosub": "forces all uploads into the top folder of the vfs",
158
161
  "magic": "enables filetype detection for nameless uploads",
159
- "gz": "allows server-side gzip of uploads with ?gz (also c,xz)",
162
+ "gz": "allows server-side gzip compression of uploads with ?gz",
163
+ "xz": "allows server-side lzma compression of uploads with ?xz",
160
164
  "pk": "forces server-side compression, optional arg: xz,9",
161
165
  },
162
166
  "upload rules": {
@@ -167,6 +171,7 @@ flagcats = {
167
171
  "medialinks": "return medialinks for non-up2k uploads (not hotlinks)",
168
172
  "rand": "force randomized filenames, 9 chars long by default",
169
173
  "nrand=N": "randomized filenames are N chars long",
174
+ "u2ow=N": "overwrite existing files? 0=no 1=if-older 2=always",
170
175
  "u2ts=fc": "[f]orce [c]lient-last-modified or [u]pload-time",
171
176
  "u2abort=1": "allow aborting unfinished uploads? 0=no 1=strict 2=ip-chk 3=acct-chk",
172
177
  "sz=1k-3m": "allow filesizes between 1 KiB and 3MiB",
@@ -197,6 +202,8 @@ flagcats = {
197
202
  "nohash=\\.iso$": "skips hashing file contents if path matches *.iso",
198
203
  "noidx=\\.iso$": "fully ignores the contents at paths matching *.iso",
199
204
  "noforget": "don't forget files when deleted from disk",
205
+ "forget_ip=43200": "forget uploader-IP after 30 days (GDPR)",
206
+ "no_db_ip": "never store uploader-IP in the db; disables unpost",
200
207
  "fat32": "avoid excessive reindexing on android sdcardfs",
201
208
  "dbd=[acid|swal|wal|yolo]": "database speed-durability tradeoff",
202
209
  "xlink": "cross-volume dupe detection / linking (dangerous)",
copyparty/httpcli.py CHANGED
@@ -1803,7 +1803,8 @@ class HttpCli(object):
1803
1803
  dst = unquotep(dst)
1804
1804
 
1805
1805
  # overwrite=True is default; rfc4918 9.8.4
1806
- overwrite = self.headers.get("overwrite", "").lower() != "f"
1806
+ zs = self.headers.get("overwrite", "").lower()
1807
+ overwrite = zs not in ["f", "false"]
1807
1808
 
1808
1809
  try:
1809
1810
  fun = self._cp if self.mode == "COPY" else self._mv
copyparty/up2k.py CHANGED
@@ -553,6 +553,7 @@ class Up2k(object):
553
553
  else:
554
554
  # important; not deferred by db_act
555
555
  timeout = self._check_lifetimes()
556
+ timeout = min(self._check_forget_ip(), timeout)
556
557
  try:
557
558
  if self.args.shr:
558
559
  timeout = min(self._check_shares(), timeout)
@@ -613,6 +614,43 @@ class Up2k(object):
613
614
  for v in vols:
614
615
  volage[v] = now
615
616
 
617
+ def _check_forget_ip(self) :
618
+ now = time.time()
619
+ timeout = now + 9001
620
+ for vp, vol in sorted(self.vfs.all_vols.items()):
621
+ maxage = vol.flags["forget_ip"]
622
+ if not maxage:
623
+ continue
624
+
625
+ cur = self.cur.get(vol.realpath)
626
+ if not cur:
627
+ continue
628
+
629
+ cutoff = now - maxage * 60
630
+
631
+ for _ in range(2):
632
+ q = "select ip, at from up where ip > '' order by +at limit 1"
633
+ hits = cur.execute(q).fetchall()
634
+ if not hits:
635
+ break
636
+
637
+ remains = hits[0][1] - cutoff
638
+ if remains > 0:
639
+ timeout = min(timeout, now + remains)
640
+ break
641
+
642
+ q = "update up set ip = '' where ip > '' and at <= %d"
643
+ cur.execute(q % (cutoff,))
644
+ zi = cur.rowcount
645
+ cur.connection.commit()
646
+
647
+ t = "forget-ip(%d) removed %d IPs from db [/%s]"
648
+ self.log(t % (maxage, zi, vol.vpath))
649
+
650
+ timeout = min(timeout, now + 900)
651
+
652
+ return timeout
653
+
616
654
  def _check_lifetimes(self) :
617
655
  now = time.time()
618
656
  timeout = now + 9001
@@ -1074,7 +1112,7 @@ class Up2k(object):
1074
1112
  ft = "\033[0;32m{}{:.0}"
1075
1113
  ff = "\033[0;35m{}{:.0}"
1076
1114
  fv = "\033[0;36m{}:\033[90m{}"
1077
- zs = "html_head mv_re_r mv_re_t rm_re_r rm_re_t srch_re_dots srch_re_nodot"
1115
+ zs = "ext_th_d html_head mv_re_r mv_re_t rm_re_r rm_re_t srch_re_dots srch_re_nodot"
1078
1116
  fx = set(zs.split())
1079
1117
  fd = vf_bmap()
1080
1118
  fd.update(vf_cmap())
@@ -3319,7 +3357,17 @@ class Up2k(object):
3319
3357
  return fname
3320
3358
 
3321
3359
  fp = djoin(fdir, fname)
3322
- if job.get("replace") and bos.path.exists(fp):
3360
+
3361
+ ow = job.get("replace") and bos.path.exists(fp)
3362
+ if ow and "mt" in str(job["replace"]).lower():
3363
+ mts = bos.stat(fp).st_mtime
3364
+ mtc = job["lmod"]
3365
+ if mtc < mts:
3366
+ t = "will not overwrite; server %d sec newer than client; %d > %d %r"
3367
+ self.log(t % (mts - mtc, mts, mtc, fp))
3368
+ ow = False
3369
+
3370
+ if ow:
3323
3371
  self.log("replacing existing file at %r" % (fp,))
3324
3372
  cur = None
3325
3373
  ptop = job["ptop"]
@@ -3770,7 +3818,7 @@ class Up2k(object):
3770
3818
  db_ip = ""
3771
3819
  else:
3772
3820
  # plugins may expect this to look like an actual IP
3773
- db_ip = "1.1.1.1" if self.args.no_db_ip else ip
3821
+ db_ip = "1.1.1.1" if "no_db_ip" in vflags else ip
3774
3822
 
3775
3823
  sql = "insert into up values (?,?,?,?,?,?,?)"
3776
3824
  v = (dwark, int(ts), sz, rd, fn, db_ip, int(at or 0))
copyparty/web/a/u2c.py CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env python3
2
2
  from __future__ import print_function, unicode_literals
3
3
 
4
- S_VERSION = "2.9"
5
- S_BUILD_DT = "2025-01-27"
4
+ S_VERSION = "2.10"
5
+ S_BUILD_DT = "2025-02-19"
6
6
 
7
7
  """
8
8
  u2c.py: upload to copyparty
@@ -805,7 +805,9 @@ def handshake(ar, file, search):
805
805
  else:
806
806
  if ar.touch:
807
807
  req["umod"] = True
808
- if ar.ow:
808
+ if ar.owo:
809
+ req["replace"] = "mt"
810
+ elif ar.ow:
809
811
  req["replace"] = True
810
812
 
811
813
  file.recheck = False
@@ -1536,6 +1538,7 @@ source file/folder selection uses rsync syntax, meaning that:
1536
1538
  ap.add_argument("--ok", action="store_true", help="continue even if some local files are inaccessible")
1537
1539
  ap.add_argument("--touch", action="store_true", help="if last-modified timestamps differ, push local to server (need write+delete perms)")
1538
1540
  ap.add_argument("--ow", action="store_true", help="overwrite existing files instead of autorenaming")
1541
+ ap.add_argument("--owo", action="store_true", help="overwrite existing files if server-file is older")
1539
1542
  ap.add_argument("--spd", action="store_true", help="print speeds for each file")
1540
1543
  ap.add_argument("--version", action="store_true", help="show version and exit")
1541
1544
 
Binary file
Binary file
copyparty/web/up2k.js.gz CHANGED
Binary file
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: copyparty
3
- Version: 1.16.13
3
+ Version: 1.16.14
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
@@ -151,9 +151,11 @@ turn almost any device into a file server with resumable uploads/downloads using
151
151
  * [reverse-proxy](#reverse-proxy) - running copyparty next to other websites
152
152
  * [real-ip](#real-ip) - teaching copyparty how to see client IPs
153
153
  * [reverse-proxy performance](#reverse-proxy-performance)
154
+ * [permanent cloudflare tunnel](#permanent-cloudflare-tunnel) - if you have a domain and want to get your copyparty online real quick
154
155
  * [prometheus](#prometheus) - metrics/stats can be enabled
155
156
  * [other extremely specific features](#other-extremely-specific-features) - you'll never find a use for these
156
157
  * [custom mimetypes](#custom-mimetypes) - change the association of a file extension
158
+ * [GDPR compliance](#GDPR-compliance) - imagine using copyparty professionally...
157
159
  * [feature chickenbits](#feature-chickenbits) - buggy feature? rip it out
158
160
  * [packages](#packages) - the party might be closer than you think
159
161
  * [arch package](#arch-package) - now [available on aur](https://aur.archlinux.org/packages/copyparty) maintained by [@icxes](https://github.com/icxes)
@@ -216,8 +218,8 @@ enable thumbnails (images/audio/video), media indexing, and audio transcoding by
216
218
  * **MacOS:** `port install py-Pillow ffmpeg`
217
219
  * **MacOS** (alternative): `brew install pillow ffmpeg`
218
220
  * **Windows:** `python -m pip install --user -U Pillow`
219
- * install python and ffmpeg manually; do not use `winget` or `Microsoft Store` (it breaks $PATH)
220
- * copyparty.exe comes with `Pillow` and only needs `ffmpeg`
221
+ * install [python](https://www.python.org/downloads/windows/) and [ffmpeg](#optional-dependencies) manually; do not use `winget` or `Microsoft Store` (it breaks $PATH)
222
+ * copyparty.exe comes with `Pillow` and only needs [ffmpeg](#optional-dependencies) for mediatags/videothumbs
221
223
  * see [optional dependencies](#optional-dependencies) to enable even more features
222
224
 
223
225
  running copyparty without arguments (for example doubleclicking it on Windows) will give everyone read/write access to the current folder; you may want [accounts and volumes](#accounts-and-volumes)
@@ -240,6 +242,8 @@ first download [cloudflared](https://developers.cloudflare.com/cloudflare-one/co
240
242
 
241
243
  as the tunnel starts, it will show a URL which you can share to let anyone browse your stash or upload files to you
242
244
 
245
+ but if you have a domain, then you probably want to skip the random autogenerated URL and instead make a [permanent cloudflare tunnel](#permanent-cloudflare-tunnel)
246
+
243
247
  since people will be connecting through cloudflare, run copyparty with `--xff-hdr cf-connecting-ip` to detect client IPs correctly
244
248
 
245
249
 
@@ -458,6 +462,9 @@ upgrade notes
458
462
 
459
463
  "frequently" asked questions
460
464
 
465
+ * can I change the 🌲 spinning pine-tree loading animation?
466
+ * [yeah...](https://github.com/9001/copyparty/tree/hovudstraum/docs/rice#boring-loader-spinner) :-(
467
+
461
468
  * is it possible to block read-access to folders unless you know the exact URL for a particular file inside?
462
469
  * yes, using the [`g` permission](#accounts-and-volumes), see the examples there
463
470
  * you can also do this with linux filesystem permissions; `chmod 111 music` will make it possible to access files and folders inside the `music` folder but not list the immediate contents -- also works with other software, not just copyparty
@@ -480,6 +487,14 @@ upgrade notes
480
487
  * copyparty seems to think I am using http, even though the URL is https
481
488
  * your reverse-proxy is not sending the `X-Forwarded-Proto: https` header; this could be because your reverse-proxy itself is confused. Ensure that none of the intermediates (such as cloudflare) are terminating https before the traffic hits your entrypoint
482
489
 
490
+ * thumbnails are broken (you get a colorful square which says the filetype instead)
491
+ * you need to install `FFmpeg` or `Pillow`; see [thumbnails](#thumbnails)
492
+
493
+ * thumbnails are broken (some images appear, but other files just get a blank box, and/or the broken-image placeholder)
494
+ * probably due to a reverse-proxy messing with the request URLs and stripping the query parameters (`?th=w`), so check your URL rewrite rules
495
+ * could also be due to incorrect caching settings in reverse-proxies and/or CDNs, so make sure that nothing is set to ignore the query string
496
+ * could also be due to misbehaving privacy-related browser extensions, so try to disable those
497
+
483
498
  * i want to learn python and/or programming and am considering looking at the copyparty source code in that occasion
484
499
  * ```bash
485
500
  _| _ __ _ _|_
@@ -710,6 +725,7 @@ press `g` or `田` to toggle grid-view instead of the file listing and `t` togg
710
725
  it does static images with Pillow / pyvips / FFmpeg, and uses FFmpeg for video files, so you may want to `--no-thumb` or maybe just `--no-vthumb` depending on how dangerous your users are
711
726
  * pyvips is 3x faster than Pillow, Pillow is 3x faster than FFmpeg
712
727
  * disable thumbnails for specific volumes with volflag `dthumb` for all, or `dvthumb` / `dathumb` / `dithumb` for video/audio/images only
728
+ * for installing FFmpeg on windows, see [optional dependencies](#optional-dependencies)
713
729
 
714
730
  audio files are converted into spectrograms using FFmpeg unless you `--no-athumb` (and some FFmpeg builds may need `--th-ff-swr`)
715
731
 
@@ -821,8 +837,11 @@ the up2k UI is the epitome of polished intuitive experiences:
821
837
  * "parallel uploads" specifies how many chunks to upload at the same time
822
838
  * `[🏃]` analysis of other files should continue while one is uploading
823
839
  * `[🥔]` shows a simpler UI for faster uploads from slow devices
840
+ * `[🛡️]` decides when to overwrite existing files on the server
841
+ * `🛡️` = never (generate a new filename instead)
842
+ * `🕒` = overwrite if the server-file is older
843
+ * `♻️` = always overwrite if the files are different
824
844
  * `[🎲]` generate random filenames during upload
825
- * `[📅]` preserve last-modified timestamps; server times will match yours
826
845
  * `[🔎]` switch between upload and [file-search](#file-search) mode
827
846
  * ignore `[🔎]` if you add files by dragging them into the browser
828
847
 
@@ -2039,6 +2058,26 @@ in summary, `haproxy > caddy > traefik > nginx > apache > lighttpd`, and use uds
2039
2058
  * if these results are bullshit because my config exampels are bad, please submit corrections!
2040
2059
 
2041
2060
 
2061
+ ## permanent cloudflare tunnel
2062
+
2063
+ if you have a domain and want to get your copyparty online real quick, either from your home-PC behind a CGNAT or from a server without an existing [reverse-proxy](#reverse-proxy) setup, one approach is to create a [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/get-started/) (formerly "Argo Tunnel")
2064
+
2065
+ I'd recommend making a `Locally-managed tunnel` for more control, but if you prefer to make a `Remotely-managed tunnel` then this is currently how:
2066
+
2067
+ * `cloudflare dashboard` » `zero trust` » `networks` » `tunnels` » `create a tunnel` » `cloudflared` » choose a cool `subdomain` and leave the `path` blank, and use `service type` = `http` and `URL` = `127.0.0.1:3923`
2068
+
2069
+ * and if you want to just run the tunnel without installing it, skip the `cloudflared service install BASE64` step and instead do `cloudflared --no-autoupdate tunnel run --token BASE64`
2070
+
2071
+ NOTE: since people will be connecting through cloudflare, as mentioned in [real-ip](#real-ip) you should run copyparty with `--xff-hdr cf-connecting-ip` to detect client IPs correctly
2072
+
2073
+ config file example:
2074
+
2075
+ ```yaml
2076
+ [global]
2077
+ xff-hdr: cf-connecting-ip
2078
+ ```
2079
+
2080
+
2042
2081
  ## prometheus
2043
2082
 
2044
2083
  metrics/stats can be enabled at URL `/.cpr/metrics` for grafana / prometheus / etc (openmetrics 1.0.0)
@@ -2125,6 +2164,18 @@ in a config file, this is the same as:
2125
2164
  run copyparty with `--mimes` to list all the default mappings
2126
2165
 
2127
2166
 
2167
+ ### GDPR compliance
2168
+
2169
+ imagine using copyparty professionally... **TINLA/IANAL; EU laws are hella confusing**
2170
+
2171
+ * remember to disable logging, or configure logrotation to an acceptable timeframe with `-lo cpp-%Y-%m%d.txt.xz` or similar
2172
+
2173
+ * if running with the database enabled (recommended), then have it forget uploader-IPs after some time using `--forget-ip 43200`
2174
+ * don't set it too low; [unposting](#unpost) a file is no longer possible after this takes effect
2175
+
2176
+ * if you actually *are* a lawyer then I'm open for feedback, would be fun
2177
+
2178
+
2128
2179
  ### feature chickenbits
2129
2180
 
2130
2181
  buggy feature? rip it out by setting any of the following environment variables to disable its associated bell or whistle,
@@ -2642,6 +2693,8 @@ enable [smb](#smb-server) support (**not** recommended): `impacket==0.12.0`
2642
2693
 
2643
2694
  `pyvips` gives higher quality thumbnails than `Pillow` and is 320% faster, using 270% more ram: `sudo apt install libvips42 && python3 -m pip install --user -U pyvips`
2644
2695
 
2696
+ to install FFmpeg on Windows, grab [a recent build](https://www.gyan.dev/ffmpeg/builds/ffmpeg-git-full.7z) -- you need `ffmpeg.exe` and `ffprobe.exe` from inside the `bin` folder; copy them into `C:\Windows\System32` or any other folder that's in your `%PATH%`
2697
+
2645
2698
 
2646
2699
  ### dependency chickenbits
2647
2700
 
@@ -1,17 +1,17 @@
1
1
  copyparty/__init__.py,sha256=VR6ZZhB9IxaK5TDXDTBM_OIP5ydkrdbaEnstktLM__s,2649
2
- copyparty/__main__.py,sha256=Tcvi7uIGA37yGVXJbbhn-Cr0OBtt81aRF2Or0ZHXz6U,116449
3
- copyparty/__version__.py,sha256=Kh8nmhFwgLz9KpLvVPB-drOjIKb4uSXTYfW7c0xGr3E,252
4
- copyparty/authsrv.py,sha256=-oy1PtcMONLcrMllSY2aPuyHWQmE0Ot_EQTX7UJ5tuc,107035
2
+ copyparty/__main__.py,sha256=JDjMsCiOMMBPs8HR8vpgEJMgnxq-qjX-hcgxKHF9WX4,117137
3
+ copyparty/__version__.py,sha256=-v6S2kv2wFcsrV1NBHpDXFZYQtr_j2DfwN5pjYFcYX4,252
4
+ copyparty/authsrv.py,sha256=EqlE2YztBcZHF5MHStZawA8ZKSlm-ePkrhsen90lKE8,107740
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
8
8
  copyparty/broker_util.py,sha256=76mfnFOpX1gUUvtjm8UQI7jpTIaVINX10QonM-B7ggc,1680
9
9
  copyparty/cert.py,sha256=0ZAPeXeMR164vWn9GQU3JDKooYXEq_NOQkDeg543ivg,8009
10
- copyparty/cfg.py,sha256=-Cbva1shfXQVGFl8Xbo-bkUYjkpU6amPZpTyPJcE7M0,12926
10
+ copyparty/cfg.py,sha256=Z04AuNy-viZiiVJ8fLf3RULgH4w8ZidjsAVj4cmJKlA,13272
11
11
  copyparty/dxml.py,sha256=vu5uZQtwvwoqnFHbULs2Zh_y2DETu0T-ENpMZ1i2CV4,2505
12
12
  copyparty/fsutil.py,sha256=IVOFG8zBQPMQDDv7RIStSJHwHiAnVNROZS37O5k465A,4524
13
13
  copyparty/ftpd.py,sha256=T97SFS7JFtvRLbJX8C4fJSYwe13vhN3-E6emtlVmqLA,17608
14
- copyparty/httpcli.py,sha256=Dr776ra7_wTCghymLOymy_Bpv8A15Qmgt9ERe-8kZ5A,219131
14
+ copyparty/httpcli.py,sha256=QKgO3TTweln1N_w6Du7PDs1HJrT1c_zISUDZoima_X0,219162
15
15
  copyparty/httpconn.py,sha256=mQSgljh0Q-jyWjF4tQLrHbRKRe9WKl19kGqsGMsJpWo,6880
16
16
  copyparty/httpsrv.py,sha256=pxH_Eh8ElBLvOEDejgpP9Bvk65HNEou-03aYIcgXhrs,18090
17
17
  copyparty/ico.py,sha256=eWSxEae4wOCfheHl-m-wchYvFRAR_97kJDb4NGaB-Z8,3561
@@ -31,7 +31,7 @@ copyparty/tftpd.py,sha256=PXgG4rTmiaU_TavSyZWD5cFphdfChs9YvNY21qfExt8,13611
31
31
  copyparty/th_cli.py,sha256=PxDAmUvO_8Vm5edXiWtsCft0Fw69QL9rCHf9zLmUNeA,4800
32
32
  copyparty/th_srv.py,sha256=tHbh_Ve3v8tYclWH2thLs5oFufeXgJi1duUMveKIx9k,30725
33
33
  copyparty/u2idx.py,sha256=G6MDbD4I_sJSOwaNFZ6XLTQhnEDrB12pVKuKhzQ_leE,13676
34
- copyparty/up2k.py,sha256=yli2ALT61o1sPta4ckJu4v7hwUrV7IAJSsJo1-OEZWY,175423
34
+ copyparty/up2k.py,sha256=flkVZkHy7cfRZh7DSbTMbr4jfw7poZDOX3gFu5vyFxM,176973
35
35
  copyparty/util.py,sha256=Y_znSn3hBNYaaduwcCB7mmBYsi6vv9CYC1zJ9rq9yeQ,99435
36
36
  copyparty/bos/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
37
  copyparty/bos/bos.py,sha256=Wb7eWsXJgR5AFlBR9ZOyKrLTwy-Kct9RrGiOu4Jo37Y,1622
@@ -55,9 +55,9 @@ 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=r2c_hOZV_RTyl4CqWWX14FDWP8nnDVwGkDl4Sfk0rU4,8239
58
- copyparty/web/browser.css.gz,sha256=A44DddZBf-PEEMOj-u5YF_JrSk5DZYf-8f_J5jqC2is,11651
58
+ copyparty/web/browser.css.gz,sha256=_HiFW5vPUusWadoqdY8ZihuWizY9UECAc5nIamBPRi4,11654
59
59
  copyparty/web/browser.html,sha256=auvhLVE_t0aIN0q-nk0zOWFqITgDhroMAAviBNLoFfc,4788
60
- copyparty/web/browser.js.gz,sha256=Ec5tzZutoI8daxzHdfRfDP7L9ovDTY10j2g-hkeRlmA,91598
60
+ copyparty/web/browser.js.gz,sha256=7XJ99kbDhfTelhK92K2MhJu1f47XSHhYtztjAhxPOk4,92085
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
@@ -83,12 +83,12 @@ copyparty/web/splash.js.gz,sha256=4VqNznN10-bT33IJm3VWzBEJ1s08XZyxFB1TYPUkuAo,27
83
83
  copyparty/web/svcs.html,sha256=dnE1fG15zOpq7u0GYt8ij6BUv_LTwsiipFeneVYlMsM,14140
84
84
  copyparty/web/svcs.js.gz,sha256=lMXEP9W-VlXyANlva4q0ASSxvvHYlE2CrmxGgZXZop0,713
85
85
  copyparty/web/ui.css.gz,sha256=0sHIwGsL3_xH8Uu6N0Ag3bKBTjf-e_yfFbKynEZXAnk,2800
86
- copyparty/web/up2k.js.gz,sha256=N4idIqOefXurVh4ZhN6lv9nFPX_azLwE41vhXT2qBkI,23833
86
+ copyparty/web/up2k.js.gz,sha256=o3FAMh8TxmN7SfiI15yQddyR1JSpzhHWC4u6qztNJgY,24057
87
87
  copyparty/web/util.js.gz,sha256=wD3tP5j1iE5Uj5AvLW5zZbQJXDIFDlqgBTGdXeRVqo0,15110
88
88
  copyparty/web/w.hash.js.gz,sha256=l3GpSJD6mcU-1CRWkIj7PybgbjlfSr8oeO3vortIrQk,1105
89
89
  copyparty/web/a/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
90
90
  copyparty/web/a/partyfuse.py,sha256=9p5Hpg_IBiSimv7j9kmPhCGpy-FLXSRUOYnLjJ5JifU,28049
91
- copyparty/web/a/u2c.py,sha256=8F-uVfu0ceXRehbNLjjRfcBKStP5Lm_vJ_JAhEM6zgk,52994
91
+ copyparty/web/a/u2c.py,sha256=oRKEApPuaXiOkmUyA-WGCDjtWsn8FirSW6nCJtx9sgk,53157
92
92
  copyparty/web/a/webdav-cfg.bat,sha256=Y4NoGZlksAIg4cBMb7KdJrpKC6Nx97onaTl6yMjaimk,1449
93
93
  copyparty/web/dd/2.png,sha256=gJ14XFPzaw95L6z92fSq9eMPikSQyu-03P1lgiGe0_I,258
94
94
  copyparty/web/dd/3.png,sha256=4lho8Koz5tV7jJ4ODo6GMTScZfkqsT05yp48EDFIlyg,252
@@ -109,9 +109,9 @@ copyparty/web/deps/prismd.css.gz,sha256=ObUlksQVr-OuYlTz-I4B23TeBg2QDVVGRnWBz8cV
109
109
  copyparty/web/deps/scp.woff2,sha256=w99BDU5i8MukkMEL-iW0YO9H4vFFZSPWxbkH70ytaAg,8612
110
110
  copyparty/web/deps/sha512.ac.js.gz,sha256=lFZaCLumgWxrvEuDr4bqdKHsqjX82AbVAb7_F45Yk88,7033
111
111
  copyparty/web/deps/sha512.hw.js.gz,sha256=UAed2_ocklZCnIzcSYz2h4P1ycztlCLj-ewsRTud2lU,7939
112
- copyparty-1.16.13.dist-info/LICENSE,sha256=gOr4h33pCsBEg9uIy9AYmb7qlocL4V9t2uPJS5wllr0,1072
113
- copyparty-1.16.13.dist-info/METADATA,sha256=hm4IR2Xqc3bnZLZuEE3MPuNqwi73-IXzd_WqnVo_2NI,154166
114
- copyparty-1.16.13.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
115
- copyparty-1.16.13.dist-info/entry_points.txt,sha256=4zw6a3rqASywQomiYLObjjlxybaI65LYYOTJwgKz7b0,128
116
- copyparty-1.16.13.dist-info/top_level.txt,sha256=LnYUPsDyk-8kFgM6YJLG4h820DQekn81cObKSu9g-sI,10
117
- copyparty-1.16.13.dist-info/RECORD,,
112
+ copyparty-1.16.14.dist-info/LICENSE,sha256=gOr4h33pCsBEg9uIy9AYmb7qlocL4V9t2uPJS5wllr0,1072
113
+ copyparty-1.16.14.dist-info/METADATA,sha256=MwVuGqaNzreAqN-HP6IfmsOzEKGS6_iYy2BB3dCvFbU,157768
114
+ copyparty-1.16.14.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
115
+ copyparty-1.16.14.dist-info/entry_points.txt,sha256=4zw6a3rqASywQomiYLObjjlxybaI65LYYOTJwgKz7b0,128
116
+ copyparty-1.16.14.dist-info/top_level.txt,sha256=LnYUPsDyk-8kFgM6YJLG4h820DQekn81cObKSu9g-sI,10
117
+ copyparty-1.16.14.dist-info/RECORD,,