瀏覽代碼

luci-app-ssr-plus: optimize code.

zxlhhyccc 4 天之前
父節點
當前提交
f02a09479e

+ 7 - 7
luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm

@@ -177,13 +177,13 @@ function import_ssr_url(btn, urlname, sid) {
 
 			// 再分离 ? 或 /?(参数)
 			var queryIndex = (url0 = url0.replace('/?', '?')).indexOf("?");
-			var queryStr = "";
+			var query = "";
 			if (queryIndex >= 0) {
-				queryStr = url0.substring(queryIndex + 1);
+				query = url0.substring(queryIndex + 1);
 				url0 = url0.substring(0, queryIndex);
 			}
 
-			var params = Object.fromEntries(new URLSearchParams(queryStr));
+			var params = Object.fromEntries(new URLSearchParams(query));
 
 			if ( ! params.type) {
 				// 普通 SS 导入逻辑
@@ -503,7 +503,7 @@ function import_ssr_url(btn, urlname, sid) {
 				document.getElementsByName('cbid.shadowsocksr.' + sid + '.password')[0].value = decodeURIComponent(url.username);
 				document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].checked = true;
 				document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].dispatchEvent(event);
-				document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_host')[0].value = params.get("sni");
+				document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_host')[0].value = params.get("peer") || params.get("sni");
 				if (params.get("allowInsecure") === "1") {
 					document.getElementsByName('cbid.shadowsocksr.' + sid + '.insecure')[0].checked = true; // 设置 insecure 为 true
 					document.getElementsByName('cbid.shadowsocksr.' + sid + '.insecure')[0].dispatchEvent(event); // 触发事件
@@ -834,13 +834,13 @@ function import_ssr_url(btn, urlname, sid) {
 
 			// 再分离 ? 或 /?(参数)
 			var queryIndex = (url0 = url0.replace('/?', '?')).indexOf("?");
-			var queryStr = "";
+			var query = "";
 			if (queryIndex >= 0) {
-				queryStr = url0.substring(queryIndex + 1);
+				query = url0.substring(queryIndex + 1);
 				url0 = url0.substring(0, queryIndex);
 			}
 
-			var params = Object.fromEntries(new URLSearchParams(queryStr));
+			var params = Object.fromEntries(new URLSearchParams(query));
 
 			var sipIndex = url0.indexOf("@");
 			var userInfo = url0.substring(0, sipIndex);      // 格式:uuid:password

+ 131 - 162
luci-app-ssr-plus/root/usr/share/shadowsocksr/subscribe.lua

@@ -318,8 +318,10 @@ local function processData(szType, content)
 			result.xhttp_host = info.host
 			result.xhttp_path = info.path
 			-- 检查 extra 参数是否存在且非空
-			result.enable_xhttp_extra = (info.extra and info.extra ~= "") and "1" or nil
-			result.xhttp_extra = (info.extra and info.extra ~= "") and info.extra or nil
+			if params.extra and params.extra ~= "" then
+				result.enable_xhttp_extra = "1"
+				result.xhttp_extra = params.extra
+			end
 			-- 尝试解析 JSON 数据
 			local success, Data = pcall(jsonParse, info.extra or "")
 			if success and type(Data) == "table" then
@@ -403,16 +405,18 @@ local function processData(szType, content)
 		local idx_sp = content:find("#") or 0
 		local alias = ""
 		if idx_sp > 0 then
-			alias = UrlDecode(content:sub(idx_sp + 1))
+			alias = content:sub(idx_sp + 1, -1)
+			content = content:sub(0, idx_sp - 1):gsub("/%?", "?")
 		end
-		local info = content:sub(1, idx_sp > 0 and idx_sp - 1 or #content):gsub("/%?", "?")
+		result.alias = UrlDecode(alias)
 
 		-- 拆 base64 主体和 ? 参数部分
-		local uri_main, query_str = info:match("^([^?]+)%??(.*)$")
-		--log("SS 节点格式:", uri_main)
+		local info = content
+		local find_index, query = info:match("^([^?]+)%??(.*)$")
+		--log("SS 节点格式:", find_index)
 		local params = {}
-		if query_str and query_str ~= "" then
-			for _, v in ipairs(split(query_str, '&')) do
+		if query and query ~= "" then
+			for _, v in ipairs(split(query, '&')) do
 				local t = split(v, '=')
 				if #t >= 2 then
 					params[t[1]] = UrlDecode(t[2])
@@ -421,28 +425,28 @@ local function processData(szType, content)
 		end
 
 		if not params.type or params.type == "" then
-			local is_old_format = uri_main:find("@") and not uri_main:find("://.*@")
-			local base64_str, host_port, userinfo, server, port, method, password
+			local is_old_format = find_index:find("@") and not find_index:find("://.*@")
+			local old_base64, host_port, userinfo, server, port, method, password
 
 			if is_old_format then
 				-- 旧格式:base64(method:pass)@host:port
-				base64_str, host_port = uri_main:match("^([^@]+)@(.-)$")
-				log("SS 节点旧格式解析:", base64_str)
-				if not base64_str or not host_port then
-					log("SS 节点旧格式解析失败:", uri_main)
+				old_base64, host_port = find_index:match("^([^@]+)@(.-)$")
+				log("SS 节点旧格式解析:", old_base64)
+				if not old_base64 or not host_port then
+					log("SS 节点旧格式解析失败:", find_index)
 					return nil
 				end
-				local decoded = base64Decode(UrlDecode(base64_str))
+				local decoded = base64Decode(UrlDecode(old_base64))
 				if not decoded then
-					log("SS base64 解码失败(旧格式):", base64_str)
+					log("SS base64 解码失败(旧格式):", old_base64)
 					return nil
 				end
 				userinfo = decoded
 			else
 				-- 新格式:base64(method:pass@host:port)
-				local decoded = base64Decode(UrlDecode(uri_main))
+				local decoded = base64Decode(UrlDecode(find_index))
 				if not decoded then
-					log("SS base64 解码失败(新格式):", uri_main)
+					log("SS base64 解码失败(新格式):", find_index)
 					return nil
 				end
 				userinfo, host_port = decoded:match("^(.-)@(.-)$")
@@ -453,13 +457,13 @@ local function processData(szType, content)
 			end
 
 			-- 解析加密方式和密码(允许密码包含冒号)
-			local split_pos = userinfo:find(":")
-			if not split_pos then
+			local meth_pass = userinfo:find(":")
+			if not meth_pass then
 				log("SS 用户信息格式错误:", userinfo)
 				return nil
 			end
-			method = userinfo:sub(1, split_pos - 1)
-			password = userinfo:sub(split_pos + 1)
+			method = userinfo:sub(1, meth_pass - 1)
+			password = userinfo:sub(meth_pass + 1)
 
 			-- 判断密码是否经过url编码
 			local function isURLEncodedPassword(pwd)
@@ -492,23 +496,13 @@ local function processData(szType, content)
 			end
 
 			-- 填充 result
-			result.alias = alias
 			result.type = v2_ss
-			result.v2ray_protocol = (v2_ss == "v2ray") and "shadowsocks" or nil
 			result.has_ss_type = has_ss_type
 			result.encrypt_method_ss = method
 			result.password = password
 			result.server = server
 			result.server_port = port
 
-			-- 仅在 v2ray + shadowsocks 协议时处理 ECH
-			if v2_ss == "v2ray" and result.v2ray_protocol == "shadowsocks" then
-				if params.ech and params.ech ~= "" then
-					result.enable_ech = "1"
-					result.ech_config = ech
-				end
-			end
-
 			-- 插件处理
 			if params.plugin then
 				local plugin_info = UrlDecode(params.plugin)
@@ -573,17 +567,17 @@ local function processData(szType, content)
 			local url = URL.parse("http://" .. info)
 			local params = url.query
 
-			result.alias = alias
-			result.type = "v2ray"
+			v2_ss = "v2ray"
+			result.type = v2_ss
 			result.v2ray_protocol = "shadowsocks"
 			result.server = url.host
 			result.server_port = url.port
 
 			-- 判断 @ 前部分是否为 Base64
-			local is_base64_decoded = base64Decode(UrlDecode(url.user))
-			if is_base64_decoded:find(":") then
+			local is_base64 = base64Decode(UrlDecode(url.user))
+			if is_base64:find(":") then
         		-- 新格式:method:password
-        		result.encrypt_method_ss, result.password = is_base64_decoded:match("^(.-):(.*)$")
+        		result.encrypt_method_ss, result.password = is_base64:match("^(.-):(.*)$")
 			else
         		-- 旧格式:UUID 直接作为密码
         		result.password = url.user
@@ -613,11 +607,15 @@ local function processData(szType, content)
 			result.reality_shortid = params.sid
 			result.reality_spiderx = params.spx and UrlDecode(params.spx) or nil
 			-- 检查 ech 参数是否存在且非空
-			result.enable_ech = (params.ech and params.ech ~= "") and "1" or nil
-			result.ech_config = (params.ech and params.ech ~= "") and params.ech or nil
+			if params.ech and params.ech ~= "" then
+				result.enable_ech = "1"
+				result.ech_config = params.ech
+			end
 			-- 检查 pqv 参数是否存在且非空
-			result.enable_mldsa65verify = (params.pqv and params.pqv ~= "") and "1" or nil
-			result.reality_mldsa65verify = (params.pqv and params.pqv ~= "") and params.pqv or nil
+			if params.pqv and params.pqv ~= "" then
+				result.enable_mldsa65verify = "1"
+				result.reality_mldsa65verify = params.pqv
+			end
 			if result.transport == "ws" then
 				result.ws_host = (result.tls ~= "1") and (params.host and UrlDecode(params.host)) or nil
 				result.ws_path = params.path and UrlDecode(params.path) or "/"
@@ -629,8 +627,10 @@ local function processData(szType, content)
 				result.xhttp_mode = params.mode or "auto"
 				result.xhttp_path = params.path and UrlDecode(params.path) or "/"
 				-- 检查 extra 参数是否存在且非空
-				result.enable_xhttp_extra = (params.extra and params.extra ~= "") and "1" or nil
-				result.xhttp_extra = (params.extra and params.extra ~= "") and params.extra or nil
+				if params.extra and params.extra ~= "" then
+					result.enable_xhttp_extra = "1"
+					result.xhttp_extra = params.extra
+				end
 				-- 尝试解析 JSON 数据
 				local success, Data = pcall(jsonParse, params.extra or "")
 				if success and type(Data) == "table" then
@@ -703,90 +703,67 @@ local function processData(szType, content)
 			result.server = nil
 		end
 	elseif szType == "trojan" then
-		local params = {}
-		local idx_sp = 0
-		local alias = ""
-
 		-- 提取别名(如果存在)
+		local alias = ""
 		if content:find("#") then
-			idx_sp = content:find("#")
+			local idx_sp = content:find("#")
 			alias = content:sub(idx_sp + 1, -1)
+			content = content:sub(0, idx_sp - 1)
 		end
-		local info = content:sub(1, idx_sp > 0 and idx_sp - 1 or #content):gsub("/%?", "?")
-		local paramStr = ""
-
-		if info:find("?") then
-			paramStr = info:match("%?(.*)$") or ""
-			info = info:gsub("%?.*$", "") -- 去掉 ? 后的参数部分
-		end
-
-		-- 解析 query 参数(key=value&key2=value2)
-		for k, v in paramStr:gmatch("([^&=?]+)=([^&=?]+)") do
-			params[k] = UrlDecode(v)
-		end
-
-		local hostInfo = split(info, "@")
-
-		-- 基础验证
-		if #hostInfo < 2 then
-			--log("Trojan节点格式错误: 缺少@符号")
-			return nil
-		end
-
-		local userinfo = hostInfo[1]
-		local hostPort = hostInfo[2]
-		
-		-- 分离服务器地址和端口
-		local hostParts = split(hostPort, ":")
-
-		-- 验证服务器地址和端口
-		if #hostParts < 2 then
-			--log("Trojan节点格式错误: 缺少端口号")
-			return nil
-		end
-
-		local server = hostParts[1]
-		local port = hostParts[2]
-
 		result.alias = UrlDecode(alias)
-		result.server = server
-		result.password = userinfo
-
-		-- 默认设置
-		-- 按照官方的建议 默认验证ssl证书
-		result.insecure = "0"
-		result.tls = "1"
-
-		-- 解析查询参数(如果存在)
-		if port:find("?") then
-			local queryParts = split(port, "?")
-			result.server_port = queryParts[1]
-
-			-- 解析查询参数
-			for _, v in pairs(split(queryParts[2], "&")) do
-				local t = split(v, "=")
-				if #t >= 2 then
-					params[t[1]] = t[2]
+
+		-- 分离和提取 password		
+		local Info = content
+		local params = {} 
+		if Info:find("@") then
+			local contents = split(Info, "@")
+			result.password = UrlDecode(contents[1])
+			local port = "443"
+			Info = (contents[2] or ""):gsub("/%?", "?")
+
+			-- 分离主机和 query 参数(key=value&key2=value2)
+			local query = split(Info, "%?")
+			local host_port = query[1]
+			for _, v in pairs(split(query[2], '&')) do
+				local t = split(v, '=')
+				if #t > 1 then
+					params[string.lower(t[1])] = UrlDecode(t[2])
 				end
 			end
 
+			-- 提取服务器地址和端口
+			if host_port:find(":") then
+				local sp = split(host_port, ":")
+				result.server_port = sp[#sp]
+				result.server = sp[1]
+			else
+				result.server = host_port
+			end
+
+			-- 默认设置
+			-- 按照官方的建议 默认验证ssl证书
+			result.insecure = "0"
+			result.tls = "1"
+
 			-- 处理参数
 			if params.alpn then
 				-- 处理 alpn 参数
 				result.tls_alpn = params.alpn
 			end
-
-			if params.sni then
+			if params.peer or params.sni then
 				-- 未指定peer(sni)默认使用remote addr
-				result.tls_host = params.sni
+				result.tls_host = params.peer or params.sni
 			end
-
 			if params.allowInsecure then
 				-- 处理 insecure 参数
-				result.insecure = params.allowInsecure
+				if params.allowinsecure == "1" or params.allowinsecure == "0" then
+					result.insecure = params.allowInsecure
+				else
+					result.insecure = string.lower(params.allowinsecure) == "true" and "1" or "0"
+				end
 			end
 			if params.tfo then
-				-- 处理 insecure 参数
+				-- 处理 fast open 参数
 				result.fast_open = params.tfo
 			end
 		else
@@ -831,8 +808,10 @@ local function processData(szType, content)
 					result.xhttp_mode = params.mode or "auto"
 					result.xhttp_path = params.path and UrlDecode(params.path) or "/"
 					-- 检查 extra 参数是否存在且非空
-					result.enable_xhttp_extra = (params.extra and params.extra ~= "") and "1" or nil
-					result.xhttp_extra = (params.extra and params.extra ~= "") and params.extra or nil
+					if params.extra and params.extra ~= "" then
+						result.enable_xhttp_extra = "1"
+						result.xhttp_extra = params.extra
+					end
 					-- 尝试解析 JSON 数据
 					local success, Data = pcall(jsonParse, params.extra or "")
 					if success and type(Data) == "table" then
@@ -908,11 +887,15 @@ local function processData(szType, content)
 		result.reality_shortid = params.sid
 		result.reality_spiderx = params.spx and UrlDecode(params.spx) or nil
 		-- 检查 ech 参数是否存在且非空
-		result.enable_ech = (params.ech and params.ech ~= "") and "1" or nil
-		result.ech_config = (params.ech and params.ech ~= "") and params.ech or nil
+		if params.ech and params.ech ~= "" then
+			result.enable_ech = "1"
+			result.ech_config = params.ech
+		end
 		-- 检查 pqv 参数是否存在且非空
-		result.enable_mldsa65verify = (params.pqv and params.pqv ~= "") and "1" or nil
-		result.reality_mldsa65verify = (params.pqv and params.pqv ~= "") and params.pqv or nil
+		if params.pqv and params.pqv ~= "" then
+			result.enable_mldsa65verify = "1"
+			result.reality_mldsa65verify = params.pqv
+		end
 		if result.transport == "ws" then
 			result.ws_host = (result.tls ~= "1") and (params.host and UrlDecode(params.host)) or nil
 			result.ws_path = params.path and UrlDecode(params.path) or "/"
@@ -924,8 +907,10 @@ local function processData(szType, content)
 			result.xhttp_mode = params.mode or "auto"
 			result.xhttp_path = params.path and UrlDecode(params.path) or "/"
 			-- 检查 extra 参数是否存在且非空
-			result.enable_xhttp_extra = (params.extra and params.extra ~= "") and "1" or nil
-			result.xhttp_extra = (params.extra and params.extra ~= "") and params.extra or nil
+			if params.extra and params.extra ~= "" then
+				result.enable_xhttp_extra = "1"
+				result.xhttp_extra = params.extra
+			end
 			-- 尝试解析 JSON 数据
 			local success, Data = pcall(jsonParse, params.extra or "")
 			if success and type(Data) == "table" then
@@ -965,64 +950,48 @@ local function processData(szType, content)
 			end
 		end
 	elseif szType == "tuic" then
-		local params = {}
-		local idx_sp = 0
-		local alias = ""
-
 		-- 提取别名(如果存在)
+		local alias = ""
 		if content:find("#") then
-			idx_sp = content:find("#")
+			local idx_sp = content:find("#")
 			alias = content:sub(idx_sp + 1, -1)
+			content = content:sub(0, idx_sp - 1)
 		end
-		local info = content:sub(1, idx_sp > 0 and idx_sp - 1 or #content):gsub("/%?", "?")
-		local paramStr = ""
-
-		if info:find("?") then
-			paramStr = info:match("%?(.*)$") or ""
-			info = info:gsub("%?.*$", "") -- 去掉 ? 后的参数部分
-		end
+		result.alias = UrlDecode(alias)
 
-		-- 解析 query 参数(key=value&key2=value2)
-		for k, v in paramStr:gmatch("([^&=?]+)=([^&=?]+)") do
-			params[k] = UrlDecode(v)
+		-- 分离和提取 uuid 和 password
+		local Info = content
+		if Info:find("@") then
+			local contents = split(Info, "@")
+			if contents[1]:find(":") then
+				local userinfo = split(contents[1], ":")
+				result.tuic_uuid = UrlDecode(userinfo[1])
+				result.tuic_passwd = UrlDecode(userinfo[2])
+			end
+			Info = (contents[2] or ""):gsub("/%?", "?")
 		end
 
-		local hostInfo = split(info, "@")
-		-- 基础验证
-		if #hostInfo < 2 then
-			log("TUIC 节点格式错误: 缺少 @")
-			return nil
+		-- 分离主机和 query 参数(key=value&key2=value2)
+		local query = split(Info, "%?")
+		local host_port = query[1]
+		local params = {}
+		for _, v in pairs(split(query[2], '&')) do
+			local t = split(v, '=')
+			if #t > 1 then
+				params[string.lower(t[1])] = UrlDecode(t[2])
+			end
 		end
 
-		local userinfo = hostInfo[1]
-		local hostPort = hostInfo[2]
-
-		-- 分离 uuid 和 password
-		local userInfoSplit = split(userinfo, ":")
-		if #userInfoSplit < 2 then
-			log("TUIC 节点格式错误: 用户信息不完整")
-			return nil
-		end
-		local uuid = userInfoSplit[1]
-		local password = userInfoSplit[2]
-	
-		-- 分离服务器地址和端口
-		local hostParts = split(hostPort, ":")
-		-- 验证服务器地址和端口
-		if #hostParts < 2 then
-			log("TUIC 节点格式错误: 缺少端口号")
-			return nil
+		-- 提取服务器地址和端口
+		if host_port:find(":") then
+			local sp = split(host_port, ":")
+			result.server_port = sp[#sp]
+			result.server = sp[1]
+		else
+			result.server = host_port
 		end
-		local server = hostParts[1]
-		local port = hostParts[2]
 
 		result.type = tuic_type
-		result.alias = UrlDecode(alias)
-		result.server = server
-		result.server_port = port
-		result.tuic_uuid = uuid
-		result.tuic_passwd = password
-
 		result.tuic_ip = params.sni or ""
 		result.udp_relay_mode = params.udp_relay_mode or "native"
 		result.congestion_control = params.congestion_control or "cubic"