Update On Fri Dec 6 19:37:13 CET 2024

This commit is contained in:
github-action[bot]
2024-12-06 19:37:13 +01:00
parent e7ed3f08e7
commit 6f64ef7b44
72 changed files with 2200 additions and 613 deletions

1
.github/update.log vendored
View File

@@ -846,3 +846,4 @@ Update On Mon Dec 2 19:39:13 CET 2024
Update On Tue Dec 3 19:35:29 CET 2024
Update On Wed Dec 4 19:40:09 CET 2024
Update On Thu Dec 5 19:36:56 CET 2024
Update On Fri Dec 6 19:37:02 CET 2024

View File

@@ -127,10 +127,10 @@ func router(isDebug bool, secret string, dohServer string, cors Cors) *chi.Mux {
r.Mount("/providers/rules", ruleProviderRouter())
r.Mount("/cache", cacheRouter())
r.Mount("/dns", dnsRouter())
if !embedMode { // disallow restart and upgrade in embed mode
if !embedMode { // disallow restart in embed mode
r.Mount("/restart", restartRouter())
r.Mount("/upgrade", upgradeRouter())
}
r.Mount("/upgrade", upgradeRouter())
addExternalRouters(r)
})

View File

@@ -14,9 +14,11 @@ import (
func upgradeRouter() http.Handler {
r := chi.NewRouter()
r.Post("/", upgradeCore)
r.Post("/ui", updateUI)
r.Post("/geo", updateGeoDatabases)
if !embedMode { // disallow upgrade core/geo in embed mode
r.Post("/", upgradeCore)
r.Post("/geo", updateGeoDatabases)
}
return r
}

View File

@@ -1433,9 +1433,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.22"
version = "4.5.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69371e34337c4c984bbe322360c2547210bf632eb2814bbe78a6e87a2935bd2b"
checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84"
dependencies = [
"clap_builder",
"clap_derive",
@@ -1443,9 +1443,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.22"
version = "4.5.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e24c1b4099818523236a8ca881d2b45db98dadfb4625cf6608c12069fcbbde1"
checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838"
dependencies = [
"anstream",
"anstyle",
@@ -1467,9 +1467,9 @@ dependencies = [
[[package]]
name = "clap_lex"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7"
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]]
name = "clash-nyanpasu"

View File

@@ -18,6 +18,6 @@
"swr": "2.2.5"
},
"devDependencies": {
"@types/react": "18.3.13"
"@types/react": "18.3.14"
}
}

View File

@@ -52,11 +52,11 @@
"@csstools/normalize.css": "12.1.1",
"@emotion/babel-plugin": "11.13.5",
"@emotion/react": "11.13.5",
"@iconify/json": "2.2.279",
"@iconify/json": "2.2.280",
"@monaco-editor/react": "4.6.0",
"@tanstack/react-router": "1.85.5",
"@tanstack/router-devtools": "1.85.5",
"@tanstack/router-plugin": "1.85.3",
"@tanstack/react-router": "1.85.10",
"@tanstack/router-devtools": "1.85.10",
"@tanstack/router-plugin": "1.85.9",
"@tauri-apps/plugin-clipboard-manager": "2.0.1",
"@tauri-apps/plugin-dialog": "2.0.1",
"@tauri-apps/plugin-fs": "2.0.3",
@@ -65,8 +65,8 @@
"@tauri-apps/plugin-process": "2.0.0",
"@tauri-apps/plugin-shell": "2.0.1",
"@tauri-apps/plugin-updater": "2.0.0",
"@types/react": "18.3.13",
"@types/react-dom": "18.3.1",
"@types/react": "18.3.14",
"@types/react-dom": "18.3.2",
"@types/validator": "13.12.2",
"@vitejs/plugin-legacy": "6.0.0",
"@vitejs/plugin-react": "4.3.4",
@@ -82,9 +82,9 @@
"shiki": "1.24.0",
"tailwindcss-textshadow": "2.1.3",
"unplugin-auto-import": "0.18.6",
"unplugin-icons": "0.20.2",
"unplugin-icons": "0.21.0",
"validator": "13.12.0",
"vite": "6.0.2",
"vite": "6.0.3",
"vite-plugin-sass-dts": "1.3.29",
"vite-plugin-svgr": "4.3.0",
"vite-tsconfig-paths": "5.1.3",

View File

@@ -24,7 +24,7 @@
"@radix-ui/react-scroll-area": "1.2.1",
"@tauri-apps/api": "2.1.1",
"@types/d3": "7.4.3",
"@types/react": "18.3.13",
"@types/react": "18.3.14",
"@vitejs/plugin-react": "4.3.4",
"ahooks": "3.8.4",
"d3": "7.9.0",
@@ -34,7 +34,7 @@
"react-error-boundary": "4.1.2",
"react-i18next": "15.1.3",
"react-use": "17.5.1",
"vite": "6.0.2",
"vite": "6.0.3",
"vite-tsconfig-paths": "5.1.3"
},
"devDependencies": {

View File

@@ -64,8 +64,8 @@
"@types/fs-extra": "11.0.4",
"@types/lodash-es": "4.17.12",
"@types/node": "22.10.1",
"@typescript-eslint/eslint-plugin": "8.16.0",
"@typescript-eslint/parser": "8.16.0",
"@typescript-eslint/eslint-plugin": "8.17.0",
"@typescript-eslint/parser": "8.17.0",
"autoprefixer": "10.4.20",
"conventional-changelog-conventionalcommits": "8.0.0",
"cross-env": "7.0.3",
@@ -89,7 +89,7 @@
"postcss-html": "1.7.0",
"postcss-import": "16.1.0",
"postcss-scss": "4.0.9",
"prettier": "3.4.1",
"prettier": "3.4.2",
"prettier-plugin-tailwindcss": "0.6.9",
"prettier-plugin-toml": "2.0.1",
"react-devtools": "6.0.1",
@@ -106,7 +106,7 @@
},
"packageManager": "pnpm@9.14.4+sha512.c8180b3fbe4e4bca02c94234717896b5529740a6cbadf19fa78254270403ea2f27d4e1d46a08a0f56c89b63dc8ebfd3ee53326da720273794e6200fcf0d184ab",
"engines": {
"node": "22.11.0"
"node": "22.12.0"
},
"pnpm": {
"overrides": {

View File

@@ -28,7 +28,7 @@ importers:
version: 19.6.0
'@ianvs/prettier-plugin-sort-imports':
specifier: 4.4.0
version: 4.4.0(prettier@3.4.1)
version: 4.4.0(prettier@3.4.2)
'@tauri-apps/cli':
specifier: 2.1.0
version: 2.1.0
@@ -42,11 +42,11 @@ importers:
specifier: 22.10.1
version: 22.10.1
'@typescript-eslint/eslint-plugin':
specifier: 8.16.0
version: 8.16.0(@typescript-eslint/parser@8.16.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2)
specifier: 8.17.0
version: 8.17.0(@typescript-eslint/parser@8.17.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2)
'@typescript-eslint/parser':
specifier: 8.16.0
version: 8.16.0(eslint@8.57.1)(typescript@5.7.2)
specifier: 8.17.0
version: 8.17.0(eslint@8.57.1)(typescript@5.7.2)
autoprefixer:
specifier: 10.4.20
version: 10.4.20(postcss@8.4.49)
@@ -67,22 +67,22 @@ importers:
version: 9.1.0(eslint@8.57.1)
eslint-config-standard:
specifier: 17.1.0
version: 17.1.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.16.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1))(eslint-plugin-n@17.14.0(eslint@8.57.1))(eslint-plugin-promise@7.2.1(eslint@8.57.1))(eslint@8.57.1)
version: 17.1.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.17.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1))(eslint-plugin-n@17.14.0(eslint@8.57.1))(eslint-plugin-promise@7.2.1(eslint@8.57.1))(eslint@8.57.1)
eslint-import-resolver-alias:
specifier: 1.1.2
version: 1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.16.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1))
version: 1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.17.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1))
eslint-plugin-html:
specifier: 8.1.2
version: 8.1.2
eslint-plugin-import:
specifier: 2.31.0
version: 2.31.0(@typescript-eslint/parser@8.16.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)
version: 2.31.0(@typescript-eslint/parser@8.17.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)
eslint-plugin-n:
specifier: 17.14.0
version: 17.14.0(eslint@8.57.1)
eslint-plugin-prettier:
specifier: 5.2.1
version: 5.2.1(eslint-config-prettier@9.1.0(eslint@8.57.1))(eslint@8.57.1)(prettier@3.4.1)
version: 5.2.1(eslint-config-prettier@9.1.0(eslint@8.57.1))(eslint@8.57.1)(prettier@3.4.2)
eslint-plugin-promise:
specifier: 7.2.1
version: 7.2.1(eslint@8.57.1)
@@ -117,14 +117,14 @@ importers:
specifier: 4.0.9
version: 4.0.9(postcss@8.4.49)
prettier:
specifier: 3.4.1
version: 3.4.1
specifier: 3.4.2
version: 3.4.2
prettier-plugin-tailwindcss:
specifier: 0.6.9
version: 0.6.9(@ianvs/prettier-plugin-sort-imports@4.4.0(prettier@3.4.1))(@trivago/prettier-plugin-sort-imports@4.3.0(prettier@3.4.1))(prettier@3.4.1)
version: 0.6.9(@ianvs/prettier-plugin-sort-imports@4.4.0(prettier@3.4.2))(@trivago/prettier-plugin-sort-imports@4.3.0(prettier@3.4.2))(prettier@3.4.2)
prettier-plugin-toml:
specifier: 2.0.1
version: 2.0.1(prettier@3.4.1)
version: 2.0.1(prettier@3.4.2)
react-devtools:
specifier: 6.0.1
version: 6.0.1(bufferutil@4.0.8)(utf-8-validate@5.0.10)
@@ -218,7 +218,7 @@ importers:
version: link:../ui
'@tanstack/router-zod-adapter':
specifier: 1.81.5
version: 1.81.5(@tanstack/react-router@1.85.5(@tanstack/router-generator@1.85.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1))(zod@3.23.8)
version: 1.81.5(@tanstack/react-router@1.85.10(@tanstack/router-generator@1.85.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1))(zod@3.23.8)
'@tauri-apps/api':
specifier: 2.1.1
version: 2.1.1
@@ -305,20 +305,20 @@ importers:
specifier: 11.13.5
version: 11.13.5(react@19.0.0-rc.1)(types-react@19.0.0-rc.1)
'@iconify/json':
specifier: 2.2.279
version: 2.2.279
specifier: 2.2.280
version: 2.2.280
'@monaco-editor/react':
specifier: 4.6.0
version: 4.6.0(monaco-editor@0.52.0)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1)
'@tanstack/react-router':
specifier: 1.85.5
version: 1.85.5(@tanstack/router-generator@1.85.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1)
specifier: 1.85.10
version: 1.85.10(@tanstack/router-generator@1.85.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1)
'@tanstack/router-devtools':
specifier: 1.85.5
version: 1.85.5(@tanstack/react-router@1.85.5(@tanstack/router-generator@1.85.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1))(csstype@3.1.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1)
specifier: 1.85.10
version: 1.85.10(@tanstack/react-router@1.85.10(@tanstack/router-generator@1.85.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1))(csstype@3.1.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1)
'@tanstack/router-plugin':
specifier: 1.85.3
version: 1.85.3(vite@6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))
specifier: 1.85.9
version: 1.85.9(vite@6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))
'@tauri-apps/plugin-clipboard-manager':
specifier: 2.0.1
version: 2.0.1
@@ -354,13 +354,13 @@ importers:
version: 13.12.2
'@vitejs/plugin-legacy':
specifier: 6.0.0
version: 6.0.0(terser@5.36.0)(vite@6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))
version: 6.0.0(terser@5.36.0)(vite@6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))
'@vitejs/plugin-react':
specifier: 4.3.4
version: 4.3.4(vite@6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))
version: 4.3.4(vite@6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))
'@vitejs/plugin-react-swc':
specifier: 3.7.2
version: 3.7.2(vite@6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))
version: 3.7.2(vite@6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))
change-case:
specifier: 5.4.4
version: 5.4.4
@@ -395,23 +395,23 @@ importers:
specifier: 0.18.6
version: 0.18.6(rollup@4.27.4)
unplugin-icons:
specifier: 0.20.2
version: 0.20.2(@svgr/core@8.1.0(typescript@5.7.2))
specifier: 0.21.0
version: 0.21.0(@svgr/core@8.1.0(typescript@5.7.2))
validator:
specifier: 13.12.0
version: 13.12.0
vite:
specifier: 6.0.2
version: 6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)
specifier: 6.0.3
version: 6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)
vite-plugin-sass-dts:
specifier: 1.3.29
version: 1.3.29(postcss@8.4.49)(prettier@3.4.1)(sass-embedded@1.78.0)(vite@6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))
version: 1.3.29(postcss@8.4.49)(prettier@3.4.2)(sass-embedded@1.78.0)(vite@6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))
vite-plugin-svgr:
specifier: 4.3.0
version: 4.3.0(rollup@4.27.4)(typescript@5.7.2)(vite@6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))
version: 4.3.0(rollup@4.27.4)(typescript@5.7.2)(vite@6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))
vite-tsconfig-paths:
specifier: 5.1.3
version: 5.1.3(typescript@5.7.2)(vite@6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))
version: 5.1.3(typescript@5.7.2)(vite@6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))
zod:
specifier: 3.23.8
version: 3.23.8
@@ -447,7 +447,7 @@ importers:
version: types-react@19.0.0-rc.1
'@vitejs/plugin-react':
specifier: 4.3.4
version: 4.3.4(vite@6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))
version: 4.3.4(vite@6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))
ahooks:
specifier: 3.8.4
version: 3.8.4(react@19.0.0-rc.1)
@@ -473,11 +473,11 @@ importers:
specifier: 17.5.1
version: 17.5.1(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1)
vite:
specifier: 6.0.2
version: 6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)
specifier: 6.0.3
version: 6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)
vite-tsconfig-paths:
specifier: 5.1.3
version: 5.1.3(typescript@5.7.2)(vite@6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))
version: 5.1.3(typescript@5.7.2)(vite@6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))
devDependencies:
'@emotion/react':
specifier: 11.13.5
@@ -502,7 +502,7 @@ importers:
version: 5.1.0(typescript@5.7.2)
vite-plugin-dts:
specifier: 4.3.0
version: 4.3.0(@types/node@22.10.1)(rollup@4.27.4)(typescript@5.7.2)(vite@6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))
version: 4.3.0(@types/node@22.10.1)(rollup@4.27.4)(typescript@5.7.2)(vite@6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))
scripts:
dependencies:
@@ -559,8 +559,8 @@ importers:
specifier: 2.26.8
version: 2.26.8
undici:
specifier: 7.0.0
version: 7.0.0
specifier: 7.1.0
version: 7.1.0
packages:
@@ -1695,8 +1695,8 @@ packages:
'@vue/compiler-sfc':
optional: true
'@iconify/json@2.2.279':
resolution: {integrity: sha512-9HJWOos32Qik+Mg0fTgP/FgoCpswQPAsFAJtGQv7PN3KQ3Dwta5DDfpEj/QSwdNB9xJ/gI+aFhSlULgeah7eFA==}
'@iconify/json@2.2.280':
resolution: {integrity: sha512-3N1lTn6XBPQ+wMTiYkBAx+GE4yBD8B3l9/OGzs2sEy4FDsYoq7lLoiSo7S0XA6NN/dK9rv6bup8NPCIwIkOPOw==}
'@iconify/types@2.0.0':
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
@@ -2644,11 +2644,11 @@ packages:
resolution: {integrity: sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==}
engines: {node: '>=12'}
'@tanstack/react-router@1.85.5':
resolution: {integrity: sha512-OCPka0mj+lPCUPiZmQUavRKu7NB8/HrDZIl8MHpjgzkvSOV0U+mszUl3FJxiMb1vXOJaY0/gny/96YbCzcsgdA==}
'@tanstack/react-router@1.85.10':
resolution: {integrity: sha512-fDvaJt+o4ASwA13+TW6rEhlGsHlYnI+ZF8fvW0WuZUi/1a3AAIId5vZgtVI8/HSj/jOuC+2sRZUx9xNljEifTA==}
engines: {node: '>=12'}
peerDependencies:
'@tanstack/router-generator': 1.85.3
'@tanstack/router-generator': ^1.85.3
react: '>=18'
react-dom: '>=18'
peerDependenciesMeta:
@@ -2674,11 +2674,11 @@ packages:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
'@tanstack/router-devtools@1.85.5':
resolution: {integrity: sha512-C5A0TP2dFSu3o4Bc1jHzX6ZRC4FC3BmjPJbUx3wJJduPaW72FwTqbGfeT79oyk8mOC69bvLTLydRGfMHQZbIRQ==}
'@tanstack/router-devtools@1.85.10':
resolution: {integrity: sha512-9ruoorsRL9CszcredHGoMMtxJqD9Ipnr+cb1GkOBS17yg+vcSYAes0HWrySAnIFXKXHpNb5c/9oBFIY63vCn0Q==}
engines: {node: '>=12'}
peerDependencies:
'@tanstack/react-router': ^1.85.5
'@tanstack/react-router': ^1.85.10
react: '>=18'
react-dom: '>=18'
@@ -2686,12 +2686,12 @@ packages:
resolution: {integrity: sha512-ka3hO1EPgV4h2hhECUHi4PGyCCUoo70Masb1/idyL7zzkDX/OPZnRd7JxxyneuRGKJ+GI//YWevqjAemyYeg1A==}
engines: {node: '>=12'}
'@tanstack/router-plugin@1.85.3':
resolution: {integrity: sha512-se75j7NZ+I44dcbi6CayvWhfp0r/3pfqgHNYgEQ5BSSPTtXYDaZXxFm5eU6oNxej8IqkzEZS5CMSkq9iHRvaUA==}
'@tanstack/router-plugin@1.85.9':
resolution: {integrity: sha512-P4sflxLw6MCQcS0TkOUjWe6nI7Ilnsy/kzTBgkIjVqQD3XxWolyczMPphOW9lMTsYY+HQQEb+4AFBA2U3fi5CQ==}
engines: {node: '>=12'}
peerDependencies:
'@rsbuild/core': '>=1.0.2'
vite: '>=5.0.0'
vite: '>=5.0.0 || >=6.0.0'
webpack: '>=5.92.0'
peerDependenciesMeta:
'@rsbuild/core':
@@ -3045,8 +3045,8 @@ packages:
'@types/yauzl@2.10.3':
resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==}
'@typescript-eslint/eslint-plugin@8.16.0':
resolution: {integrity: sha512-5YTHKV8MYlyMI6BaEG7crQ9BhSc8RxzshOReKwZwRWN0+XvvTOm+L/UYLCYxFpfwYuAAqhxiq4yae0CMFwbL7Q==}
'@typescript-eslint/eslint-plugin@8.17.0':
resolution: {integrity: sha512-HU1KAdW3Tt8zQkdvNoIijfWDMvdSweFYm4hWh+KwhPstv+sCmWb89hCIP8msFm9N1R/ooh9honpSuvqKWlYy3w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
'@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0
@@ -3056,8 +3056,8 @@ packages:
typescript:
optional: true
'@typescript-eslint/parser@8.16.0':
resolution: {integrity: sha512-D7DbgGFtsqIPIFMPJwCad9Gfi/hC0PWErRRHFnaCWoEDYi5tQUDiJCTmGUbBiLzjqAck4KcXt9Ayj0CNlIrF+w==}
'@typescript-eslint/parser@8.17.0':
resolution: {integrity: sha512-Drp39TXuUlD49F7ilHHCG7TTg8IkA+hxCuULdmzWYICxGXvDXmDmWEjJYZQYgf6l/TFfYNE167m7isnc3xlIEg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
@@ -3066,12 +3066,12 @@ packages:
typescript:
optional: true
'@typescript-eslint/scope-manager@8.16.0':
resolution: {integrity: sha512-mwsZWubQvBki2t5565uxF0EYvG+FwdFb8bMtDuGQLdCCnGPrDEDvm1gtfynuKlnpzeBRqdFCkMf9jg1fnAK8sg==}
'@typescript-eslint/scope-manager@8.17.0':
resolution: {integrity: sha512-/ewp4XjvnxaREtqsZjF4Mfn078RD/9GmiEAtTeLQ7yFdKnqwTOgRMSvFz4et9U5RiJQ15WTGXPLj89zGusvxBg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/type-utils@8.16.0':
resolution: {integrity: sha512-IqZHGG+g1XCWX9NyqnI/0CX5LL8/18awQqmkZSl2ynn8F76j579dByc0jhfVSnSnhf7zv76mKBQv9HQFKvDCgg==}
'@typescript-eslint/type-utils@8.17.0':
resolution: {integrity: sha512-q38llWJYPd63rRnJ6wY/ZQqIzPrBCkPdpIsaCfkR3Q4t3p6sb422zougfad4TFW9+ElIFLVDzWGiGAfbb/v2qw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
@@ -3080,12 +3080,12 @@ packages:
typescript:
optional: true
'@typescript-eslint/types@8.16.0':
resolution: {integrity: sha512-NzrHj6thBAOSE4d9bsuRNMvk+BvaQvmY4dDglgkgGC0EW/tB3Kelnp3tAKH87GEwzoxgeQn9fNGRyFJM/xd+GQ==}
'@typescript-eslint/types@8.17.0':
resolution: {integrity: sha512-gY2TVzeve3z6crqh2Ic7Cr+CAv6pfb0Egee7J5UAVWCpVvDI/F71wNfolIim4FE6hT15EbpZFVUj9j5i38jYXA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/typescript-estree@8.16.0':
resolution: {integrity: sha512-E2+9IzzXMc1iaBy9zmo+UYvluE3TW7bCGWSF41hVWUE01o8nzr1rvOQYSxelxr6StUvRcTMe633eY8mXASMaNw==}
'@typescript-eslint/typescript-estree@8.17.0':
resolution: {integrity: sha512-JqkOopc1nRKZpX+opvKqnM3XUlM7LpFMD0lYxTqOTKQfCWAmxw45e3qlOCsEqEB2yuacujivudOFpCnqkBDNMw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '*'
@@ -3093,8 +3093,8 @@ packages:
typescript:
optional: true
'@typescript-eslint/utils@8.16.0':
resolution: {integrity: sha512-C1zRy/mOL8Pj157GiX4kaw7iyRLKfJXBR3L82hk5kS/GyHcOFmy4YUq/zfZti72I9wnuQtA/+xzft4wCC8PJdA==}
'@typescript-eslint/utils@8.17.0':
resolution: {integrity: sha512-bQC8BnEkxqG8HBGKwG9wXlZqg37RKSMY7v/X8VEWD8JG2JuTHuNK0VFvMPMUKQcbk6B+tf05k+4AShAEtCtJ/w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
@@ -3103,8 +3103,8 @@ packages:
typescript:
optional: true
'@typescript-eslint/visitor-keys@8.16.0':
resolution: {integrity: sha512-pq19gbaMOmFE3CbL0ZB8J8BFCo2ckfHBfaIsaOZgBIF4EoISJIdLX5xRhd0FGB0LlHReNRuzoJoMGpTjq8F2CQ==}
'@typescript-eslint/visitor-keys@8.17.0':
resolution: {integrity: sha512-1Hm7THLpO6ww5QU6H/Qp+AusUUl+z/CAm3cNZZ0jQvon9yicgO7Rwd+/WWRpMKLYV6p2UvdbR27c86rzCPpreg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@ungap/structured-clone@1.2.0':
@@ -5925,9 +5925,6 @@ packages:
resolution: {integrity: sha512-q/R5GrMek0vzgoomq6rm9OX+3PQve8sLwTirmK30YB3Cu0Bbt9OX9M/SIUnroN5BGJkzwGsFwDaRGD9EwBOlCA==}
engines: {node: '>=4'}
package-manager-detector@0.2.0:
resolution: {integrity: sha512-E385OSk9qDcXhcM9LNSe4sdhx8a9mAPrZ4sMLW+tmxl5ZuGtPUcdFu+MPP2jbgiWAZ6Pfe5soGFMd+0Db5Vrog==}
package-manager-detector@0.2.5:
resolution: {integrity: sha512-3dS7y28uua+UDbRCLBqltMBrbI+A5U2mI9YuxHRxIWYmLj3DwntEBmERYzIAQ4DMeuCUOBSak7dBHHoXKpOTYQ==}
@@ -6262,8 +6259,8 @@ packages:
engines: {node: '>=10.13.0'}
hasBin: true
prettier@3.4.1:
resolution: {integrity: sha512-G+YdqtITVZmOJje6QkXQWzl3fSfMxFwm1tjTyo9exhkmWSqC4Yhd1+lug++IlR2mvRVAxEDDWYkQdeSztajqgg==}
prettier@3.4.2:
resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==}
engines: {node: '>=14'}
hasBin: true
@@ -7325,8 +7322,8 @@ packages:
resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==}
engines: {node: '>=14.0'}
undici@7.0.0:
resolution: {integrity: sha512-c4xi3kWnQJrb7h2q8aJYKvUzmz7boCgz1cUCC6OwdeM5Tr2P0hDuthr2iut4ggqsz+Cnh20U/LoTzbKIdDS/Nw==}
undici@7.1.0:
resolution: {integrity: sha512-3+mdX2R31khuLCm2mKExSlMdJsfol7bJkIMH80tdXA74W34rT1jKemUTlYR7WY3TqsV4wfOgpatWmmB2Jl1+5g==}
engines: {node: '>=20.18.1'}
unicode-canonical-property-names-ecmascript@2.0.1:
@@ -7406,8 +7403,8 @@ packages:
'@vueuse/core':
optional: true
unplugin-icons@0.20.2:
resolution: {integrity: sha512-Ak6TKAiO812aIUrCelrBSTQbYC4FiqawnFrAusP/hjmB8f9cAug9jr381ItvLl+Asi4IVcjoOiPbpy9CfFGKvQ==}
unplugin-icons@0.21.0:
resolution: {integrity: sha512-sRic+yj7cCbpDFwrRj+m55ogOZi6PQRDc/WUEmjHLAnc90v0g5UVxE0cVAZgBOsAPCieizZJui/sgrCYrVx8mQ==}
peerDependencies:
'@svgr/core': '>=7.0.0'
'@svgx/core': ^1.0.1
@@ -7554,8 +7551,8 @@ packages:
vite:
optional: true
vite@6.0.2:
resolution: {integrity: sha512-XdQ+VsY2tJpBsKGs0wf3U/+azx8BBpYRHFAyKm5VeEZNOJZRB63q7Sc8Iup3k0TrN3KO6QgyzFf+opSbfY1y0g==}
vite@6.0.3:
resolution: {integrity: sha512-Cmuo5P0ENTN6HxLSo6IHsjCLn/81Vgrp81oaiFFMRa8gGDj5xEjIcEpf2ZymZtZR8oU0P2JX5WuUp/rlXcHkAw==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
peerDependencies:
@@ -7796,8 +7793,8 @@ snapshots:
'@antfu/install-pkg@0.4.1':
dependencies:
package-manager-detector: 0.2.0
tinyexec: 0.3.0
package-manager-detector: 0.2.5
tinyexec: 0.3.1
'@antfu/install-pkg@0.5.0':
dependencies:
@@ -9014,18 +9011,18 @@ snapshots:
'@humanwhocodes/object-schema@2.0.3': {}
'@ianvs/prettier-plugin-sort-imports@4.4.0(prettier@3.4.1)':
'@ianvs/prettier-plugin-sort-imports@4.4.0(prettier@3.4.2)':
dependencies:
'@babel/generator': 7.26.2
'@babel/parser': 7.26.2
'@babel/traverse': 7.25.9
'@babel/types': 7.26.0
prettier: 3.4.1
prettier: 3.4.2
semver: 7.6.3
transitivePeerDependencies:
- supports-color
'@iconify/json@2.2.279':
'@iconify/json@2.2.280':
dependencies:
'@iconify/types': 2.0.0
pathe: 1.1.2
@@ -9945,7 +9942,7 @@ snapshots:
dependencies:
remove-accents: 0.5.0
'@tanstack/react-router@1.85.5(@tanstack/router-generator@1.85.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1)':
'@tanstack/react-router@1.85.10(@tanstack/router-generator@1.85.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1)':
dependencies:
'@tanstack/history': 1.85.3
'@tanstack/react-store': 0.6.1(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1)
@@ -9976,9 +9973,9 @@ snapshots:
react: 19.0.0-rc.1
react-dom: 19.0.0-rc.1(react@19.0.0-rc.1)
'@tanstack/router-devtools@1.85.5(@tanstack/react-router@1.85.5(@tanstack/router-generator@1.85.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1))(csstype@3.1.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1)':
'@tanstack/router-devtools@1.85.10(@tanstack/react-router@1.85.10(@tanstack/router-generator@1.85.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1))(csstype@3.1.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1)':
dependencies:
'@tanstack/react-router': 1.85.5(@tanstack/router-generator@1.85.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1)
'@tanstack/react-router': 1.85.10(@tanstack/router-generator@1.85.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1)
clsx: 2.1.1
goober: 2.1.16(csstype@3.1.3)
react: 19.0.0-rc.1
@@ -9989,11 +9986,11 @@ snapshots:
'@tanstack/router-generator@1.85.3':
dependencies:
'@tanstack/virtual-file-routes': 1.81.9
prettier: 3.4.1
prettier: 3.4.2
tsx: 4.19.2
zod: 3.23.8
'@tanstack/router-plugin@1.85.3(vite@6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))':
'@tanstack/router-plugin@1.85.9(vite@6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))':
dependencies:
'@babel/core': 7.26.0
'@babel/generator': 7.26.2
@@ -10014,13 +10011,13 @@ snapshots:
unplugin: 1.16.0
zod: 3.23.8
optionalDependencies:
vite: 6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)
vite: 6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)
transitivePeerDependencies:
- supports-color
'@tanstack/router-zod-adapter@1.81.5(@tanstack/react-router@1.85.5(@tanstack/router-generator@1.85.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1))(zod@3.23.8)':
'@tanstack/router-zod-adapter@1.81.5(@tanstack/react-router@1.85.10(@tanstack/router-generator@1.85.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1))(zod@3.23.8)':
dependencies:
'@tanstack/react-router': 1.85.5(@tanstack/router-generator@1.85.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1)
'@tanstack/react-router': 1.85.10(@tanstack/router-generator@1.85.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1)
zod: 3.23.8
'@tanstack/store@0.6.0': {}
@@ -10114,7 +10111,7 @@ snapshots:
dependencies:
'@tauri-apps/api': 2.1.1
'@trivago/prettier-plugin-sort-imports@4.3.0(prettier@3.4.1)':
'@trivago/prettier-plugin-sort-imports@4.3.0(prettier@3.4.2)':
dependencies:
'@babel/generator': 7.17.7
'@babel/parser': 7.26.2
@@ -10122,7 +10119,7 @@ snapshots:
'@babel/types': 7.17.0
javascript-natural-sort: 0.7.1
lodash: 4.17.21
prettier: 3.4.1
prettier: 3.4.2
transitivePeerDependencies:
- supports-color
optional: true
@@ -10378,14 +10375,14 @@ snapshots:
'@types/node': 22.10.1
optional: true
'@typescript-eslint/eslint-plugin@8.16.0(@typescript-eslint/parser@8.16.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2)':
'@typescript-eslint/eslint-plugin@8.17.0(@typescript-eslint/parser@8.17.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2)':
dependencies:
'@eslint-community/regexpp': 4.11.0
'@typescript-eslint/parser': 8.16.0(eslint@8.57.1)(typescript@5.7.2)
'@typescript-eslint/scope-manager': 8.16.0
'@typescript-eslint/type-utils': 8.16.0(eslint@8.57.1)(typescript@5.7.2)
'@typescript-eslint/utils': 8.16.0(eslint@8.57.1)(typescript@5.7.2)
'@typescript-eslint/visitor-keys': 8.16.0
'@typescript-eslint/parser': 8.17.0(eslint@8.57.1)(typescript@5.7.2)
'@typescript-eslint/scope-manager': 8.17.0
'@typescript-eslint/type-utils': 8.17.0(eslint@8.57.1)(typescript@5.7.2)
'@typescript-eslint/utils': 8.17.0(eslint@8.57.1)(typescript@5.7.2)
'@typescript-eslint/visitor-keys': 8.17.0
eslint: 8.57.1
graphemer: 1.4.0
ignore: 5.3.2
@@ -10396,12 +10393,12 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/parser@8.16.0(eslint@8.57.1)(typescript@5.7.2)':
'@typescript-eslint/parser@8.17.0(eslint@8.57.1)(typescript@5.7.2)':
dependencies:
'@typescript-eslint/scope-manager': 8.16.0
'@typescript-eslint/types': 8.16.0
'@typescript-eslint/typescript-estree': 8.16.0(typescript@5.7.2)
'@typescript-eslint/visitor-keys': 8.16.0
'@typescript-eslint/scope-manager': 8.17.0
'@typescript-eslint/types': 8.17.0
'@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2)
'@typescript-eslint/visitor-keys': 8.17.0
debug: 4.3.7
eslint: 8.57.1
optionalDependencies:
@@ -10409,15 +10406,15 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/scope-manager@8.16.0':
'@typescript-eslint/scope-manager@8.17.0':
dependencies:
'@typescript-eslint/types': 8.16.0
'@typescript-eslint/visitor-keys': 8.16.0
'@typescript-eslint/types': 8.17.0
'@typescript-eslint/visitor-keys': 8.17.0
'@typescript-eslint/type-utils@8.16.0(eslint@8.57.1)(typescript@5.7.2)':
'@typescript-eslint/type-utils@8.17.0(eslint@8.57.1)(typescript@5.7.2)':
dependencies:
'@typescript-eslint/typescript-estree': 8.16.0(typescript@5.7.2)
'@typescript-eslint/utils': 8.16.0(eslint@8.57.1)(typescript@5.7.2)
'@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2)
'@typescript-eslint/utils': 8.17.0(eslint@8.57.1)(typescript@5.7.2)
debug: 4.3.7
eslint: 8.57.1
ts-api-utils: 1.3.0(typescript@5.7.2)
@@ -10426,12 +10423,12 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/types@8.16.0': {}
'@typescript-eslint/types@8.17.0': {}
'@typescript-eslint/typescript-estree@8.16.0(typescript@5.7.2)':
'@typescript-eslint/typescript-estree@8.17.0(typescript@5.7.2)':
dependencies:
'@typescript-eslint/types': 8.16.0
'@typescript-eslint/visitor-keys': 8.16.0
'@typescript-eslint/types': 8.17.0
'@typescript-eslint/visitor-keys': 8.17.0
debug: 4.3.7
fast-glob: 3.3.2
is-glob: 4.0.3
@@ -10443,26 +10440,26 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@8.16.0(eslint@8.57.1)(typescript@5.7.2)':
'@typescript-eslint/utils@8.17.0(eslint@8.57.1)(typescript@5.7.2)':
dependencies:
'@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1)
'@typescript-eslint/scope-manager': 8.16.0
'@typescript-eslint/types': 8.16.0
'@typescript-eslint/typescript-estree': 8.16.0(typescript@5.7.2)
'@typescript-eslint/scope-manager': 8.17.0
'@typescript-eslint/types': 8.17.0
'@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2)
eslint: 8.57.1
optionalDependencies:
typescript: 5.7.2
transitivePeerDependencies:
- supports-color
'@typescript-eslint/visitor-keys@8.16.0':
'@typescript-eslint/visitor-keys@8.17.0':
dependencies:
'@typescript-eslint/types': 8.16.0
'@typescript-eslint/types': 8.17.0
eslint-visitor-keys: 4.2.0
'@ungap/structured-clone@1.2.0': {}
'@vitejs/plugin-legacy@6.0.0(terser@5.36.0)(vite@6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))':
'@vitejs/plugin-legacy@6.0.0(terser@5.36.0)(vite@6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))':
dependencies:
'@babel/core': 7.26.0
'@babel/preset-env': 7.26.0(@babel/core@7.26.0)
@@ -10473,25 +10470,25 @@ snapshots:
regenerator-runtime: 0.14.1
systemjs: 6.15.1
terser: 5.36.0
vite: 6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)
vite: 6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)
transitivePeerDependencies:
- supports-color
'@vitejs/plugin-react-swc@3.7.2(vite@6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))':
'@vitejs/plugin-react-swc@3.7.2(vite@6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))':
dependencies:
'@swc/core': 1.7.26
vite: 6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)
vite: 6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)
transitivePeerDependencies:
- '@swc/helpers'
'@vitejs/plugin-react@4.3.4(vite@6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))':
'@vitejs/plugin-react@4.3.4(vite@6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))':
dependencies:
'@babel/core': 7.26.0
'@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.0)
'@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.0)
'@types/babel__core': 7.20.5
react-refresh: 0.14.2
vite: 6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)
vite: 6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)
transitivePeerDependencies:
- supports-color
@@ -11790,16 +11787,16 @@ snapshots:
dependencies:
eslint: 8.57.1
eslint-config-standard@17.1.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.16.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1))(eslint-plugin-n@17.14.0(eslint@8.57.1))(eslint-plugin-promise@7.2.1(eslint@8.57.1))(eslint@8.57.1):
eslint-config-standard@17.1.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.17.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1))(eslint-plugin-n@17.14.0(eslint@8.57.1))(eslint-plugin-promise@7.2.1(eslint@8.57.1))(eslint@8.57.1):
dependencies:
eslint: 8.57.1
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.16.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.17.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)
eslint-plugin-n: 17.14.0(eslint@8.57.1)
eslint-plugin-promise: 7.2.1(eslint@8.57.1)
eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.16.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)):
eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.17.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)):
dependencies:
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.16.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.17.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)
eslint-import-resolver-node@0.3.9:
dependencies:
@@ -11809,11 +11806,11 @@ snapshots:
transitivePeerDependencies:
- supports-color
eslint-module-utils@2.12.0(@typescript-eslint/parser@8.16.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1):
eslint-module-utils@2.12.0(@typescript-eslint/parser@8.17.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1):
dependencies:
debug: 3.2.7
optionalDependencies:
'@typescript-eslint/parser': 8.16.0(eslint@8.57.1)(typescript@5.7.2)
'@typescript-eslint/parser': 8.17.0(eslint@8.57.1)(typescript@5.7.2)
eslint: 8.57.1
eslint-import-resolver-node: 0.3.9
transitivePeerDependencies:
@@ -11830,7 +11827,7 @@ snapshots:
dependencies:
htmlparser2: 9.1.0
eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.16.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1):
eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.17.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.8
@@ -11841,7 +11838,7 @@ snapshots:
doctrine: 2.1.0
eslint: 8.57.1
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.16.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1)
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.17.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1)
hasown: 2.0.2
is-core-module: 2.15.1
is-glob: 4.0.3
@@ -11853,7 +11850,7 @@ snapshots:
string.prototype.trimend: 1.0.8
tsconfig-paths: 3.15.0
optionalDependencies:
'@typescript-eslint/parser': 8.16.0(eslint@8.57.1)(typescript@5.7.2)
'@typescript-eslint/parser': 8.17.0(eslint@8.57.1)(typescript@5.7.2)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
@@ -11871,10 +11868,10 @@ snapshots:
minimatch: 9.0.5
semver: 7.6.3
eslint-plugin-prettier@5.2.1(eslint-config-prettier@9.1.0(eslint@8.57.1))(eslint@8.57.1)(prettier@3.4.1):
eslint-plugin-prettier@5.2.1(eslint-config-prettier@9.1.0(eslint@8.57.1))(eslint@8.57.1)(prettier@3.4.2):
dependencies:
eslint: 8.57.1
prettier: 3.4.1
prettier: 3.4.2
prettier-linter-helpers: 1.0.0
synckit: 0.9.1
optionalDependencies:
@@ -13660,8 +13657,6 @@ snapshots:
registry-url: 3.1.0
semver: 5.7.2
package-manager-detector@0.2.0: {}
package-manager-detector@0.2.5: {}
pako@2.1.0: {}
@@ -13897,21 +13892,21 @@ snapshots:
dependencies:
fast-diff: 1.3.0
prettier-plugin-tailwindcss@0.6.9(@ianvs/prettier-plugin-sort-imports@4.4.0(prettier@3.4.1))(@trivago/prettier-plugin-sort-imports@4.3.0(prettier@3.4.1))(prettier@3.4.1):
prettier-plugin-tailwindcss@0.6.9(@ianvs/prettier-plugin-sort-imports@4.4.0(prettier@3.4.2))(@trivago/prettier-plugin-sort-imports@4.3.0(prettier@3.4.2))(prettier@3.4.2):
dependencies:
prettier: 3.4.1
prettier: 3.4.2
optionalDependencies:
'@ianvs/prettier-plugin-sort-imports': 4.4.0(prettier@3.4.1)
'@trivago/prettier-plugin-sort-imports': 4.3.0(prettier@3.4.1)
'@ianvs/prettier-plugin-sort-imports': 4.4.0(prettier@3.4.2)
'@trivago/prettier-plugin-sort-imports': 4.3.0(prettier@3.4.2)
prettier-plugin-toml@2.0.1(prettier@3.4.1):
prettier-plugin-toml@2.0.1(prettier@3.4.2):
dependencies:
'@taplo/lib': 0.4.0-alpha.2
prettier: 3.4.1
prettier: 3.4.2
prettier@2.8.8: {}
prettier@3.4.1: {}
prettier@3.4.2: {}
pretty-hrtime@1.0.3: {}
@@ -15124,7 +15119,7 @@ snapshots:
dependencies:
'@fastify/busboy': 2.1.1
undici@7.0.0: {}
undici@7.1.0: {}
unicode-canonical-property-names-ecmascript@2.0.1: {}
@@ -15222,7 +15217,7 @@ snapshots:
transitivePeerDependencies:
- rollup
unplugin-icons@0.20.2(@svgr/core@8.1.0(typescript@5.7.2)):
unplugin-icons@0.21.0(@svgr/core@8.1.0(typescript@5.7.2)):
dependencies:
'@antfu/install-pkg': 0.5.0
'@antfu/utils': 0.7.10
@@ -15328,7 +15323,7 @@ snapshots:
- rollup
- supports-color
vite-plugin-dts@4.3.0(@types/node@22.10.1)(rollup@4.27.4)(typescript@5.7.2)(vite@6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)):
vite-plugin-dts@4.3.0(@types/node@22.10.1)(rollup@4.27.4)(typescript@5.7.2)(vite@6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)):
dependencies:
'@microsoft/api-extractor': 7.47.11(@types/node@22.10.1)
'@rollup/pluginutils': 5.1.0(rollup@4.27.4)
@@ -15341,43 +15336,43 @@ snapshots:
magic-string: 0.30.11
typescript: 5.7.2
optionalDependencies:
vite: 6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)
vite: 6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)
transitivePeerDependencies:
- '@types/node'
- rollup
- supports-color
vite-plugin-sass-dts@1.3.29(postcss@8.4.49)(prettier@3.4.1)(sass-embedded@1.78.0)(vite@6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)):
vite-plugin-sass-dts@1.3.29(postcss@8.4.49)(prettier@3.4.2)(sass-embedded@1.78.0)(vite@6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)):
dependencies:
postcss: 8.4.49
postcss-js: 4.0.1(postcss@8.4.49)
prettier: 3.4.1
prettier: 3.4.2
sass-embedded: 1.78.0
vite: 6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)
vite: 6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)
vite-plugin-svgr@4.3.0(rollup@4.27.4)(typescript@5.7.2)(vite@6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)):
vite-plugin-svgr@4.3.0(rollup@4.27.4)(typescript@5.7.2)(vite@6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)):
dependencies:
'@rollup/pluginutils': 5.1.3(rollup@4.27.4)
'@svgr/core': 8.1.0(typescript@5.7.2)
'@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.7.2))
vite: 6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)
vite: 6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)
transitivePeerDependencies:
- rollup
- supports-color
- typescript
vite-tsconfig-paths@5.1.3(typescript@5.7.2)(vite@6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)):
vite-tsconfig-paths@5.1.3(typescript@5.7.2)(vite@6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)):
dependencies:
debug: 4.3.7
globrex: 0.1.2
tsconfck: 3.0.3(typescript@5.7.2)
optionalDependencies:
vite: 6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)
vite: 6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)
transitivePeerDependencies:
- supports-color
- typescript
vite@6.0.2(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1):
vite@6.0.3(@types/node@22.10.1)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1):
dependencies:
esbuild: 0.24.0
postcss: 8.4.49

View File

@@ -22,6 +22,6 @@
"picocolors": "1.1.1",
"tar": "7.4.3",
"telegram": "2.26.8",
"undici": "7.0.0"
"undici": "7.1.0"
}
}

View File

@@ -1,2 +1,2 @@
LINUX_VERSION-6.12 = .1
LINUX_KERNEL_HASH-6.12.1 = 0193b1d86dd372ec891bae799f6da20deef16fc199f30080a4ea9de8cef0c619
LINUX_VERSION-6.12 = .3
LINUX_KERNEL_HASH-6.12.3 = c89809cc777d50f1ea484a118630281a26383707a0e752c96fd834f6e765deae

View File

@@ -42,8 +42,27 @@ endef
# The last two DEPENDS are hacks in order to get CONFIG_ASN1 and CONFIG_OID_REGISTRY
# which it seems can't be selected independently. Some bug in either base or upstream.
define KernelPackage/fs-ksmbd/description
Ksmbd is an In-kernel SMBv(1)2/3 fileserver.
It's an implementation of the SMB protocol in kernel space for sharing files and IPC services over network.
endef
define KernelPackage/fs-ksmbd/config
config KSMBD_SMB_INSECURE_SERVER
bool "Support for insecure SMB1/CIFS and SMB2.0 protocols"
depends on PACKAGE_kmod-fs-ksmbd
help
This enables deprecated insecure protocols dialects: SMB1/CIFS and SMB2.0.
default n
endef
ifeq ($(CONFIG_KSMBD_SMB_INSECURE_SERVER),y)
PKG_EXTRA_KCONFIG:=CONFIG_SMB_INSECURE_SERVER=y
EXTRA_CFLAGS += -DCONFIG_SMB_INSECURE_SERVER=1
endif
define Build/Compile
$(KERNEL_MAKE) M="$(PKG_BUILD_DIR)" \
EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
$(PKG_EXTRA_KCONFIG) \
CONFIG_SMB_SERVER=m \
modules
endef

View File

@@ -5,7 +5,7 @@
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 9, 0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 60)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 110)
static inline bool is_dot_dotdot(const char *name, size_t len)
{
return len && unlikely(name[0] == '.') &&

View File

@@ -13,7 +13,7 @@ PKG_DATE:=2022-07-05
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/mbuesch/b43-tools.git
PKG_SOURCE_VERSION:=2fe10ea6690df9a068cb21cde537236bae784a14
PKG_MIRROR_HASH:=4009d6c1f9ede43102897d6ebf4bd954331f3c4e2a94d4e61c0e5f303f929914
PKG_MIRROR_HASH:=4f1cde5da35a1e768f6a01d67888549d04512073990769342381af1b2c9e7fd2
include $(INCLUDE_DIR)/host-build.mk

View File

@@ -12,7 +12,7 @@ PKG_SOURCE_DATE := 2017-04-13
PKG_SOURCE_PROTO := git
PKG_SOURCE_URL := https://github.com/NVIDIA/cbootimage-configs.git
PKG_SOURCE_VERSION := 7c3b458b93ed6947cd083623f543e93f9103cc0f
PKG_MIRROR_HASH := 6ba2dde907d3cc403720954738a92431b1f40d562db5815c08971c39374d72a1
PKG_MIRROR_HASH := 1d24421af8cf74ec2d625e237aa8121b1273774c4380ad333e2954e052a5a4fe
include $(INCLUDE_DIR)/host-build.mk

View File

@@ -12,7 +12,7 @@ PKG_VERSION := 1.8
PKG_SOURCE_PROTO := git
PKG_SOURCE_URL := https://github.com/NVIDIA/cbootimage.git
PKG_SOURCE_VERSION := 7c9db585d06cce9efffa2a82245f233233680060
PKG_MIRROR_HASH := e38b1e9581524fcabc7b24fff1c18d13f7e3a93accf73c55caf33832249bfd03
PKG_MIRROR_HASH := 84d9abaaa3eddde05f506dc16effe1c9e18eb94727ed59c5e0a879baeb04e0b2
HOST_BUILD_PARALLEL := 1

View File

@@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=e2fsprogs
PKG_CPE_ID:=cpe:/a:e2fsprogs_project:e2fsprogs
PKG_VERSION:=1.46.6
PKG_HASH:=skip
PKG_HASH:=8749efc57cda3b6cfcb16a2d2ccd8b8be676c8827e5bae338aa327219a9c2fc4
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz

View File

@@ -13,7 +13,7 @@ PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=$(PROJECT_GIT)/project/firmware-utils.git
PKG_SOURCE_DATE:=2024-10-20
PKG_SOURCE_VERSION:=4b7638925d3eac03e614e40bc30cb49f5877c46d
PKG_MIRROR_HASH:=ea0e30f2b20211e4153704019ebb3f8789269893a4af6d853a85fae7c091802c
PKG_MIRROR_HASH:=849193bcd9b7be96eada2219f3e8b2d229186cae4e4b7a8746375480fbcd2683
include $(INCLUDE_DIR)/host-build.mk
include $(INCLUDE_DIR)/cmake.mk

View File

@@ -13,7 +13,7 @@ PKG_SOURCE_URL=$(PROJECT_GIT)/project/make_ext4fs.git
PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2020-01-05
PKG_SOURCE_VERSION:=5c201be7d72aff735da27e17c29852e0cefe3e52
PKG_MIRROR_HASH:=ec8304dc06f94338e14e608a807f48e10d0987bdac4d90f235650b46994dfbd7
PKG_MIRROR_HASH:=a9b74b7b95acc84a5a5c33d6acf493faad8f161caca3180734d9bd383c9d823f
include $(INCLUDE_DIR)/host-build.mk

View File

@@ -13,7 +13,7 @@ PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/mhei/fsl-imx-uuc.git
PKG_SOURCE_DATE:=2018-11-18
PKG_SOURCE_VERSION:=c6536ac5b4388b33c217bde2c3a76a4e96d64176
PKG_MIRROR_HASH:=c4487635ea06ea6311a28739c58f7f889b888c91b7ccc0398d225b4bcdeb76a3
PKG_MIRROR_HASH:=747fb640a0596cab7d516979188e1f85be58c470df85cf1f7e3dcf8a4c1b36e5
PKG_LICENSE:=GPL-2.0+
PKG_LICENSE_FILES:=LICENSE

View File

@@ -15,7 +15,7 @@ PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/plougher/squashfs-tools
PKG_SOURCE_DATE:=2023-03-26
PKG_SOURCE_VERSION:=d8cb82d9840330f9344ec37b992595b5d7b44184
PKG_MIRROR_HASH:=e84026de1ab187f3f76d1b781a29259d818f887e1651225f850a62d6f90b1b9e
PKG_MIRROR_HASH:=fc625af657ca284d69fbc32e3bb572d0afd566cf816b7c1c1b66dda0a0c2760a
HOST_BUILD_PARALLEL:=1

View File

@@ -20,5 +20,6 @@ package protocol
import "time"
const (
outputLoopInterval = 1 * time.Millisecond
// tickInterval is the event trigger interval.
tickInterval = 1 * time.Millisecond
)

View File

@@ -20,5 +20,6 @@ package protocol
import "time"
const (
outputLoopInterval = 10 * time.Millisecond
// tickInterval is the event trigger interval.
tickInterval = 5 * time.Millisecond
)

View File

@@ -129,7 +129,7 @@ var _ net.Conn = &Session{}
// NewSession creates a new session.
func NewSession(id uint32, isClient bool, mtu int, users map[string]*appctlpb.User) *Session {
rttStat := congestion.NewRTTStats()
rttStat.SetMaxAckDelay(outputLoopInterval)
rttStat.SetMaxAckDelay(tickInterval)
rttStat.SetRTOMultiplier(txTimeoutBackOff)
return &Session{
conn: nil,
@@ -300,16 +300,16 @@ func (s *Session) Write(b []byte) (n int, err error) {
}
}
n = len(b)
if log.IsLevelEnabled(log.TraceLevel) {
log.Tracef("%v writing %d bytes", s, n)
}
for len(b) > 0 {
sizeToSend := mathext.Min(len(b), maxPDU)
if _, err = s.writeChunk(b[:sizeToSend]); err != nil {
return 0, err
if sent, err := s.writeChunk(b[:sizeToSend]); sent == 0 || err != nil {
return n, err
}
b = b[sizeToSend:]
n += sizeToSend
}
if log.IsLevelEnabled(log.TraceLevel) {
log.Tracef("%v wrote %d bytes", s, n)
@@ -430,11 +430,16 @@ func (s *Session) writeChunk(b []byte) (n int, err error) {
seqBeforeWrite, _ := s.sendQueue.MinSeq()
// Determine number of fragments to write.
// Return if there is no enough space in send queue.
nFragment := 1
fragmentSize := MaxFragmentSize(s.mtu, s.conn.TransportProtocol())
if len(b) > fragmentSize {
nFragment = (len(b)-1)/fragmentSize + 1
}
if s.sendQueue.Remaining() <= nFragment { // leave one slot in case it is needed
time.Sleep(tickInterval) // add back pressure
return 0, nil
}
s.oLock.Lock()
ptr := b
@@ -527,7 +532,7 @@ func (s *Session) runInputLoop(ctx context.Context) error {
}
func (s *Session) runOutputLoop(ctx context.Context) error {
ticker := time.NewTicker(outputLoopInterval)
ticker := time.NewTicker(tickInterval)
defer ticker.Stop()
for {
select {

View File

@@ -11,13 +11,13 @@ LUCI_DEPENDS:=+curl +opkg +luci-base +tar +libuci-lua +mount-utils +luci-lib-tas
LUCI_EXTRA_DEPENDS:=luci-lib-taskd (>=1.0.19)
LUCI_PKGARCH:=all
PKG_VERSION:=0.1.27-1
PKG_VERSION:=0.1.26-4
# PKG_RELEASE MUST be empty for luci.mk
PKG_RELEASE:=
ISTORE_UI_VERSION:=0.1.27
ISTORE_UI_RELEASE:=1
PKG_HASH:=e1cb70d586d880c18ef2d59848fcf6c60d3f827bfa662ea62de1fa0cbd385d39
ISTORE_UI_VERSION:=0.1.26
ISTORE_UI_RELEASE:=2
PKG_HASH:=01eb10649514c4ea0a86e848db1129b642f0ad5b5d371021821c2488454463fc
PKG_SOURCE_URL_FILE:=v$(ISTORE_UI_VERSION)-$(ISTORE_UI_RELEASE).tar.gz
PKG_SOURCE:=istore-ui-$(PKG_SOURCE_URL_FILE)

View File

@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=taskd
PKG_VERSION:=1.0.3
PKG_RELEASE:=1
PKG_RELEASE:=2
PKG_MAINTAINER:=jjm2473 <jjm2473@gmail.com>
include $(INCLUDE_DIR)/package.mk
@@ -18,7 +18,7 @@ define Package/$(PKG_NAME)
SECTION:=utils
CATEGORY:=Utilities
TITLE:=Simple Task Manager
DEPENDS:=+procd +script-utils +coreutils-stty
DEPENDS:=+procd +script-utils +coreutils +coreutils-stty
PKGARCH:=all
endef

View File

@@ -216,6 +216,9 @@ function index_status()
local dns_shunt = uci:get(appname, "@global[0]", "dns_shunt") or "dnsmasq"
if dns_shunt == "smartdns" then
e.dns_mode_status = luci.sys.call("pidof smartdns >/dev/null") == 0
elseif dns_shunt == "chinadns-ng" then
local port = string.match(luci.sys.exec("cat /tmp/etc/passwall/acl/default/chinadns_ng.conf"), "bind%-port%s*(%d+)") or "65353"
e.dns_mode_status = luci.sys.call(string.format("netstat -apn | grep ':%s ' >/dev/null", port)) == 0
else
e.dns_mode_status = luci.sys.call("netstat -apn | grep ':15353 ' >/dev/null") == 0
end
@@ -258,19 +261,17 @@ function connect_status()
e.use_time = ""
local url = luci.http.formvalue("url")
local baidu = string.find(url, "baidu")
local enabled = uci:get(appname, "@global[0]", "enabled") or "0"
local chn_list = uci:get(appname, "@global[0]", "chn_list") or "direct"
local gfw_list = uci:get(appname, "@global[0]", "use_gfw_list") or "1"
local proxy_mode = uci:get(appname, "@global[0]", "tcp_proxy_mode") or "proxy"
local socks_port = uci:get(appname, "@global[0]", "tcp_node_socks_port") or "1070"
local local_proxy = uci:get(appname, "@global[0]", "localhost_proxy") or "1"
if enabled == "1" and local_proxy == "0" then
local socks_server = luci.sys.exec("[ -f /tmp/etc/passwall/acl/default/TCP_SOCKS_server ] && echo -n $(cat /tmp/etc/passwall/acl/default/TCP_SOCKS_server) || echo -n ''")
if socks_server ~= "" then
if (chn_list == "proxy" and gfw_list == "0" and proxy_mode ~= "proxy" and baidu ~= nil) or (chn_list == "0" and gfw_list == "0" and proxy_mode == "proxy") then
-- 中国列表+百度 or 全局
url = "-x socks5h://127.0.0.1:" .. socks_port .. " " .. url
url = "-x socks5h://" .. socks_server .. " " .. url
elseif baidu == nil then
-- 其他代理模式+百度以外网站
url = "-x socks5h://127.0.0.1:" .. socks_port .. " " .. url
url = "-x socks5h://" .. socks_server .. " " .. url
end
end
local result = luci.sys.exec('curl --connect-timeout 3 -o /dev/null -I -sk -w "%{http_code}:%{time_appconnect}" ' .. url)

View File

@@ -545,18 +545,18 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.22"
version = "4.5.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69371e34337c4c984bbe322360c2547210bf632eb2814bbe78a6e87a2935bd2b"
checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84"
dependencies = [
"clap_builder",
]
[[package]]
name = "clap_builder"
version = "4.5.22"
version = "4.5.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e24c1b4099818523236a8ca881d2b45db98dadfb4625cf6608c12069fcbbde1"
checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838"
dependencies = [
"anstream",
"anstyle",
@@ -567,9 +567,9 @@ dependencies = [
[[package]]
name = "clap_lex"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7"
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]]
name = "cmake"
@@ -3741,12 +3741,11 @@ dependencies = [
[[package]]
name = "tokio-rustls"
version = "0.26.0"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4"
checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37"
dependencies = [
"rustls",
"rustls-pki-types",
"tokio",
]

View File

@@ -36,7 +36,7 @@ RUN case "$TARGETARCH" in \
&& RUSTFLAGS="-C linker=$CC" CC=$CC cargo build --target "$RUST_TARGET" --release --features "full" \
&& mv target/$RUST_TARGET/release/ss* target/release/
FROM alpine:3.20 AS sslocal
FROM alpine:3.21 AS sslocal
# NOTE: Please be careful to change the path of these binaries, refer to #1149 for more information.
COPY --from=builder /root/shadowsocks-rust/target/release/sslocal /usr/bin/
@@ -46,7 +46,7 @@ COPY --from=builder /root/shadowsocks-rust/docker/docker-entrypoint.sh /usr/bin/
ENTRYPOINT [ "docker-entrypoint.sh" ]
CMD [ "sslocal", "--log-without-time", "-c", "/etc/shadowsocks-rust/config.json" ]
FROM alpine:3.20 AS ssserver
FROM alpine:3.21 AS ssserver
COPY --from=builder /root/shadowsocks-rust/target/release/ssserver /usr/bin/
COPY --from=builder /root/shadowsocks-rust/examples/config.json /etc/shadowsocks-rust/

View File

@@ -3,19 +3,23 @@ name: Build
on:
workflow_dispatch:
inputs:
tag:
description: "The tag version you want to build"
version:
description: "The version name"
push:
branches:
- dev-next
concurrency:
group: ${{ github.workflow }}-${{ github.event_name }}
cancel-in-progress: true
jobs:
calculate_tag:
calculate_version:
name: Calculate version
if: github.event_name != 'workflow_dispatch'
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.calculate.outputs.tag }}
version: ${{ steps.calculate.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
@@ -30,13 +34,14 @@ jobs:
run: |-
go install -v ./cmd/internal/read_tag # TODO: remove
git checkout dev
TAG=$(read_tag --nightly)
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
VERSION=$(read_tag --nightly)
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
build:
if: false
name: Build binary
runs-on: ubuntu-latest
needs:
- calculate_tag
- calculate_version
strategy:
matrix:
include:
@@ -52,6 +57,11 @@ jobs:
- name: linux_arm
goos: linux
goarch: arm
goarm: 6
- name: linux_arm_v7
goos: linux
goarch: arm
goarm: 7
- name: linux_s390x
goos: linux
goarch: s390x
@@ -85,6 +95,7 @@ jobs:
- name: android_arm
goos: android
goarch: arm
goarm: 7
- name: android_amd64
goos: android
goarch: amd64
@@ -136,16 +147,20 @@ jobs:
- name: Set tag
if: github.event_name == 'workflow_dispatch'
run: |-
git tag ${{ github.event.inputs.tag }}
git tag v${{ github.event.inputs.version }}
- name: Set nightly tag
if: github.event_name != 'workflow_dispatch'
run: |-
git tag ${{ needs.calculate_tag.outputs.tag }}
git tag v${{ needs.calculate_version.outputs.version }}
- name: Build
if: matrix.goos != 'android'
run: |-
goreleaser release --clean --split
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
GOPATH: ${{ env.HOME }}/go
GOARM: ${{ matrix.goarm }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
NFPM_KEY_PATH: ${{ env.HOME }}/.gnupg/sagernet.key
@@ -153,8 +168,12 @@ jobs:
- name: Build Android
if: matrix.goos == 'android'
run: |-
go run -v ./cmd/internal/build goreleaser release --clean --split
go install -v ./cmd/internal/build
GOOS=$BUILD_GOOS GOARCH=$BUILD_GOARCH build goreleaser release --clean --split
env:
BUILD_GOOS: ${{ matrix.goos }}
BUILD_GOARCH: ${{ matrix.goarch }}
GOARM: ${{ matrix.goarm }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
NFPM_KEY_PATH: ${{ env.HOME }}/.gnupg/sagernet.key
@@ -165,10 +184,11 @@ jobs:
name: binary-${{ matrix.name }}
path: 'dist'
build_android:
if: false
name: Build Android
runs-on: ubuntu-latest
needs:
- calculate_tag
- calculate_version
steps:
- name: Checkout
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
@@ -191,13 +211,11 @@ jobs:
- name: Set tag
if: github.event_name == 'workflow_dispatch'
run: |-
git tag ${{ github.event.inputs.tag }}
echo "TAG=${{ github.event.inputs.tag }}" >> "$GITHUB_ENV"
git tag v${{ github.event.inputs.version }}
- name: Set nightly tag
if: github.event_name != 'workflow_dispatch'
run: |-
git tag ${{ needs.calculate_tag.outputs.tag }}
echo "TAG=${{ needs.calculate_tag.outputs.tag }}" >> "$GITHUB_ENV"
git tag v${{ needs.calculate_version.outputs.version }}
- name: Build library
run: |-
make lib_install
@@ -209,9 +227,9 @@ jobs:
- name: Checkout dev branch
if: github.ref == 'refs/heads/dev-next'
run: |-
cd clients/android &&
git checkout dev &&
mkdir app/libs
cd clients/android
git checkout dev
mkdir app/libs
- name: Gradle cache
uses: actions/cache@v4
with:
@@ -219,7 +237,8 @@ jobs:
key: gradle-${{ hashFiles('**/*.gradle') }}
- name: Build Android
run: |-
mv libbox.aar clients/android/app/libs
go run -v ./cmd/internal/update_android_version --ci
cp libbox.aar clients/android/app/libs
pushd clients/android
./gradlew :app:assemblePlayRelease :app:assembleOtherRelease
popd
@@ -233,15 +252,210 @@ jobs:
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: binary-android
name: binary-android-apks
path: 'dist'
build_apple_library:
name: Build Apple library
runs-on: macos-15
needs:
- calculate_version
steps:
- name: Checkout
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
fetch-depth: 0
submodules: 'recursive'
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ^1.23
- name: Setup Xcode
run: |-
sudo xcode-select -s /Applications/Xcode_16.2_beta_3.app
- name: Set tag
if: github.event_name == 'workflow_dispatch'
run: |-
git tag v${{ github.event.inputs.version }}
- name: Set nightly tag
if: github.event_name != 'workflow_dispatch'
run: |-
git tag v${{ needs.calculate_version.outputs.version }}
- name: Build library
run: |-
make lib_install
export PATH="$PATH:$(go env GOPATH)/bin"
make lib_ios
- name: Upload library
uses: actions/upload-artifact@v4
with:
name: library-apple
path: 'Libbox.xcframework'
build_apple:
name: Build Apple clients
runs-on: macos-15
needs:
- calculate_version
- build_apple_library
strategy:
fail-fast: false
matrix:
include:
- name: iOS
scheme: SFI
destination: 'generic/platform=iOS'
archive: build/SFI.xcarchive
upload: SFI/Upload.plist
- name: macOS
scheme: SFM
destination: 'generic/platform=macOS'
archive: build/SFM.xcarchive
upload: SFI/Upload.plist
- name: tvOS
scheme: SFT
destination: 'generic/platform=tvOS'
archive: build/SFT.xcarchive
upload: SFI/Upload.plist
- name: macOS-standalone
scheme: SFM.System
destination: 'generic/platform=macOS'
archive: build/SFM.System.xcarchive
export: SFM.System/Export.plist
export_path: build/SFM.System
steps:
- name: Checkout
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
fetch-depth: 0
submodules: 'recursive'
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ^1.23
- name: Setup Xcode
run: |-
sudo xcode-select -s /Applications/Xcode_16.2_beta_3.app
- name: Set tag
if: github.event_name == 'workflow_dispatch'
run: |-
git tag v${{ github.event.inputs.version }}
echo "VERSION=${{ github.event.inputs.version }}" >> "$GITHUB_ENV"
- name: Set nightly tag
if: github.event_name != 'workflow_dispatch'
run: |-
git tag v${{ needs.calculate_version.outputs.version }}
echo "VERSION=${{ needs.calculate_version.outputs.version }}" >> "$GITHUB_ENV"
- name: Checkout dev branch
if: github.ref == 'refs/heads/dev-next'
run: |-
pushd clients/apple
git checkout dev
popd
go run -v ./cmd/internal/update_apple_version --ci
- name: Setup certificates
run: |-
CERTIFICATE_PATH=$RUNNER_TEMP/Certificates.p12
KEYCHAIN_PATH=$RUNNER_TEMP/certificates.keychain-db
echo -n "$CERTIFICATES_P12" | base64 --decode -o $CERTIFICATE_PATH
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH
PROFILES_ZIP_PATH=$RUNNER_TEMP/Profiles.zip
echo -n "$PROVISIONING_PROFILES" | base64 --decode -o $PROFILES_ZIP_PATH
PROFILES_PATH="$HOME/Library/MobileDevice/Provisioning Profiles"
mkdir -p "$PROFILES_PATH"
unzip $PROFILES_ZIP_PATH -d "$PROFILES_PATH"
ASC_KEY_PATH=$RUNNER_TEMP/Key.p12
echo -n "$ASC_KEY" | base64 --decode -o $ASC_KEY_PATH
xcrun notarytool store-credentials "notarytool-password" \
--key $ASC_KEY_PATH \
--key-id $ASC_KEY_ID \
--issuer $ASC_KEY_ISSUER_ID
env:
CERTIFICATES_P12: ${{ secrets.CERTIFICATES_P12 }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.P12_PASSWORD }}
PROVISIONING_PROFILES: ${{ secrets.PROVISIONING_PROFILES }}
ASC_KEY: ${{ secrets.ASC_KEY }}
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_KEY_ISSUER_ID: ${{ secrets.ASC_KEY_ISSUER_ID }}
- name: Download library
uses: actions/download-artifact@v4
with:
name: library-apple
path: clients/apple/Libbox.xcframework
- name: Build
run: |-
cd clients/apple
xcodebuild archive \
-scheme "${{ matrix.scheme }}" \
-configuration Release \
-destination "${{ matrix.destination }}" \
-archivePath "${{ matrix.archive }}" \
-allowProvisioningUpdates \
-authenticationKeyPath $RUNNER_TEMP/Key.p12 \
-authenticationKeyID $ASC_KEY_ID \
-authenticationKeyIssuerID $ASC_KEY_ISSUER_ID
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_KEY_ISSUER_ID: ${{ secrets.ASC_KEY_ISSUER_ID }}
- name: Upload to App Store Connect
if: matrix.name != 'macOS-standalone'
run: |-
cd clients/apple
xcodebuild -verbose -exportArchive \
-archivePath "${{ matrix.archive }}" \
-exportOptionsPlist ${{ matrix.upload }} \
-allowProvisioningUpdates \
-authenticationKeyPath $RUNNER_TEMP/Key.p12 \
-authenticationKeyID $ASC_KEY_ID \
-authenticationKeyIssuerID $ASC_KEY_ISSUER_ID
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_KEY_ISSUER_ID: ${{ secrets.ASC_KEY_ISSUER_ID }}
- name: Build image
if: matrix.name == 'macOS-standalone'
run: |-
pushd clients/apple
xcodebuild -exportArchive \
-archivePath "${{ matrix.archive }}" \
-exportOptionsPlist ${{ matrix.export }} \
-exportPath "${{ matrix.export_path }}"
brew install create-dmg
create-dmg \
--volname "sing-box" \
--volicon "${{ matrix.export_path }}/SFM.app/Contents/Resources/AppIcon.icns" \
--icon "SFM.app" 0 0 \
--hide-extension "SFM.app" \
--app-drop-link 0 0 \
--skip-jenkins \
SFM.dmg "${{ matrix.export_path }}/SFM.app"
xcrun notarytool submit "SFM.dmg" --wait --keychain-profile "notarytool-password"
popd
mkdir dist
cp clients/apple/SFM.dmg "dist/SFM-${VERSION}-universal.dmg"
- name: Upload image
if: matrix.name == 'macOS-standalone'
uses: actions/upload-artifact@v4
with:
name: binary-macos-dmg
path: 'dist'
upload:
if: false
name: Upload builds
runs-on: ubuntu-latest
needs:
- calculate_tag
- calculate_version
- build
- build_android
- build_apple
steps:
- name: Checkout
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
@@ -263,41 +477,46 @@ jobs:
- name: Setup ghr
if: steps.cache-ghr.outputs.cache-hit != 'true'
run: |-
git clone https://github.com/nekohasekai/ghr $HOME/ghr
cd $HOME/ghr && go install -v .
cd $HOME
git clone https://github.com/nekohasekai/ghr ghr
cd ghr
go install -v .
- name: Set tag
if: github.event_name == 'workflow_dispatch'
run: |-
git tag ${{ github.event.inputs.tag }}
echo "TAG=${{ github.event.inputs.tag }}" >> "$GITHUB_ENV"
git tag v${{ github.event.inputs.version }}
echo "VERSION=${{ github.event.inputs.version }}" >> "$GITHUB_ENV"
- name: Set nightly tag
if: github.event_name != 'workflow_dispatch'
run: |-
git tag ${{ needs.calculate_tag.outputs.tag }}
echo "TAG=${{ needs.calculate_tag.outputs.tag }}" >> "$GITHUB_ENV"
git tag v${{ needs.calculate_version.outputs.version }}
echo "VERSION=${{ needs.calculate_version.outputs.version }}" >> "$GITHUB_ENV"
- name: Download builds
uses: actions/download-artifact@v4
with:
path: dist/tmp
pattern: binary-*
# merge-multiple: true
path: dist
merge-multiple: true
- name: Merge builds
run: |-
mv dist/tmp/*/* dist
goreleaser continue --merge --skip publish
mkdir -p dist/release
mv dist/*.tar.gz \
dist/*.zip \
dist/*.deb \
dist/*.rpm \
dist/*_amd64.pkg.tar.zst \
dist/*_arm64.pkg.tar.zst \
mv dist/*/*.tar.gz \
dist/*/*.zip \
dist/*/*.deb \
dist/*/*.rpm \
dist/*/*_amd64.pkg.tar.zst \
dist/*/*_arm64.pkg.tar.zst \
dist/release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
- name: Upload builds
run: |-
ghr --replace --draft --prerelease -p 5 "$TAG" dist/release
export PATH="$PATH:$HOME/go/bin"
ghr --replace --draft --prerelease -p 5 "v${VERSION}" dist/release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Delete artifacts
uses: geekyeggo/delete-artifact@v5
with:
name: binary-*

View File

@@ -1,6 +1,7 @@
package main
import (
"flag"
"os"
"path/filepath"
"runtime"
@@ -12,9 +13,22 @@ import (
"github.com/sagernet/sing/common"
)
var flagRunInCI bool
func init() {
flag.BoolVar(&flagRunInCI, "ci", false, "Run in CI")
}
func main() {
newVersion := common.Must1(build_shared.ReadTagVersion())
androidPath, err := filepath.Abs("../sing-box-for-android")
flag.Parse()
newVersion := common.Must1(build_shared.ReadTag())
var androidPath string
if flagRunInCI {
androidPath = "clients/android"
} else {
androidPath = "../sing-box-for-android"
}
androidPath, err := filepath.Abs(androidPath)
if err != nil {
log.Fatal(err)
}
@@ -31,10 +45,10 @@ func main() {
for _, propPair := range propsList {
switch propPair[0] {
case "VERSION_NAME":
if propPair[1] != newVersion.String() {
if propPair[1] != newVersion {
versionUpdated = true
propPair[1] = newVersion.String()
log.Info("updated version to ", newVersion.String())
propPair[1] = newVersion
log.Info("updated version to ", newVersion)
}
case "GO_VERSION":
if propPair[1] != runtime.Version() {

View File

@@ -1,6 +1,7 @@
package main
import (
"flag"
"os"
"path/filepath"
"regexp"
@@ -13,9 +14,22 @@ import (
"howett.net/plist"
)
var flagRunInCI bool
func init() {
flag.BoolVar(&flagRunInCI, "ci", false, "Run in CI")
}
func main() {
flag.Parse()
newVersion := common.Must1(build_shared.ReadTagVersion())
applePath, err := filepath.Abs("../sing-box-for-apple")
var applePath string
if flagRunInCI {
applePath = "clients/apple"
} else {
applePath = "../sing-box-for-apple"
}
applePath, err := filepath.Abs(applePath)
if err != nil {
log.Fatal(err)
}

View File

@@ -32,7 +32,7 @@ func groupRouter(server *Server) http.Handler {
func getGroups(server *Server) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
groups := common.Map(common.Filter(server.outboundManager.Outbounds(), func(it adapter.Outbound) bool {
groups := common.Map(common.Filter(server.outbound.Outbounds(), func(it adapter.Outbound) bool {
_, isGroup := it.(adapter.OutboundGroup)
return isGroup
}), func(it adapter.Outbound) *badjson.JSONObject {
@@ -86,7 +86,7 @@ func getGroupDelay(server *Server) func(w http.ResponseWriter, r *http.Request)
result, err = urlTestGroup.URLTest(ctx)
} else {
outbounds := common.FilterNotNil(common.Map(outboundGroup.All(), func(it string) adapter.Outbound {
itOutbound, _ := server.outboundManager.Outbound(it)
itOutbound, _ := server.outbound.Outbound(it)
return itOutbound
}))
b, _ := batch.New(ctx, batch.WithConcurrencyNum[any](10))
@@ -100,7 +100,7 @@ func getGroupDelay(server *Server) func(w http.ResponseWriter, r *http.Request)
continue
}
checked[realTag] = true
p, loaded := server.outboundManager.Outbound(realTag)
p, loaded := server.outbound.Outbound(realTag)
if !loaded {
continue
}

View File

@@ -46,7 +46,7 @@ func findProxyByName(server *Server) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
name := r.Context().Value(CtxKeyProxyName).(string)
proxy, exist := server.outboundManager.Outbound(name)
proxy, exist := server.outbound.Outbound(name)
if !exist {
render.Status(r, http.StatusNotFound)
render.JSON(w, r, ErrNotFound)
@@ -86,9 +86,14 @@ func proxyInfo(server *Server, detour adapter.Outbound) *badjson.JSONObject {
func getProxies(server *Server) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
var proxyMap badjson.JSONObject
outbounds := common.Filter(server.outboundManager.Outbounds(), func(detour adapter.Outbound) bool {
outbounds := common.Filter(server.outbound.Outbounds(), func(detour adapter.Outbound) bool {
return detour.Tag() != ""
})
outbounds = append(outbounds, common.Map(common.Filter(server.endpoint.Endpoints(), func(detour adapter.Endpoint) bool {
return detour.Tag() != ""
}), func(it adapter.Endpoint) adapter.Outbound {
return it
})...)
allProxies := make([]string, 0, len(outbounds))
@@ -100,7 +105,7 @@ func getProxies(server *Server) func(w http.ResponseWriter, r *http.Request) {
allProxies = append(allProxies, detour.Tag())
}
defaultTag := server.outboundManager.Default().Tag()
defaultTag := server.outbound.Default().Tag()
sort.SliceStable(allProxies, func(i, j int) bool {
return allProxies[i] == defaultTag

View File

@@ -40,16 +40,17 @@ func init() {
var _ adapter.ClashServer = (*Server)(nil)
type Server struct {
ctx context.Context
router adapter.Router
outboundManager adapter.OutboundManager
logger log.Logger
httpServer *http.Server
trafficManager *trafficontrol.Manager
urlTestHistory *urltest.HistoryStorage
mode string
modeList []string
modeUpdateHook chan<- struct{}
ctx context.Context
router adapter.Router
outbound adapter.OutboundManager
endpoint adapter.EndpointManager
logger log.Logger
httpServer *http.Server
trafficManager *trafficontrol.Manager
urlTestHistory *urltest.HistoryStorage
mode string
modeList []string
modeUpdateHook chan<- struct{}
externalController bool
externalUI string
@@ -61,10 +62,11 @@ func NewServer(ctx context.Context, logFactory log.ObservableFactory, options op
trafficManager := trafficontrol.NewManager()
chiRouter := chi.NewRouter()
s := &Server{
ctx: ctx,
router: service.FromContext[adapter.Router](ctx),
outboundManager: service.FromContext[adapter.OutboundManager](ctx),
logger: logFactory.NewLogger("clash-api"),
ctx: ctx,
router: service.FromContext[adapter.Router](ctx),
outbound: service.FromContext[adapter.OutboundManager](ctx),
endpoint: service.FromContext[adapter.EndpointManager](ctx),
logger: logFactory.NewLogger("clash-api"),
httpServer: &http.Server{
Addr: options.ExternalController,
Handler: chiRouter,
@@ -242,11 +244,11 @@ func (s *Server) TrafficManager() *trafficontrol.Manager {
}
func (s *Server) RoutedConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, matchedRule adapter.Rule, matchOutbound adapter.Outbound) net.Conn {
return trafficontrol.NewTCPTracker(conn, s.trafficManager, metadata, s.outboundManager, matchedRule, matchOutbound)
return trafficontrol.NewTCPTracker(conn, s.trafficManager, metadata, s.outbound, matchedRule, matchOutbound)
}
func (s *Server) RoutedPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, matchedRule adapter.Rule, matchOutbound adapter.Outbound) N.PacketConn {
return trafficontrol.NewUDPTracker(conn, s.trafficManager, metadata, s.outboundManager, matchedRule, matchOutbound)
return trafficontrol.NewUDPTracker(conn, s.trafficManager, metadata, s.outbound, matchedRule, matchOutbound)
}
func authentication(serverSecret string) func(next http.Handler) http.Handler {

View File

@@ -44,13 +44,13 @@ func (s *Server) downloadExternalUI() error {
s.logger.Info("downloading external ui")
var detour adapter.Outbound
if s.externalUIDownloadDetour != "" {
outbound, loaded := s.outboundManager.Outbound(s.externalUIDownloadDetour)
outbound, loaded := s.outbound.Outbound(s.externalUIDownloadDetour)
if !loaded {
return E.New("detour outbound not found: ", s.externalUIDownloadDetour)
}
detour = outbound
} else {
outbound := s.outboundManager.Default()
outbound := s.outbound.Default()
detour = outbound
}
httpClient := &http.Client{

View File

@@ -216,6 +216,9 @@ function index_status()
local dns_shunt = uci:get(appname, "@global[0]", "dns_shunt") or "dnsmasq"
if dns_shunt == "smartdns" then
e.dns_mode_status = luci.sys.call("pidof smartdns >/dev/null") == 0
elseif dns_shunt == "chinadns-ng" then
local port = string.match(luci.sys.exec("cat /tmp/etc/passwall/acl/default/chinadns_ng.conf"), "bind%-port%s*(%d+)") or "65353"
e.dns_mode_status = luci.sys.call(string.format("netstat -apn | grep ':%s ' >/dev/null", port)) == 0
else
e.dns_mode_status = luci.sys.call("netstat -apn | grep ':15353 ' >/dev/null") == 0
end
@@ -258,19 +261,17 @@ function connect_status()
e.use_time = ""
local url = luci.http.formvalue("url")
local baidu = string.find(url, "baidu")
local enabled = uci:get(appname, "@global[0]", "enabled") or "0"
local chn_list = uci:get(appname, "@global[0]", "chn_list") or "direct"
local gfw_list = uci:get(appname, "@global[0]", "use_gfw_list") or "1"
local proxy_mode = uci:get(appname, "@global[0]", "tcp_proxy_mode") or "proxy"
local socks_port = uci:get(appname, "@global[0]", "tcp_node_socks_port") or "1070"
local local_proxy = uci:get(appname, "@global[0]", "localhost_proxy") or "1"
if enabled == "1" and local_proxy == "0" then
local socks_server = luci.sys.exec("[ -f /tmp/etc/passwall/acl/default/TCP_SOCKS_server ] && echo -n $(cat /tmp/etc/passwall/acl/default/TCP_SOCKS_server) || echo -n ''")
if socks_server ~= "" then
if (chn_list == "proxy" and gfw_list == "0" and proxy_mode ~= "proxy" and baidu ~= nil) or (chn_list == "0" and gfw_list == "0" and proxy_mode == "proxy") then
-- 中国列表+百度 or 全局
url = "-x socks5h://127.0.0.1:" .. socks_port .. " " .. url
url = "-x socks5h://" .. socks_server .. " " .. url
elseif baidu == nil then
-- 其他代理模式+百度以外网站
url = "-x socks5h://127.0.0.1:" .. socks_port .. " " .. url
url = "-x socks5h://" .. socks_server .. " " .. url
end
end
local result = luci.sys.exec('curl --connect-timeout 3 -o /dev/null -I -sk -w "%{http_code}:%{time_appconnect}" ' .. url)

View File

@@ -18,16 +18,18 @@ LOG_FILE=/var/log/ssrplus.log
TMP_PATH=/var/etc/ssrplus
TMP_BIN_PATH=$TMP_PATH/bin
# 设置 DNSMASQ_CONF_DIR 和 TMP_DNSMASQ_PATH
[ -f /etc/openwrt_release ] && {
# 获取默认的 DNSMasq 配置 ID
DEFAULT_DNSMASQ_CFGID=$(uci show dhcp.@dnsmasq[0] | awk -F '.' '{print $2}' | awk -F '=' '{print $1}' | head -n 1)
# 查找包含 conf-dir 选项的 dnsmasq.conf 文件路径
DNSMASQ_CONF_PATH=$(grep -l "^conf-dir=" "/tmp/etc/dnsmasq.conf.${DEFAULT_DNSMASQ_CFGID}")
# 从 conf-dir 行中提取目录路径
DNSMASQ_CONF_DIR=$(grep '^conf-dir=' "$DNSMASQ_CONF_PATH" | cut -d'=' -f2 | head -n 1)
# 设置 TMP_DNSMASQ_PATH并去除路径末尾的斜杠
TMP_DNSMASQ_PATH="${DNSMASQ_CONF_DIR%*/}/dnsmasq-ssrplus.d"
}
if [ -f /etc/openwrt_release ]; then
# 获取默认的 DNSMASQ 配置 ID
DEFAULT_DNSMASQ_CFGID="$(uci -q show "dhcp.@dnsmasq[0]" | awk 'NR==1 {split($0, conf, /[.=]/); print conf[2]}')"
# 从 conf-dir 行中提取配置目录路径
if [ -f "/tmp/etc/dnsmasq.conf.$DEFAULT_DNSMASQ_CFGID" ]; then
DNSMASQ_CONF_DIR="$(awk -F '=' '/^conf-dir=/ {print $2}' "/tmp/etc/dnsmasq.conf.$DEFAULT_DNSMASQ_CFGID")"
else
DNSMASQ_CONF_DIR="/tmp/dnsmasq.d"
fi
# 设置 TMP_DNSMASQ_PATH并去除路径末尾的斜杠
TMP_DNSMASQ_PATH="${DNSMASQ_CONF_DIR%*/}/dnsmasq-ssrplus.d"
fi
chain_config_file= #generate shadowtls chain proxy config file
tcp_config_file=

View File

@@ -11,40 +11,24 @@ local args = arg[1]
local uci = luci.model.uci.cursor()
-- 以下设置更新数据库至 DNSMASQ 配置路径
-- 获取 DNSMasq 配置 ID
local DEFAULT_DNSMASQ_CFGID = uci:get_first("dhcp", "dnsmasq", ".name")
-- 获取 DNSMASQ 配置 ID
local DNSMASQ_UCI_CONFIG = uci:get_first("dhcp", "dnsmasq", ".name")
if not DEFAULT_DNSMASQ_CFGID then
error("未找到默认的 DNSMasq 配置 ID")
-- 获取 DNSMASQ 默认配置文件
local DNSMASQ_CONF_PATH = "/tmp/etc/dnsmasq.conf." .. DNSMASQ_UCI_CONFIG
-- 检查 DNSMASQ 配置文件是否存在,如果存在则提取 conf-dir
for line in io.lines(DNSMASQ_CONF_PATH) do
local conf_dir = line:match("^conf%-dir=(.+)")
if conf_dir then
DNSMASQ_CONF_DIR = conf_dir:gsub("%s+", "") -- 去除空白字符
break
end
end
-- 查找包含 conf-dir 选项的 dnsmasq.conf 文件路径
local DNSMASQ_CONF_PATH_CMD = string.format("grep -l '^conf-dir=' /tmp/etc/dnsmasq.conf.%s*", DEFAULT_DNSMASQ_CFGID)
local DNSMASQ_CONF_PATH = io.popen(DNSMASQ_CONF_PATH_CMD):read("*l")
if not DNSMASQ_CONF_PATH or DNSMASQ_CONF_PATH:match("^%s*$") then
error("无法找到包含 conf-dir 选项的 dnsmasq.conf 文件路径")
end
DNSMASQ_CONF_PATH = DNSMASQ_CONF_PATH:gsub("%s+", "") -- 去除空白字符
-- 获取 DNSMASQ 配置路径
local DNSMASQ_CONF_DIR_CMD = string.format("grep '^conf-dir=' %s | cut -d'=' -f2 | head -n 1", DNSMASQ_CONF_PATH)
local DNSMASQ_CONF_DIR = io.popen(DNSMASQ_CONF_DIR_CMD):read("*l")
if not DNSMASQ_CONF_DIR or DNSMASQ_CONF_DIR:match("^%s*$") then
error("无法提取 conf-dir 配置,请检查 dnsmasq.conf 文件内容")
end
DNSMASQ_CONF_DIR = DNSMASQ_CONF_DIR:gsub("%s+", "") -- 去除空白字符
-- 设置 dnsmasq-ssrplus.d 目录路径,并去除路径末尾的斜杠
local TMP_DNSMASQ_PATH = DNSMASQ_CONF_DIR:match("^(.-)/?$") .. "/dnsmasq-ssrplus.d"
if not TMP_DNSMASQ_PATH or TMP_DNSMASQ_PATH:match("^%s*$") then
error("无法找到包含 dnsmasq 选项的 dnsmasq-ssrplus.d 目录路径")
end
local TMP_PATH = "/var/etc/ssrplus"
-- match comments/title/whitelist/ip address/excluded_domain
local comment_pattern = "^[!\\[@]+"

View File

@@ -10,7 +10,7 @@ namespace ServiceLib.Common
{
private static readonly Lazy<HttpClientHelper> _instance = new(() =>
{
HttpClientHandler handler = new() { UseCookies = false };
SocketsHttpHandler handler = new() { UseCookies = false };
HttpClientHelper helper = new(new HttpClient(handler));
return helper;
});

View File

@@ -68,7 +68,8 @@
public const string AutoRunRegPath = @"Software\Microsoft\Windows\CurrentVersion\Run";
public const string AutoRunName = "v2rayNAutoRun";
public const string CustomIconName = "v2rayN.ico";
public const string IEProxyExceptions = "localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*";
public const string SystemProxyExceptionsWindows = "localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*";
public const string SystemProxyExceptionsLinux = "localhost, 127.0.0.0/8, ::1";
public const string RoutingRuleComma = "<COMMA>";
public const string GrpcGunMode = "gun";
public const string GrpcMultiMode = "multi";

View File

@@ -120,9 +120,14 @@ namespace ServiceLib.Handler
}
config.ConstItem ??= new ConstItem();
if (Utils.IsNullOrEmpty(config.ConstItem.DefIEProxyExceptions))
if (Utils.IsNotEmpty(config.ConstItem.DefIEProxyExceptions))
{
config.ConstItem.DefIEProxyExceptions = Global.IEProxyExceptions;
config.SystemProxyItem.SystemProxyExceptions = $"{config.ConstItem.DefIEProxyExceptions};{config.SystemProxyItem.SystemProxyExceptions}";
config.ConstItem.DefIEProxyExceptions = string.Empty;
}
if (config.SystemProxyItem.SystemProxyExceptions.IsNullOrEmpty())
{
config.SystemProxyItem.SystemProxyExceptions = Utils.IsWindows() ? Global.SystemProxyExceptionsWindows : Global.SystemProxyExceptionsLinux;
}
config.SpeedTestItem ??= new();

View File

@@ -2,9 +2,9 @@
{
public class ProxySettingLinux
{
public static async Task SetProxy(string host, int port)
public static async Task SetProxy(string host, int port, string exceptions)
{
var lstCmd = GetSetCmds(host, port);
var lstCmd = GetSetCmds(host, port, exceptions);
await ExecCmd(lstCmd);
}
@@ -29,7 +29,7 @@
}
}
private static List<CmdItem> GetSetCmds(string host, int port)
private static List<CmdItem> GetSetCmds(string host, int port, string exceptions)
{
var isKde = IsKde(out var configDir);
List<string> lstType = ["", "http", "https", "socks", "ftp"];
@@ -41,6 +41,10 @@
{
lstCmd.AddRange(GetSetCmd4Kde(type, host, port, configDir));
}
if (exceptions.IsNotEmpty())
{
lstCmd.AddRange(GetSetCmd4Kde("exceptions", exceptions, 0, configDir));
}
}
else
{
@@ -48,6 +52,10 @@
{
lstCmd.AddRange(GetSetCmd4Gnome(type, host, port));
}
if (exceptions.IsNotEmpty())
{
lstCmd.AddRange(GetSetCmd4Gnome("exceptions", exceptions, 0));
}
}
return lstCmd;
}
@@ -89,6 +97,14 @@
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", "ProxyType", "1"]
});
}
else if (type == "exceptions")
{
lstCmd.Add(new()
{
Cmd = "kwriteconfig5",
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", "NoProxyFor", host]
});
}
else
{
var type2 = type.Equals("https") ? "http" : type;
@@ -114,6 +130,14 @@
Arguments = ["set", "org.gnome.system.proxy", "mode", "manual"]
});
}
else if (type == "exceptions")
{
lstCmd.Add(new()
{
Cmd = "gsettings",
Arguments = ["set", $"org.gnome.system.proxy", "ignore-hosts", JsonUtils.Serialize(host.Split(','), false)]
});
}
else
{
lstCmd.Add(new()

View File

@@ -14,6 +14,7 @@
try
{
var port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
var exceptions = config.SystemProxyItem.SystemProxyExceptions;
if (port <= 0)
{
return false;
@@ -27,7 +28,7 @@
break;
}
case ESysProxyType.ForcedChange when Utils.IsLinux():
await ProxySettingLinux.SetProxy(Global.Loopback, port);
await ProxySettingLinux.SetProxy(Global.Loopback, port, exceptions);
break;
case ESysProxyType.ForcedChange when Utils.IsOSX():
@@ -65,7 +66,7 @@
private static void GetWindowsProxyString(Config config, int port, out string strProxy, out string strExceptions)
{
strExceptions = $"{config.ConstItem.DefIEProxyExceptions};{config.SystemProxyItem.SystemProxyExceptions}";
strExceptions = config.SystemProxyItem.SystemProxyExceptions;
if (config.SystemProxyItem.NotProxyLocalAddress)
{
strExceptions = $"<local>;{strExceptions}";

View File

@@ -3058,6 +3058,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Exception. Do not use proxy server for addresses,with a comma (,) 的本地化字符串。
/// </summary>
public static string TbSettingsExceptionTip2 {
get {
return ResourceManager.GetString("TbSettingsExceptionTip2", resourceCulture);
}
}
/// <summary>
/// 查找类似 Follow System Theme 的本地化字符串。
/// </summary>

View File

@@ -118,7 +118,7 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="BatchExportURLSuccessfully" xml:space="preserve">
<value>Batch export share URL to clipboard successfully</value>
<value>ارسال دسته ای آدرس اینترنتی اشتراک گذاری به کلیپ بورد با موفقیت.</value>
</data>
<data name="CheckServerSettings" xml:space="preserve">
<value>لطفا ابتدا تنظیمات سرور را بررسی کنید</value>
@@ -136,7 +136,7 @@
<value>دانلود</value>
</data>
<data name="DownloadYesNo" xml:space="preserve">
<value>Whether to download? {0}</value>
<value>آیا برای دانلود؟ {0}</value>
</data>
<data name="FailedConversionConfiguration" xml:space="preserve">
<value>تبدیل فایل پیکربندی انجام نشد</value>
@@ -226,7 +226,7 @@
<value>هیچ اشتراک معتبری تنظیم نشده است</value>
</data>
<data name="MsgParsingSuccessfully" xml:space="preserve">
<value>Resolve {0} successfully</value>
<value>حل {0} با موفقیت</value>
</data>
<data name="MsgStartGettingSubscriptions" xml:space="preserve">
<value>شروع به دریافت اشتراک شد</value>
@@ -253,19 +253,19 @@
<value>هسته با موفقیت بروزرسانی شد! راه اندازی مجدد سرویس...</value>
</data>
<data name="NonvmessOrssProtocol" xml:space="preserve">
<value>Non-VMess or ss protocol</value>
<value>پروتکل غیر VMess یا ss</value>
</data>
<data name="NotFoundCore" xml:space="preserve">
<value>The Core file (file name: {1}) was not found under the folder ({0}), please download and put it in the folder, download address: {2}</value>
<value>فایل Core (نام فایل: {1}) در زیر پوشه ({0}) یافت نشد، لطفاً آن را دانلود کرده و در پوشه قرار دهید، آدرس دانلود: {2}</value>
</data>
<data name="NoValidQRcodeFound" xml:space="preserve">
<value>Scan completed, no valid QR code found</value>
<value>اسکن کامل شد، QRcode معتبری یافت نشد</value>
</data>
<data name="OperationFailed" xml:space="preserve">
<value> عملیات انجام نشد، لطفا بررسی کنید و دوباره امتحان کنید</value>
</data>
<data name="PleaseFillRemarks" xml:space="preserve">
<value>Please Fill Remarks</value>
<value>لطفا ملاحظات را پر کنید</value>
</data>
<data name="PleaseSelectEncryption" xml:space="preserve">
<value>لطفاً روش رمزگذاری را انتخاب کنید</value>
@@ -277,16 +277,16 @@
<value>لطفا ابتدا سرور را انتخاب کنید</value>
</data>
<data name="RemoveDuplicateServerResult" xml:space="preserve">
<value>Servers deduplication completed. Old: {0}, New: {1}.</value>
<value>حذف مجدد سرورها تکمیل شد. قدیمی: {0}، جدید: {1}.</value>
</data>
<data name="RemoveServer" xml:space="preserve">
<value>آیا مطمئن هستید که سرور را حذف می کنید؟</value>
</data>
<data name="SaveClientConfigurationIn" xml:space="preserve">
<value>The client configuration file is saved at: {0}</value>
<value>فایل پیکربندی کلاینت در این آدرس ذخیره می شود: {0}</value>
</data>
<data name="StartService" xml:space="preserve">
<value>Start service ({0})...</value>
<value>شروع سرویس ({0})...</value>
</data>
<data name="SuccessfulConfiguration" xml:space="preserve">
<value>پیکربندی با موفقیت انجام شد
@@ -317,19 +317,19 @@
<value>{0},یکی از مورد نیاز.</value>
</data>
<data name="LvRemarks" xml:space="preserve">
<value>Remarks</value>
<value>ملاحظات</value>
</data>
<data name="LvUrl" xml:space="preserve">
<value>Url(Optional)</value>
<value>آدرس اینترنتی (اختیاری)</value>
</data>
<data name="LvCount" xml:space="preserve">
<value>Count</value>
<value>شمارش</value>
</data>
<data name="MsgNeedUrl" xml:space="preserve">
<value>Please fill in the address (Url)</value>
<value>لطفا آدرس (آدرس اینترنتی) را وارد کنید</value>
</data>
<data name="AddBatchRoutingRulesYesNo" xml:space="preserve">
<value>Do you want to append rules? Choose yes to append, choose otherwise to replace</value>
<value>آیا می خواهید قوانین را اضافه کنید؟ برای ضمیمه بله را انتخاب کنید، در غیر این صورت جایگزین کنید</value>
</data>
<data name="MsgDownloadGeoFileSuccessfully" xml:space="preserve">
<value>دانلود GeoFile: {0} با موفقیت</value>
@@ -386,10 +386,10 @@
<value>*Kcp seed</value>
</data>
<data name="RegisterGlobalHotkeyFailed" xml:space="preserve">
<value>Global hotkey {0} registered failed, reason {1}</value>
<value>کلید میانبر جهانی {0} ثبت نشد، دلیل کلید میانبر جهانی {0} ثبت ناموفق بود، دلیل {1}{1}</value>
</data>
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
<value>Global hotkey {0} registered successfully</value>
<value>کلید میانبر جهانی {0} با موفقیت ثبت شد</value>
</data>
<data name="UngroupedServers" xml:space="preserve">
<value>گروه بندی نشده</value>
@@ -398,7 +398,7 @@
<value>همه سرورها</value>
</data>
<data name="FillServerAddressCustom" xml:space="preserve">
<value>Please browse to import server configuration</value>
<value>لطفاً برای وارد کردن پیکربندی سرور مرور کنید</value>
</data>
<data name="Speedtesting" xml:space="preserve">
<value>درحال تست کردن...</value>
@@ -593,7 +593,7 @@
<value>آدرس</value>
</data>
<data name="TbAllowInsecure" xml:space="preserve">
<value>اجازه ناامن</value>
<value>اعطای مجوز ناامن</value>
</data>
<data name="TbAlpn" xml:space="preserve">
<value>Alpn</value>
@@ -602,10 +602,10 @@
<value>AlterId</value>
</data>
<data name="TbFingerprint" xml:space="preserve">
<value>Fingerprint</value>
<value>اثرانگشت</value>
</data>
<data name="TbHeaderType" xml:space="preserve">
<value>Camouflage type</value>
<value>نوع Camouflage</value>
</data>
<data name="TbId" xml:space="preserve">
<value>UUID(id)</value>
@@ -620,13 +620,13 @@
<value>پورت</value>
</data>
<data name="TbRemarks" xml:space="preserve">
<value>Alias (remarks)</value>
<value>نام مستعار (ملاحظات)</value>
</data>
<data name="TbRequestHost" xml:space="preserve">
<value>Camouflage domain(host)</value>
</data>
<data name="TbSecurity" xml:space="preserve">
<value>Encryption method (security)</value>
<value>روش رمزگذاری (امنیتی)</value>
</data>
<data name="TbSNI" xml:space="preserve">
<value>SNI</value>
@@ -635,7 +635,7 @@
<value>TLS</value>
</data>
<data name="TipNetwork" xml:space="preserve">
<value>*Default value tcp</value>
<value>*مقدار پیش فرض tcp</value>
</data>
<data name="TbCoreType" xml:space="preserve">
<value>نوع هسته</value>
@@ -644,7 +644,7 @@
<value>جریان</value>
</data>
<data name="TbGUID" xml:space="preserve">
<value>Generate</value>
<value>ساختن</value>
</data>
<data name="TbId3" xml:space="preserve">
<value>رمزعبور</value>
@@ -668,10 +668,10 @@
<value>txtPreSocksPort</value>
</data>
<data name="TipPreSocksPort" xml:space="preserve">
<value>* After setting this value, an socks service will be started using Xray/sing-box(Tun) to provide functions such as speed display</value>
<value>* پس از تنظیم این مقدار، یک سرویس جوراب با استفاده از Xray/sing-box (Tun) برای ارائه عملکردهایی مانند نمایش سرعت شروع می شود.</value>
</data>
<data name="TbBrowse" xml:space="preserve">
<value>Browse</value>
<value>مرور کردن</value>
</data>
<data name="TbEdit" xml:space="preserve">
<value>ویرایش</value>
@@ -683,7 +683,7 @@
<value>اتصالات از LAN را مجاز کنید</value>
</data>
<data name="TbSettingsAutoHideStartup" xml:space="preserve">
<value>Auto hide startup</value>
<value>راه اندازی مخفی کردن خودکار</value>
</data>
<data name="TbSettingsAutoUpdateInterval" xml:space="preserve">
<value>فاصله به روز رسانی خودکار و Geo (ساعت)</value>
@@ -692,7 +692,7 @@
<value>هسته: تنظیمات اولیه</value>
</data>
<data name="TbSettingsCoreDns" xml:space="preserve">
<value>V2ray DNS settings</value>
<value>تنظیمات V2ray DNS</value>
</data>
<data name="TbSettingsCoreKcp" xml:space="preserve">
<value>هسته: تنظیمات KCP</value>
@@ -701,7 +701,7 @@
<value>تنظیمات CoreType</value>
</data>
<data name="TbSettingsDefAllowInsecure" xml:space="preserve">
<value>اجازه ناامن</value>
<value>اعطای مجوز ناامن</value>
</data>
<data name="TbSettingsDomainStrategy4Freedom" xml:space="preserve">
<value>Outbound Freedom domainStrategy</value>
@@ -716,7 +716,7 @@
<value>استثنا</value>
</data>
<data name="TbSettingsExceptionTip" xml:space="preserve">
<value>Exception. Do not use proxy server for addresses beginning with,Use semicolon (;)</value>
<value>استثنا: از سرور پروکسی برای آدرس هایی که با شروع می شوند استفاده نکنید، از نقطه ویرگول (;) استفاده کنید.</value>
</data>
<data name="TbSettingsHttpPort" xml:space="preserve">
<value>پورت Http</value>
@@ -725,7 +725,7 @@
<value>هنگام به‌روزرسانی هسته، فایل‌های Geo را نادیده بگیرید</value>
</data>
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
<value>Keep older when deduplication</value>
<value>هنگام کپی برداری، نگه داری قدیمی تر ها</value>
</data>
<data name="TbSettingsLogEnabled" xml:space="preserve">
<value>ثبت گزارش های محلی</value>
@@ -734,25 +734,25 @@
<value>سطح ثبت رویداد</value>
</data>
<data name="TbSettingsMuxEnabled" xml:space="preserve">
<value>Turn on Mux Multiplexing</value>
<value>فعال کردن Mux Multiplexing</value>
</data>
<data name="TbSettingsN" xml:space="preserve">
<value>تنظیمات v2rayN</value>
</data>
<data name="TbSettingsPass" xml:space="preserve">
<value>Auth pass</value>
<value>مجوز احراز هویت</value>
</data>
<data name="TbSettingsRemoteDNS" xml:space="preserve">
<value>سفارشی DNS (multiple, separated by commas (,))</value>
</data>
<data name="TbSettingsSetUWP" xml:space="preserve">
<value>Set Win10 UWP Loopback</value>
<value>تنظیم کردن Win10 UWP Loopback</value>
</data>
<data name="TbSettingsSniffingEnabled" xml:space="preserve">
<value>Turn on Sniffing</value>
<value>فعال کردن Sniffing</value>
</data>
<data name="TbSettingsSocksPort" xml:space="preserve">
<value>Mixed Port</value>
<value>پورت Mixed</value>
</data>
<data name="TbSettingsStartBoot" xml:space="preserve">
<value>درهنگام راه ائدازی شروع شود</value>
@@ -761,22 +761,22 @@
<value>فعال کردن آمار (نیاز به راه اندازی مجدد)</value>
</data>
<data name="TbSettingsSubConvert" xml:space="preserve">
<value>Subscription conversion Url</value>
<value>آدرس اینترنتی تبدیل اشتراک</value>
</data>
<data name="TbSettingsSystemproxy" xml:space="preserve">
<value>تنظیمات پراکسی سیستم</value>
</data>
<data name="TbSettingsTLS13" xml:space="preserve">
<value>Enable Security Protocol TLS v1.3 (subscription/update)</value>
<value>فعال کردن پروتکل امنیتی TLS نسخه 1.3 (اشتراک/به‌روزرسانی)</value>
</data>
<data name="TbSettingsTrayMenuServersLimit" xml:space="preserve">
<value>Tray right-click menu servers display limit</value>
<value>محدودیت نمایش سرورهای منوی سینی کلیک راست</value>
</data>
<data name="TbSettingsUdpEnabled" xml:space="preserve">
<value>UDP را فعال شود</value>
<value>فعال سازی UDP</value>
</data>
<data name="TbSettingsUser" xml:space="preserve">
<value>Auth user</value>
<value>تایید کاربر</value>
</data>
<data name="TbClearSystemProxy" xml:space="preserve">
<value>پاک کردن پروکسی سیستم</value>
@@ -821,16 +821,16 @@
<value>پایین (D)</value>
</data>
<data name="menuMoveTop" xml:space="preserve">
<value>Move to top (T)</value>
<value>حرکت به بالا (T)</value>
</data>
<data name="menuMoveUp" xml:space="preserve">
<value>Up (U)</value>
<value>بالا (U)</value>
</data>
<data name="MsgFilterTitle" xml:space="preserve">
<value>Filter, support regular</value>
<value>فیلتر، پشتیبانی منظم</value>
</data>
<data name="menuWebsiteItem" xml:space="preserve">
<value>{0} Website</value>
<value>{0} وب سایت</value>
</data>
<data name="menuRoutingAdvanced" xml:space="preserve">
<value>عملکرد پیشرفته</value>
@@ -845,7 +845,7 @@
<value>حذف انتخاب شده</value>
</data>
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
<value>Set as active rule</value>
<value>تنظیم کردن به عنوان قانون فعال</value>
</data>
<data name="TbdomainMatcher" xml:space="preserve">
<value>تطبیق دامنه</value>
@@ -857,19 +857,19 @@
<value>فعال کردن عملکرد پیشرفته</value>
</data>
<data name="TbRoutingTabBlock" xml:space="preserve">
<value>3.Block Domain or IP</value>
<value>3. مسدود کردن دامنه یا آیپی</value>
</data>
<data name="TbRoutingTabDirect" xml:space="preserve">
<value>2.Direct Domain or IP</value>
<value>2. دایرکت کردن دامنه یا IP</value>
</data>
<data name="TbRoutingTabProxy" xml:space="preserve">
<value>1.Proxy Domain or IP</value>
<value>1. پروکسی کردن دامنه یا IP</value>
</data>
<data name="TbRoutingTabRuleList" xml:space="preserve">
<value>لیست مجموعه قوانین از پیش تعریف شده</value>
</data>
<data name="TbRoutingTips" xml:space="preserve">
<value>*Set the rules, separated by commas (,); The comma in the regular is replaced by &lt;COMMA&gt;</value>
<value>*قوانین را تنظیم کنید که با کاما از هم جدا شده اند (,); کاما در حالت عادی با &lt;COMMA&gt;</value>
</data>
<data name="menuImportRulesFromClipboard" xml:space="preserve">
<value>وارد کردن قوانین از کلیپ بورد</value>
@@ -878,7 +878,7 @@
<value>وارد کردن قوانین از فایل</value>
</data>
<data name="menuImportRulesFromUrl" xml:space="preserve">
<value>وارد کردن قوانین از Sub Url</value>
<value>وارد کردن قوانین از آدرس اینترنتی Sub</value>
</data>
<data name="menuRoutingRuleSetting" xml:space="preserve">
<value>تنظیم قانون</value>
@@ -902,7 +902,7 @@
<value>دامنه و آی پی در هنگام ذخیره به طور خودکار مرتب می شوند</value>
</data>
<data name="TbRuleobjectDoc" xml:space="preserve">
<value>Ruleobject Doc</value>
<value>مستندات شی قانون</value>
</data>
<data name="TbDnsObjectDoc" xml:space="preserve">
<value>پشتیبانی از DnsObject</value>
@@ -920,16 +920,16 @@
<value>فقط مسیر</value>
</data>
<data name="TbSettingsNotProxyLocalAddress" xml:space="preserve">
<value>يەرلىك (Intranet) ئادرېسلارغا ۋاكالەتچى مۇلازىمېتىر ئىشلەتمەڭ</value>
<value>از سرورهای پروکسی برای آدرس های محلی (اینترانت) استفاده نکنید</value>
</data>
<data name="menuMixedTestServer" xml:space="preserve">
<value>One-click test Latency and speed (Ctrl+E)</value>
<value>تاخیر و سرعت تست با یک کلیک (Ctrl+E)</value>
</data>
<data name="LvTestDelay" xml:space="preserve">
<value>تاخیر (میلی‌ثانیه)</value>
</data>
<data name="LvTestSpeed" xml:space="preserve">
<value>Speed(M/s)</value>
<value>سرعت (M/s)</value>
</data>
<data name="FailedToRunCore" xml:space="preserve">
<value>Core اجرا نشد، لطفاً گزارش را ببینید</value>
@@ -944,7 +944,7 @@
<value>پیکربندی قدیمی guiNConfig را وارد شود</value>
</data>
<data name="TbEnableTunAs" xml:space="preserve">
<value>Tun را فعال شود</value>
<value>فعال سازی Tun</value>
</data>
<data name="TbSettingsNewPort4LAN" xml:space="preserve">
<value>پورت جدید برای LAN</value>
@@ -956,10 +956,10 @@
<value>User-Agent</value>
</data>
<data name="TbSettingsDefUserAgentTips" xml:space="preserve">
<value>This parameter is valid only for tcp/http and ws</value>
<value>این پارامتر فقط برای tcp/http و ws معتبر است</value>
</data>
<data name="TbSettingsEnableHWA" xml:space="preserve">
<value>فعال‌سازی شتاب‌دهنده سخت‌افزاری (نیاز به راه‌اندازی مجدد)</value>
<value>فعال‌ سازی شتاب‌ دهنده سخت‌افزاری (نیاز به راه‌اندازی مجدد)</value>
</data>
<data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve">
<value>فعال کردن کش فایل مجموعه قوانین برای sing-box</value>
@@ -968,7 +968,7 @@
<value>مرتب سازی</value>
</data>
<data name="TbSortingDefault" xml:space="preserve">
<value>Default</value>
<value>پیش فرض</value>
</data>
<data name="TbSortingDelay" xml:space="preserve">
<value>تاخیر</value>
@@ -1007,10 +1007,10 @@
<value>نوع قانون</value>
</data>
<data name="menuModeDirect" xml:space="preserve">
<value>Direct</value>
<value>مستقیم</value>
</data>
<data name="menuModeGlobal" xml:space="preserve">
<value>Global</value>
<value>جهانی</value>
</data>
<data name="menuModeNothing" xml:space="preserve">
<value>تغییر نده</value>
@@ -1019,193 +1019,193 @@
<value>قانون</value>
</data>
<data name="menuProxiesDelaytest" xml:space="preserve">
<value>Latency Test</value>
<value>تست تأخیر</value>
</data>
<data name="menuProxiesDelaytestPart" xml:space="preserve">
<value>Part Node Latency Test</value>
<value>تست تاخیر قسمت گره (نقطه اتصال)</value>
</data>
<data name="menuProxiesSelectActivity" xml:space="preserve">
<value>Select active node (Enter)</value>
<value>انتخاب گره فعال (Enter)</value>
</data>
<data name="menuRemoteBackup" xml:space="preserve">
<value>Backup to remote (WebDAV)</value>
<value>پشتیبان گیری از راه دور (WebDAV)</value>
</data>
<data name="menuRemoteRestore" xml:space="preserve">
<value>Restore from remote (WebDAV)</value>
<value>بازیابی از راه دور (WebDAV)</value>
</data>
<data name="TbSettingsDomainStrategy4Out" xml:space="preserve">
<value>Default domain strategy for outbound</value>
<value>استراتژی دامنه پیش فرض برای خروجی</value>
</data>
<data name="menuSetDefaultMultipleServer" xml:space="preserve">
<value>Multi-Server lowest latency</value>
<value>کمترین تأخیر چند سروره</value>
</data>
<data name="TbSettingsMainGirdOrientation" xml:space="preserve">
<value>Main layout orientation(Require restart)</value>
<value>جهت چیدمان اصلی (نیاز به راه اندازی مجدد)</value>
</data>
<data name="menuSetDefaultLoadBalanceServer" xml:space="preserve">
<value>Multi-server load balancing</value>
<value>تعادل بار چند سروره</value>
</data>
<data name="TbSettingsDomainDNSAddress" xml:space="preserve">
<value>Outbound DNS address</value>
<value>آدرس DNS خروجی</value>
</data>
<data name="menuProfileAutofitColumnWidth" xml:space="preserve">
<value>Auto column width adjustment</value>
<value>تنظیم خودکار عرض ستون</value>
</data>
<data name="menuExport2ShareUrlBase64" xml:space="preserve">
<value>Export Base64-encoded Share Links to Clipboard</value>
<value>صادر کردن پیوندهای اشتراک گذاری کدگذاری شده با Base64 به کلیپ بورد</value>
</data>
<data name="menuExport2ClientConfigClipboard" xml:space="preserve">
<value>Export selected server for complete configuration to clipboard</value>
<value>صادر کردن سرور انتخاب شده برای پیکربندی کامل به کلیپ بورد</value>
</data>
<data name="menuShowOrHideMainWindow" xml:space="preserve">
<value>Show or hide the main window</value>
<value>نمایش یا پنهان کردن پنجره اصلی</value>
</data>
<data name="UpdateStandalonePackageTip" xml:space="preserve">
<value>You are currently running a standalone package, please manually download the SelfContained.7z file to unzip and overwrite it!</value>
<value>شما در حال حاضر در حال اجرای یک بسته مستقل هستید، لطفاً فایل SelfContained.7z را به صورت دستی دانلود کنید تا آن را از حالت فشرده خارج کرده و بازنویسی کنید!</value>
</data>
<data name="TbPreSocksPort4Sub" xml:space="preserve">
<value>Custom config socks port</value>
<value>پیکربندی سفارشی ساکس پورت</value>
</data>
<data name="menuBackupAndRestore" xml:space="preserve">
<value>Backup and Restore</value>
<value>پشتیبان گیری و بازیابی</value>
</data>
<data name="menuLocalBackup" xml:space="preserve">
<value>Backup to local</value>
<value>پشتیبان گیری به محلی</value>
</data>
<data name="menuLocalRestore" xml:space="preserve">
<value>Restore from local</value>
<value>بازیابی از محلی</value>
</data>
<data name="menuLocalBackupAndRestore" xml:space="preserve">
<value>Local</value>
<value>محلی</value>
</data>
<data name="menuRemoteBackupAndRestore" xml:space="preserve">
<value>Remote (WebDAV)</value>
<value>از راه دور (WebDAV)</value>
</data>
<data name="LvWebDavUrl" xml:space="preserve">
<value>WebDav Url</value>
<value>آدرس اینترنتی WebDav</value>
</data>
<data name="LvWebDavUserName" xml:space="preserve">
<value>WebDav User Name</value>
<value>نام کاربری WebDav</value>
</data>
<data name="LvWebDavPassword" xml:space="preserve">
<value>WebDav Password</value>
<value>پسورد WebDav</value>
</data>
<data name="LvWebDavCheck" xml:space="preserve">
<value>WebDav Check</value>
<value>چک کردن WebDav</value>
</data>
<data name="LvWebDavDirName" xml:space="preserve">
<value>Remote folder name (optional)</value>
<value>نام پوشه راه دور (اختیاری)</value>
</data>
<data name="LocalRestoreInvalidZipTips" xml:space="preserve">
<value>Invalid backup file</value>
<value>فایل پشتیبان نامعتبر است</value>
</data>
<data name="ConnectionsHostFilterTitle" xml:space="preserve">
<value>Host filter</value>
</data>
<data name="TipActiveServer" xml:space="preserve">
<value>Active</value>
<value>فعال سازی</value>
</data>
<data name="menuStorageUI" xml:space="preserve">
<value>Save Interface Layout</value>
<value>ذخیره طرح رابط</value>
</data>
<data name="TbSettingsGeoFilesSource" xml:space="preserve">
<value>Geo files source (optional)</value>
<value>منبع فایل های جغرافیایی (اختیاری)</value>
</data>
<data name="TbSettingsSrsFilesSource" xml:space="preserve">
<value>sing-box ruleset files source (optional)</value>
<value>منبع فایل های مجموعه قوانین sing-box (اختیاری)</value>
</data>
<data name="UpgradeAppNotExistTip" xml:space="preserve">
<value>UpgradeApp does not exist</value>
<value>برنامه ارتقا وجود ندارد</value>
</data>
<data name="TbSettingsRoutingRulesSource" xml:space="preserve">
<value>Routing rules source (optional)</value>
<value>منبع قوانین مسیریابی (اختیاری)</value>
</data>
<data name="menuRegionalPresets" xml:space="preserve">
<value>Regional presets setting</value>
<value>تنظیمات از پیش تعیین شده منطقه ای</value>
</data>
<data name="menuRegionalPresetsDefault" xml:space="preserve">
<value>Default</value>
<value>پیش فرض</value>
</data>
<data name="menuRegionalPresetsRussia" xml:space="preserve">
<value>Russia</value>
<value>روسیه</value>
</data>
<data name="TbSettingsChinaUserTip" xml:space="preserve">
<value>Users in China region can ignore this item</value>
<value>کاربران در منطقه چین می توانند این مورد را نادیده بگیرند</value>
</data>
<data name="menuAddServerViaImage" xml:space="preserve">
<value>Scan QR code in the image</value>
<value>اسکن کردن QRcode موجود در تصویر</value>
</data>
<data name="InvalidUrlTip" xml:space="preserve">
<value>Invalid address (Url)</value>
<value>آدرس نامعتبر (آدرس اینترنتی)</value>
</data>
<data name="InsecureUrlProtocol" xml:space="preserve">
<value>Please do not use the insecure HTTP protocol subscription address</value>
<value>لطفاً از آدرس اشتراک پروتکل HTTP ناامن استفاده نکنید</value>
</data>
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
<value>Install the font to the system and restart the settings</value>
<value>فونت را روی سیستم نصب کنید و تنظیمات را مجددا راه اندازی کنید</value>
</data>
<data name="menuExitTips" xml:space="preserve">
<value>Are you sure to exit?</value>
<value>آیا مطمئن هستید که خارج می شوید؟</value>
</data>
<data name="LvMemo" xml:space="preserve">
<value>Remarks Memo</value>
<value>یادداشت ملاحظات</value>
</data>
<data name="TbSettingsLogEnabledToFile" xml:space="preserve">
<value>Enable logging to file</value>
<value>فعال کردن ورود به فایل</value>
</data>
<data name="MsgSkipSubscriptionUpdate" xml:space="preserve">
<value>Updates are not enabled, skip this subscription</value>
<value>به روز رسانی ها فعال نیستند، از این اشتراک رد شوید</value>
</data>
<data name="menuRebootAsAdmin" xml:space="preserve">
<value>Restart as Administrator</value>
<value>به عنوان مدیر راه اندازی مجدد</value>
</data>
<data name="LvMoreUrl" xml:space="preserve">
<value>More URLs, separated by commas; Subscription conversion will be invalid</value>
<value>نشانی‌های وب بیشتر که با کاما از هم جدا شده‌اند. تبدیل اشتراک نامعتبر خواهد بود</value>
</data>
<data name="SpeedDisplayText" xml:space="preserve">
<value>{0} : {1}/s↑ | {2}/s↓</value>
</data>
<data name="LvAutoUpdateInterval" xml:space="preserve">
<value>Automatic update interval (minutes)</value>
<value>فاصله به روز رسانی خودکار (دقیقه)</value>
</data>
<data name="LvConvertTarget" xml:space="preserve">
<value>Convert target type</value>
<value>تبدیل نوع هدف</value>
</data>
<data name="LvConvertTargetTip" xml:space="preserve">
<value>Please leave blank if no conversion is required</value>
<value>اگر نیازی به تبدیل نیست، لطفاً خالی بگذارید</value>
</data>
<data name="TipDisplayLog" xml:space="preserve">
<value>Please turn off when there is an abnormal disconnection</value>
<value>لطفاً در صورت قطع غیرعادی آن را خاموش کنید</value>
</data>
<data name="menuDNSSetting" xml:space="preserve">
<value>DNS Settings</value>
<value>تنظیمات DNS</value>
</data>
<data name="TbDnsSingboxObjectDoc" xml:space="preserve">
<value>Please fill in DNS Structure, Click to view the document</value>
<value>لطفا ساختار DNS را پر کنید، برای مشاهده سند کلیک کنید</value>
</data>
<data name="TbSettingDnsImportDefConfig" xml:space="preserve">
<value>Click to import default DNS config</value>
<value>برای وارد کردن تنظیمات پیش‌فرض DNS کلیک کنید</value>
</data>
<data name="TbdomainStrategy4Singbox" xml:space="preserve">
<value>sing-box domain strategy</value>
<value>استراتژی دامنه sing-box</value>
</data>
<data name="TbSettingsMux4SboxProtocol" xml:space="preserve">
<value>sing-box Mux Protocol</value>
<value>پروتکل sing-box Mux</value>
</data>
<data name="TbRoutingRuleProcess" xml:space="preserve">
<value>Full process name (Tun mode)</value>
<value>نام کامل فرانید (حالت Tun)</value>
</data>
<data name="TbRoutingRuleIP" xml:space="preserve">
<value>IP or IP CIDR</value>
</data>
<data name="TbRoutingRuleDomain" xml:space="preserve">
<value>Domain</value>
<value>دامنه</value>
</data>
<data name="TbSettingsCoreDnsSingbox" xml:space="preserve">
<value>sing-box DNS settings</value>
<value>تنظیمات DNS sing-box</value>
</data>
<data name="SpeedtestingWait" xml:space="preserve">
<value>Waiting for testing (press ESC to terminate)...</value>
<value>در انتظار آزمایش (برای پایان دادن به ESC فشار دهید)...</value>
</data>
<data name="TbSpiderX" xml:space="preserve">
<value>SpiderX</value>
@@ -1214,52 +1214,52 @@
<value>ShortId</value>
</data>
<data name="menuMoveToGroup" xml:space="preserve">
<value>Move to group</value>
<value>انتقال به گروه</value>
</data>
<data name="TbSettingsEnableDragDropSort" xml:space="preserve">
<value>Enable Server Drag Drop Sort(Require restart)</value>
<value>فعال کردن مرتب سازی با کشیدن سرور (نیاز به راه اندازی مجدد)</value>
</data>
<data name="TbAutoRefresh" xml:space="preserve">
<value>AutoRefresh</value>
<value>بازخوانی خودکار</value>
</data>
<data name="SpeedtestingSkip" xml:space="preserve">
<value>Skip test</value>
<value>رد شدن از آزمون</value>
</data>
<data name="menuEditServer" xml:space="preserve">
<value>Edit Server (Ctrl+D)</value>
<value>ویرایش سرور (Ctrl+D)</value>
</data>
<data name="TbSettingsDoubleClick2Activate" xml:space="preserve">
<value>Double-click server make active</value>
<value>روی server make active دوبار کلیک کنید</value>
</data>
<data name="SpeedtestingCompleted" xml:space="preserve">
<value>Test completed</value>
<value>تست تکمیل شد</value>
</data>
<data name="TbSettingsDefFingerprint" xml:space="preserve">
<value>Default TLS fingerprint</value>
<value>اثر انگشت tls پیش فرض</value>
</data>
<data name="TbSettingsCurrentFontFamily" xml:space="preserve">
<value>FontFamily(Require restart)</value>
<value>FontFamily (نیاز به راه اندازی مجدد)</value>
</data>
<data name="TbSettingsCurrentFontFamilyTip" xml:space="preserve">
<value>Copy the font TTF/TTC file to the directory guiFonts, restart the settings</value>
<value>فایل TTF/TTC فونت را در دایرکتوری guiFonts کپی کنید، تنظیمات را مجددا راه اندازی کنید</value>
</data>
<data name="TbSettingsSocksPortTip" xml:space="preserve">
<value>Pac port = +2; Xray API port = +3; mihomo API port = +4;</value>
<value>پورت Pac = +2; پورت Xray API = +3; پورت mihomo API = +4;</value>
</data>
<data name="TbSettingsStartBootTip" xml:space="preserve">
<value>Set this with admin privileges, get admin privileges after startup</value>
<value>این را با امتیازات ادمین تنظیم کنید، پس از راه اندازی، امتیازات مدیر را دریافت کنید</value>
</data>
<data name="TbSettingsFontSize" xml:space="preserve">
<value>Font Size</value>
<value>اندازه فونت</value>
</data>
<data name="TbSettingsSpeedTestTimeout" xml:space="preserve">
<value>SpeedTest Single Timeout Value</value>
<value>یمقدار تاخیر تست سرعت منفرد</value>
</data>
<data name="TbSettingsSpeedTestUrl" xml:space="preserve">
<value>SpeedTest URL</value>
<value>/آدرس اینترنتی SpeedTest</value>
</data>
<data name="menuMoveTo" xml:space="preserve">
<value>Move up and down</value>
<value>بالا و پایین حرکت کنید</value>
</data>
<data name="TbPublicKey" xml:space="preserve">
<value>PublicKey</value>
@@ -1268,46 +1268,46 @@
<value>Add [Hysteria2] server</value>
</data>
<data name="TbSettingsHysteriaBandwidth" xml:space="preserve">
<value>Hysteria Max bandwidth (Up/Dw)</value>
<value>حداکتر پهنای باند هیستریا (آپلود/دانلود)</value>
</data>
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
<value>Follow System Theme</value>
<value>دنبال کردن تم سیستم</value>
</data>
<data name="menuAddTuicServer" xml:space="preserve">
<value>Add [TUIC] server</value>
<value>افزودن سرور [TUIC]</value>
</data>
<data name="TbSettingsEnableUpdateSubOnlyRemarksExist" xml:space="preserve">
<value>Updating subscription, only determine remarks exists</value>
<value>اشتراک در حال به‌روزرسانی، فقط مشخص کنید که ملاحظاتی وجود دارد</value>
</data>
<data name="menuProxiesReload" xml:space="preserve">
<value>Refresh Proxies</value>
<value>تازه سازی پروکسی ها</value>
</data>
<data name="TbSortingNetwork" xml:space="preserve">
<value>Network</value>
<value>شبکه</value>
</data>
<data name="TbSortingType" xml:space="preserve">
<value>Type</value>
<value>نوع</value>
</data>
<data name="TransportRequestHostTip5" xml:space="preserve">
<value>*grpc Authority</value>
</data>
<data name="menuAddHttpServer" xml:space="preserve">
<value>Add [HTTP] server</value>
<value>افزودن سرور [HTTP]</value>
</data>
<data name="TbSettingsSpeedPingTestUrl" xml:space="preserve">
<value>Speed Ping Test URL</value>
<value>آدرس اینترنتی تست پینگ سرعت</value>
</data>
<data name="TbSettingsEnableFragmentTips" xml:space="preserve">
<value>Use Xray and enable non-Tun mode, which conflicts with the group previous proxy</value>
<value>از Xray استفاده کنید و حالت non-Tun را فعال کنید، که با پراکسی قبلی گروه در تضاد است</value>
</data>
<data name="LvCustomRulesetPath4Singbox" xml:space="preserve">
<value>Custom the rule-set of sing-box</value>
<value>سفارش سازی مجموعه قوانین از sing box</value>
</data>
<data name="NeedRebootTips" xml:space="preserve">
<value>Successful operation. Click the settings menu to reboot the app.</value>
<value>عملکرد موفقیت آمیز بود، روی منوی تنظیمات کلیک کنید تا برنامه راه اندازی مجدد شود.</value>
</data>
<data name="menuOpenTheFileLocation" xml:space="preserve">
<value>Open the storage location</value>
<value>باز کردن محل ذخیره سازی</value>
</data>
<data name="TbSortingChain" xml:space="preserve">
<value>Chain</value>
@@ -1316,75 +1316,78 @@
<value>Host</value>
</data>
<data name="TbSettingsUseSystemHosts" xml:space="preserve">
<value>Use System Hosts</value>
<value>استفاده کردن از System Hosts</value>
</data>
<data name="TbSettingsEnableFragment" xml:space="preserve">
<value>Enable fragment</value>
<value>فعال کردن فرگمنت</value>
</data>
<data name="TbAutoScrollToEnd" xml:space="preserve">
<value>Auto ScrollToEnd</value>
<value>خودکار ScrollToEnd</value>
</data>
<data name="SpeedtestingStop" xml:space="preserve">
<value>Test terminating...</value>
<value>پایان تست...</value>
</data>
<data name="LvNextProfile" xml:space="preserve">
<value>Next proxy remarks</value>
</data>
<data name="TbPath7" xml:space="preserve">
<value>obfs password</value>
<value>پسورد obfs</value>
</data>
<data name="TbHeaderType8" xml:space="preserve">
<value>Congestion control</value>
<value>کنترل تراکم</value>
</data>
<data name="LvPrevProfile" xml:space="preserve">
<value>Previous proxy remarks</value>
</data>
<data name="TbLocalAddress" xml:space="preserve">
<value>Address(Ip,Ipv6)</value>
<value>آدرس (IP, IPv6)</value>
</data>
<data name="TbReserved" xml:space="preserve">
<value>Reserved(2,3,4)</value>
</data>
<data name="TbPrivateKey" xml:space="preserve">
<value>PrivateKey</value>
<value>کلید خصوصی</value>
</data>
<data name="menuAddWireguardServer" xml:space="preserve">
<value>Add [WireGuard] server</value>
<value>افزودن سرور [WireGuard]</value>
</data>
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
<value>Enable IPv6 Address</value>
<value>فعال سازی آدرس IPv6</value>
</data>
<data name="TbSettingsEnableExInbound" xml:space="preserve">
<value>Enable additional Inbound</value>
<value>فعال سازی additional Inbound</value>
</data>
<data name="LvPrevProfileTip" xml:space="preserve">
<value>Please make sure the remarks exists and is unique</value>
<value>لطفاً مطمئن شوید که ملاحظات وجود دارد و منحصر به فرد است</value>
</data>
<data name="TbRuleMatchingTips" xml:space="preserve">
<value>(Domain or IP or ProcName) and Port and Protocol and InboundTag =&gt; OutboundTag</value>
</data>
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
<value>System sudo password</value>
<value>رمز عبور sudo سیستم</value>
</data>
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
<value>The password is encrypted and stored only in local files.</value>
<value>رمز عبور رمزگذاری شده و فقط در فایل های محلی ذخیره می شود.</value>
</data>
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
<value>Please set the sudo password in Tun mode settings first</value>
<value>لطفاً ابتدا رمز عبور sudo را در تنظیمات حالت Tun تنظیم کنید</value>
</data>
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
<value>Please do not run this app with sudo</value>
<value>لطفا این برنامه را با sudo اجرا نکنید</value>
</data>
<data name="TransportHeaderTypeTip5" xml:space="preserve">
<value>*xhttp mode</value>
<value>*حالت xhttp</value>
</data>
<data name="TransportExtraTip" xml:space="preserve">
<value>XHTTP Extra raw JSON, format: { XHTTPObject }</value>
<value>جیسون خام XHTTP Extra, فرمت: { XHTTPObject }</value>
</data>
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
<value>Hide to tray when closing the window</value>
<value>هنگام بستن پنجره در سینی پنهان شوید</value>
</data>
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
<value>Number per time for auto batch during speedtest(max 1000)</value>
<value>تعداد در هر زمان برای دسته خودکار در طول تست سرعت (حداکثر 1000)</value>
</data>
<data name="TbSettingsExceptionTip2" xml:space="preserve">
<value>Exception. Do not use proxy server for addresses,with a comma (,)</value>
</data>
</root>

View File

@@ -1387,4 +1387,7 @@
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
<value>Number per time for auto batch during speedtest(max 1000)</value>
</data>
<data name="TbSettingsExceptionTip2" xml:space="preserve">
<value>Exception. Do not use proxy server for addresses,with a comma (,)</value>
</data>
</root>

View File

@@ -1387,4 +1387,7 @@
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
<value>Number per time for auto batch during speedtest(max 1000)</value>
</data>
<data name="TbSettingsExceptionTip2" xml:space="preserve">
<value>Exception. Do not use proxy server for addresses,with a comma (,)</value>
</data>
</root>

View File

@@ -1384,4 +1384,7 @@
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
<value>测速时自动分批的每批数量最大1000</value>
</data>
<data name="TbSettingsExceptionTip2" xml:space="preserve">
<value>例外. 对于下列地址不使用代理配置文件:使用逗号(,)分隔</value>
</data>
</root>

View File

@@ -1384,4 +1384,7 @@
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
<value>測速時自動分批的每批數量最大1000</value>
</data>
<data name="TbSettingsExceptionTip2" xml:space="preserve">
<value>例外. 對於下列位址不使用代理設定檔:使用逗號(,)分隔</value>
</data>
</root>

View File

@@ -122,7 +122,7 @@ namespace ServiceLib.Services.CoreConfig
singboxConfig.inbounds.Clear();
singboxConfig.outbounds.RemoveAt(0);
var httpPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
var initPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
foreach (var it in selecteds)
{
@@ -144,8 +144,8 @@ namespace ServiceLib.Services.CoreConfig
}
//find unused port
var port = httpPort;
for (int k = httpPort; k < Global.MaxPort; k++)
var port = initPort;
for (int k = initPort; k < Global.MaxPort; k++)
{
if (lstIpEndPoints?.FindIndex(_it => _it.Port == k) >= 0)
{
@@ -157,7 +157,7 @@ namespace ServiceLib.Services.CoreConfig
}
//found
port = k;
httpPort = port + 1;
initPort = port + 1;
break;
}

View File

@@ -248,7 +248,7 @@ namespace ServiceLib.Services.CoreConfig
v2rayConfig.outbounds.Clear();
v2rayConfig.routing.rules.Clear();
var httpPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
var initPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
foreach (var it in selecteds)
{
@@ -270,8 +270,8 @@ namespace ServiceLib.Services.CoreConfig
}
//find unused port
var port = httpPort;
for (var k = httpPort; k < Global.MaxPort; k++)
var port = initPort;
for (var k = initPort; k < Global.MaxPort; k++)
{
if (lstIpEndPoints?.FindIndex(_it => _it.Port == k) >= 0)
{
@@ -283,7 +283,7 @@ namespace ServiceLib.Services.CoreConfig
}
//found
port = k;
httpPort = port + 1;
initPort = port + 1;
break;
}

View File

@@ -280,13 +280,13 @@ namespace ServiceLib.Services
{
return null;
}
var httpPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
if (await SocketCheck(Global.Loopback, httpPort) == false)
var port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
if (await SocketCheck(Global.Loopback, port) == false)
{
return null;
}
return new WebProxy(Global.Loopback, httpPort);
return new WebProxy($"socks5://{Global.Loopback}:{port}");
}
private async Task<bool> SocketCheck(string ip, int port)

View File

@@ -191,7 +191,7 @@ namespace ServiceLib.Services
{
try
{
WebProxy webProxy = new(Global.Loopback, it.Port);
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
var output = await GetRealPingTime(downloadHandle, webProxy);
ProfileExHandler.Instance.SetTestDelay(it.IndexId, output);
@@ -262,7 +262,7 @@ namespace ServiceLib.Services
var item = await AppHandler.Instance.GetProfileItem(it.IndexId);
if (item is null) continue;
WebProxy webProxy = new(Global.Loopback, it.Port);
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
await downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) =>
{
@@ -324,7 +324,7 @@ namespace ServiceLib.Services
var item = await AppHandler.Instance.GetProfileItem(it.IndexId);
if (item is null) continue;
WebProxy webProxy = new(Global.Loopback, it.Port);
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
_ = downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) =>
{
decimal.TryParse(msg, out var dec);

View File

@@ -697,7 +697,10 @@
<TabItem Name="tabSystemproxy" Header="{x:Static resx:ResUI.TbSettingsSystemproxy}">
<DockPanel Classes="Margin8">
<StackPanel DockPanel.Dock="Bottom" Orientation="Vertical">
<StackPanel
Name="panSystemProxyAdvanced"
DockPanel.Dock="Bottom"
Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock
VerticalAlignment="Center"
@@ -723,11 +726,17 @@
</StackPanel>
<TextBlock
Grid.Row="1"
Name="txbSettingsExceptionTip"
VerticalAlignment="Center"
Classes="Margin8"
DockPanel.Dock="Top"
Text="{x:Static resx:ResUI.TbSettingsExceptionTip}" />
<TextBlock
Name="txbSettingsExceptionTip2"
VerticalAlignment="Center"
Classes="Margin8"
DockPanel.Dock="Top"
Text="{x:Static resx:ResUI.TbSettingsExceptionTip2}" />
<TextBox
x:Name="txtsystemProxyExceptions"
VerticalAlignment="Stretch"

View File

@@ -166,9 +166,14 @@ namespace v2rayN.Desktop.Views
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
});
if (!Utils.IsWindows())
if (Utils.IsWindows())
{
tabSystemproxy.IsVisible = false;
txbSettingsExceptionTip2.IsVisible = false;
}
else
{
txbSettingsExceptionTip.IsVisible = false;
panSystemProxyAdvanced.IsVisible = false;
}
if (Utils.IsOSX())

View File

@@ -35,10 +35,10 @@ import java.lang.ref.SoftReference
class V2RayVpnService : VpnService(), ServiceControl {
companion object {
private const val VPN_MTU = 1500
private const val PRIVATE_VLAN4_CLIENT = "26.26.26.1"
private const val PRIVATE_VLAN4_ROUTER = "26.26.26.2"
private const val PRIVATE_VLAN6_CLIENT = "da26:2626::1"
private const val PRIVATE_VLAN6_ROUTER = "da26:2626::2"
private const val PRIVATE_VLAN4_CLIENT = "10.10.10.1"
private const val PRIVATE_VLAN4_ROUTER = "10.10.10.2"
private const val PRIVATE_VLAN6_CLIENT = "fc00::10:10:10:1"
private const val PRIVATE_VLAN6_ROUTER = "fc00::10:10:10:2"
private const val TUN2SOCKS = "libtun2socks.so"
}

View File

@@ -144,14 +144,15 @@ func (s *Server) forwardConnection(dest net.Destination, conn net.Conn) {
Reason: "",
})
if s.info.inboundTag != nil {
ctx = session.ContextWithInbound(ctx, s.info.inboundTag)
}
// what's this?
// Session information should not be shared between different connections
// why reuse them in server level? This will cause incorrect destoverride and unexpected routing behavior.
// Disable it temporarily. Maybe s.info should be removed.
// if s.info.inboundTag != nil {
// ctx = session.ContextWithInbound(ctx, s.info.inboundTag)
// }
// if s.info.outboundTag != nil {
// ctx = session.ContextWithOutbounds(ctx, []*session.Outbound{s.info.outboundTag})
// }

View File

@@ -4144,6 +4144,7 @@ set(files
src/net/base64.cpp
src/net/cipher.cpp
src/net/iobuf.cpp
src/net/io_buffer.cpp
src/net/hkdf_sha1.cpp
src/net/hmac_sha1.cpp
src/net/dns_addrinfo_helper.cpp
@@ -4210,6 +4211,7 @@ set(hfiles
src/net/base64.hpp
src/net/cipher.hpp
src/net/iobuf.hpp
src/net/io_buffer.hpp
src/net/hkdf_sha1.hpp
src/net/hmac_sha1.hpp
src/net/dns_addrinfo_helper.hpp

147
yass/src/net/io_buffer.cpp Normal file
View File

@@ -0,0 +1,147 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2024 Chilledheart */
#include "net/io_buffer.hpp"
#include <utility>
#include "base/check_op.h"
#include "base/numerics/safe_math.h"
namespace net {
// TODO(eroman): IOBuffer is being converted to require buffer sizes and offsets
// be specified as "size_t" rather than "int" (crbug.com/488553). To facilitate
// this move (since LOTS of code needs to be updated), this function ensures
// that sizes can be safely converted to an "int" without truncation. The
// assert ensures calling this with an "int" argument is also safe.
void IOBuffer::AssertValidBufferSize(size_t size) {
static_assert(sizeof(size_t) >= sizeof(int));
gurl_base::CheckedNumeric<int>(size).ValueOrDie();
}
IOBuffer::IOBuffer() = default;
IOBuffer::IOBuffer(char* data, size_t size) : data_(data), size_(size) {
AssertValidBufferSize(size);
}
IOBuffer::~IOBuffer() = default;
IOBufferWithSize::IOBufferWithSize() = default;
IOBufferWithSize::IOBufferWithSize(size_t buffer_size) {
AssertValidBufferSize(buffer_size);
if (buffer_size) {
size_ = buffer_size;
data_ = new char[buffer_size];
}
}
IOBufferWithSize::~IOBufferWithSize() {
#if 0
data_.ClearAndDeleteArray();
#else
delete[] data_;
#endif
}
StringIOBuffer::StringIOBuffer(std::string s) : string_data_(std::move(s)) {
// Can't pass `s.data()` directly to IOBuffer constructor since moving
// from `s` may invalidate it. This is especially true for libc++ short
// string optimization where the data may be held in the string variable
// itself, instead of in a movable backing store.
AssertValidBufferSize(string_data_.size());
data_ = string_data_.data();
size_ = string_data_.size();
}
StringIOBuffer::~StringIOBuffer() {
// Clear pointer before this destructor makes it dangle.
data_ = nullptr;
}
DrainableIOBuffer::DrainableIOBuffer(scoped_refptr<IOBuffer> base, size_t size)
: IOBuffer(base->data(), size), base_(std::move(base)) {}
void DrainableIOBuffer::DidConsume(int bytes) {
SetOffset(used_ + bytes);
}
int DrainableIOBuffer::BytesRemaining() const {
return size_ - used_;
}
// Returns the number of consumed bytes.
int DrainableIOBuffer::BytesConsumed() const {
return used_;
}
void DrainableIOBuffer::SetOffset(int bytes) {
CHECK_GE(bytes, 0);
CHECK_LE(bytes, size_);
used_ = bytes;
data_ = base_->data() + used_;
}
DrainableIOBuffer::~DrainableIOBuffer() {
// Clear ptr before this destructor destroys the |base_| instance,
// making it dangle.
data_ = nullptr;
}
GrowableIOBuffer::GrowableIOBuffer() = default;
void GrowableIOBuffer::SetCapacity(int capacity) {
CHECK_GE(capacity, 0);
// this will get reset in `set_offset`.
data_ = nullptr;
size_ = 0;
// realloc will crash if it fails.
real_data_.reset(static_cast<char*>(realloc(real_data_.release(), capacity)));
capacity_ = capacity;
if (offset_ > capacity)
set_offset(capacity);
else
set_offset(offset_); // The pointer may have changed.
}
void GrowableIOBuffer::set_offset(int offset) {
CHECK_GE(offset, 0);
CHECK_LE(offset, capacity_);
offset_ = offset;
data_ = real_data_.get() + offset;
size_ = capacity_ - offset;
}
int GrowableIOBuffer::RemainingCapacity() {
return capacity_ - offset_;
}
char* GrowableIOBuffer::StartOfBuffer() {
return real_data_.get();
}
GrowableIOBuffer::~GrowableIOBuffer() {
data_ = nullptr;
}
PickledIOBuffer::PickledIOBuffer() = default;
void PickledIOBuffer::Done() {
data_ = const_cast<char*>(pickle_.data_as_char());
size_ = pickle_.size();
}
PickledIOBuffer::~PickledIOBuffer() {
// Avoid dangling ptr when this destructor destroys the pickle.
data_ = nullptr;
}
WrappedIOBuffer::WrappedIOBuffer(const char* data, size_t size) : IOBuffer(const_cast<char*>(data), size) {}
WrappedIOBuffer::~WrappedIOBuffer() = default;
} // namespace net

239
yass/src/net/io_buffer.hpp Normal file
View File

@@ -0,0 +1,239 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2024 Chilledheart */
#ifndef NET_BASE_IO_BUFFER_H_
#define NET_BASE_IO_BUFFER_H_
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <string>
#include "base/memory/free_deleter.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/pickle.h"
namespace net {
// IOBuffers are reference counted data buffers used for easier asynchronous
// IO handling.
//
// They are often used as the destination buffers for Read() operations, or as
// the source buffers for Write() operations.
//
// IMPORTANT: Never re-use an IOBuffer after cancelling the IO operation that
// was using it, since this may lead to memory corruption!
//
// -----------------------
// Ownership of IOBuffers:
// -----------------------
//
// Although IOBuffers are RefCountedThreadSafe, they are not intended to be
// used as a shared buffer, nor should they be used simultaneously across
// threads. The fact that they are reference counted is an implementation
// detail for allowing them to outlive cancellation of asynchronous
// operations.
//
// Instead, think of the underlying |char*| buffer contained by the IOBuffer
// as having exactly one owner at a time.
//
// Whenever you call an asynchronous operation that takes an IOBuffer,
// ownership is implicitly transferred to the called function, until the
// operation has completed (at which point it transfers back to the caller).
//
// ==> The IOBuffer's data should NOT be manipulated, destroyed, or read
// until the operation has completed.
//
// ==> Cancellation does NOT count as completion. If an operation using
// an IOBuffer is cancelled, the caller should release their
// reference to this IOBuffer at the time of cancellation since
// they can no longer use it.
//
// For instance, if you were to call a Read() operation on some class which
// takes an IOBuffer, and then delete that class (which generally will
// trigger cancellation), the IOBuffer which had been passed to Read() should
// never be re-used.
//
// This usage contract is assumed by any API which takes an IOBuffer, even
// though it may not be explicitly mentioned in the function's comments.
//
// -----------------------
// Motivation
// -----------------------
//
// The motivation for transferring ownership during cancellation is
// to make it easier to work with un-cancellable operations.
//
// For instance, let's say under the hood your API called out to the
// operating system's synchronous ReadFile() function on a worker thread.
// When cancelling through our asynchronous interface, we have no way of
// actually aborting the in progress ReadFile(). We must let it keep running,
// and hence the buffer it was reading into must remain alive. Using
// reference counting we can add a reference to the IOBuffer and make sure
// it is not destroyed until after the synchronous operation has completed.
// Base class, never instantiated, does not own the buffer.
class IOBuffer : public gurl_base::RefCountedThreadSafe<IOBuffer> {
public:
int size() const { return size_; }
char* data() { return data_; }
const char* data() const { return data_; }
uint8_t* bytes() { return reinterpret_cast<uint8_t*>(data()); }
const uint8_t* bytes() const { return reinterpret_cast<const uint8_t*>(data()); }
protected:
friend class gurl_base::RefCountedThreadSafe<IOBuffer>;
static void AssertValidBufferSize(size_t size);
IOBuffer();
IOBuffer(char* data, size_t size);
virtual ~IOBuffer();
raw_ptr<char> data_ = nullptr;
int size_ = 0;
};
// Class which owns its buffer and manages its destruction.
class IOBufferWithSize : public IOBuffer {
public:
IOBufferWithSize();
explicit IOBufferWithSize(size_t size);
protected:
~IOBufferWithSize() override;
};
// This is a read only IOBuffer. The data is stored in a string and
// the IOBuffer interface does not provide a proper way to modify it.
class StringIOBuffer : public IOBuffer {
public:
explicit StringIOBuffer(std::string s);
private:
~StringIOBuffer() override;
std::string string_data_;
};
// This version wraps an existing IOBuffer and provides convenient functions
// to progressively read all the data.
//
// DrainableIOBuffer is useful when you have an IOBuffer that contains data
// to be written progressively, and Write() function takes an IOBuffer rather
// than char*. DrainableIOBuffer can be used as follows:
//
// // payload is the IOBuffer containing the data to be written.
// buf = gurl_base::MakeRefCounted<DrainableIOBuffer>(payload, payload_size);
//
// while (buf->BytesRemaining() > 0) {
// // Write() takes an IOBuffer. If it takes char*, we could
// // simply use the regular IOBuffer like payload->data() + offset.
// int bytes_written = Write(buf, buf->BytesRemaining());
// buf->DidConsume(bytes_written);
// }
//
class DrainableIOBuffer : public IOBuffer {
public:
DrainableIOBuffer(scoped_refptr<IOBuffer> base, size_t size);
// DidConsume() changes the |data_| pointer so that |data_| always points
// to the first unconsumed byte.
void DidConsume(int bytes);
// Returns the number of unconsumed bytes.
int BytesRemaining() const;
// Returns the number of consumed bytes.
int BytesConsumed() const;
// Seeks to an arbitrary point in the buffer. The notion of bytes consumed
// and remaining are updated appropriately.
void SetOffset(int bytes);
private:
~DrainableIOBuffer() override;
scoped_refptr<IOBuffer> base_;
int used_ = 0;
};
// This version provides a resizable buffer and a changeable offset.
//
// GrowableIOBuffer is useful when you read data progressively without
// knowing the total size in advance. GrowableIOBuffer can be used as
// follows:
//
// buf = gurl_base::MakeRefCounted<GrowableIOBuffer>();
// buf->SetCapacity(1024); // Initial capacity.
//
// while (!some_stream->IsEOF()) {
// // Double the capacity if the remaining capacity is empty.
// if (buf->RemainingCapacity() == 0)
// buf->SetCapacity(buf->capacity() * 2);
// int bytes_read = some_stream->Read(buf, buf->RemainingCapacity());
// buf->set_offset(buf->offset() + bytes_read);
// }
//
class GrowableIOBuffer : public IOBuffer {
public:
GrowableIOBuffer();
// realloc memory to the specified capacity.
void SetCapacity(int capacity);
int capacity() { return capacity_; }
// |offset| moves the |data_| pointer, allowing "seeking" in the data.
void set_offset(int offset);
int offset() { return offset_; }
int RemainingCapacity();
char* StartOfBuffer();
private:
~GrowableIOBuffer() override;
std::unique_ptr<char, gurl_base::FreeDeleter> real_data_;
int capacity_ = 0;
int offset_ = 0;
};
// This versions allows a pickle to be used as the storage for a write-style
// operation, avoiding an extra data copy.
class PickledIOBuffer : public IOBuffer {
public:
PickledIOBuffer();
gurl_base::Pickle* pickle() { return &pickle_; }
// Signals that we are done writing to the pickle and we can use it for a
// write-style IO operation.
void Done();
private:
~PickledIOBuffer() override;
gurl_base::Pickle pickle_;
};
// This class allows the creation of a temporary IOBuffer that doesn't really
// own the underlying buffer. Please use this class only as a last resort.
// A good example is the buffer for a synchronous operation, where we can be
// sure that nobody is keeping an extra reference to this object so the lifetime
// of the buffer can be completely managed by its intended owner.
class WrappedIOBuffer : public IOBuffer {
public:
WrappedIOBuffer(const char* data, size_t size);
protected:
~WrappedIOBuffer() override;
};
} // namespace net
#endif // NET_BASE_IO_BUFFER_H_

View File

@@ -166,6 +166,8 @@ add_library(url STATIC
googleurl/url/url_parse_internal.h
googleurl/url/url_util.cc
googleurl/url/url_util_internal.h
googleurl-override/base/pickle.h
googleurl-override/base/pickle.cc
# googleurl/url/scheme_host_port.cc
# googleurl/url/scheme_host_port.h
# googleurl/url/origin.cc

View File

@@ -0,0 +1,25 @@
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_MEMORY_FREE_DELETER_H_
#define BASE_MEMORY_FREE_DELETER_H_
#include <stdlib.h>
namespace gurl_base {
// Function object which invokes 'free' on its parameter, which must be
// a pointer. Can be used to store malloc-allocated pointers in std::unique_ptr:
//
// std::unique_ptr<int, base::FreeDeleter> foo_ptr(
// static_cast<int*>(malloc(sizeof(int))));
struct FreeDeleter {
inline void operator()(void* ptr) const {
free(ptr);
}
};
} // namespace gurl_base
#endif // BASE_MEMORY_FREE_DELETER_H_

View File

@@ -0,0 +1,459 @@
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/pickle.h"
#include <algorithm>
#include <cstdlib>
#include <limits>
#include <ostream>
#include <type_traits>
#include "base/bits.h"
#include "base/numerics/safe_conversions.h"
#include "base/numerics/safe_math.h"
#include "build/build_config.h"
namespace gurl_base {
// static
const size_t Pickle::kPayloadUnit = 64;
static const size_t kCapacityReadOnly = static_cast<size_t>(-1);
PickleIterator::PickleIterator(const Pickle& pickle)
: payload_(pickle.payload()),
read_index_(0),
end_index_(pickle.payload_size()) {}
template <typename Type>
inline bool PickleIterator::ReadBuiltinType(Type* result) {
static_assert(
std::is_integral_v<Type> && !std::is_same_v<Type, bool>,
"This method is only safe with to use with types without padding bits.");
const char* read_from = GetReadPointerAndAdvance<Type>();
if (!read_from)
return false;
memcpy(result, read_from, sizeof(*result));
return true;
}
inline void PickleIterator::Advance(size_t size) {
size_t aligned_size = bits::AlignUp(size, sizeof(uint32_t));
if (end_index_ - read_index_ < aligned_size) {
read_index_ = end_index_;
} else {
read_index_ += aligned_size;
}
}
template <typename Type>
inline const char* PickleIterator::GetReadPointerAndAdvance() {
if (sizeof(Type) > end_index_ - read_index_) {
read_index_ = end_index_;
return nullptr;
}
const char* current_read_ptr = payload_ + read_index_;
Advance(sizeof(Type));
return current_read_ptr;
}
const char* PickleIterator::GetReadPointerAndAdvance(size_t num_bytes) {
if (num_bytes > end_index_ - read_index_) {
read_index_ = end_index_;
return nullptr;
}
const char* current_read_ptr = payload_ + read_index_;
Advance(num_bytes);
return current_read_ptr;
}
inline const char* PickleIterator::GetReadPointerAndAdvance(
size_t num_elements,
size_t size_element) {
// Check for size_t overflow.
size_t num_bytes;
if (!CheckMul(num_elements, size_element).AssignIfValid(&num_bytes))
return nullptr;
return GetReadPointerAndAdvance(num_bytes);
}
bool PickleIterator::ReadBool(bool* result) {
// Not all bit patterns are valid bools. Avoid undefined behavior by reading a
// type with no padding bits, then converting to bool.
uint8_t v;
if (!ReadBuiltinType(&v)) {
return false;
}
*result = v != 0;
return true;
}
bool PickleIterator::ReadInt(int* result) {
return ReadBuiltinType(result);
}
bool PickleIterator::ReadLong(long* result) {
// Always read long as a 64-bit value to ensure compatibility between 32-bit
// and 64-bit processes.
int64_t result_int64 = 0;
if (!ReadBuiltinType(&result_int64))
return false;
if (!IsValueInRangeForNumericType<long>(result_int64))
return false;
*result = static_cast<long>(result_int64);
return true;
}
bool PickleIterator::ReadUInt16(uint16_t* result) {
return ReadBuiltinType(result);
}
bool PickleIterator::ReadUInt32(uint32_t* result) {
return ReadBuiltinType(result);
}
bool PickleIterator::ReadInt64(int64_t* result) {
return ReadBuiltinType(result);
}
bool PickleIterator::ReadUInt64(uint64_t* result) {
return ReadBuiltinType(result);
}
bool PickleIterator::ReadFloat(float* result) {
// crbug.com/315213
// The source data may not be properly aligned, and unaligned float reads
// cause SIGBUS on some ARM platforms, so force using memcpy to copy the data
// into the result.
const char* read_from = GetReadPointerAndAdvance<float>();
if (!read_from)
return false;
memcpy(result, read_from, sizeof(*result));
return true;
}
bool PickleIterator::ReadDouble(double* result) {
// crbug.com/315213
// The source data may not be properly aligned, and unaligned double reads
// cause SIGBUS on some ARM platforms, so force using memcpy to copy the data
// into the result.
const char* read_from = GetReadPointerAndAdvance<double>();
if (!read_from)
return false;
memcpy(result, read_from, sizeof(*result));
return true;
}
bool PickleIterator::ReadString(std::string* result) {
size_t len;
if (!ReadLength(&len))
return false;
const char* read_from = GetReadPointerAndAdvance(len);
if (!read_from)
return false;
result->assign(read_from, len);
return true;
}
bool PickleIterator::ReadStringPiece(StringPiece* result) {
size_t len;
if (!ReadLength(&len))
return false;
const char* read_from = GetReadPointerAndAdvance(len);
if (!read_from)
return false;
*result = StringPiece(read_from, len);
return true;
}
bool PickleIterator::ReadString16(std::u16string* result) {
size_t len;
if (!ReadLength(&len))
return false;
const char* read_from = GetReadPointerAndAdvance(len, sizeof(char16_t));
if (!read_from)
return false;
result->assign(reinterpret_cast<const char16_t*>(read_from), len);
return true;
}
bool PickleIterator::ReadStringPiece16(StringPiece16* result) {
size_t len;
if (!ReadLength(&len))
return false;
const char* read_from = GetReadPointerAndAdvance(len, sizeof(char16_t));
if (!read_from)
return false;
*result = StringPiece16(reinterpret_cast<const char16_t*>(read_from), len);
return true;
}
bool PickleIterator::ReadData(const char** data, size_t* length) {
*length = 0;
*data = nullptr;
if (!ReadLength(length))
return false;
return ReadBytes(data, *length);
}
std::optional<gurl_base::span<const uint8_t>> PickleIterator::ReadData() {
const char* ptr;
size_t length;
if (!ReadData(&ptr, &length))
return absl::nullopt;
return gurl_base::as_bytes(gurl_base::make_span(ptr, length));
}
bool PickleIterator::ReadBytes(const char** data, size_t length) {
const char* read_from = GetReadPointerAndAdvance(length);
if (!read_from)
return false;
*data = read_from;
return true;
}
Pickle::Attachment::Attachment() = default;
Pickle::Attachment::~Attachment() = default;
// Payload is uint32_t aligned.
Pickle::Pickle()
: header_(nullptr),
header_size_(sizeof(Header)),
capacity_after_header_(0),
write_offset_(0) {
static_assert(gurl_base::bits::IsPowerOfTwo(Pickle::kPayloadUnit),
"Pickle::kPayloadUnit must be a power of two");
Resize(kPayloadUnit);
header_->payload_size = 0;
}
Pickle::Pickle(size_t header_size)
: header_(nullptr),
header_size_(bits::AlignUp(header_size, sizeof(uint32_t))),
capacity_after_header_(0),
write_offset_(0) {
DCHECK_GE(header_size, sizeof(Header));
DCHECK_LE(header_size, kPayloadUnit);
Resize(kPayloadUnit);
header_->payload_size = 0;
}
Pickle::Pickle(span<const uint8_t> data)
: Pickle(reinterpret_cast<const char*>(data.data()), data.size()) {}
Pickle::Pickle(const char* data, size_t data_len)
: header_(reinterpret_cast<Header*>(const_cast<char*>(data))),
header_size_(0),
capacity_after_header_(kCapacityReadOnly),
write_offset_(0) {
if (data_len >= sizeof(Header))
header_size_ = data_len - header_->payload_size;
if (header_size_ > data_len)
header_size_ = 0;
if (header_size_ != bits::AlignUp(header_size_, sizeof(uint32_t)))
header_size_ = 0;
// If there is anything wrong with the data, we're not going to use it.
if (!header_size_)
header_ = nullptr;
}
Pickle::Pickle(const Pickle& other)
: header_(nullptr),
header_size_(other.header_size_),
capacity_after_header_(0),
write_offset_(other.write_offset_) {
if (other.header_) {
Resize(other.header_->payload_size);
memcpy(header_, other.header_, header_size_ + other.header_->payload_size);
}
}
Pickle::~Pickle() {
if (capacity_after_header_ != kCapacityReadOnly)
free(header_);
}
Pickle& Pickle::operator=(const Pickle& other) {
if (this == &other) {
return *this;
}
if (capacity_after_header_ == kCapacityReadOnly) {
header_ = nullptr;
capacity_after_header_ = 0;
}
if (header_size_ != other.header_size_) {
free(header_);
header_ = nullptr;
header_size_ = other.header_size_;
}
if (other.header_) {
Resize(other.header_->payload_size);
memcpy(header_, other.header_,
other.header_size_ + other.header_->payload_size);
write_offset_ = other.write_offset_;
}
return *this;
}
void Pickle::WriteString(const StringPiece& value) {
WriteData(value.data(), value.size());
}
void Pickle::WriteString16(const StringPiece16& value) {
WriteInt(checked_cast<int>(value.size()));
WriteBytes(value.data(), value.size() * sizeof(char16_t));
}
void Pickle::WriteData(const char* data, size_t length) {
WriteInt(checked_cast<int>(length));
WriteBytes(data, length);
}
void Pickle::WriteBytes(const void* data, size_t length) {
WriteBytesCommon(data, length);
}
void Pickle::Reserve(size_t length) {
size_t data_len = bits::AlignUp(length, sizeof(uint32_t));
DCHECK_GE(data_len, length);
#ifdef ARCH_CPU_64_BITS
DCHECK_LE(data_len, std::numeric_limits<uint32_t>::max());
#endif
DCHECK_LE(write_offset_, std::numeric_limits<uint32_t>::max() - data_len);
size_t new_size = write_offset_ + data_len;
if (new_size > capacity_after_header_)
Resize(capacity_after_header_ * 2 + new_size);
}
bool Pickle::WriteAttachment(scoped_refptr<Attachment> attachment) {
return false;
}
bool Pickle::ReadAttachment(gurl_base::PickleIterator* iter,
scoped_refptr<Attachment>* attachment) const {
return false;
}
bool Pickle::HasAttachments() const {
return false;
}
void Pickle::Resize(size_t new_capacity) {
CHECK_NE(capacity_after_header_, kCapacityReadOnly);
capacity_after_header_ = bits::AlignUp(new_capacity, kPayloadUnit);
void* p = realloc(header_, GetTotalAllocatedSize());
CHECK(p);
header_ = reinterpret_cast<Header*>(p);
}
void* Pickle::ClaimBytes(size_t num_bytes) {
void* p = ClaimUninitializedBytesInternal(num_bytes);
CHECK(p);
memset(p, 0, num_bytes);
return p;
}
size_t Pickle::GetTotalAllocatedSize() const {
if (capacity_after_header_ == kCapacityReadOnly)
return 0;
return header_size_ + capacity_after_header_;
}
// static
const char* Pickle::FindNext(size_t header_size,
const char* start,
const char* end) {
size_t pickle_size = 0;
if (!PeekNext(header_size, start, end, &pickle_size))
return nullptr;
if (pickle_size > static_cast<size_t>(end - start))
return nullptr;
return start + pickle_size;
}
// static
bool Pickle::PeekNext(size_t header_size,
const char* start,
const char* end,
size_t* pickle_size) {
DCHECK_EQ(header_size, bits::AlignUp(header_size, sizeof(uint32_t)));
DCHECK_GE(header_size, sizeof(Header));
DCHECK_LE(header_size, static_cast<size_t>(kPayloadUnit));
size_t length = static_cast<size_t>(end - start);
if (length < sizeof(Header))
return false;
const Header* hdr = reinterpret_cast<const Header*>(start);
if (length < header_size)
return false;
// If payload_size causes an overflow, we return maximum possible
// pickle size to indicate that.
*pickle_size = ClampAdd(header_size, hdr->payload_size);
return true;
}
template <size_t length>
void Pickle::WriteBytesStatic(const void* data) {
WriteBytesCommon(data, length);
}
template void Pickle::WriteBytesStatic<2>(const void* data);
template void Pickle::WriteBytesStatic<4>(const void* data);
template void Pickle::WriteBytesStatic<8>(const void* data);
inline void* Pickle::ClaimUninitializedBytesInternal(size_t length) {
DCHECK_NE(kCapacityReadOnly, capacity_after_header_)
<< "oops: pickle is readonly";
size_t data_len = bits::AlignUp(length, sizeof(uint32_t));
DCHECK_GE(data_len, length);
#ifdef ARCH_CPU_64_BITS
DCHECK_LE(data_len, std::numeric_limits<uint32_t>::max());
#endif
DCHECK_LE(write_offset_, std::numeric_limits<uint32_t>::max() - data_len);
size_t new_size = write_offset_ + data_len;
if (new_size > capacity_after_header_) {
size_t new_capacity = capacity_after_header_ * 2;
const size_t kPickleHeapAlign = 4096;
if (new_capacity > kPickleHeapAlign) {
new_capacity =
bits::AlignUp(new_capacity, kPickleHeapAlign) - kPayloadUnit;
}
Resize(std::max(new_capacity, new_size));
}
char* write = mutable_payload() + write_offset_;
std::fill(write + length, write + data_len, 0); // Always initialize padding
header_->payload_size = static_cast<uint32_t>(new_size);
write_offset_ = new_size;
return write;
}
inline void Pickle::WriteBytesCommon(const void* data, size_t length) {
DCHECK_NE(kCapacityReadOnly, capacity_after_header_)
<< "oops: pickle is readonly";
MSAN_CHECK_MEM_IS_INITIALIZED(data, length);
void* write = ClaimUninitializedBytesInternal(length);
std::copy(static_cast<const char*>(data),
static_cast<const char*>(data) + length, static_cast<char*>(write));
}
} // namespace gurl_base

View File

@@ -0,0 +1,352 @@
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_PICKLE_H_
#define BASE_PICKLE_H_
#include <stddef.h>
#include <stdint.h>
#include <optional>
#include <string>
#include "base/base_export.h"
#include "base/check_op.h"
#include "base/containers/span.h"
#include "base/memory/raw_ptr_exclusion.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string_piece.h"
namespace gurl_base {
class Pickle;
// PickleIterator reads data from a Pickle. The Pickle object must remain valid
// while the PickleIterator object is in use.
class BASE_EXPORT PickleIterator {
public:
PickleIterator() : payload_(nullptr), read_index_(0), end_index_(0) {}
explicit PickleIterator(const Pickle& pickle);
// Methods for reading the payload of the Pickle. To read from the start of
// the Pickle, create a PickleIterator from a Pickle. If successful, these
// methods return true. Otherwise, false is returned to indicate that the
// result could not be extracted. It is not possible to read from the iterator
// after that.
[[nodiscard]] bool ReadBool(bool* result);
[[nodiscard]] bool ReadInt(int* result);
[[nodiscard]] bool ReadLong(long* result);
[[nodiscard]] bool ReadUInt16(uint16_t* result);
[[nodiscard]] bool ReadUInt32(uint32_t* result);
[[nodiscard]] bool ReadInt64(int64_t* result);
[[nodiscard]] bool ReadUInt64(uint64_t* result);
[[nodiscard]] bool ReadFloat(float* result);
[[nodiscard]] bool ReadDouble(double* result);
[[nodiscard]] bool ReadString(std::string* result);
// The StringPiece data will only be valid for the lifetime of the message.
[[nodiscard]] bool ReadStringPiece(StringPiece* result);
[[nodiscard]] bool ReadString16(std::u16string* result);
// The StringPiece16 data will only be valid for the lifetime of the message.
[[nodiscard]] bool ReadStringPiece16(StringPiece16* result);
// A pointer to the data will be placed in |*data|, and the length will be
// placed in |*length|. The pointer placed into |*data| points into the
// message's buffer so it will be scoped to the lifetime of the message (or
// until the message data is mutated). Do not keep the pointer around!
[[nodiscard]] bool ReadData(const char** data, size_t* length);
// Similar, but using gurl_base::span for convenience.
[[nodiscard]] std::optional<gurl_base::span<const uint8_t>> ReadData();
// A pointer to the data will be placed in |*data|. The caller specifies the
// number of bytes to read, and ReadBytes will validate this length. The
// pointer placed into |*data| points into the message's buffer so it will be
// scoped to the lifetime of the message (or until the message data is
// mutated). Do not keep the pointer around!
[[nodiscard]] bool ReadBytes(const char** data, size_t length);
// A version of ReadInt() that checks for the result not being negative. Use
// it for reading the object sizes.
[[nodiscard]] bool ReadLength(size_t* result) {
int result_int;
if (!ReadInt(&result_int) || result_int < 0)
return false;
*result = static_cast<size_t>(result_int);
return true;
}
// Skips bytes in the read buffer and returns true if there are at least
// num_bytes available. Otherwise, does nothing and returns false.
[[nodiscard]] bool SkipBytes(size_t num_bytes) {
return !!GetReadPointerAndAdvance(num_bytes);
}
bool ReachedEnd() const { return read_index_ == end_index_; }
private:
// Read Type from Pickle.
template <typename Type>
bool ReadBuiltinType(Type* result);
// Advance read_index_ but do not allow it to exceed end_index_.
// Keeps read_index_ aligned.
void Advance(size_t size);
// Get read pointer for Type and advance read pointer.
template<typename Type>
const char* GetReadPointerAndAdvance();
// Get read pointer for |num_bytes| and advance read pointer. This method
// checks num_bytes for wrapping.
const char* GetReadPointerAndAdvance(size_t num_bytes);
// Get read pointer for (num_elements * size_element) bytes and advance read
// pointer. This method checks for overflow and wrapping.
const char* GetReadPointerAndAdvance(size_t num_elements,
size_t size_element);
const char* payload_; // Start of our pickle's payload.
size_t read_index_; // Offset of the next readable byte in payload.
size_t end_index_; // Payload size.
};
// This class provides facilities for basic binary value packing and unpacking.
//
// The Pickle class supports appending primitive values (ints, strings, etc.)
// to a pickle instance. The Pickle instance grows its internal memory buffer
// dynamically to hold the sequence of primitive values. The internal memory
// buffer is exposed as the "data" of the Pickle. This "data" can be passed
// to a Pickle object to initialize it for reading.
//
// When reading from a Pickle object, it is important for the consumer to know
// what value types to read and in what order to read them as the Pickle does
// not keep track of the type of data written to it.
//
// The Pickle's data has a header which contains the size of the Pickle's
// payload. It can optionally support additional space in the header. That
// space is controlled by the header_size parameter passed to the Pickle
// constructor.
//
class BASE_EXPORT Pickle {
public:
// Auxiliary data attached to a Pickle. Pickle must be subclassed along with
// this interface in order to provide a concrete implementation of support
// for attachments. The base Pickle implementation does not accept
// attachments.
class BASE_EXPORT Attachment : public RefCountedThreadSafe<Attachment> {
public:
Attachment();
Attachment(const Attachment&) = delete;
Attachment& operator=(const Attachment&) = delete;
protected:
friend class RefCountedThreadSafe<Attachment>;
virtual ~Attachment();
};
// Initialize a Pickle object using the default header size.
Pickle();
// Initialize a Pickle object with the specified header size in bytes, which
// must be greater-than-or-equal-to sizeof(Pickle::Header). The header size
// will be rounded up to ensure that the header size is 32bit-aligned.
explicit Pickle(size_t header_size);
// Initializes a Pickle from a const block of data. The data is not copied;
// instead the data is merely referenced by this Pickle. Only const methods
// should be used on the Pickle when initialized this way. The header
// padding size is deduced from the data length.
explicit Pickle(span<const uint8_t> data);
// TODO(crbug.com/1490484): Migrate callers of this overload to the span
// version.
Pickle(const char* data, size_t data_len);
// Initializes a Pickle as a deep copy of another Pickle.
Pickle(const Pickle& other);
// Note: Other classes are derived from this class, and they may well
// delete through this parent class, e.g. std::uniuqe_ptr<Pickle> exists
// in several places the code.
virtual ~Pickle();
// Performs a deep copy.
Pickle& operator=(const Pickle& other);
// Returns the number of bytes written in the Pickle, including the header.
size_t size() const {
return header_ ? header_size_ + header_->payload_size : 0;
}
// Returns the data for this Pickle.
const uint8_t* data() const {
return reinterpret_cast<const uint8_t*>(header_);
}
// Handy method to simplify calling data() with a reinterpret_cast.
const char* data_as_char() const {
return reinterpret_cast<const char*>(data());
}
// Returns the effective memory capacity of this Pickle, that is, the total
// number of bytes currently dynamically allocated or 0 in the case of a
// read-only Pickle. This should be used only for diagnostic / profiling
// purposes.
size_t GetTotalAllocatedSize() const;
// Methods for adding to the payload of the Pickle. These values are
// appended to the end of the Pickle's payload. When reading values from a
// Pickle, it is important to read them in the order in which they were added
// to the Pickle.
void WriteBool(bool value) { WriteInt(value ? 1 : 0); }
void WriteInt(int value) { WritePOD(value); }
void WriteLong(long value) {
// Always write long as a 64-bit value to ensure compatibility between
// 32-bit and 64-bit processes.
WritePOD(static_cast<int64_t>(value));
}
void WriteUInt16(uint16_t value) { WritePOD(value); }
void WriteUInt32(uint32_t value) { WritePOD(value); }
void WriteInt64(int64_t value) { WritePOD(value); }
void WriteUInt64(uint64_t value) { WritePOD(value); }
void WriteFloat(float value) { WritePOD(value); }
void WriteDouble(double value) { WritePOD(value); }
void WriteString(const StringPiece& value);
void WriteString16(const StringPiece16& value);
// "Data" is a blob with a length. When you read it out you will be given the
// length. See also WriteBytes.
void WriteData(const char* data, size_t length);
// "Bytes" is a blob with no length. The caller must specify the length both
// when reading and writing. It is normally used to serialize PoD types of a
// known size. See also WriteData.
void WriteBytes(const void* data, size_t length);
// WriteAttachment appends |attachment| to the pickle. It returns
// false iff the set is full or if the Pickle implementation does not support
// attachments.
virtual bool WriteAttachment(scoped_refptr<Attachment> attachment);
// ReadAttachment parses an attachment given the parsing state |iter| and
// writes it to |*attachment|. It returns true on success.
virtual bool ReadAttachment(gurl_base::PickleIterator* iter,
scoped_refptr<Attachment>* attachment) const;
// Indicates whether the pickle has any attachments.
virtual bool HasAttachments() const;
// Reserves space for upcoming writes when multiple writes will be made and
// their sizes are computed in advance. It can be significantly faster to call
// Reserve() before calling WriteFoo() multiple times.
void Reserve(size_t additional_capacity);
// Payload follows after allocation of Header (header size is customizable).
struct Header {
uint32_t payload_size; // Specifies the size of the payload.
};
// Returns the header, cast to a user-specified type T. The type T must be a
// subclass of Header and its size must correspond to the header_size passed
// to the Pickle constructor.
template <class T>
T* headerT() {
DCHECK_EQ(header_size_, sizeof(T));
return static_cast<T*>(header_);
}
template <class T>
const T* headerT() const {
DCHECK_EQ(header_size_, sizeof(T));
return static_cast<const T*>(header_);
}
// The payload is the pickle data immediately following the header.
size_t payload_size() const {
return header_ ? header_->payload_size : 0;
}
const char* payload() const {
return reinterpret_cast<const char*>(header_) + header_size_;
}
// Returns the address of the byte immediately following the currently valid
// header + payload.
const char* end_of_payload() const {
// This object may be invalid.
return header_ ? payload() + payload_size() : NULL;
}
protected:
// Returns size of the header, which can have default value, set by user or
// calculated by passed raw data.
size_t header_size() const { return header_size_; }
char* mutable_payload() {
return reinterpret_cast<char*>(header_) + header_size_;
}
size_t capacity_after_header() const {
return capacity_after_header_;
}
// Resize the capacity, note that the input value should not include the size
// of the header.
void Resize(size_t new_capacity);
// Claims |num_bytes| bytes of payload. This is similar to Reserve() in that
// it may grow the capacity, but it also advances the write offset of the
// pickle by |num_bytes|. Claimed memory, including padding, is zeroed.
//
// Returns the address of the first byte claimed.
void* ClaimBytes(size_t num_bytes);
// Find the end of the pickled data that starts at range_start. Returns NULL
// if the entire Pickle is not found in the given data range.
static const char* FindNext(size_t header_size,
const char* range_start,
const char* range_end);
// Parse pickle header and return total size of the pickle. Data range
// doesn't need to contain entire pickle.
// Returns true if pickle header was found and parsed. Callers must check
// returned |pickle_size| for sanity (against maximum message size, etc).
// NOTE: when function successfully parses a header, but encounters an
// overflow during pickle size calculation, it sets |pickle_size| to the
// maximum size_t value and returns true.
static bool PeekNext(size_t header_size,
const char* range_start,
const char* range_end,
size_t* pickle_size);
// The allocation granularity of the payload.
static const size_t kPayloadUnit;
private:
friend class PickleIterator;
// `header_` is not a raw_ptr<...> for performance reasons (based on analysis
// of sampling profiler data).
RAW_PTR_EXCLUSION Header* header_;
size_t header_size_; // Supports extra data between header and payload.
// Allocation size of payload (or -1 if allocation is const). Note: this
// doesn't count the header.
size_t capacity_after_header_;
// The offset at which we will write the next field. Note: this doesn't count
// the header.
size_t write_offset_;
// Just like WriteBytes, but with a compile-time size, for performance.
template<size_t length> void BASE_EXPORT WriteBytesStatic(const void* data);
// Writes a POD by copying its bytes.
template <typename T> bool WritePOD(const T& data) {
WriteBytesStatic<sizeof(data)>(&data);
return true;
}
inline void* ClaimUninitializedBytesInternal(size_t num_bytes);
inline void WriteBytesCommon(const void* data, size_t length);
};
} // namespace gurl_base
#endif // BASE_PICKLE_H_

View File

@@ -710,3 +710,4 @@ subrat-lima
gitninja1234
jkruse
xiaomac
wesson09

View File

@@ -4,6 +4,19 @@
# To create a release, dispatch the https://github.com/yt-dlp/yt-dlp/actions/workflows/release.yml workflow on master
-->
### 2024.12.06
#### Core changes
- **cookies**: [Add `--cookies-from-browser` support for MS Store Firefox](https://github.com/yt-dlp/yt-dlp/commit/354cb4026cf2191e1a130ec2a627b95cabfbc60a) ([#11731](https://github.com/yt-dlp/yt-dlp/issues/11731)) by [wesson09](https://github.com/wesson09)
#### Extractor changes
- **bilibili**: [Fix HD formats extraction](https://github.com/yt-dlp/yt-dlp/commit/fca3eb5f8be08d5fab2e18b45b7281a12e566725) ([#11734](https://github.com/yt-dlp/yt-dlp/issues/11734)) by [grqz](https://github.com/grqz)
- **soundcloud**: [Fix formats extraction](https://github.com/yt-dlp/yt-dlp/commit/2feb28028ee48f2185d2d95076e62accb09b9e2e) ([#11742](https://github.com/yt-dlp/yt-dlp/issues/11742)) by [bashonly](https://github.com/bashonly)
- **youtube**
- [Fix `n` sig extraction for player `3bb1f723`](https://github.com/yt-dlp/yt-dlp/commit/a95ee6d8803fca9157adecf63732ab58bf87fd88) ([#11750](https://github.com/yt-dlp/yt-dlp/issues/11750)) by [bashonly](https://github.com/bashonly) (With fixes in [4bd2655](https://github.com/yt-dlp/yt-dlp/commit/4bd2655398aed450456197a6767639114a24eac2))
- [Fix signature function extraction](https://github.com/yt-dlp/yt-dlp/commit/4c85ccd1366c88cf93982f8350f58eed17355981) ([#11751](https://github.com/yt-dlp/yt-dlp/issues/11751)) by [bashonly](https://github.com/bashonly)
- [Player client maintenance](https://github.com/yt-dlp/yt-dlp/commit/2e49c789d3eebc39af8910705d65a98bca0e4c4f) ([#11724](https://github.com/yt-dlp/yt-dlp/issues/11724)) by [bashonly](https://github.com/bashonly)
### 2024.12.03
#### Core changes

View File

@@ -1860,7 +1860,7 @@ The following extractors use this feature:
* `cdn`: One or more CDN IDs to use with the API call for stream URLs, e.g. `gcp_cdn`, `gs_cdn_pc_app`, `gs_cdn_mobile_web`, `gs_cdn_pc_web`
#### soundcloud
* `formats`: Formats to request from the API. Requested values should be in the format of `{protocol}_{extension}` (omitting the bitrate), e.g. `hls_opus,http_aac`. The `*` character functions as a wildcard, e.g. `*_mp3`, and can be passed by itself to request all formats. Known protocols include `http`, `hls` and `hls-aes`; known extensions include `aac`, `opus` and `mp3`. Original `download` formats are always extracted. Default is `http_aac,hls_aac,http_opus,hls_opus,http_mp3,hls_mp3`
* `formats`: Formats to request from the API. Requested values should be in the format of `{protocol}_{codec}`, e.g. `hls_opus,http_aac`. The `*` character functions as a wildcard, e.g. `*_mp3`, and can be passed by itself to request all formats. Known protocols include `http`, `hls` and `hls-aes`; known codecs include `aac`, `opus` and `mp3`. Original `download` formats are always extracted. Default is `http_aac,hls_aac,http_opus,hls_opus,http_mp3,hls_mp3`
#### orfon (orf:on)
* `prefer_segments_playlist`: Prefer a playlist of program segments instead of a single complete video when available. If individual segments are desired, use `--concat-playlist never --extractor-args "orfon:prefer_segments_playlist"`

View File

@@ -68,6 +68,11 @@ _SIG_TESTS = [
'2aq0aqSyOoJXtK73m-uME_jv7-pT15gOFC02RFkGMqWpzEICs69VdbwQ0LDp1v7j8xx92efCJlYFYb1sUkkBSPOlPmXgIARw8JQ0qOAOAA',
'AOq0QJ8wRAIgXmPlOPSBkkUs1bYFYlJCfe29xx8j7v1pDL2QwbdV96sCIEzpWqMGkFR20CFOg51Tp-7vj_EMu-m37KtXJoOySqa0',
),
(
'https://www.youtube.com/s/player/3bb1f723/player_ias.vflset/en_US/base.js',
'2aq0aqSyOoJXtK73m-uME_jv7-pT15gOFC02RFkGMqWpzEICs69VdbwQ0LDp1v7j8xx92efCJlYFYb1sUkkBSPOlPmXgIARw8JQ0qOAOAA',
'MyOSJXtKI3m-uME_jv7-pT12gOFC02RFkGoqWpzE0Cs69VdbwQ0LDp1v7j8xx92efCJlYFYb1sUkkBSPOlPmXgIARw8JQ0qOAOAA',
),
]
_NSIG_TESTS = [
@@ -183,6 +188,10 @@ _NSIG_TESTS = [
'https://www.youtube.com/s/player/b12cc44b/player_ias.vflset/en_US/base.js',
'keLa5R2U00sR9SQK', 'N1OGyujjEwMnLw',
),
(
'https://www.youtube.com/s/player/3bb1f723/player_ias.vflset/en_US/base.js',
'gK15nzVyaXE9RsMP3z', 'ZFFWFLPWx9DEgQ',
),
]
@@ -254,8 +263,11 @@ def signature(jscode, sig_input):
def n_sig(jscode, sig_input):
funcname = YoutubeIE(FakeYDL())._extract_n_function_name(jscode)
return JSInterpreter(jscode).call_function(funcname, sig_input)
ie = YoutubeIE(FakeYDL())
funcname = ie._extract_n_function_name(jscode)
jsi = JSInterpreter(jscode)
func = jsi.extract_function_from_code(*ie._fixup_n_function_code(*jsi.extract_function_code(funcname)))
return func([sig_input])
make_sig_test = t_factory(

View File

@@ -7,7 +7,6 @@ from .common import InfoExtractor, SearchInfoExtractor
from ..networking import HEADRequest
from ..networking.exceptions import HTTPError
from ..utils import (
KNOWN_EXTENSIONS,
ExtractorError,
float_or_none,
int_or_none,
@@ -251,50 +250,15 @@ class SoundcloudBaseIE(InfoExtractor):
def invalid_url(url):
return not url or url in format_urls
def add_format(f, protocol, is_preview=False):
mobj = re.search(r'\.(?P<abr>\d+)\.(?P<ext>[0-9a-z]{3,4})(?=[/?])', stream_url)
if mobj:
for k, v in mobj.groupdict().items():
if not f.get(k):
f[k] = v
format_id_list = []
if protocol:
format_id_list.append(protocol)
ext = f.get('ext')
if ext == 'aac':
f.update({
'abr': 256,
'quality': 5,
'format_note': 'Premium',
})
for k in ('ext', 'abr'):
v = str_or_none(f.get(k))
if v:
format_id_list.append(v)
preview = is_preview or re.search(r'/(?:preview|playlist)/0/30/', f['url'])
if preview:
format_id_list.append('preview')
abr = f.get('abr')
if abr:
f['abr'] = int(abr)
if protocol in ('hls', 'hls-aes'):
protocol = 'm3u8' if ext == 'aac' else 'm3u8_native'
else:
protocol = 'http'
f.update({
'format_id': '_'.join(format_id_list),
'protocol': protocol,
'preference': -10 if preview else None,
})
formats.append(f)
# New API
for t in traverse_obj(info, ('media', 'transcodings', lambda _, v: url_or_none(v['url']))):
for t in traverse_obj(info, ('media', 'transcodings', lambda _, v: url_or_none(v['url']) and v['preset'])):
if extract_flat:
break
format_url = t['url']
preset = t['preset']
preset_base = preset.partition('_')[0]
protocol = traverse_obj(t, ('format', 'protocol', {str}))
protocol = traverse_obj(t, ('format', 'protocol', {str})) or 'http'
if protocol == 'progressive':
protocol = 'http'
if protocol != 'hls' and '/hls' in format_url:
@@ -302,32 +266,54 @@ class SoundcloudBaseIE(InfoExtractor):
if protocol == 'encrypted-hls' or '/encrypted-hls' in format_url:
protocol = 'hls-aes'
ext = None
if preset := traverse_obj(t, ('preset', {str_or_none})):
ext = preset.split('_')[0]
if ext not in KNOWN_EXTENSIONS:
ext = mimetype2ext(traverse_obj(t, ('format', 'mime_type', {str})))
identifier = join_nonempty(protocol, ext, delim='_')
if not self._is_requested(identifier):
self.write_debug(f'"{identifier}" is not a requested format, skipping')
short_identifier = f'{protocol}_{preset_base}'
if preset_base == 'abr':
self.write_debug(f'Skipping broken "{short_identifier}" format')
continue
if not self._is_requested(short_identifier):
self.write_debug(f'"{short_identifier}" is not a requested format, skipping')
continue
# XXX: if not extract_flat, 429 error must be caught where _extract_info_dict is called
stream_url = traverse_obj(self._call_api(
format_url, track_id, f'Downloading {identifier} format info JSON',
format_url, track_id, f'Downloading {short_identifier} format info JSON',
query=query, headers=self._HEADERS), ('url', {url_or_none}))
if invalid_url(stream_url):
continue
format_urls.add(stream_url)
add_format({
mime_type = traverse_obj(t, ('format', 'mime_type', {str}))
codec = self._search_regex(r'codecs="([^"]+)"', mime_type, 'codec', default=None)
ext = {
'mp4a': 'm4a',
'opus': 'opus',
}.get(codec[:4] if codec else None) or mimetype2ext(mime_type, default=None)
if not ext or ext == 'm3u8':
ext = preset_base
is_premium = t.get('quality') == 'hq'
abr = int_or_none(
self._search_regex(r'(\d+)k$', preset, 'abr', default=None)
or self._search_regex(r'\.(\d+)\.(?:opus|mp3)[/?]', stream_url, 'abr', default=None)
or (256 if (is_premium and 'aac' in preset) else None))
is_preview = (t.get('snipped')
or '/preview/' in format_url
or re.search(r'/(?:preview|playlist)/0/30/', stream_url))
formats.append({
'format_id': join_nonempty(protocol, preset, is_preview and 'preview', delim='_'),
'url': stream_url,
'ext': ext,
}, protocol, t.get('snipped') or '/preview/' in format_url)
for f in formats:
f['vcodec'] = 'none'
'acodec': codec,
'vcodec': 'none',
'abr': abr,
'protocol': 'm3u8_native' if protocol in ('hls', 'hls-aes') else 'http',
'container': 'm4a_dash' if ext == 'm4a' else None,
'quality': 5 if is_premium else 0 if (abr and abr >= 160) else -1,
'format_note': 'Premium' if is_premium else None,
'preference': -10 if is_preview else None,
})
if not formats and info.get('policy') == 'BLOCK':
self.raise_geo_restricted(metadata_available=True)

View File

@@ -3119,19 +3119,26 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
self.to_screen('Extracted signature function:\n' + code)
def _parse_sig_js(self, jscode):
# Examples where `sig` is funcname:
# sig=function(a){a=a.split(""); ... ;return a.join("")};
# ;c&&(c=sig(decodeURIComponent(c)),a.set(b,encodeURIComponent(c)));return a};
# {var l=f,m=h.sp,n=sig(decodeURIComponent(h.s));l.set(m,encodeURIComponent(n))}
# sig=function(J){J=J.split(""); ... ;return J.join("")};
# ;N&&(N=sig(decodeURIComponent(N)),J.set(R,encodeURIComponent(N)));return J};
# {var H=u,k=f.sp,v=sig(decodeURIComponent(f.s));H.set(k,encodeURIComponent(v))}
funcname = self._search_regex(
(r'\b[cs]\s*&&\s*[adf]\.set\([^,]+\s*,\s*encodeURIComponent\s*\(\s*(?P<sig>[a-zA-Z0-9$]+)\(',
(r'\b(?P<var>[a-zA-Z0-9$]+)&&\((?P=var)=(?P<sig>[a-zA-Z0-9$]{2,})\(decodeURIComponent\((?P=var)\)\)',
r'(?P<sig>[a-zA-Z0-9$]+)\s*=\s*function\(\s*(?P<arg>[a-zA-Z0-9$]+)\s*\)\s*{\s*(?P=arg)\s*=\s*(?P=arg)\.split\(\s*""\s*\)\s*;\s*[^}]+;\s*return\s+(?P=arg)\.join\(\s*""\s*\)',
r'(?:\b|[^a-zA-Z0-9$])(?P<sig>[a-zA-Z0-9$]{2,})\s*=\s*function\(\s*a\s*\)\s*{\s*a\s*=\s*a\.split\(\s*""\s*\)(?:;[a-zA-Z0-9$]{2}\.[a-zA-Z0-9$]{2}\(a,\d+\))?',
# Old patterns
r'\b[cs]\s*&&\s*[adf]\.set\([^,]+\s*,\s*encodeURIComponent\s*\(\s*(?P<sig>[a-zA-Z0-9$]+)\(',
r'\b[a-zA-Z0-9]+\s*&&\s*[a-zA-Z0-9]+\.set\([^,]+\s*,\s*encodeURIComponent\s*\(\s*(?P<sig>[a-zA-Z0-9$]+)\(',
r'\bm=(?P<sig>[a-zA-Z0-9$]{2,})\(decodeURIComponent\(h\.s\)\)',
r'\bc&&\(c=(?P<sig>[a-zA-Z0-9$]{2,})\(decodeURIComponent\(c\)\)',
r'(?:\b|[^a-zA-Z0-9$])(?P<sig>[a-zA-Z0-9$]{2,})\s*=\s*function\(\s*a\s*\)\s*{\s*a\s*=\s*a\.split\(\s*""\s*\)(?:;[a-zA-Z0-9$]{2}\.[a-zA-Z0-9$]{2}\(a,\d+\))?',
r'(?P<sig>[a-zA-Z0-9$]+)\s*=\s*function\(\s*a\s*\)\s*{\s*a\s*=\s*a\.split\(\s*""\s*\)',
# Obsolete patterns
r'("|\')signature\1\s*,\s*(?P<sig>[a-zA-Z0-9$]+)\(',
r'\.sig\|\|(?P<sig>[a-zA-Z0-9$]+)\(',
r'yt\.akamaized\.net/\)\s*\|\|\s*.*?\s*[cs]\s*&&\s*[adf]\.set\([^,]+\s*,\s*(?:encodeURIComponent\s*\()?\s*(?P<sig>[a-zA-Z0-9$]+)\(',
r'\b[cs]\s*&&\s*[adf]\.set\([^,]+\s*,\s*(?P<sig>[a-zA-Z0-9$]+)\(',
r'\b[a-zA-Z0-9]+\s*&&\s*[a-zA-Z0-9]+\.set\([^,]+\s*,\s*(?P<sig>[a-zA-Z0-9$]+)\(',
r'\bc\s*&&\s*[a-zA-Z0-9]+\.set\([^,]+\s*,\s*\([^)]*\)\s*\(\s*(?P<sig>[a-zA-Z0-9$]+)\('),
jscode, 'Initial JS player signature function name', group='sig')
@@ -3205,6 +3212,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
# * a.D&&(b="nn"[+a.D],c=a.get(b))&&(c=narray[idx](c),a.set(b,c),narray.length||nfunc("")
# * a.D&&(PL(a),b=a.j.n||null)&&(b=narray[0](b),a.set("n",b),narray.length||nfunc("")
# * a.D&&(b="nn"[+a.D],vL(a),c=a.j[b]||null)&&(c=narray[idx](c),a.set(b,c),narray.length||nfunc("")
# * J.J="";J.url="";J.Z&&(R="nn"[+J.Z],mW(J),N=J.K[R]||null)&&(N=narray[idx](N),J.set(R,N))}};
funcname, idx = self._search_regex(
r'''(?x)
(?:
@@ -3221,7 +3229,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
)\)&&\(c=|
\b(?P<var>[a-zA-Z0-9_$]+)=
)(?P<nfunc>[a-zA-Z0-9_$]+)(?:\[(?P<idx>\d+)\])?\([a-zA-Z]\)
(?(var),[a-zA-Z0-9_$]+\.set\("n"\,(?P=var)\),(?P=nfunc)\.length)''',
(?(var),[a-zA-Z0-9_$]+\.set\((?:"n+"|[a-zA-Z0-9_$]+)\,(?P=var)\))''',
jscode, 'n function name', group=('nfunc', 'idx'), default=(None, None))
if not funcname:
self.report_warning(join_nonempty(
@@ -3230,7 +3238,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
return self._search_regex(
r'''(?xs)
;\s*(?P<name>[a-zA-Z0-9_$]+)\s*=\s*function\([a-zA-Z0-9_$]+\)
\s*\{(?:(?!};).)+?["']enhanced_except_''',
\s*\{(?:(?!};).)+?return\s*(?P<q>["'])[\w-]+_w8_(?P=q)\s*\+\s*[a-zA-Z0-9_$]+''',
jscode, 'Initial JS player n function name', group='name')
elif not idx:
return funcname
@@ -3239,6 +3247,11 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
rf'var {re.escape(funcname)}\s*=\s*(\[.+?\])\s*[,;]', jscode,
f'Initial JS player n function list ({funcname}.{idx})')))[int(idx)]
def _fixup_n_function_code(self, argnames, code):
return argnames, re.sub(
rf';\s*if\s*\(\s*typeof\s+[a-zA-Z0-9_$]+\s*===?\s*(["\'])undefined\1\s*\)\s*return\s+{argnames[0]};',
';', code)
def _extract_n_function_code(self, video_id, player_url):
player_id = self._extract_player_info(player_url)
func_code = self.cache.load('youtube-nsig', player_id, min_ver='2024.07.09')
@@ -3250,7 +3263,8 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
func_name = self._extract_n_function_name(jscode, player_url=player_url)
func_code = jsi.extract_function_code(func_name)
# XXX: Workaround for the `typeof` gotcha
func_code = self._fixup_n_function_code(*jsi.extract_function_code(func_name))
self.cache.store('youtube-nsig', player_id, func_code)
return jsi, player_id, func_code
@@ -3266,7 +3280,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
except Exception as e:
raise JSInterpreter.Exception(traceback.format_exc(), cause=e)
if ret.startswith('enhanced_except_'):
if ret.startswith('enhanced_except_') or ret.endswith(s):
raise JSInterpreter.Exception('Signature function returned an exception')
return ret

View File

@@ -1,8 +1,8 @@
# Autogenerated by devscripts/update-version.py
__version__ = '2024.12.03'
__version__ = '2024.12.06'
RELEASE_GIT_HEAD = '2b67ac300ac8b44368fb121637d1743cea8c5b6b'
RELEASE_GIT_HEAD = '4bd2655398aed450456197a6767639114a24eac2'
VARIANT = None
@@ -12,4 +12,4 @@ CHANNEL = 'stable'
ORIGIN = 'yt-dlp/yt-dlp'
_pkg_version = '2024.12.03'
_pkg_version = '2024.12.06'