diff --git a/.build/default.init.aardio b/.build/default.init.aardio index be0e6ef..4da1894 100644 --- a/.build/default.init.aardio +++ b/.build/default.init.aardio @@ -1,5 +1,5 @@ //发布前触发 import ide; -io.remove("\..\xray-core\config.json") -io.remove("\..\winXray\xray-core\config.json") +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 index f2f1b0a..6f69530 100644 --- a/.build/default.main.aardio +++ b/.build/default.main.aardio @@ -1,6 +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(); \ No newline at end of file +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 index 9d213e9..23027ec 100644 --- a/.build/update-maker.table +++ b/.build/update-maker.table @@ -1,5 +1,6 @@ { updateUrl="https://raw.githubusercontent.com/winXray/winXray/master/release/update/"; -description="发布 v2.3,修正刷新clash订阅连接重复添加服务器,改进订阅管理等。"; +singleFile=1; +description="发布 v3.7,增加托盘图标显示代理状态,增加 UWP 代理设置"; outputDir="/release/update/" } \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3f055cd..66c7d4e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ -/xray-core/config.json -/winXray/xray-core/config.json +/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/README.md b/README.md index 6ed902b..0dfb4e3 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,139 @@ [winXray 入门小技巧](./sub/introduce.md) -[winXray 最新视频教程](https://www.youtube.com/results?search_query=winXray&sp=CAI%253D) +[winXray 相关视频列表](https://www.youtube.com/results?search_query=winXray) [网络免费 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 强大的兼容性。 +可复制上面各种格式订阅链接,在 winXray 中点击「批量导入链接」体验 winXray 有强大的兼容性。 +免费的服务器仅供测试(一定要走 PAC,不要开全局代理不要登录账号更不要长时间使用 )。 # winXray -本软件源码已贡献到公共领域并放弃版权,源码可使用 [aardio(开发环境仅6.5MB)](http://www.aardio.com) 编译生成单文件绿色EXE( 不需要.Net等任何外部运行库 ),**[点这里下载](./../../raw/master/release/winXray.7z)** ( [64位版本](./../../raw/master/release/winXray.7z) / [32位版本](./../../raw/master/release/winXray32.7z) ),解压即可直接使用( 仅 **[5.0MB](./../../raw/master/release/winXray.7z)** - 已自带 Xray-core)。 +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系统),支持并发检测大量服务器并迅速找到当前最快的服务器,服务器连接异常时可自动寻找其他速度最快的服务器 - 切换速度快如闪电,自订阅源获取的服务器异常时可自动刷新订阅,并且自带一键自动部署服务端工具。 -winXray[:loud_sound:](http://dict.youdao.com/dictvoice?audio=winxray&type=2) 是一个简洁稳定的 [Xray/V2Ray(vmess/vless/xtls)、Shadowsocks、Trojan](https://github.com/XTLS/Xray-core) 通用客户端(Windows系统),可自动检测并连接访问速度最快的代理服务器。服务器连接异常时可以自动更换代理服务器 - 再也不用担心服务器抽风了。winXray 也提供一键安装 XRay(V2Ray、Shadowsocks、Trojan) 服务器工具。 +**本软件源码已放弃版权贡献到公共域** ,源码可使用 [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 的主要代码,用了几天升级就迅速达到了一般其他软件写了几年的成熟度!因为我即将删库,但是我推上去的更新 - fork 的项目基本都没有那么迅速的主动拉更新,大家可以看一下 winXray 上线才短短几天就超过了 600 forks, 所以如果我推送更新之前不删库,那么我删库以后就没有人能找到最新版本的源代码。 + +现在大多杀毒软件都是白名单查杀,所以新生的EXE都会乱报病毒,因为我更新的速度太快,所以不断的推新EXE上来,所以你可能遇到误报,但是你完全可以使用源代码自己编译出一模一样的EXE,还有人吹牛说其他翻墙软件不误报 - 你去 issues 里以及网上搜一下有多少误报好不好?!遇到误报可以提交给你的杀毒厂商核实,也可以自己编译源码生成EXE后使用,解决和核实问题很容易 - 其他套路都是多余的。 + +本来 winXray 源码已放弃版权贡献到公共域,但是有人(TheMRLL )把源码拿去拖了个又大又丑的推广按钮上去,什么功能也不加就发布新版自称官方,而且还把源码搞得很乱出了问题的对本作者进行诋毁( 错误信息都看不懂居然自称开源软件官方 ),对提及原版 winXray 的帖子进行封删和威胁,我真是惊到了世上居然有如此无耻之人,本来就是给你自由发挥的,吃相这么难看良心不会痛吗?!本来我想改一个许可证限制一下这种不好的行为,但是最后我还是决定继续放弃版权,继续将源码贡献到公共域,即然开放源码,就一定要开放得彻底,我们不能因为世上有个别的恶棍而放弃自己善良的初心。 + +最近又发现 TheMRLL 有一些很奇怪的行为。每次我发布新版,他就在后面复制粘贴然后改版本号发布,更奇怪的是他的 commits 基本都是伪造的,我用文件比较工具查了一下,他的多个所谓的改进都只是添加了空函数( 而且还是在开发工具里双击控件生成的范例代码 )。另外他不知道为什么复制粘贴时很多代码放错了位置,所以他提供的程序很多奇怪的 BUG - 这些我提供的原版是没有的。 虽然我并不反对大家自由使用 winXray 的源码,但这个 TheMRLL 实在是太不像话,他提供的 EXE 请大家注意安全谨慎下载。 + +# PAC 代理模式 / 全局代理 + 路由模式 对比 + +winXray 的 PAC 代理稳定、流畅、易用。 在 PAC 模式下,winXray 会优先启用高效安全的 SOCKS5 协议,并且可以自动兼容在 PAC 模式下仅支持 HTTP代理的应用。winXray 也可以在 PAC 模式下完美支持 Telegram IP 地址库 。 + +SOCKS5 支持对比: +- [ ] 全局路由模式: 不支持 SOCKS5 +- [x] PAC模式: 支持 高效安全的SOCKS5 -之前我用过很多代理客户端,经常用一会就挂掉了,有些测试很久才找到下一个可用的服务器,有时怎么切换都不行,一定要把整个软件退出重启才能恢复。而且在WIN10上都有相同的BUG:PAC代理用一段时间就会卡死( winXray已经通过自行实现PAC服务器解决了这个问题 ),其实这些软件里提供的很多功能我并不需要,我只想愉快地用下 google 找点技术资料提升工作效率。但是在网上找了很久都没找到适合的软件,于是决定自己动手写一个,还好用 aardio 写软件的速度很快 - 大概用了几个小时就完成了 winXray 的主要代码,改进了几个版本以后就很稳定了,**我自己用了 winXray 几个月再也没有遇到 google 抽风访问不了的问题**。 +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 网速优化工具】 -一些网友对 winXray 的测速功能存在误解,简单的测速不但不必要的消耗流量而且没有什么实用价值,例如Ping通了TCP访问不了,TCP通了但浏览器被阻断,或者下载测速需要连接代理服务器以后长时间测试才能得到下载速度 - 如果有很多服务器需要频繁快速地测速这样显然是不行的。**根据我长时间的实测,我使用一堆的服务器,大多时候 winXray 都能最快的找到其中速度最快、且能正常使用的线路**。要考虑到网络速度与服务器响应速度本来就是波动的,**winXray 能在连接代理服务器以前在零点几秒以内快速地在上百个代理服务器中找出最快的服务器** - 可以节省我们大量手动测试切换的时间,如果你有一个比我们幸福的网络环境,有一堆稳定流畅看4K视频的代理服务器 - 那你确实可以关闭自动切换功能 - 手动切换即可。 +注意不同的代理协议连接时会调用不同的 Core, +例如 NaïveProxy 连接时会启动 naive.exe,这时候系统防火墙会有提示, +如果这时候没看清就点了拒绝,那么就无法正常使用相应的 Core 了, +所以请看清楚再点,点错了到系统防火墙里再打开一下就可以了。 -![winXray](./screenshots/winXray.png) +# 安装 NaïveProxy 服务端 -winXray支持批量导入 vless、vmess、ss、trojan、trojan-go …… 等格式的分享链接, -也可以导入v2ray,、Shadowsocks、trojan等通用订阅链接,兼容 base 64、json …… 等不同格式的服务器配置,也可以导入 Clash proxy-provider 配置,winXray将自动转化各种不兼容的配置为统一、规范的格式。winXray 有强大的兼容性,我们甚至可以直接自 github 项目地址导入代理服务器,例如直接复制链接 [https://github.com/winXray/winXray/blob/master/sub/sample.json](./sub/sample.json) 即可一键导入 winXray。 +参考:https://github.com/klzgrad/naiveproxy 以 CentOS 为例: -![服务器配置](./screenshots/config.json.png) -**小技巧: JSON里点击任意字段都会显示该字段的用法说明。** 个人认为做很多对话框来配置服务器的参数是非常蠢的,winXray已经把各种代理协议的配置简化为几个统一命名的JSON字段( **也可以作为一种标准的、统一的、通用的订阅响应格式使用** ),只要稍加学习就可以非常熟练的添加、修改各种代理协议的配置。而且对于大多数用户根本不需要改配置 - 简单的复制导入分享链接就可以,我们不必要把简单的事搞复杂。 +```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 -可选在 ["/xray-core/winXray-default-servers.json"](./xray-core/winXray-default-servers.json) 文件中添加默认服务器配置(生成EXE后默认配置自动嵌入到EXE文件,可选删除该文件,也可以继续使用该文件覆盖EXE自带的默认服务器列表)。 +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 -![PAC配置](./screenshots/pac.png) -**小技巧: PAC编辑器里点击任意域名都会自动关联到单选框,可以直接切换代理或直连。** +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 -软件首次运行时会在当前目录查找 "./xray-core/xray.exe" -发行文件仅需要 "./winXray.exe",可选带上 "./xray-core/" 目录( 如果没有找到会自动到v2ray官网下载,不过没有代理服务器下载有时候非常慢 )。 +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; -![端口配置](./screenshots/config.advanced.png) +./naive/naive --config ./naive/config.json & +./caddy run # 后台运行改成 ./caddy start +``` -Telegram 端口配置 +安装以前需要提前准备一个域名,并将上面脚本中的 example.com 替换为你的域名,user:pass 改为代理登录用户名与密码。 \ No newline at end of file diff --git a/default.aproj b/default.aproj index 59a511a..ae636c9 100644 --- a/default.aproj +++ b/default.aproj @@ -1,27 +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 index 1348dbd..6a619a5 100644 --- a/forms/main/config/advancedConfig.aardio +++ b/forms/main/config/advancedConfig.aardio @@ -1,34 +1,39 @@ import fonts.fontAwesome; import win.ui; /*DSG{{*/ -var winform = win.form(text="aardio form";right=938;bottom=604;bgcolor=16777215) +var winform = win.form(text="aardio form";right=892;bottom=573;bgcolor=16777215) winform.add( -btnOpenFirewall={cls="plus";text="设置防火墙";left=511;top=424;right=641;bottom=454;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=545;right=619;bottom=581;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=302;top=463;right=818;bottom=494;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=302;top=423;right=509;bottom=454;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=302;top=503;right=818;bottom=534;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=304;top=163;right=384;bottom=187;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=306;top=364;right=725;bottom=388;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=304;top=272;right=384;bottom=296;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=304;top=319;right=723;bottom=343;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=304;top=124;right=384;bottom=148;align="left";bgcolor=16777215;border={bottom=1;color=-8355712};db=1;dl=1;editable="edit";font=LOGFONT(h=-16);textPadding={bottom=1};z=3}; -lbMaxTestServers={cls="static";text="100";left=590;top=93;right=926;bottom=119;bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-13);transparent=1;z=25}; -lbTestInterval={cls="static";text="15秒";left=590;top=56;right=788;bottom=82;bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-13);transparent=1;z=20}; -lnkVersion={cls="plus";text="正在检查新版本";left=19;top=575;right=380;bottom=606;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}; -radioHttpGlobal={cls="plus";text="全局/PAC 默认使用HTTP代理";left=246;top=206;right=491;bottom=237;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}; -radioSocksGlobal={cls="plus";text="全局/PAC 默认使用SOCKS代理";left=491;top=206;right=750;bottom=237;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}; -static={cls="static";text="SOCKS 代理服务端口:";left=94;top=128;right=292;bottom=154;align="right";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);transparent=1;z=4}; -static2={cls="static";text="PAC 端口:";left=162;top=277;right=292;bottom=303;align="right";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);transparent=1;z=6}; -static3={cls="static";text="本机 PAC 地址:";left=134;top=324;right=292;bottom=350;align="right";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);transparent=1;z=9}; -static4={cls="static";text="局域网 PAC 地址:";left=134;top=370;right=292;bottom=396;align="right";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);transparent=1;z=12}; -static5={cls="static";text="HTTP/HTTPS 代理服务端口:";left=34;top=167;right=292;bottom=193;align="right";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);transparent=1;z=15}; -static6={cls="static";text="支持 SOCKS4、SOCKS4A、SOCKS5";left=392;top=128;right=679;bottom=154;bgcolor=16777215;color=5921370;db=1;dl=1;font=LOGFONT(h=-13);transparent=1;z=16}; -static7={cls="static";text="检测服务器异常间隔时间:";left=47;top=50;right=292;bottom=76;align="right";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);transparent=1;z=19}; -static8={cls="static";text="允许同时测速的服务器数目:";left=47;top=89;right=292;bottom=115;align="right";bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);transparent=1;z=24}; -static9={cls="static";text="PAC 模式默认启用 SOCKS5 或 HTTP 代理,都支持 DNS 保护。全局代理设为默认 HTTP 代理时支持 DNS保 护。";left=250;top=247;right=891;bottom=273;color=12632256;db=1;dl=1;font=LOGFONT(h=-11);transparent=1;z=26}; -tbMaxTestServers={cls="plus";left=304;top=95;right=585;bottom=107;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=304;top=57;right=585;bottom=69;bgcolor=-2512093;border={radius=-1};color=23807;db=1;dl=1;foreRight=13;forecolor=-14911489;notify=1;paddingBottom=5;paddingTop=5;z=18} +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} ) /*}}*/ @@ -36,27 +41,32 @@ import style; winform.chkLan.skin(style.checkBox); winform.chkEnableGitConfigGithub.skin(style.checkBox); winform.chkSystemStart.skin(style.checkBox); -winform.radioHttpGlobal.skin(style.radio) -winform.radioSocksGlobal.skin(style.radio) +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; -winform.lnkVersion.skin(style.link) import win.ui.tooltip; var tooltipCtrl = win.ui.tooltip( winform ); -tooltipCtrl.addTool(winform.lnkVersion,"点击检测更新" ); -tooltipCtrl.addTool(winform.editSocksPort,"点击右键可以复制IP:端口" ); -tooltipCtrl.addTool(winform.radioHttpGlobal,"点击右键可以复制IP:端口" ); -tooltipCtrl.addTool(winform.radioHttpGlobal,"如果某些程序不支持SOCKS全局代理,可以切换到此选项。" ); -tooltipCtrl.addTool(winform.radioSocksGlobal,"如果某些程序不支持SOCKS全局代理,可以切换到HTTP全局代理。" ); +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 xray.pacServer; +import v2ray.pacServer; onPacUpdated = function(){ - winform.editPacPort.text = xray.pacServer.getPort() || config.proxy.pacPort || 1083; - winform.editPacUrl.text = xray.pacServer.getUrl(); - winform.editLanPacUrl.text = xray.pacServer.getUrl(true); + 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; } @@ -65,17 +75,19 @@ subscribe("pacServer.restarted",function(pacPort){ }) subscribe("sysProxy.modeChanged",function(mode){ - if(mode==="mode"){ - winform.editPacUrl.text = xray.pacServer.getUrl(); - winform.editLanPacUrl.text = xray.pacServer.getUrl(true); + 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 xray.core; +import v2ray.core; var onInboundsUpdated = function(){ var inbounds = ..config.core.default[["inbounds"]]; - winform.editSocksPort.text = xray.core.socksProxyPort || inbounds[[1]][["port"]] || 1081; - winform.editHttpPort.text = xray.core.httpProxyPort || inbounds[[2]][["port"]] || 1082; + winform.editSocksPort.text = v2ray.core.socksProxyPort || inbounds[[1]][["port"]] || 1081; + winform.editHttpPort.text = v2ray.core.httpProxyPort || inbounds[[2]][["port"]] || 1082; winform.chkLan.checked = inbounds[[1]][["listen"]] !== "127.0.0.1"; winform.btnOpenFirewall.disabled = !winform.chkLan.checked; } @@ -84,7 +96,7 @@ subscribe("config.core.changed",function(){ onInboundsUpdated(); }) -subscribe("xrayCore.restarted",function(socksProxyPort,httpProxPort){ +subscribe("v2RayCore.restarted",function(socksProxyPort,httpProxPort){ onInboundsUpdated(); }) @@ -94,19 +106,27 @@ winform.chkSystemStart.checked = reg.queryValue("winXray"); reg.close(); winform.chkEnableGitConfigGithub.checked = config.proxy.enableGitConfigGithub; -winform.radioHttpGlobal.checked = config.proxy.useHttpGlobal; -winform.radioSocksGlobal.checked = !config.proxy.useHttpGlobal; +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.radioHttpGlobal.checked; - xray.pacServer.updateUseHttpProxy(config.proxy.useHttpGlobal); + 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 = xray.core.socksProxyPort; + 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) ){ @@ -117,7 +137,7 @@ winform.btnUpdate.oncommand = function(id,event){ client.close(); var client = wsock.tcp.client(); - var oldPacPort = xray.pacServer.getPort(); + 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) ){ @@ -131,12 +151,12 @@ winform.btnUpdate.oncommand = function(id,event){ if(winform.chkEnableGitConfigGithub.checked!=config.proxy.enableGitConfigGithub){ config.proxy.enableGitConfigGithub = winform.chkEnableGitConfigGithub.checked; - import xray.github; + import v2ray.github; if(!config.proxy.enableGitConfigGithub){ - xray.github.setProxy(false); + v2ray.github.setProxy(false); } else { - xray.github.setProxy(null); + v2ray.github.setProxy(null); } } @@ -164,15 +184,15 @@ winform.btnUpdate.oncommand = function(id,event){ restartCore = true; } - config.core.save(); + config.core.save(); publish("config.inbounds.changed"); if(restartCore) { - publish("uiCommand.restartXrayCore"); + publish("uiCommand.restartV2RayCore"); } config.proxy.pacPort = tonumber(winform.editPacPort.text) if(oldPacPort!=tonumber(winform.editPacPort.text)){ - xray.pacServer.restart(); + v2ray.pacServer.restart(); } config.proxy.save(); @@ -190,6 +210,12 @@ winform.btnUpdate.oncommand = function(id,event){ } 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); } @@ -245,6 +271,7 @@ 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; } @@ -277,39 +304,46 @@ winform.tbMaxTestServers.onPosChanged = function( pos,thumbTrack ){ config.proxy.save(); } -import 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.oncommand = function(id,event){ +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.text = fsys.update.simpleMain.getReadyStatusInfo() ? "正在启动自动更新" : "正在检查新版本"; - winform.lnkVersion.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'} - if(fsys.update.simpleMain.checkUpdate(true)){ - win.quitMessage(); + 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.close(); +} + winform.btnOpenFirewall.skin(style.plainButton) winform.btnOpenFirewall.oncommand = function(id,event){ diff --git a/forms/main/config/coreConfigs/default.json b/forms/main/config/coreConfigs/default.json new file mode 100644 index 0000000..b213cee --- /dev/null +++ b/forms/main/config/coreConfigs/default.json @@ -0,0 +1,71 @@ +{ + "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" + } + ] + } +} \ 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..dc9608d --- /dev/null +++ b/forms/main/config/coreConfigs/v2ray.rules.json @@ -0,0 +1,164 @@ +{ + "inbounds": [ + { + "listen": "127.0.0.1", + "port": 1081, + "protocol": "socks", + "settings": { + "auth": "noauth", + "udp": true + }, + "sniffing": { + "destOverride": [ + "http", + "tls" + ], + "enabled": true + }, + "tag": "proxy" + }, + { + "listen": "127.0.0.1", + "port": 1082, + "protocol": "http", + "settings": {}, + "sniffing": { + "destOverride": [ + "http", + "tls" + ], + "enabled": true + }, + "tag": "http_proxy" + } + ], + "log": { + "access": "", + "error": "", + "loglevel": "warning" + }, + "outbounds": [ + { + "tag": "proxy" + }, + { + "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 index 55d5c99..a611f51 100644 --- a/forms/main/config/jsonConfig.aardio +++ b/forms/main/config/jsonConfig.aardio @@ -1,20 +1,26 @@ import fonts.fontAwesome; import win.ui; /*DSG{{*/ -var winform = win.form(text="aardio form";right=912;bottom=793;bgcolor=16777215) +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=29;right=902;bottom=739;bgcolor=16777215;db=1;dl=1;dr=1;dt=1;edge=1;z=10}; -btnUpdate={cls="plus";text="更新服务器配置";left=687;top=753;right=856;bottom=784;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=5}; -editCoreConfig={cls="edit";left=9;top=29;right=902;bottom=739;db=1;dl=1;dr=1;dt=1;edge=1;hide=1;hscroll=1;multiline=1;vscroll=1;z=8}; -editOutbounds={cls="edit";left=9;top=29;right=902;bottom=739;db=1;dl=1;dr=1;dt=1;edge=1;hscroll=1;multiline=1;vscroll=1;z=7}; -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=6}; -navAdvancedConfig={cls="plus";text="代理端口 / 高级配置";left=359;top=750;right=493;bottom=782;border={top=1;color=-16744448};db=1;dl=1;z=9}; -navCoreConfig={cls="plus";text="Xray配置 ( JSON )";left=162;top=750;right=293;bottom=782;border={top=1;color=-16744448};db=1;dl=1;z=2}; -navOutbounds={cls="plus";text="服务器配置( JSON )";left=31;top=750;right=162;bottom=782;border={top=1;color=-16744448};db=1;dl=1;z=1}; -navRight={cls="plus";left=493;top=750;right=762;bottom=751;bgcolor=16777215;border={color=-16744448};db=1;dl=1;dr=1;forecolor=32768;linearGradient=180;z=3}; -navSubscription={cls="plus";text="订阅";left=293;top=750;right=359;bottom=782;border={top=1;color=-16744448};db=1;dl=1;z=12}; -plus={cls="plus";left=9;top=750;right=31;bottom=751;border={color=-16744448};db=1;dl=1;forecolor=32768;z=4}; -subscription={cls="\forms\main\config\subscription.aardio";left=9;top=29;right=902;bottom=739;bgcolor=16777215;db=1;dl=1;dr=1;dt=1;edge=1;z=11} +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}; +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} ) /*}}*/ @@ -41,45 +47,27 @@ tbs.skin({ }); 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; + if(idx==1){ - winform.editOutbounds.hide = false; - winform.advancedConfig.hide = true; - winform.editCoreConfig.hide = true; - winform.subscription.hide = true; - - winform.lbTip.text = `可在下面输入多行服务器分享链接,或JSON数组( 点击字段名会显示用法说明 ):`; - winform.btnUpdate.text = "更新服务器配置"; - winform.btnUpdate.hide = false; + winform.btnUpdate.text = "更新服务器配置"; } - elseif(idx==2) { - winform.editCoreConfig.hide = false; - winform.editOutbounds.hide = true; - winform.advancedConfig.hide = true; - winform.subscription.hide = true; - - winform.lbTip.text = `inbounds[0],inbounds[1]必须为入站socks、http 代理,outbounds[0] 会转换为出站服务器数组: ` - winform.btnUpdate.text = "更新Xray配置 " - winform.btnUpdate.hide = false; + elseif(idx==2) { + winform.btnUpdate.text = "更新内核配置 " } - elseif(idx==3) { - - winform.subscription.hide = false; - winform.editOutbounds.hide = true; - winform.advancedConfig.hide = true; - winform.editCoreConfig.hide = true; - - winform.lbTip.text = `` - winform.btnUpdate.hide = true; + elseif(idx==3) { winform.subscription.loadSubscriptionsOnce(); - } - else { - winform.advancedConfig.hide = false; - winform.editOutbounds.hide = true; - winform.subscription.hide = true; - winform.editCoreConfig.hide = true; - winform.lbTip.text = `` - winform.btnUpdate.hide = true; - } + } } tbs.selIndex = 1; @@ -98,19 +86,19 @@ winform.btnUpdate.oncommand = function(id,event){ } if(cfg){ - cfg = xray.outbounds.validAll(cfg) + cfg = v2ray.outbounds.validAll(cfg) } config.proxy.outbounds = cfg : ..table.array(); } else { - var outbounds = xray.outbounds.importFromString(winform.editOutbounds.text); + 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.restartXrayCore",cfg) + publish("uiCommand.restartV2RayCore",cfg) } elseif(tbs.selIndex==2) { var cfg,err = web.json.tryParse(winform.editCoreConfig.text); @@ -152,7 +140,8 @@ winform.btnUpdate.oncommand = function(id,event){ config.core.default = cfg; config.core.save(); - publish("uiCommand.restartXrayCore",cfg) + + publish("uiCommand.restartV2RayCore",cfg); publish("config.core.changed"); } @@ -162,7 +151,7 @@ winform.btnUpdate.oncommand = function(id,event){ } -import xray.outbounds; +import v2ray.outbounds; winform.editOutbounds.enablePopMenu(function(){ if(tbs.selIndex==1){ var strEditBounds = string.trim(winform.editOutbounds.text); @@ -171,7 +160,7 @@ winform.editOutbounds.enablePopMenu(function(){ { "自剪贴板导入 vmess/vless/trojan/ss 链接或订阅源"; function(id){ - var outbounds = xray.outbounds.importFromClipboard(); + var outbounds = v2ray.outbounds.importFromClipboard(); if(#outbounds){ var json = strEditBounds; if( (!#json) || ..string.match(json,"%\[\]")){ @@ -198,7 +187,7 @@ winform.editOutbounds.enablePopMenu(function(){ winform.editOutbounds.text = ..web.json.stringifyArray(cfgOutbounds,true,false,true); } else { - var str = xray.outbounds.exportSharedLinks(outbounds); + var str = v2ray.outbounds.exportSharedLinks(outbounds); if(#strEditBounds){ winform.editOutbounds.text = strEditBounds+ '\r\n' + str; } @@ -213,7 +202,7 @@ winform.editOutbounds.enablePopMenu(function(){ return; } - winform.msgFrown('未导入服务器!\r\n请先复制以下格式文本(自动清除其中的无效内容):\r\n\r\n1、一行或多行(忽略无效行)分享链接或服务器JSON配置。\r\n支持 vmess://,vless://,ss://,trojan://, trojan-go:// 等通用分享链接。\r\n\r\n2、包含多个服务器配置的JSON数组。\r\n\r\n3、单个 http:// 或 https:// 开头的通用订阅源地址。\r\n订阅源地址支持直接使用github项目文件地址(网址含raw或blob目录名)。\r\n订阅源可以BASE64编码或明文返回以上1、2条规定的配置或分享链接。') + 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条规定的配置或分享链接。') } }; } @@ -254,7 +243,7 @@ winform.editOutbounds.enablePopMenu(function(){ var count = 0; for(url,v in subscribeUrls){ - var outbounds = xray.outbounds.importFromString(url); + var outbounds = v2ray.outbounds.importFromString(url); if(#outbounds){ for(i=#cfg;1;-1){ var outbound = cfg[i] @@ -298,7 +287,7 @@ winform.editOutbounds.enablePopMenu(function(){ } } - var str = xray.outbounds.exportSharedLinks(cfgOutbouds); + var str = v2ray.outbounds.exportSharedLinks(cfgOutbouds); if(str){ winform.editOutbounds.text = str; winform.editOutbounds.modified = true; @@ -313,7 +302,7 @@ winform.editOutbounds.enablePopMenu(function(){ return; } - var str = xray.outbounds.exportSharedLinks(cfg); + var str = v2ray.outbounds.exportSharedLinks(cfg); if(str){ import crypt; winform.editOutbounds.text = ..crypt.encodeBin(str); @@ -328,7 +317,7 @@ winform.editOutbounds.enablePopMenu(function(){ menu[4] = { "转换为 JSON"; function(id){ import web.json; - var outbounds = xray.outbounds.importFromString(strEditBounds); + var outbounds = v2ray.outbounds.importFromString(strEditBounds); if(outbounds){ winform.editOutbounds.text = web.json.stringifyArray(outbounds,true,false,true); winform.editOutbounds.modified = true; @@ -370,8 +359,8 @@ winform.editOutbounds.enablePopMenu(function(){ config.proxy.outbounds,true,false,true ) - string.save("/xray-core/winXray-default-servers.json",str ); - winform.msgOk("已存为默认服务器列表 /xray-core/winXray-default-servers.json",1000) + string.save("/v2ray-core/winXray-default-servers.json",str ); + winform.msgOk("已存为默认服务器列表 /v2ray-core/winXray-default-servers.json",1000) } }); @@ -396,7 +385,7 @@ winform.editOutbounds.enablePopMenu(function(){ winform.btnUpdate.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'} ..config.__loadDefaultOutbounds(); winform.editOutbounds.modified = false; - publish("uiCommand.restartXrayCore",cfg); + publish("uiCommand.restartV2RayCore",cfg); winform.btnUpdate.disabledText = null; } @@ -448,11 +437,6 @@ winform.editOutbounds.enablePopMenu(function(){ winform.editOutbounds.selText = '"security":"auto",' } }; - { "启用TLS:tls"; - function(id){ - winform.editOutbounds.selText = '"tls":"xtls",' - } - }; { "允许忽略证书:allowInsecure"; function(id){ winform.editOutbounds.selText = '"allowInsecure":true,' @@ -465,7 +449,7 @@ winform.editOutbounds.enablePopMenu(function(){ }; { "启用TLS:tls"; function(id){ - winform.editOutbounds.selText = '"tls":"xtls",' + winform.editOutbounds.selText = '"tls":"tls",' } }; { "流控:flow"; @@ -533,12 +517,28 @@ winform.editOutbounds.enablePopMenu(function(){ winform.editCoreConfig.enablePopMenu({ { /*---分隔线---*/ }; - { "重置为默认 Xray 配置"; + { "重置为默认内核配置"; function(id){ - config.__resetDefaultCore(); + winform.editCoreConfig.text = ..string.load("\forms\main\config\coreConfigs\default.json") + winform.editCoreConfig.msgOk('已重置为默认内核配置。\n请在下面点击:『更新内核配置』启用新的配置。',1300) + } + }; + { "重置为启用路由规则默认内核配置"; + function(id){ + winform.editCoreConfig.text = ..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) } }; } ) @@ -579,7 +579,7 @@ var editOutboundsTip = { address = {"代理服务器地址";"值可以是域名或者IP地址"}; alterId = {"额外ID";"仅用于VMESS协议,与服务器一致即可"}; aid = {"额外ID(alterId)";"数值,仅用于VMESS协议,与服务器一致即可"}; - network = {"传输协议(network)";"可选值为tcp,ws等"}; + 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 = {"备注";"备注"}; @@ -594,6 +594,9 @@ var editOutboundsTip = { 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根据连接协议自动设定此值。"}; } @@ -615,10 +618,123 @@ winform.editOutbounds.wndproc = function(hwnd,message,wParam,lParam){ } } +winform.editCoreConfig.oncommand = function(id,event){ + if( event === 0x100/*_EN_SETFOCUS*/){ + winform.editCoreConfig.showInfoTip("提示",'inbounds[0] 必须为入站 SOCKS 代理,\ninbounds[1] 必须为入站 HTTP 代理,\noutbounds[0] 会转换为出站服务器数组。') + } +} + winform.editOutbounds.limit = 0; winform.editCoreConfig.limit = 0; -winform.enableDpiScaling(); +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; +return winform; \ No newline at end of file diff --git a/forms/main/config/subscription.aardio b/forms/main/config/subscription.aardio index 20db4f5..2318224 100644 --- a/forms/main/config/subscription.aardio +++ b/forms/main/config/subscription.aardio @@ -1,14 +1,14 @@ import fonts.fontAwesome; import win.ui; /*DSG{{*/ -var winform = win.form(text="aardio form";right=892;bottom=709;bgcolor=16777215) +var winform = win.form(text="aardio form";right=892;bottom=564;bgcolor=16777215) winform.add( -btnAdd={cls="plus";text="添加订阅";left=10;top=1;right=143;bottom=28;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=1;right=276;bottom=28;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=576;top=654;right=698;bottom=690;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=628;right=118;bottom=659;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=663;right=527;bottom=694;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=34;right=883;bottom=609;db=1;dl=1;dr=1;dt=1;edge=1;fullRow=1;gridLines=1;z=4}; +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} ) /*}}*/ @@ -163,9 +163,9 @@ winform.btnUpdate.oncommand = function(id,event){ if(removed) config.proxy.save(); - import xray.outbounds; - if(!xray.outbounds.updateSubscription()){ - if(removed) publish("uiCommand.restartXrayCore",outbounds) + import v2ray.outbounds; + if(!v2ray.outbounds.updateSubscription()){ + if(removed) publish("uiCommand.restartV2RayCore",outbounds) } winform.btnUpdate.disabledText = null; @@ -208,7 +208,7 @@ winform.btnRemove.oncommand = function(id,event){ config.proxy.save(); if(outboundRemoved){ - publish("uiCommand.restartXrayCore") + publish("uiCommand.restartV2RayCore") } else { win.delay(200); diff --git a/forms/main/json.aardio b/forms/main/json.aardio deleted file mode 100644 index 5d7b8ea..0000000 --- a/forms/main/json.aardio +++ /dev/null @@ -1,342 +0,0 @@ -import fonts.fontAwesome; -import win.ui; -/*DSG{{*/ -var winform = win.form(text="aardio form";right=912;bottom=793;bgcolor=16777215) -winform.add( -btnUpdate={cls="plus";text="更新设置";left=731;top=750;right=863;bottom=781;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=7}; -editCoreConfig={cls="edit";left=10;top=34;right=903;bottom=744;db=1;dl=1;dr=1;dt=1;edge=1;hide=1;hscroll=1;multiline=1;vscroll=1;z=6}; -editOutbounds={cls="edit";left=9;top=32;right=902;bottom=743;db=1;dl=1;dr=1;dt=1;edge=1;hscroll=1;multiline=1;vscroll=1;z=1}; -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=8}; -navCoreConfig={cls="plus";text="高级配置( JSON )";left=184;top=750;right=315;bottom=782;border={top=1;color=-16744448};db=1;dl=1;z=3}; -navOutbounds={cls="plus";text="服务器配置( JSON )";left=53;top=750;right=184;bottom=782;border={top=1;color=-16744448};db=1;dl=1;z=2}; -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=4}; -plus={cls="plus";left=9;top=750;right=53;bottom=751;border={color=-16744448};db=1;dl=1;forecolor=32768;z=5} -) -/*}}*/ - -import config; -import web.json; -import win.ui.tabs; -var tbs = win.ui.tabs(winform.navOutbounds,winform.navCoreConfig,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.editOutbounds.hide = false; - winform.editCoreConfig.hide = true; - winform.lbTip.text = `可在下面输入JSON数组、或每行一个服务器链接、或每行以空格分开的服务器配置文本:` - } - else { - winform.editOutbounds.hide = true; - winform.editCoreConfig.hide = false; - winform.lbTip.text = `outbounds[1]会被自动替换为服务器数组,请勿修改: ` - } -} -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; - } - config.proxy.outbounds = cfg : ..table.array(); - } - else { - var outbounds = xray.outbounds.importFromString(winform.editOutbounds.text); - config.proxy.outbounds = outbounds : ..table.array(); - winform.editOutbounds.text = web.json.stringify(outbounds,true); - } - - config.proxy.save(); - winform.editOutbounds.modified = false; - publish("config.proxy.outbounds.changed",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; - } - - if(cfg.outbounds[[1]][["tag"]]!="proxy"){ - winform.msgErr(`outbounds[1]必须指定为{"tag":"proxy"}`); - winform.btnUpdate.disabledText = null; - return; - } - - config.core.default = cfg; - config.core.save(); - publish("config.proxy.outbounds.changed",cfg) - } - - win.delay(500); - winform.btnUpdate.disabledText = null; - winform.msgOk("配置已更新",1200); -} - - -import xray.outbounds; -winform.editOutbounds.enablePopMenu(function(){ - if(tbs.selIndex==1){ - var strEditBounds = string.trim(winform.editOutbounds.text); - var menu = { - { /*---分隔线---*/ }; - { "自剪贴板批量导入vmess、trojan、ss链接、或订阅源"; - function(id){ - - var outbounds = xray.outbounds.importOutboundFromClip(); - if(#outbounds){ - var json = strEditBounds; - if( (!#json) || ..string.match(json,"%\[\]")){ - var cfg,err = ..table.array(); - if(#json){ - cfg,err= web.json.tryParse(strEditBounds); - if(!cfg){ - winform.editOutbounds.showErrorTip(,string.concat("当前配置存在JSON语法错误 ",err)); - return; - } - } - - ..table.append(cfg,outbounds); - winform.editOutbounds.text = ..web.json.stringify(cfg,true); - } - else { - var str = xray.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("未导入服务器, 请先复制订阅源、或vmess、ss、trojan链接!") - } - }; - } - - 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 = xray.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.stringify(cfg,true); - - winform.msgOk("已成功刷新" + count + "个服务器,请点击「更新设置」启用新配置。",1200); - winform.editOutbounds.modified = true; - winform.editOutbounds.setFocus(); - return; - } - }; - } - - if(..string.match(strEditBounds,"%\[\]")){ - menu[4] = {} - menu[5] = { "转换为 vmess、trojan、ss 分享链接"; - function(id){ - var cfg,err = web.json.tryParse(strEditBounds); - if(!cfg){ - winform.editOutbounds.showErrorTip(,string.concat("JSON语法错误 ",err)); - return; - } - - var str = xray.outbounds.exportSharedLinks(cfg); - 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 = xray.outbounds.exportSharedLinks(cfg); - if(str){ - import crypt; - winform.editOutbounds.text = ..crypt.encodeBin(str); - winform.editOutbounds.modified = true; - } - } - }; - menu[7] = { "转换为文本格式"; - function(id){ - var cfg,err = web.json.tryParse(strEditBounds); - if(!cfg){ - winform.editOutbounds.showErrorTip(,string.concat("JSON语法错误 ",err)); - return; - } - - var outstr = {}; - for i,outbound in table.eachIndex(cfg){ - if(outbound.protocol != "shadowsocks"){ - var path = outbound.path; - if( outbound.host){ - path = ( (#outbound.type && outbound.type!="none") ? outbound.type : outbound.network : "") - + "://" + outbound.host ++ path; - } - - table.push(outstr, string.concat( outbound.address,'\t' - ,outbound.port,'\t' - ,outbound.id,,'\t' - ,outbound.network,'\t' - ,path,'\t' - ,outbound.tls ) ); - } - else { - table.push(outstr, string.concat( outbound.address,'\t' - ,outbound.port,'\t' - ,outbound.id,,'\t' - ,'shadowsocks\t' - ,outbound.security) ); - } - } - - winform.editOutbounds.text = string.join(outstr,'\r\n'); - winform.editOutbounds.modified = true; - } - }; - } - elseif( #strEditBounds ) { - menu[3] = {} - - menu[4] = { "转换为 JSON"; - function(id){ - import web.json; - var outbounds = xray.outbounds.importFromString(strEditBounds); - if(outbounds){ - winform.editOutbounds.text = web.json.stringify(outbounds,true); - winform.editOutbounds.modified = true; - } - } - }; - } - - table.push(menu,{ /*---分隔线---*/ }); - if(winform.editOutbounds.modified){ - table.push(menu,{ "恢复为当前服务器配置(JSON)"; - function(id){ - winform.editOutbounds.text = web.json.stringify( - config.proxy.outbounds,true - ) - winform.editOutbounds.modified = false; - } - }); - } - - table.push(menu,{ "恢复为默认服务器配置(JSON)"; - function(id){ - ..config.__loadDefaultOutbounds(); - publish("config.proxy.outbounds.changed",cfg); - } - }); - - return menu; - } -}) - -subscribe("config.proxy.outbounds.config.changed",function(){ - if(winform.editOutbounds.modified){ - return; - } - - winform.editOutbounds.text = web.json.stringify( - config.proxy.outbounds,true - ) - - winform.editOutbounds.modified = false; -} ) - -winform.editOutbounds.text = #config.proxy.outbounds ? web.json.stringify( - config.proxy.outbounds ,true -) : "[]" -winform.editOutbounds.modified = false; - -winform.editCoreConfig.text = web.json.stringify( - config.core.default,true -) - -winform.enableDpiScaling(); -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 index a825c84..3e27acb 100644 --- a/forms/main/pac.aardio +++ b/forms/main/pac.aardio @@ -76,7 +76,7 @@ tbs.selIndex = 1; import win.dlg.message; win.dlg.message.install(); -winform.loadPacToEdit = function(str){ +winform.loadPacToEdit = function(str,fromUpdater){ var rules = string.match(str,"var\s+rules\s*=\s*(%\[\])") if(!rules) return winform.msgErr("PAC文件格式错误"); @@ -88,6 +88,21 @@ winform.loadPacToEdit = function(str){ 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) @@ -102,14 +117,40 @@ winform.btnUpdate.oncommand = function(id,event){ import web.rest.github; var result = web.rest.github.getContent("petronny","gfwlist2pac","gfwlist.pac"); if( result ){ - winform.loadPacToEdit( 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」按钮"); + winform.msgOk("PAC 已同步到最新版本,请点击「保存 PAC」按钮"); } else { - winform.msgFrown("PAC更新失败,建议开启全局代理后重试。") + winform.msgFrown("PAC 更新失败,建议开启全局代理后重试。") } winform.btnUpdate.disabledText = null; },winform @@ -118,7 +159,7 @@ winform.btnUpdate.oncommand = function(id,event){ import sysProxy; import string.conv; -import xray.pacServer; +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)) @@ -131,13 +172,13 @@ winform.savePacToFile = function(){ return winform.msgErr("直连域名配置格式错误"); } - xray.pacServer.savePacText(web.json.stringify({{direct;proxy}},true)); + 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.msgOk("已保存 PAC 文件",1200); winform.btnSave.disabledText = null; winform.btnSave.disabled = true; winform.btnReset.disabled = true; @@ -160,19 +201,19 @@ winform.btnReset.oncommand = function(id,event){ thread.invoke( function(winform){ - import xray.pacServer; - winform.loadPacToEdit(xray.pacServer.loadPacText()); + import v2ray.pacServer; + winform.loadPacToEdit(v2ray.pacServer.loadPacText()); winform.btnReset.disabledText = null; winform.btnSave.disabled = true; winform.btnReset.disabled = true; - winform.msgOk("已恢复到当前PAC配置") + winform.msgOk("已恢复到当前 PAC 配置") },winform ) } -import xray.pacServer; -winform.loadPacToEdit( xray.pacServer.loadPacText() ); +import v2ray.pacServer; +winform.loadPacToEdit( v2ray.pacServer.loadPacText() ); winform.editPacProxy.modified = false; winform.editPacDirect.modified = false; @@ -260,7 +301,7 @@ winform.editPacDirect.enablePopMenu(function(){ } }; {}; - { "自剪贴板导入直连域名(支持任意空白分隔符)"; + { "自剪贴板导入直连域名或 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)) @@ -270,7 +311,7 @@ winform.editPacDirect.enablePopMenu(function(){ import win.clip; var str = win.clip.read(); if(!str){ - return winform.msgWarn("请先复制域名到剪贴板"); + return winform.msgWarn("请先复制域名或CIDR格式IP段到剪贴板(支持任意空白分隔符)"); } var count,ignored = 0,0; @@ -288,25 +329,40 @@ winform.editPacDirect.enablePopMenu(function(){ 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+' 个直连域名,\r\n' + winform.msgInfo('已成功导入 '+count+' 个直连域名或 IP 段,\r\n' + ignored + '个域名已经是直连域名无需添加。\r\n下一步请点下面的「保存PAC」按钮。',1500); } }; - { "重置为默认PAC"; + { "重置为默认 PAC"; function(id){ - import xray.pacServer; - xray.pacServer.resetPac(); - winform.loadPacToEdit(xray.pacServer.loadPacText()); + import v2ray.pacServer; + v2ray.pacServer.resetPac(); + winform.loadPacToEdit(v2ray.pacServer.loadPacText()); } }; - { "恢复为当前使用的PAC"; + { "恢复为当前使用的 PAC"; function(id){ - import xray.pacServer; - winform.loadPacToEdit(xray.pacServer.loadPacText()); + import v2ray.pacServer; + winform.loadPacToEdit(v2ray.pacServer.loadPacText()); } }; } @@ -326,7 +382,7 @@ winform.editPacProxy.enablePopMenu(function(){ } }; {}; - { "自剪贴板导入代理域名(支持任意空白分隔符)"; + { "自剪贴板导入代理域名或 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)) @@ -336,7 +392,7 @@ winform.editPacProxy.enablePopMenu(function(){ import win.clip; var str = win.clip.read(); if(!str){ - return winform.msgWarn("请先复制域名到剪贴板"); + return winform.msgWarn("请先复制域名或 CIDR 格式 IP 段到剪贴板(支持任意空白分隔符)"); } var count,ignored = 0,0; @@ -354,25 +410,71 @@ winform.editPacProxy.enablePopMenu(function(){ 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+' 个代理域名,\r\n' + winform.msgInfo('已成功导入 '+count+' 个代理域名或 IP 段,\r\n' + ignored + '个域名已经是代理域名无需添加。\r\n下一步请点下面的「保存PAC」按钮。',1500); } }; - { "重置为默认PAC"; + + { "导入所有 Telegram IP"; function(id){ - import xray.pacServer; - xray.pacServer.resetPac(); - winform.loadPacToEdit(xray.pacServer.loadPacText()); + 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"; + { /*分隔符*/ }; + { "重置为默认 PAC"; function(id){ - import xray.pacServer; - winform.loadPacToEdit(xray.pacServer.loadPacText()); + import v2ray.pacServer; + v2ray.pacServer.resetPac(); + winform.loadPacToEdit(v2ray.pacServer.loadPacText()); + } + }; + { "恢复为当前使用的 PAC"; + function(id){ + import v2ray.pacServer; + winform.loadPacToEdit(v2ray.pacServer.loadPacText()); } }; } @@ -403,11 +505,11 @@ winform.btnDeleteDomain.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数组"); + 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配置不包含此域名") + winform.editPacDomain.editBox.showInfoTip(,"PAC 配置不包含此域名") return; } @@ -469,7 +571,7 @@ winform.onClose = function(hwnd,message,wParam,lParam){ if(winform.editPacDirect.modified||winform.editPacProxy.modified){ winform.btnUpdate.disabled = true; - if(!winform.msgAsk("PAC配置已修改但尚未保存,确定要退出并放弃更改吗?")){ + if(!winform.msgAsk("PAC 配置已修改但尚未保存,确定要退出并放弃更改吗?")){ return true; } } diff --git a/forms/main/tools/github.aardio b/forms/main/tools/github.aardio index be59758..eb7b218 100644 --- a/forms/main/tools/github.aardio +++ b/forms/main/tools/github.aardio @@ -10,7 +10,8 @@ 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官网接口优化http协议访问官网速度( 适用于无代理连接 )。";left=49;top=50;right=635;bottom=86;font=LOGFONT(h=-13);transparent=1;z=4}; +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} ) /*}}*/ diff --git a/forms/main/tools/tools.aardio b/forms/main/tools/tools.aardio index 2cb53b0..3d33574 100644 --- a/forms/main/tools/tools.aardio +++ b/forms/main/tools/tools.aardio @@ -3,23 +3,22 @@ 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=579;right=460;bottom=621;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=438;right=205;bottom=480;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=11}; -btnDeleteIconCache={cls="plus";text="修复桌面图标空白";left=26;top=485;right=269;bottom=527;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=17}; -btnDnsFlush={cls="plus";text="清空DNS缓存";left=26;top=202;right=412;bottom=244;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=296;right=262;bottom=338;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=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='\uF029';notify=1;textPadding={left=50};z=15}; -btnSshInstall={cls="plus";text="一键安装 Xray 服务端";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=10}; -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=12}; -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=13}; -btnUpdateSystemTime={cls="plus";text="同步系统时间( 修正 Xray 连接报错 )";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='\uF017';notify=1;textPadding={left=50};z=4}; -btnUpdateXrayCore={cls="plus";text="更新 Xray Core";left=26;top=108;right=269;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='\uF01A';notify=1;textPadding={left=50};z=6}; -btnUuid={cls="plus";text="UUID 生成工具";left=26;top=391;right=262;bottom=433;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=16}; -btnWubiLex={cls="plus";text="WIN10 五笔助手(仅830KB,自带五笔86、98、091、新世纪、郑码……)";left=26;top=532;right=661;bottom=574;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=7}; -btnYoutube={cls="plus";text="youtube 视频下载工具";left=26;top=249;right=262;bottom=291;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=8}; -lbCurrentProxyLocation={cls="static";left=245;top=74;right=729;bottom=101;color=32768;dl=1;dt=1;transparent=1;z=14}; -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=9} +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}; +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} ) /*}}*/ @@ -70,7 +69,7 @@ winform.btnUpdateSystemTime.oncommand = function(id,event){ winform.btnUpdateSystemTime.text = '时间已同步' winform.setTimeout( function(){ - winform.btnUpdateSystemTime.text = '同步系统时间( 修正 xray 连接报错 )' + winform.btnUpdateSystemTime.text = '同步系统时间( 修正 v2ray 连接报错 )' },2000) } else { @@ -93,22 +92,6 @@ winform.btnDnsFlush.oncommand = function(id,event){ winform.btnDnsFlush.disabledText = null; } -winform.btnUpdateXrayCore.skin(style.plainButton) -winform.btnUpdateXrayCore.oncommand = function(id,event){ - winform.btnUpdateXrayCore.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'}; - - import xray.core; - var versionTag = xray.core.updateCore(); - if( versionTag ){ - publish("uiCommand.restartXrayCore"); - winform.btnUpdateXrayCore.disabledText = null; - winform.msgOk("Xray Core 已更新到:" + versionTag,1500) - } - else { - winform.btnUpdateXrayCore.disabledText = null; - } -} - import process; winform.btnWubiLex.skin(style.plainButton) winform.btnWubiLex.oncommand = function(id,event){ @@ -172,7 +155,7 @@ winform.btnCreateLnk.oncommand = function(id,event){ import fsys.lnk; var lnk = fsys.lnk(); - lnk.description = "winXray(Xray/V2Ray、Shadowsocks、Trojan通用客户端 )" + lnk.description = "winXray(V2Ray/V2Ray、Shadowsocks、Trojan通用客户端 )" lnk.path = io._exepath //设置目标路径 lnk.setIcon(io._exepath,0); //设置图标 @@ -196,8 +179,8 @@ winform.btnTestSpeed.oncommand = function(id,event){ return; } - import xray.core; - if(!xray.core.socksProxyPort){ + import v2ray.core; + if(!v2ray.core.socksProxyPort){ winform.msgFrown('抱歉,当前未连接到任何代理服务器!'); return; } @@ -227,7 +210,7 @@ winform.btnTestSpeed.oncommand = function(id,event){ return null; } restClient.close(); - },xray.core.socksProxyPort + },v2ray.core.socksProxyPort ) if(!ipip){ @@ -239,7 +222,7 @@ winform.btnTestSpeed.oncommand = function(id,event){ winform.lbCurrentProxyLocation.text = ipip; import process - process.execute(chromePath,` --proxy-server="SOCKS5://127.0.0.1:`+xray.core.socksProxyPort + 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; } @@ -286,6 +269,8 @@ winform.btnDeleteIconCache.oncommand = function(id,event){ } } + + winform.enableDpiScaling(); winform.show(); win.loopMessage(); \ No newline at end of file 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/xray.aardio b/forms/main/v2ray.aardio similarity index 84% rename from forms/main/xray.aardio rename to forms/main/v2ray.aardio index f1f3f5f..68bde8c 100644 --- a/forms/main/xray.aardio +++ b/forms/main/v2ray.aardio @@ -3,10 +3,10 @@ import fonts.fontAwesome; /*DSG{{*/ var frmXray = win.form(text="winXray ";right=959;bottom=591;bgcolor=16777215) frmXray.add( -btnEditPac={cls="plus";text="编辑PAC";left=332;top=366;right=438;bottom=396;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=366;right=592;bottom=396;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}; +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=366;right=729;bottom=396;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}; +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}; @@ -23,15 +23,20 @@ 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 xray.core; +import v2ray.core; var currentOutboundIndex,currentOutboundAddress; -var activeOutbound = function(outboundIndex,outboundAddress,enableRetry){ +var activeOutbound = function(outboundIndex,outboundAddress,enableRetry,timerTesting){ + if(!outboundIndex && !outboundAddress){ outboundIndex,outboundAddress = currentOutboundIndex,currentOutboundAddress; - if(!outboundIndex && !outboundAddress) return; + if(!outboundIndex && !outboundAddress) { + return; + } } var outbound = config.proxy.outbounds[outboundIndex]; @@ -39,17 +44,16 @@ var activeOutbound = function(outboundIndex,outboundAddress,enableRetry){ return ; } - var currentTesting = false; - if( ! xray.core.isInboundPortChanged() ){ - currentTesting = currentOutboundIndex == outboundIndex && currentOutboundAddress == outboundAddress - } - - var startTesting = currentTesting; + + var startTesting = timerTesting; if(!startTesting){ - var started,err = xray.core.restart(frmXray.edit,outbound); + ..publish("activeOutbound",false); + + var started,err = v2ray.core.restart(frmXray.edit,outbound); startTesting = started; - if(err){ - frmXray.edit.print("启动 Xray 错误:",err); + if(!started){ + frmXray.edit.print("启动 V2Ray 错误",err:""); + frmXray.btnTcping.disabledText = null; return false; } } @@ -59,37 +63,43 @@ var activeOutbound = function(outboundIndex,outboundAddress,enableRetry){ frmXray.autoTesting = true; ..thread.invoke( - function(frmXray,outboundIndex,outboundAddress,sockProxyPort,httpProxyAddress,enableRetry,currentTesting){ + function(frmXray,outboundIndex,outboundAddress,sockProxyPort,httpProxyAddress,enableRetry,timerTesting){ import web.rest.client; var restClient = web.rest.client(,httpProxyAddress); restClient._http.setTimeouts(1000,2000,2000); - restClient.get("https://www.google.com/generate_204"); + var ret = restClient.get("https://www.google.com/generate_204"); var lastStatusCode = restClient.lastStatusCode; + if( lastStatusCode == 204 ){ - frmXray.onStartXrayComplete(outboundIndex,currentTesting,outboundAddress); + frmXray.onStartXrayComplete(outboundIndex,timerTesting,outboundAddress); return; } restClient.close(); - if(currentTesting){ - sleep(500); + if(timerTesting){ + sleep(100); } import inet.http; - if(inet.http.isAlive(,httpProxyAddress)){ - frmXray.onStartXrayComplete(outboundIndex,currentTesting,outboundAddress); + 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(currentTesting){ - sleep(500); + if(timerTesting){ + sleep(100); } import wsock.tcp.socks5Client; var client; for(i=1;2;1){ - sleep(500); + sleep(200); client = wsock.tcp.socks5Client("127.0.0.1",sockProxyPort); if(client)break; } @@ -112,14 +122,14 @@ Accept-Charset:utf-8; client.close(); if( rep && ..string.startWith(rep,"HTTP/1.1 ") ){ - frmXray.onStartXrayComplete(outboundIndex,currentTesting,outboundAddress); + frmXray.onStartXrayComplete(outboundIndex,timerTesting,outboundAddress); return; } } }; frmXray.onStartXrayFailed(outboundIndex,enableRetry,outboundAddress); },frmXray,outboundIndex,outboundAddress, - xray.core.socksProxyPort,xray.core.getHttpProxyAddress(),enableRetry,currentTesting + v2ray.core.socksProxyPort,v2ray.core.getSystemProxyConfig(),enableRetry,timerTesting ) return true; @@ -138,13 +148,13 @@ frmXray.autoUpdateSubscription = function(timeout){ autoUpdateSubscriptionTimerId = ..win.setTimeout(function(){ autoUpdateSubscriptionTimerId = null; - import xray.outbounds; - xray.outbounds.autoUpdateSubscription(); + import v2ray.outbounds; + v2ray.outbounds.autoUpdateSubscription(); },timeout:10000) } } -frmXray.onStartXrayComplete = function(outboundIndex,currentTesting,outboundAddress){ +frmXray.onStartXrayComplete = function(outboundIndex,timerTesting,outboundAddress){ frmXray.autoUpdateSubscription(-1); var outbound = config.proxy.outbounds[outboundIndex]; @@ -164,7 +174,7 @@ frmXray.onStartXrayComplete = function(outboundIndex,currentTesting,outboundAddr listview.activeOutboundIndex = outboundIndex; var address = listview.getItemText(outboundIndex,2); - if(!currentTesting) frmXray.edit.print("已切换到服务器:",address); + if(!timerTesting) frmXray.edit.print("已切换到服务器:",address); listview.activeOutboundAddress = address; if(listview.getItemText(outboundIndex,7)=="不可用"){ @@ -179,17 +189,16 @@ frmXray.onStartXrayComplete = function(outboundIndex,currentTesting,outboundAddr frmXray.validOutbounds = {}; frmXray.btnTcping.disabledText = null; - ..publish("activeOutbound",address); + ..publish("activeOutbound",address); } subscribe("activeOutbound",function(address){ ..globalActiveOutbound = address; } ) -frmXray.onStartXrayFailed = function(outboundIndex,enableRetry,outboundAddress){ +frmXray.onStartXrayFailed = function(outboundIndex,enableRetry,outboundAddress){ + ..publish("activeOutbound",false); - ..publish("activeOutbound",false); - var outbound = ..config.proxy.outbounds[outboundIndex]; if(!(outbound && (outbound.address == outboundAddress))){ return; @@ -226,6 +235,7 @@ frmXray.onStartXrayFailed = function(outboundIndex,enableRetry,outboundAddress){ } frmXray.btnTcping.disabledText = null; + } var tcping = function(frmXray,outboundIndex,outbound){ @@ -265,6 +275,7 @@ var retryOnNetworkAliveTimerId; frmXray.onTcpingFailed = function(){ frmXray.autoTesting = false; frmXray.btnTcping.disabledText = null; + ..publish("activeOutbound",false); if(retryOnNetworkAliveTimerId){ frmXray.clearTimeout(retryOnNetworkAliveTimerId); @@ -275,7 +286,8 @@ frmXray.onTcpingFailed = function(){ } else { retryOnNetworkAliveTimerId = frmXray.setInterval( - 1000,function(){ + 1000,function(){ + if(frmXray.listview.activeOutboundIndex){ retryOnNetworkAliveTimerId = null; return 0; @@ -302,12 +314,13 @@ frmXray.btnTcping.oncommand = function(id,event){ var items = frmXray.listview.items; if(#items){ frmXray.btnTcping.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'} - if(!xray.core.getPath()){ - frmXray.btnTcping.disabledText = null; - frmXray.msgErr("下载 xray.exe 失败") - return; - } + 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)){ @@ -380,7 +393,7 @@ frmXray.btnTcping.oncommand = function(id,event){ } else { if(id) frmXray.msgWarn("请先添加服务器") - xray.core.stop(); + v2ray.core.stop(); frmXray.btnTcping.disabledText = null; frmXray.autoTesting = false; @@ -388,11 +401,11 @@ frmXray.btnTcping.oncommand = function(id,event){ } } -import xray.core; -import xray.pacServer; +import v2ray.core; +import v2ray.pacServer; frmXray.onDestroy = function(){ - xray.core.stop(); - xray.pacServer.stop(); + v2ray.core.stop(); + v2ray.pacServer.stop(); } var pingThread = function( ip,frmXray ) { @@ -453,11 +466,11 @@ var removeOutbounds = function(selectedItems){ publish("outbounds.updateConfigJson"); if(activeIndex && (!frmXray.listview.activeOutboundIndex) ){ - frmXray.btnTcping.oncommand(); + if(!v2ray.core.lastDownloadingCoreFailed) frmXray.btnTcping.oncommand(); } } -import xray.outbounds; +import v2ray.outbounds; frmXray.listview.onnotify = function(id,code,ptr){ select(code) { case 0xFFFFFFF4/*_NM_CUSTOMDRAW*/ { @@ -491,6 +504,8 @@ frmXray.listview.onnotify = function(id,code,ptr){ 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); @@ -512,13 +527,17 @@ frmXray.listview.onnotify = function(id,code,ptr){ 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){ - xray.outbounds.updateSubscription(); + v2ray.outbounds.updateSubscription(); }); popmenu.add(); @@ -541,7 +560,7 @@ frmXray.listview.onnotify = function(id,code,ptr){ function(id){ ..config.__loadDefaultOutbounds(); publish("outbounds.updateConfigJson"); - publish("uiCommand.restartXrayCore"); + publish("uiCommand.restartV2RayCore"); } ); popmenu.add(); @@ -562,6 +581,8 @@ frmXray.listview.onnotify = function(id,code,ptr){ 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); @@ -576,29 +597,15 @@ frmXray.listview.onnotify = function(id,code,ptr){ activeOutbound(currentIdx,frmXray.listview.getItemText(currentIdx,2),false) } }); + + 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.add("编辑 / 新增代理服务器",function(id){ + var frmOutbound = frmXray.loadForm("\forms\main\outbound.aardio"); + frmOutbound.setOutboundConfig(config.proxy.outbounds[currentIdx]); + frmOutbound.doModal() }); - popmenu.check(id,autoConnect,0/*_MF_BYCOMMAND*/); - - popmenu.add(); - popmenu.add("自剪贴板批量导入分享链接、订阅源",function(id){ frmXray.btnImportServerFromClipBd.oncommand(); @@ -623,18 +630,37 @@ frmXray.listview.onnotify = function(id,code,ptr){ popmenu.add('更新当前订阅源'+ps,function(id){ if(currentIdx){ - xray.outbounds.updateSubscription({[subscribeUrl]=true}); + v2ray.outbounds.updateSubscription({[subscribeUrl]=true}); } }); } popmenu.add('更新所有订阅源',function(id){ if(currentIdx){ - xray.outbounds.updateSubscription(); + 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); @@ -656,19 +682,19 @@ frmXray.listview.onnotify = function(id,code,ptr){ function(id){ ..config.__loadDefaultOutbounds(); publish("outbounds.updateConfigJson"); - publish("uiCommand.restartXrayCore"); + publish("uiCommand.restartV2RayCore"); } - ); + ); if(#selectedItems==1){ popmenu.add(); popmenu.add('生成二维码',function(id){ if(currentIdx){ - import xray.outbounds; + import v2ray.outbounds; import win.clip; - var str = xray.outbounds.exportSharedLinks({config.proxy.outbounds[currentIdx]}); + var str = v2ray.outbounds.exportSharedLinks({config.proxy.outbounds[currentIdx]}); if(str){ var frmChild = frmXray.loadForm("\forms\main\tools\qr.aardio"); frmChild.createQrCode(str); @@ -679,33 +705,17 @@ frmXray.listview.onnotify = function(id,code,ptr){ popmenu.add('复制服务器分享链接',function(id){ if(currentIdx){ - import xray.outbounds; + import v2ray.outbounds; import win.clip; - var str = xray.outbounds.exportSharedLinks({config.proxy.outbounds[currentIdx]}); + var str = v2ray.outbounds.exportSharedLinks({config.proxy.outbounds[currentIdx]}); if(str){ win.clip.write(str); frmXray.edit.print("已复制链接:",str); } } }); - - popmenu.add('复制服务器地址',function(id){ - if(currentIdx){ - import win.clip; - win.clip.write(config.proxy.outbounds[currentIdx].address + ":" + config.proxy.outbounds[currentIdx].port); - frmXray.edit.print("已复制服务器地址:",config.proxy.outbounds[currentIdx].address + ":" + config.proxy.outbounds[currentIdx].port); - } - }); - popmenu.add('复制服务器 JSON 配置',function(id){ - if(currentIdx){ - import win.clip; - import web.json; - var str = web.json.stringify(config.proxy.outbounds[currentIdx],true,false); - win.clip.write(str); - frmXray.edit.print(str); - } - }); + popmenu.add(); var toolMenu = win.ui.popmenu(frmXray) @@ -739,8 +749,16 @@ frmXray.listview.onnotify = function(id,code,ptr){ 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("服务器工具",toolMenu) popmenu.add('SSH 登录服务器',function(id){ if(currentIdx){ @@ -753,16 +771,7 @@ frmXray.listview.onnotify = function(id,code,ptr){ + config.proxy.outbounds[currentIdx].address + ":" + (config.proxy.outbounds[currentIdx].sshPort||22)); } - }); - - if(config.proxy.outbounds[currentIdx].port == 443 && config.proxy.outbounds[currentIdx].tls){ - popmenu.add('浏览 HTTPS 主页 ...',function(id){ - if(currentIdx){ - process.openUrl("https" ++ "://" + config.proxy.outbounds[currentIdx].address); - } - }); - popmenu.add(); - } + }); } popmenu.popup(x,y,true); } @@ -873,7 +882,7 @@ 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.restartXrayCore",function(){ +subscribe("uiCommand.restartV2RayCore",function(){ config.proxy.outbounds.fields = {"protocol";"address";"port";"security";"network";"ps";} var outbounds = config.proxy.outbounds; @@ -884,7 +893,7 @@ subscribe("uiCommand.restartXrayCore",function(){ } frmXray.listview.setTable(outbounds); - frmXray.btnTcping.oncommand(); + if(!v2ray.core.lastDownloadingCoreFailed) frmXray.btnTcping.oncommand(); } ) import process; @@ -901,7 +910,7 @@ if(#config.proxy.outbounds){ frmXray.setTimeout( function(){ - publish("uiCommand.restartXrayCore"); + publish("uiCommand.restartV2RayCore"); },1000 ); } @@ -913,9 +922,11 @@ subscribe("sysProxy.modeChanged",function(mode){ 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; @@ -940,8 +951,19 @@ frmXray.radioProxy.oncommand = switchProxyMode; frmXray.radioProxyDirect.oncommand = switchProxyMode; import win.dlg.message; -frmXray.btnEditPac.skin(style.plainButton) -frmXray.btnEditPac.oncommand = function(id,event){ +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*/ ); @@ -953,14 +975,14 @@ frmXray.btnEditPac.oncommand = function(id,event){ frmPac.show(); } subscribe("uiCommand.showPacForm",function(...){ - frmXray.btnEditPac.oncommand(); + frmXray.btnEditPacOrUwp.oncommand(); } ) subscribe("uiCommand.print",function(...){ frmXray.edit.print(...); } ) -import xray.outbounds; +import v2ray.outbounds; frmXray.btnImportServerFromClipBd.skin(style.plainButton) frmXray.btnImportServerFromClipBd.oncommand = function(id,event){ var str = ..win.clip.read(); @@ -973,21 +995,21 @@ frmXray.btnImportServerFromClipBd.oncommand = function(id,event){ str = "https://github.com" + str; } - xray.outbounds.updateSubscription({[str]=true}); + v2ray.outbounds.updateSubscription({[str]=true}); return; } - var outbounds = xray.outbounds.importFromString(str); + var outbounds = v2ray.outbounds.importFromString(str); if(#outbounds){ ..table.append(config.proxy.outbounds,outbounds); - publish("uiCommand.restartXrayCore"); + 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://,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条规定的配置或分享链接。') + 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; @@ -1002,7 +1024,9 @@ frmXray.chkAutoTest.oncommand = function(id,event){ import inet.http; testTimerId = frmXray.setInterval( config.proxy.testInterval*1000,function(){ - if( frmXray.autoTesting ) return; + if(frmXray.btnTcping.disabled) return; + if( frmXray.autoTesting ) return; + var idx = frmXray.listview.activeOutboundIndex; var address = frmXray.listview.activeOutboundAddress; if( !( idx&&address) ){ @@ -1010,12 +1034,12 @@ frmXray.chkAutoTest.oncommand = function(id,event){ return config.proxy.testInterval*1000; } - frmXray.btnTcping.oncommand(); + if(!v2ray.core.lastDownloadingCoreFailed) frmXray.btnTcping.oncommand(); return; } frmXray.autoTesting = true; - activeOutbound(idx,address,true); + activeOutbound(idx,address,true,true); return config.proxy.testInterval*1000; } diff --git a/lib/config.aardio b/lib/config.aardio index 23be8cc..0b3eecb 100644 --- a/lib/config.aardio +++ b/lib/config.aardio @@ -5,11 +5,11 @@ config = fsys.config( io.appData("/winXray/") ); namespace config { __appName = "winXray"; __loadDefaultOutbounds = function(){ - import xray.outbounds; - var serverData = ..string.load("/xray-core/winXray-default-servers.json") - : $"/xray-core/winXray-default-servers.json" + import v2ray.outbounds; + var serverData = ..string.load("/v2ray-core/winXray-default-servers.json") + : $"/v2ray-core/winXray-default-servers.json" - proxy.outbounds = ..xray.outbounds.importFromString(..string.removeBom(serverData)); + proxy.outbounds = ..v2ray.outbounds.importFromString(..string.removeBom(serverData)); ..publish("outbounds.updateConfigJson",) } @@ -21,7 +21,10 @@ namespace config { if(!config.proxy.mode) config.proxy.mode = "pac"; if(!config.proxy.pacPort) config.proxy.pacPort = 0; if(config.proxy.useHttpGlobal===null){ - config.proxy.useHttpGlobal = !_WIN10_LATER; + config.proxy.useHttpGlobal = true; +} +if(config.proxy.useSocksPac===null){ + config.proxy.useSocksPac = _WIN10_LATER; } if(config.proxy.enableGitConfigGithub===null){ @@ -50,6 +53,10 @@ if(!config.proxy.subscribeUrls){ } } +if(!config.proxy.hotkey){ + config.proxy.hotkey = {1/*_MOD_ALT*/|2/*_MOD_CONTROL*/|4/*_MOD_SHIFT*/;'P'#} +} + config.__resetDefaultCore = function(){ config.core.default = { inbounds={ diff --git a/lib/sysProxy.aardio b/lib/sysProxy.aardio index 13c5423..016c3fe 100644 --- a/lib/sysProxy.aardio +++ b/lib/sysProxy.aardio @@ -1,37 +1,37 @@ //sysProxy 系统代理 import config; import inet.conn; -import xray.github; -import xray.pacServer; +import v2ray.github; +import v2ray.pacServer; namespace sysProxy; switch = function(mode){ ..config.proxy.mode = mode : "direct"; ..config.proxy.save(); - + if(mode=="pac"){ - var pacUrl = ..xray.pacServer.getUrl(); + var pacUrl = ..v2ray.pacServer.getUrl(); if(pacUrl){ - ..inet.conn.setProxyAutoConfig(,pacUrl ); + ..inet.conn.setProxyAutoConfig(,pacUrl ); } else { - ..xray.pacServer.restart(); + ..v2ray.pacServer.restart(); } - ..xray.github.setProxy(true); + ..v2ray.github.setProxy(true); } elseif(mode=="proxy"){ - import xray.core; - var address = xray.core.getHttpProxyAddress(); + import v2ray.core; + var address = v2ray.core.getSystemProxyConfig(); if(address){ ..inet.conn.setProxy(,address); - ..xray.github.setProxy(true); + ..v2ray.github.setProxy(true); } } else { ..inet.conn.setProxy(); - ..xray.github.setProxy(false); + ..v2ray.github.setProxy(false); } ..publish("sysProxy.modeChanged",mode) } @@ -48,11 +48,23 @@ 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(); - ..xray.github.setProxy(false); + ..v2ray.github.setProxy(false); } return; } @@ -67,7 +79,7 @@ reset = function(proxy){ } } ) -..subscribe("xrayCore.restarted",function(socksProxyPort,httpProxPort){ +..subscribe("v2RayCore.restarted",function(socksProxyPort,httpProxPort){ if(..config.proxy.mode != "direct"){ reset(true); } 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/xray/core/configJson.aardio b/lib/v2ray/core/configJson.aardio similarity index 83% rename from lib/xray/core/configJson.aardio rename to lib/v2ray/core/configJson.aardio index 9490b20..5d54800 100644 --- a/lib/xray/core/configJson.aardio +++ b/lib/v2ray/core/configJson.aardio @@ -1,10 +1,10 @@ -//configJson 启动配置 +//configJson 内核配置 import config; import web.json; import inet.url; import crypt; -namespace xray.core.configJson; +namespace v2ray.core.configJson; write = function(jsonPath,outbound,sockPort,httpPort){ if(!outbound){ return; } @@ -22,6 +22,11 @@ write = function(jsonPath,outbound,sockPort,httpPort){ inbounds[1].port = sockPort; if(inbounds[2]){ inbounds[2].port = httpPort; } + + if(sockPort<0){ + ..table.shift(inbounds); + } + if(#outbound.tls && !outbound.sni){ var host = outbound.host; if(..table.isArray(host)){ host = host[1] } @@ -340,7 +345,7 @@ write = function(jsonPath,outbound,sockPort,httpPort){ address=outbound.address; level=outbound.level : 0; method=outbound.security; - ota=false; + ota=!!outbound.ota; password=outbound.id; port=outbound.port; } @@ -354,6 +359,88 @@ write = function(jsonPath,outbound,sockPort,httpPort){ ..table.assign(current.outbounds[1],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(current.outbounds[1],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(current.outbounds[1],ob); + } ..string.save(jsonPath,..web.json.stringify(current) ); return jsonPath; 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/xray/github.aardio b/lib/v2ray/github.aardio similarity index 94% rename from lib/xray/github.aardio rename to lib/v2ray/github.aardio index 1e08512..7f94965 100644 --- a/lib/xray/github.aardio +++ b/lib/v2ray/github.aardio @@ -1,7 +1,7 @@ //github 代理设置 -import xray.core; +import v2ray.core; import process.popen; -namespace xray.github; +namespace v2ray.github; setProxy = function(enableProxy){ if(enableProxy===null){ @@ -12,7 +12,7 @@ setProxy = function(enableProxy){ } } - var socksPort = ..xray.core.socksProxyPort; + var socksPort = ..v2ray.core.socksProxyPort; if(!socksPort && enableProxy) return; var git; diff --git a/lib/xray/outbounds.aardio b/lib/v2ray/outbounds.aardio similarity index 71% rename from lib/xray/outbounds.aardio rename to lib/v2ray/outbounds.aardio index 5271ef3..032b56e 100644 --- a/lib/xray/outbounds.aardio +++ b/lib/v2ray/outbounds.aardio @@ -3,8 +3,9 @@ import web.json; import inet.url; import win.clip; import crypt; +import crypt.bin; -namespace xray.outbounds; +namespace v2ray.outbounds; exportSharedLinks = function(outbounds){ var outString = {}; @@ -31,8 +32,37 @@ exportSharedLinks = function(outbounds){ 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 = outbound.protocol + "://" + outbound.id + "@" + outbound.address + ":" + outbound.port; + 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; @@ -50,8 +80,10 @@ exportSharedLinks = function(outbounds){ ..table.push(outString,trojan); } elseif(outbound.protocol == "vless"){ - var vless = "vless://" + outbound.id + "@" + outbound.address + ":" + outbound.port; - + 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; @@ -76,6 +108,65 @@ exportSharedLinks = function(outbounds){ } ..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'); @@ -185,6 +276,7 @@ importFromString = function(str,subscribeUrl){ 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); @@ -209,7 +301,7 @@ importFromString = function(str,subscribeUrl){ return inet.http().get(subscribeUrl); },subscribeUrl ) - + form.close(); if(!str){ return; @@ -250,8 +342,8 @@ importFromString = function(str,subscribeUrl){ var crc32 = ..string.crc32(str); _subscriptionResponseCache[subscribeUrl] = crc32; } - - if(..string.match(str,"^[\w=+/-_]+$")){ + + if(..string.match(str,"^\s*[\w=+/-_]+\s*$")){ str = ..crypt.decodeBin(str); if(!str) return; } @@ -270,7 +362,7 @@ importFromString = function(str,subscribeUrl){ continue; } - var vmess2 = ..string.match(line,`vmess\:\/\/[^\@\s]+\@[^\?\#\s\:]+\:\d+\S*`); + 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){ @@ -297,7 +389,9 @@ importFromString = function(str,subscribeUrl){ if(info.security) outbound.tls = info.security; if(info.flow) outbound.flow = info.flow; - if(info.allowInsecure!==null) outbound.allowInsecure = info.allowInsecure; + 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; } @@ -313,8 +407,8 @@ importFromString = function(str,subscribeUrl){ continue; } - var vmess = ..string.match(line,`vmess\:\/\/([\w=+]+)`); - if( vmess ) { + var vmess = ..string.match(line,`vmess\:\/\/([\w=+/-_]+)`); + if( vmess ) { var json = ..crypt.decodeBin(vmess); var outbound = ..web.json.tryParse(json); if(type(outbound)=="table"){ @@ -345,9 +439,9 @@ importFromString = function(str,subscribeUrl){ } continue; - } + } - var vless = ..string.match(line,`vless\:\/\/[^\@\s]+\@[^\?\#\s\:]+\:\d+\S*`); + var vless = ..string.match(line,`vless\:\/\/\S+`); if( vless ) { var vlessUrl = ..inet.url.split(vless) if(vlessUrl.user && vlessUrl.host && vlessUrl.port){ @@ -374,7 +468,9 @@ importFromString = function(str,subscribeUrl){ if(info.security) outbound.tls = info.security; if(info.flow) outbound.flow = info.flow; - if(info.allowInsecure!==null) outbound.allowInsecure = info.allowInsecure; + 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; } @@ -394,13 +490,13 @@ importFromString = function(str,subscribeUrl){ if( ss ) { var userinfo,address,port = ..string.match(ss,"^([^:]+)\@(.+)\:(\d+)") if(!(userinfo&&address&&port)){ - var str = ..crypt.decodeBin(ss); + var str = ..crypt.bin.decodeUrlBase64(ss); if(str){ ss = str; } method,password,address,port = ..string.match(ss,"^(.+)\:(.+)\@(.+)\:(\d+)") } else { - userinfo = ..crypt.decodeBin(userinfo); + userinfo = ..crypt.bin.decodeUrlBase64(userinfo); if(userinfo){ method,password = ..string.match(userinfo,"^(.+)\:(.+)$") } @@ -440,10 +536,10 @@ importFromString = function(str,subscribeUrl){ continue; } - var trojan = ..string.match(line,`trojan\:\/\/[^\@\s]+\@[^\?\#\s\:]+\:\d+\S*`); + var trojan = ..string.match(line,`trojan\:\/\/\S+`); if( trojan ) { var trojanUrl = ..inet.url.split(trojan) - if(trojanUrl.user && trojanUrl.host && trojanUrl.port){ + if(trojanUrl.user && trojanUrl.host){ var outbound = { address = trojanUrl.host; port = tonumber(trojanUrl.port) : 443; @@ -480,10 +576,10 @@ importFromString = function(str,subscribeUrl){ continue; } - var trojan = ..string.match(line,`trojan-go\:\/\/[^\@\s]+\@[^\?\#\s\:]+\:\d+\S*`); + var trojan = ..string.match(line,`trojan-go\:\/\/\S+`); if( trojan ) { var trojanUrl = ..inet.url.split(trojan) - if(trojanUrl.user && trojanUrl.host && trojanUrl.port){ + if(trojanUrl.user && trojanUrl.host){ var outbound = { address = trojanUrl.host; port = tonumber(trojanUrl.port) : 443; @@ -496,7 +592,10 @@ importFromString = function(str,subscribeUrl){ var info = ..inet.url.splitParameters(trojanUrl.extraInfo); outbound.sni = info.sni || info.peer; outbound.host = info.host; - outbound.path = info.path; + 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; @@ -518,6 +617,144 @@ importFromString = function(str,subscribeUrl){ 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 ) { @@ -525,7 +762,15 @@ importFromString = function(str,subscribeUrl){ if(type(outbound)=="table"){ if(outbound.type){ if(outbound.type=="ssr"){ - continue; + 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"){ @@ -578,6 +823,9 @@ validAll = function(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; @@ -777,7 +1025,7 @@ updateSubscription = function(outbondSubscribeUrlMap){ var count = 0; for(url,data in outbondSubscribeUrlMap){ - var impOutbounds = ..xray.outbounds.importFromString(url); + var impOutbounds = ..v2ray.outbounds.importFromString(url); if(#impOutbounds){ for(i=#cfgOutbounds;1;-1){ var outbound = cfgOutbounds[i] @@ -793,7 +1041,7 @@ updateSubscription = function(outbondSubscribeUrlMap){ ..config.proxy.save(); ..publish("outbounds.updateConfigJson"); - ..publish("uiCommand.restartXrayCore",cfgOutbounds) + ..publish("uiCommand.restartV2RayCore",cfgOutbounds) ..mainForm.msgOk("已刷新" + count + "个订阅服务器。",1500); return count; @@ -825,8 +1073,8 @@ autoUpdateSubscription = function(){ var http = inet.http(); for(url,v in outbondSubscribeUrlMap){ - if( string.indexOf(subscribeUrl,"github.com") - || string.indexOf(subscribeUrl,"raw.githubusercontent.com") + if( string.indexOf(url,"github.com") + || string.indexOf(url,"raw.githubusercontent.com") ){ outbondSubscribeUrlMap[url] = web.rest.github.getContent(url) } @@ -850,13 +1098,22 @@ autoUpdateSubscription = function(){ ) } +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 = ..xray.outbounds.importFromString(data,url); + var impOutbounds = ..v2ray.outbounds.importFromString(data,url); if(#impOutbounds){ for(i=#cfgOutbounds;1;-1){ var outbound = cfgOutbounds[i] @@ -878,11 +1135,11 @@ autoUpdateSubscription = function(){ ..config.proxy.save(); ..publish("outbounds.updateConfigJson"); - ..publish("uiCommand.restartXrayCore") + ..publish("uiCommand.restartV2RayCore") ..publish("uiCommand.print","已自动刷新" + count + "个订阅服务器。") } ) -/**intellisense(xray.outbounds) +/**intellisense(v2ray.outbounds) exportSharedLinks(.(outbounds) = 导出分享链接 importFromString(.(str,subscribeUrl) = 导入分享链接 importFromClipboard() = 自剪贴板导入分享链接 diff --git a/lib/xray/pacServer.aardio b/lib/v2ray/pacServer.aardio similarity index 82% rename from lib/xray/pacServer.aardio rename to lib/v2ray/pacServer.aardio index bf90676..ad61015 100644 --- a/lib/xray/pacServer.aardio +++ b/lib/v2ray/pacServer.aardio @@ -4,11 +4,12 @@ import wsock.tcp.simpleHttpServer; import inet.http; import inet.url; -namespace xray.pacServer; +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"]]){ @@ -16,11 +17,23 @@ $serverMain = ..wsock.tcp.simpleHttpServer.mainThread( 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 +"'"); - if(useHttpProxy.get()){ + 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); } } @@ -48,7 +61,7 @@ savePacText = function(json){ var inboundPort = ..thread.var(); var useHttpProxy = ..thread.var(); restart = function(){ - useHttpProxy.set(..config.proxy.useHttpGlobal); + useHttpProxy.set(!..config.proxy.useSocksPac); $serverMain.threadGlobal = { inboundPort = inboundPort; @@ -94,7 +107,7 @@ updateConfig = function(socksProxyPort,httpProxyPort){ } } -..subscribe("xrayCore.restarted",function(socksProxyPort,httpProxyPort){ +..subscribe("v2RayCore.restarted",function(socksProxyPort,httpProxyPort){ updateConfig(socksProxyPort,httpProxyPort); } ) @@ -119,7 +132,7 @@ getPort = function(){ } -/**intellisense(xray.pacServer) +/**intellisense(v2ray.pacServer) stop() = 停止PAC服务器 restart() = 重启PAC服务器 getUrl(.(localIp) = 返回PAC服务地址 diff --git a/lib/xray/core/_.aardio b/lib/xray/core/_.aardio deleted file mode 100644 index 33a7bc2..0000000 --- a/lib/xray/core/_.aardio +++ /dev/null @@ -1,182 +0,0 @@ -//core 代理服务 -import wsock.tcp.server; -import process.popen; -import config; - -namespace xray.core; - -socksProxyPort = null; -httpProxPort = null; - -getHttpProxyAddress = 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 prcsXray; -import process.job.limitKill; -restart = function(editor,outbound){ - if(!outbound){ return null,"错误的出站代理服务器配置" } - if(_WINXP){ - return null,"抱歉!Xray 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(prcsXray){ - prcsXray.terminate(); - prcsXray = null; - } - - 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) } - - var corePath = getPath(editor.hwnd); - if(!corePath){ return false,"启动失败,未找到xray.exe"; } - - import xray.core.configJson; - var jsonPath,err = ..xray.core.configJson.write( - ..io.joinpath(..io.splitpath(corePath).dir,"config.json") - ,outbound,socksProxyPort,httpProxPort); - if(!jsonPath){ - return false,err:"启动失败,写入配置文件遇到错误!"; - } - - ..publish("activeOutbound",false); - - import sysProxy; - ..sysProxy.reset(false); - - var err; - prcsXray,err = ..process.popen(corePath,"-c=config.json" ); - if(!prcsXray){ - ..publish("uiCommand.print",err:"启动 Xray Core 时遇到未知错误!"); - - if(!..process().isWow64()){ - if(..process.isExe(corePath)!="PE32"){ - ..io.remove(corePath); - if(!..io.exist(corePath)){ - ..publish("uiCommand.print","当前操作系统是32位,已删除无效的64位 Xray Core,正在下载32位 Xray Core"); - return restart(editor,outbound) - } - else { - ..publish("uiCommand.print","当前操作系统是32位,但是找到的 Xray Core 是64位,请重新下载32位 Xray Core"); - } - } - } - - return; - } - prcsXray.assignToJobObject(process.job.limitKill); - prcsXray.codepage = 65001; - prcsXray.logResponse(editor); - - inbounds[1].port = socksProxyPort; - inbounds[2].port = httpProxPort; - ..config.core.save(); - - ..publish("uiCommand.print","已启动代理服务器,SOCKS端口:" + socksProxyPort + " HTTP端口:" + httpProxPort) - ..publish("xrayCore.restarted",socksProxyPort,httpProxPort); - return true; -} - -stop = function(){ - if(prcsXray){ - prcsXray.terminate(); - prcsXray = null; - } - - ..sysProxy.reset(false); - - import xray.github; - xray.github.setProxy(false); -} - -var getXrayCoreUrl = function(){ - 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) return; - - return "https://github.com/XTLS/Xray-core/releases/download/" - + tag + "/xray-windows-" + (..process().isWow64() ? "64" : "32") + ".zip",tag -} - -getPath = function(hwnd){ - var path = ..io.fullpath("/xray-core/xray.exe"); - if(..io.exist(path)){ - return path; - } - - var path = ..io.appData("/xray/core/xray.exe"); - if(..io.exist(path)){ - return path; - } - - var url = getXrayCoreUrl(); - if(!url) return null; - - import zlib.httpFile; - if( ..zlib.httpFile.download(url,"正在下载 Xray Core" - ,..io.appData("/xray/download/") - ,..io.appData("/xray/core/"),,hwnd) ) - return ..io.exist(path); -} - -updateCore = function(){ - var coreDir = ..io.exist("/xray-core/xray.exe") ? ..io.fullpath("/xray-core/"); - if(!coreDir){ - coreDir = ..io.appData("/xray/core/"); - } - - var url,versionTag = getXrayCoreUrl(); - if(!url) return null; - - import fsys; - fsys.delete(..io.appData("/xray/temp/")) - - import zlib.httpFile; - if( ..zlib.httpFile.download(url,"正在下载 Xray Core" - ,..io.appData("/xray/download/") - ,..io.appData("/xray/temp/"),,..mainForm.hwnd) ){ - if(..io.exist(..io.appData("/xray/temp/xray.exe"))){ - import sysProxy; - sysProxy.reset(false); - - import process.file; - process.file.terminate(..io.joinpath(coreDir,"xray.exe")); - fsys.copy(..io.appData("/xray/temp/xray.exe"),..io.joinpath(coreDir,"xray.exe")); - - return versionTag; - } - } -} - -/**intellisense(xray.core) -socksProxyPort = SOCKS代理端口 -httpProxPort = HTTP代理端口 -isInboundPortChanged() = 是否已变更代理端口配置 -restart(.(editor,outbound) = 重启启动 Xray 服务进程 -end intellisense**/ diff --git a/main.aardio b/main.aardio index 8ab304b..8396f2f 100644 --- a/main.aardio +++ b/main.aardio @@ -3,6 +3,10 @@ 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; @@ -143,23 +147,21 @@ else { import fsys.update.simpleMain; if( fsys.update.simpleMain( - "winXray(Xray/V2Ray、Shadowsocks、Trojan通用客户端 )", - process().isWow64() ? "https://raw.githubusercontent.com/winXray/winXray/master/release/update/version.txt" - : "https://raw.githubusercontent.com/winXray/winXray/master/release/update32/version.txt", + "winXray(V2Ray/V2Ray、Shadowsocks、Trojan通用客户端 )", + "https://raw.githubusercontent.com/winXray/winXray/master/release/update/version.txt", ..io.appData("/winXray/update"), - function(version,description,status){})){ + 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 2.3";left=67;top=9;right=727;bottom=27;align="left";color=6052956;dl=1;dt=1;font=LOGFONT(h=-14);z=7}; +caption={cls="bkplus";text="winXray 3.7";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}; @@ -178,12 +180,6 @@ if(!atom){ return; } -import xray.core; -if(!xray.core.getPath()) { - mainForm.close(); - return; -} - import win.ui.simpleWindow; win.ui.simpleWindow( mainForm ); @@ -212,12 +208,13 @@ tbs.skin({ } }) -tbs.loadForm(1,"\forms\main\xray.aardio" ); +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){ @@ -225,16 +222,14 @@ mainForm.wndproc = { win.setForeground(mainForm.hwnd) mainForm.popmenu = win.ui.popmenu(mainForm); mainForm.popmenu.add('自动切换到最快的服务器',function(id){ - publish("uiCommand.restartXrayCore",) + publish("uiCommand.restartV2RayCore",) }); mainForm.popmenu.add('立即更新所有订阅源',function(id){ - xray.outbounds.updateSubscription(); + v2ray.outbounds.updateSubscription(); }); mainForm.popmenu.add(); - import sysProxy; - import xray.core; - + import v2ray.core; var id = mainForm.popmenu.add('不使用代理',function(id){ sysProxy.switch("direct"); }); @@ -252,10 +247,22 @@ mainForm.wndproc = { mainForm.popmenu.add(); - var id = mainForm.popmenu.add('编辑 PAC 配置',function(id){ + 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){ @@ -286,13 +293,12 @@ mainForm.wndproc = { process.openUrl("https://github.com/search?q=winXray+license%3AUnlicense+fork%3Atrue+sort%3Aupdated") }); - import xray.core; import chrome.path; var chromePath = chrome.path(); - if(chromePath && xray.core.socksProxyPort){ + if(chromePath && v2ray.core.socksProxyPort){ mainForm.popmenu.add('使用 SOCKS5 代理打开浏览器',function(id){ import process - process.execute(chromePath,` --proxy-server="SOCKS5://127.0.0.1:`+xray.core.socksProxyPort + 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`); }); } @@ -320,8 +326,6 @@ mainForm.wndproc = { } } -mainForm.enableDpiScaling(); - mainForm.onDestroy = function(){ mainForm.tray.delete(); } @@ -344,4 +348,32 @@ 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 index a5e25c7..a63f623 100644 --- a/pac.txt +++ b/pac.txt @@ -1,4 +1,4 @@ -/** +/** * genpac 2.1.0 https://github.com/JinnLynn/genpac * GFWList Last-Modified: 2020-10-21 00:11:38 */ @@ -87,7 +87,21 @@ var rules = [ "zhongsou.com" ], [ - "raw.githubusercontent.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", @@ -226,6 +240,7 @@ var rules = [ "acevpn.com", "acg18.me", "acgkj.com", + "acgnx.se", "acmedia365.com", "acmetoy.com", "acnw.com.au", @@ -940,6 +955,7 @@ var rules = [ "circlethebayfortibet.org", "cirosantilli.com", "citizencn.com", + "citizenlab.ca", "citizenlab.org", "citizenscommission.hk", "citizensradio.org", @@ -1916,6 +1932,7 @@ var rules = [ "golang.org", "goldbet.com", "goldbetsports.com", + "golden-ages.org", "goldeneyevault.com", "goldenfrog.com", "goldjizz.com", @@ -2209,6 +2226,7 @@ var rules = [ "gtricks.com", "gts-vpn.com", "gtv.org", + "gtv1.org", "gu-chu-sum.org", "guaguass.com", "guaguass.org", @@ -2400,6 +2418,7 @@ var rules = [ "hongkongfp.com", "hongmeimei.com", "hongzhi.li", + "honven.xyz", "hootsuite.com", "hoovers.com", "hopedialogue.org", @@ -2499,6 +2518,7 @@ var rules = [ "iask.ca", "iav19.com", "ibiblio.org", + "ibit.am", "iblist.com", "iblogserv-f.net", "ibros.org", @@ -2736,6 +2756,7 @@ var rules = [ "jobso.tv", "joinbbs.net", "joinmastodon.org", + "joins.com", "journalchretien.net", "journalofdemocracy.org", "joymiihub.com", @@ -2851,6 +2872,7 @@ var rules = [ "kurtmunger.com", "kusocity.com", "kwcg.ca", + "kwok7.com", "kwongwah.com.my", "kxsw.life", "kyofun.com", @@ -2868,6 +2890,7 @@ var rules = [ "lamenhu.com", "lamnia.co.uk", "lamrim.com", + "landofhope.tv", "lanterncn.cn", "lantosfoundation.org", "laod.cn", @@ -2903,6 +2926,7 @@ var rules = [ "lester850.info", "letou.com", "letscorp.net", + "letsencrypt.org", "levyhsu.com", "lflink.com", "lflinkup.com", @@ -2998,6 +3022,7 @@ var rules = [ "lsmwebcast.com", "lsxszzg.com", "ltn.com.tw", + "luckydesigner.space", "luke54.com", "luke54.org", "lupm.org", @@ -3527,6 +3552,7 @@ var rules = [ "ogaoga.org", "ogate.org", "ohchr.org", + "ohmyrss.com", "oikos.com.tw", "oiktv.com", "oizoblog.com", @@ -4024,6 +4050,7 @@ var rules = [ "rsf-chinese.org", "rsf.org", "rsgamen.org", + "rsshub.app", "rssing.com", "rssmeme.com", "rtalabel.org", @@ -4088,10 +4115,10 @@ var rules = [ "scramble.io", "scribd.com", "scriptspot.com", - "seapuff.com", "search.com", "search.xxx", "searchtruth.com", + "searx.me", "seatguru.com", "secretchina.com", "secretgarden.no", @@ -4393,6 +4420,7 @@ var rules = [ "stoweboyd.com", "stranabg.com", "straplessdildo.com", + "streamate.com", "streamingthe.net", "streema.com", "streetvoice.com", @@ -4569,6 +4597,7 @@ var rules = [ "thegay.com", "thegioitinhoc.vn", "thegly.com", + "theguardian.com", "thehots.info", "thehousenews.com", "thehun.net", @@ -5452,6 +5481,7 @@ var rules = [ "yangjianli.com", "yasni.co.uk", "yayabay.com", + "ycombinator.com", "ydy.com", "yeahteentube.com", "yecl.net", @@ -5502,6 +5532,7 @@ var rules = [ "yourtrap.com", "yousendit.com", "youshun12.com", + "youthforfreechina.org", "youthnetradio.org", "youthwant.com.tw", "youtu.be", @@ -5601,7 +5632,16 @@ var rules = [ "zyzc9.com", "zzcartoon.com", "zzcloud.me", - "zzux.com" + "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" ] ] ]; @@ -5618,11 +5658,23 @@ function FindProxyForURL(url, host) { } 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; + return i % 2 == 0 ? 'DIRECT' : proxy; } } lastRule = ''; diff --git a/release/update/checksum.lzma b/release/update/checksum.lzma index 912c3f4..51029eb 100644 Binary files a/release/update/checksum.lzma and b/release/update/checksum.lzma differ diff --git a/release/update/files/winXray.exe.lzma b/release/update/files/winXray.exe.lzma index 32fd19f..f24180d 100644 Binary files a/release/update/files/winXray.exe.lzma and b/release/update/files/winXray.exe.lzma differ diff --git a/release/update/files/xray-core/LICENSE.lzma b/release/update/files/xray-core/LICENSE.lzma deleted file mode 100644 index ef14391..0000000 Binary files a/release/update/files/xray-core/LICENSE.lzma and /dev/null differ diff --git a/release/update/files/xray-core/winXray-default-servers.json.lzma b/release/update/files/xray-core/winXray-default-servers.json.lzma deleted file mode 100644 index 4f50475..0000000 Binary files a/release/update/files/xray-core/winXray-default-servers.json.lzma and /dev/null differ diff --git a/release/update/files/xray-core/xray.exe.lzma b/release/update/files/xray-core/xray.exe.lzma deleted file mode 100644 index 8e4dd47..0000000 Binary files a/release/update/files/xray-core/xray.exe.lzma and /dev/null differ diff --git a/release/update/version.txt b/release/update/version.txt index 345b08f..c5da9a6 100644 --- a/release/update/version.txt +++ b/release/update/version.txt @@ -1,8 +1,8 @@ { - "description":"发布 v2.3,修正刷新clash订阅连接重复添加服务器,改进订阅管理等。", + "description":"发布 v3.7,增加托盘图标显示代理状态,增加 UWP 代理设置", "format":".lzma", "main":"\\winXray.exe", "updater":"\\winXray.exe", "url":"https://raw.githubusercontent.com/winXray/winXray/master/release/update/", - "version":"2.3" + "version":"3.7" } \ No newline at end of file diff --git a/release/update32/checksum.lzma b/release/update32/checksum.lzma deleted file mode 100644 index bbaed56..0000000 Binary files a/release/update32/checksum.lzma and /dev/null differ diff --git a/release/update32/files/winXray.exe.lzma b/release/update32/files/winXray.exe.lzma deleted file mode 100644 index 32fd19f..0000000 Binary files a/release/update32/files/winXray.exe.lzma and /dev/null differ diff --git a/release/update32/files/xray-core/LICENSE.lzma b/release/update32/files/xray-core/LICENSE.lzma deleted file mode 100644 index ef14391..0000000 Binary files a/release/update32/files/xray-core/LICENSE.lzma and /dev/null differ diff --git a/release/update32/files/xray-core/winXray-default-servers.json.lzma b/release/update32/files/xray-core/winXray-default-servers.json.lzma deleted file mode 100644 index 723ebca..0000000 Binary files a/release/update32/files/xray-core/winXray-default-servers.json.lzma and /dev/null differ diff --git a/release/update32/files/xray-core/xray.exe.lzma b/release/update32/files/xray-core/xray.exe.lzma deleted file mode 100644 index 0a643e2..0000000 Binary files a/release/update32/files/xray-core/xray.exe.lzma and /dev/null differ diff --git a/release/update32/version.txt b/release/update32/version.txt index e91ecc1..c5da9a6 100644 --- a/release/update32/version.txt +++ b/release/update32/version.txt @@ -1,8 +1,8 @@ { - "description":"发布 v2.3,修正刷新clash订阅连接重复添加服务器,改进订阅管理等。", + "description":"发布 v3.7,增加托盘图标显示代理状态,增加 UWP 代理设置", "format":".lzma", "main":"\\winXray.exe", "updater":"\\winXray.exe", - "url":"https://raw.githubusercontent.com/winXray/winXray/master/release/update32/", - "version":"2.3" + "url":"https://raw.githubusercontent.com/winXray/winXray/master/release/update/", + "version":"3.7" } \ No newline at end of file diff --git a/release/winXray.7z b/release/winXray.7z index c5ce29c..d5e02bf 100644 Binary files a/release/winXray.7z and b/release/winXray.7z differ diff --git a/release/winXray32.7z b/release/winXray32.7z index 80f72cc..e9e3687 100644 Binary files a/release/winXray32.7z and b/release/winXray32.7z differ diff --git a/screenshots/config.advanced.png b/screenshots/config.advanced.png index 4398d2b..2149235 100644 Binary files a/screenshots/config.advanced.png and b/screenshots/config.advanced.png differ diff --git a/screenshots/config.json.png b/screenshots/config.json.png index 9d85acf..7e0dba3 100644 Binary files a/screenshots/config.json.png 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 index 50d1834..fd670de 100644 Binary files a/screenshots/pac.png and b/screenshots/pac.png differ diff --git a/screenshots/winXray.png b/screenshots/winXray.png index daa810c..85be3ba 100644 Binary files a/screenshots/winXray.png and b/screenshots/winXray.png differ diff --git a/sub/introduce.md b/sub/introduce.md index 0b52346..c4e9b62 100644 --- a/sub/introduce.md +++ b/sub/introduce.md @@ -2,35 +2,56 @@ ### 一、批量导入链接技巧 -winXray 最新版支持直接使用 github 网址作为订阅链接。例如,我们在浏览器里访问 github项目文件的地址是这样的: [https://github.com/winXray/winXray/blob/master/sub/sample.json](./sample.json) 我们直接复制前面的链接,然后在 winXray 中点击 **「批量导入链接」** 就可以导入里面的服务器配置了。 +winXray 可通过【批量导入链接】功能导入以下格式的分享链接、订阅源、或JSON配置: -winXray可以兼容以下格式的github文件地址( 支持省略域或并以斜杆开头的地址 ): + 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 -即使在国内打不开 githubusercontent.com,winXray 仍然可以机智地调用 github 的API 顺利地把目标文件下载下来。 +### 二、使用新增、编辑服务器配置的对话框 + +winXray 新版已经添加了新增、编辑服务器配置的对话框,请直接在 winXray 首页服务器列表点右键菜单,然后点【新增、编辑代理服务器】即可。 + +![新增、编辑服务器](./../screenshots/winXray.png) -winXray 的订阅链接可以返回所有 winXray 能兼容的服务器配置,例如: -1、直接返回一行或多行分享链接,支持vmess,vless,ss,trojan,trojan-go 这一堆的各种通用分享格式,每行一个有效链接,无效的行 winXray 会自动忽略。 -2、可以每行一个服务器配置JSON,也可以把多个服务器配置JSON放到一个数组里(就是放到方括号里),winXray都能兼容,JSON推荐使用 winXray 的语法 - winXray已经把各种不同的代理协议配置规范化为了几个简单且通用的字段。当然你可以返回一些 winXray 可以兼容的通用JSON,winXray 会最大可能的识别并转换各种JSON格式,例如服务器的字段名你可以写为add,address,server 等等不同的名字。 -服务器可以返回base64编码的配置,也可以直接返回服务器配置,winXray都能识别。 winXray可以导入v2ray,、Shadowsocks、trojan等通用订阅链接,也可以导入 Clash proxy-provider 配置,winXray将自动转化各种不兼容的配置为统一、规范的格式。 +![代理服务器配置](./../screenshots/outbound.png) -我们平时复制配置和链接导入 winXray 一样,winXray都会最大可能的识别并兼容各种格式,并且尝试自动清除复制文本中的无效内容。例如使用 winXray 自带的 v2ray agent 安装服务端以后,我们不需要在给出的配置中挑选出JSON慢慢的修改和设置,你只需要把安装程序返回的一大堆账号配置文本直接复制出来(包含各种无效的、无关的说明文字), winXray 会自动分析识别并导入有效的服务器配置。 +### 三、使用JSON配置服务器 +![三、使用JSON配置服务器](./../screenshots/config.json.png) +JSON配置界面里点击任意字段都会显示该字段的用法说明。个人认为做很多对话框来配置服务器的参数其实是把简单的事搞复杂了,winXray已经把各种代理协议的配置简化为几个统一命名的JSON字段( **也可以作为一种标准的、统一的、通用的订阅响应格式使用** ),只要稍加学习就可以非常熟练的添加、修改各种代理协议的配置。而且对于大多数用户根本不需要改配置 - 简单的复制导入分享链接就可以,我们不必要把简单的事搞复杂。 -有些人崇尚复杂,但是winXray 的目标就是让一切变得更简单,软件能自动做的事就自动做好,**人生苦短,哪有那么多时间折腾?!** +### 四、使用 PAC 编辑器 +可以直接复制网址( 不需要去截取域名 ) ,然后打开 PAC 编辑器,这时候 winXray 会自动从剪贴板把域名取出来并且输入好,只要点一下设为代理,然后添加域名就可以了。也可以一次复制多个域名,域名可以任何空白字符(或者换行)分隔,然后点右键菜单,再点批量导入域名即可。 -### 二、使用JSON配置服务器技巧 -![服务器配置](./../screenshots/config.json.png) -JSON配置界面里点击任意字段都会显示该字段的用法说明。个人认为做很多对话框来配置服务器的参数是非常蠢的,winXray已经把各种代理协议的配置简化为几个统一命名的JSON字段( **也可以作为一种标准的、统一的、通用的订阅响应格式使用** ),只要稍加学习就可以非常熟练的添加、修改各种代理协议的配置。而且对于大多数用户根本不需要改配置 - 简单的复制导入分享链接就可以,我们不必要把简单的事搞复杂。 +winXray 里的 PAC 支持 CIDR 格式的 IP 地址段, 使用此功能可以轻松的让 PAC 代理支持 Telegram。 -### 三、Telegram 代理设置 -因为Telegram 使用的IP非常多,PAC代理确实不好支持Telegram ,但是使用IP路由去适配Telegram其实是不必要的,试想一下一个IP路由的数据就几十MB - 有这个必要吗?!我们为什么不直接告诉 Telegram 他要使用的代理服务器地址,而是 他在每个IP请求的时候都去判断一下呢?。 +![使用 PAC 编辑器](./../screenshots/pac.png) -所以更简洁、更聪明的方法就是直接告诉 Telegram 他要使用的代理服务器地址,这个操作非常简单 - 绝对比下载 Telegram 更简单,请看下面的动画: +### 五、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 index 1e5d637..e7ab7e5 100644 --- a/sub/sample.json +++ b/sub/sample.json @@ -1,26 +1,4 @@ -[ - { - "address":"us.winray.xyz", - "flow":"xtls-rprx-direct", - "host":"us.winray.xyz", - "id":"0d841558-eade-cfa9-f3ea-b6ab735a7867", - "port":443, - "protocol":"vless", - "ps":"美国西雅图xtls黑科技", - "sni":"us.winray.xyz", - "tls":"xtls" - }, - { - "address":"jp.winray.xyz", - "flow":"xtls-rprx-direct", - "host":"jp.winray.xyz", - "id":"1fd55a0e-67e1-a70e-acdc-86605b0b7f00", - "port":443, - "protocol":"vless", - "ps":"日本东京xtls黑科技", - "sni":"jp.winray.xyz", - "tls":"xtls" - }, +[ { "address":"www.aech.cc", "alterId":64, 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..95787f5 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..b71541e Binary files /dev/null and b/v2ray-core-32/v2ray.exe differ diff --git a/xray-core/winXray-default-servers.json b/v2ray-core-32/winXray-default-servers.json similarity index 97% rename from xray-core/winXray-default-servers.json rename to v2ray-core-32/winXray-default-servers.json index 160afc6..a52ea5d 100644 --- a/xray-core/winXray-default-servers.json +++ b/v2ray-core-32/winXray-default-servers.json @@ -1,7 +1,7 @@ // 号开头为注释行。 // 本文件用于指定默认服务器列表。 // 本文件可以直接输入json格式的服务器数组( 服务器可以使用subscribeUrl字段指定订阅源地址,可以指定"autoConnect":false字段禁止自动连接 ) -// 也可以每行一个 vless://、vmess://、trojan、trojan-go、ss:// 等分享链接 +// 也可以每行一个 vless://、vmess://、trojan、trojan-go、ss://、ssr://, 等分享链接 [ { "address":"服务器地址", 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..d698012 Binary files /dev/null and b/v2ray-core/v2ctl.exe differ diff --git a/xray-core/xray.exe b/v2ray-core/v2ray.exe similarity index 68% rename from xray-core/xray.exe rename to v2ray-core/v2ray.exe index ebd08e3..c4f6e60 100644 Binary files a/xray-core/xray.exe 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 diff --git a/xray-core/LICENSE b/xray-core/LICENSE deleted file mode 100644 index 2acac8a..0000000 --- a/xray-core/LICENSE +++ /dev/null @@ -1 +0,0 @@ -https://github.com/XTLS/Xray-core/blob/main/LICENSE \ No newline at end of file