Browse Source

🪓 Split into multiple projects

- Shadowsocks
- Shadowsocks.Common
- Shadowsocks.Crypto
- Shadowsocks.WPF
pull/2897/head
database64128 3 years ago
parent
commit
cf7e639cef
No known key found for this signature in database GPG Key ID: 1CA27546BEDB8B01
91 changed files with 3038 additions and 2658 deletions
  1. +100
    -0
      .editorconfig
  2. +9
    -0
      Shadowsocks.Common/Models/IoCManager.cs
  3. +17
    -0
      Shadowsocks.Common/Shadowsocks.Common.csproj
  4. +1
    -5
      Shadowsocks.Common/SystemProxy/ProxyException.cs
  5. +143
    -151
      Shadowsocks.Common/Utilities/LoggerExtension.cs
  6. +5
    -5
      Shadowsocks.Crypto/Crypto/AEAD/AEADAesGcmNativeCrypto.cs
  7. +5
    -4
      Shadowsocks.Crypto/Crypto/AEAD/AEADBouncyCastleCrypto.cs
  8. +322
    -320
      Shadowsocks.Crypto/Crypto/AEAD/AEADCrypto.cs
  9. +15
    -11
      Shadowsocks.Crypto/Crypto/AEAD/AEADNaClCrypto.cs
  10. +5
    -5
      Shadowsocks.Crypto/Crypto/CipherInfo.cs
  11. +48
    -49
      Shadowsocks.Crypto/Crypto/CryptoBase.cs
  12. +123
    -119
      Shadowsocks.Crypto/Crypto/CryptoFactory.cs
  13. +17
    -17
      Shadowsocks.Crypto/Crypto/Exception/CryptoException.cs
  14. +14
    -14
      Shadowsocks.Crypto/Crypto/ICrypto.cs
  15. +50
    -50
      Shadowsocks.Crypto/Crypto/RNG.cs
  16. +0
    -0
      Shadowsocks.Crypto/Crypto/Stream/ExtendedCfbBlockCipher.cs
  17. +5
    -5
      Shadowsocks.Crypto/Crypto/Stream/StreamAesBouncyCastleCrypto.cs
  18. +5
    -5
      Shadowsocks.Crypto/Crypto/Stream/StreamChachaNaClCrypto.cs
  19. +181
    -179
      Shadowsocks.Crypto/Crypto/Stream/StreamCrypto.cs
  20. +4
    -4
      Shadowsocks.Crypto/Crypto/Stream/StreamPlainNativeCrypto.cs
  21. +4
    -5
      Shadowsocks.Crypto/Crypto/Stream/StreamRc4NativeCrypto.cs
  22. +20
    -0
      Shadowsocks.Crypto/Crypto/TCPInfo.cs
  23. +18
    -0
      Shadowsocks.Crypto/Shadowsocks.Crypto.csproj
  24. +4
    -4
      Shadowsocks.Crypto/Util/CryptoUtils.cs
  25. +15
    -0
      Shadowsocks.WPF/App.xaml
  26. +20
    -0
      Shadowsocks.WPF/App.xaml.cs
  27. +10
    -0
      Shadowsocks.WPF/AssemblyInfo.cs
  28. +0
    -0
      Shadowsocks.WPF/Assets/shadowsocks.ico
  29. +0
    -0
      Shadowsocks.WPF/Assets/ss128.pdn
  30. +0
    -0
      Shadowsocks.WPF/Assets/ss32.pdn
  31. +0
    -0
      Shadowsocks.WPF/Assets/ss32Fill.png
  32. +0
    -0
      Shadowsocks.WPF/Assets/ss32In.png
  33. +0
    -0
      Shadowsocks.WPF/Assets/ss32Out.png
  34. +0
    -0
      Shadowsocks.WPF/Assets/ss32Outline.png
  35. +0
    -0
      Shadowsocks.WPF/Assets/ssw128.png
  36. +3
    -0
      Shadowsocks.WPF/FodyWeavers.xml
  37. +26
    -0
      Shadowsocks.WPF/FodyWeavers.xsd
  38. +15
    -0
      Shadowsocks.WPF/Localization/LocalizationProvider.cs
  39. +1
    -1
      Shadowsocks.WPF/Localization/Strings.Designer.cs
  40. +0
    -0
      Shadowsocks.WPF/Localization/Strings.fr.resx
  41. +0
    -0
      Shadowsocks.WPF/Localization/Strings.ja.resx
  42. +0
    -0
      Shadowsocks.WPF/Localization/Strings.ko.resx
  43. +0
    -0
      Shadowsocks.WPF/Localization/Strings.resx
  44. +0
    -0
      Shadowsocks.WPF/Localization/Strings.ru.resx
  45. +0
    -0
      Shadowsocks.WPF/Localization/Strings.zh-Hans.resx
  46. +188
    -188
      Shadowsocks.WPF/Localization/Strings.zh-Hant.resx
  47. +11
    -9
      Shadowsocks.WPF/Properties/PublishProfiles/FolderProfile.pubxml
  48. +0
    -0
      Shadowsocks.WPF/Properties/PublishProfiles/FolderProfile.pubxml.user
  49. +1
    -1
      Shadowsocks.WPF/Properties/PublishProfiles/win-x64.pubxml
  50. +0
    -0
      Shadowsocks.WPF/Properties/PublishProfiles/win-x64.pubxml.user
  51. +1
    -1
      Shadowsocks.WPF/Properties/PublishProfiles/win-x86.pubxml
  52. +4
    -4
      Shadowsocks.WPF/Properties/PublishProfiles/win-x86.pubxml.user
  53. +133
    -0
      Shadowsocks.WPF/Resource.Designer.cs
  54. +141
    -156
      Shadowsocks.WPF/Resource.resx
  55. +70
    -0
      Shadowsocks.WPF/Shadowsocks.WPF.csproj
  56. +21
    -0
      Shadowsocks.WPF/Shadowsocks.WPF.csproj.user
  57. +1
    -1
      Shadowsocks.WPF/ViewModels/ForwardProxyViewModel.cs
  58. +1
    -1
      Shadowsocks.WPF/ViewModels/HotkeysViewModel.cs
  59. +14
    -0
      Shadowsocks.WPF/ViewModels/MainWindowViewModel.cs
  60. +1
    -1
      Shadowsocks.WPF/ViewModels/OnlineConfigViewModel.cs
  61. +1
    -1
      Shadowsocks.WPF/ViewModels/ServerSharingViewModel.cs
  62. +1
    -1
      Shadowsocks.WPF/ViewModels/VersionUpdatePromptViewModel.cs
  63. +3
    -3
      Shadowsocks.WPF/Views/ForwardProxyView.xaml
  64. +2
    -2
      Shadowsocks.WPF/Views/ForwardProxyView.xaml.cs
  65. +3
    -3
      Shadowsocks.WPF/Views/HotkeysView.xaml
  66. +2
    -2
      Shadowsocks.WPF/Views/HotkeysView.xaml.cs
  67. +21
    -0
      Shadowsocks.WPF/Views/MainWindow.xaml
  68. +17
    -0
      Shadowsocks.WPF/Views/MainWindow.xaml.cs
  69. +3
    -3
      Shadowsocks.WPF/Views/OnlineConfigView.xaml
  70. +2
    -2
      Shadowsocks.WPF/Views/OnlineConfigView.xaml.cs
  71. +3
    -3
      Shadowsocks.WPF/Views/ServerSharingView.xaml
  72. +2
    -2
      Shadowsocks.WPF/Views/ServerSharingView.xaml.cs
  73. +3
    -3
      Shadowsocks.WPF/Views/VersionUpdatePromptView.xaml
  74. +2
    -2
      Shadowsocks.WPF/Views/VersionUpdatePromptView.xaml.cs
  75. +13
    -0
      Shadowsocks/Assets/NLog.config
  76. +810
    -810
      Shadowsocks/Assets/abp.js
  77. +0
    -0
      Shadowsocks/Assets/dlc.dat
  78. +0
    -0
      Shadowsocks/Assets/privoxy.exe.gz
  79. +8
    -8
      Shadowsocks/Assets/privoxy_conf.txt
  80. +2
    -2
      Shadowsocks/Assets/user-rule.txt
  81. +153
    -0
      Shadowsocks/Resource.Designer.cs
  82. +139
    -0
      Shadowsocks/Resource.resx
  83. +31
    -0
      Shadowsocks/Shadowsocks.csproj
  84. +0
    -13
      shadowsocks-csharp/Data/NLog.config
  85. +0
    -6
      shadowsocks-csharp/FodyWeavers.xml
  86. +0
    -113
      shadowsocks-csharp/FodyWeavers.xsd
  87. +0
    -13
      shadowsocks-csharp/Localization/LocalizationProvider.cs
  88. +0
    -244
      shadowsocks-csharp/Properties/Resources.Designer.cs
  89. +0
    -86
      shadowsocks-csharp/Properties/Settings.Designer.cs
  90. +0
    -21
      shadowsocks-csharp/Properties/Settings.settings
  91. +25
    -0
      shadowsocks-windows.sln

+ 100
- 0
.editorconfig View File

@@ -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

+ 9
- 0
Shadowsocks.Common/Models/IoCManager.cs View File

@@ -0,0 +1,9 @@
using SimpleInjector;

namespace Shadowsocks.Common.Model
{
public static class IoCManager
{
public static Container Container { get; } = new Container();
}
}

+ 17
- 0
Shadowsocks.Common/Shadowsocks.Common.csproj View File

@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<Authors>clowwindy &amp; community 2020</Authors>
<Company>clowwindy &amp; 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>

shadowsocks-csharp/Util/SystemProxy/ProxyException.cs → Shadowsocks.Common/SystemProxy/ProxyException.cs View File

@@ -1,11 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;

namespace Shadowsocks.Util.SystemProxy
namespace Shadowsocks.Common.SystemProxy
{
enum ProxyExceptionType
{

shadowsocks-csharp/Controller/LoggerExtension.cs → Shadowsocks.Common/Utilities/LoggerExtension.cs View File

@@ -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);
}
}
}
}

shadowsocks-csharp/Encryption/AEAD/AEADAesGcmNativeEncryptor.cs → Shadowsocks.Crypto/Crypto/AEAD/AEADAesGcmNativeCrypto.cs View File

@@ -1,12 +1,12 @@
using System;
using System;
using System.Collections.Generic;
using System.Security.Cryptography;

namespace Shadowsocks.Encryption.AEAD
namespace Shadowsocks.Crypto.AEAD
{
public class AEADAesGcmNativeEncryptor : AEADEncryptor
public class AEADAesGcmNativeCrypto : AEADCrypto
{
public AEADAesGcmNativeEncryptor(string method, string password) : base(method, password)
public AEADAesGcmNativeCrypto(string method, string password) : base(method, password)
{
}

@@ -51,4 +51,4 @@ namespace Shadowsocks.Encryption.AEAD
return clen;
}
}
}
}

shadowsocks-csharp/Encryption/AEAD/AEADBouncyCastleEncryptor.cs → Shadowsocks.Crypto/Crypto/AEAD/AEADBouncyCastleCrypto.cs View File

@@ -1,16 +1,17 @@
using System;
using System;
using System.Collections.Generic;

using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;

namespace Shadowsocks.Encryption.AEAD
namespace Shadowsocks.Crypto.AEAD
{
public class AEADBouncyCastleEncryptor : AEADEncryptor
public class AEADBouncyCastleCrypto : AEADCrypto
{
IAeadCipher aead;
bool enc;
public AEADBouncyCastleEncryptor(string method, string password) : base(method, password)
public AEADBouncyCastleCrypto(string method, string password) : base(method, password)
{
aead = cipherFamily switch
{

shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs → Shadowsocks.Crypto/Crypto/AEAD/AEADCrypto.cs View File

@@ -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;
}
}
}

shadowsocks-csharp/Encryption/AEAD/AEADNaClEncryptor.cs → Shadowsocks.Crypto/Crypto/AEAD/AEADNaClCrypto.cs View File

@@ -1,15 +1,16 @@
using NaCl.Core;
using NaCl.Core.Base;
using System;
using System.Collections.Generic;

namespace Shadowsocks.Encryption.AEAD
using NaCl.Core;
using NaCl.Core.Base;

namespace Shadowsocks.Crypto.AEAD
{
public class AEADNaClEncryptor : AEADEncryptor
public class AEADNaClCrypto : AEADCrypto
{

SnufflePoly1305 enc;
public AEADNaClEncryptor(string method, string password) : base(method, password)
public AEADNaClCrypto(string method, string password) : base(method, password)
{
}

@@ -43,16 +44,19 @@ namespace Shadowsocks.Encryption.AEAD

public override int CipherEncrypt(ReadOnlySpan<byte> plain, Span<byte> cipher)
{
byte[] ct = enc.Encrypt(plain, null, nonce);
ct.CopyTo(cipher);
return ct.Length;
//byte[] ct = enc.Encrypt(plain, null, nonce);
//ct.CopyTo(cipher);
//return ct.Length;

throw new NotImplementedException();
}

public override int CipherDecrypt(Span<byte> plain, ReadOnlySpan<byte> cipher)
{
byte[] pt = enc.Decrypt(cipher, null, nonce);
pt.CopyTo(plain);
return pt.Length;
//byte[] pt = enc.Decrypt(cipher, null, nonce);
//pt.CopyTo(plain);
//return pt.Length;
throw new NotImplementedException();
}
}
}

shadowsocks-csharp/Encryption/CipherInfo.cs → Shadowsocks.Crypto/Crypto/CipherInfo.cs View File

@@ -1,6 +1,4 @@
using Shadowsocks.Controller;

namespace Shadowsocks.Encryption
namespace Shadowsocks.Crypto
{
public enum CipherFamily
{
@@ -96,7 +94,9 @@ namespace Shadowsocks.Encryption

public override string ToString()
{
return StandardState == CipherStandardState.InUse ? Name : $"{Name} ({I18N.GetString(StandardState.ToString().ToLower())})";
// TODO:
// return StandardState == CipherStandardState.InUse ? Name : $"{Name} ({I18N.GetString(StandardState.ToString().ToLower())})";
return "";
}
public string ToString(bool verbose)
{
@@ -108,4 +108,4 @@ namespace Shadowsocks.Encryption
return $"{Name} {StandardState} {CipherParameter}";
}
}
}
}

shadowsocks-csharp/Encryption/EncryptorBase.cs → Shadowsocks.Crypto/Crypto/CryptoBase.cs View File

@@ -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;
}
}

shadowsocks-csharp/Encryption/EncryptorFactory.cs → Shadowsocks.Crypto/Crypto/CryptoFactory.cs View File

@@ -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;
}
}
}

shadowsocks-csharp/Encryption/Exception/CryptoException.cs → Shadowsocks.Crypto/Crypto/Exception/CryptoException.cs View File

@@ -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)
{
}
}
}

shadowsocks-csharp/Encryption/IEncryptor.cs → Shadowsocks.Crypto/Crypto/ICrypto.cs View File

@@ -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);
}
}

shadowsocks-csharp/Encryption/RNG.cs → Shadowsocks.Crypto/Crypto/RNG.cs View File

@@ -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);
}
}
}
}

shadowsocks-csharp/Encryption/Stream/ExtendedCfbBlockCipher.cs → Shadowsocks.Crypto/Crypto/Stream/ExtendedCfbBlockCipher.cs View File


shadowsocks-csharp/Encryption/Stream/StreamAesBouncyCastleEncryptor.cs → Shadowsocks.Crypto/Crypto/Stream/StreamAesBouncyCastleCrypto.cs View File

@@ -1,19 +1,19 @@
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

namespace Shadowsocks.Encryption.Stream
namespace Shadowsocks.Crypto.Stream
{

public class StreamAesCfbBouncyCastleEncryptor : StreamEncryptor
public class StreamAesCfbBouncyCastleCrypto : StreamCrypto
{
readonly byte[] cfbBuf = new byte[MaxInputSize + 128];
int ptr = 0;
readonly ExtendedCfbBlockCipher b;
public StreamAesCfbBouncyCastleEncryptor(string method, string password) : base(method, password)
public StreamAesCfbBouncyCastleCrypto(string method, string password) : base(method, password)
{
b = new ExtendedCfbBlockCipher(new AesEngine(), 128);
}
@@ -36,7 +36,7 @@ namespace Shadowsocks.Encryption.Stream
return cipher.Length;
}

[MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
[MethodImpl( MethodImplOptions.AggressiveInlining)]
private void CipherUpdate(ReadOnlySpan<byte> i, Span<byte> o)
{
Span<byte> ob = new byte[o.Length + 128];

shadowsocks-csharp/Encryption/Stream/StreamChachaNaClEncryptor.cs → Shadowsocks.Crypto/Crypto/Stream/StreamChachaNaClCrypto.cs View File

@@ -1,11 +1,11 @@
using System;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using NaCl.Core;

namespace Shadowsocks.Encryption.Stream
namespace Shadowsocks.Crypto.Stream
{
public class StreamChachaNaClEncryptor : StreamEncryptor
public class StreamChachaNaClCrypto : StreamCrypto
{
const int BlockSize = 64;

@@ -22,7 +22,7 @@ namespace Shadowsocks.Encryption.Stream
int remain = 0;
// increase counter manually...
int ic = 0;
public StreamChachaNaClEncryptor(string method, string password) : base(method, password)
public StreamChachaNaClCrypto(string method, string password) : base(method, password)
{
}

@@ -36,7 +36,7 @@ namespace Shadowsocks.Encryption.Stream
return CipherUpdate(plain, cipher, true);
}

[MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int CipherUpdate(ReadOnlySpan<byte> i, Span<byte> o, bool enc)
{
// about performance problem:

shadowsocks-csharp/Encryption/Stream/StreamEncryptor.cs → Shadowsocks.Crypto/Crypto/Stream/StreamCrypto.cs View File

@@ -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
}
}

shadowsocks-csharp/Encryption/Stream/StreamPlainNativeEncryptor.cs → Shadowsocks.Crypto/Crypto/Stream/StreamPlainNativeCrypto.cs View File

@@ -1,12 +1,12 @@
using System;
using System;
using System.Collections.Generic;

namespace Shadowsocks.Encryption.Stream
namespace Shadowsocks.Crypto.Stream
{
public class StreamPlainNativeEncryptor : StreamEncryptor
public class StreamPlainNativeCrypto : StreamCrypto
{

public StreamPlainNativeEncryptor(string method, string password) : base(method, password)
public StreamPlainNativeCrypto(string method, string password) : base(method, password)
{
}


shadowsocks-csharp/Encryption/Stream/StreamRc4NativeEncryptor.cs → Shadowsocks.Crypto/Crypto/Stream/StreamRc4NativeCrypto.cs View File

@@ -1,14 +1,14 @@
using System;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

namespace Shadowsocks.Encryption.Stream
namespace Shadowsocks.Crypto.Stream
{
public class StreamRc4NativeEncryptor : StreamEncryptor
public class StreamRc4NativeCrypto : StreamCrypto
{
byte[] realkey = new byte[256];
byte[] sbox = new byte[256];
public StreamRc4NativeEncryptor(string method, string password) : base(method, password)
public StreamRc4NativeCrypto(string method, string password) : base(method, password)
{
}

@@ -94,7 +94,6 @@ namespace Shadowsocks.Encryption.Stream
return s;
}

[MethodImpl(MethodImplOptions.AggressiveOptimization)]
private void RC4(Span<byte> s, Span<byte> data, int length)
{
for (int n = 0; n < length; n++)

+ 20
- 0
Shadowsocks.Crypto/Crypto/TCPInfo.cs View File

@@ -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 */;
}
}

+ 18
- 0
Shadowsocks.Crypto/Shadowsocks.Crypto.csproj View File

@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<Authors>clowwindy &amp; 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>

shadowsocks-csharp/Encryption/CryptoUtils.cs → Shadowsocks.Crypto/Util/CryptoUtils.cs View File

@@ -1,4 +1,4 @@
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
@@ -6,7 +6,7 @@ using System;
using System.Security.Cryptography;
using System.Threading;

namespace Shadowsocks.Encryption
namespace Shadowsocks.Crypto
{
public static class CryptoUtils
{
@@ -14,14 +14,14 @@ namespace Shadowsocks.Encryption

public static byte[] MD5(byte[] b)
{
var hash = new byte[EncryptorBase.MD5Length];
var hash = new byte[CryptoBase.MD5Length];
Md5Hasher.Value.TryComputeHash(b, hash, out _);
return hash;
}
// currently useless, just keep api same
public static Span<byte> MD5(Span<byte> span)
{
Span<byte> hash = new byte[EncryptorBase.MD5Length];
Span<byte> hash = new byte[CryptoBase.MD5Length];
Md5Hasher.Value.TryComputeHash(span, hash, out _);
return hash;
}

+ 15
- 0
Shadowsocks.WPF/App.xaml View File

@@ -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>

+ 20
- 0
Shadowsocks.WPF/App.xaml.cs View File

@@ -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());
}
}
}

+ 10
- 0
Shadowsocks.WPF/AssemblyInfo.cs View File

@@ -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)
)]

shadowsocks-csharp/shadowsocks.ico → Shadowsocks.WPF/Assets/shadowsocks.ico View File

Before After

shadowsocks-csharp/Resources/ss128.pdn → Shadowsocks.WPF/Assets/ss128.pdn View File


shadowsocks-csharp/Resources/ss32.pdn → Shadowsocks.WPF/Assets/ss32.pdn View File


shadowsocks-csharp/Resources/ss32Fill.png → Shadowsocks.WPF/Assets/ss32Fill.png View File


shadowsocks-csharp/Resources/ss32In.png → Shadowsocks.WPF/Assets/ss32In.png View File


shadowsocks-csharp/Resources/ss32Out.png → Shadowsocks.WPF/Assets/ss32Out.png View File


shadowsocks-csharp/Resources/ss32Outline.png → Shadowsocks.WPF/Assets/ss32Outline.png View File


shadowsocks-csharp/Resources/ssw128.png → Shadowsocks.WPF/Assets/ssw128.png View File

Before After
Width: 128  |  Height: 128  |  Size: 1.7 kB Width: 128  |  Height: 128  |  Size: 1.7 kB

+ 3
- 0
Shadowsocks.WPF/FodyWeavers.xml View File

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

+ 26
- 0
Shadowsocks.WPF/FodyWeavers.xsd View File

@@ -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>

+ 15
- 0
Shadowsocks.WPF/Localization/LocalizationProvider.cs View File

@@ -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}");
}
}

shadowsocks-csharp/Localization/Strings.Designer.cs → Shadowsocks.WPF/Localization/Strings.Designer.cs View File

@@ -8,7 +8,7 @@
// </auto-generated>
//------------------------------------------------------------------------------

namespace Shadowsocks.Localization {
namespace Shadowsocks.WPF.Localization {
using System;

shadowsocks-csharp/Localization/Strings.fr.resx → Shadowsocks.WPF/Localization/Strings.fr.resx View File


shadowsocks-csharp/Localization/Strings.ja.resx → Shadowsocks.WPF/Localization/Strings.ja.resx View File


shadowsocks-csharp/Localization/Strings.ko.resx → Shadowsocks.WPF/Localization/Strings.ko.resx View File


shadowsocks-csharp/Localization/Strings.resx → Shadowsocks.WPF/Localization/Strings.resx View File


shadowsocks-csharp/Localization/Strings.ru.resx → Shadowsocks.WPF/Localization/Strings.ru.resx View File


shadowsocks-csharp/Localization/Strings.zh-Hans.resx → Shadowsocks.WPF/Localization/Strings.zh-Hans.resx View File


shadowsocks-csharp/Localization/Strings.zh-Hant.resx → Shadowsocks.WPF/Localization/Strings.zh-Hant.resx View File

@@ -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>

shadowsocks-csharp/Properties/PublishProfiles/FolderProfile.pubxml → Shadowsocks.WPF/Properties/PublishProfiles/FolderProfile.pubxml View File

@@ -1,12 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>bin\Release\netcoreapp3.1\publish\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
</PropertyGroup>
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration>Debug</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>bin\Release\netcoreapp3.1\publish\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<TargetFramework>netcoreapp3.1</TargetFramework>
<SelfContained>false</SelfContained>
</PropertyGroup>
</Project>

shadowsocks-csharp/Properties/PublishProfiles/win-x64.pubxml.user → Shadowsocks.WPF/Properties/PublishProfiles/FolderProfile.pubxml.user View File


shadowsocks-csharp/Properties/PublishProfiles/win-x64.pubxml → Shadowsocks.WPF/Properties/PublishProfiles/win-x64.pubxml View File

@@ -6,7 +6,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>bin\Release\netcoreapp3.1\win-x64\publish\</PublishDir>
<PublishDir>bin\Release\netcoreapp3.1\publish\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>

shadowsocks-csharp/Properties/PublishProfiles/win-x86.pubxml.user → Shadowsocks.WPF/Properties/PublishProfiles/win-x64.pubxml.user View File


shadowsocks-csharp/Properties/PublishProfiles/win-x86.pubxml → Shadowsocks.WPF/Properties/PublishProfiles/win-x86.pubxml View File

@@ -6,7 +6,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>bin\Release\netcoreapp3.1\win-x86\publish\</PublishDir>
<PublishDir>bin\Release\netcoreapp3.1\publish\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RuntimeIdentifier>win-x86</RuntimeIdentifier>

shadowsocks-csharp/Properties/PublishProfiles/FolderProfile.pubxml.user → Shadowsocks.WPF/Properties/PublishProfiles/win-x86.pubxml.user View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
</Project>
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
</Project>

+ 133
- 0
Shadowsocks.WPF/Resource.Designer.cs View File

@@ -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));
}
}
}
}

shadowsocks-csharp/Properties/Resources.resx → Shadowsocks.WPF/Resource.resx View File

@@ -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>

+ 70
- 0
Shadowsocks.WPF/Shadowsocks.WPF.csproj View File

@@ -0,0 +1,70 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UseWPF>true</UseWPF>
<Authors>clowwindy &amp; 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>

+ 21
- 0
Shadowsocks.WPF/Shadowsocks.WPF.csproj.user View File

@@ -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>

shadowsocks-csharp/ViewModels/ForwardProxyViewModel.cs → Shadowsocks.WPF/ViewModels/ForwardProxyViewModel.cs View File

@@ -9,7 +9,7 @@ using System.Linq;
using System.Reactive;
using System.Reactive.Linq;

namespace Shadowsocks.ViewModels
namespace Shadowsocks.WPF.ViewModels
{
public class ForwardProxyViewModel : ReactiveValidationObject
{

shadowsocks-csharp/ViewModels/HotkeysViewModel.cs → Shadowsocks.WPF/ViewModels/HotkeysViewModel.cs View File

@@ -7,7 +7,7 @@ using System.Reactive;
using System.Text;
using System.Windows.Input;

namespace Shadowsocks.ViewModels
namespace Shadowsocks.WPF.ViewModels
{
public class HotkeysViewModel : ReactiveObject
{

+ 14
- 0
Shadowsocks.WPF/ViewModels/MainWindowViewModel.cs View File

@@ -0,0 +1,14 @@
using ReactiveUI;
using Shadowsocks.Controller.Service;

using System;

namespace Shadowsocks.WPF.ViewModels
{
public class MainWindowViewModel : ReactiveObject
{
public MainWindowViewModel()
{
}
}
}

shadowsocks-csharp/ViewModels/OnlineConfigViewModel.cs → Shadowsocks.WPF/ViewModels/OnlineConfigViewModel.cs View File

@@ -15,7 +15,7 @@ using System.Reactive.Linq;
using System.Text;
using System.Windows;

namespace Shadowsocks.ViewModels
namespace Shadowsocks.WPF.ViewModels
{
public class OnlineConfigViewModel : ReactiveValidationObject
{

shadowsocks-csharp/ViewModels/ServerSharingViewModel.cs → Shadowsocks.WPF/ViewModels/ServerSharingViewModel.cs View File

@@ -10,7 +10,7 @@ using System.Reactive;
using System.Windows;
using System.Windows.Media.Imaging;

namespace Shadowsocks.ViewModels
namespace Shadowsocks.WPF.ViewModels
{
public class ServerSharingViewModel : ReactiveObject
{

shadowsocks-csharp/ViewModels/VersionUpdatePromptViewModel.cs → Shadowsocks.WPF/ViewModels/VersionUpdatePromptViewModel.cs View File

@@ -3,7 +3,7 @@ using ReactiveUI;
using Shadowsocks.Controller;
using System.Reactive;

namespace Shadowsocks.ViewModels
namespace Shadowsocks.WPF.ViewModels
{
public class VersionUpdatePromptViewModel : ReactiveObject
{

shadowsocks-csharp/Views/ForwardProxyView.xaml → Shadowsocks.WPF/Views/ForwardProxyView.xaml View File

@@ -1,12 +1,12 @@
<reactiveui:ReactiveUserControl
x:Class="Shadowsocks.Views.ForwardProxyView"
x:Class="Shadowsocks.WPF.Views.ForwardProxyView"
x:TypeArguments="vms:ForwardProxyViewModel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Shadowsocks.Views"
xmlns:vms="clr-namespace:Shadowsocks.ViewModels"
xmlns:local="clr-namespace:Shadowsocks.WPF.Views"
xmlns:vms="clr-namespace:Shadowsocks.WPF.ViewModels"
xmlns:reactiveui="http://reactiveui.net"
xmlns:lex="http://wpflocalizeextension.codeplex.com"
lex:LocalizeDictionary.DesignCulture="en"

shadowsocks-csharp/Views/ForwardProxyView.xaml.cs → Shadowsocks.WPF/Views/ForwardProxyView.xaml.cs View File

@@ -1,8 +1,8 @@
using ReactiveUI;
using Shadowsocks.ViewModels;
using Shadowsocks.WPF.ViewModels;
using System.Reactive.Disposables;

namespace Shadowsocks.Views
namespace Shadowsocks.WPF.Views
{
/// <summary>
/// Interaction logic for ForwardProxyView.xaml

shadowsocks-csharp/Views/HotkeysView.xaml → Shadowsocks.WPF/Views/HotkeysView.xaml View File

@@ -1,12 +1,12 @@
<reactiveui:ReactiveUserControl
x:Class="Shadowsocks.Views.HotkeysView"
x:Class="Shadowsocks.WPF.Views.HotkeysView"
x:TypeArguments="vms:HotkeysViewModel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Shadowsocks.Views"
xmlns:vms="clr-namespace:Shadowsocks.ViewModels"
xmlns:local="clr-namespace:Shadowsocks.WPF.Views"
xmlns:vms="clr-namespace:Shadowsocks.WPF.ViewModels"
xmlns:reactiveui="http://reactiveui.net"
xmlns:lex="http://wpflocalizeextension.codeplex.com"
lex:LocalizeDictionary.DesignCulture="en"

shadowsocks-csharp/Views/HotkeysView.xaml.cs → Shadowsocks.WPF/Views/HotkeysView.xaml.cs View File

@@ -1,5 +1,5 @@
using ReactiveUI;
using Shadowsocks.ViewModels;
using Shadowsocks.WPF.ViewModels;
using System;
using System.Reactive.Disposables;
using System.Windows;
@@ -11,7 +11,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;

namespace Shadowsocks.Views
namespace Shadowsocks.WPF.Views
{
/// <summary>
/// Interaction logic for HotkeysView.xaml

+ 21
- 0
Shadowsocks.WPF/Views/MainWindow.xaml View File

@@ -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>

+ 17
- 0
Shadowsocks.WPF/Views/MainWindow.xaml.cs View File

@@ -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();
}
}
}

shadowsocks-csharp/Views/OnlineConfigView.xaml → Shadowsocks.WPF/Views/OnlineConfigView.xaml View File

@@ -1,12 +1,12 @@
<reactiveui:ReactiveUserControl
x:Class="Shadowsocks.Views.OnlineConfigView"
x:Class="Shadowsocks.WPF.Views.OnlineConfigView"
x:TypeArguments="vms:OnlineConfigViewModel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Shadowsocks.Views"
xmlns:vms="clr-namespace:Shadowsocks.ViewModels"
xmlns:local="clr-namespace:Shadowsocks.WPF.Views"
xmlns:vms="clr-namespace:Shadowsocks.WPF.ViewModels"
xmlns:reactiveui="http://reactiveui.net"
xmlns:lex="http://wpflocalizeextension.codeplex.com"
lex:LocalizeDictionary.DesignCulture="en"

shadowsocks-csharp/Views/OnlineConfigView.xaml.cs → Shadowsocks.WPF/Views/OnlineConfigView.xaml.cs View File

@@ -1,8 +1,8 @@
using ReactiveUI;
using Shadowsocks.ViewModels;
using Shadowsocks.WPF.ViewModels;
using System.Reactive.Disposables;

namespace Shadowsocks.Views
namespace Shadowsocks.WPF.Views
{
/// <summary>
/// Interaction logic for OnlineConfigView.xaml

shadowsocks-csharp/Views/ServerSharingView.xaml → Shadowsocks.WPF/Views/ServerSharingView.xaml View File

@@ -1,12 +1,12 @@
<reactiveui:ReactiveUserControl
x:Class="Shadowsocks.Views.ServerSharingView"
x:Class="Shadowsocks.WPF.Views.ServerSharingView"
x:TypeArguments="vms:ServerSharingViewModel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Shadowsocks.Views"
xmlns:vms="clr-namespace:Shadowsocks.ViewModels"
xmlns:local="clr-namespace:Shadowsocks.WPF.Views"
xmlns:vms="clr-namespace:Shadowsocks.WPF.ViewModels"
xmlns:reactiveui="http://reactiveui.net"
xmlns:lex="http://wpflocalizeextension.codeplex.com"
lex:LocalizeDictionary.DesignCulture="en"

shadowsocks-csharp/Views/ServerSharingView.xaml.cs → Shadowsocks.WPF/Views/ServerSharingView.xaml.cs View File

@@ -1,9 +1,9 @@
using ReactiveUI;
using Shadowsocks.ViewModels;
using Shadowsocks.WPF.ViewModels;
using System.Reactive.Disposables;
using System.Windows.Input;

namespace Shadowsocks.Views
namespace Shadowsocks.WPF.Views
{
/// <summary>
/// Interaction logic for ServerSharingView.xaml

shadowsocks-csharp/Views/VersionUpdatePromptView.xaml → Shadowsocks.WPF/Views/VersionUpdatePromptView.xaml View File

@@ -1,12 +1,12 @@
<reactiveui:ReactiveUserControl
x:Class="Shadowsocks.Views.VersionUpdatePromptView"
x:Class="Shadowsocks.WPF.Views.VersionUpdatePromptView"
x:TypeArguments="vms:VersionUpdatePromptViewModel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Shadowsocks.Views"
xmlns:vms="clr-namespace:Shadowsocks.ViewModels"
xmlns:local="clr-namespace:Shadowsocks.WPF.Views"
xmlns:vms="clr-namespace:Shadowsocks.WPF.ViewModels"
xmlns:reactiveui="http://reactiveui.net"
xmlns:mdxam="clr-namespace:MdXaml;assembly=MdXaml"
xmlns:lex="http://wpflocalizeextension.codeplex.com"

shadowsocks-csharp/Views/VersionUpdatePromptView.xaml.cs → Shadowsocks.WPF/Views/VersionUpdatePromptView.xaml.cs View File

@@ -1,9 +1,9 @@
using Newtonsoft.Json.Linq;
using ReactiveUI;
using Shadowsocks.ViewModels;
using Shadowsocks.WPF.ViewModels;
using System.Reactive.Disposables;

namespace Shadowsocks.Views
namespace Shadowsocks.WPF.Views
{
/// <summary>
/// Interaction logic for VersionUpdatePromptView.xaml

+ 13
- 0
Shadowsocks/Assets/NLog.config View File

@@ -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>

Shadowsocks/Assets/abp.js
File diff suppressed because it is too large
View File


shadowsocks-csharp/Data/dlc.dat → Shadowsocks/Assets/dlc.dat View File


shadowsocks-csharp/Data/privoxy.exe.gz → Shadowsocks/Assets/privoxy.exe.gz View File


shadowsocks-csharp/Data/privoxy_conf.txt → Shadowsocks/Assets/privoxy_conf.txt View File

@@ -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

shadowsocks-csharp/Data/user-rule.txt → Shadowsocks/Assets/user-rule.txt View File

@@ -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

+ 153
- 0
Shadowsocks/Resource.Designer.cs View File

@@ -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 &apos;javascript&apos; 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 &lt; __RULES__.length; i++) {
/// var s = __RULES__[i];
/// if (s.substring(0, 2) == &quot;||&quot;) s += &quot;^&quot;;
/// rules.push(s);
///}
///
///for (var i = 0; i &lt; [字符串的其余部分被截断]&quot;; 的本地化字符串。
/// </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>
/// 查找类似 &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
///&lt;!-- Warning: Configuration may reset after shadowsocks upgrade. --&gt;
///&lt;!-- If you messed it up, delete this file and Shadowsocks will create a new one. --&gt;
///&lt;nlog xmlns=&quot;http://www.nlog-project.org/schemas/NLog.xsd&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&gt;
/// &lt;targets&gt;
/// &lt;!-- This line is managed by Shadowsocks. Do not modify it unless you know what you are doing.--&gt;
/// &lt;target name=&quot;file&quot; xsi:type=&quot;File&quot; fileName=&quot;ss_win_temp\shadowsocks [字符串的其余部分被截断]&quot;; 的本地化字符串。
/// </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);
}
}
}
}

+ 139
- 0
Shadowsocks/Resource.resx View File

@@ -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>

+ 31
- 0
Shadowsocks/Shadowsocks.csproj View File

@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<Authors>clowwindy &amp; 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>

+ 0
- 13
shadowsocks-csharp/Data/NLog.config View File

@@ -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>

+ 0
- 6
shadowsocks-csharp/FodyWeavers.xml View File

@@ -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>

+ 0
- 113
shadowsocks-csharp/FodyWeavers.xsd View File

@@ -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>

+ 0
- 13
shadowsocks-csharp/Localization/LocalizationProvider.cs View File

@@ -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);
}
}
}

+ 0
- 244
shadowsocks-csharp/Properties/Resources.Designer.cs View File

@@ -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 &apos;javascript&apos; 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 &lt; __RULES__.length; i++) {
/// var s = __RULES__[i];
/// if (s.substring(0, 2) == &quot;||&quot;) s += &quot;^&quot;;
/// rules.push(s);
///}
///
///for (var i = 0; i &lt; [rest of string was truncated]&quot;;.
/// </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,,,,,,
///&quot;#You can find it by search &quot;&quot;Current language is:&quot;&quot;&quot;,,,,,,
///#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]&quot;;.
/// </summary>
public static string i18n_csv {
get {
return ResourceManager.GetString("i18n_csv", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
///&lt;!-- Warning: Configuration may reset after shadowsocks upgrade. --&gt;
///&lt;!-- If you messed it up, delete this file and Shadowsocks will create a new one. --&gt;
///&lt;nlog xmlns=&quot;http://www.nlog-project.org/schemas/NLog.xsd&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&gt;
/// &lt;targets&gt;
/// &lt;!-- This line is managed by Shadowsocks. Do not modify it unless you know what you are doing.--&gt;
/// &lt;target name=&quot;file&quot; xsi:type=&quot;File&quot; fileName=&quot;ss_win_temp\shadowsocks.log&quot; writ [rest of string was truncated]&quot;;.
/// </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);
}
}
}
}

+ 0
- 86
shadowsocks-csharp/Properties/Settings.Designer.cs View File

@@ -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;
}
}
}
}

+ 0
- 21
shadowsocks-csharp/Properties/Settings.settings View File

@@ -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>

+ 25
- 0
shadowsocks-windows.sln View File

@@ -12,6 +12,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ShadowsocksTest", "test\Sha
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7BD54B24-BBD7-4DD8-99EF-DAEE6684B673}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.gitignore = .gitignore
appveyor.yml = appveyor.yml
appveyor.yml.obsolete = appveyor.yml.obsolete
@@ -23,6 +24,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
README.md = README.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shadowsocks.Common", "Shadowsocks.Common\Shadowsocks.Common.csproj", "{61AF0616-8E90-46C4-908A-E182A5001AB5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shadowsocks.Crypto", "Shadowsocks.Crypto\Shadowsocks.Crypto.csproj", "{AD8974F4-EFDC-4EC5-A147-54CD4934D295}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shadowsocks", "Shadowsocks\Shadowsocks.csproj", "{85C2FC93-91F0-454F-AF0A-522FCD20827A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shadowsocks.WPF", "Shadowsocks.WPF\Shadowsocks.WPF.csproj", "{EA1FB2D4-B5A7-47A6-B097-2F4D29E23010}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -37,6 +46,22 @@ Global
{45913187-0685-4903-B250-DCEF0479CD86}.Debug|Any CPU.Build.0 = Debug|Any CPU
{45913187-0685-4903-B250-DCEF0479CD86}.Release|Any CPU.ActiveCfg = Release|Any CPU
{45913187-0685-4903-B250-DCEF0479CD86}.Release|Any CPU.Build.0 = Release|Any CPU
{61AF0616-8E90-46C4-908A-E182A5001AB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{61AF0616-8E90-46C4-908A-E182A5001AB5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{61AF0616-8E90-46C4-908A-E182A5001AB5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{61AF0616-8E90-46C4-908A-E182A5001AB5}.Release|Any CPU.Build.0 = Release|Any CPU
{AD8974F4-EFDC-4EC5-A147-54CD4934D295}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AD8974F4-EFDC-4EC5-A147-54CD4934D295}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AD8974F4-EFDC-4EC5-A147-54CD4934D295}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AD8974F4-EFDC-4EC5-A147-54CD4934D295}.Release|Any CPU.Build.0 = Release|Any CPU
{85C2FC93-91F0-454F-AF0A-522FCD20827A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{85C2FC93-91F0-454F-AF0A-522FCD20827A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{85C2FC93-91F0-454F-AF0A-522FCD20827A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{85C2FC93-91F0-454F-AF0A-522FCD20827A}.Release|Any CPU.Build.0 = Release|Any CPU
{EA1FB2D4-B5A7-47A6-B097-2F4D29E23010}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EA1FB2D4-B5A7-47A6-B097-2F4D29E23010}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EA1FB2D4-B5A7-47A6-B097-2F4D29E23010}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EA1FB2D4-B5A7-47A6-B097-2F4D29E23010}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE


Loading…
Cancel
Save