Files
op-packages/luci-app-homeproxy/root/etc/homeproxy/scripts/clash_api.uc
T

117 lines
3.0 KiB
Ucode

/*
* SPDX-License-Identifier: GPL-2.0-only
*
* HomeProxy Clash API controller 地址 helper。
*/
'use strict';
import { cursor } from 'uci';
function is_empty(value) {
return !value || value === 'nil' || (type(value) in ['array', 'object'] && length(value) === 0);
}
export function first_value(value) {
return (type(value) === 'array') ? value[0] : value;
};
export function strip_cidr(value) {
return replace(trim(first_value(value) || ''), /\/.*$/, '');
};
export function is_ipv4_address(value) {
return !!match(value || '', /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/);
};
export function is_portable_bind_host(value) {
value = lc(trim(value || ''));
return value === 'localhost' ||
value === '0.0.0.0' ||
value === '::' ||
value === '[::]' ||
value === '::1' ||
value === '[::1]' ||
!!match(value, /^127\./);
};
export function append_ipv4_address(addresses, value) {
value = strip_cidr(value);
if (is_ipv4_address(value) && index(addresses, value) === -1)
push(addresses, value);
};
export function local_ipv4_addresses(command_output) {
const netuci = cursor();
let addresses = [];
netuci.load('network');
let lan_ipaddr = netuci.get('network', 'lan', 'ipaddr');
if (type(lan_ipaddr) === 'array') {
for (let addr in lan_ipaddr)
append_ipv4_address(addresses, addr);
} else {
append_ipv4_address(addresses, lan_ipaddr);
}
const ip_addresses = (type(command_output) === 'function')
? (command_output('/sbin/ip -4 -o addr show scope global') || '')
: '';
for (let line in split(ip_addresses, /\n/)) {
let matched = match(line, /[ \t]inet[ \t]+([0-9.]+)(\/[0-9]+)?[ \t]/);
if (matched)
append_ipv4_address(addresses, matched[1]);
}
return addresses;
};
export function parse_controller(value, default_port) {
value = trim(replace(first_value(value) || '', /^https?:\/\//, ''));
value = replace(value, /\/.*$/, '');
let matched = match(value, /^\[([^\]]+)\](:([0-9]+))?$/);
if (matched)
return { host: matched[1], port: int(matched[3] || default_port) };
matched = match(value, /^([^:]+):([0-9]+)$/);
if (matched)
return { host: matched[1], port: int(matched[2]) };
return { host: value, port: int(default_port) };
};
export function format_controller(host, port) {
return sprintf((index(host, ':') >= 0) ? '[%s]:%d' : '%s:%d', host, port);
};
export function normalize_local_controller_option(uci, config, section, local_addresses, fallback_host, option, default_port, set_when_empty) {
let value = uci.get(config, section, option);
if (is_empty(value)) {
if (!set_when_empty)
return null;
let next = format_controller(fallback_host, default_port);
uci.set(config, section, option, next);
return next;
}
let controller = parse_controller(value, default_port),
host = controller.host;
if (is_empty(host))
host = fallback_host;
else if (is_portable_bind_host(host))
return null;
else if (!is_ipv4_address(host) || index(local_addresses, host) !== -1)
return null;
let next = format_controller(fallback_host, controller.port || default_port);
uci.set(config, section, option, next);
return next;
};