Compare commits
27 Commits
v1.19.1
...
hovudstrau
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f4a3fba29c | ||
![]() |
3aa8b7aa2d | ||
![]() |
d56230573d | ||
![]() |
af8620da92 | ||
![]() |
2961dea5bb | ||
![]() |
4e878d2f1e | ||
![]() |
7f44875061 | ||
![]() |
68907eaf48 | ||
![]() |
c4a4fddd27 | ||
![]() |
5b62742512 | ||
![]() |
554cc2f3ee | ||
![]() |
6303effe59 | ||
![]() |
659f351c65 | ||
![]() |
d676a86f3f | ||
![]() |
715d374ee4 | ||
![]() |
c9fd608732 | ||
![]() |
c32a672a68 | ||
![]() |
69d9878acd | ||
![]() |
d8662aeb0e | ||
![]() |
a407eb9269 | ||
![]() |
1ebe06f51e | ||
![]() |
88243ac8d6 | ||
![]() |
6ccc9224f3 | ||
![]() |
0177a9b402 | ||
![]() |
9435e6b2e2 | ||
![]() |
0da93659a4 | ||
![]() |
db2a03409c |
10
README.md
10
README.md
@ -266,6 +266,7 @@ also see [comparison to similar software](./docs/versus.md)
|
|||||||
* ☑ realtime streaming of growing files (logfiles and such)
|
* ☑ realtime streaming of growing files (logfiles and such)
|
||||||
* ☑ [thumbnails](#thumbnails)
|
* ☑ [thumbnails](#thumbnails)
|
||||||
* ☑ ...of images using Pillow, pyvips, or FFmpeg
|
* ☑ ...of images using Pillow, pyvips, or FFmpeg
|
||||||
|
* ☑ ...of RAW images using rawpy
|
||||||
* ☑ ...of videos using FFmpeg
|
* ☑ ...of videos using FFmpeg
|
||||||
* ☑ ...of audio (spectrograms) using FFmpeg
|
* ☑ ...of audio (spectrograms) using FFmpeg
|
||||||
* ☑ cache eviction (max-age; maybe max-size eventually)
|
* ☑ cache eviction (max-age; maybe max-size eventually)
|
||||||
@ -512,6 +513,8 @@ examples:
|
|||||||
* replacing the `g` permission with `wg` would let anonymous users upload files, but not see the required filekey to access it
|
* replacing the `g` permission with `wg` would let anonymous users upload files, but not see the required filekey to access it
|
||||||
* replacing the `g` permission with `wG` would let anonymous users upload files, receiving a working direct link in return
|
* replacing the `g` permission with `wG` would let anonymous users upload files, receiving a working direct link in return
|
||||||
|
|
||||||
|
if you want to grant access to all users who are logged in, the group `acct` will always contain all known users, so for example `-v /mnt/music:music:r,@acct`
|
||||||
|
|
||||||
anyone trying to bruteforce a password gets banned according to `--ban-pw`; default is 24h ban for 9 failed attempts in 1 hour
|
anyone trying to bruteforce a password gets banned according to `--ban-pw`; default is 24h ban for 9 failed attempts in 1 hour
|
||||||
|
|
||||||
and if you want to use config files instead of commandline args (good!) then here's the same examples as a configfile; save it as `foobar.conf` and use it like this: `python copyparty-sfx.py -c foobar.conf`
|
and if you want to use config files instead of commandline args (good!) then here's the same examples as a configfile; save it as `foobar.conf` and use it like this: `python copyparty-sfx.py -c foobar.conf`
|
||||||
@ -537,6 +540,7 @@ and if you want to use config files instead of commandline args (good!) then her
|
|||||||
accs:
|
accs:
|
||||||
r: u1, u2 # only these accounts can read,
|
r: u1, u2 # only these accounts can read,
|
||||||
r: @g1 # (exactly the same, just with a group instead)
|
r: @g1 # (exactly the same, just with a group instead)
|
||||||
|
r: @acct # (alternatively, ALL users who are logged in)
|
||||||
rw: u3 # and only u3 can read-write
|
rw: u3 # and only u3 can read-write
|
||||||
|
|
||||||
[/inc]
|
[/inc]
|
||||||
@ -2792,9 +2796,10 @@ enable [music tags](#metadata-from-audio-files):
|
|||||||
enable [thumbnails](#thumbnails) of...
|
enable [thumbnails](#thumbnails) of...
|
||||||
* **images:** `Pillow` and/or `pyvips` and/or `ffmpeg` (requires py2.7 or py3.5+)
|
* **images:** `Pillow` and/or `pyvips` and/or `ffmpeg` (requires py2.7 or py3.5+)
|
||||||
* **videos/audio:** `ffmpeg` and `ffprobe` somewhere in `$PATH`
|
* **videos/audio:** `ffmpeg` and `ffprobe` somewhere in `$PATH`
|
||||||
* **HEIF pictures:** `pyvips` or `ffmpeg` or `pyheif-pillow-opener` (requires Linux or a C compiler)
|
* **HEIF pictures:** `pyvips` or `ffmpeg` or `pillow-heif`
|
||||||
* **AVIF pictures:** `pyvips` or `ffmpeg` or `pillow-avif-plugin` or pillow v11.3+
|
* **AVIF pictures:** `pyvips` or `ffmpeg` or `pillow-avif-plugin` or pillow v11.3+
|
||||||
* **JPEG XL pictures:** `pyvips` or `ffmpeg`
|
* **JPEG XL pictures:** `pyvips` or `ffmpeg`
|
||||||
|
* **RAW images:** `rawpy`, plus one of `pyvips` or `Pillow` (for some formats)
|
||||||
|
|
||||||
enable sending [zeromq messages](#zeromq) from event-hooks: `pyzmq`
|
enable sending [zeromq messages](#zeromq) from event-hooks: `pyzmq`
|
||||||
|
|
||||||
@ -2825,9 +2830,10 @@ set any of the following environment variables to disable its associated optiona
|
|||||||
| `PRTY_NO_PIL` | disable all [Pillow](https://pypi.org/project/pillow/)-based thumbnail support; will fallback to libvips or ffmpeg |
|
| `PRTY_NO_PIL` | disable all [Pillow](https://pypi.org/project/pillow/)-based thumbnail support; will fallback to libvips or ffmpeg |
|
||||||
| `PRTY_NO_PILF` | disable Pillow `ImageFont` text rendering, used for folder thumbnails |
|
| `PRTY_NO_PILF` | disable Pillow `ImageFont` text rendering, used for folder thumbnails |
|
||||||
| `PRTY_NO_PIL_AVIF` | disable Pillow avif support (internal and/or [plugin](https://pypi.org/project/pillow-avif-plugin/)) |
|
| `PRTY_NO_PIL_AVIF` | disable Pillow avif support (internal and/or [plugin](https://pypi.org/project/pillow-avif-plugin/)) |
|
||||||
| `PRTY_NO_PIL_HEIF` | disable 3rd-party Pillow plugin for [HEIF support](https://pypi.org/project/pyheif-pillow-opener/) |
|
| `PRTY_NO_PIL_HEIF` | disable 3rd-party Pillow plugin for [HEIF support](https://pypi.org/project/pillow-heif/) |
|
||||||
| `PRTY_NO_PIL_WEBP` | disable use of native webp support in Pillow |
|
| `PRTY_NO_PIL_WEBP` | disable use of native webp support in Pillow |
|
||||||
| `PRTY_NO_PSUTIL` | do not use [psutil](https://pypi.org/project/psutil/) for reaping stuck hooks and plugins on Windows |
|
| `PRTY_NO_PSUTIL` | do not use [psutil](https://pypi.org/project/psutil/) for reaping stuck hooks and plugins on Windows |
|
||||||
|
| `PRTY_NO_RAW` | disable all [rawpy](https://pypi.org/project/rawpy/)-based thumbnail support for RAW images |
|
||||||
| `PRTY_NO_VIPS` | disable all [libvips](https://pypi.org/project/pyvips/)-based thumbnail support; will fallback to Pillow or ffmpeg |
|
| `PRTY_NO_VIPS` | disable all [libvips](https://pypi.org/project/pyvips/)-based thumbnail support; will fallback to Pillow or ffmpeg |
|
||||||
|
|
||||||
example: `PRTY_NO_PIL=1 python3 copyparty-sfx.py`
|
example: `PRTY_NO_PIL=1 python3 copyparty-sfx.py`
|
||||||
|
@ -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.19.0"
|
pkgver="1.19.1"
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="File server with accelerated resumable uploads, dedup, WebDAV, FTP, TFTP, zeroconf, media indexer, thumbnails++"
|
pkgdesc="File server with accelerated resumable uploads, dedup, WebDAV, FTP, TFTP, zeroconf, media indexer, thumbnails++"
|
||||||
arch=("any")
|
arch=("any")
|
||||||
@ -23,7 +23,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=("179b027d51e4fe7ebdab2b18c07475d52c57e2ce69256292b157a8efacd82118")
|
sha256sums=("bbc250db23eb80bc96c27b2efa456ce1e7f49c7dfaabadb91a571f70064b6f91")
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
cd "${srcdir}/${pkgname}-${pkgver}/copyparty/web"
|
cd "${srcdir}/${pkgname}-${pkgver}/copyparty/web"
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
|
|
||||||
pkgname=copyparty
|
pkgname=copyparty
|
||||||
pkgver=1.19.0
|
pkgver=1.19.1
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="File server with accelerated resumable uploads, dedup, WebDAV, FTP, TFTP, zeroconf, media indexer, thumbnails++"
|
pkgdesc="File server with accelerated resumable uploads, dedup, WebDAV, FTP, TFTP, zeroconf, media indexer, thumbnails++"
|
||||||
arch=("any")
|
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")
|
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=("179b027d51e4fe7ebdab2b18c07475d52c57e2ce69256292b157a8efacd82118")
|
sha256sums=("bbc250db23eb80bc96c27b2efa456ce1e7f49c7dfaabadb91a571f70064b6f91")
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
cd "${srcdir}/${pkgname}-${pkgver}/copyparty/web"
|
cd "${srcdir}/${pkgname}-${pkgver}/copyparty/web"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"url": "https://github.com/9001/copyparty/releases/download/v1.19.0/copyparty-sfx.py",
|
"url": "https://github.com/9001/copyparty/releases/download/v1.19.1/copyparty-sfx.py",
|
||||||
"version": "1.19.0",
|
"version": "1.19.1",
|
||||||
"hash": "sha256-9A+zPtkVtUuGHB/JJV3fhVtJderLUGxHqvuJQz0/1+Q="
|
"hash": "sha256-Orn0N//DD5/5rIWK9yYRcvyOnt/bKCE9CeoxkfNO76s="
|
||||||
}
|
}
|
62
contrib/package/rpm/copyparty.spec
Normal file
62
contrib/package/rpm/copyparty.spec
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
Name: copyparty
|
||||||
|
Version: $pkgver
|
||||||
|
Release: $pkgrel
|
||||||
|
License: MIT
|
||||||
|
Group: Utilities
|
||||||
|
URL: https://github.com/9001/copyparty
|
||||||
|
Source0: copyparty-$pkgver.tar.gz
|
||||||
|
Summary: File server with accelerated resumable uploads, dedup, WebDAV, FTP, TFTP, zeroconf, media indexer, thumbnails++
|
||||||
|
BuildArch: noarch
|
||||||
|
BuildRequires: python3, python3-devel, pyproject-rpm-macros, python-setuptools, python-wheel, make
|
||||||
|
Requires: python3, (python3-jinja2 or python-jinja2), lsof
|
||||||
|
Recommends: ffmpeg, (golang-github-cloudflare-cfssl or cfssl), python-mutagen, python-pillow, python-pyvips
|
||||||
|
Recommends: qm-vamp-plugins, python-argon2-cffi, (python-pyopenssl or pyopenssl), python-impacket
|
||||||
|
|
||||||
|
%description
|
||||||
|
Portable file server with accelerated resumable uploads, dedup, WebDAV, FTP, TFTP, zeroconf, media indexer, thumbnails++ all in one file, no deps
|
||||||
|
|
||||||
|
See release at https://github.com/9001/copyparty/releases
|
||||||
|
|
||||||
|
%global debug_package %{nil}
|
||||||
|
|
||||||
|
%generate_buildrequires
|
||||||
|
%pyproject_buildrequires
|
||||||
|
|
||||||
|
%prep
|
||||||
|
%setup -q
|
||||||
|
|
||||||
|
%build
|
||||||
|
cd "copyparty/web"
|
||||||
|
make
|
||||||
|
cd -
|
||||||
|
%pyproject_wheel
|
||||||
|
|
||||||
|
%install
|
||||||
|
mkdir -p %{buildroot}%{_bindir}
|
||||||
|
mkdir -p %{buildroot}%{_libdir}/systemd/{system,user}
|
||||||
|
mkdir -p %{buildroot}/etc/%{name}
|
||||||
|
mkdir -p %{buildroot}/var/lib/%{name}-jail
|
||||||
|
mkdir -p %{buildroot}%{_datadir}/licenses/%{name}
|
||||||
|
|
||||||
|
%pyproject_install
|
||||||
|
%pyproject_save_files copyparty
|
||||||
|
|
||||||
|
install -m 0755 bin/prisonparty.sh %{buildroot}%{_bindir}/prisonpary.sh
|
||||||
|
install -m 0644 contrib/systemd/%{name}.conf %{buildroot}/etc/%{name}/%{name}.conf
|
||||||
|
install -m 0644 contrib/systemd/%{name}@.service %{buildroot}%{_libdir}/systemd/system/%{name}@.service
|
||||||
|
install -m 0644 contrib/systemd/%{name}-user.service %{buildroot}%{_libdir}/systemd/user/%{name}.service
|
||||||
|
install -m 0644 contrib/systemd/prisonparty@.service %{buildroot}%{_libdir}/systemd/system/prisonparty@.service
|
||||||
|
install -m 0644 contrib/systemd/index.md %{buildroot}/var/lib/%{name}-jail/README.md
|
||||||
|
install -m 0644 LICENSE %{buildroot}%{_datadir}/licenses/%{name}/LICENSE
|
||||||
|
|
||||||
|
%files -n copyparty -f %{pyproject_files}
|
||||||
|
%license LICENSE
|
||||||
|
%{_bindir}/copyparty
|
||||||
|
%{_bindir}/partyfuse
|
||||||
|
%{_bindir}/u2c
|
||||||
|
%{_bindir}/prisonpary.sh
|
||||||
|
/etc/%{name}/%{name}.conf
|
||||||
|
%{_libdir}/systemd/system/%{name}@.service
|
||||||
|
%{_libdir}/systemd/user/%{name}.service
|
||||||
|
%{_libdir}/systemd/system/prisonparty@.service
|
||||||
|
/var/lib/%{name}-jail/README.md
|
@ -609,6 +609,9 @@ def get_sects():
|
|||||||
if no accounts or volumes are configured,
|
if no accounts or volumes are configured,
|
||||||
current folder will be read/write for everyone
|
current folder will be read/write for everyone
|
||||||
|
|
||||||
|
the group @acct will always have every user with an account
|
||||||
|
(the name of that group can be changed with --grp-all)
|
||||||
|
|
||||||
consider the config file for more flexible account/volume management,
|
consider the config file for more flexible account/volume management,
|
||||||
including dynamic reload at runtime (and being more readable w)
|
including dynamic reload at runtime (and being more readable w)
|
||||||
"""
|
"""
|
||||||
@ -1019,14 +1022,15 @@ def add_general(ap, nc, srvname):
|
|||||||
|
|
||||||
def add_qr(ap, tty):
|
def add_qr(ap, tty):
|
||||||
ap2 = ap.add_argument_group("qr options")
|
ap2 = ap.add_argument_group("qr options")
|
||||||
ap2.add_argument("--qr", action="store_true", help="show http:// QR-code on startup")
|
ap2.add_argument("--qr", action="store_true", help="show QR-code on startup")
|
||||||
ap2.add_argument("--qrs", action="store_true", help="show https:// QR-code on startup")
|
ap2.add_argument("--qrs", action="store_true", help="change the QR-code URL to https://")
|
||||||
ap2.add_argument("--qrl", metavar="PATH", type=u, default="", help="location to include in the url, for example [\033[32mpriv/?pw=hunter2\033[0m]")
|
ap2.add_argument("--qrl", metavar="PATH", type=u, default="", help="location to include in the url, for example [\033[32mpriv/?pw=hunter2\033[0m]")
|
||||||
ap2.add_argument("--qri", metavar="PREFIX", type=u, default="", help="select IP which starts with \033[33mPREFIX\033[0m; [\033[32m.\033[0m] to force default IP when mDNS URL would have been used instead")
|
ap2.add_argument("--qri", metavar="PREFIX", type=u, default="", help="select IP which starts with \033[33mPREFIX\033[0m; [\033[32m.\033[0m] to force default IP when mDNS URL would have been used instead")
|
||||||
ap2.add_argument("--qr-fg", metavar="COLOR", type=int, default=0 if tty else 16, help="foreground; try [\033[32m0\033[0m] if the qr-code is unreadable")
|
ap2.add_argument("--qr-fg", metavar="COLOR", type=int, default=0 if tty else 16, help="foreground; try [\033[32m0\033[0m] or [\033[32m-1\033[0m] if the qr-code is unreadable")
|
||||||
ap2.add_argument("--qr-bg", metavar="COLOR", type=int, default=229, help="background (white=255)")
|
ap2.add_argument("--qr-bg", metavar="COLOR", type=int, default=229, help="background (white=255)")
|
||||||
ap2.add_argument("--qrp", metavar="CELLS", type=int, default=4, help="padding (spec says 4 or more, but 1 is usually fine)")
|
ap2.add_argument("--qrp", metavar="CELLS", type=int, default=4, help="padding (spec says 4 or more, but 1 is usually fine)")
|
||||||
ap2.add_argument("--qrz", metavar="N", type=int, default=0, help="[\033[32m1\033[0m]=1x, [\033[32m2\033[0m]=2x, [\033[32m0\033[0m]=auto (try [\033[32m2\033[0m] on broken fonts)")
|
ap2.add_argument("--qrz", metavar="N", type=int, default=0, help="[\033[32m1\033[0m]=1x, [\033[32m2\033[0m]=2x, [\033[32m0\033[0m]=auto (try [\033[32m2\033[0m] on broken fonts)")
|
||||||
|
ap2.add_argument("--qr-pin", metavar="N", type=int, default=0, help="sticky/pin the qr-code to always stay on-screen; [\033[32m0\033[0m]=disabled, [\033[32m1\033[0m]=with-url, [\033[32m2\033[0m]=just-qr")
|
||||||
|
|
||||||
|
|
||||||
def add_fs(ap):
|
def add_fs(ap):
|
||||||
@ -1162,6 +1166,7 @@ def add_auth(ap):
|
|||||||
ap2.add_argument("--ses-db", metavar="PATH", type=u, default=ses_db, help="where to store the sessions database (if you run multiple copyparty instances, make sure they use different DBs)")
|
ap2.add_argument("--ses-db", metavar="PATH", type=u, default=ses_db, help="where to store the sessions database (if you run multiple copyparty instances, make sure they use different DBs)")
|
||||||
ap2.add_argument("--ses-len", metavar="CHARS", type=int, default=20, help="session key length; default is 120 bits ((20//4)*4*6)")
|
ap2.add_argument("--ses-len", metavar="CHARS", type=int, default=20, help="session key length; default is 120 bits ((20//4)*4*6)")
|
||||||
ap2.add_argument("--no-ses", action="store_true", help="disable sessions; use plaintext passwords in cookies")
|
ap2.add_argument("--no-ses", action="store_true", help="disable sessions; use plaintext passwords in cookies")
|
||||||
|
ap2.add_argument("--grp-all", metavar="NAME", type=u, default="acct", help="the name of the auto-generated group which contains every username which is known")
|
||||||
ap2.add_argument("--ipu", metavar="CIDR=USR", type=u, action="append", help="\033[34mREPEATABLE:\033[0m users with IP matching \033[33mCIDR\033[0m are auto-authenticated as username \033[33mUSR\033[0m; example: [\033[32m172.16.24.0/24=dave]")
|
ap2.add_argument("--ipu", metavar="CIDR=USR", type=u, action="append", help="\033[34mREPEATABLE:\033[0m users with IP matching \033[33mCIDR\033[0m are auto-authenticated as username \033[33mUSR\033[0m; example: [\033[32m172.16.24.0/24=dave]")
|
||||||
|
|
||||||
|
|
||||||
@ -1318,6 +1323,7 @@ def add_optouts(ap):
|
|||||||
ap2.add_argument("--no-del", action="store_true", help="disable delete operations")
|
ap2.add_argument("--no-del", action="store_true", help="disable delete operations")
|
||||||
ap2.add_argument("--no-mv", action="store_true", help="disable move/rename operations")
|
ap2.add_argument("--no-mv", action="store_true", help="disable move/rename operations")
|
||||||
ap2.add_argument("--no-cp", action="store_true", help="disable copy operations")
|
ap2.add_argument("--no-cp", action="store_true", help="disable copy operations")
|
||||||
|
ap2.add_argument("--no-fs-abrt", action="store_true", help="disable ability to abort ongoing copy/move")
|
||||||
ap2.add_argument("-nth", action="store_true", help="no title hostname; don't show \033[33m--name\033[0m in <title>")
|
ap2.add_argument("-nth", action="store_true", help="no title hostname; don't show \033[33m--name\033[0m in <title>")
|
||||||
ap2.add_argument("-nih", action="store_true", help="no info hostname -- don't show in UI")
|
ap2.add_argument("-nih", action="store_true", help="no info hostname -- don't show in UI")
|
||||||
ap2.add_argument("-nid", action="store_true", help="no info disk-usage -- don't show in UI")
|
ap2.add_argument("-nid", action="store_true", help="no info disk-usage -- don't show in UI")
|
||||||
@ -1361,6 +1367,8 @@ def add_safety(ap):
|
|||||||
ap2.add_argument("--sus-urls", metavar="R", type=u, default=r"\.php$|(^|/)wp-(admin|content|includes)/", help="URLs which are considered sus / eligible for banning; disable with blank or [\033[32mno\033[0m]")
|
ap2.add_argument("--sus-urls", metavar="R", type=u, default=r"\.php$|(^|/)wp-(admin|content|includes)/", help="URLs which are considered sus / eligible for banning; disable with blank or [\033[32mno\033[0m]")
|
||||||
ap2.add_argument("--nonsus-urls", metavar="R", type=u, default=r"^(favicon\.ico|robots\.txt)$|^apple-touch-icon|^\.well-known", help="harmless URLs ignored from 404-bans; disable with blank or [\033[32mno\033[0m]")
|
ap2.add_argument("--nonsus-urls", metavar="R", type=u, default=r"^(favicon\.ico|robots\.txt)$|^apple-touch-icon|^\.well-known", help="harmless URLs ignored from 404-bans; disable with blank or [\033[32mno\033[0m]")
|
||||||
ap2.add_argument("--early-ban", action="store_true", help="if a client is banned, reject its connection as soon as possible; not a good idea to enable when proxied behind cloudflare since it could ban your reverse-proxy")
|
ap2.add_argument("--early-ban", action="store_true", help="if a client is banned, reject its connection as soon as possible; not a good idea to enable when proxied behind cloudflare since it could ban your reverse-proxy")
|
||||||
|
ap2.add_argument("--cookie-nmax", metavar="N", type=int, default=50, help="reject HTTP-request from client if they send more than N cookies")
|
||||||
|
ap2.add_argument("--cookie-cmax", metavar="N", type=int, default=8192, help="reject HTTP-request from client if more than N characters in Cookie header")
|
||||||
ap2.add_argument("--aclose", metavar="MIN", type=int, default=10, help="if a client maxes out the server connection limit, downgrade it from connection:keep-alive to connection:close for \033[33mMIN\033[0m minutes (and also kill its active connections) -- disable with 0")
|
ap2.add_argument("--aclose", metavar="MIN", type=int, default=10, help="if a client maxes out the server connection limit, downgrade it from connection:keep-alive to connection:close for \033[33mMIN\033[0m minutes (and also kill its active connections) -- disable with 0")
|
||||||
ap2.add_argument("--loris", metavar="B", type=int, default=60, help="if a client maxes out the server connection limit without sending headers, ban it for \033[33mB\033[0m minutes; disable with [\033[32m0\033[0m]")
|
ap2.add_argument("--loris", metavar="B", type=int, default=60, help="if a client maxes out the server connection limit without sending headers, ban it for \033[33mB\033[0m minutes; disable with [\033[32m0\033[0m]")
|
||||||
ap2.add_argument("--acao", metavar="V[,V]", type=u, default="*", help="Access-Control-Allow-Origin; list of origins (domains/IPs without port) to accept requests from; [\033[32mhttps://1.2.3.4\033[0m]. Default [\033[32m*\033[0m] allows requests from all sites but removes cookies and http-auth; only ?pw=hunter2 survives")
|
ap2.add_argument("--acao", metavar="V[,V]", type=u, default="*", help="Access-Control-Allow-Origin; list of origins (domains/IPs without port) to accept requests from; [\033[32mhttps://1.2.3.4\033[0m]. Default [\033[32m*\033[0m] allows requests from all sites but removes cookies and http-auth; only ?pw=hunter2 survives")
|
||||||
@ -1427,11 +1435,12 @@ def add_thumbnail(ap):
|
|||||||
ap2.add_argument("--no-athumb", action="store_true", help="disable audio thumbnails (spectrograms) (volflag=dathumb)")
|
ap2.add_argument("--no-athumb", action="store_true", help="disable audio thumbnails (spectrograms) (volflag=dathumb)")
|
||||||
ap2.add_argument("--th-size", metavar="WxH", default="320x256", help="thumbnail res (volflag=thsize)")
|
ap2.add_argument("--th-size", metavar="WxH", default="320x256", help="thumbnail res (volflag=thsize)")
|
||||||
ap2.add_argument("--th-mt", metavar="CORES", type=int, default=CORES, help="num cpu cores to use for generating thumbnails")
|
ap2.add_argument("--th-mt", metavar="CORES", type=int, default=CORES, help="num cpu cores to use for generating thumbnails")
|
||||||
ap2.add_argument("--th-convt", metavar="SEC", type=float, default=60.0, help="conversion timeout in seconds (volflag=convt)")
|
ap2.add_argument("--th-convt", metavar="SEC", type=float, default=60.0, help="convert-to-image timeout in seconds (volflag=convt)")
|
||||||
|
ap2.add_argument("--ac-convt", metavar="SEC", type=float, default=150.0, help="convert-to-audio timeout in seconds (volflag=aconvt)")
|
||||||
ap2.add_argument("--th-ram-max", metavar="GB", type=float, default=th_ram, help="max memory usage (GiB) permitted by thumbnailer; not very accurate")
|
ap2.add_argument("--th-ram-max", metavar="GB", type=float, default=th_ram, help="max memory usage (GiB) permitted by thumbnailer; not very accurate")
|
||||||
ap2.add_argument("--th-crop", metavar="TXT", type=u, default="y", help="crop thumbnails to 4:3 or keep dynamic height; client can override in UI unless force. [\033[32my\033[0m]=crop, [\033[32mn\033[0m]=nocrop, [\033[32mfy\033[0m]=force-y, [\033[32mfn\033[0m]=force-n (volflag=crop)")
|
ap2.add_argument("--th-crop", metavar="TXT", type=u, default="y", help="crop thumbnails to 4:3 or keep dynamic height; client can override in UI unless force. [\033[32my\033[0m]=crop, [\033[32mn\033[0m]=nocrop, [\033[32mfy\033[0m]=force-y, [\033[32mfn\033[0m]=force-n (volflag=crop)")
|
||||||
ap2.add_argument("--th-x3", metavar="TXT", type=u, default="n", help="show thumbs at 3x resolution; client can override in UI unless force. [\033[32my\033[0m]=yes, [\033[32mn\033[0m]=no, [\033[32mfy\033[0m]=force-yes, [\033[32mfn\033[0m]=force-no (volflag=th3x)")
|
ap2.add_argument("--th-x3", metavar="TXT", type=u, default="n", help="show thumbs at 3x resolution; client can override in UI unless force. [\033[32my\033[0m]=yes, [\033[32mn\033[0m]=no, [\033[32mfy\033[0m]=force-yes, [\033[32mfn\033[0m]=force-no (volflag=th3x)")
|
||||||
ap2.add_argument("--th-dec", metavar="LIBS", default="vips,pil,ff", help="image decoders, in order of preference")
|
ap2.add_argument("--th-dec", metavar="LIBS", default="vips,pil,raw,ff", help="image decoders, in order of preference")
|
||||||
ap2.add_argument("--th-no-jpg", action="store_true", help="disable jpg output")
|
ap2.add_argument("--th-no-jpg", action="store_true", help="disable jpg output")
|
||||||
ap2.add_argument("--th-no-webp", action="store_true", help="disable webp output")
|
ap2.add_argument("--th-no-webp", action="store_true", help="disable webp output")
|
||||||
ap2.add_argument("--th-ff-jpg", action="store_true", help="force jpg output for video thumbs (avoids issues on some FFmpeg builds)")
|
ap2.add_argument("--th-ff-jpg", action="store_true", help="force jpg output for video thumbs (avoids issues on some FFmpeg builds)")
|
||||||
@ -1442,14 +1451,16 @@ def add_thumbnail(ap):
|
|||||||
ap2.add_argument("--th-covers", metavar="N,N", type=u, default="folder.png,folder.jpg,cover.png,cover.jpg", help="folder thumbnails to stat/look for; enabling \033[33m-e2d\033[0m will make these case-insensitive, and try them as dotfiles (.folder.jpg), and also automatically select thumbnails for all folders that contain pics, even if none match this pattern")
|
ap2.add_argument("--th-covers", metavar="N,N", type=u, default="folder.png,folder.jpg,cover.png,cover.jpg", help="folder thumbnails to stat/look for; enabling \033[33m-e2d\033[0m will make these case-insensitive, and try them as dotfiles (.folder.jpg), and also automatically select thumbnails for all folders that contain pics, even if none match this pattern")
|
||||||
# https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html
|
# https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html
|
||||||
# https://github.com/libvips/libvips
|
# https://github.com/libvips/libvips
|
||||||
|
# https://stackoverflow.com/a/47612661
|
||||||
# ffmpeg -hide_banner -demuxers | awk '/^ D /{print$2}' | while IFS= read -r x; do ffmpeg -hide_banner -h demuxer=$x; done | grep -E '^Demuxer |extensions:'
|
# ffmpeg -hide_banner -demuxers | awk '/^ D /{print$2}' | while IFS= read -r x; do ffmpeg -hide_banner -h demuxer=$x; done | grep -E '^Demuxer |extensions:'
|
||||||
ap2.add_argument("--th-r-pil", metavar="T,T", type=u, default="avif,avifs,blp,bmp,cbz,dcx,dds,dib,emf,eps,fits,flc,fli,fpx,gif,heic,heics,heif,heifs,icns,ico,im,j2p,j2k,jp2,jpeg,jpg,jpx,pbm,pcx,pgm,png,pnm,ppm,psd,qoi,sgi,spi,tga,tif,tiff,webp,wmf,xbm,xpm", help="image formats to decode using pillow")
|
ap2.add_argument("--th-r-pil", metavar="T,T", type=u, default="avif,avifs,blp,bmp,cbz,dcx,dds,dib,emf,eps,epub,fits,flc,fli,fpx,gif,heic,heics,heif,heifs,icns,ico,im,j2p,j2k,jp2,jpeg,jpg,jpx,pbm,pcx,pgm,png,pnm,ppm,psd,qoi,sgi,spi,tga,tif,tiff,webp,wmf,xbm,xpm", help="image formats to decode using pillow")
|
||||||
ap2.add_argument("--th-r-vips", metavar="T,T", type=u, default="avif,exr,fit,fits,fts,gif,hdr,heic,jp2,jpeg,jpg,jpx,jxl,nii,pfm,pgm,png,ppm,svg,tif,tiff,webp", help="image formats to decode using pyvips")
|
ap2.add_argument("--th-r-vips", metavar="T,T", type=u, default="avif,exr,fit,fits,fts,gif,hdr,heic,jp2,jpeg,jpg,jpx,jxl,nii,pfm,pgm,png,ppm,svg,tif,tiff,webp", help="image formats to decode using pyvips")
|
||||||
ap2.add_argument("--th-r-ffi", metavar="T,T", type=u, default="apng,avif,avifs,bmp,cbz,dds,dib,fit,fits,fts,gif,hdr,heic,heics,heif,heifs,icns,ico,jp2,jpeg,jpg,jpx,jxl,pbm,pcx,pfm,pgm,png,pnm,ppm,psd,qoi,sgi,tga,tif,tiff,webp,xbm,xpm", help="image formats to decode using ffmpeg")
|
ap2.add_argument("--th-r-raw", metavar="T,T", type=u, default="arw,cr2,cr3,crw,dcr,dng,erf,k25,kdc,mrw,nef,orf,pef,raf,raw,sr2,srf,x3f", help="image formats to decode using rawpy")
|
||||||
|
ap2.add_argument("--th-r-ffi", metavar="T,T", type=u, default="apng,avif,avifs,bmp,cbz,dds,dib,epub,fit,fits,fts,gif,hdr,heic,heics,heif,heifs,icns,ico,jp2,jpeg,jpg,jpx,jxl,pbm,pcx,pfm,pgm,png,pnm,ppm,psd,qoi,sgi,tga,tif,tiff,webp,xbm,xpm", help="image formats to decode using ffmpeg")
|
||||||
ap2.add_argument("--th-r-ffv", metavar="T,T", type=u, default="3gp,asf,av1,avc,avi,flv,h264,h265,hevc,m4v,mjpeg,mjpg,mkv,mov,mp4,mpeg,mpeg2,mpegts,mpg,mpg2,mts,nut,ogm,ogv,rm,ts,vob,webm,wmv", help="video formats to decode using ffmpeg")
|
ap2.add_argument("--th-r-ffv", metavar="T,T", type=u, default="3gp,asf,av1,avc,avi,flv,h264,h265,hevc,m4v,mjpeg,mjpg,mkv,mov,mp4,mpeg,mpeg2,mpegts,mpg,mpg2,mts,nut,ogm,ogv,rm,ts,vob,webm,wmv", help="video formats to decode using ffmpeg")
|
||||||
ap2.add_argument("--th-r-ffa", metavar="T,T", type=u, default="aac,ac3,aif,aiff,alac,alaw,amr,apac,ape,au,bonk,dfpwm,dts,flac,gsm,ilbc,it,itgz,itxz,itz,m4a,mdgz,mdxz,mdz,mo3,mod,mp2,mp3,mpc,mptm,mt2,mulaw,oga,ogg,okt,opus,ra,s3m,s3gz,s3xz,s3z,tak,tta,ulaw,wav,wma,wv,xm,xmgz,xmxz,xmz,xpk", help="audio formats to decode using ffmpeg")
|
ap2.add_argument("--th-r-ffa", metavar="T,T", type=u, default="aac,ac3,aif,aiff,alac,alaw,amr,apac,ape,au,bonk,dfpwm,dts,flac,gsm,ilbc,it,itgz,itxz,itz,m4a,mdgz,mdxz,mdz,mo3,mod,mp2,mp3,mpc,mptm,mt2,mulaw,oga,ogg,okt,opus,ra,s3m,s3gz,s3xz,s3z,tak,tta,ulaw,wav,wma,wv,xm,xmgz,xmxz,xmz,xpk", help="audio formats to decode using ffmpeg")
|
||||||
ap2.add_argument("--th-spec-cnv", metavar="T", type=u, default="it,itgz,itxz,itz,mdgz,mdxz,mdz,mo3,mod,s3m,s3gz,s3xz,s3z,xm,xmgz,xmxz,xmz,xpk", help="audio formats which provoke https://trac.ffmpeg.org/ticket/10797 (huge ram usage for s3xmodit spectrograms)")
|
ap2.add_argument("--th-spec-cnv", metavar="T", type=u, default="it,itgz,itxz,itz,mdgz,mdxz,mdz,mo3,mod,s3m,s3gz,s3xz,s3z,xm,xmgz,xmxz,xmz,xpk", help="audio formats which provoke https://trac.ffmpeg.org/ticket/10797 (huge ram usage for s3xmodit spectrograms)")
|
||||||
ap2.add_argument("--au-unpk", metavar="E=F.C", type=u, default="mdz=mod.zip, mdgz=mod.gz, mdxz=mod.xz, s3z=s3m.zip, s3gz=s3m.gz, s3xz=s3m.xz, xmz=xm.zip, xmgz=xm.gz, xmxz=xm.xz, itz=it.zip, itgz=it.gz, itxz=it.xz, cbz=jpg.cbz", help="audio/image formats to decompress before passing to ffmpeg")
|
ap2.add_argument("--au-unpk", metavar="E=F.C", type=u, default="mdz=mod.zip, mdgz=mod.gz, mdxz=mod.xz, s3z=s3m.zip, s3gz=s3m.gz, s3xz=s3m.xz, xmz=xm.zip, xmgz=xm.gz, xmxz=xm.xz, itz=it.zip, itgz=it.gz, itxz=it.xz, cbz=jpg.cbz, epub=jpg.epub", help="audio/image formats to decompress before passing to ffmpeg")
|
||||||
|
|
||||||
|
|
||||||
def add_transcoding(ap):
|
def add_transcoding(ap):
|
||||||
@ -1565,9 +1576,9 @@ def add_ui(ap, retry):
|
|||||||
ap2.add_argument("--grid", action="store_true", help="show grid/thumbnails by default (volflag=grid)")
|
ap2.add_argument("--grid", action="store_true", help="show grid/thumbnails by default (volflag=grid)")
|
||||||
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("--lang", metavar="LANG", type=u, default="eng", help="language; one of the following: \033[32meng nor chi\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("--theme", metavar="NUM", type=int, default=0, help="default theme to use (0..7)")
|
ap2.add_argument("--theme", metavar="NUM", type=int, default=0, help="default theme to use (0..7)")
|
||||||
ap2.add_argument("--themes", metavar="NUM", type=int, default=8, help="number of themes installed")
|
ap2.add_argument("--themes", metavar="NUM", type=int, default=10, 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")
|
||||||
ap2.add_argument("--sort", metavar="C,C,C", type=u, default="href", help="default sort order, comma-separated column IDs (see header tooltips), prefix with '-' for descending. Examples: \033[32mhref -href ext sz ts tags/Album tags/.tn\033[0m (volflag=sort)")
|
ap2.add_argument("--sort", metavar="C,C,C", type=u, default="href", help="default sort order, comma-separated column IDs (see header tooltips), prefix with '-' for descending. Examples: \033[32mhref -href ext sz ts tags/Album tags/.tn\033[0m (volflag=sort)")
|
||||||
ap2.add_argument("--nsort", action="store_true", help="default-enable natural sort of filenames with leading numbers (volflag=nsort)")
|
ap2.add_argument("--nsort", action="store_true", help="default-enable natural sort of filenames with leading numbers (volflag=nsort)")
|
||||||
|
@ -1099,6 +1099,9 @@ class AuthSrv(object):
|
|||||||
if rejected:
|
if rejected:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if gn == self.args.grp_all:
|
||||||
|
gn = ""
|
||||||
|
|
||||||
# if ap/vp has a user/group placeholder, make sure to keep
|
# if ap/vp has a user/group placeholder, make sure to keep
|
||||||
# track so the same user/group is mapped when setting perms;
|
# track so the same user/group is mapped when setting perms;
|
||||||
# otherwise clear un/gn to indicate it's a regular volume
|
# otherwise clear un/gn to indicate it's a regular volume
|
||||||
@ -1208,6 +1211,7 @@ class AuthSrv(object):
|
|||||||
self.load_idp_db(bool(self.idp_accs))
|
self.load_idp_db(bool(self.idp_accs))
|
||||||
ret = {un: gns[:] for un, gns in self.idp_accs.items()}
|
ret = {un: gns[:] for un, gns in self.idp_accs.items()}
|
||||||
ret.update({zs: [""] for zs in acct if zs not in ret})
|
ret.update({zs: [""] for zs in acct if zs not in ret})
|
||||||
|
grps[self.args.grp_all] = list(ret.keys())
|
||||||
for gn, uns in grps.items():
|
for gn, uns in grps.items():
|
||||||
for un in uns:
|
for un in uns:
|
||||||
try:
|
try:
|
||||||
@ -1881,6 +1885,16 @@ class AuthSrv(object):
|
|||||||
if LEELOO_DALLAS in all_users:
|
if LEELOO_DALLAS in all_users:
|
||||||
raise Exception("sorry, reserved username: " + LEELOO_DALLAS)
|
raise Exception("sorry, reserved username: " + LEELOO_DALLAS)
|
||||||
|
|
||||||
|
zsl = []
|
||||||
|
for usr in list(acct)[:]:
|
||||||
|
zs = acct[usr].strip()
|
||||||
|
if not zs:
|
||||||
|
zs = ub64enc(os.urandom(48)).decode("ascii")
|
||||||
|
zsl.append(usr)
|
||||||
|
acct[usr] = zs
|
||||||
|
if zsl:
|
||||||
|
self.log("generated random passwords for users %r" % (zsl,), 6)
|
||||||
|
|
||||||
seenpwds = {}
|
seenpwds = {}
|
||||||
for usr, pwd in acct.items():
|
for usr, pwd in acct.items():
|
||||||
if pwd in seenpwds:
|
if pwd in seenpwds:
|
||||||
@ -2206,7 +2220,7 @@ class AuthSrv(object):
|
|||||||
if k in vol.flags:
|
if k in vol.flags:
|
||||||
vol.flags[k] = int(vol.flags[k])
|
vol.flags[k] = int(vol.flags[k])
|
||||||
|
|
||||||
zs = "convt tail_fd tail_rate tail_tmax"
|
zs = "aconvt convt tail_fd tail_rate tail_tmax"
|
||||||
for k in zs.split():
|
for k in zs.split():
|
||||||
if k in vol.flags:
|
if k in vol.flags:
|
||||||
vol.flags[k] = float(vol.flags[k])
|
vol.flags[k] = float(vol.flags[k])
|
||||||
|
@ -68,6 +68,7 @@ def vf_bmap() -> dict[str, str]:
|
|||||||
def vf_vmap() -> dict[str, str]:
|
def vf_vmap() -> dict[str, str]:
|
||||||
"""argv-to-volflag: simple values"""
|
"""argv-to-volflag: simple values"""
|
||||||
ret = {
|
ret = {
|
||||||
|
"ac_convt": "aconvt",
|
||||||
"no_hash": "nohash",
|
"no_hash": "nohash",
|
||||||
"no_idx": "noidx",
|
"no_idx": "noidx",
|
||||||
"re_maxage": "scan",
|
"re_maxage": "scan",
|
||||||
@ -260,7 +261,8 @@ flagcats = {
|
|||||||
"thsize": "thumbnail res; WxH",
|
"thsize": "thumbnail res; WxH",
|
||||||
"crop": "center-cropping (y/n/fy/fn)",
|
"crop": "center-cropping (y/n/fy/fn)",
|
||||||
"th3x": "3x resolution (y/n/fy/fn)",
|
"th3x": "3x resolution (y/n/fy/fn)",
|
||||||
"convt": "conversion timeout in seconds",
|
"convt": "convert-to-image timeout in seconds",
|
||||||
|
"aconvt": "convert-to-audio timeout in seconds",
|
||||||
"ext_th=s=/b.png": "use /b.png as thumbnail for file-extension s",
|
"ext_th=s=/b.png": "use /b.png as thumbnail for file-extension s",
|
||||||
},
|
},
|
||||||
"handlers\n(better explained in --help-handlers)": {
|
"handlers\n(better explained in --help-handlers)": {
|
||||||
|
@ -65,6 +65,9 @@ DXMLParser = _DXMLParser
|
|||||||
|
|
||||||
|
|
||||||
def parse_xml(txt: str) -> ET.Element:
|
def parse_xml(txt: str) -> ET.Element:
|
||||||
|
"""
|
||||||
|
Parse XML into an xml.etree.ElementTree.Element while defusing some unsafe parts.
|
||||||
|
"""
|
||||||
parser = DXMLParser()
|
parser = DXMLParser()
|
||||||
parser.feed(txt)
|
parser.feed(txt)
|
||||||
return parser.close() # type: ignore
|
return parser.close() # type: ignore
|
||||||
|
@ -285,9 +285,12 @@ class FtpFs(AbstractedFS):
|
|||||||
# returning 550 is library-default and suitable
|
# returning 550 is library-default and suitable
|
||||||
raise FSE("No such file or directory")
|
raise FSE("No such file or directory")
|
||||||
|
|
||||||
avfs = vfs.chk_ap(ap, st)
|
if vfs.realpath:
|
||||||
if not avfs:
|
avfs = vfs.chk_ap(ap, st)
|
||||||
raise FSE("Permission denied", 1)
|
if not avfs:
|
||||||
|
raise FSE("Permission denied", 1)
|
||||||
|
else:
|
||||||
|
avfs = vfs
|
||||||
|
|
||||||
self.cwd = nwd
|
self.cwd = nwd
|
||||||
(
|
(
|
||||||
@ -492,7 +495,11 @@ class FtpHandler(FTPHandler):
|
|||||||
def ftp_STOR(self, file: str, mode: str = "w") -> Any:
|
def ftp_STOR(self, file: str, mode: str = "w") -> Any:
|
||||||
# Optional[str]
|
# Optional[str]
|
||||||
vp = join(self.fs.cwd, file).lstrip("/")
|
vp = join(self.fs.cwd, file).lstrip("/")
|
||||||
ap, vfs, rem = self.fs.v2a(vp, w=True)
|
try:
|
||||||
|
ap, vfs, rem = self.fs.v2a(vp, w=True)
|
||||||
|
except Exception as ex:
|
||||||
|
self.respond("550 %s" % (ex,), logging.info)
|
||||||
|
return
|
||||||
self.vfs_map[ap] = vp
|
self.vfs_map[ap] = vp
|
||||||
xbu = vfs.flags.get("xbu")
|
xbu = vfs.flags.get("xbu")
|
||||||
if xbu and not runhook(
|
if xbu and not runhook(
|
||||||
|
@ -562,7 +562,7 @@ class HttpCli(object):
|
|||||||
|
|
||||||
zso = self.headers.get("cookie")
|
zso = self.headers.get("cookie")
|
||||||
if zso:
|
if zso:
|
||||||
if len(zso) > 8192:
|
if len(zso) > self.args.cookie_cmax:
|
||||||
self.loud_reply("cookie header too big", status=400)
|
self.loud_reply("cookie header too big", status=400)
|
||||||
return False
|
return False
|
||||||
zsll = [x.split("=", 1) for x in zso.split(";") if "=" in x]
|
zsll = [x.split("=", 1) for x in zso.split(";") if "=" in x]
|
||||||
@ -570,11 +570,15 @@ class HttpCli(object):
|
|||||||
cookie_pw = cookies.get("cppws") or cookies.get("cppwd") or ""
|
cookie_pw = cookies.get("cppws") or cookies.get("cppwd") or ""
|
||||||
if "b" in cookies and "b" not in uparam:
|
if "b" in cookies and "b" not in uparam:
|
||||||
uparam["b"] = cookies["b"]
|
uparam["b"] = cookies["b"]
|
||||||
|
if len(cookies) > self.args.cookie_nmax:
|
||||||
|
self.loud_reply("too many cookies", status=400)
|
||||||
else:
|
else:
|
||||||
cookies = {}
|
cookies = {}
|
||||||
cookie_pw = ""
|
cookie_pw = ""
|
||||||
|
|
||||||
if len(uparam) > 10 or len(cookies) > 50:
|
if len(uparam) > 12:
|
||||||
|
t = "http-request rejected; num.params: %d %r"
|
||||||
|
self.log(t % (len(uparam), self.req), 3)
|
||||||
self.loud_reply("u wot m8", status=400)
|
self.loud_reply("u wot m8", status=400)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -700,7 +704,7 @@ class HttpCli(object):
|
|||||||
cookies["b"] = ""
|
cookies["b"] = ""
|
||||||
|
|
||||||
vn, rem = self.asrv.vfs.get(self.vpath, self.uname, False, False)
|
vn, rem = self.asrv.vfs.get(self.vpath, self.uname, False, False)
|
||||||
if "xdev" in vn.flags or "xvol" in vn.flags:
|
if vn.realpath and ("xdev" in vn.flags or "xvol" in vn.flags):
|
||||||
ap = vn.canonical(rem)
|
ap = vn.canonical(rem)
|
||||||
avn = vn.chk_ap(ap)
|
avn = vn.chk_ap(ap)
|
||||||
else:
|
else:
|
||||||
@ -1987,6 +1991,9 @@ class HttpCli(object):
|
|||||||
if "eshare" in self.uparam:
|
if "eshare" in self.uparam:
|
||||||
return self.handle_eshare()
|
return self.handle_eshare()
|
||||||
|
|
||||||
|
if "fs_abrt" in self.uparam:
|
||||||
|
return self.handle_fs_abrt()
|
||||||
|
|
||||||
if "application/octet-stream" in ctype:
|
if "application/octet-stream" in ctype:
|
||||||
return self.handle_post_binary()
|
return self.handle_post_binary()
|
||||||
|
|
||||||
@ -5958,7 +5965,9 @@ class HttpCli(object):
|
|||||||
self.asrv.vfs.get(vdst, self.uname, False, True, False, True)
|
self.asrv.vfs.get(vdst, self.uname, False, True, False, True)
|
||||||
wunlink(self.log, dabs, dvn.flags)
|
wunlink(self.log, dabs, dvn.flags)
|
||||||
|
|
||||||
x = self.conn.hsrv.broker.ask("up2k.handle_mv", self.uname, self.ip, vsrc, vdst)
|
x = self.conn.hsrv.broker.ask(
|
||||||
|
"up2k.handle_mv", self.ouparam.get("akey"), self.uname, self.ip, vsrc, vdst
|
||||||
|
)
|
||||||
self.loud_reply(x.get(), status=201)
|
self.loud_reply(x.get(), status=201)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -5988,10 +5997,21 @@ class HttpCli(object):
|
|||||||
self.asrv.vfs.get(vdst, self.uname, False, True, False, True)
|
self.asrv.vfs.get(vdst, self.uname, False, True, False, True)
|
||||||
wunlink(self.log, dabs, dvn.flags)
|
wunlink(self.log, dabs, dvn.flags)
|
||||||
|
|
||||||
x = self.conn.hsrv.broker.ask("up2k.handle_cp", self.uname, self.ip, vsrc, vdst)
|
x = self.conn.hsrv.broker.ask(
|
||||||
|
"up2k.handle_cp", self.ouparam.get("akey"), self.uname, self.ip, vsrc, vdst
|
||||||
|
)
|
||||||
self.loud_reply(x.get(), status=201)
|
self.loud_reply(x.get(), status=201)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def handle_fs_abrt(self):
|
||||||
|
if self.args.no_fs_abrt:
|
||||||
|
t = "aborting an ongoing copy/move is disabled in server config"
|
||||||
|
raise Pebkac(403, t)
|
||||||
|
|
||||||
|
self.conn.hsrv.broker.say("up2k.handle_fs_abrt", self.uparam["fs_abrt"])
|
||||||
|
self.loud_reply("aborting", status=200)
|
||||||
|
return True
|
||||||
|
|
||||||
def tx_ls(self, ls: dict[str, Any]) -> bool:
|
def tx_ls(self, ls: dict[str, Any]) -> bool:
|
||||||
dirs = ls["dirs"]
|
dirs = ls["dirs"]
|
||||||
files = ls["files"]
|
files = ls["files"]
|
||||||
|
@ -29,7 +29,7 @@ from .util import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
if True: # pylint: disable=using-constant-test
|
if True: # pylint: disable=using-constant-test
|
||||||
from typing import Any, Optional, Union
|
from typing import IO, Any, Optional, Union
|
||||||
|
|
||||||
from .util import NamedLogger, RootLogger
|
from .util import NamedLogger, RootLogger
|
||||||
|
|
||||||
@ -176,6 +176,9 @@ def au_unpk(
|
|||||||
raise Exception("no images inside cbz")
|
raise Exception("no images inside cbz")
|
||||||
fi = zf.open(using)
|
fi = zf.open(using)
|
||||||
|
|
||||||
|
elif pk == "epub":
|
||||||
|
fi = get_cover_from_epub(log, abspath)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise Exception("unknown compression %s" % (pk,))
|
raise Exception("unknown compression %s" % (pk,))
|
||||||
|
|
||||||
@ -365,6 +368,76 @@ def parse_ffprobe(txt: str) -> tuple[dict[str, tuple[int, Any]], dict[str, list[
|
|||||||
return zd, md
|
return zd, md
|
||||||
|
|
||||||
|
|
||||||
|
def get_cover_from_epub(log: "NamedLogger", abspath: str) -> Optional[IO[bytes]]:
|
||||||
|
import zipfile
|
||||||
|
|
||||||
|
from .dxml import parse_xml
|
||||||
|
|
||||||
|
try:
|
||||||
|
from urlparse import urljoin # Python2
|
||||||
|
except ImportError:
|
||||||
|
from urllib.parse import urljoin # Python3
|
||||||
|
|
||||||
|
with zipfile.ZipFile(abspath, "r") as z:
|
||||||
|
# First open the container file to find the package document (.opf file)
|
||||||
|
try:
|
||||||
|
container_root = parse_xml(z.read("META-INF/container.xml").decode())
|
||||||
|
except KeyError:
|
||||||
|
log("epub: no container file found in %s" % (abspath,))
|
||||||
|
return None
|
||||||
|
|
||||||
|
# https://www.w3.org/TR/epub-33/#sec-container.xml-rootfile-elem
|
||||||
|
container_ns = {"": "urn:oasis:names:tc:opendocument:xmlns:container"}
|
||||||
|
# One file could contain multiple package documents, default to the first one
|
||||||
|
rootfile_path = container_root.find("./rootfiles/rootfile", container_ns).get(
|
||||||
|
"full-path"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Then open the first package document to find the path of the cover image
|
||||||
|
try:
|
||||||
|
package_root = parse_xml(z.read(rootfile_path).decode())
|
||||||
|
except KeyError:
|
||||||
|
log("epub: no package document found in %s" % (abspath,))
|
||||||
|
return None
|
||||||
|
|
||||||
|
# https://www.w3.org/TR/epub-33/#sec-package-doc
|
||||||
|
package_ns = {"": "http://www.idpf.org/2007/opf"}
|
||||||
|
# https://www.w3.org/TR/epub-33/#sec-cover-image
|
||||||
|
coverimage_path_node = package_root.find(
|
||||||
|
"./manifest/item[@properties='cover-image']", package_ns
|
||||||
|
)
|
||||||
|
if coverimage_path_node is not None:
|
||||||
|
coverimage_path = coverimage_path_node.get("href")
|
||||||
|
else:
|
||||||
|
# This might be an EPUB2 file, try the legacy way of specifying covers
|
||||||
|
coverimage_path = _get_cover_from_epub2(log, package_root, package_ns)
|
||||||
|
|
||||||
|
# This url is either absolute (in the .epub) or relative to the package document
|
||||||
|
adjusted_cover_path = urljoin(rootfile_path, coverimage_path)
|
||||||
|
|
||||||
|
return z.open(adjusted_cover_path)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_cover_from_epub2(
|
||||||
|
log: "NamedLogger", package_root, package_ns
|
||||||
|
) -> Optional[str]:
|
||||||
|
# <meta name="cover" content="id-to-cover-image"> in <metadata>, then
|
||||||
|
# <item> in <manifest>
|
||||||
|
cover_id = package_root.find("./metadata/meta[@name='cover']", package_ns).get(
|
||||||
|
"content"
|
||||||
|
)
|
||||||
|
|
||||||
|
if not cover_id:
|
||||||
|
return None
|
||||||
|
|
||||||
|
for node in package_root.iterfind("./manifest/item", package_ns):
|
||||||
|
if node.get("id") == cover_id:
|
||||||
|
cover_path = node.get("href")
|
||||||
|
return cover_path
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class MTag(object):
|
class MTag(object):
|
||||||
def __init__(self, log_func: "RootLogger", args: argparse.Namespace) -> None:
|
def __init__(self, log_func: "RootLogger", args: argparse.Namespace) -> None:
|
||||||
self.log_func = log_func
|
self.log_func = log_func
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
from __future__ import print_function, unicode_literals
|
from __future__ import print_function, unicode_literals
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import atexit
|
||||||
import errno
|
import errno
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
@ -38,6 +39,7 @@ from .th_srv import (
|
|||||||
HAVE_FFPROBE,
|
HAVE_FFPROBE,
|
||||||
HAVE_HEIF,
|
HAVE_HEIF,
|
||||||
HAVE_PIL,
|
HAVE_PIL,
|
||||||
|
HAVE_RAW,
|
||||||
HAVE_VIPS,
|
HAVE_VIPS,
|
||||||
HAVE_WEBP,
|
HAVE_WEBP,
|
||||||
ThumbSrv,
|
ThumbSrv,
|
||||||
@ -72,6 +74,7 @@ from .util import (
|
|||||||
pybin,
|
pybin,
|
||||||
start_log_thrs,
|
start_log_thrs,
|
||||||
start_stackmon,
|
start_stackmon,
|
||||||
|
termsize,
|
||||||
ub64enc,
|
ub64enc,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -321,6 +324,8 @@ class SvcHub(object):
|
|||||||
decs.pop("vips", None)
|
decs.pop("vips", None)
|
||||||
if not HAVE_PIL:
|
if not HAVE_PIL:
|
||||||
decs.pop("pil", None)
|
decs.pop("pil", None)
|
||||||
|
if not HAVE_RAW:
|
||||||
|
decs.pop("raw", None)
|
||||||
if not HAVE_FFMPEG or not HAVE_FFPROBE:
|
if not HAVE_FFMPEG or not HAVE_FFPROBE:
|
||||||
decs.pop("ff", None)
|
decs.pop("ff", None)
|
||||||
|
|
||||||
@ -772,6 +777,39 @@ class SvcHub(object):
|
|||||||
def sigterm(self) -> None:
|
def sigterm(self) -> None:
|
||||||
self.signal_handler(signal.SIGTERM, None)
|
self.signal_handler(signal.SIGTERM, None)
|
||||||
|
|
||||||
|
def sticky_qr(self) -> None:
|
||||||
|
tw, th = termsize()
|
||||||
|
zs1, qr = self.tcpsrv.qr.split("\n", 1)
|
||||||
|
url, colr = zs1.split(" ", 1)
|
||||||
|
nl = len(qr.split("\n")) # numlines
|
||||||
|
lp = 3 if nl * 2 + 4 < tw else 0 # leftpad
|
||||||
|
lp0 = lp
|
||||||
|
if self.args.qr_pin == 2:
|
||||||
|
url = ""
|
||||||
|
else:
|
||||||
|
while lp and (nl + lp) * 2 + len(url) + 1 > tw:
|
||||||
|
lp -= 1
|
||||||
|
if (nl + lp) * 2 + len(url) + 1 > tw:
|
||||||
|
qr = url + "\n" + qr
|
||||||
|
url = ""
|
||||||
|
nl += 1
|
||||||
|
lp = lp0
|
||||||
|
sh = 1 + th - nl
|
||||||
|
if lp:
|
||||||
|
zs = " " * lp
|
||||||
|
qr = zs + qr.replace("\n", "\n" + zs)
|
||||||
|
if url:
|
||||||
|
url = "%s\033[%d;%dH%s\033[0m" % (colr, sh + 1, (nl + lp) * 2, url)
|
||||||
|
qr = colr + qr
|
||||||
|
|
||||||
|
def unlock():
|
||||||
|
print("\033[s\033[r\033[u", file=sys.stderr)
|
||||||
|
|
||||||
|
atexit.register(unlock)
|
||||||
|
t = "%s\033[%dA" % ("\n" * nl, nl)
|
||||||
|
t = "%s\033[s\033[1;%dr\033[%dH%s%s\033[u" % (t, sh - 1, sh, qr, url)
|
||||||
|
self.pr(t, file=sys.stderr)
|
||||||
|
|
||||||
def cb_httpsrv_up(self) -> None:
|
def cb_httpsrv_up(self) -> None:
|
||||||
self.httpsrv_up += 1
|
self.httpsrv_up += 1
|
||||||
if self.httpsrv_up != self.broker.num_workers:
|
if self.httpsrv_up != self.broker.num_workers:
|
||||||
@ -784,7 +822,10 @@ class SvcHub(object):
|
|||||||
break
|
break
|
||||||
|
|
||||||
if self.tcpsrv.qr:
|
if self.tcpsrv.qr:
|
||||||
self.log("qr-code", self.tcpsrv.qr)
|
if self.args.qr_pin:
|
||||||
|
self.sticky_qr()
|
||||||
|
else:
|
||||||
|
self.log("qr-code", self.tcpsrv.qr)
|
||||||
else:
|
else:
|
||||||
self.log("root", "workers OK\n")
|
self.log("root", "workers OK\n")
|
||||||
|
|
||||||
@ -811,6 +852,7 @@ class SvcHub(object):
|
|||||||
(HAVE_ZMQ, "pyzmq", "send zeromq messages from event-hooks"),
|
(HAVE_ZMQ, "pyzmq", "send zeromq messages from event-hooks"),
|
||||||
(HAVE_HEIF, "pillow-heif", "read .heif images with pillow (rarely useful)"),
|
(HAVE_HEIF, "pillow-heif", "read .heif images with pillow (rarely useful)"),
|
||||||
(HAVE_AVIF, "pillow-avif", "read .avif images with pillow (rarely useful)"),
|
(HAVE_AVIF, "pillow-avif", "read .avif images with pillow (rarely useful)"),
|
||||||
|
(HAVE_RAW, "rawpy", "read RAW images"),
|
||||||
]
|
]
|
||||||
if ANYWIN:
|
if ANYWIN:
|
||||||
to_check += [
|
to_check += [
|
||||||
|
@ -614,6 +614,10 @@ class TcpSrv(object):
|
|||||||
|
|
||||||
fg = self.args.qr_fg
|
fg = self.args.qr_fg
|
||||||
bg = self.args.qr_bg
|
bg = self.args.qr_bg
|
||||||
|
nocolor = fg == -1
|
||||||
|
if nocolor:
|
||||||
|
fg = 0
|
||||||
|
|
||||||
pad = self.args.qrp
|
pad = self.args.qrp
|
||||||
zoom = self.args.qrz
|
zoom = self.args.qrz
|
||||||
qrc = QrCode.encode_binary(btxt)
|
qrc = QrCode.encode_binary(btxt)
|
||||||
@ -641,6 +645,8 @@ class TcpSrv(object):
|
|||||||
|
|
||||||
qr = qr.replace("\n", "\033[K\n") + "\033[K" # win10do
|
qr = qr.replace("\n", "\033[K\n") + "\033[K" # win10do
|
||||||
cc = " \033[0;38;5;{0};47;48;5;{1}m" if fg else " \033[0;30;47m"
|
cc = " \033[0;38;5;{0};47;48;5;{1}m" if fg else " \033[0;30;47m"
|
||||||
|
if nocolor:
|
||||||
|
cc = " \033[0m"
|
||||||
t = cc + "\n{2}\033[999G\033[0m\033[J"
|
t = cc + "\n{2}\033[999G\033[0m\033[J"
|
||||||
t = t.format(fg, bg, qr)
|
t = t.format(fg, bg, qr)
|
||||||
if ANYWIN:
|
if ANYWIN:
|
||||||
|
@ -36,11 +36,15 @@ class ThumbCli(object):
|
|||||||
if not c:
|
if not c:
|
||||||
raise Exception()
|
raise Exception()
|
||||||
except:
|
except:
|
||||||
c = {k: set() for k in ["thumbable", "pil", "vips", "ffi", "ffv", "ffa"]}
|
c = {
|
||||||
|
k: set()
|
||||||
|
for k in ["thumbable", "pil", "vips", "raw", "ffi", "ffv", "ffa"]
|
||||||
|
}
|
||||||
|
|
||||||
self.thumbable = c["thumbable"]
|
self.thumbable = c["thumbable"]
|
||||||
self.fmt_pil = c["pil"]
|
self.fmt_pil = c["pil"]
|
||||||
self.fmt_vips = c["vips"]
|
self.fmt_vips = c["vips"]
|
||||||
|
self.fmt_raw = c["raw"]
|
||||||
self.fmt_ffi = c["ffi"]
|
self.fmt_ffi = c["ffi"]
|
||||||
self.fmt_ffv = c["ffv"]
|
self.fmt_ffv = c["ffv"]
|
||||||
self.fmt_ffa = c["ffa"]
|
self.fmt_ffa = c["ffa"]
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
from __future__ import print_function, unicode_literals
|
from __future__ import print_function, unicode_literals
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import io
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
@ -85,7 +86,10 @@ try:
|
|||||||
if os.environ.get("PRTY_NO_PIL_HEIF"):
|
if os.environ.get("PRTY_NO_PIL_HEIF"):
|
||||||
raise Exception()
|
raise Exception()
|
||||||
|
|
||||||
from pyheif_pillow_opener import register_heif_opener
|
try:
|
||||||
|
from pillow_heif import register_heif_opener
|
||||||
|
except ImportError:
|
||||||
|
from pyheif_pillow_opener import register_heif_opener
|
||||||
|
|
||||||
register_heif_opener()
|
register_heif_opener()
|
||||||
HAVE_HEIF = True
|
HAVE_HEIF = True
|
||||||
@ -112,14 +116,28 @@ except:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
if os.environ.get("PRTY_NO_VIPS"):
|
if os.environ.get("PRTY_NO_VIPS"):
|
||||||
raise Exception()
|
raise ImportError()
|
||||||
|
|
||||||
HAVE_VIPS = True
|
HAVE_VIPS = True
|
||||||
import pyvips
|
import pyvips
|
||||||
|
|
||||||
logging.getLogger("pyvips").setLevel(logging.WARNING)
|
logging.getLogger("pyvips").setLevel(logging.WARNING)
|
||||||
except:
|
except Exception as e:
|
||||||
HAVE_VIPS = False
|
HAVE_VIPS = False
|
||||||
|
if not isinstance(e, ImportError):
|
||||||
|
logging.warning("libvips found, but failed to load: " + str(e))
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
if os.environ.get("PRTY_NO_RAW"):
|
||||||
|
raise Exception()
|
||||||
|
|
||||||
|
HAVE_RAW = True
|
||||||
|
import rawpy
|
||||||
|
|
||||||
|
logging.getLogger("rawpy").setLevel(logging.WARNING)
|
||||||
|
except:
|
||||||
|
HAVE_RAW = False
|
||||||
|
|
||||||
|
|
||||||
th_dir_cache = {}
|
th_dir_cache = {}
|
||||||
@ -205,11 +223,19 @@ class ThumbSrv(object):
|
|||||||
if self.args.th_clean:
|
if self.args.th_clean:
|
||||||
Daemon(self.cleaner, "thumb.cln")
|
Daemon(self.cleaner, "thumb.cln")
|
||||||
|
|
||||||
self.fmt_pil, self.fmt_vips, self.fmt_ffi, self.fmt_ffv, self.fmt_ffa = [
|
(
|
||||||
|
self.fmt_pil,
|
||||||
|
self.fmt_vips,
|
||||||
|
self.fmt_raw,
|
||||||
|
self.fmt_ffi,
|
||||||
|
self.fmt_ffv,
|
||||||
|
self.fmt_ffa,
|
||||||
|
) = [
|
||||||
set(y.split(","))
|
set(y.split(","))
|
||||||
for y in [
|
for y in [
|
||||||
self.args.th_r_pil,
|
self.args.th_r_pil,
|
||||||
self.args.th_r_vips,
|
self.args.th_r_vips,
|
||||||
|
self.args.th_r_raw,
|
||||||
self.args.th_r_ffi,
|
self.args.th_r_ffi,
|
||||||
self.args.th_r_ffv,
|
self.args.th_r_ffv,
|
||||||
self.args.th_r_ffa,
|
self.args.th_r_ffa,
|
||||||
@ -232,6 +258,9 @@ class ThumbSrv(object):
|
|||||||
if "vips" in self.args.th_dec:
|
if "vips" in self.args.th_dec:
|
||||||
self.thumbable |= self.fmt_vips
|
self.thumbable |= self.fmt_vips
|
||||||
|
|
||||||
|
if "raw" in self.args.th_dec:
|
||||||
|
self.thumbable |= self.fmt_raw
|
||||||
|
|
||||||
if "ff" in self.args.th_dec:
|
if "ff" in self.args.th_dec:
|
||||||
for zss in [self.fmt_ffi, self.fmt_ffv, self.fmt_ffa]:
|
for zss in [self.fmt_ffi, self.fmt_ffv, self.fmt_ffa]:
|
||||||
self.thumbable |= zss
|
self.thumbable |= zss
|
||||||
@ -313,6 +342,7 @@ class ThumbSrv(object):
|
|||||||
"thumbable": self.thumbable,
|
"thumbable": self.thumbable,
|
||||||
"pil": self.fmt_pil,
|
"pil": self.fmt_pil,
|
||||||
"vips": self.fmt_vips,
|
"vips": self.fmt_vips,
|
||||||
|
"raw": self.fmt_raw,
|
||||||
"ffi": self.fmt_ffi,
|
"ffi": self.fmt_ffi,
|
||||||
"ffv": self.fmt_ffv,
|
"ffv": self.fmt_ffv,
|
||||||
"ffa": self.fmt_ffa,
|
"ffa": self.fmt_ffa,
|
||||||
@ -368,6 +398,8 @@ class ThumbSrv(object):
|
|||||||
funs.append(self.conv_pil)
|
funs.append(self.conv_pil)
|
||||||
elif lib == "vips" and ext in self.fmt_vips:
|
elif lib == "vips" and ext in self.fmt_vips:
|
||||||
funs.append(self.conv_vips)
|
funs.append(self.conv_vips)
|
||||||
|
elif lib == "raw" and ext in self.fmt_raw:
|
||||||
|
funs.append(self.conv_raw)
|
||||||
elif can_au and (want_png or want_au):
|
elif can_au and (want_png or want_au):
|
||||||
if want_opus:
|
if want_opus:
|
||||||
funs.append(self.conv_opus)
|
funs.append(self.conv_opus)
|
||||||
@ -480,35 +512,38 @@ class ThumbSrv(object):
|
|||||||
|
|
||||||
return im
|
return im
|
||||||
|
|
||||||
|
def conv_image_pil(self, im: "Image.Image", tpath: str, fmt: str, vn: VFS) -> None:
|
||||||
|
try:
|
||||||
|
im = self.fancy_pillow(im, fmt, vn)
|
||||||
|
except Exception as ex:
|
||||||
|
self.log("fancy_pillow {}".format(ex), "90")
|
||||||
|
im.thumbnail(self.getres(vn, fmt))
|
||||||
|
|
||||||
|
fmts = ["RGB", "L"]
|
||||||
|
args = {"quality": 40}
|
||||||
|
|
||||||
|
if tpath.endswith(".webp"):
|
||||||
|
# quality 80 = pillow-default
|
||||||
|
# quality 75 = ffmpeg-default
|
||||||
|
# method 0 = pillow-default, fast
|
||||||
|
# method 4 = ffmpeg-default
|
||||||
|
# method 6 = max, slow
|
||||||
|
fmts.extend(("RGBA", "LA"))
|
||||||
|
args["method"] = 6
|
||||||
|
else:
|
||||||
|
# default q = 75
|
||||||
|
args["progressive"] = True
|
||||||
|
|
||||||
|
if im.mode not in fmts:
|
||||||
|
# print("conv {}".format(im.mode))
|
||||||
|
im = im.convert("RGB")
|
||||||
|
|
||||||
|
im.save(tpath, **args)
|
||||||
|
|
||||||
def conv_pil(self, abspath: str, tpath: str, fmt: str, vn: VFS) -> None:
|
def conv_pil(self, abspath: str, tpath: str, fmt: str, vn: VFS) -> None:
|
||||||
self.wait4ram(0.2, tpath)
|
self.wait4ram(0.2, tpath)
|
||||||
with Image.open(fsenc(abspath)) as im:
|
with Image.open(fsenc(abspath)) as im:
|
||||||
try:
|
self.conv_image_pil(im, tpath, fmt, vn)
|
||||||
im = self.fancy_pillow(im, fmt, vn)
|
|
||||||
except Exception as ex:
|
|
||||||
self.log("fancy_pillow {}".format(ex), "90")
|
|
||||||
im.thumbnail(self.getres(vn, fmt))
|
|
||||||
|
|
||||||
fmts = ["RGB", "L"]
|
|
||||||
args = {"quality": 40}
|
|
||||||
|
|
||||||
if tpath.endswith(".webp"):
|
|
||||||
# quality 80 = pillow-default
|
|
||||||
# quality 75 = ffmpeg-default
|
|
||||||
# method 0 = pillow-default, fast
|
|
||||||
# method 4 = ffmpeg-default
|
|
||||||
# method 6 = max, slow
|
|
||||||
fmts.extend(("RGBA", "LA"))
|
|
||||||
args["method"] = 6
|
|
||||||
else:
|
|
||||||
# default q = 75
|
|
||||||
args["progressive"] = True
|
|
||||||
|
|
||||||
if im.mode not in fmts:
|
|
||||||
# print("conv {}".format(im.mode))
|
|
||||||
im = im.convert("RGB")
|
|
||||||
|
|
||||||
im.save(tpath, **args)
|
|
||||||
|
|
||||||
def conv_vips(self, abspath: str, tpath: str, fmt: str, vn: VFS) -> None:
|
def conv_vips(self, abspath: str, tpath: str, fmt: str, vn: VFS) -> None:
|
||||||
self.wait4ram(0.2, tpath)
|
self.wait4ram(0.2, tpath)
|
||||||
@ -531,6 +566,50 @@ class ThumbSrv(object):
|
|||||||
assert img # type: ignore # !rm
|
assert img # type: ignore # !rm
|
||||||
img.write_to_file(tpath, Q=40)
|
img.write_to_file(tpath, Q=40)
|
||||||
|
|
||||||
|
def conv_raw(self, abspath: str, tpath: str, fmt: str, vn: VFS) -> None:
|
||||||
|
self.wait4ram(0.2, tpath)
|
||||||
|
with rawpy.imread(abspath) as raw:
|
||||||
|
thumb = raw.extract_thumb()
|
||||||
|
if thumb.format == rawpy.ThumbFormat.JPEG and tpath.endswith(".jpg"):
|
||||||
|
# if we have a jpg thumbnail and no webp output is available,
|
||||||
|
# just write the jpg directly (it'll be the wrong size, but it's fast)
|
||||||
|
with open(tpath, "wb") as f:
|
||||||
|
f.write(thumb.data)
|
||||||
|
if HAVE_VIPS:
|
||||||
|
crops = ["centre", "none"]
|
||||||
|
if "f" in fmt:
|
||||||
|
crops = ["none"]
|
||||||
|
w, h = self.getres(vn, fmt)
|
||||||
|
kw = {"height": h, "size": "down", "intent": "relative"}
|
||||||
|
|
||||||
|
for c in crops:
|
||||||
|
try:
|
||||||
|
kw["crop"] = c
|
||||||
|
if thumb.format == rawpy.ThumbFormat.BITMAP:
|
||||||
|
img = pyvips.Image.new_from_array(
|
||||||
|
thumb.data, interpretation="rgb"
|
||||||
|
)
|
||||||
|
img = img.thumbnail_image(w, **kw)
|
||||||
|
else:
|
||||||
|
img = pyvips.Image.thumbnail_buffer(thumb.data, w, **kw)
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
if c == crops[-1]:
|
||||||
|
raise
|
||||||
|
|
||||||
|
assert img # type: ignore # !rm
|
||||||
|
img.write_to_file(tpath, Q=40)
|
||||||
|
elif HAVE_PIL:
|
||||||
|
if thumb.format == rawpy.ThumbFormat.BITMAP:
|
||||||
|
im = Image.fromarray(thumb.data, "RGB")
|
||||||
|
else:
|
||||||
|
im = Image.open(io.BytesIO(thumb.data))
|
||||||
|
self.conv_image_pil(im, tpath, fmt, vn)
|
||||||
|
else:
|
||||||
|
raise Exception(
|
||||||
|
"either pil or vips is needed to process embedded bitmap thumbnails in raw files"
|
||||||
|
)
|
||||||
|
|
||||||
def conv_ffmpeg(self, abspath: str, tpath: str, fmt: str, vn: VFS) -> None:
|
def conv_ffmpeg(self, abspath: str, tpath: str, fmt: str, vn: VFS) -> None:
|
||||||
self.wait4ram(0.2, tpath)
|
self.wait4ram(0.2, tpath)
|
||||||
ret, _ = ffprobe(abspath, int(vn.flags["convt"] / 2))
|
ret, _ = ffprobe(abspath, int(vn.flags["convt"] / 2))
|
||||||
@ -583,11 +662,11 @@ class ThumbSrv(object):
|
|||||||
]
|
]
|
||||||
|
|
||||||
cmd += [fsenc(tpath)]
|
cmd += [fsenc(tpath)]
|
||||||
self._run_ff(cmd, vn)
|
self._run_ff(cmd, vn, "convt")
|
||||||
|
|
||||||
def _run_ff(self, cmd: list[bytes], vn: VFS, oom: int = 400) -> None:
|
def _run_ff(self, cmd: list[bytes], vn: VFS, kto: str, oom: int = 400) -> None:
|
||||||
# self.log((b" ".join(cmd)).decode("utf-8"))
|
# self.log((b" ".join(cmd)).decode("utf-8"))
|
||||||
ret, _, serr = runcmd(cmd, timeout=vn.flags["convt"], nice=True, oom=oom)
|
ret, _, serr = runcmd(cmd, timeout=vn.flags[kto], nice=True, oom=oom)
|
||||||
if not ret:
|
if not ret:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -669,7 +748,7 @@ class ThumbSrv(object):
|
|||||||
# fmt: on
|
# fmt: on
|
||||||
|
|
||||||
cmd += [fsenc(tpath)]
|
cmd += [fsenc(tpath)]
|
||||||
self._run_ff(cmd, vn)
|
self._run_ff(cmd, vn, "convt")
|
||||||
|
|
||||||
if "pngquant" in vn.flags:
|
if "pngquant" in vn.flags:
|
||||||
wtpath = tpath + ".png"
|
wtpath = tpath + ".png"
|
||||||
@ -730,7 +809,7 @@ class ThumbSrv(object):
|
|||||||
b"-y", fsenc(infile),
|
b"-y", fsenc(infile),
|
||||||
]
|
]
|
||||||
# fmt: on
|
# fmt: on
|
||||||
self._run_ff(cmd, vn)
|
self._run_ff(cmd, vn, "convt")
|
||||||
|
|
||||||
fc = "[0:a:0]aresample=48000{},showspectrumpic=s="
|
fc = "[0:a:0]aresample=48000{},showspectrumpic=s="
|
||||||
if "3" in fmt:
|
if "3" in fmt:
|
||||||
@ -772,7 +851,7 @@ class ThumbSrv(object):
|
|||||||
]
|
]
|
||||||
|
|
||||||
cmd += [fsenc(tpath)]
|
cmd += [fsenc(tpath)]
|
||||||
self._run_ff(cmd, vn)
|
self._run_ff(cmd, vn, "convt")
|
||||||
|
|
||||||
def conv_mp3(self, abspath: str, tpath: str, fmt: str, vn: VFS) -> None:
|
def conv_mp3(self, abspath: str, tpath: str, fmt: str, vn: VFS) -> None:
|
||||||
quality = self.args.q_mp3.lower()
|
quality = self.args.q_mp3.lower()
|
||||||
@ -811,7 +890,7 @@ class ThumbSrv(object):
|
|||||||
fsenc(tpath)
|
fsenc(tpath)
|
||||||
]
|
]
|
||||||
# fmt: on
|
# fmt: on
|
||||||
self._run_ff(cmd, vn, oom=300)
|
self._run_ff(cmd, vn, "aconvt", oom=300)
|
||||||
|
|
||||||
def conv_flac(self, abspath: str, tpath: str, fmt: str, vn: VFS) -> None:
|
def conv_flac(self, abspath: str, tpath: str, fmt: str, vn: VFS) -> None:
|
||||||
if self.args.no_acode or not self.args.allow_flac:
|
if self.args.no_acode or not self.args.allow_flac:
|
||||||
@ -836,7 +915,7 @@ class ThumbSrv(object):
|
|||||||
fsenc(tpath)
|
fsenc(tpath)
|
||||||
]
|
]
|
||||||
# fmt: on
|
# fmt: on
|
||||||
self._run_ff(cmd, vn, oom=300)
|
self._run_ff(cmd, vn, "aconvt", oom=300)
|
||||||
|
|
||||||
def conv_wav(self, abspath: str, tpath: str, fmt: str, vn: VFS) -> None:
|
def conv_wav(self, abspath: str, tpath: str, fmt: str, vn: VFS) -> None:
|
||||||
if self.args.no_acode or not self.args.allow_wav:
|
if self.args.no_acode or not self.args.allow_wav:
|
||||||
@ -871,7 +950,7 @@ class ThumbSrv(object):
|
|||||||
fsenc(tpath)
|
fsenc(tpath)
|
||||||
]
|
]
|
||||||
# fmt: on
|
# fmt: on
|
||||||
self._run_ff(cmd, vn, oom=300)
|
self._run_ff(cmd, vn, "aconvt", oom=300)
|
||||||
|
|
||||||
def conv_opus(self, abspath: str, tpath: str, fmt: str, vn: VFS) -> None:
|
def conv_opus(self, abspath: str, tpath: str, fmt: str, vn: VFS) -> None:
|
||||||
if self.args.no_acode or not self.args.q_opus:
|
if self.args.no_acode or not self.args.q_opus:
|
||||||
@ -927,7 +1006,7 @@ class ThumbSrv(object):
|
|||||||
fsenc(tpath)
|
fsenc(tpath)
|
||||||
]
|
]
|
||||||
# fmt: on
|
# fmt: on
|
||||||
self._run_ff(cmd, vn, oom=300)
|
self._run_ff(cmd, vn, "aconvt", oom=300)
|
||||||
|
|
||||||
def _conv_caf(
|
def _conv_caf(
|
||||||
self,
|
self,
|
||||||
@ -967,7 +1046,7 @@ class ThumbSrv(object):
|
|||||||
fsenc(tmp_opus)
|
fsenc(tmp_opus)
|
||||||
]
|
]
|
||||||
# fmt: on
|
# fmt: on
|
||||||
self._run_ff(cmd, vn, oom=300)
|
self._run_ff(cmd, vn, "aconvt", oom=300)
|
||||||
|
|
||||||
# iOS fails to play some "insufficiently complex" files
|
# iOS fails to play some "insufficiently complex" files
|
||||||
# (average file shorter than 8 seconds), so of course we
|
# (average file shorter than 8 seconds), so of course we
|
||||||
@ -994,7 +1073,7 @@ class ThumbSrv(object):
|
|||||||
fsenc(tpath)
|
fsenc(tpath)
|
||||||
]
|
]
|
||||||
# fmt: on
|
# fmt: on
|
||||||
self._run_ff(cmd, vn, oom=300)
|
self._run_ff(cmd, vn, "aconvt", oom=300)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# simple remux should be safe
|
# simple remux should be safe
|
||||||
@ -1013,7 +1092,7 @@ class ThumbSrv(object):
|
|||||||
fsenc(tpath)
|
fsenc(tpath)
|
||||||
]
|
]
|
||||||
# fmt: on
|
# fmt: on
|
||||||
self._run_ff(cmd, vn, oom=300)
|
self._run_ff(cmd, vn, "aconvt", oom=300)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
wunlink(self.log, tmp_opus, vn.flags)
|
wunlink(self.log, tmp_opus, vn.flags)
|
||||||
|
@ -144,6 +144,7 @@ class Up2k(object):
|
|||||||
|
|
||||||
self.salt = self.args.warksalt
|
self.salt = self.args.warksalt
|
||||||
self.r_hash = re.compile("^[0-9a-zA-Z_-]{44}$")
|
self.r_hash = re.compile("^[0-9a-zA-Z_-]{44}$")
|
||||||
|
self.abrt_key = ""
|
||||||
|
|
||||||
self.gid = 0
|
self.gid = 0
|
||||||
self.gt0 = 0
|
self.gt0 = 0
|
||||||
@ -3988,6 +3989,9 @@ class Up2k(object):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def handle_fs_abrt(self, akey: str) -> None:
|
||||||
|
self.abrt_key = akey
|
||||||
|
|
||||||
def handle_rm(
|
def handle_rm(
|
||||||
self,
|
self,
|
||||||
uname: str,
|
uname: str,
|
||||||
@ -4197,7 +4201,7 @@ class Up2k(object):
|
|||||||
|
|
||||||
return n_files, ok + ok2, ng + ng2
|
return n_files, ok + ok2, ng + ng2
|
||||||
|
|
||||||
def handle_cp(self, uname: str, ip: str, svp: str, dvp: str) -> str:
|
def handle_cp(self, abrt: str, uname: str, ip: str, svp: str, dvp: str) -> str:
|
||||||
if svp == dvp or dvp.startswith(svp + "/"):
|
if svp == dvp or dvp.startswith(svp + "/"):
|
||||||
raise Pebkac(400, "cp: cannot copy parent into subfolder")
|
raise Pebkac(400, "cp: cannot copy parent into subfolder")
|
||||||
|
|
||||||
@ -4244,6 +4248,8 @@ class Up2k(object):
|
|||||||
|
|
||||||
dvpf = dvp + svpf[len(svp) :]
|
dvpf = dvp + svpf[len(svp) :]
|
||||||
self._cp_file(uname, ip, svpf, dvpf, curs)
|
self._cp_file(uname, ip, svpf, dvpf, curs)
|
||||||
|
if abrt and abrt == self.abrt_key:
|
||||||
|
raise Pebkac(400, "filecopy aborted by http-api")
|
||||||
|
|
||||||
for v in curs:
|
for v in curs:
|
||||||
v.connection.commit()
|
v.connection.commit()
|
||||||
@ -4411,7 +4417,7 @@ class Up2k(object):
|
|||||||
|
|
||||||
return "k"
|
return "k"
|
||||||
|
|
||||||
def handle_mv(self, uname: str, ip: str, svp: str, dvp: str) -> str:
|
def handle_mv(self, abrt: str, uname: str, ip: str, svp: str, dvp: str) -> str:
|
||||||
if svp == dvp or dvp.startswith(svp + "/"):
|
if svp == dvp or dvp.startswith(svp + "/"):
|
||||||
raise Pebkac(400, "mv: cannot move parent into subfolder")
|
raise Pebkac(400, "mv: cannot move parent into subfolder")
|
||||||
|
|
||||||
@ -4466,6 +4472,8 @@ class Up2k(object):
|
|||||||
|
|
||||||
dvpf = dvp + svpf[len(svp) :]
|
dvpf = dvp + svpf[len(svp) :]
|
||||||
self._mv_file(uname, ip, svpf, dvpf, curs)
|
self._mv_file(uname, ip, svpf, dvpf, curs)
|
||||||
|
if abrt and abrt == self.abrt_key:
|
||||||
|
raise Pebkac(400, "filemove aborted by http-api")
|
||||||
|
|
||||||
for v in curs:
|
for v in curs:
|
||||||
v.connection.commit()
|
v.connection.commit()
|
||||||
|
@ -399,6 +399,9 @@ application swf=x-shockwave-flash m3u=vnd.apple.mpegurl db3=vnd.sqlite3 sqlite=v
|
|||||||
text ass=plain ssa=plain
|
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 heic=heic-sequence heif=heif-sequence hdr=vnd.radiance svg=svg+xml
|
image heic=heic-sequence heif=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 k25=x-kodak-k25 kdc=x-kodak-kdc mrw=x-minolta-mrw nef=x-nikon-nef orf=x-olympus-orf
|
||||||
|
image pef=x-pentax-pef raf=x-fuji-raf raw=x-panasonic-raw sr2=x-sony-sr2 srf=x-sony-srf x3f=x-sigma-x3f
|
||||||
audio caf=x-caf mp3=mpeg m4a=mp4 mid=midi mpc=musepack aif=aiff au=basic qcp=qcelp
|
audio caf=x-caf mp3=mpeg m4a=mp4 mid=midi mpc=musepack aif=aiff au=basic qcp=qcelp
|
||||||
video mkv=x-matroska mov=quicktime avi=x-msvideo m4v=x-m4v ts=mp2t
|
video mkv=x-matroska mov=quicktime avi=x-msvideo m4v=x-m4v ts=mp2t
|
||||||
video asf=x-ms-asf flv=x-flv 3gp=3gpp 3g2=3gpp2 rmvb=vnd.rn-realmedia-vbr
|
video asf=x-ms-asf flv=x-flv 3gp=3gpp 3g2=3gpp2 rmvb=vnd.rn-realmedia-vbr
|
||||||
|
@ -1930,6 +1930,11 @@ html.y #tree.nowrap .ntree a+a:hover {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
}
|
}
|
||||||
|
#fs_abrt {
|
||||||
|
margin-top: 1em;
|
||||||
|
text-shadow: 0;
|
||||||
|
box-shadow: 1px 1px 0 var(--bg-d3);
|
||||||
|
}
|
||||||
#doc {
|
#doc {
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
@ -3272,3 +3277,790 @@ html.d #treepar {
|
|||||||
transition: background-color .3s ease, color .3s ease;
|
transition: background-color .3s ease, color .3s ease;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
html.ey {
|
||||||
|
--negative-space: 0em; /* Use this to change the global spacing of the 95 theme */
|
||||||
|
--font-main: consolas;
|
||||||
|
--font-serif: consolas;
|
||||||
|
--font-mono: consolas;
|
||||||
|
--w: #fff;
|
||||||
|
--w2: #dfdfdf;
|
||||||
|
--w3: grey;
|
||||||
|
--fg: #000;
|
||||||
|
--fg-max: #0000ff;
|
||||||
|
--fg-weak: #0000ff;
|
||||||
|
--bg: #c6c3c6;
|
||||||
|
--bg-d3: #ff0;
|
||||||
|
--bg-d2: var(--w3);
|
||||||
|
--bg-d1: var(--bg);
|
||||||
|
--bg-u2: var(--bg);
|
||||||
|
--bg-u3: var(--bg);
|
||||||
|
--bg-u5: var(--shadow-color-2);
|
||||||
|
--tab-alt: #00f;
|
||||||
|
--g-fsel-bg: #00f;
|
||||||
|
--g-sel-bg: #00f;
|
||||||
|
--g-fsel-b1: #fff;
|
||||||
|
--row-alt: var(--w);
|
||||||
|
--scroll: var(--silver);
|
||||||
|
--f-sel-sh: transparent;
|
||||||
|
--a: #000;
|
||||||
|
--a-b: #fff;
|
||||||
|
--a-hil: #fff;
|
||||||
|
--a-h-bg: var(--bg);
|
||||||
|
--a-dark: var(--a);
|
||||||
|
--a-gray: var(--fg-weak);
|
||||||
|
--btn-fg: var(--fg);
|
||||||
|
--btn-bg: var(--bg);
|
||||||
|
--btn-h-fg: var(--fg);
|
||||||
|
--btn-h-bg: var(--bg);
|
||||||
|
--btn-1-fg: var(--fg);
|
||||||
|
--btn-1-bg: var(--bg);
|
||||||
|
--btn-1h-bg: var(--bg-d3);
|
||||||
|
--txt-sh: a;
|
||||||
|
--txt-bg: var(--white);
|
||||||
|
--u2-b1-bg: var(--w2);
|
||||||
|
--u2-b2-bg: var(--w2);
|
||||||
|
--u2-txt-bg: var(--w2);
|
||||||
|
--u2-tab-bg: a;
|
||||||
|
--u2-tab-1-bg: var(--w2);
|
||||||
|
--sort-1: var(--fg-weak);
|
||||||
|
--tree-bg: var(--w);
|
||||||
|
--g-b1: a;
|
||||||
|
--g-b2: a;
|
||||||
|
--g-f-bg: var(--w2);
|
||||||
|
--f-sh1: 0.1;
|
||||||
|
--f-sh2: 0.02;
|
||||||
|
--f-sh3: 0.1;
|
||||||
|
--f-h-b1: a;
|
||||||
|
--srv-1: var(--w);
|
||||||
|
--srv-3: var(--a);
|
||||||
|
--mp-sh: a;
|
||||||
|
--black: #000;
|
||||||
|
--white: #fff;
|
||||||
|
--grey: grey;
|
||||||
|
--silver: silver;
|
||||||
|
--transparent: transparent;
|
||||||
|
--shadow-color-1: #0a0a0a;
|
||||||
|
--shadow-color-2: #808080;
|
||||||
|
--border-dashed-black: 1px dashed var(--black);
|
||||||
|
--radius: 0;
|
||||||
|
--focus-outline: 1px dashed var(--black);
|
||||||
|
--hover-outline: 1px dotted var(--black);
|
||||||
|
--fm-off: var(--w3);
|
||||||
|
--ttlbar: linear-gradient(90deg, navy, #1084d0);
|
||||||
|
--inset-bg: var(--white);
|
||||||
|
--scroll-bkg: var(--white);
|
||||||
|
|
||||||
|
/*All sides*/
|
||||||
|
--shadow-outset: inset -1px -1px var(--shadow-color-1),
|
||||||
|
inset 1px 1px var(--white), inset -2px -2px var(--grey),
|
||||||
|
inset 2px 2px var(--w2);
|
||||||
|
|
||||||
|
--shadow-inset: inset -1px -1px var(--white),
|
||||||
|
inset 1px 1px var(--shadow-color-1), inset -2px -2px var(--w2),
|
||||||
|
inset 2px 2px var(--shadow-color-2);
|
||||||
|
|
||||||
|
--shadow-input: inset -1px -1px var(--white), inset 1px 1px var(--grey),
|
||||||
|
inset -2px -2px var(--w2), inset 2px 2px var(--shadow-color-1);
|
||||||
|
|
||||||
|
/*Indiv sides*/
|
||||||
|
--shadow-outset-bottom: inset 0 -1px var(--shadow-color-1),
|
||||||
|
inset 0 -2px var(--grey);
|
||||||
|
--shadow-outset-right: inset -1px 0 var(--shadow-color-1),
|
||||||
|
inset -2px 0 var(--grey);
|
||||||
|
--shadow-outset-left: inset 1px 0 var(--white), inset 2px 0 var(--w2);
|
||||||
|
--shadow-outset-top: inset 0 1px var(--white), inset 0 2px var(--w2);
|
||||||
|
|
||||||
|
--shadow-inset-bottom: inset 0 -1px var(--white), inset 0 -2px var(--w2);
|
||||||
|
--shadow-inset-right: inset -1px 0 var(--white), inset -2px 0 var(--w2);
|
||||||
|
--shadow-inset-left: inset 1px 0 var(--shadow-color-1),
|
||||||
|
inset 2px 0 var(--shadow-color-2);
|
||||||
|
--shadow-inset-top: inset 0 1px var(--shadow-color-1),
|
||||||
|
inset 0 2px var(--shadow-color-2);
|
||||||
|
}
|
||||||
|
html.ez {
|
||||||
|
--negative-space: 0em; /* Use this to change the global spacing of your theme :) */
|
||||||
|
--font-main: consolas;
|
||||||
|
--font-serif: consolas;
|
||||||
|
--font-mono: consolas;
|
||||||
|
--w: #fff;
|
||||||
|
--w2: var(--inset-bg);
|
||||||
|
--w3: grey;
|
||||||
|
--fg: #cfcfcf;
|
||||||
|
--fg-max: #47b8ff;
|
||||||
|
--fg-weak: #47b8ff;
|
||||||
|
--bg: #383838;
|
||||||
|
--bg-d3: #600000;
|
||||||
|
--bg-d2: var(--shadow-color-1);
|
||||||
|
--bg-d1: var(--bg);
|
||||||
|
--u2-tab-1-fg: #ff0;
|
||||||
|
--bg-u2: var(--bg);
|
||||||
|
--bg-u3: var(--bg);
|
||||||
|
--bg-u5: var(--shadow-color-2);
|
||||||
|
--tab-alt: #47b8ff;
|
||||||
|
--g-fsel-bg: #0000b7;
|
||||||
|
--g-sel-bg: #00f;
|
||||||
|
--g-fsel-b1: #fff;
|
||||||
|
--row-alt: #555555;
|
||||||
|
--scroll: #555555;
|
||||||
|
--f-sel-sh: transparent;
|
||||||
|
--a: var(--fg);
|
||||||
|
--a-b: var(--fg);
|
||||||
|
--a-hil: var(--fg);
|
||||||
|
--btn-1h-bg: var(--bg-d3);
|
||||||
|
--a-h-bg: var(--bg);
|
||||||
|
--a-dark: var(--a);
|
||||||
|
--a-gray: var(--fg-weak);
|
||||||
|
--btn-fg: var(--white);
|
||||||
|
--btn-bg: var(--bg);
|
||||||
|
--btn-h-fg: var(--white);
|
||||||
|
--btn-h-bg: var(--bg);
|
||||||
|
--btn-1-fg: var(--white);
|
||||||
|
--btn-1-bg: var(--bg);
|
||||||
|
--txt-sh: a;
|
||||||
|
--u2-b1-bg: var(--w2);
|
||||||
|
--u2-b2-bg: var(--w2);
|
||||||
|
--u2-txt-bg: var(--w2);
|
||||||
|
--u2-tab-bg: a;
|
||||||
|
--u2-tab-1-bg: var(--w2);
|
||||||
|
--sort-1: var(--fg-weak);
|
||||||
|
--g-b1: a;
|
||||||
|
--g-b2: a;
|
||||||
|
--g-f-bg: var(--w2);
|
||||||
|
--f-sh1: 0.1;
|
||||||
|
--f-sh2: 0.02;
|
||||||
|
--f-sh3: 0.1;
|
||||||
|
--f-h-b1: a;
|
||||||
|
--srv-1: var(--w);
|
||||||
|
--srv-3: var(--a);
|
||||||
|
--mp-sh: a;
|
||||||
|
--black: #000;
|
||||||
|
--white: #fff;
|
||||||
|
--grey: grey;
|
||||||
|
--silver: #858585;
|
||||||
|
--transparent: transparent;
|
||||||
|
--shadow-color-1: #101010;
|
||||||
|
--shadow-color-2: #1f1f1f;
|
||||||
|
--border-dashed-black: 1px dashed var(--shadow-color-1);
|
||||||
|
--radius: 0;
|
||||||
|
--focus-outline: 1px dashed var(--white);
|
||||||
|
--hover-outline: 1px dotted var(--white);
|
||||||
|
--fm-off: var(--w3);
|
||||||
|
--ttlbar: linear-gradient(90deg, var(--shadow-color-1) 20%, #888888);
|
||||||
|
--inset-bg: #3f3f3f;
|
||||||
|
--tree-bg: var(--inset-bg);
|
||||||
|
--txt-bg: var(--inset-bg);
|
||||||
|
--scroll-bkg: var(--black);
|
||||||
|
|
||||||
|
/*All sides*/
|
||||||
|
--shadow-outset: inset -1px -1px var(--shadow-color-1), inset 1px 1px #878787,
|
||||||
|
inset -2px -2px var(--shadow-color-2), inset 2px 2px #575757;
|
||||||
|
|
||||||
|
--shadow-inset: inset -1px -1px #878787, inset 1px 1px var(--shadow-color-1),
|
||||||
|
inset -2px -2px #575757, inset 2px 2px var(--shadow-color-2);
|
||||||
|
|
||||||
|
--shadow-input: inset -1px -1px var(--white),
|
||||||
|
inset 1px 1px var(--shadow-color-2), inset -2px -2px #575757,
|
||||||
|
inset 2px 2px var(--shadow-color-1);
|
||||||
|
|
||||||
|
--shadow-outset-bottom: inset 0 -1px var(--shadow-color-1),
|
||||||
|
inset 0 -2px var(--shadow-color-2);
|
||||||
|
--shadow-outset-right: inset -1px 0 var(--shadow-color-1),
|
||||||
|
inset -2px 0 var(--shadow-color-2);
|
||||||
|
--shadow-outset-left: inset 1px 0 #878787, inset 2px 0 #575757;
|
||||||
|
--shadow-outset-top: inset 0 1px #878787, inset 0 2px #575757;
|
||||||
|
|
||||||
|
--shadow-inset-bottom: inset 0 -1px #878787, inset 0 -2px #575757;
|
||||||
|
--shadow-inset-right: inset -1px 0 #878787, inset -2px 0 #575757;
|
||||||
|
--shadow-inset-left: inset 1px 0 var(--shadow-color-1),
|
||||||
|
inset 2px 0 var(--shadow-color-2);
|
||||||
|
--shadow-inset-top: inset 0 1px var(--shadow-color-1),
|
||||||
|
inset 0 2px var(--shadow-color-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
html.e {
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.e #files,
|
||||||
|
html.e #u2conf input[type="checkbox"]:hover + label,
|
||||||
|
html.e .tgl.btn.on:hover,
|
||||||
|
html.e body {
|
||||||
|
background: var(--bg);
|
||||||
|
}
|
||||||
|
html.e #pctl a,
|
||||||
|
html.e #repl,
|
||||||
|
html.e #u2conf a,
|
||||||
|
html.e #u2conf input[type="checkbox"] + label,
|
||||||
|
html.e #wfp a,
|
||||||
|
html.e .btn,
|
||||||
|
html.e .eq_step,
|
||||||
|
html.e input[type="submit"] {
|
||||||
|
box-shadow: var(--shadow-outset);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
background: var(--bg);
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
a.s0r,
|
||||||
|
html.e #ghead a.s0,
|
||||||
|
html.e #u2conf input[type="checkbox"]:checked + label,
|
||||||
|
html.e .tgl.btn.on,
|
||||||
|
html.e input[type="submit"]:active {
|
||||||
|
box-shadow: var(--shadow-inset) !important;
|
||||||
|
}
|
||||||
|
html.e #ops a:hover,
|
||||||
|
html.e #pctl a:hover,
|
||||||
|
html.e #repl:hover,
|
||||||
|
html.e #u2conf a:hover,
|
||||||
|
html.e #u2conf input[type="checkbox"]:hover + label,
|
||||||
|
html.e #wfp a:hover,
|
||||||
|
html.e .btn:hover,
|
||||||
|
html.e .eq_step:hover,
|
||||||
|
html.e input[type="submit"]:hover {
|
||||||
|
outline: var(--hover-outline);
|
||||||
|
outline-offset: -4px;
|
||||||
|
}
|
||||||
|
html.e .ntree a:hover,
|
||||||
|
html.e :focus,
|
||||||
|
html.e :focus + label,
|
||||||
|
html.e a:active,
|
||||||
|
html.e tr:focus,
|
||||||
|
input[type="text"]:focus {
|
||||||
|
outline: var(--focus-outline) !important;
|
||||||
|
}
|
||||||
|
html.e tr:focus {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
html.e #pctl a:focus,
|
||||||
|
html.e #repl:hover,
|
||||||
|
html.e #u2conf input[type="checkbox"]:focus + label,
|
||||||
|
html.e #wfp a:focus,
|
||||||
|
html.e .btn:focus,
|
||||||
|
html.e .eq_step:focus {
|
||||||
|
border: 0 !important;
|
||||||
|
outline: var(--focus-outline) !important;
|
||||||
|
outline-offset: 2px;
|
||||||
|
box-shadow: var(--shadow-outset) !important;
|
||||||
|
}
|
||||||
|
html.e #files tbody,
|
||||||
|
html.e #u2cards a.act {
|
||||||
|
box-shadow: var(--shadow-inset);
|
||||||
|
}
|
||||||
|
html.e #files {
|
||||||
|
border: 2px groove var(--transparent);
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.3em;
|
||||||
|
top: 0;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
html.e #files tbody tr td,
|
||||||
|
html.e #files thead th {
|
||||||
|
border-radius: var(--radius);
|
||||||
|
}
|
||||||
|
#files td {
|
||||||
|
background: var(--w2);
|
||||||
|
}
|
||||||
|
html.e #files tr {
|
||||||
|
background-color: var(--black);
|
||||||
|
}
|
||||||
|
html.e #srv_info span,
|
||||||
|
html.e label {
|
||||||
|
color: var(--btn-fg) !important;
|
||||||
|
}
|
||||||
|
html.e #acc_info {
|
||||||
|
background: var(--transparent);
|
||||||
|
color: var(--white);
|
||||||
|
height: 2em;
|
||||||
|
left: 1em;
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
html.e #acc_info,
|
||||||
|
html.e #ops,
|
||||||
|
html.e #srv_info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
html.e #flogout:before {
|
||||||
|
padding-left: 0.2em;
|
||||||
|
padding-right: 0.4em;
|
||||||
|
content: " | ";
|
||||||
|
}
|
||||||
|
html.e #blogout {
|
||||||
|
color: var(--w);
|
||||||
|
box-shadow: none;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
html.e .opwide > div {
|
||||||
|
border-left: 1px solid var(--fg);
|
||||||
|
}
|
||||||
|
html.e #srv_info {
|
||||||
|
background: var(--transparent);
|
||||||
|
color: var(--white);
|
||||||
|
height: fit-content;
|
||||||
|
top: 3.2em;
|
||||||
|
left: 1em;
|
||||||
|
gap: 0.2em;
|
||||||
|
}
|
||||||
|
html.e #u2cards a.act {
|
||||||
|
padding: 0.2em 1em;
|
||||||
|
}
|
||||||
|
html.e #u2btn {
|
||||||
|
border: var(--border-dashed-black);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
transform: translateY(30%);
|
||||||
|
}
|
||||||
|
html.e #ops,
|
||||||
|
html.e #ops a {
|
||||||
|
border-radius: var(--radius);
|
||||||
|
}
|
||||||
|
@media only screen and (max-width: 600px) {
|
||||||
|
html.e #acc_info {
|
||||||
|
background: var(--transparent);
|
||||||
|
color: var(--white);
|
||||||
|
height: fit-content;
|
||||||
|
align-items: center;
|
||||||
|
top: 3.2em;
|
||||||
|
right: 1em;
|
||||||
|
left: auto;
|
||||||
|
display: flex;
|
||||||
|
gap: 0.2em;
|
||||||
|
}
|
||||||
|
html.e #u2btn {
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
html.e #ops {
|
||||||
|
background: var(--ttlbar);
|
||||||
|
/*HC*/
|
||||||
|
box-shadow: inset 0-1px grey, inset 0-2px var(--shadow-color-1);
|
||||||
|
height: 2em;
|
||||||
|
gap: 0.6em;
|
||||||
|
padding: 0.2em;
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
margin-bottom: 1.2em;
|
||||||
|
}
|
||||||
|
html.e #srch_form,
|
||||||
|
html.e .opbox {
|
||||||
|
padding-bottom: 1em;
|
||||||
|
padding-top: 1em;
|
||||||
|
max-width: 100vw;
|
||||||
|
}
|
||||||
|
html.e #ghead,
|
||||||
|
html.e #ops a {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
html.e #ops a {
|
||||||
|
text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.5);
|
||||||
|
height: 1.4em;
|
||||||
|
padding: 0;
|
||||||
|
box-shadow: var(--shadow-outset);
|
||||||
|
background: var(--bg);
|
||||||
|
aspect-ratio: 1/1;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 1.25em;
|
||||||
|
z-index: 4;
|
||||||
|
}
|
||||||
|
html.e #blogout:focus,
|
||||||
|
html.e #ops a:focus {
|
||||||
|
outline: 1px dashed var(--w) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.e #blogout:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.e #ops > a:not(:first-child).act {
|
||||||
|
height: 1.4em;
|
||||||
|
width: 1.4em;
|
||||||
|
padding-bottom: 0.3em;
|
||||||
|
margin-top: 0.3em;
|
||||||
|
border-top-left-radius: 3px;
|
||||||
|
border-top-right-radius: 3px;
|
||||||
|
box-shadow: var(--shadow-inset-left), var(--shadow-inset-top),
|
||||||
|
var(--shadow-inset-right);
|
||||||
|
z-index: 6;
|
||||||
|
}
|
||||||
|
html.e #ops a.act {
|
||||||
|
box-shadow: var(--shadow-inset);
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
html.e a:active {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
html.e :focus,
|
||||||
|
html.e :focus + label {
|
||||||
|
border: 0 !important;
|
||||||
|
outline-offset: 1px;
|
||||||
|
border-radius: var(--radius) !important;
|
||||||
|
box-shadow: inherit;
|
||||||
|
}
|
||||||
|
html.e #opa_x {
|
||||||
|
text-shadow: 0 0 0 var(--transparent) !important;
|
||||||
|
color: var(--bg) !important;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
html.e #opa_x:before {
|
||||||
|
content: "⨯";
|
||||||
|
color: var(--fg) !important;
|
||||||
|
margin-top: -0.1em;
|
||||||
|
font-size: 1.75em;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
html.e .opbox {
|
||||||
|
margin: -1.2em 0 0;
|
||||||
|
box-shadow: var(--shadow-inset-bottom), var(--shadow-inset-left),
|
||||||
|
var(--shadow-inset-right);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
z-index: 5;
|
||||||
|
background: var(--bg);
|
||||||
|
}
|
||||||
|
html.e #srch_form {
|
||||||
|
margin: 0;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
}
|
||||||
|
html.e #op_unpost {
|
||||||
|
max-width: 100vw;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
html.e label:focus {
|
||||||
|
box-shadow: 0 0;
|
||||||
|
}
|
||||||
|
html.e #tree {
|
||||||
|
box-shadow: none;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
html.e #tt {
|
||||||
|
background: var(--w2);
|
||||||
|
}
|
||||||
|
html.e .mdo a {
|
||||||
|
background: 0 0;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
html.e .mdo code,
|
||||||
|
html.e .mdo pre {
|
||||||
|
color: var(--white);
|
||||||
|
background: var(--w2);
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
html.e .mdo h1,
|
||||||
|
html.e .mdo h2 {
|
||||||
|
background: 0 0;
|
||||||
|
border-color: var(--w2);
|
||||||
|
}
|
||||||
|
html.e #tt,
|
||||||
|
html.e .mdo ol ol,
|
||||||
|
html.e .mdo ol ul,
|
||||||
|
html.e .mdo ul ol,
|
||||||
|
html.e .mdo ul ul {
|
||||||
|
border-color: var(--w2);
|
||||||
|
}
|
||||||
|
html.e .mdo li > em,
|
||||||
|
html.e .mdo p > em,
|
||||||
|
html.e .mdo td > em {
|
||||||
|
color: #fd0;
|
||||||
|
}
|
||||||
|
html.e input.txtbox,
|
||||||
|
html.e input[type="text"],
|
||||||
|
html.e select {
|
||||||
|
background-color: var(--txt-bg);
|
||||||
|
box-shadow: var(--shadow-input) !important;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 3px 4px;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
html.e #gfiles {
|
||||||
|
box-shadow: var(--shadow-outset);
|
||||||
|
background: var(--bg);
|
||||||
|
padding: 0.4em;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.3em;
|
||||||
|
}
|
||||||
|
html.e #ggrid {
|
||||||
|
background-color: var(--inset-bg);
|
||||||
|
box-shadow: var(--shadow-input);
|
||||||
|
padding: 1.5em;
|
||||||
|
margin: 0;
|
||||||
|
overflow-x: scroll;
|
||||||
|
}
|
||||||
|
html.e #ghead {
|
||||||
|
margin: 0;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 0.4em;
|
||||||
|
padding: 0;
|
||||||
|
overflow: auto;
|
||||||
|
top: 0px;
|
||||||
|
border-radius: 0px;
|
||||||
|
}
|
||||||
|
html.e #ghead a {
|
||||||
|
margin: 0;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
}
|
||||||
|
html.e ::-webkit-scrollbar,
|
||||||
|
html.e::-webkit-scrollbar {
|
||||||
|
width: 16px !important;
|
||||||
|
height: 16px !important;
|
||||||
|
background: var(--transparent) !important;
|
||||||
|
}
|
||||||
|
html.e ::-webkit-scrollbar-button,
|
||||||
|
html.e ::-webkit-scrollbar-thumb,
|
||||||
|
html.e::-webkit-scrollbar-button,
|
||||||
|
html.e::-webkit-scrollbar-thumb {
|
||||||
|
width: 16px !important;
|
||||||
|
height: 16px !important;
|
||||||
|
background: var(--scroll) !important;
|
||||||
|
/*HC*/
|
||||||
|
box-shadow: var(--shadow-outset);
|
||||||
|
border: 1px solid !important;
|
||||||
|
border-color: var(--silver) var(--black) var(--black) var(--silver) !important;
|
||||||
|
}
|
||||||
|
html.e ::-webkit-scrollbar-track,
|
||||||
|
html.e::-webkit-scrollbar-track {
|
||||||
|
image-rendering: optimize-contrast !important;
|
||||||
|
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgLTAuNSAyIDIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyI+CjxtZXRhZGF0YT5NYWRlIHdpdGggUGl4ZWxzIHRvIFN2ZyBodHRwczovL2NvZGVwZW4uaW8vc2hzaGF3L3Blbi9YYnh2Tmo8L21ldGFkYXRhPgo8cGF0aCBzdHJva2U9IiNjMGMwYzAiIGQ9Ik0wIDBoMU0xIDFoMSIgLz4KPC9zdmc+) !important;
|
||||||
|
background-position: 0 0 !important;
|
||||||
|
background-repeat: repeat !important;
|
||||||
|
background-size: 2px !important;
|
||||||
|
background: var(--scroll-bkg);
|
||||||
|
}
|
||||||
|
#tree::-webkit-scrollbar,
|
||||||
|
#tree::-webkit-scrollbar-track {
|
||||||
|
background: var(--scroll-bkg);
|
||||||
|
}
|
||||||
|
html.e ::-webkit-scrollbar-button,
|
||||||
|
html.e::-webkit-scrollbar-button {
|
||||||
|
background-repeat: no-repeat !important;
|
||||||
|
background-size: 16px !important;
|
||||||
|
}
|
||||||
|
html.e ::-webkit-scrollbar-button:single-button:vertical:decrement,
|
||||||
|
html.e::-webkit-scrollbar-button:single-button:vertical:decrement {
|
||||||
|
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgLTAuNSAxNiAxNiIgc2hhcGUtcmVuZGVyaW5nPSJjcmlzcEVkZ2VzIj4KPG1ldGFkYXRhPk1hZGUgd2l0aCBQaXhlbHMgdG8gU3ZnIGh0dHBzOi8vY29kZXBlbi5pby9zaHNoYXcvcGVuL1hieHZOajwvbWV0YWRhdGE+CjxwYXRoIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTcgNWgxTTYgNmgzTTUgN2g1TTQgOGg3IiAvPgo8L3N2Zz4=) !important;
|
||||||
|
}
|
||||||
|
html.e ::-webkit-scrollbar-button:single-button:vertical:increment,
|
||||||
|
html.e::-webkit-scrollbar-button:single-button:vertical:increment {
|
||||||
|
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgLTAuNSAxNiAxNiIgc2hhcGUtcmVuZGVyaW5nPSJjcmlzcEVkZ2VzIj4KPG1ldGFkYXRhPk1hZGUgd2l0aCBQaXhlbHMgdG8gU3ZnIGh0dHBzOi8vY29kZXBlbi5pby9zaHNoYXcvcGVuL1hieHZOajwvbWV0YWRhdGE+CjxwYXRoIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTQgNWg3TTUgNmg1TTYgN2gzTTcgOGgxIiAvPgo8L3N2Zz4=) !important;
|
||||||
|
}
|
||||||
|
html.e ::-webkit-scrollbar-button:single-button:horizontal:decrement,
|
||||||
|
html.e::-webkit-scrollbar-button:single-button:horizontal:decrement {
|
||||||
|
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgLTAuNSAxNiAxNiIgc2hhcGUtcmVuZGVyaW5nPSJjcmlzcEVkZ2VzIj4KPG1ldGFkYXRhPk1hZGUgd2l0aCBQaXhlbHMgdG8gU3ZnIGh0dHBzOi8vY29kZXBlbi5pby9zaHNoYXcvcGVuL1hieHZOajwvbWV0YWRhdGE+CjxwYXRoIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTggM2gxTTcgNGgyTTYgNWgzTTUgNmg0TTYgN2gzTTcgOGgyTTggOWgxIiAvPgo8L3N2Zz4=) !important;
|
||||||
|
}
|
||||||
|
html.e ::-webkit-scrollbar-button:single-button:horizontal:increment,
|
||||||
|
html.e::-webkit-scrollbar-button:single-button:horizontal:increment {
|
||||||
|
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgLTAuNSAxNiAxNiIgc2hhcGUtcmVuZGVyaW5nPSJjcmlzcEVkZ2VzIj4KPG1ldGFkYXRhPk1hZGUgd2l0aCBQaXhlbHMgdG8gU3ZnIGh0dHBzOi8vY29kZXBlbi5pby9zaHNoYXcvcGVuL1hieHZOajwvbWV0YWRhdGE+CjxwYXRoIHN0cm9rZT0iIzAwMDAwMCIgZD0iTTYgM2gxTTYgNGgyTTYgNWgzTTYgNmg0TTYgN2gzTTYgOGgyTTYgOWgxIiAvPgo8L3N2Zz4=) !important;
|
||||||
|
}
|
||||||
|
html.e ::-webkit-scrollbar-corner,
|
||||||
|
html.e::-webkit-scrollbar-corner {
|
||||||
|
background: var(--silver) !important;
|
||||||
|
}
|
||||||
|
html,
|
||||||
|
html.e #tree {
|
||||||
|
scrollbar-color: inherit !important;
|
||||||
|
}
|
||||||
|
html.e #tree {
|
||||||
|
background: var(--bg);
|
||||||
|
padding-left: 0.4em;
|
||||||
|
padding-top: 0;
|
||||||
|
margin-left: var(--negative-space);
|
||||||
|
}
|
||||||
|
html.e.noscroll #tree {
|
||||||
|
/*HC*/
|
||||||
|
box-shadow: 1px 1px var(--grey), 2px 2px var(--shadow-color-1),
|
||||||
|
var(--shadow-outset-bottom);
|
||||||
|
}
|
||||||
|
html.e #treeh {
|
||||||
|
background: var(--bg);
|
||||||
|
box-shadow: var(--shadow-outset-top), var(--shadow-outset-bottom);
|
||||||
|
width: calc(1.5em + var(--nav-sz) - var(--sbw));
|
||||||
|
height: 2.4em;
|
||||||
|
border: none;
|
||||||
|
top: -2px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.6em;
|
||||||
|
}
|
||||||
|
html.e #treeh .btn {
|
||||||
|
margin: 0px;
|
||||||
|
top: auto;
|
||||||
|
}
|
||||||
|
html.e #tree ul {
|
||||||
|
border-left: var(--border-dashed-black);
|
||||||
|
margin-left: 2.15em;
|
||||||
|
}
|
||||||
|
html.e .ntree a:first-child {
|
||||||
|
font-family: scp, monospace, monospace;
|
||||||
|
font-size: 1.2em;
|
||||||
|
line-height: 0;
|
||||||
|
background: var(--inset-bg);
|
||||||
|
aspect-ratio: 1/1;
|
||||||
|
text-align: center;
|
||||||
|
align-content: center;
|
||||||
|
border-radius: var(--radius) !important;
|
||||||
|
padding: 0.057em;
|
||||||
|
border: 1px solid var(--black);
|
||||||
|
}
|
||||||
|
html.e .ntree a:first-child:after {
|
||||||
|
content: ".";
|
||||||
|
position: absolute;
|
||||||
|
border-top: var(--border-dashed-black);
|
||||||
|
color: var(--transparent);
|
||||||
|
font-size: 0.9em;
|
||||||
|
margin-left: 0.13em;
|
||||||
|
}
|
||||||
|
html.e #treeul {
|
||||||
|
border: 0 !important;
|
||||||
|
position: static;
|
||||||
|
margin: 0 !important;
|
||||||
|
min-height: 100%;
|
||||||
|
height: max-content;
|
||||||
|
}
|
||||||
|
html.e .ntree a:last-of-type:before {
|
||||||
|
content: "📁";
|
||||||
|
margin-left: 0.3em;
|
||||||
|
}
|
||||||
|
html.e .ntree {
|
||||||
|
padding-left: 1em !important;
|
||||||
|
padding-top: 0.3em !important;
|
||||||
|
background: var(--inset-bg);
|
||||||
|
box-shadow: var(--shadow-inset-left), var(--shadow-inset-bottom);
|
||||||
|
}
|
||||||
|
html.e #tree li {
|
||||||
|
margin-left: -0.5em;
|
||||||
|
border-top: 0;
|
||||||
|
}
|
||||||
|
html.e .ntree a:hover {
|
||||||
|
outline-offset: -2px;
|
||||||
|
color: var(--fg);
|
||||||
|
border-radius: var(--radius) !important;
|
||||||
|
}
|
||||||
|
html.e #treepar {
|
||||||
|
width: calc(-1em + var(--nav-sz) - var(--sbw));
|
||||||
|
overflow: hidden;
|
||||||
|
left: -0.7em;
|
||||||
|
box-shadow: var(--shadow-inset-left), var(--shadow-inset-top);
|
||||||
|
border-left: 0 !important;
|
||||||
|
border-bottom: var(--border-dashed-black);
|
||||||
|
margin-left: calc(2.1em - (1em - var(--negative-space))) !important;
|
||||||
|
}
|
||||||
|
html.e #path,
|
||||||
|
html.e #widgeti,
|
||||||
|
html.e #wtoggle,
|
||||||
|
html.e #wtoggle a,
|
||||||
|
html.e #files,
|
||||||
|
html.e #files thead th,
|
||||||
|
html.e #ghead a,
|
||||||
|
html.e #tree {
|
||||||
|
box-shadow: var(--shadow-outset);
|
||||||
|
}
|
||||||
|
html.e.noscroll #treepar {
|
||||||
|
width: calc(var(--nav-sz) - 1em);
|
||||||
|
}
|
||||||
|
html.e #docul {
|
||||||
|
border-left: 0 !important;
|
||||||
|
margin-left: 0 !important;
|
||||||
|
}
|
||||||
|
html.e #wrap {
|
||||||
|
transform: translateX(calc((var(--negative-space) * 2) - 1.2em));
|
||||||
|
padding-right: var(--negative-space);
|
||||||
|
position: relative;
|
||||||
|
margin-right: calc((var(--negative-space) * 2) - 1.2em);
|
||||||
|
margin-top: var(--negative-space);
|
||||||
|
margin-left: 1.2em;
|
||||||
|
/*overflow-x: auto; fix for OOB table when screen space is limited (mobile), but removes sticky header*/
|
||||||
|
}
|
||||||
|
html.e input[type="radio"] {
|
||||||
|
accent-color: #232323;
|
||||||
|
}
|
||||||
|
html.e #path {
|
||||||
|
width: calc(100% - 0.4em);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.2em;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
html.e #path i {
|
||||||
|
border: 1px solid var(--w);
|
||||||
|
border-color: var(--w);
|
||||||
|
margin: 0;
|
||||||
|
border-width: 0.1em 0.1em 0 0;
|
||||||
|
height: 0.5em;
|
||||||
|
width: 0.5em;
|
||||||
|
}/*
|
||||||
|
html.e #hovertree:after {
|
||||||
|
color: red;
|
||||||
|
content: "BUGGY";
|
||||||
|
html.ez #hovertree:after {
|
||||||
|
color: rgb(255 98 98);
|
||||||
|
content: "BUGGY";
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
html.e #widget {
|
||||||
|
box-shadow: 0 0;
|
||||||
|
border: 0 !important;
|
||||||
|
}
|
||||||
|
html.e #wtico,
|
||||||
|
html.e #zip1 {
|
||||||
|
box-shadow: 0 0 !important;
|
||||||
|
}
|
||||||
|
html.e #wtgrid {
|
||||||
|
top: -0.09em;
|
||||||
|
}
|
||||||
|
html.e #wfs,
|
||||||
|
html.e #wm3u,
|
||||||
|
html.e #wnp,
|
||||||
|
html.e #wzip {
|
||||||
|
border-width: 0 1px 0 0;
|
||||||
|
}
|
||||||
|
html.e #wfm.act + #wzip1 + #wzip,
|
||||||
|
html.e #wfm.act + #wzip1 + #wzip + #wnp {
|
||||||
|
border-left-width: 1px;
|
||||||
|
}
|
||||||
|
html.e #barpos {
|
||||||
|
/* border-radius: var(--radius); */
|
||||||
|
box-shadow: var(--shadow-inset);
|
||||||
|
}
|
||||||
|
html.e #goh + span {
|
||||||
|
border-left: 0.1em solid var(--bg-u5);
|
||||||
|
}
|
||||||
|
html.e #wfp {
|
||||||
|
margin: var(--negative-space);
|
||||||
|
font-size: 0;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
html.e #wfp a {
|
||||||
|
font-size: large;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
html.e #repl {
|
||||||
|
font-size: large;
|
||||||
|
padding: 0.33em;
|
||||||
|
right: calc(var(--negative-space) * 0.89);
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
html.e #epi {
|
||||||
|
text-align: center;
|
||||||
|
text-wrap-mode: nowrap;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.e #epi.logue:not(.mdo) {
|
||||||
|
padding: 0.8em;
|
||||||
|
box-shadow: var(--shadow-outset);
|
||||||
|
}
|
||||||
|
|
||||||
|
html.e #epi.logue.mdo {
|
||||||
|
padding-left: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.e #doc {
|
||||||
|
box-shadow: var(--shadow-inset);
|
||||||
|
background: var(--inset-bg);
|
||||||
|
margin: 0.2em;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
html.e #detree {
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -24,6 +24,7 @@ h1 {
|
|||||||
li {
|
li {
|
||||||
margin: 1em 0;
|
margin: 1em 0;
|
||||||
}
|
}
|
||||||
|
#lo,
|
||||||
a {
|
a {
|
||||||
color: #047;
|
color: #047;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
@ -47,6 +48,7 @@ td a {
|
|||||||
float: right;
|
float: right;
|
||||||
margin: -.2em 0 0 .8em;
|
margin: -.2em 0 0 .8em;
|
||||||
}
|
}
|
||||||
|
#lo,
|
||||||
.logout,
|
.logout,
|
||||||
a.r {
|
a.r {
|
||||||
color: #c04;
|
color: #c04;
|
||||||
@ -176,12 +178,14 @@ html.z {
|
|||||||
html.z h1 {
|
html.z h1 {
|
||||||
border-color: #777;
|
border-color: #777;
|
||||||
}
|
}
|
||||||
|
html.z #lo,
|
||||||
html.z a {
|
html.z a {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background: #057;
|
background: #057;
|
||||||
border-color: #37a;
|
border-color: #37a;
|
||||||
}
|
}
|
||||||
html.z .logout,
|
html.z .logout,
|
||||||
|
html.z #lo,
|
||||||
html.z a.r {
|
html.z a.r {
|
||||||
background: #804;
|
background: #804;
|
||||||
border-color: #c28;
|
border-color: #c28;
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
<p id="b">howdy stranger <small>(you're not logged in)</small></p>
|
<p id="b">howdy stranger <small>(you're not logged in)</small></p>
|
||||||
{%- else %}
|
{%- else %}
|
||||||
<a id="c" href="{{ r }}/?pw=x" class="logout">logout</a>
|
<a id="c" href="{{ r }}/?pw=x" class="logout">logout</a>
|
||||||
<p><span id="m">welcome back,</span> <strong>{{ this.uname|e }}</strong></p>
|
<p><span id="m">welcome back,</span> <strong id="un">{{ this.uname|e }}</strong></p>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
@ -168,6 +168,13 @@
|
|||||||
|
|
||||||
<li><a id="af" href="{{ r }}/?ru">show recent uploads</a></li>
|
<li><a id="af" href="{{ r }}/?ru">show recent uploads</a></li>
|
||||||
<li><a id="k" href="{{ r }}/?reset" class="r" onclick="localStorage.clear();return true">reset client settings</a></li>
|
<li><a id="k" href="{{ r }}/?reset" class="r" onclick="localStorage.clear();return true">reset client settings</a></li>
|
||||||
|
|
||||||
|
{%- if this.uname != '*' %}
|
||||||
|
<li><form method="post" enctype="multipart/form-data">
|
||||||
|
<input type="hidden" name="act" value="logout" />
|
||||||
|
<input type="submit" id="lo" value="logout “{{ this.uname|e }}” everywhere" />
|
||||||
|
</form></li>
|
||||||
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -17,6 +17,11 @@ var Ls = {
|
|||||||
"j1": "k304 bryter tilkoplingen for hver HTTP 304. Dette hjelper mot visse mellomtjenere som kan sette seg fast / plutselig slutter å laste sider, men det reduserer også ytelsen betydelig",
|
"j1": "k304 bryter tilkoplingen for hver HTTP 304. Dette hjelper mot visse mellomtjenere som kan sette seg fast / plutselig slutter å laste sider, men det reduserer også ytelsen betydelig",
|
||||||
"k1": "nullstill innstillinger",
|
"k1": "nullstill innstillinger",
|
||||||
"l1": "logg inn:",
|
"l1": "logg inn:",
|
||||||
|
"ls3": "logg inn",
|
||||||
|
"lu4": "brukernavn",
|
||||||
|
"lp4": "passord",
|
||||||
|
"lo3": "logg ut “{0}” overalt",
|
||||||
|
"lo2": "avslutter økten på alle nettlesere",
|
||||||
"m1": "velkommen tilbake,",
|
"m1": "velkommen tilbake,",
|
||||||
"n1": "404: filen finnes ikke ┐( ´ -`)┌",
|
"n1": "404: filen finnes ikke ┐( ´ -`)┌",
|
||||||
"o1": 'eller kanskje du ikke har tilgang? prøv et passord eller <a href="' + SR + '/?h">gå hjem</a>',
|
"o1": 'eller kanskje du ikke har tilgang? prøv et passord eller <a href="' + SR + '/?h">gå hjem</a>',
|
||||||
@ -46,6 +51,7 @@ var Ls = {
|
|||||||
"eng": {
|
"eng": {
|
||||||
"d2": "shows the state of all active threads",
|
"d2": "shows the state of all active threads",
|
||||||
"e2": "reload config files (accounts/volumes/volflags),$Nand rescan all e2ds volumes$N$Nnote: any changes to global settings$Nrequire a full restart to take effect",
|
"e2": "reload config files (accounts/volumes/volflags),$Nand rescan all e2ds volumes$N$Nnote: any changes to global settings$Nrequire a full restart to take effect",
|
||||||
|
"lo2": "ends the session on all browsers",
|
||||||
"u2": "time since the last server write$N( upload / rename / ... )$N$N17d = 17 days$N1h23 = 1 hour 23 minutes$N4m56 = 4 minutes 56 seconds",
|
"u2": "time since the last server write$N( upload / rename / ... )$N$N17d = 17 days$N1h23 = 1 hour 23 minutes$N4m56 = 4 minutes 56 seconds",
|
||||||
"v2": "use this server as a local HDD",
|
"v2": "use this server as a local HDD",
|
||||||
"ta1": "fill in your new password first",
|
"ta1": "fill in your new password first",
|
||||||
@ -68,6 +74,11 @@ var Ls = {
|
|||||||
"j1": "k304 会在每个 HTTP 304 时断开连接。这有助于避免某些代理服务器卡住或突然停止加载页面,但也会显著降低性能。",
|
"j1": "k304 会在每个 HTTP 304 时断开连接。这有助于避免某些代理服务器卡住或突然停止加载页面,但也会显著降低性能。",
|
||||||
"k1": "重置设置",
|
"k1": "重置设置",
|
||||||
"l1": "登录:",
|
"l1": "登录:",
|
||||||
|
"ls3": "登录", //m
|
||||||
|
"lu4": "用户名", //m
|
||||||
|
"lp4": "密码", //m
|
||||||
|
"lo3": "在所有地方注销 {0}", //m
|
||||||
|
"lo2": "这将结束在所有浏览器中的会话", //m
|
||||||
"m1": "欢迎回来,",
|
"m1": "欢迎回来,",
|
||||||
"n1": "404: 文件不存在 ┐( ´ -`)┌",
|
"n1": "404: 文件不存在 ┐( ´ -`)┌",
|
||||||
"o1": '或者你可能没有权限?尝试输入密码或 <a href="' + SR + '/?h">回家</a>',
|
"o1": '或者你可能没有权限?尝试输入密码或 <a href="' + SR + '/?h">回家</a>',
|
||||||
@ -110,6 +121,11 @@ var Ls = {
|
|||||||
"j1": "povolení k304 odpojí vašeho klienta při každém HTTP 304, což může zabránit některým chybovým proxy serverům, aby se zasekly (náhle nenačítaly stránky), <em>ale</em> také to obecně zpomalí věci",
|
"j1": "povolení k304 odpojí vašeho klienta při každém HTTP 304, což může zabránit některým chybovým proxy serverům, aby se zasekly (náhle nenačítaly stránky), <em>ale</em> také to obecně zpomalí věci",
|
||||||
"k1": "resetovat nastavení klienta",
|
"k1": "resetovat nastavení klienta",
|
||||||
"l1": "přihlaste se pro více:",
|
"l1": "přihlaste se pro více:",
|
||||||
|
"ls3": "přihlásit se", //m
|
||||||
|
"lu4": "uživatelské jméno", //m
|
||||||
|
"lp4": "heslo", //m
|
||||||
|
"lo3": "odhlásit “{0}” všude", //m
|
||||||
|
"lo2": "tímto ukončíte relaci ve všech prohlížečích", //m
|
||||||
"m1": "vítej zpět,",
|
"m1": "vítej zpět,",
|
||||||
"n1": "404 nenalezeno ┐( ´ -`)┌",
|
"n1": "404 nenalezeno ┐( ´ -`)┌",
|
||||||
"o1": 'nebo možná nemáš přístup -- zkus heslo nebo <a href="' + SR + '/?h">jdi domů</a>',
|
"o1": 'nebo možná nemáš přístup -- zkus heslo nebo <a href="' + SR + '/?h">jdi domů</a>',
|
||||||
@ -151,6 +167,11 @@ var Ls = {
|
|||||||
"j1": "k304 trennt die Clientverbindung bei jedem HTTP 304, was Bugs mit problematischen Proxies vorbeugen kann (z.B. nicht ladenden Seiten), macht Dinge aber generell langsamer",
|
"j1": "k304 trennt die Clientverbindung bei jedem HTTP 304, was Bugs mit problematischen Proxies vorbeugen kann (z.B. nicht ladenden Seiten), macht Dinge aber generell langsamer",
|
||||||
"k1": "Client-Einstellungen zurücksetzen",
|
"k1": "Client-Einstellungen zurücksetzen",
|
||||||
"l1": "Melde dich an für mehr:",
|
"l1": "Melde dich an für mehr:",
|
||||||
|
"ls3": "Anmelden", //m
|
||||||
|
"lu4": "Benutzername", //m
|
||||||
|
"lp4": "Passwort", //m
|
||||||
|
"lo3": "“{0}” überall abmelden", //m
|
||||||
|
"lo2": "Dies beendet die Sitzung in allen Browsern", //m
|
||||||
"m1": "Willkommen zurück,",
|
"m1": "Willkommen zurück,",
|
||||||
"n1": "404 Nicht gefunden ┐( ´ -`)┌",
|
"n1": "404 Nicht gefunden ┐( ´ -`)┌",
|
||||||
"o1": 'or maybe you don\'t have access -- try a password or <a href="' + SR + '/?h">go home</a>',
|
"o1": 'or maybe you don\'t have access -- try a password or <a href="' + SR + '/?h">go home</a>',
|
||||||
@ -192,6 +213,11 @@ var Ls = {
|
|||||||
"j1": "k304 katkaisee yhteytesi jokaisella HTTP 304:llä, mikä voi estää joitain bugisia välityspalvelimia jumittumasta/lopettamasta sivujen lataamista, <em>mutta</em> se myös vähentää suorituskykyä",
|
"j1": "k304 katkaisee yhteytesi jokaisella HTTP 304:llä, mikä voi estää joitain bugisia välityspalvelimia jumittumasta/lopettamasta sivujen lataamista, <em>mutta</em> se myös vähentää suorituskykyä",
|
||||||
"k1": "nollaa asetukset",
|
"k1": "nollaa asetukset",
|
||||||
"l1": "kirjaudu sisään:",
|
"l1": "kirjaudu sisään:",
|
||||||
|
"ls3": "kirjaudu sisään", //m
|
||||||
|
"lu4": "käyttäjätunnus", //m
|
||||||
|
"lp4": "salasana", //m
|
||||||
|
"lo3": "kirjaa “{0}” ulos kaikkialta", //m
|
||||||
|
"lo2": "tämä lopettaa istunnon kaikissa selaimissa", //m
|
||||||
"m1": "tervetuloa takaisin,",
|
"m1": "tervetuloa takaisin,",
|
||||||
"n1": "404: ei löytynyt mitään ┐( ´ -`)┌",
|
"n1": "404: ei löytynyt mitään ┐( ´ -`)┌",
|
||||||
"o1": 'tai ehkä sinulla ei vain ole käyttöoikeuksia? kokeile salasanaa tai <a href="' + SR + '/?h">mene kotiin</a>',
|
"o1": 'tai ehkä sinulla ei vain ole käyttöoikeuksia? kokeile salasanaa tai <a href="' + SR + '/?h">mene kotiin</a>',
|
||||||
@ -234,6 +260,11 @@ var Ls = {
|
|||||||
"j1": "activer k304 va déconnecter votre client sur chaque HTTP 304, ce qui peut éviter à certains proxies défectueux de rester bloqués (les pages ne se chargent soudainement plus), <em>mais</em> cela ralentira également les choses en général",
|
"j1": "activer k304 va déconnecter votre client sur chaque HTTP 304, ce qui peut éviter à certains proxies défectueux de rester bloqués (les pages ne se chargent soudainement plus), <em>mais</em> cela ralentira également les choses en général",
|
||||||
"k1": "réinitialiser les paramètres du client",
|
"k1": "réinitialiser les paramètres du client",
|
||||||
"l1": "connectez-vous pour en savoir plus :",
|
"l1": "connectez-vous pour en savoir plus :",
|
||||||
|
"ls3": "se connecter", //m
|
||||||
|
"lu4": "nom d'utilisateur", //m
|
||||||
|
"lp4": "mot de passe", //m
|
||||||
|
"lo3": "déconnecter “{0}” partout", //m
|
||||||
|
"lo2": "cela mettra fin à la session sur tous les navigateurs", //m
|
||||||
"m1": "heureux de vous revoir,",
|
"m1": "heureux de vous revoir,",
|
||||||
"n1": "404 introuvable ┐( ´ -`)┌",
|
"n1": "404 introuvable ┐( ´ -`)┌",
|
||||||
"o1": 'ou peut-être que vous n\'y avez pas accès -- essayer un mot de passe ou <a href="' + SR + '/?h">aller à la page d\'accueil</a>',
|
"o1": 'ou peut-être que vous n\'y avez pas accès -- essayer un mot de passe ou <a href="' + SR + '/?h">aller à la page d\'accueil</a>',
|
||||||
@ -275,6 +306,11 @@ var Ls = {
|
|||||||
"j1": "η ενεργοποίηση του k304 θα αποσυνδέσει το πρόγραμμα πελάτη σου σε κάθε HTTP 304, κάτι που μπορεί να αποτρέψει κάποια προβληματικά proxies από το να κολλάνε (να μην φορτώνουν ξαφνικά σελίδες), <em>αλλά</em> θα κάνει τα πράγματα, γενικά πιο αργά",
|
"j1": "η ενεργοποίηση του k304 θα αποσυνδέσει το πρόγραμμα πελάτη σου σε κάθε HTTP 304, κάτι που μπορεί να αποτρέψει κάποια προβληματικά proxies από το να κολλάνε (να μην φορτώνουν ξαφνικά σελίδες), <em>αλλά</em> θα κάνει τα πράγματα, γενικά πιο αργά",
|
||||||
"k1": "επαναφορά ρυθμίσεων στο πρόγραμμα πελάτη",
|
"k1": "επαναφορά ρυθμίσεων στο πρόγραμμα πελάτη",
|
||||||
"l1": "συνδέσου για περισσότερα:",
|
"l1": "συνδέσου για περισσότερα:",
|
||||||
|
"ls3": "σύνδεση", //m
|
||||||
|
"lu4": "όνομα χρήστη", //m
|
||||||
|
"lp4": "κωδικός πρόσβασης", //m
|
||||||
|
"lo3": "αποσύνδεση του “{0}” από παντού", //m
|
||||||
|
"lo2": "αυτό θα τερματίσει τη συνεδρία σε όλους τους περιηγητές", //m
|
||||||
"m1": "καλώς ήρθες,",
|
"m1": "καλώς ήρθες,",
|
||||||
"n1": "404 δεν βρέθηκε ┐( ´ -`)┌",
|
"n1": "404 δεν βρέθηκε ┐( ´ -`)┌",
|
||||||
"o1": '´η μήπως δεν έχεις πρόσβαση -- δοκίμασε έναν κωδικό <a href="' + SR + '/?h">πήγαινε στην αρχική</a>',
|
"o1": '´η μήπως δεν έχεις πρόσβαση -- δοκίμασε έναν κωδικό <a href="' + SR + '/?h">πήγαινε στην αρχική</a>',
|
||||||
@ -316,6 +352,11 @@ var Ls = {
|
|||||||
"j1": "k304 interrompe la connessione per ogni HTTP 304. Questo aiuta contro alcuni proxy difettosi che possono bloccarsi o smettere improvvisamente di caricare pagine, ma riduce notevolmente le prestazioni",
|
"j1": "k304 interrompe la connessione per ogni HTTP 304. Questo aiuta contro alcuni proxy difettosi che possono bloccarsi o smettere improvvisamente di caricare pagine, ma riduce notevolmente le prestazioni",
|
||||||
"k1": "resetta impostazioni",
|
"k1": "resetta impostazioni",
|
||||||
"l1": "accedi:",
|
"l1": "accedi:",
|
||||||
|
"ls3": "accedi", //m
|
||||||
|
"lu4": "nome utente", //m
|
||||||
|
"lp4": "password", //m
|
||||||
|
"lo3": "disconnetti “{0}” ovunque", //m
|
||||||
|
"lo2": "questo terminerà la sessione su tutti i browser", //m
|
||||||
"m1": "bentornato,",
|
"m1": "bentornato,",
|
||||||
"n1": "404: file non trovato ┐( ´ -`)┌",
|
"n1": "404: file non trovato ┐( ´ -`)┌",
|
||||||
"o1": "oppure forse non hai accesso? prova una password o <a href=\"SR/?h\">torna alla home</a>",
|
"o1": "oppure forse non hai accesso? prova una password o <a href=\"SR/?h\">torna alla home</a>",
|
||||||
@ -342,6 +383,53 @@ var Ls = {
|
|||||||
"af1": "mostra i file caricati di recente",
|
"af1": "mostra i file caricati di recente",
|
||||||
"ag1": "mostra utenti IdP conosciuti"
|
"ag1": "mostra utenti IdP conosciuti"
|
||||||
},
|
},
|
||||||
|
"kor": {
|
||||||
|
"a1": "새로고침",
|
||||||
|
"b1": "어이 친구! 처음 보는 얼굴인데? <small>(로그인되어 있지 않습니다)</small>",
|
||||||
|
"c1": "로그아웃",
|
||||||
|
"d1": "스택 덤프하기",
|
||||||
|
"d2": "모든 활성 스레드의 상태를 표시합니다",
|
||||||
|
"e1": "설정 다시 불러오기",
|
||||||
|
"e2": "설정 파일(계정/볼륨/볼륨 플래그)을 다시 불러오고,$N모든 e2ds 볼륨을 다시 스캔합니다$N$N참고: 전역 설정에 대한 변경 사항은$N적용하려면 전체 재시작이 필요합니다",
|
||||||
|
"f1": "탐색 가능한 곳:",
|
||||||
|
"g1": "업로드 가능한 곳:",
|
||||||
|
"cc1": "기타 항목:",
|
||||||
|
"h1": "k304 비활성화",
|
||||||
|
"i1": "k304 활성화",
|
||||||
|
"j1": "k304를 활성화하면 모든 HTTP 304 응답 시 클라이언트 연결이 끊어집니다. 이는 일부 프록시가 멈추는 현상(갑자기 페이지가 로드되지 않음)을 방지할 수 있지만, <em>대신 전반적인 속도는 느려집니다.</em>",
|
||||||
|
"k1": "클라이언트 설정 초기화",
|
||||||
|
"l1": "로그인하기:",
|
||||||
|
"ls3": "로그인", //m
|
||||||
|
"lu4": "사용자 이름", //m
|
||||||
|
"lp4": "비밀번호", //m
|
||||||
|
"lo3": "{0}을(를) 모든 곳에서 로그아웃", //m
|
||||||
|
"lo2": "이 작업은 모든 브라우저에서 세션을 종료합니다", //m
|
||||||
|
"m1": "또 오셨네요,",
|
||||||
|
"n1": "404 찾을 수 없음 ┐( ´ -`)┌",
|
||||||
|
"o1": "또는 접근 권한이 없을 수 있습니다. 비밀번호를 입력하거나 <a href=\"' + SR + '/?h\">홈으로 이동</a>하세요",
|
||||||
|
"p1": "403 접근 금지 ~┻━┻",
|
||||||
|
"q1": "비밀번호를 입력하거나 <a href=\"' + SR + '/?h\">홈으로 이동</a>하세요",
|
||||||
|
"r1": "홈으로 이동",
|
||||||
|
".s1": "다시 스캔",
|
||||||
|
"t1": "작업",
|
||||||
|
"u2": "서버에 마지막으로 쓰기 작업을 한 후 경과된 시간$N(업로드 / 이름 변경 / 등등...)$N$N17d = 17일$N1h23 = 1시간 23분$N4m56 = 4분 56초",
|
||||||
|
"v1": "연결",
|
||||||
|
"v2": "이 서버를 로컬 하드디스크처럼 사용하기",
|
||||||
|
"w1": "HTTPS로 전환",
|
||||||
|
"x1": "비밀번호 변경",
|
||||||
|
"y1": "공유 설정",
|
||||||
|
"z1": "이 공유 잠금해제:",
|
||||||
|
"ta1": "새 비밀번호를 먼저 입력하세요",
|
||||||
|
"ta2": "새 비밀번호 확인을 위해 다시 입력하세요:",
|
||||||
|
"ta3": "오타가 있습니다. 다시 시도해주세요",
|
||||||
|
"aa1": "수신 중인 파일:",
|
||||||
|
"ab1": "no304 비활성화",
|
||||||
|
"ac1": "no304 활성화",
|
||||||
|
"ad1": "no304를 활성화하면 모든 캐싱이 비활성화됩니다. k304로 충분하지 않은 경우 시도해보세요. 네트워크 트래픽이 대량으로 낭비됩니다!",
|
||||||
|
"ae1": "활성 다운로드:",
|
||||||
|
"af1": "최근 업로드 보기",
|
||||||
|
"ag1": "IdP 캐시 보기"
|
||||||
|
},
|
||||||
"nld": {
|
"nld": {
|
||||||
"a1": "Update",
|
"a1": "Update",
|
||||||
"b1": "Hallo, hoe gaat het met jou? <small>(Je bent niet ingelogd)</small>",
|
"b1": "Hallo, hoe gaat het met jou? <small>(Je bent niet ingelogd)</small>",
|
||||||
@ -358,6 +446,11 @@ var Ls = {
|
|||||||
"j1": "k304 verbreekt de verbinding voor elke HTTP 304. Dit helpt tegen bepaalde proxy servers die kunnen vastlopen/plotseling stoppen met het laden van pagina's, maar het vermindert ook de prestaties aanzienlijk",
|
"j1": "k304 verbreekt de verbinding voor elke HTTP 304. Dit helpt tegen bepaalde proxy servers die kunnen vastlopen/plotseling stoppen met het laden van pagina's, maar het vermindert ook de prestaties aanzienlijk",
|
||||||
"k1": "Instellingen resetten",
|
"k1": "Instellingen resetten",
|
||||||
"l1": "Inloggen:",
|
"l1": "Inloggen:",
|
||||||
|
"ls3": "inloggen", //m
|
||||||
|
"lu4": "gebruikersnaam", //m
|
||||||
|
"lp4": "wachtwoord", //m
|
||||||
|
"lo3": "“{0}” overal afmelden", //m
|
||||||
|
"lo2": "dit zal de sessie in alle browsers beëindigen", //m
|
||||||
"m1": "Welkom terug,",
|
"m1": "Welkom terug,",
|
||||||
"n1": "404: bestand bestaat niet ┐( ´ -`)┌",
|
"n1": "404: bestand bestaat niet ┐( ´ -`)┌",
|
||||||
"o1": 'of misschien heb je geen toegang? probeer een wachtwoord of <a href="' + SR + '/?h">ga naar startscherm</a>',
|
"o1": 'of misschien heb je geen toegang? probeer een wachtwoord of <a href="' + SR + '/?h">ga naar startscherm</a>',
|
||||||
@ -400,6 +493,11 @@ var Ls = {
|
|||||||
"j1": "k304 bryt tilkoplinga for kvar HTTP 304. Dette hjelp mot visse mellomtjenarar som kan sette seg fast / plutselig sluttar å laste sider, men det sett óg ytinga ned betydelig",
|
"j1": "k304 bryt tilkoplinga for kvar HTTP 304. Dette hjelp mot visse mellomtjenarar som kan sette seg fast / plutselig sluttar å laste sider, men det sett óg ytinga ned betydelig",
|
||||||
"k1": "nullstill innstillinger",
|
"k1": "nullstill innstillinger",
|
||||||
"l1": "logg inn:",
|
"l1": "logg inn:",
|
||||||
|
"ls3": "logg inn",
|
||||||
|
"lu4": "brukarnamn",
|
||||||
|
"lp4": "passord",
|
||||||
|
"lo3": "logg ut “{0}” overalt",
|
||||||
|
"lo2": "avslutt økta på alle nettlesarar",
|
||||||
"m1": "velkomen attende,",
|
"m1": "velkomen attende,",
|
||||||
"n1": "404: filen finnast ikkje ┐( ´ -`)┌",
|
"n1": "404: filen finnast ikkje ┐( ´ -`)┌",
|
||||||
"o1": 'eller kanskje du ikkje har høve? prøv eit passord eller <a href="' + SR + '/?h">gå heim</a>',
|
"o1": 'eller kanskje du ikkje har høve? prøv eit passord eller <a href="' + SR + '/?h">gå heim</a>',
|
||||||
@ -442,6 +540,11 @@ var Ls = {
|
|||||||
"j1": "włączenie k304 będzie odłączało klienta przy każdorazowym otrzymaniu kodu HTTP 304, co może zapobiec wieszaniu się wadliwych proxy, <em>ale</em> spowolni ogólne działanie",
|
"j1": "włączenie k304 będzie odłączało klienta przy każdorazowym otrzymaniu kodu HTTP 304, co może zapobiec wieszaniu się wadliwych proxy, <em>ale</em> spowolni ogólne działanie",
|
||||||
"k1": "zresetuj ustawienia klienta",
|
"k1": "zresetuj ustawienia klienta",
|
||||||
"l1": "zaloguj się po więcej:",
|
"l1": "zaloguj się po więcej:",
|
||||||
|
"ls3": "zaloguj się", //m
|
||||||
|
"lu4": "nazwa użytkownika", //m
|
||||||
|
"lp4": "hasło", //m
|
||||||
|
"lo3": "wyloguj “{0}” wszędzie", //m
|
||||||
|
"lo2": "spowoduje to zakończenie sesji we wszystkich przeglądarkach", //m
|
||||||
"m1": "Witaj,",
|
"m1": "Witaj,",
|
||||||
"n1": "404 nie znaleziono ┐( ´ -`)┌",
|
"n1": "404 nie znaleziono ┐( ´ -`)┌",
|
||||||
"o1": 'lub możesz nie mieć dostępu -- spróbuj wprowadzić hasło lub <a href="' + SR + '/?h">przejdź do strony głównej</a>',
|
"o1": 'lub możesz nie mieć dostępu -- spróbuj wprowadzić hasło lub <a href="' + SR + '/?h">przejdź do strony głównej</a>',
|
||||||
@ -484,6 +587,11 @@ var Ls = {
|
|||||||
"j1": "activar k304 desconectará tu cliente en cada HTTP 304, lo que puede evitar que algunos proxies con errores se atasquen (dejando de cargar páginas de repente), <em>pero</em> también ralentizará las cosas en general",
|
"j1": "activar k304 desconectará tu cliente en cada HTTP 304, lo que puede evitar que algunos proxies con errores se atasquen (dejando de cargar páginas de repente), <em>pero</em> también ralentizará las cosas en general",
|
||||||
"k1": "restablecer config. de cliente",
|
"k1": "restablecer config. de cliente",
|
||||||
"l1": "inicia sesión para más:",
|
"l1": "inicia sesión para más:",
|
||||||
|
"ls3": "iniciar sesión", //m
|
||||||
|
"lu4": "nombre de usuario", //m
|
||||||
|
"lp4": "contraseña", //m
|
||||||
|
"lo3": "cerrar sesión de “{0}” en todas partes", //m
|
||||||
|
"lo2": "esto finalizará la sesión en todos los navegadores", //m
|
||||||
"m1": "bienvenido de nuevo,",
|
"m1": "bienvenido de nuevo,",
|
||||||
"n1": "404 no encontrado ┐( ´ -`)┌",
|
"n1": "404 no encontrado ┐( ´ -`)┌",
|
||||||
"o1": '¿o quizás no tienes acceso? -- prueba con una contraseña o <a href=\"' + SR + '/?h\">vuelve al inicio</a>',
|
"o1": '¿o quizás no tienes acceso? -- prueba con una contraseña o <a href=\"' + SR + '/?h\">vuelve al inicio</a>',
|
||||||
@ -510,6 +618,53 @@ var Ls = {
|
|||||||
"af1": "mostrar subidas recientes",
|
"af1": "mostrar subidas recientes",
|
||||||
"ag1": "mostrar usuarios IdP conocidos"
|
"ag1": "mostrar usuarios IdP conocidos"
|
||||||
},
|
},
|
||||||
|
"swe": {
|
||||||
|
"a1": "uppdatera",
|
||||||
|
"b1": "tjena främling <small>(du är inte inloggad)</small>",
|
||||||
|
"c1": "logga ut",
|
||||||
|
"d1": "dumpa stacken",
|
||||||
|
"d2": "visar tillståndet på alla aktiva trådar",
|
||||||
|
"e1": "ladda om konfig.",
|
||||||
|
"e2": "ladda om konfigurationsfiler (konton/volymer/volflaggor),$Noch skanna om alla e2ds-volymer$N$Nobs.: ändrade globala inställningar$Nkräver en fullständig omstart",
|
||||||
|
"f1": "du kan bläddra:",
|
||||||
|
"g1": "du kan ladda upp till:",
|
||||||
|
"cc1": "annat:",
|
||||||
|
"h1": "avaktivera k304",
|
||||||
|
"i1": "aktivera k304",
|
||||||
|
"j1": "med k304 aktiverad kommer klienten att koppla bort sig vid varje HTTP 304-fel, vilket kan hindra vissa buggiga proxyservrar från att fastna (sidor slutar ladda), <em>men</em> saker kommer också att bli långsammare i allmänhet",
|
||||||
|
"k1": "återställ klientinställningar",
|
||||||
|
"l1": "logga in för att se mer:",
|
||||||
|
"ls3": "logga in", //m
|
||||||
|
"lu4": "användarnamn", //m
|
||||||
|
"lp4": "lösenord", //m
|
||||||
|
"lo3": "logga ut “{0}” överallt", //m
|
||||||
|
"lo2": "avsluta sessionen i alla webbläsare", //m
|
||||||
|
"m1": "välkommen tillbaka,",
|
||||||
|
"n1": "404 hittades inte ┐( ´ -`)┌",
|
||||||
|
"o1": 'eller så har du kanske inte tillgång -- prova ett lösenord eller <a href="' + SR + '/?h">åk hem</a>',
|
||||||
|
"p1": "403 nekat ~┻━┻",
|
||||||
|
"q1": 'använd ett lösenord eller <a href="' + SR + '/?h">åk hem</a>',
|
||||||
|
"r1": "åk hem",
|
||||||
|
".s1": "skanna om",
|
||||||
|
"t1": "åtgärd",
|
||||||
|
"u2": "tid sedan senaste serverskrivning$N( uppladdning / namnbyte / ... )$N$N17d = 17 dagar$N1h23 = 1 timme 23 minuter$N4m56 = 4 minuter 56 sekunder",
|
||||||
|
"v1": "koppla upp",
|
||||||
|
"v2": "använd denna server som en lokal disk",
|
||||||
|
"w1": "byt till https",
|
||||||
|
"x1": "byt lösenord",
|
||||||
|
"y1": "redigera utdelningar",
|
||||||
|
"z1": "lås upp denna utdelning:",
|
||||||
|
"ta1": "fyll i ditt nya lösenord",
|
||||||
|
"ta2": "upprepa det nya lösenordet:",
|
||||||
|
"ta3": "det blev fel; vänligen försök igen",
|
||||||
|
"aa1": "inkommande filer:",
|
||||||
|
"ab1": "avaktivera no304",
|
||||||
|
"ac1": "aktivera no304",
|
||||||
|
"ad1": "detta stänger av all cachning; prova detta om k304 inte räckte till. Detta kommer att slösa enorma mängder nätverkstrafik!",
|
||||||
|
"ae1": "aktiva nedladdningar:",
|
||||||
|
"af1": "visa senaste uppladdningar",
|
||||||
|
"ag1": "visa idp-cache"
|
||||||
|
},
|
||||||
"ukr": {
|
"ukr": {
|
||||||
"a1": "оновити",
|
"a1": "оновити",
|
||||||
"b1": "привітик, незнайомцю <small>(ви не авторизовані)</small>",
|
"b1": "привітик, незнайомцю <small>(ви не авторизовані)</small>",
|
||||||
@ -526,6 +681,11 @@ var Ls = {
|
|||||||
"j1": "увімкнення k304 буде відключати ваш клієнт при кожному HTTP 304, що може запобігти зависанню деяких глючних проксі (раптово перестають завантажувати сторінки), <em>але</em> це також зробить усе повільнішим загалом",
|
"j1": "увімкнення k304 буде відключати ваш клієнт при кожному HTTP 304, що може запобігти зависанню деяких глючних проксі (раптово перестають завантажувати сторінки), <em>але</em> це також зробить усе повільнішим загалом",
|
||||||
"k1": "скинути налаштування клієнта",
|
"k1": "скинути налаштування клієнта",
|
||||||
"l1": "авторизуйтесь для інших опцій:",
|
"l1": "авторизуйтесь для інших опцій:",
|
||||||
|
"ls3": "увійти", //m
|
||||||
|
"lu4": "ім'я користувача", //m
|
||||||
|
"lp4": "пароль", //m
|
||||||
|
"lo3": "вийти з облікового запису “{0}” всюди", //m
|
||||||
|
"lo2": "це завершить сеанс у всіх браузерах", //m
|
||||||
"m1": "з поверненням,",
|
"m1": "з поверненням,",
|
||||||
"n1": "404 не знайдено ┐( ´ -`)┌",
|
"n1": "404 не знайдено ┐( ´ -`)┌",
|
||||||
"o1": 'або у вас немає доступу -- спробуйте авторизуватися або <a href="' + SR + '/?h">повернутися на головну</a>',
|
"o1": 'або у вас немає доступу -- спробуйте авторизуватися або <a href="' + SR + '/?h">повернутися на головну</a>',
|
||||||
@ -568,6 +728,11 @@ var Ls = {
|
|||||||
"j1": "включённый k304 будет отключать вас при получении HTTP 304, что может помочь при работе с некоторыми глючными прокси (перестают загружаться страницы), <em>но</em> это также сделает работу клиента медленнее",
|
"j1": "включённый k304 будет отключать вас при получении HTTP 304, что может помочь при работе с некоторыми глючными прокси (перестают загружаться страницы), <em>но</em> это также сделает работу клиента медленнее",
|
||||||
"k1": "сбросить локальные настройки",
|
"k1": "сбросить локальные настройки",
|
||||||
"l1": "авторизуйтесь для других опций:",
|
"l1": "авторизуйтесь для других опций:",
|
||||||
|
"ls3": "войти", //m
|
||||||
|
"lu4": "имя пользователя", //m
|
||||||
|
"lp4": "пароль", //m
|
||||||
|
"lo3": "выйти из “{0}” везде", //m
|
||||||
|
"lo2": "это завершит сеанс во всех браузерах", //m
|
||||||
"m1": "с возвращением,",
|
"m1": "с возвращением,",
|
||||||
"n1": "404 не найдено ┐( ´ -`)┌",
|
"n1": "404 не найдено ┐( ´ -`)┌",
|
||||||
"o1": 'или у вас нет доступа -- попробуйте авторизоваться или <a href="' + SR + '/?h">вернуться на главную</a>',
|
"o1": 'или у вас нет доступа -- попробуйте авторизоваться или <a href="' + SR + '/?h">вернуться на главную</a>',
|
||||||
@ -612,7 +777,14 @@ for (var k in (d || {})) {
|
|||||||
o[a].innerHTML = d[k];
|
o[a].innerHTML = d[k];
|
||||||
else if (f == 2)
|
else if (f == 2)
|
||||||
o[a].setAttribute("tt", d[k]);
|
o[a].setAttribute("tt", d[k]);
|
||||||
|
else if (f == 3)
|
||||||
|
o[a].setAttribute("value", d[k]);
|
||||||
|
else if (f == 4)
|
||||||
|
o[a].setAttribute("placeholder", " " + d[k]);
|
||||||
}
|
}
|
||||||
|
var o1 = ebi('lo'), o2 = ebi('un');
|
||||||
|
if (o1 && o2 && d.lo3)
|
||||||
|
o1.setAttribute("value", d.lo3.format(o2.textContent));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (is_idp) {
|
if (is_idp) {
|
||||||
|
@ -2831,7 +2831,7 @@ function up2k_init(subtle) {
|
|||||||
if (!t.t_uploading)
|
if (!t.t_uploading)
|
||||||
t.t_uploading = Date.now();
|
t.t_uploading = Date.now();
|
||||||
|
|
||||||
pvis.seth(t.n, 1, "🚀 send");
|
pvis.seth(t.n, 1, "🚀 " + L.ul_send);
|
||||||
|
|
||||||
var chunksize = get_chunksize(t.size),
|
var chunksize = get_chunksize(t.size),
|
||||||
car = pcar * chunksize,
|
car = pcar * chunksize,
|
||||||
|
@ -1083,7 +1083,7 @@
|
|||||||
th-x3: n # default
|
th-x3: n # default
|
||||||
|
|
||||||
# image decoders, in order of preference
|
# image decoders, in order of preference
|
||||||
th-dec: vips,pil,ff # default
|
th-dec: vips,pil,raw,ff # default
|
||||||
|
|
||||||
# disable jpg output
|
# disable jpg output
|
||||||
th-no-jpg
|
th-no-jpg
|
||||||
@ -1115,6 +1115,9 @@
|
|||||||
# image formats to decode using pyvips
|
# image formats to decode using pyvips
|
||||||
th-r-vips: a,very,long,list,of,file,extensions # hint
|
th-r-vips: a,very,long,list,of,file,extensions # hint
|
||||||
|
|
||||||
|
# image formats to decode using rawpy
|
||||||
|
th-r-raw: a,very,long,list,of,file,extensions # hint
|
||||||
|
|
||||||
# image formats to decode using ffmpeg
|
# image formats to decode using ffmpeg
|
||||||
th-r-ffi: a,very,long,list,of,file,extensions # hint
|
th-r-ffi: a,very,long,list,of,file,extensions # hint
|
||||||
|
|
||||||
|
@ -354,7 +354,7 @@ pip install mutagen # audio metadata
|
|||||||
pip install pyftpdlib # ftp server
|
pip install pyftpdlib # ftp server
|
||||||
pip install partftpy # tftp server
|
pip install partftpy # tftp server
|
||||||
pip install impacket # smb server -- disable Windows Defender if you REALLY need this on windows
|
pip install impacket # smb server -- disable Windows Defender if you REALLY need this on windows
|
||||||
pip install Pillow pyheif-pillow-opener # thumbnails
|
pip install Pillow pillow-heif # thumbnails
|
||||||
pip install pyvips # faster thumbnails
|
pip install pyvips # faster thumbnails
|
||||||
pip install psutil # better cleanup of stuck metadata parsers on windows
|
pip install psutil # better cleanup of stuck metadata parsers on windows
|
||||||
pip install black==21.12b0 click==8.0.2 bandit pylint flake8 isort mypy # vscode tooling
|
pip install black==21.12b0 click==8.0.2 bandit pylint flake8 isort mypy # vscode tooling
|
||||||
|
66
scripts/make-rpm.sh
Executable file
66
scripts/make-rpm.sh
Executable file
@ -0,0 +1,66 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
#--localbuild to build webdeps and tar locally; otherwise just download prebuilt
|
||||||
|
#--pm change packagemanager; otherwise default to dnf
|
||||||
|
|
||||||
|
while [ ! -z "$1" ]; do
|
||||||
|
case $1 in
|
||||||
|
local-build) local_build=1 ; ;;
|
||||||
|
pm) shift;packagemanager="$1"; ;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
[ -e copyparty/__main__.py ] || cd ..
|
||||||
|
[ -e copyparty/__main__.py ] ||
|
||||||
|
{
|
||||||
|
echo "run me from within the project root folder"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
packagemanager=${packagemanager:-dnf}
|
||||||
|
ver=$(awk '/^VERSION/{gsub(/[^0-9]/," ");printf "%d.%d.%d\n",$1,$2,$3}' copyparty/__version__.py)
|
||||||
|
releasedir="dist/temp_copyparty_$ver"
|
||||||
|
sourcepkg="copyparty-$ver.tar.gz"
|
||||||
|
|
||||||
|
#make temporary directory to build rpm in
|
||||||
|
mkdir -p $releasedir/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
|
||||||
|
trap "rm -rf $releasedir" EXIT
|
||||||
|
|
||||||
|
# make/get tarball
|
||||||
|
if [ $local_build ]; then
|
||||||
|
if [ ! -f "copyparty/web/deps/mini-fa.woff" ]; then
|
||||||
|
sudo $packagemanager update
|
||||||
|
sudo $packagemanager install podman-docker docker
|
||||||
|
make -C deps-docker
|
||||||
|
fi
|
||||||
|
if [ ! -f "dist/$sourcepkg" ]; then
|
||||||
|
./$cppdir/scripts/make-sfx.sh gz fast # pulls some build-deps + good smoketest
|
||||||
|
./$cppdir/scripts/make-tgz-release.sh "$ver"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ ! -f "dist/$sourcepkg" ]; then
|
||||||
|
curl -OL https://github.com/9001/copyparty/releases/download/v$ver/$sourcepkg --output-dir dist
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
cp dist/$sourcepkg "$releasedir/SOURCES/$sourcepkg"
|
||||||
|
|
||||||
|
cp "contrib/package/rpm/copyparty.spec" "$releasedir/SPECS/"
|
||||||
|
sed -i "s/\$pkgver/$ver/g" "$releasedir/SPECS/copyparty.spec"
|
||||||
|
sed -i "s/\$pkgrel/1/g" "$releasedir/SPECS/copyparty.spec"
|
||||||
|
|
||||||
|
sudo $packagemanager update
|
||||||
|
sudo $packagemanager install \
|
||||||
|
rpmdevtools python-devel pyproject-rpm-macros \
|
||||||
|
python-wheel python-setuptools python-jinja2 \
|
||||||
|
make pigz
|
||||||
|
cd "$releasedir/"
|
||||||
|
rpmbuild --define "_topdir `pwd`" -bb SPECS/copyparty.spec
|
||||||
|
cd -
|
||||||
|
|
||||||
|
rpm="copyparty-$ver-1.noarch.rpm"
|
||||||
|
mv "$releasedir/RPMS/noarch/$rpm" dist/$rpm
|
@ -143,7 +143,7 @@ class Cfg(Namespace):
|
|||||||
def __init__(self, a=None, v=None, c=None, **ka0):
|
def __init__(self, a=None, v=None, c=None, **ka0):
|
||||||
ka = {}
|
ka = {}
|
||||||
|
|
||||||
ex = "allow_flac allow_wav chpw cookie_lax daw dav_auth dav_mac dav_rt e2d e2ds e2dsa e2t e2ts e2tsr e2v e2vu e2vp early_ban ed emp exp force_js getmod grid gsel hardlink hardlink_only ih ihead localtime magic nid nih no_acode no_athumb no_bauth no_clone no_cp no_dav no_db_ip no_del no_dirsz no_dupe no_fnugg no_lifetime no_logues no_mv no_pipe no_poll no_readme no_robots no_sb_md no_sb_lg no_scandir no_tail no_tarcmp no_thumb no_vthumb no_zip nrand nsort nw og og_no_head og_s_title ohead q rand re_dirsz reflink rmagic rss smb srch_dbg srch_excl stats uqe usernames vague_403 vc ver wo_up_readme write_uplog xdev xlink xvol zipmaxu zs"
|
ex = "allow_flac allow_wav chpw cookie_lax daw dav_auth dav_mac dav_rt e2d e2ds e2dsa e2t e2ts e2tsr e2v e2vu e2vp early_ban ed emp exp force_js getmod grid gsel hardlink hardlink_only ih ihead localtime magic nid nih no_acode no_athumb no_bauth no_clone no_cp no_dav no_db_ip no_del no_dirsz no_dupe no_fnugg no_lifetime no_logues no_mv no_pipe no_poll no_readme no_robots no_sb_md no_sb_lg no_scandir no_tail no_tarcmp no_thumb no_vthumb no_u2abrt no_zip nrand nsort nw og og_no_head og_s_title ohead q rand re_dirsz reflink rmagic rss smb srch_dbg srch_excl stats uqe usernames vague_403 vc ver wo_up_readme write_uplog xdev xlink xvol zipmaxu zs"
|
||||||
ka.update(**{k: False for k in ex.split()})
|
ka.update(**{k: False for k in ex.split()})
|
||||||
|
|
||||||
ex = "dav_inf dedup dotpart dotsrch hook_v no_dhash no_fastboot no_fpool no_htp no_rescan no_sendfile no_ses no_snap no_up_list no_voldump re_dhash see_dots plain_ip"
|
ex = "dav_inf dedup dotpart dotsrch hook_v no_dhash no_fastboot no_fpool no_htp no_rescan no_sendfile no_ses no_snap no_up_list no_voldump re_dhash see_dots plain_ip"
|
||||||
@ -158,10 +158,10 @@ class Cfg(Namespace):
|
|||||||
ex = "hash_mt hsortn qdel safe_dedup srch_time tail_fd tail_rate u2abort u2j u2sz"
|
ex = "hash_mt hsortn qdel safe_dedup srch_time tail_fd tail_rate u2abort u2j u2sz"
|
||||||
ka.update(**{k: 1 for k in ex.split()})
|
ka.update(**{k: 1 for k in ex.split()})
|
||||||
|
|
||||||
ex = "au_vol dl_list mtab_age reg_cap s_thead s_tbody tail_tmax tail_who th_convt ups_who zip_who"
|
ex = "ac_convt au_vol dl_list mtab_age reg_cap s_thead s_tbody tail_tmax tail_who th_convt ups_who 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 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 idp_cookie idp_store k304 loris no304 nosubtle qr_pin 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 chmod_f chpw_db doctitle df exit favico idp_h_usr ipa html_head lg_sba lg_sbf log_fk md_sba md_sbf name og_desc og_site og_th og_title og_title_a og_title_v og_title_i shr tcolor textfiles txt_eol unlist vname xff_src zipmaxt R RS SR"
|
ex = "ah_alg bname chmod_f chpw_db doctitle df exit favico idp_h_usr ipa html_head lg_sba lg_sbf log_fk md_sba md_sbf name og_desc og_site og_th og_title og_title_a og_title_v og_title_i shr tcolor textfiles txt_eol unlist vname xff_src zipmaxt R RS SR"
|
||||||
@ -185,9 +185,12 @@ class Cfg(Namespace):
|
|||||||
E=E,
|
E=E,
|
||||||
bup_ck="sha512",
|
bup_ck="sha512",
|
||||||
chmod_d="755",
|
chmod_d="755",
|
||||||
|
cookie_cmax=8192,
|
||||||
|
cookie_nmax=50,
|
||||||
dbd="wal",
|
dbd="wal",
|
||||||
dk_salt="b" * 16,
|
dk_salt="b" * 16,
|
||||||
fk_salt="a" * 16,
|
fk_salt="a" * 16,
|
||||||
|
grp_all="acct",
|
||||||
idp_gsep=re.compile("[|:;+,]"),
|
idp_gsep=re.compile("[|:;+,]"),
|
||||||
iobuf=256 * 1024,
|
iobuf=256 * 1024,
|
||||||
lang="eng",
|
lang="eng",
|
||||||
|
Loading…
Reference in New Issue
Block a user