From 35ca24adb886721fc9d5e1a68cfc577e2c5f0230 Mon Sep 17 00:00:00 2001 From: jagadam97 Date: Sat, 12 Jul 2025 11:38:30 +0530 Subject: [PATCH 001/240] build: improve docker image and binary sizes --- .github/workflows/main.yaml | 2 ++ .goreleaser.yml | 11 +++++++++++ Dockerfile | 2 +- Dockerfile.s6 | 2 +- docker/common/healthcheck.sh | 2 +- 5 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index ee01149a..0b053ffd 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -85,6 +85,8 @@ jobs: node-version: "22.x" cache: "pnpm" cache-dependency-path: "frontend/pnpm-lock.yaml" + - name: Install upx + run: sudo apt-get install -y upx - name: Set up QEMU uses: docker/setup-qemu-action@v1 - name: Set up Docker Buildx diff --git a/.goreleaser.yml b/.goreleaser.yml index 57b7b44a..e59ef7f9 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -40,6 +40,17 @@ archives: - goos: windows formats: ["zip"] +upx: + - enabled: true + goos: + - linux + - darwin + goarch: + - amd64 + - arm64 + compress: "best" + lzma: true + dockers: # Alpine docker images - dockerfile: Dockerfile diff --git a/Dockerfile b/Dockerfile index 0e64f120..eb5751e8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM alpine:3.22 RUN apk update && \ - apk --no-cache add ca-certificates mailcap curl jq tini + apk --no-cache add ca-certificates mailcap jq tini # Make user and create necessary directories ENV UID=1000 diff --git a/Dockerfile.s6 b/Dockerfile.s6 index cb34cbd1..7e281ad7 100644 --- a/Dockerfile.s6 +++ b/Dockerfile.s6 @@ -1,7 +1,7 @@ FROM ghcr.io/linuxserver/baseimage-alpine:3.22 RUN apk update && \ - apk --no-cache add ca-certificates mailcap curl jq + apk --no-cache add ca-certificates mailcap jq # Make user and create necessary directories RUN mkdir -p /config /database /srv && \ diff --git a/docker/common/healthcheck.sh b/docker/common/healthcheck.sh index e0ab1e65..3984adb6 100755 --- a/docker/common/healthcheck.sh +++ b/docker/common/healthcheck.sh @@ -6,4 +6,4 @@ PORT=${FB_PORT:-$(jq -r .port /config/settings.json)} ADDRESS=${FB_ADDRESS:-$(jq -r .address /config/settings.json)} ADDRESS=${ADDRESS:-localhost} -curl -f http://$ADDRESS:$PORT/health || exit 1 +wget -q --spider http://$ADDRESS:$PORT/health || exit 1 From 01c814cf98f81f2bcd622aea75e5b1efe3484940 Mon Sep 17 00:00:00 2001 From: outlook84 <96007761+outlook84@users.noreply.github.com> Date: Sat, 12 Jul 2025 19:30:36 +0800 Subject: [PATCH 002/240] feat: Improve Docker entrypoint and config handling --- Dockerfile | 2 +- docker/alpine/init.sh | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index eb5751e8..68dec799 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,4 +29,4 @@ VOLUME /srv /config /database EXPOSE 80 -ENTRYPOINT [ "tini", "--", "/init.sh", "filebrowser", "--config", "/config/settings.json" ] +ENTRYPOINT [ "tini", "--", "/init.sh" ] diff --git a/docker/alpine/init.sh b/docker/alpine/init.sh index 4dc5908a..ccd04cd4 100755 --- a/docker/alpine/init.sh +++ b/docker/alpine/init.sh @@ -7,4 +7,19 @@ if [ ! -f "/config/settings.json" ]; then cp -a /defaults/settings.json /config/settings.json fi -exec "$@" +# Deal with the case where user does not provide a config argument +has_config_arg=0 +for arg in "$@"; do + case "$arg" in + --config|--config=*|-c|-c=*) + has_config_arg=1 + break + ;; + esac +done + +if [ "$has_config_arg" -eq 0 ]; then + set -- --config=/config/settings.json "$@" +fi + +exec filebrowser "$@" \ No newline at end of file From 7c716862c1bd3cdedd3c02d3a37207293db197ca Mon Sep 17 00:00:00 2001 From: Jagadam Dinesh Reddy Date: Sat, 12 Jul 2025 17:57:08 +0530 Subject: [PATCH 003/240] feat: rewrite the archiver and added support for zstd and brotli (#5283) --- frontend/src/components/prompts/Download.vue | 2 + go.mod | 20 +- go.sum | 266 +++++++++++++++++-- http/raw.go | 105 ++++---- 4 files changed, 317 insertions(+), 76 deletions(-) diff --git a/frontend/src/components/prompts/Download.vue b/frontend/src/components/prompts/Download.vue index 176a9638..85467d8c 100644 --- a/frontend/src/components/prompts/Download.vue +++ b/frontend/src/components/prompts/Download.vue @@ -36,5 +36,7 @@ const formats = { tarxz: "tar.xz", tarlz4: "tar.lz4", tarsz: "tar.sz", + tarbr: "tar.br", + tarzst: "tar.zst", }; diff --git a/go.mod b/go.mod index 90e05b2b..504fadae 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/gorilla/websocket v1.5.3 github.com/maruel/natural v1.1.1 github.com/marusama/semaphore/v2 v2.5.0 - github.com/mholt/archiver/v3 v3.5.1 + github.com/mholt/archives v0.1.3 github.com/mitchellh/go-homedir v1.1.0 github.com/pelletier/go-toml/v2 v2.2.4 github.com/shirou/gopsutil/v3 v3.24.5 @@ -32,11 +32,15 @@ require ( ) require ( - github.com/andybalholm/brotli v1.1.1 // indirect + github.com/STARRY-S/zip v0.2.1 // indirect + github.com/andybalholm/brotli v1.1.2-0.20250424173009-453214e765f3 // indirect github.com/asticode/go-astikit v0.55.0 // indirect github.com/asticode/go-astits v1.13.0 // indirect + github.com/bodgit/plumbing v1.3.0 // indirect + github.com/bodgit/sevenzip v1.6.0 // indirect + github.com/bodgit/windows v1.0.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect + github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect @@ -45,21 +49,27 @@ require ( github.com/go-viper/mapstructure/v2 v2.3.0 // indirect github.com/golang/geo v0.0.0-20250606134707-e8fe6a72b492 // indirect github.com/golang/snappy v1.0.0 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/klauspost/compress v1.18.0 // indirect github.com/klauspost/pgzip v1.2.6 // indirect - github.com/nwaples/rardecode v1.1.3 // indirect + github.com/mikelolasagasti/xz v1.0.1 // indirect + github.com/minio/minlz v1.0.0 // indirect + github.com/nwaples/rardecode/v2 v2.1.0 // indirect github.com/pierrec/lz4/v4 v4.1.22 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/sagikazarmark/locafero v0.9.0 // indirect + github.com/sorairolake/lzip-go v0.3.5 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/cast v1.9.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/ulikunitz/xz v0.5.12 // indirect - github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect go.uber.org/multierr v1.11.0 // indirect + go4.org v0.0.0-20230225012048-214862532bf5 // indirect golang.org/x/net v0.41.0 // indirect golang.org/x/sys v0.33.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect diff --git a/go.sum b/go.sum index 27e66a86..fa589357 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,30 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM= github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/STARRY-S/zip v0.2.1 h1:pWBd4tuSGm3wtpoqRZZ2EAwOmcHK6XFf7bU9qcJXyFg= +github.com/STARRY-S/zip v0.2.1/go.mod h1:xNvshLODWtC4EJ702g7cTYn13G53o1+X9BWnPFpcWV4= github.com/Sereal/Sereal v0.0.0-20190618215532-0b8ac451a863 h1:BRrxwOZBolJN4gIwvZMJY1tzqBvQgpaZiQRuIDD40jM= github.com/Sereal/Sereal v0.0.0-20190618215532-0b8ac451a863/go.mod h1:D0JMgToj/WdxCgd30Kc1UcA9E+WdZoJqeVOuYW7iTBM= -github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= -github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= -github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= +github.com/andybalholm/brotli v1.1.2-0.20250424173009-453214e765f3 h1:8PmGpDEZl9yDpcdEr6Odf23feCxK3LNUNMxjXg41pZQ= +github.com/andybalholm/brotli v1.1.2-0.20250424173009-453214e765f3/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= github.com/asdine/storm/v3 v3.2.1 h1:I5AqhkPK6nBZ/qJXySdI7ot5BlXSZ7qvDY1zAn5ZJac= github.com/asdine/storm/v3 v3.2.1/go.mod h1:LEpXwGt4pIqrE/XcTvCnZHT5MgZCV6Ub9q7yQzOFWr0= github.com/asticode/go-astikit v0.20.0/go.mod h1:h4ly7idim1tNhaVkdVBeXQZEE3L0xblP7fCWbgwipF0= @@ -16,6 +36,17 @@ github.com/asticode/go-astisub v0.34.0/go.mod h1:WTkuSzFB+Bp7wezuSf2Oxulj5A8zu2z github.com/asticode/go-astits v1.8.0/go.mod h1:DkOWmBNQpnr9mv24KfZjq4JawCFX1FCqjLVGvO0DygQ= github.com/asticode/go-astits v1.13.0 h1:XOgkaadfZODnyZRR5Y0/DWkA9vrkLLPLeeOvDwfKZ1c= github.com/asticode/go-astits v1.13.0/go.mod h1:QSHmknZ51pf6KJdHKZHJTLlMegIrhega3LPWz3ND/iI= +github.com/bodgit/plumbing v1.3.0 h1:pf9Itz1JOQgn7vEOE7v7nlEfBykYqvUYioC61TwWCFU= +github.com/bodgit/plumbing v1.3.0/go.mod h1:JOTb4XiRu5xfnmdnDJo6GmSbSbtSyufrsyZFByMtKEs= +github.com/bodgit/sevenzip v1.6.0 h1:a4R0Wu6/P1o1pP/3VV++aEOcyeBxeO/xE2Y9NSTrr6A= +github.com/bodgit/sevenzip v1.6.0/go.mod h1:zOBh9nJUof7tcrlqJFv1koWRrhz3LbDbUNngkuZxLMc= +github.com/bodgit/windows v1.0.1 h1:tF7K6KOluPYygXa3Z2594zxlkbKPAOvqr97etrGNIz4= +github.com/bodgit/windows v1.0.1/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -23,8 +54,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= -github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY= -github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= +github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 h1:2tV76y6Q9BB+NEBasnqvs7e49aEBFI8ejC89PSnWH+4= +github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= github.com/dsoprea/go-exif/v2 v2.0.0-20200321225314-640175a69fe4/go.mod h1:Lm2lMM2zx8p4a34ZemkaUV95AnMl4ZvLbCUbwOvLC2E= github.com/dsoprea/go-exif/v3 v3.0.0-20200717053412-08f1b6708903/go.mod h1:0nsO1ce0mh5czxGeLo4+OCZ/C6Eo6ZlMWsz7rH/Gxv8= @@ -43,6 +74,8 @@ github.com/dsoprea/go-utility/v2 v2.0.0-20221003142440-7a1927d49d9d/go.mod h1:LV github.com/dsoprea/go-utility/v2 v2.0.0-20221003160719-7bc88537c05e/go.mod h1:VZ7cB0pTjm1ADBWhJUOHESu4ZYy9JN+ZPqjfiW09EPU= github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 h1:DilThiXje0z+3UQ5YjYiSRRzVdtamFpvBQXKwMglWqw= github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349/go.mod h1:4GC5sXji84i/p+irqghpPFZBF8tRN/Q7+700G0/DLe8= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= @@ -55,6 +88,8 @@ github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWE github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= @@ -67,30 +102,63 @@ github.com/golang/geo v0.0.0-20200319012246-673a6f80352d/go.mod h1:QZ0nwyI2jOfgR github.com/golang/geo v0.0.0-20210211234256-740aa86cb551/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/geo v0.0.0-20250606134707-e8fe6a72b492 h1:8mHyM6CCmj/DQAhHXJVTgdkg/6hAH71N7qGEF+t4Bzg= github.com/golang/geo v0.0.0-20250606134707-e8fe6a72b492/go.mod h1:Vaw7L5b+xa3Rj4/pRtrQkymn3lSBRB/NAEdbF9YEVLA= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -105,16 +173,18 @@ github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo= github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg= github.com/marusama/semaphore/v2 v2.5.0 h1:o/1QJD9DBYOWRnDhPwDVAXQn6mQYD0gZaS1Tpx6DJGM= github.com/marusama/semaphore/v2 v2.5.0/go.mod h1:z9nMiNUekt/LTpTUQdpp+4sJeYqUGpwMHfW0Z8V8fnQ= -github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo= -github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= +github.com/mholt/archives v0.1.3 h1:aEAaOtNra78G+TvV5ohmXrJOAzf++dIlYeDW3N9q458= +github.com/mholt/archives v0.1.3/go.mod h1:LUCGp++/IbV/I0Xq4SzcIR6uwgeh2yjnQWamjRQfLTU= +github.com/mikelolasagasti/xz v1.0.1 h1:Q2F2jX0RYJUG3+WsM+FJknv+6eVjsjXNDV0KJXZzkD0= +github.com/mikelolasagasti/xz v1.0.1/go.mod h1:muAirjiOUxPRXwm9HdDtB3uoRPrGnL85XHtokL9Hcgc= +github.com/minio/minlz v1.0.0 h1:Kj7aJZ1//LlTP1DM8Jm7lNKvvJS2m74gyyXXn3+uJWQ= +github.com/minio/minlz v1.0.0/go.mod h1:qT0aEB35q79LLornSzeDH75LBf3aH1MV+jB5w9Wasec= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= -github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc= -github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= +github.com/nwaples/rardecode/v2 v2.1.0 h1:JQl9ZoBPDy+nIZGb1mx8+anfHp/LV3NE2MjMiv0ct/U= +github.com/nwaples/rardecode/v2 v2.1.0/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= -github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/profile v1.4.0/go.mod h1:NWz/XGvpEW1FyYQ7fCx4dqYBLlfTcE+A9FLAkNKqjFE= @@ -123,13 +193,18 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= github.com/sagikazarmark/locafero v0.9.0 h1:GbgQGNtTrEmddYDSAH9QLRyfAHY12md+8YFTqyMTC9k= github.com/sagikazarmark/locafero v0.9.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk= github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI= github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk= +github.com/sorairolake/lzip-go v0.3.5 h1:ms5Xri9o1JBIWvOFAorYtUNik6HI3HgBTkISiqu0Cwg= +github.com/sorairolake/lzip-go v0.3.5/go.mod h1:N0KYq5iWrMXI0ZEXKXaS9hCyOjZUQdBDEIbXfoUwbdk= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= @@ -143,8 +218,13 @@ github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= @@ -152,69 +232,210 @@ github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSW github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce h1:fb190+cK2Xz/dvi9Hv8eCYJYvIGUTN2/KLq1pT6CjEc= github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= -github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= -github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.4.1 h1:5mOV+HWjIPLEAlUGMsveaUvK2+byZMFOzojoi7bh7uI= go.etcd.io/bbolt v1.4.1/go.mod h1:c8zu2BnXWTu2XM4XcICtbGSl9cFwsXtcf9zLt2OncM8= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc= +go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.28.0 h1:gdem5JW1OLS4FbkWgLO+7ZeFzYtL3xClb97GaUzYMFE= golang.org/x/image v0.28.0/go.mod h1:GUJYXtnGKEUgggyzh+Vxt+AviiCcyiwpsl8iQ8MvwGY= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191105084925-a882066a44e0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -222,5 +443,14 @@ gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/http/raw.go b/http/raw.go index cd05a1bc..cbddad59 100644 --- a/http/raw.go +++ b/http/raw.go @@ -2,6 +2,7 @@ package http import ( "errors" + "io/fs" "log" "net/http" "net/url" @@ -9,7 +10,7 @@ import ( "path/filepath" "strings" - "github.com/mholt/archiver/v3" + "github.com/mholt/archives" "github.com/filebrowser/filebrowser/v2/files" "github.com/filebrowser/filebrowser/v2/fileutils" @@ -44,22 +45,26 @@ func parseQueryFiles(r *http.Request, f *files.FileInfo, _ *users.User) ([]strin return fileSlice, nil } -func parseQueryAlgorithm(r *http.Request) (string, archiver.Writer, error) { +func parseQueryAlgorithm(r *http.Request) (string, archives.Archival, error) { switch r.URL.Query().Get("algo") { case "zip", "true", "": - return ".zip", archiver.NewZip(), nil + return ".zip", archives.Zip{}, nil case "tar": - return ".tar", archiver.NewTar(), nil + return ".tar", archives.Tar{}, nil case "targz": - return ".tar.gz", archiver.NewTarGz(), nil + return ".tar.gz", archives.CompressedArchive{Compression: archives.Gz{}, Archival: archives.Tar{}}, nil case "tarbz2": - return ".tar.bz2", archiver.NewTarBz2(), nil + return ".tar.bz2", archives.CompressedArchive{Compression: archives.Bz2{}, Archival: archives.Tar{}}, nil case "tarxz": - return ".tar.xz", archiver.NewTarXz(), nil + return ".tar.xz", archives.CompressedArchive{Compression: archives.Xz{}, Archival: archives.Tar{}}, nil case "tarlz4": - return ".tar.lz4", archiver.NewTarLz4(), nil + return ".tar.lz4", archives.CompressedArchive{Compression: archives.Lz4{}, Archival: archives.Tar{}}, nil case "tarsz": - return ".tar.sz", archiver.NewTarSz(), nil + return ".tar.sz", archives.CompressedArchive{Compression: archives.Sz{}, Archival: archives.Tar{}}, nil + case "tarbr": + return ".tar.br", archives.CompressedArchive{Compression: archives.Brotli{}, Archival: archives.Tar{}}, nil + case "tarzst": + return ".tar.zst", archives.CompressedArchive{Compression: archives.Zstd{}, Archival: archives.Tar{}}, nil default: return "", nil, errors.New("format not implemented") } @@ -103,57 +108,55 @@ var rawHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) return rawDirHandler(w, r, d, file) }) -func addFile(ar archiver.Writer, d *data, path, commonPath string) error { +func getFiles(d *data, path, commonPath string) ([]archives.FileInfo, error) { if !d.Check(path) { - return nil + return nil, nil } info, err := d.user.Fs.Stat(path) if err != nil { - return err + return nil, err } - if !info.IsDir() && !info.Mode().IsRegular() { - return nil - } - - file, err := d.user.Fs.Open(path) - if err != nil { - return err - } - defer file.Close() + var archiveFiles []archives.FileInfo if path != commonPath { - filename := strings.TrimPrefix(path, commonPath) - filename = strings.TrimPrefix(filename, string(filepath.Separator)) - err = ar.Write(archiver.File{ - FileInfo: archiver.FileInfo{ - FileInfo: info, - CustomName: filename, + nameInArchive := strings.TrimPrefix(path, commonPath) + nameInArchive = strings.TrimPrefix(nameInArchive, string(filepath.Separator)) + + archiveFiles = append(archiveFiles, archives.FileInfo{ + FileInfo: info, + NameInArchive: nameInArchive, + Open: func() (fs.File, error) { + return d.user.Fs.Open(path) }, - ReadCloser: file, }) - if err != nil { - return err - } } if info.IsDir() { - names, err := file.Readdirnames(0) + f, err := d.user.Fs.Open(path) if err != nil { - return err + return nil, err + } + defer f.Close() + + names, err := f.Readdirnames(0) + if err != nil { + return nil, err } for _, name := range names { fPath := filepath.Join(path, name) - err = addFile(ar, d, fPath, commonPath) + subFiles, err := getFiles(d, fPath, commonPath) if err != nil { - log.Printf("Failed to archive %s: %v", fPath, err) + log.Printf("Failed to get files from %s: %v", fPath, err) + continue } + archiveFiles = append(archiveFiles, subFiles...) } } - return nil + return archiveFiles, nil } func rawDirHandler(w http.ResponseWriter, r *http.Request, d *data, file *files.FileInfo) (int, error) { @@ -162,27 +165,28 @@ func rawDirHandler(w http.ResponseWriter, r *http.Request, d *data, file *files. return http.StatusInternalServerError, err } - extension, ar, err := parseQueryAlgorithm(r) + extension, archiver, err := parseQueryAlgorithm(r) if err != nil { return http.StatusInternalServerError, err } - err = ar.Create(w) - if err != nil { - return http.StatusInternalServerError, err - } - defer ar.Close() - commonDir := fileutils.CommonPrefix(filepath.Separator, filenames...) + var allFiles []archives.FileInfo + for _, fname := range filenames { + archiveFiles, err := getFiles(d, fname, commonDir) + if err != nil { + log.Printf("Failed to get files from %s: %v", fname, err) + continue + } + allFiles = append(allFiles, archiveFiles...) + } + name := filepath.Base(commonDir) if name == "." || name == "" || name == string(filepath.Separator) { - // Not sure when/if this will ever be true, though kept incase there is an edge-case where it is if file.Name != "" { name = file.Name } else { - // This should indicate that the fs root is the directory being downloaded, lookup its name - actual, statErr := file.Fs.Stat(".") if statErr != nil { return http.StatusInternalServerError, statErr @@ -190,19 +194,14 @@ func rawDirHandler(w http.ResponseWriter, r *http.Request, d *data, file *files. name = actual.Name() } } - // Prefix used to distinguish a filelist generated - // archive from the full directory archive if len(filenames) > 1 { name = "_" + name } name += extension w.Header().Set("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(name)) - for _, fname := range filenames { - err = addFile(ar, d, fname, commonDir) - if err != nil { - log.Printf("Failed to archive %s: %v", fname, err) - } + if err := archiver.Archive(r.Context(), w, allFiles); err != nil { + return http.StatusInternalServerError, err } return 0, nil From 0f27c91eca581482ce4f82f6429f5dac12f8b64e Mon Sep 17 00:00:00 2001 From: Ramires Viana <59319979+ramiresviana@users.noreply.github.com> Date: Sun, 13 Jul 2025 03:16:01 -0300 Subject: [PATCH 004/240] fix: drop modify permission for uploading new file (#5270) --- frontend/src/api/tus.ts | 47 ++++----- frontend/src/stores/upload.ts | 23 ++--- frontend/src/types/upload.d.ts | 8 -- go.mod | 2 + go.sum | 2 + http/http.go | 2 +- http/tus_handlers.go | 179 ++++++++++++++++++++++++++++++--- 7 files changed, 197 insertions(+), 66 deletions(-) diff --git a/frontend/src/api/tus.ts b/frontend/src/api/tus.ts index 5e4e116b..64efe69a 100644 --- a/frontend/src/api/tus.ts +++ b/frontend/src/api/tus.ts @@ -3,7 +3,6 @@ import { baseURL, tusEndpoint, tusSettings } from "@/utils/constants"; import { useAuthStore } from "@/stores/auth"; import { useUploadStore } from "@/stores/upload"; import { removePrefix } from "@/api/utils"; -import { fetchURL } from "./utils"; const RETRY_BASE_DELAY = 1000; const RETRY_MAX_DELAY = 20000; @@ -28,8 +27,6 @@ export async function upload( filePath = removePrefix(filePath); const resourcePath = `${tusEndpoint}${filePath}?override=${overwrite}`; - await createUpload(resourcePath); - const authStore = useAuthStore(); // Exit early because of typescript, tus content can't be a string @@ -38,7 +35,7 @@ export async function upload( } return new Promise((resolve, reject) => { const upload = new tus.Upload(content, { - uploadUrl: `${baseURL}${resourcePath}`, + endpoint: `${baseURL}${resourcePath}`, chunkSize: tusSettings.chunkSize, retryDelays: computeRetryDelays(tusSettings), parallelUploads: 1, @@ -46,6 +43,18 @@ export async function upload( headers: { "X-Auth": authStore.jwt, }, + onShouldRetry: function (err) { + const status = err.originalResponse + ? err.originalResponse.getStatus() + : 0; + + // Do not retry for file conflict. + if (status === 409) { + return false; + } + + return true; + }, onError: function (error) { if (CURRENT_UPLOAD_LIST[filePath].interval) { clearInterval(CURRENT_UPLOAD_LIST[filePath].interval); @@ -92,17 +101,6 @@ export async function upload( }); } -async function createUpload(resourcePath: string) { - const headResp = await fetchURL(resourcePath, { - method: "POST", - }); - if (headResp.status !== 201) { - throw new Error( - `Failed to create an upload: ${headResp.status} ${headResp.statusText}` - ); - } -} - function computeRetryDelays(tusSettings: TusSettings): number[] | undefined { if (!tusSettings.retryCount || tusSettings.retryCount < 1) { // Disable retries altogether @@ -130,7 +128,8 @@ function isTusSupported() { return tus.isSupported === true; } -function computeETA(state: ETAState, speed?: number) { +function computeETA(speed?: number) { + const state = useUploadStore(); if (state.speedMbyte === 0) { return Infinity; } @@ -138,22 +137,13 @@ function computeETA(state: ETAState, speed?: number) { (acc: number, size: number) => acc + size, 0 ); - const uploadedSize = state.progress.reduce( - (acc: number, progress: Progress) => { - if (typeof progress === "number") { - return acc + progress; - } - return acc; - }, - 0 - ); + const uploadedSize = state.progress.reduce((a, b) => a + b, 0); const remainingSize = totalSize - uploadedSize; const speedBytesPerSecond = (speed ?? state.speedMbyte) * 1024 * 1024; return remainingSize / speedBytesPerSecond; } function computeGlobalSpeedAndETA() { - const uploadStore = useUploadStore(); let totalSpeed = 0; let totalCount = 0; @@ -165,7 +155,7 @@ function computeGlobalSpeedAndETA() { if (totalCount === 0) return { speed: 0, eta: Infinity }; const averageSpeed = totalSpeed / totalCount; - const averageETA = computeETA(uploadStore, averageSpeed); + const averageETA = computeETA(averageSpeed); return { speed: averageSpeed, eta: averageETA }; } @@ -207,6 +197,9 @@ export function abortAllUploads() { } if (CURRENT_UPLOAD_LIST[filePath].upload) { CURRENT_UPLOAD_LIST[filePath].upload.abort(true); + CURRENT_UPLOAD_LIST[filePath].upload.options!.onError!( + new Error("Upload aborted") + ); } delete CURRENT_UPLOAD_LIST[filePath]; } diff --git a/frontend/src/stores/upload.ts b/frontend/src/stores/upload.ts index d9698255..8429146e 100644 --- a/frontend/src/stores/upload.ts +++ b/frontend/src/stores/upload.ts @@ -30,7 +30,7 @@ export const useUploadStore = defineStore("upload", { state: (): { id: number; sizes: number[]; - progress: Progress[]; + progress: number[]; queue: UploadItem[]; uploads: Uploads; speedMbyte: number; @@ -54,9 +54,7 @@ export const useUploadStore = defineStore("upload", { } const totalSize = state.sizes.reduce((a, b) => a + b, 0); - - // TODO: this looks ugly but it works with ts now - const sum = state.progress.reduce((acc, val) => +acc + +val) as number; + const sum = state.progress.reduce((a, b) => a + b, 0); return Math.ceil((sum / totalSize) * 100); }, getProgressDecimal: (state) => { @@ -65,21 +63,14 @@ export const useUploadStore = defineStore("upload", { } const totalSize = state.sizes.reduce((a, b) => a + b, 0); - - // TODO: this looks ugly but it works with ts now - const sum = state.progress.reduce((acc, val) => +acc + +val) as number; + const sum = state.progress.reduce((a, b) => a + b, 0); return ((sum / totalSize) * 100).toFixed(2); }, getTotalProgressBytes: (state) => { if (state.progress.length === 0 || state.sizes.length === 0) { return "0 Bytes"; } - const sum = state.progress.reduce( - (sum, p, i) => - (sum as number) + - (typeof p === "number" ? p : p ? state.sizes[i] : 0), - 0 - ) as number; + const sum = state.progress.reduce((a, b) => a + b, 0); return formatSize(sum); }, getTotalSize: (state) => { @@ -104,7 +95,7 @@ export const useUploadStore = defineStore("upload", { const isDir = upload.file.isDir; const progress = isDir ? 100 - : Math.ceil(((state.progress[id] as number) / size) * 100); + : Math.ceil((state.progress[id] / size) * 100); files.push({ id, @@ -124,7 +115,7 @@ export const useUploadStore = defineStore("upload", { }, actions: { // no context as first argument, use `this` instead - setProgress({ id, loaded }: { id: number; loaded: Progress }) { + setProgress({ id, loaded }: { id: number; loaded: number }) { this.progress[id] = loaded; }, setError(error: Error) { @@ -168,7 +159,7 @@ export const useUploadStore = defineStore("upload", { this.processUploads(); }, finishUpload(item: UploadItem) { - this.setProgress({ id: item.id, loaded: item.file.size > 0 }); + this.setProgress({ id: item.id, loaded: item.file.size }); this.removeJob(item.id); this.processUploads(); }, diff --git a/frontend/src/types/upload.d.ts b/frontend/src/types/upload.d.ts index 263b6bf5..131f4b2c 100644 --- a/frontend/src/types/upload.d.ts +++ b/frontend/src/types/upload.d.ts @@ -28,8 +28,6 @@ interface UploadEntry { type UploadList = UploadEntry[]; -type Progress = number | boolean; - type CurrentUploadList = { [key: string]: { upload: import("tus-js-client").Upload; @@ -43,9 +41,3 @@ type CurrentUploadList = { interval: number | undefined; }; }; - -interface ETAState { - sizes: number[]; - progress: Progress[]; - speedMbyte: number; -} diff --git a/go.mod b/go.mod index 504fadae..09a12662 100644 --- a/go.mod +++ b/go.mod @@ -53,6 +53,7 @@ require ( github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jellydator/ttlcache/v3 v3.4.0 // indirect github.com/klauspost/compress v1.18.0 // indirect github.com/klauspost/pgzip v1.2.6 // indirect github.com/mikelolasagasti/xz v1.0.1 // indirect @@ -71,6 +72,7 @@ require ( go.uber.org/multierr v1.11.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect golang.org/x/net v0.41.0 // indirect + golang.org/x/sync v0.15.0 // indirect golang.org/x/sys v0.33.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index fa589357..8e5e336c 100644 --- a/go.sum +++ b/go.sum @@ -150,6 +150,8 @@ github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyf github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jellydator/ttlcache/v3 v3.4.0 h1:YS4P125qQS0tNhtL6aeYkheEaB/m8HCqdMMP4mnWdTY= +github.com/jellydator/ttlcache/v3 v3.4.0/go.mod h1:Hw9EgjymziQD3yGsQdf1FqFdpp7YjFMd4Srg5EJlgD4= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= diff --git a/http/http.go b/http/http.go index 620c43fd..2d87535f 100644 --- a/http/http.go +++ b/http/http.go @@ -69,7 +69,7 @@ func NewHandler( api.PathPrefix("/tus").Handler(monkey(tusPostHandler(), "/api/tus")).Methods("POST") api.PathPrefix("/tus").Handler(monkey(tusHeadHandler(), "/api/tus")).Methods("HEAD", "GET") api.PathPrefix("/tus").Handler(monkey(tusPatchHandler(), "/api/tus")).Methods("PATCH") - api.PathPrefix("/tus").Handler(monkey(resourceDeleteHandler(fileCache), "/api/tus")).Methods("DELETE") + api.PathPrefix("/tus").Handler(monkey(tusDeleteHandler(), "/api/tus")).Methods("DELETE") api.PathPrefix("/usage").Handler(monkey(diskUsage, "/api/usage")).Methods("GET") diff --git a/http/tus_handlers.go b/http/tus_handlers.go index 7a3254ae..c5eec9ad 100644 --- a/http/tus_handlers.go +++ b/http/tus_handlers.go @@ -1,6 +1,7 @@ package http import ( + "context" "errors" "fmt" "io" @@ -8,14 +9,76 @@ import ( "os" "path/filepath" "strconv" + "time" + "github.com/jellydator/ttlcache/v3" "github.com/spf13/afero" "github.com/filebrowser/filebrowser/v2/files" ) +const maxUploadWait = 3 * time.Minute + +// Tracks active uploads along with their respective upload lengths +var activeUploads = initActiveUploads() + +func initActiveUploads() *ttlcache.Cache[string, int64] { + cache := ttlcache.New[string, int64]() + cache.OnEviction(func(_ context.Context, reason ttlcache.EvictionReason, item *ttlcache.Item[string, int64]) { + if reason == ttlcache.EvictionReasonExpired { + fmt.Printf("deleting incomplete upload file: \"%s\"", item.Key()) + os.Remove(item.Key()) + } + }) + go cache.Start() + + return cache +} + +func registerUpload(filePath string, fileSize int64) { + activeUploads.Set(filePath, fileSize, maxUploadWait) +} + +func completeUpload(filePath string) { + activeUploads.Delete(filePath) +} + +func getActiveUploadLength(filePath string) (int64, error) { + item := activeUploads.Get(filePath) + if item == nil { + return 0, fmt.Errorf("no active upload found for the given path") + } + + return item.Value(), nil +} + +func keepUploadActive(filePath string) func() { + stop := make(chan bool) + + go func() { + ticker := time.NewTicker(2 * time.Second) + defer ticker.Stop() + + for { + select { + case <-stop: + return + case <-ticker.C: + activeUploads.Touch(filePath) + } + } + }() + + return func() { + close(stop) + } +} + func tusPostHandler() handleFunc { - return withUser(func(_ http.ResponseWriter, r *http.Request, d *data) (int, error) { + return withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) { + if !d.user.Perm.Create || !d.Check(r.URL.Path) { + return http.StatusForbidden, nil + } file, err := files.NewFileInfo(&files.FileOptions{ Fs: d.user.Fs, Path: r.URL.Path, @@ -26,10 +89,6 @@ func tusPostHandler() handleFunc { }) switch { case errors.Is(err, afero.ErrFileNotFound): - if !d.user.Perm.Create || !d.Check(r.URL.Path) { - return http.StatusForbidden, nil - } - dirPath := filepath.Dir(r.URL.Path) if _, statErr := d.user.Fs.Stat(dirPath); os.IsNotExist(statErr) { if mkdirErr := d.user.Fs.MkdirAll(dirPath, files.PermDir); mkdirErr != nil { @@ -41,25 +100,55 @@ func tusPostHandler() handleFunc { } fileFlags := os.O_CREATE | os.O_WRONLY - if r.URL.Query().Get("override") == "true" { - fileFlags |= os.O_TRUNC - } // if file exists if file != nil { if file.IsDir { return http.StatusBadRequest, fmt.Errorf("cannot upload to a directory %s", file.RealPath()) } + + // Existing files will remain untouched unless explicitly instructed to override + if r.URL.Query().Get("override") != "true" { + return http.StatusConflict, nil + } + + // Permission for overwriting the file + if !d.user.Perm.Modify { + return http.StatusForbidden, nil + } + + fileFlags |= os.O_TRUNC } openFile, err := d.user.Fs.OpenFile(r.URL.Path, fileFlags, files.PermFile) if err != nil { return errToStatus(err), err } - if err := openFile.Close(); err != nil { + defer openFile.Close() + + file, err = files.NewFileInfo(&files.FileOptions{ + Fs: d.user.Fs, + Path: r.URL.Path, + Modify: d.user.Perm.Modify, + Expand: false, + ReadHeader: false, + Checker: d, + Content: false, + }) + if err != nil { return errToStatus(err), err } + uploadLength, err := getUploadLength(r) + if err != nil { + return http.StatusBadRequest, fmt.Errorf("invalid upload length: %w", err) + } + + // Enables the user to utilize the PATCH endpoint for uploading file data + registerUpload(file.RealPath(), uploadLength) + + w.Header().Set("Location", "/api/tus/"+r.URL.Path) + return http.StatusCreated, nil }) } @@ -67,7 +156,7 @@ func tusPostHandler() handleFunc { func tusHeadHandler() handleFunc { return withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) { w.Header().Set("Cache-Control", "no-store") - if !d.Check(r.URL.Path) { + if !d.user.Perm.Create || !d.Check(r.URL.Path) { return http.StatusForbidden, nil } @@ -83,8 +172,13 @@ func tusHeadHandler() handleFunc { return errToStatus(err), err } + uploadLength, err := getActiveUploadLength(file.RealPath()) + if err != nil { + return http.StatusNotFound, err + } + w.Header().Set("Upload-Offset", strconv.FormatInt(file.Size, 10)) - w.Header().Set("Upload-Length", "-1") + w.Header().Set("Upload-Length", strconv.FormatInt(uploadLength, 10)) return http.StatusOK, nil }) @@ -92,7 +186,7 @@ func tusHeadHandler() handleFunc { func tusPatchHandler() handleFunc { return withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) { - if !d.user.Perm.Modify || !d.Check(r.URL.Path) { + if !d.user.Perm.Create || !d.Check(r.URL.Path) { return http.StatusForbidden, nil } if r.Header.Get("Content-Type") != "application/offset+octet-stream" { @@ -101,7 +195,7 @@ func tusPatchHandler() handleFunc { uploadOffset, err := getUploadOffset(r) if err != nil { - return http.StatusBadRequest, fmt.Errorf("invalid upload offset: %w", err) + return http.StatusBadRequest, fmt.Errorf("invalid upload offset") } file, err := files.NewFileInfo(&files.FileOptions{ @@ -120,6 +214,15 @@ func tusPatchHandler() handleFunc { return errToStatus(err), err } + uploadLength, err := getActiveUploadLength(file.RealPath()) + if err != nil { + return http.StatusNotFound, err + } + + // Prevent the upload from being evicted during the transfer + stop := keepUploadActive(file.RealPath()) + defer stop() + switch { case file.IsDir: return http.StatusBadRequest, fmt.Errorf("cannot upload to a directory %s", file.RealPath()) @@ -148,12 +251,60 @@ func tusPatchHandler() handleFunc { return http.StatusInternalServerError, fmt.Errorf("could not write to file: %w", err) } - w.Header().Set("Upload-Offset", strconv.FormatInt(uploadOffset+bytesWritten, 10)) + newOffset := uploadOffset + bytesWritten + w.Header().Set("Upload-Offset", strconv.FormatInt(newOffset, 10)) + + if newOffset >= uploadLength { + completeUpload(file.RealPath()) + _ = d.RunHook(func() error { return nil }, "upload", r.URL.Path, "", d.user) + } return http.StatusNoContent, nil }) } +func tusDeleteHandler() handleFunc { + return withUser(func(_ http.ResponseWriter, r *http.Request, d *data) (int, error) { + if r.URL.Path == "/" || !d.user.Perm.Create { + return http.StatusForbidden, nil + } + + file, err := files.NewFileInfo(&files.FileOptions{ + Fs: d.user.Fs, + Path: r.URL.Path, + Modify: d.user.Perm.Modify, + Expand: false, + ReadHeader: d.server.TypeDetectionByHeader, + Checker: d, + }) + if err != nil { + return errToStatus(err), err + } + + _, err = getActiveUploadLength(file.RealPath()) + if err != nil { + return http.StatusNotFound, err + } + + err = d.user.Fs.RemoveAll(r.URL.Path) + if err != nil { + return errToStatus(err), err + } + + completeUpload(file.RealPath()) + + return http.StatusNoContent, nil + }) +} + +func getUploadLength(r *http.Request) (int64, error) { + uploadOffset, err := strconv.ParseInt(r.Header.Get("Upload-Length"), 10, 64) + if err != nil { + return 0, fmt.Errorf("invalid upload length: %w", err) + } + return uploadOffset, nil +} + func getUploadOffset(r *http.Request) (int64, error) { uploadOffset, err := strconv.ParseInt(r.Header.Get("Upload-Offset"), 10, 64) if err != nil { From 5a8e7171b1b41eff771fe27133c91d2c250896a8 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Sun, 13 Jul 2025 08:18:06 +0200 Subject: [PATCH 005/240] fix: Settings button in the sidebar --- frontend/src/components/Sidebar.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/Sidebar.vue b/frontend/src/components/Sidebar.vue index 93cda311..74fb45ad 100644 --- a/frontend/src/components/Sidebar.vue +++ b/frontend/src/components/Sidebar.vue @@ -41,7 +41,7 @@
@@ -81,6 +88,7 @@ import { useAuthStore } from "@/stores/auth"; import { useLayoutStore } from "@/stores/layout"; import { users as api } from "@/api"; +import AceEditorTheme from "@/components/settings/AceEditorTheme.vue"; import Languages from "@/components/settings/Languages.vue"; import { computed, inject, onMounted, ref } from "vue"; import { useI18n } from "vue-i18n"; @@ -98,6 +106,7 @@ const hideDotfiles = ref(false); const singleClick = ref(false); const dateFormat = ref(false); const locale = ref(""); +const aceEditorTheme = ref(""); const passwordClass = computed(() => { const baseClass = "input input--block"; @@ -113,13 +122,14 @@ const passwordClass = computed(() => { return `${baseClass} input--red`; }); -onMounted(() => { +onMounted(async () => { layoutStore.loading = true; if (authStore.user === null) return false; locale.value = authStore.user.locale; hideDotfiles.value = authStore.user.hideDotfiles; singleClick.value = authStore.user.singleClick; dateFormat.value = authStore.user.dateFormat; + aceEditorTheme.value = authStore.user.aceEditorTheme; layoutStore.loading = false; return true; }); @@ -163,6 +173,7 @@ const updateSettings = async (event: Event) => { hideDotfiles: hideDotfiles.value, singleClick: singleClick.value, dateFormat: dateFormat.value, + aceEditorTheme: aceEditorTheme.value, }; await api.update(data, [ @@ -170,6 +181,7 @@ const updateSettings = async (event: Event) => { "hideDotfiles", "singleClick", "dateFormat", + "aceEditorTheme", ]); authStore.updateUser(data); $showSuccess(t("settings.settingsUpdated")); diff --git a/http/auth.go b/http/auth.go index 0ecaed14..62d6779e 100644 --- a/http/auth.go +++ b/http/auth.go @@ -31,6 +31,7 @@ type userInfo struct { HideDotfiles bool `json:"hideDotfiles"` DateFormat bool `json:"dateFormat"` Username string `json:"username"` + AceEditorTheme string `json:"aceEditorTheme"` } type authToken struct { @@ -200,6 +201,7 @@ func printToken(w http.ResponseWriter, _ *http.Request, d *data, user *users.Use HideDotfiles: user.HideDotfiles, DateFormat: user.DateFormat, Username: user.Username, + AceEditorTheme: user.AceEditorTheme, }, RegisteredClaims: jwt.RegisteredClaims{ IssuedAt: jwt.NewNumericDate(time.Now()), diff --git a/settings/defaults.go b/settings/defaults.go index d60e36dc..5b6c3f2a 100644 --- a/settings/defaults.go +++ b/settings/defaults.go @@ -8,15 +8,16 @@ import ( // UserDefaults is a type that holds the default values // for some fields on User. type UserDefaults struct { - Scope string `json:"scope"` - Locale string `json:"locale"` - ViewMode users.ViewMode `json:"viewMode"` - SingleClick bool `json:"singleClick"` - Sorting files.Sorting `json:"sorting"` - Perm users.Permissions `json:"perm"` - Commands []string `json:"commands"` - HideDotfiles bool `json:"hideDotfiles"` - DateFormat bool `json:"dateFormat"` + Scope string `json:"scope"` + Locale string `json:"locale"` + ViewMode users.ViewMode `json:"viewMode"` + SingleClick bool `json:"singleClick"` + Sorting files.Sorting `json:"sorting"` + Perm users.Permissions `json:"perm"` + Commands []string `json:"commands"` + HideDotfiles bool `json:"hideDotfiles"` + DateFormat bool `json:"dateFormat"` + AceEditorTheme string `json:"aceEditorTheme"` } // Apply applies the default options to a user. @@ -30,4 +31,5 @@ func (d *UserDefaults) Apply(u *users.User) { u.Commands = d.Commands u.HideDotfiles = d.HideDotfiles u.DateFormat = d.DateFormat + u.AceEditorTheme = d.AceEditorTheme } diff --git a/tools/package.json b/tools/package.json index 9a2bd1c6..9433b94e 100644 --- a/tools/package.json +++ b/tools/package.json @@ -3,5 +3,6 @@ "@commitlint/cli": "^15.0.0", "@commitlint/config-conventional": "^15.0.0", "standard-version": "^9.3.2" - } + }, + "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" } diff --git a/users/users.go b/users/users.go index e0310f21..020faf11 100644 --- a/users/users.go +++ b/users/users.go @@ -20,21 +20,22 @@ const ( // User describes a user. type User struct { - ID uint `storm:"id,increment" json:"id"` - Username string `storm:"unique" json:"username"` - Password string `json:"password"` - Scope string `json:"scope"` - Locale string `json:"locale"` - LockPassword bool `json:"lockPassword"` - ViewMode ViewMode `json:"viewMode"` - SingleClick bool `json:"singleClick"` - Perm Permissions `json:"perm"` - Commands []string `json:"commands"` - Sorting files.Sorting `json:"sorting"` - Fs afero.Fs `json:"-" yaml:"-"` - Rules []rules.Rule `json:"rules"` - HideDotfiles bool `json:"hideDotfiles"` - DateFormat bool `json:"dateFormat"` + ID uint `storm:"id,increment" json:"id"` + Username string `storm:"unique" json:"username"` + Password string `json:"password"` + Scope string `json:"scope"` + Locale string `json:"locale"` + LockPassword bool `json:"lockPassword"` + ViewMode ViewMode `json:"viewMode"` + SingleClick bool `json:"singleClick"` + Perm Permissions `json:"perm"` + Commands []string `json:"commands"` + Sorting files.Sorting `json:"sorting"` + Fs afero.Fs `json:"-" yaml:"-"` + Rules []rules.Rule `json:"rules"` + HideDotfiles bool `json:"hideDotfiles"` + DateFormat bool `json:"dateFormat"` + AceEditorTheme string `json:"aceEditorTheme"` } // GetRules implements rules.Provider. From 692ca5eaf01e4dcf346ba03f82c5dbd50cce246b Mon Sep 17 00:00:00 2001 From: MSomnium Studios <70982507+ArielLeyva@users.noreply.github.com> Date: Thu, 25 Sep 2025 10:54:28 -0400 Subject: [PATCH 066/240] fix(upload): throttle upload speed calculation to 100ms to avoid Infinity MB/s (#5456) Co-authored-by: Henrique Dias --- .../src/components/prompts/UploadFiles.vue | 29 ++++++++++++-- http/auth.go | 40 +++++++++---------- 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/frontend/src/components/prompts/UploadFiles.vue b/frontend/src/components/prompts/UploadFiles.vue index 883fffe3..4d96d5bb 100644 --- a/frontend/src/components/prompts/UploadFiles.vue +++ b/frontend/src/components/prompts/UploadFiles.vue @@ -14,7 +14,7 @@ }}
-
{{ speedMbytes }}/s
+
{{ speedText }}/s
{{ formattedETA }} remaining
{{ sentPercent }}% Completed
@@ -88,6 +88,7 @@ const uploadStore = useUploadStore(); const { sentBytes, totalBytes } = storeToRefs(uploadStore); const byteToMbyte = partial({ exponent: 2 }); +const byteToKbyte = partial({ exponent: 1 }); const sentPercent = computed(() => ((uploadStore.sentBytes / uploadStore.totalBytes) * 100).toFixed(2) @@ -95,11 +96,33 @@ const sentPercent = computed(() => const sentMbytes = computed(() => byteToMbyte(uploadStore.sentBytes)); const totalMbytes = computed(() => byteToMbyte(uploadStore.totalBytes)); -const speedMbytes = computed(() => byteToMbyte(speed.value)); +const speedText = computed(() => { + const bytes = speed.value; + + if (bytes < 1024 * 1024) { + const kb = parseFloat(byteToKbyte(bytes)); + return `${kb.toFixed(2)} KB`; + } else { + const mb = parseFloat(byteToMbyte(bytes)); + return `${mb.toFixed(2)} MB`; + } +}); let lastSpeedUpdate: number = 0; let recentSpeeds: number[] = []; +let lastThrottleTime = 0; + +const throttledCalculateSpeed = (sentBytes: number, oldSentBytes: number) => { + const now = Date.now(); + if (now - lastThrottleTime < 100) { + return; + } + + lastThrottleTime = now; + calculateSpeed(sentBytes, oldSentBytes); +}; + const calculateSpeed = (sentBytes: number, oldSentBytes: number) => { // Reset the state when the uploads batch is complete if (sentBytes === 0) { @@ -149,7 +172,7 @@ const calculateEta = () => { eta.value = remainingSize / speedBytesPerSecond; }; -watch(sentBytes, calculateSpeed); +watch(sentBytes, throttledCalculateSpeed); watch(totalBytes, (totalBytes, oldTotalBytes) => { if (oldTotalBytes !== 0) { diff --git a/http/auth.go b/http/auth.go index 62d6779e..18d10025 100644 --- a/http/auth.go +++ b/http/auth.go @@ -21,16 +21,16 @@ const ( ) type userInfo struct { - ID uint `json:"id"` - Locale string `json:"locale"` - ViewMode users.ViewMode `json:"viewMode"` - SingleClick bool `json:"singleClick"` - Perm users.Permissions `json:"perm"` - Commands []string `json:"commands"` - LockPassword bool `json:"lockPassword"` - HideDotfiles bool `json:"hideDotfiles"` - DateFormat bool `json:"dateFormat"` - Username string `json:"username"` + ID uint `json:"id"` + Locale string `json:"locale"` + ViewMode users.ViewMode `json:"viewMode"` + SingleClick bool `json:"singleClick"` + Perm users.Permissions `json:"perm"` + Commands []string `json:"commands"` + LockPassword bool `json:"lockPassword"` + HideDotfiles bool `json:"hideDotfiles"` + DateFormat bool `json:"dateFormat"` + Username string `json:"username"` AceEditorTheme string `json:"aceEditorTheme"` } @@ -191,16 +191,16 @@ func renewHandler(tokenExpireTime time.Duration) handleFunc { func printToken(w http.ResponseWriter, _ *http.Request, d *data, user *users.User, tokenExpirationTime time.Duration) (int, error) { claims := &authToken{ User: userInfo{ - ID: user.ID, - Locale: user.Locale, - ViewMode: user.ViewMode, - SingleClick: user.SingleClick, - Perm: user.Perm, - LockPassword: user.LockPassword, - Commands: user.Commands, - HideDotfiles: user.HideDotfiles, - DateFormat: user.DateFormat, - Username: user.Username, + ID: user.ID, + Locale: user.Locale, + ViewMode: user.ViewMode, + SingleClick: user.SingleClick, + Perm: user.Perm, + LockPassword: user.LockPassword, + Commands: user.Commands, + HideDotfiles: user.HideDotfiles, + DateFormat: user.DateFormat, + Username: user.Username, AceEditorTheme: user.AceEditorTheme, }, RegisteredClaims: jwt.RegisteredClaims{ From d29ad356d1067c87b2821debab91286549f512a0 Mon Sep 17 00:00:00 2001 From: MSomnium Studios <70982507+ArielLeyva@users.noreply.github.com> Date: Thu, 25 Sep 2025 10:57:30 -0400 Subject: [PATCH 067/240] feat: Improved path display in the new file and directory modal (#5451) --- .../src/components/prompts/CreateFilePath.vue | 87 +++++++++++++++++++ frontend/src/components/prompts/NewDir.vue | 2 + frontend/src/components/prompts/NewFile.vue | 2 + 3 files changed, 91 insertions(+) create mode 100644 frontend/src/components/prompts/CreateFilePath.vue diff --git a/frontend/src/components/prompts/CreateFilePath.vue b/frontend/src/components/prompts/CreateFilePath.vue new file mode 100644 index 00000000..9636b6cc --- /dev/null +++ b/frontend/src/components/prompts/CreateFilePath.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/frontend/src/components/prompts/NewDir.vue b/frontend/src/components/prompts/NewDir.vue index 1eb6d481..85d47bb8 100644 --- a/frontend/src/components/prompts/NewDir.vue +++ b/frontend/src/components/prompts/NewDir.vue @@ -14,6 +14,7 @@ v-model.trim="name" tabindex="1" /> +
@@ -48,6 +49,7 @@ import { files as api } from "@/api"; import url from "@/utils/url"; import { useRoute, useRouter } from "vue-router"; import { useI18n } from "vue-i18n"; +import CreateFilePath from "@/components/prompts/CreateFilePath.vue"; const $showError = inject("$showError")!; diff --git a/frontend/src/components/prompts/NewFile.vue b/frontend/src/components/prompts/NewFile.vue index b7c05d44..d3fb34ed 100644 --- a/frontend/src/components/prompts/NewFile.vue +++ b/frontend/src/components/prompts/NewFile.vue @@ -13,6 +13,7 @@ @keyup.enter="submit" v-model.trim="name" /> +
@@ -42,6 +43,7 @@ import { useI18n } from "vue-i18n"; import { useRoute, useRouter } from "vue-router"; import { useFileStore } from "@/stores/file"; import { useLayoutStore } from "@/stores/layout"; +import CreateFilePath from "@/components/prompts/CreateFilePath.vue"; import { files as api } from "@/api"; import url from "@/utils/url"; From c4725428e07da72b855009e2c13c6ed91d32e0b7 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Thu, 25 Sep 2025 17:09:16 +0200 Subject: [PATCH 068/240] fix: computation of file path --- frontend/src/components/prompts/CreateFilePath.vue | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/frontend/src/components/prompts/CreateFilePath.vue b/frontend/src/components/prompts/CreateFilePath.vue index 9636b6cc..ec470f3a 100644 --- a/frontend/src/components/prompts/CreateFilePath.vue +++ b/frontend/src/components/prompts/CreateFilePath.vue @@ -41,12 +41,11 @@ const container = ref(null); const path = computed(() => { let basePath = fileStore.isFiles ? route.path : url.removeLastDir(route.path); + if (!basePath.endsWith("/")) { + basePath += "/"; + } basePath += props.name; - - return basePath - .replace(/^\/[^\/]+/, "") - .split("/") - .filter(Boolean); + return basePath.split("/").filter(Boolean).splice(1); }); watch(path, () => { From 949ddffef20e38169902c5fd74dca4815dcecf11 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Thu, 25 Sep 2025 17:13:30 +0200 Subject: [PATCH 069/240] fix: some formatting issues with i18n files --- frontend/src/i18n/ar.json | 4 ++-- frontend/src/i18n/ca.json | 4 ++-- frontend/src/i18n/cs.json | 4 ++-- frontend/src/i18n/de.json | 4 ++-- frontend/src/i18n/el.json | 4 ++-- frontend/src/i18n/en.json | 4 ++-- frontend/src/i18n/es.json | 4 ++-- frontend/src/i18n/fa.json | 4 ++-- frontend/src/i18n/fr.json | 4 ++-- frontend/src/i18n/he.json | 4 ++-- frontend/src/i18n/hu.json | 4 ++-- frontend/src/i18n/is.json | 4 ++-- frontend/src/i18n/it.json | 4 ++-- frontend/src/i18n/ja.json | 4 ++-- frontend/src/i18n/ko.json | 4 ++-- frontend/src/i18n/nl-be.json | 4 ++-- frontend/src/i18n/no.json | 4 ++-- frontend/src/i18n/pl.json | 4 ++-- frontend/src/i18n/pt-br.json | 4 ++-- frontend/src/i18n/pt.json | 4 ++-- frontend/src/i18n/ro.json | 4 ++-- frontend/src/i18n/ru.json | 4 ++-- frontend/src/i18n/sk.json | 4 ++-- frontend/src/i18n/sv-se.json | 4 ++-- frontend/src/i18n/tr.json | 4 ++-- frontend/src/i18n/uk.json | 4 ++-- frontend/src/i18n/vi.json | 4 ++-- frontend/src/i18n/zh-cn.json | 4 ++-- frontend/src/i18n/zh-tw.json | 4 ++-- 29 files changed, 58 insertions(+), 58 deletions(-) diff --git a/frontend/src/i18n/ar.json b/frontend/src/i18n/ar.json index 70feef51..9b06d2d3 100644 --- a/frontend/src/i18n/ar.json +++ b/frontend/src/i18n/ar.json @@ -42,8 +42,8 @@ "update": "تحديث", "upload": "رفع", "openFile": "فتح الملف", - "discardChanges": "إلغاء التغييرات", - "saveChanges": "Save changes" + "discardChanges": "إلغاء التغييرات", + "saveChanges": "Save changes" }, "download": { "downloadFile": "تحميل الملف", diff --git a/frontend/src/i18n/ca.json b/frontend/src/i18n/ca.json index 4d698fa5..353eeb22 100644 --- a/frontend/src/i18n/ca.json +++ b/frontend/src/i18n/ca.json @@ -42,8 +42,8 @@ "update": "Actualitzar", "upload": "Pujar", "openFile": "Obrir fitxer", - "discardChanges": "Descartar", - "saveChanges": "Save changes" + "discardChanges": "Descartar", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Descarregar fitxer", diff --git a/frontend/src/i18n/cs.json b/frontend/src/i18n/cs.json index c7e32842..635a1d96 100644 --- a/frontend/src/i18n/cs.json +++ b/frontend/src/i18n/cs.json @@ -42,8 +42,8 @@ "update": "Aktualizovat", "upload": "Nahrát", "openFile": "Otevřít soubor", - "discardChanges": "Zrušit změny", - "saveChanges": "Save changes" + "discardChanges": "Zrušit změny", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Stáhnout soubor", diff --git a/frontend/src/i18n/de.json b/frontend/src/i18n/de.json index d22a3be1..40971820 100644 --- a/frontend/src/i18n/de.json +++ b/frontend/src/i18n/de.json @@ -42,8 +42,8 @@ "update": "Update", "upload": "Upload", "openFile": "Datei öffnen", - "discardChanges": "Verwerfen", - "saveChanges": "Save changes" + "discardChanges": "Verwerfen", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Download Datei", diff --git a/frontend/src/i18n/el.json b/frontend/src/i18n/el.json index 9fed72f1..ba75606f 100644 --- a/frontend/src/i18n/el.json +++ b/frontend/src/i18n/el.json @@ -42,8 +42,8 @@ "update": "Ενημέρωση", "upload": "Μεταφόρτωση", "openFile": "Άνοιγμα αρχείου", - "discardChanges": "Discard", - "saveChanges": "Save changes" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Λήψη αρχείου", diff --git a/frontend/src/i18n/en.json b/frontend/src/i18n/en.json index b6325511..15a297df 100644 --- a/frontend/src/i18n/en.json +++ b/frontend/src/i18n/en.json @@ -42,8 +42,8 @@ "update": "Update", "upload": "Upload", "openFile": "Open file", - "discardChanges": "Discard", - "saveChanges": "Save changes" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Download File", diff --git a/frontend/src/i18n/es.json b/frontend/src/i18n/es.json index e7f9e882..a3565f4f 100644 --- a/frontend/src/i18n/es.json +++ b/frontend/src/i18n/es.json @@ -42,8 +42,8 @@ "update": "Actualizar", "upload": "Subir", "openFile": "Abrir archivo", - "discardChanges": "Discard", - "saveChanges": "Guardar cambios" + "discardChanges": "Discard", + "saveChanges": "Guardar cambios" }, "download": { "downloadFile": "Descargar fichero", diff --git a/frontend/src/i18n/fa.json b/frontend/src/i18n/fa.json index 70e10c12..e4a2532e 100644 --- a/frontend/src/i18n/fa.json +++ b/frontend/src/i18n/fa.json @@ -42,8 +42,8 @@ "update": "به روز سانی", "upload": "آپلود", "openFile": "باز کردن فایل", - "discardChanges": "لغو کردن", - "saveChanges": "Save changes" + "discardChanges": "لغو کردن", + "saveChanges": "Save changes" }, "download": { "downloadFile": "دانلود فایل", diff --git a/frontend/src/i18n/fr.json b/frontend/src/i18n/fr.json index 16508807..fcbd239b 100644 --- a/frontend/src/i18n/fr.json +++ b/frontend/src/i18n/fr.json @@ -42,8 +42,8 @@ "update": "Mettre à jour", "upload": "Importer", "openFile": "Ouvrir le fichier", - "discardChanges": "Annuler", - "saveChanges": "Save changes" + "discardChanges": "Annuler", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Télécharger le fichier", diff --git a/frontend/src/i18n/he.json b/frontend/src/i18n/he.json index a8e89a93..9bb3145a 100644 --- a/frontend/src/i18n/he.json +++ b/frontend/src/i18n/he.json @@ -42,8 +42,8 @@ "update": "עדכון", "upload": "העלאה", "openFile": "פתח קובץ", - "discardChanges": "זריקת השינויים", - "saveChanges": "Save changes" + "discardChanges": "זריקת השינויים", + "saveChanges": "Save changes" }, "download": { "downloadFile": "הורד קובץ", diff --git a/frontend/src/i18n/hu.json b/frontend/src/i18n/hu.json index 00fc419e..0971d9cc 100644 --- a/frontend/src/i18n/hu.json +++ b/frontend/src/i18n/hu.json @@ -42,8 +42,8 @@ "update": "Frissítés", "upload": "Feltöltés", "openFile": "Fájl megnyitása", - "discardChanges": "Discard", - "saveChanges": "Save changes" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Fájl letöltése", diff --git a/frontend/src/i18n/is.json b/frontend/src/i18n/is.json index c55455e5..65a5eb00 100644 --- a/frontend/src/i18n/is.json +++ b/frontend/src/i18n/is.json @@ -42,8 +42,8 @@ "update": "Vista", "upload": "Hlaða upp", "openFile": "Open file", - "discardChanges": "Discard", - "saveChanges": "Save changes" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Sækja skjal", diff --git a/frontend/src/i18n/it.json b/frontend/src/i18n/it.json index 995ba7cd..b1135aac 100644 --- a/frontend/src/i18n/it.json +++ b/frontend/src/i18n/it.json @@ -42,8 +42,8 @@ "update": "Aggiorna", "upload": "Carica", "openFile": "Apri file", - "discardChanges": "Ignora", - "saveChanges": "Save changes" + "discardChanges": "Ignora", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Scarica file", diff --git a/frontend/src/i18n/ja.json b/frontend/src/i18n/ja.json index 99e4b017..574bf59a 100644 --- a/frontend/src/i18n/ja.json +++ b/frontend/src/i18n/ja.json @@ -42,8 +42,8 @@ "update": "更新", "upload": "アップロード", "openFile": "ファイルを開く", - "discardChanges": "Discard", - "saveChanges": "Save changes" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "ファイルのダウンロード", diff --git a/frontend/src/i18n/ko.json b/frontend/src/i18n/ko.json index ec64bd62..ea5a1e67 100644 --- a/frontend/src/i18n/ko.json +++ b/frontend/src/i18n/ko.json @@ -42,8 +42,8 @@ "update": "업데이트", "upload": "업로드", "openFile": "파일 열기", - "discardChanges": "변경 사항 취소", - "saveChanges": "변경사항 저장" + "discardChanges": "변경 사항 취소", + "saveChanges": "변경사항 저장" }, "download": { "downloadFile": "파일 다운로드", diff --git a/frontend/src/i18n/nl-be.json b/frontend/src/i18n/nl-be.json index c104ef81..af659e5c 100644 --- a/frontend/src/i18n/nl-be.json +++ b/frontend/src/i18n/nl-be.json @@ -42,8 +42,8 @@ "update": "Updaten", "upload": "Uploaden", "openFile": "Open file", - "discardChanges": "Discard", - "saveChanges": "Save changes" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Bestand downloaden", diff --git a/frontend/src/i18n/no.json b/frontend/src/i18n/no.json index a3803ae9..08c6992c 100644 --- a/frontend/src/i18n/no.json +++ b/frontend/src/i18n/no.json @@ -42,8 +42,8 @@ "update": "Opptater", "upload": "Last opp", "openFile": "Open file", - "discardChanges": "Slett", - "saveChanges": "Lagre Endringane " + "discardChanges": "Slett", + "saveChanges": "Lagre Endringane " }, "download": { "downloadFile": "Nedlast filen", diff --git a/frontend/src/i18n/pl.json b/frontend/src/i18n/pl.json index 54dd9aed..06f1c8fd 100644 --- a/frontend/src/i18n/pl.json +++ b/frontend/src/i18n/pl.json @@ -42,8 +42,8 @@ "update": "Aktualizuj", "upload": "Wyślij", "openFile": "Otwórz plik", - "discardChanges": "Odrzuć", - "saveChanges": "Zapisz zmiany" + "discardChanges": "Odrzuć", + "saveChanges": "Zapisz zmiany" }, "download": { "downloadFile": "Pobierz plik", diff --git a/frontend/src/i18n/pt-br.json b/frontend/src/i18n/pt-br.json index 8e314c77..a4938c49 100644 --- a/frontend/src/i18n/pt-br.json +++ b/frontend/src/i18n/pt-br.json @@ -42,8 +42,8 @@ "update": "Atualizar", "upload": "Enviar", "openFile": "Abrir", - "discardChanges": "Discard", - "saveChanges": "Save changes" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Baixar arquivo", diff --git a/frontend/src/i18n/pt.json b/frontend/src/i18n/pt.json index 4c719cc9..2555eafb 100644 --- a/frontend/src/i18n/pt.json +++ b/frontend/src/i18n/pt.json @@ -42,8 +42,8 @@ "update": "Atualizar", "upload": "Enviar", "openFile": "Open file", - "discardChanges": "Discard", - "saveChanges": "Save changes" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Descarregar ficheiro", diff --git a/frontend/src/i18n/ro.json b/frontend/src/i18n/ro.json index 232b0e4d..5f4a630e 100644 --- a/frontend/src/i18n/ro.json +++ b/frontend/src/i18n/ro.json @@ -42,8 +42,8 @@ "update": "Actualizează", "upload": "Încarcă", "openFile": "Open file", - "discardChanges": "Discard", - "saveChanges": "Save changes" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Descarcă fișier", diff --git a/frontend/src/i18n/ru.json b/frontend/src/i18n/ru.json index 931cf68d..d9407647 100644 --- a/frontend/src/i18n/ru.json +++ b/frontend/src/i18n/ru.json @@ -42,8 +42,8 @@ "update": "Обновить", "upload": "Загрузить", "openFile": "Открыть файл", - "discardChanges": "Отказаться", - "saveChanges": "Save changes" + "discardChanges": "Отказаться", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Скачать файл", diff --git a/frontend/src/i18n/sk.json b/frontend/src/i18n/sk.json index 2f01ef8c..06c73a98 100644 --- a/frontend/src/i18n/sk.json +++ b/frontend/src/i18n/sk.json @@ -42,8 +42,8 @@ "update": "Aktualizovať", "upload": "Nahrať", "openFile": "Otvoriť súbor", - "discardChanges": "Zahodiť", - "saveChanges": "Save changes" + "discardChanges": "Zahodiť", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Stiahnuť súbor", diff --git a/frontend/src/i18n/sv-se.json b/frontend/src/i18n/sv-se.json index 319b7eb2..47c041c0 100644 --- a/frontend/src/i18n/sv-se.json +++ b/frontend/src/i18n/sv-se.json @@ -42,8 +42,8 @@ "update": "Uppdatera", "upload": "Ladda upp", "openFile": "Open file", - "discardChanges": "Discard", - "saveChanges": "Save changes" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Ladda ner fil", diff --git a/frontend/src/i18n/tr.json b/frontend/src/i18n/tr.json index aa0d3558..ed635501 100644 --- a/frontend/src/i18n/tr.json +++ b/frontend/src/i18n/tr.json @@ -42,8 +42,8 @@ "update": "Güncelle", "upload": "Yükle", "openFile": "Dosyayı aç", - "discardChanges": "Discard", - "saveChanges": "Save changes" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Dosyayı indir", diff --git a/frontend/src/i18n/uk.json b/frontend/src/i18n/uk.json index d3f01c9f..a81010f6 100644 --- a/frontend/src/i18n/uk.json +++ b/frontend/src/i18n/uk.json @@ -42,8 +42,8 @@ "update": "Оновити", "upload": "Вивантажити", "openFile": "Відкрити файл", - "discardChanges": "Скасувати", - "saveChanges": "Save changes" + "discardChanges": "Скасувати", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Завантажити файл", diff --git a/frontend/src/i18n/vi.json b/frontend/src/i18n/vi.json index 380f98ff..07864ce8 100644 --- a/frontend/src/i18n/vi.json +++ b/frontend/src/i18n/vi.json @@ -42,8 +42,8 @@ "update": "Cập nhật", "upload": "Tải lên", "openFile": "Mở tệp", - "discardChanges": "Hủy bỏ thay đổi", - "saveChanges": "Save changes" + "discardChanges": "Hủy bỏ thay đổi", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Tải xuống tệp tin", diff --git a/frontend/src/i18n/zh-cn.json b/frontend/src/i18n/zh-cn.json index c18c7e98..6a8b9065 100644 --- a/frontend/src/i18n/zh-cn.json +++ b/frontend/src/i18n/zh-cn.json @@ -42,8 +42,8 @@ "update": "更新", "upload": "上传", "openFile": "打开文件", - "discardChanges": "放弃更改", - "saveChanges": "Save changes" + "discardChanges": "放弃更改", + "saveChanges": "Save changes" }, "download": { "downloadFile": "下载文件", diff --git a/frontend/src/i18n/zh-tw.json b/frontend/src/i18n/zh-tw.json index adcfde91..4ceb886c 100644 --- a/frontend/src/i18n/zh-tw.json +++ b/frontend/src/i18n/zh-tw.json @@ -42,8 +42,8 @@ "update": "更新", "upload": "上傳", "openFile": "開啟檔案", - "discardChanges": "放棄變更", - "saveChanges": "Save changes" + "discardChanges": "放棄變更", + "saveChanges": "Save changes" }, "download": { "downloadFile": "下載檔案", From 1165f00bd4dcb0dcfbc084f54f51902ba4b4a714 Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Thu, 25 Sep 2025 17:19:21 +0200 Subject: [PATCH 070/240] feat: Updates for project File Browser (#5457) Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com> --- frontend/src/i18n/ar.json | 1 + frontend/src/i18n/ca.json | 1 + frontend/src/i18n/cs.json | 1 + frontend/src/i18n/de.json | 1 + frontend/src/i18n/el.json | 1 + frontend/src/i18n/es.json | 1 + frontend/src/i18n/fa.json | 1 + frontend/src/i18n/fr.json | 1 + frontend/src/i18n/he.json | 1 + frontend/src/i18n/hu.json | 1 + frontend/src/i18n/is.json | 1 + frontend/src/i18n/it.json | 1 + frontend/src/i18n/ja.json | 1 + frontend/src/i18n/ko.json | 1 + frontend/src/i18n/nl-be.json | 1 + frontend/src/i18n/no.json | 1 + frontend/src/i18n/pl.json | 1 + frontend/src/i18n/pt-br.json | 1 + frontend/src/i18n/pt.json | 1 + frontend/src/i18n/ro.json | 1 + frontend/src/i18n/ru.json | 1 + frontend/src/i18n/sk.json | 1 + frontend/src/i18n/sv-se.json | 1 + frontend/src/i18n/tr.json | 1 + frontend/src/i18n/uk.json | 1 + frontend/src/i18n/vi.json | 1 + frontend/src/i18n/zh-cn.json | 1 + frontend/src/i18n/zh-tw.json | 1 + 28 files changed, 28 insertions(+) diff --git a/frontend/src/i18n/ar.json b/frontend/src/i18n/ar.json index 9b06d2d3..26e95765 100644 --- a/frontend/src/i18n/ar.json +++ b/frontend/src/i18n/ar.json @@ -158,6 +158,7 @@ "video": "فيديوهات" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "إدارة", "administrator": "مدير", "allowCommands": "تنفيذ اﻷوامر", diff --git a/frontend/src/i18n/ca.json b/frontend/src/i18n/ca.json index 353eeb22..e17c7c80 100644 --- a/frontend/src/i18n/ca.json +++ b/frontend/src/i18n/ca.json @@ -158,6 +158,7 @@ "video": "Vídeo" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrador", "allowCommands": "Executar comandes", diff --git a/frontend/src/i18n/cs.json b/frontend/src/i18n/cs.json index 635a1d96..914b843f 100644 --- a/frontend/src/i18n/cs.json +++ b/frontend/src/i18n/cs.json @@ -158,6 +158,7 @@ "video": "Video" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrátor", "allowCommands": "Povolit příkazy", diff --git a/frontend/src/i18n/de.json b/frontend/src/i18n/de.json index 40971820..48c91eb8 100644 --- a/frontend/src/i18n/de.json +++ b/frontend/src/i18n/de.json @@ -158,6 +158,7 @@ "video": "Video" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrator", "allowCommands": "Befehle ausführen", diff --git a/frontend/src/i18n/el.json b/frontend/src/i18n/el.json index ba75606f..97206a1f 100644 --- a/frontend/src/i18n/el.json +++ b/frontend/src/i18n/el.json @@ -158,6 +158,7 @@ "video": "Βίντεο" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Διαχειριστής", "administrator": "Διαχειριστής", "allowCommands": "Εκτέλεση εντολών", diff --git a/frontend/src/i18n/es.json b/frontend/src/i18n/es.json index a3565f4f..2981ece1 100644 --- a/frontend/src/i18n/es.json +++ b/frontend/src/i18n/es.json @@ -158,6 +158,7 @@ "video": "Vídeo" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrador", "allowCommands": "Ejecutar comandos", diff --git a/frontend/src/i18n/fa.json b/frontend/src/i18n/fa.json index e4a2532e..1d885fcc 100644 --- a/frontend/src/i18n/fa.json +++ b/frontend/src/i18n/fa.json @@ -158,6 +158,7 @@ "video": "ویدئو " }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrator", "allowCommands": "اجرای دستورات", diff --git a/frontend/src/i18n/fr.json b/frontend/src/i18n/fr.json index fcbd239b..bf07499a 100644 --- a/frontend/src/i18n/fr.json +++ b/frontend/src/i18n/fr.json @@ -158,6 +158,7 @@ "video": "Vidéo" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrateur·ice", "allowCommands": "Exécuter des commandes", diff --git a/frontend/src/i18n/he.json b/frontend/src/i18n/he.json index 9bb3145a..6576ebd0 100644 --- a/frontend/src/i18n/he.json +++ b/frontend/src/i18n/he.json @@ -158,6 +158,7 @@ "video": "וידאו" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "מנהל", "administrator": "מנהל ראשי", "allowCommands": "הפעלת פקודות", diff --git a/frontend/src/i18n/hu.json b/frontend/src/i18n/hu.json index 0971d9cc..dd58ed1d 100644 --- a/frontend/src/i18n/hu.json +++ b/frontend/src/i18n/hu.json @@ -158,6 +158,7 @@ "video": "Videó" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Adminisztrátor", "allowCommands": "Parancsok futtatása", diff --git a/frontend/src/i18n/is.json b/frontend/src/i18n/is.json index 65a5eb00..431f21ef 100644 --- a/frontend/src/i18n/is.json +++ b/frontend/src/i18n/is.json @@ -158,6 +158,7 @@ "video": "Myndbönd" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Stjórnandi", "administrator": "Stjórnandi", "allowCommands": "Senda skipanir", diff --git a/frontend/src/i18n/it.json b/frontend/src/i18n/it.json index b1135aac..929d90ed 100644 --- a/frontend/src/i18n/it.json +++ b/frontend/src/i18n/it.json @@ -158,6 +158,7 @@ "video": "Video" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Amministratore", "allowCommands": "Esegui comandi", diff --git a/frontend/src/i18n/ja.json b/frontend/src/i18n/ja.json index 574bf59a..0e6b9c04 100644 --- a/frontend/src/i18n/ja.json +++ b/frontend/src/i18n/ja.json @@ -158,6 +158,7 @@ "video": "動画" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "管理者", "administrator": "管理者", "allowCommands": "コマンドの実行", diff --git a/frontend/src/i18n/ko.json b/frontend/src/i18n/ko.json index ea5a1e67..64a6c7d5 100644 --- a/frontend/src/i18n/ko.json +++ b/frontend/src/i18n/ko.json @@ -158,6 +158,7 @@ "video": "비디오" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "관리자", "administrator": "관리자", "allowCommands": "명령 실행", diff --git a/frontend/src/i18n/nl-be.json b/frontend/src/i18n/nl-be.json index af659e5c..78a7c281 100644 --- a/frontend/src/i18n/nl-be.json +++ b/frontend/src/i18n/nl-be.json @@ -158,6 +158,7 @@ "video": "Video" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrator", "allowCommands": "Commando's uitvoeren", diff --git a/frontend/src/i18n/no.json b/frontend/src/i18n/no.json index 08c6992c..3eea3638 100644 --- a/frontend/src/i18n/no.json +++ b/frontend/src/i18n/no.json @@ -158,6 +158,7 @@ "video": "Video" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrator", "allowCommands": "Utfør kommandoer", diff --git a/frontend/src/i18n/pl.json b/frontend/src/i18n/pl.json index 06f1c8fd..b9db7455 100644 --- a/frontend/src/i18n/pl.json +++ b/frontend/src/i18n/pl.json @@ -158,6 +158,7 @@ "video": "Wideo" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrator", "allowCommands": "Wykonaj polecenie", diff --git a/frontend/src/i18n/pt-br.json b/frontend/src/i18n/pt-br.json index a4938c49..d29f98d6 100644 --- a/frontend/src/i18n/pt-br.json +++ b/frontend/src/i18n/pt-br.json @@ -158,6 +158,7 @@ "video": "Vídeos" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrador", "allowCommands": "Executar comandos", diff --git a/frontend/src/i18n/pt.json b/frontend/src/i18n/pt.json index 2555eafb..e54a4f0d 100644 --- a/frontend/src/i18n/pt.json +++ b/frontend/src/i18n/pt.json @@ -158,6 +158,7 @@ "video": "Vídeos" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrador", "allowCommands": "Executar comandos", diff --git a/frontend/src/i18n/ro.json b/frontend/src/i18n/ro.json index 5f4a630e..73719a4e 100644 --- a/frontend/src/i18n/ro.json +++ b/frontend/src/i18n/ro.json @@ -158,6 +158,7 @@ "video": "Video" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrator", "allowCommands": "Execută comenzi", diff --git a/frontend/src/i18n/ru.json b/frontend/src/i18n/ru.json index d9407647..0678ce14 100644 --- a/frontend/src/i18n/ru.json +++ b/frontend/src/i18n/ru.json @@ -158,6 +158,7 @@ "video": "Видео" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Админ", "administrator": "Администратор", "allowCommands": "Запуск команд", diff --git a/frontend/src/i18n/sk.json b/frontend/src/i18n/sk.json index 06c73a98..68112fba 100644 --- a/frontend/src/i18n/sk.json +++ b/frontend/src/i18n/sk.json @@ -158,6 +158,7 @@ "video": "Video" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrátor", "allowCommands": "Vykonávať príkazy", diff --git a/frontend/src/i18n/sv-se.json b/frontend/src/i18n/sv-se.json index 47c041c0..9f66a141 100644 --- a/frontend/src/i18n/sv-se.json +++ b/frontend/src/i18n/sv-se.json @@ -158,6 +158,7 @@ "video": "Video" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administratör", "allowCommands": "Exekvera kommandon", diff --git a/frontend/src/i18n/tr.json b/frontend/src/i18n/tr.json index ed635501..7493821e 100644 --- a/frontend/src/i18n/tr.json +++ b/frontend/src/i18n/tr.json @@ -158,6 +158,7 @@ "video": "Video" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Yönetim", "administrator": "Yönetici", "allowCommands": "Komutları çalıştır", diff --git a/frontend/src/i18n/uk.json b/frontend/src/i18n/uk.json index a81010f6..40a96893 100644 --- a/frontend/src/i18n/uk.json +++ b/frontend/src/i18n/uk.json @@ -158,6 +158,7 @@ "video": "Відео" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Адмін", "administrator": "Адміністратор", "allowCommands": "Запуск команд", diff --git a/frontend/src/i18n/vi.json b/frontend/src/i18n/vi.json index 07864ce8..fab93759 100644 --- a/frontend/src/i18n/vi.json +++ b/frontend/src/i18n/vi.json @@ -158,6 +158,7 @@ "video": "Video" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Quản trị viên", "administrator": "Người quản trị", "allowCommands": "Thực thi lệnh", diff --git a/frontend/src/i18n/zh-cn.json b/frontend/src/i18n/zh-cn.json index 6a8b9065..15cf8e3c 100644 --- a/frontend/src/i18n/zh-cn.json +++ b/frontend/src/i18n/zh-cn.json @@ -158,6 +158,7 @@ "video": "视频" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "管理员", "administrator": "管理员", "allowCommands": "执行命令(Shell 命令)", diff --git a/frontend/src/i18n/zh-tw.json b/frontend/src/i18n/zh-tw.json index 4ceb886c..d59f1efd 100644 --- a/frontend/src/i18n/zh-tw.json +++ b/frontend/src/i18n/zh-tw.json @@ -158,6 +158,7 @@ "video": "影片" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "管理員", "administrator": "管理員", "allowCommands": "執行命令", From 878cdfbc52bdb4c4385f24904a87927f852cb907 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Thu, 25 Sep 2025 17:20:12 +0200 Subject: [PATCH 071/240] chore(release): 2.44.0 --- CHANGELOG.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f81c8cd4..9bf8bd77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,26 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [2.44.0](https://github.com/filebrowser/filebrowser/compare/v2.43.0...v2.44.0) (2025-09-25) + + +### Features + +* allow setting ace editor theme ([#3826](https://github.com/filebrowser/filebrowser/issues/3826)) ([b9787c7](https://github.com/filebrowser/filebrowser/commit/b9787c78f3889171f94db19e7655dce68c64b6fb)) +* Improved path display in the new file and directory modal ([#5451](https://github.com/filebrowser/filebrowser/issues/5451)) ([d29ad35](https://github.com/filebrowser/filebrowser/commit/d29ad356d1067c87b2821debab91286549f512a0)) +* Translate frontend/src/i18n/en.json in no ([dec7a02](https://github.com/filebrowser/filebrowser/commit/dec7a027378fbc6948d203199c44a640a141bcad)) +* Updates for project File Browser ([#5446](https://github.com/filebrowser/filebrowser/issues/5446)) ([4ff247e](https://github.com/filebrowser/filebrowser/commit/4ff247e134e4d61668ee656a258ed67f71414e18)) +* Updates for project File Browser ([#5450](https://github.com/filebrowser/filebrowser/issues/5450)) ([0eade71](https://github.com/filebrowser/filebrowser/commit/0eade717ce9d04bf48051922f11d983edbc7c2d0)) +* Updates for project File Browser ([#5457](https://github.com/filebrowser/filebrowser/issues/5457)) ([1165f00](https://github.com/filebrowser/filebrowser/commit/1165f00bd4dcb0dcfbc084f54f51902ba4b4a714)) + + +### Bug Fixes + +* computation of file path ([c472542](https://github.com/filebrowser/filebrowser/commit/c4725428e07da72b855009e2c13c6ed91d32e0b7)) +* show login when session token expires ([e6c674b](https://github.com/filebrowser/filebrowser/commit/e6c674b3c616831942c4d4aacab0907d58003e23)) +* some formatting issues with i18n files ([949ddff](https://github.com/filebrowser/filebrowser/commit/949ddffef20e38169902c5fd74dca4815dcecf11)) +* **upload:** throttle upload speed calculation to 100ms to avoid Infinity MB/s ([#5456](https://github.com/filebrowser/filebrowser/issues/5456)) ([692ca5e](https://github.com/filebrowser/filebrowser/commit/692ca5eaf01e4dcf346ba03f82c5dbd50cce246b)) + ## [2.43.0](https://github.com/filebrowser/filebrowser/compare/v2.42.5...v2.43.0) (2025-09-13) From d0039afbb76a9364c1e6ac9715ccc3c239dc8cb6 Mon Sep 17 00:00:00 2001 From: Ryan <43447928+Rmiller5466@users.noreply.github.com> Date: Fri, 3 Oct 2025 04:42:24 -0400 Subject: [PATCH 072/240] fix: wrong url on settings branding link --- frontend/src/views/settings/Global.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/views/settings/Global.vue b/frontend/src/views/settings/Global.vue index e397c6f7..0a42a293 100644 --- a/frontend/src/views/settings/Global.vue +++ b/frontend/src/views/settings/Global.vue @@ -65,7 +65,7 @@ {{ t("settings.documentation") }} From a397e7305d1572baf67823413f97a29eea38f0cc Mon Sep 17 00:00:00 2001 From: Ryan <43447928+Rmiller5466@users.noreply.github.com> Date: Fri, 17 Oct 2025 10:45:36 -0400 Subject: [PATCH 073/240] fix: editor discard prompt doesn't save nor discard Co-authored-by: Ryan Miller --- .../components/prompts/DiscardEditorChanges.vue | 10 ++-------- frontend/src/views/files/Editor.vue | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/frontend/src/components/prompts/DiscardEditorChanges.vue b/frontend/src/components/prompts/DiscardEditorChanges.vue index bd6bc49a..7a99c5fc 100644 --- a/frontend/src/components/prompts/DiscardEditorChanges.vue +++ b/frontend/src/components/prompts/DiscardEditorChanges.vue @@ -17,7 +17,7 @@