- 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; | ||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Runtime.Serialization; | using System.Runtime.Serialization; | ||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace Shadowsocks.Util.SystemProxy | |||||
namespace Shadowsocks.Common.SystemProxy | |||||
{ | { | ||||
enum ProxyExceptionType | 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.Collections.Generic; | ||||
using System.Security.Cryptography; | 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; | return clen; | ||||
} | } | ||||
} | } | ||||
} | |||||
} |
@@ -1,16 +1,17 @@ | |||||
using System; | |||||
using System; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using Org.BouncyCastle.Crypto.Engines; | using Org.BouncyCastle.Crypto.Engines; | ||||
using Org.BouncyCastle.Crypto.Modes; | using Org.BouncyCastle.Crypto.Modes; | ||||
using Org.BouncyCastle.Crypto.Parameters; | using Org.BouncyCastle.Crypto.Parameters; | ||||
namespace Shadowsocks.Encryption.AEAD | |||||
namespace Shadowsocks.Crypto.AEAD | |||||
{ | { | ||||
public class AEADBouncyCastleEncryptor : AEADEncryptor | |||||
public class AEADBouncyCastleCrypto : AEADCrypto | |||||
{ | { | ||||
IAeadCipher aead; | IAeadCipher aead; | ||||
bool enc; | bool enc; | ||||
public AEADBouncyCastleEncryptor(string method, string password) : base(method, password) | |||||
public AEADBouncyCastleCrypto(string method, string password) : base(method, password) | |||||
{ | { | ||||
aead = cipherFamily switch | 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; | ||||
using System.Collections.Generic; | 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; | 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) | 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) | 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 | public enum CipherFamily | ||||
{ | { | ||||
@@ -96,7 +94,9 @@ namespace Shadowsocks.Encryption | |||||
public override string ToString() | 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) | public string ToString(bool verbose) | ||||
{ | { | ||||
@@ -108,4 +108,4 @@ namespace Shadowsocks.Encryption | |||||
return $"{Name} {StandardState} {CipherParameter}"; | 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.Modes; | ||||
using Org.BouncyCastle.Crypto.Parameters; | using Org.BouncyCastle.Crypto.Parameters; | ||||
using System; | using System; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Runtime.CompilerServices; | 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]; | readonly byte[] cfbBuf = new byte[MaxInputSize + 128]; | ||||
int ptr = 0; | int ptr = 0; | ||||
readonly ExtendedCfbBlockCipher b; | 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); | b = new ExtendedCfbBlockCipher(new AesEngine(), 128); | ||||
} | } | ||||
@@ -36,7 +36,7 @@ namespace Shadowsocks.Encryption.Stream | |||||
return cipher.Length; | return cipher.Length; | ||||
} | } | ||||
[MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)] | |||||
[MethodImpl( MethodImplOptions.AggressiveInlining)] | |||||
private void CipherUpdate(ReadOnlySpan<byte> i, Span<byte> o) | private void CipherUpdate(ReadOnlySpan<byte> i, Span<byte> o) | ||||
{ | { | ||||
Span<byte> ob = new byte[o.Length + 128]; | Span<byte> ob = new byte[o.Length + 128]; |
@@ -1,11 +1,11 @@ | |||||
using System; | |||||
using System; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Runtime.CompilerServices; | using System.Runtime.CompilerServices; | ||||
using NaCl.Core; | using NaCl.Core; | ||||
namespace Shadowsocks.Encryption.Stream | |||||
namespace Shadowsocks.Crypto.Stream | |||||
{ | { | ||||
public class StreamChachaNaClEncryptor : StreamEncryptor | |||||
public class StreamChachaNaClCrypto : StreamCrypto | |||||
{ | { | ||||
const int BlockSize = 64; | const int BlockSize = 64; | ||||
@@ -22,7 +22,7 @@ namespace Shadowsocks.Encryption.Stream | |||||
int remain = 0; | int remain = 0; | ||||
// increase counter manually... | // increase counter manually... | ||||
int ic = 0; | 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); | return CipherUpdate(plain, cipher, true); | ||||
} | } | ||||
[MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)] | |||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |||||
private int CipherUpdate(ReadOnlySpan<byte> i, Span<byte> o, bool enc) | private int CipherUpdate(ReadOnlySpan<byte> i, Span<byte> o, bool enc) | ||||
{ | { | ||||
// about performance problem: | // 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; | 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.Collections.Generic; | ||||
using System.Runtime.CompilerServices; | 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[] realkey = new byte[256]; | ||||
byte[] sbox = 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; | return s; | ||||
} | } | ||||
[MethodImpl(MethodImplOptions.AggressiveOptimization)] | |||||
private void RC4(Span<byte> s, Span<byte> data, int length) | private void RC4(Span<byte> s, Span<byte> data, int length) | ||||
{ | { | ||||
for (int n = 0; n < length; n++) | 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.Digests; | ||||
using Org.BouncyCastle.Crypto.Generators; | using Org.BouncyCastle.Crypto.Generators; | ||||
using Org.BouncyCastle.Crypto.Parameters; | using Org.BouncyCastle.Crypto.Parameters; | ||||
@@ -6,7 +6,7 @@ using System; | |||||
using System.Security.Cryptography; | using System.Security.Cryptography; | ||||
using System.Threading; | using System.Threading; | ||||
namespace Shadowsocks.Encryption | |||||
namespace Shadowsocks.Crypto | |||||
{ | { | ||||
public static class CryptoUtils | public static class CryptoUtils | ||||
{ | { | ||||
@@ -14,14 +14,14 @@ namespace Shadowsocks.Encryption | |||||
public static byte[] MD5(byte[] b) | public static byte[] MD5(byte[] b) | ||||
{ | { | ||||
var hash = new byte[EncryptorBase.MD5Length]; | |||||
var hash = new byte[CryptoBase.MD5Length]; | |||||
Md5Hasher.Value.TryComputeHash(b, hash, out _); | Md5Hasher.Value.TryComputeHash(b, hash, out _); | ||||
return hash; | return hash; | ||||
} | } | ||||
// currently useless, just keep api same | // currently useless, just keep api same | ||||
public static Span<byte> MD5(Span<byte> span) | 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 _); | Md5Hasher.Value.TryComputeHash(span, hash, out _); | ||||
return hash; | 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> | // </auto-generated> | ||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
namespace Shadowsocks.Localization { | |||||
namespace Shadowsocks.WPF.Localization { | |||||
using System; | 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> | </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. | 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> | </Project> |
@@ -6,7 +6,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121. | |||||
<PropertyGroup> | <PropertyGroup> | ||||
<Configuration>Release</Configuration> | <Configuration>Release</Configuration> | ||||
<Platform>Any CPU</Platform> | <Platform>Any CPU</Platform> | ||||
<PublishDir>bin\Release\netcoreapp3.1\win-x64\publish\</PublishDir> | |||||
<PublishDir>bin\Release\netcoreapp3.1\publish\</PublishDir> | |||||
<PublishProtocol>FileSystem</PublishProtocol> | <PublishProtocol>FileSystem</PublishProtocol> | ||||
<TargetFramework>netcoreapp3.1</TargetFramework> | <TargetFramework>netcoreapp3.1</TargetFramework> | ||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier> | <RuntimeIdentifier>win-x64</RuntimeIdentifier> |
@@ -6,7 +6,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121. | |||||
<PropertyGroup> | <PropertyGroup> | ||||
<Configuration>Release</Configuration> | <Configuration>Release</Configuration> | ||||
<Platform>Any CPU</Platform> | <Platform>Any CPU</Platform> | ||||
<PublishDir>bin\Release\netcoreapp3.1\win-x86\publish\</PublishDir> | |||||
<PublishDir>bin\Release\netcoreapp3.1\publish\</PublishDir> | |||||
<PublishProtocol>FileSystem</PublishProtocol> | <PublishProtocol>FileSystem</PublishProtocol> | ||||
<TargetFramework>netcoreapp3.1</TargetFramework> | <TargetFramework>netcoreapp3.1</TargetFramework> | ||||
<RuntimeIdentifier>win-x86</RuntimeIdentifier> | <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. | 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> | </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; | ||||
using System.Reactive.Linq; | using System.Reactive.Linq; | ||||
namespace Shadowsocks.ViewModels | |||||
namespace Shadowsocks.WPF.ViewModels | |||||
{ | { | ||||
public class ForwardProxyViewModel : ReactiveValidationObject | public class ForwardProxyViewModel : ReactiveValidationObject | ||||
{ | { |
@@ -7,7 +7,7 @@ using System.Reactive; | |||||
using System.Text; | using System.Text; | ||||
using System.Windows.Input; | using System.Windows.Input; | ||||
namespace Shadowsocks.ViewModels | |||||
namespace Shadowsocks.WPF.ViewModels | |||||
{ | { | ||||
public class HotkeysViewModel : ReactiveObject | 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.Text; | ||||
using System.Windows; | using System.Windows; | ||||
namespace Shadowsocks.ViewModels | |||||
namespace Shadowsocks.WPF.ViewModels | |||||
{ | { | ||||
public class OnlineConfigViewModel : ReactiveValidationObject | public class OnlineConfigViewModel : ReactiveValidationObject | ||||
{ | { |
@@ -10,7 +10,7 @@ using System.Reactive; | |||||
using System.Windows; | using System.Windows; | ||||
using System.Windows.Media.Imaging; | using System.Windows.Media.Imaging; | ||||
namespace Shadowsocks.ViewModels | |||||
namespace Shadowsocks.WPF.ViewModels | |||||
{ | { | ||||
public class ServerSharingViewModel : ReactiveObject | public class ServerSharingViewModel : ReactiveObject | ||||
{ | { |
@@ -3,7 +3,7 @@ using ReactiveUI; | |||||
using Shadowsocks.Controller; | using Shadowsocks.Controller; | ||||
using System.Reactive; | using System.Reactive; | ||||
namespace Shadowsocks.ViewModels | |||||
namespace Shadowsocks.WPF.ViewModels | |||||
{ | { | ||||
public class VersionUpdatePromptViewModel : ReactiveObject | public class VersionUpdatePromptViewModel : ReactiveObject | ||||
{ | { |
@@ -1,12 +1,12 @@ | |||||
<reactiveui:ReactiveUserControl | <reactiveui:ReactiveUserControl | ||||
x:Class="Shadowsocks.Views.ForwardProxyView" | |||||
x:Class="Shadowsocks.WPF.Views.ForwardProxyView" | |||||
x:TypeArguments="vms:ForwardProxyViewModel" | x:TypeArguments="vms:ForwardProxyViewModel" | ||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | 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:reactiveui="http://reactiveui.net" | ||||
xmlns:lex="http://wpflocalizeextension.codeplex.com" | xmlns:lex="http://wpflocalizeextension.codeplex.com" | ||||
lex:LocalizeDictionary.DesignCulture="en" | lex:LocalizeDictionary.DesignCulture="en" |
@@ -1,8 +1,8 @@ | |||||
using ReactiveUI; | using ReactiveUI; | ||||
using Shadowsocks.ViewModels; | |||||
using Shadowsocks.WPF.ViewModels; | |||||
using System.Reactive.Disposables; | using System.Reactive.Disposables; | ||||
namespace Shadowsocks.Views | |||||
namespace Shadowsocks.WPF.Views | |||||
{ | { | ||||
/// <summary> | /// <summary> | ||||
/// Interaction logic for ForwardProxyView.xaml | /// Interaction logic for ForwardProxyView.xaml |
@@ -1,12 +1,12 @@ | |||||
<reactiveui:ReactiveUserControl | <reactiveui:ReactiveUserControl | ||||
x:Class="Shadowsocks.Views.HotkeysView" | |||||
x:Class="Shadowsocks.WPF.Views.HotkeysView" | |||||
x:TypeArguments="vms:HotkeysViewModel" | x:TypeArguments="vms:HotkeysViewModel" | ||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | 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:reactiveui="http://reactiveui.net" | ||||
xmlns:lex="http://wpflocalizeextension.codeplex.com" | xmlns:lex="http://wpflocalizeextension.codeplex.com" | ||||
lex:LocalizeDictionary.DesignCulture="en" | lex:LocalizeDictionary.DesignCulture="en" |
@@ -1,5 +1,5 @@ | |||||
using ReactiveUI; | using ReactiveUI; | ||||
using Shadowsocks.ViewModels; | |||||
using Shadowsocks.WPF.ViewModels; | |||||
using System; | using System; | ||||
using System.Reactive.Disposables; | using System.Reactive.Disposables; | ||||
using System.Windows; | using System.Windows; | ||||
@@ -11,7 +11,7 @@ using System.Windows.Media; | |||||
using System.Windows.Media.Imaging; | using System.Windows.Media.Imaging; | ||||
using System.Windows.Navigation; | using System.Windows.Navigation; | ||||
namespace Shadowsocks.Views | |||||
namespace Shadowsocks.WPF.Views | |||||
{ | { | ||||
/// <summary> | /// <summary> | ||||
/// Interaction logic for HotkeysView.xaml | /// 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 | <reactiveui:ReactiveUserControl | ||||
x:Class="Shadowsocks.Views.OnlineConfigView" | |||||
x:Class="Shadowsocks.WPF.Views.OnlineConfigView" | |||||
x:TypeArguments="vms:OnlineConfigViewModel" | x:TypeArguments="vms:OnlineConfigViewModel" | ||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | 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:reactiveui="http://reactiveui.net" | ||||
xmlns:lex="http://wpflocalizeextension.codeplex.com" | xmlns:lex="http://wpflocalizeextension.codeplex.com" | ||||
lex:LocalizeDictionary.DesignCulture="en" | lex:LocalizeDictionary.DesignCulture="en" |
@@ -1,8 +1,8 @@ | |||||
using ReactiveUI; | using ReactiveUI; | ||||
using Shadowsocks.ViewModels; | |||||
using Shadowsocks.WPF.ViewModels; | |||||
using System.Reactive.Disposables; | using System.Reactive.Disposables; | ||||
namespace Shadowsocks.Views | |||||
namespace Shadowsocks.WPF.Views | |||||
{ | { | ||||
/// <summary> | /// <summary> | ||||
/// Interaction logic for OnlineConfigView.xaml | /// Interaction logic for OnlineConfigView.xaml |
@@ -1,12 +1,12 @@ | |||||
<reactiveui:ReactiveUserControl | <reactiveui:ReactiveUserControl | ||||
x:Class="Shadowsocks.Views.ServerSharingView" | |||||
x:Class="Shadowsocks.WPF.Views.ServerSharingView" | |||||
x:TypeArguments="vms:ServerSharingViewModel" | x:TypeArguments="vms:ServerSharingViewModel" | ||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | 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:reactiveui="http://reactiveui.net" | ||||
xmlns:lex="http://wpflocalizeextension.codeplex.com" | xmlns:lex="http://wpflocalizeextension.codeplex.com" | ||||
lex:LocalizeDictionary.DesignCulture="en" | lex:LocalizeDictionary.DesignCulture="en" |
@@ -1,9 +1,9 @@ | |||||
using ReactiveUI; | using ReactiveUI; | ||||
using Shadowsocks.ViewModels; | |||||
using Shadowsocks.WPF.ViewModels; | |||||
using System.Reactive.Disposables; | using System.Reactive.Disposables; | ||||
using System.Windows.Input; | using System.Windows.Input; | ||||
namespace Shadowsocks.Views | |||||
namespace Shadowsocks.WPF.Views | |||||
{ | { | ||||
/// <summary> | /// <summary> | ||||
/// Interaction logic for ServerSharingView.xaml | /// Interaction logic for ServerSharingView.xaml |
@@ -1,12 +1,12 @@ | |||||
<reactiveui:ReactiveUserControl | <reactiveui:ReactiveUserControl | ||||
x:Class="Shadowsocks.Views.VersionUpdatePromptView" | |||||
x:Class="Shadowsocks.WPF.Views.VersionUpdatePromptView" | |||||
x:TypeArguments="vms:VersionUpdatePromptViewModel" | x:TypeArguments="vms:VersionUpdatePromptViewModel" | ||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | 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:reactiveui="http://reactiveui.net" | ||||
xmlns:mdxam="clr-namespace:MdXaml;assembly=MdXaml" | xmlns:mdxam="clr-namespace:MdXaml;assembly=MdXaml" | ||||
xmlns:lex="http://wpflocalizeextension.codeplex.com" | xmlns:lex="http://wpflocalizeextension.codeplex.com" |
@@ -1,9 +1,9 @@ | |||||
using Newtonsoft.Json.Linq; | using Newtonsoft.Json.Linq; | ||||
using ReactiveUI; | using ReactiveUI; | ||||
using Shadowsocks.ViewModels; | |||||
using Shadowsocks.WPF.ViewModels; | |||||
using System.Reactive.Disposables; | using System.Reactive.Disposables; | ||||
namespace Shadowsocks.Views | |||||
namespace Shadowsocks.WPF.Views | |||||
{ | { | ||||
/// <summary> | /// <summary> | ||||
/// Interaction logic for VersionUpdatePromptView.xaml | /// 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 | EndProject | ||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7BD54B24-BBD7-4DD8-99EF-DAEE6684B673}" | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7BD54B24-BBD7-4DD8-99EF-DAEE6684B673}" | ||||
ProjectSection(SolutionItems) = preProject | ProjectSection(SolutionItems) = preProject | ||||
.editorconfig = .editorconfig | |||||
.gitignore = .gitignore | .gitignore = .gitignore | ||||
appveyor.yml = appveyor.yml | appveyor.yml = appveyor.yml | ||||
appveyor.yml.obsolete = appveyor.yml.obsolete | appveyor.yml.obsolete = appveyor.yml.obsolete | ||||
@@ -23,6 +24,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution | |||||
README.md = README.md | README.md = README.md | ||||
EndProjectSection | EndProjectSection | ||||
EndProject | 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 | Global | ||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
Debug|Any CPU = Debug|Any CPU | 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}.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.ActiveCfg = Release|Any CPU | ||||
{45913187-0685-4903-B250-DCEF0479CD86}.Release|Any CPU.Build.0 = 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 | EndGlobalSection | ||||
GlobalSection(SolutionProperties) = preSolution | GlobalSection(SolutionProperties) = preSolution | ||||
HideSolutionNode = FALSE | HideSolutionNode = FALSE | ||||