ssrurl.htm 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  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 || "80";
  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")) {
  132. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].checked = true; // 设置 flag_obfs 为 true
  133. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].dispatchEvent(event); // 触发事件
  134. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_host')[0].value = params.get("sni") || "";
  135. }
  136. if (params.get("insecure") === "1") {
  137. document.getElementsByName('cbid.shadowsocksr.' + sid + '.insecure')[0].checked = true;
  138. document.getElementsByName('cbid.shadowsocksr.' + sid + '.insecure')[0].dispatchEvent(event);
  139. if (params.get("sni")) {
  140. document.getElementsByName('cbid.shadowsocksr.' + sid + '.pinsha256')[0].value = params.get("pinsha256") || "";
  141. }
  142. }
  143. document.getElementsByName('cbid.shadowsocksr.' + sid + '.alias')[0].value = url.hash ? decodeURIComponent(url.hash.slice(1)) : "";
  144. s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
  145. return false;
  146. case "ss":
  147. var url0 = ssu[1] || "";
  148. var param = "";
  149. // 先分离 #(alias)
  150. var hashIndex = url0.indexOf("#");
  151. if (hashIndex >= 0) {
  152. param = url0.substring(hashIndex + 1);
  153. url0 = url0.substring(0, hashIndex);
  154. }
  155. // 再分离 ? 或 /?(参数)
  156. var queryIndex = (url0 = url0.replace('/?', '?')).indexOf("?");
  157. var queryStr = "";
  158. if (queryIndex >= 0) {
  159. queryStr = url0.substring(queryIndex + 1);
  160. url0 = url0.substring(0, queryIndex);
  161. }
  162. var params = Object.fromEntries(new URLSearchParams(queryStr));
  163. // 判断是否 SIP002 格式(即含 @)
  164. if (url0.indexOf("@") !== -1) {
  165. // === SIP002 格式 ===
  166. var sipIndex = url0.indexOf("@");
  167. // 先 URL 解码 base64 再解码
  168. var userInfoB64 = decodeURIComponent(url0.substring(0, sipIndex));
  169. var userInfo = b64decsafe(userInfoB64);
  170. var userInfoSplitIndex = userInfo.indexOf(":");
  171. if(userInfoSplitIndex < 0) {
  172. // 格式错误
  173. s.innerHTML = "<font style='color:red'>Userinfo format error</font>";
  174. break;
  175. }
  176. var method = userInfo.substring(0, userInfoSplitIndex);
  177. var password = userInfo.substring(userInfoSplitIndex + 1);
  178. var serverPart = url0.substring(sipIndex + 1);
  179. var serverInfo = serverPart.split(":");
  180. var server = serverInfo[0];
  181. var port = serverInfo[1];
  182. var plugin = "", pluginOpts = "";
  183. if (params.plugin) {
  184. var pluginParams = decodeURIComponent(params.plugin).split(";");
  185. plugin = pluginParams.shift();
  186. pluginOpts = pluginParams.join(";");
  187. }
  188. } else {
  189. // === Base64 SS2022 / 普通格式 的整体编码格式 ===
  190. // 先 URL 解码整个字符串
  191. var decodedUrl0 = decodeURIComponent(url0);
  192. var sstr = b64decsafe(decodedUrl0);
  193. if (!sstr) {
  194. s.innerHTML = "<font style='color:red'>Base64 sstr failed</font>";
  195. break;
  196. }
  197. // 支持 SS2022 / 普通格式
  198. var regex2022 = /^([^:]+):([^:]+):([^@]+)@([^:]+):(\d+)$/;
  199. var regexNormal = /^([^:]+):([^@]+)@([^:]+):(\d+)$/;
  200. var m2022 = sstr.match(regex2022);
  201. var mNormal = sstr.match(regexNormal);
  202. if (m2022) {
  203. var method = m2022[1];
  204. var password = m2022[2] + ":" + m2022[3];
  205. var server = m2022[4];
  206. var port = m2022[5];
  207. } else if (mNormal) {
  208. var method = mNormal[1];
  209. var password = mNormal[2];
  210. var server = mNormal[3];
  211. var port = mNormal[4];
  212. } else {
  213. s.innerHTML = "<font style='color:red'>SS URL base64 sstr format not recognized</font>";
  214. break;
  215. }
  216. var plugin = "", pluginOpts = "";
  217. if (params["shadow-tls"]) {
  218. try {
  219. var decoded_tls = JSON.parse(atob(decodeURIComponent(params["shadow-tls"])));
  220. plugin = "shadow-tls";
  221. var versionFlag = "";
  222. if (decoded_tls.version && !isNaN(decoded_tls.version)) {
  223. versionFlag = "v" + decoded_tls.version + "=1;";
  224. }
  225. pluginOpts = versionFlag + "host=" + (decoded_tls.host || "") + ";passwd=" + (decoded_tls.password || "");
  226. } catch (e) {
  227. console.log("shadow-tls decode failed:", e);
  228. }
  229. }
  230. }
  231. // 判断密码是否经过url编码
  232. const isURLEncodedPassword = function(pwd) {
  233. if (!/%[0-9A-Fa-f]{2}/.test(pwd)) return false;
  234. try {
  235. const decoded = decodeURIComponent(pwd.replace(/\+/g, "%20"));
  236. const reencoded = encodeURIComponent(decoded);
  237. return reencoded === pwd;
  238. } catch (e) {
  239. return false;
  240. }
  241. }
  242. if (isURLEncodedPassword(password)) {
  243. password = decodeURIComponent(password); // 解码URL编码
  244. } else {
  245. password = password; // 保持原始值
  246. }
  247. // === 填充配置项 ===
  248. var has_ss_type = (ss_type === "ss-rust") ? "ss-rust" : "ss-libev";
  249. document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].value = ssu[0];
  250. document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].dispatchEvent(event);
  251. document.getElementsByName('cbid.shadowsocksr.' + sid + '.has_ss_type')[0].value = has_ss_type;
  252. document.getElementsByName('cbid.shadowsocksr.' + sid + '.has_ss_type')[0].dispatchEvent(event);
  253. document.getElementsByName('cbid.shadowsocksr.' + sid + '.server')[0].value = server;
  254. document.getElementsByName('cbid.shadowsocksr.' + sid + '.server_port')[0].value = port;
  255. document.getElementsByName('cbid.shadowsocksr.' + sid + '.password')[0].value = password || "";
  256. document.getElementsByName('cbid.shadowsocksr.' + sid + '.encrypt_method_ss')[0].value = method;
  257. document.getElementsByName('cbid.shadowsocksr.' + sid + '.encrypt_method_ss')[0].dispatchEvent(event);
  258. if (plugin && plugin !== "none") {
  259. document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_plugin')[0].checked = true; // 设置 enable_plugin 为 true
  260. document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_plugin')[0].dispatchEvent(event); // 触发事件
  261. document.getElementsByName('cbid.shadowsocksr.' + sid + '.plugin')[0].value = plugin;
  262. document.getElementsByName('cbid.shadowsocksr.' + sid + '.plugin')[0].dispatchEvent(event);
  263. if (plugin !== undefined) {
  264. document.getElementsByName('cbid.shadowsocksr.' + sid + '.plugin_opts')[0].value = pluginOpts || "";
  265. }
  266. } else {
  267. document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_plugin')[0].checked = false;
  268. }
  269. if (param != undefined) {
  270. document.getElementsByName('cbid.shadowsocksr.' + sid + '.alias')[0].value = decodeURIComponent(param);
  271. }
  272. s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
  273. return false;
  274. case "ssr":
  275. var sstr = b64decsafe(ssu[1]);
  276. var ploc = sstr.indexOf("/?");
  277. document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].value = ssu[0];
  278. document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].dispatchEvent(event);
  279. var url0, param = "";
  280. if (ploc > 0) {
  281. url0 = sstr.substr(0, ploc);
  282. param = sstr.substr(ploc + 2);
  283. }
  284. var ssm = url0.match(/^(.+):([^:]+):([^:]*):([^:]+):([^:]*):([^:]+)/);
  285. if (!ssm || ssm.length < 7) return false;
  286. var pdict = {};
  287. if (param.length > 2) {
  288. var a = param.split('&');
  289. for (var i = 0; i < a.length; i++) {
  290. var b = a[i].split('=');
  291. pdict[decodeURIComponent(b[0])] = decodeURIComponent(b[1] || '');
  292. }
  293. }
  294. document.getElementsByName('cbid.shadowsocksr.' + sid + '.server')[0].value = ssm[1];
  295. document.getElementsByName('cbid.shadowsocksr.' + sid + '.server_port')[0].value = ssm[2];
  296. document.getElementsByName('cbid.shadowsocksr.' + sid + '.protocol')[0].value = ssm[3];
  297. document.getElementsByName('cbid.shadowsocksr.' + sid + '.encrypt_method')[0].value = ssm[4];
  298. document.getElementsByName('cbid.shadowsocksr.' + sid + '.obfs')[0].value = ssm[5];
  299. document.getElementsByName('cbid.shadowsocksr.' + sid + '.password')[0].value = b64decsafe(ssm[6]);
  300. document.getElementsByName('cbid.shadowsocksr.' + sid + '.obfs_param')[0].value = dictvalue(pdict, 'obfsparam');
  301. document.getElementsByName('cbid.shadowsocksr.' + sid + '.protocol_param')[0].value = dictvalue(pdict, 'protoparam');
  302. var rem = pdict['remarks'];
  303. if (typeof (rem) != 'undefined' && rem != '' && rem.length > 0) document.getElementsByName('cbid.shadowsocksr.' + sid + '.alias')[0].value = b64decutf8safe(rem);
  304. s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
  305. return false;
  306. case "trojan":
  307. try {
  308. var url = new URL("http://" + ssu[1]);
  309. var params = url.searchParams;
  310. } catch(e) {
  311. alert(e);
  312. return false;
  313. }
  314. document.getElementsByName('cbid.shadowsocksr.' + sid + '.alias')[0].value = url.hash ? decodeURIComponent(url.hash.slice(1)) : "";
  315. document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].value = "v2ray";
  316. document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].dispatchEvent(event);
  317. document.getElementsByName('cbid.shadowsocksr.' + sid + '.v2ray_protocol')[0].value = "trojan";
  318. document.getElementsByName('cbid.shadowsocksr.' + sid + '.v2ray_protocol')[0].dispatchEvent(event);
  319. document.getElementsByName('cbid.shadowsocksr.' + sid + '.server')[0].value = url.hostname;
  320. document.getElementsByName('cbid.shadowsocksr.' + sid + '.server_port')[0].value = url.port || "80";
  321. document.getElementsByName('cbid.shadowsocksr.' + sid + '.password')[0].value = decodeURIComponent(url.username);
  322. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].checked = true;
  323. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].dispatchEvent(event);
  324. document.getElementsByName('cbid.shadowsocksr.' + sid + '.fingerprint')[0].value = params.get("fp") || "";
  325. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_host')[0].value = params.get("sni");
  326. if (params.get("allowInsecure") === "1") {
  327. document.getElementsByName('cbid.shadowsocksr.' + sid + '.insecure')[0].checked = true; // 设置 insecure 为 true
  328. document.getElementsByName('cbid.shadowsocksr.' + sid + '.insecure')[0].dispatchEvent(event); // 触发事件
  329. }
  330. if (params.get("ech") && params.get("ech").trim() !== "") {
  331. document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_ech')[0].checked = true; // 设置 enable_ech 为 true
  332. document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_ech')[0].dispatchEvent(event); // 触发事件
  333. document.getElementsByName('cbid.shadowsocksr.' + sid + '.ech_config')[0].value = params.get("ech");
  334. }
  335. document.getElementsByName('cbid.shadowsocksr.' + sid + '.transport')[0].value =
  336. params.get("type") == "http" ? "h2" :
  337. (["tcp", "raw"].includes(params.get("type")) ? "raw" :
  338. (params.get("type") || "raw"));
  339. document.getElementsByName('cbid.shadowsocksr.' + sid + '.transport')[0].dispatchEvent(event);
  340. switch (params.get("type")) {
  341. case "ws":
  342. if (params.get("security") !== "tls") {
  343. setElementValue('cbid.shadowsocksr.' + sid + '.ws_host', params.get("host") ? decodeURIComponent(params.get("host")) : "");
  344. }
  345. setElementValue('cbid.shadowsocksr.' + sid + '.ws_path', params.get("path") ? decodeURIComponent(params.get("path")) : "/");
  346. break;
  347. case "httpupgrade":
  348. if (params.get("security") !== "tls") {
  349. document.getElementsByName('cbid.shadowsocksr.' + sid + '.httpupgrade_host')[0].value = params.get("host") ? decodeURIComponent(params.get("host")) : "";
  350. }
  351. document.getElementsByName('cbid.shadowsocksr.' + sid + '.httpupgrade_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : "/";
  352. break;
  353. case "splithttp":
  354. if (params.get("security") !== "tls") {
  355. document.getElementsByName('cbid.shadowsocksr.' + sid + '.splithttp_host')[0].value = params.get("host") ? decodeURIComponent(params.get("host")) : "";
  356. }
  357. document.getElementsByName('cbid.shadowsocksr.' + sid + '.splithttp_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : "/";
  358. break;
  359. case "xhttp":
  360. if (params.get("security") !== "tls") {
  361. document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_host')[0].value = params.get("host") ? decodeURIComponent(params.get("host")) : "";
  362. }
  363. document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_mode')[0].value = params.get("mode") || "auto";
  364. document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : "/";
  365. if (params.get("extra") && params.get("extra").trim() !== "") {
  366. document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra')[0].checked = true; // 设置 enable_xhttp_extra 为 true
  367. document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra')[0].dispatchEvent(event); // 触发事件
  368. document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_extra')[0].value = params.get("extra") || "";
  369. }
  370. break;
  371. case "kcp":
  372. document.getElementsByName('cbid.shadowsocksr.' + sid + '.kcp_guise')[0].value = params.get("headerType") || "none";
  373. document.getElementsByName('cbid.shadowsocksr.' + sid + '.seed')[0].value = params.get("seed") || "";
  374. break;
  375. case "http":
  376. /* this is non-standard, bullshit */
  377. case "h2":
  378. document.getElementsByName('cbid.shadowsocksr.' + sid + '.h2_host')[0].value = params.get("host") ? decodeURIComponent(params.get("host")) : "";
  379. document.getElementsByName('cbid.shadowsocksr.' + sid + '.h2_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : "";
  380. break;
  381. case "quic":
  382. document.getElementsByName('cbid.shadowsocksr.' + sid + '.quic_guise')[0].value = params.get("headerType") || "none";
  383. document.getElementsByName('cbid.shadowsocksr.' + sid + '.quic_security')[0].value = params.get("quicSecurity") || "none";
  384. document.getElementsByName('cbid.shadowsocksr.' + sid + '.quic_key')[0].value = params.get("key") || "";
  385. break;
  386. case "grpc":
  387. document.getElementsByName('cbid.shadowsocksr.' + sid + '.serviceName')[0].value = params.get("serviceName") || "";
  388. document.getElementsByName('cbid.shadowsocksr.' + sid + '.grpc_mode')[0].value = params.get("mode") || "gun";
  389. break;
  390. case "raw":
  391. case "tcp":
  392. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tcp_guise')[0].value = params.get("headerType") || "none";
  393. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tcp_guise')[0].dispatchEvent(event);
  394. if (params.get("headerType") === "http") {
  395. document.getElementsByName('cbid.shadowsocksr.' + sid + '.http_host')[0].value = params.get("host") ? decodeURIComponent(params.get("host")) : "";
  396. document.getElementsByName('cbid.shadowsocksr.' + sid + '.http_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : "";
  397. }
  398. break;
  399. }
  400. s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
  401. return false;
  402. case "vmess":
  403. var sstr = b64DecodeUnicode(ssu[1]);
  404. var ploc = sstr.indexOf("/?");
  405. document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].value = "v2ray";
  406. document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].dispatchEvent(event);
  407. document.getElementsByName('cbid.shadowsocksr.' + sid + '.v2ray_protocol')[0].value = "vmess";
  408. document.getElementsByName('cbid.shadowsocksr.' + sid + '.v2ray_protocol')[0].dispatchEvent(event);
  409. var url0, param = "";
  410. if (ploc > 0) {
  411. url0 = sstr.substr(0, ploc);
  412. param = sstr.substr(ploc + 2);
  413. }
  414. var ssm = JSON.parse(sstr);
  415. document.getElementsByName('cbid.shadowsocksr.' + sid + '.alias')[0].value = ssm.ps;
  416. document.getElementsByName('cbid.shadowsocksr.' + sid + '.server')[0].value = ssm.add;
  417. document.getElementsByName('cbid.shadowsocksr.' + sid + '.server_port')[0].value = ssm.port;
  418. document.getElementsByName('cbid.shadowsocksr.' + sid + '.alter_id')[0].value = ssm.aid;
  419. document.getElementsByName('cbid.shadowsocksr.' + sid + '.vmess_id')[0].value = ssm.id;
  420. document.getElementsByName('cbid.shadowsocksr.' + sid + '.transport')[0].value =
  421. (ssm.net === "raw" || ssm.net === "tcp") ? "raw" : ssm.net;
  422. document.getElementsByName('cbid.shadowsocksr.' + sid + '.transport')[0].dispatchEvent(event);
  423. if (ssm.net === "raw" || ssm.net === "tcp") {
  424. if (ssm.type && ssm.type != "http") {
  425. ssm.type = "none";
  426. } else {
  427. document.getElementsByName('cbid.shadowsocksr.' + sid + '.http_host')[0].value = ssm.host;
  428. document.getElementsByName('cbid.shadowsocksr.' + sid + '.http_path')[0].value = ssm.path;
  429. }
  430. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tcp_guise')[0].value = ssm.type;
  431. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tcp_guise')[0].dispatchEvent(event);
  432. }
  433. if (ssm.net == "ws") {
  434. document.getElementsByName('cbid.shadowsocksr.' + sid + '.ws_host')[0].value = ssm.host;
  435. document.getElementsByName('cbid.shadowsocksr.' + sid + '.ws_path')[0].value = ssm.path;
  436. }
  437. if (ssm.net == "httpupgrade") {
  438. document.getElementsByName('cbid.shadowsocksr.' + sid + '.httpupgrade_host')[0].value = ssm.host;
  439. document.getElementsByName('cbid.shadowsocksr.' + sid + '.httpupgrade_path')[0].value = ssm.path;
  440. }
  441. if (ssm.net == "splithttp") {
  442. document.getElementsByName('cbid.shadowsocksr.' + sid + '.splithttp_host')[0].value = ssm.host;
  443. document.getElementsByName('cbid.shadowsocksr.' + sid + '.splithttp_path')[0].value = ssm.path;
  444. }
  445. if (ssm.net == "xhttp") {
  446. document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_mode')[0].value = ssm.mode;
  447. document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_host')[0].value = ssm.host;
  448. document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_path')[0].value = ssm.path;
  449. if (ssm.extra !== "" && ssm.extra !== undefined) {
  450. document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra')[0].checked = true; // 设置 enable_xhttp_extra 为 true
  451. document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra')[0].dispatchEvent(event); // 触发事件
  452. document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_extra')[0].value = ssm.extra;
  453. }
  454. }
  455. if (ssm.net == "h2") {
  456. document.getElementsByName('cbid.shadowsocksr.' + sid + '.h2_host')[0].value = ssm.host;
  457. document.getElementsByName('cbid.shadowsocksr.' + sid + '.h2_path')[0].value = ssm.path;
  458. }
  459. if (ssm.net == "quic") {
  460. document.getElementsByName('cbid.shadowsocksr.' + sid + '.quic_security')[0].value = ssm.securty;
  461. document.getElementsByName('cbid.shadowsocksr.' + sid + '.quic_key')[0].value = ssm.key;
  462. }
  463. if (ssm.net == "kcp") {
  464. document.getElementsByName('cbid.shadowsocksr.' + sid + '.kcp_guise')[0].value = ssm.type;
  465. }
  466. if (ssm.tls == "tls") {
  467. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].checked = true;
  468. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].dispatchEvent(event);
  469. if (ssm.fq !== "" && ssm.fq !== undefined) {
  470. document.getElementsByName('cbid.shadowsocksr.' + sid + '.fingerprint')[0].value = ssm.fp;
  471. }
  472. if (ssm.net == "xhttp") {
  473. document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_alpn')[0].value = ssm.alpn;
  474. }
  475. document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_host')[0].value = ssm.sni || ssm.host;
  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. }
  482. if (ssm.mux !== undefined) {
  483. document.getElementsByName('cbid.shadowsocksr.' + sid + '.mux')[0].checked = true;
  484. document.getElementsByName('cbid.shadowsocksr.' + sid + '.mux')[0].dispatchEvent(event);
  485. }
  486. if (ssm.xmux !== undefined) {
  487. document.getElementsByName('cbid.shadowsocksr.' + sid + '.xmux')[0].checked = true;
  488. document.getElementsByName('cbid.shadowsocksr.' + sid + '.xmux')[0].dispatchEvent(event);
  489. }
  490. s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
  491. return false;
  492. case "vless":
  493. try {
  494. var url = new URL("http://" + ssu[1]);
  495. var params = url.searchParams;
  496. } catch(e) {
  497. alert(e);
  498. return false;
  499. }
  500. // Check if the elements exist before trying to modify them
  501. function setElementValue(name, value) {
  502. const element = document.getElementsByName(name)[0];
  503. if (element) {
  504. if (element.type === "checkbox" || element.type === "radio") {
  505. element.checked = value === true;
  506. } else {
  507. element.value = value;
  508. }
  509. }
  510. }
  511. function dispatchEventIfExists(name, event) {
  512. const element = document.getElementsByName(name)[0];
  513. if (element) {
  514. element.dispatchEvent(event);
  515. }
  516. }
  517. setElementValue('cbid.shadowsocksr.' + sid + '.alias', url.hash ? decodeURIComponent(url.hash.slice(1)) : "");
  518. setElementValue('cbid.shadowsocksr.' + sid + '.type', "v2ray");
  519. dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.type', event);
  520. setElementValue('cbid.shadowsocksr.' + sid + '.v2ray_protocol', "vless");
  521. dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.v2ray_protocol', event);
  522. setElementValue('cbid.shadowsocksr.' + sid + '.server', url.hostname);
  523. setElementValue('cbid.shadowsocksr.' + sid + '.server_port', url.port || "80");
  524. setElementValue('cbid.shadowsocksr.' + sid + '.vmess_id', url.username);
  525. setElementValue('cbid.shadowsocksr.' + sid + '.transport',
  526. params.get("type") === "http" ? "h2" :
  527. (["tcp", "raw"].includes(params.get("type")) ? "raw" :
  528. (params.get("type") || "tcp"))
  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. }
  542. if (params.get("security") === "reality") {
  543. setElementValue('cbid.shadowsocksr.' + sid + '.reality_publickey', params.get("pbk") ? decodeURIComponent(params.get("pbk")) : "");
  544. setElementValue('cbid.shadowsocksr.' + sid + '.reality_shortid', params.get("sid") || "");
  545. setElementValue('cbid.shadowsocksr.' + sid + '.reality_spiderx', params.get("spx") ? decodeURIComponent(params.get("spx")) : "");
  546. if (params.get("pqv") && params.get("pqv").trim() !== "") {
  547. setElementValue('cbid.shadowsocksr.' + sid + '.enable_mldsa65verify', true); // 设置 enable_mldsa65verify 为 true
  548. dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.enable_mldsa65verify', event); // 触发事件
  549. setElementValue('cbid.shadowsocksr.' + sid + '.reality_mldsa65verify', params.get("pqv") || "");
  550. }
  551. }
  552. setElementValue('cbid.shadowsocksr.' + sid + '.tls_flow', params.get("flow") || "none");
  553. dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.tls_flow', event);
  554. setElementValue('cbid.shadowsocksr.' + sid + '.xhttp_alpn', params.get("alpn") || "");
  555. setElementValue('cbid.shadowsocksr.' + sid + '.fingerprint', params.get("fp") || "");
  556. setElementValue('cbid.shadowsocksr.' + sid + '.tls_host', params.get("sni") || "");
  557. }
  558. switch (params.get("type")) {
  559. case "ws":
  560. if (params.get("security") !== "tls") {
  561. setElementValue('cbid.shadowsocksr.' + sid + '.ws_host', params.get("host") ? decodeURIComponent(params.get("host")) : "");
  562. }
  563. setElementValue('cbid.shadowsocksr.' + sid + '.ws_path', params.get("path") ? decodeURIComponent(params.get("path")) : "/");
  564. break;
  565. case "httpupgrade":
  566. if (params.get("security") !== "tls") {
  567. setElementValue('cbid.shadowsocksr.' + sid + '.httpupgrade_host', params.get("host") ? decodeURIComponent(params.get("host")) : "");
  568. }
  569. setElementValue('cbid.shadowsocksr.' + sid + '.httpupgrade_path', params.get("path") ? decodeURIComponent(params.get("path")) : "/");
  570. break;
  571. case "splithttp":
  572. if (params.get("security") !== "tls") {
  573. setElementValue('cbid.shadowsocksr.' + sid + '.splithttp_host', params.get("host") ? decodeURIComponent(params.get("host")) : "");
  574. }
  575. setElementValue('cbid.shadowsocksr.' + sid + '.splithttp_path', params.get("path") ? decodeURIComponent(params.get("path")) : "/");
  576. break;
  577. case "xhttp":
  578. if (params.get("security") !== "tls") {
  579. setElementValue('cbid.shadowsocksr.' + sid + '.xhttp_host', params.get("host") ? decodeURIComponent(params.get("host")) : "");
  580. }
  581. setElementValue('cbid.shadowsocksr.' + sid + '.xhttp_mode', params.get("mode") || "auto");
  582. setElementValue('cbid.shadowsocksr.' + sid + '.xhttp_path', params.get("path") ? decodeURIComponent(params.get("path")) : "/");
  583. if (params.get("extra") && params.get("extra").trim() !== "") {
  584. setElementValue('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra', true); // 设置 enable_xhttp_extra 为 true
  585. dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra', event); // 触发事件
  586. setElementValue('cbid.shadowsocksr.' + sid + '.xhttp_extra', params.get("extra") || "");
  587. }
  588. break;
  589. case "kcp":
  590. setElementValue('cbid.shadowsocksr.' + sid + '.kcp_guise', params.get("headerType") || "none");
  591. setElementValue('cbid.shadowsocksr.' + sid + '.seed', params.get("seed") || "");
  592. break;
  593. case "http":
  594. /* this is non-standard, bullshit */
  595. case "h2":
  596. setElementValue('cbid.shadowsocksr.' + sid + '.h2_host', params.get("host") ? decodeURIComponent(params.get("host")) : "");
  597. setElementValue('cbid.shadowsocksr.' + sid + '.h2_path', params.get("path") ? decodeURIComponent(params.get("path")) : "");
  598. break;
  599. case "quic":
  600. setElementValue('cbid.shadowsocksr.' + sid + '.quic_guise', params.get("headerType") || "none");
  601. setElementValue('cbid.shadowsocksr.' + sid + '.quic_security', params.get("quicSecurity") || "none");
  602. setElementValue('cbid.shadowsocksr.' + sid + '.quic_key', params.get("key") || "");
  603. break;
  604. case "grpc":
  605. setElementValue('cbid.shadowsocksr.' + sid + '.serviceName', params.get("serviceName") || "");
  606. setElementValue('cbid.shadowsocksr.' + sid + '.grpc_mode', params.get("mode") || "gun");
  607. break;
  608. case "tcp":
  609. case "raw":
  610. setElementValue('cbid.shadowsocksr.' + sid + '.tcp_guise', params.get("headerType") || "none");
  611. dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.tcp_guise', event);
  612. if (params.get("headerType") === "http") {
  613. setElementValue('cbid.shadowsocksr.' + sid + '.http_host', params.get("host") ? decodeURIComponent(params.get("host")) : "");
  614. setElementValue('cbid.shadowsocksr.' + sid + '.http_path', params.get("path") ? decodeURIComponent(params.get("path")) : "");
  615. }
  616. break;
  617. }
  618. s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
  619. return false;
  620. default:
  621. s.innerHTML = "<font style=\'color:red\'><%:Invalid format.%></font>";
  622. return false;
  623. }
  624. }
  625. //]]>
  626. </script>
  627. <input type="button" class="btn cbi-button cbi-button-apply" value="<%:Import%>" onclick="return import_ssr_url(this, '<%=self.option%>', '<%=self.value%>')" />
  628. <span id="<%=self.option%>-status"></span>
  629. <%+cbi/valuefooter%>