ssrurl.htm 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. <%+cbi/valueheader%>
  2. <%
  3. local map = self.map
  4. local ss_type = map:get("@server_subscribe[0]", "ss_type")
  5. -%>
  6. <script type="text/javascript">
  7. //<![CDATA[
  8. let ss_type = "<%=ss_type%>"
  9. function padright(str, cnt, pad) {
  10. return str + Array(cnt + 1).join(pad);
  11. }
  12. function b64EncodeUnicode(str) {
  13. return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
  14. return String.fromCharCode('0x' + p1);
  15. }));
  16. }
  17. function b64encutf8safe(str) {
  18. return b64EncodeUnicode(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, '');
  19. }
  20. function b64DecodeUnicode(str) {
  21. return decodeURIComponent(Array.prototype.map.call(atob(str), function (c) {
  22. return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
  23. }).join(''));
  24. }
  25. function b64decutf8safe(str) {
  26. var l;
  27. str = str.replace(/-/g, "+").replace(/_/g, "/");
  28. l = str.length;
  29. l = (4 - l % 4) % 4;
  30. if (l) str = padright(str, l, "=");
  31. return b64DecodeUnicode(str);
  32. }
  33. function b64encsafe(str) {
  34. return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, '')
  35. }
  36. function b64decsafe(str) {
  37. var l;
  38. str = str.replace(/-/g, "+").replace(/_/g, "/");
  39. l = str.length;
  40. l = (4 - l % 4) % 4;
  41. if (l) str = padright(str, l, "=");
  42. return atob(str);
  43. }
  44. function dictvalue(d, key) {
  45. var v = d[key];
  46. if (typeof (v) == 'undefined' || v == '') return '';
  47. return b64decsafe(v);
  48. }
  49. function export_ssr_url(btn, urlname, sid) {
  50. var s = document.getElementById(urlname + '-status');
  51. if (!s) return false;
  52. var v_server = document.getElementsByName('cbid.shadowsocksr.' + sid + '.server')[0];
  53. var v_port = document.getElementsByName('cbid.shadowsocksr.' + sid + '.server_port')[0];
  54. var v_protocol = document.getElementsByName('cbid.shadowsocksr.' + sid + '.protocol')[0];
  55. var v_method = document.getElementsByName('cbid.shadowsocksr.' + sid + '.encrypt_method')[0];
  56. var v_obfs = document.getElementsByName('cbid.shadowsocksr.' + sid + '.obfs')[0];
  57. var v_password = document.getElementsByName('cbid.shadowsocksr.' + sid + '.password')[0];
  58. var v_obfs_param = document.getElementsByName('cbid.shadowsocksr.' + sid + '.obfs_param')[0];
  59. var v_protocol_param = document.getElementsByName('cbid.shadowsocksr.' + sid + '.protocol_param')[0];
  60. var v_alias = document.getElementsByName('cbid.shadowsocksr.' + sid + '.alias')[0];
  61. var ssr_str = v_server.value + ":" + v_port.value + ":" + v_protocol.value + ":" + v_method.value + ":" + v_obfs.value + ":" + b64encsafe(v_password.value) + "/?obfsparam=" + b64encsafe(v_obfs_param.value) + "&protoparam=" + b64encsafe(v_protocol_param.value) + "&remarks=" + b64encutf8safe(v_alias.value);
  62. var textarea = document.createElement("textarea");
  63. textarea.textContent = "ssr://" + b64encsafe(ssr_str);
  64. textarea.style.position = "fixed";
  65. document.body.appendChild(textarea);
  66. textarea.select();
  67. try {
  68. document.execCommand("copy"); // Security exception may be thrown by some browsers.
  69. s.innerHTML = "<font style=\'color:green\'><%:Copy SSR to clipboard successfully.%></font>";
  70. } catch (ex) {
  71. s.innerHTML = "<font style=\'color:red\'><%:Unable to copy SSR to clipboard.%></font>";
  72. } finally {
  73. document.body.removeChild(textarea);
  74. }
  75. return false;
  76. }
  77. function import_ssr_url(btn, urlname, sid) {
  78. var s = document.getElementById(urlname + '-status');
  79. if (!s) return false;
  80. var ssrurl = prompt("<%:Paste sharing link here%>", "");
  81. if (ssrurl == null || ssrurl == "") {
  82. s.innerHTML = "<font style=\'color:red\'><%:User cancelled.%></font>";
  83. return false;
  84. }
  85. s.innerHTML = "";
  86. //var ssu = ssrurl.match(/ssr:\/\/([A-Za-z0-9_-]+)/i);
  87. var ssu = ssrurl.split('://');
  88. //console.log(ssu.length);
  89. var event = document.createEvent("HTMLEvents");
  90. event.initEvent("change", true, true);
  91. switch (ssu[0]) {
  92. case "hysteria2":
  93. case "hy2":
  94. try {
  95. var url = new URL("http://" + ssu[1]);
  96. var params = url.searchParams;
  97. } catch(e) {
  98. alert(e);
  99. return false;
  100. }
  101. document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].value = (ssu[0] === "hy2") ? "hysteria2" : ssu[0];
  102. document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].dispatchEvent(event);
  103. document.getElementsByName('cbid.shadowsocksr.' + sid + '.server')[0].value = url.hostname;
  104. document.getElementsByName('cbid.shadowsocksr.' + sid + '.server_port')[0].value = url.port || "443";
  105. if (params.get("lazy") === "1") {
  106. document.getElementsByName('cbid.shadowsocksr.' + sid + '.lazy_mode')[0].checked = true;
  107. document.getElementsByName('cbid.shadowsocksr.' + sid + '.lazy_mode')[0].dispatchEvent(event);
  108. }
  109. if (params.get("mport")) {
  110. document.getElementsByName('cbid.shadowsocksr.' + sid + '.flag_port_hopping')[0].checked = true; // 设置 flag_port_hopping 为 true
  111. document.getElementsByName('cbid.shadowsocksr.' + sid + '.flag_port_hopping')[0].dispatchEvent(event); // 触发事件
  112. document.getElementsByName('cbid.shadowsocksr.' + sid + '.port_range')[0].value = params.get("mport") || "";
  113. }
  114. if (params.get("protocol")) {
  115. document.getElementsByName('cbid.shadowsocksr.' + sid + '.flag_transport')[0].checked = true; // 设置 flag_transport 为 true
  116. document.getElementsByName('cbid.shadowsocksr.' + sid + '.flag_transport')[0].dispatchEvent(event); // 触发事件
  117. document.getElementsByName('cbid.shadowsocksr.' + sid + '.transport_protocol')[0].value = params.get("protocol") || "udp";
  118. }
  119. document.getElementsByName('cbid.shadowsocksr.' + sid + '.hy2_auth')[0].value = decodeURIComponent(url.username);
  120. document.getElementsByName('cbid.shadowsocksr.' + sid + '.hy2_auth')[0].dispatchEvent(event);
  121. document.getElementsByName('cbid.shadowsocksr.' + sid + '.uplink_capacity')[0].value =
  122. (params.get("upmbps") && params.get("upmbps").match(/\d+/)) ? params.get("upmbps").match(/\d+/)[0] : "";
  123. document.getElementsByName('cbid.shadowsocksr.' + sid + '.downlink_capacity')[0].value =
  124. (params.get("downmbps") && params.get("downmbps").match(/\d+/)) ? params.get("downmbps").match(/\d+/)[0] : "";
  125. if (params.get("obfs") && params.get("obfs") !== "none") {
  126. document.getElementsByName('cbid.shadowsocksr.' + sid + '.flag_obfs')[0].checked = true; // 设置 flag_obfs 为 true
  127. document.getElementsByName('cbid.shadowsocksr.' + sid + '.flag_obfs')[0].dispatchEvent(event); // 触发事件
  128. document.getElementsByName('cbid.shadowsocksr.' + sid + '.obfs_type')[0].value = params.get("obfs");
  129. document.getElementsByName('cbid.shadowsocksr.' + sid + '.salamander')[0].value = params.get("obfs-password") || params.get("obfs_password");
  130. }
  131. if (params.get("sni") || params.get("alpn")) {
  132. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].checked = true; // 设置 flag_obfs 为 true
  133. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].dispatchEvent(event); // 触发事件
  134. if (params.get("sni")) {
  135. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_host')[0].value = params.get("sni") || "";
  136. }
  137. if (params.get("alpn")) {
  138. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_alpn')[0].value = params.get("alpn") || "";
  139. }
  140. }
  141. if (params.get("insecure") === "1") {
  142. document.getElementsByName('cbid.shadowsocksr.' + sid + '.insecure')[0].checked = true;
  143. document.getElementsByName('cbid.shadowsocksr.' + sid + '.insecure')[0].dispatchEvent(event);
  144. }
  145. if (params.get("pinSHA256")) {
  146. document.getElementsByName('cbid.shadowsocksr.' + sid + '.pinsha256')[0].value = params.get("pinSHA256") || "";
  147. }
  148. document.getElementsByName('cbid.shadowsocksr.' + sid + '.alias')[0].value = url.hash ? decodeURIComponent(url.hash.slice(1)) : "";
  149. s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
  150. return false;
  151. case "ss":
  152. var url0 = ssu[1] || "";
  153. var param = "";
  154. // 先分离 #(alias)
  155. var hashIndex = url0.indexOf("#");
  156. if (hashIndex >= 0) {
  157. param = url0.substring(hashIndex + 1);
  158. url0 = url0.substring(0, hashIndex);
  159. }
  160. // 再分离 ? 或 /?(参数)
  161. var queryIndex = (url0 = url0.replace('/?', '?')).indexOf("?");
  162. var queryStr = "";
  163. if (queryIndex >= 0) {
  164. queryStr = url0.substring(queryIndex + 1);
  165. url0 = url0.substring(0, queryIndex);
  166. }
  167. var params = Object.fromEntries(new URLSearchParams(queryStr));
  168. // 判断是否 SIP002 格式(即含 @)
  169. if (url0.indexOf("@") !== -1) {
  170. // === SIP002 格式 ===
  171. var sipIndex = url0.indexOf("@");
  172. // 先 URL 解码 base64 再解码
  173. var userInfoB64 = decodeURIComponent(url0.substring(0, sipIndex));
  174. var userInfo = b64decsafe(userInfoB64);
  175. var userInfoSplitIndex = userInfo.indexOf(":");
  176. if(userInfoSplitIndex < 0) {
  177. // 格式错误
  178. s.innerHTML = "<font style='color:red'>Userinfo format error</font>";
  179. break;
  180. }
  181. var method = userInfo.substring(0, userInfoSplitIndex);
  182. var password = userInfo.substring(userInfoSplitIndex + 1);
  183. var serverPart = url0.substring(sipIndex + 1);
  184. var serverInfo = serverPart.split(":");
  185. var server = serverInfo[0];
  186. var port = serverInfo[1];
  187. var plugin = "", pluginOpts = "";
  188. if (params.plugin) {
  189. var pluginParams = decodeURIComponent(params.plugin).split(";");
  190. plugin = pluginParams.shift();
  191. pluginOpts = pluginParams.join(";");
  192. }
  193. } else {
  194. // === Base64 SS2022 / 普通格式 的整体编码格式 ===
  195. // 先 URL 解码整个字符串
  196. var decodedUrl0 = decodeURIComponent(url0);
  197. var sstr = b64decsafe(decodedUrl0);
  198. if (!sstr) {
  199. s.innerHTML = "<font style='color:red'>Base64 sstr failed</font>";
  200. break;
  201. }
  202. // 支持 SS2022 / 普通格式
  203. var regex2022 = /^([^:]+):([^:]+):([^@]+)@([^:]+):(\d+)$/;
  204. var regexNormal = /^([^:]+):([^@]+)@([^:]+):(\d+)$/;
  205. var m2022 = sstr.match(regex2022);
  206. var mNormal = sstr.match(regexNormal);
  207. if (m2022) {
  208. var method = m2022[1];
  209. var password = m2022[2] + ":" + m2022[3];
  210. var server = m2022[4];
  211. var port = m2022[5];
  212. } else if (mNormal) {
  213. var method = mNormal[1];
  214. var password = mNormal[2];
  215. var server = mNormal[3];
  216. var port = mNormal[4];
  217. } else {
  218. s.innerHTML = "<font style='color:red'>SS URL base64 sstr format not recognized</font>";
  219. break;
  220. }
  221. var plugin = "", pluginOpts = "";
  222. if (params["shadow-tls"]) {
  223. try {
  224. var decoded_tls = JSON.parse(atob(decodeURIComponent(params["shadow-tls"])));
  225. plugin = "shadow-tls";
  226. var versionFlag = "";
  227. if (decoded_tls.version && !isNaN(decoded_tls.version)) {
  228. versionFlag = "v" + decoded_tls.version + "=1;";
  229. }
  230. pluginOpts = versionFlag + "host=" + (decoded_tls.host || "") + ";passwd=" + (decoded_tls.password || "");
  231. } catch (e) {
  232. console.log("shadow-tls decode failed:", e);
  233. }
  234. }
  235. }
  236. // 判断密码是否经过url编码
  237. const isURLEncodedPassword = function(pwd) {
  238. if (!/%[0-9A-Fa-f]{2}/.test(pwd)) return false;
  239. try {
  240. const decoded = decodeURIComponent(pwd.replace(/\+/g, "%20"));
  241. const reencoded = encodeURIComponent(decoded);
  242. return reencoded === pwd;
  243. } catch (e) {
  244. return false;
  245. }
  246. }
  247. if (isURLEncodedPassword(password)) {
  248. password = decodeURIComponent(password); // 解码URL编码
  249. } else {
  250. password = password; // 保持原始值
  251. }
  252. // === 填充配置项 ===
  253. var has_ss_type = (ss_type === "ss-rust") ? "ss-rust" : "ss-libev";
  254. document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].value = ssu[0];
  255. document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].dispatchEvent(event);
  256. document.getElementsByName('cbid.shadowsocksr.' + sid + '.has_ss_type')[0].value = has_ss_type;
  257. document.getElementsByName('cbid.shadowsocksr.' + sid + '.has_ss_type')[0].dispatchEvent(event);
  258. document.getElementsByName('cbid.shadowsocksr.' + sid + '.server')[0].value = server;
  259. document.getElementsByName('cbid.shadowsocksr.' + sid + '.server_port')[0].value = port;
  260. document.getElementsByName('cbid.shadowsocksr.' + sid + '.password')[0].value = password || "";
  261. document.getElementsByName('cbid.shadowsocksr.' + sid + '.encrypt_method_ss')[0].value = method;
  262. document.getElementsByName('cbid.shadowsocksr.' + sid + '.encrypt_method_ss')[0].dispatchEvent(event);
  263. if (plugin && plugin !== "none") {
  264. document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_plugin')[0].checked = true; // 设置 enable_plugin 为 true
  265. document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_plugin')[0].dispatchEvent(event); // 触发事件
  266. document.getElementsByName('cbid.shadowsocksr.' + sid + '.plugin')[0].value = plugin;
  267. document.getElementsByName('cbid.shadowsocksr.' + sid + '.plugin')[0].dispatchEvent(event);
  268. if (plugin !== undefined) {
  269. document.getElementsByName('cbid.shadowsocksr.' + sid + '.plugin_opts')[0].value = pluginOpts || "";
  270. }
  271. } else {
  272. document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_plugin')[0].checked = false;
  273. }
  274. if (param != undefined) {
  275. document.getElementsByName('cbid.shadowsocksr.' + sid + '.alias')[0].value = decodeURIComponent(param);
  276. }
  277. s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
  278. return false;
  279. case "ssr":
  280. var sstr = b64decsafe((ssu[1] || "").replace(/#.*/, "").trim());
  281. var ploc = sstr.indexOf("/?");
  282. document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].value = ssu[0];
  283. document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].dispatchEvent(event);
  284. var url0, param = "";
  285. if (ploc > 0) {
  286. url0 = sstr.substr(0, ploc);
  287. param = sstr.substr(ploc + 2);
  288. }
  289. var ssm = url0.match(/^(.+):([^:]+):([^:]*):([^:]+):([^:]*):([^:]+)/);
  290. if (!ssm || ssm.length < 7) return false;
  291. var pdict = {};
  292. if (param.length > 2) {
  293. var a = param.split('&');
  294. for (var i = 0; i < a.length; i++) {
  295. var b = a[i].split('=');
  296. pdict[decodeURIComponent(b[0])] = decodeURIComponent(b[1] || '');
  297. }
  298. }
  299. document.getElementsByName('cbid.shadowsocksr.' + sid + '.server')[0].value = ssm[1];
  300. document.getElementsByName('cbid.shadowsocksr.' + sid + '.server_port')[0].value = ssm[2];
  301. document.getElementsByName('cbid.shadowsocksr.' + sid + '.protocol')[0].value = ssm[3];
  302. document.getElementsByName('cbid.shadowsocksr.' + sid + '.encrypt_method')[0].value = ssm[4];
  303. document.getElementsByName('cbid.shadowsocksr.' + sid + '.obfs')[0].value = ssm[5];
  304. document.getElementsByName('cbid.shadowsocksr.' + sid + '.password')[0].value = b64decsafe(ssm[6]);
  305. document.getElementsByName('cbid.shadowsocksr.' + sid + '.obfs_param')[0].value = dictvalue(pdict, 'obfsparam');
  306. document.getElementsByName('cbid.shadowsocksr.' + sid + '.protocol_param')[0].value = dictvalue(pdict, 'protoparam');
  307. var rem = pdict['remarks'];
  308. if (typeof (rem) != 'undefined' && rem != '' && rem.length > 0) document.getElementsByName('cbid.shadowsocksr.' + sid + '.alias')[0].value = b64decutf8safe(rem);
  309. s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
  310. return false;
  311. case "trojan":
  312. try {
  313. var url = new URL("http://" + ssu[1]);
  314. var params = url.searchParams;
  315. } catch(e) {
  316. alert(e);
  317. return false;
  318. }
  319. document.getElementsByName('cbid.shadowsocksr.' + sid + '.alias')[0].value = url.hash ? decodeURIComponent(url.hash.slice(1)) : "";
  320. document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].value = "v2ray";
  321. document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].dispatchEvent(event);
  322. document.getElementsByName('cbid.shadowsocksr.' + sid + '.v2ray_protocol')[0].value = "trojan";
  323. document.getElementsByName('cbid.shadowsocksr.' + sid + '.v2ray_protocol')[0].dispatchEvent(event);
  324. document.getElementsByName('cbid.shadowsocksr.' + sid + '.server')[0].value = url.hostname;
  325. document.getElementsByName('cbid.shadowsocksr.' + sid + '.server_port')[0].value = url.port || "80";
  326. document.getElementsByName('cbid.shadowsocksr.' + sid + '.password')[0].value = decodeURIComponent(url.username);
  327. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].checked = true;
  328. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].dispatchEvent(event);
  329. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_host')[0].value = params.get("sni");
  330. if (params.get("allowInsecure") === "1") {
  331. document.getElementsByName('cbid.shadowsocksr.' + sid + '.insecure')[0].checked = true; // 设置 insecure 为 true
  332. document.getElementsByName('cbid.shadowsocksr.' + sid + '.insecure')[0].dispatchEvent(event); // 触发事件
  333. }
  334. if (params.get("ech") && params.get("ech").trim() !== "") {
  335. document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_ech')[0].checked = true; // 设置 enable_ech 为 true
  336. document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_ech')[0].dispatchEvent(event); // 触发事件
  337. document.getElementsByName('cbid.shadowsocksr.' + sid + '.ech_config')[0].value = params.get("ech");
  338. }
  339. document.getElementsByName('cbid.shadowsocksr.' + sid + '.transport')[0].value =
  340. params.get("type") == "http" ? "h2" :
  341. (["xhttp", "splithttp"].includes(params.get("type")) ? "xhttp" :
  342. (["tcp", "raw"].includes(params.get("type")) ? "raw" :
  343. (params.get("type") || "raw")));
  344. document.getElementsByName('cbid.shadowsocksr.' + sid + '.transport')[0].dispatchEvent(event);
  345. if (params.get("security") === "tls") {
  346. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_alpn')[0].value = params.get("alpn") || "";
  347. document.getElementsByName('cbid.shadowsocksr.' + sid + '.fingerprint')[0].value = params.get("fp") || "";
  348. }
  349. switch (params.get("type")) {
  350. case "ws":
  351. if (params.get("security") !== "tls") {
  352. document.getElementsByName('cbid.shadowsocksr.' + sid + '.ws_host')[0].value = params.get("host") ? decodeURIComponent(params.get("host")) : "";
  353. }
  354. document.getElementsByName('cbid.shadowsocksr.' + sid + '.ws_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : "/";
  355. break;
  356. case "httpupgrade":
  357. if (params.get("security") !== "tls") {
  358. document.getElementsByName('cbid.shadowsocksr.' + sid + '.httpupgrade_host')[0].value = params.get("host") ? decodeURIComponent(params.get("host")) : "";
  359. }
  360. document.getElementsByName('cbid.shadowsocksr.' + sid + '.httpupgrade_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : "/";
  361. break;
  362. case "xhttp":
  363. case "splithttp":
  364. document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_host')[0].value = params.get("host") ? decodeURIComponent(params.get("host")) : "";
  365. document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_mode')[0].value = params.get("mode") || "auto";
  366. document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : "/";
  367. if (params.get("extra") && params.get("extra").trim() !== "") {
  368. document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra')[0].checked = true; // 设置 enable_xhttp_extra 为 true
  369. document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra')[0].dispatchEvent(event); // 触发事件
  370. document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_extra')[0].value = params.get("extra") || "";
  371. }
  372. break;
  373. case "kcp":
  374. document.getElementsByName('cbid.shadowsocksr.' + sid + '.kcp_guise')[0].value = params.get("headerType") || "none";
  375. document.getElementsByName('cbid.shadowsocksr.' + sid + '.seed')[0].value = params.get("seed") || "";
  376. break;
  377. case "http":
  378. /* this is non-standard, bullshit */
  379. case "h2":
  380. document.getElementsByName('cbid.shadowsocksr.' + sid + '.h2_host')[0].value = params.get("host") ? decodeURIComponent(params.get("host")) : "";
  381. document.getElementsByName('cbid.shadowsocksr.' + sid + '.h2_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : "";
  382. break;
  383. case "quic":
  384. document.getElementsByName('cbid.shadowsocksr.' + sid + '.quic_guise')[0].value = params.get("headerType") || "none";
  385. document.getElementsByName('cbid.shadowsocksr.' + sid + '.quic_security')[0].value = params.get("quicSecurity") || "none";
  386. document.getElementsByName('cbid.shadowsocksr.' + sid + '.quic_key')[0].value = params.get("key") || "";
  387. break;
  388. case "grpc":
  389. document.getElementsByName('cbid.shadowsocksr.' + sid + '.serviceName')[0].value = params.get("serviceName") || "";
  390. document.getElementsByName('cbid.shadowsocksr.' + sid + '.grpc_mode')[0].value = params.get("mode") || "gun";
  391. break;
  392. case "raw":
  393. case "tcp":
  394. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tcp_guise')[0].value = params.get("headerType") || "none";
  395. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tcp_guise')[0].dispatchEvent(event);
  396. if (params.get("headerType") === "http") {
  397. document.getElementsByName('cbid.shadowsocksr.' + sid + '.http_host')[0].value = params.get("host") ? decodeURIComponent(params.get("host")) : "";
  398. document.getElementsByName('cbid.shadowsocksr.' + sid + '.http_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : "";
  399. }
  400. break;
  401. }
  402. s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
  403. return false;
  404. case "vmess":
  405. var sstr = b64DecodeUnicode((ssu[1] || "").replace(/#.*/, "").trim());
  406. var ploc = sstr.indexOf("/?");
  407. document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].value = "v2ray";
  408. document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].dispatchEvent(event);
  409. document.getElementsByName('cbid.shadowsocksr.' + sid + '.v2ray_protocol')[0].value = "vmess";
  410. document.getElementsByName('cbid.shadowsocksr.' + sid + '.v2ray_protocol')[0].dispatchEvent(event);
  411. var url0, param = "";
  412. if (ploc > 0) {
  413. url0 = sstr.substr(0, ploc);
  414. param = sstr.substr(ploc + 2);
  415. }
  416. var ssm = JSON.parse(sstr);
  417. document.getElementsByName('cbid.shadowsocksr.' + sid + '.alias')[0].value = ssm.ps;
  418. document.getElementsByName('cbid.shadowsocksr.' + sid + '.server')[0].value = ssm.add;
  419. document.getElementsByName('cbid.shadowsocksr.' + sid + '.server_port')[0].value = ssm.port;
  420. document.getElementsByName('cbid.shadowsocksr.' + sid + '.alter_id')[0].value = ssm.aid;
  421. document.getElementsByName('cbid.shadowsocksr.' + sid + '.vmess_id')[0].value = ssm.id;
  422. document.getElementsByName('cbid.shadowsocksr.' + sid + '.transport')[0].value =
  423. (["xhttp", "splithttp"].includes(ssm.net) ? "xhttp" :
  424. (["tcp", "raw"].includes(ssm.net) ? "raw" :
  425. (ssm.net || "raw")));
  426. document.getElementsByName('cbid.shadowsocksr.' + sid + '.transport')[0].dispatchEvent(event);
  427. if (ssm.net === "raw" || ssm.net === "tcp") {
  428. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tcp_guise')[0].value = ssm.type;
  429. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tcp_guise')[0].dispatchEvent(event);
  430. if (ssm.type === "http") {
  431. document.getElementsByName('cbid.shadowsocksr.' + sid + '.http_host')[0].value = ssm.host;
  432. document.getElementsByName('cbid.shadowsocksr.' + sid + '.http_path')[0].value = ssm.path;
  433. }
  434. }
  435. if (ssm.net == "ws") {
  436. document.getElementsByName('cbid.shadowsocksr.' + sid + '.ws_host')[0].value = ssm.host;
  437. document.getElementsByName('cbid.shadowsocksr.' + sid + '.ws_path')[0].value = ssm.path;
  438. }
  439. if (ssm.net == "httpupgrade") {
  440. document.getElementsByName('cbid.shadowsocksr.' + sid + '.httpupgrade_host')[0].value = ssm.host;
  441. document.getElementsByName('cbid.shadowsocksr.' + sid + '.httpupgrade_path')[0].value = ssm.path;
  442. }
  443. if (ssm.net == "xhttp" || ssm.net == "splithttp") {
  444. document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_mode')[0].value = ssm.mode || "auto";
  445. document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_host')[0].value = ssm.host;
  446. document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_path')[0].value = ssm.path;
  447. if (ssm.extra !== "" && ssm.extra !== undefined) {
  448. document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra')[0].checked = true; // 设置 enable_xhttp_extra 为 true
  449. document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra')[0].dispatchEvent(event); // 触发事件
  450. document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_extra')[0].value = ssm.extra;
  451. }
  452. }
  453. if (ssm.net == "h2") {
  454. document.getElementsByName('cbid.shadowsocksr.' + sid + '.h2_host')[0].value = ssm.host;
  455. document.getElementsByName('cbid.shadowsocksr.' + sid + '.h2_path')[0].value = ssm.path;
  456. }
  457. if (ssm.net == "quic") {
  458. document.getElementsByName('cbid.shadowsocksr.' + sid + '.quic_security')[0].value = ssm.securty;
  459. document.getElementsByName('cbid.shadowsocksr.' + sid + '.quic_key')[0].value = ssm.key;
  460. }
  461. if (ssm.net == "kcp") {
  462. document.getElementsByName('cbid.shadowsocksr.' + sid + '.kcp_guise')[0].value = ssm.type;
  463. }
  464. if (ssm.tls == "tls") {
  465. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].checked = true;
  466. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].dispatchEvent(event);
  467. if (ssm.fp !== "" && ssm.fp !== undefined) {
  468. document.getElementsByName('cbid.shadowsocksr.' + sid + '.fingerprint')[0].value = ssm.fp;
  469. }
  470. if (ssm.alpn !== "" && ssm.alpn !== undefined) {
  471. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_alpn')[0].value = ssm.alpn;
  472. }
  473. if (ssm.host !== "" && ssm.host !== undefined) {
  474. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_host')[0].value = ssm.sni || ssm.host;
  475. }
  476. if (ssm.ech !== "" && ssm.ech !== undefined) {
  477. document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_ech')[0].checked = true; // 设置 enable_ech 为 true
  478. document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_ech')[0].dispatchEvent(event); // 触发事件
  479. document.getElementsByName('cbid.shadowsocksr.' + sid + '.ech_config')[0].value = ssm.ech;
  480. }
  481. document.getElementsByName('cbid.shadowsocksr.' + sid + '.insecure')[0].checked =
  482. !!(ssm.allowInsecure ?? ssm.allowlnsecure ?? ssm['skip-cert-verify']); // 设置 insecure 为 true
  483. document.getElementsByName('cbid.shadowsocksr.' + sid + '.insecure')[0].dispatchEvent(event); // 触发事件
  484. }
  485. if (ssm.mux !== undefined) {
  486. document.getElementsByName('cbid.shadowsocksr.' + sid + '.mux')[0].checked = true;
  487. document.getElementsByName('cbid.shadowsocksr.' + sid + '.mux')[0].dispatchEvent(event);
  488. }
  489. s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
  490. return false;
  491. case "vless":
  492. try {
  493. var url = new URL("http://" + ssu[1]);
  494. var params = url.searchParams;
  495. } catch(e) {
  496. alert(e);
  497. return false;
  498. }
  499. // Check if the elements exist before trying to modify them
  500. function setElementValue(name, value) {
  501. const element = document.getElementsByName(name)[0];
  502. if (element) {
  503. if (element.type === "checkbox" || element.type === "radio") {
  504. element.checked = value === true;
  505. } else {
  506. element.value = value;
  507. }
  508. }
  509. }
  510. function dispatchEventIfExists(name, event) {
  511. const element = document.getElementsByName(name)[0];
  512. if (element) {
  513. element.dispatchEvent(event);
  514. }
  515. }
  516. setElementValue('cbid.shadowsocksr.' + sid + '.alias', url.hash ? decodeURIComponent(url.hash.slice(1)) : "");
  517. setElementValue('cbid.shadowsocksr.' + sid + '.type', "v2ray");
  518. dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.type', event);
  519. setElementValue('cbid.shadowsocksr.' + sid + '.v2ray_protocol', "vless");
  520. dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.v2ray_protocol', event);
  521. setElementValue('cbid.shadowsocksr.' + sid + '.server', url.hostname);
  522. setElementValue('cbid.shadowsocksr.' + sid + '.server_port', url.port || "80");
  523. setElementValue('cbid.shadowsocksr.' + sid + '.vmess_id', url.username);
  524. setElementValue('cbid.shadowsocksr.' + sid + '.transport',
  525. params.get("type") === "http" ? "h2" :
  526. (["xhttp", "splithttp"].includes(params.get("type")) ? "xhttp" :
  527. (["tcp", "raw"].includes(params.get("type")) ? "raw" :
  528. (params.get("type") || "raw")))
  529. );
  530. dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.transport', event);
  531. setElementValue('cbid.shadowsocksr.' + sid + '.vless_encryption', params.get("encryption") || "none");
  532. if ([ "tls", "xtls", "reality" ].includes(params.get("security"))) {
  533. setElementValue('cbid.shadowsocksr.' + sid + '.' + params.get("security"), true);
  534. dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.' + params.get("security"), event);
  535. if (params.get("security") === "tls") {
  536. if (params.get("ech") && params.get("ech").trim() !== "") {
  537. setElementValue('cbid.shadowsocksr.' + sid + '.enable_ech', true); // 设置 enable_ech 为 true
  538. dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.enable_ech', event); // 触发事件
  539. setElementValue('cbid.shadowsocksr.' + sid + '.ech_config', params.get("ech") || "");
  540. }
  541. if (params.get("allowInsecure") === "1") {
  542. setElementValue('cbid.shadowsocksr.' + sid + '.insecure', true); // 设置 insecure 为 true
  543. dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.insecure', event); // 触发事件
  544. }
  545. }
  546. if (params.get("security") === "reality") {
  547. setElementValue('cbid.shadowsocksr.' + sid + '.reality_publickey', params.get("pbk") ? decodeURIComponent(params.get("pbk")) : "");
  548. setElementValue('cbid.shadowsocksr.' + sid + '.reality_shortid', params.get("sid") || "");
  549. setElementValue('cbid.shadowsocksr.' + sid + '.reality_spiderx', params.get("spx") ? decodeURIComponent(params.get("spx")) : "");
  550. if (params.get("pqv") && params.get("pqv").trim() !== "") {
  551. setElementValue('cbid.shadowsocksr.' + sid + '.enable_mldsa65verify', true); // 设置 enable_mldsa65verify 为 true
  552. dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.enable_mldsa65verify', event); // 触发事件
  553. setElementValue('cbid.shadowsocksr.' + sid + '.reality_mldsa65verify', params.get("pqv") || "");
  554. }
  555. }
  556. setElementValue('cbid.shadowsocksr.' + sid + '.tls_flow', params.get("flow") || "none");
  557. dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.tls_flow', event);
  558. setElementValue('cbid.shadowsocksr.' + sid + '.tls_alpn', params.get("alpn") || "");
  559. setElementValue('cbid.shadowsocksr.' + sid + '.fingerprint', params.get("fp") || "");
  560. setElementValue('cbid.shadowsocksr.' + sid + '.tls_host', params.get("sni") || "");
  561. }
  562. switch (params.get("type")) {
  563. case "ws":
  564. if (params.get("security") !== "tls") {
  565. setElementValue('cbid.shadowsocksr.' + sid + '.ws_host', params.get("host") ? decodeURIComponent(params.get("host")) : "");
  566. }
  567. setElementValue('cbid.shadowsocksr.' + sid + '.ws_path', params.get("path") ? decodeURIComponent(params.get("path")) : "/");
  568. break;
  569. case "httpupgrade":
  570. if (params.get("security") !== "tls") {
  571. setElementValue('cbid.shadowsocksr.' + sid + '.httpupgrade_host', params.get("host") ? decodeURIComponent(params.get("host")) : "");
  572. }
  573. setElementValue('cbid.shadowsocksr.' + sid + '.httpupgrade_path', params.get("path") ? decodeURIComponent(params.get("path")) : "/");
  574. break;
  575. case "xhttp":
  576. case "splithttp":
  577. if (params.get("security") !== "tls") {
  578. setElementValue('cbid.shadowsocksr.' + sid + '.xhttp_host', params.get("host") ? decodeURIComponent(params.get("host")) : "");
  579. }
  580. setElementValue('cbid.shadowsocksr.' + sid + '.xhttp_mode', params.get("mode") || "auto");
  581. setElementValue('cbid.shadowsocksr.' + sid + '.xhttp_path', params.get("path") ? decodeURIComponent(params.get("path")) : "/");
  582. if (params.get("extra") && params.get("extra").trim() !== "") {
  583. setElementValue('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra', true); // 设置 enable_xhttp_extra 为 true
  584. dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra', event); // 触发事件
  585. setElementValue('cbid.shadowsocksr.' + sid + '.xhttp_extra', params.get("extra") || "");
  586. }
  587. break;
  588. case "kcp":
  589. setElementValue('cbid.shadowsocksr.' + sid + '.kcp_guise', params.get("headerType") || "none");
  590. setElementValue('cbid.shadowsocksr.' + sid + '.seed', params.get("seed") || "");
  591. break;
  592. case "http":
  593. /* this is non-standard, bullshit */
  594. case "h2":
  595. setElementValue('cbid.shadowsocksr.' + sid + '.h2_host', params.get("host") ? decodeURIComponent(params.get("host")) : "");
  596. setElementValue('cbid.shadowsocksr.' + sid + '.h2_path', params.get("path") ? decodeURIComponent(params.get("path")) : "");
  597. break;
  598. case "quic":
  599. setElementValue('cbid.shadowsocksr.' + sid + '.quic_guise', params.get("headerType") || "none");
  600. setElementValue('cbid.shadowsocksr.' + sid + '.quic_security', params.get("quicSecurity") || "none");
  601. setElementValue('cbid.shadowsocksr.' + sid + '.quic_key', params.get("key") || "");
  602. break;
  603. case "grpc":
  604. setElementValue('cbid.shadowsocksr.' + sid + '.serviceName', params.get("serviceName") || "");
  605. setElementValue('cbid.shadowsocksr.' + sid + '.grpc_mode', params.get("mode") || "gun");
  606. break;
  607. case "tcp":
  608. case "raw":
  609. setElementValue('cbid.shadowsocksr.' + sid + '.tcp_guise', params.get("headerType") || "none");
  610. dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.tcp_guise', event);
  611. if (params.get("headerType") === "http") {
  612. setElementValue('cbid.shadowsocksr.' + sid + '.http_host', params.get("host") ? decodeURIComponent(params.get("host")) : "");
  613. setElementValue('cbid.shadowsocksr.' + sid + '.http_path', params.get("path") ? decodeURIComponent(params.get("path")) : "");
  614. }
  615. break;
  616. }
  617. s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
  618. return false;
  619. default:
  620. s.innerHTML = "<font style=\'color:red\'><%:Invalid format.%></font>";
  621. return false;
  622. }
  623. }
  624. //]]>
  625. </script>
  626. <input type="button" class="btn cbi-button cbi-button-apply" value="<%:Import%>" onclick="return import_ssr_url(this, '<%=self.option%>', '<%=self.value%>')" />
  627. <span id="<%=self.option%>-status"></span>
  628. <%+cbi/valuefooter%>