mirror of
https://git.mirrors.martin98.com/https://github.com/sub-store-org/Sub-Store.git
synced 2025-08-12 15:48:59 +08:00
Various bug fixes for URI format parsing
This commit is contained in:
parent
4dde556daf
commit
e401a31b6c
6
backend/dist/sub-store-parser.loon.min.js
vendored
6
backend/dist/sub-store-parser.loon.min.js
vendored
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sub-store",
|
"name": "sub-store",
|
||||||
"version": "2.0.7",
|
"version": "2.0.8",
|
||||||
"description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and ShadowRocket.",
|
"description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and ShadowRocket.",
|
||||||
"main": "src/main.js",
|
"main": "src/main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { getIfNotBlank, isPresent, isNotBlank, getIfPresent } from '@/utils';
|
||||||
import getSurgeParser from './peggy/surge';
|
import getSurgeParser from './peggy/surge';
|
||||||
import getLoonParser from './peggy/loon';
|
import getLoonParser from './peggy/loon';
|
||||||
import getQXParser from './peggy/qx';
|
import getQXParser from './peggy/qx';
|
||||||
@ -11,14 +12,12 @@ function URI_SS() {
|
|||||||
return /^ss:\/\//.test(line);
|
return /^ss:\/\//.test(line);
|
||||||
};
|
};
|
||||||
const parse = (line) => {
|
const parse = (line) => {
|
||||||
const supported = {};
|
|
||||||
// parse url
|
// parse url
|
||||||
let content = line.split('ss://')[1];
|
let content = line.split('ss://')[1];
|
||||||
|
|
||||||
const proxy = {
|
const proxy = {
|
||||||
name: decodeURIComponent(line.split('#')[1]),
|
name: decodeURIComponent(line.split('#')[1]),
|
||||||
type: 'ss',
|
type: 'ss',
|
||||||
supported,
|
|
||||||
};
|
};
|
||||||
content = content.split('#')[0]; // strip proxy name
|
content = content.split('#')[0]; // strip proxy name
|
||||||
// handle IPV4 and IPV6
|
// handle IPV4 and IPV6
|
||||||
@ -49,21 +48,16 @@ function URI_SS() {
|
|||||||
proxy.plugin = 'obfs';
|
proxy.plugin = 'obfs';
|
||||||
proxy['plugin-opts'] = {
|
proxy['plugin-opts'] = {
|
||||||
mode: params.obfs,
|
mode: params.obfs,
|
||||||
host: params['obfs-host'],
|
host: getIfNotBlank(params['obfs-host']),
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case 'v2ray-plugin':
|
case 'v2ray-plugin':
|
||||||
proxy.supported = {
|
|
||||||
...supported,
|
|
||||||
Loon: false,
|
|
||||||
Surge: false,
|
|
||||||
};
|
|
||||||
proxy.obfs = 'v2ray-plugin';
|
proxy.obfs = 'v2ray-plugin';
|
||||||
proxy['plugin-opts'] = {
|
proxy['plugin-opts'] = {
|
||||||
mode: 'websocket',
|
mode: 'websocket',
|
||||||
host: params['obfs-host'],
|
host: getIfNotBlank(params['obfs-host']),
|
||||||
path: params.path || '',
|
path: getIfNotBlank(params.path),
|
||||||
tls: params.tls || false,
|
tls: getIfPresent(params.tls),
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -83,10 +77,6 @@ function URI_SSR() {
|
|||||||
const test = (line) => {
|
const test = (line) => {
|
||||||
return /^ssr:\/\//.test(line);
|
return /^ssr:\/\//.test(line);
|
||||||
};
|
};
|
||||||
const supported = {
|
|
||||||
Surge: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
const parse = (line) => {
|
const parse = (line) => {
|
||||||
line = Base64.decode(line.split('ssr://')[1]);
|
line = Base64.decode(line.split('ssr://')[1]);
|
||||||
|
|
||||||
@ -116,7 +106,6 @@ function URI_SSR() {
|
|||||||
cipher: params[1],
|
cipher: params[1],
|
||||||
obfs: params[2],
|
obfs: params[2],
|
||||||
password: Base64.decode(params[3]),
|
password: Base64.decode(params[3]),
|
||||||
supported,
|
|
||||||
};
|
};
|
||||||
// get other params
|
// get other params
|
||||||
const other_params = {};
|
const other_params = {};
|
||||||
@ -132,12 +121,11 @@ function URI_SSR() {
|
|||||||
name: other_params.remarks
|
name: other_params.remarks
|
||||||
? Base64.decode(other_params.remarks)
|
? Base64.decode(other_params.remarks)
|
||||||
: proxy.server,
|
: proxy.server,
|
||||||
'protocol-param': Base64.decode(
|
'protocol-param': getIfNotBlank(
|
||||||
other_params.protoparam || '',
|
Base64.decode(other_params.protoparam || '').replace(/\s/g, ''),
|
||||||
).replace(/\s/g, ''),
|
),
|
||||||
'obfs-param': Base64.decode(other_params.obfsparam || '').replace(
|
'obfs-param': getIfNotBlank(
|
||||||
/\s/g,
|
Base64.decode(other_params.obfsparam || '').replace(/\s/g, ''),
|
||||||
'',
|
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
return proxy;
|
return proxy;
|
||||||
@ -156,7 +144,6 @@ function URI_VMess() {
|
|||||||
return /^vmess:\/\//.test(line);
|
return /^vmess:\/\//.test(line);
|
||||||
};
|
};
|
||||||
const parse = (line) => {
|
const parse = (line) => {
|
||||||
const supported = {};
|
|
||||||
line = line.split('vmess://')[1];
|
line = line.split('vmess://')[1];
|
||||||
const content = Base64.decode(line);
|
const content = Base64.decode(line);
|
||||||
if (/=\s*vmess/.test(content)) {
|
if (/=\s*vmess/.test(content)) {
|
||||||
@ -176,41 +163,38 @@ function URI_VMess() {
|
|||||||
type: 'vmess',
|
type: 'vmess',
|
||||||
server: partitions[1],
|
server: partitions[1],
|
||||||
port: partitions[2],
|
port: partitions[2],
|
||||||
cipher: partitions[3],
|
cipher: getIfNotBlank(partitions[3], 'auto'),
|
||||||
uuid: partitions[4].match(/^"(.*)"$/)[1],
|
uuid: partitions[4].match(/^"(.*)"$/)[1],
|
||||||
tls: params.obfs === 'over-tls' || params.obfs === 'wss',
|
tls: params.obfs === 'wss',
|
||||||
|
udp: getIfPresent(params['udp-relay']),
|
||||||
|
tfo: getIfPresent(params['fast-open']),
|
||||||
|
'skip-cert-verify': isPresent(params['tls-verification'])
|
||||||
|
? !params['tls-verification']
|
||||||
|
: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeof params['udp-relay'] !== 'undefined')
|
|
||||||
proxy.udp = JSON.parse(params['udp-relay']);
|
|
||||||
if (typeof params['fast-open'] !== 'undefined')
|
|
||||||
proxy.udp = JSON.parse(params['fast-open']);
|
|
||||||
|
|
||||||
// handle ws headers
|
// handle ws headers
|
||||||
|
if (isPresent(params.obfs)) {
|
||||||
if (params.obfs === 'ws' || params.obfs === 'wss') {
|
if (params.obfs === 'ws' || params.obfs === 'wss') {
|
||||||
proxy.network = 'ws';
|
proxy.network = 'ws';
|
||||||
proxy['ws-opts'].path = (params['obfs-path'] || '"/"').match(
|
proxy['ws-opts'].path = (
|
||||||
/^"(.*)"$/,
|
getIfNotBlank(params['obfs-path']) || '"/"'
|
||||||
)[1];
|
).match(/^"(.*)"$/)[1];
|
||||||
let obfs_host = params['obfs-header'];
|
let obfs_host = params['obfs-header'];
|
||||||
if (obfs_host && obfs_host.indexOf('Host') !== -1) {
|
if (obfs_host && obfs_host.indexOf('Host') !== -1) {
|
||||||
obfs_host = obfs_host.match(/Host:\s*([a-zA-Z0-9-.]*)/)[1];
|
obfs_host = obfs_host.match(
|
||||||
|
/Host:\s*([a-zA-Z0-9-.]*)/,
|
||||||
|
)[1];
|
||||||
}
|
}
|
||||||
|
if (isNotBlank(obfs_host)) {
|
||||||
proxy['ws-opts'].headers = {
|
proxy['ws-opts'].headers = {
|
||||||
Host: obfs_host || proxy.server, // if no host provided, use the same as server
|
Host: obfs_host,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
// handle scert
|
throw new Error(`Unsupported obfs: ${params.obfs}`);
|
||||||
if (proxy.tls && params['"tls-verification"'] === 'false') {
|
|
||||||
proxy['skip-cert-verify'] = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle sni
|
|
||||||
if (proxy.tls && params['obfs-host']) {
|
|
||||||
proxy.sni = params['obfs-host'];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return proxy;
|
return proxy;
|
||||||
} else {
|
} else {
|
||||||
// V2rayN URI format
|
// V2rayN URI format
|
||||||
@ -222,25 +206,23 @@ function URI_VMess() {
|
|||||||
port: params.port,
|
port: params.port,
|
||||||
cipher: 'auto', // V2rayN has no default cipher! use aes-128-gcm as default.
|
cipher: 'auto', // V2rayN has no default cipher! use aes-128-gcm as default.
|
||||||
uuid: params.id,
|
uuid: params.id,
|
||||||
alterId: params.aid || 0,
|
alterId: getIfPresent(params.aid, 0),
|
||||||
tls: params.tls === 'tls' || params.tls === true,
|
tls: params.tls === 'tls' || params.tls === true,
|
||||||
supported,
|
'skip-cert-verify': isPresent(params.verify_cert)
|
||||||
|
? !params.verify_cert
|
||||||
|
: undefined,
|
||||||
};
|
};
|
||||||
// handle obfs
|
// handle obfs
|
||||||
if (params.net === 'ws') {
|
if (params.net === 'ws') {
|
||||||
proxy.network = 'ws';
|
proxy.network = 'ws';
|
||||||
proxy['ws-opts'] = {
|
proxy['ws-opts'] = {
|
||||||
path: params.path,
|
path: getIfNotBlank(params.path),
|
||||||
headers: { Host: params.host || params.add },
|
headers: { Host: getIfNotBlank(params.host) },
|
||||||
};
|
};
|
||||||
if (proxy.tls && params.host) {
|
if (proxy.tls && params.host) {
|
||||||
proxy.sni = params.host;
|
proxy.sni = params.host;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// handle scert
|
|
||||||
if (params.verify_cert === false) {
|
|
||||||
proxy['skip-cert-verify'] = true;
|
|
||||||
}
|
|
||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -255,7 +237,6 @@ function URI_Trojan() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const parse = (line) => {
|
const parse = (line) => {
|
||||||
const supported = {};
|
|
||||||
line = line.split('trojan://')[1];
|
line = line.split('trojan://')[1];
|
||||||
const [server, port] = line.split('@')[1].split('?')[0].split(':');
|
const [server, port] = line.split('@')[1].split('?')[0].split(':');
|
||||||
const name = decodeURIComponent(line.split('#')[1].trim());
|
const name = decodeURIComponent(line.split('#')[1].trim());
|
||||||
@ -278,7 +259,6 @@ function URI_Trojan() {
|
|||||||
port,
|
port,
|
||||||
password: line.split('@')[0],
|
password: line.split('@')[0],
|
||||||
sni,
|
sni,
|
||||||
supported,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
return { name, test, parse };
|
return { name, test, parse };
|
||||||
|
@ -144,9 +144,6 @@ function trojan(proxy) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// tls
|
|
||||||
appendIfPresent(`,over-tls=${proxy.tls}`, 'tls');
|
|
||||||
|
|
||||||
// tls fingerprint
|
// tls fingerprint
|
||||||
appendIfPresent(
|
appendIfPresent(
|
||||||
`,tls-cert-sha256=${proxy['tls-fingerprint']}`,
|
`,tls-cert-sha256=${proxy['tls-fingerprint']}`,
|
||||||
|
@ -25,5 +25,6 @@ export class Result {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function isPresent(obj, attr) {
|
export function isPresent(obj, attr) {
|
||||||
return typeof _.get(obj, attr) !== 'undefined';
|
const data = _.get(obj, attr);
|
||||||
|
return typeof data !== 'undefined' && data !== null;
|
||||||
}
|
}
|
||||||
|
@ -13,4 +13,20 @@ function isIPv6(ip) {
|
|||||||
return IPV6_REGEX.test(ip);
|
return IPV6_REGEX.test(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { isIPv4, isIPv6 };
|
function isNotBlank(str) {
|
||||||
|
return typeof str === 'string' && str.trim().length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getIfNotBlank(str, defaultValue) {
|
||||||
|
return isNotBlank(str) ? str : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isPresent(obj) {
|
||||||
|
return typeof obj !== 'undefined' && obj !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getIfPresent(obj, defaultValue) {
|
||||||
|
return isPresent(obj) ? obj : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { isIPv4, isIPv6, isNotBlank, getIfNotBlank, isPresent, getIfPresent };
|
||||||
|
6
backend/sub-store.min.js
vendored
6
backend/sub-store.min.js
vendored
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user