diff --git a/contrib/package/arch/PKGBUILD b/contrib/package/arch/PKGBUILD index 92423af8..40c0b62b 100644 --- a/contrib/package/arch/PKGBUILD +++ b/contrib/package/arch/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: icxes pkgname=copyparty -pkgver="1.18.8" +pkgver="1.18.9" pkgrel=1 pkgdesc="File server with accelerated resumable uploads, dedup, WebDAV, FTP, TFTP, zeroconf, media indexer, thumbnails++" arch=("any") @@ -22,7 +22,7 @@ optdepends=("ffmpeg: thumbnails for videos, images (slower) and audio, music tag ) source=("https://github.com/9001/${pkgname}/releases/download/v${pkgver}/${pkgname}-${pkgver}.tar.gz") backup=("etc/${pkgname}.d/init" ) -sha256sums=("d8af012f552a6f1dfc501d0ce94990b932d422df74f6afb66ca2a31985f5809b") +sha256sums=("d5d33b50d6717e52427956beb1687061a6f28b467997506505151e3ae18c58e5") build() { cd "${srcdir}/${pkgname}-${pkgver}" diff --git a/contrib/package/makedeb-mpr/PKGBUILD b/contrib/package/makedeb-mpr/PKGBUILD index 7f1b4b1e..227fc4cf 100644 --- a/contrib/package/makedeb-mpr/PKGBUILD +++ b/contrib/package/makedeb-mpr/PKGBUILD @@ -2,7 +2,7 @@ pkgname=copyparty -pkgver=1.18.8 +pkgver=1.18.9 pkgrel=1 pkgdesc="File server with accelerated resumable uploads, dedup, WebDAV, FTP, TFTP, zeroconf, media indexer, thumbnails++" arch=("any") @@ -20,7 +20,7 @@ optdepends=("ffmpeg: thumbnails for videos, images (slower) and audio, music tag ) source=("https://github.com/9001/${pkgname}/releases/download/v${pkgver}/${pkgname}-${pkgver}.tar.gz") backup=("/etc/${pkgname}.d/init" ) -sha256sums=("5bbda1e67f20a4a7fc10887235dba441544642d33c6d918f8a46867cda684572") +sha256sums=("d5d33b50d6717e52427956beb1687061a6f28b467997506505151e3ae18c58e5") build() { cd "${srcdir}/${pkgname}-${pkgver}/copyparty/web" diff --git a/contrib/package/nix/copyparty/pin.json b/contrib/package/nix/copyparty/pin.json index 1afe1c79..734dec31 100644 --- a/contrib/package/nix/copyparty/pin.json +++ b/contrib/package/nix/copyparty/pin.json @@ -1,5 +1,5 @@ { - "url": "https://github.com/9001/copyparty/releases/download/v1.18.8/copyparty-sfx.py", - "version": "1.18.8", - "hash": "sha256-ZQtpGVcC6fmJCC65hXN4v3ERiB3jPz+oqvFHtbxR8+o=" + "url": "https://github.com/9001/copyparty/releases/download/v1.18.9/copyparty-sfx.py", + "version": "1.18.9", + "hash": "sha256-R1OVx4f8GERAG80ZcHAIP6HK2TlBbKJZpvnJmJbGPRY=" } \ No newline at end of file diff --git a/copyparty/__version__.py b/copyparty/__version__.py index cd73581d..a82053fb 100644 --- a/copyparty/__version__.py +++ b/copyparty/__version__.py @@ -1,8 +1,8 @@ # coding: utf-8 -VERSION = (1, 18, 8) +VERSION = (1, 18, 9) CODENAME = "logtail" -BUILD_DT = (2025, 7, 31) +BUILD_DT = (2025, 8, 1) S_VERSION = ".".join(map(str, VERSION)) S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT) diff --git a/copyparty/httpcli.py b/copyparty/httpcli.py index 8f28fe5e..bea4ce43 100644 --- a/copyparty/httpcli.py +++ b/copyparty/httpcli.py @@ -107,6 +107,7 @@ from .util import ( sendfile_py, set_fperms, stat_resource, + str_anchor, ub64dec, ub64enc, ujoin, @@ -5369,9 +5370,9 @@ class HttpCli(object): raise Pebkac(500, "sqlite3 not found on server; unpost is disabled") raise Pebkac(500, "server busy, cannot unpost; please retry in a bit") - zs = self.uparam.get("filter") or "" - filt = re.compile(zs, re.I) if zs else None - lm = "ups %r" % (zs,) + sfilt = self.uparam.get("filter") or "" + nfi, vfi = str_anchor(sfilt) + lm = "ups %d%r" % (nfi, sfilt) if self.args.shr and self.vpath.startswith(self.args.shr1): shr_dbv, shr_vrem = self.vn.get_dbv(self.rem) @@ -5431,8 +5432,14 @@ class HttpCli(object): q = "select sz, rd, fn, at from up where ip=? and at>? order by at desc" for sz, rd, fn, at in cur.execute(q, (self.ip, lim)): vp = "/" + "/".join(x for x in [vol.vpath, rd, fn] if x) - if filt and not filt.search(vp): - continue + if nfi == 0 or (nfi == 1 and vfi in vp): + pass + elif nfi == 2: + if not vp.startswith(vfi): + continue + elif nfi == 3: + if not vp.endswith(vfi): + continue n -= 1 if not n: @@ -5513,8 +5520,8 @@ class HttpCli(object): raise Pebkac(500, "server busy, cannot list recent uploads; please retry") sfilt = self.uparam.get("filter") or "" - filt = re.compile(sfilt, re.I) if sfilt else None - lm = "ru %r" % (sfilt,) + nfi, vfi = str_anchor(sfilt) + lm = "ru %d%r" % (nfi, sfilt) self.log(lm) ret: list[dict[str, Any]] = [] @@ -5549,8 +5556,14 @@ class HttpCli(object): q = "select sz, rd, fn, ip, at from up where at>0 order by at desc" for sz, rd, fn, ip, at in cur.execute(q): vp = "/" + "/".join(x for x in [vol.vpath, rd, fn] if x) - if filt and not filt.search(vp): - continue + if nfi == 0 or (nfi == 1 and vfi in vp): + pass + elif nfi == 2: + if not vp.startswith(vfi): + continue + elif nfi == 3: + if not vp.endswith(vfi): + continue if not dots and "/." in vp: continue diff --git a/copyparty/up2k.py b/copyparty/up2k.py index ea2bbb57..ae5ed07f 100644 --- a/copyparty/up2k.py +++ b/copyparty/up2k.py @@ -402,7 +402,7 @@ class Up2k(object): def get_unfinished_by_user(self, uname, ip) -> dict[str, Any]: # returns dict due to ExceptionalQueue if PY2 or not self.reg_mutex.acquire(timeout=2): - return {"timeout":1} + return {"timeout": 1} ret: list[tuple[int, str, int, int, int]] = [] userset = set([(uname or "\n"), "*"]) diff --git a/copyparty/util.py b/copyparty/util.py index 73284bbb..15b1924b 100644 --- a/copyparty/util.py +++ b/copyparty/util.py @@ -2396,6 +2396,21 @@ def ujoin(rd: str, fn: str) -> str: return rd or fn +def str_anchor(txt) -> tuple[int, str]: + if not txt: + return 0, "" + txt = txt.lower() + a = txt.startswith("^") + b = txt.endswith("$") + if not b: + if not a: + return 1, txt # ~ + return 2, txt[1:] # ^ + if not a: + return 3, txt[:-1] # $ + return 4, txt[1:-1] # ^$ + + def log_reloc( log: "NamedLogger", re: dict[str, str], diff --git a/docs/changelog.md b/docs/changelog.md index 7a9571f1..5e1d7717 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,3 +1,81 @@ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +# 2025-0731-0833 `v1.18.8` sfx hotfix + +## 🩹 bugfixes + +* #354 fix `copyparty-sfx.py` failing to start on certain versions of python c17ce4892ecdb4e11437bc2785d132bd8100eaec + + + +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +# 2025-0730-2131 `v1.18.7` SECURITY: fix another XSS + +## ⚠️ ATTN: this release fixes an XSS vulnerability + +[GHSA-8mx2-rjh8-q3jq](https://github.com/9001/copyparty/security/advisories/GHSA-8mx2-rjh8-q3jq), could let an attacker execute arbitrary JS by tricking you into clicking a malicious URL + +Soon there won't be many of these left, surely. Huge thanks to @Ju0x for finding and reporting this. + +## 🧪 new features + +* #265 uid/gid for new files can be configured per-volume f1959988 + * has preconditions; [see readme](https://github.com/9001/copyparty#chmod-and-chown) +* #212 add German translation (thx @rGunti, @Scotsguy, @chocolateimage) 9d32564c + +## 🩹 bugfixes + +* GHSA-8mx2-rjh8-q3jq a8705e61 +* #276 windows: fix segfault (thx @kernel1994 for debugging!) a9d07c63 +* #272 webdav: send disk-size and disk-free to clients 4988a55e +* #285 use disk-free sans root-reserve on linux (thx @Arklaum!) c3cc2dde +* cors-check was funky on IPv6 e9684d40 +* #325 upgrade sharex example for newer versions 6016ec93 +* #300 restore support for old versions of python 2.7 b7ca6f4a + +## 🔧 other changes + +* shares: the config POST-target is now always the webroot (for ease of IdP configuration) fb7cbc42 +* unlist: now applies to the navpane too fbf17be2 +* windows: show disk-usage as well, not just disk-free 5c6341e9 +* #228 nix-pkg improvements (thx @dtomvan!) 4915b14b +* docker-compose: ensure logs appear in realtime 3cde1f3b +* mention that IdP-volumes and users [can now be persisted](https://github.com/9001/copyparty/blob/hovudstraum/docs/idp.md#but-you-can-enable-idp-volume-persistence) 6069bc9b +* #316 explain a scary-looking thing in the code 053de619 + + + +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +# 2025-0728-2320 `v1.18.6` reflink-dedup + +## 🧪 new features + +* #201 add support for reflink-based dedup on cow filesystems df9feabc + * combine `--dedup` with `--reflink` to enable, or volflags with same name + * a better and safer alternative to the other dedup approaches (symlink/hardlink), but only possible to use in some cases: + * needs linux 5.3 or newer, python 3.14 or newer, btrfs/xfs/zfs + * not available in the docker images yet; needs a new version of python, so maybe next alpine release (november/december 2025) +* ratelimit password changes to impede bruteforcing a2601fd6 + * limit is set by `--ban-pwc` (default is 5 changes in 60min) + +## 🩹 bugfixes + +* #240 nixos: fix unixgroups issue (thx @chinponya!) 7c9c962b +* #246 cbz: use correct page for thumbnail (thx @Scotsguy!) 542a1de1 + +## 🔧 other changes + +* volflag `nosub` now also prevents mkdir 0f2c6235 +* improve documentation: + * #229 use the same example UDS path everywhere cb019afe + * [example nginx config](https://github.com/9001/copyparty/blob/hovudstraum/contrib/nginx/copyparty.conf) had misleading cloudflare comment (thx @jmi2k!) 674fc1fe + * more readable `--help-chmod` 03d23dae + * #244 fix typo in `--help` 4f013f64 +* #242 hide "use real pw" on connectpage if no accounts (thx @toast003!) 025942a7 +* #211 docker: remove deprecated attribute (thx @ptweezy!) 5b98e104 +* #190 add the feature-showcase video to the readme (thx @RustoMCSpit!) 43e6da34 + + + ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ # 2025-0727-2305 `v1.18.5` SECURITY: fix XSS in media tags