import { ValidationResult } from './types'; import { isValidHost, isValidPort } from './hostPort'; function decodeBase64Json(value: string): unknown { const normalized = value.replace(/-/g, '+').replace(/_/g, '/'); const padded = normalized.padEnd( normalized.length + ((4 - (normalized.length % 4)) % 4), '=', ); const binary = atob(padded); const decoded = decodeURIComponent( Array.from(binary) .map((char) => `%${char.charCodeAt(0).toString(16).padStart(2, '0')}`) .join(''), ); return JSON.parse(decoded); } export function validateVmessUrl(url: string): ValidationResult { try { if (!url.startsWith('vmess://')) { return { valid: false, message: 'Invalid VMess URL: must start with vmess://', }; } if (/\s/.test(url)) { return { valid: false, message: 'Invalid VMess URL: must not contain spaces', }; } const body = url.slice('vmess://'.length); const [encoded] = body.split('#'); if (!encoded) { return { valid: false, message: 'Invalid VMess URL: missing encoded config', }; } const config = decodeBase64Json(encoded); if (!config || typeof config !== 'object') { return { valid: false, message: 'Invalid VMess URL: invalid config' }; } const { add, port, id } = config as Record; if (!add || typeof add !== 'string' || !isValidHost(add)) { return { valid: false, message: 'Invalid VMess URL: invalid server' }; } if (!isValidPort(port)) { return { valid: false, message: 'Invalid VMess URL: invalid port number', }; } if (!id || typeof id !== 'string') { return { valid: false, message: 'Invalid VMess URL: missing UUID' }; } return { valid: true, message: _('Valid') }; } catch (_e) { return { valid: false, message: _('Invalid VMess URL: parsing failed') }; } }