- Shadowsocks - Shadowsocks.Common - Shadowsocks.Crypto - Shadowsocks.WPFpull/2897/head
| @@ -0,0 +1,100 @@ | |||
| root = true | |||
| # EditorConfig: http://EditorConfig.org | |||
| # VS extension: https://marketplace.visualstudio.com/items?itemName = MadsKristensen.EditorConfig | |||
| # 4 space indentation | |||
| [*] | |||
| charset = utf-8 | |||
| indent_style = space | |||
| indent_size = 4 | |||
| # Microsoft .NET properties | |||
| csharp_new_line_before_members_in_object_initializers = false | |||
| csharp_preferred_modifier_order = public, private, protected, internal, new, abstract, virtual, sealed, override, static, readonly, extern, unsafe, volatile, async:suggestion | |||
| csharp_style_expression_bodied_methods = true:suggestion | |||
| csharp_style_var_elsewhere = true:suggestion | |||
| csharp_style_var_for_built_in_types = true:suggestion | |||
| csharp_style_var_when_type_is_apparent = true:suggestion | |||
| dotnet_naming_rule.private_constants_rule.severity = suggestion | |||
| dotnet_naming_rule.private_constants_rule.style = all_upper_style | |||
| dotnet_naming_rule.private_constants_rule.symbols = private_constants_symbols | |||
| dotnet_naming_rule.private_static_readonly_rule.severity = suggestion | |||
| dotnet_naming_rule.private_static_readonly_rule.style = lower_camel_case_style | |||
| dotnet_naming_rule.private_static_readonly_rule.symbols = private_static_readonly_symbols | |||
| dotnet_naming_style.all_upper_style.capitalization = all_upper | |||
| dotnet_naming_style.all_upper_style.word_separator = _ | |||
| dotnet_naming_style.lower_camel_case_style.capitalization = camel_case | |||
| dotnet_naming_style.lower_camel_case_style.required_prefix = _ | |||
| dotnet_naming_symbols.private_constants_symbols.applicable_accessibilities = private | |||
| dotnet_naming_symbols.private_constants_symbols.applicable_kinds = field | |||
| dotnet_naming_symbols.private_constants_symbols.required_modifiers = const | |||
| dotnet_naming_symbols.private_static_readonly_symbols.applicable_accessibilities = private | |||
| dotnet_naming_symbols.private_static_readonly_symbols.applicable_kinds = field | |||
| dotnet_naming_symbols.private_static_readonly_symbols.required_modifiers = static,readonly | |||
| dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none | |||
| dotnet_style_parentheses_in_other_binary_operators = never_if_unnecessary:none | |||
| dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none | |||
| dotnet_style_qualification_for_event = false:warning | |||
| dotnet_style_qualification_for_field = false:warning | |||
| dotnet_style_qualification_for_method = false:warning | |||
| dotnet_style_qualification_for_property = false:warning | |||
| dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion | |||
| # CSharp code style settings: | |||
| [*.cs] | |||
| # Prefer "var" everywhere | |||
| csharp_style_var_for_built_in_types = true:suggestion | |||
| csharp_style_var_when_type_is_apparent = true:suggestion | |||
| csharp_style_var_elsewhere = true:suggestion | |||
| # Prefer method-like constructs to have a block body | |||
| csharp_style_expression_bodied_methods = true:suggestion | |||
| csharp_style_expression_bodied_constructors = false:none | |||
| csharp_style_expression_bodied_operators = true:suggestion | |||
| # Prefer property-like constructs to have an expression-body | |||
| csharp_style_expression_bodied_properties = true:suggestion | |||
| csharp_style_expression_bodied_indexers = true:suggestion | |||
| csharp_style_expression_bodied_accessors = true:none | |||
| # Suggest more modern language features when available | |||
| csharp_style_pattern_matching_over_is_with_cast_check = false:none | |||
| csharp_style_pattern_matching_over_as_with_null_check = false:none | |||
| csharp_style_inlined_variable_declaration = false:none | |||
| csharp_style_throw_expression = false:none | |||
| csharp_style_conditional_delegate_call = true:suggestion | |||
| # Newline settings | |||
| csharp_new_line_before_open_brace = all | |||
| csharp_new_line_before_else = true | |||
| csharp_new_line_before_catch = true | |||
| csharp_new_line_before_finally = true | |||
| csharp_new_line_before_members_in_object_initializers = false | |||
| csharp_new_line_before_members_in_anonymous_types = false | |||
| # Dotnet code style settings: | |||
| [*.{cs,vb}] | |||
| # Sort using and Import directives with System.* appearing first | |||
| dotnet_sort_system_directives_first = false | |||
| # Avoid "this." and "Me." if not necessary | |||
| dotnet_style_qualification_for_field = false:warning | |||
| dotnet_style_qualification_for_property = false:warning | |||
| dotnet_style_qualification_for_method = false:warning | |||
| dotnet_style_qualification_for_event = false:warning | |||
| # Use language keywords instead of framework type names for type references | |||
| dotnet_style_predefined_type_for_locals_parameters_members = true:silent | |||
| dotnet_style_predefined_type_for_member_access = true:silent | |||
| # Suggest more modern language features when available | |||
| dotnet_style_object_initializer = true:silent | |||
| dotnet_style_collection_initializer = true:silent | |||
| dotnet_style_coalesce_expression = true:suggestion | |||
| dotnet_style_null_propagation = true:suggestion | |||
| dotnet_style_explicit_tuple_names = true:suggestion | |||
| [*.{appxmanifest,asax,ascx,aspx,axml,build,config,cs,cshtml,csproj,css,dbml,discomap,dtd,htm,html,js,json,jsproj,jsx,lsproj,master,njsproj,nuspec,proj,props,proto,razor,resjson,resw,resx,skin,StyleCop,targets,tasks,ts,tsx,vb,vbproj,xaml,xamlx,xml,xoml,xsd}] | |||
| indent_style = space | |||
| indent_size = 4 | |||
| tab_width = 4 | |||
| @@ -0,0 +1,9 @@ | |||
| using SimpleInjector; | |||
| namespace Shadowsocks.Common.Model | |||
| { | |||
| public static class IoCManager | |||
| { | |||
| public static Container Container { get; } = new Container(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,17 @@ | |||
| <Project Sdk="Microsoft.NET.Sdk"> | |||
| <PropertyGroup> | |||
| <TargetFramework>netstandard2.1</TargetFramework> | |||
| <Authors>clowwindy & community 2020</Authors> | |||
| <Company>clowwindy & community 2020</Company> | |||
| <Product>Shadowsocks Common</Product> | |||
| </PropertyGroup> | |||
| <ItemGroup> | |||
| <PackageReference Include="Google.Protobuf" Version="3.13.0" /> | |||
| <PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> | |||
| <PackageReference Include="NLog" Version="4.7.5" /> | |||
| <PackageReference Include="SimpleInjector" Version="5.0.4" /> | |||
| </ItemGroup> | |||
| </Project> | |||
| @@ -1,11 +1,7 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Runtime.Serialization; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Shadowsocks.Util.SystemProxy | |||
| namespace Shadowsocks.Common.SystemProxy | |||
| { | |||
| enum ProxyExceptionType | |||
| { | |||
| @@ -1,151 +1,143 @@ | |||
| using System; | |||
| using System.ComponentModel; | |||
| using System.IO; | |||
| using System.Net.Sockets; | |||
| using System.Net; | |||
| using System.Diagnostics; | |||
| using System.Text; | |||
| using Shadowsocks.Util.SystemProxy; | |||
| namespace NLog | |||
| { | |||
| public static class LoggerExtension | |||
| { | |||
| // for key, iv, etc... | |||
| public static void Dump(this Logger logger, string tag, ReadOnlySpan<byte> arr) | |||
| { | |||
| logger.Dump(tag, arr.ToArray(), arr.Length); | |||
| } | |||
| public static void Dump(this Logger logger, string tag, byte[] arr, int length = -1) | |||
| { | |||
| if (arr == null) logger.Trace($@" | |||
| {tag}: | |||
| (null) | |||
| "); | |||
| if (length == -1) length = arr.Length; | |||
| if (!logger.IsTraceEnabled) return; | |||
| string hex = BitConverter.ToString(arr.AsSpan(0, Math.Min(arr.Length, length)).ToArray()).Replace("-", ""); | |||
| string content = $@" | |||
| {tag}: | |||
| {hex} | |||
| "; | |||
| logger.Trace(content); | |||
| } | |||
| // for cipher and plain text, so we can use openssl to test | |||
| public static void DumpBase64(this Logger logger, string tag, ReadOnlySpan<byte> arr) | |||
| { | |||
| logger.DumpBase64(tag, arr.ToArray(), arr.Length); | |||
| } | |||
| public static void DumpBase64(this Logger logger, string tag, byte[] arr, int length = -1) | |||
| { | |||
| if (arr == null) logger.Trace($@" | |||
| {tag}: | |||
| (null) | |||
| "); | |||
| if (length == -1) length = arr.Length; | |||
| if (!logger.IsTraceEnabled) return; | |||
| string hex = Convert.ToBase64String(arr.AsSpan(0, Math.Min(arr.Length, length)).ToArray()); | |||
| string content = $@" | |||
| {tag}: | |||
| {hex} | |||
| "; | |||
| logger.Trace(content); | |||
| } | |||
| public static void Debug(this Logger logger, EndPoint local, EndPoint remote, int len, string header = null, string tailer = null) | |||
| { | |||
| if (logger.IsDebugEnabled) | |||
| { | |||
| if (header == null && tailer == null) | |||
| logger.Debug($"{local} => {remote} (size={len})"); | |||
| else if (header == null && tailer != null) | |||
| logger.Debug($"{local} => {remote} (size={len}), {tailer}"); | |||
| else if (header != null && tailer == null) | |||
| logger.Debug($"{header}: {local} => {remote} (size={len})"); | |||
| else | |||
| logger.Debug($"{header}: {local} => {remote} (size={len}), {tailer}"); | |||
| } | |||
| } | |||
| public static void Debug(this Logger logger, Socket sock, int len, string header = null, string tailer = null) | |||
| { | |||
| if (logger.IsDebugEnabled) | |||
| { | |||
| logger.Debug(sock.LocalEndPoint, sock.RemoteEndPoint, len, header, tailer); | |||
| } | |||
| } | |||
| public static void LogUsefulException(this Logger logger, Exception e) | |||
| { | |||
| // just log useful exceptions, not all of them | |||
| if (e is SocketException) | |||
| { | |||
| SocketException se = (SocketException)e; | |||
| if (se.SocketErrorCode == SocketError.ConnectionAborted) | |||
| { | |||
| // closed by browser when sending | |||
| // normally happens when download is canceled or a tab is closed before page is loaded | |||
| } | |||
| else if (se.SocketErrorCode == SocketError.ConnectionReset) | |||
| { | |||
| // received rst | |||
| } | |||
| else if (se.SocketErrorCode == SocketError.NotConnected) | |||
| { | |||
| // The application tried to send or receive data, and the System.Net.Sockets.Socket is not connected. | |||
| } | |||
| else if (se.SocketErrorCode == SocketError.HostUnreachable) | |||
| { | |||
| // There is no network route to the specified host. | |||
| } | |||
| else if (se.SocketErrorCode == SocketError.TimedOut) | |||
| { | |||
| // The connection attempt timed out, or the connected host has failed to respond. | |||
| } | |||
| else | |||
| { | |||
| logger.Warn(e); | |||
| } | |||
| } | |||
| else if (e is ObjectDisposedException) | |||
| { | |||
| } | |||
| else if (e is Win32Exception) | |||
| { | |||
| var ex = (Win32Exception)e; | |||
| // Win32Exception (0x80004005): A 32 bit processes cannot access modules of a 64 bit process. | |||
| if ((uint)ex.ErrorCode != 0x80004005) | |||
| { | |||
| logger.Warn(e); | |||
| } | |||
| } | |||
| else if (e is ProxyException) | |||
| { | |||
| var ex = (ProxyException)e; | |||
| switch (ex.Type) | |||
| { | |||
| case ProxyExceptionType.FailToRun: | |||
| case ProxyExceptionType.QueryReturnMalformed: | |||
| case ProxyExceptionType.SysproxyExitError: | |||
| logger.Error($"sysproxy - {ex.Type.ToString()}:{ex.Message}"); | |||
| break; | |||
| case ProxyExceptionType.QueryReturnEmpty: | |||
| case ProxyExceptionType.Unspecific: | |||
| logger.Error($"sysproxy - {ex.Type.ToString()}"); | |||
| break; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| logger.Warn(e); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| using Shadowsocks.Common.SystemProxy; | |||
| using System; | |||
| using System.ComponentModel; | |||
| using System.Net; | |||
| using System.Net.Sockets; | |||
| namespace NLog | |||
| { | |||
| public static class LoggerExtension | |||
| { | |||
| // for key, iv, etc... | |||
| public static void Dump(this Logger logger, string tag, ReadOnlySpan<byte> arr) | |||
| { | |||
| logger.Dump(tag, arr.ToArray(), arr.Length); | |||
| } | |||
| public static void Dump(this Logger logger, string tag, byte[] arr, int length = -1) | |||
| { | |||
| if (arr == null) logger.Trace($@" | |||
| {tag}: | |||
| (null) | |||
| "); | |||
| if (length == -1) length = arr.Length; | |||
| if (!logger.IsTraceEnabled) return; | |||
| string hex = BitConverter.ToString(arr.AsSpan(0, Math.Min(arr.Length, length)).ToArray()).Replace("-", ""); | |||
| string content = $@" | |||
| {tag}: | |||
| {hex} | |||
| "; | |||
| logger.Trace(content); | |||
| } | |||
| // for cipher and plain text, so we can use openssl to test | |||
| public static void DumpBase64(this Logger logger, string tag, ReadOnlySpan<byte> arr) | |||
| { | |||
| logger.DumpBase64(tag, arr.ToArray(), arr.Length); | |||
| } | |||
| public static void DumpBase64(this Logger logger, string tag, byte[] arr, int length = -1) | |||
| { | |||
| if (arr == null) logger.Trace($@" | |||
| {tag}: | |||
| (null) | |||
| "); | |||
| if (length == -1) length = arr.Length; | |||
| if (!logger.IsTraceEnabled) return; | |||
| string hex = Convert.ToBase64String(arr.AsSpan(0, Math.Min(arr.Length, length)).ToArray()); | |||
| string content = $@" | |||
| {tag}: | |||
| {hex} | |||
| "; | |||
| logger.Trace(content); | |||
| } | |||
| public static void Debug(this Logger logger, EndPoint local, EndPoint remote, int len, string header = null, string tailer = null) | |||
| { | |||
| if (logger.IsDebugEnabled) | |||
| { | |||
| if (header == null && tailer == null) | |||
| logger.Debug($"{local} => {remote} (size={len})"); | |||
| else if (header == null && tailer != null) | |||
| logger.Debug($"{local} => {remote} (size={len}), {tailer}"); | |||
| else if (header != null && tailer == null) | |||
| logger.Debug($"{header}: {local} => {remote} (size={len})"); | |||
| else | |||
| logger.Debug($"{header}: {local} => {remote} (size={len}), {tailer}"); | |||
| } | |||
| } | |||
| public static void Debug(this Logger logger, Socket sock, int len, string header = null, string tailer = null) | |||
| { | |||
| if (logger.IsDebugEnabled) | |||
| logger.Debug(sock.LocalEndPoint, sock.RemoteEndPoint, len, header, tailer); | |||
| } | |||
| public static void LogUsefulException(this Logger logger, Exception e) | |||
| { | |||
| // just log useful exceptions, not all of them | |||
| if (e is SocketException se) | |||
| { | |||
| if (se.SocketErrorCode == SocketError.ConnectionAborted) | |||
| { | |||
| // closed by browser when sending | |||
| // normally happens when download is canceled or a tab is closed before page is loaded | |||
| } | |||
| else if (se.SocketErrorCode == SocketError.ConnectionReset) | |||
| { | |||
| // received rst | |||
| } | |||
| else if (se.SocketErrorCode == SocketError.NotConnected) | |||
| { | |||
| // The application tried to send or receive data, and the System.Net.Sockets.Socket is not connected. | |||
| } | |||
| else if (se.SocketErrorCode == SocketError.HostUnreachable) | |||
| { | |||
| // There is no network route to the specified host. | |||
| } | |||
| else if (se.SocketErrorCode == SocketError.TimedOut) | |||
| { | |||
| // The connection attempt timed out, or the connected host has failed to respond. | |||
| } | |||
| else | |||
| { | |||
| logger.Warn(e); | |||
| } | |||
| } | |||
| else if (e is ObjectDisposedException) | |||
| { | |||
| } | |||
| else if (e is Win32Exception ex) | |||
| { | |||
| // Win32Exception (0x80004005): A 32 bit processes cannot access modules of a 64 bit process. | |||
| if ((uint)ex.ErrorCode != 0x80004005) | |||
| logger.Warn(e); | |||
| } | |||
| else if (e is ProxyException pe) | |||
| { | |||
| switch (pe.Type) | |||
| { | |||
| case ProxyExceptionType.FailToRun: | |||
| case ProxyExceptionType.QueryReturnMalformed: | |||
| case ProxyExceptionType.SysproxyExitError: | |||
| logger.Error($"sysproxy - {pe.Type}:{pe.Message}"); | |||
| break; | |||
| case ProxyExceptionType.QueryReturnEmpty: | |||
| case ProxyExceptionType.Unspecific: | |||
| logger.Error($"sysproxy - {pe.Type}"); | |||
| break; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| logger.Warn(e); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1,12 +1,12 @@ | |||
| using System; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Security.Cryptography; | |||
| namespace Shadowsocks.Encryption.AEAD | |||
| namespace Shadowsocks.Crypto.AEAD | |||
| { | |||
| public class AEADAesGcmNativeEncryptor : AEADEncryptor | |||
| public class AEADAesGcmNativeCrypto : AEADCrypto | |||
| { | |||
| public AEADAesGcmNativeEncryptor(string method, string password) : base(method, password) | |||
| public AEADAesGcmNativeCrypto(string method, string password) : base(method, password) | |||
| { | |||
| } | |||
| @@ -51,4 +51,4 @@ namespace Shadowsocks.Encryption.AEAD | |||
| return clen; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1,16 +1,17 @@ | |||
| using System; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using Org.BouncyCastle.Crypto.Engines; | |||
| using Org.BouncyCastle.Crypto.Modes; | |||
| using Org.BouncyCastle.Crypto.Parameters; | |||
| namespace Shadowsocks.Encryption.AEAD | |||
| namespace Shadowsocks.Crypto.AEAD | |||
| { | |||
| public class AEADBouncyCastleEncryptor : AEADEncryptor | |||
| public class AEADBouncyCastleCrypto : AEADCrypto | |||
| { | |||
| IAeadCipher aead; | |||
| bool enc; | |||
| public AEADBouncyCastleEncryptor(string method, string password) : base(method, password) | |||
| public AEADBouncyCastleCrypto(string method, string password) : base(method, password) | |||
| { | |||
| aead = cipherFamily switch | |||
| { | |||
| @@ -1,320 +1,322 @@ | |||
| using NLog; | |||
| using Shadowsocks.Controller; | |||
| using Shadowsocks.Encryption.Exception; | |||
| using Shadowsocks.Encryption.Stream; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Net; | |||
| using System.Runtime.CompilerServices; | |||
| using System.Text; | |||
| namespace Shadowsocks.Encryption.AEAD | |||
| { | |||
| public abstract class AEADEncryptor : EncryptorBase | |||
| { | |||
| private static readonly Logger logger = LogManager.GetCurrentClassLogger(); | |||
| // We are using the same saltLen and keyLen | |||
| private const string Info = "ss-subkey"; | |||
| private static readonly byte[] InfoBytes = Encoding.ASCII.GetBytes(Info); | |||
| // every connection should create its own buffer | |||
| private readonly byte[] buffer = new byte[65536]; | |||
| private int bufPtr = 0; | |||
| public const int ChunkLengthBytes = 2; | |||
| public const uint ChunkLengthMask = 0x3FFFu; | |||
| protected CipherFamily cipherFamily; | |||
| protected CipherInfo CipherInfo; | |||
| protected static byte[] masterKey = Array.Empty<byte>(); | |||
| protected byte[] sessionKey = Array.Empty<byte>(); | |||
| protected int keyLen; | |||
| protected int saltLen; | |||
| protected int tagLen; | |||
| protected int nonceLen; | |||
| protected byte[] salt; | |||
| protected byte[] nonce; | |||
| // Is first packet | |||
| protected bool saltReady; | |||
| // Is first chunk(tcp request) | |||
| protected bool tcpRequestSent; | |||
| public AEADEncryptor(string method, string password) | |||
| : base(method, password) | |||
| { | |||
| CipherInfo = GetCiphers()[method.ToLower()]; | |||
| cipherFamily = CipherInfo.Type; | |||
| AEADCipherParameter parameter = (AEADCipherParameter)CipherInfo.CipherParameter; | |||
| keyLen = parameter.KeySize; | |||
| saltLen = parameter.SaltSize; | |||
| tagLen = parameter.TagSize; | |||
| nonceLen = parameter.NonceSize; | |||
| InitKey(password); | |||
| salt = new byte[saltLen]; | |||
| // Initialize all-zero nonce for each connection | |||
| nonce = new byte[nonceLen]; | |||
| logger.Dump($"masterkey {instanceId}", masterKey, keyLen); | |||
| logger.Dump($"nonce {instanceId}", nonce, keyLen); | |||
| } | |||
| protected abstract Dictionary<string, CipherInfo> GetCiphers(); | |||
| protected void InitKey(string password) | |||
| { | |||
| byte[] passbuf = Encoding.UTF8.GetBytes(password); | |||
| // init master key | |||
| if (masterKey == null) | |||
| { | |||
| masterKey = new byte[keyLen]; | |||
| } | |||
| if (masterKey.Length != keyLen) | |||
| { | |||
| Array.Resize(ref masterKey, keyLen); | |||
| } | |||
| StreamEncryptor.LegacyDeriveKey(passbuf, masterKey, keyLen); | |||
| // init session key | |||
| sessionKey = new byte[keyLen]; | |||
| } | |||
| public virtual void InitCipher(byte[] salt, bool isEncrypt) | |||
| { | |||
| this.salt = new byte[saltLen]; | |||
| Array.Copy(salt, this.salt, saltLen); | |||
| CryptoUtils.HKDF(keyLen, masterKey, salt, InfoBytes).CopyTo(sessionKey, 0); | |||
| logger.Dump($"salt {instanceId}", salt, saltLen); | |||
| logger.Dump($"sessionkey {instanceId}", sessionKey, keyLen); | |||
| } | |||
| public abstract int CipherEncrypt(ReadOnlySpan<byte> plain, Span<byte> cipher); | |||
| public abstract int CipherDecrypt(Span<byte> plain, ReadOnlySpan<byte> cipher); | |||
| #region TCP | |||
| [MethodImpl(MethodImplOptions.Synchronized | MethodImplOptions.AggressiveOptimization)] | |||
| public override int Encrypt(ReadOnlySpan<byte> plain, Span<byte> cipher) | |||
| { | |||
| // push data | |||
| Span<byte> tmp = buffer.AsSpan(0, plain.Length + bufPtr); | |||
| plain.CopyTo(tmp.Slice(bufPtr)); | |||
| int outlength = 0; | |||
| if (!saltReady) | |||
| { | |||
| saltReady = true; | |||
| // Generate salt | |||
| byte[] saltBytes = RNG.GetBytes(saltLen); | |||
| InitCipher(saltBytes, true); | |||
| saltBytes.CopyTo(cipher); | |||
| outlength = saltLen; | |||
| } | |||
| if (!tcpRequestSent) | |||
| { | |||
| tcpRequestSent = true; | |||
| // read addr byte to encrypt | |||
| int encAddrBufLength = ChunkEncrypt(tmp.Slice(0, AddressBufferLength), cipher.Slice(outlength)); | |||
| tmp = tmp.Slice(AddressBufferLength); | |||
| outlength += encAddrBufLength; | |||
| } | |||
| // handle other chunks | |||
| while (true) | |||
| { | |||
| // calculate next chunk size | |||
| int bufSize = tmp.Length; | |||
| if (bufSize <= 0) | |||
| { | |||
| return outlength; | |||
| } | |||
| int chunklength = (int)Math.Min(bufSize, ChunkLengthMask); | |||
| // read next chunk | |||
| int encChunkLength = ChunkEncrypt(tmp.Slice(0, chunklength), cipher.Slice(outlength)); | |||
| tmp = tmp.Slice(chunklength); | |||
| outlength += encChunkLength; | |||
| // check if we have enough space for outbuf | |||
| // if not, keep buf for next run, at this condition, buffer is not empty | |||
| if (outlength + TCPHandler.ChunkOverheadSize > TCPHandler.BufferSize) | |||
| { | |||
| logger.Debug("enc outbuf almost full, giving up"); | |||
| // write rest data to head of shared buffer | |||
| tmp.CopyTo(buffer); | |||
| bufPtr = tmp.Length; | |||
| return outlength; | |||
| } | |||
| // check if buffer empty | |||
| bufSize = tmp.Length; | |||
| if (bufSize <= 0) | |||
| { | |||
| logger.Debug("No more data to encrypt, leaving"); | |||
| return outlength; | |||
| } | |||
| } | |||
| } | |||
| [MethodImpl(MethodImplOptions.Synchronized | MethodImplOptions.AggressiveOptimization)] | |||
| public override int Decrypt(Span<byte> plain, ReadOnlySpan<byte> cipher) | |||
| { | |||
| int outlength = 0; | |||
| // drop all into buffer | |||
| Span<byte> tmp = buffer.AsSpan(0, cipher.Length + bufPtr); | |||
| cipher.CopyTo(tmp.Slice(bufPtr)); | |||
| int bufSize = tmp.Length; | |||
| logger.Debug($"{instanceId} decrypt tcp, read salt: {!saltReady}"); | |||
| if (!saltReady) | |||
| { | |||
| // check if we get the leading salt | |||
| if (bufSize <= saltLen) | |||
| { | |||
| // need more, write back cache | |||
| tmp.CopyTo(buffer); | |||
| bufPtr = tmp.Length; | |||
| return outlength; | |||
| } | |||
| saltReady = true; | |||
| byte[] salt = tmp.Slice(0, saltLen).ToArray(); | |||
| tmp = tmp.Slice(saltLen); | |||
| InitCipher(salt, false); | |||
| } | |||
| // handle chunks | |||
| while (true) | |||
| { | |||
| bufSize = tmp.Length; | |||
| // check if we have any data | |||
| if (bufSize <= 0) | |||
| { | |||
| logger.Trace("No data in buffer"); | |||
| return outlength; | |||
| } | |||
| // first get chunk length | |||
| if (bufSize <= ChunkLengthBytes + tagLen) | |||
| { | |||
| // so we only have chunk length and its tag? | |||
| // wait more | |||
| logger.Trace($"{instanceId} not enough data to decrypt chunk. write {tmp.Length} byte back to buffer."); | |||
| tmp.CopyTo(buffer); | |||
| bufPtr = tmp.Length; | |||
| return outlength; | |||
| } | |||
| logger.Trace($"{instanceId} try decrypt to offset {outlength}"); | |||
| int len = ChunkDecrypt(plain.Slice(outlength), tmp); | |||
| if (len <= 0) | |||
| { | |||
| logger.Trace($"{instanceId} no chunk decrypted, write {tmp.Length} byte back to buffer."); | |||
| // no chunk decrypted | |||
| tmp.CopyTo(buffer); | |||
| bufPtr = tmp.Length; | |||
| return outlength; | |||
| } | |||
| logger.Trace($"{instanceId} decrypted {len} to offset {outlength}"); | |||
| // drop decrypted data | |||
| tmp = tmp.Slice(ChunkLengthBytes + tagLen + len + tagLen); | |||
| outlength += len; | |||
| // logger.Debug("aead dec outlength " + outlength); | |||
| if (outlength + 100 > TCPHandler.BufferSize) | |||
| { | |||
| logger.Trace($"{instanceId} output almost full, write {tmp.Length} byte back to buffer."); | |||
| tmp.CopyTo(buffer); | |||
| bufPtr = tmp.Length; | |||
| return outlength; | |||
| } | |||
| bufSize = tmp.Length; | |||
| // check if we already done all of them | |||
| if (bufSize <= 0) | |||
| { | |||
| bufPtr = 0; | |||
| logger.Debug($"{instanceId} no data in buffer, already all done"); | |||
| return outlength; | |||
| } | |||
| } | |||
| } | |||
| #endregion | |||
| #region UDP | |||
| [MethodImpl(MethodImplOptions.Synchronized | MethodImplOptions.AggressiveOptimization)] | |||
| public override int EncryptUDP(ReadOnlySpan<byte> plain, Span<byte> cipher) | |||
| { | |||
| RNG.GetSpan(cipher.Slice(0, saltLen)); | |||
| InitCipher(cipher.Slice(0, saltLen).ToArray(), true); | |||
| return saltLen + CipherEncrypt(plain, cipher.Slice(saltLen)); | |||
| } | |||
| [MethodImpl(MethodImplOptions.Synchronized | MethodImplOptions.AggressiveOptimization)] | |||
| public override int DecryptUDP(Span<byte> plain, ReadOnlySpan<byte> cipher) | |||
| { | |||
| InitCipher(cipher.Slice(0, saltLen).ToArray(), false); | |||
| return CipherDecrypt(plain, cipher.Slice(saltLen)); | |||
| } | |||
| #endregion | |||
| [MethodImpl(MethodImplOptions.Synchronized | MethodImplOptions.AggressiveOptimization)] | |||
| private int ChunkEncrypt(ReadOnlySpan<byte> plain, Span<byte> cipher) | |||
| { | |||
| if (plain.Length > ChunkLengthMask) | |||
| { | |||
| logger.Error("enc chunk too big"); | |||
| throw new CryptoErrorException(); | |||
| } | |||
| byte[] lenbuf = BitConverter.GetBytes((ushort)IPAddress.HostToNetworkOrder((short)plain.Length)); | |||
| int cipherLenSize = CipherEncrypt(lenbuf, cipher); | |||
| CryptoUtils.SodiumIncrement(nonce); | |||
| int cipherDataSize = CipherEncrypt(plain, cipher.Slice(cipherLenSize)); | |||
| CryptoUtils.SodiumIncrement(nonce); | |||
| return cipherLenSize + cipherDataSize; | |||
| } | |||
| [MethodImpl(MethodImplOptions.Synchronized | MethodImplOptions.AggressiveOptimization)] | |||
| private int ChunkDecrypt(Span<byte> plain, ReadOnlySpan<byte> cipher) | |||
| { | |||
| // try to dec chunk len | |||
| byte[] chunkLengthByte = new byte[ChunkLengthBytes]; | |||
| CipherDecrypt(chunkLengthByte, cipher.Slice(0, ChunkLengthBytes + tagLen)); | |||
| ushort chunkLength = (ushort)IPAddress.NetworkToHostOrder((short)BitConverter.ToUInt16(chunkLengthByte, 0)); | |||
| if (chunkLength > ChunkLengthMask) | |||
| { | |||
| // we get invalid chunk | |||
| logger.Error($"{instanceId} Invalid chunk length: {chunkLength}"); | |||
| throw new CryptoErrorException(); | |||
| } | |||
| // logger.Debug("Get the real chunk len:" + chunkLength); | |||
| int bufSize = cipher.Length; | |||
| if (bufSize < ChunkLengthBytes + tagLen /* we haven't remove them */+ chunkLength + tagLen) | |||
| { | |||
| logger.Debug($"{instanceId} need {ChunkLengthBytes + tagLen + chunkLength + tagLen}, but have {cipher.Length}"); | |||
| return 0; | |||
| } | |||
| CryptoUtils.SodiumIncrement(nonce); | |||
| // we have enough data to decrypt one chunk | |||
| // drop chunk len and its tag from buffer | |||
| int len = CipherDecrypt(plain, cipher.Slice(ChunkLengthBytes + tagLen, chunkLength + tagLen)); | |||
| CryptoUtils.SodiumIncrement(nonce); | |||
| logger.Trace($"{instanceId} decrypted {len} byte chunk used {ChunkLengthBytes + tagLen + chunkLength + tagLen} from {cipher.Length}"); | |||
| return len; | |||
| } | |||
| } | |||
| } | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Net; | |||
| using System.Runtime.CompilerServices; | |||
| using System.Text; | |||
| using NLog; | |||
| using Shadowsocks.Crypto.Exception; | |||
| using Shadowsocks.Crypto.Stream; | |||
| namespace Shadowsocks.Crypto.AEAD | |||
| { | |||
| public abstract class AEADCrypto : CryptoBase | |||
| { | |||
| private static readonly Logger logger = LogManager.GetCurrentClassLogger(); | |||
| // We are using the same saltLen and keyLen | |||
| private const string Info = "ss-subkey"; | |||
| private static readonly byte[] InfoBytes = Encoding.ASCII.GetBytes(Info); | |||
| // every connection should create its own buffer | |||
| private readonly byte[] buffer = new byte[65536]; | |||
| private int bufPtr = 0; | |||
| public const int ChunkLengthBytes = 2; | |||
| public const uint ChunkLengthMask = 0x3FFFu; | |||
| protected CipherFamily cipherFamily; | |||
| protected CipherInfo CipherInfo; | |||
| protected static byte[] masterKey = Array.Empty<byte>(); | |||
| protected byte[] sessionKey = Array.Empty<byte>(); | |||
| protected int keyLen; | |||
| protected int saltLen; | |||
| protected int tagLen; | |||
| protected int nonceLen; | |||
| protected byte[] salt; | |||
| protected byte[] nonce; | |||
| // Is first packet | |||
| protected bool saltReady; | |||
| // Is first chunk(tcp request) | |||
| protected bool tcpRequestSent; | |||
| public AEADCrypto(string method, string password) | |||
| : base(method, password) | |||
| { | |||
| CipherInfo = GetCiphers()[method.ToLower()]; | |||
| cipherFamily = CipherInfo.Type; | |||
| AEADCipherParameter parameter = (AEADCipherParameter)CipherInfo.CipherParameter; | |||
| keyLen = parameter.KeySize; | |||
| saltLen = parameter.SaltSize; | |||
| tagLen = parameter.TagSize; | |||
| nonceLen = parameter.NonceSize; | |||
| InitKey(password); | |||
| salt = new byte[saltLen]; | |||
| // Initialize all-zero nonce for each connection | |||
| nonce = new byte[nonceLen]; | |||
| logger.Dump($"masterkey {instanceId}", masterKey, keyLen); | |||
| logger.Dump($"nonce {instanceId}", nonce, keyLen); | |||
| } | |||
| protected abstract Dictionary<string, CipherInfo> GetCiphers(); | |||
| protected void InitKey(string password) | |||
| { | |||
| byte[] passbuf = Encoding.UTF8.GetBytes(password); | |||
| // init master key | |||
| if (masterKey == null) | |||
| { | |||
| masterKey = new byte[keyLen]; | |||
| } | |||
| if (masterKey.Length != keyLen) | |||
| { | |||
| Array.Resize(ref masterKey, keyLen); | |||
| } | |||
| StreamCrypto.LegacyDeriveKey(passbuf, masterKey, keyLen); | |||
| // init session key | |||
| sessionKey = new byte[keyLen]; | |||
| } | |||
| public virtual void InitCipher(byte[] salt, bool isEncrypt) | |||
| { | |||
| this.salt = new byte[saltLen]; | |||
| Array.Copy(salt, this.salt, saltLen); | |||
| CryptoUtils.HKDF(keyLen, masterKey, salt, InfoBytes).CopyTo(sessionKey, 0); | |||
| logger.Dump($"salt {instanceId}", salt, saltLen); | |||
| logger.Dump($"sessionkey {instanceId}", sessionKey, keyLen); | |||
| } | |||
| public abstract int CipherEncrypt(ReadOnlySpan<byte> plain, Span<byte> cipher); | |||
| public abstract int CipherDecrypt(Span<byte> plain, ReadOnlySpan<byte> cipher); | |||
| #region TCP | |||
| [MethodImpl(MethodImplOptions.Synchronized)] | |||
| public override int Encrypt(ReadOnlySpan<byte> plain, Span<byte> cipher) | |||
| { | |||
| // push data | |||
| Span<byte> tmp = buffer.AsSpan(0, plain.Length + bufPtr); | |||
| plain.CopyTo(tmp.Slice(bufPtr)); | |||
| int outlength = 0; | |||
| if (!saltReady) | |||
| { | |||
| saltReady = true; | |||
| // Generate salt | |||
| byte[] saltBytes = RNG.GetBytes(saltLen); | |||
| InitCipher(saltBytes, true); | |||
| saltBytes.CopyTo(cipher); | |||
| outlength = saltLen; | |||
| } | |||
| if (!tcpRequestSent) | |||
| { | |||
| tcpRequestSent = true; | |||
| // read addr byte to encrypt | |||
| int encAddrBufLength = ChunkEncrypt(tmp.Slice(0, AddressBufferLength), cipher.Slice(outlength)); | |||
| tmp = tmp.Slice(AddressBufferLength); | |||
| outlength += encAddrBufLength; | |||
| } | |||
| // handle other chunks | |||
| while (true) | |||
| { | |||
| // calculate next chunk size | |||
| int bufSize = tmp.Length; | |||
| if (bufSize <= 0) | |||
| { | |||
| return outlength; | |||
| } | |||
| int chunklength = (int)Math.Min(bufSize, ChunkLengthMask); | |||
| // read next chunk | |||
| int encChunkLength = ChunkEncrypt(tmp.Slice(0, chunklength), cipher.Slice(outlength)); | |||
| tmp = tmp.Slice(chunklength); | |||
| outlength += encChunkLength; | |||
| // check if we have enough space for outbuf | |||
| // if not, keep buf for next run, at this condition, buffer is not empty | |||
| if (outlength + TCPParameter.ChunkOverheadSize > TCPParameter.BufferSize) | |||
| { | |||
| logger.Debug("enc outbuf almost full, giving up"); | |||
| // write rest data to head of shared buffer | |||
| tmp.CopyTo(buffer); | |||
| bufPtr = tmp.Length; | |||
| return outlength; | |||
| } | |||
| // check if buffer empty | |||
| bufSize = tmp.Length; | |||
| if (bufSize <= 0) | |||
| { | |||
| logger.Debug("No more data to encrypt, leaving"); | |||
| return outlength; | |||
| } | |||
| } | |||
| } | |||
| [MethodImpl(MethodImplOptions.Synchronized)] | |||
| public override int Decrypt(Span<byte> plain, ReadOnlySpan<byte> cipher) | |||
| { | |||
| int outlength = 0; | |||
| // drop all into buffer | |||
| Span<byte> tmp = buffer.AsSpan(0, cipher.Length + bufPtr); | |||
| cipher.CopyTo(tmp.Slice(bufPtr)); | |||
| int bufSize = tmp.Length; | |||
| logger.Debug($"{instanceId} decrypt tcp, read salt: {!saltReady}"); | |||
| if (!saltReady) | |||
| { | |||
| // check if we get the leading salt | |||
| if (bufSize <= saltLen) | |||
| { | |||
| // need more, write back cache | |||
| tmp.CopyTo(buffer); | |||
| bufPtr = tmp.Length; | |||
| return outlength; | |||
| } | |||
| saltReady = true; | |||
| byte[] salt = tmp.Slice(0, saltLen).ToArray(); | |||
| tmp = tmp.Slice(saltLen); | |||
| InitCipher(salt, false); | |||
| } | |||
| // handle chunks | |||
| while (true) | |||
| { | |||
| bufSize = tmp.Length; | |||
| // check if we have any data | |||
| if (bufSize <= 0) | |||
| { | |||
| logger.Trace("No data in buffer"); | |||
| return outlength; | |||
| } | |||
| // first get chunk length | |||
| if (bufSize <= ChunkLengthBytes + tagLen) | |||
| { | |||
| // so we only have chunk length and its tag? | |||
| // wait more | |||
| logger.Trace($"{instanceId} not enough data to decrypt chunk. write {tmp.Length} byte back to buffer."); | |||
| tmp.CopyTo(buffer); | |||
| bufPtr = tmp.Length; | |||
| return outlength; | |||
| } | |||
| logger.Trace($"{instanceId} try decrypt to offset {outlength}"); | |||
| int len = ChunkDecrypt(plain.Slice(outlength), tmp); | |||
| if (len <= 0) | |||
| { | |||
| logger.Trace($"{instanceId} no chunk decrypted, write {tmp.Length} byte back to buffer."); | |||
| // no chunk decrypted | |||
| tmp.CopyTo(buffer); | |||
| bufPtr = tmp.Length; | |||
| return outlength; | |||
| } | |||
| logger.Trace($"{instanceId} decrypted {len} to offset {outlength}"); | |||
| // drop decrypted data | |||
| tmp = tmp.Slice(ChunkLengthBytes + tagLen + len + tagLen); | |||
| outlength += len; | |||
| // logger.Debug("aead dec outlength " + outlength); | |||
| if (outlength + 100 > TCPParameter.BufferSize) | |||
| { | |||
| logger.Trace($"{instanceId} output almost full, write {tmp.Length} byte back to buffer."); | |||
| tmp.CopyTo(buffer); | |||
| bufPtr = tmp.Length; | |||
| return outlength; | |||
| } | |||
| bufSize = tmp.Length; | |||
| // check if we already done all of them | |||
| if (bufSize <= 0) | |||
| { | |||
| bufPtr = 0; | |||
| logger.Debug($"{instanceId} no data in buffer, already all done"); | |||
| return outlength; | |||
| } | |||
| } | |||
| } | |||
| #endregion | |||
| #region UDP | |||
| [MethodImpl(MethodImplOptions.Synchronized)] | |||
| public override int EncryptUDP(ReadOnlySpan<byte> plain, Span<byte> cipher) | |||
| { | |||
| RNG.GetSpan(cipher.Slice(0, saltLen)); | |||
| InitCipher(cipher.Slice(0, saltLen).ToArray(), true); | |||
| return saltLen + CipherEncrypt(plain, cipher.Slice(saltLen)); | |||
| } | |||
| [MethodImpl(MethodImplOptions.Synchronized)] | |||
| public override int DecryptUDP(Span<byte> plain, ReadOnlySpan<byte> cipher) | |||
| { | |||
| InitCipher(cipher.Slice(0, saltLen).ToArray(), false); | |||
| return CipherDecrypt(plain, cipher.Slice(saltLen)); | |||
| } | |||
| #endregion | |||
| [MethodImpl(MethodImplOptions.Synchronized)] | |||
| private int ChunkEncrypt(ReadOnlySpan<byte> plain, Span<byte> cipher) | |||
| { | |||
| if (plain.Length > ChunkLengthMask) | |||
| { | |||
| logger.Error("enc chunk too big"); | |||
| throw new CryptoErrorException(); | |||
| } | |||
| byte[] lenbuf = BitConverter.GetBytes((ushort)IPAddress.HostToNetworkOrder((short)plain.Length)); | |||
| int cipherLenSize = CipherEncrypt(lenbuf, cipher); | |||
| CryptoUtils.SodiumIncrement(nonce); | |||
| int cipherDataSize = CipherEncrypt(plain, cipher.Slice(cipherLenSize)); | |||
| CryptoUtils.SodiumIncrement(nonce); | |||
| return cipherLenSize + cipherDataSize; | |||
| } | |||
| [MethodImpl(MethodImplOptions.Synchronized)] | |||
| private int ChunkDecrypt(Span<byte> plain, ReadOnlySpan<byte> cipher) | |||
| { | |||
| // try to dec chunk len | |||
| byte[] chunkLengthByte = new byte[ChunkLengthBytes]; | |||
| CipherDecrypt(chunkLengthByte, cipher.Slice(0, ChunkLengthBytes + tagLen)); | |||
| ushort chunkLength = (ushort)IPAddress.NetworkToHostOrder((short)BitConverter.ToUInt16(chunkLengthByte, 0)); | |||
| if (chunkLength > ChunkLengthMask) | |||
| { | |||
| // we get invalid chunk | |||
| logger.Error($"{instanceId} Invalid chunk length: {chunkLength}"); | |||
| throw new CryptoErrorException(); | |||
| } | |||
| // logger.Debug("Get the real chunk len:" + chunkLength); | |||
| int bufSize = cipher.Length; | |||
| if (bufSize < ChunkLengthBytes + tagLen /* we haven't remove them */+ chunkLength + tagLen) | |||
| { | |||
| logger.Debug($"{instanceId} need {ChunkLengthBytes + tagLen + chunkLength + tagLen}, but have {cipher.Length}"); | |||
| return 0; | |||
| } | |||
| CryptoUtils.SodiumIncrement(nonce); | |||
| // we have enough data to decrypt one chunk | |||
| // drop chunk len and its tag from buffer | |||
| int len = CipherDecrypt(plain, cipher.Slice(ChunkLengthBytes + tagLen, chunkLength + tagLen)); | |||
| CryptoUtils.SodiumIncrement(nonce); | |||
| logger.Trace($"{instanceId} decrypted {len} byte chunk used {ChunkLengthBytes + tagLen + chunkLength + tagLen} from {cipher.Length}"); | |||
| return len; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,15 +1,16 @@ | |||
| using NaCl.Core; | |||
| using NaCl.Core.Base; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| namespace Shadowsocks.Encryption.AEAD | |||
| using NaCl.Core; | |||
| using NaCl.Core.Base; | |||
| namespace Shadowsocks.Crypto.AEAD | |||
| { | |||
| public class AEADNaClEncryptor : AEADEncryptor | |||
| public class AEADNaClCrypto : AEADCrypto | |||
| { | |||
| SnufflePoly1305 enc; | |||
| public AEADNaClEncryptor(string method, string password) : base(method, password) | |||
| public AEADNaClCrypto(string method, string password) : base(method, password) | |||
| { | |||
| } | |||
| @@ -43,16 +44,19 @@ namespace Shadowsocks.Encryption.AEAD | |||
| public override int CipherEncrypt(ReadOnlySpan<byte> plain, Span<byte> cipher) | |||
| { | |||
| byte[] ct = enc.Encrypt(plain, null, nonce); | |||
| ct.CopyTo(cipher); | |||
| return ct.Length; | |||
| //byte[] ct = enc.Encrypt(plain, null, nonce); | |||
| //ct.CopyTo(cipher); | |||
| //return ct.Length; | |||
| throw new NotImplementedException(); | |||
| } | |||
| public override int CipherDecrypt(Span<byte> plain, ReadOnlySpan<byte> cipher) | |||
| { | |||
| byte[] pt = enc.Decrypt(cipher, null, nonce); | |||
| pt.CopyTo(plain); | |||
| return pt.Length; | |||
| //byte[] pt = enc.Decrypt(cipher, null, nonce); | |||
| //pt.CopyTo(plain); | |||
| //return pt.Length; | |||
| throw new NotImplementedException(); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,6 +1,4 @@ | |||
| using Shadowsocks.Controller; | |||
| namespace Shadowsocks.Encryption | |||
| namespace Shadowsocks.Crypto | |||
| { | |||
| public enum CipherFamily | |||
| { | |||
| @@ -96,7 +94,9 @@ namespace Shadowsocks.Encryption | |||
| public override string ToString() | |||
| { | |||
| return StandardState == CipherStandardState.InUse ? Name : $"{Name} ({I18N.GetString(StandardState.ToString().ToLower())})"; | |||
| // TODO: | |||
| // return StandardState == CipherStandardState.InUse ? Name : $"{Name} ({I18N.GetString(StandardState.ToString().ToLower())})"; | |||
| return ""; | |||
| } | |||
| public string ToString(bool verbose) | |||
| { | |||
| @@ -108,4 +108,4 @@ namespace Shadowsocks.Encryption | |||
| return $"{Name} {StandardState} {CipherParameter}"; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1,49 +1,48 @@ | |||
| using System; | |||
| using System.Runtime.CompilerServices; | |||
| namespace Shadowsocks.Encryption | |||
| { | |||
| public abstract class EncryptorBase : IEncryptor | |||
| { | |||
| private static int _currentId = 0; | |||
| public const int MaxInputSize = 32768; | |||
| public const int MAX_DOMAIN_LEN = 255; | |||
| public const int ADDR_PORT_LEN = 2; | |||
| public const int ADDR_ATYP_LEN = 1; | |||
| public const int ATYP_IPv4 = 0x01; | |||
| public const int ATYP_DOMAIN = 0x03; | |||
| public const int ATYP_IPv6 = 0x04; | |||
| public const int MD5Length = 16; | |||
| // for debugging only, give it a number to trace data stream | |||
| public readonly int instanceId; | |||
| protected EncryptorBase(string method, string password) | |||
| { | |||
| instanceId = _currentId; | |||
| _currentId++; | |||
| Method = method; | |||
| Password = password; | |||
| } | |||
| protected string Method; | |||
| protected string Password; | |||
| public override string ToString() | |||
| { | |||
| return $"{instanceId}({Method},{Password})"; | |||
| } | |||
| public abstract int Encrypt(ReadOnlySpan<byte> plain, Span<byte> cipher); | |||
| public abstract int Decrypt(Span<byte> plain, ReadOnlySpan<byte> cipher); | |||
| public abstract int EncryptUDP(ReadOnlySpan<byte> plain, Span<byte> cipher); | |||
| public abstract int DecryptUDP(Span<byte> plain, ReadOnlySpan<byte> cipher); | |||
| public int AddressBufferLength { get; set; } = -1; | |||
| } | |||
| } | |||
| using System; | |||
| namespace Shadowsocks.Crypto | |||
| { | |||
| public abstract class CryptoBase : ICrypto | |||
| { | |||
| private static int _currentId = 0; | |||
| public const int MaxInputSize = 32768; | |||
| public const int MAX_DOMAIN_LEN = 255; | |||
| public const int ADDR_PORT_LEN = 2; | |||
| public const int ADDR_ATYP_LEN = 1; | |||
| public const int ATYP_IPv4 = 0x01; | |||
| public const int ATYP_DOMAIN = 0x03; | |||
| public const int ATYP_IPv6 = 0x04; | |||
| public const int MD5Length = 16; | |||
| // for debugging only, give it a number to trace data stream | |||
| public readonly int instanceId; | |||
| protected CryptoBase(string method, string password) | |||
| { | |||
| instanceId = _currentId; | |||
| _currentId++; | |||
| Method = method; | |||
| Password = password; | |||
| } | |||
| protected string Method; | |||
| protected string Password; | |||
| public override string ToString() | |||
| { | |||
| return $"{instanceId}({Method},{Password})"; | |||
| } | |||
| public abstract int Encrypt(ReadOnlySpan<byte> plain, Span<byte> cipher); | |||
| public abstract int Decrypt(Span<byte> plain, ReadOnlySpan<byte> cipher); | |||
| public abstract int EncryptUDP(ReadOnlySpan<byte> plain, Span<byte> cipher); | |||
| public abstract int DecryptUDP(Span<byte> plain, ReadOnlySpan<byte> cipher); | |||
| public int AddressBufferLength { get; set; } = -1; | |||
| } | |||
| } | |||
| @@ -1,119 +1,123 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Reflection; | |||
| using System.Text; | |||
| using Shadowsocks.Encryption.AEAD; | |||
| using Shadowsocks.Encryption.Stream; | |||
| namespace Shadowsocks.Encryption | |||
| { | |||
| public static class EncryptorFactory | |||
| { | |||
| public static string DefaultCipher = "chacha20-ietf-poly1305"; | |||
| private static readonly Dictionary<string, Type> _registeredEncryptors = new Dictionary<string, Type>(); | |||
| private static readonly Dictionary<string, CipherInfo> ciphers = new Dictionary<string, CipherInfo>(); | |||
| private static readonly Type[] ConstructorTypes = { typeof(string), typeof(string) }; | |||
| static EncryptorFactory() | |||
| { | |||
| foreach (var method in StreamPlainNativeEncryptor.SupportedCiphers()) | |||
| { | |||
| if (!_registeredEncryptors.ContainsKey(method.Key)) | |||
| { | |||
| ciphers.Add(method.Key, method.Value); | |||
| _registeredEncryptors.Add(method.Key, typeof(StreamPlainNativeEncryptor)); | |||
| } | |||
| } | |||
| foreach (var method in StreamRc4NativeEncryptor.SupportedCiphers()) | |||
| { | |||
| if (!_registeredEncryptors.ContainsKey(method.Key)) | |||
| { | |||
| ciphers.Add(method.Key, method.Value); | |||
| _registeredEncryptors.Add(method.Key, typeof(StreamRc4NativeEncryptor)); | |||
| } | |||
| } | |||
| foreach (var method in StreamAesCfbBouncyCastleEncryptor.SupportedCiphers()) | |||
| { | |||
| if (!_registeredEncryptors.ContainsKey(method.Key)) | |||
| { | |||
| ciphers.Add(method.Key, method.Value); | |||
| _registeredEncryptors.Add(method.Key, typeof(StreamAesCfbBouncyCastleEncryptor)); | |||
| } | |||
| } | |||
| foreach (var method in StreamChachaNaClEncryptor.SupportedCiphers()) | |||
| { | |||
| if (!_registeredEncryptors.ContainsKey(method.Key)) | |||
| { | |||
| ciphers.Add(method.Key, method.Value); | |||
| _registeredEncryptors.Add(method.Key, typeof(StreamChachaNaClEncryptor)); | |||
| } | |||
| } | |||
| foreach (var method in AEADAesGcmNativeEncryptor.SupportedCiphers()) | |||
| { | |||
| if (!_registeredEncryptors.ContainsKey(method.Key)) | |||
| { | |||
| ciphers.Add(method.Key, method.Value); | |||
| _registeredEncryptors.Add(method.Key, typeof(AEADAesGcmNativeEncryptor)); | |||
| } | |||
| } | |||
| foreach (var method in AEADNaClEncryptor.SupportedCiphers()) | |||
| { | |||
| if (!_registeredEncryptors.ContainsKey(method.Key)) | |||
| { | |||
| ciphers.Add(method.Key, method.Value); | |||
| _registeredEncryptors.Add(method.Key, typeof(AEADNaClEncryptor)); | |||
| } | |||
| } | |||
| } | |||
| public static IEncryptor GetEncryptor(string method, string password) | |||
| { | |||
| if (string.IsNullOrEmpty(method)) | |||
| { | |||
| method = Model.Server.DefaultMethod; | |||
| } | |||
| method = method.ToLowerInvariant(); | |||
| bool ok = _registeredEncryptors.TryGetValue(method, out Type t); | |||
| if (!ok) | |||
| { | |||
| t = _registeredEncryptors[DefaultCipher]; | |||
| } | |||
| ConstructorInfo c = t?.GetConstructor(ConstructorTypes) ?? | |||
| throw new TypeLoadException("can't load constructor"); | |||
| if (c == null) throw new System.Exception("Invalid ctor"); | |||
| IEncryptor result = (IEncryptor)c.Invoke(new object[] { method, password }); | |||
| return result; | |||
| } | |||
| public static string DumpRegisteredEncryptor() | |||
| { | |||
| var sb = new StringBuilder(); | |||
| sb.Append(Environment.NewLine); | |||
| sb.AppendLine("-------------------------"); | |||
| sb.AppendLine("Registered Encryptor Info"); | |||
| foreach (var encryptor in _registeredEncryptors) | |||
| { | |||
| sb.AppendLine($"{ciphers[encryptor.Key].ToString(true)} => {encryptor.Value.Name}"); | |||
| } | |||
| // use ----- instead of =======, so when user paste it to Github, it won't became title | |||
| sb.AppendLine("-------------------------"); | |||
| return sb.ToString(); | |||
| } | |||
| public static CipherInfo GetCipherInfo(string name) | |||
| { | |||
| // TODO: Replace cipher when required not exist | |||
| return ciphers[name]; | |||
| } | |||
| public static IEnumerable<CipherInfo> ListAvaliableCiphers() | |||
| { | |||
| return ciphers.Values; | |||
| } | |||
| } | |||
| } | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Reflection; | |||
| using System.Text; | |||
| using Shadowsocks.Common.Crypto; | |||
| using Shadowsocks.Common.Model; | |||
| using Shadowsocks.Crypto.AEAD; | |||
| using Shadowsocks.Crypto.Stream; | |||
| namespace Shadowsocks.Crypto | |||
| { | |||
| public static class CryptoFactory | |||
| { | |||
| public static string DefaultCipher = "chacha20-ietf-poly1305"; | |||
| private static readonly Dictionary<string, Type> _registeredEncryptors = new Dictionary<string, Type>(); | |||
| private static readonly Dictionary<string, CipherInfo> ciphers = new Dictionary<string, CipherInfo>(); | |||
| private static readonly Type[] ConstructorTypes = { typeof(string), typeof(string) }; | |||
| static CryptoFactory() | |||
| { | |||
| foreach (var method in StreamPlainNativeCrypto.SupportedCiphers()) | |||
| { | |||
| if (!_registeredEncryptors.ContainsKey(method.Key)) | |||
| { | |||
| ciphers.Add(method.Key, method.Value); | |||
| _registeredEncryptors.Add(method.Key, typeof(StreamPlainNativeCrypto)); | |||
| } | |||
| } | |||
| foreach (var method in StreamRc4NativeCrypto.SupportedCiphers()) | |||
| { | |||
| if (!_registeredEncryptors.ContainsKey(method.Key)) | |||
| { | |||
| ciphers.Add(method.Key, method.Value); | |||
| _registeredEncryptors.Add(method.Key, typeof(StreamRc4NativeCrypto)); | |||
| } | |||
| } | |||
| foreach (var method in StreamAesCfbBouncyCastleCrypto.SupportedCiphers()) | |||
| { | |||
| if (!_registeredEncryptors.ContainsKey(method.Key)) | |||
| { | |||
| ciphers.Add(method.Key, method.Value); | |||
| _registeredEncryptors.Add(method.Key, typeof(StreamAesCfbBouncyCastleCrypto)); | |||
| } | |||
| } | |||
| foreach (var method in StreamChachaNaClCrypto.SupportedCiphers()) | |||
| { | |||
| if (!_registeredEncryptors.ContainsKey(method.Key)) | |||
| { | |||
| ciphers.Add(method.Key, method.Value); | |||
| _registeredEncryptors.Add(method.Key, typeof(StreamChachaNaClCrypto)); | |||
| } | |||
| } | |||
| foreach (var method in AEADAesGcmNativeCrypto.SupportedCiphers()) | |||
| { | |||
| if (!_registeredEncryptors.ContainsKey(method.Key)) | |||
| { | |||
| ciphers.Add(method.Key, method.Value); | |||
| _registeredEncryptors.Add(method.Key, typeof(AEADAesGcmNativeCrypto)); | |||
| } | |||
| } | |||
| foreach (var method in AEADNaClCrypto.SupportedCiphers()) | |||
| { | |||
| if (!_registeredEncryptors.ContainsKey(method.Key)) | |||
| { | |||
| ciphers.Add(method.Key, method.Value); | |||
| _registeredEncryptors.Add(method.Key, typeof(AEADNaClCrypto)); | |||
| } | |||
| } | |||
| } | |||
| public static ICrypto GetEncryptor(string method, string password) | |||
| { | |||
| if (string.IsNullOrEmpty(method)) | |||
| { | |||
| // todo | |||
| //method = IoCManager.Container.Resolve<IDefaultCrypto>().GetDefaultMethod(); | |||
| } | |||
| method = method.ToLowerInvariant(); | |||
| bool ok = _registeredEncryptors.TryGetValue(method, out Type t); | |||
| if (!ok) | |||
| { | |||
| t = _registeredEncryptors[DefaultCipher]; | |||
| } | |||
| ConstructorInfo c = t?.GetConstructor(ConstructorTypes) ?? | |||
| throw new TypeLoadException("can't load constructor"); | |||
| if (c == null) throw new System.Exception("Invalid ctor"); | |||
| ICrypto result = (ICrypto)c.Invoke(new object[] { method, password }); | |||
| return result; | |||
| } | |||
| public static string DumpRegisteredEncryptor() | |||
| { | |||
| var sb = new StringBuilder(); | |||
| sb.Append(Environment.NewLine); | |||
| sb.AppendLine("-------------------------"); | |||
| sb.AppendLine("Registered Encryptor Info"); | |||
| foreach (var encryptor in _registeredEncryptors) | |||
| { | |||
| sb.AppendLine($"{ciphers[encryptor.Key].ToString(true)} => {encryptor.Value.Name}"); | |||
| } | |||
| // use ----- instead of =======, so when user paste it to Github, it won't became title | |||
| sb.AppendLine("-------------------------"); | |||
| return sb.ToString(); | |||
| } | |||
| public static CipherInfo GetCipherInfo(string name) | |||
| { | |||
| // TODO: Replace cipher when required not exist | |||
| return ciphers[name]; | |||
| } | |||
| public static IEnumerable<CipherInfo> ListAvaliableCiphers() | |||
| { | |||
| return ciphers.Values; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,17 +1,17 @@ | |||
| namespace Shadowsocks.Encryption.Exception | |||
| { | |||
| public class CryptoErrorException : System.Exception | |||
| { | |||
| public CryptoErrorException() | |||
| { | |||
| } | |||
| public CryptoErrorException(string msg) : base(msg) | |||
| { | |||
| } | |||
| public CryptoErrorException(string message, System.Exception innerException) : base(message, innerException) | |||
| { | |||
| } | |||
| } | |||
| } | |||
| namespace Shadowsocks.Crypto.Exception | |||
| { | |||
| public class CryptoErrorException : System.Exception | |||
| { | |||
| public CryptoErrorException() | |||
| { | |||
| } | |||
| public CryptoErrorException(string msg) : base(msg) | |||
| { | |||
| } | |||
| public CryptoErrorException(string message, System.Exception innerException) : base(message, innerException) | |||
| { | |||
| } | |||
| } | |||
| } | |||
| @@ -1,14 +1,14 @@ | |||
| using System; | |||
| namespace Shadowsocks.Encryption | |||
| { | |||
| public interface IEncryptor | |||
| { | |||
| /* length == -1 means not used */ | |||
| int AddressBufferLength { set; get; } | |||
| int Encrypt(ReadOnlySpan<byte> plain, Span<byte> cipher); | |||
| int Decrypt(Span<byte> plain, ReadOnlySpan<byte> cipher); | |||
| int EncryptUDP(ReadOnlySpan<byte> plain, Span<byte> cipher); | |||
| int DecryptUDP(Span<byte> plain, ReadOnlySpan<byte> cipher); | |||
| } | |||
| } | |||
| using System; | |||
| namespace Shadowsocks.Crypto | |||
| { | |||
| public interface ICrypto | |||
| { | |||
| /* length == -1 means not used */ | |||
| int AddressBufferLength { set; get; } | |||
| int Encrypt(ReadOnlySpan<byte> plain, Span<byte> cipher); | |||
| int Decrypt(Span<byte> plain, ReadOnlySpan<byte> cipher); | |||
| int EncryptUDP(ReadOnlySpan<byte> plain, Span<byte> cipher); | |||
| int DecryptUDP(Span<byte> plain, ReadOnlySpan<byte> cipher); | |||
| } | |||
| } | |||
| @@ -1,50 +1,50 @@ | |||
| using System; | |||
| using System.Security.Cryptography; | |||
| namespace Shadowsocks.Encryption | |||
| { | |||
| public static class RNG | |||
| { | |||
| private static RNGCryptoServiceProvider _rng = new RNGCryptoServiceProvider(); | |||
| public static void Reload() | |||
| { | |||
| _rng.Dispose(); | |||
| _rng = new RNGCryptoServiceProvider(); | |||
| } | |||
| public static void GetSpan(Span<byte> span) | |||
| { | |||
| _rng.GetBytes(span); | |||
| } | |||
| public static Span<byte> GetSpan(int length) | |||
| { | |||
| Span<byte> span = new byte[length]; | |||
| _rng.GetBytes(span); | |||
| return span; | |||
| } | |||
| public static byte[] GetBytes(int length) | |||
| { | |||
| byte[] buf = new byte[length]; | |||
| _rng.GetBytes(buf); | |||
| return buf; | |||
| } | |||
| public static void GetBytes(byte[] buf, int len) | |||
| { | |||
| try | |||
| { | |||
| _rng.GetBytes(buf, 0, len); | |||
| } | |||
| catch | |||
| { | |||
| // the backup way | |||
| byte[] tmp = new byte[len]; | |||
| _rng.GetBytes(tmp); | |||
| Buffer.BlockCopy(tmp, 0, buf, 0, len); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| using System; | |||
| using System.Security.Cryptography; | |||
| namespace Shadowsocks.Crypto | |||
| { | |||
| public static class RNG | |||
| { | |||
| private static RNGCryptoServiceProvider _rng = new RNGCryptoServiceProvider(); | |||
| public static void Reload() | |||
| { | |||
| _rng.Dispose(); | |||
| _rng = new RNGCryptoServiceProvider(); | |||
| } | |||
| public static void GetSpan(Span<byte> span) | |||
| { | |||
| _rng.GetBytes(span); | |||
| } | |||
| public static Span<byte> GetSpan(int length) | |||
| { | |||
| Span<byte> span = new byte[length]; | |||
| _rng.GetBytes(span); | |||
| return span; | |||
| } | |||
| public static byte[] GetBytes(int length) | |||
| { | |||
| byte[] buf = new byte[length]; | |||
| _rng.GetBytes(buf); | |||
| return buf; | |||
| } | |||
| public static void GetBytes(byte[] buf, int len) | |||
| { | |||
| try | |||
| { | |||
| _rng.GetBytes(buf, 0, len); | |||
| } | |||
| catch | |||
| { | |||
| // the backup way | |||
| byte[] tmp = new byte[len]; | |||
| _rng.GetBytes(tmp); | |||
| Buffer.BlockCopy(tmp, 0, buf, 0, len); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1,19 +1,19 @@ | |||
| using Org.BouncyCastle.Crypto.Engines; | |||
| using Org.BouncyCastle.Crypto.Engines; | |||
| using Org.BouncyCastle.Crypto.Modes; | |||
| using Org.BouncyCastle.Crypto.Parameters; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Runtime.CompilerServices; | |||
| namespace Shadowsocks.Encryption.Stream | |||
| namespace Shadowsocks.Crypto.Stream | |||
| { | |||
| public class StreamAesCfbBouncyCastleEncryptor : StreamEncryptor | |||
| public class StreamAesCfbBouncyCastleCrypto : StreamCrypto | |||
| { | |||
| readonly byte[] cfbBuf = new byte[MaxInputSize + 128]; | |||
| int ptr = 0; | |||
| readonly ExtendedCfbBlockCipher b; | |||
| public StreamAesCfbBouncyCastleEncryptor(string method, string password) : base(method, password) | |||
| public StreamAesCfbBouncyCastleCrypto(string method, string password) : base(method, password) | |||
| { | |||
| b = new ExtendedCfbBlockCipher(new AesEngine(), 128); | |||
| } | |||
| @@ -36,7 +36,7 @@ namespace Shadowsocks.Encryption.Stream | |||
| return cipher.Length; | |||
| } | |||
| [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)] | |||
| [MethodImpl( MethodImplOptions.AggressiveInlining)] | |||
| private void CipherUpdate(ReadOnlySpan<byte> i, Span<byte> o) | |||
| { | |||
| Span<byte> ob = new byte[o.Length + 128]; | |||
| @@ -1,11 +1,11 @@ | |||
| using System; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Runtime.CompilerServices; | |||
| using NaCl.Core; | |||
| namespace Shadowsocks.Encryption.Stream | |||
| namespace Shadowsocks.Crypto.Stream | |||
| { | |||
| public class StreamChachaNaClEncryptor : StreamEncryptor | |||
| public class StreamChachaNaClCrypto : StreamCrypto | |||
| { | |||
| const int BlockSize = 64; | |||
| @@ -22,7 +22,7 @@ namespace Shadowsocks.Encryption.Stream | |||
| int remain = 0; | |||
| // increase counter manually... | |||
| int ic = 0; | |||
| public StreamChachaNaClEncryptor(string method, string password) : base(method, password) | |||
| public StreamChachaNaClCrypto(string method, string password) : base(method, password) | |||
| { | |||
| } | |||
| @@ -36,7 +36,7 @@ namespace Shadowsocks.Encryption.Stream | |||
| return CipherUpdate(plain, cipher, true); | |||
| } | |||
| [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)] | |||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | |||
| private int CipherUpdate(ReadOnlySpan<byte> i, Span<byte> o, bool enc) | |||
| { | |||
| // about performance problem: | |||
| @@ -1,179 +1,181 @@ | |||
| using NLog; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Runtime.CompilerServices; | |||
| using System.Text; | |||
| namespace Shadowsocks.Encryption.Stream | |||
| { | |||
| public abstract class StreamEncryptor : EncryptorBase | |||
| { | |||
| private static readonly Logger logger = LogManager.GetCurrentClassLogger(); | |||
| // shared by TCP decrypt UDP encrypt and decrypt | |||
| protected static byte[] sharedBuffer = new byte[65536]; | |||
| // Is first packet | |||
| protected bool ivReady; | |||
| protected CipherFamily cipherFamily; | |||
| protected CipherInfo CipherInfo; | |||
| // long-time master key | |||
| protected static byte[] key = Array.Empty<byte>(); | |||
| protected byte[] iv = Array.Empty<byte>(); | |||
| protected int keyLen; | |||
| protected int ivLen; | |||
| public StreamEncryptor(string method, string password) | |||
| : base(method, password) | |||
| { | |||
| CipherInfo = GetCiphers()[method.ToLower()]; | |||
| cipherFamily = CipherInfo.Type; | |||
| StreamCipherParameter parameter = (StreamCipherParameter)CipherInfo.CipherParameter; | |||
| keyLen = parameter.KeySize; | |||
| ivLen = parameter.IvSize; | |||
| InitKey(password); | |||
| logger.Dump($"key {instanceId}", key, keyLen); | |||
| } | |||
| protected abstract Dictionary<string, CipherInfo> GetCiphers(); | |||
| private void InitKey(string password) | |||
| { | |||
| byte[] passbuf = Encoding.UTF8.GetBytes(password); | |||
| key ??= new byte[keyLen]; | |||
| if (key.Length != keyLen) | |||
| { | |||
| Array.Resize(ref key, keyLen); | |||
| } | |||
| LegacyDeriveKey(passbuf, key, keyLen); | |||
| } | |||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | |||
| public static void LegacyDeriveKey(byte[] password, byte[] key, int keylen) | |||
| { | |||
| byte[] result = new byte[password.Length + MD5Length]; | |||
| int i = 0; | |||
| byte[] md5sum = Array.Empty<byte>(); | |||
| while (i < keylen) | |||
| { | |||
| if (i == 0) | |||
| { | |||
| md5sum = CryptoUtils.MD5(password); | |||
| } | |||
| else | |||
| { | |||
| Array.Copy(md5sum, 0, result, 0, MD5Length); | |||
| Array.Copy(password, 0, result, MD5Length, password.Length); | |||
| md5sum = CryptoUtils.MD5(result); | |||
| } | |||
| Array.Copy(md5sum, 0, key, i, Math.Min(MD5Length, keylen - i)); | |||
| i += MD5Length; | |||
| } | |||
| } | |||
| protected virtual void InitCipher(byte[] iv, bool isEncrypt) | |||
| { | |||
| if (ivLen == 0) | |||
| { | |||
| return; | |||
| } | |||
| this.iv = new byte[ivLen]; | |||
| Array.Copy(iv, this.iv, ivLen); | |||
| } | |||
| protected abstract int CipherEncrypt(ReadOnlySpan<byte> plain, Span<byte> cipher); | |||
| protected abstract int CipherDecrypt(Span<byte> plain, ReadOnlySpan<byte> cipher); | |||
| #region TCP | |||
| [MethodImpl(MethodImplOptions.Synchronized | MethodImplOptions.AggressiveOptimization)] | |||
| public override int Encrypt(ReadOnlySpan<byte> plain, Span<byte> cipher) | |||
| { | |||
| int cipherOffset = 0; | |||
| logger.Trace($"{instanceId} encrypt TCP, generate iv: {!ivReady}"); | |||
| if (!ivReady) | |||
| { | |||
| // Generate IV | |||
| byte[] ivBytes = RNG.GetBytes(ivLen); | |||
| InitCipher(ivBytes, true); | |||
| ivBytes.CopyTo(cipher); | |||
| cipherOffset = ivLen; | |||
| cipher = cipher.Slice(cipherOffset); | |||
| ivReady = true; | |||
| } | |||
| int clen = CipherEncrypt(plain, cipher); | |||
| logger.DumpBase64($"plain {instanceId}", plain); | |||
| logger.DumpBase64($"cipher {instanceId}", cipher.Slice(0, clen)); | |||
| logger.Dump($"iv {instanceId}", iv, ivLen); | |||
| return clen + cipherOffset; | |||
| } | |||
| private int recieveCtr = 0; | |||
| [MethodImpl(MethodImplOptions.Synchronized | MethodImplOptions.AggressiveOptimization)] | |||
| public override int Decrypt(Span<byte> plain, ReadOnlySpan<byte> cipher) | |||
| { | |||
| logger.Trace($"{instanceId} decrypt TCP, read iv: {!ivReady}"); | |||
| int cipherOffset = 0; | |||
| // is first packet, need read iv | |||
| if (!ivReady) | |||
| { | |||
| // push to buffer in case of not enough data | |||
| cipher.CopyTo(sharedBuffer.AsSpan(recieveCtr)); | |||
| recieveCtr += cipher.Length; | |||
| // not enough data for read iv, return 0 byte data | |||
| if (recieveCtr <= ivLen) | |||
| { | |||
| return 0; | |||
| } | |||
| // start decryption | |||
| ivReady = true; | |||
| if (ivLen > 0) | |||
| { | |||
| // read iv | |||
| byte[] iv = sharedBuffer.AsSpan(0, ivLen).ToArray(); | |||
| InitCipher(iv, false); | |||
| } | |||
| else | |||
| { | |||
| InitCipher(Array.Empty<byte>(), false); | |||
| } | |||
| cipherOffset += ivLen; | |||
| } | |||
| // read all data from buffer | |||
| int len = CipherDecrypt(plain, cipher.Slice(cipherOffset)); | |||
| logger.DumpBase64($"cipher {instanceId}", cipher.Slice(cipherOffset)); | |||
| logger.DumpBase64($"plain {instanceId}", plain.Slice(0, len)); | |||
| logger.Dump($"iv {instanceId}", iv, ivLen); | |||
| return len; | |||
| } | |||
| #endregion | |||
| #region UDP | |||
| [MethodImpl(MethodImplOptions.Synchronized | MethodImplOptions.AggressiveOptimization)] | |||
| public override int EncryptUDP(ReadOnlySpan<byte> plain, Span<byte> cipher) | |||
| { | |||
| byte[] iv = RNG.GetBytes(ivLen); | |||
| iv.CopyTo(cipher); | |||
| InitCipher(iv, true); | |||
| return ivLen + CipherEncrypt(plain, cipher.Slice(ivLen)); | |||
| } | |||
| [MethodImpl(MethodImplOptions.Synchronized | MethodImplOptions.AggressiveOptimization)] | |||
| public override int DecryptUDP(Span<byte> plain, ReadOnlySpan<byte> cipher) | |||
| { | |||
| InitCipher(cipher.Slice(0, ivLen).ToArray(), false); | |||
| return CipherDecrypt(plain, cipher.Slice(ivLen)); | |||
| } | |||
| #endregion | |||
| } | |||
| } | |||
| using NLog; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Runtime.CompilerServices; | |||
| using System.Text; | |||
| namespace Shadowsocks.Crypto.Stream | |||
| { | |||
| public abstract class StreamCrypto : CryptoBase | |||
| { | |||
| private static readonly Logger logger = LogManager.GetCurrentClassLogger(); | |||
| // shared by TCP decrypt UDP encrypt and decrypt | |||
| protected static byte[] sharedBuffer = new byte[65536]; | |||
| // Is first packet | |||
| protected bool ivReady; | |||
| protected CipherFamily cipherFamily; | |||
| protected CipherInfo CipherInfo; | |||
| // long-time master key | |||
| protected static byte[] key = Array.Empty<byte>(); | |||
| protected byte[] iv = Array.Empty<byte>(); | |||
| protected int keyLen; | |||
| protected int ivLen; | |||
| public StreamCrypto(string method, string password) | |||
| : base(method, password) | |||
| { | |||
| CipherInfo = GetCiphers()[method.ToLower()]; | |||
| cipherFamily = CipherInfo.Type; | |||
| StreamCipherParameter parameter = (StreamCipherParameter)CipherInfo.CipherParameter; | |||
| keyLen = parameter.KeySize; | |||
| ivLen = parameter.IvSize; | |||
| InitKey(password); | |||
| logger.Dump($"key {instanceId}", key, keyLen); | |||
| } | |||
| protected abstract Dictionary<string, CipherInfo> GetCiphers(); | |||
| private void InitKey(string password) | |||
| { | |||
| byte[] passbuf = Encoding.UTF8.GetBytes(password); | |||
| key ??= new byte[keyLen]; | |||
| if (key.Length != keyLen) | |||
| { | |||
| Array.Resize(ref key, keyLen); | |||
| } | |||
| LegacyDeriveKey(passbuf, key, keyLen); | |||
| } | |||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | |||
| public static void LegacyDeriveKey(byte[] password, byte[] key, int keylen) | |||
| { | |||
| byte[] result = new byte[password.Length + MD5Length]; | |||
| int i = 0; | |||
| byte[] md5sum = Array.Empty<byte>(); | |||
| while (i < keylen) | |||
| { | |||
| if (i == 0) | |||
| { | |||
| md5sum = CryptoUtils.MD5(password); | |||
| } | |||
| else | |||
| { | |||
| Array.Copy(md5sum, 0, result, 0, MD5Length); | |||
| Array.Copy(password, 0, result, MD5Length, password.Length); | |||
| md5sum = CryptoUtils.MD5(result); | |||
| } | |||
| Array.Copy(md5sum, 0, key, i, Math.Min(MD5Length, keylen - i)); | |||
| i += MD5Length; | |||
| } | |||
| } | |||
| protected virtual void InitCipher(byte[] iv, bool isEncrypt) | |||
| { | |||
| if (ivLen == 0) | |||
| { | |||
| return; | |||
| } | |||
| this.iv = new byte[ivLen]; | |||
| Array.Copy(iv, this.iv, ivLen); | |||
| } | |||
| protected abstract int CipherEncrypt(ReadOnlySpan<byte> plain, Span<byte> cipher); | |||
| protected abstract int CipherDecrypt(Span<byte> plain, ReadOnlySpan<byte> cipher); | |||
| #region TCP | |||
| [MethodImpl(MethodImplOptions.Synchronized)] | |||
| public override int Encrypt(ReadOnlySpan<byte> plain, Span<byte> cipher) | |||
| { | |||
| int cipherOffset = 0; | |||
| logger.Trace($"{instanceId} encrypt TCP, generate iv: {!ivReady}"); | |||
| if (!ivReady) | |||
| { | |||
| // Generate IV | |||
| byte[] ivBytes = RNG.GetBytes(ivLen); | |||
| InitCipher(ivBytes, true); | |||
| ivBytes.CopyTo(cipher); | |||
| cipherOffset = ivLen; | |||
| cipher = cipher.Slice(cipherOffset); | |||
| ivReady = true; | |||
| } | |||
| int clen = CipherEncrypt(plain, cipher); | |||
| logger.DumpBase64($"plain {instanceId}", plain); | |||
| logger.DumpBase64($"cipher {instanceId}", cipher.Slice(0, clen)); | |||
| logger.Dump($"iv {instanceId}", iv, ivLen); | |||
| return clen + cipherOffset; | |||
| } | |||
| private int recieveCtr = 0; | |||
| [MethodImpl(MethodImplOptions.Synchronized)] | |||
| public override int Decrypt(Span<byte> plain, ReadOnlySpan<byte> cipher) | |||
| { | |||
| logger.Trace($"{instanceId} decrypt TCP, read iv: {!ivReady}"); | |||
| int cipherOffset = 0; | |||
| // is first packet, need read iv | |||
| if (!ivReady) | |||
| { | |||
| // push to buffer in case of not enough data | |||
| cipher.CopyTo(sharedBuffer.AsSpan(recieveCtr)); | |||
| recieveCtr += cipher.Length; | |||
| // not enough data for read iv, return 0 byte data | |||
| if (recieveCtr <= ivLen) | |||
| { | |||
| return 0; | |||
| } | |||
| // start decryption | |||
| ivReady = true; | |||
| if (ivLen > 0) | |||
| { | |||
| // read iv | |||
| byte[] iv = sharedBuffer.AsSpan(0, ivLen).ToArray(); | |||
| InitCipher(iv, false); | |||
| } | |||
| else | |||
| { | |||
| InitCipher(Array.Empty<byte>(), false); | |||
| } | |||
| cipherOffset += ivLen; | |||
| } | |||
| // read all data from buffer | |||
| int len = CipherDecrypt(plain, cipher.Slice(cipherOffset)); | |||
| logger.DumpBase64($"cipher {instanceId}", cipher.Slice(cipherOffset)); | |||
| logger.DumpBase64($"plain {instanceId}", plain.Slice(0, len)); | |||
| logger.Dump($"iv {instanceId}", iv, ivLen); | |||
| return len; | |||
| } | |||
| #endregion | |||
| #region UDP | |||
| [MethodImpl(MethodImplOptions.Synchronized)] | |||
| public override int EncryptUDP(ReadOnlySpan<byte> plain, Span<byte> cipher) | |||
| { | |||
| byte[] iv = RNG.GetBytes(ivLen); | |||
| iv.CopyTo(cipher); | |||
| InitCipher(iv, true); | |||
| return ivLen + CipherEncrypt(plain, cipher.Slice(ivLen)); | |||
| } | |||
| [MethodImpl(MethodImplOptions.Synchronized)] | |||
| public override int DecryptUDP(Span<byte> plain, ReadOnlySpan<byte> cipher) | |||
| { | |||
| InitCipher(cipher.Slice(0, ivLen).ToArray(), false); | |||
| return CipherDecrypt(plain, cipher.Slice(ivLen)); | |||
| } | |||
| #endregion | |||
| } | |||
| } | |||
| @@ -1,12 +1,12 @@ | |||
| using System; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| namespace Shadowsocks.Encryption.Stream | |||
| namespace Shadowsocks.Crypto.Stream | |||
| { | |||
| public class StreamPlainNativeEncryptor : StreamEncryptor | |||
| public class StreamPlainNativeCrypto : StreamCrypto | |||
| { | |||
| public StreamPlainNativeEncryptor(string method, string password) : base(method, password) | |||
| public StreamPlainNativeCrypto(string method, string password) : base(method, password) | |||
| { | |||
| } | |||
| @@ -1,14 +1,14 @@ | |||
| using System; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Runtime.CompilerServices; | |||
| namespace Shadowsocks.Encryption.Stream | |||
| namespace Shadowsocks.Crypto.Stream | |||
| { | |||
| public class StreamRc4NativeEncryptor : StreamEncryptor | |||
| public class StreamRc4NativeCrypto : StreamCrypto | |||
| { | |||
| byte[] realkey = new byte[256]; | |||
| byte[] sbox = new byte[256]; | |||
| public StreamRc4NativeEncryptor(string method, string password) : base(method, password) | |||
| public StreamRc4NativeCrypto(string method, string password) : base(method, password) | |||
| { | |||
| } | |||
| @@ -94,7 +94,6 @@ namespace Shadowsocks.Encryption.Stream | |||
| return s; | |||
| } | |||
| [MethodImpl(MethodImplOptions.AggressiveOptimization)] | |||
| private void RC4(Span<byte> s, Span<byte> data, int length) | |||
| { | |||
| for (int n = 0; n < length; n++) | |||
| @@ -0,0 +1,20 @@ | |||
| using Shadowsocks.Crypto.AEAD; | |||
| namespace Shadowsocks.Crypto | |||
| { | |||
| public static class TCPParameter | |||
| { | |||
| // each recv size. | |||
| public const int RecvSize = 2048; | |||
| // overhead of one chunk, reserved for AEAD ciphers | |||
| // /* two tags */ | |||
| public const int ChunkOverheadSize = 16 * 2 + AEADCrypto.ChunkLengthBytes; | |||
| // max chunk size | |||
| public const uint MaxChunkSize = AEADCrypto.ChunkLengthMask + AEADCrypto.ChunkLengthBytes + 16 * 2; | |||
| // In general, the ciphertext length, we should take overhead into account | |||
| public const int BufferSize = RecvSize + (int)MaxChunkSize + 32 /* max salt len */; | |||
| } | |||
| } | |||
| @@ -0,0 +1,18 @@ | |||
| <Project Sdk="Microsoft.NET.Sdk"> | |||
| <PropertyGroup> | |||
| <TargetFramework>netstandard2.1</TargetFramework> | |||
| <Authors>clowwindy & community 2020</Authors> | |||
| <Product>Shadowsocks Crypto</Product> | |||
| </PropertyGroup> | |||
| <ItemGroup> | |||
| <PackageReference Include="BouncyCastle.NetCore" Version="1.8.6" /> | |||
| <PackageReference Include="NaCl.Core" Version="2.0.0" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <ProjectReference Include="..\Shadowsocks.Common\Shadowsocks.Common.csproj" /> | |||
| </ItemGroup> | |||
| </Project> | |||
| @@ -1,4 +1,4 @@ | |||
| using Org.BouncyCastle.Crypto; | |||
| using Org.BouncyCastle.Crypto; | |||
| using Org.BouncyCastle.Crypto.Digests; | |||
| using Org.BouncyCastle.Crypto.Generators; | |||
| using Org.BouncyCastle.Crypto.Parameters; | |||
| @@ -6,7 +6,7 @@ using System; | |||
| using System.Security.Cryptography; | |||
| using System.Threading; | |||
| namespace Shadowsocks.Encryption | |||
| namespace Shadowsocks.Crypto | |||
| { | |||
| public static class CryptoUtils | |||
| { | |||
| @@ -14,14 +14,14 @@ namespace Shadowsocks.Encryption | |||
| public static byte[] MD5(byte[] b) | |||
| { | |||
| var hash = new byte[EncryptorBase.MD5Length]; | |||
| var hash = new byte[CryptoBase.MD5Length]; | |||
| Md5Hasher.Value.TryComputeHash(b, hash, out _); | |||
| return hash; | |||
| } | |||
| // currently useless, just keep api same | |||
| public static Span<byte> MD5(Span<byte> span) | |||
| { | |||
| Span<byte> hash = new byte[EncryptorBase.MD5Length]; | |||
| Span<byte> hash = new byte[CryptoBase.MD5Length]; | |||
| Md5Hasher.Value.TryComputeHash(span, hash, out _); | |||
| return hash; | |||
| } | |||
| @@ -0,0 +1,15 @@ | |||
| <Application x:Class="Shadowsocks.WPF.App" | |||
| xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |||
| xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |||
| xmlns:local="clr-namespace:Shadowsocks.WPF" | |||
| xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes" | |||
| StartupUri="Views/MainWindow.xaml"> | |||
| <Application.Resources> | |||
| <ResourceDictionary> | |||
| <ResourceDictionary.MergedDictionaries> | |||
| <md:BundledTheme BaseTheme="Light" PrimaryColor="DeepPurple" SecondaryColor="Lime" /> | |||
| <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" /> | |||
| </ResourceDictionary.MergedDictionaries> | |||
| </ResourceDictionary> | |||
| </Application.Resources> | |||
| </Application> | |||
| @@ -0,0 +1,20 @@ | |||
| using ReactiveUI; | |||
| using Splat; | |||
| using System.Reflection; | |||
| using System.Windows; | |||
| namespace Shadowsocks.WPF | |||
| { | |||
| /// <summary> | |||
| /// Interaction logic for App.xaml | |||
| /// </summary> | |||
| public partial class App : Application | |||
| { | |||
| public App() | |||
| { | |||
| Locator.CurrentMutable.RegisterViewsForViewModels(Assembly.GetCallingAssembly()); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,10 @@ | |||
| using System.Windows; | |||
| [assembly: ThemeInfo( | |||
| ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located | |||
| //(used if a resource is not found in the page, | |||
| // or application resource dictionaries) | |||
| ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located | |||
| //(used if a resource is not found in the page, | |||
| // app, or any theme specific resource dictionaries) | |||
| )] | |||
| @@ -0,0 +1,3 @@ | |||
| <Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> | |||
| <ReactiveUI /> | |||
| </Weavers> | |||
| @@ -0,0 +1,26 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> | |||
| <!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> | |||
| <xs:element name="Weavers"> | |||
| <xs:complexType> | |||
| <xs:all> | |||
| <xs:element name="ReactiveUI" minOccurs="0" maxOccurs="1" type="xs:anyType" /> | |||
| </xs:all> | |||
| <xs:attribute name="VerifyAssembly" type="xs:boolean"> | |||
| <xs:annotation> | |||
| <xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> | |||
| </xs:annotation> | |||
| </xs:attribute> | |||
| <xs:attribute name="VerifyIgnoreCodes" type="xs:string"> | |||
| <xs:annotation> | |||
| <xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> | |||
| </xs:annotation> | |||
| </xs:attribute> | |||
| <xs:attribute name="GenerateXsd" type="xs:boolean"> | |||
| <xs:annotation> | |||
| <xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> | |||
| </xs:annotation> | |||
| </xs:attribute> | |||
| </xs:complexType> | |||
| </xs:element> | |||
| </xs:schema> | |||
| @@ -0,0 +1,15 @@ | |||
| using Shadowsocks.Common.Model; | |||
| using System.Reflection; | |||
| using WPFLocalizeExtension.Extensions; | |||
| namespace Shadowsocks.WPF.Localization | |||
| { | |||
| public class LocalizationProvider : ILocalizationProvider | |||
| { | |||
| private static readonly string CallingAssemblyName = Assembly.GetCallingAssembly().GetName().Name; | |||
| public T GetLocalizedValue<T>(string key) => LocExtension.GetLocalizedValue<T>($"{CallingAssemblyName}:Strings:{key}"); | |||
| } | |||
| } | |||
| @@ -8,7 +8,7 @@ | |||
| // </auto-generated> | |||
| //------------------------------------------------------------------------------ | |||
| namespace Shadowsocks.Localization { | |||
| namespace Shadowsocks.WPF.Localization { | |||
| using System; | |||
| @@ -1,189 +1,189 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <root> | |||
| <!-- | |||
| Microsoft ResX Schema | |||
| Version 2.0 | |||
| The primary goals of this format is to allow a simple XML format | |||
| that is mostly human readable. The generation and parsing of the | |||
| various data types are done through the TypeConverter classes | |||
| associated with the data types. | |||
| Example: | |||
| ... ado.net/XML headers & schema ... | |||
| <resheader name="resmimetype">text/microsoft-resx</resheader> | |||
| <resheader name="version">2.0</resheader> | |||
| <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> | |||
| <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> | |||
| <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> | |||
| <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> | |||
| <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> | |||
| <value>[base64 mime encoded serialized .NET Framework object]</value> | |||
| </data> | |||
| <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> | |||
| <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> | |||
| <comment>This is a comment</comment> | |||
| </data> | |||
| There are any number of "resheader" rows that contain simple | |||
| name/value pairs. | |||
| Each data row contains a name, and value. The row also contains a | |||
| type or mimetype. Type corresponds to a .NET class that support | |||
| text/value conversion through the TypeConverter architecture. | |||
| Classes that don't support this are serialized and stored with the | |||
| mimetype set. | |||
| The mimetype is used for serialized objects, and tells the | |||
| ResXResourceReader how to depersist the object. This is currently not | |||
| extensible. For a given mimetype the value must be set accordingly: | |||
| Note - application/x-microsoft.net.object.binary.base64 is the format | |||
| that the ResXResourceWriter will generate, however the reader can | |||
| read any of the formats listed below. | |||
| mimetype: application/x-microsoft.net.object.binary.base64 | |||
| value : The object must be serialized with | |||
| : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter | |||
| : and then encoded with base64 encoding. | |||
| mimetype: application/x-microsoft.net.object.soap.base64 | |||
| value : The object must be serialized with | |||
| : System.Runtime.Serialization.Formatters.Soap.SoapFormatter | |||
| : and then encoded with base64 encoding. | |||
| mimetype: application/x-microsoft.net.object.bytearray.base64 | |||
| value : The object must be serialized into a byte array | |||
| : using a System.ComponentModel.TypeConverter | |||
| : and then encoded with base64 encoding. | |||
| --> | |||
| <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> | |||
| <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> | |||
| <xsd:element name="root" msdata:IsDataSet="true"> | |||
| <xsd:complexType> | |||
| <xsd:choice maxOccurs="unbounded"> | |||
| <xsd:element name="metadata"> | |||
| <xsd:complexType> | |||
| <xsd:sequence> | |||
| <xsd:element name="value" type="xsd:string" minOccurs="0" /> | |||
| </xsd:sequence> | |||
| <xsd:attribute name="name" use="required" type="xsd:string" /> | |||
| <xsd:attribute name="type" type="xsd:string" /> | |||
| <xsd:attribute name="mimetype" type="xsd:string" /> | |||
| <xsd:attribute ref="xml:space" /> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| <xsd:element name="assembly"> | |||
| <xsd:complexType> | |||
| <xsd:attribute name="alias" type="xsd:string" /> | |||
| <xsd:attribute name="name" type="xsd:string" /> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| <xsd:element name="data"> | |||
| <xsd:complexType> | |||
| <xsd:sequence> | |||
| <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | |||
| <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> | |||
| </xsd:sequence> | |||
| <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> | |||
| <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> | |||
| <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> | |||
| <xsd:attribute ref="xml:space" /> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| <xsd:element name="resheader"> | |||
| <xsd:complexType> | |||
| <xsd:sequence> | |||
| <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | |||
| </xsd:sequence> | |||
| <xsd:attribute name="name" type="xsd:string" use="required" /> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| </xsd:choice> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| </xsd:schema> | |||
| <resheader name="resmimetype"> | |||
| <value>text/microsoft-resx</value> | |||
| </resheader> | |||
| <resheader name="version"> | |||
| <value>2.0</value> | |||
| </resheader> | |||
| <resheader name="reader"> | |||
| <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
| </resheader> | |||
| <resheader name="writer"> | |||
| <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
| </resheader> | |||
| <data name="Password" xml:space="preserve"> | |||
| <value>密碼</value> | |||
| </data> | |||
| <data name="Port" xml:space="preserve"> | |||
| <value>Port</value> | |||
| </data> | |||
| <data name="Type" xml:space="preserve"> | |||
| <value>類型</value> | |||
| </data> | |||
| <data name="Address" xml:space="preserve"> | |||
| <value>位址</value> | |||
| </data> | |||
| <data name="Timeout" xml:space="preserve"> | |||
| <value>逾時 (秒)</value> | |||
| </data> | |||
| <data name="cancelButton_Content" xml:space="preserve"> | |||
| <value>取消</value> | |||
| </data> | |||
| <data name="okButton_Content" xml:space="preserve"> | |||
| <value>確定</value> | |||
| </data> | |||
| <data name="ToggleSystemProxy" xml:space="preserve"> | |||
| <value>切換系統 Proxy 狀態</value> | |||
| </data> | |||
| <data name="ToggleProxyMode" xml:space="preserve"> | |||
| <value>切換系統 Proxy 模式</value> | |||
| </data> | |||
| <data name="AllowClientsFromLAN" xml:space="preserve"> | |||
| <value>切換區域網路共用</value> | |||
| </data> | |||
| <data name="OpenLogsWindow" xml:space="preserve"> | |||
| <value>顯示記錄檔</value> | |||
| </data> | |||
| <data name="SwitchToPreviousServer" xml:space="preserve"> | |||
| <value>切換上一個伺服器</value> | |||
| </data> | |||
| <data name="SwitchToNextServer" xml:space="preserve"> | |||
| <value>切換下一個伺服器</value> | |||
| </data> | |||
| <data name="RegisterHotkeysAtStartup" xml:space="preserve"> | |||
| <value>註冊所有快速鍵</value> | |||
| </data> | |||
| <data name="registerAllButton_Content" xml:space="preserve"> | |||
| <value>啟動時註冊快速鍵</value> | |||
| </data> | |||
| <data name="updateButton_Content" xml:space="preserve"> | |||
| <value>更新</value> | |||
| </data> | |||
| <data name="updateAllButton_Content" xml:space="preserve"> | |||
| <value>全部更新</value> | |||
| </data> | |||
| <data name="addButton_Content" xml:space="preserve"> | |||
| <value>新增</value> | |||
| </data> | |||
| <data name="skipVersionButton_Content" xml:space="preserve"> | |||
| <value>跳過版本</value> | |||
| </data> | |||
| <data name="notNowButton_Content" xml:space="preserve"> | |||
| <value>暫不更新</value> | |||
| </data> | |||
| <data name="updatePromptTitle" xml:space="preserve"> | |||
| <value>發現可用更新</value> | |||
| </data> | |||
| <data name="copyLinkButton_Content" xml:space="preserve"> | |||
| <value>複製鏈接</value> | |||
| </data> | |||
| <data name="Copy" xml:space="preserve"> | |||
| <value>複製</value> | |||
| </data> | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <root> | |||
| <!-- | |||
| Microsoft ResX Schema | |||
| Version 2.0 | |||
| The primary goals of this format is to allow a simple XML format | |||
| that is mostly human readable. The generation and parsing of the | |||
| various data types are done through the TypeConverter classes | |||
| associated with the data types. | |||
| Example: | |||
| ... ado.net/XML headers & schema ... | |||
| <resheader name="resmimetype">text/microsoft-resx</resheader> | |||
| <resheader name="version">2.0</resheader> | |||
| <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> | |||
| <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> | |||
| <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> | |||
| <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> | |||
| <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> | |||
| <value>[base64 mime encoded serialized .NET Framework object]</value> | |||
| </data> | |||
| <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> | |||
| <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> | |||
| <comment>This is a comment</comment> | |||
| </data> | |||
| There are any number of "resheader" rows that contain simple | |||
| name/value pairs. | |||
| Each data row contains a name, and value. The row also contains a | |||
| type or mimetype. Type corresponds to a .NET class that support | |||
| text/value conversion through the TypeConverter architecture. | |||
| Classes that don't support this are serialized and stored with the | |||
| mimetype set. | |||
| The mimetype is used for serialized objects, and tells the | |||
| ResXResourceReader how to depersist the object. This is currently not | |||
| extensible. For a given mimetype the value must be set accordingly: | |||
| Note - application/x-microsoft.net.object.binary.base64 is the format | |||
| that the ResXResourceWriter will generate, however the reader can | |||
| read any of the formats listed below. | |||
| mimetype: application/x-microsoft.net.object.binary.base64 | |||
| value : The object must be serialized with | |||
| : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter | |||
| : and then encoded with base64 encoding. | |||
| mimetype: application/x-microsoft.net.object.soap.base64 | |||
| value : The object must be serialized with | |||
| : System.Runtime.Serialization.Formatters.Soap.SoapFormatter | |||
| : and then encoded with base64 encoding. | |||
| mimetype: application/x-microsoft.net.object.bytearray.base64 | |||
| value : The object must be serialized into a byte array | |||
| : using a System.ComponentModel.TypeConverter | |||
| : and then encoded with base64 encoding. | |||
| --> | |||
| <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> | |||
| <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> | |||
| <xsd:element name="root" msdata:IsDataSet="true"> | |||
| <xsd:complexType> | |||
| <xsd:choice maxOccurs="unbounded"> | |||
| <xsd:element name="metadata"> | |||
| <xsd:complexType> | |||
| <xsd:sequence> | |||
| <xsd:element name="value" type="xsd:string" minOccurs="0" /> | |||
| </xsd:sequence> | |||
| <xsd:attribute name="name" use="required" type="xsd:string" /> | |||
| <xsd:attribute name="type" type="xsd:string" /> | |||
| <xsd:attribute name="mimetype" type="xsd:string" /> | |||
| <xsd:attribute ref="xml:space" /> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| <xsd:element name="assembly"> | |||
| <xsd:complexType> | |||
| <xsd:attribute name="alias" type="xsd:string" /> | |||
| <xsd:attribute name="name" type="xsd:string" /> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| <xsd:element name="data"> | |||
| <xsd:complexType> | |||
| <xsd:sequence> | |||
| <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | |||
| <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> | |||
| </xsd:sequence> | |||
| <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> | |||
| <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> | |||
| <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> | |||
| <xsd:attribute ref="xml:space" /> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| <xsd:element name="resheader"> | |||
| <xsd:complexType> | |||
| <xsd:sequence> | |||
| <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | |||
| </xsd:sequence> | |||
| <xsd:attribute name="name" type="xsd:string" use="required" /> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| </xsd:choice> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| </xsd:schema> | |||
| <resheader name="resmimetype"> | |||
| <value>text/microsoft-resx</value> | |||
| </resheader> | |||
| <resheader name="version"> | |||
| <value>2.0</value> | |||
| </resheader> | |||
| <resheader name="reader"> | |||
| <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
| </resheader> | |||
| <resheader name="writer"> | |||
| <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
| </resheader> | |||
| <data name="Password" xml:space="preserve"> | |||
| <value>密碼</value> | |||
| </data> | |||
| <data name="Port" xml:space="preserve"> | |||
| <value>Port</value> | |||
| </data> | |||
| <data name="Type" xml:space="preserve"> | |||
| <value>類型</value> | |||
| </data> | |||
| <data name="Address" xml:space="preserve"> | |||
| <value>位址</value> | |||
| </data> | |||
| <data name="Timeout" xml:space="preserve"> | |||
| <value>逾時 (秒)</value> | |||
| </data> | |||
| <data name="cancelButton_Content" xml:space="preserve"> | |||
| <value>取消</value> | |||
| </data> | |||
| <data name="okButton_Content" xml:space="preserve"> | |||
| <value>確定</value> | |||
| </data> | |||
| <data name="ToggleSystemProxy" xml:space="preserve"> | |||
| <value>切換系統 Proxy 狀態</value> | |||
| </data> | |||
| <data name="ToggleProxyMode" xml:space="preserve"> | |||
| <value>切換系統 Proxy 模式</value> | |||
| </data> | |||
| <data name="AllowClientsFromLAN" xml:space="preserve"> | |||
| <value>切換區域網路共用</value> | |||
| </data> | |||
| <data name="OpenLogsWindow" xml:space="preserve"> | |||
| <value>顯示記錄檔</value> | |||
| </data> | |||
| <data name="SwitchToPreviousServer" xml:space="preserve"> | |||
| <value>切換上一個伺服器</value> | |||
| </data> | |||
| <data name="SwitchToNextServer" xml:space="preserve"> | |||
| <value>切換下一個伺服器</value> | |||
| </data> | |||
| <data name="RegisterHotkeysAtStartup" xml:space="preserve"> | |||
| <value>註冊所有快速鍵</value> | |||
| </data> | |||
| <data name="registerAllButton_Content" xml:space="preserve"> | |||
| <value>啟動時註冊快速鍵</value> | |||
| </data> | |||
| <data name="updateButton_Content" xml:space="preserve"> | |||
| <value>更新</value> | |||
| </data> | |||
| <data name="updateAllButton_Content" xml:space="preserve"> | |||
| <value>全部更新</value> | |||
| </data> | |||
| <data name="addButton_Content" xml:space="preserve"> | |||
| <value>新增</value> | |||
| </data> | |||
| <data name="skipVersionButton_Content" xml:space="preserve"> | |||
| <value>跳過版本</value> | |||
| </data> | |||
| <data name="notNowButton_Content" xml:space="preserve"> | |||
| <value>暫不更新</value> | |||
| </data> | |||
| <data name="updatePromptTitle" xml:space="preserve"> | |||
| <value>發現可用更新</value> | |||
| </data> | |||
| <data name="copyLinkButton_Content" xml:space="preserve"> | |||
| <value>複製鏈接</value> | |||
| </data> | |||
| <data name="Copy" xml:space="preserve"> | |||
| <value>複製</value> | |||
| </data> | |||
| </root> | |||
| @@ -1,12 +1,14 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <!-- | |||
| https://go.microsoft.com/fwlink/?LinkID=208121. | |||
| --> | |||
| <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
| <PropertyGroup> | |||
| <Configuration>Release</Configuration> | |||
| <Platform>Any CPU</Platform> | |||
| <PublishDir>bin\Release\netcoreapp3.1\publish\</PublishDir> | |||
| <PublishProtocol>FileSystem</PublishProtocol> | |||
| </PropertyGroup> | |||
| --> | |||
| <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
| <PropertyGroup> | |||
| <Configuration>Debug</Configuration> | |||
| <Platform>Any CPU</Platform> | |||
| <PublishDir>bin\Release\netcoreapp3.1\publish\</PublishDir> | |||
| <PublishProtocol>FileSystem</PublishProtocol> | |||
| <TargetFramework>netcoreapp3.1</TargetFramework> | |||
| <SelfContained>false</SelfContained> | |||
| </PropertyGroup> | |||
| </Project> | |||
| @@ -6,7 +6,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121. | |||
| <PropertyGroup> | |||
| <Configuration>Release</Configuration> | |||
| <Platform>Any CPU</Platform> | |||
| <PublishDir>bin\Release\netcoreapp3.1\win-x64\publish\</PublishDir> | |||
| <PublishDir>bin\Release\netcoreapp3.1\publish\</PublishDir> | |||
| <PublishProtocol>FileSystem</PublishProtocol> | |||
| <TargetFramework>netcoreapp3.1</TargetFramework> | |||
| <RuntimeIdentifier>win-x64</RuntimeIdentifier> | |||
| @@ -6,7 +6,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121. | |||
| <PropertyGroup> | |||
| <Configuration>Release</Configuration> | |||
| <Platform>Any CPU</Platform> | |||
| <PublishDir>bin\Release\netcoreapp3.1\win-x86\publish\</PublishDir> | |||
| <PublishDir>bin\Release\netcoreapp3.1\publish\</PublishDir> | |||
| <PublishProtocol>FileSystem</PublishProtocol> | |||
| <TargetFramework>netcoreapp3.1</TargetFramework> | |||
| <RuntimeIdentifier>win-x86</RuntimeIdentifier> | |||
| @@ -1,6 +1,6 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <!-- | |||
| https://go.microsoft.com/fwlink/?LinkID=208121. | |||
| --> | |||
| <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
| </Project> | |||
| --> | |||
| <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
| </Project> | |||
| @@ -0,0 +1,133 @@ | |||
| //------------------------------------------------------------------------------ | |||
| // <auto-generated> | |||
| // 此代码由工具生成。 | |||
| // 运行时版本:4.0.30319.42000 | |||
| // | |||
| // 对此文件的更改可能会导致不正确的行为,并且如果 | |||
| // 重新生成代码,这些更改将会丢失。 | |||
| // </auto-generated> | |||
| //------------------------------------------------------------------------------ | |||
| namespace Shadowsocks.WPF { | |||
| using System; | |||
| /// <summary> | |||
| /// 一个强类型的资源类,用于查找本地化的字符串等。 | |||
| /// </summary> | |||
| // 此类是由 StronglyTypedResourceBuilder | |||
| // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 | |||
| // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen | |||
| // (以 /str 作为命令选项),或重新生成 VS 项目。 | |||
| [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] | |||
| [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] | |||
| [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] | |||
| internal class Resource { | |||
| private static global::System.Resources.ResourceManager resourceMan; | |||
| private static global::System.Globalization.CultureInfo resourceCulture; | |||
| [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] | |||
| internal Resource() { | |||
| } | |||
| /// <summary> | |||
| /// 返回此类使用的缓存的 ResourceManager 实例。 | |||
| /// </summary> | |||
| [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] | |||
| internal static global::System.Resources.ResourceManager ResourceManager { | |||
| get { | |||
| if (object.ReferenceEquals(resourceMan, null)) { | |||
| global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Shadowsocks.WPF.Resource", typeof(Resource).Assembly); | |||
| resourceMan = temp; | |||
| } | |||
| return resourceMan; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 重写当前线程的 CurrentUICulture 属性 | |||
| /// 重写当前线程的 CurrentUICulture 属性。 | |||
| /// </summary> | |||
| [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] | |||
| internal static global::System.Globalization.CultureInfo Culture { | |||
| get { | |||
| return resourceCulture; | |||
| } | |||
| set { | |||
| resourceCulture = value; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 查找 System.Byte[] 类型的本地化资源。 | |||
| /// </summary> | |||
| internal static byte[] ss128 { | |||
| get { | |||
| object obj = ResourceManager.GetObject("ss128", resourceCulture); | |||
| return ((byte[])(obj)); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 查找 System.Byte[] 类型的本地化资源。 | |||
| /// </summary> | |||
| internal static byte[] ss32 { | |||
| get { | |||
| object obj = ResourceManager.GetObject("ss32", resourceCulture); | |||
| return ((byte[])(obj)); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 查找 System.Drawing.Bitmap 类型的本地化资源。 | |||
| /// </summary> | |||
| internal static System.Drawing.Bitmap ss32Fill { | |||
| get { | |||
| object obj = ResourceManager.GetObject("ss32Fill", resourceCulture); | |||
| return ((System.Drawing.Bitmap)(obj)); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 查找 System.Drawing.Bitmap 类型的本地化资源。 | |||
| /// </summary> | |||
| internal static System.Drawing.Bitmap ss32In { | |||
| get { | |||
| object obj = ResourceManager.GetObject("ss32In", resourceCulture); | |||
| return ((System.Drawing.Bitmap)(obj)); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 查找 System.Drawing.Bitmap 类型的本地化资源。 | |||
| /// </summary> | |||
| internal static System.Drawing.Bitmap ss32Out { | |||
| get { | |||
| object obj = ResourceManager.GetObject("ss32Out", resourceCulture); | |||
| return ((System.Drawing.Bitmap)(obj)); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 查找 System.Drawing.Bitmap 类型的本地化资源。 | |||
| /// </summary> | |||
| internal static System.Drawing.Bitmap ss32Outline { | |||
| get { | |||
| object obj = ResourceManager.GetObject("ss32Outline", resourceCulture); | |||
| return ((System.Drawing.Bitmap)(obj)); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 查找 System.Drawing.Bitmap 类型的本地化资源。 | |||
| /// </summary> | |||
| internal static System.Drawing.Bitmap ssw128 { | |||
| get { | |||
| object obj = ResourceManager.GetObject("ssw128", resourceCulture); | |||
| return ((System.Drawing.Bitmap)(obj)); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1,157 +1,142 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <root> | |||
| <!-- | |||
| Microsoft ResX Schema | |||
| Version 2.0 | |||
| The primary goals of this format is to allow a simple XML format | |||
| that is mostly human readable. The generation and parsing of the | |||
| various data types are done through the TypeConverter classes | |||
| associated with the data types. | |||
| Example: | |||
| ... ado.net/XML headers & schema ... | |||
| <resheader name="resmimetype">text/microsoft-resx</resheader> | |||
| <resheader name="version">2.0</resheader> | |||
| <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> | |||
| <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> | |||
| <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> | |||
| <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> | |||
| <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> | |||
| <value>[base64 mime encoded serialized .NET Framework object]</value> | |||
| </data> | |||
| <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> | |||
| <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> | |||
| <comment>This is a comment</comment> | |||
| </data> | |||
| There are any number of "resheader" rows that contain simple | |||
| name/value pairs. | |||
| Each data row contains a name, and value. The row also contains a | |||
| type or mimetype. Type corresponds to a .NET class that support | |||
| text/value conversion through the TypeConverter architecture. | |||
| Classes that don't support this are serialized and stored with the | |||
| mimetype set. | |||
| The mimetype is used for serialized objects, and tells the | |||
| ResXResourceReader how to depersist the object. This is currently not | |||
| extensible. For a given mimetype the value must be set accordingly: | |||
| Note - application/x-microsoft.net.object.binary.base64 is the format | |||
| that the ResXResourceWriter will generate, however the reader can | |||
| read any of the formats listed below. | |||
| mimetype: application/x-microsoft.net.object.binary.base64 | |||
| value : The object must be serialized with | |||
| : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter | |||
| : and then encoded with base64 encoding. | |||
| mimetype: application/x-microsoft.net.object.soap.base64 | |||
| value : The object must be serialized with | |||
| : System.Runtime.Serialization.Formatters.Soap.SoapFormatter | |||
| : and then encoded with base64 encoding. | |||
| mimetype: application/x-microsoft.net.object.bytearray.base64 | |||
| value : The object must be serialized into a byte array | |||
| : using a System.ComponentModel.TypeConverter | |||
| : and then encoded with base64 encoding. | |||
| --> | |||
| <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> | |||
| <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> | |||
| <xsd:element name="root" msdata:IsDataSet="true"> | |||
| <xsd:complexType> | |||
| <xsd:choice maxOccurs="unbounded"> | |||
| <xsd:element name="metadata"> | |||
| <xsd:complexType> | |||
| <xsd:sequence> | |||
| <xsd:element name="value" type="xsd:string" minOccurs="0" /> | |||
| </xsd:sequence> | |||
| <xsd:attribute name="name" use="required" type="xsd:string" /> | |||
| <xsd:attribute name="type" type="xsd:string" /> | |||
| <xsd:attribute name="mimetype" type="xsd:string" /> | |||
| <xsd:attribute ref="xml:space" /> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| <xsd:element name="assembly"> | |||
| <xsd:complexType> | |||
| <xsd:attribute name="alias" type="xsd:string" /> | |||
| <xsd:attribute name="name" type="xsd:string" /> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| <xsd:element name="data"> | |||
| <xsd:complexType> | |||
| <xsd:sequence> | |||
| <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | |||
| <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> | |||
| </xsd:sequence> | |||
| <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> | |||
| <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> | |||
| <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> | |||
| <xsd:attribute ref="xml:space" /> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| <xsd:element name="resheader"> | |||
| <xsd:complexType> | |||
| <xsd:sequence> | |||
| <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | |||
| </xsd:sequence> | |||
| <xsd:attribute name="name" type="xsd:string" use="required" /> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| </xsd:choice> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| </xsd:schema> | |||
| <resheader name="resmimetype"> | |||
| <value>text/microsoft-resx</value> | |||
| </resheader> | |||
| <resheader name="version"> | |||
| <value>2.0</value> | |||
| </resheader> | |||
| <resheader name="reader"> | |||
| <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
| </resheader> | |||
| <resheader name="writer"> | |||
| <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
| </resheader> | |||
| <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> | |||
| <data name="abp_js" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>..\Data\abp.js;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;gb2312</value> | |||
| </data> | |||
| <data name="dlc_dat" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>..\data\dlc.dat;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
| </data> | |||
| <data name="i18n_csv" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>..\Data\i18n.csv;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value> | |||
| </data> | |||
| <data name="NLog_config" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>..\data\nlog.config;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value> | |||
| </data> | |||
| <data name="privoxy_conf" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>..\data\privoxy_conf.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value> | |||
| </data> | |||
| <data name="privoxy_exe" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>..\data\privoxy.exe.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
| </data> | |||
| <data name="ss32Fill" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>..\Resources\ss32Fill.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> | |||
| </data> | |||
| <data name="ss32In" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>..\Resources\ss32In.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> | |||
| </data> | |||
| <data name="ss32Out" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>..\Resources\ss32Out.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> | |||
| </data> | |||
| <data name="ss32Outline" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>..\Resources\ss32Outline.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> | |||
| </data> | |||
| <data name="ssw128" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>..\Resources\ssw128.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> | |||
| </data> | |||
| <data name="user_rule" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>..\data\user-rule.txt;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value> | |||
| </data> | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <root> | |||
| <!-- | |||
| Microsoft ResX Schema | |||
| Version 2.0 | |||
| The primary goals of this format is to allow a simple XML format | |||
| that is mostly human readable. The generation and parsing of the | |||
| various data types are done through the TypeConverter classes | |||
| associated with the data types. | |||
| Example: | |||
| ... ado.net/XML headers & schema ... | |||
| <resheader name="resmimetype">text/microsoft-resx</resheader> | |||
| <resheader name="version">2.0</resheader> | |||
| <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> | |||
| <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> | |||
| <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> | |||
| <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> | |||
| <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> | |||
| <value>[base64 mime encoded serialized .NET Framework object]</value> | |||
| </data> | |||
| <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> | |||
| <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> | |||
| <comment>This is a comment</comment> | |||
| </data> | |||
| There are any number of "resheader" rows that contain simple | |||
| name/value pairs. | |||
| Each data row contains a name, and value. The row also contains a | |||
| type or mimetype. Type corresponds to a .NET class that support | |||
| text/value conversion through the TypeConverter architecture. | |||
| Classes that don't support this are serialized and stored with the | |||
| mimetype set. | |||
| The mimetype is used for serialized objects, and tells the | |||
| ResXResourceReader how to depersist the object. This is currently not | |||
| extensible. For a given mimetype the value must be set accordingly: | |||
| Note - application/x-microsoft.net.object.binary.base64 is the format | |||
| that the ResXResourceWriter will generate, however the reader can | |||
| read any of the formats listed below. | |||
| mimetype: application/x-microsoft.net.object.binary.base64 | |||
| value : The object must be serialized with | |||
| : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter | |||
| : and then encoded with base64 encoding. | |||
| mimetype: application/x-microsoft.net.object.soap.base64 | |||
| value : The object must be serialized with | |||
| : System.Runtime.Serialization.Formatters.Soap.SoapFormatter | |||
| : and then encoded with base64 encoding. | |||
| mimetype: application/x-microsoft.net.object.bytearray.base64 | |||
| value : The object must be serialized into a byte array | |||
| : using a System.ComponentModel.TypeConverter | |||
| : and then encoded with base64 encoding. | |||
| --> | |||
| <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> | |||
| <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> | |||
| <xsd:element name="root" msdata:IsDataSet="true"> | |||
| <xsd:complexType> | |||
| <xsd:choice maxOccurs="unbounded"> | |||
| <xsd:element name="metadata"> | |||
| <xsd:complexType> | |||
| <xsd:sequence> | |||
| <xsd:element name="value" type="xsd:string" minOccurs="0" /> | |||
| </xsd:sequence> | |||
| <xsd:attribute name="name" use="required" type="xsd:string" /> | |||
| <xsd:attribute name="type" type="xsd:string" /> | |||
| <xsd:attribute name="mimetype" type="xsd:string" /> | |||
| <xsd:attribute ref="xml:space" /> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| <xsd:element name="assembly"> | |||
| <xsd:complexType> | |||
| <xsd:attribute name="alias" type="xsd:string" /> | |||
| <xsd:attribute name="name" type="xsd:string" /> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| <xsd:element name="data"> | |||
| <xsd:complexType> | |||
| <xsd:sequence> | |||
| <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | |||
| <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> | |||
| </xsd:sequence> | |||
| <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> | |||
| <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> | |||
| <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> | |||
| <xsd:attribute ref="xml:space" /> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| <xsd:element name="resheader"> | |||
| <xsd:complexType> | |||
| <xsd:sequence> | |||
| <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | |||
| </xsd:sequence> | |||
| <xsd:attribute name="name" type="xsd:string" use="required" /> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| </xsd:choice> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| </xsd:schema> | |||
| <resheader name="resmimetype"> | |||
| <value>text/microsoft-resx</value> | |||
| </resheader> | |||
| <resheader name="version"> | |||
| <value>2.0</value> | |||
| </resheader> | |||
| <resheader name="reader"> | |||
| <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
| </resheader> | |||
| <resheader name="writer"> | |||
| <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
| </resheader> | |||
| <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> | |||
| <data name="ss128" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>assets\ss128.pdn;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
| </data> | |||
| <data name="ss32" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>assets\ss32.pdn;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
| </data> | |||
| <data name="ss32Fill" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>assets\ss32fill.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> | |||
| </data> | |||
| <data name="ss32In" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>assets\ss32in.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> | |||
| </data> | |||
| <data name="ss32Out" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>assets\ss32out.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> | |||
| </data> | |||
| <data name="ss32Outline" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>assets\ss32outline.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> | |||
| </data> | |||
| <data name="ssw128" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>assets\ssw128.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> | |||
| </data> | |||
| </root> | |||
| @@ -0,0 +1,70 @@ | |||
| <Project Sdk="Microsoft.NET.Sdk.WindowsDesktop"> | |||
| <PropertyGroup> | |||
| <OutputType>Exe</OutputType> | |||
| <TargetFramework>netcoreapp3.1</TargetFramework> | |||
| <UseWPF>true</UseWPF> | |||
| <Authors>clowwindy & community 2020</Authors> | |||
| <PackageId>Shadowsocks.WPF</PackageId> | |||
| <Product>Shadowsocks WPF GUI</Product> | |||
| <AssemblyVersion>5.0.0.0</AssemblyVersion> | |||
| <Version>1.0.0</Version> | |||
| <ApplicationIcon>Assets\shadowsocks.ico</ApplicationIcon> | |||
| <NoWin32Manifest>true</NoWin32Manifest> | |||
| </PropertyGroup> | |||
| <ItemGroup> | |||
| <PackageReference Include="MaterialDesignThemes" Version="3.2.0" /> | |||
| <PackageReference Include="OxyPlot.Wpf" Version="2.0.0" /> | |||
| <PackageReference Include="ReactiveUI.Events.WPF" Version="12.1.1" /> | |||
| <PackageReference Include="ReactiveUI.Fody" Version="12.1.1" /> | |||
| <PackageReference Include="ReactiveUI.Validation" Version="1.8.6" /> | |||
| <PackageReference Include="ReactiveUI.WPF" Version="12.1.1" /> | |||
| <PackageReference Include="WPFLocalizeExtension" Version="3.8.0" /> | |||
| <PackageReference Include="ZXing.Net" Version="0.16.6" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <ProjectReference Include="..\Shadowsocks\Shadowsocks.csproj" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <Resource Include="Assets\ss128.pdn" /> | |||
| <Resource Include="Assets\ss32.pdn" /> | |||
| <Resource Include="Assets\ss32Fill.png" /> | |||
| <Resource Include="Assets\ss32In.png" /> | |||
| <Resource Include="Assets\ss32Out.png" /> | |||
| <Resource Include="Assets\ss32Outline.png" /> | |||
| <Resource Include="Assets\ssw128.png" /> | |||
| <Resource Include="Assets\shadowsocks.ico" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <Compile Update="Localization\Strings.Designer.cs"> | |||
| <DesignTime>True</DesignTime> | |||
| <AutoGen>True</AutoGen> | |||
| <DependentUpon>Strings.resx</DependentUpon> | |||
| </Compile> | |||
| <Compile Update="Resource.Designer.cs"> | |||
| <DesignTime>True</DesignTime> | |||
| <AutoGen>True</AutoGen> | |||
| <DependentUpon>Resource.resx</DependentUpon> | |||
| </Compile> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <EmbeddedResource Update="Localization\Strings.resx"> | |||
| <Generator>ResXFileCodeGenerator</Generator> | |||
| <LastGenOutput>Strings.Designer.cs</LastGenOutput> | |||
| </EmbeddedResource> | |||
| <EmbeddedResource Update="Resource.resx"> | |||
| <Generator>ResXFileCodeGenerator</Generator> | |||
| <LastGenOutput>Resource.Designer.cs</LastGenOutput> | |||
| </EmbeddedResource> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <Folder Include="Resources\" /> | |||
| </ItemGroup> | |||
| </Project> | |||
| @@ -0,0 +1,21 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
| <PropertyGroup> | |||
| <_LastSelectedProfileId>D:\workspaces\repos\shadowsocks-windows\Shadowsocks.WPF\Properties\PublishProfiles\win-x64.pubxml</_LastSelectedProfileId> | |||
| </PropertyGroup> | |||
| <ItemGroup> | |||
| <ApplicationDefinition Update="App.xaml"> | |||
| <SubType>Designer</SubType> | |||
| </ApplicationDefinition> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <Compile Update="Views\MainWindow.xaml.cs"> | |||
| <SubType>Code</SubType> | |||
| </Compile> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <Page Update="Views\MainWindow.xaml"> | |||
| <SubType>Designer</SubType> | |||
| </Page> | |||
| </ItemGroup> | |||
| </Project> | |||
| @@ -9,7 +9,7 @@ using System.Linq; | |||
| using System.Reactive; | |||
| using System.Reactive.Linq; | |||
| namespace Shadowsocks.ViewModels | |||
| namespace Shadowsocks.WPF.ViewModels | |||
| { | |||
| public class ForwardProxyViewModel : ReactiveValidationObject | |||
| { | |||
| @@ -7,7 +7,7 @@ using System.Reactive; | |||
| using System.Text; | |||
| using System.Windows.Input; | |||
| namespace Shadowsocks.ViewModels | |||
| namespace Shadowsocks.WPF.ViewModels | |||
| { | |||
| public class HotkeysViewModel : ReactiveObject | |||
| { | |||
| @@ -0,0 +1,14 @@ | |||
| using ReactiveUI; | |||
| using Shadowsocks.Controller.Service; | |||
| using System; | |||
| namespace Shadowsocks.WPF.ViewModels | |||
| { | |||
| public class MainWindowViewModel : ReactiveObject | |||
| { | |||
| public MainWindowViewModel() | |||
| { | |||
| } | |||
| } | |||
| } | |||
| @@ -15,7 +15,7 @@ using System.Reactive.Linq; | |||
| using System.Text; | |||
| using System.Windows; | |||
| namespace Shadowsocks.ViewModels | |||
| namespace Shadowsocks.WPF.ViewModels | |||
| { | |||
| public class OnlineConfigViewModel : ReactiveValidationObject | |||
| { | |||
| @@ -10,7 +10,7 @@ using System.Reactive; | |||
| using System.Windows; | |||
| using System.Windows.Media.Imaging; | |||
| namespace Shadowsocks.ViewModels | |||
| namespace Shadowsocks.WPF.ViewModels | |||
| { | |||
| public class ServerSharingViewModel : ReactiveObject | |||
| { | |||
| @@ -3,7 +3,7 @@ using ReactiveUI; | |||
| using Shadowsocks.Controller; | |||
| using System.Reactive; | |||
| namespace Shadowsocks.ViewModels | |||
| namespace Shadowsocks.WPF.ViewModels | |||
| { | |||
| public class VersionUpdatePromptViewModel : ReactiveObject | |||
| { | |||
| @@ -1,12 +1,12 @@ | |||
| <reactiveui:ReactiveUserControl | |||
| x:Class="Shadowsocks.Views.ForwardProxyView" | |||
| x:Class="Shadowsocks.WPF.Views.ForwardProxyView" | |||
| x:TypeArguments="vms:ForwardProxyViewModel" | |||
| xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |||
| xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |||
| xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | |||
| xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | |||
| xmlns:local="clr-namespace:Shadowsocks.Views" | |||
| xmlns:vms="clr-namespace:Shadowsocks.ViewModels" | |||
| xmlns:local="clr-namespace:Shadowsocks.WPF.Views" | |||
| xmlns:vms="clr-namespace:Shadowsocks.WPF.ViewModels" | |||
| xmlns:reactiveui="http://reactiveui.net" | |||
| xmlns:lex="http://wpflocalizeextension.codeplex.com" | |||
| lex:LocalizeDictionary.DesignCulture="en" | |||
| @@ -1,8 +1,8 @@ | |||
| using ReactiveUI; | |||
| using Shadowsocks.ViewModels; | |||
| using Shadowsocks.WPF.ViewModels; | |||
| using System.Reactive.Disposables; | |||
| namespace Shadowsocks.Views | |||
| namespace Shadowsocks.WPF.Views | |||
| { | |||
| /// <summary> | |||
| /// Interaction logic for ForwardProxyView.xaml | |||
| @@ -1,12 +1,12 @@ | |||
| <reactiveui:ReactiveUserControl | |||
| x:Class="Shadowsocks.Views.HotkeysView" | |||
| x:Class="Shadowsocks.WPF.Views.HotkeysView" | |||
| x:TypeArguments="vms:HotkeysViewModel" | |||
| xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |||
| xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |||
| xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | |||
| xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | |||
| xmlns:local="clr-namespace:Shadowsocks.Views" | |||
| xmlns:vms="clr-namespace:Shadowsocks.ViewModels" | |||
| xmlns:local="clr-namespace:Shadowsocks.WPF.Views" | |||
| xmlns:vms="clr-namespace:Shadowsocks.WPF.ViewModels" | |||
| xmlns:reactiveui="http://reactiveui.net" | |||
| xmlns:lex="http://wpflocalizeextension.codeplex.com" | |||
| lex:LocalizeDictionary.DesignCulture="en" | |||
| @@ -1,5 +1,5 @@ | |||
| using ReactiveUI; | |||
| using Shadowsocks.ViewModels; | |||
| using Shadowsocks.WPF.ViewModels; | |||
| using System; | |||
| using System.Reactive.Disposables; | |||
| using System.Windows; | |||
| @@ -11,7 +11,7 @@ using System.Windows.Media; | |||
| using System.Windows.Media.Imaging; | |||
| using System.Windows.Navigation; | |||
| namespace Shadowsocks.Views | |||
| namespace Shadowsocks.WPF.Views | |||
| { | |||
| /// <summary> | |||
| /// Interaction logic for HotkeysView.xaml | |||
| @@ -0,0 +1,21 @@ | |||
| <reactiveui:ReactiveWindow x:Class="Shadowsocks.WPF.Views.MainWindow" | |||
| xmlns:reactiveui="http://reactiveui.net" | |||
| xmlns:vm="clr-namespace:Shadowsocks.WPF.ViewModels" | |||
| x:TypeArguments="vm:MainWindowViewModel" | |||
| xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |||
| xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |||
| xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | |||
| xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | |||
| xmlns:local="clr-namespace:Shadowsocks.WPF" | |||
| xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes" | |||
| mc:Ignorable="d" | |||
| Title="Shadowsocks" Width="800" Height="600" | |||
| TextElement.Foreground="{DynamicResource MaterialDesignBody}" | |||
| TextElement.FontWeight="Regular" | |||
| TextElement.FontSize="13" | |||
| TextOptions.TextFormattingMode="Ideal" | |||
| TextOptions.TextRenderingMode="Auto" | |||
| Background="{DynamicResource MaterialDesignPaper}" | |||
| FontFamily="{DynamicResource MaterialDesignFont}"> | |||
| </reactiveui:ReactiveWindow> | |||
| @@ -0,0 +1,17 @@ | |||
| using ReactiveUI; | |||
| using Shadowsocks.WPF.ViewModels; | |||
| namespace Shadowsocks.WPF.Views | |||
| { | |||
| /// <summary> | |||
| /// Interaction logic for MainWindow.xaml | |||
| /// </summary> | |||
| public partial class MainWindow : ReactiveWindow<MainWindowViewModel> | |||
| { | |||
| public MainWindow() | |||
| { | |||
| InitializeComponent(); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,12 +1,12 @@ | |||
| <reactiveui:ReactiveUserControl | |||
| x:Class="Shadowsocks.Views.OnlineConfigView" | |||
| x:Class="Shadowsocks.WPF.Views.OnlineConfigView" | |||
| x:TypeArguments="vms:OnlineConfigViewModel" | |||
| xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |||
| xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |||
| xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | |||
| xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | |||
| xmlns:local="clr-namespace:Shadowsocks.Views" | |||
| xmlns:vms="clr-namespace:Shadowsocks.ViewModels" | |||
| xmlns:local="clr-namespace:Shadowsocks.WPF.Views" | |||
| xmlns:vms="clr-namespace:Shadowsocks.WPF.ViewModels" | |||
| xmlns:reactiveui="http://reactiveui.net" | |||
| xmlns:lex="http://wpflocalizeextension.codeplex.com" | |||
| lex:LocalizeDictionary.DesignCulture="en" | |||
| @@ -1,8 +1,8 @@ | |||
| using ReactiveUI; | |||
| using Shadowsocks.ViewModels; | |||
| using Shadowsocks.WPF.ViewModels; | |||
| using System.Reactive.Disposables; | |||
| namespace Shadowsocks.Views | |||
| namespace Shadowsocks.WPF.Views | |||
| { | |||
| /// <summary> | |||
| /// Interaction logic for OnlineConfigView.xaml | |||
| @@ -1,12 +1,12 @@ | |||
| <reactiveui:ReactiveUserControl | |||
| x:Class="Shadowsocks.Views.ServerSharingView" | |||
| x:Class="Shadowsocks.WPF.Views.ServerSharingView" | |||
| x:TypeArguments="vms:ServerSharingViewModel" | |||
| xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |||
| xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |||
| xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | |||
| xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | |||
| xmlns:local="clr-namespace:Shadowsocks.Views" | |||
| xmlns:vms="clr-namespace:Shadowsocks.ViewModels" | |||
| xmlns:local="clr-namespace:Shadowsocks.WPF.Views" | |||
| xmlns:vms="clr-namespace:Shadowsocks.WPF.ViewModels" | |||
| xmlns:reactiveui="http://reactiveui.net" | |||
| xmlns:lex="http://wpflocalizeextension.codeplex.com" | |||
| lex:LocalizeDictionary.DesignCulture="en" | |||
| @@ -1,9 +1,9 @@ | |||
| using ReactiveUI; | |||
| using Shadowsocks.ViewModels; | |||
| using Shadowsocks.WPF.ViewModels; | |||
| using System.Reactive.Disposables; | |||
| using System.Windows.Input; | |||
| namespace Shadowsocks.Views | |||
| namespace Shadowsocks.WPF.Views | |||
| { | |||
| /// <summary> | |||
| /// Interaction logic for ServerSharingView.xaml | |||
| @@ -1,12 +1,12 @@ | |||
| <reactiveui:ReactiveUserControl | |||
| x:Class="Shadowsocks.Views.VersionUpdatePromptView" | |||
| x:Class="Shadowsocks.WPF.Views.VersionUpdatePromptView" | |||
| x:TypeArguments="vms:VersionUpdatePromptViewModel" | |||
| xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |||
| xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |||
| xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | |||
| xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | |||
| xmlns:local="clr-namespace:Shadowsocks.Views" | |||
| xmlns:vms="clr-namespace:Shadowsocks.ViewModels" | |||
| xmlns:local="clr-namespace:Shadowsocks.WPF.Views" | |||
| xmlns:vms="clr-namespace:Shadowsocks.WPF.ViewModels" | |||
| xmlns:reactiveui="http://reactiveui.net" | |||
| xmlns:mdxam="clr-namespace:MdXaml;assembly=MdXaml" | |||
| xmlns:lex="http://wpflocalizeextension.codeplex.com" | |||
| @@ -1,9 +1,9 @@ | |||
| using Newtonsoft.Json.Linq; | |||
| using ReactiveUI; | |||
| using Shadowsocks.ViewModels; | |||
| using Shadowsocks.WPF.ViewModels; | |||
| using System.Reactive.Disposables; | |||
| namespace Shadowsocks.Views | |||
| namespace Shadowsocks.WPF.Views | |||
| { | |||
| /// <summary> | |||
| /// Interaction logic for VersionUpdatePromptView.xaml | |||
| @@ -0,0 +1,13 @@ | |||
| <?xml version="1.0" encoding="utf-8" ?> | |||
| <!-- Warning: Configuration may reset after shadowsocks upgrade. --> | |||
| <!-- If you messed it up, delete this file and Shadowsocks will create a new one. --> | |||
| <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | |||
| <targets> | |||
| <!-- This line is managed by Shadowsocks. Do not modify it unless you know what you are doing.--> | |||
| <target name="file" xsi:type="File" fileName="ss_win_temp\shadowsocks.log" writeBom="false" encoding="utf-8"/> | |||
| </targets> | |||
| <rules> | |||
| <!-- This line is managed by Shadowsocks. Do not modify it unless you know what you are doing. --> | |||
| <logger name="*" minlevel="Info" writeTo="file"/> | |||
| </rules> | |||
| </nlog> | |||
| @@ -1,8 +1,8 @@ | |||
| listen-address __PRIVOXY_BIND_IP__:__PRIVOXY_BIND_PORT__ | |||
| toggle 0 | |||
| logfile ss_privoxy.log | |||
| show-on-task-bar 0 | |||
| activity-animation 0 | |||
| forward-socks5 / __SOCKS_HOST__:__SOCKS_PORT__ . | |||
| max-client-connections 2048 | |||
| hide-console | |||
| listen-address __PRIVOXY_BIND_IP__:__PRIVOXY_BIND_PORT__ | |||
| toggle 0 | |||
| logfile ss_privoxy.log | |||
| show-on-task-bar 0 | |||
| activity-animation 0 | |||
| forward-socks5 / __SOCKS_HOST__:__SOCKS_PORT__ . | |||
| max-client-connections 2048 | |||
| hide-console | |||
| @@ -1,2 +1,2 @@ | |||
| ! Put user rules line by line in this file. | |||
| ! See https://adblockplus.org/en/filter-cheatsheet | |||
| ! Put user rules line by line in this file. | |||
| ! See https://adblockplus.org/en/filter-cheatsheet | |||
| @@ -0,0 +1,153 @@ | |||
| //------------------------------------------------------------------------------ | |||
| // <auto-generated> | |||
| // 此代码由工具生成。 | |||
| // 运行时版本:4.0.30319.42000 | |||
| // | |||
| // 对此文件的更改可能会导致不正确的行为,并且如果 | |||
| // 重新生成代码,这些更改将会丢失。 | |||
| // </auto-generated> | |||
| //------------------------------------------------------------------------------ | |||
| namespace Shadowsocks { | |||
| using System; | |||
| /// <summary> | |||
| /// 一个强类型的资源类,用于查找本地化的字符串等。 | |||
| /// </summary> | |||
| // 此类是由 StronglyTypedResourceBuilder | |||
| // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 | |||
| // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen | |||
| // (以 /str 作为命令选项),或重新生成 VS 项目。 | |||
| [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] | |||
| [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] | |||
| [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] | |||
| internal class Resource { | |||
| private static global::System.Resources.ResourceManager resourceMan; | |||
| private static global::System.Globalization.CultureInfo resourceCulture; | |||
| [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] | |||
| internal Resource() { | |||
| } | |||
| /// <summary> | |||
| /// 返回此类使用的缓存的 ResourceManager 实例。 | |||
| /// </summary> | |||
| [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] | |||
| internal static global::System.Resources.ResourceManager ResourceManager { | |||
| get { | |||
| if (object.ReferenceEquals(resourceMan, null)) { | |||
| global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Shadowsocks.Resource", typeof(Resource).Assembly); | |||
| resourceMan = temp; | |||
| } | |||
| return resourceMan; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 重写当前线程的 CurrentUICulture 属性 | |||
| /// 重写当前线程的 CurrentUICulture 属性。 | |||
| /// </summary> | |||
| [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] | |||
| internal static global::System.Globalization.CultureInfo Culture { | |||
| get { | |||
| return resourceCulture; | |||
| } | |||
| set { | |||
| resourceCulture = value; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 查找类似 /* eslint-disable */ | |||
| ///// Was generated by gfwlist2pac in precise mode | |||
| ///// https://github.com/clowwindy/gfwlist2pac | |||
| /// | |||
| ///// 2019-10-06: More 'javascript' way to interaction with main program | |||
| ///// 2019-02-08: Updated to support shadowsocks-windows user rules. | |||
| /// | |||
| ///var proxy = __PROXY__; | |||
| ///var userrules = []; | |||
| ///var rules = []; | |||
| /// | |||
| ///// convert to abp grammar | |||
| ///for (var i = 0; i < __RULES__.length; i++) { | |||
| /// var s = __RULES__[i]; | |||
| /// if (s.substring(0, 2) == "||") s += "^"; | |||
| /// rules.push(s); | |||
| ///} | |||
| /// | |||
| ///for (var i = 0; i < [字符串的其余部分被截断]"; 的本地化字符串。 | |||
| /// </summary> | |||
| internal static string ABP_JS { | |||
| get { | |||
| return ResourceManager.GetString("ABP_JS", resourceCulture); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 查找 System.Byte[] 类型的本地化资源。 | |||
| /// </summary> | |||
| internal static byte[] DLC_DAT { | |||
| get { | |||
| object obj = ResourceManager.GetObject("DLC_DAT", resourceCulture); | |||
| return ((byte[])(obj)); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 查找类似 <?xml version="1.0" encoding="utf-8" ?> | |||
| ///<!-- Warning: Configuration may reset after shadowsocks upgrade. --> | |||
| ///<!-- If you messed it up, delete this file and Shadowsocks will create a new one. --> | |||
| ///<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | |||
| /// <targets> | |||
| /// <!-- This line is managed by Shadowsocks. Do not modify it unless you know what you are doing.--> | |||
| /// <target name="file" xsi:type="File" fileName="ss_win_temp\shadowsocks [字符串的其余部分被截断]"; 的本地化字符串。 | |||
| /// </summary> | |||
| internal static string NLOG_CONFIG { | |||
| get { | |||
| return ResourceManager.GetString("NLOG_CONFIG", resourceCulture); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 查找类似 listen-address __PRIVOXY_BIND_IP__:__PRIVOXY_BIND_PORT__ | |||
| ///toggle 0 | |||
| ///logfile ss_privoxy.log | |||
| ///show-on-task-bar 0 | |||
| ///activity-animation 0 | |||
| ///forward-socks5 / __SOCKS_HOST__:__SOCKS_PORT__ . | |||
| ///max-client-connections 2048 | |||
| ///hide-console | |||
| /// 的本地化字符串。 | |||
| /// </summary> | |||
| internal static string PRIVOXY_CONF { | |||
| get { | |||
| return ResourceManager.GetString("PRIVOXY_CONF", resourceCulture); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 查找 System.Byte[] 类型的本地化资源。 | |||
| /// </summary> | |||
| internal static byte[] PRIVOXY_EXE { | |||
| get { | |||
| object obj = ResourceManager.GetObject("PRIVOXY_EXE", resourceCulture); | |||
| return ((byte[])(obj)); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 查找类似 ! Put user rules line by line in this file. | |||
| ///! See https://adblockplus.org/en/filter-cheatsheet | |||
| /// 的本地化字符串。 | |||
| /// </summary> | |||
| internal static string USER_RULE { | |||
| get { | |||
| return ResourceManager.GetString("USER_RULE", resourceCulture); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,139 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <root> | |||
| <!-- | |||
| Microsoft ResX Schema | |||
| Version 2.0 | |||
| The primary goals of this format is to allow a simple XML format | |||
| that is mostly human readable. The generation and parsing of the | |||
| various data types are done through the TypeConverter classes | |||
| associated with the data types. | |||
| Example: | |||
| ... ado.net/XML headers & schema ... | |||
| <resheader name="resmimetype">text/microsoft-resx</resheader> | |||
| <resheader name="version">2.0</resheader> | |||
| <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> | |||
| <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> | |||
| <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> | |||
| <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> | |||
| <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> | |||
| <value>[base64 mime encoded serialized .NET Framework object]</value> | |||
| </data> | |||
| <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> | |||
| <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> | |||
| <comment>This is a comment</comment> | |||
| </data> | |||
| There are any number of "resheader" rows that contain simple | |||
| name/value pairs. | |||
| Each data row contains a name, and value. The row also contains a | |||
| type or mimetype. Type corresponds to a .NET class that support | |||
| text/value conversion through the TypeConverter architecture. | |||
| Classes that don't support this are serialized and stored with the | |||
| mimetype set. | |||
| The mimetype is used for serialized objects, and tells the | |||
| ResXResourceReader how to depersist the object. This is currently not | |||
| extensible. For a given mimetype the value must be set accordingly: | |||
| Note - application/x-microsoft.net.object.binary.base64 is the format | |||
| that the ResXResourceWriter will generate, however the reader can | |||
| read any of the formats listed below. | |||
| mimetype: application/x-microsoft.net.object.binary.base64 | |||
| value : The object must be serialized with | |||
| : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter | |||
| : and then encoded with base64 encoding. | |||
| mimetype: application/x-microsoft.net.object.soap.base64 | |||
| value : The object must be serialized with | |||
| : System.Runtime.Serialization.Formatters.Soap.SoapFormatter | |||
| : and then encoded with base64 encoding. | |||
| mimetype: application/x-microsoft.net.object.bytearray.base64 | |||
| value : The object must be serialized into a byte array | |||
| : using a System.ComponentModel.TypeConverter | |||
| : and then encoded with base64 encoding. | |||
| --> | |||
| <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> | |||
| <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> | |||
| <xsd:element name="root" msdata:IsDataSet="true"> | |||
| <xsd:complexType> | |||
| <xsd:choice maxOccurs="unbounded"> | |||
| <xsd:element name="metadata"> | |||
| <xsd:complexType> | |||
| <xsd:sequence> | |||
| <xsd:element name="value" type="xsd:string" minOccurs="0" /> | |||
| </xsd:sequence> | |||
| <xsd:attribute name="name" use="required" type="xsd:string" /> | |||
| <xsd:attribute name="type" type="xsd:string" /> | |||
| <xsd:attribute name="mimetype" type="xsd:string" /> | |||
| <xsd:attribute ref="xml:space" /> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| <xsd:element name="assembly"> | |||
| <xsd:complexType> | |||
| <xsd:attribute name="alias" type="xsd:string" /> | |||
| <xsd:attribute name="name" type="xsd:string" /> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| <xsd:element name="data"> | |||
| <xsd:complexType> | |||
| <xsd:sequence> | |||
| <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | |||
| <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> | |||
| </xsd:sequence> | |||
| <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> | |||
| <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> | |||
| <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> | |||
| <xsd:attribute ref="xml:space" /> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| <xsd:element name="resheader"> | |||
| <xsd:complexType> | |||
| <xsd:sequence> | |||
| <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | |||
| </xsd:sequence> | |||
| <xsd:attribute name="name" type="xsd:string" use="required" /> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| </xsd:choice> | |||
| </xsd:complexType> | |||
| </xsd:element> | |||
| </xsd:schema> | |||
| <resheader name="resmimetype"> | |||
| <value>text/microsoft-resx</value> | |||
| </resheader> | |||
| <resheader name="version"> | |||
| <value>2.0</value> | |||
| </resheader> | |||
| <resheader name="reader"> | |||
| <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
| </resheader> | |||
| <resheader name="writer"> | |||
| <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
| </resheader> | |||
| <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> | |||
| <data name="ABP_JS" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>assets\abp.js;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;gb2312</value> | |||
| </data> | |||
| <data name="DLC_DAT" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>assets\dlc.dat;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
| </data> | |||
| <data name="NLOG_CONFIG" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>assets\nlog.config;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;gb2312</value> | |||
| </data> | |||
| <data name="PRIVOXY_CONF" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>assets\privoxy_conf.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;gb2312</value> | |||
| </data> | |||
| <data name="PRIVOXY_EXE" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>assets\privoxy.exe.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
| </data> | |||
| <data name="USER_RULE" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||
| <value>assets\user-rule.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value> | |||
| </data> | |||
| </root> | |||
| @@ -0,0 +1,31 @@ | |||
| <Project Sdk="Microsoft.NET.Sdk"> | |||
| <PropertyGroup> | |||
| <TargetFramework>netstandard2.1</TargetFramework> | |||
| <Authors>clowwindy & community 2020</Authors> | |||
| </PropertyGroup> | |||
| <ItemGroup> | |||
| <PackageReference Include="CommandLineParser" Version="2.8.0" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <ProjectReference Include="..\Shadowsocks.Crypto\Shadowsocks.Crypto.csproj" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <Compile Update="Resource.Designer.cs"> | |||
| <DesignTime>True</DesignTime> | |||
| <AutoGen>True</AutoGen> | |||
| <DependentUpon>Resource.resx</DependentUpon> | |||
| </Compile> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <EmbeddedResource Update="Resource.resx"> | |||
| <Generator>ResXFileCodeGenerator</Generator> | |||
| <LastGenOutput>Resource.Designer.cs</LastGenOutput> | |||
| </EmbeddedResource> | |||
| </ItemGroup> | |||
| </Project> | |||
| @@ -1,13 +0,0 @@ | |||
| <?xml version="1.0" encoding="utf-8" ?> | |||
| <!-- Warning: Configuration may reset after shadowsocks upgrade. --> | |||
| <!-- If you messed it up, delete this file and Shadowsocks will create a new one. --> | |||
| <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | |||
| <targets> | |||
| <!-- This line is managed by Shadowsocks. Do not modify it unless you know what you are doing.--> | |||
| <target name="file" xsi:type="File" fileName="ss_win_temp\shadowsocks.log" writeBom="false" encoding="utf-8"/> | |||
| </targets> | |||
| <rules> | |||
| <!-- This line is managed by Shadowsocks. Do not modify it unless you know what you are doing. --> | |||
| <logger name="*" minlevel="Info" writeTo="file"/> | |||
| </rules> | |||
| </nlog> | |||
| @@ -1,6 +0,0 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> | |||
| <Caseless StringComparison="Ordinal" /> | |||
| <Costura /> | |||
| <ReactiveUI /> | |||
| </Weavers> | |||
| @@ -1,113 +0,0 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> | |||
| <!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> | |||
| <xs:element name="Weavers"> | |||
| <xs:complexType> | |||
| <xs:all> | |||
| <xs:element name="ReactiveUI" minOccurs="0" maxOccurs="1" type="xs:anyType" /> | |||
| <xs:element name="Costura" minOccurs="0" maxOccurs="1"> | |||
| <xs:complexType> | |||
| <xs:all> | |||
| <xs:element minOccurs="0" maxOccurs="1" name="ExcludeAssemblies" type="xs:string"> | |||
| <xs:annotation> | |||
| <xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation> | |||
| </xs:annotation> | |||
| </xs:element> | |||
| <xs:element minOccurs="0" maxOccurs="1" name="IncludeAssemblies" type="xs:string"> | |||
| <xs:annotation> | |||
| <xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation> | |||
| </xs:annotation> | |||
| </xs:element> | |||
| <xs:element minOccurs="0" maxOccurs="1" name="Unmanaged32Assemblies" type="xs:string"> | |||
| <xs:annotation> | |||
| <xs:documentation>A list of unmanaged 32 bit assembly names to include, delimited with line breaks.</xs:documentation> | |||
| </xs:annotation> | |||
| </xs:element> | |||
| <xs:element minOccurs="0" maxOccurs="1" name="Unmanaged64Assemblies" type="xs:string"> | |||
| <xs:annotation> | |||
| <xs:documentation>A list of unmanaged 64 bit assembly names to include, delimited with line breaks.</xs:documentation> | |||
| </xs:annotation> | |||
| </xs:element> | |||
| <xs:element minOccurs="0" maxOccurs="1" name="PreloadOrder" type="xs:string"> | |||
| <xs:annotation> | |||
| <xs:documentation>The order of preloaded assemblies, delimited with line breaks.</xs:documentation> | |||
| </xs:annotation> | |||
| </xs:element> | |||
| </xs:all> | |||
| <xs:attribute name="CreateTemporaryAssemblies" type="xs:boolean"> | |||
| <xs:annotation> | |||
| <xs:documentation>This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file.</xs:documentation> | |||
| </xs:annotation> | |||
| </xs:attribute> | |||
| <xs:attribute name="IncludeDebugSymbols" type="xs:boolean"> | |||
| <xs:annotation> | |||
| <xs:documentation>Controls if .pdbs for reference assemblies are also embedded.</xs:documentation> | |||
| </xs:annotation> | |||
| </xs:attribute> | |||
| <xs:attribute name="DisableCompression" type="xs:boolean"> | |||
| <xs:annotation> | |||
| <xs:documentation>Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option.</xs:documentation> | |||
| </xs:annotation> | |||
| </xs:attribute> | |||
| <xs:attribute name="DisableCleanup" type="xs:boolean"> | |||
| <xs:annotation> | |||
| <xs:documentation>As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off.</xs:documentation> | |||
| </xs:annotation> | |||
| </xs:attribute> | |||
| <xs:attribute name="LoadAtModuleInit" type="xs:boolean"> | |||
| <xs:annotation> | |||
| <xs:documentation>Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code.</xs:documentation> | |||
| </xs:annotation> | |||
| </xs:attribute> | |||
| <xs:attribute name="IgnoreSatelliteAssemblies" type="xs:boolean"> | |||
| <xs:annotation> | |||
| <xs:documentation>Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior.</xs:documentation> | |||
| </xs:annotation> | |||
| </xs:attribute> | |||
| <xs:attribute name="ExcludeAssemblies" type="xs:string"> | |||
| <xs:annotation> | |||
| <xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation> | |||
| </xs:annotation> | |||
| </xs:attribute> | |||
| <xs:attribute name="IncludeAssemblies" type="xs:string"> | |||
| <xs:annotation> | |||
| <xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation> | |||
| </xs:annotation> | |||
| </xs:attribute> | |||
| <xs:attribute name="Unmanaged32Assemblies" type="xs:string"> | |||
| <xs:annotation> | |||
| <xs:documentation>A list of unmanaged 32 bit assembly names to include, delimited with |.</xs:documentation> | |||
| </xs:annotation> | |||
| </xs:attribute> | |||
| <xs:attribute name="Unmanaged64Assemblies" type="xs:string"> | |||
| <xs:annotation> | |||
| <xs:documentation>A list of unmanaged 64 bit assembly names to include, delimited with |.</xs:documentation> | |||
| </xs:annotation> | |||
| </xs:attribute> | |||
| <xs:attribute name="PreloadOrder" type="xs:string"> | |||
| <xs:annotation> | |||
| <xs:documentation>The order of preloaded assemblies, delimited with |.</xs:documentation> | |||
| </xs:annotation> | |||
| </xs:attribute> | |||
| </xs:complexType> | |||
| </xs:element> | |||
| <xs:element name="Caseless" minOccurs="0" maxOccurs="1" type="xs:anyType" /> | |||
| </xs:all> | |||
| <xs:attribute name="VerifyAssembly" type="xs:boolean"> | |||
| <xs:annotation> | |||
| <xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> | |||
| </xs:annotation> | |||
| </xs:attribute> | |||
| <xs:attribute name="VerifyIgnoreCodes" type="xs:string"> | |||
| <xs:annotation> | |||
| <xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> | |||
| </xs:annotation> | |||
| </xs:attribute> | |||
| <xs:attribute name="GenerateXsd" type="xs:boolean"> | |||
| <xs:annotation> | |||
| <xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> | |||
| </xs:annotation> | |||
| </xs:attribute> | |||
| </xs:complexType> | |||
| </xs:element> | |||
| </xs:schema> | |||
| @@ -1,13 +0,0 @@ | |||
| using System.Reflection; | |||
| using WPFLocalizeExtension.Extensions; | |||
| namespace Shadowsocks.Localization | |||
| { | |||
| public static class LocalizationProvider | |||
| { | |||
| public static T GetLocalizedValue<T>(string key) | |||
| { | |||
| return LocExtension.GetLocalizedValue<T>(Assembly.GetCallingAssembly().GetName().Name + ":Strings:" + key); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,244 +0,0 @@ | |||
| //------------------------------------------------------------------------------ | |||
| // <auto-generated> | |||
| // This code was generated by a tool. | |||
| // Runtime Version:4.0.30319.42000 | |||
| // | |||
| // Changes to this file may cause incorrect behavior and will be lost if | |||
| // the code is regenerated. | |||
| // </auto-generated> | |||
| //------------------------------------------------------------------------------ | |||
| namespace Shadowsocks.Properties { | |||
| using System; | |||
| /// <summary> | |||
| /// A strongly-typed resource class, for looking up localized strings, etc. | |||
| /// </summary> | |||
| // This class was auto-generated by the StronglyTypedResourceBuilder | |||
| // class via a tool like ResGen or Visual Studio. | |||
| // To add or remove a member, edit your .ResX file then rerun ResGen | |||
| // with the /str option, or rebuild your VS project. | |||
| [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] | |||
| [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] | |||
| [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] | |||
| public class Resources { | |||
| private static global::System.Resources.ResourceManager resourceMan; | |||
| private static global::System.Globalization.CultureInfo resourceCulture; | |||
| [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] | |||
| internal Resources() { | |||
| } | |||
| /// <summary> | |||
| /// Returns the cached ResourceManager instance used by this class. | |||
| /// </summary> | |||
| [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] | |||
| public static global::System.Resources.ResourceManager ResourceManager { | |||
| get { | |||
| if (object.ReferenceEquals(resourceMan, null)) { | |||
| global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Shadowsocks.Properties.Resources", typeof(Resources).Assembly); | |||
| resourceMan = temp; | |||
| } | |||
| return resourceMan; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Overrides the current thread's CurrentUICulture property for all | |||
| /// resource lookups using this strongly typed resource class. | |||
| /// </summary> | |||
| [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] | |||
| public static global::System.Globalization.CultureInfo Culture { | |||
| get { | |||
| return resourceCulture; | |||
| } | |||
| set { | |||
| resourceCulture = value; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Looks up a localized string similar to /* eslint-disable */ | |||
| ///// Was generated by gfwlist2pac in precise mode | |||
| ///// https://github.com/clowwindy/gfwlist2pac | |||
| /// | |||
| ///// 2019-10-06: More 'javascript' way to interaction with main program | |||
| ///// 2019-02-08: Updated to support shadowsocks-windows user rules. | |||
| /// | |||
| ///var proxy = __PROXY__; | |||
| ///var userrules = []; | |||
| ///var rules = []; | |||
| /// | |||
| ///// convert to abp grammar | |||
| ///for (var i = 0; i < __RULES__.length; i++) { | |||
| /// var s = __RULES__[i]; | |||
| /// if (s.substring(0, 2) == "||") s += "^"; | |||
| /// rules.push(s); | |||
| ///} | |||
| /// | |||
| ///for (var i = 0; i < [rest of string was truncated]";. | |||
| /// </summary> | |||
| public static string abp_js { | |||
| get { | |||
| return ResourceManager.GetString("abp_js", resourceCulture); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Looks up a localized resource of type System.Byte[]. | |||
| /// </summary> | |||
| public static byte[] dlc_dat { | |||
| get { | |||
| object obj = ResourceManager.GetObject("dlc_dat", resourceCulture); | |||
| return ((byte[])(obj)); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Looks up a localized string similar to en,ru-RU,zh-CN,zh-TW,ja,ko,fr | |||
| ///#Restart program to apply translation,,,,,, | |||
| ///#This is comment line,,,,,, | |||
| ///#Always keep language name at head of file,,,,,, | |||
| ///#Language name is output in log,,,,,, | |||
| ///"#You can find it by search ""Current language is:""",,,,,, | |||
| ///#Please use UTF-8 with BOM encoding so we can edit it in Excel,,,,,, | |||
| ///,,,,,, | |||
| ///Shadowsocks,Shadowsocks,Shadowsocks,Shadowsocks,Shadowsocks,Shadowsocks,Shadowsocks | |||
| ///,,,,,, | |||
| ///#Menu,,,,,, | |||
| ///,,,,,, | |||
| ///System Proxy,Системный прокси-сервер,系统代理,系統代理,システムプロキシ,시스템 프록시,P [rest of string was truncated]";. | |||
| /// </summary> | |||
| public static string i18n_csv { | |||
| get { | |||
| return ResourceManager.GetString("i18n_csv", resourceCulture); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8" ?> | |||
| ///<!-- Warning: Configuration may reset after shadowsocks upgrade. --> | |||
| ///<!-- If you messed it up, delete this file and Shadowsocks will create a new one. --> | |||
| ///<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | |||
| /// <targets> | |||
| /// <!-- This line is managed by Shadowsocks. Do not modify it unless you know what you are doing.--> | |||
| /// <target name="file" xsi:type="File" fileName="ss_win_temp\shadowsocks.log" writ [rest of string was truncated]";. | |||
| /// </summary> | |||
| public static string NLog_config { | |||
| get { | |||
| return ResourceManager.GetString("NLog_config", resourceCulture); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Looks up a localized string similar to listen-address __PRIVOXY_BIND_IP__:__PRIVOXY_BIND_PORT__ | |||
| ///toggle 0 | |||
| ///logfile ss_privoxy.log | |||
| ///show-on-task-bar 0 | |||
| ///activity-animation 0 | |||
| ///forward-socks5 / __SOCKS_HOST__:__SOCKS_PORT__ . | |||
| ///max-client-connections 2048 | |||
| ///hide-console | |||
| ///. | |||
| /// </summary> | |||
| public static string privoxy_conf { | |||
| get { | |||
| return ResourceManager.GetString("privoxy_conf", resourceCulture); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Looks up a localized resource of type System.Byte[]. | |||
| /// </summary> | |||
| public static byte[] privoxy_exe { | |||
| get { | |||
| object obj = ResourceManager.GetObject("privoxy_exe", resourceCulture); | |||
| return ((byte[])(obj)); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Looks up a localized resource of type System.Drawing.Bitmap. | |||
| /// </summary> | |||
| public static System.Drawing.Bitmap ss32Fill { | |||
| get { | |||
| object obj = ResourceManager.GetObject("ss32Fill", resourceCulture); | |||
| return ((System.Drawing.Bitmap)(obj)); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Looks up a localized resource of type System.Drawing.Bitmap. | |||
| /// </summary> | |||
| public static System.Drawing.Bitmap ss32In { | |||
| get { | |||
| object obj = ResourceManager.GetObject("ss32In", resourceCulture); | |||
| return ((System.Drawing.Bitmap)(obj)); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Looks up a localized resource of type System.Drawing.Bitmap. | |||
| /// </summary> | |||
| public static System.Drawing.Bitmap ss32Out { | |||
| get { | |||
| object obj = ResourceManager.GetObject("ss32Out", resourceCulture); | |||
| return ((System.Drawing.Bitmap)(obj)); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Looks up a localized resource of type System.Drawing.Bitmap. | |||
| /// </summary> | |||
| public static System.Drawing.Bitmap ss32Outline { | |||
| get { | |||
| object obj = ResourceManager.GetObject("ss32Outline", resourceCulture); | |||
| return ((System.Drawing.Bitmap)(obj)); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Looks up a localized resource of type System.Drawing.Bitmap. | |||
| /// </summary> | |||
| public static System.Drawing.Bitmap ssw128 { | |||
| get { | |||
| object obj = ResourceManager.GetObject("ssw128", resourceCulture); | |||
| return ((System.Drawing.Bitmap)(obj)); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Looks up a localized resource of type System.Byte[]. | |||
| /// </summary> | |||
| public static byte[] sysproxy_exe { | |||
| get { | |||
| object obj = ResourceManager.GetObject("sysproxy_exe", resourceCulture); | |||
| return ((byte[])(obj)); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Looks up a localized resource of type System.Byte[]. | |||
| /// </summary> | |||
| public static byte[] sysproxy64_exe { | |||
| get { | |||
| object obj = ResourceManager.GetObject("sysproxy64_exe", resourceCulture); | |||
| return ((byte[])(obj)); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Looks up a localized string similar to ! Put user rules line by line in this file. | |||
| ///! See https://adblockplus.org/en/filter-cheatsheet | |||
| ///. | |||
| /// </summary> | |||
| public static string user_rule { | |||
| get { | |||
| return ResourceManager.GetString("user_rule", resourceCulture); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1,86 +0,0 @@ | |||
| //------------------------------------------------------------------------------ | |||
| // <auto-generated> | |||
| // 此代码由工具生成。 | |||
| // 运行时版本:4.0.30319.42000 | |||
| // | |||
| // 对此文件的更改可能会导致不正确的行为,并且如果 | |||
| // 重新生成代码,这些更改将会丢失。 | |||
| // </auto-generated> | |||
| //------------------------------------------------------------------------------ | |||
| namespace Shadowsocks.Properties { | |||
| [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] | |||
| [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.4.0.0")] | |||
| internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { | |||
| private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); | |||
| public static Settings Default { | |||
| get { | |||
| return defaultInstance; | |||
| } | |||
| } | |||
| [global::System.Configuration.UserScopedSettingAttribute()] | |||
| [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] | |||
| [global::System.Configuration.DefaultSettingValueAttribute("600")] | |||
| public int LogViewerWidth { | |||
| get { | |||
| return ((int)(this["LogViewerWidth"])); | |||
| } | |||
| set { | |||
| this["LogViewerWidth"] = value; | |||
| } | |||
| } | |||
| [global::System.Configuration.UserScopedSettingAttribute()] | |||
| [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] | |||
| [global::System.Configuration.DefaultSettingValueAttribute("400")] | |||
| public int LogViewerHeight { | |||
| get { | |||
| return ((int)(this["LogViewerHeight"])); | |||
| } | |||
| set { | |||
| this["LogViewerHeight"] = value; | |||
| } | |||
| } | |||
| [global::System.Configuration.UserScopedSettingAttribute()] | |||
| [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] | |||
| [global::System.Configuration.DefaultSettingValueAttribute("True")] | |||
| public bool LogViewerMaximized { | |||
| get { | |||
| return ((bool)(this["LogViewerMaximized"])); | |||
| } | |||
| set { | |||
| this["LogViewerMaximized"] = value; | |||
| } | |||
| } | |||
| [global::System.Configuration.UserScopedSettingAttribute()] | |||
| [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] | |||
| [global::System.Configuration.DefaultSettingValueAttribute("0")] | |||
| public int LogViewerTop { | |||
| get { | |||
| return ((int)(this["LogViewerTop"])); | |||
| } | |||
| set { | |||
| this["LogViewerTop"] = value; | |||
| } | |||
| } | |||
| [global::System.Configuration.UserScopedSettingAttribute()] | |||
| [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] | |||
| [global::System.Configuration.DefaultSettingValueAttribute("0")] | |||
| public int LogViewerLeft { | |||
| get { | |||
| return ((int)(this["LogViewerLeft"])); | |||
| } | |||
| set { | |||
| this["LogViewerLeft"] = value; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1,21 +0,0 @@ | |||
| <?xml version='1.0' encoding='utf-8'?> | |||
| <SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="Shadowsocks.Properties" GeneratedClassName="Settings"> | |||
| <Profiles /> | |||
| <Settings> | |||
| <Setting Name="LogViewerWidth" Type="System.Int32" Scope="User"> | |||
| <Value Profile="(Default)">600</Value> | |||
| </Setting> | |||
| <Setting Name="LogViewerHeight" Type="System.Int32" Scope="User"> | |||
| <Value Profile="(Default)">400</Value> | |||
| </Setting> | |||
| <Setting Name="LogViewerMaximized" Type="System.Boolean" Scope="User"> | |||
| <Value Profile="(Default)">True</Value> | |||
| </Setting> | |||
| <Setting Name="LogViewerTop" Type="System.Int32" Scope="User"> | |||
| <Value Profile="(Default)">0</Value> | |||
| </Setting> | |||
| <Setting Name="LogViewerLeft" Type="System.Int32" Scope="User"> | |||
| <Value Profile="(Default)">0</Value> | |||
| </Setting> | |||
| </Settings> | |||
| </SettingsFile> | |||
| @@ -12,6 +12,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ShadowsocksTest", "test\Sha | |||
| EndProject | |||
| Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7BD54B24-BBD7-4DD8-99EF-DAEE6684B673}" | |||
| ProjectSection(SolutionItems) = preProject | |||
| .editorconfig = .editorconfig | |||
| .gitignore = .gitignore | |||
| appveyor.yml = appveyor.yml | |||
| appveyor.yml.obsolete = appveyor.yml.obsolete | |||
| @@ -23,6 +24,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution | |||
| README.md = README.md | |||
| EndProjectSection | |||
| EndProject | |||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shadowsocks.Common", "Shadowsocks.Common\Shadowsocks.Common.csproj", "{61AF0616-8E90-46C4-908A-E182A5001AB5}" | |||
| EndProject | |||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shadowsocks.Crypto", "Shadowsocks.Crypto\Shadowsocks.Crypto.csproj", "{AD8974F4-EFDC-4EC5-A147-54CD4934D295}" | |||
| EndProject | |||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shadowsocks", "Shadowsocks\Shadowsocks.csproj", "{85C2FC93-91F0-454F-AF0A-522FCD20827A}" | |||
| EndProject | |||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shadowsocks.WPF", "Shadowsocks.WPF\Shadowsocks.WPF.csproj", "{EA1FB2D4-B5A7-47A6-B097-2F4D29E23010}" | |||
| EndProject | |||
| Global | |||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||
| Debug|Any CPU = Debug|Any CPU | |||
| @@ -37,6 +46,22 @@ Global | |||
| {45913187-0685-4903-B250-DCEF0479CD86}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {45913187-0685-4903-B250-DCEF0479CD86}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {45913187-0685-4903-B250-DCEF0479CD86}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| {61AF0616-8E90-46C4-908A-E182A5001AB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
| {61AF0616-8E90-46C4-908A-E182A5001AB5}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {61AF0616-8E90-46C4-908A-E182A5001AB5}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {61AF0616-8E90-46C4-908A-E182A5001AB5}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| {AD8974F4-EFDC-4EC5-A147-54CD4934D295}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
| {AD8974F4-EFDC-4EC5-A147-54CD4934D295}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {AD8974F4-EFDC-4EC5-A147-54CD4934D295}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {AD8974F4-EFDC-4EC5-A147-54CD4934D295}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| {85C2FC93-91F0-454F-AF0A-522FCD20827A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
| {85C2FC93-91F0-454F-AF0A-522FCD20827A}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {85C2FC93-91F0-454F-AF0A-522FCD20827A}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {85C2FC93-91F0-454F-AF0A-522FCD20827A}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| {EA1FB2D4-B5A7-47A6-B097-2F4D29E23010}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
| {EA1FB2D4-B5A7-47A6-B097-2F4D29E23010}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {EA1FB2D4-B5A7-47A6-B097-2F4D29E23010}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {EA1FB2D4-B5A7-47A6-B097-2F4D29E23010}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| EndGlobalSection | |||
| GlobalSection(SolutionProperties) = preSolution | |||
| HideSolutionNode = FALSE | |||