add luci-app-openclash
This commit is contained in:
parent
bc128f872e
commit
a018e8f622
45
package/cnsztl/luci-app-openclash/Makefile
Executable file
45
package/cnsztl/luci-app-openclash/Makefile
Executable file
@ -0,0 +1,45 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-openclash
|
||||
PKG_VERSION=0.30.0
|
||||
PKG_RELEASE:=1
|
||||
PKG_MAINTAINER:=frainzy1477&vernesong <https://github.com/vernesong/OpenClash>
|
||||
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/$(PKG_NAME)
|
||||
CATEGORY:=Utilities
|
||||
SUBMENU:=Luci
|
||||
TITLE:=LuCI support for clash
|
||||
PKGARCH:=all
|
||||
DEPENDS:=+coreutils-nohup +bash +wget
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/description
|
||||
A LuCI support for clash
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/postinst
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
$(foreach po,$(wildcard ${CURDIR}/i18n/zh-cn/*.po), \
|
||||
po2lmo $(po) $(PKG_BUILD_DIR)/$(patsubst %.po,%.lmo,$(notdir $(po)));)
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/install
|
||||
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/i18n
|
||||
$(INSTALL_DATA) $(PKG_BUILD_DIR)/*.*.lmo $(1)/usr/lib/lua/luci/i18n/
|
||||
$(CP) ./files/* $(1)/
|
||||
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,$(PKG_NAME)))
|
||||
13
package/cnsztl/luci-app-openclash/files/etc/config/openclash
Executable file
13
package/cnsztl/luci-app-openclash/files/etc/config/openclash
Executable file
@ -0,0 +1,13 @@
|
||||
|
||||
config openclash 'config'
|
||||
option proxy_port '7892'
|
||||
option enable '0'
|
||||
option en_mode '0'
|
||||
option auto_update '0'
|
||||
option auto_update_time '0'
|
||||
option cn_port '9090'
|
||||
option dashboard_password '123456'
|
||||
option rule_source '0'
|
||||
option enable_custom_dns '0'
|
||||
option enable_custom_clash_rules '0'
|
||||
option other_rule_auto_update '0'
|
||||
@ -0,0 +1,13 @@
|
||||
##- DOMAIN-SUFFIX,google.com,Proxy 匹配域名后缀(交由Proxy代理服务器组)
|
||||
##- DOMAIN-KEYWORD,google,Proxy 匹配域名关键字(交由Proxy代理服务器组)
|
||||
##- DOMAIN,google.com,Proxy 匹配域名(交由Proxy代理服务器组)
|
||||
##- DOMAIN-SUFFIX,ad.com,REJECT 匹配域名后缀(拒绝)
|
||||
##- IP-CIDR,127.0.0.0/8,DIRECT 匹配数据目标IP(直连)
|
||||
##- SRC-IP-CIDR,192.168.1.201/32,DIRECT 匹配数据发起IP(直连)
|
||||
##- DST-PORT,80,DIRECT 匹配数据目标端口(直连)
|
||||
##- SRC-PORT,7777,DIRECT 匹配数据源端口(直连)
|
||||
|
||||
##排序在上的规则优先生效,如添加(去除#号):
|
||||
##- SRC-IP-CIDR,192.168.1.201/32,Rule
|
||||
##- SRC-IP-CIDR,192.168.1.0/24,DIRECT
|
||||
##此时IP为192.168.1.201的客户端流量走代理(策略),其余客户端不走代理
|
||||
326
package/cnsztl/luci-app-openclash/files/etc/init.d/openclash
Executable file
326
package/cnsztl/luci-app-openclash/files/etc/init.d/openclash
Executable file
@ -0,0 +1,326 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (c) 2011-2015 OpenWrt.org
|
||||
|
||||
START=99
|
||||
STOP=15
|
||||
|
||||
|
||||
CLASH="/etc/openclash/clash"
|
||||
CLASH_CONFIG="/etc/openclash"
|
||||
CRON_FILE="/etc/crontabs/root"
|
||||
CONFIG_FILE="/etc/openclash/config.yml"
|
||||
LOG_FILE="/tmp/openclash.log"
|
||||
START_LOG="/tmp/openclash_start.log"
|
||||
BACKPACK_FILE="/etc/openclash/config.bak"
|
||||
CHANGE_FILE="/tmp/yml_change.yml"
|
||||
RULE_FILE="/tmp/yml_rules.yml"
|
||||
DNS_FILE="/tmp/yml_dns.yml"
|
||||
|
||||
|
||||
add_cron()
|
||||
{
|
||||
[ -z "`grep "openclash.log" "$CRON_FILE"`" ] && {
|
||||
echo '0 0 * * 0 echo "" > /tmp/openclash.log' >> $CRON_FILE
|
||||
}
|
||||
[ -z "`grep "openclash.sh" "$CRON_FILE"`" ] && {
|
||||
[ "$(uci get openclash.config.auto_update 2>/dev/null)" -eq 1 ] && echo "0 $(uci get openclash.config.auto_update_time 2>/dev/null) * * * /usr/share/openclash/openclash.sh" >> $CRON_FILE
|
||||
}
|
||||
[ -z "`grep "openclash_rule.sh" "$CRON_FILE"`" ] && {
|
||||
[ "$(uci get openclash.config.other_rule_auto_update 2>/dev/null)" -eq 1 ] && echo "0 $(uci get openclash.config.other_rule_update_day_time 2>/dev/null) * * $(uci get openclash.config.other_rule_update_week_time 2>/dev/null) /usr/share/openclash/openclash_rule.sh" >> $CRON_FILE
|
||||
}
|
||||
crontab $CRON_FILE
|
||||
nohup /usr/share/openclash/openclash_watchdog.sh &
|
||||
}
|
||||
|
||||
del_cron()
|
||||
{
|
||||
sed -i '/openclash.sh/d' $CRON_FILE 2>/dev/null
|
||||
sed -i '/openclash_rule.sh/d' $CRON_FILE 2>/dev/null
|
||||
/etc/init.d/cron restart
|
||||
}
|
||||
|
||||
yml_check()
|
||||
{
|
||||
if [ ! -f "$4" ]; then
|
||||
cp "$3" "$4"
|
||||
fi
|
||||
|
||||
if [ "$(grep -c '^##Custom DNS##' "$CONFIG_FILE")" -gt 0 ] && [ "$2" = 0 ]; then
|
||||
cp "$4" "$3"
|
||||
fi
|
||||
|
||||
if [ "$1" = 0 ]; then
|
||||
if [ -f "$4" ]; then
|
||||
[ ! -z "`grep "OpenClash-General" "$CONFIG_FILE"`" ] && {
|
||||
cp "$4" "$3"
|
||||
}
|
||||
else
|
||||
[ -z "`grep "OpenClash-General" "$CONFIG_FILE"`" ] && {
|
||||
cp "$3" "$4"
|
||||
}
|
||||
fi
|
||||
fi
|
||||
sed -i '/OpenClash-General/d' "$3" 2>/dev/null
|
||||
sed -i '/^Proxy:/i\#===================== OpenClash-General-Settings =====================#' "$3" 2>/dev/null
|
||||
}
|
||||
|
||||
yml_dns_check()
|
||||
{
|
||||
if [ "$1" -eq 53 ]; then
|
||||
sed -i "/^ listen:/c\ listen: 0.0.0.0:7874" "$2"
|
||||
dns_port=7874
|
||||
fi
|
||||
|
||||
[ -z "`grep "^dns:" $CONFIG_FILE`" ] && {
|
||||
sed -i -e "/^Proxy:$/i\dns:"\
|
||||
-e "/^dns:/a\ enable: true"\
|
||||
-e "/enable: true/a\ listen: 0.0.0.0:${1}"\
|
||||
-e "/listen:/a\ enhanced-mode: redir-host"\
|
||||
-e "/enhanced-mode:/a\ nameserver:"\
|
||||
-e "/nameserver:/a\ - 114.114.114.114"\
|
||||
-e "/114.114.114.114/a\ - 119.29.29.29"\
|
||||
-e "/119.29.29.29/a\ - 223.5.5.5"\
|
||||
-e "/223.5.5.5/a\ fallback:"\
|
||||
-e "/fallback:/a\ - tls://dns.rubyfish.cn:853"\
|
||||
-e "/dns.rubyfish.cn:853/a\- tcp://1.1.1.1:53"\
|
||||
-e "/1.1.1.1:53/a\ - tcp://208.67.222.222:443"\
|
||||
-e "/208.67.222.222:443/a\ - tls://dns.google" "$2"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
yml_cut()
|
||||
{
|
||||
cp "$5" "$2"
|
||||
if [ "$1" = 0 ]; then
|
||||
sed -i '/^Rule:$/,$d' "$2"
|
||||
sed -n '/^Rule:$/,$p' "$5" >"$3"
|
||||
else
|
||||
sed -i '/^Rule:$/,$d' "$2"
|
||||
sed -n '/nameserver:$/,$p' "$2" >"$4"
|
||||
sed -i '/nameserver:$/,$d' "$2"
|
||||
sed -n '/^Rule:$/,$p' "$5" >"$3"
|
||||
fi
|
||||
}
|
||||
|
||||
yml_dns_get()
|
||||
{
|
||||
|
||||
local section="$1"
|
||||
local dns_type=""
|
||||
local dns_address=""
|
||||
config_get "port" "$section" "port" ""
|
||||
config_get "type" "$section" "type" ""
|
||||
config_get "ip" "$section" "ip" ""
|
||||
config_get "group" "$section" "group" ""
|
||||
|
||||
|
||||
if [ -z "$ip" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [ "$type" = "tcp" ]; then
|
||||
dns_type="- tcp://"
|
||||
elif [ "$type" = "tls" ]; then
|
||||
dns_type="- tls://"
|
||||
elif [ "$type" = "udp" ]; then
|
||||
dns_type="- "
|
||||
fi
|
||||
|
||||
if [ ! -z "$port" ] && [ ! -z "$ip" ]; then
|
||||
dns_address="$ip:$port"
|
||||
elif [ -z "$port" ] && [ ! -z "$ip" ]; then
|
||||
dns_address="$ip"
|
||||
else
|
||||
return
|
||||
fi
|
||||
|
||||
if [ ! -z "$group" ]; then
|
||||
if [ "$group" = "nameserver" ]; then
|
||||
echo " $dns_type$dns_address" >>/etc/openclash/config.namedns
|
||||
else
|
||||
grep "fallback:$" /etc/openclash/config.falldns 1>/dev/null
|
||||
if [ "$?" -ne "0" ]; then
|
||||
echo " fallback:" >/etc/openclash/config.falldns
|
||||
fi
|
||||
echo " $dns_type$dns_address" >>/etc/openclash/config.falldns
|
||||
fi
|
||||
else
|
||||
return
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
yml_dns_custom()
|
||||
{
|
||||
[ "$1" = 1 ] && {
|
||||
echo " nameserver:" >/etc/openclash/config.namedns
|
||||
config_load "openclash"
|
||||
config_foreach yml_dns_get "dns_servers"
|
||||
sed -i '/nameserver:$/i\##Custom DNS##' "$2" 2>/dev/null
|
||||
sed -i '/OpenClash-General-Settings/i\Custom DNS End' "$2" 2>/dev/null
|
||||
sed -i '/nameserver:$/,/^Custom DNS End$/d' "$2" 2>/dev/null
|
||||
sed -i '/^##Custom DNS##$/r/etc/openclash/config.falldns' "$2" 2>/dev/null
|
||||
sed -i '/^##Custom DNS##$/r/etc/openclash/config.namedns' "$2" 2>/dev/null
|
||||
rm -rf /etc/openclash/config.namedns 2>/dev/null
|
||||
rm -rf /etc/openclash/config.falldns 2>/dev/null
|
||||
}
|
||||
}
|
||||
|
||||
start()
|
||||
{
|
||||
echo "OpenClash 开始启动..." >$START_LOG
|
||||
enable=$(uci get openclash.config.enable 2>/dev/null)
|
||||
LOGTIME=$(date "+%Y-%m-%d %H:%M:%S")
|
||||
if [ ! -f $CONFIG_FILE ] && [ -f $BACKPACK_FILE ]; then
|
||||
cp $BACKPACK_FILE $CONFIG_FILE
|
||||
fi
|
||||
if [ "$enable" -eq 1 ] && [ -f $CONFIG_FILE ]; then
|
||||
echo "第一步: 获取配置中..." >$START_LOG
|
||||
en_mode=$(uci get openclash.config.en_mode 2>/dev/null)
|
||||
enable_custom_dns=$(uci get openclash.config.enable_custom_dns 2>/dev/null)
|
||||
rule_source=$(uci get openclash.config.rule_source 2>/dev/null)
|
||||
enable_custom_clash_rules=$(uci get openclash.config.enable_custom_clash_rules 2>/dev/null)
|
||||
da_password=$(uci get openclash.config.dashboard_password 2>/dev/null)
|
||||
cn_port=$(uci get openclash.config.cn_port 2>/dev/null)
|
||||
proxy_port=$(uci get openclash.config.proxy_port 2>/dev/null)
|
||||
echo "第二步: 配置文件检查..." >$START_LOG
|
||||
yml_check "$en_mode" "$enable_custom_dns" "$CONFIG_FILE" "$BACKPACK_FILE"
|
||||
current_mode=$(grep "enhanced-mode:" $CONFIG_FILE |awk -F ' ' '{print $2}' 2>/dev/null)
|
||||
dns_port=`grep listen: $CONFIG_FILE |awk -F ':' '{print $3}' |tr -cd "[0-9]"`
|
||||
yml_dns_check "$dns_port" "$CONFIG_FILE"
|
||||
echo "第三步: 修改配置文件..." >$START_LOG
|
||||
yml_cut "$enable_custom_dns" "$CHANGE_FILE" "$RULE_FILE" "$DNS_FILE" "$CONFIG_FILE"
|
||||
yml_dns_custom "$enable_custom_dns" "$DNS_FILE"
|
||||
sh /usr/share/openclash/yml_change.sh "$LOGTIME" "$en_mode" "$enable_custom_dns" "$da_password" "$cn_port" "$proxy_port" "$current_mode" "$CHANGE_FILE" &
|
||||
sh /usr/share/openclash/yml_rules_change.sh "$LOGTIME" "$rule_source" "$enable_custom_clash_rules" "$RULE_FILE" &
|
||||
wait
|
||||
cat $CHANGE_FILE $DNS_FILE $RULE_FILE > $CONFIG_FILE 2>/dev/null
|
||||
rm -rf /tmp/yml_* 2>/dev/null
|
||||
echo "第四步: 配置文件完整性检查..." >$START_LOG
|
||||
grep "^Proxy Group:$" $CONFIG_FILE 1>/dev/null && grep "^Rule:$" $CONFIG_FILE 1>/dev/null && grep "^- GEOIP" $CONFIG_FILE 1>/dev/null && grep "nameserver:$" $CONFIG_FILE 1>/dev/null
|
||||
if [ "$?" -ne "0" ]; then
|
||||
echo "错误: 配置文件完整性检查不通过,已自动还原配置文件,请对照模板格式检查修改配置文件..." >$START_LOG
|
||||
cp $BACKPACK_FILE $CONFIG_FILE
|
||||
echo "${LOGTIME} OpenClash Config Error,Please Check And Try Again" >>$LOG_FILE
|
||||
sleep 20
|
||||
echo "" >$START_LOG
|
||||
elif [ ! -z "`sed -n '/nameserver:/{n;p}' $CONFIG_FILE |grep 'fallback:'`" ]; then
|
||||
echo "错误: 配置文件DNS选项下的Nameserver必须设置服务器,已自动还原配置文件,请修改好后再重新启动..." >$START_LOG
|
||||
echo "${LOGTIME} Nameserver Must Be Set, Please Change Your Configrations In Config.yml" >>$LOG_FILE
|
||||
cp $BACKPACK_FILE $CONFIG_FILE
|
||||
sleep 20
|
||||
echo "" >$START_LOG
|
||||
else
|
||||
echo "第五步: 启动 Clash 主程序..." >$START_LOG
|
||||
nohup $CLASH -d "$CLASH_CONFIG" > $LOG_FILE 2>&1 &
|
||||
|
||||
echo "第六步: 设置 OpenClash 防火墙规则..." >$START_LOG
|
||||
ln -s /usr/share/openclash/web /www/openclash 2>/dev/null
|
||||
|
||||
uci set firewall.@defaults[0].flow_offloading=1
|
||||
uci commit firewall
|
||||
/etc/init.d/firewall restart >/dev/null 2>&1
|
||||
lan_ip=$(uci get network.lan.ipaddr)
|
||||
|
||||
iptables -t nat -N openclash
|
||||
iptables -t nat -N openclash_dns
|
||||
iptables -t nat -A openclash -d 0.0.0.0/8 -j RETURN
|
||||
iptables -t nat -A openclash -d 10.0.0.0/8 -j RETURN
|
||||
iptables -t nat -A openclash -d 127.0.0.0/8 -j RETURN
|
||||
iptables -t nat -A openclash -d 169.254.0.0/16 -j RETURN
|
||||
iptables -t nat -A openclash -d 172.16.0.0/12 -j RETURN
|
||||
iptables -t nat -A openclash -d 192.168.0.0/16 -j RETURN
|
||||
iptables -t nat -A openclash -d 224.0.0.0/4 -j RETURN
|
||||
iptables -t nat -A openclash -d 240.0.0.0/4 -j RETURN
|
||||
iptables -t nat -A openclash_dns -p udp -j REDIRECT --to-ports "$dns_port"
|
||||
iptables -t nat -A openclash_dns -p tcp -j REDIRECT --to-ports "$dns_port"
|
||||
iptables -t nat -A openclash -p tcp -j REDIRECT --to-ports "$proxy_port"
|
||||
iptables -t nat -I PREROUTING 1 -p tcp --dport 53 -j openclash_dns
|
||||
iptables -t nat -I PREROUTING 1 -p udp --dport 53 -j openclash_dns
|
||||
iptables -t nat -A PREROUTING -p tcp -j openclash
|
||||
|
||||
echo "第七步: 重启 Dnsmasq 程序..." >$START_LOG
|
||||
/etc/init.d/dnsmasq restart >/dev/null 2>&1
|
||||
if pidof clash >/dev/null; then
|
||||
echo "第八步: 添加 OpenClash 计划任务,启动进程守护程序..." >$START_LOG
|
||||
add_cron
|
||||
echo "OpenClash 启动成功,请等待服务器上线!" >$START_LOG
|
||||
echo "${LOGTIME} OpenClash Start Successfully" >> $LOG_FILE
|
||||
sleep 5
|
||||
echo "" >$START_LOG
|
||||
else
|
||||
echo "错误: OpenClash 启动失败,请到日志页面查看详细错误信息!" >$START_LOG
|
||||
echo "${LOGTIME} OpenClash Can Not Start, Please Check The Error Info And Try Again" >> $LOG_FILE
|
||||
sleep 20
|
||||
echo "" >$START_LOG
|
||||
stop
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "错误: OpenClash 缺少配置文件,请上传或更新配置文件!" >$START_LOG
|
||||
echo "${LOGTIME} config.yml Missing Or Clash Not Enable" >> $LOG_FILE
|
||||
sleep 5
|
||||
echo "" >$START_LOG
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
stop()
|
||||
{
|
||||
echo "OpenClash 开始关闭..." >$START_LOG
|
||||
echo "第一步: 删除 OpenClash 防火墙规则..." >$START_LOG
|
||||
iptables -t nat -F openclash >/dev/null 2>&1
|
||||
iptables -t nat -F openclash_dns >/dev/null 2>&1
|
||||
|
||||
nat_clashs=$(iptables -nvL PREROUTING -t nat | sed 1,2d | sed -n '/openclash/=' | sort -r)
|
||||
for nat_clash in $nat_clashs; do
|
||||
iptables -t nat -D PREROUTING "$nat_clash" >/dev/null 2>&1
|
||||
done
|
||||
|
||||
iptables -t nat -X openclash >/dev/null 2>&1
|
||||
iptables -t nat -X openclash_dns >/dev/null 2>&1
|
||||
|
||||
uci set firewall.@defaults[0].flow_offloading=1
|
||||
uci commit firewall
|
||||
/etc/init.d/firewall restart >/dev/null 2>&1
|
||||
|
||||
echo "第二步: 关闭 OpenClash 守护程序..." >$START_LOG
|
||||
kill -9 "$(ps |grep openclash_watchdog.sh |grep -v grep |awk '{print $1}')" >/dev/null 2>&1
|
||||
|
||||
echo "第三步: 关闭 Clash 主程序..." >$START_LOG
|
||||
kill -9 "$(pidof clash|sed 's/$//g')" 2>/dev/null
|
||||
|
||||
echo "第四步: 删除 OpenClash 计划任务..." >$START_LOG
|
||||
del_cron
|
||||
|
||||
echo "第五步: 重启 Dnsmasq 程序..." >$START_LOG
|
||||
/etc/init.d/dnsmasq restart >/dev/null 2>&1
|
||||
|
||||
echo "第六步: 删除 OpenClash 残留文件..." >$START_LOG
|
||||
rule_source=$(uci get openclash.config.rule_source 2>/dev/null)
|
||||
if [ "$rule_source" != 0 ]; then
|
||||
rm -rf /tmp/clash_rule.yml >/dev/null 2>&1
|
||||
rm -rf /tmp/Proxy_Group >/dev/null 2>&1
|
||||
fi
|
||||
enable=$(uci get openclash.config.enable 2>/dev/null)
|
||||
if [ "$enable" -eq 0 ]; then
|
||||
rm -rf $LOG_FILE
|
||||
rm -rf /www/openclash 2> /dev/null
|
||||
rm -rf /tmp/openclash_last_version 2> /dev/null
|
||||
sed -i '/openclash.log/d' $CRON_FILE
|
||||
echo "OpenClash 关闭成功!" >$START_LOG
|
||||
rm -rf $START_LOG
|
||||
else
|
||||
echo "OpenClash 关闭成功!" >$START_LOG
|
||||
fi
|
||||
|
||||
echo "CLASH STOP"
|
||||
}
|
||||
|
||||
|
||||
restart()
|
||||
{
|
||||
stop
|
||||
start
|
||||
}
|
||||
1056
package/cnsztl/luci-app-openclash/files/etc/openclash/ConnersHua.yml
Executable file
1056
package/cnsztl/luci-app-openclash/files/etc/openclash/ConnersHua.yml
Executable file
File diff suppressed because it is too large
Load Diff
79
package/cnsztl/luci-app-openclash/files/etc/openclash/ConnersHua_return.yml
Executable file
79
package/cnsztl/luci-app-openclash/files/etc/openclash/ConnersHua_return.yml
Executable file
@ -0,0 +1,79 @@
|
||||
Rule:
|
||||
##source:ConnersHua_return
|
||||
# (Video)
|
||||
# AcFun
|
||||
# USER-AGENT,AcFun*,PROXY
|
||||
- DOMAIN-SUFFIX,acfun.cn,PROXY
|
||||
- DOMAIN-SUFFIX,acfun.com,PROXY
|
||||
- DOMAIN-SUFFIX,aixifan.com,PROXY
|
||||
# > bilibili
|
||||
# USER-AGENT,bili-universal,PROXY
|
||||
# USER-AGENT,Bilibili*,PROXY
|
||||
- DOMAIN-SUFFIX,acgvideo.com,PROXY
|
||||
- DOMAIN-SUFFIX,bilibili.com,PROXY
|
||||
- DOMAIN-SUFFIX,hdslb.com,PROXY
|
||||
# > HunanTV
|
||||
# USER-AGENT,MGTV*,PROXY
|
||||
- DOMAIN-SUFFIX,hitv.com,PROXY
|
||||
- DOMAIN-SUFFIX,hunantv.com,PROXY
|
||||
- DOMAIN-SUFFIX,mgtv.com,PROXY
|
||||
# > Migu
|
||||
# USER-AGENT,MiguVideo*,PROXY
|
||||
# USER-AGENT,%E5%92%AA%E5%92%95%E8%A7%86%E9%A2%91,PROXY
|
||||
- DOMAIN-SUFFIX,cmvideo.cn,PROXY
|
||||
- DOMAIN-SUFFIX,migu.cn,PROXY
|
||||
- DOMAIN-SUFFIX,miguvideo.com,PROXY
|
||||
# > iQiyi
|
||||
# USER-AGENT,iQiYiPhoneVideo,PROXY
|
||||
# USER-AGENT,PPStream,PROXY
|
||||
# USER-AGENT,QIYIVideo,PROXY
|
||||
# USER-AGENT,QYPlayer,PROXY
|
||||
- DOMAIN-SUFFIX,iqiyi.com,PROXY
|
||||
- DOMAIN-SUFFIX,iqiyipic.com,PROXY
|
||||
- DOMAIN-SUFFIX,qy.net,PROXY
|
||||
# > Sohu
|
||||
- DOMAIN-SUFFIX,sohu.com,PROXY
|
||||
- DOMAIN-SUFFIX,sohu.com.cn,PROXY
|
||||
- DOMAIN-SUFFIX,itc.cn,PROXY
|
||||
- DOMAIN-SUFFIX,v-56.com,PROXY
|
||||
# > Tencent
|
||||
# USER-AGENT,live4iphone*,PROXY
|
||||
# USER-AGENT,qqlive4iphone*,PROXY
|
||||
# USER-AGENT,TencentMidasConnect*,PROXY
|
||||
- DOMAIN-SUFFIX,video.qq.com,PROXY
|
||||
# > Youku
|
||||
# USER-AGENT,Youku*,PROXY
|
||||
# USER-AGENT,%E4%BC%98%E9%85%B7*,PROXY
|
||||
- DOMAIN-SUFFIX,soku.com,PROXY
|
||||
- DOMAIN-SUFFIX,youku.com,PROXY
|
||||
- DOMAIN-SUFFIX,ykimg.com,PROXY
|
||||
|
||||
# (Music)
|
||||
# > Alibaba
|
||||
# USER-AGENT,walkman*,PROXY
|
||||
# USER-AGENT,xiami*,PROXY
|
||||
- DOMAIN-SUFFIX,xiami.com,PROXY
|
||||
- DOMAIN-SUFFIX,xiami.net,PROXY
|
||||
# > Netease
|
||||
# USER-AGENT,NeteaseMusic*,PROXY
|
||||
# USER-AGENT,%E7%BD%91%E6%98%93%E4%BA%91%E9%9F%B3%E4%B9%90*,PROXY
|
||||
- DOMAIN-SUFFIX,music.126.net,PROXY
|
||||
- DOMAIN-SUFFIX,music.163.com,PROXY
|
||||
# > Tencent
|
||||
# USER-AGENT,MOO%E9%9F%B3%E4%B9%90*,PROXY
|
||||
# USER-AGENT,QQ%E9%9F%B3%E4%B9%90,PROXY
|
||||
- DOMAIN-SUFFIX,qqmusic.qq.com,PROXY
|
||||
- DOMAIN-SUFFIX,y.qq.com,PROXY
|
||||
- DOMAIN,aqqmusic.tc.qq.com,PROXY
|
||||
# Kugou and Kuwo
|
||||
- DOMAIN-SUFFIX,kugou.com,PROXY
|
||||
# USER-AGENT,%E9%85%B7%E6%88%91%E9%9F%B3%E4%B9%90*,PROXY
|
||||
- DOMAIN-SUFFIX,kuwo.cn,PROXY
|
||||
- DOMAIN-SUFFIX,koowo.com,PROXY
|
||||
# > Baidu
|
||||
# USER-AGENT,baiduyinyue,PROXY
|
||||
- DOMAIN-SUFFIX,qianqian.com,PROXY
|
||||
|
||||
- GEOIP,CN,PROXY
|
||||
|
||||
- MATCH,DIRECT
|
||||
BIN
package/cnsztl/luci-app-openclash/files/etc/openclash/Country.mmdb
Executable file
BIN
package/cnsztl/luci-app-openclash/files/etc/openclash/Country.mmdb
Executable file
Binary file not shown.
1503
package/cnsztl/luci-app-openclash/files/etc/openclash/lhie1.yml
Executable file
1503
package/cnsztl/luci-app-openclash/files/etc/openclash/lhie1.yml
Executable file
File diff suppressed because it is too large
Load Diff
2
package/cnsztl/luci-app-openclash/files/etc/openclash/openclash_version
Executable file
2
package/cnsztl/luci-app-openclash/files/etc/openclash/openclash_version
Executable file
File diff suppressed because one or more lines are too long
@ -0,0 +1,128 @@
|
||||
module("luci.controller.openclash", package.seeall)
|
||||
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/openclash") then
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
entry({"admin", "services", "openclash"},alias("admin", "services", "openclash", "client"), _("OpenClash"), 50).dependent = true
|
||||
entry({"admin", "services", "openclash", "client"},cbi("openclash/client"),_("Clash Global State"), 20).leaf = true
|
||||
entry({"admin", "services", "openclash", "status"},call("action_status")).leaf=true
|
||||
entry({"admin", "services", "openclash", "state"},call("action_state")).leaf=true
|
||||
entry({"admin", "services", "openclash", "startlog"},call("action_start")).leaf=true
|
||||
entry({"admin", "services", "openclash", "currentversion"},call("action_currentversion"))
|
||||
entry({"admin", "services", "openclash", "lastversion"},call("action_lastversion"))
|
||||
entry({"admin", "services", "openclash", "config"},cbi("openclash/config"),_("Server Config"), 30).leaf = true
|
||||
entry({"admin", "services", "openclash", "settings"},cbi("openclash/settings"),_("Clash Settings"), 40).leaf = true
|
||||
entry({"admin", "services", "openclash", "update"},cbi("openclash/update"),_("Update Setting"), 50).leaf = true
|
||||
entry({"admin", "services", "openclash", "rule"},cbi("openclash/rule"),_("Rules Setting"), 60).leaf = true
|
||||
entry({"admin", "services", "openclash", "log"},cbi("openclash/log"),_("Logs"), 70).leaf = true
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
local function is_running()
|
||||
return luci.sys.call("pidof clash >/dev/null") == 0
|
||||
end
|
||||
|
||||
local function is_web()
|
||||
return luci.sys.call("pidof clash >/dev/null") == 0
|
||||
end
|
||||
|
||||
local function is_watchdog()
|
||||
return luci.sys.exec("ps |grep openclash_watchdog.sh |grep -v grep 2>/dev/null")
|
||||
end
|
||||
|
||||
local function config_check()
|
||||
return luci.sys.call("grep '^Proxy Group:$' /etc/openclash/config.yml 1>/dev/null && grep '^Rule:$' /etc/openclash/config.yml 1>/dev/null && grep '^- GEOIP' /etc/openclash/config.yml 1>/dev/null && grep ' nameserver:$' /etc/openclash/config.yml 1>/dev/null") == 0
|
||||
end
|
||||
|
||||
local function cn_port()
|
||||
return luci.sys.exec("uci get openclash.config.cn_port 2>/dev/null")
|
||||
end
|
||||
|
||||
local function config()
|
||||
return luci.sys.exec("ls -l --full-time /etc/openclash/config.bak|awk '{print $6,$7;}' 2>/dev/null")
|
||||
end
|
||||
|
||||
local function ipdb()
|
||||
return luci.sys.exec("ls -l --full-time /etc/openclash/Country.mmdb|awk '{print $6,$7;}' 2>/dev/null")
|
||||
end
|
||||
|
||||
local function lhie1()
|
||||
return luci.sys.exec("ls -l --full-time /etc/openclash/lhie1.yml|awk '{print $6,$7;}' 2>/dev/null")
|
||||
end
|
||||
|
||||
local function ConnersHua()
|
||||
return luci.sys.exec("ls -l --full-time /etc/openclash/ConnersHua.yml|awk '{print $6,$7;}' 2>/dev/null")
|
||||
end
|
||||
|
||||
local function ConnersHua_return()
|
||||
return luci.sys.exec("ls -l --full-time /etc/openclash/ConnersHua_return.yml|awk '{print $6,$7;}' 2>/dev/null")
|
||||
end
|
||||
|
||||
local function daip()
|
||||
return luci.sys.exec("uci get network.lan.ipaddr")
|
||||
end
|
||||
|
||||
local function dase()
|
||||
return luci.sys.exec("uci get openclash.config.dashboard_password 2>/dev/null")
|
||||
end
|
||||
|
||||
local function check_lastversion()
|
||||
return luci.sys.exec("sh /usr/share/openclash/openclash_version.sh && sed -n '/^data:/,$p' /tmp/openclash_last_version 2>/dev/null")
|
||||
end
|
||||
|
||||
local function check_currentversion()
|
||||
return luci.sys.exec("sed -n '/^data:/,$p' /etc/openclash/openclash_version 2>/dev/null")
|
||||
end
|
||||
|
||||
local function startlog()
|
||||
return luci.sys.exec("sed -n '$p' /tmp/openclash_start.log 2>/dev/null")
|
||||
end
|
||||
|
||||
function action_status()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
clash = is_running(),
|
||||
watchdog = is_watchdog(),
|
||||
daip = daip(),
|
||||
dase = dase(),
|
||||
web = is_web(),
|
||||
cn_port = cn_port();
|
||||
})
|
||||
end
|
||||
function action_state()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
config_check = config_check(),
|
||||
config = config(),
|
||||
lhie1 = lhie1(),
|
||||
ConnersHua = ConnersHua(),
|
||||
ConnersHua_return = ConnersHua_return(),
|
||||
ipdb = ipdb();
|
||||
})
|
||||
end
|
||||
|
||||
function action_lastversion()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
lastversion = check_lastversion();
|
||||
})
|
||||
end
|
||||
|
||||
function action_currentversion()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
currentversion = check_currentversion();
|
||||
})
|
||||
end
|
||||
|
||||
function action_start()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
startlog = startlog();
|
||||
})
|
||||
end
|
||||
@ -0,0 +1,46 @@
|
||||
|
||||
local NXFS = require "nixio.fs"
|
||||
local SYS = require "luci.sys"
|
||||
local HTTP = require "luci.http"
|
||||
local DISP = require "luci.dispatcher"
|
||||
local UTIL = require "luci.util"
|
||||
|
||||
local t = {
|
||||
{enable, disable}
|
||||
}
|
||||
|
||||
a = SimpleForm("apply")
|
||||
a.reset = false
|
||||
a.submit = false
|
||||
s = a:section(Table, t)
|
||||
|
||||
o = s:option(Button, "enable")
|
||||
o.inputtitle = translate("Enable Clash")
|
||||
o.inputstyle = "apply"
|
||||
o.write = function()
|
||||
os.execute("uci set openclash.config.enable=1 && uci commit openclash && /etc/init.d/openclash restart >/dev/null 2>&1 &")
|
||||
HTTP.redirect(DISP.build_url("admin", "services", "openclash"))
|
||||
end
|
||||
|
||||
o = s:option(Button, "disable")
|
||||
o.inputtitle = translate("Disable Clash")
|
||||
o.inputstyle = "reset"
|
||||
o.write = function()
|
||||
os.execute("uci set openclash.config.enable=0 && uci commit openclash && /etc/init.d/openclash stop >/dev/null 2>&1 &")
|
||||
end
|
||||
|
||||
m = Map("openclash")
|
||||
m.title = translate("OpenClash")
|
||||
m.description = translate("A Clash Client For OpenWrt")
|
||||
m.pageaction = false
|
||||
|
||||
m:section(SimpleSection).template = "openclash/status"
|
||||
m:section(SimpleSection).template = "openclash/state"
|
||||
m:section(SimpleSection).template = "openclash/myip"
|
||||
|
||||
d = Map("openclash")
|
||||
d.title = translate("Technical Support")
|
||||
d.pageaction = false
|
||||
d:section(SimpleSection).template = "openclash/developer"
|
||||
|
||||
return m, a, d
|
||||
@ -0,0 +1,74 @@
|
||||
|
||||
local NXFS = require "nixio.fs"
|
||||
local SYS = require "luci.sys"
|
||||
local HTTP = require "luci.http"
|
||||
local DISP = require "luci.dispatcher"
|
||||
local UTIL = require "luci.util"
|
||||
|
||||
|
||||
local http = luci.http
|
||||
|
||||
ful = SimpleForm("upload", translate("Server Configuration"), nil)
|
||||
ful.reset = false
|
||||
ful.submit = false
|
||||
|
||||
sul =ful:section(SimpleSection, "", translate(""))
|
||||
o = sul:option(FileUpload, "")
|
||||
o.title = translate("Upload Clash Configuration")
|
||||
o.template = "openclash/clash_upload"
|
||||
o.description = translate("NB: Rename your config file to config.yml before upload. file will save to /etc/openclash")
|
||||
um = sul:option(DummyValue, "", nil)
|
||||
um.template = "openclash/clash_dvalue"
|
||||
|
||||
local dir, fd
|
||||
dir = "/etc/openclash/"
|
||||
http.setfilehandler(
|
||||
function(meta, chunk, eof)
|
||||
if not fd then
|
||||
if not meta then return end
|
||||
|
||||
if meta and chunk then fd = nixio.open(dir .. meta.file, "w") end
|
||||
|
||||
if not fd then
|
||||
um.value = translate("upload file error.")
|
||||
return
|
||||
end
|
||||
end
|
||||
if chunk and fd then
|
||||
fd:write(chunk)
|
||||
end
|
||||
if eof and fd then
|
||||
fd:close()
|
||||
fd = nil
|
||||
um.value = translate("File saved to") .. ' "/etc/openclash/' .. meta.file .. '"'
|
||||
SYS.exec("cp /etc/openclash/config.yml /etc/openclash/config.bak")
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
if luci.http.formvalue("upload") then
|
||||
local f = luci.http.formvalue("ulfile")
|
||||
if #f <= 0 then
|
||||
um.value = translate("No specify upload file.")
|
||||
end
|
||||
end
|
||||
|
||||
m = Map("openclash")
|
||||
s = m:section(TypedSection, "openclash")
|
||||
s.anonymous = true
|
||||
s.addremove=false
|
||||
|
||||
|
||||
local conf = "/etc/openclash/config.yml"
|
||||
sev = s:option(TextValue, "conf")
|
||||
sev.readonly=true
|
||||
sev.description = translate("Changes to config file must be made from source")
|
||||
sev.rows = 20
|
||||
sev.wrap = "off"
|
||||
sev.cfgvalue = function(self, section)
|
||||
return NXFS.readfile(conf) or ""
|
||||
end
|
||||
sev.write = function(self, section, value)
|
||||
end
|
||||
|
||||
return ful , m
|
||||
@ -0,0 +1,28 @@
|
||||
--
|
||||
local NXFS = require "nixio.fs"
|
||||
local SYS = require "luci.sys"
|
||||
local HTTP = require "luci.http"
|
||||
local DISP = require "luci.dispatcher"
|
||||
local UTIL = require "luci.util"
|
||||
|
||||
|
||||
m = Map("openclash", translate("Server logs"))
|
||||
s = m:section(TypedSection, "openclash")
|
||||
m.pageaction = false
|
||||
s.anonymous = true
|
||||
s.addremove=false
|
||||
|
||||
local clog = "/tmp/openclash.log"
|
||||
log = s:option(TextValue, "clog")
|
||||
log.readonly=true
|
||||
log.description = translate("")
|
||||
log.rows = 29
|
||||
log.wrap = "off"
|
||||
log.cfgvalue = function(self, section)
|
||||
return NXFS.readfile(clog) or ""
|
||||
end
|
||||
log.write = function(self, section, value)
|
||||
NXFS.writefile(clog, value:gsub("\r\n", "\n"))
|
||||
end
|
||||
|
||||
return m
|
||||
@ -0,0 +1,123 @@
|
||||
--
|
||||
local NXFS = require "nixio.fs"
|
||||
local SYS = require "luci.sys"
|
||||
local HTTP = require "luci.http"
|
||||
local DISP = require "luci.dispatcher"
|
||||
local UTIL = require "luci.util"
|
||||
|
||||
m = Map("openclash", translate("Rules Setting"))
|
||||
s = m:section(TypedSection, "openclash")
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(ListValue, "enable_custom_clash_rules", translate("Custom Clash Rules"))
|
||||
o.description = translate("Use Custom Rules")
|
||||
o:value("0", translate("Disable Custom Clash Rules"))
|
||||
o:value("1", translate("Enable Custom Clash Rules"))
|
||||
o.default = 0
|
||||
|
||||
o = s:option(ListValue, "rule_source", translate("Enable Other Rules"))
|
||||
o.description = translate("Use Other Rules")
|
||||
o:value("0", translate("Disable Other Rules"))
|
||||
o:value("lhie1", translate("lhie1 Rules"))
|
||||
o:value("ConnersHua", translate("ConnersHua Rules"))
|
||||
o:value("ConnersHua_return", translate("ConnersHua Return Rules"))
|
||||
|
||||
os.execute("awk '/Proxy Group:/,/Rule:/{print}' /etc/openclash/config.yml |grep ^- |grep name: |sed 's/,.*//' |awk -F 'name: ' '{print $2}' |sed 's/\"//g' >/tmp/Proxy_Group 2>&1")
|
||||
os.execute("echo 'DIRECT' >>/tmp/Proxy_Group")
|
||||
os.execute("echo 'REJECT' >>/tmp/Proxy_Group")
|
||||
file = io.open("/tmp/Proxy_Group", "r");
|
||||
|
||||
o = s:option(ListValue, "GlobalTV", translate("GlobalTV"))
|
||||
o:depends("rule_source", "lhie1")
|
||||
o:depends("rule_source", "ConnersHua")
|
||||
for l in file:lines() do
|
||||
o:value(l)
|
||||
end
|
||||
file:seek("set")
|
||||
o = s:option(ListValue, "AsianTV", translate("AsianTV"))
|
||||
o:depends("rule_source", "lhie1")
|
||||
o:depends("rule_source", "ConnersHua")
|
||||
for l in file:lines() do
|
||||
o:value(l)
|
||||
end
|
||||
file:seek("set")
|
||||
o = s:option(ListValue, "Proxy", translate("Proxy"))
|
||||
o:depends("rule_source", "lhie1")
|
||||
o:depends("rule_source", "ConnersHua")
|
||||
o:depends("rule_source", "ConnersHua_return")
|
||||
for l in file:lines() do
|
||||
o:value(l)
|
||||
end
|
||||
file:seek("set")
|
||||
o = s:option(ListValue, "Apple", translate("Apple"))
|
||||
o:depends("rule_source", "lhie1")
|
||||
o:depends("rule_source", "ConnersHua")
|
||||
for l in file:lines() do
|
||||
o:value(l)
|
||||
end
|
||||
file:seek("set")
|
||||
o = s:option(ListValue, "AdBlock", translate("AdBlock"))
|
||||
o:depends("rule_source", "lhie1")
|
||||
o:depends("rule_source", "ConnersHua")
|
||||
for l in file:lines() do
|
||||
o:value(l)
|
||||
end
|
||||
file:seek("set")
|
||||
o = s:option(ListValue, "Domestic", translate("Domestic"))
|
||||
o:depends("rule_source", "lhie1")
|
||||
o:depends("rule_source", "ConnersHua")
|
||||
for l in file:lines() do
|
||||
o:value(l)
|
||||
end
|
||||
file:seek("set")
|
||||
o = s:option(ListValue, "Others", translate("Others"))
|
||||
o:depends("rule_source", "lhie1")
|
||||
o:depends("rule_source", "ConnersHua")
|
||||
o:depends("rule_source", "ConnersHua_return")
|
||||
o.description = translate("Choose Proxy Group, Base On Your Servers Group in config.yml")
|
||||
for l in file:lines() do
|
||||
o:value(l)
|
||||
end
|
||||
file:close()
|
||||
|
||||
custom_rules = s:option(Value, "custom_rules", translate("Custom Clash Rules Here"), translate("For More Go Github:https://github.com/Dreamacro/clash"))
|
||||
custom_rules.template = "cbi/tvalue"
|
||||
custom_rules.rows = 20
|
||||
custom_rules.wrap = "off"
|
||||
custom_rules:depends("enable_custom_clash_rules", 1)
|
||||
|
||||
function custom_rules.cfgvalue(self, section)
|
||||
return NXFS.readfile("/etc/config/openclash_custom_rules.list") or ""
|
||||
end
|
||||
function custom_rules.write(self, section, value)
|
||||
if value then
|
||||
value = value:gsub("\r\n", "\n")
|
||||
NXFS.writefile("/etc/config/openclash_custom_rules.list", value)
|
||||
end
|
||||
end
|
||||
|
||||
local t = {
|
||||
{Commit, Apply}
|
||||
}
|
||||
|
||||
a = SimpleForm("apply")
|
||||
a.reset = false
|
||||
a.submit = false
|
||||
s = a:section(Table, t)
|
||||
|
||||
o = s:option(Button, "Commit")
|
||||
o.inputtitle = translate("Commit Configurations")
|
||||
o.inputstyle = "apply"
|
||||
o.write = function()
|
||||
os.execute("uci commit openclash")
|
||||
end
|
||||
|
||||
o = s:option(Button, "Apply")
|
||||
o.inputtitle = translate("Apply Configurations")
|
||||
o.inputstyle = "apply"
|
||||
o.write = function()
|
||||
os.execute("uci commit openclash && /etc/init.d/openclash restart >/dev/null 2>&1 &")
|
||||
HTTP.redirect(DISP.build_url("admin", "services", "openclash"))
|
||||
end
|
||||
|
||||
return m , a
|
||||
@ -0,0 +1,107 @@
|
||||
|
||||
local NXFS = require "nixio.fs"
|
||||
local SYS = require "luci.sys"
|
||||
local HTTP = require "luci.http"
|
||||
local DISP = require "luci.dispatcher"
|
||||
local UTIL = require "luci.util"
|
||||
|
||||
local t = {
|
||||
{Commit, Apply}
|
||||
}
|
||||
|
||||
a = SimpleForm("apply")
|
||||
a.reset = false
|
||||
a.submit = false
|
||||
s = a:section(Table, t)
|
||||
|
||||
o = s:option(Button, "Commit")
|
||||
o.inputtitle = translate("Commit Configurations")
|
||||
o.inputstyle = "apply"
|
||||
o.write = function()
|
||||
os.execute("uci commit openclash")
|
||||
end
|
||||
|
||||
o = s:option(Button, "Apply")
|
||||
o.inputtitle = translate("Apply Configurations")
|
||||
o.inputstyle = "apply"
|
||||
o.write = function()
|
||||
os.execute("uci commit openclash && /etc/init.d/openclash restart >/dev/null 2>&1 &")
|
||||
HTTP.redirect(DISP.build_url("admin", "services", "openclash"))
|
||||
end
|
||||
|
||||
m = Map("openclash", translate("Clash Settings"))
|
||||
m.pageaction = false
|
||||
|
||||
s = m:section(TypedSection, "openclash")
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(ListValue, "en_mode", translate("Select Mode"))
|
||||
o.description = translate("Will to Take Over Your General Settings, Network Error Try Flush DNS Cache")
|
||||
o:value("0", translate("Disable Mode Control"))
|
||||
o:value("redir-host", translate("redir-host"))
|
||||
o:value("fake-ip", translate("fake-ip"))
|
||||
o.default = 0
|
||||
|
||||
o = s:option(ListValue, "enable_custom_dns", translate("Custom DNS Setting"))
|
||||
o.description = translate("Set OpenClash Upstream DNS Resolve Server")
|
||||
o:value("0", translate("Disable Custom DNS Setting"))
|
||||
o:value("1", translate("Enable Custom DNS Setting"))
|
||||
o.default = 0
|
||||
|
||||
o = s:option(Value, "proxy_port")
|
||||
o.title = translate("Clash config redir-port")
|
||||
o.default = 7892
|
||||
o.datatype = "port"
|
||||
o.rmempty = false
|
||||
o.description = translate("Clash Redir Port, Please Make Sure Ports Available")
|
||||
|
||||
o = s:option(Value, "cn_port")
|
||||
o.title = translate("Dashboard Port")
|
||||
o.default = 9090
|
||||
o.datatype = "port"
|
||||
o.rmempty = false
|
||||
o.description = translate("Dashboard hostname is Your Router IP. Dashboard:192.168.1.1/openclash")
|
||||
|
||||
o = s:option(Value, "dashboard_password")
|
||||
o.title = translate("Dashboard Secret")
|
||||
o.default = 123456
|
||||
o.rmempty = false
|
||||
o.description = translate("Set Dashboard Secret")
|
||||
|
||||
-- [[ Edit Server ]] --
|
||||
s = m:section(TypedSection, "dns_servers", translate("Add Custom DNS Servers"))
|
||||
s.anonymous = true
|
||||
s.addremove = true
|
||||
s.sortable = false
|
||||
s.template = "cbi/tblsection"
|
||||
s.rmempty = false
|
||||
|
||||
---- group
|
||||
o = s:option(ListValue, "group", translate("DNS Server Group"))
|
||||
o:value("nameserver", translate("Nameserver"))
|
||||
o:value("fallback", translate("Fallback"))
|
||||
o.default = "udp"
|
||||
o.rempty = false
|
||||
|
||||
---- IP address
|
||||
o = s:option(Value, "ip", translate("DNS Server IP"))
|
||||
o.datatype = "or(host, string)"
|
||||
o.rmempty = false
|
||||
|
||||
---- port
|
||||
o = s:option(Value, "port", translate("DNS Server Port"))
|
||||
o.placeholder = "53"
|
||||
o.datatype = "port"
|
||||
o.rempty = false
|
||||
|
||||
---- type
|
||||
o = s:option(ListValue, "type", translate("DNS Server Type"))
|
||||
o:value("udp", translate("udp"))
|
||||
o:value("tcp", translate("tcp"))
|
||||
o:value("tls", translate("tls"))
|
||||
o.default = "udp"
|
||||
o.rempty = false
|
||||
|
||||
return m, a
|
||||
|
||||
|
||||
@ -0,0 +1,97 @@
|
||||
--
|
||||
local NXFS = require "nixio.fs"
|
||||
local SYS = require "luci.sys"
|
||||
local HTTP = require "luci.http"
|
||||
local DISP = require "luci.dispatcher"
|
||||
local UTIL = require "luci.util"
|
||||
|
||||
m = Map("openclash", translate("Update Setting"))
|
||||
s = m:section(TypedSection, "openclash", translate("Subscription Update"))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(Flag, "auto_update", translate("Auto Update"))
|
||||
o.description = translate("Auto Update Server subscription")
|
||||
o.default=0
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "auto_update_time", translate("Update time (every day)"))
|
||||
for t = 0,23 do
|
||||
o:value(t, t..":00")
|
||||
end
|
||||
o.default=0
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "subscribe_url")
|
||||
o.title = translate("Subcription Url")
|
||||
o.description = translate("Server Subscription Address")
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(Button,translate("Config File Update"))
|
||||
o.title = translate("Update Subcription")
|
||||
o.inputtitle = translate("Update Configuration")
|
||||
o.inputstyle = "reload"
|
||||
o.write = function()
|
||||
SYS.call("uci commit openclash && sh /usr/share/openclash/openclash.sh >/dev/null 2>&1 &")
|
||||
HTTP.redirect(DISP.build_url("admin", "services", "openclash"))
|
||||
end
|
||||
|
||||
f = m:section(TypedSection, "openclash", translate("Other Rules Update(Only in Use)"))
|
||||
f.anonymous = true
|
||||
o = f:option(Flag, "other_rule_auto_update", translate("Auto Update"))
|
||||
o.description = translate("Auto Update Other Rules")
|
||||
o.default=0
|
||||
o.rmempty = false
|
||||
|
||||
o = f:option(ListValue, "other_rule_update_week_time", translate("Update Time (Every Week)"))
|
||||
o:value("1", translate("Every Monday"))
|
||||
o:value("2", translate("Every Tuesday"))
|
||||
o:value("3", translate("Every Wednesday"))
|
||||
o:value("4", translate("Every Thursday"))
|
||||
o:value("5", translate("Every Friday"))
|
||||
o:value("6", translate("Every Saturday"))
|
||||
o:value("7", translate("Every Sunday"))
|
||||
o.default=1
|
||||
|
||||
o = f:option(ListValue, "other_rule_update_day_time", translate("Update time (every day)"))
|
||||
for t = 0,23 do
|
||||
o:value(t, t..":00")
|
||||
end
|
||||
o.default=0
|
||||
|
||||
o = f:option(Button,translate("Other Rules Update"))
|
||||
o.title = translate("Update Other Rules")
|
||||
o.inputtitle = translate("Start Update Other Rules")
|
||||
o.inputstyle = "reload"
|
||||
o.write = function()
|
||||
SYS.call("uci commit openclash && sh /usr/share/openclash/openclash_rule.sh >/dev/null 2>&1 &")
|
||||
HTTP.redirect(DISP.build_url("admin", "services", "openclash"))
|
||||
end
|
||||
|
||||
u = m:section(TypedSection, "openclash", translate("GEOIP(By MaxMind) Update"))
|
||||
u.anonymous = true
|
||||
o = u:option(Button,translate("GEOIP Database Update"))
|
||||
o.title = translate("Update GEOIP Database")
|
||||
o.inputtitle = translate("Start Update GEOIP Database")
|
||||
o.inputstyle = "reload"
|
||||
o.write = function()
|
||||
SYS.call("sh /usr/share/openclash/openclash_ipdb.sh >/dev/null 2>&1 &")
|
||||
HTTP.redirect(DISP.build_url("admin", "services", "openclash"))
|
||||
end
|
||||
|
||||
local t = {
|
||||
{Commit}
|
||||
}
|
||||
|
||||
a = SimpleForm("apply")
|
||||
a.reset = false
|
||||
a.submit = false
|
||||
s = a:section(Table, t)
|
||||
|
||||
o = s:option(Button, "Commit")
|
||||
o.inputtitle = translate("Commit Configurations")
|
||||
o.inputstyle = "apply"
|
||||
o.write = function()
|
||||
os.execute("uci commit openclash")
|
||||
end
|
||||
|
||||
return m , a
|
||||
@ -0,0 +1,8 @@
|
||||
<%+cbi/valueheader%>
|
||||
<span style="color: green">
|
||||
<%
|
||||
local val = self:cfgvalue(section) or self.default or ""
|
||||
write(pcdata(val))
|
||||
%>
|
||||
</span>
|
||||
<%+cbi/valuefooter%>
|
||||
@ -0,0 +1,5 @@
|
||||
<%+cbi/valueheader%>
|
||||
<label class="cbi-value" style="display:inline-block;" for="ulfile"></label>
|
||||
<input class="cbi-input-file" style="width: 400px" type="file" id="ulfile" name="ulfile" />
|
||||
<input type="submit" class="cbi-button cbi-input-reload" name="upload" value="<%:Upload%>" />
|
||||
<%+cbi/valuefooter%>
|
||||
@ -0,0 +1,56 @@
|
||||
<fieldset class="cbi-section">
|
||||
<table>
|
||||
<tr><td width="25%"> Clash 主程序发布: </td><td width="25%" align="left" id="_binupdate"><%:Collecting data...%></td><td width="25%"> OpenClash 客户端发布: </td><td width="25%" align="left" id="_openupdate"><%:Collecting data...%></td></tr>
|
||||
<tr><td width="25%"> Clash 主程序开发: Dreamacro </td><td width="25%" align="left" id="_Dreamacro"><%:Collecting data...%></td><td width="25%"> OpenClash 客户端开发: vernesong </td><td width="25%" align="left" id="_vernesong"><%:Collecting data...%></td></tr>
|
||||
<tr><td width="25%"> Clash 客户端开发: frainzy1477 </td><td width="25%" align="left" id="_frainzy1477"><%:Collecting data...%></td><td width="25%"> MyIP: SukkaW </td><td width="25%" align="left" id="_SukkaW"><%:Collecting data...%></td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var Dreamacro = document.getElementById('_Dreamacro');
|
||||
var vernesong = document.getElementById('_vernesong');
|
||||
var frainzy1477 = document.getElementById('_frainzy1477');
|
||||
var SukkaW = document.getElementById('_SukkaW');
|
||||
var binupdate = document.getElementById('_binupdate');
|
||||
var openupdate = document.getElementById('_openupdate');
|
||||
var github = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAdCAMAAACKeiw+AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyFpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQyIDc5LjE2MDkyNCwgMjAxNy8wNy8xMy0wMTowNjozOSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpGRjUyRDgzQjhBRDcxMUU5ODM5RkRFNTEzOTgzREM4RiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpGRjUyRDgzQzhBRDcxMUU5ODM5RkRFNTEzOTgzREM4RiI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkZGNTJEODM5OEFENzExRTk4MzlGREU1MTM5ODNEQzhGIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkZGNTJEODNBOEFENzExRTk4MzlGREU1MTM5ODNEQzhGIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+F8FkZAAAAddQTFRF////AAAAAQEBAgICcnJyAwMDVVBLZmZma2trFxcXDQ0NCwsLjY2NuLi4UFBQurq6e3t7NjY2PDw8m5ubSEhISkpKMDAw7OTe/vv5cXFxqKiovLy819fX1MvEtbW1hX56UEtG5t/YhX54/f39WVlZmpqaLyso4drU1s7HXFxcVVFNf39/WVJM0dLSoKCgk5OTfHx8ysrKLi4uvb29RkZG6+vrp52Vr6+v1MzGpZuU5d7Z8uvkvrSr8Orkw8PD1cvCWFNNqaKdx720PDczxLqxw7qzQUFBV1dXQDs3qZ+W8fHx0Ma9t62ksbGxubq7IiIhCAgInp6eDg4O5t7Xsami7u7u/fv5oaGhcHBwISIjbGxsJiYnqamp0snA/Pz8o6Oj8PDw1tbWwbivz8/PBwcHUE1L//38g3pzOzs7wcHBSEVFZWVlq6ur29LLn5+fpJuSfHZyIB8f5OTkyMjIYGBgJCIfPj4+ubCoMCwpPDg0FBQUtKqhQEBATEpH6ubi4tnRDg8Qs7Oz1s3F8uvm6enpHhsZvrSsVFBMioN8JiYmsaql+vby/fr3IiIiKioqZ2Bb9/PvhH13HhwaVlRR6eDZPz8/MzMzDQ0OEQ8OOzg0kImCnZSL////7wd0TgAAAJ10Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AMv8vEwAAAF8SURBVHjabNNlY4MwEAbgO2jn1rm7u7u7u7u7u7u7a3/scmSsDHYfmuR9gKbNAcbf2r30e+rqGJkvyDRlIE98yvG31ktUfFSEf+qxScmDqKkME6fiPzUmczZbiIKSBJF9fHF+ZlO9V42rgAIrdp1w0TdkycI84tENNisFAN8X3fRSwkHUeCxb2LHw/YpxIT0tAlTlQGkFY3+aJKp5m9KTawiQ9rKq5jIpDodmGkRvNbdsUn4ODzS4gKY6KT+DSRo8tBxHf8QCvBE7aLmB2Ar2iS20bMN5h9hZyxaU10EgDY0pag26oTwS1qQfGK9mJ+mIPsFNYrH7r06IUjwDxmjE9lcUlo9NWKnjutIKxh7EWTBHHDaY95P16gzWP8deTeedj2gDjmyVzO+dkpsi1J04i331IthZ3uZyTpMbZ483UxVisGJbST+6JbdiMaKjk23IAGd7rnOmRj6ktd5TyafK1+DejLVnG2dbhh85qpco7M66lnNMvVm6nH4LMAB50ohVhJZ1iwAAAABJRU5ErkJggg=="
|
||||
var release = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAeCAMAAAAfOR5kAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyFpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQyIDc5LjE2MDkyNCwgMjAxNy8wNy8xMy0wMTowNjozOSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpDNTk0NDQzNThBRDgxMUU5OTgwMkVGQkFDRDdENTg1MyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpDNTk0NDQzNjhBRDgxMUU5OTgwMkVGQkFDRDdENTg1MyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkM1OTQ0NDMzOEFEODExRTk5ODAyRUZCQUNEN0Q1ODUzIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkM1OTQ0NDM0OEFEODExRTk5ODAyRUZCQUNEN0Q1ODUzIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+JpJc6gAAAPZQTFRFAAAA////+Pj4/v7+/f39+/v7AQEB39/f/Pz88vLyKysr3d3dCgoKpqam6urq4eHh7e3t4+Pj5eXlycnJ9PT09fX1BQUF9/f3AgICy8vLDg4OYmJi2NjY2tra8PDwz8/PNDQ0Pz8/v7+/ra2tu7u7wcHBQkJCjo6Om5ubXFxcXV1dDAwMCQkJLS0trKyszMzMIyMjRUVF0tLSxMTEeXl5ZWVlJiYm+vr61NTUjY2NyMjIXl5ekZGR6OjoV1dXoqKiLi4uRkZGT09P7OzsdnZ2fn5+xsbGsbGx1tbW5+fnFhYW3t7e8fHxY2NjkJCQJSUlERER////3OeyVgAAAFJ0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////AK0tDHEAAAD0SURBVHjajNHXUsMwEAXQKxfshFSSEDoEEnrvvYeS0O7//wyWZEaOpQf2YUd7ZrRaSWBwtesxE+3ybEywAGDdC57mL1/mKmHrKym9hN8g40dlbKv8kfAhrKgk3LR0zE975/iGEEt2k5KPRTjiFRsuXkXRxfu4d/E3nl18i7qLp8ETWzsCDAYWy6fi2cEo7rQomeJuxuDkdUDNZNzY1Pi4HCpA+icLmt/T8o8nNI//jwtTimuGw71qdXhUUmN0o6je8BSLsvoSmdSWCz9t0sveZsX0joyeZ49snmrcqo1OEj9ILbZzA1L0gU+feSbXjs36V4ABANF7Sn61vZbYAAAAAElFTkSuQmCC"
|
||||
Dreamacro.innerHTML = '<img src="'+github+'" alt="Dreamacro" width="30" onclick="return Dreamacro_rediret()">';
|
||||
vernesong.innerHTML = '<img src="'+github+'" alt="vernesong" width="30" onclick="return vernesong_rediret()">';
|
||||
frainzy1477.innerHTML = '<img src="'+github+'" alt="frainzy1477" width="30" onclick="return frainzy1477_rediret()">';
|
||||
SukkaW.innerHTML = '<img src="'+github+'" alt="SukkaW" width="30" onclick="return SukkaW_rediret()">';
|
||||
binupdate.innerHTML = '<img src="'+release+'" alt="binupdate" width="30" height="30" onclick="return binupdate_rediret()">';
|
||||
openupdate.innerHTML = '<img src="'+release+'" alt="openupdate" width="30" height="30" onclick="return openupdate_rediret()">';
|
||||
|
||||
function Dreamacro_rediret()
|
||||
{
|
||||
url1='https://github.com/Dreamacro';
|
||||
window.open(url1);
|
||||
}
|
||||
function vernesong_rediret()
|
||||
{
|
||||
url2='https://github.com/vernesong';
|
||||
window.open(url2);
|
||||
}
|
||||
function frainzy1477_rediret()
|
||||
{
|
||||
url3='https://github.com/frainzy1477';
|
||||
window.open(url3);
|
||||
}
|
||||
function SukkaW_rediret()
|
||||
{
|
||||
url4='https://github.com/SukkaW';
|
||||
window.open(url4);
|
||||
}
|
||||
function binupdate_rediret()
|
||||
{
|
||||
url5='https://github.com/Dreamacro/clash/releases';
|
||||
window.open(url5);
|
||||
}
|
||||
function openupdate_rediret()
|
||||
{
|
||||
url6='https://github.com/vernesong/OpenClash/releases';
|
||||
window.open(url6);
|
||||
}
|
||||
|
||||
//]]></script>
|
||||
@ -0,0 +1,28 @@
|
||||
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<table>
|
||||
<tr><td align="left"><input type="button" class="cbi-button cbi-button-reload" value="<%:刷新%>" onclick="refreshFrame(200)"/></td></tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr><td><iframe id="myip" name="myip" src="https://ip.skk.moe/simple/" scrolling="no" onerror="return refreshFrame(5000)" onload="iFrameHeight()" frameborder="0" style="padding: 0px; width:100%; height:120%; float:left; margin:0; padding:0;"></iframe></td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
function iFrameHeight() {
|
||||
var ifm = document.getElementById("myip");
|
||||
var subWeb = document.frames ? document.frames["myip"].document : ifm.contentDocument;
|
||||
if (ifm != null && subWeb != null) {
|
||||
ifm.height = subWeb.body.scrollHeight;
|
||||
ifm.width = subWeb.body.scrollWidth;
|
||||
}
|
||||
}
|
||||
function refreshFrame(delay)
|
||||
{
|
||||
setTimeout(function(){ document.getElementById('myip').src="https://ip.skk.moe/simple/"; }, delay);
|
||||
}
|
||||
|
||||
//]]></script>
|
||||
@ -0,0 +1,28 @@
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<table>
|
||||
<tr><td width="100%" colspan="4" align="center"><b> 一些必要的状态显示,运行前请确保各项目显示正常,需要更新请到更新设置页面操作 </b></td></tr>
|
||||
<tr><td width="25%"> OpenClash 配置文件状态 </td><td width="25%" align="left" id="_config_check"><%:Collecting data...%></td><td width="25%"> OpenClash 配置文件更新日期 </td><td width="25%"v align="left" id="_config"><%:Collecting data...%></td></tr>
|
||||
<tr><td width="25%"> GEOIP(By MaxMind) 数据库日期 </td><td width="25%" align="left" id="_ipdb"><%:Collecting data...%></td><td width="25%"> lhie1 规则更新日期 </td><td width="25%" align="left" id="_lhie1"><%:Collecting data...%></td></tr>
|
||||
<tr><td width="25%"> ConnersHua 规则更新日期 </td><td width="25%" align="left" id="_ConnersHua"><%:Collecting data...%></td><td width="25%"> ConnersHua 回国规则更新日期 </td><td width="25%" align="left" id="_ConnersHua_return"><%:Collecting data...%></td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var config = document.getElementById('_config');
|
||||
var ipdb = document.getElementById('_ipdb');
|
||||
var lhie1 = document.getElementById('_lhie1');
|
||||
var ConnersHua = document.getElementById('_ConnersHua');
|
||||
var ConnersHua_return = document.getElementById('_ConnersHua_return');
|
||||
var config_check = document.getElementById('_config_check');
|
||||
XHR.poll(2, '<%=luci.dispatcher.build_url("admin", "services", "openclash", "state")%>', null, function(x, status) {
|
||||
if ( x && x.status == 200 ) {
|
||||
config_check.innerHTML = status.config_check ? '<b><font color=green><%:Config Normal%></font></b>' : '<b><font color=red><%:Config Abnormal%></font></b>';
|
||||
config.innerHTML = status.config ? "<b><font color=green>"+status.config+"</font></b>" : "<b><font color=red>"+"<%:File No Update%>"+"</font></b>";
|
||||
ipdb.innerHTML = status.ipdb ? "<b><font color=green>"+status.ipdb+"</font></b>" : "<b><font color=red>"+"<%:File Not Exist%>"+"</font></b>";
|
||||
lhie1.innerHTML = status.lhie1 ? "<b><font color=green>"+status.lhie1+"</font></b>" : "<b><font color=red>"+"<%:File Not Exist%>"+"</font></b>";
|
||||
ConnersHua.innerHTML = status.ConnersHua ? "<b><font color=green>"+status.ConnersHua+"</font></b>" : "<b><font color=red>"+"<%:File Not Exist%>"+"</font></b>";
|
||||
ConnersHua_return.innerHTML = status.ConnersHua_return ? "<b><font color=green>"+status.ConnersHua_return+"</font></b>" : "<b><font color=red>"+"<%:File Not Exist%>"+"</font></b>";
|
||||
}
|
||||
});
|
||||
//]]></script>
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 6.0 KiB |
@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<title>Clash</title>
|
||||
<link href="main.5b2a02b81ea75793d649.css" rel="stylesheet"></head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="text/javascript" src="js/1.bundle.5b2a02b81ea75793d649.min.js"></script><script type="text/javascript" src="js/bundle.5b2a02b81ea75793d649.min.js"></script></body>
|
||||
</html>
|
||||
93
package/cnsztl/luci-app-openclash/files/usr/share/openclash/dashboard/js/1.bundle.5b2a02b81ea75793d649.min.js
vendored
Executable file
93
package/cnsztl/luci-app-openclash/files/usr/share/openclash/dashboard/js/1.bundle.5b2a02b81ea75793d649.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
79
package/cnsztl/luci-app-openclash/files/usr/share/openclash/dashboard/js/1.bundle.7fa6738617874ea86872.min.js
vendored
Executable file
79
package/cnsztl/luci-app-openclash/files/usr/share/openclash/dashboard/js/1.bundle.7fa6738617874ea86872.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
1
package/cnsztl/luci-app-openclash/files/usr/share/openclash/dashboard/js/bundle.5b2a02b81ea75793d649.min.js
vendored
Executable file
1
package/cnsztl/luci-app-openclash/files/usr/share/openclash/dashboard/js/bundle.5b2a02b81ea75793d649.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
1
package/cnsztl/luci-app-openclash/files/usr/share/openclash/dashboard/js/bundle.7fa6738617874ea86872.min.js
vendored
Executable file
1
package/cnsztl/luci-app-openclash/files/usr/share/openclash/dashboard/js/bundle.7fa6738617874ea86872.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
39
package/cnsztl/luci-app-openclash/files/usr/share/openclash/openclash.sh
Executable file
39
package/cnsztl/luci-app-openclash/files/usr/share/openclash/openclash.sh
Executable file
@ -0,0 +1,39 @@
|
||||
#!/bin/sh
|
||||
START_LOG="/tmp/openclash_start.log"
|
||||
LOGTIME=$(date "+%Y-%m-%d %H:%M:%S")
|
||||
echo "开始下载配置文件..." >$START_LOG
|
||||
subscribe_url=$(uci get openclash.config.subscribe_url 2>/dev/null)
|
||||
wget-ssl --no-check-certificate "$subscribe_url" -O /tmp/config.yml
|
||||
if [ "$?" -eq "0" ]; then
|
||||
echo "配置文件下载成功,检查是否有更新..." >$START_LOG
|
||||
if [ -f /etc/openclash/config.yml ]; then
|
||||
cmp -s /etc/openclash/config.bak /tmp/config.yml
|
||||
if [ "$?" -ne "0" ]; then
|
||||
echo "配置文件有更新,开始替换..." >$START_LOG
|
||||
mv /tmp/config.yml /etc/openclash/config.yml 2>/dev/null\
|
||||
&& cp /etc/openclash/config.yml /etc/openclash/config.bak\
|
||||
&& echo "配置文件替换成功,开始启动 OpenClash ..." >$START_LOG\
|
||||
&& /etc/init.d/openclash restart 2>/dev/null
|
||||
echo "${LOGTIME} Config Update Successful" >>/tmp/openclash.log
|
||||
else
|
||||
echo "配置文件没有任何更新,停止继续操作..." >$START_LOG
|
||||
rm -rf /tmp/config.yml
|
||||
echo "${LOGTIME} Updated Config No Change, Do Nothing" >>/tmp/openclash.log
|
||||
sleep 5
|
||||
echo "" >$START_LOG
|
||||
fi
|
||||
else
|
||||
echo "配置文件下载成功,本地没有配置文件,开始创建 ..." >$START_LOG
|
||||
mv /tmp/config.yml /etc/openclash/config.yml 2>/dev/null\
|
||||
&& cp /etc/openclash/config.yml /etc/openclash/config.bak\
|
||||
&& echo "配置文件创建成功,开始启动 OpenClash ..." >$START_LOG\
|
||||
&& /etc/init.d/openclash restart 2>/dev/null
|
||||
echo "${LOGTIME} Config Update Successful" >>/tmp/openclash.log
|
||||
fi
|
||||
else
|
||||
echo "配置文件下载失败,请检查网络或稍后再试!" >$START_LOG
|
||||
echo "${LOGTIME} Config Update Error" >>/tmp/openclash.log
|
||||
rm -rf /tmp/config.yml 2>/dev/null
|
||||
sleep 10
|
||||
echo "" >$START_LOG
|
||||
fi
|
||||
@ -0,0 +1,35 @@
|
||||
#!/bin/sh
|
||||
START_LOG="/tmp/openclash_start.log"
|
||||
LOGTIME=$(date "+%Y-%m-%d %H:%M:%S")
|
||||
echo "开始下载 GEOIP 数据库..." >$START_LOG
|
||||
wget-ssl --no-check-certificate https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.tar.gz -O /tmp/ipdb.tar.gz
|
||||
if [ "$?" -eq "0" ]; then
|
||||
echo "GEOIP 数据库下载成功,检查数据库版本是否更新..." >$START_LOG
|
||||
tar zxvf /tmp/ipdb.tar.gz -C /tmp >/dev/null 2>&1\
|
||||
&& rm -rf /tmp/ipdb.tar.gz >/dev/null 2>&1
|
||||
cmp -s /tmp/GeoLite2-Country_*/GeoLite2-Country.mmdb /etc/openclash/Country.mmdb
|
||||
if [ "$?" -ne "0" ]; then
|
||||
echo "数据库版本有更新,开始替换数据库版本..." >$START_LOG
|
||||
/etc/init.d/openclash stop\
|
||||
&& mv /tmp/GeoLite2-Country_*/GeoLite2-Country.mmdb /etc/openclash/Country.mmdb >/dev/null 2>&1\
|
||||
&& /etc/init.d/openclash start\
|
||||
&& echo "删除下载缓存..." >$START_LOG\
|
||||
&& rm -rf /tmp/GeoLite2-Country_* >/dev/null 2>&1
|
||||
echo "GEOIP 数据库更新成功!" >$START_LOG
|
||||
echo "${LOGTIME} GEOIP Database Update Successful" >>/tmp/openclash.log
|
||||
sleep 10
|
||||
echo "" >$START_LOG
|
||||
else
|
||||
echo "数据库版本没有更新,停止继续操作..." >$START_LOG
|
||||
echo "${LOGTIME} Updated GEOIP Database No Change, Do Nothing" >>/tmp/openclash.log
|
||||
rm -rf /tmp/GeoLite2-Country_* >/dev/null 2>&1
|
||||
sleep 5
|
||||
echo "" >$START_LOG
|
||||
fi
|
||||
else
|
||||
echo "GEOIP 数据库下载失败,请检查网络或稍后再试!" >$START_LOG
|
||||
rm -rf /tmp/ipdb.tar.gz >/dev/null 2>&1
|
||||
echo "${LOGTIME} GEOIP Database Update Error" >>/tmp/openclash.log
|
||||
sleep 10
|
||||
echo "" >$START_LOG
|
||||
fi
|
||||
@ -0,0 +1,41 @@
|
||||
#!/bin/sh
|
||||
START_LOG="/tmp/openclash_start.log"
|
||||
LOGTIME=$(date "+%Y-%m-%d %H:%M:%S")
|
||||
echo "开始获取使用中的第三方规则名称..." >$START_LOG
|
||||
rule_source=$(uci get openclash.config.rule_source 2>/dev/null)
|
||||
echo "开始下载使用中的第三方规则..." >$START_LOG
|
||||
if [ "$rule_source" = "lhie1" ]; then
|
||||
wget-ssl --no-check-certificate https://raw.githubusercontent.com/lhie1/Rules/master/Clash/Rule.yml -O /tmp/rules.yml
|
||||
elif [ "$rule_source" = "ConnersHua" ]; then
|
||||
wget-ssl --no-check-certificate https://raw.githubusercontent.com/ConnersHua/Profiles/master/Clash/Global.yml -O /tmp/rules.yml
|
||||
sed -i -n '/^Rule:$/,$p' /tmp/rules.yml
|
||||
elif [ "$rule_source" = "ConnersHua_return" ]; then
|
||||
wget-ssl --no-check-certificate https://raw.githubusercontent.com/ConnersHua/Profiles/master/Clash/China.yml -O /tmp/rules.yml
|
||||
sed -i -n '/^Rule:$/,$p' /tmp/rules.yml
|
||||
fi
|
||||
if [ "$?" -eq "0" ] && [ "$rule_source" != 0 ]; then
|
||||
echo "下载成功,开始预处理规则文件..." >$START_LOG
|
||||
sed -i "/^Rule:$/a\##source:${rule_source}" /tmp/rules.yml >/dev/null 2>&1
|
||||
echo "检查下载的规则文件是否有更新..." >$START_LOG
|
||||
cmp -s /etc/openclash/"$rule_source".yml /tmp/rules.yml
|
||||
if [ "$?" -ne "0" ]; then
|
||||
echo "检测到下载的规则文件有更新,开始替换..." >$START_LOG
|
||||
mv /tmp/rules.yml /etc/openclash/"$rule_source".yml >/dev/null 2>&1
|
||||
sed -i '/^Rule:$/a\##updated' /etc/openclash/"$rule_source".yml >/dev/null 2>&1
|
||||
echo "替换成功,重新加载 OpenClash 应用新规则..." >$START_LOG
|
||||
/etc/init.d/openclash reload 2>/dev/null
|
||||
echo "${LOGTIME} Other Rules Update Successful" >>/tmp/openclash.log
|
||||
else
|
||||
echo "检测到下载的规则文件没有更新,停止继续操作..." >$START_LOG
|
||||
rm -rf /tmp/rules.yml >/dev/null 2>&1
|
||||
echo "${LOGTIME} Updated Other Rules No Change, Do Nothing" >>/tmp/openclash.log
|
||||
sleep 10
|
||||
echo "" >$START_LOG
|
||||
fi
|
||||
else
|
||||
echo "第三方规则下载失败,请检查网络或稍后再试!" >$START_LOG
|
||||
rm -rf /tmp/rules.yml >/dev/null 2>&1
|
||||
echo "${LOGTIME} Other Rules Update Error" >>/tmp/openclash.log
|
||||
sleep 10
|
||||
echo "" >$START_LOG
|
||||
fi
|
||||
@ -0,0 +1,22 @@
|
||||
#!/bin/sh
|
||||
START_LOG="/tmp/openclash_start.log"
|
||||
version_url="https://github.com/vernesong/OpenClash/raw/master/version"
|
||||
echo "开始获取最新版本..." >$START_LOG
|
||||
wget-ssl --no-check-certificate --timeout=3 --tries=2 "$version_url" -O /tmp/openclash_last_version
|
||||
if [ "$?" -eq "0" ]; then
|
||||
echo "版本获取成功..." >$START_LOG
|
||||
if [ -f /etc/openclash/openclash_version ]; then
|
||||
echo "对比版本信息..." >$START_LOG
|
||||
if [ "$(sed -n 1p /etc/openclash/openclash_version)" = "$(sed -n 1p /tmp/openclash_last_version)" ]; then
|
||||
echo "" >/tmp/openclash_last_version
|
||||
echo "本地已安装最新版本!" >$START_LOG
|
||||
sleep 10
|
||||
fi
|
||||
fi
|
||||
echo "" >$START_LOG
|
||||
else
|
||||
echo "" >/tmp/openclash_last_version
|
||||
echo "版本获取失败,请稍后再试!" >$START_LOG
|
||||
sleep 10
|
||||
echo "" >$START_LOG
|
||||
fi
|
||||
@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
|
||||
status=`ps|grep -c openclash_watchdog.sh`
|
||||
[ "$status" -gt "3" ] && echo "another clash_watchdog.sh is running,exit "
|
||||
[ "$status" -gt "3" ] && exit 0
|
||||
|
||||
while :;
|
||||
do
|
||||
enable=$(uci get openclash.config.enable)
|
||||
if [ "$enable" -eq 1 ]; then
|
||||
if ! pidof clash >/dev/null; then
|
||||
LOGTIME=$(date "+%Y-%m-%d %H:%M:%S")
|
||||
echo "${LOGTIME} Watchdog: OpenClash Problem, Restart " >>/tmp/openclash.log
|
||||
/etc/init.d/openclash restart
|
||||
fi
|
||||
fi
|
||||
sleep 60
|
||||
done 2>/dev/null
|
||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,20 @@
|
||||
._1EnK5MMInH{width:100%;height:100%;display:flex;justify-content:center;align-items:center}._39z9L5I2ao{--color1:#ddd;--size:40px;width:var(--size);height:var(--size);margin:10px;background-color:var(--color1);border-radius:100%;-webkit-animation:_1DSWK2a-pe 1s ease-in-out infinite;animation:_1DSWK2a-pe 1s ease-in-out infinite}@-webkit-keyframes _1DSWK2a-pe{0%{-webkit-transform:scale(0);transform:scale(0)}to{-webkit-transform:scale(1);transform:scale(1);opacity:0}}@keyframes _1DSWK2a-pe{0%{-webkit-transform:scale(0);transform:scale(0)}to{-webkit-transform:scale(1);transform:scale(1);opacity:0}}
|
||||
._1rJPiLWN4s{position:fixed;top:0;bottom:0;left:0;right:0;overflow:hidden;padding:20px;background:var(--color-background);color:var(--color-text);text-align:center}._3h_IywJG1l{color:#2a477a;opacity:.6;display:flex;justify-content:center;padding:40px}.aXXDDfyTjE,._3h_IywJG1l{align-items:center}.aXXDDfyTjE{display:inline-flex;color:var(--color-text-secondary)}.aXXDDfyTjE:active,.aXXDDfyTjE:hover{color:#387cec}.aXXDDfyTjE svg{margin-right:5px}
|
||||
._30oJwXNik9{background:var(--color-bg-sidebar);position:relative}._1SsCcpJvxN{display:block}._2r8EkOI78X{display:flex;align-items:center;justify-content:center;padding:25px 0 15px;color:#2a477a;transition:color .3s ease-in-out}@media (max-width:768px){._2r8EkOI78X{padding:0}}._2r8EkOI78X:hover{-webkit-animation:_2KRqAfqV8c .3s ease-in-out 0s infinite alternate;animation:_2KRqAfqV8c .3s ease-in-out 0s infinite alternate}._2r8EkOI78X img{width:80px;height:80px}@-webkit-keyframes _2KRqAfqV8c{0%{color:#2a477a}to{color:#1f52ac}}@keyframes _2KRqAfqV8c{0%{color:#2a477a}to{color:#1f52ac}}@media (max-width:768px){._2vUQ0Hs_C5{display:flex;justify-content:space-between;overflow:scroll}}._8mEn9Wlw1n{color:var(--color-text);text-decoration:none;display:flex;align-items:center;padding:8px 20px}@media (max-width:768px){._8mEn9Wlw1n{flex-direction:column}}._8mEn9Wlw1n svg{color:var(--color-icon)}._1WyHmd6t6y{background:var(--color-sb-active-row-bg)}@media (max-width:768px){._1WyHmd6t6y{background:none;border-bottom:2px solid #387cec}}._2eMIYGbP9O{padding-left:14px}@media (max-width:768px){._2eMIYGbP9O{padding-left:0;padding-top:5px}}.nURY8qkFLS{--sz:50px;position:absolute;bottom:0;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%);width:var(--sz);height:var(--sz);padding:20px 0;display:flex;justify-content:center;align-items:center}@media (max-width:768px){.nURY8qkFLS{display:none}}.nURY8qkFLS svg{display:block;color:var(--color-icon)}
|
||||
.SNYKRrv_2I{height:76px;display:flex;align-items:center}.VG1cD2OYvg{padding:0 40px;text-align:left;margin:0}
|
||||
._37kQcxVR4T{color:var(--color-text);display:flex;align-items:center}._1U3kUwas7v,.-Hr5Z5iYfF{padding-top:10px;padding-bottom:10px;width:200px}._1U3kUwas7v div:first-child,.-Hr5Z5iYfF div:first-child{color:var(--color-text-secondary)}._1U3kUwas7v div:nth-child(2),.-Hr5Z5iYfF div:nth-child(2){padding:10px 0 0;font-size:2em}.-Hr5Z5iYfF{padding-right:20px}._1U3kUwas7v{padding-left:20px}
|
||||
._2rN7aLQPCl{padding:10px 40px}
|
||||
._1u5AP7XMF9{padding:0 40px 5px}._2zeyKJDdFH{position:relative;height:40px}._3DQ7SXxKRA{position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);left:0;width:100%}._1f-XUgRxH1{-webkit-appearance:none;background-color:var(--color-input-bg);background-image:none;border-radius:20px;border:1px solid var(--color-input-border);box-sizing:border-box;color:#c1c1c1;display:inline-block;font-size:inherit;height:40px;outline:none;padding:0 15px 0 35px;transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}._3PLtWxZwrd{position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);left:10px}
|
||||
._2tpN_G7FeO{display:flex;align-items:center;flex-wrap:wrap;font-size:.9em;padding:10px}._3wuPHKqO5W{color:#eee;flex-shrink:0;text-align:center;width:66px;background:green;border-radius:5px;padding:3px 5px;margin:0 8px}.IwiVCclCSC{flex-shrink:0;color:#999;font-size:14px}._3I1beKAMFt{flex-shrink:0;display:flex;font-family:Roboto Mono,Menlo,monospace;align-items:center;padding:8px 0;width:100%;white-space:pre;overflow:auto}._2MDNI6JESq{margin:0;padding:0;color:var(--color-text)}._2MDNI6JESq li,._2MDNI6JESq li.even{background:var(--color-background)}._3KX1sKJ1QD{padding:10px 40px}._19_8g6kTIV{display:flex;flex-direction:column;align-items:center;justify-content:center;color:#2d2d30}._19_8g6kTIV div:nth-child(2){color:var(--color-text-secondary);font-size:1.4em;opacity:.6}._3ljFcrWmBC{opacity:.3}
|
||||
input.nJQwngxVo8[type=checkbox]{--white:#fff;--grey:#d3d3d3;--color-theme:#047aff;-webkit-appearance:none;-moz-appearance:none;appearance:none;outline:none;background-color:darken(var(--white),2%);border:1px solid var(--grey);border-radius:26px;box-shadow:inset 0 0 0 1px var(--grey);cursor:pointer;height:28px;position:relative;transition:border .25s .15s,box-shadow .25s .3s,padding .25s;width:44px;vertical-align:top}input.nJQwngxVo8[type=checkbox]:after{background-color:var(--white);border:1px solid var(--grey);border-radius:24px;box-shadow:inset 0 -3px 3px rgba(0,0,0,.025),0 1px 4px rgba(0,0,0,.15),0 4px 4px rgba(0,0,0,.1);content:"";display:block;height:26px;left:0;position:absolute;right:16px;top:0;transition:border .25s .15s,left .25s .1s,right .15s .175s}input.nJQwngxVo8[type=checkbox]:checked{border-color:var(--color-theme);box-shadow:inset 0 0 0 13px var(--color-theme);padding-left:18px;transition:border .25s,box-shadow .25s,padding .25s .15s}input.nJQwngxVo8[type=checkbox]:checked:after{border-color:var(--color-theme);left:16px;right:0;transition:border .25s,left .15s .25s,right .25s .175s}
|
||||
._3evbv-Ui87{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:1px solid #525252;color:var(--color-text);background:var(--color-toggle-bg);display:flex;position:relative}._3evbv-Ui87 input{position:absolute;left:0;opacity:0}._3evbv-Ui87 label{flex:1;z-index:2;display:flex;align-items:center;justify-content:center;padding:10px 0;cursor:pointer}._1ok8KIb1RH{z-index:1;position:absolute;display:block;left:0;height:100%;transition:left .2s ease-out;background:var(--color-toggle-selected)}
|
||||
._2S85tjFa1n{-webkit-appearance:none;background-color:var(--color-input-bg);background-image:none;border-radius:4px;border:1px solid var(--color-input-border);box-sizing:border-box;color:#c1c1c1;display:inline-block;font-size:inherit;height:40px;outline:none;padding:0 15px;transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}._2S85tjFa1n:focus{border-color:var(--color-focus-blue)}input::-webkit-inner-spin-button,input::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}
|
||||
._2A0HoxnDqc{-webkit-appearance:none;outline:none;color:var(--color-btn-fg);background:var(--color-btn-bg);border:1px solid #555;border-radius:100px;padding:6px 12px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}._2A0HoxnDqc:focus{border-color:var(--color-focus-blue)}._2A0HoxnDqc:hover{background:#387cec;border:1px solid #387cec;color:#fff}._2A0HoxnDqc:active{-webkit-transform:scale(.97);transform:scale(.97)}
|
||||
._2id19fefQX{display:flex;flex-wrap:wrap}._2QQQyNTKoG{flex-grow:0;flex-wrap:0;margin-right:10px;margin-bottom:10px;cursor:pointer;border:2px solid transparent}.XJkW0wZSAx{border-color:#387cec}
|
||||
._2OZZRrEL0J{padding:10px 40px 40px}._2OZZRrEL0J>div{width:360px}.lF_ZoyIdZN{padding:10px 40px 40px}.VduFBb2hWX{padding:0 40px}.VduFBb2hWX>div{border-top:1px dashed #373737}._2NQoBOQcGA{padding:16px 0}
|
||||
.ctrHyq7uir{position:fixed;top:0;right:0;left:0;bottom:0;background:#444;z-index:1024}._17mHpKiOUD{outline:none;position:absolute;color:#ddd;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);background:#444;padding:20px;border-radius:10px}
|
||||
._1r-KsYFNaj{position:relative;padding:10px 0}._1r-KsYFNaj input{-webkit-appearance:none;background-color:transparent;background-image:none;border:none;border-radius:0;border-bottom:1px solid var(--color-input-border);box-sizing:border-box;color:#c1c1c1;display:inline-block;font-size:inherit;height:40px;outline:none;padding:0 8px;transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}._1r-KsYFNaj input:focus{border-color:var(--color-focus-blue)}._1r-KsYFNaj label{position:absolute;left:8px;bottom:22px;transition:-webkit-transform .15s ease-in-out;transition:transform .15s ease-in-out;transition:transform .15s ease-in-out,-webkit-transform .15s ease-in-out;-webkit-transform-origin:0 0;transform-origin:0 0}._1r-KsYFNaj input:focus+label,._1r-KsYFNaj label.Hn6h5kxOg7{-webkit-transform:scale(.75) translateY(-25px);transform:scale(.75) translateY(-25px)}._1r-KsYFNaj input:focus+label{color:var(--color-focus-blue)}
|
||||
._3hz7LVhvUv:focus{outline:none}._3HF-KB9mgO{display:flex;justify-content:center;align-items:center}._3HF-KB9mgO ._3HzgPICn91{color:#2d2d30;opacity:.4;transition:opacity .4s}._3HF-KB9mgO ._3HzgPICn91:hover{opacity:.7}._1wpZuvoD5I{padding:30px 0 10px}.L7jTy-EFJ2{display:flex}.L7jTy-EFJ2 div{flex:1 1 auto}.L7jTy-EFJ2 div:nth-child(2){flex-grow:0;flex-basis:120px;margin-left:10px}._2fehqRU9GV{padding:30px 0 10px;display:flex;justify-content:flex-end;align-items:center}
|
||||
._3D3ZNp4oBz{background:none;position:fixed;top:0;bottom:0;left:0;right:0;-webkit-transform:none;transform:none;padding:0;border-radius:0}.tgH3yv-xGR{position:absolute;top:10%;left:50%;-webkit-transform:translate(-50%);transform:translate(-50%);max-width:376px;margin:0 auto}._3MMuzHtwZL{background:#222}
|
||||
@font-face{font-family:Roboto Mono;font-style:normal;font-weight:400;src:local("Roboto Mono"),local("RobotoMono-Regular"),url(https://cdn.jsdelivr.net/npm/@hsjs/fonts@0.0.1/robotomono/v5/L0x5DF4xlVMF-BfR8bXMIjhLq3-cXbKD.woff2) format("woff2");unicode-range:U+00??,U+0131,U+0152-0153,U+02bb-02bc,U+02c6,U+02da,U+02dc,U+2000-206f,U+2074,U+20ac,U+2122,U+2191,U+2193,U+2212,U+2215,U+feff,U+fffd}.border-bottom,.border-left,.border-top{position:relative}.border-top:before{top:0}.border-bottom:after,.border-top:before{position:absolute;content:"";height:1px;width:100%;-webkit-transform:scaleY(.5) translateZ(0);transform:scaleY(.5) translateZ(0);left:0;right:0;background:#555}.border-bottom:after{bottom:0}.border-left:before{position:absolute;content:"";height:100%;width:1px;-webkit-transform:scaleX(.5) translateZ(0);transform:scaleX(.5) translateZ(0);top:0;bottom:0;background:#555;left:0}*,:after,:before{box-sizing:border-box}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,PingFang SC,Microsoft YaHei,微软雅黑;margin:0;padding:0;--color-focus-blue:#1a73e8}body,body.dark{--color-background:#202020;--color-text:#ddd;--color-text-secondary:#ccc;--color-bg-sidebar:#2d2d30;--color-sb-active-row-bg:#494b4e;--color-input-bg:#2d2d30;--color-input-border:#3f3f3f;--color-toggle-bg:#353535;--color-toggle-selected:#181818;--color-icon:#c7c7c7;--color-btn-bg:#232323;--color-btn-fg:#bebebe}body.light{--color-background:#fbfbfb;--color-text:#222;--color-text-secondary:#646464;--color-bg-sidebar:#e7e7e7;--color-sb-active-row-bg:#d0d0d0;--color-input-bg:#fff;--color-input-border:silver;--color-toggle-bg:#fff;--color-toggle-selected:#d7d7d7;--color-icon:#5b5b5b;--color-btn-bg:#f4f4f4;--color-btn-fg:#101010}
|
||||
._35EMVy62Je{display:flex;background:var(--color-background);color:var(--color-text);min-height:300px;height:100vh}@media (max-width:768px){._35EMVy62Je{flex-direction:column}}.AwL8oIubvP{flex-grow:1;overflow:auto}
|
||||
File diff suppressed because one or more lines are too long
@ -0,0 +1 @@
|
||||
(window.webpackJsonp=window.webpackJsonp||[]).push([[1],{RnhZ:function(s,j,a){var e={"./af":"K/tc","./af.js":"K/tc","./ar":"jnO4","./ar-dz":"o1bE","./ar-dz.js":"o1bE","./ar-kw":"Qj4J","./ar-kw.js":"Qj4J","./ar-ly":"HP3h","./ar-ly.js":"HP3h","./ar-ma":"CoRJ","./ar-ma.js":"CoRJ","./ar-sa":"gjCT","./ar-sa.js":"gjCT","./ar-tn":"bYM6","./ar-tn.js":"bYM6","./ar.js":"jnO4","./az":"SFxW","./az.js":"SFxW","./be":"H8ED","./be.js":"H8ED","./bg":"hKrs","./bg.js":"hKrs","./bm":"p/rL","./bm.js":"p/rL","./bn":"kEOa","./bn.js":"kEOa","./bo":"0mo+","./bo.js":"0mo+","./br":"aIdf","./br.js":"aIdf","./bs":"JVSJ","./bs.js":"JVSJ","./ca":"1xZ4","./ca.js":"1xZ4","./cs":"PA2r","./cs.js":"PA2r","./cv":"A+xa","./cv.js":"A+xa","./cy":"l5ep","./cy.js":"l5ep","./da":"DxQv","./da.js":"DxQv","./de":"tGlX","./de-at":"s+uk","./de-at.js":"s+uk","./de-ch":"u3GI","./de-ch.js":"u3GI","./de.js":"tGlX","./dv":"WYrj","./dv.js":"WYrj","./el":"jUeY","./el.js":"jUeY","./en-SG":"zavE","./en-SG.js":"zavE","./en-au":"Dmvi","./en-au.js":"Dmvi","./en-ca":"OIYi","./en-ca.js":"OIYi","./en-gb":"Oaa7","./en-gb.js":"Oaa7","./en-ie":"4dOw","./en-ie.js":"4dOw","./en-il":"czMo","./en-il.js":"czMo","./en-nz":"b1Dy","./en-nz.js":"b1Dy","./eo":"Zduo","./eo.js":"Zduo","./es":"iYuL","./es-do":"CjzT","./es-do.js":"CjzT","./es-us":"Vclq","./es-us.js":"Vclq","./es.js":"iYuL","./et":"7BjC","./et.js":"7BjC","./eu":"D/JM","./eu.js":"D/JM","./fa":"jfSC","./fa.js":"jfSC","./fi":"gekB","./fi.js":"gekB","./fo":"ByF4","./fo.js":"ByF4","./fr":"nyYc","./fr-ca":"2fjn","./fr-ca.js":"2fjn","./fr-ch":"Dkky","./fr-ch.js":"Dkky","./fr.js":"nyYc","./fy":"cRix","./fy.js":"cRix","./ga":"USCx","./ga.js":"USCx","./gd":"9rRi","./gd.js":"9rRi","./gl":"iEDd","./gl.js":"iEDd","./gom-latn":"DKr+","./gom-latn.js":"DKr+","./gu":"4MV3","./gu.js":"4MV3","./he":"x6pH","./he.js":"x6pH","./hi":"3E1r","./hi.js":"3E1r","./hr":"S6ln","./hr.js":"S6ln","./hu":"WxRl","./hu.js":"WxRl","./hy-am":"1rYy","./hy-am.js":"1rYy","./id":"UDhR","./id.js":"UDhR","./is":"BVg3","./is.js":"BVg3","./it":"bpih","./it-ch":"bxKX","./it-ch.js":"bxKX","./it.js":"bpih","./ja":"B55N","./ja.js":"B55N","./jv":"tUCv","./jv.js":"tUCv","./ka":"IBtZ","./ka.js":"IBtZ","./kk":"bXm7","./kk.js":"bXm7","./km":"6B0Y","./km.js":"6B0Y","./kn":"PpIw","./kn.js":"PpIw","./ko":"Ivi+","./ko.js":"Ivi+","./ku":"JCF/","./ku.js":"JCF/","./ky":"lgnt","./ky.js":"lgnt","./lb":"RAwQ","./lb.js":"RAwQ","./lo":"sp3z","./lo.js":"sp3z","./lt":"JvlW","./lt.js":"JvlW","./lv":"uXwI","./lv.js":"uXwI","./me":"KTz0","./me.js":"KTz0","./mi":"aIsn","./mi.js":"aIsn","./mk":"aQkU","./mk.js":"aQkU","./ml":"AvvY","./ml.js":"AvvY","./mn":"lYtQ","./mn.js":"lYtQ","./mr":"Ob0Z","./mr.js":"Ob0Z","./ms":"6+QB","./ms-my":"ZAMP","./ms-my.js":"ZAMP","./ms.js":"6+QB","./mt":"G0Uy","./mt.js":"G0Uy","./my":"honF","./my.js":"honF","./nb":"bOMt","./nb.js":"bOMt","./ne":"OjkT","./ne.js":"OjkT","./nl":"+s0g","./nl-be":"2ykv","./nl-be.js":"2ykv","./nl.js":"+s0g","./nn":"uEye","./nn.js":"uEye","./pa-in":"8/+R","./pa-in.js":"8/+R","./pl":"jVdC","./pl.js":"jVdC","./pt":"8mBD","./pt-br":"0tRk","./pt-br.js":"0tRk","./pt.js":"8mBD","./ro":"lyxo","./ro.js":"lyxo","./ru":"lXzo","./ru.js":"lXzo","./sd":"Z4QM","./sd.js":"Z4QM","./se":"//9w","./se.js":"//9w","./si":"7aV9","./si.js":"7aV9","./sk":"e+ae","./sk.js":"e+ae","./sl":"gVVK","./sl.js":"gVVK","./sq":"yPMs","./sq.js":"yPMs","./sr":"zx6S","./sr-cyrl":"E+lV","./sr-cyrl.js":"E+lV","./sr.js":"zx6S","./ss":"Ur1D","./ss.js":"Ur1D","./sv":"X709","./sv.js":"X709","./sw":"dNwA","./sw.js":"dNwA","./ta":"PeUW","./ta.js":"PeUW","./te":"XLvN","./te.js":"XLvN","./tet":"V2x9","./tet.js":"V2x9","./tg":"Oxv6","./tg.js":"Oxv6","./th":"EOgW","./th.js":"EOgW","./tl-ph":"Dzi0","./tl-ph.js":"Dzi0","./tlh":"z3Vd","./tlh.js":"z3Vd","./tr":"DoHr","./tr.js":"DoHr","./tzl":"z1FC","./tzl.js":"z1FC","./tzm":"wQk9","./tzm-latn":"tT3J","./tzm-latn.js":"tT3J","./tzm.js":"wQk9","./ug-cn":"YRex","./ug-cn.js":"YRex","./uk":"raLr","./uk.js":"raLr","./ur":"UpQW","./ur.js":"UpQW","./uz":"Loxo","./uz-latn":"AQ68","./uz-latn.js":"AQ68","./uz.js":"Loxo","./vi":"KSF8","./vi.js":"KSF8","./x-pseudo":"/X5v","./x-pseudo.js":"/X5v","./yo":"fzPg","./yo.js":"fzPg","./zh-cn":"XDpg","./zh-cn.js":"XDpg","./zh-hk":"SatO","./zh-hk.js":"SatO","./zh-tw":"kOpN","./zh-tw.js":"kOpN"};function n(s){var j=r(s);return a(j)}function r(s){if(!a.o(e,s)){var j=new Error("Cannot find module '"+s+"'");throw j.code="MODULE_NOT_FOUND",j}return e[s]}n.keys=function(){return Object.keys(e)},n.resolve=r,s.exports=n,n.id="RnhZ"}}]);
|
||||
@ -0,0 +1 @@
|
||||
[0522/053329.127:ERROR:crash_report_database_win.cc(428)] unexpected header
|
||||
40
package/cnsztl/luci-app-openclash/files/usr/share/openclash/web/index.html
Executable file
40
package/cnsztl/luci-app-openclash/files/usr/share/openclash/web/index.html
Executable file
@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="shortcut icon" href="yacd.ico">
|
||||
<link rel="icon" type="image/png" sizes="64x64" href="yacd-64.png">
|
||||
<link rel="icon" type="image/png" sizes="128x128" href="yacd-128.png">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name=viewport content="width=device-width, initial-scale=1">
|
||||
<meta name="application-name" content="Clash Dashboard">
|
||||
<meta name="description" content="Clash Dashboard">
|
||||
<meta name="theme-color" content="#202020">
|
||||
<title>Clash Dashboard</title>
|
||||
<link rel="prefetch" href="https://cdn.jsdelivr.net/npm/@hsjs/fonts@0.0.1/robotomono/v5/L0x5DF4xlVMF-BfR8bXMIjhLq3-cXbKD.woff2">
|
||||
<meta property="og:image" content="https://user-images.githubusercontent.com/1166872/47304841-536f3d80-d65a-11e8-8908-1917127dafc5.png">
|
||||
<meta property="og:site_name" content="yacd">
|
||||
<meta property="og:type" content="object">
|
||||
<meta property="og:description" content="Clash Dashboard">
|
||||
|
||||
|
||||
<link href="vendors~app.31d7bcb28b9aaba65968.css" rel="stylesheet">
|
||||
|
||||
<link href="app.0a46527a296fe87c6f7a.css" rel="stylesheet">
|
||||
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
|
||||
<script src="runtime~app.ebef38faf2aa388ee472.js" type="text/javascript"></script>
|
||||
|
||||
<script src="react~app.2889399d0f29b961e8c2.js" type="text/javascript"></script>
|
||||
|
||||
<script src="vendors~app.3aefabaae8e43cd5bd7f.js" type="text/javascript"></script>
|
||||
|
||||
<script src="app.9b891454b1d74a441519.js" type="text/javascript"></script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,4 @@
|
||||
._2V-RqIAl7n{border-radius:20px;margin:10px 0;padding:3px 0;color:#eee}
|
||||
.NpfXwxWAxo{position:relative;height:90px}._250hnPTi2J{position:absolute;bottom:0;left:20%;display:flex;align-items:center;justify-content:center}._28H2QsOrtc{position:absolute;top:0;left:0;width:100%;height:100%}._3kdi5nima5{width:100%;padding-right:20px;overflow:hidden;text-overflow:ellipsis;margin:10px 0;font-size:1.1em}
|
||||
._3PCSxT0l14>h2{margin-top:0}._3PCSxT0l14>h2 span:nth-child(2){font-size:12px;color:#777;font-weight:400;margin:0 .3em}._1yYRIyvlRd{display:flex;flex-wrap:wrap}._1OcDlvlM5R{width:300px;padding:10px 5px;transition:-webkit-transform .2s ease-in-out;transition:transform .2s ease-in-out;transition:transform .2s ease-in-out,-webkit-transform .2s ease-in-out}._1OcDlvlM5R._3oAxPKtZFv{cursor:pointer}._1OcDlvlM5R._3oAxPKtZFv:hover{-webkit-transform:scale(1.1);transform:scale(1.1)}
|
||||
._1myfcMimT9{padding:10px 40px}._1khaX45NQe{position:fixed;right:20px;bottom:20px}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
64
package/cnsztl/luci-app-openclash/files/usr/share/openclash/web/report.html
Executable file
64
package/cnsztl/luci-app-openclash/files/usr/share/openclash/web/report.html
Executable file
File diff suppressed because one or more lines are too long
@ -0,0 +1,2 @@
|
||||
._3eSLieOhVX{display:flex;align-items:center;padding:10px 40px}._2n1pW09UvV{width:40px;padding-right:15px;color:var(--color-text-secondary);opacity:.4}.t1XJIwvW7A{display:flex;align-items:center;font-size:12px;opacity:.8}._1fNf8kj0HA{padding:10px 0;font-family:Roboto Mono,Menlo,monospace;font-size:19px}._3yJmN0tON0{width:110px}
|
||||
._2Tux7NhweE{position:fixed;right:20px;bottom:20px}
|
||||
@ -0,0 +1 @@
|
||||
(window.webpackJsonp=window.webpackJsonp||[]).push([[4],{BVyM:function(e,t,a){"use strict";a.r(t);var n=a("ODXe"),r=a("q1tI"),c=a.n(r),l=a("u4Dv"),i=a("5Wrh"),u=a("iR1w"),s=a("DKqX"),o=a("17x9"),m=a.n(o),f=a("xrux"),d=a.n(f),p={_default:"#59caf9",DIRECT:"#f5bc41",REJECT:"#cb3166"};function v(e){var t=e.type,a=e.payload,n=e.proxy,r=e.id,l=function(e){var t=e.proxy,a=p._default;return p[t]&&(a=p[t]),{color:a}}({proxy:n});return c.a.createElement("div",{className:d.a.rule},c.a.createElement("div",{className:d.a.left},r),c.a.createElement("div",null,c.a.createElement("div",{className:d.a.b},a),c.a.createElement("div",{className:d.a.a},c.a.createElement("div",{className:d.a.type},t),c.a.createElement("div",{style:l},n))))}v.propTypes={id:m.a.number,type:m.a.string,payload:m.a.string,proxy:m.a.string};var b=v,E=a("II4a"),h=a("Tvb5"),y={updateSearchText:h.f},x=Object(E.a)({mapStateToProps:function(e){return{searchText:Object(h.e)(e)}},actions:y}),O=a("Kv4h"),j=a("mlDh"),w=a.n(j);a.d(t,"default",function(){return _});var N=30,R=function(e){return{rules:Object(h.d)(e)}},g={fetchRules:h.b,fetchRulesOnce:h.c};function T(e,t){return t[e].id}var D=Object(r.memo)(function(e){var t=e.index,a=e.style,n=e.data[t];return c.a.createElement("div",{style:a},c.a.createElement(b,n))},u.b);function _(){var e=Object(l.b)(g),t=e.fetchRulesOnce,a=e.fetchRules,o=Object(l.c)(R).rules;Object(r.useEffect)(function(){t()},[t]);var m=Object(O.a)(),f=Object(n.a)(m,2),d=f[0],p=f[1];return c.a.createElement("div",null,c.a.createElement(s.a,{title:"Rules"}),c.a.createElement(x,null),c.a.createElement("div",{ref:d,style:{paddingBottom:N}},c.a.createElement(u.a,{height:p-N,width:"100%",itemCount:o.length,itemSize:80,itemData:o,itemKey:T},D)),c.a.createElement("div",{className:w.a.fabgrp},c.a.createElement(i.a,{label:"Refresh",onClick:a})))}},mlDh:function(e,t,a){e.exports={fabgrp:"_2Tux7NhweE"}},xrux:function(e,t,a){e.exports={rule:"_3eSLieOhVX",left:"_2n1pW09UvV",a:"t1XJIwvW7A",b:"_1fNf8kj0HA",type:"_3yJmN0tON0"}}}]);
|
||||
@ -0,0 +1 @@
|
||||
!function(e){function t(t){for(var n,o,u=t[0],i=t[1],f=t[2],l=0,d=[];l<u.length;l++)o=u[l],a[o]&&d.push(a[o][0]),a[o]=0;for(n in i)Object.prototype.hasOwnProperty.call(i,n)&&(e[n]=i[n]);for(s&&s(t);d.length;)d.shift()();return c.push.apply(c,f||[]),r()}function r(){for(var e,t=0;t<c.length;t++){for(var r=c[t],n=!0,o=1;o<r.length;o++){var i=r[o];0!==a[i]&&(n=!1)}n&&(c.splice(t--,1),e=u(u.s=r[0]))}return e}var n={},o={5:0},a={5:0},c=[];function u(t){if(n[t])return n[t].exports;var r=n[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,u),r.l=!0,r.exports}u.e=function(e){var t=[];o[e]?t.push(o[e]):0!==o[e]&&{2:1,4:1}[e]&&t.push(o[e]=new Promise(function(t,r){for(var n=({1:"chartjs",2:"proxies",4:"rules",7:"vendors~chartjs"}[e]||e)+"."+{1:"3492c684ba7d8497de04",2:"462629c0ce55931a9066",4:"0051e218ebc63aef81f1",7:"60c4bfacb0e342e6819f",8:"c1eaea41bb4791c0be2b"}[e]+".css",a=u.p+n,c=document.getElementsByTagName("link"),i=0;i<c.length;i++){var f=(s=c[i]).getAttribute("data-href")||s.getAttribute("href");if("stylesheet"===s.rel&&(f===n||f===a))return t()}var l=document.getElementsByTagName("style");for(i=0;i<l.length;i++){var s;if((f=(s=l[i]).getAttribute("data-href"))===n||f===a)return t()}var d=document.createElement("link");d.rel="stylesheet",d.type="text/css",d.onload=t,d.onerror=function(t){var n=t&&t.target&&t.target.src||a,c=new Error("Loading CSS chunk "+e+" failed.\n("+n+")");c.code="CSS_CHUNK_LOAD_FAILED",c.request=n,delete o[e],d.parentNode.removeChild(d),r(c)},d.href=a,document.getElementsByTagName("head")[0].appendChild(d)}).then(function(){o[e]=0}));var r=a[e];if(0!==r)if(r)t.push(r[2]);else{var n=new Promise(function(t,n){r=a[e]=[t,n]});t.push(r[2]=n);var c,i=document.createElement("script");i.charset="utf-8",i.timeout=120,u.nc&&i.setAttribute("nonce",u.nc),i.src=function(e){return u.p+""+({1:"chartjs",2:"proxies",4:"rules",7:"vendors~chartjs"}[e]||e)+"."+{1:"707c4e7f2cfb4dfd187a",2:"687ac8f8aaa8ce3509ca",4:"a68d49f3a80e76d735e1",7:"c9231179be225dfb8564",8:"45fc79574f18cfbcc680"}[e]+".js"}(e),c=function(t){i.onerror=i.onload=null,clearTimeout(f);var r=a[e];if(0!==r){if(r){var n=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src,c=new Error("Loading chunk "+e+" failed.\n("+n+": "+o+")");c.type=n,c.request=o,r[1](c)}a[e]=void 0}};var f=setTimeout(function(){c({type:"timeout",target:i})},12e4);i.onerror=i.onload=c,document.head.appendChild(i)}return Promise.all(t)},u.m=e,u.c=n,u.d=function(e,t,r){u.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},u.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},u.t=function(e,t){if(1&t&&(e=u(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(u.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)u.d(r,n,function(t){return e[t]}.bind(null,n));return r},u.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return u.d(t,"a",t),t},u.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},u.p="",u.oe=function(e){throw console.error(e),e};var i=window.webpackJsonp=window.webpackJsonp||[],f=i.push.bind(i);i.push=t,i=i.slice();for(var l=0;l<i.length;l++)t(i[l]);var s=f;r()}([]);
|
||||
@ -0,0 +1 @@
|
||||
/*! modern-normalize | MIT License | https://github.com/sindresorhus/modern-normalize */html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}:root{-moz-tab-size:4;-o-tab-size:4;tab-size:4}html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}hr{height:0}abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{padding:0}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
BIN
package/cnsztl/luci-app-openclash/files/usr/share/openclash/web/yacd-128.png
Executable file
BIN
package/cnsztl/luci-app-openclash/files/usr/share/openclash/web/yacd-128.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 7.5 KiB |
BIN
package/cnsztl/luci-app-openclash/files/usr/share/openclash/web/yacd-64.png
Executable file
BIN
package/cnsztl/luci-app-openclash/files/usr/share/openclash/web/yacd-64.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
BIN
package/cnsztl/luci-app-openclash/files/usr/share/openclash/web/yacd.ico
Executable file
BIN
package/cnsztl/luci-app-openclash/files/usr/share/openclash/web/yacd.ico
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
48
package/cnsztl/luci-app-openclash/files/usr/share/openclash/yml_change.sh
Executable file
48
package/cnsztl/luci-app-openclash/files/usr/share/openclash/yml_change.sh
Executable file
@ -0,0 +1,48 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -z "$7" ]; then
|
||||
sed -i "/^dns:$/a\ enhanced-mode: ${2}" "$8"
|
||||
elif [ "$7" != "$2" ] && [ "$2" != "0" ]; then
|
||||
sed -i "s/${7}$/${2}/" "$8"
|
||||
fi
|
||||
if [ "$2" = "fake-ip" ]; then
|
||||
if [ ! -z "`grep "fake-ip-range:" "$8"`" ]; then
|
||||
sed -i "/fake-ip-range:/c\ fake-ip-range: 198.18.0.1/16" "$8"
|
||||
else
|
||||
sed -i "/enhanced-mode:/a\ fake-ip-range: 198.18.0.1/16" "$8"
|
||||
fi
|
||||
else
|
||||
sed -i '/fake-ip-range:/d' "$8" 2>/dev/null
|
||||
fi
|
||||
sed -i '/^##Custom DNS##$/d' "$8" 2>/dev/null
|
||||
|
||||
if [ ! -z "`grep "^redir-port:" "$8"`" ]; then
|
||||
sed -i "/^redir-port:/c\redir-port: ${6}" "$8"
|
||||
else
|
||||
sed -i "3i\redir-port: ${6}" "$8"
|
||||
fi
|
||||
if [ ! -z "`grep "^external-controller:" "$8"`" ]; then
|
||||
sed -i "/^external-controller:/c\external-controller: 0.0.0.0:${5}" "$8"
|
||||
else
|
||||
sed -i "3i\external-controller: 0.0.0.0:${5}" "$8"
|
||||
fi
|
||||
if [ ! -z "`grep "^secret:" "$8"`" ]; then
|
||||
sed -i "/^secret:/c\secret: '${4}'" "$8"
|
||||
else
|
||||
sed -i "3i\secret: '${4}'" "$8"
|
||||
fi
|
||||
if [ ! -z "`grep "^ enable:" "$8"`" ]; then
|
||||
sed -i "/^ enable:/c\ enable: true" "$8"
|
||||
else
|
||||
sed -i "/^dns:/a\ enable: true" "$8"
|
||||
fi
|
||||
if [ ! -z "`grep "^allow-lan:" "$8"`" ]; then
|
||||
sed -i "/^allow-lan:/c\allow-lan: true" "$8"
|
||||
else
|
||||
sed -i "3i\allow-lan: true" "$8"
|
||||
fi
|
||||
if [ ! -z "`grep "^external-ui:" "$8"`" ]; then
|
||||
sed -i '/^external-ui:/c\external-ui: "/usr/share/openclash/dashboard"' "$8"
|
||||
else
|
||||
sed -i '3i\external-ui: "/usr/share/openclash/dashboard"' "$8"
|
||||
fi
|
||||
107
package/cnsztl/luci-app-openclash/files/usr/share/openclash/yml_rules_change.sh
Executable file
107
package/cnsztl/luci-app-openclash/files/usr/share/openclash/yml_rules_change.sh
Executable file
@ -0,0 +1,107 @@
|
||||
#!/bin/sh
|
||||
|
||||
check_def=0
|
||||
if [ "$2" != 0 ]; then
|
||||
if [ ! -f /etc/openclash/"$2".yml ]; then
|
||||
echo "${1} /etc/openclash/"$2".yml Not Exist, Will Use Self Rules, Please Update and Try Again" >>/tmp/clash.log
|
||||
exit 0
|
||||
else
|
||||
rulesource=$(grep '##source:' "$4" |awk -F ':' '{print $2}')
|
||||
[ "$rulesource" != "$2" ] && {
|
||||
check_def=1
|
||||
}
|
||||
|
||||
[ "$check_def" -ne 1 ] && {
|
||||
grep "^##updated$" /etc/openclash/"$2".yml 1>/dev/null
|
||||
[ "$?" -eq "0" ] && {
|
||||
sed -i '/^##updated$/d' /etc/openclash/"$2".yml
|
||||
check_def=1
|
||||
}
|
||||
}
|
||||
|
||||
[ "$check_def" -ne 1 ] && {
|
||||
GlobalTV=$(grep '##GlobalTV:' "$4" |awk -F ':' '{print $2}')
|
||||
AsianTV=$(grep '##AsianTV:' "$4" |awk -F ':' '{print $2}')
|
||||
Proxy=$(grep '##Proxy:' "$4" |awk -F ':' '{print $2}')
|
||||
Apple=$(grep '##Apple:' "$4" |awk -F ':' '{print $2}')
|
||||
AdBlock=$(grep '##AdBlock:' "$4" |awk -F ':' '{print $2}')
|
||||
Others=$(grep '##Others:' "$4" |awk -F ':' '{print $2}')
|
||||
Domestic=$(grep '##Domestic:' "$4" |awk -F ':' '{print $2}')
|
||||
if [ "$2" = "ConnersHua_return" ]; then
|
||||
if [ "$(uci get openclash.config.Proxy)" != "$Proxy" ]\
|
||||
|| [ "$(uci get openclash.config.Others)" != "$Others" ];then
|
||||
check_def=1
|
||||
fi
|
||||
else
|
||||
if [ "$(uci get openclash.config.GlobalTV)" != "$GlobalTV" ]\
|
||||
|| [ "$(uci get openclash.config.AsianTV)" != "$AsianTV" ]\
|
||||
|| [ "$(uci get openclash.config.Proxy)" != "$Proxy" ]\
|
||||
|| [ "$(uci get openclash.config.Apple)" != "$Apple" ]\
|
||||
|| [ "$(uci get openclash.config.AdBlock)" != "$AdBlock" ]\
|
||||
|| [ "$(uci get openclash.config.Others)" != "$Others" ]\
|
||||
|| [ "$(uci get openclash.config.Domestic)" != "$Domestic" ]; then
|
||||
check_def=1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "$check_def" -eq 1 ]; then
|
||||
GlobalTV=$(uci get openclash.config.GlobalTV 2>/dev/null)
|
||||
AsianTV=$(uci get openclash.config.AsianTV 2>/dev/null)
|
||||
Proxy=$(uci get openclash.config.Proxy 2>/dev/null)
|
||||
Apple=$(uci get openclash.config.Apple 2>/dev/null)
|
||||
AdBlock=$(uci get openclash.config.AdBlock 2>/dev/null)
|
||||
Domestic=$(uci get openclash.config.Domestic 2>/dev/null)
|
||||
Others=$(uci get openclash.config.Others 2>/dev/null)
|
||||
if [ "$2" = "lhie1" ]; then
|
||||
sed -i '/^Rule:$/,$d' "$4"
|
||||
cat /etc/openclash/lhie1.yml >> "$4"
|
||||
sed -i -e "s/,GlobalTV$/,${GlobalTV}#d/g" -e "/Rule:/a\##GlobalTV:${GlobalTV}"\
|
||||
-e "s/,AsianTV$/,${AsianTV}#d/g" -e "/Rule:/a\##AsianTV:${AsianTV}"\
|
||||
-e "s/,Proxy$/,${Proxy}#d/g" -e "/Rule:/a\##Proxy:${Proxy}"\
|
||||
-e "s/,Apple$/,${Apple}#d/g" -e "/Rule:/a\##Apple:${Apple}"\
|
||||
-e "s/,AdBlock$/,${AdBlock}#d/g" -e "/Rule:/a\##AdBlock:${AdBlock}"\
|
||||
-e "s/,Domestic$/,${Domestic}#d/g" -e "/Rule:/a\##Domestic:${Domestic}"\
|
||||
-e "s/,Others$/,${Others}#d/g" -e "/Rule:/a\##Others:${Others}"\
|
||||
-e "s/#d$//g" "$4"
|
||||
elif [ "$2" = "ConnersHua" ]; then
|
||||
sed -i '/^Rule:$/,$d' "$4"
|
||||
cat /etc/openclash/ConnersHua.yml >> "$4"
|
||||
sed -i -e "s/,ForeignMedia$/,${GlobalTV}#d/g" -e "/Rule:/a\##GlobalTV:${GlobalTV}"\
|
||||
-e "s/,DomesticMedia$/,${AsianTV}#d/g" -e "/Rule:/a\##AsianTV:${AsianTV}"\
|
||||
-e "s/,PROXY$/,${Proxy}#d/g" -e "/Rule:/a\##Proxy:${Proxy}"\
|
||||
-e "s/,Apple$/,${Apple}#d/g" -e "/Rule:/a\##Apple:${Apple}"\
|
||||
-e "s/,Hijacking$/,${AdBlock}#d/g" -e "/Rule:/a\##AdBlock:${AdBlock}"\
|
||||
-e "s/,DIRECT$/,${Domestic}#d/g" -e "/Rule:/a\##Domestic:${Domestic}"\
|
||||
-e "s/,Final$/,${Others}#d/g" -e "/Rule:/a\##Others:${Others}"\
|
||||
-e "s/#d$//g" "$4"
|
||||
else
|
||||
sed -i '/^Rule:$/,$d' "$4"
|
||||
cat /etc/openclash/ConnersHua_return.yml >> "$4"
|
||||
sed -i -e "s/,PROXY$/,${Proxy}#d/g" -e "/Rule:/a\##Proxy:${Proxy}"\
|
||||
-e "s/,DIRECT$/,${Others}#d/g" -e "/Rule:/a\##Others:${Others}"\
|
||||
-e "s/#d$//g" "$4"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
elif [ "$2" = 0 ]; then
|
||||
[ -f /etc/openclash/config.bak ] && {
|
||||
grep '##source:' "$4" 1>/dev/null
|
||||
if [ "$?" -eq "0" ]; then
|
||||
cp /etc/openclash/config.bak /etc/openclash/configrules.bak
|
||||
sed -i -n '/^Rule:$/,$p' /etc/openclash/configrules.bak
|
||||
sed -i '/^Rule:$/,$d' "$4"
|
||||
cat /etc/openclash/configrules.bak >> "$4"
|
||||
rm -rf /etc/openclash/configrules.bak
|
||||
fi
|
||||
}
|
||||
fi
|
||||
|
||||
sed -i '/^##Custom Rules$/,/^##Custom Rules End$/d' "$4" 2>/dev/null
|
||||
sed -i '/^##Custom Rules$/d' "$4" 2>/dev/null
|
||||
sed -i '/^##Custom Rules End$/d' "$4" 2>/dev/null
|
||||
[ "$3" = 1 ] && {
|
||||
sed -i '/^Rule:$/a\##Custom Rules End' "$4" 2>/dev/null
|
||||
sed -i '/^Rule:$/a\##Custom Rules' "$4" 2>/dev/null
|
||||
sed -i '/^##Custom Rules$/r/etc/config/openclash_custom_rules.list' "$4" 2>/dev/null
|
||||
}
|
||||
278
package/cnsztl/luci-app-openclash/i18n/zh-cn/openclash.zh-cn.po
Executable file
278
package/cnsztl/luci-app-openclash/i18n/zh-cn/openclash.zh-cn.po
Executable file
@ -0,0 +1,278 @@
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=UTF-8\n"
|
||||
|
||||
msgid "clash"
|
||||
msgstr "clash"
|
||||
|
||||
msgid "OpenClash"
|
||||
msgstr "OpenClash"
|
||||
|
||||
msgid "A Clash Client For OpenWrt"
|
||||
msgstr "一个运行在OpenWrt上的Clash客户端"
|
||||
|
||||
msgid "Technical Support"
|
||||
msgstr "技术支持"
|
||||
|
||||
msgid "Clash Global State"
|
||||
msgstr "运行状态"
|
||||
|
||||
msgid "Clash Settings"
|
||||
msgstr "全局设置"
|
||||
|
||||
msgid "Config Normal"
|
||||
msgstr "配置文件正常"
|
||||
|
||||
msgid "Config Abnormal"
|
||||
msgstr "配置文件(异常/不存在)"
|
||||
|
||||
msgid "File Not Exist"
|
||||
msgstr "文件不存在"
|
||||
|
||||
msgid "Not Set"
|
||||
msgstr "未设置"
|
||||
|
||||
msgid "File No Update"
|
||||
msgstr "原始/不存在(配置文件)"
|
||||
|
||||
msgid "Server Configuration"
|
||||
msgstr "配置文件"
|
||||
|
||||
msgid "Server logs"
|
||||
msgstr "服务器日志"
|
||||
|
||||
msgid "Logs"
|
||||
msgstr "服务器日志"
|
||||
|
||||
msgid "Update Setting"
|
||||
msgstr "更新设置"
|
||||
|
||||
msgid "General Settings"
|
||||
msgstr "全局设置"
|
||||
|
||||
msgid "Enable Clash"
|
||||
msgstr "启动 OpenClash"
|
||||
|
||||
msgid "Disable Clash"
|
||||
msgstr "关闭 OpenClash"
|
||||
|
||||
msgid "Commit Configurations"
|
||||
msgstr "保存配置"
|
||||
|
||||
msgid "Apply Configurations"
|
||||
msgstr "应用配置"
|
||||
|
||||
msgid "Select Mode"
|
||||
msgstr "运行模式"
|
||||
|
||||
msgid "redir-host"
|
||||
msgstr "Redir-Host模式"
|
||||
|
||||
msgid "fake-ip"
|
||||
msgstr "Fake-IP模式"
|
||||
|
||||
msgid "Will to Take Over Your General Settings, Network Error Try Flush DNS Cache"
|
||||
msgstr "启用将接管配置文件的模式设置,如客户端的网络无法连接请尝试清除DNS缓存"
|
||||
|
||||
msgid "Disable Mode Control"
|
||||
msgstr "使用配置文件设定的模式"
|
||||
|
||||
msgid "Custom DNS Setting"
|
||||
msgstr "自定义DNS服务器"
|
||||
|
||||
msgid "Use Custom Rules"
|
||||
msgstr "添加并启用自定义规则"
|
||||
|
||||
msgid "Add Custom DNS Servers"
|
||||
msgstr "添加自定义DNS服务器"
|
||||
|
||||
msgid "Set OpenClash Upstream DNS Resolve Server"
|
||||
msgstr "自定义DNS上游服务器,将替换配置文件内的DNS服务器设置"
|
||||
|
||||
msgid "Disable Custom DNS Setting"
|
||||
msgstr "不使用自定义DNS服务器"
|
||||
|
||||
msgid "DNS Server Group"
|
||||
msgstr "上游DNS服务器分组"
|
||||
|
||||
msgid "DNS Server IP"
|
||||
msgstr "DNS服务器IP"
|
||||
|
||||
msgid "DNS Server Port"
|
||||
msgstr "DNS服务器端口"
|
||||
|
||||
msgid "DNS Server Type"
|
||||
msgstr "DNS服务器类型"
|
||||
|
||||
msgid "Enable Custom DNS Setting"
|
||||
msgstr "使用自定义DNS服务器"
|
||||
|
||||
msgid "Rules Setting"
|
||||
msgstr "规则设置"
|
||||
|
||||
msgid "Server Config"
|
||||
msgstr "配置文件"
|
||||
|
||||
msgid "Upload Clash Configuration"
|
||||
msgstr "上传配置文件"
|
||||
|
||||
msgid ""
|
||||
"NB: Rename your config file to config.yml before upload. file will save to /"
|
||||
"etc/openclash"
|
||||
msgstr ""
|
||||
"注意:上传之前,请将配置文件重命名为config.yml,文件将保存到 /etc/openclash 文件夹"
|
||||
|
||||
msgid "Clash Redir Port, Please Make Sure Ports Available"
|
||||
msgstr "OpenClash转发端口,请确保端口可用"
|
||||
|
||||
msgid "Subscription Update"
|
||||
msgstr "配置文件"
|
||||
|
||||
msgid "Subcription Url"
|
||||
msgstr "订阅URL"
|
||||
|
||||
msgid "Update Subcription"
|
||||
msgstr "更新订阅配置"
|
||||
|
||||
msgid "Update Configuration"
|
||||
msgstr "点击更新配置文件"
|
||||
|
||||
msgid "Update time (every day)"
|
||||
msgstr "更新时间(每天)"
|
||||
|
||||
msgid "Auto Update"
|
||||
msgstr "自动更新"
|
||||
|
||||
msgid "After clash start running, wait a moment for servers to resolve,enjoy"
|
||||
msgstr "运行后,请等待服务器上线"
|
||||
|
||||
msgid "Clash config redir-port"
|
||||
msgstr "转发端口"
|
||||
|
||||
msgid "Server Subscription Address"
|
||||
msgstr "服务器订阅地址"
|
||||
|
||||
msgid "Auto Update Server subscription"
|
||||
msgstr "自动更新服务器订阅"
|
||||
|
||||
msgid "Daily Server subscription update time"
|
||||
msgstr "每日服务器订阅更新时间"
|
||||
|
||||
msgid "Under Server Config You Can Manually Upload Configuration From PC"
|
||||
msgstr "或在配置文件页面手动上载配置"
|
||||
|
||||
msgid "Changes to config file must be made from source"
|
||||
msgstr "必须从源文件更改配置文件"
|
||||
|
||||
msgid "Dashboard Secret"
|
||||
msgstr "管理页面登录密码"
|
||||
|
||||
msgid "Set Dashboard Secret"
|
||||
msgstr "设置您的管理页面登录密码"
|
||||
|
||||
msgid "Dashboard hostname is Your Router IP. Dashboard:192.168.1.1/openclash"
|
||||
msgstr "登录主机名是您的路由器IP, 管理页面地址示例:192.168.1.1/openclash、192.168.1.1:9090/ui"
|
||||
|
||||
msgid "Dashboard Port"
|
||||
msgstr "管理页面端口"
|
||||
|
||||
msgid "GEOIP(By MaxMind) Update"
|
||||
msgstr "GEOIP 数据库(By MaxMind)"
|
||||
|
||||
msgid "Update GEOIP Database"
|
||||
msgstr "更新GEOIP数据库"
|
||||
|
||||
msgid "Start Update GEOIP Database"
|
||||
msgstr "点击更新GEOIP数据库"
|
||||
|
||||
msgid "Other Rules Update(Only in Use)"
|
||||
msgstr "第三方规则(仅对正在使用的规则生效)"
|
||||
|
||||
msgid "Enable Other Rules"
|
||||
msgstr "第三方规则"
|
||||
|
||||
msgid "Use Other Rules"
|
||||
msgstr "选择并启用第三方规则,将替换配置文件内的所有规则"
|
||||
|
||||
msgid "Disable Other Rules"
|
||||
msgstr "不使用第三方规则"
|
||||
|
||||
msgid "lhie1 Rules"
|
||||
msgstr "lhie1 规则"
|
||||
|
||||
msgid "ConnersHua Rules"
|
||||
msgstr "ConnersHua 规则"
|
||||
|
||||
msgid "ConnersHua Return Rules"
|
||||
msgstr "ConnersHua 回国规则"
|
||||
|
||||
msgid "Auto Update Other Rules"
|
||||
msgstr "启用第三方规则自动更新"
|
||||
|
||||
msgid "Update Time (Every Week)"
|
||||
msgstr "更新时间(每周)"
|
||||
|
||||
msgid "Every Monday"
|
||||
msgstr "每周一"
|
||||
|
||||
msgid "Every Tuesday"
|
||||
msgstr "每周二"
|
||||
|
||||
msgid "Every Wednesday"
|
||||
msgstr "每周三"
|
||||
|
||||
msgid "Every Thursday"
|
||||
msgstr "每周四"
|
||||
|
||||
msgid "Every Friday"
|
||||
msgstr "每周五"
|
||||
|
||||
msgid "Every Saturday"
|
||||
msgstr "每周六"
|
||||
|
||||
msgid "Every Sunday"
|
||||
msgstr "每周日"
|
||||
|
||||
msgid "Update Other Rules"
|
||||
msgstr "更新第三方规则"
|
||||
|
||||
msgid "Start Update Other Rules"
|
||||
msgstr "点击更新第三方规则"
|
||||
|
||||
msgid "GlobalTV"
|
||||
msgstr "国际流媒体流量"
|
||||
|
||||
msgid "AsianTV"
|
||||
msgstr "亚洲流媒体流量"
|
||||
|
||||
msgid "Proxy"
|
||||
msgstr "必须代理的流量"
|
||||
|
||||
msgid "Apple"
|
||||
msgstr "苹果服务流量"
|
||||
|
||||
msgid "AdBlock"
|
||||
msgstr "广告流量"
|
||||
|
||||
msgid "Domestic"
|
||||
msgstr "国内流量"
|
||||
|
||||
msgid "Others"
|
||||
msgstr "未匹配到规则的流量"
|
||||
|
||||
msgid "Choose Proxy Group, Base On Your Servers Group in config.yml"
|
||||
msgstr "指定流量(策略)的代理方式,服务器组信息来源于您的config.yml"
|
||||
|
||||
msgid "Custom Clash Rules"
|
||||
msgstr "自定义规则"
|
||||
|
||||
msgid "Custom Clash Rules Here"
|
||||
msgstr "设置自定义规则"
|
||||
|
||||
msgid "Disable Custom Clash Rules"
|
||||
msgstr "不设置自定义规则"
|
||||
|
||||
msgid "Enable Custom Clash Rules"
|
||||
msgstr "设置自定义规则"
|
||||
|
||||
msgid "For More Go Github:https://github.com/Dreamacro/clash"
|
||||
msgstr "更多规则信息请前往Github( https://github.com/Dreamacro/clash )查询"
|
||||
12
package/cnsztl/luci-app-openclash/tools/po2lmo/Makefile
Executable file
12
package/cnsztl/luci-app-openclash/tools/po2lmo/Makefile
Executable file
@ -0,0 +1,12 @@
|
||||
|
||||
INSTALL = install
|
||||
PREFIX = /usr/bin
|
||||
|
||||
po2lmo: src/po2lmo.o src/template_lmo.o
|
||||
$(CC) $(LDFLAGS) -o src/po2lmo src/po2lmo.o src/template_lmo.o
|
||||
|
||||
install:
|
||||
$(INSTALL) -m 755 src/po2lmo $(PREFIX)
|
||||
|
||||
clean:
|
||||
$(RM) src/po2lmo src/*.o
|
||||
BIN
package/cnsztl/luci-app-openclash/tools/po2lmo/src/po2lmo
Executable file
BIN
package/cnsztl/luci-app-openclash/tools/po2lmo/src/po2lmo
Executable file
Binary file not shown.
247
package/cnsztl/luci-app-openclash/tools/po2lmo/src/po2lmo.c
Executable file
247
package/cnsztl/luci-app-openclash/tools/po2lmo/src/po2lmo.c
Executable file
@ -0,0 +1,247 @@
|
||||
/*
|
||||
* lmo - Lua Machine Objects - PO to LMO conversion tool
|
||||
*
|
||||
* Copyright (C) 2009-2012 Jo-Philipp Wich <xm@subsignal.org>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "template_lmo.h"
|
||||
|
||||
static void die(const char *msg)
|
||||
{
|
||||
fprintf(stderr, "Error: %s\n", msg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void usage(const char *name)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s input.po output.lmo\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void print(const void *ptr, size_t size, size_t nmemb, FILE *stream)
|
||||
{
|
||||
if( fwrite(ptr, size, nmemb, stream) == 0 )
|
||||
die("Failed to write stdout");
|
||||
}
|
||||
|
||||
static int extract_string(const char *src, char *dest, int len)
|
||||
{
|
||||
int pos = 0;
|
||||
int esc = 0;
|
||||
int off = -1;
|
||||
|
||||
for( pos = 0; (pos < strlen(src)) && (pos < len); pos++ )
|
||||
{
|
||||
if( (off == -1) && (src[pos] == '"') )
|
||||
{
|
||||
off = pos + 1;
|
||||
}
|
||||
else if( off >= 0 )
|
||||
{
|
||||
if( esc == 1 )
|
||||
{
|
||||
switch (src[pos])
|
||||
{
|
||||
case '"':
|
||||
case '\\':
|
||||
off++;
|
||||
break;
|
||||
}
|
||||
dest[pos-off] = src[pos];
|
||||
esc = 0;
|
||||
}
|
||||
else if( src[pos] == '\\' )
|
||||
{
|
||||
dest[pos-off] = src[pos];
|
||||
esc = 1;
|
||||
}
|
||||
else if( src[pos] != '"' )
|
||||
{
|
||||
dest[pos-off] = src[pos];
|
||||
}
|
||||
else
|
||||
{
|
||||
dest[pos-off] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (off > -1) ? strlen(dest) : -1;
|
||||
}
|
||||
|
||||
static int cmp_index(const void *a, const void *b)
|
||||
{
|
||||
uint32_t x = ((const lmo_entry_t *)a)->key_id;
|
||||
uint32_t y = ((const lmo_entry_t *)b)->key_id;
|
||||
|
||||
if (x < y)
|
||||
return -1;
|
||||
else if (x > y)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void print_uint32(uint32_t x, FILE *out)
|
||||
{
|
||||
uint32_t y = htonl(x);
|
||||
print(&y, sizeof(uint32_t), 1, out);
|
||||
}
|
||||
|
||||
static void print_index(void *array, int n, FILE *out)
|
||||
{
|
||||
lmo_entry_t *e;
|
||||
|
||||
qsort(array, n, sizeof(*e), cmp_index);
|
||||
|
||||
for (e = array; n > 0; n--, e++)
|
||||
{
|
||||
print_uint32(e->key_id, out);
|
||||
print_uint32(e->val_id, out);
|
||||
print_uint32(e->offset, out);
|
||||
print_uint32(e->length, out);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char line[4096];
|
||||
char key[4096];
|
||||
char val[4096];
|
||||
char tmp[4096];
|
||||
int state = 0;
|
||||
int offset = 0;
|
||||
int length = 0;
|
||||
int n_entries = 0;
|
||||
void *array = NULL;
|
||||
lmo_entry_t *entry = NULL;
|
||||
uint32_t key_id, val_id;
|
||||
|
||||
FILE *in;
|
||||
FILE *out;
|
||||
|
||||
if( (argc != 3) || ((in = fopen(argv[1], "r")) == NULL) || ((out = fopen(argv[2], "w")) == NULL) )
|
||||
usage(argv[0]);
|
||||
|
||||
memset(line, 0, sizeof(key));
|
||||
memset(key, 0, sizeof(val));
|
||||
memset(val, 0, sizeof(val));
|
||||
|
||||
while( (NULL != fgets(line, sizeof(line), in)) || (state >= 2 && feof(in)) )
|
||||
{
|
||||
if( state == 0 && strstr(line, "msgid \"") == line )
|
||||
{
|
||||
switch(extract_string(line, key, sizeof(key)))
|
||||
{
|
||||
case -1:
|
||||
die("Syntax error in msgid");
|
||||
case 0:
|
||||
state = 1;
|
||||
break;
|
||||
default:
|
||||
state = 2;
|
||||
}
|
||||
}
|
||||
else if( state == 1 || state == 2 )
|
||||
{
|
||||
if( strstr(line, "msgstr \"") == line || state == 2 )
|
||||
{
|
||||
switch(extract_string(line, val, sizeof(val)))
|
||||
{
|
||||
case -1:
|
||||
state = 4;
|
||||
break;
|
||||
default:
|
||||
state = 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(extract_string(line, tmp, sizeof(tmp)))
|
||||
{
|
||||
case -1:
|
||||
state = 2;
|
||||
break;
|
||||
default:
|
||||
strcat(key, tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( state == 3 )
|
||||
{
|
||||
switch(extract_string(line, tmp, sizeof(tmp)))
|
||||
{
|
||||
case -1:
|
||||
state = 4;
|
||||
break;
|
||||
default:
|
||||
strcat(val, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
if( state == 4 )
|
||||
{
|
||||
if( strlen(key) > 0 && strlen(val) > 0 )
|
||||
{
|
||||
key_id = sfh_hash(key, strlen(key));
|
||||
val_id = sfh_hash(val, strlen(val));
|
||||
|
||||
if( key_id != val_id )
|
||||
{
|
||||
n_entries++;
|
||||
array = realloc(array, n_entries * sizeof(lmo_entry_t));
|
||||
entry = (lmo_entry_t *)array + n_entries - 1;
|
||||
|
||||
if (!array)
|
||||
die("Out of memory");
|
||||
|
||||
entry->key_id = key_id;
|
||||
entry->val_id = val_id;
|
||||
entry->offset = offset;
|
||||
entry->length = strlen(val);
|
||||
|
||||
length = strlen(val) + ((4 - (strlen(val) % 4)) % 4);
|
||||
|
||||
print(val, length, 1, out);
|
||||
offset += length;
|
||||
}
|
||||
}
|
||||
|
||||
state = 0;
|
||||
memset(key, 0, sizeof(key));
|
||||
memset(val, 0, sizeof(val));
|
||||
}
|
||||
|
||||
memset(line, 0, sizeof(line));
|
||||
}
|
||||
|
||||
print_index(array, n_entries, out);
|
||||
|
||||
if( offset > 0 )
|
||||
{
|
||||
print_uint32(offset, out);
|
||||
fsync(fileno(out));
|
||||
fclose(out);
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose(out);
|
||||
unlink(argv[2]);
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
return(0);
|
||||
}
|
||||
328
package/cnsztl/luci-app-openclash/tools/po2lmo/src/template_lmo.c
Executable file
328
package/cnsztl/luci-app-openclash/tools/po2lmo/src/template_lmo.c
Executable file
@ -0,0 +1,328 @@
|
||||
/*
|
||||
* lmo - Lua Machine Objects - Base functions
|
||||
*
|
||||
* Copyright (C) 2009-2010 Jo-Philipp Wich <xm@subsignal.org>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "template_lmo.h"
|
||||
|
||||
/*
|
||||
* Hash function from http://www.azillionmonkeys.com/qed/hash.html
|
||||
* Copyright (C) 2004-2008 by Paul Hsieh
|
||||
*/
|
||||
|
||||
uint32_t sfh_hash(const char *data, int len)
|
||||
{
|
||||
uint32_t hash = len, tmp;
|
||||
int rem;
|
||||
|
||||
if (len <= 0 || data == NULL) return 0;
|
||||
|
||||
rem = len & 3;
|
||||
len >>= 2;
|
||||
|
||||
/* Main loop */
|
||||
for (;len > 0; len--) {
|
||||
hash += sfh_get16(data);
|
||||
tmp = (sfh_get16(data+2) << 11) ^ hash;
|
||||
hash = (hash << 16) ^ tmp;
|
||||
data += 2*sizeof(uint16_t);
|
||||
hash += hash >> 11;
|
||||
}
|
||||
|
||||
/* Handle end cases */
|
||||
switch (rem) {
|
||||
case 3: hash += sfh_get16(data);
|
||||
hash ^= hash << 16;
|
||||
hash ^= data[sizeof(uint16_t)] << 18;
|
||||
hash += hash >> 11;
|
||||
break;
|
||||
case 2: hash += sfh_get16(data);
|
||||
hash ^= hash << 11;
|
||||
hash += hash >> 17;
|
||||
break;
|
||||
case 1: hash += *data;
|
||||
hash ^= hash << 10;
|
||||
hash += hash >> 1;
|
||||
}
|
||||
|
||||
/* Force "avalanching" of final 127 bits */
|
||||
hash ^= hash << 3;
|
||||
hash += hash >> 5;
|
||||
hash ^= hash << 4;
|
||||
hash += hash >> 17;
|
||||
hash ^= hash << 25;
|
||||
hash += hash >> 6;
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
uint32_t lmo_canon_hash(const char *str, int len)
|
||||
{
|
||||
char res[4096];
|
||||
char *ptr, prev;
|
||||
int off;
|
||||
|
||||
if (!str || len >= sizeof(res))
|
||||
return 0;
|
||||
|
||||
for (prev = ' ', ptr = res, off = 0; off < len; prev = *str, off++, str++)
|
||||
{
|
||||
if (isspace(*str))
|
||||
{
|
||||
if (!isspace(prev))
|
||||
*ptr++ = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr++ = *str;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ptr > res) && isspace(*(ptr-1)))
|
||||
ptr--;
|
||||
|
||||
return sfh_hash(res, ptr - res);
|
||||
}
|
||||
|
||||
lmo_archive_t * lmo_open(const char *file)
|
||||
{
|
||||
int in = -1;
|
||||
uint32_t idx_offset = 0;
|
||||
struct stat s;
|
||||
|
||||
lmo_archive_t *ar = NULL;
|
||||
|
||||
if (stat(file, &s) == -1)
|
||||
goto err;
|
||||
|
||||
if ((in = open(file, O_RDONLY)) == -1)
|
||||
goto err;
|
||||
|
||||
if ((ar = (lmo_archive_t *)malloc(sizeof(*ar))) != NULL)
|
||||
{
|
||||
memset(ar, 0, sizeof(*ar));
|
||||
|
||||
ar->fd = in;
|
||||
ar->size = s.st_size;
|
||||
|
||||
fcntl(ar->fd, F_SETFD, fcntl(ar->fd, F_GETFD) | FD_CLOEXEC);
|
||||
|
||||
if ((ar->mmap = mmap(NULL, ar->size, PROT_READ, MAP_SHARED, ar->fd, 0)) == MAP_FAILED)
|
||||
goto err;
|
||||
|
||||
idx_offset = ntohl(*((const uint32_t *)
|
||||
(ar->mmap + ar->size - sizeof(uint32_t))));
|
||||
|
||||
if (idx_offset >= ar->size)
|
||||
goto err;
|
||||
|
||||
ar->index = (lmo_entry_t *)(ar->mmap + idx_offset);
|
||||
ar->length = (ar->size - idx_offset - sizeof(uint32_t)) / sizeof(lmo_entry_t);
|
||||
ar->end = ar->mmap + ar->size;
|
||||
|
||||
return ar;
|
||||
}
|
||||
|
||||
err:
|
||||
if (in > -1)
|
||||
close(in);
|
||||
|
||||
if (ar != NULL)
|
||||
{
|
||||
if ((ar->mmap != NULL) && (ar->mmap != MAP_FAILED))
|
||||
munmap(ar->mmap, ar->size);
|
||||
|
||||
free(ar);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void lmo_close(lmo_archive_t *ar)
|
||||
{
|
||||
if (ar != NULL)
|
||||
{
|
||||
if ((ar->mmap != NULL) && (ar->mmap != MAP_FAILED))
|
||||
munmap(ar->mmap, ar->size);
|
||||
|
||||
close(ar->fd);
|
||||
free(ar);
|
||||
|
||||
ar = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
lmo_catalog_t *_lmo_catalogs = NULL;
|
||||
lmo_catalog_t *_lmo_active_catalog = NULL;
|
||||
|
||||
int lmo_load_catalog(const char *lang, const char *dir)
|
||||
{
|
||||
DIR *dh = NULL;
|
||||
char pattern[16];
|
||||
char path[PATH_MAX];
|
||||
struct dirent *de = NULL;
|
||||
|
||||
lmo_archive_t *ar = NULL;
|
||||
lmo_catalog_t *cat = NULL;
|
||||
|
||||
if (!lmo_change_catalog(lang))
|
||||
return 0;
|
||||
|
||||
if (!dir || !(dh = opendir(dir)))
|
||||
goto err;
|
||||
|
||||
if (!(cat = malloc(sizeof(*cat))))
|
||||
goto err;
|
||||
|
||||
memset(cat, 0, sizeof(*cat));
|
||||
|
||||
snprintf(cat->lang, sizeof(cat->lang), "%s", lang);
|
||||
snprintf(pattern, sizeof(pattern), "*.%s.lmo", lang);
|
||||
|
||||
while ((de = readdir(dh)) != NULL)
|
||||
{
|
||||
if (!fnmatch(pattern, de->d_name, 0))
|
||||
{
|
||||
snprintf(path, sizeof(path), "%s/%s", dir, de->d_name);
|
||||
ar = lmo_open(path);
|
||||
|
||||
if (ar)
|
||||
{
|
||||
ar->next = cat->archives;
|
||||
cat->archives = ar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dh);
|
||||
|
||||
cat->next = _lmo_catalogs;
|
||||
_lmo_catalogs = cat;
|
||||
|
||||
if (!_lmo_active_catalog)
|
||||
_lmo_active_catalog = cat;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (dh) closedir(dh);
|
||||
if (cat) free(cat);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int lmo_change_catalog(const char *lang)
|
||||
{
|
||||
lmo_catalog_t *cat;
|
||||
|
||||
for (cat = _lmo_catalogs; cat; cat = cat->next)
|
||||
{
|
||||
if (!strncmp(cat->lang, lang, sizeof(cat->lang)))
|
||||
{
|
||||
_lmo_active_catalog = cat;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static lmo_entry_t * lmo_find_entry(lmo_archive_t *ar, uint32_t hash)
|
||||
{
|
||||
unsigned int m, l, r;
|
||||
uint32_t k;
|
||||
|
||||
l = 0;
|
||||
r = ar->length - 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
m = l + ((r - l) / 2);
|
||||
|
||||
if (r < l)
|
||||
break;
|
||||
|
||||
k = ntohl(ar->index[m].key_id);
|
||||
|
||||
if (k == hash)
|
||||
return &ar->index[m];
|
||||
|
||||
if (k > hash)
|
||||
{
|
||||
if (!m)
|
||||
break;
|
||||
|
||||
r = m - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
l = m + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int lmo_translate(const char *key, int keylen, char **out, int *outlen)
|
||||
{
|
||||
uint32_t hash;
|
||||
lmo_entry_t *e;
|
||||
lmo_archive_t *ar;
|
||||
|
||||
if (!key || !_lmo_active_catalog)
|
||||
return -2;
|
||||
|
||||
hash = lmo_canon_hash(key, keylen);
|
||||
|
||||
for (ar = _lmo_active_catalog->archives; ar; ar = ar->next)
|
||||
{
|
||||
if ((e = lmo_find_entry(ar, hash)) != NULL)
|
||||
{
|
||||
*out = ar->mmap + ntohl(e->offset);
|
||||
*outlen = ntohl(e->length);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void lmo_close_catalog(const char *lang)
|
||||
{
|
||||
lmo_archive_t *ar, *next;
|
||||
lmo_catalog_t *cat, *prev;
|
||||
|
||||
for (prev = NULL, cat = _lmo_catalogs; cat; prev = cat, cat = cat->next)
|
||||
{
|
||||
if (!strncmp(cat->lang, lang, sizeof(cat->lang)))
|
||||
{
|
||||
if (prev)
|
||||
prev->next = cat->next;
|
||||
else
|
||||
_lmo_catalogs = cat->next;
|
||||
|
||||
for (ar = cat->archives; ar; ar = next)
|
||||
{
|
||||
next = ar->next;
|
||||
lmo_close(ar);
|
||||
}
|
||||
|
||||
free(cat);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
92
package/cnsztl/luci-app-openclash/tools/po2lmo/src/template_lmo.h
Executable file
92
package/cnsztl/luci-app-openclash/tools/po2lmo/src/template_lmo.h
Executable file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* lmo - Lua Machine Objects - General header
|
||||
*
|
||||
* Copyright (C) 2009-2012 Jo-Philipp Wich <xm@subsignal.org>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _TEMPLATE_LMO_H_
|
||||
#define _TEMPLATE_LMO_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fnmatch.h>
|
||||
#include <dirent.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
|
||||
#if (defined(__GNUC__) && defined(__i386__))
|
||||
#define sfh_get16(d) (*((const uint16_t *) (d)))
|
||||
#else
|
||||
#define sfh_get16(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
|
||||
+(uint32_t)(((const uint8_t *)(d))[0]) )
|
||||
#endif
|
||||
|
||||
|
||||
struct lmo_entry {
|
||||
uint32_t key_id;
|
||||
uint32_t val_id;
|
||||
uint32_t offset;
|
||||
uint32_t length;
|
||||
} __attribute__((packed));
|
||||
|
||||
typedef struct lmo_entry lmo_entry_t;
|
||||
|
||||
|
||||
struct lmo_archive {
|
||||
int fd;
|
||||
int length;
|
||||
uint32_t size;
|
||||
lmo_entry_t *index;
|
||||
char *mmap;
|
||||
char *end;
|
||||
struct lmo_archive *next;
|
||||
};
|
||||
|
||||
typedef struct lmo_archive lmo_archive_t;
|
||||
|
||||
|
||||
struct lmo_catalog {
|
||||
char lang[6];
|
||||
struct lmo_archive *archives;
|
||||
struct lmo_catalog *next;
|
||||
};
|
||||
|
||||
typedef struct lmo_catalog lmo_catalog_t;
|
||||
|
||||
|
||||
uint32_t sfh_hash(const char *data, int len);
|
||||
uint32_t lmo_canon_hash(const char *data, int len);
|
||||
|
||||
lmo_archive_t * lmo_open(const char *file);
|
||||
void lmo_close(lmo_archive_t *ar);
|
||||
|
||||
|
||||
extern lmo_catalog_t *_lmo_catalogs;
|
||||
extern lmo_catalog_t *_lmo_active_catalog;
|
||||
|
||||
int lmo_load_catalog(const char *lang, const char *dir);
|
||||
int lmo_change_catalog(const char *lang);
|
||||
int lmo_translate(const char *key, int keylen, char **out, int *outlen);
|
||||
void lmo_close_catalog(const char *lang);
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue
Block a user