From 28bd924bd7d1106e7900da902e32062f8d7d476f Mon Sep 17 00:00:00 2001 From: enximi Date: Fri, 10 Apr 2026 14:52:35 +0800 Subject: [PATCH] parser: accept plaintext SS userinfo emitted by Sub-Store Subconverter currently accepts SS links where the userinfo before `@` is URL-safe base64: ss://@server:port#remark Example shape: ss://YWVzLTI1Ni1nY206YzJWamNtVjA@server.example.com:443#Node Sub-Store can also emit SS links where the userinfo is plaintext and URL-encoded instead of base64-encoded: ss://:@server:port#remark Example shape: ss://aes-256-gcm:c2VjcmV0JTNEJTNE@server.example.com:443#Node The previous parser only tried to base64-decode the userinfo when `@` was present, so plaintext SS userinfo in this form was rejected. Keep the existing base64 path and add a fallback that parses URL-decoded plaintext `method:password` userinfo. --- src/parser/subparser.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/parser/subparser.cpp b/src/parser/subparser.cpp index 6ef0f7f74..d9e8cd4e3 100644 --- a/src/parser/subparser.cpp +++ b/src/parser/subparser.cpp @@ -609,6 +609,9 @@ void explodeVmessConf(std::string content, std::vector &nodes) void explodeSS(std::string ss, Proxy &node) { std::string ps, password, method, server, port, plugins, plugin, pluginopts, addition, group = SS_DEFAULT_GROUP, secret; + auto parse_ss_userinfo = [&](const std::string &userinfo) { + return regGetMatch(userinfo, "(\\S+?):(\\S+)", 3, 0, &method, &password) == 0; + }; //std::vector args, secret; ss = replaceAllDistinct(ss.substr(5), "/?", "?"); if(strFind(ss, "#")) @@ -634,7 +637,7 @@ void explodeSS(std::string ss, Proxy &node) { if(regGetMatch(ss, "(\\S+?)@(\\S+):(\\d+)", 4, 0, &secret, &server, &port)) return; - if(regGetMatch(urlSafeBase64Decode(secret), "(\\S+?):(\\S+)", 3, 0, &method, &password)) + if(!parse_ss_userinfo(urlSafeBase64Decode(secret)) && !parse_ss_userinfo(urlDecode(secret))) return; } else