mirror of
https://github.com/itdoginfo/podkop.git
synced 2026-06-10 21:38:15 +03:00
125 lines
3.4 KiB
TypeScript
125 lines
3.4 KiB
TypeScript
import { ValidationResult } from './types';
|
|
import { parseQueryString } from '../helpers/parseQueryString';
|
|
|
|
export function validateHysteria2Url(url: string): ValidationResult {
|
|
try {
|
|
const isHY2 = url.startsWith('hysteria2://');
|
|
const isHY2Short = url.startsWith('hy2://');
|
|
|
|
if (!isHY2 && !isHY2Short)
|
|
return {
|
|
valid: false,
|
|
message: _('Invalid HY2 URL: must start with hysteria2:// or hy2://'),
|
|
};
|
|
|
|
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('#');
|
|
const [authHostPort, queryString] = mainPart.split('?');
|
|
|
|
if (!authHostPort)
|
|
return {
|
|
valid: false,
|
|
message: _('Invalid HY2 URL: missing credentials/server'),
|
|
};
|
|
|
|
const [passwordPart, hostPortPart] = authHostPort.split('@');
|
|
|
|
if (!passwordPart)
|
|
return { valid: false, message: _('Invalid HY2 URL: missing password') };
|
|
|
|
if (!hostPortPart)
|
|
return {
|
|
valid: false,
|
|
message: _('Invalid HY2 URL: missing host & port'),
|
|
};
|
|
|
|
const [host, port] = hostPortPart.split(':');
|
|
|
|
if (!host)
|
|
return { valid: false, message: _('Invalid HY2 URL: missing host') };
|
|
|
|
if (!port)
|
|
return { valid: false, message: _('Invalid HY2 URL: missing port') };
|
|
|
|
const cleanedPort = port.replace('/', '');
|
|
const portEntries = cleanedPort.split(',');
|
|
|
|
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);
|
|
const paramsKeys = Object.keys(params);
|
|
|
|
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))
|
|
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)
|
|
return {
|
|
valid: false,
|
|
message: _('Invalid HY2 URL: sni cannot be empty'),
|
|
};
|
|
}
|
|
|
|
return { valid: true, message: _('Valid') };
|
|
} catch (_e) {
|
|
return { valid: false, message: _('Invalid HY2 URL: parsing failed') };
|
|
}
|
|
}
|