Compare commits
268 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
27c53be209 | ||
|
|
d93c12b354 | ||
|
|
98d4a47efb | ||
|
|
8ab04c65b5 | ||
|
|
1b2dab1388 | ||
|
|
4f8dae7fa0 | ||
|
|
cdc23e32c4 | ||
|
|
20457e9e63 | ||
|
|
e63042af84 | ||
|
|
c35b4d3c1b | ||
|
|
64a83a5d64 | ||
|
|
01039d0b47 | ||
|
|
7c1e5a3cba | ||
|
|
038161527f | ||
|
|
b12b7a17e6 | ||
|
|
37cf23d5fe | ||
|
|
ed7fb4f6e3 | ||
|
|
5d4bd2fee6 | ||
|
|
aae5906311 | ||
|
|
4a7bafd011 | ||
|
|
626ebfe65d | ||
|
|
3cc75cd46d | ||
|
|
f809ee7b20 | ||
|
|
1295d8191c | ||
|
|
bc2adbfa77 | ||
|
|
9583dff176 | ||
|
|
5732b84a7b | ||
|
|
c0d27504ac | ||
|
|
3db1dd7bbb | ||
|
|
5392766c5e | ||
|
|
730b7dea37 | ||
|
|
02a13ce028 | ||
|
|
7884853098 | ||
|
|
e122ea8146 | ||
|
|
f500d2b9f4 | ||
|
|
79e53bf1f5 | ||
|
|
31de7ec094 | ||
|
|
2e4501187c | ||
|
|
4430c9bd74 | ||
|
|
cf8be85ff7 | ||
|
|
0759be1223 | ||
|
|
21f8ddcf9f | ||
|
|
37cba5ee34 | ||
|
|
ff642fd1ac | ||
|
|
647f1d9c8b | ||
|
|
d886195ee3 | ||
|
|
e2b8f4f89a | ||
|
|
1dcfe661e9 | ||
|
|
d6dd110781 | ||
|
|
a0f956c885 | ||
|
|
88bcafed97 | ||
|
|
6e4f15ab52 | ||
|
|
20cae1ff4d | ||
|
|
dcf621b822 | ||
|
|
eafa20032b | ||
|
|
7375e1a490 | ||
|
|
199d87ba84 | ||
|
|
b43975ebfc | ||
|
|
fe7314c978 | ||
|
|
d4eb8e59a6 | ||
|
|
8ee00907b7 | ||
|
|
25fddc3c71 | ||
|
|
c78b733850 | ||
|
|
a57c83125e | ||
|
|
247b59985f | ||
|
|
7470b8b6d3 | ||
|
|
776d37b7aa | ||
|
|
8f532f8468 | ||
|
|
472963fe2d | ||
|
|
6a9b62ab9a | ||
|
|
9ac8aa2969 | ||
|
|
838bd2c794 | ||
|
|
b2bbe432e0 | ||
|
|
b3d8042452 | ||
|
|
0c758a7fdc | ||
|
|
85cb1d1c92 | ||
|
|
2cd2e8894d | ||
|
|
abb58379b3 | ||
|
|
4f48e8b190 | ||
|
|
2b5cbb5e74 | ||
|
|
23dd140921 | ||
|
|
8c8d7bda64 | ||
|
|
a6e246948a | ||
|
|
c49ba735a0 | ||
|
|
1a33c598e8 | ||
|
|
a4bbdb49de | ||
|
|
cf3846fbfd | ||
|
|
d46943eedf | ||
|
|
3bc17bd50a | ||
|
|
48a159f4c8 | ||
|
|
3d1bcffdc5 | ||
|
|
45fa0f94d2 | ||
|
|
ed16b7de4a | ||
|
|
f2ec03c7ec | ||
|
|
11db87f1e6 | ||
|
|
a1feaf33e0 | ||
|
|
53a99e3f79 | ||
|
|
e7f04f55c2 | ||
|
|
6653ea12b7 | ||
|
|
a28cef5b98 | ||
|
|
78a28fbdb3 | ||
|
|
bf8bbbdcb0 | ||
|
|
83ad83b135 | ||
|
|
dbd4f55981 | ||
|
|
5f5d7172ee | ||
|
|
fbd4557b44 | ||
|
|
5d55a55754 | ||
|
|
84032aec33 | ||
|
|
a372d8902e | ||
|
|
c38c62e4c3 | ||
|
|
8aceff7480 | ||
|
|
736c450161 | ||
|
|
3b63a3d308 | ||
|
|
4f56174c8f | ||
|
|
4d2eb324f1 | ||
|
|
3f2ab8ddcb | ||
|
|
fd8f863c5b | ||
|
|
246f1d7df0 | ||
|
|
ccacda9bf5 | ||
|
|
5494d63878 | ||
|
|
c32b9812a7 | ||
|
|
9eb9898b61 | ||
|
|
834e05999f | ||
|
|
b4c37d9906 | ||
|
|
9326b450d7 | ||
|
|
019ee8b1ba | ||
|
|
f043645397 | ||
|
|
3b173f0b3e | ||
|
|
f36c06389d | ||
|
|
d3a0b44247 | ||
|
|
e4d3a98aa8 | ||
|
|
f685682214 | ||
|
|
1c6323315b | ||
|
|
1ff4839be1 | ||
|
|
558e5bb340 | ||
|
|
48a9d208e6 | ||
|
|
f29e1f8c45 | ||
|
|
5d2bc88bb9 | ||
|
|
298fdb1191 | ||
|
|
59b34688ea | ||
|
|
5ce0bb6e4a | ||
|
|
487b1ab182 | ||
|
|
5c144a8ba3 | ||
|
|
ad344356df | ||
|
|
a55c65374d | ||
|
|
28447a9d43 | ||
|
|
0c03550c62 | ||
|
|
6d9a84803f | ||
|
|
03b0e4e2bb | ||
|
|
a00e9a6f5e | ||
|
|
ba17f8fde9 | ||
|
|
01d35456bd | ||
|
|
672b8c48ac | ||
|
|
ac1a357740 | ||
|
|
504f8d09a6 | ||
|
|
89ce7c23c9 | ||
|
|
a5d99b1eb5 | ||
|
|
800d193acb | ||
|
|
7a1d12be76 | ||
|
|
1b9c95e801 | ||
|
|
9f44815470 | ||
|
|
ca38239bce | ||
|
|
d9c22de6b8 | ||
|
|
49a3c84fc5 | ||
|
|
5e0c28438b | ||
|
|
a6dc801bc4 | ||
|
|
22009d1b71 | ||
|
|
50f39dc40e | ||
|
|
05d446ed37 | ||
|
|
7a0b068642 | ||
|
|
c0ef8c09af | ||
|
|
a2db6dd468 | ||
|
|
471bc0f65d | ||
|
|
80f840a7c2 | ||
|
|
a2413fdf23 | ||
|
|
9cbe2b938c | ||
|
|
e915726c52 | ||
|
|
b11e68cfd8 | ||
|
|
bee66d06dd | ||
|
|
945a0add96 | ||
|
|
294cabcf05 | ||
|
|
22eb993ebf | ||
|
|
b5e1a297ae | ||
|
|
499a16feae | ||
|
|
1866a59d12 | ||
|
|
10513e0f3b | ||
|
|
2e32de2fbb | ||
|
|
30a838df77 | ||
|
|
7cf9b9f57e | ||
|
|
736d995d4c | ||
|
|
e335b2c0d6 | ||
|
|
96ae5517f6 | ||
|
|
fb4b8d923a | ||
|
|
2ade705e51 | ||
|
|
e0086b4b79 | ||
|
|
8f6d443104 | ||
|
|
5dbce16895 | ||
|
|
1016dcb3d1 | ||
|
|
ba5ad12e13 | ||
|
|
57f9c8158e | ||
|
|
b8a0293b52 | ||
|
|
59b7daaef5 | ||
|
|
d781c768e9 | ||
|
|
04efed2079 | ||
|
|
2de9e14c7d | ||
|
|
a849dec6c2 | ||
|
|
28019dc511 | ||
|
|
9d638968a9 | ||
|
|
f921ff7d77 | ||
|
|
e3ea329795 | ||
|
|
87f1c129b6 | ||
|
|
a1c8bc0e61 | ||
|
|
61e9101851 | ||
|
|
a6289347cc | ||
|
|
9e84de8e76 | ||
|
|
d04cc53152 | ||
|
|
1ff3c5fc07 | ||
|
|
3db047a12f | ||
|
|
bf4615f2f2 | ||
|
|
798c7fad9a | ||
|
|
5797b37262 | ||
|
|
ce22f34cd6 | ||
|
|
4c49e52e26 | ||
|
|
47318b5d70 | ||
|
|
d12297909c | ||
|
|
5fb4edae2d | ||
|
|
c4b490e46d | ||
|
|
45febe3fff | ||
|
|
689a81a985 | ||
|
|
28620b385a | ||
|
|
be13446e69 | ||
|
|
ee57d5b8e6 | ||
|
|
4eda3dd8fa | ||
|
|
911dc7f90e | ||
|
|
18005b96e8 | ||
|
|
a3e45d206e | ||
|
|
0accf262dc | ||
|
|
e0eb73bb0a | ||
|
|
258e822c13 | ||
|
|
4f05b93d63 | ||
|
|
bb661d4f50 | ||
|
|
201cfaa922 | ||
|
|
c339aa349c | ||
|
|
046421f345 | ||
|
|
3a2c9e7aaa | ||
|
|
0bb6e6bd86 | ||
|
|
693e8ab157 | ||
|
|
033c16c992 | ||
|
|
6ec61433fb | ||
|
|
072f773245 | ||
|
|
0086f65a96 | ||
|
|
281f14f47e | ||
|
|
9fd20ff001 | ||
|
|
7df90a6034 | ||
|
|
019869ec28 | ||
|
|
b7f4fd7469 | ||
|
|
1273d2aee1 | ||
|
|
88990b4828 | ||
|
|
2f02c2970c | ||
|
|
ade789c6d4 | ||
|
|
9738f90970 | ||
|
|
6ed0741339 | ||
|
|
e6b1e22245 | ||
|
|
6b922be0c6 | ||
|
|
6e35a260e8 | ||
|
|
1106fd8cf1 | ||
|
|
fb92b90d5c | ||
|
|
5effbee50b |
77
.github/workflows/build-linux.yml
vendored
Normal file
77
.github/workflows/build-linux.yml
vendored
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
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-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- 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
|
||||||
|
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
|
||||||
|
|
||||||
|
# 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
|
||||||
78
.github/workflows/build-osx.yml
vendored
Normal file
78
.github/workflows/build-osx.yml
vendored
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
- 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
|
||||||
|
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
|
||||||
|
|
||||||
|
# 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
|
||||||
68
.github/workflows/build-windows.yml
vendored
Normal file
68
.github/workflows/build-windows.yml
vendored
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
- 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
|
||||||
|
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 "windows-64-With-Core" $OutputPath64
|
||||||
|
./package-release-zip.sh $OutputArchArm $OutputPathArm64
|
||||||
|
./package-release-zip.sh "windows-64-SelfContained" $OutputPath64Sc
|
||||||
|
./package-release-zip.sh "windows-64-SelfContained-With-Core" $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
|
||||||
60
.github/workflows/build.yml
vendored
60
.github/workflows/build.yml
vendored
@@ -1,60 +0,0 @@
|
|||||||
name: release
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ "master" ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ "master" ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
configuration: [Release]
|
|
||||||
|
|
||||||
runs-on: windows-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
# - name: 删除工作流运行
|
|
||||||
# uses: Mattraks/delete-workflow-runs@v2
|
|
||||||
# with:
|
|
||||||
# token: ${{ github.token }}
|
|
||||||
# repository: ${{ github.repository }}
|
|
||||||
# retain_days: 0
|
|
||||||
# keep_minimum_runs: 1
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: cd v2rayN &&
|
|
||||||
.\build.ps1
|
|
||||||
|
|
||||||
# - name: Package
|
|
||||||
# shell: pwsh
|
|
||||||
# run: |
|
|
||||||
# 7z a -mx9 ..\v2rayN.7z $env:Wap_Project_Directory
|
|
||||||
|
|
||||||
- name: Upload build artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: v2rayN
|
|
||||||
path: |
|
|
||||||
.\v2rayN\v2rayN.zip
|
|
||||||
|
|
||||||
# - name: Release
|
|
||||||
# uses: softprops/action-gh-release@v1
|
|
||||||
# env:
|
|
||||||
# GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
|
|
||||||
# with:
|
|
||||||
# prerelease: ${{ contains(github.ref, '-') }}
|
|
||||||
# draft: false
|
|
||||||
# files: |
|
|
||||||
# .\v2rayN\v2rayN.zip
|
|
||||||
# body: |
|
|
||||||
# [](https://t.me/netch_channel) [](https://t.me/netch_group)
|
|
||||||
# ## Changelogs
|
|
||||||
# * This is an automated deployment of GitHub Actions, the change log should be updated manually soon
|
|
||||||
|
|
||||||
# ## 更新日志
|
|
||||||
# * 这是 GitHub Actions 自动化部署,更新日志应该很快会手动更新
|
|
||||||
31
.github/workflows/winget-publish.yml
vendored
Normal file
31
.github/workflows/winget-publish.yml
vendored
Normal 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-With-Core\.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
|
||||||
23
README.md
23
README.md
@@ -1,5 +1,5 @@
|
|||||||
# v2rayN
|
# v2rayN
|
||||||
A GUI client for Windows, support [Xray core](https://github.com/XTLS/Xray-core) and [v2fly core](https://github.com/v2fly/v2ray-core) and [others](https://github.com/2dust/v2rayN/wiki/List-of-supported-cores)
|
A GUI client for Windows, Linux and macOS, support [Xray core](https://github.com/XTLS/Xray-core) and [sing-box-core](https://github.com/SagerNet/sing-box/releases) and [others](https://github.com/2dust/v2rayN/wiki/List-of-supported-cores)
|
||||||
|
|
||||||
|
|
||||||
[](https://github.com/2dust/v2rayN/commits/master)
|
[](https://github.com/2dust/v2rayN/commits/master)
|
||||||
@@ -9,13 +9,24 @@ A GUI client for Windows, support [Xray core](https://github.com/XTLS/Xray-core)
|
|||||||
|
|
||||||
|
|
||||||
## How to use
|
## How to use
|
||||||
- If you are new to this, please download v2rayN-With-Core.zip from [releases](https://github.com/2dust/v2rayN/releases)
|
Check [Release files introduction](https://github.com/2dust/v2rayN/wiki/Release-files-introduction) and select the version you need to download
|
||||||
- Otherwise please download v2rayN.zip (you will also need to download cores in the bin directory)
|
### Windows
|
||||||
- Run v2rayN.exe
|
- Run `v2rayN.exe`
|
||||||
|
### Linux
|
||||||
|
- `chmod +x v2rayN` Run `./v2rayN` under user permissions
|
||||||
|
```
|
||||||
|
Debian 9+
|
||||||
|
Ubuntu 16.04+
|
||||||
|
Fedora 30+
|
||||||
|
```
|
||||||
|
### macOS
|
||||||
|
- `chmod +x v2rayN` Run `./v2rayN` under user permissions
|
||||||
|
```
|
||||||
|
macOS 11+
|
||||||
|
```
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
- (6.35 and above)[Microsoft .NET 8.0 Desktop Runtime ](https://dotnet.microsoft.com/en-us/download/dotnet/8.0)
|
- [Microsoft .NET 8.0 Desktop Runtime ](https://dotnet.microsoft.com/en-us/download/dotnet/8.0)
|
||||||
- (6.33 and below)[Microsoft .NET 6.0 Desktop Runtime ](https://dotnet.microsoft.com/en-us/download/dotnet/6.0)
|
|
||||||
- [Supported cores](https://github.com/2dust/v2rayN/wiki/List-of-supported-cores)
|
- [Supported cores](https://github.com/2dust/v2rayN/wiki/List-of-supported-cores)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
53
package-debian.sh
Normal file
53
package-debian.sh
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
Arch="$1"
|
||||||
|
OutputPath="$2"
|
||||||
|
Version="$3"
|
||||||
|
|
||||||
|
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"
|
||||||
65
package-osx.sh
Executable file
65
package-osx.sh
Executable file
@@ -0,0 +1,65 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
Arch="$1"
|
||||||
|
OutputPath="$2"
|
||||||
|
Version="$3"
|
||||||
|
|
||||||
|
PackagePath="v2rayN-Package-${Arch}"
|
||||||
|
mkdir -p "$PackagePath/v2rayN.app/Contents/Resources"
|
||||||
|
cp -rf "$OutputPath" "$PackagePath/v2rayN.app/Contents/MacOS"
|
||||||
|
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"
|
||||||
|
|
||||||
|
mkdir -p "$PackagePath/icons.iconset"
|
||||||
|
sips -z 16 16 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_16x16.png"
|
||||||
|
sips -z 32 32 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_16x16@2x.png"
|
||||||
|
sips -z 32 32 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_32x32.png"
|
||||||
|
sips -z 64 64 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_32x32@2x.png"
|
||||||
|
sips -z 128 128 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_128x128.png"
|
||||||
|
sips -z 256 256 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_128x128@2x.png"
|
||||||
|
sips -z 256 256 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_256x256.png"
|
||||||
|
sips -z 512 512 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_256x256@2x.png"
|
||||||
|
sips -z 512 512 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_512x512.png"
|
||||||
|
sips -z 1024 1024 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_512x512@2x.png"
|
||||||
|
iconutil -c icns "$PackagePath/icons.iconset" -o "$PackagePath/v2rayN.app/Contents/Resources/AppIcon.icns"
|
||||||
|
|
||||||
|
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
15
package-release-zip.sh
Normal 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
|
||||||
@@ -6,7 +6,22 @@
|
|||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<Copyright>Copyright © 2017-2024 (GPLv3)</Copyright>
|
<Copyright>Copyright © 2017-2024 (GPLv3)</Copyright>
|
||||||
<FileVersion>1.3.0</FileVersion>
|
<FileVersion>1.3.1</FileVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Update="Resx\Resource.Designer.cs">
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>Resource.resx</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Update="Resx\Resource.resx">
|
||||||
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>Resource.Designer.cs</LastGenOutput>
|
||||||
|
</EmbeddedResource>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -10,13 +10,20 @@
|
|||||||
{
|
{
|
||||||
if (args.Length == 0)
|
if (args.Length == 0)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Please run it from the main application.(请从主应用运行)");
|
Console.WriteLine(Resx.Resource.Guidelines);
|
||||||
Thread.Sleep(5000);
|
Thread.Sleep(5000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileName = Uri.UnescapeDataString(string.Join(" ", args));
|
var argData = Uri.UnescapeDataString(string.Join(" ", args));
|
||||||
UpgradeApp.Upgrade(fileName);
|
if (argData.Equals("rebootas"))
|
||||||
|
{
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
Utils.StartV2RayN();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpgradeApp.Upgrade(argData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
171
v2rayN/AmazTool/Resx/Resource.Designer.cs
generated
Normal file
171
v2rayN/AmazTool/Resx/Resource.Designer.cs
generated
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
156
v2rayN/AmazTool/Resx/Resource.resx
Normal file
156
v2rayN/AmazTool/Resx/Resource.resx
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<data name="Restartv2rayN" xml:space="preserve">
|
||||||
|
<value>Start v2rayN, please wait...</value>
|
||||||
|
</data>
|
||||||
|
<data name="Guidelines" xml:space="preserve">
|
||||||
|
<value>Please run it from the main application.</value>
|
||||||
|
</data>
|
||||||
|
<data name="UpgradeFileNotFound" xml:space="preserve">
|
||||||
|
<value>Upgrade failed, file not found.</value>
|
||||||
|
</data>
|
||||||
|
<data name="InProgress" xml:space="preserve">
|
||||||
|
<value>In progress, please wait...</value>
|
||||||
|
</data>
|
||||||
|
<data name="TryTerminateProcess" xml:space="preserve">
|
||||||
|
<value>Try to terminate the v2rayN process...</value>
|
||||||
|
</data>
|
||||||
|
<data name="FailedTerminateProcess" xml:space="preserve">
|
||||||
|
<value>Failed to terminate the v2rayN.Close it manually,or the upgrade may fail.</value>
|
||||||
|
</data>
|
||||||
|
<data name="StartUnzipping" xml:space="preserve">
|
||||||
|
<value>Start extracting the update package...</value>
|
||||||
|
</data>
|
||||||
|
<data name="SuccessUnzipping" xml:space="preserve">
|
||||||
|
<value>Successfully extracted the update package.</value>
|
||||||
|
</data>
|
||||||
|
<data name="FailedUnzipping" xml:space="preserve">
|
||||||
|
<value>Failed to extract the update package.</value>
|
||||||
|
</data>
|
||||||
|
<data name="FailedUpgrade" xml:space="preserve">
|
||||||
|
<value>Upgrade failed.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SuccessUpgrade" xml:space="preserve">
|
||||||
|
<value>Upgrade success.</value>
|
||||||
|
</data>
|
||||||
|
<data name="Information" xml:space="preserve">
|
||||||
|
<value>Information</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
@@ -117,8 +117,40 @@
|
|||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
<data name="Restartv2rayN" xml:space="preserve">
|
||||||
<data name="pac" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<value>正在重启,请等待...</value>
|
||||||
<value>Resources\pac.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;gb2312</value>
|
</data>
|
||||||
|
<data name="Guidelines" xml:space="preserve">
|
||||||
|
<value>请从主应用运行。</value>
|
||||||
|
</data>
|
||||||
|
<data name="UpgradeFileNotFound" xml:space="preserve">
|
||||||
|
<value>升级失败,文件不存在。</value>
|
||||||
|
</data>
|
||||||
|
<data name="InProgress" xml:space="preserve">
|
||||||
|
<value>正在进行中,请等待...</value>
|
||||||
|
</data>
|
||||||
|
<data name="TryTerminateProcess" xml:space="preserve">
|
||||||
|
<value>尝试结束 v2rayN 进程...</value>
|
||||||
|
</data>
|
||||||
|
<data name="FailedTerminateProcess" xml:space="preserve">
|
||||||
|
<value>请手动关闭正在运行的v2rayN,否则可能升级失败。</value>
|
||||||
|
</data>
|
||||||
|
<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>
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -8,41 +8,41 @@ namespace AmazTool
|
|||||||
{
|
{
|
||||||
public static void Upgrade(string fileName)
|
public static void Upgrade(string fileName)
|
||||||
{
|
{
|
||||||
Console.WriteLine(fileName);
|
Console.WriteLine($"{Resx.Resource.StartUnzipping}\n{fileName}");
|
||||||
Console.WriteLine("In progress, please wait...(正在进行中,请等待)");
|
|
||||||
|
|
||||||
Thread.Sleep(5000);
|
Waiting(3);
|
||||||
|
|
||||||
if (!File.Exists(fileName))
|
if (!File.Exists(fileName))
|
||||||
{
|
{
|
||||||
Console.WriteLine("Upgrade Failed, File Not Exist(升级失败,文件不存在).");
|
Console.WriteLine(Resx.Resource.UpgradeFileNotFound);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Console.WriteLine(Resx.Resource.TryTerminateProcess);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Process[] existing = Process.GetProcessesByName(V2rayN);
|
var existing = Process.GetProcessesByName(Utils.V2rayN);
|
||||||
foreach (Process p in existing)
|
foreach (var pp in existing)
|
||||||
{
|
{
|
||||||
var path = p.MainModule?.FileName ?? "";
|
var path = pp.MainModule?.FileName ?? "";
|
||||||
if (path.StartsWith(GetPath(V2rayN)))
|
if (path.StartsWith(Utils.GetPath(Utils.V2rayN)))
|
||||||
{
|
{
|
||||||
p.Kill();
|
pp?.Kill();
|
||||||
p.WaitForExit(100);
|
pp?.WaitForExit(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// Access may be denied without admin right. The user may not be an administrator.
|
// Access may be denied without admin right. The user may not be an administrator.
|
||||||
Console.WriteLine("Failed to close v2rayN(关闭v2rayN失败).\n" +
|
Console.WriteLine(Resx.Resource.FailedTerminateProcess + ex.StackTrace);
|
||||||
"Close it manually, or the upgrade may fail.(请手动关闭正在运行的v2rayN,否则可能升级失败。\n\n" + ex.StackTrace);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Console.WriteLine(Resx.Resource.StartUnzipping);
|
||||||
StringBuilder sb = new();
|
StringBuilder sb = new();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string thisAppOldFile = $"{GetExePath()}.tmp";
|
string thisAppOldFile = $"{Utils.GetExePath()}.tmp";
|
||||||
File.Delete(thisAppOldFile);
|
File.Delete(thisAppOldFile);
|
||||||
string splitKey = "/";
|
string splitKey = "/";
|
||||||
|
|
||||||
@@ -56,16 +56,18 @@ namespace AmazTool
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Console.WriteLine(entry.FullName);
|
||||||
|
|
||||||
var lst = entry.FullName.Split(splitKey);
|
var lst = entry.FullName.Split(splitKey);
|
||||||
if (lst.Length == 1) continue;
|
if (lst.Length == 1) continue;
|
||||||
string fullName = string.Join(splitKey, lst[1..lst.Length]);
|
string fullName = string.Join(splitKey, lst[1..lst.Length]);
|
||||||
|
|
||||||
if (string.Equals(GetExePath(), GetPath(fullName), StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(Utils.GetExePath(), Utils.GetPath(fullName), StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
File.Move(GetExePath(), thisAppOldFile);
|
File.Move(Utils.GetExePath(), thisAppOldFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
string entryOutputPath = GetPath(fullName);
|
string entryOutputPath = Utils.GetPath(fullName);
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(entryOutputPath)!);
|
Directory.CreateDirectory(Path.GetDirectoryName(entryOutputPath)!);
|
||||||
entry.ExtractToFile(entryOutputPath, true);
|
entry.ExtractToFile(entryOutputPath, true);
|
||||||
|
|
||||||
@@ -79,49 +81,28 @@ namespace AmazTool
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Upgrade Failed(升级失败)." + ex.StackTrace);
|
Console.WriteLine(Resx.Resource.FailedUpgrade + ex.StackTrace);
|
||||||
return;
|
//return;
|
||||||
}
|
}
|
||||||
if (sb.Length > 0)
|
if (sb.Length > 0)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Upgrade Failed.\n" +
|
Console.WriteLine(Resx.Resource.FailedUpgrade + sb.ToString());
|
||||||
"(升级失败)." + sb.ToString());
|
//return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine("Start v2rayN, please wait...(正在重启,请等待)");
|
Console.WriteLine(Resx.Resource.Restartv2rayN);
|
||||||
Thread.Sleep(3000);
|
Waiting(2);
|
||||||
Process process = new()
|
|
||||||
|
Utils.StartV2RayN();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Waiting(int second)
|
||||||
|
{
|
||||||
|
for (var i = second; i > 0; i--)
|
||||||
{
|
{
|
||||||
StartInfo = new()
|
Console.WriteLine(i);
|
||||||
{
|
Thread.Sleep(1000);
|
||||||
FileName = V2rayN,
|
|
||||||
WorkingDirectory = StartupPath()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
process.Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetExePath()
|
|
||||||
{
|
|
||||||
return Environment.ProcessPath ?? Process.GetCurrentProcess().MainModule?.FileName ?? string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string StartupPath()
|
|
||||||
{
|
|
||||||
return AppDomain.CurrentDomain.BaseDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetPath(string fileName)
|
|
||||||
{
|
|
||||||
string startupPath = StartupPath();
|
|
||||||
if (string.IsNullOrEmpty(fileName))
|
|
||||||
{
|
|
||||||
return startupPath;
|
|
||||||
}
|
}
|
||||||
return Path.Combine(startupPath, fileName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string V2rayN => "v2rayN";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
43
v2rayN/AmazTool/Utils.cs
Normal file
43
v2rayN/AmazTool/Utils.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
using System.IO;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace PacLib;
|
|
||||||
|
|
||||||
public class PacHandler
|
|
||||||
{
|
|
||||||
private static string _configPath;
|
|
||||||
private static int _httpPort;
|
|
||||||
private static int _pacPort;
|
|
||||||
private static TcpListener? _tcpListener;
|
|
||||||
private static string _pacText;
|
|
||||||
private static bool _isRunning;
|
|
||||||
private static bool _needRestart = true;
|
|
||||||
|
|
||||||
public static void Start(string configPath, int httpPort, int pacPort)
|
|
||||||
{
|
|
||||||
_needRestart = (configPath != _configPath || httpPort != _httpPort || pacPort != _pacPort || !_isRunning);
|
|
||||||
|
|
||||||
_configPath = configPath;
|
|
||||||
_httpPort = httpPort;
|
|
||||||
_pacPort = pacPort;
|
|
||||||
|
|
||||||
InitText();
|
|
||||||
|
|
||||||
if (_needRestart)
|
|
||||||
{
|
|
||||||
Stop();
|
|
||||||
RunListener();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void InitText()
|
|
||||||
{
|
|
||||||
var path = Path.Combine(_configPath, "pac.txt");
|
|
||||||
if (!File.Exists(path))
|
|
||||||
{
|
|
||||||
File.AppendAllText(path, Resources.ResourceManager.GetString("pac"));
|
|
||||||
}
|
|
||||||
|
|
||||||
_pacText = File.ReadAllText(path).Replace("__PROXY__", $"PROXY 127.0.0.1:{_httpPort};DIRECT;");
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = _tcpListener.AcceptTcpClient();
|
|
||||||
await Task.Run(() =>
|
|
||||||
{
|
|
||||||
var stream = client.GetStream();
|
|
||||||
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);
|
|
||||||
var content = Encoding.UTF8.GetBytes(sb.ToString());
|
|
||||||
stream.Write(content, 0, content.Length);
|
|
||||||
stream.Flush();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, TaskCreationOptions.LongRunning);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Stop()
|
|
||||||
{
|
|
||||||
if (_tcpListener == null) return;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_isRunning = false;
|
|
||||||
_tcpListener.Stop();
|
|
||||||
_tcpListener = null;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Update="Resources.Designer.cs">
|
|
||||||
<DesignTime>True</DesignTime>
|
|
||||||
<AutoGen>True</AutoGen>
|
|
||||||
<DependentUpon>Resources.resx</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<EmbeddedResource Update="Resources.resx">
|
|
||||||
<Generator>ResXFileCodeGenerator</Generator>
|
|
||||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
|
||||||
</EmbeddedResource>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
95
v2rayN/PacLib/Resources.Designer.cs
generated
95
v2rayN/PacLib/Resources.Designer.cs
generated
@@ -1,95 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
// <auto-generated>
|
|
||||||
// 此代码由工具生成。
|
|
||||||
// 运行时版本:4.0.30319.42000
|
|
||||||
//
|
|
||||||
// 对此文件的更改可能会导致不正确的行为,并且如果
|
|
||||||
// 重新生成代码,这些更改将会丢失。
|
|
||||||
// </auto-generated>
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
namespace PacLib {
|
|
||||||
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 Resources {
|
|
||||||
|
|
||||||
private static global::System.Resources.ResourceManager resourceMan;
|
|
||||||
|
|
||||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
|
||||||
|
|
||||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
|
||||||
internal Resources() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <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("PacLib.Resources", typeof(Resources).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>
|
|
||||||
/// 查找类似 var proxy = '__PROXY__';
|
|
||||||
///var rules = [
|
|
||||||
/// [
|
|
||||||
/// [],
|
|
||||||
/// []
|
|
||||||
/// ],
|
|
||||||
/// [
|
|
||||||
/// [
|
|
||||||
/// "aftygh.gov.tw",
|
|
||||||
/// "aide.gov.tw",
|
|
||||||
/// "aliyun.com",
|
|
||||||
/// "arte.gov.tw",
|
|
||||||
/// "baidu.com",
|
|
||||||
/// "chinaso.com",
|
|
||||||
/// "chinaz.com",
|
|
||||||
/// "chukuang.gov.tw",
|
|
||||||
/// "cycab.gov.tw",
|
|
||||||
/// "dbnsa.gov.tw",
|
|
||||||
/// "df.gov.tw",
|
|
||||||
/// "eastcoast-nsa.gov.tw",
|
|
||||||
/// "erv-nsa.gov.tw",
|
|
||||||
/// "grb.gov.tw",
|
|
||||||
/// "haosou.com",
|
|
||||||
/// [字符串的其余部分被截断]"; 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
internal static string pac {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("pac", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Protobuf Include="Statistics.proto" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Google.Protobuf" Version="3.28.3" />
|
|
||||||
<PackageReference Include="Grpc.Net.Client" Version="2.66.0" />
|
|
||||||
<PackageReference Include="Grpc.Tools" Version="2.67.0">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
||||||
</PackageReference>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package v2ray.core.app.stats.command;
|
|
||||||
option csharp_namespace = "ProtosLib.Statistics";
|
|
||||||
|
|
||||||
message GetStatsRequest {
|
|
||||||
// Name of the stat counter.
|
|
||||||
string name = 1;
|
|
||||||
// Whether or not to reset the counter to fetching its value.
|
|
||||||
bool reset = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message Stat {
|
|
||||||
string name = 1;
|
|
||||||
int64 value = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message GetStatsResponse {
|
|
||||||
Stat stat = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message QueryStatsRequest {
|
|
||||||
string pattern = 1;
|
|
||||||
bool reset = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message QueryStatsResponse {
|
|
||||||
repeated Stat stat = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message SysStatsRequest {
|
|
||||||
}
|
|
||||||
|
|
||||||
message SysStatsResponse {
|
|
||||||
uint32 NumGoroutine = 1;
|
|
||||||
uint32 NumGC = 2;
|
|
||||||
uint64 Alloc = 3;
|
|
||||||
uint64 TotalAlloc = 4;
|
|
||||||
uint64 Sys = 5;
|
|
||||||
uint64 Mallocs = 6;
|
|
||||||
uint64 Frees = 7;
|
|
||||||
uint64 LiveObjects = 8;
|
|
||||||
uint64 PauseTotalNs = 9;
|
|
||||||
uint32 Uptime = 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
service StatsService {
|
|
||||||
rpc GetStats(GetStatsRequest) returns (GetStatsResponse) {}
|
|
||||||
rpc QueryStats(QueryStatsRequest) returns (QueryStatsResponse) {}
|
|
||||||
rpc GetSysStats(SysStatsRequest) returns (SysStatsResponse) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
message Config {}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
using ProtosLib.Statistics;
|
|
||||||
|
|
||||||
namespace ProtosLib
|
|
||||||
{
|
|
||||||
public class Tests
|
|
||||||
{
|
|
||||||
private StatsService.StatsServiceClient client_;
|
|
||||||
|
|
||||||
public Tests()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
101
v2rayN/ServiceLib/Common/AesUtils.cs
Normal file
101
v2rayN/ServiceLib/Common/AesUtils.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
75
v2rayN/ServiceLib/Common/DesUtils.cs
Normal file
75
v2rayN/ServiceLib/Common/DesUtils.cs
Normal 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,8 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
public static class FileManager
|
public static class FileManager
|
||||||
{
|
{
|
||||||
|
private static readonly string _tag = "FileManager";
|
||||||
|
|
||||||
public static bool ByteArrayToFile(string fileName, byte[] content)
|
public static bool ByteArrayToFile(string fileName, byte[] content)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -15,7 +17,7 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -30,7 +32,7 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +48,7 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +62,7 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +81,7 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,13 +107,13 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
catch (IOException ex)
|
catch (IOException ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -130,7 +132,7 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -148,7 +150,7 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Net.Mime;
|
using System.Net.Mime;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
private static readonly Lazy<HttpClientHelper> _instance = new(() =>
|
private static readonly Lazy<HttpClientHelper> _instance = new(() =>
|
||||||
{
|
{
|
||||||
HttpClientHandler handler = new() { UseCookies = false };
|
SocketsHttpHandler handler = new() { UseCookies = false };
|
||||||
HttpClientHelper helper = new(new HttpClient(handler));
|
HttpClientHelper helper = new(new HttpClient(handler));
|
||||||
return helper;
|
return helper;
|
||||||
});
|
});
|
||||||
@@ -98,7 +98,7 @@ namespace ServiceLib.Common
|
|||||||
totalRead += read;
|
totalRead += read;
|
||||||
|
|
||||||
if (read == 0) break;
|
if (read == 0) break;
|
||||||
await file.WriteAsync(buffer, 0, read, token);
|
await file.WriteAsync(buffer.AsMemory(0, read), token);
|
||||||
|
|
||||||
if (canReportProgress)
|
if (canReportProgress)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
public class JsonUtils
|
public class JsonUtils
|
||||||
{
|
{
|
||||||
|
private static readonly string _tag = "JsonUtils";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// DeepCopy
|
/// DeepCopy
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -70,8 +72,9 @@ namespace ServiceLib.Common
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="obj"></param>
|
/// <param name="obj"></param>
|
||||||
/// <param name="indented"></param>
|
/// <param name="indented"></param>
|
||||||
|
/// <param name="nullValue"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static string Serialize(object? obj, bool indented = true)
|
public static string Serialize(object? obj, bool indented = true, bool nullValue = false)
|
||||||
{
|
{
|
||||||
var result = string.Empty;
|
var result = string.Empty;
|
||||||
try
|
try
|
||||||
@@ -82,14 +85,14 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
var options = new JsonSerializerOptions
|
var options = new JsonSerializerOptions
|
||||||
{
|
{
|
||||||
WriteIndented = indented ? true : false,
|
WriteIndented = indented,
|
||||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
|
DefaultIgnoreCondition = nullValue ? JsonIgnoreCondition.Never : JsonIgnoreCondition.WhenWritingNull
|
||||||
};
|
};
|
||||||
result = JsonSerializer.Serialize(obj, options);
|
result = JsonSerializer.Serialize(obj, options);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -100,38 +103,5 @@ namespace ServiceLib.Common
|
|||||||
/// <param name="obj"></param>
|
/// <param name="obj"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static JsonNode? SerializeToNode(object? obj) => JsonSerializer.SerializeToNode(obj);
|
public static JsonNode? SerializeToNode(object? obj) => JsonSerializer.SerializeToNode(obj);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Save as json file
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="obj"></param>
|
|
||||||
/// <param name="filePath"></param>
|
|
||||||
/// <param name="nullValue"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static int ToFile(object? obj, string? filePath, bool nullValue = true)
|
|
||||||
{
|
|
||||||
if (filePath is null)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using var file = File.Create(filePath);
|
|
||||||
|
|
||||||
var options = new JsonSerializerOptions
|
|
||||||
{
|
|
||||||
WriteIndented = true,
|
|
||||||
DefaultIgnoreCondition = nullValue ? JsonIgnoreCondition.Never : JsonIgnoreCondition.WhenWritingNull
|
|
||||||
};
|
|
||||||
|
|
||||||
JsonSerializer.Serialize(file, obj, options);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logging.SaveLog(ex.Message, ex);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,40 +37,41 @@ namespace ServiceLib.Common
|
|||||||
foreach (var filePath in files)
|
foreach (var filePath in files)
|
||||||
{
|
{
|
||||||
var file = new FileInfo(filePath);
|
var file = new FileInfo(filePath);
|
||||||
if (file.CreationTime < now)
|
if (file.CreationTime >= now) continue;
|
||||||
|
try
|
||||||
{
|
{
|
||||||
try
|
file.Delete();
|
||||||
{
|
}
|
||||||
file.Delete();
|
catch
|
||||||
}
|
{
|
||||||
catch { }
|
// ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch { }
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SaveLog(string strContent)
|
public static void SaveLog(string strContent)
|
||||||
{
|
{
|
||||||
if (LogManager.IsLoggingEnabled())
|
if (!LogManager.IsLoggingEnabled()) return;
|
||||||
{
|
|
||||||
var logger = LogManager.GetLogger("Log1");
|
LogManager.GetLogger("Log1").Info(strContent);
|
||||||
logger.Info(strContent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SaveLog(string strTitle, Exception ex)
|
public static void SaveLog(string strTitle, Exception ex)
|
||||||
{
|
{
|
||||||
if (LogManager.IsLoggingEnabled())
|
if (!LogManager.IsLoggingEnabled()) return;
|
||||||
|
|
||||||
|
var logger = LogManager.GetLogger("Log2");
|
||||||
|
logger.Debug($"{strTitle},{ex.Message}");
|
||||||
|
logger.Debug(ex.StackTrace);
|
||||||
|
if (ex?.InnerException != null)
|
||||||
{
|
{
|
||||||
var logger = LogManager.GetLogger("Log2");
|
logger.Error(ex.InnerException);
|
||||||
logger.Debug($"{strTitle},{ex.Message}");
|
|
||||||
logger.Debug(ex.StackTrace);
|
|
||||||
if (ex?.InnerException != null)
|
|
||||||
{
|
|
||||||
logger.Error(ex.InnerException);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
118
v2rayN/ServiceLib/Common/ProcUtils.cs
Normal file
118
v2rayN/ServiceLib/Common/ProcUtils.cs
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
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 process = new()
|
||||||
|
{
|
||||||
|
StartInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
UseShellExecute = true,
|
||||||
|
FileName = fileName,
|
||||||
|
Arguments = arguments,
|
||||||
|
WorkingDirectory = dir
|
||||||
|
}
|
||||||
|
};
|
||||||
|
process.Start();
|
||||||
|
return process.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
var procId = review ? proc?.Id : null;
|
||||||
|
var fileName = review ? proc?.MainModule?.FileName : null;
|
||||||
|
var processName = review ? proc?.ProcessName : null;
|
||||||
|
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
using System.Linq.Expressions;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace ServiceLib.Common
|
|
||||||
{
|
|
||||||
public static class QueryableExtension
|
|
||||||
{
|
|
||||||
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> query, string propertyName)
|
|
||||||
{
|
|
||||||
return _OrderBy<T>(query, propertyName, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> query, string propertyName)
|
|
||||||
{
|
|
||||||
return _OrderBy<T>(query, propertyName, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IOrderedQueryable<T> _OrderBy<T>(IQueryable<T> query, string propertyName, bool isDesc)
|
|
||||||
{
|
|
||||||
var methodname = (isDesc) ? "OrderByDescendingInternal" : "OrderByInternal";
|
|
||||||
|
|
||||||
var memberProp = typeof(T).GetProperty(propertyName);
|
|
||||||
|
|
||||||
var method = typeof(QueryableExtension).GetMethod(methodname)
|
|
||||||
.MakeGenericMethod(typeof(T), memberProp.PropertyType);
|
|
||||||
|
|
||||||
return (IOrderedQueryable<T>)method.Invoke(null, new object[] { query, memberProp });
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IOrderedQueryable<T> OrderByInternal<T, TProp>(IQueryable<T> query, PropertyInfo memberProperty)
|
|
||||||
{//public
|
|
||||||
return query.OrderBy(_GetLambda<T, TProp>(memberProperty));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IOrderedQueryable<T> OrderByDescendingInternal<T, TProp>(IQueryable<T> query, PropertyInfo memberProperty)
|
|
||||||
{//public
|
|
||||||
return query.OrderByDescending(_GetLambda<T, TProp>(memberProperty));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Expression<Func<T, TProp>> _GetLambda<T, TProp>(PropertyInfo memberProperty)
|
|
||||||
{
|
|
||||||
if (memberProperty.PropertyType != typeof(TProp)) throw new Exception();
|
|
||||||
|
|
||||||
var thisArg = Expression.Parameter(typeof(T));
|
|
||||||
var lambda = Expression.Lambda<Func<T, TProp>>(Expression.Property(thisArg, memberProperty), thisArg);
|
|
||||||
|
|
||||||
return lambda;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -31,8 +31,8 @@
|
|||||||
var parts = this.version.Split('.');
|
var parts = this.version.Split('.');
|
||||||
if (parts.Length == 2)
|
if (parts.Length == 2)
|
||||||
{
|
{
|
||||||
this.major = int.Parse(parts[0]);
|
this.major = int.Parse(parts.First());
|
||||||
this.minor = int.Parse(parts[1]);
|
this.minor = int.Parse(parts.Last());
|
||||||
this.patch = 0;
|
this.patch = 0;
|
||||||
}
|
}
|
||||||
else if (parts.Length is 3 or 4)
|
else if (parts.Length is 3 or 4)
|
||||||
|
|||||||
@@ -73,5 +73,19 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
return _dbAsync.Table<T>();
|
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;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -22,7 +22,7 @@ namespace ServiceLib.Common
|
|||||||
public static bool BeginWithAny(this string s, IEnumerable<char> chars)
|
public static bool BeginWithAny(this string s, IEnumerable<char> chars)
|
||||||
{
|
{
|
||||||
if (s.IsNullOrEmpty()) return false;
|
if (s.IsNullOrEmpty()) return false;
|
||||||
return chars.Contains(s[0]);
|
return chars.Contains(s.First());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsWhiteSpace(this string value)
|
private static bool IsWhiteSpace(this string value)
|
||||||
@@ -61,7 +61,7 @@ namespace ServiceLib.Common
|
|||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
return char.ToUpper(value[0]) + value[1..];
|
return char.ToUpper(value.First()) + value[1..];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string AppendQuotes(this string value)
|
public static string AppendQuotes(this string value)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using CliWrap;
|
using CliWrap;
|
||||||
using CliWrap.Buffered;
|
using CliWrap.Buffered;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@@ -15,6 +15,8 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
public class Utils
|
public class Utils
|
||||||
{
|
{
|
||||||
|
private static readonly string _tag = "Utils";
|
||||||
|
|
||||||
#region 资源操作
|
#region 资源操作
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -36,8 +38,9 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,8 +59,9 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,8 +94,9 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,8 +119,9 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,8 +141,9 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,8 +161,9 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog("Base64Encode", ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,16 +178,16 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
if (plainText.IsNullOrEmpty()) return "";
|
if (plainText.IsNullOrEmpty()) return "";
|
||||||
plainText = plainText.Trim()
|
plainText = plainText.Trim()
|
||||||
.Replace(Environment.NewLine, "")
|
.Replace(Environment.NewLine, "")
|
||||||
.Replace("\n", "")
|
.Replace("\n", "")
|
||||||
.Replace("\r", "")
|
.Replace("\r", "")
|
||||||
.Replace('_', '/')
|
.Replace('_', '/')
|
||||||
.Replace('-', '+')
|
.Replace('-', '+')
|
||||||
.Replace(" ", "");
|
.Replace(" ", "");
|
||||||
|
|
||||||
if (plainText.Length % 4 > 0)
|
if (plainText.Length % 4 > 0)
|
||||||
{
|
{
|
||||||
plainText = plainText.PadRight(plainText.Length + 4 - plainText.Length % 4, '=');
|
plainText = plainText.PadRight(plainText.Length + 4 - (plainText.Length % 4), '=');
|
||||||
}
|
}
|
||||||
|
|
||||||
var data = Convert.FromBase64String(plainText);
|
var data = Convert.FromBase64String(plainText);
|
||||||
@@ -187,8 +195,9 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog("Base64Decode", ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,14 +260,17 @@ namespace ServiceLib.Common
|
|||||||
unit = "TB";
|
unit = "TB";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = GBs + ((MBs % factor) / (factor + 0.0));
|
result = GBs + ((MBs % factor) / (factor + 0.0));
|
||||||
unit = "GB";
|
unit = "GB";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = MBs + ((KBs % factor) / (factor + 0.0));
|
result = MBs + ((KBs % factor) / (factor + 0.0));
|
||||||
unit = "MB";
|
unit = "MB";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = KBs + ((amount % factor) / (factor + 0.0));
|
result = KBs + ((amount % factor) / (factor + 0.0));
|
||||||
unit = "KB";
|
unit = "KB";
|
||||||
return;
|
return;
|
||||||
@@ -302,8 +314,9 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var key = Uri.UnescapeDataString(keyValue[0]);
|
|
||||||
var val = Uri.UnescapeDataString(keyValue[1]);
|
var key = Uri.UnescapeDataString(keyValue.First());
|
||||||
|
var val = Uri.UnescapeDataString(keyValue.Last());
|
||||||
|
|
||||||
if (result[key] is null)
|
if (result[key] is null)
|
||||||
{
|
{
|
||||||
@@ -323,6 +336,7 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
sb.Append(b.ToString("x2"));
|
sb.Append(b.ToString("x2"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,6 +351,7 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Uri uri = new(url);
|
Uri uri = new(url);
|
||||||
@@ -368,6 +383,7 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
return text.Replace(",", ",").Replace(Environment.NewLine, ",");
|
return text.Replace(",", ",").Replace(Environment.NewLine, ",");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,6 +407,7 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return text == "null";
|
return text == "null";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,6 +441,7 @@ namespace ServiceLib.Common
|
|||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -448,6 +466,7 @@ namespace ServiceLib.Common
|
|||||||
if (ipBytes[0] == 172 && ipBytes[1] >= 16 && ipBytes[1] <= 31) return true;
|
if (ipBytes[0] == 172 && ipBytes[1] >= 16 && ipBytes[1] <= 31) return true;
|
||||||
if (ipBytes[0] == 192 && ipBytes[1] == 168) return true;
|
if (ipBytes[0] == 192 && ipBytes[1] == 168) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -466,8 +485,9 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,6 +509,7 @@ namespace ServiceLib.Common
|
|||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
return 59090;
|
return 59090;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -496,10 +517,10 @@ namespace ServiceLib.Common
|
|||||||
|
|
||||||
#region 杂项
|
#region 杂项
|
||||||
|
|
||||||
public static bool UpgradeAppExists(out string fileName)
|
public static bool UpgradeAppExists(out string upgradeFileName)
|
||||||
{
|
{
|
||||||
fileName = Path.Combine(Utils.StartupPath(), GetExeName("AmazTool"));
|
upgradeFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, GetExeName("AmazTool"));
|
||||||
return File.Exists(fileName);
|
return File.Exists(upgradeFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -510,19 +531,15 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (blFull)
|
return blFull
|
||||||
{
|
? $"{Global.AppName} - V{GetVersionInfo()} - {RuntimeInformation.ProcessArchitecture}"
|
||||||
return $"{Global.AppName} - V{GetVersionInfo()} - {RuntimeInformation.ProcessArchitecture} - {File.GetLastWriteTime(GetExePath()):yyyy/MM/dd}";
|
: $"{Global.AppName}/{GetVersionInfo()}";
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return $"{Global.AppName}/{GetVersionInfo()}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Global.AppName;
|
return Global.AppName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,11 +551,16 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
return "0.0";
|
return "0.0";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string GetRuntimeInfo()
|
||||||
|
{
|
||||||
|
return $"{Utils.GetVersion()} | {Utils.StartupPath()} | {Utils.GetExePath()} | {Environment.OSVersion} | {(Environment.Is64BitOperatingSystem ? 64 : 32)}";
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 取得GUID
|
/// 取得GUID
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -558,8 +580,9 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -568,19 +591,6 @@ namespace ServiceLib.Common
|
|||||||
return Guid.TryParse(strSrc, out _);
|
return Guid.TryParse(strSrc, out _);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ProcessStart(string? fileName, string arguments = "")
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (fileName.IsNullOrEmpty()) { return; }
|
|
||||||
Process.Start(new ProcessStartInfo(fileName, arguments) { UseShellExecute = true });
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logging.SaveLog(ex.Message, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Dictionary<string, string> GetSystemHosts()
|
public static Dictionary<string, string> GetSystemHosts()
|
||||||
{
|
{
|
||||||
var systemHosts = new Dictionary<string, string>();
|
var systemHosts = new Dictionary<string, string>();
|
||||||
@@ -596,15 +606,16 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
if (host.StartsWith("#")) continue;
|
if (host.StartsWith("#")) continue;
|
||||||
var hostItem = host.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
|
var hostItem = host.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
if (hostItem.Length < 2) continue;
|
if (hostItem.Length != 2) continue;
|
||||||
systemHosts.Add(hostItem[1], hostItem[0]);
|
systemHosts.Add(hostItem.Last(), hostItem.First());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return systemHosts;
|
return systemHosts;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -629,17 +640,20 @@ namespace ServiceLib.Common
|
|||||||
cmd = cmd.WithArguments(args);
|
cmd = cmd.WithArguments(args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await cmd.ExecuteBufferedAsync();
|
var result = await cmd.ExecuteBufferedAsync();
|
||||||
if (result.IsSuccess)
|
if (result.IsSuccess)
|
||||||
{
|
{
|
||||||
return result.StandardOutput.ToString();
|
return result.StandardOutput.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
Logging.SaveLog(result.ToString() ?? "");
|
Logging.SaveLog(result.ToString() ?? "");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog("GetCliWrapOutput", ex);
|
Logging.SaveLog("GetCliWrapOutput", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -647,6 +661,33 @@ namespace ServiceLib.Common
|
|||||||
|
|
||||||
#region TempPath
|
#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(AppDomain.CurrentDomain.BaseDirectory, "NotStoreConfigHere.txt")))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tempPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "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)
|
public static string GetPath(string fileName)
|
||||||
{
|
{
|
||||||
var startupPath = StartupPath();
|
var startupPath = StartupPath();
|
||||||
@@ -654,6 +695,7 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
return startupPath;
|
return startupPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Path.Combine(startupPath, fileName);
|
return Path.Combine(startupPath, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -664,6 +706,11 @@ namespace ServiceLib.Common
|
|||||||
|
|
||||||
public static string StartupPath()
|
public static string StartupPath()
|
||||||
{
|
{
|
||||||
|
if (Utils.IsNonWindows() && Environment.GetEnvironmentVariable("V2RAYN_LOCAL_APPLICATION_DATA") == "1")
|
||||||
|
{
|
||||||
|
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "v2rayN");
|
||||||
|
}
|
||||||
|
|
||||||
return AppDomain.CurrentDomain.BaseDirectory;
|
return AppDomain.CurrentDomain.BaseDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -674,6 +721,7 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
Directory.CreateDirectory(tempPath);
|
Directory.CreateDirectory(tempPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsNullOrEmpty(filename))
|
if (IsNullOrEmpty(filename))
|
||||||
{
|
{
|
||||||
return tempPath;
|
return tempPath;
|
||||||
@@ -691,6 +739,7 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
Directory.CreateDirectory(tempPath);
|
Directory.CreateDirectory(tempPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Path.Combine(tempPath, filename);
|
return Path.Combine(tempPath, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -701,6 +750,7 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
Directory.CreateDirectory(tempPath);
|
Directory.CreateDirectory(tempPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Utils.IsNullOrEmpty(filename))
|
if (Utils.IsNullOrEmpty(filename))
|
||||||
{
|
{
|
||||||
return tempPath;
|
return tempPath;
|
||||||
@@ -718,6 +768,7 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
Directory.CreateDirectory(tempPath);
|
Directory.CreateDirectory(tempPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (coreType != null)
|
if (coreType != null)
|
||||||
{
|
{
|
||||||
tempPath = Path.Combine(tempPath, coreType.ToLower().ToString());
|
tempPath = Path.Combine(tempPath, coreType.ToLower().ToString());
|
||||||
@@ -726,6 +777,7 @@ namespace ServiceLib.Common
|
|||||||
Directory.CreateDirectory(tempPath);
|
Directory.CreateDirectory(tempPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsNullOrEmpty(filename))
|
if (IsNullOrEmpty(filename))
|
||||||
{
|
{
|
||||||
return tempPath;
|
return tempPath;
|
||||||
@@ -743,6 +795,7 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
Directory.CreateDirectory(tempPath);
|
Directory.CreateDirectory(tempPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Utils.IsNullOrEmpty(filename))
|
if (Utils.IsNullOrEmpty(filename))
|
||||||
{
|
{
|
||||||
return tempPath;
|
return tempPath;
|
||||||
@@ -760,6 +813,7 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
Directory.CreateDirectory(tempPath);
|
Directory.CreateDirectory(tempPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Utils.IsNullOrEmpty(filename))
|
if (Utils.IsNullOrEmpty(filename))
|
||||||
{
|
{
|
||||||
return tempPath;
|
return tempPath;
|
||||||
@@ -780,6 +834,8 @@ namespace ServiceLib.Common
|
|||||||
|
|
||||||
public static bool IsOSX() => RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
|
public static bool IsOSX() => RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
|
||||||
|
|
||||||
|
public static bool IsNonWindows() => !RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
|
||||||
|
|
||||||
public static string GetExeName(string name)
|
public static string GetExeName(string name)
|
||||||
{
|
{
|
||||||
return IsWindows() ? $"{name}.exe" : name;
|
return IsWindows() ? $"{name}.exe" : name;
|
||||||
@@ -791,18 +847,19 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
|
return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
|
||||||
}
|
}
|
||||||
else
|
return false;
|
||||||
{
|
//else
|
||||||
var id = GetLinuxUserId().Result ?? "1000";
|
//{
|
||||||
if (int.TryParse(id, out var userId))
|
// var id = GetLinuxUserId().Result ?? "1000";
|
||||||
{
|
// if (int.TryParse(id, out var userId))
|
||||||
return userId == 0;
|
// {
|
||||||
}
|
// return userId == 0;
|
||||||
else
|
// }
|
||||||
{
|
// else
|
||||||
return false;
|
// {
|
||||||
}
|
// return false;
|
||||||
}
|
// }
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<string?> GetLinuxUserId()
|
private static async Task<string?> GetLinuxUserId()
|
||||||
@@ -814,10 +871,32 @@ namespace ServiceLib.Common
|
|||||||
public static async Task<string?> SetLinuxChmod(string? fileName)
|
public static async Task<string?> SetLinuxChmod(string? fileName)
|
||||||
{
|
{
|
||||||
if (fileName.IsNullOrEmpty()) return null;
|
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}" };
|
var arg = new List<string>() { "-c", $"chmod +x {fileName}" };
|
||||||
return await GetCliWrapOutput("/bin/bash", arg);
|
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
|
#endregion Platform
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
54
v2rayN/ServiceLib/Common/WindowsUtils.cs
Normal file
54
v2rayN/ServiceLib/Common/WindowsUtils.cs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,8 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
public class YamlUtils
|
public class YamlUtils
|
||||||
{
|
{
|
||||||
|
private static readonly string _tag = "YamlUtils";
|
||||||
|
|
||||||
#region YAML
|
#region YAML
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -26,7 +28,7 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog("FromYaml", ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
return deserializer.Deserialize<T>("");
|
return deserializer.Deserialize<T>("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,7 +55,7 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -71,7 +73,7 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog("PreprocessYaml", ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,14 +4,8 @@
|
|||||||
{
|
{
|
||||||
v2fly = 1,
|
v2fly = 1,
|
||||||
Xray = 2,
|
Xray = 2,
|
||||||
|
|
||||||
//SagerNet = 3,
|
|
||||||
v2fly_v5 = 4,
|
v2fly_v5 = 4,
|
||||||
|
|
||||||
//clash = 11,
|
|
||||||
//clash_meta = 12,
|
|
||||||
mihomo = 13,
|
mihomo = 13,
|
||||||
|
|
||||||
hysteria = 21,
|
hysteria = 21,
|
||||||
naiveproxy = 22,
|
naiveproxy = 22,
|
||||||
tuic = 23,
|
tuic = 23,
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
public enum EInboundProtocol
|
public enum EInboundProtocol
|
||||||
{
|
{
|
||||||
socks = 0,
|
socks = 0,
|
||||||
http,
|
|
||||||
socks2,
|
socks2,
|
||||||
http2,
|
socks3,
|
||||||
pac,
|
pac,
|
||||||
api,
|
api,
|
||||||
api2,
|
api2,
|
||||||
|
mixed,
|
||||||
speedtest = 21
|
speedtest = 21
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,8 @@
|
|||||||
ClearMsg,
|
ClearMsg,
|
||||||
SendMsgView,
|
SendMsgView,
|
||||||
SendSnackMsg,
|
SendSnackMsg,
|
||||||
RefreshProfiles
|
RefreshProfiles,
|
||||||
|
StopSpeedtest,
|
||||||
|
AppExit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,5 +4,6 @@
|
|||||||
{
|
{
|
||||||
Default = 0,
|
Default = 0,
|
||||||
Russia = 1,
|
Russia = 1,
|
||||||
|
Iran = 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
kcp,
|
kcp,
|
||||||
ws,
|
ws,
|
||||||
httpupgrade,
|
httpupgrade,
|
||||||
splithttp,
|
xhttp,
|
||||||
h2,
|
h2,
|
||||||
http,
|
http,
|
||||||
quic,
|
quic,
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
Shutdown,
|
Shutdown,
|
||||||
BrowseServer,
|
BrowseServer,
|
||||||
ImportRulesFromFile,
|
ImportRulesFromFile,
|
||||||
|
InitSettingFont,
|
||||||
SubEditWindow,
|
SubEditWindow,
|
||||||
RoutingRuleSettingWindow,
|
RoutingRuleSettingWindow,
|
||||||
RoutingRuleDetailsWindow,
|
RoutingRuleDetailsWindow,
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
public const string JuicityCoreUrl = "https://github.com/juicity/juicity/releases";
|
public const string JuicityCoreUrl = "https://github.com/juicity/juicity/releases";
|
||||||
public const string CustomRoutingListUrl = @"https://raw.githubusercontent.com/2dust/v2rayCustomRoutingList/master/";
|
public const string CustomRoutingListUrl = @"https://raw.githubusercontent.com/2dust/v2rayCustomRoutingList/master/";
|
||||||
public const string SingboxRulesetUrl = @"https://raw.githubusercontent.com/2dust/sing-box-rules/rule-set-{0}/{1}.srs";
|
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 PromotionUrl = @"aHR0cHM6Ly85LjIzNDQ1Ni54eXovYWJjLmh0bWw=";
|
||||||
public const string ConfigFileName = "guiNConfig.json";
|
public const string ConfigFileName = "guiNConfig.json";
|
||||||
@@ -28,21 +29,25 @@
|
|||||||
public const string CoreSpeedtestConfigFileName = "configSpeedtest.json";
|
public const string CoreSpeedtestConfigFileName = "configSpeedtest.json";
|
||||||
public const string CoreMultipleLoadConfigFileName = "configMultipleLoad.json";
|
public const string CoreMultipleLoadConfigFileName = "configMultipleLoad.json";
|
||||||
public const string ClashMixinConfigFileName = "Mixin.yaml";
|
public const string ClashMixinConfigFileName = "Mixin.yaml";
|
||||||
public const string V2raySampleClient = "ServiceLib.Sample.SampleClientConfig";
|
|
||||||
public const string SingboxSampleClient = "ServiceLib.Sample.SingboxSampleClientConfig";
|
public const string NamespaceSample = "ServiceLib.Sample.";
|
||||||
public const string V2raySampleHttpRequestFileName = "ServiceLib.Sample.SampleHttpRequest";
|
public const string V2raySampleClient = NamespaceSample + "SampleClientConfig";
|
||||||
public const string V2raySampleHttpResponseFileName = "ServiceLib.Sample.SampleHttpResponse";
|
public const string SingboxSampleClient = NamespaceSample + "SingboxSampleClientConfig";
|
||||||
public const string V2raySampleInbound = "ServiceLib.Sample.SampleInbound";
|
public const string V2raySampleHttpRequestFileName = NamespaceSample + "SampleHttpRequest";
|
||||||
public const string V2raySampleOutbound = "ServiceLib.Sample.SampleOutbound";
|
public const string V2raySampleHttpResponseFileName = NamespaceSample + "SampleHttpResponse";
|
||||||
public const string SingboxSampleOutbound = "ServiceLib.Sample.SingboxSampleOutbound";
|
public const string V2raySampleInbound = NamespaceSample + "SampleInbound";
|
||||||
public const string CustomRoutingFileName = "ServiceLib.Sample.custom_routing_";
|
public const string V2raySampleOutbound = NamespaceSample + "SampleOutbound";
|
||||||
public const string TunSingboxDNSFileName = "ServiceLib.Sample.tun_singbox_dns";
|
public const string SingboxSampleOutbound = NamespaceSample + "SingboxSampleOutbound";
|
||||||
public const string TunSingboxInboundFileName = "ServiceLib.Sample.tun_singbox_inbound";
|
public const string CustomRoutingFileName = NamespaceSample + "custom_routing_";
|
||||||
public const string TunSingboxRulesFileName = "ServiceLib.Sample.tun_singbox_rules";
|
public const string TunSingboxDNSFileName = NamespaceSample + "tun_singbox_dns";
|
||||||
public const string DNSV2rayNormalFileName = "ServiceLib.Sample.dns_v2ray_normal";
|
public const string TunSingboxInboundFileName = NamespaceSample + "tun_singbox_inbound";
|
||||||
public const string DNSSingboxNormalFileName = "ServiceLib.Sample.dns_singbox_normal";
|
public const string TunSingboxRulesFileName = NamespaceSample + "tun_singbox_rules";
|
||||||
public const string ClashMixinYaml = "ServiceLib.Sample.clash_mixin_yaml";
|
public const string DNSV2rayNormalFileName = NamespaceSample + "dns_v2ray_normal";
|
||||||
public const string ClashTunYaml = "ServiceLib.Sample.clash_tun_yaml";
|
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 DefaultSecurity = "auto";
|
||||||
public const string DefaultNetwork = "tcp";
|
public const string DefaultNetwork = "tcp";
|
||||||
@@ -63,15 +68,17 @@
|
|||||||
public const string AutoRunRegPath = @"Software\Microsoft\Windows\CurrentVersion\Run";
|
public const string AutoRunRegPath = @"Software\Microsoft\Windows\CurrentVersion\Run";
|
||||||
public const string AutoRunName = "v2rayNAutoRun";
|
public const string AutoRunName = "v2rayNAutoRun";
|
||||||
public const string CustomIconName = "v2rayN.ico";
|
public const string CustomIconName = "v2rayN.ico";
|
||||||
public const string IEProxyExceptions = "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 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 RoutingRuleComma = "<COMMA>";
|
||||||
public const string GrpcGunMode = "gun";
|
public const string GrpcGunMode = "gun";
|
||||||
public const string GrpcMultiMode = "multi";
|
public const string GrpcMultiMode = "multi";
|
||||||
public const int MaxPort = 65536;
|
public const int MaxPort = 65536;
|
||||||
public const string DelayUnit = "";
|
public const string DelayUnit = "";
|
||||||
public const string SpeedUnit = "";
|
public const string SpeedUnit = "";
|
||||||
public const int MinFontSize = 10;
|
public const int MinFontSize = 8;
|
||||||
public const string RebootAs = "rebootas";
|
public const string RebootAs = "rebootas";
|
||||||
|
public const string AvaAssets = "avares://v2rayN/Assets/";
|
||||||
|
|
||||||
public static readonly List<string> IEProxyProtocols = new() {
|
public static readonly List<string> IEProxyProtocols = new() {
|
||||||
"{ip}:{http_port}",
|
"{ip}:{http_port}",
|
||||||
@@ -102,9 +109,9 @@
|
|||||||
|
|
||||||
public static readonly List<string> SpeedTestUrls = new() {
|
public static readonly List<string> SpeedTestUrls = new() {
|
||||||
@"https://speed.cloudflare.com/__down?bytes=100000000",
|
@"https://speed.cloudflare.com/__down?bytes=100000000",
|
||||||
|
@"https://speed.cloudflare.com/__down?bytes=50000000",
|
||||||
@"https://speed.cloudflare.com/__down?bytes=10000000",
|
@"https://speed.cloudflare.com/__down?bytes=10000000",
|
||||||
@"http://cachefly.cachefly.net/50mb.test",
|
@"https://cachefly.cachefly.net/50mb.test",
|
||||||
@"http://cachefly.cachefly.net/10mb.test"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly List<string> SpeedPingTestUrls = new() {
|
public static readonly List<string> SpeedPingTestUrls = new() {
|
||||||
@@ -117,21 +124,25 @@
|
|||||||
public static readonly List<string> GeoFilesSources = new() {
|
public static readonly List<string> GeoFilesSources = new() {
|
||||||
"",
|
"",
|
||||||
@"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/{0}.dat",
|
@"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 = new() {
|
public static readonly List<string> SingboxRulesetSources = new() {
|
||||||
"",
|
"",
|
||||||
@"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-rules-dat@release/sing-box/rule-set-{0}/{1}.srs",
|
@"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 = new() {
|
public static readonly List<string> RoutingRulesSources = new() {
|
||||||
"",
|
"",
|
||||||
@"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/v2rayN/template.json",
|
@"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 = new() {
|
public static readonly List<string> DNSTemplateSources = new() {
|
||||||
"",
|
"",
|
||||||
@"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/v2rayN/",
|
@"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()
|
public static readonly Dictionary<string, string> UserAgentTexts = new()
|
||||||
@@ -172,41 +183,40 @@
|
|||||||
|
|
||||||
public static readonly List<string> VmessSecurities = new() { "aes-128-gcm", "chacha20-poly1305", "auto", "none", "zero" };
|
public static readonly List<string> VmessSecurities = new() { "aes-128-gcm", "chacha20-poly1305", "auto", "none", "zero" };
|
||||||
public static readonly List<string> SsSecurities = new() { "aes-256-gcm", "aes-128-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305", "none", "plain" };
|
public static readonly List<string> SsSecurities = new() { "aes-256-gcm", "aes-128-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305", "none", "plain" };
|
||||||
public static readonly List<string> SsSecuritiesInSagerNet = new() { "none", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305", "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", "xchacha20-ietf-poly1305", "rc4", "rc4-md5", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "aes-128-cfb8", "aes-192-cfb8", "aes-256-cfb8", "aes-128-ofb", "aes-192-ofb", "aes-256-ofb", "bf-cfb", "cast5-cfb", "des-cfb", "idea-cfb", "rc2-cfb", "seed-cfb", "camellia-128-cfb", "camellia-192-cfb", "camellia-256-cfb", "camellia-128-cfb8", "camellia-192-cfb8", "camellia-256-cfb8", "salsa20", "chacha20", "chacha20-ietf", "xchacha20" };
|
|
||||||
public static readonly List<string> SsSecuritiesInXray = new() { "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> SsSecuritiesInXray = new() { "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 = new() { "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> SsSecuritiesInSingbox = new() { "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 = new() { "", "xtls-rprx-vision", "xtls-rprx-vision-udp443" };
|
public static readonly List<string> Flows = new() { "", "xtls-rprx-vision", "xtls-rprx-vision-udp443" };
|
||||||
public static readonly List<string> Networks = new() { "tcp", "kcp", "ws", "httpupgrade", "splithttp", "h2", "quic", "grpc" };
|
public static readonly List<string> Networks = new() { "tcp", "kcp", "ws", "httpupgrade", "xhttp", "h2", "quic", "grpc" };
|
||||||
public static readonly List<string> KcpHeaderTypes = new() { "srtp", "utp", "wechat-video", "dtls", "wireguard" };
|
public static readonly List<string> KcpHeaderTypes = new() { "srtp", "utp", "wechat-video", "dtls", "wireguard" };
|
||||||
public static readonly List<string> CoreTypes = new() { "v2fly", "Xray", "sing_box" };
|
public static readonly List<string> CoreTypes = new() { "Xray", "sing_box" };
|
||||||
public static readonly List<string> CoreTypes4VLESS = new() { "Xray", "sing_box" };
|
|
||||||
public static readonly List<string> DomainStrategies = new() { "AsIs", "IPIfNonMatch", "IPOnDemand" };
|
public static readonly List<string> DomainStrategies = new() { "AsIs", "IPIfNonMatch", "IPOnDemand" };
|
||||||
public static readonly List<string> DomainStrategies4Singbox = new() { "ipv4_only", "ipv6_only", "prefer_ipv4", "prefer_ipv6", "" };
|
public static readonly List<string> DomainStrategies4Singbox = new() { "ipv4_only", "ipv6_only", "prefer_ipv4", "prefer_ipv6", "" };
|
||||||
public static readonly List<string> DomainMatchers = new() { "linear", "mph", "" };
|
public static readonly List<string> DomainMatchers = new() { "linear", "mph", "" };
|
||||||
public static readonly List<string> Fingerprints = new() { "chrome", "firefox", "safari", "ios", "android", "edge", "360", "qq", "random", "randomized", "" };
|
public static readonly List<string> Fingerprints = new() { "chrome", "firefox", "safari", "ios", "android", "edge", "360", "qq", "random", "randomized", "" };
|
||||||
public static readonly List<string> UserAgent = new() { "chrome", "firefox", "safari", "edge", "none" };
|
public static readonly List<string> UserAgent = new() { "chrome", "firefox", "safari", "edge", "none" };
|
||||||
|
public static readonly List<string> XhttpMode = new() { "auto", "packet-up", "stream-up", "stream-one" };
|
||||||
|
|
||||||
public static readonly List<string> AllowInsecure = new() { "true", "false", "" };
|
public static readonly List<string> AllowInsecure = new() { "true", "false", "" };
|
||||||
public static readonly List<string> DomainStrategy4Freedoms = new() { "AsIs", "UseIP", "UseIPv4", "UseIPv6", "" };
|
public static readonly List<string> DomainStrategy4Freedoms = new() { "AsIs", "UseIP", "UseIPv4", "UseIPv6", "" };
|
||||||
public static readonly List<string> SingboxDomainStrategy4Out = new() { "ipv4_only", "prefer_ipv4", "prefer_ipv6", "ipv6_only", "" };
|
public static readonly List<string> SingboxDomainStrategy4Out = new() { "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> 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> SingboxDomainDNSAddress = ["223.5.5.5", "223.6.6.6", "dhcp://auto"];
|
||||||
public static readonly List<string> Languages = new() { "zh-Hans", "zh-Hant", "en", "fa-Ir", "ru" };
|
public static readonly List<string> Languages = new() { "zh-Hans", "zh-Hant", "en", "fa-Ir", "ru", "hu" };
|
||||||
public static readonly List<string> Alpns = new() { "h3", "h2", "http/1.1", "h3,h2", "h2,http/1.1", "h3,h2,http/1.1", "" };
|
public static readonly List<string> Alpns = new() { "h3", "h2", "http/1.1", "h3,h2", "h2,http/1.1", "h3,h2,http/1.1", "" };
|
||||||
public static readonly List<string> LogLevels = new() { "debug", "info", "warning", "error", "none" };
|
public static readonly List<string> LogLevels = new() { "debug", "info", "warning", "error", "none" };
|
||||||
public static readonly List<string> InboundTags = new() { "socks", "http", "socks2", "http2" };
|
public static readonly List<string> InboundTags = new() { "socks", "socks2", "socks3" };
|
||||||
public static readonly List<string> RuleProtocols = new() { "http", "tls", "bittorrent" };
|
public static readonly List<string> RuleProtocols = new() { "http", "tls", "bittorrent" };
|
||||||
public static readonly List<string> RuleNetworks = new() { "", "tcp", "udp", "tcp,udp" };
|
public static readonly List<string> RuleNetworks = new() { "", "tcp", "udp", "tcp,udp" };
|
||||||
public static readonly List<string> destOverrideProtocols = ["http", "tls", "quic", "fakedns", "fakedns+others"];
|
public static readonly List<string> destOverrideProtocols = ["http", "tls", "quic", "fakedns", "fakedns+others"];
|
||||||
public static readonly List<string> TunMtus = new() { "1280", "1408", "1500", "9000" };
|
public static readonly List<string> TunMtus = new() { "1280", "1408", "1500", "9000" };
|
||||||
public static readonly List<string> TunStacks = new() { "gvisor", "system" };
|
public static readonly List<string> TunStacks = new() { "gvisor", "system", "mixed" };
|
||||||
public static readonly List<string> PresetMsgFilters = new() { "proxy", "direct", "block", "" };
|
public static readonly List<string> PresetMsgFilters = new() { "proxy", "direct", "block", "" };
|
||||||
public static readonly List<string> SingboxMuxs = new() { "h2mux", "smux", "yamux", "" };
|
public static readonly List<string> SingboxMuxs = new() { "h2mux", "smux", "yamux", "" };
|
||||||
public static readonly List<string> TuicCongestionControls = new() { "cubic", "new_reno", "bbr" };
|
public static readonly List<string> TuicCongestionControls = new() { "cubic", "new_reno", "bbr" };
|
||||||
|
|
||||||
public static readonly List<string> allowSelectType = new List<string> { "selector", "urltest", "loadbalance", "fallback" };
|
public static readonly List<string> allowSelectType = new() { "selector", "urltest", "loadbalance", "fallback" };
|
||||||
public static readonly List<string> notAllowTestType = new List<string> { "selector", "urltest", "direct", "reject", "compatible", "pass", "loadbalance", "fallback" };
|
public static readonly List<string> notAllowTestType = new() { "selector", "urltest", "direct", "reject", "compatible", "pass", "loadbalance", "fallback" };
|
||||||
public static readonly List<string> proxyVehicleType = new List<string> { "file", "http" };
|
public static readonly List<string> proxyVehicleType = new() { "file", "http" };
|
||||||
|
|
||||||
#endregion const
|
#endregion const
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
get
|
get
|
||||||
{
|
{
|
||||||
_statePort2 ??= Utils.GetFreePort(GetLocalPort(EInboundProtocol.api2));
|
_statePort2 ??= Utils.GetFreePort(GetLocalPort(EInboundProtocol.api2));
|
||||||
return _statePort2.Value;
|
return _statePort2.Value + (_config.TunModeItem.EnableTun ? 1 : 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,11 +46,18 @@
|
|||||||
|
|
||||||
public bool InitApp()
|
public bool InitApp()
|
||||||
{
|
{
|
||||||
_config = ConfigHandler.LoadConfig();
|
if (Utils.IsNonWindows() && Utils.HasWritePermission() == false)
|
||||||
if (_config == null)
|
{
|
||||||
|
Environment.SetEnvironmentVariable("V2RAYN_LOCAL_APPLICATION_DATA", "1", EnvironmentVariableTarget.Process);
|
||||||
|
}
|
||||||
|
|
||||||
|
Logging.Setup();
|
||||||
|
var config = ConfigHandler.LoadConfig();
|
||||||
|
if (config == null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
_config = config;
|
||||||
Thread.CurrentThread.CurrentUICulture = new(_config.UiItem.CurrentLanguage);
|
Thread.CurrentThread.CurrentUICulture = new(_config.UiItem.CurrentLanguage);
|
||||||
|
|
||||||
//Under Win10
|
//Under Win10
|
||||||
@@ -70,15 +77,20 @@
|
|||||||
|
|
||||||
public bool InitComponents()
|
public bool InitComponents()
|
||||||
{
|
{
|
||||||
Logging.Setup();
|
Logging.SaveLog($"v2rayN start up | {Utils.GetRuntimeInfo()}");
|
||||||
Logging.LoggingEnabled(true);
|
Logging.LoggingEnabled(_config.GuiItem.EnableLog);
|
||||||
Logging.SaveLog($"v2rayN start up | {Utils.GetVersion()} | {Utils.GetExePath()}");
|
|
||||||
Logging.SaveLog($"{Environment.OSVersion} - {(Environment.Is64BitOperatingSystem ? 64 : 32)}");
|
|
||||||
Logging.ClearLogs();
|
Logging.ClearLogs();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool Reset()
|
||||||
|
{
|
||||||
|
_statePort = null;
|
||||||
|
_statePort2 = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion Init
|
#endregion Init
|
||||||
|
|
||||||
#region Config
|
#region Config
|
||||||
@@ -159,7 +171,7 @@
|
|||||||
await ConfigHandler.SetDefaultServer(_config, lstModel);
|
await ConfigHandler.SetDefaultServer(_config, lstModel);
|
||||||
|
|
||||||
var lstServerStat = (_config.GuiItem.EnableStatistics ? StatisticsHandler.Instance.ServerStat : null) ?? [];
|
var lstServerStat = (_config.GuiItem.EnableStatistics ? StatisticsHandler.Instance.ServerStat : null) ?? [];
|
||||||
var lstProfileExs = ProfileExHandler.Instance.ProfileExs;
|
var lstProfileExs = await ProfileExHandler.Instance.GetProfileExs();
|
||||||
lstModel = (from t in lstModel
|
lstModel = (from t in lstModel
|
||||||
join t2 in lstServerStat on t.IndexId equals t2.IndexId into t2b
|
join t2 in lstServerStat on t.IndexId equals t2.IndexId into t2b
|
||||||
from t22 in t2b.DefaultIfEmpty()
|
from t22 in t2b.DefaultIfEmpty()
|
||||||
@@ -211,12 +223,12 @@
|
|||||||
|
|
||||||
public async Task<List<RoutingItem>?> RoutingItems()
|
public async Task<List<RoutingItem>?> RoutingItems()
|
||||||
{
|
{
|
||||||
return await SQLiteHelper.Instance.TableAsync<RoutingItem>().Where(it => it.Locked == false).OrderBy(t => t.Sort).ToListAsync();
|
return await SQLiteHelper.Instance.TableAsync<RoutingItem>().OrderBy(t => t.Sort).ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<RoutingItem?> GetRoutingItem(string id)
|
public async Task<RoutingItem?> GetRoutingItem(string id)
|
||||||
{
|
{
|
||||||
return await SQLiteHelper.Instance.TableAsync<RoutingItem>().FirstOrDefaultAsync(it => it.Locked == false && it.Id == id);
|
return await SQLiteHelper.Instance.TableAsync<RoutingItem>().FirstOrDefaultAsync(it => it.Id == id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<DNSItem>?> DNSItems()
|
public async Task<List<DNSItem>?> DNSItems()
|
||||||
@@ -247,7 +259,7 @@
|
|||||||
case ECoreType.sing_box:
|
case ECoreType.sing_box:
|
||||||
return Global.SsSecuritiesInSingbox;
|
return Global.SsSecuritiesInSingbox;
|
||||||
}
|
}
|
||||||
return Global.SsSecuritiesInSagerNet;
|
return Global.SsSecuritiesInSingbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ECoreType GetCoreType(ProfileItem profileItem, EConfigType eConfigType)
|
public ECoreType GetCoreType(ProfileItem profileItem, EConfigType eConfigType)
|
||||||
@@ -257,16 +269,8 @@
|
|||||||
return (ECoreType)profileItem.CoreType;
|
return (ECoreType)profileItem.CoreType;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_config.CoreTypeItem == null)
|
var item = _config.CoreTypeItem?.FirstOrDefault(it => it.ConfigType == eConfigType);
|
||||||
{
|
return item?.CoreType ?? ECoreType.Xray;
|
||||||
return ECoreType.Xray;
|
|
||||||
}
|
|
||||||
var item = _config.CoreTypeItem.FirstOrDefault(it => it.ConfigType == eConfigType);
|
|
||||||
if (item == null)
|
|
||||||
{
|
|
||||||
return ECoreType.Xray;
|
|
||||||
}
|
|
||||||
return item.CoreType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion Core Type
|
#endregion Core Type
|
||||||
|
|||||||
161
v2rayN/ServiceLib/Handler/AutoStartupHandler.cs
Normal file
161
v2rayN/ServiceLib/Handler/AutoStartupHandler.cs
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
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())
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows
|
||||||
|
|
||||||
|
private static async Task ClearTaskWindows()
|
||||||
|
{
|
||||||
|
var autoRunName = GetAutoRunNameWindows();
|
||||||
|
WindowsUtils.RegWriteValue(Global.AutoRunRegPath, autoRunName, "");
|
||||||
|
if (Utils.IsAdministrator())
|
||||||
|
{
|
||||||
|
AutoStartTaskService(autoRunName, "", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task SetTaskLinux()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var linuxConfig = Utils.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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ namespace ServiceLib.Handler
|
|||||||
|
|
||||||
private Dictionary<string, ProxiesItem>? _proxies;
|
private Dictionary<string, ProxiesItem>? _proxies;
|
||||||
public Dictionary<string, object> ProfileContent { get; set; }
|
public Dictionary<string, object> ProfileContent { get; set; }
|
||||||
|
private static readonly string _tag = "ClashApiHandler";
|
||||||
|
|
||||||
public async Task<Tuple<ClashProxies, ClashProviders>?> GetClashProxiesAsync(Config config)
|
public async Task<Tuple<ClashProxies, ClashProviders>?> GetClashProxiesAsync(Config config)
|
||||||
{
|
{
|
||||||
@@ -28,7 +29,7 @@ namespace ServiceLib.Handler
|
|||||||
return new Tuple<ClashProxies, ClashProviders>(clashProxies, clashProviders);
|
return new Tuple<ClashProxies, ClashProviders>(clashProxies, clashProviders);
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Delay(5000);
|
await Task.Delay(2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -109,7 +110,7 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog("GetClashProxyGroups", ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -125,7 +126,7 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +154,7 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +170,7 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -184,7 +185,7 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace ServiceLib.Handler
|
namespace ServiceLib.Handler
|
||||||
@@ -9,7 +9,7 @@ namespace ServiceLib.Handler
|
|||||||
public class ConfigHandler
|
public class ConfigHandler
|
||||||
{
|
{
|
||||||
private static readonly string _configRes = Global.ConfigFileName;
|
private static readonly string _configRes = Global.ConfigFileName;
|
||||||
private static readonly object _objLock = new();
|
private static readonly string _tag = "ConfigHandler";
|
||||||
|
|
||||||
#region ConfigHandler
|
#region ConfigHandler
|
||||||
|
|
||||||
@@ -62,17 +62,14 @@ namespace ServiceLib.Handler
|
|||||||
{
|
{
|
||||||
if (config.Inbound.Count > 0)
|
if (config.Inbound.Count > 0)
|
||||||
{
|
{
|
||||||
config.Inbound[0].Protocol = EInboundProtocol.socks.ToString();
|
config.Inbound.First().Protocol = EInboundProtocol.socks.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
config.RoutingBasicItem ??= new()
|
|
||||||
{
|
|
||||||
EnableRoutingAdvanced = true
|
|
||||||
};
|
|
||||||
|
|
||||||
|
config.RoutingBasicItem ??= new();
|
||||||
if (Utils.IsNullOrEmpty(config.RoutingBasicItem.DomainStrategy))
|
if (Utils.IsNullOrEmpty(config.RoutingBasicItem.DomainStrategy))
|
||||||
{
|
{
|
||||||
config.RoutingBasicItem.DomainStrategy = Global.DomainStrategies[0];//"IPIfNonMatch";
|
config.RoutingBasicItem.DomainStrategy = Global.DomainStrategies.First();
|
||||||
}
|
}
|
||||||
|
|
||||||
config.KcpItem ??= new KcpItem
|
config.KcpItem ??= new KcpItem
|
||||||
@@ -113,7 +110,7 @@ namespace ServiceLib.Handler
|
|||||||
{
|
{
|
||||||
if (Thread.CurrentThread.CurrentCulture.Name.Equals("zh-cn", StringComparison.CurrentCultureIgnoreCase))
|
if (Thread.CurrentThread.CurrentCulture.Name.Equals("zh-cn", StringComparison.CurrentCultureIgnoreCase))
|
||||||
{
|
{
|
||||||
config.UiItem.CurrentLanguage = Global.Languages[0];
|
config.UiItem.CurrentLanguage = Global.Languages.First();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -122,10 +119,6 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
|
|
||||||
config.ConstItem ??= new ConstItem();
|
config.ConstItem ??= new ConstItem();
|
||||||
if (Utils.IsNullOrEmpty(config.ConstItem.DefIEProxyExceptions))
|
|
||||||
{
|
|
||||||
config.ConstItem.DefIEProxyExceptions = Global.IEProxyExceptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
config.SpeedTestItem ??= new();
|
config.SpeedTestItem ??= new();
|
||||||
if (config.SpeedTestItem.SpeedTestTimeout < 10)
|
if (config.SpeedTestItem.SpeedTestTimeout < 10)
|
||||||
@@ -134,7 +127,7 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
if (Utils.IsNullOrEmpty(config.SpeedTestItem.SpeedTestUrl))
|
if (Utils.IsNullOrEmpty(config.SpeedTestItem.SpeedTestUrl))
|
||||||
{
|
{
|
||||||
config.SpeedTestItem.SpeedTestUrl = Global.SpeedTestUrls[0];
|
config.SpeedTestItem.SpeedTestUrl = Global.SpeedTestUrls.First();
|
||||||
}
|
}
|
||||||
if (Utils.IsNullOrEmpty(config.SpeedTestItem.SpeedPingTestUrl))
|
if (Utils.IsNullOrEmpty(config.SpeedTestItem.SpeedPingTestUrl))
|
||||||
{
|
{
|
||||||
@@ -150,7 +143,7 @@ namespace ServiceLib.Handler
|
|||||||
|
|
||||||
config.Mux4SboxItem ??= new()
|
config.Mux4SboxItem ??= new()
|
||||||
{
|
{
|
||||||
Protocol = Global.SingboxMuxs[0],
|
Protocol = Global.SingboxMuxs.First(),
|
||||||
MaxConnections = 8
|
MaxConnections = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -162,6 +155,23 @@ namespace ServiceLib.Handler
|
|||||||
config.ClashUIItem ??= new();
|
config.ClashUIItem ??= new();
|
||||||
config.SystemProxyItem ??= new();
|
config.SystemProxyItem ??= new();
|
||||||
config.WebDavItem ??= new();
|
config.WebDavItem ??= new();
|
||||||
|
config.CheckUpdateItem ??= new();
|
||||||
|
config.Fragment4RayItem ??= new()
|
||||||
|
{
|
||||||
|
Packets = "tlshello",
|
||||||
|
Length = "100-200",
|
||||||
|
Interval = "10-20"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (Utils.IsNotEmpty(config.ConstItem.DefIEProxyExceptions))
|
||||||
|
{
|
||||||
|
config.SystemProxyItem.SystemProxyExceptions = $"{config.ConstItem.DefIEProxyExceptions};{config.SystemProxyItem.SystemProxyExceptions}";
|
||||||
|
config.ConstItem.DefIEProxyExceptions = string.Empty;
|
||||||
|
}
|
||||||
|
if (config.SystemProxyItem.SystemProxyExceptions.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
config.SystemProxyItem.SystemProxyExceptions = Utils.IsWindows() ? Global.SystemProxyExceptionsWindows : Global.SystemProxyExceptionsLinux;
|
||||||
|
}
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
@@ -173,30 +183,26 @@ namespace ServiceLib.Handler
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static async Task<int> SaveConfig(Config config)
|
public static async Task<int> SaveConfig(Config config)
|
||||||
{
|
{
|
||||||
lock (_objLock)
|
try
|
||||||
{
|
{
|
||||||
try
|
//save temp file
|
||||||
{
|
var resPath = Utils.GetConfigPath(_configRes);
|
||||||
//save temp file
|
var tempPath = $"{resPath}_temp";
|
||||||
var resPath = Utils.GetConfigPath(_configRes);
|
|
||||||
var tempPath = $"{resPath}_temp";
|
|
||||||
if (JsonUtils.ToFile(config, tempPath) != 0)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (File.Exists(resPath))
|
var content = JsonUtils.Serialize(config, true, true);
|
||||||
{
|
if (content.IsNullOrEmpty())
|
||||||
File.Delete(resPath);
|
|
||||||
}
|
|
||||||
//rename
|
|
||||||
File.Move(tempPath, resPath);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
{
|
||||||
Logging.SaveLog("ToJsonFile", ex);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
await File.WriteAllTextAsync(tempPath, content);
|
||||||
|
|
||||||
|
//rename
|
||||||
|
File.Move(tempPath, resPath, true);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(_tag, ex);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -239,6 +245,7 @@ namespace ServiceLib.Handler
|
|||||||
item.PublicKey = profileItem.PublicKey;
|
item.PublicKey = profileItem.PublicKey;
|
||||||
item.ShortId = profileItem.ShortId;
|
item.ShortId = profileItem.ShortId;
|
||||||
item.SpiderX = profileItem.SpiderX;
|
item.SpiderX = profileItem.SpiderX;
|
||||||
|
item.Extra = profileItem.Extra;
|
||||||
}
|
}
|
||||||
|
|
||||||
var ret = item.ConfigType switch
|
var ret = item.ConfigType switch
|
||||||
@@ -383,7 +390,7 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
|
|
||||||
var item = await SQLiteHelper.Instance.TableAsync<ProfileItem>().FirstOrDefaultAsync(t => t.Port > 0);
|
var item = await SQLiteHelper.Instance.TableAsync<ProfileItem>().FirstOrDefaultAsync(t => t.Port > 0);
|
||||||
return await SetDefaultServerIndex(config, item.IndexId);
|
return await SetDefaultServerIndex(config, item?.IndexId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<ProfileItem?> GetDefaultServer(Config config)
|
public static async Task<ProfileItem?> GetDefaultServer(Config config)
|
||||||
@@ -429,7 +436,7 @@ namespace ServiceLib.Handler
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
sort = ProfileExHandler.Instance.GetSort(lstProfile[0].IndexId) - 1;
|
sort = ProfileExHandler.Instance.GetSort(lstProfile.First().IndexId) - 1;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -465,7 +472,7 @@ namespace ServiceLib.Handler
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EMove.Position:
|
case EMove.Position:
|
||||||
sort = pos * 10 + 1;
|
sort = (pos * 10) + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -500,7 +507,7 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -746,7 +753,7 @@ namespace ServiceLib.Handler
|
|||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
var lstProfileExs = ProfileExHandler.Instance.ProfileExs;
|
var lstProfileExs = await ProfileExHandler.Instance.GetProfileExs();
|
||||||
var lstProfile = (from t in lstModel
|
var lstProfile = (from t in lstModel
|
||||||
join t3 in lstProfileExs on t.IndexId equals t3.IndexId into t3b
|
join t3 in lstProfileExs on t.IndexId equals t3.IndexId into t3b
|
||||||
from t33 in t3b.DefaultIfEmpty()
|
from t33 in t3b.DefaultIfEmpty()
|
||||||
@@ -766,69 +773,66 @@ namespace ServiceLib.Handler
|
|||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
Enum.TryParse(colName, true, out EServerColName name);
|
Enum.TryParse(colName, true, out EServerColName name);
|
||||||
var propertyName = string.Empty;
|
|
||||||
switch (name)
|
|
||||||
{
|
|
||||||
case EServerColName.ConfigType:
|
|
||||||
case EServerColName.Remarks:
|
|
||||||
case EServerColName.Address:
|
|
||||||
case EServerColName.Port:
|
|
||||||
case EServerColName.Network:
|
|
||||||
case EServerColName.StreamSecurity:
|
|
||||||
propertyName = name.ToString();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EServerColName.DelayVal:
|
|
||||||
propertyName = "Delay";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EServerColName.SpeedVal:
|
|
||||||
propertyName = "Speed";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EServerColName.SubRemarks:
|
|
||||||
propertyName = "Subid";
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var items = lstProfile.AsQueryable();
|
|
||||||
|
|
||||||
if (asc)
|
if (asc)
|
||||||
{
|
{
|
||||||
lstProfile = items.OrderBy(propertyName).ToList();
|
lstProfile = name switch
|
||||||
|
{
|
||||||
|
EServerColName.ConfigType => lstProfile.OrderBy(t => t.ConfigType).ToList(),
|
||||||
|
EServerColName.Remarks => lstProfile.OrderBy(t => t.Remarks).ToList(),
|
||||||
|
EServerColName.Address => lstProfile.OrderBy(t => t.Address).ToList(),
|
||||||
|
EServerColName.Port => lstProfile.OrderBy(t => t.Port).ToList(),
|
||||||
|
EServerColName.Network => lstProfile.OrderBy(t => t.Network).ToList(),
|
||||||
|
EServerColName.StreamSecurity => lstProfile.OrderBy(t => t.StreamSecurity).ToList(),
|
||||||
|
EServerColName.DelayVal => lstProfile.OrderBy(t => t.Delay).ToList(),
|
||||||
|
EServerColName.SpeedVal => lstProfile.OrderBy(t => t.Speed).ToList(),
|
||||||
|
EServerColName.SubRemarks => lstProfile.OrderBy(t => t.Subid).ToList(),
|
||||||
|
_ => lstProfile
|
||||||
|
};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lstProfile = items.OrderByDescending(propertyName).ToList();
|
lstProfile = name switch
|
||||||
|
{
|
||||||
|
EServerColName.ConfigType => lstProfile.OrderByDescending(t => t.ConfigType).ToList(),
|
||||||
|
EServerColName.Remarks => lstProfile.OrderByDescending(t => t.Remarks).ToList(),
|
||||||
|
EServerColName.Address => lstProfile.OrderByDescending(t => t.Address).ToList(),
|
||||||
|
EServerColName.Port => lstProfile.OrderByDescending(t => t.Port).ToList(),
|
||||||
|
EServerColName.Network => lstProfile.OrderByDescending(t => t.Network).ToList(),
|
||||||
|
EServerColName.StreamSecurity => lstProfile.OrderByDescending(t => t.StreamSecurity).ToList(),
|
||||||
|
EServerColName.DelayVal => lstProfile.OrderByDescending(t => t.Delay).ToList(),
|
||||||
|
EServerColName.SpeedVal => lstProfile.OrderByDescending(t => t.Speed).ToList(),
|
||||||
|
EServerColName.SubRemarks => lstProfile.OrderByDescending(t => t.Subid).ToList(),
|
||||||
|
_ => lstProfile
|
||||||
|
};
|
||||||
}
|
}
|
||||||
for (int i = 0; i < lstProfile.Count; i++)
|
|
||||||
|
for (var i = 0; i < lstProfile.Count; i++)
|
||||||
{
|
{
|
||||||
ProfileExHandler.Instance.SetSort(lstProfile[i].IndexId, (i + 1) * 10);
|
ProfileExHandler.Instance.SetSort(lstProfile[i].IndexId, (i + 1) * 10);
|
||||||
}
|
}
|
||||||
if (name == EServerColName.DelayVal)
|
switch (name)
|
||||||
{
|
{
|
||||||
var maxSort = lstProfile.Max(t => t.Sort) + 10;
|
case EServerColName.DelayVal:
|
||||||
foreach (var item in lstProfile)
|
|
||||||
{
|
|
||||||
if (item.Delay <= 0)
|
|
||||||
{
|
{
|
||||||
ProfileExHandler.Instance.SetSort(item.IndexId, maxSort);
|
var maxSort = lstProfile.Max(t => t.Sort) + 10;
|
||||||
|
foreach (var item in lstProfile.Where(item => item.Delay <= 0))
|
||||||
|
{
|
||||||
|
ProfileExHandler.Instance.SetSort(item.IndexId, maxSort);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
case EServerColName.SpeedVal:
|
||||||
}
|
|
||||||
if (name == EServerColName.SpeedVal)
|
|
||||||
{
|
|
||||||
var maxSort = lstProfile.Max(t => t.Sort) + 10;
|
|
||||||
foreach (var item in lstProfile)
|
|
||||||
{
|
|
||||||
if (item.Speed <= 0)
|
|
||||||
{
|
{
|
||||||
ProfileExHandler.Instance.SetSort(item.IndexId, maxSort);
|
var maxSort = lstProfile.Max(t => t.Sort) + 10;
|
||||||
|
foreach (var item in lstProfile.Where(item => item.Speed <= 0))
|
||||||
|
{
|
||||||
|
ProfileExHandler.Instance.SetSort(item.IndexId, maxSort);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -957,7 +961,6 @@ namespace ServiceLib.Handler
|
|||||||
&& o.Address == n.Address
|
&& o.Address == n.Address
|
||||||
&& o.Port == n.Port
|
&& o.Port == n.Port
|
||||||
&& o.Id == n.Id
|
&& o.Id == n.Id
|
||||||
&& o.AlterId == n.AlterId
|
|
||||||
&& o.Security == n.Security
|
&& o.Security == n.Security
|
||||||
&& o.Network == n.Network
|
&& o.Network == n.Network
|
||||||
&& o.HeaderType == n.HeaderType
|
&& o.HeaderType == n.HeaderType
|
||||||
@@ -966,6 +969,10 @@ namespace ServiceLib.Handler
|
|||||||
&& (o.ConfigType == EConfigType.Trojan || o.StreamSecurity == n.StreamSecurity)
|
&& (o.ConfigType == EConfigType.Trojan || o.StreamSecurity == n.StreamSecurity)
|
||||||
&& o.Flow == n.Flow
|
&& o.Flow == n.Flow
|
||||||
&& o.Sni == n.Sni
|
&& o.Sni == n.Sni
|
||||||
|
&& o.Alpn == n.Alpn
|
||||||
|
&& o.Fingerprint == n.Fingerprint
|
||||||
|
&& o.PublicKey == n.PublicKey
|
||||||
|
&& o.ShortId == n.ShortId
|
||||||
&& (!remarks || o.Remarks == n.Remarks);
|
&& (!remarks || o.Remarks == n.Remarks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -987,7 +994,7 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog("Remove Item", ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1023,6 +1030,35 @@ namespace ServiceLib.Handler
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task<ProfileItem?> GetPreSocksItem(Config config, ProfileItem node, ECoreType coreType)
|
||||||
|
{
|
||||||
|
ProfileItem? itemSocks = null;
|
||||||
|
if (node.ConfigType != EConfigType.Custom && coreType != ECoreType.sing_box && config.TunModeItem.EnableTun)
|
||||||
|
{
|
||||||
|
itemSocks = new ProfileItem()
|
||||||
|
{
|
||||||
|
CoreType = ECoreType.sing_box,
|
||||||
|
ConfigType = EConfigType.SOCKS,
|
||||||
|
Address = Global.Loopback,
|
||||||
|
Sni = node.Address, //Tun2SocksAddress
|
||||||
|
Port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if ((node.ConfigType == EConfigType.Custom && node.PreSocksPort > 0))
|
||||||
|
{
|
||||||
|
var preCoreType = config.RunningCoreType = config.TunModeItem.EnableTun ? ECoreType.sing_box : ECoreType.Xray;
|
||||||
|
itemSocks = new ProfileItem()
|
||||||
|
{
|
||||||
|
CoreType = preCoreType,
|
||||||
|
ConfigType = EConfigType.SOCKS,
|
||||||
|
Address = Global.Loopback,
|
||||||
|
Port = node.PreSocksPort.Value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemSocks;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion Server
|
#endregion Server
|
||||||
|
|
||||||
#region Batch add servers
|
#region Batch add servers
|
||||||
@@ -1034,14 +1070,14 @@ namespace ServiceLib.Handler
|
|||||||
/// <param name="strData"></param>
|
/// <param name="strData"></param>
|
||||||
/// <param name="subid"></param>
|
/// <param name="subid"></param>
|
||||||
/// <returns>成功导入的数量</returns>
|
/// <returns>成功导入的数量</returns>
|
||||||
private static async Task<int> AddBatchServers(Config config, string strData, string subid, bool isSub, List<ProfileItem> lstOriSub)
|
private static async Task<int> AddBatchServersCommon(Config config, string strData, string subid, bool isSub)
|
||||||
{
|
{
|
||||||
if (Utils.IsNullOrEmpty(strData))
|
if (Utils.IsNullOrEmpty(strData))
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
string subFilter = string.Empty;
|
var subFilter = string.Empty;
|
||||||
//remove sub items
|
//remove sub items
|
||||||
if (isSub && Utils.IsNotEmpty(subid))
|
if (isSub && Utils.IsNotEmpty(subid))
|
||||||
{
|
{
|
||||||
@@ -1049,16 +1085,14 @@ namespace ServiceLib.Handler
|
|||||||
subFilter = (await AppHandler.Instance.GetSubItem(subid))?.Filter ?? "";
|
subFilter = (await AppHandler.Instance.GetSubItem(subid))?.Filter ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
int countServers = 0;
|
var countServers = 0;
|
||||||
//Check for duplicate indexId
|
|
||||||
List<string>? lstDbIndexId = null;
|
|
||||||
List<ProfileItem> lstAdd = new();
|
List<ProfileItem> lstAdd = new();
|
||||||
var arrData = strData.Split(Environment.NewLine.ToCharArray()).Where(t => !t.IsNullOrEmpty());
|
var arrData = strData.Split(Environment.NewLine.ToCharArray()).Where(t => !t.IsNullOrEmpty());
|
||||||
if (isSub)
|
if (isSub)
|
||||||
{
|
{
|
||||||
arrData = arrData.Distinct();
|
arrData = arrData.Distinct();
|
||||||
}
|
}
|
||||||
foreach (string str in arrData)
|
foreach (var str in arrData)
|
||||||
{
|
{
|
||||||
//maybe sub
|
//maybe sub
|
||||||
if (!isSub && (str.StartsWith(Global.HttpsProtocol) || str.StartsWith(Global.HttpProtocol)))
|
if (!isSub && (str.StartsWith(Global.HttpsProtocol) || str.StartsWith(Global.HttpProtocol)))
|
||||||
@@ -1075,35 +1109,12 @@ namespace ServiceLib.Handler
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//exist sub items
|
//exist sub items //filter
|
||||||
if (isSub && Utils.IsNotEmpty(subid))
|
if (isSub && Utils.IsNotEmpty(subid) && Utils.IsNotEmpty(subFilter))
|
||||||
{
|
{
|
||||||
var existItem = lstOriSub?.FirstOrDefault(t => t.IsSub == isSub
|
if (!Regex.IsMatch(profileItem.Remarks, subFilter))
|
||||||
&& config.UiItem.EnableUpdateSubOnlyRemarksExist ? t.Remarks == profileItem.Remarks : CompareProfileItem(t, profileItem, true));
|
|
||||||
if (existItem != null)
|
|
||||||
{
|
{
|
||||||
//Check for duplicate indexId
|
continue;
|
||||||
if (lstDbIndexId is null)
|
|
||||||
{
|
|
||||||
lstDbIndexId = await AppHandler.Instance.ProfileItemIndexes("");
|
|
||||||
}
|
|
||||||
if (lstAdd.Any(t => t.IndexId == existItem.IndexId)
|
|
||||||
|| lstDbIndexId.Any(t => t == existItem.IndexId))
|
|
||||||
{
|
|
||||||
profileItem.IndexId = string.Empty;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
profileItem.IndexId = existItem.IndexId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//filter
|
|
||||||
if (Utils.IsNotEmpty(subFilter))
|
|
||||||
{
|
|
||||||
if (!Regex.IsMatch(profileItem.Remarks, subFilter))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
profileItem.Subid = subid;
|
profileItem.Subid = subid;
|
||||||
@@ -1138,7 +1149,7 @@ namespace ServiceLib.Handler
|
|||||||
return countServers;
|
return countServers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<int> AddBatchServers4Custom(Config config, string strData, string subid, bool isSub, List<ProfileItem> lstOriSub)
|
private static async Task<int> AddBatchServers4Custom(Config config, string strData, string subid, bool isSub)
|
||||||
{
|
{
|
||||||
if (Utils.IsNullOrEmpty(strData))
|
if (Utils.IsNullOrEmpty(strData))
|
||||||
{
|
{
|
||||||
@@ -1222,10 +1233,7 @@ namespace ServiceLib.Handler
|
|||||||
{
|
{
|
||||||
await RemoveServerViaSubid(config, subid, isSub);
|
await RemoveServerViaSubid(config, subid, isSub);
|
||||||
}
|
}
|
||||||
if (isSub && lstOriSub?.Count == 1)
|
|
||||||
{
|
|
||||||
profileItem.IndexId = lstOriSub[0].IndexId;
|
|
||||||
}
|
|
||||||
profileItem.Subid = subid;
|
profileItem.Subid = subid;
|
||||||
profileItem.IsSub = isSub;
|
profileItem.IsSub = isSub;
|
||||||
profileItem.PreSocksPort = preSocksPort;
|
profileItem.PreSocksPort = preSocksPort;
|
||||||
@@ -1239,7 +1247,7 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<int> AddBatchServers4SsSIP008(Config config, string strData, string subid, bool isSub, List<ProfileItem> lstOriSub)
|
private static async Task<int> AddBatchServers4SsSIP008(Config config, string strData, string subid, bool isSub)
|
||||||
{
|
{
|
||||||
if (Utils.IsNullOrEmpty(strData))
|
if (Utils.IsNullOrEmpty(strData))
|
||||||
{
|
{
|
||||||
@@ -1278,34 +1286,61 @@ namespace ServiceLib.Handler
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
List<ProfileItem>? lstOriSub = null;
|
List<ProfileItem>? lstOriSub = null;
|
||||||
|
ProfileItem? activeProfile = null;
|
||||||
if (isSub && Utils.IsNotEmpty(subid))
|
if (isSub && Utils.IsNotEmpty(subid))
|
||||||
{
|
{
|
||||||
lstOriSub = await AppHandler.Instance.ProfileItems(subid);
|
lstOriSub = await AppHandler.Instance.ProfileItems(subid);
|
||||||
|
activeProfile = lstOriSub?.FirstOrDefault(t => t.IndexId == config.IndexId);
|
||||||
}
|
}
|
||||||
|
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
if (Utils.IsBase64String(strData))
|
if (Utils.IsBase64String(strData))
|
||||||
{
|
{
|
||||||
counter = await AddBatchServers(config, Utils.Base64Decode(strData), subid, isSub, lstOriSub);
|
counter = await AddBatchServersCommon(config, Utils.Base64Decode(strData), subid, isSub);
|
||||||
}
|
}
|
||||||
if (counter < 1)
|
if (counter < 1)
|
||||||
{
|
{
|
||||||
counter = await AddBatchServers(config, strData, subid, isSub, lstOriSub);
|
counter = await AddBatchServersCommon(config, strData, subid, isSub);
|
||||||
}
|
}
|
||||||
if (counter < 1)
|
if (counter < 1)
|
||||||
{
|
{
|
||||||
counter = await AddBatchServers(config, Utils.Base64Decode(strData), subid, isSub, lstOriSub);
|
counter = await AddBatchServersCommon(config, Utils.Base64Decode(strData), subid, isSub);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (counter < 1)
|
if (counter < 1)
|
||||||
{
|
{
|
||||||
counter = await AddBatchServers4SsSIP008(config, strData, subid, isSub, lstOriSub);
|
counter = await AddBatchServers4SsSIP008(config, strData, subid, isSub);
|
||||||
}
|
}
|
||||||
|
|
||||||
//maybe other sub
|
//maybe other sub
|
||||||
if (counter < 1)
|
if (counter < 1)
|
||||||
{
|
{
|
||||||
counter = await AddBatchServers4Custom(config, strData, subid, isSub, lstOriSub);
|
counter = await AddBatchServers4Custom(config, strData, subid, isSub);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Select active node
|
||||||
|
if (activeProfile != null)
|
||||||
|
{
|
||||||
|
var lstSub = await AppHandler.Instance.ProfileItems(subid);
|
||||||
|
var existItem = lstSub?.FirstOrDefault(t => config.UiItem.EnableUpdateSubOnlyRemarksExist ? t.Remarks == activeProfile.Remarks : CompareProfileItem(t, activeProfile, true));
|
||||||
|
if (existItem != null)
|
||||||
|
{
|
||||||
|
await ConfigHandler.SetDefaultServerIndex(config, existItem.IndexId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Keep the last traffic statistics
|
||||||
|
if (lstOriSub != null)
|
||||||
|
{
|
||||||
|
var lstSub = await AppHandler.Instance.ProfileItems(subid);
|
||||||
|
foreach (var item in lstSub)
|
||||||
|
{
|
||||||
|
var existItem = lstOriSub?.FirstOrDefault(t => config.UiItem.EnableUpdateSubOnlyRemarksExist ? t.Remarks == item.Remarks : CompareProfileItem(t, item, true));
|
||||||
|
if (existItem != null)
|
||||||
|
{
|
||||||
|
await StatisticsHandler.Instance.CloneServerStatItem(existItem.IndexId, item.IndexId);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return counter;
|
return counter;
|
||||||
@@ -1373,6 +1408,7 @@ namespace ServiceLib.Handler
|
|||||||
item.PrevProfile = subItem.PrevProfile;
|
item.PrevProfile = subItem.PrevProfile;
|
||||||
item.NextProfile = subItem.NextProfile;
|
item.NextProfile = subItem.NextProfile;
|
||||||
item.PreSocksPort = subItem.PreSocksPort;
|
item.PreSocksPort = subItem.PreSocksPort;
|
||||||
|
item.Memo = subItem.Memo;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Utils.IsNullOrEmpty(item.Id))
|
if (Utils.IsNullOrEmpty(item.Id))
|
||||||
@@ -1609,7 +1645,7 @@ namespace ServiceLib.Handler
|
|||||||
var item = await AppHandler.Instance.GetRoutingItem(config.RoutingBasicItem.RoutingIndexId);
|
var item = await AppHandler.Instance.GetRoutingItem(config.RoutingBasicItem.RoutingIndexId);
|
||||||
if (item is null)
|
if (item is null)
|
||||||
{
|
{
|
||||||
var item2 = await SQLiteHelper.Instance.TableAsync<RoutingItem>().FirstOrDefaultAsync(t => t.Locked == false);
|
var item2 = await SQLiteHelper.Instance.TableAsync<RoutingItem>().FirstOrDefaultAsync();
|
||||||
await SetDefaultRouting(config, item2);
|
await SetDefaultRouting(config, item2);
|
||||||
return item2;
|
return item2;
|
||||||
}
|
}
|
||||||
@@ -1683,6 +1719,15 @@ namespace ServiceLib.Handler
|
|||||||
{
|
{
|
||||||
var ver = "V3-";
|
var ver = "V3-";
|
||||||
var items = await AppHandler.Instance.RoutingItems();
|
var items = await AppHandler.Instance.RoutingItems();
|
||||||
|
|
||||||
|
//TODO Temporary code to be removed later
|
||||||
|
var lockItem = items?.FirstOrDefault(t => t.Locked == true);
|
||||||
|
if (lockItem != null)
|
||||||
|
{
|
||||||
|
await ConfigHandler.RemoveRoutingItem(lockItem);
|
||||||
|
items = await AppHandler.Instance.RoutingItems();
|
||||||
|
}
|
||||||
|
|
||||||
if (!blImportAdvancedRules && items.Where(t => t.Remarks.StartsWith(ver)).ToList().Count > 0)
|
if (!blImportAdvancedRules && items.Where(t => t.Remarks.StartsWith(ver)).ToList().Count > 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1723,11 +1768,6 @@ namespace ServiceLib.Handler
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<RoutingItem?> GetLockedRoutingItem(Config config)
|
|
||||||
{
|
|
||||||
return await SQLiteHelper.Instance.TableAsync<RoutingItem>().FirstOrDefaultAsync(it => it.Locked == true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task RemoveRoutingItem(RoutingItem routingItem)
|
public static async Task RemoveRoutingItem(RoutingItem routingItem)
|
||||||
{
|
{
|
||||||
await SQLiteHelper.Instance.DeleteAsync(routingItem);
|
await SQLiteHelper.Instance.DeleteAsync(routingItem);
|
||||||
@@ -1835,6 +1875,16 @@ namespace ServiceLib.Handler
|
|||||||
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[1] + "v2ray.json"));
|
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[1] + "v2ray.json"));
|
||||||
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[1] + "sing_box.json"));
|
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[1] + "sing_box.json"));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case EPresetType.Iran:
|
||||||
|
config.ConstItem.GeoSourceUrl = Global.GeoFilesSources[2];
|
||||||
|
config.ConstItem.SrsSourceUrl = Global.SingboxRulesetSources[2];
|
||||||
|
config.ConstItem.RouteRulesTemplateSourceUrl = Global.RoutingRulesSources[2];
|
||||||
|
|
||||||
|
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[2] + "v2ray.json"));
|
||||||
|
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[2] + "sing_box.json"));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class CoreConfigHandler
|
public class CoreConfigHandler
|
||||||
{
|
{
|
||||||
|
private static readonly string _tag = "CoreConfigHandler";
|
||||||
|
|
||||||
public static async Task<RetResult> GenerateClientConfig(ProfileItem node, string? fileName)
|
public static async Task<RetResult> GenerateClientConfig(ProfileItem node, string? fileName)
|
||||||
{
|
{
|
||||||
var config = AppHandler.Instance.Config;
|
var config = AppHandler.Instance.Config;
|
||||||
@@ -12,18 +14,12 @@
|
|||||||
|
|
||||||
if (node.ConfigType == EConfigType.Custom)
|
if (node.ConfigType == EConfigType.Custom)
|
||||||
{
|
{
|
||||||
if (node.CoreType is ECoreType.mihomo)
|
result = node.CoreType switch
|
||||||
{
|
{
|
||||||
result = await new CoreConfigClashService(config).GenerateClientCustomConfig(node, fileName);
|
ECoreType.mihomo => await new CoreConfigClashService(config).GenerateClientCustomConfig(node, fileName),
|
||||||
}
|
ECoreType.sing_box => await new CoreConfigSingboxService(config).GenerateClientCustomConfig(node, fileName),
|
||||||
if (node.CoreType is ECoreType.sing_box)
|
_ => await GenerateClientCustomConfig(node, fileName)
|
||||||
{
|
};
|
||||||
result = await new CoreConfigSingboxService(config).GenerateClientCustomConfig(node, fileName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = await GenerateClientCustomConfig(node, fileName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (AppHandler.Instance.GetCoreType(node, node.ConfigType) == ECoreType.sing_box)
|
else if (AppHandler.Instance.GetCoreType(node, node.ConfigType) == ECoreType.sing_box)
|
||||||
{
|
{
|
||||||
@@ -88,7 +84,7 @@
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog("GenerateClientCustomConfig", ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ namespace ServiceLib.Handler
|
|||||||
private Config _config;
|
private Config _config;
|
||||||
private Process? _process;
|
private Process? _process;
|
||||||
private Process? _processPre;
|
private Process? _processPre;
|
||||||
|
private int _linuxSudoPid = -1;
|
||||||
private Action<bool, string>? _updateFunc;
|
private Action<bool, string>? _updateFunc;
|
||||||
|
private const string _tag = "CoreHandler";
|
||||||
|
|
||||||
public async Task Init(Config config, Action<bool, string> updateFunc)
|
public async Task Init(Config config, Action<bool, string> updateFunc)
|
||||||
{
|
{
|
||||||
@@ -23,19 +25,23 @@ namespace ServiceLib.Handler
|
|||||||
Environment.SetEnvironmentVariable("V2RAY_LOCATION_ASSET", Utils.GetBinPath(""), EnvironmentVariableTarget.Process);
|
Environment.SetEnvironmentVariable("V2RAY_LOCATION_ASSET", Utils.GetBinPath(""), EnvironmentVariableTarget.Process);
|
||||||
Environment.SetEnvironmentVariable("XRAY_LOCATION_ASSET", Utils.GetBinPath(""), EnvironmentVariableTarget.Process);
|
Environment.SetEnvironmentVariable("XRAY_LOCATION_ASSET", Utils.GetBinPath(""), EnvironmentVariableTarget.Process);
|
||||||
|
|
||||||
if (Utils.IsLinux())
|
if (Utils.IsNonWindows())
|
||||||
{
|
{
|
||||||
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo();
|
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo();
|
||||||
foreach (var it in coreInfo)
|
foreach (var it in coreInfo)
|
||||||
{
|
{
|
||||||
if (it.CoreType == ECoreType.v2rayN)
|
if (it.CoreType == ECoreType.v2rayN)
|
||||||
{
|
{
|
||||||
|
if (Utils.UpgradeAppExists(out var upgradeFileName))
|
||||||
|
{
|
||||||
|
await Utils.SetLinuxChmod(upgradeFileName);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var vName in it.CoreExes)
|
foreach (var name in it.CoreExes)
|
||||||
{
|
{
|
||||||
var exe = Utils.GetExeName(Utils.GetBinPath(vName, it.CoreType.ToString()));
|
var exe = Utils.GetBinPath(Utils.GetExeName(name), it.CoreType.ToString());
|
||||||
if (File.Exists(exe))
|
if (File.Exists(exe))
|
||||||
{
|
{
|
||||||
await Utils.SetLinuxChmod(exe);
|
await Utils.SetLinuxChmod(exe);
|
||||||
@@ -49,259 +55,149 @@ namespace ServiceLib.Handler
|
|||||||
{
|
{
|
||||||
if (node == null)
|
if (node == null)
|
||||||
{
|
{
|
||||||
ShowMsg(false, ResUI.CheckServerSettings);
|
UpdateFunc(false, ResUI.CheckServerSettings);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileName = Utils.GetConfigPath(Global.CoreConfigFileName);
|
var fileName = Utils.GetConfigPath(Global.CoreConfigFileName);
|
||||||
var result = await CoreConfigHandler.GenerateClientConfig(node, fileName);
|
var result = await CoreConfigHandler.GenerateClientConfig(node, fileName);
|
||||||
ShowMsg(false, result.Msg);
|
|
||||||
if (result.Success != true)
|
if (result.Success != true)
|
||||||
{
|
{
|
||||||
|
UpdateFunc(true, result.Msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
ShowMsg(true, $"{node.GetSummary()}");
|
|
||||||
await CoreStop();
|
|
||||||
await CoreStart(node);
|
|
||||||
|
|
||||||
//In tun mode, do a delay check and restart the core
|
UpdateFunc(true, $"{node.GetSummary()}");
|
||||||
//if (_config.tunModeItem.enableTun)
|
UpdateFunc(false, $"{Utils.GetRuntimeInfo()}");
|
||||||
//{
|
UpdateFunc(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
|
||||||
// Observable.Range(1, 1)
|
await CoreStop();
|
||||||
// .Delay(TimeSpan.FromSeconds(15))
|
await Task.Delay(100);
|
||||||
// .Subscribe(x =>
|
await CoreStart(node);
|
||||||
// {
|
await CoreStartPreService(node);
|
||||||
// {
|
|
||||||
// if (_process == null || _process.HasExited)
|
|
||||||
// {
|
|
||||||
// CoreStart(node);
|
|
||||||
// ShowMsg(false, "Tun mode restart the core once");
|
|
||||||
// Logging.SaveLog("Tun mode restart the core once");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> LoadCoreConfigSpeedtest(List<ServerTestItem> selecteds)
|
public async Task<int> LoadCoreConfigSpeedtest(List<ServerTestItem> selecteds)
|
||||||
{
|
{
|
||||||
var pid = -1;
|
|
||||||
var coreType = selecteds.Exists(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard) ? ECoreType.sing_box : ECoreType.Xray;
|
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 configPath = Utils.GetConfigPath(Global.CoreSpeedtestConfigFileName);
|
||||||
var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType);
|
var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType);
|
||||||
ShowMsg(false, result.Msg);
|
UpdateFunc(false, result.Msg);
|
||||||
if (result.Success)
|
if (result.Success != true)
|
||||||
{
|
{
|
||||||
pid = await CoreStartSpeedtest(configPath, coreType);
|
return -1;
|
||||||
}
|
}
|
||||||
return pid;
|
|
||||||
|
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()
|
public async Task CoreStop()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
bool hasProc = false;
|
|
||||||
if (_process != null)
|
if (_process != null)
|
||||||
{
|
{
|
||||||
await KillProcess(_process);
|
await ProcUtils.ProcessKill(_process, true);
|
||||||
_process.Dispose();
|
|
||||||
_process = null;
|
_process = null;
|
||||||
hasProc = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_processPre != null)
|
if (_processPre != null)
|
||||||
{
|
{
|
||||||
await KillProcess(_processPre);
|
await ProcUtils.ProcessKill(_processPre, true);
|
||||||
_processPre.Dispose();
|
|
||||||
_processPre = null;
|
_processPre = null;
|
||||||
hasProc = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasProc)
|
if (_linuxSudoPid > 0)
|
||||||
{
|
{
|
||||||
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo();
|
await KillProcessAsLinuxSudo();
|
||||||
foreach (var it in coreInfo)
|
|
||||||
{
|
|
||||||
if (it.CoreType == ECoreType.v2rayN)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
foreach (string vName in it.CoreExes)
|
|
||||||
{
|
|
||||||
var existing = Process.GetProcessesByName(vName);
|
|
||||||
foreach (Process p in existing)
|
|
||||||
{
|
|
||||||
string? path = p.MainModule?.FileName;
|
|
||||||
if (path == Utils.GetExeName(Utils.GetBinPath(vName, it.CoreType.ToString())))
|
|
||||||
{
|
|
||||||
await KillProcess(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
_linuxSudoPid = -1;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task CoreStopPid(int pid)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var _p = Process.GetProcessById(pid);
|
|
||||||
await KillProcess(_p);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logging.SaveLog(ex.Message, ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Private
|
#region Private
|
||||||
|
|
||||||
private string CoreFindExe(CoreInfo coreInfo)
|
|
||||||
{
|
|
||||||
string fileName = string.Empty;
|
|
||||||
foreach (string name in coreInfo.CoreExes)
|
|
||||||
{
|
|
||||||
string vName = Utils.GetExeName(name);
|
|
||||||
vName = Utils.GetBinPath(vName, coreInfo.CoreType.ToString());
|
|
||||||
if (File.Exists(vName))
|
|
||||||
{
|
|
||||||
fileName = vName;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Utils.IsNullOrEmpty(fileName))
|
|
||||||
{
|
|
||||||
string msg = string.Format(ResUI.NotFoundCore, Utils.GetBinPath("", coreInfo.CoreType.ToString()), string.Join(", ", coreInfo.CoreExes.ToArray()), coreInfo.Url);
|
|
||||||
Logging.SaveLog(msg);
|
|
||||||
ShowMsg(false, msg);
|
|
||||||
}
|
|
||||||
return fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task CoreStart(ProfileItem node)
|
private async Task CoreStart(ProfileItem node)
|
||||||
{
|
{
|
||||||
ShowMsg(false, $"{Environment.OSVersion} - {(Environment.Is64BitOperatingSystem ? 64 : 32)}");
|
var coreType = _config.RunningCoreType = AppHandler.Instance.GetCoreType(node, node.ConfigType);
|
||||||
ShowMsg(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
|
|
||||||
|
|
||||||
//ECoreType coreType;
|
|
||||||
//if (node.configType != EConfigType.Custom && _config.tunModeItem.enableTun)
|
|
||||||
//{
|
|
||||||
// coreType = ECoreType.sing_box;
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// coreType = LazyConfig.Instance.GetCoreType(node, node.configType);
|
|
||||||
//}
|
|
||||||
var coreType = AppHandler.Instance.GetCoreType(node, node.ConfigType);
|
|
||||||
_config.RunningCoreType = coreType;
|
|
||||||
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
|
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
|
||||||
|
|
||||||
var displayLog = node.ConfigType != EConfigType.Custom || node.DisplayLog;
|
var displayLog = node.ConfigType != EConfigType.Custom || node.DisplayLog;
|
||||||
var proc = await RunProcess(node, coreInfo, "", displayLog);
|
var proc = await RunProcess(coreInfo, Global.CoreConfigFileName, displayLog, true);
|
||||||
if (proc is null)
|
if (proc is null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_process = proc;
|
_process = proc;
|
||||||
|
}
|
||||||
|
|
||||||
//start a pre service
|
private async Task CoreStartPreService(ProfileItem node)
|
||||||
|
{
|
||||||
if (_process != null && !_process.HasExited)
|
if (_process != null && !_process.HasExited)
|
||||||
{
|
{
|
||||||
ProfileItem? itemSocks = null;
|
var coreType = AppHandler.Instance.GetCoreType(node, node.ConfigType);
|
||||||
var preCoreType = ECoreType.sing_box;
|
var itemSocks = await ConfigHandler.GetPreSocksItem(_config, node, coreType);
|
||||||
if (node.ConfigType != EConfigType.Custom && coreType != ECoreType.sing_box && _config.TunModeItem.EnableTun)
|
|
||||||
{
|
|
||||||
itemSocks = new ProfileItem()
|
|
||||||
{
|
|
||||||
CoreType = preCoreType,
|
|
||||||
ConfigType = EConfigType.SOCKS,
|
|
||||||
Address = Global.Loopback,
|
|
||||||
Sni = node.Address, //Tun2SocksAddress
|
|
||||||
Port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if ((node.ConfigType == EConfigType.Custom && node.PreSocksPort > 0))
|
|
||||||
{
|
|
||||||
preCoreType = _config.TunModeItem.EnableTun ? ECoreType.sing_box : ECoreType.Xray;
|
|
||||||
itemSocks = new ProfileItem()
|
|
||||||
{
|
|
||||||
CoreType = preCoreType,
|
|
||||||
ConfigType = EConfigType.SOCKS,
|
|
||||||
Address = Global.Loopback,
|
|
||||||
Port = node.PreSocksPort.Value,
|
|
||||||
};
|
|
||||||
_config.RunningCoreType = preCoreType;
|
|
||||||
}
|
|
||||||
if (itemSocks != null)
|
if (itemSocks != null)
|
||||||
{
|
{
|
||||||
string fileName2 = Utils.GetConfigPath(Global.CorePreConfigFileName);
|
var preCoreType = itemSocks.CoreType ?? ECoreType.sing_box;
|
||||||
var result = await CoreConfigHandler.GenerateClientConfig(itemSocks, fileName2);
|
var fileName = Utils.GetConfigPath(Global.CorePreConfigFileName);
|
||||||
|
var result = await CoreConfigHandler.GenerateClientConfig(itemSocks, fileName);
|
||||||
if (result.Success)
|
if (result.Success)
|
||||||
{
|
{
|
||||||
var coreInfo2 = CoreInfoHandler.Instance.GetCoreInfo(preCoreType);
|
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(preCoreType);
|
||||||
var proc2 = await RunProcess(node, coreInfo2, $" -c {Global.CorePreConfigFileName}", true);
|
var proc = await RunProcess(coreInfo, Global.CorePreConfigFileName, true, true);
|
||||||
if (proc2 is not null)
|
if (proc is null)
|
||||||
{
|
{
|
||||||
_processPre = proc2;
|
return;
|
||||||
}
|
}
|
||||||
|
_processPre = proc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<int> CoreStartSpeedtest(string configPath, ECoreType coreType)
|
private void UpdateFunc(bool notify, string msg)
|
||||||
{
|
|
||||||
ShowMsg(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
|
|
||||||
|
|
||||||
ShowMsg(false, configPath);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
|
|
||||||
var proc = await RunProcess(new(), coreInfo, $" -c {Global.CoreSpeedtestConfigFileName}", true);
|
|
||||||
if (proc is null)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return proc.Id;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logging.SaveLog(ex.Message, ex);
|
|
||||||
string msg = ex.Message;
|
|
||||||
ShowMsg(false, msg);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ShowMsg(bool notify, string msg)
|
|
||||||
{
|
{
|
||||||
_updateFunc?.Invoke(notify, 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
|
#endregion Private
|
||||||
|
|
||||||
#region Process
|
#region Process
|
||||||
|
|
||||||
private async Task<Process?> RunProcess(ProfileItem node, CoreInfo coreInfo, string configPath, bool displayLog)
|
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
|
try
|
||||||
{
|
{
|
||||||
string fileName = CoreFindExe(coreInfo);
|
|
||||||
if (Utils.IsNullOrEmpty(fileName))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Process proc = new()
|
Process proc = new()
|
||||||
{
|
{
|
||||||
StartInfo = new()
|
StartInfo = new()
|
||||||
@@ -317,33 +213,45 @@ namespace ServiceLib.Handler
|
|||||||
StandardErrorEncoding = displayLog ? Encoding.UTF8 : null,
|
StandardErrorEncoding = displayLog ? Encoding.UTF8 : null,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var isNeedSudo = mayNeedSudo && IsNeedSudo(coreInfo.CoreType);
|
||||||
|
if (isNeedSudo)
|
||||||
|
{
|
||||||
|
await RunProcessAsLinuxSudo(proc, fileName, coreInfo, configPath);
|
||||||
|
}
|
||||||
|
|
||||||
var startUpErrorMessage = new StringBuilder();
|
var startUpErrorMessage = new StringBuilder();
|
||||||
var startUpSuccessful = false;
|
var startUpSuccessful = false;
|
||||||
if (displayLog)
|
if (displayLog)
|
||||||
{
|
{
|
||||||
proc.OutputDataReceived += (sender, e) =>
|
proc.OutputDataReceived += (sender, e) =>
|
||||||
{
|
{
|
||||||
if (Utils.IsNotEmpty(e.Data))
|
if (Utils.IsNullOrEmpty(e.Data)) return;
|
||||||
{
|
UpdateFunc(false, e.Data + Environment.NewLine);
|
||||||
string msg = e.Data + Environment.NewLine;
|
|
||||||
ShowMsg(false, msg);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
proc.ErrorDataReceived += (sender, e) =>
|
proc.ErrorDataReceived += (sender, e) =>
|
||||||
{
|
{
|
||||||
if (Utils.IsNotEmpty(e.Data))
|
if (Utils.IsNullOrEmpty(e.Data)) return;
|
||||||
{
|
UpdateFunc(false, e.Data + Environment.NewLine);
|
||||||
string msg = e.Data + Environment.NewLine;
|
|
||||||
ShowMsg(false, msg);
|
|
||||||
|
|
||||||
if (!startUpSuccessful)
|
if (!startUpSuccessful)
|
||||||
{
|
{
|
||||||
startUpErrorMessage.Append(msg);
|
startUpErrorMessage.Append(e.Data + Environment.NewLine);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
proc.Start();
|
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)
|
if (displayLog)
|
||||||
{
|
{
|
||||||
proc.BeginOutputReadLine();
|
proc.BeginOutputReadLine();
|
||||||
@@ -365,35 +273,96 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
string msg = ex.Message;
|
UpdateFunc(true, ex.Message);
|
||||||
ShowMsg(true, msg);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task KillProcess(Process? proc)
|
#endregion Process
|
||||||
|
|
||||||
|
#region Linux
|
||||||
|
|
||||||
|
private async Task RunProcessAsLinuxSudo(Process proc, string fileName, CoreInfo coreInfo, string configPath)
|
||||||
{
|
{
|
||||||
if (proc is null)
|
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())
|
||||||
{
|
{
|
||||||
return;
|
proc.StartInfo.StandardInputEncoding = Encoding.UTF8;
|
||||||
}
|
proc.StartInfo.RedirectStandardInput = true;
|
||||||
try
|
|
||||||
{
|
|
||||||
proc.Kill();
|
|
||||||
proc.WaitForExit(100);
|
|
||||||
if (!proc.HasExited)
|
|
||||||
{
|
|
||||||
proc.Kill();
|
|
||||||
proc.WaitForExit(100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logging.SaveLog(ex.Message, ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion Process
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
using System.Runtime.Intrinsics.X86;
|
namespace ServiceLib.Handler
|
||||||
|
|
||||||
namespace ServiceLib.Handler
|
|
||||||
{
|
{
|
||||||
public sealed class CoreInfoHandler
|
public sealed class CoreInfoHandler
|
||||||
{
|
{
|
||||||
@@ -31,6 +29,27 @@ namespace ServiceLib.Handler
|
|||||||
return _coreInfo ?? [];
|
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()), string.Join(", ", coreInfo.CoreExes.ToArray()), coreInfo.Url);
|
||||||
|
Logging.SaveLog(msg);
|
||||||
|
}
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
private void InitCoreInfo()
|
private void InitCoreInfo()
|
||||||
{
|
{
|
||||||
_coreInfo = [];
|
_coreInfo = [];
|
||||||
@@ -44,6 +63,8 @@ namespace ServiceLib.Handler
|
|||||||
DownloadUrlWinArm64 = Global.NUrl + "/download/{0}/v2rayN-windows-arm64.zip",
|
DownloadUrlWinArm64 = Global.NUrl + "/download/{0}/v2rayN-windows-arm64.zip",
|
||||||
DownloadUrlLinux64 = Global.NUrl + "/download/{0}/v2rayN-linux-64.zip",
|
DownloadUrlLinux64 = Global.NUrl + "/download/{0}/v2rayN-linux-64.zip",
|
||||||
DownloadUrlLinuxArm64 = Global.NUrl + "/download/{0}/v2rayN-linux-arm64.zip",
|
DownloadUrlLinuxArm64 = Global.NUrl + "/download/{0}/v2rayN-linux-arm64.zip",
|
||||||
|
DownloadUrlOSX64 = Global.NUrl + "/download/{0}/v2rayN-macos-64.zip",
|
||||||
|
DownloadUrlOSXArm64 = Global.NUrl + "/download/{0}/v2rayN-macos-arm64.zip",
|
||||||
});
|
});
|
||||||
|
|
||||||
_coreInfo.Add(new CoreInfo
|
_coreInfo.Add(new CoreInfo
|
||||||
@@ -74,13 +95,15 @@ namespace ServiceLib.Handler
|
|||||||
{
|
{
|
||||||
CoreType = ECoreType.Xray,
|
CoreType = ECoreType.Xray,
|
||||||
CoreExes = new List<string> { "xray", "wxray" },
|
CoreExes = new List<string> { "xray", "wxray" },
|
||||||
Arguments = "run {0}",
|
Arguments = "run -c {0}",
|
||||||
Url = Global.XrayCoreUrl,
|
Url = Global.XrayCoreUrl,
|
||||||
ReleaseApiUrl = Global.XrayCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
ReleaseApiUrl = Global.XrayCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
||||||
DownloadUrlWin64 = Global.XrayCoreUrl + "/download/{0}/Xray-windows-64.zip",
|
DownloadUrlWin64 = Global.XrayCoreUrl + "/download/{0}/Xray-windows-64.zip",
|
||||||
DownloadUrlWinArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-windows-arm64-v8a.zip",
|
DownloadUrlWinArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-windows-arm64-v8a.zip",
|
||||||
DownloadUrlLinux64 = Global.XrayCoreUrl + "/download/{0}/Xray-linux-64.zip",
|
DownloadUrlLinux64 = Global.XrayCoreUrl + "/download/{0}/Xray-linux-64.zip",
|
||||||
DownloadUrlLinuxArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-linux-arm64-v8a.zip",
|
DownloadUrlLinuxArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-linux-arm64-v8a.zip",
|
||||||
|
DownloadUrlOSX64 = Global.XrayCoreUrl + "/download/{0}/Xray-macos-64.zip",
|
||||||
|
DownloadUrlOSXArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-macos-arm64-v8a.zip",
|
||||||
Match = "Xray",
|
Match = "Xray",
|
||||||
VersionArg = "-version",
|
VersionArg = "-version",
|
||||||
RedirectInfo = true,
|
RedirectInfo = true,
|
||||||
@@ -89,7 +112,7 @@ namespace ServiceLib.Handler
|
|||||||
_coreInfo.Add(new CoreInfo
|
_coreInfo.Add(new CoreInfo
|
||||||
{
|
{
|
||||||
CoreType = ECoreType.mihomo,
|
CoreType = ECoreType.mihomo,
|
||||||
CoreExes = new List<string> { $"mihomo-windows-amd64{(Avx2.X64.IsSupported ? "" : "-compatible")}", "mihomo-windows-amd64-compatible", "mihomo-windows-amd64", "mihomo-windows-386", "mihomo", "clash" },
|
CoreExes = new List<string> { "mihomo-windows-amd64-compatible", "mihomo-windows-amd64", "mihomo-linux-amd64", "mihomo", "clash" },
|
||||||
Arguments = "-f config.json" + PortableMode(),
|
Arguments = "-f config.json" + PortableMode(),
|
||||||
Url = Global.MihomoCoreUrl,
|
Url = Global.MihomoCoreUrl,
|
||||||
ReleaseApiUrl = Global.MihomoCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
ReleaseApiUrl = Global.MihomoCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
||||||
@@ -97,6 +120,8 @@ namespace ServiceLib.Handler
|
|||||||
DownloadUrlWinArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-windows-arm64-{0}.zip",
|
DownloadUrlWinArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-windows-arm64-{0}.zip",
|
||||||
DownloadUrlLinux64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-linux-amd64-compatible-{0}.gz",
|
DownloadUrlLinux64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-linux-amd64-compatible-{0}.gz",
|
||||||
DownloadUrlLinuxArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-linux-arm64-{0}.gz",
|
DownloadUrlLinuxArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-linux-arm64-{0}.gz",
|
||||||
|
DownloadUrlOSX64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-darwin-amd64-compatible-{0}.gz",
|
||||||
|
DownloadUrlOSXArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-darwin-arm64-{0}.gz",
|
||||||
Match = "Mihomo",
|
Match = "Mihomo",
|
||||||
VersionArg = "-v",
|
VersionArg = "-v",
|
||||||
RedirectInfo = true,
|
RedirectInfo = true,
|
||||||
@@ -105,7 +130,7 @@ namespace ServiceLib.Handler
|
|||||||
_coreInfo.Add(new CoreInfo
|
_coreInfo.Add(new CoreInfo
|
||||||
{
|
{
|
||||||
CoreType = ECoreType.hysteria,
|
CoreType = ECoreType.hysteria,
|
||||||
CoreExes = new List<string> { "hysteria-windows-amd64", "hysteria-windows-386", "hysteria" },
|
CoreExes = new List<string> { "hysteria-windows-amd64", "hysteria" },
|
||||||
Arguments = "",
|
Arguments = "",
|
||||||
Url = Global.HysteriaCoreUrl,
|
Url = Global.HysteriaCoreUrl,
|
||||||
ReleaseApiUrl = Global.HysteriaCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
ReleaseApiUrl = Global.HysteriaCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
||||||
@@ -134,7 +159,7 @@ namespace ServiceLib.Handler
|
|||||||
{
|
{
|
||||||
CoreType = ECoreType.sing_box,
|
CoreType = ECoreType.sing_box,
|
||||||
CoreExes = new List<string> { "sing-box-client", "sing-box" },
|
CoreExes = new List<string> { "sing-box-client", "sing-box" },
|
||||||
Arguments = "run {0} --disable-color",
|
Arguments = "run -c {0} --disable-color",
|
||||||
Url = Global.SingboxCoreUrl,
|
Url = Global.SingboxCoreUrl,
|
||||||
RedirectInfo = true,
|
RedirectInfo = true,
|
||||||
ReleaseApiUrl = Global.SingboxCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
ReleaseApiUrl = Global.SingboxCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
||||||
@@ -142,6 +167,8 @@ namespace ServiceLib.Handler
|
|||||||
DownloadUrlWinArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-windows-arm64.zip",
|
DownloadUrlWinArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-windows-arm64.zip",
|
||||||
DownloadUrlLinux64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-linux-amd64.tar.gz",
|
DownloadUrlLinux64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-linux-amd64.tar.gz",
|
||||||
DownloadUrlLinuxArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-linux-arm64.tar.gz",
|
DownloadUrlLinuxArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-linux-arm64.tar.gz",
|
||||||
|
DownloadUrlOSX64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-darwin-amd64.tar.gz",
|
||||||
|
DownloadUrlOSXArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-darwin-arm64.tar.gz",
|
||||||
Match = "sing-box",
|
Match = "sing-box",
|
||||||
VersionArg = "version",
|
VersionArg = "version",
|
||||||
});
|
});
|
||||||
@@ -157,7 +184,7 @@ namespace ServiceLib.Handler
|
|||||||
_coreInfo.Add(new CoreInfo
|
_coreInfo.Add(new CoreInfo
|
||||||
{
|
{
|
||||||
CoreType = ECoreType.hysteria2,
|
CoreType = ECoreType.hysteria2,
|
||||||
CoreExes = new List<string> { "hysteria-windows-amd64", "hysteria-windows-386", "hysteria" },
|
CoreExes = new List<string> { "hysteria-windows-amd64", "hysteria-linux-amd64", "hysteria" },
|
||||||
Arguments = "",
|
Arguments = "",
|
||||||
Url = Global.HysteriaCoreUrl,
|
Url = Global.HysteriaCoreUrl,
|
||||||
ReleaseApiUrl = Global.HysteriaCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
ReleaseApiUrl = Global.HysteriaCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
||||||
@@ -167,7 +194,7 @@ namespace ServiceLib.Handler
|
|||||||
|
|
||||||
private string PortableMode()
|
private string PortableMode()
|
||||||
{
|
{
|
||||||
return $" -d \"{Utils.GetBinPath("")}\"";
|
return $" -d {Utils.GetBinPath("").AppendQuotes()}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,6 @@ namespace ServiceLib.Handler.Fmt
|
|||||||
|
|
||||||
case nameof(ETransport.ws):
|
case nameof(ETransport.ws):
|
||||||
case nameof(ETransport.httpupgrade):
|
case nameof(ETransport.httpupgrade):
|
||||||
case nameof(ETransport.splithttp):
|
|
||||||
if (Utils.IsNotEmpty(item.RequestHost))
|
if (Utils.IsNotEmpty(item.RequestHost))
|
||||||
{
|
{
|
||||||
dicQuery.Add("host", Utils.UrlEncode(item.RequestHost));
|
dicQuery.Add("host", Utils.UrlEncode(item.RequestHost));
|
||||||
@@ -94,6 +93,25 @@ namespace ServiceLib.Handler.Fmt
|
|||||||
}
|
}
|
||||||
break;
|
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.http):
|
||||||
case nameof(ETransport.h2):
|
case nameof(ETransport.h2):
|
||||||
dicQuery["type"] = nameof(ETransport.http);
|
dicQuery["type"] = nameof(ETransport.http);
|
||||||
@@ -156,11 +174,17 @@ namespace ServiceLib.Handler.Fmt
|
|||||||
|
|
||||||
case nameof(ETransport.ws):
|
case nameof(ETransport.ws):
|
||||||
case nameof(ETransport.httpupgrade):
|
case nameof(ETransport.httpupgrade):
|
||||||
case nameof(ETransport.splithttp):
|
|
||||||
item.RequestHost = Utils.UrlDecode(query["host"] ?? "");
|
item.RequestHost = Utils.UrlDecode(query["host"] ?? "");
|
||||||
item.Path = Utils.UrlDecode(query["path"] ?? "/");
|
item.Path = Utils.UrlDecode(query["path"] ?? "/");
|
||||||
break;
|
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.http):
|
||||||
case nameof(ETransport.h2):
|
case nameof(ETransport.h2):
|
||||||
item.Network = nameof(ETransport.h2);
|
item.Network = nameof(ETransport.h2);
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
{
|
{
|
||||||
public class FmtHandler
|
public class FmtHandler
|
||||||
{
|
{
|
||||||
|
private static readonly string _tag = "FmtHandler";
|
||||||
|
|
||||||
public static string? GetShareUri(ProfileItem item)
|
public static string? GetShareUri(ProfileItem item)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -23,7 +25,7 @@
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,7 +83,7 @@
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
msg = ResUI.Incorrectconfiguration;
|
msg = ResUI.Incorrectconfiguration;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,8 +99,8 @@ namespace ServiceLib.Handler.Fmt
|
|||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
item.Security = userInfoParts[0];
|
item.Security = userInfoParts.First();
|
||||||
item.Id = Utils.UrlDecode(userInfoParts[1]);
|
item.Id = Utils.UrlDecode(userInfoParts.Last());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -111,8 +111,8 @@ namespace ServiceLib.Handler.Fmt
|
|||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
item.Security = userInfoParts[0];
|
item.Security = userInfoParts.First();
|
||||||
item.Id = userInfoParts[1];
|
item.Id = userInfoParts.Last();
|
||||||
}
|
}
|
||||||
|
|
||||||
var queryParameters = Utils.ParseQueryString(parsedUrl.Query);
|
var queryParameters = Utils.ParseQueryString(parsedUrl.Query);
|
||||||
|
|||||||
@@ -5,9 +5,8 @@
|
|||||||
public static ProfileItem? Resolve(string str, out string msg)
|
public static ProfileItem? Resolve(string str, out string msg)
|
||||||
{
|
{
|
||||||
msg = ResUI.ConfigurationFormatIncorrect;
|
msg = ResUI.ConfigurationFormatIncorrect;
|
||||||
ProfileItem? item;
|
|
||||||
|
|
||||||
item = ResolveSocksNew(str) ?? ResolveSocks(str);
|
var item = ResolveSocksNew(str) ?? ResolveSocks(str);
|
||||||
if (item == null)
|
if (item == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@@ -25,19 +24,13 @@
|
|||||||
public static string? ToUri(ProfileItem? item)
|
public static string? ToUri(ProfileItem? item)
|
||||||
{
|
{
|
||||||
if (item == null) return null;
|
if (item == null) return null;
|
||||||
string url = string.Empty;
|
var url = string.Empty;
|
||||||
|
|
||||||
string remark = string.Empty;
|
var remark = string.Empty;
|
||||||
if (Utils.IsNotEmpty(item.Remarks))
|
if (Utils.IsNotEmpty(item.Remarks))
|
||||||
{
|
{
|
||||||
remark = "#" + Utils.UrlEncode(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
|
//new
|
||||||
var pw = Utils.Base64Encode($"{item.Security}:{item.Id}");
|
var pw = Utils.Base64Encode($"{item.Security}:{item.Id}");
|
||||||
return ToUri(EConfigType.SOCKS, item.Address, item.Port, pw, null, remark);
|
return ToUri(EConfigType.SOCKS, item.Address, item.Port, pw, null, remark);
|
||||||
@@ -51,7 +44,7 @@
|
|||||||
};
|
};
|
||||||
result = result[Global.ProtocolShares[EConfigType.SOCKS].Length..];
|
result = result[Global.ProtocolShares[EConfigType.SOCKS].Length..];
|
||||||
//remark
|
//remark
|
||||||
int indexRemark = result.IndexOf("#");
|
var indexRemark = result.IndexOf("#");
|
||||||
if (indexRemark > 0)
|
if (indexRemark > 0)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -62,7 +55,7 @@
|
|||||||
result = result[..indexRemark];
|
result = result[..indexRemark];
|
||||||
}
|
}
|
||||||
//part decode
|
//part decode
|
||||||
int indexS = result.IndexOf("@");
|
var indexS = result.IndexOf("@");
|
||||||
if (indexS > 0)
|
if (indexS > 0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -71,21 +64,20 @@
|
|||||||
result = Utils.Base64Decode(result);
|
result = Utils.Base64Decode(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
string[] arr1 = result.Split('@');
|
var arr1 = result.Split('@');
|
||||||
if (arr1.Length != 2)
|
if (arr1.Length != 2)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
string[] arr21 = arr1[0].Split(':');
|
var arr21 = arr1.First().Split(':');
|
||||||
//string[] arr22 = arr1[1].Split(':');
|
var indexPort = arr1.Last().LastIndexOf(":");
|
||||||
int indexPort = arr1[1].LastIndexOf(":");
|
|
||||||
if (arr21.Length != 2 || indexPort < 0)
|
if (arr21.Length != 2 || indexPort < 0)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
item.Address = arr1[1][..indexPort];
|
item.Address = arr1[1][..indexPort];
|
||||||
item.Port = Utils.ToInt(arr1[1][(indexPort + 1)..]);
|
item.Port = Utils.ToInt(arr1[1][(indexPort + 1)..]);
|
||||||
item.Security = arr21[0];
|
item.Security = arr21.First();
|
||||||
item.Id = arr21[1];
|
item.Id = arr21[1];
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
@@ -106,10 +98,10 @@
|
|||||||
// parse base64 UserInfo
|
// parse base64 UserInfo
|
||||||
var rawUserInfo = Utils.UrlDecode(parsedUrl.UserInfo);
|
var rawUserInfo = Utils.UrlDecode(parsedUrl.UserInfo);
|
||||||
var userInfo = Utils.Base64Decode(rawUserInfo);
|
var userInfo = Utils.Base64Decode(rawUserInfo);
|
||||||
var userInfoParts = userInfo.Split(new[] { ':' }, 2);
|
var userInfoParts = userInfo.Split([':'], 2);
|
||||||
if (userInfoParts.Length == 2)
|
if (userInfoParts.Length == 2)
|
||||||
{
|
{
|
||||||
item.Security = userInfoParts[0];
|
item.Security = userInfoParts.First();
|
||||||
item.Id = userInfoParts[1];
|
item.Id = userInfoParts[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,8 +21,8 @@
|
|||||||
var userInfoParts = rawUserInfo.Split(new[] { ':' }, 2);
|
var userInfoParts = rawUserInfo.Split(new[] { ':' }, 2);
|
||||||
if (userInfoParts.Length == 2)
|
if (userInfoParts.Length == 2)
|
||||||
{
|
{
|
||||||
item.Id = userInfoParts[0];
|
item.Id = userInfoParts.First();
|
||||||
item.Security = userInfoParts[1];
|
item.Security = userInfoParts.Last();
|
||||||
}
|
}
|
||||||
|
|
||||||
var query = Utils.ParseQueryString(url.Query);
|
var query = Utils.ParseQueryString(url.Query);
|
||||||
|
|||||||
105
v2rayN/ServiceLib/Handler/PacHandler.cs
Normal file
105
v2rayN/ServiceLib/Handler/PacHandler.cs
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
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 = Utils.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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,27 +9,32 @@ namespace ServiceLib.Handler
|
|||||||
private static readonly Lazy<ProfileExHandler> _instance = new(() => new());
|
private static readonly Lazy<ProfileExHandler> _instance = new(() => new());
|
||||||
private ConcurrentBag<ProfileExItem> _lstProfileEx = [];
|
private ConcurrentBag<ProfileExItem> _lstProfileEx = [];
|
||||||
private Queue<string> _queIndexIds = new();
|
private Queue<string> _queIndexIds = new();
|
||||||
public ConcurrentBag<ProfileExItem> ProfileExs => _lstProfileEx;
|
|
||||||
public static ProfileExHandler Instance => _instance.Value;
|
public static ProfileExHandler Instance => _instance.Value;
|
||||||
|
private static readonly string _tag = "ProfileExHandler";
|
||||||
|
|
||||||
public ProfileExHandler()
|
public ProfileExHandler()
|
||||||
{
|
{
|
||||||
Init();
|
//Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Init()
|
public async Task Init()
|
||||||
{
|
{
|
||||||
await InitData();
|
await InitData();
|
||||||
await Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
await SaveQueueIndexIds();
|
|
||||||
await Task.Delay(1000 * 600);
|
await Task.Delay(1000 * 600);
|
||||||
|
await SaveQueueIndexIds();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<ConcurrentBag<ProfileExItem>> GetProfileExs()
|
||||||
|
{
|
||||||
|
return _lstProfileEx;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task InitData()
|
private async Task InitData()
|
||||||
{
|
{
|
||||||
await SQLiteHelper.Instance.ExecuteAsync($"delete from ProfileExItem where indexId not in ( select indexId from ProfileItem )");
|
await SQLiteHelper.Instance.ExecuteAsync($"delete from ProfileExItem where indexId not in ( select indexId from ProfileItem )");
|
||||||
@@ -83,7 +88,7 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog("ProfileExHandler", ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -115,7 +120,7 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,10 @@
|
|||||||
private ServerStatItem? _serverStatItem;
|
private ServerStatItem? _serverStatItem;
|
||||||
private List<ServerStatItem> _lstServerStat;
|
private List<ServerStatItem> _lstServerStat;
|
||||||
private Action<ServerSpeedItem>? _updateFunc;
|
private Action<ServerSpeedItem>? _updateFunc;
|
||||||
private StatisticsV2rayService? _statisticsV2Ray;
|
|
||||||
private StatisticsSingboxService? _statisticsSingbox;
|
|
||||||
|
|
||||||
|
private StatisticsXrayService? _statisticsXray;
|
||||||
|
private StatisticsSingboxService? _statisticsSingbox;
|
||||||
|
private static readonly string _tag = "StatisticsHandler";
|
||||||
public List<ServerStatItem> ServerStat => _lstServerStat;
|
public List<ServerStatItem> ServerStat => _lstServerStat;
|
||||||
|
|
||||||
public async Task Init(Config config, Action<ServerSpeedItem> updateFunc)
|
public async Task Init(Config config, Action<ServerSpeedItem> updateFunc)
|
||||||
@@ -25,7 +26,7 @@
|
|||||||
|
|
||||||
await InitData();
|
await InitData();
|
||||||
|
|
||||||
_statisticsV2Ray = new StatisticsV2rayService(config, UpdateServerStatHandler);
|
_statisticsXray = new StatisticsXrayService(config, UpdateServerStatHandler);
|
||||||
_statisticsSingbox = new StatisticsSingboxService(config, UpdateServerStatHandler);
|
_statisticsSingbox = new StatisticsSingboxService(config, UpdateServerStatHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,12 +34,12 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_statisticsV2Ray?.Close();
|
_statisticsXray?.Close();
|
||||||
_statisticsSingbox?.Close();
|
_statisticsSingbox?.Close();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,10 +61,29 @@
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task CloneServerStatItem(string indexId, string toIndexId)
|
||||||
|
{
|
||||||
|
if (_lstServerStat == null)
|
||||||
|
{
|
||||||
|
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()
|
private async Task InitData()
|
||||||
{
|
{
|
||||||
await SQLiteHelper.Instance.ExecuteAsync($"delete from ServerStatItem where indexId not in ( select indexId from ProfileItem )");
|
await SQLiteHelper.Instance.ExecuteAsync($"delete from ServerStatItem where indexId not in ( select indexId from ProfileItem )");
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
{
|
{
|
||||||
public class ProxySettingLinux
|
public class ProxySettingLinux
|
||||||
{
|
{
|
||||||
public static async Task SetProxy(string host, int port)
|
public static async Task SetProxy(string host, int port, string exceptions)
|
||||||
{
|
{
|
||||||
var lstCmd = GetSetCmds(host, port);
|
var lstCmd = GetSetCmds(host, port, exceptions);
|
||||||
|
|
||||||
await ExecCmd(lstCmd);
|
await ExecCmd(lstCmd);
|
||||||
}
|
}
|
||||||
@@ -29,25 +29,39 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<CmdItem> GetSetCmds(string host, int port)
|
private static List<CmdItem> GetSetCmds(string host, int port, string exceptions)
|
||||||
{
|
{
|
||||||
var isKde = IsKde(out var configDir);
|
var isKde = IsKde(out var configDir);
|
||||||
List<string> lstType = ["", "http", "https", "socks", "ftp"];
|
List<string> lstType = ["", "http", "https", "socks", "ftp"];
|
||||||
List<CmdItem> lstCmd = [];
|
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)
|
if (isKde)
|
||||||
{
|
{
|
||||||
foreach (var type in lstType)
|
foreach (var type in lstType)
|
||||||
{
|
{
|
||||||
lstCmd.AddRange(GetSetCmd4Kde(type, host, port, configDir));
|
lstCmd.AddRange(GetSetCmd4Kde(type, host, port, configDir));
|
||||||
}
|
}
|
||||||
}
|
if (exceptions.IsNotEmpty())
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (var type in lstType)
|
|
||||||
{
|
{
|
||||||
lstCmd.AddRange(GetSetCmd4Gnome(type, host, port));
|
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;
|
return lstCmd;
|
||||||
}
|
}
|
||||||
@@ -57,44 +71,58 @@
|
|||||||
var isKde = IsKde(out var configDir);
|
var isKde = IsKde(out var configDir);
|
||||||
List<CmdItem> lstCmd = [];
|
List<CmdItem> lstCmd = [];
|
||||||
|
|
||||||
|
//GNOME
|
||||||
|
lstCmd.Add(new CmdItem()
|
||||||
|
{
|
||||||
|
Cmd = "gsettings",
|
||||||
|
Arguments = ["set", "org.gnome.system.proxy", "mode", "none"]
|
||||||
|
});
|
||||||
|
|
||||||
if (isKde)
|
if (isKde)
|
||||||
{
|
{
|
||||||
lstCmd.Add(new CmdItem()
|
lstCmd.Add(new CmdItem()
|
||||||
{
|
{
|
||||||
Cmd = "kwriteconfig5",
|
Cmd = GetKdeVersion(),
|
||||||
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", "ProxyType", "0"]
|
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", "ProxyType", "0"]
|
||||||
});
|
});
|
||||||
}
|
|
||||||
else
|
// Notify system to reload
|
||||||
{
|
|
||||||
lstCmd.Add(new CmdItem()
|
lstCmd.Add(new CmdItem()
|
||||||
{
|
{
|
||||||
Cmd = "gsettings",
|
Cmd = "dbus-send",
|
||||||
Arguments = ["set", "org.gnome.system.proxy", "mode", "none"]
|
Arguments = ["--type=signal", "/KIO/Scheduler", "org.kde.KIO.Scheduler.reparseSlaveConfiguration", "string:''"]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return lstCmd;
|
return lstCmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<CmdItem> GetSetCmd4Kde(string type, string host, int port, string configDir)
|
private static List<CmdItem> GetSetCmd4Kde(string type, string host, int port, string configDir)
|
||||||
{
|
{
|
||||||
List<CmdItem> lstCmd = [];
|
List<CmdItem> lstCmd = [];
|
||||||
|
var cmd = GetKdeVersion();
|
||||||
|
|
||||||
if (type.IsNullOrEmpty())
|
if (type.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
lstCmd.Add(new()
|
lstCmd.Add(new()
|
||||||
{
|
{
|
||||||
Cmd = "kwriteconfig5",
|
Cmd = cmd,
|
||||||
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", "ProxyType", "1"]
|
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
|
else
|
||||||
{
|
{
|
||||||
var type2 = type.Equals("https") ? "http" : type;
|
var type2 = type.Equals("https") ? "http" : type;
|
||||||
lstCmd.Add(new CmdItem()
|
lstCmd.Add(new CmdItem()
|
||||||
{
|
{
|
||||||
Cmd = "kwriteconfig5",
|
Cmd = cmd,
|
||||||
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", $"{type}Proxy", $"{type2}://{host}:{port}"]
|
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", $"{type}Proxy", $"{type2}://{host}:{port}"]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -114,6 +142,14 @@
|
|||||||
Arguments = ["set", "org.gnome.system.proxy", "mode", "manual"]
|
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
|
else
|
||||||
{
|
{
|
||||||
lstCmd.Add(new()
|
lstCmd.Add(new()
|
||||||
@@ -136,7 +172,11 @@
|
|||||||
{
|
{
|
||||||
configDir = "/home";
|
configDir = "/home";
|
||||||
var desktop = Environment.GetEnvironmentVariable("XDG_CURRENT_DESKTOP");
|
var desktop = Environment.GetEnvironmentVariable("XDG_CURRENT_DESKTOP");
|
||||||
var isKde = string.Equals(desktop, "KDE", StringComparison.OrdinalIgnoreCase);
|
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)
|
if (isKde)
|
||||||
{
|
{
|
||||||
var homeDir = Environment.GetEnvironmentVariable("HOME");
|
var homeDir = Environment.GetEnvironmentVariable("HOME");
|
||||||
@@ -148,5 +188,15 @@
|
|||||||
|
|
||||||
return isKde;
|
return isKde;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string GetKdeVersion()
|
||||||
|
{
|
||||||
|
var ver = Environment.GetEnvironmentVariable("KDE_SESSION_VERSION") ?? "0";
|
||||||
|
return ver switch
|
||||||
|
{
|
||||||
|
"6" => "kwriteconfig6",
|
||||||
|
_ => "kwriteconfig5"
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,12 +2,100 @@
|
|||||||
{
|
{
|
||||||
public class ProxySettingOSX
|
public class ProxySettingOSX
|
||||||
{
|
{
|
||||||
public static async Task SetProxy(string host, int port)
|
/// <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()
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using static ServiceLib.Handler.SysProxy.ProxySettingWindows.InternetConnectionOption;
|
using static ServiceLib.Handler.SysProxy.ProxySettingWindows.InternetConnectionOption;
|
||||||
|
|
||||||
namespace ServiceLib.Handler.SysProxy
|
namespace ServiceLib.Handler.SysProxy
|
||||||
@@ -11,24 +11,24 @@ namespace ServiceLib.Handler.SysProxy
|
|||||||
{
|
{
|
||||||
if (type == 1)
|
if (type == 1)
|
||||||
{
|
{
|
||||||
RegWriteValue(_regPath, "ProxyEnable", 0);
|
WindowsUtils.RegWriteValue(_regPath, "ProxyEnable", 0);
|
||||||
RegWriteValue(_regPath, "ProxyServer", string.Empty);
|
WindowsUtils.RegWriteValue(_regPath, "ProxyServer", string.Empty);
|
||||||
RegWriteValue(_regPath, "ProxyOverride", string.Empty);
|
WindowsUtils.RegWriteValue(_regPath, "ProxyOverride", string.Empty);
|
||||||
RegWriteValue(_regPath, "AutoConfigURL", string.Empty);
|
WindowsUtils.RegWriteValue(_regPath, "AutoConfigURL", string.Empty);
|
||||||
}
|
}
|
||||||
if (type == 2)
|
if (type == 2)
|
||||||
{
|
{
|
||||||
RegWriteValue(_regPath, "ProxyEnable", 1);
|
WindowsUtils.RegWriteValue(_regPath, "ProxyEnable", 1);
|
||||||
RegWriteValue(_regPath, "ProxyServer", strProxy ?? string.Empty);
|
WindowsUtils.RegWriteValue(_regPath, "ProxyServer", strProxy ?? string.Empty);
|
||||||
RegWriteValue(_regPath, "ProxyOverride", exceptions ?? string.Empty);
|
WindowsUtils.RegWriteValue(_regPath, "ProxyOverride", exceptions ?? string.Empty);
|
||||||
RegWriteValue(_regPath, "AutoConfigURL", string.Empty);
|
WindowsUtils.RegWriteValue(_regPath, "AutoConfigURL", string.Empty);
|
||||||
}
|
}
|
||||||
else if (type == 4)
|
else if (type == 4)
|
||||||
{
|
{
|
||||||
RegWriteValue(_regPath, "ProxyEnable", 0);
|
WindowsUtils.RegWriteValue(_regPath, "ProxyEnable", 0);
|
||||||
RegWriteValue(_regPath, "ProxyServer", string.Empty);
|
WindowsUtils.RegWriteValue(_regPath, "ProxyServer", string.Empty);
|
||||||
RegWriteValue(_regPath, "ProxyOverride", string.Empty);
|
WindowsUtils.RegWriteValue(_regPath, "ProxyOverride", string.Empty);
|
||||||
RegWriteValue(_regPath, "AutoConfigURL", strProxy ?? string.Empty);
|
WindowsUtils.RegWriteValue(_regPath, "AutoConfigURL", strProxy ?? string.Empty);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -72,7 +72,6 @@ namespace ServiceLib.Handler.SysProxy
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
SetProxyFallback(strProxy, exceptions, type);
|
SetProxyFallback(strProxy, exceptions, type);
|
||||||
//Logging.SaveLog(ex.Message, ex);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,12 +143,12 @@ namespace ServiceLib.Handler.SysProxy
|
|||||||
{
|
{
|
||||||
if (Environment.Is64BitOperatingSystem)
|
if (Environment.Is64BitOperatingSystem)
|
||||||
{
|
{
|
||||||
nint opt = new(optionsPtr.ToInt64() + i * optSize);
|
nint opt = new(optionsPtr.ToInt64() + (i * optSize));
|
||||||
Marshal.StructureToPtr(options[i], opt, false);
|
Marshal.StructureToPtr(options[i], opt, false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nint opt = new(optionsPtr.ToInt32() + i * optSize);
|
nint opt = new(optionsPtr.ToInt32() + (i * optSize));
|
||||||
Marshal.StructureToPtr(options[i], opt, false);
|
Marshal.StructureToPtr(options[i], opt, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,7 +246,7 @@ namespace ServiceLib.Handler.SysProxy
|
|||||||
|
|
||||||
//[MarshalAs(UnmanagedType.)]
|
//[MarshalAs(UnmanagedType.)]
|
||||||
public nint options;
|
public nint options;
|
||||||
};
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||||
public struct InternetConnectionOption
|
public struct InternetConnectionOption
|
||||||
@@ -356,30 +355,5 @@ namespace ServiceLib.Handler.SysProxy
|
|||||||
ref int lpcEntries // Number of entries written to the buffer
|
ref int lpcEntries // Number of entries written to the buffer
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void RegWriteValue(string path, string name, object value)
|
|
||||||
{
|
|
||||||
Microsoft.Win32.RegistryKey? regKey = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
regKey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(path);
|
|
||||||
if (string.IsNullOrEmpty(value.ToString()))
|
|
||||||
{
|
|
||||||
regKey?.DeleteValue(name, false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
regKey?.SetValue(name, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
//Logging.SaveLog(ex.Message, ex);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
regKey?.Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
using PacLib;
|
namespace ServiceLib.Handler.SysProxy
|
||||||
|
|
||||||
namespace ServiceLib.Handler.SysProxy
|
|
||||||
{
|
{
|
||||||
public static class SysProxyHandler
|
public static class SysProxyHandler
|
||||||
{
|
{
|
||||||
|
private static readonly string _tag = "SysProxyHandler";
|
||||||
|
|
||||||
public static async Task<bool> UpdateSysProxy(Config config, bool forceDisable)
|
public static async Task<bool> UpdateSysProxy(Config config, bool forceDisable)
|
||||||
{
|
{
|
||||||
var type = config.SystemProxyItem.SysProxyType;
|
var type = config.SystemProxyItem.SysProxyType;
|
||||||
@@ -15,8 +15,8 @@ namespace ServiceLib.Handler.SysProxy
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var port = AppHandler.Instance.GetLocalPort(EInboundProtocol.http);
|
var port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
|
||||||
var portSocks = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
|
var exceptions = config.SystemProxyItem.SystemProxyExceptions;
|
||||||
if (port <= 0)
|
if (port <= 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -25,23 +25,18 @@ namespace ServiceLib.Handler.SysProxy
|
|||||||
{
|
{
|
||||||
case ESysProxyType.ForcedChange when Utils.IsWindows():
|
case ESysProxyType.ForcedChange when Utils.IsWindows():
|
||||||
{
|
{
|
||||||
GetWindowsProxyString(config, port, portSocks, out var strProxy, out var strExceptions);
|
GetWindowsProxyString(config, port, out var strProxy, out var strExceptions);
|
||||||
ProxySettingWindows.SetProxy(strProxy, strExceptions, 2);
|
ProxySettingWindows.SetProxy(strProxy, strExceptions, 2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ESysProxyType.ForcedChange when Utils.IsLinux():
|
case ESysProxyType.ForcedChange when Utils.IsLinux():
|
||||||
await ProxySettingLinux.SetProxy(Global.Loopback, port);
|
await ProxySettingLinux.SetProxy(Global.Loopback, port, exceptions);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ESysProxyType.ForcedChange:
|
case ESysProxyType.ForcedChange when Utils.IsOSX():
|
||||||
{
|
await ProxySettingOSX.SetProxy(Global.Loopback, port, exceptions);
|
||||||
if (Utils.IsOSX())
|
break;
|
||||||
{
|
|
||||||
await ProxySettingOSX.SetProxy(Global.Loopback, port);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ESysProxyType.ForcedClear when Utils.IsWindows():
|
case ESysProxyType.ForcedClear when Utils.IsWindows():
|
||||||
ProxySettingWindows.UnsetProxy();
|
ProxySettingWindows.UnsetProxy();
|
||||||
break;
|
break;
|
||||||
@@ -50,23 +45,13 @@ namespace ServiceLib.Handler.SysProxy
|
|||||||
await ProxySettingLinux.UnsetProxy();
|
await ProxySettingLinux.UnsetProxy();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ESysProxyType.ForcedClear:
|
case ESysProxyType.ForcedClear when Utils.IsOSX():
|
||||||
{
|
await ProxySettingOSX.UnsetProxy();
|
||||||
if (Utils.IsOSX())
|
break;
|
||||||
{
|
|
||||||
await ProxySettingOSX.UnsetProxy();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ESysProxyType.Pac when Utils.IsWindows():
|
case ESysProxyType.Pac when Utils.IsWindows():
|
||||||
{
|
await SetWindowsProxyPac(port);
|
||||||
var portPac = AppHandler.Instance.GetLocalPort(EInboundProtocol.pac);
|
break;
|
||||||
PacHandler.Start(Utils.GetConfigPath(), port, portPac);
|
|
||||||
var strProxy = $"{Global.HttpProtocol}{Global.Loopback}:{portPac}/pac?t={DateTime.Now.Ticks}";
|
|
||||||
ProxySettingWindows.SetProxy(strProxy, "", 4);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != ESysProxyType.Pac && Utils.IsWindows())
|
if (type != ESysProxyType.Pac && Utils.IsWindows())
|
||||||
@@ -76,17 +61,17 @@ namespace ServiceLib.Handler.SysProxy
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GetWindowsProxyString(Config config, int port, int portSocks, out string strProxy, out string strExceptions)
|
private static void GetWindowsProxyString(Config config, int port, out string strProxy, out string strExceptions)
|
||||||
{
|
{
|
||||||
strExceptions = "";
|
strExceptions = config.SystemProxyItem.SystemProxyExceptions;
|
||||||
if (config.SystemProxyItem.NotProxyLocalAddress)
|
if (config.SystemProxyItem.NotProxyLocalAddress)
|
||||||
{
|
{
|
||||||
strExceptions = $"<local>;{config.ConstItem.DefIEProxyExceptions};{config.SystemProxyItem.SystemProxyExceptions}";
|
strExceptions = $"<local>;{strExceptions}";
|
||||||
}
|
}
|
||||||
|
|
||||||
strProxy = string.Empty;
|
strProxy = string.Empty;
|
||||||
@@ -99,8 +84,16 @@ namespace ServiceLib.Handler.SysProxy
|
|||||||
strProxy = config.SystemProxyItem.SystemProxyAdvancedProtocol
|
strProxy = config.SystemProxyItem.SystemProxyAdvancedProtocol
|
||||||
.Replace("{ip}", Global.Loopback)
|
.Replace("{ip}", Global.Loopback)
|
||||||
.Replace("{http_port}", port.ToString())
|
.Replace("{http_port}", port.ToString())
|
||||||
.Replace("{socks_port}", portSocks.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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,7 @@ namespace ServiceLib.Handler
|
|||||||
private string? _lastDescription;
|
private string? _lastDescription;
|
||||||
private string _webDir = Global.AppName + "_backup";
|
private string _webDir = Global.AppName + "_backup";
|
||||||
private readonly string _webFileName = "backup.zip";
|
private readonly string _webFileName = "backup.zip";
|
||||||
private string _logTitle = "WebDav--";
|
private readonly string _tag = "WebDav--";
|
||||||
|
|
||||||
public WebDavHandler()
|
public WebDavHandler()
|
||||||
{
|
{
|
||||||
@@ -81,13 +81,13 @@ namespace ServiceLib.Handler
|
|||||||
private void SaveLog(string desc)
|
private void SaveLog(string desc)
|
||||||
{
|
{
|
||||||
_lastDescription = desc;
|
_lastDescription = desc;
|
||||||
Logging.SaveLog(_logTitle + desc);
|
Logging.SaveLog(_tag + desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SaveLog(Exception ex)
|
private void SaveLog(Exception ex)
|
||||||
{
|
{
|
||||||
_lastDescription = ex.Message;
|
_lastDescription = ex.Message;
|
||||||
Logging.SaveLog(_logTitle, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> CheckConnection()
|
public async Task<bool> CheckConnection()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace ServiceLib.Models
|
namespace ServiceLib.Models
|
||||||
{
|
{
|
||||||
public class CheckUpdateItem
|
public class CheckUpdateModel
|
||||||
{
|
{
|
||||||
public bool? IsSelected { get; set; }
|
public bool? IsSelected { get; set; }
|
||||||
public string? CoreType { get; set; }
|
public string? CoreType { get; set; }
|
||||||
@@ -15,15 +15,15 @@
|
|||||||
|
|
||||||
public bool IsRunningCore(ECoreType type)
|
public bool IsRunningCore(ECoreType type)
|
||||||
{
|
{
|
||||||
if (type == ECoreType.Xray && RunningCoreType is ECoreType.Xray or ECoreType.v2fly or ECoreType.v2fly_v5)
|
switch (type)
|
||||||
{
|
{
|
||||||
return true;
|
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;
|
||||||
}
|
}
|
||||||
if (type == ECoreType.sing_box && RunningCoreType is ECoreType.sing_box or ECoreType.mihomo)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion property
|
#endregion property
|
||||||
@@ -46,6 +46,8 @@
|
|||||||
public ClashUIItem ClashUIItem { get; set; }
|
public ClashUIItem ClashUIItem { get; set; }
|
||||||
public SystemProxyItem SystemProxyItem { get; set; }
|
public SystemProxyItem SystemProxyItem { get; set; }
|
||||||
public WebDavItem WebDavItem { 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<InItem> Inbound { get; set; }
|
||||||
public List<KeyEventItem> GlobalHotkeys { get; set; }
|
public List<KeyEventItem> GlobalHotkeys { get; set; }
|
||||||
public List<CoreTypeItem> CoreTypeItem { get; set; }
|
public List<CoreTypeItem> CoreTypeItem { get; set; }
|
||||||
|
|||||||
@@ -24,21 +24,16 @@
|
|||||||
public class InItem
|
public class InItem
|
||||||
{
|
{
|
||||||
public int LocalPort { get; set; }
|
public int LocalPort { get; set; }
|
||||||
|
|
||||||
public string Protocol { get; set; }
|
public string Protocol { get; set; }
|
||||||
|
|
||||||
public bool UdpEnabled { get; set; }
|
public bool UdpEnabled { get; set; }
|
||||||
|
|
||||||
public bool SniffingEnabled { get; set; } = true;
|
public bool SniffingEnabled { get; set; } = true;
|
||||||
public List<string>? DestOverride { get; set; } = ["http", "tls"];
|
public List<string>? DestOverride { get; set; } = ["http", "tls"];
|
||||||
public bool RouteOnly { get; set; }
|
public bool RouteOnly { get; set; }
|
||||||
public bool AllowLANConn { get; set; }
|
public bool AllowLANConn { get; set; }
|
||||||
|
|
||||||
public bool NewPort4LAN { get; set; }
|
public bool NewPort4LAN { get; set; }
|
||||||
|
|
||||||
public string User { get; set; }
|
public string User { get; set; }
|
||||||
|
|
||||||
public string Pass { get; set; }
|
public string Pass { get; set; }
|
||||||
|
public bool SecondLocalPortEnabled { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
@@ -81,13 +76,13 @@
|
|||||||
|
|
||||||
public int AutoUpdateInterval { get; set; }
|
public int AutoUpdateInterval { get; set; }
|
||||||
|
|
||||||
public bool CheckPreReleaseUpdate { get; set; } = false;
|
|
||||||
|
|
||||||
public bool EnableSecurityProtocolTls13 { get; set; }
|
public bool EnableSecurityProtocolTls13 { get; set; }
|
||||||
|
|
||||||
public int TrayMenuServersLimit { get; set; } = 20;
|
public int TrayMenuServersLimit { get; set; } = 20;
|
||||||
|
|
||||||
public bool EnableHWA { get; set; } = false;
|
public bool EnableHWA { get; set; } = false;
|
||||||
|
|
||||||
|
public bool EnableLog { get; set; } = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
@@ -116,6 +111,7 @@
|
|||||||
public bool EnableDragDropSort { get; set; }
|
public bool EnableDragDropSort { get; set; }
|
||||||
public bool DoubleClick2Activate { get; set; }
|
public bool DoubleClick2Activate { get; set; }
|
||||||
public bool AutoHideStartup { get; set; }
|
public bool AutoHideStartup { get; set; }
|
||||||
|
public bool Hide2TrayWhenClose { get; set; }
|
||||||
public List<ColumnItem> MainColumnItem { get; set; }
|
public List<ColumnItem> MainColumnItem { get; set; }
|
||||||
public bool ShowInTaskbar { get; set; }
|
public bool ShowInTaskbar { get; set; }
|
||||||
}
|
}
|
||||||
@@ -161,6 +157,7 @@
|
|||||||
public int Mtu { get; set; }
|
public int Mtu { get; set; }
|
||||||
public bool EnableExInbound { get; set; }
|
public bool EnableExInbound { get; set; }
|
||||||
public bool EnableIPv6Address { get; set; }
|
public bool EnableIPv6Address { get; set; }
|
||||||
|
public string? LinuxSudoPwd { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
@@ -169,6 +166,7 @@
|
|||||||
public int SpeedTestTimeout { get; set; }
|
public int SpeedTestTimeout { get; set; }
|
||||||
public string SpeedTestUrl { get; set; }
|
public string SpeedTestUrl { get; set; }
|
||||||
public string SpeedPingTestUrl { get; set; }
|
public string SpeedPingTestUrl { get; set; }
|
||||||
|
public int SpeedTestPageSize { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
@@ -178,7 +176,6 @@
|
|||||||
public string DomainStrategy4Singbox { get; set; }
|
public string DomainStrategy4Singbox { get; set; }
|
||||||
public string DomainMatcher { get; set; }
|
public string DomainMatcher { get; set; }
|
||||||
public string RoutingIndexId { get; set; }
|
public string RoutingIndexId { get; set; }
|
||||||
public bool EnableRoutingAdvanced { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
@@ -221,7 +218,6 @@
|
|||||||
public int ProxiesSorting { get; set; }
|
public int ProxiesSorting { get; set; }
|
||||||
public bool ProxiesAutoRefresh { get; set; }
|
public bool ProxiesAutoRefresh { get; set; }
|
||||||
public int ProxiesAutoDelayTestInterval { get; set; } = 10;
|
public int ProxiesAutoDelayTestInterval { get; set; } = 10;
|
||||||
public int ConnectionsSorting { get; set; }
|
|
||||||
public bool ConnectionsAutoRefresh { get; set; }
|
public bool ConnectionsAutoRefresh { get; set; }
|
||||||
public int ConnectionsRefreshInterval { get; set; } = 2;
|
public int ConnectionsRefreshInterval { get; set; } = 2;
|
||||||
}
|
}
|
||||||
@@ -243,4 +239,19 @@
|
|||||||
public string? Password { get; set; }
|
public string? Password { get; set; }
|
||||||
public string? DirName { 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; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -12,6 +12,8 @@
|
|||||||
public string? DownloadUrlWinArm64 { get; set; }
|
public string? DownloadUrlWinArm64 { get; set; }
|
||||||
public string? DownloadUrlLinux64 { get; set; }
|
public string? DownloadUrlLinux64 { get; set; }
|
||||||
public string? DownloadUrlLinuxArm64 { get; set; }
|
public string? DownloadUrlLinuxArm64 { get; set; }
|
||||||
|
public string? DownloadUrlOSX64 { get; set; }
|
||||||
|
public string? DownloadUrlOSXArm64 { get; set; }
|
||||||
public string? Match { get; set; }
|
public string? Match { get; set; }
|
||||||
public string? VersionArg { get; set; }
|
public string? VersionArg { get; set; }
|
||||||
public bool RedirectInfo { get; set; }
|
public bool RedirectInfo { get; set; }
|
||||||
|
|||||||
13
v2rayN/ServiceLib/Models/IPAPIInfo.cs
Normal file
13
v2rayN/ServiceLib/Models/IPAPIInfo.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace ServiceLib.Models
|
||||||
|
{
|
||||||
|
internal class IPAPIInfo
|
||||||
|
{
|
||||||
|
public string? ip { get; set; }
|
||||||
|
public string? city { get; set; }
|
||||||
|
public string? region { get; set; }
|
||||||
|
public string? region_code { get; set; }
|
||||||
|
public string? country { get; set; }
|
||||||
|
public string? country_name { get; set; }
|
||||||
|
public string? country_code { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,44 +30,25 @@ namespace ServiceLib.Models
|
|||||||
|
|
||||||
public string GetSummary()
|
public string GetSummary()
|
||||||
{
|
{
|
||||||
string summary = string.Format("[{0}] ", (ConfigType).ToString());
|
var summary = $"[{(ConfigType).ToString()}] ";
|
||||||
string[] arrAddr = Address.Split('.');
|
var arrAddr = Address.Split('.');
|
||||||
string addr;
|
var addr = arrAddr.Length switch
|
||||||
if (arrAddr.Length > 2)
|
|
||||||
{
|
{
|
||||||
addr = $"{arrAddr.First()}***{arrAddr.Last()}";
|
> 2 => $"{arrAddr.First()}***{arrAddr.Last()}",
|
||||||
}
|
> 1 => $"***{arrAddr.Last()}",
|
||||||
else if (arrAddr.Length > 1)
|
_ => Address
|
||||||
|
};
|
||||||
|
summary += ConfigType switch
|
||||||
{
|
{
|
||||||
addr = $"***{arrAddr.Last()}";
|
EConfigType.Custom => $"[{CoreType.ToString()}]{Remarks}",
|
||||||
}
|
_ => $"{Remarks}({addr}:{Port})"
|
||||||
else
|
};
|
||||||
{
|
|
||||||
addr = Address;
|
|
||||||
}
|
|
||||||
switch (ConfigType)
|
|
||||||
{
|
|
||||||
case EConfigType.Custom:
|
|
||||||
summary += string.Format("[{1}]{0}", Remarks, CoreType.ToString());
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
summary += string.Format("{0}({1}:{2})", Remarks, addr, Port);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return summary;
|
return summary;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<string>? GetAlpn()
|
public List<string>? GetAlpn()
|
||||||
{
|
{
|
||||||
if (Utils.IsNullOrEmpty(Alpn))
|
return Utils.IsNullOrEmpty(Alpn) ? null : Utils.String2List(Alpn);
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return Utils.String2List(Alpn);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetNetwork()
|
public string GetNetwork()
|
||||||
@@ -110,5 +91,6 @@ namespace ServiceLib.Models
|
|||||||
public string PublicKey { get; set; }
|
public string PublicKey { get; set; }
|
||||||
public string ShortId { get; set; }
|
public string ShortId { get; set; }
|
||||||
public string SpiderX { get; set; }
|
public string SpiderX { get; set; }
|
||||||
|
public string Extra { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,8 +78,7 @@
|
|||||||
public int? listen_port { get; set; }
|
public int? listen_port { get; set; }
|
||||||
public string? domain_strategy { get; set; }
|
public string? domain_strategy { get; set; }
|
||||||
public string interface_name { get; set; }
|
public string interface_name { get; set; }
|
||||||
public string inet4_address { get; set; }
|
public List<string>? address { get; set; }
|
||||||
public string? inet6_address { get; set; }
|
|
||||||
public int? mtu { get; set; }
|
public int? mtu { get; set; }
|
||||||
public bool? auto_route { get; set; }
|
public bool? auto_route { get; set; }
|
||||||
public bool? strict_route { get; set; }
|
public bool? strict_route { get; set; }
|
||||||
|
|||||||
@@ -33,5 +33,7 @@ namespace ServiceLib.Models
|
|||||||
public string? NextProfile { get; set; }
|
public string? NextProfile { get; set; }
|
||||||
|
|
||||||
public int? PreSocksPort { get; set; }
|
public int? PreSocksPort { get; set; }
|
||||||
|
|
||||||
|
public string? Memo { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,61 +1,34 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace ServiceLib.Models
|
namespace ServiceLib.Models
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// v2ray配置文件实体类 例子SampleConfig.txt
|
|
||||||
/// </summary>
|
|
||||||
public class V2rayConfig
|
public class V2rayConfig
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Properties that do not belong to Ray
|
|
||||||
/// </summary>
|
|
||||||
public string? remarks { get; set; }
|
public string? remarks { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 日志配置
|
|
||||||
/// </summary>
|
|
||||||
public Log4Ray log { get; set; }
|
public Log4Ray log { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 传入连接配置
|
|
||||||
/// </summary>
|
|
||||||
public List<Inbounds4Ray> inbounds { get; set; }
|
public List<Inbounds4Ray> inbounds { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 传出连接配置
|
|
||||||
/// </summary>
|
|
||||||
public List<Outbounds4Ray> outbounds { get; set; }
|
public List<Outbounds4Ray> outbounds { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
public Stats4Ray? stats { get; set; }
|
||||||
/// 统计需要, 空对象
|
|
||||||
/// </summary>
|
|
||||||
public Stats4Ray stats { get; set; }
|
|
||||||
|
|
||||||
/// </summary>
|
public Metrics4Ray? metrics { get; set; }
|
||||||
public API4Ray api { get; set; }
|
|
||||||
|
|
||||||
/// </summary>
|
public Policy4Ray? policy { get; set; }
|
||||||
public Policy4Ray policy { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// DNS 配置
|
|
||||||
/// </summary>
|
|
||||||
public object dns { get; set; }
|
public object dns { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 路由配置
|
|
||||||
/// </summary>
|
|
||||||
public Routing4Ray routing { get; set; }
|
public Routing4Ray routing { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Stats4Ray
|
public class Stats4Ray
|
||||||
{ };
|
{ }
|
||||||
|
|
||||||
public class API4Ray
|
public class Metrics4Ray
|
||||||
{
|
{
|
||||||
public string tag { get; set; }
|
public string tag { get; set; }
|
||||||
public List<string> services { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Policy4Ray
|
public class Policy4Ray
|
||||||
@@ -71,124 +44,59 @@ namespace ServiceLib.Models
|
|||||||
|
|
||||||
public class Log4Ray
|
public class Log4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
public string? access { get; set; }
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string access { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
public string? error { get; set; }
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string error { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
public string? loglevel { get; set; }
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string loglevel { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Inbounds4Ray
|
public class Inbounds4Ray
|
||||||
{
|
{
|
||||||
public string tag { get; set; }
|
public string tag { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int port { get; set; }
|
public int port { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string listen { get; set; }
|
public string listen { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string protocol { get; set; }
|
public string protocol { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public Sniffing4Ray sniffing { get; set; }
|
public Sniffing4Ray sniffing { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public Inboundsettings4Ray settings { get; set; }
|
public Inboundsettings4Ray settings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public StreamSettings4Ray streamSettings { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Inboundsettings4Ray
|
public class Inboundsettings4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
public string? auth { get; set; }
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string auth { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
public bool? udp { get; set; }
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public bool udp { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
public string? ip { get; set; }
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ip { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
public string? address { get; set; }
|
||||||
/// api 使用
|
|
||||||
/// </summary>
|
|
||||||
public string address { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
public List<UsersItem4Ray>? clients { get; set; }
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public List<UsersItem4Ray> clients { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
public string? decryption { get; set; }
|
||||||
/// VLESS
|
|
||||||
/// </summary>
|
|
||||||
public string decryption { get; set; }
|
|
||||||
|
|
||||||
public bool allowTransparent { get; set; }
|
public bool? allowTransparent { get; set; }
|
||||||
|
|
||||||
public List<AccountsItem4Ray> accounts { get; set; }
|
public List<AccountsItem4Ray>? accounts { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UsersItem4Ray
|
public class UsersItem4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
public string? id { get; set; }
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
public int? alterId { get; set; }
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int alterId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
public string? email { get; set; }
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string email { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
public string? security { get; set; }
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string security { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
public string? encryption { get; set; }
|
||||||
/// VLESS
|
|
||||||
/// </summary>
|
|
||||||
public string encryption { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// VLESS
|
|
||||||
/// </summary>
|
|
||||||
public string? flow { get; set; }
|
public string? flow { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,57 +109,27 @@ namespace ServiceLib.Models
|
|||||||
|
|
||||||
public class Outbounds4Ray
|
public class Outbounds4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// 默认值agentout
|
|
||||||
/// </summary>
|
|
||||||
public string tag { get; set; }
|
public string tag { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string protocol { get; set; }
|
public string protocol { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public Outboundsettings4Ray settings { get; set; }
|
public Outboundsettings4Ray settings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public StreamSettings4Ray streamSettings { get; set; }
|
public StreamSettings4Ray streamSettings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public Mux4Ray mux { get; set; }
|
public Mux4Ray mux { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Outboundsettings4Ray
|
public class Outboundsettings4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public List<VnextItem4Ray>? vnext { get; set; }
|
public List<VnextItem4Ray>? vnext { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
public List<ServersItem4Ray>? servers { get; set; }
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public List<ServersItem4Ray> servers { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
public Response4Ray? response { get; set; }
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public Response4Ray response { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string domainStrategy { get; set; }
|
public string domainStrategy { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int? userLevel { get; set; }
|
public int? userLevel { get; set; }
|
||||||
|
|
||||||
public FragmentItem4Ray? fragment { get; set; }
|
public FragmentItem4Ray? fragment { get; set; }
|
||||||
@@ -259,85 +137,40 @@ namespace ServiceLib.Models
|
|||||||
|
|
||||||
public class VnextItem4Ray
|
public class VnextItem4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string address { get; set; }
|
public string address { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int port { get; set; }
|
public int port { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public List<UsersItem4Ray> users { get; set; }
|
public List<UsersItem4Ray> users { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ServersItem4Ray
|
public class ServersItem4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string email { get; set; }
|
public string email { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string address { get; set; }
|
public string address { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? method { get; set; }
|
public string? method { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public bool? ota { get; set; }
|
public bool? ota { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? password { get; set; }
|
public string? password { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int port { get; set; }
|
public int port { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int? level { get; set; }
|
public int? level { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// trojan
|
|
||||||
/// </summary>
|
|
||||||
public string flow { get; set; }
|
public string flow { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public List<SocksUsersItem4Ray> users { get; set; }
|
public List<SocksUsersItem4Ray> users { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SocksUsersItem4Ray
|
public class SocksUsersItem4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string user { get; set; }
|
public string user { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string pass { get; set; }
|
public string pass { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int? level { get; set; }
|
public int? level { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,17 +184,11 @@ namespace ServiceLib.Models
|
|||||||
|
|
||||||
public class Response4Ray
|
public class Response4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string type { get; set; }
|
public string type { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Dns4Ray
|
public class Dns4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public List<string> servers { get; set; }
|
public List<string> servers { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,19 +200,10 @@ namespace ServiceLib.Models
|
|||||||
|
|
||||||
public class Routing4Ray
|
public class Routing4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string domainStrategy { get; set; }
|
public string domainStrategy { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? domainMatcher { get; set; }
|
public string? domainMatcher { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public List<RulesItem4Ray> rules { get; set; }
|
public List<RulesItem4Ray> rules { get; set; }
|
||||||
|
|
||||||
public List<BalancersItem4Ray>? balancers { get; set; }
|
public List<BalancersItem4Ray>? balancers { get; set; }
|
||||||
@@ -426,87 +244,39 @@ namespace ServiceLib.Models
|
|||||||
|
|
||||||
public class StreamSettings4Ray
|
public class StreamSettings4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string network { get; set; }
|
public string network { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string security { get; set; }
|
public string security { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public TlsSettings4Ray? tlsSettings { get; set; }
|
public TlsSettings4Ray? tlsSettings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tcp传输额外设置
|
|
||||||
/// </summary>
|
|
||||||
public TcpSettings4Ray? tcpSettings { get; set; }
|
public TcpSettings4Ray? tcpSettings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Kcp传输额外设置
|
|
||||||
/// </summary>
|
|
||||||
public KcpSettings4Ray? kcpSettings { get; set; }
|
public KcpSettings4Ray? kcpSettings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// ws传输额外设置
|
|
||||||
/// </summary>
|
|
||||||
public WsSettings4Ray? wsSettings { get; set; }
|
public WsSettings4Ray? wsSettings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public HttpupgradeSettings4Ray? httpupgradeSettings { get; set; }
|
public HttpupgradeSettings4Ray? httpupgradeSettings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
public XhttpSettings4Ray? xhttpSettings { get; set; }
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public SplithttpSettings4Ray? splithttpSettings { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// h2传输额外设置
|
|
||||||
/// </summary>
|
|
||||||
public HttpSettings4Ray? httpSettings { get; set; }
|
public HttpSettings4Ray? httpSettings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// QUIC
|
|
||||||
/// </summary>
|
|
||||||
public QuicSettings4Ray? quicSettings { get; set; }
|
public QuicSettings4Ray? quicSettings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// VLESS only
|
|
||||||
/// </summary>
|
|
||||||
public TlsSettings4Ray? realitySettings { get; set; }
|
public TlsSettings4Ray? realitySettings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// grpc
|
|
||||||
/// </summary>
|
|
||||||
public GrpcSettings4Ray? grpcSettings { get; set; }
|
public GrpcSettings4Ray? grpcSettings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// sockopt
|
|
||||||
/// </summary>
|
|
||||||
public Sockopt4Ray? sockopt { get; set; }
|
public Sockopt4Ray? sockopt { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TlsSettings4Ray
|
public class TlsSettings4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// 是否允许不安全连接(用于客户端)
|
|
||||||
/// </summary>
|
|
||||||
public bool? allowInsecure { get; set; }
|
public bool? allowInsecure { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? serverName { get; set; }
|
public string? serverName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public List<string>? alpn { get; set; }
|
public List<string>? alpn { get; set; }
|
||||||
|
|
||||||
public string? fingerprint { get; set; }
|
public string? fingerprint { get; set; }
|
||||||
@@ -519,157 +289,83 @@ namespace ServiceLib.Models
|
|||||||
|
|
||||||
public class TcpSettings4Ray
|
public class TcpSettings4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// 数据包头部伪装设置
|
|
||||||
/// </summary>
|
|
||||||
public Header4Ray header { get; set; }
|
public Header4Ray header { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Header4Ray
|
public class Header4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// 伪装
|
|
||||||
/// </summary>
|
|
||||||
public string type { get; set; }
|
public string type { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 结构复杂,直接存起来
|
|
||||||
/// </summary>
|
|
||||||
public object request { get; set; }
|
public object request { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 结构复杂,直接存起来
|
|
||||||
/// </summary>
|
|
||||||
public object response { get; set; }
|
public object response { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class KcpSettings4Ray
|
public class KcpSettings4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int mtu { get; set; }
|
public int mtu { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int tti { get; set; }
|
public int tti { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int uplinkCapacity { get; set; }
|
public int uplinkCapacity { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int downlinkCapacity { get; set; }
|
public int downlinkCapacity { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public bool congestion { get; set; }
|
public bool congestion { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int readBufferSize { get; set; }
|
public int readBufferSize { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int writeBufferSize { get; set; }
|
public int writeBufferSize { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public Header4Ray header { get; set; }
|
public Header4Ray header { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string seed { get; set; }
|
public string seed { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WsSettings4Ray
|
public class WsSettings4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
public string? path { get; set; }
|
||||||
///
|
public string? host { get; set; }
|
||||||
/// </summary>
|
|
||||||
public string path { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public Headers4Ray headers { get; set; }
|
public Headers4Ray headers { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Headers4Ray
|
public class Headers4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string Host { get; set; }
|
public string Host { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 用户代理
|
|
||||||
/// </summary>
|
|
||||||
[JsonPropertyName("User-Agent")]
|
[JsonPropertyName("User-Agent")]
|
||||||
public string UserAgent { get; set; }
|
public string UserAgent { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class HttpupgradeSettings4Ray
|
public class HttpupgradeSettings4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? path { get; set; }
|
public string? path { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? host { get; set; }
|
public string? host { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SplithttpSettings4Ray
|
public class XhttpSettings4Ray
|
||||||
{
|
{
|
||||||
public string? path { get; set; }
|
public string? path { get; set; }
|
||||||
|
|
||||||
public string? host { get; set; }
|
public string? host { get; set; }
|
||||||
|
public string? mode { get; set; }
|
||||||
public int? maxUploadSize { get; set; }
|
public object? extra { get; set; }
|
||||||
|
|
||||||
public int? maxConcurrentUploads { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class HttpSettings4Ray
|
public class HttpSettings4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? path { get; set; }
|
public string? path { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public List<string>? host { get; set; }
|
public List<string>? host { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class QuicSettings4Ray
|
public class QuicSettings4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string security { get; set; }
|
public string security { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string key { get; set; }
|
public string key { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public Header4Ray header { get; set; }
|
public Header4Ray header { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -686,14 +382,8 @@ namespace ServiceLib.Models
|
|||||||
|
|
||||||
public class AccountsItem4Ray
|
public class AccountsItem4Ray
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string user { get; set; }
|
public string user { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string pass { get; set; }
|
public string pass { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
20
v2rayN/ServiceLib/Models/V2rayMetricsVars.cs
Normal file
20
v2rayN/ServiceLib/Models/V2rayMetricsVars.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace ServiceLib.Models
|
||||||
|
{
|
||||||
|
internal class V2rayMetricsVars
|
||||||
|
{
|
||||||
|
public V2rayMetricsVarsStats? stats { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class V2rayMetricsVarsStats
|
||||||
|
{
|
||||||
|
public Hashtable? outbound { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class V2rayMetricsVarsLink
|
||||||
|
{
|
||||||
|
public long downlink { get; set; }
|
||||||
|
public long uplink { get; set; }
|
||||||
|
}
|
||||||
172
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
172
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
@@ -447,6 +447,15 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Remarks Memo 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string LvMemo {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LvMemo", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 More URLs, separated by commas; Subscription conversion will be invalid 的本地化字符串。
|
/// 查找类似 More URLs, separated by commas; Subscription conversion will be invalid 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -870,6 +879,15 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Are you sure to exit? 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string menuExitTips {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("menuExitTips", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Export selected server for complete configuration 的本地化字符串。
|
/// 查找类似 Export selected server for complete configuration 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -1230,6 +1248,15 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Iran 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string menuRegionalPresetsIran {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("menuRegionalPresetsIran", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Russia 的本地化字符串。
|
/// 查找类似 Russia 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -1347,24 +1374,6 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 Basic Function 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string menuRoutingBasic {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("menuRoutingBasic", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 Import Basic Rules 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string menuRoutingBasicImportRules {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("menuRoutingBasicImportRules", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 RoutingRuleDetailsSetting 的本地化字符串。
|
/// 查找类似 RoutingRuleDetailsSetting 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -2599,6 +2608,15 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 socks: local port, socks2: second local port, socks3: LAN port 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TbRoutingInboundTagTips {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TbRoutingInboundTagTips", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Domain 的本地化字符串。
|
/// 查找类似 Domain 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -2860,6 +2878,15 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Install the font to the system and restart the settings 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TbSettingsCurrentFontFamilyLinuxTip {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TbSettingsCurrentFontFamilyLinuxTip", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Copy the font TTF/TTC file to the directory guiFonts, restart the settings 的本地化字符串。
|
/// 查找类似 Copy the font TTF/TTC file to the directory guiFonts, restart the settings 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -2905,6 +2932,15 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Sniffing type 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TbSettingsDestOverride {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TbSettingsDestOverride", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Outbound DNS address 的本地化字符串。
|
/// 查找类似 Outbound DNS address 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -3049,6 +3085,15 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Exception. Do not use proxy server for addresses,with a comma (,) 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TbSettingsExceptionTip2 {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TbSettingsExceptionTip2", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Follow System Theme 的本地化字符串。
|
/// 查找类似 Follow System Theme 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -3076,6 +3121,15 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Hide to tray when closing the window 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TbSettingsHide2TrayWhenClose {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TbSettingsHide2TrayWhenClose", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 HTTP Port 的本地化字符串。
|
/// 查找类似 HTTP Port 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -3121,6 +3175,42 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 System sudo password 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TbSettingsLinuxSudoPassword {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TbSettingsLinuxSudoPassword", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Please set the sudo password in Tun mode settings first 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TbSettingsLinuxSudoPasswordIsEmpty {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TbSettingsLinuxSudoPasswordIsEmpty", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Please do not run this app with sudo 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TbSettingsLinuxSudoPasswordNotSudoRunApp {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TbSettingsLinuxSudoPasswordNotSudoRunApp", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 The password is encrypted and stored only in local files. 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TbSettingsLinuxSudoPasswordTip {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TbSettingsLinuxSudoPasswordTip", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Enable Log 的本地化字符串。
|
/// 查找类似 Enable Log 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -3238,6 +3328,15 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Enable second mixed port 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TbSettingsSecondLocalPortEnabled {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TbSettingsSecondLocalPortEnabled", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Set Win10 UWP Loopback 的本地化字符串。
|
/// 查找类似 Set Win10 UWP Loopback 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -3257,7 +3356,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 SOCKS Port 的本地化字符串。
|
/// 查找类似 Mixed Port 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TbSettingsSocksPort {
|
public static string TbSettingsSocksPort {
|
||||||
get {
|
get {
|
||||||
@@ -3266,7 +3365,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 http port = +1; Pac port = +4; *ray API port = +5; mihomo API port = +6; 的本地化字符串。
|
/// 查找类似 Pac port = +3; Xray API port = +4; mihomo API port = +5; 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TbSettingsSocksPortTip {
|
public static string TbSettingsSocksPortTip {
|
||||||
get {
|
get {
|
||||||
@@ -3283,6 +3382,15 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Number per time for auto batch during speedtest(max 1000) 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TbSettingsSpeedTestPageSize {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TbSettingsSpeedTestPageSize", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 SpeedTest Single Timeout Value 的本地化字符串。
|
/// 查找类似 SpeedTest Single Timeout Value 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -3572,7 +3680,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 The ping of current service: {0} ms 的本地化字符串。
|
/// 查找类似 The delay : {0} ms, {1} 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TestMeOutput {
|
public static string TestMeOutput {
|
||||||
get {
|
get {
|
||||||
@@ -3634,6 +3742,15 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 XHTTP Extra raw JSON, format: { XHTTPObject } 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TransportExtraTip {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TransportExtraTip", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 *tcp camouflage type 的本地化字符串。
|
/// 查找类似 *tcp camouflage type 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -3671,7 +3788,16 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 *ws/httpupgrade/splithttp path 的本地化字符串。
|
/// 查找类似 *xhttp mode 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TransportHeaderTypeTip5 {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TransportHeaderTypeTip5", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 *ws/httpupgrade/xhttp path 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TransportPathTip1 {
|
public static string TransportPathTip1 {
|
||||||
get {
|
get {
|
||||||
@@ -3725,7 +3851,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 *ws/httpupgrade/splithttp host 的本地化字符串。
|
/// 查找类似 *ws/httpupgrade/xhttp host 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TransportRequestHostTip2 {
|
public static string TransportRequestHostTip2 {
|
||||||
get {
|
get {
|
||||||
|
|||||||
@@ -118,7 +118,7 @@
|
|||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<data name="BatchExportURLSuccessfully" xml:space="preserve">
|
<data name="BatchExportURLSuccessfully" xml:space="preserve">
|
||||||
<value>Batch export share URL to clipboard successfully</value>
|
<value>ارسال دسته ای آدرس اینترنتی اشتراک گذاری به کلیپ بورد با موفقیت.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CheckServerSettings" xml:space="preserve">
|
<data name="CheckServerSettings" xml:space="preserve">
|
||||||
<value>لطفا ابتدا تنظیمات سرور را بررسی کنید</value>
|
<value>لطفا ابتدا تنظیمات سرور را بررسی کنید</value>
|
||||||
@@ -136,7 +136,7 @@
|
|||||||
<value>دانلود</value>
|
<value>دانلود</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DownloadYesNo" xml:space="preserve">
|
<data name="DownloadYesNo" xml:space="preserve">
|
||||||
<value>Whether to download? {0}</value>
|
<value>آیا برای دانلود؟ {0}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FailedConversionConfiguration" xml:space="preserve">
|
<data name="FailedConversionConfiguration" xml:space="preserve">
|
||||||
<value>تبدیل فایل پیکربندی انجام نشد</value>
|
<value>تبدیل فایل پیکربندی انجام نشد</value>
|
||||||
@@ -226,7 +226,7 @@
|
|||||||
<value>هیچ اشتراک معتبری تنظیم نشده است</value>
|
<value>هیچ اشتراک معتبری تنظیم نشده است</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgParsingSuccessfully" xml:space="preserve">
|
<data name="MsgParsingSuccessfully" xml:space="preserve">
|
||||||
<value>Resolve {0} successfully</value>
|
<value>حل {0} با موفقیت</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgStartGettingSubscriptions" xml:space="preserve">
|
<data name="MsgStartGettingSubscriptions" xml:space="preserve">
|
||||||
<value>شروع به دریافت اشتراک شد</value>
|
<value>شروع به دریافت اشتراک شد</value>
|
||||||
@@ -253,19 +253,19 @@
|
|||||||
<value>هسته با موفقیت بروزرسانی شد! راه اندازی مجدد سرویس...</value>
|
<value>هسته با موفقیت بروزرسانی شد! راه اندازی مجدد سرویس...</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="NonvmessOrssProtocol" xml:space="preserve">
|
<data name="NonvmessOrssProtocol" xml:space="preserve">
|
||||||
<value>Non-VMess or ss protocol</value>
|
<value>پروتکل غیر VMess یا ss</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="NotFoundCore" xml:space="preserve">
|
<data name="NotFoundCore" xml:space="preserve">
|
||||||
<value>The Core file (file name: {1}) was not found under the folder ({0}), please download and put it in the folder, download address: {2}</value>
|
<value>فایل Core (نام فایل: {1}) در زیر پوشه ({0}) یافت نشد، لطفاً آن را دانلود کرده و در پوشه قرار دهید، آدرس دانلود: {2}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="NoValidQRcodeFound" xml:space="preserve">
|
<data name="NoValidQRcodeFound" xml:space="preserve">
|
||||||
<value>Scan completed, no valid QR code found</value>
|
<value>اسکن کامل شد، QRcode معتبری یافت نشد</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="OperationFailed" xml:space="preserve">
|
<data name="OperationFailed" xml:space="preserve">
|
||||||
<value> عملیات انجام نشد، لطفا بررسی کنید و دوباره امتحان کنید</value>
|
<value> عملیات انجام نشد، لطفا بررسی کنید و دوباره امتحان کنید</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PleaseFillRemarks" xml:space="preserve">
|
<data name="PleaseFillRemarks" xml:space="preserve">
|
||||||
<value>Please Fill Remarks</value>
|
<value>لطفا ملاحظات را پر کنید</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PleaseSelectEncryption" xml:space="preserve">
|
<data name="PleaseSelectEncryption" xml:space="preserve">
|
||||||
<value>لطفاً روش رمزگذاری را انتخاب کنید</value>
|
<value>لطفاً روش رمزگذاری را انتخاب کنید</value>
|
||||||
@@ -277,16 +277,16 @@
|
|||||||
<value>لطفا ابتدا سرور را انتخاب کنید</value>
|
<value>لطفا ابتدا سرور را انتخاب کنید</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RemoveDuplicateServerResult" xml:space="preserve">
|
<data name="RemoveDuplicateServerResult" xml:space="preserve">
|
||||||
<value>Servers deduplication completed. Old: {0}, New: {1}.</value>
|
<value>حذف مجدد سرورها تکمیل شد. قدیمی: {0}، جدید: {1}.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RemoveServer" xml:space="preserve">
|
<data name="RemoveServer" xml:space="preserve">
|
||||||
<value>آیا مطمئن هستید که سرور را حذف می کنید؟</value>
|
<value>آیا مطمئن هستید که سرور را حذف می کنید؟</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SaveClientConfigurationIn" xml:space="preserve">
|
<data name="SaveClientConfigurationIn" xml:space="preserve">
|
||||||
<value>The client configuration file is saved at: {0}</value>
|
<value>فایل پیکربندی کلاینت در این آدرس ذخیره می شود: {0}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="StartService" xml:space="preserve">
|
<data name="StartService" xml:space="preserve">
|
||||||
<value>Start service ({0})...</value>
|
<value>شروع سرویس ({0})...</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SuccessfulConfiguration" xml:space="preserve">
|
<data name="SuccessfulConfiguration" xml:space="preserve">
|
||||||
<value>پیکربندی با موفقیت انجام شد
|
<value>پیکربندی با موفقیت انجام شد
|
||||||
@@ -302,7 +302,7 @@
|
|||||||
<value>اسکن URL وارد کردن با موفقیت</value>
|
<value>اسکن URL وارد کردن با موفقیت</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TestMeOutput" xml:space="preserve">
|
<data name="TestMeOutput" xml:space="preserve">
|
||||||
<value>پینگ سرویس فعلی: {0} ms</value>
|
<value>پینگ سرویس فعلی: {0} ms, {1}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="OperationSuccess" xml:space="preserve">
|
<data name="OperationSuccess" xml:space="preserve">
|
||||||
<value>موفقیت عملیات</value>
|
<value>موفقیت عملیات</value>
|
||||||
@@ -317,19 +317,19 @@
|
|||||||
<value>{0},یکی از مورد نیاز.</value>
|
<value>{0},یکی از مورد نیاز.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvRemarks" xml:space="preserve">
|
<data name="LvRemarks" xml:space="preserve">
|
||||||
<value>Remarks</value>
|
<value>ملاحظات</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvUrl" xml:space="preserve">
|
<data name="LvUrl" xml:space="preserve">
|
||||||
<value>Url(Optional)</value>
|
<value>آدرس اینترنتی (اختیاری)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvCount" xml:space="preserve">
|
<data name="LvCount" xml:space="preserve">
|
||||||
<value>Count</value>
|
<value>شمارش</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgNeedUrl" xml:space="preserve">
|
<data name="MsgNeedUrl" xml:space="preserve">
|
||||||
<value>Please fill in the address (Url)</value>
|
<value>لطفا آدرس (آدرس اینترنتی) را وارد کنید</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AddBatchRoutingRulesYesNo" xml:space="preserve">
|
<data name="AddBatchRoutingRulesYesNo" xml:space="preserve">
|
||||||
<value>Do you want to append rules? Choose yes to append, choose otherwise to replace</value>
|
<value>آیا می خواهید قوانین را اضافه کنید؟ برای ضمیمه بله را انتخاب کنید، در غیر این صورت جایگزین کنید</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgDownloadGeoFileSuccessfully" xml:space="preserve">
|
<data name="MsgDownloadGeoFileSuccessfully" xml:space="preserve">
|
||||||
<value>دانلود GeoFile: {0} با موفقیت</value>
|
<value>دانلود GeoFile: {0} با موفقیت</value>
|
||||||
@@ -386,10 +386,10 @@
|
|||||||
<value>*Kcp seed</value>
|
<value>*Kcp seed</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RegisterGlobalHotkeyFailed" xml:space="preserve">
|
<data name="RegisterGlobalHotkeyFailed" xml:space="preserve">
|
||||||
<value>Global hotkey {0} registered failed, reason {1}</value>
|
<value>کلید میانبر جهانی {0} ثبت نشد، دلیل کلید میانبر جهانی {0} ثبت ناموفق بود، دلیل {1}{1}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
|
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
|
||||||
<value>Global hotkey {0} registered successfully</value>
|
<value>کلید میانبر جهانی {0} با موفقیت ثبت شد</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UngroupedServers" xml:space="preserve">
|
<data name="UngroupedServers" xml:space="preserve">
|
||||||
<value>گروه بندی نشده</value>
|
<value>گروه بندی نشده</value>
|
||||||
@@ -398,7 +398,7 @@
|
|||||||
<value>همه سرورها</value>
|
<value>همه سرورها</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FillServerAddressCustom" xml:space="preserve">
|
<data name="FillServerAddressCustom" xml:space="preserve">
|
||||||
<value>Please browse to import server configuration</value>
|
<value>لطفاً برای وارد کردن پیکربندی سرور مرور کنید</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Speedtesting" xml:space="preserve">
|
<data name="Speedtesting" xml:space="preserve">
|
||||||
<value>درحال تست کردن...</value>
|
<value>درحال تست کردن...</value>
|
||||||
@@ -593,7 +593,7 @@
|
|||||||
<value>آدرس</value>
|
<value>آدرس</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbAllowInsecure" xml:space="preserve">
|
<data name="TbAllowInsecure" xml:space="preserve">
|
||||||
<value>اجازه ناامن</value>
|
<value>اعطای مجوز ناامن</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbAlpn" xml:space="preserve">
|
<data name="TbAlpn" xml:space="preserve">
|
||||||
<value>Alpn</value>
|
<value>Alpn</value>
|
||||||
@@ -602,10 +602,10 @@
|
|||||||
<value>AlterId</value>
|
<value>AlterId</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbFingerprint" xml:space="preserve">
|
<data name="TbFingerprint" xml:space="preserve">
|
||||||
<value>Fingerprint</value>
|
<value>اثرانگشت</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbHeaderType" xml:space="preserve">
|
<data name="TbHeaderType" xml:space="preserve">
|
||||||
<value>Camouflage type</value>
|
<value>نوع Camouflage</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbId" xml:space="preserve">
|
<data name="TbId" xml:space="preserve">
|
||||||
<value>UUID(id)</value>
|
<value>UUID(id)</value>
|
||||||
@@ -620,13 +620,13 @@
|
|||||||
<value>پورت</value>
|
<value>پورت</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRemarks" xml:space="preserve">
|
<data name="TbRemarks" xml:space="preserve">
|
||||||
<value>Alias (remarks)</value>
|
<value>نام مستعار (ملاحظات)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRequestHost" xml:space="preserve">
|
<data name="TbRequestHost" xml:space="preserve">
|
||||||
<value>Camouflage domain(host)</value>
|
<value>Camouflage domain(host)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSecurity" xml:space="preserve">
|
<data name="TbSecurity" xml:space="preserve">
|
||||||
<value>Encryption method (security)</value>
|
<value>روش رمزگذاری (امنیتی)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSNI" xml:space="preserve">
|
<data name="TbSNI" xml:space="preserve">
|
||||||
<value>SNI</value>
|
<value>SNI</value>
|
||||||
@@ -635,7 +635,7 @@
|
|||||||
<value>TLS</value>
|
<value>TLS</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TipNetwork" xml:space="preserve">
|
<data name="TipNetwork" xml:space="preserve">
|
||||||
<value>*Default value tcp</value>
|
<value>*مقدار پیش فرض tcp</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbCoreType" xml:space="preserve">
|
<data name="TbCoreType" xml:space="preserve">
|
||||||
<value>نوع هسته</value>
|
<value>نوع هسته</value>
|
||||||
@@ -644,7 +644,7 @@
|
|||||||
<value>جریان</value>
|
<value>جریان</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbGUID" xml:space="preserve">
|
<data name="TbGUID" xml:space="preserve">
|
||||||
<value>Generate</value>
|
<value>ساختن</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbId3" xml:space="preserve">
|
<data name="TbId3" xml:space="preserve">
|
||||||
<value>رمزعبور</value>
|
<value>رمزعبور</value>
|
||||||
@@ -668,10 +668,10 @@
|
|||||||
<value>txtPreSocksPort</value>
|
<value>txtPreSocksPort</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TipPreSocksPort" xml:space="preserve">
|
<data name="TipPreSocksPort" xml:space="preserve">
|
||||||
<value>* After setting this value, an socks service will be started using Xray/sing-box(Tun) to provide functions such as speed display</value>
|
<value>* پس از تنظیم این مقدار، یک سرویس جوراب با استفاده از Xray/sing-box (Tun) برای ارائه عملکردهایی مانند نمایش سرعت شروع می شود.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbBrowse" xml:space="preserve">
|
<data name="TbBrowse" xml:space="preserve">
|
||||||
<value>Browse</value>
|
<value>مرور کردن</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbEdit" xml:space="preserve">
|
<data name="TbEdit" xml:space="preserve">
|
||||||
<value>ویرایش</value>
|
<value>ویرایش</value>
|
||||||
@@ -683,7 +683,7 @@
|
|||||||
<value>اتصالات از LAN را مجاز کنید</value>
|
<value>اتصالات از LAN را مجاز کنید</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsAutoHideStartup" xml:space="preserve">
|
<data name="TbSettingsAutoHideStartup" xml:space="preserve">
|
||||||
<value>Auto hide startup</value>
|
<value>راه اندازی مخفی کردن خودکار</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsAutoUpdateInterval" xml:space="preserve">
|
<data name="TbSettingsAutoUpdateInterval" xml:space="preserve">
|
||||||
<value>فاصله به روز رسانی خودکار و Geo (ساعت)</value>
|
<value>فاصله به روز رسانی خودکار و Geo (ساعت)</value>
|
||||||
@@ -692,7 +692,7 @@
|
|||||||
<value>هسته: تنظیمات اولیه</value>
|
<value>هسته: تنظیمات اولیه</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsCoreDns" xml:space="preserve">
|
<data name="TbSettingsCoreDns" xml:space="preserve">
|
||||||
<value>V2ray DNS settings</value>
|
<value>تنظیمات V2ray DNS</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsCoreKcp" xml:space="preserve">
|
<data name="TbSettingsCoreKcp" xml:space="preserve">
|
||||||
<value>هسته: تنظیمات KCP</value>
|
<value>هسته: تنظیمات KCP</value>
|
||||||
@@ -701,7 +701,7 @@
|
|||||||
<value>تنظیمات CoreType</value>
|
<value>تنظیمات CoreType</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsDefAllowInsecure" xml:space="preserve">
|
<data name="TbSettingsDefAllowInsecure" xml:space="preserve">
|
||||||
<value>اجازه ناامن</value>
|
<value>اعطای مجوز ناامن</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsDomainStrategy4Freedom" xml:space="preserve">
|
<data name="TbSettingsDomainStrategy4Freedom" xml:space="preserve">
|
||||||
<value>Outbound Freedom domainStrategy</value>
|
<value>Outbound Freedom domainStrategy</value>
|
||||||
@@ -716,7 +716,7 @@
|
|||||||
<value>استثنا</value>
|
<value>استثنا</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsExceptionTip" xml:space="preserve">
|
<data name="TbSettingsExceptionTip" xml:space="preserve">
|
||||||
<value>Exception. Do not use proxy server for addresses beginning with,Use semicolon (;)</value>
|
<value>استثنا: از سرور پروکسی برای آدرس هایی که با شروع می شوند استفاده نکنید، از نقطه ویرگول (;) استفاده کنید.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsHttpPort" xml:space="preserve">
|
<data name="TbSettingsHttpPort" xml:space="preserve">
|
||||||
<value>پورت Http</value>
|
<value>پورت Http</value>
|
||||||
@@ -725,7 +725,7 @@
|
|||||||
<value>هنگام بهروزرسانی هسته، فایلهای Geo را نادیده بگیرید</value>
|
<value>هنگام بهروزرسانی هسته، فایلهای Geo را نادیده بگیرید</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
|
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
|
||||||
<value>Keep older when deduplication</value>
|
<value>هنگام کپی برداری، نگه داری قدیمی تر ها</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsLogEnabled" xml:space="preserve">
|
<data name="TbSettingsLogEnabled" xml:space="preserve">
|
||||||
<value>ثبت گزارش های محلی</value>
|
<value>ثبت گزارش های محلی</value>
|
||||||
@@ -734,25 +734,25 @@
|
|||||||
<value>سطح ثبت رویداد</value>
|
<value>سطح ثبت رویداد</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsMuxEnabled" xml:space="preserve">
|
<data name="TbSettingsMuxEnabled" xml:space="preserve">
|
||||||
<value>Turn on Mux Multiplexing</value>
|
<value>فعال کردن Mux Multiplexing</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsN" xml:space="preserve">
|
<data name="TbSettingsN" xml:space="preserve">
|
||||||
<value>تنظیمات v2rayN</value>
|
<value>تنظیمات v2rayN</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsPass" xml:space="preserve">
|
<data name="TbSettingsPass" xml:space="preserve">
|
||||||
<value>Auth pass</value>
|
<value>مجوز احراز هویت</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsRemoteDNS" xml:space="preserve">
|
<data name="TbSettingsRemoteDNS" xml:space="preserve">
|
||||||
<value>سفارشی DNS (multiple, separated by commas (,))</value>
|
<value>سفارشی DNS (multiple, separated by commas (,))</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSetUWP" xml:space="preserve">
|
<data name="TbSettingsSetUWP" xml:space="preserve">
|
||||||
<value>Set Win10 UWP Loopback</value>
|
<value>تنظیم کردن Win10 UWP Loopback</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSniffingEnabled" xml:space="preserve">
|
<data name="TbSettingsSniffingEnabled" xml:space="preserve">
|
||||||
<value>Turn on Sniffing</value>
|
<value>فعال کردن Sniffing</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSocksPort" xml:space="preserve">
|
<data name="TbSettingsSocksPort" xml:space="preserve">
|
||||||
<value>ساکس Port</value>
|
<value>پورت Mixed</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsStartBoot" xml:space="preserve">
|
<data name="TbSettingsStartBoot" xml:space="preserve">
|
||||||
<value>درهنگام راه ائدازی شروع شود</value>
|
<value>درهنگام راه ائدازی شروع شود</value>
|
||||||
@@ -761,22 +761,22 @@
|
|||||||
<value>فعال کردن آمار (نیاز به راه اندازی مجدد)</value>
|
<value>فعال کردن آمار (نیاز به راه اندازی مجدد)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSubConvert" xml:space="preserve">
|
<data name="TbSettingsSubConvert" xml:space="preserve">
|
||||||
<value>Subscription conversion Url</value>
|
<value>آدرس اینترنتی تبدیل اشتراک</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSystemproxy" xml:space="preserve">
|
<data name="TbSettingsSystemproxy" xml:space="preserve">
|
||||||
<value>تنظیمات پراکسی سیستم</value>
|
<value>تنظیمات پراکسی سیستم</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsTLS13" xml:space="preserve">
|
<data name="TbSettingsTLS13" xml:space="preserve">
|
||||||
<value>Enable Security Protocol TLS v1.3 (subscription/update)</value>
|
<value>فعال کردن پروتکل امنیتی TLS نسخه 1.3 (اشتراک/بهروزرسانی)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsTrayMenuServersLimit" xml:space="preserve">
|
<data name="TbSettingsTrayMenuServersLimit" xml:space="preserve">
|
||||||
<value>Tray right-click menu servers display limit</value>
|
<value>محدودیت نمایش سرورهای منوی سینی کلیک راست</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsUdpEnabled" xml:space="preserve">
|
<data name="TbSettingsUdpEnabled" xml:space="preserve">
|
||||||
<value>UDP را فعال شود</value>
|
<value>فعال سازی UDP</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsUser" xml:space="preserve">
|
<data name="TbSettingsUser" xml:space="preserve">
|
||||||
<value>Auth user</value>
|
<value>تایید کاربر</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbClearSystemProxy" xml:space="preserve">
|
<data name="TbClearSystemProxy" xml:space="preserve">
|
||||||
<value>پاک کردن پروکسی سیستم</value>
|
<value>پاک کردن پروکسی سیستم</value>
|
||||||
@@ -821,16 +821,16 @@
|
|||||||
<value>پایین (D)</value>
|
<value>پایین (D)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuMoveTop" xml:space="preserve">
|
<data name="menuMoveTop" xml:space="preserve">
|
||||||
<value>Move to top (T)</value>
|
<value>حرکت به بالا (T)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuMoveUp" xml:space="preserve">
|
<data name="menuMoveUp" xml:space="preserve">
|
||||||
<value>Up (U)</value>
|
<value>بالا (U)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgFilterTitle" xml:space="preserve">
|
<data name="MsgFilterTitle" xml:space="preserve">
|
||||||
<value>Filter, support regular</value>
|
<value>فیلتر، پشتیبانی منظم</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuWebsiteItem" xml:space="preserve">
|
<data name="menuWebsiteItem" xml:space="preserve">
|
||||||
<value>{0} Website</value>
|
<value>{0} وب سایت</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRoutingAdvanced" xml:space="preserve">
|
<data name="menuRoutingAdvanced" xml:space="preserve">
|
||||||
<value>عملکرد پیشرفته</value>
|
<value>عملکرد پیشرفته</value>
|
||||||
@@ -845,13 +845,7 @@
|
|||||||
<value>حذف انتخاب شده</value>
|
<value>حذف انتخاب شده</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
||||||
<value>Set as active rule</value>
|
<value>تنظیم کردن به عنوان قانون فعال</value>
|
||||||
</data>
|
|
||||||
<data name="menuRoutingBasic" xml:space="preserve">
|
|
||||||
<value>عملکرد پایه</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuRoutingBasicImportRules" xml:space="preserve">
|
|
||||||
<value>واردات قوانین اساسی</value>
|
|
||||||
</data>
|
</data>
|
||||||
<data name="TbdomainMatcher" xml:space="preserve">
|
<data name="TbdomainMatcher" xml:space="preserve">
|
||||||
<value>تطبیق دامنه</value>
|
<value>تطبیق دامنه</value>
|
||||||
@@ -863,19 +857,19 @@
|
|||||||
<value>فعال کردن عملکرد پیشرفته</value>
|
<value>فعال کردن عملکرد پیشرفته</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRoutingTabBlock" xml:space="preserve">
|
<data name="TbRoutingTabBlock" xml:space="preserve">
|
||||||
<value>3.Block Domain or IP</value>
|
<value>3. مسدود کردن دامنه یا آیپی</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRoutingTabDirect" xml:space="preserve">
|
<data name="TbRoutingTabDirect" xml:space="preserve">
|
||||||
<value>2.Direct Domain or IP</value>
|
<value>2. دایرکت کردن دامنه یا IP</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRoutingTabProxy" xml:space="preserve">
|
<data name="TbRoutingTabProxy" xml:space="preserve">
|
||||||
<value>1.Proxy Domain or IP</value>
|
<value>1. پروکسی کردن دامنه یا IP</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRoutingTabRuleList" xml:space="preserve">
|
<data name="TbRoutingTabRuleList" xml:space="preserve">
|
||||||
<value>لیست مجموعه قوانین از پیش تعریف شده</value>
|
<value>لیست مجموعه قوانین از پیش تعریف شده</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRoutingTips" xml:space="preserve">
|
<data name="TbRoutingTips" xml:space="preserve">
|
||||||
<value>*Set the rules, separated by commas (,); The comma in the regular is replaced by <COMMA></value>
|
<value>*قوانین را تنظیم کنید که با کاما از هم جدا شده اند (,); کاما در حالت عادی با <COMMA></value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuImportRulesFromClipboard" xml:space="preserve">
|
<data name="menuImportRulesFromClipboard" xml:space="preserve">
|
||||||
<value>وارد کردن قوانین از کلیپ بورد</value>
|
<value>وارد کردن قوانین از کلیپ بورد</value>
|
||||||
@@ -884,7 +878,7 @@
|
|||||||
<value>وارد کردن قوانین از فایل</value>
|
<value>وارد کردن قوانین از فایل</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuImportRulesFromUrl" xml:space="preserve">
|
<data name="menuImportRulesFromUrl" xml:space="preserve">
|
||||||
<value>وارد کردن قوانین از Sub Url</value>
|
<value>وارد کردن قوانین از آدرس اینترنتی Sub</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRoutingRuleSetting" xml:space="preserve">
|
<data name="menuRoutingRuleSetting" xml:space="preserve">
|
||||||
<value>تنظیم قانون</value>
|
<value>تنظیم قانون</value>
|
||||||
@@ -908,7 +902,7 @@
|
|||||||
<value>دامنه و آی پی در هنگام ذخیره به طور خودکار مرتب می شوند</value>
|
<value>دامنه و آی پی در هنگام ذخیره به طور خودکار مرتب می شوند</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRuleobjectDoc" xml:space="preserve">
|
<data name="TbRuleobjectDoc" xml:space="preserve">
|
||||||
<value>Ruleobject Doc</value>
|
<value>مستندات شی قانون</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbDnsObjectDoc" xml:space="preserve">
|
<data name="TbDnsObjectDoc" xml:space="preserve">
|
||||||
<value>پشتیبانی از DnsObject</value>
|
<value>پشتیبانی از DnsObject</value>
|
||||||
@@ -926,16 +920,16 @@
|
|||||||
<value>فقط مسیر</value>
|
<value>فقط مسیر</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsNotProxyLocalAddress" xml:space="preserve">
|
<data name="TbSettingsNotProxyLocalAddress" xml:space="preserve">
|
||||||
<value>يەرلىك (Intranet) ئادرېسلارغا ۋاكالەتچى مۇلازىمېتىر ئىشلەتمەڭ</value>
|
<value>از سرورهای پروکسی برای آدرس های محلی (اینترانت) استفاده نکنید</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuMixedTestServer" xml:space="preserve">
|
<data name="menuMixedTestServer" xml:space="preserve">
|
||||||
<value>One-click test Latency and speed (Ctrl+E)</value>
|
<value>تاخیر و سرعت تست با یک کلیک (Ctrl+E)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvTestDelay" xml:space="preserve">
|
<data name="LvTestDelay" xml:space="preserve">
|
||||||
<value>تاخیر (میلیثانیه)</value>
|
<value>تاخیر (میلیثانیه)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvTestSpeed" xml:space="preserve">
|
<data name="LvTestSpeed" xml:space="preserve">
|
||||||
<value>Speed(M/s)</value>
|
<value>سرعت (M/s)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FailedToRunCore" xml:space="preserve">
|
<data name="FailedToRunCore" xml:space="preserve">
|
||||||
<value>Core اجرا نشد، لطفاً گزارش را ببینید</value>
|
<value>Core اجرا نشد، لطفاً گزارش را ببینید</value>
|
||||||
@@ -950,7 +944,7 @@
|
|||||||
<value>پیکربندی قدیمی guiNConfig را وارد شود</value>
|
<value>پیکربندی قدیمی guiNConfig را وارد شود</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbEnableTunAs" xml:space="preserve">
|
<data name="TbEnableTunAs" xml:space="preserve">
|
||||||
<value>Tun را فعال شود</value>
|
<value>فعال سازی Tun</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsNewPort4LAN" xml:space="preserve">
|
<data name="TbSettingsNewPort4LAN" xml:space="preserve">
|
||||||
<value>پورت جدید برای LAN</value>
|
<value>پورت جدید برای LAN</value>
|
||||||
@@ -962,10 +956,10 @@
|
|||||||
<value>User-Agent</value>
|
<value>User-Agent</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsDefUserAgentTips" xml:space="preserve">
|
<data name="TbSettingsDefUserAgentTips" xml:space="preserve">
|
||||||
<value>This parameter is valid only for tcp/http and ws</value>
|
<value>این پارامتر فقط برای tcp/http و ws معتبر است</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableHWA" xml:space="preserve">
|
<data name="TbSettingsEnableHWA" xml:space="preserve">
|
||||||
<value>فعالسازی شتابدهنده سختافزاری (نیاز به راهاندازی مجدد)</value>
|
<value>فعال سازی شتاب دهنده سختافزاری (نیاز به راهاندازی مجدد)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve">
|
<data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve">
|
||||||
<value>فعال کردن کش فایل مجموعه قوانین برای sing-box</value>
|
<value>فعال کردن کش فایل مجموعه قوانین برای sing-box</value>
|
||||||
@@ -974,7 +968,7 @@
|
|||||||
<value>مرتب سازی</value>
|
<value>مرتب سازی</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSortingDefault" xml:space="preserve">
|
<data name="TbSortingDefault" xml:space="preserve">
|
||||||
<value>Default</value>
|
<value>پیش فرض</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSortingDelay" xml:space="preserve">
|
<data name="TbSortingDelay" xml:space="preserve">
|
||||||
<value>تاخیر</value>
|
<value>تاخیر</value>
|
||||||
@@ -1013,10 +1007,10 @@
|
|||||||
<value>نوع قانون</value>
|
<value>نوع قانون</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuModeDirect" xml:space="preserve">
|
<data name="menuModeDirect" xml:space="preserve">
|
||||||
<value>Direct</value>
|
<value>مستقیم</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuModeGlobal" xml:space="preserve">
|
<data name="menuModeGlobal" xml:space="preserve">
|
||||||
<value>Global</value>
|
<value>جهانی</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuModeNothing" xml:space="preserve">
|
<data name="menuModeNothing" xml:space="preserve">
|
||||||
<value>تغییر نده</value>
|
<value>تغییر نده</value>
|
||||||
@@ -1025,12 +1019,387 @@
|
|||||||
<value>قانون</value>
|
<value>قانون</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuProxiesDelaytest" xml:space="preserve">
|
<data name="menuProxiesDelaytest" xml:space="preserve">
|
||||||
<value>Latency Test</value>
|
<value>تست تأخیر</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuProxiesDelaytestPart" xml:space="preserve">
|
<data name="menuProxiesDelaytestPart" xml:space="preserve">
|
||||||
<value>Part Node Latency Test</value>
|
<value>تست تاخیر قسمت گره (نقطه اتصال)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuProxiesSelectActivity" xml:space="preserve">
|
<data name="menuProxiesSelectActivity" xml:space="preserve">
|
||||||
<value>Select active node (Enter)</value>
|
<value>انتخاب گره فعال (Enter)</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
<data name="menuRemoteBackup" xml:space="preserve">
|
||||||
|
<value>پشتیبان گیری از راه دور (WebDAV)</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuRemoteRestore" xml:space="preserve">
|
||||||
|
<value>بازیابی از راه دور (WebDAV)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsDomainStrategy4Out" xml:space="preserve">
|
||||||
|
<value>استراتژی دامنه پیش فرض برای خروجی</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuSetDefaultMultipleServer" xml:space="preserve">
|
||||||
|
<value>کمترین تأخیر چند سروره</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsMainGirdOrientation" xml:space="preserve">
|
||||||
|
<value>جهت چیدمان اصلی (نیاز به راه اندازی مجدد)</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuSetDefaultLoadBalanceServer" xml:space="preserve">
|
||||||
|
<value>تعادل بار چند سروره</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsDomainDNSAddress" xml:space="preserve">
|
||||||
|
<value>آدرس DNS خروجی</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuProfileAutofitColumnWidth" xml:space="preserve">
|
||||||
|
<value>تنظیم خودکار عرض ستون</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuExport2ShareUrlBase64" xml:space="preserve">
|
||||||
|
<value>صادر کردن پیوندهای اشتراک گذاری کدگذاری شده با Base64 به کلیپ بورد</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuExport2ClientConfigClipboard" xml:space="preserve">
|
||||||
|
<value>صادر کردن سرور انتخاب شده برای پیکربندی کامل به کلیپ بورد</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuShowOrHideMainWindow" xml:space="preserve">
|
||||||
|
<value>نمایش یا پنهان کردن پنجره اصلی</value>
|
||||||
|
</data>
|
||||||
|
<data name="UpdateStandalonePackageTip" xml:space="preserve">
|
||||||
|
<value>شما در حال حاضر در حال اجرای یک بسته مستقل هستید، لطفاً فایل SelfContained.7z را به صورت دستی دانلود کنید تا آن را از حالت فشرده خارج کرده و بازنویسی کنید!</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbPreSocksPort4Sub" xml:space="preserve">
|
||||||
|
<value>پیکربندی سفارشی ساکس پورت</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuBackupAndRestore" xml:space="preserve">
|
||||||
|
<value>پشتیبان گیری و بازیابی</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuLocalBackup" xml:space="preserve">
|
||||||
|
<value>پشتیبان گیری به محلی</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuLocalRestore" xml:space="preserve">
|
||||||
|
<value>بازیابی از محلی</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuLocalBackupAndRestore" xml:space="preserve">
|
||||||
|
<value>محلی</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuRemoteBackupAndRestore" xml:space="preserve">
|
||||||
|
<value>از راه دور (WebDAV)</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvWebDavUrl" xml:space="preserve">
|
||||||
|
<value>آدرس اینترنتی WebDav</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvWebDavUserName" xml:space="preserve">
|
||||||
|
<value>نام کاربری WebDav</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvWebDavPassword" xml:space="preserve">
|
||||||
|
<value>پسورد WebDav</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvWebDavCheck" xml:space="preserve">
|
||||||
|
<value>چک کردن WebDav</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvWebDavDirName" xml:space="preserve">
|
||||||
|
<value>نام پوشه راه دور (اختیاری)</value>
|
||||||
|
</data>
|
||||||
|
<data name="LocalRestoreInvalidZipTips" xml:space="preserve">
|
||||||
|
<value>فایل پشتیبان نامعتبر است</value>
|
||||||
|
</data>
|
||||||
|
<data name="ConnectionsHostFilterTitle" xml:space="preserve">
|
||||||
|
<value>Host filter</value>
|
||||||
|
</data>
|
||||||
|
<data name="TipActiveServer" xml:space="preserve">
|
||||||
|
<value>فعال سازی</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuStorageUI" xml:space="preserve">
|
||||||
|
<value>ذخیره طرح رابط</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsGeoFilesSource" xml:space="preserve">
|
||||||
|
<value>منبع فایل های جغرافیایی (اختیاری)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsSrsFilesSource" xml:space="preserve">
|
||||||
|
<value>منبع فایل های مجموعه قوانین sing-box (اختیاری)</value>
|
||||||
|
</data>
|
||||||
|
<data name="UpgradeAppNotExistTip" xml:space="preserve">
|
||||||
|
<value>برنامه ارتقا وجود ندارد</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsRoutingRulesSource" xml:space="preserve">
|
||||||
|
<value>منبع قوانین مسیریابی (اختیاری)</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuRegionalPresets" xml:space="preserve">
|
||||||
|
<value>تنظیمات از پیش تعیین شده منطقه ای</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuRegionalPresetsDefault" xml:space="preserve">
|
||||||
|
<value>پیش فرض</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuRegionalPresetsRussia" xml:space="preserve">
|
||||||
|
<value>روسیه</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuRegionalPresetsIran" xml:space="preserve">
|
||||||
|
<value>ایران</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsChinaUserTip" xml:space="preserve">
|
||||||
|
<value>کاربران در منطقه چین می توانند این مورد را نادیده بگیرند</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuAddServerViaImage" xml:space="preserve">
|
||||||
|
<value>اسکن کردن QRcode موجود در تصویر</value>
|
||||||
|
</data>
|
||||||
|
<data name="InvalidUrlTip" xml:space="preserve">
|
||||||
|
<value>آدرس نامعتبر (آدرس اینترنتی)</value>
|
||||||
|
</data>
|
||||||
|
<data name="InsecureUrlProtocol" xml:space="preserve">
|
||||||
|
<value>لطفاً از آدرس اشتراک پروتکل HTTP ناامن استفاده نکنید</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
||||||
|
<value>فونت را روی سیستم نصب کنید و تنظیمات را مجددا راه اندازی کنید</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuExitTips" xml:space="preserve">
|
||||||
|
<value>آیا مطمئن هستید که خارج می شوید؟</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvMemo" xml:space="preserve">
|
||||||
|
<value>یادداشت ملاحظات</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLogEnabledToFile" xml:space="preserve">
|
||||||
|
<value>فعال کردن ورود به فایل</value>
|
||||||
|
</data>
|
||||||
|
<data name="MsgSkipSubscriptionUpdate" xml:space="preserve">
|
||||||
|
<value>به روز رسانی ها فعال نیستند، از این اشتراک رد شوید</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuRebootAsAdmin" xml:space="preserve">
|
||||||
|
<value>به عنوان مدیر راه اندازی مجدد</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvMoreUrl" xml:space="preserve">
|
||||||
|
<value>نشانیهای وب بیشتر که با کاما از هم جدا شدهاند. تبدیل اشتراک نامعتبر خواهد بود</value>
|
||||||
|
</data>
|
||||||
|
<data name="SpeedDisplayText" xml:space="preserve">
|
||||||
|
<value>{0} : {1}/s↑ | {2}/s↓</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvAutoUpdateInterval" xml:space="preserve">
|
||||||
|
<value>فاصله به روز رسانی خودکار (دقیقه)</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvConvertTarget" xml:space="preserve">
|
||||||
|
<value>تبدیل نوع هدف</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvConvertTargetTip" xml:space="preserve">
|
||||||
|
<value>اگر نیازی به تبدیل نیست، لطفاً خالی بگذارید</value>
|
||||||
|
</data>
|
||||||
|
<data name="TipDisplayLog" xml:space="preserve">
|
||||||
|
<value>لطفاً در صورت قطع غیرعادی آن را خاموش کنید</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuDNSSetting" xml:space="preserve">
|
||||||
|
<value>تنظیمات DNS</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbDnsSingboxObjectDoc" xml:space="preserve">
|
||||||
|
<value>لطفا ساختار DNS را پر کنید، برای مشاهده سند کلیک کنید</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingDnsImportDefConfig" xml:space="preserve">
|
||||||
|
<value>برای وارد کردن تنظیمات پیشفرض DNS کلیک کنید</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbdomainStrategy4Singbox" xml:space="preserve">
|
||||||
|
<value>استراتژی دامنه sing-box</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsMux4SboxProtocol" xml:space="preserve">
|
||||||
|
<value>پروتکل sing-box Mux</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbRoutingRuleProcess" xml:space="preserve">
|
||||||
|
<value>نام کامل فرانید (حالت Tun)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbRoutingRuleIP" xml:space="preserve">
|
||||||
|
<value>IP or IP CIDR</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbRoutingRuleDomain" xml:space="preserve">
|
||||||
|
<value>دامنه</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsCoreDnsSingbox" xml:space="preserve">
|
||||||
|
<value>تنظیمات DNS sing-box</value>
|
||||||
|
</data>
|
||||||
|
<data name="SpeedtestingWait" xml:space="preserve">
|
||||||
|
<value>در انتظار آزمایش (برای پایان دادن به ESC فشار دهید)...</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSpiderX" xml:space="preserve">
|
||||||
|
<value>SpiderX</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbShortId" xml:space="preserve">
|
||||||
|
<value>ShortId</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuMoveToGroup" xml:space="preserve">
|
||||||
|
<value>انتقال به گروه</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsEnableDragDropSort" xml:space="preserve">
|
||||||
|
<value>فعال کردن مرتب سازی با کشیدن سرور (نیاز به راه اندازی مجدد)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbAutoRefresh" xml:space="preserve">
|
||||||
|
<value>بازخوانی خودکار</value>
|
||||||
|
</data>
|
||||||
|
<data name="SpeedtestingSkip" xml:space="preserve">
|
||||||
|
<value>رد شدن از آزمون</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuEditServer" xml:space="preserve">
|
||||||
|
<value>ویرایش سرور (Ctrl+D)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsDoubleClick2Activate" xml:space="preserve">
|
||||||
|
<value>روی server make active دوبار کلیک کنید</value>
|
||||||
|
</data>
|
||||||
|
<data name="SpeedtestingCompleted" xml:space="preserve">
|
||||||
|
<value>تست تکمیل شد</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsDefFingerprint" xml:space="preserve">
|
||||||
|
<value>اثر انگشت tls پیش فرض</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsCurrentFontFamily" xml:space="preserve">
|
||||||
|
<value>FontFamily (نیاز به راه اندازی مجدد)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsCurrentFontFamilyTip" xml:space="preserve">
|
||||||
|
<value>فایل TTF/TTC فونت را در دایرکتوری guiFonts کپی کنید، تنظیمات را مجددا راه اندازی کنید</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsSocksPortTip" xml:space="preserve">
|
||||||
|
<value>پورت Pac = +3; پورت Xray API = +4; پورت mihomo API = +5;</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsStartBootTip" xml:space="preserve">
|
||||||
|
<value>این را با امتیازات ادمین تنظیم کنید، پس از راه اندازی، امتیازات مدیر را دریافت کنید</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsFontSize" xml:space="preserve">
|
||||||
|
<value>اندازه فونت</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsSpeedTestTimeout" xml:space="preserve">
|
||||||
|
<value>یمقدار تاخیر تست سرعت منفرد</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsSpeedTestUrl" xml:space="preserve">
|
||||||
|
<value>/آدرس اینترنتی SpeedTest</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuMoveTo" xml:space="preserve">
|
||||||
|
<value>بالا و پایین حرکت کنید</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbPublicKey" xml:space="preserve">
|
||||||
|
<value>PublicKey</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuAddHysteria2Server" xml:space="preserve">
|
||||||
|
<value>Add [Hysteria2] server</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsHysteriaBandwidth" xml:space="preserve">
|
||||||
|
<value>حداکتر پهنای باند هیستریا (آپلود/دانلود)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
|
||||||
|
<value>دنبال کردن تم سیستم</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuAddTuicServer" xml:space="preserve">
|
||||||
|
<value>افزودن سرور [TUIC]</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsEnableUpdateSubOnlyRemarksExist" xml:space="preserve">
|
||||||
|
<value>اشتراک در حال بهروزرسانی، فقط مشخص کنید که ملاحظاتی وجود دارد</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuProxiesReload" xml:space="preserve">
|
||||||
|
<value>تازه سازی پروکسی ها</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingNetwork" xml:space="preserve">
|
||||||
|
<value>شبکه</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingType" xml:space="preserve">
|
||||||
|
<value>نوع</value>
|
||||||
|
</data>
|
||||||
|
<data name="TransportRequestHostTip5" xml:space="preserve">
|
||||||
|
<value>*grpc Authority</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuAddHttpServer" xml:space="preserve">
|
||||||
|
<value>افزودن سرور [HTTP]</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsSpeedPingTestUrl" xml:space="preserve">
|
||||||
|
<value>آدرس اینترنتی تست پینگ سرعت</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsEnableFragmentTips" xml:space="preserve">
|
||||||
|
<value>از Xray استفاده کنید و حالت non-Tun را فعال کنید، که با پراکسی قبلی گروه در تضاد است</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvCustomRulesetPath4Singbox" xml:space="preserve">
|
||||||
|
<value>سفارش سازی مجموعه قوانین از sing box</value>
|
||||||
|
</data>
|
||||||
|
<data name="NeedRebootTips" xml:space="preserve">
|
||||||
|
<value>عملکرد موفقیت آمیز بود، روی منوی تنظیمات کلیک کنید تا برنامه راه اندازی مجدد شود.</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuOpenTheFileLocation" xml:space="preserve">
|
||||||
|
<value>باز کردن محل ذخیره سازی</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingChain" xml:space="preserve">
|
||||||
|
<value>Chain</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingHost" xml:space="preserve">
|
||||||
|
<value>Host</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsUseSystemHosts" xml:space="preserve">
|
||||||
|
<value>استفاده کردن از System Hosts</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
||||||
|
<value>فعال کردن فرگمنت</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbAutoScrollToEnd" xml:space="preserve">
|
||||||
|
<value>خودکار ScrollToEnd</value>
|
||||||
|
</data>
|
||||||
|
<data name="SpeedtestingStop" xml:space="preserve">
|
||||||
|
<value>پایان تست...</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvNextProfile" xml:space="preserve">
|
||||||
|
<value>Next proxy remarks</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbPath7" xml:space="preserve">
|
||||||
|
<value>پسورد obfs</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbHeaderType8" xml:space="preserve">
|
||||||
|
<value>کنترل تراکم</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvPrevProfile" xml:space="preserve">
|
||||||
|
<value>Previous proxy remarks</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbLocalAddress" xml:space="preserve">
|
||||||
|
<value>آدرس (IP, IPv6)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbReserved" xml:space="preserve">
|
||||||
|
<value>Reserved(2,3,4)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbPrivateKey" xml:space="preserve">
|
||||||
|
<value>کلید خصوصی</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuAddWireguardServer" xml:space="preserve">
|
||||||
|
<value>افزودن سرور [WireGuard]</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
||||||
|
<value>فعال سازی آدرس IPv6</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsEnableExInbound" xml:space="preserve">
|
||||||
|
<value>فعال سازی additional Inbound</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvPrevProfileTip" xml:space="preserve">
|
||||||
|
<value>لطفاً مطمئن شوید که ملاحظات وجود دارد و منحصر به فرد است</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbRuleMatchingTips" xml:space="preserve">
|
||||||
|
<value>(Domain or IP or ProcName) and Port and Protocol and InboundTag => OutboundTag</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
|
||||||
|
<value>رمز عبور sudo سیستم</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||||
|
<value>رمز عبور رمزگذاری شده و فقط در فایل های محلی ذخیره می شود.</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||||
|
<value>لطفاً ابتدا رمز عبور sudo را در تنظیمات حالت Tun تنظیم کنید</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
||||||
|
<value>لطفا این برنامه را با sudo اجرا نکنید</value>
|
||||||
|
</data>
|
||||||
|
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
||||||
|
<value>*حالت xhttp</value>
|
||||||
|
</data>
|
||||||
|
<data name="TransportExtraTip" xml:space="preserve">
|
||||||
|
<value>جیسون خام XHTTP Extra, فرمت: { XHTTPObject }</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||||
|
<value>هنگام بستن پنجره در سینی پنهان شوید</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
|
||||||
|
<value>تعداد در هر زمان برای دسته خودکار در طول تست سرعت (حداکثر 1000)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
||||||
|
<value>استثنا:از سرور پروکسی برای آدرس ها، با کاما (،) استفاده نکنید</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsDestOverride" xml:space="preserve">
|
||||||
|
<value>نوع Sniffing</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsSecondLocalPortEnabled" xml:space="preserve">
|
||||||
|
<value>فعال کردن دومین پورت ترکیبی</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbRoutingInboundTagTips" xml:space="preserve">
|
||||||
|
<value>socks:پورت محلی، socks2: پورت دوم محلی، socks3: پورت LAN</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
|
|||||||
1405
v2rayN/ServiceLib/Resx/ResUI.hu.resx
Normal file
1405
v2rayN/ServiceLib/Resx/ResUI.hu.resx
Normal file
File diff suppressed because it is too large
Load Diff
@@ -302,7 +302,7 @@
|
|||||||
<value>Scan import the shared link successfully</value>
|
<value>Scan import the shared link successfully</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TestMeOutput" xml:space="preserve">
|
<data name="TestMeOutput" xml:space="preserve">
|
||||||
<value>The ping of current service: {0} ms</value>
|
<value>The delay : {0} ms, {1}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="OperationSuccess" xml:space="preserve">
|
<data name="OperationSuccess" xml:space="preserve">
|
||||||
<value>Operation success</value>
|
<value>Operation success</value>
|
||||||
@@ -344,7 +344,7 @@
|
|||||||
<value>Please fill in the correct custom DNS</value>
|
<value>Please fill in the correct custom DNS</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportPathTip1" xml:space="preserve">
|
<data name="TransportPathTip1" xml:space="preserve">
|
||||||
<value>*ws/httpupgrade/splithttp path</value>
|
<value>*ws/httpupgrade/xhttp path</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportPathTip2" xml:space="preserve">
|
<data name="TransportPathTip2" xml:space="preserve">
|
||||||
<value>*h2 path</value>
|
<value>*h2 path</value>
|
||||||
@@ -359,7 +359,7 @@
|
|||||||
<value>*http host Separated by commas (,)</value>
|
<value>*http host Separated by commas (,)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportRequestHostTip2" xml:space="preserve">
|
<data name="TransportRequestHostTip2" xml:space="preserve">
|
||||||
<value>*ws/httpupgrade/splithttp host</value>
|
<value>*ws/httpupgrade/xhttp host</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportRequestHostTip3" xml:space="preserve">
|
<data name="TransportRequestHostTip3" xml:space="preserve">
|
||||||
<value>*h2 host Separated by commas (,)</value>
|
<value>*h2 host Separated by commas (,)</value>
|
||||||
@@ -755,7 +755,7 @@
|
|||||||
<value>Turn on Sniffing</value>
|
<value>Turn on Sniffing</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSocksPort" xml:space="preserve">
|
<data name="TbSettingsSocksPort" xml:space="preserve">
|
||||||
<value>SOCKS Port</value>
|
<value>Mixed Port</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsStartBoot" xml:space="preserve">
|
<data name="TbSettingsStartBoot" xml:space="preserve">
|
||||||
<value>Start on boot</value>
|
<value>Start on boot</value>
|
||||||
@@ -850,12 +850,6 @@
|
|||||||
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
||||||
<value>Set as active rule(Enter)</value>
|
<value>Set as active rule(Enter)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRoutingBasic" xml:space="preserve">
|
|
||||||
<value>Basic Function</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuRoutingBasicImportRules" xml:space="preserve">
|
|
||||||
<value>Import Basic Rules</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbdomainMatcher" xml:space="preserve">
|
<data name="TbdomainMatcher" xml:space="preserve">
|
||||||
<value>Domain Matcher</value>
|
<value>Domain Matcher</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -998,7 +992,7 @@
|
|||||||
<value>Copy the font TTF/TTC file to the directory guiFonts, restart the settings</value>
|
<value>Copy the font TTF/TTC file to the directory guiFonts, restart the settings</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSocksPortTip" xml:space="preserve">
|
<data name="TbSettingsSocksPortTip" xml:space="preserve">
|
||||||
<value>http port = +1; Pac port = +4; *ray API port = +5; mihomo API port = +6;</value>
|
<value>Pac port = +3; Xray API port = +4; mihomo API port = +5;</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsStartBootTip" xml:space="preserve">
|
<data name="TbSettingsStartBootTip" xml:space="preserve">
|
||||||
<value>Set this with admin privileges, get admin privileges after startup</value>
|
<value>Set this with admin privileges, get admin privileges after startup</value>
|
||||||
@@ -1348,6 +1342,9 @@
|
|||||||
<data name="menuRegionalPresetsRussia" xml:space="preserve">
|
<data name="menuRegionalPresetsRussia" xml:space="preserve">
|
||||||
<value>Russia</value>
|
<value>Russia</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="menuRegionalPresetsIran" xml:space="preserve">
|
||||||
|
<value>Iran</value>
|
||||||
|
</data>
|
||||||
<data name="TbSettingsChinaUserTip" xml:space="preserve">
|
<data name="TbSettingsChinaUserTip" xml:space="preserve">
|
||||||
<value>Users in China region can ignore this item</value>
|
<value>Users in China region can ignore this item</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1360,4 +1357,49 @@
|
|||||||
<data name="InsecureUrlProtocol" xml:space="preserve">
|
<data name="InsecureUrlProtocol" xml:space="preserve">
|
||||||
<value>Please do not use the insecure HTTP protocol subscription address</value>
|
<value>Please do not use the insecure HTTP protocol subscription address</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
||||||
|
<value>Install the font to the system and restart the settings</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuExitTips" xml:space="preserve">
|
||||||
|
<value>Are you sure to exit?</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvMemo" xml:space="preserve">
|
||||||
|
<value>Remarks Memo</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
|
||||||
|
<value>System sudo password</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||||
|
<value>The password is encrypted and stored only in local files.</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||||
|
<value>Please set the sudo password in Tun mode settings first</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
||||||
|
<value>Please do not run this app with sudo</value>
|
||||||
|
</data>
|
||||||
|
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
||||||
|
<value>*xhttp mode</value>
|
||||||
|
</data>
|
||||||
|
<data name="TransportExtraTip" xml:space="preserve">
|
||||||
|
<value>XHTTP Extra raw JSON, format: { XHTTPObject }</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||||
|
<value>Hide to tray when closing the window</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
|
||||||
|
<value>Number per time for auto batch during speedtest(max 1000)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
||||||
|
<value>Exception. Do not use proxy server for addresses,with a comma (,)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsDestOverride" xml:space="preserve">
|
||||||
|
<value>Sniffing type</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsSecondLocalPortEnabled" xml:space="preserve">
|
||||||
|
<value>Enable second mixed port</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbRoutingInboundTagTips" xml:space="preserve">
|
||||||
|
<value>socks: local port, socks2: second local port, socks3: LAN port</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -302,7 +302,7 @@
|
|||||||
<value>Сканирование URL-адреса импорта успешна.</value>
|
<value>Сканирование URL-адреса импорта успешна.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TestMeOutput" xml:space="preserve">
|
<data name="TestMeOutput" xml:space="preserve">
|
||||||
<value>Задержка текущего сервера: {0} мс</value>
|
<value>Задержка текущего сервера: {0} мс, {1}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="OperationSuccess" xml:space="preserve">
|
<data name="OperationSuccess" xml:space="preserve">
|
||||||
<value>Операция успешна</value>
|
<value>Операция успешна</value>
|
||||||
@@ -761,7 +761,7 @@
|
|||||||
<value>Включить сниффинг</value>
|
<value>Включить сниффинг</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSocksPort" xml:space="preserve">
|
<data name="TbSettingsSocksPort" xml:space="preserve">
|
||||||
<value>Порт Socks</value>
|
<value>Mixed Port</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsStartBoot" xml:space="preserve">
|
<data name="TbSettingsStartBoot" xml:space="preserve">
|
||||||
<value>Автозапуск</value>
|
<value>Автозапуск</value>
|
||||||
@@ -856,12 +856,6 @@
|
|||||||
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
||||||
<value>Установить как активное правило</value>
|
<value>Установить как активное правило</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRoutingBasic" xml:space="preserve">
|
|
||||||
<value>Основные функции</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuRoutingBasicImportRules" xml:space="preserve">
|
|
||||||
<value>Импорт основных правил</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbdomainMatcher" xml:space="preserve">
|
<data name="TbdomainMatcher" xml:space="preserve">
|
||||||
<value>Сопоставитель доменов</value>
|
<value>Сопоставитель доменов</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1045,7 +1039,367 @@
|
|||||||
<data name="menuRegionalPresetsRussia" xml:space="preserve">
|
<data name="menuRegionalPresetsRussia" xml:space="preserve">
|
||||||
<value>Россия</value>
|
<value>Россия</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="menuRegionalPresetsIran" xml:space="preserve">
|
||||||
|
<value>Иран</value>
|
||||||
|
</data>
|
||||||
<data name="TbSettingsChinaUserTip" xml:space="preserve">
|
<data name="TbSettingsChinaUserTip" xml:space="preserve">
|
||||||
<value>Используйте Настройки -> Региональные пресеты вместо изменения этого поля</value>
|
<value>Используйте Настройки -> Региональные пресеты вместо изменения этого поля</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvMemo" xml:space="preserve">
|
||||||
|
<value>Remarks Memo</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsSpeedPingTestUrl" xml:space="preserve">
|
||||||
|
<value>Speed Ping Test URL</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuProxiesDelaytestPart" xml:space="preserve">
|
||||||
|
<value>Part Node Latency Test</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuProxiesReload" xml:space="preserve">
|
||||||
|
<value>Refresh Proxies</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbAutoScrollToEnd" xml:space="preserve">
|
||||||
|
<value>Auto ScrollToEnd</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuProxiesSelectActivity" xml:space="preserve">
|
||||||
|
<value>Select active node (Enter)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbRuleMatchingTips" xml:space="preserve">
|
||||||
|
<value>(Domain or IP or ProcName) and Port and Protocol and InboundTag => OutboundTag</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbPath7" xml:space="preserve">
|
||||||
|
<value>obfs password</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbLocalAddress" xml:space="preserve">
|
||||||
|
<value>Address(Ip,Ipv6)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsDomainStrategy4Out" xml:space="preserve">
|
||||||
|
<value>Default domain strategy for outbound</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuSetDefaultMultipleServer" xml:space="preserve">
|
||||||
|
<value>Multi-Server lowest latency</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsMainGirdOrientation" xml:space="preserve">
|
||||||
|
<value>Main layout orientation(Require restart)</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuSetDefaultLoadBalanceServer" xml:space="preserve">
|
||||||
|
<value>Multi-server load balancing</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuProxiesDelaytest" xml:space="preserve">
|
||||||
|
<value>Latency Test</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbReserved" xml:space="preserve">
|
||||||
|
<value>Reserved(2,3,4)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbPrivateKey" xml:space="preserve">
|
||||||
|
<value>PrivateKey</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuAddWireguardServer" xml:space="preserve">
|
||||||
|
<value>Add [WireGuard] server</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuProfileAutofitColumnWidth" xml:space="preserve">
|
||||||
|
<value>Auto column width adjustment</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuExport2ShareUrlBase64" xml:space="preserve">
|
||||||
|
<value>Export Base64-encoded Share Links to Clipboard</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingDelay" xml:space="preserve">
|
||||||
|
<value>Delay</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsEnableExInbound" xml:space="preserve">
|
||||||
|
<value>Enable additional Inbound</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvPrevProfileTip" xml:space="preserve">
|
||||||
|
<value>Please make sure the remarks exists and is unique</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuExport2ClientConfigClipboard" xml:space="preserve">
|
||||||
|
<value>Export selected server for complete configuration to clipboard</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvNextProfile" xml:space="preserve">
|
||||||
|
<value>Next proxy remarks</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuShowOrHideMainWindow" xml:space="preserve">
|
||||||
|
<value>Show or hide the main window</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvPrevProfile" xml:space="preserve">
|
||||||
|
<value>Previous proxy remarks</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbHeaderType8" xml:space="preserve">
|
||||||
|
<value>Congestion control</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsDomainDNSAddress" xml:space="preserve">
|
||||||
|
<value>Outbound DNS address</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsEnableUpdateSubOnlyRemarksExist" xml:space="preserve">
|
||||||
|
<value>Updating subscription, only determine remarks exists</value>
|
||||||
|
</data>
|
||||||
|
<data name="SpeedtestingStop" xml:space="preserve">
|
||||||
|
<value>Test terminating...</value>
|
||||||
|
</data>
|
||||||
|
<data name="TransportRequestHostTip5" xml:space="preserve">
|
||||||
|
<value>*grpc Authority</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingDefault" xml:space="preserve">
|
||||||
|
<value>Default</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingChain" xml:space="preserve">
|
||||||
|
<value>Chain</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSorting" xml:space="preserve">
|
||||||
|
<value>Sorting</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuOpenTheFileLocation" xml:space="preserve">
|
||||||
|
<value>Open the storage location</value>
|
||||||
|
</data>
|
||||||
|
<data name="NeedRebootTips" xml:space="preserve">
|
||||||
|
<value>Successful operation. Click the settings menu to reboot the app.</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvCustomRulesetPath4Singbox" xml:space="preserve">
|
||||||
|
<value>Custom the rule-set of sing-box</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingDownTraffic" xml:space="preserve">
|
||||||
|
<value>Download Traffic</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingHost" xml:space="preserve">
|
||||||
|
<value>Host</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingName" xml:space="preserve">
|
||||||
|
<value>Name</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingNetwork" xml:space="preserve">
|
||||||
|
<value>Network</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingTime" xml:space="preserve">
|
||||||
|
<value>Time</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingType" xml:space="preserve">
|
||||||
|
<value>Type</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve">
|
||||||
|
<value>Enable cache file for sing-box (ruleset files)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingUpSpeed" xml:space="preserve">
|
||||||
|
<value>Upload Speed</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingUpTraffic" xml:space="preserve">
|
||||||
|
<value>Upload Traffic</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbConnections" xml:space="preserve">
|
||||||
|
<value>Connections</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuConnectionClose" xml:space="preserve">
|
||||||
|
<value>Close Connection</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuConnectionCloseAll" xml:space="preserve">
|
||||||
|
<value>Close All Connection</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbProxies" xml:space="preserve">
|
||||||
|
<value>Proxies</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuRulemode" xml:space="preserve">
|
||||||
|
<value>Rule mode</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuModeDirect" xml:space="preserve">
|
||||||
|
<value>Direct</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuModeGlobal" xml:space="preserve">
|
||||||
|
<value>Global</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuModeNothing" xml:space="preserve">
|
||||||
|
<value>Do not change</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
||||||
|
<value>Enable fragment</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsEnableFragmentTips" xml:space="preserve">
|
||||||
|
<value>Use Xray and enable non-Tun mode, which conflicts with the group previous proxy</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuModeRule" xml:space="preserve">
|
||||||
|
<value>Rule</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuAddHttpServer" xml:space="preserve">
|
||||||
|
<value>Add [HTTP] server</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuAddTuicServer" xml:space="preserve">
|
||||||
|
<value>Add [TUIC] server</value>
|
||||||
|
</data>
|
||||||
|
<data name="UpdateStandalonePackageTip" xml:space="preserve">
|
||||||
|
<value>You are currently running a standalone package, please manually download the SelfContained.7z file to unzip and overwrite it!</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
||||||
|
<value>Enable IPv6 Address</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbPreSocksPort4Sub" xml:space="preserve">
|
||||||
|
<value>Custom config socks port</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvWebDavCheck" xml:space="preserve">
|
||||||
|
<value>WebDav Check</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbRoutingRuleDomain" xml:space="preserve">
|
||||||
|
<value>Domain</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbRoutingRuleIP" xml:space="preserve">
|
||||||
|
<value>IP or IP CIDR</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbRoutingRuleProcess" xml:space="preserve">
|
||||||
|
<value>Full process name (Tun mode)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsMux4SboxProtocol" xml:space="preserve">
|
||||||
|
<value>sing-box Mux Protocol</value>
|
||||||
|
</data>
|
||||||
|
<data name="LocalRestoreInvalidZipTips" xml:space="preserve">
|
||||||
|
<value>Invalid backup file</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbdomainStrategy4Singbox" xml:space="preserve">
|
||||||
|
<value>sing-box domain strategy</value>
|
||||||
|
</data>
|
||||||
|
<data name="ConnectionsHostFilterTitle" xml:space="preserve">
|
||||||
|
<value>Host filter</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingDnsImportDefConfig" xml:space="preserve">
|
||||||
|
<value>Click to import default DNS config</value>
|
||||||
|
</data>
|
||||||
|
<data name="TipActiveServer" xml:space="preserve">
|
||||||
|
<value>Active</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbDnsSingboxObjectDoc" xml:space="preserve">
|
||||||
|
<value>Please fill in DNS Structure, Click to view the document</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvConvertTargetTip" xml:space="preserve">
|
||||||
|
<value>Please leave blank if no conversion is required</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvConvertTarget" xml:space="preserve">
|
||||||
|
<value>Convert target type</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuStorageUI" xml:space="preserve">
|
||||||
|
<value>Save Interface Layout</value>
|
||||||
|
</data>
|
||||||
|
<data name="SpeedDisplayText" xml:space="preserve">
|
||||||
|
<value>{0} : {1}/s↑ | {2}/s↓</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvMoreUrl" xml:space="preserve">
|
||||||
|
<value>More URLs, separated by commas; Subscription conversion will be invalid</value>
|
||||||
|
</data>
|
||||||
|
<data name="MsgSkipSubscriptionUpdate" xml:space="preserve">
|
||||||
|
<value>Updates are not enabled, skip this subscription</value>
|
||||||
|
</data>
|
||||||
|
<data name="UpgradeAppNotExistTip" xml:space="preserve">
|
||||||
|
<value>UpgradeApp does not exist</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuAddServerViaImage" xml:space="preserve">
|
||||||
|
<value>Scan QR code in the image</value>
|
||||||
|
</data>
|
||||||
|
<data name="TipDisplayLog" xml:space="preserve">
|
||||||
|
<value>Please turn off when there is an abnormal disconnection</value>
|
||||||
|
</data>
|
||||||
|
<data name="SpeedtestingWait" xml:space="preserve">
|
||||||
|
<value>Waiting for testing (press ESC to terminate)...</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSpiderX" xml:space="preserve">
|
||||||
|
<value>SpiderX</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbShortId" xml:space="preserve">
|
||||||
|
<value>ShortId</value>
|
||||||
|
</data>
|
||||||
|
<data name="InvalidUrlTip" xml:space="preserve">
|
||||||
|
<value>Invalid address (Url)</value>
|
||||||
|
</data>
|
||||||
|
<data name="InsecureUrlProtocol" xml:space="preserve">
|
||||||
|
<value>Please do not use the insecure HTTP protocol subscription address</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbPublicKey" xml:space="preserve">
|
||||||
|
<value>PublicKey</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuMoveTo" xml:space="preserve">
|
||||||
|
<value>Move up and down</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsSocksPortTip" xml:space="preserve">
|
||||||
|
<value>Pac port = +3; Xray API port = +4; mihomo API port = +5;</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
||||||
|
<value>Install the font to the system and restart the settings</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuAddHysteria2Server" xml:space="preserve">
|
||||||
|
<value>Add [Hysteria2] server</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvWebDavPassword" xml:space="preserve">
|
||||||
|
<value>WebDav Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvWebDavDirName" xml:space="preserve">
|
||||||
|
<value>Remote folder name (optional)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingDownSpeed" xml:space="preserve">
|
||||||
|
<value>Download Speed</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuRemoteRestore" xml:space="preserve">
|
||||||
|
<value>Restore from remote (WebDAV)</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuRemoteBackup" xml:space="preserve">
|
||||||
|
<value>Backup to remote (WebDAV)</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvWebDavUserName" xml:space="preserve">
|
||||||
|
<value>WebDav User Name</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuLocalRestore" xml:space="preserve">
|
||||||
|
<value>Restore from local</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuLocalBackup" xml:space="preserve">
|
||||||
|
<value>Backup to local</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsUseSystemHosts" xml:space="preserve">
|
||||||
|
<value>Use System Hosts</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuBackupAndRestore" xml:space="preserve">
|
||||||
|
<value>Backup and Restore</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuLocalBackupAndRestore" xml:space="preserve">
|
||||||
|
<value>Local</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuExitTips" xml:space="preserve">
|
||||||
|
<value>Are you sure to exit?</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsHysteriaBandwidth" xml:space="preserve">
|
||||||
|
<value>Hysteria Max bandwidth (Up/Dw)</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvWebDavUrl" xml:space="preserve">
|
||||||
|
<value>WebDav Url</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuRemoteBackupAndRestore" xml:space="preserve">
|
||||||
|
<value>Remote (WebDAV)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
|
||||||
|
<value>System sudo password</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||||
|
<value>The password is encrypted and stored only in local files.</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||||
|
<value>Please set the sudo password in Tun mode settings first</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
||||||
|
<value>Please do not run this app with sudo</value>
|
||||||
|
</data>
|
||||||
|
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
||||||
|
<value>*xhttp mode</value>
|
||||||
|
</data>
|
||||||
|
<data name="TransportExtraTip" xml:space="preserve">
|
||||||
|
<value>XHTTP Extra raw JSON, format: { XHTTPObject }</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||||
|
<value>Hide to tray when closing the window</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
|
||||||
|
<value>Number per time for auto batch during speedtest(max 1000)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
||||||
|
<value>Exception. Do not use proxy server for addresses,with a comma (,)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsDestOverride" xml:space="preserve">
|
||||||
|
<value>Sniffing type</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsSecondLocalPortEnabled" xml:space="preserve">
|
||||||
|
<value>Enable second mixed port</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbRoutingInboundTagTips" xml:space="preserve">
|
||||||
|
<value>socks: local port, socks2: second local port, socks3: LAN port</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -127,7 +127,7 @@
|
|||||||
<value>配置格式不正确</value>
|
<value>配置格式不正确</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CustomServerTips" xml:space="preserve">
|
<data name="CustomServerTips" xml:space="preserve">
|
||||||
<value>注意,自定义配置完全依赖您自己的配置,不能使用所有设置功能。如需使用系统代理请手动修改监听端口。</value>
|
<value>注意,自定义配置完全依赖您自己的配置,不能使用所有设置功能。如需使用系统代理请手动修改监听端口。</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Downloading" xml:space="preserve">
|
<data name="Downloading" xml:space="preserve">
|
||||||
<value>下载开始...</value>
|
<value>下载开始...</value>
|
||||||
@@ -136,7 +136,7 @@
|
|||||||
<value>下载</value>
|
<value>下载</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DownloadYesNo" xml:space="preserve">
|
<data name="DownloadYesNo" xml:space="preserve">
|
||||||
<value>是否下载? {0}</value>
|
<value>是否下载?{0}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FailedConversionConfiguration" xml:space="preserve">
|
<data name="FailedConversionConfiguration" xml:space="preserve">
|
||||||
<value>转换配置文件失败</value>
|
<value>转换配置文件失败</value>
|
||||||
@@ -154,7 +154,7 @@
|
|||||||
<value>读取配置文件失败</value>
|
<value>读取配置文件失败</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FillCorrectServerPort" xml:space="preserve">
|
<data name="FillCorrectServerPort" xml:space="preserve">
|
||||||
<value>请填写正确格式服务器端口</value>
|
<value>请填写正确格式的服务器端口</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FillLocalListeningPort" xml:space="preserve">
|
<data name="FillLocalListeningPort" xml:space="preserve">
|
||||||
<value>请填写本地监听端口</value>
|
<value>请填写本地监听端口</value>
|
||||||
@@ -169,16 +169,16 @@
|
|||||||
<value>请填写用户ID</value>
|
<value>请填写用户ID</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Incorrectconfiguration" xml:space="preserve">
|
<data name="Incorrectconfiguration" xml:space="preserve">
|
||||||
<value>不是正确的配置,请检查</value>
|
<value>配置不正确,请检查</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="InitialConfiguration" xml:space="preserve">
|
<data name="InitialConfiguration" xml:space="preserve">
|
||||||
<value>初始化配置</value>
|
<value>初始化配置</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="IsLatestCore" xml:space="preserve">
|
<data name="IsLatestCore" xml:space="preserve">
|
||||||
<value>{0} {1} 已是最新版本。</value>
|
<value>{0} {1} 已是最新版本</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="IsLatestN" xml:space="preserve">
|
<data name="IsLatestN" xml:space="preserve">
|
||||||
<value>{0} {1} 已是最新版本。</value>
|
<value>{0} {1} 已是最新版本</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvAddress" xml:space="preserve">
|
<data name="LvAddress" xml:space="preserve">
|
||||||
<value>地址</value>
|
<value>地址</value>
|
||||||
@@ -226,7 +226,7 @@
|
|||||||
<value>未设置有效的订阅</value>
|
<value>未设置有效的订阅</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgParsingSuccessfully" xml:space="preserve">
|
<data name="MsgParsingSuccessfully" xml:space="preserve">
|
||||||
<value>解析{0}成功</value>
|
<value>解析 {0} 成功</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgStartGettingSubscriptions" xml:space="preserve">
|
<data name="MsgStartGettingSubscriptions" xml:space="preserve">
|
||||||
<value>开始获取订阅内容</value>
|
<value>开始获取订阅内容</value>
|
||||||
@@ -259,10 +259,10 @@
|
|||||||
<value>在文件夹 ({0}) 下未找到Core文件 (文件名:{1}),请下载后放入文件夹,下载地址: {2}</value>
|
<value>在文件夹 ({0}) 下未找到Core文件 (文件名:{1}),请下载后放入文件夹,下载地址: {2}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="NoValidQRcodeFound" xml:space="preserve">
|
<data name="NoValidQRcodeFound" xml:space="preserve">
|
||||||
<value>扫描完成,未发现有效二维码</value>
|
<value>扫描完成,未发现有效二维码</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="OperationFailed" xml:space="preserve">
|
<data name="OperationFailed" xml:space="preserve">
|
||||||
<value>操作失败,请检查重试</value>
|
<value>操作失败,请检查并重试</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PleaseFillRemarks" xml:space="preserve">
|
<data name="PleaseFillRemarks" xml:space="preserve">
|
||||||
<value>请填写别名</value>
|
<value>请填写别名</value>
|
||||||
@@ -280,10 +280,10 @@
|
|||||||
<value>服务器去重完成。原数量: {0},现数量: {1}</value>
|
<value>服务器去重完成。原数量: {0},现数量: {1}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RemoveServer" xml:space="preserve">
|
<data name="RemoveServer" xml:space="preserve">
|
||||||
<value>是否确定移除服务器?</value>
|
<value>是否确定移除服务器?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SaveClientConfigurationIn" xml:space="preserve">
|
<data name="SaveClientConfigurationIn" xml:space="preserve">
|
||||||
<value>客户端配置文件保存在:{0}</value>
|
<value>客户端配置文件保存在:{0}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="StartService" xml:space="preserve">
|
<data name="StartService" xml:space="preserve">
|
||||||
<value>启动服务({0})...</value>
|
<value>启动服务({0})...</value>
|
||||||
@@ -302,7 +302,7 @@
|
|||||||
<value>扫描导入分享链接成功</value>
|
<value>扫描导入分享链接成功</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TestMeOutput" xml:space="preserve">
|
<data name="TestMeOutput" xml:space="preserve">
|
||||||
<value>当前服务的真连接延迟: {0} ms</value>
|
<value>当前延迟: {0} ms,{1}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="OperationSuccess" xml:space="preserve">
|
<data name="OperationSuccess" xml:space="preserve">
|
||||||
<value>操作成功</value>
|
<value>操作成功</value>
|
||||||
@@ -311,10 +311,10 @@
|
|||||||
<value>请先选择规则</value>
|
<value>请先选择规则</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RemoveRules" xml:space="preserve">
|
<data name="RemoveRules" xml:space="preserve">
|
||||||
<value>是否确定移除规则?</value>
|
<value>是否确定移除规则?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RoutingRuleDetailRequiredTips" xml:space="preserve">
|
<data name="RoutingRuleDetailRequiredTips" xml:space="preserve">
|
||||||
<value>{0},必填其中一项.</value>
|
<value>{0},必填其中一项.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvRemarks" xml:space="preserve">
|
<data name="LvRemarks" xml:space="preserve">
|
||||||
<value>别名</value>
|
<value>别名</value>
|
||||||
@@ -329,10 +329,10 @@
|
|||||||
<value>请填写Url</value>
|
<value>请填写Url</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AddBatchRoutingRulesYesNo" xml:space="preserve">
|
<data name="AddBatchRoutingRulesYesNo" xml:space="preserve">
|
||||||
<value>是否追加规则?选择是则追加,选择否则替换</value>
|
<value>是否追加规则?选择“是”则追加,选择“否”则全部替换。</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgDownloadGeoFileSuccessfully" xml:space="preserve">
|
<data name="MsgDownloadGeoFileSuccessfully" xml:space="preserve">
|
||||||
<value>下载 GeoFile: {0} 成功</value>
|
<value>下载 GeoFile:{0} 成功</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgInformationTitle" xml:space="preserve">
|
<data name="MsgInformationTitle" xml:space="preserve">
|
||||||
<value>信息</value>
|
<value>信息</value>
|
||||||
@@ -344,7 +344,7 @@
|
|||||||
<value>请填写正确的自定义DNS</value>
|
<value>请填写正确的自定义DNS</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportPathTip1" xml:space="preserve">
|
<data name="TransportPathTip1" xml:space="preserve">
|
||||||
<value>*ws/httpupgrade/splithttp path</value>
|
<value>*ws/httpupgrade/xhttp path</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportPathTip2" xml:space="preserve">
|
<data name="TransportPathTip2" xml:space="preserve">
|
||||||
<value>*h2 path</value>
|
<value>*h2 path</value>
|
||||||
@@ -359,7 +359,7 @@
|
|||||||
<value>*http host中间逗号(,)分隔</value>
|
<value>*http host中间逗号(,)分隔</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportRequestHostTip2" xml:space="preserve">
|
<data name="TransportRequestHostTip2" xml:space="preserve">
|
||||||
<value>*ws/httpupgrade/splithttp host</value>
|
<value>*ws/httpupgrade/xhttp host</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportRequestHostTip3" xml:space="preserve">
|
<data name="TransportRequestHostTip3" xml:space="preserve">
|
||||||
<value>*h2 host中间逗号(,)分隔</value>
|
<value>*h2 host中间逗号(,)分隔</value>
|
||||||
@@ -386,7 +386,7 @@
|
|||||||
<value>*Kcp seed</value>
|
<value>*Kcp seed</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RegisterGlobalHotkeyFailed" xml:space="preserve">
|
<data name="RegisterGlobalHotkeyFailed" xml:space="preserve">
|
||||||
<value>注册全局热键 {0} 失败,原因 {1}</value>
|
<value>注册全局热键 {0} 失败,原因:{1}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
|
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
|
||||||
<value>注册全局热键 {0} 成功</value>
|
<value>注册全局热键 {0} 成功</value>
|
||||||
@@ -485,10 +485,10 @@
|
|||||||
<value>暗黑模式</value>
|
<value>暗黑模式</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
|
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
|
||||||
<value>是否跟随系统主题</value>
|
<value>跟随系统主题</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsLanguage" xml:space="preserve">
|
<data name="TbSettingsLanguage" xml:space="preserve">
|
||||||
<value>语言(重启)</value>
|
<value>语言(需重启)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuAddServerViaClipboard" xml:space="preserve">
|
<data name="menuAddServerViaClipboard" xml:space="preserve">
|
||||||
<value>从剪贴板导入分享链接 (Ctrl+V)</value>
|
<value>从剪贴板导入分享链接 (Ctrl+V)</value>
|
||||||
@@ -638,7 +638,7 @@
|
|||||||
<value>传输层安全(TLS)</value>
|
<value>传输层安全(TLS)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TipNetwork" xml:space="preserve">
|
<data name="TipNetwork" xml:space="preserve">
|
||||||
<value>*默认tcp,选错会无法连接</value>
|
<value>*默认tcp,选错会无法连接</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbCoreType" xml:space="preserve">
|
<data name="TbCoreType" xml:space="preserve">
|
||||||
<value>Core类型</value>
|
<value>Core类型</value>
|
||||||
@@ -671,7 +671,7 @@
|
|||||||
<value>Socks端口</value>
|
<value>Socks端口</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TipPreSocksPort" xml:space="preserve">
|
<data name="TipPreSocksPort" xml:space="preserve">
|
||||||
<value>* 自定义配置的Socks端口值,可不设置;当设置此值后,将使用Xray/sing-box(Tun)额外启动一个前置Socks服务,提供分流和速度显示等功能</value>
|
<value>*自定义配置的Socks端口值,可不设置;当设置此值后,将使用Xray/sing-box(Tun)额外启动一个前置Socks服务,提供分流和速度显示等功能</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbBrowse" xml:space="preserve">
|
<data name="TbBrowse" xml:space="preserve">
|
||||||
<value>浏览</value>
|
<value>浏览</value>
|
||||||
@@ -680,7 +680,7 @@
|
|||||||
<value>编辑</value>
|
<value>编辑</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsAdvancedProtocol" xml:space="preserve">
|
<data name="TbSettingsAdvancedProtocol" xml:space="preserve">
|
||||||
<value>高级代理设置, 协议选择(可选)</value>
|
<value>高级代理设置,协议选择(可选)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsAllowLAN" xml:space="preserve">
|
<data name="TbSettingsAllowLAN" xml:space="preserve">
|
||||||
<value>允许来自局域网的连接</value>
|
<value>允许来自局域网的连接</value>
|
||||||
@@ -689,19 +689,19 @@
|
|||||||
<value>启动后隐藏窗口</value>
|
<value>启动后隐藏窗口</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsAutoUpdateInterval" xml:space="preserve">
|
<data name="TbSettingsAutoUpdateInterval" xml:space="preserve">
|
||||||
<value>自动更新Geo文件的间隔(单位小时)</value>
|
<value>自动更新Geo文件的间隔(小时)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsCore" xml:space="preserve">
|
<data name="TbSettingsCore" xml:space="preserve">
|
||||||
<value>Core: 基础设置</value>
|
<value>Core: 基础设置</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsCoreDns" xml:space="preserve">
|
<data name="TbSettingsCoreDns" xml:space="preserve">
|
||||||
<value>V2ray DNS设置</value>
|
<value>v2ray DNS设置</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsCoreKcp" xml:space="preserve">
|
<data name="TbSettingsCoreKcp" xml:space="preserve">
|
||||||
<value>Core: KCP设置</value>
|
<value>Core: KCP设置</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsCoreType" xml:space="preserve">
|
<data name="TbSettingsCoreType" xml:space="preserve">
|
||||||
<value>Core类型设置</value>
|
<value>Core 类型设置</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsDefAllowInsecure" xml:space="preserve">
|
<data name="TbSettingsDefAllowInsecure" xml:space="preserve">
|
||||||
<value>默认跳过证书验证(allowInsecure)</value>
|
<value>默认跳过证书验证(allowInsecure)</value>
|
||||||
@@ -719,7 +719,7 @@
|
|||||||
<value>例外</value>
|
<value>例外</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsExceptionTip" xml:space="preserve">
|
<data name="TbSettingsExceptionTip" xml:space="preserve">
|
||||||
<value>例外. 对于下列字符开头的地址不使用代理配置文件:使用分号(;)分隔</value>
|
<value>例外:对于下列字符开头的地址,不使用代理配置文件。使用分号(;)分隔。</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsHttpPort" xml:space="preserve">
|
<data name="TbSettingsHttpPort" xml:space="preserve">
|
||||||
<value>本地http监听端口</value>
|
<value>本地http监听端口</value>
|
||||||
@@ -746,7 +746,7 @@
|
|||||||
<value>认证密码</value>
|
<value>认证密码</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsRemoteDNS" xml:space="preserve">
|
<data name="TbSettingsRemoteDNS" xml:space="preserve">
|
||||||
<value>自定义DNS(可多个,用逗号(,)分隔)</value>
|
<value>自定义DNS(可多个,用逗号(,)分隔)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSetUWP" xml:space="preserve">
|
<data name="TbSettingsSetUWP" xml:space="preserve">
|
||||||
<value>解除Win10 UWP应用回环代理限制</value>
|
<value>解除Win10 UWP应用回环代理限制</value>
|
||||||
@@ -755,7 +755,7 @@
|
|||||||
<value>开启流量探测</value>
|
<value>开启流量探测</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSocksPort" xml:space="preserve">
|
<data name="TbSettingsSocksPort" xml:space="preserve">
|
||||||
<value>本地socks监听端口</value>
|
<value>本地混合监听端口</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsStartBoot" xml:space="preserve">
|
<data name="TbSettingsStartBoot" xml:space="preserve">
|
||||||
<value>开机启动(可能会不成功)</value>
|
<value>开机启动(可能会不成功)</value>
|
||||||
@@ -791,7 +791,7 @@
|
|||||||
<value>全局热键设置</value>
|
<value>全局热键设置</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbGlobalHotkeySettingTip" xml:space="preserve">
|
<data name="TbGlobalHotkeySettingTip" xml:space="preserve">
|
||||||
<value>直接按键盘进行设置, 重启后生效</value>
|
<value>直接按键盘进行设置,重启后生效</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbNotChangeSystemProxy" xml:space="preserve">
|
<data name="TbNotChangeSystemProxy" xml:space="preserve">
|
||||||
<value>不改变系统代理</value>
|
<value>不改变系统代理</value>
|
||||||
@@ -830,7 +830,7 @@
|
|||||||
<value>上移 (U)</value>
|
<value>上移 (U)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgFilterTitle" xml:space="preserve">
|
<data name="MsgFilterTitle" xml:space="preserve">
|
||||||
<value>过滤器, 支持正则</value>
|
<value>过滤器(支持正则)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuWebsiteItem" xml:space="preserve">
|
<data name="menuWebsiteItem" xml:space="preserve">
|
||||||
<value>{0} 官网</value>
|
<value>{0} 官网</value>
|
||||||
@@ -850,12 +850,6 @@
|
|||||||
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
||||||
<value>设为活动规则 (Enter)</value>
|
<value>设为活动规则 (Enter)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRoutingBasic" xml:space="preserve">
|
|
||||||
<value>基础功能</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuRoutingBasicImportRules" xml:space="preserve">
|
|
||||||
<value>一键导入基础规则</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbdomainMatcher" xml:space="preserve">
|
<data name="TbdomainMatcher" xml:space="preserve">
|
||||||
<value>域名匹配算法</value>
|
<value>域名匹配算法</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -878,7 +872,7 @@
|
|||||||
<value>预定义规则集列表</value>
|
<value>预定义规则集列表</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRoutingTips" xml:space="preserve">
|
<data name="TbRoutingTips" xml:space="preserve">
|
||||||
<value>*设置的路由规则,用逗号(,)分隔;正则中的逗号用<COMMA>替代</value>
|
<value>*设置的路由规则,用逗号(,)分隔;正则中的逗号用<COMMA>替代</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuImportRulesFromClipboard" xml:space="preserve">
|
<data name="menuImportRulesFromClipboard" xml:space="preserve">
|
||||||
<value>从剪贴板中导入规则</value>
|
<value>从剪贴板中导入规则</value>
|
||||||
@@ -908,13 +902,13 @@
|
|||||||
<value>路由规则详情设置</value>
|
<value>路由规则详情设置</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbAutoSort" xml:space="preserve">
|
<data name="TbAutoSort" xml:space="preserve">
|
||||||
<value>保存时Domain, IP, 进程名 自动排序</value>
|
<value>保存时 Domain, IP, 进程名 自动排序</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRuleobjectDoc" xml:space="preserve">
|
<data name="TbRuleobjectDoc" xml:space="preserve">
|
||||||
<value>规则详细说明文档</value>
|
<value>规则详细说明文档</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbDnsObjectDoc" xml:space="preserve">
|
<data name="TbDnsObjectDoc" xml:space="preserve">
|
||||||
<value>支持填写DnsObject,JSON格式,点击查看文档</value>
|
<value>支持填写DnsObject,JSON格式,点击查看文档</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SubUrlTips" xml:space="preserve">
|
<data name="SubUrlTips" xml:space="preserve">
|
||||||
<value>普通分组此处请留空</value>
|
<value>普通分组此处请留空</value>
|
||||||
@@ -926,7 +920,7 @@
|
|||||||
<value>系统代理设置改变</value>
|
<value>系统代理设置改变</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsRouteOnly" xml:space="preserve">
|
<data name="TbSettingsRouteOnly" xml:space="preserve">
|
||||||
<value>RouteOnly</value>
|
<value>仅限路由(routeOnly)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsNotProxyLocalAddress" xml:space="preserve">
|
<data name="TbSettingsNotProxyLocalAddress" xml:space="preserve">
|
||||||
<value>请勿将代理服务器用于本地(Intranet)地址</value>
|
<value>请勿将代理服务器用于本地(Intranet)地址</value>
|
||||||
@@ -941,7 +935,7 @@
|
|||||||
<value>速度(M/s)</value>
|
<value>速度(M/s)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FailedToRunCore" xml:space="preserve">
|
<data name="FailedToRunCore" xml:space="preserve">
|
||||||
<value>运行Core失败,请看日志</value>
|
<value>运行Core失败,请查看日志</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvFilter" xml:space="preserve">
|
<data name="LvFilter" xml:space="preserve">
|
||||||
<value>别名正则过滤</value>
|
<value>别名正则过滤</value>
|
||||||
@@ -959,7 +953,7 @@
|
|||||||
<value>为局域网开启新的端口</value>
|
<value>为局域网开启新的端口</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsTunMode" xml:space="preserve">
|
<data name="TbSettingsTunMode" xml:space="preserve">
|
||||||
<value>Tun模式设置</value>
|
<value>Tun 模式设置</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuMoveToGroup" xml:space="preserve">
|
<data name="menuMoveToGroup" xml:space="preserve">
|
||||||
<value>移至订阅分组</value>
|
<value>移至订阅分组</value>
|
||||||
@@ -998,7 +992,7 @@
|
|||||||
<value>拷贝字体TTF/TTC文件到目录guiFonts,重启设置</value>
|
<value>拷贝字体TTF/TTC文件到目录guiFonts,重启设置</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSocksPortTip" xml:space="preserve">
|
<data name="TbSettingsSocksPortTip" xml:space="preserve">
|
||||||
<value>http端口= +1;Pac端口= +4;*ray API端口= +5;mihomo API端口= +6;</value>
|
<value>Pac端口= +3;Xray API端口= +4;mihomo API端口= +5;</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsStartBootTip" xml:space="preserve">
|
<data name="TbSettingsStartBootTip" xml:space="preserve">
|
||||||
<value>以管理员权限设置此项,在启动后获得管理员权限</value>
|
<value>以管理员权限设置此项,在启动后获得管理员权限</value>
|
||||||
@@ -1271,7 +1265,7 @@
|
|||||||
<value>显示或隐藏主界面</value>
|
<value>显示或隐藏主界面</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UpdateStandalonePackageTip" xml:space="preserve">
|
<data name="UpdateStandalonePackageTip" xml:space="preserve">
|
||||||
<value>您当前运行的是独立包,请手动下载 SelfContained.7z文件解压覆盖</value>
|
<value>您当前运行的是独立包,请手动下载 SelfContained.7z文件解压覆盖!</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbPreSocksPort4Sub" xml:space="preserve">
|
<data name="TbPreSocksPort4Sub" xml:space="preserve">
|
||||||
<value>自定义配置的Socks端口</value>
|
<value>自定义配置的Socks端口</value>
|
||||||
@@ -1348,6 +1342,9 @@
|
|||||||
<data name="menuRegionalPresetsRussia" xml:space="preserve">
|
<data name="menuRegionalPresetsRussia" xml:space="preserve">
|
||||||
<value>俄罗斯</value>
|
<value>俄罗斯</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="menuRegionalPresetsIran" xml:space="preserve">
|
||||||
|
<value>伊朗</value>
|
||||||
|
</data>
|
||||||
<data name="menuAddServerViaImage" xml:space="preserve">
|
<data name="menuAddServerViaImage" xml:space="preserve">
|
||||||
<value>扫描图片中的二维码</value>
|
<value>扫描图片中的二维码</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1357,4 +1354,49 @@
|
|||||||
<data name="InsecureUrlProtocol" xml:space="preserve">
|
<data name="InsecureUrlProtocol" xml:space="preserve">
|
||||||
<value>请不要使用不安全的HTTP协议订阅地址</value>
|
<value>请不要使用不安全的HTTP协议订阅地址</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
||||||
|
<value>安装字体到系统中,重启设置</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuExitTips" xml:space="preserve">
|
||||||
|
<value>是否确定退出?</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvMemo" xml:space="preserve">
|
||||||
|
<value>备注备忘</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
|
||||||
|
<value>系统的sudo密码</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||||
|
<value>密码已加密且只存储在本地文件中,无密码则每次都要输入</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||||
|
<value>请先在Tun模式设置中设置sudo密码</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
||||||
|
<value>请不要用sudo运行本程序</value>
|
||||||
|
</data>
|
||||||
|
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
||||||
|
<value>*xhttp 模式</value>
|
||||||
|
</data>
|
||||||
|
<data name="TransportExtraTip" xml:space="preserve">
|
||||||
|
<value>XHTTP Extra 原始 JSON,格式: { XHTTPObject }</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||||
|
<value>关闭窗口时隐藏至托盘</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
|
||||||
|
<value>测试时自动分批的每批数量(最大1000)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
||||||
|
<value>例外:对于下列地址不使用代理配置文件。使用逗号(,)分隔。</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsDestOverride" xml:space="preserve">
|
||||||
|
<value>流量探测类型</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsSecondLocalPortEnabled" xml:space="preserve">
|
||||||
|
<value>开启第二个本地监听端口</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbRoutingInboundTagTips" xml:space="preserve">
|
||||||
|
<value>socks:本地端口,socks2:第二个本地端口,socks3:局域网端口</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -127,7 +127,7 @@
|
|||||||
<value>設定格式不正確</value>
|
<value>設定格式不正確</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CustomServerTips" xml:space="preserve">
|
<data name="CustomServerTips" xml:space="preserve">
|
||||||
<value>注意,自訂設定完全依賴您自己的設定,不能使用所有設定功能。如需使用系統代理請手動修改監聽埠。</value>
|
<value>注意,自訂設定完全依賴您自己的設定,不能使用所有設定功能。如需使用系統代理請手動修改偵聽埠。</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Downloading" xml:space="preserve">
|
<data name="Downloading" xml:space="preserve">
|
||||||
<value>下載開始...</value>
|
<value>下載開始...</value>
|
||||||
@@ -136,7 +136,7 @@
|
|||||||
<value>下載</value>
|
<value>下載</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DownloadYesNo" xml:space="preserve">
|
<data name="DownloadYesNo" xml:space="preserve">
|
||||||
<value>是否下載? {0}</value>
|
<value>是否下載?{0}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FailedConversionConfiguration" xml:space="preserve">
|
<data name="FailedConversionConfiguration" xml:space="preserve">
|
||||||
<value>轉換設定檔失敗</value>
|
<value>轉換設定檔失敗</value>
|
||||||
@@ -154,10 +154,10 @@
|
|||||||
<value>讀取設定檔失敗</value>
|
<value>讀取設定檔失敗</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FillCorrectServerPort" xml:space="preserve">
|
<data name="FillCorrectServerPort" xml:space="preserve">
|
||||||
<value>請填寫正確格式伺服器埠</value>
|
<value>請填寫正確格式的伺服器埠</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FillLocalListeningPort" xml:space="preserve">
|
<data name="FillLocalListeningPort" xml:space="preserve">
|
||||||
<value>請填寫本機監聽埠</value>
|
<value>請填寫本機偵聽埠</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FillPassword" xml:space="preserve">
|
<data name="FillPassword" xml:space="preserve">
|
||||||
<value>請填寫密碼</value>
|
<value>請填寫密碼</value>
|
||||||
@@ -169,16 +169,16 @@
|
|||||||
<value>請填寫使用者ID</value>
|
<value>請填寫使用者ID</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Incorrectconfiguration" xml:space="preserve">
|
<data name="Incorrectconfiguration" xml:space="preserve">
|
||||||
<value>不是正確的設定,請檢查</value>
|
<value>設定不正確,請檢查</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="InitialConfiguration" xml:space="preserve">
|
<data name="InitialConfiguration" xml:space="preserve">
|
||||||
<value>初始化設定</value>
|
<value>初始化設定</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="IsLatestCore" xml:space="preserve">
|
<data name="IsLatestCore" xml:space="preserve">
|
||||||
<value>{0} {1} 已是最新版本。</value>
|
<value>{0} {1} 已是最新版本</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="IsLatestN" xml:space="preserve">
|
<data name="IsLatestN" xml:space="preserve">
|
||||||
<value>{0} {1} 已是最新版本。</value>
|
<value>{0} {1} 已是最新版本</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvAddress" xml:space="preserve">
|
<data name="LvAddress" xml:space="preserve">
|
||||||
<value>位址</value>
|
<value>位址</value>
|
||||||
@@ -226,7 +226,7 @@
|
|||||||
<value>未設定有效的訂閱</value>
|
<value>未設定有效的訂閱</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgParsingSuccessfully" xml:space="preserve">
|
<data name="MsgParsingSuccessfully" xml:space="preserve">
|
||||||
<value>解析{0}成功</value>
|
<value>解析 {0} 成功</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgStartGettingSubscriptions" xml:space="preserve">
|
<data name="MsgStartGettingSubscriptions" xml:space="preserve">
|
||||||
<value>開始獲取訂閱內容</value>
|
<value>開始獲取訂閱內容</value>
|
||||||
@@ -259,10 +259,10 @@
|
|||||||
<value>在資料夾 ({0}) 下未找到Core檔案 (檔案名:{1}),請下載後放入資料夾,下載網址: {2}</value>
|
<value>在資料夾 ({0}) 下未找到Core檔案 (檔案名:{1}),請下載後放入資料夾,下載網址: {2}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="NoValidQRcodeFound" xml:space="preserve">
|
<data name="NoValidQRcodeFound" xml:space="preserve">
|
||||||
<value>掃描完成,未發現有效二維碼</value>
|
<value>掃描完成,未發現有效二維碼</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="OperationFailed" xml:space="preserve">
|
<data name="OperationFailed" xml:space="preserve">
|
||||||
<value>操作失敗,請檢查重試</value>
|
<value>操作失敗,請檢查後重試</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PleaseFillRemarks" xml:space="preserve">
|
<data name="PleaseFillRemarks" xml:space="preserve">
|
||||||
<value>請填寫別名</value>
|
<value>請填寫別名</value>
|
||||||
@@ -280,16 +280,17 @@
|
|||||||
<value>伺服器去重完成。原數量: {0},現數量: {1}</value>
|
<value>伺服器去重完成。原數量: {0},現數量: {1}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RemoveServer" xml:space="preserve">
|
<data name="RemoveServer" xml:space="preserve">
|
||||||
<value>是否確定移除伺服器?</value>
|
<value>是否確定移除伺服器?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SaveClientConfigurationIn" xml:space="preserve">
|
<data name="SaveClientConfigurationIn" xml:space="preserve">
|
||||||
<value>用戶端設定檔儲存在:{0}</value>
|
<value>用戶端設定檔儲存在:{0}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="StartService" xml:space="preserve">
|
<data name="StartService" xml:space="preserve">
|
||||||
<value>啟動服務({0})...</value>
|
<value>啟動服務({0})...</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SuccessfulConfiguration" xml:space="preserve">
|
<data name="SuccessfulConfiguration" xml:space="preserve">
|
||||||
<value>設定成功{0}</value>
|
<value>設定成功
|
||||||
|
{0}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SuccessfullyImportedCustomServer" xml:space="preserve">
|
<data name="SuccessfullyImportedCustomServer" xml:space="preserve">
|
||||||
<value>成功匯入自訂設定伺服器</value>
|
<value>成功匯入自訂設定伺服器</value>
|
||||||
@@ -301,7 +302,7 @@
|
|||||||
<value>掃描匯入分享链接成功</value>
|
<value>掃描匯入分享链接成功</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TestMeOutput" xml:space="preserve">
|
<data name="TestMeOutput" xml:space="preserve">
|
||||||
<value>目前服務的真連接延遲: {0} ms</value>
|
<value>目前延遲: {0} ms,{1}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="OperationSuccess" xml:space="preserve">
|
<data name="OperationSuccess" xml:space="preserve">
|
||||||
<value>操作成功</value>
|
<value>操作成功</value>
|
||||||
@@ -310,10 +311,10 @@
|
|||||||
<value>請先選擇規則</value>
|
<value>請先選擇規則</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RemoveRules" xml:space="preserve">
|
<data name="RemoveRules" xml:space="preserve">
|
||||||
<value>是否確定移除規則?</value>
|
<value>是否確定移除規則?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RoutingRuleDetailRequiredTips" xml:space="preserve">
|
<data name="RoutingRuleDetailRequiredTips" xml:space="preserve">
|
||||||
<value>{0},必填其中一項.</value>
|
<value>{0},必填其中一項.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvRemarks" xml:space="preserve">
|
<data name="LvRemarks" xml:space="preserve">
|
||||||
<value>別名</value>
|
<value>別名</value>
|
||||||
@@ -328,10 +329,10 @@
|
|||||||
<value>請填寫URL</value>
|
<value>請填寫URL</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AddBatchRoutingRulesYesNo" xml:space="preserve">
|
<data name="AddBatchRoutingRulesYesNo" xml:space="preserve">
|
||||||
<value>是否追加規則?選擇是則追加,選擇否則取代</value>
|
<value>是否追加規則?選擇“是”則追加,選擇“否”則完全取代。</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgDownloadGeoFileSuccessfully" xml:space="preserve">
|
<data name="MsgDownloadGeoFileSuccessfully" xml:space="preserve">
|
||||||
<value>下載 GeoFile: {0} 成功</value>
|
<value>下載 GeoFile:{0} 成功</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgInformationTitle" xml:space="preserve">
|
<data name="MsgInformationTitle" xml:space="preserve">
|
||||||
<value>資訊</value>
|
<value>資訊</value>
|
||||||
@@ -343,7 +344,7 @@
|
|||||||
<value>請填寫正確的自訂DNS</value>
|
<value>請填寫正確的自訂DNS</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportPathTip1" xml:space="preserve">
|
<data name="TransportPathTip1" xml:space="preserve">
|
||||||
<value>*ws/httpupgrade/splithttp path</value>
|
<value>*ws/httpupgrade/xhttp path</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportPathTip2" xml:space="preserve">
|
<data name="TransportPathTip2" xml:space="preserve">
|
||||||
<value>*h2 path</value>
|
<value>*h2 path</value>
|
||||||
@@ -358,7 +359,7 @@
|
|||||||
<value>*http host中間逗號(,)分隔</value>
|
<value>*http host中間逗號(,)分隔</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportRequestHostTip2" xml:space="preserve">
|
<data name="TransportRequestHostTip2" xml:space="preserve">
|
||||||
<value>*ws/httpupgrade/splithttp host</value>
|
<value>*ws/httpupgrade/xhttp host</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportRequestHostTip3" xml:space="preserve">
|
<data name="TransportRequestHostTip3" xml:space="preserve">
|
||||||
<value>*h2 host中間逗號(,)分隔</value>
|
<value>*h2 host中間逗號(,)分隔</value>
|
||||||
@@ -385,7 +386,7 @@
|
|||||||
<value>*KCP seed</value>
|
<value>*KCP seed</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RegisterGlobalHotkeyFailed" xml:space="preserve">
|
<data name="RegisterGlobalHotkeyFailed" xml:space="preserve">
|
||||||
<value>註冊全域快速鍵 {0} 失敗,原因 {1}</value>
|
<value>註冊全域快速鍵 {0} 失敗,原因:{1}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
|
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
|
||||||
<value>註冊全域快速鍵 {0} 成功</value>
|
<value>註冊全域快速鍵 {0} 成功</value>
|
||||||
@@ -484,10 +485,10 @@
|
|||||||
<value>暗黑模式</value>
|
<value>暗黑模式</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
|
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
|
||||||
<value>是否跟隨系統主題</value>
|
<value>跟隨系統主題</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsLanguage" xml:space="preserve">
|
<data name="TbSettingsLanguage" xml:space="preserve">
|
||||||
<value>語言(重啟)</value>
|
<value>語言(需重啟)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuAddServerViaClipboard" xml:space="preserve">
|
<data name="menuAddServerViaClipboard" xml:space="preserve">
|
||||||
<value>從剪貼簿導入分享鏈接 (Ctrl+V)</value>
|
<value>從剪貼簿導入分享鏈接 (Ctrl+V)</value>
|
||||||
@@ -511,7 +512,7 @@
|
|||||||
<value>清除所有服務統計資料</value>
|
<value>清除所有服務統計資料</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRealPingServer" xml:space="preserve">
|
<data name="menuRealPingServer" xml:space="preserve">
|
||||||
<value>測試伺服器真連接延遲(多選) (Ctrl+R)</value>
|
<value>測試伺服器真連線延遲(多選) (Ctrl+R)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuSortServerResult" xml:space="preserve">
|
<data name="menuSortServerResult" xml:space="preserve">
|
||||||
<value>按測試結果排序</value>
|
<value>按測試結果排序</value>
|
||||||
@@ -637,7 +638,7 @@
|
|||||||
<value>傳輸層安全(TLS)</value>
|
<value>傳輸層安全(TLS)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TipNetwork" xml:space="preserve">
|
<data name="TipNetwork" xml:space="preserve">
|
||||||
<value>*預設TCP,選錯會無法連接</value>
|
<value>*預設TCP,選錯會無法連接</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbCoreType" xml:space="preserve">
|
<data name="TbCoreType" xml:space="preserve">
|
||||||
<value>Core類型</value>
|
<value>Core類型</value>
|
||||||
@@ -670,7 +671,7 @@
|
|||||||
<value>SOCKS埠</value>
|
<value>SOCKS埠</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TipPreSocksPort" xml:space="preserve">
|
<data name="TipPreSocksPort" xml:space="preserve">
|
||||||
<value>* 自訂設定的Socks埠值,可不設定;當設定此值後,將使用Xray/sing-box(Tun)額外啟動一個前置Socks服務,提供分流和速度顯示等功能</value>
|
<value>*自訂設定的Socks埠值,可不設定;當設定此值後,將使用Xray/sing-box(Tun)額外啟動一個前置Socks服務,提供分流和速度顯示等功能</value>
|
||||||
</data>
|
</data>
|
||||||
<!--********************************************-->
|
<!--********************************************-->
|
||||||
<data name="TbBrowse" xml:space="preserve">
|
<data name="TbBrowse" xml:space="preserve">
|
||||||
@@ -680,16 +681,16 @@
|
|||||||
<value>編輯</value>
|
<value>編輯</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsAdvancedProtocol" xml:space="preserve">
|
<data name="TbSettingsAdvancedProtocol" xml:space="preserve">
|
||||||
<value>進階代理設定, 協定選擇(可選)</value>
|
<value>進階代理設定,協定選擇(可選)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsAllowLAN" xml:space="preserve">
|
<data name="TbSettingsAllowLAN" xml:space="preserve">
|
||||||
<value>允許來自區域網路的連接</value>
|
<value>允許來自區域網路的連線</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsAutoHideStartup" xml:space="preserve">
|
<data name="TbSettingsAutoHideStartup" xml:space="preserve">
|
||||||
<value>啟動後隱藏視窗</value>
|
<value>啟動後隱藏視窗</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsAutoUpdateInterval" xml:space="preserve">
|
<data name="TbSettingsAutoUpdateInterval" xml:space="preserve">
|
||||||
<value>自動更新Geo檔案的間隔(單位小時)</value>
|
<value>自動更新Geo檔案的間隔(小時)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsCore" xml:space="preserve">
|
<data name="TbSettingsCore" xml:space="preserve">
|
||||||
<value>Core: 基礎設定</value>
|
<value>Core: 基礎設定</value>
|
||||||
@@ -701,7 +702,7 @@
|
|||||||
<value>Core: KCP設定</value>
|
<value>Core: KCP設定</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsCoreType" xml:space="preserve">
|
<data name="TbSettingsCoreType" xml:space="preserve">
|
||||||
<value>Core類型設定</value>
|
<value>Core 類型設定</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsDefAllowInsecure" xml:space="preserve">
|
<data name="TbSettingsDefAllowInsecure" xml:space="preserve">
|
||||||
<value>預設跳過憑證驗證(allowinsecure)</value>
|
<value>預設跳過憑證驗證(allowinsecure)</value>
|
||||||
@@ -719,10 +720,10 @@
|
|||||||
<value>例外</value>
|
<value>例外</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsExceptionTip" xml:space="preserve">
|
<data name="TbSettingsExceptionTip" xml:space="preserve">
|
||||||
<value>例外. 對於下列字元開頭的位址不使用代理設定檔:使用分號(;)分隔</value>
|
<value>例外:對於下列字元開頭的位址,不使用代理設定檔。使用分號(;)分隔。</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsHttpPort" xml:space="preserve">
|
<data name="TbSettingsHttpPort" xml:space="preserve">
|
||||||
<value>本機HTTP監聽埠</value>
|
<value>本機HTTP偵聽埠</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsIgnoreGeoUpdateCore" xml:space="preserve">
|
<data name="TbSettingsIgnoreGeoUpdateCore" xml:space="preserve">
|
||||||
<value>更新Core時忽略Geo檔案</value>
|
<value>更新Core時忽略Geo檔案</value>
|
||||||
@@ -746,7 +747,7 @@
|
|||||||
<value>認證密碼</value>
|
<value>認證密碼</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsRemoteDNS" xml:space="preserve">
|
<data name="TbSettingsRemoteDNS" xml:space="preserve">
|
||||||
<value>自訂DNS(可多個,用逗號(,)分隔)</value>
|
<value>自訂DNS(可多個,用逗號(,)分隔)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSetUWP" xml:space="preserve">
|
<data name="TbSettingsSetUWP" xml:space="preserve">
|
||||||
<value>解除Win10 UWP應用回環代理限制</value>
|
<value>解除Win10 UWP應用回環代理限制</value>
|
||||||
@@ -755,7 +756,7 @@
|
|||||||
<value>開啟流量探測</value>
|
<value>開啟流量探測</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSocksPort" xml:space="preserve">
|
<data name="TbSettingsSocksPort" xml:space="preserve">
|
||||||
<value>本機SOCKS監聽埠</value>
|
<value>本機混合偵聽埠</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsStartBoot" xml:space="preserve">
|
<data name="TbSettingsStartBoot" xml:space="preserve">
|
||||||
<value>開機啟動(可能會不成功)</value>
|
<value>開機啟動(可能會不成功)</value>
|
||||||
@@ -791,7 +792,7 @@
|
|||||||
<value>全域快速鍵設定</value>
|
<value>全域快速鍵設定</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbGlobalHotkeySettingTip" xml:space="preserve">
|
<data name="TbGlobalHotkeySettingTip" xml:space="preserve">
|
||||||
<value>直接按鍵盤進行設定, 重啟後生效</value>
|
<value>直接按鍵盤進行設定,重啟後生效</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbNotChangeSystemProxy" xml:space="preserve">
|
<data name="TbNotChangeSystemProxy" xml:space="preserve">
|
||||||
<value>不改變系統代理</value>
|
<value>不改變系統代理</value>
|
||||||
@@ -830,7 +831,7 @@
|
|||||||
<value>上移 (U)</value>
|
<value>上移 (U)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgFilterTitle" xml:space="preserve">
|
<data name="MsgFilterTitle" xml:space="preserve">
|
||||||
<value>過濾, 支援正則</value>
|
<value>過濾(允許正則)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuWebsiteItem" xml:space="preserve">
|
<data name="menuWebsiteItem" xml:space="preserve">
|
||||||
<value>{0} 官網</value>
|
<value>{0} 官網</value>
|
||||||
@@ -850,12 +851,6 @@
|
|||||||
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
||||||
<value>設為活動規則 (Enter)</value>
|
<value>設為活動規則 (Enter)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRoutingBasic" xml:space="preserve">
|
|
||||||
<value>基礎功能</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuRoutingBasicImportRules" xml:space="preserve">
|
|
||||||
<value>一鍵匯入基礎規則</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbdomainMatcher" xml:space="preserve">
|
<data name="TbdomainMatcher" xml:space="preserve">
|
||||||
<value>域名匹配演算法</value>
|
<value>域名匹配演算法</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -878,7 +873,7 @@
|
|||||||
<value>預定義規則集列表</value>
|
<value>預定義規則集列表</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRoutingTips" xml:space="preserve">
|
<data name="TbRoutingTips" xml:space="preserve">
|
||||||
<value>*設定的路由規則,用逗號(,)分隔;正則中的逗號用<COMMA>替代</value>
|
<value>*設定的路由規則,用逗號(,)分隔;正則中的逗號用<COMMA>替代</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuImportRulesFromClipboard" xml:space="preserve">
|
<data name="menuImportRulesFromClipboard" xml:space="preserve">
|
||||||
<value>從剪貼簿中匯入規則</value>
|
<value>從剪貼簿中匯入規則</value>
|
||||||
@@ -908,13 +903,13 @@
|
|||||||
<value>路由規則詳情設定</value>
|
<value>路由規則詳情設定</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbAutoSort" xml:space="preserve">
|
<data name="TbAutoSort" xml:space="preserve">
|
||||||
<value>儲存時Domain, IP, 行程名 自動排序</value>
|
<value>儲存時 Domain, IP, 行程名 自動排序</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRuleobjectDoc" xml:space="preserve">
|
<data name="TbRuleobjectDoc" xml:space="preserve">
|
||||||
<value>規則詳細說明檔案</value>
|
<value>規則詳細說明檔案</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbDnsObjectDoc" xml:space="preserve">
|
<data name="TbDnsObjectDoc" xml:space="preserve">
|
||||||
<value>支援填寫DnsObject,JSON格式,點擊查看檔案</value>
|
<value>支援填寫DnsObject,JSON格式,點擊查看説明</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SubUrlTips" xml:space="preserve">
|
<data name="SubUrlTips" xml:space="preserve">
|
||||||
<value>普通分組此處請留空</value>
|
<value>普通分組此處請留空</value>
|
||||||
@@ -926,7 +921,7 @@
|
|||||||
<value>系統代理設定已改變</value>
|
<value>系統代理設定已改變</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsRouteOnly" xml:space="preserve">
|
<data name="TbSettingsRouteOnly" xml:space="preserve">
|
||||||
<value>RouteOnly</value>
|
<value>僅限路由(routeOnly)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsNotProxyLocalAddress" xml:space="preserve">
|
<data name="TbSettingsNotProxyLocalAddress" xml:space="preserve">
|
||||||
<value>請勿將代理伺服器用於本機(Intranet)位址</value>
|
<value>請勿將代理伺服器用於本機(Intranet)位址</value>
|
||||||
@@ -941,7 +936,7 @@
|
|||||||
<value>速度(M/s)</value>
|
<value>速度(M/s)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FailedToRunCore" xml:space="preserve">
|
<data name="FailedToRunCore" xml:space="preserve">
|
||||||
<value>執行Core失敗,請看日誌</value>
|
<value>執行Core失敗,請查閲日誌</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvFilter" xml:space="preserve">
|
<data name="LvFilter" xml:space="preserve">
|
||||||
<value>別名正則過濾</value>
|
<value>別名正則過濾</value>
|
||||||
@@ -953,13 +948,13 @@
|
|||||||
<value>匯入舊的設定檔guiNConfig</value>
|
<value>匯入舊的設定檔guiNConfig</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbEnableTunAs" xml:space="preserve">
|
<data name="TbEnableTunAs" xml:space="preserve">
|
||||||
<value>啟用TUN</value>
|
<value>啟用Tun</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsNewPort4LAN" xml:space="preserve">
|
<data name="TbSettingsNewPort4LAN" xml:space="preserve">
|
||||||
<value>為區域網路開啟新的埠</value>
|
<value>為區域網路開啟新的埠</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsTunMode" xml:space="preserve">
|
<data name="TbSettingsTunMode" xml:space="preserve">
|
||||||
<value>TUN模式設定</value>
|
<value>Tun 模式設定</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuMoveToGroup" xml:space="preserve">
|
<data name="menuMoveToGroup" xml:space="preserve">
|
||||||
<value>移至訂閱分組</value>
|
<value>移至訂閱分組</value>
|
||||||
@@ -998,7 +993,7 @@
|
|||||||
<value>複製字型TTF/TTC檔案到目錄guiFonts,重啟設定</value>
|
<value>複製字型TTF/TTC檔案到目錄guiFonts,重啟設定</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSocksPortTip" xml:space="preserve">
|
<data name="TbSettingsSocksPortTip" xml:space="preserve">
|
||||||
<value>http端口= +1;Pac端口= +4;*ray API端口= +5;mihomo API端口= +6;</value>
|
<value>Pac連接埠= +3;Xray API連接埠= +4;mihomo API連接埠= +5;</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsStartBootTip" xml:space="preserve">
|
<data name="TbSettingsStartBootTip" xml:space="preserve">
|
||||||
<value>以管理員權限設定此項,在啟動後獲得管理員權限</value>
|
<value>以管理員權限設定此項,在啟動後獲得管理員權限</value>
|
||||||
@@ -1073,7 +1068,7 @@
|
|||||||
<value>sing-box Mux 多路復用協定</value>
|
<value>sing-box Mux 多路復用協定</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRoutingRuleProcess" xml:space="preserve">
|
<data name="TbRoutingRuleProcess" xml:space="preserve">
|
||||||
<value>行程名全稱 (TUN模式)</value>
|
<value>行程名全稱 (Tun模式)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRoutingRuleDomain" xml:space="preserve">
|
<data name="TbRoutingRuleDomain" xml:space="preserve">
|
||||||
<value>Domain</value>
|
<value>Domain</value>
|
||||||
@@ -1094,7 +1089,7 @@
|
|||||||
<value>請確保別名存在並且唯一</value>
|
<value>請確保別名存在並且唯一</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableExInbound" xml:space="preserve">
|
<data name="TbSettingsEnableExInbound" xml:space="preserve">
|
||||||
<value>啟用額外監聽端口</value>
|
<value>啟用額外偵聽連接埠</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
||||||
<value>啟用IPv6</value>
|
<value>啟用IPv6</value>
|
||||||
@@ -1106,7 +1101,7 @@
|
|||||||
<value>自动滚动到末尾</value>
|
<value>自动滚动到末尾</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSpeedPingTestUrl" xml:space="preserve">
|
<data name="TbSettingsSpeedPingTestUrl" xml:space="preserve">
|
||||||
<value>真連接測試地址</value>
|
<value>真連線測試位址</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableUpdateSubOnlyRemarksExist" xml:space="preserve">
|
<data name="TbSettingsEnableUpdateSubOnlyRemarksExist" xml:space="preserve">
|
||||||
<value>更新訂閱時只判斷別名是否存在</value>
|
<value>更新訂閱時只判斷別名是否存在</value>
|
||||||
@@ -1151,10 +1146,10 @@
|
|||||||
<value>顯示或隱藏主介面</value>
|
<value>顯示或隱藏主介面</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UpdateStandalonePackageTip" xml:space="preserve">
|
<data name="UpdateStandalonePackageTip" xml:space="preserve">
|
||||||
<value>您目前運行的是獨立包,請手動下載 SelfContained.7z檔案解壓縮覆蓋</value>
|
<value>您目前運行的是獨立包,請手動下載 SelfContained.7z檔案解壓縮覆蓋!</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbPreSocksPort4Sub" xml:space="preserve">
|
<data name="TbPreSocksPort4Sub" xml:space="preserve">
|
||||||
<value>自訂設定的Socks端口</value>
|
<value>自訂設定的Socks連接埠</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuBackupAndRestore" xml:space="preserve">
|
<data name="menuBackupAndRestore" xml:space="preserve">
|
||||||
<value>備份和還原</value>
|
<value>備份和還原</value>
|
||||||
@@ -1187,7 +1182,7 @@
|
|||||||
<value>WebDav 密碼</value>
|
<value>WebDav 密碼</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvWebDavUrl" xml:space="preserve">
|
<data name="LvWebDavUrl" xml:space="preserve">
|
||||||
<value>WebDav 伺服器地址</value>
|
<value>WebDav 伺服器位址</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvWebDavDirName" xml:space="preserve">
|
<data name="LvWebDavDirName" xml:space="preserve">
|
||||||
<value>遠端資料夾名稱(可選)</value>
|
<value>遠端資料夾名稱(可選)</value>
|
||||||
@@ -1205,36 +1200,204 @@
|
|||||||
<value>儲存介面佈局</value>
|
<value>儲存介面佈局</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsGeoFilesSource" xml:space="preserve">
|
<data name="TbSettingsGeoFilesSource" xml:space="preserve">
|
||||||
<value>Geo文件來源(可選)</value>
|
<value>Geo檔案來源(可選)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UpgradeAppNotExistTip" xml:space="preserve">
|
<data name="UpgradeAppNotExistTip" xml:space="preserve">
|
||||||
<value>升级工具App不存在</value>
|
<value>升級工具App不存在</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSrsFilesSource" xml:space="preserve">
|
<data name="TbSettingsSrsFilesSource" xml:space="preserve">
|
||||||
<value>sing-box ruleset文件來源(可選)</value>
|
<value>sing-box ruleset檔案來源(可選)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsRoutingRulesSource" xml:space="preserve">
|
<data name="TbSettingsRoutingRulesSource" xml:space="preserve">
|
||||||
<value>路由规则集来源(可选)</value>
|
<value>路由規則集來源(可選)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsChinaUserTip" xml:space="preserve">
|
<data name="TbSettingsChinaUserTip" xml:space="preserve">
|
||||||
<value>中国区域用户可忽略此项</value>
|
<value>中國區域用戶可忽略此項</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRegionalPresets" xml:space="preserve">
|
<data name="menuRegionalPresets" xml:space="preserve">
|
||||||
<value>区域预置设置</value>
|
<value>區域預置設定</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRegionalPresetsDefault" xml:space="preserve">
|
<data name="menuRegionalPresetsDefault" xml:space="preserve">
|
||||||
<value>默认区域</value>
|
<value>預設區域</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRegionalPresetsRussia" xml:space="preserve">
|
<data name="menuRegionalPresetsRussia" xml:space="preserve">
|
||||||
<value>俄羅斯</value>
|
<value>俄羅斯</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="menuRegionalPresetsIran" xml:space="preserve">
|
||||||
|
<value>伊朗</value>
|
||||||
|
</data>
|
||||||
<data name="menuAddServerViaImage" xml:space="preserve">
|
<data name="menuAddServerViaImage" xml:space="preserve">
|
||||||
<value>掃描圖片中的二維碼</value>
|
<value>掃描圖片中的二維碼</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="InvalidUrlTip" xml:space="preserve">
|
<data name="InvalidUrlTip" xml:space="preserve">
|
||||||
<value>地址(Url)無效</value>
|
<value>位址(Url)無效</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="InsecureUrlProtocol" xml:space="preserve">
|
<data name="InsecureUrlProtocol" xml:space="preserve">
|
||||||
<value>請不要使用不安全的HTTP協定訂閱位址</value>
|
<value>請不要使用不安全的HTTP協定訂閱位址</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
||||||
|
<value>安裝字型到系統中,重新啟動設定</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuExitTips" xml:space="preserve">
|
||||||
|
<value>是否確定退出?</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvMemo" xml:space="preserve">
|
||||||
|
<value>備註備忘</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbHeaderType8" xml:space="preserve">
|
||||||
|
<value>擁塞控制算法</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuProxiesSelectActivity" xml:space="preserve">
|
||||||
|
<value>設為活動節點 (Enter)</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuProxiesReload" xml:space="preserve">
|
||||||
|
<value>重新整理</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSorting" xml:space="preserve">
|
||||||
|
<value>排序</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuProxiesDelaytest" xml:space="preserve">
|
||||||
|
<value>延遲測試</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuModeRule" xml:space="preserve">
|
||||||
|
<value>規則</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuModeNothing" xml:space="preserve">
|
||||||
|
<value>随原配置</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuModeGlobal" xml:space="preserve">
|
||||||
|
<value>全局</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuModeDirect" xml:space="preserve">
|
||||||
|
<value>直連</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuRulemode" xml:space="preserve">
|
||||||
|
<value>規則模式</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbProxies" xml:space="preserve">
|
||||||
|
<value>目前代理</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuConnectionCloseAll" xml:space="preserve">
|
||||||
|
<value>關閉所有連線</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsDomainStrategy4Out" xml:space="preserve">
|
||||||
|
<value>Outbound預設解析策略</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuConnectionClose" xml:space="preserve">
|
||||||
|
<value>關閉連線</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingUpTraffic" xml:space="preserve">
|
||||||
|
<value>上傳流量</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingUpSpeed" xml:space="preserve">
|
||||||
|
<value>上傳速度</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingType" xml:space="preserve">
|
||||||
|
<value>類型</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingTime" xml:space="preserve">
|
||||||
|
<value>時間</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingNetwork" xml:space="preserve">
|
||||||
|
<value>網路</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingName" xml:space="preserve">
|
||||||
|
<value>名稱</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingHost" xml:space="preserve">
|
||||||
|
<value>主機</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingDownTraffic" xml:space="preserve">
|
||||||
|
<value>下載流量</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingDownSpeed" xml:space="preserve">
|
||||||
|
<value>下載速度</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingDelay" xml:space="preserve">
|
||||||
|
<value>延遲</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingDefault" xml:space="preserve">
|
||||||
|
<value>預設</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbConnections" xml:space="preserve">
|
||||||
|
<value>目前連線</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuSetDefaultMultipleServer" xml:space="preserve">
|
||||||
|
<value>多伺服器最低延遲 (多選)</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuProxiesDelaytestPart" xml:space="preserve">
|
||||||
|
<value>目前部分節點延遲測試</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuSetDefaultLoadBalanceServer" xml:space="preserve">
|
||||||
|
<value>多伺服器負載平衡 (多選)</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuAddHysteria2Server" xml:space="preserve">
|
||||||
|
<value>添加[Hysteria2]伺服器</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsHysteriaBandwidth" xml:space="preserve">
|
||||||
|
<value>Hysteria 最大頻寬(Up/Dw)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsMainGirdOrientation" xml:space="preserve">
|
||||||
|
<value>主界面佈局方向(需重啟)</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuAddWireguardServer" xml:space="preserve">
|
||||||
|
<value>添加[WireGuard]伺服器</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbPrivateKey" xml:space="preserve">
|
||||||
|
<value>PrivateKey</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbReserved" xml:space="preserve">
|
||||||
|
<value>Reserved(2,3,4)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbLocalAddress" xml:space="preserve">
|
||||||
|
<value>Address(Ip,Ipv6)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsUseSystemHosts" xml:space="preserve">
|
||||||
|
<value>使用系統hosts</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSortingChain" xml:space="preserve">
|
||||||
|
<value>路由鏈</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsDomainDNSAddress" xml:space="preserve">
|
||||||
|
<value>Outbound域名解析位址</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbPath7" xml:space="preserve">
|
||||||
|
<value>混淆密碼(obfs password)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
|
||||||
|
<value>系統的sudo密碼</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||||
|
<value>密碼已加密且只儲存在本機檔案中,無密碼則每次都要輸入</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||||
|
<value>請先在Tun模式設定中設定sudo密碼</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
||||||
|
<value>請不要用sudo來運行此App</value>
|
||||||
|
</data>
|
||||||
|
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
||||||
|
<value>*xhttp 模式</value>
|
||||||
|
</data>
|
||||||
|
<data name="TransportExtraTip" xml:space="preserve">
|
||||||
|
<value>XHTTP Extra 原始 JSON,格式: { XHTTPObject }</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||||
|
<value>關閉視窗時隱藏至托盤</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
|
||||||
|
<value>測試時自動分批的每批數量(最大1000)</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
||||||
|
<value>例外:對於下列位址不使用代理設定檔,使用逗號(,)分隔。</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsDestOverride" xml:space="preserve">
|
||||||
|
<value>流量探測類型</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsSecondLocalPortEnabled" xml:space="preserve">
|
||||||
|
<value>開啟第二個本機監聽埠</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbRoutingInboundTagTips" xml:space="preserve">
|
||||||
|
<value>socks:本地端口,socks2:第二個本地端口,socks3:區域網路端口</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -5,24 +5,25 @@
|
|||||||
"loglevel": "warning"
|
"loglevel": "warning"
|
||||||
},
|
},
|
||||||
"inbounds": [],
|
"inbounds": [],
|
||||||
"outbounds": [{
|
"outbounds": [
|
||||||
|
{
|
||||||
"tag": "proxy",
|
"tag": "proxy",
|
||||||
"protocol": "vmess",
|
"protocol": "vmess",
|
||||||
"settings": {
|
"settings": {
|
||||||
"vnext": [{
|
"vnext": [{
|
||||||
"address": "v2ray.cool",
|
"address": "",
|
||||||
"port": 10086,
|
"port": 0,
|
||||||
"users": [{
|
"users": [{
|
||||||
"id": "a3482e88-686a-4a58-8126-99c9df64b7bf",
|
"id": "",
|
||||||
"security": "auto"
|
"security": "auto"
|
||||||
}]
|
}]
|
||||||
}],
|
}],
|
||||||
"servers": [{
|
"servers": [{
|
||||||
"address": "v2ray.cool",
|
"address": "",
|
||||||
"method": "chacha20",
|
"method": "",
|
||||||
"ota": false,
|
"ota": false,
|
||||||
"password": "123456",
|
"password": "",
|
||||||
"port": 10086,
|
"port": 0,
|
||||||
"level": 1
|
"level": 1
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
@@ -35,27 +36,23 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"protocol": "freedom",
|
"protocol": "freedom",
|
||||||
"settings": {},
|
|
||||||
"tag": "direct"
|
"tag": "direct"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"protocol": "blackhole",
|
"protocol": "blackhole",
|
||||||
"tag": "block",
|
"tag": "block"
|
||||||
"settings": {
|
|
||||||
"response": {
|
|
||||||
"type": "http"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"routing": {
|
"routing": {
|
||||||
"domainStrategy": "IPIfNonMatch",
|
"domainStrategy": "IPIfNonMatch",
|
||||||
"rules": [
|
"rules": [
|
||||||
{
|
{
|
||||||
"inboundTag": ["api"],
|
"inboundTag": [
|
||||||
"outboundTag": "api",
|
"api"
|
||||||
"type": "field"
|
],
|
||||||
}
|
"outboundTag": "api",
|
||||||
|
"type": "field"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,13 @@
|
|||||||
"bittorrent"
|
"bittorrent"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"remarks": "api.ip.sb",
|
||||||
|
"outboundTag": "proxy",
|
||||||
|
"domain": [
|
||||||
|
"api.ip.sb"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"remarks": "Google cn",
|
"remarks": "Google cn",
|
||||||
"outboundTag": "proxy",
|
"outboundTag": "proxy",
|
||||||
@@ -42,21 +49,89 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"remarks": "代理GFW",
|
"remarks": "代理海外公共DNSIP",
|
||||||
"outboundTag": "proxy",
|
"outboundTag": "proxy",
|
||||||
"domain": [
|
"ip": [
|
||||||
"geosite:gfw",
|
"1.1.1.1",
|
||||||
"geosite:greatfire"
|
"1.0.0.1",
|
||||||
|
"2606:4700:4700::1111",
|
||||||
|
"2606:4700:4700::1001",
|
||||||
|
"1.1.1.2",
|
||||||
|
"1.0.0.2",
|
||||||
|
"2606:4700:4700::1112",
|
||||||
|
"2606:4700:4700::1002",
|
||||||
|
"1.1.1.3",
|
||||||
|
"1.0.0.3",
|
||||||
|
"2606:4700:4700::1113",
|
||||||
|
"2606:4700:4700::1003",
|
||||||
|
"8.8.8.8",
|
||||||
|
"8.8.4.4",
|
||||||
|
"2001:4860:4860::8888",
|
||||||
|
"2001:4860:4860::8844",
|
||||||
|
"94.140.14.14",
|
||||||
|
"94.140.15.15",
|
||||||
|
"2a10:50c0::ad1:ff",
|
||||||
|
"2a10:50c0::ad2:ff",
|
||||||
|
"94.140.14.15",
|
||||||
|
"94.140.15.16",
|
||||||
|
"2a10:50c0::bad1:ff",
|
||||||
|
"2a10:50c0::bad2:ff",
|
||||||
|
"94.140.14.140",
|
||||||
|
"94.140.14.141",
|
||||||
|
"2a10:50c0::1:ff",
|
||||||
|
"2a10:50c0::2:ff",
|
||||||
|
"208.67.222.222",
|
||||||
|
"208.67.220.220",
|
||||||
|
"2620:119:35::35",
|
||||||
|
"2620:119:53::53",
|
||||||
|
"208.67.222.123",
|
||||||
|
"208.67.220.123",
|
||||||
|
"2620:119:35::123",
|
||||||
|
"2620:119:53::123",
|
||||||
|
"9.9.9.9",
|
||||||
|
"149.112.112.112",
|
||||||
|
"2620:fe::9",
|
||||||
|
"2620:fe::fe",
|
||||||
|
"9.9.9.11",
|
||||||
|
"149.112.112.11",
|
||||||
|
"2620:fe::11",
|
||||||
|
"2620:fe::fe:11",
|
||||||
|
"9.9.9.10",
|
||||||
|
"149.112.112.10",
|
||||||
|
"2620:fe::10",
|
||||||
|
"2620:fe::fe:10",
|
||||||
|
"77.88.8.8",
|
||||||
|
"77.88.8.1",
|
||||||
|
"2a02:6b8::feed:0ff",
|
||||||
|
"2a02:6b8:0:1::feed:0ff",
|
||||||
|
"77.88.8.88",
|
||||||
|
"77.88.8.2",
|
||||||
|
"2a02:6b8::feed:bad",
|
||||||
|
"2a02:6b8:0:1::feed:bad",
|
||||||
|
"77.88.8.7",
|
||||||
|
"77.88.8.3",
|
||||||
|
"2a02:6b8::feed:a11",
|
||||||
|
"2a02:6b8:0:1::feed:a11"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"remarks": "代理Google等",
|
"remarks": "代理海外公共DNS域名",
|
||||||
|
"outboundTag": "proxy",
|
||||||
|
"domain": [
|
||||||
|
"domain:cloudflare-dns.com",
|
||||||
|
"domain:one.one.one.one",
|
||||||
|
"domain:dns.google",
|
||||||
|
"domain:adguard-dns.com",
|
||||||
|
"domain:opendns.com",
|
||||||
|
"domain:umbrella.com",
|
||||||
|
"domain:quad9.net",
|
||||||
|
"domain:yandex.net"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"remarks": "代理IP",
|
||||||
"outboundTag": "proxy",
|
"outboundTag": "proxy",
|
||||||
"ip": [
|
"ip": [
|
||||||
"1.0.0.1",
|
|
||||||
"1.1.1.1",
|
|
||||||
"8.8.8.8",
|
|
||||||
"8.8.4.4",
|
|
||||||
"geoip:facebook",
|
"geoip:facebook",
|
||||||
"geoip:fastly",
|
"geoip:fastly",
|
||||||
"geoip:google",
|
"geoip:google",
|
||||||
@@ -65,6 +140,14 @@
|
|||||||
"geoip:twitter"
|
"geoip:twitter"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"remarks": "代理GFW",
|
||||||
|
"outboundTag": "proxy",
|
||||||
|
"domain": [
|
||||||
|
"geosite:gfw",
|
||||||
|
"geosite:greatfire"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"remarks": "最终直连",
|
"remarks": "最终直连",
|
||||||
"port": "0-65535",
|
"port": "0-65535",
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"domain": [
|
|
||||||
"geosite:google"
|
|
||||||
],
|
|
||||||
"outboundTag": "proxy"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"outboundTag": "direct",
|
|
||||||
"domain": [
|
|
||||||
"domain:example-example.com",
|
|
||||||
"domain:example-example2.com"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"outboundTag": "block",
|
|
||||||
"domain": [
|
|
||||||
"geosite:category-ads-all"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
[{
|
|
||||||
"remarks": "block",
|
|
||||||
"outboundTag": "block",
|
|
||||||
"domain": [
|
|
||||||
"geosite:category-ads-all"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"remarks": "direct",
|
|
||||||
"outboundTag": "direct",
|
|
||||||
"domain": [
|
|
||||||
"geosite:cn"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"remarks": "direct",
|
|
||||||
"outboundTag": "direct",
|
|
||||||
"ip": [
|
|
||||||
"geoip:private",
|
|
||||||
"geoip:cn"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"remarks": "proxy",
|
|
||||||
"port": "0-65535",
|
|
||||||
"outboundTag": "proxy"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -35,47 +35,69 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"remarks": "绕过中国域名",
|
"remarks": "绕过中国公共DNSIP",
|
||||||
|
"outboundTag": "direct",
|
||||||
|
"ip": [
|
||||||
|
"223.5.5.5",
|
||||||
|
"223.6.6.6",
|
||||||
|
"2400:3200::1",
|
||||||
|
"2400:3200:baba::1",
|
||||||
|
"119.29.29.29",
|
||||||
|
"1.12.12.12",
|
||||||
|
"120.53.53.53",
|
||||||
|
"2402:4e00::",
|
||||||
|
"2402:4e00:1::",
|
||||||
|
"180.76.76.76",
|
||||||
|
"2400:da00::6666",
|
||||||
|
"114.114.114.114",
|
||||||
|
"114.114.115.115",
|
||||||
|
"114.114.114.119",
|
||||||
|
"114.114.115.119",
|
||||||
|
"114.114.114.110",
|
||||||
|
"114.114.115.110",
|
||||||
|
"180.184.1.1",
|
||||||
|
"180.184.2.2",
|
||||||
|
"101.226.4.6",
|
||||||
|
"218.30.118.6",
|
||||||
|
"123.125.81.6",
|
||||||
|
"140.207.198.6",
|
||||||
|
"1.2.4.8",
|
||||||
|
"210.2.4.8",
|
||||||
|
"52.80.66.66",
|
||||||
|
"117.50.22.22",
|
||||||
|
"2400:7fc0:849e:200::4",
|
||||||
|
"2404:c2c0:85d8:901::4",
|
||||||
|
"117.50.10.10",
|
||||||
|
"52.80.52.52",
|
||||||
|
"2400:7fc0:849e:200::8",
|
||||||
|
"2404:c2c0:85d8:901::8",
|
||||||
|
"117.50.60.30",
|
||||||
|
"52.80.60.30"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"remarks": "绕过中国公共DNS域名",
|
||||||
"outboundTag": "direct",
|
"outboundTag": "direct",
|
||||||
"domain": [
|
"domain": [
|
||||||
"domain:dns.alidns.com",
|
"domain:alidns.com",
|
||||||
"domain:doh.pub",
|
"domain:doh.pub",
|
||||||
"domain:dot.pub",
|
"domain:dot.pub",
|
||||||
"domain:doh.360.cn",
|
"domain:360.cn",
|
||||||
"domain:dot.360.cn",
|
"domain:onedns.net"
|
||||||
"geosite:cn",
|
|
||||||
"geosite:geolocation-cn"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"remarks": "绕过中国IP",
|
"remarks": "绕过中国IP",
|
||||||
"outboundTag": "direct",
|
"outboundTag": "direct",
|
||||||
"ip": [
|
"ip": [
|
||||||
"223.5.5.5/32",
|
|
||||||
"223.6.6.6/32",
|
|
||||||
"2400:3200::1/128",
|
|
||||||
"2400:3200:baba::1/128",
|
|
||||||
"119.29.29.29/32",
|
|
||||||
"1.12.12.12/32",
|
|
||||||
"120.53.53.53/32",
|
|
||||||
"2402:4e00::/128",
|
|
||||||
"2402:4e00:1::/128",
|
|
||||||
"180.76.76.76/32",
|
|
||||||
"2400:da00::6666/128",
|
|
||||||
"114.114.114.114/32",
|
|
||||||
"114.114.115.115/32",
|
|
||||||
"180.184.1.1/32",
|
|
||||||
"180.184.2.2/32",
|
|
||||||
"101.226.4.6/32",
|
|
||||||
"218.30.118.6/32",
|
|
||||||
"123.125.81.6/32",
|
|
||||||
"140.207.198.6/32",
|
|
||||||
"geoip:cn"
|
"geoip:cn"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"remarks": "最终代理",
|
"remarks": "绕过中国域名",
|
||||||
"port": "0-65535",
|
"outboundTag": "direct",
|
||||||
"outboundTag": "proxy"
|
"domain": [
|
||||||
|
"geosite:cn"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -20,8 +20,7 @@
|
|||||||
"rules": [
|
"rules": [
|
||||||
{
|
{
|
||||||
"rule_set": [
|
"rule_set": [
|
||||||
"geosite-cn",
|
"geosite-cn"
|
||||||
"geosite-geolocation-cn"
|
|
||||||
],
|
],
|
||||||
"server": "local"
|
"server": "local"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,17 +4,24 @@
|
|||||||
"proxy.example.com": "127.0.0.1"
|
"proxy.example.com": "127.0.0.1"
|
||||||
},
|
},
|
||||||
"servers": [
|
"servers": [
|
||||||
|
{
|
||||||
|
"address": "1.1.1.1",
|
||||||
|
"domains": [
|
||||||
|
"geosite:geolocation-!cn"
|
||||||
|
],
|
||||||
|
"expectIPs": [
|
||||||
|
"geoip:!cn"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"address": "223.5.5.5",
|
"address": "223.5.5.5",
|
||||||
"domains": [
|
"domains": [
|
||||||
"geosite:cn",
|
"geosite:cn"
|
||||||
"geosite:geolocation-cn"
|
|
||||||
],
|
],
|
||||||
"expectIPs": [
|
"expectIPs": [
|
||||||
"geoip:cn"
|
"geoip:cn"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"1.1.1.1",
|
|
||||||
"8.8.8.8",
|
"8.8.8.8",
|
||||||
"https://dns.google/dns-query"
|
"https://dns.google/dns-query"
|
||||||
]
|
]
|
||||||
|
|||||||
10
v2rayN/ServiceLib/Sample/linux_autostart_config
Normal file
10
v2rayN/ServiceLib/Sample/linux_autostart_config
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Type=Application
|
||||||
|
Exec=$ExecPath$
|
||||||
|
Hidden=false
|
||||||
|
NoDisplay=false
|
||||||
|
X-GNOME-Autostart-enabled=true
|
||||||
|
Name[en_US]=v2rayN
|
||||||
|
Name=v2rayN
|
||||||
|
Comment[en_US]=v2rayN
|
||||||
|
Comment=v2rayN
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -2,8 +2,10 @@
|
|||||||
"type": "tun",
|
"type": "tun",
|
||||||
"tag": "tun-in",
|
"tag": "tun-in",
|
||||||
"interface_name": "singbox_tun",
|
"interface_name": "singbox_tun",
|
||||||
"inet4_address": "172.19.0.1/30",
|
"address": [
|
||||||
"inet6_address": "fdfe:dcba:9876::1/126",
|
"172.18.0.1/30",
|
||||||
|
"fdfe:dcba:9876::1/126"
|
||||||
|
],
|
||||||
"mtu": 9000,
|
"mtu": 9000,
|
||||||
"auto_route": true,
|
"auto_route": true,
|
||||||
"strict_route": false,
|
"strict_route": false,
|
||||||
|
|||||||
@@ -4,21 +4,23 @@
|
|||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<Version>7.0.1</Version>
|
<Version>7.5.6</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Downloader" Version="3.2.1" />
|
<PackageReference Include="Downloader" Version="3.3.1" />
|
||||||
<PackageReference Include="ReactiveUI" Version="20.1.63" />
|
<PackageReference Include="ReactiveUI" Version="20.1.63" />
|
||||||
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
|
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
|
||||||
<PackageReference Include="sqlite-net-pcl" Version="1.9.172" />
|
<PackageReference Include="sqlite-net-pcl" Version="1.9.172" />
|
||||||
<PackageReference Include="Splat.NLog" Version="15.2.22" />
|
<PackageReference Include="Splat.NLog" Version="15.2.22" />
|
||||||
<PackageReference Include="WebDav.Client" Version="2.8.0" />
|
<PackageReference Include="WebDav.Client" Version="2.8.0" />
|
||||||
<PackageReference Include="YamlDotNet" Version="16.1.3" />
|
<PackageReference Include="YamlDotNet" Version="16.3.0" />
|
||||||
<PackageReference Include="QRCoder" Version="1.6.0" />
|
<PackageReference Include="QRCoder" Version="1.6.0" />
|
||||||
<PackageReference Include="CliWrap" Version="3.6.6" />
|
<PackageReference Include="CliWrap" Version="3.7.0" />
|
||||||
<PackageReference Include="SkiaSharp.QrCode" Version="0.7.0" />
|
<PackageReference Include="SkiaSharp.QrCode" Version="0.7.0" />
|
||||||
<PackageReference Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.14" />
|
<PackageReference Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.14" />
|
||||||
|
<PackageReference Include="TaskScheduler" Version="2.11.0" />
|
||||||
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -26,11 +28,10 @@
|
|||||||
<EmbeddedResource Include="Sample\clash_tun_yaml" />
|
<EmbeddedResource Include="Sample\clash_tun_yaml" />
|
||||||
<EmbeddedResource Include="Sample\custom_routing_black" />
|
<EmbeddedResource Include="Sample\custom_routing_black" />
|
||||||
<EmbeddedResource Include="Sample\custom_routing_global" />
|
<EmbeddedResource Include="Sample\custom_routing_global" />
|
||||||
<EmbeddedResource Include="Sample\custom_routing_locked" />
|
|
||||||
<EmbeddedResource Include="Sample\custom_routing_rules" />
|
|
||||||
<EmbeddedResource Include="Sample\custom_routing_white" />
|
<EmbeddedResource Include="Sample\custom_routing_white" />
|
||||||
<EmbeddedResource Include="Sample\dns_singbox_normal" />
|
<EmbeddedResource Include="Sample\dns_singbox_normal" />
|
||||||
<EmbeddedResource Include="Sample\dns_v2ray_normal" />
|
<EmbeddedResource Include="Sample\dns_v2ray_normal" />
|
||||||
|
<EmbeddedResource Include="Sample\pac" />
|
||||||
<EmbeddedResource Include="Sample\SampleClientConfig" />
|
<EmbeddedResource Include="Sample\SampleClientConfig" />
|
||||||
<EmbeddedResource Include="Sample\SampleHttpRequest" />
|
<EmbeddedResource Include="Sample\SampleHttpRequest" />
|
||||||
<EmbeddedResource Include="Sample\SampleHttpResponse" />
|
<EmbeddedResource Include="Sample\SampleHttpResponse" />
|
||||||
@@ -41,14 +42,9 @@
|
|||||||
<EmbeddedResource Include="Sample\tun_singbox_dns" />
|
<EmbeddedResource Include="Sample\tun_singbox_dns" />
|
||||||
<EmbeddedResource Include="Sample\tun_singbox_inbound" />
|
<EmbeddedResource Include="Sample\tun_singbox_inbound" />
|
||||||
<EmbeddedResource Include="Sample\tun_singbox_rules" />
|
<EmbeddedResource Include="Sample\tun_singbox_rules" />
|
||||||
|
<EmbeddedResource Include="Sample\linux_autostart_config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\PacLib\PacLib.csproj" />
|
|
||||||
<ProjectReference Include="..\ProtosLib\ProtosLib.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Update="Resx\ResUI.Designer.cs">
|
<Compile Update="Resx\ResUI.Designer.cs">
|
||||||
<DependentUpon>ResUI.resx</DependentUpon>
|
<DependentUpon>ResUI.resx</DependentUpon>
|
||||||
@@ -62,6 +58,9 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Update="Resx\ResUI.hu.resx">
|
||||||
|
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||||
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Update="Resx\ResUI.resx">
|
<EmbeddedResource Update="Resx\ResUI.resx">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<LastGenOutput>ResUI.Designer.cs</LastGenOutput>
|
<LastGenOutput>ResUI.Designer.cs</LastGenOutput>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace ServiceLib.Services.CoreConfig
|
namespace ServiceLib.Services.CoreConfig
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Core configuration file processing class
|
/// Core configuration file processing class
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
public class CoreConfigClashService
|
public class CoreConfigClashService
|
||||||
{
|
{
|
||||||
private Config _config;
|
private Config _config;
|
||||||
|
private static readonly string _tag = "CoreConfigClashService";
|
||||||
|
|
||||||
public CoreConfigClashService(Config config)
|
public CoreConfigClashService(Config config)
|
||||||
{
|
{
|
||||||
@@ -66,7 +67,7 @@
|
|||||||
txtFile = txtFile.Replace(tagYamlStr1, tagYamlStr2);
|
txtFile = txtFile.Replace(tagYamlStr1, tagYamlStr2);
|
||||||
|
|
||||||
//YAML anchors
|
//YAML anchors
|
||||||
if (txtFile.Contains("<<:") && txtFile.Contains("*") && txtFile.Contains("&"))
|
if (txtFile.Contains("<<:") && txtFile.Contains('*') && txtFile.Contains('&'))
|
||||||
{
|
{
|
||||||
txtFile = YamlUtils.PreprocessYaml(txtFile);
|
txtFile = YamlUtils.PreprocessYaml(txtFile);
|
||||||
}
|
}
|
||||||
@@ -78,17 +79,15 @@
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//port
|
//mixed-port
|
||||||
fileContent["port"] = AppHandler.Instance.GetLocalPort(EInboundProtocol.http);
|
fileContent["mixed-port"] = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
|
||||||
//socks-port
|
|
||||||
fileContent["socks-port"] = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
|
|
||||||
//log-level
|
//log-level
|
||||||
fileContent["log-level"] = GetLogLevel(_config.CoreBasicItem.Loglevel);
|
fileContent["log-level"] = GetLogLevel(_config.CoreBasicItem.Loglevel);
|
||||||
|
|
||||||
//external-controller
|
//external-controller
|
||||||
fileContent["external-controller"] = $"{Global.Loopback}:{AppHandler.Instance.StatePort2}";
|
fileContent["external-controller"] = $"{Global.Loopback}:{AppHandler.Instance.StatePort2}";
|
||||||
//allow-lan
|
//allow-lan
|
||||||
if (_config.Inbound[0].AllowLANConn)
|
if (_config.Inbound.First().AllowLANConn)
|
||||||
{
|
{
|
||||||
fileContent["allow-lan"] = "true";
|
fileContent["allow-lan"] = "true";
|
||||||
fileContent["bind-address"] = "*";
|
fileContent["bind-address"] = "*";
|
||||||
@@ -133,7 +132,7 @@
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog("GenerateClientConfigClash-Mixin", ex);
|
Logging.SaveLog($"{_tag}-Mixin", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
var txtFileNew = YamlUtils.ToYaml(fileContent).Replace(tagYamlStr2, tagYamlStr3);
|
var txtFileNew = YamlUtils.ToYaml(fileContent).Replace(tagYamlStr2, tagYamlStr3);
|
||||||
@@ -153,7 +152,7 @@
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog("GenerateClientConfigClash", ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
|
|
||||||
@@ -7,6 +7,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
public class CoreConfigSingboxService
|
public class CoreConfigSingboxService
|
||||||
{
|
{
|
||||||
private Config _config;
|
private Config _config;
|
||||||
|
private static readonly string _tag = "CoreConfigSingboxService";
|
||||||
|
|
||||||
public CoreConfigSingboxService(Config config)
|
public CoreConfigSingboxService(Config config)
|
||||||
{
|
{
|
||||||
@@ -26,7 +27,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
ret.Msg = ResUI.CheckServerSettings;
|
ret.Msg = ResUI.CheckServerSettings;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if (node.GetNetwork() is nameof(ETransport.kcp) or nameof(ETransport.splithttp))
|
if (node.GetNetwork() is nameof(ETransport.kcp) or nameof(ETransport.xhttp))
|
||||||
{
|
{
|
||||||
ret.Msg = ResUI.Incorrectconfiguration + $" - {node.GetNetwork()}";
|
ret.Msg = ResUI.Incorrectconfiguration + $" - {node.GetNetwork()}";
|
||||||
return ret;
|
return ret;
|
||||||
@@ -52,7 +53,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
|
|
||||||
await GenInbounds(singboxConfig);
|
await GenInbounds(singboxConfig);
|
||||||
|
|
||||||
await GenOutbound(node, singboxConfig.outbounds[0]);
|
await GenOutbound(node, singboxConfig.outbounds.First());
|
||||||
|
|
||||||
await GenMoreOutbounds(node, singboxConfig);
|
await GenMoreOutbounds(node, singboxConfig);
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog("GenerateClientConfig4Singbox", ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -90,8 +91,8 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
|
|
||||||
ret.Msg = ResUI.InitialConfiguration;
|
ret.Msg = ResUI.InitialConfiguration;
|
||||||
|
|
||||||
string result = Utils.GetEmbedText(Global.SingboxSampleClient);
|
var result = Utils.GetEmbedText(Global.SingboxSampleClient);
|
||||||
string txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound);
|
var txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound);
|
||||||
if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty())
|
if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
||||||
@@ -114,15 +115,15 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
await GenLog(singboxConfig);
|
await GenLog(singboxConfig);
|
||||||
//GenDns(new(), singboxConfig);
|
//GenDns(new(), singboxConfig);
|
||||||
singboxConfig.inbounds.Clear(); // Remove "proxy" service for speedtest, avoiding port conflicts.
|
singboxConfig.inbounds.Clear();
|
||||||
singboxConfig.outbounds.RemoveAt(0);
|
singboxConfig.outbounds.RemoveAt(0);
|
||||||
|
|
||||||
int httpPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
|
var initPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
|
||||||
|
|
||||||
foreach (var it in selecteds)
|
foreach (var it in selecteds)
|
||||||
{
|
{
|
||||||
@@ -144,8 +145,8 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
//find unused port
|
//find unused port
|
||||||
var port = httpPort;
|
var port = initPort;
|
||||||
for (int k = httpPort; k < Global.MaxPort; k++)
|
for (int k = initPort; k < Global.MaxPort; k++)
|
||||||
{
|
{
|
||||||
if (lstIpEndPoints?.FindIndex(_it => _it.Port == k) >= 0)
|
if (lstIpEndPoints?.FindIndex(_it => _it.Port == k) >= 0)
|
||||||
{
|
{
|
||||||
@@ -157,7 +158,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
//found
|
//found
|
||||||
port = k;
|
port = k;
|
||||||
httpPort = port + 1;
|
initPort = port + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +175,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
{
|
{
|
||||||
listen = Global.Loopback,
|
listen = Global.Loopback,
|
||||||
listen_port = port,
|
listen_port = port,
|
||||||
type = EInboundProtocol.http.ToString(),
|
type = EInboundProtocol.mixed.ToString(),
|
||||||
};
|
};
|
||||||
inbound.tag = inbound.type + inbound.listen_port.ToString();
|
inbound.tag = inbound.type + inbound.listen_port.ToString();
|
||||||
singboxConfig.inbounds.Add(inbound);
|
singboxConfig.inbounds.Add(inbound);
|
||||||
@@ -235,7 +236,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -312,7 +313,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
var outbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound);
|
var outbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound);
|
||||||
await GenOutbound(item, outbound);
|
await GenOutbound(item, outbound);
|
||||||
outbound.tag = $"{Global.ProxyTag}-{tagProxy.Count + 1}";
|
outbound.tag = $"{Global.ProxyTag}-{tagProxy.Count + 1}";
|
||||||
singboxConfig.outbounds.Add(outbound);
|
singboxConfig.outbounds.Insert(0, outbound);
|
||||||
tagProxy.Add(outbound.tag);
|
tagProxy.Add(outbound.tag);
|
||||||
}
|
}
|
||||||
if (tagProxy.Count <= 0)
|
if (tagProxy.Count <= 0)
|
||||||
@@ -332,7 +333,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
outbounds = tagProxy,
|
outbounds = tagProxy,
|
||||||
interrupt_exist_connections = false,
|
interrupt_exist_connections = false,
|
||||||
};
|
};
|
||||||
singboxConfig.outbounds.Add(outUrltest);
|
singboxConfig.outbounds.Insert(0, outUrltest);
|
||||||
|
|
||||||
//add selector outbound
|
//add selector outbound
|
||||||
var outSelector = new Outbound4Sbox
|
var outSelector = new Outbound4Sbox
|
||||||
@@ -343,7 +344,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
interrupt_exist_connections = false,
|
interrupt_exist_connections = false,
|
||||||
};
|
};
|
||||||
outSelector.outbounds.Insert(0, outUrltest.tag);
|
outSelector.outbounds.Insert(0, outUrltest.tag);
|
||||||
singboxConfig.outbounds.Add(outSelector);
|
singboxConfig.outbounds.Insert(0, outSelector);
|
||||||
|
|
||||||
ret.Success = true;
|
ret.Success = true;
|
||||||
ret.Data = JsonUtils.Serialize(singboxConfig);
|
ret.Data = JsonUtils.Serialize(singboxConfig);
|
||||||
@@ -351,7 +352,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -409,7 +410,9 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
{
|
{
|
||||||
await GenInbounds(singboxConfig);
|
await GenInbounds(singboxConfig);
|
||||||
await GenExperimental(singboxConfig);
|
await GenExperimental(singboxConfig);
|
||||||
JsonUtils.ToFile(singboxConfig, fileName, false);
|
|
||||||
|
var content = JsonUtils.Serialize(singboxConfig, true);
|
||||||
|
await File.WriteAllTextAsync(fileName, content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -430,7 +433,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -440,7 +443,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
|
|
||||||
#region private gen function
|
#region private gen function
|
||||||
|
|
||||||
public async Task<int> GenLog(SingboxConfig singboxConfig)
|
private async Task<int> GenLog(SingboxConfig singboxConfig)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -471,7 +474,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -484,57 +487,50 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
singboxConfig.inbounds = [];
|
singboxConfig.inbounds = [];
|
||||||
|
|
||||||
if (!_config.TunModeItem.EnableTun
|
if (!_config.TunModeItem.EnableTun
|
||||||
|| _config.TunModeItem.EnableTun && _config.TunModeItem.EnableExInbound && _config.RunningCoreType == ECoreType.sing_box)
|
|| (_config.TunModeItem.EnableTun && _config.TunModeItem.EnableExInbound && _config.RunningCoreType == ECoreType.sing_box))
|
||||||
{
|
{
|
||||||
var inbound = new Inbound4Sbox()
|
var inbound = new Inbound4Sbox()
|
||||||
{
|
{
|
||||||
type = EInboundProtocol.socks.ToString(),
|
type = EInboundProtocol.mixed.ToString(),
|
||||||
tag = EInboundProtocol.socks.ToString(),
|
tag = EInboundProtocol.socks.ToString(),
|
||||||
listen = Global.Loopback,
|
listen = Global.Loopback,
|
||||||
};
|
};
|
||||||
singboxConfig.inbounds.Add(inbound);
|
singboxConfig.inbounds.Add(inbound);
|
||||||
|
|
||||||
inbound.listen_port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
|
inbound.listen_port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
|
||||||
inbound.sniff = _config.Inbound[0].SniffingEnabled;
|
inbound.sniff = _config.Inbound.First().SniffingEnabled;
|
||||||
inbound.sniff_override_destination = _config.Inbound[0].RouteOnly ? false : _config.Inbound[0].SniffingEnabled;
|
inbound.sniff_override_destination = _config.Inbound.First().RouteOnly ? false : _config.Inbound.First().SniffingEnabled;
|
||||||
inbound.domain_strategy = Utils.IsNullOrEmpty(_config.RoutingBasicItem.DomainStrategy4Singbox) ? null : _config.RoutingBasicItem.DomainStrategy4Singbox;
|
inbound.domain_strategy = Utils.IsNullOrEmpty(_config.RoutingBasicItem.DomainStrategy4Singbox) ? null : _config.RoutingBasicItem.DomainStrategy4Singbox;
|
||||||
|
|
||||||
if (_config.RoutingBasicItem.EnableRoutingAdvanced)
|
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
||||||
|
if (Utils.IsNotEmpty(routing.DomainStrategy4Singbox))
|
||||||
{
|
{
|
||||||
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
inbound.domain_strategy = routing.DomainStrategy4Singbox;
|
||||||
if (Utils.IsNotEmpty(routing.DomainStrategy4Singbox))
|
|
||||||
{
|
|
||||||
inbound.domain_strategy = routing.DomainStrategy4Singbox;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//http
|
if (_config.Inbound.First().SecondLocalPortEnabled)
|
||||||
var inbound2 = GetInbound(inbound, EInboundProtocol.http, false);
|
|
||||||
singboxConfig.inbounds.Add(inbound2);
|
|
||||||
|
|
||||||
if (_config.Inbound[0].AllowLANConn)
|
|
||||||
{
|
{
|
||||||
if (_config.Inbound[0].NewPort4LAN)
|
var inbound2 = GetInbound(inbound, EInboundProtocol.socks2, true);
|
||||||
|
singboxConfig.inbounds.Add(inbound2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_config.Inbound.First().AllowLANConn)
|
||||||
|
{
|
||||||
|
if (_config.Inbound.First().NewPort4LAN)
|
||||||
{
|
{
|
||||||
var inbound3 = GetInbound(inbound, EInboundProtocol.socks2, true);
|
var inbound3 = GetInbound(inbound, EInboundProtocol.socks3, true);
|
||||||
inbound3.listen = listen;
|
inbound3.listen = listen;
|
||||||
singboxConfig.inbounds.Add(inbound3);
|
singboxConfig.inbounds.Add(inbound3);
|
||||||
|
|
||||||
var inbound4 = GetInbound(inbound, EInboundProtocol.http2, false);
|
|
||||||
inbound4.listen = listen;
|
|
||||||
singboxConfig.inbounds.Add(inbound4);
|
|
||||||
|
|
||||||
//auth
|
//auth
|
||||||
if (Utils.IsNotEmpty(_config.Inbound[0].User) && Utils.IsNotEmpty(_config.Inbound[0].Pass))
|
if (Utils.IsNotEmpty(_config.Inbound.First().User) && Utils.IsNotEmpty(_config.Inbound.First().Pass))
|
||||||
{
|
{
|
||||||
inbound3.users = new() { new() { username = _config.Inbound[0].User, password = _config.Inbound[0].Pass } };
|
inbound3.users = new() { new() { username = _config.Inbound.First().User, password = _config.Inbound.First().Pass } };
|
||||||
inbound4.users = new() { new() { username = _config.Inbound[0].User, password = _config.Inbound[0].Pass } };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
inbound.listen = listen;
|
inbound.listen = listen;
|
||||||
inbound2.listen = listen;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -543,22 +539,23 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
{
|
{
|
||||||
if (_config.TunModeItem.Mtu <= 0)
|
if (_config.TunModeItem.Mtu <= 0)
|
||||||
{
|
{
|
||||||
_config.TunModeItem.Mtu = Utils.ToInt(Global.TunMtus[0]);
|
_config.TunModeItem.Mtu = Utils.ToInt(Global.TunMtus.First());
|
||||||
}
|
}
|
||||||
if (Utils.IsNullOrEmpty(_config.TunModeItem.Stack))
|
if (Utils.IsNullOrEmpty(_config.TunModeItem.Stack))
|
||||||
{
|
{
|
||||||
_config.TunModeItem.Stack = Global.TunStacks[0];
|
_config.TunModeItem.Stack = Global.TunStacks.First();
|
||||||
}
|
}
|
||||||
|
|
||||||
var tunInbound = JsonUtils.Deserialize<Inbound4Sbox>(Utils.GetEmbedText(Global.TunSingboxInboundFileName)) ?? new Inbound4Sbox { };
|
var tunInbound = JsonUtils.Deserialize<Inbound4Sbox>(Utils.GetEmbedText(Global.TunSingboxInboundFileName)) ?? new Inbound4Sbox { };
|
||||||
|
tunInbound.interface_name = Utils.IsOSX() ? $"utun{new Random().Next(99)}" : "singbox_tun";
|
||||||
tunInbound.mtu = _config.TunModeItem.Mtu;
|
tunInbound.mtu = _config.TunModeItem.Mtu;
|
||||||
tunInbound.strict_route = _config.TunModeItem.StrictRoute;
|
tunInbound.strict_route = _config.TunModeItem.StrictRoute;
|
||||||
tunInbound.stack = _config.TunModeItem.Stack;
|
tunInbound.stack = _config.TunModeItem.Stack;
|
||||||
tunInbound.sniff = _config.Inbound[0].SniffingEnabled;
|
tunInbound.sniff = _config.Inbound.First().SniffingEnabled;
|
||||||
//tunInbound.sniff_override_destination = _config.inbound[0].routeOnly ? false : _config.inbound[0].sniffingEnabled;
|
//tunInbound.sniff_override_destination = _config.inbound.First().routeOnly ? false : _config.inbound.First().sniffingEnabled;
|
||||||
if (_config.TunModeItem.EnableIPv6Address == false)
|
if (_config.TunModeItem.EnableIPv6Address == false)
|
||||||
{
|
{
|
||||||
tunInbound.inet6_address = null;
|
tunInbound.address = ["172.18.0.1/30"];
|
||||||
}
|
}
|
||||||
|
|
||||||
singboxConfig.inbounds.Add(tunInbound);
|
singboxConfig.inbounds.Add(tunInbound);
|
||||||
@@ -566,7 +563,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -576,11 +573,11 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
var inbound = JsonUtils.DeepCopy(inItem);
|
var inbound = JsonUtils.DeepCopy(inItem);
|
||||||
inbound.tag = protocol.ToString();
|
inbound.tag = protocol.ToString();
|
||||||
inbound.listen_port = inItem.listen_port + (int)protocol;
|
inbound.listen_port = inItem.listen_port + (int)protocol;
|
||||||
inbound.type = bSocks ? EInboundProtocol.socks.ToString() : EInboundProtocol.http.ToString();
|
inbound.type = EInboundProtocol.mixed.ToString();
|
||||||
return inbound;
|
return inbound;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> GenOutbound(ProfileItem node, Outbound4Sbox outbound)
|
private async Task<int> GenOutbound(ProfileItem node, Outbound4Sbox outbound)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -699,12 +696,12 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> GenOutboundMux(ProfileItem node, Outbound4Sbox outbound)
|
private async Task<int> GenOutboundMux(ProfileItem node, Outbound4Sbox outbound)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -722,12 +719,12 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> GenOutboundTls(ProfileItem node, Outbound4Sbox outbound)
|
private async Task<int> GenOutboundTls(ProfileItem node, Outbound4Sbox outbound)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -772,12 +769,12 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> GenOutboundTransport(ProfileItem node, Outbound4Sbox outbound)
|
private async Task<int> GenOutboundTransport(ProfileItem node, Outbound4Sbox outbound)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -849,7 +846,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -869,7 +866,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
//current proxy
|
//current proxy
|
||||||
var outbound = singboxConfig.outbounds[0];
|
var outbound = singboxConfig.outbounds.First();
|
||||||
var txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound);
|
var txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound);
|
||||||
|
|
||||||
//Previous proxy
|
//Previous proxy
|
||||||
@@ -901,7 +898,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -912,7 +909,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var dnsOutbound = "dns_out";
|
var dnsOutbound = "dns_out";
|
||||||
if (!_config.Inbound[0].SniffingEnabled)
|
if (!_config.Inbound.First().SniffingEnabled)
|
||||||
{
|
{
|
||||||
singboxConfig.route.rules.Add(new()
|
singboxConfig.route.rules.Add(new()
|
||||||
{
|
{
|
||||||
@@ -958,28 +955,13 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_config.RoutingBasicItem.EnableRoutingAdvanced)
|
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
||||||
|
if (routing != null)
|
||||||
{
|
{
|
||||||
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);
|
||||||
if (routing != null)
|
foreach (var item in rules ?? [])
|
||||||
{
|
{
|
||||||
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);
|
if (item.Enabled)
|
||||||
foreach (var item in rules ?? [])
|
|
||||||
{
|
|
||||||
if (item.Enabled)
|
|
||||||
{
|
|
||||||
await GenRoutingUserRule(item, singboxConfig.route.rules);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var lockedItem = await ConfigHandler.GetLockedRoutingItem(_config);
|
|
||||||
if (lockedItem != null)
|
|
||||||
{
|
|
||||||
var rules = JsonUtils.Deserialize<List<RulesItem>>(lockedItem.RuleSet);
|
|
||||||
foreach (var item in rules ?? [])
|
|
||||||
{
|
{
|
||||||
await GenRoutingUserRule(item, singboxConfig.route.rules);
|
await GenRoutingUserRule(item, singboxConfig.route.rules);
|
||||||
}
|
}
|
||||||
@@ -988,7 +970,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1019,7 +1001,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> GenRoutingUserRule(RulesItem item, List<Rule4Sbox> rules)
|
private async Task<int> GenRoutingUserRule(RulesItem item, List<Rule4Sbox> rules)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1104,7 +1086,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1177,7 +1159,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> GenDns(ProfileItem? node, SingboxConfig singboxConfig)
|
private async Task<int> GenDns(ProfileItem? node, SingboxConfig singboxConfig)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1203,12 +1185,12 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> GenDnsDomains(ProfileItem? node, SingboxConfig singboxConfig, DNSItem? dNSItem)
|
private async Task<int> GenDnsDomains(ProfileItem? node, SingboxConfig singboxConfig, DNSItem? dNSItem)
|
||||||
{
|
{
|
||||||
var dns4Sbox = singboxConfig.dns ?? new();
|
var dns4Sbox = singboxConfig.dns ?? new();
|
||||||
dns4Sbox.servers ??= [];
|
dns4Sbox.servers ??= [];
|
||||||
@@ -1261,7 +1243,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> GenExperimental(SingboxConfig singboxConfig)
|
private async Task<int> GenExperimental(SingboxConfig singboxConfig)
|
||||||
{
|
{
|
||||||
//if (_config.guiItem.enableStatistics)
|
//if (_config.guiItem.enableStatistics)
|
||||||
{
|
{
|
||||||
@@ -1334,20 +1316,18 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
|
|
||||||
//load custom ruleset file
|
//load custom ruleset file
|
||||||
List<Ruleset4Sbox> customRulesets = [];
|
List<Ruleset4Sbox> customRulesets = [];
|
||||||
if (_config.RoutingBasicItem.EnableRoutingAdvanced)
|
|
||||||
|
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
||||||
|
if (Utils.IsNotEmpty(routing.CustomRulesetPath4Singbox))
|
||||||
{
|
{
|
||||||
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
var result = Utils.LoadResource(routing.CustomRulesetPath4Singbox);
|
||||||
if (Utils.IsNotEmpty(routing.CustomRulesetPath4Singbox))
|
if (Utils.IsNotEmpty(result))
|
||||||
{
|
{
|
||||||
var result = Utils.LoadResource(routing.CustomRulesetPath4Singbox);
|
customRulesets = (JsonUtils.Deserialize<List<Ruleset4Sbox>>(result) ?? [])
|
||||||
if (Utils.IsNotEmpty(result))
|
.Where(t => t.tag != null)
|
||||||
{
|
.Where(t => t.type != null)
|
||||||
customRulesets = (JsonUtils.Deserialize<List<Ruleset4Sbox>>(result) ?? [])
|
.Where(t => t.format != null)
|
||||||
.Where(t => t.tag != null)
|
.ToList();
|
||||||
.Where(t => t.type != null)
|
|
||||||
.Where(t => t.format != null)
|
|
||||||
.ToList();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
public class CoreConfigV2rayService
|
public class CoreConfigV2rayService
|
||||||
{
|
{
|
||||||
private Config _config;
|
private Config _config;
|
||||||
|
private static readonly string _tag = "CoreConfigV2rayService";
|
||||||
|
|
||||||
public CoreConfigV2rayService(Config config)
|
public CoreConfigV2rayService(Config config)
|
||||||
{
|
{
|
||||||
@@ -27,6 +28,12 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node.GetNetwork() is nameof(ETransport.quic))
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.Incorrectconfiguration + $" - {node.GetNetwork()}";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
ret.Msg = ResUI.InitialConfiguration;
|
ret.Msg = ResUI.InitialConfiguration;
|
||||||
|
|
||||||
var result = Utils.GetEmbedText(Global.V2raySampleClient);
|
var result = Utils.GetEmbedText(Global.V2raySampleClient);
|
||||||
@@ -49,7 +56,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
|
|
||||||
await GenRouting(v2rayConfig);
|
await GenRouting(v2rayConfig);
|
||||||
|
|
||||||
await GenOutbound(node, v2rayConfig.outbounds[0]);
|
await GenOutbound(node, v2rayConfig.outbounds.First());
|
||||||
|
|
||||||
await GenMoreOutbounds(node, v2rayConfig);
|
await GenMoreOutbounds(node, v2rayConfig);
|
||||||
|
|
||||||
@@ -64,7 +71,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog("GenerateClientConfig4V2ray", ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -147,7 +154,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
var outbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
|
var outbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
|
||||||
await GenOutbound(item, outbound);
|
await GenOutbound(item, outbound);
|
||||||
outbound.tag = $"{Global.ProxyTag}-{tagProxy.Count + 1}";
|
outbound.tag = $"{Global.ProxyTag}-{tagProxy.Count + 1}";
|
||||||
v2rayConfig.outbounds.Add(outbound);
|
v2rayConfig.outbounds.Insert(0, outbound);
|
||||||
tagProxy.Add(outbound.tag);
|
tagProxy.Add(outbound.tag);
|
||||||
}
|
}
|
||||||
if (tagProxy.Count <= 0)
|
if (tagProxy.Count <= 0)
|
||||||
@@ -175,15 +182,12 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
rule.balancerTag = balancer.tag;
|
rule.balancerTag = balancer.tag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
v2rayConfig.routing.rules.Add(new()
|
||||||
{
|
{
|
||||||
v2rayConfig.routing.rules.Add(new()
|
network = "tcp,udp",
|
||||||
{
|
balancerTag = balancer.tag,
|
||||||
network = "tcp,udp",
|
type = "field"
|
||||||
balancerTag = balancer.tag,
|
});
|
||||||
type = "field"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.Success = true;
|
ret.Success = true;
|
||||||
ret.Data = JsonUtils.Serialize(v2rayConfig);
|
ret.Data = JsonUtils.Serialize(v2rayConfig);
|
||||||
@@ -191,7 +195,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -210,8 +214,8 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
|
|
||||||
ret.Msg = ResUI.InitialConfiguration;
|
ret.Msg = ResUI.InitialConfiguration;
|
||||||
|
|
||||||
string result = Utils.GetEmbedText(Global.V2raySampleClient);
|
var result = Utils.GetEmbedText(Global.V2raySampleClient);
|
||||||
string txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound);
|
var txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound);
|
||||||
if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty())
|
if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
||||||
@@ -234,14 +238,15 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
await GenLog(v2rayConfig);
|
await GenLog(v2rayConfig);
|
||||||
v2rayConfig.inbounds.Clear(); // Remove "proxy" service for speedtest, avoiding port conflicts.
|
v2rayConfig.inbounds.Clear();
|
||||||
v2rayConfig.outbounds.RemoveAt(0);
|
v2rayConfig.outbounds.Clear();
|
||||||
|
v2rayConfig.routing.rules.Clear();
|
||||||
|
|
||||||
int httpPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
|
var initPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
|
||||||
|
|
||||||
foreach (var it in selecteds)
|
foreach (var it in selecteds)
|
||||||
{
|
{
|
||||||
@@ -263,8 +268,8 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
//find unused port
|
//find unused port
|
||||||
var port = httpPort;
|
var port = initPort;
|
||||||
for (int k = httpPort; k < Global.MaxPort; k++)
|
for (var k = initPort; k < Global.MaxPort; k++)
|
||||||
{
|
{
|
||||||
if (lstIpEndPoints?.FindIndex(_it => _it.Port == k) >= 0)
|
if (lstIpEndPoints?.FindIndex(_it => _it.Port == k) >= 0)
|
||||||
{
|
{
|
||||||
@@ -276,7 +281,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
//found
|
//found
|
||||||
port = k;
|
port = k;
|
||||||
httpPort = port + 1;
|
initPort = port + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,16 +293,6 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
it.Port = port;
|
it.Port = port;
|
||||||
it.AllowTest = true;
|
it.AllowTest = true;
|
||||||
|
|
||||||
//inbound
|
|
||||||
Inbounds4Ray inbound = new()
|
|
||||||
{
|
|
||||||
listen = Global.Loopback,
|
|
||||||
port = port,
|
|
||||||
protocol = EInboundProtocol.http.ToString(),
|
|
||||||
};
|
|
||||||
inbound.tag = inbound.protocol + inbound.port.ToString();
|
|
||||||
v2rayConfig.inbounds.Add(inbound);
|
|
||||||
|
|
||||||
//outbound
|
//outbound
|
||||||
if (item is null)
|
if (item is null)
|
||||||
{
|
{
|
||||||
@@ -320,6 +315,16 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//inbound
|
||||||
|
Inbounds4Ray inbound = new()
|
||||||
|
{
|
||||||
|
listen = Global.Loopback,
|
||||||
|
port = port,
|
||||||
|
protocol = EInboundProtocol.socks.ToString(),
|
||||||
|
};
|
||||||
|
inbound.tag = inbound.protocol + inbound.port.ToString();
|
||||||
|
v2rayConfig.inbounds.Add(inbound);
|
||||||
|
|
||||||
var outbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
|
var outbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
|
||||||
await GenOutbound(item, outbound);
|
await GenOutbound(item, outbound);
|
||||||
outbound.tag = Global.ProxyTag + inbound.port.ToString();
|
outbound.tag = Global.ProxyTag + inbound.port.ToString();
|
||||||
@@ -342,7 +347,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -352,7 +357,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
|
|
||||||
#region private gen function
|
#region private gen function
|
||||||
|
|
||||||
public async Task<int> GenLog(V2rayConfig v2rayConfig)
|
private async Task<int> GenLog(V2rayConfig v2rayConfig)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -366,63 +371,57 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
v2rayConfig.log.loglevel = _config.CoreBasicItem.Loglevel;
|
v2rayConfig.log.loglevel = _config.CoreBasicItem.Loglevel;
|
||||||
v2rayConfig.log.access = "";
|
v2rayConfig.log.access = null;
|
||||||
v2rayConfig.log.error = "";
|
v2rayConfig.log.error = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> GenInbounds(V2rayConfig v2rayConfig)
|
private async Task<int> GenInbounds(V2rayConfig v2rayConfig)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var listen = "0.0.0.0";
|
var listen = "0.0.0.0";
|
||||||
v2rayConfig.inbounds = [];
|
v2rayConfig.inbounds = [];
|
||||||
|
|
||||||
Inbounds4Ray? inbound = GetInbound(_config.Inbound[0], EInboundProtocol.socks, true);
|
var inbound = GetInbound(_config.Inbound.First(), EInboundProtocol.socks, true);
|
||||||
v2rayConfig.inbounds.Add(inbound);
|
v2rayConfig.inbounds.Add(inbound);
|
||||||
|
|
||||||
//http
|
if (_config.Inbound.First().SecondLocalPortEnabled)
|
||||||
Inbounds4Ray? inbound2 = GetInbound(_config.Inbound[0], EInboundProtocol.http, false);
|
|
||||||
v2rayConfig.inbounds.Add(inbound2);
|
|
||||||
|
|
||||||
if (_config.Inbound[0].AllowLANConn)
|
|
||||||
{
|
{
|
||||||
if (_config.Inbound[0].NewPort4LAN)
|
var inbound2 = GetInbound(_config.Inbound.First(), EInboundProtocol.socks2, true);
|
||||||
|
v2rayConfig.inbounds.Add(inbound2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_config.Inbound.First().AllowLANConn)
|
||||||
|
{
|
||||||
|
if (_config.Inbound.First().NewPort4LAN)
|
||||||
{
|
{
|
||||||
var inbound3 = GetInbound(_config.Inbound[0], EInboundProtocol.socks2, true);
|
var inbound3 = GetInbound(_config.Inbound.First(), EInboundProtocol.socks3, true);
|
||||||
inbound3.listen = listen;
|
inbound3.listen = listen;
|
||||||
v2rayConfig.inbounds.Add(inbound3);
|
v2rayConfig.inbounds.Add(inbound3);
|
||||||
|
|
||||||
var inbound4 = GetInbound(_config.Inbound[0], EInboundProtocol.http2, false);
|
|
||||||
inbound4.listen = listen;
|
|
||||||
v2rayConfig.inbounds.Add(inbound4);
|
|
||||||
|
|
||||||
//auth
|
//auth
|
||||||
if (Utils.IsNotEmpty(_config.Inbound[0].User) && Utils.IsNotEmpty(_config.Inbound[0].Pass))
|
if (Utils.IsNotEmpty(_config.Inbound.First().User) && Utils.IsNotEmpty(_config.Inbound.First().Pass))
|
||||||
{
|
{
|
||||||
inbound3.settings.auth = "password";
|
inbound3.settings.auth = "password";
|
||||||
inbound3.settings.accounts = new List<AccountsItem4Ray> { new AccountsItem4Ray() { user = _config.Inbound[0].User, pass = _config.Inbound[0].Pass } };
|
inbound3.settings.accounts = new List<AccountsItem4Ray> { new AccountsItem4Ray() { user = _config.Inbound.First().User, pass = _config.Inbound.First().Pass } };
|
||||||
|
|
||||||
inbound4.settings.auth = "password";
|
|
||||||
inbound4.settings.accounts = new List<AccountsItem4Ray> { new AccountsItem4Ray() { user = _config.Inbound[0].User, pass = _config.Inbound[0].Pass } };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
inbound.listen = listen;
|
inbound.listen = listen;
|
||||||
inbound2.listen = listen;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -442,7 +441,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
inbound.tag = protocol.ToString();
|
inbound.tag = protocol.ToString();
|
||||||
inbound.port = inItem.LocalPort + (int)protocol;
|
inbound.port = inItem.LocalPort + (int)protocol;
|
||||||
inbound.protocol = bSocks ? EInboundProtocol.socks.ToString() : EInboundProtocol.http.ToString();
|
inbound.protocol = EInboundProtocol.socks.ToString();
|
||||||
inbound.settings.udp = inItem.UdpEnabled;
|
inbound.settings.udp = inItem.UdpEnabled;
|
||||||
inbound.sniffing.enabled = inItem.SniffingEnabled;
|
inbound.sniffing.enabled = inItem.SniffingEnabled;
|
||||||
inbound.sniffing.destOverride = inItem.DestOverride;
|
inbound.sniffing.destOverride = inItem.DestOverride;
|
||||||
@@ -460,33 +459,17 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
v2rayConfig.routing.domainStrategy = _config.RoutingBasicItem.DomainStrategy;
|
v2rayConfig.routing.domainStrategy = _config.RoutingBasicItem.DomainStrategy;
|
||||||
v2rayConfig.routing.domainMatcher = Utils.IsNullOrEmpty(_config.RoutingBasicItem.DomainMatcher) ? null : _config.RoutingBasicItem.DomainMatcher;
|
v2rayConfig.routing.domainMatcher = Utils.IsNullOrEmpty(_config.RoutingBasicItem.DomainMatcher) ? null : _config.RoutingBasicItem.DomainMatcher;
|
||||||
|
|
||||||
if (_config.RoutingBasicItem.EnableRoutingAdvanced)
|
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
||||||
|
if (routing != null)
|
||||||
{
|
{
|
||||||
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
if (Utils.IsNotEmpty(routing.DomainStrategy))
|
||||||
if (routing != null)
|
|
||||||
{
|
{
|
||||||
if (Utils.IsNotEmpty(routing.DomainStrategy))
|
v2rayConfig.routing.domainStrategy = routing.DomainStrategy;
|
||||||
{
|
|
||||||
v2rayConfig.routing.domainStrategy = routing.DomainStrategy;
|
|
||||||
}
|
|
||||||
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);
|
|
||||||
foreach (var item in rules)
|
|
||||||
{
|
|
||||||
if (item.Enabled)
|
|
||||||
{
|
|
||||||
var item2 = JsonUtils.Deserialize<RulesItem4Ray>(JsonUtils.Serialize(item));
|
|
||||||
await GenRoutingUserRule(item2, v2rayConfig);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);
|
||||||
else
|
foreach (var item in rules)
|
||||||
{
|
|
||||||
var lockedItem = await ConfigHandler.GetLockedRoutingItem(_config);
|
|
||||||
if (lockedItem != null)
|
|
||||||
{
|
{
|
||||||
var rules = JsonUtils.Deserialize<List<RulesItem>>(lockedItem.RuleSet);
|
if (item.Enabled)
|
||||||
foreach (var item in rules)
|
|
||||||
{
|
{
|
||||||
var item2 = JsonUtils.Deserialize<RulesItem4Ray>(JsonUtils.Serialize(item));
|
var item2 = JsonUtils.Deserialize<RulesItem4Ray>(JsonUtils.Serialize(item));
|
||||||
await GenRoutingUserRule(item2, v2rayConfig);
|
await GenRoutingUserRule(item2, v2rayConfig);
|
||||||
@@ -497,12 +480,12 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> GenRoutingUserRule(RulesItem4Ray? rule, V2rayConfig v2rayConfig)
|
private async Task<int> GenRoutingUserRule(RulesItem4Ray? rule, V2rayConfig v2rayConfig)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -575,15 +558,16 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> GenOutbound(ProfileItem node, Outbounds4Ray outbound)
|
private async Task<int> GenOutbound(ProfileItem node, Outbounds4Ray outbound)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var muxEnabled = _config.CoreBasicItem.MuxEnabled;
|
||||||
switch (node.ConfigType)
|
switch (node.ConfigType)
|
||||||
{
|
{
|
||||||
case EConfigType.VMess:
|
case EConfigType.VMess:
|
||||||
@@ -596,7 +580,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
vnextItem = outbound.settings.vnext[0];
|
vnextItem = outbound.settings.vnext.First();
|
||||||
}
|
}
|
||||||
vnextItem.address = node.Address;
|
vnextItem.address = node.Address;
|
||||||
vnextItem.port = node.Port;
|
vnextItem.port = node.Port;
|
||||||
@@ -609,7 +593,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
usersItem = vnextItem.users[0];
|
usersItem = vnextItem.users.First();
|
||||||
}
|
}
|
||||||
//远程服务器用户ID
|
//远程服务器用户ID
|
||||||
usersItem.id = node.Id;
|
usersItem.id = node.Id;
|
||||||
@@ -624,7 +608,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
usersItem.security = Global.DefaultSecurity;
|
usersItem.security = Global.DefaultSecurity;
|
||||||
}
|
}
|
||||||
|
|
||||||
await GenOutboundMux(node, outbound, _config.CoreBasicItem.MuxEnabled);
|
await GenOutboundMux(node, outbound, muxEnabled, muxEnabled);
|
||||||
|
|
||||||
outbound.settings.servers = null;
|
outbound.settings.servers = null;
|
||||||
break;
|
break;
|
||||||
@@ -639,7 +623,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
serversItem = outbound.settings.servers[0];
|
serversItem = outbound.settings.servers.First();
|
||||||
}
|
}
|
||||||
serversItem.address = node.Address;
|
serversItem.address = node.Address;
|
||||||
serversItem.port = node.Port;
|
serversItem.port = node.Port;
|
||||||
@@ -649,7 +633,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
serversItem.ota = false;
|
serversItem.ota = false;
|
||||||
serversItem.level = 1;
|
serversItem.level = 1;
|
||||||
|
|
||||||
await GenOutboundMux(node, outbound, false);
|
await GenOutboundMux(node, outbound);
|
||||||
|
|
||||||
outbound.settings.vnext = null;
|
outbound.settings.vnext = null;
|
||||||
break;
|
break;
|
||||||
@@ -665,7 +649,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
serversItem = outbound.settings.servers[0];
|
serversItem = outbound.settings.servers.First();
|
||||||
}
|
}
|
||||||
serversItem.address = node.Address;
|
serversItem.address = node.Address;
|
||||||
serversItem.port = node.Port;
|
serversItem.port = node.Port;
|
||||||
@@ -685,7 +669,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
serversItem.users = new List<SocksUsersItem4Ray>() { socksUsersItem };
|
serversItem.users = new List<SocksUsersItem4Ray>() { socksUsersItem };
|
||||||
}
|
}
|
||||||
|
|
||||||
await GenOutboundMux(node, outbound, false);
|
await GenOutboundMux(node, outbound);
|
||||||
|
|
||||||
outbound.settings.vnext = null;
|
outbound.settings.vnext = null;
|
||||||
break;
|
break;
|
||||||
@@ -700,7 +684,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
vnextItem = outbound.settings.vnext[0];
|
vnextItem = outbound.settings.vnext.First();
|
||||||
}
|
}
|
||||||
vnextItem.address = node.Address;
|
vnextItem.address = node.Address;
|
||||||
vnextItem.port = node.Port;
|
vnextItem.port = node.Port;
|
||||||
@@ -713,29 +697,21 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
usersItem = vnextItem.users[0];
|
usersItem = vnextItem.users.First();
|
||||||
}
|
}
|
||||||
usersItem.id = node.Id;
|
usersItem.id = node.Id;
|
||||||
usersItem.email = Global.UserEMail;
|
usersItem.email = Global.UserEMail;
|
||||||
usersItem.encryption = node.Security;
|
usersItem.encryption = node.Security;
|
||||||
|
|
||||||
await GenOutboundMux(node, outbound, _config.CoreBasicItem.MuxEnabled);
|
if (node.Flow.IsNullOrEmpty())
|
||||||
|
|
||||||
if (node.StreamSecurity == Global.StreamSecurityReality
|
|
||||||
|| node.StreamSecurity == Global.StreamSecurity)
|
|
||||||
{
|
{
|
||||||
if (Utils.IsNotEmpty(node.Flow))
|
await GenOutboundMux(node, outbound, muxEnabled, muxEnabled);
|
||||||
{
|
|
||||||
usersItem.flow = node.Flow;
|
|
||||||
|
|
||||||
await GenOutboundMux(node, outbound, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (node.StreamSecurity == Global.StreamSecurityReality && Utils.IsNullOrEmpty(node.Flow))
|
else
|
||||||
{
|
{
|
||||||
await GenOutboundMux(node, outbound, _config.CoreBasicItem.MuxEnabled);
|
usersItem.flow = node.Flow;
|
||||||
|
await GenOutboundMux(node, outbound, false, muxEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
outbound.settings.servers = null;
|
outbound.settings.servers = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -749,7 +725,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
serversItem = outbound.settings.servers[0];
|
serversItem = outbound.settings.servers.First();
|
||||||
}
|
}
|
||||||
serversItem.address = node.Address;
|
serversItem.address = node.Address;
|
||||||
serversItem.port = node.Port;
|
serversItem.port = node.Port;
|
||||||
@@ -758,7 +734,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
serversItem.ota = false;
|
serversItem.ota = false;
|
||||||
serversItem.level = 1;
|
serversItem.level = 1;
|
||||||
|
|
||||||
await GenOutboundMux(node, outbound, false);
|
await GenOutboundMux(node, outbound);
|
||||||
|
|
||||||
outbound.settings.vnext = null;
|
outbound.settings.vnext = null;
|
||||||
break;
|
break;
|
||||||
@@ -766,47 +742,51 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
outbound.protocol = Global.ProtocolTypes[node.ConfigType];
|
outbound.protocol = Global.ProtocolTypes[node.ConfigType];
|
||||||
await GenBoundStreamSettings(node, outbound.streamSettings);
|
await GenBoundStreamSettings(node, outbound);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> GenOutboundMux(ProfileItem node, Outbounds4Ray outbound, bool enabled)
|
private async Task<int> GenOutboundMux(ProfileItem node, Outbounds4Ray outbound, bool enabledTCP = false, bool enabledUDP = false)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (enabled)
|
outbound.mux.enabled = false;
|
||||||
|
outbound.mux.concurrency = -1;
|
||||||
|
|
||||||
|
if (enabledTCP)
|
||||||
{
|
{
|
||||||
outbound.mux.enabled = true;
|
outbound.mux.enabled = true;
|
||||||
outbound.mux.concurrency = _config.Mux4RayItem.Concurrency;
|
outbound.mux.concurrency = _config.Mux4RayItem.Concurrency;
|
||||||
|
}
|
||||||
|
else if (enabledUDP)
|
||||||
|
{
|
||||||
|
outbound.mux.enabled = true;
|
||||||
outbound.mux.xudpConcurrency = _config.Mux4RayItem.XudpConcurrency;
|
outbound.mux.xudpConcurrency = _config.Mux4RayItem.XudpConcurrency;
|
||||||
outbound.mux.xudpProxyUDP443 = _config.Mux4RayItem.XudpProxyUDP443;
|
outbound.mux.xudpProxyUDP443 = _config.Mux4RayItem.XudpProxyUDP443;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
outbound.mux.enabled = false;
|
|
||||||
outbound.mux.concurrency = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> GenBoundStreamSettings(ProfileItem node, StreamSettings4Ray streamSettings)
|
private async Task<int> GenBoundStreamSettings(ProfileItem node, Outbounds4Ray outbound)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var streamSettings = outbound.streamSettings;
|
||||||
streamSettings.network = node.GetNetwork();
|
streamSettings.network = node.GetNetwork();
|
||||||
string host = node.RequestHost.TrimEx();
|
var host = node.RequestHost.TrimEx();
|
||||||
string sni = node.Sni;
|
var path = node.Path.TrimEx();
|
||||||
string useragent = "";
|
var sni = node.Sni.TrimEx();
|
||||||
|
var useragent = "";
|
||||||
if (!_config.CoreBasicItem.DefUserAgent.IsNullOrEmpty())
|
if (!_config.CoreBasicItem.DefUserAgent.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -879,9 +859,9 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
{
|
{
|
||||||
type = node.HeaderType
|
type = node.HeaderType
|
||||||
};
|
};
|
||||||
if (Utils.IsNotEmpty(node.Path))
|
if (Utils.IsNotEmpty(path))
|
||||||
{
|
{
|
||||||
kcpSettings.seed = node.Path;
|
kcpSettings.seed = path;
|
||||||
}
|
}
|
||||||
streamSettings.kcpSettings = kcpSettings;
|
streamSettings.kcpSettings = kcpSettings;
|
||||||
break;
|
break;
|
||||||
@@ -889,9 +869,10 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
case nameof(ETransport.ws):
|
case nameof(ETransport.ws):
|
||||||
WsSettings4Ray wsSettings = new();
|
WsSettings4Ray wsSettings = new();
|
||||||
wsSettings.headers = new Headers4Ray();
|
wsSettings.headers = new Headers4Ray();
|
||||||
string path = node.Path;
|
|
||||||
if (Utils.IsNotEmpty(host))
|
if (Utils.IsNotEmpty(host))
|
||||||
{
|
{
|
||||||
|
wsSettings.host = host;
|
||||||
wsSettings.headers.Host = host;
|
wsSettings.headers.Host = host;
|
||||||
}
|
}
|
||||||
if (Utils.IsNotEmpty(path))
|
if (Utils.IsNotEmpty(path))
|
||||||
@@ -909,9 +890,9 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
case nameof(ETransport.httpupgrade):
|
case nameof(ETransport.httpupgrade):
|
||||||
HttpupgradeSettings4Ray httpupgradeSettings = new();
|
HttpupgradeSettings4Ray httpupgradeSettings = new();
|
||||||
|
|
||||||
if (Utils.IsNotEmpty(node.Path))
|
if (Utils.IsNotEmpty(path))
|
||||||
{
|
{
|
||||||
httpupgradeSettings.path = node.Path;
|
httpupgradeSettings.path = path;
|
||||||
}
|
}
|
||||||
if (Utils.IsNotEmpty(host))
|
if (Utils.IsNotEmpty(host))
|
||||||
{
|
{
|
||||||
@@ -920,23 +901,30 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
streamSettings.httpupgradeSettings = httpupgradeSettings;
|
streamSettings.httpupgradeSettings = httpupgradeSettings;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
//splithttp
|
//xhttp
|
||||||
case nameof(ETransport.splithttp):
|
case nameof(ETransport.xhttp):
|
||||||
SplithttpSettings4Ray splithttpSettings = new()
|
streamSettings.network = ETransport.xhttp.ToString();
|
||||||
{
|
XhttpSettings4Ray xhttpSettings = new();
|
||||||
maxUploadSize = 1000000,
|
|
||||||
maxConcurrentUploads = 10
|
|
||||||
};
|
|
||||||
|
|
||||||
if (Utils.IsNotEmpty(node.Path))
|
if (Utils.IsNotEmpty(path))
|
||||||
{
|
{
|
||||||
splithttpSettings.path = node.Path;
|
xhttpSettings.path = path;
|
||||||
}
|
}
|
||||||
if (Utils.IsNotEmpty(host))
|
if (Utils.IsNotEmpty(host))
|
||||||
{
|
{
|
||||||
splithttpSettings.host = host;
|
xhttpSettings.host = host;
|
||||||
}
|
}
|
||||||
streamSettings.splithttpSettings = splithttpSettings;
|
if (Utils.IsNotEmpty(node.HeaderType) && Global.XhttpMode.Contains(node.HeaderType))
|
||||||
|
{
|
||||||
|
xhttpSettings.mode = node.HeaderType;
|
||||||
|
}
|
||||||
|
if (Utils.IsNotEmpty(node.Extra))
|
||||||
|
{
|
||||||
|
xhttpSettings.extra = JsonUtils.ParseJson(node.Extra);
|
||||||
|
}
|
||||||
|
|
||||||
|
streamSettings.xhttpSettings = xhttpSettings;
|
||||||
|
await GenOutboundMux(node, outbound);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
//h2
|
//h2
|
||||||
@@ -947,7 +935,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
{
|
{
|
||||||
httpSettings.host = Utils.String2List(host);
|
httpSettings.host = Utils.String2List(host);
|
||||||
}
|
}
|
||||||
httpSettings.path = node.Path;
|
httpSettings.path = path;
|
||||||
|
|
||||||
streamSettings.httpSettings = httpSettings;
|
streamSettings.httpSettings = httpSettings;
|
||||||
|
|
||||||
@@ -957,7 +945,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
QuicSettings4Ray quicsettings = new()
|
QuicSettings4Ray quicsettings = new()
|
||||||
{
|
{
|
||||||
security = host,
|
security = host,
|
||||||
key = node.Path,
|
key = path,
|
||||||
header = new Header4Ray
|
header = new Header4Ray
|
||||||
{
|
{
|
||||||
type = node.HeaderType
|
type = node.HeaderType
|
||||||
@@ -981,7 +969,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
GrpcSettings4Ray grpcSettings = new()
|
GrpcSettings4Ray grpcSettings = new()
|
||||||
{
|
{
|
||||||
authority = Utils.IsNullOrEmpty(host) ? null : host,
|
authority = Utils.IsNullOrEmpty(host) ? null : host,
|
||||||
serviceName = node.Path,
|
serviceName = path,
|
||||||
multiMode = node.HeaderType == Global.GrpcMultiMode,
|
multiMode = node.HeaderType == Global.GrpcMultiMode,
|
||||||
idle_timeout = _config.GrpcItem.IdleTimeout,
|
idle_timeout = _config.GrpcItem.IdleTimeout,
|
||||||
health_check_timeout = _config.GrpcItem.HealthCheckTimeout,
|
health_check_timeout = _config.GrpcItem.HealthCheckTimeout,
|
||||||
@@ -1006,18 +994,17 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
//request Host
|
//request Host
|
||||||
string request = Utils.GetEmbedText(Global.V2raySampleHttpRequestFileName);
|
string request = Utils.GetEmbedText(Global.V2raySampleHttpRequestFileName);
|
||||||
string[] arrHost = host.Split(',');
|
string[] arrHost = host.Split(',');
|
||||||
string host2 = string.Join("\",\"", arrHost);
|
string host2 = string.Join(",".AppendQuotes(), arrHost);
|
||||||
request = request.Replace("$requestHost$", $"\"{host2}\"");
|
request = request.Replace("$requestHost$", $"{host2.AppendQuotes()}");
|
||||||
//request = request.Replace("$requestHost$", string.Format("\"{0}\"", config.requestHost()));
|
request = request.Replace("$requestUserAgent$", $"{useragent.AppendQuotes()}");
|
||||||
request = request.Replace("$requestUserAgent$", $"\"{useragent}\"");
|
|
||||||
//Path
|
//Path
|
||||||
string pathHttp = @"/";
|
string pathHttp = @"/";
|
||||||
if (Utils.IsNotEmpty(node.Path))
|
if (Utils.IsNotEmpty(path))
|
||||||
{
|
{
|
||||||
string[] arrPath = node.Path.Split(',');
|
string[] arrPath = path.Split(',');
|
||||||
pathHttp = string.Join("\",\"", arrPath);
|
pathHttp = string.Join(",".AppendQuotes(), arrPath);
|
||||||
}
|
}
|
||||||
request = request.Replace("$requestPath$", $"\"{pathHttp}\"");
|
request = request.Replace("$requestPath$", $"{pathHttp.AppendQuotes()}");
|
||||||
tcpSettings.header.request = JsonUtils.Deserialize<object>(request);
|
tcpSettings.header.request = JsonUtils.Deserialize<object>(request);
|
||||||
|
|
||||||
streamSettings.tcpSettings = tcpSettings;
|
streamSettings.tcpSettings = tcpSettings;
|
||||||
@@ -1027,12 +1014,12 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> GenDns(ProfileItem? node, V2rayConfig v2rayConfig)
|
private async Task<int> GenDns(ProfileItem? node, V2rayConfig v2rayConfig)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1047,9 +1034,13 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
//Outbound Freedom domainStrategy
|
//Outbound Freedom domainStrategy
|
||||||
if (Utils.IsNotEmpty(domainStrategy4Freedom))
|
if (Utils.IsNotEmpty(domainStrategy4Freedom))
|
||||||
{
|
{
|
||||||
var outbound = v2rayConfig.outbounds[1];
|
var outbound = v2rayConfig.outbounds.FirstOrDefault(t => t is { protocol: "freedom", tag: Global.DirectTag });
|
||||||
outbound.settings.domainStrategy = domainStrategy4Freedom;
|
if (outbound != null)
|
||||||
outbound.settings.userLevel = 0;
|
{
|
||||||
|
outbound.settings = new();
|
||||||
|
outbound.settings.domainStrategy = domainStrategy4Freedom;
|
||||||
|
outbound.settings.userLevel = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var obj = JsonUtils.ParseJson(normalDNS);
|
var obj = JsonUtils.ParseJson(normalDNS);
|
||||||
@@ -1090,12 +1081,12 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> GenDnsDomains(ProfileItem? node, JsonNode dns, DNSItem? dNSItem)
|
private async Task<int> GenDnsDomains(ProfileItem? node, JsonNode dns, DNSItem? dNSItem)
|
||||||
{
|
{
|
||||||
if (node == null)
|
if (node == null)
|
||||||
{ return 0; }
|
{ return 0; }
|
||||||
@@ -1115,22 +1106,19 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> GenStatistic(V2rayConfig v2rayConfig)
|
private async Task<int> GenStatistic(V2rayConfig v2rayConfig)
|
||||||
{
|
{
|
||||||
if (_config.GuiItem.EnableStatistics)
|
if (_config.GuiItem.EnableStatistics)
|
||||||
{
|
{
|
||||||
string tag = EInboundProtocol.api.ToString();
|
string tag = EInboundProtocol.api.ToString();
|
||||||
API4Ray apiObj = new();
|
Metrics4Ray apiObj = new();
|
||||||
Policy4Ray policyObj = new();
|
Policy4Ray policyObj = new();
|
||||||
SystemPolicy4Ray policySystemSetting = new();
|
SystemPolicy4Ray policySystemSetting = new();
|
||||||
|
|
||||||
string[] services = { "StatsService" };
|
|
||||||
|
|
||||||
v2rayConfig.stats = new Stats4Ray();
|
v2rayConfig.stats = new Stats4Ray();
|
||||||
|
|
||||||
apiObj.tag = tag;
|
apiObj.tag = tag;
|
||||||
apiObj.services = services.ToList();
|
v2rayConfig.metrics = apiObj;
|
||||||
v2rayConfig.api = apiObj;
|
|
||||||
|
|
||||||
policySystemSetting.statsOutboundDownlink = true;
|
policySystemSetting.statsOutboundDownlink = true;
|
||||||
policySystemSetting.statsOutboundUplink = true;
|
policySystemSetting.statsOutboundUplink = true;
|
||||||
@@ -1169,7 +1157,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
{
|
{
|
||||||
//fragment proxy
|
//fragment proxy
|
||||||
if (_config.CoreBasicItem.EnableFragment
|
if (_config.CoreBasicItem.EnableFragment
|
||||||
&& Utils.IsNotEmpty(v2rayConfig.outbounds[0].streamSettings?.security))
|
&& Utils.IsNotEmpty(v2rayConfig.outbounds.First().streamSettings?.security))
|
||||||
{
|
{
|
||||||
var fragmentOutbound = new Outbounds4Ray
|
var fragmentOutbound = new Outbounds4Ray
|
||||||
{
|
{
|
||||||
@@ -1179,15 +1167,15 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
{
|
{
|
||||||
fragment = new()
|
fragment = new()
|
||||||
{
|
{
|
||||||
packets = "tlshello",
|
packets = _config.Fragment4RayItem?.Packets,
|
||||||
length = "100-200",
|
length = _config.Fragment4RayItem?.Length,
|
||||||
interval = "10-20"
|
interval = _config.Fragment4RayItem?.Interval
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
v2rayConfig.outbounds.Add(fragmentOutbound);
|
v2rayConfig.outbounds.Add(fragmentOutbound);
|
||||||
v2rayConfig.outbounds[0].streamSettings.sockopt = new()
|
v2rayConfig.outbounds.First().streamSettings.sockopt = new()
|
||||||
{
|
{
|
||||||
dialerProxy = fragmentOutbound.tag
|
dialerProxy = fragmentOutbound.tag
|
||||||
};
|
};
|
||||||
@@ -1207,7 +1195,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
//current proxy
|
//current proxy
|
||||||
var outbound = v2rayConfig.outbounds[0];
|
var outbound = v2rayConfig.outbounds.First();
|
||||||
var txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound);
|
var txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound);
|
||||||
|
|
||||||
//Previous proxy
|
//Previous proxy
|
||||||
@@ -1251,7 +1239,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ namespace ServiceLib.Services
|
|||||||
|
|
||||||
public event ErrorEventHandler? Error;
|
public event ErrorEventHandler? Error;
|
||||||
|
|
||||||
|
private static readonly string _tag = "DownloadService";
|
||||||
|
|
||||||
public async Task<int> DownloadDataAsync(string url, WebProxy webProxy, int downloadTimeout, Action<bool, string> updateFunc)
|
public async Task<int> DownloadDataAsync(string url, WebProxy webProxy, int downloadTimeout, Action<bool, string> updateFunc)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -68,7 +70,7 @@ namespace ServiceLib.Services
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
|
|
||||||
Error?.Invoke(this, new ErrorEventArgs(ex));
|
Error?.Invoke(this, new ErrorEventArgs(ex));
|
||||||
if (ex.InnerException != null)
|
if (ex.InnerException != null)
|
||||||
@@ -113,7 +115,7 @@ namespace ServiceLib.Services
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
Error?.Invoke(this, new ErrorEventArgs(ex));
|
Error?.Invoke(this, new ErrorEventArgs(ex));
|
||||||
if (ex.InnerException != null)
|
if (ex.InnerException != null)
|
||||||
{
|
{
|
||||||
@@ -131,7 +133,7 @@ namespace ServiceLib.Services
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
Error?.Invoke(this, new ErrorEventArgs(ex));
|
Error?.Invoke(this, new ErrorEventArgs(ex));
|
||||||
if (ex.InnerException != null)
|
if (ex.InnerException != null)
|
||||||
{
|
{
|
||||||
@@ -177,7 +179,7 @@ namespace ServiceLib.Services
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
Error?.Invoke(this, new ErrorEventArgs(ex));
|
Error?.Invoke(this, new ErrorEventArgs(ex));
|
||||||
if (ex.InnerException != null)
|
if (ex.InnerException != null)
|
||||||
{
|
{
|
||||||
@@ -208,7 +210,7 @@ namespace ServiceLib.Services
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
Error?.Invoke(this, new ErrorEventArgs(ex));
|
Error?.Invoke(this, new ErrorEventArgs(ex));
|
||||||
if (ex.InnerException != null)
|
if (ex.InnerException != null)
|
||||||
{
|
{
|
||||||
@@ -232,13 +234,13 @@ namespace ServiceLib.Services
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -280,13 +282,13 @@ namespace ServiceLib.Services
|
|||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
var httpPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.http);
|
var port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
|
||||||
if (await SocketCheck(Global.Loopback, httpPort) == false)
|
if (await SocketCheck(Global.Loopback, port) == false)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new WebProxy(Global.Loopback, httpPort);
|
return new WebProxy($"socks5://{Global.Loopback}:{port}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> SocketCheck(string ip, int port)
|
private async Task<bool> SocketCheck(string ip, int port)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Diagnostics;
|
using ReactiveUI;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
|
||||||
@@ -7,19 +8,17 @@ namespace ServiceLib.Services
|
|||||||
public class SpeedtestService
|
public class SpeedtestService
|
||||||
{
|
{
|
||||||
private Config? _config;
|
private Config? _config;
|
||||||
private List<ServerTestItem> _selecteds;
|
|
||||||
private ESpeedActionType _actionType;
|
|
||||||
private Action<SpeedTestResult>? _updateFunc;
|
private Action<SpeedTestResult>? _updateFunc;
|
||||||
|
|
||||||
private bool _exitLoop = false;
|
private bool _exitLoop = false;
|
||||||
|
private static readonly string _tag = "SpeedtestService";
|
||||||
|
|
||||||
public SpeedtestService(Config config, List<ProfileItem> selecteds, ESpeedActionType actionType, Action<SpeedTestResult> updateFunc)
|
public SpeedtestService(Config config, List<ProfileItem> selecteds, ESpeedActionType actionType, Action<SpeedTestResult> updateFunc)
|
||||||
{
|
{
|
||||||
_config = config;
|
_config = config;
|
||||||
|
|
||||||
_actionType = actionType;
|
|
||||||
_updateFunc = updateFunc;
|
_updateFunc = updateFunc;
|
||||||
|
|
||||||
_selecteds = new List<ServerTestItem>();
|
var lstSelected = new List<ServerTestItem>();
|
||||||
foreach (var it in selecteds)
|
foreach (var it in selecteds)
|
||||||
{
|
{
|
||||||
if (it.ConfigType == EConfigType.Custom)
|
if (it.ConfigType == EConfigType.Custom)
|
||||||
@@ -30,7 +29,7 @@ namespace ServiceLib.Services
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_selecteds.Add(new ServerTestItem()
|
lstSelected.Add(new ServerTestItem()
|
||||||
{
|
{
|
||||||
IndexId = it.IndexId,
|
IndexId = it.IndexId,
|
||||||
Address = it.Address,
|
Address = it.Address,
|
||||||
@@ -38,8 +37,9 @@ namespace ServiceLib.Services
|
|||||||
ConfigType = it.ConfigType
|
ConfigType = it.ConfigType
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//clear test result
|
//clear test result
|
||||||
foreach (var it in _selecteds)
|
foreach (var it in lstSelected)
|
||||||
{
|
{
|
||||||
switch (actionType)
|
switch (actionType)
|
||||||
{
|
{
|
||||||
@@ -62,38 +62,74 @@ namespace ServiceLib.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (actionType)
|
MessageBus.Current.Listen<string>(EMsgCommand.StopSpeedtest.ToString()).Subscribe(ExitLoop);
|
||||||
{
|
|
||||||
case ESpeedActionType.Tcping:
|
|
||||||
Task.Run(RunTcping);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ESpeedActionType.Realping:
|
Task.Run(async () => { await RunAsync(actionType, lstSelected); });
|
||||||
Task.Run(RunRealPing);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ESpeedActionType.Speedtest:
|
|
||||||
Task.Run(RunSpeedTestAsync);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ESpeedActionType.Mixedtest:
|
|
||||||
Task.Run(RunMixedtestAsync);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ExitLoop()
|
private async Task RunAsync(ESpeedActionType actionType, List<ServerTestItem> lstSelected)
|
||||||
{
|
{
|
||||||
|
if (actionType == ESpeedActionType.Tcping)
|
||||||
|
{
|
||||||
|
await RunTcpingAsync(lstSelected);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pageSize = _config.SpeedTestItem.SpeedTestPageSize;
|
||||||
|
if (pageSize is <= 0 or > 1000)
|
||||||
|
{
|
||||||
|
pageSize = 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<List<ServerTestItem>> lstTest = new();
|
||||||
|
var lst1 = lstSelected.Where(t => t.ConfigType is not (EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard)).ToList();
|
||||||
|
var lst2 = lstSelected.Where(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard).ToList();
|
||||||
|
|
||||||
|
for (var num = 0; num < (int)Math.Ceiling(lst1.Count * 1.0 / pageSize); num++)
|
||||||
|
{
|
||||||
|
lstTest.Add(lst1.Skip(num * pageSize).Take(pageSize).ToList());
|
||||||
|
}
|
||||||
|
for (var num = 0; num < (int)Math.Ceiling(lst2.Count * 1.0 / pageSize); num++)
|
||||||
|
{
|
||||||
|
lstTest.Add(lst2.Skip(num * pageSize).Take(pageSize).ToList());
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var lst in lstTest)
|
||||||
|
{
|
||||||
|
switch (actionType)
|
||||||
|
{
|
||||||
|
case ESpeedActionType.Realping:
|
||||||
|
await RunRealPingAsync(lst);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ESpeedActionType.Speedtest:
|
||||||
|
await RunSpeedTestAsync(lst);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ESpeedActionType.Mixedtest:
|
||||||
|
await RunMixedTestAsync(lst);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateFunc("", ResUI.SpeedtestingCompleted);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExitLoop(string x)
|
||||||
|
{
|
||||||
|
if (_exitLoop) return;
|
||||||
_exitLoop = true;
|
_exitLoop = true;
|
||||||
UpdateFunc("", ResUI.SpeedtestingStop);
|
UpdateFunc("", ResUI.SpeedtestingStop);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RunTcping()
|
private async Task RunTcpingAsync(List<ServerTestItem> selecteds)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
List<Task> tasks = [];
|
List<Task> tasks = [];
|
||||||
foreach (var it in _selecteds)
|
foreach (var it in selecteds)
|
||||||
{
|
{
|
||||||
if (it.ConfigType == EConfigType.Custom)
|
if (it.ConfigType == EConfigType.Custom)
|
||||||
{
|
{
|
||||||
@@ -103,7 +139,7 @@ namespace ServiceLib.Services
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
int time = await GetTcpingTime(it.Address, it.Port);
|
var time = await GetTcpingTime(it.Address, it.Port);
|
||||||
var output = FormatOut(time, Global.DelayUnit);
|
var output = FormatOut(time, Global.DelayUnit);
|
||||||
|
|
||||||
ProfileExHandler.Instance.SetTestDelay(it.IndexId, output);
|
ProfileExHandler.Instance.SetTestDelay(it.IndexId, output);
|
||||||
@@ -111,7 +147,7 @@ namespace ServiceLib.Services
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -119,7 +155,7 @@ namespace ServiceLib.Services
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -127,24 +163,22 @@ namespace ServiceLib.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RunRealPing()
|
private async Task RunRealPingAsync(List<ServerTestItem> selecteds)
|
||||||
{
|
{
|
||||||
int pid = -1;
|
var pid = -1;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string msg = string.Empty;
|
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
|
||||||
|
|
||||||
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(_selecteds);
|
|
||||||
if (pid < 0)
|
if (pid < 0)
|
||||||
{
|
{
|
||||||
UpdateFunc("", ResUI.FailedToRunCore);
|
UpdateFunc("", ResUI.FailedToRunCore);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadService downloadHandle = new DownloadService();
|
var downloadHandle = new DownloadService();
|
||||||
|
|
||||||
List<Task> tasks = new();
|
List<Task> tasks = new();
|
||||||
foreach (var it in _selecteds)
|
foreach (var it in selecteds)
|
||||||
{
|
{
|
||||||
if (!it.AllowTest)
|
if (!it.AllowTest)
|
||||||
{
|
{
|
||||||
@@ -158,17 +192,17 @@ namespace ServiceLib.Services
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
WebProxy webProxy = new(Global.Loopback, it.Port);
|
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
|
||||||
string output = await GetRealPingTime(downloadHandle, webProxy);
|
var output = await GetRealPingTime(downloadHandle, webProxy);
|
||||||
|
|
||||||
ProfileExHandler.Instance.SetTestDelay(it.IndexId, output);
|
ProfileExHandler.Instance.SetTestDelay(it.IndexId, output);
|
||||||
UpdateFunc(it.IndexId, output);
|
UpdateFunc(it.IndexId, output);
|
||||||
int.TryParse(output, out int delay);
|
int.TryParse(output, out var delay);
|
||||||
it.Delay = delay;
|
it.Delay = delay;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -176,39 +210,34 @@ namespace ServiceLib.Services
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (pid > 0)
|
if (pid > 0)
|
||||||
{
|
{
|
||||||
CoreHandler.Instance.CoreStopPid(pid);
|
await ProcUtils.ProcessKill(pid);
|
||||||
}
|
}
|
||||||
await ProfileExHandler.Instance.SaveTo();
|
await ProfileExHandler.Instance.SaveTo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RunSpeedTestAsync()
|
private async Task RunSpeedTestAsync(List<ServerTestItem> selecteds)
|
||||||
{
|
{
|
||||||
int pid = -1;
|
var pid = -1;
|
||||||
//if (_actionType == ESpeedActionType.Mixedtest)
|
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
|
||||||
//{
|
|
||||||
// _selecteds = _selecteds.OrderBy(t => t.delay).ToList();
|
|
||||||
//}
|
|
||||||
|
|
||||||
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(_selecteds);
|
|
||||||
if (pid < 0)
|
if (pid < 0)
|
||||||
{
|
{
|
||||||
UpdateFunc("", ResUI.FailedToRunCore);
|
UpdateFunc("", ResUI.FailedToRunCore);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string url = _config.SpeedTestItem.SpeedTestUrl;
|
var url = _config.SpeedTestItem.SpeedTestUrl;
|
||||||
var timeout = _config.SpeedTestItem.SpeedTestTimeout;
|
var timeout = _config.SpeedTestItem.SpeedTestTimeout;
|
||||||
|
|
||||||
DownloadService downloadHandle = new();
|
DownloadService downloadHandle = new();
|
||||||
|
|
||||||
foreach (var it in _selecteds)
|
foreach (var it in selecteds)
|
||||||
{
|
{
|
||||||
if (_exitLoop)
|
if (_exitLoop)
|
||||||
{
|
{
|
||||||
@@ -234,11 +263,11 @@ namespace ServiceLib.Services
|
|||||||
var item = await AppHandler.Instance.GetProfileItem(it.IndexId);
|
var item = await AppHandler.Instance.GetProfileItem(it.IndexId);
|
||||||
if (item is null) continue;
|
if (item is null) continue;
|
||||||
|
|
||||||
WebProxy webProxy = new(Global.Loopback, it.Port);
|
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
|
||||||
|
|
||||||
await downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) =>
|
await downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) =>
|
||||||
{
|
{
|
||||||
decimal.TryParse(msg, out decimal dec);
|
decimal.TryParse(msg, out var dec);
|
||||||
if (dec > 0)
|
if (dec > 0)
|
||||||
{
|
{
|
||||||
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, msg);
|
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, msg);
|
||||||
@@ -249,28 +278,27 @@ namespace ServiceLib.Services
|
|||||||
|
|
||||||
if (pid > 0)
|
if (pid > 0)
|
||||||
{
|
{
|
||||||
CoreHandler.Instance.CoreStopPid(pid);
|
await ProcUtils.ProcessKill(pid);
|
||||||
}
|
}
|
||||||
UpdateFunc("", ResUI.SpeedtestingCompleted);
|
|
||||||
await ProfileExHandler.Instance.SaveTo();
|
await ProfileExHandler.Instance.SaveTo();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RunSpeedTestMulti()
|
private async Task RunSpeedTestMulti(List<ServerTestItem> selecteds)
|
||||||
{
|
{
|
||||||
int pid = -1;
|
var pid = -1;
|
||||||
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(_selecteds);
|
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
|
||||||
if (pid < 0)
|
if (pid < 0)
|
||||||
{
|
{
|
||||||
UpdateFunc("", ResUI.FailedToRunCore);
|
UpdateFunc("", ResUI.FailedToRunCore);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string url = _config.SpeedTestItem.SpeedTestUrl;
|
var url = _config.SpeedTestItem.SpeedTestUrl;
|
||||||
var timeout = _config.SpeedTestItem.SpeedTestTimeout;
|
var timeout = _config.SpeedTestItem.SpeedTestTimeout;
|
||||||
|
|
||||||
DownloadService downloadHandle = new();
|
DownloadService downloadHandle = new();
|
||||||
|
|
||||||
foreach (var it in _selecteds)
|
foreach (var it in selecteds)
|
||||||
{
|
{
|
||||||
if (_exitLoop)
|
if (_exitLoop)
|
||||||
{
|
{
|
||||||
@@ -297,10 +325,10 @@ namespace ServiceLib.Services
|
|||||||
var item = await AppHandler.Instance.GetProfileItem(it.IndexId);
|
var item = await AppHandler.Instance.GetProfileItem(it.IndexId);
|
||||||
if (item is null) continue;
|
if (item is null) continue;
|
||||||
|
|
||||||
WebProxy webProxy = new(Global.Loopback, it.Port);
|
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
|
||||||
_ = downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) =>
|
_ = downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) =>
|
||||||
{
|
{
|
||||||
decimal.TryParse(msg, out decimal dec);
|
decimal.TryParse(msg, out var dec);
|
||||||
if (dec > 0)
|
if (dec > 0)
|
||||||
{
|
{
|
||||||
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, msg);
|
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, msg);
|
||||||
@@ -314,38 +342,37 @@ namespace ServiceLib.Services
|
|||||||
|
|
||||||
if (pid > 0)
|
if (pid > 0)
|
||||||
{
|
{
|
||||||
CoreHandler.Instance.CoreStopPid(pid);
|
await ProcUtils.ProcessKill(pid);
|
||||||
}
|
}
|
||||||
UpdateFunc("", ResUI.SpeedtestingCompleted);
|
|
||||||
await ProfileExHandler.Instance.SaveTo();
|
await ProfileExHandler.Instance.SaveTo();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RunMixedtestAsync()
|
private async Task RunMixedTestAsync(List<ServerTestItem> selecteds)
|
||||||
{
|
{
|
||||||
await RunRealPing();
|
await RunRealPingAsync(selecteds);
|
||||||
|
|
||||||
await Task.Delay(1000);
|
await Task.Delay(1000);
|
||||||
|
|
||||||
await RunSpeedTestMulti();
|
await RunSpeedTestMulti(selecteds);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> GetRealPingTime(DownloadService downloadHandle, IWebProxy webProxy)
|
private async Task<string> GetRealPingTime(DownloadService downloadHandle, IWebProxy webProxy)
|
||||||
{
|
{
|
||||||
int responseTime = await downloadHandle.GetRealPingTime(_config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10);
|
var responseTime = await downloadHandle.GetRealPingTime(_config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10);
|
||||||
//string output = Utile.IsNullOrEmpty(status) ? FormatOut(responseTime, "ms") : status;
|
//string output = Utile.IsNullOrEmpty(status) ? FormatOut(responseTime, "ms") : status;
|
||||||
return FormatOut(responseTime, Global.DelayUnit);
|
return FormatOut(responseTime, Global.DelayUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<int> GetTcpingTime(string url, int port)
|
private async Task<int> GetTcpingTime(string url, int port)
|
||||||
{
|
{
|
||||||
int responseTime = -1;
|
var responseTime = -1;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!IPAddress.TryParse(url, out IPAddress? ipAddress))
|
if (!IPAddress.TryParse(url, out var ipAddress))
|
||||||
{
|
{
|
||||||
IPHostEntry ipHostInfo = Dns.GetHostEntry(url);
|
var ipHostInfo = await Dns.GetHostEntryAsync(url);
|
||||||
ipAddress = ipHostInfo.AddressList[0];
|
ipAddress = ipHostInfo.AddressList.First();
|
||||||
}
|
}
|
||||||
|
|
||||||
var timer = Stopwatch.StartNew();
|
var timer = Stopwatch.StartNew();
|
||||||
@@ -363,7 +390,7 @@ namespace ServiceLib.Services
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
return responseTime;
|
return responseTime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,9 @@ namespace ServiceLib.Services.Statistics
|
|||||||
private Config _config;
|
private Config _config;
|
||||||
private bool _exitFlag;
|
private bool _exitFlag;
|
||||||
private ClientWebSocket? webSocket;
|
private ClientWebSocket? webSocket;
|
||||||
private string url = string.Empty;
|
|
||||||
private Action<ServerSpeedItem>? _updateFunc;
|
private Action<ServerSpeedItem>? _updateFunc;
|
||||||
|
private string Url => $"ws://{Global.Loopback}:{AppHandler.Instance.StatePort2}/traffic";
|
||||||
|
private static readonly string _tag = "StatisticsSingboxService";
|
||||||
|
|
||||||
public StatisticsSingboxService(Config config, Action<ServerSpeedItem> updateFunc)
|
public StatisticsSingboxService(Config config, Action<ServerSpeedItem> updateFunc)
|
||||||
{
|
{
|
||||||
@@ -26,12 +27,10 @@ namespace ServiceLib.Services.Statistics
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
url = $"ws://{Global.Loopback}:{AppHandler.Instance.StatePort2}/traffic";
|
|
||||||
|
|
||||||
if (webSocket == null)
|
if (webSocket == null)
|
||||||
{
|
{
|
||||||
webSocket = new ClientWebSocket();
|
webSocket = new ClientWebSocket();
|
||||||
await webSocket.ConnectAsync(new Uri(url), CancellationToken.None);
|
await webSocket.ConnectAsync(new Uri(Url), CancellationToken.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
@@ -50,7 +49,7 @@ namespace ServiceLib.Services.Statistics
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,135 +0,0 @@
|
|||||||
using Grpc.Core;
|
|
||||||
using Grpc.Net.Client;
|
|
||||||
using ProtosLib.Statistics;
|
|
||||||
|
|
||||||
namespace ServiceLib.Services.Statistics
|
|
||||||
{
|
|
||||||
public class StatisticsV2rayService
|
|
||||||
{
|
|
||||||
private Models.Config _config;
|
|
||||||
private GrpcChannel? _channel;
|
|
||||||
private StatsService.StatsServiceClient? _client;
|
|
||||||
private bool _exitFlag;
|
|
||||||
private Action<ServerSpeedItem>? _updateFunc;
|
|
||||||
|
|
||||||
public StatisticsV2rayService(Models.Config config, Action<ServerSpeedItem> updateFunc)
|
|
||||||
{
|
|
||||||
_config = config;
|
|
||||||
_updateFunc = updateFunc;
|
|
||||||
_exitFlag = false;
|
|
||||||
|
|
||||||
GrpcInit();
|
|
||||||
|
|
||||||
Task.Run(Run);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GrpcInit()
|
|
||||||
{
|
|
||||||
if (_channel is null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_channel = GrpcChannel.ForAddress($"{Global.HttpProtocol}{Global.Loopback}:{AppHandler.Instance.StatePort}");
|
|
||||||
_client = new StatsService.StatsServiceClient(_channel);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logging.SaveLog(ex.Message, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Close()
|
|
||||||
{
|
|
||||||
_exitFlag = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void Run()
|
|
||||||
{
|
|
||||||
while (!_exitFlag)
|
|
||||||
{
|
|
||||||
await Task.Delay(1000);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!_config.IsRunningCore(ECoreType.Xray))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (_channel?.State == ConnectivityState.Ready)
|
|
||||||
{
|
|
||||||
QueryStatsResponse? res = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_client != null)
|
|
||||||
res = await _client.QueryStatsAsync(new QueryStatsRequest() { Pattern = "", Reset = true });
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res != null)
|
|
||||||
{
|
|
||||||
ParseOutput(res.Stat, out ServerSpeedItem server);
|
|
||||||
_updateFunc?.Invoke(server);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_channel != null)
|
|
||||||
await _channel.ConnectAsync();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ParseOutput(Google.Protobuf.Collections.RepeatedField<Stat> source, out ServerSpeedItem server)
|
|
||||||
{
|
|
||||||
server = new();
|
|
||||||
long aggregateProxyUp = 0;
|
|
||||||
long aggregateProxyDown = 0;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
foreach (Stat stat in source)
|
|
||||||
{
|
|
||||||
string name = stat.Name;
|
|
||||||
long value = stat.Value / 1024; //KByte
|
|
||||||
string[] nStr = name.Split(">>>".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
string type = "";
|
|
||||||
|
|
||||||
name = name.Trim();
|
|
||||||
|
|
||||||
name = nStr[1];
|
|
||||||
type = nStr[3];
|
|
||||||
|
|
||||||
if (name.StartsWith(Global.ProxyTag))
|
|
||||||
{
|
|
||||||
if (type == "uplink")
|
|
||||||
{
|
|
||||||
aggregateProxyUp += value;
|
|
||||||
}
|
|
||||||
else if (type == "downlink")
|
|
||||||
{
|
|
||||||
aggregateProxyDown += value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (name == Global.DirectTag)
|
|
||||||
{
|
|
||||||
if (type == "uplink")
|
|
||||||
{
|
|
||||||
server.DirectUp = value;
|
|
||||||
}
|
|
||||||
else if (type == "downlink")
|
|
||||||
{
|
|
||||||
server.DirectDown = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
server.ProxyUp = aggregateProxyUp;
|
|
||||||
server.ProxyDown = aggregateProxyDown;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
105
v2rayN/ServiceLib/Services/Statistics/StatisticsXrayService.cs
Normal file
105
v2rayN/ServiceLib/Services/Statistics/StatisticsXrayService.cs
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
namespace ServiceLib.Services.Statistics
|
||||||
|
{
|
||||||
|
public class StatisticsXrayService
|
||||||
|
{
|
||||||
|
private const long linkBase = 1024;
|
||||||
|
private ServerSpeedItem _serverSpeedItem = new();
|
||||||
|
private Config _config;
|
||||||
|
private bool _exitFlag;
|
||||||
|
private Action<ServerSpeedItem>? _updateFunc;
|
||||||
|
private string Url => $"{Global.HttpProtocol}{Global.Loopback}:{AppHandler.Instance.StatePort}/debug/vars";
|
||||||
|
|
||||||
|
public StatisticsXrayService(Config config, Action<ServerSpeedItem> updateFunc)
|
||||||
|
{
|
||||||
|
_config = config;
|
||||||
|
_updateFunc = updateFunc;
|
||||||
|
_exitFlag = false;
|
||||||
|
|
||||||
|
Task.Run(Run);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
_exitFlag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void Run()
|
||||||
|
{
|
||||||
|
while (!_exitFlag)
|
||||||
|
{
|
||||||
|
await Task.Delay(1000);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_config.RunningCoreType != ECoreType.Xray)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = await HttpClientHelper.Instance.TryGetAsync(Url);
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
var server = ParseOutput(result) ?? new ServerSpeedItem();
|
||||||
|
_updateFunc?.Invoke(server);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ServerSpeedItem? ParseOutput(string result)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var source = JsonUtils.Deserialize<V2rayMetricsVars>(result);
|
||||||
|
if (source?.stats?.outbound == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerSpeedItem server = new();
|
||||||
|
foreach (string key in source.stats.outbound.Keys)
|
||||||
|
{
|
||||||
|
var value = source.stats.outbound[key];
|
||||||
|
if (value == null) continue;
|
||||||
|
var state = JsonUtils.Deserialize<V2rayMetricsVarsLink>(value.ToString());
|
||||||
|
|
||||||
|
if (key.StartsWith(Global.ProxyTag))
|
||||||
|
{
|
||||||
|
server.ProxyUp += state.uplink / linkBase;
|
||||||
|
server.ProxyDown += state.downlink / linkBase;
|
||||||
|
}
|
||||||
|
else if (key == Global.DirectTag)
|
||||||
|
{
|
||||||
|
server.DirectUp = state.uplink / linkBase;
|
||||||
|
server.DirectDown = state.downlink / linkBase;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server.DirectDown < _serverSpeedItem.DirectDown || server.ProxyDown < _serverSpeedItem.ProxyDown)
|
||||||
|
{
|
||||||
|
_serverSpeedItem = new();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerSpeedItem curItem = new()
|
||||||
|
{
|
||||||
|
ProxyUp = server.ProxyUp - _serverSpeedItem.ProxyUp,
|
||||||
|
ProxyDown = server.ProxyDown - _serverSpeedItem.ProxyDown,
|
||||||
|
DirectUp = server.DirectUp - _serverSpeedItem.DirectUp,
|
||||||
|
DirectDown = server.DirectDown - _serverSpeedItem.DirectDown,
|
||||||
|
};
|
||||||
|
_serverSpeedItem = server;
|
||||||
|
return curItem;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace ServiceLib.Services
|
namespace ServiceLib.Services
|
||||||
@@ -6,12 +6,11 @@ namespace ServiceLib.Services
|
|||||||
public class UpdateService
|
public class UpdateService
|
||||||
{
|
{
|
||||||
private Action<bool, string>? _updateFunc;
|
private Action<bool, string>? _updateFunc;
|
||||||
private Config _config;
|
|
||||||
private int _timeout = 30;
|
private int _timeout = 30;
|
||||||
|
private static readonly string _tag = "UpdateService";
|
||||||
|
|
||||||
public async Task CheckUpdateGuiN(Config config, Action<bool, string> updateFunc, bool preRelease)
|
public async Task CheckUpdateGuiN(Config config, Action<bool, string> updateFunc, bool preRelease)
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
_updateFunc = updateFunc;
|
_updateFunc = updateFunc;
|
||||||
var url = string.Empty;
|
var url = string.Empty;
|
||||||
var fileName = string.Empty;
|
var fileName = string.Empty;
|
||||||
@@ -53,7 +52,6 @@ namespace ServiceLib.Services
|
|||||||
|
|
||||||
public async Task CheckUpdateCore(ECoreType type, Config config, Action<bool, string> updateFunc, bool preRelease)
|
public async Task CheckUpdateCore(ECoreType type, Config config, Action<bool, string> updateFunc, bool preRelease)
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
_updateFunc = updateFunc;
|
_updateFunc = updateFunc;
|
||||||
var url = string.Empty;
|
var url = string.Empty;
|
||||||
var fileName = string.Empty;
|
var fileName = string.Empty;
|
||||||
@@ -108,13 +106,12 @@ namespace ServiceLib.Services
|
|||||||
|
|
||||||
public async Task UpdateSubscriptionProcess(Config config, string subId, bool blProxy, Action<bool, string> updateFunc)
|
public async Task UpdateSubscriptionProcess(Config config, string subId, bool blProxy, Action<bool, string> updateFunc)
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
_updateFunc = updateFunc;
|
_updateFunc = updateFunc;
|
||||||
|
|
||||||
_updateFunc?.Invoke(false, ResUI.MsgUpdateSubscriptionStart);
|
_updateFunc?.Invoke(false, ResUI.MsgUpdateSubscriptionStart);
|
||||||
var subItem = await AppHandler.Instance.SubItems();
|
var subItem = await AppHandler.Instance.SubItems();
|
||||||
|
|
||||||
if (subItem == null || subItem.Count <= 0)
|
if (subItem is not { Count: > 0 })
|
||||||
{
|
{
|
||||||
_updateFunc?.Invoke(false, ResUI.MsgNoValidSubscription);
|
_updateFunc?.Invoke(false, ResUI.MsgNoValidSubscription);
|
||||||
return;
|
return;
|
||||||
@@ -122,11 +119,11 @@ namespace ServiceLib.Services
|
|||||||
|
|
||||||
foreach (var item in subItem)
|
foreach (var item in subItem)
|
||||||
{
|
{
|
||||||
string id = item.Id.TrimEx();
|
var id = item.Id.TrimEx();
|
||||||
string url = item.Url.TrimEx();
|
var url = item.Url.TrimEx();
|
||||||
string userAgent = item.UserAgent.TrimEx();
|
var userAgent = item.UserAgent.TrimEx();
|
||||||
string hashCode = $"{item.Remarks}->";
|
var hashCode = $"{item.Remarks}->";
|
||||||
if (Utils.IsNullOrEmpty(id) || Utils.IsNullOrEmpty(url) || Utils.IsNotEmpty(subId) && item.Id != subId)
|
if (Utils.IsNullOrEmpty(id) || Utils.IsNullOrEmpty(url) || (Utils.IsNotEmpty(subId) && item.Id != subId))
|
||||||
{
|
{
|
||||||
//_updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgNoValidSubscription}");
|
//_updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgNoValidSubscription}");
|
||||||
continue;
|
continue;
|
||||||
@@ -219,7 +216,7 @@ namespace ServiceLib.Services
|
|||||||
_updateFunc?.Invoke(false, $"{hashCode}{result}");
|
_updateFunc?.Invoke(false, $"{hashCode}{result}");
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = await ConfigHandler.AddBatchServers(config, result, id, true);
|
var ret = await ConfigHandler.AddBatchServers(config, result, id, true);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
{
|
{
|
||||||
Logging.SaveLog("FailedImportSubscription");
|
Logging.SaveLog("FailedImportSubscription");
|
||||||
@@ -231,6 +228,8 @@ namespace ServiceLib.Services
|
|||||||
: $"{hashCode}{ResUI.MsgFailedImportSubscription}");
|
: $"{hashCode}{ResUI.MsgFailedImportSubscription}");
|
||||||
}
|
}
|
||||||
_updateFunc?.Invoke(false, "-------------------------------------------------------");
|
_updateFunc?.Invoke(false, "-------------------------------------------------------");
|
||||||
|
|
||||||
|
//await ConfigHandler.DedupServerList(config, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateFunc?.Invoke(true, $"{ResUI.MsgUpdateSubscriptionEnd}");
|
_updateFunc?.Invoke(true, $"{ResUI.MsgUpdateSubscriptionEnd}");
|
||||||
@@ -246,8 +245,17 @@ namespace ServiceLib.Services
|
|||||||
|
|
||||||
public async Task RunAvailabilityCheck(Action<bool, string> updateFunc)
|
public async Task RunAvailabilityCheck(Action<bool, string> updateFunc)
|
||||||
{
|
{
|
||||||
var time = await new DownloadService().RunAvailabilityCheck(null);
|
var downloadHandle = new DownloadService();
|
||||||
updateFunc?.Invoke(false, string.Format(ResUI.TestMeOutput, time));
|
var time = await downloadHandle.RunAvailabilityCheck(null);
|
||||||
|
var ip = Global.None;
|
||||||
|
if (time > 0)
|
||||||
|
{
|
||||||
|
var result = await downloadHandle.TryDownloadString(Global.IPAPIUrl, true, Global.IPAPIUrl);
|
||||||
|
var ipInfo = JsonUtils.Deserialize<IPAPIInfo>(result);
|
||||||
|
ip = $"({ipInfo?.country_code}) {ipInfo?.ip}";
|
||||||
|
}
|
||||||
|
|
||||||
|
updateFunc?.Invoke(false, string.Format(ResUI.TestMeOutput, time, ip));
|
||||||
}
|
}
|
||||||
|
|
||||||
#region CheckUpdate private
|
#region CheckUpdate private
|
||||||
@@ -265,7 +273,7 @@ namespace ServiceLib.Services
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
_updateFunc?.Invoke(false, ex.Message);
|
_updateFunc?.Invoke(false, ex.Message);
|
||||||
return new RetResult(false, ex.Message);
|
return new RetResult(false, ex.Message);
|
||||||
}
|
}
|
||||||
@@ -309,10 +317,9 @@ namespace ServiceLib.Services
|
|||||||
{
|
{
|
||||||
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(type);
|
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(type);
|
||||||
string filePath = string.Empty;
|
string filePath = string.Empty;
|
||||||
foreach (string name in coreInfo.CoreExes)
|
foreach (var name in coreInfo.CoreExes)
|
||||||
{
|
{
|
||||||
string vName = Utils.GetExeName(name);
|
var vName = Utils.GetBinPath(Utils.GetExeName(name), coreInfo.CoreType.ToString());
|
||||||
vName = Utils.GetBinPath(vName, coreInfo.CoreType.ToString());
|
|
||||||
if (File.Exists(vName))
|
if (File.Exists(vName))
|
||||||
{
|
{
|
||||||
filePath = vName;
|
filePath = vName;
|
||||||
@@ -350,7 +357,7 @@ namespace ServiceLib.Services
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
_updateFunc?.Invoke(false, ex.Message);
|
_updateFunc?.Invoke(false, ex.Message);
|
||||||
return new SemanticVersion("");
|
return new SemanticVersion("");
|
||||||
}
|
}
|
||||||
@@ -409,7 +416,7 @@ namespace ServiceLib.Services
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(ex.Message, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
_updateFunc?.Invoke(false, ex.Message);
|
_updateFunc?.Invoke(false, ex.Message);
|
||||||
return new RetResult(false, ex.Message);
|
return new RetResult(false, ex.Message);
|
||||||
}
|
}
|
||||||
@@ -444,6 +451,15 @@ namespace ServiceLib.Services
|
|||||||
_ => null,
|
_ => null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
else if (Utils.IsOSX())
|
||||||
|
{
|
||||||
|
return RuntimeInformation.ProcessArchitecture switch
|
||||||
|
{
|
||||||
|
Architecture.Arm64 => coreInfo?.DownloadUrlOSXArm64,
|
||||||
|
Architecture.X64 => coreInfo?.DownloadUrlOSX64,
|
||||||
|
_ => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -453,7 +469,6 @@ namespace ServiceLib.Services
|
|||||||
|
|
||||||
private async Task UpdateGeoFile(string geoName, Config config, Action<bool, string> updateFunc)
|
private async Task UpdateGeoFile(string geoName, Config config, Action<bool, string> updateFunc)
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
_updateFunc = updateFunc;
|
_updateFunc = updateFunc;
|
||||||
|
|
||||||
var geoUrl = string.IsNullOrEmpty(config?.ConstItem.GeoSourceUrl)
|
var geoUrl = string.IsNullOrEmpty(config?.ConstItem.GeoSourceUrl)
|
||||||
@@ -469,7 +484,6 @@ namespace ServiceLib.Services
|
|||||||
|
|
||||||
private async Task UpdateSrsFileAll(Config config, Action<bool, string> updateFunc)
|
private async Task UpdateSrsFileAll(Config config, Action<bool, string> updateFunc)
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
_updateFunc = updateFunc;
|
_updateFunc = updateFunc;
|
||||||
|
|
||||||
var geoipFiles = new List<string>();
|
var geoipFiles = new List<string>();
|
||||||
@@ -520,9 +534,9 @@ namespace ServiceLib.Services
|
|||||||
|
|
||||||
private async Task UpdateSrsFile(string type, string srsName, Config config, Action<bool, string> updateFunc)
|
private async Task UpdateSrsFile(string type, string srsName, Config config, Action<bool, string> updateFunc)
|
||||||
{
|
{
|
||||||
var srsUrl = string.IsNullOrEmpty(_config.ConstItem.SrsSourceUrl)
|
var srsUrl = string.IsNullOrEmpty(config.ConstItem.SrsSourceUrl)
|
||||||
? Global.SingboxRulesetUrl
|
? Global.SingboxRulesetUrl
|
||||||
: _config.ConstItem.SrsSourceUrl;
|
: config.ConstItem.SrsSourceUrl;
|
||||||
|
|
||||||
var fileName = $"{type}-{srsName}.srs";
|
var fileName = $"{type}-{srsName}.srs";
|
||||||
var targetPath = Path.Combine(Utils.GetBinPath("srss"), fileName);
|
var targetPath = Path.Combine(Utils.GetBinPath("srss"), fileName);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user