From f2c654a47ce45d11bc73da4906fd141d3a3fdcbb Mon Sep 17 00:00:00 2001 From: "github-action[bot]" Date: Sun, 30 Nov 2025 19:38:24 +0100 Subject: [PATCH] Update On Sun Nov 30 19:38:24 CET 2025 --- .github/update.log | 1 + clash-meta/go.mod | 4 +- clash-meta/go.sum | 8 +- clash-nyanpasu/manifest/version.json | 4 +- filebrowser/.github/workflows/docs.yml | 20 +-- filebrowser/CHANGELOG.md | 15 ++ filebrowser/cmd/config.go | 4 + filebrowser/frontend/index.html | 1 + filebrowser/frontend/pnpm-lock.yaml | 22 +-- .../frontend/src/components/Sidebar.vue | 3 +- .../src/components/files/CsvViewer.vue | 13 +- filebrowser/frontend/src/i18n/ar.json | 7 +- filebrowser/frontend/src/i18n/bg.json | 7 +- filebrowser/frontend/src/i18n/ca.json | 7 +- filebrowser/frontend/src/i18n/cs.json | 7 +- filebrowser/frontend/src/i18n/de.json | 7 +- filebrowser/frontend/src/i18n/el.json | 7 +- filebrowser/frontend/src/i18n/es.json | 7 +- filebrowser/frontend/src/i18n/fa.json | 7 +- filebrowser/frontend/src/i18n/fr.json | 7 +- filebrowser/frontend/src/i18n/he.json | 7 +- filebrowser/frontend/src/i18n/hr.json | 7 +- filebrowser/frontend/src/i18n/hu.json | 7 +- filebrowser/frontend/src/i18n/is.json | 7 +- filebrowser/frontend/src/i18n/it.json | 7 +- filebrowser/frontend/src/i18n/ja.json | 7 +- filebrowser/frontend/src/i18n/ko.json | 7 +- filebrowser/frontend/src/i18n/nl-be.json | 7 +- filebrowser/frontend/src/i18n/no.json | 7 +- filebrowser/frontend/src/i18n/pl.json | 7 +- filebrowser/frontend/src/i18n/pt-br.json | 7 +- filebrowser/frontend/src/i18n/pt.json | 7 +- filebrowser/frontend/src/i18n/ro.json | 7 +- filebrowser/frontend/src/i18n/ru.json | 7 +- filebrowser/frontend/src/i18n/sk.json | 7 +- filebrowser/frontend/src/i18n/sv-se.json | 7 +- filebrowser/frontend/src/i18n/tr.json | 7 +- filebrowser/frontend/src/i18n/uk.json | 7 +- filebrowser/frontend/src/i18n/vi.json | 7 +- filebrowser/frontend/src/i18n/zh-cn.json | 7 +- filebrowser/frontend/src/i18n/zh-tw.json | 7 +- filebrowser/frontend/src/utils/auth.ts | 10 +- filebrowser/frontend/src/utils/constants.ts | 2 + .../frontend/src/views/files/Editor.vue | 9 +- filebrowser/http/auth.go | 28 ++- filebrowser/http/static.go | 1 + filebrowser/settings/settings.go | 2 + filebrowser/settings/storage.go | 10 ++ .../www/docs/cli/filebrowser-config-init.md | 1 + .../www/docs/cli/filebrowser-config-set.md | 1 + mieru/Makefile | 2 +- mieru/apis/common/conn.go | 72 ++++++++ mieru/apis/common/conn_test.go | 43 +++++ mieru/{pkg => apis}/common/user_context.go | 0 mieru/apis/server/interface.go | 2 + mieru/apis/server/server.go | 4 + .../package/mieru/amd64/debian/DEBIAN/control | 2 +- .../build/package/mieru/amd64/rpm/mieru.spec | 2 +- .../package/mieru/arm64/debian/DEBIAN/control | 2 +- .../build/package/mieru/arm64/rpm/mieru.spec | 2 +- .../package/mita/amd64/debian/DEBIAN/control | 2 +- mieru/build/package/mita/amd64/rpm/mita.spec | 2 +- .../package/mita/arm64/debian/DEBIAN/control | 2 +- mieru/build/package/mita/arm64/rpm/mita.spec | 2 +- mieru/docs/server-install.md | 16 +- mieru/docs/server-install.zh_CN.md | 16 +- mieru/pkg/appctl/appctlcommon/client.go | 16 +- mieru/pkg/common/conn.go | 56 ------ mieru/pkg/common/conn_test.go | 21 --- mieru/pkg/protocol/mux.go | 4 +- mieru/pkg/protocol/session.go | 23 ++- mieru/pkg/protocol/underlay_packet.go | 4 +- mieru/pkg/protocol/underlay_stream.go | 9 +- mieru/pkg/socks5/socks5.go | 23 ++- mieru/pkg/version/current.go | 2 +- .../cmd/exampleapiserver/exampleapiserver.go | 11 +- mieru/test/deploy/mihomo/client_tcp.json | 2 +- .../deploy/mihomo/client_tcp_no_wait.json | 2 +- mieru/test/deploy/mihomo/client_udp.json | 2 +- .../deploy/mihomo/client_udp_no_wait.json | 2 +- .../mihomo/mihomo-client-tcp-no-wait.yaml | 2 +- .../test/deploy/mihomo/mihomo-client-tcp.yaml | 2 +- .../mihomo/mihomo-client-udp-no-wait.yaml | 2 +- .../test/deploy/mihomo/mihomo-client-udp.yaml | 2 +- mieru/test/deploy/mihomo/test.sh | 10 +- mihomo/go.mod | 4 +- mihomo/go.sum | 8 +- openwrt-packages/filebrowser/Makefile | 4 +- openwrt-passwall/luci-app-passwall/Makefile | 2 +- .../view/passwall/node_list/node_list.htm | 165 ++++++++++++++---- small/gn/Makefile | 6 +- small/gn/src/out/last_commit_position.h | 4 +- small/luci-app-passwall/Makefile | 2 +- .../view/passwall/node_list/node_list.htm | 165 ++++++++++++++---- small/v2ray-geodata/Makefile | 4 +- xray-core/proxy/proxy.go | 68 +++++++- yt-dlp/.github/workflows/build.yml | 18 +- yt-dlp/pyproject.toml | 4 +- 98 files changed, 816 insertions(+), 373 deletions(-) create mode 100644 mieru/apis/common/conn.go create mode 100644 mieru/apis/common/conn_test.go rename mieru/{pkg => apis}/common/user_context.go (100%) diff --git a/.github/update.log b/.github/update.log index c484a31613..f171135561 100644 --- a/.github/update.log +++ b/.github/update.log @@ -1197,3 +1197,4 @@ Update On Wed Nov 26 19:35:47 CET 2025 Update On Thu Nov 27 19:38:17 CET 2025 Update On Fri Nov 28 19:37:50 CET 2025 Update On Sat Nov 29 19:37:01 CET 2025 +Update On Sun Nov 30 19:38:16 CET 2025 diff --git a/clash-meta/go.mod b/clash-meta/go.mod index aaf8890ccf..3ae50c987c 100644 --- a/clash-meta/go.mod +++ b/clash-meta/go.mod @@ -32,11 +32,11 @@ require ( github.com/metacubex/sing-shadowsocks v0.2.12 github.com/metacubex/sing-shadowsocks2 v0.2.7 github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 - github.com/metacubex/sing-tun v0.4.9 + github.com/metacubex/sing-tun v0.4.10 github.com/metacubex/sing-vmess v0.2.4 github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f github.com/metacubex/smux v0.0.0-20251111013112-03f8d12dafc1 - github.com/metacubex/tfo-go v0.0.0-20251024101424-368b42b59148 + github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443 github.com/metacubex/utls v1.8.3 github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f github.com/miekg/dns v1.1.63 // lastest version compatible with golang1.20 diff --git a/clash-meta/go.sum b/clash-meta/go.sum index 1186bda8f2..7d24c9c06b 100644 --- a/clash-meta/go.sum +++ b/clash-meta/go.sum @@ -131,16 +131,16 @@ github.com/metacubex/sing-shadowsocks2 v0.2.7 h1:hSuuc0YpsfiqYqt1o+fP4m34BQz4e6w github.com/metacubex/sing-shadowsocks2 v0.2.7/go.mod h1:vOEbfKC60txi0ca+yUlqEwOGc3Obl6cnSgx9Gf45KjE= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 h1:gXU+MYPm7Wme3/OAY2FFzVq9d9GxPHOqu5AQfg/ddhI= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2/go.mod h1:mbfboaXauKJNIHJYxQRa+NJs4JU9NZfkA+I33dS2+9E= -github.com/metacubex/sing-tun v0.4.9 h1:jY0Yyt8nnN3yQRN/jTxgqNCmGi1dsFdxdIi7pQUlVVU= -github.com/metacubex/sing-tun v0.4.9/go.mod h1:L/TjQY5JEGy8nvsuYmy/XgMFMCPiF0+AWSFCYfS6r9w= +github.com/metacubex/sing-tun v0.4.10 h1:DllQTERAcqQyiEl4L/R7Ia0jCiSzZzikw2kL8N85p0E= +github.com/metacubex/sing-tun v0.4.10/go.mod h1:L/TjQY5JEGy8nvsuYmy/XgMFMCPiF0+AWSFCYfS6r9w= github.com/metacubex/sing-vmess v0.2.4 h1:Tx6AGgCiEf400E/xyDuYyafsel6sGbR8oF7RkAaus6I= github.com/metacubex/sing-vmess v0.2.4/go.mod h1:21R5R1u90uUvBQF0owoooEu96/SAYYD56nDrwm6nFaM= github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f h1:Sr/DYKYofKHKc4GF3qkRGNuj6XA6c0eqPgEDN+VAsYU= github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f/go.mod h1:jpAkVLPnCpGSfNyVmj6Cq4YbuZsFepm/Dc+9BAOcR80= github.com/metacubex/smux v0.0.0-20251111013112-03f8d12dafc1 h1:a6DF0ze9miXes+rdwl8a4Wkvfpe0lXYU82sPJfDzz6s= github.com/metacubex/smux v0.0.0-20251111013112-03f8d12dafc1/go.mod h1:4bPD8HWx9jPJ9aE4uadgyN7D1/Wz3KmPy+vale8sKLE= -github.com/metacubex/tfo-go v0.0.0-20251024101424-368b42b59148 h1:Zd0QqciLIhv9MKbGKTPEgN8WUFsgQGA1WJBy6spEnVU= -github.com/metacubex/tfo-go v0.0.0-20251024101424-368b42b59148/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw= +github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443 h1:H6TnfM12tOoTizYE/qBHH3nEuibIelmHI+BVSxVJr8o= +github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw= github.com/metacubex/utls v1.8.3 h1:0m/yCxm3SK6kWve2lKiFb1pue1wHitJ8sQQD4Ikqde4= github.com/metacubex/utls v1.8.3/go.mod h1:kncGGVhFaoGn5M3pFe3SXhZCzsbCJayNOH4UEqTKTko= github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f h1:FGBPRb1zUabhPhDrlKEjQ9lgIwQ6cHL4x8M9lrERhbk= diff --git a/clash-nyanpasu/manifest/version.json b/clash-nyanpasu/manifest/version.json index c50c4e9f32..b10550bebf 100644 --- a/clash-nyanpasu/manifest/version.json +++ b/clash-nyanpasu/manifest/version.json @@ -2,7 +2,7 @@ "manifest_version": 1, "latest": { "mihomo": "v1.19.16", - "mihomo_alpha": "alpha-6cf1743", + "mihomo_alpha": "alpha-93de49d", "clash_rs": "v0.9.2", "clash_premium": "2023-09-05-gdcc8d87", "clash_rs_alpha": "0.9.2-alpha+sha.87c7b2c" @@ -69,5 +69,5 @@ "linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf" } }, - "updated_at": "2025-11-28T22:21:05.844Z" + "updated_at": "2025-11-29T22:21:10.978Z" } diff --git a/filebrowser/.github/workflows/docs.yml b/filebrowser/.github/workflows/docs.yml index 1f64177c52..5b21ccba79 100644 --- a/filebrowser/.github/workflows/docs.yml +++ b/filebrowser/.github/workflows/docs.yml @@ -28,9 +28,11 @@ jobs: if: github.event_name == 'push' && github.ref == 'refs/heads/master' name: Build and Release Docs permissions: - contents: read - deployments: write - pull-requests: write + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest timeout-minutes: 5 steps: @@ -42,11 +44,9 @@ jobs: uses: go-task/setup-task@v1 - name: Build site run: task docs - - name: Deploy to Cloudflare Pages - uses: cloudflare/wrangler-action@v3 + - name: Upload static files as artifact + uses: actions/upload-pages-artifact@v4 with: - apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} - accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} - command: pages deploy www/public --project-name=${{ secrets.CLOUDFLARE_PROJECT_NAME }} - gitHubToken: ${{ secrets.GITHUB_TOKEN }} - + path: www/public + - name: Deploy to GitHub Pages + uses: actions/deploy-pages@v4 diff --git a/filebrowser/CHANGELOG.md b/filebrowser/CHANGELOG.md index 49f40267a7..e9eef70a10 100644 --- a/filebrowser/CHANGELOG.md +++ b/filebrowser/CHANGELOG.md @@ -2,6 +2,21 @@ All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. +## [2.50.0](https://github.com/filebrowser/filebrowser/compare/v2.49.0...v2.50.0) (2025-11-30) + + +### Features + +* configurable logout page URL for proxy/hook auth ([#3884](https://github.com/filebrowser/filebrowser/issues/3884)) ([b9ac45d](https://github.com/filebrowser/filebrowser/commit/b9ac45d5dac4b4eb2ba364629090fbf306cffd2b)) +* render CSVs as table ([#5569](https://github.com/filebrowser/filebrowser/issues/5569)) ([982405e](https://github.com/filebrowser/filebrowser/commit/982405ec944f94baf43594b0ed2f06329ff4e9ed)) +* update frontend/src/i18n/hr.json ([279a5cc](https://github.com/filebrowser/filebrowser/commit/279a5ccd1e8d7bde4568b63cb3c506af48b6c618)) +* update translations ([78e0395](https://github.com/filebrowser/filebrowser/commit/78e039596070a3a9e643a693cc99960c69dcfe92)) + + +### Bug Fixes + +* do not close editor if save failed ([701522a](https://github.com/filebrowser/filebrowser/commit/701522a0600cfa542469540ed764630c0ba1a732)), closes [#5591](https://github.com/filebrowser/filebrowser/issues/5591) + ## [2.49.0](https://github.com/filebrowser/filebrowser/compare/v2.48.2...v2.49.0) (2025-11-22) diff --git a/filebrowser/cmd/config.go b/filebrowser/cmd/config.go index 550ab5c912..93ba29dfb3 100644 --- a/filebrowser/cmd/config.go +++ b/filebrowser/cmd/config.go @@ -45,6 +45,7 @@ func addConfigFlags(flags *pflag.FlagSet) { flags.String("auth.method", string(auth.MethodJSONAuth), "authentication type") flags.String("auth.header", "", "HTTP header for auth.method=proxy") flags.String("auth.command", "", "command for auth.method=hook") + flags.String("auth.logoutPage", "", "url of custom logout page") flags.String("recaptcha.host", "https://www.google.com", "use another host for ReCAPTCHA. recaptcha.net might be useful in China") flags.String("recaptcha.key", "", "ReCaptcha site key") @@ -201,6 +202,7 @@ func printSettings(ser *settings.Server, set *settings.Settings, auther auth.Aut fmt.Fprintf(w, "Sign up:\t%t\n", set.Signup) fmt.Fprintf(w, "Hide Login Button:\t%t\n", set.HideLoginButton) fmt.Fprintf(w, "Create User Dir:\t%t\n", set.CreateUserDir) + fmt.Fprintf(w, "Logout Page:\t%s\n", set.LogoutPage) fmt.Fprintf(w, "Minimum Password Length:\t%d\n", set.MinimumPasswordLength) fmt.Fprintf(w, "Auth Method:\t%s\n", set.AuthMethod) fmt.Fprintf(w, "Shell:\t%s\t\n", strings.Join(set.Shell, " ")) @@ -328,6 +330,8 @@ func getSettings(flags *pflag.FlagSet, set *settings.Settings, ser *settings.Ser set.DirMode, err = getAndParseFileMode(flags, flag.Name) case "auth.method": hasAuth = true + case "auth.logoutPage": + set.LogoutPage, err = flags.GetString(flag.Name) case "branding.name": set.Branding.Name, err = flags.GetString(flag.Name) case "branding.theme": diff --git a/filebrowser/frontend/index.html b/filebrowser/frontend/index.html index b3de680496..19308a9543 100644 --- a/filebrowser/frontend/index.html +++ b/filebrowser/frontend/index.html @@ -39,6 +39,7 @@ DisableUsedPercentage: false, EnableExec: true, EnableThumbs: true, + LogoutPage: "", LoginPage: true, Name: "", NoAuth: false, diff --git a/filebrowser/frontend/pnpm-lock.yaml b/filebrowser/frontend/pnpm-lock.yaml index 670e35fe9c..698416bbab 100644 --- a/filebrowser/frontend/pnpm-lock.yaml +++ b/filebrowser/frontend/pnpm-lock.yaml @@ -119,7 +119,7 @@ importers: version: 6.0.2(vite@7.2.4(@types/node@24.10.1)(terser@5.44.1)(yaml@2.7.0))(vue@3.5.25(typescript@5.9.3)) '@vue/eslint-config-prettier': specifier: ^10.2.0 - version: 10.2.0(eslint@9.39.1)(prettier@3.7.2) + version: 10.2.0(eslint@9.39.1)(prettier@3.7.3) '@vue/eslint-config-typescript': specifier: ^14.6.0 version: 14.6.0(eslint-plugin-vue@10.6.2(@typescript-eslint/parser@8.37.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(vue-eslint-parser@10.2.0(eslint@9.39.1)))(eslint@9.39.1)(typescript@5.9.3) @@ -137,7 +137,7 @@ importers: version: 10.1.8(eslint@9.39.1) eslint-plugin-prettier: specifier: ^5.5.1 - version: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.39.1))(eslint@9.39.1)(prettier@3.7.2) + version: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.39.1))(eslint@9.39.1)(prettier@3.7.3) eslint-plugin-vue: specifier: ^10.5.1 version: 10.6.2(@typescript-eslint/parser@8.37.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(vue-eslint-parser@10.2.0(eslint@9.39.1)) @@ -146,7 +146,7 @@ importers: version: 8.5.6 prettier: specifier: ^3.6.2 - version: 3.7.2 + version: 3.7.3 terser: specifier: ^5.43.1 version: 5.44.1 @@ -2167,8 +2167,8 @@ packages: resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} engines: {node: '>=6.0.0'} - prettier@3.7.2: - resolution: {integrity: sha512-n3HV2J6QhItCXndGa3oMWvWFAgN1ibnS7R9mt6iokScBOC0Ul9/iZORmU2IWUMcyAQaMPjTlY3uT34TqocUxMA==} + prettier@3.7.3: + resolution: {integrity: sha512-QgODejq9K3OzoBbuyobZlUhznP5SKwPqp+6Q6xw6o8gnhr4O85L2U915iM2IDcfF2NPXVaM9zlo9tdwipnYwzg==} engines: {node: '>=14'} hasBin: true @@ -3882,12 +3882,12 @@ snapshots: dependencies: rfdc: 1.4.1 - '@vue/eslint-config-prettier@10.2.0(eslint@9.39.1)(prettier@3.7.2)': + '@vue/eslint-config-prettier@10.2.0(eslint@9.39.1)(prettier@3.7.3)': dependencies: eslint: 9.39.1 eslint-config-prettier: 10.1.8(eslint@9.39.1) - eslint-plugin-prettier: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.39.1))(eslint@9.39.1)(prettier@3.7.2) - prettier: 3.7.2 + eslint-plugin-prettier: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.39.1))(eslint@9.39.1)(prettier@3.7.3) + prettier: 3.7.3 transitivePeerDependencies: - '@types/eslint' @@ -4219,10 +4219,10 @@ snapshots: dependencies: eslint: 9.39.1 - eslint-plugin-prettier@5.5.4(eslint-config-prettier@10.1.8(eslint@9.39.1))(eslint@9.39.1)(prettier@3.7.2): + eslint-plugin-prettier@5.5.4(eslint-config-prettier@10.1.8(eslint@9.39.1))(eslint@9.39.1)(prettier@3.7.3): dependencies: eslint: 9.39.1 - prettier: 3.7.2 + prettier: 3.7.3 prettier-linter-helpers: 1.0.0 synckit: 0.11.11 optionalDependencies: @@ -4697,7 +4697,7 @@ snapshots: dependencies: fast-diff: 1.3.0 - prettier@3.7.2: {} + prettier@3.7.3: {} pretty-bytes@7.1.0: {} diff --git a/filebrowser/frontend/src/components/Sidebar.vue b/filebrowser/frontend/src/components/Sidebar.vue index 531ec58342..c7961e3ece 100644 --- a/filebrowser/frontend/src/components/Sidebar.vue +++ b/filebrowser/frontend/src/components/Sidebar.vue @@ -129,6 +129,7 @@ import { disableExternal, disableUsedPercentage, noAuth, + logoutPage, loginPage, } from "@/utils/constants"; import { files as api } from "@/api"; @@ -159,7 +160,7 @@ export default { version: () => version, disableExternal: () => disableExternal, disableUsedPercentage: () => disableUsedPercentage, - canLogout: () => !noAuth && loginPage, + canLogout: () => !noAuth && (loginPage || logoutPage !== "/login"), }, methods: { ...mapActions(useLayoutStore, ["closeHovers", "showHover"]), diff --git a/filebrowser/frontend/src/components/files/CsvViewer.vue b/filebrowser/frontend/src/components/files/CsvViewer.vue index ad1e7e229f..180cf7e21a 100644 --- a/filebrowser/frontend/src/components/files/CsvViewer.vue +++ b/filebrowser/frontend/src/components/files/CsvViewer.vue @@ -8,12 +8,7 @@ description

{{ $t("files.lonely") }}

-
+
@@ -66,7 +61,11 @@ const displayError = computed(() => { return props.error; } // Check for parse errors - if (props.content && props.content.trim().length > 0 && data.value.headers.length === 0) { + if ( + props.content && + props.content.trim().length > 0 && + data.value.headers.length === 0 + ) { return "Failed to parse CSV file"; } return null; diff --git a/filebrowser/frontend/src/i18n/ar.json b/filebrowser/frontend/src/i18n/ar.json index 5e736eaabb..b316245819 100644 --- a/filebrowser/frontend/src/i18n/ar.json +++ b/filebrowser/frontend/src/i18n/ar.json @@ -43,7 +43,8 @@ "upload": "رفع", "openFile": "فتح الملف", "discardChanges": "إلغاء التغييرات", - "saveChanges": "Save changes" + "saveChanges": "Save changes", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "تحميل الملف", @@ -75,7 +76,9 @@ "sortByLastModified": "الترتيب بآخر تعديل", "sortByName": "الترتيب باﻹسم", "sortBySize": "الترتيب بالحجم", - "noPreview": "لا يوجد عرض مسبق لهذا الملف." + "noPreview": "لا يوجد عرض مسبق لهذا الملف.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "حدد الملف أو المجلد", diff --git a/filebrowser/frontend/src/i18n/bg.json b/filebrowser/frontend/src/i18n/bg.json index e71fa87b02..277df47f17 100644 --- a/filebrowser/frontend/src/i18n/bg.json +++ b/filebrowser/frontend/src/i18n/bg.json @@ -43,7 +43,8 @@ "upload": "Качи", "openFile": "Отвори файл", "discardChanges": "Изчисти", - "saveChanges": "Запиши промените" + "saveChanges": "Запиши промените", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "Свали файл", @@ -75,7 +76,9 @@ "sortByLastModified": "Подредба по последна промяна", "sortByName": "Подредба по име", "sortBySize": "Подредба по размер", - "noPreview": "За този файл не е наличен преглед." + "noPreview": "За този файл не е наличен преглед.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "избери файл или директория", diff --git a/filebrowser/frontend/src/i18n/ca.json b/filebrowser/frontend/src/i18n/ca.json index 9c23e6781c..6d7573aede 100644 --- a/filebrowser/frontend/src/i18n/ca.json +++ b/filebrowser/frontend/src/i18n/ca.json @@ -43,7 +43,8 @@ "upload": "Pujar", "openFile": "Obrir fitxer", "discardChanges": "Descartar", - "saveChanges": "Save changes" + "saveChanges": "Save changes", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "Descarregar fitxer", @@ -75,7 +76,9 @@ "sortByLastModified": "Ordenar per última modificació", "sortByName": "Ordenar per nom", "sortBySize": "Ordenar per mida", - "noPreview": "La vista prèvia no està disponible per a aquest fitxer." + "noPreview": "La vista prèvia no està disponible per a aquest fitxer.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "seleccionar fitxer o carpeta", diff --git a/filebrowser/frontend/src/i18n/cs.json b/filebrowser/frontend/src/i18n/cs.json index ba0119fcd6..7ff856a5aa 100644 --- a/filebrowser/frontend/src/i18n/cs.json +++ b/filebrowser/frontend/src/i18n/cs.json @@ -43,7 +43,8 @@ "upload": "Nahrát", "openFile": "Otevřít soubor", "discardChanges": "Zrušit změny", - "saveChanges": "Save changes" + "saveChanges": "Save changes", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "Stáhnout soubor", @@ -75,7 +76,9 @@ "sortByLastModified": "Seřadit podle poslední změny", "sortByName": "Seřadit podle názvu", "sortBySize": "Seřadit podle velikosti", - "noPreview": "Náhled pro tento soubor není k dispozici." + "noPreview": "Náhled pro tento soubor není k dispozici.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "vyberte soubor nebo adresář", diff --git a/filebrowser/frontend/src/i18n/de.json b/filebrowser/frontend/src/i18n/de.json index de34b6e210..623912f1be 100644 --- a/filebrowser/frontend/src/i18n/de.json +++ b/filebrowser/frontend/src/i18n/de.json @@ -43,7 +43,8 @@ "upload": "Upload", "openFile": "Datei öffnen", "discardChanges": "Verwerfen", - "saveChanges": "Save changes" + "saveChanges": "Save changes", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "Download Datei", @@ -75,7 +76,9 @@ "sortByLastModified": "Nach Änderungsdatum sortieren", "sortByName": "Nach Namen sortieren", "sortBySize": "Nach Größe sortieren", - "noPreview": "Für diese Datei ist keine Vorschau verfügbar." + "noPreview": "Für diese Datei ist keine Vorschau verfügbar.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "Wähle Datei oder Ordner", diff --git a/filebrowser/frontend/src/i18n/el.json b/filebrowser/frontend/src/i18n/el.json index 1826047c9c..8c661b1fb5 100644 --- a/filebrowser/frontend/src/i18n/el.json +++ b/filebrowser/frontend/src/i18n/el.json @@ -43,7 +43,8 @@ "upload": "Μεταφόρτωση", "openFile": "Άνοιγμα αρχείου", "discardChanges": "Discard", - "saveChanges": "Save changes" + "saveChanges": "Save changes", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "Λήψη αρχείου", @@ -75,7 +76,9 @@ "sortByLastModified": "Ταξινόμηση κατά πρόσφατη τροποποίηση", "sortByName": "Ταξινόμηση κατά όνομα", "sortBySize": "Ταξινόμηση κατά μέγεθος", - "noPreview": "Η προεπισκόπηση δεν είναι διαθέσιμη για αυτό το αρχείο." + "noPreview": "Η προεπισκόπηση δεν είναι διαθέσιμη για αυτό το αρχείο.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "επιλέξτε αρχείο ή φάκελο", diff --git a/filebrowser/frontend/src/i18n/es.json b/filebrowser/frontend/src/i18n/es.json index 2ad3e6fd2b..d1ca875fd0 100644 --- a/filebrowser/frontend/src/i18n/es.json +++ b/filebrowser/frontend/src/i18n/es.json @@ -43,7 +43,8 @@ "upload": "Subir", "openFile": "Abrir archivo", "discardChanges": "Discard", - "saveChanges": "Guardar cambios" + "saveChanges": "Guardar cambios", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "Descargar fichero", @@ -75,7 +76,9 @@ "sortByLastModified": "Ordenar por última modificación", "sortByName": "Ordenar por nombre", "sortBySize": "Ordenar por tamaño", - "noPreview": "La vista previa no está disponible para este archivo." + "noPreview": "La vista previa no está disponible para este archivo.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "seleccionar archivo o carpeta", diff --git a/filebrowser/frontend/src/i18n/fa.json b/filebrowser/frontend/src/i18n/fa.json index db61992483..d71b640616 100644 --- a/filebrowser/frontend/src/i18n/fa.json +++ b/filebrowser/frontend/src/i18n/fa.json @@ -43,7 +43,8 @@ "upload": "آپلود", "openFile": "باز کردن فایل", "discardChanges": "لغو کردن", - "saveChanges": "Save changes" + "saveChanges": "Save changes", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "دانلود فایل", @@ -75,7 +76,9 @@ "sortByLastModified": "مرتب سازی آخرین ویرایش", "sortByName": "مرتب سازی نام", "sortBySize": "مرتب سازی اندازه", - "noPreview": "این فایل قابل نمایش نیست" + "noPreview": "این فایل قابل نمایش نیست", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "انتخاب فایل یا پوشه", diff --git a/filebrowser/frontend/src/i18n/fr.json b/filebrowser/frontend/src/i18n/fr.json index b9bba59a7f..2125dd8737 100644 --- a/filebrowser/frontend/src/i18n/fr.json +++ b/filebrowser/frontend/src/i18n/fr.json @@ -43,7 +43,8 @@ "upload": "Importer", "openFile": "Ouvrir le fichier", "discardChanges": "Annuler", - "saveChanges": "Save changes" + "saveChanges": "Save changes", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "Télécharger le fichier", @@ -75,7 +76,9 @@ "sortByLastModified": "Trier par date de modification", "sortByName": "Trier par nom", "sortBySize": "Trier par taille", - "noPreview": "L'aperçu n'est pas disponible pour ce fichier." + "noPreview": "L'aperçu n'est pas disponible pour ce fichier.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "Sélectionner un fichier ou dossier", diff --git a/filebrowser/frontend/src/i18n/he.json b/filebrowser/frontend/src/i18n/he.json index 29bc684226..2ea11e976a 100644 --- a/filebrowser/frontend/src/i18n/he.json +++ b/filebrowser/frontend/src/i18n/he.json @@ -43,7 +43,8 @@ "upload": "העלאה", "openFile": "פתח קובץ", "discardChanges": "זריקת השינויים", - "saveChanges": "Save changes" + "saveChanges": "Save changes", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "הורד קובץ", @@ -75,7 +76,9 @@ "sortByLastModified": "מיין לפי השינוי האחרון", "sortByName": "מיין לפי שם", "sortBySize": "מיין לפי גודל", - "noPreview": "לא זמינה תצוגה מקדימה לקובץ זה" + "noPreview": "לא זמינה תצוגה מקדימה לקובץ זה", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "בחר קובץ או תיקייה", diff --git a/filebrowser/frontend/src/i18n/hr.json b/filebrowser/frontend/src/i18n/hr.json index e466a5ede3..e81efe4001 100644 --- a/filebrowser/frontend/src/i18n/hr.json +++ b/filebrowser/frontend/src/i18n/hr.json @@ -43,7 +43,8 @@ "upload": "Prenesi", "openFile": "Otvori datoteku", "discardChanges": "Odbaci", - "saveChanges": "Spremi promjene" + "saveChanges": "Spremi promjene", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "Preuzmi Datoteku", @@ -75,7 +76,9 @@ "sortByLastModified": "Sortiraj po zadnjoj izmjeni", "sortByName": "Sortiraj po nazivu", "sortBySize": "Sortiraj po veličini", - "noPreview": "Pregled nije dostupan za ovu datoteku." + "noPreview": "Pregled nije dostupan za ovu datoteku.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "odaberi datoteku ili mapu", diff --git a/filebrowser/frontend/src/i18n/hu.json b/filebrowser/frontend/src/i18n/hu.json index 565fb076d4..ff22287c33 100644 --- a/filebrowser/frontend/src/i18n/hu.json +++ b/filebrowser/frontend/src/i18n/hu.json @@ -43,7 +43,8 @@ "upload": "Feltöltés", "openFile": "Fájl megnyitása", "discardChanges": "Discard", - "saveChanges": "Save changes" + "saveChanges": "Save changes", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "Fájl letöltése", @@ -75,7 +76,9 @@ "sortByLastModified": "Rendezés utolsó módosítás szerint", "sortByName": "Rendezés név szerint", "sortBySize": "Rendezés méret szerint", - "noPreview": "Ehhez a fájlhoz nincs előnézet." + "noPreview": "Ehhez a fájlhoz nincs előnézet.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "mappa vagy fájl kijelölése", diff --git a/filebrowser/frontend/src/i18n/is.json b/filebrowser/frontend/src/i18n/is.json index ac114dc9c0..37767678e4 100644 --- a/filebrowser/frontend/src/i18n/is.json +++ b/filebrowser/frontend/src/i18n/is.json @@ -43,7 +43,8 @@ "upload": "Hlaða upp", "openFile": "Open file", "discardChanges": "Discard", - "saveChanges": "Save changes" + "saveChanges": "Save changes", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "Sækja skjal", @@ -75,7 +76,9 @@ "sortByLastModified": "Flokka eftir Seinast breytt", "sortByName": "Flokka eftir nafni", "sortBySize": "Flokka eftir stærð", - "noPreview": "Preview is not available for this file." + "noPreview": "Preview is not available for this file.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "velja skjal eða möppu", diff --git a/filebrowser/frontend/src/i18n/it.json b/filebrowser/frontend/src/i18n/it.json index 50170b7034..9efd046129 100644 --- a/filebrowser/frontend/src/i18n/it.json +++ b/filebrowser/frontend/src/i18n/it.json @@ -43,7 +43,8 @@ "upload": "Carica", "openFile": "Apri file", "discardChanges": "Ignora", - "saveChanges": "Save changes" + "saveChanges": "Save changes", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "Scarica file", @@ -75,7 +76,9 @@ "sortByLastModified": "Ordina per ultima modifica", "sortByName": "Ordina per nome", "sortBySize": "Ordina per dimensione", - "noPreview": "L'anteprima non è disponibile per questo file." + "noPreview": "L'anteprima non è disponibile per questo file.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "seleziona un file o una cartella", diff --git a/filebrowser/frontend/src/i18n/ja.json b/filebrowser/frontend/src/i18n/ja.json index 870d38c722..d1a6bcc74c 100644 --- a/filebrowser/frontend/src/i18n/ja.json +++ b/filebrowser/frontend/src/i18n/ja.json @@ -43,7 +43,8 @@ "upload": "アップロード", "openFile": "ファイルを開く", "discardChanges": "Discard", - "saveChanges": "Save changes" + "saveChanges": "Save changes", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "ファイルのダウンロード", @@ -75,7 +76,9 @@ "sortByLastModified": "更新日時で並べ替え", "sortByName": "名前で並べ替え", "sortBySize": "サイズで並べ替え", - "noPreview": "プレビューはこのファイルでは利用できません" + "noPreview": "プレビューはこのファイルでは利用できません", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "ファイルやフォルダーを選択", diff --git a/filebrowser/frontend/src/i18n/ko.json b/filebrowser/frontend/src/i18n/ko.json index cae58cae9b..0c5d016570 100644 --- a/filebrowser/frontend/src/i18n/ko.json +++ b/filebrowser/frontend/src/i18n/ko.json @@ -43,7 +43,8 @@ "upload": "업로드", "openFile": "파일 열기", "discardChanges": "변경 사항 취소", - "saveChanges": "변경사항 저장" + "saveChanges": "변경사항 저장", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "파일 다운로드", @@ -75,7 +76,9 @@ "sortByLastModified": "수정시간순 정렬", "sortByName": "이름순", "sortBySize": "크기순", - "noPreview": "미리 보기가 지원되지 않는 파일 유형입니다." + "noPreview": "미리 보기가 지원되지 않는 파일 유형입니다.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "파일이나 디렉토리를 선택해주세요.", diff --git a/filebrowser/frontend/src/i18n/nl-be.json b/filebrowser/frontend/src/i18n/nl-be.json index 83bf3ce045..13aedf3d51 100644 --- a/filebrowser/frontend/src/i18n/nl-be.json +++ b/filebrowser/frontend/src/i18n/nl-be.json @@ -43,7 +43,8 @@ "upload": "Uploaden", "openFile": "Open file", "discardChanges": "Discard", - "saveChanges": "Save changes" + "saveChanges": "Save changes", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "Bestand downloaden", @@ -75,7 +76,9 @@ "sortByLastModified": "Sorteren op laatst bewerkt", "sortByName": "Sorteren op naam", "sortBySize": "Sorteren op grootte", - "noPreview": "Preview is not available for this file." + "noPreview": "Preview is not available for this file.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "selecteer bestand of map", diff --git a/filebrowser/frontend/src/i18n/no.json b/filebrowser/frontend/src/i18n/no.json index 918ef19fc6..1017f75a76 100644 --- a/filebrowser/frontend/src/i18n/no.json +++ b/filebrowser/frontend/src/i18n/no.json @@ -43,7 +43,8 @@ "upload": "Last opp", "openFile": "Open file", "discardChanges": "Slett", - "saveChanges": "Lagre Endringane " + "saveChanges": "Lagre Endringane ", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "Nedlast filen", @@ -75,7 +76,9 @@ "sortByLastModified": "Sorter etter sist endret", "sortByName": "Sorter etter navn", "sortBySize": "Sorter etter størrelse", - "noPreview": "Forhåndsvisning er ikkje tilgjengeleg for denne filen." + "noPreview": "Forhåndsvisning er ikkje tilgjengeleg for denne filen.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "velg fil eller katalog", diff --git a/filebrowser/frontend/src/i18n/pl.json b/filebrowser/frontend/src/i18n/pl.json index 177909352c..11c792153a 100644 --- a/filebrowser/frontend/src/i18n/pl.json +++ b/filebrowser/frontend/src/i18n/pl.json @@ -43,7 +43,8 @@ "upload": "Wyślij", "openFile": "Otwórz plik", "discardChanges": "Odrzuć", - "saveChanges": "Zapisz zmiany" + "saveChanges": "Zapisz zmiany", + "editAsText": "Edytuj jako tekst" }, "download": { "downloadFile": "Pobierz plik", @@ -75,7 +76,9 @@ "sortByLastModified": "Sortuj wg ostatniej modyfikacji", "sortByName": "Sortuj wg nazwy", "sortBySize": "Sortuj wg rozmiaru", - "noPreview": "Podgląd tego pliku jest niedostępny." + "noPreview": "Podgląd tego pliku jest niedostępny.", + "csvTooLarge": "Plik CSV jest za duży do podglądu (>5 MB). Pobierz, aby wyświetlić.", + "csvLoadFailed": "Nie udało się załadować pliku CSV." }, "help": { "click": "zaznacz plik lub folder", diff --git a/filebrowser/frontend/src/i18n/pt-br.json b/filebrowser/frontend/src/i18n/pt-br.json index f6ef04e62b..94562d11a1 100644 --- a/filebrowser/frontend/src/i18n/pt-br.json +++ b/filebrowser/frontend/src/i18n/pt-br.json @@ -43,7 +43,8 @@ "upload": "Enviar", "openFile": "Abrir", "discardChanges": "Discard", - "saveChanges": "Save changes" + "saveChanges": "Save changes", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "Baixar arquivo", @@ -75,7 +76,9 @@ "sortByLastModified": "Ordenar pela última modificação", "sortByName": "Ordenar pelo nome", "sortBySize": "Ordenar pelo tamanho", - "noPreview": "Pré-visualização não disponível para este arquivo." + "noPreview": "Pré-visualização não disponível para este arquivo.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "selecionar pasta ou arquivo", diff --git a/filebrowser/frontend/src/i18n/pt.json b/filebrowser/frontend/src/i18n/pt.json index 38e5f89b7e..07558b5cf7 100644 --- a/filebrowser/frontend/src/i18n/pt.json +++ b/filebrowser/frontend/src/i18n/pt.json @@ -43,7 +43,8 @@ "upload": "Enviar", "openFile": "Open file", "discardChanges": "Discard", - "saveChanges": "Save changes" + "saveChanges": "Save changes", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "Descarregar ficheiro", @@ -75,7 +76,9 @@ "sortByLastModified": "Ordenar pela última alteração", "sortByName": "Ordenar pelo nome", "sortBySize": "Ordenar pelo tamanho", - "noPreview": "Preview is not available for this file." + "noPreview": "Preview is not available for this file.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "selecionar pasta ou ficheiro", diff --git a/filebrowser/frontend/src/i18n/ro.json b/filebrowser/frontend/src/i18n/ro.json index a2072b2eb0..78781cebb3 100644 --- a/filebrowser/frontend/src/i18n/ro.json +++ b/filebrowser/frontend/src/i18n/ro.json @@ -43,7 +43,8 @@ "upload": "Încarcă", "openFile": "Open file", "discardChanges": "Discard", - "saveChanges": "Save changes" + "saveChanges": "Save changes", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "Descarcă fișier", @@ -75,7 +76,9 @@ "sortByLastModified": "Ordonează dup ultima modificare", "sortByName": "Ordonează după nume", "sortBySize": "Ordonează după dimensiune", - "noPreview": "Preview is not available for this file." + "noPreview": "Preview is not available for this file.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "alege fișier sau director", diff --git a/filebrowser/frontend/src/i18n/ru.json b/filebrowser/frontend/src/i18n/ru.json index 1cadeb3b07..5b80a3eea7 100644 --- a/filebrowser/frontend/src/i18n/ru.json +++ b/filebrowser/frontend/src/i18n/ru.json @@ -43,7 +43,8 @@ "upload": "Загрузить", "openFile": "Открыть файл", "discardChanges": "Отказаться", - "saveChanges": "Save changes" + "saveChanges": "Save changes", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "Скачать файл", @@ -75,7 +76,9 @@ "sortByLastModified": "Сортировка по дате изменения", "sortByName": "Сортировка по имени", "sortBySize": "Сортировка по размеру", - "noPreview": "Предварительный просмотр для этого файла недоступен." + "noPreview": "Предварительный просмотр для этого файла недоступен.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "выбрать файл или каталог", diff --git a/filebrowser/frontend/src/i18n/sk.json b/filebrowser/frontend/src/i18n/sk.json index 9cb1c94115..0790bec6cd 100644 --- a/filebrowser/frontend/src/i18n/sk.json +++ b/filebrowser/frontend/src/i18n/sk.json @@ -43,7 +43,8 @@ "upload": "Nahrať", "openFile": "Otvoriť súbor", "discardChanges": "Zahodiť", - "saveChanges": "Uložiť zmeny" + "saveChanges": "Uložiť zmeny", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "Stiahnuť súbor", @@ -75,7 +76,9 @@ "sortByLastModified": "Zoradiť podľa dátumu", "sortByName": "Zoradiť podľa názvu", "sortBySize": "Zoradiť podľa veľkosti", - "noPreview": "Pre tento súbor nie je dostupný náhľad." + "noPreview": "Pre tento súbor nie je dostupný náhľad.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "vyberie súbor alebo priečinok", diff --git a/filebrowser/frontend/src/i18n/sv-se.json b/filebrowser/frontend/src/i18n/sv-se.json index 4cced166a2..eb2cf7d23d 100644 --- a/filebrowser/frontend/src/i18n/sv-se.json +++ b/filebrowser/frontend/src/i18n/sv-se.json @@ -43,7 +43,8 @@ "upload": "Ladda upp", "openFile": "Öppna fil", "discardChanges": "Förkasta", - "saveChanges": "Spara ändringar" + "saveChanges": "Spara ändringar", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "Ladda ner fil", @@ -75,7 +76,9 @@ "sortByLastModified": "Sortera på senast ändrad", "sortByName": "Sortera på namn", "sortBySize": "Sortera på storlek", - "noPreview": "Förhandsvisning är inte tillgänglig för denna fil." + "noPreview": "Förhandsvisning är inte tillgänglig för denna fil.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "välj fil eller mapp", diff --git a/filebrowser/frontend/src/i18n/tr.json b/filebrowser/frontend/src/i18n/tr.json index 144cf73d29..7674c047ae 100644 --- a/filebrowser/frontend/src/i18n/tr.json +++ b/filebrowser/frontend/src/i18n/tr.json @@ -43,7 +43,8 @@ "upload": "Yükle", "openFile": "Dosyayı aç", "discardChanges": "Discard", - "saveChanges": "Save changes" + "saveChanges": "Save changes", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "Dosyayı indir", @@ -75,7 +76,9 @@ "sortByLastModified": "Güncelleme tarihine göre sırala", "sortByName": "İsme göre sırala", "sortBySize": "Boyuta göre sırala", - "noPreview": "Bu dosya için önizleme aktif değil" + "noPreview": "Bu dosya için önizleme aktif değil", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "dosya veya klasör seçin", diff --git a/filebrowser/frontend/src/i18n/uk.json b/filebrowser/frontend/src/i18n/uk.json index 465c0364ec..bb383674c2 100644 --- a/filebrowser/frontend/src/i18n/uk.json +++ b/filebrowser/frontend/src/i18n/uk.json @@ -43,7 +43,8 @@ "upload": "Вивантажити", "openFile": "Відкрити файл", "discardChanges": "Скасувати", - "saveChanges": "Save changes" + "saveChanges": "Save changes", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "Завантажити файл", @@ -75,7 +76,9 @@ "sortByLastModified": "Сортувати за останнім зміненням", "sortByName": "Сортувати за іменем", "sortBySize": "Сортувати за розміром", - "noPreview": "Попередній перегляд для цього файлу недоступний." + "noPreview": "Попередній перегляд для цього файлу недоступний.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "вибрати файл чи каталог", diff --git a/filebrowser/frontend/src/i18n/vi.json b/filebrowser/frontend/src/i18n/vi.json index 77e7655ecf..a1b440b94c 100644 --- a/filebrowser/frontend/src/i18n/vi.json +++ b/filebrowser/frontend/src/i18n/vi.json @@ -43,7 +43,8 @@ "upload": "Tải lên", "openFile": "Mở tệp", "discardChanges": "Hủy bỏ thay đổi", - "saveChanges": "Save changes" + "saveChanges": "Save changes", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "Tải xuống tệp tin", @@ -75,7 +76,9 @@ "sortByLastModified": "Sắp xếp theo ngày sửa đổi", "sortByName": "Sắp xếp theo tên", "sortBySize": "Sắp xếp theo kích thước", - "noPreview": "Không có bản xem trước cho tập tin này." + "noPreview": "Không có bản xem trước cho tập tin này.", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "chọn tập tin hoặc thư mục", diff --git a/filebrowser/frontend/src/i18n/zh-cn.json b/filebrowser/frontend/src/i18n/zh-cn.json index fd927ce327..a2e16aaf50 100644 --- a/filebrowser/frontend/src/i18n/zh-cn.json +++ b/filebrowser/frontend/src/i18n/zh-cn.json @@ -43,7 +43,8 @@ "upload": "上传", "openFile": "打开文件", "discardChanges": "放弃更改", - "saveChanges": "Save changes" + "saveChanges": "Save changes", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "下载文件", @@ -75,7 +76,9 @@ "sortByLastModified": "按最后修改时间排序", "sortByName": "按名称排序", "sortBySize": "按大小排序", - "noPreview": "此文件无法预览。" + "noPreview": "此文件无法预览。", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "选择文件或文件夹", diff --git a/filebrowser/frontend/src/i18n/zh-tw.json b/filebrowser/frontend/src/i18n/zh-tw.json index 3682852288..c66fd85234 100644 --- a/filebrowser/frontend/src/i18n/zh-tw.json +++ b/filebrowser/frontend/src/i18n/zh-tw.json @@ -43,7 +43,8 @@ "upload": "上傳", "openFile": "開啟檔案", "discardChanges": "放棄變更", - "saveChanges": "Save changes" + "saveChanges": "Save changes", + "editAsText": "Edit as Text" }, "download": { "downloadFile": "下載檔案", @@ -75,7 +76,9 @@ "sortByLastModified": "按最後修改時間排序", "sortByName": "按名稱排序", "sortBySize": "按大小排序", - "noPreview": "此檔案無法預覽。" + "noPreview": "此檔案無法預覽。", + "csvTooLarge": "CSV file is too large for preview (>5MB). Please download to view.", + "csvLoadFailed": "Failed to load CSV file." }, "help": { "click": "選擇檔案或目錄", diff --git a/filebrowser/frontend/src/utils/auth.ts b/filebrowser/frontend/src/utils/auth.ts index dcd1cdc5e2..e75714f241 100644 --- a/filebrowser/frontend/src/utils/auth.ts +++ b/filebrowser/frontend/src/utils/auth.ts @@ -2,7 +2,7 @@ import { useAuthStore } from "@/stores/auth"; import router from "@/router"; import type { JwtPayload } from "jwt-decode"; import { jwtDecode } from "jwt-decode"; -import { baseURL, noAuth } from "./constants"; +import { authMethod, baseURL, noAuth, logoutPage } from "./constants"; import { StatusError } from "@/api/utils"; import { setSafeTimeout } from "@/api/utils"; @@ -18,6 +18,12 @@ export function parseToken(token: string) { authStore.jwt = token; authStore.setUser(data.user); + // proxy auth with custom logout subject to unknown external timeout + if (logoutPage !== "/login" && authMethod === "proxy") { + console.warn("idle timeout disabled with proxy auth and custom logout"); + return; + } + if (authStore.logoutTimer) { clearTimeout(authStore.logoutTimer); } @@ -118,6 +124,8 @@ export function logout(reason?: string) { localStorage.setItem("jwt", ""); if (noAuth) { window.location.reload(); + } else if (logoutPage !== "/login") { + document.location.href = `${logoutPage}`; } else { if (typeof reason === "string" && reason.trim() !== "") { router.push({ diff --git a/filebrowser/frontend/src/utils/constants.ts b/filebrowser/frontend/src/utils/constants.ts index ae491397d6..0580205a4d 100644 --- a/filebrowser/frontend/src/utils/constants.ts +++ b/filebrowser/frontend/src/utils/constants.ts @@ -10,6 +10,7 @@ const version: string = window.FileBrowser.Version; const logoURL = `${staticURL}/img/logo.svg`; const noAuth: boolean = window.FileBrowser.NoAuth; const authMethod = window.FileBrowser.AuthMethod; +const logoutPage: string = window.FileBrowser.LogoutPage; const loginPage: boolean = window.FileBrowser.LoginPage; const theme: UserTheme = window.FileBrowser.Theme; const enableThumbs: boolean = window.FileBrowser.EnableThumbs; @@ -32,6 +33,7 @@ export { version, noAuth, authMethod, + logoutPage, loginPage, theme, enableThumbs, diff --git a/filebrowser/frontend/src/views/files/Editor.vue b/filebrowser/frontend/src/views/files/Editor.vue index 0913ea9826..58f0d52451 100644 --- a/filebrowser/frontend/src/views/files/Editor.vue +++ b/filebrowser/frontend/src/views/files/Editor.vue @@ -186,7 +186,7 @@ const handlePageChange = (event: BeforeUnloadEvent) => { } }; -const save = async () => { +const save = async (throwError?: boolean) => { const button = "save"; buttons.loading("save"); @@ -197,6 +197,7 @@ const save = async () => { } catch (e: any) { buttons.done(button); $showError(e); + if (throwError) throw e; } }; @@ -223,8 +224,10 @@ const close = () => { finishClose(); }, saveAction: async () => { - await save(); - finishClose(); + try { + await save(true); + finishClose(); + } catch {} }, }); return; diff --git a/filebrowser/http/auth.go b/filebrowser/http/auth.go index 2e4518f089..4c052a5c15 100644 --- a/filebrowser/http/auth.go +++ b/filebrowser/http/auth.go @@ -12,7 +12,9 @@ import ( "github.com/golang-jwt/jwt/v5" "github.com/golang-jwt/jwt/v5/request" + fbAuth "github.com/filebrowser/filebrowser/v2/auth" fbErrors "github.com/filebrowser/filebrowser/v2/errors" + "github.com/filebrowser/filebrowser/v2/settings" "github.com/filebrowser/filebrowser/v2/users" ) @@ -61,6 +63,22 @@ func (e extractor) ExtractToken(r *http.Request) (string, error) { return "", request.ErrNoTokenInRequest } +func renewableErr(err error, d *data) bool { + if d.settings.AuthMethod != fbAuth.MethodProxyAuth || err == nil { + return false + } + + if d.settings.LogoutPage == settings.DefaultLogoutPage { + return false + } + + if !errors.Is(err, jwt.ErrTokenExpired) { + return false + } + + return true +} + func withUser(fn handleFunc) handleFunc { return func(w http.ResponseWriter, r *http.Request, d *data) (int, error) { keyFunc := func(_ *jwt.Token) (interface{}, error) { @@ -68,13 +86,9 @@ func withUser(fn handleFunc) handleFunc { } var tk authToken - token, err := request.ParseFromRequest(r, &extractor{}, keyFunc, request.WithClaims(&tk)) - if err != nil || !token.Valid { - return http.StatusUnauthorized, nil - } - - err = jwt.NewValidator(jwt.WithExpirationRequired()).Validate(tk) - if err != nil { + p := jwt.NewParser(jwt.WithValidMethods([]string{jwt.SigningMethodHS256.Alg()}), jwt.WithExpirationRequired()) + token, err := request.ParseFromRequest(r, &extractor{}, keyFunc, request.WithClaims(&tk), request.WithParser(p)) + if (err != nil || !token.Valid) && !renewableErr(err, d) { return http.StatusUnauthorized, nil } diff --git a/filebrowser/http/static.go b/filebrowser/http/static.go index be2c135cbf..b8883c4ebe 100644 --- a/filebrowser/http/static.go +++ b/filebrowser/http/static.go @@ -38,6 +38,7 @@ func handleWithStaticData(w http.ResponseWriter, _ *http.Request, d *data, fSys "Signup": d.settings.Signup, "NoAuth": d.settings.AuthMethod == auth.MethodNoAuth, "AuthMethod": d.settings.AuthMethod, + "LogoutPage": d.settings.LogoutPage, "LoginPage": auther.LoginPage(), "CSS": false, "ReCaptcha": false, diff --git a/filebrowser/settings/settings.go b/filebrowser/settings/settings.go index c263bf363d..6bcc36f8e3 100644 --- a/filebrowser/settings/settings.go +++ b/filebrowser/settings/settings.go @@ -11,6 +11,7 @@ import ( ) const DefaultUsersHomeBasePath = "/users" +const DefaultLogoutPage = "/login" const DefaultMinimumPasswordLength = 12 const DefaultFileMode = 0640 const DefaultDirMode = 0750 @@ -27,6 +28,7 @@ type Settings struct { UserHomeBasePath string `json:"userHomeBasePath"` Defaults UserDefaults `json:"defaults"` AuthMethod AuthMethod `json:"authMethod"` + LogoutPage string `json:"logoutPage"` Branding Branding `json:"branding"` Tus Tus `json:"tus"` Commands map[string][]string `json:"commands"` diff --git a/filebrowser/settings/storage.go b/filebrowser/settings/storage.go index d401996d4a..8bf11a64b4 100644 --- a/filebrowser/settings/storage.go +++ b/filebrowser/settings/storage.go @@ -30,24 +30,34 @@ func (s *Storage) Get() (*Settings, error) { if err != nil { return nil, err } + if set.UserHomeBasePath == "" { set.UserHomeBasePath = DefaultUsersHomeBasePath } + + if set.LogoutPage == "" { + set.LogoutPage = DefaultLogoutPage + } + if set.MinimumPasswordLength == 0 { set.MinimumPasswordLength = DefaultMinimumPasswordLength } + if set.Tus == (Tus{}) { set.Tus = Tus{ ChunkSize: DefaultTusChunkSize, RetryCount: DefaultTusRetryCount, } } + if set.FileMode == 0 { set.FileMode = DefaultFileMode } + if set.DirMode == 0 { set.DirMode = DefaultDirMode } + return set, nil } diff --git a/filebrowser/www/docs/cli/filebrowser-config-init.md b/filebrowser/www/docs/cli/filebrowser-config-init.md index 6ea484e64a..1029890f91 100644 --- a/filebrowser/www/docs/cli/filebrowser-config-init.md +++ b/filebrowser/www/docs/cli/filebrowser-config-init.md @@ -21,6 +21,7 @@ filebrowser config init [flags] -a, --address string address to listen on (default "127.0.0.1") --auth.command string command for auth.method=hook --auth.header string HTTP header for auth.method=proxy + --auth.logoutPage string url of custom logout page --auth.method string authentication type (default "json") -b, --baseURL string base url --branding.color string set the theme color diff --git a/filebrowser/www/docs/cli/filebrowser-config-set.md b/filebrowser/www/docs/cli/filebrowser-config-set.md index 93515ab403..3cacdceff5 100644 --- a/filebrowser/www/docs/cli/filebrowser-config-set.md +++ b/filebrowser/www/docs/cli/filebrowser-config-set.md @@ -18,6 +18,7 @@ filebrowser config set [flags] -a, --address string address to listen on (default "127.0.0.1") --auth.command string command for auth.method=hook --auth.header string HTTP header for auth.method=proxy + --auth.logoutPage string url of custom logout page --auth.method string authentication type (default "json") -b, --baseURL string base url --branding.color string set the theme color diff --git a/mieru/Makefile b/mieru/Makefile index eebdad1425..11108d3425 100644 --- a/mieru/Makefile +++ b/mieru/Makefile @@ -32,7 +32,7 @@ PROJECT_NAME=$(shell basename "${ROOT}") # - pkg/version/current.go # # Use `tools/bump_version.sh` script to change all those files at one shot. -VERSION="3.24.1" +VERSION="3.25.0" # With .ONESHELL, each recipe is executed in a single shell instance. # This allows `cd` to affect subsequent commands in the same recipe. diff --git a/mieru/apis/common/conn.go b/mieru/apis/common/conn.go new file mode 100644 index 0000000000..c384a3e779 --- /dev/null +++ b/mieru/apis/common/conn.go @@ -0,0 +1,72 @@ +// Copyright (C) 2025 mieru authors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package common + +import ( + "net" + "sync" +) + +// HierarchyConn closes all child connections when this connection is closed. +type HierarchyConn interface { + net.Conn + + // Add attach a child connection to this connection. + // The child connection is closed when this connection close. + Add(conn net.Conn) +} + +type hierarchyConn struct { + net.Conn + subConnetions []HierarchyConn + mu sync.Mutex +} + +var ( + _ HierarchyConn = (*hierarchyConn)(nil) + _ UserContext = (*hierarchyConn)(nil) +) + +func (h *hierarchyConn) Close() error { + h.mu.Lock() + defer h.mu.Unlock() + for _, sub := range h.subConnetions { + if sub != nil { + sub.Close() + } + } + return h.Conn.Close() +} + +func (h *hierarchyConn) Add(conn net.Conn) { + h.mu.Lock() + defer h.mu.Unlock() + h.subConnetions = append(h.subConnetions, WrapHierarchyConn(conn)) +} + +func (h *hierarchyConn) UserName() string { + h.mu.Lock() + defer h.mu.Unlock() + if userCtx, ok := h.Conn.(UserContext); ok { + return userCtx.UserName() + } + return "" +} + +// WrapHierarchyConn wraps an existing connection with HierarchyConn. +func WrapHierarchyConn(conn net.Conn) HierarchyConn { + return &hierarchyConn{Conn: conn} +} diff --git a/mieru/apis/common/conn_test.go b/mieru/apis/common/conn_test.go new file mode 100644 index 0000000000..f49d899566 --- /dev/null +++ b/mieru/apis/common/conn_test.go @@ -0,0 +1,43 @@ +// Copyright (C) 2025 mieru authors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package common_test + +import ( + "net" + "testing" + + "github.com/enfein/mieru/v3/apis/common" +) + +type counterCloser struct { + net.Conn + Counter *int +} + +func (cc counterCloser) Close() error { + *cc.Counter = *cc.Counter + 1 + return nil +} + +func TestHierarchyConn(t *testing.T) { + counter := 0 + parent := common.WrapHierarchyConn(counterCloser{Conn: nil, Counter: &counter}) + parent.Add(counterCloser{Conn: nil, Counter: &counter}) + parent.Close() + if counter != 2 { + t.Errorf("counter = %d, want %d", counter, 2) + } +} diff --git a/mieru/pkg/common/user_context.go b/mieru/apis/common/user_context.go similarity index 100% rename from mieru/pkg/common/user_context.go rename to mieru/apis/common/user_context.go diff --git a/mieru/apis/server/interface.go b/mieru/apis/server/interface.go index 31d89b95ea..9bf1bd0279 100644 --- a/mieru/apis/server/interface.go +++ b/mieru/apis/server/interface.go @@ -72,6 +72,8 @@ type ServerNetworkService interface { // Accept accepts a new proxy connection from a client. // It returns the proxy connection and the socks5 request sent by the client. // Additional handshake is required with the returned proxy connection. + // + // The returned proxy connection implements UserContext interface. Accept() (net.Conn, *model.Request, error) } diff --git a/mieru/apis/server/server.go b/mieru/apis/server/server.go index 59e4f9283f..020fac7b21 100644 --- a/mieru/apis/server/server.go +++ b/mieru/apis/server/server.go @@ -21,6 +21,7 @@ import ( "sync" "time" + apicommon "github.com/enfein/mieru/v3/apis/common" "github.com/enfein/mieru/v3/apis/model" "github.com/enfein/mieru/v3/pkg/appctl/appctlcommon" "github.com/enfein/mieru/v3/pkg/appctl/appctlpb" @@ -127,6 +128,9 @@ func (ms *mieruServer) Accept() (net.Conn, *model.Request, error) { if err != nil { return nil, nil, err } + if _, ok := conn.(apicommon.UserContext); !ok { + return nil, nil, fmt.Errorf("internal error: connection doesn't implement UserContext interface") + } common.SetReadTimeout(conn, 10*time.Second) defer func() { diff --git a/mieru/build/package/mieru/amd64/debian/DEBIAN/control b/mieru/build/package/mieru/amd64/debian/DEBIAN/control index d71d88c5e9..0ea29592a4 100755 --- a/mieru/build/package/mieru/amd64/debian/DEBIAN/control +++ b/mieru/build/package/mieru/amd64/debian/DEBIAN/control @@ -1,5 +1,5 @@ Package: mieru -Version: 3.24.1 +Version: 3.25.0 Section: net Priority: optional Architecture: amd64 diff --git a/mieru/build/package/mieru/amd64/rpm/mieru.spec b/mieru/build/package/mieru/amd64/rpm/mieru.spec index 30a15af685..23dab2959e 100644 --- a/mieru/build/package/mieru/amd64/rpm/mieru.spec +++ b/mieru/build/package/mieru/amd64/rpm/mieru.spec @@ -1,5 +1,5 @@ Name: mieru -Version: 3.24.1 +Version: 3.25.0 Release: 1%{?dist} Summary: Mieru proxy client License: GPLv3+ diff --git a/mieru/build/package/mieru/arm64/debian/DEBIAN/control b/mieru/build/package/mieru/arm64/debian/DEBIAN/control index 59164c959b..4d43c97d06 100755 --- a/mieru/build/package/mieru/arm64/debian/DEBIAN/control +++ b/mieru/build/package/mieru/arm64/debian/DEBIAN/control @@ -1,5 +1,5 @@ Package: mieru -Version: 3.24.1 +Version: 3.25.0 Section: net Priority: optional Architecture: arm64 diff --git a/mieru/build/package/mieru/arm64/rpm/mieru.spec b/mieru/build/package/mieru/arm64/rpm/mieru.spec index 30a15af685..23dab2959e 100644 --- a/mieru/build/package/mieru/arm64/rpm/mieru.spec +++ b/mieru/build/package/mieru/arm64/rpm/mieru.spec @@ -1,5 +1,5 @@ Name: mieru -Version: 3.24.1 +Version: 3.25.0 Release: 1%{?dist} Summary: Mieru proxy client License: GPLv3+ diff --git a/mieru/build/package/mita/amd64/debian/DEBIAN/control b/mieru/build/package/mita/amd64/debian/DEBIAN/control index 08b665bc68..e22cf0790f 100755 --- a/mieru/build/package/mita/amd64/debian/DEBIAN/control +++ b/mieru/build/package/mita/amd64/debian/DEBIAN/control @@ -1,5 +1,5 @@ Package: mita -Version: 3.24.1 +Version: 3.25.0 Section: net Priority: optional Architecture: amd64 diff --git a/mieru/build/package/mita/amd64/rpm/mita.spec b/mieru/build/package/mita/amd64/rpm/mita.spec index d77caa49aa..67397ab2b9 100644 --- a/mieru/build/package/mita/amd64/rpm/mita.spec +++ b/mieru/build/package/mita/amd64/rpm/mita.spec @@ -1,5 +1,5 @@ Name: mita -Version: 3.24.1 +Version: 3.25.0 Release: 1%{?dist} Summary: Mieru proxy server License: GPLv3+ diff --git a/mieru/build/package/mita/arm64/debian/DEBIAN/control b/mieru/build/package/mita/arm64/debian/DEBIAN/control index 2a970af574..edc4b1226d 100755 --- a/mieru/build/package/mita/arm64/debian/DEBIAN/control +++ b/mieru/build/package/mita/arm64/debian/DEBIAN/control @@ -1,5 +1,5 @@ Package: mita -Version: 3.24.1 +Version: 3.25.0 Section: net Priority: optional Architecture: arm64 diff --git a/mieru/build/package/mita/arm64/rpm/mita.spec b/mieru/build/package/mita/arm64/rpm/mita.spec index aa35964452..b22de6ca49 100644 --- a/mieru/build/package/mita/arm64/rpm/mita.spec +++ b/mieru/build/package/mita/arm64/rpm/mita.spec @@ -1,5 +1,5 @@ Name: mita -Version: 3.24.1 +Version: 3.25.0 Release: 1%{?dist} Summary: Mieru proxy server License: GPLv3+ diff --git a/mieru/docs/server-install.md b/mieru/docs/server-install.md index b7cbad8c29..6b1563fe97 100644 --- a/mieru/docs/server-install.md +++ b/mieru/docs/server-install.md @@ -18,32 +18,32 @@ Or you can manually install and configure proxy server using the steps below. ```sh # Debian / Ubuntu - X86_64 -curl -LSO https://github.com/enfein/mieru/releases/download/v3.24.1/mita_3.24.1_amd64.deb +curl -LSO https://github.com/enfein/mieru/releases/download/v3.25.0/mita_3.25.0_amd64.deb # Debian / Ubuntu - ARM 64 -curl -LSO https://github.com/enfein/mieru/releases/download/v3.24.1/mita_3.24.1_arm64.deb +curl -LSO https://github.com/enfein/mieru/releases/download/v3.25.0/mita_3.25.0_arm64.deb # RedHat / CentOS / Rocky Linux - X86_64 -curl -LSO https://github.com/enfein/mieru/releases/download/v3.24.1/mita-3.24.1-1.x86_64.rpm +curl -LSO https://github.com/enfein/mieru/releases/download/v3.25.0/mita-3.25.0-1.x86_64.rpm # RedHat / CentOS / Rocky Linux - ARM 64 -curl -LSO https://github.com/enfein/mieru/releases/download/v3.24.1/mita-3.24.1-1.aarch64.rpm +curl -LSO https://github.com/enfein/mieru/releases/download/v3.25.0/mita-3.25.0-1.aarch64.rpm ``` ## Install mita package ```sh # Debian / Ubuntu - X86_64 -sudo dpkg -i mita_3.24.1_amd64.deb +sudo dpkg -i mita_3.25.0_amd64.deb # Debian / Ubuntu - ARM 64 -sudo dpkg -i mita_3.24.1_arm64.deb +sudo dpkg -i mita_3.25.0_arm64.deb # RedHat / CentOS / Rocky Linux - X86_64 -sudo rpm -Uvh --force mita-3.24.1-1.x86_64.rpm +sudo rpm -Uvh --force mita-3.25.0-1.x86_64.rpm # RedHat / CentOS / Rocky Linux - ARM 64 -sudo rpm -Uvh --force mita-3.24.1-1.aarch64.rpm +sudo rpm -Uvh --force mita-3.25.0-1.aarch64.rpm ``` Those instructions can also be used to upgrade the version of mita software package. diff --git a/mieru/docs/server-install.zh_CN.md b/mieru/docs/server-install.zh_CN.md index 5ca092fd74..b861c34481 100644 --- a/mieru/docs/server-install.zh_CN.md +++ b/mieru/docs/server-install.zh_CN.md @@ -18,32 +18,32 @@ sudo python3 setup.py --lang=zh ```sh # Debian / Ubuntu - X86_64 -curl -LSO https://github.com/enfein/mieru/releases/download/v3.24.1/mita_3.24.1_amd64.deb +curl -LSO https://github.com/enfein/mieru/releases/download/v3.25.0/mita_3.25.0_amd64.deb # Debian / Ubuntu - ARM 64 -curl -LSO https://github.com/enfein/mieru/releases/download/v3.24.1/mita_3.24.1_arm64.deb +curl -LSO https://github.com/enfein/mieru/releases/download/v3.25.0/mita_3.25.0_arm64.deb # RedHat / CentOS / Rocky Linux - X86_64 -curl -LSO https://github.com/enfein/mieru/releases/download/v3.24.1/mita-3.24.1-1.x86_64.rpm +curl -LSO https://github.com/enfein/mieru/releases/download/v3.25.0/mita-3.25.0-1.x86_64.rpm # RedHat / CentOS / Rocky Linux - ARM 64 -curl -LSO https://github.com/enfein/mieru/releases/download/v3.24.1/mita-3.24.1-1.aarch64.rpm +curl -LSO https://github.com/enfein/mieru/releases/download/v3.25.0/mita-3.25.0-1.aarch64.rpm ``` ## 安装 mita 软件包 ```sh # Debian / Ubuntu - X86_64 -sudo dpkg -i mita_3.24.1_amd64.deb +sudo dpkg -i mita_3.25.0_amd64.deb # Debian / Ubuntu - ARM 64 -sudo dpkg -i mita_3.24.1_arm64.deb +sudo dpkg -i mita_3.25.0_arm64.deb # RedHat / CentOS / Rocky Linux - X86_64 -sudo rpm -Uvh --force mita-3.24.1-1.x86_64.rpm +sudo rpm -Uvh --force mita-3.25.0-1.x86_64.rpm # RedHat / CentOS / Rocky Linux - ARM 64 -sudo rpm -Uvh --force mita-3.24.1-1.aarch64.rpm +sudo rpm -Uvh --force mita-3.25.0-1.aarch64.rpm ``` 上述指令也可以用来升级 mita 软件包的版本。 diff --git a/mieru/pkg/appctl/appctlcommon/client.go b/mieru/pkg/appctl/appctlcommon/client.go index d69141e1c1..efabc691b3 100644 --- a/mieru/pkg/appctl/appctlcommon/client.go +++ b/mieru/pkg/appctl/appctlcommon/client.go @@ -16,7 +16,6 @@ package appctlcommon import ( - "context" "encoding/hex" "fmt" "net" @@ -96,10 +95,7 @@ func NewClientMuxFromProfile(activeProfile *pb.ClientProfile, dialer apicommon.D // Set DNS resolver. // If DNS resolver is not provided, disable DNS resolution. // Connection to a domain name endpoint may fail. - enableDNS := false - if resolver != nil { - enableDNS = true - } else { + if resolver == nil { resolver = apicommon.NilDNSResolver{} } mux.SetResolver(resolver) @@ -142,16 +138,6 @@ func NewClientMuxFromProfile(activeProfile *pb.ClientProfile, dialer apicommon.D var proxyIP net.IP if serverInfo.GetDomainName() != "" { proxyHost = serverInfo.GetDomainName() - if enableDNS { - proxyIPs, err := resolver.LookupIP(context.Background(), "ip", proxyHost) - if err != nil { - return nil, fmt.Errorf(stderror.LookupIPFailedErr, err) - } - if len(proxyIPs) == 0 { - return nil, fmt.Errorf(stderror.IPAddressNotFound, proxyHost) - } - proxyIP = proxyIPs[0] - } } else { proxyHost = serverInfo.GetIpAddress() proxyIP = net.ParseIP(proxyHost) diff --git a/mieru/pkg/common/conn.go b/mieru/pkg/common/conn.go index 555b6f1d89..36e4e4490c 100644 --- a/mieru/pkg/common/conn.go +++ b/mieru/pkg/common/conn.go @@ -18,8 +18,6 @@ package common import ( "context" "io" - "net" - "sync" "time" ) @@ -62,57 +60,3 @@ func RoundTrip(ctx context.Context, rw io.ReadWriter, req []byte, maxRespSize in resp = resp[:n] return } - -// HierarchyConn closes sub-connections when this connection is closed. -type HierarchyConn interface { - net.Conn - - // AddSubConnection attach a child connection to this connection. - // The child connection is closed when this connection close. - AddSubConnection(conn net.Conn) -} - -type hierarchyConn struct { - net.Conn - subConnetions []HierarchyConn - mu sync.Mutex -} - -var ( - _ HierarchyConn = (*hierarchyConn)(nil) - _ UserContext = (*hierarchyConn)(nil) -) - -func (h *hierarchyConn) Close() error { - h.mu.Lock() - defer h.mu.Unlock() - for _, sub := range h.subConnetions { - if sub != nil { - sub.Close() - } - } - return h.Conn.Close() -} - -func (h *hierarchyConn) AddSubConnection(conn net.Conn) { - h.mu.Lock() - defer h.mu.Unlock() - if h.subConnetions == nil { - h.subConnetions = make([]HierarchyConn, 0) - } - h.subConnetions = append(h.subConnetions, WrapHierarchyConn(conn)) -} - -func (h *hierarchyConn) UserName() string { - h.mu.Lock() - defer h.mu.Unlock() - if userCtx, ok := h.Conn.(UserContext); ok { - return userCtx.UserName() - } - return "" -} - -// WrapHierarchyConn wraps an existing connection with HierarchyConn. -func WrapHierarchyConn(conn net.Conn) HierarchyConn { - return &hierarchyConn{Conn: conn} -} diff --git a/mieru/pkg/common/conn_test.go b/mieru/pkg/common/conn_test.go index f0e14209b9..a80ef98956 100644 --- a/mieru/pkg/common/conn_test.go +++ b/mieru/pkg/common/conn_test.go @@ -20,7 +20,6 @@ import ( crand "crypto/rand" "io" mrand "math/rand" - "net" "testing" ) @@ -37,23 +36,3 @@ func TestReadAllAndDiscard(t *testing.T) { t.Errorf("buf.Len() = %d, want 0", buf.Len()) } } - -type counterCloser struct { - net.Conn - Counter *int -} - -func (cc counterCloser) Close() error { - *cc.Counter = *cc.Counter + 1 - return nil -} - -func TestHierarchyConn(t *testing.T) { - counter := 0 - parent := WrapHierarchyConn(counterCloser{Conn: nil, Counter: &counter}) - parent.AddSubConnection(counterCloser{Conn: nil, Counter: &counter}) - parent.Close() - if counter != 2 { - t.Errorf("counter = %d, want %d", counter, 2) - } -} diff --git a/mieru/pkg/protocol/mux.go b/mieru/pkg/protocol/mux.go index 96fe4ccb5f..9286322f73 100644 --- a/mieru/pkg/protocol/mux.go +++ b/mieru/pkg/protocol/mux.go @@ -617,7 +617,7 @@ func (m *Mux) newUnderlay(ctx context.Context) (Underlay, error) { block.SetBlockContext(cipher.BlockContext{ UserName: m.username, }) - underlay, err = NewStreamUnderlay(ctx, m.dialer, p.RemoteAddr().Network(), p.RemoteAddr().String(), p.MTU(), block) + underlay, err = NewStreamUnderlay(ctx, m.dialer, m.resolver, p.RemoteAddr().Network(), p.RemoteAddr().String(), p.MTU(), block) if err != nil { return nil, fmt.Errorf("NewTCPUnderlay() failed: %v", err) } @@ -629,7 +629,7 @@ func (m *Mux) newUnderlay(ctx context.Context) (Underlay, error) { block.SetBlockContext(cipher.BlockContext{ UserName: m.username, }) - underlay, err = NewPacketUnderlay(ctx, m.packetDialer, p.RemoteAddr().Network(), p.RemoteAddr().String(), p.MTU(), block, m.resolver) + underlay, err = NewPacketUnderlay(ctx, m.packetDialer, m.resolver, p.RemoteAddr().Network(), p.RemoteAddr().String(), p.MTU(), block) if err != nil { return nil, fmt.Errorf("NewUDPUnderlay() failed: %v", err) } diff --git a/mieru/pkg/protocol/session.go b/mieru/pkg/protocol/session.go index 5ff602c3ea..9fbcd1ca1b 100644 --- a/mieru/pkg/protocol/session.go +++ b/mieru/pkg/protocol/session.go @@ -25,6 +25,7 @@ import ( "sync/atomic" "time" + apicommon "github.com/enfein/mieru/v3/apis/common" "github.com/enfein/mieru/v3/pkg/appctl/appctlpb" "github.com/enfein/mieru/v3/pkg/cipher" "github.com/enfein/mieru/v3/pkg/common" @@ -109,7 +110,7 @@ type Session struct { status statusCode // session status users map[string]*appctlpb.User // all registered users, only used by server - userName string // user that owns this session, only used by server + userName atomic.Pointer[string] // user that owns this session, only used by server ready chan struct{} // indicate the session is ready to use closeRequested atomic.Bool // the session is being closed or has been closed @@ -155,8 +156,8 @@ var ( // Session implements net.Conn interface. _ net.Conn = (*Session)(nil) - // Session implements common.UserContext interface. - _ common.UserContext = (*Session)(nil) + // Session implements UserContext interface. + _ apicommon.UserContext = (*Session)(nil) ) // NewSession creates a new session. @@ -403,7 +404,10 @@ func (s *Session) SetWriteDeadline(t time.Time) error { // UserName returns the user that owns this session, // only if this is a server session. func (s *Session) UserName() string { - return s.userName + if p := s.userName.Load(); p != nil { + return *p + } + return "" } // ToSessionInfo creates related SessionInfo protobuf object. @@ -905,8 +909,9 @@ func (s *Session) input(seg *segment) error { } s.block.Store(&seg.block) - if s.userName == "" && seg.block.BlockContext().UserName != "" { - s.userName = seg.block.BlockContext().UserName + if s.UserName() == "" && seg.block.BlockContext().UserName != "" { + userName := seg.block.BlockContext().UserName + s.userName.Store(&userName) } // Register server per user metrics. @@ -1026,14 +1031,14 @@ func (s *Session) inputData(seg *segment) error { // Server needs to send open session response. // Check user quota if we can identify the user. s.oLock.Lock() - if s.userName != "" { - quotaOK, err := s.checkQuota(s.userName) + if userName := s.UserName(); userName != "" { + quotaOK, err := s.checkQuota(userName) if err != nil { log.Debugf("%v checkQuota() failed: %v", s, err) } if !quotaOK { s.status = statusQuotaExhausted - log.Debugf("Closing %v because user %s used all the quota", s, s.userName) + log.Debugf("Closing %v because user %s used all the quota", s, userName) s.oLock.Unlock() s.Close() return nil diff --git a/mieru/pkg/protocol/underlay_packet.go b/mieru/pkg/protocol/underlay_packet.go index c34f4d238f..0cf5fe043a 100644 --- a/mieru/pkg/protocol/underlay_packet.go +++ b/mieru/pkg/protocol/underlay_packet.go @@ -66,7 +66,7 @@ var _ Underlay = &PacketUnderlay{} // "block" is the block encryption algorithm to encrypt packets. // // This function is only used by proxy client. -func NewPacketUnderlay(ctx context.Context, packetDialer apicommon.PacketDialer, network, addr string, mtu int, block cipher.BlockCipher, resolver apicommon.DNSResolver) (*PacketUnderlay, error) { +func NewPacketUnderlay(ctx context.Context, packetDialer apicommon.PacketDialer, resolver apicommon.DNSResolver, network, addr string, mtu int, block cipher.BlockCipher) (*PacketUnderlay, error) { switch network { case "udp", "udp4", "udp6": default: @@ -75,7 +75,7 @@ func NewPacketUnderlay(ctx context.Context, packetDialer apicommon.PacketDialer, if !block.IsStateless() { return nil, fmt.Errorf("packet underlay block cipher must be stateless") } - remoteAddr, err := apicommon.ResolveUDPAddr(resolver, "udp", addr) + remoteAddr, err := apicommon.ResolveUDPAddr(resolver, network, addr) if err != nil { return nil, fmt.Errorf("ResolveUDPAddr() failed: %w", err) } diff --git a/mieru/pkg/protocol/underlay_stream.go b/mieru/pkg/protocol/underlay_stream.go index b763697954..3942fe1a8a 100644 --- a/mieru/pkg/protocol/underlay_stream.go +++ b/mieru/pkg/protocol/underlay_stream.go @@ -63,7 +63,7 @@ var _ Underlay = &StreamUnderlay{} // "block" is the block encryption algorithm to encrypt packets. // // This function is only used by proxy client. -func NewStreamUnderlay(ctx context.Context, dialer apicommon.Dialer, network, addr string, mtu int, block cipher.BlockCipher) (*StreamUnderlay, error) { +func NewStreamUnderlay(ctx context.Context, dialer apicommon.Dialer, resolver apicommon.DNSResolver, network, addr string, mtu int, block cipher.BlockCipher) (*StreamUnderlay, error) { switch network { case "tcp", "tcp4", "tcp6": default: @@ -72,7 +72,12 @@ func NewStreamUnderlay(ctx context.Context, dialer apicommon.Dialer, network, ad if block.IsStateless() { return nil, fmt.Errorf("stream underlay block cipher must be stateful") } - conn, err := dialer.DialContext(ctx, network, addr) + remoteAddr, err := apicommon.ResolveTCPAddr(resolver, network, addr) + if err != nil { + return nil, fmt.Errorf("ResolveTCPAddr() failed: %w", err) + } + + conn, err := dialer.DialContext(ctx, network, remoteAddr.String()) if err != nil { return nil, fmt.Errorf("DialContext() failed: %w", err) } diff --git a/mieru/pkg/socks5/socks5.go b/mieru/pkg/socks5/socks5.go index 12e565e144..e8eda38e2b 100644 --- a/mieru/pkg/socks5/socks5.go +++ b/mieru/pkg/socks5/socks5.go @@ -160,7 +160,7 @@ func (s *Server) Serve(l net.Listener) error { // ServeConn is used to serve a single connection. func (s *Server) ServeConn(conn net.Conn) error { - conn = common.WrapHierarchyConn(conn) + conn = apicommon.WrapHierarchyConn(conn) defer conn.Close() log.Debugf("socks5 server starts to serve connection [%v - %v]", conn.LocalAddr(), conn.RemoteAddr()) @@ -227,7 +227,7 @@ func (s *Server) clientServeConn(conn net.Conn) error { return common.BidiCopy(conn, proxyConn) } log.Debugf("UDP association is listening on %v", udpAssociateConn.LocalAddr()) - conn.(common.HierarchyConn).AddSubConnection(udpAssociateConn) + conn.(apicommon.HierarchyConn).Add(udpAssociateConn) go func() { common.ReadAllAndDiscard(conn) conn.Close() @@ -262,18 +262,15 @@ func (s *Server) serverServeConn(conn net.Conn) error { Protocol: appctlpb.ProxyProtocol_SOCKS5_PROXY_PROTOCOL, Data: request.Raw, } - if userCtx, ok := conn.(common.UserContext); ok { - userName := userCtx.UserName() - if userName == "" { - log.Debugf("Failed to determine user name from the connection") - } else { - log.Debugf("User %q initiated the connection", userName) - egressInput.Env = map[string]string{ - "user": userName, - } - } + userCtx := conn.(apicommon.UserContext) + userName := userCtx.UserName() + if userName == "" { + log.Debugf("Failed to determine user name from the connection") } else { - log.Errorf("%T doesn't implement common.UserContext interface", conn) + log.Debugf("User %q initiated the connection", userName) + egressInput.Env = map[string]string{ + "user": userName, + } } action := s.FindAction(ctx, egressInput) if action.Action == appctlpb.EgressAction_PROXY { diff --git a/mieru/pkg/version/current.go b/mieru/pkg/version/current.go index d6f60462c5..9020eb1c79 100644 --- a/mieru/pkg/version/current.go +++ b/mieru/pkg/version/current.go @@ -16,5 +16,5 @@ package version const ( - AppVersion = "3.24.1" + AppVersion = "3.25.0" ) diff --git a/mieru/test/cmd/exampleapiserver/exampleapiserver.go b/mieru/test/cmd/exampleapiserver/exampleapiserver.go index 42a032bfc3..8df35acc9b 100644 --- a/mieru/test/cmd/exampleapiserver/exampleapiserver.go +++ b/mieru/test/cmd/exampleapiserver/exampleapiserver.go @@ -102,11 +102,16 @@ func main() { } func handleOneProxyConn(proxyConn net.Conn, req *model.Request) { - if *debug { - fmt.Printf("Received %v\n", req) - } defer proxyConn.Close() + userCtx := proxyConn.(apicommon.UserContext) + if userCtx.UserName() == "" { + panic("User name is empty") + } + if *debug { + fmt.Printf("Received %v from %s\n", req, userCtx.UserName()) + } + var isTCP, isUDP bool switch req.Command { case constant.Socks5ConnectCmd: diff --git a/mieru/test/deploy/mihomo/client_tcp.json b/mieru/test/deploy/mihomo/client_tcp.json index 367fe3d998..a92ebca904 100644 --- a/mieru/test/deploy/mihomo/client_tcp.json +++ b/mieru/test/deploy/mihomo/client_tcp.json @@ -8,7 +8,7 @@ }, "servers": [ { - "domainName": "localhost", + "ipAddress": "127.0.0.1", "portBindings": [ { "port": 8966, diff --git a/mieru/test/deploy/mihomo/client_tcp_no_wait.json b/mieru/test/deploy/mihomo/client_tcp_no_wait.json index 444230e257..6cab5227a7 100644 --- a/mieru/test/deploy/mihomo/client_tcp_no_wait.json +++ b/mieru/test/deploy/mihomo/client_tcp_no_wait.json @@ -8,7 +8,7 @@ }, "servers": [ { - "domainName": "localhost", + "ipAddress": "127.0.0.1", "portBindings": [ { "port": 8966, diff --git a/mieru/test/deploy/mihomo/client_udp.json b/mieru/test/deploy/mihomo/client_udp.json index de4210a46b..1241c3965b 100644 --- a/mieru/test/deploy/mihomo/client_udp.json +++ b/mieru/test/deploy/mihomo/client_udp.json @@ -8,7 +8,7 @@ }, "servers": [ { - "domainName": "localhost", + "ipAddress": "127.0.0.1", "portBindings": [ { "port": 8966, diff --git a/mieru/test/deploy/mihomo/client_udp_no_wait.json b/mieru/test/deploy/mihomo/client_udp_no_wait.json index 6146567d3f..41ab3120ea 100644 --- a/mieru/test/deploy/mihomo/client_udp_no_wait.json +++ b/mieru/test/deploy/mihomo/client_udp_no_wait.json @@ -8,7 +8,7 @@ }, "servers": [ { - "domainName": "localhost", + "ipAddress": "127.0.0.1", "portBindings": [ { "port": 8966, diff --git a/mieru/test/deploy/mihomo/mihomo-client-tcp-no-wait.yaml b/mieru/test/deploy/mihomo/mihomo-client-tcp-no-wait.yaml index 945f813afd..40ab03fee5 100644 --- a/mieru/test/deploy/mihomo/mihomo-client-tcp-no-wait.yaml +++ b/mieru/test/deploy/mihomo/mihomo-client-tcp-no-wait.yaml @@ -8,7 +8,7 @@ mode: rule proxies: - name: mieru type: mieru - server: 127.0.0.1 + server: localhost port-range: 8964-8965 transport: TCP udp: true diff --git a/mieru/test/deploy/mihomo/mihomo-client-tcp.yaml b/mieru/test/deploy/mihomo/mihomo-client-tcp.yaml index 7af7575db9..cbfee05066 100644 --- a/mieru/test/deploy/mihomo/mihomo-client-tcp.yaml +++ b/mieru/test/deploy/mihomo/mihomo-client-tcp.yaml @@ -8,7 +8,7 @@ mode: rule proxies: - name: mieru type: mieru - server: 127.0.0.1 + server: localhost port-range: 8964-8965 transport: TCP udp: true diff --git a/mieru/test/deploy/mihomo/mihomo-client-udp-no-wait.yaml b/mieru/test/deploy/mihomo/mihomo-client-udp-no-wait.yaml index 259b7a9a62..16e88ff33f 100644 --- a/mieru/test/deploy/mihomo/mihomo-client-udp-no-wait.yaml +++ b/mieru/test/deploy/mihomo/mihomo-client-udp-no-wait.yaml @@ -8,7 +8,7 @@ mode: rule proxies: - name: mieru type: mieru - server: 127.0.0.1 + server: localhost port-range: 8964-8965 transport: UDP udp: true diff --git a/mieru/test/deploy/mihomo/mihomo-client-udp.yaml b/mieru/test/deploy/mihomo/mihomo-client-udp.yaml index 97b51b695e..b6c9980ebf 100644 --- a/mieru/test/deploy/mihomo/mihomo-client-udp.yaml +++ b/mieru/test/deploy/mihomo/mihomo-client-udp.yaml @@ -8,7 +8,7 @@ mode: rule proxies: - name: mieru type: mieru - server: 127.0.0.1 + server: localhost port-range: 8964-8965 transport: UDP udp: true diff --git a/mieru/test/deploy/mihomo/test.sh b/mieru/test/deploy/mihomo/test.sh index 9695c119f0..bc6279b7a0 100755 --- a/mieru/test/deploy/mihomo/test.sh +++ b/mieru/test/deploy/mihomo/test.sh @@ -35,16 +35,16 @@ sleep 1 ./mita run & sleep 1 -# Run server test. -echo "========== BEGIN OF SERVER TEST ==========" -./test_server.sh -echo "========== END OF SERVER TEST ==========" - # Run client test. echo "========== BEGIN OF CLIENT TEST ==========" ./test_client.sh echo "========== END OF CLIENT TEST ==========" +# Run server test. +echo "========== BEGIN OF SERVER TEST ==========" +./test_server.sh +echo "========== END OF SERVER TEST ==========" + echo "Test is successful." sleep 1 exit 0 diff --git a/mihomo/go.mod b/mihomo/go.mod index aaf8890ccf..3ae50c987c 100644 --- a/mihomo/go.mod +++ b/mihomo/go.mod @@ -32,11 +32,11 @@ require ( github.com/metacubex/sing-shadowsocks v0.2.12 github.com/metacubex/sing-shadowsocks2 v0.2.7 github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 - github.com/metacubex/sing-tun v0.4.9 + github.com/metacubex/sing-tun v0.4.10 github.com/metacubex/sing-vmess v0.2.4 github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f github.com/metacubex/smux v0.0.0-20251111013112-03f8d12dafc1 - github.com/metacubex/tfo-go v0.0.0-20251024101424-368b42b59148 + github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443 github.com/metacubex/utls v1.8.3 github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f github.com/miekg/dns v1.1.63 // lastest version compatible with golang1.20 diff --git a/mihomo/go.sum b/mihomo/go.sum index 1186bda8f2..7d24c9c06b 100644 --- a/mihomo/go.sum +++ b/mihomo/go.sum @@ -131,16 +131,16 @@ github.com/metacubex/sing-shadowsocks2 v0.2.7 h1:hSuuc0YpsfiqYqt1o+fP4m34BQz4e6w github.com/metacubex/sing-shadowsocks2 v0.2.7/go.mod h1:vOEbfKC60txi0ca+yUlqEwOGc3Obl6cnSgx9Gf45KjE= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 h1:gXU+MYPm7Wme3/OAY2FFzVq9d9GxPHOqu5AQfg/ddhI= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2/go.mod h1:mbfboaXauKJNIHJYxQRa+NJs4JU9NZfkA+I33dS2+9E= -github.com/metacubex/sing-tun v0.4.9 h1:jY0Yyt8nnN3yQRN/jTxgqNCmGi1dsFdxdIi7pQUlVVU= -github.com/metacubex/sing-tun v0.4.9/go.mod h1:L/TjQY5JEGy8nvsuYmy/XgMFMCPiF0+AWSFCYfS6r9w= +github.com/metacubex/sing-tun v0.4.10 h1:DllQTERAcqQyiEl4L/R7Ia0jCiSzZzikw2kL8N85p0E= +github.com/metacubex/sing-tun v0.4.10/go.mod h1:L/TjQY5JEGy8nvsuYmy/XgMFMCPiF0+AWSFCYfS6r9w= github.com/metacubex/sing-vmess v0.2.4 h1:Tx6AGgCiEf400E/xyDuYyafsel6sGbR8oF7RkAaus6I= github.com/metacubex/sing-vmess v0.2.4/go.mod h1:21R5R1u90uUvBQF0owoooEu96/SAYYD56nDrwm6nFaM= github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f h1:Sr/DYKYofKHKc4GF3qkRGNuj6XA6c0eqPgEDN+VAsYU= github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f/go.mod h1:jpAkVLPnCpGSfNyVmj6Cq4YbuZsFepm/Dc+9BAOcR80= github.com/metacubex/smux v0.0.0-20251111013112-03f8d12dafc1 h1:a6DF0ze9miXes+rdwl8a4Wkvfpe0lXYU82sPJfDzz6s= github.com/metacubex/smux v0.0.0-20251111013112-03f8d12dafc1/go.mod h1:4bPD8HWx9jPJ9aE4uadgyN7D1/Wz3KmPy+vale8sKLE= -github.com/metacubex/tfo-go v0.0.0-20251024101424-368b42b59148 h1:Zd0QqciLIhv9MKbGKTPEgN8WUFsgQGA1WJBy6spEnVU= -github.com/metacubex/tfo-go v0.0.0-20251024101424-368b42b59148/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw= +github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443 h1:H6TnfM12tOoTizYE/qBHH3nEuibIelmHI+BVSxVJr8o= +github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw= github.com/metacubex/utls v1.8.3 h1:0m/yCxm3SK6kWve2lKiFb1pue1wHitJ8sQQD4Ikqde4= github.com/metacubex/utls v1.8.3/go.mod h1:kncGGVhFaoGn5M3pFe3SXhZCzsbCJayNOH4UEqTKTko= github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f h1:FGBPRb1zUabhPhDrlKEjQ9lgIwQ6cHL4x8M9lrERhbk= diff --git a/openwrt-packages/filebrowser/Makefile b/openwrt-packages/filebrowser/Makefile index 3d59fa3ed3..909dba2779 100644 --- a/openwrt-packages/filebrowser/Makefile +++ b/openwrt-packages/filebrowser/Makefile @@ -5,12 +5,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=filebrowser -PKG_VERSION:=2.49.0 +PKG_VERSION:=2.50.0 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/filebrowser/filebrowser/tar.gz/v${PKG_VERSION}? -PKG_HASH:=5f35beedf818feef315d84222dd957b8e10fab65a80a7d6ff10e22a31a11722f +PKG_HASH:=5947c8a8c7c8df2b2646953cfa1fdee9efac8b4415a368074acab94eacc56fd7 PKG_LICENSE:=Apache-2.0 PKG_LICENSE_FILES:=LICENSE diff --git a/openwrt-passwall/luci-app-passwall/Makefile b/openwrt-passwall/luci-app-passwall/Makefile index fd6fb7202f..e0ece6c8cc 100644 --- a/openwrt-passwall/luci-app-passwall/Makefile +++ b/openwrt-passwall/luci-app-passwall/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall -PKG_VERSION:=25.11.27 +PKG_VERSION:=25.12.1 PKG_RELEASE:=1 PKG_PO_VERSION:=$(PKG_VERSION) diff --git a/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm b/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm index c8a27c2f58..b0787f8725 100644 --- a/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm +++ b/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm @@ -1,7 +1,7 @@ <% local api = require "luci.passwall.api" -%> - +