diff --git a/.build/default.Manifest.xml b/.build/default.Manifest.xml
new file mode 100644
index 0000000..916d05f
--- /dev/null
+++ b/.build/default.Manifest.xml
@@ -0,0 +1,60 @@
+
+
+
+ winXray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True/PM
+
+
+
\ No newline at end of file
diff --git a/.build/default.init.aardio b/.build/default.init.aardio
new file mode 100644
index 0000000..2b00a05
--- /dev/null
+++ b/.build/default.init.aardio
@@ -0,0 +1,5 @@
+//发布前触发
+import ide;
+io.remove("\..\v2ray-core\config.json")
+io.remove("\..\WinXray\v2ray-core\config.json")
+
\ No newline at end of file
diff --git a/.build/default.main.aardio b/.build/default.main.aardio
new file mode 100644
index 0000000..6f69530
--- /dev/null
+++ b/.build/default.main.aardio
@@ -0,0 +1,40 @@
+//此触发器在生成EXE以后执行
+
+import ide;
+import fsys;
+import console;
+if( !console.askYesNo('是否生成 winXray.7z,winXray32.7z ? 按Y键继续,按N键取消') ){
+ return console.close();
+}
+
+//获取生成的EXE文件路径
+var publishFile = ide.getPublishPath();
+var projectDir = ide.getProjectDir();
+
+var tempDir = io.joinpath(projectDir,"release/7z-temp");
+fsys.createDir(tempDir,true)
+
+fsys.copy(publishFile,io.joinpath(tempDir,ide.getPublishName()));
+fsys.copy(io.joinpath(projectDir,"v2ray-core\*.*"),io.joinpath(tempDir,"v2ray-core"));
+
+import console;
+import sevenZip.cmd;
+
+console.open()
+console.showLoading(" 正在生成 winXray.7z, winXray32.7z");
+
+fsys.delete(io.joinpath(projectDir,"release/winXray.7z"));
+sevenZip.cmd.compress( io.joinpath(tempDir,"*")
+ ,io.joinpath(projectDir,"release/winXray.7z")
+ ,console.log //这里可以设置一个回调函数,输出回显结果
+ )
+
+fsys.delete(io.joinpath(projectDir,"release/winXray32.7z"));
+fsys.copy(io.joinpath(projectDir,"v2ray-core-32\*.*"),io.joinpath(tempDir,"v2ray-core"));
+sevenZip.cmd.compress( io.joinpath(tempDir,"*")
+ ,io.joinpath(projectDir,"release/winXray32.7z")
+ ,console.log //这里可以设置一个回调函数,输出回显结果
+ )
+
+fsys.delete(tempDir);
+console.close();
\ No newline at end of file
diff --git a/.build/update-maker.table b/.build/update-maker.table
new file mode 100644
index 0000000..ded4862
--- /dev/null
+++ b/.build/update-maker.table
@@ -0,0 +1,6 @@
+{
+updateUrl="https://raw.githubusercontent.com/winXray/winXray/master/release/update/";
+singleFile=1;
+description="发布 v3.8, 优化代码修正已知问题。";
+outputDir="/release/update/"
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..66c7d4e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+/v2ray-core/config.json
+/v2ray-core-32/config.json
+/v2ray-core/ssr-core/
+/winXray/v2ray-core/config.json
+/winXray/
+/release/winXray/
+/release/winXray32/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..3c577b0
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,24 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..33ad3d2
--- /dev/null
+++ b/README.md
@@ -0,0 +1,140 @@
+
+# WinXray
+WinXray[:loud_sound:](http://dict.youdao.com/dictvoice?audio=winxray&type=2) 是最简洁轻快的 V2Ray、XRay、Trojan、Trojan-go、Shadowsocks、SSR(ShadowsocksR)、SSRoT、NaïveProxy,SOCKS,HTTP,HTTPS 全能通用客户端(Windows系统),支持并发检测大量服务器并迅速找到当前最快的服务器,服务器连接异常时可自动寻找其他速度最快的服务器 - 切换速度快如闪电,自订阅源获取的服务器异常时可自动刷新订阅,并且自带一键自动部署服务端工具。
+
+**本软件源码已放弃版权贡献到公共域** ,源码可使用 [aardio](http://www.aardio.com) 编译生成单文件绿色EXE,**[点这里下载](./../../raw/master/release/winXray.7z)** ( [64位版本](./../../raw/master/release/winXray.7z) / [32位版本](./../../raw/master/release/winXray32.7z) ),解压即可直接使用( 体积很小仅 **[6.1 MB](./../../raw/master/release/winXray.7z)** - 已自带 V2Ray Core )。
+
+# WinXray 未注册任何域名,谨防钓鱼网站
+WinXray 分为原版、抄袭版。
+抄袭版没有贡献任何功能,仅添加了假冒官网推广链接,然后原版更新任何功能,抄袭版都会复制粘贴改成他自己的名字重新提交,并且乱改版本号,日常踩原作者吹捧自己。原版作者估计是受不了那货已经失踪很久了。
+
+本项目基于原版 WinXray v3.7 基础上继续更新 ,并将保持原版干净、纯净。本项目严禁上述假冒官网的抄袭版抄袭本项目的任何一句代码 。
+
+# 免费服务器
+[网络免费 vmess 服务器订阅链接](https://proxypool.ga/vmess/sub)
+[网络免费 Shadowsocks 服务器订阅链接](https://proxypool.ga/ss/sub)
+[网络免费 clash 服务器订阅链接](https://proxypoolss.tk/clash/proxies?speed=100&type=vmess,trojan)
+可复制上面各种格式订阅链接,在 winXray 中点击「批量导入链接」体验 winXray 有强大的兼容性。
+免费的服务器仅供测试(一定要走 PAC,不要开全局代理不要登录账号更不要长时间使用 )。
+
+# 关于误报
+现在大多杀毒软件都是白名单查杀,所以新生的EXE都会乱报病毒,因为我更新的速度太快,所以不断的推新EXE上来,所以你可能遇到误报,但是你完全可以使用源代码自己编译出一模一样的EXE,还有人吹牛说其他翻墙软件不误报 - 你去 issues 里以及网上搜一下有多少误报好不好?!遇到误报可以提交给你的杀毒厂商核实,也可以自己编译源码生成EXE后使用,解决和核实问题很容易 - 其他套路都是多余的。
+
+
+# PAC 代理模式 / 全局代理 + 路由模式 对比
+
+winXray 的 PAC 代理稳定、流畅、易用。 在 PAC 模式下,winXray 会优先启用高效安全的 SOCKS5 协议,并且可以自动兼容在 PAC 模式下仅支持 HTTP代理的应用。winXray 也可以在 PAC 模式下完美支持 Telegram IP 地址库 。
+
+SOCKS5 支持对比:
+- [ ] 全局路由模式: 不支持 SOCKS5
+- [x] PAC模式: 支持 高效安全的SOCKS5
+
+UWP 应用支持对比:
+- [ ] 全局路由模式: UWP 应用全部无法联网。
+- [x] PAC模式: UWP 应用可以正常联网,使用 winXray 自带工具也可以为UWP应用开启本地代理。
+
+DNS 解析对比:
+- [ ] 全局路由模式: 使用本机发起 DNS 解析,即使设为国外 DNS 服务器,仍然会返回适用于国内线路地址。
+- [x] PAC模式: 使用服务器上的 DNS 解析,安全可靠。
+
+根据客户端自动切换代理协议:
+- [ ] 全局路由模式: 不支持
+- [x] PAC模式: winXray 里的 PAC 代理可以让目标应用(例如浏览器)优先选择高效安全的 SOCKS5 代理协议,对于不支持 SOCKS 代理的应用(例如谷歌地球),winXray 在 PAC 模式下会自动为这些应用提供 HTTP 代理。
+
+IP 段代理规则:
+- [x] 全局路由模式: 比较好的支持 IP 段代理规则
+- [x] PAC模式: winXray 里 PAC 可以支持IP 段代理规则( 完美支持 Telegram )。
+
+独立性
+- [ ] 全局路由模式: 不独立,代理规则集成在翻墙软件内核中
+- [x] PAC模式: 完全独立,PAC 代理服务完全独立于翻墙软件,只有 PAC 指定的域名或IP才会与翻墙软件发生交互。
+
+兼容性
+- [ ] 全局路由模式: 不是由系统实现的规则,一旦设置全局代理,不管适不适合走代理的软件都被强制使用代理,所以兼容性不太好,会导致上述的 UWP 无法联网等问题。
+- [x] PAC模式: 由系统提供的PAC有良好的兼容性,因为历史悠久,一般的软件都会对PAC有良好的兼容,PAC 主要为适合走代理的浏览器等软件而设计,所以其他软件可以较好的识别并判断是不是要使用 PAC 指定的代理还是直连。
+
+简易度
+- [ ] 全局路由模式: 配置复杂,有一定门槛。
+- [x] PAC模式: 配置非常简单。
+
+
+一般不建议普通用户去编辑路由规则 - 错误的配置可能会导致敏感的流量误走代理服务器。
+专业的事请交给专业的人去做,使用 winXray 可以一键启用、更新 [v2ray-rules-dat](https://github.com/Loyalsoldier/v2ray-rules-dat) 提供的最新路由规则。
+
+注意在 winXray 里无论使用 NaïveProxy 还是 SSR,SSRoT 都支持 V2Ray 路由规则。
+
+# 设置系统代理失败怎么办
+如果设置代理以后不能正常生效:请首先右键点击 winXray 任务栏的托盘图标,在弹出的右键菜单中点击【查看 Internet 代理设置】,并检查代理设置是否正常。如果 winXray 不能修改代理设置,但是可以手动修改成功,这一般是被安全软件错误地拦截了( 而且安全软件没有正常弹出确认对话框,或者误点了阻止设置 )。这时候请到安全软件的相关设置中将 winXray 添加到信任列表即可。
+
+如果不是上面的原因,请按下【Win + R】组合键打开系统运行对话框,输入 regedit 点击确定打开注册表路径
+HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections
+然后将“Connections”项删除,注销一下系统即可正常使用代理了。
+
+如果上面的方法仍然不行,请在注册表中打开打开路径
+Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WinHttpAutoProxySvc
+将 start 的值改为 2, 也就是将 WinHttpAutoProxySvc 服务改为自动启动,然后重启计算机即可。
+
+# Core 默认路径:
+
+可在「 winXray/ 配置 / Core配置 」 下载更新 V2Ray Core / Xray Core / SSR Core ,
+下载更新 V2Ray Core(或 Xray Core)完成后会自动切换 V2Ray 内核。
+
+默认会在以下目录查找 V2Ray Core(或 Xray Core):
+
+ ./v2ray-core/
+ %localappdata%\winXray\core
+
+默认会在以下目录查找 SSR Core:
+
+ ./v2ray-core/ssr-core
+ %localappdata%\winXray\ssr-core
+
+默认会在以下目录查找 NaïveProxy Core:
+
+ ./v2ray-core/naive-core
+ %localappdata%\winXray\naive-core
+
+找不到会自动下载,没有代理访问 Github 会很慢很慢,有时可能根本打不开,建议经常运行一下 winXray 工具里自带的 【Github 网速优化工具】
+
+注意不同的代理协议连接时会调用不同的 Core,
+例如 NaïveProxy 连接时会启动 naive.exe,这时候系统防火墙会有提示,
+如果这时候没看清就点了拒绝,那么就无法正常使用相应的 Core 了,
+所以请看清楚再点,点错了到系统防火墙里再打开一下就可以了。
+
+# 安装 NaïveProxy 服务端
+
+参考:https://github.com/klzgrad/naiveproxy 以 CentOS 为例:
+
+```sh
+yum intall golang
+yum install git
+go get -u github.com/caddyserver/xcaddy/cmd/xcaddy
+~/go/bin/xcaddy build --with github.com/caddyserver/forwardproxy@caddy2=github.com/klzgrad/forwardproxy@naive
+sudo setcap cap_net_bind_service=+ep ./caddy
+wget -O naive.tar.xz https://github.com/klzgrad/naiveproxy/releases/download/v88.0.4324.96-1/naiveproxy-v88.0.4324.96-1-linux-x64.tar.xz
+tar -xf ./naive.tar.xz
+
+mv naiveproxy-v88.0.4324.96-1-linux-x64 naive
+echo -e "{\n \"listen\": \"socks://127.0.0.1:1080\",\n \"proxy\": \"https://user:pass@example.com\"\n}" > ./naive/config.json
+
+cat << EOF > ./Caddyfile
+:443, example.com
+tls me@example.com
+route {
+ forward_proxy {
+ basic_auth user pass
+ hide_ip
+ hide_via
+ probe_resistance
+ }
+ file_server { root /var/www/html }
+}
+EOF
+
+iptables -A INPUT -p tcp --dport 80 -j ACCEPT;iptables -A INPUT -p tcp --dport 443 -j ACCEPT;firewall-cmd --permanent --add-port=80/tcp;firewall-cmd --permanent --add-port=443/tcp;firewall-cmd --reload;
+
+./naive/naive --config ./naive/config.json &
+./caddy run # 后台运行改成 ./caddy start
+```
+
+安装以前需要提前准备一个域名,并将上面脚本中的 example.com 替换为你的域名,user:pass 改为代理登录用户名与密码。
\ No newline at end of file
diff --git a/default.aproj b/default.aproj
new file mode 100644
index 0000000..81b1507
--- /dev/null
+++ b/default.aproj
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/forms/ico/app-direct.ico b/forms/ico/app-direct.ico
new file mode 100644
index 0000000..5de600e
Binary files /dev/null and b/forms/ico/app-direct.ico differ
diff --git a/forms/ico/app-pac.ico b/forms/ico/app-pac.ico
new file mode 100644
index 0000000..95d7a0d
Binary files /dev/null and b/forms/ico/app-pac.ico differ
diff --git a/forms/ico/app.ico b/forms/ico/app.ico
new file mode 100644
index 0000000..1b9402b
Binary files /dev/null and b/forms/ico/app.ico differ
diff --git a/forms/main/config/advancedConfig.aardio b/forms/main/config/advancedConfig.aardio
new file mode 100644
index 0000000..f050347
--- /dev/null
+++ b/forms/main/config/advancedConfig.aardio
@@ -0,0 +1,396 @@
+import fonts.fontAwesome;
+import win.ui;
+/*DSG{{*/
+var winform = win.form(text="aardio form";right=892;bottom=573;bgcolor=16777215)
+winform.add(
+btnOpenFirewall={cls="plus";text="设置防火墙";left=485;top=398;right=615;bottom=428;align="left";db=1;dl=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=12}};iconText='\uF09C';notify=1;textPadding={left=30};z=7};
+btnUpdate={cls="plus";text="保 存";left=516;top=514;right=619;bottom=550;align="left";bgcolor=11580047;db=1;dl=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=22}};iconText='\uF0C7';notify=1;textPadding={left=40};z=5};
+chkEnableGitConfigGithub={cls="plus";text="设置 git 客户端启用 github.com 代理提速(支持https、ssh协议)";left=276;top=437;right=792;bottom=468;align="left";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-16;name='FontAwesome')};iconText='\uF0C8';notify=1;textPadding={left=19};z=13};
+chkLan={cls="plus";text="允许来自局域网的连接";left=276;top=397;right=483;bottom=428;align="left";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-16;name='FontAwesome')};iconText='\uF0C8';notify=1;textPadding={left=19};z=1};
+chkSystemStart={cls="plus";text="允许开机启动 winXray";left=276;top=476;right=792;bottom=507;align="left";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-16;name='FontAwesome')};iconText='\uF0C8';notify=1;textPadding={left=19};z=17};
+editHttpPort={cls="plus";left=278;top=126;right=358;bottom=150;align="left";bgcolor=16777215;border={bottom=1;color=-8355712};db=1;dl=1;editable="edit";font=LOGFONT(h=-16);textPadding={bottom=1};z=14};
+editLanPacUrl={cls="plus";left=280;top=357;right=699;bottom=381;align="left";bgcolor=16777215;border={bottom=1;color=-8355712};db=1;dl=1;editable="edit";font=LOGFONT(h=-16);textPadding={bottom=1};z=11};
+editPacPort={cls="plus";left=278;top=281;right=358;bottom=305;align="left";bgcolor=16777215;border={bottom=1;color=-8355712};db=1;dl=1;editable="edit";font=LOGFONT(h=-16);textPadding={bottom=1};z=2};
+editPacUrl={cls="plus";left=278;top=318;right=697;bottom=342;align="left";bgcolor=16777215;border={bottom=1;color=-8355712};db=1;dl=1;editable="edit";font=LOGFONT(h=-16);textPadding={bottom=1};z=8};
+editSocksPort={cls="plus";left=278;top=91;right=358;bottom=115;align="left";bgcolor=16777215;border={bottom=1;color=-8355712};db=1;dl=1;editable="edit";font=LOGFONT(h=-16);textPadding={bottom=1};z=3};
+hotkey={cls="hotkey";left=227;top=249;right=367;bottom=269;clip=1;db=1;dl=1;edge=1;z=26};
+lbMaxTestServers={cls="static";text="100";left=564;top=62;right=880;bottom=88;bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-13);transparent=1;z=25};
+lbTestInterval={cls="static";text="15秒";left=564;top=26;right=823;bottom=52;bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-13);transparent=1;z=20};
+lnkVersion={cls="plus";text="正在检查新版本";left=15;top=533;right=376;bottom=564;align="left";color=8388608;db=1;dl=1;font=LOGFONT(h=-13);iconColor=2960685;iconStyle={align="left";font=LOGFONT(h=-16;name='FontAwesome')};iconText='\uF021';notify=1;paddingLeft=20;z=10};
+plus={cls="plus";text="全局/PAC 代理切换热键";left=368;top=248;right=702;bottom=270;align="left";db=1;dl=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(name='FontAwesome');padding={left=9}};iconText='\uF11C ';notify=1;tabstop=1;textPadding={left=25};z=27};
+radioHttpPac={cls="plus";text="仅 HTTP";left=273;top=167;right=365;bottom=198;align="left";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-16;name='FontAwesome')};iconText='\uF111 ';notify=1;textPadding={left=19};z=21};
+radioHttpProxy={cls="plus";text="HTTP( 推荐 )";left=378;top=205;right=537;bottom=236;align="left";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-16;name='FontAwesome')};iconText='\uF111 ';notify=1;textPadding={left=19};z=29};
+radioSocksPac={cls="plus";text="SOCKS5/SOCKS4/HTTP 自动兼容( 推荐 ) ";left=378;top=167;right=727;bottom=198;align="left";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-16;name='FontAwesome')};iconText='\uF111 ';notify=1;textPadding={left=19};z=22};
+radioSocksProxy={cls="plus";text="SOCKS4";left=273;top=205;right=371;bottom=236;align="left";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-16;name='FontAwesome')};iconText='\uF111 ';notify=1;textPadding={left=19};z=28};
+static={cls="static";text="SOCKS 代理服务端口:";left=68;top=95;right=266;bottom=121;align="right";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);transparent=1;z=4};
+static10={cls="static";text="PAC代理模式:";left=8;top=170;right=266;bottom=196;align="right";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);transparent=1;z=30};
+static11={cls="static";text="全局代理模式:";left=8;top=208;right=266;bottom=234;align="right";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);transparent=1;z=31};
+static2={cls="static";text="PAC 端口:";left=136;top=286;right=266;bottom=312;align="right";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);transparent=1;z=6};
+static3={cls="static";text="本机 PAC 地址:";left=108;top=325;right=266;bottom=351;align="right";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);transparent=1;z=9};
+static4={cls="static";text="局域网 PAC 地址:";left=108;top=364;right=266;bottom=390;align="right";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);transparent=1;z=12};
+static5={cls="static";text="HTTP 代理服务端口:";left=8;top=132;right=266;bottom=158;align="right";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);transparent=1;z=15};
+static6={cls="static";text="支持 SOCKS4、SOCKS4A、SOCKS5";left=366;top=96;right=653;bottom=122;bgcolor=16777215;color=5921370;db=1;dl=1;font=LOGFONT(h=-13);transparent=1;z=16};
+static7={cls="static";text="检测服务器异常间隔时间:";left=21;top=19;right=266;bottom=45;align="right";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);transparent=1;z=19};
+static8={cls="static";text="允许同时测速的服务器数目:";left=21;top=57;right=266;bottom=83;align="right";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);transparent=1;z=24};
+tbMaxTestServers={cls="plus";left=278;top=64;right=559;bottom=76;bgcolor=-2512093;border={radius=-1};color=23807;db=1;dl=1;foreRight=13;forecolor=-14911489;notify=1;paddingBottom=5;paddingTop=5;z=23};
+tbTestInterval={cls="plus";left=278;top=27;right=559;bottom=39;bgcolor=-2512093;border={radius=-1};color=23807;db=1;dl=1;foreRight=13;forecolor=-14911489;notify=1;paddingBottom=5;paddingTop=5;z=18}
+)
+/*}}*/
+
+import style;
+winform.chkLan.skin(style.checkBox);
+winform.chkEnableGitConfigGithub.skin(style.checkBox);
+winform.chkSystemStart.skin(style.checkBox);
+winform.radioHttpProxy.skin(style.radio)
+winform.radioSocksProxy.skin(style.radio)
+winform.radioHttpPac.skin(style.radio)
+winform.radioSocksPac.skin(style.radio)
+winform.btnUpdate.skin(style.primaryButton);
+winform.editSocksPort.skin(style.edit);
+winform.editPacPort.skin(style.edit);
+winform.editPacUrl.editBox.readonly = true;
+
+import win.ui.tooltip;
+var tooltipCtrl = win.ui.tooltip( winform );
+tooltipCtrl.addTool(winform.editSocksPort,"点击右键可以复制IP:端口" );
+tooltipCtrl.addTool(winform.radioHttpProxy,"全局代理使用 HTTP 代理端口可以避免使用本机 DNS 解析域名。" );
+tooltipCtrl.addTool(winform.radioSocksProxy,'全局代理使用 SOCKS 代理端口时,Chrome 浏览器等会默认选用 SOCKS4 协议,SOCKS4 会使用本机 DNS 解析域名。' );
+tooltipCtrl.addTool(winform.radioHttpPac,"PAC 仅使用使用 HTTP 代理端口,不推荐此选项。" );
+tooltipCtrl.addTool(winform.radioSocksPac,'开启此选项以后:\nChrome 浏览器会优先使用高效安全的 SOCKS 5 协议。\n也可以自动兼容仅支持 SOCKS4 或 HTTP代理的应用' );
+
+import v2ray.pacServer;
+onPacUpdated = function(){
+ winform.editPacPort.text = v2ray.pacServer.getPort() || config.proxy.pacPort || 1083;
+
+ var pac = v2ray.pacServer.getUrl();
+ winform.editPacUrl.text = pac ? string.match(pac,"[^?]+");
+ pac = v2ray.pacServer.getUrl(true);
+ winform.editLanPacUrl.text = pac ? string.match(pac,"[^?]+");
+
+ winform.editLanPacUrl.disabled = !winform.chkLan.checked;
+}
+
+subscribe("pacServer.restarted",function(pacPort){
+ onPacUpdated()
+})
+
+subscribe("sysProxy.modeChanged",function(mode){
+ if(mode==="pac"){
+ var pac = v2ray.pacServer.getUrl();
+ winform.editPacUrl.text = pac ? string.match(pac,"[^?]+");
+ pac = v2ray.pacServer.getUrl(true);
+ winform.editLanPacUrl.text = pac ? string.match(pac,"[^?]+");
+ }
+})
+
+import v2ray.core;
+var onInboundsUpdated = function(){
+ var inbounds = ..config.core.default[["inbounds"]];
+ var socksInbounds,httpInbounds;
+ for(k,ib in inbounds){
+ if(ib.tag == "proxy"){
+ socksInbounds = ib;
+ }
+ elseif(ib.tag == "http_proxy"){
+ httpInbounds = ib;
+ }
+ }
+
+ winform.editSocksPort.text = v2ray.core.socksProxyPort || socksInbounds[["port"]] || 1081;
+ winform.editHttpPort.text = v2ray.core.httpProxyPort || httpInbounds[["port"]] || 1082;
+ winform.chkLan.checked = socksInbounds[["listen"]] !== "127.0.0.1";
+ winform.btnOpenFirewall.disabled = !winform.chkLan.checked;
+}
+
+subscribe("config.core.changed",function(){
+ onInboundsUpdated();
+})
+
+subscribe("v2RayCore.restarted",function(socksProxyPort,httpProxPort){
+ onInboundsUpdated();
+})
+
+import win.reg;
+var reg = win.reg("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run\");
+winform.chkSystemStart.checked = reg.queryValue("winXray");
+reg.close();
+
+winform.chkEnableGitConfigGithub.checked = config.proxy.enableGitConfigGithub;
+winform.radioSocksProxy.radioGroup = "proxy.mode";
+winform.radioHttpProxy.radioGroup = "proxy.mode";
+winform.radioHttpPac.radioGroup = "pac.mode";
+winform.radioSocksPac.radioGroup = "pac.mode";
+winform.radioHttpProxy.checked = config.proxy.useHttpGlobal;
+winform.radioSocksProxy.checked = !config.proxy.useHttpGlobal;
+winform.radioHttpPac.checked = !config.proxy.useSocksPac;
+winform.radioSocksPac.checked = config.proxy.useSocksPac;
+winform.hotkey.sethotkey(config.proxy.hotkey[1],config.proxy.hotkey[2])
+onInboundsUpdated();
+onPacUpdated();
+
+import wsock.tcp.client;
+winform.btnUpdate.oncommand = function(id,event){
+ winform.btnUpdate.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'};
+ config.proxy.useHttpGlobal = winform.radioHttpProxy.checked;
+ config.proxy.useSocksPac = winform.radioSocksPac.checked;
+ v2ray.pacServer.updateUseHttpProxy(!config.proxy.useSocksPac);
+
+ var client = wsock.tcp.client();
+ var oldPort = v2ray.core.socksProxyPort;
+ if( tonumber(winform.editSocksPort.text)
+ && tonumber(winform.editSocksPort.text) != oldPort
+ && client.connectTimeout("127.0.0.1",tonumber(winform.editSocksPort.text) ,0.5) ){
+ winform.editSocksPort.editBox.showErrorTip(,"端口已被占用");
+ winform.btnUpdate.disabledText = null;
+ return client.close();
+ }
+ client.close();
+
+ var client = wsock.tcp.client();
+ var oldHttpPort = v2ray.core.httpProxPort;
+ if( tonumber(winform.editHttpPort.text)
+ && tonumber(winform.editHttpPort.text) != oldHttpPort
+ && client.connectTimeout("127.0.0.1",tonumber(winform.editHttpPort.text) ,0.5) ){
+ winform.editHttpPort.editBox.showErrorTip(,"端口已被占用");
+ winform.btnUpdate.disabledText = null;
+ return client.close();
+ }
+ client.close();
+
+ var client = wsock.tcp.client();
+ var oldPacPort = v2ray.pacServer.getPort();
+ if( tonumber(winform.editPacPort.text)
+ && tonumber(winform.editPacPort.text) != oldPacPort
+ && client.connectTimeout("127.0.0.1",tonumber(winform.editPacPort.text) ,0.5) ){
+ winform.editPacPort.editBox.showErrorTip(,"PAC端口已被占用");
+ winform.btnUpdate.disabledText = null;
+ return client.close();
+ }
+ client.close();
+
+
+ if(winform.chkEnableGitConfigGithub.checked!=config.proxy.enableGitConfigGithub){
+ config.proxy.enableGitConfigGithub = winform.chkEnableGitConfigGithub.checked;
+
+ import v2ray.github;
+ if(!config.proxy.enableGitConfigGithub){
+ v2ray.github.setProxy(false);
+ }
+ else {
+ v2ray.github.setProxy(null);
+ }
+ }
+
+ var restartCore = false;
+
+ var socksInbounds,httpInbounds;
+ for(k,ib in config.core.default.inbounds){
+ if(ib.tag == "proxy"){
+ socksInbounds = ib;
+ }
+ elseif(ib.tag == "http_proxy"){
+ httpInbounds = ib;
+ }
+ }
+
+ var port = tonumber(winform.editSocksPort.text)
+ socksInbounds["port"] = port;
+ if(port!=oldPort){
+ restartCore = true;
+ }
+
+ var port = tonumber(winform.editHttpPort.text)
+ httpInbounds["port"] = port;
+ if(port!=oldHttpPort){
+ restartCore = true;
+ }
+
+ var listen = winform.chkLan.checked ? "0.0.0.0" : "127.0.0.1";
+ if(listen!=socksInbounds["listen"]){
+ socksInbounds["listen"]= listen;
+ restartCore = true;
+ }
+
+ if(listen!=config.core.default.inbounds[2]["listen"]){
+ httpInbounds["listen"]= listen;
+ restartCore = true;
+ }
+
+ config.core.save();
+ publish("config.inbounds.changed");
+ if(restartCore) {
+ publish("uiCommand.restartV2RayCore");
+ }
+
+ config.proxy.pacPort = tonumber(winform.editPacPort.text)
+ if(oldPacPort!=tonumber(winform.editPacPort.text)){
+ v2ray.pacServer.restart();
+ }
+
+ config.proxy.save();
+ sysProxy.reset(true);
+
+ import win.reg;
+ var reg = win.reg("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run\");
+ if(!_STUDIO_INVOKED){
+ if(winform.chkSystemStart.checked){
+ reg.setSzValue("winXray",`"`+io._exepath+`" /tray`);
+ }
+ else {
+ reg.delValue("winXray");
+ }
+ }
+ reg.close();
+
+ var hotmod,hotkey = winform.hotkey.gethotkey()
+ config.proxy.hotkey = {hotmod;hotkey};
+ config.proxy.save();
+
+ publish("uiCommand.HotkeyChanged");
+
+ winform.btnUpdate.disabledText = null;
+ winform.msgOk("配置已更新",1200);
+}
+
+winform.editPacUrl.editBox.readonly = true;
+winform.editLanPacUrl.editBox.readonly = true;
+
+import win.clip;
+import wsock.tcp.client;
+winform.editSocksPort.editBox.enablePopMenu(function(){
+ var lanIp = wsock.tcp.client.getLocalIp("www.baidu.com");
+ return {
+ { "复制端口" + winform.editSocksPort.text;
+ function(id){
+ win.clip.write("" + winform.editSocksPort.text)
+ }
+ };
+ { "复制本机IP与端口 127.0.0.1:" + winform.editSocksPort.text;
+ function(id){
+ win.clip.write("127.0.0.1:" + winform.editSocksPort.text)
+ }
+ };
+ { "复制局域网IP与端口 "+lanIp+":" + winform.editSocksPort.text;
+ function(id){
+ win.clip.write(lanIp+":" + winform.editSocksPort.text)
+ }
+ };
+ }
+} )
+
+winform.editHttpPort.editBox.enablePopMenu(function(){
+ var lanIp = wsock.tcp.client.getLocalIp("www.baidu.com");
+ return {
+ { "复制端口" + winform.editHttpPort.text;
+ function(id){
+ win.clip.write("" + winform.editHttpPort.text)
+ }
+ };
+ { "复制本机IP与端口 127.0.0.1:" + winform.editHttpPort.text;
+ function(id){
+ win.clip.write("127.0.0.1:" + winform.editHttpPort.text)
+ }
+ };
+ { "复制局域网IP与端口 "+lanIp+":" + winform.editHttpPort.text;
+ function(id){
+ win.clip.write(lanIp+":" + winform.editHttpPort.text)
+ }
+ };
+ }
+} )
+
+winform.editPacUrl.setCueBannerText("当前未启用本机PAC代理");
+winform.editLanPacUrl.setCueBannerText("当前未启用局域网PAC代理");
+
+winform.chkLan.oncommand = function(id,event){
+ winform.editLanPacUrl.editBox.setsel(0);
+ winform.editLanPacUrl.disabled = !winform.chkLan.checked;
+ winform.btnOpenFirewall.disabled = !winform.chkLan.checked;
+}
+
+winform.tbTestInterval.setTrackbarRange(1,30);
+winform.tbTestInterval.skin(style.trackbar);
+winform.tbTestInterval.progressPos = config.proxy.testInterval;
+winform.lbTestInterval.text = config.proxy.testInterval+"秒";
+winform.tbTestInterval.onPosChanged = function( pos,thumbTrack ){
+ winform.lbTestInterval.text = pos+"秒";
+ config.proxy.testInterval = pos;
+ config.proxy.save();
+}
+
+winform.tbMaxTestServers.setTrackbarRange(50,1000);
+winform.tbMaxTestServers.skin(style.trackbar);
+winform.tbMaxTestServers.progressPos = config.proxy.maxTestServers;
+winform.lbMaxTestServers.text = config.proxy.maxTestServers+"个服务器";
+winform.tbMaxTestServers.onPosChanged = function( pos,thumbTrack ){
+ if(pos>300){
+ winform.lbMaxTestServers.color = 0xFF;
+ winform.lbMaxTestServers.text = pos+"个服务器( 数值太大可能导致卡顿 )";
+ }
+ else {
+ winform.lbMaxTestServers.color = 0;
+ winform.lbMaxTestServers.text = pos+"个服务器";
+ }
+
+ config.proxy.maxTestServers = pos;
+ config.proxy.save();
+}
+
+if(table.getByNamespace("fsys.update.simpleMain")){
+ fsys.update.simpleMain.onStatusChanged(function(version,description,status){
+ /*注意此回调可捕获到调用前或调用后的更新状态变更*/
+ if(status=="ready"){
+ winform.lnkVersion.disabledText = null;
+ winform.lnkVersion.text = "点这里重新启动软件更新到新版本:" + version
+ tooltipCtrl.addTool(winform.lnkVersion,description);
+ }
+ elseif(status=="complete"){
+ winform.lnkVersion.text = "已更新到最新版本:" + version;
+ tooltipCtrl.addTool(winform.lnkVersion,description);
+ ..publish("uiCommand.print",winform.lnkVersion.text );
+ }
+ elseif(status=="latest"){
+ winform.lnkVersion.disabledText = null;
+ winform.lnkVersion.text = "已经是最新版本";
+
+ }
+ elseif(status=="failed"){
+ winform.lnkVersion.disabledText = null;
+ ..publish("uiCommand.print",description);
+ ..publish("uiCommand.print","建议在「工具」中运行「github优化工具」修复无法访问 raw.githubusercontent.com 的问题。");
+ }
+ })
+
+ winform.lnkVersion.skin(style.link)
+ tooltipCtrl.addTool(winform.lnkVersion,"点击检测更新" );
+ winform.lnkVersion.oncommand = function(id,event){
+
+ winform.lnkVersion.text = fsys.update.simpleMain.getReadyStatusInfo() ? "正在启动自动更新" : "正在检查新版本";
+ winform.lnkVersion.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'}
+ if(fsys.update.simpleMain.checkUpdate(true)){
+ win.quitMessage();
+ }
+ }
+}
+else {
+ winform.lnkVersion.iconText = '\uF09B';
+ winform.lnkVersion.text = "github.com/win-xray/win-xray";
+ tooltipCtrl.addTool(winform.lnkVersion,"访问项目主页,友情提醒:WinXray未注册任何域名,谨防钓鱼网站" );
+
+ winform.lnkVersion.oncommand = function(id,event){
+
+ import process;
+ process.openUrl("https://github.com/win-xray/win-xray");
+ }
+}
+
+
+winform.btnOpenFirewall.skin(style.plainButton)
+winform.btnOpenFirewall.oncommand = function(id,event){
+ import process.control;
+ process.control("firewall.cpl")
+}
+
+winform.show();
+win.loopMessage();
+return winform;
\ No newline at end of file
diff --git a/forms/main/config/coreConfigs/default.json b/forms/main/config/coreConfigs/default.json
new file mode 100644
index 0000000..75489b2
--- /dev/null
+++ b/forms/main/config/coreConfigs/default.json
@@ -0,0 +1,71 @@
+{
+ "inbounds": [ // 入站节点,也就是本地代理端口配置
+ {
+ "listen": "127.0.0.1", // 本机 SOCKS 代理端口,设为 0 时由 winXray 重置为合适的默认端口
+ "port": 0, // 本机 SOCKS 代理端口,设为 0 时由 winXray 重置为合适的默认端口
+ "protocol": "socks", // 入站代理协议
+ "settings": {
+ "auth": "noauth",
+ "udp": true
+ },
+ "sniffing": {
+ "destOverride": [
+ "http",
+ "tls"
+ ],
+ "enabled": true
+ },
+ "tag": "proxy" // 名称为"proxy"的节点由 winXray 自动维护并添加用户配置
+ },
+ {
+ "listen": "127.0.0.1",
+ "port": 0,
+ "protocol": "http",
+ "settings": {},
+ "sniffing": {
+ "destOverride": [
+ "http",
+ "tls"
+ ],
+ "enabled": true
+ },
+ "tag": "http_proxy" // 名称为"http_proxy"的入站节点由 winXray 自动维护并添加用户配置
+ }
+ ],
+ "log": {
+ "access": "",
+ "error": "",
+ "loglevel": "warning"
+ },
+ "outbounds": [
+ {
+ "tag": "proxy" // 名称为"proxy"的节点由 winXray 自动维护并添加用户配置
+ },
+ {
+ "protocol": "freedom",
+ "settings": {},
+ "tag": "direct"
+ },
+ {
+ "protocol": "blackhole",
+ "settings": {
+ "response": {
+ "type": "http"
+ }
+ },
+ "tag": "block"
+ }
+ ],
+ "routing": {
+ "domainStrategy": "IPIfNonMatch",
+ "rules": [
+ {
+ "inboundTag": [
+ "api"
+ ],
+ "outboundTag": "api",
+ "type": "field"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/forms/main/config/coreConfigs/v2ray.rules.json b/forms/main/config/coreConfigs/v2ray.rules.json
new file mode 100644
index 0000000..a9a301e
--- /dev/null
+++ b/forms/main/config/coreConfigs/v2ray.rules.json
@@ -0,0 +1,164 @@
+{
+ "inbounds": [ // 入站节点,也就是本地代理端口配置
+ {
+ "listen": "127.0.0.1", // 本机监听IP,允许局域网时需要设为 "0.0.0,0"
+ "port": 1081, // 本机 SOCKS 代理端口,设为 0 时由 winXray 重置为合适的默认端口
+ "protocol": "socks", // 入站代理协议
+ "settings": {
+ "auth": "noauth",
+ "udp": true
+ },
+ "sniffing": {
+ "destOverride": [
+ "http",
+ "tls"
+ ],
+ "enabled": true
+ },
+ "tag": "proxy" // 名称为"proxy"的节点由 winXray 自动维护并添加用户配置
+ },
+ {
+ "listen": "127.0.0.1",
+ "port": 1082,
+ "protocol": "http",
+ "settings": {},
+ "sniffing": {
+ "destOverride": [
+ "http",
+ "tls"
+ ],
+ "enabled": true
+ },
+ "tag": "http_proxy" // 名称为"http_proxy"的入站节点由 winXray 自动维护并添加用户配置
+ }
+ ],
+ "log": {
+ "access": "",
+ "error": "",
+ "loglevel": "warning"
+ },
+ "outbounds": [
+ {
+ "tag": "proxy" // 作为第一个节点表示默认走代理,名称为"proxy"的节点由 winXray 自动维护并添加用户配置
+ },
+ {
+ "protocol": "dns",
+ "tag": "Dns-Out"
+ },
+ {
+ "protocol": "freedom", // 直连出站节点
+ "tag": "Direct", // 如果移动到第一个节点表示默认走直连
+ "settings": {
+ "domainStrategy": "UseIPv4"
+ }
+ },
+ {
+ "protocol": "blackhole",
+ "tag": "Reject",
+ "settings": {
+ "response": {
+ "type": "http"
+ }
+ }
+ }
+ ],
+ "dns": {
+ "hosts": {
+ "dns.google": "8.8.8.8",
+ "doh.pub": "119.29.29.29"
+ },
+ "servers": [
+ "https://dns.google/dns-query",
+ {
+ "address": "https+local://223.5.5.5/dns-query",
+ "domains": [
+ "geosite:cn",
+ "geosite:icloud"
+ ],
+ "expectIPs": [
+ "geoip:cn"
+ ]
+ },
+ {
+ "address": "https://1.1.1.1/dns-query",
+ "domains": [
+ "geosite:geolocation-!cn"
+ ]
+ }
+ ]
+ },
+ "routing": {
+ "domainStrategy": "IPIfNonMatch",
+ "rules": [
+ {
+ "type": "field",
+ "outboundTag": "Direct",
+ "protocol": [
+ "bittorrent"
+ ]
+ },
+ {
+ "type": "field",
+ "outboundTag": "Dns-Out",
+ "inboundTag": [
+ "Socks-In",
+ "Http-In"
+ ],
+ "network": "udp",
+ "port": 53
+ },
+ {
+ "type": "field",
+ "outboundTag": "Reject",
+ "domain": [
+ "geosite:category-ads-all",
+ "geosite:win-spy"
+ ]
+ },
+ {
+ "type": "field",
+ "outboundTag": "proxy",
+ "domain": [
+ "full:www.icloud.com",
+ "domain:icloud-content.com"
+ ]
+ },
+ {
+ "type": "field",
+ "outboundTag": "Direct",
+ "domain": [
+ "geosite:tld-cn",
+ "geosite:icloud"
+ ]
+ },
+ {
+ "type": "field",
+ "outboundTag": "proxy",
+ "domain": [
+ "geosite:geolocation-!cn"
+ ]
+ },
+ {
+ "type": "field",
+ "outboundTag": "Direct",
+ "domain": [
+ "geosite:cn",
+ "geosite:private"
+ ]
+ },
+ {
+ "type": "field",
+ "outboundTag": "Direct",
+ "ip": [
+ "geoip:cn",
+ "geoip:private"
+ ]
+ },
+ {
+ "type": "field",
+ "outboundTag": "proxy",
+ "network": "tcp,udp"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/forms/main/config/jsonConfig.aardio b/forms/main/config/jsonConfig.aardio
new file mode 100644
index 0000000..0873209
--- /dev/null
+++ b/forms/main/config/jsonConfig.aardio
@@ -0,0 +1,771 @@
+import fonts.fontAwesome;
+import win.ui;
+/*DSG{{*/
+var winform = win.form(text="aardio form";right=938;bottom=638;bgcolor=16777215)
+winform.add(
+advancedConfig={cls="\forms\main\config\advancedConfig.aardio";left=9;top=20;right=930;bottom=594;bgcolor=16777215;db=1;dl=1;dr=1;dt=1;edge=1;z=12};
+btnUpdate={cls="plus";text="更新服务器配置";left=699;top=604;right=868;bottom=635;align="left";bgcolor=11580047;db=1;dr=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=22}};iconText='\uF0C7';notify=1;textPadding={left=40};z=6};
+btnUpdateNaiveCore={cls="plus";text="下载 / 更新 NaÏveProxy Core";left=448;top=7;right=709;bottom=35;align="left";color=3947580;dl=1;dt=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-17;name='FontAwesome');padding={left=18}};iconText='\uF1A0';notify=1;textPadding={left=50};z=17};
+btnUpdateRules={cls="plus";text="下载 / 更新 路由规则";left=227;top=39;right=425;bottom=67;align="left";color=3947580;dl=1;dt=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-19;name='FontAwesome');padding={left=18}};iconText='\uF041';notify=1;textPadding={left=50};z=15};
+btnUpdateSsrCore={cls="plus";text="下载 / 更新 SSR Core";left=16;top=39;right=214;bottom=67;align="left";color=3947580;dl=1;dt=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-17;name='FontAwesome');padding={left=18}};iconText='\uF1D8';notify=1;textPadding={left=50};z=16};
+btnUpdateV2RayCore={cls="plus";text="下载 / 更新 V2Ray Core";left=16;top=5;right=223;bottom=33;align="left";color=3947580;dl=1;dt=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-19;name='FontAwesome');padding={left=18}};iconText='\uF27D';notify=1;textPadding={left=50};z=13};
+btnUpdateXrayCore={cls="plus";text="下载 / 更新 Xray Core";left=227;top=5;right=425;bottom=33;align="left";color=3947580;dl=1;dt=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-19;name='FontAwesome');padding={left=18}};iconText='\uF0E7';notify=1;textPadding={left=50};z=14};
+editCoreConfig={cls="edit";left=9;top=72;right=930;bottom=594;db=1;dl=1;dr=1;dt=1;edge=1;hide=1;hscroll=1;multiline=1;vscroll=1;z=7};
+editOutbounds={cls="edit";left=9;top=29;right=930;bottom=594;db=1;dl=1;dr=1;dt=1;edge=1;hscroll=1;multiline=1;vscroll=1;z=8};
+lbTip={cls="static";text="可在下面输入多行服务器分享链接,或JSON数组( 点击字段名会显示用法说明 ):";left=11;top=9;right=899;bottom=29;color=3947580;dl=1;dr=1;dt=1;font=LOGFONT(h=-13);transparent=1;z=9};
+lbTipForCoreJson={cls="static";text="tag 指定为 proxy,http_proxy 的节点属于自动维护节点 - 不可删除";left=468;top=45;right=849;bottom=68;color=4964352;dl=1;dt=1;transparent=1;z=19};
+navAdvancedConfig={cls="plus";text="代理端口 / 高级配置";left=359;top=600;right=493;bottom=632;border={top=1;color=-16744448};db=1;dl=1;z=10};
+navCoreConfig={cls="plus";text="Core 配置 ( JSON )";left=162;top=600;right=293;bottom=632;border={top=1;color=-16744448};db=1;dl=1;z=3};
+navOutbounds={cls="plus";text="服务器配置( JSON )";left=31;top=600;right=162;bottom=632;border={top=1;color=-16744448};db=1;dl=1;z=2};
+navRight={cls="plus";left=493;top=600;right=762;bottom=601;bgcolor=16777215;border={top=1;color=-16744448};db=1;dl=1;dr=1;linearGradient=180;z=4};
+navSubscription={cls="plus";text="订阅";left=293;top=600;right=359;bottom=632;border={top=1;color=-16744448};db=1;dl=1;z=11};
+navUwpExemption={cls="plus";text="UWP 应用配置";left=499;top=600;right=633;bottom=632;border={top=1;color=-16744448};db=1;dl=1;notify=1;z=18};
+plus={cls="plus";left=9;top=600;right=31;bottom=601;border={top=1;color=-16744448};db=1;dl=1;z=5};
+subscription={cls="\forms\main\config\subscription.aardio";left=9;top=19;right=930;bottom=594;bgcolor=16777215;db=1;dl=1;dr=1;dt=1;edge=1;z=1}
+)
+/*}}*/
+
+import config;
+import web.json;
+import win.ui.tabs;
+var tbs = win.ui.tabs(winform.navOutbounds,winform.navCoreConfig,winform.navSubscription,winform.navAdvancedConfig);
+tbs.margin = 0;
+
+tbs.skin({
+ foreground={
+ active=0xFFFFFFFF;
+ default=0x00FFFFFF;
+ hover=0xFFCCCCCC;
+ };
+ checked={
+ foreground={
+ default=0x00FFFFFF;
+ };
+ border = {
+ default = {left=1;right=1;bottom=1;color=0xFF008000}
+ };
+ }
+});
+
+tbs.onSelchange = function(idx,strip,form){
+ winform.btnUpdateSsrCore.hide = idx!=2;
+ winform.btnUpdateV2RayCore.hide = idx!=2;
+ winform.btnUpdateXrayCore.hide = idx!=2;
+ winform.btnUpdateRules.hide = idx!=2;
+ winform.btnUpdateNaiveCore.hide = idx!=2;
+ winform.editCoreConfig.hide = idx!=2;
+ winform.editOutbounds.hide = idx!=1;
+ winform.subscription.hide = idx!=3;
+ winform.advancedConfig.hide = idx!=4;
+ winform.btnUpdate.hide = idx>2;
+ winform.lbTip.hide = idx!=1;
+ winform.lbTipForCoreJson.hide = true;
+
+ if(idx==1){
+ winform.btnUpdate.text = "更新服务器配置";
+ }
+ elseif(idx==2) {
+ winform.btnUpdate.text = "更新内核配置 "
+ }
+ elseif(idx==3) {
+ winform.subscription.loadSubscriptionsOnce();
+ }
+}
+tbs.selIndex = 1;
+
+import style;
+winform.btnUpdate.skin(style.primaryButton);
+winform.btnUpdate.oncommand = function(id,event){
+ winform.btnUpdate.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'};
+
+ if(tbs.selIndex==1){
+ if(..string.match(winform.editOutbounds.text,"%\[\]")){
+ var cfg,err = web.json.tryParse(winform.editOutbounds.text);
+ if(!cfg){
+ winform.editOutbounds.showErrorTip(,string.concat("JSON语法错误 ",err));
+ winform.btnUpdate.disabledText = null;
+ return;
+ }
+
+ if(cfg){
+ cfg = v2ray.outbounds.validAll(cfg)
+ }
+ config.proxy.outbounds = cfg : ..table.array();
+ }
+ else {
+ var outbounds = v2ray.outbounds.importFromString(winform.editOutbounds.text);
+ config.proxy.outbounds = outbounds : ..table.array();
+ winform.editOutbounds.text = web.json.stringifyArray(outbounds,true,false,true);
+ }
+
+ config.proxy.save();
+ winform.editOutbounds.modified = false;
+ publish("uiCommand.restartV2RayCore",cfg)
+ }
+ elseif(tbs.selIndex==2) {
+ var cfg,err = web.json.tryParse(winform.editCoreConfig.text);
+ if(type(cfg)!==type.table){
+ winform.editCoreConfig.showErrorTip(,string.concat("JSON语法错误 ",err));
+ winform.btnUpdate.disabledText = null;
+ return;
+ }
+
+ var proxyOutboundInCore;
+ for(k,ob in cfg.outbounds){
+ if(ob.tag == "proxy"){
+ proxyOutboundInCore = ob;
+ }
+ }
+
+ if( type(proxyOutboundInCore) !="table" ){
+ winform.msgErr(`outbounds 数组中未找到默认出站节点 {tag:"proxy"}`);
+ winform.btnUpdate.disabledText = null;
+ return;
+ }
+
+ var socksInbounds,httpInbounds;
+ for(k,ib in cfg.inbounds){
+ if(ib.tag == "proxy"){
+ socksInbounds = ib;
+ }
+ elseif(ib.tag == "http_proxy"){
+ httpInbounds = ib;
+ }
+ }
+
+ if( type(socksInbounds) !="table" ){
+ winform.msgErr(`inbounds 数组中未找到SOCKS协议入站节点 {tag:"proxy"}`);
+ winform.btnUpdate.disabledText = null;
+ return;
+ }
+
+ if( type(httpInbounds) !="table" ){
+ winform.msgErr(`inbounds 数组中未找到HTTP协议入站节点 {tag:"http_proxy"}`);
+ winform.btnUpdate.disabledText = null;
+ return;
+ }
+
+ if(type(socksInbounds[["listen"]])!="string"){
+ winform.msgErr(`出站节点 {tag:"proxy"} listen字段必须指定IP或0.0.0.0`);
+ winform.btnUpdate.disabledText = null;
+ return;
+ }
+
+ if(type(socksInbounds[["port"]])!="number"){
+ winform.msgErr(`出站节点 {tag:"proxy"} port字段必须用数值指定监听端口`);
+ winform.btnUpdate.disabledText = null;
+ return;
+ }
+
+ if(type(httpInbounds[["listen"]])!="string"){
+ winform.msgErr(`出站节点 {tag:"http_proxy"} listen字段必须指定IP或0.0.0.0`);
+ winform.btnUpdate.disabledText = null;
+ return;
+ }
+
+ if(type(httpInbounds[["port"]])!="number"){
+ winform.msgErr(`出站节点 {tag:"http_proxy"} port字段必须用数值指定监听端口`);
+ winform.btnUpdate.disabledText = null;
+ return;
+ }
+
+ config.core.default = cfg;
+ config.core.save();
+
+ publish("uiCommand.restartV2RayCore",cfg);
+ publish("config.core.changed");
+ }
+
+ win.delay(500);
+ winform.btnUpdate.disabledText = null;
+ winform.msgOk("配置已更新",1200);
+}
+
+
+import v2ray.outbounds;
+winform.editOutbounds.enablePopMenu(function(){
+ if(tbs.selIndex==1){
+ var strEditBounds = string.trim(winform.editOutbounds.text);
+ var menu = {
+ { /*---分隔线---*/ };
+ { "自剪贴板导入 vmess/vless/trojan/ss 链接或订阅源";
+ function(id){
+
+ var outbounds = v2ray.outbounds.importFromClipboard();
+ if(#outbounds){
+ var json = strEditBounds;
+ if( (!#json) || ..string.match(json,"%\[\]")){
+ var cfgOutbounds,err = ..table.array();
+ if(#json){
+ cfgOutbounds,err= web.json.tryParse(strEditBounds);
+ if(!cfgOutbounds){
+ winform.editOutbounds.showErrorTip(,string.concat("当前配置存在JSON语法错误 ",err));
+ return;
+ }
+ }
+
+ var subscribeUrl = outbounds[1].subscribeUrl;
+ if(subscribeUrl){
+ for(i=#cfgOutbounds;1;-1){
+ var outbound = cfgOutbounds[i]
+ if(outbound.subscribeUrl==url){
+ ..table.remove( cfgOutbounds,i );
+ }
+ }
+ }
+
+ ..table.append(cfgOutbounds,outbounds);
+ winform.editOutbounds.text = ..web.json.stringifyArray(cfgOutbounds,true,false,true);
+ }
+ else {
+ var str = v2ray.outbounds.exportSharedLinks(outbounds);
+ if(#strEditBounds){
+ winform.editOutbounds.text = strEditBounds+ '\r\n' + str;
+ }
+ else {
+ winform.editOutbounds.text = str;
+ }
+ }
+
+ winform.msgOk("已成功导入" + #outbounds + "个服务器,请点击「更新设置」启用新配置。",1200);
+ winform.editOutbounds.modified = true;
+ winform.editOutbounds.setFocus();
+ return;
+ }
+
+ winform.msgFrown('未导入服务器!\r\n请先复制以下格式文本(自动清除其中的无效内容):\r\n\r\n1、一行或多行(忽略无效行)分享链接或服务器JSON配置。\r\n支持 vmess://,vless://,ss://,ssr://,trojan://, trojan-go:// 等通用分享链接。\r\n\r\n2、包含多个服务器配置的JSON数组。\r\n\r\n3、单个 http:// 或 https:// 开头的通用订阅源地址。\r\n订阅源地址支持直接使用github项目文件地址(网址含raw或blob目录名)。\r\n订阅源可以BASE64编码或明文返回以上1、2条规定的配置或分享链接。')
+ }
+ };
+ }
+
+ if( (!#strEditBounds) || ..string.match(strEditBounds,"%\[\]")){
+ menu[3] = { "更新当前配置内订阅源";
+ function(id){
+ var cfg,err = ..table.array();
+
+ var json = strEditBounds;
+ if(#json){
+ cfg,err = web.json.tryParse(strEditBounds);
+ if(!cfg){
+ winform.editOutbounds.showErrorTip(,string.concat("JSON语法错误 ",err));
+ return;
+ }
+ }
+
+ var subscribeUrls = {}
+ for(i=#cfg;1;-1){
+ var outbound = cfg[i]
+ if(outbound.subscribeUrl){
+ subscribeUrls[outbound.subscribeUrl] = true;
+ }
+ }
+
+ if(!table.count(subscribeUrls)){
+ import win.clip;
+ var clibStr = win.clip.read();
+ if( ..string.startWith(clibStr,"http://") || ..string.startWith(clibStr,"https://") ){
+ subscribeUrls[clibStr] = true;
+ }
+ else {
+ winform.msgWarn('当前配置不包含来自订阅源的服务器,\n请先复制订阅源网址到剪贴板!');
+ return;
+ }
+ }
+
+ var count = 0;
+ for(url,v in subscribeUrls){
+ var outbounds = v2ray.outbounds.importFromString(url);
+ if(#outbounds){
+ for(i=#cfg;1;-1){
+ var outbound = cfg[i]
+ if(outbound.subscribeUrl==url){
+ ..table.remove( cfg,i );
+ }
+ }
+
+ count = count + #outbounds;
+ ..table.append(cfg,outbounds);
+ }
+ }
+
+ winform.editOutbounds.text = ..web.json.stringifyArray(cfg,true,false,true);
+
+ winform.msgOk("已成功刷新" + count + "个服务器,请点击「更新设置」启用新配置。",1200);
+ winform.editOutbounds.modified = true;
+ winform.editOutbounds.setFocus();
+ return;
+ }
+ };
+ }
+
+ if(..string.match(strEditBounds,"%\[\]")){
+ menu[4] = {}
+ menu[5] = { "转换为 vmess、vless、trojan、trojan-go、ss 分享链接";
+ function(id){
+ var cfgOutbouds,err = web.json.tryParse(strEditBounds);
+ if(!cfgOutbouds){
+ winform.editOutbounds.showErrorTip(,string.concat("JSON语法错误 ",err));
+ return;
+ }
+
+ for(i,ob in cfgOutbouds){
+ if(ob.subscribeUrl){
+ if(!winform.msgAsk('当前配置包含订阅源,\n转换为分享链接所有服务器与订阅源将解除关联,\n按确定继续操作,按取消中止。')){
+ return;
+ }
+
+ break;
+ }
+ }
+
+ var str = v2ray.outbounds.exportSharedLinks(cfgOutbouds);
+ if(str){
+ winform.editOutbounds.text = str;
+ winform.editOutbounds.modified = true;
+ }
+ }
+ };
+ menu[6] = { "转换为 Base64 订阅源";
+ function(id){
+ var cfg,err = web.json.tryParse(strEditBounds);
+ if(!cfg){
+ winform.editOutbounds.showErrorTip(,string.concat("JSON语法错误 ",err));
+ return;
+ }
+
+ var str = v2ray.outbounds.exportSharedLinks(cfg);
+ if(str){
+ import crypt;
+ winform.editOutbounds.text = ..crypt.encodeBin(str);
+ winform.editOutbounds.modified = true;
+ }
+ }
+ };
+ }
+ elseif( #strEditBounds ) {
+ menu[3] = {}
+
+ menu[4] = { "转换为 JSON";
+ function(id){
+ import web.json;
+ var outbounds = v2ray.outbounds.importFromString(strEditBounds);
+ if(outbounds){
+ winform.editOutbounds.text = web.json.stringifyArray(outbounds,true,false,true);
+ winform.editOutbounds.modified = true;
+ }
+ }
+ };
+ }
+
+ table.push(menu,{ /*---分隔线---*/ });
+
+ table.push(menu,{ "打开配置文件(JSON)";
+ function(id){
+ import fsys.dlg;
+ var path = fsys.dlg.open("*.json|*.json||","打开 json 文件",,winform)
+ if(path){
+ winform.editOutbounds.text = string.load(path);
+ winform.editOutbounds.modified = true;
+ }
+ }
+ });
+
+ table.push(menu,{ "另存为配置文件(JSON)";
+ function(id){
+ import fsys.dlg;
+ var path = fsys.dlg.save("*.json|*.json||","另存为 json 文件",,winform)
+ if(path){
+ var str = web.json.stringifyArray(
+ config.proxy.outbounds,true,false,true
+ )
+
+ string.save(path,str )
+ }
+ }
+ });
+
+ table.push(menu,{ "另存为默认服务器列表(JSON)";
+ function(id){
+ var str = web.json.stringifyArray(
+ config.proxy.outbounds,true,false,true
+ )
+
+ string.save("/v2ray-core/winXray-default-servers.json",str );
+ winform.msgOk("已存为默认服务器列表 /v2ray-core/winXray-default-servers.json",1000)
+ }
+ });
+
+ table.push(menu,{ /*---分隔线---*/ });
+ if(winform.editOutbounds.modified){
+ table.push(menu,{ "恢复为当前使用的服务器列表(JSON)";
+ function(id){
+ winform.btnUpdate.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'}
+ winform.editOutbounds.text = web.json.stringifyArray(
+ config.proxy.outbounds,true,false,true
+ )
+ winform.editOutbounds.modified = false;
+
+ win.delay(500);
+ winform.btnUpdate.disabledText = null;
+ }
+ });
+ }
+
+ table.push(menu,{ "重置为默认服务器列表(JSON)";
+ function(id){
+ winform.btnUpdate.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'}
+ ..config.__loadDefaultOutbounds();
+ winform.editOutbounds.modified = false;
+ publish("uiCommand.restartV2RayCore",cfg);
+
+ winform.btnUpdate.disabledText = null;
+ }
+ });
+
+ table.push(menu,{ "清空服务器列表";
+ function(id){
+ winform.editOutbounds.text = "[]";
+ winform.editOutbounds.modified = true;
+ }
+ });
+
+ if( ..string.match(winform.editOutbounds.text,"%\[\]")){
+
+ table.push(menu,{ /*---分隔线---*/ });
+ table.push(menu,{ "插入配置字段";{
+ { "代理服务协议:protocol";
+ function(id){
+ winform.editOutbounds.selText = '"protocol":"vless",'
+ }
+ };
+ { "SSH管理端口:sshPort";
+ function(id){
+ winform.editOutbounds.selText = '"sshPort":22,'
+ }
+ };
+ { "代理服务器地址:address";
+ function(id){
+ winform.editOutbounds.selText = '"address":"",'
+ }
+ };
+ { "端口:port";
+ function(id){
+ winform.editOutbounds.selText = '"port":443,'
+ }
+ };
+ { "网络协议:network";
+ function(id){
+ winform.editOutbounds.selText = '"network":"tcp",'
+ }
+ };
+ { "服务器密码:id";
+ function(id){
+ winform.editOutbounds.selText = '"id":"",'
+ }
+ };
+ { "加密方式:security";
+ function(id){
+ winform.editOutbounds.selText = '"security":"auto",'
+ }
+ };
+ { "允许忽略证书:allowInsecure";
+ function(id){
+ winform.editOutbounds.selText = '"allowInsecure":true,'
+ }
+ };
+ { "TLS服务器名:sni";
+ function(id){
+ winform.editOutbounds.selText = '"sni":"",'
+ }
+ };
+ { "启用TLS:tls";
+ function(id){
+ winform.editOutbounds.selText = '"tls":"tls",'
+ }
+ };
+ { "流控:flow";
+ function(id){
+ winform.editOutbounds.selText = '"flow":"xtls-rprx-direct",'
+ }
+ };
+ { "多路复用最大连接:concurrency";
+ function(id){
+ winform.editOutbounds.selText = '"concurrency":4,'
+ }
+ };
+
+ { "伪装类型:type";
+ function(id){
+ winform.editOutbounds.selText = '"type":"http",'
+ }
+ };
+ { "备注:ps";
+ function(id){
+ winform.editOutbounds.selText = '"ps":"",'
+ }
+ };
+ { "请求主机名:host";
+ function(id){
+ winform.editOutbounds.selText = '"host":"",'
+ }
+ };
+ { "请求路径:path";
+ function(id){
+ winform.editOutbounds.selText = '"path":"/",'
+ }
+ };
+ { "HTTP请求方法:httpMethod";
+ function(id){
+ winform.editOutbounds.selText = '"httpMethod":"GET",'
+ }
+ };
+ { "HTTP请求头:headers";
+ function(id){
+ winform.editOutbounds.selText = '"headers":{"method":"GET"},'
+ }
+ };
+ { "绑定的订阅网址:subscribeUrl";
+ function(id){
+ winform.editOutbounds.selText = '"subscribeUrl":"https://",'
+ }
+ };
+ { "允许自动测试并连接:autoConnect";
+ function(id){
+ winform.editOutbounds.selText = '"autoConnect":false,'
+ }
+ };
+ { "备注:ps";
+ function(id){
+ winform.editOutbounds.selText = '"ps":"",'
+ }
+ };
+ }});
+ }
+
+ return menu;
+ }
+})
+
+winform.editCoreConfig.enablePopMenu({
+ { /*---分隔线---*/ };
+ { "重置为默认内核配置";
+ function(id){
+ winform.editCoreConfig.text = string.crlf( string.load("\forms\main\config\coreConfigs\default.json") )
+ winform.editCoreConfig.msgOk('已重置为默认内核配置。\n请在下面点击:『更新内核配置』启用新的配置。',1300)
+ }
+ };
+ { "重置为启用路由规则默认内核配置";
+ function(id){
+ winform.editCoreConfig.text = string.crlf( string.load("\forms\main\config\coreConfigs\v2ray.rules.json") )
+ import v2ray.core.rules;
+ var versionTag = v2ray.core.rules.check();
+ if(versionTag) winform.editCoreConfig.msgOk('已重置为启用路由规则默认内核配置,\n已下载路由规则数据最新版本:' + versionTag+ '\n\n请在下面点击:『更新内核配置』启用新的配置。',2000)
+ else winform.msgOk('已重置为启用路由规则默认内核配置,\n请在下面点击:『更新内核配置』启用新的配置。',1300)
+ }
+ };
+ { "恢复到当前正在使用的内核配置";
+ function(id){
+ winform.editCoreConfig.text = web.json.stringify(
+ config.core.default,true
+ )
+
+ winform.editCoreConfig.msgOk('已恢复到当前正在使用的内核配置',1300)
+ }
+ };
+} )
+
+subscribe("outbounds.updateConfigJson",function(){
+ if(winform.editOutbounds.modified){
+ return;
+ }
+
+ winform.editOutbounds.text = web.json.stringifyArray(
+ config.proxy.outbounds,true,false,true
+ )
+
+ winform.editOutbounds.modified = false;
+} )
+
+winform.editOutbounds.text = web.json.stringifyArray(
+ config.proxy.outbounds,true,false,true
+) : "[]"
+winform.editOutbounds.modified = false;
+
+subscribe("config.inbounds.changed",function(){
+ if(winform.editCoreConfig.modified){
+ return;
+ }
+
+ winform.editCoreConfig.text = web.json.stringify(
+ config.core.default,true
+ )
+
+ winform.editCoreConfig.modified = false;
+} )
+winform.editCoreConfig.text = web.json.stringify(
+ config.core.default,true
+)
+
+var editOutboundsTip = {
+ address = {"代理服务器地址";"值可以是域名或者IP地址"};
+ alterId = {"额外ID";"仅用于VMESS协议,与服务器一致即可"};
+ aid = {"额外ID(alterId)";"数值,仅用于VMESS协议,与服务器一致即可"};
+ network = {"传输协议(network)";"可选值为tcp,ws等,也可以放 SSR 的 protocol 值"};
+ net = {"传输协议(network)";"可选值为tcp,ws等"};
+ type = {"伪装类型";"默认的可选值为none,http等,kcp或quic此字段表示header.type,可选值为 none,srtp,utp,wechat-video,dtls,wireguard"};
+ ps = {"备注";"备注"};
+ tls = {"是否启用TLS";"可选值为tls,xtls或空值,vless协议省略时默认值为tls"};
+ path = {"请求路径";"用于ws,http等协议指定请求路径"};
+ httpMethod = {"HTTP请求方法";"用于http协议指定请求方法"};
+ headers = {"HTTP请求头";"用于ws,http等协议指定请求头"};
+ id = {"密码";"服务器密码"};
+ host = {"主机名";"用于指定http,ws等协议请求头中的主机名"};
+ protocol = {"协议";"可选值为 vmess,vless,shadowsocks,trojan,trojan-go 之一"};
+ port = {"端口";"服务器端口,数值"};
+ security = {"加密方式";"可省略,vmess协议默认为auto,vless协议默认为none"};
+ sni = {"TLS服务器名";"TLS客户端请求中的服务器名字段,如果不指定则默认取host或address字段值。"};
+ flow = {"流控";"目前仅用于选择 XTLS 的算法,省略时默认值为xtls-rprx-direct"};
+ obfs = {"混淆插件";"可选值:plain,http_simple,http_post,tls1.2_ticket_auth ..."};
+ obfsParam = {"混淆参数";"SSR 里的 obfs_param"};
+ networkParam = {"SSR网络协议参数";"SSR 里的 protocol_param"};
+ concurrency = {"Mux多路复用:最大并发连接数";"最小值1,最大值1024,特殊值-1,不加载mux模块。缺省由winXray根据连接协议自动设定此值。"};
+}
+
+winform.editOutbounds.wndproc = function(hwnd,message,wParam,lParam){
+ if(message == 0x202/*_WM_LBUTTONUP*/){
+ var lineIndex = winform.editOutbounds.lineFromChar();
+ if(lineIndex == winform.editOutbounds.preLineIndex){
+ return;
+ }
+ winform.editOutbounds.preLineIndex = lineIndex;
+
+ var line = winform.editOutbounds.lineText();
+ var n,v = string.match(line,`^\s*\"(\w+)\"\s*\:\s*(%"")[\,\s]*$`);
+ if( !n ) n,v = string.match(line,`^\s*\"(\w+)\"\s*\:\s*(\d+)[\,\s]*$`);
+ if( !n ) n,v = string.match(line,`^\s*\"(\w+)\"\s*\:\s*\{`);
+ if(editOutboundsTip[n]){
+ winform.editOutbounds.showInfoTip(editOutboundsTip[n][1],editOutboundsTip[n][2])
+ }
+ }
+}
+
+winform.editCoreConfig.oncommand = function(id,event){
+ if( event === 0x100/*_EN_SETFOCUS*/){
+ winform.lbTipForCoreJson.hide = false;
+ }
+}
+
+winform.editOutbounds.limit = 0;
+winform.editCoreConfig.limit = 0;
+
+winform.btnUpdateSsrCore.skin(style.plainButton)
+winform.btnUpdateSsrCore.oncommand = function(id,event){
+ winform.btnUpdateSsrCore.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'};
+
+ import v2ray.core.ssr;
+ var versionTag = v2ray.core.ssr.updateCore();
+ if( versionTag ){
+ publish("uiCommand.restartV2RayCore");
+ winform.btnUpdateSsrCore.disabledText = null;
+ winform.msgOk("SSR Core( ShadowsocksR-native ) 已更新到:" + versionTag,1500)
+ }
+ else {
+ winform.btnUpdateSsrCore.disabledText = null;
+ }
+}
+
+winform.btnUpdateV2RayCore.skin(style.plainButton)
+winform.btnUpdateV2RayCore.oncommand = function(id,event){
+ winform.btnUpdateXrayCore.disabled = true;
+ winform.btnUpdateV2RayCore.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'};
+
+ import v2ray.core;
+ var versionTag = v2ray.core.updateCore();
+ if( versionTag ){
+ publish("uiCommand.restartV2RayCore");
+ winform.btnUpdateV2RayCore.disabledText = null;
+ winform.msgOk("已下载最新 V2Ray Core 版本:" + versionTag + '\nV2Ray 内核已切换为: V2Ray Core',1500)
+ }
+ else {
+ winform.btnUpdateV2RayCore.disabledText = null;
+ winform.msgErr("V2Ray Core 下载失败!");
+ }
+
+ winform.btnUpdateXrayCore.disabled = false;
+}
+
+winform.btnUpdateXrayCore.skin(style.plainButton)
+winform.btnUpdateXrayCore.oncommand = function(id,event){
+
+ winform.btnUpdateV2RayCore.disabled = true;
+ winform.btnUpdateXrayCore.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'};
+
+ import v2ray.core.xray;
+ var versionTag = v2ray.core.xray.updateCore();
+ if( versionTag ){
+ publish("uiCommand.restartV2RayCore");
+ winform.btnUpdateXrayCore.disabledText = null;
+ winform.msgOk("已下载最新 XRay Core 版本:" + versionTag+ '\nV2Ray 内核已切换为:XRay Core',1500)
+ }
+ else {
+ winform.btnUpdateXrayCore.disabledText = null;
+ winform.msgErr("XRay Core 下载失败!");
+ }
+
+ winform.btnUpdateV2RayCore.disabled = false;
+}
+
+winform.btnUpdateRules.skin(style.plainButton)
+winform.btnUpdateRules.oncommand = function(id,event){
+
+ winform.btnUpdateRules.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'};
+
+ import v2ray.core.rules;
+ var versionTag = v2ray.core.rules.update();
+ if( versionTag ){
+ publish("uiCommand.restartV2RayCore");
+ winform.btnUpdateRules.disabledText = null;
+ winform.msgOk('已下载路由规则到最新版本:' + versionTag+ '\n请在下面的配置编辑器点击右键,然后点击:\n『重置为启用路由规则默认内核配置』',2000)
+ }
+ else {
+ winform.btnUpdateRules.disabledText = null;
+ winform.msgErr("路由规则下载失败!");
+ }
+}
+
+winform.btnUpdateNaiveCore.skin(style.plainButton)
+winform.btnUpdateNaiveCore.oncommand = function(id,event){
+ winform.btnUpdateNaiveCore.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'};
+
+ import v2ray.core.naive;
+ var versionTag = v2ray.core.naive.updateCore();
+ if( versionTag ){
+ publish("uiCommand.restartV2RayCore");
+ winform.btnUpdateNaiveCore.disabledText = null;
+ winform.msgOk("NaÏveProxy Core 已更新到:" + versionTag,1500)
+ }
+ else {
+ winform.btnUpdateNaiveCore.disabledText = null;
+ winform.msgErr("NaÏveProxy Core 下载失败!");
+ }
+}
+
+if(!_WIN10_LATER){
+ winform.navUwpExemption.close();
+}
+else {
+ winform.navUwpExemption.skin(style.plainButton)
+ winform.navUwpExemption.oncommand = function( id,event ){
+ if(_STUDIO_INVOKED){
+ winform.msgErr("请先发布为 EXE!");
+ return;
+ }
+
+ import process;
+ process.execute(io._exepath,"/uwp","runas")
+ }
+}
+
+winform.show();
+win.loopMessage();
+return winform;
\ No newline at end of file
diff --git a/forms/main/config/subscription.aardio b/forms/main/config/subscription.aardio
new file mode 100644
index 0000000..2318224
--- /dev/null
+++ b/forms/main/config/subscription.aardio
@@ -0,0 +1,308 @@
+import fonts.fontAwesome;
+import win.ui;
+/*DSG{{*/
+var winform = win.form(text="aardio form";right=892;bottom=564;bgcolor=16777215)
+winform.add(
+btnAdd={cls="plus";text="添加订阅";left=10;top=4;right=143;bottom=31;align="left";dl=1;dt=1;font=LOGFONT(h=-15);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=12}};iconText='\uF196 ';notify=1;textPadding={left=30};z=5};
+btnRemove={cls="plus";text="移除选中订阅";left=143;top=4;right=276;bottom=31;align="left";dl=1;dt=1;font=LOGFONT(h=-15);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=12}};iconText='\uF014';notify=1;textPadding={left=30};z=6};
+btnUpdate={cls="plus";text="更新订阅";left=608;top=506;right=730;bottom=542;align="left";bgcolor=11580047;db=1;dr=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=22}};iconText='\uF0C7';notify=1;textPadding={left=40};z=1};
+chkAll={cls="plus";text="全部启用";left=11;top=489;right=118;bottom=520;align="left";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-16;name='FontAwesome')};iconText='\uF0C8';notify=1;textPadding={left=19};z=3};
+chkAutoRefreshSubscription={cls="plus";text="允许出站服务器异常自动刷新订阅";left=11;top=524;right=527;bottom=555;align="left";bgcolor=16777215;db=1;dl=1;dr=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-16;name='FontAwesome')};iconText='\uF0C8';notify=1;textPadding={left=19};z=2};
+listview={cls="listview";left=10;top=36;right=883;bottom=477;db=1;dl=1;dr=1;dt=1;edge=1;fullRow=1;gridLines=1;z=4};
+static={cls="static";text="双击上面单元格可直接编辑";left=710;top=616;right=867;bottom=634;color=10789024;db=1;dr=1;transparent=1;z=7}
+)
+/*}}*/
+
+import style;
+winform.chkAutoRefreshSubscription.skin(style.checkBox);
+winform.chkAll.skin(style.checkBox);
+winform.btnAdd.skin(style.plainButton);
+
+winform.listview.insertColumn("",20)
+winform.listview.insertColumn("状态",50)
+winform.listview.insertColumn("备注",150)
+winform.listview.insertColumn("订阅地址",-1)
+winform.listview.checkbox = true;
+winform.listview.gridLines = 0;
+
+import win.ui.grid;
+var grid = win.ui.grid(winform.listview);//创建数据视图
+grid.readonlyColums = { [1] = true;[2] = true };
+
+import config;
+import inet.url;
+var reloadSubscriptions = function(){
+ winform.chkAutoRefreshSubscription.checked = config.proxy.autoRefreshSubscription;
+ config.proxy.subscribeUrls.fields = {"";"checked";"ps";"url";}
+ var outbounds = ..config.proxy.outbounds : ..table.array();
+
+ var outbondSubscribeUrlMap = {};
+ for(i=#outbounds;1;-1){
+ var outbound = outbounds[i]
+ if(outbound.subscribeUrl){
+ outbondSubscribeUrlMap[outbound.subscribeUrl] = true;
+ }
+ }
+
+ var cfgSubscribeUrls = config.proxy.subscribeUrls;
+ for(i=#cfgSubscribeUrls;1;-1){
+ var sub = cfgSubscribeUrls[i]
+ if(outbondSubscribeUrlMap[sub.url]){
+ outbondSubscribeUrlMap[sub.url] = null;
+ }
+ else{
+ sub.checked = "禁用";
+ }
+ }
+
+ var count = 0;
+ for(url,v in outbondSubscribeUrlMap){
+ var tUrl = ..inet.url.split(subscribeUrl);
+ ..table.push(cfgSubscribeUrls,{url=url;ps=tUrl ? tUrl.host : "";checked="启用"})
+ }
+
+ var chkAll = true;
+ var checked = {}
+ for(i=#cfgSubscribeUrls;1;-1){
+ var sub = cfgSubscribeUrls[i]
+ if(sub.checked=="启用"){
+ table.push(checked,i)
+ }
+ else {
+ chkAll = false;
+ }
+ }
+ winform.chkAll.checked = chkAll;
+
+ grid.setTable( cfgSubscribeUrls );
+ winform.listview.checked = checked;
+}
+
+winform.loadSubscriptionsOnce = function(){
+ reloadSubscriptions();
+ winform.loadSubscriptionsOnce = function(){};
+}
+
+subscribe("uiCommand.subscriptionNew",function(subItem,existIndex){
+ if(existIndex){
+ winform.listview.setItemText(subItem.url,existIndex,4);
+ winform.listview.setChecked(existIndex,true);
+ return;
+ }
+
+ var item = winform.listview.addItem({"",subItem.checked,subItem.ps,subItem.url});
+ winform.listview.setChecked(item,true);
+} )
+
+//编辑变更值会触发下面的事件
+grid.onEditChanged = function(text,iItem,iSubItem){
+ var name = config.proxy.subscribeUrls.fields[iSubItem]
+ var sub = config.proxy.subscribeUrls[iItem];
+
+ if( name==="url" ){
+ if( text[1]=='/'#) {
+ text = "https://github.com"+text;
+ }
+
+ if(sub && sub.ps=="订阅源"){
+ import inet.url;
+ var tUrl = inet.url.split(text);
+ if(tUrl&tUrl.host){
+ sub.ps = tUrl.host;
+ winform.listview.setItemText(sub.ps,iItem,3);
+ }
+ }
+ }
+
+ if(sub){
+ sub[name] = text;
+ config.proxy.save();
+ }
+ else {
+ winform.msgErr("错误的订阅索引")
+ }
+}
+
+winform.popmenu = win.ui.popmenu(winform);//创建弹出菜单
+winform.popmenu.add('删除',function(id){
+ winform.btnRemove.oncommand();
+});
+winform.popmenu.add('全部删除',function(id){
+ for(i=1; winform.listview.count) winform.listview.setSelected(i,true);
+ winform.btnRemove.oncommand();
+});
+winform.popmenu.add();
+winform.popmenu.add('自剪贴板添加订阅',function(id){
+ winform.btnAdd.oncommand();
+});
+
+winform.btnUpdate.skin(style.primaryButton);
+winform.btnUpdate.oncommand = function(id,event){
+
+ winform.btnUpdate.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'}
+ config.proxy.autoRefreshSubscription = winform.chkAutoRefreshSubscription.checked;
+
+ var outbondSubscribeUrlMap = {};
+ var cfgSubscribeUrls = config.proxy.subscribeUrls;
+ for(i=#cfgSubscribeUrls;1;-1){
+ var sub = cfgSubscribeUrls[i]
+ outbondSubscribeUrlMap[sub.url] = sub.checked=="启用";
+ }
+
+ var removed = 0;
+ var outbounds = ..config.proxy.outbounds : ..table.array();
+ for(i=#outbounds;1;-1){
+ var outbound = outbounds[i]
+ if(outbound.subscribeUrl){
+ if(!outbondSubscribeUrlMap[outbound.subscribeUrl]){
+ table.remove(outbounds,i);
+ removed++;
+ }
+ }
+ }
+
+ if(removed) config.proxy.save();
+
+ import v2ray.outbounds;
+ if(!v2ray.outbounds.updateSubscription()){
+ if(removed) publish("uiCommand.restartV2RayCore",outbounds)
+ }
+
+ winform.btnUpdate.disabledText = null;
+}
+
+winform.chkAll.oncommand = function(id,event){
+ var checked = winform.chkAll.checked
+ for hItem in winform.listview.each(){
+ winform.listview.setChecked(hItem,checked)
+ }
+}
+
+winform.btnRemove.skin(style.plainButton)
+winform.btnRemove.oncommand = function(id,event){
+
+ var outboundRemoved = 0;
+ var subscribeUrls = config.proxy.subscribeUrls;
+ var items = winform.listview.selected;
+ if(!#items){
+ return winform.msgWarn("未选中任何订阅项( 请用鼠标单击订阅链接,不是指「勾选」 )")
+ }
+
+ winform.btnUpdate.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'}
+
+ for(i=#items;1;-1){
+ var url = subscribeUrls[items[i]].url;
+ table.remove(subscribeUrls,items[i]);
+ winform.listview.delItem(items[i]);
+
+ var outbounds = ..config.proxy.outbounds : ..table.array();
+ for(i=#outbounds;1;-1){
+ var outbound = outbounds[i]
+ if(outbound.subscribeUrl===url){
+ table.remove(outbounds,i);
+ outboundRemoved++;
+ }
+ }
+ }
+
+ config.proxy.save();
+
+ if(outboundRemoved){
+ publish("uiCommand.restartV2RayCore")
+ }
+ else {
+ win.delay(200);
+ }
+
+ publish("outbounds.updateConfigJson");
+ winform.btnUpdate.disabledText = null;
+}
+
+winform.btnAdd.oncommand = function(id,event){
+ import inet.url;
+ import win.clip;
+
+ var ps = "订阅源";
+ var url = win.clip.read();
+ url = url ? string.trim(url,'"\'\s\t\r\n ');
+ if(url && url[1]=='/'#){
+ url = "http://github.com" + url;
+ }
+
+ if(!inet.url.is(url)){
+ url = "";
+ }
+ else {
+ var tUrl = inet.url.split(url);
+ if(tUrl && tUrl.host){
+ ps = tUrl.host
+ }
+ }
+
+ config.proxy.subscribeUrls[winform.listview.count+1] = {checked="启用";ps="订阅源";url=url}
+ var item = winform.listview.addItem({
+ "";"启用";ps;url
+ })
+
+ winform.listview.setChecked(item,true);
+ grid.beginEdit(item,4);
+}
+
+winform.listview.onnotify = function(id,code,ptr){
+ if( code == 0xFFFFFF9B/*_LVN_ITEMCHANGED*/ ){
+ var nmListView = winform.listview.getNotifyMessage(code,ptr);
+ if( !nmListView )
+ return;
+
+ if( nmListView.uNewState & 0xF000/*_LVIS_STATEIMAGEMASK*/){
+ var selIndex = nmListView.iItem;
+ if( winform.listview.getChecked( selIndex ) ){
+ config.proxy.subscribeUrls[selIndex].checked = "启用";
+ config.proxy.save();
+
+ winform.listview.setItemText("启用",selIndex,2);
+ }
+ else {
+ config.proxy.subscribeUrls[selIndex].checked = "禁用";
+ config.proxy.save();
+
+ winform.listview.setItemText("禁用",selIndex,2);
+ }
+
+ var chkAll = true;
+ for(i=#config.proxy.subscribeUrls;1;-1){
+ var sub = config.proxy.subscribeUrls[i]
+ if(sub.checked!="启用"){
+ chkAll = false;
+
+ }
+ }
+
+ winform.chkAll.checked = chkAll;
+ }
+ }
+ elseif( code == 0xFFFFFFF4/*_NM_CUSTOMDRAW*/ ) {
+ var lvcd = winform.listview.getNotifyCustomDraw(code,ptr);
+ if( lvcd.nmcd.dwDrawStage == 0x10001/*_CDDS_ITEMPREPAINT*/)
+ return 0x20/*_CDRF_NOTIFYSUBITEMDRAW*/
+ elseif( lvcd.nmcd.dwDrawStage == 1/*_CDDS_PREPAINT*/ ){
+ return 0x20/*_CDRF_NOTIFYITEMDRAW*/;
+ }
+ elseif( lvcd.nmcd.dwDrawStage == ( 0x10001/*_CDDS_ITEMPREPAINT*/ | 0x20000/*_CDDS_SUBITEM*/) ){
+ //注意这里 iSubItem 的索引自0开始( 其他函数通常自1开始 )
+ lvcd.clrText = lvcd.nmcd.dwItemSpec % 2 ? 0x373737 : 0;
+ lvcd.clrTextBk = lvcd.nmcd.dwItemSpec % 2 ? 0xFFFFFF : 0xF5F5F5;
+ lvcd.update();
+
+ return 0/*_CDRF_DODEFAULT*/
+ }
+ }
+ elseif( code == 0xFFFFFFFB/*_NM_RCLICK*/ ) {
+ var x,y = win.getCursorPos();
+ winform.popmenu.popup(x,y,true);//弹出菜单
+ }
+}
+
+winform.show();
+win.loopMessage();
+return winform;
\ No newline at end of file
diff --git a/forms/main/outbound.aardio b/forms/main/outbound.aardio
new file mode 100644
index 0000000..77af6a2
--- /dev/null
+++ b/forms/main/outbound.aardio
@@ -0,0 +1,626 @@
+import web.json;
+import win.dlg.message;
+import fonts.fontAwesome;
+import win.ui;
+/*DSG{{*/
+var winform = win.form(text="winXray - 代理服务器配置";right=999;bottom=504;bgcolor=16777215;exmode="none";min=false;mode="popup")
+winform.add(
+btnAddOutbound={cls="plus";text="新 增";left=705;top=410;right=808;bottom=446;align="left";bgcolor=14935259;db=1;dr=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=22}};iconText='\uF067';notify=1;textPadding={left=40};z=17};
+btnCopySharedLink={cls="plus";text="复制";left=829;top=471;right=901;bottom=496;align="left";clip=1;db=1;dr=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=12}};iconText='\uF0C1';notify=1;textPadding={left=30};z=1};
+btnGenGuid={cls="plus";text="生成";left=914;top=259;right=986;bottom=284;align="left";clip=1;dr=1;dt=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=12}};iconText='\uF0AD';notify=1;textPadding={left=30};z=19};
+btnImportSharedLink={cls="plus";text="导入";left=912;top=471;right=984;bottom=496;align="left";clip=1;db=1;dr=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=12}};iconText='\uF0C1';notify=1;textPadding={left=30};z=21};
+btnInsertField={cls="plus";text="插入更多配置字段";left=10;top=0;right=191;bottom=24;align="left";dl=1;dt=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=12}};iconText='\uF196 ';notify=1;textPadding={left=30};z=18};
+btnSaveOutbound={cls="plus";text="保 存";left=826;top=410;right=929;bottom=446;align="left";bgcolor=11580047;db=1;disabled=1;dr=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=22}};iconText='\uF0C7';notify=1;textPadding={left=40};z=16};
+btnUpdateCore={cls="plus";text="下载 / 更新 NaÏveProxy Core";left=637;top=61;right=979;bottom=89;align="left";color=3947580;dr=1;dt=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-17;name='FontAwesome');padding={left=18}};iconText='\uF0AB';notify=1;textPadding={left=50};z=23};
+cmbNetwork={cls="combobox";left=656;top=97;right=814;bottom=123;dr=1;dt=1;edge=1;items={"tcp";"kcp";"ws";"h2";"quic"};mode="dropdown";z=13};
+cmbProtocol={cls="combobox";left=656;top=28;right=814;bottom=54;dr=1;dt=1;edge=1;items={"vmess";"vless";"trojan";"trojan-go";"ssr";"shadowsocks";"naive";"socks";"https";"http"};mode="dropdown";z=12};
+cmbSecurity={cls="combobox";left=656;top=140;right=814;bottom=166;dr=1;dt=1;edge=1;items={"auto";"none";"chacha20-poly1305";"aes-128-gcm"};mode="dropdown";z=15};
+editAddress={cls="plus";left=656;top=183;right=878;bottom=207;align="left";bgcolor=16777215;border={bottom=1;color=-8355712};dr=1;dt=1;editable="edit";font=LOGFONT(h=-16);textPadding={bottom=1};z=2};
+editId={cls="plus";left=656;top=263;right=986;bottom=287;align="left";bgcolor=16777215;border={bottom=1;color=-8355712};clip=1;dr=1;dt=1;editable="edit";font=LOGFONT(h=-16);notify=1;textPadding={right=75;bottom=1};z=20};
+editOutbound={cls="edit";left=15;top=25;right=472;bottom=462;db=1;dl=1;dr=1;dt=1;edge=1;font=LOGFONT(h=-13);hscroll=1;multiline=1;vscroll=1;z=14};
+editPort={cls="plus";left=656;top=224;right=745;bottom=248;align="left";bgcolor=16777215;num=1;border={bottom=1;color=-8355712};dr=1;dt=1;editable="edit";font=LOGFONT(h=-16);textPadding={bottom=1};z=4};
+editPs={cls="plus";left=656;top=306;right=878;bottom=330;align="left";bgcolor=16777215;border={bottom=1;color=-8355712};dr=1;dt=1;editable="edit";font=LOGFONT(h=-16);textPadding={bottom=1};z=7};
+editSharedLink={cls="plus";left=13;top=475;right=986;bottom=499;align="left";bgcolor=16777215;border={bottom=1;color=-8355712};clip=1;db=1;dl=1;dr=1;font=LOGFONT(h=-16);notify=1;textPadding={right=150;bottom=1};z=22};
+lbId={cls="static";text="登录用户( id ):";left=492;top=262;right=641;bottom=288;align="right";bgcolor=16777215;dr=1;dt=1;font=LOGFONT(h=-16);transparent=1;z=6};
+lbSecurity={cls="static";text="加密方式( security ):";left=473;top=136;right=641;bottom=162;align="right";bgcolor=16777215;dl=1;dr=1;dt=1;font=LOGFONT(h=-16);transparent=1;z=10};
+qrPicture={cls="plus";left=510;top=358;right=606;bottom=454;bgcolor=16777215;db=1;dr=1;notify=1;repeat="scale";z=24};
+static={cls="static";text="服务器( address ):";left=481;top=178;right=641;bottom=204;align="right";bgcolor=16777215;dl=1;dr=1;dt=1;font=LOGFONT(h=-16);transparent=1;z=3};
+static10={cls="static";text="代理协议( protocol ):";left=473;top=26;right=641;bottom=52;align="right";bgcolor=16777215;dl=1;dr=1;dt=1;font=LOGFONT(h=-16);transparent=1;z=11};
+static2={cls="static";text="服务端口( port ):";left=498;top=220;right=641;bottom=246;align="right";bgcolor=16777215;dr=1;dt=1;font=LOGFONT(h=-16);transparent=1;z=5};
+static4={cls="static";text="备注( ps ):";left=498;top=304;right=641;bottom=330;align="right";bgcolor=16777215;dr=1;dt=1;font=LOGFONT(h=-16);transparent=1;z=8};
+static5={cls="static";text="传输协议( network ):";left=473;top=94;right=641;bottom=126;align="right";bgcolor=16777215;dl=1;dr=1;dt=1;font=LOGFONT(h=-16);transparent=1;z=9}
+)
+/*}}*/
+
+winform.outboundConfig = {};
+winform.addOutboundField = function(k,v){
+ if(winform.outboundConfig[k] !== null){
+ return winform.msgInfo("该字段已经存在,不需要添加!");
+ }
+
+ winform.outboundConfig[k] = v;
+ winform.editOutbound.text = web.json.stringify(winform.outboundConfig,true,false);
+ winform.updateSharedLink();
+}
+
+winform.cmbProtocol.onProtocolChange = function(){
+ var sel = winform.cmbProtocol.selText;
+ if(sel=="vmess"){
+ winform.cmbSecurity.items = {
+ "auto";"none";"chacha20-poly1305";"aes-128-gcm"
+ }
+ winform.cmbSecurity.selIndex = 1;
+ winform.outboundConfig.security = "auto";
+
+ winform.cmbNetwork.items = {
+ "tcp";"kcp";"h2";"quic";
+ }
+ winform.cmbNetwork.selIndex = 1;
+ winform.outboundConfig.network = "tcp";
+ winform.btnUpdateCore.text = '下载 / 更新支持组件: V2Ray Core';
+ winform.editId.setCueBannerText("请输入 GUID");
+ }
+ elseif(sel=="shadowsocks"){
+ winform.cmbSecurity.items = {
+ "aes-256-gcm";"aes-128-gcm";"chacha20-poly1305";"chacha20-ietf-poly1305";"none"
+ }
+
+ winform.cmbSecurity.selIndex = 1;
+ winform.outboundConfig.security = "aes-256-gcm";
+
+ winform.cmbNetwork.items = {"tcp";}
+ winform.cmbNetwork.selIndex = 1;
+ winform.outboundConfig.network = "tcp";
+ winform.btnUpdateCore.text = '下载 / 更新支持组件: V2Ray Core';
+ winform.editId.setCueBannerText("请输入密码");
+ }
+ elseif(sel=="ssr"){
+ winform.cmbNetwork.items = {
+ "origin";"plain";"auth_sha1_v4";"http_simple";"auth_aes128_sha1";"http_post";"auth_aes128_md5";"http_mix";"auth_chain_a";"tls1.2_ticket_auth";"auth_chain_b";"tls1.2_ticket_fastauth";"auth_chain_c/d/e/f";
+ }
+ winform.cmbNetwork.selIndex = 1;
+ winform.outboundConfig.network = "origin";
+
+ winform.cmbSecurity.items = {
+ "none";"table";"rc4";"rc4-md5-6";"rc4-md5";"aes-128-cfb";"aes-192-cfb";"aes-256-cfb";"aes-128-ctr";"aes-192-ctr";"aes-256-ctr";"camellia-128-cfb";"camellia-192-cfb";"camellia-256-cfb";"bf-cfb";"cast5-cfb";"des-cfb";"idea-cfb";"rc2-cfb";"seed-cfb";"salsa20";"chacha20";"chacha20-ietf";
+ }
+
+ winform.cmbSecurity.selIndex = 1;
+ winform.outboundConfig.security = "none";
+ winform.btnUpdateCore.text = '下载 / 更新支持组件: SSR Core';
+ winform.editId.setCueBannerText("请输入密码");
+ }
+ elseif(sel=="vless"){
+ winform.cmbSecurity.items = {
+ "none";
+ }
+ winform.cmbSecurity.selIndex = 1;
+ winform.outboundConfig.security = "none";
+
+ winform.cmbNetwork.items = {
+ "tcp";"kcp";"h2";"quic";
+ }
+ winform.cmbNetwork.selIndex = 1;
+ winform.outboundConfig.network = "tcp";
+ winform.btnUpdateCore.text = '下载 / 更新支持组件: Xray Core';
+ winform.editId.setCueBannerText("请输入 GUID");
+ }
+ elseif(sel=="naive"){
+ winform.cmbNetwork.items = {
+ "https";"quic";
+ }
+ winform.cmbNetwork.selIndex = 1;
+ winform.outboundConfig.network = "https";
+
+ winform.cmbSecurity.items = {}
+ winform.outboundConfig.security = null;
+
+ winform.btnUpdateCore.text = '下载 / 更新支持组件: NaïveProxy Core';
+ winform.editId.setCueBannerText("请输入 用户名:密码");
+ }
+ elseif(sel=="socks"){
+ winform.cmbSecurity.items = { }
+ winform.outboundConfig.security = null;
+
+ winform.cmbNetwork.items = {"tcp";}
+ winform.cmbNetwork.selIndex = 1;
+ winform.outboundConfig.network = "tcp";
+ winform.btnUpdateCore.text = '下载 / 更新支持组件: V2Ray Core';
+ winform.editId.setCueBannerText("请输入 用户名:密码");
+ }
+ elseif(sel=="http" || sel=="https"){
+ winform.cmbSecurity.items = { }
+ winform.outboundConfig.security = null;
+
+ winform.cmbNetwork.items = {"tcp";}
+ winform.cmbNetwork.selIndex = 1;
+ winform.outboundConfig.network = "tcp";
+ winform.btnUpdateCore.text = '下载 / 更新支持组件: V2Ray Core';
+ winform.editId.setCueBannerText("请输入 用户名:密码");
+ }
+ else {
+ winform.cmbSecurity.items = { }
+ winform.outboundConfig.security = null;
+
+ winform.cmbNetwork.items = {"tcp";}
+ winform.cmbNetwork.selIndex = 1;
+ winform.outboundConfig.network = "tcp";
+ winform.btnUpdateCore.text = '下载 / 更新支持组件: V2Ray Core';
+ winform.editId.setCueBannerText("请输入密码");
+ }
+}
+
+winform.cmbProtocol.onListChange = function(){
+ winform.cmbProtocol.onProtocolChange();
+
+ table.define(winform.outboundConfig);
+ winform.outboundConfig.protocol = winform.cmbProtocol.selText;;
+ winform.editOutbound.text = web.json.stringify(winform.outboundConfig,true,false);
+ winform.updateSharedLink();
+}
+
+winform.cmbNetwork.onListChange = function(){
+ var sel = winform.cmbNetwork.selText;
+ winform.outboundConfig.network = sel;
+ winform.editOutbound.text = web.json.stringify(winform.outboundConfig,true,false);
+ winform.updateSharedLink();
+}
+
+winform.cmbSecurity.onListChange = function(){
+ var sel = winform.cmbSecurity.selText;
+ winform.outboundConfig.security = sel;
+ winform.editOutbound.text = web.json.stringify(winform.outboundConfig,true,false);
+ winform.updateSharedLink();
+}
+
+winform.editId.editBox.onChange = function(){
+ if( winform.outboundConfig.id == winform.editId.text ){
+ return;
+ }
+
+ winform.outboundConfig.id = winform.editId.text;
+ winform.editOutbound.text = web.json.stringify(winform.outboundConfig,true,false);
+ winform.updateSharedLink();
+}
+
+winform.editPort.editBox.onChange = function(){
+ winform.outboundConfig.port = tonumber(owner.text):443;
+ winform.editOutbound.text = web.json.stringify(winform.outboundConfig,true,false);
+ winform.updateSharedLink();
+}
+
+winform.editAddress.editBox.onChange = function(){
+ winform.outboundConfig.address = owner.text;
+ winform.editOutbound.text = web.json.stringify(winform.outboundConfig,true,false);
+ winform.updateSharedLink();
+}
+
+winform.editPs.editBox.onChange = function(){
+ winform.outboundConfig.ps = owner.text;
+ winform.editOutbound.text = web.json.stringify(winform.outboundConfig,true,false);
+ winform.updateSharedLink();
+}
+
+var editOutboundTip = {
+ address = {"代理服务器地址";"值可以是域名或者IP地址"};
+ alterId = {"额外ID";"仅用于VMESS协议,与服务器一致即可"};
+ aid = {"额外ID(alterId)";"数值,仅用于VMESS协议,与服务器一致即可"};
+ network = {"传输协议(network)";"可选值为tcp,ws等,也可以放 SSR 的 protocol 值"};
+ net = {"传输协议(network)";"可选值为tcp,ws等"};
+ type = {"伪装类型";"默认的可选值为none,http等,kcp或quic此字段表示header.type,可选值为 none,srtp,utp,wechat-video,dtls,wireguard"};
+ ps = {"备注";"备注"};
+ tls = {"是否启用TLS";"可选值为tls,xtls或空值,vless协议省略时默认值为tls"};
+ path = {"请求路径";"用于ws,http等协议指定请求路径"};
+ httpMethod = {"HTTP请求方法";"用于http协议指定请求方法"};
+ headers = {"HTTP请求头";"用于ws,http等协议指定请求头"};
+ id = {"密码";"服务器密码"};
+ host = {"主机名";"用于指定http,ws等协议请求头中的主机名"};
+ protocol = {"协议";"可选值为 vmess,vless,shadowsocks,trojan,trojan-go 之一"};
+ port = {"端口";"服务器端口,数值"};
+ security = {"加密方式";"可省略,vmess协议默认为auto,vless协议默认为none"};
+ sni = {"TLS服务器名";"TLS客户端请求中的服务器名字段,如果不指定则默认取host或address字段值。"};
+ flow = {"流控";"目前仅用于选择 XTLS 的算法,省略时默认值为xtls-rprx-direct"};
+ obfs = {"混淆插件";"可选值:plain,http_simple,http_post,tls1.2_ticket_auth ..."};
+ obfsParam = {"混淆参数";"SSR 里的 obfs_param"};
+ networkParam = {"SSR网络协议参数";"SSR 里的 protocol_param"};
+ concurrency = {"Mux多路复用:最大并发连接数";"最小值1,最大值1024,特殊值-1,不加载mux模块。缺省由winXray根据连接协议自动设定此值。"};
+}
+
+winform.editOutbound.wndproc = function(hwnd,message,wParam,lParam){
+ if(message == 0x202/*_WM_LBUTTONUP*/){
+ var lineIndex = winform.editOutbound.lineFromChar();
+ if(lineIndex == winform.editOutbound.preLineIndex){
+ return;
+ }
+ winform.editOutbound.preLineIndex = lineIndex;
+
+ var line = winform.editOutbound.lineText();
+ var n,v = string.match(line,`^\s*\"(\w+)\"\s*\:\s*(%"")[\,\s]*$`);
+ if( !n ) n,v = string.match(line,`^\s*\"(\w+)\"\s*\:\s*(\d+)[\,\s]*$`);
+ if( !n ) n,v = string.match(line,`^\s*\"(\w+)\"\s*\:\s*\{`);
+ if(editOutboundTip[n]){
+ winform.editOutbound.showInfoTip(editOutboundTip[n][1],editOutboundTip[n][2])
+ }
+ }
+}
+
+import win.ui.menu;
+var insertFieldMenu = {
+ { "允许忽略证书:allowInsecure";
+ function(id){
+ winform.addOutboundField("allowInsecure",true);
+ }
+ };
+ { "TLS服务器名:sni";
+ function(id){
+ winform.addOutboundField("sni","");
+ }
+ };
+ { "启用TLS:tls";
+ function(id){
+ winform.addOutboundField("tls","xtls");
+ }
+ };
+ { "流控:flow";
+ function(id){
+ winform.addOutboundField("flow","xtls-rprx-direct");
+ }
+ };
+ { "多路复用最大连接:concurrency";
+ function(id){
+ winform.addOutboundField("concurrency",4);
+ }
+ };
+
+ { "伪装类型:type";
+ function(id){
+ winform.addOutboundField("type","http");
+ }
+ };
+ { "备注:ps";
+ function(id){
+ winform.addOutboundField("ps","");
+ }
+ };
+ { "请求主机名:host";
+ function(id){
+ winform.addOutboundField("host","");
+ }
+ };
+ { "请求路径:path";
+ function(id){
+ winform.addOutboundField("path","/");
+ }
+ };
+ { "HTTP请求方法:httpMethod";
+ function(id){
+ winform.addOutboundField("httpMethod","GET");
+ }
+ };
+ { "HTTP请求头:headers";
+ function(id){
+ winform.addOutboundField("headers",{method="GET"});
+ }
+ };
+ { "SSR混淆插件:obfs";
+ function(id){
+ winform.addOutboundField("obfs","plain");
+ }
+ };
+ { "SSR混淆参数:obfsParam";
+ function(id){
+ winform.addOutboundField("obfsParam","");
+ }
+ };
+ { "SSR网络协议参数:networkParam";
+ function(id){
+ winform.addOutboundField("networkParam","");
+ }
+ };
+ { "绑定的订阅网址:subscribeUrl";
+ function(id){
+ winform.addOutboundField("subscribeUrl","https://");
+ }
+ };
+ { "允许自动测试并连接:autoConnect";
+ function(id){
+ winform.addOutboundField("autoConnect",false);
+ }
+ };
+ { "SSH管理端口:sshPort";
+ function(id){
+ winform.addOutboundField("sshPort",22);
+ }
+ };
+}
+winform.editOutbound.enablePopMenu({
+ { "插入配置字段";insertFieldMenu}
+})
+
+import style;
+winform.btnInsertField.skin(style.transButton)
+winform.btnInsertField.oncommand = function(id,event){
+ var popInsertFieldMenu = win.ui.popmenu(winform);
+ popInsertFieldMenu.addTable(insertFieldMenu);
+
+ var x,y,cx,cy = winform.btnInsertField.getPos();
+ popInsertFieldMenu.popup(x,y+cy);
+}
+
+import win.debounce;
+var onEditChange = win.debounce(
+ function(){
+ var data,err = web.json.tryParse(winform.editOutbound.text);
+ if(!data){
+ if(err){
+ return winform.editOutbound.showErrorTip("JSON 语法错误",err)
+ }
+ return;
+ }
+
+ var editPortChange = winform.editPort.editBox.onChange;
+ var editIdChange = winform.editId.editBox.onChange;
+ var editAddressChange = winform.editAddress.editBox.onChange;
+ var editPsChange = winform.editPs.editBox.onChange;
+
+ winform.editPort.editBox.onChange = null;
+ winform.editId.editBox.onChange = null;
+ winform.editAddress.editBox.onChange = null;
+ winform.editPs.editBox.onChange = null;
+
+ winform.editPort.text = data.port;
+ winform.editId.text = data.id;
+ winform.editAddress.text = data.address;
+ winform.editPs.text = data.ps;
+
+ winform.editPort.editBox.onChange = editPortChange;
+ winform.editId.editBox.onChange = editIdChange;
+ winform.editAddress.editBox.onChange = editAddressChange;
+ winform.editPs.editBox.onChange = editPsChange;
+
+ var cmbNetworkChange = winform.cmbNetwork.onListChange;
+ var cmbProtocolChange = winform.cmbProtocol.onListChange;
+ var cmbSecurityChange = winform.cmbSecurity.onListChange;
+
+ winform.cmbNetwork.onListChange = null;
+ winform.cmbProtocol.onListChange = null;
+ winform.cmbSecurity.onListChange = null;
+
+ winform.cmbNetwork.selText = data.network;
+ winform.cmbProtocol.selText = data.protocol;
+ winform.cmbProtocol.onProtocolChange();
+ winform.cmbSecurity.selText = data.security;
+
+ winform.cmbNetwork.onListChange = cmbNetworkChange;
+ winform.cmbProtocol.onListChange = cmbProtocolChange;
+ winform.cmbSecurity.onListChange = cmbSecurityChange;
+
+ winform.updateSharedLink();
+ },500
+)
+
+winform.editOutbound.onChange = function(){
+ onEditChange();
+}
+
+winform.btnSaveOutbound.oncommand = function(id,event){
+ if(!#winform.editAddress.text){
+ return winform.editAddress.editBox.showErrorTip("配置错误","服务器地址不能为空")
+ }
+
+ if(!#winform.editPort.text){
+ return winform.editPort.editBox.showErrorTip("配置错误","端口不能为空")
+ }
+
+ if( !#winform.editId.text ){
+ var protocol = winform.outboundConfig.protocol;
+ if((protocol!="socks") && (protocol!="http") && (protocol!="https")){
+ return winform.editId.editBox.showErrorTip("配置错误","当前代理协议密码不能为空")
+ }
+ }
+
+ table.assign(winform.origOutboundConfig,winform.outboundConfig);
+ winform.endModal();
+
+ publish("uiCommand.restartV2RayCore");
+ publish("outbounds.updateConfigJson");
+
+}
+
+import config;
+winform.btnAddOutbound.oncommand = function(id,event){
+ if(!#winform.editAddress.text){
+ return winform.editAddress.editBox.showErrorTip("配置错误","服务器地址不能为空")
+ }
+
+ if(!#winform.editPort.text){
+ return winform.editPort.editBox.showErrorTip("配置错误","端口不能为空")
+ }
+
+ if(!#winform.editId.text ){
+ var protocol = winform.outboundConfig.protocol
+ if( (protocol!="socks") && (protocol!="http") && (protocol!="https") ){
+ return winform.editId.editBox.showErrorTip("配置错误","当前代理协议密码不能为空")
+ }
+ }
+
+ table.push(config.proxy.outbounds,winform.outboundConfig);
+ winform.endModal();
+
+ publish("uiCommand.restartV2RayCore");
+ publish("outbounds.updateConfigJson");
+}
+
+import win.guid;
+winform.btnGenGuid.oncommand = function(id,event){
+ var sel = winform.cmbProtocol.selText;
+ if(sel=="socks" || sel=="http" || sel=="https" || sel=="naive" ){
+ winform.editId.text = "user:" + string.random(16);
+ }
+ elseif(sel=="shadowsocks" || sel=="ssr" ){
+ winform.editId.text = string.random(22,"/@0123456abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ }
+ else {
+ var guid = win.guid.create();
+ winform.editId.text = string.lower( tostring(guid) );
+ }
+}
+winform.btnGenGuid.skin(style.link)
+
+winform.btnSaveOutbound.skin(style.button)
+winform.btnAddOutbound.skin(style.primaryButton)
+winform.btnSaveOutbound.disabled = true;
+
+import qrencode.bitmap;
+import v2ray.outbounds;
+winform.updateSharedLink = function(modified){
+ var cfg = winform.outboundConfig;
+ var link = "";
+
+ if(#cfg.address && (cfg.port!==null) && #cfg.protocol){
+ link = v2ray.outbounds.exportSharedLinks({winform.outboundConfig});
+ }
+
+ winform.editSharedLink.text = link;
+
+ if(#link){
+ var qrBmp = qrencode.bitmap(link,0,0);
+ if(qrBmp){
+ winform.qrPicture.setBackground(qrBmp.copyBitmap(winform.qrPicture.width));
+ }
+ }
+}
+
+import win.clip;
+winform.btnImportSharedLink.skin(style.link);
+winform.btnImportSharedLink.oncommand = function(id,event){
+ var str = ..win.clip.read();
+ if(str){
+ var outbounds = v2ray.outbounds.importFromString(str);
+ if(#outbounds){
+ var cfg = winform.outboundConfig;
+ table.clear(cfg);
+ table.assign(cfg,outbounds[1]);
+
+ winform.editOutbound.text = web.json.stringify(winform.outboundConfig,true,false);
+ onEditChange();
+
+ winform.msgOk("已成功导入服务器",1000);
+ return;
+ }
+ }
+
+ winform.msgFrown('未导入服务器!\r\n请先复制以下格式文本(自动清除其中的无效内容):\r\n\r\n1、分享链接或服务器JSON配置。\r\n支持 vmess://,vless://,ss://,ssr://,trojan://, trojan-go:// 等通用分享链接。\r\n\r\n2、服务器配置的JSON数组,支持winXray格式以及通用格式JSON。\r\n其他 BASE64 编码或明文返回以上1、2条规定的配置或分享链接。')
+}
+
+winform.btnCopySharedLink.skin(style.link)
+winform.btnCopySharedLink.oncommand = function(id,event){
+ var lnk = winform.editSharedLink.text;
+ if(!#lnk){
+ winform.msgErr("分享链接不能为空",1500);
+ }
+ else {
+ win.clip.write(lnk);
+ winform.msgOk("分享链接已复制到剪贴板",1500);
+ }
+}
+
+
+winform.setOutboundConfig = function(cfg){
+ winform.cmbProtocol.selText = cfg.protocol;
+ winform.cmbProtocol.onListChange();
+
+ winform.btnAddOutbound.skin(style.button);
+ winform.btnSaveOutbound.skin(style.primaryButton);
+ winform.btnSaveOutbound.disabled = false;
+
+ winform.origOutboundConfig = cfg;
+ winform.outboundConfig = table.clone(cfg);
+ winform.editOutbound.text = web.json.stringify(winform.outboundConfig,true,false);
+ onEditChange();
+}
+winform.setOutboundConfig({
+ port = 443;
+ protocol = "vmess";
+ network = "tcp";
+});
+winform.btnAddOutbound.skin(style.primaryButton);
+winform.btnSaveOutbound.skin(style.button);
+winform.btnSaveOutbound.disabled = true;
+
+winform.btnUpdateCore.skin(style.plainButton)
+winform.btnUpdateCore.oncommand = function(id,event){
+ winform.btnUpdateCore.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'};
+ var sel = winform.cmbProtocol.selText;
+
+ if(sel=="ssr"){
+ import v2ray.core.ssr;
+ var versionTag = v2ray.core.ssr.updateCore();
+ if( versionTag ){
+ publish("uiCommand.restartV2RayCore");
+ winform.btnUpdateCore.disabledText = null;
+ winform.msgOk("SSR Core( ShadowsocksR-native ) 已更新到:" + versionTag,1500)
+ }
+ else {
+ winform.btnUpdateCore.disabledText = null;
+ }
+ }
+ elseif(sel=="vless"){
+ import v2ray.core.xray;
+ var versionTag = v2ray.core.xray.updateCore();
+ if( versionTag ){
+ publish("uiCommand.restartV2RayCore");
+ winform.btnUpdateCore.disabledText = null;
+ winform.msgOk("已下载最新 XRay Core 版本:" + versionTag+ '\nV2Ray 内核已切换为:XRay Core',1500)
+ }
+ else {
+ winform.btnUpdateCore.disabledText = null;
+ winform.msgErr("XRay Core 下载失败!");
+ }
+ }
+ elseif(sel=="naive"){
+ import v2ray.core.naive;
+ var versionTag = v2ray.core.naive.updateCore();
+ if( versionTag ){
+ publish("uiCommand.restartV2RayCore");
+ winform.btnUpdateCore.disabledText = null;
+ winform.msgOk("NaÏveProxy Core 已更新到:" + versionTag,1500)
+ }
+ else {
+ winform.btnUpdateCore.disabledText = null;
+ winform.msgErr("NaÏveProxy Core 下载失败!");
+ }
+ }
+ else {
+ import v2ray.core;
+ var versionTag = v2ray.core.updateCore();
+ if( versionTag ){
+ publish("uiCommand.restartV2RayCore");
+ winform.btnUpdateCore.disabledText = null;
+ winform.msgOk("已下载最新 V2Ray Core 版本:" + versionTag + '\nV2Ray 内核已切换为: V2Ray Core',1500)
+ }
+ else {
+ winform.btnUpdateCore.disabledText = null;
+ winform.msgErr("V2Ray Core 下载失败!");
+ }
+ }
+}
+
+winform.qrPicture.skin(
+ foreground = {
+ hover = 0x10FFFF00;
+ active = 0x20EEEE00;
+ }
+)
+winform.qrPicture.oncommand = function(id,event){
+ var lnk = string.trim(winform.editSharedLink.text);
+ if(#lnk){
+ var frmChild = winform.loadForm("\forms\main\tools\qr.aardio");
+ frmChild.createQrCode(lnk);
+ frmChild.show();
+ }
+}
+
+winform.show();
+win.loopMessage();
+return winform;
\ No newline at end of file
diff --git a/forms/main/pac.aardio b/forms/main/pac.aardio
new file mode 100644
index 0000000..3e27acb
--- /dev/null
+++ b/forms/main/pac.aardio
@@ -0,0 +1,626 @@
+import win.ui;
+import win.ui.atom;
+import fonts.fontAwesome;
+/*DSG{{*/
+var winform = win.form(text="winXray - 代理自动配置文件(PAC)";right=912;bottom=802;bgcolor=16777215)
+winform.add(
+btnAddDomain={cls="plus";text="添加";left=625;top=25;right=723;bottom=56;align="left";bgcolor=14935259;dr=1;dt=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=22}};iconText='\uF1C4';notify=1;textPadding={left=40};z=16};
+btnDeleteDomain={cls="plus";text="移除";left=740;top=25;right=838;bottom=56;align="left";bgcolor=14935259;dr=1;dt=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=22}};iconText='\uF1C4';notify=1;textPadding={left=40};z=17};
+btnReset={cls="plus";text="恢复PAC";left=609;top=763;right=741;bottom=794;align="left";bgcolor=14935259;db=1;dr=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=22}};iconText='\uF0E2';notify=1;textPadding={left=40};z=9};
+btnSave={cls="plus";text="保存PAC";left=751;top=763;right=883;bottom=794;align="left";bgcolor=11580047;db=1;dr=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=22}};iconText='\uF0C7';notify=1;textPadding={left=40};z=10};
+btnUpdate={cls="plus";text="同步到网络最新PAC";left=402;top=763;right=599;bottom=794;align="left";bgcolor=14935259;db=1;dr=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=22}};iconText='\uF26B';notify=1;textPadding={left=40};z=7};
+editPacDirect={cls="richedit";left=8;top=97;right=901;bottom=745;db=1;dl=1;dr=1;dt=1;edge=1;font=LOGFONT(h=-13);hidesel=false;hscroll=1;multiline=1;vscroll=1;z=2};
+editPacDomain={cls="plus";left=91;top=29;right=436;bottom=53;align="right";bgcolor=16777215;border={bottom=1;color=-8355712};dl=1;dr=1;dt=1;editable="edit";font=LOGFONT(h=-16);textPadding={bottom=1};z=12};
+editPacProxy={cls="richedit";left=8;top=97;right=901;bottom=751;db=1;dl=1;dr=1;dt=1;edge=1;font=LOGFONT(h=-15);hidesel=false;hscroll=1;multiline=1;vscroll=1;z=3};
+groupbox={cls="groupbox";text="域名项";left=8;top=8;right=901;bottom=64;bgcolor=16777215;dl=1;dr=1;dt=1;edge=1;z=1};
+lbTip={cls="plus";text="以下域名通过代理连接( 点域名绑定上面选项,点击右键菜单可批量导入域名 )。";left=10;top=66;right=898;bottom=92;align="left";color=3947580;dl=1;dr=1;dt=1;font=LOGFONT(h=-13);notify=1;transparent=1;z=13};
+navDirect={cls="plus";text="直连域名( JSON )";left=184;top=750;right=315;bottom=782;border={top=1;color=-16744448};db=1;dl=1;z=8};
+navProxy={cls="plus";text="代理域名( JSON )";left=53;top=750;right=184;bottom=782;border={top=1;color=-16744448};db=1;dl=1;z=5};
+navRight={cls="plus";left=314;top=750;right=604;bottom=751;bgcolor=16777215;border={color=-16744448};db=1;dl=1;dr=1;forecolor=32768;linearGradient=180;z=11};
+plus={cls="plus";left=9;top=750;right=53;bottom=751;border={color=-16744448};db=1;dl=1;forecolor=32768;z=14};
+plus2={cls="plus";text="域名:";left=16;top=28;right=79;bottom=54;align="right";color=3947580;dl=1;dt=1;font=LOGFONT(h=-13);notify=1;transparent=1;z=15};
+radioDirect={cls="plus";text="直连";left=540;top=27;right=611;bottom=58;align="left";dr=1;dt=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-15;name='FontAwesome')};iconText='\uF111';notify=1;textPadding={left=15};z=6};
+radioProxy={cls="plus";text="代理";left=460;top=27;right=529;bottom=58;align="left";dr=1;dt=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-15;name='FontAwesome')};iconText='\uF111';notify=1;textPadding={left=15};z=4}
+)
+/*}}*/
+
+import config;
+import style;
+winform.btnSave.skin(style.primaryButton);
+winform.btnUpdate.skin(style.button);
+winform.btnReset.skin(style.button);
+winform.btnAddDomain.skin(style.button);
+winform.btnDeleteDomain.skin(style.button);
+winform.radioDirect.skin(style.radio);
+winform.radioProxy.skin(style.radio);
+winform.radioProxy.checked = true;
+
+import config;
+import web.json;
+import win.ui.tabs;
+var tbs = win.ui.tabs(winform.navProxy,winform.navDirect,winform.nav06,winform.nav091,winform.navZhengMa,winform.navTxt)
+tbs.margin = 0;
+
+tbs.skin({
+ foreground={
+ active=0xFFFFFFFF;
+ default=0x00FFFFFF;
+ hover=0xFFCCCCCC;
+ };
+ checked={
+ foreground={
+ default=0x00FFFFFF;
+ };
+ border = {
+ default = {left=1;right=1;bottom=1;color=0xFF008000}
+ };
+ }
+});
+
+tbs.onSelchange = function(idx,strip,form){
+ if(idx==1){
+ winform.currentEditPac = winform.editPacProxy;
+ winform.editPacProxy.hide = false;
+ winform.editPacDirect.hide = true;
+ winform.lbTip.text = `以下域名通过代理连接( 点域名绑定上面选项,点击右键菜单可批量导入代理域名 ):`
+ }
+ else {
+ winform.currentEditPac = winform.editPacDirect;
+ winform.editPacProxy.hide = true;
+ winform.editPacDirect.hide = false;
+ winform.lbTip.text = `以下域名不使用代理( 点域名绑定上面选项,点击右键菜单可批量导入直连域名 ): `
+ }
+}
+tbs.selIndex = 1;
+
+import win.dlg.message;
+win.dlg.message.install();
+
+winform.loadPacToEdit = function(str,fromUpdater){
+ var rules = string.match(str,"var\s+rules\s*=\s*(%\[\])")
+ if(!rules) return winform.msgErr("PAC文件格式错误");
+
+ rules = web.json.parse(rules);
+ if(!(rules && table.isArray(rules) && type(rules[1][1])==type.table)) return winform.msgErr("PAC文件格式错误");
+
+ var proxy,direct = table.array(),table.array()
+ for(i=1;#rules){
+ table.append(direct,rules[i][1]);
+ table.append(proxy,rules[i][2]);
+ }
+
+ if(fromUpdater && !..table.find(proxy,"91.108.56.0/22") ){
+ // https://ipinfo.io/AS44907 https://ipinfo.io/AS59930 https://ipinfo.io/AS62041
+ table.push(proxy,
+ "149.154.160.0/22",
+ "149.154.164.0/22",
+ "149.154.172.0/22",
+ "91.108.4.0/22",
+ "91.108.20.0/22",
+ "91.108.56.0/22",
+ "91.108.8.0/22",
+ "95.161.64.0/20",
+ "91.108.12.0/22"
+ )
+ }
+
+ winform.editPacProxy.text = web.json.stringify(proxy,true)
+ winform.editPacDirect.text = web.json.stringify(direct,true)
+}
+
+
+winform.btnUpdate.oncommand = function(id,event){
+ winform.btnUpdate.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'};
+
+ thread.invoke(
+ function(winform){
+ import web.rest.github;
+ var result = web.rest.github.getContent("petronny","gfwlist2pac","gfwlist.pac");
+ if( result ){
+ var jsTestHost = /***
+function testHost(host, index) {
+ if( /^\d+\.\d+\.\d+\.\d+$/.test(host) && ( typeof isInNetEx !== "undefined" ) ){
+ for (var i = 0; i < rules[index].length; i++) {
+ for (var j = 0; j < rules[index][i].length; j++) {
+ lastRule = rules[index][i][j];
+ if(host == lastRule || host.endsWith('.' + lastRule) || ( lastRule.indexOf("/") && isInNetEx(host, lastRule) ) ){
+ return i % 2 == 0 ? 'DIRECT' : proxy;
+ }
+ }
+ }
+ return;
+ }
+
+ for (var i = 0; i < rules[index].length; i++) {
+ for (var j = 0; j < rules[index][i].length; j++) {
+ lastRule = rules[index][i][j];
+ if (host == lastRule || host.endsWith('.' + lastRule))
+ return i % 2 == 0 ? 'DIRECT' : proxy;
+ }
+ }
+ lastRule = '';
+}
+***/
+ var result = string.replace(result,"function\s*testHost\s*%\(\)\s*%\{\}",jsTestHost);
+
+ winform.loadPacToEdit( result,true );
+ winform.editPacDirect.modified = true;
+ winform.btnSave.disabled = false;
+ winform.btnReset.disabled = false;
+ winform.msgOk("PAC 已同步到最新版本,请点击「保存 PAC」按钮");
+ }
+ else {
+ winform.msgFrown("PAC 更新失败,建议开启全局代理后重试。")
+ }
+ winform.btnUpdate.disabledText = null;
+ },winform
+ )
+}
+
+import sysProxy;
+import string.conv;
+import v2ray.pacServer;
+winform.savePacToFile = function(){
+ var proxy = web.json.tryParse(string.conv.fromWide(winform.editPacProxy.text))
+ var direct = web.json.tryParse(string.conv.fromWide(winform.editPacDirect.text))
+ if(!(table.isArray(proxy))) {
+ winform.btnSave.disabledText = null;
+ return winform.msgErr("代理域名配置格式错误");
+ }
+ if(!(table.isArray(direct))) {
+ winform.btnSave.disabledText = null;
+ return winform.msgErr("直连域名配置格式错误");
+ }
+
+ v2ray.pacServer.savePacText(web.json.stringify({{direct;proxy}},true));
+
+ winform.editPacDirect.modified = false;
+ winform.editPacProxy.modified = false;
+ sysProxy.reset(true);
+
+ winform.msgOk("已保存 PAC 文件",1200);
+ winform.btnSave.disabledText = null;
+ winform.btnSave.disabled = true;
+ winform.btnReset.disabled = true;
+}
+
+winform.btnSave.oncommand = function(id,event){
+ winform.btnSave.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'};
+
+ thread.invoke(
+ function(winform){
+ sleep(300)
+ winform.savePacToFile();
+
+ },winform
+ )
+}
+
+winform.btnReset.oncommand = function(id,event){
+ winform.btnReset.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'};
+
+ thread.invoke(
+ function(winform){
+ import v2ray.pacServer;
+ winform.loadPacToEdit(v2ray.pacServer.loadPacText());
+
+ winform.btnReset.disabledText = null;
+ winform.btnSave.disabled = true;
+ winform.btnReset.disabled = true;
+ winform.msgOk("已恢复到当前 PAC 配置")
+ },winform
+ )
+}
+
+import v2ray.pacServer;
+winform.loadPacToEdit( v2ray.pacServer.loadPacText() );
+
+winform.editPacProxy.modified = false;
+winform.editPacDirect.modified = false;
+winform.btnSave.disabled = true;
+winform.btnReset.disabled = true;
+
+winform.editPacDirect.limit = -1;
+winform.editPacDirect.onChange = function(){
+ winform.btnSave.disabled = false;
+ winform.btnReset.disabled = false;
+}
+
+winform.editPacProxy.limit = -1;
+winform.editPacProxy.onChange = function(){
+ winform.btnSave.disabled = false;
+ winform.btnReset.disabled = false;
+}
+
+import process;
+winform.lbTip.oncommand = function(id,event){
+ process.openUrl("https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Proxy_servers_and_tunneling/Proxy_Auto-Configuration_(PAC)_file")
+}
+
+winform.editPacDirect.wndproc = function(hwnd,message,wParam,lParam){
+ if(message == 0x202/*_WM_LBUTTONUP*/){
+ var lineIndex = winform.editPacDirect.lineFromChar();
+ if(lineIndex == winform.editPacDirect.preLineIndex){
+ return;
+ }
+ winform.editPacDirect.preLineIndex = lineIndex;
+
+ var line = winform.editPacDirect.lineText();
+ var domain = string.match(line,`\"(.+)\"`);
+
+ if(domain){
+ winform.editPacDomain.text = domain;
+ winform.radioDirect.checked = true;
+ }
+ }
+}
+
+winform.editPacProxy.wndproc = function(hwnd,message,wParam,lParam){
+ if(message == 0x202/*_WM_LBUTTONUP*/){
+ var lineIndex = winform.editPacProxy.lineFromChar();
+ if(lineIndex == winform.editPacProxy.preLineIndex){
+ return;
+ }
+ winform.editPacProxy.preLineIndex = lineIndex;
+
+ var line = winform.editPacProxy.lineText();
+ var domain = string.match(line,`\"(.+)\"`);
+
+ if(domain){
+ winform.editPacDomain.text = domain;
+ winform.radioProxy.checked = true;
+ }
+ }
+}
+
+import win.dlg.findReplace;
+var findDlgDirect = win.dlg.findReplace(winform);
+
+findDlgDirect.onSearch = function(findWhat,down,matchCase,wholeWord){
+ winform.currentEditPac.findText(findWhat,findDlgDirect.flags);
+}
+
+findDlgDirect.onReplace = function(findWhat,replaceWith,down,matchCase,wholeWord){
+ winform.currentEditPac.replaceText(findWhat,replaceWith,findDlgDirect.flags);
+}
+
+findDlgDirect.onReplaceAll = function(findWhat,replaceWith,down,matchCase,wholeWord){
+ winform.currentEditPac.replaceAll(findWhat,replaceWith,findDlgDirect.flags)
+}
+
+winform.editPacDirect.enablePopMenu(function(){
+ var items = {
+ { "查找 Ctrl + F";
+ function(id){
+ findDlgDirect.find(winform.editPacDirect.selText)
+ }
+ };
+ { "替换 Ctrl + H";
+ function(id){
+ findDlgDirect.replace(winform.editPacDirect.selText);
+ }
+ };
+ {};
+ { "自剪贴板导入直连域名或 CIDR 格式 IP 段";
+ function(id){
+ var proxy = web.json.tryParse(string.conv.fromWide(winform.editPacProxy.text))
+ var direct = web.json.tryParse(string.conv.fromWide(winform.editPacDirect.text))
+ if(!(proxy)) return winform.msgErr("代理域名配置格式错误");
+ if(!(direct)) return winform.msgErr("直连域名配置格式错误");
+
+ import win.clip;
+ var str = win.clip.read();
+ if(!str){
+ return winform.msgWarn("请先复制域名或CIDR格式IP段到剪贴板(支持任意空白分隔符)");
+ }
+
+ var count,ignored = 0,0;
+ for domain in string.gmatch(str,"\w<[\w-_]*\.>+\w{1,8}") {
+
+ if(!table.indexOf(proxy,domain) && table.indexOf(direct,domain) ){
+ ignored++;
+ continue;
+ }
+
+ proxy = table.filter(proxy,lambda(v) v!=domain);
+ if(!table.indexOf(direct,domain)){
+ table.unshift(direct,domain)
+ }
+ count++;
+ }
+
+ //CIDR IP
+ for cidrIp in string.gmatch(str,"\d+\.\d+\.\d+\.\d+<\/\d+>*") {
+
+ if(!table.indexOf(direct,cidrIp) && table.indexOf(proxy,cidrIp) ){
+ ignored++;
+ continue;
+ }
+
+ direct = table.filter(direct,lambda(v) v!=cidrIp);
+ if(!table.indexOf(proxy,cidrIp)){
+ table.unshift(proxy,cidrIp)
+ }
+ count++;
+ }
+
+ winform.editPacProxy.text = web.json.stringify(proxy,true)
+ winform.editPacDirect.text = web.json.stringify(direct,true)
+ winform.editPacProxy.modified = true;
+ winform.editPacDirect.modified = true;
+ winform.msgInfo('已成功导入 '+count+' 个直连域名或 IP 段,\r\n'
+ + ignored + '个域名已经是直连域名无需添加。\r\n下一步请点下面的「保存PAC」按钮。',1500);
+ }
+ };
+ { "重置为默认 PAC";
+ function(id){
+ import v2ray.pacServer;
+ v2ray.pacServer.resetPac();
+ winform.loadPacToEdit(v2ray.pacServer.loadPacText());
+ }
+ };
+ { "恢复为当前使用的 PAC";
+ function(id){
+ import v2ray.pacServer;
+ winform.loadPacToEdit(v2ray.pacServer.loadPacText());
+ }
+ };
+ }
+ return items;
+});
+
+winform.editPacProxy.enablePopMenu(function(){
+ var items = {
+ { "查找 Ctrl + F";
+ function(id){
+ findDlgDirect.find(winform.editPacProxy.selText)
+ }
+ };
+ { "替换 Ctrl + H";
+ function(id){
+ findDlgDirect.replace(winform.editPacProxy.selText);
+ }
+ };
+ {};
+ { "自剪贴板导入代理域名或 CIDR 格式 IP 段";
+ function(id){
+ var proxy = web.json.tryParse(string.conv.fromWide(winform.editPacProxy.text))
+ var direct = web.json.tryParse(string.conv.fromWide(winform.editPacDirect.text))
+ if(!(proxy)) return winform.msgErr("代理域名配置格式错误");
+ if(!(direct)) return winform.msgErr("直连域名配置格式错误");
+
+ import win.clip;
+ var str = win.clip.read();
+ if(!str){
+ return winform.msgWarn("请先复制域名或 CIDR 格式 IP 段到剪贴板(支持任意空白分隔符)");
+ }
+
+ var count,ignored = 0,0;
+ for domain in string.gmatch(str,"\w<[\w-_]*\.>+\w{1,8}") {
+
+ if(!table.indexOf(direct,domain) && table.indexOf(proxy,domain) ){
+ ignored++;
+ continue;
+ }
+
+ direct = table.filter(direct,lambda(v) v!=domain);
+ if(!table.indexOf(proxy,domain)){
+ table.unshift(proxy,domain)
+ }
+ count++;
+ }
+
+ //CIDR IP
+ for cidrIp in string.gmatch(str,"\d+\.\d+\.\d+\.\d+<\/\d+>*") {
+
+ if(!table.indexOf(direct,cidrIp) && table.indexOf(proxy,cidrIp) ){
+ ignored++;
+ continue;
+ }
+
+ direct = table.filter(direct,lambda(v) v!=cidrIp);
+ if(!table.indexOf(proxy,cidrIp)){
+ table.unshift(proxy,cidrIp)
+ }
+ count++;
+ }
+
+
+ winform.editPacProxy.text = web.json.stringify(proxy,true)
+ winform.editPacDirect.text = web.json.stringify(direct,true)
+ winform.editPacProxy.modified = true;
+ winform.editPacDirect.modified = true;
+ winform.msgInfo('已成功导入 '+count+' 个代理域名或 IP 段,\r\n'
+ + ignored + '个域名已经是代理域名无需添加。\r\n下一步请点下面的「保存PAC」按钮。',1500);
+ }
+ };
+
+ { "导入所有 Telegram IP";
+ function(id){
+ var proxy = web.json.tryParse(string.conv.fromWide(winform.editPacProxy.text))
+ if(!(proxy)) return winform.msgErr("代理域名配置格式错误");
+
+ if( !..table.find(proxy,"91.108.56.0/22") ){
+ // https://ipinfo.io/AS44907 https://ipinfo.io/AS59930 https://ipinfo.io/AS62041
+ table.push(proxy,
+ "149.154.160.0/22",
+ "149.154.164.0/22",
+ "149.154.172.0/22",
+ "91.108.4.0/22",
+ "91.108.20.0/22",
+ "91.108.56.0/22",
+ "91.108.8.0/22",
+ "95.161.64.0/20",
+ "91.108.12.0/22"
+ )
+
+ winform.editPacProxy.text = web.json.stringify(proxy,true)
+ winform.msgOk('已成功导入所有 Telegram IP\r\n下一步请点下面的「保存PAC」按钮。')
+ }
+ else {
+ winform.msgWarn("代理 IP 段已包含所有 Telegram IP,不需要重复导入!")
+ }
+
+ }
+ };
+ { /*分隔符*/ };
+ { "重置为默认 PAC";
+ function(id){
+ import v2ray.pacServer;
+ v2ray.pacServer.resetPac();
+ winform.loadPacToEdit(v2ray.pacServer.loadPacText());
+ }
+ };
+ { "恢复为当前使用的 PAC";
+ function(id){
+ import v2ray.pacServer;
+ winform.loadPacToEdit(v2ray.pacServer.loadPacText());
+ }
+ };
+ }
+ return items;
+});
+
+
+import win.ui.accelerator;
+var accelerator = win.ui.accelerator({
+
+ {
+ ctrl = true; vkey = 'F'#;
+ oncommand = function() findDlgDirect.find(winform.currentEditPac.selText);
+ };
+
+ {
+ ctrl = true; vkey = 'H'#;
+ oncommand = function() findDlgDirect.replace(winform.currentEditPac.selText);
+ };
+
+},winform );
+
+winform.btnDeleteDomain.oncommand = function(id,event){
+ var domain = winform.editPacDomain.text;
+ if(!#domain){
+ return winform.editPacDomain.editBox.showErrorTip(,"请先指定域名")
+ }
+
+ var proxy = web.json.tryParse(string.conv.fromWide(winform.editPacProxy.text))
+ var direct = web.json.tryParse(string.conv.fromWide(winform.editPacDirect.text))
+ if(!(table.isArray(proxy))) return winform.msgErr("代理域名配置格式错误:不是有效的 JSON 数组。");
+ if(!(table.isArray(direct))) return winform.msgErr("直连域名配置格式错误:不是有效的 JSON 数组");
+
+ if(!table.indexOf(proxy,domain) && !table.indexOf(direct,domain) ){
+ winform.editPacDomain.editBox.showInfoTip(,"PAC 配置不包含此域名")
+ return;
+ }
+
+ direct = table.filter(direct,lambda(v) v!=domain);
+ proxy = table.filter(proxy,lambda(v) v!=domain);
+
+ winform.editPacProxy.text = web.json.stringify(proxy,true);
+ winform.editPacDirect.text = web.json.stringify(direct,true);
+ winform.editPacProxy.modified = true;
+ winform.editPacDirect.modified = true;
+ winform.btnUpdate.disabled = false;
+ winform.editPacDomain.editBox.showInfoTip(,"已移除此域名");
+}
+
+winform.btnAddDomain.oncommand = function(id,event){
+ var proxy = web.json.tryParse(string.conv.fromWide(winform.editPacProxy.text))
+ var direct = web.json.tryParse(string.conv.fromWide(winform.editPacDirect.text))
+ if(!(table.isArray(proxy))) return winform.msgErr("代理域名配置格式错误:不是有效的JSON数组。");
+ if(!(table.isArray(direct))) return winform.msgErr("直连域名配置格式错误:不是有效的JSON数组");
+
+ var domain = winform.editPacDomain.text;
+ if(!#domain){
+ return winform.editPacDomain.editBox.showErrorTip(,"请先指定域名")
+ }
+
+ if(winform.radioProxy.checked){
+ if(!table.indexOf(direct,domain) && table.indexOf(proxy,domain) ){
+ winform.editPacDomain.editBox.showWarningTip(,"此域名已经是代理域名,无需添加")
+ return;
+ }
+
+ direct = table.filter(direct,lambda(v) v!=domain);
+ if(!table.indexOf(proxy,domain)){
+ table.unshift(proxy,domain)
+ }
+ winform.editPacDomain.editBox.showInfoTip(,"已添加到代理域名");
+ }
+ else {
+ if(table.indexOf(direct,domain) && !table.indexOf(proxy,domain) ){
+ winform.editPacDomain.editBox.showWarningTip(,"此域名已经是直连域名,无需添加")
+ return;
+ }
+
+ proxy = table.filter(proxy,lambda(v) v!=domain);
+ if(!table.indexOf(direct,domain)){
+ table.unshift(direct,domain)
+ }
+ winform.editPacDomain.editBox.showInfoTip(,"已添加到直连域名");
+ }
+
+ winform.editPacProxy.text = web.json.stringify(proxy,true)
+ winform.editPacDirect.text = web.json.stringify(direct,true)
+ winform.editPacProxy.modified = true;
+ winform.editPacDirect.modified = true;
+ winform.btnUpdate.disabled = false;
+}
+
+winform.onClose = function(hwnd,message,wParam,lParam){
+ if(winform.editPacDirect.modified||winform.editPacProxy.modified){
+ winform.btnUpdate.disabled = true;
+
+ if(!winform.msgAsk("PAC 配置已修改但尚未保存,确定要退出并放弃更改吗?")){
+ return true;
+ }
+ }
+}
+
+winform.onDestroy = function(){
+ if(mainForm){
+ win.setActive(mainForm.hwnd);
+ win.setForeground(mainForm.hwnd);
+ }
+}
+
+import win.clip;
+winform.onActivate = function(state,hwndOther,minimized){
+ if(state){
+ if(#winform.editPacDomain.text){
+ return;
+ }
+
+ var str = win.clip.read();
+ if(str){
+ var domain = string.match(str,"\w<[\w-_]*\.>+\w{1,8}");
+ if(domain){
+ winform.editPacDomain.text = domain;
+
+ var proxy = web.json.tryParse(string.conv.fromWide(winform.editPacProxy.text))
+ if( (proxy)) {
+ winform.radioProxy.checked = table.indexOf(proxy,domain);
+ winform.radioDirect.checked = !winform.radioProxy.checked;
+ }
+ }
+ }
+ }
+}
+
+import inet.url;
+winform.editPacDomain.editBox.onChange = function(){
+ var url = owner.text;
+ if(string.startWith(url,"http:",true) || string.startWith(url,"https:",true) ){
+ var tUrl = inet.url.split(url);
+ if(tUrl && #tUrl.host){
+ owner.text = tUrl.host;
+ owner.setFocus();
+ }
+ }
+}
+
+winform.enableDpiScaling();
+winform.show();
+win.loopMessage();
+
+return winform;
\ No newline at end of file
diff --git a/forms/main/tools/github.aardio b/forms/main/tools/github.aardio
new file mode 100644
index 0000000..eb7b218
--- /dev/null
+++ b/forms/main/tools/github.aardio
@@ -0,0 +1,241 @@
+//RUNAS//github优化
+import fonts.fontAwesome;
+import win.ui;
+/*DSG{{*/
+var winform = win.form(text="github.com 网速优化工具";right=655;bottom=281;bgcolor=16777215;border="none";max=false)
+winform.add(
+bk={cls="bk";left=0;top=0;right=659;bottom=34;bgcolor=12632256;z=8};
+cmbIpCidrs={cls="combobox";left=49;top=111;right=328;bottom=137;edge=1;items={};mode="dropdown";z=1};
+editIpCurrent={cls="edit";left=118;top=206;right=366;bottom=230;edge=1;z=5};
+plusExploreHosts={cls="plus";text='\uF07C 编辑hosts文件';left=450;top=204;right=607;bottom=235;bgcolor=-6371181;font=LOGFONT(h=-15;name='FontAwesome';charset=0);notify=1;z=7};
+plusUpdateDns={cls="plus";text='\uF0AD 更改github.com解析到选定IP / 并更新图像等服务器IP';left=77;top=158;right=563;bottom=189;bgcolor=-6371181;font=LOGFONT(h=-15;name='FontAwesome';charset=0);notify=1;z=3};
+plusUpdateIps={cls="plus";text='\uF021 获取最新IP列表 / 测速';left=345;top=108;right=607;bottom=139;bgcolor=-6371181;font=LOGFONT(h=-15;name='FontAwesome';charset=0);notify=1;z=2};
+static={cls="static";text="本工具优化无代理时直连 Github 官网访问当前速度最快的服务器,
+可解决无法下载更新 V2Ray Core / SSR Core ,无法显示 Github 上的图像等问题。";left=49;top=45;right=635;bottom=93;font=LOGFONT(h=-13);transparent=1;z=4};
+static2={cls="static";text="当前指向IP:";left=27;top=208;right=111;bottom=228;align="right";transparent=1;z=6}
+)
+/*}}*/
+
+winform.cmbIpCidrs.onListChange = function(){
+ winform.setTimeout(
+ function(){
+ var ip = string.match(winform.cmbIpCidrs.selText,"\d+\.\d+\.\d+\.\d+");
+ if(!ip){
+ return ;
+ }
+ winform.plusUpdateDns.text = "更改 github.com 域名解析到:" + ip
+ }
+ );
+}
+
+import wsock;
+import fsys.config;
+config = fsys.config( io.appData("/aardio/github-ip-tools/") );
+winform.plusUpdateIps.oncommand = function(id,event){
+ winform.editIpCurrent.text = wsock.getIp("www.github.com")
+
+ winform.plusUpdateIps.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'}
+ winform.text = "请稍候,正在测试github.com所有可用IP的响应速度"
+
+ var metaInfo = win.invoke(
+ function(){
+ import win;
+ import web.rest.jsonClient;
+ var http = web.rest.jsonClient();
+ var github = http.api("https://api.github.com/")
+
+ return github.meta.get() : { git = {
+ "192.30.252.0";
+ "185.199.108.0";
+ "140.82.112.0";
+ "13.114.40.48";
+ "13.229.188.59";
+ "13.234.176.102";
+ "13.234.210.38";
+ "13.236.229.21";
+ "13.237.44.5";
+ "13.250.177.223";
+ "15.164.81.167";
+ "18.194.104.89";
+ "18.195.85.27";
+ "35.159.8.160";
+ "52.192.72.89";
+ "52.64.108.95";
+ "52.69.186.44";
+ "52.74.223.119";
+ "52.78.231.108"
+ } };
+ }
+ )
+
+ if(metaInfo[["git"]]){
+ config.meta.data = table.map(metaInfo.git,lambda(v)..string.match(v,"^\d+\.\d+\.\d+\.\d+"))
+ }
+ elseif(!config.meta.data){
+ winform.msgboxErr("您的操作系统版本过低")
+ }
+
+ var pingThread = function( ip ) {
+ import wsock.tcp.client;
+
+ var result = 0;
+ for(i=1;4;1){
+
+ var beginTick = ..time.tick()
+ var tcp = wsock.tcp.client()
+
+ tcp.setTimeouts(1000,1000);
+ if( ! tcp.connectTimeout(ip,80,2) ){
+ return;
+ };
+
+ sendData =/***********
+GET / HTTP/1.1
+Host: www.github.com
+Connection: close
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64)
+Accept: */*;
+Accept-Language: zh-CN,zh;
+Accept-Charset:utf-8;
+***********/
+ tcp.write( sendData + '\r\n\r\n' )
+
+ var rep = tcp.readAll();
+ tcp.close();
+
+ if( rep && ..string.startWith(rep,"HTTP/1.1 301 Moved Permanently") ){
+ result = result + ((..time.tick() - beginTick)/1000);
+ }
+ else {
+ return;
+ }
+
+ }
+
+ return ip,math.round(result/4,2);
+
+ }
+
+ import thread.manage;
+ manage = thread.manage(#config.meta.data)
+
+ var ipData = {}
+ for(k,ip in config.meta.data){
+ manage.createSuspended(pingThread,ip).onEnd = function(ip,sec){
+ if(ip && sec!==null ) {
+ table.push(ipData,ip + " 响应速度:" + sec + "秒");
+ winform.cmbIpCidrs.items = ipData;
+ winform.cmbIpCidrs.selIndex = 1;
+ }
+ }
+ }
+
+ manage.resume();
+ manage.waitClose();
+
+ winform.cmbIpCidrs.items = ipData;
+ winform.cmbIpCidrs.selIndex = 1;
+ winform.cmbIpCidrs.onListChange();
+
+ winform.text = "github.com 网速优化工具"
+ winform.plusUpdateIps.disabledText = null;
+}
+
+import fsys.hosts;
+winform.plusUpdateDns.oncommand = function(id,event){
+ var ip = winform.cmbIpCidrs.text;
+ if(!#ip){
+ winform.msgboxErr("请选选择IP地址")
+ return;
+ }
+
+ ip = string.match(ip,"\d+\.\d+\.\d+\.\d+");
+ if( ip == winform.editIpCurrent.text ) return winform.msgboxErr("域名之前已经解析到该IP地址")
+
+ winform.plusUpdateDns.disabledText = "正在更新IP"
+
+ var githubIps = {
+ ["www.github.com"] = ip;
+ ["github.com"] = ip;
+ }
+
+ import web.rest.jsonLiteClient;
+ var http = web.rest.jsonLiteClient();
+ var ipApi = http.api("http://ip-api.com/json");
+ var data = ipApi["raw.githubusercontent.com"].get();
+ if(data[["query"]]){
+ githubIps["raw.github.com"] = data[["query"]];
+ githubIps["assets-cdn.github.com"] = data[["query"]];
+ githubIps["raw.githubusercontent.com"] = data[["query"]];
+ githubIps["gist.githubusercontent.com"] = data[["query"]];
+ githubIps["cloud.githubusercontent.com"] = data[["query"]];
+ githubIps["camo.githubusercontent.com"] = data[["query"]];
+ githubIps["avatars0.githubusercontent.com"] = data[["query"]];
+ githubIps["avatars1.githubusercontent.com"] = data[["query"]];
+ githubIps["avatars2.githubusercontent.com"] = data[["query"]];
+ githubIps["avatars3.githubusercontent.com"] = data[["query"]];
+ githubIps["avatars4.githubusercontent.com"] = data[["query"]];
+ githubIps["avatars5.githubusercontent.com"] = data[["query"]];
+ githubIps["avatars6.githubusercontent.com"] = data[["query"]];
+ githubIps["avatars7.githubusercontent.com"] = data[["query"]];
+ githubIps["avatars8.githubusercontent.com"] = data[["query"]];
+ githubIps["marketplace-screenshots.githubusercontent.com"] = data[["query"]];
+ githubIps["repository-images.githubusercontent.com"] = data[["query"]];
+ githubIps["user-images.githubusercontent.com"] = data[["query"]];
+ githubIps["desktop.githubusercontent.com"] = data[["query"]];
+ }
+
+ fsys.hosts.ownCacls();
+ fsys.hosts.update(githubIps);
+
+ win.delay(1000);
+ winform.editIpCurrent.text = wsock.getIp("www.github.com");
+ winform.plusUpdateDns.disabledText = null;
+
+ if( ip != winform.editIpCurrent.text ){
+ winform.msgboxErr("修改hosts文件失败,如果hosts文件被其他软件锁定时请先解除锁定,也可以搜索网上教程试试设置文件权限")
+ }
+}
+
+winform.plusExploreHosts.skin(
+ background = {
+ hover = "/res/images/btn-hover.png";
+ focus = "/res/images/btn-focus.jpg";
+ active = "/res/images/btn-active.png";
+ disabled = "/res/images/btn-disabled.png";
+ }
+)
+winform.plusExploreHosts.oncommand = function(id,event){
+ import process;
+ process.execute("notepad.exe",fsys.hosts.path,"runas")
+}
+
+winform.plusUpdateDns.skin({
+ background={
+ default=0xFF93C89E;
+ hover=0xFF928BB3
+ }
+})
+
+winform.plusUpdateIps.skin({
+ background={
+ default=0xFF93C89E;
+ hover=0xFF928BB3
+ }
+})
+
+winform.plusExploreHosts.skin({
+ background={
+ default=0xFF93C89E;
+ hover=0xFF928BB3
+ }
+})
+
+import win.ui.simpleWindow2;
+win.ui.simpleWindow2(winform);
+
+winform.enableDpiScaling();
+winform.show()
+winform.plusUpdateIps.oncommand();
+
+win.loopMessage();
diff --git a/forms/main/tools/qr.aardio b/forms/main/tools/qr.aardio
new file mode 100644
index 0000000..82db4fd
--- /dev/null
+++ b/forms/main/tools/qr.aardio
@@ -0,0 +1,71 @@
+import win.ui;
+import win.ui.atom;
+import fonts.fontAwesome;
+/*DSG{{*/
+var winform = win.form(text="winXray - 二维码生成工具";right=730;bottom=678;bgcolor=16777215;border="none";exmode="none";mode="popup")
+winform.add(
+bk={cls="bk";left=-6;top=-2;right=734;bottom=27;bgcolor=12632256;z=10};
+btnQrEnode={cls="plus";text="生成二维码";left=562;top=565;right=694;bottom=595;align="left";bgcolor=14935259;db=1;dr=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=22}};iconText='\uF1C4';notify=1;textPadding={left=40};z=9};
+editUrl={cls="plus";left=44;top=569;right=537;bottom=594;align="right";bgcolor=16777215;border={bottom=1;color=-8355712};db=1;dl=1;dr=1;editable="edit";font=LOGFONT(h=-16);textPadding={bottom=1};z=8};
+lbErrLevel={cls="static";text=" 0:L 可纠错7%数据码字";left=104;top=656;right=272;bottom=679;db=1;dl=1;transparent=1;z=6};
+lbVersion={cls="static";text="自动选择版本";left=466;top=656;right=672;bottom=679;db=1;dr=1;transparent=1;z=7};
+plus={cls="plus";left=28;top=49;right=708;bottom=522;bgcolor=16777215;db=1;dl=1;dr=1;dt=1;repeat="scale";z=1};
+static={cls="static";text="纠错级别:";left=13;top=624;right=97;bottom=651;align="right";db=1;dl=1;transparent=1;z=3};
+static2={cls="static";text="版本(大小):";left=353;top=624;right=437;bottom=651;align="right";db=1;dl=1;dr=1;transparent=1;z=5};
+static3={cls="static";text="winXray - 二维码生成工具";left=17;top=4;right=230;bottom=24;color=3947580;transparent=1;z=11};
+tbErrLevel={cls="trackbar";left=96;top=611;right=290;bottom=641;bgcolor=16777215;db=1;dl=1;max=3;min=0;z=2};
+tbVersion={cls="trackbar";left=439;top=611;right=703;bottom=641;bgcolor=16777215;db=1;dr=1;max=40;min=0;z=4}
+)
+/*}}*/
+
+import style;
+winform.btnQrEnode.skin(style.primaryButton);
+
+winform.tbErrLevel.oncommand = function(id,event,pos){
+
+ if( event == 0x8/*_TB_ENDTRACK*/ ){
+ pos = winform.tbErrLevel.pos;
+ var v = {[0]="L 可纠错7%数据码字";[1]="M 可纠错15%的数据码字";[2]="Q 可纠错25%的数据码字";[3]="H 可纠错30%的数据码字";}
+ winform.lbErrLevel.text = pos +":"+ v[pos];
+ }
+}
+
+winform.tbVersion.oncommand = function(id,event,pos){
+ if( event == 0x8/*_TB_ENDTRACK*/ ){
+ pos = winform.tbVersion.pos;
+ if(!pos)winform.lbVersion.text = "自动选择版本";
+ else {
+ var width = ((pos-1)*4)+21;
+ winform.lbVersion.text = string.format("版本:%d 二维码数据大小:%d x %d",pos,width,width );
+ }
+ }
+}
+
+import win.dlg.message;
+import qrencode.bitmap;
+winform.btnQrEnode.oncommand = function(id,event){
+ if(!#winform.editUrl.text){
+ return winform.msgErr("请先输入内容")
+ }
+
+ winform.plus.hide = true;
+ var qrBmp = qrencode.bitmap(winform.editUrl.text,winform.tbVersion.pos,winform.tbErrLevel.pos );
+ if(!qrBmp){
+ return winform.msgErr("请先输入内容")
+ }
+ winform.plus.setBackground(qrBmp.copyBitmap(winform.plus.width));
+
+ winform.plus.hide = false;
+ winform.plus.redraw()
+}
+
+winform.createQrCode = function(url){
+ winform.editUrl.text = url;
+ winform.btnQrEnode.oncommand();
+}
+
+import win.ui.simpleWindow2;
+win.ui.simpleWindow2(winform);
+
+winform.show()
+win.loopMessage();
diff --git a/forms/main/tools/tools.aardio b/forms/main/tools/tools.aardio
new file mode 100644
index 0000000..e606548
--- /dev/null
+++ b/forms/main/tools/tools.aardio
@@ -0,0 +1,277 @@
+import fonts.fontAwesome;
+import win.ui;
+/*DSG{{*/
+var winform = win.form(text="aardio form";right=938;bottom=638;bgcolor=16777215)
+winform.add(
+btnAardio={cls="plus";text="aardio 桌面软件快速开发( 开发环境仅 6.5MB )";left=26;top=533;right=460;bottom=575;align="left";color=3947580;dl=1;dt=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-27;name='FontAwesome');padding={left=18}};iconText='\uF17A';notify=1;textPadding={left=50};z=3};
+btnCreateLnk={cls="plus";text="创建桌面图标";left=26;top=391;right=205;bottom=433;align="left";color=3947580;dl=1;dt=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-23;name='FontAwesome');padding={left=18}};iconText='\uF108';notify=1;textPadding={left=50};z=10};
+btnDeleteIconCache={cls="plus";text="修复桌面图标空白";left=26;top=439;right=269;bottom=481;align="left";color=3947580;dl=1;dt=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-23;name='FontAwesome');padding={left=18}};iconText='\uF0AD';notify=1;textPadding={left=50};z=16};
+btnDnsFlush={cls="plus";text="清空 DNS 缓存";left=26;top=155;right=412;bottom=197;align="left";color=3947580;dl=1;dt=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-27;name='FontAwesome');padding={left=18}};iconText='\uF021';notify=1;textPadding={left=50};z=5};
+btnGitHub={cls="plus";text="Github 网速优化";left=26;top=250;right=262;bottom=292;align="left";color=3947580;dl=1;dt=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-27;name='FontAwesome');padding={left=18}};iconText='\uF09B';notify=1;textPadding={left=50};z=2};
+btnQrCode={cls="plus";text="二维码生成工具";left=26;top=297;right=262;bottom=339;align="left";color=3947580;dl=1;dt=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-27;name='FontAwesome');padding={left=18}};iconText='\uF029';notify=1;textPadding={left=50};z=14};
+btnSshInstall={cls="plus";text="一键安装 V2Ray 服务端";left=393;top=14;right=601;bottom=56;align="left";color=3947580;dl=1;dt=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-27;name='FontAwesome');padding={left=11}};iconText='\uF17C';notify=1;textPadding={left=40};z=9};
+btnSshInstallKey={cls="plus";text="安装SSH密钥";left=606;top=15;right=755;bottom=57;align="left";color=3947580;dl=1;dt=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-24;name='FontAwesome');padding={left=11}};iconText='\uF084';notify=1;textPadding={left=40};z=11};
+btnTestSpeed={cls="plus";text="当前代理服务器测速";left=26;top=61;right=244;bottom=103;align="left";color=3947580;dl=1;dt=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-24;name='FontAwesome');padding={left=18}};iconText='\uF0ED';notify=1;textPadding={left=50};z=12};
+btnUpdateSystemTime={cls="plus";text="同步系统时间( 修正 V2Ray 连接报错 )";left=26;top=108;right=412;bottom=150;align="left";color=3947580;dl=1;dt=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-27;name='FontAwesome');padding={left=18}};iconText='\uF017';notify=1;textPadding={left=50};z=4};
+btnUuid={cls="plus";text="UUID 生成工具";left=26;top=344;right=262;bottom=386;align="left";color=3947580;dl=1;dt=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-27;name='FontAwesome');padding={left=18}};iconText='\uF13E';notify=1;textPadding={left=50};z=15};
+btnWubiLex={cls="plus";text="WIN10 五笔助手(仅830KB,自带五笔86、98、091、新世纪、郑码……)";left=26;top=486;right=661;bottom=528;align="left";color=3947580;dl=1;dt=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-24;name='FontAwesome');padding={left=18}};iconText='\uF11C';notify=1;textPadding={left=50};z=6};
+btnYoutube={cls="plus";text="Youtube 视频下载工具";left=26;top=203;right=262;bottom=245;align="left";color=3947580;dl=1;dt=1;font=LOGFONT(h=-16);iconStyle={align="left";font=LOGFONT(h=-27;name='FontAwesome');padding={left=18}};iconText='\uF167';notify=1;textPadding={left=50};z=1};
+editSshHost={cls="plus";left=158;top=23;right=386;bottom=47;align="left";bgcolor=16777215;border={bottom=1;color=-8355712};dl=1;dt=1;editable="edit";font=LOGFONT(h=-16);textPadding={bottom=1};z=7};
+lbCurrentProxyLocation={cls="static";left=245;top=74;right=729;bottom=101;color=32768;dl=1;dt=1;transparent=1;z=13};
+lbTip={cls="static";text="友情提醒:winXray 不会注册任何域名,谨防冒充官网的钓鱼网站!!!";left=227;top=603;right=918;bottom=630;align="right";color=5921370;db=1;dr=1;font=LOGFONT(h=-13);transparent=1;z=17};
+static={cls="static";text="账号@服务器:";left=36;top=27;right=151;bottom=54;align="right";color=4934475;dl=1;dt=1;font=LOGFONT(h=-13);transparent=1;z=8}
+)
+/*}}*/
+
+import style;
+winform.btnYoutube.skin(style.plainButton);
+
+var frmYoutube;
+winform.btnYoutube.oncommand = function(id,event){
+ if(frmYoutube&&win.isWindow(frmYoutube.hwnd)){
+ if(win.isIconic(frmYoutube.hwnd)){
+ frmYoutube.show(9/*_SW_RESTORE*/);
+ }
+
+ frmYoutube.show();
+ return;
+ }
+
+ frmYoutube = winform.loadForm("\forms\main\tools\youtube.aardio");
+ frmYoutube.show();
+}
+
+import process;
+winform.btnGitHub.skin(style.plainButton)
+winform.btnGitHub.oncommand = function(id,event){
+ if(_STUDIO_INVOKED){
+ winform.msgboxErr("请在发布后运行此功能");
+ return;
+ }
+
+ process.execute(io._exepath,"/github","runas");
+}
+
+winform.btnAardio.skin(style.plainButton)
+winform.btnAardio.oncommand = function(id,event){
+ process.openUrl("http://www.aardio.com")
+}
+
+winform.btnUpdateSystemTime.skin(style.plainButton)
+winform.btnUpdateSystemTime.oncommand = function(id,event){
+ if(_STUDIO_INVOKED){
+ winform.msgboxErr("请在发布后运行此功能");
+ return;
+ }
+
+ winform.btnUpdateSystemTime.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'}
+ if( process.executeWait(io._exepath,"/updateTime","runas") ){
+ winform.btnUpdateSystemTime.disabledText = null;
+ winform.btnUpdateSystemTime.text = '时间已同步'
+ winform.setTimeout(
+ function(){
+ winform.btnUpdateSystemTime.text = '同步系统时间( 修正 v2ray 连接报错 )'
+ },2000)
+ }
+ else {
+ winform.btnUpdateSystemTime.disabledText = null;
+ }
+}
+
+winform.btnDnsFlush.skin(style.plainButton)
+winform.btnDnsFlush.oncommand = function(id,event){
+ winform.btnDnsFlush.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'}
+
+ import process.popen;
+ var prcs = process.popen(,"ipconfig /flushdns");
+ var str = prcs.read(-1)
+
+ var dnsapi = ..raw.loadDll("dnsapi.dll");
+ dnsapi.DnsFlushResolverCacheB();
+
+ winform.msgInfo(str);
+ winform.btnDnsFlush.disabledText = null;
+}
+
+import process;
+winform.btnWubiLex.skin(style.plainButton)
+winform.btnWubiLex.oncommand = function(id,event){
+ process.openUrl("http://wubi.aardio.com/");
+}
+
+winform.editSshHost.setCueBannerText("root@0.0.0.0:22")
+winform.btnSshInstall.skin(style.plainButton)
+winform.btnSshInstall.oncommand = function(id,event){
+
+ if(_STUDIO_INVOKED){
+ winform.msgErr("请在发布后运行此功能");
+ return;
+ }
+
+ config.ui.sshServer = winform.editSshHost.text;
+ config.ui.save();
+
+ winform.btnSshInstall.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'}
+
+ var server = winform.editSshHost.text;
+ if( ! ..string.indexOf(server,"@") ){
+ server = "root@" + server;
+ }
+ process.execute(io._exepath,"/sshInstall " + server);
+ win.delay(1000);
+ winform.btnSshInstall.disabledText = null;
+}
+
+import config;
+if(config.ui.sshServer){
+ winform.editSshHost.text = config.ui.sshServer;
+}
+
+winform.btnSshInstallKey.skin(style.plainButton)
+winform.btnSshInstallKey.oncommand = function(id,event){
+ if(_STUDIO_INVOKED){
+ winform.msgErr("请在发布后运行此功能");
+ return;
+ }
+
+ config.ui.sshServer = winform.editSshHost.text;
+ config.ui.save();
+
+ winform.btnSshInstall.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'}
+
+ var server = winform.editSshHost.text;
+ if( ! ..string.indexOf(server,"@") ){
+ server = "root@" + server;
+ }
+ process.execute(io._exepath,"/sshInstallKey " + server);
+ win.delay(1000);
+ winform.btnSshInstall.disabledText = null;
+}
+
+winform.btnCreateLnk.skin(style.plainButton)
+winform.btnCreateLnk.oncommand = function(id,event){
+ if(_STUDIO_INVOKED){
+ return winform.msgboxErr("请在发布后使用此功能")
+ }
+
+ import fsys.lnk;
+ var lnk = fsys.lnk();
+ lnk.description = "winXray(V2Ray/V2Ray、Shadowsocks、Trojan通用客户端 )"
+
+ lnk.path = io._exepath //设置目标路径
+ lnk.setIcon(io._exepath,0); //设置图标
+
+ lnk.save(
+ io.getSpecial(0/*_CSIDL_DESKTOP*/,"winXray.lnk" )
+ )
+
+ ::Shell32.SHChangeNotify(0x8000000/*_SHCNE_ASSOCCHANGED*/,0,0,0);
+
+ import com;
+ com.CreateObject("Shell.Application").MinimizeAll();
+}
+
+winform.btnTestSpeed.skin(style.plainButton)
+winform.btnTestSpeed.oncommand = function(id,event){
+ import chrome.path;
+ var chromePath = chrome.path();
+ if(!chromePath){
+ winform.msgFrown('抱歉,\r\n测速工具需要调用Chrome或兼容浏览器才能运行,\r\n但是当前系统未找到任何Chrome兼容浏览器!');
+ return;
+ }
+
+ import v2ray.core;
+ if(!v2ray.core.socksProxyPort){
+ winform.msgFrown('抱歉,当前未连接到任何代理服务器!');
+ return;
+ }
+
+ winform.btnTestSpeed.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'}
+
+ var ipip = win.invoke(
+ function(port){
+ import web.rest.client;
+ var restClient = web.rest.client(,"SOCKS=127.0.0.1:"+port);
+ restClient._http.setTimeouts(1000,2000,2000);
+ restClient.get("https://www.google.com/generate_204");
+ var lastStatusCode = restClient.lastStatusCode;
+
+ if( lastStatusCode == 204 ){
+
+ var ipip,err = restClient.get("http://myip.ipip.net");
+ if(ipip){
+ ipip = ..string.match(ipip,"\d+\.\d+\.\d+\.\d+\A+");
+ if(ipip) {
+ restClient.close();
+ return "当前代理服务器:"+ipip;
+ }
+ }
+
+ restClient.close();
+ return null;
+ }
+ restClient.close();
+ },v2ray.core.socksProxyPort
+ )
+
+ if(!ipip){
+ winform.msgFrown('抱歉,当前未连接到任何代理服务器!');
+ winform.btnTestSpeed.disabledText = null;
+ return;
+ }
+
+ winform.lbCurrentProxyLocation.text = ipip;
+
+ import process
+ process.execute(chromePath,` --proxy-server="SOCKS5://127.0.0.1:`+v2ray.core.socksProxyPort
+ +`" --user-data-dir="` +io.appData("winXray/chrome-socks5")+ `" --app="https://speed.cloudflare.com/"`);
+ winform.btnTestSpeed.disabledText = null;
+}
+
+onActiveOutbound = function(address){
+ winform.btnTestSpeed.disabled = !address;
+ if(type.isString(address)){
+ winform.lbCurrentProxyLocation.text = "当前活动的代理服务器:" + address;
+ }
+}
+
+subscribe("activeOutbound",function(address){
+ onActiveOutbound(address)
+} )
+if(globalActiveOutbound){
+ onActiveOutbound(globalActiveOutbound)
+}
+
+winform.btnQrCode.skin(style.plainButton)
+winform.btnQrCode.oncommand = function(id,event){
+
+ var frmChild = winform.loadForm("\forms\main\tools\qr.aardio");
+ frmChild.show();
+
+}
+
+winform.btnUuid.skin(style.plainButton)
+winform.btnUuid.oncommand = function(id,event){
+ var frmChild = winform.loadForm("\forms\main\tools\uuid.aardio");
+ frmChild.show();
+}
+
+winform.btnDeleteIconCache.skin(style.plainButton)
+winform.btnDeleteIconCache.oncommand = function(id,event){
+ import fsys;
+ import process;
+
+ var explorerPath = process.kill("explorer.exe")
+ if( explorerPath ) {
+ fsys.delete(io.appData("iconcache.db"));
+ process.execute(explorerPath);
+
+ ::Shell32.SHChangeNotify(0x8000000/*_SHCNE_ASSOCCHANGED*/,0,0,0);
+ }
+}
+
+
+
+winform.enableDpiScaling();
+winform.show();
+win.loopMessage();
\ No newline at end of file
diff --git a/forms/main/tools/uuid.aardio b/forms/main/tools/uuid.aardio
new file mode 100644
index 0000000..a59218a
--- /dev/null
+++ b/forms/main/tools/uuid.aardio
@@ -0,0 +1,28 @@
+//GUID生成器
+import win.ui;
+import win.ui.menu;
+import win.guid;
+import win.clip;
+/*DSG{{*/
+var winform = win.form(text="UUID 生成器 - 已生成新的UUID";right=550;bottom=91;border="dialog frame";exmode="none";max=false;parent=...)
+winform.add(
+btnCpy={cls="button";text="复制到剪贴板";left=436;top=21;right=529;bottom=47;z=3};
+btnGenerant={cls="button";text="生成UUID";left=339;top=21;right=432;bottom=47;z=2};
+static={cls="static";text="UUID理论上能产生全球唯一的值";left=37;top=63;right=543;bottom=80;transparent=1;z=4};
+txtGuid={cls="edit";left=31;top=21;right=327;bottom=47;edge=1;multiline=1;z=1}
+)
+/*}}*/
+
+winform.btnCpy.oncommand = function(id,event){
+ win.clip.write(winform.txtGuid.text)
+}
+
+winform.btnGenerant.oncommand = function(id,event){
+ winform.txtGuid.text = string.lower( tostring(win.guid.create() ));
+}
+winform.btnGenerant.oncommand();
+
+winform.enableDpiScaling();
+winform.show(true)
+win.loopMessage();
+return winform;
diff --git a/forms/main/tools/uwpExemption.aardio b/forms/main/tools/uwpExemption.aardio
new file mode 100644
index 0000000..ffa60de
--- /dev/null
+++ b/forms/main/tools/uwpExemption.aardio
@@ -0,0 +1,240 @@
+//RUNAS//UWP本机隔离
+import win.ui;
+import win.ui.atom;
+import win.ui.menu;
+import fonts.fontAwesome;
+/*DSG{{*/
+var winform = win.form(text="UWP 应用 - 本机网络隔离工具";right=1150;bottom=666;bgcolor=16777215)
+winform.add(
+btnAllowLocalhostLoopback={cls="plus";text='\uF13E 允许所有应用访问本机网络';left=562;top=625;right=818;bottom=661;bgcolor=14609886;db=1;dr=1;font=LOGFONT(h=-16;name='FontAwesome');notify=1;tabstop=1;z=5};
+btnDisableLocalhostLoopback={cls="plus";text='\uF023 禁止所有应用访问本机网络';left=825;top=625;right=1081;bottom=661;bgcolor=14147583;db=1;dr=1;font=LOGFONT(h=-16;name='FontAwesome');notify=1;tabstop=1;z=6};
+listview={cls="listview";left=8;top=41;right=1138;bottom=617;acceptfiles=1;asel=false;bgcolor=16777215;db=1;dl=1;dr=1;dt=1;edge=1;font=LOGFONT(name='SimSun');fullRow=1;gridLines=1;hide=1;vscroll=1;z=1};
+plusLoading={cls="plus";left=368;top=195;right=739;bottom=457;color=15780518;db=1;dl=1;dr=1;dt=1;font=LOGFONT(h=-96;name='FontAwesome');z=2};
+plusSearch={cls="plus";left=727;top=3;right=1136;bottom=33;align="right";autohscroll=false;autovscroll=false;border={bottom=1;color=-4144960};dr=1;dt=1;editable=1;font=LOGFONT(h=-13);hide=1;textPadding={top=10;bottom=3};valign="top";z=3};
+tip={cls="static";text="单击列标题可排序,双击列表项可复制,右键点列表项可弹出菜单,回车搜索或刷新";left=13;top=626;right=552;bottom=655;db=1;dl=1;dr=1;transparent=1;z=4}
+)
+/*}}*/
+
+var atom,hwnd = winform.atom("winXray.762C7E32-3E75-42BE-8F4A-4B0E8AAC4EF0");
+if(!atom && hwnd){
+ win.showForeground(hwnd);
+ win.quitMessage(); return;
+}
+
+uiLanguage = {
+ displayName = "显示名称";
+ packageName = "完整包名";
+ localhost = "本机";
+ enabled = "允许";
+ disabled = "禁止";
+ searchCueBannerText = "输入应用名(支持模式匹配)";
+ exemptAll = '\uF13E 允许所有应用访问本机网络';
+ exemptNone = '\uF023 禁止所有应用访问本机网络';
+ allowLocalhostLoopback = "允许访问本机网络";
+ disableLocalhostLoopback = "禁止访问本机网络";
+ requiredWin10 = "本程序仅支持 WIN10";
+ run = "启动应用";
+ tip = "单击列标题可排序,双击列表项可复制,右键点列表项可弹出菜单,回车搜索或刷新";
+ title = "UWP 应用 - 本机网络隔离工具";
+}
+
+import win.ui.grid;
+var grid = win.ui.grid(winform.listview);
+
+var reloadItemData = function(){
+ thread.invoke(
+ function(uiLanguage,winform,grid){
+ winform.plusLoading.hide = false;
+ winform.plusSearch.hide = true;
+ winform.listview.hide = true;
+ winform.plusLoading.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'}
+
+ import sys.networkIsolation;
+ var exemptApps = sys.networkIsolation.getLoopbackState();
+ var dataTable = sys.networkIsolation.getAppContainers();
+
+ var word = string.trim(winform.plusSearch.text);
+ if(#word){
+ word = "@@" + word;
+ dataTable = table.filter(dataTable
+ ,lambda(v) string.find(v.displayName,word) || string.find(v.appContainerName,word)|| string.find(v.description,word) )
+
+ }
+
+ for(k,app in dataTable){
+ app.loopback = exemptApps[app.sid]?uiLanguage.enabled:uiLanguage.disabled;
+ }
+
+
+ dataTable.fields = {"displayName","appContainerName","loopback","sid"}
+ if(grid.sortCloumn){
+ var name = dataTable.fields[grid.sortCloumn];
+ if(name){
+ if(!grid.sortDesc){
+ table.sort(dataTable,function(b){
+ return owner[name] < b[name]
+ })
+ }
+ else {
+ table.sort(dataTable,function(b){
+ return owner[name] > b[name]
+ })
+ }
+ }
+ }
+
+ grid.setTable( dataTable )
+ sleep(300);
+
+ winform.plusLoading.disabledText = null;
+ winform.plusLoading.hide = true;
+ winform.listview.hide = false;
+ winform.plusSearch.hide = false;
+
+ winform.resize();
+
+ },uiLanguage,winform,grid
+ )
+}
+
+grid.onSortColumn = function(cloumn,desc){
+ grid.sortDesc = desc;
+ grid.sortCloumn = cloumn ;
+ reloadItemData();
+ return true;
+}
+
+grid.onEditChanged = function(text,iItem,iSubItem){
+ return false; //禁止编辑
+}
+
+winform.adjust = function( cx,cy,wParam ) {
+ winform.listview.fillParent();
+};
+
+import win.debounce;
+winform.plusSearch.editBox.onChange = win.debounce(function(){
+ if(#winform.plusSearch.text) reloadItemData();
+})
+
+import sys.networkIsolation
+var exemptUwpApp = function(exempted){
+ var sidConfigs = {};
+ for item,sid in winform.listview.eachSelected(4){
+ sidConfigs[sid] = exempted;
+ }
+ sys.networkIsolation.enableLoopback(sidConfigs);
+
+ var exemptApps = sys.networkIsolation.getLoopbackState();
+ for item,sid in winform.listview.eachSelected(4){
+ winform.listview.setItemText( exemptApps[sid]?uiLanguage.enabled:uiLanguage.disabled,item,3);
+ }
+}
+
+import com.shell;
+winform.listview.onnotify = function(id,code,ptr){
+
+ select(code) {
+ case 0xFFFFFFFB/*_NM_RCLICK*/ {
+
+ var x,y = win.getCursorPos();
+ winform.popmenu = win.ui.popmenu(winform);
+
+ if(1===#winform.listview.selected){
+ var item,path = winform.listview.getSelection(,2);
+ winform.popmenu.add(uiLanguage.run,function(id){
+ import com.shell;
+ com.shell.activateApp(path+"!App");
+ });
+ }
+
+ winform.popmenu.add(uiLanguage.allowLocalhostLoopback,function(id){
+ exemptUwpApp(true);
+ });
+
+ winform.popmenu.add(uiLanguage.disableLocalhostLoopback,function(id){
+ exemptUwpApp(false);
+ });
+
+ winform.popmenu.popup(x,y,true);
+ }
+ }
+}
+
+winform.btnAllowLocalhostLoopback.skin({
+ background={
+ default=0x669BCC9B;
+ hover=0xFF928BB3;
+ disabled=0xFFCCCCCC;
+ }
+})
+winform.btnAllowLocalhostLoopback.oncommand = function(id,event){
+ var sidConfigs = {};
+ for item,sid in winform.listview.each(0,0,4){
+ sidConfigs[sid] = true;
+ }
+ sys.networkIsolation.enableLoopback(sidConfigs);
+ reloadItemData();
+}
+
+winform.btnDisableLocalhostLoopback.skin({
+ background={
+ default=0x66FFA07D;
+ hover=0xFF928BB3;
+ disabled=0xFFCCCCCC;
+ }
+})
+winform.btnDisableLocalhostLoopback.oncommand = function(id,event){
+ var sidConfigs = {};
+ for item,sid in winform.listview.each(0,0,4){
+ sidConfigs[sid] = false;
+ }
+ sys.networkIsolation.enableLoopback(sidConfigs);
+ reloadItemData();
+}
+
+winform.onOk = function(){
+ winform.plusSearch.setFocus()
+}
+
+winform.plusSearch.setCueBannerText(uiLanguage.searchCueBannerText);
+winform.listview.setExtended(0x10000/*_LVS_EX_DOUBLEBUFFER*/);
+
+var setUiLanguage = function(lang){
+ uiLanguage = lang;
+ winform.text = uiLanguage.title;
+ winform.btnAllowLocalhostLoopback.text = uiLanguage.exemptAll;
+ winform.btnDisableLocalhostLoopback.text = uiLanguage.exemptNone;
+ winform.tip.text = uiLanguage.tip;
+
+ winform.listview.clear(true);
+ winform.listview.insertColumn(uiLanguage.displayName,300)
+ winform.listview.insertColumn(uiLanguage.packageName,300)
+ winform.listview.insertColumn(uiLanguage.localhost,80)
+ winform.listview.insertColumn("SID",-2)
+ winform.plusSearch.setCueBannerText(uiLanguage.searchCueBannerText)
+}
+
+var lcid = ::Kernel32.GetUserDefaultLCID()
+if( lcid==1028 || lcid == 3076 || lcid == 5124 ){
+ import string.conv;
+ setUiLanguage(table.map(uiLanguage,lambda(v) string.conv.traditionalized(v)) )
+}
+else {
+ setUiLanguage(uiLanguage);
+}
+
+reloadItemData();
+
+winform.plusSearch.editBox.onOk = function(){
+ reloadItemData();
+ return true;
+}
+
+winform.show();
+import win.dlg.message;
+if(!_WIN10_LATER){
+ winform.msgWarn(uiLanguage.requiredWin10)
+}
+
+win.loopMessage();
\ No newline at end of file
diff --git a/forms/main/tools/youtube.aardio b/forms/main/tools/youtube.aardio
new file mode 100644
index 0000000..3fe7587
--- /dev/null
+++ b/forms/main/tools/youtube.aardio
@@ -0,0 +1,95 @@
+import fonts.fontAwesome;
+import win.ui;
+import win.ui.atom;
+/*DSG{{*/
+var winform = win.form(text="youtube 视频下载工具(点击视频链接即可下载)";right=759;bottom=469)
+winform.add(
+btnVideoInfo={cls="button";text="获取视频下载地址";left=511;top=27;right=732;bottom=60;dr=1;dt=1;font=LOGFONT(h=-16;name='FontAwesome');z=3};
+editInfo={cls="richedit";left=29;top=83;right=735;bottom=445;autohscroll=false;db=1;dl=1;dr=1;dt=1;edge=1;link=1;multiline=1;vscroll=1;z=1};
+editVideoUrl={cls="edit";text="https://www.youtube.com/watch?v=ZFA5Rax0ypU";left=27;top=29;right=499;bottom=58;dl=1;dr=1;dt=1;edge=1;multiline=1;z=2}
+)
+/*}}*/
+
+winform.btnVideoInfo.oncommand = function(id,event){
+ var url = winform.editVideoUrl.text;
+ var vid = string.match(url,"v=([\w\-]+)");
+ if(!vid){
+ return winform.editVideoUrl.showErrorTip(,"请输入正确的视频地址");
+ }
+
+ winform.btnVideoInfo.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'}
+ thread.invoke(
+ function(winform,vid){
+ import web.rest.jsonLiteClient;
+ var http = web.rest.jsonLiteClient();
+
+ var videoApi = http.api("https://www.youtube.com/get_video_info?video_id={video_id}");
+ var info = videoApi[vid].get();
+
+ if(!info){
+ winform.editInfo.text = "网络错误";
+ winform.btnVideoInfo.disabledText = null;
+ }
+
+ winform.editInfo.text = "";
+ winform.editInfo.print( "视频作者:",info.player_response.videoDetails.author);
+ winform.editInfo.print( "视频标题:",info.player_response.videoDetails.title);
+ winform.editInfo.print( "视频说明:",info.player_response.videoDetails.shortDescription);
+ winform.videoTitle = info.player_response.videoDetails.title;
+
+ for(i,v in info.player_response.streamingData.adaptiveFormats){
+ if(!string.indexOf(v.mimeType,"audio/mp4")){
+ continue;
+ }
+
+ winform.editInfo.print();
+ winform.editInfo.print("音频质量:",v.quality);
+ winform.editInfo.print("音频地址:",v.url);
+ }
+
+ for(i,v in info.player_response.streamingData.formats){
+ if(!string.indexOf(v.mimeType,"video/mp4")){
+ continue;
+ }
+
+ winform.editInfo.print();
+ winform.editInfo.print("视频质量:",v.qualityLabel);
+ winform.editInfo.print("视频地址(含音频):",v.url);
+ }
+
+
+ var captionTracks = info.player_response.captions[["playerCaptionsTracklistRenderer"]][["captionTracks"]];
+ if(info.captions[["playerCaptionsTracklistRenderer"]][["captionTracks"]]){
+ if(#captionTracks){
+ for(k,v in captionTracks){
+ if(v.languageCode=="en"){
+ var str = http.get(v.baseUrl)
+ winform.editInfo.print(str);
+ break
+ }
+ }
+
+ }
+ }
+
+ winform.editInfo.setFocus();
+ winform.btnVideoInfo.disabledText = null;
+ },winform,vid
+ )
+}
+
+import fsys.dlg;
+import inet.downBox;
+winform.editInfo.onlink=function(message,href){
+ if( message = 0x202/*_WM_LBUTTONUP*/ ) {
+ var path = fsys.dlg.open("*.mp4|*.mp4","请选择下载路径",,winform,,fsys.path.validName(winform.videoTitle))
+ if(!path) return;
+
+ var downBox = inet.downBox(winform,"下载视频");
+ downBox.download(href,path);
+ }
+}
+
+winform.enableDpiScaling();
+winform.show();
+win.loopMessage();
\ No newline at end of file
diff --git a/forms/main/v2ray.aardio b/forms/main/v2ray.aardio
new file mode 100644
index 0000000..5548495
--- /dev/null
+++ b/forms/main/v2ray.aardio
@@ -0,0 +1,1058 @@
+import win.ui;
+import fonts.fontAwesome;
+/*DSG{{*/
+var frmXray = win.form(text="winXray ";right=959;bottom=591;bgcolor=16777215)
+frmXray.add(
+btnEditPacOrUwp={cls="plus";text="编辑PAC";left=328;top=367;right=447;bottom=397;align="left";db=1;dr=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=12}};iconText='\uF1C4';notify=1;textPadding={left=30};z=7};
+btnImportServerFromClipBd={cls="plus";text="批量导入链接";left=459;top=367;right=592;bottom=397;align="left";db=1;dr=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=12}};iconText='\uF196 ';notify=1;textPadding={left=30};z=8};
+btnTcping={cls="plus";text="检测并连接最快服务器";left=735;top=366;right=941;bottom=398;align="left";bgcolor=11580047;border={radius=4};db=1;dr=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=18}};iconText='\uF012';notify=1;textPadding={left=42};z=3};
+chkAutoTest={cls="plus";text="异常自动重连 ";left=598;top=367;right=729;bottom=397;align="left";db=1;dr=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=12}};iconText='\uF0C8';notify=1;textPadding={left=30};z=9};
+edit={cls="edit";left=6;top=405;right=953;bottom=585;bgcolor=0;color=16777215;db=1;dl=1;dr=1;edge=1;hscroll=1;multiline=1;vscroll=1;z=2};
+listview={cls="listview";left=4;top=5;right=954;bottom=358;db=1;dl=1;dr=1;dt=1;edge=1;fullRow=1;gridLines=1;z=1};
+radioProxy={cls="radiobutton";text="全局代理";left=129;top=369;right=226;bottom=395;bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-13);z=4};
+radioProxyDirect={cls="radiobutton";text="不使用代理";left=14;top=369;right=120;bottom=395;bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-13);z=6};
+radioProxyPac={cls="radiobutton";text="PAC代理";left=234;top=369;right=321;bottom=395;bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-13);z=5}
+)
+/*}}*/
+
+frmXray.listview.insertColumn("类型",100)
+frmXray.listview.insertColumn("服务器",160)
+frmXray.listview.insertColumn("端口",70)
+frmXray.listview.insertColumn("加密",90)
+frmXray.listview.insertColumn("协议",50)
+frmXray.listview.insertColumn("备注",190)
+frmXray.listview.insertColumn("响应速度",95)
+frmXray.listview.insertColumn("状态",-1)
+frmXray.listview.setExtended(0x10000/*_LVS_EX_DOUBLEBUFFER*/);
+
+frmXray.show();
+
+import config;
+import v2ray.core;
+var currentOutboundIndex,currentOutboundAddress;
+var activeOutbound = function(outboundIndex,outboundAddress,enableRetry,timerTesting){
+
+ if(!outboundIndex && !outboundAddress){
+ outboundIndex,outboundAddress = currentOutboundIndex,currentOutboundAddress;
+ if(!outboundIndex && !outboundAddress) {
+ return;
+ }
+ }
+
+ var outbound = config.proxy.outbounds[outboundIndex];
+ if(!outbound){
+ return ;
+ }
+
+
+ var startTesting = timerTesting;
+ if(!startTesting){
+ ..publish("activeOutbound",false);
+
+ var started,err = v2ray.core.restart(frmXray.edit,outbound);
+ startTesting = started;
+ if(!started){
+ frmXray.edit.print("启动 V2Ray 错误",err:"");
+ frmXray.btnTcping.disabledText = null;
+ return false;
+ }
+ }
+
+ if( startTesting ){
+ currentOutboundIndex,currentOutboundAddress = outboundIndex,outboundAddress;
+ frmXray.autoTesting = true;
+
+ ..thread.invoke(
+ function(frmXray,outboundIndex,outboundAddress,sockProxyPort,httpProxyAddress,enableRetry,timerTesting){
+ import web.rest.client;
+ var restClient = web.rest.client(,httpProxyAddress);
+ restClient._http.setTimeouts(1000,2000,2000);
+ var ret = restClient.get("https://www.google.com/generate_204");
+ var lastStatusCode = restClient.lastStatusCode;
+
+ if( lastStatusCode == 204 ){
+ frmXray.onStartXrayComplete(outboundIndex,timerTesting,outboundAddress);
+ return;
+ }
+ restClient.close();
+
+ if(timerTesting){
+ sleep(100);
+ }
+
+ import inet.http;
+ var http = inet.http(,httpProxyAddress);
+ http.setTimeouts(1000,1000,1000);
+ var isAlive = http.get("http://www.msftconnecttest.com/connecttest.txt")=="Microsoft Connect Test";
+ http.close();
+
+ if(isAlive){
+ frmXray.onStartXrayComplete(outboundIndex,timerTesting,outboundAddress);
+ return;
+ }
+
+ if(timerTesting){
+ sleep(100);
+ }
+
+ import wsock.tcp.socks5Client;
+
+ var client;
+ for(i=1;2;1){
+ sleep(200);
+ client = wsock.tcp.socks5Client("127.0.0.1",sockProxyPort);
+ if(client)break;
+ }
+
+ if(client){
+ client.setTimeouts(1000,1000);
+ if(client.connect("www.google.com",80) ){
+
+ var sendData =/***********
+GET / HTTP/1.1
+Host: www.google.com
+Connection: close
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64)
+Accept: */*;
+Accept-Language: zh-CN,zh;
+Accept-Charset:utf-8;
+***********/
+ client.write( sendData + '\r\n\r\n' )
+ var rep = client.read(9);
+ client.close();
+
+ if( rep && ..string.startWith(rep,"HTTP/1.1 ") ){
+ frmXray.onStartXrayComplete(outboundIndex,timerTesting,outboundAddress);
+ return;
+ }
+ }
+ };
+ frmXray.onStartXrayFailed(outboundIndex,enableRetry,outboundAddress);
+ },frmXray,outboundIndex,outboundAddress,
+ v2ray.core.socksProxyPort,v2ray.core.getSystemProxyConfig(),enableRetry,timerTesting
+ )
+
+ return true;
+ }
+}
+
+var autoUpdateSubscriptionTimerId;
+frmXray.autoUpdateSubscription = function(timeout){
+ ..win.clearTimeout(autoUpdateSubscriptionTimerId);
+ if(timeout===-1){
+ autoUpdateSubscriptionTimerId = null;
+ return;
+ }
+
+ if(config.proxy.autoRefreshSubscription){
+ autoUpdateSubscriptionTimerId = ..win.setTimeout(function(){
+ autoUpdateSubscriptionTimerId = null;
+
+ import v2ray.outbounds;
+ v2ray.outbounds.autoUpdateSubscription();
+ },timeout:10000)
+ }
+}
+
+frmXray.onStartXrayComplete = function(outboundIndex,timerTesting,outboundAddress){
+ frmXray.autoUpdateSubscription(-1);
+
+ var outbound = config.proxy.outbounds[outboundIndex];
+ var outbound = ..config.proxy.outbounds[outboundIndex];
+ if(!(outbound && (outbound.address == outboundAddress))){
+ return;
+ }
+
+ var listview = frmXray.listview;
+ listview.ensureVisible(outboundIndex);
+ for b,v in table.eachIndex(config.proxy.outbounds){
+ listview.setItemText("",b,8);
+ }
+
+ frmXray.autoTesting = false;
+ listview.setItemText("活动服务器:正常",outboundIndex,8);
+ listview.activeOutboundIndex = outboundIndex;
+
+ var address = listview.getItemText(outboundIndex,2);
+ if(!timerTesting) frmXray.edit.print("已切换到服务器:",address);
+ listview.activeOutboundAddress = address;
+
+ if(listview.getItemText(outboundIndex,7)=="不可用"){
+ listview.setItemText("",outboundIndex,7);
+ }
+
+ frmXray.onTcpingReturn = function(outboundIndex,address,succeeded,speedText){
+ if(address==listview.getItemText(outboundIndex,2)){
+ listview.setItemText(speedText,outboundIndex,7);
+ }
+ };
+ frmXray.validOutbounds = {};
+
+ frmXray.btnTcping.disabledText = null;
+ ..publish("activeOutbound",address);
+}
+
+subscribe("activeOutbound",function(address){
+ ..globalActiveOutbound = address;
+} )
+
+frmXray.onStartXrayFailed = function(outboundIndex,enableRetry,outboundAddress){
+ ..publish("activeOutbound",false);
+
+ var outbound = ..config.proxy.outbounds[outboundIndex];
+ if(!(outbound && (outbound.address == outboundAddress))){
+ return;
+ }
+
+ if(outbound.subscribeUrl){
+ frmXray.autoUpdateSubscription();
+ }
+
+ var listview = frmXray.listview;
+ listview.ensureVisible(outboundIndex);
+ if(listview.activeOutboundIndex==outboundIndex){
+ listview.activeOutboundIndex=null;
+ listview.activeOutboundAddress = null;
+ }
+
+ listview.setItemText("不可用",outboundIndex,7);
+ if(enableRetry){
+ if(#frmXray.validOutbounds){
+ var next = table.shift(frmXray.validOutbounds);
+ activeOutbound(next[1],next[2],#frmXray.validOutbounds);
+ listview.setItemText("异常,测试下一个...",outboundIndex,8);
+ frmXray.edit.print("服务器异常:",listview.getItemText(outboundIndex,2));
+ frmXray.edit.print("正在尝试连接:",next[2]);
+ }
+ else {
+ frmXray.btnTcping.oncommand();
+ }
+ }
+ else {
+ listview.setItemText("活动服务器:异常",outboundIndex,8);
+ frmXray.edit.print("已切换到服务器:",listview.getItemText(outboundIndex,2));
+ frmXray.autoTesting = false;
+ }
+
+ frmXray.btnTcping.disabledText = null;
+
+}
+
+var tcping = function(frmXray,outboundIndex,outbound){
+ import wsock.tcp.client;
+ var timeout = 0;
+ var failed = 0;
+ for(i=1;8;1){
+ sleep(1);
+
+ var client = wsock.tcp.client();
+ var tickBegin = time.tick();
+ if(client.connectTimeout(outbound.address,tonumber(outbound.port),3)){
+ var ret = client.send(".");
+ client.close();
+
+ if( ret != 1){
+ frmXray.onTcpingReturn(outboundIndex,outbound.address,false,"不可用");
+ return;
+ }
+ timeout = timeout + (time.tick() - tickBegin);
+ }
+ else {
+ client.close();
+
+ failed++;
+ if(failed>1){
+ frmXray.onTcpingReturn(outboundIndex,outbound.address,false,"不可用");
+ return;
+ }
+ }
+ }
+
+ frmXray.onTcpingReturn(outboundIndex,outbound.address,true,math.round(timeout / (8-failed) / 1000,2)+"秒");
+};
+
+var retryOnNetworkAliveTimerId;
+frmXray.onTcpingFailed = function(){
+ frmXray.autoTesting = false;
+ frmXray.btnTcping.disabledText = null;
+ ..publish("activeOutbound",false);
+
+ if(retryOnNetworkAliveTimerId){
+ frmXray.clearTimeout(retryOnNetworkAliveTimerId);
+ }
+
+ if(inet.http.isAlive(,false)){
+ frmXray.autoUpdateSubscription(1000);
+ }
+ else {
+ retryOnNetworkAliveTimerId = frmXray.setInterval(
+ 1000,function(){
+
+ if(frmXray.listview.activeOutboundIndex){
+ retryOnNetworkAliveTimerId = null;
+ return 0;
+ }
+
+ if(inet.http.isAlive(,false)){
+ frmXray.btnTcping.oncommand();
+ retryOnNetworkAliveTimerId = null;
+ return false;
+ }
+ }
+ )
+ }
+}
+
+import sysProxy;
+import style;
+frmXray.btnTcping.skin(style.primaryButton);
+frmXray.btnTcping.oncommand = function(id,event){
+ frmXray.listview.activeOutboundIndex = null;
+ frmXray.listview.activeOutboundAddress = null;
+ frmXray.listview.clearColumnImage();
+
+ var items = frmXray.listview.items;
+ if(#items){
+ frmXray.btnTcping.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'}
+
+ v2ray.core.lastDownloadingCoreFailed = false;
+ if(!v2ray.core.getPath()){
+ frmXray.btnTcping.disabledText = null;
+ return;
+ }
+
+ var failedCount = 0;
+ frmXray.onTcpingReturn = function(outboundIndex,address,succeeded,speedText){
+ if(address!=frmXray.listview.getItemText(outboundIndex,2)){
+ return;
+ }
+ frmXray.listview.setItemText(speedText,outboundIndex,7);
+
+ if(succeeded){
+ frmXray.listview.setItemText(speedText,outboundIndex,7);
+ frmXray.validOutbounds = {}
+ frmXray.onTcpingReturn = function(outboundIndex,address,succeeded,speedText){
+ if(address!=frmXray.listview.getItemText(outboundIndex,2)){
+ return;
+ }
+
+ frmXray.listview.setItemText(speedText,outboundIndex,7);
+ if(succeeded) {
+ table.push(frmXray.validOutbounds,{outboundIndex;address});
+ }
+ else{
+ failedCount++;
+ if(failedCount==#items) {
+ frmXray.onTcpingFailed();
+ }
+ }
+ }
+ activeOutbound(outboundIndex,address,#items>1);
+ }
+ else{
+ failedCount++;
+ if(failedCount==#items) {
+ frmXray.onTcpingFailed();
+ }
+ }
+ }
+
+ thread.createSuspended(true);
+
+ var handles = {};
+ var outbounds = config.proxy.outbounds;
+ var lenPing = 0;
+ var listview = frmXray.listview;
+ for(i=1;#items;1){
+ if(outbounds[i].autoConnect===false){
+ listview.setItemText("禁止测速",i,7);
+ continue;
+ }
+
+ if(lenPing>config.proxy.maxTestServers){
+ frmXray.edit.print("测速服务器数超出设定上限:"+config.proxy.maxTestServers + ",您可在「配置 / 高级设置」中修改此值。")
+ break;
+ }
+ lenPing++;
+
+ listview.setItemText("...",i,7);
+ listview.setItemText("",i,8);
+
+ var h = thread.create(tcping,frmXray,i,config.proxy.outbounds[i]);
+ table.push(handles,h);
+ }
+ thread.createSuspended(false);
+
+ for(i=1;#handles;1){
+ var h = handles[i];
+ thread.resume(h);
+ raw.closehandle(h);
+ }
+
+ if(#handles) ..thread.waitOne(handles);
+ }
+ else {
+ if(id) frmXray.msgWarn("请先添加服务器")
+ v2ray.core.stop();
+
+ frmXray.btnTcping.disabledText = null;
+ frmXray.autoTesting = false;
+ frmXray.onTcpingReturn = function(outboundIndex,address,succeeded,speedText){};
+ }
+}
+
+import v2ray.core;
+import v2ray.pacServer;
+frmXray.onDestroy = function(){
+ v2ray.core.stop();
+ v2ray.pacServer.stop();
+}
+
+var pingThread = function( ip,frmXray ) {
+ import icmp.ping;
+ var ping = icmp.ping();
+
+ for(i=1;4;1){
+ if( ping.perform(ip) ){
+ frmXray.edit.print(ip,string.format( "Reply from %s: bytes=%d time=%dms TTL=%d"
+ , ping.ip , #ping.requestData , ping.echoReply.roundTripTime , ping.echoReply.options.ttl ) );
+ }
+ else {
+ frmXray.edit.print(ip,"Request timed out");
+ }
+
+ }
+}
+
+var removeOutbounds = function(selectedItems){
+
+ //避免后台线程改变activeIndex
+ frmXray.onTcpingReturn = function(outboundIndex,address,succeeded,speedText){};
+ frmXray.btnTcping.disabledText = null;
+ frmXray.autoTesting = false;
+
+ var activeIndex = frmXray.listview.activeOutboundIndex;
+ var outbounds = config.proxy.outbounds;
+ for(i=#outbounds;1;-1){
+ var ob = outbounds[i];
+ if(activeIndex==i){
+ ob.active = true;
+ }
+ }
+
+ if(#selectedItems){
+ for(i=#selectedItems;1;-1){
+ var item = selectedItems[i]
+ frmXray.listview.delItem(item);
+ ..table.remove(config.proxy.outbounds,item);
+ }
+ }
+ else{
+ for(i=#outbounds;1;-1){
+ if(frmXray.listview.getItemText(i,7)=="不可用"){
+ ..table.remove(outbounds,i);
+ frmXray.listview.delItem(i);
+ }
+ }
+ }
+
+ frmXray.listview.activeOutboundIndex = null;
+ for(i=1;#outbounds;1){
+ if(outbounds[i].active){
+ frmXray.listview.activeOutboundIndex = i;
+ break;
+ }
+ }
+ publish("outbounds.updateConfigJson");
+
+ if(activeIndex && (!frmXray.listview.activeOutboundIndex) ){
+ if(!v2ray.core.lastDownloadingCoreFailed) frmXray.btnTcping.oncommand();
+ }
+}
+
+import v2ray.outbounds;
+frmXray.listview.onnotify = function(id,code,ptr){
+ select(code) {
+ case 0xFFFFFFF4/*_NM_CUSTOMDRAW*/ {
+ var lvcd = frmXray.listview.getNotifyCustomDraw(code,ptr);
+ if( lvcd.nmcd.dwDrawStage == 0x10001/*_CDDS_ITEMPREPAINT*/)
+ return 0x20/*_CDRF_NOTIFYSUBITEMDRAW*/
+ elseif( lvcd.nmcd.dwDrawStage == 1/*_CDDS_PREPAINT*/ ){
+ return 0x20/*_CDRF_NOTIFYITEMDRAW*/;
+ }
+ elseif( lvcd.nmcd.dwDrawStage == ( 0x10001/*_CDDS_ITEMPREPAINT*/ | 0x20000/*_CDDS_SUBITEM*/) ){
+ //注意这里 iSubItem 的索引自0开始( 其他函数通常自1开始 )
+ lvcd.clrText = lvcd.nmcd.dwItemSpec % 2 ? 0x373737 : 0;
+ lvcd.clrTextBk = lvcd.nmcd.dwItemSpec % 2 ? 0xFFFFFF : 0xF5F5F5;
+
+ var item = lvcd.nmcd.dwItemSpec+1;
+ if(lvcd.iSubItem==7){
+ if(frmXray.listview.activeOutboundIndex=item){
+ lvcd.clrTextBk = 0x8AFFC3
+ }
+ }
+ elseif(lvcd.iSubItem==6){
+ if(..config.proxy.outbounds[item].autoConnect===false){
+ lvcd.clrText = 0xCCCCCC;
+ }
+ }
+ lvcd.update()
+
+ return 0/*_CDRF_DODEFAULT*/
+ }
+ }
+ case 0xFFFFFFFD/*_NM_DBLCLK*/ {
+ var nm = frmXray.listview.getNotifyMessage(code,ptr);
+ if( nm ){
+ v2ray.core.lastDownloadingCoreFailed = false;
+
+ frmXray.onTcpingReturn = function(outboundIndex,address,succeeded,speedText){
+ if(address==frmXray.listview.getItemText(outboundIndex,2)){
+ frmXray.listview.setItemText(speedText,outboundIndex,7);
+ }
+ }
+ frmXray.btnTcping.disabledText = null;
+
+ for b,v in table.eachIndex(config.proxy.outbounds){
+ frmXray.listview.setItemText("",b,8);
+ }
+ activeOutbound(nm.iItem,frmXray.listview.getItemText(nm.iItem,2),false);
+ }
+ }
+ case 0xFFFFFFFB/*_NM_RCLICK*/ {
+ var x,y = win.getCursorPos();
+ var nm = frmXray.listview.getNotifyMessage(code,ptr);
+ if(!nm) return;
+
+ var currentIdx = nm.iItem;
+ if(!currentIdx){
+ var popmenu = win.ui.popmenu(frmXray);
+ popmenu.add("新增代理服务器",function(id){
+ var frmOutbound = frmXray.loadForm("\forms\main\outbound.aardio");
+ frmOutbound.doModal()
+ });
+
+ popmenu.add("自剪贴板批量导入分享链接、订阅源",function(id){
+ frmXray.btnImportServerFromClipBd.oncommand();
+ });
+
+ popmenu.add('立即更新所有订阅源',function(id){
+ v2ray.outbounds.updateSubscription();
+ });
+
+ popmenu.add();
+
+ popmenu.add('清空服务器列表',function(id){
+ config.proxy.outbounds = ..table.array();
+ frmXray.listview.clear();
+
+ frmXray.btnTcping.disabledText = null;
+ frmXray.autoTesting = false;
+ frmXray.onTcpingReturn = function(outboundIndex,address,succeeded,speedText){}
+ publish("outbounds.updateConfigJson");
+ });
+
+ popmenu.add('清除「不可用」服务器',function(id){
+ removeOutbounds();
+ });
+
+ popmenu.add("重置为默认服务器列表",
+ function(id){
+ ..config.__loadDefaultOutbounds();
+ publish("outbounds.updateConfigJson");
+ publish("uiCommand.restartV2RayCore");
+ }
+ );
+ popmenu.add();
+
+ if(!frmXray.btnTcping.disabledText){
+ popmenu.add('按「响应速度」排序服务器',function(id){
+ frmXray.listview.sortBySpeed();
+ });
+ popmenu.add();
+ };
+ popmenu.popup(x,y,true);
+ return;
+ }
+
+ var selectedItems = frmXray.listview.selected;
+ var popmenu = win.ui.popmenu(frmXray);
+
+ if(#selectedItems==1){
+ popmenu.add('设为活动服务器( 鼠标双击 )',function(id){
+ if(currentIdx){
+ v2ray.core.lastDownloadingCoreFailed = false;
+
+ frmXray.onTcpingReturn = function(outboundIndex,address,succeeded,speedText){
+ if(address==frmXray.listview.getItemText(outboundIndex,2)){
+ frmXray.listview.setItemText(speedText,outboundIndex,7);
+ }
+ }
+
+ frmXray.btnTcping.disabledText = null;
+
+ for b,v in table.eachIndex(config.proxy.outbounds){
+ frmXray.listview.setItemText("",b,8);
+ }
+ activeOutbound(currentIdx,frmXray.listview.getItemText(currentIdx,2),false)
+ }
+ });
+
+ popmenu.add();
+ }
+
+ popmenu.add("编辑 / 新增代理服务器",function(id){
+ var frmOutbound = frmXray.loadForm("\forms\main\outbound.aardio");
+ frmOutbound.setOutboundConfig(config.proxy.outbounds[currentIdx]);
+ frmOutbound.doModal()
+ });
+
+ popmenu.add("自剪贴板批量导入分享链接、订阅源",function(id){
+ frmXray.btnImportServerFromClipBd.oncommand();
+ });
+
+ var subscribeUrl = config.proxy.outbounds[currentIdx][["subscribeUrl"]];
+ if(#selectedItems=1 && subscribeUrl){
+
+ var ps;
+ var cfgSubscribeUrls = ..config.proxy.subscribeUrls;
+ for(i=#cfgSubscribeUrls;1;-1){
+ var sub = cfgSubscribeUrls[i]
+ if(sub.url===subscribeUrl) {
+ ps = sub.ps;
+ break;
+ }
+ }
+
+ if(#ps){
+ ps = ": "+ps;
+ }
+
+ popmenu.add('更新当前订阅源'+ps,function(id){
+ if(currentIdx){
+ v2ray.outbounds.updateSubscription({[subscribeUrl]=true});
+ }
+ });
+ }
+
+ popmenu.add('更新所有订阅源',function(id){
+ if(currentIdx){
+ v2ray.outbounds.updateSubscription();
+ }
+ });
+
+ popmenu.add()
+
+ var autoConnect = config.proxy.outbounds[currentIdx].autoConnect!==false;
+ var id = popmenu.add('允许自动测速并连接',function(id){
+ if(currentIdx){
+ for(i=#selectedItems;1;-1){
+ var item = selectedItems[i];
+ if(autoConnect === false){
+ config.proxy.outbounds[item].autoConnect = null;
+ frmXray.listview.setItemText("",item,7);
+ }
+ else {
+ config.proxy.outbounds[item].autoConnect = false;
+ frmXray.listview.setItemText("禁止测速",item,7);
+ }
+ }
+ }
+ });
+ popmenu.check(id,autoConnect,0/*_MF_BYCOMMAND*/);
+ popmenu.add()
+
+ popmenu.add('删除服务器',function(id){
+ removeOutbounds(selectedItems);
+ });
+
+ popmenu.add('清空服务器列表',function(id){
+ if(currentIdx){
+ config.proxy.outbounds = ..table.array();
+ frmXray.listview.clear();
+ publish("outbounds.updateConfigJson");
+ }
+ });
+
+ popmenu.add('清除「不可用」服务器',function(id){
+ removeOutbounds();
+ });
+
+ popmenu.add("重置为默认服务器列表",
+ function(id){
+ ..config.__loadDefaultOutbounds();
+ publish("outbounds.updateConfigJson");
+ publish("uiCommand.restartV2RayCore");
+ }
+ );
+
+ if(#selectedItems==1){
+
+ popmenu.add();
+ popmenu.add('生成二维码',function(id){
+ if(currentIdx){
+ import v2ray.outbounds;
+ import win.clip;
+
+ var str = v2ray.outbounds.exportSharedLinks({config.proxy.outbounds[currentIdx]});
+ if(str){
+ var frmChild = frmXray.loadForm("\forms\main\tools\qr.aardio");
+ frmChild.createQrCode(str);
+ frmChild.show();
+ }
+ }
+ });
+
+ popmenu.add('复制服务器分享链接',function(id){
+ if(currentIdx){
+ import v2ray.outbounds;
+ import win.clip;
+
+ var str = v2ray.outbounds.exportSharedLinks({config.proxy.outbounds[currentIdx]});
+ if(str){
+ win.clip.write(str);
+ frmXray.edit.print("已复制链接:",str);
+ }
+ }
+ });
+
+ popmenu.add();
+
+ var toolMenu = win.ui.popmenu(frmXray)
+ toolMenu.add('本机 Ping 检测',function(id){
+ if(currentIdx){
+ thread.invoke(pingThread,config.proxy.outbounds[currentIdx].address,frmXray)
+ }
+ });
+
+ toolMenu.add('全球范围 Ping 检测 ...',function(id){
+ if(currentIdx){
+ process.openUrl("http://ping.pe/" + config.proxy.outbounds[currentIdx].address)
+ }
+ });
+
+ toolMenu.add('全球范围端口检测 ...',function(id){
+ if(currentIdx){
+ process.openUrl("http://port.ping.pe/" + config.proxy.outbounds[currentIdx].address + ":" + config.proxy.outbounds[currentIdx].port)
+ }
+ });
+
+ toolMenu.add('在线路由跟踪检测 ...',function(id){
+ if(currentIdx){
+ process.openUrl("https://www.boce.com/traceroute/" + config.proxy.outbounds[currentIdx].address)
+ }
+ });
+
+ toolMenu.add('本机路由检测',function(id){
+ if(currentIdx){
+ import process;
+ process.execute("cmd.exe","/k tracert " + config.proxy.outbounds[currentIdx].address);
+ }
+ });
+
+ if(config.proxy.outbounds[currentIdx].port == 443 && config.proxy.outbounds[currentIdx].tls){
+ toolMenu.add('浏览 HTTPS 主页 ...',function(id){
+ if(currentIdx){
+ process.openUrl("https" ++ "://" + config.proxy.outbounds[currentIdx].address);
+ }
+ });
+ }
+
+ popmenu.add("服务器工具",toolMenu)
+
+ popmenu.add('SSH 登录服务器',function(id){
+ if(currentIdx){
+ if(_STUDIO_INVOKED){
+ frmXray.msgErr("请在发布后运行此功能");
+ return;
+ }
+ import process;
+ process.execute(io._exepath,"/sshLogin root@"
+ + config.proxy.outbounds[currentIdx].address + ":"
+ + (config.proxy.outbounds[currentIdx].sshPort||22));
+ }
+ });
+ }
+ popmenu.popup(x,y,true);
+ }
+ case 0xFFFFFF94/*_LVN_COLUMNCLICK*/{
+ var nm = frmXray.listview.getNotifyMessage(code,ptr)
+ if(nm.iSubItem==7){
+ frmXray.listview.sortBySpeed();
+ }
+ else {
+ frmXray.msgWarn("排序请点击「响应速度」列")
+ }
+ }
+ }
+}
+
+// 排序函数
+frmXray.listview.sortBySpeed = function () {
+ if(frmXray.btnTcping.disabledText){
+ frmXray.msgWarn("请等待测速完成,然后再点击此排序列。");
+ return;
+ }
+
+ var outbounds = ..table.clone(config.proxy.outbounds);
+ var activeIndex = frmXray.listview.activeOutboundIndex;
+ frmXray.onTcpingReturn = function(outboundIndex,address,succeeded,speedText){}; //避免后台线程改变activeIndex
+
+ for(i=#outbounds;1;-1){
+ var ob = outbounds[i];
+ if(type(ob)!="table"){
+ table.remove(outbounds,i);
+ continue;
+ }
+
+ ob.speed = frmXray.listview.getItemText(i,7);
+ if(ob.speed=="不可用"){
+ ob.speedNum = 0xFFFE;
+ }
+ elseif(ob.speed==""){
+ ob.speedNum = 0xFFFF;
+ }
+ elseif(ob.speed=="..."){
+ frmXray.msgWarn("请等待检测速度完成,然后再点击此排序列。")
+ return;
+ }
+ else {
+ ob.speedNum = tonumber(ob.speed):-3;
+ }
+
+ if(activeIndex==i){
+ ob.active = true;
+ }
+ }
+
+ var hasStatus;
+ for(i=1;#outbounds;1){
+ if(#outbounds[i].speed){
+ hasStatus = true;
+ break;
+ }
+ }
+
+ if(!hasStatus){
+ frmXray.msgWarn("请先点击「检测并连接服务器」获取服务器响应速度!");
+ return;
+ }
+
+ var desc = frmXray.listview.getColumnImage(7) == 0;
+ if(desc){
+ table.sort(outbounds,function(b){
+ return owner.speedNum > b.speedNum;
+ })
+ }
+ else {
+ table.sort(outbounds,function(b){
+ return owner.speedNum < b.speedNum;
+ })
+ }
+
+ frmXray.listview.activeOutboundIndex = null;
+ for(i=1;#outbounds;1){
+ if(outbounds[i].active){
+ frmXray.listview.activeOutboundIndex = i;
+ break;
+ }
+ }
+
+ outbounds.fields = {"protocol";"address";"port";"security";"network";"ps";"speed"}
+ config.proxy.outbounds = outbounds;
+ frmXray.listview.setTable(outbounds);
+ outbounds.fields = {"protocol";"address";"port";"security";"network";"ps"}
+
+ //清理用于排序的临时字段
+ for(i=1;#outbounds;1){
+ var ob = outbounds[i];
+ ob.speedNum = null;
+ ob.speed = null;
+ ob.active = null;
+ }
+
+ if(frmXray.listview.activeOutboundIndex){
+ frmXray.listview.setItemText("活动服务器:正常",frmXray.listview.activeOutboundIndex,8)
+ }
+ frmXray.listview.setColumnImage(7, desc ? 1 : 0);
+}
+
+import win.imageList;
+var iml = win.imageList(16, 15);
+iml.add('GIF\56\57a \0\15\0\x80\0\0\x80\x80\x80\xff\0\xff\33\xf9\4\0\0\0\0\0\44\0\0\0\0 \0\15\0\0\2\31\x8c\x8f\xa9\xcb\xed\15\xa3\x9c\xb4N\xf0\x80\xde\56k\xbfA\\\xd7\x84 \x97Y\xea\xca\xb6\xee\11\xc7F\1\0;', 0xff00ff);
+frmXray.listview.setColumnImageList(iml);
+
+subscribe("uiCommand.restartV2RayCore",function(){
+ config.proxy.outbounds.fields = {"protocol";"address";"port";"security";"network";"ps";}
+
+ var outbounds = config.proxy.outbounds;
+ for(i=#outbounds;1;-1){
+ if(type(outbounds[i])!="table"){
+ table.remove(outbounds,i);
+ }
+ }
+ frmXray.listview.setTable(outbounds);
+
+ if(!v2ray.core.lastDownloadingCoreFailed) frmXray.btnTcping.oncommand();
+} )
+
+import process;
+if(#config.proxy.outbounds){
+ config.proxy.outbounds.fields = {"protocol";"address";"port";"security";"network";"ps";}
+
+ var outbounds = config.proxy.outbounds;
+ for(i=#outbounds;1;-1){
+ if(type(outbounds[i])!="table"){
+ table.remove(outbounds,i);
+ }
+ }
+ frmXray.listview.setTable(outbounds);
+
+ frmXray.setTimeout(
+ function(){
+ publish("uiCommand.restartV2RayCore");
+ },1000
+ );
+}
+
+subscribe("sysProxy.modeChanged",function(mode){
+ frmXray.radioProxyPac.checked = false;
+ frmXray.radioProxy.checked = false;
+ frmXray.radioProxyDirect.checked = false;
+
+ if(mode = "pac"){
+ frmXray.radioProxyPac.checked = true;
+ if(_WIN10_LATER) frmXray.btnEditPacOrUwp.text = "编辑 PAC";
+ }
+ elseif(mode = "proxy"){
+ frmXray.radioProxy.checked = true;
+ if(_WIN10_LATER) frmXray.btnEditPacOrUwp.text = "配置 UWP";
+ }
+ else{
+ frmXray.radioProxyDirect.checked = true;
+ }
+} )
+publish("sysProxy.modeChanged",config.proxy.mode);
+
+import sysProxy;
+var switchProxyMode = function(){
+ if(frmXray.radioProxyPac.checked){
+ sysProxy.switchToPacMode();
+ }
+ elseif(frmXray.radioProxy.checked){
+ sysProxy.switchToGlobalMode();
+ }
+ else {
+ sysProxy.switchToDirectMode();
+ }
+}
+frmXray.radioProxyPac.oncommand = switchProxyMode;
+frmXray.radioProxy.oncommand = switchProxyMode;
+frmXray.radioProxyDirect.oncommand = switchProxyMode;
+
+import win.dlg.message;
+frmXray.btnEditPacOrUwp.skin(style.plainButton)
+frmXray.btnEditPacOrUwp.oncommand = function(id,event){
+ if(frmXray.radioProxy.checked && _WIN10_LATER ){
+ if(_STUDIO_INVOKED){
+ frmXray.msgErr("请先发布为 EXE!");
+ return;
+ }
+
+ import process;
+ process.execute(io._exepath,"/uwp","runas")
+ return;
+ }
+
+ if(frmPac && win.isWindow(frmPac.hwnd)){
+ if( win.isIconic(frmPac.hwnd) ) win.show(frmPac.hwnd,9/*_SW_RESTORE*/ );
+ if( !win.isVisible(frmPac.hwnd) ) win.show(frmPac.hwnd,0x1/*_SW_NORMAL*/ );
+ win.setForeground(frmPac.hwnd)
+ return;
+ }
+
+ frmPac = ..mainForm.loadForm("\forms\main\pac.aardio");
+ frmPac.show();
+}
+subscribe("uiCommand.showPacForm",function(...){
+ frmXray.btnEditPacOrUwp.oncommand();
+} )
+
+subscribe("uiCommand.print",function(...){
+ frmXray.edit.print(...);
+} )
+
+import v2ray.outbounds;
+frmXray.btnImportServerFromClipBd.skin(style.plainButton)
+frmXray.btnImportServerFromClipBd.oncommand = function(id,event){
+ var str = ..win.clip.read();
+ if(str){
+ str = ..string.trim(str,'"\'\t\r\n ');
+ if( ..string.startWith(str,"http://")
+ || ..string.startWith(str,"https://")
+ || ..string.match(str,"^\s*/\N+\s*$") ){
+ if(..string.match(str,"^\s*/\N+\s*$")){
+ str = "https://github.com" + str;
+ }
+
+ v2ray.outbounds.updateSubscription({[str]=true});
+ return;
+ }
+
+ var outbounds = v2ray.outbounds.importFromString(str);
+ if(#outbounds){
+ ..table.append(config.proxy.outbounds,outbounds);
+ publish("uiCommand.restartV2RayCore");
+ publish("outbounds.updateConfigJson");
+ frmXray.msgOk("已成功导入" + #outbounds + "个服务器",1200);
+ return;
+ }
+ }
+
+ frmXray.msgFrown('未导入服务器!\r\n请先复制以下格式文本(自动清除其中的无效内容):\r\n\r\n1、一行或多行(忽略无效行)分享链接或服务器JSON配置。\r\n支持 vmess://,vless://,ss://,ssr://,trojan://, trojan-go:// 等通用分享链接。\r\n\r\n2、包含多个服务器配置的JSON数组,支持winXray格式以及通用格式JSON。\r\n\r\n3、单个 http:// 或 https:// 开头的通用订阅源地址。\r\n可直接使用浏览器地址栏的github文件地址(含blob或raw目录名)。\r\n也可以仅复制单斜杆开始的github文件路径。\r\n\r\n订阅源可用BASE64编码或明文返回以上1、2条规定的配置或分享链接。')
+}
+
+var testTimerId;
+frmXray.chkAutoTest.oncommand = function(id,event){
+ if(testTimerId){
+ frmXray.clearInterval(testTimerId);
+ }
+
+ config.proxy.test = frmXray.chkAutoTest.checked;
+ if(!config.proxy.test) return;
+
+ import inet.http;
+ testTimerId = frmXray.setInterval(
+ config.proxy.testInterval*1000,function(){
+ if(frmXray.btnTcping.disabled) return;
+ if( frmXray.autoTesting ) return;
+
+ var idx = frmXray.listview.activeOutboundIndex;
+ var address = frmXray.listview.activeOutboundAddress;
+ if( !( idx&&address) ){
+ if(!inet.http.isAlive(,false)){
+ return config.proxy.testInterval*1000;
+ }
+
+ if(!v2ray.core.lastDownloadingCoreFailed) frmXray.btnTcping.oncommand();
+ return;
+ }
+
+ frmXray.autoTesting = true;
+ activeOutbound(idx,address,true,true);
+
+ return config.proxy.testInterval*1000;
+ }
+ )
+}
+
+if(config.proxy.test){
+ frmXray.chkAutoTest.checked = true;
+ frmXray.chkAutoTest.oncommand();
+}
+
+frmXray.chkAutoTest.skin(style.checkBox);
+frmXray.edit.print("友情提醒:WinXray 未注册任何域名,谨防钓鱼网站")
+
+frmXray.enableDpiScaling();
+win.loopMessage();
\ No newline at end of file
diff --git a/lib/config.aardio b/lib/config.aardio
new file mode 100644
index 0000000..0b3eecb
--- /dev/null
+++ b/lib/config.aardio
@@ -0,0 +1,158 @@
+//config 配置文件
+import fsys.config;
+config = fsys.config( io.appData("/winXray/") );
+
+namespace config {
+ __appName = "winXray";
+ __loadDefaultOutbounds = function(){
+ import v2ray.outbounds;
+ var serverData = ..string.load("/v2ray-core/winXray-default-servers.json")
+ : $"/v2ray-core/winXray-default-servers.json"
+
+ proxy.outbounds = ..v2ray.outbounds.importFromString(..string.removeBom(serverData));
+ ..publish("outbounds.updateConfigJson",)
+ }
+
+ if(!proxy.outbounds){
+ __loadDefaultOutbounds();
+ }
+}
+
+if(!config.proxy.mode) config.proxy.mode = "pac";
+if(!config.proxy.pacPort) config.proxy.pacPort = 0;
+if(config.proxy.useHttpGlobal===null){
+ config.proxy.useHttpGlobal = true;
+}
+if(config.proxy.useSocksPac===null){
+ config.proxy.useSocksPac = _WIN10_LATER;
+}
+
+if(config.proxy.enableGitConfigGithub===null){
+ config.proxy.enableGitConfigGithub = true;
+}
+
+if(config.proxy.test === null){
+ config.proxy.test = true;
+}
+
+if(config.proxy.autoRefreshSubscription === null){
+ config.proxy.autoRefreshSubscription = true;
+}
+
+if(!config.proxy.testInterval){
+ config.proxy.testInterval = 15;
+}
+
+if(!config.proxy.maxTestServers){
+ config.proxy.maxTestServers = 100;
+}
+
+if(!config.proxy.subscribeUrls){
+ config.proxy.subscribeUrls = {
+ fields = {"";"checked";"ps";"url";}
+ }
+}
+
+if(!config.proxy.hotkey){
+ config.proxy.hotkey = {1/*_MOD_ALT*/|2/*_MOD_CONTROL*/|4/*_MOD_SHIFT*/;'P'#}
+}
+
+config.__resetDefaultCore = function(){
+ config.core.default = {
+ inbounds={
+ {
+ listen="127.0.0.1";
+ port=0;
+ protocol="socks";
+ settings={
+ auth="noauth";
+ udp=true;
+ };
+ sniffing={
+ destOverride={
+ "http";
+ "tls"
+ };
+ enabled=true
+ };
+ tag="proxy";
+ };
+ {
+ listen="127.0.0.1";
+ port=0;
+ protocol="http";
+ settings={};
+ sniffing={
+ destOverride={
+ "http";
+ "tls"
+ };
+ enabled=true
+ };
+ tag="http_proxy"
+ }
+ };
+ log={
+ access="";
+ error="";
+ loglevel="warning"
+ };
+ outbounds={
+ {
+ tag="proxy"
+ };
+ {
+ protocol="freedom";
+ settings={};
+ tag="direct";
+ };
+ {
+ protocol="blackhole";
+ settings={
+ response={
+ type="http"
+ };
+ };
+ tag="block";
+ }
+ };
+ routing={
+ domainStrategy="IPIfNonMatch";
+ rules={
+ {
+ inboundTag={
+ "api"
+ };
+ outboundTag="api";
+ type="field";
+ }
+ }
+ };
+ }
+}
+
+if(!config.core.default){
+ config.__resetDefaultCore();
+}
+
+if(!config.core.default.inbounds[2]){
+ config.core.default.inbounds[2] = {
+ listen="127.0.0.1";
+ port=0;
+ protocol="http";
+ settings={};
+ sniffing={
+ destOverride={
+ "http";
+ "tls"
+ };
+ enabled=true
+ };
+ tag="http_proxy"
+ }
+}
+
+/**intellisense(config)
+__appName = 应用程序名
+? = 配置文件名,\n读写配置并序列化为一个表对象,\n表的成员值可以是支持序列化的普通变量,支持table对象\n配置文件在首次使用时自动加载,退出程序时自动保存\n!fsys_table.
+end intellisense**/
\ No newline at end of file
diff --git a/lib/dnsApi.aardio b/lib/dnsApi.aardio
new file mode 100644
index 0000000..3530d6d
--- /dev/null
+++ b/lib/dnsApi.aardio
@@ -0,0 +1,11 @@
+//dnsApi 域名解析
+namespace dnsApi
+
+_dll = ..raw.loadDll("dnsapi.dll");
+flush = function(domain){
+ return domain ? _dll.DnsFlushResolverCacheB() : _dll.DnsFlushResolverCacheEntry_A(domain);
+}
+
+/**intellisense(dnsApi)
+flush(.(domain) = 清空指定域名的DNS缓存,\n如果参数不指定域名则清空所有DNS缓存
+end intellisense**/
diff --git a/lib/style.aardio b/lib/style.aardio
new file mode 100644
index 0000000..42e0c0c
--- /dev/null
+++ b/lib/style.aardio
@@ -0,0 +1,108 @@
+//style 外观样式
+
+namespace style{
+ primaryButton = {
+ background={
+ default=0xFF8FB2B0;
+ hover=0xFF928BB3;
+ disabled=0xFFCCCCCC;
+ }
+ };
+ button = {
+ background={
+ default=0x668FB2B0;
+ hover=0xFF928BB3;
+ disabled=0xFFCCCCCC;
+ }
+ };
+ transButton = {
+ background={
+ default=0;
+ hover=0xFF928BB3;
+ disabled=0xFFCCCCCC;
+ }
+ };
+ checkBox = {
+ color = {
+ hover = 0xFFFF0000;
+ active = 0xFF00FF00;
+ disabled = 0xEE666666;
+ }
+ checked = {
+ color = {
+ hover = 0xFFFF0000;
+ active = 0xFF00FF00;
+ disabled = 0xEE666666;
+ }
+ iconText = '\uF14a'/*_FA_CHECK_SQUARE*/
+ }
+ };
+ radio ={
+ group = "default";
+ color = {
+ hover = 0xFFFF0000;
+ active = 0xFF00FF00;
+ }
+ checked = {
+ iconText = '\uF058'/*_FA_CHECK_CIRCLE*/
+ }
+ };
+ link = {
+ color = {
+ default = 0xFF000080;
+ hover = 0xFFFF0000;
+ active = 0xFF00FF00;
+ }
+ };
+ plainButton = {
+ color = {
+ default = 0xFF3C3C3C;
+ hover = 0xFFFF0000;
+ active = 0xFF00FF00;
+ disabled = 0xFFCCCCCC;
+ }
+ };
+ key = {
+ foreground={
+ default = 0x00FFFFFF;
+ hover= 0xFF8ADBAF;
+ };
+ };
+ dropdown = {
+ background={
+ default=0xFF68CC95;
+ disabled=0xFFC4CCC8;
+ hover=0xFF4A522F;
+ };
+ color={
+ default=0xFF000000;
+ disabled=0xFF8A8A8A;
+ hover=0xFFFFFFFF
+ };
+ checked = {
+ foreground={
+ default = 0xFFDB8A8E;
+ hover= 0xFF8ADBAF;
+ };
+ }
+ };
+ edit = {
+ border={
+ default={bottom=1;color=0xFF808080};
+ disabled={bottom=1;color=0xFFCCCCCC}
+ }
+ };
+ trackbar = {
+ background={
+ default=0xFF23ABD9
+ };
+ foreground={
+ default=0xFFFF771C;
+ hover=0xFFFF6600
+ };
+ color={
+ default=0xFFFF5C00;
+ hover=0xFFFF6600
+ }
+ }
+}
diff --git a/lib/sysProxy.aardio b/lib/sysProxy.aardio
new file mode 100644
index 0000000..016c3fe
--- /dev/null
+++ b/lib/sysProxy.aardio
@@ -0,0 +1,95 @@
+//sysProxy 系统代理
+import config;
+import inet.conn;
+import v2ray.github;
+import v2ray.pacServer;
+
+namespace sysProxy;
+
+switch = function(mode){
+ ..config.proxy.mode = mode : "direct";
+ ..config.proxy.save();
+
+ if(mode=="pac"){
+ var pacUrl = ..v2ray.pacServer.getUrl();
+ if(pacUrl){
+ ..inet.conn.setProxyAutoConfig(,pacUrl );
+ }
+ else {
+ ..v2ray.pacServer.restart();
+ }
+ ..v2ray.github.setProxy(true);
+ }
+ elseif(mode=="proxy"){
+ import v2ray.core;
+ var address = v2ray.core.getSystemProxyConfig();
+
+ if(address){
+ ..inet.conn.setProxy(,address);
+ ..v2ray.github.setProxy(true);
+ }
+ }
+ else {
+ ..inet.conn.setProxy();
+ ..v2ray.github.setProxy(false);
+ }
+ ..publish("sysProxy.modeChanged",mode)
+}
+
+switchToGlobalMode = function(){
+ switch("proxy")
+}
+
+switchToPacMode = function(){
+ switch("pac")
+}
+
+switchToDirectMode = function(){
+ switch("direct")
+}
+
+switchHotkey = function(){
+ var mode = ..config.proxy.mode;
+ if( mode != "pac"){
+ switch("pac")
+ }
+ else {
+ switch("proxy")
+ }
+
+ return ..config.proxy.mode;
+}
+
+reset = function(proxy){
+ if(proxy===false){
+ if(..config.proxy.mode != "direct"){
+ ..inet.conn.setProxy();
+ ..v2ray.github.setProxy(false);
+ }
+ return;
+ }
+
+ ..inet.conn.setProxy();
+ switch(..config.proxy.mode);
+}
+
+..subscribe("pacServer.restarted",function(pacPort){
+ if(..config.proxy.mode == "pac"){
+ switchToPacMode();
+ }
+} )
+
+..subscribe("v2RayCore.restarted",function(socksProxyPort,httpProxPort){
+ if(..config.proxy.mode != "direct"){
+ reset(true);
+ }
+} )
+
+/**intellisense(sysProxy)
+switch(.(mode) = 切换代理模式,同步修改配置文件。\n可选参数:"proxy","pac","direct"
+switchToGlobalMode() = 设为全局代理,同步修改配置文件。
+switchToPacMode() = 设为PAC自动代理,同步修改配置文件。
+switchToDirectMode() = 设为禁用代理,同步修改配置文件。
+reset(.(是否启用代理)) = 重置系统代理设置,不修改配置文件。\n省略参数时默认值为true。
+end intellisense**/
+
\ No newline at end of file
diff --git a/lib/v2ray/core/_.aardio b/lib/v2ray/core/_.aardio
new file mode 100644
index 0000000..19e9f4b
--- /dev/null
+++ b/lib/v2ray/core/_.aardio
@@ -0,0 +1,344 @@
+//内核进程
+import v2ray.core.ssr;
+import v2ray.core.naive;
+import wsock.tcp.server;
+import process.popen;
+import config;
+
+namespace v2ray.core;
+
+socksProxyPort = null;
+httpProxPort = null;
+
+getSystemProxyConfig = function(){
+ if(!(socksProxyPort&&httpProxPort)){ return null; }
+ return ..config.proxy.useHttpGlobal ? ("127.0.0.1:" + httpProxPort ): ("SOCKS=127.0.0.1:"+socksProxyPort)
+}
+
+isInboundPortChanged = function(){
+ var inbounds = ..config.core.default.inbounds;
+ if(! (..table.isArray(inbounds) && inbounds[1] && inbounds[2]) ){
+ return true;
+ }
+
+ return (inbounds[1].port!=socksProxyPort) || (inbounds[2].port!=httpProxPort)
+}
+
+var prcsV2Ray,v2RayStarting;
+import process.job.limitKill;
+restart = function(editor,outbound){
+
+ if(!outbound){ return null,"错误的出站代理服务器配置" }
+ if(_WINXP){
+ return null,"抱歉!V2Ray Core 不支持 Windows XP, 仅支持 Windows 7, Windows 10 以及更新操作系统。";
+ }
+
+ var inbounds = ..config.core.default[["inbounds"]];
+ if(! (..table.isArray(inbounds) && inbounds[1] ) ){
+ return null,"错误的入站SOCKS代理服务器配置"
+ }
+ if(! ( inbounds[2] ) ){
+ return null,"错误的入站HTTP代理服务器配置"
+ }
+
+ if(v2RayStarting){ return null,"不能重复启动 V2Ray Core" }
+ v2RayStarting = true;
+
+ var corePath = getPath(editor.hwnd);
+ if(!corePath){
+ v2RayStarting = false;
+ return false,"启动失败,未找到 v2ray.exe";
+ }
+
+ // 先不要断开当前代理,使用当前代理下载会更快。
+ if( outbound.protocol == "ssr" ){
+ if(!..v2ray.core.ssr.getPath(editor.hwnd)){
+ v2RayStarting = false;
+ return false,"启动失败,未找到 SSR Core";
+ }
+ }
+ if( outbound.protocol == "naive" ){
+ if(!..v2ray.core.naive.getPath(editor.hwnd)){
+ v2RayStarting = false;
+ return false,"启动失败,未找到 NaïveProxy Core";
+ }
+ }
+
+ ..publish("activeOutbound",false);
+
+ import sysProxy;
+ ..sysProxy.reset(false);
+
+
+ socksProxyPort = inbounds[1].port;
+ httpProxPort = inbounds[2].port;
+ if( (! socksProxyPort) || socksProxyPort >= 49152 ){ socksProxyPort = ..wsock.tcp.server.getFreePort("127.0.0.1",1081,10801,10811,44821) }
+ if( (! httpProxPort) || httpProxPort >= 49152 ){ httpProxPort = ..wsock.tcp.server.getFreePort("127.0.0.1",1082,10802,10812,44822) }
+
+ if(prcsV2Ray){
+ prcsV2Ray.terminate();
+ prcsV2Ray = null;
+ }
+
+ ..v2ray.core.ssr.stop();
+ ..v2ray.core.naive.stop();
+
+ var nexCore;
+ if( outbound.protocol == "ssr" ){
+ var nextProxyPort = ..wsock.getFreePort();
+ if(!..v2ray.core.ssr.restart(editor,outbound,nextProxyPort)){
+ v2RayStarting = false;
+ return false,"SSR Core 启动失败";
+ }
+
+ outbound = {
+ protocol = "socks";
+ address = "127.0.0.1";
+ port = nextProxyPort;
+ }
+
+ nexCore = ..v2ray.core.ssr;
+ }
+ elseif( outbound.protocol == "naive" ){
+ var nextProxyPort = ..wsock.getFreePort();
+ if(!..v2ray.core.naive.restart(editor,outbound,nextProxyPort)){
+ v2RayStarting = false;
+ return false,"SSR Core 启动失败";
+ }
+
+ outbound = {
+ protocol = "socks";
+ address = "127.0.0.1";
+ port = nextProxyPort;
+ }
+
+ nexCore = ..v2ray.core.naive;
+ }
+
+ if( ! prcsV2Ray ){
+
+ import v2ray.core.configJson;
+ var jsonPath,err = ..v2ray.core.configJson.write(
+ ..io.joinpath(..io.splitpath(corePath).dir,"config.json")
+ ,outbound,socksProxyPort,httpProxPort);
+
+ if(!jsonPath){
+ if( nexCore ){ nexCore.stop(); }
+
+ v2RayStarting = false;
+ return false,err:"启动失败,写入配置文件遇到错误!";
+ }
+
+ var err;
+ prcsV2Ray,err = ..process.popen(corePath,"-c=config.json" );
+ if(!prcsV2Ray){
+ if( nexCore ){ nexCore.stop(); }
+
+ ..publish("uiCommand.print",err:"启动 V2Ray Core 时遇到未知错误!");
+
+ if(!..process().isWow64()){
+ if(..process.isExe(corePath)!="PE32"){
+ ..io.remove(corePath);
+ if(!..io.exist(corePath)){
+ ..publish("uiCommand.print","当前操作系统是32位,已删除无效的64位 V2Ray Core,正在下载32位 V2Ray Core");
+ v2RayStarting = false;
+ return restart(editor,outbound)
+ }
+ else {
+ ..publish("uiCommand.print","当前操作系统是32位,但是找到的 V2Ray Core 是64位,请重新下载32位 V2Ray Core");
+ }
+ }
+ }
+
+ v2RayStarting = false;
+ return;
+ }
+ prcsV2Ray.assignToJobObject(process.job.limitKill);
+ prcsV2Ray.codepage = 65001;
+ prcsV2Ray.logResponse(editor);
+
+ inbounds[1].port = socksProxyPort;
+ inbounds[2].port = httpProxPort;
+ ..config.core.save();
+ }
+
+ ..publish("uiCommand.print","已启动代理服务器,SOCKS端口:" + socksProxyPort + " HTTP端口:" + httpProxPort)
+ ..publish("v2RayCore.restarted",socksProxyPort,httpProxPort);
+ v2RayStarting = false;
+ return true;
+}
+
+stop = function(){
+ ..v2ray.core.ssr.stop();
+
+ if(prcsV2Ray){
+ prcsV2Ray.terminate();
+ prcsV2Ray = null;
+ }
+
+ ..sysProxy.reset(false);
+
+ import v2ray.github;
+ v2ray.github.setProxy(false);
+}
+
+var getV2RayCoreUrl = function(){
+ var msgDlg = ..win.dlg.message(..mainForm);
+ var form = msgDlg.create('正在获取 V2Ray Core 最新版本',,true)
+ form.icon = '\uF1D8';
+ form.progress.startProgress(50);
+
+ var url,tag = ..win.invoke(function(){
+ import process;
+ import inet.http;
+ var http = ..inet.http();
+ var url = http.location("https://github.com/v2fly/v2ray-core/releases/latest");
+ http.close();
+
+ if(!url) return;
+
+ var tag = ..string.match(url,"[^/]+$")
+ if(!tag || (tag=="latest")) return;;
+
+ return "https://github.com/v2fly/v2ray-core/releases/download/"
+ + tag + "/v2ray-windows-" + (..process().isWow64() ? "64" : "32") + ".zip",tag
+ });
+ form.close();
+
+ return url,tag;
+}
+
+getPath = function(hwnd){
+ var path = ..io.fullpath("/v2ray-core/v2ray.exe");
+ if(..io.exist(path)){
+ return path;
+ }
+
+ var path = ..io.appData("/winXray/core/v2ray.exe");
+ if(..io.exist(path)){
+ return path;
+ }
+
+ var path = ..io.fullpath("/xray-core/xray.exe");
+ if(..io.exist(path)){
+ ..io.rename("/xray-core/","/v2ray-core/")
+ }
+
+ var path = ..io.fullpath("/v2ray-core/xray.exe");
+ if(..io.exist(path)){
+ ..io.rename("/v2ray-core/xray.exe","/v2ray-core/v2ray.exe")
+ return ..io.fullpath("/v2ray-core/v2ray.exe");
+ }
+
+ if(self.lastDownloadingCoreFailed){
+ return;
+ }
+
+ ..mainForm.disabled = true;
+ var url,versionTag = getV2RayCoreUrl();
+
+ if(!url) {
+ ..publish("uiCommand.print","请下载 V2Rary Core 到以下路径:");
+ ..publish("uiCommand.print",path);
+
+ ..mainForm.disabled = false;
+ self.lastDownloadingCoreFailed = true;
+ return null;
+ }
+
+ import zlib.httpFile;
+ if( ..zlib.httpFile.download(url,"正在下载 V2Ray Core"
+ ,..io.appData("/winXray/download/")
+ ,..io.appData("/winXray/core/"),,..mainForm.hwnd) ){
+
+ self.lastDownloadingCoreFailed = null;
+ ..mainForm.disabled = false;
+ return ..io.exist(path);
+ }
+ else {
+ ..mainForm.disabled = false;
+ self.lastDownloadingCoreFailed = true;
+
+ ..publish("uiCommand.print","请到以下网址下载 V2Ray Core:");
+ ..publish("uiCommand.print",url);
+
+ ..publish("uiCommand.print","下载后请解压到以下目录内:");
+ ..publish("uiCommand.print",..io.appData("/winXray/core/"));
+
+ //import process;
+ //process.execute(..io._exepath,"/github","runas");
+ }
+}
+
+getCoreDir = function(hwnd){
+ var path = ..io.fullpath("/v2ray-core/v2ray.exe");
+ if(..io.exist(path)){
+ return ..io.fullpath("/v2ray-core/");
+ }
+
+ var path = ..io.appData("/winXray/core/v2ray.exe");
+ if(..io.exist(path)){
+ return ..io.appData("/winXray/core/");;
+ }
+
+ var path = ..io.fullpath("/v2ray-core/");
+ if(..io.exist(path)){
+ return path;
+ }
+
+ return ..io.appData("/winXray/core/");
+}
+
+updateCore = function(){
+ ..mainForm.disabled = true;
+
+ var coreDir = getCoreDir();
+ var url,versionTag = getV2RayCoreUrl();
+ if(!url){
+ ..mainForm.disabled = false;
+ self.lastDownloadingCoreFailed = true;
+ return null;
+ }
+
+ import fsys;
+ fsys.delete( ..io.appData("/winXray/temp/v2ray/") );
+
+
+ import zlib.httpFile;
+ if( ..zlib.httpFile.download(url,"正在下载 V2Ray Core,版本:" + versionTag
+ ,..io.appData("/winXray/download/")
+ ,..io.appData("/winXray/temp/v2ray/"),,..mainForm.hwnd) ){
+ ..mainForm.disabled = false;
+
+ if(..io.exist(..io.appData("/winXray/temp/v2ray/v2ray.exe"))){
+ import sysProxy;
+ sysProxy.reset(false);
+
+ import process.file;
+ process.file.terminate(..io.joinpath(coreDir,"v2ray.exe"));
+ process.file.terminate(..io.joinpath(coreDir,"v2ctl.exe"));
+
+ ..io.createDir(coreDir);
+ fsys.copy(..io.appData("/winXray/temp/v2ray/v2ray.exe"),..io.joinpath(coreDir,"v2ray.exe"));
+ fsys.copy(..io.appData("/winXray/temp/v2ray/v2ctl.exe"),..io.joinpath(coreDir,"v2ctl.exe"));
+
+ self.lastDownloadingCoreFailed = null;
+ return versionTag;
+ }
+ else {
+ self.lastDownloadingCoreFailed = true;
+ }
+ }
+ else {
+ ..mainForm.disabled = false;
+ self.lastDownloadingCoreFailed = true;
+ }
+}
+
+/**intellisense(v2ray.core)
+socksProxyPort = SOCKS代理端口
+httpProxPort = HTTP代理端口
+isInboundPortChanged() = 是否已变更代理端口配置
+restart(.(editor,outbound) = 重启启动 V2Ray 服务进程
+lastDownloadingCoreFailed = 上次下载 Core 是否失败,如果希望重新下载请重新赋值为 null
+end intellisense**/
diff --git a/lib/v2ray/core/configJson.aardio b/lib/v2ray/core/configJson.aardio
new file mode 100644
index 0000000..adbef4a
--- /dev/null
+++ b/lib/v2ray/core/configJson.aardio
@@ -0,0 +1,475 @@
+//configJson 内核配置
+import config;
+import web.json;
+import inet.url;
+import crypt;
+
+namespace v2ray.core.configJson;
+
+write = function(jsonPath,outbound,sockPort,httpPort){
+ if(!outbound){ return; }
+ if(type(outbound.port)!=type.number){
+ outbound.port = tonumber(outbound.port);
+ }
+
+ var currentCore = ..table.clone(..config.core.default);
+ if(! ..table.isArray(currentCore.outbounds) ){
+ return null,"错误的出站代理服务器配置"
+ }
+
+ var inboundsInCore = currentCore.inbounds;
+ if(! ..table.isArray(inboundsInCore) ){
+ return null,"错误的入站代理服务器配置"
+ }
+
+ var proxyOutboundInCore;
+ for(k,ob in currentCore.outbounds){
+ if(ob.tag == "proxy"){
+ proxyOutboundInCore = ob;
+ }
+ }
+
+ if( type(proxyOutboundInCore) !="table" ){
+ return null,"未找到默认出站代理服务器配置节点"
+ }
+
+ var socksInbounds,httpInbounds;
+ for(k,ib in currentCore.inbounds){
+ if(ib.tag == "proxy"){
+ socksInbounds = ib;
+ socksInbounds.port = sockPort;
+ }
+ elseif(ib.tag == "http_proxy"){
+ httpInbounds = ib;
+ httpInbounds.port = httpPort;
+ }
+ }
+
+ if( type(socksInbounds) !="table" ){
+ return null,"未找到默认 SOCKS 入站代理服务器配置节点"
+ }
+
+ if( type(httpInbounds) !="table" ){
+ return null,"未找到默认 HTTP 入站代理服务器配置节点"
+ }
+
+ if(#outbound.tls && !outbound.sni){
+ var host = outbound.host;
+ if(..table.isArray(host)){ host = host[1] }
+ outbound.sni = host ? host : outbound.address
+ }
+
+ if(outbound.protocol=="vless"){
+ if(!outbound.tls && outbound.port==443) outbound.tls = "tls";
+ if(!outbound.tls) outbound.tls = "tls";
+
+ var mux = (outbound.concurrency !== null) ? {
+ concurrency=outbound.concurrency;
+ enabled=outbound.concurrency ? ( outbound.concurrency > 0)
+ } : {
+ concurrency=8;
+ enabled=true
+ };
+
+ var ob = {
+ mux = outbound.tls != "xtls" ? mux : null;
+ protocol="vless";
+
+ settings={
+ vnext={
+ {
+ address=outbound.address;
+ port=tonumber(outbound.port);
+ users={
+ {
+ id=outbound.id;
+ flow=outbound.flow : (outbound.tls == "xtls" ? "xtls-rprx-direct" : null);
+ encryption=( (!#outbound.security) || outbound.security=="auto") ? "none" : outbound.security;
+ level=outbound.level : 0;
+ }
+ }
+ }
+ };
+ };
+ streamSettings={
+ network=outbound.network : "tcp";
+ security=#outbound.tls ? outbound.tls : null;
+ tlsSettings = (#outbound.tls && outbound.tls != "xtls") ? {
+ allowInsecure = !!outbound.allowInsecure;
+ serverName = outbound.sni : outbound.address;
+ alpn = outbound.alpn;
+ disableSessionResumption = outbound.disableSessionResumption;
+ } : null;
+ xtlsSettings = outbound.tls == "xtls" ? {
+ allowInsecure = !!outbound.allowInsecure;
+ serverName = outbound.sni : outbound.address;
+ alpn = outbound.alpn;
+ disableSessionResumption = outbound.disableSessionResumption;
+ } : null;
+ };
+ tag="proxy"
+ };
+
+ if( outbound.network == "ws" ){
+ ob.streamSettings.wsSettings = {
+ path = outbound.path;
+ headers = outbound.headers;
+ }
+
+ if( outbound.host ) {
+ if(!ob.streamSettings.wsSettings.headers){
+ ob.streamSettings.wsSettings.headers = {}
+ }
+ ob.streamSettings.wsSettings.headers.Host = outbound.host;
+ }
+ }
+ elseif( (outbound.network == "http") || (outbound.network == "h2") ){
+ var host = outbound.host;
+ if(type.isString(host)){host = {host}};
+
+ ob.streamSettings.httpSettings = {
+ path = outbound.path;
+ host = host;
+ }
+ }
+ elseif( outbound.network == "tcp" ){
+ if( outbound.type == "http" ){
+ ob.streamSettings.tcpSettings = {
+ header = {
+ request={
+ headers=..table.assign({
+ Connection={
+ "keep-alive"
+ };
+ Host=outbound.host;
+ Pragma="no-cache";
+ ["Accept-Encoding"]={
+ "gzip, deflate"
+ };
+ ["User-Agent"]={
+ "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36";
+ "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_2 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/53.0.2785.109 Mobile/14A456 Safari/601.1.46"
+ }
+ },outbound.headers);
+ method = outbound.httpMethod : "GET";
+ path = outbound.path;
+ version="1.1"
+ };
+ type="http";
+ }
+ }
+ }
+ }
+ elseif( outbound.network == "kcp" ){
+ ob.streamSettings.kcpSettings = {
+ congestion = outbound.congestion;
+ seed = outbound.seed;
+ mtu = outbound.mtu;
+ tti = outbound.tti;
+ uplinkCapacity = outbound.uplinkCapacity;
+ downlinkCapacity = outbound.downlinkCapacity;
+ readBufferSize = outbound.readBufferSize;
+ writeBufferSize = outbound.writeBufferSize;
+ header = {
+ type = outbound.type;
+ }
+ }
+ }
+ elseif( outbound.network == "quic" ){
+ ob.streamSettings.kcpSettings = {
+ key = outbound.key;
+ security = outbound.security ? outbound.security : "none";
+ header = {
+ type = outbound.type;
+ }
+ }
+ }
+
+ ..table.assign(proxyOutboundInCore,ob);
+ }
+ elseif(outbound.protocol=="vmess"){
+ if(!#outbound.security) outbound.security = "auto";
+
+ var ob = {
+ mux = (outbound.concurrency !== null) ? {
+ concurrency=outbound.concurrency;
+ enabled=outbound.concurrency ? ( outbound.concurrency > 0)
+ } : {
+ concurrency=8;
+ enabled=true
+ };
+ protocol="vmess";
+ settings={
+ vnext={
+ {
+ address=outbound.address;
+ level=outbound.level : null;
+ port=tonumber(outbound.port);
+ users={
+ {
+ alterId=tonumber(outbound.alterId) : 0;
+ email=outbound.email : "t@t.tt";
+ id=outbound.id;
+ security=outbound.security;
+ }
+ }
+ }
+ };
+ };
+ streamSettings={
+ network=outbound.network : "tcp";
+ security=#outbound.tls ? outbound.tls : null;
+ tlsSettings = #outbound.tls ? {
+ allowInsecure = !!outbound.allowInsecure;
+ serverName = outbound.sni;
+ } : null
+ };
+ tag="proxy"
+ };
+
+ if( outbound.network == "ws" ){
+ ob.streamSettings.wsSettings = {
+ path = outbound.path;
+ headers = outbound.headers;
+ }
+
+ if( outbound.host ) {
+ if(!ob.streamSettings.wsSettings.headers){
+ ob.streamSettings.wsSettings.headers = {}
+ }
+ ob.streamSettings.wsSettings.headers.Host = outbound.host;
+ }
+ }
+ elseif( (outbound.network == "http") || (outbound.network == "h2") ){
+ var host = outbound.host;
+ if(type.isString(host)){host = {host}};
+
+ ob.streamSettings.httpSettings = {
+ path = outbound.path;
+ host = host;
+ }
+ }
+ elseif( outbound.network == "tcp" ){
+ if( outbound.type == "http" ){
+ ob.streamSettings.tcpSettings = {
+ header = {
+ request={
+ headers=..table.assign({
+ Connection={
+ "keep-alive"
+ };
+ Host=outbound.host;
+ Pragma="no-cache";
+ ["Accept-Encoding"]={
+ "gzip, deflate"
+ };
+ ["User-Agent"]={
+ "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36";
+ "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_2 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/53.0.2785.109 Mobile/14A456 Safari/601.1.46"
+ }
+ },outbound.headers);
+ method=outbound.httpMethod : "GET";
+ path = outbound.path;
+ version="1.1"
+ };
+ type="http";
+ }
+ }
+ }
+ }
+ elseif( outbound.network == "kcp" ){
+ ob.streamSettings.kcpSettings = {
+ congestion = outbound.congestion;
+ seed = outbound.seed;
+ mtu = outbound.mtu;
+ tti = outbound.tti;
+ uplinkCapacity = outbound.uplinkCapacity;
+ downlinkCapacity = outbound.downlinkCapacity;
+ readBufferSize = outbound.readBufferSize;
+ writeBufferSize = outbound.writeBufferSize;
+ header = {
+ type = outbound.type;
+ }
+ }
+ }
+ elseif( outbound.network == "quic" ){
+ ob.streamSettings.kcpSettings = {
+ key = outbound.key;
+ security = outbound.security ? outbound.security : "none";
+ header = {
+ type = outbound.type;
+ }
+ }
+ }
+
+ ..table.assign(proxyOutboundInCore,ob);
+ }
+ elseif(outbound.protocol=="trojan" || outbound.protocol=="trojan-go"){
+ outbound.tls = #outbound.tls ? outbound.tls : "tls";
+ var ob = {
+ mux = (outbound.concurrency !== null) ? {
+ concurrency=outbound.concurrency;
+ enabled=outbound.concurrency ? ( outbound.concurrency > 0)
+ } : {
+ concurrency=-1;
+ enabled=false
+ };
+ protocol="trojan";
+ settings={
+ servers={
+ {
+ address=outbound.address;
+ email=outbound.email;
+ password=outbound.id;
+ port=outbound.port;
+ level=outbound.level : 0;
+ encryption=outbound.security;
+ flow=outbound.flow : (outbound.tls == "xtls" ? "xtls-rprx-direct" : null);
+ }
+ };
+ };
+ streamSettings={
+ network = outbound.network : "tcp";
+ security = #outbound.tls ? outbound.tls : "tls";
+
+ tlsSettings = (outbound.tls === "tls") ? {
+ allowInsecure = !!outbound.allowInsecure;
+ serverName = outbound.sni;
+ } : null
+ };
+ tag="proxy"
+ };
+
+ if( outbound.network == "ws" ){
+ ob.streamSettings.wsSettings = {
+ path = outbound.path;
+ headers = outbound.headers;
+ }
+
+ if( outbound.host ) {
+ if(!ob.streamSettings.wsSettings.headers){
+ ob.streamSettings.wsSettings.headers = {}
+ }
+ ob.streamSettings.wsSettings.headers.Host = outbound.host;
+ }
+ }
+ ..table.assign(proxyOutboundInCore,ob);
+ }
+ elseif(outbound.protocol=="shadowsocks"){
+ var ob = {
+ mux = (outbound.concurrency !== null) ? {
+ concurrency=outbound.concurrency;
+ enabled=outbound.concurrency ? ( outbound.concurrency > 0)
+ } : {
+ concurrency=-1;
+ enabled=false
+ };
+ protocol="shadowsocks";
+ settings={
+ servers={
+ {
+ address=outbound.address;
+ level=outbound.level : 0;
+ method=outbound.security;
+ ota=!!outbound.ota;
+ password=outbound.id;
+ port=outbound.port;
+ }
+ };
+ };
+ streamSettings={
+ network = outbound.network : "tcp";
+ };
+ tag="proxy"
+ };
+
+ ..table.assign(proxyOutboundInCore,ob);
+ }
+ elseif(outbound.protocol=="socks"){
+
+ var ob = {
+ mux = (outbound.concurrency !== null) ? {
+ concurrency=outbound.concurrency;
+ enabled=outbound.concurrency ? ( outbound.concurrency > 0)
+ } : {
+ concurrency=-1;
+ enabled=false
+ };
+ protocol="socks";
+ settings={
+ servers={
+ {
+ address=outbound.address;
+ port=outbound.port;
+ }
+ };
+ };
+ streamSettings={
+ network = outbound.network : "tcp";
+ };
+ tag="proxy"
+ };
+
+ if(#outbound.id){
+ var user,password = ..string.match(outbound.id,"([^\:]+)\:(.+)");
+ if(user && password){
+ ob.settings.servers[1].users = {
+ user = user;
+ password = password;
+ level = outbound.level : 0;
+ }
+ }
+ else{
+ ob.settings.servers[1].users = {
+ user = outbound.id;
+ level = outbound.level : 0;
+ }
+ }
+ }
+
+ ..table.assign(proxyOutboundInCore,ob);
+ }
+ elseif(outbound.protocol=="https" || outbound.protocol=="http"){
+
+ var ob = {
+ protocol="http";
+ settings={
+ servers={
+ {
+ address=outbound.address;
+ port=outbound.port;
+ }
+ };
+ };
+ streamSettings={
+ security = outbound.protocol=="https" ? "tls" : "none";
+ tlsSettings = (outbound.protocol=="https") ? {
+ allowInsecure = !!outbound.allowInsecure;
+ } : null;
+ };
+ tag="proxy"
+ };
+
+ if(#outbound.id){
+ var user,password = ..string.match(outbound.id,"([^\:]+)\:(.+)");
+ if(user && password){
+ ob.settings.servers[1].users = {
+ user = user;
+ password = password;
+ }
+ }
+ else{
+ ob.settings.servers[1].users = {
+ user = outbound.id;
+ }
+ }
+ }
+
+ ..table.assign(proxyOutboundInCore,ob);
+ }
+
+ ..string.save(jsonPath,..web.json.stringify(currentCore) );
+ return jsonPath;
+}
+
+
\ No newline at end of file
diff --git a/lib/v2ray/core/naive.aardio b/lib/v2ray/core/naive.aardio
new file mode 100644
index 0000000..3a461b5
--- /dev/null
+++ b/lib/v2ray/core/naive.aardio
@@ -0,0 +1,252 @@
+//naive 内核进程(NaïveProxy)
+import fsys;
+import wsock.tcp.server;
+import process.popen;
+import config;
+
+namespace v2ray.core.naive;
+
+var prcsNaive;
+import process.job.limitKill;
+restart = function(editor,outbound,naiveSocksPort){
+
+ if(prcsNaive){
+ prcsNaive.terminate();
+ prcsNaive = null;
+ }
+
+ var corePath = getPath(editor.hwnd);
+ if(!corePath){ return false,"启动失败,未找到 naive.exe"; }
+
+ var extraHeaders=null;
+ if(outbound.headers){
+ extraHeaders = ..web.joinHeaders(outbound.headers);
+ if(extraHeaders){
+ extraHeaders = "--extra-headers=" + extraHeaders;
+ }
+ }
+
+ var urlInfo = {
+ host = outbound.address;
+ port = outbound.port;
+ scheme = outbound.network;
+ }
+
+ if(outbound.id){
+ var u,p = ..string.match(outbound.id,"([^\:]+)\:([^\:]+)")
+ if(u && p){
+ urlInfo.user = u;
+ urlInfo.password = p;
+ }
+ else {
+ urlInfo.user = outbound.id;
+ }
+ }
+
+ var err;
+ prcsNaive,err = ..process.popen(corePath
+ ,corePath //必须补上这个参数
+ ,"--listen=socks://127.0.0.1:"+naiveSocksPort
+ ,"--proxy="+ ..inet.url.stringify(urlInfo)
+ ,extraHeaders
+ );
+
+ if(!prcsNaive){
+ ..publish("uiCommand.print",err:"启动 NaïveProxy Core 时遇到未知错误!");
+ return;
+ }
+ else{
+ ..publish("uiCommand.print","NaïveProxy Core 已启动,端口:" + naiveSocksPort);
+ }
+ prcsNaive.assignToJobObject(process.job.limitKill);
+ prcsNaive.codepage = 65001;
+ prcsNaive.logResponse(editor);
+
+ return true;
+}
+
+stop = function(){
+ if(prcsNaive){
+ prcsNaive.terminate();
+ prcsNaive = null;
+ }
+}
+
+var getNaiveCoreUrl = function(){
+ var msgDlg = ..win.dlg.message(..mainForm);
+ var form = msgDlg.create('正在获取 NaïveProxy 最新版本',,true)
+ form.icon = '\uF1D8';
+ form.progress.startProgress(50);
+
+ var url,versionTag = ..win.invoke(function(){
+ import process;
+ import inet.http;
+ var http = ..inet.http();
+ var url = http.location("https://github.com/klzgrad/naiveproxy/releases/latest");
+ http.close();
+
+ if(!url)return;
+
+ var tag = ..string.match(url,"[^/]+$")
+ if(!tag || (tag=="latest")) return;
+
+ return "https://github.com/klzgrad/naiveproxy/releases/download/"
+ + tag + "/naiveproxy-"+tag+"-win-" + (..process().isWow64() ? "x64" : "x86") + ".zip",tag
+ });
+
+ form.close();
+
+ return url,versionTag;
+}
+
+downloadCore = function(){
+ ..mainForm.disabled = true;
+
+ var url,versionTag = getNaiveCoreUrl();
+ var coreDir = getCoreDir();
+ if(!url) {
+ ..publish("uiCommand.print","请下载 NaïveProxy 解压到以下目录内:");
+ ..publish("uiCommand.print",coreDir);
+
+ ..mainForm.disabled = false;
+ self.lastDownloadingCoreFailed = true;
+ return null;
+ }
+
+ import zlib.httpFile;
+ if( ..zlib.httpFile.download(url,"正在下载 NaïveProxy "
+ ,..io.appData("/winXray/download/naive")
+ ,coreDir,,..mainForm.hwnd) ){
+
+ ..fsys.enum( coreDir, "naive.exe",
+ function(dir,filename,fullpath,findData){
+ if(filename){
+ ..fsys.copy(fullpath,..io.joinpath(coreDir, "naive.exe") )
+ ..fsys.delete( ..fsys.getParentDir(fullpath) )
+ return false;
+ }
+ }
+ );
+
+ ..mainForm.disabled = false;
+ self.lastDownloadingCoreFailed = null;
+
+ return ..io.exist(..io.joinpath(coreDir,"naive.exe"));
+ }
+ else {
+ ..mainForm.disabled = false;
+ self.lastDownloadingCoreFailed = true;
+
+ ..publish("uiCommand.print","请到以下网址下载 NaïveProxy:");
+ ..publish("uiCommand.print",url);
+
+ ..publish("uiCommand.print","下载后请解压到以下目录内:");
+ ..publish("uiCommand.print",coreDir);
+ }
+}
+
+
+getPath = function(hwnd){
+ var path = ..io.fullpath("/v2ray-core/naive-core/naive.exe");
+ if(..io.exist(path)){
+ return path;
+ }
+
+ var path = ..io.appData("/winXray/naive-core/naive.exe");
+ if(..io.exist(path)){
+ return path;
+ }
+
+ if(self.lastDownloadingCoreFailed){
+ return;
+ }
+
+ return downloadCore();
+}
+
+getCoreDir = function(hwnd){
+ var path = ..io.fullpath("/v2ray-core/naive-core/naive.exe");
+ if(..io.exist(path)){
+ return ..io.fullpath("/v2ray-core/naive-core/");
+ }
+
+ var path = ..io.appData("/winXray/naive-core/naive.exe");
+ if(..io.exist(path)){
+ return ..io.appData("/winXray/naive-core/");;;
+ }
+
+ var path = ..io.fullpath("/v2ray-core/v2ray.exe");
+ if(..io.exist(path)){
+ return ..io.fullpath("/v2ray-core/naive-core/");
+ }
+
+ var path = ..io.appData("/winXray/core/v2ray.exe");
+ if(..io.exist(path)){
+ return ..io.appData("/winXray/naive-core/");
+ }
+
+ var path = ..io.fullpath("/v2ray-core/");
+ if(..io.exist(path)){
+ return ..io.fullpath("/v2ray-core/naive-core/");
+ }
+
+ return ..io.appData("/winXray/naive-core/");
+}
+
+updateCore = function(){
+ ..mainForm.disabled = true;
+
+ var coreDir = getCoreDir();
+ var url,versionTag = getNaiveCoreUrl();
+ if(!url){
+ ..mainForm.disabled = false;
+ self.lastDownloadingCoreFailed = true;
+ return null;
+ }
+
+ import fsys;
+ fsys.delete(..io.appData("/v2ray/temp/naive/"))
+
+ import zlib.httpFile;
+ if( ..zlib.httpFile.download(url,"正在下载 NaïveProxy,版本:" + versionTag
+ ,..io.appData("/winXray/download/naive/")
+ ,..io.appData("/winXray/temp/naive/"),,..mainForm.hwnd) ){
+ ..mainForm.disabled = false;
+
+ var naivePath;
+ fsys.enum( ..io.appData("/winXray/temp/naive/"), "naive.exe",
+ function(dir,filename,fullpath,findData){
+ if(filename){
+ naivePath = fullpath;
+ return false;
+ }
+ }
+ );
+
+ if(naivePath){
+ import sysProxy;
+ sysProxy.reset(false);
+
+ import process.file;
+ process.file.terminate(..io.joinpath(coreDir,"naive.exe"));
+
+ ..io.createDir(coreDir);
+ fsys.copy(naivePath,..io.joinpath(coreDir,"naive.exe"));
+
+ return versionTag;
+ }
+ else {
+ self.lastDownloadingCoreFailed = true;
+ }
+ }
+ else {
+ ..mainForm.disabled = false;
+ self.lastDownloadingCoreFailed = true;
+ }
+}
+
+/**intellisense(v2ray.core.naive)
+restart(.(editor,outbound) = 重启启动 NaïveProxy 服务进程
+lastDownloadingCoreFailed = 上次下载 Core 是否失败,如果希望重新下载请重新赋值为 null
+end intellisense**/
+
diff --git a/lib/v2ray/core/rules.aardio b/lib/v2ray/core/rules.aardio
new file mode 100644
index 0000000..02dbfa5
--- /dev/null
+++ b/lib/v2ray/core/rules.aardio
@@ -0,0 +1,66 @@
+//rules 路由规则
+import v2ray.core;
+namespace v2ray.core.rules;
+
+var getRulesUrl = function(){
+ var msgDlg = ..win.dlg.message(..mainForm);
+ var form = msgDlg.create('正在获取路由规则最新版本',,true)
+ form.icon = '\uF1D8';
+ form.progress.startProgress(50);
+
+ var url,tag = ..win.invoke(function(){
+ import process;
+ import inet.http;
+ var http = ..inet.http();
+ var url = http.location("https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest");
+ http.close();
+
+ if(!url) return;
+
+ var tag = ..string.match(url,"[^/]+$")
+ if(!tag || (tag=="latest")) return;;
+
+ return "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/"
+ + tag + "/rules.zip",tag
+ });
+ form.close();
+
+ return url,tag;
+}
+
+
+update = function(){
+ ..mainForm.disabled = true;
+
+ var coreDir = ..v2ray.core.getCoreDir();
+ var url,versionTag = getRulesUrl();
+ if(!url){
+ ..mainForm.disabled = false;
+ return null;
+ }
+
+ import fsys;
+ fsys.delete( ..io.appData("/winXray/temp/rules/") );
+
+ import zlib.httpFile;
+ if( ..zlib.httpFile.download(url,"正在下载最新路由规则,版本:" + versionTag
+ ,..io.appData("/winXray/download/")
+ ,..io.appData("/winXray/temp/rules/"),,..mainForm.hwnd) ){
+ ..mainForm.disabled = false;
+
+ if(..io.exist(..io.appData("/winXray/temp/rules/geoip.dat"))){
+
+ ..io.createDir(coreDir);
+ fsys.copy(..io.appData("/winXray/temp/rules/*.*"),coreDir);
+ return versionTag;
+ }
+ }
+ else {
+ ..mainForm.disabled = false;
+ }
+}
+
+check = function(){
+ var coreDir = ..v2ray.core.getCoreDir();
+ if(!..io.exist( ..io.joinpath(coreDir,"geoip.dat") ) ) return update();
+}
\ No newline at end of file
diff --git a/lib/v2ray/core/ssr.aardio b/lib/v2ray/core/ssr.aardio
new file mode 100644
index 0000000..281b882
--- /dev/null
+++ b/lib/v2ray/core/ssr.aardio
@@ -0,0 +1,211 @@
+//ssr 内核进程(SSR)
+import wsock.tcp.server;
+import v2ray.core.ssrJson;
+import process.popen;
+import config;
+
+namespace v2ray.core.ssr;
+
+var prcsSsr;
+import process.job.limitKill;
+restart = function(editor,outbound,ssrSocksPort){
+
+ if(prcsSsr){
+ prcsSsr.terminate();
+ prcsSsr = null;
+ }
+
+ var corePath = getPath(editor.hwnd);
+ if(!corePath){ return false,"启动失败,未找到 ssr-client.exe"; }
+
+ import v2ray.core.ssrJson;
+ var jsonPath,err = ..v2ray.core.ssrJson.write(
+ ..io.joinpath(..io.splitpath(corePath).dir,"config.json")
+ ,outbound,ssrSocksPort);
+
+ if(!jsonPath){
+ return false,err:"启动失败,写入 SSR 配置文件遇到错误!";
+ }
+
+
+ var err;
+ prcsSsr,err = ..process.popen(corePath," -c=config.json" );
+ if(!prcsSsr){
+ ..publish("uiCommand.print",err:"启动 SSR Core 时遇到未知错误!");
+ return;
+ }
+ else{
+ ..publish("uiCommand.print","SSR Core 已启动,端口:" + ssrSocksPort);
+ }
+ prcsSsr.assignToJobObject(process.job.limitKill);
+ prcsSsr.codepage = 65001;
+ prcsSsr.logResponse(editor);
+
+ return true;
+}
+
+stop = function(){
+ if(prcsSsr){
+ prcsSsr.terminate();
+ prcsSsr = null;
+ }
+}
+
+var getSsrCoreUrl = function(){
+ var msgDlg = ..win.dlg.message(..mainForm);
+ var form = msgDlg.create('正在获取SSR Core(ShadowsocksR-native)最新版本',,true)
+ form.icon = '\uF1D8';
+ form.progress.startProgress(50);
+
+ var url,versionTag = ..win.invoke(function(){
+ import process;
+ import inet.http;
+ var http = ..inet.http();
+ var url = http.location("https://github.com/ShadowsocksR-Live/shadowsocksr-native/releases/latest");
+ http.close();
+
+ if(!url)return;
+
+ var tag = ..string.match(url,"[^/]+$")
+ if(!tag || (tag=="latest")) return;
+
+ return "https://github.com/ShadowsocksR-Live/shadowsocksr-native/releases/download/"
+ + tag + "/ssr-native-windows-" + (..process().isWow64() ? "x64" : "x86") + ".zip",tag
+ });
+
+ form.close();
+
+ return url,versionTag;
+}
+
+downloadCore = function(){
+ ..mainForm.disabled = true;
+
+ var url,versionTag = getSsrCoreUrl();
+ var coreDir = getCoreDir();
+ if(!url) {
+ ..publish("uiCommand.print","请下载 SSR Core(ShadowsocksR-native)解压到以下目录内:");
+ ..publish("uiCommand.print",coreDir);
+
+ ..mainForm.disabled = false;
+ self.lastDownloadingCoreFailed = true;
+ return null;
+ }
+
+ import zlib.httpFile;
+ if( ..zlib.httpFile.download(url,"正在下载 SSR Core(ShadowsocksR-native)"
+ ,..io.appData("/winXray/download/ssr")
+ ,coreDir,,..mainForm.hwnd) ){
+
+ ..mainForm.disabled = false;
+ self.lastDownloadingCoreFailed = null;
+
+ return ..io.exist(..io.joinpath(coreDir,"ssr-client.exe"));
+ }
+ else {
+ ..mainForm.disabled = false;
+ self.lastDownloadingCoreFailed = true;
+
+ ..publish("uiCommand.print","请到以下网址下载 SSR Core:");
+ ..publish("uiCommand.print",url);
+
+ ..publish("uiCommand.print","下载后请解压到以下目录内:");
+ ..publish("uiCommand.print",coreDir);
+ }
+}
+
+
+getPath = function(hwnd){
+ var path = ..io.fullpath("/v2ray-core/ssr-core/ssr-client.exe");
+ if(..io.exist(path)){
+ return path;
+ }
+
+ var path = ..io.appData("/winXray/ssr-core/ssr-client.exe");
+ if(..io.exist(path)){
+ return path;
+ }
+
+ if(self.lastDownloadingCoreFailed){
+ return;
+ }
+
+
+ return downloadCore();
+}
+
+getCoreDir = function(hwnd){
+ var path = ..io.fullpath("/v2ray-core/ssr-core/ssr-client.exe");
+ if(..io.exist(path)){
+ return ..io.fullpath("/v2ray-core/ssr-core/");
+ }
+
+ var path = ..io.appData("/winXray/ssr-core/ssr-client.exe");
+ if(..io.exist(path)){
+ return ..io.appData("/winXray/ssr-core/");;;
+ }
+
+ var path = ..io.fullpath("/v2ray-core/v2ray.exe");
+ if(..io.exist(path)){
+ return ..io.fullpath("/v2ray-core/ssr-core/");
+ }
+
+ var path = ..io.appData("/winXray/core/v2ray.exe");
+ if(..io.exist(path)){
+ return ..io.appData("/winXray/ssr-core/");
+ }
+
+ var path = ..io.fullpath("/v2ray-core/");
+ if(..io.exist(path)){
+ return ..io.fullpath("/v2ray-core/ssr-core/");
+ }
+
+ return ..io.appData("/winXray/ssr-core/");
+}
+
+updateCore = function(){
+ ..mainForm.disabled = true;
+
+ var coreDir = getCoreDir();
+ var url,versionTag = getSsrCoreUrl();
+ if(!url){
+ ..mainForm.disabled = false;
+ self.lastDownloadingCoreFailed = true;
+ return null;
+ }
+
+ import fsys;
+ fsys.delete(..io.appData("/v2ray/temp/ssr/"))
+
+ import zlib.httpFile;
+ if( ..zlib.httpFile.download(url,"正在下载 SSR Core(ShadowsocksR-native),版本:" + versionTag
+ ,..io.appData("/winXray/download/ssr/")
+ ,..io.appData("/winXray/temp/ssr/"),,..mainForm.hwnd) ){
+ ..mainForm.disabled = false;
+
+ if(..io.exist(..io.appData("/winXray/temp/ssr/ssr-client.exe"))){
+ import sysProxy;
+ sysProxy.reset(false);
+
+ import process.file;
+ process.file.terminate(..io.joinpath(coreDir,"ssr-client.exe"));
+
+ ..io.createDir(coreDir);
+ fsys.copy(..io.appData("/winXray/temp/ssr/*.*"),coreDir);
+
+ return versionTag;
+ }
+ else {
+ self.lastDownloadingCoreFailed = true;
+ }
+ }
+ else {
+ ..mainForm.disabled = false;
+ self.lastDownloadingCoreFailed = true;
+ }
+}
+
+/**intellisense(v2ray.core.ssr)
+restart(.(editor,outbound) = 重启启动 SSR 服务进程
+lastDownloadingCoreFailed = 上次下载 Core 是否失败,如果希望重新下载请重新赋值为 null
+end intellisense**/
diff --git a/lib/v2ray/core/ssrJson.aardio b/lib/v2ray/core/ssrJson.aardio
new file mode 100644
index 0000000..b76ccc4
--- /dev/null
+++ b/lib/v2ray/core/ssrJson.aardio
@@ -0,0 +1,40 @@
+//ssrJson 内核配置(SSR)
+import web.json;
+
+namespace v2ray.core.ssrJson;
+
+write = function(jsonPath,outbound,ssrSocksPort){
+ if(!outbound){ return; }
+ if(type(outbound.port) != type.number){
+ outbound.port = tonumber(outbound.port);
+ }
+
+ var current = {
+ client_settings = {
+ listen_address = "127.0.0.1";
+ listen_port = ssrSocksPort;
+ server = outbound.address;
+ server_port = outbound.port
+ };
+ connect_timeout = 6;
+ idle_timeout = 300;
+ method = outbound.security;
+ obfs = outbound.obfs : "plain";
+ obfs_param = outbound.obfsParam:"";
+ over_tls_settings = {
+ enable = outbound.tls == "tls";
+ path = outbound.path: "/abcd1234/";
+ server_domain = outbound.sni : "";
+ };
+ password = outbound.id;
+ protocol = outbound.network : "origin";
+ protocol_param = outbound.networkParam:"";
+ udp= outbound.udp === null? true : outbound.udp;
+ udp_timeout=6
+ }
+
+ ..string.save(jsonPath,..web.json.stringify(current) );
+ return jsonPath;
+}
+
+
\ No newline at end of file
diff --git a/lib/v2ray/core/xray.aardio b/lib/v2ray/core/xray.aardio
new file mode 100644
index 0000000..4a12b09
--- /dev/null
+++ b/lib/v2ray/core/xray.aardio
@@ -0,0 +1,76 @@
+//xray 内核
+import v2ray.core;
+namespace v2ray.core.xray;
+
+var getXrayCoreUrl = function(){
+ var msgDlg = ..win.dlg.message(..mainForm);
+ var form = msgDlg.create('正在获取 XRay Core 最新版本',,true)
+ form.icon = '\uF1D8';
+ form.progress.startProgress(50);
+
+ var url,tag = ..win.invoke(function(){
+ import process;
+ import inet.http;
+ var http = ..inet.http();
+ var url = http.location("https://github.com/XTLS/Xray-core/releases/latest");
+ http.close();
+
+ if(!url) return;
+
+ var tag = ..string.match(url,"[^/]+$")
+ if(!tag || (tag=="latest")) return;;
+
+ return "https://github.com/XTLS/Xray-core/releases/download/"
+ + tag + "/Xray-windows-" + (..process().isWow64() ? "64" : "32") + ".zip",tag
+ });
+ form.close();
+
+ return url,tag;
+}
+
+
+updateCore = function(){
+ ..mainForm.disabled = true;
+
+ var coreDir = ..v2ray.core.getCoreDir();
+ var url,versionTag = getXrayCoreUrl();
+ if(!url){
+ ..mainForm.disabled = false;
+ self.lastDownloadingCoreFailed = true;
+ return null;
+ }
+
+ import fsys;
+ fsys.delete( ..io.appData("/winXray/temp/xray/") );
+
+
+ import zlib.httpFile;
+ if( ..zlib.httpFile.download(url,"正在下载 Xray Core,版本:" + versionTag
+ ,..io.appData("/winXray/download/")
+ ,..io.appData("/winXray/temp/xray/"),,..mainForm.hwnd) ){
+ ..mainForm.disabled = false;
+
+ if(..io.exist(..io.appData("/winXray/temp/xray/xray.exe"))){
+ import sysProxy;
+ sysProxy.reset(false);
+
+ import process.file;
+ process.file.terminate(..io.joinpath(coreDir,"v2ray.exe"));
+ process.file.terminate(..io.joinpath(coreDir,"v2ctl.exe"));
+ fsys.delete(..io.joinpath(coreDir,"v2ctl.exe"));
+
+ ..io.createDir(coreDir);
+ fsys.copy(..io.appData("/winXray/temp/xray/xray.exe"),..io.joinpath(coreDir,"v2ray.exe"));
+
+ self.lastDownloadingCoreFailed = null;
+ return versionTag;
+ }
+ else {
+ self.lastDownloadingCoreFailed = true;
+ }
+ }
+ else {
+ ..mainForm.disabled = false;
+ self.lastDownloadingCoreFailed = true;
+ }
+}
\ No newline at end of file
diff --git a/lib/v2ray/github.aardio b/lib/v2ray/github.aardio
new file mode 100644
index 0000000..7f94965
--- /dev/null
+++ b/lib/v2ray/github.aardio
@@ -0,0 +1,46 @@
+//github 代理设置
+import v2ray.core;
+import process.popen;
+namespace v2ray.github;
+
+setProxy = function(enableProxy){
+ if(enableProxy===null){
+ enableProxy = (..config.proxy.mode === "pac") || (..config.proxy.mode === "proxy")
+
+ if(!..config.proxy.enableGitConfigGithub){
+ return;
+ }
+ }
+
+ var socksPort = ..v2ray.core.socksProxyPort;
+ if(!socksPort && enableProxy) return;
+
+ var git;
+ if(enableProxy){
+ git = ..process.popen("git config --global http.https://github.com.proxy socks5://127.0.0.1:" + socksPort)
+
+ var path = ..io.getSpecial(0x28/*_CSIDL_PROFILE*/,".ssh/config")
+ var str = ..string.load(path):"";
+ if(..string.find(str,"Host\s+github.com" ) ){
+ if(!..string.find(str,"Host\s+github.com\s+ProxyCommand\s+connect\s+\-S\s+127\.0\.0\.1\:\d+ \-a none \%h \%p" )){
+ str = ..string.replace(str,"Host\s+github.com",'Host github.com\r\n ProxyCommand connect -S 127.0.0.1:' + socksPort + ' -a none %h %p')
+ }
+ }
+ else {
+ str = str + '\r\n\r\nHost github.com\r\n ProxyCommand connect -S 127.0.0.1:' + socksPort + ' -a none %h %p'
+ }
+
+ ..string.save(path,str)
+ }
+ else {
+ git = ..process.popen("git config --global --unset http.https://github.com.proxy")
+ var path = ..io.getSpecial(0x28/*_CSIDL_PROFILE*/,".ssh/config")
+ var str = ..string.load(path):"";
+ if(..string.find(str,"Host\s+github.com" ) ){
+ if(..string.find(str,"Host\s+github.com\s+ProxyCommand\s+connect\s+\-S\s+127\.0\.0\.1\:\d+ \-a none \%h \%p" )){
+ str = ..string.replace(str,"Host\s+github.com\s+ProxyCommand\s+connect\s+\-S\s+127\.0\.0\.1\:\d+ \-a none \%h \%p",'Host github.com')
+ ..string.save(path,str)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/v2ray/outbounds.aardio b/lib/v2ray/outbounds.aardio
new file mode 100644
index 0000000..032b56e
--- /dev/null
+++ b/lib/v2ray/outbounds.aardio
@@ -0,0 +1,1148 @@
+//outbounds 出站代理
+import web.json;
+import inet.url;
+import win.clip;
+import crypt;
+import crypt.bin;
+
+namespace v2ray.outbounds;
+
+exportSharedLinks = function(outbounds){
+ var outString = {};
+ for i,outbound in ..table.eachIndex(outbounds){
+ if(outbound.protocol == "vmess"){
+ var json = ..web.json.stringify({
+ v = 2;
+ add = outbound.address;
+ aid = outbound.alterId;
+ id = outbound.id;
+ port = outbound.port;
+ net = outbound.network;
+ type = outbound.type;
+ path = outbound.path;
+ host = outbound.host;
+ tls = outbound.tls;
+ ps = outbound.ps;
+ })
+
+ var vmess = "vmess://" + ..crypt.encodeBin(json);
+ ..table.push(outString,vmess);
+ }
+ elseif(outbound.protocol == "shadowsocks"){
+ var ss = "ss://" + ..crypt.encodeBin( outbound.security + ":" + outbound.id + "@" + outbound.address + ":" + outbound.port) + "#" + outbound.address + ":" + outbound.port;
+ ..table.push(outString,ss);
+ }
+ elseif(outbound.protocol == "socks"){
+ var ss;
+ if(outbound.id) ss = outbound.protocol + "://" + ..inet.url.encode(outbound.id) + "@" + outbound.address + ":" + outbound.port;
+ else ss = outbound.protocol + "://" + outbound.address + ":" + outbound.port;
+ ..table.push(outString,ss);
+ }
+ elseif(outbound.protocol == "ssr" ){
+ var ssrUrl = outbound.address + ":" + outbound.port
+ + ":" + (outbound.network:"origin")+ ":" + (outbound.security:"")+ ":" + (outbound.obfs:"plain")
+ + ":" + ..crypt.bin.encodeUrlBase64(outbound.id:"");
+
+ var info = {};
+
+ if(#outbound.ps)info.remarks = ..crypt.bin.encodeUrlBase64(outbound.ps);
+ if(#outbound.obfsParam)info.obfsparam = ..crypt.bin.encodeUrlBase64(outbound.obfsParam);
+ if(#outbound.networkParam)info.protoparam = ..crypt.bin.encodeUrlBase64(outbound.networkParam);
+
+ if(#outbound.path)info.ot_path = ..crypt.bin.encodeUrlBase64(outbound.path);
+ if(#outbound.sni)info.ot_domain = ..crypt.bin.encodeUrlBase64(outbound.sni);
+ if(outbound.tls=="tls"){ info.ot_enable = "1"; }
+
+ if(..table.count(info)){
+ ssrUrl = ssrUrl +"/?"+ ..inet.url.stringifyParameters(info)
+ }
+
+ ..table.push(outString,outbound.protocol + "://" + ..crypt.encodeBin(ssrUrl) );
+ }
+ elseif(outbound.protocol == "trojan" || outbound.protocol == "trojan-go"){
+ var trojan;
+ if(outbound.id) trojan = outbound.protocol + "://" + ..inet.url.encode(outbound.id) + "@" + outbound.address + ":" + outbound.port;
+ else trojan = outbound.protocol + "://" + outbound.address + ":" + outbound.port;
+
+ var info = {};
+ if(outbound.network!="tcp") info.type = outbound.network;
+ if(outbound.sni){ info.sni = outbound.sni;}
+ info.host = outbound.host;
+ info.path = outbound.path;
+
+ if(..table.count(info)){
+ trojan = ..inet.url.appendExtraInfo(trojan,info)
+ }
+
+ if(outbound.ps){
+ trojan = trojan + "#" + ..inet.url.encode(outbound.ps);
+ }
+ ..table.push(outString,trojan);
+ }
+ elseif(outbound.protocol == "vless"){
+ var vless;
+ if(outbound.id) vless = "vless://" + ..inet.url.encode(outbound.id) + "@" + outbound.address + ":" + outbound.port;
+ else vless = "vless://" + outbound.address + ":" + outbound.port;
+
+ var info = {};
+ if(outbound.network!="tcp") info.type = outbound.network ;
+ if(outbound.security!="none") info.encryption = outbound.security;
+ if(outbound.tls) info.security = outbound.tls;
+ if(outbound.flow) info.flow = outbound.flow;
+ if(outbound.allowInsecure) info.allowInsecure = outbound.allowInsecure;
+ if(outbound.alpn) info.alpn = outbound.alpn;
+ if(outbound.disableSessionResumption) info.disableSessionResumption = outbound.disableSessionResumption;
+ if(outbound.sni){ info.sni = outbound.sni;}
+ info.host = outbound.host;
+ info.path = outbound.path;
+ info.seed = info.seed;
+ info.key = info.key;
+ info.headerType = info.type;
+
+ if(..table.count(info)){
+ vless = ..inet.url.appendExtraInfo(vless,info)
+ }
+
+ if(outbound.ps){
+ vless = vless + "#" + ..inet.url.encode(outbound.ps);
+ }
+ ..table.push(outString,vless);
+ }
+ elseif(outbound.protocol == "naive"){
+ var urlInfo = {
+ host = outbound.address;
+ port = outbound.port;
+ scheme = "naive+"+outbound.network;
+ location = outbound.ps;
+ }
+
+ if(outbound.headers){
+ urlInfo.extraInfo ={
+ ["extra-headers"] = outbound.headers
+ }
+ }
+
+ if(outbound.id){
+ var u,p = ..string.match(outbound.id,"([^\:]+)\:([^\:]+)")
+ if(u && p){
+ urlInfo.user = u;
+ urlInfo.password = p;
+ }
+ else {
+ urlInfo.user = outbound.id;
+ }
+ }
+
+ ..table.push(outString,..inet.url.stringify(urlInfo));
+ }
+ elseif((outbound.protocol == "https") || (outbound.protocol == "http")){
+ var urlInfo = {
+ host = outbound.address;
+ port = outbound.port;
+ scheme = "proxy";
+ location = outbound.ps;
+ }
+
+ if(outbound.protocol == "http"){
+ urlInfo.extraInfo ={
+ ["tls"] = "none"
+ }
+ }
+ elseif(outbound.allowInsecure){
+ urlInfo.extraInfo ={
+ ["allowInsecure"] = 1
+ }
+ }
+
+ if(outbound.id){
+ var u,p = ..string.match(outbound.id,"([^\:]+)\:([^\:]+)")
+ if(u && p){
+ urlInfo.user = u;
+ urlInfo.password = p;
+ }
+ else {
+ urlInfo.user = outbound.id;
+ }
+ }
+
+ ..table.push(outString,..inet.url.stringify(urlInfo));
+ }
+ }
+
+ return ..string.join(outString,'\r\n');
+}
+
+var _subscriptionResponseCache = {
+ @{_weak="kv"}
+}
+importFromString = function(str,subscribeUrl){
+ if(!str){ return; }
+ str = ..string.trim(str);
+
+ var jsonData;
+ if(..string.match(str,"%\[\]") || (
+ ..string.match(str,"%\{\}") && !..string.match(str,"%\{\}.+%\{\}")
+ ) ){
+
+ if(subscribeUrl){
+ var crc32 = ..string.crc32(str);
+ _subscriptionResponseCache[subscribeUrl] = crc32;
+ }
+ jsonData = ..web.json.tryParse(str);
+ }
+
+ if( ..table.isArray(jsonData) ){
+ for(i=#jsonData;1;-1){
+ if( !validOutbound(jsonData[i]) ) {
+ ..table.remove(jsonData,i);
+ }
+
+ if(subscribeUrl)jsonData[i].subscribeUrl = subscribeUrl;
+ }
+
+ return jsonData;
+ }
+ elseif( type(jsonData) == type.table ){
+ if( jsonData[["servers"]] ){
+
+ var servers = jsonData[["servers"]]
+ var outbounds = ..table.array();
+ for i,v in ..table.eachIndex(servers){
+ var outbound = ..table.assign(,v);
+ if(outbound.protocol === null){
+ outbound.protocol = (outbound.server_port&&outbound.password) ? "shadowsocks":"vless"
+ }
+
+ if(outbound.remarks){
+ outbound.ps = outbound.remarks;
+ outbound.remarks = null;
+ }
+
+ if(outbound.server){
+ outbound.address = outbound.server;
+ outbound.server = null;
+ }
+
+ if(outbound.server_port){
+ outbound.port = outbound.server_port;
+ outbound.server_port = null;
+ }
+
+ if(outbound.password){
+ if(outbound.id){
+ outbound.serverId = outbound.id;
+ }
+ outbound.id = outbound.password;
+ outbound.password = null;
+ }
+
+ if(outbound.method){
+ outbound.security = outbound.method;
+ outbound.method = null;
+ }
+
+ if(subscribeUrl)outbound.subscribeUrl = subscribeUrl;
+ ..table.push(outbounds,outbound);
+ }
+
+ return outbounds;
+ }
+ else {
+ if( validOutbound(jsonData) ) {
+ if(subscribeUrl)jsonData.subscribeUrl = subscribeUrl;
+ return {jsonData};
+ }
+ }
+ }
+
+ if( ..string.startWith(str,"http://")
+ || ..string.startWith(str,"https://")
+ || ..string.match(str,"^\s*/\N+\s*$") ){
+
+ import win.dlg.message;
+ var msgDlg = win.dlg.message(..mainForm);
+
+ var title = '正在获取订阅源 ... ';
+ var cfgSubscribeUrls = ..config.proxy.subscribeUrls;
+ for(i=#cfgSubscribeUrls;1;-1){
+ var sub = cfgSubscribeUrls[i]
+ if( (sub.url === str) ){
+ if(#sub.ps) title = '正在获取订阅源: ' + sub.ps;
+ ..config.proxy.save();
+ }
+ }
+
+ var form = msgDlg.create(title,,true)
+ form.progress.startProgress(50);
+
+ subscribeUrl = str;
+
+ if(..string.match(subscribeUrl,"^\s*/\N+\s*$") ){
+ if(!..string.find(subscribeUrl,"/|")){
+ subscribeUrl = ..inet.url.append("https://raw.githubusercontent.com",subscribeUrl);
+ }
+ else {
+ subscribeUrl = ..inet.url.append("https://github.com",subscribeUrl);
+ }
+ }
+
+ str = ..win.invoke(
+ function(subscribeUrl){
+ import inet.http;
+ import web.rest.github;
+ if( string.indexOf(subscribeUrl,"github.com")
+ || string.indexOf(subscribeUrl,"raw.githubusercontent.com")
+ ){
+
+ var ret = web.rest.github.getContent(subscribeUrl)
+ if(ret) return ret;
+ }
+
+ return inet.http().get(subscribeUrl);
+ },subscribeUrl
+ )
+
+ form.close();
+ if(!str){
+ return;
+ }
+
+ var existIndex;
+ var cfgSubscribeUrls = ..config.proxy.subscribeUrls : ..table.array();
+ for(i=#cfgSubscribeUrls;1;-1){
+ var sub = cfgSubscribeUrls[i]
+ if(sub.url==subscribeUrl){
+ sub.checked="启用";
+ existIndex=i;
+ break;
+ }
+ }
+ if(!existIndex){
+ var tUrl = ..inet.url.split(subscribeUrl);
+ ..table.push(cfgSubscribeUrls,{url=subscribeUrl;ps=tUrl ? tUrl.host : "";checked="启用"})
+ ..publish("uiCommand.subscriptionNew",cfgSubscribeUrls[#cfgSubscribeUrls]);
+ }
+ else{
+ ..publish("uiCommand.subscriptionNew",cfgSubscribeUrls[existIndex],existIndex);
+ }
+ ..config.proxy.subscribeUrls = cfgSubscribeUrls;
+ ..config.proxy.save();
+
+ var jsonData;
+ if(..string.match(str,"%\[\]") || ..string.match(str,"%\{\}")){
+ jsonData = ..web.json.tryParse(str);
+ }
+
+ if( type(jsonData) === type.table ){
+ return importFromString(str,subscribeUrl);
+ }
+ }
+
+ if(subscribeUrl){
+ var crc32 = ..string.crc32(str);
+ _subscriptionResponseCache[subscribeUrl] = crc32;
+ }
+
+ if(..string.match(str,"^\s*[\w=+/-_]+\s*$")){
+ str = ..crypt.decodeBin(str);
+ if(!str) return;
+ }
+
+ var outbounds = ..table.array();
+ for(line in ..string.lines(str) ){
+ if(#outbounds>=1500){
+ import win.dlg.message;
+ var msgDlg = win.dlg.message(..mainForm);
+ var form = msgDlg.warn("导入的节点数目过多,已导入1500个节点并中止操作!")
+
+ return outbounds;
+ }
+
+ if(line[1]=='/'# && line[2]=='/'#){
+ continue;
+ }
+
+ var vmess2 = ..string.match(line,`vmess\:\/\/[^\@\s]+\@[^\?\#\s\:]+<\:\d+>*\S*`);
+ if( vmess2 ) {
+ var vmessUrl = ..inet.url.split(vmess2)
+ if(vmessUrl.user && vmessUrl.host && vmessUrl.port){
+ var outbound = {
+ address = vmessUrl.host;
+ port = tonumber(vmessUrl.port) : 443;
+ id = vmessUrl.user;
+ network = "tcp";
+ protocol = "vmess";
+ tls = "tls";
+ };
+
+ if(vmessUrl.extraInfo){
+ var info = ..inet.url.splitParameters(vmessUrl.extraInfo);
+ outbound.sni = info.sni;
+ outbound.host = info.host;
+ outbound.path = info.path;
+ outbound.security = info.encryption;
+ outbound.seed = info.seed;
+ outbound.key = info.key;
+
+ outbound.network = info.type;
+ outbound.type = info.headerType; //kcp || quic
+
+ if(info.security) outbound.tls = info.security;
+ if(info.flow) outbound.flow = info.flow;
+ if(info.allowInsecure!==null) {
+ outbound.allowInsecure = (info.allowInsecure!=="0" ||info.allowInsecure!=="false" )
+ }
+ if(info.disableSessionResumption) outbound.disableSessionResumption = info.disableSessionResumption;
+ if(info.alpn) outbound.alpn = info.alpn;
+ }
+
+ if(vmessUrl.location){
+ outbound.ps = ..inet.url.decode(vmessUrl.location);
+ }
+
+ outbound.subscribeUrl = subscribeUrl;
+ ..table.push(outbounds,outbound);
+ }
+
+ continue;
+ }
+
+ var vmess = ..string.match(line,`vmess\:\/\/([\w=+/-_]+)`);
+ if( vmess ) {
+ var json = ..crypt.decodeBin(vmess);
+ var outbound = ..web.json.tryParse(json);
+ if(type(outbound)=="table"){
+ ..table.clear(outbound@._defined);
+ outbound.protocol = "vmess";
+ outbound.address = outbound.add;
+ outbound.alterId = tonumber(outbound.aid);
+ outbound.security = "auto";
+ outbound.network = outbound.net : "tcp";
+ outbound.net = null;
+ outbound.add = null;
+ outbound.aid = null;
+ outbound.v = null;
+ outbound.subscribeUrl = subscribeUrl;
+
+ if(outbound.ps){
+ var u,h,p = ..string.match(outbound.ps,"(.+)\@(.+)\:(\d+)")
+ if(u&&h&&p){
+ if(h && ..string.endWith(h,"jamjams.net") && subscribeUrl && ..string.match(subscribeUrl,"justmysocks\d+\.net")){
+ if(..string.match(outbound.address,"^\d+\.\d+\.\d+\.\d+$") ){
+ outbound.address = h;
+ }
+ }
+ outbound.ps = h;
+ }
+ }
+ ..table.push(outbounds,outbound);
+ }
+
+ continue;
+ }
+
+ var vless = ..string.match(line,`vless\:\/\/\S+`);
+ if( vless ) {
+ var vlessUrl = ..inet.url.split(vless)
+ if(vlessUrl.user && vlessUrl.host && vlessUrl.port){
+ var outbound = {
+ address = vlessUrl.host;
+ port = tonumber(vlessUrl.port) : 443;
+ id = vlessUrl.user;
+ network = "tcp";
+ protocol = "vless";
+ tls = "tls";
+ };
+
+ if(vlessUrl.extraInfo){
+ var info = ..inet.url.splitParameters(vlessUrl.extraInfo);
+ outbound.sni = info.sni;
+ outbound.host = info.host;
+ outbound.path = info.path;
+ outbound.security = info.encryption;
+ outbound.seed = info.seed;
+ outbound.key = info.key;
+
+ outbound.network = info.type;
+ outbound.type = info.headerType; //kcp || quic
+
+ if(info.security) outbound.tls = info.security;
+ if(info.flow) outbound.flow = info.flow;
+ if(info.allowInsecure!==null) {
+ outbound.allowInsecure = (info.allowInsecure!=="0" ||info.allowInsecure!=="false" )
+ }
+ if(info.disableSessionResumption) outbound.disableSessionResumption = info.disableSessionResumption;
+ if(info.alpn) outbound.alpn = info.alpn;
+ }
+
+ if(vlessUrl.location){
+ outbound.ps = ..inet.url.decode(vlessUrl.location);
+ }
+
+ outbound.subscribeUrl = subscribeUrl;
+ ..table.push(outbounds,outbound);
+ }
+
+ continue;
+ }
+
+ var ss,comment = ..string.match(line,`ss\:\/\/([^\s\#]+)(<#\S+>?)`);
+ if( ss ) {
+ var userinfo,address,port = ..string.match(ss,"^([^:]+)\@(.+)\:(\d+)")
+ if(!(userinfo&&address&&port)){
+ var str = ..crypt.bin.decodeUrlBase64(ss);
+ if(str){ ss = str; }
+
+ method,password,address,port = ..string.match(ss,"^(.+)\:(.+)\@(.+)\:(\d+)")
+ }
+ else {
+ userinfo = ..crypt.bin.decodeUrlBase64(userinfo);
+ if(userinfo){
+ method,password = ..string.match(userinfo,"^(.+)\:(.+)$")
+ }
+ }
+
+ if(address && password && port){
+ var outbound = {
+ address = address;
+ port = tonumber(port);
+ security = method;
+ id = password;
+ network = "tcp";
+ protocol = "shadowsocks"
+ };
+
+ if(comment){
+ comment = ..string.right(comment,-2);
+ comment = ..inet.url.decode(comment);
+ var u,h,p = ..string.match(comment,"(.+)\@(.+)\:(\d+)")
+ if(u&&h&&p){
+ if(h && ..string.endWith(h,"jamjams.net") && subscribeUrl && ..string.match(subscribeUrl,"justmysocks\d+\.net")){
+ if(..string.match(outbound.address,"^\d+\.\d+\.\d+\.\d+$") ){
+ outbound.address = h;
+ }
+ }
+
+ comment = h;
+ }
+
+ outbound.ps = comment;
+ }
+
+ outbound.subscribeUrl = subscribeUrl;
+ ..table.push(outbounds,outbound);
+ }
+
+ continue;
+ }
+
+ var trojan = ..string.match(line,`trojan\:\/\/\S+`);
+ if( trojan ) {
+ var trojanUrl = ..inet.url.split(trojan)
+ if(trojanUrl.user && trojanUrl.host){
+ var outbound = {
+ address = trojanUrl.host;
+ port = tonumber(trojanUrl.port) : 443;
+ id = trojanUrl.user;
+ network = "tcp";
+ protocol = "trojan"
+ };
+
+ if(trojanUrl.extraInfo){
+ var info = ..inet.url.splitParameters(trojanUrl.extraInfo);
+ outbound.sni = info.sni || info.peer;
+
+ outbound.host = info.host;
+ outbound.path = info.path;
+
+ if(info.type && info.type!=="original"){
+ outbound.network = info.type;
+ if(outbound.network=="h2"){
+ outbound.network="http"
+ }
+ }
+
+ outbound.security = info.encryption;
+ }
+
+ if(trojanUrl.location){
+ outbound.ps = ..inet.url.decode(trojanUrl.location);
+ }
+
+ outbound.subscribeUrl = subscribeUrl;
+ ..table.push(outbounds,outbound);
+ }
+
+ continue;
+ }
+
+ var trojan = ..string.match(line,`trojan-go\:\/\/\S+`);
+ if( trojan ) {
+ var trojanUrl = ..inet.url.split(trojan)
+ if(trojanUrl.user && trojanUrl.host){
+ var outbound = {
+ address = trojanUrl.host;
+ port = tonumber(trojanUrl.port) : 443;
+ id = trojanUrl.user;
+ network = "tcp";
+ protocol = "trojan-go"
+ };
+
+ if(trojanUrl.extraInfo){
+ var info = ..inet.url.splitParameters(trojanUrl.extraInfo);
+ outbound.sni = info.sni || info.peer;
+ outbound.host = info.host;
+ outbound.path = info.path;
+ if(info.allowInsecure!==null) {
+ outbound.allowInsecure = (info.allowInsecure!=="0" ||info.allowInsecure!=="false" )
+ }
+
+ if(info.type && info.type!=="original"){
+ outbound.network = info.type;
+ if(outbound.network=="h2"){
+ outbound.network="http"
+ }
+ }
+
+ outbound.security = info.encryption;
+ }
+
+ if(trojanUrl.location){
+ outbound.ps = ..inet.url.decode(trojanUrl.location);
+ }
+
+ outbound.subscribeUrl = subscribeUrl;
+ ..table.push(outbounds,outbound);
+ }
+
+ continue;
+ }
+
+ var ssrBase64 = ..string.match(line,`ssr\:\/\/([\w=+/-_]+)`);
+ if( ssrBase64 ) {
+ var ssrUrl = ..crypt.bin.decodeUrlBase64(ssrBase64);
+ if(ssrUrl){
+ var ssrInfo,ssrParam = ..string.match(ssrUrl,"(.+)\/\?(.+)")
+ var info = ..string.split(ssrInfo:ssrUrl,':');
+ var outbound = {
+ address = info[1];
+ port = info[2];
+ network = info[3];
+ security = info[4];
+ obfs = info[5];
+ protocol = "ssr";
+ }
+
+ outbound.id = ..crypt.bin.decodeUrlBase64(info[6]:"");
+ if(ssrParam){
+ var params = ..inet.url.splitParameters(ssrParam);
+ if(params){
+ outbound.ps = ..crypt.bin.decodeUrlBase64(params.remarks);
+ outbound.obfsParam = ..crypt.bin.decodeUrlBase64(params.obfsparam);
+ outbound.protoParam = ..crypt.bin.decodeUrlBase64(params.protoparam);
+
+ if(params.group){
+ //outbound.subscribeGroup = ..crypt.bin.decodeUrlBase64(params.group);
+ }
+
+ if(params.ot_enable && (params.ot_enable!="0")){ outbound.tls = "tls"; }
+ outbound.path = ..crypt.bin.decodeUrlBase64(params.ot_path);
+ outbound.sni = ..crypt.bin.decodeUrlBase64(params.ot_domain);
+ }
+ }
+
+ outbound.subscribeUrl = subscribeUrl;
+
+ if(outbound.address && outbound.port){
+ ..table.push(outbounds,outbound);
+ continue;
+ }
+ }
+ }
+
+ var socks = ..string.match(line,`socks\:(\/\/\S+)`);
+ if( socks ) {
+ var socksUrl = ..inet.url.split("socks5:"+socks)
+ if( socksUrl.host && socksUrl.port){
+ var outbound = {
+ address = socksUrl.host;
+ port = tonumber(socksUrl.port);
+ network = "tcp";
+ protocol = "socks"
+ };
+
+ if(socksUrl.user && socksUrl.password){
+ outbound.id = socksUrl.user +":"+ socksUrl.password
+ }
+
+ if(socksUrl.location){
+ outbound.ps = ..inet.url.decode(socksUrl.location);
+ }
+
+ outbound.subscribeUrl = subscribeUrl;
+ ..table.push(outbounds,outbound);
+ }
+
+ continue;
+ }
+
+ var proxy = ..string.match(line,`proxy\:\/\/\S+`);
+ if( proxy ) {
+ var proxyUrl = ..inet.url.split(proxy)
+ if( proxyUrl.host && proxyUrl.port){
+ var outbound = {
+ address = proxyUrl.host;
+ port = tonumber(proxyUrl.port);
+ network = "tcp";
+ protocol = "https"
+ };
+
+ if(proxyUrl.user && proxyUrl.password){
+ outbound.id = proxyUrl.user +":"+ proxyUrl.password
+ }
+
+ if(proxyUrl.extraInfo){
+ var info = ..inet.url.splitParameters(proxyUrl.extraInfo);
+ if(info.tls==="none") {
+ outbound.protocol = "http";
+ }
+
+ if(info.allowInsecure){
+ outbound.allowInsecure = (info.allowInsecure!=="0" ||info.allowInsecure!=="false" )
+ }
+ }
+
+ if(proxyUrl.location){
+ outbound.ps = ..inet.url.decode(proxyUrl.location);
+ }
+
+ outbound.subscribeUrl = subscribeUrl;
+ ..table.push(outbounds,outbound);
+ }
+
+ continue;
+ }
+
+ var naive,naiveNetwork = ..string.match(line,`(naive\+(\w+)\:\/\/\S+)`);
+ if( naive ) {
+ var naiveUrl = ..inet.url.split(naive)
+ if( naiveUrl.host ){
+ var outbound = {
+ address = naiveUrl.host;
+ port = tonumber(naiveUrl.port) : 443;
+ id = naiveUrl.user;
+ network = naiveNetwork;
+ protocol = "naive"
+ };
+
+ if(naiveUrl.user && naiveUrl.password){
+ outbound.id = naiveUrl.user +":"+ naiveUrl.password
+ }
+
+ if(naiveUrl.extraInfo){
+ var info = ..inet.url.splitParameters(naiveUrl.extraInfo);
+ if(info["extra-headers"]){
+ outbound.headers = info["extra-headers"];
+ }
+ }
+ if(naiveUrl.location){
+ outbound.ps = ..inet.url.decode(naiveUrl.location);
+ }
+
+ outbound.subscribeUrl = subscribeUrl;
+ ..table.push(outbounds,outbound);
+ }
+
+ continue;
+ }
+
+ var clashJson = ..string.match(line,`^\s*-\s*(%\{\})\s*$`);
+ if( clashJson ) {
+ var outbound = ..web.json.tryParse(clashJson)
+ if(type(outbound)=="table"){
+ if(outbound.type){
+ if(outbound.type=="ssr"){
+ outbound.network = outbound.protocol;
+ outbound.protocol = "ssr";
+
+ outbound.networkParam = outbound.protocol_param;
+ outbound.protocol_param = null;
+
+ outbound.sni = outbound.ot_domain;
+ outbound.path = outbound.ot_path;
+ outbound.tls = outbound.ot_enable ? "tls" : null;
+ }
+
+ if(outbound.type=="ss"){
+ outbound.type = "shadowsocks";
+ outbound.network = "tcp";
+ }
+ outbound.protocol = outbound.type;
+ outbound.type = null;
+ }
+
+ if( validOutbound(outbound) ){
+ outbound.subscribeUrl = subscribeUrl;
+ ..table.push(outbounds,outbound );
+ }
+ continue;
+ }
+ }
+
+ var json = ..string.match(line,`^\s*%\{\}\s*$`);
+ if( json ) {
+ var outbound = ..web.json.tryParse(json)
+ if(type(outbound)=="table"){
+ if( validOutbound(outbound) ) ..table.push(outbounds,outbound );
+ continue;
+ }
+ }
+ }
+
+ return outbounds;
+}
+
+importFromClipboard = function(){
+ var str = ..win.clip.read();
+ if(!str){ return; }
+
+ str = ..string.trim(str,'"\'\t\r\n ');
+ return importFromString(str);
+}
+
+validAll = function(outbounds){
+ for(i=#outbounds;1;-1){
+ if(!validOutbound(outbounds[i])){
+ ..table.remove(outbounds,i);
+ }
+ }
+
+ return outbounds;
+}
+
+validOutbound = function(outbound){
+ if(type(outbound)!="table"){ return; }
+
+ outbound.obfsParam = outbound.obfs_param;
+ outbound.obfs_param = null;
+
+ if(outbound.aid){
+ outbound.alterId = outbound.aid;
+ outbound.aid = null;
+ }
+
+ if(outbound.add){
+ outbound.address = outbound.add;
+ outbound.add = null;
+ ..table.define(outbound);
+ }
+
+ if(outbound.net){
+ outbound.network = outbound.net;
+ outbound.net = null;
+ ..table.define(outbound);
+ }
+
+ if(outbound.peer ){
+ if(#outbound.peer) outbound.sni = outbound.peer;
+ outbound.peer = null;
+ ..table.define(outbound);
+ }
+
+ if(!outbound.security){
+ if(outbound.method && outbound.method!="none"){
+ outbound.security = outbound.method;
+ }
+ if(outbound.cipher && outbound.cipher!="none" && outbound.cipher!="auto"){
+ outbound.security = outbound.cipher;
+ }
+ outbound.cipher = null;
+ outbound.method = null;
+ }
+
+ if(!outbound.address){
+ if(outbound.server){
+ outbound.address = outbound.server;
+ outbound.server = null;
+ }
+ }
+
+ if(!outbound.ps){
+ if(outbound.remarks){
+ outbound.ps = outbound.remarks;
+ outbound.remarks = null;
+ }
+ elseif(outbound.name){
+ outbound.ps = outbound.name;
+ outbound.name = null;
+ }
+ }
+
+ if(!outbound.port){
+ if(outbound.server_port){
+ outbound.port = outbound.server_port;
+ outbound.server_port = null;
+
+ if(!outbound.protocol && outbound.password){
+ outbound.protocol = "shadowsocks";
+ }
+ }
+ else {
+ outbound.port=443;
+ }
+ }
+
+ if(!outbound.protocol){
+ outbound.protocol = "vmess";
+ if(outbound.ps && (..string.find(outbound.ps,"@@vless") || ..string.find(outbound.ps,"@@xtls"))){
+ outbound.protocol = "vless";
+ }
+ }
+
+ if(!outbound.id){
+ if(outbound.password){
+ outbound.id = outbound.password;
+ outbound.password = null;
+ }
+ if(outbound.uuid){
+ outbound.id = outbound.uuid;
+ outbound.uuid = null;
+ }
+ }
+
+ if(outbound["skip-cert-verify"]){
+ outbound.allowInsecure = outbound["skip-cert-verify"];
+ outbound["skip-cert-verify"] = null;
+ }
+
+ if(outbound["ws-path"]){
+ outbound.path = outbound["ws-path"];
+ outbound["ws-path"] = null;
+ }
+
+ if(outbound["ws-headers"]){
+ outbound.headers = outbound["ws-headers"];
+ outbound["ws-headers"] = null;
+ }
+
+ if(type(outbound.tls)!="string"){
+ if(outbound.tls) outbound.tls = "tls";
+ else outbound.tls = "";
+ }
+
+ if(outbound.servername){
+ outbound.host = outbound.servername;
+ outbound.servername = null;
+ }
+
+ var httpOpts = outbound["http-opts"];
+ if(httpOpts){
+ if(!..table.count(httpOpts)){
+ httpOpts = outbound["h2-opts"] : httpOpts;
+ }
+
+ if(httpOpts.method){
+ outbound.httpMethod = httpOpts.method;
+ }
+
+ if(httpOpts.path){
+ outbound.path = httpOpts.path;
+ }
+
+ if(httpOpts.headers){
+ outbound.headers = httpOpts.headers;
+ }
+
+ if(httpOpts.host){
+ outbound.host = httpOpts.host;
+ }
+ }
+
+ if(outbound.headers){
+ var headers = {};
+ for k,v in ..table.eachName(outbound.headers){
+ var k = ..string.replace("HOST","(\a)(\a+)",lambda(a,b) ..string.upper(a) + ..string.lower(b) );
+ headers[k] = v;
+ }
+ outbound.headers = headers;
+
+ if(outbound.headers.Host){
+ if(outbound.headers.Host==outbound.host){
+ outbound.headers.Host = null;
+ }
+ elseif(!outbound.host){
+ outbound.host = outbound.headers.Host;
+ outbound.headers.Host = null;
+ }
+ }
+
+ if(!..table.count(outbound.headers)){
+ outbound.headers = null;
+ }
+ }
+
+ outbound["http-opts"] = null;
+ outbound["h2-opts"] = null;
+ outbound.country = null;
+ outbound.v = null;
+
+ ..table.define(outbound);
+
+ if(outbound.address){
+ return outbound;
+ }
+}
+
+updateSubscription = function(outbondSubscribeUrlMap){
+
+ var cfgOutbounds = ..config.proxy.outbounds : ..table.array();
+ if(!outbondSubscribeUrlMap) {
+ outbondSubscribeUrlMap = {}
+
+ for(i=#cfgOutbounds;1;-1){
+ var outbound = cfgOutbounds[i]
+ if(outbound.subscribeUrl){
+ outbondSubscribeUrlMap[outbound.subscribeUrl] = true;
+ }
+ }
+
+ var cfgSubscribeUrls = ..config.proxy.subscribeUrls;
+ for(i=#cfgSubscribeUrls;1;-1){
+ var sub = cfgSubscribeUrls[i]
+ if(sub.checked === "启用") {
+ outbondSubscribeUrlMap[sub.url] = true;
+ }
+ else {
+ outbondSubscribeUrlMap[sub.url] = null;
+ }
+ }
+
+ if(!..table.count(outbondSubscribeUrlMap)){
+ ..mainForm.msgWarn('当前未启用任何订阅源,\n请先复制订阅源网址到剪贴板然后点击「批量导入链接」!');
+ return;
+ }
+ }
+
+ var count = 0;
+ for(url,data in outbondSubscribeUrlMap){
+ var impOutbounds = ..v2ray.outbounds.importFromString(url);
+ if(#impOutbounds){
+ for(i=#cfgOutbounds;1;-1){
+ var outbound = cfgOutbounds[i]
+ if(outbound.subscribeUrl==url){
+ ..table.remove( cfgOutbounds,i );
+ }
+ }
+
+ ..table.append(cfgOutbounds,impOutbounds);
+ count = count + #impOutbounds;
+ }
+ }
+
+ ..config.proxy.save();
+ ..publish("outbounds.updateConfigJson");
+ ..publish("uiCommand.restartV2RayCore",cfgOutbounds)
+ ..mainForm.msgOk("已刷新" + count + "个订阅服务器。",1500);
+
+ return count;
+}
+
+autoUpdateSubscription = function(){
+ var outbondSubscribeUrlMap = {}
+ var cfgSubscribeUrls = ..config.proxy.subscribeUrls;
+ for(i=#cfgSubscribeUrls;1;-1){
+ var sub = cfgSubscribeUrls[i]
+ if(!#sub.url){
+ continue;
+ }
+
+ if(sub.checked === "启用") {
+ outbondSubscribeUrlMap[sub.url] = true;
+ }
+ }
+
+ if(!..table.count(outbondSubscribeUrlMap)){
+ return;
+ }
+
+ ..thread.invoke(
+ function(winform,outbondSubscribeUrlMap,responseCache){
+ import inet.http;
+ import web.rest.github;
+
+ var http = inet.http();
+ for(url,v in outbondSubscribeUrlMap){
+
+ if( string.indexOf(url,"github.com")
+ || string.indexOf(url,"raw.githubusercontent.com")
+ ){
+ outbondSubscribeUrlMap[url] = web.rest.github.getContent(url)
+ }
+ else{
+ outbondSubscribeUrlMap[url] = http.get(url);
+ }
+
+ if(!outbondSubscribeUrlMap[url]){
+ continue;
+ }
+
+ if(responseCache){
+ if(responseCache[url] && responseCache[url]===..string.crc32(outbondSubscribeUrlMap[url])){
+ outbondSubscribeUrlMap[url] = null;
+ }
+ }
+ }
+
+ winform.publish("thread.subscriptionUpdated",outbondSubscribeUrlMap)
+ },..mainForm,outbondSubscribeUrlMap,_subscriptionResponseCache
+ )
+}
+
+var currentActiveOutbound = ..globalActiveOutbound;
+..subscribe("activeOutbound",function(address){
+ currentActiveOutbound = address;
+} )
+
+..subscribe("thread.subscriptionUpdated",function(outbondSubscribeUrlMap){
+ if(currentActiveOutbound){
+ return;
+ }
+
+ var cfgOutbounds = ..config.proxy.outbounds : ..table.array();
+
+ var count = 0;
+ for(url,data in outbondSubscribeUrlMap){
+
+ var impOutbounds = ..v2ray.outbounds.importFromString(data,url);
+ if(#impOutbounds){
+ for(i=#cfgOutbounds;1;-1){
+ var outbound = cfgOutbounds[i]
+ if(outbound.subscribeUrl==url){
+ ..table.remove( cfgOutbounds,i );
+ }
+ }
+
+ ..table.append(cfgOutbounds,impOutbounds);
+ count = count + #impOutbounds;
+ }
+ }
+
+ if(!count){
+ return;
+ }
+
+ ..config.proxy.outbounds = cfgOutbounds;
+ ..config.proxy.save();
+
+ ..publish("outbounds.updateConfigJson");
+ ..publish("uiCommand.restartV2RayCore")
+ ..publish("uiCommand.print","已自动刷新" + count + "个订阅服务器。")
+} )
+
+/**intellisense(v2ray.outbounds)
+exportSharedLinks(.(outbounds) = 导出分享链接
+importFromString(.(str,subscribeUrl) = 导入分享链接
+importFromClipboard() = 自剪贴板导入分享链接
+autoUpdateSubscription() = 自动并静默更新订阅源
+updateSubscription() = 更新或自剪贴板导入订阅源\n可选在参数中用一个表自定义要更新的订阅地址,\n参数表中键为url,值为true
+end intellisense**/
diff --git a/lib/v2ray/pacServer.aardio b/lib/v2ray/pacServer.aardio
new file mode 100644
index 0000000..ad61015
--- /dev/null
+++ b/lib/v2ray/pacServer.aardio
@@ -0,0 +1,142 @@
+//pacServer 自动代理服务
+import config;
+import wsock.tcp.simpleHttpServer;
+import inet.http;
+import inet.url;
+
+namespace v2ray.pacServer;
+$serverMain = ..wsock.tcp.simpleHttpServer.mainThread(
+ function(response,request,session){
+
+ if(request.path=="/proxy.pac"){
+
+ var pacData = ..string.load(pacPath);
+ var proxPorts = inboundPort.get();
+ if(!proxPorts[["socksProxy"]]){
+ response.errorStatus(404);
+ return;
+ }
+
+ var reps = ..string.replace(pacData,"var\s+proxy\s+=\s+%''","var proxy = 'SOCKS5 "+ request.environ.SERVER_NAME +":"+proxPorts.socksProxy
+ +";SOCKS "+ request.environ.SERVER_NAME +":"+proxPorts.socksProxy
+ +";PROXY "+ request.environ.SERVER_NAME +":"+proxPorts.httpProxy +"'");
+
+ var useHttp = useHttpProxy.get();
+ if(!useHttp){
+ var ua = request.headers["user-agent"];
+ if( ua && ..string.find(ua,"WinHttp-Autoproxy-Service/")){
+ useHttp = true;
+ }
+ }
+
+ if(useHttp){
+ reps = ..string.replace(pacData,"var\s+proxy\s+=\s+%''","var proxy = 'PROXY "+ request.environ.SERVER_NAME +":"+proxPorts.httpProxy +"'");
+ }
+
+ response.contentType = "application/x-ns-proxy-autoconfig";
+ response.write(reps);
+ }
+ }
+);
+$serverMain.threadNum = 50;
+
+var pacPath = ..io.appData("/winXray/pac.txt");
+resetPac = function(){
+ ..string.save(pacPath,$"/pac.txt" )
+}
+
+if( ! ..io.exist(pacPath) ){
+ resetPac();
+}
+
+loadPacText = function(){
+ return ..io.exist(pacPath) ? ..string.load(pacPath) || $"/pac.txt";
+}
+
+savePacText = function(json){
+ var str = ..string.replace($"/pac.txt","var\s+rules\s*=\s*%\[\]","var rules = " + json);
+ ..string.save(pacPath,str );
+}
+
+var inboundPort = ..thread.var();
+var useHttpProxy = ..thread.var();
+restart = function(){
+ useHttpProxy.set(!..config.proxy.useSocksPac);
+
+ $serverMain.threadGlobal = {
+ inboundPort = inboundPort;
+ pacPath = pacPath;
+ useHttpProxy = useHttpProxy;
+ }
+
+ var pacPort = ..config.proxy.pacPort;
+ if( (! pacPort) || pacPort >= 49152 ){ pacPort = ..wsock.tcp.server.getFreePort("127.0.0.1",1083,10803,10813,44823) }
+
+ var currentIp,currentPort = $serverMain.getLocalIp();
+ if(currentIp!==..config.core.default.inbounds[[1]][["listen"]]
+ || currentPort != pacPort ){
+ $serverMain.stop();
+
+ var ok,err = $serverMain.start(
+ ..config.core.default.inbounds[[1]][["listen"]] : "127.0.0.1",pacPort );
+ if(!ok){
+ ..publish("uiCommand.print","启动PAC服务器失败",err)
+ return false,err;
+ }
+
+ ..publish("uiCommand.print","PAC服务器已启动",getUrl())
+ ..publish("pacServer.restarted",pacPort);
+ }
+
+ return true;
+}
+
+stop = function(){
+ if($serverMain){
+ $serverMain.stop();
+ }
+}
+
+updateUseHttpProxy = function(httpProxy){
+ useHttpProxy.set(httpProxy);
+}
+
+updateConfig = function(socksProxyPort,httpProxyPort){
+ if(socksProxyPort && httpProxyPort){
+ inboundPort.set( {socksProxy=socksProxyPort;httpProxy=httpProxyPort} );
+ }
+}
+
+..subscribe("v2RayCore.restarted",function(socksProxyPort,httpProxyPort){
+ updateConfig(socksProxyPort,httpProxyPort);
+} )
+
+getUrl = function(localIp){
+ var url = $serverMain.getUrl("/proxy.pac?" + ..time.tick() )
+ if(!url){ return }
+
+ var tUrl = ..inet.url.split(url);
+ if(!localIp){
+ tUrl.host = "127.0.0.1"
+ }
+ else {
+ tUrl.host = ..wsock.tcp.client.getLocalIp("www.baidu.com");
+ }
+
+ return tostring(tUrl);
+}
+
+getPort = function(){
+ var ip,port = $serverMain.getLocalIp();
+ return port;
+}
+
+
+/**intellisense(v2ray.pacServer)
+stop() = 停止PAC服务器
+restart() = 重启PAC服务器
+getUrl(.(localIp) = 返回PAC服务地址
+getPort() = 返回PAC端口
+updateConfig(.(socksProxyPort,httpProxPort) = 更新代理端口或PAC数据
+resetPac() = 重置为默认PAC
+end intellisense**/
diff --git a/main.aardio b/main.aardio
new file mode 100644
index 0000000..522c488
--- /dev/null
+++ b/main.aardio
@@ -0,0 +1,381 @@
+/*启动参数检测{{*/
+if(_ARGV.github){
+ loadcodex("\forms\main\tools\github.aardio");
+ return;
+}
+if(_ARGV.uwp){
+ loadcodex("\forms\main\tools\uwpExemption.aardio");
+ return;
+}
+elseif(_ARGV.sshInstall){
+ import fsys.wow64;
+ import process;
+ import console;
+ console.open();
+
+ var prcs;
+ fsys.wow64.disableRedirection(
+ function(){
+ var dest,port = string.match(_ARGV.sshInstall,"(.+)\:(\d+)");
+ if(dest&&port){
+ _ARGV.sshInstall = "-p" + port +" " + dest;
+ }
+
+ prcs = process("ssh","-t " +_ARGV.sshInstall + ` "echo -e '安装完成以后,您可以一次性复制所有服务器账号配置 - 然后在 winXray 主界面点击\e[1;31m「批量导入链接」\e[0m即可,winXray将逐行识别有效的服务器分享链接或通用JSON配置,并忽略无效的行。如果 CentOS 8安装失败 - 可尝试更换为 CentOS 7 并重新安装。\n';firewall-cmd --permanent --add-port=80/tcp;firewall-cmd --permanent --add-port=443/tcp;firewall-cmd --reload;iptables -A INPUT -p tcp --dport 80 -j ACCEPT;iptables -A INPUT -p tcp --dport 443 -j ACCEPT;wget -P /root -N --no-check-certificate ""https://raw.githubusercontent.com/mack-a/v2ray-agent/master/install.sh"" && chmod 700 /root/install.sh && /root/install.sh"`)
+ if(!prcs){
+ if(_WIN10_LATER){
+ import process.control;
+ process.control("ms-settings:optionalfeatures");
+ console.log("请检查是否指定了正确的SSH端口,或尝试重新安装 OpenSSH.Client");
+ }
+ else {
+ console.log("此功能仅支持 Windows 10 系统");
+ }
+ }
+ else {
+ import process.job.limitKill;
+ prcs.assignToJobObject(process.job.limitKill);
+ prcs.wait();
+ }
+
+ console.pause();
+ }
+ )
+
+ return;
+}
+elseif(_ARGV.sshLogin){
+ import fsys.wow64;
+ import process;
+ import console;
+ console.open();
+
+ var prcs;
+ fsys.wow64.disableRedirection(
+ function(){
+ var dest,port = string.match(_ARGV.sshLogin,"(.+)\:(\d+)");
+ if(dest&&port){
+ _ARGV.sshLogin = "-p" + port +" " + dest;
+ }
+
+ prcs = process("ssh","-t " +_ARGV.sshLogin + ``)
+ if(!prcs){
+ if(_WIN10_LATER){
+ import process.control;
+ process.control("ms-settings:optionalfeatures");
+ console.log("请检查是否指定了正确的SSH端口,或尝试重新安装 OpenSSH.Client");
+ }
+ else {
+ console.log("此功能仅支持 Windows 10 系统");
+ }
+ }
+ else {
+ import process.job.limitKill;
+ prcs.assignToJobObject(process.job.limitKill);
+ prcs.wait();
+ }
+
+ console.pause();
+ }
+ )
+
+ return;
+}
+elseif(_ARGV.sshInstallKey){
+ import fsys.wow64;
+ import process;
+ import console;
+ console.open();
+
+ var prcs;
+ fsys.wow64.disableRedirection(
+ function(){
+ var sshKeyPath = io.getSpecial(0x28/*_CSIDL_PROFILE*/,"/.ssh/id_rsa.pub") ;
+ var keyData = string.load(sshKeyPath);
+ if(!keyData){
+ var prcs = process.popen("ssh-keygen",` -t rsa -f "`+io.getSpecial(0x28/*_CSIDL_PROFILE*/,"/.ssh/id_rsa")+`" -y`);
+ keyData = prcs? prcs.read(-1);
+ }
+
+ if(!keyData){
+ if(_WIN10_LATER){
+ import process.control;
+ process.control("ms-settings:optionalfeatures");
+ console.log("请检查是否指定了正确的SSH端口,或尝试重新安装 OpenSSH.Client");
+ }
+ else {
+ console.log("此功能仅支持 Windows 10 系统");
+ }
+ }
+ else{
+ var dest,port = string.match(_ARGV.sshInstallKey,"(.+)\:(\d+)");
+ if(dest&&port){
+ _ARGV.sshInstallKey = "-p" + port +" " + dest;
+ }
+
+ prcs = process("ssh","-t " +_ARGV.sshInstallKey + ` "mkdir -p ~/.ssh;chmod 700 ~/.ssh;chmod 600 ~/.ssh/authorized_keys;echo '`+keyData+`' > ~/.ssh/authorized_keys"`)
+ if(!prcs){
+ if(_WIN10_LATER){
+ import process.control;
+ process.control("ms-settings:optionalfeatures");
+ console.log("请检查是否指定了正确的SSH端口,或尝试重新安装 OpenSSH.Client");
+ }
+ else {
+ console.log("此功能仅支持 Windows 10 系统");
+ }
+ }
+ else {
+ import process.job.limitKill;
+ prcs.assignToJobObject(process.job.limitKill);
+ prcs.wait();
+ }
+ }
+
+ console.pause();
+ }
+ )
+
+ return;
+}
+elseif(_ARGV.updateTime){
+ import time.ntp;
+ time.ntp.updateSystemTime();
+ return;
+}
+else {
+ /*
+ import process;
+ import fsys.update.#simpleMain;
+
+ if( fsys.update.simpleMain(
+ "winXray(V2Ray/V2Ray、Shadowsocks、Trojan通用客户端 )",
+ "https://raw.githubusercontent.com/win-xray/win-xray/master/release/update/version.txt",
+ ..io.appData("/winXray/update"),
+ function(version,description,status){}
+ ,,false)){
+ return 0;
+ }
+ */
+}
+/*}}*/
+import fonts.fontAwesome;
+import win.ui;
+/*DSG{{*/
+mainForm = win.form(text="winXray";right=1019;bottom=679;bgcolor=15793151;border="none")
+mainForm.add(
+caption={cls="bkplus";text="WinXray 3.8";left=67;top=9;right=727;bottom=27;align="left";color=6052956;dl=1;dt=1;font=LOGFONT(h=-14);z=7};
+custom={cls="custom";left=83;top=40;right=1022;bottom=679;bgcolor=16777215;db=1;dl=1;dr=1;dt=1;z=4};
+logo={cls="bkplus";text='\uF1D9';left=35;top=7;right=64;bottom=32;color=3054125;dl=1;dt=1;font=LOGFONT(h=-18;name='FontAwesome');z=6};
+navBar={cls="bkplus";left=0;top=37;right=83;bottom=681;bgcolor=3442175;db=1;dl=1;dt=1;z=1};
+navJsonConfig={cls="plus";text="配置";left=0;top=132;right=85;bottom=212;bkBottom=3;bkLeft=7;bkRight=8;bkTop=2;border={color=-65536};color=16777215;dl=1;dt=1;font=LOGFONT(h=-13);iconStyle={font=LOGFONT(h=-37;name='FontAwesome');padding={bottom=20}};iconText='\uF0F6';notify=1;textPadding={bottom=10};valign="bottom";x=0.5;y=0.2;z=5};
+navStart={cls="plus";text="首页";left=0;top=48;right=85;bottom=128;bkBottom=3;bkLeft=7;bkRight=8;bkTop=2;border={color=-65536};color=16777215;dl=1;dt=1;font=LOGFONT(h=-13);iconStyle={font=LOGFONT(h=-37;name='FontAwesome');padding={bottom=20}};iconText='\uF015';notify=1;textPadding={bottom=10};valign="bottom";x=0.5;y=0.2;z=3};
+navTools={cls="plus";text="工具";left=0;top=216;right=85;bottom=296;bkBottom=3;bkLeft=7;bkRight=8;bkTop=2;border={color=-65536};color=16777215;dl=1;dt=1;font=LOGFONT(h=-13);iconStyle={font=LOGFONT(h=-37;name='FontAwesome');padding={bottom=20}};iconText='\uF0AD';notify=1;textPadding={bottom=10};valign="bottom";x=0.5;y=0.2;z=8};
+titleBar={cls="bkplus";left=0;top=0;right=1022;bottom=38;bgcolor=8036607;dl=1;dr=1;dt=1;forecolor=16777215;linearGradient=180;z=2}
+)
+/*}}*/
+
+import win.ui.atom;
+var atom,hwnd = mainForm.atom("DFA5667E-1D8C-49C0-8918-C6FEC2DECCF8");
+if(!atom){
+ win.showForeground(hwnd);
+ win.quitMessage();
+ return;
+}
+
+import win.ui.simpleWindow;
+win.ui.simpleWindow( mainForm );
+
+import win.dlg.message;
+win.dlg.message.install();
+
+import win.ui.tabs;
+var tbs = win.ui.tabs(
+ mainForm.navStart,
+ mainForm.navJsonConfig,
+ mainForm.navTools
+);
+
+tbs.skin({
+ background={
+ active=0xFFFFFFFF;
+ default=0x00FFFFFF;
+ hover=0x38FFFFFF
+ };
+ color={
+ default=0xFFFFFFFF;
+ };
+ checked={
+ background={default=0xFFFFFFFF;};
+ color={default=0xff86a543;};
+ }
+})
+
+tbs.loadForm(1,"\forms\main\v2ray.aardio" );
+tbs.loadForm(2,"\forms\main\config\jsonConfig.aardio" );
+tbs.loadForm(3,"\forms\main\tools\tools.aardio");
+
+tbs.selIndex = 1;
+
+import v2ray.core;
+import win.ui.menu;
+mainForm.wndproc = {
+ [0xACCF/*_WM_TRAYMESSAGE*/ ] = function(hwnd,message,wParam,lParam){
+ if( lParam = 0x205/*_WM_RBUTTONUP*/ ){
+ win.setForeground(mainForm.hwnd)
+ mainForm.popmenu = win.ui.popmenu(mainForm);
+ mainForm.popmenu.add('自动切换到最快的服务器',function(id){
+ publish("uiCommand.restartV2RayCore",)
+ });
+ mainForm.popmenu.add('立即更新所有订阅源',function(id){
+ v2ray.outbounds.updateSubscription();
+ });
+ mainForm.popmenu.add();
+
+ import v2ray.core;
+ var id = mainForm.popmenu.add('不使用代理',function(id){
+ sysProxy.switch("direct");
+ });
+ mainForm.popmenu.check(id,config.proxy.mode=="direct",0/*_MF_BYCOMMAND*/);
+
+ var id = mainForm.popmenu.add('使用全局代理',function(id){
+ sysProxy.switch("proxy");
+ });
+ mainForm.popmenu.check(id,config.proxy.mode=="proxy",0/*_MF_BYCOMMAND*/);
+
+ var id = mainForm.popmenu.add('使用 PAC 自动代理',function(id){
+ sysProxy.switch("pac");
+ });
+ mainForm.popmenu.check(id,config.proxy.mode=="pac",0/*_MF_BYCOMMAND*/);
+
+ mainForm.popmenu.add();
+
+ mainForm.popmenu.add('编辑 PAC 配置',function(id){
+ publish("uiCommand.showPacForm");
+ });
+
+ if(_WIN10_LATER){
+ mainForm.popmenu.add('UWP 应用代理配置',function(id){
+ if(_STUDIO_INVOKED){
+ mainForm.msgErr("请先发布为 EXE!");
+ return;
+ }
+
+ import process;
+ process.execute(io._exepath,"/uwp","runas")
+ });
+ }
+
+ mainForm.popmenu.add();
+
+ if(_WIN10_LATER){
+ mainForm.popmenu.add('打开系统代理设置',function(id){
+ import process.control;
+ process.control("ms-settings:network-proxy")
+ });
+ mainForm.popmenu.add('打开 Internet 代理选项',function(id){
+ import process.control;
+ process.control("inetcpl.cpl",,4);
+ });
+ }
+ else {
+ mainForm.popmenu.add('打开系统代理设置',function(id){
+ import process.control;
+ process.control("inetcpl.cpl",,4);
+ });
+ }
+
+ mainForm.popmenu.add('打开网卡连接',function(id){
+ import process;
+ process.explore("shell:::{7007ACC7-3202-11D1-AAD2-00805FC1270E}");
+ });
+ mainForm.popmenu.add();
+
+ mainForm.popmenu.add('获取 winXray 最新源代码',function(id){
+ import process;
+ process.openUrl("https://www.github.com/win-xray/win-xray")
+ });
+
+ import chrome.path;
+ var chromePath = chrome.path();
+ if(chromePath && v2ray.core.socksProxyPort){
+ mainForm.popmenu.add('使用 SOCKS5 代理打开浏览器',function(id){
+ import process
+ process.execute(chromePath,` --proxy-server="SOCKS5://127.0.0.1:`+v2ray.core.socksProxyPort
+ +`" --user-data-dir="` +io.appData("winXray/chrome-socks5")+ `" https://www.google.com`);
+ });
+ }
+
+ mainForm.popmenu.add();
+ mainForm.popmenu.add('退出',function(id){
+ mainForm.onClose = null;
+ mainForm.close()
+ });
+
+ var pt = ::POINT();
+ ::User32.GetCursorPos(pt);
+ mainForm.popmenu.popup(pt.x,pt.y,true)
+ }
+ elseif( lParam = 0x203/*_WM_LBUTTONDBLCLK*/) {
+ if(win.isIconic(mainForm.hwnd)){
+ mainForm.show(9/*_SW_RESTORE*/);
+ }
+ else {
+ mainForm.show();
+ }
+
+ win.setForeground(mainForm.hwnd);
+ }
+ }
+}
+
+mainForm.onDestroy = function(){
+ mainForm.tray.delete();
+}
+
+import win.util.tray;
+mainForm.onClose = function(hwnd,message,wParam,lParam){
+ if(!mainForm.tray){
+ mainForm.tray = win.util.tray(mainForm);
+ }
+ else {
+ mainForm.tray.reset();
+ }
+
+ mainForm.show(false);
+ return true;
+}
+
+mainForm.tray = win.util.tray(mainForm)
+if(!_ARGV.tray){
+ mainForm.show();
+}
+
+import win.image;
+var trayIcons = {
+ direct = win.image.loadIconFromFile("\forms\ico\app-direct.ico");
+ pac = win.image.loadIconFromFile("\forms\ico\app-pac.ico");
+ proxy = _HAPPICON
+}
+
+subscribe("sysProxy.modeChanged",function(active){
+ mainForm.tray.icon = trayIcons[config.proxy.mode] ;
+})
+
+subscribe("uiCommand.HotkeyChanged",function(...){
+ if(#config.proxy.hotkey){
+ if(mainForm.hkProxyId){
+ mainForm.unreghotkey(mainForm.hkProxyId)
+ mainForm.hkProxyId = null;
+ }
+
+ mainForm.hkProxyId = mainForm.reghotkey( function(id,mod,vk){
+ import sysProxy;
+ var mode = sysProxy.switchHotkey();
+ var dlg = win.dlg.message(win.getForeground())
+ dlg.ok(mode=="pac"?"已切换到 PAC 代理模式":"已切换到全局代理模式",1200);
+ },config.proxy.hotkey[1],config.proxy.hotkey[2])
+ }
+} )
+publish("uiCommand.HotkeyChanged");
+
+return win.loopMessage();
diff --git a/pac.txt b/pac.txt
new file mode 100644
index 0000000..a63f623
--- /dev/null
+++ b/pac.txt
@@ -0,0 +1,5694 @@
+/**
+ * genpac 2.1.0 https://github.com/JinnLynn/genpac
+ * GFWList Last-Modified: 2020-10-21 00:11:38
+ */
+
+var proxy = 'SOCKS5 127.0.0.1:1080';
+var rules = [
+ [
+ [
+ "aftygh.gov.tw",
+ "aide.gov.tw",
+ "aliyun.com",
+ "arte.gov.tw",
+ "baidu.com",
+ "chinaso.com",
+ "chinaz.com",
+ "chukuang.gov.tw",
+ "cycab.gov.tw",
+ "dbnsa.gov.tw",
+ "df.gov.tw",
+ "eastcoast-nsa.gov.tw",
+ "erv-nsa.gov.tw",
+ "gravatar.com",
+ "grb.gov.tw",
+ "haosou.com",
+ "haygo.com",
+ "hchcc.gov.tw",
+ "hsinchu-cc.gov.tw",
+ "iner.gov.tw",
+ "ip.cn",
+ "jike.com",
+ "jpush.cn",
+ "klsio.gov.tw",
+ "kmseh.gov.tw",
+ "locql.com",
+ "lungtanhr.gov.tw",
+ "maolin-nsa.gov.tw",
+ "matsu-news.gov.tw",
+ "matsu-nsa.gov.tw",
+ "matsucc.gov.tw",
+ "moe.gov.tw",
+ "nankan.gov.tw",
+ "ncree.gov.tw",
+ "necoast-nsa.gov.tw",
+ "ner.gov.tw",
+ "nmmba.gov.tw",
+ "nmp.gov.tw",
+ "nmvttc.gov.tw",
+ "northguan-nsa.gov.tw",
+ "npm.gov.tw",
+ "nstm.gov.tw",
+ "ntdmh.gov.tw",
+ "ntl.gov.tw",
+ "ntsec.gov.tw",
+ "ntuh.gov.tw",
+ "nvri.gov.tw",
+ "nyc.gov.tw",
+ "penghu-nsa.gov.tw",
+ "post.gov.tw",
+ "qq.com",
+ "simplecd.me",
+ "sina.cn",
+ "sina.com.cn",
+ "siraya-nsa.gov.tw",
+ "sl-reverse.com",
+ "so.com",
+ "sogou.com",
+ "soso.com",
+ "stdtime.gov.tw",
+ "sunmoonlake.gov.tw",
+ "syniumsoftware.com",
+ "taitung-house.gov.tw",
+ "taoyuan.gov.tw",
+ "tphcc.gov.tw",
+ "trimt-nsa.gov.tw",
+ "uluai.com.cn",
+ "vghks.gov.tw",
+ "vghtc.gov.tw",
+ "vghtpe.gov.tw",
+ "wallproxy.com.cn",
+ "wanfang.gov.tw",
+ "weibo.com",
+ "yahoo.cn",
+ "yatsen.gov.tw",
+ "yda.gov.tw",
+ "youdao.com",
+ "zhongsou.com"
+ ],
+ [
+ "realtimesupport.clients6.google.com",
+ "apis.google.com",
+ "fonts.gstatic.com",
+ "play.google.com",
+ "ssl.gstatic.com",
+ "csi.gstatic.com",
+ "khmdb.google.com",
+ "www.google-analytics.com",
+ "www.gstatic.com",
+ "support.google.com",
+ "mw2.google.com",
+ "mw1.google.com",
+ "kh.google.com",
+ "geoauth.google.com",
+ "maps.google.com",
+ "030buy.com",
+ "0rz.tw",
+ "1-apple.com.tw",
+ "10.tt",
+ "1000giri.net",
+ "100ke.org",
+ "10conditionsoflove.com",
+ "10musume.com",
+ "123rf.com",
+ "12bet.com",
+ "12vpn.com",
+ "12vpn.net",
+ "138.com",
+ "141hongkong.com",
+ "141jj.com",
+ "141tube.com",
+ "1688.com.au",
+ "173ng.com",
+ "177pic.info",
+ "17t17p.com",
+ "18board.com",
+ "18board.info",
+ "18onlygirls.com",
+ "18p2p.com",
+ "18virginsex.com",
+ "1949er.org",
+ "1984.city",
+ "1984bbs.com",
+ "1984bbs.org",
+ "1991way.com",
+ "1998cdp.org",
+ "1bao.org",
+ "1dumb.com",
+ "1e100.net",
+ "1eew.com",
+ "1mobile.com",
+ "1mobile.tw",
+ "1pondo.tv",
+ "2-hand.info",
+ "2000fun.com",
+ "2008xianzhang.info",
+ "2017.hk",
+ "21andy.com",
+ "21join.com",
+ "21pron.com",
+ "21sextury.com",
+ "228.net.tw",
+ "233abc.com",
+ "24hrs.ca",
+ "24smile.org",
+ "25u.com",
+ "2lipstube.com",
+ "2shared.com",
+ "2waky.com",
+ "3-a.net",
+ "30boxes.com",
+ "315lz.com",
+ "32red.com",
+ "36rain.com",
+ "3a5a.com",
+ "3arabtv.com",
+ "3boys2girls.com",
+ "3d-game.com",
+ "3proxy.ru",
+ "3ren.ca",
+ "3tui.net",
+ "43110.cf",
+ "466453.com",
+ "4bluestones.biz",
+ "4chan.com",
+ "4dq.com",
+ "4everproxy.com",
+ "4irc.com",
+ "4mydomain.com",
+ "4pu.com",
+ "4rbtv.com",
+ "4shared.com",
+ "4sqi.net",
+ "50webs.com",
+ "51.ca",
+ "51jav.org",
+ "51luoben.com",
+ "5278.cc",
+ "5299.tv",
+ "5aimiku.com",
+ "5i01.com",
+ "5isotoi5.org",
+ "5maodang.com",
+ "63i.com",
+ "64museum.org",
+ "64tianwang.com",
+ "64wiki.com",
+ "66.ca",
+ "666kb.com",
+ "6park.com",
+ "6parker.com",
+ "6parknews.com",
+ "7capture.com",
+ "7cow.com",
+ "8-d.com",
+ "85cc.net",
+ "85cc.us",
+ "85st.com",
+ "881903.com",
+ "888.com",
+ "888poker.com",
+ "89-64.org",
+ "8news.com.tw",
+ "8z1.net",
+ "9001700.com",
+ "908taiwan.org",
+ "91porn.com",
+ "91vps.club",
+ "92ccav.com",
+ "991.com",
+ "99btgc01.com",
+ "99cn.info",
+ "9bis.com",
+ "9bis.net",
+ "9gag.com",
+ "a-normal-day.com",
+ "aamacau.com",
+ "abc.com",
+ "abc.net.au",
+ "abc.xyz",
+ "abchinese.com",
+ "abclite.net",
+ "abebooks.com",
+ "ablwang.com",
+ "aboluowang.com",
+ "about.google",
+ "aboutgfw.com",
+ "abs.edu",
+ "accim.org",
+ "aceros-de-hispania.com",
+ "acevpn.com",
+ "acg18.me",
+ "acgkj.com",
+ "acgnx.se",
+ "acmedia365.com",
+ "acmetoy.com",
+ "acnw.com.au",
+ "actfortibet.org",
+ "actimes.com.au",
+ "activpn.com",
+ "aculo.us",
+ "adcex.com",
+ "addictedtocoffee.de",
+ "adelaidebbs.com",
+ "admob.com",
+ "adpl.org.hk",
+ "ads-twitter.com",
+ "adsense.com",
+ "adult-sex-games.com",
+ "adultfriendfinder.com",
+ "adultkeep.net",
+ "advanscene.com",
+ "advertfan.com",
+ "ae.org",
+ "aenhancers.com",
+ "aex.com",
+ "af.mil",
+ "afantibbs.com",
+ "agnesb.fr",
+ "agoogleaday.com",
+ "agro.hk",
+ "ai-kan.net",
+ "ai-wen.net",
+ "ai.google",
+ "aiph.net",
+ "airasia.com",
+ "airconsole.com",
+ "aircrack-ng.org",
+ "airvpn.org",
+ "aisex.com",
+ "ait.org.tw",
+ "aiweiwei.com",
+ "aiweiweiblog.com",
+ "ajsands.com",
+ "akademiye.org",
+ "akamai.net",
+ "akamaihd.net",
+ "akamaistream.net",
+ "akamaized.net",
+ "akiba-online.com",
+ "akiba-web.com",
+ "akow.org",
+ "al-islam.com",
+ "al-qimmah.net",
+ "alabout.com",
+ "alanhou.com",
+ "alarab.qa",
+ "alasbarricadas.org",
+ "alexlur.org",
+ "alforattv.net",
+ "alhayat.com",
+ "alicejapan.co.jp",
+ "aliengu.com",
+ "alkasir.com",
+ "all4mom.org",
+ "allcoin.com",
+ "allconnected.co",
+ "alldrawnsex.com",
+ "allervpn.com",
+ "allfinegirls.com",
+ "allgirlmassage.com",
+ "allgirlsallowed.org",
+ "allgravure.com",
+ "alliance.org.hk",
+ "allinfa.com",
+ "alljackpotscasino.com",
+ "allmovie.com",
+ "allowed.org",
+ "almasdarnews.com",
+ "almostmy.com",
+ "alphaporno.com",
+ "alternate-tools.com",
+ "alternativeto.net",
+ "altrec.com",
+ "alvinalexander.com",
+ "alwaysdata.com",
+ "alwaysdata.net",
+ "alwaysvpn.com",
+ "am730.com.hk",
+ "amazon.co.jp",
+ "amazon.com",
+ "amazonaws.com",
+ "ameblo.jp",
+ "america.gov",
+ "american.edu",
+ "americangreencard.com",
+ "americanunfinished.com",
+ "americorps.gov",
+ "amiblockedornot.com",
+ "amigobbs.net",
+ "amitabhafoundation.us",
+ "amnesty.org",
+ "amnesty.org.hk",
+ "amnesty.tw",
+ "amnestyusa.org",
+ "amnyemachen.org",
+ "amoiist.com",
+ "ampproject.org",
+ "amtb-taipei.org",
+ "anchorfree.com",
+ "ancsconf.org",
+ "andfaraway.net",
+ "android-x86.org",
+ "android.com",
+ "androidify.com",
+ "androidplus.co",
+ "androidtv.com",
+ "andygod.com",
+ "angela-merkel.de",
+ "angelfire.com",
+ "angola.org",
+ "angularjs.org",
+ "animecrazy.net",
+ "animeshippuuden.com",
+ "aniscartujo.com",
+ "annatam.com",
+ "anobii.com",
+ "anontext.com",
+ "anonymise.us",
+ "anonymitynetwork.com",
+ "anonymizer.com",
+ "anonymouse.org",
+ "anpopo.com",
+ "answering-islam.org",
+ "antd.org",
+ "anthonycalzadilla.com",
+ "anti1984.com",
+ "antichristendom.com",
+ "antiwave.net",
+ "anws.gov.tw",
+ "anyporn.com",
+ "anysex.com",
+ "ao3.org",
+ "aobo.com.au",
+ "aofriend.com",
+ "aofriend.com.au",
+ "aojiao.org",
+ "aol.ca",
+ "aol.co.uk",
+ "aol.com",
+ "aolnews.com",
+ "aomiwang.com",
+ "ap.org",
+ "apartmentratings.com",
+ "apartments.com",
+ "apetube.com",
+ "api.ai",
+ "apiary.io",
+ "apigee.com",
+ "apk-dl.com",
+ "apkcombo.com",
+ "apkmirror.com",
+ "apkmonk.com",
+ "apkplz.com",
+ "apkpure.com",
+ "aplusvpn.com",
+ "appdownloader.net",
+ "appledaily.com",
+ "appledaily.com.hk",
+ "appledaily.com.tw",
+ "appshopper.com",
+ "appsocks.net",
+ "appspot.com",
+ "appsto.re",
+ "aptoide.com",
+ "archive.fo",
+ "archive.is",
+ "archive.li",
+ "archive.org",
+ "archive.ph",
+ "archive.today",
+ "archiveofourown.com",
+ "archiveofourown.org",
+ "archives.gov",
+ "archives.gov.tw",
+ "arctosia.com",
+ "areca-backup.org",
+ "arena.taipei",
+ "arethusa.su",
+ "arlingtoncemetery.mil",
+ "army.mil",
+ "art4tibet1998.org",
+ "arte.tv",
+ "artofpeacefoundation.org",
+ "artstation.com",
+ "artsy.net",
+ "asacp.org",
+ "asdfg.jp",
+ "asg.to",
+ "asia-gaming.com",
+ "asiaharvest.org",
+ "asianews.it",
+ "asianfreeforum.com",
+ "asiansexdiary.com",
+ "asianspiss.com",
+ "asianwomensfilm.de",
+ "asiatgp.com",
+ "asiatoday.us",
+ "askstudent.com",
+ "askynz.net",
+ "assembla.com",
+ "assimp.org",
+ "astrill.com",
+ "atc.org.au",
+ "atchinese.com",
+ "atdmt.com",
+ "atgfw.org",
+ "athenaeizou.com",
+ "atlanta168.com",
+ "atlaspost.com",
+ "atnext.com",
+ "audionow.com",
+ "authorizeddns.net",
+ "authorizeddns.org",
+ "authorizeddns.us",
+ "autodraw.com",
+ "av-e-body.com",
+ "av.com",
+ "av.movie",
+ "avaaz.org",
+ "avbody.tv",
+ "avcity.tv",
+ "avcool.com",
+ "avdb.in",
+ "avdb.tv",
+ "avfantasy.com",
+ "avg.com",
+ "avgle.com",
+ "avidemux.org",
+ "avmo.pw",
+ "avmoo.com",
+ "avmoo.net",
+ "avmoo.pw",
+ "avoision.com",
+ "avyahoo.com",
+ "axureformac.com",
+ "azerbaycan.tv",
+ "azerimix.com",
+ "azubu.tv",
+ "azurewebsites.net",
+ "b0ne.com",
+ "baby-kingdom.com",
+ "babynet.com.hk",
+ "backchina.com",
+ "backpackers.com.tw",
+ "backtotiananmen.com",
+ "badiucao.com",
+ "badjojo.com",
+ "badoo.com",
+ "baidu.jp",
+ "baijie.org",
+ "bailandaily.com",
+ "baixing.me",
+ "bakgeekhome.tk",
+ "banana-vpn.com",
+ "band.us",
+ "bandwagonhost.com",
+ "bangbrosnetwork.com",
+ "bangchen.net",
+ "bangdream.space",
+ "bangyoulater.com",
+ "bankmobilevibe.com",
+ "bannedbook.org",
+ "bannednews.org",
+ "banorte.com",
+ "baramangaonline.com",
+ "barenakedislam.com",
+ "barnabu.co.uk",
+ "barton.de",
+ "bartvpn.com",
+ "bash-hackers.org",
+ "bastillepost.com",
+ "bayvoice.net",
+ "baywords.com",
+ "bb-chat.tv",
+ "bbc.co.uk",
+ "bbc.com",
+ "bbc.in",
+ "bbcchinese.com",
+ "bbchat.tv",
+ "bbci.co.uk",
+ "bbg.gov",
+ "bbkz.com",
+ "bbnradio.org",
+ "bbs-tw.com",
+ "bbsdigest.com",
+ "bbsfeed.com",
+ "bbsland.com",
+ "bbsmo.com",
+ "bbsone.com",
+ "bbtoystore.com",
+ "bcast.co.nz",
+ "bcc.com.tw",
+ "bcchinese.net",
+ "bcex.ca",
+ "bcmorning.com",
+ "bdsmvideos.net",
+ "beaconevents.com",
+ "bebo.com",
+ "beeg.com",
+ "beevpn.com",
+ "behance.net",
+ "behindkink.com",
+ "beijing1989.com",
+ "beijingspring.com",
+ "beijingzx.org",
+ "belamionline.com",
+ "bell.wiki",
+ "bemywife.cc",
+ "beric.me",
+ "berlintwitterwall.com",
+ "berm.co.nz",
+ "bestforchina.org",
+ "bestgore.com",
+ "bestpornstardb.com",
+ "bestvpn.com",
+ "bestvpnanalysis.com",
+ "bestvpnserver.com",
+ "bestvpnservice.com",
+ "bestvpnusa.com",
+ "bet365.com",
+ "betfair.com",
+ "betternet.co",
+ "bettervpn.com",
+ "bettween.com",
+ "betvictor.com",
+ "bewww.net",
+ "beyondfirewall.com",
+ "bfnn.org",
+ "bfsh.hk",
+ "bgvpn.com",
+ "bianlei.com",
+ "biantailajiao.com",
+ "biantailajiao.in",
+ "biblesforamerica.org",
+ "bibox.com",
+ "bic2011.org",
+ "big.one",
+ "bigfools.com",
+ "bigjapanesesex.com",
+ "bigmoney.biz",
+ "bignews.org",
+ "bigsound.org",
+ "biliworld.com",
+ "billypan.com",
+ "binance.com",
+ "bing.com",
+ "binux.me",
+ "binwang.me",
+ "bipic.net",
+ "bird.so",
+ "bit-z.com",
+ "bit.do",
+ "bit.ly",
+ "bitcointalk.org",
+ "bitcoinworld.com",
+ "bitfinex.com",
+ "bithumb.com",
+ "bitinka.com.ar",
+ "bitmex.com",
+ "bitshare.com",
+ "bitsnoop.com",
+ "bitterwinter.org",
+ "bitvise.com",
+ "bizhat.com",
+ "bjnewlife.org",
+ "bjs.org",
+ "bjzc.org",
+ "bl-doujinsouko.com",
+ "blacklogic.com",
+ "blackvpn.com",
+ "blewpass.com",
+ "blingblingsquad.net",
+ "blinkx.com",
+ "blinw.com",
+ "blip.tv",
+ "blockcn.com",
+ "blockless.com",
+ "blog.de",
+ "blog.google",
+ "blog.jp",
+ "blogblog.com",
+ "blogcatalog.com",
+ "blogcity.me",
+ "blogdns.org",
+ "blogger.com",
+ "blogimg.jp",
+ "bloglines.com",
+ "bloglovin.com",
+ "blogs.com",
+ "blogspot.com",
+ "blogspot.hk",
+ "blogspot.jp",
+ "blogspot.tw",
+ "blogtd.net",
+ "blogtd.org",
+ "bloodshed.net",
+ "bloomberg.cn",
+ "bloomberg.com",
+ "bloomberg.de",
+ "bloombergview.com",
+ "bloomfortune.com",
+ "blueangellive.com",
+ "bmfinn.com",
+ "bnews.co",
+ "bnn.co",
+ "bnrmetal.com",
+ "boardreader.com",
+ "bod.asia",
+ "bodog88.com",
+ "bolehvpn.net",
+ "bonbonme.com",
+ "bonbonsex.com",
+ "bonfoundation.org",
+ "bongacams.com",
+ "boobstagram.com",
+ "book.com.tw",
+ "bookepub.com",
+ "books.com.tw",
+ "booktopia.com.au",
+ "boomssr.com",
+ "bot.nu",
+ "botanwang.com",
+ "bowenpress.com",
+ "box.com",
+ "box.net",
+ "boxpn.com",
+ "boxun.com",
+ "boxun.tv",
+ "boxunblog.com",
+ "boxunclub.com",
+ "boyangu.com",
+ "boyfriendtv.com",
+ "boysfood.com",
+ "boysmaster.com",
+ "br.st",
+ "brainyquote.com",
+ "brandonhutchinson.com",
+ "braumeister.org",
+ "bravotube.net",
+ "brazzers.com",
+ "break.com",
+ "breakgfw.com",
+ "breaking911.com",
+ "breakingtweets.com",
+ "breakwall.net",
+ "briefdream.com",
+ "briian.com",
+ "brizzly.com",
+ "brkmd.com",
+ "broadbook.com",
+ "broadpressinc.com",
+ "brockbbs.com",
+ "brucewang.net",
+ "brutaltgp.com",
+ "bt2mag.com",
+ "bt95.com",
+ "btaia.com",
+ "btbtav.com",
+ "btc98.com",
+ "btcbank.bank",
+ "btctrade.im",
+ "btdigg.org",
+ "btku.me",
+ "btku.org",
+ "btspread.com",
+ "btsynckeys.com",
+ "budaedu.org",
+ "buddhanet.com.tw",
+ "buddhistchannel.tv",
+ "buffered.com",
+ "bullog.org",
+ "bullogger.com",
+ "bunbunhk.com",
+ "busayari.com",
+ "businessinsider.com",
+ "businessinsider.com.au",
+ "businesstoday.com.tw",
+ "businessweek.com",
+ "busu.org",
+ "busytrade.com",
+ "buugaa.com",
+ "buzzhand.com",
+ "buzzhand.net",
+ "buzzorange.com",
+ "bvpn.com",
+ "bwbx.io",
+ "bwgyhw.com",
+ "bwh1.net",
+ "bwsj.hk",
+ "bx.in.th",
+ "bx.tl",
+ "bynet.co.il",
+ "c-est-simple.com",
+ "c-spanvideo.org",
+ "c100tibet.org",
+ "c2cx.com",
+ "cablegatesearch.net",
+ "cachinese.com",
+ "cacnw.com",
+ "cactusvpn.com",
+ "cafepress.com",
+ "cahr.org.tw",
+ "caijinglengyan.com",
+ "calameo.com",
+ "calebelston.com",
+ "calgarychinese.ca",
+ "calgarychinese.com",
+ "calgarychinese.net",
+ "calibre-ebook.com",
+ "calstate.edu",
+ "caltech.edu",
+ "cam4.com",
+ "cam4.jp",
+ "cam4.sg",
+ "camfrog.com",
+ "campaignforuyghurs.org",
+ "cams.com",
+ "cams.org.sg",
+ "canadameet.com",
+ "canalporno.com",
+ "cantonese.asia",
+ "canyu.org",
+ "cao.im",
+ "caobian.info",
+ "caochangqing.com",
+ "cap.org.hk",
+ "carabinasypistolas.com",
+ "cardinalkungfoundation.org",
+ "carfax.com",
+ "cari.com.my",
+ "caribbeancom.com",
+ "carmotorshow.com",
+ "carryzhou.com",
+ "cartoonmovement.com",
+ "casadeltibetbcn.org",
+ "casatibet.org.mx",
+ "casinobellini.com",
+ "casinoking.com",
+ "casinoriva.com",
+ "castbox.fm",
+ "catch22.net",
+ "catchgod.com",
+ "catfightpayperview.xxx",
+ "catholic.org.hk",
+ "catholic.org.tw",
+ "cathvoice.org.tw",
+ "cattt.com",
+ "cbc.ca",
+ "cbsnews.com",
+ "cbtc.org.hk",
+ "cccat.cc",
+ "cccat.co",
+ "ccdtr.org",
+ "cchere.com",
+ "ccim.org",
+ "cclife.ca",
+ "cclife.org",
+ "cclifefl.org",
+ "ccthere.com",
+ "ccthere.net",
+ "cctmweb.net",
+ "cctongbao.com",
+ "ccue.ca",
+ "ccue.com",
+ "ccvoice.ca",
+ "ccw.org.tw",
+ "cdbook.org",
+ "cdcparty.com",
+ "cdef.org",
+ "cdig.info",
+ "cdjp.org",
+ "cdn-apple.com",
+ "cdnews.com.tw",
+ "cdninstagram.com",
+ "cdp1989.org",
+ "cdp1998.org",
+ "cdp2006.org",
+ "cdpeu.org",
+ "cdpusa.org",
+ "cdpweb.org",
+ "cdpwu.org",
+ "cdw.com",
+ "cecc.gov",
+ "cellulo.info",
+ "cenews.eu",
+ "centauro.com.br",
+ "centerforhumanreprod.com",
+ "centralnation.com",
+ "centurys.net",
+ "certificate-transparency.org",
+ "cfhks.org.hk",
+ "cfos.de",
+ "cftfc.com",
+ "cgdepot.org",
+ "cgst.edu",
+ "change.org",
+ "changeip.name",
+ "changeip.net",
+ "changeip.org",
+ "changp.com",
+ "changsa.net",
+ "channel8news.sg",
+ "chaoex.com",
+ "chapm25.com",
+ "chatnook.com",
+ "chaturbate.com",
+ "chengmingmag.com",
+ "chenguangcheng.com",
+ "chenpokong.com",
+ "chenpokong.net",
+ "cherrysave.com",
+ "chhongbi.org",
+ "chicagoncmtv.com",
+ "china-mmm.net",
+ "china-review.com.ua",
+ "china-week.com",
+ "china101.com",
+ "china18.org",
+ "china21.com",
+ "china21.org",
+ "china5000.us",
+ "chinaaffairs.org",
+ "chinaaid.me",
+ "chinaaid.net",
+ "chinaaid.org",
+ "chinaaid.us",
+ "chinachange.org",
+ "chinachannel.hk",
+ "chinacitynews.be",
+ "chinacomments.org",
+ "chinadialogue.net",
+ "chinadigitaltimes.net",
+ "chinaelections.org",
+ "chinaeweekly.com",
+ "chinafreepress.org",
+ "chinagate.com",
+ "chinageeks.org",
+ "chinagfw.org",
+ "chinagonet.com",
+ "chinagreenparty.org",
+ "chinahorizon.org",
+ "chinahush.com",
+ "chinainperspective.com",
+ "chinainterimgov.org",
+ "chinalaborwatch.org",
+ "chinalawandpolicy.com",
+ "chinalawtranslate.com",
+ "chinamule.com",
+ "chinamz.org",
+ "chinanewscenter.com",
+ "chinapost.com.tw",
+ "chinapress.com.my",
+ "chinarightsia.org",
+ "chinasmile.net",
+ "chinasocialdemocraticparty.com",
+ "chinasoul.org",
+ "chinasucks.net",
+ "chinatimes.com",
+ "chinatopsex.com",
+ "chinatown.com.au",
+ "chinatweeps.com",
+ "chinaway.org",
+ "chinaworker.info",
+ "chinaxchina.com",
+ "chinayouth.org.hk",
+ "chinayuanmin.org",
+ "chinese-hermit.net",
+ "chinese-leaders.org",
+ "chinese-memorial.org",
+ "chinesedaily.com",
+ "chinesedailynews.com",
+ "chinesedemocracy.com",
+ "chinesegay.org",
+ "chinesen.de",
+ "chinesenews.net.au",
+ "chinesepen.org",
+ "chinesetalks.net",
+ "chineseupress.com",
+ "chingcheong.com",
+ "chinman.net",
+ "chithu.org",
+ "chobit.cc",
+ "chosun.com",
+ "chrdnet.com",
+ "christianfreedom.org",
+ "christianstudy.com",
+ "christiantimes.org.hk",
+ "christusrex.org",
+ "chrlawyers.hk",
+ "chrome.com",
+ "chromecast.com",
+ "chromeexperiments.com",
+ "chromercise.com",
+ "chromestatus.com",
+ "chromium.org",
+ "chuang-yen.org",
+ "chubold.com",
+ "chubun.com",
+ "chuizi.net",
+ "churchinhongkong.org",
+ "chushigangdrug.ch",
+ "cienen.com",
+ "cineastentreff.de",
+ "cipfg.org",
+ "circlethebayfortibet.org",
+ "cirosantilli.com",
+ "citizencn.com",
+ "citizenlab.ca",
+ "citizenlab.org",
+ "citizenscommission.hk",
+ "citizensradio.org",
+ "city365.ca",
+ "city9x.com",
+ "citypopulation.de",
+ "citytalk.tw",
+ "civicparty.hk",
+ "civildisobediencemovement.org",
+ "civilhrfront.org",
+ "civiliangunner.com",
+ "civilmedia.tw",
+ "civisec.org",
+ "cjb.net",
+ "ck101.com",
+ "clarionproject.org",
+ "classicalguitarblog.net",
+ "clb.org.hk",
+ "cleansite.biz",
+ "cleansite.info",
+ "cleansite.us",
+ "clearharmony.net",
+ "clearsurance.com",
+ "clearwisdom.net",
+ "clementine-player.org",
+ "clinica-tibet.ru",
+ "clipfish.de",
+ "cloakpoint.com",
+ "cloudfront.net",
+ "club1069.com",
+ "clyp.it",
+ "cmcn.org",
+ "cmi.org.tw",
+ "cmoinc.org",
+ "cms.gov",
+ "cmu.edu",
+ "cmule.com",
+ "cmule.org",
+ "cmx.im",
+ "cn-proxy.com",
+ "cn.com",
+ "cn6.eu",
+ "cna.com.tw",
+ "cnabc.com",
+ "cnd.org",
+ "cnet.com",
+ "cnex.org.cn",
+ "cnineu.com",
+ "cnitter.com",
+ "cnn.com",
+ "cnpolitics.org",
+ "cnproxy.com",
+ "cnyes.com",
+ "co.tv",
+ "coat.co.jp",
+ "cobinhood.com",
+ "cochina.co",
+ "cochina.org",
+ "code1984.com",
+ "codeplex.com",
+ "codeshare.io",
+ "codeskulptor.org",
+ "coin2co.in",
+ "coinbene.com",
+ "coinegg.com",
+ "coinex.com",
+ "coingi.com",
+ "coinrail.co.kr",
+ "cointiger.com",
+ "cointobe.com",
+ "coinut.com",
+ "collateralmurder.com",
+ "collateralmurder.org",
+ "com.google",
+ "com.ru",
+ "com.uk",
+ "comedycentral.com",
+ "comefromchina.com",
+ "comic-mega.me",
+ "comico.tw",
+ "commandarms.com",
+ "commentshk.com",
+ "communistcrimes.org",
+ "communitychoicecu.com",
+ "compileheart.com",
+ "compress.to",
+ "compython.net",
+ "conoha.jp",
+ "constitutionalism.solutions",
+ "contactmagazine.net",
+ "convio.net",
+ "coobay.com",
+ "cool18.com",
+ "coolaler.com",
+ "coolder.com",
+ "coolloud.org.tw",
+ "coolncute.com",
+ "coolstuffinc.com",
+ "corumcollege.com",
+ "cos-moe.com",
+ "cosplayjav.pl",
+ "costco.com",
+ "cotweet.com",
+ "counter.social",
+ "coursehero.com",
+ "cpj.org",
+ "cq99.us",
+ "crackle.com",
+ "crazys.cc",
+ "crazyshit.com",
+ "crbug.com",
+ "crchina.org",
+ "crd-net.org",
+ "creaders.net",
+ "creadersnet.com",
+ "creativelab5.com",
+ "crisisresponse.google",
+ "cristyli.com",
+ "crocotube.com",
+ "crossfire.co.kr",
+ "crossthewall.net",
+ "crossvpn.net",
+ "crrev.com",
+ "crucial.com",
+ "csdparty.com",
+ "csuchen.de",
+ "csw.org.uk",
+ "ct.org.tw",
+ "ctao.org",
+ "ctfriend.net",
+ "ctitv.com.tw",
+ "cts.com.tw",
+ "cuhk.edu.hk",
+ "cuhkacs.org",
+ "cuihua.org",
+ "cuiweiping.net",
+ "culture.tw",
+ "cumlouder.com",
+ "curvefish.com",
+ "cusu.hk",
+ "cutscenes.net",
+ "cw.com.tw",
+ "cwb.gov.tw",
+ "cyberctm.com",
+ "cyberghostvpn.com",
+ "cynscribe.com",
+ "cytode.us",
+ "cz.cc",
+ "d-fukyu.com",
+ "d0z.net",
+ "d100.net",
+ "d2bay.com",
+ "d2pass.com",
+ "dabr.co.uk",
+ "dabr.eu",
+ "dabr.me",
+ "dabr.mobi",
+ "dadazim.com",
+ "dadi360.com",
+ "dafabet.com",
+ "dafagood.com",
+ "dafahao.com",
+ "dafoh.org",
+ "daftporn.com",
+ "dagelijksestandaard.nl",
+ "daidostup.ru",
+ "dailidaili.com",
+ "dailymotion.com",
+ "dailyview.tw",
+ "daiphapinfo.net",
+ "dajiyuan.com",
+ "dajiyuan.de",
+ "dajiyuan.eu",
+ "dalailama-archives.org",
+ "dalailama.com",
+ "dalailama.mn",
+ "dalailama.ru",
+ "dalailama80.org",
+ "dalailamacenter.org",
+ "dalailamafellows.org",
+ "dalailamafilm.com",
+ "dalailamafoundation.org",
+ "dalailamahindi.com",
+ "dalailamainaustralia.org",
+ "dalailamajapanese.com",
+ "dalailamaprotesters.info",
+ "dalailamaquotes.org",
+ "dalailamatrust.org",
+ "dalailamavisit.org.nz",
+ "dalailamaworld.com",
+ "dalianmeng.org",
+ "daliulian.org",
+ "danke4china.net",
+ "danwei.org",
+ "daolan.net",
+ "daozhongxing.org",
+ "darktech.org",
+ "darktoy.net",
+ "darpa.mil",
+ "dastrassi.org",
+ "data-vocabulary.org",
+ "data.gov.tw",
+ "daum.net",
+ "david-kilgour.com",
+ "dawangidc.com",
+ "daxa.cn",
+ "dayabook.com",
+ "daylife.com",
+ "db.tt",
+ "dbc.hk",
+ "dcard.tw",
+ "dcmilitary.com",
+ "ddc.com.tw",
+ "ddhw.info",
+ "ddns.info",
+ "ddns.me.uk",
+ "ddns.mobi",
+ "ddns.ms",
+ "ddns.name",
+ "ddns.net",
+ "ddns.us",
+ "de-sci.org",
+ "deaftone.com",
+ "debian.org",
+ "debug.com",
+ "deck.ly",
+ "decodet.co",
+ "deepmind.com",
+ "deezer.com",
+ "definebabe.com",
+ "deja.com",
+ "delcamp.net",
+ "delicious.com",
+ "democrats.org",
+ "demosisto.hk",
+ "depositphotos.com",
+ "desc.se",
+ "design.google",
+ "desipro.de",
+ "dessci.com",
+ "destroy-china.jp",
+ "deutsche-welle.de",
+ "devio.us",
+ "devpn.com",
+ "dfas.mil",
+ "dfn.org",
+ "dharamsalanet.com",
+ "dharmakara.net",
+ "dhcp.biz",
+ "diaoyuislands.org",
+ "difangwenge.org",
+ "digiland.tw",
+ "digisfera.com",
+ "digitalnomadsproject.org",
+ "diigo.com",
+ "dilber.se",
+ "dingchin.com.tw",
+ "dipity.com",
+ "directcreative.com",
+ "discoins.com",
+ "disconnect.me",
+ "discord.com",
+ "discord.gg",
+ "discordapp.com",
+ "discordapp.net",
+ "discuss.com.hk",
+ "discuss4u.com",
+ "dish.com",
+ "disp.cc",
+ "disqus.com",
+ "dit-inc.us",
+ "dizhidizhi.com",
+ "dizhuzhishang.com",
+ "djangosnippets.org",
+ "djorz.com",
+ "dl-laby.jp",
+ "dlsite.com",
+ "dlsite.jp",
+ "dlyoutube.com",
+ "dm530.net",
+ "dmcdn.net",
+ "dmhy.org",
+ "dmm.co.jp",
+ "dmm.com",
+ "dns-dns.com",
+ "dns-stuff.com",
+ "dns.google",
+ "dns04.com",
+ "dns05.com",
+ "dns1.us",
+ "dns2.us",
+ "dns2go.com",
+ "dnscrypt.org",
+ "dnset.com",
+ "dnsrd.com",
+ "dnssec.net",
+ "dnvod.tv",
+ "doctorvoice.org",
+ "documentingreality.com",
+ "dogfartnetwork.com",
+ "dojin.com",
+ "dok-forum.net",
+ "dolc.de",
+ "dolf.org.hk",
+ "dollf.com",
+ "domain.club.tw",
+ "domains.google",
+ "domaintoday.com.au",
+ "donga.com",
+ "dongtaiwang.com",
+ "dongtaiwang.net",
+ "dongyangjing.com",
+ "donmai.us",
+ "dontfilter.us",
+ "dontmovetochina.com",
+ "dorjeshugden.com",
+ "dotplane.com",
+ "dotsub.com",
+ "dotvpn.com",
+ "doub.io",
+ "doubibackup.com",
+ "doubmirror.cf",
+ "dougscripts.com",
+ "douhokanko.net",
+ "doujincafe.com",
+ "dowei.org",
+ "dphk.org",
+ "dpp.org.tw",
+ "dpr.info",
+ "dragonex.io",
+ "dragonsprings.org",
+ "dreamamateurs.com",
+ "drepung.org",
+ "drgan.net",
+ "drmingxia.org",
+ "dropbooks.tv",
+ "dropbox.com",
+ "dropboxapi.com",
+ "dropboxusercontent.com",
+ "drsunacademy.com",
+ "drtuber.com",
+ "dscn.info",
+ "dsmtp.com",
+ "dstk.dk",
+ "dtdns.net",
+ "dtiblog.com",
+ "dtic.mil",
+ "dtwang.org",
+ "duanzhihu.com",
+ "dubox.com",
+ "duck.com",
+ "duckdns.org",
+ "duckduckgo.com",
+ "duckload.com",
+ "duckmylife.com",
+ "duga.jp",
+ "duihua.org",
+ "duihuahrjournal.org",
+ "dumb1.com",
+ "dunyabulteni.net",
+ "duoweitimes.com",
+ "duping.net",
+ "duplicati.com",
+ "dupola.com",
+ "dupola.net",
+ "dushi.ca",
+ "dvdpac.com",
+ "dvorak.org",
+ "dw-world.com",
+ "dw-world.de",
+ "dw.com",
+ "dw.de",
+ "dwheeler.com",
+ "dwnews.com",
+ "dwnews.net",
+ "dxiong.com",
+ "dynamic-dns.net",
+ "dynamicdns.biz",
+ "dynamicdns.co.uk",
+ "dynamicdns.me.uk",
+ "dynamicdns.org.uk",
+ "dynawebinc.com",
+ "dyndns-ip.com",
+ "dyndns-pics.com",
+ "dyndns.org",
+ "dyndns.pro",
+ "dynssl.com",
+ "dynu.com",
+ "dynu.net",
+ "dysfz.cc",
+ "dzze.com",
+ "e-classical.com.tw",
+ "e-gold.com",
+ "e-hentai.org",
+ "e-hentaidb.com",
+ "e-info.org.tw",
+ "e-traderland.net",
+ "e-zone.com.hk",
+ "e123.hk",
+ "earlytibet.com",
+ "earthcam.com",
+ "earthvpn.com",
+ "eastern-ark.com",
+ "easternlightning.org",
+ "eastturkestan.com",
+ "eastturkistan-gov.org",
+ "eastturkistan.net",
+ "eastturkistancc.org",
+ "eastturkistangovernmentinexile.us",
+ "easyca.ca",
+ "easypic.com",
+ "ebony-beauty.com",
+ "ebookbrowse.com",
+ "ebookee.com",
+ "ebtcbank.com",
+ "ecfa.org.tw",
+ "echainhost.com",
+ "echofon.com",
+ "ecimg.tw",
+ "ecministry.net",
+ "economist.com",
+ "ecstart.com",
+ "edgecastcdn.net",
+ "edgesuite.net",
+ "edicypages.com",
+ "edmontonchina.cn",
+ "edmontonservice.com",
+ "edns.biz",
+ "edoors.com",
+ "edubridge.com",
+ "edupro.org",
+ "eesti.ee",
+ "eevpn.com",
+ "efcc.org.hk",
+ "effers.com",
+ "efksoft.com",
+ "efukt.com",
+ "eic-av.com",
+ "eireinikotaerukai.com",
+ "eisbb.com",
+ "eksisozluk.com",
+ "electionsmeter.com",
+ "elgoog.im",
+ "ellawine.org",
+ "elpais.com",
+ "eltondisney.com",
+ "emaga.com",
+ "emanna.com",
+ "embr.in",
+ "emilylau.org.hk",
+ "emory.edu",
+ "empfil.com",
+ "emule-ed2k.com",
+ "emulefans.com",
+ "emuparadise.me",
+ "enanyang.my",
+ "encyclopedia.com",
+ "enewstree.com",
+ "enfal.de",
+ "engadget.com",
+ "engagedaily.org",
+ "englishforeveryone.org",
+ "englishfromengland.co.uk",
+ "englishpen.org",
+ "enlighten.org.tw",
+ "entermap.com",
+ "entnt.com",
+ "environment.google",
+ "epa.gov.tw",
+ "epac.to",
+ "episcopalchurch.org",
+ "epochhk.com",
+ "epochtimes-bg.com",
+ "epochtimes-romania.com",
+ "epochtimes.co.il",
+ "epochtimes.co.kr",
+ "epochtimes.com",
+ "epochtimes.cz",
+ "epochtimes.de",
+ "epochtimes.fr",
+ "epochtimes.ie",
+ "epochtimes.it",
+ "epochtimes.jp",
+ "epochtimes.ru",
+ "epochtimes.se",
+ "epochtimestr.com",
+ "epochweek.com",
+ "epochweekly.com",
+ "eporner.com",
+ "equinenow.com",
+ "erabaru.net",
+ "eracom.com.tw",
+ "eraysoft.com.tr",
+ "erepublik.com",
+ "erights.net",
+ "eriversoft.com",
+ "erktv.com",
+ "ernestmandel.org",
+ "erodaizensyu.com",
+ "erodoujinlog.com",
+ "erodoujinworld.com",
+ "eromanga-kingdom.com",
+ "eromangadouzin.com",
+ "eromon.net",
+ "eroprofile.com",
+ "eroticsaloon.net",
+ "eslite.com",
+ "esmtp.biz",
+ "esu.im",
+ "esurance.com",
+ "etaa.org.au",
+ "etadult.com",
+ "etaiwannews.com",
+ "etherdelta.com",
+ "etizer.org",
+ "etokki.com",
+ "etowns.net",
+ "etowns.org",
+ "ettoday.net",
+ "etvonline.hk",
+ "eu.org",
+ "eucasino.com",
+ "eulam.com",
+ "eurekavpt.com",
+ "euronews.com",
+ "europa.eu",
+ "evschool.net",
+ "exblog.co.jp",
+ "exblog.jp",
+ "exchristian.hk",
+ "excite.co.jp",
+ "exmo.com",
+ "exmormon.org",
+ "expatshield.com",
+ "expecthim.com",
+ "expekt.com",
+ "experts-univers.com",
+ "exploader.net",
+ "expofutures.com",
+ "expressvpn.com",
+ "exrates.me",
+ "extmatrix.com",
+ "extremetube.com",
+ "exx.com",
+ "eyevio.jp",
+ "eyny.com",
+ "ezpc.tk",
+ "ezpeer.com",
+ "ezua.com",
+ "fa.gov.tw",
+ "facebook.br",
+ "facebook.com",
+ "facebook.design",
+ "facebook.hu",
+ "facebook.in",
+ "facebook.net",
+ "facebook.nl",
+ "facebook.se",
+ "facebookmail.com",
+ "facebookquotes4u.com",
+ "faceless.me",
+ "facesofnyfw.com",
+ "facesoftibetanselfimmolators.info",
+ "fail.hk",
+ "faith100.org",
+ "faithfuleye.com",
+ "faiththedog.info",
+ "fakku.net",
+ "falsefire.com",
+ "falun-co.org",
+ "falun-ny.net",
+ "falunart.org",
+ "falunasia.info",
+ "falunau.org",
+ "falunaz.net",
+ "falundafa-dc.org",
+ "falundafa-florida.org",
+ "falundafa-nc.org",
+ "falundafa-pa.net",
+ "falundafa-sacramento.org",
+ "falundafa.org",
+ "falundafaindia.org",
+ "falundafamuseum.org",
+ "falungong.club",
+ "falungong.de",
+ "falungong.org.uk",
+ "falunhr.org",
+ "faluninfo.de",
+ "faluninfo.net",
+ "falunpilipinas.net",
+ "falunworld.net",
+ "familyfed.org",
+ "famunion.com",
+ "fan-qiang.com",
+ "fangbinxing.com",
+ "fangeming.com",
+ "fangeqiang.com",
+ "fanglizhi.info",
+ "fangmincn.org",
+ "fangong.org",
+ "fangongheike.com",
+ "fanhaodang.com",
+ "fanqiang.tk",
+ "fanqiangdang.com",
+ "fanqianghou.com",
+ "fanqiangyakexi.net",
+ "fanqiangzhe.com",
+ "fanswong.com",
+ "fanyue.info",
+ "fapdu.com",
+ "faproxy.com",
+ "faqserv.com",
+ "fartit.com",
+ "farwestchina.com",
+ "fastly.net",
+ "fastpic.ru",
+ "fastssh.com",
+ "faststone.org",
+ "fatbtc.com",
+ "favotter.net",
+ "favstar.fm",
+ "fawanghuihui.org",
+ "faydao.com",
+ "fb.com",
+ "fb.me",
+ "fbaddins.com",
+ "fbcdn.net",
+ "fbsbx.com",
+ "fbworkmail.com",
+ "fc2.com",
+ "fc2blog.net",
+ "fc2china.com",
+ "fc2cn.com",
+ "fc2web.com",
+ "fda.gov.tw",
+ "fdbox.com",
+ "fdc64.de",
+ "fdc64.org",
+ "fdc89.jp",
+ "feedburner.com",
+ "feedly.com",
+ "feedx.net",
+ "feelssh.com",
+ "feer.com",
+ "feifeiss.com",
+ "feitian-california.org",
+ "feitianacademy.org",
+ "feministteacher.com",
+ "fengzhenghu.com",
+ "fengzhenghu.net",
+ "fevernet.com",
+ "ff.im",
+ "fffff.at",
+ "fflick.com",
+ "ffvpn.com",
+ "fgmtv.net",
+ "fgmtv.org",
+ "fhreports.net",
+ "figprayer.com",
+ "fileflyer.com",
+ "fileforum.com",
+ "files2me.com",
+ "fileserve.com",
+ "filesor.com",
+ "fillthesquare.org",
+ "filmingfortibet.org",
+ "filthdump.com",
+ "financetwitter.com",
+ "finchvpn.com",
+ "findmespot.com",
+ "findyoutube.com",
+ "findyoutube.net",
+ "fingerdaily.com",
+ "finler.net",
+ "firearmsworld.net",
+ "firebaseio.com",
+ "fireofliberty.org",
+ "firetweet.io",
+ "firstfivefollowers.com",
+ "fizzik.com",
+ "flagsonline.it",
+ "flecheinthepeche.fr",
+ "fleshbot.com",
+ "fleursdeslettres.com",
+ "flgg.us",
+ "flgjustice.org",
+ "flickr.com",
+ "flickrhivemind.net",
+ "flickriver.com",
+ "fling.com",
+ "flipboard.com",
+ "flipkart.com",
+ "flitto.com",
+ "flnet.org",
+ "flog.tw",
+ "flurry.com",
+ "flyvpn.com",
+ "flyzy2005.com",
+ "fmnnow.com",
+ "fnac.be",
+ "fnac.com",
+ "fochk.org",
+ "focustaiwan.tw",
+ "focusvpn.com",
+ "fofg-europe.net",
+ "fofg.org",
+ "fofldfradio.org",
+ "foolsmountain.com",
+ "fooooo.com",
+ "footwiball.com",
+ "foreignpolicy.com",
+ "forum4hk.com",
+ "forums-free.com",
+ "fotile.me",
+ "fourthinternational.org",
+ "foxbusiness.com",
+ "foxdie.us",
+ "foxgay.com",
+ "foxsub.com",
+ "foxtang.com",
+ "fpmt-osel.org",
+ "fpmt.org",
+ "fpmt.tw",
+ "fpmtmexico.org",
+ "fqok.org",
+ "fqrouter.com",
+ "franklc.com",
+ "freakshare.com",
+ "free-gate.org",
+ "free-hada-now.org",
+ "free-proxy.cz",
+ "free-ss.site",
+ "free-ssh.com",
+ "free.fr",
+ "free4u.com.ar",
+ "freealim.com",
+ "freebearblog.org",
+ "freebrowser.org",
+ "freechal.com",
+ "freechina.net",
+ "freechina.news",
+ "freechinaforum.org",
+ "freechinaweibo.com",
+ "freeddns.com",
+ "freeddns.org",
+ "freedomchina.info",
+ "freedomcollection.org",
+ "freedomhouse.org",
+ "freedomsherald.org",
+ "freeforums.org",
+ "freefq.com",
+ "freefuckvids.com",
+ "freegao.com",
+ "freehongkong.org",
+ "freeilhamtohti.org",
+ "freekazakhs.org",
+ "freekwonpyong.org",
+ "freelotto.com",
+ "freeman2.com",
+ "freemoren.com",
+ "freemorenews.com",
+ "freemuse.org",
+ "freenet-china.org",
+ "freenetproject.org",
+ "freenewscn.com",
+ "freeones.com",
+ "freeopenvpn.com",
+ "freeoz.org",
+ "freerk.com",
+ "freessh.us",
+ "freetcp.com",
+ "freetibet.net",
+ "freetibet.org",
+ "freetibetanheroes.org",
+ "freeviewmovies.com",
+ "freevpn.me",
+ "freevpn.nl",
+ "freewallpaper4.me",
+ "freewebs.com",
+ "freewechat.com",
+ "freeweibo.com",
+ "freewww.biz",
+ "freewww.info",
+ "freexinwen.com",
+ "freeyellow.com",
+ "freeyoutubeproxy.net",
+ "frienddy.com",
+ "friendfeed-media.com",
+ "friendfeed.com",
+ "friendfinder.com",
+ "friends-of-tibet.org",
+ "friendsoftibet.org",
+ "fring.com",
+ "fringenetwork.com",
+ "from-pr.com",
+ "from-sd.com",
+ "fromchinatousa.net",
+ "frommel.net",
+ "frontlinedefenders.org",
+ "frootvpn.com",
+ "fscked.org",
+ "fsurf.com",
+ "ftchinese.com",
+ "ftp1.biz",
+ "ftpserver.biz",
+ "ftv.com.tw",
+ "fucd.com",
+ "fuckcnnic.net",
+ "fuckgfw.org",
+ "fuckgfw233.org",
+ "fulione.com",
+ "fullerconsideration.com",
+ "fulue.com",
+ "funf.tw",
+ "funkyimg.com",
+ "funp.com",
+ "fuq.com",
+ "furbo.org",
+ "furhhdl.org",
+ "furinkan.com",
+ "furl.net",
+ "futurechinaforum.org",
+ "futuremessage.org",
+ "fux.com",
+ "fuyin.net",
+ "fuyindiantai.org",
+ "fuyu.org.tw",
+ "fw.cm",
+ "fxcm-chinese.com",
+ "fxnetworks.com",
+ "fzh999.com",
+ "fzh999.net",
+ "fzlm.com",
+ "g-area.org",
+ "g-queen.com",
+ "g.co",
+ "g0v.social",
+ "g6hentai.com",
+ "gabocorp.com",
+ "gaeproxy.com",
+ "gaforum.org",
+ "gagaoolala.com",
+ "galaxymacau.com",
+ "galenwu.com",
+ "galstars.net",
+ "game735.com",
+ "gamebase.com.tw",
+ "gamejolt.com",
+ "gamer.com.tw",
+ "gamerp.jp",
+ "gamez.com.tw",
+ "gamousa.com",
+ "ganges.com",
+ "gaoming.net",
+ "gaopi.net",
+ "gaozhisheng.net",
+ "gaozhisheng.org",
+ "gardennetworks.com",
+ "gardennetworks.org",
+ "gartlive.com",
+ "gate-project.com",
+ "gate.io",
+ "gatecoin.com",
+ "gather.com",
+ "gatherproxy.com",
+ "gati.org.tw",
+ "gaybubble.com",
+ "gaycn.net",
+ "gayhub.com",
+ "gaymap.cc",
+ "gaymenring.com",
+ "gaytube.com",
+ "gaywatch.com",
+ "gazotube.com",
+ "gcc.org.hk",
+ "gclooney.com",
+ "gcmasia.com",
+ "gcpnews.com",
+ "gcr.io",
+ "gdbt.net",
+ "gdzf.org",
+ "geek-art.net",
+ "geekerhome.com",
+ "geekheart.info",
+ "gekikame.com",
+ "gelbooru.com",
+ "geocities.co.jp",
+ "geocities.com",
+ "geocities.jp",
+ "gerefoundation.org",
+ "get.app",
+ "get.dev",
+ "get.how",
+ "get.page",
+ "getastrill.com",
+ "getchu.com",
+ "getcloak.com",
+ "getfoxyproxy.org",
+ "getfreedur.com",
+ "getgom.com",
+ "geti2p.net",
+ "getiton.com",
+ "getjetso.com",
+ "getlantern.org",
+ "getmdl.io",
+ "getoutline.org",
+ "getsocialscope.com",
+ "getsync.com",
+ "gettrials.com",
+ "gettyimages.com",
+ "getuploader.com",
+ "gfbv.de",
+ "gfgold.com.hk",
+ "gfsale.com",
+ "gfw.org.ua",
+ "gfw.press",
+ "ggpht.com",
+ "ggssl.com",
+ "ghostpath.com",
+ "ghut.org",
+ "giantessnight.com",
+ "gifree.com",
+ "giga-web.jp",
+ "gigacircle.com",
+ "giganews.com",
+ "gigporno.ru",
+ "girlbanker.com",
+ "git.io",
+ "gitbooks.io",
+ "github.com",
+ "github.io",
+ "githubassets.com",
+ "githubusercontent.com",
+ "gizlen.net",
+ "gjczz.com",
+ "glass8.eu",
+ "globaljihad.net",
+ "globalmediaoutreach.com",
+ "globalmuseumoncommunism.org",
+ "globalrescue.net",
+ "globaltm.org",
+ "globalvoices.org",
+ "globalvoicesonline.org",
+ "globalvpn.net",
+ "glock.com",
+ "gloryhole.com",
+ "glorystar.me",
+ "gluckman.com",
+ "glype.com",
+ "gmail.com",
+ "gmbd.cn",
+ "gmhz.org",
+ "gmiddle.com",
+ "gmiddle.net",
+ "gmll.org",
+ "gmodules.com",
+ "gnci.org.hk",
+ "gnews.org",
+ "go-pki.com",
+ "go141.com",
+ "goagent.biz",
+ "goagentplus.com",
+ "gobet.cc",
+ "godfootsteps.org",
+ "godns.work",
+ "godoc.org",
+ "godsdirectcontact.co.uk",
+ "godsdirectcontact.org",
+ "godsdirectcontact.org.tw",
+ "godsimmediatecontact.com",
+ "gogotunnel.com",
+ "gohappy.com.tw",
+ "gokbayrak.com",
+ "golang.org",
+ "goldbet.com",
+ "goldbetsports.com",
+ "golden-ages.org",
+ "goldeneyevault.com",
+ "goldenfrog.com",
+ "goldjizz.com",
+ "goldstep.net",
+ "goldwave.com",
+ "gongm.in",
+ "gongmeng.info",
+ "gongminliliang.com",
+ "gongwt.com",
+ "goo.gl",
+ "goo.ne.jp",
+ "gooday.xyz",
+ "gooddns.info",
+ "goodreaders.com",
+ "goodreads.com",
+ "goodtv.com.tw",
+ "goodtv.tv",
+ "goofind.com",
+ "google.ac",
+ "google.ad",
+ "google.ae",
+ "google.af",
+ "google.al",
+ "google.am",
+ "google.as",
+ "google.at",
+ "google.az",
+ "google.ba",
+ "google.be",
+ "google.bf",
+ "google.bg",
+ "google.bi",
+ "google.bj",
+ "google.bs",
+ "google.bt",
+ "google.by",
+ "google.ca",
+ "google.cat",
+ "google.cd",
+ "google.cf",
+ "google.cg",
+ "google.ch",
+ "google.ci",
+ "google.cl",
+ "google.cm",
+ "google.cn",
+ "google.co.ao",
+ "google.co.bw",
+ "google.co.ck",
+ "google.co.cr",
+ "google.co.id",
+ "google.co.il",
+ "google.co.in",
+ "google.co.jp",
+ "google.co.ke",
+ "google.co.kr",
+ "google.co.ls",
+ "google.co.ma",
+ "google.co.mz",
+ "google.co.nz",
+ "google.co.th",
+ "google.co.tz",
+ "google.co.ug",
+ "google.co.uk",
+ "google.co.uz",
+ "google.co.ve",
+ "google.co.vi",
+ "google.co.za",
+ "google.co.zm",
+ "google.co.zw",
+ "google.com",
+ "google.com.af",
+ "google.com.ag",
+ "google.com.ai",
+ "google.com.ar",
+ "google.com.au",
+ "google.com.bd",
+ "google.com.bh",
+ "google.com.bn",
+ "google.com.bo",
+ "google.com.br",
+ "google.com.bz",
+ "google.com.co",
+ "google.com.cu",
+ "google.com.cy",
+ "google.com.do",
+ "google.com.ec",
+ "google.com.eg",
+ "google.com.et",
+ "google.com.fj",
+ "google.com.gh",
+ "google.com.gi",
+ "google.com.gt",
+ "google.com.hk",
+ "google.com.jm",
+ "google.com.kh",
+ "google.com.kw",
+ "google.com.lb",
+ "google.com.ly",
+ "google.com.mm",
+ "google.com.mt",
+ "google.com.mx",
+ "google.com.my",
+ "google.com.na",
+ "google.com.nf",
+ "google.com.ng",
+ "google.com.ni",
+ "google.com.np",
+ "google.com.om",
+ "google.com.pa",
+ "google.com.pe",
+ "google.com.pg",
+ "google.com.ph",
+ "google.com.pk",
+ "google.com.pr",
+ "google.com.py",
+ "google.com.qa",
+ "google.com.sa",
+ "google.com.sb",
+ "google.com.sg",
+ "google.com.sl",
+ "google.com.sv",
+ "google.com.tj",
+ "google.com.tr",
+ "google.com.tw",
+ "google.com.ua",
+ "google.com.uy",
+ "google.com.vc",
+ "google.com.vn",
+ "google.cv",
+ "google.cz",
+ "google.de",
+ "google.dev",
+ "google.dj",
+ "google.dk",
+ "google.dm",
+ "google.dz",
+ "google.ee",
+ "google.es",
+ "google.eu",
+ "google.fi",
+ "google.fm",
+ "google.fr",
+ "google.ga",
+ "google.ge",
+ "google.gg",
+ "google.gl",
+ "google.gm",
+ "google.gp",
+ "google.gr",
+ "google.gy",
+ "google.hk",
+ "google.hn",
+ "google.hr",
+ "google.ht",
+ "google.hu",
+ "google.ie",
+ "google.im",
+ "google.iq",
+ "google.is",
+ "google.it",
+ "google.it.ao",
+ "google.je",
+ "google.jo",
+ "google.kg",
+ "google.ki",
+ "google.kz",
+ "google.la",
+ "google.li",
+ "google.lk",
+ "google.lt",
+ "google.lu",
+ "google.lv",
+ "google.md",
+ "google.me",
+ "google.mg",
+ "google.mk",
+ "google.ml",
+ "google.mn",
+ "google.ms",
+ "google.mu",
+ "google.mv",
+ "google.mw",
+ "google.mx",
+ "google.ne",
+ "google.nl",
+ "google.no",
+ "google.nr",
+ "google.nu",
+ "google.org",
+ "google.pl",
+ "google.pn",
+ "google.ps",
+ "google.pt",
+ "google.ro",
+ "google.rs",
+ "google.ru",
+ "google.rw",
+ "google.sc",
+ "google.se",
+ "google.sh",
+ "google.si",
+ "google.sk",
+ "google.sm",
+ "google.sn",
+ "google.so",
+ "google.sr",
+ "google.st",
+ "google.td",
+ "google.tg",
+ "google.tk",
+ "google.tl",
+ "google.tm",
+ "google.tn",
+ "google.to",
+ "google.tt",
+ "google.us",
+ "google.vg",
+ "google.vn",
+ "google.vu",
+ "google.ws",
+ "googleapis.cn",
+ "googleapis.com",
+ "googleapps.com",
+ "googlearth.com",
+ "googleartproject.com",
+ "googleblog.com",
+ "googlebot.com",
+ "googlechinawebmaster.com",
+ "googlecode.com",
+ "googlecommerce.com",
+ "googledomains.com",
+ "googledrive.com",
+ "googleearth.com",
+ "googlegroups.com",
+ "googlehosted.com",
+ "googleideas.com",
+ "googleinsidesearch.com",
+ "googlelabs.com",
+ "googlemail.com",
+ "googlemashups.com",
+ "googlepagecreator.com",
+ "googleplay.com",
+ "googleplus.com",
+ "googlescholar.com",
+ "googlesile.com",
+ "googlesource.com",
+ "googleusercontent.com",
+ "googlevideo.com",
+ "googleweblight.com",
+ "googlezip.net",
+ "gopetition.com",
+ "goproxing.net",
+ "goregrish.com",
+ "gospelherald.com",
+ "got-game.org",
+ "gotdns.ch",
+ "gotgeeks.com",
+ "gotrusted.com",
+ "gotw.ca",
+ "gov.taipei",
+ "gr8domain.biz",
+ "gr8name.biz",
+ "gradconnection.com",
+ "grammaly.com",
+ "grandtrial.org",
+ "grangorz.org",
+ "graphis.ne.jp",
+ "graphql.org",
+ "greasespot.net",
+ "great-firewall.com",
+ "great-roc.org",
+ "greatfire.org",
+ "greatfirewall.biz",
+ "greatfirewallofchina.net",
+ "greatfirewallofchina.org",
+ "greatroc.org",
+ "greatroc.tw",
+ "greatzhonghua.org",
+ "greenfieldbookstore.com.hk",
+ "greenparty.org.tw",
+ "greenpeace.com.tw",
+ "greenpeace.org",
+ "greenreadings.com",
+ "greenvpn.net",
+ "greenvpn.org",
+ "grotty-monday.com",
+ "grow.google",
+ "gs-discuss.com",
+ "gstatic.com",
+ "gtricks.com",
+ "gts-vpn.com",
+ "gtv.org",
+ "gtv1.org",
+ "gu-chu-sum.org",
+ "guaguass.com",
+ "guaguass.org",
+ "guancha.org",
+ "guaneryu.com",
+ "guangming.com.my",
+ "guangnianvpn.com",
+ "guardster.com",
+ "guishan.org",
+ "gumroad.com",
+ "gun-world.net",
+ "gunsamerica.com",
+ "gunsandammo.com",
+ "guo.media",
+ "guruonline.hk",
+ "gutteruncensored.com",
+ "gvlib.com",
+ "gvm.com.tw",
+ "gvt0.com",
+ "gvt1.com",
+ "gvt3.com",
+ "gwtproject.org",
+ "gyalwarinpoche.com",
+ "gyatsostudio.com",
+ "gzm.tv",
+ "gzone-anime.info",
+ "h-china.org",
+ "h-moe.com",
+ "h1n1china.org",
+ "h528.com",
+ "h5dm.com",
+ "h5galgame.me",
+ "hacg.club",
+ "hacg.in",
+ "hacg.li",
+ "hacg.me",
+ "hacg.red",
+ "hacken.cc",
+ "hacker.org",
+ "hackthatphone.net",
+ "hahlo.com",
+ "hakkatv.org.tw",
+ "handcraftedsoftware.org",
+ "hanime.tv",
+ "hanminzu.org",
+ "hanunyi.com",
+ "hao.news",
+ "hao123.com",
+ "hao123img.com",
+ "happy-vpn.com",
+ "haproxy.org",
+ "hardsextube.com",
+ "harunyahya.com",
+ "hasi.wang",
+ "hautelook.com",
+ "hautelookcdn.com",
+ "have8.com",
+ "hbg.com",
+ "hbo.com",
+ "hclips.com",
+ "hdlt.me",
+ "hdtvb.net",
+ "hdzog.com",
+ "heartyit.com",
+ "heavy-r.com",
+ "hec.su",
+ "hecaitou.net",
+ "hechaji.com",
+ "heeact.edu.tw",
+ "hegre-art.com",
+ "helixstudios.net",
+ "helloandroid.com",
+ "helloqueer.com",
+ "helloss.pw",
+ "hellotxt.com",
+ "hellouk.org",
+ "helpeachpeople.com",
+ "helplinfen.com",
+ "helpster.de",
+ "helpuyghursnow.org",
+ "helpzhuling.org",
+ "hentai.to",
+ "hentaitube.tv",
+ "hentaivideoworld.com",
+ "heqinglian.net",
+ "here.com",
+ "heroku.com",
+ "heungkongdiscuss.com",
+ "hexieshe.com",
+ "hexieshe.xyz",
+ "hexxeh.net",
+ "heywire.com",
+ "heyzo.com",
+ "hgseav.com",
+ "hhdcb3office.org",
+ "hhthesakyatrizin.org",
+ "hi-on.org.tw",
+ "hidden-advent.org",
+ "hide.me",
+ "hidecloud.com",
+ "hidein.net",
+ "hideipvpn.com",
+ "hideman.net",
+ "hideme.nl",
+ "hidemy.name",
+ "hidemyass.com",
+ "hidemycomp.com",
+ "higfw.com",
+ "highpeakspureearth.com",
+ "highrockmedia.com",
+ "hightail.com",
+ "hihiforum.com",
+ "hihistory.net",
+ "hiitch.com",
+ "hikinggfw.org",
+ "hilive.tv",
+ "himalayan-foundation.org",
+ "himalayanglacier.com",
+ "himemix.com",
+ "himemix.net",
+ "hinet.net",
+ "hitbtc.com",
+ "hitomi.la",
+ "hiwifi.com",
+ "hizb-ut-tahrir.info",
+ "hizb-ut-tahrir.org",
+ "hizbuttahrir.org",
+ "hjclub.info",
+ "hk-pub.com",
+ "hk01.com",
+ "hk32168.com",
+ "hkacg.com",
+ "hkacg.net",
+ "hkatvnews.com",
+ "hkbc.net",
+ "hkbf.org",
+ "hkbookcity.com",
+ "hkchurch.org",
+ "hkci.org.hk",
+ "hkcmi.edu",
+ "hkcnews.com",
+ "hkcoc.com",
+ "hkctu.org.hk",
+ "hkdailynews.com.hk",
+ "hkday.net",
+ "hkdf.org",
+ "hkej.com",
+ "hkepc.com",
+ "hket.com",
+ "hkfaa.com",
+ "hkfreezone.com",
+ "hkfront.org",
+ "hkgalden.com",
+ "hkgolden.com",
+ "hkgreenradio.org",
+ "hkheadline.com",
+ "hkhkhk.com",
+ "hkhrc.org.hk",
+ "hkhrm.org.hk",
+ "hkip.org.uk",
+ "hkja.org.hk",
+ "hkjc.com",
+ "hkjp.org",
+ "hklft.com",
+ "hklts.org.hk",
+ "hkpeanut.com",
+ "hkptu.org",
+ "hkreporter.com",
+ "hku.hk",
+ "hkusu.net",
+ "hkvwet.com",
+ "hkwcc.org.hk",
+ "hkzone.org",
+ "hmonghot.com",
+ "hmv.co.jp",
+ "hmvdigital.ca",
+ "hmvdigital.com",
+ "hnjhj.com",
+ "hnntube.com",
+ "hola.com",
+ "hola.org",
+ "holymountaincn.com",
+ "holyspiritspeaks.org",
+ "homedepot.com",
+ "homeip.net",
+ "homeperversion.com",
+ "homeservershow.com",
+ "honeynet.org",
+ "hongkongfp.com",
+ "hongmeimei.com",
+ "hongzhi.li",
+ "honven.xyz",
+ "hootsuite.com",
+ "hoovers.com",
+ "hopedialogue.org",
+ "hopto.org",
+ "hornygamer.com",
+ "hornytrip.com",
+ "hotav.tv",
+ "hotels.cn",
+ "hotfrog.com.tw",
+ "hotgoo.com",
+ "hotpornshow.com",
+ "hotpot.hk",
+ "hotshame.com",
+ "hotspotshield.com",
+ "hotvpn.com",
+ "hougaige.com",
+ "howtoforge.com",
+ "hoxx.com",
+ "hpa.gov.tw",
+ "hqcdp.org",
+ "hqjapanesesex.com",
+ "hqmovies.com",
+ "hrcchina.org",
+ "hrcir.com",
+ "hrea.org",
+ "hrichina.org",
+ "hrtsea.com",
+ "hrw.org",
+ "hrweb.org",
+ "hsjp.net",
+ "hsselite.com",
+ "hst.net.tw",
+ "hstern.net",
+ "hstt.net",
+ "ht.ly",
+ "htkou.net",
+ "htl.li",
+ "html5rocks.com",
+ "https443.net",
+ "https443.org",
+ "hua-yue.net",
+ "huaglad.com",
+ "huanghuagang.org",
+ "huangyiyu.com",
+ "huaren.us",
+ "huaren4us.com",
+ "huashangnews.com",
+ "huasing.org",
+ "huaxia-news.com",
+ "huaxiabao.org",
+ "huaxin.ph",
+ "huayuworld.org",
+ "hudatoriq.web.id",
+ "hudson.org",
+ "huffingtonpost.com",
+ "hugoroy.eu",
+ "huhaitai.com",
+ "huhamhire.com",
+ "huhangfei.com",
+ "huiyi.in",
+ "hulkshare.com",
+ "hulu.com",
+ "huluim.com",
+ "humanrightsbriefing.org",
+ "hung-ya.com",
+ "hungerstrikeforaids.org",
+ "huobi.com",
+ "huobi.pro",
+ "huobipro.com",
+ "huping.net",
+ "hurgokbayrak.com",
+ "hurriyet.com.tr",
+ "hustler.com",
+ "hustlercash.com",
+ "hut2.ru",
+ "hutianyi.net",
+ "hutong9.net",
+ "huyandex.com",
+ "hwadzan.tw",
+ "hwayue.org.tw",
+ "hwinfo.com",
+ "hxwk.org",
+ "hxwq.org",
+ "hybrid-analysis.com",
+ "hyperrate.com",
+ "hyread.com.tw",
+ "i-cable.com",
+ "i-part.com.tw",
+ "i-scmp.com",
+ "i1.hk",
+ "i2p2.de",
+ "i2runner.com",
+ "i818hk.com",
+ "iam.soy",
+ "iamtopone.com",
+ "iask.bz",
+ "iask.ca",
+ "iav19.com",
+ "ibiblio.org",
+ "ibit.am",
+ "iblist.com",
+ "iblogserv-f.net",
+ "ibros.org",
+ "ibtimes.com",
+ "ibvpn.com",
+ "icams.com",
+ "icerocket.com",
+ "icij.org",
+ "icl-fi.org",
+ "icoco.com",
+ "iconfactory.net",
+ "iconpaper.org",
+ "icu-project.org",
+ "idaiwan.com",
+ "iddddg.com",
+ "idemocracy.asia",
+ "identi.ca",
+ "idiomconnection.com",
+ "idlcoyote.com",
+ "idouga.com",
+ "idreamx.com",
+ "idsam.com",
+ "ieasy5.com",
+ "ied2k.net",
+ "ienergy1.com",
+ "ifanqiang.com",
+ "ifcss.org",
+ "ifjc.org",
+ "ifreewares.com",
+ "ift.tt",
+ "igcd.net",
+ "igfw.net",
+ "igfw.tech",
+ "igmg.de",
+ "ignitedetroit.net",
+ "igoogle.com",
+ "igotmail.com.tw",
+ "igvita.com",
+ "ihakka.net",
+ "ihao.org",
+ "iicns.com",
+ "ikstar.com",
+ "ikwb.com",
+ "ilhamtohtiinstitute.org",
+ "illusionfactory.com",
+ "ilove80.be",
+ "ilovelongtoes.com",
+ "im.tv",
+ "im88.tw",
+ "imageab.com",
+ "imagefap.com",
+ "imageflea.com",
+ "images-gaytube.com",
+ "imageshack.us",
+ "imagevenue.com",
+ "imagezilla.net",
+ "imb.org",
+ "imdb.com",
+ "img.ly",
+ "imgchili.net",
+ "imgmega.com",
+ "imgur.com",
+ "imkev.com",
+ "imlive.com",
+ "immigration.gov.tw",
+ "immoral.jp",
+ "impact.org.au",
+ "impp.mn",
+ "in-disguise.com",
+ "in.com",
+ "in99.org",
+ "incapdns.net",
+ "incloak.com",
+ "incredibox.fr",
+ "indiandefensenews.in",
+ "indiatimes.com",
+ "indiemerch.com",
+ "info-graf.fr",
+ "informer.com",
+ "initiativesforchina.org",
+ "inkui.com",
+ "inmediahk.net",
+ "innermongolia.org",
+ "inoreader.com",
+ "inote.tw",
+ "insecam.org",
+ "insidevoa.com",
+ "instagram.com",
+ "instanthq.com",
+ "institut-tibetain.org",
+ "internet.org",
+ "internetdefenseleague.org",
+ "internetfreedom.org",
+ "internetpopculture.com",
+ "inthenameofconfuciusmovie.com",
+ "inxian.com",
+ "iownyour.biz",
+ "iownyour.org",
+ "ipalter.com",
+ "ipfire.org",
+ "ipfs.io",
+ "iphone4hongkong.com",
+ "iphonehacks.com",
+ "iphonetaiwan.org",
+ "iphonix.fr",
+ "ipicture.ru",
+ "ipjetable.net",
+ "ipobar.com",
+ "ipoock.com",
+ "iportal.me",
+ "ippotv.com",
+ "ipredator.se",
+ "iptv.com.tw",
+ "iptvbin.com",
+ "ipvanish.com",
+ "iqiyi.com",
+ "iredmail.org",
+ "irib.ir",
+ "ironpython.net",
+ "ironsocket.com",
+ "is-a-hunter.com",
+ "is.gd",
+ "isaacmao.com",
+ "isasecret.com",
+ "isgreat.org",
+ "islahhaber.net",
+ "islam.org.hk",
+ "islamawareness.net",
+ "islamhouse.com",
+ "islamicity.com",
+ "islamicpluralism.org",
+ "islamtoday.net",
+ "ismaelan.com",
+ "ismalltits.com",
+ "ismprofessional.net",
+ "isohunt.com",
+ "israbox.com",
+ "issuu.com",
+ "istars.co.nz",
+ "istarshine.com",
+ "istef.info",
+ "istiqlalhewer.com",
+ "istockphoto.com",
+ "isunaffairs.com",
+ "isuntv.com",
+ "itaboo.info",
+ "itaiwan.gov.tw",
+ "italiatibet.org",
+ "itasoftware.com",
+ "itemdb.com",
+ "ithome.com.tw",
+ "itsaol.com",
+ "itshidden.com",
+ "itsky.it",
+ "itweet.net",
+ "iu45.com",
+ "iuhrdf.org",
+ "iuksky.com",
+ "ivacy.com",
+ "iverycd.com",
+ "ivpn.net",
+ "ixquick.com",
+ "ixxx.com",
+ "iyouport.com",
+ "izaobao.us",
+ "izihost.org",
+ "izles.net",
+ "izlesem.org",
+ "j.mp",
+ "jackjia.com",
+ "jamaat.org",
+ "jamyangnorbu.com",
+ "jandyx.com",
+ "janwongphoto.com",
+ "japan-whores.com",
+ "japantimes.co.jp",
+ "jav.com",
+ "jav101.com",
+ "jav2be.com",
+ "jav68.tv",
+ "javakiba.org",
+ "javbus.com",
+ "javfor.me",
+ "javhd.com",
+ "javhip.com",
+ "javhub.net",
+ "javhuge.com",
+ "javlibrary.com",
+ "javmobile.net",
+ "javmoo.com",
+ "javmoo.xyz",
+ "javseen.com",
+ "javtag.com",
+ "javzoo.com",
+ "jbtalks.cc",
+ "jbtalks.com",
+ "jbtalks.my",
+ "jcpenney.com",
+ "jdwsy.com",
+ "jeanyim.com",
+ "jetos.com",
+ "jex.com",
+ "jfqu36.club",
+ "jfqu37.xyz",
+ "jgoodies.com",
+ "jiangweiping.com",
+ "jiaoyou8.com",
+ "jiehua.cz",
+ "jiepang.com",
+ "jieshibaobao.com",
+ "jigglegifs.com",
+ "jigong1024.com",
+ "jigsy.com",
+ "jihadology.net",
+ "jiji.com",
+ "jims.net",
+ "jinbushe.org",
+ "jingpin.org",
+ "jingsim.org",
+ "jinhai.de",
+ "jinpianwang.com",
+ "jinroukong.com",
+ "jintian.net",
+ "jinx.com",
+ "jiruan.net",
+ "jitouch.com",
+ "jizzthis.com",
+ "jjgirls.com",
+ "jkb.cc",
+ "jkforum.net",
+ "jkub.com",
+ "jma.go.jp",
+ "jmscult.com",
+ "joachims.org",
+ "jobso.tv",
+ "joinbbs.net",
+ "joinmastodon.org",
+ "joins.com",
+ "journalchretien.net",
+ "journalofdemocracy.org",
+ "joymiihub.com",
+ "joyourself.com",
+ "jp.net",
+ "jpopforum.net",
+ "jqueryui.com",
+ "jshell.net",
+ "jtvnw.net",
+ "jubushoushen.com",
+ "juhuaren.com",
+ "jukujo-club.com",
+ "juliepost.com",
+ "juliereyc.com",
+ "junauza.com",
+ "june4commemoration.org",
+ "junefourth-20.net",
+ "jungleheart.com",
+ "junglobal.net",
+ "juoaa.com",
+ "justdied.com",
+ "justfreevpn.com",
+ "justicefortenzin.org",
+ "justpaste.it",
+ "justtristan.com",
+ "juyuange.org",
+ "juziyue.com",
+ "jwmusic.org",
+ "jyxf.net",
+ "k-doujin.net",
+ "ka-wai.com",
+ "kadokawa.co.jp",
+ "kagyu.org",
+ "kagyu.org.za",
+ "kagyumonlam.org",
+ "kagyunews.com.hk",
+ "kagyuoffice.org",
+ "kagyuoffice.org.tw",
+ "kaiyuan.de",
+ "kakao.com",
+ "kalachakralugano.org",
+ "kangye.org",
+ "kankan.today",
+ "kannewyork.com",
+ "kanshifang.com",
+ "kantie.org",
+ "kanzhongguo.com",
+ "kanzhongguo.eu",
+ "kaotic.com",
+ "karayou.com",
+ "karkhung.com",
+ "karmapa-teachings.org",
+ "karmapa.org",
+ "kawaiikawaii.jp",
+ "kawase.com",
+ "kba-tx.org",
+ "kcoolonline.com",
+ "kebrum.com",
+ "kechara.com",
+ "keepandshare.com",
+ "keezmovies.com",
+ "kendatire.com",
+ "kendincos.net",
+ "kenengba.com",
+ "keontech.net",
+ "kepard.com",
+ "keso.cn",
+ "kex.com",
+ "keycdn.com",
+ "khabdha.org",
+ "khatrimaza.org",
+ "khmusic.com.tw",
+ "kichiku-doujinko.com",
+ "kik.com",
+ "killwall.com",
+ "kimy.com.tw",
+ "kindleren.com",
+ "kingdomsalvation.org",
+ "kinghost.com",
+ "kingstone.com.tw",
+ "kink.com",
+ "kinmen.org.tw",
+ "kinmen.travel",
+ "kinokuniya.com",
+ "kir.jp",
+ "kissbbao.cn",
+ "kiwi.kz",
+ "kk-whys.co.jp",
+ "kkbox.com",
+ "kknews.cc",
+ "klip.me",
+ "kmuh.org.tw",
+ "knowledgerush.com",
+ "kobo.com",
+ "kobobooks.com",
+ "kodingen.com",
+ "kompozer.net",
+ "konachan.com",
+ "kone.com",
+ "koolsolutions.com",
+ "koornk.com",
+ "koranmandarin.com",
+ "korenan2.com",
+ "krtco.com.tw",
+ "ksdl.org",
+ "ksnews.com.tw",
+ "kspcoin.com",
+ "ktzhk.com",
+ "kucoin.com",
+ "kui.name",
+ "kun.im",
+ "kurashsultan.com",
+ "kurtmunger.com",
+ "kusocity.com",
+ "kwcg.ca",
+ "kwok7.com",
+ "kwongwah.com.my",
+ "kxsw.life",
+ "kyofun.com",
+ "kyohk.net",
+ "kyoyue.com",
+ "kyzyhello.com",
+ "kzeng.info",
+ "la-forum.org",
+ "labiennale.org",
+ "ladbrokes.com",
+ "lagranepoca.com",
+ "lalulalu.com",
+ "lama.com.tw",
+ "lamayeshe.com",
+ "lamenhu.com",
+ "lamnia.co.uk",
+ "lamrim.com",
+ "landofhope.tv",
+ "lanterncn.cn",
+ "lantosfoundation.org",
+ "laod.cn",
+ "laogai.org",
+ "laomiu.com",
+ "laoyang.info",
+ "laptoplockdown.com",
+ "laqingdan.net",
+ "larsgeorge.com",
+ "lastcombat.com",
+ "lastfm.es",
+ "latelinenews.com",
+ "latibet.org",
+ "law.com",
+ "lbank.info",
+ "le-vpn.com",
+ "leafyvpn.net",
+ "lecloud.net",
+ "leeao.com.cn",
+ "lefora.com",
+ "left21.hk",
+ "legalporno.com",
+ "legsjapan.com",
+ "leirentv.ca",
+ "leisurecafe.ca",
+ "leisurepro.com",
+ "lematin.ch",
+ "lemonde.fr",
+ "lenwhite.com",
+ "lerosua.org",
+ "lers.google",
+ "lesoir.be",
+ "lester850.info",
+ "letou.com",
+ "letscorp.net",
+ "letsencrypt.org",
+ "levyhsu.com",
+ "lflink.com",
+ "lflinkup.com",
+ "lflinkup.net",
+ "lflinkup.org",
+ "lfpcontent.com",
+ "lhakar.org",
+ "lhasocialwork.org",
+ "liangyou.net",
+ "liangzhichuanmei.com",
+ "lianyue.net",
+ "liaowangxizang.net",
+ "liberal.org.hk",
+ "libertytimes.com.tw",
+ "libraryinformationtechnology.com",
+ "lidecheng.com",
+ "lifemiles.com",
+ "lighten.org.tw",
+ "lighti.me",
+ "lightnovel.cn",
+ "lightyearvpn.com",
+ "lihkg.com",
+ "like.com",
+ "limiao.net",
+ "line-apps.com",
+ "line-scdn.net",
+ "line.me",
+ "linglingfa.com",
+ "lingvodics.com",
+ "link-o-rama.com",
+ "linkideo.com",
+ "linksalpha.com",
+ "linkuswell.com",
+ "linpie.com",
+ "linux.org.hk",
+ "linuxtoy.org",
+ "lionsroar.com",
+ "lipuman.com",
+ "liquidvpn.com",
+ "list-manage.com",
+ "listentoyoutube.com",
+ "listorious.com",
+ "lithium.com",
+ "liu-xiaobo.org",
+ "liudejun.com",
+ "liuhanyu.com",
+ "liujianshu.com",
+ "liuxiaobo.net",
+ "liuxiaotong.com",
+ "live.com",
+ "livecoin.net",
+ "livedoor.jp",
+ "liveleak.com",
+ "livestation.com",
+ "livestream.com",
+ "livevideo.com",
+ "livingonline.us",
+ "livingstream.com",
+ "liwangyang.com",
+ "lizhizhuangbi.com",
+ "lkcn.net",
+ "llss.me",
+ "load.to",
+ "lobsangwangyal.com",
+ "localbitcoins.com",
+ "localdomain.ws",
+ "localpresshk.com",
+ "lockestek.com",
+ "logbot.net",
+ "logiqx.com",
+ "logmein.com",
+ "londonchinese.ca",
+ "longhair.hk",
+ "longmusic.com",
+ "longtermly.net",
+ "longtoes.com",
+ "lookpic.com",
+ "looktoronto.com",
+ "lotsawahouse.org",
+ "lotuslight.org.hk",
+ "lotuslight.org.tw",
+ "loved.hk",
+ "lovetvshow.com",
+ "lpsg.com",
+ "lrfz.com",
+ "lrip.org",
+ "lsd.org.hk",
+ "lsforum.net",
+ "lsm.org",
+ "lsmchinese.org",
+ "lsmkorean.org",
+ "lsmradio.com",
+ "lsmwebcast.com",
+ "lsxszzg.com",
+ "ltn.com.tw",
+ "luckydesigner.space",
+ "luke54.com",
+ "luke54.org",
+ "lupm.org",
+ "lushstories.com",
+ "luxebc.com",
+ "lvhai.org",
+ "lvv2.com",
+ "lyfhk.net",
+ "lzmtnews.org",
+ "m-sport.co.uk",
+ "m-team.cc",
+ "m.me",
+ "macgamestore.com",
+ "macrovpn.com",
+ "macts.com.tw",
+ "mad-ar.ch",
+ "madewithcode.com",
+ "madonna-av.com",
+ "madrau.com",
+ "madthumbs.com",
+ "magic-net.info",
+ "mahabodhi.org",
+ "maiio.net",
+ "mail-archive.com",
+ "mail.ru",
+ "mailchimp.com",
+ "maildns.xyz",
+ "maiplus.com",
+ "maizhong.org",
+ "makemymood.com",
+ "makkahnewspaper.com",
+ "malaysiakini.com",
+ "mamingzhe.com",
+ "manchukuo.net",
+ "mangafox.com",
+ "mangafox.me",
+ "maniash.com",
+ "manicur4ik.ru",
+ "mansion.com",
+ "mansionpoker.com",
+ "manta.com",
+ "maplew.com",
+ "marc.info",
+ "marguerite.su",
+ "martau.com",
+ "martincartoons.com",
+ "martinoei.com",
+ "martsangkagyuofficial.org",
+ "maruta.be",
+ "marxist.com",
+ "marxist.net",
+ "marxists.org",
+ "mash.to",
+ "maskedip.com",
+ "mastodon.cloud",
+ "mastodon.host",
+ "mastodon.social",
+ "matainja.com",
+ "material.io",
+ "mathable.io",
+ "mathiew-badimon.com",
+ "matome-plus.com",
+ "matome-plus.net",
+ "matsushimakaede.com",
+ "matters.news",
+ "mattwilcox.net",
+ "maturejp.com",
+ "maxing.jp",
+ "mayimayi.com",
+ "mcadforums.com",
+ "mcaf.ee",
+ "mcfog.com",
+ "mcreasite.com",
+ "md-t.org",
+ "me.me",
+ "meansys.com",
+ "media.org.hk",
+ "mediachinese.com",
+ "mediafire.com",
+ "mediafreakcity.com",
+ "medium.com",
+ "meetav.com",
+ "meetup.com",
+ "mefeedia.com",
+ "meforum.org",
+ "mefound.com",
+ "mega.nz",
+ "megaproxy.com",
+ "megarotic.com",
+ "megavideo.com",
+ "megurineluka.com",
+ "meirixiaochao.com",
+ "meltoday.com",
+ "memehk.com",
+ "memorybbs.com",
+ "memri.org",
+ "memrijttm.org",
+ "mercatox.com",
+ "mercyprophet.org",
+ "mergersandinquisitions.org",
+ "meridian-trust.org",
+ "meripet.biz",
+ "meripet.com",
+ "merit-times.com.tw",
+ "meshrep.com",
+ "mesotw.com",
+ "messenger.com",
+ "metacafe.com",
+ "metart.com",
+ "metarthunter.com",
+ "meteorshowersonline.com",
+ "metro.taipei",
+ "metrohk.com.hk",
+ "metrolife.ca",
+ "metroradio.com.hk",
+ "meyou.jp",
+ "meyul.com",
+ "mfxmedia.com",
+ "mgoon.com",
+ "mgstage.com",
+ "mh4u.org",
+ "mhradio.org",
+ "michaelanti.com",
+ "michaelmarketl.com",
+ "microvpn.com",
+ "middle-way.net",
+ "mihk.hk",
+ "mihr.com",
+ "mihua.org",
+ "mikesoltys.com",
+ "mikocon.com",
+ "milph.net",
+ "milsurps.com",
+ "mimiai.net",
+ "mimivip.com",
+ "mimivv.com",
+ "mindrolling.org",
+ "mingdemedia.org",
+ "minghui-a.org",
+ "minghui-b.org",
+ "minghui-school.org",
+ "minghui.or.kr",
+ "minghui.org",
+ "mingjinglishi.com",
+ "mingjingnews.com",
+ "mingjingtimes.com",
+ "mingpao.com",
+ "mingpaocanada.com",
+ "mingpaomonthly.com",
+ "mingpaonews.com",
+ "mingpaony.com",
+ "mingpaosf.com",
+ "mingpaotor.com",
+ "mingpaovan.com",
+ "mingshengbao.com",
+ "minhhue.net",
+ "miniforum.org",
+ "ministrybooks.org",
+ "minzhuhua.net",
+ "minzhuzhanxian.com",
+ "minzhuzhongguo.org",
+ "miroguide.com",
+ "mirrorbooks.com",
+ "mist.vip",
+ "mit.edu",
+ "mitao.com.tw",
+ "mitbbs.com",
+ "mitbbsau.com",
+ "mixero.com",
+ "mixpod.com",
+ "mixx.com",
+ "mizzmona.com",
+ "mjib.gov.tw",
+ "mk5000.com",
+ "mlcool.com",
+ "mlzs.work",
+ "mm-cg.com",
+ "mmaaxx.com",
+ "mmmca.com",
+ "mnewstv.com",
+ "mobatek.net",
+ "mobile01.com",
+ "mobileways.de",
+ "moby.to",
+ "mobypicture.com",
+ "moeaic.gov.tw",
+ "moeerolibrary.com",
+ "moegirl.org",
+ "mofa.gov.tw",
+ "mofaxiehui.com",
+ "mofos.com",
+ "mog.com",
+ "mohu.club",
+ "mohu.ml",
+ "mojim.com",
+ "mol.gov.tw",
+ "molihua.org",
+ "monar.ch",
+ "mondex.org",
+ "money-link.com.tw",
+ "moneyhome.biz",
+ "monitorchina.org",
+ "monitorware.com",
+ "monlamit.org",
+ "monster.com",
+ "moodyz.com",
+ "moonbbs.com",
+ "moonbingo.com",
+ "mooo.com",
+ "morbell.com",
+ "morningsun.org",
+ "moroneta.com",
+ "mos.ru",
+ "motherless.com",
+ "motiyun.com",
+ "motor4ik.ru",
+ "mousebreaker.com",
+ "movements.org",
+ "moviefap.com",
+ "moztw.org",
+ "mp3buscador.com",
+ "mp3ye.eu",
+ "mpettis.com",
+ "mpfinance.com",
+ "mpinews.com",
+ "mponline.hk",
+ "mqxd.org",
+ "mrbasic.com",
+ "mrbonus.com",
+ "mrface.com",
+ "mrslove.com",
+ "mrtweet.com",
+ "msa-it.org",
+ "msguancha.com",
+ "msha.gov",
+ "msn.com",
+ "msn.com.tw",
+ "mswe1.org",
+ "mthruf.com",
+ "mtw.tl",
+ "mubi.com",
+ "muchosucko.com",
+ "mullvad.net",
+ "multiply.com",
+ "multiproxy.org",
+ "multiupload.com",
+ "mummysgold.com",
+ "murmur.tw",
+ "musicade.net",
+ "muslimvideo.com",
+ "muzi.com",
+ "muzi.net",
+ "muzu.tv",
+ "mvdis.gov.tw",
+ "mvg.jp",
+ "mx981.com",
+ "my-formosa.com",
+ "my-private-network.co.uk",
+ "my-proxy.com",
+ "my03.com",
+ "my903.com",
+ "myactimes.com",
+ "myanniu.com",
+ "myaudiocast.com",
+ "myav.com.tw",
+ "mybbs.us",
+ "mybet.com",
+ "myca168.com",
+ "mycanadanow.com",
+ "mychat.to",
+ "mychinamyhome.com",
+ "mychinanet.com",
+ "mychinanews.com",
+ "mychinese.news",
+ "mycnnews.com",
+ "mycould.com",
+ "mydad.info",
+ "myddns.com",
+ "myeasytv.com",
+ "myeclipseide.com",
+ "myforum.com.hk",
+ "myfreecams.com",
+ "myfreepaysite.com",
+ "myfreshnet.com",
+ "myftp.info",
+ "myftp.name",
+ "myiphide.com",
+ "mykomica.org",
+ "mylftv.com",
+ "mymaji.com",
+ "mymediarom.com",
+ "mymoe.moe",
+ "mymom.info",
+ "mymusic.net.tw",
+ "mynetav.net",
+ "mynetav.org",
+ "mynumber.org",
+ "myparagliding.com",
+ "mypicture.info",
+ "mypop3.net",
+ "mypop3.org",
+ "mypopescu.com",
+ "myradio.hk",
+ "myreadingmanga.info",
+ "mysecondarydns.com",
+ "mysinablog.com",
+ "myspace.com",
+ "myspacecdn.com",
+ "mytalkbox.com",
+ "mytizi.com",
+ "mywww.biz",
+ "myz.info",
+ "naacoalition.org",
+ "nabble.com",
+ "naitik.net",
+ "nakido.com",
+ "nakuz.com",
+ "nalandabodhi.org",
+ "nalandawest.org",
+ "namgyal.org",
+ "namgyalmonastery.org",
+ "namsisi.com",
+ "nanyang.com",
+ "nanyangpost.com",
+ "nanzao.com",
+ "naol.ca",
+ "naol.cc",
+ "narod.ru",
+ "nasa.gov",
+ "nat.gov.tw",
+ "nat.moe",
+ "natado.com",
+ "national-lottery.co.uk",
+ "nationalawakening.org",
+ "nationalgeographic.com",
+ "nationsonline.org",
+ "nationwide.com",
+ "naughtyamerica.com",
+ "naver.jp",
+ "navy.mil",
+ "naweeklytimes.com",
+ "nbc.com",
+ "nbtvpn.com",
+ "nccwatch.org.tw",
+ "nch.com.tw",
+ "ncn.org",
+ "ncol.com",
+ "nde.de",
+ "ndr.de",
+ "ned.org",
+ "nekoslovakia.net",
+ "neo-miracle.com",
+ "nepusoku.com",
+ "nesnode.com",
+ "net-fits.pro",
+ "netbig.com",
+ "netbirds.com",
+ "netcolony.com",
+ "netfirms.com",
+ "netflix.com",
+ "netme.cc",
+ "netsneak.com",
+ "network54.com",
+ "networkedblogs.com",
+ "networktunnel.net",
+ "neverforget8964.org",
+ "new-3lunch.net",
+ "new-akiba.com",
+ "new96.ca",
+ "newcenturymc.com",
+ "newcenturynews.com",
+ "newchen.com",
+ "newgrounds.com",
+ "newipnow.com",
+ "newlandmagazine.com.au",
+ "newnews.ca",
+ "news100.com.tw",
+ "newsancai.com",
+ "newschinacomment.org",
+ "newscn.org",
+ "newsdetox.ca",
+ "newsdh.com",
+ "newsmagazine.asia",
+ "newspeak.cc",
+ "newstamago.com",
+ "newstapa.org",
+ "newstarnet.com",
+ "newtaiwan.com.tw",
+ "newtalk.tw",
+ "newyorktimes.com",
+ "nexon.com",
+ "next11.co.jp",
+ "nextmag.com.tw",
+ "nextmedia.com",
+ "nexton-net.jp",
+ "nexttv.com.tw",
+ "nf.id.au",
+ "nfjtyd.com",
+ "nflxext.com",
+ "nflximg.com",
+ "nflximg.net",
+ "nflxso.net",
+ "nflxvideo.net",
+ "ng.mil",
+ "nga.mil",
+ "ngensis.com",
+ "nhentai.net",
+ "nhi.gov.tw",
+ "nhk-ondemand.jp",
+ "nic.google",
+ "nic.gov",
+ "nicovideo.jp",
+ "nighost.org",
+ "nightlife141.com",
+ "nikkei.com",
+ "ninecommentaries.com",
+ "ning.com",
+ "ninjacloak.com",
+ "ninjaproxy.ninja",
+ "nintendium.com",
+ "ninth.biz",
+ "nitter.net",
+ "niu.moe",
+ "niusnews.com",
+ "njactb.org",
+ "njuice.com",
+ "nlfreevpn.com",
+ "no-ip.com",
+ "no-ip.org",
+ "nobel.se",
+ "nobelprize.org",
+ "nobodycanstop.us",
+ "nodesnoop.com",
+ "nofile.io",
+ "nokogiri.org",
+ "nokola.com",
+ "noodlevpn.com",
+ "norbulingka.org",
+ "nordstrom.com",
+ "nordstromimage.com",
+ "nordstromrack.com",
+ "nordvpn.com",
+ "nottinghampost.com",
+ "novelasia.com",
+ "now.com",
+ "now.im",
+ "nownews.com",
+ "nowtorrents.com",
+ "noypf.com",
+ "npa.go.jp",
+ "npa.gov.tw",
+ "npnt.me",
+ "nps.gov",
+ "npsboost.com",
+ "nradio.me",
+ "nrk.no",
+ "ns01.biz",
+ "ns01.info",
+ "ns01.us",
+ "ns02.biz",
+ "ns02.info",
+ "ns02.us",
+ "ns1.name",
+ "ns2.name",
+ "ns3.name",
+ "nsc.gov.tw",
+ "ntbk.gov.tw",
+ "ntbna.gov.tw",
+ "ntbt.gov.tw",
+ "ntd.tv",
+ "ntdtv.ca",
+ "ntdtv.co.kr",
+ "ntdtv.com",
+ "ntdtv.cz",
+ "ntdtv.org",
+ "ntdtv.ru",
+ "ntdtvla.com",
+ "ntrfun.com",
+ "ntsna.gov.tw",
+ "ntu.edu.tw",
+ "nu.nl",
+ "nubiles.net",
+ "nudezz.com",
+ "nuexpo.com",
+ "nukistream.com",
+ "nurgo-software.com",
+ "nusatrip.com",
+ "nutaku.net",
+ "nuuvem.com",
+ "nuvid.com",
+ "nuzcom.com",
+ "nvdst.com",
+ "nvquan.org",
+ "nvtongzhisheng.org",
+ "nwtca.org",
+ "nyaa.eu",
+ "nyaa.si",
+ "nydus.ca",
+ "nylon-angel.com",
+ "nylonstockingsonline.com",
+ "nyt.com",
+ "nytchina.com",
+ "nytcn.me",
+ "nytco.com",
+ "nyti.ms",
+ "nytimes.com",
+ "nytimg.com",
+ "nytlog.com",
+ "nytstyle.com",
+ "nzchinese.com",
+ "nzchinese.net.nz",
+ "oauth.net",
+ "observechina.net",
+ "obutu.com",
+ "ocaspro.com",
+ "occupytiananmen.com",
+ "oclp.hk",
+ "ocreampies.com",
+ "ocry.com",
+ "october-review.org",
+ "oculus.com",
+ "oculuscdn.com",
+ "oex.com",
+ "offbeatchina.com",
+ "officeoftibet.com",
+ "ofile.org",
+ "ogaoga.org",
+ "ogate.org",
+ "ohchr.org",
+ "ohmyrss.com",
+ "oikos.com.tw",
+ "oiktv.com",
+ "oizoblog.com",
+ "ok.ru",
+ "okayfreedom.com",
+ "okex.com",
+ "okk.tw",
+ "olabloga.pl",
+ "old-cat.net",
+ "olumpo.com",
+ "olympicwatch.org",
+ "omgili.com",
+ "omni7.jp",
+ "omnitalk.com",
+ "omnitalk.org",
+ "omy.sg",
+ "on.cc",
+ "on2.com",
+ "onapp.com",
+ "onedumb.com",
+ "onejav.com",
+ "onion.city",
+ "onlinecha.com",
+ "onlineyoutube.com",
+ "onlytweets.com",
+ "onmoon.com",
+ "onmoon.net",
+ "onmypc.biz",
+ "onmypc.info",
+ "onmypc.net",
+ "onmypc.org",
+ "onmypc.us",
+ "onthehunt.com",
+ "ontrac.com",
+ "oopsforum.com",
+ "open.com.hk",
+ "openallweb.com",
+ "opendemocracy.net",
+ "opendn.xyz",
+ "openervpn.in",
+ "openid.net",
+ "openleaks.org",
+ "opensource.google",
+ "openvpn.net",
+ "openvpn.org",
+ "openwebster.com",
+ "openwrt.org.cn",
+ "opera-mini.net",
+ "opera.com",
+ "opus-gaming.com",
+ "orchidbbs.com",
+ "organcare.org.tw",
+ "organharvestinvestigation.net",
+ "organiccrap.com",
+ "orgasm.com",
+ "orgfree.com",
+ "orient-doll.com",
+ "orientaldaily.com.my",
+ "orn.jp",
+ "orzdream.com",
+ "orzistic.org",
+ "osfoora.com",
+ "otcbtc.com",
+ "otnd.org",
+ "otto.de",
+ "otzo.com",
+ "ourdearamy.com",
+ "ourhobby.com",
+ "oursogo.com",
+ "oursteps.com.au",
+ "oursweb.net",
+ "ourtv.hk",
+ "over-blog.com",
+ "overplay.net",
+ "ovi.com",
+ "ow.ly",
+ "owind.com",
+ "owl.li",
+ "oxid.it",
+ "oyax.com",
+ "oyghan.com",
+ "ozchinese.com",
+ "ozvoice.org",
+ "ozxw.com",
+ "ozyoyo.com",
+ "pachosting.com",
+ "pacificpoker.com",
+ "packetix.net",
+ "pacopacomama.com",
+ "padmanet.com",
+ "page.tl",
+ "page2rss.com",
+ "pagodabox.com",
+ "palacemoon.com",
+ "paldengyal.com",
+ "paljorpublications.com",
+ "palmislife.com",
+ "paltalk.com",
+ "pandapow.co",
+ "pandapow.net",
+ "pandavpn-jp.com",
+ "pandora.com",
+ "pandora.tv",
+ "panluan.net",
+ "panoramio.com",
+ "pao-pao.net",
+ "paper.li",
+ "paperb.us",
+ "paradisehill.cc",
+ "paradisepoker.com",
+ "parkansky.com",
+ "parler.com",
+ "parsevideo.com",
+ "partycasino.com",
+ "partypoker.com",
+ "passion.com",
+ "passiontimes.hk",
+ "paste.ee",
+ "pastebin.com",
+ "pastie.org",
+ "pathtosharepoint.com",
+ "pbs.org",
+ "pbwiki.com",
+ "pbworks.com",
+ "pbxes.com",
+ "pbxes.org",
+ "pcanywhere.net",
+ "pcc.gov.tw",
+ "pcdvd.com.tw",
+ "pchome.com.tw",
+ "pcij.org",
+ "pcloud.com",
+ "pcstore.com.tw",
+ "pct.org.tw",
+ "pdetails.com",
+ "pdproxy.com",
+ "peace.ca",
+ "peacefire.org",
+ "peacehall.com",
+ "pearlher.org",
+ "peeasian.com",
+ "pekingduck.org",
+ "pemulihan.or.id",
+ "pen.io",
+ "penchinese.com",
+ "penchinese.net",
+ "pengyulong.com",
+ "penisbot.com",
+ "pentalogic.net",
+ "penthouse.com",
+ "pentoy.hk",
+ "peoplebookcafe.com",
+ "peoplenews.tw",
+ "peopo.org",
+ "percy.in",
+ "perfectgirls.net",
+ "perfectvpn.net",
+ "periscope.tv",
+ "persecutionblog.com",
+ "persiankitty.com",
+ "pfd.org.hk",
+ "phapluan.org",
+ "phayul.com",
+ "philborges.com",
+ "philly.com",
+ "phmsociety.org",
+ "phncdn.com",
+ "phonegap.com",
+ "photodharma.net",
+ "photofocus.com",
+ "phuquocservices.com",
+ "picacomic.com",
+ "picacomiccn.com",
+ "picasaweb.com",
+ "picidae.net",
+ "picturedip.com",
+ "picturesocial.com",
+ "pimg.tw",
+ "pin-cong.com",
+ "pin6.com",
+ "pincong.rocks",
+ "ping.fm",
+ "pinimg.com",
+ "pinkrod.com",
+ "pinoy-n.com",
+ "pinterest.at",
+ "pinterest.ca",
+ "pinterest.co.kr",
+ "pinterest.co.uk",
+ "pinterest.com",
+ "pinterest.de",
+ "pinterest.dk",
+ "pinterest.fr",
+ "pinterest.jp",
+ "pinterest.nl",
+ "pinterest.se",
+ "pipii.tv",
+ "piposay.com",
+ "piraattilahti.org",
+ "piring.com",
+ "pixelqi.com",
+ "pixiv.net",
+ "pixnet.in",
+ "pixnet.net",
+ "pk.com",
+ "pki.goog",
+ "placemix.com",
+ "playboy.com",
+ "playboyplus.com",
+ "player.fm",
+ "playno1.com",
+ "playpcesor.com",
+ "plays.com.tw",
+ "plixi.com",
+ "plm.org.hk",
+ "plunder.com",
+ "plurk.com",
+ "plus.codes",
+ "plus28.com",
+ "plusbb.com",
+ "pmatehunter.com",
+ "pmates.com",
+ "po2b.com",
+ "pobieramy.top",
+ "podictionary.com",
+ "pokerstars.com",
+ "pokerstars.net",
+ "pokerstrategy.com",
+ "politicalchina.org",
+ "politicalconsultation.org",
+ "politiscales.net",
+ "poloniex.com",
+ "polymer-project.org",
+ "polymerhk.com",
+ "popo.tw",
+ "popvote.hk",
+ "popyard.com",
+ "popyard.org",
+ "porn.com",
+ "porn2.com",
+ "porn5.com",
+ "pornbase.org",
+ "pornerbros.com",
+ "pornhd.com",
+ "pornhost.com",
+ "pornhub.com",
+ "pornhubdeutsch.net",
+ "pornmm.net",
+ "pornoxo.com",
+ "pornrapidshare.com",
+ "pornsharing.com",
+ "pornsocket.com",
+ "pornstarclub.com",
+ "porntube.com",
+ "porntubenews.com",
+ "porntvblog.com",
+ "pornvisit.com",
+ "port25.biz",
+ "portablevpn.nl",
+ "poskotanews.com",
+ "post01.com",
+ "post76.com",
+ "post852.com",
+ "postadult.com",
+ "postimg.org",
+ "potato.im",
+ "potvpn.com",
+ "power.com",
+ "powerapple.com",
+ "powercx.com",
+ "powerphoto.org",
+ "powerpointninja.com",
+ "pp.ru",
+ "prayforchina.net",
+ "premeforwindows7.com",
+ "premproxy.com",
+ "presentationzen.com",
+ "presidentlee.tw",
+ "prestige-av.com",
+ "pride.google",
+ "printfriendly.com",
+ "prism-break.org",
+ "prisoneralert.com",
+ "pritunl.com",
+ "privacybox.de",
+ "private.com",
+ "privateinternetaccess.com",
+ "privatepaste.com",
+ "privatetunnel.com",
+ "privatevpn.com",
+ "procopytips.com",
+ "prosiben.de",
+ "protonvpn.com",
+ "provideocoalition.com",
+ "provpnaccounts.com",
+ "proxfree.com",
+ "proxifier.com",
+ "proxlet.com",
+ "proxomitron.info",
+ "proxpn.com",
+ "proxyanonimo.es",
+ "proxydns.com",
+ "proxylist.org.uk",
+ "proxynetwork.org.uk",
+ "proxypy.net",
+ "proxyroad.com",
+ "proxytunnel.net",
+ "proyectoclubes.com",
+ "prozz.net",
+ "psblog.name",
+ "pscp.tv",
+ "pshvpn.com",
+ "psiphon.ca",
+ "psiphon3.com",
+ "psiphontoday.com",
+ "pts.org.tw",
+ "ptt.cc",
+ "pttvan.org",
+ "pubu.com.tw",
+ "puffinbrowser.com",
+ "puffstore.com",
+ "pullfolio.com",
+ "punyu.com",
+ "pure18.com",
+ "pureapk.com",
+ "pureconcepts.net",
+ "pureinsight.org",
+ "purepdf.com",
+ "purevpn.com",
+ "purplelotus.org",
+ "pursuestar.com",
+ "pushchinawall.com",
+ "pussyspace.com",
+ "putihome.org",
+ "putlocker.com",
+ "putty.org",
+ "puuko.com",
+ "pwned.com",
+ "python.com",
+ "python.com.tw",
+ "pythonhackers.com",
+ "pythonic.life",
+ "pytorch.org",
+ "qanote.com",
+ "qgirl.com.tw",
+ "qhigh.com",
+ "qi-gong.me",
+ "qiandao.today",
+ "qiangyou.org",
+ "qidian.ca",
+ "qienkuen.org",
+ "qiwen.lu",
+ "qixianglu.cn",
+ "qkshare.com",
+ "qmzdd.com",
+ "qoos.com",
+ "qooza.hk",
+ "qpoe.com",
+ "qq.co.za",
+ "qstatus.com",
+ "qtrac.eu",
+ "qtweeter.com",
+ "quannengshen.org",
+ "quantumbooter.net",
+ "questvisual.com",
+ "quitccp.net",
+ "quitccp.org",
+ "quora.com",
+ "quoracdn.net",
+ "quran.com",
+ "quranexplorer.com",
+ "qusi8.net",
+ "qvodzy.org",
+ "qx.net",
+ "qxbbs.org",
+ "qz.com",
+ "r18.com",
+ "ra.gg",
+ "radicalparty.org",
+ "radiko.jp",
+ "radio.garden",
+ "radioaustralia.net.au",
+ "radiohilight.net",
+ "radiotime.com",
+ "radiovaticana.org",
+ "radiovncr.com",
+ "rael.org",
+ "raggedbanner.com",
+ "raidcall.com.tw",
+ "raidtalk.com.tw",
+ "rainbowplan.org",
+ "raindrop.io",
+ "raizoji.or.jp",
+ "ramcity.com.au",
+ "rangwang.biz",
+ "rangzen.com",
+ "rangzen.net",
+ "rangzen.org",
+ "ranxiang.com",
+ "ranyunfei.com",
+ "rapbull.net",
+ "rapidgator.net",
+ "rapidmoviez.com",
+ "rapidvpn.com",
+ "rarbgprx.org",
+ "raremovie.cc",
+ "raremovie.net",
+ "rawgit.com",
+ "rawgithub.com",
+ "raxcdn.com",
+ "razyboard.com",
+ "rcinet.ca",
+ "rd.com",
+ "rdio.com",
+ "read01.com",
+ "read100.com",
+ "readingtimes.com.tw",
+ "readmoo.com",
+ "readydown.com",
+ "realcourage.org",
+ "realitykings.com",
+ "realraptalk.com",
+ "realsexpass.com",
+ "reason.com",
+ "rebatesrule.net",
+ "recaptcha.net",
+ "recordhistory.org",
+ "recovery.org.tw",
+ "recoveryversion.com.tw",
+ "recoveryversion.org",
+ "red-lang.org",
+ "redballoonsolidarity.org",
+ "redchinacn.net",
+ "redchinacn.org",
+ "redd.it",
+ "reddit.com",
+ "redditlist.com",
+ "redditmedia.com",
+ "redditstatic.com",
+ "redhotlabs.com",
+ "redtube.com",
+ "referer.us",
+ "reflectivecode.com",
+ "registry.google",
+ "relaxbbs.com",
+ "relay.com.tw",
+ "releaseinternational.org",
+ "religioustolerance.org",
+ "renminbao.com",
+ "renyurenquan.org",
+ "rerouted.org",
+ "resilio.com",
+ "resistchina.org",
+ "retweeteffect.com",
+ "retweetist.com",
+ "retweetrank.com",
+ "reuters.com",
+ "reutersmedia.net",
+ "revleft.com",
+ "revocationcheck.com",
+ "revver.com",
+ "rfa.org",
+ "rfachina.com",
+ "rfamobile.org",
+ "rfaweb.org",
+ "rferl.org",
+ "rfi.fr",
+ "rfi.my",
+ "rightbtc.com",
+ "rightster.com",
+ "rigpa.org",
+ "riku.me",
+ "rileyguide.com",
+ "riseup.net",
+ "ritouki.jp",
+ "ritter.vg",
+ "rixcloud.com",
+ "rixcloud.us",
+ "rlwlw.com",
+ "rmjdw.com",
+ "rmjdw132.info",
+ "roadshow.hk",
+ "roboforex.com",
+ "robustnessiskey.com",
+ "rocket-inc.net",
+ "rocketbbs.com",
+ "rocksdb.org",
+ "rojo.com",
+ "rolia.net",
+ "ronjoneswriter.com",
+ "roodo.com",
+ "rosechina.net",
+ "rotten.com",
+ "rsdlmonitor.com",
+ "rsf-chinese.org",
+ "rsf.org",
+ "rsgamen.org",
+ "rsshub.app",
+ "rssing.com",
+ "rssmeme.com",
+ "rtalabel.org",
+ "rthk.hk",
+ "rthk.org.hk",
+ "rti.org.tw",
+ "rtycminnesota.org",
+ "ruanyifeng.com",
+ "rukor.org",
+ "runbtx.com",
+ "rushbee.com",
+ "ruten.com.tw",
+ "rutube.ru",
+ "ruyiseek.com",
+ "rxhj.net",
+ "s-cute.com",
+ "s-dragon.org",
+ "s1heng.com",
+ "s1s1s1.com",
+ "s4miniarchive.com",
+ "s8forum.com",
+ "sa.com",
+ "saboom.com",
+ "sacks.com",
+ "sacom.hk",
+ "sadistic-v.com",
+ "sadpanda.us",
+ "safervpn.com",
+ "safety.google",
+ "saintyculture.com",
+ "saiq.me",
+ "sakuralive.com",
+ "sakya.org",
+ "salvation.org.hk",
+ "samair.ru",
+ "sambhota.org",
+ "sandscotaicentral.com",
+ "sanmin.com.tw",
+ "sans.edu",
+ "sapikachu.net",
+ "saveliuxiaobo.com",
+ "savemedia.com",
+ "savethedate.foo",
+ "savethesounds.info",
+ "savetibet.de",
+ "savetibet.fr",
+ "savetibet.nl",
+ "savetibet.org",
+ "savetibet.ru",
+ "savetibetstore.org",
+ "savevid.com",
+ "say2.info",
+ "sbme.me",
+ "sbs.com.au",
+ "scasino.com",
+ "schema.org",
+ "sciencemag.org",
+ "sciencenets.com",
+ "scieron.com",
+ "scmp.com",
+ "scmpchinese.com",
+ "scramble.io",
+ "scribd.com",
+ "scriptspot.com",
+ "search.com",
+ "search.xxx",
+ "searchtruth.com",
+ "searx.me",
+ "seatguru.com",
+ "secretchina.com",
+ "secretgarden.no",
+ "secretsline.biz",
+ "securetunnel.com",
+ "securityinabox.org",
+ "securitykiss.com",
+ "seed4.me",
+ "seehua.com",
+ "seesmic.com",
+ "seevpn.com",
+ "seezone.net",
+ "sejie.com",
+ "sellclassics.com",
+ "sendsmtp.com",
+ "sendspace.com",
+ "seraph.me",
+ "servehttp.com",
+ "serveuser.com",
+ "serveusers.com",
+ "sesawe.net",
+ "sesawe.org",
+ "sethwklein.net",
+ "setn.com",
+ "settv.com.tw",
+ "setty.com.tw",
+ "sevenload.com",
+ "sex-11.com",
+ "sex.com",
+ "sex3.com",
+ "sex8.cc",
+ "sexandsubmission.com",
+ "sexbot.com",
+ "sexhu.com",
+ "sexhuang.com",
+ "sexidude.com",
+ "sexinsex.net",
+ "sextvx.com",
+ "sexxxy.biz",
+ "sf.net",
+ "sfileydy.com",
+ "sfshibao.com",
+ "sftindia.org",
+ "sftuk.org",
+ "shadeyouvpn.com",
+ "shadow.ma",
+ "shadowsky.xyz",
+ "shadowsocks-r.com",
+ "shadowsocks.asia",
+ "shadowsocks.be",
+ "shadowsocks.com",
+ "shadowsocks.com.hk",
+ "shadowsocks.org",
+ "shadowsocks9.com",
+ "shafaqna.com",
+ "shambalapost.com",
+ "shambhalasun.com",
+ "shangfang.org",
+ "shapeservices.com",
+ "sharebee.com",
+ "sharecool.org",
+ "sharpdaily.com.hk",
+ "sharpdaily.hk",
+ "sharpdaily.tw",
+ "shat-tibet.com",
+ "shattered.io",
+ "sheikyermami.com",
+ "shellfire.de",
+ "shemalez.com",
+ "shenshou.org",
+ "shenyun.com",
+ "shenyunperformingarts.org",
+ "shenzhoufilm.com",
+ "sherabgyaltsen.com",
+ "shiatv.net",
+ "shicheng.org",
+ "shiksha.com",
+ "shinychan.com",
+ "shipcamouflage.com",
+ "shireyishunjian.com",
+ "shitaotv.org",
+ "shixiao.org",
+ "shizhao.org",
+ "shkspr.mobi",
+ "shodanhq.com",
+ "shooshtime.com",
+ "shop2000.com.tw",
+ "shopee.tw",
+ "shopping.com",
+ "showhaotu.com",
+ "showtime.jp",
+ "shutterstock.com",
+ "shvoong.com",
+ "shwchurch.org",
+ "shwchurch3.com",
+ "siddharthasintent.org",
+ "sidelinesnews.com",
+ "sidelinessportseatery.com",
+ "sierrafriendsoftibet.org",
+ "sijihuisuo.club",
+ "sijihuisuo.com",
+ "silkbook.com",
+ "simbolostwitter.com",
+ "simplecd.org",
+ "simpleproductivityblog.com",
+ "sina.com",
+ "sina.com.hk",
+ "sina.com.tw",
+ "sinchew.com.my",
+ "singaporepools.com.sg",
+ "singfortibet.com",
+ "singpao.com.hk",
+ "singtao.ca",
+ "singtao.com",
+ "singtaousa.com",
+ "sino-monthly.com",
+ "sinoants.com",
+ "sinocast.com",
+ "sinocism.com",
+ "sinomontreal.ca",
+ "sinonet.ca",
+ "sinopitt.info",
+ "sinoquebec.com",
+ "sipml5.org",
+ "sis.xxx",
+ "sis001.com",
+ "sis001.us",
+ "site2unblock.com",
+ "site90.net",
+ "sitebro.tw",
+ "sitekreator.com",
+ "sitemaps.org",
+ "six-degrees.io",
+ "sixth.biz",
+ "sjrt.org",
+ "sjum.cn",
+ "sketchappsources.com",
+ "skimtube.com",
+ "skybet.com",
+ "skyking.com.tw",
+ "skykiwi.com",
+ "skynet.be",
+ "skype.com",
+ "skyvegas.com",
+ "skyxvpn.com",
+ "slacker.com",
+ "slandr.net",
+ "slaytizle.com",
+ "sleazydream.com",
+ "slheng.com",
+ "slickvpn.com",
+ "slideshare.net",
+ "slime.com.tw",
+ "slinkset.com",
+ "slutload.com",
+ "slutmoonbeam.com",
+ "slyip.com",
+ "slyip.net",
+ "sm-miracle.com",
+ "smartdnsproxy.com",
+ "smarthide.com",
+ "smartmailcloud.com",
+ "smchbooks.com",
+ "smh.com.au",
+ "smhric.org",
+ "smith.edu",
+ "smyxy.org",
+ "snapchat.com",
+ "snaptu.com",
+ "sndcdn.com",
+ "sneakme.net",
+ "snowlionpub.com",
+ "so-net.net.tw",
+ "sobees.com",
+ "soc.mil",
+ "socialwhale.com",
+ "socks-proxy.net",
+ "sockscap64.com",
+ "sockslist.net",
+ "socrec.org",
+ "sod.co.jp",
+ "softether-download.com",
+ "softether.co.jp",
+ "softether.org",
+ "softfamous.com",
+ "softlayer.net",
+ "softsmirror.cf",
+ "softwarebychuck.com",
+ "sogclub.com",
+ "sogoo.org",
+ "sogrady.me",
+ "soh.tw",
+ "sohcradio.com",
+ "sohfrance.org",
+ "soifind.com",
+ "sokamonline.com",
+ "sokmil.com",
+ "solidaritetibet.org",
+ "solidfiles.com",
+ "somee.com",
+ "songjianjun.com",
+ "sonicbbs.cc",
+ "sonidodelaesperanza.org",
+ "sopcast.com",
+ "sopcast.org",
+ "sorazone.net",
+ "sorting-algorithms.com",
+ "sos.org",
+ "sosreader.com",
+ "sostibet.org",
+ "sou-tong.org",
+ "soubory.com",
+ "soul-plus.net",
+ "soulcaliburhentai.net",
+ "soumo.info",
+ "soundcloud.com",
+ "soundofhope.kr",
+ "soundofhope.org",
+ "soup.io",
+ "soupofmedia.com",
+ "sourceforge.net",
+ "sourcewadio.com",
+ "southnews.com.tw",
+ "sowers.org.hk",
+ "sowiki.net",
+ "soylent.com",
+ "soylentnews.org",
+ "spankbang.com",
+ "spankingtube.com",
+ "spankwire.com",
+ "spb.com",
+ "speakerdeck.com",
+ "speedify.com",
+ "spem.at",
+ "spencertipping.com",
+ "spendee.com",
+ "spicevpn.com",
+ "spideroak.com",
+ "spike.com",
+ "spotflux.com",
+ "spotify.com",
+ "spreadshirt.es",
+ "spring4u.info",
+ "springboardplatform.com",
+ "sprite.org",
+ "sproutcore.com",
+ "sproxy.info",
+ "squirly.info",
+ "srocket.us",
+ "ss-link.com",
+ "ssglobal.co",
+ "ssglobal.me",
+ "ssh91.com",
+ "ssl443.org",
+ "sspanel.net",
+ "sspro.ml",
+ "ssr.tools",
+ "ssrshare.com",
+ "sss.camp",
+ "sstmlt.moe",
+ "sstmlt.net",
+ "stackoverflow.com",
+ "stage64.hk",
+ "standupfortibet.org",
+ "standwithhk.org",
+ "stanford.edu",
+ "starfishfx.com",
+ "starp2p.com",
+ "startpage.com",
+ "startuplivingchina.com",
+ "stat.gov.tw",
+ "state.gov",
+ "static-economist.com",
+ "staticflickr.com",
+ "statueofdemocracy.org",
+ "stc.com.sa",
+ "steamcommunity.com",
+ "steampowered.com",
+ "steel-storm.com",
+ "steemit.com",
+ "steganos.com",
+ "steganos.net",
+ "stepchina.com",
+ "stephaniered.com",
+ "stgloballink.com",
+ "stheadline.com",
+ "sthoo.com",
+ "stickam.com",
+ "stickeraction.com",
+ "stileproject.com",
+ "sto.cc",
+ "stoporganharvesting.org",
+ "stoptibetcrisis.net",
+ "storagenewsletter.com",
+ "stories.google",
+ "storify.com",
+ "storm.mg",
+ "stormmediagroup.com",
+ "stoweboyd.com",
+ "stranabg.com",
+ "straplessdildo.com",
+ "streamate.com",
+ "streamingthe.net",
+ "streema.com",
+ "streetvoice.com",
+ "strikingly.com",
+ "strongvpn.com",
+ "strongwindpress.com",
+ "student.tw",
+ "studentsforafreetibet.org",
+ "stumbleupon.com",
+ "stupidvideos.com",
+ "successfn.com",
+ "sueddeutsche.de",
+ "sugarsync.com",
+ "sugobbs.com",
+ "sugumiru18.com",
+ "suissl.com",
+ "sulian.me",
+ "summify.com",
+ "sumrando.com",
+ "sun1911.com",
+ "sunmedia.ca",
+ "sunporno.com",
+ "sunskyforum.com",
+ "sunta.com.tw",
+ "sunvpn.net",
+ "suoluo.org",
+ "supchina.com",
+ "superfreevpn.com",
+ "superokayama.com",
+ "superpages.com",
+ "supervpn.net",
+ "superzooi.com",
+ "suppig.net",
+ "suprememastertv.com",
+ "surfeasy.com",
+ "surfeasy.com.au",
+ "suroot.com",
+ "surrenderat20.net",
+ "sustainability.google",
+ "suyangg.com",
+ "svsfx.com",
+ "swagbucks.com",
+ "swissinfo.ch",
+ "swissvpn.net",
+ "switch1.jp",
+ "switchvpn.net",
+ "sydneytoday.com",
+ "sylfoundation.org",
+ "syncback.com",
+ "synergyse.com",
+ "sysresccd.org",
+ "sytes.net",
+ "syx86.cn",
+ "syx86.com",
+ "szbbs.net",
+ "szetowah.org.hk",
+ "t-g.com",
+ "t.co",
+ "t.me",
+ "t35.com",
+ "t66y.com",
+ "taa-usa.org",
+ "taaze.tw",
+ "tablesgenerator.com",
+ "tabtter.jp",
+ "tacem.org",
+ "taconet.com.tw",
+ "taedp.org.tw",
+ "tafm.org",
+ "tagwa.org.au",
+ "tagwalk.com",
+ "tahr.org.tw",
+ "taipei.gov.tw",
+ "taipeisociety.org",
+ "taiwan-sex.com",
+ "taiwanbible.com",
+ "taiwancon.com",
+ "taiwandaily.net",
+ "taiwandc.org",
+ "taiwanjobs.gov.tw",
+ "taiwanjustice.com",
+ "taiwanjustice.net",
+ "taiwankiss.com",
+ "taiwannation.com",
+ "taiwannation.com.tw",
+ "taiwanncf.org.tw",
+ "taiwannews.com.tw",
+ "taiwanonline.cc",
+ "taiwantp.net",
+ "taiwantt.org.tw",
+ "taiwanus.net",
+ "taiwanyes.com",
+ "talk853.com",
+ "talkboxapp.com",
+ "talkcc.com",
+ "talkonly.net",
+ "tamiaode.tk",
+ "tampabay.com",
+ "tanc.org",
+ "tangben.com",
+ "tangren.us",
+ "taoism.net",
+ "taolun.info",
+ "tapanwap.com",
+ "tapatalk.com",
+ "taragana.com",
+ "target.com",
+ "tascn.com.au",
+ "taup.net",
+ "taup.org.tw",
+ "taweet.com",
+ "tbcollege.org",
+ "tbi.org.hk",
+ "tbicn.org",
+ "tbjyt.org",
+ "tbpic.info",
+ "tbrc.org",
+ "tbs-rainbow.org",
+ "tbsec.org",
+ "tbsmalaysia.org",
+ "tbsn.org",
+ "tbsseattle.org",
+ "tbssqh.org",
+ "tbswd.org",
+ "tbtemple.org.uk",
+ "tbthouston.org",
+ "tccwonline.org",
+ "tcewf.org",
+ "tchrd.org",
+ "tcnynj.org",
+ "tcpspeed.co",
+ "tcpspeed.com",
+ "tcsofbc.org",
+ "tcsovi.org",
+ "tdesktop.com",
+ "tdm.com.mo",
+ "teachparentstech.org",
+ "teamamericany.com",
+ "techviz.net",
+ "teck.in",
+ "teco-hk.org",
+ "teco-mo.org",
+ "teddysun.com",
+ "teeniefuck.net",
+ "teensinasia.com",
+ "telecomspace.com",
+ "telegra.ph",
+ "telegram.dog",
+ "telegram.me",
+ "telegram.org",
+ "telegramdownload.com",
+ "telegraph.co.uk",
+ "telesco.pe",
+ "tellme.pw",
+ "tenacy.com",
+ "tensorflow.org",
+ "tenzinpalmo.com",
+ "tew.org",
+ "textnow.me",
+ "tfhub.dev",
+ "thaicn.com",
+ "thb.gov.tw",
+ "theatrum-belli.com",
+ "thebcomplex.com",
+ "theblemish.com",
+ "thebobs.com",
+ "thebodyshop-usa.com",
+ "thechinabeat.org",
+ "thechinastory.org",
+ "thedalailamamovie.com",
+ "thedw.us",
+ "thefacebook.com",
+ "thefrontier.hk",
+ "thegay.com",
+ "thegioitinhoc.vn",
+ "thegly.com",
+ "theguardian.com",
+ "thehots.info",
+ "thehousenews.com",
+ "thehun.net",
+ "theinitium.com",
+ "thenewslens.com",
+ "thepiratebay.org",
+ "theporndude.com",
+ "theportalwiki.com",
+ "thereallove.kr",
+ "therock.net.nz",
+ "thespeeder.com",
+ "thestandnews.com",
+ "thetibetcenter.org",
+ "thetibetconnection.org",
+ "thetibetmuseum.org",
+ "thetibetpost.com",
+ "thetinhat.com",
+ "thetrotskymovie.com",
+ "thevivekspot.com",
+ "thewgo.org",
+ "theync.com",
+ "thinkgeek.com",
+ "thinkingtaiwan.com",
+ "thinkwithgoogle.com",
+ "thisav.com",
+ "thlib.org",
+ "thomasbernhard.org",
+ "thongdreams.com",
+ "threatchaos.com",
+ "throughnightsfire.com",
+ "thumbzilla.com",
+ "thywords.com",
+ "thywords.com.tw",
+ "tiananmenduizhi.com",
+ "tiananmenmother.org",
+ "tiananmenuniv.com",
+ "tiananmenuniv.net",
+ "tiandixing.org",
+ "tianhuayuan.com",
+ "tianlawoffice.com",
+ "tianti.io",
+ "tiantibooks.org",
+ "tianyantong.org.cn",
+ "tianzhu.org",
+ "tibet-envoy.eu",
+ "tibet-foundation.org",
+ "tibet-house-trust.co.uk",
+ "tibet-initiative.de",
+ "tibet-munich.de",
+ "tibet.a.se",
+ "tibet.at",
+ "tibet.ca",
+ "tibet.com",
+ "tibet.fr",
+ "tibet.net",
+ "tibet.nu",
+ "tibet.org",
+ "tibet.org.tw",
+ "tibet.sk",
+ "tibet.to",
+ "tibet3rdpole.org",
+ "tibetaction.net",
+ "tibetaid.org",
+ "tibetalk.com",
+ "tibetan-alliance.org",
+ "tibetan.fr",
+ "tibetanaidproject.org",
+ "tibetanarts.org",
+ "tibetanbuddhistinstitute.org",
+ "tibetancommunity.org",
+ "tibetancommunityuk.net",
+ "tibetanculture.org",
+ "tibetanfeministcollective.org",
+ "tibetanjournal.com",
+ "tibetanlanguage.org",
+ "tibetanliberation.org",
+ "tibetanpaintings.com",
+ "tibetanphotoproject.com",
+ "tibetanpoliticalreview.org",
+ "tibetanreview.net",
+ "tibetansports.org",
+ "tibetanwomen.org",
+ "tibetanyouth.org",
+ "tibetanyouthcongress.org",
+ "tibetcharity.dk",
+ "tibetcharity.in",
+ "tibetchild.org",
+ "tibetcity.com",
+ "tibetcollection.com",
+ "tibetcorps.org",
+ "tibetexpress.net",
+ "tibetfocus.com",
+ "tibetfund.org",
+ "tibetgermany.com",
+ "tibetgermany.de",
+ "tibethaus.com",
+ "tibetheritagefund.org",
+ "tibethouse.jp",
+ "tibethouse.org",
+ "tibethouse.us",
+ "tibetinfonet.net",
+ "tibetjustice.org",
+ "tibetkomite.dk",
+ "tibetmuseum.org",
+ "tibetnetwork.org",
+ "tibetoffice.ch",
+ "tibetoffice.com.au",
+ "tibetoffice.eu",
+ "tibetoffice.org",
+ "tibetonline.com",
+ "tibetonline.tv",
+ "tibetoralhistory.org",
+ "tibetpolicy.eu",
+ "tibetrelieffund.co.uk",
+ "tibetsites.com",
+ "tibetsociety.com",
+ "tibetsun.com",
+ "tibetsupportgroup.org",
+ "tibetswiss.ch",
+ "tibettelegraph.com",
+ "tibettimes.net",
+ "tibetwrites.org",
+ "ticket.com.tw",
+ "tigervpn.com",
+ "tiltbrush.com",
+ "timdir.com",
+ "time.com",
+ "timsah.com",
+ "tinc-vpn.org",
+ "tiney.com",
+ "tineye.com",
+ "tintuc101.com",
+ "tiny.cc",
+ "tinychat.com",
+ "tinypaste.com",
+ "tipo.gov.tw",
+ "tistory.com",
+ "tkcs-collins.com",
+ "tl.gd",
+ "tma.co.jp",
+ "tmagazine.com",
+ "tmdfish.com",
+ "tmi.me",
+ "tmpp.org",
+ "tnaflix.com",
+ "tngrnow.com",
+ "tngrnow.net",
+ "tnp.org",
+ "to-porno.com",
+ "togetter.com",
+ "toh.info",
+ "tokyo-247.com",
+ "tokyo-hot.com",
+ "tokyo-porn-tube.com",
+ "tokyocn.com",
+ "tomonews.net",
+ "tongil.or.kr",
+ "tono-oka.jp",
+ "tonyyan.net",
+ "toodoc.com",
+ "toonel.net",
+ "top.tv",
+ "top10vpn.com",
+ "top81.ws",
+ "topbtc.com",
+ "topnews.in",
+ "toppornsites.com",
+ "topshareware.com",
+ "topsy.com",
+ "toptip.ca",
+ "tora.to",
+ "torcn.com",
+ "torguard.net",
+ "torproject.org",
+ "torrentprivacy.com",
+ "torrentproject.se",
+ "torrenty.org",
+ "torrentz.eu",
+ "torvpn.com",
+ "totalvpn.com",
+ "toutiaoabc.com",
+ "towngain.com",
+ "toypark.in",
+ "toythieves.com",
+ "toytractorshow.com",
+ "tparents.org",
+ "tpi.org.tw",
+ "tracfone.com",
+ "traffichaus.com",
+ "transparency.org",
+ "treemall.com.tw",
+ "trendsmap.com",
+ "trialofccp.org",
+ "trickip.net",
+ "trickip.org",
+ "trimondi.de",
+ "trouw.nl",
+ "trt.net.tr",
+ "trtc.com.tw",
+ "truebuddha-md.org",
+ "trulyergonomic.com",
+ "truthontour.org",
+ "truveo.com",
+ "tryheart.jp",
+ "tsctv.net",
+ "tsemtulku.com",
+ "tsquare.tv",
+ "tsu.org.tw",
+ "tsunagarumon.com",
+ "tt1069.com",
+ "tttan.com",
+ "ttv.com.tw",
+ "ttvnw.net",
+ "tu8964.com",
+ "tubaholic.com",
+ "tube.com",
+ "tube8.com",
+ "tube911.com",
+ "tubecup.com",
+ "tubegals.com",
+ "tubeislam.com",
+ "tubepornclassic.com",
+ "tubestack.com",
+ "tubewolf.com",
+ "tuibeitu.net",
+ "tuidang.net",
+ "tuidang.org",
+ "tuidang.se",
+ "tuitui.info",
+ "tuitwit.com",
+ "tumblr.com",
+ "tumutanzi.com",
+ "tumview.com",
+ "tunein.com",
+ "tunnelbear.com",
+ "tunnelr.com",
+ "tuo8.blue",
+ "tuo8.cc",
+ "tuo8.club",
+ "tuo8.fit",
+ "tuo8.hk",
+ "tuo8.in",
+ "tuo8.ninja",
+ "tuo8.org",
+ "tuo8.pw",
+ "tuo8.red",
+ "tuo8.space",
+ "turansam.org",
+ "turbobit.net",
+ "turbohide.com",
+ "turbotwitter.com",
+ "turkistantimes.com",
+ "turntable.fm",
+ "tushycash.com",
+ "tutanota.com",
+ "tuvpn.com",
+ "tuzaijidi.com",
+ "tv.com",
+ "tvants.com",
+ "tvb.com",
+ "tvboxnow.com",
+ "tvbs.com.tw",
+ "tvider.com",
+ "tvmost.com.hk",
+ "tvplayvideos.com",
+ "tvunetworks.com",
+ "tw-blog.com",
+ "tw-npo.org",
+ "tw01.org",
+ "twaitter.com",
+ "twapperkeeper.com",
+ "twaud.io",
+ "twavi.com",
+ "twbbs.net.tw",
+ "twbbs.org",
+ "twbbs.tw",
+ "twblogger.com",
+ "tweepguide.com",
+ "tweeplike.me",
+ "tweepmag.com",
+ "tweepml.org",
+ "tweetbackup.com",
+ "tweetboard.com",
+ "tweetboner.biz",
+ "tweetcs.com",
+ "tweetdeck.com",
+ "tweetedtimes.com",
+ "tweetmylast.fm",
+ "tweetphoto.com",
+ "tweetrans.com",
+ "tweetree.com",
+ "tweettunnel.com",
+ "tweetwally.com",
+ "tweetymail.com",
+ "tweez.net",
+ "twelve.today",
+ "twerkingbutt.com",
+ "twftp.org",
+ "twgreatdaily.com",
+ "twibase.com",
+ "twibble.de",
+ "twibbon.com",
+ "twibs.com",
+ "twicountry.org",
+ "twicsy.com",
+ "twiends.com",
+ "twifan.com",
+ "twiffo.com",
+ "twiggit.org",
+ "twilightsex.com",
+ "twilio.com",
+ "twilog.org",
+ "twimbow.com",
+ "twimg.com",
+ "twindexx.com",
+ "twip.me",
+ "twipple.jp",
+ "twishort.com",
+ "twistar.cc",
+ "twister.net.co",
+ "twisterio.com",
+ "twisternow.com",
+ "twistory.net",
+ "twit2d.com",
+ "twitbrowser.net",
+ "twitcause.com",
+ "twitch.tv",
+ "twitchcdn.net",
+ "twitgether.com",
+ "twitgoo.com",
+ "twitiq.com",
+ "twitlonger.com",
+ "twitmania.com",
+ "twitoaster.com",
+ "twitonmsn.com",
+ "twitpic.com",
+ "twitstat.com",
+ "twittbot.net",
+ "twitter.com",
+ "twitter.jp",
+ "twitter4j.org",
+ "twittercounter.com",
+ "twitterfeed.com",
+ "twittergadget.com",
+ "twitterkr.com",
+ "twittermail.com",
+ "twitterrific.com",
+ "twittertim.es",
+ "twitthat.com",
+ "twitturk.com",
+ "twitturly.com",
+ "twitvid.com",
+ "twitzap.com",
+ "twiyia.com",
+ "twnorth.org.tw",
+ "twskype.com",
+ "twstar.net",
+ "twt.tl",
+ "twtkr.com",
+ "twtrland.com",
+ "twttr.com",
+ "twurl.nl",
+ "twyac.org",
+ "txxx.com",
+ "tycool.com",
+ "typepad.com",
+ "u15.info",
+ "u9un.com",
+ "ub0.cc",
+ "ubddns.org",
+ "uberproxy.net",
+ "uc-japan.org",
+ "ucam.org",
+ "ucanews.com",
+ "ucdc1998.org",
+ "uchicago.edu",
+ "uderzo.it",
+ "udn.com",
+ "udn.com.tw",
+ "udnbkk.com",
+ "uforadio.com.tw",
+ "ufreevpn.com",
+ "ugo.com",
+ "uhdwallpapers.org",
+ "uhrp.org",
+ "uighur.nl",
+ "uighurbiz.net",
+ "uk.to",
+ "ukcdp.co.uk",
+ "ukliferadio.co.uk",
+ "uku.im",
+ "ulike.net",
+ "ulop.net",
+ "ultravpn.fr",
+ "ultraxs.com",
+ "umich.edu",
+ "unblock-us.com",
+ "unblockdmm.com",
+ "unblocker.yt",
+ "unblocksit.es",
+ "uncyclomedia.org",
+ "uncyclopedia.hk",
+ "uncyclopedia.tw",
+ "underwoodammo.com",
+ "unholyknight.com",
+ "uni.cc",
+ "unicode.org",
+ "unification.net",
+ "unification.org.tw",
+ "unirule.cloud",
+ "unitedsocialpress.com",
+ "unix100.com",
+ "unknownspace.org",
+ "unodedos.com",
+ "unpo.org",
+ "unseen.is",
+ "untraceable.us",
+ "uocn.org",
+ "updatestar.com",
+ "upholdjustice.org",
+ "upload4u.info",
+ "uploaded.net",
+ "uploaded.to",
+ "uploadstation.com",
+ "upmedia.mg",
+ "upornia.com",
+ "uproxy.org",
+ "uptodown.com",
+ "upwill.org",
+ "ur7s.com",
+ "uraban.me",
+ "urbansurvival.com",
+ "urchin.com",
+ "url.com.tw",
+ "url.tw",
+ "urlborg.com",
+ "urlparser.com",
+ "us.to",
+ "usacn.com",
+ "usaip.eu",
+ "usc.edu",
+ "usembassy.gov",
+ "usfk.mil",
+ "usma.edu",
+ "usmc.mil",
+ "usocctn.com",
+ "uspto.gov",
+ "ustream.tv",
+ "usunitednews.com",
+ "usus.cc",
+ "utopianpal.com",
+ "uu-gg.com",
+ "uukanshu.com",
+ "uvwxyz.xyz",
+ "uwants.com",
+ "uwants.net",
+ "uyghur-j.org",
+ "uyghur.co.uk",
+ "uyghuramerican.org",
+ "uyghurcanadiansociety.org",
+ "uyghurcongress.org",
+ "uyghurensemble.co.uk",
+ "uyghurpen.org",
+ "uyghurpress.com",
+ "uyghurstudies.org",
+ "uygur.org",
+ "uymaarip.com",
+ "v2ex.com",
+ "v2ray.com",
+ "van001.com",
+ "van698.com",
+ "vanemu.cn",
+ "vanilla-jp.com",
+ "vanpeople.com",
+ "vansky.com",
+ "vaticannews.va",
+ "vatn.org",
+ "vcf-online.org",
+ "vcfbuilder.org",
+ "vegasred.com",
+ "velkaepocha.sk",
+ "venbbs.com",
+ "venchina.com",
+ "venetianmacao.com",
+ "ventureswell.com",
+ "veoh.com",
+ "verizon.net",
+ "vermonttibet.org",
+ "versavpn.com",
+ "verybs.com",
+ "vevo.com",
+ "vft.com.tw",
+ "viber.com",
+ "vica.info",
+ "victimsofcommunism.org",
+ "vid.me",
+ "vidble.com",
+ "videobam.com",
+ "videodetective.com",
+ "videomega.tv",
+ "videomo.com",
+ "videopediaworld.com",
+ "videopress.com",
+ "vidinfo.org",
+ "vietdaikynguyen.com",
+ "vijayatemple.org",
+ "vimeo.com",
+ "vimperator.org",
+ "vincnd.com",
+ "vine.co",
+ "vinniev.com",
+ "vip-enterprise.com",
+ "virginia.edu",
+ "virtualrealporn.com",
+ "visibletweets.com",
+ "visiontimes.com",
+ "vital247.org",
+ "viu.com",
+ "viu.tv",
+ "vivahentai4u.net",
+ "vivatube.com",
+ "vivthomas.com",
+ "vizvaz.com",
+ "vjav.com",
+ "vjmedia.com.hk",
+ "vllcs.org",
+ "vmixcore.com",
+ "vmpsoft.com",
+ "vnet.link",
+ "voa.mobi",
+ "voacantonese.com",
+ "voachinese.com",
+ "voachineseblog.com",
+ "voagd.com",
+ "voanews.com",
+ "voatibetan.com",
+ "voatibetanenglish.com",
+ "vocativ.com",
+ "vocn.tv",
+ "vot.org",
+ "vovo2000.com",
+ "voxer.com",
+ "voy.com",
+ "vpn.ac",
+ "vpn4all.com",
+ "vpnaccount.org",
+ "vpnaccounts.com",
+ "vpnbook.com",
+ "vpncomparison.org",
+ "vpncoupons.com",
+ "vpncup.com",
+ "vpndada.com",
+ "vpnfan.com",
+ "vpnfire.com",
+ "vpnfires.biz",
+ "vpnforgame.net",
+ "vpngate.jp",
+ "vpngate.net",
+ "vpngratis.net",
+ "vpnhq.com",
+ "vpninja.net",
+ "vpnintouch.com",
+ "vpnintouch.net",
+ "vpnjack.com",
+ "vpnmaster.com",
+ "vpnmentor.com",
+ "vpnpick.com",
+ "vpnpop.com",
+ "vpnpronet.com",
+ "vpnreactor.com",
+ "vpnreviewz.com",
+ "vpnsecure.me",
+ "vpnshazam.com",
+ "vpnshieldapp.com",
+ "vpnsp.com",
+ "vpntraffic.com",
+ "vpntunnel.com",
+ "vpnuk.info",
+ "vpnunlimitedapp.com",
+ "vpnvip.com",
+ "vpnworldwide.com",
+ "vporn.com",
+ "vpser.net",
+ "vraiesagesse.net",
+ "vrmtr.com",
+ "vrsmash.com",
+ "vs.com",
+ "vtunnel.com",
+ "vuku.cc",
+ "vultryhw.com",
+ "vzw.com",
+ "w3.org",
+ "w3schools.com",
+ "waffle1999.com",
+ "wahas.com",
+ "waigaobu.com",
+ "waikeung.org",
+ "wailaike.net",
+ "waiwaier.com",
+ "wallmama.com",
+ "wallornot.org",
+ "wallpapercasa.com",
+ "wallproxy.com",
+ "waltermartin.com",
+ "waltermartin.org",
+ "wan-press.org",
+ "wanderinghorse.net",
+ "wangafu.net",
+ "wangjinbo.org",
+ "wanglixiong.com",
+ "wango.org",
+ "wangruoshui.net",
+ "wangruowang.org",
+ "want-daily.com",
+ "wanz-factory.com",
+ "wapedia.mobi",
+ "warehouse333.com",
+ "waselpro.com",
+ "washeng.net",
+ "washingtonpost.com",
+ "watch8x.com",
+ "watchinese.com",
+ "watchmygf.net",
+ "wattpad.com",
+ "wav.tv",
+ "waveprotocol.org",
+ "waymo.com",
+ "wda.gov.tw",
+ "wdf5.com",
+ "wearehairy.com",
+ "wearn.com",
+ "weather.com.hk",
+ "web.dev",
+ "web2project.net",
+ "webbang.net",
+ "webevader.org",
+ "webfreer.com",
+ "webjb.org",
+ "weblagu.com",
+ "webmproject.org",
+ "webpack.de",
+ "webrtc.org",
+ "webrush.net",
+ "webs-tv.net",
+ "websitepulse.com",
+ "websnapr.com",
+ "webwarper.net",
+ "webworkerdaily.com",
+ "weekmag.info",
+ "wefightcensorship.org",
+ "wefong.com",
+ "weiboleak.com",
+ "weihuo.org",
+ "weijingsheng.org",
+ "weiming.info",
+ "weiquanwang.org",
+ "weisuo.ws",
+ "welovecock.com",
+ "wemigrate.org",
+ "wengewang.com",
+ "wengewang.org",
+ "wenhui.ch",
+ "wenweipo.com",
+ "wenxuecity.com",
+ "wenyunchao.com",
+ "wenzhao.ca",
+ "westca.com",
+ "westernshugdensociety.org",
+ "westernwolves.com",
+ "westkit.net",
+ "westpoint.edu",
+ "wetplace.com",
+ "wetpussygames.com",
+ "wexiaobo.org",
+ "wezhiyong.org",
+ "wezone.net",
+ "wforum.com",
+ "wha.la",
+ "whatblocked.com",
+ "whatbrowser.org",
+ "whatsapp.com",
+ "whatsapp.net",
+ "whatsonweibo.com",
+ "wheatseeds.org",
+ "wheelockslatin.com",
+ "whereiswerner.com",
+ "wheretowatch.com",
+ "whippedass.com",
+ "whodns.xyz",
+ "whoer.net",
+ "whotalking.com",
+ "whylover.com",
+ "whyx.org",
+ "widevine.com",
+ "wikaba.com",
+ "wikia.com",
+ "wikileaks-forum.com",
+ "wikileaks.ch",
+ "wikileaks.com",
+ "wikileaks.de",
+ "wikileaks.eu",
+ "wikileaks.lu",
+ "wikileaks.org",
+ "wikileaks.pl",
+ "wikilivres.info",
+ "wikimapia.org",
+ "wikinews.org",
+ "wikipedia.org",
+ "wikisource.org",
+ "wikiwiki.jp",
+ "wildammo.com",
+ "williamhill.com",
+ "willw.net",
+ "windowsphoneme.com",
+ "windscribe.com",
+ "windy.com",
+ "wingamestore.com",
+ "wingy.site",
+ "winning11.com",
+ "winwhispers.info",
+ "wionews.com",
+ "wire.com",
+ "wiredbytes.com",
+ "wiredpen.com",
+ "wisdompubs.org",
+ "wisevid.com",
+ "wistia.com",
+ "withgoogle.com",
+ "withyoutube.com",
+ "witnessleeteaching.com",
+ "witopia.net",
+ "wizcrafts.net",
+ "wjbk.org",
+ "wn.com",
+ "wnacg.com",
+ "wnacg.org",
+ "wo.tc",
+ "woeser.com",
+ "woesermiddle-way.net",
+ "wokar.org",
+ "wolfax.com",
+ "woolyss.com",
+ "woopie.jp",
+ "woopie.tv",
+ "wordpress.com",
+ "workatruna.com",
+ "workerdemo.org.hk",
+ "workerempowerment.org",
+ "workersthebig.net",
+ "workflow.is",
+ "worldcat.org",
+ "worldjournal.com",
+ "worldvpn.net",
+ "wow-life.net",
+ "wow.com",
+ "wowgirls.com",
+ "wowlegacy.ml",
+ "wowporn.com",
+ "wowrk.com",
+ "woxinghuiguo.com",
+ "woyaolian.org",
+ "wozy.in",
+ "wp.com",
+ "wpoforum.com",
+ "wqyd.org",
+ "wrchina.org",
+ "wretch.cc",
+ "wsj.com",
+ "wsj.net",
+ "wsjhk.com",
+ "wtbn.org",
+ "wtfpeople.com",
+ "wuerkaixi.com",
+ "wufafangwen.com",
+ "wufi.org.tw",
+ "wuguoguang.com",
+ "wujie.net",
+ "wujieliulan.com",
+ "wukangrui.net",
+ "wuw.red",
+ "wuyanblog.com",
+ "wwe.com",
+ "wwitv.com",
+ "www1.biz",
+ "wwwhost.biz",
+ "wzyboy.im",
+ "x-art.com",
+ "x-berry.com",
+ "x-wall.org",
+ "x.company",
+ "x1949x.com",
+ "x24hr.com",
+ "x365x.com",
+ "xanga.com",
+ "xbabe.com",
+ "xbookcn.com",
+ "xbtce.com",
+ "xcafe.in",
+ "xcity.jp",
+ "xcritic.com",
+ "xda-developers.com",
+ "xerotica.com",
+ "xfiles.to",
+ "xfinity.com",
+ "xgmyd.com",
+ "xhamster.com",
+ "xianba.net",
+ "xianchawang.net",
+ "xianjian.tw",
+ "xianqiao.net",
+ "xiaobaiwu.com",
+ "xiaochuncnjp.com",
+ "xiaod.in",
+ "xiaohexie.com",
+ "xiaolan.me",
+ "xiaoma.org",
+ "xiezhua.com",
+ "xihua.es",
+ "xinbao.de",
+ "xing.com",
+ "xinhuanet.org",
+ "xinmiao.com.hk",
+ "xinsheng.net",
+ "xinshijue.com",
+ "xinyubbs.net",
+ "xiongpian.com",
+ "xiuren.org",
+ "xizang-zhiye.org",
+ "xjp.cc",
+ "xjtravelguide.com",
+ "xkiwi.tk",
+ "xlfmtalk.com",
+ "xlfmwz.info",
+ "xm.com",
+ "xml-training-guide.com",
+ "xmovies.com",
+ "xn--4gq171p.com",
+ "xn--czq75pvv1aj5c.org",
+ "xn--i2ru8q2qg.com",
+ "xn--ngstr-lra8j.com",
+ "xn--oiq.cc",
+ "xn--p8j9a0d9c9a.xn--q9jyb4c",
+ "xnxx.com",
+ "xpdo.net",
+ "xpud.org",
+ "xrentdvd.com",
+ "xskywalker.com",
+ "xskywalker.net",
+ "xtube.com",
+ "xuchao.net",
+ "xuchao.org",
+ "xuehua.us",
+ "xuite.net",
+ "xuzhiyong.net",
+ "xvideo.cc",
+ "xvideos.com",
+ "xvideos.es",
+ "xxbbx.com",
+ "xxlmovies.com",
+ "xxuz.com",
+ "xxx.com",
+ "xxx.xxx",
+ "xxxfuckmom.com",
+ "xxxx.com.au",
+ "xxxy.biz",
+ "xxxy.info",
+ "xxxymovies.com",
+ "xys.org",
+ "xysblogs.org",
+ "xyy69.com",
+ "xyy69.info",
+ "yahoo.co.jp",
+ "yahoo.com",
+ "yahoo.com.hk",
+ "yahoo.com.tw",
+ "yahoo.net",
+ "yakbutterblues.com",
+ "yam.com",
+ "yam.org.tw",
+ "yanghengjun.com",
+ "yangjianli.com",
+ "yasni.co.uk",
+ "yayabay.com",
+ "ycombinator.com",
+ "ydy.com",
+ "yeahteentube.com",
+ "yecl.net",
+ "yeelou.com",
+ "yeeyi.com",
+ "yegle.net",
+ "yes-news.com",
+ "yes.xxx",
+ "yes123.com.tw",
+ "yesasia.com",
+ "yesasia.com.hk",
+ "yespornplease.com",
+ "yeyeclub.com",
+ "ygto.com",
+ "yhcw.net",
+ "yibada.com",
+ "yibaochina.com",
+ "yidio.com",
+ "yigeni.com",
+ "yilubbs.com",
+ "yimg.com",
+ "yingsuoss.com",
+ "yinlei.org",
+ "yipub.com",
+ "yizhihongxing.com",
+ "yobit.net",
+ "yobt.com",
+ "yobt.tv",
+ "yogichen.org",
+ "yolasite.com",
+ "yomiuri.co.jp",
+ "yong.hu",
+ "yorkbbs.ca",
+ "you-get.org",
+ "youdontcare.com",
+ "youjizz.com",
+ "youmaker.com",
+ "youngpornvideos.com",
+ "youngspiration.hk",
+ "youpai.org",
+ "youporn.com",
+ "youporngay.com",
+ "your-freedom.net",
+ "yourepeat.com",
+ "yourlisten.com",
+ "yourlust.com",
+ "yourprivatevpn.com",
+ "yourtrap.com",
+ "yousendit.com",
+ "youshun12.com",
+ "youthforfreechina.org",
+ "youthnetradio.org",
+ "youthwant.com.tw",
+ "youtu.be",
+ "youtube-nocookie.com",
+ "youtube.com",
+ "youtubecn.com",
+ "youtubeeducation.com",
+ "youtubegaming.com",
+ "youversion.com",
+ "youwin.com",
+ "youxu.info",
+ "yt.be",
+ "ytht.net",
+ "ytimg.com",
+ "ytn.co.kr",
+ "yuanming.net",
+ "yuanzhengtang.org",
+ "yulghun.com",
+ "yunchao.net",
+ "yuntipub.com",
+ "yuvutu.com",
+ "yvesgeleyn.com",
+ "ywpw.com",
+ "yx51.net",
+ "yyii.org",
+ "yzzk.com",
+ "zacebook.com",
+ "zalmos.com",
+ "zannel.com",
+ "zaobao.com",
+ "zaobao.com.sg",
+ "zaozon.com",
+ "zapto.org",
+ "zattoo.com",
+ "zb.com",
+ "zdnet.com.tw",
+ "zello.com",
+ "zengjinyan.org",
+ "zenmate.com",
+ "zeronet.io",
+ "zeutch.com",
+ "zfreet.com",
+ "zgsddh.com",
+ "zgzcjj.net",
+ "zhanbin.net",
+ "zhangboli.net",
+ "zhangtianliang.com",
+ "zhanlve.org",
+ "zhenghui.org",
+ "zhengjian.org",
+ "zhengwunet.org",
+ "zhenlibu.info",
+ "zhenlibu1984.com",
+ "zhenxiang.biz",
+ "zhinengluyou.com",
+ "zhongguo.ca",
+ "zhongguorenquan.org",
+ "zhongguotese.net",
+ "zhongmeng.org",
+ "zhoushuguang.com",
+ "zhreader.com",
+ "zhuangbi.me",
+ "zhuanxing.cn",
+ "zhuatieba.com",
+ "zhuichaguoji.org",
+ "zi5.me",
+ "ziddu.com",
+ "zillionk.com",
+ "zim.vn",
+ "zinio.com",
+ "ziporn.com",
+ "zippyshare.com",
+ "zkaip.com",
+ "zkiz.com",
+ "zmw.cn",
+ "zodgame.us",
+ "zoho.com",
+ "zomobo.net",
+ "zonaeuropa.com",
+ "zonghexinwen.com",
+ "zonghexinwen.net",
+ "zoogvpn.com",
+ "zootool.com",
+ "zoozle.net",
+ "zorrovpn.com",
+ "zozotown.com",
+ "zpn.im",
+ "zspeeder.me",
+ "zsrhao.com",
+ "zuo.la",
+ "zuobiao.me",
+ "zuola.com",
+ "zvereff.com",
+ "zynaima.com",
+ "zynamics.com",
+ "zyns.com",
+ "zyzc9.com",
+ "zzcartoon.com",
+ "zzcloud.me",
+ "zzux.com",
+ "149.154.160.0/22",
+ "149.154.164.0/22",
+ "149.154.172.0/22",
+ "91.108.4.0/22",
+ "91.108.20.0/22",
+ "91.108.56.0/22",
+ "91.108.8.0/22",
+ "95.161.64.0/20",
+ "91.108.12.0/22"
+ ]
+ ]
+];
+
+var lastRule = '';
+
+function FindProxyForURL(url, host) {
+ for (var i = 0; i < rules.length; i++) {
+ ret = testHost(host, i);
+ if (ret != undefined)
+ return ret;
+ }
+ return 'DIRECT';
+}
+
+function testHost(host, index) {
+ if( /^\d+\.\d+\.\d+\.\d+$/.test(host) && ( typeof isInNetEx !== "undefined" ) ){
+ for (var i = 0; i < rules[index].length; i++) {
+ for (var j = 0; j < rules[index][i].length; j++) {
+ lastRule = rules[index][i][j];
+ if(host == lastRule || host.endsWith('.' + lastRule) || ( lastRule.indexOf("/") && isInNetEx(host, lastRule) ) ){
+ return i % 2 == 0 ? 'DIRECT' : proxy;
+ }
+ }
+ }
+ return;
+ }
+
+ for (var i = 0; i < rules[index].length; i++) {
+ for (var j = 0; j < rules[index][i].length; j++) {
+ lastRule = rules[index][i][j];
+ if (host == lastRule || host.endsWith('.' + lastRule))
+ return i % 2 == 0 ? 'DIRECT' : proxy;
+ }
+ }
+ lastRule = '';
+}
+
+// REF: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
+if (!String.prototype.endsWith) {
+ String.prototype.endsWith = function(searchString, position) {
+ var subjectString = this.toString();
+ if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {
+ position = subjectString.length;
+ }
+ position -= searchString.length;
+ var lastIndex = subjectString.indexOf(searchString, position);
+ return lastIndex !== -1 && lastIndex === position;
+ };
+}
\ No newline at end of file
diff --git a/release/winXray.7z b/release/winXray.7z
new file mode 100644
index 0000000..0a1139f
Binary files /dev/null and b/release/winXray.7z differ
diff --git a/release/winXray32.7z b/release/winXray32.7z
new file mode 100644
index 0000000..9ebcf13
Binary files /dev/null and b/release/winXray32.7z differ
diff --git a/screenshots/config.advanced.png b/screenshots/config.advanced.png
new file mode 100644
index 0000000..2149235
Binary files /dev/null and b/screenshots/config.advanced.png differ
diff --git a/screenshots/config.json.png b/screenshots/config.json.png
new file mode 100644
index 0000000..7e0dba3
Binary files /dev/null and b/screenshots/config.json.png differ
diff --git a/screenshots/outbound.png b/screenshots/outbound.png
new file mode 100644
index 0000000..4600f43
Binary files /dev/null and b/screenshots/outbound.png differ
diff --git a/screenshots/pac.png b/screenshots/pac.png
new file mode 100644
index 0000000..fd670de
Binary files /dev/null and b/screenshots/pac.png differ
diff --git a/screenshots/telegram.gif b/screenshots/telegram.gif
new file mode 100644
index 0000000..b99d158
Binary files /dev/null and b/screenshots/telegram.gif differ
diff --git a/screenshots/winXray.png b/screenshots/winXray.png
new file mode 100644
index 0000000..85be3ba
Binary files /dev/null and b/screenshots/winXray.png differ
diff --git a/sub/introduce.md b/sub/introduce.md
new file mode 100644
index 0000000..c4e9b62
--- /dev/null
+++ b/sub/introduce.md
@@ -0,0 +1,58 @@
+# winXray 小技巧
+
+### 一、批量导入链接技巧
+
+winXray 可通过【批量导入链接】功能导入以下格式的分享链接、订阅源、或JSON配置:
+
+ 1、一行或多行(忽略无效行)分享链接或服务器JSON配置。
+ 支持 vmess://,vless://,ss://,ssr://,trojan://, trojan-go://,native+http://,socks://, proxy:// 等通用分享链接。
+
+ 2、包含多个服务器配置的JSON数组,支持winXray格式以及通用格式JSON。
+
+ 3、单个 http:// 或 https:// 开头的通用订阅源地址。
+ 可直接使用浏览器地址栏的github文件地址(含blob或raw目录名)。
+ 也可以仅复制单斜杆开始的github文件路径。
+
+ 订阅源可用BASE64编码或明文返回以上1、2条规定的配置或分享链接。
+
+
+[网络免费 vmess 服务器订阅链接](https://proxypool.ga/vmess/sub)
+[网络免费 Shadowsocks 服务器订阅链接](https://proxypool.ga/ss/sub)
+[网络免费 clash 服务器订阅链接](https://proxypoolss.tk/clash/proxies?speed=100&type=vmess,trojan)
+
+可复制上面各种格式订阅链接,在 winXray 中点击【批量导入链接】体验 winXray 有强大的兼容性。
+
+支持以下格式的 Github 项目文件地址作为订阅源( 可省略域名并以斜杆开头 ):
+https://github.com/winXray/winXray/blob/master/sub/sample.json
+[/winXray/blob/master/sub/sample.json](./sample.json)
+https://github.com/winXray/winXray/raw/master/sub/sample.json
+[/winXray/winXray/raw/master/sub/sample.json](./sample.json)
+https://raw.githubusercontent.com/winXray/winXray/master/sub/sample.json
+
+### 二、使用新增、编辑服务器配置的对话框
+
+winXray 新版已经添加了新增、编辑服务器配置的对话框,请直接在 winXray 首页服务器列表点右键菜单,然后点【新增、编辑代理服务器】即可。
+
+![新增、编辑服务器](./../screenshots/winXray.png)
+
+![代理服务器配置](./../screenshots/outbound.png)
+
+### 三、使用JSON配置服务器
+![三、使用JSON配置服务器](./../screenshots/config.json.png)
+JSON配置界面里点击任意字段都会显示该字段的用法说明。个人认为做很多对话框来配置服务器的参数其实是把简单的事搞复杂了,winXray已经把各种代理协议的配置简化为几个统一命名的JSON字段( **也可以作为一种标准的、统一的、通用的订阅响应格式使用** ),只要稍加学习就可以非常熟练的添加、修改各种代理协议的配置。而且对于大多数用户根本不需要改配置 - 简单的复制导入分享链接就可以,我们不必要把简单的事搞复杂。
+
+### 四、使用 PAC 编辑器
+可以直接复制网址( 不需要去截取域名 ) ,然后打开 PAC 编辑器,这时候 winXray 会自动从剪贴板把域名取出来并且输入好,只要点一下设为代理,然后添加域名就可以了。也可以一次复制多个域名,域名可以任何空白字符(或者换行)分隔,然后点右键菜单,再点批量导入域名即可。
+
+winXray 里的 PAC 支持 CIDR 格式的 IP 地址段, 使用此功能可以轻松的让 PAC 代理支持 Telegram。
+
+![使用 PAC 编辑器](./../screenshots/pac.png)
+
+### 五、Telegram 代理设置
+有很多软件的 PAC 代理不支持 Telegram,但 winXray 的 PAC 代理有良好的兼容性 - 可以完美支持 Telegram IP 地址库( 旧版本升级请在 PAC 编辑器右键添加 Telegram IP 地址库 ) 。
+
+当然我们也可以直接告诉 Telegram 他要使用的代理服务器地址的操作非常简单,请看下面的动画:
+![Telegram 代理设置](./../screenshots/telegram.gif)
+
+
+
diff --git a/sub/sample.json b/sub/sample.json
new file mode 100644
index 0000000..e7ab7e5
--- /dev/null
+++ b/sub/sample.json
@@ -0,0 +1,87 @@
+[
+ {
+ "address":"www.aech.cc",
+ "alterId":64,
+ "host":"",
+ "id":"ef3c6aa0-e5f2-4332-bad8-17c0438dfaa3",
+ "network":"ws",
+ "path":"/ray",
+ "port":443,
+ "protocol":"vmess",
+ "ps":"香港4",
+ "security":"auto",
+ "tls":"tls",
+ "type":"none"
+ },
+ {
+ "address":"23.225.125.86",
+ "alterId":64,
+ "host":"www.56626173.xyz",
+ "id":"8fb921c0-564d-4d5a-9b13-384c01820126",
+ "network":"ws",
+ "path":"/footers",
+ "port":443,
+ "protocol":"vmess",
+ "ps":"美国4",
+ "security":"auto",
+ "tls":"tls",
+ "type":"none"
+ },
+ {
+ "address":"104.16.160.20",
+ "alterId":2,
+ "host":"freeus.mcan.tech",
+ "id":"9e6ceeff-2546-3690-ac00-6fcdf31dec94",
+ "network":"ws",
+ "path":"/y284",
+ "port":443,
+ "protocol":"vmess",
+ "ps":"美国4",
+ "security":"auto",
+ "sni":"freeus.mcan.tech",
+ "tls":"tls",
+ "type":"none"
+ },
+ {
+ "address":"llajv.rebldp.tech",
+ "alterId":64,
+ "host":"llajv.rebldp.tech",
+ "id":"3b5e258e-8c5e-45d3-b7d2-02c8f5fc0bb2",
+ "network":"ws",
+ "path":"/",
+ "port":443,
+ "protocol":"vmess",
+ "ps":"德国4",
+ "security":"auto",
+ "tls":"tls",
+ "type":"none"
+ },
+ {
+ "address":"154.84.1.140",
+ "alterId":64,
+ "host":"154.84.1.140",
+ "id":"2a7349d6-994a-434b-9589-c0020685e528",
+ "network":"tcp",
+ "path":"/",
+ "port":54671,
+ "protocol":"vmess",
+ "ps":"荷兰4",
+ "security":"auto",
+ "tls":"",
+ "type":"none"
+ },
+ {
+ "address":"consum2.cukee.cc",
+ "alterId":64,
+ "host":"consum2.cukee.cc",
+ "id":"02914F25-41C8-3114-50F3-19359B631C77",
+ "network":"ws",
+ "path":"/",
+ "port":443,
+ "protocol":"vmess",
+ "ps":"法国4",
+ "security":"auto",
+ "tls":"tls",
+ "type":"none"
+ }
+]
\ No newline at end of file
diff --git a/v2ray-core-32/LICENSE b/v2ray-core-32/LICENSE
new file mode 100644
index 0000000..ac130ba
--- /dev/null
+++ b/v2ray-core-32/LICENSE
@@ -0,0 +1 @@
+https://github.com/v2fly/v2ray-core/blob/master/LICENSE
\ No newline at end of file
diff --git a/v2ray-core-32/v2ctl.exe b/v2ray-core-32/v2ctl.exe
new file mode 100644
index 0000000..afcf69b
Binary files /dev/null and b/v2ray-core-32/v2ctl.exe differ
diff --git a/v2ray-core-32/v2ray.exe b/v2ray-core-32/v2ray.exe
new file mode 100644
index 0000000..ec6e01a
Binary files /dev/null and b/v2ray-core-32/v2ray.exe differ
diff --git a/v2ray-core-32/winXray-default-servers.json b/v2ray-core-32/winXray-default-servers.json
new file mode 100644
index 0000000..a52ea5d
--- /dev/null
+++ b/v2ray-core-32/winXray-default-servers.json
@@ -0,0 +1,19 @@
+// 号开头为注释行。
+// 本文件用于指定默认服务器列表。
+// 本文件可以直接输入json格式的服务器数组( 服务器可以使用subscribeUrl字段指定订阅源地址,可以指定"autoConnect":false字段禁止自动连接 )
+// 也可以每行一个 vless://、vmess://、trojan、trojan-go、ss://、ssr://, 等分享链接
+[
+ {
+ "address":"服务器地址",
+ "port":443, // 服务器端口
+ "id":"UUID或密码", // v2ray就指定UUID,shadowsocks在这里指定密码
+ "network":"tcp", // 网络协议可以改为 "tcp", "ws" 等
+ "security":"none", // 加密方法,vmess 默认为 auto, vless 默认为 none, shadowsocks也可以在这里指定加密方法,例如:"aes-256-gcm",
+ "protocol":"vless", // 协议可以更换为 "vless","vmess","shadowsocks","trojan","trojan-go" 等
+ "host":"伪装主机域名", // 例如ws协议通过这个指定HTTP头里的host字段。
+ "sni":"TLS域名", // 不指定使用host的值,如果host也没指定就使用 address的值
+ "tls":"xtls", // 可以不写,值可以指定为 "","tls","xtls" 等
+ "flow":"流控", // xtls需要用到的字段,可以不指定使用默认值 "xtls-rprx-direct"
+ "ps":"描述文本"
+ }
+]
\ No newline at end of file
diff --git a/v2ray-core/LICENSE b/v2ray-core/LICENSE
new file mode 100644
index 0000000..ac130ba
--- /dev/null
+++ b/v2ray-core/LICENSE
@@ -0,0 +1 @@
+https://github.com/v2fly/v2ray-core/blob/master/LICENSE
\ No newline at end of file
diff --git a/v2ray-core/v2ctl.exe b/v2ray-core/v2ctl.exe
new file mode 100644
index 0000000..79e4316
Binary files /dev/null and b/v2ray-core/v2ctl.exe differ
diff --git a/v2ray-core/v2ray.exe b/v2ray-core/v2ray.exe
new file mode 100644
index 0000000..5095f88
Binary files /dev/null and b/v2ray-core/v2ray.exe differ
diff --git a/v2ray-core/winXray-default-servers.json b/v2ray-core/winXray-default-servers.json
new file mode 100644
index 0000000..a52ea5d
--- /dev/null
+++ b/v2ray-core/winXray-default-servers.json
@@ -0,0 +1,19 @@
+// 号开头为注释行。
+// 本文件用于指定默认服务器列表。
+// 本文件可以直接输入json格式的服务器数组( 服务器可以使用subscribeUrl字段指定订阅源地址,可以指定"autoConnect":false字段禁止自动连接 )
+// 也可以每行一个 vless://、vmess://、trojan、trojan-go、ss://、ssr://, 等分享链接
+[
+ {
+ "address":"服务器地址",
+ "port":443, // 服务器端口
+ "id":"UUID或密码", // v2ray就指定UUID,shadowsocks在这里指定密码
+ "network":"tcp", // 网络协议可以改为 "tcp", "ws" 等
+ "security":"none", // 加密方法,vmess 默认为 auto, vless 默认为 none, shadowsocks也可以在这里指定加密方法,例如:"aes-256-gcm",
+ "protocol":"vless", // 协议可以更换为 "vless","vmess","shadowsocks","trojan","trojan-go" 等
+ "host":"伪装主机域名", // 例如ws协议通过这个指定HTTP头里的host字段。
+ "sni":"TLS域名", // 不指定使用host的值,如果host也没指定就使用 address的值
+ "tls":"xtls", // 可以不写,值可以指定为 "","tls","xtls" 等
+ "flow":"流控", // xtls需要用到的字段,可以不指定使用默认值 "xtls-rprx-direct"
+ "ps":"描述文本"
+ }
+]
\ No newline at end of file