package lienol: merge upstream source
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2018-2019 Lienol
|
||||
# Copyright (C) 2018-2020 Lienol <lawlienol@gmail.com>
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall
|
||||
PKG_VERSION:=3.0
|
||||
PKG_RELEASE:=127-20191214
|
||||
PKG_RELEASE:=135-20191220
|
||||
|
||||
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
|
||||
PO2LMO:=./po2lmo
|
||||
@ -67,11 +67,7 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_pdnsd
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_dns2socks
|
||||
bool "Include dns2socks"
|
||||
default n
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_dns-forwarder
|
||||
bool "Include dns-forwarder"
|
||||
default n
|
||||
default y
|
||||
|
||||
endmenu
|
||||
endef
|
||||
@ -95,8 +91,7 @@ define Package/$(PKG_NAME)
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_haproxy:haproxy \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_ChinaDNS:openwrt_chinadns \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_pdnsd:pdnsd-alt \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_dns2socks:dns2socks \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_dns-forwarder:dns-forwarder
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_dns2socks:dns2socks
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
|
||||
@ -1 +0,0 @@
|
||||
本人十分喜欢lean源码,但本插件并非魔改版SSR Plus,不喜欢勿用!!!
|
||||
@ -1,4 +1,4 @@
|
||||
-- Copyright 2018-2019 Lienol <lawlienol@gmail.com>
|
||||
-- Copyright 2018-2020 Lienol <lawlienol@gmail.com>
|
||||
module("luci.controller.passwall", package.seeall)
|
||||
local appname = "passwall"
|
||||
local http = require "luci.http"
|
||||
@ -52,6 +52,8 @@ function index()
|
||||
true
|
||||
entry({"admin", "vpn", "passwall", "auto_ping_node"}, call("auto_ping_node")).leaf =
|
||||
true
|
||||
entry({"admin", "vpn", "passwall", "auto_ping_node_list"},
|
||||
call("auto_ping_node_list")).leaf = true
|
||||
entry({"admin", "vpn", "passwall", "ping_node"}, call("ping_node")).leaf =
|
||||
true
|
||||
entry({"admin", "vpn", "passwall", "set_node"}, call("set_node")).leaf =
|
||||
@ -188,7 +190,7 @@ function auto_ping_node()
|
||||
appname) == "1" and
|
||||
luci.sys.exec("echo -n `command -v tcping`") ~= "" then
|
||||
e.ping = luci.sys.exec(
|
||||
"echo -n `tcping -q -c 1 -i 3 -p " .. port .. " " ..
|
||||
"echo -n `tcping -q -c 1 -i 1 -p " .. port .. " " ..
|
||||
address ..
|
||||
" 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print$2}'`")
|
||||
else
|
||||
@ -200,6 +202,33 @@ function auto_ping_node()
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
|
||||
function auto_ping_node_list()
|
||||
local e = {}
|
||||
local json_str = luci.http.formvalue("json")
|
||||
local json = luci.jsonc.parse(json_str)
|
||||
local index = json["index"]
|
||||
local address = json["address"]
|
||||
local port = json["port"]
|
||||
|
||||
local obj = {}
|
||||
obj.index = index
|
||||
if luci.sys.exec("echo -n `uci -q get %s.@global_other[0].use_tcping`" %
|
||||
appname) == "1" and
|
||||
luci.sys.exec("echo -n `command -v tcping`") ~= "" then
|
||||
obj.ping = luci.sys.exec("echo -n `tcping -q -c 1 -i 1 -p " .. port ..
|
||||
" " .. address ..
|
||||
" 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print$2}'`")
|
||||
else
|
||||
obj.ping = luci.sys.exec(
|
||||
"echo -n `ping -c 1 -W 1 %q 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print$2}'`" %
|
||||
address)
|
||||
end
|
||||
e = obj
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
|
||||
function ping_node()
|
||||
local e = {}
|
||||
local address = luci.http.formvalue("address")
|
||||
@ -208,7 +237,7 @@ function ping_node()
|
||||
appname) == "1" and
|
||||
luci.sys.exec("echo -n `command -v tcping`") ~= "" then
|
||||
e.ping = luci.sys.exec(
|
||||
"echo -n `tcping -q -c 1 -i 3 -p " .. port .. " " ..
|
||||
"echo -n `tcping -q -c 1 -i 1 -p " .. port .. " " ..
|
||||
address ..
|
||||
" 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print$2}'`")
|
||||
else
|
||||
@ -221,26 +250,14 @@ function ping_node()
|
||||
end
|
||||
|
||||
function set_node()
|
||||
local e = {}
|
||||
local protocol = luci.http.formvalue("protocol")
|
||||
local number = luci.http.formvalue("number")
|
||||
local section = luci.http.formvalue("section")
|
||||
if protocol == "tcp" then
|
||||
luci.sys.call("uci set passwall.@global[0].tcp_node" .. number .. "=" ..
|
||||
section ..
|
||||
" && uci commit passwall && /etc/init.d/passwall restart")
|
||||
elseif protocol == "udp" then
|
||||
luci.sys.call("uci set passwall.@global[0].udp_node" .. number .. "=" ..
|
||||
section ..
|
||||
" && uci commit passwall && /etc/init.d/passwall restart")
|
||||
elseif protocol == "socks5" then
|
||||
luci.sys.call(
|
||||
"uci set passwall.@global[0].socks5_node" .. number .. "=" ..
|
||||
section ..
|
||||
" && uci commit passwall && /etc/init.d/passwall restart")
|
||||
end
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(e)
|
||||
luci.sys.call("uci set passwall.@global[0]." .. protocol .. "_node" ..
|
||||
number .. "=" .. section ..
|
||||
" && uci commit passwall && /etc/init.d/passwall restart > /dev/null 2>&1 &")
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall",
|
||||
"log"))
|
||||
end
|
||||
|
||||
function copy_node()
|
||||
|
||||
@ -90,8 +90,8 @@ for i = 1, socks5_node_num, 1 do
|
||||
end
|
||||
|
||||
---- DNS Forward Mode
|
||||
o = s:option(ListValue, "dns_mode", translate("DNS Forward Mode"),
|
||||
translate("if you use no patterns are used, DNS of wan will be used by default as upstream of dnsmasq"))
|
||||
o = s:option(ListValue, "dns_mode", translate("DNS Forward Mode"), translate(
|
||||
"if you use no patterns are used, DNS of wan will be used by default as upstream of dnsmasq"))
|
||||
o.rmempty = false
|
||||
o:reset_values()
|
||||
if is_installed("openwrt_chinadns") or is_finded("chinadns") then
|
||||
@ -100,27 +100,26 @@ end
|
||||
if is_installed("dns2socks") or is_finded("dns2socks") then
|
||||
o:value("dns2socks", "dns2socks " .. translate("Need Socks5 server"))
|
||||
end
|
||||
if is_installed("pcap-dnsproxy") or is_finded("Pcap_DNSProxy") then
|
||||
o:value("Pcap_DNSProxy", "Pcap_DNSProxy")
|
||||
end
|
||||
if is_installed("pdnsd") or is_installed("pdnsd-alt") or is_finded("pdnsd") then
|
||||
o:value("pdnsd", "pdnsd")
|
||||
end
|
||||
o:value("local_7913", translate("Use local port 7913 as DNS"))
|
||||
o:value("nonuse", translate("No patterns are used"))
|
||||
|
||||
o = s:option(Value, "dns2socks_forward", translate("DNS Forward Address"))
|
||||
o.default = "8.8.4.4"
|
||||
o:value("8.8.4.4", "8.8.4.4(Google DNS1)")
|
||||
o:value("8.8.8.8", "8.8.8.8(Google DNS2)")
|
||||
o:value("208.67.222.222", "208.67.222.222(OpenDNS DNS1)")
|
||||
o:value("208.67.220.220", "208.67.220.220(OpenDNS DNS2)")
|
||||
o:depends("dns_mode", "dns2socks")
|
||||
|
||||
---- upstreamm DNS Server for ChinaDNS
|
||||
o = s:option(ListValue, "up_chinadns_mode",
|
||||
translate("upstreamm DNS Server for ChinaDNS"), translate(
|
||||
"Domestic DNS server 1 in advanced Settings is used as domestic DNS by default"))
|
||||
o.default = "OpenDNS_1"
|
||||
o:depends("dns_mode", "chinadns")
|
||||
if is_installed("dnsproxy") or is_finded("dnsproxy") then
|
||||
o:value("dnsproxy", "dnsproxy")
|
||||
end
|
||||
if is_installed("dns-forwarder") or is_finded("dns-forwarder") then
|
||||
o:value("dns-forwarder", "dns-forwarder")
|
||||
end
|
||||
o:value("OpenDNS_1", "OpenDNS_1")
|
||||
o:value("OpenDNS_2", "OpenDNS_2")
|
||||
o:value("custom", translate("custom"))
|
||||
|
||||
@ -19,7 +19,11 @@ o.default = 1
|
||||
---- Auto Ping
|
||||
o = s:option(Flag, "auto_ping", translate("Auto Ping"),
|
||||
translate("This will automatically ping the node for latency"))
|
||||
o.default = 0
|
||||
o.default = 1
|
||||
|
||||
---- Concise display nodes
|
||||
o = s:option(Flag, "compact_display_nodes", translate("Concise display nodes"))
|
||||
o.default = 1
|
||||
|
||||
-- [[ Add the node via the link ]]--
|
||||
s:append(Template("passwall/node_list/link_add_node"))
|
||||
@ -27,7 +31,6 @@ s:append(Template("passwall/node_list/link_add_node"))
|
||||
-- [[ Node List ]]--
|
||||
s = m:section(TypedSection, "nodes")
|
||||
s.anonymous = true
|
||||
s.sortable = true
|
||||
s.addremove = true
|
||||
s.template = "cbi/tblsection"
|
||||
s.extedit = d.build_url("admin", "vpn", "passwall", "node_config", "%s")
|
||||
@ -43,32 +46,62 @@ function s.remove(t, a)
|
||||
luci.http.redirect(d.build_url("admin", "vpn", "passwall", "node_list"))
|
||||
end
|
||||
|
||||
---- Remarks
|
||||
o = s:option(DummyValue, "remarks", translate("Remarks"))
|
||||
|
||||
---- Add Mode
|
||||
o = s:option(DummyValue, "add_mode", translate("Add Mode"))
|
||||
o.cfgvalue = function(t, n)
|
||||
local v = Value.cfgvalue(t, n)
|
||||
if v and v ~= '' then
|
||||
return v
|
||||
else
|
||||
return '手动'
|
||||
-- 简洁模式
|
||||
if api.uci_get_type("global_other", "compact_display_nodes", "1") == "1" then
|
||||
o = s:option(DummyValue, "group", translate("Group"))
|
||||
o.width = "25%"
|
||||
o.cfgvalue = function(t, n)
|
||||
local group = api.uci_get_type_id(n, "group") or "无"
|
||||
return group ~= "" and group or "无"
|
||||
end
|
||||
return str
|
||||
end
|
||||
|
||||
---- Type
|
||||
o = s:option(DummyValue, "type", translate("Type"))
|
||||
o = s:option(DummyValue, "remarks", translate("Remarks"))
|
||||
o.cfgvalue = function(t, n)
|
||||
local str = ""
|
||||
local is_sub = api.uci_get_type_id(n, "is_sub") or ""
|
||||
local group = api.uci_get_type_id(n, "group") or ""
|
||||
local remarks = api.uci_get_type_id(n, "remarks") or ""
|
||||
local type = api.uci_get_type_id(n, "type") or ""
|
||||
local address = api.uci_get_type_id(n, "address") or ""
|
||||
local port = api.uci_get_type_id(n, "port") or ""
|
||||
if is_sub == "" and group == "" then
|
||||
str = str .. type .. ":"
|
||||
end
|
||||
str = str .. remarks
|
||||
if address ~= "" and port ~= "" then
|
||||
local s = " (" .. address .. ":" .. port .. ")"
|
||||
str = str .. s
|
||||
end
|
||||
return str
|
||||
end
|
||||
else
|
||||
s.sortable = true
|
||||
---- Remarks
|
||||
o = s:option(DummyValue, "remarks", translate("Remarks"))
|
||||
|
||||
---- Address
|
||||
o = s:option(DummyValue, "address", translate("Address"))
|
||||
---- Add Mode
|
||||
o = s:option(DummyValue, "add_mode", translate("Add Mode"))
|
||||
o.cfgvalue = function(t, n)
|
||||
local v = Value.cfgvalue(t, n)
|
||||
if v and v ~= '' then
|
||||
return v
|
||||
else
|
||||
return '手动'
|
||||
end
|
||||
return str
|
||||
end
|
||||
|
||||
---- Port
|
||||
o = s:option(DummyValue, "port", translate("Port"))
|
||||
---- Type
|
||||
o = s:option(DummyValue, "type", translate("Type"))
|
||||
|
||||
---- Encrypt Method
|
||||
--[[ o = s:option(DummyValue, "encrypt_method", translate("Encrypt Method"))
|
||||
---- Address
|
||||
o = s:option(DummyValue, "address", translate("Address"))
|
||||
|
||||
---- Port
|
||||
o = s:option(DummyValue, "port", translate("Port"))
|
||||
|
||||
---- Encrypt Method
|
||||
--[[ o = s:option(DummyValue, "encrypt_method", translate("Encrypt Method"))
|
||||
o.width = "15%"
|
||||
o.cfgvalue = function(t, n)
|
||||
local str = "无"
|
||||
@ -82,9 +115,11 @@ o.cfgvalue = function(t, n)
|
||||
end
|
||||
return str
|
||||
end--]]
|
||||
end
|
||||
|
||||
---- Ping
|
||||
o = s:option(DummyValue, "ping", translate("Ping"))
|
||||
o.width = "10%"
|
||||
if api.uci_get_type("global_other", "auto_ping", "0") == "0" then
|
||||
o.template = "passwall/node_list/ping"
|
||||
else
|
||||
|
||||
@ -51,19 +51,6 @@ s = m:section(TypedSection, "global_dns", translate("DNS Settings"))
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
---- DNS Forward Address
|
||||
o = s:option(Value, "dns_forward", translate("DNS Forward Address"))
|
||||
o.rmempty = false
|
||||
o.default = "8.8.4.4:53"
|
||||
o:value("8.8.4.4:53", "8.8.4.4:53(Google DNS1)")
|
||||
o:value("8.8.8.8:53", "8.8.8.8:53(Google DNS2)")
|
||||
o:value("208.67.222.222:53", "208.67.222.222:53(OpenDNS DNS1_53)")
|
||||
o:value("208.67.222.222:5353", "208.67.222.222:5353(OpenDNS DNS1_5353)")
|
||||
o:value("208.67.222.222:443", "208.67.222.222:443(OpenDNS DNS1_443)")
|
||||
o:value("208.67.220.220:53", "208.67.220.220:53(OpenDNS DNS2_53)")
|
||||
o:value("208.67.220.220:5353", "208.67.220.220:5353(OpenDNS DNS2_5353)")
|
||||
o:value("208.67.220.220:443", "208.67.220.220:443(OpenDNS DNS2_443)")
|
||||
|
||||
---- Mainland DNS Sever 1
|
||||
o = s:option(Value, "dns_1", translate("Mainland DNS Sever 1"))
|
||||
o.rmempty = false
|
||||
|
||||
@ -28,36 +28,13 @@ o.default = 0
|
||||
o:depends("auto_update", 1)
|
||||
|
||||
-- [[ Subscribe Settings ]]--
|
||||
s = m:section(TypedSection, "global_subscribe", translate("Node Subscribe"))
|
||||
s = m:section(TypedSection, "global_subscribe", translate("Node Subscribe"),
|
||||
translate(
|
||||
"Please input the subscription url first, save and submit before updating. If you subscribe to update, it is recommended to delete all subscriptions and then re-subscribe."))
|
||||
s.anonymous = true
|
||||
|
||||
---- Subscribe URL
|
||||
o = s:option(DynamicList, "subscribe_url", translate("Subscribe URL"),
|
||||
translate(
|
||||
"Please input the subscription url first, save and submit before updating. If you subscribe to update, it is recommended to delete all subscriptions and then re-subscribe."))
|
||||
|
||||
---- Subscribe Manually update
|
||||
o = s:option(Button, "_update", translate("Manually update"))
|
||||
o.inputstyle = "apply"
|
||||
function o.write(e, e)
|
||||
luci.sys
|
||||
.call("nohup /usr/share/passwall/subscription.sh > /dev/null 2>&1 &")
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall",
|
||||
"log"))
|
||||
end
|
||||
|
||||
---- Subscribe Delete All
|
||||
o = s:option(Button, "_stop", translate("Delete All Subscribe Node"))
|
||||
o.inputstyle = "remove"
|
||||
function o.write(e, e)
|
||||
luci.sys.call(
|
||||
"nohup /usr/share/passwall/subscription.sh stop > /dev/null 2>&1 &")
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall",
|
||||
"log"))
|
||||
end
|
||||
|
||||
---- Subscribe via proxy
|
||||
o = s:option(Flag, "subscribe_by_ss", translate("Subscribe via proxy"))
|
||||
o = s:option(Flag, "subscribe_proxy", translate("Subscribe via proxy"))
|
||||
o.default = 0
|
||||
o.rmempty = false
|
||||
|
||||
@ -81,6 +58,43 @@ for e = 0, 23 do o:value(e, e .. translate("oclock")) end
|
||||
o.default = 0
|
||||
o:depends("auto_update_subscribe", 1)
|
||||
|
||||
---- Subscribe Manually update
|
||||
o = s:option(Button, "_update", translate("Manually update"))
|
||||
o.inputstyle = "apply"
|
||||
function o.write(e, e)
|
||||
luci.sys
|
||||
.call("nohup /usr/share/passwall/subscription.sh > /dev/null 2>&1 &")
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall",
|
||||
"log"))
|
||||
end
|
||||
|
||||
---- Subscribe Delete All
|
||||
o = s:option(Button, "_stop", translate("Delete All Subscribe Node"))
|
||||
o.inputstyle = "remove"
|
||||
function o.write(e, e)
|
||||
luci.sys.call(
|
||||
"nohup /usr/share/passwall/subscription.sh stop > /dev/null 2>&1 &")
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall",
|
||||
"log"))
|
||||
end
|
||||
|
||||
s = m:section(TypedSection, "subscribe_list")
|
||||
s.addremove = true
|
||||
s.anonymous = true
|
||||
s.sortable = true
|
||||
s.template = "cbi/tblsection"
|
||||
|
||||
o = s:option(Flag, "enabled", translate("Enabled"))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "remark", translate("Subscribe Remark"))
|
||||
o.width = "auto"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "url", translate("Subscribe URL"))
|
||||
o.width = "auto"
|
||||
o.rmempty = false
|
||||
|
||||
-- [[ App Settings ]]--
|
||||
s = m:section(TypedSection, "global_app", translate("App Update"),
|
||||
translate("Please confirm that your firmware supports FPU."))
|
||||
|
||||
@ -362,22 +362,21 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
},
|
||||
function(x, rv) {
|
||||
if (rv.status) {
|
||||
var receiveDate = (new Date()).getTime();
|
||||
var responseTimeMs = receiveDate - sendDate;
|
||||
var time = ((new Date()).getTime() - sendDate) / 1000;
|
||||
var speed = "";
|
||||
if (responseTimeMs < 300) {
|
||||
if (time < 0.5) {
|
||||
s.className="green";
|
||||
speed = "<%:very good%>";
|
||||
} else if (responseTimeMs < 600) {
|
||||
} else if (time < 0.8) {
|
||||
s.className="green";
|
||||
speed = "<%:good%>";
|
||||
} else if (responseTimeMs < 2000) {
|
||||
} else if (time < 1.5) {
|
||||
s.className="yellow";
|
||||
speed = "<%:general%>";
|
||||
} else if (responseTimeMs < 5000) {
|
||||
} else if (time < 3) {
|
||||
s.className="red";
|
||||
speed = "<%:bad%>";
|
||||
} else if (responseTimeMs >= 5000) {
|
||||
} else if (time >= 3) {
|
||||
s.className="red";
|
||||
speed = "<%:very bad%>";
|
||||
}
|
||||
|
||||
@ -216,23 +216,22 @@ local socks5_node_num = api.uci_get_type("global_other", "socks5_node_num", 1)
|
||||
var s = document.getElementById('_' + type + '_status');
|
||||
if(s) {
|
||||
if(rv.status) {
|
||||
var receiveDate = (new Date()).getTime();
|
||||
var responseTimeMs = receiveDate - sendDate;
|
||||
var time = ((new Date()).getTime() - sendDate) / 1000;
|
||||
var speed = "";
|
||||
var color="red";
|
||||
if (responseTimeMs < 300) {
|
||||
if (time < 0.5) {
|
||||
color = "green";
|
||||
speed = "<%:very good%>";
|
||||
} else if (responseTimeMs < 600) {
|
||||
} else if (time < 0.8) {
|
||||
color = "green";
|
||||
speed = "<%:good%>";
|
||||
} else if (responseTimeMs < 2000) {
|
||||
} else if (time < 1.5) {
|
||||
color = "#b9b90b";
|
||||
speed = "<%:general%>";
|
||||
} else if (responseTimeMs < 5000) {
|
||||
} else if (time < 3) {
|
||||
color = "red";
|
||||
speed = "<%:bad%>";
|
||||
} else if (responseTimeMs >= 5000) {
|
||||
} else if (time >= 3) {
|
||||
color = "red";
|
||||
speed = "<%:very bad%>";
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
local tcp_node_num = api.uci_get_type("global_other", "tcp_node_num", 1)
|
||||
local udp_node_num = api.uci_get_type("global_other", "udp_node_num", 1)
|
||||
local socks5_node_num = api.uci_get_type("global_other", "socks5_node_num", 1)
|
||||
local compact_display_nodes = api.uci_get_type("global_other", "compact_display_nodes", 1)
|
||||
-%>
|
||||
|
||||
<style>
|
||||
@ -33,6 +34,52 @@ table td, .table .td {
|
||||
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
var ajax = {
|
||||
post: function(url, data, fn_success, fn_timeout) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
var code = ajax.encode(data);
|
||||
xhr.open("POST", url, true);
|
||||
xhr.timeout = 2000;
|
||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
xhr.ontimeout = function() {
|
||||
fn_timeout(xhr);
|
||||
}
|
||||
xhr.onreadystatechange = function() {
|
||||
if(xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) {
|
||||
var json = null;
|
||||
if (xhr.getResponseHeader("Content-Type") == "application/json") {
|
||||
try {
|
||||
json = eval('(' + xhr.responseText + ')');
|
||||
}
|
||||
catch(e) {
|
||||
json = null;
|
||||
}
|
||||
}
|
||||
fn_success(xhr, json);
|
||||
}
|
||||
};
|
||||
xhr.send(code);
|
||||
},
|
||||
encode: function(obj) {
|
||||
obj = obj ? obj : { };
|
||||
obj['_'] = Math.random();
|
||||
|
||||
if (typeof obj == 'object')
|
||||
{
|
||||
var code = '';
|
||||
var self = this;
|
||||
|
||||
for (var k in obj)
|
||||
code += (code ? '&' : '') +
|
||||
k + '=' + encodeURIComponent(obj[k]);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
var section = "";
|
||||
function open_set_node_div(cbi_id) {
|
||||
section = cbi_id;
|
||||
@ -46,58 +93,93 @@ table td, .table .td {
|
||||
document.getElementById("set_node_name").innerHTML = "";
|
||||
}
|
||||
|
||||
|
||||
var auto_ping_value = document.getElementsByClassName('auto_ping_value');
|
||||
for(var i = 0; i < auto_ping_value.length; i++) {
|
||||
var cbi_id = auto_ping_value[i].getAttribute("cbiid");
|
||||
var address = document.getElementById("cbid.passwall." + cbi_id + ".address").value;
|
||||
var port = document.getElementById("cbid.passwall." + cbi_id + ".port").value;
|
||||
XHR.get('<%=dsp.build_url("admin/vpn/passwall/auto_ping_node")%>', {
|
||||
index: i,
|
||||
address: address,
|
||||
port: port
|
||||
},
|
||||
function(x, result) {
|
||||
auto_ping_value[result.index].innerHTML = (result.ping ? result.ping : "--") + " ms";
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function set_node(protocol,number) {
|
||||
if (confirm('<%:Are you sure set to%> ' + protocol.toUpperCase() + "_" + number + '<%:the server?%>')==true){
|
||||
XHR.get('<%=dsp.build_url("admin/vpn/passwall/set_node")%>', { "protocol" : protocol , "number" : number , "section" : section },
|
||||
function(x, result) {
|
||||
if(x && x.status == 200) {
|
||||
//window.location.href = '<%=dsp.build_url("admin/vpn/passwall/log")%>'
|
||||
}
|
||||
}
|
||||
);
|
||||
window.location.href = '<%=dsp.build_url("admin/vpn/passwall/log")%>'
|
||||
window.location.href = '<%=dsp.build_url("admin/vpn/passwall/set_node")%>?protocol=' + protocol + '&number=' + number + '§ion=' + section;
|
||||
}
|
||||
}
|
||||
|
||||
function ping_node(cbi_id,dom) {
|
||||
var address = document.getElementById("cbid.passwall." + cbi_id + ".address").value;
|
||||
var port = document.getElementById("cbid.passwall." + cbi_id + ".port").value;
|
||||
XHR.get('<%=dsp.build_url("admin/vpn/passwall/ping_node")%>', {
|
||||
<% if compact_display_nodes and tonumber(compact_display_nodes) == 1 then %>
|
||||
var remarks = document.getElementById("cbid.passwall." + cbi_id + ".remarks").value;
|
||||
var address_full = remarks.substring(remarks.lastIndexOf("(") + 1, remarks.lastIndexOf(")"));
|
||||
var address = address_full.substring(0, address_full.lastIndexOf(":"));
|
||||
var port = address_full.substring(address_full.lastIndexOf(":") + 1);
|
||||
<% else %>
|
||||
var address = document.getElementById("cbid.passwall." + cbi_id + ".address").value;
|
||||
var port = document.getElementById("cbid.passwall." + cbi_id + ".port").value;
|
||||
<% end %>
|
||||
if ((address != null && address != "") && (port != null && port != "")) {
|
||||
XHR.get('<%=dsp.build_url("admin/vpn/passwall/ping_node")%>', {
|
||||
address: address,
|
||||
port: port
|
||||
},
|
||||
function(x, result) {
|
||||
if(x && x.status == 200) {
|
||||
if (result.ping != null && result.ping != "")
|
||||
dom.outerHTML = result.ping + " ms";
|
||||
else
|
||||
dom.outerHTML = "--";
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/* 自动Ping */
|
||||
var node_list = [];
|
||||
var auto_ping_value = document.getElementsByClassName('auto_ping_value');
|
||||
for(var i = 0; i < auto_ping_value.length; i++) {
|
||||
var cbi_id = auto_ping_value[i].getAttribute("cbiid");
|
||||
<% if compact_display_nodes and tonumber(compact_display_nodes) == 1 then %>
|
||||
var remarks = document.getElementById("cbid.passwall." + cbi_id + ".remarks").value;
|
||||
var address_full = remarks.substring(remarks.lastIndexOf("(") + 1, remarks.lastIndexOf(")"));
|
||||
var address = address_full.substring(0, address_full.lastIndexOf(":"));
|
||||
var port = address_full.substring(address_full.lastIndexOf(":") + 1);
|
||||
<% else %>
|
||||
var address = document.getElementById("cbid.passwall." + cbi_id + ".address").value;
|
||||
var port = document.getElementById("cbid.passwall." + cbi_id + ".port").value;
|
||||
<% end %>
|
||||
if ((address != null && address != "") && (port != null && port != "")) {
|
||||
var data = {
|
||||
index: i,
|
||||
address: address,
|
||||
port: port
|
||||
};
|
||||
node_list.push(data);
|
||||
}
|
||||
}
|
||||
|
||||
var index = 0;
|
||||
function auto_ping() {
|
||||
if (index >= node_list.length){
|
||||
return;
|
||||
}
|
||||
var json = JSON.stringify(node_list[index]);
|
||||
ajax.post('<%=dsp.build_url("admin/vpn/passwall/auto_ping_node_list")%>', {
|
||||
json: json
|
||||
},
|
||||
function(x, result) {
|
||||
if(x && x.status == 200) {
|
||||
if (result.ping != null && result.ping != "")
|
||||
dom.outerHTML = result.ping + " ms";
|
||||
else
|
||||
dom.outerHTML = "--";
|
||||
auto_ping_value[result.index].innerHTML = (result.ping ? result.ping : "--") + " ms";
|
||||
}
|
||||
}
|
||||
index++;
|
||||
auto_ping();
|
||||
},
|
||||
function(x) {
|
||||
index++;
|
||||
auto_ping();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
auto_ping();
|
||||
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
<div id="set_node_div">
|
||||
<div class="cbi-value">您选择的服务器是:<span id="set_node_name"></span></div>
|
||||
<div class="cbi-value"><%:You choose node is:%><span id="set_node_name"></span></div>
|
||||
<div class="cbi-value">
|
||||
<% if tcp_node_num and tonumber(tcp_node_num) >= 1 then %>
|
||||
<% for i = 1, tcp_node_num, 1 do %>
|
||||
|
||||
@ -232,6 +232,9 @@ msgstr "你确定要设为"
|
||||
msgid "the server?"
|
||||
msgstr "服务器吗?"
|
||||
|
||||
msgid "You choose node is:"
|
||||
msgstr "你选择的节点是:"
|
||||
|
||||
msgid "The server client can also use this rule to scientifically surf the Internet"
|
||||
msgstr "本机服务器的客户端也可以使用这个代理模式上网"
|
||||
|
||||
@ -268,6 +271,9 @@ msgstr "Ping延迟"
|
||||
msgid "Ping Value"
|
||||
msgstr "Ping值"
|
||||
|
||||
msgid "Group"
|
||||
msgstr "组"
|
||||
|
||||
msgid "Use TCPing"
|
||||
msgstr "使用TCPing"
|
||||
|
||||
@ -280,6 +286,9 @@ msgstr "自动Ping"
|
||||
msgid "This will automatically ping the node for latency"
|
||||
msgstr "选中后保存应用后即自动Ping节点"
|
||||
|
||||
msgid "Concise display nodes"
|
||||
msgstr "简洁显示节点"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr "应用"
|
||||
|
||||
@ -547,6 +556,9 @@ msgstr "如果你希望从内存中运行,请更改路径,例如/tmp/brook
|
||||
msgid "Node Subscribe"
|
||||
msgstr "节点订阅"
|
||||
|
||||
msgid "Subscribe Remark"
|
||||
msgstr "订阅备注(机场)"
|
||||
|
||||
msgid "Subscribe URL"
|
||||
msgstr "订阅网址"
|
||||
|
||||
|
||||
0
package/lienol/luci-app-passwall/po2lmo
Normal file → Executable file
@ -3,10 +3,10 @@ config global
|
||||
option tcp_node1 'nil'
|
||||
option udp_node1 'nil'
|
||||
option socks5_node1 'nil'
|
||||
option dns_mode 'chinadns'
|
||||
option up_chinadns_mode 'OpenDNS_1'
|
||||
option dns_mode 'pdnsd'
|
||||
option dns2socks_forward '8.8.4.4'
|
||||
option proxy_mode 'chnroute'
|
||||
option localhost_proxy_mode 'default'
|
||||
option localhost_proxy_mode 'gfwlist'
|
||||
|
||||
config global_haproxy
|
||||
option balancing_enable '0'
|
||||
@ -20,7 +20,6 @@ config global_dns
|
||||
option dns_port '0'
|
||||
option wan_port '0'
|
||||
option dns_53 '1'
|
||||
option dns_forward '8.8.4.4:53'
|
||||
option dns_1 '114.114.114.114'
|
||||
option dns_2 '119.29.29.29'
|
||||
|
||||
@ -38,11 +37,12 @@ config global_proxy
|
||||
|
||||
config global_other
|
||||
option use_tcping '1'
|
||||
option auto_ping '0'
|
||||
option auto_ping '1'
|
||||
option tcp_node_num '1'
|
||||
option udp_node_num '1'
|
||||
option socks5_node_num '1'
|
||||
option status_use_big_icon '1'
|
||||
option compact_display_nodes '1'
|
||||
|
||||
config global_rules
|
||||
option auto_update '0'
|
||||
@ -57,7 +57,7 @@ config global_app
|
||||
option brook_file '/usr/bin/brook'
|
||||
|
||||
config global_subscribe
|
||||
option subscribe_by_ss '0'
|
||||
option subscribe_proxy '0'
|
||||
option auto_update_subscribe '0'
|
||||
|
||||
config auto_switch
|
||||
|
||||
0
package/lienol/luci-app-passwall/root/etc/config/passwall_rule/blacklist_host
Normal file → Executable file
0
package/lienol/luci-app-passwall/root/etc/config/passwall_rule/blacklist_ip
Normal file → Executable file
0
package/lienol/luci-app-passwall/root/etc/config/passwall_rule/chnroute
Normal file → Executable file
0
package/lienol/luci-app-passwall/root/etc/config/passwall_rule/gfwlist.conf
Normal file → Executable file
0
package/lienol/luci-app-passwall/root/etc/config/passwall_rule/router
Normal file → Executable file
0
package/lienol/luci-app-passwall/root/etc/config/passwall_rule/user.conf
Normal file → Executable file
0
package/lienol/luci-app-passwall/root/etc/config/passwall_rule/whitelist_host
Normal file → Executable file
0
package/lienol/luci-app-passwall/root/etc/config/passwall_rule/whitelist_ip
Normal file → Executable file
0
package/lienol/luci-app-passwall/root/etc/uci-defaults/luci-app-passwall
Normal file → Executable file
115
package/lienol/luci-app-passwall/root/usr/share/passwall/app.sh
Normal file → Executable file
@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2018-2019 Lienol <lawlienol@gmail.com>
|
||||
# Copyright (C) 2018-2020 Lienol <lawlienol@gmail.com>
|
||||
|
||||
. $IPKG_INSTROOT/lib/functions.sh
|
||||
. $IPKG_INSTROOT/lib/functions/service.sh
|
||||
@ -14,7 +14,7 @@ REDSOCKS_CONFIG_UDP_FILE=$CONFIG_PATH/redsocks_UDP.conf
|
||||
CONFIG_TCP_FILE=$CONFIG_PATH/TCP.json
|
||||
CONFIG_UDP_FILE=$CONFIG_PATH/UDP.json
|
||||
CONFIG_SOCKS5_FILE=$CONFIG_PATH/SOCKS5.json
|
||||
LOCK_FILE=$CONFIG_PATH/$CONFIG.lock
|
||||
LOCK_FILE=/var/lock/$CONFIG.lock
|
||||
LOG_FILE=/var/log/$CONFIG.log
|
||||
RULE_PATH=/etc/config/${CONFIG}_rule
|
||||
APP_PATH=/usr/share/$CONFIG
|
||||
@ -117,6 +117,24 @@ get_not_exists_port_after() {
|
||||
fi
|
||||
}
|
||||
|
||||
set_subscribe_proxy() {
|
||||
local enabled
|
||||
local url
|
||||
config_get enabled $1 enabled
|
||||
config_get url $1 url
|
||||
[ "$enabled" == "1" ] && {
|
||||
[ -n "$url" -a "$url" != "" ] && {
|
||||
if [ -n "$(echo -n "$url" | grep "//")" ]; then
|
||||
echo -n "$url" | awk -F'/' '{print $3}' | sed "s/^/server=&\/./g" | sed "s/$/\/127.0.0.1#$DNS_PORT/g" >>$TMP_DNSMASQ_PATH/subscribe.conf
|
||||
echo -n "$url" | awk -F'/' '{print $3}' | sed "s/^/ipset=&\/./g" | sed "s/$/\/router/g" >>$TMP_DNSMASQ_PATH/subscribe.conf
|
||||
else
|
||||
echo -n "$url" | awk -F'/' '{print $1}' | sed "s/^/server=&\/./g" | sed "s/$/\/127.0.0.1#$DNS_PORT/g" >>$TMP_DNSMASQ_PATH/subscribe.conf
|
||||
echo -n "$url" | awk -F'/' '{print $1}' | sed "s/^/ipset=&\/./g" | sed "s/$/\/router/g" >>$TMP_DNSMASQ_PATH/subscribe.conf
|
||||
fi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TCP_NODE_NUM=$(config_t_get global_other tcp_node_num 1)
|
||||
for i in $(seq 1 $TCP_NODE_NUM); do
|
||||
eval TCP_NODE$i=$(config_t_get global tcp_node$i nil)
|
||||
@ -170,9 +188,6 @@ load_config() {
|
||||
process=$(config_t_get global_forwarding process)
|
||||
fi
|
||||
LOCALHOST_PROXY_MODE=$(config_t_get global localhost_proxy_mode default)
|
||||
DNS_FORWARD=$(config_t_get global_dns dns_forward 208.67.222.222:443)
|
||||
DNS_FORWARD_IP=$(echo "$DNS_FORWARD" | awk -F':' '{print $1}')
|
||||
DNS_FORWARD_PORT=$(echo "$DNS_FORWARD" | awk -F':' '{print $2}')
|
||||
DNS1=$(config_t_get global_dns dns_1)
|
||||
DNS2=$(config_t_get global_dns dns_2)
|
||||
TCP_REDIR_PORT1=$(config_t_get global_proxy tcp_redir_port 1041)
|
||||
@ -622,24 +637,21 @@ start_dns() {
|
||||
nonuse)
|
||||
echolog "不使用任何DNS转发模式,将会直接将WAN口DNS给dnsmasq上游!"
|
||||
;;
|
||||
local_7913)
|
||||
echolog "运行DNS转发模式:使用本机7913端口DNS服务器解析域名..."
|
||||
;;
|
||||
dns2socks)
|
||||
if [ -n "$SOCKS5_NODE1" -a "$SOCKS5_NODE1" != "nil" ]; then
|
||||
dns2socks_bin=$(find_bin dns2socks)
|
||||
[ -n "$dns2socks_bin" ] && {
|
||||
nohup $dns2socks_bin 127.0.0.1:$SOCKS5_PROXY_PORT1 $DNS_FORWARD 127.0.0.1:$DNS_PORT >/dev/null 2>&1 &
|
||||
local dns=$(config_t_get global dns2socks_forward 8.8.4.4)
|
||||
nohup $dns2socks_bin 127.0.0.1:$SOCKS5_PROXY_PORT1 ${dns}:53 127.0.0.1:$DNS_PORT >/dev/null 2>&1 &
|
||||
echolog "运行DNS转发模式:dns2socks..."
|
||||
}
|
||||
else
|
||||
echolog "dns2socks模式需要使用Socks5代理节点,请开启!"
|
||||
fi
|
||||
;;
|
||||
Pcap_DNSProxy)
|
||||
Pcap_DNSProxy_bin=$(find_bin Pcap_DNSProxy)
|
||||
[ -n "$Pcap_DNSProxy_bin" ] && {
|
||||
nohup $Pcap_DNSProxy_bin -c /etc/pcap-dnsproxy >/dev/null 2>&1 &
|
||||
echolog "运行DNS转发模式:Pcap_DNSProxy..."
|
||||
}
|
||||
;;
|
||||
pdnsd)
|
||||
pdnsd_bin=$(find_bin pdnsd)
|
||||
[ -n "$pdnsd_bin" ] && {
|
||||
@ -648,16 +660,14 @@ start_dns() {
|
||||
echolog "运行DNS转发模式:Pdnsd..."
|
||||
}
|
||||
;;
|
||||
local_7913)
|
||||
echolog "运行DNS转发模式:使用本机7913端口DNS服务器解析域名..."
|
||||
;;
|
||||
chinadns)
|
||||
chinadns_bin=$(find_bin ChinaDNS)
|
||||
[ -n "$chinadns_bin" ] && {
|
||||
other=1
|
||||
other_port=$(expr $DNS_PORT + 1)
|
||||
echolog "运行DNS转发模式:ChinaDNS..."
|
||||
dns1=$(config_t_get global_dns dns_1)
|
||||
[ "$dns1" = "dnsbyisp" ] && dns1=$(cat /tmp/resolv.conf.auto 2>/dev/null | grep -E -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" | sort -u | grep -v 0.0.0.0 | grep -v 127.0.0.1 | sed -n '2P')
|
||||
local dns1=$DNS1
|
||||
[ "$DNS1" = "dnsbyisp" ] && dns1=$(cat /tmp/resolv.conf.auto 2>/dev/null | grep -E -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" | grep -v 0.0.0.0 | grep -v 127.0.0.1 | sed -n '1P')
|
||||
case "$UP_CHINADNS_MODE" in
|
||||
OpenDNS_1)
|
||||
other=0
|
||||
@ -675,23 +685,9 @@ start_dns() {
|
||||
nohup $chinadns_bin -p $DNS_PORT -c $RULE_PATH/chnroute -m -d -s $UP_CHINADNS_CUSTOM >/dev/null 2>&1 &
|
||||
echolog "运行ChinaDNS上游转发模式:$UP_CHINADNS_CUSTOM..."
|
||||
;;
|
||||
dnsproxy)
|
||||
dnsproxy_bin=$(find_bin dnsproxy)
|
||||
[ -n "$dnsproxy_bin" ] && {
|
||||
nohup $dnsproxy_bin -d -T -p $DNS_PORT -R $DNS_FORWARD_IP -P $DNS_FORWARD_PORT >/dev/null 2>&1 &
|
||||
echolog "运行ChinaDNS上游转发模式:dnsproxy..."
|
||||
}
|
||||
;;
|
||||
dns-forwarder)
|
||||
dnsforwarder_bin=$(find_bin dns-forwarder)
|
||||
[ -n "$dnsforwarder_bin" ] && {
|
||||
nohup $dnsforwarder_bin -p $DNS_PORT -s $DNS_FORWARD >/dev/null 2>&1 &
|
||||
echolog "运行ChinaDNS上游转发模式:dns-forwarder..."
|
||||
}
|
||||
;;
|
||||
esac
|
||||
if [ "$other" = "1" ]; then
|
||||
nohup $chinadns_bin -p 7923 -c $RULE_PATH/chnroute -m -d -s $dns1,127.0.0.1:$DNS_PORT >/dev/null 2>&1 &
|
||||
nohup $chinadns_bin -p $DNS_PORT -c $RULE_PATH/chnroute -m -d -s $dns1,127.0.0.1:$other_port >/dev/null 2>&1 &
|
||||
fi
|
||||
}
|
||||
;;
|
||||
@ -717,7 +713,6 @@ EOF
|
||||
echolog "生成Dnsmasq配置文件。"
|
||||
|
||||
if [ "$dnsport" != "0" ]; then
|
||||
isp_dns=$(cat /tmp/resolv.conf.auto 2>/dev/null | grep -E -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" | sort -u | grep -v 0.0.0.0 | grep -v 127.0.0.1)
|
||||
failcount=0
|
||||
while [ "$failcount" -lt "10" ]; do
|
||||
interface=$(ifconfig | grep "$dnsport" | awk '{print $1}')
|
||||
@ -727,13 +722,6 @@ EOF
|
||||
[ "$failcount" -ge 10 ] && exit 0
|
||||
sleep 1m
|
||||
else
|
||||
[ -n "$isp_dns" ] && {
|
||||
for isp_ip in $isp_dns; do
|
||||
echo server=$isp_ip >>/etc/dnsmasq.conf
|
||||
route add -host ${isp_ip} dev ${dnsport}
|
||||
echolog "添加运营商DNS出口路由表:$dnsport"
|
||||
done
|
||||
}
|
||||
[ "$DNS1" != "dnsbyisp" ] && {
|
||||
route add -host ${DNS1} dev ${dnsport}
|
||||
echolog "添加DNS1出口路由表:$dnsport"
|
||||
@ -748,10 +736,10 @@ EOF
|
||||
fi
|
||||
done
|
||||
else
|
||||
isp_dns=$(cat /tmp/resolv.conf.auto 2>/dev/null | grep -E -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" | sort -u | grep -v 0.0.0.0 | grep -v 127.0.0.1)
|
||||
[ -n "$isp_dns" ] && {
|
||||
for isp_ip in $isp_dns; do
|
||||
echo server=$isp_ip >>/etc/dnsmasq.conf
|
||||
isp_dnss=$(cat /tmp/resolv.conf.auto 2>/dev/null | grep -E -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" | sort -u | grep -v 0.0.0.0 | grep -v 127.0.0.1)
|
||||
[ -n "$isp_dnss" ] && {
|
||||
for isp_dns in $isp_dnss; do
|
||||
echo server=$isp_dns >>/etc/dnsmasq.conf
|
||||
done
|
||||
}
|
||||
[ "$DNS1" != "dnsbyisp" ] && {
|
||||
@ -805,22 +793,10 @@ EOF
|
||||
# done
|
||||
# fi
|
||||
|
||||
subscribe_by_ss=$(config_t_get global_subscribe subscribe_by_ss)
|
||||
[ -z "$subscribe_by_ss" ] && subscribe_by_ss=0
|
||||
[ "$subscribe_by_ss" -eq 1 ] && {
|
||||
subscribe_url=$(config_t_get global_subscribe subscribe_url)
|
||||
[ -n "$subscribe_url" ] && {
|
||||
for url in $subscribe_url; do
|
||||
if [ -n "$(echo -n "$url" | grep "//")" ]; then
|
||||
echo -n "$url" | awk -F'/' '{print $3}' | sed "s/^/server=&\/./g" | sed "s/$/\/127.0.0.1#$DNS_PORT/g" >>$TMP_DNSMASQ_PATH/subscribe.conf
|
||||
echo -n "$url" | awk -F'/' '{print $3}' | sed "s/^/ipset=&\/./g" | sed "s/$/\/router/g" >>$TMP_DNSMASQ_PATH/subscribe.conf
|
||||
else
|
||||
echo -n "$url" | awk -F'/' '{print $1}' | sed "s/^/server=&\/./g" | sed "s/$/\/127.0.0.1#$DNS_PORT/g" >>$TMP_DNSMASQ_PATH/subscribe.conf
|
||||
echo -n "$url" | awk -F'/' '{print $1}' | sed "s/^/ipset=&\/./g" | sed "s/$/\/router/g" >>$TMP_DNSMASQ_PATH/subscribe.conf
|
||||
fi
|
||||
done
|
||||
restdns=1
|
||||
}
|
||||
subscribe_proxy=$(config_t_get global_subscribe subscribe_proxy 0)
|
||||
[ "$subscribe_proxy" -eq 1 ] && {
|
||||
config_foreach set_subscribe_proxy "subscribe_list"
|
||||
restdns=1
|
||||
}
|
||||
|
||||
if [ ! -f "$TMP_DNSMASQ_PATH/gfwlist.conf" -a "$DNS_MODE" != "nonuse" ]; then
|
||||
@ -977,13 +953,10 @@ gen_pdnsd_config() {
|
||||
}
|
||||
|
||||
stop_dnsmasq() {
|
||||
if [ "$TCP_NODE1" == "nil" ]; then
|
||||
rm -rf /var/dnsmasq.d/dnsmasq-$CONFIG.conf
|
||||
rm -rf $DNSMASQ_PATH/dnsmasq-$CONFIG.conf
|
||||
rm -rf $TMP_DNSMASQ_PATH
|
||||
/etc/init.d/dnsmasq restart 2>/dev/null
|
||||
echolog "没有选择节点!"
|
||||
fi
|
||||
rm -rf /var/dnsmasq.d/dnsmasq-$CONFIG.conf
|
||||
rm -rf $DNSMASQ_PATH/dnsmasq-$CONFIG.conf
|
||||
rm -rf $TMP_DNSMASQ_PATH
|
||||
/etc/init.d/dnsmasq restart 2>/dev/null
|
||||
}
|
||||
|
||||
start_haproxy() {
|
||||
@ -1136,11 +1109,9 @@ boot() {
|
||||
}
|
||||
|
||||
start() {
|
||||
#防止并发启动
|
||||
! load_config && return 1
|
||||
[ -f "$LOCK_FILE" ] && return 3
|
||||
touch "$LOCK_FILE"
|
||||
echolog "开始运行脚本!"
|
||||
! load_config && return 1
|
||||
add_vps_port
|
||||
start_haproxy
|
||||
start_socks5_proxy
|
||||
@ -1164,7 +1135,7 @@ stop() {
|
||||
clean_log
|
||||
source $APP_PATH/iptables.sh stop
|
||||
del_vps_port
|
||||
kill_all pdnsd Pcap_DNSProxy brook dns2socks haproxy dns-forwarder chinadns dnsproxy ipt2socks
|
||||
kill_all pdnsd brook dns2socks haproxy chinadns ipt2socks
|
||||
ps -w | grep -E "$CONFIG_TCP_FILE|$CONFIG_UDP_FILE|$CONFIG_SOCKS5_FILE" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 &
|
||||
ps -w | grep -E "$CONFIG_PATH" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 &
|
||||
ps -w | grep "kcptun_client" | grep "$KCPTUN_REDIR_PORT" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 &
|
||||
|
||||
0
package/lienol/luci-app-passwall/root/usr/share/passwall/iptables.sh
Normal file → Executable file
0
package/lienol/luci-app-passwall/root/usr/share/passwall/monitor.sh
Normal file → Executable file
0
package/lienol/luci-app-passwall/root/usr/share/passwall/rule_update.sh
Normal file → Executable file
183
package/lienol/luci-app-passwall/root/usr/share/passwall/subscription.sh
Normal file → Executable file
@ -1,5 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
. $IPKG_INSTROOT/lib/functions.sh
|
||||
. /usr/share/libubox/jshn.sh
|
||||
|
||||
CONFIG=passwall
|
||||
@ -31,6 +32,76 @@ decode_url_link() {
|
||||
fi
|
||||
}
|
||||
|
||||
start_subscribe() {
|
||||
local enabled
|
||||
local url
|
||||
config_get enabled $1 enabled
|
||||
config_get url $1 url
|
||||
[ "$enabled" == "1" ] && {
|
||||
[ -n "$url" -a "$url" != "" ] && {
|
||||
local addnum_ss=0
|
||||
local updatenum_ss=0
|
||||
local delnum_ss=0
|
||||
local addnum_ssr=0
|
||||
local updatenum_ssr=0
|
||||
local delnum_ssr=0
|
||||
local addnum_v2ray=0
|
||||
local updatenum_v2ray=0
|
||||
local delnum_v2ray=0
|
||||
local addnum_trojan=0
|
||||
local updatenum_trojan=0
|
||||
local delnum_trojan=0
|
||||
config_get subscrib_remark $1 remark
|
||||
let index+=1
|
||||
echo "$Date: 正在订阅:$url" >> $LOG_FILE
|
||||
result=$(/usr/bin/curl --connect-timeout 10 -sL $url)
|
||||
[ "$?" != 0 ] || [ -z "$result" ] && {
|
||||
result=$(/usr/bin/wget --no-check-certificate --timeout=8 -t 1 -O- $url)
|
||||
[ "$?" != 0 ] || [ -z "$result" ] && echo "$Date: 订阅失败:$url,请检测订阅链接是否正常或使用代理尝试!" >> $LOG_FILE && continue
|
||||
}
|
||||
file="/var/${CONFIG}_sub/$index"
|
||||
echo "$result" > $file
|
||||
|
||||
get_local_nodes
|
||||
|
||||
[ -z "$(du -sh $file 2> /dev/null)" ] && echo "$Date: 订阅失败:$url,解密失败!" >> $LOG_FILE && continue
|
||||
decode_link=$(cat "$file" | base64 -d 2> /dev/null)
|
||||
maxnum=$(echo -n "$decode_link" | grep "MAX=" | awk -F"=" '{print $2}')
|
||||
if [ -n "$maxnum" ]; then
|
||||
decode_link=$(echo -n "$decode_link" | sed '/MAX=/d' | shuf -n${maxnum})
|
||||
else
|
||||
decode_link=$(echo -n "$decode_link")
|
||||
fi
|
||||
|
||||
[ -z "$decode_link" ] && continue
|
||||
for link in $decode_link
|
||||
do
|
||||
if expr "$link" : "ss://";then
|
||||
link_type="ss"
|
||||
new_link=$(echo -n "$link" | sed 's/ss:\/\///g')
|
||||
elif expr "$link" : "ssr://";then
|
||||
link_type="ssr"
|
||||
new_link=$(echo -n "$link" | sed 's/ssr:\/\///g')
|
||||
elif expr "$link" : "vmess://";then
|
||||
link_type="v2ray"
|
||||
new_link=$(echo -n "$link" | sed 's/vmess:\/\///g')
|
||||
elif expr "$link" : "trojan://";then
|
||||
link_type="trojan"
|
||||
new_link=$(echo -n "$link" | sed 's/trojan:\/\///g')
|
||||
fi
|
||||
[ -z "$link_type" ] && continue
|
||||
get_remote_config "$link_type" "$new_link"
|
||||
update_config
|
||||
done
|
||||
|
||||
[ "$addnum_ss" -gt 0 ] || [ "$updatenum_ss" -gt 0 ] || [ "$delnum_ss" -gt 0 ] && echo "$Date: $subscrib_remark: SS节点新增 $addnum_ss 个,修改 $updatenum_ss 个,删除 $delnum_ss 个。" >> $LOG_FILE
|
||||
[ "$addnum_ssr" -gt 0 ] || [ "$updatenum_ssr" -gt 0 ] || [ "$delnum_ssr" -gt 0 ] && echo "$Date: $subscrib_remark: SSR节点新增 $addnum_ssr 个,修改 $updatenum_ssr 个,删除 $delnum_ssr 个。" >> $LOG_FILE
|
||||
[ "$addnum_v2ray" -gt 0 ] || [ "$updatenum_v2ray" -gt 0 ] || [ "$delnum_v2ray" -gt 0 ] && echo "$Date: $subscrib_remark: V2ray节点新增 $addnum_v2ray 个,修改 $updatenum_v2ray 个,删除 $delnum_v2ray 个。" >> $LOG_FILE
|
||||
[ "$addnum_trojan" -gt 0 ] || [ "$updatenum_trojan" -gt 0 ] || [ "$delnum_trojan" -gt 0 ] && echo "$Date: $subscrib_remark: Trojan节点新增 $addnum_trojan 个,修改 $updatenum_trojan 个,删除 $delnum_trojan 个。" >> $LOG_FILE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ss_decode() {
|
||||
temp_link=$1
|
||||
if [[ "$(echo $temp_link | grep "@")" != "" ]]; then
|
||||
@ -54,11 +125,11 @@ get_node_index(){
|
||||
}
|
||||
|
||||
get_local_nodes(){
|
||||
[ -f "/etc/config/$CONFIG" ] && [ "`uci show $CONFIG | grep -c 'sub_node'`" -gt 0 ] && {
|
||||
[ -f "/etc/config/$CONFIG" ] && [ "`uci show $CONFIG | grep -c 'is_sub'`" -gt 0 ] && {
|
||||
get_node_index
|
||||
for i in `seq $nodes_index -1 1`
|
||||
do
|
||||
[ "$(uci show $CONFIG.@nodes[$(($i-1))]|grep -c "sub_node")" -eq 1 ] && {
|
||||
[ "$(uci show $CONFIG.@nodes[$(($i-1))]|grep -c "is_sub")" -eq 1 ] && {
|
||||
if [ ! -f "/usr/share/${CONFIG}/sub/all_localnodes" ]; then
|
||||
echo $(config_t_get nodes address $(($i-1))) > /usr/share/${CONFIG}/sub/all_localnodes
|
||||
else
|
||||
@ -71,9 +142,8 @@ get_local_nodes(){
|
||||
|
||||
get_remote_config(){
|
||||
isAdd=1
|
||||
add_mode="订阅"
|
||||
add_mode="$subscrib_remark"
|
||||
[ -n "$3" ] && add_mode="导入"
|
||||
group="sub_node"
|
||||
if [ "$1" == "ss" ]; then
|
||||
decode_link="$2"
|
||||
decode_link=$(ss_decode $decode_link)
|
||||
@ -86,8 +156,6 @@ get_remote_config(){
|
||||
decode_link="$2"
|
||||
decode_link=$(decode_url_link $decode_link 1)
|
||||
node_address=$(echo "$decode_link" | awk -F ':' '{print $1}')
|
||||
node_address=$(echo $node_address |awk '{print gensub(/[^!-~]/,"","g",$0)}')
|
||||
[ -z "$node_address" -o "$node_address" == "" ] && isAdd=0
|
||||
node_port=$(echo "$decode_link" | awk -F ':' '{print $2}')
|
||||
protocol=$(echo "$decode_link" | awk -F ':' '{print $3}')
|
||||
ssr_encrypt_method=$(echo "$decode_link" | awk -F ':' '{print $4}')
|
||||
@ -101,6 +169,7 @@ get_remote_config(){
|
||||
remarks_temp=$(echo "$decode_link" |grep -Eo "remarks.+" |sed 's/remarks=//g'|awk -F'&' '{print $1}')
|
||||
[ -n "$remarks_temp" ] && remarks="$(decode_url_link $remarks_temp 0)"
|
||||
group_temp=$(echo "$decode_link" |grep -Eo "group.+" |sed 's/group=//g'|awk -F'&' '{print $1}')
|
||||
[ -n "$group_temp" ] && group="$(decode_url_link $group_temp 0)"
|
||||
elif [ "$1" == "v2ray" ]; then
|
||||
decode_link=$(decode_url_link $2 1)
|
||||
json_load "$decode_link"
|
||||
@ -134,6 +203,9 @@ get_remote_config(){
|
||||
remarks="${node_address}:${node_port}"
|
||||
fi
|
||||
|
||||
node_address=$(echo $node_address |awk '{print gensub(/[^!-~]/,"","g",$0)}')
|
||||
#[ -z "$node_address" -o "$node_address" == "" ] && isAdd=0
|
||||
|
||||
# 把全部节点节点写入文件 /usr/share/${CONFIG}/sub/all_onlinenodes
|
||||
if [ ! -f "/usr/share/${CONFIG}/sub/all_onlinenodes" ]; then
|
||||
echo $node_address > /usr/share/${CONFIG}/sub/all_onlinenodes
|
||||
@ -147,7 +219,7 @@ add_nodes(){
|
||||
get_node_index
|
||||
uci_set="uci set $CONFIG.@nodes[$nodes_index]."
|
||||
uci add $CONFIG nodes > /dev/null
|
||||
[ -z "$3" ] && ${uci_set}group="$group"
|
||||
[ -z "$3" ] && ${uci_set}is_sub="is_sub"
|
||||
if [ "$2" == "ss" ]; then
|
||||
${uci_set}add_mode="$add_mode"
|
||||
${uci_set}remarks="$remarks"
|
||||
@ -181,6 +253,7 @@ add_nodes(){
|
||||
${uci_set}obfs_param="$obfsparam"
|
||||
${uci_set}timeout=300
|
||||
${uci_set}tcp_fast_open=false
|
||||
${uci_set}group="$group"
|
||||
|
||||
if [ "$1" == "add" ]; then
|
||||
let addnum_ssr+=1
|
||||
@ -234,14 +307,11 @@ add_nodes(){
|
||||
|
||||
update_config(){
|
||||
[ "$isAdd" == 1 ] && {
|
||||
isadded_address=$(uci show $CONFIG | grep -c "remarks='$remarks'")
|
||||
if [ "$isadded_address" -eq 0 ]; then
|
||||
isadded_remarks=$(uci show $CONFIG | grep -c "remarks='$remarks'")
|
||||
if [ "$isadded_remarks" -eq 0 ]; then
|
||||
add_nodes add "$link_type"
|
||||
else
|
||||
index=$(uci show $CONFIG | grep -w "remarks='$remarks'" | cut -d '[' -f2|cut -d ']' -f1)
|
||||
local_port=$(config_t_get nodes port $index)
|
||||
local_vmess_id=$(config_t_get nodes v2ray_VMess_id $index)
|
||||
|
||||
uci delete $CONFIG.@nodes[$index]
|
||||
add_nodes update "$link_type"
|
||||
fi
|
||||
@ -275,7 +345,7 @@ del_config(){
|
||||
|
||||
del_all_config(){
|
||||
get_node_index
|
||||
[ "`uci show $CONFIG | grep -c 'sub_node'`" -eq 0 ] && exit 0
|
||||
[ "`uci show $CONFIG | grep -c 'is_sub'`" -eq 0 ] && exit 0
|
||||
TCP_NODE_NUM=$(uci get $CONFIG.@global_other[0].tcp_node_num)
|
||||
for i in $(seq 1 $TCP_NODE_NUM); do
|
||||
eval TCP_NODE$i=$(config_t_get global tcp_node$i)
|
||||
@ -293,11 +363,14 @@ del_all_config(){
|
||||
|
||||
[ "$UDP_NODE1" == "default" ] && UDP_NODE1=$TCP_NODE1
|
||||
|
||||
is_stop=0
|
||||
|
||||
for i in $(seq 1 $TCP_NODE_NUM); do
|
||||
eval node=\$TCP_NODE$i
|
||||
[ -n "$node" -a "$node" != "nil" ] && {
|
||||
is_sub_node=`uci -q get $CONFIG.$node.group`
|
||||
is_sub_node=`uci -q get $CONFIG.$node.is_sub`
|
||||
[ -n "$is_sub_node" ] && {
|
||||
is_stop=1
|
||||
uci set $CONFIG.@global[0].tcp_node$i="nil" && uci commit $CONFIG
|
||||
}
|
||||
}
|
||||
@ -306,8 +379,9 @@ del_all_config(){
|
||||
for i in $(seq 1 $UDP_NODE_NUM); do
|
||||
eval node=\$UDP_NODE$i
|
||||
[ "$node" != "nil" ] && {
|
||||
is_sub_node=`uci -q get $CONFIG.$node.group`
|
||||
is_sub_node=`uci -q get $CONFIG.$node.is_sub`
|
||||
[ -n "$is_sub_node" ] && {
|
||||
is_stop=1
|
||||
uci set $CONFIG.@global[0].udp_node$i="nil" && uci commit $CONFIG
|
||||
}
|
||||
}
|
||||
@ -316,8 +390,9 @@ del_all_config(){
|
||||
for i in $(seq 1 $SOCKS5_NODE_NUM); do
|
||||
eval node=\$SOCKS5_NODE$i
|
||||
[ "$node" != "nil" ] && {
|
||||
is_sub_node=`uci -q get $CONFIG.$node.group`
|
||||
is_sub_node=`uci -q get $CONFIG.$node.is_sub`
|
||||
[ -n "$is_sub_node" ] && {
|
||||
is_stop=1
|
||||
uci set $CONFIG.@global[0].socks5_node$i="nil" && uci commit $CONFIG
|
||||
}
|
||||
}
|
||||
@ -325,10 +400,10 @@ del_all_config(){
|
||||
|
||||
for i in `seq $nodes_index -1 1`
|
||||
do
|
||||
[ "$(uci show $CONFIG.@nodes[$(($i-1))] | grep -c 'sub_node')" -eq 1 ] && uci delete $CONFIG.@nodes[$(($i-1))] && uci commit $CONFIG
|
||||
[ "$(uci show $CONFIG.@nodes[$(($i-1))] | grep -c 'is_sub')" -eq 1 ] && uci delete $CONFIG.@nodes[$(($i-1))] && uci commit $CONFIG
|
||||
done
|
||||
|
||||
/etc/init.d/$CONFIG stop
|
||||
[ "$is_stop" == 1 ] && /etc/init.d/$CONFIG restart
|
||||
}
|
||||
|
||||
add() {
|
||||
@ -371,82 +446,24 @@ start() {
|
||||
touch "$LOCK_FILE"
|
||||
base64=$(command -v base64)
|
||||
[ -z "$base64" ] && echo "$Date: 找不到Base64程序,请安装后重试!" >> $LOG_FILE && rm -f "$LOCK_FILE" && exit 0
|
||||
addnum_ss=0
|
||||
updatenum_ss=0
|
||||
delnum_ss=0
|
||||
addnum_ssr=0
|
||||
updatenum_ssr=0
|
||||
delnum_ssr=0
|
||||
addnum_v2ray=0
|
||||
updatenum_v2ray=0
|
||||
delnum_v2ray=0
|
||||
addnum_trojan=0
|
||||
updatenum_trojan=0
|
||||
delnum_trojan=0
|
||||
subscribe_url=$(uci get $CONFIG.@global_subscribe[0].subscribe_url) # 订阅地址
|
||||
[ -z "$subscribe_url" ] && echo "$Date: 订阅地址为空,订阅失败!" >> $LOG_FILE && rm -f "$LOCK_FILE" && exit 0
|
||||
has_subscribe=$(uci show $CONFIG | grep @subscribe_list | grep enabled=\'1\')
|
||||
[ -z "$has_subscribe" -o "$has_subscribe" = "" ] && echo "$Date: 没有订阅地址或没启用!" >> $LOG_FILE && rm -f "$LOCK_FILE" && exit 0
|
||||
|
||||
echo "$Date: 开始订阅..." >> $LOG_FILE
|
||||
mkdir -p /var/${CONFIG}_sub && rm -f /var/${CONFIG}_sub/*
|
||||
index=0
|
||||
for url in $subscribe_url
|
||||
do
|
||||
let index+=1
|
||||
echo "$Date: 正在订阅:$url" >> $LOG_FILE
|
||||
result=$(/usr/bin/curl --connect-timeout 10 -sL $url)
|
||||
[ "$?" != 0 ] || [ -z "$result" ] && {
|
||||
result=$(/usr/bin/wget --no-check-certificate --timeout=8 -t 1 -O- $url)
|
||||
[ "$?" != 0 ] || [ -z "$result" ] && echo "$Date: 订阅失败:$url,请检测订阅链接是否正常或使用代理尝试!" >> $LOG_FILE && continue
|
||||
}
|
||||
echo "$result" > /var/${CONFIG}_sub/$index
|
||||
done
|
||||
[ ! -d "/var/${CONFIG}_sub" ] || [ "$(ls /var/${CONFIG}_sub | wc -l)" -eq 0 ] && echo "$Date: 订阅失败" >> $LOG_FILE && rm -f "$LOCK_FILE" && exit 0
|
||||
mkdir -p /usr/share/${CONFIG}/sub && rm -f /usr/share/${CONFIG}/sub/*
|
||||
get_local_nodes
|
||||
for file in /var/${CONFIG}_sub/*
|
||||
do
|
||||
[ -z "$(du -sh $file 2> /dev/null)" ] && echo "$Date: 订阅失败:$url,解密失败!" >> $LOG_FILE && continue
|
||||
decode_link=$(cat "$file" | base64 -d 2> /dev/null)
|
||||
maxnum=$(echo -n "$decode_link" | grep "MAX=" | awk -F"=" '{print $2}')
|
||||
if [ -n "$maxnum" ]; then
|
||||
decode_link=$(echo -n "$decode_link" | sed '/MAX=/d' | shuf -n${maxnum})
|
||||
else
|
||||
decode_link=$(echo -n "$decode_link")
|
||||
fi
|
||||
|
||||
[ -z "$decode_link" ] && continue
|
||||
for link in $decode_link
|
||||
do
|
||||
if expr "$link" : "ss://";then
|
||||
link_type="ss"
|
||||
new_link=$(echo -n "$link" | sed 's/ss:\/\///g')
|
||||
elif expr "$link" : "ssr://";then
|
||||
link_type="ssr"
|
||||
new_link=$(echo -n "$link" | sed 's/ssr:\/\///g')
|
||||
elif expr "$link" : "vmess://";then
|
||||
link_type="v2ray"
|
||||
new_link=$(echo -n "$link" | sed 's/vmess:\/\///g')
|
||||
elif expr "$link" : "trojan://";then
|
||||
link_type="trojan"
|
||||
new_link=$(echo -n "$link" | sed 's/trojan:\/\///g')
|
||||
fi
|
||||
[ -z "$link_type" ] && continue
|
||||
get_remote_config "$link_type" "$new_link"
|
||||
update_config
|
||||
done
|
||||
done
|
||||
index=0
|
||||
config_load $CONFIG
|
||||
config_foreach start_subscribe "subscribe_list"
|
||||
|
||||
[ -f "/usr/share/${CONFIG}/sub/all_localnodes" ] && del_config
|
||||
echo "$Date: 本次更新,SS节点新增 $addnum_ss 个,修改 $updatenum_ss 个,删除 $delnum_ss 个。" >> $LOG_FILE
|
||||
echo "$Date: 本次更新,SSR节点新增 $addnum_ssr 个,修改 $updatenum_ssr 个,删除 $delnum_ssr 个。" >> $LOG_FILE
|
||||
echo "$Date: 本次更新,V2ray节点新增 $addnum_v2ray 个,修改 $updatenum_v2ray 个,删除 $delnum_v2ray 个。" >> $LOG_FILE
|
||||
echo "$Date: 本次更新,Trojan节点新增 $addnum_trojan 个,修改 $updatenum_trojan 个,删除 $delnum_trojan 个。" >> $LOG_FILE
|
||||
echo "$Date: 订阅完毕..." >> $LOG_FILE
|
||||
rm -f "$LOCK_FILE"
|
||||
exit 0
|
||||
}
|
||||
|
||||
stop() {
|
||||
[ "`uci show $CONFIG | grep -c 'sub_node'`" -gt 0 ] && {
|
||||
[ "`uci show $CONFIG | grep -c 'is_sub'`" -gt 0 ] && {
|
||||
del_all_config
|
||||
echo "$Date: 在线订阅节点已全部删除" >> $LOG_FILE
|
||||
}
|
||||
|
||||
1
package/lienol/luci-app-passwall/root/usr/share/passwall/test.sh
Normal file → Executable file
@ -11,6 +11,7 @@ test_url() {
|
||||
status=$(/usr/bin/curl -I -o /dev/null -s --connect-timeout 3 -w %{http_code} "$1" | grep 200)
|
||||
[ "$?" != 0 ] && {
|
||||
status=$(/usr/bin/wget --no-check-certificate --spider --timeout=3 "$1")
|
||||
[ "$?" == 0 ] && status=200
|
||||
}
|
||||
echo $status
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2019 Lienol
|
||||
# Copyright (C) 2019-2020 Lienol
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
@ -10,9 +10,9 @@ LUCI_TITLE:=LuCI support for Trojan Server
|
||||
LUCI_DEPENDS:=+luci-lib-jsonc +trojan
|
||||
LUCI_PKGARCH:=all
|
||||
PKG_VERSION:=1.0
|
||||
PKG_RELEASE:=2-20191207
|
||||
PKG_RELEASE:=3-20191220
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
include ../luci_my.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2019 Lienol <lawlienol@gmail.com>
|
||||
# Copyright (C) 2019-2020 Lienol <lawlienol@gmail.com>
|
||||
|
||||
START=99
|
||||
|
||||
@ -20,13 +20,6 @@ gen_trojan_config_file() {
|
||||
lua /usr/lib/lua/luci/model/cbi/trojan_server/api/gen_trojan_config_file.lua $1 > $CONFIG_PATH/$1.json
|
||||
echolog "$remarks $port 生成并运行 Trojan 配置文件 - $CONFIG_PATH/$1.json"
|
||||
trojan -c $CONFIG_PATH/$1.json >/dev/null 2>&1 &
|
||||
|
||||
is_run=`ps -w| grep -v grep | grep "$CONFIG_PATH/$1.json"`
|
||||
if [ -z "$is_run" ];then
|
||||
echolog "$remarks $port Trojan 运行失败"
|
||||
else
|
||||
echolog "$remarks $port Trojan 运行成功"
|
||||
fi
|
||||
}
|
||||
|
||||
start_trojan_server() {
|
||||
|
||||
0
package/lienol/luci-app-trojan-server/root/etc/uci-defaults/luci-app-trojan-server
Normal file → Executable file
0
package/lienol/luci-app-trojan-server/root/usr/share/trojan_server/firewall.include
Normal file → Executable file
19
package/lienol/luci-app-v2ray-server/Makefile
Executable file
@ -0,0 +1,19 @@
|
||||
# Copyright (C) 2018-2020 Lienol
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-v2ray-server
|
||||
LUCI_TITLE:=LuCI support for V2ray Server
|
||||
LUCI_DEPENDS:=+libsodium +luci-lib-jsonc +unzip +v2ray
|
||||
LUCI_PKGARCH:=all
|
||||
PKG_VERSION:=1.0
|
||||
PKG_RELEASE:=29-20191220
|
||||
|
||||
include ../luci_my.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
||||
|
||||
|
||||
@ -0,0 +1,66 @@
|
||||
-- Copyright 2018-2019 Lienol <lawlienol@gmail.com>
|
||||
module("luci.controller.v2ray_server", package.seeall)
|
||||
local http = require "luci.http"
|
||||
local v2ray = require "luci.model.cbi.v2ray_server.api.v2ray"
|
||||
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/v2ray_server") then return end
|
||||
entry({"admin", "vpn"}, firstchild(), "VPN", 45).dependent = false
|
||||
entry({"admin", "vpn", "v2ray_server"}, cbi("v2ray_server/index"),
|
||||
_("V2ray Server"), 3).dependent = true
|
||||
entry({"admin", "vpn", "v2ray_server", "config"}, cbi("v2ray_server/config")).leaf =
|
||||
true
|
||||
|
||||
entry({"admin", "vpn", "v2ray_server", "users_status"},
|
||||
call("v2ray_users_status")).leaf = true
|
||||
entry({"admin", "vpn", "v2ray_server", "check"}, call("v2ray_check")).leaf =
|
||||
true
|
||||
entry({"admin", "vpn", "v2ray_server", "update"}, call("v2ray_update")).leaf =
|
||||
true
|
||||
entry({"admin", "vpn", "v2ray_server", "get_log"}, call("get_log")).leaf =
|
||||
true
|
||||
entry({"admin", "vpn", "v2ray_server", "clear_log"}, call("clear_log")).leaf =
|
||||
true
|
||||
end
|
||||
|
||||
local function http_write_json(content)
|
||||
http.prepare_content("application/json")
|
||||
http.write_json(content or {code = 1})
|
||||
end
|
||||
|
||||
function v2ray_users_status()
|
||||
local e = {}
|
||||
e.index = luci.http.formvalue("index")
|
||||
e.status = luci.sys.call(
|
||||
"ps -w| grep -v grep | grep '/var/etc/v2ray_server/" ..
|
||||
luci.http.formvalue("id") .. "' >/dev/null") == 0
|
||||
http_write_json(e)
|
||||
end
|
||||
|
||||
function v2ray_check()
|
||||
local json = v2ray.to_check("")
|
||||
http_write_json(json)
|
||||
end
|
||||
|
||||
function v2ray_update()
|
||||
local json = nil
|
||||
local task = http.formvalue("task")
|
||||
if task == "extract" then
|
||||
json =
|
||||
v2ray.to_extract(http.formvalue("file"), http.formvalue("subfix"))
|
||||
elseif task == "move" then
|
||||
json = v2ray.to_move(http.formvalue("file"))
|
||||
else
|
||||
json = v2ray.to_download(http.formvalue("url"))
|
||||
end
|
||||
|
||||
http_write_json(json)
|
||||
end
|
||||
|
||||
function get_log()
|
||||
luci.http.write(luci.sys.exec(
|
||||
"[ -f '/var/log/v2ray_server/app.log' ] && cat /var/log/v2ray_server/app.log"))
|
||||
end
|
||||
|
||||
function clear_log() luci.sys.call("echo '' > /var/log/v2ray_server/app.log") end
|
||||
|
||||
@ -0,0 +1,91 @@
|
||||
local ucursor = require"luci.model.uci".cursor()
|
||||
local json = require "luci.jsonc"
|
||||
local server_section = arg[1]
|
||||
local server = ucursor:get_all("v2ray_server", server_section)
|
||||
|
||||
local settings = nil
|
||||
|
||||
if server.protocol == "vmess" then
|
||||
if server.VMess_id then
|
||||
local clients = {}
|
||||
for i = 1, #server.VMess_id do
|
||||
clients[i] = {
|
||||
id = server.VMess_id[i],
|
||||
level = tonumber(server.VMess_level),
|
||||
alterId = tonumber(server.VMess_alterId)
|
||||
}
|
||||
end
|
||||
settings = {clients = clients}
|
||||
end
|
||||
elseif server.protocol == "socks" then
|
||||
settings = {
|
||||
auth = "password",
|
||||
accounts = {
|
||||
{user = server.socks_username, pass = server.socks_password}
|
||||
}
|
||||
}
|
||||
elseif server.protocol == "shadowsocks" then
|
||||
settings = {
|
||||
method = server.ss_method,
|
||||
password = server.ss_password,
|
||||
level = tonumber(server.ss_level),
|
||||
network = server.ss_network,
|
||||
ota = (server.ss_ota == '1') and true or false
|
||||
}
|
||||
end
|
||||
|
||||
local v2ray = {
|
||||
log = {
|
||||
-- error = "/var/log/v2ray.log",
|
||||
loglevel = "warning"
|
||||
},
|
||||
-- 传入连接
|
||||
inbound = {
|
||||
listen = (server.bind_local == "1") and "127.0.0.1" or nil,
|
||||
port = tonumber(server.port),
|
||||
protocol = server.protocol,
|
||||
-- 底层传输配置
|
||||
settings = settings,
|
||||
streamSettings = (server.protocol == "vmess") and {
|
||||
network = server.transport,
|
||||
security = (server.tls_enable == '1') and "tls" or "none",
|
||||
tlsSettings = (server.tls_enable == '1') and {
|
||||
-- serverName = (server.tls_serverName),
|
||||
allowInsecure = false,
|
||||
disableSystemRoot = false,
|
||||
certificates = {
|
||||
{
|
||||
certificateFile = server.tls_certificateFile,
|
||||
keyFile = server.tls_keyFile
|
||||
}
|
||||
}
|
||||
} or nil,
|
||||
kcpSettings = (server.transport == "mkcp") and {
|
||||
mtu = tonumber(server.mkcp_mtu),
|
||||
tti = tonumber(server.mkcp_tti),
|
||||
uplinkCapacity = tonumber(server.mkcp_uplinkCapacity),
|
||||
downlinkCapacity = tonumber(server.mkcp_downlinkCapacity),
|
||||
congestion = (server.mkcp_congestion == "1") and true or false,
|
||||
readBufferSize = tonumber(server.mkcp_readBufferSize),
|
||||
writeBufferSize = tonumber(server.mkcp_writeBufferSize),
|
||||
header = {type = server.mkcp_guise}
|
||||
} or nil,
|
||||
wsSettings = (server.transport == "ws") and {
|
||||
headers = (server.ws_host) and {Host = server.ws_host} or nil,
|
||||
path = server.ws_path
|
||||
} or nil,
|
||||
httpSettings = (server.transport == "h2") and
|
||||
{path = server.h2_path, host = server.h2_host} or nil,
|
||||
quicSettings = (server.transport == "quic") and {
|
||||
security = server.quic_security,
|
||||
key = server.quic_key,
|
||||
header = {type = server.quic_guise}
|
||||
} or nil
|
||||
} or nil
|
||||
},
|
||||
-- 传出连接
|
||||
outbound = {protocol = "freedom"},
|
||||
-- 额外传出连接
|
||||
outboundDetour = {{protocol = "blackhole", tag = "blocked"}}
|
||||
}
|
||||
print(json.stringify(v2ray, 1))
|
||||
@ -0,0 +1,326 @@
|
||||
module("luci.model.cbi.v2ray_server.api.v2ray", package.seeall)
|
||||
local fs = require "nixio.fs"
|
||||
local sys = require "luci.sys"
|
||||
local uci = require"luci.model.uci".cursor()
|
||||
local util = require "luci.util"
|
||||
local i18n = require "luci.i18n"
|
||||
local ipkg = require "luci.model.ipkg"
|
||||
|
||||
local v2ray_api =
|
||||
"https://api.github.com/repos/v2ray/v2ray-core/releases/latest"
|
||||
local wget = "/usr/bin/wget"
|
||||
local wget_args = {
|
||||
"--no-check-certificate", "--quiet", "--timeout=100", "--tries=3"
|
||||
}
|
||||
local curl = "/usr/bin/curl"
|
||||
local command_timeout = 300
|
||||
|
||||
local LEDE_BOARD = nil
|
||||
local DISTRIB_TARGET = nil
|
||||
local is_armv7 = false
|
||||
|
||||
local function _unpack(t, i)
|
||||
i = i or 1
|
||||
if t[i] ~= nil then return t[i], _unpack(t, i + 1) end
|
||||
end
|
||||
|
||||
local function exec(cmd, args, writer, timeout)
|
||||
local os = require "os"
|
||||
local nixio = require "nixio"
|
||||
|
||||
local fdi, fdo = nixio.pipe()
|
||||
local pid = nixio.fork()
|
||||
|
||||
if pid > 0 then
|
||||
fdo:close()
|
||||
|
||||
if writer or timeout then
|
||||
local starttime = os.time()
|
||||
while true do
|
||||
if timeout and os.difftime(os.time(), starttime) >= timeout then
|
||||
nixio.kill(pid, nixio.const.SIGTERM)
|
||||
return 1
|
||||
end
|
||||
|
||||
if writer then
|
||||
local buffer = fdi:read(2048)
|
||||
if buffer and #buffer > 0 then
|
||||
writer(buffer)
|
||||
end
|
||||
end
|
||||
|
||||
local wpid, stat, code = nixio.waitpid(pid, "nohang")
|
||||
|
||||
if wpid and stat == "exited" then return code end
|
||||
|
||||
if not writer and timeout then nixio.nanosleep(1) end
|
||||
end
|
||||
else
|
||||
local wpid, stat, code = nixio.waitpid(pid)
|
||||
return wpid and stat == "exited" and code
|
||||
end
|
||||
elseif pid == 0 then
|
||||
nixio.dup(fdo, nixio.stdout)
|
||||
fdi:close()
|
||||
fdo:close()
|
||||
nixio.exece(cmd, args, nil)
|
||||
nixio.stdout:close()
|
||||
os.exit(1)
|
||||
end
|
||||
end
|
||||
|
||||
local function compare_versions(ver1, comp, ver2)
|
||||
local table = table
|
||||
|
||||
local av1 = util.split(ver1, "[%.%-]", nil, true)
|
||||
local av2 = util.split(ver2, "[%.%-]", nil, true)
|
||||
|
||||
local max = table.getn(av1)
|
||||
local n2 = table.getn(av2)
|
||||
if (max < n2) then max = n2 end
|
||||
|
||||
for i = 1, max, 1 do
|
||||
local s1 = av1[i] or ""
|
||||
local s2 = av2[i] or ""
|
||||
|
||||
if comp == "~=" and (s1 ~= s2) then return true end
|
||||
if (comp == "<" or comp == "<=") and (s1 < s2) then return true end
|
||||
if (comp == ">" or comp == ">=") and (s1 > s2) then return true end
|
||||
if (s1 ~= s2) then return false end
|
||||
end
|
||||
|
||||
return not (comp == "<" or comp == ">")
|
||||
end
|
||||
|
||||
local function auto_get_arch()
|
||||
local arch = nixio.uname().machine or ""
|
||||
if fs.access("/usr/lib/os-release") then
|
||||
LEDE_BOARD = sys.exec(
|
||||
"echo -n `grep 'LEDE_BOARD' /usr/lib/os-release | awk -F '[\\042\\047]' '{print $2}'`")
|
||||
end
|
||||
if fs.access("/etc/openwrt_release") then
|
||||
DISTRIB_TARGET = sys.exec(
|
||||
"echo -n `grep 'DISTRIB_TARGET' /etc/openwrt_release | awk -F '[\\042\\047]' '{print $2}'`")
|
||||
end
|
||||
|
||||
if arch == "mips" then
|
||||
if LEDE_BOARD and LEDE_BOARD ~= "" then
|
||||
if string.match(LEDE_BOARD, "ramips") == "ramips" then
|
||||
arch = "ramips"
|
||||
else
|
||||
arch = sys.exec("echo '" .. LEDE_BOARD ..
|
||||
"' | grep -oE 'ramips|ar71xx'")
|
||||
end
|
||||
elseif DISTRIB_TARGET and DISTRIB_TARGET ~= "" then
|
||||
if string.match(DISTRIB_TARGET, "ramips") == "ramips" then
|
||||
arch = "ramips"
|
||||
else
|
||||
arch = sys.exec("echo '" .. DISTRIB_TARGET ..
|
||||
"' | grep -oE 'ramips|ar71xx'")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return util.trim(arch)
|
||||
end
|
||||
|
||||
local function get_file_info(arch)
|
||||
local file_tree = ""
|
||||
local sub_version = ""
|
||||
|
||||
if arch == "x86_64" then
|
||||
file_tree = "64"
|
||||
elseif arch == "aarch64" then
|
||||
file_tree = "arm64"
|
||||
elseif arch == "ramips" then
|
||||
file_tree = "mipsle"
|
||||
elseif arch == "ar71xx" then
|
||||
file_tree = "mips"
|
||||
elseif arch:match("^i[%d]86$") then
|
||||
file_tree = "32"
|
||||
elseif arch:match("^armv[5-8]") then
|
||||
file_tree = "arm"
|
||||
sub_version = arch:match("[5-8]")
|
||||
if LEDE_BOARD and string.match(LEDE_BOARD, "bcm53xx") == "bcm53xx" then
|
||||
sub_version = "5"
|
||||
elseif DISTRIB_TARGET and string.match(DISTRIB_TARGET, "bcm53xx") ==
|
||||
"bcm53xx" then
|
||||
sub_version = "5"
|
||||
end
|
||||
sub_version = "5"
|
||||
if sub_version == "7" then is_armv7 = true end
|
||||
end
|
||||
|
||||
return file_tree, sub_version
|
||||
end
|
||||
|
||||
local function get_api_json(url)
|
||||
local jsonc = require "luci.jsonc"
|
||||
|
||||
local output = {}
|
||||
-- exec(wget, { "-O-", url, _unpack(wget_args) },
|
||||
-- function(chunk) output[#output + 1] = chunk end)
|
||||
-- local json_content = util.trim(table.concat(output))
|
||||
|
||||
local json_content = luci.sys.exec(curl .. " -sL " .. url)
|
||||
|
||||
if json_content == "" then return {} end
|
||||
|
||||
return jsonc.parse(json_content) or {}
|
||||
end
|
||||
|
||||
function get_v2ray_file_path() return "/usr/bin/v2ray" end
|
||||
|
||||
function get_v2ray_version()
|
||||
if get_v2ray_file_path() and get_v2ray_file_path() ~= "" then
|
||||
if fs.access(get_v2ray_file_path() .. "/v2ray") then
|
||||
return luci.sys.exec("echo -n `" .. get_v2ray_file_path() ..
|
||||
"/v2ray -version | awk '{print $2}' | sed -n 1P" ..
|
||||
"`")
|
||||
end
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
function to_check(arch)
|
||||
if not arch or arch == "" then arch = auto_get_arch() end
|
||||
|
||||
local file_tree, sub_version = get_file_info(arch)
|
||||
|
||||
if file_tree == "" then
|
||||
return {
|
||||
code = 1,
|
||||
error = i18n.translate(
|
||||
"Can't determine ARCH, or ARCH not supported.")
|
||||
}
|
||||
end
|
||||
|
||||
local json = get_api_json(v2ray_api)
|
||||
|
||||
if json.tag_name == nil then
|
||||
return {
|
||||
code = 1,
|
||||
error = i18n.translate("Get remote version info failed.")
|
||||
}
|
||||
end
|
||||
|
||||
local remote_version = json.tag_name:match("[^v]+")
|
||||
local needs_update = compare_versions(get_v2ray_version(), "<",
|
||||
remote_version)
|
||||
local html_url, download_url
|
||||
|
||||
if needs_update then
|
||||
html_url = json.html_url
|
||||
for _, v in ipairs(json.assets) do
|
||||
if v.name and v.name:match("linux%-" .. file_tree) then
|
||||
download_url = v.browser_download_url
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if needs_update and not download_url then
|
||||
return {
|
||||
code = 1,
|
||||
now_version = get_v2ray_version(),
|
||||
version = remote_version,
|
||||
html_url = html_url,
|
||||
error = i18n.translate(
|
||||
"New version found, but failed to get new version download url.")
|
||||
}
|
||||
end
|
||||
|
||||
return {
|
||||
code = 0,
|
||||
update = needs_update,
|
||||
now_version = get_v2ray_version(),
|
||||
version = remote_version,
|
||||
url = {html = html_url, download = download_url}
|
||||
}
|
||||
end
|
||||
|
||||
function to_download(url)
|
||||
if not url or url == "" then
|
||||
return {code = 1, error = i18n.translate("Download url is required.")}
|
||||
end
|
||||
|
||||
sys.call("/bin/rm -f /tmp/v2ray_download.*")
|
||||
|
||||
local tmp_file = util.trim(util.exec("mktemp -u -t v2ray_download.XXXXXX"))
|
||||
|
||||
local result = exec(wget, {"-O", tmp_file, url, _unpack(wget_args)}, nil,
|
||||
command_timeout) == 0
|
||||
|
||||
if not result then
|
||||
exec("/bin/rm", {"-f", tmp_file})
|
||||
return {
|
||||
code = 1,
|
||||
error = i18n.translatef("File download failed or timed out: %s", url)
|
||||
}
|
||||
end
|
||||
|
||||
return {code = 0, file = tmp_file}
|
||||
end
|
||||
|
||||
function to_extract(file, subfix)
|
||||
local isinstall_unzip = ipkg.installed("unzip")
|
||||
if isinstall_unzip == nil then
|
||||
ipkg.update()
|
||||
ipkg.install("unzip")
|
||||
end
|
||||
|
||||
if not file or file == "" or not fs.access(file) then
|
||||
return {code = 1, error = i18n.translate("File path required.")}
|
||||
end
|
||||
|
||||
sys.call("/bin/rm -rf /tmp/v2ray_extract.*")
|
||||
local tmp_dir = util.trim(util.exec("mktemp -d -t v2ray_extract.XXXXXX"))
|
||||
|
||||
local output = {}
|
||||
exec("/usr/bin/unzip", {"-o", file, "-d", tmp_dir},
|
||||
function(chunk) output[#output + 1] = chunk end)
|
||||
|
||||
local files = util.split(table.concat(output))
|
||||
|
||||
exec("/bin/rm", {"-f", file})
|
||||
|
||||
return {code = 0, file = tmp_dir}
|
||||
end
|
||||
|
||||
function to_move(file)
|
||||
if not file or file == "" then
|
||||
sys.call("/bin/rm -rf /tmp/v2ray_extract.*")
|
||||
return {code = 1, error = i18n.translate("Client file is required.")}
|
||||
end
|
||||
|
||||
local client_file = get_v2ray_file_path()
|
||||
|
||||
sys.call("mkdir -p " .. client_file)
|
||||
|
||||
if not arch or arch == "" then arch = auto_get_arch() end
|
||||
local file_tree, sub_version = get_file_info(arch)
|
||||
local result = nil
|
||||
if is_armv7 and is_armv7 == true then
|
||||
result = exec("/bin/mv", {
|
||||
"-f", file .. "/v2ray_armv7", file .. "/v2ctl_armv7", client_file
|
||||
}, nil, command_timeout) == 0
|
||||
else
|
||||
result = exec("/bin/mv",
|
||||
{"-f", file .. "/v2ray", file .. "/v2ctl", client_file},
|
||||
nil, command_timeout) == 0
|
||||
end
|
||||
if not result or not fs.access(client_file) then
|
||||
sys.call("/bin/rm -rf /tmp/v2ray_extract.*")
|
||||
return {
|
||||
code = 1,
|
||||
error = i18n.translatef("Can't move new file to path: %s",
|
||||
client_file)
|
||||
}
|
||||
end
|
||||
|
||||
exec("/bin/chmod", {"-R", "755", client_file})
|
||||
|
||||
sys.call("/bin/rm -rf /tmp/v2ray_extract.*")
|
||||
|
||||
return {code = 0}
|
||||
end
|
||||
@ -0,0 +1,220 @@
|
||||
local app_name = "v2ray_server"
|
||||
local d = require "luci.dispatcher"
|
||||
|
||||
local header_type = {"none", "srtp", "utp", "wechat-video", "dtls", "wireguard"}
|
||||
|
||||
map = Map(app_name, "V2ray " .. translate("Server Config"))
|
||||
map.redirect = d.build_url("admin", "vpn", "v2ray_server")
|
||||
|
||||
t = map:section(NamedSection, arg[1], "user", "")
|
||||
t.addremove = false
|
||||
t.dynamic = false
|
||||
|
||||
enable = t:option(Flag, "enable", translate("Enable"))
|
||||
enable.default = "1"
|
||||
enable.rmempty = false
|
||||
|
||||
remarks = t:option(Value, "remarks", translate("Remarks"))
|
||||
remarks.default = translate("Remarks")
|
||||
remarks.rmempty = false
|
||||
|
||||
bind_local = t:option(Flag, "bind_local", translate("Bind Local"), translate(
|
||||
"When selected, it can only be accessed locally,It is recommended to turn on when using reverse proxies."))
|
||||
bind_local.default = "0"
|
||||
bind_local.rmempty = false
|
||||
|
||||
port = t:option(Value, "port", translate("Port"))
|
||||
port.datatype = "port"
|
||||
port.rmempty = false
|
||||
|
||||
protocol = t:option(ListValue, "protocol", translate("Protocol"))
|
||||
protocol:value("vmess", translate("Vmess"))
|
||||
protocol:value("socks", translate("Socks"))
|
||||
protocol:value("shadowsocks", translate("Shadowsocks"))
|
||||
|
||||
socks_username = t:option(Value, "socks_username", translate("User name"))
|
||||
socks_username:depends("protocol", "socks")
|
||||
|
||||
socks_password = t:option(Value, "socks_password", translate("Password"))
|
||||
socks_password.password = true
|
||||
socks_password:depends("protocol", "socks")
|
||||
|
||||
ss_method = t:option(ListValue, "ss_method", translate("Encrypt Method"))
|
||||
ss_method:value("aes-128-cfb")
|
||||
ss_method:value("aes-256-cfb")
|
||||
ss_method:value("aes-128-gcm")
|
||||
ss_method:value("aes-256-gcm")
|
||||
ss_method:value("chacha20")
|
||||
ss_method:value("chacha20-ietf")
|
||||
ss_method:value("chacha20-poly1305")
|
||||
ss_method:value("chacha20-ietf-poly1305")
|
||||
ss_method:depends("protocol", "shadowsocks")
|
||||
|
||||
ss_password = t:option(Value, "ss_password", translate("Password"))
|
||||
ss_password:depends("protocol", "shadowsocks")
|
||||
|
||||
ss_level = t:option(Value, "ss_level", translate("User Level"))
|
||||
ss_level.default = 1
|
||||
ss_level:depends("protocol", "shadowsocks")
|
||||
|
||||
ss_network = t:option(ListValue, "ss_network", translate("Transport"))
|
||||
ss_network.default = "tcp,udp"
|
||||
ss_network:value("tcp", "TCP")
|
||||
ss_network:value("udp", "UDP")
|
||||
ss_network:value("tcp,udp", "TCP,UDP")
|
||||
ss_network:depends("protocol", "shadowsocks")
|
||||
|
||||
ss_ota = t:option(Flag, "ss_ota", translate("OTA"), translate(
|
||||
"When OTA is enabled, V2Ray will reject connections that are not OTA enabled. This option is invalid when using AEAD encryption."))
|
||||
ss_ota.default = "0"
|
||||
ss_ota:depends("protocol", "shadowsocks")
|
||||
|
||||
VMess_id = t:option(DynamicList, "VMess_id", translate("ID"))
|
||||
for i = 1, 3 do
|
||||
local uuid = luci.sys.exec("cat /proc/sys/kernel/random/uuid")
|
||||
VMess_id:value(uuid)
|
||||
end
|
||||
VMess_id:depends("protocol", "vmess")
|
||||
|
||||
VMess_alterId = t:option(Value, "VMess_alterId", translate("Alter ID"))
|
||||
VMess_alterId.default = 16
|
||||
VMess_alterId:depends("protocol", "vmess")
|
||||
|
||||
VMess_level = t:option(Value, "VMess_level", translate("User Level"))
|
||||
VMess_level.default = 1
|
||||
VMess_level:depends("protocol", "vmess")
|
||||
|
||||
transport = t:option(ListValue, "transport", translate("Transport"))
|
||||
transport:value("tcp", "TCP")
|
||||
transport:value("mkcp", "mKCP")
|
||||
transport:value("ws", "WebSocket")
|
||||
transport:value("h2", "HTTP/2")
|
||||
transport:value("quic", "QUIC")
|
||||
transport:depends("protocol", "vmess")
|
||||
|
||||
-- [[ TCP部分 ]]--
|
||||
-- TCP伪装
|
||||
tcp_guise = t:option(ListValue, "tcp_guise", translate("Camouflage Type"))
|
||||
tcp_guise:depends("transport", "tcp")
|
||||
tcp_guise:value("none", "none")
|
||||
tcp_guise:value("http", "http")
|
||||
|
||||
-- HTTP域名
|
||||
tcp_guise_http_host = t:option(DynamicList, "tcp_guise_http_host",
|
||||
translate("HTTP Host"))
|
||||
tcp_guise_http_host:depends("tcp_guise", "http")
|
||||
|
||||
-- HTTP路径
|
||||
tcp_guise_http_path = t:option(DynamicList, "tcp_guise_http_path",
|
||||
translate("HTTP Path"))
|
||||
tcp_guise_http_path:depends("tcp_guise", "http")
|
||||
|
||||
-- [[ mKCP部分 ]]--
|
||||
mkcp_guise = t:option(ListValue, "mkcp_guise", translate("Camouflage Type"),
|
||||
translate(
|
||||
'<br>none: default, no masquerade, data sent is packets with no characteristics.<br>srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).<br>utp: packets disguised as uTP will be recognized as bittorrent downloaded data.<br>wechat-video: packets disguised as WeChat video calls.<br>dtls: disguised as DTLS 1.2 packet.<br>wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)'))
|
||||
for a, t in ipairs(header_type) do mkcp_guise:value(t) end
|
||||
mkcp_guise:depends("transport", "mkcp")
|
||||
|
||||
mkcp_mtu = t:option(Value, "mkcp_mtu", translate("KCP MTU"))
|
||||
mkcp_mtu:depends("transport", "mkcp")
|
||||
|
||||
mkcp_tti = t:option(Value, "mkcp_tti", translate("KCP TTI"))
|
||||
mkcp_tti:depends("transport", "mkcp")
|
||||
|
||||
mkcp_uplinkCapacity = t:option(Value, "mkcp_uplinkCapacity",
|
||||
translate("KCP uplinkCapacity"))
|
||||
mkcp_uplinkCapacity:depends("transport", "mkcp")
|
||||
|
||||
mkcp_downlinkCapacity = t:option(Value, "mkcp_downlinkCapacity",
|
||||
translate("KCP downlinkCapacity"))
|
||||
mkcp_downlinkCapacity:depends("transport", "mkcp")
|
||||
|
||||
mkcp_congestion = t:option(Flag, "mkcp_congestion", translate("KCP Congestion"))
|
||||
mkcp_congestion:depends("transport", "mkcp")
|
||||
|
||||
mkcp_readBufferSize = t:option(Value, "mkcp_readBufferSize",
|
||||
translate("KCP readBufferSize"))
|
||||
mkcp_readBufferSize:depends("transport", "mkcp")
|
||||
|
||||
mkcp_writeBufferSize = t:option(Value, "mkcp_writeBufferSize",
|
||||
translate("KCP writeBufferSize"))
|
||||
mkcp_writeBufferSize:depends("transport", "mkcp")
|
||||
|
||||
-- [[ WebSocket部分 ]]--
|
||||
ws_path = t:option(Value, "ws_path", translate("WebSocket Path"))
|
||||
ws_path:depends("transport", "ws")
|
||||
|
||||
ws_host = t:option(Value, "ws_host", translate("WebSocket Host"))
|
||||
ws_host:depends("transport", "ws")
|
||||
|
||||
-- [[ HTTP/2部分 ]]--
|
||||
h2_path = t:option(Value, "h2_path", translate("HTTP/2 Path"))
|
||||
h2_path:depends("transport", "h2")
|
||||
|
||||
h2_host = t:option(DynamicList, "h2_host", translate("HTTP/2 Host"),
|
||||
translate("Camouflage Domain,you can not fill in"))
|
||||
h2_host:depends("transport", "h2")
|
||||
|
||||
-- [[ QUIC部分 ]]--
|
||||
quic_security =
|
||||
t:option(ListValue, "quic_security", translate("Encrypt Method"))
|
||||
quic_security:value("none")
|
||||
quic_security:value("aes-128-gcm")
|
||||
quic_security:value("chacha20-poly1305")
|
||||
quic_security:depends("transport", "quic")
|
||||
|
||||
quic_key = t:option(Value, "quic_key",
|
||||
translate("Encrypt Method") .. translate("Key"))
|
||||
quic_key:depends("transport", "quic")
|
||||
|
||||
quic_guise = t:option(ListValue, "quic_guise", translate("Camouflage Type"))
|
||||
for a, t in ipairs(header_type) do quic_guise:value(t) end
|
||||
quic_guise:depends("transport", "quic")
|
||||
|
||||
-- [[ TLS部分 ]] --
|
||||
tls_enable = t:option(Flag, "tls_enable", translate("Use HTTPS"))
|
||||
tls_enable:depends("transport", "ws")
|
||||
tls_enable:depends("transport", "h2")
|
||||
tls_enable.default = "1"
|
||||
tls_enable.rmempty = false
|
||||
|
||||
-- tls_serverName = t:option(Value, "tls_serverName", translate("Domain"))
|
||||
-- tls_serverName:depends("transport", "ws")
|
||||
-- tls_serverName:depends("transport", "h2")
|
||||
|
||||
tls_certificateFile = t:option(Value, "tls_certificateFile",
|
||||
translate("Public key absolute path"),
|
||||
translate("as:") .. "/etc/ssl/fullchain.pem")
|
||||
tls_certificateFile:depends("tls_enable", 1)
|
||||
|
||||
tls_keyFile = t:option(Value, "tls_keyFile",
|
||||
translate("Private key absolute path"),
|
||||
translate("as:") .. "/etc/ssl/private.key")
|
||||
tls_keyFile:depends("tls_enable", 1)
|
||||
|
||||
function rmempty_restore()
|
||||
VMess_id.rmempty = true
|
||||
VMess_alterId.rmempty = true
|
||||
socks_username.rmempty = true
|
||||
socks_password.rmempty = true
|
||||
ss_password.rmempty = true
|
||||
ss_ota.rmempty = true
|
||||
end
|
||||
|
||||
protocol.validate = function(self, value)
|
||||
rmempty_restore()
|
||||
if value == "vmess" then
|
||||
VMess_id.rmempty = false
|
||||
VMess_alterId.rmempty = false
|
||||
elseif value == "socks" then
|
||||
socks_username.rmempty = true
|
||||
socks_password.rmempty = true
|
||||
elseif value == "shadowsocks" then
|
||||
ss_password.rmempty = false
|
||||
ss_ota.rmempty = false
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
return map
|
||||
@ -0,0 +1,105 @@
|
||||
local i = require "luci.dispatcher"
|
||||
local e = require "nixio.fs"
|
||||
local e = require "luci.sys"
|
||||
local e = luci.model.uci.cursor()
|
||||
local o = "v2ray_server"
|
||||
|
||||
m = Map(o, translate("V2ray Server"))
|
||||
|
||||
t = m:section(TypedSection, "global", translate("Global Settings"))
|
||||
t.anonymous = true
|
||||
t.addremove = false
|
||||
e = t:option(Flag, "enable", translate("Enable"))
|
||||
e.rmempty = false
|
||||
t:append(Template("v2ray_server/v2ray"))
|
||||
|
||||
t = m:section(TypedSection, "user", translate("Users Manager"))
|
||||
t.anonymous = true
|
||||
t.addremove = true
|
||||
t.template = "cbi/tblsection"
|
||||
t.extedit = i.build_url("admin", "vpn", o, "config", "%s")
|
||||
function t.create(t, e)
|
||||
local e = TypedSection.create(t, e)
|
||||
luci.http.redirect(i.build_url("admin", "vpn", o, "config", e))
|
||||
end
|
||||
function t.remove(t, a)
|
||||
t.map.proceed = true
|
||||
t.map:del(a)
|
||||
luci.http.redirect(i.build_url("admin", "vpn", o))
|
||||
end
|
||||
e = t:option(Flag, "enable", translate("Enable"))
|
||||
e.width = "5%"
|
||||
e.rmempty = false
|
||||
e = t:option(DummyValue, "status", translate("Status"))
|
||||
e.template = "v2ray_server/users_status"
|
||||
e.value = translate("Collecting data...")
|
||||
e = t:option(DummyValue, "remarks", translate("Remarks"))
|
||||
e.width = "15%"
|
||||
e = t:option(DummyValue, "port", translate("Port"))
|
||||
e.width = "10%"
|
||||
e = t:option(DummyValue, "protocol", translate("Protocol"))
|
||||
e.width = "15%"
|
||||
e.cfgvalue = function(self, section)
|
||||
local str = "未知"
|
||||
local protocol = m:get(section, "protocol") or ""
|
||||
if protocol ~= "" then str = (protocol:gsub("^%l", string.upper)) end
|
||||
return str
|
||||
end
|
||||
e = t:option(DummyValue, "transport", translate("Transport"))
|
||||
e.width = "10%"
|
||||
e.cfgvalue = function(self, section)
|
||||
local t = "未知"
|
||||
local b = ""
|
||||
local protocol = m:get(section, "protocol") or ""
|
||||
if protocol == "vmess" then
|
||||
b = "transport"
|
||||
elseif protocol == "shadowsocks" then
|
||||
b = "ss_network"
|
||||
end
|
||||
local a = m:get(section, b) or ""
|
||||
if a == "tcp" then
|
||||
t = "TCP"
|
||||
elseif a == "udp" then
|
||||
t = "UDP"
|
||||
elseif a == "tcp,udp" then
|
||||
t = "TCP,UDP"
|
||||
elseif a == "mkcp" then
|
||||
t = "mKCP"
|
||||
elseif a == "ws" then
|
||||
t = "WebSocket"
|
||||
elseif a == "h2" then
|
||||
t = "HTTP/2"
|
||||
elseif a == "quic" then
|
||||
t = "QUIC"
|
||||
else
|
||||
t = "TCP,UDP"
|
||||
end
|
||||
return t
|
||||
end
|
||||
e = t:option(DummyValue, "password", translate("Password"))
|
||||
e.width = "30%"
|
||||
e.cfgvalue = function(self, section)
|
||||
local e = ""
|
||||
local protocol = m:get(section, "protocol") or ""
|
||||
if protocol == "vmess" then
|
||||
e = "VMess_id"
|
||||
elseif protocol == "shadowsocks" then
|
||||
e = "ss_password"
|
||||
elseif protocol == "socks" then
|
||||
e = "socks_password"
|
||||
end
|
||||
local e = m:get(section, e) or ""
|
||||
local t = ""
|
||||
if type(e) == "table" then
|
||||
for a = 1, #e do t = t .. e[a] end
|
||||
else
|
||||
t = e
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
m:append(Template("v2ray_server/log"))
|
||||
|
||||
m:append(Template("v2ray_server/users_list_status"))
|
||||
return m
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
function clear_log(btn) {
|
||||
XHR.get('<%=url([[admin]], [[vpn]], [[v2ray_server]], [[clear_log]])%>', null,
|
||||
function(x, data) {
|
||||
if(x && x.status == 200) {
|
||||
var log_textarea = document.getElementById('log_textarea');
|
||||
log_textarea.innerHTML = "";
|
||||
log_textarea.scrollTop = log_textarea.scrollHeight;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
XHR.poll(3, '<%=url([[admin]], [[vpn]], [[v2ray_server]], [[get_log]])%>', null,
|
||||
function(x, data) {
|
||||
if(x && x.status == 200) {
|
||||
var log_textarea = document.getElementById('log_textarea');
|
||||
log_textarea.innerHTML = x.responseText;
|
||||
log_textarea.scrollTop = log_textarea.scrollHeight;
|
||||
}
|
||||
}
|
||||
);
|
||||
//]]>
|
||||
</script>
|
||||
<fieldset class="cbi-section" id="_log_fieldset">
|
||||
<legend>
|
||||
<%:Logs%>
|
||||
</legend>
|
||||
<input class="cbi-button cbi-input-remove" type="button" onclick="clear_log()" value="<%:Clear logs%>">
|
||||
<textarea id="log_textarea" class="cbi-input-textarea" style="width: 100%;margin-top: 10px;" data-update="change" rows="20" wrap="off" readonly="readonly"></textarea>
|
||||
</fieldset>
|
||||
@ -0,0 +1,23 @@
|
||||
<%
|
||||
local dsp = require "luci.dispatcher"
|
||||
-%>
|
||||
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
var v2ray_users_status = document.getElementsByClassName('v2ray_users_status');
|
||||
for(var i = 0; i < v2ray_users_status.length; i++) {
|
||||
var id = v2ray_users_status[i].parentElement.parentElement.parentElement.id;
|
||||
id = id.substr(id.lastIndexOf("-") + 1);
|
||||
XHR.poll(1,'<%=dsp.build_url("admin/vpn/v2ray_server/users_status")%>', {
|
||||
index: i,
|
||||
id: id
|
||||
},
|
||||
function(x, result) {
|
||||
v2ray_users_status[result.index].setAttribute("style","font-weight:bold;");
|
||||
v2ray_users_status[result.index].setAttribute("color",result.status ? "green":"red");
|
||||
v2ray_users_status[result.index].innerHTML = (result.status ? '✓' : 'X');
|
||||
}
|
||||
);
|
||||
}
|
||||
//]]>
|
||||
</script>
|
||||
@ -0,0 +1,3 @@
|
||||
<%+cbi/valueheader%>
|
||||
<font class="v2ray_users_status" hint="<%=self:cfgvalue(section)%>">--</font>
|
||||
<%+cbi/valuefooter%>
|
||||
@ -0,0 +1,182 @@
|
||||
<%
|
||||
local v2ray_version=luci.sys.exec("/usr/bin/v2ray/v2ray -version | awk '{print $2}' | sed -n 1P")
|
||||
local dsp = require "luci.dispatcher"
|
||||
-%>
|
||||
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
var v2rayInfo;
|
||||
var tokenStr = '<%=token%>';
|
||||
var noUpdateText = '<%:已是最新版本%>';
|
||||
var updateSuccessText = '<%:更新成功.%>';
|
||||
var clickToUpdateText = '<%:点击更新%>';
|
||||
var inProgressText = '<%:正在更新...%>';
|
||||
var unexpectedErrorText = '<%:意外错误.%>';
|
||||
var updateInProgressNotice = '<%:正在更新,你确认要关闭吗?%>';
|
||||
|
||||
window.onload = function() {
|
||||
var v2rayCheckBtn = document.getElementById('_v2ray-check_btn');
|
||||
var v2rayDetailElm = document.getElementById('_v2ray-check_btn-detail');
|
||||
};
|
||||
|
||||
function addPageNotice_v2ray() {
|
||||
window.onbeforeunload = function(e) {
|
||||
e.returnValue = updateInProgressNotice;
|
||||
return updateInProgressNotice;
|
||||
};
|
||||
}
|
||||
|
||||
function removePageNotice_v2ray() {
|
||||
window.onbeforeunload = undefined;
|
||||
}
|
||||
|
||||
function onUpdateSuccess_v2ray(btn) {
|
||||
alert(updateSuccessText);
|
||||
|
||||
if(btn) {
|
||||
btn.value = updateSuccessText;
|
||||
btn.placeholder = updateSuccessText;
|
||||
btn.disabled = true;
|
||||
}
|
||||
|
||||
window.setTimeout(function() {
|
||||
window.location.reload();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function onRequestError_v2ray(btn, errorMessage) {
|
||||
btn.disabled = false;
|
||||
btn.value = btn.placeholder;
|
||||
|
||||
if(errorMessage) {
|
||||
alert(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
function doAjaxGet(url, data, onResult) {
|
||||
new XHR().get(url, data, function(_, json) {
|
||||
var resultJson = json || {
|
||||
'code': 1,
|
||||
'error': unexpectedErrorText
|
||||
};
|
||||
|
||||
if(typeof onResult === 'function') {
|
||||
onResult(resultJson);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function onBtnClick_v2ray(btn) {
|
||||
if(v2rayInfo === undefined) {
|
||||
checkUpdate_v2ray(btn);
|
||||
} else {
|
||||
doUpdate_v2ray(btn);
|
||||
}
|
||||
}
|
||||
|
||||
function checkUpdate_v2ray(btn) {
|
||||
btn.disabled = true;
|
||||
btn.value = inProgressText;
|
||||
|
||||
addPageNotice_v2ray();
|
||||
|
||||
var ckeckDetailElm = document.getElementById(btn.id + '-detail');
|
||||
|
||||
doAjaxGet('<%=dsp.build_url("admin/vpn/v2ray_server/check")%>', {
|
||||
token: tokenStr,
|
||||
arch: ''
|
||||
}, function(json) {
|
||||
removePageNotice_v2ray();
|
||||
|
||||
if(json.code) {
|
||||
v2rayInfo = undefined;
|
||||
onRequestError_v2ray(btn, json.error);
|
||||
} else {
|
||||
if(json.update) {
|
||||
v2rayInfo = json;
|
||||
btn.disabled = false;
|
||||
btn.value = clickToUpdateText;
|
||||
btn.placeholder = clickToUpdateText;
|
||||
|
||||
if(ckeckDetailElm) {
|
||||
var urlNode = '';
|
||||
if(json.version) {
|
||||
urlNode = '<em style="color:red;">最新版本号:' + json.version + '</em>';
|
||||
if(json.url && json.url.html) {
|
||||
urlNode = '<a href="' + json.url.html + '" target="_blank">' + urlNode + '</a>';
|
||||
}
|
||||
}
|
||||
ckeckDetailElm.innerHTML = urlNode;
|
||||
}
|
||||
} else {
|
||||
btn.disabled = true;
|
||||
btn.value = noUpdateText;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function doUpdate_v2ray(btn) {
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:下载中...%>';
|
||||
|
||||
addPageNotice_v2ray();
|
||||
|
||||
var v2rayUpdateUrl = '<%=dsp.build_url("admin/vpn/v2ray_server/update")%>';
|
||||
// Download file
|
||||
doAjaxGet(v2rayUpdateUrl, {
|
||||
token: tokenStr,
|
||||
url: v2rayInfo ? v2rayInfo.url.download : ''
|
||||
}, function(json) {
|
||||
if(json.code) {
|
||||
removePageNotice_v2ray();
|
||||
onRequestError_v2ray(btn, json.error);
|
||||
} else {
|
||||
btn.value = '<%:解压中...%>';
|
||||
|
||||
// Extract file
|
||||
doAjaxGet(v2rayUpdateUrl, {
|
||||
token: tokenStr,
|
||||
task: 'extract',
|
||||
file: json.file,
|
||||
subfix: v2rayInfo ? v2rayInfo.type : ''
|
||||
}, function(json) {
|
||||
if(json.code) {
|
||||
removePageNotice_v2ray();
|
||||
onRequestError_v2ray(btn, json.error);
|
||||
} else {
|
||||
btn.value = '<%:移动中...%>';
|
||||
|
||||
// Move file to target dir
|
||||
doAjaxGet(v2rayUpdateUrl, {
|
||||
token: tokenStr,
|
||||
task: 'move',
|
||||
file: json.file
|
||||
}, function(json) {
|
||||
removePageNotice_v2ray();
|
||||
if(json.code) {
|
||||
onRequestError_v2ray(btn, json.error);
|
||||
} else {
|
||||
onUpdateSuccess_v2ray(btn);
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
<div class="cbi-value">
|
||||
<label class="cbi-value-title">V2ray
|
||||
<%:Version%>
|
||||
</label>
|
||||
<div class="cbi-value-field">
|
||||
<div class="cbi-value-description">
|
||||
<span>【 <%=v2ray_version%>】</span>
|
||||
<input class="cbi-button cbi-input-apply" type="submit" id="_v2ray-check_btn" onclick="onBtnClick_v2ray(this);" value="<%:Manually update%>">
|
||||
<span id="_v2ray-check_btn-detail"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
137
package/lienol/luci-app-v2ray-server/po/zh-cn/v2ray_server.po
Normal file
@ -0,0 +1,137 @@
|
||||
msgid "V2ray Server"
|
||||
msgstr "V2ray 服务器"
|
||||
|
||||
msgid "Global Settings"
|
||||
msgstr "全局设置"
|
||||
|
||||
msgid "Caddy path"
|
||||
msgstr "Caddy 路径"
|
||||
|
||||
msgid "if you want to run from memory, change the path, such as /tmp/caddy, Then save the application and update it manually."
|
||||
msgstr "如果你希望从内存中运行,请更改路径,例如/tmp/caddy,然后保存应用后,再手动更新。"
|
||||
|
||||
msgid "Server Config"
|
||||
msgstr "服务器配置"
|
||||
|
||||
msgid "Users Manager"
|
||||
msgstr "用户管理"
|
||||
|
||||
msgid "Remarks"
|
||||
msgstr "备注"
|
||||
|
||||
msgid "Bind Local"
|
||||
msgstr "本机监听"
|
||||
|
||||
msgid "When selected, it can only be accessed locally,It is recommended to turn on when using reverse proxies."
|
||||
msgstr "当勾选时,只能由本机访问此端口,当开启反向代理时建议勾选此项。"
|
||||
|
||||
msgid "Port"
|
||||
msgstr "端口"
|
||||
|
||||
msgid "Password"
|
||||
msgstr "密码"
|
||||
|
||||
msgid "Protocol"
|
||||
msgstr "协议"
|
||||
|
||||
msgid "Null"
|
||||
msgstr "无"
|
||||
|
||||
msgid "Alter ID"
|
||||
msgstr "额外ID(AlterID)"
|
||||
|
||||
msgid "User Level"
|
||||
msgstr "用户等级(Level)"
|
||||
|
||||
msgid "When OTA is enabled, V2Ray will reject connections that are not OTA enabled. This option is invalid when using AEAD encryption."
|
||||
msgstr "开启 OTA 后,V2Ray 会拒绝未启用 OTA 的连接。当使用 AEAD 加密时,该选项无效。"
|
||||
|
||||
msgid "Transport"
|
||||
msgstr "传输方式"
|
||||
|
||||
msgid "Camouflage Type"
|
||||
msgstr "伪装类型"
|
||||
|
||||
msgid "Camouflage Domain,you can not fill in"
|
||||
msgstr "伪装域名,也可以不填写"
|
||||
|
||||
msgid "Reverse Proxy"
|
||||
msgstr "反向代理"
|
||||
|
||||
msgid "Reverse Proxy Type"
|
||||
msgstr "反向代理类型"
|
||||
|
||||
msgid "can not has conflict"
|
||||
msgstr "请不要冲突"
|
||||
|
||||
msgid "Use HTTPS"
|
||||
msgstr "使用HTTPS"
|
||||
|
||||
msgid "TLS Settings"
|
||||
msgstr "TLS配置"
|
||||
|
||||
msgid "Nginx does not support HTTP/2 reverse proxies"
|
||||
msgstr "Nginx 不支持HTTP/2反向代理"
|
||||
|
||||
msgid "as:"
|
||||
msgstr "如:"
|
||||
|
||||
msgid "Public key absolute path"
|
||||
msgstr "公钥文件绝对路径"
|
||||
|
||||
msgid "Private key absolute path"
|
||||
msgstr "私钥文件绝对路径"
|
||||
|
||||
msgid "<br>none: default, no masquerade, data sent is packets with no characteristics.<br>srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).<br>utp: packets disguised as uTP will be recognized as bittorrent downloaded data.<br>wechat-video: packets disguised as WeChat video calls.<br>dtls: disguised as DTLS 1.2 packet.<br>wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)"
|
||||
msgstr "<br>none:默认值,不进行伪装,发送的数据是没有特征的数据包。<br>srtp:伪装成 SRTP 数据包,会被识别为视频通话数据(如 FaceTime)。<br>utp:伪装成 uTP 数据包,会被识别为 BT 下载数据。<br>wechat-video:伪装成微信视频通话的数据包。<br>dtls:伪装成 DTLS 1.2 数据包。<br>wireguard:伪装成 WireGuard 数据包。(并不是真正的 WireGuard 协议)"
|
||||
|
||||
msgid "Logs"
|
||||
msgstr "日志"
|
||||
|
||||
msgid "Clear logs"
|
||||
msgstr "清空日志"
|
||||
|
||||
msgid "Can't determine ARCH, or ARCH not supported."
|
||||
msgstr "无法确认ARCH架构,或是不支持。"
|
||||
|
||||
msgid "Get remote version info failed."
|
||||
msgstr "获取远程版本信息失败。"
|
||||
|
||||
msgid "New version found, but failed to get new version download url."
|
||||
msgstr "发现新版本,但未能获得新版本的下载地址。"
|
||||
|
||||
msgid "Download url is required."
|
||||
msgstr "请指定下载地址。"
|
||||
|
||||
msgid "File download failed or timed out: %s"
|
||||
msgstr "文件下载失败或超时:%s"
|
||||
|
||||
msgid "File path required."
|
||||
msgstr "请指定文件路径。"
|
||||
|
||||
msgid "Can't find client in file: %s"
|
||||
msgstr "无法在文件中找到客户端:%s"
|
||||
|
||||
msgid "Client file is required."
|
||||
msgstr "请指定客户端文件。"
|
||||
|
||||
msgid "The client file is not suitable for current device."
|
||||
msgstr "客户端文件不适合当前设备。"
|
||||
|
||||
msgid "Can't move new file to path: %s"
|
||||
msgstr "无法移动新文件到:%s"
|
||||
|
||||
msgid "Enabled"
|
||||
msgstr "启用"
|
||||
|
||||
msgid "Status"
|
||||
msgstr "状态"
|
||||
|
||||
msgid "Current Condition"
|
||||
msgstr "当前状态"
|
||||
|
||||
msgid "NOT RUNNING"
|
||||
msgstr "未运行"
|
||||
|
||||
msgid "RUNNING"
|
||||
msgstr "运行中"
|
||||
@ -0,0 +1,45 @@
|
||||
|
||||
config global
|
||||
option enable '0'
|
||||
|
||||
config user
|
||||
option enable '1'
|
||||
option remarks '备注222'
|
||||
option bind_local '0'
|
||||
option protocol 'vmess'
|
||||
list VMess_id 'fd00927a-b0c2-4629-aef7-d9ff15a9d722'
|
||||
option VMess_alterId '16'
|
||||
option VMess_level '1'
|
||||
option transport 'tcp'
|
||||
option tcp_guise 'none'
|
||||
option port '12366'
|
||||
|
||||
config user
|
||||
option enable '1'
|
||||
option remarks 'WebsocketDemo'
|
||||
option bind_local '0'
|
||||
option protocol 'vmess'
|
||||
option VMess_alterId '16'
|
||||
option VMess_level '1'
|
||||
list VMess_id 'fd00927a-b0c2-4629-aef7-d9ff15a9d722'
|
||||
option transport 'ws'
|
||||
option ws_path '/websocket'
|
||||
option tls_enable '1'
|
||||
option tls_certificateFile '/etc/config/ssl/fullchain.pem'
|
||||
option tls_keyFile '/etc/config/ssl/private.key'
|
||||
option port '30010'
|
||||
|
||||
config user
|
||||
option enable '1'
|
||||
option remarks 'H2Demo'
|
||||
option bind_local '0'
|
||||
option protocol 'vmess'
|
||||
option VMess_alterId '16'
|
||||
option VMess_level '1'
|
||||
list VMess_id 'fd00927a-b0c2-4629-aef7-d9ff15a9d722'
|
||||
option tls_enable '1'
|
||||
option tls_certificateFile '/etc/config/ssl/fullchain.pem'
|
||||
option tls_keyFile '/etc/config/ssl/private.key'
|
||||
option transport 'h2'
|
||||
option h2_path '/h2'
|
||||
option port '30011'
|
||||
59
package/lienol/luci-app-v2ray-server/root/etc/init.d/v2ray_server
Executable file
@ -0,0 +1,59 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2018-2020 Lienol <lawlienol@gmail.com>
|
||||
|
||||
START=99
|
||||
|
||||
CONFIG=v2ray_server
|
||||
CONFIG_PATH=/var/etc/$CONFIG
|
||||
LOG_PATH=/var/log/$CONFIG
|
||||
LOG_APP_FILE=$LOG_PATH/app.log
|
||||
|
||||
echolog() {
|
||||
echo -e "$(date "+%Y-%m-%d %H:%M:%S"): $1" >> $LOG_APP_FILE
|
||||
}
|
||||
|
||||
gen_v2ray_config_file() {
|
||||
config_get enable $1 enable
|
||||
[ "$enable" = "0" ] && return 0
|
||||
config_get remarks $1 remarks
|
||||
config_get port $1 port
|
||||
config_get transport $1 transport
|
||||
lua /usr/lib/lua/luci/model/cbi/v2ray_server/api/genv2rayconfig.lua $1 > $CONFIG_PATH/$1.json
|
||||
echolog "$remarks $port 生成并运行 V2ray 配置文件 - $CONFIG_PATH/$1.json"
|
||||
/usr/bin/v2ray/v2ray -config $CONFIG_PATH/$1.json >/dev/null 2>&1 &
|
||||
}
|
||||
|
||||
start_v2ray_server() {
|
||||
mkdir -p $CONFIG_PATH $LOG_PATH
|
||||
touch $LOG_APP_FILE
|
||||
caddy_file=$(uci get $CONFIG.@global[0].caddy_file)
|
||||
config_foreach gen_v2ray_config_file "user"
|
||||
fw3 reload >/dev/null 2>&1 &
|
||||
}
|
||||
|
||||
stop_v2ray_server() {
|
||||
fw3 reload >/dev/null 2>&1 &
|
||||
ps -w | grep "$CONFIG_PATH/" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 &
|
||||
rm -rf $CONFIG_PATH
|
||||
rm -rf $LOG_PATH
|
||||
}
|
||||
|
||||
start() {
|
||||
config_load $CONFIG
|
||||
enable=$(uci get $CONFIG.@global[0].enable)
|
||||
if [ "$enable" = "0" ];then
|
||||
stop_v2ray_server
|
||||
else
|
||||
start_v2ray_server
|
||||
fi
|
||||
}
|
||||
|
||||
stop() {
|
||||
stop_v2ray_server
|
||||
}
|
||||
|
||||
restart() {
|
||||
stop
|
||||
sleep 1
|
||||
start
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete firewall.v2ray_server
|
||||
set firewall.v2ray_server=include
|
||||
set firewall.v2ray_server.type=script
|
||||
set firewall.v2ray_server.path=/usr/share/v2ray_server/firewall.include
|
||||
set firewall.v2ray_server.reload=1
|
||||
EOF
|
||||
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete ucitrack.@v2ray_server[-1]
|
||||
add ucitrack v2ray_server
|
||||
set ucitrack.@v2ray_server[-1].init=v2ray_server
|
||||
commit ucitrack
|
||||
EOF
|
||||
|
||||
chmod a+x /usr/share/v2ray_server/* >/dev/null 2>&1
|
||||
|
||||
rm -f /tmp/luci-indexcache
|
||||
exit 0
|
||||
@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $IPKG_INSTROOT/lib/functions.sh
|
||||
. $IPKG_INSTROOT/lib/functions/service.sh
|
||||
|
||||
gen_user_iptables() {
|
||||
config_get enable $1 enable
|
||||
[ "$enable" = "0" ] && return 0
|
||||
config_get remarks $1 remarks
|
||||
config_get bind_local $1 bind_local
|
||||
config_get port $1 port
|
||||
dport=$port
|
||||
[ "$bind_local" != "1" ] && {
|
||||
iptables -A V2RAY-SERVER -p tcp --dport $dport -m comment --comment "$remarks" -j ACCEPT
|
||||
iptables -A V2RAY-SERVER -p udp --dport $dport -m comment --comment "$remarks" -j ACCEPT
|
||||
}
|
||||
}
|
||||
|
||||
iptables -F V2RAY-SERVER 2>/dev/null
|
||||
iptables -D INPUT -j V2RAY-SERVER 2>/dev/null
|
||||
iptables -X V2RAY-SERVER 2>/dev/null
|
||||
|
||||
enable=$(uci get v2ray_server.@global[0].enable)
|
||||
if [ $enable -eq 1 ]; then
|
||||
iptables -N V2RAY-SERVER
|
||||
iptables -I INPUT -j V2RAY-SERVER
|
||||
config_load v2ray_server
|
||||
config_foreach gen_user_iptables "user"
|
||||
fi
|
||||
0
package/lienol/luci-theme-argon-mc/root/etc/uci-defaults/30_luci-theme-argon-mc
Normal file → Executable file
16
package/lienol/luci-theme-argon-mod/Makefile
Normal file
@ -0,0 +1,16 @@
|
||||
# Copyright (C) 2008-2019 Jerrykuku
|
||||
# Copyright (C) 2019 Lienol
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=Argon Mod Theme
|
||||
LUCI_DEPENDS:=
|
||||
PKG_VERSION:=1.5
|
||||
PKG_RELEASE:=08-20191221
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata>Generated by IcoMoon</metadata>
|
||||
<defs>
|
||||
<font id="icomoon" horiz-adv-x="1024">
|
||||
<font-face units-per-em="1024" ascent="960" descent="-64" />
|
||||
<missing-glyph horiz-adv-x="1024" />
|
||||
<glyph unicode=" " horiz-adv-x="512" d="" />
|
||||
<glyph unicode="" glyph-name="expand_less" d="M512 596.667l256-256-60-60-196 196-196-196-60 60z" />
|
||||
<glyph unicode="" glyph-name="expand_more" d="M708 572.667l60-60-256-256-256 256 60 60 196-196z" />
|
||||
<glyph unicode="" glyph-name="menu" d="M128 682.667h768v-86h-768v86zM128 384.667v84h768v-84h-768zM128 170.667v86h768v-86h-768z" />
|
||||
<glyph unicode="" glyph-name="favorite" d="M512 28.667l-62 56q-106 96-154 142t-107 114-81 123-22 113q0 98 67 166t167 68q116 0 192-90 76 90 192 90 100 0 167-68t67-166q0-78-52-162t-113-146-199-186z" />
|
||||
<glyph unicode="" glyph-name="spinner9" d="M512 960c-278.748 0-505.458-222.762-511.848-499.974 5.92 241.864 189.832 435.974 415.848 435.974 229.75 0 416-200.576 416-448 0-53.020 42.98-96 96-96s96 42.98 96 96c0 282.77-229.23 512-512 512zM512-64c278.748 0 505.458 222.762 511.848 499.974-5.92-241.864-189.832-435.974-415.848-435.974-229.75 0-416 200.576-416 448 0 53.020-42.98 96-96 96s-96-42.98-96-96c0-282.77 229.23-512 512-512z" />
|
||||
<glyph unicode="" glyph-name="question-circle" horiz-adv-x="878" d="M512 164.571v109.714q0 8-5.143 13.143t-13.143 5.143h-109.714q-8 0-13.143-5.143t-5.143-13.143v-109.714q0-8 5.143-13.143t13.143-5.143h109.714q8 0 13.143 5.143t5.143 13.143zM658.286 548.571q0 50.286-31.714 93.143t-79.143 66.286-97.143 23.429q-138.857 0-212-121.714-8.571-13.714 4.571-24l75.429-57.143q4-3.429 10.857-3.429 9.143 0 14.286 6.857 30.286 38.857 49.143 52.571 19.429 13.714 49.143 13.714 27.429 0 48.857-14.857t21.429-33.714q0-21.714-11.429-34.857t-38.857-25.714q-36-16-66-49.429t-30-71.714v-20.571q0-8 5.143-13.143t13.143-5.143h109.714q8 0 13.143 5.143t5.143 13.143q0 10.857 12.286 28.286t31.143 28.286q18.286 10.286 28 16.286t26.286 20 25.429 27.429 16 34.571 7.143 46.286zM877.714 438.857q0-119.429-58.857-220.286t-159.714-159.714-220.286-58.857-220.286 58.857-159.714 159.714-58.857 220.286 58.857 220.286 159.714 159.714 220.286 58.857 220.286-58.857 159.714-159.714 58.857-220.286z" />
|
||||
</font></defs></svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 24 KiB |
6
package/lienol/luci-theme-argon-mod/htdocs/luci-static/argon_dark/js/jquery.min.js
vendored
Normal file
@ -0,0 +1,251 @@
|
||||
/**
|
||||
* Material is a clean HTML5 theme for LuCI. It is based on luci-theme-bootstrap and MUI
|
||||
*
|
||||
* luci-theme-material
|
||||
* Copyright 2015 Lutty Yang <lutty@wcan.in>
|
||||
*
|
||||
* Have a bug? Please create an issue here on GitHub!
|
||||
* https://github.com/LuttyYang/luci-theme-material/issues
|
||||
*
|
||||
* luci-theme-bootstrap:
|
||||
* Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
* Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
|
||||
* Copyright 2012 David Menting <david@nut-bolt.nl>
|
||||
*
|
||||
* MUI:
|
||||
* https://github.com/muicss/mui
|
||||
*
|
||||
* Licensed to the public under the Apache License 2.0
|
||||
*/
|
||||
|
||||
|
||||
(function ($) {
|
||||
$(".main > .loading").fadeOut();
|
||||
|
||||
/**
|
||||
* trim text, Remove spaces, wrap
|
||||
* @param text
|
||||
* @returns {string}
|
||||
*/
|
||||
function trimText(text) {
|
||||
return text.replace(/[ \t\n\r]+/g, " ");
|
||||
}
|
||||
|
||||
|
||||
var lastNode = undefined;
|
||||
var mainNodeName = undefined;
|
||||
|
||||
var nodeUrl = "";
|
||||
(function(node){
|
||||
if (node[0] == "admin"){
|
||||
luciLocation = [node[1], node[2]];
|
||||
}else{
|
||||
luciLocation = node;
|
||||
}
|
||||
|
||||
for(var i in luciLocation){
|
||||
nodeUrl += luciLocation[i];
|
||||
if (i != luciLocation.length - 1){
|
||||
nodeUrl += "/";
|
||||
}
|
||||
}
|
||||
})(luciLocation);
|
||||
|
||||
/**
|
||||
* get the current node by Burl (primary)
|
||||
* @returns {boolean} success?
|
||||
*/
|
||||
function getCurrentNodeByUrl() {
|
||||
var ret = false;
|
||||
if (!$('body').hasClass('logged-in')) {
|
||||
luciLocation = ["Main", "Login"];
|
||||
return true;
|
||||
}
|
||||
|
||||
$(".main > .main-left > .nav > .slide > .menu").each(function () {
|
||||
var ulNode = $(this);
|
||||
ulNode.next().find("a").each(function () {
|
||||
var that = $(this);
|
||||
var href = that.attr("href");
|
||||
|
||||
if (href.indexOf(nodeUrl) != -1) {
|
||||
ulNode.click();
|
||||
ulNode.next(".slide-menu").stop(true, true);
|
||||
lastNode = that.parent();
|
||||
lastNode.addClass("active");
|
||||
ret = true;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* menu click
|
||||
*/
|
||||
$(".main > .main-left > .nav > .slide > .menu").click(function () {
|
||||
var ul = $(this).next(".slide-menu");
|
||||
var menu = $(this);
|
||||
if (!ul.is(":visible")) {
|
||||
menu.addClass("active");
|
||||
ul.addClass("active");
|
||||
ul.stop(true).slideDown("fast");
|
||||
} else {
|
||||
ul.stop(true).slideUp("fast", function () {
|
||||
menu.removeClass("active");
|
||||
ul.removeClass("active");
|
||||
});
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
/**
|
||||
* hook menu click and add the hash
|
||||
*/
|
||||
$(".main > .main-left > .nav > .slide > .slide-menu > li > a").click(function () {
|
||||
if (lastNode != undefined) lastNode.removeClass("active");
|
||||
$(this).parent().addClass("active");
|
||||
$(".main > .loading").fadeIn("fast");
|
||||
return true;
|
||||
});
|
||||
|
||||
/**
|
||||
* fix menu click
|
||||
*/
|
||||
$(".main > .main-left > .nav > .slide > .slide-menu > li").click(function () {
|
||||
if (lastNode != undefined) lastNode.removeClass("active");
|
||||
$(this).addClass("active");
|
||||
$(".main > .loading").fadeIn("fast");
|
||||
window.location = $($(this).find("a")[0]).attr("href");
|
||||
return false;
|
||||
});
|
||||
|
||||
/**
|
||||
* fix submenu click
|
||||
*/
|
||||
$("#maincontent > .container > .tabs > li").click(function () {
|
||||
console.log("sub");
|
||||
$(".main > .loading").fadeIn("fast");
|
||||
window.location = $($(this).find("a")[0]).attr("href");
|
||||
return false;
|
||||
});
|
||||
/**
|
||||
* get current node and open it
|
||||
*/
|
||||
if (getCurrentNodeByUrl()) {
|
||||
mainNodeName = "node-" + luciLocation[0] + "-" + luciLocation[1];
|
||||
mainNodeName = mainNodeName.replace(/[ \t\n\r\/]+/g, "_").toLowerCase();
|
||||
$("body").addClass(mainNodeName);
|
||||
}
|
||||
$(".cbi-button-up").val("");
|
||||
$(".cbi-button-down").val("");
|
||||
|
||||
|
||||
/**
|
||||
* hook other "A Label" and add hash to it.
|
||||
*/
|
||||
$("#maincontent > .container").find("a").each(function () {
|
||||
var that = $(this);
|
||||
var href = that.attr("href");
|
||||
if (href != undefined && href.indexOf("javascript") != -1) {
|
||||
return true;
|
||||
}
|
||||
var onclick = that.attr("onclick");
|
||||
if (onclick == undefined || onclick == "") {
|
||||
that.click(function () {
|
||||
var href = that.attr("href");
|
||||
if (href.indexOf("#") == -1) {
|
||||
$(".main > .loading").fadeIn("fast");
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Sidebar expand
|
||||
*/
|
||||
var showSide = false;
|
||||
$(".showSide").click(function () {
|
||||
if (showSide) {
|
||||
$(".darkMask").stop(true).fadeOut("fast");
|
||||
$(".main-left").stop(true).animate({
|
||||
width: "0"
|
||||
}, "fast");
|
||||
$(".main-right").css("overflow-y", "auto");
|
||||
showSide = false;
|
||||
} else {
|
||||
$(".darkMask").stop(true).fadeIn("fast");
|
||||
$(".main-left").stop(true).animate({
|
||||
width: "15rem"
|
||||
}, "fast");
|
||||
$(".main-right").css("overflow-y", "hidden");
|
||||
showSide = true;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$(".darkMask").click(function () {
|
||||
if (showSide) {
|
||||
showSide = false;
|
||||
$(".darkMask").stop(true).fadeOut("fast");
|
||||
$(".main-left").stop(true).animate({
|
||||
width: "0"
|
||||
}, "fast");
|
||||
$(".main-right").css("overflow-y", "auto");
|
||||
}
|
||||
});
|
||||
|
||||
$(window).resize(function () {
|
||||
if ($(window).width() > 921) {
|
||||
$(".main-left").css("width", "");
|
||||
$(".darkMask").stop(true);
|
||||
$(".darkMask").css("display", "none");
|
||||
showSide = false;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* fix legend position
|
||||
*/
|
||||
$("legend").each(function () {
|
||||
var that = $(this);
|
||||
that.after("<span class='panel-title'>" + that.text() + "</span>");
|
||||
});
|
||||
|
||||
/* $(".cbi-section-table-titles, .cbi-section-table-descr, .cbi-section-descr").each(function () {
|
||||
var that = $(this);
|
||||
if (that.text().trim() == ""){
|
||||
that.css("display", "none");
|
||||
}
|
||||
}); */
|
||||
|
||||
|
||||
$(".main-right").focus();
|
||||
$(".main-right").blur();
|
||||
$("input").attr("size", "0");
|
||||
|
||||
if (mainNodeName != undefined) {
|
||||
console.log(mainNodeName);
|
||||
switch (mainNodeName) {
|
||||
case "node-status-system_log":
|
||||
case "node-status-kernel_log":
|
||||
$("#syslog").focus(function () {
|
||||
$("#syslog").blur();
|
||||
$(".main-right").focus();
|
||||
$(".main-right").blur();
|
||||
});
|
||||
break;
|
||||
case "node-status-firewall":
|
||||
var button = $(".node-status-firewall > .main fieldset li > a");
|
||||
button.addClass("cbi-button cbi-button-reset a-to-btn");
|
||||
break;
|
||||
case "node-system-reboot":
|
||||
var button = $(".node-system-reboot > .main > .main-right p > a");
|
||||
button.addClass("cbi-button cbi-input-reset a-to-btn");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
})(jQuery);
|
||||
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata>Generated by IcoMoon</metadata>
|
||||
<defs>
|
||||
<font id="icomoon" horiz-adv-x="1024">
|
||||
<font-face units-per-em="1024" ascent="960" descent="-64" />
|
||||
<missing-glyph horiz-adv-x="1024" />
|
||||
<glyph unicode=" " horiz-adv-x="512" d="" />
|
||||
<glyph unicode="" glyph-name="expand_less" d="M512 596.667l256-256-60-60-196 196-196-196-60 60z" />
|
||||
<glyph unicode="" glyph-name="expand_more" d="M708 572.667l60-60-256-256-256 256 60 60 196-196z" />
|
||||
<glyph unicode="" glyph-name="menu" d="M128 682.667h768v-86h-768v86zM128 384.667v84h768v-84h-768zM128 170.667v86h768v-86h-768z" />
|
||||
<glyph unicode="" glyph-name="favorite" d="M512 28.667l-62 56q-106 96-154 142t-107 114-81 123-22 113q0 98 67 166t167 68q116 0 192-90 76 90 192 90 100 0 167-68t67-166q0-78-52-162t-113-146-199-186z" />
|
||||
<glyph unicode="" glyph-name="spinner9" d="M512 960c-278.748 0-505.458-222.762-511.848-499.974 5.92 241.864 189.832 435.974 415.848 435.974 229.75 0 416-200.576 416-448 0-53.020 42.98-96 96-96s96 42.98 96 96c0 282.77-229.23 512-512 512zM512-64c278.748 0 505.458 222.762 511.848 499.974-5.92-241.864-189.832-435.974-415.848-435.974-229.75 0-416 200.576-416 448 0 53.020-42.98 96-96 96s-96-42.98-96-96c0-282.77 229.23-512 512-512z" />
|
||||
<glyph unicode="" glyph-name="question-circle" horiz-adv-x="878" d="M512 164.571v109.714q0 8-5.143 13.143t-13.143 5.143h-109.714q-8 0-13.143-5.143t-5.143-13.143v-109.714q0-8 5.143-13.143t13.143-5.143h109.714q8 0 13.143 5.143t5.143 13.143zM658.286 548.571q0 50.286-31.714 93.143t-79.143 66.286-97.143 23.429q-138.857 0-212-121.714-8.571-13.714 4.571-24l75.429-57.143q4-3.429 10.857-3.429 9.143 0 14.286 6.857 30.286 38.857 49.143 52.571 19.429 13.714 49.143 13.714 27.429 0 48.857-14.857t21.429-33.714q0-21.714-11.429-34.857t-38.857-25.714q-36-16-66-49.429t-30-71.714v-20.571q0-8 5.143-13.143t13.143-5.143h109.714q8 0 13.143 5.143t5.143 13.143q0 10.857 12.286 28.286t31.143 28.286q18.286 10.286 28 16.286t26.286 20 25.429 27.429 16 34.571 7.143 46.286zM877.714 438.857q0-119.429-58.857-220.286t-159.714-159.714-220.286-58.857-220.286 58.857-159.714 159.714-58.857 220.286 58.857 220.286 159.714 159.714 220.286 58.857 220.286-58.857 159.714-159.714 58.857-220.286z" />
|
||||
</font></defs></svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 24 KiB |
6
package/lienol/luci-theme-argon-mod/htdocs/luci-static/argon_dark_purple/js/jquery.min.js
vendored
Normal file
@ -0,0 +1,251 @@
|
||||
/**
|
||||
* Material is a clean HTML5 theme for LuCI. It is based on luci-theme-bootstrap and MUI
|
||||
*
|
||||
* luci-theme-material
|
||||
* Copyright 2015 Lutty Yang <lutty@wcan.in>
|
||||
*
|
||||
* Have a bug? Please create an issue here on GitHub!
|
||||
* https://github.com/LuttyYang/luci-theme-material/issues
|
||||
*
|
||||
* luci-theme-bootstrap:
|
||||
* Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
* Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
|
||||
* Copyright 2012 David Menting <david@nut-bolt.nl>
|
||||
*
|
||||
* MUI:
|
||||
* https://github.com/muicss/mui
|
||||
*
|
||||
* Licensed to the public under the Apache License 2.0
|
||||
*/
|
||||
|
||||
|
||||
(function ($) {
|
||||
$(".main > .loading").fadeOut();
|
||||
|
||||
/**
|
||||
* trim text, Remove spaces, wrap
|
||||
* @param text
|
||||
* @returns {string}
|
||||
*/
|
||||
function trimText(text) {
|
||||
return text.replace(/[ \t\n\r]+/g, " ");
|
||||
}
|
||||
|
||||
|
||||
var lastNode = undefined;
|
||||
var mainNodeName = undefined;
|
||||
|
||||
var nodeUrl = "";
|
||||
(function(node){
|
||||
if (node[0] == "admin"){
|
||||
luciLocation = [node[1], node[2]];
|
||||
}else{
|
||||
luciLocation = node;
|
||||
}
|
||||
|
||||
for(var i in luciLocation){
|
||||
nodeUrl += luciLocation[i];
|
||||
if (i != luciLocation.length - 1){
|
||||
nodeUrl += "/";
|
||||
}
|
||||
}
|
||||
})(luciLocation);
|
||||
|
||||
/**
|
||||
* get the current node by Burl (primary)
|
||||
* @returns {boolean} success?
|
||||
*/
|
||||
function getCurrentNodeByUrl() {
|
||||
var ret = false;
|
||||
if (!$('body').hasClass('logged-in')) {
|
||||
luciLocation = ["Main", "Login"];
|
||||
return true;
|
||||
}
|
||||
|
||||
$(".main > .main-left > .nav > .slide > .menu").each(function () {
|
||||
var ulNode = $(this);
|
||||
ulNode.next().find("a").each(function () {
|
||||
var that = $(this);
|
||||
var href = that.attr("href");
|
||||
|
||||
if (href.indexOf(nodeUrl) != -1) {
|
||||
ulNode.click();
|
||||
ulNode.next(".slide-menu").stop(true, true);
|
||||
lastNode = that.parent();
|
||||
lastNode.addClass("active");
|
||||
ret = true;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* menu click
|
||||
*/
|
||||
$(".main > .main-left > .nav > .slide > .menu").click(function () {
|
||||
var ul = $(this).next(".slide-menu");
|
||||
var menu = $(this);
|
||||
if (!ul.is(":visible")) {
|
||||
menu.addClass("active");
|
||||
ul.addClass("active");
|
||||
ul.stop(true).slideDown("fast");
|
||||
} else {
|
||||
ul.stop(true).slideUp("fast", function () {
|
||||
menu.removeClass("active");
|
||||
ul.removeClass("active");
|
||||
});
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
/**
|
||||
* hook menu click and add the hash
|
||||
*/
|
||||
$(".main > .main-left > .nav > .slide > .slide-menu > li > a").click(function () {
|
||||
if (lastNode != undefined) lastNode.removeClass("active");
|
||||
$(this).parent().addClass("active");
|
||||
$(".main > .loading").fadeIn("fast");
|
||||
return true;
|
||||
});
|
||||
|
||||
/**
|
||||
* fix menu click
|
||||
*/
|
||||
$(".main > .main-left > .nav > .slide > .slide-menu > li").click(function () {
|
||||
if (lastNode != undefined) lastNode.removeClass("active");
|
||||
$(this).addClass("active");
|
||||
$(".main > .loading").fadeIn("fast");
|
||||
window.location = $($(this).find("a")[0]).attr("href");
|
||||
return false;
|
||||
});
|
||||
|
||||
/**
|
||||
* fix submenu click
|
||||
*/
|
||||
$("#maincontent > .container > .tabs > li").click(function () {
|
||||
console.log("sub");
|
||||
$(".main > .loading").fadeIn("fast");
|
||||
window.location = $($(this).find("a")[0]).attr("href");
|
||||
return false;
|
||||
});
|
||||
/**
|
||||
* get current node and open it
|
||||
*/
|
||||
if (getCurrentNodeByUrl()) {
|
||||
mainNodeName = "node-" + luciLocation[0] + "-" + luciLocation[1];
|
||||
mainNodeName = mainNodeName.replace(/[ \t\n\r\/]+/g, "_").toLowerCase();
|
||||
$("body").addClass(mainNodeName);
|
||||
}
|
||||
$(".cbi-button-up").val("");
|
||||
$(".cbi-button-down").val("");
|
||||
|
||||
|
||||
/**
|
||||
* hook other "A Label" and add hash to it.
|
||||
*/
|
||||
$("#maincontent > .container").find("a").each(function () {
|
||||
var that = $(this);
|
||||
var href = that.attr("href");
|
||||
if (href != undefined && href.indexOf("javascript") != -1) {
|
||||
return true;
|
||||
}
|
||||
var onclick = that.attr("onclick");
|
||||
if (onclick == undefined || onclick == "") {
|
||||
that.click(function () {
|
||||
var href = that.attr("href");
|
||||
if (href.indexOf("#") == -1) {
|
||||
$(".main > .loading").fadeIn("fast");
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Sidebar expand
|
||||
*/
|
||||
var showSide = false;
|
||||
$(".showSide").click(function () {
|
||||
if (showSide) {
|
||||
$(".darkMask").stop(true).fadeOut("fast");
|
||||
$(".main-left").stop(true).animate({
|
||||
width: "0"
|
||||
}, "fast");
|
||||
$(".main-right").css("overflow-y", "auto");
|
||||
showSide = false;
|
||||
} else {
|
||||
$(".darkMask").stop(true).fadeIn("fast");
|
||||
$(".main-left").stop(true).animate({
|
||||
width: "15rem"
|
||||
}, "fast");
|
||||
$(".main-right").css("overflow-y", "hidden");
|
||||
showSide = true;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$(".darkMask").click(function () {
|
||||
if (showSide) {
|
||||
showSide = false;
|
||||
$(".darkMask").stop(true).fadeOut("fast");
|
||||
$(".main-left").stop(true).animate({
|
||||
width: "0"
|
||||
}, "fast");
|
||||
$(".main-right").css("overflow-y", "auto");
|
||||
}
|
||||
});
|
||||
|
||||
$(window).resize(function () {
|
||||
if ($(window).width() > 921) {
|
||||
$(".main-left").css("width", "");
|
||||
$(".darkMask").stop(true);
|
||||
$(".darkMask").css("display", "none");
|
||||
showSide = false;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* fix legend position
|
||||
*/
|
||||
$("legend").each(function () {
|
||||
var that = $(this);
|
||||
that.after("<span class='panel-title'>" + that.text() + "</span>");
|
||||
});
|
||||
|
||||
/* $(".cbi-section-table-titles, .cbi-section-table-descr, .cbi-section-descr").each(function () {
|
||||
var that = $(this);
|
||||
if (that.text().trim() == ""){
|
||||
that.css("display", "none");
|
||||
}
|
||||
}); */
|
||||
|
||||
|
||||
$(".main-right").focus();
|
||||
$(".main-right").blur();
|
||||
$("input").attr("size", "0");
|
||||
|
||||
if (mainNodeName != undefined) {
|
||||
console.log(mainNodeName);
|
||||
switch (mainNodeName) {
|
||||
case "node-status-system_log":
|
||||
case "node-status-kernel_log":
|
||||
$("#syslog").focus(function () {
|
||||
$("#syslog").blur();
|
||||
$(".main-right").focus();
|
||||
$(".main-right").blur();
|
||||
});
|
||||
break;
|
||||
case "node-status-firewall":
|
||||
var button = $(".node-status-firewall > .main fieldset li > a");
|
||||
button.addClass("cbi-button cbi-button-reset a-to-btn");
|
||||
break;
|
||||
case "node-system-reboot":
|
||||
var button = $(".node-system-reboot > .main > .main-right p > a");
|
||||
button.addClass("cbi-button cbi-input-reset a-to-btn");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
})(jQuery);
|
||||
|
After Width: | Height: | Size: 7.0 KiB |
@ -0,0 +1,7 @@
|
||||
/*!
|
||||
Pure v1.0.1
|
||||
Copyright 2013 Yahoo!
|
||||
Licensed under the BSD License.
|
||||
https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
*/
|
||||
.pure-g{letter-spacing:-.31em;text-rendering:optimizespeed;font-family:FreeSans,Arimo,"Droid Sans",Helvetica,Arial,sans-serif;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-align-content:flex-start;-ms-flex-line-pack:start;align-content:flex-start}@media all and (-ms-high-contrast:none),(-ms-high-contrast:active){table .pure-g{display:block}}.opera-only :-o-prefocus,.pure-g{word-spacing:-.43em}.pure-u,.pure-u-1,.pure-u-1-1,.pure-u-1-12,.pure-u-1-2,.pure-u-1-24,.pure-u-1-3,.pure-u-1-4,.pure-u-1-5,.pure-u-1-6,.pure-u-1-8,.pure-u-10-24,.pure-u-11-12,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-2-24,.pure-u-2-3,.pure-u-2-5,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24,.pure-u-3-24,.pure-u-3-4,.pure-u-3-5,.pure-u-3-8,.pure-u-4-24,.pure-u-4-5,.pure-u-5-12,.pure-u-5-24,.pure-u-5-5,.pure-u-5-6,.pure-u-5-8,.pure-u-6-24,.pure-u-7-12,.pure-u-7-24,.pure-u-7-8,.pure-u-8-24,.pure-u-9-24{display:inline-block;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-g [class*=pure-u]{font-family:sans-serif}.pure-u-1-24{width:4.1667%}.pure-u-1-12,.pure-u-2-24{width:8.3333%}.pure-u-1-8,.pure-u-3-24{width:12.5%}.pure-u-1-6,.pure-u-4-24{width:16.6667%}.pure-u-1-5{width:20%}.pure-u-5-24{width:20.8333%}.pure-u-1-4,.pure-u-6-24{width:25%}.pure-u-7-24{width:29.1667%}.pure-u-1-3,.pure-u-8-24{width:33.3333%}.pure-u-3-8,.pure-u-9-24{width:37.5%}.pure-u-2-5{width:40%}.pure-u-10-24,.pure-u-5-12{width:41.6667%}.pure-u-11-24{width:45.8333%}.pure-u-1-2,.pure-u-12-24{width:50%}.pure-u-13-24{width:54.1667%}.pure-u-14-24,.pure-u-7-12{width:58.3333%}.pure-u-3-5{width:60%}.pure-u-15-24,.pure-u-5-8{width:62.5%}.pure-u-16-24,.pure-u-2-3{width:66.6667%}.pure-u-17-24{width:70.8333%}.pure-u-18-24,.pure-u-3-4{width:75%}.pure-u-19-24{width:79.1667%}.pure-u-4-5{width:80%}.pure-u-20-24,.pure-u-5-6{width:83.3333%}.pure-u-21-24,.pure-u-7-8{width:87.5%}.pure-u-11-12,.pure-u-22-24{width:91.6667%}.pure-u-23-24{width:95.8333%}.pure-u-1,.pure-u-1-1,.pure-u-24-24,.pure-u-5-5{width:100%}
|
||||
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 69 KiB |
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata>Generated by IcoMoon</metadata>
|
||||
<defs>
|
||||
<font id="icomoon" horiz-adv-x="1024">
|
||||
<font-face units-per-em="1024" ascent="960" descent="-64" />
|
||||
<missing-glyph horiz-adv-x="1024" />
|
||||
<glyph unicode=" " horiz-adv-x="512" d="" />
|
||||
<glyph unicode="" glyph-name="expand_less" d="M512 596.667l256-256-60-60-196 196-196-196-60 60z" />
|
||||
<glyph unicode="" glyph-name="expand_more" d="M708 572.667l60-60-256-256-256 256 60 60 196-196z" />
|
||||
<glyph unicode="" glyph-name="menu" d="M128 682.667h768v-86h-768v86zM128 384.667v84h768v-84h-768zM128 170.667v86h768v-86h-768z" />
|
||||
<glyph unicode="" glyph-name="favorite" d="M512 28.667l-62 56q-106 96-154 142t-107 114-81 123-22 113q0 98 67 166t167 68q116 0 192-90 76 90 192 90 100 0 167-68t67-166q0-78-52-162t-113-146-199-186z" />
|
||||
<glyph unicode="" glyph-name="spinner9" d="M512 960c-278.748 0-505.458-222.762-511.848-499.974 5.92 241.864 189.832 435.974 415.848 435.974 229.75 0 416-200.576 416-448 0-53.020 42.98-96 96-96s96 42.98 96 96c0 282.77-229.23 512-512 512zM512-64c278.748 0 505.458 222.762 511.848 499.974-5.92-241.864-189.832-435.974-415.848-435.974-229.75 0-416 200.576-416 448 0 53.020-42.98 96-96 96s-96-42.98-96-96c0-282.77 229.23-512 512-512z" />
|
||||
<glyph unicode="" glyph-name="question-circle" horiz-adv-x="878" d="M512 164.571v109.714q0 8-5.143 13.143t-13.143 5.143h-109.714q-8 0-13.143-5.143t-5.143-13.143v-109.714q0-8 5.143-13.143t13.143-5.143h109.714q8 0 13.143 5.143t5.143 13.143zM658.286 548.571q0 50.286-31.714 93.143t-79.143 66.286-97.143 23.429q-138.857 0-212-121.714-8.571-13.714 4.571-24l75.429-57.143q4-3.429 10.857-3.429 9.143 0 14.286 6.857 30.286 38.857 49.143 52.571 19.429 13.714 49.143 13.714 27.429 0 48.857-14.857t21.429-33.714q0-21.714-11.429-34.857t-38.857-25.714q-36-16-66-49.429t-30-71.714v-20.571q0-8 5.143-13.143t13.143-5.143h109.714q8 0 13.143 5.143t5.143 13.143q0 10.857 12.286 28.286t31.143 28.286q18.286 10.286 28 16.286t26.286 20 25.429 27.429 16 34.571 7.143 46.286zM877.714 438.857q0-119.429-58.857-220.286t-159.714-159.714-220.286-58.857-220.286 58.857-159.714 159.714-58.857 220.286 58.857 220.286 159.714 159.714 220.286 58.857 220.286-58.857 159.714-159.714 58.857-220.286z" />
|
||||
</font></defs></svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata>Generated by IcoMoon</metadata>
|
||||
<defs>
|
||||
<font id="icomoon" horiz-adv-x="1024">
|
||||
<font-face units-per-em="1024" ascent="960" descent="-64" />
|
||||
<missing-glyph horiz-adv-x="1024" />
|
||||
<glyph unicode=" " horiz-adv-x="512" d="" />
|
||||
<glyph unicode="" glyph-name="angle-right" d="M704.6 414l-272-272c-18.8-18.8-49.2-18.8-67.8 0l-45.2 45.2c-18.8 18.8-18.8 49.2 0 67.8l192.8 192.8-192.8 192.8c-18.8 18.8-18.8 49.2 0 67.8l45 45.6c18.8 18.8 49.2 18.8 67.8 0l272-272c19-18.8 19-49.2 0.2-68z" />
|
||||
<glyph unicode="" glyph-name="password_unlock" d="M196.923 603.569v0zM827.077 507.077h-512v92.554c0 104.369 78.769 196.923 183.138 202.831 96.492 5.908 177.231-55.138 202.831-141.785 1.969-7.877 9.846-15.754 19.692-15.754h80.738c11.815 0 21.662 11.815 19.692 23.631-31.508 149.662-165.415 259.938-324.923 252.062-167.385-7.877-295.385-151.631-299.323-317.046v-96.492c-43.323 0-78.769-35.446-78.769-78.769v-374.154c0-43.323 35.446-78.769 78.769-78.769h630.154c43.323 0 78.769 35.446 78.769 78.769v374.154c0 43.323-35.446 78.769-78.769 78.769zM602.585 119.138c3.938-11.815-5.908-25.6-19.692-25.6h-143.754c-13.785 0-23.631 11.815-19.692 25.6l35.446 118.154c-29.538 19.692-47.262 55.138-39.385 94.523 7.877 37.415 37.415 66.954 76.8 74.831 63.015 11.815 118.154-33.477 118.154-92.554 0-31.508-15.754-61.046-41.354-76.8l33.477-118.154z" />
|
||||
</font></defs></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 166 KiB |
|
After Width: | Height: | Size: 258 KiB |
|
After Width: | Height: | Size: 243 KiB |
2
package/lienol/luci-theme-argon-mod/htdocs/luci-static/argon_light/js/jquery.min.js
vendored
Normal file
@ -0,0 +1,288 @@
|
||||
/**
|
||||
* Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material and Argon Template
|
||||
*
|
||||
* luci-theme-argon
|
||||
* Copyright 2019 Jerrykuku <jerrykuku@qq.com>
|
||||
*
|
||||
* Have a bug? Please create an issue here on GitHub!
|
||||
* https://github.com/jerrykuku/luci-theme-argon/issues
|
||||
*
|
||||
* luci-theme-bootstrap:
|
||||
* Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
* Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
|
||||
* Copyright 2012 David Menting <david@nut-bolt.nl>
|
||||
*
|
||||
* MUI:
|
||||
* https://github.com/muicss/mui
|
||||
*
|
||||
* luci-theme-material:
|
||||
* https://github.com/LuttyYang/luci-theme-material/
|
||||
*
|
||||
* Agron Theme
|
||||
* https://demos.creative-tim.com/argon-dashboard/index.html
|
||||
*
|
||||
* Login background
|
||||
* https://unsplash.com/
|
||||
*
|
||||
* Licensed to the public under the Apache License 2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Font generate by Icomoon<icomoon.io>
|
||||
*/
|
||||
(function ($) {
|
||||
$(".main > .loading").hide();
|
||||
$(".main > .loading").fadeOut();
|
||||
|
||||
/**
|
||||
* trim text, Remove spaces, wrap
|
||||
* @param text
|
||||
* @returns {string}
|
||||
*/
|
||||
function trimText(text) {
|
||||
return text.replace(/[ \t\n\r]+/g, " ");
|
||||
}
|
||||
|
||||
|
||||
var lastNode = undefined;
|
||||
var mainNodeName = undefined;
|
||||
|
||||
var nodeUrl = "";
|
||||
(function (node) {
|
||||
if (node[0] == "admin") {
|
||||
luciLocation = [node[1], node[2]];
|
||||
} else {
|
||||
luciLocation = node;
|
||||
}
|
||||
|
||||
for (var i in luciLocation) {
|
||||
nodeUrl += luciLocation[i];
|
||||
if (i != luciLocation.length - 1) {
|
||||
nodeUrl += "/";
|
||||
}
|
||||
}
|
||||
})(luciLocation);
|
||||
|
||||
/**
|
||||
* get the current node by Burl (primary)
|
||||
* @returns {boolean} success?
|
||||
*/
|
||||
function getCurrentNodeByUrl() {
|
||||
var ret = false;
|
||||
if (!$('body').hasClass('logged-in')) {
|
||||
luciLocation = ["Main", "Login"];
|
||||
return true;
|
||||
}
|
||||
$(".main > .main-left > .nav > .slide > .active").next(".slide-menu").stop(true).slideUp("fast");
|
||||
$(".main > .main-left > .nav > .slide > .menu").removeClass("active");
|
||||
$(".main > .main-left > .nav > .slide > .menu").each(function () {
|
||||
var ulNode = $(this);
|
||||
|
||||
ulNode.next().find("a").each(function () {
|
||||
var that = $(this);
|
||||
var href = that.attr("href");
|
||||
|
||||
if (href.indexOf(nodeUrl) != -1) {
|
||||
ulNode.click();
|
||||
ulNode.next(".slide-menu").stop(true, true);
|
||||
lastNode = that.parent();
|
||||
lastNode.addClass("active");
|
||||
ret = true;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* menu click
|
||||
*/
|
||||
$(".main > .main-left > .nav > .slide > .menu").click(function () {
|
||||
var ul = $(this).next(".slide-menu");
|
||||
var menu = $(this);
|
||||
if (!menu.hasClass("exit")) {
|
||||
$(".main > .main-left > .nav > .slide > .active").next(".slide-menu").stop(true).slideUp("fast");
|
||||
$(".main > .main-left > .nav > .slide > .menu").removeClass("active");
|
||||
if (!ul.is(":visible")) {
|
||||
menu.addClass("active");
|
||||
ul.addClass("active");
|
||||
ul.stop(true).slideDown("fast");
|
||||
} else {
|
||||
ul.stop(true).slideUp("fast", function () {
|
||||
menu.removeClass("active");
|
||||
ul.removeClass("active");
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
// define what element should be observed by the observer
|
||||
// and what types of mutations trigger the callback
|
||||
if ($("#cbi-dhcp-lan-ignore").length > 0) {
|
||||
observer.observe(document.getElementById("cbi-dhcp-lan-ignore"), {
|
||||
subtree: true,
|
||||
attributes: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* hook menu click and add the hash
|
||||
*/
|
||||
$(".main > .main-left > .nav > .slide > .slide-menu > li > a").click(function () {
|
||||
if (lastNode != undefined)
|
||||
lastNode.removeClass("active");
|
||||
$(this).parent().addClass("active");
|
||||
$(".main > .loading").fadeIn("fast");
|
||||
return true;
|
||||
});
|
||||
|
||||
/**
|
||||
* fix menu click
|
||||
*/
|
||||
$(".main > .main-left > .nav > .slide > .slide-menu > li").click(function () {
|
||||
if (lastNode != undefined)
|
||||
lastNode.removeClass("active");
|
||||
$(this).addClass("active");
|
||||
$(".main > .loading").fadeIn("fast");
|
||||
window.location = $($(this).find("a")[0]).attr("href");
|
||||
return false;
|
||||
});
|
||||
|
||||
/**
|
||||
* fix submenu click
|
||||
*/
|
||||
$("#maincontent > .container > .tabs > li").click(function () {
|
||||
$(".main > .loading").fadeIn("fast");
|
||||
window.location = $($(this).find("a")[0]).attr("href");
|
||||
return false;
|
||||
});
|
||||
|
||||
/**
|
||||
* get current node and open it
|
||||
*/
|
||||
if (getCurrentNodeByUrl()) {
|
||||
mainNodeName = "node-" + luciLocation[0] + "-" + luciLocation[1];
|
||||
mainNodeName = mainNodeName.replace(/[ \t\n\r\/]+/g, "_").toLowerCase();
|
||||
$("body").addClass(mainNodeName);
|
||||
}
|
||||
$(".cbi-button-up").val("");
|
||||
$(".cbi-button-down").val("");
|
||||
|
||||
|
||||
/**
|
||||
* hook other "A Label" and add hash to it.
|
||||
*/
|
||||
$("#maincontent > .container").find("a").each(function () {
|
||||
var that = $(this);
|
||||
var onclick = that.attr("onclick");
|
||||
if (onclick == undefined || onclick == "") {
|
||||
that.click(function () {
|
||||
var href = that.attr("href");
|
||||
if (href.indexOf("#") == -1) {
|
||||
$(".main > .loading").fadeIn("fast");
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Sidebar expand
|
||||
*/
|
||||
var showSide = false;
|
||||
$(".showSide").click(function () {
|
||||
if (showSide) {
|
||||
$(".darkMask").stop(true).fadeOut("fast");
|
||||
$(".main-left").stop(true).animate({
|
||||
width: "0"
|
||||
}, "fast");
|
||||
$(".main-right").css("overflow-y", "auto");
|
||||
showSide = false;
|
||||
} else {
|
||||
$(".darkMask").stop(true).fadeIn("fast");
|
||||
$(".main-left").stop(true).animate({
|
||||
width: "15rem"
|
||||
}, "fast");
|
||||
$(".main-right").css("overflow-y", "hidden");
|
||||
showSide = true;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$(".darkMask").click(function () {
|
||||
if (showSide) {
|
||||
showSide = false;
|
||||
$(".darkMask").stop(true).fadeOut("fast");
|
||||
$(".main-left").stop(true).animate({
|
||||
width: "0"
|
||||
}, "fast");
|
||||
$(".main-right").css("overflow-y", "auto");
|
||||
}
|
||||
});
|
||||
|
||||
$(window).resize(function () {
|
||||
if ($(window).width() > 921) {
|
||||
$(".main-left").css("width", "");
|
||||
$(".darkMask").stop(true);
|
||||
$(".darkMask").css("display", "none");
|
||||
showSide = false;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* fix legend position
|
||||
*/
|
||||
$("legend").each(function () {
|
||||
var that = $(this);
|
||||
that.after("<span class='panel-title'>" + that.text() + "</span>");
|
||||
});
|
||||
|
||||
$(".cbi-section-table-titles, .cbi-section-table-descr, .cbi-section-descr").each(function () {
|
||||
var that = $(this);
|
||||
if (that.text().trim() == "") {
|
||||
that.css("display", "none");
|
||||
}
|
||||
});
|
||||
|
||||
$(".node-main-login > .main .cbi-value.cbi-value-last .cbi-input-text").focus(function () {
|
||||
//$(".node-main-login > .main > .main-right > .login-bg").addClass("blur");
|
||||
});
|
||||
$(".node-main-login > .main .cbi-value.cbi-value-last .cbi-input-text").blur(function () {
|
||||
//$(".node-main-login > .main > .main-right > .login-bg").removeClass("blur");
|
||||
});
|
||||
|
||||
|
||||
$(".main-right").focus();
|
||||
$(".main-right").blur();
|
||||
$("input").attr("size", "0");
|
||||
|
||||
if (mainNodeName != undefined) {
|
||||
console.log(mainNodeName);
|
||||
switch (mainNodeName) {
|
||||
case "node-status-system_log":
|
||||
case "node-status-kernel_log":
|
||||
$("#syslog").focus(function () {
|
||||
$("#syslog").blur();
|
||||
$(".main-right").focus();
|
||||
$(".main-right").blur();
|
||||
});
|
||||
break;
|
||||
case "node-status-firewall":
|
||||
var button = $(".node-status-firewall > .main fieldset li > a");
|
||||
button.addClass("cbi-button cbi-button-reset a-to-btn");
|
||||
break;
|
||||
case "node-system-reboot":
|
||||
var button = $(".node-system-reboot > .main > .main-right p > a");
|
||||
button.addClass("cbi-button cbi-input-reset a-to-btn");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
})(jQuery);
|
||||
|
After Width: | Height: | Size: 7.0 KiB |