Compare commits

...

20 commits

Author SHA1 Message Date
ed a5d859d2b1 smb: add ipv6 support; closes #1417 2026-04-11 00:17:05 +00:00
AppleTheGolden 0b16e875da
nixos: add override example (#1406) 2026-04-10 20:02:50 +00:00
chilledfrogs f5613187b4
improve *BSD compat (#1425)
reuse some macOS stuff since lsblk and /proc doesn't apply to *BSD
2026-04-10 20:02:01 +00:00
ed 003c68d027 readme: shadowing 2026-04-10 19:52:43 +00:00
ed 961a273764 autogrid global-option 2026-04-10 19:37:00 +00:00
ed 55d37364a6 indentation 2026-04-10 19:36:06 +00:00
ed 6b3419b38f mtl new strings 2026-04-10 19:11:09 +00:00
ed 660ed7a92e tl new strings 2026-04-10 19:09:59 +00:00
exci 822fa71800
add autogrid (#1407)
Co-authored-by: ed <s@ocv.me>
2026-04-10 18:33:28 +00:00
AppleTheGolden ed516ddc20
make .txt the default extension for text/plain (#1428)
`MIMES.items()` iterates in insertion order, so the last-inserted entry
had priority, meaning that `text/plain` got `ssa` as default extension.
2026-04-09 23:20:53 +00:00
ed ede692925e reset language too 2026-04-04 20:28:16 +00:00
stackxp ec3e0e7e1d
add --glang to use browser language (#1410)
Signed-off-by: ed <s@ocv.me>
Co-authored-by: ed <s@ocv.me>
2026-04-04 20:24:11 +00:00
ed d1517d0c65 catch the server-hdd phasing out of existence (and equally unexpected stuff) 2026-04-04 18:19:49 +00:00
mid-kid fb5384f412
readme: add gentoo packaging (#1387) 2026-04-02 20:36:52 +00:00
ed 971f8ef944 devnotes: vendored deps 2026-04-02 20:28:16 +00:00
exci 198f631ac8
fix playlist error on re-sorted filelists (#1403)
m3u files would get added (not good)
2026-03-31 19:02:11 +00:00
ed 5aaa4ff15b docs: volflags examples 2026-03-30 08:43:05 +00:00
Lomain 26e663d111
add fail2ban handler (#1352) 2026-03-25 04:08:35 +00:00
ed dcbdd9e665 versus: update pydio; closes #1385 2026-03-24 21:57:57 +00:00
ed 6a9e6da864 update pkgs to 1.20.13 2026-03-23 03:33:52 +00:00
44 changed files with 320 additions and 37 deletions

View file

@ -120,6 +120,7 @@ built in Norway 🇳🇴 with contributions from [not-norway](https://github.com
* [packages](#packages) - the party might be closer than you think * [packages](#packages) - the party might be closer than you think
* [arch package](#arch-package) - `pacman -S copyparty` (in [arch linux extra](https://archlinux.org/packages/extra/any/copyparty/)) * [arch package](#arch-package) - `pacman -S copyparty` (in [arch linux extra](https://archlinux.org/packages/extra/any/copyparty/))
* [fedora package](#fedora-package) - does not exist yet * [fedora package](#fedora-package) - does not exist yet
* [gentoo ::guru package](#gentoo-guru-package) - `emerge www-servers/copyparty::guru` (in [::guru](https://wiki.gentoo.org/wiki/Project:GURU))
* [homebrew formulae](#homebrew-formulae) - `brew install copyparty ffmpeg` * [homebrew formulae](#homebrew-formulae) - `brew install copyparty ffmpeg`
* [nix package](#nix-package) - `nix profile install github:9001/copyparty` * [nix package](#nix-package) - `nix profile install github:9001/copyparty`
* [nixos module](#nixos-module) * [nixos module](#nixos-module)
@ -607,10 +608,12 @@ and if you want to use config files instead of commandline args (good!) then her
hiding specific subfolders by mounting another volume on top of them hiding specific subfolders by mounting another volume on top of them
for example `-v /mnt::r -v /var/empty:web/certs:r` mounts the server folder `/mnt` as the webroot, but another volume is mounted at `/web/certs` -- so visitors can only see the contents of `/mnt` and `/mnt/web` (at URLs `/` and `/web`), but not `/mnt/web/certs` because URL `/web/certs` is mapped to `/var/empty` for example `-v /mnt::r -v /var/empty:web/certs:` (note: no permissions) mounts the server folder `/mnt` as the webroot, but another volume is mounted at `/web/certs` -- so visitors can only see the contents of `/mnt` and `/mnt/web` (at URLs `/` and `/web`), but not `/mnt/web/certs` because URL `/web/certs` is mapped to `/var/empty`
the example config file right above this section may explain this better; the first volume `/` is mapped to `/srv` which means http://127.0.0.1:3923/music would try to read `/srv/music` on the server filesystem, but since there's another volume at `/music` mapped to `/mnt/music` then it'll go to `/mnt/music` instead the example config file right above this section may explain this better; the first volume `/` is mapped to `/srv` which means http://127.0.0.1:3923/music would try to read `/srv/music` on the server filesystem, but since there's another volume at `/music` mapped to `/mnt/music` then it'll go to `/mnt/music` instead
so, to shadow a file/folder, define a volume but leave out the `accs:` section
> this also works for single files, because files can also be volumes > this also works for single files, because files can also be volumes
@ -2585,6 +2588,23 @@ after installing, start either the system service or the user service and naviga
does not exist yet; there are rumours that it is being packaged! keep an eye on this space... does not exist yet; there are rumours that it is being packaged! keep an eye on this space...
## gentoo ::guru package
`emerge www-servers/copyparty::guru` (in [::guru](https://wiki.gentoo.org/wiki/Project:GURU))
but first enable the `::guru` repo;
```bash
emerge -an app-eselect/eselect-repository
eselect repository enable guru
emerge --sync guru
```
to start the service as a user:
* OpenRC: `rc-service -U copyparty start && rc-update -U add copyparty default`
* systemd: [todo]
## homebrew formulae ## homebrew formulae
`brew install copyparty ffmpeg` -- https://formulae.brew.sh/formula/copyparty `brew install copyparty ffmpeg` -- https://formulae.brew.sh/formula/copyparty
@ -2729,6 +2749,12 @@ services.copyparty = {
}; };
# you may increase the open file limit for the process # you may increase the open file limit for the process
openFilesLimit = 8192; openFilesLimit = 8192;
# override the package used by the module to add dependencies, e.g. for hooks
package = pkgs.copyparty.override {
# provides exiftool for bin/hooks/image-noexif.py
extraPackages = [ pkgs.exiftool ];
};
}; };
``` ```

36
bin/handlers/404-to-fail2ban.py Executable file
View file

@ -0,0 +1,36 @@
# /!\ Warning: be careful, as webdav clients often generate a large number of 404 requets.
# In your `jail.local`, add:
# [copyparty]
# enabled = true
# logtimezone = UTC
# logpath = /path/to/log/file # or keep the default value if you're using systemd
# Create the `copyparty.conf` file in `filter.d` with the following:
# [Definition]
# failregex = ^ <ADDR>$
# ignoreregex =
# datepattern = ^fail2ban: %%Y-%%m-%%dT%%H:%%M:%%S
# First check `--dont-ban`, and if it doesn't match, log the line to be intercepted by fail2ban.
from datetime import datetime, UTC
def main(cli, vn="", rem=""):
now = datetime.now(UTC).isoformat()[:19]
msg = "\nfail2ban: %s %s"
if not vn and not rem:
# got called by --xban
cli["log"](msg % (now, cli["ip"]), 3)
return {"rc": 0}
cond = cli.args.dont_ban
if (
cond == "any"
or (cond == "auth" and cli.uname != "*")
or (cond == "aa" and cli.avol)
or (cond == "av" and cli.can_admin)
or (cond == "rw" and cli.can_read and cli.can_write)
):
return ""
cli.log(msg % (now, cli.ip), 3)
return ""

View file

@ -22,10 +22,11 @@ each plugin must define a `main()` which takes 3 arguments;
* [redirect.py](redirect.py) sends an HTTP 301 or 302, redirecting the client to another page/file * [redirect.py](redirect.py) sends an HTTP 301 or 302, redirecting the client to another page/file
* [randpic.py](randpic.py) redirects `/foo/bar/randpic.jpg` to a random pic in `/foo/bar/` * [randpic.py](randpic.py) redirects `/foo/bar/randpic.jpg` to a random pic in `/foo/bar/`
* [sorry.py](answer.py) replies with a custom message instead of the usual 404 * [sorry.py](sorry.py) replies with a custom message instead of the usual 404
* [nooo.py](nooo.py) replies with an endless noooooooooooooo * [nooo.py](nooo.py) replies with an endless noooooooooooooo
* [never404.py](never404.py) 100% guarantee that 404 will never be a thing again as it automatically creates dummy files whenever necessary * [never404.py](never404.py) 100% guarantee that 404 will never be a thing again as it automatically creates dummy files whenever necessary
* [caching-proxy.py](caching-proxy.py) transforms copyparty into a squid/varnish knockoff * [caching-proxy.py](caching-proxy.py) transforms copyparty into a squid/varnish knockoff
* [404-to-fail2ban.py](404-to-fail2ban.py) creates 404 logs for fail2ban
## on403 ## on403

View file

@ -3,7 +3,7 @@
# NOTE: You generally shouldn't use this PKGBUILD on Arch, as it is mainly for testing purposes. Install copyparty using pacman instead. # NOTE: You generally shouldn't use this PKGBUILD on Arch, as it is mainly for testing purposes. Install copyparty using pacman instead.
pkgname=copyparty pkgname=copyparty
pkgver="1.20.12" pkgver="1.20.13"
pkgrel=1 pkgrel=1
pkgdesc="File server with accelerated resumable uploads, dedup, WebDAV, SFTP, FTP, TFTP, zeroconf, media indexer, thumbnails++" pkgdesc="File server with accelerated resumable uploads, dedup, WebDAV, SFTP, FTP, TFTP, zeroconf, media indexer, thumbnails++"
arch=("any") arch=("any")
@ -24,7 +24,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") source=("https://github.com/9001/${pkgname}/releases/download/v${pkgver}/${pkgname}-${pkgver}.tar.gz")
backup=("etc/${pkgname}/copyparty.conf" ) backup=("etc/${pkgname}/copyparty.conf" )
sha256sums=("3acb98e9c577245517db92e77519caeac8a3e382dbc8704ec4a8701c7d58ba76") sha256sums=("b2af9250f7ef97a5df26df412ee082c6d2be0f0cd31d579b4fbb6aa2f3e5c271")
build() { build() {
cd "${srcdir}/${pkgname}-${pkgver}/copyparty/web" cd "${srcdir}/${pkgname}-${pkgver}/copyparty/web"

View file

@ -2,7 +2,7 @@
pkgname=copyparty pkgname=copyparty
pkgver=1.20.12 pkgver=1.20.13
pkgrel=1 pkgrel=1
pkgdesc="File server with accelerated resumable uploads, dedup, WebDAV, SFTP, FTP, TFTP, zeroconf, media indexer, thumbnails++" pkgdesc="File server with accelerated resumable uploads, dedup, WebDAV, SFTP, FTP, TFTP, zeroconf, media indexer, thumbnails++"
arch=("any") arch=("any")
@ -21,7 +21,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") source=("https://github.com/9001/${pkgname}/releases/download/v${pkgver}/${pkgname}-${pkgver}.tar.gz")
backup=("/etc/${pkgname}.d/init" ) backup=("/etc/${pkgname}.d/init" )
sha256sums=("3acb98e9c577245517db92e77519caeac8a3e382dbc8704ec4a8701c7d58ba76") sha256sums=("b2af9250f7ef97a5df26df412ee082c6d2be0f0cd31d579b4fbb6aa2f3e5c271")
build() { build() {
cd "${srcdir}/${pkgname}-${pkgver}/copyparty/web" cd "${srcdir}/${pkgname}-${pkgver}/copyparty/web"

View file

@ -1,5 +1,5 @@
{ {
"url": "https://github.com/9001/copyparty/releases/download/v1.20.12/copyparty-1.20.12.tar.gz", "url": "https://github.com/9001/copyparty/releases/download/v1.20.13/copyparty-1.20.13.tar.gz",
"version": "1.20.12", "version": "1.20.13",
"hash": "sha256-OsuY6cV3JFUX25LndRnK6sij44LbyHBOxKhwHH1YunY=" "hash": "sha256-sq+SUPfvl6XfJt9BLuCCxtK+DwzTHVebT7tqovPlwnE="
} }

View file

@ -38,5 +38,7 @@
accs: accs:
rw: * # everyone gets read-write access, but rw: * # everyone gets read-write access, but
rwmda: ed # the user "ed" gets read-write-move-delete-admin rwmda: ed # the user "ed" gets read-write-move-delete-admin
flags:
e2ds # enable filesystem-scanning for this volume only
# uid: 1000 # If you're running as root, you can change the owner of this volume here # uid: 1000 # If you're running as root, you can change the owner of this volume here
# gid: 1000 # If you're running as root, you can change the group of this volume here # gid: 1000 # If you're running as root, you can change the group of this volume here

View file

@ -49,3 +49,5 @@
accs: accs:
rw: * # everyone gets read-write access, but rw: * # everyone gets read-write access, but
rwmda: ed # the user "ed" gets read-write-move-delete-admin rwmda: ed # the user "ed" gets read-write-move-delete-admin
flags:
e2ds # enable filesystem-scanning for this volume only

View file

@ -44,6 +44,14 @@ ANYWIN = WINDOWS or sys.platform in ["msys", "cygwin"]
MACOS = platform.system() == "Darwin" MACOS = platform.system() == "Darwin"
FREEBSD = platform.system() == "FreeBSD"
OPENBSD = platform.system() == "OpenBSD"
ANYBSD = FREEBSD or OPENBSD
UNIX = MACOS or ANYBSD
GRAAL = platform.python_implementation() == "GraalVM" GRAAL = platform.python_implementation() == "GraalVM"
EXE = bool(getattr(sys, "frozen", False)) EXE = bool(getattr(sys, "frozen", False))

View file

@ -1520,6 +1520,7 @@ def add_smb(ap):
ap2.add_argument("--smb-nwa-1", action="store_true", help="truncate directory listings to 64kB (~400 files); avoids impacket-0.11 bug, fixes impacket-0.12 performance") ap2.add_argument("--smb-nwa-1", action="store_true", help="truncate directory listings to 64kB (~400 files); avoids impacket-0.11 bug, fixes impacket-0.12 performance")
ap2.add_argument("--smb-nwa-2", action="store_true", help="disable impacket workaround for filecopy globs") ap2.add_argument("--smb-nwa-2", action="store_true", help="disable impacket workaround for filecopy globs")
ap2.add_argument("--smba", action="store_true", help="small performance boost: disable per-account permissions, enables account coalescing instead (if one user has write/delete-access, then everyone does)") ap2.add_argument("--smba", action="store_true", help="small performance boost: disable per-account permissions, enables account coalescing instead (if one user has write/delete-access, then everyone does)")
ap2.add_argument("--smb6", action="store_true", help="enable IPv6")
ap2.add_argument("--smbv", action="store_true", help="verbose") ap2.add_argument("--smbv", action="store_true", help="verbose")
ap2.add_argument("--smbvv", action="store_true", help="verboser") ap2.add_argument("--smbvv", action="store_true", help="verboser")
ap2.add_argument("--smbvvv", action="store_true", help="verbosest") ap2.add_argument("--smbvvv", action="store_true", help="verbosest")
@ -1868,8 +1869,10 @@ def add_ui(ap, retry: int):
ap2.add_argument("--gsel", action="store_true", help="select files in grid by ctrl-click (volflag=gsel)") ap2.add_argument("--gsel", action="store_true", help="select files in grid by ctrl-click (volflag=gsel)")
ap2.add_argument("--localtime", action="store_true", help="default to local timezone instead of UTC") ap2.add_argument("--localtime", action="store_true", help="default to local timezone instead of UTC")
ap2.add_argument("--ui-filesz", metavar="FMT", type=u, default="1", help="default filesize format; one of these: 0, 1, 2, 2c, 3, 3c, 4, 4c, 5, 5c, fuzzy (see UI)") ap2.add_argument("--ui-filesz", metavar="FMT", type=u, default="1", help="default filesize format; one of these: 0, 1, 2, 2c, 3, 3c, 4, 4c, 5, 5c, fuzzy (see UI)")
ap2.add_argument("--gauto", metavar="PERCENT", type=int, default=0, help="switch to gridview if more than \033[33mPERCENT\033[0m of files are pics/vids; 0=disabled")
ap2.add_argument("--rcm", metavar="TXT", default="yy", help="rightclick-menu; two yes/no options: 1st y/n is enable-custom-menu, 2nd y/n is enable-double") ap2.add_argument("--rcm", metavar="TXT", default="yy", help="rightclick-menu; two yes/no options: 1st y/n is enable-custom-menu, 2nd y/n is enable-double")
ap2.add_argument("--lang", metavar="LANG", type=u, default="eng", help="language, for example \033[32meng\033[0m / \033[32mnor\033[0m / ...") ap2.add_argument("--lang", metavar="LANG", type=u, default="eng", help="language, for example \033[32meng\033[0m / \033[32mnor\033[0m / ...")
ap2.add_argument("--glang", action="store_true", help="guess the browser's default language, otherwise fall back to \033[33m--lang\033[0m")
ap2.add_argument("--theme", metavar="NUM", type=int, default=0, help="default theme to use (0..%d)" % (THEMES - 1,)) ap2.add_argument("--theme", metavar="NUM", type=int, default=0, help="default theme to use (0..%d)" % (THEMES - 1,))
ap2.add_argument("--themes", metavar="NUM", type=int, default=THEMES, help="number of themes installed") ap2.add_argument("--themes", metavar="NUM", type=int, default=THEMES, help="number of themes installed")
ap2.add_argument("--au-vol", metavar="0-100", type=int, default=50, choices=range(0, 101), help="default audio/video volume percent") ap2.add_argument("--au-vol", metavar="0-100", type=int, default=50, choices=range(0, 101), help="default audio/video volume percent")

View file

@ -3258,6 +3258,7 @@ class AuthSrv(object):
"idxh": int(self.args.ih), "idxh": int(self.args.ih),
"dutc": not self.args.localtime, "dutc": not self.args.localtime,
"dfszf": self.args.ui_filesz.strip("-"), "dfszf": self.args.ui_filesz.strip("-"),
"dgauto": self.args.gauto,
"themes": self.args.themes, "themes": self.args.themes,
"turbolvl": self.args.turbo, "turbolvl": self.args.turbo,
"nosubtle": self.args.nosubtle, "nosubtle": self.args.nosubtle,
@ -3273,7 +3274,7 @@ class AuthSrv(object):
for zs in zs.split(): for zs in zs.split():
if vf.get(zs): if vf.get(zs):
js_htm[zs] = 1 js_htm[zs] = 1
zs = "notooltips" zs = "glang notooltips"
for zs in zs.split(): for zs in zs.split():
if getattr(self.args, zs, False): if getattr(self.args, zs, False):
js_htm[zs] = 1 js_htm[zs] = 1

View file

@ -7,7 +7,7 @@ import os
import re import re
import time import time
from .__init__ import ANYWIN, MACOS from .__init__ import ANYWIN, FREEBSD, MACOS, UNIX
from .authsrv import AXS, VFS, AuthSrv from .authsrv import AXS, VFS, AuthSrv
from .bos import bos from .bos import bos
from .util import chkcmd, json_hesc, min_ex, undot from .util import chkcmd, json_hesc, min_ex, undot
@ -88,7 +88,7 @@ class Fstab(object):
def _from_sp_mount(self) -> dict[str, str]: def _from_sp_mount(self) -> dict[str, str]:
sptn = r"^.*? on (.*) type ([^ ]+) \(.*" sptn = r"^.*? on (.*) type ([^ ]+) \(.*"
if MACOS: if MACOS or FREEBSD:
sptn = r"^.*? on (.*) \(([^ ]+), .*" sptn = r"^.*? on (.*) \(([^ ]+), .*"
ptn = re.compile(sptn) ptn = re.compile(sptn)
@ -118,7 +118,7 @@ class Fstab(object):
def build_tab(self) -> None: def build_tab(self) -> None:
self.log("inspecting mtab for changes") self.log("inspecting mtab for changes")
dtab = self._from_sp_mount() if MACOS else self._from_proc() dtab = self._from_sp_mount() if UNIX else self._from_proc()
# keep empirically-correct values if mounttab unchanged # keep empirically-correct values if mounttab unchanged
srctab = str(sorted(dtab.items())) srctab = str(sorted(dtab.items()))
@ -130,7 +130,7 @@ class Fstab(object):
try: try:
fuses = [mp for mp, fs in dtab.items() if fs == "fuseblk"] fuses = [mp for mp, fs in dtab.items() if fs == "fuseblk"]
if not fuses or MACOS: if not fuses or UNIX:
raise Exception() raise Exception()
try: try:
so, _ = chkcmd(["lsblk", "-nrfo", "FSTYPE,MOUNTPOINT"]) # centos6 so, _ = chkcmd(["lsblk", "-nrfo", "FSTYPE,MOUNTPOINT"]) # centos6

View file

@ -154,7 +154,7 @@ _ = (argparse, threading)
USED4SEC = {"usedforsecurity": False} if sys.version_info > (3, 9) else {} USED4SEC = {"usedforsecurity": False} if sys.version_info > (3, 9) else {}
ALL_COOKIES = "k304 no304 js idxh dots cppwd cppws".split() ALL_COOKIES = "cplng cppwd cppws dots idxh js k304 no304".split()
BADXFF = " due to dangerous misconfiguration (the http-header specified by --xff-hdr was received from an untrusted reverse-proxy)" BADXFF = " due to dangerous misconfiguration (the http-header specified by --xff-hdr was received from an untrusted reverse-proxy)"
BADXFF2 = ". Some copyparty features are now disabled as a safety measure.\n\n\n" BADXFF2 = ". Some copyparty features are now disabled as a safety measure.\n\n\n"

View file

@ -22,7 +22,7 @@ from .__init__ import TYPE_CHECKING, EnvParams
from .authsrv import AuthSrv # typechk from .authsrv import AuthSrv # typechk
from .httpcli import HttpCli from .httpcli import HttpCli
from .u2idx import U2idx from .u2idx import U2idx
from .util import HMaccas, NetMap, shut_socket from .util import HMaccas, NetMap, min_ex, shut_socket
if True: # pylint: disable=using-constant-test if True: # pylint: disable=using-constant-test
from typing import Optional, Pattern, Union from typing import Optional, Pattern, Union
@ -194,12 +194,12 @@ class HttpConn(object):
except Exception as ex: except Exception as ex:
em = str(ex) em = str(ex)
if "ALERT_CERTIFICATE_UNKNOWN" in em: if "ALERT_" in em:
# android-chrome keeps doing this self.log("client refused our TLS cert or config: " + em, c=6)
pass
else: else:
self.log("handshake\033[0m " + em, c=5) t = "https-handshake failed, probably due to client:\n"
self.log(t + min_ex(), c=5)
return return

View file

@ -89,13 +89,15 @@ class SMB(object):
smbserver.isInFileJail = self._is_in_file_jail smbserver.isInFileJail = self._is_in_file_jail
self._disarm() self._disarm()
ip = next((x for x in self.args.smb_i if ":" not in x), None) zs = " " if self.args.smb6 else ":"
ip = next((x for x in self.args.smb_i if zs not in x), None)
if not ip: if not ip:
self.log("smb", "IPv6 not supported for SMB; listening on 0.0.0.0", 3) self.log("smb", "IPv6 not enabled with --smb6; listening on 0.0.0.0", 3)
ip = "0.0.0.0" ip = "0.0.0.0"
port = int(self.args.smb_port) port = int(self.args.smb_port)
srv = smbserver.SimpleSMBServer(listenAddress=ip, listenPort=port) kw = {"ipv6": True} if ":" in ip else {}
srv = smbserver.SimpleSMBServer(listenAddress=ip, listenPort=port, **kw)
try: try:
if self.accs: if self.accs:
srv.setAuthCallback(self._auth_cb) srv.setAuthCallback(self._auth_cb)
@ -121,6 +123,7 @@ class SMB(object):
self.srv = srv self.srv = srv
self.stop = srv.stop self.stop = srv.stop
ip = "[%s]" % (ip,) if kw else ip
self.log("smb", "listening @ {}:{}".format(ip, port)) self.log("smb", "listening @ {}:{}".format(ip, port))
def nlog(self, msg: str, c: Union[int, str] = 0) -> None: def nlog(self, msg: str, c: Union[int, str] = 0) -> None:

View file

@ -7,7 +7,7 @@ import socket
import sys import sys
import time import time
from .__init__ import ANYWIN, PY2, TYPE_CHECKING, unicode from .__init__ import ANYWIN, OPENBSD, PY2, TYPE_CHECKING, UNIX, unicode
from .cert import gencert from .cert import gencert
from .qrkode import QrCode, qr2png, qr2svg, qr2txt, qrgen from .qrkode import QrCode, qr2png, qr2svg, qr2txt, qrgen
from .util import ( from .util import (
@ -510,6 +510,13 @@ class TcpSrv(object):
return eps return eps
def _extdevs_nix(self) -> Generator[str, None, None]: def _extdevs_nix(self) -> Generator[str, None, None]:
if UNIX:
so, _ = chkcmd(["netstat", "-nrf", "inet"])
for ln in so.split("\n"):
if not ln.startswith("default"):
continue
yield ln.split()[7] if OPENBSD else ln.split()[3]
return
with open("/proc/net/route", "rb") as f: with open("/proc/net/route", "rb") as f:
next(f) next(f)
for ln in f: for ln in f:

View file

@ -491,13 +491,12 @@ font woff woff2 otf ttf
for v in vs.strip().split(): for v in vs.strip().split():
MIMES[v] = "{}/{}".format(k, v) MIMES[v] = "{}/{}".format(k, v)
for ln in """text md=plain txt=plain js=javascript for ln in """text md=plain js=javascript ass=plain ssa=plain txt=plain
application 7z=x-7z-compressed tar=x-tar bz2=x-bzip2 gz=gzip rar=x-rar-compressed zst=zstd xz=x-xz lz=lzip cpio=x-cpio application 7z=x-7z-compressed tar=x-tar bz2=x-bzip2 gz=gzip rar=x-rar-compressed zst=zstd xz=x-xz lz=lzip cpio=x-cpio
application msi=x-ms-installer cab=vnd.ms-cab-compressed rpm=x-rpm crx=x-chrome-extension application msi=x-ms-installer cab=vnd.ms-cab-compressed rpm=x-rpm crx=x-chrome-extension
application epub=epub+zip mobi=x-mobipocket-ebook lit=x-ms-reader rss=rss+xml atom=atom+xml torrent=x-bittorrent application epub=epub+zip mobi=x-mobipocket-ebook lit=x-ms-reader rss=rss+xml atom=atom+xml torrent=x-bittorrent
application p7s=pkcs7-signature dcm=dicom shx=vnd.shx shp=vnd.shp dbf=x-dbf gml=gml+xml gpx=gpx+xml amf=x-amf application p7s=pkcs7-signature dcm=dicom shx=vnd.shx shp=vnd.shp dbf=x-dbf gml=gml+xml gpx=gpx+xml amf=x-amf
application swf=x-shockwave-flash m3u=vnd.apple.mpegurl db3=vnd.sqlite3 sqlite=vnd.sqlite3 application swf=x-shockwave-flash m3u=vnd.apple.mpegurl db3=vnd.sqlite3 sqlite=vnd.sqlite3
text ass=plain ssa=plain
image jpg=jpeg xpm=x-xpixmap psd=vnd.adobe.photoshop jpf=jpx tif=tiff ico=x-icon djvu=vnd.djvu image jpg=jpeg xpm=x-xpixmap psd=vnd.adobe.photoshop jpf=jpx tif=tiff ico=x-icon djvu=vnd.djvu
image heics=heic-sequence heifs=heif-sequence hdr=vnd.radiance svg=svg+xml image heics=heic-sequence heifs=heif-sequence hdr=vnd.radiance svg=svg+xml
image arw=x-sony-arw cr2=x-canon-cr2 crw=x-canon-crw dcr=x-kodak-dcr dng=x-adobe-dng erf=x-epson-erf image arw=x-sony-arw cr2=x-canon-cr2 crw=x-canon-crw dcr=x-kodak-dcr dng=x-adobe-dng erf=x-epson-erf

View file

@ -2,7 +2,7 @@
var J_BRW = 1; var J_BRW = 1;
if (window.rw_edit === undefined) if (window.dgauto === undefined)
alert('FATAL ERROR: receiving stale data from the server; this may be due to a broken reverse-proxy (stuck cache). Try restarting copyparty and press CTRL-SHIFT-R in the browser'); alert('FATAL ERROR: receiving stale data from the server; this may be due to a broken reverse-proxy (stuck cache). Try restarting copyparty and press CTRL-SHIFT-R in the browser');
var XHR = XMLHttpRequest; var XHR = XMLHttpRequest;
@ -228,6 +228,7 @@ if (1)
"cl_hpick": "tap on column headers to hide in the table below", "cl_hpick": "tap on column headers to hide in the table below",
"cl_hcancel": "column hiding aborted", "cl_hcancel": "column hiding aborted",
"cl_rcm": "right-click menu", "cl_rcm": "right-click menu",
"cl_gauto": "autogrid",
"ct_grid": '田 the grid', "ct_grid": '田 the grid',
"ct_ttips": '◔ ◡ ◔"> tooltips', "ct_ttips": '◔ ◡ ◔"> tooltips',
@ -282,6 +283,8 @@ if (1)
"tt_dynt": "autogrow as tree expands", "tt_dynt": "autogrow as tree expands",
"tt_wrap": "word wrap", "tt_wrap": "word wrap",
"tt_hover": "reveal overflowing lines on hover$N( breaks scrolling unless mouse $N&nbsp; cursor is in the left gutter )", "tt_hover": "reveal overflowing lines on hover$N( breaks scrolling unless mouse $N&nbsp; cursor is in the left gutter )",
"tt_gauto": "display as grid or list depending on folder contents",
"tt_gathr": "use grid if this percentage of files are pics/vids",
"ml_pmode": "at end of folder...", "ml_pmode": "at end of folder...",
"ml_btns": "cmds", "ml_btns": "cmds",
@ -713,6 +716,54 @@ var L = Ls[lang] || Ls.eng, LANGS = [];
for (var a = 0; a < LANGN.length; a++) for (var a = 0; a < LANGN.length; a++)
LANGS.push(LANGN[a][0]); LANGS.push(LANGN[a][0]);
if (window.glang && navigator.languages && !/\bcplng=/.test(document.cookie))
(function() {
var lmap = [
["eng", /^en/i],
["nor", /^n[ob]/i],
["chi", /^zh-cn/i],
["cze", /^cs/i],
["deu", /^de/i],
["epo", /^eo/i],
["fin", /^fi/i],
["fra", /^fr/i],
["grc", /^el/i],
["hun", /^hu/i],
["ita", /^it/i],
["jpn", /^ja/i],
["kor", /^ko/i],
["nld", /^nl/i],
["nno", /^nn/i],
["pol", /^pl/i],
["por", /^pt/i],
["rus", /^ru/i],
["spa", /^es/i],
["swe", /^sv/i],
["tur", /^tr/i],
["ukr", /^uk/i],
["vie", /^vi/i],
];
for (var a = 0; a < navigator.languages.length; a++) {
for (var b = 0; b < lmap.length; b++) {
var n = lmap[b][0];
if (!lmap[b][1].test(navigator.languages[a]) || !has(LANGS, n))
continue;
if (Ls[n]) {
lang = n;
L = Ls[n];
return;
}
if (window.stop)
window.stop();
document.body.innerHTML = 'Loading ' + n;
setck("cplng=" + n, location.reload.bind(location));
crashed = true;
throw 1;
}
}
})();
function langtest() { function langtest() {
var n = LANGS.length - 1; var n = LANGS.length - 1;
@ -721,7 +772,9 @@ function langtest() {
} }
function langtest2() { function langtest2() {
for (var a = 0; a < LANGS.length; a++) { for (var a = 0; a < LANGS.length; a++) {
if (!Ls[LANGS[a]]) continue;
for (var b = a + 1; b < LANGS.length; b++) { for (var b = a + 1; b < LANGS.length; b++) {
if (!Ls[LANGS[b]]) continue;
var i1 = Object.keys(Ls[LANGS[a]]).length > Object.keys(Ls[LANGS[b]]).length ? a : b, var i1 = Object.keys(Ls[LANGS[a]]).length > Object.keys(Ls[LANGS[b]]).length ? a : b,
i2 = i1 == a ? b : a, i2 = i1 == a ? b : a,
t1 = Ls[LANGS[i1]], t1 = Ls[LANGS[i1]],
@ -735,6 +788,7 @@ for (var a = 0; a < LANGS.length; a++) {
} }
} }
} }
langtest2();
@ -936,6 +990,13 @@ ebi('op_cfg').innerHTML = (
' </div>\n' + ' </div>\n' +
'</div>\n' + '</div>\n' +
'<div>\n' + '<div>\n' +
' <h3>' + L.cl_gauto + '</h3>\n' +
' <div>\n' +
' <a id="gauto" class="tgl btn" href="#" tt="' + L.tt_gauto + '">' + L.enable + '</a>\n' +
' <input type="text" id="ga_thresh" value="" ' + NOAC + ' style="width:1.5em" tt="' + L.tt_gathr + '" />' +
' </div>\n' +
'</div>\n' +
'<div>\n' +
' <h3>' + L.cl_hfsz + '</h3>\n' + ' <h3>' + L.cl_hfsz + '</h3>\n' +
' <div><select id="fszfmt">\n' + ' <div><select id="fszfmt">\n' +
' <option value="0">0 ┃ 1234567</option>\n' + ' <option value="0">0 ┃ 1234567</option>\n' +
@ -1155,9 +1216,7 @@ onresize100.add(read_sbw, true);
function check_image_support(format, uri) { function check_image_support(format, uri) {
var cached var cached = window['have_' + format] = sread('have_' + format);
= window['have_' + format]
= sread('have_' + format);
if (cached !== null) if (cached !== null)
return; return;
@ -1719,7 +1778,9 @@ function MPlayer() {
if (!tid || tid.indexOf('af-') !== 0) if (!tid || tid.indexOf('af-') !== 0)
continue; continue;
order.push(tid.slice(1)); tid = tid.slice(1);
if (r.tracks[tid])
order.push(tid);
} }
r.order = order; r.order = order;
r.shuffle(); r.shuffle();
@ -5557,6 +5618,16 @@ var thegrid = (function () {
r.setvis(); r.setvis();
}; };
r.autogrid = function (res) {
var ni = 0;
var nf = res.files.length;
for (var a = 0; a < nf; a++)
if (img_re.test('.' + res.files[a].ext))
ni++;
if (nf)
thegrid.en = 100 * ni / nf >= r.gathr;
};
function setln(v) { function setln(v) {
if (v) { if (v) {
r.ln += v; r.ln += v;
@ -5944,6 +6015,17 @@ var thegrid = (function () {
pbar.onresize(); pbar.onresize();
vbar.onresize(); vbar.onresize();
}); });
bcfg_bind(r, 'gaen', 'gauto', !!dgauto, function(v) {
if (r.en && sread("griden") != 1) {
r.en = false;
r.setvis(true);
}
});
ebi('ga_thresh').value = r.gathr = icfg_get('ga_thresh', dgauto || 70);
ebi('ga_thresh').oninput = function (e) {
var n = parseInt(this.value);
swrite('ga_thresh', r.gathr = (isNum(n) ? n : 0) || 70);
};
ebi('wtgrid').onclick = ebi('griden').onclick; ebi('wtgrid').onclick = ebi('griden').onclick;
return r; return r;
@ -7656,6 +7738,9 @@ var treectl = (function () {
} }
} }
if (thegrid.gaen && sread('griden') != 1)
thegrid.autogrid(res);
if (url) setTimeout(asdf, 1); else asdf(); if (url) setTimeout(asdf, 1); else asdf();
} }

View file

@ -221,6 +221,7 @@ Ls.chi = {
"cl_hpick": "在下方文件列表中点击某列表头即可从表中隐去该列", "cl_hpick": "在下方文件列表中点击某列表头即可从表中隐去该列",
"cl_hcancel": "列隐藏操作已中止", "cl_hcancel": "列隐藏操作已中止",
"cl_rcm": "右键菜单", "cl_rcm": "右键菜单",
"cl_gauto": "自动网格", //m
"ct_grid": '田 网格', "ct_grid": '田 网格',
"ct_ttips": '◔ ◡ ◔"> 提示', "ct_ttips": '◔ ◡ ◔"> 提示',
@ -275,6 +276,8 @@ Ls.chi = {
"tt_dynt": "自动随着目录树展开而变宽", "tt_dynt": "自动随着目录树展开而变宽",
"tt_wrap": "自动换行", "tt_wrap": "自动换行",
"tt_hover": "悬停时完整显示出写不下的文字$N启用后鼠标光标只有$N&nbsp; 位于左边线上才滚得动)", "tt_hover": "悬停时完整显示出写不下的文字$N启用后鼠标光标只有$N&nbsp; 位于左边线上才滚得动)",
"tt_gauto": "根据文件夹内容以网格或列表显示", //m
"tt_gathr": "当此比例的文件为图片/视频时使用网格", //m
"ml_pmode": "文件夹播完后", "ml_pmode": "文件夹播完后",
"ml_btns": "命令", "ml_btns": "命令",

View file

@ -225,6 +225,7 @@ Ls.cze = {
"cl_hpick": "klepněte na záhlaví sloupců pro skrytí v tabulce níže", "cl_hpick": "klepněte na záhlaví sloupců pro skrytí v tabulce níže",
"cl_hcancel": "skrývání sloupců zrušeno", "cl_hcancel": "skrývání sloupců zrušeno",
"cl_rcm": "kontextová nabídka", //m "cl_rcm": "kontextová nabídka", //m
"cl_gauto": "auto mřížka", //m
"ct_grid": '田 mřížka', "ct_grid": '田 mřížka',
"ct_ttips": '◔ ◡ ◔"> nápovědy', "ct_ttips": '◔ ◡ ◔"> nápovědy',
@ -279,6 +280,8 @@ Ls.cze = {
"tt_dynt": "automaticky rozrůstat jak se strom rozšiřuje", "tt_dynt": "automaticky rozrůstat jak se strom rozšiřuje",
"tt_wrap": "zalomení řádků", "tt_wrap": "zalomení řádků",
"tt_hover": "odhalit přetékající řádky při najetí$N( ruší posun pokud kurzor myši $N&nbsp; není v levém okraji )", "tt_hover": "odhalit přetékající řádky při najetí$N( ruší posun pokud kurzor myši $N&nbsp; není v levém okraji )",
"tt_gauto": "zobrazit jako mřížku nebo seznam podle obsahu složky", //m
"tt_gathr": "použít mřížku, pokud toto procento souborů tvoří obrázky/videa", //m
"ml_pmode": "na konci složky...", "ml_pmode": "na konci složky...",
"ml_btns": "příkazy", "ml_btns": "příkazy",

View file

@ -221,6 +221,7 @@ Ls.deu = {
"cl_hpick": "zum Verstecken, tippe auf Spaltenüberschriften in der Tabelle unten", "cl_hpick": "zum Verstecken, tippe auf Spaltenüberschriften in der Tabelle unten",
"cl_hcancel": "Spaltenbearbeitung abgebrochen", "cl_hcancel": "Spaltenbearbeitung abgebrochen",
"cl_rcm": "Rechtsklick-Menü", "cl_rcm": "Rechtsklick-Menü",
"cl_gauto": "auto-raster", //m
"ct_grid": '田 Das Raster&trade;', "ct_grid": '田 Das Raster&trade;',
"ct_ttips": '◔ ◡ ◔"> Tooltips', "ct_ttips": '◔ ◡ ◔"> Tooltips',
@ -275,6 +276,8 @@ Ls.deu = {
"tt_dynt": "autom. wachsen wenn Baum wächst", "tt_dynt": "autom. wachsen wenn Baum wächst",
"tt_wrap": "Zeilenumbruch", "tt_wrap": "Zeilenumbruch",
"tt_hover": "Beim Hovern überlange Zeilen anzeigen$N(Scrollen funktioniert nicht ausser $N&nbsp; Cursor ist im linken Gutter)", "tt_hover": "Beim Hovern überlange Zeilen anzeigen$N(Scrollen funktioniert nicht ausser $N&nbsp; Cursor ist im linken Gutter)",
"tt_gauto": "je nach ordnerinhalt als raster oder liste anzeigen", //m
"tt_gathr": "raster verwenden, wenn dieser prozentsatz der dateien bilder/videos sind", //m
"ml_pmode": "am Ende des Ordners...", "ml_pmode": "am Ende des Ordners...",
"ml_btns": "cmds", "ml_btns": "cmds",

View file

@ -221,6 +221,7 @@ Ls.epo = {
"cl_hpick": "alklaki la kapojn de kolumnoj por kasi en la suban tabelon", "cl_hpick": "alklaki la kapojn de kolumnoj por kasi en la suban tabelon",
"cl_hcancel": "kaŝado de kolumno nuligita", "cl_hcancel": "kaŝado de kolumno nuligita",
"cl_rcm": "dekstra-klaka menuo", "cl_rcm": "dekstra-klaka menuo",
"cl_gauto": "aŭto田", //m
"ct_grid": '田 krado', "ct_grid": '田 krado',
"ct_ttips": '◔ ◡ ◔"> ŝpruchelpiloj', "ct_ttips": '◔ ◡ ◔"> ŝpruchelpiloj',
@ -275,6 +276,8 @@ Ls.epo = {
"tt_dynt": "aŭtomate pligrandigi panelon", "tt_dynt": "aŭtomate pligrandigi panelon",
"tt_wrap": "linifaldo", "tt_wrap": "linifaldo",
"tt_hover": "montri kompletajn nomojn sur musumo$N( paneas rulumadon, se la kursoro de muso $N&nbsp; ne estas en la maldekstra malplenaĵo )", "tt_hover": "montri kompletajn nomojn sur musumo$N( paneas rulumadon, se la kursoro de muso $N&nbsp; ne estas en la maldekstra malplenaĵo )",
"tt_gauto": "montri kiel krado aŭ listo laŭ dosieruja enhavo", //m
"tt_gathr": "uzi kradon se ĉi tiu procento de dosieroj estas bildoj/filmetoj", //m
"ml_pmode": "je la fino de dosierujo...", "ml_pmode": "je la fino de dosierujo...",
"ml_btns": "komandoj", "ml_btns": "komandoj",

View file

@ -221,6 +221,7 @@ Ls.fin = {
"cl_hpick": "napauta sarakeotsikoita piilottaaksesi alla olevassa taulukossa", "cl_hpick": "napauta sarakeotsikoita piilottaaksesi alla olevassa taulukossa",
"cl_hcancel": "sarakkeiden piilotus peruttu", "cl_hcancel": "sarakkeiden piilotus peruttu",
"cl_rcm": "hiiren pikavalikko", "cl_rcm": "hiiren pikavalikko",
"cl_gauto": "auto田", //m
"ct_grid": '田 kuvanäkymä', "ct_grid": '田 kuvanäkymä',
"ct_ttips": '◔ ◡ ◔"> vihjelaatikot', "ct_ttips": '◔ ◡ ◔"> vihjelaatikot',
@ -275,6 +276,8 @@ Ls.fin = {
"tt_dynt": "kasvata automaattisesti hakemistosyvyyden kasvaessa", "tt_dynt": "kasvata automaattisesti hakemistosyvyyden kasvaessa",
"tt_wrap": "rivitys", "tt_wrap": "rivitys",
"tt_hover": "paljasta ylivuotavat rivit leijutettaessa$N( rikkoo vierityksen ellei hiiri $N&nbsp; ole vasemmassa marginaalissa )", "tt_hover": "paljasta ylivuotavat rivit leijutettaessa$N( rikkoo vierityksen ellei hiiri $N&nbsp; ole vasemmassa marginaalissa )",
"tt_gauto": "näytä ruudukkona tai listana kansion sisällön mukaan", //m
"tt_gathr": "käytä ruudukkoa jos tämä prosentti tiedostoista on kuvia/videoita", //m
"ml_pmode": "hakemiston lopussa...", "ml_pmode": "hakemiston lopussa...",
"ml_btns": "komennot", "ml_btns": "komennot",

View file

@ -221,6 +221,7 @@ Ls.fra = {
"cl_hpick": "cliquez sur les en-têtes de colonnes pour les masquer dans le tableau ci-dessous", "cl_hpick": "cliquez sur les en-têtes de colonnes pour les masquer dans le tableau ci-dessous",
"cl_hcancel": "masquage des colonnes annulé", "cl_hcancel": "masquage des colonnes annulé",
"cl_rcm": "menu contextuel", //m "cl_rcm": "menu contextuel", //m
"cl_gauto": "auto-grille", //m
"ct_grid": '田 grille', "ct_grid": '田 grille',
"ct_ttips": '◔ ◡ ◔"> infobulles', "ct_ttips": '◔ ◡ ◔"> infobulles',
@ -275,6 +276,8 @@ Ls.fra = {
"tt_dynt": "croissance automatique à mesure que l'arborescence s'étend", "tt_dynt": "croissance automatique à mesure que l'arborescence s'étend",
"tt_wrap": "retour à la ligne", "tt_wrap": "retour à la ligne",
"tt_hover": "révéler les lignes débordantes au survol$N( interrompt le défilement à moins que le curseur de la souris ne soit dans la gouttière gauche )", "tt_hover": "révéler les lignes débordantes au survol$N( interrompt le défilement à moins que le curseur de la souris ne soit dans la gouttière gauche )",
"tt_gauto": "afficher en grille ou liste selon le contenu du dossier", //m
"tt_gathr": "utiliser la grille si ce pourcentage de fichiers sont des images/vidéos", //m
"ml_pmode": "à la fin du dossier…", "ml_pmode": "à la fin du dossier…",
"ml_btns": "cmds", "ml_btns": "cmds",

View file

@ -221,6 +221,7 @@ Ls.grc = {
"cl_hpick": "πάτησε στις κεφαλίδες στηλών για να τις κρύψεις στον πίνακα παρακάτω", "cl_hpick": "πάτησε στις κεφαλίδες στηλών για να τις κρύψεις στον πίνακα παρακάτω",
"cl_hcancel": "η απόκρυψη στηλών ακυρώθηκε", "cl_hcancel": "η απόκρυψη στηλών ακυρώθηκε",
"cl_rcm": "μενού δεξιού κλικ", //m "cl_rcm": "μενού δεξιού κλικ", //m
"cl_gauto": "αυτόματο田", //m
"ct_grid": '田 το πλέγμα', "ct_grid": '田 το πλέγμα',
"ct_ttips": '◔ ◡ ◔"> συμβουλές εργαλείων', "ct_ttips": '◔ ◡ ◔"> συμβουλές εργαλείων',
@ -275,6 +276,8 @@ Ls.grc = {
"tt_dynt": "αυτόματη επέκταση καθώς επεκτείνεται το δέντρο διαδρομών", "tt_dynt": "αυτόματη επέκταση καθώς επεκτείνεται το δέντρο διαδρομών",
"tt_wrap": "αναδίπλωση λέξεων", "tt_wrap": "αναδίπλωση λέξεων",
"tt_hover": "αποκάλυψη των γραμμών που ξεπερνούν το πλάτος με το ποντίκι πάνω τους$N( σπάει το scroll εκτός αν το ποντίκι $N&nbsp; είναι στην αριστερή στήλη )", "tt_hover": "αποκάλυψη των γραμμών που ξεπερνούν το πλάτος με το ποντίκι πάνω τους$N( σπάει το scroll εκτός αν το ποντίκι $N&nbsp; είναι στην αριστερή στήλη )",
"tt_gauto": "εμφάνιση ως πλέγμα ή λίστα ανάλογα με τα περιεχόμενα του φακέλου", //m
"tt_gathr": "χρήση πλέγματος αν αυτό το ποσοστό αρχείων είναι εικόνες/βίντεο", //m
"ml_pmode": "στο τέλος του φακέλου...", "ml_pmode": "στο τέλος του φακέλου...",
"ml_btns": "εντολές", "ml_btns": "εντολές",

View file

@ -222,6 +222,7 @@ Ls.hun = {
"cl_hpick": 'kattints az oszlopfejlécre az elrejtéshez', "cl_hpick": 'kattints az oszlopfejlécre az elrejtéshez',
"cl_hcancel": 'elrejtés megszakítva', "cl_hcancel": 'elrejtés megszakítva',
"cl_rcm": 'jobb-klikkes menü', "cl_rcm": 'jobb-klikkes menü',
"cl_gauto": "auto田", //m
"ct_grid": '田 rács nézet', "ct_grid": '田 rács nézet',
"ct_ttips": '◔ ◡ ◔"> segítő szövegek', "ct_ttips": '◔ ◡ ◔"> segítő szövegek',
@ -276,6 +277,8 @@ Ls.hun = {
"tt_dynt": 'automatikus méretezés nyitáskor', "tt_dynt": 'automatikus méretezés nyitáskor',
"tt_wrap": 'sortörés', "tt_wrap": 'sortörés',
"tt_hover": 'túl hosszú sorok mutatása rámutatáskor', "tt_hover": 'túl hosszú sorok mutatása rámutatáskor',
"tt_gauto": "megjelenítés rácsban vagy listában a mappa tartalmától függően", //m
"tt_gathr": "rács használata, ha a fájlok ezen százaléka kép/videó", //m
"ml_pmode": 'mappa végén...', "ml_pmode": 'mappa végén...',
"ml_btns": 'gombok', "ml_btns": 'gombok',

View file

@ -221,6 +221,7 @@ Ls.ita = {
"cl_hpick": "tocca le intestazioni delle colonne per nascondere nella tabella sottostante", "cl_hpick": "tocca le intestazioni delle colonne per nascondere nella tabella sottostante",
"cl_hcancel": "nascondere colonne annullato", "cl_hcancel": "nascondere colonne annullato",
"cl_rcm": "menu contestuale", //m "cl_rcm": "menu contestuale", //m
"cl_gauto": "auto田", //m
"ct_grid": '田 griglia', "ct_grid": '田 griglia',
"ct_ttips": '◔ ◡ ◔"> tooltip', "ct_ttips": '◔ ◡ ◔"> tooltip',
@ -275,6 +276,8 @@ Ls.ita = {
"tt_dynt": "crescita automatica mentre l'albero si espande", "tt_dynt": "crescita automatica mentre l'albero si espande",
"tt_wrap": "a capo parola", "tt_wrap": "a capo parola",
"tt_hover": "rivela righe che traboccano al passaggio del mouse$N( interrompe lo scorrimento a meno che il cursore $N&nbsp; del mouse non sia nella grondaia sinistra )", "tt_hover": "rivela righe che traboccano al passaggio del mouse$N( interrompe lo scorrimento a meno che il cursore $N&nbsp; del mouse non sia nella grondaia sinistra )",
"tt_gauto": "mostra come griglia o lista in base al contenuto della cartella", //m
"tt_gathr": "usa la griglia se questa percentuale di file sono immagini/video", //m
"ml_pmode": "alla fine della cartella...", "ml_pmode": "alla fine della cartella...",
"ml_btns": "comandi", "ml_btns": "comandi",

View file

@ -221,6 +221,7 @@ Ls.jpn = {
"cl_hpick": "下の表で非表示にするには列ヘッダーをタップします", "cl_hpick": "下の表で非表示にするには列ヘッダーをタップします",
"cl_hcancel": "列の非表示を解除", "cl_hcancel": "列の非表示を解除",
"cl_rcm": "右クリックメニュー", "cl_rcm": "右クリックメニュー",
"cl_gauto": "自動グリッド", //m
"ct_grid": '田 グリッド', "ct_grid": '田 グリッド',
"ct_ttips": '◔ ◡ ◔"> ツールチップ', "ct_ttips": '◔ ◡ ◔"> ツールチップ',
@ -275,6 +276,8 @@ Ls.jpn = {
"tt_dynt": "ツリーが拡大するにつれて自動的に増加", "tt_dynt": "ツリーが拡大するにつれて自動的に増加",
"tt_wrap": "単語の折り返し", "tt_wrap": "単語の折り返し",
"tt_hover": "ホバーすると溢れた線を表示する$N( マウスを押さない限りスクロールが中断されます $N&nbsp; カーソルは左余白です )", "tt_hover": "ホバーすると溢れた線を表示する$N( マウスを押さない限りスクロールが中断されます $N&nbsp; カーソルは左余白です )",
"tt_gauto": "フォルダー内容に応じてグリッドまたはリスト表示", //m
"tt_gathr": "この割合のファイルが画像/動画ならグリッドを使用", //m
"ml_pmode": "フォルダの末尾...", "ml_pmode": "フォルダの末尾...",
"ml_btns": "コマンド", "ml_btns": "コマンド",

View file

@ -221,6 +221,7 @@ Ls.kor = {
"cl_hpick": "아래 테이블에서 숨기고 싶은 열의 헤더를 탭하세요", "cl_hpick": "아래 테이블에서 숨기고 싶은 열의 헤더를 탭하세요",
"cl_hcancel": "열 숨기기가 중단되었습니다", "cl_hcancel": "열 숨기기가 중단되었습니다",
"cl_rcm": "우클릭 메뉴", //m "cl_rcm": "우클릭 메뉴", //m
"cl_gauto": "자동 田", //m
"ct_grid": "田 그리드", "ct_grid": "田 그리드",
"ct_ttips": '◔ ◡ ◔"> 도움말', "ct_ttips": '◔ ◡ ◔"> 도움말',
@ -275,6 +276,8 @@ Ls.kor = {
"tt_dynt": "트리가 확장될 때 자동으로 너비 증가", "tt_dynt": "트리가 확장될 때 자동으로 너비 증가",
"tt_wrap": "자동 줄 바꿈", "tt_wrap": "자동 줄 바꿈",
"tt_hover": "마우스를 올리면 넘어가는 줄 표시$N(마우스 커서가 왼쪽 여백에$N&nbsp; 있지 않으면 스크롤이 깨짐)", "tt_hover": "마우스를 올리면 넘어가는 줄 표시$N(마우스 커서가 왼쪽 여백에$N&nbsp; 있지 않으면 스크롤이 깨짐)",
"tt_gauto": "폴더 내용에 따라 그리드 또는 목록으로 표시", //m
"tt_gathr": "파일 중 이 비율이 이미지/동영상이면 그리드 사용", //m
"ml_pmode": "폴더 끝에서...", "ml_pmode": "폴더 끝에서...",
"ml_btns": "명령", "ml_btns": "명령",

View file

@ -221,6 +221,7 @@ Ls.nld = {
"cl_hpick": "Tik op de kolomkoppen om ze in de onderstaande tabel te verbergen", "cl_hpick": "Tik op de kolomkoppen om ze in de onderstaande tabel te verbergen",
"cl_hcancel": "Kolumn verbergen geannuleerd", "cl_hcancel": "Kolumn verbergen geannuleerd",
"cl_rcm": "Rechtermuisknopmenu", //m "cl_rcm": "Rechtermuisknopmenu", //m
"cl_gauto": "auto田", //m
"ct_grid": '田 grid', "ct_grid": '田 grid',
"ct_ttips": '◔ ◡ ◔"> tooltips', "ct_ttips": '◔ ◡ ◔"> tooltips',
@ -275,6 +276,8 @@ Ls.nld = {
"tt_dynt": "Automatisch groeien naarmate de directoryboom zich uitbreidt", "tt_dynt": "Automatisch groeien naarmate de directoryboom zich uitbreidt",
"tt_wrap": "Automatische terugloop", "tt_wrap": "Automatische terugloop",
"tt_hover": "Laat overlopenden lijnen zien bij zweven$N(stopt het scrollen tenzij de muis in de linker gedeelte van het scherm is)", "tt_hover": "Laat overlopenden lijnen zien bij zweven$N(stopt het scrollen tenzij de muis in de linker gedeelte van het scherm is)",
"tt_gauto": "weergeven als grid of lijst afhankelijk van mapinhoud", //m
"tt_gathr": "gebruik grid als dit percentage bestanden afbeeldingen/video's zijn", //m
"ml_pmode": "Aan het einde van de map...", "ml_pmode": "Aan het einde van de map...",
"ml_btns": "Cmds", "ml_btns": "Cmds",

View file

@ -218,6 +218,7 @@ Ls.nno = {
"cl_hpick": "klikk på overskrifta åt kolonnene du ønskjer å skjule i tabellen nedanfor", "cl_hpick": "klikk på overskrifta åt kolonnene du ønskjer å skjule i tabellen nedanfor",
"cl_hcancel": "kolonne-skjuling avbrote", "cl_hcancel": "kolonne-skjuling avbrote",
"cl_rcm": "høgreklikkmeny", "cl_rcm": "høgreklikkmeny",
"cl_gauto": "auto田",
"ct_grid": '田 ikon', "ct_grid": '田 ikon',
"ct_ttips": 'vis hjelpetekst ved å holde musa over ting"> tips', "ct_ttips": 'vis hjelpetekst ved å holde musa over ting"> tips',
@ -272,6 +273,8 @@ Ls.nno = {
"tt_dynt": "øk bredda på panelet ettersom treet utvider seg", "tt_dynt": "øk bredda på panelet ettersom treet utvider seg",
"tt_wrap": "linjebryting", "tt_wrap": "linjebryting",
"tt_hover": "vis heile mappenamnet når musepeikaren treff mappa$N( gjer diverre at scrollhjulet fusker dersom musepeikaren ikkje finn seg i grøfta )", "tt_hover": "vis heile mappenamnet når musepeikaren treff mappa$N( gjer diverre at scrollhjulet fusker dersom musepeikaren ikkje finn seg i grøfta )",
"tt_gauto": "byt visingsmodus (liste/ikon) avhengig av mappeinnhald",
"tt_gathr": "vis som ikon når denne prosentdelen er bilete/videoar",
"ml_pmode": "ved enden av mappa", "ml_pmode": "ved enden av mappa",
"ml_btns": "knapper", "ml_btns": "knapper",

View file

@ -218,6 +218,7 @@ Ls.nor = {
"cl_hpick": "klikk på overskriften til kolonnene du ønsker å skjule i tabellen nedenfor", "cl_hpick": "klikk på overskriften til kolonnene du ønsker å skjule i tabellen nedenfor",
"cl_hcancel": "kolonne-skjuling avbrutt", "cl_hcancel": "kolonne-skjuling avbrutt",
"cl_rcm": "høyreklikkmeny", "cl_rcm": "høyreklikkmeny",
"cl_gauto": "auto田",
"ct_grid": '田 ikoner', "ct_grid": '田 ikoner',
"ct_ttips": 'vis hjelpetekst ved å holde musen over ting"> tips', "ct_ttips": 'vis hjelpetekst ved å holde musen over ting"> tips',
@ -272,6 +273,8 @@ Ls.nor = {
"tt_dynt": "øk bredden på panelet ettersom treet utvider seg", "tt_dynt": "øk bredden på panelet ettersom treet utvider seg",
"tt_wrap": "linjebryting", "tt_wrap": "linjebryting",
"tt_hover": "vis hele mappenavnet når musepekeren treffer mappen$N( gjør dessverre at scrollhjulet fusker dersom musepekeren ikke befinner seg i grøfta )", "tt_hover": "vis hele mappenavnet når musepekeren treffer mappen$N( gjør dessverre at scrollhjulet fusker dersom musepekeren ikke befinner seg i grøfta )",
"tt_gauto": "bytt visningsmodus (liste/ikoner) avhengig av mappeinnhold",
"tt_gathr": "vis som ikoner når denne prosentandelen er bilder/videoer",
"ml_pmode": "ved enden av mappen", "ml_pmode": "ved enden av mappen",
"ml_btns": "knapper", "ml_btns": "knapper",

View file

@ -224,6 +224,7 @@ Ls.pol = {
"cl_hpick": "kliknij nagłówki kolumn, aby ukryć je w tabeli niżej", "cl_hpick": "kliknij nagłówki kolumn, aby ukryć je w tabeli niżej",
"cl_hcancel": "ukrywanie kolumn przerwane", "cl_hcancel": "ukrywanie kolumn przerwane",
"cl_rcm": "menu kontekstowe", //m "cl_rcm": "menu kontekstowe", //m
"cl_gauto": "auto田", //m
"ct_grid": '田 siatka', "ct_grid": '田 siatka',
"ct_ttips": '◔ ◡ ◔"> podpowiedzi', "ct_ttips": '◔ ◡ ◔"> podpowiedzi',
@ -278,6 +279,8 @@ Ls.pol = {
"tt_dynt": "rozszerzaj panel wraz z drzewem", "tt_dynt": "rozszerzaj panel wraz z drzewem",
"tt_wrap": "zawijaj tekst", "tt_wrap": "zawijaj tekst",
"tt_hover": "pokazuj za długie linie po najechaniu kursorem$N( psuje przewijanie gdy $N&nbsp; kursor nie jest w lewym marginesie )", "tt_hover": "pokazuj za długie linie po najechaniu kursorem$N( psuje przewijanie gdy $N&nbsp; kursor nie jest w lewym marginesie )",
"tt_gauto": "wyświetl jako siatkę lub listę w zależności od zawartości folderu", //m
"tt_gathr": "użyj siatki, jeśli ten procent plików to obrazy/wideo", //m
"ml_pmode": "na końcu folderu...", "ml_pmode": "na końcu folderu...",
"ml_btns": "komendy", "ml_btns": "komendy",

View file

@ -221,6 +221,7 @@ Ls.por = {
"cl_hpick": "toque nos cabeçalhos das colunas para ocultá-los na tabela abaixo", "cl_hpick": "toque nos cabeçalhos das colunas para ocultá-los na tabela abaixo",
"cl_hcancel": "ocultar coluna abortado", "cl_hcancel": "ocultar coluna abortado",
"cl_rcm": "menu de clique direito", "cl_rcm": "menu de clique direito",
"cl_gauto": "auto田", //m
"ct_grid": '田 a grade', "ct_grid": '田 a grade',
"ct_ttips": '◔ ◡ ◔"> dicas de ferramentas', "ct_ttips": '◔ ◡ ◔"> dicas de ferramentas',
@ -275,6 +276,8 @@ Ls.por = {
"tt_dynt": "crescer automaticamente à medida que a árvore se expande", "tt_dynt": "crescer automaticamente à medida que a árvore se expande",
"tt_wrap": "quebra de linha", "tt_wrap": "quebra de linha",
"tt_hover": "revelar linhas transbordando ao passar o mouse$N( quebra a rolagem a menos que o cursor do mouse $N&nbsp; esteja na margem esquerda )", "tt_hover": "revelar linhas transbordando ao passar o mouse$N( quebra a rolagem a menos que o cursor do mouse $N&nbsp; esteja na margem esquerda )",
"tt_gauto": "exibir como grade ou lista dependendo do conteúdo da pasta", //m
"tt_gathr": "usar grade se esta porcentagem de arquivos for imagens/vídeos", //m
"ml_pmode": "ao final da pasta...", "ml_pmode": "ao final da pasta...",
"ml_btns": "comandos", "ml_btns": "comandos",

View file

@ -221,6 +221,7 @@ Ls.rus = {
"cl_hpick": "нажмите на заголовки столбцов, чтобы скрыть их в таблице ниже", "cl_hpick": "нажмите на заголовки столбцов, чтобы скрыть их в таблице ниже",
"cl_hcancel": "скрытие столбца отменено", "cl_hcancel": "скрытие столбца отменено",
"cl_rcm": "контекстное меню", //m "cl_rcm": "контекстное меню", //m
"cl_gauto": "авто田", //m
"ct_grid": '田 сетка', "ct_grid": '田 сетка',
"ct_ttips": '◔ ◡ ◔"> подсказки', "ct_ttips": '◔ ◡ ◔"> подсказки',
@ -275,6 +276,8 @@ Ls.rus = {
"tt_dynt": "автоматическое расширение панели", "tt_dynt": "автоматическое расширение панели",
"tt_wrap": "перенос слов", "tt_wrap": "перенос слов",
"tt_hover": "раскрывать обрезанные строки при наведении$N( ломает скроллинг, если $N&nbsp; курсор не в пустоте слева )", "tt_hover": "раскрывать обрезанные строки при наведении$N( ломает скроллинг, если $N&nbsp; курсор не в пустоте слева )",
"tt_gauto": "показывать как сетку или список в зависимости от содержимого папки", //m
"tt_gathr": "использовать сетку, если этот процент файлов — изображения/видео", //m
"ml_pmode": "в конце папки...", "ml_pmode": "в конце папки...",
"ml_btns": "команды", "ml_btns": "команды",

View file

@ -220,6 +220,7 @@ Ls.spa = {
"cl_hpick": "toca en las cabeceras de columna para ocultarlas en la tabla de abajo", "cl_hpick": "toca en las cabeceras de columna para ocultarlas en la tabla de abajo",
"cl_hcancel": "ocultación de columna cancelada", "cl_hcancel": "ocultación de columna cancelada",
"cl_rcm": "menú contextual", //m "cl_rcm": "menú contextual", //m
"cl_gauto": "auto田", //m
"ct_grid": '田 cuadrícula', "ct_grid": '田 cuadrícula',
"ct_ttips": '◔ ◡ ◔"> tooltips', "ct_ttips": '◔ ◡ ◔"> tooltips',
@ -274,6 +275,8 @@ Ls.spa = {
"tt_dynt": "crecimiento automático a medida que el árbol se expande", "tt_dynt": "crecimiento automático a medida que el árbol se expande",
"tt_wrap": "ajuste de línea", "tt_wrap": "ajuste de línea",
"tt_hover": "revelar líneas que se desbordan al pasar el ratón$N( rompe el desplazamiento a menos que el $N&nbsp; cursor esté en el margen izquierdo )", "tt_hover": "revelar líneas que se desbordan al pasar el ratón$N( rompe el desplazamiento a menos que el $N&nbsp; cursor esté en el margen izquierdo )",
"tt_gauto": "mostrar como cuadrícula o lista según el contenido de la carpeta", //m
"tt_gathr": "usar cuadrícula si este porcentaje de archivos son imágenes/videos", //m
"ml_pmode": "al final de la carpeta...", "ml_pmode": "al final de la carpeta...",
"ml_btns": "acciones", "ml_btns": "acciones",

View file

@ -221,6 +221,7 @@ Ls.swe = {
"cl_hpick": "tryck på en kolumntitel för att dölja den i filvyn", "cl_hpick": "tryck på en kolumntitel för att dölja den i filvyn",
"cl_hcancel": "kolumndöljning avbruten", "cl_hcancel": "kolumndöljning avbruten",
"cl_rcm": "högerklicksmeny", //m "cl_rcm": "högerklicksmeny", //m
"cl_gauto": "auto田", //m
"ct_grid": '田 rutnätet', "ct_grid": '田 rutnätet',
"ct_ttips": '◔ ◡ ◔"> tips', "ct_ttips": '◔ ◡ ◔"> tips',
@ -275,6 +276,8 @@ Ls.swe = {
"tt_dynt": "väx vyn när trädet expanderar", "tt_dynt": "väx vyn när trädet expanderar",
"tt_wrap": "automatisk radbrytning", "tt_wrap": "automatisk radbrytning",
"tt_hover": "visa överlånga rader när muspekaren hovrar över dem$N( skrollhjulet fungerar ej såvida inte pekaren$Nstår till vänster )", "tt_hover": "visa överlånga rader när muspekaren hovrar över dem$N( skrollhjulet fungerar ej såvida inte pekaren$Nstår till vänster )",
"tt_gauto": "visa som rutnät eller lista beroende på mappens innehåll", //m
"tt_gathr": "använd rutnät om denna andel filer är bilder/videor", //m
"ml_pmode": "vid mappens slut...", "ml_pmode": "vid mappens slut...",
"ml_btns": "komm.", "ml_btns": "komm.",

View file

@ -221,6 +221,7 @@ Ls.tur = {
"cl_hpick": "aşağıdaki tabloda gizlemek için sütun başlıklarına dokunun", "cl_hpick": "aşağıdaki tabloda gizlemek için sütun başlıklarına dokunun",
"cl_hcancel": "sütun gizleme iptal edildi", "cl_hcancel": "sütun gizleme iptal edildi",
"cl_rcm": "sağ tık menüsü", //m "cl_rcm": "sağ tık menüsü", //m
"cl_gauto": "otomatik田", //m
"ct_grid": '田 ızgara', "ct_grid": '田 ızgara',
"ct_ttips": '◔ ◡ ◔"> ipuçları', "ct_ttips": '◔ ◡ ◔"> ipuçları',
@ -275,6 +276,8 @@ Ls.tur = {
"tt_dynt": "ağaç genişledikçe otomatik büyüt", "tt_dynt": "ağaç genişledikçe otomatik büyüt",
"tt_wrap": "kelime sarma", "tt_wrap": "kelime sarma",
"tt_hover": "fare ile üzerine gelindiğinde taşan satırları göster$N( fare imleci sol kenarda değilse kaydırmayı bozar )", "tt_hover": "fare ile üzerine gelindiğinde taşan satırları göster$N( fare imleci sol kenarda değilse kaydırmayı bozar )",
"tt_gauto": "klasör içeriğine bağlı olarak ızgara veya liste olarak göster", //m
"tt_gathr": "dosyaların bu yüzdesi resim/video ise ızgara kullan", //m
"ml_pmode": "klasör sonunda...", "ml_pmode": "klasör sonunda...",
"ml_btns": "komutlar", "ml_btns": "komutlar",

View file

@ -221,6 +221,7 @@ Ls.ukr = {
"cl_hpick": "натисніть на заголовки стовпців, щоб приховати їх у таблиці нижче", "cl_hpick": "натисніть на заголовки стовпців, щоб приховати їх у таблиці нижче",
"cl_hcancel": "приховання стовпців скасовано", "cl_hcancel": "приховання стовпців скасовано",
"cl_rcm": "контекстне меню", //m "cl_rcm": "контекстне меню", //m
"cl_gauto": "авто田", //m
"ct_grid": '田 сітка', "ct_grid": '田 сітка',
"ct_ttips": '◔ ◡ ◔"> підказки', "ct_ttips": '◔ ◡ ◔"> підказки',
@ -275,6 +276,8 @@ Ls.ukr = {
"tt_dynt": "автоматично збільшуватися при розширенні дерева", "tt_dynt": "автоматично збільшуватися при розширенні дерева",
"tt_wrap": "перенесення слів", "tt_wrap": "перенесення слів",
"tt_hover": "показувати переповнені рядки при наведенні$N( порушує прокрутку, якщо курсор $N&nbsp; миші не знаходиться в лівому відступі )", "tt_hover": "показувати переповнені рядки при наведенні$N( порушує прокрутку, якщо курсор $N&nbsp; миші не знаходиться в лівому відступі )",
"tt_gauto": "показувати як сітку або список залежно від вмісту папки", //m
"tt_gathr": "використовувати сітку, якщо цей відсоток файлів — зображення/відео", //m
"ml_pmode": "в кінці папки...", "ml_pmode": "в кінці папки...",
"ml_btns": "команди", "ml_btns": "команди",

View file

@ -221,6 +221,7 @@ Ls.vie = {
"cl_hpick": "chạm vào tiêu đề cột để ẩn trong bảng bên dưới", "cl_hpick": "chạm vào tiêu đề cột để ẩn trong bảng bên dưới",
"cl_hcancel": "đã hủy việc ẩn cột", "cl_hcancel": "đã hủy việc ẩn cột",
"cl_rcm": "menu chuột phải", //m "cl_rcm": "menu chuột phải", //m
"cl_gauto": "lưới tự động", //m
// settings / tuỳ chọn // settings / tuỳ chọn
"ct_grid": '田 chế độ lưới', "ct_grid": '田 chế độ lưới',
@ -279,6 +280,8 @@ Ls.vie = {
"tt_dynt": "tự mở rộng khi cây mở rộng", "tt_dynt": "tự mở rộng khi cây mở rộng",
"tt_wrap": "ngắt dòng", "tt_wrap": "ngắt dòng",
"tt_hover": "hiện thị dòng tràn khi rê chuột$N( không cuộn được nếu $N&nbsp; con trỏ chuột nằm ngoài cột trái )", "tt_hover": "hiện thị dòng tràn khi rê chuột$N( không cuộn được nếu $N&nbsp; con trỏ chuột nằm ngoài cột trái )",
"tt_gauto": "hiển thị dạng lưới hoặc danh sách tùy theo nội dung thư mục", //m
"tt_gathr": "dùng lưới nếu tỷ lệ tệp này là ảnh/video", //m
"ml_pmode": "ở cuối thư mục...", "ml_pmode": "ở cuối thư mục...",
"ml_btns": "lệnh", "ml_btns": "lệnh",

View file

@ -359,6 +359,48 @@ for the `re`pack to work, first run one of the sfx'es once to unpack it
**note:** you can also just download and run [/scripts/copyparty-repack.sh](https://github.com/9001/copyparty/blob/hovudstraum/scripts/copyparty-repack.sh) -- this will grab the latest copyparty release from github and do a few repacks; works on linux/macos (and windows with msys2 or WSL) **note:** you can also just download and run [/scripts/copyparty-repack.sh](https://github.com/9001/copyparty/blob/hovudstraum/scripts/copyparty-repack.sh) -- this will grab the latest copyparty release from github and do a few repacks; works on linux/macos (and windows with msys2 or WSL)
# dependencies
## vendored dependencies
some third-party code has been vendored into the git repo; some for convenience, some because they have been lightly hacked to fit copyparty's usecase better:
* inside the folder [/copyparty/stolen](https://github.com/9001/copyparty/tree/hovudstraum/copyparty/stolen) is python-libraries which runs on the serverside:
* `surrogateescape.py` (BSD2) can be removed; only needed for python2 support
* `qrcodegen.py` (MIT) can be removed and replaced with a systemwide install of the original [qrcodegen.py](https://github.com/nayuki/QR-Code-generator/blob/daa3114/python/qrcodegen.py);
* modifications: removed code/features that copyparty does not need/use
* `ifaddr` (BSD2) can be removed and replaced with a systemwide install of the original [ifaddr](https://github.com/ifaddr/ifaddr);
* modifications: support python2, support s390x / irix32 / graal
* `dnslib` (MIT) may be deleted and replaced with a systemwide install of the original [dnslib](https://github.com/paulc/dnslib/), HOWEVER:
* will cause problems for mDNS in some network environments; 6c1cf68bca7376c6291c3cfe710ebd5bd5ed3e6c + 94d1924fa97e5faaf1ebfd85cae73faebcb89fa1
* inside the folder `/copyparty/web/deps` (only in distributed archives/builds) is [fuse.py](https://github.com/fusepy/fusepy/blob/master/fuse.py), to make it downloadable from the connect-page on the web-ui
* inside the folder `/copyparty/web` (only in distributed archives/builds) is a collection of javascript libraries (produced by [deps-docker](https://github.com/9001/copyparty/tree/hovudstraum/scripts/deps-docker)) which are used clientside by the web-UI:
* [marked.js](https://github.com/markedjs/marked/releases) (MIT) powers the markdown editor, and has been [patched](https://github.com/9001/copyparty/blob/hovudstraum/scripts/deps-docker/marked-ln.patch) to include the line-numbers of each input line, to enable scroll-sync between the editor and the preview-pane. This patch is [not strictly necessary anymore](https://github.com/markedjs/marked/issues/2134) but I haven't gotten around to making the change yet
* [easyMDE](https://github.com/Ionaru/easy-markdown-editor/) (MIT), the alternative markdown editor, has the same [patch](https://github.com/9001/copyparty/blob/hovudstraum/scripts/deps-docker/easymde-ln.patch) to enable scroll-sync, and also some [size-golfing](https://github.com/9001/copyparty/blob/hovudstraum/scripts/deps-docker/easymde.patch)
* [codemirror5](https://github.com/codemirror/codemirror5/) (MIT) has no noteworthy changes, and has only been [size-golfed](https://github.com/9001/copyparty/blob/hovudstraum/scripts/deps-docker/codemirror.patch), could have been used as-is
* [DOMPurify](https://github.com/cure53/DOMPurify) (Apache2) is used as-is
* [hash-wasm](https://github.com/Daninet/hash-wasm/) (MIT) is used entirely as-is
* [asmcrypto.js](https://github.com/openpgpjs/asmcrypto.js/) (MIT) is abandoned software, and used almost as-is (slightly golfed for size); it is probably fine to exclude/remove this, since it will only break support for uploading from really old browsers (IE10/IE11) using up2k (the "fancy uploader")
* [prism.js](https://github.com/PrismJS/prism/) (MIT) is built with a [selection of languages](https://github.com/9001/copyparty/blob/hovudstraum/scripts/deps-docker/genprism.py); there is an assumption about the exact subset of languages elsewhere in copyparty, but there shouldn't be any big consequences of replacing it with a different build if that exists in Fedora
* an old version of [SourceCodePro](https://github.com/adobe-fonts/source-code-pro) (OFL-1.1), is size-reduced to [only the necessary characters](https://github.com/9001/copyparty/blob/41ed559faabdc180efc37fd027e7f1bb2d14d174/scripts/deps-docker/mini-fa.sh#L30-L31). There will be subtle layout issues if this is replaced with a newer version, because they changed some line-heights or something in later versions, but shouldn't be a big issue
* an old version of [font-awesome](https://github.com/FortAwesome/Font-Awesome) (OFL-1.1), size-reduced to [only the necessary icons](https://github.com/9001/copyparty/blob/hovudstraum/scripts/deps-docker/mini-fa.sh). I believe a newer version should also work.
## optional dependencies
explained in the [main readme](https://github.com/9001/copyparty/tree/hovudstraum#optional-dependencies), but a quick recap:
* recommended python libraries: `argon2-cffi paramiko pyftpdlib pyopenssl pillow rawpy pyzmq` [python-magic](https://pypi.org/project/python-magic/)
* only recommended on Windows: `psutil` (not very useful on Linux)
* NOT recommended: `impacket` because the feature it enables is a security nightmare
* NOT recommended: `mutagen` because ffmpeg produces better results (albeit slower)
* NOT recommended: `pyvips` because converting to jxl is extremely RAM-heavy
* NOT recommended: `pillow-heif` due to [legal reasons](https://github.com/9001/copyparty/blob/hovudstraum/docs/bad-codecs.md)
* recommended programs: `ffmpeg ffprobe cfssl cfssljson cfssl-certinfo`
* FFmpeg powers audio transcoding, and thumbnails of formats not covered by pillow/pyvips
# building # building
## dev env setup ## dev env setup

View file

@ -38,3 +38,5 @@
accs: accs:
rw: * # everyone gets read-write access, but rw: * # everyone gets read-write access, but
rwmda: ed # the user "ed" gets read-write-move-delete-admin rwmda: ed # the user "ed" gets read-write-move-delete-admin
flags:
e2ds # enable filesystem-scanning for this volume only

View file

@ -777,7 +777,7 @@ symbol legend,
# briefly considered # briefly considered
* [pydio](https://github.com/pydio/cells): python/agpl3, looks great, fantastic ux -- but needs mariadb, systemwide install * [pydio](https://github.com/pydio/cells): go/agpl3, looks great, fantastic ux -- but needs mariadb, systemwide install, SSO is 3280€/year
* [gossa](https://github.com/pldubouilh/gossa): go/mit, minimalistic, basic file upload, text editor, mkdir and rename (no delete/move) * [gossa](https://github.com/pldubouilh/gossa): go/mit, minimalistic, basic file upload, text editor, mkdir and rename (no delete/move)

View file

@ -161,7 +161,7 @@ class Cfg(Namespace):
ex = "ac_convt au_vol dl_list du_iwho mtab_age reg_cap s_thead s_tbody tail_tmax tail_who th_convt th_qv th_qvx ups_who ver_iwho zip_who" ex = "ac_convt au_vol dl_list du_iwho mtab_age reg_cap s_thead s_tbody tail_tmax tail_who th_convt th_qv th_qvx ups_who ver_iwho zip_who"
ka.update(**{k: 9 for k in ex.split()}) ka.update(**{k: 9 for k in ex.split()})
ex = "ctl_re db_act forget_ip idp_cookie idp_store k304 loris no304 nosubtle qr_pin qr_wait re_maxage rproxy rsp_jtr rsp_slp s_wr_slp snap_wri theme themes turbo u2ow zipmaxn zipmaxs" ex = "ctl_re db_act forget_ip gauto idp_cookie idp_store k304 loris no304 nosubtle qr_pin qr_wait re_maxage rproxy rsp_jtr rsp_slp s_wr_slp snap_wri theme themes turbo u2ow zipmaxn zipmaxs"
ka.update(**{k: 0 for k in ex.split()}) ka.update(**{k: 0 for k in ex.split()})
ex = "ah_alg bname chdir chmod_f chpw_db db_xattr doctitle df epilogues exit favico fika ipa ipar html_head html_head_d html_head_s idp_login idp_logout lg_sba lg_sbf log_date log_fk md_sba md_sbf name og_desc og_site og_th og_title og_title_a og_title_v og_title_i opds_exts preadmes prologues readmes shr shr1 shr_site site smsg tcolor textfiles th_pregen txt_eol ufavico ufavico_h unlist up_site vc_url vname xff_src zipmaxt R RS SR" ex = "ah_alg bname chdir chmod_f chpw_db db_xattr doctitle df epilogues exit favico fika ipa ipar html_head html_head_d html_head_s idp_login idp_logout lg_sba lg_sbf log_date log_fk md_sba md_sbf name og_desc og_site og_th og_title og_title_a og_title_v og_title_i opds_exts preadmes prologues readmes shr shr1 shr_site site smsg tcolor textfiles th_pregen txt_eol ufavico ufavico_h unlist up_site vc_url vname xff_src zipmaxt R RS SR"