├── .gitignore
├── CLEAN.BAT
├── GenMarkdown.py
├── README.md
├── binaries
├── .gitignore
├── tun2socks_x64.exe
└── tun2socks_x86.exe
├── modes
├── Cloudflare.txt
├── Steam.txt
├── Telegram.txt
└── Warframe.txt
├── screenshots
├── four.png
├── one.png
├── three.png
└── two.png
├── v2tap.sln
└── v2tap
├── .gitignore
├── 3rd
├── IniParser
│ ├── Exceptions
│ │ └── ParsingException.cs
│ ├── FileIniParser.cs
│ ├── Helpers
│ │ └── Assert.cs
│ ├── Model
│ │ ├── Configuration
│ │ │ ├── ConcatenateDuplicatedKeysIniParserConfiguration.cs
│ │ │ └── IniParserConfiguration.cs
│ │ ├── Formatting
│ │ │ ├── DefaultIniDataFormatter.cs
│ │ │ └── IIniDataFormatter.cs
│ │ ├── IniData.cs
│ │ ├── IniDataCaseInsensitive.cs
│ │ ├── KeyData.cs
│ │ ├── KeyDataCollection.cs
│ │ ├── SectionData.cs
│ │ └── SectionDataCollection.cs
│ ├── Parser
│ │ ├── ConcatenateDuplicatedKeysIniDataParser.cs
│ │ └── IniDataParser.cs
│ ├── StreamIniDataParser.cs
│ └── StringIniParser.cs
├── SimpleJSON
│ └── SimpleJSON.cs
└── v2ray
│ └── Stats
│ ├── Command.cs
│ └── CommandGrpc.cs
├── App.config
├── Forms
├── AdvancedForm.Designer.cs
├── AdvancedForm.cs
├── AdvancedForm.resx
├── EditForm.Designer.cs
├── EditForm.cs
├── EditForm.resx
├── ImportForm.Designer.cs
├── ImportForm.cs
├── ImportForm.resx
├── MainForm.Designer.cs
├── MainForm.cs
└── MainForm.resx
├── Global.cs
├── Objects
├── Mode.cs
└── Server.cs
├── Override
└── WebClient.cs
├── Properties
├── AssemblyInfo.cs
├── Resources.Designer.cs
├── Resources.resx
├── Settings.Designer.cs
└── Settings.settings
├── Resources
├── defaultConfig.ini
├── defaultServerConfig.json
├── v2ray.json
└── v2rayNotBypassChina.json
├── Utils
└── Util.cs
├── packages.config
├── v2tap.cs
├── v2tap.csproj
└── v2tap.manifest
/.gitignore:
--------------------------------------------------------------------------------
1 | /.vs
2 | /packages
--------------------------------------------------------------------------------
/CLEAN.BAT:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 | CD v2tap
3 | RD /S /Q bin
4 | RD /S /Q obj
5 |
--------------------------------------------------------------------------------
/GenMarkdown.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | import hashlib
4 |
5 | def md5sum(filename):
6 | hash_md5 = hashlib.md5()
7 | with open(filename, 'rb') as f:
8 | for chunk in iter(lambda: f.read(4096), b''):
9 | hash_md5.update(chunk)
10 | return hash_md5.hexdigest()
11 |
12 | def sha1sum(filename):
13 | hash_sha1 = hashlib.sha1()
14 | with open(filename, 'rb') as f:
15 | for chunk in iter(lambda: f.read(4096), b''):
16 | hash_sha1.update(chunk)
17 | return hash_sha1.hexdigest()
18 |
19 | def sha256sum(filename):
20 | hash_sha256 = hashlib.sha256()
21 | with open(filename, 'rb') as f:
22 | for chunk in iter(lambda: f.read(4096), b''):
23 | hash_sha256.update(chunk)
24 | return hash_sha256.hexdigest()
25 |
26 | print('v2tap 版本:1.1.3-STABLE')
27 | print('v2ray-core 版本:4.13.0')
28 | print('')
29 | print('此包中附带 TUN/TAP 驱动程序!')
30 | print('')
31 | print('警告:32 位版本没有经过测试(手上没有 32 位系统的机器)')
32 | print('')
33 | print('| 文件名 | md5sum | sha1sum | sha256sum |')
34 | print('| :-- | :-- | :-- | :-- |')
35 |
36 | v2tap_x64_md5 = md5sum('v2tap\\bin\\Release_x64\\v2tap_x64\\v2tap_x64.7z')
37 | v2tap_x64_sha1 = sha1sum('v2tap\\bin\\Release_x64\\v2tap_x64\\v2tap_x64.7z')
38 | v2tap_x64_sha256 = sha256sum('v2tap\\bin\\Release_x64\\v2tap_x64\\v2tap_x64.7z')
39 | print('| v2tap_x64.7z | ' + v2tap_x64_md5 + ' | ' + v2tap_x64_sha1 + ' | ' + v2tap_x64_sha256 + ' |')
40 |
41 | v2tap_x86_md5 = md5sum('v2tap\\bin\\Release_x86\\v2tap_x86\\v2tap_x86.7z')
42 | v2tap_x86_sha1 = sha1sum('v2tap\\bin\\Release_x86\\v2tap_x86\\v2tap_x86.7z')
43 | v2tap_x86_sha256 = sha256sum('v2tap\\bin\\Release_x86\\v2tap_x86\\v2tap_x86.7z')
44 | print('| v2tap_x86.7z | ' + v2tap_x86_md5 + ' | ' + v2tap_x86_sha1 + ' | ' + v2tap_x86_sha256 + ' |')
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://t.me/Holli_Freed)
2 |
3 | # 此项目已更名 x2tap 继续开发:[x2tap](https://github.com/hacking001/x2tap)
4 |
5 | # v2tap
6 | 基于 TUN/TAP + tun2socks + v2ray 实现的 VPN 工具
7 |
8 | # TODO
9 | - [x] 多代理配置支持
10 | - [x] 可以导入订阅(自动保存上一次的订阅链接,方便更新)
11 | - [x] 流量信息显示(当前速度和已使用总流量)
12 | - [x] VMess 协议支持 + 多种传输方式 + TCP、mKCP、QUIC 的伪装支持 + 支持 UDP 转发
13 | - [x] 像 SSTap 那样的外置规则列表(如何创建规则参见 [wiki](https://github.com/hacking001/v2tap/wiki/CreateMode))
14 | - [ ] 本地 DNS 代理(目前考虑 DoH 来拒绝污染,也支持普通 UDP 查询代理)
15 | - [ ] 给 v2tap 上一个图标
16 | - [ ] 导入界面有待改进
17 |
18 | # 依赖文件
19 | - [TAP Windows](https://build.openvpn.net/downloads/releases/latest/tap-windows-latest-stable.exe)
20 | - [v2ray-core](https://github.com/v2ray/v2ray-core/releases)
21 | - [tun2socks](https://github.com/hacking001/v2tap/tree/master/binaries)
22 |
23 | # 准备工作
24 | 1. 从 [releases](https://github.com/hacking001/v2tap/releases) 中下载最新版的包
25 | 2. 安装 `tap-windows-latest-stable.exe`,请务必一路 next,不懂请不要乱点
26 | 3. 可用的 v2ray 服务器(暂时不支持伪装)
27 |
28 | # 正式开始
29 | 1. 打开 `v2tap.exe` 点击添加按钮增加一个配置信息
30 |
31 | 
32 |
33 | 
34 |
35 | 2. 选择新添加的配置信息
36 |
37 | 
38 |
39 | 3. 检查 [Google](https://www.google.com/ncr) 是否可以正常访问
40 |
41 | 
42 |
--------------------------------------------------------------------------------
/binaries/.gitignore:
--------------------------------------------------------------------------------
1 | /tap-windows-latest-stable.exe
2 | /v2ray
--------------------------------------------------------------------------------
/binaries/tun2socks_x64.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leitianya/v2tap/eda922f5ff0c0b7a14414d0c9a864de6be6b3e15/binaries/tun2socks_x64.exe
--------------------------------------------------------------------------------
/binaries/tun2socks_x86.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leitianya/v2tap/eda922f5ff0c0b7a14414d0c9a864de6be6b3e15/binaries/tun2socks_x86.exe
--------------------------------------------------------------------------------
/modes/Cloudflare.txt:
--------------------------------------------------------------------------------
1 | 103.21.244.0/22
2 | 103.22.200.0/22
3 | 103.31.4.0/22
4 | 104.16.0.0/12
5 | 108.162.192.0/18
6 | 131.0.72.0/22
7 | 141.101.64.0/18
8 | 162.158.0.0/15
9 | 172.64.0.0/13
10 | 173.245.48.0/20
11 | 188.114.96.0/20
12 | 190.93.240.0/20
13 | 197.234.240.0/22
14 | 198.41.128.0/17
--------------------------------------------------------------------------------
/modes/Telegram.txt:
--------------------------------------------------------------------------------
1 | 91.108.56.0/23
2 | 91.108.56.0/22
3 | 91.108.4.0/22
4 | 149.154.172.0/22
5 | 149.154.168.0/22
6 | 149.154.164.0/22
7 | 109.239.140.0/24
--------------------------------------------------------------------------------
/screenshots/four.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leitianya/v2tap/eda922f5ff0c0b7a14414d0c9a864de6be6b3e15/screenshots/four.png
--------------------------------------------------------------------------------
/screenshots/one.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leitianya/v2tap/eda922f5ff0c0b7a14414d0c9a864de6be6b3e15/screenshots/one.png
--------------------------------------------------------------------------------
/screenshots/three.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leitianya/v2tap/eda922f5ff0c0b7a14414d0c9a864de6be6b3e15/screenshots/three.png
--------------------------------------------------------------------------------
/screenshots/two.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leitianya/v2tap/eda922f5ff0c0b7a14414d0c9a864de6be6b3e15/screenshots/two.png
--------------------------------------------------------------------------------
/v2tap.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.271
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "v2tap", "v2tap\v2tap.csproj", "{53132DC3-8A46-4558-978C-605A643D1300}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release x64|Any CPU = Release x64|Any CPU
12 | Release x86|Any CPU = Release x86|Any CPU
13 | EndGlobalSection
14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
15 | {53132DC3-8A46-4558-978C-605A643D1300}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
16 | {53132DC3-8A46-4558-978C-605A643D1300}.Debug|Any CPU.Build.0 = Debug|Any CPU
17 | {53132DC3-8A46-4558-978C-605A643D1300}.Release x64|Any CPU.ActiveCfg = Release x64|Any CPU
18 | {53132DC3-8A46-4558-978C-605A643D1300}.Release x64|Any CPU.Build.0 = Release x64|Any CPU
19 | {53132DC3-8A46-4558-978C-605A643D1300}.Release x86|Any CPU.ActiveCfg = Release x86|Any CPU
20 | {53132DC3-8A46-4558-978C-605A643D1300}.Release x86|Any CPU.Build.0 = Release x86|Any CPU
21 | EndGlobalSection
22 | GlobalSection(SolutionProperties) = preSolution
23 | HideSolutionNode = FALSE
24 | EndGlobalSection
25 | GlobalSection(ExtensibilityGlobals) = postSolution
26 | SolutionGuid = {F99FB451-F677-4A31-9F3C-4BA7BD189AF5}
27 | EndGlobalSection
28 | EndGlobal
29 |
--------------------------------------------------------------------------------
/v2tap/.gitignore:
--------------------------------------------------------------------------------
1 | /bin
2 | /obj
--------------------------------------------------------------------------------
/v2tap/3rd/IniParser/Exceptions/ParsingException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace IniParser.Exceptions
4 | {
5 | ///
6 | /// Represents an error ococcurred while parsing data
7 | ///
8 | public class ParsingException : Exception
9 | {
10 | public Version LibVersion {get; private set;}
11 | public int LineNumber {get; private set;}
12 | public string LineValue {get; private set;}
13 |
14 | public ParsingException(string msg)
15 | :this(msg, 0, string.Empty, null)
16 | {}
17 |
18 | public ParsingException(string msg, Exception innerException)
19 | :this(msg, 0, string.Empty, innerException)
20 | {}
21 |
22 | public ParsingException(string msg, int lineNumber, string lineValue)
23 | :this(msg, lineNumber, lineValue, null)
24 | {}
25 |
26 | public ParsingException(string msg, int lineNumber, string lineValue, Exception innerException)
27 | : base(
28 | string.Format(
29 | "{0} while parsing line number {1} with value \'{2}\' - IniParser version: {3}",
30 | msg, lineNumber, lineValue, System.Reflection.Assembly.GetExecutingAssembly().GetName().Version),
31 | innerException)
32 | {
33 | LibVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
34 | LineNumber = lineNumber;
35 | LineValue = lineValue;
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/v2tap/3rd/IniParser/FileIniParser.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Text;
4 | using IniParser.Exceptions;
5 | using IniParser.Model;
6 | using IniParser.Parser;
7 |
8 | namespace IniParser
9 | {
10 | ///
11 | /// Represents an INI data parser for files.
12 | ///
13 | public class FileIniDataParser : StreamIniDataParser
14 | {
15 | ///
16 | /// Ctor
17 | ///
18 | public FileIniDataParser() {}
19 |
20 | ///
21 | /// Ctor
22 | ///
23 | ///
24 | public FileIniDataParser(IniDataParser parser) : base(parser)
25 | {
26 | Parser = parser;
27 | }
28 |
29 | #region Deprecated methods
30 |
31 | [Obsolete("Please use ReadFile method instead of this one as is more semantically accurate")]
32 | public IniData LoadFile(string filePath)
33 | {
34 | return ReadFile(filePath);
35 | }
36 |
37 | [Obsolete("Please use ReadFile method instead of this one as is more semantically accurate")]
38 | public IniData LoadFile(string filePath, Encoding fileEncoding)
39 | {
40 | return ReadFile(filePath, fileEncoding);
41 | }
42 | #endregion
43 |
44 | ///
45 | /// Implements reading ini data from a file.
46 | ///
47 | ///
48 | /// Uses codification for the file.
49 | ///
50 | ///
51 | /// Path to the file
52 | ///
53 | public IniData ReadFile(string filePath)
54 | {
55 | return ReadFile(filePath, Encoding.ASCII);
56 | }
57 |
58 | ///
59 | /// Implements reading ini data from a file.
60 | ///
61 | ///
62 | /// Path to the file
63 | ///
64 | ///
65 | /// File's encoding.
66 | ///
67 | public IniData ReadFile(string filePath, Encoding fileEncoding)
68 | {
69 | if (filePath == string.Empty)
70 | throw new ArgumentException("Bad filename.");
71 |
72 | try
73 | {
74 | // (FileAccess.Read) we want to open the ini only for reading
75 | // (FileShare.ReadWrite) any other process should still have access to the ini file
76 | using (FileStream fs = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
77 | {
78 | using (StreamReader sr = new StreamReader(fs, fileEncoding))
79 | {
80 | return ReadData(sr);
81 | }
82 | }
83 | }
84 | catch (IOException ex)
85 | {
86 | throw new ParsingException(String.Format("Could not parse file {0}", filePath), ex);
87 | }
88 |
89 | }
90 |
91 | ///
92 | /// Saves INI data to a file.
93 | ///
94 | ///
95 | /// Creats an ASCII encoded file by default.
96 | ///
97 | ///
98 | /// Path to the file.
99 | ///
100 | ///
101 | /// IniData to be saved as an INI file.
102 | ///
103 | [Obsolete("Please use WriteFile method instead of this one as is more semantically accurate")]
104 | public void SaveFile(string filePath, IniData parsedData)
105 | {
106 | WriteFile(filePath, parsedData, Encoding.UTF8);
107 | }
108 |
109 | ///
110 | /// Writes INI data to a text file.
111 | ///
112 | ///
113 | /// Path to the file.
114 | ///
115 | ///
116 | /// IniData to be saved as an INI file.
117 | ///
118 | ///
119 | /// Specifies the encoding used to create the file.
120 | ///
121 | public void WriteFile(string filePath, IniData parsedData, Encoding fileEncoding = null)
122 | {
123 | // The default value can't be assigned as a default parameter value because it is not
124 | // a constant expression.
125 | if (fileEncoding == null)
126 | fileEncoding = Encoding.UTF8;
127 |
128 | if (string.IsNullOrEmpty(filePath))
129 | throw new ArgumentException("Bad filename.");
130 |
131 | if (parsedData == null)
132 | throw new ArgumentNullException("parsedData");
133 |
134 | using (FileStream fs = File.Open(filePath, FileMode.Create, FileAccess.Write))
135 | {
136 | using (StreamWriter sr = new StreamWriter(fs, fileEncoding))
137 | {
138 | WriteData(sr, parsedData);
139 | }
140 | }
141 | }
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/v2tap/3rd/IniParser/Helpers/Assert.cs:
--------------------------------------------------------------------------------
1 | namespace IniParser.Helpers
2 | {
3 | internal static class Assert
4 | {
5 | ///
6 | /// Asserts that a strings has no blank spaces.
7 | ///
8 | /// The string to be checked.
9 | ///
10 | internal static bool StringHasNoBlankSpaces(string s)
11 | {
12 | return !s.Contains(" ");
13 | }
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/v2tap/3rd/IniParser/Model/Configuration/ConcatenateDuplicatedKeysIniParserConfiguration.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text.RegularExpressions;
3 | using IniParser.Parser;
4 |
5 | namespace IniParser.Model.Configuration
6 | {
7 | public class ConcatenateDuplicatedKeysIniParserConfiguration : IniParserConfiguration
8 | {
9 | public new bool AllowDuplicateKeys { get {return true; }}
10 | public ConcatenateDuplicatedKeysIniParserConfiguration()
11 | :base()
12 | {
13 | this.ConcatenateSeparator = ";";
14 | }
15 |
16 | public ConcatenateDuplicatedKeysIniParserConfiguration(ConcatenateDuplicatedKeysIniParserConfiguration ori)
17 | :base(ori)
18 | {
19 | this.ConcatenateSeparator = ori.ConcatenateSeparator;
20 | }
21 |
22 | ///
23 | /// Gets or sets the string used to concatenate duplicated keys.
24 | ///
25 | /// Defaults to ';'.
26 | ///
27 | public string ConcatenateSeparator { get; set; }
28 | }
29 |
30 | }
--------------------------------------------------------------------------------
/v2tap/3rd/IniParser/Model/Configuration/IniParserConfiguration.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text.RegularExpressions;
3 | using IniParser.Parser;
4 |
5 | namespace IniParser.Model.Configuration
6 | {
7 | [Obsolete("Kept for backward compatibility, just use IniParserConfiguration class")]
8 | public class DefaultIniParserConfiguration : ConcatenateDuplicatedKeysIniParserConfiguration {}
9 |
10 | ///
11 | /// Defines data for a Parser configuration object.
12 | ///
13 | /// With a configuration object you can redefine how the parser
14 | /// will detect special items in the ini file by defining new regex
15 | /// (e.g. you can redefine the comment regex so it just treat text as
16 | /// a comment iff the comment caracter is the first in the line)
17 | /// or changing the set of characters used to define elements in
18 | /// the ini file (e.g. change the 'comment' caracter from ';' to '#')
19 | /// You can also define how the parser should treat errors, or how liberal
20 | /// or conservative should it be when parsing files with "strange" formats.
21 | public class IniParserConfiguration : ICloneable
22 | {
23 | #region Initialization
24 | ///
25 | /// Default values used if an instance of
26 | /// is created without specifying a configuration.
27 | ///
28 | ///
29 | /// By default the various delimiters for the data are setted:
30 | /// ';' for one-line comments
31 | /// '[' ']' for delimiting a section
32 | /// '=' for linking key / value pairs
33 | ///
34 | /// An example of well formed data with the default values:
35 | ///
36 | /// ;section comment
37 | /// [section] ; section comment
38 | ///
39 | /// ; key comment
40 | /// key = value ;key comment
41 | ///
42 | /// ;key2 comment
43 | /// key2 = value
44 | ///
45 | ///
46 | ///
47 | public IniParserConfiguration()
48 | {
49 | CommentString = ";";
50 | SectionStartChar = '[';
51 | SectionEndChar = ']';
52 | KeyValueAssigmentChar = '=';
53 | AssigmentSpacer = " ";
54 | NewLineStr = Environment.NewLine;
55 | ConcatenateDuplicateKeys = false;
56 | AllowKeysWithoutSection = true;
57 | AllowDuplicateKeys = false;
58 | AllowDuplicateSections = false;
59 | AllowCreateSectionsOnFly = true;
60 | ThrowExceptionsOnError = true;
61 | SkipInvalidLines = false;
62 | }
63 |
64 | ///
65 | /// Copy ctor.
66 | ///
67 | ///
68 | /// Original instance to be copied.
69 | ///
70 | public IniParserConfiguration(IniParserConfiguration ori)
71 | {
72 | AllowDuplicateKeys = ori.AllowDuplicateKeys;
73 | OverrideDuplicateKeys = ori.OverrideDuplicateKeys;
74 | AllowDuplicateSections = ori.AllowDuplicateSections;
75 | AllowKeysWithoutSection = ori.AllowKeysWithoutSection;
76 | AllowCreateSectionsOnFly = ori.AllowCreateSectionsOnFly;
77 |
78 | SectionStartChar = ori.SectionStartChar;
79 | SectionEndChar = ori.SectionEndChar;
80 | CommentString = ori.CommentString;
81 | ThrowExceptionsOnError = ori.ThrowExceptionsOnError;
82 |
83 | // Regex values should recreate themselves.
84 | }
85 | #endregion
86 |
87 | #region IniParserConfiguration
88 |
89 | public Regex CommentRegex { get; set; }
90 |
91 | public Regex SectionRegex { get; set; }
92 |
93 | ///
94 | /// Sets the char that defines the start of a section name.
95 | ///
96 | ///
97 | /// Defaults to character '['
98 | ///
99 | public char SectionStartChar
100 | {
101 | get { return _sectionStartChar; }
102 | set
103 | {
104 | _sectionStartChar = value;
105 | RecreateSectionRegex(_sectionStartChar);
106 | }
107 | }
108 |
109 | ///
110 | /// Sets the char that defines the end of a section name.
111 | ///
112 | ///
113 | /// Defaults to character ']'
114 | ///
115 | public char SectionEndChar
116 | {
117 | get { return _sectionEndChar; }
118 | set
119 | {
120 | _sectionEndChar = value;
121 | RecreateSectionRegex(_sectionEndChar);
122 | }
123 | }
124 |
125 | ///
126 | /// Retrieving section / keys by name is done with a case-insensitive
127 | /// search.
128 | ///
129 | ///
130 | /// Defaults to false (case sensitive search)
131 | ///
132 | public bool CaseInsensitive{ get; set; }
133 |
134 | ///
135 | /// Sets the char that defines the start of a comment.
136 | /// A comment spans from the comment character to the end of the line.
137 | ///
138 | ///
139 | /// Defaults to character ';'
140 | ///
141 | [Obsolete("Please use the CommentString property")]
142 | public char CommentChar
143 | {
144 | get { return CommentString[0]; }
145 | set { CommentString = value.ToString(); }
146 | }
147 |
148 | ///
149 | /// Sets the string that defines the start of a comment.
150 | /// A comment spans from the mirst matching comment string
151 | /// to the end of the line.
152 | ///
153 | ///
154 | /// Defaults to string ";"
155 | ///
156 | public string CommentString
157 | {
158 |
159 | get { return _commentString ?? string.Empty; }
160 | set
161 | {
162 | // Sanitarize special characters for a regex
163 | foreach (var specialChar in _strSpecialRegexChars)
164 | {
165 | value = value.Replace(new String(specialChar, 1), @"\" + specialChar);
166 | }
167 |
168 | CommentRegex = new Regex(string.Format(_strCommentRegex, value));
169 | _commentString = value;
170 | }
171 | }
172 |
173 | ///
174 | /// Gets or sets the string to use as new line string when formating an IniData structure using a
175 | /// IIniDataFormatter. Parsing an ini-file accepts any new line character (Unix/windows)
176 | ///
177 | ///
178 | /// This allows to write a file with unix new line characters on windows (and vice versa)
179 | ///
180 | /// Defaults to value Environment.NewLine
181 | public string NewLineStr
182 | {
183 | get; set;
184 | }
185 | ///
186 | /// Sets the char that defines a value assigned to a key
187 | ///
188 | ///
189 | /// Defaults to character '='
190 | ///
191 | public char KeyValueAssigmentChar { get; set; }
192 |
193 | ///
194 | /// Sets the string around KeyValuesAssignmentChar
195 | ///
196 | ///
197 | /// Defaults to string ' '
198 | ///
199 | public string AssigmentSpacer { get; set; }
200 |
201 | ///
202 | /// Allows having keys in the file that don't belong to any section.
203 | /// i.e. allows defining keys before defining a section.
204 | /// If set to false and keys without a section are defined,
205 | /// the will stop with an error.
206 | ///
207 | ///
208 | /// Defaults to true.
209 | ///
210 | public bool AllowKeysWithoutSection { get; set; }
211 |
212 | ///
213 | /// If set to false and the finds duplicate keys in a
214 | /// section the parser will stop with an error.
215 | /// If set to true, duplicated keys are allowed in the file. The value
216 | /// of the duplicate key will be the last value asigned to the key in the file.
217 | ///
218 | ///
219 | /// Defaults to false.
220 | ///
221 | public bool AllowDuplicateKeys { get; set; }
222 |
223 | ///
224 | /// Only used if is also true
225 | /// If set to true when the parser finds a duplicate key, it overrites
226 | /// the previous value, so the key will always contain the value of the
227 | /// last key readed in the file
228 | /// If set to false the first readed value is preserved, so the key will
229 | /// always contain the value of the first key readed in the file
230 | ///
231 | ///
232 | /// Defaults to false.
233 | ///
234 | public bool OverrideDuplicateKeys { get; set; }
235 |
236 | ///
237 | /// Gets or sets a value indicating whether duplicate keys are concatenate
238 | /// together by .
239 | ///
240 | ///
241 | /// Defaults to false.
242 | ///
243 | public bool ConcatenateDuplicateKeys { get; set; }
244 |
245 | ///
246 | /// If true the instance will thrown an exception
247 | /// if an error is found.
248 | /// If false the parser will just stop execution and return a null value.
249 | ///
250 | ///
251 | /// Defaults to true.
252 | ///
253 | public bool ThrowExceptionsOnError { get; set; }
254 |
255 | ///
256 | /// If set to false and the finds a duplicate section
257 | /// the parser will stop with an error.
258 | /// If set to true, duplicated sections are allowed in the file, but only a
259 | /// element will be created in the
260 | /// collection.
261 | ///
262 | ///
263 | /// Defaults to false.
264 | ///
265 | public bool AllowDuplicateSections { get; set; }
266 |
267 | ///
268 | /// If set to false, the stop with a error if you try
269 | /// to access a section that was not created previously and the parser will stop with an error.
270 | /// If set to true, inexistents sections are created, always returning a valid
271 | /// element.
272 | ///
273 | ///
274 | /// Defaults to false.
275 | ///
276 | public bool AllowCreateSectionsOnFly { get; set; }
277 |
278 | public bool SkipInvalidLines { get; set; }
279 |
280 | #endregion
281 |
282 | #region Fields
283 | private char _sectionStartChar;
284 | private char _sectionEndChar;
285 | private string _commentString;
286 | #endregion
287 |
288 | #region Constants
289 | protected const string _strCommentRegex = @"^{0}(.*)";
290 | protected const string _strSectionRegexStart = @"^(\s*?)";
291 | protected const string _strSectionRegexMiddle = @"{1}\s*[\p{L}\p{P}\p{M}_\""\'\{\}\#\+\;\*\%\(\)\=\?\&\$\,\:\/\.\-\w\d\s\\\~]+\s*";
292 | protected const string _strSectionRegexEnd = @"(\s*?)$";
293 | protected const string _strKeyRegex = @"^(\s*[_\.\d\w]*\s*)";
294 | protected const string _strValueRegex = @"([\s\d\w\W\.]*)$";
295 | protected const string _strSpecialRegexChars = @"[]\^$.|?*+()";
296 | #endregion
297 |
298 | #region Helpers
299 | private void RecreateSectionRegex(char value)
300 | {
301 | if (char.IsControl(value)
302 | || char.IsWhiteSpace(value)
303 | || CommentString.Contains(new string(new [] {value}))
304 | || value == KeyValueAssigmentChar)
305 | throw new Exception(string.Format("Invalid character for section delimiter: '{0}", value));
306 |
307 | string builtRegexString = _strSectionRegexStart;
308 |
309 | if (_strSpecialRegexChars.Contains(new string(_sectionStartChar, 1)))
310 | builtRegexString += "\\" + _sectionStartChar;
311 | else builtRegexString += _sectionStartChar;
312 |
313 | builtRegexString += _strSectionRegexMiddle;
314 |
315 | if (_strSpecialRegexChars.Contains(new string(_sectionEndChar, 1)))
316 | builtRegexString += "\\" + _sectionEndChar;
317 | else
318 | builtRegexString += _sectionEndChar;
319 |
320 | builtRegexString += _strSectionRegexEnd;
321 |
322 | SectionRegex = new Regex(builtRegexString);
323 | }
324 | #endregion
325 |
326 | public override int GetHashCode()
327 | {
328 | var hash = 27;
329 | foreach (var property in GetType().GetProperties())
330 | {
331 | hash = (hash * 7) + property.GetValue(this, null).GetHashCode();
332 | }
333 |
334 | return hash;
335 | }
336 |
337 | public override bool Equals(object obj)
338 | {
339 | var copyObj = obj as IniParserConfiguration;
340 | if (copyObj == null) return false;
341 |
342 | var oriType = this.GetType();
343 | try
344 | {
345 | foreach (var property in oriType.GetProperties())
346 | {
347 | if (property.GetValue(copyObj, null).Equals(property.GetValue(this, null)))
348 | {
349 | return false;
350 | }
351 | }
352 | }
353 | catch
354 | {
355 | return false;
356 | }
357 |
358 | return true;
359 | }
360 |
361 | #region ICloneable Members
362 | ///
363 | /// Creates a new object that is a copy of the current instance.
364 | ///
365 | ///
366 | /// A new object that is a copy of this instance.
367 | ///
368 | /// 2
369 | public IniParserConfiguration Clone()
370 | {
371 | return this.MemberwiseClone() as IniParserConfiguration;
372 | }
373 |
374 | object ICloneable.Clone()
375 | {
376 | return this.Clone();
377 | }
378 |
379 | #endregion
380 | }
381 | }
382 |
--------------------------------------------------------------------------------
/v2tap/3rd/IniParser/Model/Formatting/DefaultIniDataFormatter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using IniParser.Model.Configuration;
5 |
6 | namespace IniParser.Model.Formatting
7 | {
8 |
9 | public class DefaultIniDataFormatter : IIniDataFormatter
10 | {
11 | IniParserConfiguration _configuration;
12 |
13 | #region Initialization
14 | public DefaultIniDataFormatter():this(new IniParserConfiguration()) {}
15 |
16 | public DefaultIniDataFormatter(IniParserConfiguration configuration)
17 | {
18 | if (configuration == null)
19 | throw new ArgumentNullException("configuration");
20 | this.Configuration = configuration;
21 | }
22 | #endregion
23 |
24 | public virtual string IniDataToString(IniData iniData)
25 | {
26 | var sb = new StringBuilder();
27 |
28 | if (Configuration.AllowKeysWithoutSection)
29 | {
30 | // Write global key/value data
31 | WriteKeyValueData(iniData.Global, sb);
32 | }
33 |
34 | //Write sections
35 | foreach (SectionData section in iniData.Sections)
36 | {
37 | //Write current section
38 | WriteSection(section, sb);
39 | }
40 |
41 | return sb.ToString();
42 | }
43 |
44 | ///
45 | /// Configuration used to write an ini file with the proper
46 | /// delimiter characters and data.
47 | ///
48 | ///
49 | /// If the instance was created by a parser,
50 | /// this instance is a copy of the used
51 | /// by the parser (i.e. different objects instances)
52 | /// If this instance is created programatically without using a parser, this
53 | /// property returns an instance of
54 | ///
55 | public IniParserConfiguration Configuration
56 | {
57 | get { return _configuration; }
58 | set { _configuration = value.Clone(); }
59 | }
60 |
61 | #region Helpers
62 |
63 | private void WriteSection(SectionData section, StringBuilder sb)
64 | {
65 | // Write blank line before section, but not if it is the first line
66 | if (sb.Length > 0) sb.Append(Configuration.NewLineStr);
67 |
68 | // Leading comments
69 | WriteComments(section.LeadingComments, sb);
70 |
71 | //Write section name
72 | sb.Append(string.Format("{0}{1}{2}{3}",
73 | Configuration.SectionStartChar,
74 | section.SectionName,
75 | Configuration.SectionEndChar,
76 | Configuration.NewLineStr));
77 |
78 | WriteKeyValueData(section.Keys, sb);
79 |
80 | // Trailing comments
81 | WriteComments(section.TrailingComments, sb);
82 | }
83 |
84 | private void WriteKeyValueData(KeyDataCollection keyDataCollection, StringBuilder sb)
85 | {
86 |
87 | foreach (KeyData keyData in keyDataCollection)
88 | {
89 | // Add a blank line if the key value pair has comments
90 | if (keyData.Comments.Count > 0) sb.Append(Configuration.NewLineStr);
91 |
92 | // Write key comments
93 | WriteComments(keyData.Comments, sb);
94 |
95 | //Write key and value
96 | sb.Append(string.Format("{0}{3}{1}{3}{2}{4}",
97 | keyData.KeyName,
98 | Configuration.KeyValueAssigmentChar,
99 | keyData.Value,
100 | Configuration.AssigmentSpacer,
101 | Configuration.NewLineStr));
102 | }
103 | }
104 |
105 | private void WriteComments(List comments, StringBuilder sb)
106 | {
107 | foreach (string comment in comments)
108 | sb.Append(string.Format("{0}{1}{2}", Configuration.CommentString, comment, Configuration.NewLineStr));
109 | }
110 | #endregion
111 |
112 | }
113 |
114 | }
--------------------------------------------------------------------------------
/v2tap/3rd/IniParser/Model/Formatting/IIniDataFormatter.cs:
--------------------------------------------------------------------------------
1 | using IniParser.Model.Configuration;
2 |
3 | namespace IniParser.Model.Formatting
4 | {
5 | ///
6 | /// Formats a IniData structure to an string
7 | ///
8 | public interface IIniDataFormatter
9 | {
10 | ///
11 | /// Produces an string given
12 | ///
13 | /// The data to string.
14 | /// Ini data.
15 | string IniDataToString(IniData iniData);
16 |
17 | ///
18 | /// Configuration used by this formatter when converting IniData
19 | /// to an string
20 | ///
21 | IniParserConfiguration Configuration {get;set;}
22 | }
23 |
24 | }
--------------------------------------------------------------------------------
/v2tap/3rd/IniParser/Model/IniData.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using IniParser.Model.Configuration;
3 | using IniParser.Model.Formatting;
4 |
5 | namespace IniParser.Model
6 | {
7 | ///
8 | /// Represents all data from an INI file
9 | ///
10 | public class IniData : ICloneable
11 | {
12 | #region Non-Public Members
13 | ///
14 | /// Represents all sections from an INI file
15 | ///
16 | private SectionDataCollection _sections;
17 | #endregion
18 |
19 | #region Initialization
20 |
21 | ///
22 | /// Initializes an empty IniData instance.
23 | ///
24 | public IniData()
25 | : this(new SectionDataCollection())
26 | { }
27 |
28 | ///
29 | /// Initializes a new IniData instance using a previous
30 | /// .
31 | ///
32 | ///
33 | /// object containing the
34 | /// data with the sections of the file
35 | ///
36 | public IniData(SectionDataCollection sdc)
37 | {
38 | _sections = (SectionDataCollection)sdc.Clone();
39 | Global = new KeyDataCollection();
40 | SectionKeySeparator = '.';
41 | }
42 |
43 | public IniData(IniData ori): this((SectionDataCollection)ori.Sections)
44 | {
45 | Global = (KeyDataCollection)ori.Global.Clone();
46 | Configuration = ori.Configuration.Clone();
47 | }
48 | #endregion
49 |
50 | #region Properties
51 |
52 | ///
53 | /// Configuration used to write an ini file with the proper
54 | /// delimiter characters and data.
55 | ///
56 | ///
57 | /// If the instance was created by a parser,
58 | /// this instance is a copy of the used
59 | /// by the parser (i.e. different objects instances)
60 | /// If this instance is created programatically without using a parser, this
61 | /// property returns an instance of
62 | ///
63 | public IniParserConfiguration Configuration
64 | {
65 | get
66 | {
67 | // Lazy initialization
68 | if (_configuration == null)
69 | _configuration = new IniParserConfiguration();
70 |
71 | return _configuration;
72 | }
73 |
74 | set { _configuration = value.Clone(); }
75 | }
76 |
77 | ///
78 | /// Global sections. Contains key/value pairs which are not
79 | /// enclosed in any section (i.e. they are defined at the beginning
80 | /// of the file, before any section.
81 | ///
82 | public KeyDataCollection Global { get; protected set; }
83 |
84 | ///
85 | /// Gets the instance
86 | /// with the specified section name.
87 | ///
88 | public KeyDataCollection this[string sectionName]
89 | {
90 | get
91 | {
92 | if (!_sections.ContainsSection(sectionName))
93 | if (Configuration.AllowCreateSectionsOnFly)
94 | _sections.AddSection(sectionName);
95 | else
96 | return null;
97 |
98 | return _sections[sectionName];
99 | }
100 | }
101 |
102 | ///
103 | /// Gets or sets all the
104 | /// for this IniData instance.
105 | ///
106 | public SectionDataCollection Sections
107 | {
108 | get { return _sections; }
109 | set { _sections = value; }
110 | }
111 |
112 | ///
113 | /// Used to mark the separation between the section name and the key name
114 | /// when using .
115 | ///
116 | ///
117 | /// Defaults to '.'.
118 | ///
119 | public char SectionKeySeparator { get; set; }
120 | #endregion
121 |
122 | #region Object Methods
123 | public override string ToString()
124 | {
125 | return ToString(new DefaultIniDataFormatter(Configuration));
126 | }
127 |
128 | public virtual string ToString(IIniDataFormatter formatter)
129 | {
130 | return formatter.IniDataToString(this);
131 | }
132 | #endregion
133 |
134 | #region ICloneable Members
135 |
136 | ///
137 | /// Creates a new object that is a copy of the current instance.
138 | ///
139 | ///
140 | /// A new object that is a copy of this instance.
141 | ///
142 | public object Clone()
143 | {
144 | return new IniData(this);
145 | }
146 |
147 | #endregion
148 |
149 | #region Fields
150 | ///
151 | /// See property for more information.
152 | ///
153 | private IniParserConfiguration _configuration;
154 | #endregion
155 |
156 | ///
157 | /// Deletes all comments in all sections and key values
158 | ///
159 | public void ClearAllComments()
160 | {
161 | Global.ClearComments();
162 |
163 | foreach(var section in Sections)
164 | {
165 | section.ClearComments();
166 | }
167 | }
168 |
169 | ///
170 | /// Merges the other iniData into this one by overwriting existing values.
171 | /// Comments get appended.
172 | ///
173 | ///
174 | /// IniData instance to merge into this.
175 | /// If it is null this operation does nothing.
176 | ///
177 | public void Merge(IniData toMergeIniData)
178 | {
179 |
180 | if (toMergeIniData == null) return;
181 |
182 | Global.Merge(toMergeIniData.Global);
183 |
184 | Sections.Merge(toMergeIniData.Sections);
185 |
186 | }
187 |
188 | ///
189 | /// Attempts to retrieve a key, using a single string combining section and
190 | /// key name.
191 | ///
192 | ///
193 | /// The section and key name to retrieve, separated by .
194 | ///
195 | /// If key contains no separator, it is treated as a key in the section.
196 | ///
197 | /// Key may contain no more than one separator character.
198 | ///
199 | ///
200 | /// If true is returned, is set to the value retrieved. Otherwise, is set
201 | /// to an empty string.
202 | ///
203 | ///
204 | /// True if key was found, otherwise false.
205 | ///
206 | ///
207 | /// key contained multiple separators.
208 | ///
209 | public bool TryGetKey(string key, out string value)
210 | {
211 | value = string.Empty;
212 | if (string.IsNullOrEmpty(key))
213 | return false;
214 |
215 | var splitKey = key.Split(SectionKeySeparator);
216 | var separatorCount = splitKey.Length - 1;
217 | if (separatorCount > 1)
218 | throw new ArgumentException("key contains multiple separators", "key");
219 |
220 | if (separatorCount == 0)
221 | {
222 | if (!Global.ContainsKey(key))
223 | return false;
224 |
225 | value = Global[key];
226 | return true;
227 | }
228 |
229 | var section = splitKey[0];
230 | key = splitKey[1];
231 |
232 | if (!_sections.ContainsSection(section))
233 | return false;
234 | var sectionData = _sections[section];
235 | if (!sectionData.ContainsKey(key))
236 | return false;
237 |
238 | value = sectionData[key];
239 | return true;
240 | }
241 |
242 | ///
243 | /// Retrieves a key using a single input string combining section and key name.
244 | ///
245 | ///
246 | /// The section and key name to retrieve, separated by .
247 | ///
248 | /// If key contains no separator, it is treated as a key in the section.
249 | ///
250 | /// Key may contain no more than one separator character.
251 | ///
252 | ///
253 | /// The key's value if it was found, otherwise null.
254 | ///
255 | ///
256 | /// key contained multiple separators.
257 | ///
258 | public string GetKey(string key)
259 | {
260 | string result;
261 | return TryGetKey(key, out result) ? result : null;
262 | }
263 |
264 | ///
265 | /// Merge the sections into this by overwriting this sections.
266 | ///
267 | private void MergeSection(SectionData otherSection)
268 | {
269 | // no overlap -> create no section
270 | if (!Sections.ContainsSection(otherSection.SectionName))
271 | {
272 | Sections.AddSection(otherSection.SectionName);
273 | }
274 |
275 | // merge section into the new one
276 | Sections.GetSectionData(otherSection.SectionName).Merge(otherSection);
277 | }
278 |
279 | ///
280 | /// Merges the given global values into this globals by overwriting existing values.
281 | ///
282 | private void MergeGlobal(KeyDataCollection globals)
283 | {
284 | foreach (var globalValue in globals)
285 | {
286 | Global[globalValue.KeyName] = globalValue.Value;
287 | }
288 | }
289 | }
290 | }
--------------------------------------------------------------------------------
/v2tap/3rd/IniParser/Model/IniDataCaseInsensitive.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using IniParser.Model.Configuration;
3 | using IniParser.Model.Formatting;
4 |
5 | namespace IniParser.Model
6 | {
7 | ///
8 | /// Represents all data from an INI file exactly as the
9 | /// class, but searching for sections and keys names is done with
10 | /// a case insensitive search.
11 | ///
12 | public class IniDataCaseInsensitive : IniData
13 | {
14 | ///
15 | /// Initializes an empty IniData instance.
16 | ///
17 | public IniDataCaseInsensitive()
18 | : base (new SectionDataCollection(StringComparer.OrdinalIgnoreCase))
19 | {
20 | Global = new KeyDataCollection(StringComparer.OrdinalIgnoreCase);
21 | }
22 |
23 | ///
24 | /// Initializes a new IniData instance using a previous
25 | /// .
26 | ///
27 | ///
28 | /// object containing the
29 | /// data with the sections of the file
30 | ///
31 | public IniDataCaseInsensitive(SectionDataCollection sdc)
32 | : base (new SectionDataCollection(sdc, StringComparer.OrdinalIgnoreCase))
33 | {
34 | Global = new KeyDataCollection(StringComparer.OrdinalIgnoreCase);
35 | }
36 |
37 | ///
38 | /// Copies an instance of the class
39 | ///
40 | /// Original
41 | public IniDataCaseInsensitive(IniData ori)
42 | : this(new SectionDataCollection(ori.Sections, StringComparer.OrdinalIgnoreCase))
43 | {
44 | Global = (KeyDataCollection) ori.Global.Clone();
45 | Configuration = ori.Configuration.Clone();
46 | }
47 | }
48 |
49 | }
--------------------------------------------------------------------------------
/v2tap/3rd/IniParser/Model/KeyData.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace IniParser.Model
5 | {
6 | ///
7 | /// Information associated to a key from an INI file.
8 | /// Includes both the value and the comments associated to the key.
9 | ///
10 | public class KeyData : ICloneable
11 | {
12 | #region Initialization
13 |
14 | ///
15 | /// Initializes a new instance of the class.
16 | ///
17 | public KeyData(string keyName)
18 | {
19 | if(string.IsNullOrEmpty(keyName))
20 | throw new ArgumentException("key name can not be empty");
21 |
22 | _comments = new List();
23 | _value = string.Empty;
24 | _keyName = keyName;
25 | }
26 |
27 | ///
28 | /// Initializes a new instance of the class
29 | /// from a previous instance of .
30 | ///
31 | ///
32 | /// Data is deeply copied
33 | ///
34 | ///
35 | /// The instance of the class
36 | /// used to create the new instance.
37 | ///
38 | public KeyData(KeyData ori)
39 | {
40 | _value = ori._value;
41 | _keyName = ori._keyName;
42 | _comments = new List(ori._comments);
43 | }
44 |
45 | #endregion Constructors
46 |
47 | #region Properties
48 |
49 | ///
50 | /// Gets or sets the comment list associated to this key.
51 | ///
52 | public List Comments
53 | {
54 | get { return _comments; }
55 | set { _comments = new List (value) ; }
56 | }
57 |
58 | ///
59 | /// Gets or sets the value associated to this key.
60 | ///
61 | public string Value
62 | {
63 | get { return _value; }
64 | set { _value = value; }
65 | }
66 |
67 | ///
68 | /// Gets or sets the name of the key.
69 | ///
70 | public string KeyName
71 | {
72 | get
73 | {
74 | return _keyName;
75 | }
76 |
77 | set
78 | {
79 | if (value != string.Empty)
80 | _keyName = value;
81 | }
82 |
83 | }
84 |
85 | #endregion Properties
86 |
87 | #region ICloneable Members
88 |
89 | ///
90 | /// Creates a new object that is a copy of the current instance.
91 | ///
92 | ///
93 | /// A new object that is a copy of this instance.
94 | ///
95 | public object Clone()
96 | {
97 | return new KeyData(this);
98 | }
99 |
100 | #endregion
101 |
102 | #region Non-public Members
103 |
104 | // List with comment lines associated to this key
105 | private List _comments;
106 |
107 | // Unique value associated to this key
108 | private string _value;
109 |
110 | // Name of the current key
111 | private string _keyName;
112 |
113 | #endregion
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/v2tap/3rd/IniParser/Model/KeyDataCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 |
5 | namespace IniParser.Model
6 | {
7 | ///
8 | /// Represents a collection of Keydata.
9 | ///
10 | public class KeyDataCollection : ICloneable, IEnumerable
11 | {
12 | IEqualityComparer _searchComparer;
13 | #region Initialization
14 |
15 | ///
16 | /// Initializes a new instance of the class.
17 | ///
18 | public KeyDataCollection()
19 | : this(EqualityComparer.Default)
20 | { }
21 |
22 | ///
23 | /// Initializes a new instance of the class with a given
24 | /// search comparer
25 | ///
26 | ///
27 | /// Search comparer used to find the key by name in the collection
28 | ///
29 | public KeyDataCollection(IEqualityComparer searchComparer)
30 | {
31 | _searchComparer = searchComparer;
32 | _keyData = new Dictionary(_searchComparer);
33 | }
34 |
35 | ///
36 | /// Initializes a new instance of the class
37 | /// from a previous instance of .
38 | ///
39 | ///
40 | /// Data from the original KeyDataCollection instance is deeply copied
41 | ///
42 | ///
43 | /// The instance of the class
44 | /// used to create the new instance.
45 | ///
46 | public KeyDataCollection(KeyDataCollection ori, IEqualityComparer searchComparer)
47 | : this(searchComparer)
48 | {
49 | foreach (KeyData key in ori)
50 | {
51 | if (_keyData.ContainsKey(key.KeyName))
52 | {
53 | _keyData[key.KeyName] = (KeyData)key.Clone();
54 | }
55 | else
56 | {
57 | _keyData.Add(key.KeyName, (KeyData)key.Clone());
58 | }
59 | }
60 | }
61 |
62 | #endregion
63 |
64 | #region Properties
65 |
66 | ///
67 | /// Gets or sets the value of a concrete key.
68 | ///
69 | ///
70 | /// If we try to assign the value of a key which doesn't exists,
71 | /// a new key is added with the name and the value is assigned to it.
72 | ///
73 | ///
74 | /// Name of the key
75 | ///
76 | ///
77 | /// The string with key's value or null if the key was not found.
78 | ///
79 | public string this[string keyName]
80 | {
81 | get
82 | {
83 | if (_keyData.ContainsKey(keyName))
84 | return _keyData[keyName].Value;
85 |
86 | return null;
87 | }
88 |
89 | set
90 | {
91 | if (!_keyData.ContainsKey(keyName))
92 | {
93 | this.AddKey(keyName);
94 | }
95 |
96 | _keyData[keyName].Value = value;
97 |
98 | }
99 | }
100 |
101 | ///
102 | /// Return the number of keys in the collection
103 | ///
104 | public int Count
105 | {
106 | get { return _keyData.Count; }
107 | }
108 |
109 | #endregion
110 |
111 | #region Operations
112 |
113 | ///
114 | /// Adds a new key with the specified name and empty value and comments
115 | ///
116 | ///
117 | /// New key to be added.
118 | ///
119 | /// true if the key was added false if a key with the same name already exist
120 | /// in the collection
121 | ///
122 | public bool AddKey(string keyName)
123 | {
124 | if (!_keyData.ContainsKey(keyName))
125 | {
126 | _keyData.Add(keyName, new KeyData(keyName));
127 | return true;
128 | }
129 |
130 | return false;
131 | }
132 |
133 | [Obsolete("Pottentially buggy method! Use AddKey(KeyData keyData) instead (See comments in code for an explanation of the bug)")]
134 | public bool AddKey(string keyName, KeyData keyData)
135 | {
136 | // BUG: this actually can allow you to add the keyData having
137 | // keyData.KeyName different from the argument 'keyName' in this method
138 | // which doesn't make any sense
139 | if (AddKey(keyName))
140 | {
141 | _keyData[keyName] = keyData;
142 | return true;
143 | }
144 |
145 | return false;
146 |
147 | }
148 |
149 | ///
150 | /// Adds a new key to the collection
151 | ///
152 | ///
153 | /// KeyData instance.
154 | ///
155 | ///
156 | /// true if the key was added false if a key with the same name already exist
157 | /// in the collection
158 | ///
159 | public bool AddKey(KeyData keyData)
160 | {
161 | if (AddKey(keyData.KeyName))
162 | {
163 | _keyData[keyData.KeyName] = keyData;
164 | return true;
165 | }
166 |
167 | return false;
168 | }
169 | ///
170 | /// Adds a new key with the specified name and value to the collection
171 | ///
172 | ///
173 | /// Name of the new key to be added.
174 | ///
175 | ///
176 | /// Value associated to the key.
177 | ///
178 | ///
179 | /// true if the key was added false if a key with the same name already exist
180 | /// in the collection.
181 | ///
182 | public bool AddKey(string keyName, string keyValue)
183 | {
184 | if (AddKey(keyName))
185 | {
186 | _keyData[keyName].Value = keyValue;
187 | return true;
188 | }
189 |
190 | return false;
191 |
192 | }
193 |
194 | ///
195 | /// Clears all comments of this section
196 | ///
197 | public void ClearComments()
198 | {
199 | foreach (var keydata in this)
200 | {
201 | keydata.Comments.Clear();
202 | }
203 | }
204 |
205 | ///
206 | /// Gets if a specifyed key name exists in the collection.
207 | ///
208 | /// Key name to search
209 | /// true if a key with the specified name exists in the collectoin
210 | /// false otherwise
211 | public bool ContainsKey(string keyName)
212 | {
213 | return _keyData.ContainsKey(keyName);
214 | }
215 |
216 | ///
217 | /// Retrieves the data for a specified key given its name
218 | ///
219 | /// Name of the key to retrieve.
220 | ///
221 | /// A instance holding
222 | /// the key information or null if the key wasn't found.
223 | ///
224 | public KeyData GetKeyData(string keyName)
225 | {
226 | if (_keyData.ContainsKey(keyName))
227 | return _keyData[keyName];
228 | return null;
229 | }
230 |
231 | public void Merge(KeyDataCollection keyDataToMerge)
232 | {
233 | foreach (var keyData in keyDataToMerge)
234 | {
235 | AddKey(keyData.KeyName);
236 | GetKeyData(keyData.KeyName).Comments.AddRange(keyData.Comments);
237 | this[keyData.KeyName] = keyData.Value;
238 | }
239 |
240 | }
241 |
242 | ///
243 | /// Deletes all keys in this collection.
244 | ///
245 | public void RemoveAllKeys()
246 | {
247 | _keyData.Clear();
248 | }
249 |
250 | ///
251 | /// Deletes a previously existing key, including its associated data.
252 | ///
253 | /// The key to be removed.
254 | ///
255 | /// true if a key with the specified name was removed
256 | /// false otherwise.
257 | ///
258 | public bool RemoveKey(string keyName)
259 | {
260 | return _keyData.Remove(keyName);
261 | }
262 | ///
263 | /// Sets the key data associated to a specified key.
264 | ///
265 | /// The new for the key.
266 | public void SetKeyData(KeyData data)
267 | {
268 | if (data == null) return;
269 |
270 | if (_keyData.ContainsKey(data.KeyName))
271 | RemoveKey(data.KeyName);
272 |
273 | AddKey(data);
274 | }
275 |
276 | #endregion
277 |
278 | #region IEnumerable Members
279 |
280 | ///
281 | /// Allows iteration througt the collection.
282 | ///
283 | /// A strong-typed IEnumerator
284 | public IEnumerator GetEnumerator()
285 | {
286 | foreach (string key in _keyData.Keys)
287 | yield return _keyData[key];
288 | }
289 |
290 | #region IEnumerable Members
291 |
292 | ///
293 | /// Implementation needed
294 | ///
295 | /// A weak-typed IEnumerator.
296 | IEnumerator IEnumerable.GetEnumerator()
297 | {
298 | return _keyData.GetEnumerator();
299 | }
300 |
301 | #endregion
302 |
303 | #endregion
304 |
305 | #region ICloneable Members
306 |
307 |
308 | ///
309 | /// Creates a new object that is a copy of the current instance.
310 | ///
311 | ///
312 | /// A new object that is a copy of this instance.
313 | ///
314 | public object Clone()
315 | {
316 | return new KeyDataCollection(this, _searchComparer);
317 | }
318 |
319 | #endregion
320 |
321 | #region Non-public Members
322 | // Hack for getting the last key value (if exists) w/out using LINQ
323 | // and maintain support for earlier versions of .NET
324 | internal KeyData GetLast()
325 | {
326 | KeyData result = null;
327 | if (_keyData.Keys.Count <= 0) return result;
328 |
329 |
330 | foreach (var k in _keyData.Keys) result = _keyData[k];
331 | return result;
332 | }
333 |
334 | ///
335 | /// Collection of KeyData for a given section
336 | ///
337 | private readonly Dictionary _keyData;
338 |
339 | #endregion
340 |
341 | }
342 | }
--------------------------------------------------------------------------------
/v2tap/3rd/IniParser/Model/SectionData.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace IniParser.Model
5 | {
6 | ///
7 | /// Information associated to a section in a INI File
8 | /// Includes both the value and the comments associated to the key.
9 | ///
10 | public class SectionData : ICloneable
11 | {
12 | IEqualityComparer _searchComparer;
13 | #region Initialization
14 |
15 | public SectionData(string sectionName)
16 | :this(sectionName, EqualityComparer.Default)
17 | {
18 |
19 | }
20 | ///
21 | /// Initializes a new instance of the class.
22 | ///
23 | public SectionData(string sectionName, IEqualityComparer searchComparer)
24 | {
25 | _searchComparer = searchComparer;
26 |
27 | if (string.IsNullOrEmpty(sectionName))
28 | throw new ArgumentException("section name can not be empty");
29 |
30 | _leadingComments = new List();
31 | _keyDataCollection = new KeyDataCollection(_searchComparer);
32 | SectionName = sectionName;
33 | }
34 |
35 |
36 | ///
37 | /// Initializes a new instance of the class
38 | /// from a previous instance of .
39 | ///
40 | ///
41 | /// Data is deeply copied
42 | ///
43 | ///
44 | /// The instance of the class
45 | /// used to create the new instance.
46 | ///
47 | ///
48 | /// Search comparer.
49 | ///
50 | public SectionData(SectionData ori, IEqualityComparer searchComparer = null)
51 | {
52 | SectionName = ori.SectionName;
53 |
54 | _searchComparer = searchComparer;
55 | _leadingComments = new List(ori._leadingComments);
56 | _keyDataCollection = new KeyDataCollection(ori._keyDataCollection, searchComparer ?? ori._searchComparer);
57 | }
58 |
59 | #endregion
60 |
61 | #region Operations
62 |
63 | ///
64 | /// Deletes all comments in this section and key/value pairs
65 | ///
66 | public void ClearComments()
67 | {
68 | LeadingComments.Clear();
69 | TrailingComments.Clear();
70 | Keys.ClearComments();
71 | }
72 |
73 | ///
74 | /// Deletes all the key-value pairs in this section.
75 | ///
76 | public void ClearKeyData()
77 | {
78 | Keys.RemoveAllKeys();
79 | }
80 |
81 | ///
82 | /// Merges otherSection into this, adding new keys if they don't exists
83 | /// or overwriting values if the key already exists.
84 | /// Comments get appended.
85 | ///
86 | ///
87 | /// Comments are also merged but they are always added, not overwritten.
88 | ///
89 | ///
90 | public void Merge(SectionData toMergeSection)
91 | {
92 | foreach (var comment in toMergeSection.LeadingComments)
93 | LeadingComments.Add(comment);
94 |
95 | Keys.Merge(toMergeSection.Keys);
96 |
97 | foreach(var comment in toMergeSection.TrailingComments)
98 | TrailingComments.Add(comment);
99 | }
100 |
101 | #endregion
102 |
103 | #region Properties
104 |
105 | ///
106 | /// Gets or sets the name of the section.
107 | ///
108 | ///
109 | /// The name of the section
110 | ///
111 | public string SectionName
112 | {
113 | get
114 | {
115 | return _sectionName;
116 | }
117 |
118 | set
119 | {
120 | if (!string.IsNullOrEmpty(value))
121 | _sectionName = value;
122 | }
123 | }
124 |
125 |
126 | [Obsolete("Do not use this property, use property Comments instead")]
127 | public List LeadingComments
128 | {
129 | get
130 | {
131 | return _leadingComments;
132 | }
133 |
134 | internal set
135 | {
136 | _leadingComments = new List(value);
137 | }
138 | }
139 |
140 | ///
141 | /// Gets or sets the comment list associated to this section.
142 | ///
143 | ///
144 | /// A list of strings.
145 | ///
146 | public List Comments
147 | {
148 | get
149 | {
150 | return _leadingComments;
151 | }
152 |
153 |
154 | }
155 |
156 | [Obsolete("Do not use this property, use property Comments instead")]
157 | public List TrailingComments
158 | {
159 | get
160 | {
161 | return _trailingComments;
162 | }
163 |
164 | internal set
165 | {
166 | _trailingComments = new List(value);
167 | }
168 | }
169 | ///
170 | /// Gets or sets the keys associated to this section.
171 | ///
172 | ///
173 | /// A collection of KeyData objects.
174 | ///
175 | public KeyDataCollection Keys
176 | {
177 | get
178 | {
179 | return _keyDataCollection;
180 | }
181 |
182 | set
183 | {
184 | _keyDataCollection = value;
185 | }
186 | }
187 |
188 | #endregion
189 |
190 | #region ICloneable Members
191 |
192 | ///
193 | /// Creates a new object that is a copy of the current instance.
194 | ///
195 | ///
196 | /// A new object that is a copy of this instance.
197 | ///
198 | public object Clone()
199 | {
200 | return new SectionData(this);
201 | }
202 |
203 | #endregion
204 |
205 | #region Non-public members
206 |
207 | // Comments associated to this section
208 | private List _leadingComments;
209 | private List _trailingComments = new List();
210 |
211 | // Keys associated to this section
212 | private KeyDataCollection _keyDataCollection;
213 |
214 | private string _sectionName;
215 | #endregion
216 |
217 |
218 |
219 | }
220 | }
--------------------------------------------------------------------------------
/v2tap/3rd/IniParser/Model/SectionDataCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 |
5 | namespace IniParser.Model
6 | {
7 | ///
8 | /// Represents a collection of SectionData.
9 | ///
10 | public class SectionDataCollection : ICloneable, IEnumerable
11 | {
12 | IEqualityComparer _searchComparer;
13 | #region Initialization
14 |
15 | ///
16 | /// Initializes a new instance of the class.
17 | ///
18 | public SectionDataCollection()
19 | :this(EqualityComparer.Default)
20 | {}
21 |
22 | ///
23 | /// Initializes a new instance of the class.
24 | ///
25 | ///
26 | /// StringComparer used when accessing section names
27 | ///
28 | public SectionDataCollection(IEqualityComparer searchComparer)
29 | {
30 | _searchComparer = searchComparer;
31 |
32 | _sectionData = new Dictionary(_searchComparer);
33 | }
34 |
35 | ///
36 | /// Initializes a new instance of the class
37 | /// from a previous instance of .
38 | ///
39 | ///
40 | /// Data is deeply copied
41 | ///
42 | ///
43 | /// The instance of the class
44 | /// used to create the new instance.
45 | public SectionDataCollection(SectionDataCollection ori, IEqualityComparer searchComparer)
46 | {
47 | _searchComparer = searchComparer ?? EqualityComparer.Default;
48 |
49 | _sectionData = new Dictionary(_searchComparer);
50 | foreach(var sectionData in ori)
51 | {
52 | _sectionData.Add(sectionData.SectionName, (SectionData)sectionData.Clone());
53 | };
54 | }
55 |
56 | #endregion
57 |
58 | #region Properties
59 |
60 | ///
61 | /// Returns the number of SectionData elements in the collection
62 | ///
63 | public int Count { get { return _sectionData.Count; } }
64 |
65 | ///
66 | /// Gets the key data associated to a specified section name.
67 | ///
68 | /// An instance of as class
69 | /// holding the key data from the current parsed INI data, or a null
70 | /// value if the section doesn't exist.
71 | public KeyDataCollection this[string sectionName]
72 | {
73 | get
74 | {
75 | if ( _sectionData.ContainsKey(sectionName) )
76 | return _sectionData[sectionName].Keys;
77 |
78 | return null;
79 | }
80 | }
81 |
82 | #endregion
83 |
84 | #region Public Members
85 |
86 | ///
87 | /// Creates a new section with empty data.
88 | ///
89 | ///
90 | /// If a section with the same name exists, this operation has no effect.
91 | ///
92 | /// Name of the section to be created
93 | /// true if the a new section with the specified name was added,
94 | /// false otherwise
95 | /// If the section name is not valid.
96 | public bool AddSection(string keyName)
97 | {
98 | //Checks valid section name
99 | //if ( !Assert.StringHasNoBlankSpaces(keyName) )
100 | // throw new ArgumentException("Section name contain whitespaces");
101 |
102 | if ( !ContainsSection(keyName) )
103 | {
104 | _sectionData.Add( keyName, new SectionData(keyName, _searchComparer) );
105 | return true;
106 | }
107 |
108 | return false;
109 | }
110 |
111 | ///
112 | /// Adds a new SectionData instance to the collection
113 | ///
114 | /// Data.
115 | public void Add(SectionData data)
116 | {
117 | if (ContainsSection(data.SectionName))
118 | {
119 | SetSectionData(data.SectionName, new SectionData(data, _searchComparer));
120 | }
121 | else
122 | {
123 | _sectionData.Add(data.SectionName, new SectionData(data, _searchComparer));
124 | }
125 | }
126 | ///
127 | /// Removes all entries from this collection
128 | ///
129 | public void Clear()
130 | {
131 | _sectionData.Clear();
132 | }
133 |
134 |
135 | ///
136 | /// Gets if a section with a specified name exists in the collection.
137 | ///
138 | /// Name of the section to search
139 | ///
140 | /// true if a section with the specified name exists in the
141 | /// collection false otherwise
142 | ///
143 | public bool ContainsSection(string keyName)
144 | {
145 | return _sectionData.ContainsKey(keyName);
146 | }
147 |
148 | ///
149 | /// Returns the section data from a specify section given its name.
150 | ///
151 | /// Name of the section.
152 | ///
153 | /// An instance of a class
154 | /// holding the section data for the currently INI data
155 | ///
156 | public SectionData GetSectionData(string sectionName)
157 | {
158 | if (_sectionData.ContainsKey(sectionName))
159 | return _sectionData[sectionName];
160 |
161 | return null;
162 | }
163 |
164 | public void Merge(SectionDataCollection sectionsToMerge)
165 | {
166 | foreach(var sectionDataToMerge in sectionsToMerge)
167 | {
168 | var sectionDataInThis = GetSectionData(sectionDataToMerge.SectionName);
169 |
170 | if (sectionDataInThis == null)
171 | {
172 | AddSection(sectionDataToMerge.SectionName);
173 | }
174 |
175 | this[sectionDataToMerge.SectionName].Merge(sectionDataToMerge.Keys);
176 | }
177 | }
178 |
179 | ///
180 | /// Sets the section data for given a section name.
181 | ///
182 | ///
183 | /// The new instance.
184 | public void SetSectionData(string sectionName, SectionData data)
185 | {
186 | if ( data != null )
187 | _sectionData[sectionName] = data;
188 | }
189 |
190 | ///
191 | ///
192 | ///
193 | ///
194 | /// true if the section with the specified name was removed,
195 | /// false otherwise
196 | public bool RemoveSection(string keyName)
197 | {
198 | return _sectionData.Remove(keyName);
199 | }
200 |
201 |
202 | #endregion
203 |
204 | #region IEnumerable Members
205 |
206 | ///
207 | /// Returns an enumerator that iterates through the collection.
208 | ///
209 | ///
210 | /// A that can be used to iterate through the collection.
211 | ///
212 | public IEnumerator GetEnumerator()
213 | {
214 | foreach (string sectionName in _sectionData.Keys)
215 | yield return _sectionData[sectionName];
216 | }
217 |
218 | #endregion
219 |
220 | #region IEnumerable Members
221 |
222 | ///
223 | /// Returns an enumerator that iterates through a collection.
224 | ///
225 | ///
226 | /// An object that can be used to iterate through the collection.
227 | ///
228 | IEnumerator IEnumerable.GetEnumerator()
229 | {
230 | return GetEnumerator();
231 | }
232 |
233 | #endregion
234 |
235 | #region ICloneable Members
236 |
237 | ///
238 | /// Creates a new object that is a copy of the current instance.
239 | ///
240 | ///
241 | /// A new object that is a copy of this instance.
242 | ///
243 | public object Clone()
244 | {
245 | return new SectionDataCollection(this, _searchComparer);
246 | }
247 |
248 | #endregion
249 |
250 | #region Non-public Members
251 |
252 | ///
253 | /// Data associated to this section
254 | ///
255 | private readonly Dictionary _sectionData;
256 |
257 | #endregion
258 |
259 | }
260 | }
--------------------------------------------------------------------------------
/v2tap/3rd/IniParser/Parser/ConcatenateDuplicatedKeysIniDataParser.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using IniParser.Exceptions;
4 | using IniParser.Model;
5 | using IniParser.Model.Configuration;
6 |
7 | namespace IniParser.Parser
8 | {
9 |
10 | public class ConcatenateDuplicatedKeysIniDataParser : IniDataParser
11 | {
12 | public new ConcatenateDuplicatedKeysIniParserConfiguration Configuration
13 | {
14 | get
15 | {
16 | return (ConcatenateDuplicatedKeysIniParserConfiguration)base.Configuration;
17 | }
18 | set
19 | {
20 | base.Configuration = value;
21 | }
22 | }
23 |
24 | public ConcatenateDuplicatedKeysIniDataParser()
25 | :this(new ConcatenateDuplicatedKeysIniParserConfiguration())
26 | {}
27 |
28 | public ConcatenateDuplicatedKeysIniDataParser(ConcatenateDuplicatedKeysIniParserConfiguration parserConfiguration)
29 | :base(parserConfiguration)
30 | {}
31 |
32 | protected override void HandleDuplicatedKeyInCollection(string key, string value, KeyDataCollection keyDataCollection, string sectionName)
33 | {
34 | keyDataCollection[key] += Configuration.ConcatenateSeparator + value;
35 | }
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/v2tap/3rd/IniParser/StreamIniDataParser.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using IniParser.Model;
4 | using IniParser.Parser;
5 | using IniParser.Model.Formatting;
6 |
7 | namespace IniParser
8 | {
9 |
10 | ///
11 | /// Represents an INI data parser for streams.
12 | ///
13 | public class StreamIniDataParser
14 | {
15 | ///
16 | /// This instance will handle ini data parsing and writing
17 | ///
18 | public IniDataParser Parser { get; protected set; }
19 |
20 | ///
21 | /// Ctor
22 | ///
23 | public StreamIniDataParser() : this (new IniDataParser()) {}
24 |
25 | ///
26 | /// Ctor
27 | ///
28 | ///
29 | public StreamIniDataParser(IniDataParser parser)
30 | {
31 | Parser = parser;
32 | }
33 | #region Public Methods
34 |
35 | ///
36 | /// Reads data in INI format from a stream.
37 | ///
38 | /// Reader stream.
39 | ///
40 | /// And instance with the readed ini data parsed.
41 | ///
42 | ///
43 | /// Thrown if is null.
44 | ///
45 | public IniData ReadData(StreamReader reader)
46 | {
47 | if (reader == null)
48 | throw new ArgumentNullException("reader");
49 |
50 | return Parser.Parse(reader.ReadToEnd());
51 | }
52 |
53 | ///
54 | /// Writes the ini data to a stream.
55 | ///
56 | /// A write stream where the ini data will be stored
57 | /// An instance.
58 | ///
59 | /// Thrown if is null.
60 | ///
61 | public void WriteData(StreamWriter writer, IniData iniData)
62 | {
63 | if (iniData == null)
64 | throw new ArgumentNullException("iniData");
65 | if (writer == null)
66 | throw new ArgumentNullException("writer");
67 |
68 | writer.Write(iniData.ToString());
69 | }
70 |
71 |
72 | ///
73 | /// Writes the ini data to a stream.
74 | ///
75 | /// A write stream where the ini data will be stored
76 | /// An instance.
77 | /// Formaterr instance that controls how the ini data is transformed to a string
78 | ///
79 | /// Thrown if is null.
80 | ///
81 | public void WriteData(StreamWriter writer, IniData iniData, IIniDataFormatter formatter)
82 | {
83 | if (formatter == null)
84 | throw new ArgumentNullException("formatter");
85 | if (iniData == null)
86 | throw new ArgumentNullException("iniData");
87 | if (writer == null)
88 | throw new ArgumentNullException("writer");
89 |
90 | writer.Write(iniData.ToString(formatter));
91 | }
92 |
93 | #endregion
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/v2tap/3rd/IniParser/StringIniParser.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using IniParser.Model;
3 | using IniParser.Parser;
4 |
5 | namespace IniParser
6 | {
7 | ///
8 | /// Represents an INI data parser for strings.
9 | ///
10 | ///
11 | ///
12 | /// This class is deprecated and kept for backwards compatibility.
13 | /// It's just a wrapper around class.
14 | /// Please, replace your code.
15 | ///
16 | [Obsolete("Use class IniDataParser instead. See remarks comments in this class.")]
17 | public class StringIniParser
18 | {
19 | ///
20 | /// This instance will handle ini data parsing and writing
21 | ///
22 | public IniDataParser Parser { get; protected set; }
23 |
24 | ///
25 | /// Ctor
26 | ///
27 | public StringIniParser() : this (new IniDataParser()) {}
28 |
29 | ///
30 | /// Ctor
31 | ///
32 | ///
33 | public StringIniParser(IniDataParser parser)
34 | {
35 | Parser = parser;
36 | }
37 |
38 | ///
39 | /// Parses a string containing data formatted as an INI file.
40 | ///
41 | /// The string containing the data.
42 | ///
43 | /// A new instance with the data parsed from the string.
44 | ///
45 | public IniData ParseString(string dataStr)
46 | {
47 | return Parser.Parse(dataStr);
48 | }
49 |
50 | ///
51 | /// Creates a string from the INI data.
52 | ///
53 | /// An instance.
54 | ///
55 | /// A formatted string with the contents of the
56 | /// instance object.
57 | ///
58 | public string WriteString(IniData iniData)
59 | {
60 | return iniData.ToString();
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/v2tap/3rd/v2ray/Stats/CommandGrpc.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Generated by the protocol buffer compiler. DO NOT EDIT!
3 | // source: test.proto
4 | //
5 | #pragma warning disable 0414, 1591
6 | #region Designer generated code
7 |
8 | using grpc = global::Grpc.Core;
9 |
10 | namespace v2ray.Core.App.Stats.Command {
11 | public static partial class StatsService
12 | {
13 | static readonly string __ServiceName = "v2ray.core.app.stats.command.StatsService";
14 |
15 | static readonly grpc::Marshaller __Marshaller_v2ray_core_app_stats_command_GetStatsRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::v2ray.Core.App.Stats.Command.GetStatsRequest.Parser.ParseFrom);
16 | static readonly grpc::Marshaller __Marshaller_v2ray_core_app_stats_command_GetStatsResponse = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::v2ray.Core.App.Stats.Command.GetStatsResponse.Parser.ParseFrom);
17 | static readonly grpc::Marshaller __Marshaller_v2ray_core_app_stats_command_QueryStatsRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::v2ray.Core.App.Stats.Command.QueryStatsRequest.Parser.ParseFrom);
18 | static readonly grpc::Marshaller __Marshaller_v2ray_core_app_stats_command_QueryStatsResponse = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::v2ray.Core.App.Stats.Command.QueryStatsResponse.Parser.ParseFrom);
19 |
20 | static readonly grpc::Method __Method_GetStats = new grpc::Method(
21 | grpc::MethodType.Unary,
22 | __ServiceName,
23 | "GetStats",
24 | __Marshaller_v2ray_core_app_stats_command_GetStatsRequest,
25 | __Marshaller_v2ray_core_app_stats_command_GetStatsResponse);
26 |
27 | static readonly grpc::Method __Method_QueryStats = new grpc::Method(
28 | grpc::MethodType.Unary,
29 | __ServiceName,
30 | "QueryStats",
31 | __Marshaller_v2ray_core_app_stats_command_QueryStatsRequest,
32 | __Marshaller_v2ray_core_app_stats_command_QueryStatsResponse);
33 |
34 | /// Service descriptor
35 | public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
36 | {
37 | get { return global::v2ray.Core.App.Stats.Command.TestReflection.Descriptor.Services[0]; }
38 | }
39 |
40 | /// Base class for server-side implementations of StatsService
41 | public abstract partial class StatsServiceBase
42 | {
43 | public virtual global::System.Threading.Tasks.Task GetStats(global::v2ray.Core.App.Stats.Command.GetStatsRequest request, grpc::ServerCallContext context)
44 | {
45 | throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
46 | }
47 |
48 | public virtual global::System.Threading.Tasks.Task QueryStats(global::v2ray.Core.App.Stats.Command.QueryStatsRequest request, grpc::ServerCallContext context)
49 | {
50 | throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
51 | }
52 |
53 | }
54 |
55 | /// Client for StatsService
56 | public partial class StatsServiceClient : grpc::ClientBase
57 | {
58 | /// Creates a new client for StatsService
59 | /// The channel to use to make remote calls.
60 | public StatsServiceClient(grpc::Channel channel) : base(channel)
61 | {
62 | }
63 | /// Creates a new client for StatsService that uses a custom CallInvoker.
64 | /// The callInvoker to use to make remote calls.
65 | public StatsServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker)
66 | {
67 | }
68 | /// Protected parameterless constructor to allow creation of test doubles.
69 | protected StatsServiceClient() : base()
70 | {
71 | }
72 | /// Protected constructor to allow creation of configured clients.
73 | /// The client configuration.
74 | protected StatsServiceClient(ClientBaseConfiguration configuration) : base(configuration)
75 | {
76 | }
77 |
78 | public virtual global::v2ray.Core.App.Stats.Command.GetStatsResponse GetStats(global::v2ray.Core.App.Stats.Command.GetStatsRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
79 | {
80 | return GetStats(request, new grpc::CallOptions(headers, deadline, cancellationToken));
81 | }
82 | public virtual global::v2ray.Core.App.Stats.Command.GetStatsResponse GetStats(global::v2ray.Core.App.Stats.Command.GetStatsRequest request, grpc::CallOptions options)
83 | {
84 | return CallInvoker.BlockingUnaryCall(__Method_GetStats, null, options, request);
85 | }
86 | public virtual grpc::AsyncUnaryCall GetStatsAsync(global::v2ray.Core.App.Stats.Command.GetStatsRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
87 | {
88 | return GetStatsAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
89 | }
90 | public virtual grpc::AsyncUnaryCall GetStatsAsync(global::v2ray.Core.App.Stats.Command.GetStatsRequest request, grpc::CallOptions options)
91 | {
92 | return CallInvoker.AsyncUnaryCall(__Method_GetStats, null, options, request);
93 | }
94 | public virtual global::v2ray.Core.App.Stats.Command.QueryStatsResponse QueryStats(global::v2ray.Core.App.Stats.Command.QueryStatsRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
95 | {
96 | return QueryStats(request, new grpc::CallOptions(headers, deadline, cancellationToken));
97 | }
98 | public virtual global::v2ray.Core.App.Stats.Command.QueryStatsResponse QueryStats(global::v2ray.Core.App.Stats.Command.QueryStatsRequest request, grpc::CallOptions options)
99 | {
100 | return CallInvoker.BlockingUnaryCall(__Method_QueryStats, null, options, request);
101 | }
102 | public virtual grpc::AsyncUnaryCall QueryStatsAsync(global::v2ray.Core.App.Stats.Command.QueryStatsRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
103 | {
104 | return QueryStatsAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
105 | }
106 | public virtual grpc::AsyncUnaryCall QueryStatsAsync(global::v2ray.Core.App.Stats.Command.QueryStatsRequest request, grpc::CallOptions options)
107 | {
108 | return CallInvoker.AsyncUnaryCall(__Method_QueryStats, null, options, request);
109 | }
110 | /// Creates a new instance of client from given ClientBaseConfiguration.
111 | protected override StatsServiceClient NewInstance(ClientBaseConfiguration configuration)
112 | {
113 | return new StatsServiceClient(configuration);
114 | }
115 | }
116 |
117 | /// Creates service definition that can be registered with a server
118 | /// An object implementing the server-side handling logic.
119 | public static grpc::ServerServiceDefinition BindService(StatsServiceBase serviceImpl)
120 | {
121 | return grpc::ServerServiceDefinition.CreateBuilder()
122 | .AddMethod(__Method_GetStats, serviceImpl.GetStats)
123 | .AddMethod(__Method_QueryStats, serviceImpl.QueryStats).Build();
124 | }
125 |
126 | /// Register service method implementations with a service binder. Useful when customizing the service binding logic.
127 | /// Note: this method is part of an experimental API that can change or be removed without any prior notice.
128 | /// Service methods will be bound by calling AddMethod on this object.
129 | /// An object implementing the server-side handling logic.
130 | public static void BindService(grpc::ServiceBinderBase serviceBinder, StatsServiceBase serviceImpl)
131 | {
132 | serviceBinder.AddMethod(__Method_GetStats, serviceImpl.GetStats);
133 | serviceBinder.AddMethod(__Method_QueryStats, serviceImpl.QueryStats);
134 | }
135 |
136 | }
137 | }
138 | #endregion
139 |
--------------------------------------------------------------------------------
/v2tap/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/v2tap/Forms/AdvancedForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.IO;
4 | using System.Net;
5 | using System.Net.NetworkInformation;
6 | using System.Net.Sockets;
7 | using System.Text;
8 | using System.Windows.Forms;
9 |
10 | namespace v2tap.Forms
11 | {
12 | public partial class AdvancedForm : Form
13 | {
14 | public AdvancedForm()
15 | {
16 | InitializeComponent();
17 | }
18 |
19 | private void AdvancedForm_Load(object sender, EventArgs e)
20 | {
21 | Init();
22 | }
23 |
24 | private void AdvancedForm_FormClosing(object sender, FormClosingEventArgs e)
25 | {
26 | Global.Form.MainForm.Show();
27 | }
28 |
29 | private void ComboBox_DrawItem(object sender, DrawItemEventArgs e)
30 | {
31 | var cbx = sender as ComboBox;
32 | if (cbx != null)
33 | {
34 | e.DrawBackground();
35 |
36 | if (e.Index >= 0)
37 | {
38 | var sf = new StringFormat();
39 | sf.LineAlignment = StringAlignment.Center;
40 | sf.Alignment = StringAlignment.Center;
41 |
42 | var brush = new SolidBrush(cbx.ForeColor);
43 |
44 | if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
45 | {
46 | brush = SystemBrushes.HighlightText as SolidBrush;
47 | }
48 |
49 | e.Graphics.DrawString(cbx.Items[e.Index].ToString(), cbx.Font, brush, e.Bounds, sf);
50 | }
51 | }
52 | }
53 |
54 | private void SaveButton_Click(object sender, EventArgs e)
55 | {
56 | Global.Configs.TUNTAPAddress = TUNTAPAddressTextBox.Text;
57 | Global.Configs.TUNTAPGateway = TUNTAPGatewayTextBox.Text;
58 | Global.Configs.TUNTAPNetmask = TUNTAPNetmaskTextBox.Text;
59 | Global.Configs.TUNTAPDNS = TUNTAPDNSTextBox.Text;
60 | Global.Configs.TUNTAPMetric = int.Parse(TUNTAPMetricTextBox.Text);
61 | Global.Configs.AutoAdapterMetric = AutoAdapterMetricCheckBox.Checked;
62 | Global.Configs.AutoCheckAdapter = AutoCheckAdapterCheckBox.Checked;
63 |
64 | if (v2rayLoggingLevelComboBox.Text.Contains("DEBUG")) Global.Configs.v2rayLoggingLevel = "DEBUG";
65 | if (v2rayLoggingLevelComboBox.Text.Contains("INFO")) Global.Configs.v2rayLoggingLevel = "INFO";
66 | if (v2rayLoggingLevelComboBox.Text.Contains("WARNING")) Global.Configs.v2rayLoggingLevel = "WARNING";
67 | if (v2rayLoggingLevelComboBox.Text.Contains("ERROR")) Global.Configs.v2rayLoggingLevel = "ERROR";
68 | if (v2rayLoggingLevelComboBox.Text.Contains("NONE")) Global.Configs.v2rayLoggingLevel = "NONE";
69 |
70 | Utils.Util.SaveConfigsToFile();
71 | MessageBox.Show("保存成功", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
72 | }
73 |
74 | private void ResetButton_Click(object sender, EventArgs e)
75 | {
76 | File.WriteAllText("v2tap.ini", Encoding.UTF8.GetString(Properties.Resources.defaultConfig));
77 |
78 | Utils.Util.InitConfigsFromFile();
79 | Init();
80 | MessageBox.Show("重置成功", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
81 | }
82 |
83 | private void Init()
84 | {
85 | TUNTAPAddressTextBox.Text = Global.Configs.TUNTAPAddress;
86 | TUNTAPGatewayTextBox.Text = Global.Configs.TUNTAPGateway;
87 | TUNTAPNetmaskTextBox.Text = Global.Configs.TUNTAPNetmask;
88 | TUNTAPDNSTextBox.Text = Global.Configs.TUNTAPDNS;
89 | TUNTAPMetricTextBox.Text = Global.Configs.TUNTAPMetric.ToString();
90 | AutoAdapterMetricCheckBox.Checked = Global.Configs.AutoAdapterMetric;
91 | AutoCheckAdapterCheckBox.Checked = Global.Configs.AutoCheckAdapter;
92 |
93 | foreach (var item in Global.Configs.AdapterAddress)
94 | {
95 | AdapterAddressComboBox.Items.Add(item);
96 | }
97 |
98 | AdapterAddressComboBox.SelectedIndex = Global.Configs.AdapterAddressIndex;
99 |
100 | foreach (var item in Global.Configs.AdapterGateway)
101 | {
102 | AdapterGatewayComboBox.Items.Add(item);
103 | }
104 |
105 | AdapterGatewayComboBox.SelectedIndex = Global.Configs.AdapterGatewayIndex;
106 |
107 | switch (Global.Configs.v2rayLoggingLevel)
108 | {
109 | case "DEBUG":
110 | v2rayLoggingLevelComboBox.SelectedIndex = 0;
111 | break;
112 | case "INFO":
113 | v2rayLoggingLevelComboBox.SelectedIndex = 1;
114 | break;
115 | case "WARNING":
116 | v2rayLoggingLevelComboBox.SelectedIndex = 2;
117 | break;
118 | case "ERROR":
119 | v2rayLoggingLevelComboBox.SelectedIndex = 3;
120 | break;
121 | case "NONE":
122 | v2rayLoggingLevelComboBox.SelectedIndex = 4;
123 | break;
124 | default:
125 | v2rayLoggingLevelComboBox.SelectedIndex = 0;
126 | break;
127 | }
128 | }
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/v2tap/Forms/AdvancedForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/v2tap/Forms/EditForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.Windows.Forms;
4 |
5 | namespace v2tap.Forms
6 | {
7 | public partial class EditForm : Form
8 | {
9 | ///
10 | /// 窗体模式
11 | ///
12 | public string Mode;
13 |
14 | ///
15 | /// 当工作于编辑模式下时指定配置索引号
16 | ///
17 | public int Index;
18 |
19 | ///
20 | /// 默认配置
21 | ///
22 | public Objects.Server Server;
23 |
24 | public EditForm()
25 | {
26 | InitializeComponent();
27 | }
28 |
29 | private void EditForm_Load(object sender, EventArgs e)
30 | {
31 | if (Mode == "Add")
32 | {
33 | Text = "添加 - v2tap";
34 | TransferMethodComboBox.SelectedIndex = 0;
35 | FakeComboBox.SelectedIndex = 0;
36 | }
37 | else if (Mode == "Edit")
38 | {
39 | Text = "编辑 - v2tap";
40 | RemarkTextBox.Text = Global.Proxies[Index].Remark;
41 | ServerAddressTextBox.Text = Global.Proxies[Index].Address;
42 | ServerPortTextBox.Text = Global.Proxies[Index].Port.ToString();
43 | UserIDTextBox.Text = Global.Proxies[Index].UserID;
44 | AlterIDTextBox.Text = Global.Proxies[Index].AlterID.ToString();
45 | PathTextBox.Text = Global.Proxies[Index].Path;
46 |
47 | switch (Global.Proxies[Index].TransferMethod)
48 | {
49 | case "TCP":
50 | TransferMethodComboBox.SelectedIndex = 0;
51 | break;
52 | case "mKCP":
53 | TransferMethodComboBox.SelectedIndex = 1;
54 | break;
55 | case "WebSockets":
56 | TransferMethodComboBox.SelectedIndex = 2;
57 | break;
58 | case "HTTP/2":
59 | TransferMethodComboBox.SelectedIndex = 3;
60 | break;
61 | case "QUIC":
62 | TransferMethodComboBox.SelectedIndex = 4;
63 | break;
64 | default:
65 | TransferMethodComboBox.SelectedIndex = 0;
66 | break;
67 | }
68 |
69 | switch (Global.Proxies[Index].FakeType)
70 | {
71 | case "None":
72 | FakeComboBox.SelectedIndex = 0;
73 | break;
74 | case "HTTP":
75 | FakeComboBox.SelectedIndex = 1;
76 | break;
77 | case "SRTP":
78 | FakeComboBox.SelectedIndex = 2;
79 | break;
80 | case "UTP":
81 | FakeComboBox.SelectedIndex = 3;
82 | break;
83 | case "DTLS":
84 | FakeComboBox.SelectedIndex = 4;
85 | break;
86 | case "WireGuard":
87 | FakeComboBox.SelectedIndex = 5;
88 | break;
89 | case "WeChat":
90 | FakeComboBox.SelectedIndex = 6;
91 | break;
92 | default:
93 | FakeComboBox.SelectedIndex = 0;
94 | break;
95 | }
96 |
97 | TLSSecureCheckBox.Checked = Global.Proxies[Index].TLSSecure;
98 | }
99 | }
100 |
101 | private void EditForm_FormClosing(object sender, FormClosingEventArgs e)
102 | {
103 | Global.Form.MainForm.Show();
104 | }
105 |
106 | private void InputTextBox_KeyPress(object sender, KeyPressEventArgs e)
107 | {
108 | if ((e.KeyChar >= '0' && e.KeyChar <= '9') || e.KeyChar == 8)
109 | {
110 | e.Handled = false;
111 | }
112 | else
113 | {
114 | e.Handled = true;
115 | }
116 | }
117 |
118 | private void ComboBox_DrawItem(object sender, DrawItemEventArgs e)
119 | {
120 | var cbx = sender as ComboBox;
121 | if (cbx != null)
122 | {
123 | e.DrawBackground();
124 |
125 | if (e.Index >= 0)
126 | {
127 | var sf = new StringFormat();
128 | sf.LineAlignment = StringAlignment.Center;
129 | sf.Alignment = StringAlignment.Center;
130 |
131 | var brush = new SolidBrush(cbx.ForeColor);
132 |
133 | if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
134 | {
135 | brush = SystemBrushes.HighlightText as SolidBrush;
136 | }
137 |
138 | e.Graphics.DrawString(cbx.Items[e.Index].ToString(), cbx.Font, brush, e.Bounds, sf);
139 | }
140 | }
141 | }
142 |
143 | private void ControlButton_Click(object sender, EventArgs e)
144 | {
145 | if (Mode == "Add")
146 | {
147 | try
148 | {
149 | var server = new Objects.Server()
150 | {
151 | ID = Guid.NewGuid().ToString(),
152 | Remark = RemarkTextBox.Text,
153 | Address = ServerAddressTextBox.Text,
154 | Port = int.Parse(ServerPortTextBox.Text),
155 | UserID = UserIDTextBox.Text,
156 | AlterID = int.Parse(AlterIDTextBox.Text),
157 | TransferMethod = TransferMethodComboBox.Text,
158 | Path = PathTextBox.Text,
159 | TLSSecure = TLSSecureCheckBox.Checked
160 | };
161 | Global.Proxies.Add(server);
162 | }
163 | catch (Exception ex)
164 | {
165 | MessageBox.Show("发生错误:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
166 | return;
167 | }
168 |
169 | Global.Form.MainForm.InitProxies();
170 | Utils.Util.SaveServersToFile();
171 |
172 | MessageBox.Show("保存成功", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
173 | }
174 | else if (Mode == "Edit")
175 | {
176 | Global.Proxies[Index].Remark = RemarkTextBox.Text;
177 | Global.Proxies[Index].Address = ServerAddressTextBox.Text;
178 | Global.Proxies[Index].Port = int.Parse(ServerPortTextBox.Text);
179 | Global.Proxies[Index].UserID = UserIDTextBox.Text;
180 | Global.Proxies[Index].AlterID = int.Parse(AlterIDTextBox.Text);
181 | Global.Proxies[Index].TransferMethod = TransferMethodComboBox.Text;
182 | Global.Proxies[Index].Path = PathTextBox.Text;
183 | Global.Proxies[Index].FakeType = FakeComboBox.Text;
184 | Global.Proxies[Index].TLSSecure = TLSSecureCheckBox.Checked;
185 |
186 | Global.Form.MainForm.InitProxies();
187 | Utils.Util.SaveServersToFile();
188 |
189 | MessageBox.Show("保存成功", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
190 | }
191 | }
192 | }
193 | }
194 |
--------------------------------------------------------------------------------
/v2tap/Forms/EditForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/v2tap/Forms/ImportForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace v2tap.Forms
2 | {
3 | partial class ImportForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.ImportFromSubscriptionURLGroupBox = new System.Windows.Forms.GroupBox();
32 | this.SubscriptionImportButton = new System.Windows.Forms.Button();
33 | this.SubscriptionURLTextBox = new System.Windows.Forms.TextBox();
34 | this.SubscriptionURLLabel = new System.Windows.Forms.Label();
35 | this.ImportFromTextBoxGroupBox = new System.Windows.Forms.GroupBox();
36 | this.MyButton = new System.Windows.Forms.Button();
37 | this.MyTextBox = new System.Windows.Forms.TextBox();
38 | this.ImportFromSubscriptionURLGroupBox.SuspendLayout();
39 | this.ImportFromTextBoxGroupBox.SuspendLayout();
40 | this.SuspendLayout();
41 | //
42 | // ImportFromSubscriptionURLGroupBox
43 | //
44 | this.ImportFromSubscriptionURLGroupBox.Controls.Add(this.SubscriptionImportButton);
45 | this.ImportFromSubscriptionURLGroupBox.Controls.Add(this.SubscriptionURLTextBox);
46 | this.ImportFromSubscriptionURLGroupBox.Controls.Add(this.SubscriptionURLLabel);
47 | this.ImportFromSubscriptionURLGroupBox.Location = new System.Drawing.Point(14, 17);
48 | this.ImportFromSubscriptionURLGroupBox.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
49 | this.ImportFromSubscriptionURLGroupBox.Name = "ImportFromSubscriptionURLGroupBox";
50 | this.ImportFromSubscriptionURLGroupBox.Padding = new System.Windows.Forms.Padding(3, 4, 3, 4);
51 | this.ImportFromSubscriptionURLGroupBox.Size = new System.Drawing.Size(559, 78);
52 | this.ImportFromSubscriptionURLGroupBox.TabIndex = 0;
53 | this.ImportFromSubscriptionURLGroupBox.TabStop = false;
54 | this.ImportFromSubscriptionURLGroupBox.Text = "从订阅链接导入";
55 | //
56 | // SubscriptionImportButton
57 | //
58 | this.SubscriptionImportButton.Location = new System.Drawing.Point(478, 49);
59 | this.SubscriptionImportButton.Name = "SubscriptionImportButton";
60 | this.SubscriptionImportButton.Size = new System.Drawing.Size(75, 23);
61 | this.SubscriptionImportButton.TabIndex = 2;
62 | this.SubscriptionImportButton.Text = "导入";
63 | this.SubscriptionImportButton.UseVisualStyleBackColor = true;
64 | this.SubscriptionImportButton.Click += new System.EventHandler(this.SubscriptionImportButton_Click);
65 | //
66 | // SubscriptionURLTextBox
67 | //
68 | this.SubscriptionURLTextBox.Font = new System.Drawing.Font("Consolas", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
69 | this.SubscriptionURLTextBox.Location = new System.Drawing.Point(44, 20);
70 | this.SubscriptionURLTextBox.Name = "SubscriptionURLTextBox";
71 | this.SubscriptionURLTextBox.Size = new System.Drawing.Size(509, 22);
72 | this.SubscriptionURLTextBox.TabIndex = 1;
73 | //
74 | // SubscriptionURLLabel
75 | //
76 | this.SubscriptionURLLabel.AutoSize = true;
77 | this.SubscriptionURLLabel.Location = new System.Drawing.Point(8, 23);
78 | this.SubscriptionURLLabel.Name = "SubscriptionURLLabel";
79 | this.SubscriptionURLLabel.Size = new System.Drawing.Size(44, 17);
80 | this.SubscriptionURLLabel.TabIndex = 0;
81 | this.SubscriptionURLLabel.Text = "链接:";
82 | //
83 | // ImportFromTextBoxGroupBox
84 | //
85 | this.ImportFromTextBoxGroupBox.Controls.Add(this.MyButton);
86 | this.ImportFromTextBoxGroupBox.Controls.Add(this.MyTextBox);
87 | this.ImportFromTextBoxGroupBox.Location = new System.Drawing.Point(12, 102);
88 | this.ImportFromTextBoxGroupBox.Name = "ImportFromTextBoxGroupBox";
89 | this.ImportFromTextBoxGroupBox.Size = new System.Drawing.Size(561, 260);
90 | this.ImportFromTextBoxGroupBox.TabIndex = 1;
91 | this.ImportFromTextBoxGroupBox.TabStop = false;
92 | this.ImportFromTextBoxGroupBox.Text = "从文本框中导入";
93 | //
94 | // MyButton
95 | //
96 | this.MyButton.Location = new System.Drawing.Point(480, 231);
97 | this.MyButton.Name = "MyButton";
98 | this.MyButton.Size = new System.Drawing.Size(75, 23);
99 | this.MyButton.TabIndex = 1;
100 | this.MyButton.Text = "导入";
101 | this.MyButton.UseVisualStyleBackColor = true;
102 | this.MyButton.Click += new System.EventHandler(this.MyButton_Click);
103 | //
104 | // MyTextBox
105 | //
106 | this.MyTextBox.Font = new System.Drawing.Font("Consolas", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
107 | this.MyTextBox.Location = new System.Drawing.Point(13, 22);
108 | this.MyTextBox.Multiline = true;
109 | this.MyTextBox.Name = "MyTextBox";
110 | this.MyTextBox.Size = new System.Drawing.Size(542, 203);
111 | this.MyTextBox.TabIndex = 0;
112 | //
113 | // ImportForm
114 | //
115 | this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
116 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
117 | this.ClientSize = new System.Drawing.Size(585, 375);
118 | this.Controls.Add(this.ImportFromTextBoxGroupBox);
119 | this.Controls.Add(this.ImportFromSubscriptionURLGroupBox);
120 | this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
121 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
122 | this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
123 | this.MaximizeBox = false;
124 | this.Name = "ImportForm";
125 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
126 | this.Text = "导入 - v2tap";
127 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ImportForm_FormClosing);
128 | this.Load += new System.EventHandler(this.ImportForm_Load);
129 | this.ImportFromSubscriptionURLGroupBox.ResumeLayout(false);
130 | this.ImportFromSubscriptionURLGroupBox.PerformLayout();
131 | this.ImportFromTextBoxGroupBox.ResumeLayout(false);
132 | this.ImportFromTextBoxGroupBox.PerformLayout();
133 | this.ResumeLayout(false);
134 |
135 | }
136 |
137 | #endregion
138 |
139 | private System.Windows.Forms.GroupBox ImportFromSubscriptionURLGroupBox;
140 | private System.Windows.Forms.Button SubscriptionImportButton;
141 | private System.Windows.Forms.TextBox SubscriptionURLTextBox;
142 | private System.Windows.Forms.Label SubscriptionURLLabel;
143 | private System.Windows.Forms.GroupBox ImportFromTextBoxGroupBox;
144 | private System.Windows.Forms.TextBox MyTextBox;
145 | private System.Windows.Forms.Button MyButton;
146 | }
147 | }
--------------------------------------------------------------------------------
/v2tap/Forms/ImportForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Text;
4 | using System.Windows.Forms;
5 |
6 | namespace v2tap.Forms
7 | {
8 | public partial class ImportForm : Form
9 | {
10 | public ImportForm()
11 | {
12 | InitializeComponent();
13 | }
14 |
15 | private void ImportForm_Load(object sender, EventArgs e)
16 | {
17 | // 读取订阅链接
18 | if (File.Exists("lastSubscriptionURL.txt")) SubscriptionURLTextBox.Text = File.ReadAllText("lastSubscriptionURL.txt");
19 | }
20 |
21 | private void ImportForm_FormClosing(object sender, FormClosingEventArgs e)
22 | {
23 | Global.Form.MainForm.Show();
24 | }
25 |
26 | private void SubscriptionImportButton_Click(object sender, EventArgs e)
27 | {
28 | try
29 | {
30 | var client = Override.WebClient.GetClient();
31 | var data = client.DownloadString(SubscriptionURLTextBox.Text);
32 |
33 | if (data != "")
34 | {
35 | var next = false;
36 | for (int i = 0; i < 4; i++)
37 | {
38 | try
39 | {
40 | data = Encoding.UTF8.GetString(Convert.FromBase64String(data));
41 | }
42 | catch (FormatException)
43 | {
44 | data += "=";
45 | continue;
46 | }
47 |
48 | next = true;
49 | break;
50 | }
51 |
52 | if (next)
53 | {
54 | Global.Proxies.Clear();
55 | using (StringReader sr = new StringReader(data))
56 | {
57 | string text;
58 |
59 | while ((text = sr.ReadLine()) != null)
60 | {
61 | var server = ParseServer(text);
62 |
63 | Global.Proxies.Add(server);
64 | }
65 | }
66 |
67 | Global.Form.MainForm.InitProxies();
68 | File.WriteAllText("lastSubscriptionURL.txt", SubscriptionURLTextBox.Text); // 保存订阅链接
69 | MessageBox.Show("订阅已成功导入", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
70 | }
71 | else
72 | {
73 | MessageBox.Show("Base64 解码失败", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
74 | }
75 | }
76 | else
77 | {
78 | MessageBox.Show("返回数据为空", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
79 | }
80 | }
81 | catch (Exception ex)
82 | {
83 | MessageBox.Show("发生错误:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
84 | }
85 | }
86 |
87 | private void MyButton_Click(object sender, EventArgs e)
88 | {
89 | if (MyTextBox.Text == "")
90 | {
91 | MessageBox.Show("文本框为空", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
92 | return;
93 | }
94 |
95 | try
96 | {
97 | Global.Proxies.Clear();
98 | using (StringReader sr = new StringReader(MyTextBox.Text))
99 | {
100 | string text;
101 |
102 | while ((text = sr.ReadLine()) != null)
103 | {
104 | var server = ParseServer(text);
105 |
106 | Global.Proxies.Add(server);
107 | }
108 | }
109 |
110 | Global.Form.MainForm.InitProxies();
111 | MessageBox.Show("订阅已成功导入", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
112 | }
113 | catch (Exception ex)
114 | {
115 | MessageBox.Show("发生错误:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
116 | }
117 | }
118 |
119 | public Objects.Server ParseServer(string text)
120 | {
121 | var json = SimpleJSON.JSON.Parse(Encoding.UTF8.GetString(Convert.FromBase64String(text.Replace("vmess://", ""))));
122 | var server = new Objects.Server()
123 | {
124 | ID = Guid.NewGuid().ToString(),
125 | Remark = json["ps"].Value,
126 | Address = json["add"].Value,
127 | Port = json["port"].AsInt,
128 | UserID = json["id"].Value,
129 | AlterID = json["aid"].AsInt,
130 | Path = (json["path"].Value == "") ? "/" : json["path"].Value,
131 | TLSSecure = (json["tls"].Value == "") ? false : true
132 | };
133 |
134 | switch (json["net"].Value)
135 | {
136 | case "tcp":
137 | server.TransferMethod = "TCP";
138 | break;
139 | case "kcp":
140 | server.TransferMethod = "mKCP";
141 | break;
142 | case "ws":
143 | server.TransferMethod = "WebSockets";
144 | break;
145 | case "h2":
146 | server.TransferMethod = "HTTP/2";
147 | break;
148 | case "quic":
149 | server.TransferMethod = "QUIC";
150 | break;
151 | default:
152 | server.TransferMethod = "TCP";
153 | break;
154 | }
155 |
156 | switch (json["type"].Value)
157 | {
158 | case "none":
159 | server.FakeType = "None";
160 | break;
161 | case "http":
162 | server.FakeType = "HTTP";
163 | break;
164 | case "srtp":
165 | server.FakeType = "SRTP";
166 | break;
167 | case "utp":
168 | server.FakeType = "UTP";
169 | break;
170 | case "dtls":
171 | server.FakeType = "DTLS";
172 | break;
173 | case "wireguard":
174 | server.FakeType = "WireGuard";
175 | break;
176 | case "wechat-video":
177 | server.FakeType = "WeChat";
178 | break;
179 | default:
180 | server.FakeType = "None";
181 | break;
182 | }
183 |
184 | return server;
185 | }
186 | }
187 | }
188 |
--------------------------------------------------------------------------------
/v2tap/Forms/ImportForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/v2tap/Forms/MainForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace v2tap.Forms
2 | {
3 | partial class MainForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.v2rayGroupBox = new System.Windows.Forms.GroupBox();
32 | this.v2rayEditButton = new System.Windows.Forms.Button();
33 | this.v2rayImportButton = new System.Windows.Forms.Button();
34 | this.v2rayDeleteButton = new System.Windows.Forms.Button();
35 | this.v2rayAddButton = new System.Windows.Forms.Button();
36 | this.v2rayModeComboBox = new System.Windows.Forms.ComboBox();
37 | this.v2rayModeLabel = new System.Windows.Forms.Label();
38 | this.v2rayProxyComboBox = new System.Windows.Forms.ComboBox();
39 | this.v2rayProxyLabel = new System.Windows.Forms.Label();
40 | this.AdvancedButton = new System.Windows.Forms.Button();
41 | this.ControlButton = new System.Windows.Forms.Button();
42 | this.StatusLabel = new System.Windows.Forms.Label();
43 | this.StatusStrip = new System.Windows.Forms.StatusStrip();
44 | this.UplinkLabel = new System.Windows.Forms.ToolStripStatusLabel();
45 | this.DownlinkLabel = new System.Windows.Forms.ToolStripStatusLabel();
46 | this.BandwidthLabel = new System.Windows.Forms.ToolStripStatusLabel();
47 | this.v2rayGroupBox.SuspendLayout();
48 | this.StatusStrip.SuspendLayout();
49 | this.SuspendLayout();
50 | //
51 | // v2rayGroupBox
52 | //
53 | this.v2rayGroupBox.Controls.Add(this.v2rayEditButton);
54 | this.v2rayGroupBox.Controls.Add(this.v2rayImportButton);
55 | this.v2rayGroupBox.Controls.Add(this.v2rayDeleteButton);
56 | this.v2rayGroupBox.Controls.Add(this.v2rayAddButton);
57 | this.v2rayGroupBox.Controls.Add(this.v2rayModeComboBox);
58 | this.v2rayGroupBox.Controls.Add(this.v2rayModeLabel);
59 | this.v2rayGroupBox.Controls.Add(this.v2rayProxyComboBox);
60 | this.v2rayGroupBox.Controls.Add(this.v2rayProxyLabel);
61 | this.v2rayGroupBox.Location = new System.Drawing.Point(14, 17);
62 | this.v2rayGroupBox.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
63 | this.v2rayGroupBox.Name = "v2rayGroupBox";
64 | this.v2rayGroupBox.Padding = new System.Windows.Forms.Padding(3, 4, 3, 4);
65 | this.v2rayGroupBox.Size = new System.Drawing.Size(430, 111);
66 | this.v2rayGroupBox.TabIndex = 0;
67 | this.v2rayGroupBox.TabStop = false;
68 | this.v2rayGroupBox.Text = "v2ray 配置";
69 | //
70 | // v2rayEditButton
71 | //
72 | this.v2rayEditButton.Location = new System.Drawing.Point(268, 82);
73 | this.v2rayEditButton.Name = "v2rayEditButton";
74 | this.v2rayEditButton.Size = new System.Drawing.Size(75, 23);
75 | this.v2rayEditButton.TabIndex = 7;
76 | this.v2rayEditButton.Text = "编辑";
77 | this.v2rayEditButton.UseVisualStyleBackColor = true;
78 | this.v2rayEditButton.Click += new System.EventHandler(this.v2rayEditButton_Click);
79 | //
80 | // v2rayImportButton
81 | //
82 | this.v2rayImportButton.Location = new System.Drawing.Point(349, 82);
83 | this.v2rayImportButton.Name = "v2rayImportButton";
84 | this.v2rayImportButton.Size = new System.Drawing.Size(75, 23);
85 | this.v2rayImportButton.TabIndex = 6;
86 | this.v2rayImportButton.Text = "导入";
87 | this.v2rayImportButton.UseVisualStyleBackColor = true;
88 | this.v2rayImportButton.Click += new System.EventHandler(this.v2rayImportButton_Click);
89 | //
90 | // v2rayDeleteButton
91 | //
92 | this.v2rayDeleteButton.Location = new System.Drawing.Point(187, 82);
93 | this.v2rayDeleteButton.Name = "v2rayDeleteButton";
94 | this.v2rayDeleteButton.Size = new System.Drawing.Size(75, 23);
95 | this.v2rayDeleteButton.TabIndex = 5;
96 | this.v2rayDeleteButton.Text = "删除";
97 | this.v2rayDeleteButton.UseVisualStyleBackColor = true;
98 | this.v2rayDeleteButton.Click += new System.EventHandler(this.v2rayDeleteButton_Click);
99 | //
100 | // v2rayAddButton
101 | //
102 | this.v2rayAddButton.Location = new System.Drawing.Point(106, 82);
103 | this.v2rayAddButton.Name = "v2rayAddButton";
104 | this.v2rayAddButton.Size = new System.Drawing.Size(75, 23);
105 | this.v2rayAddButton.TabIndex = 4;
106 | this.v2rayAddButton.Text = "添加";
107 | this.v2rayAddButton.UseVisualStyleBackColor = true;
108 | this.v2rayAddButton.Click += new System.EventHandler(this.v2rayAddButton_Click);
109 | //
110 | // v2rayModeComboBox
111 | //
112 | this.v2rayModeComboBox.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
113 | this.v2rayModeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
114 | this.v2rayModeComboBox.FormattingEnabled = true;
115 | this.v2rayModeComboBox.Items.AddRange(new object[] {
116 | "[内部规则] 绕过局域网",
117 | "[内部规则] 绕过局域网和中国"});
118 | this.v2rayModeComboBox.Location = new System.Drawing.Point(44, 51);
119 | this.v2rayModeComboBox.Name = "v2rayModeComboBox";
120 | this.v2rayModeComboBox.Size = new System.Drawing.Size(380, 24);
121 | this.v2rayModeComboBox.TabIndex = 3;
122 | this.v2rayModeComboBox.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.ComboBox_DrawItem);
123 | //
124 | // v2rayModeLabel
125 | //
126 | this.v2rayModeLabel.AutoSize = true;
127 | this.v2rayModeLabel.Location = new System.Drawing.Point(4, 55);
128 | this.v2rayModeLabel.Name = "v2rayModeLabel";
129 | this.v2rayModeLabel.Size = new System.Drawing.Size(44, 17);
130 | this.v2rayModeLabel.TabIndex = 2;
131 | this.v2rayModeLabel.Text = "模式:";
132 | //
133 | // v2rayProxyComboBox
134 | //
135 | this.v2rayProxyComboBox.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
136 | this.v2rayProxyComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
137 | this.v2rayProxyComboBox.FormattingEnabled = true;
138 | this.v2rayProxyComboBox.Location = new System.Drawing.Point(44, 20);
139 | this.v2rayProxyComboBox.Name = "v2rayProxyComboBox";
140 | this.v2rayProxyComboBox.Size = new System.Drawing.Size(380, 24);
141 | this.v2rayProxyComboBox.TabIndex = 1;
142 | this.v2rayProxyComboBox.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.ComboBox_DrawItem);
143 | //
144 | // v2rayProxyLabel
145 | //
146 | this.v2rayProxyLabel.AutoSize = true;
147 | this.v2rayProxyLabel.Location = new System.Drawing.Point(4, 24);
148 | this.v2rayProxyLabel.Name = "v2rayProxyLabel";
149 | this.v2rayProxyLabel.Size = new System.Drawing.Size(44, 17);
150 | this.v2rayProxyLabel.TabIndex = 0;
151 | this.v2rayProxyLabel.Text = "代理:";
152 | //
153 | // AdvancedButton
154 | //
155 | this.AdvancedButton.Location = new System.Drawing.Point(14, 135);
156 | this.AdvancedButton.Name = "AdvancedButton";
157 | this.AdvancedButton.Size = new System.Drawing.Size(75, 23);
158 | this.AdvancedButton.TabIndex = 1;
159 | this.AdvancedButton.Text = "高级设置";
160 | this.AdvancedButton.UseVisualStyleBackColor = true;
161 | this.AdvancedButton.Click += new System.EventHandler(this.AdvancedButton_Click);
162 | //
163 | // ControlButton
164 | //
165 | this.ControlButton.Location = new System.Drawing.Point(369, 135);
166 | this.ControlButton.Name = "ControlButton";
167 | this.ControlButton.Size = new System.Drawing.Size(75, 23);
168 | this.ControlButton.TabIndex = 2;
169 | this.ControlButton.Text = "启动";
170 | this.ControlButton.UseVisualStyleBackColor = true;
171 | this.ControlButton.Click += new System.EventHandler(this.ControlButton_Click);
172 | //
173 | // StatusLabel
174 | //
175 | this.StatusLabel.AutoSize = true;
176 | this.StatusLabel.Location = new System.Drawing.Point(95, 138);
177 | this.StatusLabel.Name = "StatusLabel";
178 | this.StatusLabel.Size = new System.Drawing.Size(128, 17);
179 | this.StatusLabel.TabIndex = 3;
180 | this.StatusLabel.Text = "当前状态:等待指令中";
181 | //
182 | // StatusStrip
183 | //
184 | this.StatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
185 | this.UplinkLabel,
186 | this.DownlinkLabel,
187 | this.BandwidthLabel});
188 | this.StatusStrip.Location = new System.Drawing.Point(0, 163);
189 | this.StatusStrip.Name = "StatusStrip";
190 | this.StatusStrip.Size = new System.Drawing.Size(456, 22);
191 | this.StatusStrip.SizingGrip = false;
192 | this.StatusStrip.TabIndex = 4;
193 | //
194 | // UplinkLabel
195 | //
196 | this.UplinkLabel.Name = "UplinkLabel";
197 | this.UplinkLabel.Size = new System.Drawing.Size(60, 17);
198 | this.UplinkLabel.Text = "↑:0KB/s";
199 | //
200 | // DownlinkLabel
201 | //
202 | this.DownlinkLabel.Name = "DownlinkLabel";
203 | this.DownlinkLabel.Size = new System.Drawing.Size(60, 17);
204 | this.DownlinkLabel.Text = "↓:0KB/s";
205 | //
206 | // BandwidthLabel
207 | //
208 | this.BandwidthLabel.Name = "BandwidthLabel";
209 | this.BandwidthLabel.Size = new System.Drawing.Size(83, 17);
210 | this.BandwidthLabel.Text = "总流量:0 KB";
211 | //
212 | // MainForm
213 | //
214 | this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
215 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
216 | this.ClientSize = new System.Drawing.Size(456, 185);
217 | this.Controls.Add(this.StatusStrip);
218 | this.Controls.Add(this.StatusLabel);
219 | this.Controls.Add(this.ControlButton);
220 | this.Controls.Add(this.AdvancedButton);
221 | this.Controls.Add(this.v2rayGroupBox);
222 | this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
223 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
224 | this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
225 | this.MaximizeBox = false;
226 | this.Name = "MainForm";
227 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
228 | this.Text = "v2tap";
229 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing);
230 | this.Load += new System.EventHandler(this.MainForm_Load);
231 | this.v2rayGroupBox.ResumeLayout(false);
232 | this.v2rayGroupBox.PerformLayout();
233 | this.StatusStrip.ResumeLayout(false);
234 | this.StatusStrip.PerformLayout();
235 | this.ResumeLayout(false);
236 | this.PerformLayout();
237 |
238 | }
239 |
240 | #endregion
241 | public System.Windows.Forms.GroupBox v2rayGroupBox;
242 | public System.Windows.Forms.Label v2rayProxyLabel;
243 | public System.Windows.Forms.ComboBox v2rayProxyComboBox;
244 | public System.Windows.Forms.Button v2rayAddButton;
245 | public System.Windows.Forms.ComboBox v2rayModeComboBox;
246 | public System.Windows.Forms.Label v2rayModeLabel;
247 | public System.Windows.Forms.Button v2rayDeleteButton;
248 | public System.Windows.Forms.Button v2rayImportButton;
249 | private System.Windows.Forms.Button AdvancedButton;
250 | public System.Windows.Forms.Button v2rayEditButton;
251 | public System.Windows.Forms.Button ControlButton;
252 | private System.Windows.Forms.Label StatusLabel;
253 | private System.Windows.Forms.StatusStrip StatusStrip;
254 | private System.Windows.Forms.ToolStripStatusLabel UplinkLabel;
255 | private System.Windows.Forms.ToolStripStatusLabel DownlinkLabel;
256 | private System.Windows.Forms.ToolStripStatusLabel BandwidthLabel;
257 | }
258 | }
--------------------------------------------------------------------------------
/v2tap/Forms/MainForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 17, 17
122 |
123 |
--------------------------------------------------------------------------------
/v2tap/Global.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace v2tap
8 | {
9 | ///
10 | /// 全局变量
11 | ///
12 | public static class Global
13 | {
14 | ///
15 | /// 路径
16 | ///
17 | public static class Path
18 | {
19 | ///
20 | /// 日志目录
21 | ///
22 | public static string LoggingDirectory = "logging";
23 |
24 | ///
25 | /// v2tap 日志
26 | ///
27 | public static string v2tapLogging = "v2tap.txt";
28 |
29 | ///
30 | /// v2ray 日志
31 | ///
32 | public static string v2rayLogging = "v2ray.txt";
33 |
34 | ///
35 | /// tun2socks 日志
36 | ///
37 | public static string tun2socksLogging = "tun2socks.txt";
38 |
39 | ///
40 | /// 模式目录
41 | ///
42 | public static string ModeDirectory = "mode";
43 | }
44 |
45 | ///
46 | /// 日志等级
47 | ///
48 | public enum Level
49 | {
50 | ///
51 | /// 调试
52 | ///
53 | DEBUG,
54 |
55 | ///
56 | /// 信息
57 | ///
58 | INFO,
59 |
60 | ///
61 | /// 警告
62 | ///
63 | WARNING,
64 |
65 | ///
66 | /// 错误
67 | ///
68 | ERROR
69 | }
70 |
71 | ///
72 | /// 窗体
73 | ///
74 | public static class Form
75 | {
76 | ///
77 | /// 主窗体
78 | ///
79 | public static Forms.MainForm MainForm;
80 |
81 | ///
82 | /// 编辑
83 | ///
84 | public static Forms.EditForm EditForm;
85 |
86 | ///
87 | /// 导入
88 | ///
89 | public static Forms.ImportForm ImportForm;
90 |
91 | ///
92 | /// 高级设置
93 | ///
94 | public static Forms.AdvancedForm AdvancedForm;
95 | }
96 |
97 | ///
98 | /// 配置信息
99 | ///
100 | public static class Configs
101 | {
102 | ///
103 | /// TUN/TAP 地址
104 | ///
105 | public static string TUNTAPAddress;
106 |
107 | ///
108 | /// TUN/TAP 网关
109 | ///
110 | public static string TUNTAPGateway;
111 |
112 | ///
113 | /// TUN/TAP 掩码
114 | ///
115 | public static string TUNTAPNetmask;
116 |
117 | ///
118 | /// TUN/TAP DNS
119 | ///
120 | public static string TUNTAPDNS;
121 |
122 | ///
123 | /// TUN/TAP 跃点数
124 | ///
125 | public static int TUNTAPMetric;
126 |
127 | ///
128 | /// 自动降低适配器跃点数
129 | ///
130 | public static bool AutoAdapterMetric;
131 |
132 | ///
133 | /// 适配器地址
134 | ///
135 | public static List AdapterAddress = new List();
136 |
137 | ///
138 | /// 适配器地址索引
139 | ///
140 | public static int AdapterAddressIndex;
141 |
142 | ///
143 | /// 适配器网关
144 | ///
145 | public static List AdapterGateway = new List();
146 |
147 | ///
148 | /// 适配器网关索引
149 | ///
150 | public static int AdapterGatewayIndex;
151 |
152 | ///
153 | /// 自动检测出网适配器
154 | ///
155 | public static bool AutoCheckAdapter;
156 |
157 | ///
158 | /// v2ray 日志等级
159 | ///
160 | public static string v2rayLoggingLevel;
161 | }
162 |
163 | ///
164 | /// 代理信息
165 | ///
166 | public static List Proxies = new List();
167 |
168 | ///
169 | /// 模式信息
170 | ///
171 | public static List Modes = new List();
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/v2tap/Objects/Mode.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace v2tap.Objects
4 | {
5 | public class Mode
6 | {
7 | ///
8 | /// 名称
9 | ///
10 | public string Name;
11 |
12 | ///
13 | /// 规则
14 | ///
15 | public List> Rule = new List>();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/v2tap/Objects/Server.cs:
--------------------------------------------------------------------------------
1 | namespace v2tap.Objects
2 | {
3 | public class Server
4 | {
5 | ///
6 | /// 唯一 ID
7 | ///
8 | public string ID;
9 |
10 | ///
11 | /// 备注
12 | ///
13 | public string Remark;
14 |
15 | ///
16 | /// 地址
17 | ///
18 | public string Address;
19 |
20 | ///
21 | /// 端口
22 | ///
23 | public int Port;
24 |
25 | ///
26 | /// 用户 ID
27 | ///
28 | public string UserID;
29 |
30 | ///
31 | /// 额外 ID
32 | ///
33 | public int AlterID;
34 |
35 | ///
36 | /// 传输方式
37 | ///
38 | public string TransferMethod;
39 |
40 | ///
41 | /// 路径
42 | ///
43 | public string Path;
44 |
45 | ///
46 | /// 伪装类型
47 | ///
48 | public string FakeType;
49 |
50 | ///
51 | /// TLS 底层传输安全
52 | ///
53 | public bool TLSSecure;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/v2tap/Override/WebClient.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 |
4 | namespace v2tap.Override
5 | {
6 | public class WebClient : System.Net.WebClient
7 | {
8 | ///
9 | /// 超时
10 | ///
11 | public int Timeout = 4000;
12 |
13 | protected override WebRequest GetWebRequest(Uri address)
14 | {
15 | var request = base.GetWebRequest(address);
16 | request.Timeout = Timeout;
17 | ((HttpWebRequest)request).ReadWriteTimeout = Timeout;
18 |
19 | return request;
20 | }
21 |
22 | public static WebClient GetClient()
23 | {
24 | return new WebClient();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/v2tap/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("v2tap")]
9 | [assembly: AssemblyDescription("将 tun2socks 和 v2ray 搭配实现的 VPN 工具,跟 SSTap 类似")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("v2tap")]
13 | [assembly: AssemblyCopyright("Copyright © 2018 - 2019 Holli_Freed")]
14 | [assembly: AssemblyTrademark("Holli_Freed")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 会使此程序集中的类型
18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("53132dc3-8a46-4558-978c-605a643d1300")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
33 | // 方法是按如下所示使用“*”: :
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("0.1.1.3")]
36 | [assembly: AssemblyFileVersion("0.1.1.3")]
37 |
--------------------------------------------------------------------------------
/v2tap/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本:4.0.30319.42000
5 | //
6 | // 对此文件的更改可能会导致不正确的行为,并且如果
7 | // 重新生成代码,这些更改将会丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace v2tap.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// 一个强类型的资源类,用于查找本地化的字符串等。
17 | ///
18 | // 此类是由 StronglyTypedResourceBuilder
19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
21 | // (以 /str 作为命令选项),或重新生成 VS 项目。
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// 返回此类使用的缓存的 ResourceManager 实例。
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("v2tap.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// 重写当前线程的 CurrentUICulture 属性
51 | /// 重写当前线程的 CurrentUICulture 属性。
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// 查找 System.Byte[] 类型的本地化资源。
65 | ///
66 | internal static byte[] defaultConfig {
67 | get {
68 | object obj = ResourceManager.GetObject("defaultConfig", resourceCulture);
69 | return ((byte[])(obj));
70 | }
71 | }
72 |
73 | ///
74 | /// 查找 System.Byte[] 类型的本地化资源。
75 | ///
76 | internal static byte[] defaultServerConfig {
77 | get {
78 | object obj = ResourceManager.GetObject("defaultServerConfig", resourceCulture);
79 | return ((byte[])(obj));
80 | }
81 | }
82 |
83 | ///
84 | /// 查找 System.Byte[] 类型的本地化资源。
85 | ///
86 | internal static byte[] v2ray {
87 | get {
88 | object obj = ResourceManager.GetObject("v2ray", resourceCulture);
89 | return ((byte[])(obj));
90 | }
91 | }
92 |
93 | ///
94 | /// 查找 System.Byte[] 类型的本地化资源。
95 | ///
96 | internal static byte[] v2rayNotBypassChina {
97 | get {
98 | object obj = ResourceManager.GetObject("v2rayNotBypassChina", resourceCulture);
99 | return ((byte[])(obj));
100 | }
101 | }
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/v2tap/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | ..\Resources\defaultConfig.ini;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
123 |
124 |
125 | ..\Resources\defaultServerConfig.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
126 |
127 |
128 | ..\Resources\v2ray.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
129 |
130 |
131 | ..\Resources\v2rayNotBypassChina.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
132 |
133 |
--------------------------------------------------------------------------------
/v2tap/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace v2tap.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/v2tap/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/v2tap/Resources/defaultConfig.ini:
--------------------------------------------------------------------------------
1 | [v2tap]
2 | TUNTAPAddress = 10.0.100.10
3 | TUNTAPGateway = 10.0.100.1
4 | TUNTAPNetmask = 255.255.255.0
5 | TUNTAPDNS = 114.114.114.114,114.114.115.115
6 | TUNTAPMetric = 100
7 | AutoAdapterMetric = True
8 | AutoCheckAdapter = True
9 | v2rayLoggingLevel = ERROR
10 |
--------------------------------------------------------------------------------
/v2tap/Resources/defaultServerConfig.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "ID": "918170c7-b3cc-4fa4-aac6-c763886ffed1",
4 | "Remark": "HK - BandwagonHost - 1Gbps",
5 | "Address": "www.baidu.com",
6 | "Port": 443,
7 | "UserID": "e02d1b2d-7a22-453f-adb7-4576016df5c6",
8 | "AlterId": 0,
9 | "TransferMethod": "WebSockets",
10 | "Path": "/",
11 | "FakeType": "None",
12 | "TLSSecure": true
13 | }
14 | ]
--------------------------------------------------------------------------------
/v2tap/Resources/v2ray.json:
--------------------------------------------------------------------------------
1 | {
2 | "stats": {},
3 | "log": {
4 | "access": "logging\\v2ray-access.log",
5 | "error": "logging\\v2ray-error.log",
6 | "loglevel": "v2rayLoggingLevel"
7 | },
8 | "api": {
9 | "services": [
10 | "StatsService"
11 | ],
12 | "tag": "api"
13 | },
14 | "policy": {
15 | "system": {
16 | "statsInboundUplink": true,
17 | "statsInboundDownlink": true
18 | }
19 | },
20 | "dns": {
21 | "clientIP": "AdapterAddress",
22 | "hosts": {
23 | "localhost": "127.0.0.1",
24 | "domain:lan": "127.0.0.1",
25 | "domain:arpa": "127.0.0.1",
26 | "domain:local": "127.0.0.1"
27 | },
28 | "servers": [
29 | "8.8.8.8",
30 | {
31 | "address": "114.114.114.114",
32 | "port": 53,
33 | "domains": [
34 | "geosite:cn"
35 | ]
36 | }
37 | ]
38 | },
39 | "routing": {
40 | "strategy": "rules",
41 | "settings": {
42 | "domainStrategy": "IPIfNonMatch",
43 | "rules": [
44 | {
45 | "type": "field",
46 | "inboundTag": [
47 | "api"
48 | ],
49 | "outboundTag": "api"
50 | },
51 | {
52 | "type": "field",
53 | "domain": [
54 | "geosite:cn"
55 | ],
56 | "outboundTag": "directOutbound"
57 | },
58 | {
59 | "type": "field",
60 | "ip": [
61 | "geoip:cn",
62 | "geoip:private"
63 | ],
64 | "outboundTag": "directOutbound"
65 | }
66 | ]
67 | }
68 | },
69 | "inbounds": [
70 | {
71 | "listen": "127.0.0.1",
72 | "port": 1099,
73 | "protocol": "socks",
74 | "settings": {
75 | "udp": true
76 | },
77 | "sniffing": {
78 | "enabled": true,
79 | "destOverride": [
80 | "http",
81 | "tls"
82 | ]
83 | },
84 | "tag": "defaultInbound"
85 | },
86 | {
87 | "listen": "127.0.0.1",
88 | "port": 1020,
89 | "protocol": "dokodemo-door",
90 | "settings": {
91 | "address": "127.0.0.1"
92 | },
93 | "tag": "api"
94 | }
95 | ],
96 | "outbounds": [
97 | {
98 | "sendThrough": "AdapterAddress",
99 | "protocol": "vmess",
100 | "settings": {
101 | "vnext": [
102 | {
103 | "address": "v2rayServerAddress",
104 | "port": v2rayServerPort,
105 | "users": [
106 | {
107 | "id": "v2rayUserID",
108 | "alterId": v2rayAlterID,
109 | "security": "auto"
110 | }
111 | ]
112 | }
113 | ]
114 | },
115 | "streamSettings": {
116 | "network": "v2rayTransferMethod",
117 | "security": "v2rayTLSSecure",
118 | "tcpSettings": {
119 | "header": {
120 | "type": "v2rayFakeType",
121 | "request": {},
122 | "response": {}
123 | }
124 | },
125 | "kcpSettings": {
126 | "header": {
127 | "type": "v2rayFakeType"
128 | }
129 | },
130 | "wsSettings": {
131 | "path": "v2rayPath"
132 | },
133 | "httpSettings": {
134 | "path": "v2rayPath"
135 | },
136 | "quicSettings": {
137 | "header": {
138 | "type": "v2rayFakeType"
139 | }
140 | }
141 | },
142 | "tag": "defaultOutbound"
143 | },
144 | {
145 | "sendThrough": "AdapterAddress",
146 | "protocol": "freedom",
147 | "settings": {},
148 | "tag": "directOutbound"
149 | }
150 | ]
151 | }
--------------------------------------------------------------------------------
/v2tap/Resources/v2rayNotBypassChina.json:
--------------------------------------------------------------------------------
1 | {
2 | "stats": {},
3 | "log": {
4 | "access": "logging\\v2ray-access.log",
5 | "error": "logging\\v2ray-error.log",
6 | "loglevel": "v2rayLoggingLevel"
7 | },
8 | "api": {
9 | "services": [
10 | "StatsService"
11 | ],
12 | "tag": "api"
13 | },
14 | "policy": {
15 | "system": {
16 | "statsInboundUplink": true,
17 | "statsInboundDownlink": true
18 | }
19 | },
20 | "dns": {
21 | "clientIP": "AdapterAddress",
22 | "hosts": {
23 | "localhost": "127.0.0.1",
24 | "domain:lan": "127.0.0.1",
25 | "domain:arpa": "127.0.0.1",
26 | "domain:local": "127.0.0.1"
27 | },
28 | "servers": [
29 | "8.8.8.8",
30 | {
31 | "address": "114.114.114.114",
32 | "port": 53,
33 | "domains": [
34 | "geosite:cn"
35 | ]
36 | }
37 | ]
38 | },
39 | "routing": {
40 | "strategy": "rules",
41 | "settings": {
42 | "domainStrategy": "IPIfNonMatch",
43 | "rules": [
44 | {
45 | "type": "field",
46 | "inboundTag": [
47 | "api"
48 | ],
49 | "outboundTag": "api"
50 | },
51 | {
52 | "type": "field",
53 | "ip": [
54 | "geoip:private"
55 | ],
56 | "outboundTag": "directOutbound"
57 | }
58 | ]
59 | }
60 | },
61 | "inbounds": [
62 | {
63 | "listen": "127.0.0.1",
64 | "port": 1099,
65 | "protocol": "socks",
66 | "settings": {
67 | "udp": true
68 | },
69 | "sniffing": {
70 | "enabled": true,
71 | "destOverride": [
72 | "http",
73 | "tls"
74 | ]
75 | },
76 | "tag": "defaultInbound"
77 | },
78 | {
79 | "listen": "127.0.0.1",
80 | "port": 1020,
81 | "protocol": "dokodemo-door",
82 | "settings": {
83 | "address": "127.0.0.1"
84 | },
85 | "tag": "api"
86 | }
87 | ],
88 | "outbounds": [
89 | {
90 | "sendThrough": "AdapterAddress",
91 | "protocol": "vmess",
92 | "settings": {
93 | "vnext": [
94 | {
95 | "address": "v2rayServerAddress",
96 | "port": v2rayServerPort,
97 | "users": [
98 | {
99 | "id": "v2rayUserID",
100 | "alterId": v2rayAlterID,
101 | "security": "auto"
102 | }
103 | ]
104 | }
105 | ]
106 | },
107 | "streamSettings": {
108 | "network": "v2rayTransferMethod",
109 | "security": "v2rayTLSSecure",
110 | "tcpSettings": {
111 | "header": {
112 | "type": "v2rayFakeType",
113 | "request": {},
114 | "response": {}
115 | }
116 | },
117 | "kcpSettings": {
118 | "header": {
119 | "type": "v2rayFakeType"
120 | }
121 | },
122 | "wsSettings": {
123 | "path": "v2rayPath"
124 | },
125 | "httpSettings": {
126 | "path": "v2rayPath"
127 | },
128 | "quicSettings": {
129 | "header": {
130 | "type": "v2rayFakeType"
131 | }
132 | }
133 | },
134 | "tag": "defaultOutbound"
135 | },
136 | {
137 | "sendThrough": "AdapterAddress",
138 | "protocol": "freedom",
139 | "settings": {},
140 | "tag": "directOutbound"
141 | }
142 | ]
143 | }
--------------------------------------------------------------------------------
/v2tap/Utils/Util.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Net;
6 | using System.Net.NetworkInformation;
7 | using System.Net.Sockets;
8 | using System.Text;
9 |
10 | namespace v2tap.Utils
11 | {
12 | public static class Util
13 | {
14 | ///
15 | /// 写日志
16 | ///
17 | /// 日志内容
18 | public static void WriteLine(string content, Global.Level level)
19 | {
20 | var path = String.Format("{0}\\{1}", Global.Path.LoggingDirectory, Global.Path.v2tapLogging);
21 | var info = String.Format("[{0}][{1}] {2}\n", DateTime.Now.ToString(), "{0}", content);
22 |
23 | switch (level)
24 | {
25 | case Global.Level.DEBUG:
26 | File.AppendAllText(path, String.Format(info, "DBUG"));
27 | break;
28 | case Global.Level.INFO:
29 | File.AppendAllText(path, String.Format(info, "INFO"));
30 | break;
31 | case Global.Level.WARNING:
32 | File.AppendAllText(path, String.Format(info, "WARN"));
33 | break;
34 | case Global.Level.ERROR:
35 | File.AppendAllText(path, String.Format(info, "EROR"));
36 | break;
37 | default:
38 | break;
39 | }
40 | }
41 |
42 | ///
43 | /// 执行命令行命令
44 | ///
45 | /// 命令内容
46 | public static void ExecuteCommand(string content)
47 | {
48 | var p = new Process();
49 | p.StartInfo.FileName = "cmd.exe";
50 | p.StartInfo.Arguments = "/c " + content;
51 | p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
52 | p.Start();
53 | }
54 |
55 | ///
56 | /// 将 CIDR /xx 翻译为掩码
57 | ///
58 | /// CIDR
59 | /// 掩码
60 | public static string TranslateCIDRToNetmask(string CIDR)
61 | {
62 | var dict = new Dictionary()
63 | {
64 | { "1", "128.0.0.0" },
65 | { "2", "192.0.0.0" },
66 | { "3", "224.0.0.0" },
67 | { "4", "240.0.0.0" },
68 | { "5", "248.0.0.0" },
69 | { "6", "252.0.0.0" },
70 | { "7", "254.0.0.0" },
71 | { "8", "255.0.0.0" },
72 | { "9", "255.128.0.0" },
73 | { "10", "255.192.0.0" },
74 | { "11", "255.224.0.0" },
75 | { "12", "255.240.0.0" },
76 | { "13", "255.248.0.0" },
77 | { "14", "255.252.0.0" },
78 | { "15", "255.254.0.0" },
79 | { "16", "255.255.0.0" },
80 | { "17", "255.255.128.0" },
81 | { "18", "255.255.192.0" },
82 | { "19", "255.255.224.0" },
83 | { "20", "255.255.240.0" },
84 | { "21", "255.255.248.0" },
85 | { "22", "255.255.252.0" },
86 | { "23", "255.255.254.0" },
87 | { "24", "255.255.255.0" },
88 | { "25", "255.255.255.128" },
89 | { "26", "255.255.255.192" },
90 | { "27", "255.255.255.224" },
91 | { "28", "255.255.255.240" },
92 | { "29", "255.255.255.248" },
93 | { "30", "255.255.255.252" },
94 | { "31", "255.255.255.254" },
95 | { "32", "255.255.255.255" }
96 | };
97 |
98 | if (dict.ContainsKey(CIDR))
99 | {
100 | return dict[CIDR];
101 | }
102 | else
103 | {
104 | return "255.255.255.255";
105 | }
106 | }
107 |
108 | ///
109 | /// 从文件中加载配置信息
110 | ///
111 | public static void InitConfigsFromFile()
112 | {
113 | var data = new IniParser.FileIniDataParser().ReadFile("v2tap.ini");
114 |
115 | Global.Configs.TUNTAPAddress = data["v2tap"]["TUNTAPAddress"];
116 | Global.Configs.TUNTAPGateway = data["v2tap"]["TUNTAPGateway"];
117 | Global.Configs.TUNTAPNetmask = data["v2tap"]["TUNTAPNetmask"];
118 | Global.Configs.TUNTAPDNS = data["v2tap"]["TUNTAPDNS"];
119 | Global.Configs.TUNTAPMetric = int.Parse(data["v2tap"]["TUNTAPMetric"]);
120 | Global.Configs.AutoAdapterMetric = Boolean.Parse(data["v2tap"]["AutoAdapterMetric"]);
121 | Global.Configs.AutoCheckAdapter = Boolean.Parse(data["v2tap"]["AutoCheckAdapter"]);
122 | Global.Configs.v2rayLoggingLevel = data["v2tap"]["v2rayLoggingLevel"];
123 | }
124 |
125 | ///
126 | /// 将配置信息保存到文件中
127 | ///
128 | public static void SaveConfigsToFile()
129 | {
130 | var data = new IniParser.FileIniDataParser().ReadFile("v2tap.ini");
131 |
132 | data["v2tap"]["TUNTAPAddress"] = Global.Configs.TUNTAPAddress;
133 | data["v2tap"]["TUNTAPGateway"] = Global.Configs.TUNTAPGateway;
134 | data["v2tap"]["TUNTAPNetmask"] = Global.Configs.TUNTAPNetmask;
135 | data["v2tap"]["TUNTAPDNS"] = Global.Configs.TUNTAPDNS;
136 | data["v2tap"]["TUNTAPMetric"] = Global.Configs.TUNTAPMetric.ToString();
137 | data["v2tap"]["AutoAdapterMetric"] = Global.Configs.AutoAdapterMetric.ToString();
138 | data["v2tap"]["AutoCheckAdapter"] = Global.Configs.AutoCheckAdapter.ToString();
139 | data["v2tap"]["v2rayLoggingLevel"] = Global.Configs.v2rayLoggingLevel;
140 |
141 | File.WriteAllText("v2tap.ini", data.ToString());
142 | }
143 |
144 | ///
145 | /// 从文件中加载服务器配置信息
146 | ///
147 | public static void InitServersFromFile()
148 | {
149 | Global.Proxies = Newtonsoft.Json.JsonConvert.DeserializeObject>(File.ReadAllText("v2tap.json"));
150 | }
151 |
152 | ///
153 | /// 将服务器配置信息保存到文件中
154 | ///
155 | public static void SaveServersToFile()
156 | {
157 | File.WriteAllText("v2tap.json", Newtonsoft.Json.JsonConvert.SerializeObject(Global.Proxies));
158 | }
159 |
160 | ///
161 | /// 从文件中加载模式配置信息
162 | ///
163 | public static void InitModesFromFile()
164 | {
165 | foreach (var filename in Directory.GetFiles(Global.Path.ModeDirectory, "*.txt"))
166 | {
167 | var mode = new Objects.Mode();
168 | mode.Name = filename
169 | .Replace(Global.Path.ModeDirectory + "\\", "")
170 | .Replace(".txt", "");
171 |
172 | using (var sr = new StringReader(File.ReadAllText(filename)))
173 | {
174 | string text;
175 |
176 | while ((text = sr.ReadLine()) != null)
177 | {
178 | var splited = text.Split('/');
179 | mode.Rule.Add(new KeyValuePair(splited[0], TranslateCIDRToNetmask(splited[1])));
180 | }
181 | }
182 |
183 | Global.Modes.Add(mode);
184 | }
185 | }
186 |
187 | ///
188 | /// 加载适配器信息
189 | ///
190 | public static void InitAdapter()
191 | {
192 | if (Global.Configs.AutoAdapterMetric)
193 | {
194 | using (var client = new UdpClient("114.114.114.114", 53))
195 | {
196 | var address = ((IPEndPoint)client.Client.LocalEndPoint).Address;
197 |
198 | int addressCount = 0;
199 | int gatewayCount = 0;
200 | bool addressGeted = false;
201 |
202 | var adapters = NetworkInterface.GetAllNetworkInterfaces();
203 | foreach (var adapter in adapters)
204 | {
205 | var properties = adapter.GetIPProperties();
206 |
207 | foreach (var information in properties.UnicastAddresses)
208 | {
209 | if (information.Address.AddressFamily == AddressFamily.InterNetwork)
210 | {
211 | var ip = information.Address.ToString();
212 |
213 | if (ip.StartsWith("10.") || ip.StartsWith("172.") || ip.StartsWith("192."))
214 | {
215 | if (Equals(information.Address, address))
216 | {
217 | addressGeted = true;
218 | }
219 | else
220 | {
221 | if (!addressGeted) addressCount++;
222 | }
223 |
224 | Global.Configs.AdapterAddress.Add(ip);
225 | }
226 | }
227 | }
228 |
229 | foreach (var information in properties.GatewayAddresses)
230 | {
231 | if (information.Address.AddressFamily == AddressFamily.InterNetwork)
232 | {
233 | string IP = information.Address.ToString();
234 |
235 | if (IP.StartsWith("10.") || IP.StartsWith("172.") || IP.StartsWith("192."))
236 | {
237 | if (!addressGeted)
238 | {
239 | gatewayCount++;
240 | }
241 |
242 | Global.Configs.AdapterGateway.Add(IP);
243 | }
244 | }
245 | }
246 | }
247 |
248 | Global.Configs.AdapterAddressIndex = addressCount;
249 | Global.Configs.AdapterGatewayIndex = gatewayCount;
250 | }
251 | }
252 | }
253 |
254 | ///
255 | /// 处理流量信息
256 | ///
257 | /// 流量信息
258 | /// 处理好的信息
259 | public static string ProcessBandwidth(long bandwidth)
260 | {
261 | var result = ((double)bandwidth) / 1024;
262 |
263 | if (result < 1024)
264 | {
265 | return Math.Round(result, 2).ToString() + " KB";
266 | }
267 |
268 | result = result / 1024;
269 | if (result < 1024)
270 | {
271 | return Math.Round(result, 2).ToString() + " MB";
272 | }
273 |
274 | result = result / 1024;
275 | if (result < 1024)
276 | {
277 | return Math.Round(result, 2).ToString() + " GB";
278 | }
279 |
280 | result = result / 1024;
281 | return Math.Round(result, 2).ToString() + " TB";
282 | }
283 | }
284 | }
285 |
--------------------------------------------------------------------------------
/v2tap/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/v2tap/v2tap.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Text;
4 | using System.Windows.Forms;
5 |
6 | namespace v2tap
7 | {
8 | public static class v2tap
9 | {
10 | public static String[] RequiredFile = new String[]
11 | {
12 | "tun2socks.exe",
13 | "wv2ray.exe",
14 | "v2ray.exe",
15 | "v2ctl.exe",
16 | "geoip.dat",
17 | "geosite.dat"
18 | };
19 |
20 | ///
21 | /// 应用程序的主入口点
22 | ///
23 | [STAThread]
24 | public static void Main()
25 | {
26 | try
27 | {
28 | #if !DEBUG
29 | // 检查文件
30 | foreach (var file in RequiredFile)
31 | {
32 | if (!File.Exists(file))
33 | {
34 | MessageBox.Show($"缺失重要文件:{file}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
35 | return;
36 | }
37 | }
38 | #endif
39 |
40 | // 日志目录
41 | if (!Directory.Exists(Global.Path.LoggingDirectory)) Directory.CreateDirectory(Global.Path.LoggingDirectory);
42 |
43 | // 模式目录
44 | if (!Directory.Exists(Global.Path.ModeDirectory)) Directory.CreateDirectory(Global.Path.ModeDirectory);
45 |
46 | // 默认配置
47 | if (!File.Exists("v2tap.ini")) File.WriteAllText("v2tap.ini", Encoding.UTF8.GetString(Properties.Resources.defaultConfig));
48 | if (!File.Exists("v2tap.json")) File.WriteAllText("v2tap.json", Encoding.UTF8.GetString(Properties.Resources.defaultServerConfig));
49 |
50 | // 加载配置
51 | Utils.Util.InitConfigsFromFile();
52 | Utils.Util.InitServersFromFile();
53 | Utils.Util.InitModesFromFile();
54 |
55 | // 初始化适配器
56 | Utils.Util.InitAdapter();
57 | }
58 | catch (Exception ex)
59 | {
60 | MessageBox.Show("在初始化配置时发生错误:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
61 | return;
62 | }
63 |
64 | Application.EnableVisualStyles();
65 | Application.SetCompatibleTextRenderingDefault(false);
66 | Application.Run(Global.Form.MainForm = new Forms.MainForm());
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/v2tap/v2tap.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Debug
8 | AnyCPU
9 | {53132DC3-8A46-4558-978C-605A643D1300}
10 | WinExe
11 | v2tap
12 | v2tap
13 | v4.7.2
14 | 512
15 | true
16 | true
17 |
18 |
19 | false
20 | publish\
21 | true
22 | Disk
23 | false
24 | Foreground
25 | 7
26 | Days
27 | false
28 | false
29 | true
30 | 0
31 | 1.0.0.%2a
32 | false
33 | true
34 |
35 |
36 | x64
37 | true
38 | full
39 | false
40 | bin\Debug\
41 | DEBUG;TRACE
42 | prompt
43 | 4
44 | CS0618
45 |
46 |
47 |
48 | v2tap.manifest
49 |
50 |
51 | v2tap.v2tap
52 |
53 |
54 | bin\Release_x64\
55 | TRACE
56 | true
57 | CS0618
58 | pdbonly
59 | x64
60 | prompt
61 | MinimumRecommendedRules.ruleset
62 | true
63 |
64 |
65 | bin\Release_x86\
66 | TRACE
67 | true
68 | CS0618
69 | pdbonly
70 | x86
71 | prompt
72 | MinimumRecommendedRules.ruleset
73 | true
74 |
75 |
76 |
77 | ..\packages\Google.Protobuf.3.6.1\lib\net45\Google.Protobuf.dll
78 |
79 |
80 | ..\packages\Grpc.Core.1.18.0\lib\net45\Grpc.Core.dll
81 |
82 |
83 | ..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll
84 | True
85 |
86 |
87 |
88 |
89 | ..\packages\System.Interactive.Async.3.1.1\lib\net46\System.Interactive.Async.dll
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 | Form
124 |
125 |
126 | AdvancedForm.cs
127 |
128 |
129 | Form
130 |
131 |
132 | EditForm.cs
133 |
134 |
135 | Form
136 |
137 |
138 | ImportForm.cs
139 |
140 |
141 | Form
142 |
143 |
144 | MainForm.cs
145 |
146 |
147 |
148 |
149 |
150 | Component
151 |
152 |
153 |
154 |
155 |
156 | AdvancedForm.cs
157 |
158 |
159 | EditForm.cs
160 |
161 |
162 | ImportForm.cs
163 |
164 |
165 | MainForm.cs
166 |
167 |
168 | ResXFileCodeGenerator
169 | Resources.Designer.cs
170 | Designer
171 |
172 |
173 | True
174 | Resources.resx
175 | True
176 |
177 |
178 | SettingsSingleFileGenerator
179 | Settings.Designer.cs
180 |
181 |
182 | True
183 | Settings.settings
184 | True
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 | False
195 | Microsoft .NET Framework 4.7.2 %28x86 和 x64%29
196 | true
197 |
198 |
199 | False
200 | .NET Framework 3.5 SP1
201 | false
202 |
203 |
204 |
205 |
206 |
207 |
208 | 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 | @echo off
217 |
218 | cd /d $(TargetDir)
219 | if "$(ConfigurationName)"=="Release x64" goto do64
220 | if "$(ConfigurationName)"=="Release x86" goto do86
221 | goto doNone
222 |
223 | :do64
224 | mkdir v2tap_x64 > nul 2>&1
225 | copy /y Google.Protobuf.dll v2tap_x64 > nul 2>&1
226 | copy /y Grpc.Core.dll v2tap_x64 > nul 2>&1
227 | copy /y grpc_csharp_ext.x64.dll v2tap_x64 > nul 2>&1
228 | copy /y Newtonsoft.Json.dll v2tap_x64 > nul 2>&1
229 | copy /y System.Interactive.Async.dll v2tap_x64 > nul 2>&1
230 | copy /y v2tap.exe v2tap_x64 > nul 2>&1
231 | copy /y ..\..\..\binaries\tap-windows-latest-stable.exe v2tap_x64 > nul 2>&1
232 | copy /y ..\..\..\binaries\tun2socks_x64.exe v2tap_x64\tun2socks.exe > nul 2>&1
233 | copy /y ..\..\..\binaries\v2ray\x64\v2ray.exe v2tap_x64 > nul 2>&1
234 | copy /y ..\..\..\binaries\v2ray\x64\wv2ray.exe v2tap_x64 > nul 2>&1
235 | copy /y ..\..\..\binaries\v2ray\x64\v2ctl.exe v2tap_x64 > nul 2>&1
236 | copy /y ..\..\..\binaries\v2ray\x64\geosite.dat v2tap_x64 > nul 2>&1
237 | copy /y ..\..\..\binaries\v2ray\x64\geoip.dat v2tap_x64 > nul 2>&1
238 | mkdir v2tap_x64\mode > nul 2>&1
239 | copy /y ..\..\..\modes\* v2tap_x64\mode > nul 2>&1
240 | bc c -fmt:7z -r v2tap_x64\v2tap_x64.7z v2tap_x64\* > nul 2>&1
241 | goto doNone
242 |
243 | :do86
244 | mkdir v2tap_x86 > nul 2>&1
245 | copy /y Google.Protobuf.dll v2tap_x86 > nul 2>&1
246 | copy /y Grpc.Core.dll v2tap_x86 > nul 2>&1
247 | copy /y grpc_csharp_ext.x86.dll v2tap_x86 > nul 2>&1
248 | copy /y Newtonsoft.Json.dll v2tap_x86 > nul 2>&1
249 | copy /y System.Interactive.Async.dll v2tap_x86 > nul 2>&1
250 | copy /y v2tap.exe v2tap_x86 > nul 2>&1
251 | copy /y ..\..\..\binaries\tap-windows-latest-stable.exe v2tap_x86 > nul 2>&1
252 | copy /y ..\..\..\binaries\tun2socks_x86.exe v2tap_x86\tun2socks.exe > nul 2>&1
253 | copy /y ..\..\..\binaries\v2ray\x86\v2ray.exe v2tap_x86 > nul 2>&1
254 | copy /y ..\..\..\binaries\v2ray\x86\wv2ray.exe v2tap_x86 > nul 2>&1
255 | copy /y ..\..\..\binaries\v2ray\x86\v2ctl.exe v2tap_x86 > nul 2>&1
256 | copy /y ..\..\..\binaries\v2ray\x86\geosite.dat v2tap_x86 > nul 2>&1
257 | copy /y ..\..\..\binaries\v2ray\x86\geoip.dat v2tap_x86 > nul 2>&1
258 | mkdir v2tap_x86\mode > nul 2>&1
259 | copy /y ..\..\..\modes\* v2tap_x86\mode > nul 2>&1
260 | bc c -fmt:7z -r v2tap_x86\v2tap_x86.7z v2tap_x86\* > nul 2>&1
261 | goto doNone
262 |
263 | :doNone
264 | exit
265 |
266 |
267 | @echo off
268 |
269 | cd /d $(TargetDir)
270 | if "$(ConfigurationName)"=="Release x64" goto do64
271 | if "$(ConfigurationName)"=="Release x86" goto do86
272 | goto doNone
273 |
274 | :do64
275 | rd /s /q v2tap_x64 > nul 2>&1
276 | goto doNone
277 |
278 | :do86
279 | rd /s /q v2tap_x86 > nul 2>&1
280 | goto doNone
281 |
282 | :doNone
283 | exit
284 |
285 |
--------------------------------------------------------------------------------
/v2tap/v2tap.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------