Compare commits

...

1306 Commits
5.35 ... 7.8.3

Author SHA1 Message Date
2dust
4104964e38 up 7.8.3 2025-02-12 20:04:29 +08:00
2dust
3bbd1edf06 Update V2rayConfig.cs 2025-02-12 19:18:59 +08:00
lyranico
41cc260b5c Fix Package AppImage script (#6681) 2025-02-12 14:33:02 +08:00
2dust
6cd5063c9b Fix call core file
https://github.com/2dust/v2rayN/issues/6680
2025-02-12 11:23:22 +08:00
2dust
e544df6d01 up 7.8.2 2025-02-11 16:30:16 +08:00
2dust
f952d2383c Remove IncludeNativeLibrariesForSelfExtract 2025-02-11 10:16:19 +08:00
2dust
8a29e147d3 Added Enable Mixin parameter 2025-02-10 20:04:47 +08:00
Alphax-Hue3682
8a19128e7f Update Persian translate (#6651)
* Update Persian translate

* Update ResUI.fa-Ir.resx
2025-02-10 17:40:21 +08:00
2dust
7dc9fbd8ff Improved and optimized speedtest 2025-02-10 10:08:03 +08:00
2dust
31a179e647 Code clean 2025-02-09 20:17:56 +08:00
2dust
c3fdfcc4bd up 7.8.1 2025-02-08 16:49:59 +08:00
2dust
7ea8fae2da Improve test logic
Retest the failed part of the test and call it recursively.
Remove the number of batches that are automatically divided when testing parameters.
2025-02-08 16:43:40 +08:00
2dust
67ffa810d3 Optimize code and remove Action 2025-02-06 15:28:51 +08:00
2dust
ba2a636dd2 Fixed the system language judgment during the first run
https://github.com/2dust/v2rayN/issues/6638
2025-02-06 14:36:38 +08:00
2dust
d471336994 Adjust App Exit function
https://github.com/2dust/v2rayN/issues/6634
2025-02-05 17:31:13 +08:00
2dust
7e6482fdff Adjust hysteria core run arguments
https://github.com/2dust/v2rayN/issues/6635
2025-02-05 17:14:56 +08:00
2dust
a8eba93ffd up 7.8.0 2025-02-04 14:30:42 +08:00
2dust
4ffe595db6 Code clean 2025-02-04 14:30:28 +08:00
2dust
885587e551 Update Directory.Packages.props 2025-02-04 14:19:56 +08:00
2dust
e986dc189e Fix ProcUtils NoAssociatedProcess issue 2025-02-04 10:30:33 +08:00
2dust
bccab41c8f Update Directory.Build.props 2025-02-04 10:28:49 +08:00
2dust
79a0538ca0 Improve core info 2025-02-03 20:19:20 +08:00
2dust
e6b27d17e4 Add support for overtls custom configuration
https://github.com/ShadowsocksR-Live/overtls
2025-02-03 15:43:26 +08:00
2dust
2a0012824a Add support for brook custom configuration
https://github.com/txthinking/brook
https://github.com/txthinking/brook/issues/1372
2025-02-03 15:06:21 +08:00
2dust
9d92be99ee Improve core running arguments 2025-02-03 14:48:53 +08:00
2dust
6914831d30 Code clean 2025-02-02 17:48:59 +08:00
2dust
19d83be6de Fix Package AppImage script 2025-02-01 19:10:54 +08:00
2dust
ce7303bd0d up 7.7.1 2025-02-01 14:16:54 +08:00
2dust
4c3318ac86 Revert "Update MainWindow.axaml.cs"
This reverts commit 4d95d7d8c0.
2025-02-01 14:11:12 +08:00
2dust
db25fdeee1 Revert "Remove using System.Reflection"
This reverts commit 732c3eee8b.
2025-02-01 13:51:28 +08:00
2dust
732c3eee8b Remove using System.Reflection 2025-02-01 10:34:05 +08:00
2dust
2b0d805b2f Update Directory.Build.props 2025-02-01 10:33:11 +08:00
2dust
4faa94b2a3 Cache when reading embedded resources 2025-01-31 16:02:29 +08:00
2dust
331d11aee2 Update .editorconfig 2025-01-31 15:59:44 +08:00
2dust
4d95d7d8c0 Update MainWindow.axaml.cs
if (Utils.IsOSX() || _config.UiItem.Hide2TrayWhenClose)
2025-01-31 15:59:35 +08:00
dependabot[bot]
fd82623c74 Bump actions/setup-dotnet from 4.2.0 to 4.3.0 (#6604)
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 4.2.0 to 4.3.0.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](https://github.com/actions/setup-dotnet/compare/v4.2.0...v4.3.0)

---
updated-dependencies:
- dependency-name: actions/setup-dotnet
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-31 09:17:42 +08:00
2dust
4a32b2c814 Fixed the issue of update the Windows self contained version 2025-01-30 18:06:13 +08:00
2dust
45264005a4 Code clean 2025-01-30 17:10:05 +08:00
2dust
253219dd16 Update .editorconfig 2025-01-30 16:35:48 +08:00
ShiinaRinne
b2feaf3ba9 [macOS] feat: auto run. https://github.com/2dust/v2rayN/issues/6383 (#6597) 2025-01-30 13:24:01 +08:00
2dust
6c5011ad68 Try to remove the tun device when restarting the service in Windows
https://github.com/2dust/v2rayN/pull/6561
2025-01-30 10:46:04 +08:00
ShiinaRinne
c0f8b6b84c [macOS] amend: Child window visibility handling (#6598)
https://github.com/2dust/v2rayN/pull/6596

When the main window is hidden, open child windows are mistakenly hidden as well.
This prevents reopening child windows after the main window is shown again.
2025-01-30 10:12:59 +08:00
ShiinaRinne
f71125d8f3 macOS 一些优化 (#6596)
* [macOS] hide icon in Dock

* [macOS] fix: close button not work

* [macOS] fix: cant directly show window when click `Show or hide the main window` on minimized
2025-01-29 19:26:40 +08:00
2dust
e674a025d8 Adjust Directory.Build.props
https://learn.microsoft.com/zh-cn/dotnet/core/deploying/trimming/trimming-options

https://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/compiler-options/code-generation
2025-01-29 15:17:30 +08:00
2dust
dadc24876f Change Directory 2025-01-29 14:22:30 +08:00
Anatoliy
98d4801b7e Use Directory.Build.props for centralized configuration management (#6591)
* use Directory.Buld.props

* remove some properties
2025-01-28 20:01:59 +08:00
Anatoliy
0e50bfb6eb create editorconfig (#6592) 2025-01-28 12:16:04 +08:00
2dust
a5aa286535 Add Name to App.axaml 2025-01-25 20:45:56 +08:00
2dust
3caf025c3c Update README.md 2025-01-25 20:19:02 +08:00
2dust
c943c6c60a Update README.md 2025-01-25 20:15:16 +08:00
2dust
8c55c629cd Fix PackageReference 2025-01-24 20:28:04 +08:00
2dust
0c38ebb63f Added Avalonia UI Windows version compilation script 2025-01-24 20:01:36 +08:00
2dust
75df85f598 Release script adjust prerelease = true 2025-01-24 19:48:34 +08:00
2dust
59e99b2316 Downgrade ZXing.Net.Bindings.SkiaSharp to version 0.16.14
In linux report
Unhandled exception. System.TypeInitializationException: The type initializer for 'SkiaSharp.SKFontManager' threw an exception.
 ---> System.TypeInitializationException: The type initializer for 'SkiaSharp.SKObject' threw an exception.
 ---> System.InvalidOperationException: The version of the native libSkiaSharp library (88.1) is incompatible with this version of SkiaSharp. Supported versions of the native libSkiaSharp library are in the range [116.0, 117.0).
   at SkiaSharp.SkiaSharpVersion.CheckNativeLibraryCompatible(Version minSupported, Version current, Boolean throwIfIncompatible)
   at SkiaSharp.SkiaSharpVersion.CheckNativeLibraryCompatible(Boolean throwIfIncompatible)
   at SkiaSharp.SKObject..cctor()
2025-01-24 19:46:28 +08:00
Anatoliy
02f4dcbaf7 use Directory.Packages.props (#6581) 2025-01-24 19:00:21 +08:00
2dust
470dec5588 up PackageReference 2025-01-24 17:24:07 +08:00
2dust
be1e37ddd0 Hide the upgrade core in Windows 7 2025-01-24 14:26:51 +08:00
2dust
fdc32601a9 Update ResUI.Designer.cs 2025-01-24 14:25:56 +08:00
2dust
d3b86858e1 Revert "Use Directory.Packages.props (#6575)"
This reverts commit 9c20d9cb1f.
2025-01-24 14:25:13 +08:00
Anatoliy
9c20d9cb1f Use Directory.Packages.props (#6575) 2025-01-24 09:57:38 +08:00
alphax-hue3682
d2cda16378 Update Persian Translate (#6559) 2025-01-22 10:00:33 +08:00
aucub
2ab00d5b6f Add Package AppImage script (#6556) 2025-01-21 09:27:38 +08:00
OnceUponATimeInAmerica
1b8a58cd07 Update English translation (#6555) 2025-01-21 09:15:48 +08:00
Anatoliy
0c3293045f Remove extra .gitignore file and move .gitattributes to the root folder for consistent storage of .git-related files. (#6545) 2025-01-20 09:28:30 +08:00
2dust
4c4ce7e8d1 Revert "增加macos dmg软件签名 (#6541)"
This reverts commit a0d4a3f2e8.
2025-01-19 18:58:32 +08:00
zjt003
a0d4a3f2e8 增加macos dmg软件签名 (#6541)
* Update package-osx.sh

* Update build-osx.yml
2025-01-19 18:34:39 +08:00
2dust
26abe7e7d7 up 7.7.0 2025-01-19 09:36:43 +08:00
2dust
b9c86ed3a1 Modify the file name in winget release package 2025-01-19 09:35:19 +08:00
2dust
b7cff66a80 Remove the core name in the Windows release version 2025-01-19 09:34:37 +08:00
2dust
61a40d2860 up PackageReference 2025-01-19 09:27:20 +08:00
2dust
80eb569366 The bin folder is added to the package
54fe669d89
2025-01-18 21:10:41 +08:00
2dust
54fe669d89 Copy the bin folder to the storage location (for init) 2025-01-18 16:58:44 +08:00
2dust
0953237e9e Improvements 2025-01-18 16:01:52 +08:00
2dust
cf1a8599eb When updating the bin folder, skip the file if it already exists.
https://github.com/2dust/v2rayN/issues/6515
2025-01-17 10:27:29 +08:00
alphax-hue3682
171132be12 Update Persian Translate (#6513) 2025-01-16 15:56:05 +08:00
2dust
43c95422b7 up 7.6.2 2025-01-15 19:49:14 +08:00
esmaiel777
2662243641 Update dns_singbox_normal (#6511) 2025-01-15 19:47:45 +08:00
esmaiel777
060a35e091 Update tun_singbox_dns (#6510) 2025-01-15 19:47:34 +08:00
2dust
de1132c2df Added option to display real-time speed 2025-01-15 19:45:53 +08:00
2dust
f19edc9370 Improvements and Adjustments
InitCoreInfo()
2025-01-15 17:31:13 +08:00
2dust
f1601c463b Improvements and Adjustments
await Task.CompletedTask;
return await Task.FromResult(0);
2025-01-15 17:26:15 +08:00
2dust
77b15cd530 Add a prompt for not setting a password when open Tun on macos 2025-01-15 11:02:49 +08:00
2dust
a6479fe0d0 Update build-windows.yml 2025-01-14 18:15:45 +08:00
2dust
4ad4e27dc1 Improve reload function 2025-01-14 17:05:13 +08:00
2dust
7370684985 Improve delete expired files 2025-01-14 17:04:43 +08:00
2dust
5ae58e6a98 Improve reload function 2025-01-14 14:49:17 +08:00
2dust
780ccb1932 Improved ProfileItemsEx 2025-01-14 11:48:02 +08:00
2dust
6b4076be10 up 7.6.1 2025-01-12 19:36:19 +08:00
alphax-hue3682
d7a04a15ae Update Persian translate (#6487) 2025-01-12 19:33:57 +08:00
2dust
2ae43f8bdb Revert "Remove rules custom Icon"
This reverts commit d3ebc17a10.
2025-01-12 19:33:23 +08:00
2dust
d3ebc17a10 Remove rules custom Icon 2025-01-12 14:35:59 +08:00
2dust
7a8680711e Improvements and Adjustments 2025-01-12 14:30:49 +08:00
2dust
649e89e7af Added Copy Terminal proxy command to clipboard in tray menu
https://github.com/2dust/v2rayN/issues/6482
2025-01-12 11:07:34 +08:00
2dust
cb94d64395 Bug fix 2025-01-11 19:35:32 +08:00
2dust
2440dc2440 Remove deprecated DefIEProxyExceptions 2025-01-11 19:34:04 +08:00
Little丶Dreams
364a24c580 CloneServerStatItem 时检查indexId和toIndexId是否相同 (#6478) 2025-01-11 14:44:09 +08:00
2dust
8f3e0dbd82 up 7.6.0 2025-01-11 11:48:57 +08:00
alphax-hue3682
596234df26 Update Persian translate (#6465)
* Update ResUI.fa-Ir.resx

e0ae101ff4

* Update ResUI.fa-Ir.resx
2025-01-11 11:30:06 +08:00
2dust
c38aec50dc Delete unused resources 2025-01-11 11:28:35 +08:00
2dust
40915b5f98 Adjust theme options for windows 2025-01-11 11:23:40 +08:00
2dust
a176613119 Bug fix for ProcUtils 2025-01-11 10:44:34 +08:00
2dust
6c6de1ae7f Improvements and Adjustments 2025-01-10 20:12:42 +08:00
2dust
edbd168dcf Add theme options for desktop 2025-01-10 15:53:06 +08:00
2dust
127858d582 Adjust UI for desktop 2025-01-10 14:23:03 +08:00
2dust
baf90cfbdd Sing-box cache file specified path
https://github.com/2dust/v2rayN/issues/6460
2025-01-10 10:00:00 +08:00
2dust
1a5eeb9401 Adjust UI for desktop 2025-01-09 21:03:17 +08:00
2dust
e0ae101ff4 Adjust UI for desktop 2025-01-09 15:14:03 +08:00
Long Yixing
8b4a07dfe8 Modify the macos build script (#6461)
No longer generate AppIcon.icns
2025-01-09 10:21:07 +08:00
2dust
db934e70cb The icon of the system proxy can be customized
https://github.com/2dust/v2rayN/issues/6459
2025-01-08 20:35:33 +08:00
2dust
b770048f05 The exported routing rules are compatible with the import function of v2rayNG 2025-01-08 17:57:23 +08:00
2dust
27c53be209 up 7.5.6 2025-01-08 14:16:30 +08:00
2dust
d93c12b354 Add more options to xray fragment 2025-01-08 13:52:21 +08:00
2dust
98d4a47efb Fix Mux for XUDP
https://github.com/2dust/v2rayN/issues/6446
2025-01-07 20:16:05 +08:00
2dust
8ab04c65b5 Update README.md 2025-01-07 14:33:15 +08:00
2dust
1b2dab1388 Bug fix
https://github.com/2dust/v2rayN/issues/6448
2025-01-07 11:28:46 +08:00
2dust
4f8dae7fa0 Add the mixed option in Stack in Tun mode settings
https://github.com/2dust/v2rayN/issues/6441
2025-01-06 20:46:07 +08:00
Harry Huang
cdc23e32c4 Fix zh-Hans and zh-Hant translation style (#6443)
* Fix zh-Hans i10n translation style

* Fix zh-Hant i10n translation style
2025-01-06 19:05:43 +08:00
2dust
20457e9e63 up 7.5.5 2025-01-05 19:10:57 +08:00
2dust
e63042af84 Bug fix for fontsize 2025-01-05 19:10:12 +08:00
2dust
c35b4d3c1b up 7.5.4 2025-01-05 17:58:55 +08:00
2dust
64a83a5d64 down PackageReference 2025-01-05 17:58:23 +08:00
2dust
01039d0b47 up 7.5.3 2025-01-05 17:31:32 +08:00
2dust
7c1e5a3cba Fixed possible crash issues 2025-01-05 17:12:51 +08:00
2dust
038161527f Buf fix for CurrentFontSize 2025-01-05 17:11:32 +08:00
2dust
b12b7a17e6 Fix possible issues with load balancing 2025-01-05 16:31:32 +08:00
2dust
37cf23d5fe up PackageReference 2025-01-05 15:01:15 +08:00
2dust
ed7fb4f6e3 Code clean 2025-01-05 14:50:31 +08:00
2dust
5d4bd2fee6 Fix possible issues with load balancing
https://github.com/2dust/v2rayN/issues/6429
2025-01-05 14:49:53 +08:00
2dust
aae5906311 Fix GetListNetworkServices 2025-01-05 12:24:14 +08:00
2dust
4a7bafd011 Fix Linux restore backup function
Fixed the issue that the guiNConfig.json file cannot be restored in the backup and restore function
2025-01-05 10:22:18 +08:00
2dust
626ebfe65d Improved ModifyFontSize 2025-01-04 20:42:42 +08:00
2dust
3cc75cd46d up 7.5.2 2025-01-04 19:07:16 +08:00
2dust
f809ee7b20 Adjust the macos package icon
https://github.com/2dust/v2rayN/issues/6404
2025-01-04 19:06:26 +08:00
2dust
1295d8191c Fix DNS
https://github.com/2dust/v2rayN/issues/6416
2025-01-04 17:47:54 +08:00
2dust
bc2adbfa77 Add restart to Linux restore backup function 2025-01-04 17:03:12 +08:00
2dust
9583dff176 Added the function of restarting the main app to AmazTool 2025-01-04 17:01:57 +08:00
2dust
5732b84a7b Refactor KillProcess 2025-01-04 15:06:30 +08:00
2dust
c0d27504ac Refactor ProcessStart RebootAsAdmin 2025-01-03 20:56:51 +08:00
2dust
3db1dd7bbb Add a title to SaveLog 2025-01-03 15:02:31 +08:00
2dust
5392766c5e Improved KillProcess 2025-01-03 15:01:30 +08:00
2dust
730b7dea37 Adjust upgrade waiting time 2025-01-03 09:50:21 +08:00
2dust
02a13ce028 Add logging to KillProcess
https://github.com/2dust/v2rayN/issues/6386
2025-01-02 13:54:17 +08:00
2dust
7884853098 Improved backup and restore
Overwrite the configuration file directly in the main program
2025-01-02 13:36:26 +08:00
2dust
e122ea8146 Optimize VerticalAlignment="Center" 2025-01-02 12:20:43 +08:00
2dust
f500d2b9f4 up 7.5.1 2025-01-01 16:25:53 +08:00
2dust
79e53bf1f5 Improve macos system proxy code 2025-01-01 14:24:23 +08:00
2dust
31de7ec094 Bug fix SetLinuxChmod 2025-01-01 12:27:49 +08:00
2dust
2e4501187c Window title display adjustment
https://github.com/2dust/v2rayN/issues/6389
2025-01-01 10:38:55 +08:00
2dust
4430c9bd74 Remove the last rule from the Whitelist
https://github.com/2dust/v2rayN/issues/6378
2024-12-31 20:37:14 +08:00
2dust
cf8be85ff7 Remove the display of run as an administrator in Linux and macos 2024-12-31 16:30:27 +08:00
2dust
0759be1223 Fix rule required
https://github.com/2dust/v2rayN/issues/6378
2024-12-31 15:32:31 +08:00
2dust
21f8ddcf9f macos adds system proxy for USB
https://github.com/2dust/v2rayN/issues/6381
2024-12-31 14:55:35 +08:00
2dust
37cba5ee34 Fix export rule order issue
https://github.com/2dust/v2rayN/issues/6377
2024-12-31 14:15:09 +08:00
OnceUponATimeInAmerica
ff642fd1ac Add full support for (one-click) Iran regional preset by using Chocolate4U's github repos for iran routing rules (#6384) 2024-12-31 13:51:06 +08:00
2dust
647f1d9c8b up 7.5.0 2024-12-30 19:56:33 +08:00
2dust
d886195ee3 Adjust upgrade waiting time 2024-12-30 19:55:32 +08:00
2dust
e2b8f4f89a If Process.start contains spaces, add quotes 2024-12-30 19:33:39 +08:00
2dust
1dcfe661e9 Modify the build script
When NotStoreConfigHere.txt file exists, the configs not stored in the current folder
2024-12-30 18:16:07 +08:00
2dust
d6dd110781 Adjust open the storage location 2024-12-30 11:10:27 +08:00
2dust
a0f956c885 Add command shortcut keys for macos
https://github.com/2dust/v2rayN/issues/6375
2024-12-30 11:02:09 +08:00
Long Yixing
88bcafed97 Modify the build macos script (#6374) 2024-12-30 09:24:22 +08:00
2dust
6e4f15ab52 Update README.md 2024-12-27 10:12:38 +08:00
Wydy
20cae1ff4d Update pac (#6356) 2024-12-27 09:48:28 +08:00
2dust
dcf621b822 Modify the build script 2024-12-26 17:19:42 +08:00
2dust
eafa20032b Modify the build windows script 2024-12-25 17:06:03 +08:00
2dust
7375e1a490 Modify the build macos script 2024-12-25 16:48:23 +08:00
2dust
199d87ba84 Modify the build linux script and add release package deb 2024-12-25 16:11:02 +08:00
2dust
b43975ebfc Add v2rayN.png for desktop 2024-12-25 16:06:11 +08:00
2dust
fe7314c978 up 7.4.2 2024-12-24 10:55:25 +08:00
2dust
d4eb8e59a6 update build 2024-12-23 17:39:50 +08:00
2dust
8ee00907b7 update build 2024-12-23 17:34:06 +08:00
2dust
25fddc3c71 Code clean for desktop 2024-12-23 14:28:33 +08:00
2dust
c78b733850 Revert "update build macos"
This reverts commit a57c83125e.
2024-12-23 13:59:55 +08:00
2dust
a57c83125e update build macos 2024-12-23 12:12:03 +08:00
2dust
247b59985f update build 2024-12-23 11:31:56 +08:00
2dust
7470b8b6d3 Try to fix
https://github.com/2dust/v2rayN/issues/6073
2024-12-23 10:38:37 +08:00
2dust
776d37b7aa Optimize port display 2024-12-23 10:37:43 +08:00
alphax-hue3682
8f532f8468 Update persian translate (#6325) 2024-12-23 10:00:51 +08:00
2dust
472963fe2d Add a second local listening port
https://github.com/2dust/v2rayN/issues/6321
2024-12-22 20:03:20 +08:00
2dust
6a9b62ab9a Improve Ctrl+V for Windows 2024-12-22 12:02:00 +08:00
2dust
9ac8aa2969 up PackageReference 2024-12-22 12:00:50 +08:00
2dust
838bd2c794 up 7.4.1 2024-12-19 16:18:45 +08:00
2dust
b2bbe432e0 Fix
https://github.com/2dust/v2rayN/issues/6309
2024-12-19 16:07:45 +08:00
2dust
b3d8042452 The lower limit of the font size from 10 to 8 2024-12-19 13:53:40 +08:00
2dust
0c758a7fdc Optimize UI for macos 2024-12-19 13:36:45 +08:00
2dust
85cb1d1c92 Bug fix system proxy for macos 2024-12-19 13:20:12 +08:00
2dust
2cd2e8894d Add system proxy exception function for macos 2024-12-19 11:40:16 +08:00
2dust
abb58379b3 Add IsNonWindows instead of IsLinux or IsOSX 2024-12-19 11:24:52 +08:00
2dust
4f48e8b190 Optimize UI 2024-12-19 10:23:46 +08:00
2dust
2b5cbb5e74 UnauthorizedAccessException to Exception 2024-12-18 15:27:00 +08:00
2dust
23dd140921 up 7.4.0 2024-12-18 14:47:27 +08:00
2dust
8c8d7bda64 StartupPath optional LocalApplicationData for linux 2024-12-18 10:27:58 +08:00
2dust
a6e246948a Linux system proxy adds kde version processing 2024-12-17 11:05:12 +08:00
2dust
c49ba735a0 Optimize code 2024-12-16 21:05:36 +08:00
2dust
1a33c598e8 Disable mux when using xhttp 2024-12-16 21:01:03 +08:00
2dust
a4bbdb49de proxy api.ip.sb
https://github.com/2dust/v2rayN/issues/6280
2024-12-16 19:59:46 +08:00
2dust
cf3846fbfd Update README.md 2024-12-16 19:47:27 +08:00
2dust
d46943eedf Optimize UI 2024-12-16 14:28:22 +08:00
2dust
3bc17bd50a Add host for xray ws
https://github.com/XTLS/Xray-core/pull/4142
2024-12-16 14:22:31 +08:00
2dust
48a159f4c8 Need SkiaSharp V2.88 2024-12-15 16:15:58 +08:00
2dust
3d1bcffdc5 up 7.3.2 2024-12-15 15:14:25 +08:00
2dust
45fa0f94d2 up PackageReference 2024-12-15 15:13:37 +08:00
2dust
ed16b7de4a Fix
https://github.com/2dust/v2rayN/issues/6258
2024-12-15 14:41:48 +08:00
2dust
f2ec03c7ec Bug fix
https://github.com/2dust/v2rayN/issues/6263
2024-12-15 14:41:29 +08:00
2dust
11db87f1e6 Remove unused resources 2024-12-15 14:27:00 +08:00
phoenix6936
a1feaf33e0 Update persian translation (#6245)
* Update persian translation

* Update ResUI.fa-Ir.resx
2024-12-15 11:24:13 +08:00
2dust
53a99e3f79 Remove part System.Reflection 2024-12-08 11:11:06 +08:00
2dust
e7f04f55c2 Remove QueryableExtension 2024-12-08 11:10:15 +08:00
2dust
6653ea12b7 Add Language: Hungarian
https://github.com/2dust/v2rayN/issues/6252
2024-12-07 21:25:53 +08:00
2dust
a28cef5b98 Fixed the issue of save window size when exit
https://github.com/2dust/v2rayN/issues/6251
2024-12-07 21:13:57 +08:00
2dust
78a28fbdb3 up 7.3.1 2024-12-07 16:30:32 +08:00
2dust
bf8bbbdcb0 Code clean 2024-12-07 16:29:58 +08:00
2dust
83ad83b135 Optimize save config files 2024-12-07 14:07:51 +08:00
2dust
dbd4f55981 Add system proxy exception function for linux
https://github.com/2dust/v2rayN/issues/6214
2024-12-06 19:12:32 +08:00
2dust
5f5d7172ee Optimize system proxy exceptions 2024-12-06 16:38:23 +08:00
2dust
fbd4557b44 WebProxy uses socks5 instead of http 2024-12-06 14:01:11 +08:00
phoenix6936
5d55a55754 Update persian translate (#6237)
* Update persian translate

* Update ResUI.fa-Ir.resx
2024-12-06 10:01:11 +08:00
phoenix6936
84032aec33 Update persian translation (#6227)
* Update persian translation

* Update ResUI.fa-Ir.resx

* Update ResUI.fa-Ir.resx

* Update ResUI.fa-Ir.resx

* Update ResUI.fa-Ir.resx

* Update ResUI.fa-Ir.resx

* Update ResUI.fa-Ir.resx

* Update ResUI.fa-Ir.resx
2024-12-06 09:38:56 +08:00
2dust
a372d8902e up 7.3.0 2024-12-05 20:08:23 +08:00
2dust
c38c62e4c3 Add automatic batching during speed test and real ping 2024-12-05 19:48:42 +08:00
2dust
8aceff7480 Enhanced testing function
Separate xray-core and sing-box-core testing
2024-12-05 15:21:16 +08:00
2dust
736c450161 Improve the code 2024-12-05 14:05:12 +08:00
2dust
3b63a3d308 Fix
https://github.com/2dust/v2rayN/issues/6216
2024-12-05 14:04:39 +08:00
2dust
4f56174c8f Bug fix
https://github.com/2dust/v2rayN/issues/6219
2024-12-05 12:16:53 +08:00
2dust
4d2eb324f1 Adjust UI
https://github.com/2dust/v2rayN/issues/6217
2024-12-05 10:39:08 +08:00
2dust
3f2ab8ddcb Try to fix
https://github.com/2dust/v2rayN/issues/6186
2024-12-05 10:12:26 +08:00
2dust
fd8f863c5b Add stream-one for xhttp mode 2024-12-03 18:00:55 +08:00
2dust
246f1d7df0 Update README.md 2024-12-03 17:54:13 +08:00
2dust
ccacda9bf5 Using mixed local listening ports 2024-12-03 15:01:36 +08:00
2dust
5494d63878 Remove v2fly-core UI operation support 2024-12-03 13:58:56 +08:00
2dust
c32b9812a7 up PackageReference 2024-12-02 14:43:07 +08:00
2dust
9eb9898b61 Improve the clash connection 2024-12-02 14:40:09 +08:00
2dust
834e05999f Paste import functionality moved to server list
https://github.com/2dust/v2rayN/issues/6201
2024-12-02 11:01:32 +08:00
2dust
b4c37d9906 Bug fix
https://github.com/2dust/v2rayN/issues/6200
2024-12-02 10:16:07 +08:00
2dust
9326b450d7 Delete .github/workflows/winget-pre-release-publish.yml 2024-12-01 14:39:36 +08:00
2dust
019ee8b1ba Update winget-publish.yml 2024-12-01 14:30:39 +08:00
Merrick Zhang
f043645397 Create winget-publish.yml (#6014)
* Create winget-publish.yml

Publish to winget after release

* Update winget-publish.yml

change to released trigger

* Create winget-pre-release-publish.yml

publish pre-release versions.
2024-12-01 14:29:10 +08:00
2dust
3b173f0b3e Improve code 2024-12-01 11:17:36 +08:00
2dust
f36c06389d Improve the clash connection 2024-12-01 10:18:36 +08:00
2dust
d3a0b44247 Bug fix
https://github.com/2dust/v2rayN/issues/6182
2024-11-30 13:49:26 +08:00
2dust
e4d3a98aa8 Fixed the problem of traffic statistics api url 2024-11-30 10:58:53 +08:00
2dust
f685682214 Code clean 2024-11-29 19:21:09 +08:00
2dust
1c6323315b up 7.2.3 2024-11-29 11:43:53 +08:00
2dust
1ff4839be1 Bug fix
https://github.com/2dust/v2rayN/issues/6160
2024-11-29 11:31:22 +08:00
2dust
558e5bb340 Improve tun for linux 2024-11-29 10:31:57 +08:00
2dust
48a9d208e6 Label text optimization 2024-11-28 14:44:24 +08:00
2dust
f29e1f8c45 up 7.2.2 2024-11-27 18:54:16 +08:00
2dust
5d2bc88bb9 up PackageReference 2024-11-27 18:53:32 +08:00
2dust
298fdb1191 Change IPAPI
https://github.com/2dust/v2rayN/issues/6172
2024-11-27 17:03:16 +08:00
2dust
59b34688ea Improve tun for linux 2024-11-27 16:52:25 +08:00
2dust
5ce0bb6e4a Up 2024-11-27 14:40:01 +08:00
2dust
487b1ab182 Update build-osx 2024-11-27 14:37:39 +08:00
2dust
5c144a8ba3 Create build-osx.yml 2024-11-27 14:29:22 +08:00
2dust
ad344356df Create build-osx.sh 2024-11-27 14:23:16 +08:00
2dust
a55c65374d Update build.ps1 2024-11-27 14:22:42 +08:00
2dust
28447a9d43 Update build.ps1 2024-11-27 13:57:51 +08:00
2dust
0c03550c62 Update build.yml 2024-11-27 12:22:40 +08:00
2dust
6d9a84803f Update build.yml 2024-11-27 12:20:26 +08:00
2dust
03b0e4e2bb Update build.yml 2024-11-27 12:18:15 +08:00
2dust
a00e9a6f5e Update build.ps1 2024-11-27 11:25:37 +08:00
2dust
ba17f8fde9 Improve CoreHandler 2024-11-27 11:05:41 +08:00
2dust
01d35456bd Update AesUtils.cs 2024-11-26 20:07:41 +08:00
cryptochecktool
672b8c48ac AesUtils重新修改 (#6165)
* Create AesUtils.cs

新增AesUtils,替换掉DesUtils,提高安全性。
细节:
1.使用AES代替DES
2.正确使用IV调用方式
3.使用SHA256代替MD5进行密钥派生
4.使用PBKDF进行迭代生成密钥。

* Update AesUtils.cs

1.将默认密钥规则设置为与DES一致
2.经过本地测试
2024-11-26 19:54:46 +08:00
2dust
ac1a357740 Delete AesUtils.cs 2024-11-26 19:52:22 +08:00
2dust
504f8d09a6 Tun enable in macos when opening the app 2024-11-26 16:33:19 +08:00
2dust
89ce7c23c9 Fix tun interface name in macos 2024-11-26 15:32:35 +08:00
2dust
a5d99b1eb5 Improved Tun mode function in Linux version 2024-11-26 15:11:02 +08:00
2dust
800d193acb Bug fix 2024-11-26 14:39:33 +08:00
cryptochecktool
7a1d12be76 Update CoreHandler.cs (#6163)
将Desutils替换为Aesutils,提高安全性
2024-11-26 13:54:12 +08:00
cryptochecktool
1b9c95e801 Update OptionSettingViewModel.cs (#6162)
将Desutils替换为Aesutils,提升安全性。
2024-11-26 13:53:50 +08:00
cryptochecktool
9f44815470 Create AesUtils.cs (#6161)
新增AesUtils,替换掉DesUtils,提高安全性。
细节:
1.使用AES代替DES
2.正确使用IV调用方式
3.使用SHA256代替MD5进行密钥派生
4.使用PBKDF进行迭代生成密钥。
2024-11-26 13:52:37 +08:00
2dust
ca38239bce Add Font setting for macos 2024-11-25 21:00:49 +08:00
2dust
d9c22de6b8 Added core update function for macos 2024-11-25 20:31:12 +08:00
2dust
49a3c84fc5 up 7.2.1 2024-11-24 11:31:45 +08:00
2dust
5e0c28438b Refactor Localization for AmazTool 2024-11-23 14:41:19 +08:00
2dust
a6dc801bc4 Merge pac function into the main program 2024-11-23 14:08:08 +08:00
Space Time
22009d1b71 调整订阅分组设置窗口的布局 (#6132)
* 调整订阅分组设置窗口的布局

* 避免添加配置后出现滚动条
2024-11-23 10:45:16 +08:00
2dust
50f39dc40e Delete splithttp 2024-11-22 20:56:34 +08:00
2dust
05d446ed37 up 7.2.0 2024-11-22 18:04:36 +08:00
2dust
7a0b068642 Improve Follow System Theme for windows 2024-11-22 17:37:30 +08:00
2dust
c0ef8c09af Add Follow System Theme for desktop 2024-11-22 17:35:49 +08:00
fonaix
a2db6dd468 修复:TrayIcon不跟随代理模式变化的问题 (#6126)
* 添加:MacOS 代理配置与清除

* 修复:点击表头排序时,超时服务器排在前面的问题

* 添加:MacOS 打开存储所在位置功能

* 修复:删除全部节点时,UI不更新的问题

* 修复:TrayIcon不跟随代理模式变化的问题
2024-11-21 09:02:35 +08:00
2dust
471bc0f65d Update README.md 2024-11-20 15:33:29 +08:00
2dust
80f840a7c2 Fix
https://github.com/2dust/v2rayN/issues/6119
2024-11-20 15:29:06 +08:00
2dust
a2413fdf23 Remove Routing Basic function 2024-11-20 12:01:04 +08:00
2dust
9cbe2b938c Fixed the inbound issue caused by server configuration error during speed test
https://github.com/2dust/v2rayN/issues/6110
2024-11-20 10:34:51 +08:00
2dust
e915726c52 Improved upgrade
https://github.com/2dust/v2rayN/issues/6102
2024-11-20 10:29:04 +08:00
2dust
b11e68cfd8 Remove StatisticsV2rayService
Remove ProtosLib project
2024-11-19 19:20:12 +08:00
2dust
bee66d06dd Added real IP location display
https://ipapi.co/api/?shell#introduction
2024-11-19 16:43:00 +08:00
2dust
945a0add96 Code clean 2024-11-19 15:52:08 +08:00
2dust
294cabcf05 Update README.md 2024-11-18 17:14:42 +08:00
2dust
22eb993ebf up 7.1.3 2024-11-18 16:51:51 +08:00
2dust
b5e1a297ae Optimize Linux start tun mode
You can choose not to store the password and enter it manually each time
2024-11-18 16:44:12 +08:00
2dust
499a16feae Fix LocalizationHelper for AmazTool 2024-11-18 10:13:49 +08:00
Slnanx
1866a59d12 更新程序内嵌资源文件 (#6101)
* fix

* fix

* 移除自述

* 改用单例模式,避免多次初始化。

* 小修正

* 修正

* 更正自述

* 应该完成了

* 内嵌资源

* Update LocalizationHelper.cs
2024-11-18 09:57:38 +08:00
2dust
10513e0f3b Fixed the problem that the statistics column would not be hidden 2024-11-18 09:56:13 +08:00
Slnanx
2e32de2fbb fix (#6099)
* fix

* fix

* 移除自述

* 改用单例模式,避免多次初始化。

* 小修正

* 修正

* 更正自述

* 应该完成了
2024-11-17 19:42:14 +08:00
2dust
30a838df77 Bug fix
https://github.com/2dust/v2rayN/issues/6092
2024-11-17 16:18:46 +08:00
2dust
7cf9b9f57e up 7.1.2 2024-11-17 14:15:37 +08:00
2dust
736d995d4c up PackageReference 2024-11-17 14:11:51 +08:00
2dust
e335b2c0d6 Fix with AppendQuotes 2024-11-17 14:11:17 +08:00
2dust
96ae5517f6 Improve core msg 2024-11-17 09:58:57 +08:00
Slnanx
fb4b8d923a 可以通过判断系统语言来显示对应语言 (#6083) 2024-11-17 09:42:40 +08:00
2dust
2ade705e51 Bug fix 2024-11-16 20:15:05 +08:00
NagisaEfi
e0086b4b79 Update ResUI.zh-Hant.resx (#6080) 2024-11-16 10:34:55 +08:00
2dust
8f6d443104 Hide to tray when closing the window
https://github.com/2dust/v2rayN/issues/6076
2024-11-15 19:50:37 +08:00
2dust
5dbce16895 up 7.1.1 2024-11-15 13:36:44 +08:00
2dust
1016dcb3d1 Improve PAC 2024-11-15 11:59:22 +08:00
2dust
ba5ad12e13 Linux password encryption storage 2024-11-15 09:42:49 +08:00
2dust
57f9c8158e up 7.1.0 2024-11-14 15:20:14 +08:00
2dust
b8a0293b52 Add xhttp extra for xray
https://github.com/XTLS/Xray-core/pull/4000
2024-11-14 14:37:03 +08:00
2dust
59b7daaef5 Improve UI 2024-11-14 14:25:58 +08:00
2dust
d781c768e9 Add xhttp mode for xray
https://github.com/XTLS/Xray-core/pull/3994
2024-11-14 09:48:43 +08:00
2dust
04efed2079 SplitHTTP is now XHTTP for xray 2024-11-13 19:48:44 +08:00
2dust
2de9e14c7d xray-core uses quic to add failure prompts and plans to remove quic 2024-11-13 19:00:35 +08:00
2dust
a849dec6c2 Remove SagerNet 2024-11-13 18:00:31 +08:00
2dust
28019dc511 Migrate xray traffic statistics to Metrics
https://xtls.github.io/config/metrics.html
2024-11-13 16:45:23 +08:00
2dust
9d638968a9 Use tun mode without running with sudo in linux 2024-11-13 16:22:56 +08:00
2dust
f921ff7d77 Update README.md 2024-11-13 16:00:01 +08:00
NagisaEfi
e3ea329795 Update ResUI.zh-Hant.resx (#6049) 2024-11-13 09:49:41 +08:00
TTG
87f1c129b6 Update DNS Routing (#6045)
* Update DNS Routing

* Removed outdated DNS IP
2024-11-12 09:42:10 +08:00
2dust
a1c8bc0e61 Improve the code 2024-11-11 16:56:08 +08:00
fonaix
61e9101851 添加:MacOS 打开存储所在位置功能 (#6038)
* 添加:MacOS 代理配置与清除

* 修复:点击表头排序时,超时服务器排在前面的问题

* 添加:MacOS 打开存储所在位置功能

* 修复:删除全部节点时,UI不更新的问题
2024-11-11 09:48:20 +08:00
2dust
a6289347cc Bug fix
https://github.com/2dust/v2rayN/issues/6037
2024-11-11 09:37:49 +08:00
2dust
9e84de8e76 Migrating the sing-box configuration to 1.10.0
https://sing-box.sagernet.org/migration/#tun-address-fields-are-merged
2024-11-10 17:30:03 +08:00
2dust
d04cc53152 Fill ResUI 2024-11-10 17:25:36 +08:00
2dust
1ff3c5fc07 Fix
https://github.com/2dust/v2rayN/issues/6032
2024-11-10 17:24:41 +08:00
2dust
3db047a12f Fix 2024-11-09 14:37:48 +08:00
TTG
bf4615f2f2 Update Configuration to Optimize (#6027)
* Remove geolocation-cn

* Segment and update DNS lists
2024-11-09 09:28:10 +08:00
2dust
798c7fad9a up 7.0.9 2024-11-08 20:44:28 +08:00
2dust
5797b37262 Bug fix
https://github.com/2dust/v2rayN/issues/6023
2024-11-08 20:41:07 +08:00
2dust
ce22f34cd6 up 7.0.8 2024-11-08 20:01:36 +08:00
2dust
4c49e52e26 Bug fix
https://github.com/2dust/v2rayN/issues/5963
2024-11-08 19:24:36 +08:00
2dust
47318b5d70 Improve the code for Desktop Exit 2024-11-08 11:11:06 +08:00
2dust
d12297909c Improve the code for WPF Global Window 2024-11-08 11:04:03 +08:00
fonaix
5fb4edae2d 添加:MacOS 代理配置与清除 (#6018)
* 添加:MacOS 代理配置与清除

* 修复:点击表头排序时,超时服务器排在前面的问题
2024-11-08 09:21:43 +08:00
DecorativeFamily
c4b490e46d [CodeFactor] Apply fixes (#6005)
Co-authored-by: codefactor-io <support@codefactor.io>
2024-11-07 14:46:27 +08:00
2dust
45febe3fff up 7.0.7
https://github.com/2dust/v2rayN/issues/5970
2024-11-06 15:00:45 +08:00
2dust
689a81a985 Built-in font for Desktop
https://github.com/2dust/v2rayN/issues/5970
2024-11-06 14:52:54 +08:00
2dust
28620b385a Update MsgView.xaml
https://github.com/2dust/v2rayN/issues/5997
2024-11-05 19:49:27 +08:00
2dust
be13446e69 Speed ​​test address maintenance 2024-11-04 14:21:11 +08:00
2dust
ee57d5b8e6 Improve checkup date 2024-11-04 14:15:59 +08:00
2dust
4eda3dd8fa Add Memo attribute to subscription group
https://github.com/2dust/v2rayN/issues/5981
2024-11-04 10:42:42 +08:00
2dust
911dc7f90e Revert
9fd20ff001
2024-11-04 10:37:44 +08:00
fonaix
18005b96e8 修复:双击表头弹出编辑窗口的问题 (#5984)
* 修复:日志文本框垂直显示上下空白问题

* 修复:双击表头弹出编辑窗口的问题
2024-11-04 09:44:03 +08:00
2dust
a3e45d206e Bug fix
https://github.com/2dust/v2rayN/issues/5979
2024-11-03 21:15:50 +08:00
2dust
0accf262dc up 7.0.6 2024-11-03 16:49:06 +08:00
2dust
e0eb73bb0a Code clean 2024-11-03 16:45:48 +08:00
2dust
258e822c13 Add exit function to the main interface for Desktop 2024-11-03 14:48:13 +08:00
2dust
4f05b93d63 Bug fix
MainModule FileName only exists in Win32.
2024-11-03 13:44:12 +08:00
2dust
bb661d4f50 Only one instance is allowed to run 2024-11-03 13:30:32 +08:00
2dust
201cfaa922 Fix
https://github.com/2dust/v2rayN/issues/5966
2024-11-02 15:02:30 +08:00
2dust
c339aa349c up PackageReference 2024-11-02 14:42:26 +08:00
2dust
046421f345 Code clean 2024-11-02 14:42:01 +08:00
fonaix
3a2c9e7aaa 修复:日志文本框垂直显示上下空白问题 (#5967) 2024-11-02 10:28:18 +08:00
2dust
0bb6e6bd86 up 7.0.5 2024-11-01 16:54:16 +08:00
2dust
693e8ab157 Add startup auto-start for desktop 2024-11-01 14:54:23 +08:00
2dust
033c16c992 Refactor to select active nodes when updating subscriptions 2024-11-01 10:19:31 +08:00
2dust
6ec61433fb Only update the stable version of the core
https://github.com/2dust/v2rayN/issues/5950
2024-11-01 09:26:15 +08:00
2dust
072f773245 up 7.0.4 2024-10-31 09:59:59 +08:00
2dust
0086f65a96 Bug fix
b7f4fd7469
2024-10-30 08:57:10 +08:00
2dust
281f14f47e Adjustment of preset rule sets 2024-10-28 13:45:39 +08:00
2dust
9fd20ff001 De-duplication after subscription update 2024-10-28 09:38:20 +08:00
2dust
7df90a6034 Bug fix
https://github.com/2dust/v2rayN/issues/5928
2024-10-28 09:16:24 +08:00
2dust
019869ec28 up 7.0.3 2024-10-27 15:01:14 +08:00
2dust
b7f4fd7469 Add font settings for Desktop 2024-10-27 14:59:06 +08:00
2dust
1273d2aee1 Improved font settings 2024-10-27 14:57:45 +08:00
2dust
88990b4828 Bug fix
0efb0b5e3e
2024-10-26 18:00:22 +08:00
2dust
2f02c2970c UseShellExecute = true 2024-10-26 17:55:36 +08:00
2dust
ade789c6d4 Update UpgradeApp.cs 2024-10-26 17:55:08 +08:00
2dust
9738f90970 up 7.0.2 2024-10-26 15:00:57 +08:00
2dust
6ed0741339 Bug fix
https://github.com/2dust/v2rayN/issues/5923
2024-10-26 14:57:28 +08:00
2dust
e6b1e22245 Update UpgradeApp.cs 2024-10-26 14:42:58 +08:00
2dust
6b922be0c6 Set AssemblyName to v2rayN 2024-10-26 10:42:29 +08:00
2dust
6e35a260e8 Bug fix
https://github.com/2dust/v2rayN/issues/5915
2024-10-26 09:55:22 +08:00
2dust
1106fd8cf1 Give upgrade app execute permission at runtime 2024-10-25 20:32:47 +08:00
2dust
fb92b90d5c Bug fix
https://github.com/2dust/v2rayN/issues/5909
2024-10-25 17:58:54 +08:00
2dust
5effbee50b Fix
https://github.com/2dust/v2rayN/issues/5905
2024-10-25 17:41:01 +08:00
2dust
9bc50a9f34 up 7.0.1 2024-10-25 13:50:17 +08:00
2dust
2a5a339c27 Update UpgradeApp.cs 2024-10-25 11:56:15 +08:00
2dust
78d182fff3 Add a warning about the use of insecure HTTP protocol subscription address 2024-10-25 11:06:04 +08:00
2dust
0efb0b5e3e Give core execute permission at runtime 2024-10-25 10:10:55 +08:00
2dust
a2e8755730 Xray Asset Location use XRAY_LOCATION_ASSET 2024-10-25 09:31:16 +08:00
2dust
06ddedbc4c The core folder is all lowercase letters 2024-10-25 09:27:11 +08:00
2dust
fa148cdf42 Bug fix 2024-10-25 09:01:59 +08:00
2dust
c1f71dee15 up 7.0.0 2024-10-24 17:57:04 +08:00
2dust
871cb81323 Code clean 2024-10-24 17:56:39 +08:00
2dust
34f5c0f910 Adding checks for subscription url 2024-10-24 17:09:07 +08:00
2dust
3fafc6de93 Code optimization 2024-10-24 15:35:37 +08:00
2dust
b013213745 Remove simple routing settings 2024-10-24 10:55:15 +08:00
2dust
40ea454a7c Remove X86 support 2024-10-24 10:32:19 +08:00
2dust
f0bac4b4c8 Code optimization 2024-10-24 10:25:02 +08:00
2dust
ffb38129e2 The first letter of the guiconfig attribute must be capitalized. 2024-10-23 17:19:57 +08:00
2dust
3c550c094a The first letter of the guiconfig attribute must be capitalized. 2024-10-23 17:00:33 +08:00
2dust
2d143687b8 The first letter of the guiconfig attribute must be capitalized. 2024-10-23 10:42:35 +08:00
2dust
1e7284f141 Bug fix 2024-10-23 10:18:55 +08:00
DecorativeFamily
50bdf0927c use Dependabot keep actions updated to latest (#5886)
like: v2-->v3
2024-10-23 09:35:02 +08:00
2dust
10a60b26fa After the Linux version updates the core, set chmod+x 2024-10-22 20:08:33 +08:00
2dust
b3c2084b76 Code optimization, function asynchrony 2024-10-22 17:50:42 +08:00
2dust
3bf2dc711d Improved fontsize 2024-10-22 11:04:12 +08:00
2dust
5a7836115e Fix some code 2024-10-22 09:46:50 +08:00
gush4
0da9cb45bd Add icon for PAC mode (#5876)
Co-authored-by: author <mail@example.com>
2024-10-22 09:32:07 +08:00
2dust
28aa954f8c Improved CheckUpdate 2024-10-21 20:31:19 +08:00
2dust
4fc71fb77e Merge branch 'master' of https://github.com/2dust/v2rayN 2024-10-21 20:29:54 +08:00
2dust
5ea6b1e08a Update RetResult 2024-10-21 18:18:41 +08:00
runetfreedom
0cdfc97460 change ru templates path (#5869) 2024-10-21 13:47:38 +08:00
2dust
3dd54312e7 Code optimization, function asynchrony 2024-10-21 13:46:13 +08:00
2dust
a866017b4c Code optimization, function asynchrony 2024-10-21 09:45:33 +08:00
2dust
394b657fc9 Code optimization, function asynchrony 2024-10-20 11:51:05 +08:00
2dust
50449df08d Improved 2024-10-19 14:30:14 +08:00
2dust
fe3836be14 Bug fix QRCodeHelper 2024-10-19 14:29:53 +08:00
runetfreedom
055cd62dd8 Sing-box srs updating support (#5855) 2024-10-18 20:33:41 +08:00
runetfreedom
4d1f7fa60c External dns configs support + ru translation (#5854)
* Ru translation

* External dns for presets
2024-10-18 17:54:47 +08:00
2dust
5c0fba8744 Add scanning QR code from image 2024-10-18 17:35:32 +08:00
2dust
b74ddc0b43 Adjust Resources 2024-10-17 15:29:23 +08:00
2dust
d004c6860e Add check update for sing-box 2024-10-17 15:28:32 +08:00
2dust
fc3ba6c030 Improved UI 2024-10-16 19:36:38 +08:00
2dust
9c4dc185be Adjust some code
https://github.com/2dust/v2rayN/pull/5840
2024-10-16 15:42:44 +08:00
runetfreedom
2edbbc523a External routing rules templates + regional presets support (#5840)
* External routing rules templates + auto download geo file if repo changed

* Regional presets support
2024-10-16 14:11:20 +08:00
2dust
a5122b656d Bug fix for Dsktop 2024-10-16 10:52:45 +08:00
2dust
74f980aab1 Refactor system proxy 2024-10-16 09:20:05 +08:00
2dust
35e5475255 Add system proxy for kde 2024-10-15 20:22:26 +08:00
2dust
fb649c04cf Code clean 2024-10-15 15:17:05 +08:00
2dust
4ce7ca3c6f Fix
https://github.com/2dust/v2rayN/pull/5835
2024-10-15 13:37:36 +08:00
runetfreedom
eebb6735aa Add sing-box srs custom url support for fix TUN (#5835)
Co-authored-by: 2dust <31833384+2dust@users.noreply.github.com>
2024-10-15 13:28:51 +08:00
2dust
e96c9abd69 Improved share Uri
https://github.com/2dust/v2rayN/issues/5807
2024-10-15 11:02:17 +08:00
2dust
fd7cf164ff Fix
https://github.com/2dust/v2rayN/issues/5821
2024-10-15 09:31:30 +08:00
2dust
24afe8bde4 Fix
https://github.com/2dust/v2rayN/pull/5829
2024-10-14 19:29:15 +08:00
2dust
9540669f56 prefer_ipv4 for sing-box dns strategy
https://github.com/2dust/v2rayN/issues/5790
2024-10-14 19:27:22 +08:00
runetfreedom
c6caf29b5b Custom geo file source from settings (#5829)
Co-authored-by: 2dust <31833384+2dust@users.noreply.github.com>
2024-10-14 17:50:44 +08:00
2dust
2698137dea Improved UI
https://github.com/2dust/v2rayN/issues/5814
2024-10-14 17:28:10 +08:00
2dust
bdae08b13b Improved UI 2024-10-14 14:27:53 +08:00
2dust
019c69ecff Refactor Common 2024-10-14 10:57:40 +08:00
2dust
6b99b7eec5 Refactor Utils 2024-10-14 10:42:05 +08:00
2dust
4eb443e547 Bug fix for IsAdministrator
This reverts commit 7618f9f7d4.
2024-10-13 20:15:43 +08:00
2dust
e530789739 Improved Desktop TrayIcon 2024-10-12 19:46:06 +08:00
2dust
7618f9f7d4 Refactor new StatusBarViewModel 2024-10-12 15:45:21 +08:00
2dust
d7bde77977 up PackageReference 2024-10-11 15:06:48 +08:00
2dust
a0286ff810 Improved MessageBus contract 2024-10-11 10:17:44 +08:00
2dust
b172b03927 Improved UI for Desktop 2024-10-11 09:24:15 +08:00
2dust
a556bf9487 Improved ReactiveCommand.CreateFromTask 2024-10-10 18:02:09 +08:00
2dust
4f5362fdc4 Update build.ps1 2024-10-10 14:05:14 +08:00
2dust
176a91e7c5 Update build.ps1 2024-10-09 20:44:37 +08:00
2dust
3c45ef624a Rename v2rayUpgrade 2 AmazTool 2024-10-09 20:13:25 +08:00
2dust
fea7c9fbd7 Improved CliWrap 2024-10-08 20:45:56 +08:00
2dust
aa6b6e3849 Remove Mono.Posix.NETStandard 2024-10-08 17:40:25 +08:00
2dust
f5956e7bf0 Improved await _updateView 2024-10-08 14:55:06 +08:00
2dust
b2669103dc Refactor Upgrade 2024-10-08 14:03:15 +08:00
2dust
53e19ecb1d Improved Action Invoke 2024-10-08 13:47:13 +08:00
2dust
3e74bb65bd Improved models 2024-10-08 09:50:03 +08:00
2dust
f60575b77c Improved CoreInfo 2024-10-07 20:10:00 +08:00
2dust
7a839063d0 Refactor CoreHandler 2024-10-07 11:18:24 +08:00
2dust
4ccc7aa92d Refactor NoticeHandler 2024-10-07 10:59:13 +08:00
2dust
d5c6a42a9a Refactor some service 2024-10-07 10:39:43 +08:00
2dust
3bdef4d6d8 Rename LazyConfig to AppHandler 2024-10-07 09:51:41 +08:00
2dust
f40eb724d7 Add AppViewModel for Desktop 2024-10-06 21:16:17 +08:00
2dust
4d84eede56 Refactor ProxySettingWindows 2024-10-06 20:44:43 +08:00
2dust
53a2fbd0ff Bug fix 2024-10-06 10:42:08 +08:00
2dust
409fe5290e Implementing IsAdministrator for non-Windows 2024-10-06 10:23:44 +08:00
2dust
75d86cf883 Remove SagerNet clash clash_meta 2024-10-05 17:51:31 +08:00
2dust
b33f536dbd Improved UI for Desktop PathIcon 2024-10-05 14:53:34 +08:00
2dust
1f77c56eaf Fix TrayIcon display 2024-10-05 11:12:52 +08:00
2dust
fe895b1b27 Improved v2rayUpgrade 2024-10-05 10:43:37 +08:00
2dust
20bb263b06 Bug fix for check update 2024-10-04 17:10:30 +08:00
2dust
3ecbd3bc10 Improved UI for Desktop CheckUpdate 2024-10-04 16:01:36 +08:00
2dust
fe81b51dcb Add BackupAndRestore 2024-10-04 15:22:32 +08:00
2dust
90ba80436d Improved UI for Desktop version 2024-10-04 14:25:09 +08:00
2dust
2bb5f6afc4 Add DialogHost fro Desktop 2024-10-03 17:22:07 +08:00
2dust
3971318ffb Improved UI for routing rules 2024-10-03 13:56:06 +08:00
2dust
5fbeb4b0fb Improved UI for Desktop version 2024-10-02 21:08:17 +08:00
NagisaEfi
1b2b838bc0 Update ResUI.resx and ResUI.zh-Hant.resx (#5767) 2024-10-01 09:49:02 +08:00
2dust
8e28cc01b8 Fix TextFormattingMode = Display
https://github.com/2dust/v2rayN/discussions/5740
2024-09-30 09:29:06 +08:00
2dust
77a59e9107 StorageUI and RestoreUI 2024-09-29 20:59:53 +08:00
2dust
1411643192 Add system proxy for Linux 2024-09-28 10:41:30 +08:00
2dust
fde2a768cf Improved UI for Desktop version 2024-09-27 20:25:06 +08:00
2dust
b008a58cf8 Code improvements 2024-09-27 09:58:33 +08:00
2dust
8e02394ff4 Adjustments to automatically update GEO files 2024-09-27 09:58:09 +08:00
2dust
60a75d9a31 up 6.60 2024-09-23 17:23:23 +08:00
2dust
24566901fb up PackageReference 2024-09-23 17:22:14 +08:00
2dust
cc428618e5 Adjusting the text display 2024-09-23 17:17:12 +08:00
2dust
4d330cedac Disable auto update geo 2024-09-23 17:05:03 +08:00
2dust
2503583498 System proxy and tun mode
https://github.com/2dust/v2rayN/issues/5651
2024-09-23 17:03:28 +08:00
2dust
1b11916e1e Preparing to remove part of the core
https://github.com/2dust/v2rayN/discussions/5703
2024-09-23 15:16:32 +08:00
2dust
3dfd557265 Fix the problem of showing and hiding statistics columns 2024-09-23 15:00:25 +08:00
2dust
cd6bea28b6 Improved font display
https://github.com/2dust/v2rayN/issues/5713
2024-09-23 14:10:58 +08:00
2dust
054f0f2bc7 Bug fix
https://github.com/2dust/v2rayN/issues/5725
2024-09-23 13:37:18 +08:00
2dust
97347674e7 Bug fix
https://github.com/2dust/v2rayN/issues/5724
2024-09-23 12:09:17 +08:00
2dust
36d15852aa Setting up not to automatically update the GEO file on first run
https://github.com/2dust/v2rayN/issues/5704
2024-09-23 11:04:37 +08:00
2dust
4813610492 When running for the first time, switch the interface language to English when judging that the system language is not Chinese.
https://github.com/2dust/v2rayN/issues/5670
2024-09-23 11:01:03 +08:00
2dust
243dbab06a Fix ?! 2024-09-18 19:54:38 +08:00
2dust
073eaa9a26 Bug fix 2024-09-18 09:31:14 +08:00
2dust
cb1f936d05 Fix Speedtest bug 2024-09-17 18:41:01 +08:00
2dust
a7f3a7b1a7 up 6.59 2024-09-17 18:07:07 +08:00
2dust
71eb5f0813 HyperlinkButton Classes="WithIcon" 2024-09-17 17:26:01 +08:00
2dust
b4f50258a7 Fix style for desktop 2024-09-17 17:20:37 +08:00
2dust
346a9c5fcc Add Connections Host Filter 2024-09-17 16:59:35 +08:00
2dust
61635db5b5 Add IsNotEmpty function 2024-09-17 16:52:41 +08:00
2dust
4c0a59a715 Add Connections Host Filter
https://github.com/2dust/v2rayN/issues/5683
2024-09-17 14:50:31 +08:00
2dust
aa829a66ea Improved Style for Desktop version 2024-09-16 18:21:30 +08:00
2dust
885f193a00 Fix GetVersion 2024-09-16 15:34:35 +08:00
2dust
0a9bbf526d up PackageReference 2024-09-16 15:26:17 +08:00
2dust
ff6716b39d Restore backup file check 2024-09-16 15:23:06 +08:00
2dust
8505f2db96 Optimize backup
https://github.com/2dust/v2rayN/issues/5681
2024-09-16 13:37:38 +08:00
2dust
233d605256 Optimize the information function 2024-09-16 11:09:44 +08:00
2dust
c4e01d20a0 up 6.58 2024-09-08 13:39:13 +08:00
2dust
07156cb55c Bug fix 2024-09-08 10:45:05 +08:00
2dust
8361b4e4a0 Fix 2024-09-07 19:04:19 +08:00
2dust
bb90671979 Fix 2024-09-07 18:08:56 +08:00
2dust
beddc71ed8 Add backup and restore 2024-09-07 14:52:33 +08:00
2dust
d5f1cc99ac Refactor V2rayUpgrade 2024-09-06 18:37:46 +08:00
2dust
d03a86292e Add SaveFileDialog 2024-09-06 15:51:06 +08:00
2dust
c061a24948 Update v2rayUpgrade 2024-09-06 14:07:48 +08:00
2dust
9c7446f820 In-app update alone package 2024-09-06 14:07:26 +08:00
2dust
8be1730719 Bug fix 2024-09-06 09:40:45 +08:00
2dust
7ceaf5c071 Add preprocess of yaml file
https://github.com/2dust/v2rayN/issues/5646
2024-09-06 08:57:42 +08:00
2dust
7901a59aa4 Code clean 2024-09-05 13:29:51 +08:00
2dust
8343a1002f Improvement check updates for Desktop 2024-09-05 13:29:25 +08:00
2dust
c83dce3cc0 Fix
https://github.com/2dust/v2rayN/issues/5644
2024-09-05 10:02:26 +08:00
2dust
14afeab2bb Fix
https://github.com/2dust/v2rayN/issues/5640
2024-09-05 09:55:36 +08:00
2dust
c22b57927c up 6.57 2024-09-04 16:23:10 +08:00
2dust
81b84d235c Code clean 2024-09-04 16:15:31 +08:00
2dust
488e8aab00 Improvement check updates 2024-09-04 15:47:17 +08:00
Wydy
fc43a9a726 Update pac.txt (#5636) 2024-09-04 09:42:54 +08:00
2dust
31947fdcb3 Bug fix
https://github.com/2dust/v2rayN/issues/5635
2024-09-03 19:30:23 +08:00
2dust
34c7963d28 Bug fix
https://github.com/2dust/v2rayN/issues/5627
2024-09-03 16:14:49 +08:00
2dust
d91b0afb9a Improved log message display 2024-09-03 16:03:26 +08:00
2dust
82eb3fd6bd Unified processing version 2024-09-03 10:16:50 +08:00
2dust
3d3d3f83df Bug fix
https://github.com/2dust/v2rayN/issues/5619#issuecomment-2323968966
2024-09-02 15:10:34 +08:00
2dust
6879c75bc8 Using Queues to Improve Message Display 2024-09-02 14:20:09 +08:00
2dust
b02ad6cdab up 6.56 2024-09-01 19:56:11 +08:00
2dust
f7b16952ea PackageReference 2024-09-01 19:51:18 +08:00
2dust
f0d05a7d4e Refactor check updates 2024-09-01 16:39:45 +08:00
2dust
d6ca317b20 xray mux add more option
https://github.com/2dust/v2rayN/issues/5565
2024-08-31 10:12:21 +08:00
2dust
2879fddfd9 sinb-box mux add padding option
https://github.com/2dust/v2rayN/issues/5544
2024-08-31 09:38:15 +08:00
2dust
b6c09470fc Add global exception catching 2024-08-30 13:47:53 +08:00
2dust
9fdf6c6c32 Bug fix 2024-08-30 13:15:25 +08:00
2dust
79085af994 Bug fix 2024-08-30 12:59:43 +08:00
2dust
d189f4b443 Add custom config Socks port to the group
https://github.com/2dust/v2rayN/issues/5576
2024-08-30 10:12:40 +08:00
2dust
c9d65e5cd9 Fix
https://github.com/2dust/v2rayN/issues/5595
2024-08-30 09:31:44 +08:00
2dust
639d62588a Refactor click event 2024-08-29 20:32:00 +08:00
2dust
6c9db51fd5 Creating a new desktop app with avaloniaui 2024-08-29 15:48:51 +08:00
2dust
f0dbb6b22c Bug fix 2024-08-29 15:19:03 +08:00
2dust
f10f7b6268 Add Portable Mode for mihomo 2024-08-29 10:10:55 +08:00
2dust
48a5cbc552 Check for standalone windows .Net version 2024-08-29 10:09:45 +08:00
2dust
6721d150e0 Refactor QRCodeHelper 2024-08-28 10:20:37 +08:00
2dust
54c16cad7d Adding OSPlatform Processing 2024-08-27 19:44:50 +08:00
2dust
ae3ab15245 Add Socks Protocol string 2024-08-27 16:09:07 +08:00
2dust
d3c0f50fec Adjustment of server binding 2024-08-27 13:18:18 +08:00
2dust
43753b1b7a Add linux download url 2024-08-27 13:06:39 +08:00
2dust
6f3e4b3682 Adding OSPlatform Processing 2024-08-26 18:45:41 +08:00
2dust
b57cdd31bd Refactor_updateView to add task 2024-08-22 19:51:10 +08:00
2dust
b936c194e4 Refactor v2rayUpgrade 2024-08-22 15:23:29 +08:00
2dust
064431421a Bug fix 2024-08-21 21:12:01 +08:00
TTG
9d49c7aad0 Update custom_routing_white (#5566) 2024-08-21 11:18:15 +08:00
2dust
a6f27e5071 Code clean 2024-08-20 14:30:45 +08:00
2dust
8d1d10b783 Refactoring Project 2024-08-20 14:15:29 +08:00
2dust
61bea05f63 Refactoring Project 2024-08-19 18:15:54 +08:00
2dust
bbe7c7b884 Optimized code 2024-08-18 15:04:56 +08:00
Milinda Brantini
a432852b78 Update cidr for direct outboundTag (#5550)
Signed-off-by: Milinda Brantini <C_A_T_T_E_R_Y@outlook.com>
2024-08-18 09:59:33 +08:00
2dust
770e8b8cfa >Export Base64-encoded Share Links to Clipboard 2024-08-17 20:53:42 +08:00
2dust
7faabdc375 Refactor code to decouple view and viewmodel 2024-08-17 10:53:02 +08:00
2dust
a9860418ba Optimized code 2024-08-15 21:03:00 +08:00
2dust
30ff9d0ea9 Optimized code
CoreInfoHandler
2024-08-15 20:13:59 +08:00
2dust
bbc2298939 Bug fix
https://github.com/2dust/v2rayN/issues/5517
2024-08-15 13:58:07 +08:00
2dust
3286e8e24d Refactor code to decouple view and viewmodel 2024-08-15 13:51:30 +08:00
2dust
372f3991e1 Refactor code to decouple view and viewmodel 2024-08-12 20:25:31 +08:00
2dust
9aa5c0d135 Refactor code to decouple view and viewmodel 2024-08-11 20:44:29 +08:00
2dust
9e9808e489 Refactor code to decouple view and viewmodel 2024-08-11 15:45:55 +08:00
2dust
3dd75b17cf Clean code 2024-08-10 19:20:31 +08:00
2dust
2504b4737b Refactor code to decouple view and viewmodel 2024-08-10 14:44:25 +08:00
2dust
8ff04dca0d Refactor code to decouple view and viewmodel 2024-08-10 10:02:00 +08:00
2dust
d893ee4829 up 6.55 2024-08-05 14:41:54 +08:00
2dust
dfc5ec0705 Improve UI 2024-08-05 14:39:04 +08:00
2dust
8023eb74c9 Bug fix 2024-08-04 19:26:01 +08:00
2dust
bb4d3997ad Bug fix
https://github.com/2dust/v2rayN/issues/5467
2024-08-04 09:40:33 +08:00
2dust
7ede3af762 up 6.54 2024-08-03 16:02:42 +08:00
2dust
97ea1c7a9e Add toolTip 2024-08-03 15:59:00 +08:00
2dust
43bb2c0fb8 Bug fix
https://github.com/2dust/v2rayN/issues/5462
2024-08-03 15:37:47 +08:00
2dust
6e7196bb27 Bug fix
https://github.com/2dust/v2rayN/issues/5437
2024-07-31 20:13:41 +08:00
2dust
87a71d58e8 Fix
https://github.com/2dust/v2rayN/issues/5438
2024-07-30 16:22:54 +08:00
2dust
32ffd43fe3 Bug fix
https://github.com/2dust/v2rayN/issues/5425
2024-07-30 16:06:43 +08:00
2dust
6500c8d85e up 6.53 2024-07-26 11:05:53 +08:00
2dust
9866d436da Add Outbound DNS address
https://github.com/2dust/v2rayN/issues/5387
2024-07-26 11:00:07 +08:00
2dust
0f4884d9d8 Improve and refactor the code 2024-07-25 10:26:39 +08:00
2dust
5a81441351 Adjust resx 2024-07-24 20:14:07 +08:00
2dust
e8721bfb6b Default dns changed to whitelist 2024-07-24 20:01:26 +08:00
2dust
1b09d95209 Improve UI 2024-07-24 19:51:13 +08:00
Jabin Kong
35f3b5a50e 1 (#5394) 2024-07-23 20:41:00 +08:00
2dust
ff5203a561 alpn h2,h3 2024-07-23 20:33:02 +08:00
2dust
c3c1ced309 up 6.52 2024-07-21 15:15:51 +08:00
2dust
08b1c8ec83 Improve latency testing 2024-07-21 15:15:00 +08:00
NagisaEfi
1dd3ee4e0a Update English translations (#5381)
* Update ResUI.resx

* Update ResUI.resx
2024-07-21 11:48:55 +08:00
Random Guy
06d0c6517d fix: add real delay test for custom config (#5377) 2024-07-21 11:44:12 +08:00
2dust
4938ce6364 Code clean 2024-07-21 11:37:11 +08:00
2dust
25f3fc354f Add multi-server load balancing 2024-07-21 11:26:10 +08:00
2dust
ad1a1f8015 Main window layout orientation setting 2024-07-19 20:31:07 +08:00
2dust
5c070e2ca8 Improve UI 2024-07-19 10:51:14 +08:00
2dust
70ea21fca2 Improve UI 2024-07-18 19:59:46 +08:00
2dust
bc3593871b Refactor the main interface 2024-07-18 17:39:11 +08:00
2dust
355a424be2 Code clean 2024-07-18 17:31:49 +08:00
2dust
0ffa9a0cc8 Remove unused resx
Remove Batch export subscription to clipboard
2024-07-15 20:17:55 +08:00
2dust
72fecb2b9a Add clash_mode to rule 2024-07-14 20:17:48 +08:00
2dust
4e9dfe5478 Improve 2024-07-14 17:16:07 +08:00
2dust
c79e2e3ad4 Add functionality multi-server set as active
Implemented using sing-box Selector, which can be switched using the clash api
2024-07-14 16:13:28 +08:00
2dust
7c33c1c322 Add reload for ClashProxiesView 2024-07-14 14:28:45 +08:00
2dust
ea32f75925 Code clean 2024-07-14 11:00:22 +08:00
2dust
7eaed21b9a Improve 2024-07-14 10:59:36 +08:00
2dust
cfe8fcd28d up 6.51 2024-07-12 14:23:29 +08:00
2dust
9f4718af70 Code clean
Add allowInsecure to Share
2024-07-11 14:42:01 +08:00
2dust
39faccfd0b Bug fix 2024-07-10 17:32:26 +08:00
2dust
7545763dae Default domain strategy for resolving the outbound domain names -- singbox 2024-07-08 18:45:29 +08:00
2dust
c2928be35d Log messages are not displayed when in the background 2024-07-08 17:16:49 +08:00
2dust
449bb40d48 sing-box prioritizes the use of local srs 2024-07-08 14:20:41 +08:00
2dust
4caf1a1e63 Improve and refactor the code 2024-07-08 09:52:11 +08:00
2dust
01b205e6f1 Adjust information DispatcherPriority 2024-07-07 21:11:04 +08:00
2dust
160d3843a6 Bug fix 2024-07-05 15:28:28 +08:00
2dust
5efb784115 up 6.50 2024-07-05 11:18:36 +08:00
2dust
acde5b8384 Bug fix 2024-07-05 11:18:14 +08:00
2dust
373ee6586a Optimize system proxy code 2024-07-04 17:07:05 +08:00
2dust
215308c329 Change srs source
https://github.com/2dust/sing-box-rules
2024-07-04 16:27:44 +08:00
2dust
478cadba5e Bug fix 2024-06-30 20:43:06 +08:00
2dust
f4af4da791 Adjust res 2024-06-30 10:00:28 +08:00
2dust
22d4f435de Add tun and mixin functions to clash 2024-06-28 20:29:44 +08:00
2dust
ccb8cd5c04 up 6.49 2024-06-28 16:14:45 +08:00
2dust
e963f9e349 Add clash display in the main interface 2024-06-28 16:14:19 +08:00
2dust
e3c2a4b8da Bug fix 2024-06-28 10:41:17 +08:00
2dust
324f46cdad Bug fix
https://github.com/2dust/v2rayN/discussions/5268
2024-06-27 17:59:39 +08:00
2dust
691b19b5fd Adding support for the clash proxies interface 2024-06-27 16:36:36 +08:00
2dust
63ed2311dc Bug fix 2024-06-26 16:00:37 +08:00
2dust
d59e59ca40 up 6.48 2024-06-24 17:42:37 +08:00
2dust
c9a278b4a2 Check for updates mihomo 2024-06-24 17:41:53 +08:00
2dust
8ee5304148 Bug fix 2024-06-24 16:42:17 +08:00
2dust
3beaa8145f Bug fix 2024-06-24 16:19:00 +08:00
2dust
e30c55a0af up 6.47 2024-06-24 15:34:41 +08:00
2dust
b583590a64 Update ConfigHandler.cs
https://github.com/2dust/v2rayN/pull/5264
2024-06-24 15:25:00 +08:00
OnceUponATimeInAmerica
a28c63168a Support for setting subs-group remarks (group's name) from the (optional) "remark" query parameter in the pasted subs url (#5264) 2024-06-24 15:20:16 +08:00
2dust
620422350f Improved tun mode
Enabling tun mode.
Only one core will be run when using sing-box core;
When using a non-sing-box, the sing-box will be used to start an additional front Socks service to provide a tun entry, which will then run two cores
2024-06-24 15:19:42 +08:00
2dust
b77cc3c33b Add network attribute to route rule
https://github.com/2dust/v2rayN/discussions/5256
2024-06-22 16:44:15 +08:00
2dust
71bf9b4887 up 6.46 2024-06-21 16:02:08 +08:00
2dust
9039d401da set DOTNET_EnableWriteXorExecute=0 under win10
https://github.com/2dust/v2rayN/issues/5186
2024-06-21 14:09:57 +08:00
2dust
74a0a93201 Improve and refactor the code 2024-06-21 11:15:35 +08:00
2dust
522571f0b3 Add splithttp transport for xray
https://github.com/XTLS/Xray-core/releases/tag/v1.8.15
2024-06-20 16:20:05 +08:00
Lsyx-Good
123c49c22d Adjust singbox DNS server and rule position (#5229) 2024-06-20 16:08:08 +08:00
OnceUponATimeInAmerica
1ff88d29be Extend stats reporting to support custom configs with several load-balanced outbounds in them, with tags starting with "proxy" e.g. proxy1, proxy2 (fully compatible with existing configs) (#5225) 2024-06-20 15:32:10 +08:00
Lsyx-Good
63d5a2a1be Fix bug (#5213) 2024-06-10 15:12:39 +08:00
2dust
1e9a6cb06b Refactor code 2024-06-04 09:48:04 +08:00
2dust
31748aa660 Refactor code 2024-06-03 17:50:18 +08:00
2dust
d0c6ea6a63 remove http://cachefly.cachefly.net/100mb.test 2024-06-03 14:06:59 +08:00
2dust
7ffe286a56 Up PackageReference 2024-06-03 07:37:49 +08:00
2dust
b99b30163b Bug fix 2024-06-03 07:37:26 +08:00
kirilllivanov
83b4f1e660 Fix incorrect filenames (#5122) 2024-05-18 17:11:38 +08:00
2dust
b57ba6a98b up 6.45 2024-05-18 09:53:15 +08:00
2dust
d748e6eff4 Add destOverride 2024-05-14 15:31:19 +08:00
2dust
315d4b75b2 Optimize code 2024-05-14 13:42:42 +08:00
2dust
31267cbc33 Adjust Scan screen qrcode 2024-05-12 17:07:56 +08:00
2dust
c23379b3b6 Adjust sing-box dns 2024-05-12 15:42:28 +08:00
2dust
568144d6a2 TransitionAssist DisableTransitions 2024-05-12 14:59:23 +08:00
2dust
5857042963 Up 6.44 2024-05-08 13:40:24 +08:00
2dust
28e41dc621 Add open the file location 2024-05-08 11:43:03 +08:00
2dust
baef3b364b Bug fix 2024-05-08 11:42:01 +08:00
2dust
4b9ddb803f Bug fix 2024-05-07 14:15:08 +08:00
2dust
c07c7ad82f Added reminder that a reboot is required to modify settings 2024-05-06 17:19:29 +08:00
2dust
e223b80b95 Merge pull request #5066 from sincereliu/master
Optimize code for better performance
2024-05-06 09:55:30 +08:00
sincere liu
5fe468fa1b Optimize code for better performance 2024-05-05 22:07:51 +08:00
2dust
60068d8d16 Themes migrate 2024-05-05 16:19:47 +08:00
2dust
b6c5b46afe Up PackageReference 2024-05-05 10:10:19 +08:00
2dust
124cbfadb4 Add custom sing-box rule-set support 2024-05-04 13:54:22 +08:00
2dust
8d21f9b900 Bug fix 2024-05-04 13:24:13 +08:00
2dust
398dbbd2e5 Bug fix
https://github.com/2dust/v2rayN/issues/5035
2024-05-03 10:29:32 +08:00
2dust
e9b392d1c0 Optimized sorted storage 2024-04-30 14:44:02 +08:00
2dust
9d7c7e3225 Adjust the experimental and mux of sing-box 2024-04-27 10:05:13 +08:00
2dust
855fd4f0b7 Merge pull request #5026 from GibMeMyPacket/feat/singbox/exp_cachefile
Add `Enable cache file for sing-box`
2024-04-27 09:42:31 +08:00
GibMeMyPacket
807839929d Add Enable cache file for sing-box 2024-04-25 12:07:53 +00:00
2dust
870955fee1 Bug fix 2024-04-11 08:07:21 +08:00
2dust
e0cea929ea Up 6.43 2024-04-10 13:52:38 +08:00
2dust
315f4c35f0 Code clean 2024-04-10 13:32:50 +08:00
2dust
d961ea22a6 Built-in routing rule set upgraded to V2 2024-04-10 10:50:52 +08:00
2dust
5c0c07c78f Migrate geosite & geoip to rule sets (sing-box) 2024-04-10 08:42:53 +08:00
2dust
bba93a0fb7 Added tls fragment support (Xray-core)
https://github.com/2dust/v2rayN/issues/4900
2024-04-08 17:06:48 +08:00
2dust
5683df2fc0 Added outbound HTTP support (support group prefix proxy)
https://github.com/2dust/v2rayN/discussions/4550
2024-04-08 14:02:56 +08:00
2dust
b5cb9ce67e Set autoHideStartup default value is false 2024-04-05 17:24:53 +08:00
2dust
06a32dc895 Adjust sing-box dns default example 2024-04-05 11:05:45 +08:00
2dust
dff12a8a3a fix
https://github.com/2dust/v2rayN/issues/4928
2024-04-05 11:04:35 +08:00
2dust
dc3f07ee84 Bug fix 2024-04-03 09:51:07 +08:00
2dust
1aef49ee11 Custom configuration file to use Xray prefix in non-Tun mode
https://github.com/2dust/v2rayN/issues/4855
2024-04-01 08:22:14 +08:00
2dust
ee3159b00e Update 6.42 2024-03-31 17:26:02 +08:00
2dust
86d2c307f1 Bug fix 2024-03-31 17:23:33 +08:00
2dust
7823a217b4 Update 6.41 2024-03-31 08:09:13 +08:00
2dust
2004df8337 Rename Model to Models 2024-03-31 08:08:06 +08:00
2dust
13bc2d0340 Bug fix
https://github.com/2dust/v2rayN/issues/4902
2024-03-31 07:54:22 +08:00
2dust
edbc850346 Update 6.40 2024-03-30 18:12:37 +08:00
2dust
901d3c85ca Up PackageReference 2024-03-30 16:15:13 +08:00
2dust
abbe83f3c2 Fixed issues with multi-core traffic processing 2024-03-30 16:00:19 +08:00
2dust
bb3a04a9c8 Bug fix for exit app 2024-03-30 15:26:12 +08:00
2dust
bac13e8b71 Rename Utile to Utils 2024-03-26 14:26:03 +08:00
2dust
3871681de3 Improve remove Application.Current.Shutdown 2024-03-26 14:22:53 +08:00
2dust
ae6f2b6df6 Up PackageReference 2024-03-26 14:19:14 +08:00
2dust
f59bbc9981 Add authority for grpc 2024-03-23 18:26:44 +08:00
2dust
eac0c84e11 Improve IsNullOrEmpty 2024-03-23 18:26:04 +08:00
2dust
f814cc443d Improve 2024-03-23 10:47:06 +08:00
2dust
262466303b Import Multiple Custom v2ray-core Json Configs from Subscription
https://github.com/2dust/v2rayN/issues/4745
2024-03-23 10:46:45 +08:00
2dust
3b4cc2c5f2 Merge pull request #4848 from 1208nn/patch-2
Update schdtask related code
2024-03-16 16:25:58 +08:00
ShH Y
023d3fbf6f Update Utile.cs 2024-03-16 11:38:41 +08:00
2dust
fe01f290bc Improve 2024-03-13 16:38:37 +08:00
2dust
5805ac9f7f Update 6.39 2024-03-12 09:19:19 +08:00
2dust
4e2f38a343 Clean 2024-03-12 09:14:21 +08:00
2dust
572c924e5c Add httpupgrade 2024-03-12 09:05:59 +08:00
2dust
e90353e550 Bug fix 2024-03-11 14:46:24 +08:00
2dust
f8ae1b8c49 Bug fix 2024-03-11 08:34:07 +08:00
2dust
186d995919 Improve 2024-03-09 14:30:39 +08:00
2dust
70584aff9d Refactor 2024-03-09 10:12:45 +08:00
2dust
dcdc63785a HTTP port=SOCKS port+1;Pac port=SOCKS port+4;API port=SOCKS port+5; 2024-03-09 09:40:19 +08:00
2dust
0e7bfa65de Refactor 2024-03-09 09:27:55 +08:00
2dust
9427340ab7 Update 6.38 2024-03-08 09:55:13 +08:00
2dust
63af5bae8a Bug fix 2024-03-08 09:41:38 +08:00
2dust
9232f1fa40 Merge pull request #4802 from Array-Cats/master
Update README.md
2024-03-08 09:40:28 +08:00
Array-Cats
15bdb551f4 Update README.md 2024-03-07 23:56:58 +08:00
2dust
2cda2b53ed Improve 2024-03-07 11:51:45 +08:00
2dust
028c9ea0b5 Bug fix 2024-03-07 09:06:35 +08:00
2dust
315b51e7ca Up PackageReference 2024-03-05 09:45:27 +08:00
2dust
0185b3b145 Remove some pop-up messages 2024-03-04 10:41:42 +08:00
2dust
afaad49879 Bug fix 2024-03-02 10:35:33 +08:00
2dust
4b2b45979b Return api port=socks port +11 2024-03-02 10:00:28 +08:00
2dust
66e40edd0e Bug fix singbox transport type http 2024-03-02 09:58:50 +08:00
2dust
3d5168885f up 6.37 2024-02-29 17:25:50 +08:00
2dust
6eee2c2342 Add obfs=http support for sing-box ss 2024-02-29 10:11:27 +08:00
2dust
11ec27147a Use Global.None instead of none 2024-02-29 09:43:04 +08:00
2dust
a522a02ba2 Temporarily add compatibility to VLESS 2024-02-29 09:39:12 +08:00
2dust
5ff4d35a30 Added termination speed test 2024-02-25 18:28:59 +08:00
2dust
4c5546bf52 Merge pull request #4757 from NagisaEfi/master
Update translation
2024-02-25 09:28:06 +08:00
NagisaEfi
ab37a46e83 Update translation 2024-02-23 23:46:44 +08:00
2dust
0b3635b5c5 Bug fix 2024-02-21 10:17:28 +08:00
2dust
2a338d9a83 Merge pull request #4743 from NagisaEfi/master
Localization (CHT and ENG)
2024-02-20 16:46:17 +08:00
NagisaEfi
7031a4c26c Localization (CHT and ENG) 2024-02-20 15:59:35 +08:00
2dust
2c5ca97476 Merge pull request #4738 from NimaZare/master
spell check and update
2024-02-20 13:07:28 +08:00
NimaZare
fc0c8f6bb1 spell check and update 2024-02-19 13:13:36 +03:30
2dust
643547704e Up 6.36 2024-02-18 11:09:00 +08:00
2dust
4717b63775 Bug fix 4 mihomo 2024-02-18 11:02:50 +08:00
2dust
4af148f480 Bug fix 2024-02-15 10:34:43 +08:00
2dust
a9c59693ee Bug fix 2024-02-13 10:11:17 +08:00
2dust
9b3ac159c1 Merge pull request #4712 from hxdhttk/hxdhttk/statePortConf
Fix the state ports conflicts when multiple `v2rayN` instances start in a short period.
2024-02-13 09:57:59 +08:00
2dust
c03c98157f Merge pull request #4711 from hxdhttk/hxdhttk/mixedStdErr
Fix misleading "Cannot mix synchronous and asynchronous operation on process stream." logs.
2024-02-13 09:47:19 +08:00
Minghao Hu
74149b761f Resolve the StatePort when the other components call it. 2024-02-12 22:49:57 +09:00
Minghao Hu
44cfa2d8dc Add a start up error receiver. 2024-02-12 22:12:57 +09:00
Minghao Hu
b0fb00d597 Merge new commits. 2024-02-12 21:20:16 +09:00
2dust
af3c1dc039 Bug fix
https://github.com/2dust/v2rayN/issues/4707
2024-02-12 08:49:22 +08:00
2dust
1c94b5d5f0 Up 6.35 2024-02-10 17:07:30 +08:00
2dust
fbb00c0f85 Improve 2024-02-10 16:57:26 +08:00
2dust
4a72e63d1c When updating a subscription, only determine whether the alias already exists 2024-02-09 09:57:28 +08:00
2dust
ce94e0ba4d Refactor 2024-02-08 16:22:38 +08:00
2dust
e2c836794b Refactor 2024-02-08 14:01:33 +08:00
2dust
05e424f805 Bug fix 2024-02-08 09:32:01 +08:00
2dust
bf30819a4a Bug fix
https://github.com/2dust/v2rayN/issues/4334
2024-02-05 20:24:30 +08:00
2dust
52e9d30b46 Improve 2024-02-04 10:02:02 +08:00
2dust
1fa2d55e1d Up PackageReference 2024-02-03 10:27:40 +08:00
2dust
4d0ee652d8 Bug fix 2024-02-03 10:26:37 +08:00
2dust
ff215bc9aa Remove ping test 2024-02-02 10:39:07 +08:00
2dust
e1cadc878a Improve VmessQRCode json 2024-02-02 10:21:13 +08:00
2dust
57d9d8ddb9 Improve 2024-02-01 12:44:47 +08:00
2dust
f76b1a5363 Add editing subscription in the main interface 2024-01-31 10:16:21 +08:00
2dust
9b579be2be Try to remove the tun device when turning on 2024-01-31 09:56:47 +08:00
2dust
9d43465eab Improve 2024-01-30 18:29:52 +08:00
2dust
fc52870431 Add setting 4 SpeedPingTestUrl 2024-01-30 18:04:10 +08:00
2dust
c466ea100a Refactor 2024-01-30 17:18:00 +08:00
2dust
4054369611 Up PackageReference 2024-01-29 17:20:15 +08:00
2dust
11106937a3 Improve 2024-01-29 11:50:24 +08:00
2dust
fdddf901f3 Remove the main interface Encryption Method 2024-01-29 11:15:11 +08:00
2dust
2e30c04238 Migrate from Newtonsoft.Json to System.Text.Json 2024-01-28 19:53:20 +08:00
2dust
bd838094cd bug fix 2024-01-27 18:29:17 +08:00
2dust
6f22b74154 Improve 2024-01-27 10:57:40 +08:00
2dust
e71525db0e Refactor 2024-01-25 17:28:06 +08:00
2dust
d7c1516ec2 bug fix for test shadowsocks 2024-01-23 12:30:11 +08:00
2dust
ff91a5dad9 Add obfs 4 hysteria2 2024-01-22 18:45:22 +08:00
2dust
d76679c2b6 Fill alpns & bug fix 2024-01-20 17:43:42 +08:00
2dust
d7cb88f0a4 Bug fix 2024-01-20 09:45:00 +08:00
2dust
8a3eb41314 Add Wireguard uri 2024-01-16 11:05:51 +08:00
2dust
e2f9aac1c9 remove System.Web 2024-01-16 11:05:02 +08:00
2dust
08c7396404 Add mtu setting 4 Wireguard 2024-01-15 17:11:00 +08:00
2dust
69cbdbd20e Added Wireguard support (using sing-box) 2024-01-14 17:33:41 +08:00
2dust
005f26ba7c bug fix 2024-01-14 10:23:46 +08:00
2dust
a1dc0c8104 Update ResUI.resx 2024-01-14 10:04:02 +08:00
2dust
75435b8fe0 Merge pull request #4621 from yscjr/master
修改修改非管理员模式下tun模式启动逻辑;缩短自动隐藏时间
2024-01-14 10:00:09 +08:00
John Edwerd
6d7385788e 修改修改非管理员模式下tun模式启动逻辑;缩短自动隐藏时间 2024-01-13 21:54:03 +08:00
2dust
726d9d410f Refactor 2024-01-13 16:52:42 +08:00
2dust
ee2a61bb61 bug fix 2024-01-12 18:22:23 +08:00
2dust
40748d6e42 Update ResUI.zh-Hant.resx 2024-01-12 18:06:35 +08:00
2dust
02225ad0b8 Refactor 2024-01-11 18:34:33 +08:00
2dust
3c4703ad85 Optimize code 2024-01-11 18:24:32 +08:00
2dust
6762f35ade Optimize code 2024-01-10 17:44:55 +08:00
2dust
5135afcf8f Refactor 2024-01-10 16:32:26 +08:00
2dust
4aae82e0cc Adjust Tool code 2024-01-10 10:56:10 +08:00
2dust
ea95c6de79 Refactor Utils 2024-01-10 10:43:48 +08:00
2dust
4a67e963ed Up TargetFramework to net8.0 2024-01-10 10:01:59 +08:00
2dust
720f177d65 Merge pull request #4603 from ShiinaRinne/hysteria2_uri
fix https://github.com/2dust/v2rayN/issues/4590
2024-01-10 09:55:51 +08:00
ShiinaRinne
2b4a043a92 fix https://github.com/2dust/v2rayN/issues/4590 2024-01-09 23:20:30 +08:00
2dust
77b20bc562 Merge pull request #4594 from yin1999/bump-action
build(ci): bump actions/upload-artifact from v3 to v4
2024-01-09 09:57:45 +08:00
Allo
063449448a build(ci): bump actions/upload-artifact from v3 to v4 2024-01-08 21:35:28 +08:00
2dust
559ffcbab5 up 6.33 2024-01-06 13:47:03 +08:00
2dust
80ed8346be Bug fix 2024-01-06 10:41:07 +08:00
2dust
a49455f330 Code clean 2024-01-05 13:48:42 +08:00
2dust
c3de6f6d02 Merge pull request #4568 from ShiinaRinne/theme
fix: 当关闭"是否跟随系统主题"时,无法应用"暗黑模式"的设置
2024-01-03 20:07:43 +08:00
2dust
ee416b1bf2 Merge pull request #4567 from ShiinaRinne/patch-2
添加ico格式的自定义图标支持
2024-01-03 20:06:54 +08:00
2dust
784928ffc8 Merge pull request #4571 from canmengxian/patch-2
禁用删除工作流运行
2024-01-03 20:06:34 +08:00
残梦
609360a1d0 禁用删除工作流运行 2024-01-02 23:52:14 +08:00
ShiinaRinne
18ce2f7b1c fix: 当关闭"是否跟随系统主题"时,无法应用"暗黑模式"的设置 2024-01-02 15:34:42 +08:00
ShiinaRinne
78625d82ae 添加ico格式的自定义图标支持 2024-01-02 15:03:21 +08:00
2dust
2ca34fb9ad Bug fix 2023-12-29 18:16:02 +08:00
2dust
f5f944aa50 up 6.32 2023-12-29 10:02:24 +08:00
2dust
83b4ab83d1 Improve speed test,add Hy2 and Tuic test 2023-12-29 09:39:55 +08:00
2dust
34f63f9006 Add ipv6 option for Tun mode 2023-12-26 18:13:12 +08:00
2dust
b74188d904 Previous and next proxy 4 sing-box 2023-12-25 16:42:23 +08:00
Minghao Hu
ba246e99e8 Fix mixed sync/async ops on Process streams. 2023-12-24 16:21:21 +09:00
2dust
51576b54c3 Previous and next proxy setting 2023-12-24 10:34:55 +08:00
2dust
0d5a9fcf4a Previous and next proxy 2023-12-23 20:57:31 +08:00
2dust
b0c5f74edb Refactor 2023-12-23 17:49:39 +08:00
2dust
1ac7661593 Refactor 2023-12-23 10:19:41 +08:00
2dust
caa2c523f4 Remove singbox update geo file 2023-12-22 16:56:09 +08:00
2dust
7b9f1e6788 Refactor 2023-12-22 16:03:25 +08:00
2dust
86f3ed29f9 Adjust cores 2023-12-22 12:13:36 +08:00
2dust
655d411afe Fix something 2023-12-22 09:46:55 +08:00
2dust
f5deb8e168 Code clean 2023-12-19 18:09:11 +08:00
2dust
fcdb61bfbf Code clean 2023-12-19 16:49:45 +08:00
2dust
bd9a4ca094 Added Tuic v5 support (using sing-box) 2023-12-19 16:03:30 +08:00
2dust
e2657e746d UI adjust 2023-12-16 17:45:52 +08:00
2dust
6f5a174231 Update Package Reference 2023-12-16 17:45:29 +08:00
2dust
91e9c0b02b up 6.31 2023-12-03 17:03:33 +08:00
2dust
658ea26ab7 Bug fix 2023-12-03 17:02:34 +08:00
2dust
77b736541e Bug fix 2023-12-01 17:03:49 +08:00
2dust
843b881da6 Merge pull request #4464 from ShiinaRinne/host
feat: 支持导入系统hosts追加至dns设置
2023-12-01 16:21:37 +08:00
2dust
3ca8acc805 Merge pull request #4457 from canmengxian/patch-1
优化自动化编译
2023-12-01 16:02:48 +08:00
ShiinaRinne
63809d4f16 Added: 支持导入系统hosts添加至dns设置中 2023-12-01 12:37:49 +08:00
残梦
557660b16b 优化自动化编译 2023-11-28 23:56:44 +08:00
2dust
12be8bda52 Code clean 2023-11-28 16:07:53 +08:00
2dust
81efd25e0a Added Hysteria2 support (using sing-box) 2023-11-28 15:45:53 +08:00
2dust
7037009ce4 Added Hysteria2 support (using sing-box) 2023-11-27 17:58:34 +08:00
2dust
4a0902d4c8 Bug fix 2023-11-26 10:39:03 +08:00
2dust
ed25ac1748 Merge pull request #4444 from flyoutsea/master
Fixed Issue #3875 that ProxySetting doesn't support PPPoE connection. Remove unnecessary sysproxy.exe.
2023-11-26 10:03:27 +08:00
flyoutsea
55e09ed062 Fix build warnings: unused variable and obsolete dpiAware settings. 2023-11-25 21:48:33 +08:00
flyoutsea
babb548c22 Fixed Issue #3875 that ProxySetting doesn't support PPPoE connection. Remove sysproxy.exe, which is the unnecessary workaround. 2023-11-25 21:29:59 +08:00
2dust
1d0e8434ad up 6.30 2023-11-22 16:47:57 +08:00
2dust
e7b2deb941 In tun mode, do a delay check and restart the core 2023-11-22 16:37:46 +08:00
2dust
2a37a6a28e Merge pull request #4432 from The-Mojoo/master
Add Update CoreTypeName
2023-11-22 16:31:56 +08:00
Jimmy Mo
735ebbe92a Add Update CoreTypeName 2023-11-22 11:48:49 +08:00
2dust
2031729656 Merge pull request #4409 from Dts0/master
Fix the issue of readonly custom config  and add github workflow
2023-11-18 18:06:57 +08:00
zhaojingshi
f39fdc38cb add github workflow
The output can be found in actions->workflow->Artifacts
2023-11-18 10:22:47 +08:00
zhaojingshi
6b62623615 Fixed the issue of readonly custom config
Fixed the issue where importing read-only custom files would cause the service to fail to start
2023-11-18 10:22:37 +08:00
2dust
f3f3dc1951 Adjust some core 2023-11-17 13:38:50 +08:00
2dust
f4dd970f5e Add core hysteria2 2023-11-16 20:08:17 +08:00
2dust
74332c58c5 Adjust some core 2023-11-16 19:56:14 +08:00
2dust
f7ce49020f Update Package Reference 2023-11-16 17:47:32 +08:00
2dust
aaba1f7209 Merge pull request #4405 from ShiinaRinne/patch-1
fix https://github.com/2dust/v2rayN/pull/4287#discussion_r1394166976
2023-11-16 17:37:46 +08:00
ShiinaRinne
a9c7916b3d fix https://github.com/2dust/v2rayN/pull/4287#discussion_r1394166976 2023-11-15 21:01:38 +08:00
2dust
e3c8ccfafe Merge pull request #4385 from ShiinaRinne/font-ttc
Add: 添加TTC格式字体支持
2023-11-10 15:09:34 +08:00
2dust
2a22b65b2d Merge pull request #4321 from hxdhttk/hxdhttk/keyDown
Fix that editing the basic routing settings will trigger unexpected error messages.
2023-11-10 15:06:18 +08:00
2dust
ce5728e2df Merge pull request #4287 from MichaelHinrichs/Switch
Use a switch
2023-11-10 15:03:03 +08:00
2dust
cba82e0e8e Adjust speedtest addr 2023-11-10 15:00:48 +08:00
ShiinaRinne
be30064f9a Merge branch 'master' into font-ttc 2023-11-09 14:07:16 +08:00
ShiinaRinne
1798981380 Update ResUI.zh-Hant.resx 2023-11-09 13:56:27 +08:00
ShiinaRinne
06586d3405 Add: 添加TTC格式字体支持
https://github.com/2dust/v2rayN/issues/4089
2023-11-09 13:03:45 +08:00
Minghao Hu
31bcbd0e13 Do not execute keyboard shorcut on basic routing setting window. 2023-10-12 05:05:30 +08:00
2dust
2652beed88 Merge pull request #4299 from hxdhttk/hxdhttk/notifyUpd
Update the H.NotifyIcon to show default system tooltip for sys tray icon.
2023-09-30 14:25:03 +08:00
Minghao Hu
a2b87b862f Merge branch '2dust:master' into hxdhttk/notifyUpd 2023-09-29 14:38:06 +08:00
NintenHero
85e8d9479e Fix switch 2023-09-25 10:05:56 -05:00
NintenHero
119508a4e3 Use a switch 2023-09-25 04:45:50 -04:00
2dust
3c2da0a225 up 6.29 2023-09-24 16:17:54 +08:00
Minghao Hu
ef79e6adf9 Use latest update. 2023-09-24 02:05:04 +08:00
2dust
528400579a Merge pull request #4255 from crazypeace/master
解决当订阅数量较多时,占用窗口空间太大的问题
2023-09-22 14:57:07 +08:00
2dust
521ce1a487 Merge pull request #4235 from YheonYeung/patch-1
修正繁中用詞
2023-09-22 14:56:17 +08:00
Minghao Hu
014cc9bc16 Update H.NotifyIcon. 2023-09-17 16:10:05 +08:00
crazypeace
34c6c953ac 考虑在更大的屏幕上可以接受更高尺寸的占用
https://zelikk.blogspot.com/2023/09/v2rayn-lstgroup-maxheight.html
2023-09-09 15:59:08 +08:00
crazypeace
40fbbc7c58 设置 订阅/分组 显示空间的最大高度
避免占用过大的窗口面积
https://github.com/2dust/v2rayN/issues/4224
2023-09-09 15:00:59 +08:00
YheonYeung
534c329970 Update ResUI.zh-Hant.resx 2023-09-01 23:42:07 +08:00
YheonYeung
328d728257 Update ResUI.zh-Hant.resx 2023-09-01 23:39:16 +08:00
YheonYeung
fae6d42758 Update ResUI.zh-Hant.resx 2023-09-01 23:33:39 +08:00
YheonYeung
27693f6d23 Update ResUI.zh-Hant.resx 2023-09-01 23:31:24 +08:00
YheonYeung
89c4bab5b9 Update ResUI.zh-Hant.resx 2023-09-01 23:29:19 +08:00
YheonYeung
9d2ff04838 Update ResUI.zh-Hant.resx 2023-09-01 23:27:15 +08:00
YheonYeung
cf00243107 Update ResUI.zh-Hant.resx 2023-09-01 23:25:12 +08:00
YheonYeung
e8019ba7a5 修正繁中用詞 2023-09-01 23:21:10 +08:00
2dust
4f30e3f0e3 Merge pull request #4149 from eltociear/patch-1
fix typo in MainForm.cs
2023-08-02 10:15:55 +08:00
Ikko Eltociear Ashimine
047d08470f fix typo in MainForm.cs
entryOuputPath -> entryOutputPath
2023-08-02 00:33:10 +09:00
2dust
9643695389 Merge pull request #4144 from chika0801/master
修正 juicity 启动参数少了 run
2023-07-31 09:21:33 +08:00
chika0801
5cabec86e7 修正 juicity 启动参数少了 run
它的客户端启动参数是 ./juicity-client run -c config.json

https://github.com/juicity/juicity/blob/main/cmd/client/README.md#run
2023-07-30 21:33:12 +08:00
2dust
f2d0e37255 Merge pull request #4141 from chika0801/master
添加 juicity 作为自定义 core
2023-07-30 18:26:36 +08:00
chika0801
9560851a3f add juicity 2023-07-30 16:37:44 +08:00
chika0801
4aeec1caa1 add juicity 2023-07-30 16:36:48 +08:00
chika0801
ae45b1ef44 Update Global.cs 2023-07-30 16:33:11 +08:00
2dust
aad1b087c9 Up 6.28 2023-07-30 14:30:20 +08:00
2dust
b69c581fa1 Merge pull request #4123 from openGiraffes/master
繁体字典添加
2023-07-30 11:08:24 +08:00
2dust
9eb4d90cd6 Merge pull request #4122 from yu0A/master
Fix timestamps in log TextBox
2023-07-30 11:08:14 +08:00
Ding
958567c2c5 繁體支持 2023-07-24 10:55:45 +08:00
yu0A
f1fc4583ed fix #4121 2023-07-23 21:20:36 +08:00
Ding
f7bfd5f766 upload part1 2023-07-21 17:57:16 +08:00
2dust
aadc3c216a Merge pull request #4055 from meaqese/meaqese-patch-1
Russian lang improvements
2023-07-10 15:27:43 +08:00
2dust
6fd2499daf Merge pull request #4048 from crazypeace/master
解决窗口尺寸大于屏幕尺寸的问题 #
2023-07-10 15:26:20 +08:00
meaqese
f0405f1c5d imporvements 2 2023-07-04 21:16:01 +03:00
crazypeace
1914cb3994 Delete dotnet-desktop.yml 2023-07-03 01:50:27 +08:00
crazypeace
ab38fb572d Update dotnet-desktop.yml 2023-07-02 19:52:42 +08:00
crazypeace
46d7128a6e Update dotnet-desktop.yml 2023-07-02 19:49:09 +08:00
crazypeace
0821884ff3 Create dotnet-desktop.yml 2023-07-02 19:45:15 +08:00
crazypeace
62233281ef 与上游一致 2023-07-02 12:40:01 +08:00
crazypeace
39504502af Update AddServerWindow.xaml.cs 2023-07-02 12:22:17 +08:00
crazypeace
f97530a671 设置窗口的尺寸不大于屏幕的尺寸 2023-07-02 12:15:51 +08:00
crazypeace
0fe7d5e598 Update AddServerWindow.xaml.cs 2023-07-01 04:53:42 +08:00
crazypeace
527362dc9f 初始化窗口宽和高的最大值, 依据工作区的宽和高.
解决在笔记本屏幕上因为DPI较高导致窗口显示不全的问题.
2023-06-30 13:29:43 +08:00
meaqese
1023426c8d Russian imporvements 2023-06-18 12:34:53 +03:00
2dust
4458fd7541 Up 6.27 2023-06-18 16:44:03 +08:00
2dust
f0b03f59ff Up PackageReference 2023-06-18 16:33:18 +08:00
2dust
d5b17b3cfb Update MainWindowViewModel.cs 2023-06-18 16:23:03 +08:00
2dust
9664d1d77f Fix update the pre version 2023-06-18 16:18:50 +08:00
2dust
d329646a52 Merge pull request #3989 from hvvvvvvv/v2rayN_2
Update HotkeyHandler.cs
2023-06-18 09:43:50 +08:00
2dust
8eafe72bb0 Merge pull request #3943 from hsbtr/master
feat: pac rule add chat.openai.com
2023-06-18 09:43:31 +08:00
2dust
c38a0bde65 Optimize interface 2023-06-18 09:42:45 +08:00
2dust
eef5d3cc16 Update DNSSettingWindow.xaml.cs
https://github.com/2dust/v2rayN/issues/3992
2023-06-18 08:49:04 +08:00
咸鱼而已
59ada594a5 Merge pull request #1 from hvvvvvvv/hvvvvvvv-patch-1
Update HotkeyHandler.cs
2023-06-15 17:12:03 +08:00
咸鱼而已
5ec1d18143 Update HotkeyHandler.cs
fix bug
2023-06-15 16:58:04 +08:00
2dust
fd1e1bb6bf AddServerView CanResize 2023-06-11 19:57:00 +08:00
2dust
5d545d8a85 bug fixes 2023-06-08 20:36:13 +08:00
liuyan
e38bc45527 feat: pac rule add chat.openai.com 2023-06-05 17:42:06 +08:00
2dust
1b11425acd up 6.26 2023-06-04 20:31:05 +08:00
2dust
1e67850a80 Add inet6_address for sing-box 2023-06-04 20:30:00 +08:00
2dust
975f89456f Update ProtosLib.csproj 2023-06-04 17:13:37 +08:00
2dust
e267b4b379 Update v2rayN.csproj 2023-06-04 17:13:34 +08:00
2dust
2fd21690a5 Enable extra inbound for tun mode 2023-06-04 17:11:37 +08:00
2dust
b176ad03aa Remove ToolTipText 2023-06-04 16:30:42 +08:00
2dust
152c4802d0 Fix the bug for flow is empty 2023-06-04 16:24:48 +08:00
2dust
8adbc57f23 remove statisticsFreshRate 2023-06-04 16:14:17 +08:00
2dust
d263a78db8 bug fixes 2023-06-04 15:50:38 +08:00
2dust
b94a065c06 Optimize Subscription 2023-06-04 15:50:25 +08:00
2dust
bc957fea71 up 6.25 2023-05-21 16:31:48 +08:00
2dust
566f056149 use Task.Delay instead of Thread.Sleep 2023-05-21 16:30:05 +08:00
2dust
abe484b0df use Task.Delay instead of Thread.Sleep 2023-05-21 16:29:57 +08:00
2dust
982c865245 Fix subscription ordering 2023-05-21 16:03:29 +08:00
2dust
07d2a27b5f optimize sing-box DNS 2023-05-21 15:22:30 +08:00
2dust
e4c65deda8 Add fakeip for sing-box 2023-05-21 15:05:15 +08:00
2dust
4930646e05 Tum mode forcibly closes the system proxy 2023-05-21 14:55:48 +08:00
2dust
01dd1ff56f Fix cannot insert routing rule with only process name 2023-05-21 14:43:07 +08:00
2dust
9433213fe5 Fill sing-box server_name 2023-05-21 14:35:18 +08:00
2dust
82dea829f1 Temporarily disable sing-box multiplex 2023-05-21 14:30:48 +08:00
2dust
dafc83aa53 Code clean 2023-05-14 17:25:05 +08:00
2dust
7ab1cd6612 Merge pull request #3852 from qhy040404/master
Fix download url
2023-05-14 17:21:33 +08:00
qhy040404
d0e3b3ffbd Fix download url 2023-05-14 17:16:55 +08:00
2dust
50bcc88700 up 6.24 2023-05-14 16:01:57 +08:00
2dust
8fb8575f4b Update v2rayN.csproj 2023-05-13 20:45:02 +08:00
2dust
e63c113b8a Update ProtosLib.csproj 2023-05-13 20:39:24 +08:00
2dust
43d892dbf7 Fix follow system theme 2023-05-13 20:39:16 +08:00
2dust
d9bf31d4f0 Merge pull request #3844 from JasonWues/master
add follow system theme func
2023-05-13 20:04:41 +08:00
2dust
0bde282448 Merge pull request #3842 from ShiinaRinne/hotkey
修复部分键位无法录入热键
2023-05-13 19:33:07 +08:00
2dust
6098132fdf Merge pull request #3834 from qhy040404/master
Avoid to update core if current version is newer than remote version
2023-05-13 19:32:55 +08:00
Metatron
a6bb8947f3 add follow system theme func 2023-05-12 16:19:09 +08:00
ShiinaRinne
48880328b0 Merge branch '2dust:master' into hotkey 2023-05-11 23:32:20 +08:00
ShiinaRinne
25776a788e https://github.com/2dust/v2rayN/issues/3678 2023-05-11 23:31:47 +08:00
qhy040404
f5e8f2831e Cleanup 2023-05-09 23:08:14 +08:00
qhy040404
b3fe13c97a Avoid to update core if current version is newer than remote version 2023-05-09 21:54:56 +08:00
2dust
7845569319 Add ws headers for sing-box 2023-05-09 18:44:04 +08:00
2dust
69b3178c13 remove tun template 2023-05-09 16:14:07 +08:00
2dust
1dce0f0366 Add speed display for sing-box , using clash api 2023-05-09 15:51:32 +08:00
2dust
db1b3fdaad Remove TunHandler 2023-05-07 19:09:51 +08:00
2dust
032d12a592 Add process name (Tun mode) to the rule
Add Tun DNS in the DNS settings of sing-box
Remove Tun mode settings process name and dns
2023-05-07 19:09:13 +08:00
2dust
94cc36a08f Rename the v2ray configuration class 2023-05-07 16:35:46 +08:00
2dust
4fcae44fb7 The default color is Blue 2023-05-07 15:54:40 +08:00
2dust
83719dfe17 vless reality mux can be used when the flow is empty 2023-05-07 09:01:50 +08:00
2dust
c8b01a5530 bug fixes 2023-05-04 20:28:38 +08:00
2dust
b469d73385 add mux for sing-box vless 2023-05-04 20:23:54 +08:00
2dust
69468b1770 Sing2sing 2023-05-04 20:18:21 +08:00
2dust
7e4f66d533 Add Multiplex protocol settings for sing-box 2023-05-04 16:30:35 +08:00
2dust
758d0d82d4 Tun mode force start sing-box core 2023-05-04 11:44:51 +08:00
2dust
a01b934fdb Fix update geoip 2023-04-30 16:46:49 +08:00
2dust
e9b0372174 Enable pre tun mode for other cores 2023-04-29 19:38:00 +08:00
2dust
288c02e092 Adjust some settings 2023-04-29 16:41:31 +08:00
2dust
33322e8795 Improved true connection test 2023-04-28 21:10:13 +08:00
2dust
ec8f6478df update geo files for sing-box 2023-04-28 15:54:51 +08:00
2dust
59d397a3a0 fix some text 2023-04-28 14:15:03 +08:00
2dust
b06540f2ec Custom config pre-service uses sing-box instead of v2ray 2023-04-28 12:09:02 +08:00
2dust
419f5458b4 Add domainStrategy4Singbox in rule set settings 2023-04-28 10:41:50 +08:00
2dust
ca4e8960d2 Delete shortcut keys for routing rules 2023-04-28 10:23:48 +08:00
2dust
7b3bed015a Add the ip and domain separator convert it to a comma 2023-04-28 10:22:55 +08:00
2dust
c97fa3a767 format dns config 2023-04-28 10:02:42 +08:00
2dust
42f7c7cb43 Adjust some config for sing-box 2023-04-27 16:20:13 +08:00
2dust
c8ae834f50 bug fixes 2023-04-27 14:17:27 +08:00
2dust
b8644268b3 Enter to set active routing rules 2023-04-27 10:28:20 +08:00
2dust
75742d8a9e Convert rule domain newLine to comma 2023-04-27 10:21:06 +08:00
2dust
6b6169e248 Adjust some config 2023-04-27 10:15:22 +08:00
2dust
3c4ae902fd Add dns for tun mode 2023-04-26 20:53:43 +08:00
2dust
bfc8bf91ee Add def dns for normal 2023-04-26 20:32:01 +08:00
2dust
768d5cce27 Add Sing-box domain strategy 2023-04-26 15:11:57 +08:00
2dust
d54a1c2754 Adjust some def configs 2023-04-26 14:39:04 +08:00
2dust
282ad3ab2d Add import default DNS config 2023-04-26 10:43:05 +08:00
2dust
c692dd3a66 add sing-box new LAN port 2023-04-26 10:00:51 +08:00
2dust
e461fce2cb add sing-box tun bypassMode 2023-04-26 09:36:30 +08:00
2dust
4d92caabf8 Trojan add reality 2023-04-25 20:34:37 +08:00
2dust
07c07ec60a sniff_override_destination = RouteOnly ? false 2023-04-25 20:34:18 +08:00
2dust
4020213729 generate a single file for sing-box tun mode 2023-04-25 20:27:21 +08:00
2dust
b9beb4be9d Add registry settings system proxy 2023-04-25 10:56:07 +08:00
2dust
f747416d3b Merge pull request #3756 from MohammadHadi2031/dev/ma/perf
use WaitAsync for Timeout
2023-04-25 10:03:40 +08:00
MohammadHadi Attarieh
41241b694f use WaitAsync instead of CTS 2023-04-24 18:34:30 +03:30
2dust
26c5c1ac01 bug fixes 2023-04-24 14:27:17 +08:00
2dust
dedd5b197c DNS independent setting, V2ray and Sing-box 2023-04-24 11:55:26 +08:00
2dust
6340764a6c Add basic rules for sing-box 2023-04-24 09:40:38 +08:00
2dust
a262c1e98d Add sing-box core config file support 2023-04-23 20:21:52 +08:00
2dust
7b9c64c5a5 remove export to server config 2023-04-23 15:06:51 +08:00
2dust
4283404f35 bug fixes 2023-04-22 20:29:06 +08:00
2dust
f612ce5db8 up 6.23 2023-04-21 15:55:05 +08:00
2dust
831a20ff91 Code clean 2023-04-21 15:15:35 +08:00
2dust
38ae669070 bug fixes for ErrorDataReceived 2023-04-21 14:49:33 +08:00
2dust
fed7e7764e bug fixes 2023-04-21 14:09:55 +08:00
2dust
f3804fce40 Add subscription conversion
https://github.com/tindy2013/subconverter/blob/master/README-cn.md
2023-04-21 12:15:24 +08:00
2dust
88e7cd09d7 The skip delay is -1 speed test in multi-threaded test 2023-04-21 12:11:09 +08:00
2dust
1ce5571ac6 Hide tray tip text 2023-04-21 10:32:41 +08:00
2dust
355bf84af4 bug fixes 2023-04-19 16:33:08 +08:00
2dust
6e8a3a4867 Code clean 2023-04-16 20:45:47 +08:00
2dust
bf6dcdf2bd Code clean 2023-04-14 20:49:36 +08:00
2dust
165454dc57 Migrate from Grpc.Core to Grpc.Net.Client 2023-04-14 15:51:34 +08:00
2dust
34b4b9d099 up 6.22 2023-04-13 16:00:30 +08:00
2dust
0808ec1612 Add Check update for sing-box core 2023-04-13 15:50:28 +08:00
2dust
6b12549cd9 bug fixes 2023-04-12 20:15:17 +08:00
2dust
92baf9025a Update StatisticsHandler.cs 2023-04-12 15:30:07 +08:00
2dust
d58861ab88 Adjust some style 2023-04-12 14:26:37 +08:00
2dust
142230e56a Fix description 2023-04-12 14:08:30 +08:00
2dust
b8959c8f12 Optimize server filter 2023-04-12 11:34:42 +08:00
2dust
3fa22fdc55 bug fixes 2023-04-11 20:18:49 +08:00
2dust
a1c743e59c bug fixes 2023-04-10 17:30:27 +08:00
2dust
ebd0f45c10 Adjust VLESS flow config 2023-04-10 16:21:19 +08:00
2dust
fce6c46250 Can set the update interval for each subscription 2023-04-10 16:00:32 +08:00
2dust
6114e4ff55 Temporary fix for arm64 grpc issues 2023-04-10 11:28:53 +08:00
2dust
cc3d1ff7de Update Package Reference 2023-04-09 09:13:28 +08:00
2dust
2f721c8535 Merge pull request #3635 from kidfruit/core-arm
Core arm
2023-04-09 08:26:33 +08:00
kidfruit
ddb790104f delete .vs 2023-04-08 12:57:11 +08:00
liqi
181dfd2f51 add arm64 download path for core 2023-04-07 21:32:28 +08:00
liqi
fca062f75a add arm64 download path for core 2023-04-07 18:13:37 +08:00
2dust
52b84c3201 bug fixes 2023-04-07 15:38:30 +08:00
2dust
e1021a6832 Merge pull request #3631 from fonaix/master
fix bug #3630
2023-04-07 15:37:28 +08:00
fonaix
aa338d2da5 fix bug #3630 2023-04-07 15:21:09 +08:00
2dust
44471c4926 Update README.md 2023-04-07 13:56:16 +08:00
2dust
930c7e4ce5 Update README.md 2023-04-07 13:55:32 +08:00
2dust
2e64f23ef9 up 6.21 2023-04-07 11:03:23 +08:00
2dust
801d1fd320 clean up res 2023-04-07 10:16:05 +08:00
2dust
cfffb5756e Update ResUI.zh-Hans.resx 2023-04-06 20:39:40 +08:00
2dust
b30daf8e56 Add more subscription url for one group 2023-04-06 15:09:49 +08:00
2dust
84eba671f0 Optimize add batch servers 2023-04-06 11:40:28 +08:00
2dust
f28b93daa0 Use H.NotifyIcon.Wpf 2023-04-06 10:44:58 +08:00
2dust
dc16136c59 Add Reboot as administrator 2023-04-06 10:44:29 +08:00
2dust
e47caf8c4f VLESS flow check 2023-04-05 21:07:47 +08:00
2dust
8ad80bb75d Remove System.Windows.Forms references 2023-04-05 20:53:05 +08:00
2dust
22475e459d Remove the function of minimizing at startup, because it affects the startup position 2023-04-05 09:43:33 +08:00
2dust
73ad33dfc9 Merge pull request #3611 from fonaix/master
fix bug #3218  and optimize the background color display effect of the active row
2023-04-05 08:23:33 +08:00
fonaix
f1782c78f4 fix bug #3218 2023-04-05 00:57:30 +08:00
fonaix
b544dde2c6 Optimize the background color display effect of the active row 2023-04-04 23:39:56 +08:00
2dust
1a7dca8e58 Fix subscription update duplicate server bug 2023-04-04 20:19:52 +08:00
2dust
23c7d7fb46 Remove some System.Windows.Forms references 2023-04-04 15:59:28 +08:00
2dust
65fda407dc RemoveSystem.Windows.Forms references 2023-04-04 15:59:08 +08:00
2dust
12ebad436a Autofit Column Width 2023-04-04 13:30:29 +08:00
2dust
c7297dba7e Merge pull request #3598 from JasonWues/master
当前选中节点标识改为背景颜色更改
2023-04-04 10:31:56 +08:00
2dust
e61368a26e Remove some System.Windows.Forms references 2023-04-04 10:22:13 +08:00
2dust
b98da3a5dc Optimized move to group 2023-04-04 10:21:12 +08:00
2dust
12f3400894 Subscription multi-select delete 2023-04-04 10:20:19 +08:00
Metatron
4b5508fc3c Style change 2023-04-03 14:43:30 +08:00
Metatron
5f40e6e0b7 fix 2023-04-03 10:50:56 +08:00
Metatron
080d660cfa Select row background change 2023-04-03 10:45:21 +08:00
2dust
790209efbc up 6.20 2023-04-01 18:57:24 +08:00
2dust
f1679e444c Add skip subscription tips 2023-03-31 20:07:39 +08:00
2dust
9dc6ba182a Fix delete duplicate server 2023-03-30 14:09:14 +08:00
2dust
785a30e623 Update CoreConfigHandler.cs 2023-03-26 20:05:51 +08:00
2dust
f09efdad66 Add tip for custom log 2023-03-25 18:05:01 +08:00
2dust
4e73b3ae28 Adjust some style 2023-03-25 17:50:32 +08:00
2dust
6213f86f81 up 6.19 2023-03-21 17:20:24 +08:00
2dust
0a6955cd59 Add log start core 2023-03-21 14:22:13 +08:00
2dust
6ee8f03ec0 Gui's log can be turned off 2023-03-20 15:25:58 +08:00
2dust
b1a82d95c2 Hide title when title width is equal to 0 2023-03-20 15:23:29 +08:00
2dust
30bc9ded29 Add REALITY share link 2023-03-20 15:20:55 +08:00
2dust
5a32892e94 bug fixes 2023-03-20 14:03:50 +08:00
2dust
e33de896b6 Merge pull request #3507 from ShiinaRinne/dev
Update: 默认关闭硬件加速
2023-03-20 13:23:58 +08:00
ShiinaRinne
3ba92444a5 Update: 默认关闭硬件加速
开启硬件加速时可能会导致奇奇怪怪的问题,因此修改为默认关闭
https://github.com/2dust/v2rayN/issues/3379
https://github.com/2dust/v2rayN/issues/3279
2023-03-18 20:49:02 +08:00
2dust
4f120e8eb4 bug fixes 2023-03-17 17:20:40 +08:00
2dust
08aebf5736 up 6.18 2023-03-17 13:53:14 +08:00
2dust
5a4966ba8d Adjust speed test 2023-03-17 10:32:56 +08:00
2dust
9ba963fc45 bug fixes 2023-03-16 20:11:10 +08:00
2dust
ccc10dbae4 Merge pull request #3493 from ShiinaRinne/AddEnableHWA
Add: 设置中添加"启用硬件加速"的选项
2023-03-16 14:10:20 +08:00
ShiinaRinne
d858342269 Add: 设置中添加"启用硬件加速"的选项 2023-03-15 23:27:51 +08:00
2dust
63f251d1fd up 6.17 2023-03-10 20:38:08 +08:00
2dust
83efe66f3e bug fixes 2023-03-10 11:25:34 +08:00
2dust
3f5729044f up 6.16 2023-03-09 21:02:41 +08:00
2dust
045af7e8df Add reality and remove legacy xtls settings 2023-03-09 20:57:12 +08:00
2dust
6f181053b2 Optimize 2023-03-08 20:39:50 +08:00
2dust
4ff1dc2982 code cleanup 2023-03-07 20:24:51 +08:00
2dust
a883ba8808 Optimize add and delete performance 2023-03-07 20:24:26 +08:00
2dust
961bd6140c bug fixes 2023-03-06 20:08:21 +08:00
2dust
5f364b48c9 Enable themes for Windows common controls and dialogs 2023-03-05 20:08:48 +08:00
2dust
5a04911c7c fix resx 2023-03-05 20:05:39 +08:00
2dust
8ff248aa62 bug fixes 2023-03-05 20:04:31 +08:00
2dust
046ac95dc3 bug fixes 2023-03-05 19:51:26 +08:00
2dust
6fb17a4b74 Merge pull request #3419 from hxdhttk/hxdhttk/simulateToolTip
Add a control to simulate system tool tip.
2023-03-05 19:29:58 +08:00
Minghao Hu
f84397393d Niche. 2023-03-05 14:19:59 +08:00
Minghao Hu
800c93e2aa Add a control to simulate system tool tip. 2023-03-05 13:57:58 +08:00
2dust
df6179a1a8 Merge pull request #3405 from hvvvvvvv/master
优化全局热键相关代码和机制
2023-03-04 20:12:54 +08:00
hvvvvvvv
3e3a079ba1 Merge branch '2dust:master' into master 2023-03-04 18:22:08 +08:00
chao wan
0bf4a43663 删除调试代码 2023-03-04 11:52:46 +08:00
chao wan
5e9f4ad926 解决当前已注册热键无法触发UI线程控件的KeyDown事件的问题 2023-03-04 11:46:36 +08:00
2dust
69050bfe41 up 6.15 2023-03-04 08:52:03 +08:00
2dust
eebc16bcdd Minimize windows when auto-hide is enabled 2023-03-04 08:51:29 +08:00
2dust
d4921535f2 Add lock for db 2023-03-04 08:43:44 +08:00
2dust
b1eeb648a7 Adjust style for icon 2023-03-04 08:36:57 +08:00
chao wan
ba702ba041 热键相关代码更新 2023-03-04 00:40:06 +08:00
chao wan
c40d88d0b6 优化热键相关代码(未完成) 2023-03-03 18:03:29 +08:00
2dust
285f91e9e8 bug fixes 2023-03-03 10:45:09 +08:00
2dust
947a7aa7df Modify blacklist rules 2023-03-03 10:15:39 +08:00
2dust
0b37e36036 Merge pull request #3382 from hvvvvvvv/master
解决全局热键不能录制Alt组合键的问题
2023-03-01 09:18:04 +08:00
2dust
92320f5086 Merge pull request #3380 from qiopgh/master
为tun做dns分流
2023-03-01 09:17:52 +08:00
chao wan
ae17e0c264 解决全局热键不能录制Alt组合键的问题 2023-02-28 23:32:58 +08:00
qiopgh
ec756ee943 Update tun_singbox_dns
为tun做dns分流
2023-02-28 22:08:15 +08:00
2dust
b0ff814753 Adjust Running Server ToolTipText 2023-02-28 20:37:45 +08:00
2dust
1f7eb2d48a Optimizing reload core 2023-02-28 20:23:15 +08:00
2dust
eeab8e4a90 Setting tab 2023-02-27 13:26:08 +08:00
2dust
77fbddf488 Improve subscription update without proxy 2023-02-27 13:25:45 +08:00
2dust
bf396f8802 Merge pull request #3370 from hxdhttk/hxdhttk/trayToolTip
Add tray tool tip for the current running server.
2023-02-27 13:04:05 +08:00
Minghao Hu
13cb8b84bf Add tray tool tip for running server. 2023-02-27 11:30:54 +08:00
2dust
3ab992f5fb Merge pull request #3340 from ShiinaRinne/patch-2
Update OptionSettingWindow.xaml
2023-02-24 21:06:27 +08:00
2dust
a386ecfc9c Merge pull request #3336 from ShiinaRinne/patch-1
Update MainWindow.xaml
2023-02-24 21:05:42 +08:00
ShiinaRinne
a71399c42c Update OptionSettingWindow.xaml
调整option页宽度,设置说明自动换行
2023-02-24 15:00:19 +08:00
ShiinaRinne
5a5d7e0981 Update MainWindow.xaml
确保popupbox在点击功能后不会自动关闭,方便测试或多次调整看效果
2023-02-24 12:32:32 +08:00
2dust
b663a7f52a up 6.14 2023-02-24 11:55:32 +08:00
2dust
7390039086 adjust move up and down menu 2023-02-24 11:27:06 +08:00
2dust
12af02435f header sort memory 2023-02-24 11:13:13 +08:00
2dust
6f357828b7 Update SysProxyHandle.cs 2023-02-24 11:11:33 +08:00
2dust
09e1a4386d fix pac bug 2023-02-24 11:11:01 +08:00
2dust
dcc8e6dc34 Add subscription id memory 2023-02-21 20:43:32 +08:00
2dust
1b19ef54e4 Add Tun mode DNS settings 2023-02-21 20:42:55 +08:00
2dust
8ce476caf1 Optimizing sorting storage 2023-02-20 20:15:08 +08:00
2dust
dd2d9133eb Merge pull request #3323 from ilyfairy/master
commit
2023-02-20 19:56:33 +08:00
小仙女
2147d12ac8 update 2023-02-20 18:16:30 +08:00
2dust
22641a1da0 Merge pull request #3315 from ilyfairy/master
修复了一些问题
2023-02-19 20:23:38 +08:00
小仙女
2bd4088d40 使用==替代string.Equals 2023-02-19 19:15:02 +08:00
小仙女
ee61363c31 update 2023-02-19 19:06:35 +08:00
小仙女
8285688ec9 fix: 当过滤器是无效的正则时, 会输出大量异常日志 2023-02-19 18:51:08 +08:00
2dust
4eb076540e Merge pull request #3311 from ilyfairy/master
Update v2rayUpgrade
2023-02-19 16:22:53 +08:00
小仙女
527bfec24c Update v2rayUpgrade 2023-02-19 16:16:10 +08:00
2dust
2fff7d7160 Update TunHandler.cs 2023-02-19 16:09:31 +08:00
2dust
aac2b4aaf0 up 6.13 2023-02-19 15:44:52 +08:00
2dust
fe070b306f Merge pull request #3309 from ilyfairy/master
改为可空类型, 简化代码
2023-02-19 15:33:25 +08:00
2dust
ecfadf8a23 Merge branch 'master' into master 2023-02-19 15:23:04 +08:00
2dust
653af71596 Add log switch in tun mode 2023-02-19 14:55:44 +08:00
小仙女
6a89be2e89 简化代码 2023-02-19 13:34:22 +08:00
小仙女
b84bad4e1a 改为可空类型 2023-02-19 12:18:08 +08:00
2dust
0f8d86f081 Refactoring sorting and delayed storage 2023-02-19 11:23:45 +08:00
2dust
d44f311ba1 Refactoring sorting and delayed storage 2023-02-19 10:43:42 +08:00
2dust
6f5428ca61 Merge pull request #3306 from Weltolk/master
语句更通顺
2023-02-19 09:59:47 +08:00
2dust
b0bee3ca1a Merge pull request #3305 from ilyfairy/master
优化, 改成使用语法糖
2023-02-19 09:59:30 +08:00
2dust
7908194d27 Merge pull request #3301 from meaqese/add-russian-language
full-russian-support
2023-02-18 20:07:57 +08:00
小仙女
b27c7fb2dd string.Join的第二个参数(List<string>)改成ToArray 2023-02-17 22:06:17 +08:00
小仙女
a23cb95a10 性能优化 2023-02-17 15:17:01 +08:00
小仙女
fc137f9b1c 语句更通顺 2023-02-17 15:09:26 +08:00
Weltolk
84780bf9ef Update ResUI.zh-Hans.resx 2023-02-17 14:39:59 +08:00
小仙女
1321037c52 优化, 改成使用语法糖 2023-02-17 14:36:28 +08:00
meaqese
de1da12d45 full-russian-support 2023-02-17 03:18:41 +03:00
2dust
6d4cbacd50 GenerateSatelliteAssembliesForCore 2023-02-15 20:48:56 +08:00
2dust
bf9f7ca990 Adjust the group style 2023-02-15 20:47:17 +08:00
2dust
ca334104d7 bug fixes 2023-02-15 20:37:51 +08:00
2dust
c3e00ba31b bug fixes 2023-02-15 20:37:27 +08:00
2dust
ea3a9cc70e ShowInTaskbar = false 2023-02-15 20:36:50 +08:00
2dust
7ad22e0a73 up 6.12 2023-02-12 20:54:41 +08:00
2dust
ca1abb58eb Add subscription update multiple update function 2023-02-12 20:42:10 +08:00
2dust
3e353944b2 Update App.xaml 2023-02-12 20:41:06 +08:00
2dust
007a250f55 up 6.11 2023-02-12 08:54:23 +08:00
2dust
e9bb6a9951 bug fixes 2023-02-12 08:53:28 +08:00
2dust
82f236e07b up 6.10 2023-02-11 20:03:54 +08:00
2dust
17bfe74ecf Add routing sort 2023-02-11 19:34:15 +08:00
2dust
b77827df90 Update v2rayN.csproj 2023-02-10 21:02:41 +08:00
2dust
a359a508ae fix Import old config 2023-02-10 21:02:29 +08:00
2dust
3a740118f0 Adjust task service settings 2023-02-10 18:58:20 +08:00
2dust
58d9bcbd14 tidy code github 2023-02-10 16:25:16 +08:00
2dust
24be7b2180 store msg filter 2023-02-10 16:01:47 +08:00
2dust
f4c9ca8dff Refactor routing basic settings 2023-02-10 14:51:00 +08:00
2dust
9b8181b72b Refactor gui settings 2023-02-10 14:36:37 +08:00
2dust
1ff1962425 Refactor basic settings 2023-02-10 14:16:59 +08:00
2dust
9b05736746 Add environment variables to geo files 2023-02-10 11:22:03 +08:00
2dust
dec722e693 Update UpdateHandle.cs 2023-02-10 11:05:11 +08:00
2dust
49fa0a4c67 DownloadStringAsyncOri 2023-02-10 11:04:57 +08:00
2dust
0cdc69e1e8 Update MsgView.xaml 2023-02-10 09:39:18 +08:00
2dust
0494cc4ce7 adjust group style 2023-02-09 16:43:50 +08:00
2dust
30d82947d6 fix 2023-02-09 15:17:52 +08:00
2dust
ec59249d79 Optimize file download 2023-02-09 14:54:54 +08:00
2dust
7eb869ab1d Optimize file download 2023-02-09 10:54:31 +08:00
2dust
d014724a2d Optimize speed test 2023-02-08 19:20:44 +08:00
2dust
dfb6cef364 Update OptionSettingWindow.xaml.cs 2023-02-08 15:07:23 +08:00
2dust
0ebf8c9349 Optimize Font size 2023-02-07 19:05:49 +08:00
2dust
9dfd89c90d up 6.9 2023-02-06 19:28:43 +08:00
2dust
f6972125cd Update tun_singbox 2023-02-06 19:19:36 +08:00
2dust
6e366bf55a Improved enhanced tun mode 2023-02-06 15:29:10 +08:00
2dust
5e2e45c673 Merge branch 'master' of https://github.com/2dust/v2rayN 2023-02-05 20:17:07 +08:00
2dust
f879235564 fix get Win32FamilyNames 2023-02-05 20:17:03 +08:00
2dust
b00aee2ae7 Merge pull request #3187 from saphirique/patch-1
Add russian language
2023-02-05 19:57:08 +08:00
saphirique
28c2159ec3 add russian language 2023-02-05 17:55:24 +08:00
2dust
33dcef2285 Optimize Update Subscription 2023-02-04 18:52:17 +08:00
2dust
b9acd0ec28 Font size custom 2023-02-04 15:43:49 +08:00
2dust
7989d5180b adjust style 2023-02-04 14:25:21 +08:00
2dust
238086942e change fonts folder 2023-02-04 12:50:38 +08:00
2dust
a704a30242 up 6.8 2023-02-03 20:03:21 +08:00
2dust
26dd0d0ea5 add more PresetFingerprints 2023-02-03 09:45:21 +08:00
2dust
e31a4bcaa9 share link to add fingerprint 2023-02-03 09:39:39 +08:00
2dust
1722dc570b Modified the tun mode configuration template 2023-02-03 08:59:28 +08:00
2dust
3575e69b43 Tun mode can be auto turned on at startup 2023-02-02 16:27:35 +08:00
2dust
373d89874c Add custom font settings 2023-02-02 13:51:58 +08:00
2dust
976087ce97 Merge pull request #3165 from DanielBlackBeard/master
add more Farsi Translation
2023-02-02 10:51:21 +08:00
2dust
69a45788ee Merge pull request #3154 from mojpangr26/dev
增加自定义UA
2023-02-02 10:51:03 +08:00
mojpangr26
92e4de12fb 修改可编辑cmb
增加提示
2023-02-02 09:41:23 +08:00
Persian Prince
ea7fdb9b3d add more Farsi Translation 2023-02-01 21:40:26 +03:30
mojpangr26
fe1c043b8e 自定义UA 2023-02-01 17:07:36 +08:00
2dust
146f597a0b Fix the problem after clicking to sort and drag 2023-02-01 15:23:17 +08:00
2dust
d2bef312ce Add default fingerprint settings 2023-02-01 11:24:45 +08:00
2dust
61f297215d Optimize remove server 2023-02-01 11:08:05 +08:00
2dust
639a9fd540 Add test completion prompt 2023-02-01 10:06:19 +08:00
2dust
3d0428c518 add info filter the preset value 2023-02-01 09:53:37 +08:00
2dust
f40f926ce1 up 6.7 2023-01-31 19:24:55 +08:00
2dust
d6db4f0e4c Add double-click server as active parameter 2023-01-31 16:08:26 +08:00
2dust
fcbc9471aa add edit server menu 2023-01-31 14:33:17 +08:00
2dust
b147e05794 bug fix 2023-01-31 14:13:25 +08:00
2dust
47e6eb546d Optimize speed test info 2023-01-31 14:05:31 +08:00
2dust
8ba05cb4ed Replace the font with Source Han Sans CN 2023-01-31 13:34:32 +08:00
2dust
84b91e9649 Fix activity node display 2023-01-31 13:25:52 +08:00
2dust
703e17478d fix speed test url 2023-01-31 12:55:19 +08:00
2dust
8584e15c32 Optimize Sort as delay 2023-01-30 15:30:48 +08:00
2dust
46be7aadab Add refresh switch to information window 2023-01-30 14:44:49 +08:00
2dust
a5871f6cba memory log window size 2023-01-30 14:06:18 +08:00
2dust
917dc1803c Optimize custom configuration 2023-01-30 13:16:48 +08:00
2dust
c0c0961b2b Increase list line spacing 2023-01-30 12:30:04 +08:00
2dust
0995ac6f9a fix rules setting key 2023-01-30 12:27:41 +08:00
2dust
b7f40e4cbf Increase the Margin of qrcode 2023-01-30 11:18:01 +08:00
2dust
754cbb9eaa fix allowInsecure bug 2023-01-30 09:53:04 +08:00
2dust
7052b56069 Optimize font 2023-01-30 09:36:27 +08:00
2dust
decdee825b Merge pull request #3107 from buiawpkgew1/patch-1
修改hysteria 官网
2023-01-28 16:08:44 +08:00
菾凴
5f66afc399 修改hysteria 官网
https://github.com/2dust/v2rayN/issues/3094
2023-01-20 21:44:54 +08:00
2dust
5ceb638edf up 6.6 2023-01-09 20:04:24 +08:00
2dust
688b9ef5ee fix display 2023-01-09 20:03:39 +08:00
2dust
4909a557d5 Revert "Change the way to call the core in the speed test"
This reverts commit dd85ccd3f8.
2023-01-09 19:39:45 +08:00
2dust
75f63afadc bug fix 2023-01-08 09:24:09 +08:00
2dust
e90a624c9a up 6.5 2023-01-07 20:58:45 +08:00
2dust
dd85ccd3f8 Change the way to call the core in the speed test 2023-01-07 20:55:44 +08:00
2dust
fc54e19ce2 Add subscription failure log 2023-01-07 20:15:20 +08:00
2dust
118a920e57 Added drag and drop sorting option 2023-01-07 19:56:56 +08:00
2dust
975a335538 adjust timeout 2023-01-06 19:31:11 +08:00
2dust
c6ec4f38b0 Optimize speed test 2023-01-06 19:23:36 +08:00
2dust
5a5d686be1 up 6.4 2023-01-05 19:08:05 +08:00
2dust
8fc430d124 add tun mode custom config template 2023-01-05 19:05:16 +08:00
2dust
721eb40a8a bug fix 2023-01-05 19:03:29 +08:00
2dust
f18103751f Drag and Drop 2023-01-05 14:31:53 +08:00
2dust
9d30bb669e up 6.3 2023-01-04 17:18:29 +08:00
2dust
ab6f5c21c8 Auto Start via TaskService 2023-01-04 17:17:43 +08:00
2dust
4fc2ed32d2 bug fix 2023-01-04 15:47:08 +08:00
2dust
00ab4f2a7d delete temp file 2023-01-04 11:02:43 +08:00
2dust
cb5d8b405b fix bug 2023-01-04 11:02:26 +08:00
2dust
7b28aa8500 Optimize traffic statistics 2023-01-04 10:21:26 +08:00
2dust
97a369df0a Merge pull request #2962 from FrzMtrsprt/Fix_Window_Size
Fix window size on first launch
2023-01-04 09:07:23 +08:00
2dust
73a817c1cb remove tun Redirect Standard Error 2023-01-04 09:02:00 +08:00
FrzMtrsprt
c16053f0e5 Fix window size on first launch 2023-01-03 21:35:04 +08:00
2dust
3dfd108fc4 up 6.2 2023-01-03 16:32:49 +08:00
2dust
576696b25e add move to group 2023-01-03 16:32:33 +08:00
2dust
781fab5aab bug fix 2023-01-03 15:43:57 +08:00
2dust
0f099a19cd Improve traffic refresh 2023-01-03 15:11:34 +08:00
2dust
43b96ea4e5 bug fix 2023-01-03 10:52:44 +08:00
2dust
8cbf6bfffa Improve tun mode 2023-01-03 10:09:44 +08:00
2dust
52debcdcb3 Improved check for update v2rayN 2023-01-03 09:36:23 +08:00
2dust
9d38d89c25 Improve tun mode log 2023-01-02 20:22:00 +08:00
2dust
837f0ca393 Merge branch 'master' of https://github.com/2dust/v2rayN 2023-01-02 19:59:50 +08:00
2dust
42fd5b6eb2 fix bugs 2023-01-02 19:59:48 +08:00
2dust
7bdf76a665 Merge pull request #2928 from DanielBlackBeard/master
Update ResUI.fa-Ir.resx
2023-01-02 19:00:45 +08:00
Persian Prince
784ef278ea Update ResUI.fa-Ir.resx 2023-01-02 09:25:19 +03:30
2dust
9b4bf455b4 up 6.1 2023-01-02 11:13:26 +08:00
2dust
ddd3739ed9 Fix the problem of using core 2023-01-02 11:02:31 +08:00
2dust
1c95c5861c Fix startup issues 2023-01-02 11:01:43 +08:00
2dust
fd6fa1c622 fix fa-Ir 2023-01-02 10:07:10 +08:00
2dust
6809a77a41 Merge pull request #2918 from DanielBlackBeard/master
add persian(farsi) language
2023-01-02 10:00:14 +08:00
2dust
7a913ee38f Merge pull request #2911 from FrzMtrsprt/more_dark_border
Dark border for every window
2023-01-02 09:50:24 +08:00
Persian Prince
cca330829a Update ResUI.fa-Ir.resx 2023-01-01 19:44:27 +03:30
Persian Prince
e2f5c76d91 add persian(farsi) language 2023-01-01 19:25:02 +03:30
FrzMtrsprt
26bf7c149c Dark border for every window 2023-01-01 21:18:10 +08:00
2dust
020df117c4 up 6.0 2023-01-01 19:42:01 +08:00
2dust
b48037b757 Convert idn domain 2022-12-13 20:02:45 +08:00
2dust
529b6613e9 up 5.39 2022-12-11 08:29:26 +08:00
2dust
8a5d8cdf8a Check Update 2022-12-11 08:29:11 +08:00
2dust
cdf35740d9 Update UpdateHandle.cs 2022-12-01 20:22:26 +08:00
2dust
76c40585fd bug fix 2022-11-06 20:20:09 +08:00
2dust
2bf58288d3 fix vless tls flow 2022-11-02 20:56:09 +08:00
2dust
ba2eac5290 up 5.38 2022-11-02 19:20:05 +08:00
2dust
23a4e4cc19 refresh ui after update sub 2022-11-02 19:19:26 +08:00
2dust
841a20cbd4 fix naiveproxy redirect output issue 2022-11-02 19:18:31 +08:00
2dust
f70ca77913 add xtls-rprx-vision 2022-11-01 11:32:10 +08:00
2dust
c97df99c5c Merge pull request #2740 from wh201906/patch-1
Add support for config file with .yml extension
2022-10-28 09:11:01 +08:00
Self Not Found
809e170018 Add support for config file with .yml extension 2022-10-28 00:09:25 +08:00
2dust
d0c8f5eb45 Revert "add domainStrategy4Freedoms"
This reverts commit d0f953f1d8.
2022-10-26 19:41:21 +08:00
2dust
d0f953f1d8 add domainStrategy4Freedoms 2022-10-26 19:38:38 +08:00
2dust
6d1636c540 fix update check 2022-10-26 19:09:40 +08:00
2dust
b3292729b0 fix ui 2022-10-15 07:50:48 +08:00
2dust
11840ffc8a up 5.37 2022-10-14 20:47:06 +08:00
2dust
9fd20d1dc8 Add fingerprint(uTLS) option 2022-10-14 20:43:54 +08:00
2dust
ea6799d749 Update README.md 2022-10-10 20:23:37 +08:00
2dust
e23fe00a37 Revert "Merge pull request #2654 from FrzMtrsprt/ArchV3"
This reverts commit ccda957e8f, reversing
changes made to 4dfb0fa213.
2022-09-30 20:22:48 +08:00
2dust
ccda957e8f Merge pull request #2654 from FrzMtrsprt/ArchV3
Make Clash cores use newer microarch level
2022-09-27 20:46:10 +08:00
FrzMtrsprt
cdaaf00509 Make Clash cores use newer microarch level 2022-09-27 18:41:45 +08:00
2dust
4dfb0fa213 Update v2rayN.csproj 2022-09-20 20:25:35 +08:00
2dust
dcda8fc773 Update StatisticsHandler.cs 2022-09-20 20:25:32 +08:00
2dust
9c3fff8510 fix sing-box support 2022-09-20 20:19:31 +08:00
2dust
c3526ebfa3 Merge pull request #2640 from chika0801/master
add sing-box support
2022-09-20 20:04:15 +08:00
chika0801
28ba47a2f5 add sing-box support 2022-09-19 22:57:15 +08:00
chika0801
55a8b9085e add sing-box support 2022-09-19 22:56:15 +08:00
chika0801
2f250c5569 add sing-box support 2022-09-19 22:54:05 +08:00
2dust
e9d0565e6a fix ui 2022-09-13 20:42:30 +08:00
442 changed files with 83768 additions and 39556 deletions

170
.editorconfig Normal file
View File

@@ -0,0 +1,170 @@
root = true
[*]
charset = utf-8
indent_style = space
tab_width = 4
indent_size = 4
end_of_line = crlf
trim_trailing_whitespace = true
insert_final_newline = true
[*.{yml,yaml}]
indent_style = space
indent_size = 2
[*.cs]
dotnet_hide_advanced_members = true
dotnet_member_insertion_location = with_other_members_of_the_same_kind
dotnet_property_generation_behavior = prefer_throwing_properties
dotnet_search_reference_assemblies = true
dotnet_separate_import_directive_groups = false:warning
dotnet_sort_system_directives_first = true:warning
file_header_template = unset
dotnet_style_qualification_for_event = false:warning
dotnet_style_qualification_for_field = false:warning
dotnet_style_qualification_for_method = false:warning
dotnet_style_qualification_for_property = false:warning
dotnet_style_predefined_type_for_locals_parameters_members = true:warning
dotnet_style_predefined_type_for_member_access = true:warning
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning
dotnet_style_parentheses_in_other_operators = always_for_clarity:warning
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning
dotnet_style_require_accessibility_modifiers = always:warning
dotnet_prefer_system_hash_code = true:warning
dotnet_style_coalesce_expression = true:warning
dotnet_style_collection_initializer = false:warning
dotnet_style_explicit_tuple_names = true:warning
dotnet_style_namespace_match_folder = true:warning
dotnet_style_null_propagation = true:warning
dotnet_style_object_initializer = true:warning
dotnet_style_operator_placement_when_wrapping = beginning_of_line
dotnet_style_prefer_auto_properties = true:warning
dotnet_style_prefer_collection_expression = false:warning
dotnet_style_prefer_compound_assignment = true:warning
dotnet_style_prefer_conditional_expression_over_assignment = false:warning
dotnet_style_prefer_conditional_expression_over_return = false:warning
dotnet_style_prefer_foreach_explicit_cast_in_source = always:warning
dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning
dotnet_style_prefer_inferred_tuple_names = true:warning
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning
dotnet_style_prefer_simplified_boolean_expressions = true:warning
dotnet_style_prefer_simplified_interpolation = true:warning
dotnet_style_readonly_field = true:warning
dotnet_code_quality_unused_parameters = all:warning
dotnet_remove_unnecessary_suppression_exclusions = none
dotnet_style_allow_multiple_blank_lines_experimental = false:warning
dotnet_style_allow_statement_immediately_after_block_experimental = true:warning
csharp_style_var_elsewhere = true:warning
csharp_style_var_for_built_in_types = true:warning
csharp_style_var_when_type_is_apparent = true:warning
csharp_style_expression_bodied_accessors = when_on_single_line:warning
csharp_style_expression_bodied_constructors = false:warning
csharp_style_expression_bodied_indexers = when_on_single_line:warning
csharp_style_expression_bodied_lambdas = when_on_single_line:warning
csharp_style_expression_bodied_local_functions = false:warning
csharp_style_expression_bodied_methods = false:warning
csharp_style_expression_bodied_operators = false:warning
csharp_style_expression_bodied_properties = when_on_single_line:warning
csharp_style_pattern_matching_over_as_with_null_check = true:warning
csharp_style_pattern_matching_over_is_with_cast_check = true:warning
csharp_style_prefer_extended_property_pattern = true:warning
csharp_style_prefer_not_pattern = true:warning
csharp_style_prefer_pattern_matching = true:warning
csharp_style_prefer_switch_expression = false:warning
csharp_style_conditional_delegate_call = true:warning
csharp_prefer_static_anonymous_function = true:warning
csharp_prefer_static_local_function = true:warning
csharp_preferred_modifier_order = public,internal,private,protected,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async:warning
csharp_style_prefer_readonly_struct = true:warning
csharp_style_prefer_readonly_struct_member = true:warning
csharp_prefer_braces = true:warning
csharp_prefer_simple_using_statement = true:warning
csharp_prefer_system_threading_lock = true:warning
csharp_style_namespace_declarations = file_scoped:warning
csharp_style_prefer_method_group_conversion = true:warning
csharp_style_prefer_primary_constructors = true:warning
csharp_style_prefer_top_level_statements = false:warning
csharp_prefer_simple_default_expression = true:warning
csharp_style_deconstructed_variable_declaration = true:warning
csharp_style_implicit_object_creation_when_type_is_apparent = true:warning
csharp_style_inlined_variable_declaration = true:warning
csharp_style_prefer_index_operator = false:warning
csharp_style_prefer_local_over_anonymous_function = true:warning
csharp_style_prefer_null_check_over_type_check = true:warning
csharp_style_prefer_range_operator = false:warning
csharp_style_prefer_tuple_swap = true:warning
csharp_style_prefer_utf8_string_literals = true:warning
csharp_style_throw_expression = true:warning
csharp_style_unused_value_assignment_preference = discard_variable:warning
csharp_style_unused_value_expression_statement_preference = discard_variable:warning
csharp_using_directive_placement = outside_namespace:warning
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:warning
csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:warning
csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = false:warning
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false:warning
csharp_style_allow_embedded_statements_on_same_line_experimental = false:warning
csharp_new_line_before_catch = true
csharp_new_line_before_else = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_open_brace = all
csharp_new_line_between_query_expression_clauses = true
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_case_contents_when_block = true
csharp_indent_labels = no_change
csharp_indent_switch_labels = true
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = false:warning
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = false
dotnet_naming_rule.interface_should_be_pascal.severity = warning
dotnet_naming_rule.interface_should_be_pascal.symbols = interface
dotnet_naming_rule.interface_should_be_pascal.style = pascal
dotnet_naming_rule.types_should_be_pascal.severity = warning
dotnet_naming_rule.types_should_be_pascal.symbols = types
dotnet_naming_rule.types_should_be_pascal.style = pascal
dotnet_naming_rule.non_field_members_should_be_pascal.severity = warning
dotnet_naming_rule.non_field_members_should_be_pascal.symbols = non_field_members
dotnet_naming_rule.non_field_members_should_be_pascal.style = pascal
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = *
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.applicable_accessibilities = *
dotnet_naming_symbols.types.required_modifiers =
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = *
dotnet_naming_symbols.non_field_members.required_modifiers =
dotnet_naming_style.pascal.required_prefix =
dotnet_naming_style.pascal.required_suffix =
dotnet_naming_style.pascal.word_separator =
dotnet_naming_style.pascal.capitalization = pascal_case

63
.gitattributes vendored Normal file
View File

@@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

11
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
- package-ecosystem: "nuget"
directory: "/"
schedule:
interval: "daily"

99
.github/workflows/build-linux.yml vendored Normal file
View File

@@ -0,0 +1,99 @@
name: release Linux
on:
workflow_dispatch:
inputs:
release_tag:
required: false
type: string
push:
branches:
- master
env:
OutputArch: "linux-64"
OutputArchArm: "linux-arm64"
OutputPath64: "${{ github.workspace }}/v2rayN/Release/linux-64"
OutputPathArm64: "${{ github.workspace }}/v2rayN/Release/linux-arm64"
jobs:
build:
strategy:
matrix:
configuration: [Release]
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4.2.2
- name: Setup
uses: actions/setup-dotnet@v4.3.0
with:
dotnet-version: '8.0.x'
- name: Build
run: |
cd v2rayN
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r linux-x64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -o $OutputPath64
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r linux-arm64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -o $OutputPathArm64
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r linux-x64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:PublishTrimmed=true -o $OutputPath64
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r linux-arm64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:PublishTrimmed=true -o $OutputPathArm64
- name: Upload build artifacts
uses: actions/upload-artifact@v4.6.0
with:
name: v2rayN-linux
path: |
${{ github.workspace }}/v2rayN/Release/linux*
# release debian package
- name: Package debian
if: github.event.inputs.release_tag != ''
run: |
chmod 755 package-debian.sh
./package-debian.sh $OutputArch $OutputPath64 ${{ github.event.inputs.release_tag }}
./package-debian.sh $OutputArchArm $OutputPathArm64 ${{ github.event.inputs.release_tag }}
- name: Upload deb to release
uses: svenstaro/upload-release-action@v2
if: github.event.inputs.release_tag != ''
with:
file: ${{ github.workspace }}/v2rayN*.deb
tag: ${{ github.event.inputs.release_tag }}
file_glob: true
prerelease: true
- name: Package AppImage
if: github.event.inputs.release_tag != ''
run: |
chmod 755 package-appimage.sh
./package-appimage.sh $OutputArch $OutputPath64 ${{ github.event.inputs.release_tag }}
./package-appimage.sh $OutputArchArm $OutputPathArm64 ${{ github.event.inputs.release_tag }}
- name: Upload AppImage to release
uses: svenstaro/upload-release-action@v2
if: github.event.inputs.release_tag != ''
with:
file: ${{ github.workspace }}/v2rayN*.AppImage
tag: ${{ github.event.inputs.release_tag }}
file_glob: true
prerelease: true
# release zip archive
- name: Package release zip archive
if: github.event.inputs.release_tag != ''
run: |
chmod 755 package-release-zip.sh
./package-release-zip.sh $OutputArch $OutputPath64
./package-release-zip.sh $OutputArchArm $OutputPathArm64
- name: Upload zip archive to release
uses: svenstaro/upload-release-action@v2
if: github.event.inputs.release_tag != ''
with:
file: ${{ github.workspace }}/v2rayN*.zip
tag: ${{ github.event.inputs.release_tag }}
file_glob: true
prerelease: true

84
.github/workflows/build-osx.yml vendored Normal file
View File

@@ -0,0 +1,84 @@
name: release macOS
on:
workflow_dispatch:
inputs:
release_tag:
required: false
type: string
push:
branches:
- master
env:
OutputArch: "macos-64"
OutputArchArm: "macos-arm64"
OutputPath64: "${{ github.workspace }}/v2rayN/Release/macos-64"
OutputPathArm64: "${{ github.workspace }}/v2rayN/Release/macos-arm64"
jobs:
build:
strategy:
matrix:
configuration: [Release]
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v4.2.2
- name: Setup
uses: actions/setup-dotnet@v4.3.0
with:
dotnet-version: '8.0.x'
- name: Build
run: |
cd v2rayN
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r osx-x64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -o $OutputPath64
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r osx-arm64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -o $OutputPathArm64
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r osx-x64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:PublishTrimmed=true -o $OutputPath64
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r osx-arm64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:PublishTrimmed=true -o $OutputPathArm64
- name: Upload build artifacts
uses: actions/upload-artifact@v4.6.0
with:
name: v2rayN-macos
path: |
${{ github.workspace }}/v2rayN/Release/macos*
# release osx package
- name: Package osx
if: github.event.inputs.release_tag != ''
run: |
brew install create-dmg
chmod 755 package-osx.sh
./package-osx.sh $OutputArch $OutputPath64 ${{ github.event.inputs.release_tag }}
./package-osx.sh $OutputArchArm $OutputPathArm64 ${{ github.event.inputs.release_tag }}
- name: Upload dmg to release
uses: svenstaro/upload-release-action@v2
if: github.event.inputs.release_tag != ''
with:
file: ${{ github.workspace }}/v2rayN*.dmg
tag: ${{ github.event.inputs.release_tag }}
file_glob: true
prerelease: true
# release zip archive
- name: Package release zip archive
if: github.event.inputs.release_tag != ''
run: |
chmod 755 package-release-zip.sh
./package-release-zip.sh $OutputArch $OutputPath64
./package-release-zip.sh $OutputArchArm $OutputPathArm64
- name: Upload zip archive to release
uses: svenstaro/upload-release-action@v2
if: github.event.inputs.release_tag != ''
with:
file: ${{ github.workspace }}/v2rayN*.zip
tag: ${{ github.event.inputs.release_tag }}
file_glob: true
prerelease: true

View File

@@ -0,0 +1,50 @@
name: release Windows desktop (Avalonia UI)
on:
workflow_dispatch:
inputs:
release_tag:
required: false
type: string
push:
branches:
- master
env:
OutputArch: "windows-64"
OutputArchArm: "windows-arm64"
OutputPath64: "${{ github.workspace }}/v2rayN/Release/windows-64"
OutputPathArm64: "${{ github.workspace }}/v2rayN/Release/windows-arm64"
jobs:
build:
strategy:
matrix:
configuration: [Release]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4.2.2
- name: Setup
uses: actions/setup-dotnet@v4.3.0
with:
dotnet-version: '8.0.x'
- name: Build
run: |
cd v2rayN
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r win-x64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:EnableWindowsTargeting=true -o $OutputPath64
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r win-arm64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:EnableWindowsTargeting=true -o $OutputPathArm64
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-x64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:PublishTrimmed=true -p:EnableWindowsTargeting=true -o $OutputPath64
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-arm64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:PublishTrimmed=true -p:EnableWindowsTargeting=true -o $OutputPathArm64
- name: Upload build artifacts
uses: actions/upload-artifact@v4.6.0
with:
name: v2rayN-windows-desktop
path: |
${{ github.workspace }}/v2rayN/Release/windows*

71
.github/workflows/build-windows.yml vendored Normal file
View File

@@ -0,0 +1,71 @@
name: release Windows
on:
workflow_dispatch:
inputs:
release_tag:
required: false
type: string
push:
branches:
- master
env:
OutputArch: "windows-64"
OutputArchArm: "windows-arm64"
OutputPath64: "${{ github.workspace }}/v2rayN/Release/windows-64"
OutputPathArm64: "${{ github.workspace }}/v2rayN/Release/windows-arm64"
OutputPath64Sc: "${{ github.workspace }}/v2rayN/Release/windows-64-SelfContained"
jobs:
build:
strategy:
matrix:
configuration: [Release]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4.2.2
- name: Setup
uses: actions/setup-dotnet@v4.3.0
with:
dotnet-version: '8.0.x'
- name: Build
run: |
cd v2rayN
dotnet publish ./v2rayN/v2rayN.csproj -c Release -r win-x64 --self-contained=false -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:EnableWindowsTargeting=true -o $OutputPath64
dotnet publish ./v2rayN/v2rayN.csproj -c Release -r win-arm64 --self-contained=false -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:EnableWindowsTargeting=true -o $OutputPathArm64
dotnet publish ./v2rayN/v2rayN.csproj -c Release -r win-x64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:EnableWindowsTargeting=true -o $OutputPath64Sc
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-x64 --self-contained=false -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:EnableWindowsTargeting=true -o $OutputPath64
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-arm64 --self-contained=false -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:EnableWindowsTargeting=true -o $OutputPathArm64
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-x64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:PublishTrimmed=true -p:EnableWindowsTargeting=true -o $OutputPath64Sc
- name: Upload build artifacts
uses: actions/upload-artifact@v4.6.0
with:
name: v2rayN-windows
path: |
${{ github.workspace }}/v2rayN/Release/windows*
# release zip archive
- name: Package release zip archive
if: github.event.inputs.release_tag != ''
run: |
chmod 755 package-release-zip.sh
./package-release-zip.sh $OutputArch $OutputPath64
./package-release-zip.sh $OutputArchArm $OutputPathArm64
./package-release-zip.sh "windows-64-SelfContained" $OutputPath64Sc
- name: Upload zip archive to release
uses: svenstaro/upload-release-action@v2
if: github.event.inputs.release_tag != ''
with:
file: ${{ github.workspace }}/v2rayN*.zip
tag: ${{ github.event.inputs.release_tag }}
file_glob: true
prerelease: true

31
.github/workflows/winget-publish.yml vendored Normal file
View File

@@ -0,0 +1,31 @@
name: WinGet submission on release
# based off of https://github.com/nushell/nushell/blob/main/.github/workflows/winget-submission.yml
# inspired by https://github.com/microsoft/PowerToys/blob/main/.github/workflows/package-submissions.yml
# Modified by @MerrickZ https://github.com/anpho
on:
workflow_dispatch:
release:
types: [released]
jobs:
winget:
name: Publish winget package
runs-on: windows-latest
steps:
- name: Submit v2ray package to Windows Package Manager Community Repository
run: |
$wingetPackage = "2dust.v2rayN"
$gitToken = "${{ secrets.PT_WINGET }}"
$github = Invoke-RestMethod -uri "https://api.github.com/repos/2dust/v2rayN/releases"
$targetRelease = $github | Where-Object -Property prerelease -match 'False' | Select -First 1
$installerUrl = $targetRelease | Select -ExpandProperty assets -First 1 | Where-Object -Property name -match 'v2rayN-windows-64\.zip*' | Select -ExpandProperty browser_download_url
$ver = $targetRelease.tag_name
# getting latest wingetcreate file
iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe
.\wingetcreate.exe update $wingetPackage -s -v $ver -u "$installerUrl|x64" -t $gitToken

414
.gitignore vendored
View File

@@ -1,18 +1,400 @@
################################################################################
# 此 .gitignore 文件已由 Microsoft(R) Visual Studio 自动创建。
################################################################################
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
/v2rayN/.vs/
/v2rayN/v2rayN/bin/Debug/app.publish
/v2rayN/v2rayN/bin/Debug
/v2rayN/v2rayN/bin/Release
/v2rayN/v2rayN/obj/
/v2rayN/.vs/v2rayN/DesignTimeBuild
/v2rayN/packages
.vs/ProjectSettings.json
.vs/slnx.sqlite
.vs/VSWorkspaceState.json
/v2rayN/v2rayUpgrade/bin/Debug
/v2rayN/v2rayUpgrade/bin/Release
/v2rayN/v2rayUpgrade/obj/
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
# but not Directory.Build.rsp, as it configures directory-level build defaults
!Directory.Build.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml

View File

@@ -1,5 +1,5 @@
# v2rayN
A V2Ray client for Windows, support [Xray core](https://github.com/XTLS/Xray-core) and [v2fly core](https://github.com/v2fly/v2ray-core)
A GUI client for Windows, Linux and macOS, support [Xray](https://github.com/XTLS/Xray-core) and [sing-box](https://github.com/SagerNet/sing-box/releases) and [others](https://github.com/2dust/v2rayN/wiki/List-of-supported-cores)
[![GitHub commit activity](https://img.shields.io/github/commit-activity/m/2dust/v2rayN)](https://github.com/2dust/v2rayN/commits/master)
@@ -7,12 +7,10 @@ A V2Ray client for Windows, support [Xray core](https://github.com/XTLS/Xray-cor
[![GitHub Releases](https://img.shields.io/github/downloads/2dust/v2rayN/latest/total?logo=github)](https://github.com/2dust/v2rayN/releases)
[![Chat on Telegram](https://img.shields.io/badge/Chat%20on-Telegram-brightgreen.svg)](https://t.me/v2rayn)
### How to use
- If you are new to this, please download v2rayN-Core.zip from [releases](https://github.com/2dust/v2rayN/releases)
- Otherwise please download v2rayN.zip (you will also need to download v2ray core into the same folder with v2rayN.exe)
- Run v2rayN.exe
### Requirements
- Microsoft [.NET Framework 4.8 Runtime](https://dotnet.microsoft.com/zh-cn/download/dotnet-framework/thank-you/net48-offline-installer)
- v2fly core [https://github.com/v2fly/v2ray-core/releases](https://github.com/v2fly/v2ray-core/releases)
- Xray core [https://github.com/XTLS/Xray-core/releases](https://github.com/XTLS/Xray-core/releases)
## How to use
Read the [Wiki](https://github.com/2dust/v2rayN/wiki) for details.
## Telegram Channel
[github_2dust](https://t.me/github_2dust)

112
package-appimage.sh Normal file
View File

@@ -0,0 +1,112 @@
#!/bin/bash
Arch="$1"
OutputPath="$2"
Version="$3"
FileName="v2rayN-${Arch}.zip"
wget -nv -O $FileName "https://github.com/2dust/v2rayN-core-bin/raw/refs/heads/master/$FileName"
7z x $FileName -aoa
cp -rf v2rayN-${Arch}/* $OutputPath
PackagePath="v2rayN-Package-${Arch}"
mkdir -p "${PackagePath}/AppDir/opt"
cp -rf $OutputPath "${PackagePath}/AppDir/opt/v2rayN"
echo "When this file exists, app will not store configs under this folder" >"${PackagePath}/AppDir/opt/v2rayN/NotStoreConfigHere.txt"
if [ $Arch = "linux-64" ]; then
Arch2="x86_64"
Arch3="amd64"
Interpreter="ld-linux-x86-64.so.2"
else
Arch2="aarch64"
Arch3="arm64"
Interpreter="ld-linux-aarch64.so.1"
fi
echo $Arch2
# basic
cat >"${PackagePath}/AppDir/AppRun" <<-EOF
#!/bin/sh
HERE="\$(dirname "\$(readlink -f "\${0}")")"
export PATH="\${HERE}"/opt/v2rayN/:"\${PATH}"
export LD_LIBRARY_PATH="\${HERE}"/opt/v2rayN/:"\${LD_LIBRARY_PATH}"
cd "\${HERE}/opt/v2rayN"
exec "\${HERE}/opt/v2rayN/v2rayN" \$@
EOF
cat >"${PackagePath}/AppDir/v2rayN.desktop" <<-EOF
[Desktop Entry]
Name=v2rayN
Comment=A GUI client for Windows and Linux, support Xray core and sing-box-core and others
Exec=v2rayN
Icon=v2rayN
Terminal=false
Type=Application
Categories=Network;
EOF
sudo cp "${PackagePath}/AppDir/opt/v2rayN/v2rayN.png" "${PackagePath}/AppDir/v2rayN.png"
sudo dpkg --add-architecture ${Arch3}
sudo apt update
mkdir deb_folder
cd deb_folder
apt download libstdc++6:${Arch3}
apt download libc6:${Arch3}
apt download libcrypt1:${Arch3}
apt download libgcc-s1:${Arch3}
apt download libidn2-0:${Arch3}
apt download gcc-12-base:${Arch3}
apt download zlib1g:${Arch3}
apt download libfreetype6:${Arch3}
apt download libexpat1:${Arch3}
apt download libbrotli1:${Arch3}
apt download libx11-6:${Arch3}
apt download libx11-xcb1:${Arch3}
apt download libxcb1:${Arch3}
apt download libxau6:${Arch3}
apt download libxdmcp6:${Arch3}
apt download libbsd0:${Arch3}
apt download libmd0:${Arch3}
apt download libice6:${Arch3}
apt download libsm6:${Arch3}
apt download libuuid1:${Arch3}
apt download libxrandr2:${Arch3}
apt download libxext6:${Arch3}
apt download libxrender1:${Arch3}
apt download libxi6:${Arch3}
apt download libsm6:${Arch3}
apt download libxcursor1:${Arch3}
apt download libxfixes3:${Arch3}
apt download libpng16-16:${Arch3} || true
apt download libpng16-16t64:${Arch3} || true
apt download libicu66:${Arch3} || true
apt download libicu70:${Arch3} || true
apt download libicu74:${Arch3} || true
apt download libfontconfig1:${Arch3} || true
apt download libfontconfig:${Arch3} || true
mkdir ../output_folder
for deb in *.deb; do
dpkg-deb -x "$deb" ../output_folder/
done
cd ..
find output_folder -type f -name "*.so*" -exec cp {} ${PackagePath}/AppDir/opt/v2rayN/ \;
find output_folder -type l -name "*.so*" -exec cp {} ${PackagePath}/AppDir/opt/v2rayN/ \;
rm -rf deb_folder output_folder
sudo chmod 0755 "${PackagePath}/AppDir/opt/v2rayN/v2rayN"
sudo chmod 0755 "${PackagePath}/AppDir/AppRun"
sudo apt install -y patchelf
pushd "${PackagePath}/AppDir/opt/v2rayN"
patchelf --set-interpreter ${Interpreter} v2rayN
popd
# desktop && PATH
wget "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
chmod a+x appimagetool-x86_64.AppImage
sudo apt install -y libfuse2
sudo ./appimagetool-x86_64.AppImage "${PackagePath}/AppDir"
sudo mv "v2rayN-${Arch2}.AppImage" "v2rayN-${Arch}.AppImage"

58
package-debian.sh Normal file
View File

@@ -0,0 +1,58 @@
#!/bin/bash
Arch="$1"
OutputPath="$2"
Version="$3"
FileName="v2rayN-${Arch}.zip"
wget -nv -O $FileName "https://github.com/2dust/v2rayN-core-bin/raw/refs/heads/master/$FileName"
7z x $FileName
cp -rf v2rayN-${Arch}/* $OutputPath
PackagePath="v2rayN-Package-${Arch}"
mkdir -p "${PackagePath}/DEBIAN"
mkdir -p "${PackagePath}/opt"
cp -rf $OutputPath "${PackagePath}/opt/v2rayN"
echo "When this file exists, app will not store configs under this folder" > "${PackagePath}/opt/v2rayN/NotStoreConfigHere.txt"
if [ $Arch = "linux-64" ]; then
Arch2="amd64"
else
Arch2="arm64"
fi
echo $Arch2
# basic
cat >"${PackagePath}/DEBIAN/control" <<-EOF
Package: v2rayN
Version: $Version
Architecture: $Arch2
Maintainer: https://github.com/2dust/v2rayN
Description: A GUI client for Windows and Linux, support Xray core and sing-box-core and others
EOF
cat >"${PackagePath}/DEBIAN/postinst" <<-EOF
if [ ! -s /usr/share/applications/v2rayN.desktop ]; then
cat >/usr/share/applications/v2rayN.desktop<<-END
[Desktop Entry]
Name=v2rayN
Comment=A GUI client for Windows and Linux, support Xray core and sing-box-core and others
Exec=/opt/v2rayN/v2rayN
Icon=/opt/v2rayN/v2rayN.png
Terminal=false
Type=Application
Categories=Network;Application;
END
fi
update-desktop-database
EOF
sudo chmod 0755 "${PackagePath}/DEBIAN/postinst"
sudo chmod 0755 "${PackagePath}/opt/v2rayN/v2rayN"
sudo chmod 0755 "${PackagePath}/opt/v2rayN/AmazTool"
# desktop && PATH
sudo dpkg-deb -Zxz --build $PackagePath
sudo mv "${PackagePath}.deb" "v2rayN-${Arch}.deb"

58
package-osx.sh Executable file
View File

@@ -0,0 +1,58 @@
#!/bin/bash
Arch="$1"
OutputPath="$2"
Version="$3"
FileName="v2rayN-${Arch}.zip"
wget -nv -O $FileName "https://github.com/2dust/v2rayN-core-bin/raw/refs/heads/master/$FileName"
7z x $FileName
cp -rf v2rayN-${Arch}/* $OutputPath
PackagePath="v2rayN-Package-${Arch}"
mkdir -p "$PackagePath/v2rayN.app/Contents/Resources"
cp -rf "$OutputPath" "$PackagePath/v2rayN.app/Contents/MacOS"
cp -f "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN.icns" "$PackagePath/v2rayN.app/Contents/Resources/AppIcon.icns"
echo "When this file exists, app will not store configs under this folder" > "$PackagePath/v2rayN.app/Contents/MacOS/NotStoreConfigHere.txt"
chmod +x "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN"
cat >"$PackagePath/v2rayN.app/Contents/Info.plist" <<-EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDisplayName</key>
<string>v2rayN</string>
<key>CFBundleExecutable</key>
<string>v2rayN</string>
<key>CFBundleIconFile</key>
<string>AppIcon</string>
<key>CFBundleIconName</key>
<string>AppIcon</string>
<key>CFBundleIdentifier</key>
<string>2dust.v2rayN</string>
<key>CFBundleName</key>
<string>v2rayN</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>${Version}</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
</plist>
EOF
create-dmg \
--volname "v2rayN Installer" \
--window-size 700 420 \
--icon-size 100 \
--icon "v2rayN.app" 160 185 \
--hide-extension "v2rayN.app" \
--app-drop-link 500 185 \
"v2rayN-${Arch}.dmg" \
"$PackagePath/v2rayN.app"

15
package-release-zip.sh Normal file
View File

@@ -0,0 +1,15 @@
#!/bin/bash
Arch="$1"
OutputPath="$2"
OutputArch="v2rayN-${Arch}"
FileName="v2rayN-${Arch}.zip"
wget -nv -O $FileName "https://github.com/2dust/v2rayN-core-bin/raw/refs/heads/master/$FileName"
ZipPath64="./$OutputArch"
mkdir $ZipPath64
cp -rf $OutputPath "$ZipPath64/$OutputArch"
7z a -tZip $FileName "$ZipPath64/$OutputArch" -mx1

View File

@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Update="Resx\Resource.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resource.Designer.cs</LastGenOutput>
</EmbeddedResource>
<Compile Update="Resx\Resource.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resource.resx</DependentUpon>
</Compile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,29 @@
namespace AmazTool
{
internal static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
private static void Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine(Resx.Resource.Guidelines);
Thread.Sleep(5000);
return;
}
var argData = Uri.UnescapeDataString(string.Join(" ", args));
if (argData.Equals("rebootas"))
{
Thread.Sleep(1000);
Utils.StartV2RayN();
return;
}
UpgradeApp.Upgrade(argData);
}
}
}

171
v2rayN/AmazTool/Resx/Resource.Designer.cs generated Normal file
View File

@@ -0,0 +1,171 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace AmazTool.Resx {
using System;
/// <summary>
/// 一个强类型的资源类,用于查找本地化的字符串等。
/// </summary>
// 此类是由 StronglyTypedResourceBuilder
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
// (以 /str 作为命令选项),或重新生成 VS 项目。
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resource {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resource() {
}
/// <summary>
/// 返回此类使用的缓存的 ResourceManager 实例。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AmazTool.Resx.Resource", typeof(Resource).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// 重写当前线程的 CurrentUICulture 属性,对
/// 使用此强类型资源类的所有资源查找执行重写。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// 查找类似 Failed to terminate the v2rayN.Close it manually,or the upgrade may fail. 的本地化字符串。
/// </summary>
internal static string FailedTerminateProcess {
get {
return ResourceManager.GetString("FailedTerminateProcess", resourceCulture);
}
}
/// <summary>
/// 查找类似 Failed to extract the update package. 的本地化字符串。
/// </summary>
internal static string FailedUnzipping {
get {
return ResourceManager.GetString("FailedUnzipping", resourceCulture);
}
}
/// <summary>
/// 查找类似 Upgrade failed. 的本地化字符串。
/// </summary>
internal static string FailedUpgrade {
get {
return ResourceManager.GetString("FailedUpgrade", resourceCulture);
}
}
/// <summary>
/// 查找类似 Please run it from the main application. 的本地化字符串。
/// </summary>
internal static string Guidelines {
get {
return ResourceManager.GetString("Guidelines", resourceCulture);
}
}
/// <summary>
/// 查找类似 Information 的本地化字符串。
/// </summary>
internal static string Information {
get {
return ResourceManager.GetString("Information", resourceCulture);
}
}
/// <summary>
/// 查找类似 In progress, please wait... 的本地化字符串。
/// </summary>
internal static string InProgress {
get {
return ResourceManager.GetString("InProgress", resourceCulture);
}
}
/// <summary>
/// 查找类似 Start v2rayN, please wait... 的本地化字符串。
/// </summary>
internal static string Restartv2rayN {
get {
return ResourceManager.GetString("Restartv2rayN", resourceCulture);
}
}
/// <summary>
/// 查找类似 Start extracting the update package... 的本地化字符串。
/// </summary>
internal static string StartUnzipping {
get {
return ResourceManager.GetString("StartUnzipping", resourceCulture);
}
}
/// <summary>
/// 查找类似 Successfully extracted the update package. 的本地化字符串。
/// </summary>
internal static string SuccessUnzipping {
get {
return ResourceManager.GetString("SuccessUnzipping", resourceCulture);
}
}
/// <summary>
/// 查找类似 Upgrade success. 的本地化字符串。
/// </summary>
internal static string SuccessUpgrade {
get {
return ResourceManager.GetString("SuccessUpgrade", resourceCulture);
}
}
/// <summary>
/// 查找类似 Try to terminate the v2rayN process... 的本地化字符串。
/// </summary>
internal static string TryTerminateProcess {
get {
return ResourceManager.GetString("TryTerminateProcess", resourceCulture);
}
}
/// <summary>
/// 查找类似 Upgrade failed, file not found. 的本地化字符串。
/// </summary>
internal static string UpgradeFileNotFound {
get {
return ResourceManager.GetString("UpgradeFileNotFound", resourceCulture);
}
}
}
}

View File

@@ -117,44 +117,40 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="label4.Size" type="System.Drawing.Size, System.Drawing">
<value>53, 12</value>
<data name="Restartv2rayN" xml:space="preserve">
<value>Start v2rayN, please wait...</value>
</data>
<data name="label4.Text" xml:space="preserve">
<value>所属分组</value>
<data name="Guidelines" xml:space="preserve">
<value>Please run it from the main application.</value>
</data>
<data name="label1.Size" type="System.Drawing.Size, System.Drawing">
<value>101, 12</value>
<data name="UpgradeFileNotFound" xml:space="preserve">
<value>Upgrade failed, file not found.</value>
</data>
<data name="label1.Text" xml:space="preserve">
<value>User Agent(可选)</value>
<data name="InProgress" xml:space="preserve">
<value>In progress, please wait...</value>
</data>
<data name="btnShare.Text" xml:space="preserve">
<value>分享</value>
<data name="TryTerminateProcess" xml:space="preserve">
<value>Try to terminate the v2rayN process...</value>
</data>
<data name="chkEnabled.Size" type="System.Drawing.Size, System.Drawing">
<value>48, 16</value>
<data name="FailedTerminateProcess" xml:space="preserve">
<value>Failed to terminate the v2rayN.Close it manually,or the upgrade may fail.</value>
</data>
<data name="chkEnabled.Text" xml:space="preserve">
<value>启用</value>
<data name="StartUnzipping" xml:space="preserve">
<value>Start extracting the update package...</value>
</data>
<data name="btnRemove.Text" xml:space="preserve">
<value>移除</value>
<data name="SuccessUnzipping" xml:space="preserve">
<value>Successfully extracted the update package.</value>
</data>
<data name="label2.Size" type="System.Drawing.Size, System.Drawing">
<value>29, 12</value>
<data name="FailedUnzipping" xml:space="preserve">
<value>Failed to extract the update package.</value>
</data>
<data name="label2.Text" xml:space="preserve">
<value>备注</value>
<data name="FailedUpgrade" xml:space="preserve">
<value>Upgrade failed.</value>
</data>
<data name="label3.Size" type="System.Drawing.Size, System.Drawing">
<value>65, 12</value>
<data name="SuccessUpgrade" xml:space="preserve">
<value>Upgrade success.</value>
</data>
<data name="label3.Text" xml:space="preserve">
<value>地址 (url)</value>
</data>
<data name="grbMain.Text" xml:space="preserve">
<value>订阅详情</value>
<data name="Information" xml:space="preserve">
<value>Information</value>
</data>
</root>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
@@ -117,25 +117,40 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="groupBox1.Text" xml:space="preserve">
<value>过滤器</value>
<data name="Restartv2rayN" xml:space="preserve">
<value>正在重启,请等待...</value>
</data>
<data name="btnClose.Text" xml:space="preserve">
<value>取消(&amp;C)</value>
<data name="Guidelines" xml:space="preserve">
<value>请从主应用运行。</value>
</data>
<data name="btnOK.Text" xml:space="preserve">
<value>确定(&amp;O)</value>
<data name="UpgradeFileNotFound" xml:space="preserve">
<value>升级失败,文件不存在。</value>
</data>
<data name="$this.Text" xml:space="preserve">
<value>设置过滤器</value>
<data name="InProgress" xml:space="preserve">
<value>正在进行中,请等待...</value>
</data>
<data name="btnFilderProxy.Text" xml:space="preserve">
<value>过滤Proxy</value>
<data name="TryTerminateProcess" xml:space="preserve">
<value>尝试结束 v2rayN 进程...</value>
</data>
<data name="btnFilterDirect.Text" xml:space="preserve">
<value>过滤Direct</value>
<data name="FailedTerminateProcess" xml:space="preserve">
<value>请手动关闭正在运行的v2rayN否则可能升级失败。</value>
</data>
<data name="btnClear.Text" xml:space="preserve">
<value>清空</value>
<data name="StartUnzipping" xml:space="preserve">
<value>开始解压缩更新包...</value>
</data>
<data name="SuccessUnzipping" xml:space="preserve">
<value>解压缩更新包成功。</value>
</data>
<data name="FailedUnzipping" xml:space="preserve">
<value>解压缩更新包失败。</value>
</data>
<data name="FailedUpgrade" xml:space="preserve">
<value>升级失败。</value>
</data>
<data name="SuccessUpgrade" xml:space="preserve">
<value>升级成功。</value>
</data>
<data name="Information" xml:space="preserve">
<value>提示</value>
</data>
</root>

View File

@@ -0,0 +1,105 @@
using System.Diagnostics;
using System.IO.Compression;
using System.Text;
namespace AmazTool
{
internal class UpgradeApp
{
public static void Upgrade(string fileName)
{
Console.WriteLine($"{Resx.Resource.StartUnzipping}\n{fileName}");
Utils.Waiting(5);
if (!File.Exists(fileName))
{
Console.WriteLine(Resx.Resource.UpgradeFileNotFound);
return;
}
Console.WriteLine(Resx.Resource.TryTerminateProcess);
try
{
var existing = Process.GetProcessesByName(Utils.V2rayN);
foreach (var pp in existing)
{
var path = pp.MainModule?.FileName ?? "";
if (path.StartsWith(Utils.GetPath(Utils.V2rayN)))
{
pp?.Kill();
pp?.WaitForExit(1000);
}
}
}
catch (Exception ex)
{
// Access may be denied without admin right. The user may not be an administrator.
Console.WriteLine(Resx.Resource.FailedTerminateProcess + ex.StackTrace);
}
Console.WriteLine(Resx.Resource.StartUnzipping);
StringBuilder sb = new();
try
{
var thisAppOldFile = $"{Utils.GetExePath()}.tmp";
File.Delete(thisAppOldFile);
var splitKey = "/";
using var archive = ZipFile.OpenRead(fileName);
foreach (var entry in archive.Entries)
{
try
{
if (entry.Length == 0)
{
continue;
}
Console.WriteLine(entry.FullName);
var lst = entry.FullName.Split(splitKey);
if (lst.Length == 1)
continue;
var fullName = string.Join(splitKey, lst[1..lst.Length]);
if (string.Equals(Utils.GetExePath(), Utils.GetPath(fullName), StringComparison.OrdinalIgnoreCase))
{
File.Move(Utils.GetExePath(), thisAppOldFile);
}
var entryOutputPath = Utils.GetPath(fullName);
Directory.CreateDirectory(Path.GetDirectoryName(entryOutputPath)!);
//In the bin folder, if the file already exists, it will be skipped
if (fullName.StartsWith("bin") && File.Exists(entryOutputPath))
{
continue;
}
entry.ExtractToFile(entryOutputPath, true);
Console.WriteLine(entryOutputPath);
}
catch (Exception ex)
{
sb.Append(ex.StackTrace);
}
}
}
catch (Exception ex)
{
Console.WriteLine(Resx.Resource.FailedUpgrade + ex.StackTrace);
//return;
}
if (sb.Length > 0)
{
Console.WriteLine(Resx.Resource.FailedUpgrade + sb.ToString());
//return;
}
Console.WriteLine(Resx.Resource.Restartv2rayN);
Utils.Waiting(2);
Utils.StartV2RayN();
}
}
}

52
v2rayN/AmazTool/Utils.cs Normal file
View File

@@ -0,0 +1,52 @@
using System.Diagnostics;
namespace AmazTool
{
internal class Utils
{
public static string GetExePath()
{
return Environment.ProcessPath ?? Process.GetCurrentProcess().MainModule?.FileName ?? string.Empty;
}
public static string StartupPath()
{
return AppDomain.CurrentDomain.BaseDirectory;
}
public static string GetPath(string fileName)
{
string startupPath = StartupPath();
if (string.IsNullOrEmpty(fileName))
{
return startupPath;
}
return Path.Combine(startupPath, fileName);
}
public static string V2rayN => "v2rayN";
public static void StartV2RayN()
{
Process process = new()
{
StartInfo = new()
{
UseShellExecute = true,
FileName = V2rayN,
WorkingDirectory = StartupPath()
}
};
process.Start();
}
public static void Waiting(int second)
{
for (var i = second; i > 0; i--)
{
Console.WriteLine(i);
Thread.Sleep(1000);
}
}
}
}

View File

@@ -0,0 +1,32 @@
<Project>
<PropertyGroup>
<Version>7.8.3</Version>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
<NoWarn>CA1031;CS1591;NU1507;CA1416</NoWarn>
<Nullable>annotations</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<Authors>2dust</Authors>
<PackageLicenseExpression>GPL-3.0</PackageLicenseExpression>
<Copyright>Copyright © 2017-$([System.DateTime]::UtcNow.Year) $(Authors)</Copyright>
<InvariantGlobalization>false</InvariantGlobalization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<DebugType>embedded</DebugType>
<EventSourceSupport>false</EventSourceSupport>
<StackTraceSupport>false</StackTraceSupport>
<MetricsSupport>false</MetricsSupport>
<MetadataUpdaterSupport>false</MetadataUpdaterSupport>
<EnableUnsafeBinaryFormatterSerialization>false</EnableUnsafeBinaryFormatterSerialization>
<EnableUnsafeUTF7Encoding>false</EnableUnsafeUTF7Encoding>
<UseSystemResourceKeys>true</UseSystemResourceKeys>
<PublishSingleFile>true</PublishSingleFile>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,30 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
<CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.2.3" />
<PackageVersion Include="Avalonia.Desktop" Version="11.2.3" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.2.3" />
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.2.3" />
<PackageVersion Include="CliWrap" Version="3.7.1" />
<PackageVersion Include="Downloader" Version="3.3.3" />
<PackageVersion Include="H.NotifyIcon.Wpf" Version="2.2.0" />
<PackageVersion Include="MaterialDesignThemes" Version="5.2.1" />
<PackageVersion Include="MessageBox.Avalonia" Version="3.2.0" />
<PackageVersion Include="QRCoder" Version="1.6.0" />
<PackageVersion Include="ReactiveUI" Version="20.1.63" />
<PackageVersion Include="ReactiveUI.Fody" Version="19.5.41" />
<PackageVersion Include="ReactiveUI.WPF" Version="20.1.63" />
<PackageVersion Include="Semi.Avalonia" Version="11.2.1.4" />
<PackageVersion Include="Semi.Avalonia.DataGrid" Version="11.2.1.4" />
<PackageVersion Include="Splat.NLog" Version="15.3.1" />
<PackageVersion Include="sqlite-net-pcl" Version="1.9.172" />
<PackageVersion Include="TaskScheduler" Version="2.11.0" />
<PackageVersion Include="WebDav.Client" Version="2.8.0" />
<PackageVersion Include="YamlDotNet" Version="16.3.0" />
<PackageVersion Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.14" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,10 @@
using ReactiveUI;
namespace ServiceLib.Base
{
public class MyReactiveObject : ReactiveObject
{
protected static Config? _config;
protected Func<EViewAction, object?, Task<bool>>? _updateView;
}
}

View File

@@ -0,0 +1,101 @@
using System.Security.Cryptography;
using System.Text;
namespace ServiceLib.Common
{
public class AesUtils
{
private const int KeySize = 256; // AES-256
private const int IvSize = 16; // AES block size
private const int Iterations = 10000;
private static readonly byte[] Salt = Encoding.ASCII.GetBytes("saltysalt".PadRight(16, ' ')); // google浏览器默认盐值
private static readonly string DefaultPassword = Utils.GetMd5(Utils.GetHomePath() + "AesUtils");
/// <summary>
/// Encrypt
/// </summary>
/// <param name="text">Plain text</param>
/// <param name="password">Password for key derivation or direct key in ASCII bytes</param>
/// <returns>Base64 encoded cipher text with IV</returns>
public static string Encrypt(string text, string? password = null)
{
if (string.IsNullOrEmpty(text))
return string.Empty;
var plaintext = Encoding.UTF8.GetBytes(text);
var key = GetKey(password);
var iv = GenerateIv();
using var aes = Aes.Create();
aes.Key = key;
aes.IV = iv;
using var ms = new MemoryStream();
ms.Write(iv, 0, iv.Length);
using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(plaintext, 0, plaintext.Length);
cs.FlushFinalBlock();
}
var cipherTextWithIv = ms.ToArray();
return Convert.ToBase64String(cipherTextWithIv);
}
/// <summary>
/// Decrypt
/// </summary>
/// <param name="cipherTextWithIv">Base64 encoded cipher text with IV</param>
/// <param name="password">Password for key derivation or direct key in ASCII bytes</param>
/// <returns>Plain text</returns>
public static string Decrypt(string cipherTextWithIv, string? password = null)
{
if (string.IsNullOrEmpty(cipherTextWithIv))
return string.Empty;
var cipherTextWithIvBytes = Convert.FromBase64String(cipherTextWithIv);
var key = GetKey(password);
var iv = new byte[IvSize];
Buffer.BlockCopy(cipherTextWithIvBytes, 0, iv, 0, IvSize);
var cipherText = new byte[cipherTextWithIvBytes.Length - IvSize];
Buffer.BlockCopy(cipherTextWithIvBytes, IvSize, cipherText, 0, cipherText.Length);
using var aes = Aes.Create();
aes.Key = key;
aes.IV = iv;
using var ms = new MemoryStream();
using (var cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(cipherText, 0, cipherText.Length);
cs.FlushFinalBlock();
}
var plainText = ms.ToArray();
return Encoding.UTF8.GetString(plainText);
}
private static byte[] GetKey(string? password)
{
if (password.IsNullOrEmpty())
{
password = DefaultPassword;
}
using var pbkdf2 = new Rfc2898DeriveBytes(password, Salt, Iterations, HashAlgorithmName.SHA256);
return pbkdf2.GetBytes(KeySize / 8);
}
private static byte[] GenerateIv()
{
var randomNumber = new byte[IvSize];
using var rng = RandomNumberGenerator.Create();
rng.GetBytes(randomNumber);
return randomNumber;
}
}
}

View File

@@ -0,0 +1,75 @@
using System.Security.Cryptography;
using System.Text;
namespace ServiceLib.Common
{
public class DesUtils
{
/// <summary>
/// Encrypt
/// </summary>
/// <param name="text"></param>
/// /// <param name="key"></param>
/// <returns></returns>
public static string Encrypt(string? text, string? key = null)
{
if (text.IsNullOrEmpty())
{
return string.Empty;
}
GetKeyIv(key ?? GetDefaultKey(), out var rgbKey, out var rgbIv);
var dsp = DES.Create();
using var memStream = new MemoryStream();
using var cryStream = new CryptoStream(memStream, dsp.CreateEncryptor(rgbKey, rgbIv), CryptoStreamMode.Write);
using var sWriter = new StreamWriter(cryStream);
sWriter.Write(text);
sWriter.Flush();
cryStream.FlushFinalBlock();
memStream.Flush();
return Convert.ToBase64String(memStream.GetBuffer(), 0, (int)memStream.Length);
}
/// <summary>
/// Decrypt
/// </summary>
/// <param name="encryptText"></param>
/// <param name="key"></param>
/// <returns></returns>
public static string Decrypt(string? encryptText, string? key = null)
{
if (encryptText.IsNullOrEmpty())
{
return string.Empty;
}
GetKeyIv(key ?? GetDefaultKey(), out var rgbKey, out var rgbIv);
var dsp = DES.Create();
var buffer = Convert.FromBase64String(encryptText);
using var memStream = new MemoryStream();
using var cryStream = new CryptoStream(memStream, dsp.CreateDecryptor(rgbKey, rgbIv), CryptoStreamMode.Write);
cryStream.Write(buffer, 0, buffer.Length);
cryStream.FlushFinalBlock();
return Encoding.UTF8.GetString(memStream.ToArray());
}
private static void GetKeyIv(string key, out byte[] rgbKey, out byte[] rgbIv)
{
if (key.IsNullOrEmpty())
{
throw new ArgumentNullException("The key cannot be null");
}
if (key.Length <= 8)
{
throw new ArgumentNullException("The key length cannot be less than 8 characters.");
}
rgbKey = Encoding.ASCII.GetBytes(key.Substring(0, 8));
rgbIv = Encoding.ASCII.GetBytes(key.Insert(0, "w").Substring(0, 8));
}
private static string GetDefaultKey()
{
return Utils.GetMd5(Utils.GetHomePath() + "DesUtils");
}
}
}

View File

@@ -0,0 +1,184 @@
using System.Net;
using Downloader;
namespace ServiceLib.Common
{
public class DownloaderHelper
{
private static readonly Lazy<DownloaderHelper> _instance = new(() => new());
public static DownloaderHelper Instance => _instance.Value;
public async Task<string?> DownloadStringAsync(IWebProxy? webProxy, string url, string? userAgent, int timeout)
{
if (Utils.IsNullOrEmpty(url))
{
return null;
}
Uri uri = new(url);
//Authorization Header
var headers = new WebHeaderCollection();
if (Utils.IsNotEmpty(uri.UserInfo))
{
headers.Add(HttpRequestHeader.Authorization, "Basic " + Utils.Base64Encode(uri.UserInfo));
}
var downloadOpt = new DownloadConfiguration()
{
Timeout = timeout * 1000,
MaxTryAgainOnFailover = 2,
RequestConfiguration =
{
Headers = headers,
UserAgent = userAgent,
Timeout = timeout * 1000,
Proxy = webProxy
}
};
await using var downloader = new Downloader.DownloadService(downloadOpt);
downloader.DownloadFileCompleted += (sender, value) =>
{
if (value.Error != null)
{
throw value.Error;
}
};
using var cts = new CancellationTokenSource();
await using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token);
using StreamReader reader = new(stream);
downloadOpt = null;
return await reader.ReadToEndAsync(cts.Token);
}
public async Task DownloadDataAsync4Speed(IWebProxy webProxy, string url, IProgress<string> progress, int timeout)
{
if (Utils.IsNullOrEmpty(url))
{
throw new ArgumentNullException(nameof(url));
}
var downloadOpt = new DownloadConfiguration()
{
Timeout = timeout * 1000,
MaxTryAgainOnFailover = 2,
RequestConfiguration =
{
Timeout= timeout * 1000,
Proxy = webProxy
}
};
var totalDatetime = DateTime.Now;
var totalSecond = 0;
var hasValue = false;
double maxSpeed = 0;
await using var downloader = new Downloader.DownloadService(downloadOpt);
//downloader.DownloadStarted += (sender, value) =>
//{
// if (progress != null)
// {
// progress.Report("Start download data...");
// }
//};
downloader.DownloadProgressChanged += (sender, value) =>
{
var ts = (DateTime.Now - totalDatetime);
if (progress != null && ts.Seconds > totalSecond)
{
hasValue = true;
totalSecond = ts.Seconds;
if (value.BytesPerSecondSpeed > maxSpeed)
{
maxSpeed = value.BytesPerSecondSpeed;
var speed = (maxSpeed / 1000 / 1000).ToString("#0.0");
progress.Report(speed);
}
}
};
downloader.DownloadFileCompleted += (sender, value) =>
{
if (progress != null)
{
if (!hasValue && value.Error != null)
{
progress.Report(value.Error?.Message);
}
}
};
//progress.Report("......");
using var cts = new CancellationTokenSource();
cts.CancelAfter(timeout * 1000);
await using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token);
downloadOpt = null;
}
public async Task DownloadFileAsync(IWebProxy? webProxy, string url, string fileName, IProgress<double> progress, int timeout)
{
if (Utils.IsNullOrEmpty(url))
{
throw new ArgumentNullException(nameof(url));
}
if (Utils.IsNullOrEmpty(fileName))
{
throw new ArgumentNullException(nameof(fileName));
}
if (File.Exists(fileName))
{
File.Delete(fileName);
}
var downloadOpt = new DownloadConfiguration()
{
Timeout = timeout * 1000,
MaxTryAgainOnFailover = 2,
RequestConfiguration =
{
Timeout= timeout * 1000,
Proxy = webProxy
}
};
var progressPercentage = 0;
var hasValue = false;
await using var downloader = new Downloader.DownloadService(downloadOpt);
downloader.DownloadStarted += (sender, value) =>
{
progress?.Report(0);
};
downloader.DownloadProgressChanged += (sender, value) =>
{
hasValue = true;
var percent = (int)value.ProgressPercentage;// Convert.ToInt32((totalRead * 1d) / (total * 1d) * 100);
if (progressPercentage != percent && percent % 10 == 0)
{
progressPercentage = percent;
progress.Report(percent);
}
};
downloader.DownloadFileCompleted += (sender, value) =>
{
if (progress != null)
{
if (hasValue && value.Error == null)
{
progress.Report(101);
}
else if (value.Error != null)
{
throw value.Error;
}
}
};
using var cts = new CancellationTokenSource();
await downloader.DownloadFileTaskAsync(url, fileName, cts.Token);
downloadOpt = null;
}
}
}

View File

@@ -0,0 +1,61 @@
using System.Collections.Concurrent;
using System.Reflection;
namespace ServiceLib.Common;
public static class EmbedUtils
{
private static readonly string _tag = "EmbedUtils";
private static readonly ConcurrentDictionary<string, string> _dicEmbedCache = new();
/// <summary>
/// Get embedded text resources
/// </summary>
/// <param name="res"></param>
/// <returns></returns>
public static string GetEmbedText(string res)
{
if (_dicEmbedCache.TryGetValue(res, out var value))
{
return value;
}
var result = string.Empty;
try
{
var assembly = Assembly.GetExecutingAssembly();
using var stream = assembly.GetManifestResourceStream(res);
ArgumentNullException.ThrowIfNull(stream);
using StreamReader reader = new(stream);
result = reader.ReadToEnd();
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
_dicEmbedCache.TryAdd(res, result);
return result;
}
/// <summary>
/// Get local storage resources
/// </summary>
/// <returns></returns>
public static string? LoadResource(string? res)
{
try
{
if (File.Exists(res))
{
return File.ReadAllText(res);
}
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return null;
}
}

View File

@@ -0,0 +1,225 @@
using System.Formats.Tar;
using System.IO.Compression;
using System.Text;
namespace ServiceLib.Common
{
public static class FileManager
{
private static readonly string _tag = "FileManager";
public static bool ByteArrayToFile(string fileName, byte[] content)
{
try
{
File.WriteAllBytes(fileName, content);
return true;
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return false;
}
public static void DecompressFile(string fileName, byte[] content)
{
try
{
using var fs = File.Create(fileName);
using GZipStream input = new(new MemoryStream(content), CompressionMode.Decompress, false);
input.CopyTo(fs);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
public static void DecompressFile(string fileName, string toPath, string? toName)
{
try
{
FileInfo fileInfo = new(fileName);
using var originalFileStream = fileInfo.OpenRead();
using var decompressedFileStream = File.Create(toName != null ? Path.Combine(toPath, toName) : toPath);
using GZipStream decompressionStream = new(originalFileStream, CompressionMode.Decompress);
decompressionStream.CopyTo(decompressedFileStream);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
public static void DecompressTarFile(string fileName, string toPath)
{
try
{
using var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
using var gz = new GZipStream(fs, CompressionMode.Decompress, leaveOpen: true);
TarFile.ExtractToDirectory(gz, toPath, overwriteFiles: true);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
public static string NonExclusiveReadAllText(string path)
{
return NonExclusiveReadAllText(path, Encoding.Default);
}
private static string NonExclusiveReadAllText(string path, Encoding encoding)
{
try
{
using FileStream fs = new(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using StreamReader sr = new(fs, encoding);
return sr.ReadToEnd();
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
throw;
}
}
public static bool ZipExtractToFile(string fileName, string toPath, string ignoredName)
{
try
{
using var archive = ZipFile.OpenRead(fileName);
foreach (var entry in archive.Entries)
{
if (entry.Length == 0)
{
continue;
}
try
{
if (Utils.IsNotEmpty(ignoredName) && entry.Name.Contains(ignoredName))
{
continue;
}
entry.ExtractToFile(Path.Combine(toPath, entry.Name), true);
}
catch (IOException ex)
{
Logging.SaveLog(_tag, ex);
}
}
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
return false;
}
return true;
}
public static List<string>? GetFilesFromZip(string fileName)
{
if (!File.Exists(fileName))
{
return null;
}
try
{
using var archive = ZipFile.OpenRead(fileName);
return archive.Entries.Select(entry => entry.FullName).ToList();
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
return null;
}
}
public static bool CreateFromDirectory(string sourceDirectoryName, string destinationArchiveFileName)
{
try
{
if (File.Exists(destinationArchiveFileName))
{
File.Delete(destinationArchiveFileName);
}
ZipFile.CreateFromDirectory(sourceDirectoryName, destinationArchiveFileName, CompressionLevel.SmallestSize, true);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
return false;
}
return true;
}
public static void CopyDirectory(string sourceDir, string destinationDir, bool recursive, bool overwrite, string? ignoredName = null)
{
// Get information about the source directory
var dir = new DirectoryInfo(sourceDir);
// Check if the source directory exists
if (!dir.Exists)
throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}");
// Cache directories before we start copying
var dirs = dir.GetDirectories();
// Create the destination directory
Directory.CreateDirectory(destinationDir);
// Get the files in the source directory and copy to the destination directory
foreach (var file in dir.GetFiles())
{
if (Utils.IsNotEmpty(ignoredName) && file.Name.Contains(ignoredName))
{
continue;
}
if (file.Extension == file.Name)
{
continue;
}
var targetFilePath = Path.Combine(destinationDir, file.Name);
if (!overwrite && File.Exists(targetFilePath))
{
continue;
}
file.CopyTo(targetFilePath, overwrite);
}
// If recursive and copying subdirectories, recursively call this method
if (recursive)
{
foreach (var subDir in dirs)
{
var newDestinationDir = Path.Combine(destinationDir, subDir.Name);
CopyDirectory(subDir.FullName, newDestinationDir, true, overwrite, ignoredName);
}
}
}
public static void DeleteExpiredFiles(string sourceDir, DateTime dtLine)
{
try
{
var files = Directory.GetFiles(sourceDir, "*.*");
foreach (var filePath in files)
{
var file = new FileInfo(filePath);
if (file.CreationTime >= dtLine)
{
continue;
}
file.Delete();
}
}
catch
{
// ignored
}
}
}
}

View File

@@ -0,0 +1,191 @@
using System.Net.Http.Headers;
using System.Net.Mime;
using System.Text;
namespace ServiceLib.Common
{
/// <summary>
/// </summary>
public class HttpClientHelper
{
private static readonly Lazy<HttpClientHelper> _instance = new(() =>
{
SocketsHttpHandler handler = new() { UseCookies = false };
HttpClientHelper helper = new(new HttpClient(handler));
return helper;
});
public static HttpClientHelper Instance => _instance.Value;
private readonly HttpClient httpClient;
private HttpClientHelper(HttpClient httpClient) => this.httpClient = httpClient;
public async Task<string?> TryGetAsync(string url)
{
if (Utils.IsNullOrEmpty(url))
return null;
try
{
var response = await httpClient.GetAsync(url);
return await response.Content.ReadAsStringAsync();
}
catch
{
return null;
}
}
public async Task<string?> GetAsync(string url)
{
if (Utils.IsNullOrEmpty(url))
return null;
return await httpClient.GetStringAsync(url);
}
public async Task<string?> GetAsync(HttpClient client, string url, CancellationToken token = default)
{
if (Utils.IsNullOrEmpty(url))
return null;
return await client.GetStringAsync(url, token);
}
public async Task PutAsync(string url, Dictionary<string, string> headers)
{
var jsonContent = JsonUtils.Serialize(headers);
var content = new StringContent(jsonContent, Encoding.UTF8, MediaTypeNames.Application.Json);
var result = await httpClient.PutAsync(url, content);
}
public async Task PatchAsync(string url, Dictionary<string, string> headers)
{
var myContent = JsonUtils.Serialize(headers);
var buffer = System.Text.Encoding.UTF8.GetBytes(myContent);
var byteContent = new ByteArrayContent(buffer);
byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
await httpClient.PatchAsync(url, byteContent);
}
public async Task DeleteAsync(string url)
{
await httpClient.DeleteAsync(url);
}
public static async Task DownloadFileAsync(HttpClient client, string url, string fileName, IProgress<double>? progress, CancellationToken token = default)
{
ArgumentNullException.ThrowIfNull(url);
ArgumentNullException.ThrowIfNull(fileName);
if (File.Exists(fileName))
File.Delete(fileName);
using var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);
if (!response.IsSuccessStatusCode)
throw new Exception(response.StatusCode.ToString());
var total = response.Content.Headers.ContentLength ?? -1L;
var canReportProgress = total != -1 && progress != null;
await using var stream = await response.Content.ReadAsStreamAsync(token);
await using var file = File.Create(fileName);
var totalRead = 0L;
var buffer = new byte[1024 * 1024];
var progressPercentage = 0;
while (true)
{
token.ThrowIfCancellationRequested();
var read = await stream.ReadAsync(buffer, token);
totalRead += read;
if (read == 0)
break;
await file.WriteAsync(buffer.AsMemory(0, read), token);
if (canReportProgress)
{
var percent = (int)(100.0 * totalRead / total);
//if (progressPercentage != percent && percent % 10 == 0)
{
progressPercentage = percent;
progress?.Report(percent);
}
}
}
if (canReportProgress)
{
progress?.Report(101);
}
}
public async Task DownloadDataAsync4Speed(HttpClient client, string url, IProgress<string> progress, CancellationToken token = default)
{
if (Utils.IsNullOrEmpty(url))
{
throw new ArgumentNullException(nameof(url));
}
var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);
if (!response.IsSuccessStatusCode)
{
throw new Exception(response.StatusCode.ToString());
}
//var total = response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : -1L;
//var canReportProgress = total != -1 && progress != null;
await using var stream = await response.Content.ReadAsStreamAsync(token);
var totalRead = 0L;
var buffer = new byte[1024 * 64];
var isMoreToRead = true;
var progressSpeed = string.Empty;
var totalDatetime = DateTime.Now;
var totalSecond = 0;
do
{
if (token.IsCancellationRequested)
{
if (totalRead > 0)
{
return;
}
else
{
token.ThrowIfCancellationRequested();
}
}
var read = await stream.ReadAsync(buffer, token);
if (read == 0)
{
isMoreToRead = false;
}
else
{
var data = new byte[read];
buffer.ToList().CopyTo(0, data, 0, read);
totalRead += read;
var ts = (DateTime.Now - totalDatetime);
if (progress != null && ts.Seconds > totalSecond)
{
totalSecond = ts.Seconds;
var speed = (totalRead * 1d / ts.TotalMilliseconds / 1000).ToString("#0.0");
if (progressSpeed != speed)
{
progressSpeed = speed;
progress.Report(speed);
}
}
}
} while (isMoreToRead);
}
}
}

View File

@@ -1,15 +1,14 @@
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace v2rayN
namespace ServiceLib.Common
{
/*
* See:
* http://stackoverflow.com/questions/6266820/working-example-of-createjobobject-setinformationjobobject-pinvoke-in-net
*/
public class Job : IDisposable
public sealed class Job : IDisposable
{
private IntPtr handle = IntPtr.Zero;
@@ -17,12 +16,12 @@ namespace v2rayN
{
handle = CreateJobObject(IntPtr.Zero, null);
IntPtr extendedInfoPtr = IntPtr.Zero;
JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION
JOBOBJECT_BASIC_LIMIT_INFORMATION info = new()
{
LimitFlags = 0x2000
};
JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new()
{
BasicLimitInformation = info
};
@@ -34,7 +33,7 @@ namespace v2rayN
Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);
if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr,
(uint) length))
(uint)length))
throw new Exception(string.Format("Unable to set information. Error: {0}",
Marshal.GetLastWin32Error()));
}
@@ -53,7 +52,7 @@ namespace v2rayN
if (!succ)
{
Utils.SaveLog("Failed to call AssignProcessToJobObject! GetLastError=" + Marshal.GetLastWin32Error());
Logging.SaveLog("Failed to call AssignProcessToJobObject! GetLastError=" + Marshal.GetLastWin32Error());
}
return succ;
@@ -74,9 +73,10 @@ namespace v2rayN
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
private void Dispose(bool disposing)
{
if (disposed) return;
if (disposed)
return;
disposed = true;
if (disposing)
@@ -96,12 +96,12 @@ namespace v2rayN
Dispose(false);
}
#endregion
#endregion IDisposable
#region Interop
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr CreateJobObject(IntPtr a, string lpName);
private static extern IntPtr CreateJobObject(IntPtr a, string? lpName);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, UInt32 cbJobObjectInfoLength);
@@ -113,13 +113,13 @@ namespace v2rayN
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr hObject);
#endregion
#endregion Interop
}
#region Helper classes
[StructLayout(LayoutKind.Sequential)]
struct IO_COUNTERS
internal struct IO_COUNTERS
{
public UInt64 ReadOperationCount;
public UInt64 WriteOperationCount;
@@ -129,9 +129,8 @@ namespace v2rayN
public UInt64 OtherTransferCount;
}
[StructLayout(LayoutKind.Sequential)]
struct JOBOBJECT_BASIC_LIMIT_INFORMATION
internal struct JOBOBJECT_BASIC_LIMIT_INFORMATION
{
public Int64 PerProcessUserTimeLimit;
public Int64 PerJobUserTimeLimit;
@@ -153,7 +152,7 @@ namespace v2rayN
}
[StructLayout(LayoutKind.Sequential)]
struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
internal struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
public IO_COUNTERS IoInfo;
@@ -174,5 +173,5 @@ namespace v2rayN
GroupInformation = 11
}
#endregion
#endregion Helper classes
}

View File

@@ -0,0 +1,131 @@
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
namespace ServiceLib.Common
{
public class JsonUtils
{
private static readonly string _tag = "JsonUtils";
/// <summary>
/// DeepCopy
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
public static T DeepCopy<T>(T obj)
{
return Deserialize<T>(Serialize(obj, false))!;
}
/// <summary>
/// Deserialize to object
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="strJson"></param>
/// <returns></returns>
public static T? Deserialize<T>(string? strJson)
{
try
{
if (string.IsNullOrWhiteSpace(strJson))
{
return default;
}
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
return JsonSerializer.Deserialize<T>(strJson, options);
}
catch
{
return default;
}
}
/// <summary>
/// parse
/// </summary>
/// <param name="strJson"></param>
/// <returns></returns>
public static JsonNode? ParseJson(string strJson)
{
try
{
if (string.IsNullOrWhiteSpace(strJson))
{
return null;
}
return JsonNode.Parse(strJson);
}
catch
{
//SaveLog(ex.Message, ex);
return null;
}
}
/// <summary>
/// Serialize Object to Json string
/// </summary>
/// <param name="obj"></param>
/// <param name="indented"></param>
/// <param name="nullValue"></param>
/// <returns></returns>
public static string Serialize(object? obj, bool indented = true, bool nullValue = false)
{
var result = string.Empty;
try
{
if (obj == null)
{
return result;
}
var options = new JsonSerializerOptions
{
WriteIndented = indented,
DefaultIgnoreCondition = nullValue ? JsonIgnoreCondition.Never : JsonIgnoreCondition.WhenWritingNull
};
result = JsonSerializer.Serialize(obj, options);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return result;
}
/// <summary>
/// Serialize Object to Json string
/// </summary>
/// <param name="obj"></param>
/// <param name="options"></param>
/// <returns></returns>
public static string Serialize(object? obj, JsonSerializerOptions options)
{
var result = string.Empty;
try
{
if (obj == null)
{
return result;
}
result = JsonSerializer.Serialize(obj, options);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return result;
}
/// <summary>
/// SerializeToNode
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static JsonNode? SerializeToNode(object? obj) => JsonSerializer.SerializeToNode(obj);
}
}

View File

@@ -0,0 +1,50 @@
using NLog;
using NLog.Config;
using NLog.Targets;
namespace ServiceLib.Common
{
public class Logging
{
public static void Setup()
{
LoggingConfiguration config = new();
FileTarget fileTarget = new();
config.AddTarget("file", fileTarget);
fileTarget.Layout = "${longdate}-${level:uppercase=true} ${message}";
fileTarget.FileName = Utils.GetLogPath("${shortdate}.txt");
config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, fileTarget));
LogManager.Configuration = config;
}
public static void LoggingEnabled(bool enable)
{
if (!enable)
{
LogManager.SuspendLogging();
}
}
public static void SaveLog(string strContent)
{
if (!LogManager.IsLoggingEnabled())
return;
LogManager.GetLogger("Log1").Info(strContent);
}
public static void SaveLog(string strTitle, Exception ex)
{
if (!LogManager.IsLoggingEnabled())
return;
var logger = LogManager.GetLogger("Log2");
logger.Debug($"{strTitle},{ex.Message}");
logger.Debug(ex.StackTrace);
if (ex?.InnerException != null)
{
logger.Error(ex.InnerException);
}
}
}
}

View File

@@ -0,0 +1,150 @@
using System.Diagnostics;
namespace ServiceLib.Common;
public static class ProcUtils
{
private static readonly string _tag = "ProcUtils";
public static void ProcessStart(string? fileName, string arguments = "")
{
ProcessStart(fileName, arguments, null);
}
public static int? ProcessStart(string? fileName, string arguments, string? dir)
{
if (fileName.IsNullOrEmpty())
{
return null;
}
try
{
if (fileName.Contains(' '))
fileName = fileName.AppendQuotes();
if (arguments.Contains(' '))
arguments = arguments.AppendQuotes();
Process proc = new()
{
StartInfo = new ProcessStartInfo
{
UseShellExecute = true,
FileName = fileName,
Arguments = arguments,
WorkingDirectory = dir ?? string.Empty
}
};
proc.Start();
return dir is null ? null : proc.Id;
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return null;
}
public static void RebootAsAdmin(bool blAdmin = true)
{
try
{
ProcessStartInfo startInfo = new()
{
UseShellExecute = true,
Arguments = Global.RebootAs,
WorkingDirectory = Utils.StartupPath(),
FileName = Utils.GetExePath().AppendQuotes(),
Verb = blAdmin ? "runas" : null,
};
Process.Start(startInfo);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
public static async Task ProcessKill(int pid)
{
try
{
await ProcessKill(Process.GetProcessById(pid), false);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
public static async Task ProcessKill(Process? proc, bool review)
{
if (proc is null)
{
return;
}
GetProcessKeyInfo(proc, review, out var procId, out var fileName, out var processName);
try
{ proc?.Kill(true); }
catch (Exception ex) { Logging.SaveLog(_tag, ex); }
try
{ proc?.Kill(); }
catch (Exception ex) { Logging.SaveLog(_tag, ex); }
try
{ proc?.Close(); }
catch (Exception ex) { Logging.SaveLog(_tag, ex); }
try
{ proc?.Dispose(); }
catch (Exception ex) { Logging.SaveLog(_tag, ex); }
await Task.Delay(300);
await ProcessKillByKeyInfo(review, procId, fileName, processName);
}
private static void GetProcessKeyInfo(Process? proc, bool review, out int? procId, out string? fileName, out string? processName)
{
procId = null;
fileName = null;
processName = null;
if (!review)
return;
try
{
procId = proc?.Id;
fileName = proc?.MainModule?.FileName;
processName = proc?.ProcessName;
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
private static async Task ProcessKillByKeyInfo(bool review, int? procId, string? fileName, string? processName)
{
if (review && procId != null && fileName != null)
{
try
{
var lstProc = Process.GetProcessesByName(processName);
foreach (var proc2 in lstProc)
{
if (proc2.Id == procId)
{
Logging.SaveLog($"{_tag}, KillProcess not completing the job, procId");
await ProcessKill(proc2, false);
}
if (proc2.MainModule != null && proc2.MainModule?.FileName == fileName)
{
Logging.SaveLog($"{_tag}, KillProcess not completing the job, fileName");
}
}
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
}
}

View File

@@ -0,0 +1,90 @@
using QRCoder;
using SkiaSharp;
using ZXing.SkiaSharp;
namespace ServiceLib.Common
{
public class QRCodeHelper
{
public static byte[]? GenQRCode(string? url)
{
using QRCodeGenerator qrGenerator = new();
using var qrCodeData = qrGenerator.CreateQrCode(url ?? string.Empty, QRCodeGenerator.ECCLevel.Q);
using PngByteQRCode qrCode = new(qrCodeData);
return qrCode.GetGraphic(20);
}
public static string? ParseBarcode(string? fileName)
{
if (fileName == null || !File.Exists(fileName))
{
return null;
}
try
{
var image = SKImage.FromEncodedData(fileName);
var bitmap = SKBitmap.FromImage(image);
return ReaderBarcode(bitmap);
}
catch
{
// ignored
}
return null;
}
public static string? ParseBarcode(byte[]? bytes)
{
try
{
var bitmap = SKBitmap.Decode(bytes);
//using var stream = new FileStream("test2.png", FileMode.Create, FileAccess.Write);
//using var image = SKImage.FromBitmap(bitmap);
//using var encodedImage = image.Encode();
//encodedImage.SaveTo(stream);
return ReaderBarcode(bitmap);
}
catch
{
// ignored
}
return null;
}
private static string? ReaderBarcode(SKBitmap? bitmap)
{
var reader = new BarcodeReader();
var result = reader.Decode(bitmap);
if (result != null && Utils.IsNotEmpty(result.Text))
{
return result.Text;
}
//FlipBitmap
var result2 = reader.Decode(FlipBitmap(bitmap));
return result2?.Text;
}
private static SKBitmap FlipBitmap(SKBitmap bmp)
{
// Create a bitmap (to return)
var flipped = new SKBitmap(bmp.Width, bmp.Height, bmp.Info.ColorType, bmp.Info.AlphaType);
// Create a canvas to draw into the bitmap
using var canvas = new SKCanvas(flipped);
// Set a transform matrix which moves the bitmap to the right,
// and then "scales" it by -1, which just flips the pixels
// horizontally
canvas.Translate(bmp.Width, 0);
canvas.Scale(-1, 1);
canvas.DrawBitmap(bmp, 0, 0);
return flipped;
}
}
}

View File

@@ -0,0 +1,187 @@
namespace ServiceLib.Common
{
public class SemanticVersion
{
private int major;
private int minor;
private int patch;
private string version;
public SemanticVersion(int major, int minor, int patch)
{
this.major = major;
this.minor = minor;
this.patch = patch;
this.version = $"{major}.{minor}.{patch}";
}
public SemanticVersion(string? version)
{
try
{
if (version.IsNullOrEmpty())
{
this.major = 0;
this.minor = 0;
this.patch = 0;
return;
}
this.version = version.RemovePrefix('v');
var parts = this.version.Split('.');
if (parts.Length == 2)
{
this.major = int.Parse(parts.First());
this.minor = int.Parse(parts.Last());
this.patch = 0;
}
else if (parts.Length is 3 or 4)
{
this.major = int.Parse(parts[0]);
this.minor = int.Parse(parts[1]);
this.patch = int.Parse(parts[2]);
}
else
{
throw new ArgumentException("Invalid version string");
}
}
catch
{
this.major = 0;
this.minor = 0;
this.patch = 0;
}
}
public override bool Equals(object? obj)
{
if (obj is SemanticVersion other)
{
return this.major == other.major && this.minor == other.minor && this.patch == other.patch;
}
else
{
return false;
}
}
public override int GetHashCode()
{
return this.major.GetHashCode() ^ this.minor.GetHashCode() ^ this.patch.GetHashCode();
}
/// <summary>
/// Use ToVersionString(string? prefix) instead if possible.
/// </summary>
/// <returns>major.minor.patch</returns>
public override string ToString()
{
return this.version;
}
public string ToVersionString(string? prefix = null)
{
if (prefix == null)
{
return this.version;
}
else
{
return $"{prefix}{this.version}";
}
}
public static bool operator ==(SemanticVersion v1, SemanticVersion v2)
{ return v1.Equals(v2); }
public static bool operator !=(SemanticVersion v1, SemanticVersion v2)
{ return !v1.Equals(v2); }
public static bool operator >=(SemanticVersion v1, SemanticVersion v2)
{ return v1.GreaterEquals(v2); }
public static bool operator <=(SemanticVersion v1, SemanticVersion v2)
{ return v1.LessEquals(v2); }
#region Private
private bool GreaterEquals(SemanticVersion other)
{
if (this.major < other.major)
{
return false;
}
else if (this.major > other.major)
{
return true;
}
else
{
if (this.minor < other.minor)
{
return false;
}
else if (this.minor > other.minor)
{
return true;
}
else
{
if (this.patch < other.patch)
{
return false;
}
else if (this.patch > other.patch)
{
return true;
}
else
{
return true;
}
}
}
}
private bool LessEquals(SemanticVersion other)
{
if (this.major < other.major)
{
return true;
}
else if (this.major > other.major)
{
return false;
}
else
{
if (this.minor < other.minor)
{
return true;
}
else if (this.minor > other.minor)
{
return false;
}
else
{
if (this.patch < other.patch)
{
return true;
}
else if (this.patch > other.patch)
{
return false;
}
else
{
return true;
}
}
}
}
#endregion Private
}
}

View File

@@ -0,0 +1,91 @@
using System.Collections;
using SQLite;
namespace ServiceLib.Common
{
public sealed class SQLiteHelper
{
private static readonly Lazy<SQLiteHelper> _instance = new(() => new());
public static SQLiteHelper Instance => _instance.Value;
private string _connstr;
private SQLiteConnection _db;
private SQLiteAsyncConnection _dbAsync;
private readonly string _configDB = "guiNDB.db";
public SQLiteHelper()
{
_connstr = Utils.GetConfigPath(_configDB);
_db = new SQLiteConnection(_connstr, false);
_dbAsync = new SQLiteAsyncConnection(_connstr, false);
}
public CreateTableResult CreateTable<T>()
{
return _db.CreateTable<T>();
}
public async Task<int> InsertAllAsync(IEnumerable models)
{
return await _dbAsync.InsertAllAsync(models);
}
public async Task<int> InsertAsync(object model)
{
return await _dbAsync.InsertAsync(model);
}
public async Task<int> ReplaceAsync(object model)
{
return await _dbAsync.InsertOrReplaceAsync(model);
}
public async Task<int> UpdateAsync(object model)
{
return await _dbAsync.UpdateAsync(model);
}
public async Task<int> UpdateAllAsync(IEnumerable models)
{
return await _dbAsync.UpdateAllAsync(models);
}
public async Task<int> DeleteAsync(object model)
{
return await _dbAsync.DeleteAsync(model);
}
public async Task<int> DeleteAllAsync<T>()
{
return await _dbAsync.DeleteAllAsync<T>();
}
public async Task<int> ExecuteAsync(string sql)
{
return await _dbAsync.ExecuteAsync(sql);
}
public async Task<List<T>> QueryAsync<T>(string sql) where T : new()
{
return await _dbAsync.QueryAsync<T>(sql);
}
public AsyncTableQuery<T> TableAsync<T>() where T : new()
{
return _dbAsync.Table<T>();
}
public async Task DisposeDbConnectionAsync()
{
await Task.Factory.StartNew(() =>
{
_db?.Close();
_db?.Dispose();
_db = null;
_dbAsync?.GetConnection()?.Close();
_dbAsync?.GetConnection()?.Dispose();
_dbAsync = null;
});
}
}
}

View File

@@ -0,0 +1,74 @@
using System.Diagnostics.CodeAnalysis;
namespace ServiceLib.Common
{
public static class StringEx
{
public static bool IsNullOrEmpty([NotNullWhen(false)] this string? value)
{
return string.IsNullOrEmpty(value);
}
public static bool IsNullOrWhiteSpace([NotNullWhen(false)] this string? value)
{
return string.IsNullOrWhiteSpace(value);
}
public static bool IsNotEmpty([NotNullWhen(false)] this string? value)
{
return !string.IsNullOrEmpty(value);
}
public static bool BeginWithAny(this string s, IEnumerable<char> chars)
{
if (s.IsNullOrEmpty())
return false;
return chars.Contains(s.First());
}
private static bool IsWhiteSpace(this string value)
{
return value.All(char.IsWhiteSpace);
}
public static IEnumerable<string> NonWhiteSpaceLines(this TextReader reader)
{
while (reader.ReadLine() is { } line)
{
if (line.IsWhiteSpace())
continue;
yield return line;
}
}
public static string TrimEx(this string? value)
{
return value == null ? string.Empty : value.Trim();
}
public static string RemovePrefix(this string value, char prefix)
{
return value.StartsWith(prefix) ? value[1..] : value;
}
public static string RemovePrefix(this string value, string prefix)
{
return value.StartsWith(prefix) ? value[prefix.Length..] : value;
}
public static string UpperFirstChar(this string value)
{
if (string.IsNullOrEmpty(value))
{
return string.Empty;
}
return char.ToUpper(value.First()) + value[1..];
}
public static string AppendQuotes(this string value)
{
return string.IsNullOrEmpty(value) ? string.Empty : $"\"{value}\"";
}
}
}

View File

@@ -0,0 +1,866 @@
using System.Collections.Specialized;
using System.Diagnostics;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Principal;
using System.Text;
using CliWrap;
using CliWrap.Buffered;
namespace ServiceLib.Common
{
public class Utils
{
private static readonly string _tag = "Utils";
#region
/// <summary>
/// 转逗号分隔的字符串
/// </summary>
/// <param name="lst"></param>
/// <param name="wrap"></param>
/// <returns></returns>
public static string List2String(List<string>? lst, bool wrap = false)
{
try
{
if (lst == null)
{
return string.Empty;
}
if (wrap)
{
return string.Join("," + Environment.NewLine, lst);
}
else
{
return string.Join(",", lst);
}
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return string.Empty;
}
/// <summary>
/// 逗号分隔的字符串
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static List<string>? String2List(string? str)
{
try
{
if (str == null)
{
return null;
}
str = str.Replace(Environment.NewLine, "");
return new List<string>(str.Split(',', StringSplitOptions.RemoveEmptyEntries));
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return null;
}
/// <summary>
/// 逗号分隔的字符串,先排序后转List
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static List<string>? String2ListSorted(string str)
{
try
{
str = str.Replace(Environment.NewLine, "");
List<string> list = new(str.Split(',', StringSplitOptions.RemoveEmptyEntries));
list.Sort();
return list;
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return null;
}
/// <summary>
/// Base64编码
/// </summary>
/// <param name="plainText"></param>
/// <returns></returns>
public static string Base64Encode(string plainText)
{
try
{
var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
return Convert.ToBase64String(plainTextBytes);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return string.Empty;
}
/// <summary>
/// Base64解码
/// </summary>
/// <param name="plainText"></param>
/// <returns></returns>
public static string Base64Decode(string? plainText)
{
try
{
if (plainText.IsNullOrEmpty())
return "";
plainText = plainText.Trim()
.Replace(Environment.NewLine, "")
.Replace("\n", "")
.Replace("\r", "")
.Replace('_', '/')
.Replace('-', '+')
.Replace(" ", "");
if (plainText.Length % 4 > 0)
{
plainText = plainText.PadRight(plainText.Length + 4 - (plainText.Length % 4), '=');
}
var data = Convert.FromBase64String(plainText);
return Encoding.UTF8.GetString(data);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return string.Empty;
}
public static int ToInt(object? obj)
{
try
{
return Convert.ToInt32(obj ?? string.Empty);
}
catch
{
return 0;
}
}
public static bool ToBool(object obj)
{
try
{
return Convert.ToBoolean(obj);
}
catch
{
return false;
}
}
public static string ToString(object? obj)
{
try
{
return obj?.ToString() ?? string.Empty;
}
catch
{
return string.Empty;
}
}
private static void ToHumanReadable(long amount, out double result, out string unit)
{
var factor = 1024u;
//long KBs = amount / factor;
var KBs = amount;
if (KBs > 0)
{
// multi KB
var MBs = KBs / factor;
if (MBs > 0)
{
// multi MB
var GBs = MBs / factor;
if (GBs > 0)
{
// multi GB
var TBs = GBs / factor;
if (TBs > 0)
{
result = TBs + ((GBs % factor) / (factor + 0.0));
unit = "TB";
return;
}
result = GBs + ((MBs % factor) / (factor + 0.0));
unit = "GB";
return;
}
result = MBs + ((KBs % factor) / (factor + 0.0));
unit = "MB";
return;
}
result = KBs + ((amount % factor) / (factor + 0.0));
unit = "KB";
return;
}
else
{
result = amount;
unit = "B";
}
}
public static string HumanFy(long amount)
{
ToHumanReadable(amount, out var result, out var unit);
return $"{result:f1} {unit}";
}
public static string UrlEncode(string url)
{
return Uri.EscapeDataString(url);
}
public static string UrlDecode(string url)
{
return Uri.UnescapeDataString(url);
}
public static NameValueCollection ParseQueryString(string query)
{
var result = new NameValueCollection(StringComparer.OrdinalIgnoreCase);
if (IsNullOrEmpty(query))
{
return result;
}
var parts = query[1..].Split('&', StringSplitOptions.RemoveEmptyEntries);
foreach (var part in parts)
{
var keyValue = part.Split('=');
if (keyValue.Length != 2)
{
continue;
}
var key = Uri.UnescapeDataString(keyValue.First());
var val = Uri.UnescapeDataString(keyValue.Last());
if (result[key] is null)
{
result.Add(key, val);
}
}
return result;
}
public static string GetMd5(string str)
{
var byteOld = Encoding.UTF8.GetBytes(str);
var byteNew = MD5.HashData(byteOld);
StringBuilder sb = new(32);
foreach (var b in byteNew)
{
sb.Append(b.ToString("x2"));
}
return sb.ToString();
}
/// <summary>
/// idn to idc
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public static string GetPunycode(string url)
{
if (Utils.IsNullOrEmpty(url))
{
return url;
}
try
{
Uri uri = new(url);
if (uri.Host == uri.IdnHost || uri.Host == $"[{uri.IdnHost}]")
{
return url;
}
else
{
return url.Replace(uri.Host, uri.IdnHost);
}
}
catch
{
return url;
}
}
public static bool IsBase64String(string? plainText)
{
if (plainText.IsNullOrEmpty())
return false;
var buffer = new Span<byte>(new byte[plainText.Length]);
return Convert.TryFromBase64String(plainText, buffer, out var _);
}
public static string Convert2Comma(string text)
{
if (IsNullOrEmpty(text))
{
return text;
}
return text.Replace("", ",").Replace(Environment.NewLine, ",");
}
#endregion
#region
/// <summary>
/// 判断输入的是否是数字
/// </summary>
/// <param name="oText"></param>
/// <returns></returns>
public static bool IsNumeric(string oText)
{
return oText.All(char.IsNumber);
}
public static bool IsNullOrEmpty(string? text)
{
if (string.IsNullOrWhiteSpace(text))
{
return true;
}
return text == "null";
}
public static bool IsNotEmpty(string? text)
{
return !string.IsNullOrEmpty(text);
}
/// <summary>
/// 验证Domain地址是否合法
/// </summary>
/// <param name="domain"></param>
public static bool IsDomain(string? domain)
{
if (IsNullOrEmpty(domain))
{
return false;
}
return Uri.CheckHostName(domain) == UriHostNameType.Dns;
}
public static bool IsIpv6(string ip)
{
if (IPAddress.TryParse(ip, out var address))
{
return address.AddressFamily switch
{
AddressFamily.InterNetwork => false,
AddressFamily.InterNetworkV6 => true,
_ => false,
};
}
return false;
}
public static Uri? TryUri(string url)
{
try
{
return new Uri(url);
}
catch (UriFormatException)
{
return null;
}
}
public static bool IsPrivateNetwork(string ip)
{
if (IPAddress.TryParse(ip, out var address))
{
var ipBytes = address.GetAddressBytes();
if (ipBytes[0] == 10)
return true;
if (ipBytes[0] == 172 && ipBytes[1] >= 16 && ipBytes[1] <= 31)
return true;
if (ipBytes[0] == 192 && ipBytes[1] == 168)
return true;
}
return false;
}
#endregion
#region
private static bool PortInUse(int port)
{
try
{
var ipProperties = IPGlobalProperties.GetIPGlobalProperties();
var ipEndPoints = ipProperties.GetActiveTcpListeners();
//var lstIpEndPoints = new List<IPEndPoint>(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners());
return ipEndPoints.Any(endPoint => endPoint.Port == port);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return false;
}
public static int GetFreePort(int defaultPort = 9090)
{
try
{
if (!Utils.PortInUse(defaultPort))
{
return defaultPort;
}
TcpListener l = new(IPAddress.Loopback, 0);
l.Start();
var port = ((IPEndPoint)l.LocalEndpoint).Port;
l.Stop();
return port;
}
catch
{
}
return 59090;
}
#endregion
#region
public static bool UpgradeAppExists(out string upgradeFileName)
{
upgradeFileName = Path.Combine(GetBaseDirectory(), GetExeName("AmazTool"));
return File.Exists(upgradeFileName);
}
/// <summary>
/// 取得版本
/// </summary>
/// <returns></returns>
public static string GetVersion(bool blFull = true)
{
try
{
return blFull
? $"{Global.AppName} - V{GetVersionInfo()} - {RuntimeInformation.ProcessArchitecture}"
: $"{Global.AppName}/{GetVersionInfo()}";
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return Global.AppName;
}
public static string GetVersionInfo()
{
try
{
return Assembly.GetExecutingAssembly()?.GetName()?.Version?.ToString(3) ?? "0.0";
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
return "0.0";
}
}
public static string GetRuntimeInfo()
{
return $"{Utils.GetVersion()} | {Utils.StartupPath()} | {Utils.GetExePath()} | {Environment.OSVersion}";
}
/// <summary>
/// 取得GUID
/// </summary>
/// <returns></returns>
public static string GetGuid(bool full = true)
{
try
{
if (full)
{
return Guid.NewGuid().ToString("D");
}
else
{
return BitConverter.ToInt64(Guid.NewGuid().ToByteArray(), 0).ToString();
}
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return string.Empty;
}
public static bool IsGuidByParse(string strSrc)
{
return Guid.TryParse(strSrc, out _);
}
public static Dictionary<string, string> GetSystemHosts()
{
var systemHosts = new Dictionary<string, string>();
var hostFile = @"C:\Windows\System32\drivers\etc\hosts";
try
{
if (File.Exists(hostFile))
{
var hosts = File.ReadAllText(hostFile).Replace("\r", "");
var hostsList = hosts.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var host in hostsList)
{
if (host.StartsWith("#"))
continue;
var hostItem = host.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
if (hostItem.Length != 2)
continue;
systemHosts.Add(hostItem.Last(), hostItem.First());
}
}
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return systemHosts;
}
public static async Task<string?> GetCliWrapOutput(string filePath, string? arg)
{
return await GetCliWrapOutput(filePath, arg != null ? new List<string>() { arg } : null);
}
public static async Task<string?> GetCliWrapOutput(string filePath, IEnumerable<string>? args)
{
try
{
var cmd = Cli.Wrap(filePath);
if (args != null)
{
if (args.Count() == 1)
{
cmd = cmd.WithArguments(args.First());
}
else
{
cmd = cmd.WithArguments(args);
}
}
var result = await cmd.ExecuteBufferedAsync();
if (result.IsSuccess)
{
return result.StandardOutput.ToString();
}
Logging.SaveLog(result.ToString() ?? "");
}
catch (Exception ex)
{
Logging.SaveLog("GetCliWrapOutput", ex);
}
return null;
}
#endregion
#region TempPath
public static bool HasWritePermission()
{
try
{
//When this file exists, it is equivalent to having no permission to read and write
if (File.Exists(Path.Combine(GetBaseDirectory(), "NotStoreConfigHere.txt")))
{
return false;
}
var tempPath = Path.Combine(GetBaseDirectory(), "guiTemps");
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(tempPath);
}
var fileName = Path.Combine(tempPath, GetGuid());
File.Create(fileName).Close();
File.Delete(fileName);
}
catch (Exception)
{
return false;
}
return true;
}
public static string GetPath(string fileName)
{
var startupPath = StartupPath();
if (IsNullOrEmpty(fileName))
{
return startupPath;
}
return Path.Combine(startupPath, fileName);
}
public static string GetBaseDirectory(string fileName = "")
{
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
}
public static string GetExePath()
{
return Environment.ProcessPath ?? Process.GetCurrentProcess().MainModule?.FileName ?? string.Empty;
}
public static string StartupPath()
{
if (Environment.GetEnvironmentVariable(Global.LocalAppData) == "1")
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "v2rayN");
}
return GetBaseDirectory();
}
public static string GetTempPath(string filename = "")
{
var tempPath = Path.Combine(StartupPath(), "guiTemps");
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(tempPath);
}
if (IsNullOrEmpty(filename))
{
return tempPath;
}
else
{
return Path.Combine(tempPath, filename);
}
}
public static string GetBackupPath(string filename)
{
var tempPath = Path.Combine(StartupPath(), "guiBackups");
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(tempPath);
}
return Path.Combine(tempPath, filename);
}
public static string GetConfigPath(string filename = "")
{
var tempPath = Path.Combine(StartupPath(), "guiConfigs");
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(tempPath);
}
if (Utils.IsNullOrEmpty(filename))
{
return tempPath;
}
else
{
return Path.Combine(tempPath, filename);
}
}
public static string GetBinPath(string filename, string? coreType = null)
{
var tempPath = Path.Combine(StartupPath(), "bin");
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(tempPath);
}
if (coreType != null)
{
tempPath = Path.Combine(tempPath, coreType.ToLower().ToString());
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(tempPath);
}
}
if (IsNullOrEmpty(filename))
{
return tempPath;
}
else
{
return Path.Combine(tempPath, filename);
}
}
public static string GetLogPath(string filename = "")
{
var tempPath = Path.Combine(StartupPath(), "guiLogs");
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(tempPath);
}
if (Utils.IsNullOrEmpty(filename))
{
return tempPath;
}
else
{
return Path.Combine(tempPath, filename);
}
}
public static string GetFontsPath(string filename = "")
{
var tempPath = Path.Combine(StartupPath(), "guiFonts");
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(tempPath);
}
if (Utils.IsNullOrEmpty(filename))
{
return tempPath;
}
else
{
return Path.Combine(tempPath, filename);
}
}
#endregion TempPath
#region Platform
public static bool IsWindows() => RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
public static bool IsLinux() => RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
public static bool IsOSX() => RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
public static bool IsNonWindows() => !RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
public static string GetExeName(string name)
{
return IsWindows() ? $"{name}.exe" : name;
}
public static bool IsAdministrator()
{
if (IsWindows())
{
return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
}
return false;
//else
//{
// var id = GetLinuxUserId().Result ?? "1000";
// if (int.TryParse(id, out var userId))
// {
// return userId == 0;
// }
// else
// {
// return false;
// }
//}
}
private static async Task<string?> GetLinuxUserId()
{
var arg = new List<string>() { "-c", "id -u" };
return await GetCliWrapOutput("/bin/bash", arg);
}
public static async Task<string?> SetLinuxChmod(string? fileName)
{
if (fileName.IsNullOrEmpty())
return null;
if (fileName.Contains(' '))
fileName = fileName.AppendQuotes();
//File.SetUnixFileMode(fileName, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute);
var arg = new List<string>() { "-c", $"chmod +x {fileName}" };
return await GetCliWrapOutput("/bin/bash", arg);
}
public static async Task<string?> GetLinuxFontFamily(string lang)
{
// var arg = new List<string>() { "-c", $"fc-list :lang={lang} family" };
var arg = new List<string>() { "-c", $"fc-list : family" };
return await GetCliWrapOutput("/bin/bash", arg);
}
public static string? GetHomePath()
{
return IsWindows()
? Environment.ExpandEnvironmentVariables("%HOMEDRIVE%%HOMEPATH%")
: Environment.GetEnvironmentVariable("HOME");
}
public static async Task<string?> GetListNetworkServices()
{
var arg = new List<string>() { "-c", $"networksetup -listallnetworkservices" };
return await GetCliWrapOutput("/bin/bash", arg);
}
#endregion Platform
}
}

View File

@@ -0,0 +1,74 @@
using System.Security.Cryptography;
using System.Text;
using Microsoft.Win32;
namespace ServiceLib.Common
{
internal static class WindowsUtils
{
private static readonly string _tag = "WindowsUtils";
public static string? RegReadValue(string path, string name, string def)
{
RegistryKey? regKey = null;
try
{
regKey = Registry.CurrentUser.OpenSubKey(path, false);
var value = regKey?.GetValue(name) as string;
return Utils.IsNullOrEmpty(value) ? def : value;
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
finally
{
regKey?.Close();
}
return def;
}
public static void RegWriteValue(string path, string name, object value)
{
RegistryKey? regKey = null;
try
{
regKey = Registry.CurrentUser.CreateSubKey(path);
if (Utils.IsNullOrEmpty(value.ToString()))
{
regKey?.DeleteValue(name, false);
}
else
{
regKey?.SetValue(name, value);
}
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
finally
{
regKey?.Close();
}
}
public static async Task RemoveTunDevice()
{
try
{
var sum = MD5.HashData(Encoding.UTF8.GetBytes("wintunsingbox_tun"));
var guid = new Guid(sum);
var pnpUtilPath = @"C:\Windows\System32\pnputil.exe";
var arg = $$""" /remove-device "SWD\Wintun\{{{guid}}}" """;
// Try to remove the device
await Utils.GetCliWrapOutput(pnpUtilPath, arg);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
}
}

View File

@@ -0,0 +1,83 @@
using YamlDotNet.Core;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
namespace ServiceLib.Common
{
public class YamlUtils
{
private static readonly string _tag = "YamlUtils";
#region YAML
/// <summary>
/// 反序列化成对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="str"></param>
/// <returns></returns>
public static T FromYaml<T>(string str)
{
var deserializer = new DeserializerBuilder()
.WithNamingConvention(PascalCaseNamingConvention.Instance)
.Build();
try
{
var obj = deserializer.Deserialize<T>(str);
return obj;
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
return deserializer.Deserialize<T>("");
}
}
/// <summary>
/// 序列化
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static string ToYaml(object? obj)
{
var result = string.Empty;
if (obj == null)
{
return result;
}
var serializer = new SerializerBuilder()
.WithNamingConvention(HyphenatedNamingConvention.Instance)
.Build();
try
{
result = serializer.Serialize(obj);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return result;
}
public static string? PreprocessYaml(string str)
{
var deserializer = new DeserializerBuilder()
.WithNamingConvention(PascalCaseNamingConvention.Instance)
.Build();
try
{
var mergingParser = new MergingParser(new Parser(new StringReader(str)));
var obj = new DeserializerBuilder().Build().Deserialize(mergingParser);
return ToYaml(obj);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
return null;
}
}
#endregion YAML
}
}

View File

@@ -0,0 +1,16 @@
namespace ServiceLib.Enums
{
public enum EConfigType
{
VMess = 1,
Custom = 2,
Shadowsocks = 3,
SOCKS = 4,
VLESS = 5,
Trojan = 6,
Hysteria2 = 7,
TUIC = 8,
WireGuard = 9,
HTTP = 10
}
}

View File

@@ -1,17 +1,19 @@

namespace v2rayN.Mode
namespace ServiceLib.Enums
{
public enum ECoreType
{
v2fly = 1,
Xray = 2,
SagerNet = 3,
v2fly_v5 = 4,
clash = 11,
clash_meta = 12,
mihomo = 13,
hysteria = 21,
naiveproxy = 22,
tuic = 23,
sing_box = 24,
juicity = 25,
hysteria2 = 26,
brook = 27,
overtls = 28,
v2rayN = 99
}
}

View File

@@ -0,0 +1,9 @@
namespace ServiceLib.Enums
{
public enum EGirdOrientation
{
Horizontal,
Vertical,
Tab,
}
}

View File

@@ -1,5 +1,4 @@

namespace v2rayN.Mode
namespace ServiceLib.Enums
{
public enum EGlobalHotkey
{
@@ -7,5 +6,6 @@ namespace v2rayN.Mode
SystemProxyClear = 1,
SystemProxySet = 2,
SystemProxyUnchanged = 3,
SystemProxyPac = 4,
}
}
}

View File

@@ -0,0 +1,14 @@
namespace ServiceLib.Enums
{
public enum EInboundProtocol
{
socks = 0,
socks2,
socks3,
pac,
api,
api2,
mixed,
speedtest = 21
}
}

View File

@@ -1,5 +1,4 @@

namespace v2rayN.Mode
namespace ServiceLib.Enums
{
public enum EMove
{
@@ -9,4 +8,4 @@ namespace v2rayN.Mode
Bottom = 4,
Position = 5
}
}
}

View File

@@ -0,0 +1,11 @@
namespace ServiceLib.Enums
{
public enum EMsgCommand
{
ClearMsg,
SendMsgView,
SendSnackMsg,
RefreshProfiles,
AppExit
}
}

View File

@@ -0,0 +1,9 @@
namespace ServiceLib.Enums
{
public enum EPresetType
{
Default = 0,
Russia = 1,
Iran = 2,
}
}

View File

@@ -0,0 +1,10 @@
namespace ServiceLib.Enums
{
public enum ERuleMode
{
Rule = 0,
Global = 1,
Direct = 2,
Unchanged = 3
}
}

View File

@@ -0,0 +1,21 @@
namespace ServiceLib.Enums
{
public enum EServerColName
{
Def = 0,
ConfigType,
Remarks,
Address,
Port,
Network,
StreamSecurity,
SubRemarks,
DelayVal,
SpeedVal,
TodayDown,
TodayUp,
TotalDown,
TotalUp
}
}

View File

@@ -1,11 +1,10 @@

namespace v2rayN.Mode
namespace ServiceLib.Enums
{
public enum ESpeedActionType
{
Ping,
Tcping,
Realping,
Speedtest
Speedtest,
Mixedtest
}
}
}

View File

@@ -1,10 +1,10 @@

namespace v2rayN.Mode
namespace ServiceLib.Enums
{
public enum ESysProxyType
{
ForcedClear = 0,
ForcedChange = 1,
Unchanged = 2
Unchanged = 2,
Pac = 3
}
}
}

View File

@@ -0,0 +1,13 @@
namespace ServiceLib.Enums
{
public enum ETheme
{
FollowSystem,
Dark,
Light,
Aquatic,
Desert,
Dusk,
NightSky
}
}

View File

@@ -0,0 +1,15 @@
namespace ServiceLib.Enums
{
public enum ETransport
{
tcp,
kcp,
ws,
httpupgrade,
xhttp,
h2,
http,
quic,
grpc
}
}

View File

@@ -0,0 +1,46 @@
namespace ServiceLib.Enums
{
public enum EViewAction
{
CloseWindow,
ShowYesNo,
SaveFileDialog,
AddBatchRoutingRulesYesNo,
AdjustMainLvColWidth,
SetClipboardData,
AddServerViaClipboard,
ImportRulesFromClipboard,
ProfilesFocus,
ShareSub,
ShareServer,
ShowHideWindow,
ScanScreenTask,
ScanImageTask,
Shutdown,
BrowseServer,
ImportRulesFromFile,
InitSettingFont,
SubEditWindow,
RoutingRuleSettingWindow,
RoutingRuleDetailsWindow,
AddServerWindow,
AddServer2Window,
DNSSettingWindow,
RoutingSettingWindow,
OptionSettingWindow,
GlobalHotkeySettingWindow,
SubSettingWindow,
DispatcherSpeedTest,
DispatcherRefreshConnections,
DispatcherRefreshProxyGroups,
DispatcherProxiesDelayTest,
DispatcherStatistics,
DispatcherServerAvailability,
DispatcherReload,
DispatcherRefreshServersBiz,
DispatcherRefreshIcon,
DispatcherCheckUpdate,
DispatcherCheckUpdateFinished,
DispatcherShowMsg,
}
}

View File

@@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ReactiveUI />
</Weavers>

514
v2rayN/ServiceLib/Global.cs Normal file
View File

@@ -0,0 +1,514 @@
namespace ServiceLib
{
public class Global
{
#region const
public const string AppName = "v2rayN";
public const string GithubUrl = "https://github.com";
public const string GithubApiUrl = "https://api.github.com/repos";
public const string GeoUrl = "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/{0}.dat";
public const string SpeedPingTestUrl = @"https://www.google.com/generate_204";
public const string SingboxRulesetUrl = @"https://raw.githubusercontent.com/2dust/sing-box-rules/rule-set-{0}/{1}.srs";
public const string IPAPIUrl = "https://api.ip.sb/geoip";
public const string PromotionUrl = @"aHR0cHM6Ly85LjIzNDQ1Ni54eXovYWJjLmh0bWw=";
public const string ConfigFileName = "guiNConfig.json";
public const string CoreConfigFileName = "config.json";
public const string CorePreConfigFileName = "configPre.json";
public const string CoreSpeedtestConfigFileName = "configSpeedtest.json";
public const string CoreMultipleLoadConfigFileName = "configMultipleLoad.json";
public const string ClashMixinConfigFileName = "Mixin.yaml";
public const string NamespaceSample = "ServiceLib.Sample.";
public const string V2raySampleClient = NamespaceSample + "SampleClientConfig";
public const string SingboxSampleClient = NamespaceSample + "SingboxSampleClientConfig";
public const string V2raySampleHttpRequestFileName = NamespaceSample + "SampleHttpRequest";
public const string V2raySampleHttpResponseFileName = NamespaceSample + "SampleHttpResponse";
public const string V2raySampleInbound = NamespaceSample + "SampleInbound";
public const string V2raySampleOutbound = NamespaceSample + "SampleOutbound";
public const string SingboxSampleOutbound = NamespaceSample + "SingboxSampleOutbound";
public const string CustomRoutingFileName = NamespaceSample + "custom_routing_";
public const string TunSingboxDNSFileName = NamespaceSample + "tun_singbox_dns";
public const string TunSingboxInboundFileName = NamespaceSample + "tun_singbox_inbound";
public const string TunSingboxRulesFileName = NamespaceSample + "tun_singbox_rules";
public const string DNSV2rayNormalFileName = NamespaceSample + "dns_v2ray_normal";
public const string DNSSingboxNormalFileName = NamespaceSample + "dns_singbox_normal";
public const string ClashMixinYaml = NamespaceSample + "clash_mixin_yaml";
public const string ClashTunYaml = NamespaceSample + "clash_tun_yaml";
public const string LinuxAutostartConfig = NamespaceSample + "linux_autostart_config";
public const string PacFileName = NamespaceSample + "pac";
public const string DefaultSecurity = "auto";
public const string DefaultNetwork = "tcp";
public const string TcpHeaderHttp = "http";
public const string None = "none";
public const string ProxyTag = "proxy";
public const string DirectTag = "direct";
public const string BlockTag = "block";
public const string StreamSecurity = "tls";
public const string StreamSecurityReality = "reality";
public const string Loopback = "127.0.0.1";
public const string InboundAPIProtocol = "dokodemo-door";
public const string HttpProtocol = "http://";
public const string HttpsProtocol = "https://";
public const string SocksProtocol = "socks://";
public const string Socks5Protocol = "socks5://";
public const string UserEMail = "t@t.tt";
public const string AutoRunRegPath = @"Software\Microsoft\Windows\CurrentVersion\Run";
public const string AutoRunName = "v2rayNAutoRun";
public const string SystemProxyExceptionsWindows = "localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*";
public const string SystemProxyExceptionsLinux = "localhost,127.0.0.0/8,::1";
public const string RoutingRuleComma = "<COMMA>";
public const string GrpcGunMode = "gun";
public const string GrpcMultiMode = "multi";
public const int MaxPort = 65536;
public const string DelayUnit = "";
public const string SpeedUnit = "";
public const int MinFontSize = 8;
public const string RebootAs = "rebootas";
public const string AvaAssets = "avares://v2rayN/Assets/";
public const string LocalAppData = "V2RAYN_LOCAL_APPLICATION_DATA";
public const string V2RayLocalAsset = "V2RAY_LOCATION_ASSET";
public const string XrayLocalAsset = "XRAY_LOCATION_ASSET";
public const int SpeedTestPageSize = 1000;
public static readonly List<string> IEProxyProtocols =
[
"{ip}:{http_port}",
"socks={ip}:{socks_port}",
"http={ip}:{http_port};https={ip}:{http_port};ftp={ip}:{http_port};socks={ip}:{socks_port}",
"http=http://{ip}:{http_port};https=http://{ip}:{http_port}",
""
];
public static readonly List<string> SubConvertUrls =
[
@"https://sub.xeton.dev/sub?url={0}",
@"https://api.dler.io/sub?url={0}",
@"http://127.0.0.1:25500/sub?url={0}",
""
];
public static readonly List<string> SubConvertConfig =
[@"https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online.ini"];
public static readonly List<string> SubConvertTargets =
[
"",
"mixed",
"v2ray",
"clash",
"ss"
];
public static readonly List<string> SpeedTestUrls =
[
@"https://speed.cloudflare.com/__down?bytes=100000000",
@"https://speed.cloudflare.com/__down?bytes=50000000",
@"https://speed.cloudflare.com/__down?bytes=10000000",
@"https://cachefly.cachefly.net/50mb.test"
];
public static readonly List<string> SpeedPingTestUrls =
[
@"https://www.google.com/generate_204",
@"https://www.gstatic.com/generate_204",
@"https://www.apple.com/library/test/success.html",
@"http://www.msftconnecttest.com/connecttest.txt"
];
public static readonly List<string> GeoFilesSources =
[
"",
@"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/{0}.dat",
@"https://cdn.jsdelivr.net/gh/chocolate4u/Iran-v2ray-rules@release/{0}.dat"
];
public static readonly List<string> SingboxRulesetSources =
[
"",
@"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-rules-dat@release/sing-box/rule-set-{0}/{1}.srs",
@"https://cdn.jsdelivr.net/gh/chocolate4u/Iran-sing-box-rules@rule-set/{1}.srs"
];
public static readonly List<string> RoutingRulesSources =
[
"",
@"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/v2rayN/template.json",
@"https://cdn.jsdelivr.net/gh/Chocolate4U/Iran-v2ray-rules@main/v2rayN/template.json"
];
public static readonly List<string> DNSTemplateSources =
[
"",
@"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/v2rayN/",
@"https://cdn.jsdelivr.net/gh/Chocolate4U/Iran-v2ray-rules@main/v2rayN/"
];
public static readonly Dictionary<string, string> UserAgentTexts = new()
{
{"chrome","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36" },
{"firefox","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0" },
{"safari","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15" },
{"edge","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.70" },
{"none",""}
};
public const string Hysteria2ProtocolShare = "hy2://";
public static readonly Dictionary<EConfigType, string> ProtocolShares = new()
{
{ EConfigType.VMess, "vmess://" },
{ EConfigType.Shadowsocks, "ss://" },
{ EConfigType.SOCKS, "socks://" },
{ EConfigType.VLESS, "vless://" },
{ EConfigType.Trojan, "trojan://" },
{ EConfigType.Hysteria2, "hysteria2://" },
{ EConfigType.TUIC, "tuic://" },
{ EConfigType.WireGuard, "wireguard://" }
};
public static readonly Dictionary<EConfigType, string> ProtocolTypes = new()
{
{ EConfigType.VMess, "vmess" },
{ EConfigType.Shadowsocks, "shadowsocks" },
{ EConfigType.SOCKS, "socks" },
{ EConfigType.HTTP, "http" },
{ EConfigType.VLESS, "vless" },
{ EConfigType.Trojan, "trojan" },
{ EConfigType.Hysteria2, "hysteria2" },
{ EConfigType.TUIC, "tuic" },
{ EConfigType.WireGuard, "wireguard" }
};
public static readonly List<string> VmessSecurities =
[
"aes-128-gcm",
"chacha20-poly1305",
"auto",
"none",
"zero"
];
public static readonly List<string> SsSecurities =
[
"aes-256-gcm",
"aes-128-gcm",
"chacha20-poly1305",
"chacha20-ietf-poly1305",
"none",
"plain"
];
public static readonly List<string> SsSecuritiesInXray =
[
"aes-256-gcm",
"aes-128-gcm",
"chacha20-poly1305",
"chacha20-ietf-poly1305",
"xchacha20-poly1305",
"xchacha20-ietf-poly1305",
"none",
"plain",
"2022-blake3-aes-128-gcm",
"2022-blake3-aes-256-gcm",
"2022-blake3-chacha20-poly1305"
];
public static readonly List<string> SsSecuritiesInSingbox =
[
"aes-256-gcm",
"aes-192-gcm",
"aes-128-gcm",
"chacha20-ietf-poly1305",
"xchacha20-ietf-poly1305",
"none",
"2022-blake3-aes-128-gcm",
"2022-blake3-aes-256-gcm",
"2022-blake3-chacha20-poly1305",
"aes-128-ctr",
"aes-192-ctr",
"aes-256-ctr",
"aes-128-cfb",
"aes-192-cfb",
"aes-256-cfb",
"rc4-md5",
"chacha20-ietf",
"xchacha20"
];
public static readonly List<string> Flows =
[
"",
"xtls-rprx-vision",
"xtls-rprx-vision-udp443"
];
public static readonly List<string> Networks =
[
"tcp",
"kcp",
"ws",
"httpupgrade",
"xhttp",
"h2",
"quic",
"grpc"
];
public static readonly List<string> KcpHeaderTypes =
[
"srtp",
"utp",
"wechat-video",
"dtls",
"wireguard"
];
public static readonly List<string> CoreTypes =
[
"Xray",
"sing_box"
];
public static readonly List<string> DomainStrategies =
[
"AsIs",
"IPIfNonMatch",
"IPOnDemand"
];
public static readonly List<string> DomainStrategies4Singbox =
[
"ipv4_only",
"ipv6_only",
"prefer_ipv4",
"prefer_ipv6",
""
];
public static readonly List<string> DomainMatchers =
[
"linear",
"mph",
""
];
public static readonly List<string> Fingerprints =
[
"chrome",
"firefox",
"safari",
"ios",
"android",
"edge",
"360",
"qq",
"random",
"randomized",
""
];
public static readonly List<string> UserAgent =
[
"chrome",
"firefox",
"safari",
"edge",
"none"
];
public static readonly List<string> XhttpMode =
[
"auto",
"packet-up",
"stream-up",
"stream-one"
];
public static readonly List<string> AllowInsecure =
[
"true",
"false",
""
];
public static readonly List<string> DomainStrategy4Freedoms =
[
"AsIs",
"UseIP",
"UseIPv4",
"UseIPv6",
""
];
public static readonly List<string> SingboxDomainStrategy4Out =
[
"ipv4_only",
"prefer_ipv4",
"prefer_ipv6",
"ipv6_only",
""
];
public static readonly List<string> DomainDNSAddress =
[
"223.5.5.5",
"223.6.6.6",
"localhost"
];
public static readonly List<string> SingboxDomainDNSAddress =
[
"223.5.5.5",
"223.6.6.6",
"dhcp://auto"
];
public static readonly List<string> Languages =
[
"zh-Hans",
"zh-Hant",
"en",
"fa-Ir",
"ru",
"hu"
];
public static readonly List<string> Alpns =
[
"h3",
"h2",
"http/1.1",
"h3,h2",
"h2,http/1.1",
"h3,h2,http/1.1",
""
];
public static readonly List<string> LogLevels =
[
"debug",
"info",
"warning",
"error",
"none"
];
public static readonly List<string> InboundTags =
[
"socks",
"socks2",
"socks3"
];
public static readonly List<string> RuleProtocols =
[
"http",
"tls",
"bittorrent"
];
public static readonly List<string> RuleNetworks =
[
"",
"tcp",
"udp",
"tcp,udp"
];
public static readonly List<string> destOverrideProtocols =
[
"http",
"tls",
"quic",
"fakedns",
"fakedns+others"
];
public static readonly List<string> TunMtus =
[
"1280",
"1408",
"1500",
"9000"
];
public static readonly List<string> TunStacks =
[
"gvisor",
"system",
"mixed"
];
public static readonly List<string> PresetMsgFilters =
[
"proxy",
"direct",
"block",
""
];
public static readonly List<string> SingboxMuxs =
[
"h2mux",
"smux",
"yamux",
""
];
public static readonly List<string> TuicCongestionControls =
[
"cubic",
"new_reno",
"bbr"
];
public static readonly List<string> allowSelectType =
[
"selector",
"urltest",
"loadbalance",
"fallback"
];
public static readonly List<string> notAllowTestType =
[
"selector",
"urltest",
"direct",
"reject",
"compatible",
"pass",
"loadbalance",
"fallback"
];
public static readonly List<string> proxyVehicleType =
[
"file",
"http"
];
public static readonly Dictionary<ECoreType, string> CoreUrls = new()
{
{ ECoreType.v2fly, "v2fly/v2ray-core" },
{ ECoreType.v2fly_v5, "v2fly/v2ray-core" },
{ ECoreType.Xray, "XTLS/Xray-core" },
{ ECoreType.sing_box, "SagerNet/sing-box" },
{ ECoreType.mihomo, "MetaCubeX/mihomo" },
{ ECoreType.hysteria, "apernet/hysteria" },
{ ECoreType.hysteria2, "apernet/hysteria" },
{ ECoreType.naiveproxy, "klzgrad/naiveproxy" },
{ ECoreType.tuic, "EAimTY/tuic" },
{ ECoreType.juicity, "juicity/juicity" },
{ ECoreType.brook, "txthinking/brook" },
{ ECoreType.overtls, "ShadowsocksR-Live/overtls" },
{ ECoreType.v2rayN, "2dust/v2rayN" },
};
#endregion const
}
}

View File

@@ -0,0 +1,11 @@
global using ServiceLib.Base;
global using ServiceLib.Common;
global using ServiceLib.Enums;
global using ServiceLib.Handler;
global using ServiceLib.Handler.Fmt;
global using ServiceLib.Services;
global using ServiceLib.Services.Statistics;
global using ServiceLib.Services.CoreConfig;
global using ServiceLib.Models;
global using ServiceLib.Resx;
global using ServiceLib.Handler.SysProxy;

View File

@@ -0,0 +1,255 @@
namespace ServiceLib.Handler
{
public sealed class AppHandler
{
#region Property
private static readonly Lazy<AppHandler> _instance = new(() => new());
private Config _config;
private int? _statePort;
private int? _statePort2;
private Job? _processJob;
private bool? _isAdministrator;
public static AppHandler Instance => _instance.Value;
public Config Config => _config;
public int StatePort
{
get
{
_statePort ??= Utils.GetFreePort(GetLocalPort(EInboundProtocol.api));
return _statePort.Value;
}
}
public int StatePort2
{
get
{
_statePort2 ??= Utils.GetFreePort(GetLocalPort(EInboundProtocol.api2));
return _statePort2.Value + (_config.TunModeItem.EnableTun ? 1 : 0);
}
}
public bool IsAdministrator
{
get
{
_isAdministrator ??= Utils.IsAdministrator();
return _isAdministrator.Value;
}
}
#endregion Property
#region Init
public bool InitApp()
{
if (Utils.HasWritePermission() == false)
{
Environment.SetEnvironmentVariable(Global.LocalAppData, "1", EnvironmentVariableTarget.Process);
}
Logging.Setup();
var config = ConfigHandler.LoadConfig();
if (config == null)
{
return false;
}
_config = config;
Thread.CurrentThread.CurrentUICulture = new(_config.UiItem.CurrentLanguage);
//Under Win10
if (Utils.IsWindows() && Environment.OSVersion.Version.Major < 10)
{
Environment.SetEnvironmentVariable("DOTNET_EnableWriteXorExecute", "0", EnvironmentVariableTarget.User);
}
SQLiteHelper.Instance.CreateTable<SubItem>();
SQLiteHelper.Instance.CreateTable<ProfileItem>();
SQLiteHelper.Instance.CreateTable<ServerStatItem>();
SQLiteHelper.Instance.CreateTable<RoutingItem>();
SQLiteHelper.Instance.CreateTable<ProfileExItem>();
SQLiteHelper.Instance.CreateTable<DNSItem>();
return true;
}
public bool InitComponents()
{
Logging.SaveLog($"v2rayN start up | {Utils.GetRuntimeInfo()}");
Logging.LoggingEnabled(_config.GuiItem.EnableLog);
ClearExpiredFiles();
return true;
}
public bool Reset()
{
_statePort = null;
_statePort2 = null;
return true;
}
private void ClearExpiredFiles()
{
Task.Run(() =>
{
FileManager.DeleteExpiredFiles(Utils.GetLogPath(), DateTime.Now.AddMonths(-1));
FileManager.DeleteExpiredFiles(Utils.GetTempPath(), DateTime.Now.AddMonths(-1));
});
}
#endregion Init
#region Config
public int GetLocalPort(EInboundProtocol protocol)
{
var localPort = _config.Inbound.FirstOrDefault(t => t.Protocol == nameof(EInboundProtocol.socks))?.LocalPort ?? 10808;
return localPort + (int)protocol;
}
public void AddProcess(IntPtr processHandle)
{
if (Utils.IsWindows())
{
_processJob ??= new();
try
{
_processJob?.AddProcess(processHandle);
}
catch
{
}
}
}
#endregion Config
#region SqliteHelper
public async Task<List<SubItem>?> SubItems()
{
return await SQLiteHelper.Instance.TableAsync<SubItem>().OrderBy(t => t.Sort).ToListAsync();
}
public async Task<SubItem?> GetSubItem(string? subid)
{
return await SQLiteHelper.Instance.TableAsync<SubItem>().FirstOrDefaultAsync(t => t.Id == subid);
}
public async Task<List<ProfileItem>?> ProfileItems(string subid)
{
if (Utils.IsNullOrEmpty(subid))
{
return await SQLiteHelper.Instance.TableAsync<ProfileItem>().ToListAsync();
}
else
{
return await SQLiteHelper.Instance.TableAsync<ProfileItem>().Where(t => t.Subid == subid).ToListAsync();
}
}
public async Task<List<string>?> ProfileItemIndexes(string subid)
{
return (await ProfileItems(subid))?.Select(t => t.IndexId)?.ToList();
}
public async Task<List<ProfileItemModel>?> ProfileItems(string subid, string filter)
{
var sql = @$"select a.*
,b.remarks subRemarks
from ProfileItem a
left join SubItem b on a.subid = b.id
where 1=1 ";
if (Utils.IsNotEmpty(subid))
{
sql += $" and a.subid = '{subid}'";
}
if (Utils.IsNotEmpty(filter))
{
if (filter.Contains('\''))
{
filter = filter.Replace("'", "");
}
sql += string.Format(" and (a.remarks like '%{0}%' or a.address like '%{0}%') ", filter);
}
return await SQLiteHelper.Instance.QueryAsync<ProfileItemModel>(sql);
}
public async Task<ProfileItem?> GetProfileItem(string indexId)
{
if (Utils.IsNullOrEmpty(indexId))
{
return null;
}
return await SQLiteHelper.Instance.TableAsync<ProfileItem>().FirstOrDefaultAsync(it => it.IndexId == indexId);
}
public async Task<ProfileItem?> GetProfileItemViaRemarks(string? remarks)
{
if (Utils.IsNullOrEmpty(remarks))
{
return null;
}
return await SQLiteHelper.Instance.TableAsync<ProfileItem>().FirstOrDefaultAsync(it => it.Remarks == remarks);
}
public async Task<List<RoutingItem>?> RoutingItems()
{
return await SQLiteHelper.Instance.TableAsync<RoutingItem>().OrderBy(t => t.Sort).ToListAsync();
}
public async Task<RoutingItem?> GetRoutingItem(string id)
{
return await SQLiteHelper.Instance.TableAsync<RoutingItem>().FirstOrDefaultAsync(it => it.Id == id);
}
public async Task<List<DNSItem>?> DNSItems()
{
return await SQLiteHelper.Instance.TableAsync<DNSItem>().ToListAsync();
}
public async Task<DNSItem?> GetDNSItem(ECoreType eCoreType)
{
return await SQLiteHelper.Instance.TableAsync<DNSItem>().FirstOrDefaultAsync(it => it.CoreType == eCoreType);
}
#endregion SqliteHelper
#region Core Type
public List<string> GetShadowsocksSecurities(ProfileItem profileItem)
{
var coreType = GetCoreType(profileItem, EConfigType.Shadowsocks);
switch (coreType)
{
case ECoreType.v2fly:
return Global.SsSecurities;
case ECoreType.Xray:
return Global.SsSecuritiesInXray;
case ECoreType.sing_box:
return Global.SsSecuritiesInSingbox;
}
return Global.SsSecuritiesInSingbox;
}
public ECoreType GetCoreType(ProfileItem profileItem, EConfigType eConfigType)
{
if (profileItem?.CoreType != null)
{
return (ECoreType)profileItem.CoreType;
}
var item = _config.CoreTypeItem?.FirstOrDefault(it => it.ConfigType == eConfigType);
return item?.CoreType ?? ECoreType.Xray;
}
#endregion Core Type
}
}

View File

@@ -0,0 +1,242 @@
using System.Security.Principal;
using System.Text.RegularExpressions;
namespace ServiceLib.Handler
{
public static class AutoStartupHandler
{
private static readonly string _tag = "AutoStartupHandler";
public static async Task<bool> UpdateTask(Config config)
{
if (Utils.IsWindows())
{
await ClearTaskWindows();
if (config.GuiItem.AutoRun)
{
await SetTaskWindows();
}
}
else if (Utils.IsLinux())
{
await ClearTaskLinux();
if (config.GuiItem.AutoRun)
{
await SetTaskLinux();
}
}
else if (Utils.IsOSX())
{
await ClearTaskOSX();
if (config.GuiItem.AutoRun)
{
await SetTaskOSX();
}
}
return true;
}
#region Windows
private static async Task ClearTaskWindows()
{
var autoRunName = GetAutoRunNameWindows();
WindowsUtils.RegWriteValue(Global.AutoRunRegPath, autoRunName, "");
if (Utils.IsAdministrator())
{
AutoStartTaskService(autoRunName, "", "");
}
await Task.CompletedTask;
}
private static async Task SetTaskWindows()
{
try
{
var autoRunName = GetAutoRunNameWindows();
var exePath = Utils.GetExePath();
if (Utils.IsAdministrator())
{
AutoStartTaskService(autoRunName, exePath, "");
}
else
{
WindowsUtils.RegWriteValue(Global.AutoRunRegPath, autoRunName, exePath.AppendQuotes());
}
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
await Task.CompletedTask;
}
/// <summary>
/// Auto Start via TaskService
/// </summary>
/// <param name="taskName"></param>
/// <param name="fileName"></param>
/// <param name="description"></param>
/// <exception cref="ArgumentNullException"></exception>
public static void AutoStartTaskService(string taskName, string fileName, string description)
{
if (Utils.IsNullOrEmpty(taskName))
{
return;
}
var logonUser = WindowsIdentity.GetCurrent().Name;
using var taskService = new Microsoft.Win32.TaskScheduler.TaskService();
var tasks = taskService.RootFolder.GetTasks(new Regex(taskName));
if (Utils.IsNullOrEmpty(fileName))
{
foreach (var t in tasks)
{
taskService.RootFolder.DeleteTask(t.Name);
}
return;
}
var task = taskService.NewTask();
task.RegistrationInfo.Description = description;
task.Settings.DisallowStartIfOnBatteries = false;
task.Settings.StopIfGoingOnBatteries = false;
task.Settings.RunOnlyIfIdle = false;
task.Settings.IdleSettings.StopOnIdleEnd = false;
task.Settings.ExecutionTimeLimit = TimeSpan.Zero;
task.Triggers.Add(new Microsoft.Win32.TaskScheduler.LogonTrigger { UserId = logonUser, Delay = TimeSpan.FromSeconds(10) });
task.Principal.RunLevel = Microsoft.Win32.TaskScheduler.TaskRunLevel.Highest;
task.Actions.Add(new Microsoft.Win32.TaskScheduler.ExecAction(fileName.AppendQuotes(), null, Path.GetDirectoryName(fileName)));
taskService.RootFolder.RegisterTaskDefinition(taskName, task);
}
private static string GetAutoRunNameWindows()
{
return $"{Global.AutoRunName}_{Utils.GetMd5(Utils.StartupPath())}";
}
#endregion Windows
#region Linux
private static async Task ClearTaskLinux()
{
try
{
File.Delete(GetHomePathLinux());
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
await Task.CompletedTask;
}
private static async Task SetTaskLinux()
{
try
{
var linuxConfig = EmbedUtils.GetEmbedText(Global.LinuxAutostartConfig);
if (linuxConfig.IsNotEmpty())
{
linuxConfig = linuxConfig.Replace("$ExecPath$", Utils.GetExePath());
Logging.SaveLog(linuxConfig);
var homePath = GetHomePathLinux();
await File.WriteAllTextAsync(homePath, linuxConfig);
}
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
private static string GetHomePathLinux()
{
var homePath = Path.Combine(Utils.GetHomePath(), ".config", "autostart", $"{Global.AppName}.desktop");
Directory.CreateDirectory(Path.GetDirectoryName(homePath));
return homePath;
}
#endregion Linux
#region macOS
private static async Task ClearTaskOSX()
{
try
{
var launchAgentPath = GetLaunchAgentPathMacOS();
if (File.Exists(launchAgentPath))
{
var args = new[] { "-c", $"launchctl unload -w \"{launchAgentPath}\"" };
await Utils.GetCliWrapOutput("/bin/bash", args);
File.Delete(launchAgentPath);
}
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
private static async Task SetTaskOSX()
{
try
{
var plistContent = GenerateLaunchAgentPlist();
var launchAgentPath = GetLaunchAgentPathMacOS();
await File.WriteAllTextAsync(launchAgentPath, plistContent);
var args = new[] { "-c", $"launchctl load -w \"{launchAgentPath}\"" };
await Utils.GetCliWrapOutput("/bin/bash", args);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
private static string GetLaunchAgentPathMacOS()
{
var homePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
var launchAgentPath = Path.Combine(homePath, "Library", "LaunchAgents", $"{Global.AppName}-LaunchAgent.plist");
Directory.CreateDirectory(Path.GetDirectoryName(launchAgentPath));
return launchAgentPath;
}
private static string GenerateLaunchAgentPlist()
{
var exePath = Utils.GetExePath();
var appName = Path.GetFileNameWithoutExtension(exePath);
return $@"<?xml version=""1.0"" encoding=""UTF-8""?>
<!DOCTYPE plist PUBLIC ""-//Apple//DTD PLIST 1.0//EN"" ""http://www.apple.com/DTDs/PropertyList-1.0.dtd"">
<plist version=""1.0"">
<dict>
<key>Label</key>
<string>{Global.AppName}-LaunchAgent</string>
<key>ProgramArguments</key>
<array>
<string>/bin/sh</string>
<string>-c</string>
<string>if ! pgrep -x ""{appName}"" > /dev/null; then ""{exePath}""; fi</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<false/>
</dict>
</plist>";
}
#endregion macOS
}
}

View File

@@ -0,0 +1,197 @@
using static ServiceLib.Models.ClashProxies;
namespace ServiceLib.Handler
{
public sealed class ClashApiHandler
{
private static readonly Lazy<ClashApiHandler> instance = new(() => new());
public static ClashApiHandler Instance => instance.Value;
private Dictionary<string, ProxiesItem>? _proxies;
public Dictionary<string, object> ProfileContent { get; set; }
private static readonly string _tag = "ClashApiHandler";
public async Task<Tuple<ClashProxies, ClashProviders>?> GetClashProxiesAsync(Config config)
{
for (var i = 0; i < 5; i++)
{
var url = $"{GetApiUrl()}/proxies";
var result = await HttpClientHelper.Instance.TryGetAsync(url);
var clashProxies = JsonUtils.Deserialize<ClashProxies>(result);
var url2 = $"{GetApiUrl()}/providers/proxies";
var result2 = await HttpClientHelper.Instance.TryGetAsync(url2);
var clashProviders = JsonUtils.Deserialize<ClashProviders>(result2);
if (clashProxies != null || clashProviders != null)
{
_proxies = clashProxies?.proxies;
return new Tuple<ClashProxies, ClashProviders>(clashProxies, clashProviders);
}
await Task.Delay(2000);
}
return null;
}
public void ClashProxiesDelayTest(bool blAll, List<ClashProxyModel> lstProxy, Action<ClashProxyModel?, string> updateFunc)
{
Task.Run(() =>
{
if (blAll)
{
for (var i = 0; i < 5; i++)
{
if (_proxies != null)
{
break;
}
Task.Delay(5000).Wait();
}
if (_proxies == null)
{
return;
}
lstProxy = new List<ClashProxyModel>();
foreach (KeyValuePair<string, ProxiesItem> kv in _proxies)
{
if (Global.notAllowTestType.Contains(kv.Value.type.ToLower()))
{
continue;
}
lstProxy.Add(new ClashProxyModel()
{
Name = kv.Value.name,
Type = kv.Value.type.ToLower(),
});
}
}
if (lstProxy == null)
{
return;
}
var urlBase = $"{GetApiUrl()}/proxies";
urlBase += @"/{0}/delay?timeout=10000&url=" + AppHandler.Instance.Config.SpeedTestItem.SpeedPingTestUrl;
var tasks = new List<Task>();
foreach (var it in lstProxy)
{
if (Global.notAllowTestType.Contains(it.Type.ToLower()))
{
continue;
}
var name = it.Name;
var url = string.Format(urlBase, name);
tasks.Add(Task.Run(async () =>
{
var result = await HttpClientHelper.Instance.TryGetAsync(url);
updateFunc?.Invoke(it, result);
}));
}
Task.WaitAll(tasks.ToArray());
Task.Delay(1000).Wait();
updateFunc?.Invoke(null, "");
});
}
public List<ProxiesItem>? GetClashProxyGroups()
{
try
{
var fileContent = ProfileContent;
if (fileContent is null || fileContent?.ContainsKey("proxy-groups") == false)
{
return null;
}
return JsonUtils.Deserialize<List<ProxiesItem>>(JsonUtils.Serialize(fileContent["proxy-groups"]));
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
return null;
}
}
public async Task ClashSetActiveProxy(string name, string nameNode)
{
try
{
var url = $"{GetApiUrl()}/proxies/{name}";
var headers = new Dictionary<string, string>();
headers.Add("name", nameNode);
await HttpClientHelper.Instance.PutAsync(url, headers);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
public async Task ClashConfigUpdate(Dictionary<string, string> headers)
{
if (_proxies == null)
{
return;
}
var urlBase = $"{GetApiUrl()}/configs";
await HttpClientHelper.Instance.PatchAsync(urlBase, headers);
}
public async Task ClashConfigReload(string filePath)
{
await ClashConnectionClose("");
try
{
var url = $"{GetApiUrl()}/configs?force=true";
var headers = new Dictionary<string, string>();
headers.Add("path", filePath);
await HttpClientHelper.Instance.PutAsync(url, headers);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
public async Task<ClashConnections?> GetClashConnectionsAsync(Config config)
{
try
{
var url = $"{GetApiUrl()}/connections";
var result = await HttpClientHelper.Instance.TryGetAsync(url);
var clashConnections = JsonUtils.Deserialize<ClashConnections>(result);
return clashConnections;
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return null;
}
public async Task ClashConnectionClose(string id)
{
try
{
var url = $"{GetApiUrl()}/connections/{id}";
await HttpClientHelper.Instance.DeleteAsync(url);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
private string GetApiUrl()
{
return $"{Global.HttpProtocol}{Global.Loopback}:{AppHandler.Instance.StatePort2}";
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,132 @@
namespace ServiceLib.Handler
{
/// <summary>
/// Core configuration file processing class
/// </summary>
public class CoreConfigHandler
{
private static readonly string _tag = "CoreConfigHandler";
public static async Task<RetResult> GenerateClientConfig(ProfileItem node, string? fileName)
{
var config = AppHandler.Instance.Config;
var result = new RetResult();
if (node.ConfigType == EConfigType.Custom)
{
result = node.CoreType switch
{
ECoreType.mihomo => await new CoreConfigClashService(config).GenerateClientCustomConfig(node, fileName),
ECoreType.sing_box => await new CoreConfigSingboxService(config).GenerateClientCustomConfig(node, fileName),
_ => await GenerateClientCustomConfig(node, fileName)
};
}
else if (AppHandler.Instance.GetCoreType(node, node.ConfigType) == ECoreType.sing_box)
{
result = await new CoreConfigSingboxService(config).GenerateClientConfigContent(node);
}
else
{
result = await new CoreConfigV2rayService(config).GenerateClientConfigContent(node);
}
if (result.Success != true)
{
return result;
}
if (Utils.IsNotEmpty(fileName) && result.Data != null)
{
await File.WriteAllTextAsync(fileName, result.Data.ToString());
}
return result;
}
private static async Task<RetResult> GenerateClientCustomConfig(ProfileItem node, string? fileName)
{
var ret = new RetResult();
try
{
if (node == null || fileName is null)
{
ret.Msg = ResUI.CheckServerSettings;
return ret;
}
if (File.Exists(fileName))
{
File.SetAttributes(fileName, FileAttributes.Normal); //If the file has a read-only attribute, direct deletion will fail
File.Delete(fileName);
}
string addressFileName = node.Address;
if (!File.Exists(addressFileName))
{
addressFileName = Utils.GetConfigPath(addressFileName);
}
if (!File.Exists(addressFileName))
{
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
}
File.Copy(addressFileName, fileName);
File.SetAttributes(fileName, FileAttributes.Normal); //Copy will keep the attributes of addressFileName, so we need to add write permissions to fileName just in case of addressFileName is a read-only file.
//check again
if (!File.Exists(fileName))
{
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
}
ret.Msg = string.Format(ResUI.SuccessfulConfiguration, "");
ret.Success = true;
return await Task.FromResult(ret);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
}
}
public static async Task<RetResult> GenerateClientSpeedtestConfig(Config config, string fileName, List<ServerTestItem> selecteds, ECoreType coreType)
{
var result = new RetResult();
if (coreType == ECoreType.sing_box)
{
result = await new CoreConfigSingboxService(config).GenerateClientSpeedtestConfig(selecteds);
}
else if (coreType == ECoreType.Xray)
{
result = await new CoreConfigV2rayService(config).GenerateClientSpeedtestConfig(selecteds);
}
if (result.Success != true)
{
return result;
}
await File.WriteAllTextAsync(fileName, result.Data.ToString());
return result;
}
public static async Task<RetResult> GenerateClientMultipleLoadConfig(Config config, string fileName, List<ProfileItem> selecteds, ECoreType coreType)
{
var result = new RetResult();
if (coreType == ECoreType.sing_box)
{
result = await new CoreConfigSingboxService(config).GenerateClientMultipleLoadConfig(selecteds);
}
else if (coreType == ECoreType.Xray)
{
result = await new CoreConfigV2rayService(config).GenerateClientMultipleLoadConfig(selecteds);
}
if (result.Success != true)
{
return result;
}
await File.WriteAllTextAsync(fileName, result.Data.ToString());
return result;
}
}
}

View File

@@ -0,0 +1,381 @@
using System.Diagnostics;
using System.Text;
namespace ServiceLib.Handler
{
/// <summary>
/// Core process processing class
/// </summary>
public class CoreHandler
{
private static readonly Lazy<CoreHandler> _instance = new(() => new());
public static CoreHandler Instance => _instance.Value;
private Config _config;
private Process? _process;
private Process? _processPre;
private int _linuxSudoPid = -1;
private Action<bool, string>? _updateFunc;
private const string _tag = "CoreHandler";
public async Task Init(Config config, Action<bool, string> updateFunc)
{
_config = config;
_updateFunc = updateFunc;
Environment.SetEnvironmentVariable(Global.V2RayLocalAsset, Utils.GetBinPath(""), EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable(Global.XrayLocalAsset, Utils.GetBinPath(""), EnvironmentVariableTarget.Process);
//Copy the bin folder to the storage location (for init)
if (Environment.GetEnvironmentVariable(Global.LocalAppData) == "1")
{
var fromPath = Utils.GetBaseDirectory("bin");
var toPath = Utils.GetBinPath("");
if (fromPath != toPath)
{
FileManager.CopyDirectory(fromPath, toPath, true, false);
}
}
if (Utils.IsNonWindows())
{
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo();
foreach (var it in coreInfo)
{
if (it.CoreType == ECoreType.v2rayN)
{
if (Utils.UpgradeAppExists(out var upgradeFileName))
{
await Utils.SetLinuxChmod(upgradeFileName);
}
continue;
}
foreach (var name in it.CoreExes)
{
var exe = Utils.GetBinPath(Utils.GetExeName(name), it.CoreType.ToString());
if (File.Exists(exe))
{
await Utils.SetLinuxChmod(exe);
}
}
}
}
}
public async Task LoadCore(ProfileItem? node)
{
if (node == null)
{
UpdateFunc(false, ResUI.CheckServerSettings);
return;
}
var fileName = Utils.GetConfigPath(Global.CoreConfigFileName);
var result = await CoreConfigHandler.GenerateClientConfig(node, fileName);
if (result.Success != true)
{
UpdateFunc(true, result.Msg);
return;
}
UpdateFunc(false, $"{node.GetSummary()}");
UpdateFunc(false, $"{Utils.GetRuntimeInfo()}");
UpdateFunc(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
await CoreStop();
await Task.Delay(100);
if (Utils.IsWindows() && _config.TunModeItem.EnableTun)
{
await Task.Delay(100);
await WindowsUtils.RemoveTunDevice();
}
await CoreStart(node);
await CoreStartPreService(node);
if (_process != null)
{
UpdateFunc(true, $"{node.GetSummary()}");
}
}
public async Task<int> LoadCoreConfigSpeedtest(List<ServerTestItem> selecteds)
{
var coreType = selecteds.Exists(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard) ? ECoreType.sing_box : ECoreType.Xray;
var configPath = Utils.GetConfigPath(Global.CoreSpeedtestConfigFileName);
var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType);
UpdateFunc(false, result.Msg);
if (result.Success != true)
{
return -1;
}
UpdateFunc(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
UpdateFunc(false, configPath);
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
var proc = await RunProcess(coreInfo, Global.CoreSpeedtestConfigFileName, true, false);
if (proc is null)
{
return -1;
}
return proc.Id;
}
public async Task CoreStop()
{
try
{
if (_process != null)
{
await ProcUtils.ProcessKill(_process, true);
_process = null;
}
if (_processPre != null)
{
await ProcUtils.ProcessKill(_processPre, true);
_processPre = null;
}
if (_linuxSudoPid > 0)
{
await KillProcessAsLinuxSudo();
}
_linuxSudoPid = -1;
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
#region Private
private async Task CoreStart(ProfileItem node)
{
var coreType = _config.RunningCoreType = AppHandler.Instance.GetCoreType(node, node.ConfigType);
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
var displayLog = node.ConfigType != EConfigType.Custom || node.DisplayLog;
var proc = await RunProcess(coreInfo, Global.CoreConfigFileName, displayLog, true);
if (proc is null)
{
return;
}
_process = proc;
}
private async Task CoreStartPreService(ProfileItem node)
{
if (_process != null && !_process.HasExited)
{
var coreType = AppHandler.Instance.GetCoreType(node, node.ConfigType);
var itemSocks = await ConfigHandler.GetPreSocksItem(_config, node, coreType);
if (itemSocks != null)
{
var preCoreType = itemSocks.CoreType ?? ECoreType.sing_box;
var fileName = Utils.GetConfigPath(Global.CorePreConfigFileName);
var result = await CoreConfigHandler.GenerateClientConfig(itemSocks, fileName);
if (result.Success)
{
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(preCoreType);
var proc = await RunProcess(coreInfo, Global.CorePreConfigFileName, true, true);
if (proc is null)
{
return;
}
_processPre = proc;
}
}
}
}
private void UpdateFunc(bool notify, string msg)
{
_updateFunc?.Invoke(notify, msg);
}
private bool IsNeedSudo(ECoreType eCoreType)
{
return _config.TunModeItem.EnableTun
&& eCoreType == ECoreType.sing_box
&& (Utils.IsNonWindows())
//&& _config.TunModeItem.LinuxSudoPwd.IsNotEmpty()
;
}
#endregion Private
#region Process
private async Task<Process?> RunProcess(CoreInfo? coreInfo, string configPath, bool displayLog, bool mayNeedSudo)
{
var fileName = CoreInfoHandler.Instance.GetCoreExecFile(coreInfo, out var msg);
if (Utils.IsNullOrEmpty(fileName))
{
UpdateFunc(false, msg);
return null;
}
try
{
Process proc = new()
{
StartInfo = new()
{
FileName = fileName,
Arguments = string.Format(coreInfo.Arguments, coreInfo.AbsolutePath ? Utils.GetConfigPath(configPath) : configPath),
WorkingDirectory = Utils.GetConfigPath(),
UseShellExecute = false,
RedirectStandardOutput = displayLog,
RedirectStandardError = displayLog,
CreateNoWindow = true,
StandardOutputEncoding = displayLog ? Encoding.UTF8 : null,
StandardErrorEncoding = displayLog ? Encoding.UTF8 : null,
}
};
var isNeedSudo = mayNeedSudo && IsNeedSudo(coreInfo.CoreType);
if (isNeedSudo)
{
await RunProcessAsLinuxSudo(proc, fileName, coreInfo, configPath);
}
if (displayLog)
{
proc.OutputDataReceived += (sender, e) =>
{
if (Utils.IsNullOrEmpty(e.Data))
return;
UpdateFunc(false, e.Data + Environment.NewLine);
};
proc.ErrorDataReceived += (sender, e) =>
{
if (Utils.IsNullOrEmpty(e.Data))
return;
UpdateFunc(false, e.Data + Environment.NewLine);
};
}
proc.Start();
if (isNeedSudo && _config.TunModeItem.LinuxSudoPwd.IsNotEmpty())
{
var pwd = DesUtils.Decrypt(_config.TunModeItem.LinuxSudoPwd);
await Task.Delay(10);
await proc.StandardInput.WriteLineAsync(pwd);
await Task.Delay(10);
await proc.StandardInput.WriteLineAsync(pwd);
}
if (isNeedSudo)
_linuxSudoPid = proc.Id;
if (displayLog)
{
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
}
await Task.Delay(500);
AppHandler.Instance.AddProcess(proc.Handle);
if (proc is null or { HasExited: true })
{
throw new Exception(ResUI.FailedToRunCore);
}
return proc;
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
UpdateFunc(mayNeedSudo, ex.Message);
return null;
}
}
#endregion Process
#region Linux
private async Task RunProcessAsLinuxSudo(Process proc, string fileName, CoreInfo coreInfo, string configPath)
{
var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetConfigPath(configPath).AppendQuotes())}";
var shFilePath = await CreateLinuxShellFile(cmdLine, "run_as_sudo.sh");
proc.StartInfo.FileName = shFilePath;
proc.StartInfo.Arguments = "";
proc.StartInfo.WorkingDirectory = "";
if (_config.TunModeItem.LinuxSudoPwd.IsNotEmpty())
{
proc.StartInfo.StandardInputEncoding = Encoding.UTF8;
proc.StartInfo.RedirectStandardInput = true;
}
}
private async Task KillProcessAsLinuxSudo()
{
var cmdLine = $"kill {_linuxSudoPid}";
var shFilePath = await CreateLinuxShellFile(cmdLine, "kill_as_sudo.sh");
Process proc = new()
{
StartInfo = new()
{
FileName = shFilePath,
UseShellExecute = false,
CreateNoWindow = true,
StandardInputEncoding = Encoding.UTF8,
RedirectStandardInput = true
}
};
proc.Start();
if (_config.TunModeItem.LinuxSudoPwd.IsNotEmpty())
{
try
{
var pwd = DesUtils.Decrypt(_config.TunModeItem.LinuxSudoPwd);
await Task.Delay(10);
await proc.StandardInput.WriteLineAsync(pwd);
await Task.Delay(10);
await proc.StandardInput.WriteLineAsync(pwd);
}
catch (Exception)
{
// ignored
}
}
var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(10));
await proc.WaitForExitAsync(timeout.Token);
await Task.Delay(3000);
}
private async Task<string> CreateLinuxShellFile(string cmdLine, string fileName)
{
//Shell scripts
var shFilePath = Utils.GetBinPath(AppHandler.Instance.IsAdministrator ? "root_" + fileName : fileName);
File.Delete(shFilePath);
var sb = new StringBuilder();
sb.AppendLine("#!/bin/sh");
if (AppHandler.Instance.IsAdministrator)
{
sb.AppendLine($"{cmdLine}");
}
else if (_config.TunModeItem.LinuxSudoPwd.IsNullOrEmpty())
{
sb.AppendLine($"pkexec {cmdLine}");
}
else
{
sb.AppendLine($"sudo -S {cmdLine}");
}
await File.WriteAllTextAsync(shFilePath, sb.ToString());
await Utils.SetLinuxChmod(shFilePath);
Logging.SaveLog(shFilePath);
return shFilePath;
}
#endregion Linux
}
}

View File

@@ -0,0 +1,218 @@
namespace ServiceLib.Handler
{
public sealed class CoreInfoHandler
{
private static readonly Lazy<CoreInfoHandler> _instance = new(() => new());
private List<CoreInfo>? _coreInfo;
public static CoreInfoHandler Instance => _instance.Value;
public CoreInfoHandler()
{
InitCoreInfo();
}
public CoreInfo? GetCoreInfo(ECoreType coreType)
{
if (_coreInfo == null)
{
InitCoreInfo();
}
return _coreInfo?.FirstOrDefault(t => t.CoreType == coreType);
}
public List<CoreInfo> GetCoreInfo()
{
if (_coreInfo == null)
{
InitCoreInfo();
}
return _coreInfo ?? [];
}
public string GetCoreExecFile(CoreInfo? coreInfo, out string msg)
{
var fileName = string.Empty;
msg = string.Empty;
foreach (var name in coreInfo?.CoreExes)
{
var vName = Utils.GetBinPath(Utils.GetExeName(name), coreInfo.CoreType.ToString());
if (File.Exists(vName))
{
fileName = vName;
break;
}
}
if (fileName.IsNullOrEmpty())
{
msg = string.Format(ResUI.NotFoundCore, Utils.GetBinPath("", coreInfo?.CoreType.ToString()), coreInfo?.CoreExes?.LastOrDefault(), coreInfo?.Url);
Logging.SaveLog(msg);
}
return fileName;
}
private void InitCoreInfo()
{
var urlN = GetCoreUrl(ECoreType.v2rayN);
var urlXray = GetCoreUrl(ECoreType.Xray);
var urlMihomo = GetCoreUrl(ECoreType.mihomo);
var urlSingbox = GetCoreUrl(ECoreType.sing_box);
_coreInfo =
[
new CoreInfo
{
CoreType = ECoreType.v2rayN,
Url = GetCoreUrl(ECoreType.v2rayN),
ReleaseApiUrl = urlN.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = urlN + "/download/{0}/v2rayN-windows-64.zip",
DownloadUrlWinArm64 = urlN + "/download/{0}/v2rayN-windows-arm64.zip",
DownloadUrlLinux64 = urlN + "/download/{0}/v2rayN-linux-64.zip",
DownloadUrlLinuxArm64 = urlN + "/download/{0}/v2rayN-linux-arm64.zip",
DownloadUrlOSX64 = urlN + "/download/{0}/v2rayN-macos-64.zip",
DownloadUrlOSXArm64 = urlN + "/download/{0}/v2rayN-macos-arm64.zip",
},
new CoreInfo
{
CoreType = ECoreType.v2fly,
CoreExes = ["v2ray"],
Arguments = "{0}",
Url = GetCoreUrl(ECoreType.v2fly),
Match = "V2Ray",
VersionArg = "-version",
},
new CoreInfo
{
CoreType = ECoreType.v2fly_v5,
CoreExes = ["v2ray"],
Arguments = "run -c {0} -format jsonv5",
Url = GetCoreUrl(ECoreType.v2fly_v5),
Match = "V2Ray",
VersionArg = "version",
},
new CoreInfo
{
CoreType = ECoreType.Xray,
CoreExes = ["xray"],
Arguments = "run -c {0}",
Url = GetCoreUrl(ECoreType.Xray),
ReleaseApiUrl = urlXray.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = urlXray + "/download/{0}/Xray-windows-64.zip",
DownloadUrlWinArm64 = urlXray + "/download/{0}/Xray-windows-arm64-v8a.zip",
DownloadUrlLinux64 = urlXray + "/download/{0}/Xray-linux-64.zip",
DownloadUrlLinuxArm64 = urlXray + "/download/{0}/Xray-linux-arm64-v8a.zip",
DownloadUrlOSX64 = urlXray + "/download/{0}/Xray-macos-64.zip",
DownloadUrlOSXArm64 = urlXray + "/download/{0}/Xray-macos-arm64-v8a.zip",
Match = "Xray",
VersionArg = "-version",
},
new CoreInfo
{
CoreType = ECoreType.mihomo,
CoreExes = ["mihomo-windows-amd64-compatible", "mihomo-windows-amd64", "mihomo-linux-amd64", "clash", "mihomo"],
Arguments = "-f {0}" + PortableMode(),
Url = GetCoreUrl(ECoreType.mihomo),
ReleaseApiUrl = urlMihomo.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = urlMihomo + "/download/{0}/mihomo-windows-amd64-compatible-{0}.zip",
DownloadUrlWinArm64 = urlMihomo + "/download/{0}/mihomo-windows-arm64-{0}.zip",
DownloadUrlLinux64 = urlMihomo + "/download/{0}/mihomo-linux-amd64-compatible-{0}.gz",
DownloadUrlLinuxArm64 = urlMihomo + "/download/{0}/mihomo-linux-arm64-{0}.gz",
DownloadUrlOSX64 = urlMihomo + "/download/{0}/mihomo-darwin-amd64-compatible-{0}.gz",
DownloadUrlOSXArm64 = urlMihomo + "/download/{0}/mihomo-darwin-arm64-{0}.gz",
Match = "Mihomo",
VersionArg = "-v",
},
new CoreInfo
{
CoreType = ECoreType.hysteria,
CoreExes = ["hysteria"],
Arguments = "",
Url = GetCoreUrl(ECoreType.hysteria),
},
new CoreInfo
{
CoreType = ECoreType.naiveproxy,
CoreExes = [ "naive", "naiveproxy"],
Arguments = "{0}",
Url = GetCoreUrl(ECoreType.naiveproxy),
},
new CoreInfo
{
CoreType = ECoreType.tuic,
CoreExes = ["tuic-client", "tuic"],
Arguments = "-c {0}",
Url = GetCoreUrl(ECoreType.tuic),
},
new CoreInfo
{
CoreType = ECoreType.sing_box,
CoreExes = ["sing-box-client", "sing-box"],
Arguments = "run -c {0} --disable-color",
Url = GetCoreUrl(ECoreType.sing_box),
ReleaseApiUrl = urlSingbox.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = urlSingbox + "/download/{0}/sing-box-{1}-windows-amd64.zip",
DownloadUrlWinArm64 = urlSingbox + "/download/{0}/sing-box-{1}-windows-arm64.zip",
DownloadUrlLinux64 = urlSingbox + "/download/{0}/sing-box-{1}-linux-amd64.tar.gz",
DownloadUrlLinuxArm64 = urlSingbox + "/download/{0}/sing-box-{1}-linux-arm64.tar.gz",
DownloadUrlOSX64 = urlSingbox + "/download/{0}/sing-box-{1}-darwin-amd64.tar.gz",
DownloadUrlOSXArm64 = urlSingbox + "/download/{0}/sing-box-{1}-darwin-arm64.tar.gz",
Match = "sing-box",
VersionArg = "version",
},
new CoreInfo
{
CoreType = ECoreType.juicity,
CoreExes = ["juicity-client", "juicity"],
Arguments = "run -c {0}",
Url = GetCoreUrl(ECoreType.juicity)
},
new CoreInfo
{
CoreType = ECoreType.hysteria2,
CoreExes = ["hysteria-windows-amd64", "hysteria-linux-amd64", "hysteria"],
Arguments = "",
Url = GetCoreUrl(ECoreType.hysteria2),
},
new CoreInfo
{
CoreType = ECoreType.brook,
CoreExes = ["brook_windows_amd64", "brook_linux_amd64", "brook"],
Arguments = " {0}",
Url = GetCoreUrl(ECoreType.brook),
AbsolutePath = true,
},
new CoreInfo
{
CoreType = ECoreType.overtls,
CoreExes = [ "overtls-bin", "overtls"],
Arguments = "-r client -c {0}",
Url = GetCoreUrl(ECoreType.overtls),
AbsolutePath = false,
}
];
}
private static string PortableMode()
{
return $" -d {Utils.GetBinPath("").AppendQuotes()}";
}
private static string GetCoreUrl(ECoreType eCoreType)
{
return $"{Global.GithubUrl}/{Global.CoreUrls[eCoreType]}/releases";
}
}
}

View File

@@ -0,0 +1,240 @@
using System.Collections.Specialized;
namespace ServiceLib.Handler.Fmt
{
public class BaseFmt
{
protected static string GetIpv6(string address)
{
if (Utils.IsIpv6(address))
{
// 检查地址是否已经被方括号包围,如果没有,则添加方括号
return address.StartsWith('[') && address.EndsWith(']') ? address : $"[{address}]";
}
return address; // 如果不是IPv6地址直接返回原地址
}
protected static int GetStdTransport(ProfileItem item, string? securityDef, ref Dictionary<string, string> dicQuery)
{
if (Utils.IsNotEmpty(item.Flow))
{
dicQuery.Add("flow", item.Flow);
}
if (Utils.IsNotEmpty(item.StreamSecurity))
{
dicQuery.Add("security", item.StreamSecurity);
}
else
{
if (securityDef != null)
{
dicQuery.Add("security", securityDef);
}
}
if (Utils.IsNotEmpty(item.Sni))
{
dicQuery.Add("sni", item.Sni);
}
if (Utils.IsNotEmpty(item.Alpn))
{
dicQuery.Add("alpn", Utils.UrlEncode(item.Alpn));
}
if (Utils.IsNotEmpty(item.Fingerprint))
{
dicQuery.Add("fp", Utils.UrlEncode(item.Fingerprint));
}
if (Utils.IsNotEmpty(item.PublicKey))
{
dicQuery.Add("pbk", Utils.UrlEncode(item.PublicKey));
}
if (Utils.IsNotEmpty(item.ShortId))
{
dicQuery.Add("sid", Utils.UrlEncode(item.ShortId));
}
if (Utils.IsNotEmpty(item.SpiderX))
{
dicQuery.Add("spx", Utils.UrlEncode(item.SpiderX));
}
if (item.AllowInsecure.Equals("true"))
{
dicQuery.Add("allowInsecure", "1");
}
dicQuery.Add("type", Utils.IsNotEmpty(item.Network) ? item.Network : nameof(ETransport.tcp));
switch (item.Network)
{
case nameof(ETransport.tcp):
dicQuery.Add("headerType", Utils.IsNotEmpty(item.HeaderType) ? item.HeaderType : Global.None);
if (Utils.IsNotEmpty(item.RequestHost))
{
dicQuery.Add("host", Utils.UrlEncode(item.RequestHost));
}
break;
case nameof(ETransport.kcp):
dicQuery.Add("headerType", Utils.IsNotEmpty(item.HeaderType) ? item.HeaderType : Global.None);
if (Utils.IsNotEmpty(item.Path))
{
dicQuery.Add("seed", Utils.UrlEncode(item.Path));
}
break;
case nameof(ETransport.ws):
case nameof(ETransport.httpupgrade):
if (Utils.IsNotEmpty(item.RequestHost))
{
dicQuery.Add("host", Utils.UrlEncode(item.RequestHost));
}
if (Utils.IsNotEmpty(item.Path))
{
dicQuery.Add("path", Utils.UrlEncode(item.Path));
}
break;
case nameof(ETransport.xhttp):
if (Utils.IsNotEmpty(item.RequestHost))
{
dicQuery.Add("host", Utils.UrlEncode(item.RequestHost));
}
if (Utils.IsNotEmpty(item.Path))
{
dicQuery.Add("path", Utils.UrlEncode(item.Path));
}
if (Utils.IsNotEmpty(item.HeaderType) && Global.XhttpMode.Contains(item.HeaderType))
{
dicQuery.Add("mode", Utils.UrlEncode(item.HeaderType));
}
if (Utils.IsNotEmpty(item.Extra))
{
dicQuery.Add("extra", Utils.UrlEncode(item.Extra));
}
break;
case nameof(ETransport.http):
case nameof(ETransport.h2):
dicQuery["type"] = nameof(ETransport.http);
if (Utils.IsNotEmpty(item.RequestHost))
{
dicQuery.Add("host", Utils.UrlEncode(item.RequestHost));
}
if (Utils.IsNotEmpty(item.Path))
{
dicQuery.Add("path", Utils.UrlEncode(item.Path));
}
break;
case nameof(ETransport.quic):
dicQuery.Add("headerType", Utils.IsNotEmpty(item.HeaderType) ? item.HeaderType : Global.None);
dicQuery.Add("quicSecurity", Utils.UrlEncode(item.RequestHost));
dicQuery.Add("key", Utils.UrlEncode(item.Path));
break;
case nameof(ETransport.grpc):
if (Utils.IsNotEmpty(item.Path))
{
dicQuery.Add("authority", Utils.UrlEncode(item.RequestHost));
dicQuery.Add("serviceName", Utils.UrlEncode(item.Path));
if (item.HeaderType is Global.GrpcGunMode or Global.GrpcMultiMode)
{
dicQuery.Add("mode", Utils.UrlEncode(item.HeaderType));
}
}
break;
}
return 0;
}
protected static int ResolveStdTransport(NameValueCollection query, ref ProfileItem item)
{
item.Flow = query["flow"] ?? "";
item.StreamSecurity = query["security"] ?? "";
item.Sni = query["sni"] ?? "";
item.Alpn = Utils.UrlDecode(query["alpn"] ?? "");
item.Fingerprint = Utils.UrlDecode(query["fp"] ?? "");
item.PublicKey = Utils.UrlDecode(query["pbk"] ?? "");
item.ShortId = Utils.UrlDecode(query["sid"] ?? "");
item.SpiderX = Utils.UrlDecode(query["spx"] ?? "");
item.AllowInsecure = (query["allowInsecure"] ?? "") == "1" ? "true" : "";
item.Network = query["type"] ?? nameof(ETransport.tcp);
switch (item.Network)
{
case nameof(ETransport.tcp):
item.HeaderType = query["headerType"] ?? Global.None;
item.RequestHost = Utils.UrlDecode(query["host"] ?? "");
break;
case nameof(ETransport.kcp):
item.HeaderType = query["headerType"] ?? Global.None;
item.Path = Utils.UrlDecode(query["seed"] ?? "");
break;
case nameof(ETransport.ws):
case nameof(ETransport.httpupgrade):
item.RequestHost = Utils.UrlDecode(query["host"] ?? "");
item.Path = Utils.UrlDecode(query["path"] ?? "/");
break;
case nameof(ETransport.xhttp):
item.RequestHost = Utils.UrlDecode(query["host"] ?? "");
item.Path = Utils.UrlDecode(query["path"] ?? "/");
item.HeaderType = Utils.UrlDecode(query["mode"] ?? "");
item.Extra = Utils.UrlDecode(query["extra"] ?? "");
break;
case nameof(ETransport.http):
case nameof(ETransport.h2):
item.Network = nameof(ETransport.h2);
item.RequestHost = Utils.UrlDecode(query["host"] ?? "");
item.Path = Utils.UrlDecode(query["path"] ?? "/");
break;
case nameof(ETransport.quic):
item.HeaderType = query["headerType"] ?? Global.None;
item.RequestHost = query["quicSecurity"] ?? Global.None;
item.Path = Utils.UrlDecode(query["key"] ?? "");
break;
case nameof(ETransport.grpc):
item.RequestHost = Utils.UrlDecode(query["authority"] ?? "");
item.Path = Utils.UrlDecode(query["serviceName"] ?? "");
item.HeaderType = Utils.UrlDecode(query["mode"] ?? Global.GrpcGunMode);
break;
default:
break;
}
return 0;
}
protected static bool Contains(string str, params string[] s)
{
foreach (var item in s)
{
if (str.Contains(item, StringComparison.OrdinalIgnoreCase))
return true;
}
return false;
}
protected static string WriteAllText(string strData, string ext = "json")
{
var fileName = Utils.GetTempPath($"{Utils.GetGuid(false)}.{ext}");
File.WriteAllText(fileName, strData);
return fileName;
}
protected static string ToUri(EConfigType eConfigType, string address, object port, string userInfo, Dictionary<string, string>? dicQuery, string? remark)
{
var query = dicQuery != null
? ("?" + string.Join("&", dicQuery.Select(x => x.Key + "=" + x.Value).ToArray()))
: string.Empty;
var url = $"{Utils.UrlEncode(userInfo)}@{GetIpv6(address)}:{port}";
return $"{Global.ProtocolShares[eConfigType]}{url}{query}{remark}";
}
}
}

View File

@@ -0,0 +1,23 @@
namespace ServiceLib.Handler.Fmt
{
public class ClashFmt : BaseFmt
{
public static ProfileItem? ResolveFull(string strData, string? subRemarks)
{
if (Contains(strData, "port", "socks-port", "proxies"))
{
var fileName = WriteAllText(strData, "yaml");
var profileItem = new ProfileItem
{
CoreType = ECoreType.mihomo,
Address = fileName,
Remarks = subRemarks ?? "clash_custom"
};
return profileItem;
}
return null;
}
}
}

View File

@@ -0,0 +1,92 @@
namespace ServiceLib.Handler.Fmt
{
public class FmtHandler
{
private static readonly string _tag = "FmtHandler";
public static string? GetShareUri(ProfileItem item)
{
try
{
var url = item.ConfigType switch
{
EConfigType.VMess => VmessFmt.ToUri(item),
EConfigType.Shadowsocks => ShadowsocksFmt.ToUri(item),
EConfigType.SOCKS => SocksFmt.ToUri(item),
EConfigType.Trojan => TrojanFmt.ToUri(item),
EConfigType.VLESS => VLESSFmt.ToUri(item),
EConfigType.Hysteria2 => Hysteria2Fmt.ToUri(item),
EConfigType.TUIC => TuicFmt.ToUri(item),
EConfigType.WireGuard => WireguardFmt.ToUri(item),
_ => null,
};
return url;
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
return "";
}
}
public static ProfileItem? ResolveConfig(string config, out string msg)
{
msg = ResUI.ConfigurationFormatIncorrect;
try
{
string str = config.TrimEx();
if (Utils.IsNullOrEmpty(str))
{
msg = ResUI.FailedReadConfiguration;
return null;
}
if (str.StartsWith(Global.ProtocolShares[EConfigType.VMess]))
{
return VmessFmt.Resolve(str, out msg);
}
else if (str.StartsWith(Global.ProtocolShares[EConfigType.Shadowsocks]))
{
return ShadowsocksFmt.Resolve(str, out msg);
}
else if (str.StartsWith(Global.ProtocolShares[EConfigType.SOCKS]))
{
return SocksFmt.Resolve(str, out msg);
}
else if (str.StartsWith(Global.ProtocolShares[EConfigType.Trojan]))
{
return TrojanFmt.Resolve(str, out msg);
}
else if (str.StartsWith(Global.ProtocolShares[EConfigType.VLESS]))
{
return VLESSFmt.Resolve(str, out msg);
}
else if (str.StartsWith(Global.ProtocolShares[EConfigType.Hysteria2]) || str.StartsWith(Global.Hysteria2ProtocolShare))
{
return Hysteria2Fmt.Resolve(str, out msg);
}
else if (str.StartsWith(Global.ProtocolShares[EConfigType.TUIC]))
{
return TuicFmt.Resolve(str, out msg);
}
else if (str.StartsWith(Global.ProtocolShares[EConfigType.WireGuard]))
{
return WireguardFmt.Resolve(str, out msg);
}
else
{
msg = ResUI.NonvmessOrssProtocol;
return null;
}
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
msg = ResUI.Incorrectconfiguration;
return null;
}
}
}
}

View File

@@ -0,0 +1,96 @@
namespace ServiceLib.Handler.Fmt
{
public class Hysteria2Fmt : BaseFmt
{
public static ProfileItem? Resolve(string str, out string msg)
{
msg = ResUI.ConfigurationFormatIncorrect;
ProfileItem item = new()
{
ConfigType = EConfigType.Hysteria2
};
var url = Utils.TryUri(str);
if (url == null)
return null;
item.Address = url.IdnHost;
item.Port = url.Port;
item.Remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
item.Id = Utils.UrlDecode(url.UserInfo);
var query = Utils.ParseQueryString(url.Query);
ResolveStdTransport(query, ref item);
item.Path = Utils.UrlDecode(query["obfs-password"] ?? "");
item.AllowInsecure = (query["insecure"] ?? "") == "1" ? "true" : "false";
return item;
}
public static string? ToUri(ProfileItem? item)
{
if (item == null)
return null;
string url = string.Empty;
string remark = string.Empty;
if (Utils.IsNotEmpty(item.Remarks))
{
remark = "#" + Utils.UrlEncode(item.Remarks);
}
var dicQuery = new Dictionary<string, string>();
if (Utils.IsNotEmpty(item.Sni))
{
dicQuery.Add("sni", item.Sni);
}
if (Utils.IsNotEmpty(item.Alpn))
{
dicQuery.Add("alpn", Utils.UrlEncode(item.Alpn));
}
if (Utils.IsNotEmpty(item.Path))
{
dicQuery.Add("obfs", "salamander");
dicQuery.Add("obfs-password", Utils.UrlEncode(item.Path));
}
dicQuery.Add("insecure", item.AllowInsecure.ToLower() == "true" ? "1" : "0");
return ToUri(EConfigType.Hysteria2, item.Address, item.Port, item.Id, dicQuery, remark);
}
public static ProfileItem? ResolveFull(string strData, string? subRemarks)
{
if (Contains(strData, "server", "up", "down", "listen", "<html>", "<body>"))
{
var fileName = WriteAllText(strData);
var profileItem = new ProfileItem
{
CoreType = ECoreType.hysteria,
Address = fileName,
Remarks = subRemarks ?? "hysteria_custom"
};
return profileItem;
}
return null;
}
public static ProfileItem? ResolveFull2(string strData, string? subRemarks)
{
if (Contains(strData, "server", "auth", "up", "down", "listen"))
{
var fileName = WriteAllText(strData);
var profileItem = new ProfileItem
{
CoreType = ECoreType.hysteria2,
Address = fileName,
Remarks = subRemarks ?? "hysteria2_custom"
};
return profileItem;
}
return null;
}
}
}

View File

@@ -0,0 +1,23 @@
namespace ServiceLib.Handler.Fmt
{
public class NaiveproxyFmt : BaseFmt
{
public static ProfileItem? ResolveFull(string strData, string? subRemarks)
{
if (Contains(strData, "listen", "proxy", "<html>", "<body>"))
{
var fileName = WriteAllText(strData);
var profileItem = new ProfileItem
{
CoreType = ECoreType.naiveproxy,
Address = fileName,
Remarks = subRemarks ?? "naiveproxy_custom"
};
return profileItem;
}
return null;
}
}
}

View File

@@ -0,0 +1,174 @@
using System.Text.RegularExpressions;
namespace ServiceLib.Handler.Fmt
{
public class ShadowsocksFmt : BaseFmt
{
public static ProfileItem? Resolve(string str, out string msg)
{
msg = ResUI.ConfigurationFormatIncorrect;
ProfileItem? item;
item = ResolveSSLegacy(str) ?? ResolveSip002(str);
if (item == null)
{
return null;
}
if (item.Address.Length == 0 || item.Port == 0 || item.Security.Length == 0 || item.Id.Length == 0)
{
return null;
}
item.ConfigType = EConfigType.Shadowsocks;
return item;
}
public static string? ToUri(ProfileItem? item)
{
if (item == null)
return null;
string url = string.Empty;
string remark = string.Empty;
if (Utils.IsNotEmpty(item.Remarks))
{
remark = "#" + Utils.UrlEncode(item.Remarks);
}
//url = string.Format("{0}:{1}@{2}:{3}",
// item.security,
// item.id,
// item.address,
// item.port);
//url = Utile.Base64Encode(url);
//new Sip002
var pw = Utils.Base64Encode($"{item.Security}:{item.Id}");
return ToUri(EConfigType.Shadowsocks, item.Address, item.Port, pw, null, remark);
}
private static readonly Regex UrlFinder = new(@"ss://(?<base64>[A-Za-z0-9+-/=_]+)(?:#(?<tag>\S+))?", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex DetailsParser = new(@"^((?<method>.+?):(?<password>.*)@(?<hostname>.+?):(?<port>\d+?))$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static ProfileItem? ResolveSSLegacy(string result)
{
var match = UrlFinder.Match(result);
if (!match.Success)
return null;
ProfileItem item = new();
var base64 = match.Groups["base64"].Value.TrimEnd('/');
var tag = match.Groups["tag"].Value;
if (Utils.IsNotEmpty(tag))
{
item.Remarks = Utils.UrlDecode(tag);
}
Match details;
try
{
details = DetailsParser.Match(Utils.Base64Decode(base64));
}
catch (FormatException)
{
return null;
}
if (!details.Success)
return null;
item.Security = details.Groups["method"].Value;
item.Id = details.Groups["password"].Value;
item.Address = details.Groups["hostname"].Value;
item.Port = Utils.ToInt(details.Groups["port"].Value);
return item;
}
private static ProfileItem? ResolveSip002(string result)
{
var parsedUrl = Utils.TryUri(result);
if (parsedUrl == null)
return null;
ProfileItem item = new()
{
Remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped),
Address = parsedUrl.IdnHost,
Port = parsedUrl.Port,
};
var rawUserInfo = Utils.UrlDecode(parsedUrl.UserInfo);
//2022-blake3
if (rawUserInfo.Contains(':'))
{
string[] userInfoParts = rawUserInfo.Split(new[] { ':' }, 2);
if (userInfoParts.Length != 2)
{
return null;
}
item.Security = userInfoParts.First();
item.Id = Utils.UrlDecode(userInfoParts.Last());
}
else
{
// parse base64 UserInfo
string userInfo = Utils.Base64Decode(rawUserInfo);
string[] userInfoParts = userInfo.Split(new[] { ':' }, 2);
if (userInfoParts.Length != 2)
{
return null;
}
item.Security = userInfoParts.First();
item.Id = userInfoParts.Last();
}
var queryParameters = Utils.ParseQueryString(parsedUrl.Query);
if (queryParameters["plugin"] != null)
{
//obfs-host exists
var obfsHost = queryParameters["plugin"]?.Split(';').FirstOrDefault(t => t.Contains("obfs-host"));
if (queryParameters["plugin"].Contains("obfs=http") && Utils.IsNotEmpty(obfsHost))
{
obfsHost = obfsHost?.Replace("obfs-host=", "");
item.Network = Global.DefaultNetwork;
item.HeaderType = Global.TcpHeaderHttp;
item.RequestHost = obfsHost ?? "";
}
else
{
return null;
}
}
return item;
}
public static List<ProfileItem>? ResolveSip008(string result)
{
//SsSIP008
var lstSsServer = JsonUtils.Deserialize<List<SsServer>>(result);
if (lstSsServer?.Count <= 0)
{
var ssSIP008 = JsonUtils.Deserialize<SsSIP008>(result);
if (ssSIP008?.servers?.Count > 0)
{
lstSsServer = ssSIP008.servers;
}
}
if (lstSsServer?.Count > 0)
{
List<ProfileItem> lst = [];
foreach (var it in lstSsServer)
{
var ssItem = new ProfileItem()
{
Remarks = it.remarks,
Security = it.method,
Id = it.password,
Address = it.server,
Port = Utils.ToInt(it.server_port)
};
lst.Add(ssItem);
}
return lst;
}
return null;
}
}
}

View File

@@ -0,0 +1,55 @@
namespace ServiceLib.Handler.Fmt
{
public class SingboxFmt : BaseFmt
{
public static List<ProfileItem>? ResolveFullArray(string strData, string? subRemarks)
{
var configObjects = JsonUtils.Deserialize<Object[]>(strData);
if (configObjects != null && configObjects.Length > 0)
{
List<ProfileItem> lstResult = [];
foreach (var configObject in configObjects)
{
var objectString = JsonUtils.Serialize(configObject);
var singboxCon = JsonUtils.Deserialize<SingboxConfig>(objectString);
if (singboxCon?.inbounds?.Count > 0
&& singboxCon.outbounds?.Count > 0
&& singboxCon.route != null)
{
var fileName = WriteAllText(objectString);
var profileIt = new ProfileItem
{
CoreType = ECoreType.sing_box,
Address = fileName,
Remarks = subRemarks ?? "singbox_custom",
};
lstResult.Add(profileIt);
}
}
return lstResult;
}
return null;
}
public static ProfileItem? ResolveFull(string strData, string? subRemarks)
{
var singboxConfig = JsonUtils.Deserialize<SingboxConfig>(strData);
if (singboxConfig?.inbounds?.Count > 0
&& singboxConfig.outbounds?.Count > 0
&& singboxConfig.route != null)
{
var fileName = WriteAllText(strData);
var profileItem = new ProfileItem
{
CoreType = ECoreType.sing_box,
Address = fileName,
Remarks = subRemarks ?? "singbox_custom"
};
return profileItem;
}
return null;
}
}
}

View File

@@ -0,0 +1,113 @@
namespace ServiceLib.Handler.Fmt
{
public class SocksFmt : BaseFmt
{
public static ProfileItem? Resolve(string str, out string msg)
{
msg = ResUI.ConfigurationFormatIncorrect;
var item = ResolveSocksNew(str) ?? ResolveSocks(str);
if (item == null)
{
return null;
}
if (item.Address.Length == 0 || item.Port == 0)
{
return null;
}
item.ConfigType = EConfigType.SOCKS;
return item;
}
public static string? ToUri(ProfileItem? item)
{
if (item == null)
return null;
var url = string.Empty;
var remark = string.Empty;
if (Utils.IsNotEmpty(item.Remarks))
{
remark = "#" + Utils.UrlEncode(item.Remarks);
}
//new
var pw = Utils.Base64Encode($"{item.Security}:{item.Id}");
return ToUri(EConfigType.SOCKS, item.Address, item.Port, pw, null, remark);
}
private static ProfileItem? ResolveSocks(string result)
{
ProfileItem item = new()
{
ConfigType = EConfigType.SOCKS
};
result = result[Global.ProtocolShares[EConfigType.SOCKS].Length..];
//remark
var indexRemark = result.IndexOf("#");
if (indexRemark > 0)
{
try
{
item.Remarks = Utils.UrlDecode(result.Substring(indexRemark + 1, result.Length - indexRemark - 1));
}
catch { }
result = result[..indexRemark];
}
//part decode
var indexS = result.IndexOf("@");
if (indexS > 0)
{
}
else
{
result = Utils.Base64Decode(result);
}
var arr1 = result.Split('@');
if (arr1.Length != 2)
{
return null;
}
var arr21 = arr1.First().Split(':');
var indexPort = arr1.Last().LastIndexOf(":");
if (arr21.Length != 2 || indexPort < 0)
{
return null;
}
item.Address = arr1[1][..indexPort];
item.Port = Utils.ToInt(arr1[1][(indexPort + 1)..]);
item.Security = arr21.First();
item.Id = arr21[1];
return item;
}
private static ProfileItem? ResolveSocksNew(string result)
{
var parsedUrl = Utils.TryUri(result);
if (parsedUrl == null)
return null;
ProfileItem item = new()
{
Remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped),
Address = parsedUrl.IdnHost,
Port = parsedUrl.Port,
};
// parse base64 UserInfo
var rawUserInfo = Utils.UrlDecode(parsedUrl.UserInfo);
var userInfo = Utils.Base64Decode(rawUserInfo);
var userInfoParts = userInfo.Split([':'], 2);
if (userInfoParts.Length == 2)
{
item.Security = userInfoParts.First();
item.Id = userInfoParts[1];
}
return item;
}
}
}

View File

@@ -0,0 +1,46 @@
namespace ServiceLib.Handler.Fmt
{
public class TrojanFmt : BaseFmt
{
public static ProfileItem? Resolve(string str, out string msg)
{
msg = ResUI.ConfigurationFormatIncorrect;
ProfileItem item = new()
{
ConfigType = EConfigType.Trojan
};
var url = Utils.TryUri(str);
if (url == null)
return null;
item.Address = url.IdnHost;
item.Port = url.Port;
item.Remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
item.Id = Utils.UrlDecode(url.UserInfo);
var query = Utils.ParseQueryString(url.Query);
ResolveStdTransport(query, ref item);
return item;
}
public static string? ToUri(ProfileItem? item)
{
if (item == null)
return null;
string url = string.Empty;
string remark = string.Empty;
if (Utils.IsNotEmpty(item.Remarks))
{
remark = "#" + Utils.UrlEncode(item.Remarks);
}
var dicQuery = new Dictionary<string, string>();
GetStdTransport(item, null, ref dicQuery);
return ToUri(EConfigType.Trojan, item.Address, item.Port, item.Id, dicQuery, remark);
}
}
}

View File

@@ -0,0 +1,61 @@
namespace ServiceLib.Handler.Fmt
{
public class TuicFmt : BaseFmt
{
public static ProfileItem? Resolve(string str, out string msg)
{
msg = ResUI.ConfigurationFormatIncorrect;
ProfileItem item = new()
{
ConfigType = EConfigType.TUIC
};
var url = Utils.TryUri(str);
if (url == null)
return null;
item.Address = url.IdnHost;
item.Port = url.Port;
item.Remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
var rawUserInfo = Utils.UrlDecode(url.UserInfo);
var userInfoParts = rawUserInfo.Split(new[] { ':' }, 2);
if (userInfoParts.Length == 2)
{
item.Id = userInfoParts.First();
item.Security = userInfoParts.Last();
}
var query = Utils.ParseQueryString(url.Query);
ResolveStdTransport(query, ref item);
item.HeaderType = query["congestion_control"] ?? "";
return item;
}
public static string? ToUri(ProfileItem? item)
{
if (item == null)
return null;
string url = string.Empty;
string remark = string.Empty;
if (Utils.IsNotEmpty(item.Remarks))
{
remark = "#" + Utils.UrlEncode(item.Remarks);
}
var dicQuery = new Dictionary<string, string>();
if (Utils.IsNotEmpty(item.Sni))
{
dicQuery.Add("sni", item.Sni);
}
if (Utils.IsNotEmpty(item.Alpn))
{
dicQuery.Add("alpn", Utils.UrlEncode(item.Alpn));
}
dicQuery.Add("congestion_control", item.HeaderType);
return ToUri(EConfigType.TUIC, item.Address, item.Port, $"{item.Id}:{item.Security}", dicQuery, remark);
}
}
}

View File

@@ -0,0 +1,56 @@
namespace ServiceLib.Handler.Fmt
{
public class V2rayFmt : BaseFmt
{
public static List<ProfileItem>? ResolveFullArray(string strData, string? subRemarks)
{
var configObjects = JsonUtils.Deserialize<Object[]>(strData);
if (configObjects != null && configObjects.Length > 0)
{
List<ProfileItem> lstResult = [];
foreach (var configObject in configObjects)
{
var objectString = JsonUtils.Serialize(configObject);
var v2rayCon = JsonUtils.Deserialize<V2rayConfig>(objectString);
if (v2rayCon?.inbounds?.Count > 0
&& v2rayCon.outbounds?.Count > 0
&& v2rayCon.routing != null)
{
var fileName = WriteAllText(objectString);
var profileIt = new ProfileItem
{
CoreType = ECoreType.Xray,
Address = fileName,
Remarks = v2rayCon.remarks ?? subRemarks ?? "v2ray_custom",
};
lstResult.Add(profileIt);
}
}
return lstResult;
}
return null;
}
public static ProfileItem? ResolveFull(string strData, string? subRemarks)
{
var v2rayConfig = JsonUtils.Deserialize<V2rayConfig>(strData);
if (v2rayConfig?.inbounds?.Count > 0
&& v2rayConfig.outbounds?.Count > 0
&& v2rayConfig.routing != null)
{
var fileName = WriteAllText(strData);
var profileItem = new ProfileItem
{
CoreType = ECoreType.Xray,
Address = fileName,
Remarks = v2rayConfig.remarks ?? subRemarks ?? "v2ray_custom"
};
return profileItem;
}
return null;
}
}
}

View File

@@ -0,0 +1,57 @@
namespace ServiceLib.Handler.Fmt
{
public class VLESSFmt : BaseFmt
{
public static ProfileItem? Resolve(string str, out string msg)
{
msg = ResUI.ConfigurationFormatIncorrect;
ProfileItem item = new()
{
ConfigType = EConfigType.VLESS,
Security = Global.None
};
var url = Utils.TryUri(str);
if (url == null)
return null;
item.Address = url.IdnHost;
item.Port = url.Port;
item.Remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
item.Id = Utils.UrlDecode(url.UserInfo);
var query = Utils.ParseQueryString(url.Query);
item.Security = query["encryption"] ?? Global.None;
item.StreamSecurity = query["security"] ?? "";
ResolveStdTransport(query, ref item);
return item;
}
public static string? ToUri(ProfileItem? item)
{
if (item == null)
return null;
string url = string.Empty;
string remark = string.Empty;
if (Utils.IsNotEmpty(item.Remarks))
{
remark = "#" + Utils.UrlEncode(item.Remarks);
}
var dicQuery = new Dictionary<string, string>();
if (Utils.IsNotEmpty(item.Security))
{
dicQuery.Add("encryption", item.Security);
}
else
{
dicQuery.Add("encryption", Global.None);
}
GetStdTransport(item, Global.None, ref dicQuery);
return ToUri(EConfigType.VLESS, item.Address, item.Port, item.Id, dicQuery, remark);
}
}
}

View File

@@ -0,0 +1,124 @@
namespace ServiceLib.Handler.Fmt
{
public class VmessFmt : BaseFmt
{
public static ProfileItem? Resolve(string str, out string msg)
{
msg = ResUI.ConfigurationFormatIncorrect;
ProfileItem? item;
if (str.IndexOf('?') > 0 && str.IndexOf('&') > 0)
{
item = ResolveStdVmess(str);
}
else
{
item = ResolveVmess(str, out msg);
}
return item;
}
public static string? ToUri(ProfileItem? item)
{
if (item == null)
return null;
string url = string.Empty;
VmessQRCode vmessQRCode = new()
{
v = item.ConfigVersion,
ps = item.Remarks.TrimEx(),
add = item.Address,
port = item.Port,
id = item.Id,
aid = item.AlterId,
scy = item.Security,
net = item.Network,
type = item.HeaderType,
host = item.RequestHost,
path = item.Path,
tls = item.StreamSecurity,
sni = item.Sni,
alpn = item.Alpn,
fp = item.Fingerprint
};
url = JsonUtils.Serialize(vmessQRCode);
url = Utils.Base64Encode(url);
url = $"{Global.ProtocolShares[EConfigType.VMess]}{url}";
return url;
}
private static ProfileItem? ResolveVmess(string result, out string msg)
{
msg = string.Empty;
var item = new ProfileItem
{
ConfigType = EConfigType.VMess
};
result = result[Global.ProtocolShares[EConfigType.VMess].Length..];
result = Utils.Base64Decode(result);
VmessQRCode? vmessQRCode = JsonUtils.Deserialize<VmessQRCode>(result);
if (vmessQRCode == null)
{
msg = ResUI.FailedConversionConfiguration;
return null;
}
item.Network = Global.DefaultNetwork;
item.HeaderType = Global.None;
item.ConfigVersion = vmessQRCode.v;
item.Remarks = Utils.ToString(vmessQRCode.ps);
item.Address = Utils.ToString(vmessQRCode.add);
item.Port = vmessQRCode.port;
item.Id = Utils.ToString(vmessQRCode.id);
item.AlterId = vmessQRCode.aid;
item.Security = Utils.ToString(vmessQRCode.scy);
item.Security = Utils.IsNotEmpty(vmessQRCode.scy) ? vmessQRCode.scy : Global.DefaultSecurity;
if (Utils.IsNotEmpty(vmessQRCode.net))
{
item.Network = vmessQRCode.net;
}
if (Utils.IsNotEmpty(vmessQRCode.type))
{
item.HeaderType = vmessQRCode.type;
}
item.RequestHost = Utils.ToString(vmessQRCode.host);
item.Path = Utils.ToString(vmessQRCode.path);
item.StreamSecurity = Utils.ToString(vmessQRCode.tls);
item.Sni = Utils.ToString(vmessQRCode.sni);
item.Alpn = Utils.ToString(vmessQRCode.alpn);
item.Fingerprint = Utils.ToString(vmessQRCode.fp);
return item;
}
public static ProfileItem? ResolveStdVmess(string str)
{
ProfileItem item = new()
{
ConfigType = EConfigType.VMess,
Security = "auto"
};
var url = Utils.TryUri(str);
if (url == null)
return null;
item.Address = url.IdnHost;
item.Port = url.Port;
item.Remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
item.Id = Utils.UrlDecode(url.UserInfo);
var query = Utils.ParseQueryString(url.Query);
ResolveStdTransport(query, ref item);
return item;
}
}
}

View File

@@ -0,0 +1,65 @@
namespace ServiceLib.Handler.Fmt
{
public class WireguardFmt : BaseFmt
{
public static ProfileItem? Resolve(string str, out string msg)
{
msg = ResUI.ConfigurationFormatIncorrect;
ProfileItem item = new()
{
ConfigType = EConfigType.WireGuard
};
var url = Utils.TryUri(str);
if (url == null)
return null;
item.Address = url.IdnHost;
item.Port = url.Port;
item.Remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
item.Id = Utils.UrlDecode(url.UserInfo);
var query = Utils.ParseQueryString(url.Query);
item.PublicKey = Utils.UrlDecode(query["publickey"] ?? "");
item.Path = Utils.UrlDecode(query["reserved"] ?? "");
item.RequestHost = Utils.UrlDecode(query["address"] ?? "");
item.ShortId = Utils.UrlDecode(query["mtu"] ?? "");
return item;
}
public static string? ToUri(ProfileItem? item)
{
if (item == null)
return null;
string url = string.Empty;
string remark = string.Empty;
if (Utils.IsNotEmpty(item.Remarks))
{
remark = "#" + Utils.UrlEncode(item.Remarks);
}
var dicQuery = new Dictionary<string, string>();
if (Utils.IsNotEmpty(item.PublicKey))
{
dicQuery.Add("publickey", Utils.UrlEncode(item.PublicKey));
}
if (Utils.IsNotEmpty(item.Path))
{
dicQuery.Add("reserved", Utils.UrlEncode(item.Path));
}
if (Utils.IsNotEmpty(item.RequestHost))
{
dicQuery.Add("address", Utils.UrlEncode(item.RequestHost));
}
if (Utils.IsNotEmpty(item.ShortId))
{
dicQuery.Add("mtu", Utils.UrlEncode(item.ShortId));
}
return ToUri(EConfigType.WireGuard, item.Address, item.Port, item.Id, dicQuery, remark);
}
}
}

View File

@@ -0,0 +1,44 @@
using ReactiveUI;
namespace ServiceLib.Handler
{
public class NoticeHandler
{
private static readonly Lazy<NoticeHandler> _instance = new(() => new());
public static NoticeHandler Instance => _instance.Value;
public void Enqueue(string? content)
{
if (content.IsNullOrEmpty())
{
return;
}
MessageBus.Current.SendMessage(content, EMsgCommand.SendSnackMsg.ToString());
}
public void SendMessage(string? content)
{
if (content.IsNullOrEmpty())
{
return;
}
MessageBus.Current.SendMessage(content, EMsgCommand.SendMsgView.ToString());
}
public void SendMessageEx(string? content)
{
if (content.IsNullOrEmpty())
{
return;
}
content = $"{DateTime.Now:yyyy/MM/dd HH:mm:ss} {content}";
SendMessage(content);
}
public void SendMessageAndEnqueue(string? msg)
{
Enqueue(msg);
SendMessage(msg);
}
}
}

View File

@@ -0,0 +1,106 @@
using System.Net.Sockets;
using System.Text;
namespace ServiceLib.Handler
{
public class PacHandler
{
private static string _configPath;
private static int _httpPort;
private static int _pacPort;
private static TcpListener? _tcpListener;
private static byte[] _writeContent;
private static bool _isRunning;
private static bool _needRestart = true;
public static async Task Start(string configPath, int httpPort, int pacPort)
{
_needRestart = (configPath != _configPath || httpPort != _httpPort || pacPort != _pacPort || !_isRunning);
_configPath = configPath;
_httpPort = httpPort;
_pacPort = pacPort;
await InitText();
if (_needRestart)
{
Stop();
RunListener();
}
}
private static async Task InitText()
{
var path = Path.Combine(_configPath, "pac.txt");
if (!File.Exists(path))
{
var pac = EmbedUtils.GetEmbedText(Global.PacFileName);
await File.AppendAllTextAsync(path, pac);
}
var pacText =
(await File.ReadAllTextAsync(path)).Replace("__PROXY__", $"PROXY 127.0.0.1:{_httpPort};DIRECT;");
var sb = new StringBuilder();
sb.AppendLine("HTTP/1.0 200 OK");
sb.AppendLine("Content-type:application/x-ns-proxy-autoconfig");
sb.AppendLine("Connection:close");
sb.AppendLine("Content-Length:" + Encoding.UTF8.GetByteCount(pacText));
sb.AppendLine();
sb.Append(pacText);
_writeContent = Encoding.UTF8.GetBytes(sb.ToString());
}
private static void RunListener()
{
_tcpListener = TcpListener.Create(_pacPort);
_isRunning = true;
_tcpListener.Start();
Task.Factory.StartNew(async () =>
{
while (_isRunning)
{
try
{
if (!_tcpListener.Pending())
{
await Task.Delay(10);
continue;
}
var client = await _tcpListener.AcceptTcpClientAsync();
await Task.Run(() => { WriteContent(client); });
}
catch
{
// ignored
}
}
}, TaskCreationOptions.LongRunning);
}
private static void WriteContent(TcpClient client)
{
var stream = client.GetStream();
stream.Write(_writeContent, 0, _writeContent.Length);
stream.Flush();
}
public static void Stop()
{
if (_tcpListener == null)
return;
try
{
_isRunning = false;
_tcpListener.Stop();
_tcpListener = null;
}
catch
{
// ignored
}
}
}
}

View File

@@ -0,0 +1,183 @@
using System.Collections.Concurrent;
//using System.Reactive.Linq;
namespace ServiceLib.Handler
{
public class ProfileExHandler
{
private static readonly Lazy<ProfileExHandler> _instance = new(() => new());
private ConcurrentBag<ProfileExItem> _lstProfileEx = [];
private Queue<string> _queIndexIds = new();
public static ProfileExHandler Instance => _instance.Value;
private static readonly string _tag = "ProfileExHandler";
public ProfileExHandler()
{
//Init();
}
public async Task Init()
{
await InitData();
_ = Task.Run(async () =>
{
while (true)
{
await Task.Delay(1000 * 600);
await SaveQueueIndexIds();
}
});
}
public async Task<ConcurrentBag<ProfileExItem>> GetProfileExs()
{
return await Task.FromResult(_lstProfileEx);
}
private async Task InitData()
{
await SQLiteHelper.Instance.ExecuteAsync($"delete from ProfileExItem where indexId not in ( select indexId from ProfileItem )");
_lstProfileEx = new(await SQLiteHelper.Instance.TableAsync<ProfileExItem>().ToListAsync());
}
private void IndexIdEnqueue(string indexId)
{
if (Utils.IsNotEmpty(indexId) && !_queIndexIds.Contains(indexId))
{
_queIndexIds.Enqueue(indexId);
}
}
private async Task SaveQueueIndexIds()
{
var cnt = _queIndexIds.Count;
if (cnt > 0)
{
var lstExists = await SQLiteHelper.Instance.TableAsync<ProfileExItem>().ToListAsync();
List<ProfileExItem> lstInserts = [];
List<ProfileExItem> lstUpdates = [];
for (int i = 0; i < cnt; i++)
{
var id = _queIndexIds.Dequeue();
var item = lstExists.FirstOrDefault(t => t.IndexId == id);
var itemNew = _lstProfileEx?.FirstOrDefault(t => t.IndexId == id);
if (itemNew is null)
{
continue;
}
if (item is not null)
{
lstUpdates.Add(itemNew);
}
else
{
lstInserts.Add(itemNew);
}
}
try
{
if (lstInserts.Count() > 0)
await SQLiteHelper.Instance.InsertAllAsync(lstInserts);
if (lstUpdates.Count() > 0)
await SQLiteHelper.Instance.UpdateAllAsync(lstUpdates);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
}
private void AddProfileEx(string indexId, ref ProfileExItem? profileEx)
{
profileEx = new()
{
IndexId = indexId,
Delay = 0,
Speed = 0,
Sort = 0
};
_lstProfileEx.Add(profileEx);
IndexIdEnqueue(indexId);
}
public async Task ClearAll()
{
await SQLiteHelper.Instance.ExecuteAsync($"delete from ProfileExItem ");
_lstProfileEx = new();
}
public async Task SaveTo()
{
try
{
await SaveQueueIndexIds();
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
public void SetTestDelay(string indexId, string delayVal)
{
var profileEx = _lstProfileEx.FirstOrDefault(t => t.IndexId == indexId);
if (profileEx == null)
{
AddProfileEx(indexId, ref profileEx);
}
int.TryParse(delayVal, out int delay);
profileEx.Delay = delay;
IndexIdEnqueue(indexId);
}
public void SetTestSpeed(string indexId, string speedVal)
{
var profileEx = _lstProfileEx.FirstOrDefault(t => t.IndexId == indexId);
if (profileEx == null)
{
AddProfileEx(indexId, ref profileEx);
}
decimal.TryParse(speedVal, out decimal speed);
profileEx.Speed = speed;
IndexIdEnqueue(indexId);
}
public void SetSort(string indexId, int sort)
{
var profileEx = _lstProfileEx.FirstOrDefault(t => t.IndexId == indexId);
if (profileEx == null)
{
AddProfileEx(indexId, ref profileEx);
}
profileEx.Sort = sort;
IndexIdEnqueue(indexId);
}
public int GetSort(string indexId)
{
var profileEx = _lstProfileEx.FirstOrDefault(t => t.IndexId == indexId);
if (profileEx == null)
{
return 0;
}
return profileEx.Sort;
}
public int GetMaxSort()
{
if (_lstProfileEx.Count <= 0)
{
return 0;
}
return _lstProfileEx.Max(t => t == null ? 0 : t.Sort);
}
}
}

View File

@@ -0,0 +1,164 @@
namespace ServiceLib.Handler
{
public class StatisticsHandler
{
private static readonly Lazy<StatisticsHandler> instance = new(() => new());
public static StatisticsHandler Instance => instance.Value;
private Config _config;
private ServerStatItem? _serverStatItem;
private List<ServerStatItem> _lstServerStat;
private Action<ServerSpeedItem>? _updateFunc;
private StatisticsXrayService? _statisticsXray;
private StatisticsSingboxService? _statisticsSingbox;
private static readonly string _tag = "StatisticsHandler";
public List<ServerStatItem> ServerStat => _lstServerStat;
public async Task Init(Config config, Action<ServerSpeedItem> updateFunc)
{
_config = config;
_updateFunc = updateFunc;
if (config.GuiItem.EnableStatistics || _config.GuiItem.DisplayRealTimeSpeed)
{
await InitData();
_statisticsXray = new StatisticsXrayService(config, UpdateServerStatHandler);
_statisticsSingbox = new StatisticsSingboxService(config, UpdateServerStatHandler);
}
}
public void Close()
{
try
{
_statisticsXray?.Close();
_statisticsSingbox?.Close();
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
public async Task ClearAllServerStatistics()
{
await SQLiteHelper.Instance.ExecuteAsync($"delete from ServerStatItem ");
_serverStatItem = null;
_lstServerStat = new();
}
public async Task SaveTo()
{
try
{
if (_lstServerStat != null)
{
await SQLiteHelper.Instance.UpdateAllAsync(_lstServerStat);
}
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
public async Task CloneServerStatItem(string indexId, string toIndexId)
{
if (_lstServerStat == null)
{
return;
}
if (indexId == toIndexId)
{
return;
}
var stat = _lstServerStat.FirstOrDefault(t => t.IndexId == indexId);
if (stat == null)
{
return;
}
var toStat = JsonUtils.DeepCopy(stat);
toStat.IndexId = toIndexId;
await SQLiteHelper.Instance.ReplaceAsync(toStat);
_lstServerStat.Add(toStat);
}
private async Task InitData()
{
await SQLiteHelper.Instance.ExecuteAsync($"delete from ServerStatItem where indexId not in ( select indexId from ProfileItem )");
long ticks = DateTime.Now.Date.Ticks;
await SQLiteHelper.Instance.ExecuteAsync($"update ServerStatItem set todayUp = 0,todayDown=0,dateNow={ticks} where dateNow<>{ticks}");
_lstServerStat = await SQLiteHelper.Instance.TableAsync<ServerStatItem>().ToListAsync();
}
private void UpdateServerStatHandler(ServerSpeedItem server)
{
_ = UpdateServerStat(server);
}
private async Task UpdateServerStat(ServerSpeedItem server)
{
await GetServerStatItem(_config.IndexId);
if (_serverStatItem is null)
{
return;
}
if (server.ProxyUp != 0 || server.ProxyDown != 0)
{
_serverStatItem.TodayUp += server.ProxyUp;
_serverStatItem.TodayDown += server.ProxyDown;
_serverStatItem.TotalUp += server.ProxyUp;
_serverStatItem.TotalDown += server.ProxyDown;
}
server.IndexId = _config.IndexId;
server.TodayUp = _serverStatItem.TodayUp;
server.TodayDown = _serverStatItem.TodayDown;
server.TotalUp = _serverStatItem.TotalUp;
server.TotalDown = _serverStatItem.TotalDown;
_updateFunc?.Invoke(server);
}
private async Task GetServerStatItem(string indexId)
{
long ticks = DateTime.Now.Date.Ticks;
if (_serverStatItem != null && _serverStatItem.IndexId != indexId)
{
_serverStatItem = null;
}
if (_serverStatItem == null)
{
_serverStatItem = _lstServerStat.FirstOrDefault(t => t.IndexId == indexId);
if (_serverStatItem == null)
{
_serverStatItem = new ServerStatItem
{
IndexId = indexId,
TotalUp = 0,
TotalDown = 0,
TodayUp = 0,
TodayDown = 0,
DateNow = ticks
};
await SQLiteHelper.Instance.ReplaceAsync(_serverStatItem);
_lstServerStat.Add(_serverStatItem);
}
}
if (_serverStatItem.DateNow != ticks)
{
_serverStatItem.TodayUp = 0;
_serverStatItem.TodayDown = 0;
_serverStatItem.DateNow = ticks;
}
}
}
}

View File

@@ -0,0 +1,202 @@
namespace ServiceLib.Handler.SysProxy
{
public class ProxySettingLinux
{
public static async Task SetProxy(string host, int port, string exceptions)
{
var lstCmd = GetSetCmds(host, port, exceptions);
await ExecCmd(lstCmd);
}
public static async Task UnsetProxy()
{
var lstCmd = GetUnsetCmds();
await ExecCmd(lstCmd);
}
private static async Task ExecCmd(List<CmdItem> lstCmd)
{
foreach (var cmd in lstCmd)
{
if (cmd is null || cmd.Cmd.IsNullOrEmpty() || cmd.Arguments is null)
{
continue;
}
await Task.Delay(10);
await Utils.GetCliWrapOutput(cmd.Cmd, cmd.Arguments);
}
}
private static List<CmdItem> GetSetCmds(string host, int port, string exceptions)
{
var isKde = IsKde(out var configDir);
List<string> lstType = ["", "http", "https", "socks", "ftp"];
List<CmdItem> lstCmd = [];
//GNOME
foreach (var type in lstType)
{
lstCmd.AddRange(GetSetCmd4Gnome(type, host, port));
}
if (exceptions.IsNotEmpty())
{
lstCmd.AddRange(GetSetCmd4Gnome("exceptions", exceptions, 0));
}
if (isKde)
{
foreach (var type in lstType)
{
lstCmd.AddRange(GetSetCmd4Kde(type, host, port, configDir));
}
if (exceptions.IsNotEmpty())
{
lstCmd.AddRange(GetSetCmd4Kde("exceptions", exceptions, 0, configDir));
}
// Notify system to reload
lstCmd.Add(new CmdItem()
{
Cmd = "dbus-send",
Arguments = ["--type=signal", "/KIO/Scheduler", "org.kde.KIO.Scheduler.reparseSlaveConfiguration", "string:''"]
});
}
return lstCmd;
}
private static List<CmdItem> GetUnsetCmds()
{
var isKde = IsKde(out var configDir);
List<CmdItem> lstCmd = [];
//GNOME
lstCmd.Add(new CmdItem()
{
Cmd = "gsettings",
Arguments = ["set", "org.gnome.system.proxy", "mode", "none"]
});
if (isKde)
{
lstCmd.Add(new CmdItem()
{
Cmd = GetKdeVersion(),
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", "ProxyType", "0"]
});
// Notify system to reload
lstCmd.Add(new CmdItem()
{
Cmd = "dbus-send",
Arguments = ["--type=signal", "/KIO/Scheduler", "org.kde.KIO.Scheduler.reparseSlaveConfiguration", "string:''"]
});
}
return lstCmd;
}
private static List<CmdItem> GetSetCmd4Kde(string type, string host, int port, string configDir)
{
List<CmdItem> lstCmd = [];
var cmd = GetKdeVersion();
if (type.IsNullOrEmpty())
{
lstCmd.Add(new()
{
Cmd = cmd,
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", "ProxyType", "1"]
});
}
else if (type == "exceptions")
{
lstCmd.Add(new()
{
Cmd = cmd,
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", "NoProxyFor", host]
});
}
else
{
var type2 = type.Equals("https") ? "http" : type;
lstCmd.Add(new CmdItem()
{
Cmd = cmd,
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", $"{type}Proxy", $"{type2}://{host}:{port}"]
});
}
return lstCmd;
}
private static List<CmdItem> GetSetCmd4Gnome(string type, string host, int port)
{
List<CmdItem> lstCmd = [];
if (type.IsNullOrEmpty())
{
lstCmd.Add(new()
{
Cmd = "gsettings",
Arguments = ["set", "org.gnome.system.proxy", "mode", "manual"]
});
}
else if (type == "exceptions")
{
lstCmd.Add(new()
{
Cmd = "gsettings",
Arguments = ["set", $"org.gnome.system.proxy", "ignore-hosts", JsonUtils.Serialize(host.Split(','), false)]
});
}
else
{
lstCmd.Add(new()
{
Cmd = "gsettings",
Arguments = ["set", $"org.gnome.system.proxy.{type}", "host", host]
});
lstCmd.Add(new()
{
Cmd = "gsettings",
Arguments = ["set", $"org.gnome.system.proxy.{type}", "port", $"{port}"]
});
}
return lstCmd;
}
private static bool IsKde(out string configDir)
{
configDir = "/home";
var desktop = Environment.GetEnvironmentVariable("XDG_CURRENT_DESKTOP");
var desktop2 = Environment.GetEnvironmentVariable("XDG_SESSION_DESKTOP");
var isKde = string.Equals(desktop, "KDE", StringComparison.OrdinalIgnoreCase)
|| string.Equals(desktop, "plasma", StringComparison.OrdinalIgnoreCase)
|| string.Equals(desktop2, "KDE", StringComparison.OrdinalIgnoreCase)
|| string.Equals(desktop2, "plasma", StringComparison.OrdinalIgnoreCase);
if (isKde)
{
var homeDir = Environment.GetEnvironmentVariable("HOME");
if (homeDir != null)
{
configDir = Path.Combine(homeDir, ".config");
}
}
return isKde;
}
private static string GetKdeVersion()
{
var ver = Environment.GetEnvironmentVariable("KDE_SESSION_VERSION") ?? "0";
return ver switch
{
"6" => "kwriteconfig6",
_ => "kwriteconfig5"
};
}
}
}

View File

@@ -0,0 +1,101 @@
namespace ServiceLib.Handler.SysProxy
{
public class ProxySettingOSX
{
/// <summary>
/// 应用接口类型
/// </summary>
private static readonly List<string> LstInterface = ["Ethernet", "Wi-Fi", "Thunderbolt Bridge", "USB 10/100/1000 LAN"];
/// <summary>
/// 代理类型,对应 http,https,socks
/// </summary>
private static readonly List<string> LstTypes = ["setwebproxy", "setsecurewebproxy", "setsocksfirewallproxy"];
public static async Task SetProxy(string host, int port, string exceptions)
{
var lstInterface = await GetListNetworkServices();
var lstCmd = GetSetCmds(lstInterface, host, port, exceptions);
await ExecCmd(lstCmd);
}
public static async Task UnsetProxy()
{
var lstInterface = await GetListNetworkServices();
var lstCmd = GetUnsetCmds(lstInterface);
await ExecCmd(lstCmd);
}
private static async Task ExecCmd(List<CmdItem> lstCmd)
{
foreach (var cmd in lstCmd)
{
if (cmd is null || cmd.Cmd.IsNullOrEmpty() || cmd.Arguments is null)
{
continue;
}
await Task.Delay(10);
await Utils.GetCliWrapOutput(cmd.Cmd, cmd.Arguments);
}
}
private static List<CmdItem> GetSetCmds(List<string> lstInterface, string host, int port, string exceptions)
{
List<CmdItem> lstCmd = [];
foreach (var interf in lstInterface)
{
foreach (var type in LstTypes)
{
lstCmd.Add(new CmdItem()
{
Cmd = "networksetup",
Arguments = [$"-{type}", interf, host, port.ToString()]
});
}
if (exceptions.IsNotEmpty())
{
List<string> args = [$"-setproxybypassdomains", interf];
args.AddRange(exceptions.Split(','));
lstCmd.Add(new CmdItem()
{
Cmd = "networksetup",
Arguments = args
});
}
}
return lstCmd;
}
private static List<CmdItem> GetUnsetCmds(List<string> lstInterface)
{
List<CmdItem> lstCmd = [];
foreach (var interf in lstInterface)
{
foreach (var type in LstTypes)
{
lstCmd.Add(new CmdItem()
{
Cmd = "networksetup",
Arguments = [$"-{type}state", interf, "off"]
});
}
}
return lstCmd;
}
public static async Task<List<string>> GetListNetworkServices()
{
var services = await Utils.GetListNetworkServices();
if (services.IsNullOrEmpty())
{
return LstInterface;
}
var lst = services.Split(Environment.NewLine).Where(t => t.Length > 0 && t.Contains('*') == false);
return lst.ToList();
}
}
}

View File

@@ -0,0 +1,360 @@
using System.Runtime.InteropServices;
using static ServiceLib.Handler.SysProxy.ProxySettingWindows.InternetConnectionOption;
namespace ServiceLib.Handler.SysProxy
{
public class ProxySettingWindows
{
private const string _regPath = @"Software\Microsoft\Windows\CurrentVersion\Internet Settings";
private static bool SetProxyFallback(string? strProxy, string? exceptions, int type)
{
if (type == 1)
{
WindowsUtils.RegWriteValue(_regPath, "ProxyEnable", 0);
WindowsUtils.RegWriteValue(_regPath, "ProxyServer", string.Empty);
WindowsUtils.RegWriteValue(_regPath, "ProxyOverride", string.Empty);
WindowsUtils.RegWriteValue(_regPath, "AutoConfigURL", string.Empty);
}
if (type == 2)
{
WindowsUtils.RegWriteValue(_regPath, "ProxyEnable", 1);
WindowsUtils.RegWriteValue(_regPath, "ProxyServer", strProxy ?? string.Empty);
WindowsUtils.RegWriteValue(_regPath, "ProxyOverride", exceptions ?? string.Empty);
WindowsUtils.RegWriteValue(_regPath, "AutoConfigURL", string.Empty);
}
else if (type == 4)
{
WindowsUtils.RegWriteValue(_regPath, "ProxyEnable", 0);
WindowsUtils.RegWriteValue(_regPath, "ProxyServer", string.Empty);
WindowsUtils.RegWriteValue(_regPath, "ProxyOverride", string.Empty);
WindowsUtils.RegWriteValue(_regPath, "AutoConfigURL", strProxy ?? string.Empty);
}
return true;
}
/// <summary>
// set to use no proxy
/// </summary>
/// <exception cref="ApplicationException">Error message with win32 error code</exception>
public static bool UnsetProxy()
{
return SetProxy(null, null, 1);
}
/// <summary>
/// Set system proxy settings
/// </summary>
/// <param name="strProxy"> proxy address</param>
/// <param name="exceptions">exception addresses that do not use proxy</param>
/// <param name="type">type of proxy defined in PerConnFlags
/// PROXY_TYPE_DIRECT = 0x00000001, // direct connection (no proxy)
/// PROXY_TYPE_PROXY = 0x00000002, // via named proxy
/// PROXY_TYPE_AUTO_PROXY_URL = 0x00000004, // autoproxy script URL
/// PROXY_TYPE_AUTO_DETECT = 0x00000008 // use autoproxy detection
/// </param>
/// <exception cref="ApplicationException">Error message with win32 error code</exception>
/// <returns>true: one of connection is successfully updated proxy settings</returns>
public static bool SetProxy(string? strProxy, string? exceptions, int type)
{
try
{
// set proxy for LAN
bool result = SetConnectionProxy(null, strProxy, exceptions, type);
// set proxy for dial up connections
var connections = EnumerateRasEntries();
foreach (var connection in connections)
{
result |= SetConnectionProxy(connection, strProxy, exceptions, type);
}
return result;
}
catch
{
SetProxyFallback(strProxy, exceptions, type);
return false;
}
}
private static bool SetConnectionProxy(string? connectionName, string? strProxy, string? exceptions, int type)
{
InternetPerConnOptionList list = new();
int optionCount = 1;
if (type == 1) // No proxy
{
optionCount = 1;
}
else if (type is 2 or 4) // named proxy or autoproxy script URL
{
optionCount = string.IsNullOrEmpty(exceptions) ? 2 : 3;
}
int m_Int = (int)PerConnFlags.PROXY_TYPE_DIRECT;
PerConnOption m_Option = PerConnOption.INTERNET_PER_CONN_FLAGS;
if (type == 2) // named proxy
{
m_Int = (int)(PerConnFlags.PROXY_TYPE_DIRECT | PerConnFlags.PROXY_TYPE_PROXY);
m_Option = PerConnOption.INTERNET_PER_CONN_PROXY_SERVER;
}
else if (type == 4) // autoproxy script url
{
m_Int = (int)(PerConnFlags.PROXY_TYPE_DIRECT | PerConnFlags.PROXY_TYPE_AUTO_PROXY_URL);
m_Option = PerConnOption.INTERNET_PER_CONN_AUTOCONFIG_URL;
}
//int optionCount = Utile.IsNullOrEmpty(strProxy) ? 1 : (Utile.IsNullOrEmpty(exceptions) ? 2 : 3);
InternetConnectionOption[] options = new InternetConnectionOption[optionCount];
// USE a proxy server ...
options[0].m_Option = PerConnOption.INTERNET_PER_CONN_FLAGS;
//options[0].m_Value.m_Int = (int)((optionCount < 2) ? PerConnFlags.PROXY_TYPE_DIRECT : (PerConnFlags.PROXY_TYPE_DIRECT | PerConnFlags.PROXY_TYPE_PROXY));
options[0].m_Value.m_Int = m_Int;
// use THIS proxy server
if (optionCount > 1)
{
options[1].m_Option = m_Option;
options[1].m_Value.m_StringPtr = Marshal.StringToHGlobalAuto(strProxy); // !! remember to deallocate memory 1
// except for these addresses ...
if (optionCount > 2)
{
options[2].m_Option = PerConnOption.INTERNET_PER_CONN_PROXY_BYPASS;
options[2].m_Value.m_StringPtr = Marshal.StringToHGlobalAuto(exceptions); // !! remember to deallocate memory 2
}
}
// default stuff
list.dwSize = Marshal.SizeOf(list);
if (connectionName != null)
{
list.szConnection = Marshal.StringToHGlobalAuto(connectionName); // !! remember to deallocate memory 3
}
else
{
list.szConnection = nint.Zero;
}
list.dwOptionCount = options.Length;
list.dwOptionError = 0;
int optSize = Marshal.SizeOf(typeof(InternetConnectionOption));
// make a pointer out of all that ...
nint optionsPtr = Marshal.AllocCoTaskMem(optSize * options.Length); // !! remember to deallocate memory 4
// copy the array over into that spot in memory ...
for (int i = 0; i < options.Length; ++i)
{
if (Environment.Is64BitOperatingSystem)
{
nint opt = new(optionsPtr.ToInt64() + (i * optSize));
Marshal.StructureToPtr(options[i], opt, false);
}
else
{
nint opt = new(optionsPtr.ToInt32() + (i * optSize));
Marshal.StructureToPtr(options[i], opt, false);
}
}
list.options = optionsPtr;
// and then make a pointer out of the whole list
nint ipcoListPtr = Marshal.AllocCoTaskMem(list.dwSize); // !! remember to deallocate memory 5
Marshal.StructureToPtr(list, ipcoListPtr, false);
// and finally, call the API method!
bool isSuccess = NativeMethods.InternetSetOption(nint.Zero,
InternetOption.INTERNET_OPTION_PER_CONNECTION_OPTION,
ipcoListPtr, list.dwSize);
int returnvalue = 0; // ERROR_SUCCESS
if (!isSuccess)
{ // get the error codes, they might be helpful
returnvalue = Marshal.GetLastPInvokeError();
}
else
{
// Notify the system that the registry settings have been changed and cause them to be refreshed
NativeMethods.InternetSetOption(nint.Zero, InternetOption.INTERNET_OPTION_SETTINGS_CHANGED, nint.Zero, 0);
NativeMethods.InternetSetOption(nint.Zero, InternetOption.INTERNET_OPTION_REFRESH, nint.Zero, 0);
}
// FREE the data ASAP
if (list.szConnection != nint.Zero)
Marshal.FreeHGlobal(list.szConnection); // release mem 3
if (optionCount > 1)
{
Marshal.FreeHGlobal(options[1].m_Value.m_StringPtr); // release mem 1
if (optionCount > 2)
{
Marshal.FreeHGlobal(options[2].m_Value.m_StringPtr); // release mem 2
}
}
Marshal.FreeCoTaskMem(optionsPtr); // release mem 4
Marshal.FreeCoTaskMem(ipcoListPtr); // release mem 5
if (returnvalue != 0)
{
// throw the error codes, they might be helpful
throw new ApplicationException($"Set Internet Proxy failed with error code: {Marshal.GetLastWin32Error()}");
}
return true;
}
/// <summary>
/// Retrieve list of connections including LAN and WAN to support PPPoE connection
/// </summary>
/// <returns>A list of RAS connection names. May be empty list if no dial up connection.</returns>
/// <exception cref="ApplicationException">Error message with win32 error code</exception>
private static IEnumerable<string> EnumerateRasEntries()
{
int entries = 0;
// attempt to query with 1 entry buffer
RASENTRYNAME[] rasEntryNames = new RASENTRYNAME[1];
int bufferSize = Marshal.SizeOf(typeof(RASENTRYNAME));
rasEntryNames[0].dwSize = Marshal.SizeOf(typeof(RASENTRYNAME));
uint result = NativeMethods.RasEnumEntries(null, null, rasEntryNames, ref bufferSize, ref entries);
// increase buffer if the buffer is not large enough
if (result == (uint)ErrorCode.ERROR_BUFFER_TOO_SMALL)
{
rasEntryNames = new RASENTRYNAME[bufferSize / Marshal.SizeOf(typeof(RASENTRYNAME))];
for (int i = 0; i < rasEntryNames.Length; i++)
{
rasEntryNames[i].dwSize = Marshal.SizeOf(typeof(RASENTRYNAME));
}
result = NativeMethods.RasEnumEntries(null, null, rasEntryNames, ref bufferSize, ref entries);
}
if (result == 0)
{
var entryNames = new List<string>();
for (int i = 0; i < entries; i++)
{
entryNames.Add(rasEntryNames[i].szEntryName);
}
return entryNames;
}
throw new ApplicationException($"RasEnumEntries failed with error code: {result}");
}
#region WinInet structures
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct InternetPerConnOptionList
{
public int dwSize; // size of the INTERNET_PER_CONN_OPTION_LIST struct
public nint szConnection; // connection name to set/query options
public int dwOptionCount; // number of options to set/query
public int dwOptionError; // on error, which option failed
//[MarshalAs(UnmanagedType.)]
public nint options;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct InternetConnectionOption
{
private static readonly int Size;
public PerConnOption m_Option;
public InternetConnectionOptionValue m_Value;
static InternetConnectionOption()
{
Size = Marshal.SizeOf(typeof(InternetConnectionOption));
}
// Nested Types
[StructLayout(LayoutKind.Explicit)]
public struct InternetConnectionOptionValue
{
// Fields
[FieldOffset(0)]
public System.Runtime.InteropServices.ComTypes.FILETIME m_FileTime;
[FieldOffset(0)]
public int m_Int;
[FieldOffset(0)]
public nint m_StringPtr;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct RASENTRYNAME
{
public int dwSize;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = RAS_MaxEntryName + 1)]
public string szEntryName;
public int dwFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
public string szPhonebookPath;
}
// Constants
public const int RAS_MaxEntryName = 256;
public const int MAX_PATH = 260; // Standard MAX_PATH value in Windows
}
#endregion WinInet structures
#region WinInet enums
//
// options manifests for Internet{Query|Set}Option
//
public enum InternetOption : uint
{
INTERNET_OPTION_PER_CONNECTION_OPTION = 75,
INTERNET_OPTION_REFRESH = 37,
INTERNET_OPTION_SETTINGS_CHANGED = 39
}
//
// Options used in INTERNET_PER_CONN_OPTON struct
//
public enum PerConnOption
{
INTERNET_PER_CONN_FLAGS = 1, // Sets or retrieves the connection type. The Value member will contain one or more of the values from PerConnFlags
INTERNET_PER_CONN_PROXY_SERVER = 2, // Sets or retrieves a string containing the proxy servers.
INTERNET_PER_CONN_PROXY_BYPASS = 3, // Sets or retrieves a string containing the URLs that do not use the proxy server.
INTERNET_PER_CONN_AUTOCONFIG_URL = 4//, // Sets or retrieves a string containing the URL to the automatic configuration script.
}
//
// PER_CONN_FLAGS
//
[Flags]
public enum PerConnFlags
{
PROXY_TYPE_DIRECT = 0x00000001, // direct to net
PROXY_TYPE_PROXY = 0x00000002, // via named proxy
PROXY_TYPE_AUTO_PROXY_URL = 0x00000004, // autoproxy URL
PROXY_TYPE_AUTO_DETECT = 0x00000008 // use autoproxy detection
}
public enum ErrorCode : uint
{
ERROR_BUFFER_TOO_SMALL = 603,
ERROR_INVALID_SIZE = 632
}
#endregion WinInet enums
internal static class NativeMethods
{
[DllImport("WinInet.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool InternetSetOption(nint hInternet, InternetOption dwOption, nint lpBuffer, int dwBufferLength);
[DllImport("Rasapi32.dll", CharSet = CharSet.Auto)]
public static extern uint RasEnumEntries(
string? reserved, // Reserved, must be null
string? lpszPhonebook, // Pointer to full path and filename of phone-book file. If this parameter is NULL, the entries are enumerated from all the remote access phone-book files
[In, Out] RASENTRYNAME[]? lprasentryname, // Buffer to receive RAS entry names
ref int lpcb, // Size of the buffer
ref int lpcEntries // Number of entries written to the buffer
);
}
}
}

View File

@@ -0,0 +1,99 @@
namespace ServiceLib.Handler.SysProxy
{
public static class SysProxyHandler
{
private static readonly string _tag = "SysProxyHandler";
public static async Task<bool> UpdateSysProxy(Config config, bool forceDisable)
{
var type = config.SystemProxyItem.SysProxyType;
if (forceDisable && type != ESysProxyType.Unchanged)
{
type = ESysProxyType.ForcedClear;
}
try
{
var port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
var exceptions = config.SystemProxyItem.SystemProxyExceptions.Replace(" ", "");
if (port <= 0)
{
return false;
}
switch (type)
{
case ESysProxyType.ForcedChange when Utils.IsWindows():
{
GetWindowsProxyString(config, port, out var strProxy, out var strExceptions);
ProxySettingWindows.SetProxy(strProxy, strExceptions, 2);
break;
}
case ESysProxyType.ForcedChange when Utils.IsLinux():
await ProxySettingLinux.SetProxy(Global.Loopback, port, exceptions);
break;
case ESysProxyType.ForcedChange when Utils.IsOSX():
await ProxySettingOSX.SetProxy(Global.Loopback, port, exceptions);
break;
case ESysProxyType.ForcedClear when Utils.IsWindows():
ProxySettingWindows.UnsetProxy();
break;
case ESysProxyType.ForcedClear when Utils.IsLinux():
await ProxySettingLinux.UnsetProxy();
break;
case ESysProxyType.ForcedClear when Utils.IsOSX():
await ProxySettingOSX.UnsetProxy();
break;
case ESysProxyType.Pac when Utils.IsWindows():
await SetWindowsProxyPac(port);
break;
}
if (type != ESysProxyType.Pac && Utils.IsWindows())
{
PacHandler.Stop();
}
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return true;
}
private static void GetWindowsProxyString(Config config, int port, out string strProxy, out string strExceptions)
{
strExceptions = config.SystemProxyItem.SystemProxyExceptions.Replace(" ", "");
if (config.SystemProxyItem.NotProxyLocalAddress)
{
strExceptions = $"<local>;{strExceptions}";
}
strProxy = string.Empty;
if (Utils.IsNullOrEmpty(config.SystemProxyItem.SystemProxyAdvancedProtocol))
{
strProxy = $"{Global.Loopback}:{port}";
}
else
{
strProxy = config.SystemProxyItem.SystemProxyAdvancedProtocol
.Replace("{ip}", Global.Loopback)
.Replace("{http_port}", port.ToString())
.Replace("{socks_port}", port.ToString());
}
}
private static async Task SetWindowsProxyPac(int port)
{
var portPac = AppHandler.Instance.GetLocalPort(EInboundProtocol.pac);
await PacHandler.Start(Utils.GetConfigPath(), port, portPac);
var strProxy = $"{Global.HttpProtocol}{Global.Loopback}:{portPac}/pac?t={DateTime.Now.Ticks}";
ProxySettingWindows.SetProxy(strProxy, "", 4);
}
}
}

View File

@@ -0,0 +1,72 @@
namespace ServiceLib.Handler
{
public class TaskHandler
{
private static readonly Lazy<TaskHandler> _instance = new(() => new());
public static TaskHandler Instance => _instance.Value;
public void RegUpdateTask(Config config, Action<bool, string> updateFunc)
{
Task.Run(() => UpdateTaskRunSubscription(config, updateFunc));
Task.Run(() => UpdateTaskRunGeo(config, updateFunc));
}
private async Task UpdateTaskRunSubscription(Config config, Action<bool, string> updateFunc)
{
await Task.Delay(60000);
Logging.SaveLog("UpdateTaskRunSubscription");
var updateHandle = new UpdateService();
while (true)
{
var updateTime = ((DateTimeOffset)DateTime.Now).ToUnixTimeSeconds();
var lstSubs = (await AppHandler.Instance.SubItems())
.Where(t => t.AutoUpdateInterval > 0)
.Where(t => updateTime - t.UpdateTime >= t.AutoUpdateInterval * 60)
.ToList();
foreach (var item in lstSubs)
{
await updateHandle.UpdateSubscriptionProcess(config, item.Id, true, (bool success, string msg) =>
{
updateFunc?.Invoke(success, msg);
if (success)
Logging.SaveLog("subscription" + msg);
});
item.UpdateTime = updateTime;
await ConfigHandler.AddSubItem(config, item);
await Task.Delay(5000);
}
await Task.Delay(60000);
}
}
private async Task UpdateTaskRunGeo(Config config, Action<bool, string> updateFunc)
{
var autoUpdateGeoTime = DateTime.Now;
//await Task.Delay(1000 * 120);
Logging.SaveLog("UpdateTaskRunGeo");
var updateHandle = new UpdateService();
while (true)
{
await Task.Delay(1000 * 3600);
var dtNow = DateTime.Now;
if (config.GuiItem.AutoUpdateInterval > 0)
{
if ((dtNow - autoUpdateGeoTime).Hours % config.GuiItem.AutoUpdateInterval == 0)
{
await updateHandle.UpdateGeoFileAll(config, (bool success, string msg) =>
{
updateFunc?.Invoke(false, msg);
});
autoUpdateGeoTime = dtNow;
}
}
}
}
}
}

View File

@@ -0,0 +1,180 @@
using System.Net;
using WebDav;
namespace ServiceLib.Handler
{
public sealed class WebDavHandler
{
private static readonly Lazy<WebDavHandler> _instance = new(() => new());
public static WebDavHandler Instance => _instance.Value;
private Config? _config;
private WebDavClient? _client;
private string? _lastDescription;
private string _webDir = Global.AppName + "_backup";
private readonly string _webFileName = "backup.zip";
private readonly string _tag = "WebDav--";
public WebDavHandler()
{
_config = AppHandler.Instance.Config;
}
private async Task<bool> GetClient()
{
try
{
if (_config.WebDavItem.Url.IsNullOrEmpty()
|| _config.WebDavItem.UserName.IsNullOrEmpty()
|| _config.WebDavItem.Password.IsNullOrEmpty())
{
throw new ArgumentException("webdav parameter error or null");
}
if (_client != null)
{
_client?.Dispose();
_client = null;
}
if (_config.WebDavItem.DirName.IsNullOrEmpty())
{
_webDir = Global.AppName + "_backup";
}
else
{
_webDir = _config.WebDavItem.DirName.TrimEx();
}
var clientParams = new WebDavClientParams
{
BaseAddress = new Uri(_config.WebDavItem.Url),
Credentials = new NetworkCredential(_config.WebDavItem.UserName, _config.WebDavItem.Password)
};
_client = new WebDavClient(clientParams);
}
catch (Exception ex)
{
SaveLog(ex);
return false;
}
return await Task.FromResult(true);
}
private async Task<bool> TryCreateDir()
{
if (_client is null)
return false;
try
{
var result2 = await _client.Mkcol(_webDir);
if (result2.IsSuccessful)
{
return true;
}
SaveLog(result2.Description);
}
catch (Exception ex)
{
SaveLog(ex);
}
return false;
}
private void SaveLog(string desc)
{
_lastDescription = desc;
Logging.SaveLog(_tag + desc);
}
private void SaveLog(Exception ex)
{
_lastDescription = ex.Message;
Logging.SaveLog(_tag, ex);
}
public async Task<bool> CheckConnection()
{
if (await GetClient() == false)
{
return false;
}
await TryCreateDir();
try
{
var testName = "readme_test";
var myContent = new StringContent(testName);
var result = await _client.PutFile($"{_webDir}/{testName}", myContent);
if (result.IsSuccessful)
{
await _client.Delete($"{_webDir}/{testName}");
return true;
}
else
{
SaveLog(result.Description);
}
}
catch (Exception ex)
{
SaveLog(ex);
}
return false;
}
public async Task<bool> PutFile(string fileName)
{
if (await GetClient() == false)
{
return false;
}
await TryCreateDir();
try
{
await using var fs = File.OpenRead(fileName);
var result = await _client.PutFile($"{_webDir}/{_webFileName}", fs); // upload a resource
if (result.IsSuccessful)
{
return true;
}
SaveLog(result.Description);
}
catch (Exception ex)
{
SaveLog(ex);
}
return false;
}
public async Task<bool> GetRawFile(string fileName)
{
if (await GetClient() == false)
{
return false;
}
await TryCreateDir();
try
{
var response = await _client.GetRawFile($"{_webDir}/{_webFileName}");
if (!response.IsSuccessful)
{
SaveLog(response.Description);
return false;
}
await using var outputFileStream = new FileStream(fileName, FileMode.Create);
await response.Stream.CopyToAsync(outputFileStream);
return true;
}
catch (Exception ex)
{
SaveLog(ex);
}
return false;
}
public string GetLastError() => _lastDescription ?? string.Empty;
}
}

View File

@@ -0,0 +1,11 @@
namespace ServiceLib.Models
{
public class CheckUpdateModel
{
public bool? IsSelected { get; set; }
public string? CoreType { get; set; }
public string? Remarks { get; set; }
public string? FileName { get; set; }
public bool? IsFinished { get; set; }
}
}

View File

@@ -0,0 +1,17 @@
namespace ServiceLib.Models
{
public class ClashConnectionModel
{
public string? Id { get; set; }
public string? Network { get; set; }
public string? Type { get; set; }
public string? Host { get; set; }
public ulong Upload { get; set; }
public ulong Download { get; set; }
public string? UploadTraffic { get; set; }
public string? DownloadTraffic { get; set; }
public double Time { get; set; }
public string? Elapsed { get; set; }
public string? Chain { get; set; }
}
}

View File

@@ -0,0 +1,37 @@
namespace ServiceLib.Models
{
public class ClashConnections
{
public ulong downloadTotal { get; set; }
public ulong uploadTotal { get; set; }
public List<ConnectionItem>? connections { get; set; }
}
public class ConnectionItem
{
public string? id { get; set; }
public MetadataItem? metadata { get; set; }
public ulong upload { get; set; }
public ulong download { get; set; }
public DateTime start { get; set; }
public List<string>? chains { get; set; }
public string? rule { get; set; }
public string? rulePayload { get; set; }
}
public class MetadataItem
{
public string? network { get; set; }
public string? type { get; set; }
public string? sourceIP { get; set; }
public string? destinationIP { get; set; }
public string? sourcePort { get; set; }
public string? destinationPort { get; set; }
public string? host { get; set; }
public string? nsMode { get; set; }
public object? uid { get; set; }
public string? process { get; set; }
public string? processPath { get; set; }
public string? remoteDestination { get; set; }
}
}

View File

@@ -0,0 +1,17 @@
using static ServiceLib.Models.ClashProxies;
namespace ServiceLib.Models
{
public class ClashProviders
{
public Dictionary<string, ProvidersItem>? providers { get; set; }
public class ProvidersItem
{
public string? name { get; set; }
public List<ProxiesItem>? proxies { get; set; }
public string? type { get; set; }
public string? vehicleType { get; set; }
}
}
}

View File

@@ -0,0 +1,24 @@
namespace ServiceLib.Models
{
public class ClashProxies
{
public Dictionary<string, ProxiesItem>? proxies { get; set; }
public class ProxiesItem
{
public List<string>? all { get; set; }
public List<HistoryItem>? history { get; set; }
public string? name { get; set; }
public string? type { get; set; }
public bool udp { get; set; }
public string? now { get; set; }
public int delay { get; set; }
}
public class HistoryItem
{
public string? time { get; set; }
public int delay { get; set; }
}
}
}

View File

@@ -0,0 +1,18 @@
namespace ServiceLib.Models
{
[Serializable]
public class ClashProxyModel
{
public string? Name { get; set; }
public string? Type { get; set; }
public string? Now { get; set; }
public int Delay { get; set; }
public string? DelayName { get; set; }
public bool IsActive { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
namespace ServiceLib.Models
{
public class CmdItem
{
public string? Cmd { get; set; }
public List<string>? Arguments { get; set; }
}
}

View File

@@ -0,0 +1,15 @@
namespace ServiceLib.Models
{
public class ComboItem
{
public string? ID
{
get; set;
}
public string? Text
{
get; set;
}
}
}

View File

@@ -0,0 +1,57 @@
namespace ServiceLib.Models
{
/// <summary>
/// 本软件配置文件实体类
/// </summary>
[Serializable]
public class Config
{
#region property
public string IndexId { get; set; }
public string SubIndexId { get; set; }
public ECoreType RunningCoreType { get; set; }
public bool IsRunningCore(ECoreType type)
{
switch (type)
{
case ECoreType.Xray when RunningCoreType is ECoreType.Xray or ECoreType.v2fly or ECoreType.v2fly_v5:
case ECoreType.sing_box when RunningCoreType is ECoreType.sing_box or ECoreType.mihomo:
return true;
default:
return false;
}
}
#endregion property
#region other entities
public CoreBasicItem CoreBasicItem { get; set; }
public TunModeItem TunModeItem { get; set; }
public KcpItem KcpItem { get; set; }
public GrpcItem GrpcItem { get; set; }
public RoutingBasicItem RoutingBasicItem { get; set; }
public GUIItem GuiItem { get; set; }
public MsgUIItem MsgUIItem { get; set; }
public UIItem UiItem { get; set; }
public ConstItem ConstItem { get; set; }
public SpeedTestItem SpeedTestItem { get; set; }
public Mux4RayItem Mux4RayItem { get; set; }
public Mux4SboxItem Mux4SboxItem { get; set; }
public HysteriaItem HysteriaItem { get; set; }
public ClashUIItem ClashUIItem { get; set; }
public SystemProxyItem SystemProxyItem { get; set; }
public WebDavItem WebDavItem { get; set; }
public CheckUpdateItem CheckUpdateItem { get; set; }
public Fragment4RayItem? Fragment4RayItem { get; set; }
public List<InItem> Inbound { get; set; }
public List<KeyEventItem> GlobalHotkeys { get; set; }
public List<CoreTypeItem> CoreTypeItem { get; set; }
#endregion other entities
}
}

View File

@@ -0,0 +1,247 @@
namespace ServiceLib.Models
{
[Serializable]
public class CoreBasicItem
{
public bool LogEnabled { get; set; }
public string Loglevel { get; set; }
public bool MuxEnabled { get; set; }
public bool DefAllowInsecure { get; set; }
public string DefFingerprint { get; set; }
public string DefUserAgent { get; set; }
public bool EnableFragment { get; set; }
public bool EnableCacheFile4Sbox { get; set; } = true;
}
[Serializable]
public class InItem
{
public int LocalPort { get; set; }
public string Protocol { get; set; }
public bool UdpEnabled { get; set; }
public bool SniffingEnabled { get; set; } = true;
public List<string>? DestOverride { get; set; } = ["http", "tls"];
public bool RouteOnly { get; set; }
public bool AllowLANConn { get; set; }
public bool NewPort4LAN { get; set; }
public string User { get; set; }
public string Pass { get; set; }
public bool SecondLocalPortEnabled { get; set; }
}
[Serializable]
public class KcpItem
{
public int Mtu { get; set; }
public int Tti { get; set; }
public int UplinkCapacity { get; set; }
public int DownlinkCapacity { get; set; }
public bool Congestion { get; set; }
public int ReadBufferSize { get; set; }
public int WriteBufferSize { get; set; }
}
[Serializable]
public class GrpcItem
{
public int? IdleTimeout { get; set; }
public int? HealthCheckTimeout { get; set; }
public bool? PermitWithoutStream { get; set; }
public int? InitialWindowsSize { get; set; }
}
[Serializable]
public class GUIItem
{
public bool AutoRun { get; set; }
public bool EnableStatistics { get; set; }
public bool DisplayRealTimeSpeed { get; set; }
public bool KeepOlderDedupl { get; set; }
public int AutoUpdateInterval { get; set; }
public bool EnableSecurityProtocolTls13 { get; set; }
public int TrayMenuServersLimit { get; set; } = 20;
public bool EnableHWA { get; set; } = false;
public bool EnableLog { get; set; } = true;
}
[Serializable]
public class MsgUIItem
{
public string? MainMsgFilter { get; set; }
public bool? AutoRefresh { get; set; }
}
[Serializable]
public class UIItem
{
public bool EnableAutoAdjustMainLvColWidth { get; set; }
public bool EnableUpdateSubOnlyRemarksExist { get; set; }
public double MainWidth { get; set; }
public double MainHeight { get; set; }
public double MainGirdHeight1 { get; set; }
public double MainGirdHeight2 { get; set; }
public EGirdOrientation MainGirdOrientation { get; set; } = EGirdOrientation.Vertical;
public string? ColorPrimaryName { get; set; }
public string? CurrentTheme { get; set; }
public string CurrentLanguage { get; set; }
public string CurrentFontFamily { get; set; }
public int CurrentFontSize { get; set; }
public bool EnableDragDropSort { get; set; }
public bool DoubleClick2Activate { get; set; }
public bool AutoHideStartup { get; set; }
public bool Hide2TrayWhenClose { get; set; }
public List<ColumnItem> MainColumnItem { get; set; }
public bool ShowInTaskbar { get; set; }
}
[Serializable]
public class ConstItem
{
public string? SubConvertUrl { get; set; }
public string? GeoSourceUrl { get; set; }
public string? SrsSourceUrl { get; set; }
public string? RouteRulesTemplateSourceUrl { get; set; }
}
[Serializable]
public class KeyEventItem
{
public EGlobalHotkey EGlobalHotkey { get; set; }
public bool Alt { get; set; }
public bool Control { get; set; }
public bool Shift { get; set; }
public int? KeyCode { get; set; }
}
[Serializable]
public class CoreTypeItem
{
public EConfigType ConfigType { get; set; }
public ECoreType CoreType { get; set; }
}
[Serializable]
public class TunModeItem
{
public bool EnableTun { get; set; }
public bool StrictRoute { get; set; } = true;
public string Stack { get; set; }
public int Mtu { get; set; }
public bool EnableExInbound { get; set; }
public bool EnableIPv6Address { get; set; }
public string? LinuxSudoPwd { get; set; }
}
[Serializable]
public class SpeedTestItem
{
public int SpeedTestTimeout { get; set; }
public string SpeedTestUrl { get; set; }
public string SpeedPingTestUrl { get; set; }
public int SpeedTestPageSize { get; set; }
}
[Serializable]
public class RoutingBasicItem
{
public string DomainStrategy { get; set; }
public string DomainStrategy4Singbox { get; set; }
public string DomainMatcher { get; set; }
public string RoutingIndexId { get; set; }
}
[Serializable]
public class ColumnItem
{
public string Name { get; set; }
public int Width { get; set; }
public int Index { get; set; }
}
[Serializable]
public class Mux4RayItem
{
public int? Concurrency { get; set; }
public int? XudpConcurrency { get; set; }
public string? XudpProxyUDP443 { get; set; }
}
[Serializable]
public class Mux4SboxItem
{
public string Protocol { get; set; }
public int MaxConnections { get; set; }
public bool? Padding { get; set; }
}
[Serializable]
public class HysteriaItem
{
public int UpMbps { get; set; }
public int DownMbps { get; set; }
}
[Serializable]
public class ClashUIItem
{
public ERuleMode RuleMode { get; set; }
public bool EnableIPv6 { get; set; }
public bool EnableMixinContent { get; set; }
public int ProxiesSorting { get; set; }
public bool ProxiesAutoRefresh { get; set; }
public int ProxiesAutoDelayTestInterval { get; set; } = 10;
public bool ConnectionsAutoRefresh { get; set; }
public int ConnectionsRefreshInterval { get; set; } = 2;
}
[Serializable]
public class SystemProxyItem
{
public ESysProxyType SysProxyType { get; set; }
public string SystemProxyExceptions { get; set; }
public bool NotProxyLocalAddress { get; set; } = true;
public string SystemProxyAdvancedProtocol { get; set; }
}
[Serializable]
public class WebDavItem
{
public string? Url { get; set; }
public string? UserName { get; set; }
public string? Password { get; set; }
public string? DirName { get; set; }
}
[Serializable]
public class CheckUpdateItem
{
public bool CheckPreReleaseUpdate { get; set; }
public List<string>? SelectedCoreTypes { get; set; }
}
[Serializable]
public class Fragment4RayItem
{
public string? Packets { get; set; }
public string? Length { get; set; }
public string? Interval { get; set; }
}
}

Some files were not shown because too many files have changed in this diff Show More