diff --git a/fe-app-podkop/locales/calls.json b/fe-app-podkop/locales/calls.json index ecb7e1c..742d92b 100644 --- a/fe-app-podkop/locales/calls.json +++ b/fe-app-podkop/locales/calls.json @@ -648,56 +648,56 @@ "call": "Invalid HY2 URL: insecure must be 0 or 1", "key": "Invalid HY2 URL: insecure must be 0 or 1", "places": [ - "src/validators/validateHysteriaUrl.ts:76" + "src/validators/validateHysteriaUrl.ts:90" ] }, { "call": "Invalid HY2 URL: invalid port number", "key": "Invalid HY2 URL: invalid port number", "places": [ - "src/validators/validateHysteriaUrl.ts:62" + "src/validators/validateHysteriaUrl.ts:77" ] }, { "call": "Invalid HY2 URL: missing credentials/server", "key": "Invalid HY2 URL: missing credentials/server", "places": [ - "src/validators/validateHysteriaUrl.ts:32" + "src/validators/validateHysteriaUrl.ts:30" ] }, { "call": "Invalid HY2 URL: missing host", "key": "Invalid HY2 URL: missing host", "places": [ - "src/validators/validateHysteriaUrl.ts:49" + "src/validators/validateHysteriaUrl.ts:47" ] }, { "call": "Invalid HY2 URL: missing host & port", "key": "Invalid HY2 URL: missing host & port", "places": [ - "src/validators/validateHysteriaUrl.ts:43" + "src/validators/validateHysteriaUrl.ts:41" ] }, { "call": "Invalid HY2 URL: missing password", "key": "Invalid HY2 URL: missing password", "places": [ - "src/validators/validateHysteriaUrl.ts:38" + "src/validators/validateHysteriaUrl.ts:36" ] }, { "call": "Invalid HY2 URL: missing port", "key": "Invalid HY2 URL: missing port", "places": [ - "src/validators/validateHysteriaUrl.ts:53" + "src/validators/validateHysteriaUrl.ts:50" ] }, { "call": "Invalid HY2 URL: must not contain spaces", "key": "Invalid HY2 URL: must not contain spaces", "places": [ - "src/validators/validateHysteriaUrl.ts:19" + "src/validators/validateHysteriaUrl.ts:18" ] }, { @@ -711,28 +711,28 @@ "call": "Invalid HY2 URL: obfs-password required when obfs is set", "key": "Invalid HY2 URL: obfs-password required when obfs is set", "places": [ - "src/validators/validateHysteriaUrl.ts:99" + "src/validators/validateHysteriaUrl.ts:108" ] }, { "call": "Invalid HY2 URL: parsing failed", "key": "Invalid HY2 URL: parsing failed", "places": [ - "src/validators/validateHysteriaUrl.ts:115" + "src/validators/validateHysteriaUrl.ts:122" ] }, { "call": "Invalid HY2 URL: sni cannot be empty", "key": "Invalid HY2 URL: sni cannot be empty", "places": [ - "src/validators/validateHysteriaUrl.ts:108" + "src/validators/validateHysteriaUrl.ts:116" ] }, { "call": "Invalid HY2 URL: unsupported obfs type", "key": "Invalid HY2 URL: unsupported obfs type", "places": [ - "src/validators/validateHysteriaUrl.ts:88" + "src/validators/validateHysteriaUrl.ts:98" ] }, { @@ -943,7 +943,7 @@ "call": "Latest", "key": "Latest", "places": [ - "src/podkop/tabs/diagnostic/initController.ts:456" + "src/podkop/tabs/diagnostic/helpers/getPodkopVersionRow.ts:48" ] }, { @@ -1075,7 +1075,7 @@ "call": "Outdated", "key": "Outdated", "places": [ - "src/podkop/tabs/diagnostic/initController.ts:446" + "src/podkop/tabs/diagnostic/helpers/getPodkopVersionRow.ts:38" ] }, { @@ -1685,7 +1685,7 @@ "src/podkop/tabs/diagnostic/initController.ts:41", "src/podkop/tabs/diagnostic/initController.ts:42", "src/podkop/tabs/diagnostic/initController.ts:43", - "src/podkop/tabs/diagnostic/initController.ts:420" + "src/podkop/tabs/diagnostic/helpers/getPodkopVersionRow.ts:7" ] }, { @@ -1802,7 +1802,7 @@ "src/validators/validateDns.ts:18", "src/validators/validateDomain.ts:13", "src/validators/validateDomain.ts:30", - "src/validators/validateHysteriaUrl.ts:113", + "src/validators/validateHysteriaUrl.ts:120", "src/validators/validateIp.ts:8", "src/validators/validateOutboundJson.ts:7", "src/validators/validatePath.ts:16", diff --git a/fe-app-podkop/locales/podkop.pot b/fe-app-podkop/locales/podkop.pot index 1387107..d96b948 100644 --- a/fe-app-podkop/locales/podkop.pot +++ b/fe-app-podkop/locales/podkop.pot @@ -1,15 +1,15 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) 2026 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PODKOP package. -# romanvht , 2026. +# divocatt <210179590+divocatt@users.noreply.github.com>, 2026. #, fuzzy msgid "" msgstr "" "Project-Id-Version: PODKOP\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-05-09 02:49+1000\n" -"PO-Revision-Date: 2026-05-09 02:49+1000\n" -"Last-Translator: romanvht \n" +"POT-Creation-Date: 2026-05-29 13:40+0300\n" +"PO-Revision-Date: 2026-05-29 13:40+0300\n" +"Last-Translator: divocatt <210179590+divocatt@users.noreply.github.com>\n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" @@ -394,35 +394,35 @@ msgstr "" msgid "Invalid format. Use X.X.X.X or X.X.X.X/Y" msgstr "" -#: src/validators/validateHysteriaUrl.ts:76 +#: src/validators/validateHysteriaUrl.ts:90 msgid "Invalid HY2 URL: insecure must be 0 or 1" msgstr "" -#: src/validators/validateHysteriaUrl.ts:62 +#: src/validators/validateHysteriaUrl.ts:77 msgid "Invalid HY2 URL: invalid port number" msgstr "" -#: src/validators/validateHysteriaUrl.ts:32 +#: src/validators/validateHysteriaUrl.ts:30 msgid "Invalid HY2 URL: missing credentials/server" msgstr "" -#: src/validators/validateHysteriaUrl.ts:49 +#: src/validators/validateHysteriaUrl.ts:47 msgid "Invalid HY2 URL: missing host" msgstr "" -#: src/validators/validateHysteriaUrl.ts:43 +#: src/validators/validateHysteriaUrl.ts:41 msgid "Invalid HY2 URL: missing host & port" msgstr "" -#: src/validators/validateHysteriaUrl.ts:38 +#: src/validators/validateHysteriaUrl.ts:36 msgid "Invalid HY2 URL: missing password" msgstr "" -#: src/validators/validateHysteriaUrl.ts:53 +#: src/validators/validateHysteriaUrl.ts:50 msgid "Invalid HY2 URL: missing port" msgstr "" -#: src/validators/validateHysteriaUrl.ts:19 +#: src/validators/validateHysteriaUrl.ts:18 msgid "Invalid HY2 URL: must not contain spaces" msgstr "" @@ -430,19 +430,19 @@ msgstr "" msgid "Invalid HY2 URL: must start with hysteria2:// or hy2://" msgstr "" -#: src/validators/validateHysteriaUrl.ts:99 +#: src/validators/validateHysteriaUrl.ts:108 msgid "Invalid HY2 URL: obfs-password required when obfs is set" msgstr "" -#: src/validators/validateHysteriaUrl.ts:115 +#: src/validators/validateHysteriaUrl.ts:122 msgid "Invalid HY2 URL: parsing failed" msgstr "" -#: src/validators/validateHysteriaUrl.ts:108 +#: src/validators/validateHysteriaUrl.ts:116 msgid "Invalid HY2 URL: sni cannot be empty" msgstr "" -#: src/validators/validateHysteriaUrl.ts:88 +#: src/validators/validateHysteriaUrl.ts:98 msgid "Invalid HY2 URL: unsupported obfs type" msgstr "" @@ -563,7 +563,7 @@ msgstr "" msgid "Issues detected" msgstr "" -#: src/podkop/tabs/diagnostic/initController.ts:456 +#: src/podkop/tabs/diagnostic/helpers/getPodkopVersionRow.ts:48 msgid "Latest" msgstr "" @@ -641,7 +641,7 @@ msgstr "" msgid "Outbound Configuration" msgstr "" -#: src/podkop/tabs/diagnostic/initController.ts:446 +#: src/podkop/tabs/diagnostic/helpers/getPodkopVersionRow.ts:38 msgid "Outdated" msgstr "" @@ -996,7 +996,7 @@ msgstr "" #: src/podkop/tabs/diagnostic/initController.ts:41 #: src/podkop/tabs/diagnostic/initController.ts:42 #: src/podkop/tabs/diagnostic/initController.ts:43 -#: src/podkop/tabs/diagnostic/initController.ts:420 +#: src/podkop/tabs/diagnostic/helpers/getPodkopVersionRow.ts:7 msgid "unknown" msgstr "" @@ -1065,7 +1065,7 @@ msgstr "" #: src/validators/validateDns.ts:18 #: src/validators/validateDomain.ts:13 #: src/validators/validateDomain.ts:30 -#: src/validators/validateHysteriaUrl.ts:113 +#: src/validators/validateHysteriaUrl.ts:120 #: src/validators/validateIp.ts:8 #: src/validators/validateOutboundJson.ts:7 #: src/validators/validatePath.ts:16 diff --git a/fe-app-podkop/locales/podkop.ru.po b/fe-app-podkop/locales/podkop.ru.po index 52b3ff2..77a33a4 100644 --- a/fe-app-podkop/locales/podkop.ru.po +++ b/fe-app-podkop/locales/podkop.ru.po @@ -1,15 +1,15 @@ # RU translations for PODKOP package. # Copyright (C) 2026 THE PODKOP'S COPYRIGHT HOLDER # This file is distributed under the same license as the PODKOP package. -# romanvht, 2026. +# divocatt, 2026. # msgid "" msgstr "" "Project-Id-Version: PODKOP\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-05-09 12:50+1000\n" -"PO-Revision-Date: 2026-05-09 12:50+1000\n" -"Last-Translator: romanvht\n" +"POT-Creation-Date: 2026-05-29 16:40+0300\n" +"PO-Revision-Date: 2026-05-29 16:40+0300\n" +"Last-Translator: divocatt\n" "Language-Team: none\n" "Language: ru\n" "MIME-Version: 1.0\n" diff --git a/fe-app-podkop/src/podkop/methods/custom/getDashboardSections.ts b/fe-app-podkop/src/podkop/methods/custom/getDashboardSections.ts index 6696d66..a1f12d0 100644 --- a/fe-app-podkop/src/podkop/methods/custom/getDashboardSections.ts +++ b/fe-app-podkop/src/podkop/methods/custom/getDashboardSections.ts @@ -29,7 +29,9 @@ export async function getDashboardSections(): Promise - section.connection_type !== 'block' && section['.type'] !== 'settings', + section.connection_type !== 'block' && + section.connection_type !== 'exclusion' && + section['.type'] !== 'settings', ) .map((section) => { if (section.connection_type === 'proxy') { diff --git a/fe-app-podkop/src/podkop/types.ts b/fe-app-podkop/src/podkop/types.ts index 672ec0c..fff03c5 100644 --- a/fe-app-podkop/src/podkop/types.ts +++ b/fe-app-podkop/src/podkop/types.ts @@ -122,13 +122,18 @@ export namespace Podkop { connection_type: 'block'; } + export interface ConfigExclusionSection { + connection_type: 'exclusion'; + } + export type ConfigBaseSection = | ConfigProxyUrlTestSection | ConfigProxySelectorSection | ConfigProxyUrlSection | ConfigProxyOutboundSection | ConfigVpnSection - | ConfigBlockSection; + | ConfigBlockSection + | ConfigExclusionSection; export type ConfigSection = ConfigBaseSection & { '.name': string; diff --git a/fe-app-podkop/src/validators/tests/validateHysteriaUrl.test.js b/fe-app-podkop/src/validators/tests/validateHysteriaUrl.test.js index b759fd2..ce1f480 100644 --- a/fe-app-podkop/src/validators/tests/validateHysteriaUrl.test.js +++ b/fe-app-podkop/src/validators/tests/validateHysteriaUrl.test.js @@ -28,6 +28,11 @@ const validUrls = [ // Explicit obfs=none (valid) ['obfs none = ok', 'hysteria2://pw@example.com:443/?obfs=none#hy2-none'], + + [ + 'port range 5000-6000', + 'hysteria2://letmein@example.com:123,5000-6000/?insecure=1&obfs=salamander&obfs-password=gawrgura&pinSHA256=deadbeef&sni=real.example.com', + ], ]; const invalidUrls = [ diff --git a/fe-app-podkop/src/validators/validateHysteriaUrl.ts b/fe-app-podkop/src/validators/validateHysteriaUrl.ts index 464f16d..d9a01fe 100644 --- a/fe-app-podkop/src/validators/validateHysteriaUrl.ts +++ b/fe-app-podkop/src/validators/validateHysteriaUrl.ts @@ -6,19 +6,17 @@ export function validateHysteria2Url(url: string): ValidationResult { const isHY2 = url.startsWith('hysteria2://'); const isHY2Short = url.startsWith('hy2://'); - if (!isHY2 && !isHY2Short) { + if (!isHY2 && !isHY2Short) return { valid: false, message: _('Invalid HY2 URL: must start with hysteria2:// or hy2://'), }; - } - if (/\s/.test(url)) { + if (/\s/.test(url)) return { valid: false, message: _('Invalid HY2 URL: must not contain spaces'), }; - } const prefix = isHY2 ? 'hysteria2://' : 'hy2://'; const body = url.slice(prefix.length); @@ -45,23 +43,39 @@ export function validateHysteria2Url(url: string): ValidationResult { const [host, port] = hostPortPart.split(':'); - if (!host) { + if (!host) return { valid: false, message: _('Invalid HY2 URL: missing host') }; - } - if (!port) { + if (!port) return { valid: false, message: _('Invalid HY2 URL: missing port') }; - } const cleanedPort = port.replace('/', ''); - const portNum = Number(cleanedPort); + const portEntries = cleanedPort.split(','); - if (!Number.isInteger(portNum) || portNum < 1 || portNum > 65535) { + const isValidPortNumber = (value: string) => { + if (!/^\d+$/.test(value)) return false; + const num = Number(value); + return num >= 1 && num <= 65535; + }; + + const isValidPortEntry = (entry: string) => { + if (!entry) return false; + if (!entry.includes('-')) return isValidPortNumber(entry); + + const rangeParts = entry.split('-'); + if (rangeParts.length !== 2) return false; + + const [start, end] = rangeParts; + if (!isValidPortNumber(start) || !isValidPortNumber(end)) return false; + + return Number(start) <= Number(end); + }; + + if (!portEntries.every(isValidPortEntry)) return { valid: false, message: _('Invalid HY2 URL: invalid port number'), }; - } if (queryString) { const params = parseQueryString(queryString); @@ -70,44 +84,37 @@ export function validateHysteria2Url(url: string): ValidationResult { if ( paramsKeys.includes('insecure') && !['0', '1'].includes(params.insecure) - ) { + ) return { valid: false, message: _('Invalid HY2 URL: insecure must be 0 or 1'), }; - } const validObfsTypes = ['none', 'salamander']; - if ( - paramsKeys.includes('obfs') && - !validObfsTypes.includes(params.obfs) - ) { + if (paramsKeys.includes('obfs') && !validObfsTypes.includes(params.obfs)) return { valid: false, message: _('Invalid HY2 URL: unsupported obfs type'), }; - } if ( paramsKeys.includes('obfs') && params.obfs !== 'none' && !params['obfs-password'] - ) { + ) return { valid: false, message: _( 'Invalid HY2 URL: obfs-password required when obfs is set', ), }; - } - if (paramsKeys.includes('sni') && !params.sni) { + if (paramsKeys.includes('sni') && !params.sni) return { valid: false, message: _('Invalid HY2 URL: sni cannot be empty'), }; - } } return { valid: true, message: _('Valid') }; diff --git a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js index f7b9eab..009c1ae 100644 --- a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js +++ b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js @@ -453,18 +453,16 @@ function validateHysteria2Url(url) { try { const isHY2 = url.startsWith("hysteria2://"); const isHY2Short = url.startsWith("hy2://"); - if (!isHY2 && !isHY2Short) { + if (!isHY2 && !isHY2Short) return { valid: false, message: _("Invalid HY2 URL: must start with hysteria2:// or hy2://") }; - } - if (/\s/.test(url)) { + if (/\s/.test(url)) return { valid: false, message: _("Invalid HY2 URL: must not contain spaces") }; - } const prefix = isHY2 ? "hysteria2://" : "hy2://"; const body = url.slice(prefix.length); const [mainPart] = body.split("#"); @@ -483,50 +481,57 @@ function validateHysteria2Url(url) { message: _("Invalid HY2 URL: missing host & port") }; const [host, port] = hostPortPart.split(":"); - if (!host) { + if (!host) return { valid: false, message: _("Invalid HY2 URL: missing host") }; - } - if (!port) { + if (!port) return { valid: false, message: _("Invalid HY2 URL: missing port") }; - } const cleanedPort = port.replace("/", ""); - const portNum = Number(cleanedPort); - if (!Number.isInteger(portNum) || portNum < 1 || portNum > 65535) { + const portEntries = cleanedPort.split(","); + const isValidPortNumber = (value) => { + if (!/^\d+$/.test(value)) return false; + const num = Number(value); + return num >= 1 && num <= 65535; + }; + const isValidPortEntry = (entry) => { + if (!entry) return false; + if (!entry.includes("-")) return isValidPortNumber(entry); + const rangeParts = entry.split("-"); + if (rangeParts.length !== 2) return false; + const [start, end] = rangeParts; + if (!isValidPortNumber(start) || !isValidPortNumber(end)) return false; + return Number(start) <= Number(end); + }; + if (!portEntries.every(isValidPortEntry)) return { valid: false, message: _("Invalid HY2 URL: invalid port number") }; - } if (queryString) { const params = parseQueryString(queryString); const paramsKeys = Object.keys(params); - if (paramsKeys.includes("insecure") && !["0", "1"].includes(params.insecure)) { + if (paramsKeys.includes("insecure") && !["0", "1"].includes(params.insecure)) return { valid: false, message: _("Invalid HY2 URL: insecure must be 0 or 1") }; - } const validObfsTypes = ["none", "salamander"]; - if (paramsKeys.includes("obfs") && !validObfsTypes.includes(params.obfs)) { + if (paramsKeys.includes("obfs") && !validObfsTypes.includes(params.obfs)) return { valid: false, message: _("Invalid HY2 URL: unsupported obfs type") }; - } - if (paramsKeys.includes("obfs") && params.obfs !== "none" && !params["obfs-password"]) { + if (paramsKeys.includes("obfs") && params.obfs !== "none" && !params["obfs-password"]) return { valid: false, message: _( "Invalid HY2 URL: obfs-password required when obfs is set" ) }; - } - if (paramsKeys.includes("sni") && !params.sni) { + if (paramsKeys.includes("sni") && !params.sni) return { valid: false, message: _("Invalid HY2 URL: sni cannot be empty") }; - } } return { valid: true, message: _("Valid") }; } catch (_e) { @@ -711,7 +716,7 @@ async function getDashboardSections() { }) ); const data = configSections.filter( - (section) => section.connection_type !== "block" && section[".type"] !== "settings" + (section) => section.connection_type !== "block" && section.connection_type !== "exclusion" && section[".type"] !== "settings" ).map((section) => { if (section.connection_type === "proxy") { if (section.proxy_config_type === "url") { diff --git a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js index 6c89ed3..efe3c29 100644 --- a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js +++ b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js @@ -311,7 +311,7 @@ function createSettingsContent(section) { for (const secName in sections) { const sec = sections[secName]; - if (sec[".type"] === "section") { + if (sec[".type"] === "section" && sec['connection_type'] !== 'block' && sec['connection_type'] !== 'exclusion') { this.keylist.push(secName); this.vallist.push(secName); } diff --git a/luci-app-podkop/po/ru/podkop.po b/luci-app-podkop/po/ru/podkop.po index 52b3ff2..77a33a4 100644 --- a/luci-app-podkop/po/ru/podkop.po +++ b/luci-app-podkop/po/ru/podkop.po @@ -1,15 +1,15 @@ # RU translations for PODKOP package. # Copyright (C) 2026 THE PODKOP'S COPYRIGHT HOLDER # This file is distributed under the same license as the PODKOP package. -# romanvht, 2026. +# divocatt, 2026. # msgid "" msgstr "" "Project-Id-Version: PODKOP\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-05-09 12:50+1000\n" -"PO-Revision-Date: 2026-05-09 12:50+1000\n" -"Last-Translator: romanvht\n" +"POT-Creation-Date: 2026-05-29 16:40+0300\n" +"PO-Revision-Date: 2026-05-29 16:40+0300\n" +"Last-Translator: divocatt\n" "Language-Team: none\n" "Language: ru\n" "MIME-Version: 1.0\n" diff --git a/luci-app-podkop/po/templates/podkop.pot b/luci-app-podkop/po/templates/podkop.pot index 1387107..d96b948 100644 --- a/luci-app-podkop/po/templates/podkop.pot +++ b/luci-app-podkop/po/templates/podkop.pot @@ -1,15 +1,15 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) 2026 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PODKOP package. -# romanvht , 2026. +# divocatt <210179590+divocatt@users.noreply.github.com>, 2026. #, fuzzy msgid "" msgstr "" "Project-Id-Version: PODKOP\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-05-09 02:49+1000\n" -"PO-Revision-Date: 2026-05-09 02:49+1000\n" -"Last-Translator: romanvht \n" +"POT-Creation-Date: 2026-05-29 13:40+0300\n" +"PO-Revision-Date: 2026-05-29 13:40+0300\n" +"Last-Translator: divocatt <210179590+divocatt@users.noreply.github.com>\n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" @@ -394,35 +394,35 @@ msgstr "" msgid "Invalid format. Use X.X.X.X or X.X.X.X/Y" msgstr "" -#: src/validators/validateHysteriaUrl.ts:76 +#: src/validators/validateHysteriaUrl.ts:90 msgid "Invalid HY2 URL: insecure must be 0 or 1" msgstr "" -#: src/validators/validateHysteriaUrl.ts:62 +#: src/validators/validateHysteriaUrl.ts:77 msgid "Invalid HY2 URL: invalid port number" msgstr "" -#: src/validators/validateHysteriaUrl.ts:32 +#: src/validators/validateHysteriaUrl.ts:30 msgid "Invalid HY2 URL: missing credentials/server" msgstr "" -#: src/validators/validateHysteriaUrl.ts:49 +#: src/validators/validateHysteriaUrl.ts:47 msgid "Invalid HY2 URL: missing host" msgstr "" -#: src/validators/validateHysteriaUrl.ts:43 +#: src/validators/validateHysteriaUrl.ts:41 msgid "Invalid HY2 URL: missing host & port" msgstr "" -#: src/validators/validateHysteriaUrl.ts:38 +#: src/validators/validateHysteriaUrl.ts:36 msgid "Invalid HY2 URL: missing password" msgstr "" -#: src/validators/validateHysteriaUrl.ts:53 +#: src/validators/validateHysteriaUrl.ts:50 msgid "Invalid HY2 URL: missing port" msgstr "" -#: src/validators/validateHysteriaUrl.ts:19 +#: src/validators/validateHysteriaUrl.ts:18 msgid "Invalid HY2 URL: must not contain spaces" msgstr "" @@ -430,19 +430,19 @@ msgstr "" msgid "Invalid HY2 URL: must start with hysteria2:// or hy2://" msgstr "" -#: src/validators/validateHysteriaUrl.ts:99 +#: src/validators/validateHysteriaUrl.ts:108 msgid "Invalid HY2 URL: obfs-password required when obfs is set" msgstr "" -#: src/validators/validateHysteriaUrl.ts:115 +#: src/validators/validateHysteriaUrl.ts:122 msgid "Invalid HY2 URL: parsing failed" msgstr "" -#: src/validators/validateHysteriaUrl.ts:108 +#: src/validators/validateHysteriaUrl.ts:116 msgid "Invalid HY2 URL: sni cannot be empty" msgstr "" -#: src/validators/validateHysteriaUrl.ts:88 +#: src/validators/validateHysteriaUrl.ts:98 msgid "Invalid HY2 URL: unsupported obfs type" msgstr "" @@ -563,7 +563,7 @@ msgstr "" msgid "Issues detected" msgstr "" -#: src/podkop/tabs/diagnostic/initController.ts:456 +#: src/podkop/tabs/diagnostic/helpers/getPodkopVersionRow.ts:48 msgid "Latest" msgstr "" @@ -641,7 +641,7 @@ msgstr "" msgid "Outbound Configuration" msgstr "" -#: src/podkop/tabs/diagnostic/initController.ts:446 +#: src/podkop/tabs/diagnostic/helpers/getPodkopVersionRow.ts:38 msgid "Outdated" msgstr "" @@ -996,7 +996,7 @@ msgstr "" #: src/podkop/tabs/diagnostic/initController.ts:41 #: src/podkop/tabs/diagnostic/initController.ts:42 #: src/podkop/tabs/diagnostic/initController.ts:43 -#: src/podkop/tabs/diagnostic/initController.ts:420 +#: src/podkop/tabs/diagnostic/helpers/getPodkopVersionRow.ts:7 msgid "unknown" msgstr "" @@ -1065,7 +1065,7 @@ msgstr "" #: src/validators/validateDns.ts:18 #: src/validators/validateDomain.ts:13 #: src/validators/validateDomain.ts:30 -#: src/validators/validateHysteriaUrl.ts:113 +#: src/validators/validateHysteriaUrl.ts:120 #: src/validators/validateIp.ts:8 #: src/validators/validateOutboundJson.ts:7 #: src/validators/validatePath.ts:16 diff --git a/podkop/files/usr/lib/sing_box_config_facade.sh b/podkop/files/usr/lib/sing_box_config_facade.sh index 6887e20..7641673 100644 --- a/podkop/files/usr/lib/sing_box_config_facade.sh +++ b/podkop/files/usr/lib/sing_box_config_facade.sh @@ -178,8 +178,9 @@ _add_outbound_security() { local security scheme security=$(url_get_query_param "$url" "security") + scheme="$(url_get_scheme "$url")" + if [ -z "$security" ]; then - scheme="$(url_get_scheme "$url")" if [ "$scheme" = "hysteria2" ] || [ "$scheme" = "hy2" ]; then security="tls" fi @@ -195,6 +196,10 @@ _add_outbound_security() { public_key=$(url_get_query_param "$url" "pbk") short_id=$(url_get_query_param "$url" "sid") + if [ "$scheme" = "hysteria2" ] || [ "$scheme" = "hy2" ]; then + fingerprint="" + fi + config=$( sing_box_cm_set_tls_for_outbound \ "$config" \ diff --git a/podkop/files/usr/lib/sing_box_config_manager.sh b/podkop/files/usr/lib/sing_box_config_manager.sh index 782550f..c1a2943 100644 --- a/podkop/files/usr/lib/sing_box_config_manager.sh +++ b/podkop/files/usr/lib/sing_box_config_manager.sh @@ -692,6 +692,11 @@ sing_box_cm_add_hysteria2_outbound() { local download_mbps="$9" local network="${10}" + local is_multi_port="false" + case "$server_port" in + *","*|*"-"*) is_multi_port="true" ;; + esac + echo "$config" | jq \ --arg tag "$tag" \ --arg server_address "$server_address" \ @@ -702,14 +707,25 @@ sing_box_cm_add_hysteria2_outbound() { --arg upload_mbps "$upload_mbps" \ --arg download_mbps "$download_mbps" \ --arg network "$network" \ - '.outbounds += [( + --argjson is_multi_port "$is_multi_port" \ + ' + def parse_port_entry: + if index("-") then split("-") | join(":") + else . + ":" + . + end; + + .outbounds += [( { type: "hysteria2", tag: $tag, server: $server_address, - server_port: ($server_port | tonumber), password: $password } + + (if $is_multi_port then { + server_ports: ($server_port | split(",") | map(ltrimstr(" ") | rtrimstr(" ") | parse_port_entry)) + } else { + server_port: ($server_port | tonumber) + } end) + (if $obfuscator_type != "" and $obfuscator_password != "" then { obfs: { type: $obfuscator_type,