Compare commits

...
20 Commits
Author SHA1 Message Date
celeron533 08f06f7177 Update CHANGES and bump version 2017-09-09 20:24:50 +08:00
celeron533 cb3afafd54 Update readme.md 2017-09-08 21:54:38 +08:00
celeron533 05df449826 Add notification message 2017-09-05 22:31:54 +08:00
celeron533 d0e692a491 Translation for SIP003 2017-08-31 20:28:45 +08:00
Allen Zhu b0a2c2735b Merge pull request #1336 from rwasef1830/use_job_for_sip003_plugin
Use job objects with SIP003 plugin to avoid lingering processes if app is killed
2017-08-31 19:58:07 +08:00
Raif Atef f239244af2 Early start SIP003 plugins when reloading servers to avoid delay on first packet. 2017-08-27 09:11:41 +02:00
Raif Atef a316b95f45 Logging for SIP003 start failure. 2017-08-26 21:22:53 +02:00
Raif Atef cf5de91acb Use job objects with SIP003 plugin to avoid lingering processes if app is killed. 2017-08-23 12:36:32 +02:00
Allen Zhu 71120e5c3e Merge pull request #1298 from rwasef1830/sip003
SIP002 and SIP003 support.
2017-08-21 20:25:34 +08:00
Raif Atef caa96ad334 Fix port range check and move Sip003Plugin. 2017-08-17 11:11:06 +02:00
Raif Atef f04b497d79 SIP002 and SIP003 support 2017-08-14 11:48:41 +02:00
celeron533 ed31a3cab0 Update CHANGES and bump version 2017-08-09 19:20:50 +08:00
celeron533 081bbaf011 Fix #1301. Configuration is not fully initialized and cause NullReferenceException crash 2017-08-06 22:48:02 +08:00
celeron533 0251130fa5 Socket.ConnectAsync() does not call SocketAsyncEventArgs.Completed when operation completed synchronously.
#1273
2017-08-06 17:17:32 +08:00
Jacob Zuo f0b196c8c3 Fix "4.0.4 launch exception" error (PR #1232) 2017-08-06 12:06:29 +08:00
celeron533 057b148092 Merge pull request #1227 from gitzhuoer/patch-2
Add .NET Framework 4.6.2 requirement
2017-07-10 19:47:42 +08:00
Zhuoer Dong 101c33d0f1 Update README.md 2017-07-10 19:41:48 +08:00
Syrone Wong bbfc5d332d Update CHANGES and bump version
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2017-06-01 15:55:55 +08:00
Syrone Wong 5d75e19c26 prefer to use aes-256-gcm in libsodium
which is hardware accelerated compared to AES-GCM in mbedtls

We have to drop this commit when mbedtls support hw-accelerated GCM
when compiling with MSVC

Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2017-05-31 10:04:00 +08:00
Syrone Wong 816651ebdc Save user wininet settings as another config file 2017-05-25 17:18:20 +08:00
24 changed files with 838 additions and 249 deletions
+12
View File
@@ -1,3 +1,15 @@
4.0.6 2017-09-09
- SIP002 support
- SIP003 support
4.0.5 2017-08-09
- Fix crash when user-wininet.json fail to parse. (#1178)
- Bug fixes and improvements.
4.0.4 2017-06-01
- Save user wininet settings as user-wininet.json
- Improve performance of aes-256-gcm
4.0.2 2017-05-19
- Fix legacy key derivation
- Bug fixes and improvements
+16 -4
View File
@@ -13,11 +13,16 @@ Shadowsocks for Windows
4. Supports HTTP proxy
5. Supports server auto switching
6. Supports UDP relay (see Usage)
7. Supports plugins
#### Download
Download the [latest release].
#### Requirements
Microsoft [.NET Framework 4.6.2] or higher.
#### Basic
1. Find Shadowsocks icon in the notification tray
@@ -54,11 +59,17 @@ If you want to manage multiple servers using other tools like SwitchyOmega,
you can start multiple Shadowsocks instances. To avoid configuration conflicts,
copy Shadowsocks to a new directory and choose a different local port.
#### Plugins
If you would like to connect to server via a plugin, please set the plugin's
path (relative or absolute) on Edit Servers form.
Note: Forward Proxy will not be used while a plugin is enabled.
#### Global hotkeys
Hotkeys are NOT registered automatically. You should re-register all hotkeys after
restarting Shadowsocks. If you are using multiple instances of Shadowsocks,
you must set different key combination for other instances.
you must set different key combination for each instance.
##### How to input?
@@ -98,11 +109,12 @@ Please visit [Servers] for more information.
GPLv3
[Appveyor]: https://ci.appveyor.com/project/wongsyrone/shadowsocks-windows-yqdou
[Build Status]: https://ci.appveyor.com/api/projects/status/yieb7lo96irmuc28/branch/master?svg=true
[Appveyor]: https://ci.appveyor.com/project/celeron533/shadowsocks-windows
[Build Status]: https://ci.appveyor.com/api/projects/status/tfw57q6eecippsl5/branch/master?svg=true
[latest release]: https://github.com/shadowsocks/shadowsocks-csharp/releases
[GFWList]: https://github.com/gfwlist/gfwlist
[Servers]: https://github.com/shadowsocks/shadowsocks/wiki/Ports-and-Clients#linux--server-side
[中文说明]: https://github.com/shadowsocks/shadowsocks-windows/wiki/Shadowsocks-Windows-%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E
[.NET Framework 4.6.2]: https://www.microsoft.com/en-US/download/details.aspx?id=53344
[Visual Studio 2015]: https://www.visualstudio.com/downloads/
[.NET Framework 4.6.2 Developer Pack]: https://www.microsoft.com/download/details.aspx?id=53321
[.NET Framework 4.6.2 Developer Pack]: https://www.microsoft.com/download/details.aspx?id=53321
@@ -0,0 +1,140 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using Shadowsocks.Model;
using Shadowsocks.Util.ProcessManagement;
namespace Shadowsocks.Controller.Service
{
// https://github.com/shadowsocks/shadowsocks-org/wiki/Plugin
public sealed class Sip003Plugin : IDisposable
{
public IPEndPoint LocalEndPoint { get; private set; }
public int ProcessId => _started ? _pluginProcess.Id : 0;
private readonly object _startProcessLock = new object();
private readonly Job _pluginJob;
private readonly Process _pluginProcess;
private bool _started;
private bool _disposed;
public static Sip003Plugin CreateIfConfigured(Server server)
{
if (server == null)
{
throw new ArgumentNullException(nameof(server));
}
if (string.IsNullOrWhiteSpace(server.plugin))
{
return null;
}
return new Sip003Plugin(server.plugin, server.plugin_opts, server.server, server.server_port);
}
private Sip003Plugin(string plugin, string pluginOpts, string serverAddress, int serverPort)
{
if (plugin == null) throw new ArgumentNullException(nameof(plugin));
if (string.IsNullOrWhiteSpace(serverAddress))
{
throw new ArgumentException("Value cannot be null or whitespace.", nameof(serverAddress));
}
if ((ushort)serverPort != serverPort)
{
throw new ArgumentOutOfRangeException("serverPort");
}
var appPath = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().GetName().CodeBase).LocalPath);
_pluginProcess = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = plugin,
UseShellExecute = false,
CreateNoWindow = true,
ErrorDialog = false,
WindowStyle = ProcessWindowStyle.Hidden,
WorkingDirectory = appPath ?? Environment.CurrentDirectory,
Environment =
{
["SS_REMOTE_HOST"] = serverAddress,
["SS_REMOTE_PORT"] = serverPort.ToString(),
["SS_PLUGIN_OPTIONS"] = pluginOpts
}
}
};
_pluginJob = new Job();
}
public bool StartIfNeeded()
{
if (_disposed)
{
throw new ObjectDisposedException(GetType().FullName);
}
lock (_startProcessLock)
{
if (_started && !_pluginProcess.HasExited)
{
return false;
}
var localPort = GetNextFreeTcpPort();
LocalEndPoint = new IPEndPoint(IPAddress.Loopback, localPort);
_pluginProcess.StartInfo.Environment["SS_LOCAL_HOST"] = LocalEndPoint.Address.ToString();
_pluginProcess.StartInfo.Environment["SS_LOCAL_PORT"] = LocalEndPoint.Port.ToString();
_pluginProcess.Start();
_pluginJob.AddProcess(_pluginProcess.Handle);
_started = true;
}
return true;
}
static int GetNextFreeTcpPort()
{
var l = new TcpListener(IPAddress.Loopback, 0);
l.Start();
int port = ((IPEndPoint)l.LocalEndpoint).Port;
l.Stop();
return port;
}
public void Dispose()
{
if (_disposed)
{
return;
}
try
{
if (!_pluginProcess.HasExited)
{
_pluginProcess.Kill();
_pluginProcess.WaitForExit();
}
}
catch (Exception) { }
finally
{
try
{
_pluginProcess.Dispose();
_pluginJob.Dispose();
}
catch (Exception) { }
_disposed = true;
}
}
}
}
@@ -570,7 +570,15 @@ namespace Shadowsocks.Controller
// Setting up proxy
IProxy remote;
EndPoint proxyEP = null;
if (_config.proxy.useProxy)
EndPoint serverEP = SocketUtil.GetEndPoint(_server.server, _server.server_port);
EndPoint pluginEP = _controller.GetPluginLocalEndPointIfConfigured(_server);
if (pluginEP != null)
{
serverEP = pluginEP;
remote = new DirectConnect();
}
else if (_config.proxy.useProxy)
{
switch (_config.proxy.proxyType)
{
@@ -607,7 +615,7 @@ namespace Shadowsocks.Controller
proxyTimer.Enabled = true;
proxyTimer.Session = session;
proxyTimer.DestEndPoint = SocketUtil.GetEndPoint(_server.server, _server.server_port);
proxyTimer.DestEndPoint = serverEP;
proxyTimer.Server = _server;
_proxyConnected = false;
@@ -24,7 +24,7 @@ namespace Shadowsocks.Controller
public string LatestVersionLocalName;
public event EventHandler CheckUpdateCompleted;
public const string Version = "4.0.2";
public const string Version = "4.0.6";
private class CheckUpdateTimer : System.Timers.Timer
{
@@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Net;
@@ -14,6 +15,8 @@ using Shadowsocks.Model;
using Shadowsocks.Properties;
using Shadowsocks.Util;
using System.Linq;
using Shadowsocks.Controller.Service;
using Shadowsocks.Proxy;
namespace Shadowsocks.Controller
{
@@ -33,6 +36,8 @@ namespace Shadowsocks.Controller
private StrategyManager _strategyManager;
private PrivoxyRunner privoxyRunner;
private GFWListUpdater gfwListUpdater;
private readonly ConcurrentDictionary<Server, Sip003Plugin> _pluginsByServer;
public AvailabilityStatistics availabilityStatistics = AvailabilityStatistics.Instance;
public StatisticsStrategyConfiguration StatisticsConfiguration { get; private set; }
@@ -44,8 +49,6 @@ namespace Shadowsocks.Controller
private bool stopped = false;
private bool _systemProxyIsDirty = false;
public class PathEventArgs : EventArgs
{
public string Path;
@@ -81,6 +84,7 @@ namespace Shadowsocks.Controller
_config = Configuration.Load();
StatisticsConfiguration = StatisticsStrategyConfiguration.Load();
_strategyManager = new StrategyManager(this);
_pluginsByServer = new ConcurrentDictionary<Server, Sip003Plugin>();
StartReleasingMemory();
StartTrafficStatistics(61);
}
@@ -146,6 +150,31 @@ namespace Shadowsocks.Controller
return GetCurrentServer();
}
public EndPoint GetPluginLocalEndPointIfConfigured(Server server)
{
var plugin = _pluginsByServer.GetOrAdd(server, Sip003Plugin.CreateIfConfigured);
if (plugin == null)
{
return null;
}
try
{
if (plugin.StartIfNeeded())
{
Logging.Info(
$"Started SIP003 plugin for {server.Identifier()} on {plugin.LocalEndPoint} - PID: {plugin.ProcessId}");
}
}
catch (Exception ex)
{
Logging.Error("Failed to start SIP003 plugin: " + ex.Message);
throw;
}
return plugin.LocalEndPoint;
}
public void SaveServers(List<Server> servers, int localPort)
{
_config.configs = servers;
@@ -261,6 +290,7 @@ namespace Shadowsocks.Controller
{
_listener.Stop();
}
StopPlugins();
if (privoxyRunner != null)
{
privoxyRunner.Stop();
@@ -272,6 +302,15 @@ namespace Shadowsocks.Controller
Encryption.RNG.Close();
}
private void StopPlugins()
{
foreach (var serverAndPlugin in _pluginsByServer)
{
serverAndPlugin.Value?.Dispose();
}
_pluginsByServer.Clear();
}
public void TouchPACFile()
{
string pacFilename = _pacServer.TouchPACFile();
@@ -299,13 +338,41 @@ namespace Shadowsocks.Controller
public static string GetQRCode(Server server)
{
string tag = string.Empty;
string parts = $"{server.method}:{server.password}@{server.server}:{server.server_port}";
string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts));
if(!server.remarks.IsNullOrEmpty())
string url = string.Empty;
if (string.IsNullOrWhiteSpace(server.plugin))
{
// For backwards compatiblity, if no plugin, use old url format
string parts = $"{server.method}:{server.password}@{server.server}:{server.server_port}";
string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts));
url = base64;
}
else
{
// SIP002
string parts = $"{server.method}:{server.password}";
string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts));
string websafeBase64 = base64.Replace('+', '-').Replace('/', '_').TrimEnd('=');
string pluginPart = server.plugin;
if (!string.IsNullOrWhiteSpace(server.plugin_opts))
{
pluginPart += ";" + server.plugin_opts;
}
url = string.Format(
"{0}@{1}:{2}/?plugin={3}",
websafeBase64,
HttpUtility.UrlEncode(server.server, Encoding.UTF8),
server.server_port,
HttpUtility.UrlEncode(pluginPart, Encoding.UTF8));
}
if (!server.remarks.IsNullOrEmpty())
{
tag = $"#{HttpUtility.UrlEncode(server.remarks, Encoding.UTF8)}";
}
return $"ss://{base64}{tag}";
return $"ss://{url}{tag}";
}
public void UpdatePACFromGFWList()
@@ -423,6 +490,8 @@ namespace Shadowsocks.Controller
protected void Reload()
{
StopPlugins();
Encryption.RNG.Reload();
// some logic in configuration updated the config when saving, we need to read it again
_config = Configuration.Load();
@@ -465,6 +534,7 @@ namespace Shadowsocks.Controller
strategy.ReloadServers();
}
StartPlugins();
privoxyRunner.Start(_config);
TCPRelay tcpRelay = new TCPRelay(this, _config);
@@ -502,6 +572,15 @@ namespace Shadowsocks.Controller
Utils.ReleaseMemory(true);
}
private void StartPlugins()
{
foreach (var server in _config.configs)
{
// Early start plugin processes
GetPluginLocalEndPointIfConfigured(server);
}
}
protected void SaveConfig(Configuration newConfig)
{
Configuration.Save(newConfig);
@@ -510,20 +589,7 @@ namespace Shadowsocks.Controller
private void UpdateSystemProxy()
{
if (_config.enabled)
{
SystemProxy.Update(_config, false, _pacServer);
_systemProxyIsDirty = true;
}
else
{
// only switch it off if we have switched it on
if (_systemProxyIsDirty)
{
SystemProxy.Update(_config, false, _pacServer);
_systemProxyIsDirty = false;
}
}
SystemProxy.Update(_config, false, _pacServer);
}
private void pacServer_PACFileChanged(object sender, EventArgs e)
+3
View File
@@ -50,6 +50,8 @@ Server Addr=サーバーアドレス
Server Port=サーバーポート
Password=パスワード
Encryption=暗号化
Plugin=プラグイン
Plugin Options=プラグインのオプション
Proxy Port=プロキシポート
Remarks=付記
Timeout(Sec)=タイムアウト (秒)
@@ -66,6 +68,7 @@ Use Proxy=プロキシを利用する
Proxy Type=プロキシの種類
Proxy Addr=プロキシアドレス
Proxy Port=プロキシポート
If server has a plugin, proxy will not be used=サーバーにプラグインがある場合、プロキシは利用されません
# Log Form
Binary file not shown.
+3
View File
@@ -50,6 +50,8 @@ Server Addr=服务器地址
Server Port=服务器端口
Password=密码
Encryption=加密
Plugin=插件
Plugin Options=插件选项
Proxy Port=代理端口
Remarks=备注
Timeout(Sec)=超时(秒)
@@ -66,6 +68,7 @@ Use Proxy=使用代理
Proxy Type=代理类型
Proxy Addr=代理地址
Proxy Port=代理端口
If server has a plugin, proxy will not be used=若服务器含有插件,代理将不被使用
# Log Form
+3
View File
@@ -50,6 +50,8 @@ Server Addr=伺服器位址
Server Port=伺服器連接埠
Password=密碼
Encryption=加密
Plugin=插件
Plugin Options=插件選項
Proxy Port=Proxy 連接埠
Remarks=註解
Timeout(Sec)=逾時 (秒)
@@ -66,6 +68,7 @@ Use Proxy=使用 Proxy
Proxy Type=Proxy 類型
Proxy Addr=Proxy 位址
Proxy Port=Proxy 連接埠
If server has a plugin, proxy will not be used=若伺服器含有插件,Proxy 將不被使用
# Log Form
@@ -10,6 +10,7 @@ namespace Shadowsocks.Encryption.AEAD
: AEADEncryptor, IDisposable
{
private const int CIPHER_CHACHA20IETFPOLY1305 = 1;
private const int CIPHER_AES256GCM = 2;
private byte[] _sodiumEncSubkey;
private byte[] _sodiumDecSubkey;
@@ -24,6 +25,7 @@ namespace Shadowsocks.Encryption.AEAD
private static Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
{
{"chacha20-ietf-poly1305", new EncryptorInfo(32, 32, 12, 16, CIPHER_CHACHA20IETFPOLY1305)},
{"aes-256-gcm", new EncryptorInfo(32, 32, 12, 16, CIPHER_AES256GCM)},
};
public static List<string> SupportedCiphers()
@@ -63,6 +65,13 @@ namespace Shadowsocks.Encryption.AEAD
null, _encNonce,
_sodiumEncSubkey);
break;
case CIPHER_AES256GCM:
ret = Sodium.crypto_aead_aes256gcm_encrypt(ciphertext, ref encClen,
plaintext, (ulong)plen,
null, 0,
null, _encNonce,
_sodiumEncSubkey);
break;
default:
throw new System.Exception("not implemented");
}
@@ -91,6 +100,13 @@ namespace Shadowsocks.Encryption.AEAD
null, 0,
_decNonce, _sodiumDecSubkey);
break;
case CIPHER_AES256GCM:
ret = Sodium.crypto_aead_aes256gcm_decrypt(plaintext, ref decPlen,
null,
ciphertext, (ulong)clen,
null, 0,
_decNonce, _sodiumDecSubkey);
break;
default:
throw new System.Exception("not implemented");
}
@@ -14,6 +14,18 @@ namespace Shadowsocks.Encryption
static EncryptorFactory()
{
var AEADMbedTLSEncryptorSupportedCiphers = AEADMbedTLSEncryptor.SupportedCiphers();
var AEADSodiumEncryptorSupportedCiphers = AEADSodiumEncryptor.SupportedCiphers();
if (Sodium.AES256GCMAvailable)
{
// prefer to aes-256-gcm in libsodium
AEADMbedTLSEncryptorSupportedCiphers.Remove("aes-256-gcm");
}
else
{
AEADSodiumEncryptorSupportedCiphers.Remove("aes-256-gcm");
}
foreach (string method in StreamMbedTLSEncryptor.SupportedCiphers())
{
_registeredEncryptors.Add(method, typeof(StreamMbedTLSEncryptor));
@@ -22,11 +34,11 @@ namespace Shadowsocks.Encryption
{
_registeredEncryptors.Add(method, typeof(StreamSodiumEncryptor));
}
foreach (string method in AEADMbedTLSEncryptor.SupportedCiphers())
foreach (string method in AEADMbedTLSEncryptorSupportedCiphers)
{
_registeredEncryptors.Add(method, typeof(AEADMbedTLSEncryptor));
}
foreach (string method in AEADSodiumEncryptor.SupportedCiphers())
foreach (string method in AEADSodiumEncryptorSupportedCiphers)
{
_registeredEncryptors.Add(method, typeof(AEADSodiumEncryptor));
}
+16
View File
@@ -14,6 +14,8 @@ namespace Shadowsocks.Encryption
private static bool _initialized = false;
private static readonly object _initLock = new object();
public static bool AES256GCMAvailable { get; private set; } = false;
static Sodium()
{
string dllPath = Utils.GetTempPath(DLLNAME);
@@ -42,6 +44,9 @@ namespace Shadowsocks.Encryption
{
_initialized = true;
}
AES256GCMAvailable = crypto_aead_aes256gcm_is_available() == 1;
Logging.Debug($"sodium: AES256GCMAvailable is {AES256GCMAvailable}");
}
}
}
@@ -52,6 +57,9 @@ namespace Shadowsocks.Encryption
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
private static extern int sodium_init();
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
private static extern int crypto_aead_aes256gcm_is_available();
#region AEAD
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
@@ -65,6 +73,14 @@ namespace Shadowsocks.Encryption
public static extern int crypto_aead_chacha20poly1305_ietf_decrypt(byte[] m, ref ulong mlen_p,
byte[] nsec, byte[] c, ulong clen, byte[] ad, ulong adlen, byte[] npub, byte[] k);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int crypto_aead_aes256gcm_encrypt(byte[] c, ref ulong clen_p, byte[] m, ulong mlen,
byte[] ad, ulong adlen, byte[] nsec, byte[] npub, byte[] k);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int crypto_aead_aes256gcm_decrypt(byte[] m, ref ulong mlen_p, byte[] nsec, byte[] c,
ulong clen, byte[] ad, ulong adlen, byte[] npub, byte[] k);
#endregion
#region Stream
+4 -1
View File
@@ -89,7 +89,10 @@ namespace Shadowsocks.Model
configs = new List<Server>()
{
GetDefaultServer()
}
},
logViewer = new LogViewerConfig(),
proxy = new ProxyConfig(),
hotkey = new HotkeyConfig()
};
}
}
+90 -21
View File
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using Shadowsocks.Controller;
@@ -10,10 +10,6 @@ namespace Shadowsocks.Model
[Serializable]
public class Server
{
public static readonly Regex
UrlFinder = new Regex(@"ss://(?<base64>[A-Za-z0-9+-/=_]+)(?:#(?<tag>\S+))?", RegexOptions.IgnoreCase),
DetailsParser = new Regex(@"^((?<method>.+?):(?<password>.*)@(?<hostname>.+?):(?<port>\d+?))$", RegexOptions.IgnoreCase);
private const int DefaultServerTimeoutSec = 5;
public const int MaxServerTimeoutSec = 20;
@@ -21,6 +17,8 @@ namespace Shadowsocks.Model
public int server_port;
public string password;
public string method;
public string plugin;
public string plugin_opts;
public string remarks;
public int timeout;
@@ -65,6 +63,8 @@ namespace Shadowsocks.Model
server = "";
server_port = 8388;
method = "aes-256-cfb";
plugin = "";
plugin_opts = "";
password = "";
remarks = "";
timeout = DefaultServerTimeoutSec;
@@ -72,26 +72,95 @@ namespace Shadowsocks.Model
public static List<Server> GetServers(string ssURL)
{
var matches = UrlFinder.Matches(ssURL);
if (matches.Count <= 0) return null;
var serverUrls = ssURL.Split('\r', '\n');
List<Server> servers = new List<Server>();
foreach (Match match in matches)
foreach (string serverUrl in serverUrls)
{
Server tmp = new Server();
var base64 = match.Groups["base64"].Value;
var tag = match.Groups["tag"].Value;
if (!tag.IsNullOrEmpty())
if (string.IsNullOrWhiteSpace(serverUrl))
{
tmp.remarks = HttpUtility.UrlDecode(tag, Encoding.UTF8);
}
Match details = DetailsParser.Match(Encoding.UTF8.GetString(Convert.FromBase64String(
base64.PadRight(base64.Length + (4 - base64.Length % 4) % 4, '='))));
if (!details.Success)
continue;
tmp.method = details.Groups["method"].Value;
tmp.password = details.Groups["password"].Value;
tmp.server = details.Groups["hostname"].Value;
tmp.server_port = int.Parse(details.Groups["port"].Value);
}
Uri parsedUrl;
try
{
parsedUrl = new Uri(serverUrl);
}
catch (UriFormatException)
{
continue;
}
Server tmp = new Server
{
remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped)
};
string possiblyUnpaddedBase64 = parsedUrl.GetComponents(UriComponents.UserInfo, UriFormat.Unescaped);
bool isOldFormatUrl = possiblyUnpaddedBase64.Length == 0;
if (isOldFormatUrl)
{
int prefixLength = "ss://".Length;
int indexOfHashOrSlash = serverUrl.LastIndexOfAny(
new[] { '/', '#' },
serverUrl.Length - 1,
serverUrl.Length - prefixLength);
int substringLength = serverUrl.Length - prefixLength;
if (indexOfHashOrSlash >= 0)
{
substringLength = indexOfHashOrSlash - prefixLength;
}
possiblyUnpaddedBase64 = serverUrl.Substring(prefixLength, substringLength).TrimEnd('/');
}
else
{
// Web-safe base64 to normal base64
possiblyUnpaddedBase64 = possiblyUnpaddedBase64.Replace('-', '+').Replace('_', '/');
}
string base64 = possiblyUnpaddedBase64.PadRight(
possiblyUnpaddedBase64.Length + (4 - possiblyUnpaddedBase64.Length % 4) % 4,
'=');
string innerUserInfoOrUrl = Encoding.UTF8.GetString(Convert.FromBase64String(base64));
string userInfo;
if (isOldFormatUrl)
{
Uri innerUrl = new Uri("inner://" + innerUserInfoOrUrl);
userInfo = innerUrl.GetComponents(UriComponents.UserInfo, UriFormat.Unescaped);
tmp.server = innerUrl.GetComponents(UriComponents.Host, UriFormat.Unescaped);
tmp.server_port = innerUrl.Port;
}
else
{
userInfo = innerUserInfoOrUrl;
tmp.server = parsedUrl.GetComponents(UriComponents.Host, UriFormat.Unescaped);
tmp.server_port = parsedUrl.Port;
}
string[] userInfoParts = userInfo.Split(new[] { ':' }, 2);
if (userInfoParts.Length != 2)
{
continue;
}
tmp.method = userInfoParts[0];
tmp.password = userInfoParts[1];
NameValueCollection queryParameters = HttpUtility.ParseQueryString(parsedUrl.Query);
string[] pluginParts = HttpUtility.UrlDecode(queryParameters["plugin"] ?? "").Split(new[] { ';' }, 2);
if (pluginParts.Length > 0)
{
tmp.plugin = pluginParts[0] ?? "";
}
if (pluginParts.Length > 1)
{
tmp.plugin_opts = pluginParts[1] ?? "";
}
servers.Add(tmp);
}
@@ -0,0 +1,27 @@
using System;
namespace Shadowsocks.Model
{
/*
* Data come from WinINET
*/
[Serializable]
public class SysproxyConfig
{
public bool UserSettingsRecorded;
public string Flags;
public string ProxyServer;
public string BypassList;
public string PacUrl;
public SysproxyConfig()
{
UserSettingsRecorded = false;
Flags = "1";
ProxyServer = "";
BypassList = "";
PacUrl = "";
}
}
}
@@ -42,7 +42,10 @@ namespace Shadowsocks.Util.Sockets
arg.Completed += OnTcpConnectCompleted;
arg.UserToken = new TcpUserToken(callback, state);
Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, arg);
if(!Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, arg))
{
OnTcpConnectCompleted(this, arg);
}
}
private class FakeAsyncResult : IAsyncResult
+66 -31
View File
@@ -1,15 +1,19 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using Shadowsocks.Controller;
using Shadowsocks.Properties;
using Shadowsocks.Model;
using System.Text;
using Newtonsoft.Json;
namespace Shadowsocks.Util.SystemProxy
{
public static class Sysproxy
{
private static bool _userSettingsRecorded = false;
private const string _userWininetConfigFile = "user-wininet.json";
private static string _queryStr;
// In general, this won't change
// format:
@@ -17,7 +21,7 @@ namespace Shadowsocks.Util.SystemProxy
// <proxy-server><CR-LF>
// <bypass-list><CR-LF>
// <pac-url>
private static string[] _userSettings = new string[4];
private static SysproxyConfig _userSettings = null;
enum RET_ERRORS : int
{
@@ -31,8 +35,7 @@ namespace Shadowsocks.Util.SystemProxy
static Sysproxy()
{
try
{
try {
FileManager.UncompressFile(Utils.GetTempPath("sysproxy.exe"),
Environment.Is64BitOperatingSystem ? Resources.sysproxy64_exe : Resources.sysproxy_exe);
}
@@ -44,16 +47,16 @@ namespace Shadowsocks.Util.SystemProxy
public static void SetIEProxy(bool enable, bool global, string proxyServer, string pacURL)
{
string str;
if (_userSettingsRecorded == false)
Read();
if (!_userSettings.UserSettingsRecorded)
{
// record user settings
ExecSysproxy("query", out str);
ParseQueryStr(str);
_userSettingsRecorded = true;
ExecSysproxy("query");
ParseQueryStr(_queryStr);
}
string arguments;
string arguments;
if (enable)
{
arguments = global
@@ -63,20 +66,21 @@ namespace Shadowsocks.Util.SystemProxy
else
{
// restore user settings
var flags = _userSettings[0];
var proxy_server = _userSettings[1] ?? "-";
var bypass_list = _userSettings[2] ?? "-";
var pac_url = _userSettings[3] ?? "-";
var flags = _userSettings.Flags;
var proxy_server = _userSettings.ProxyServer ?? "-";
var bypass_list = _userSettings.BypassList ?? "-";
var pac_url = _userSettings.PacUrl ?? "-";
arguments = $"set {flags} {proxy_server} {bypass_list} {pac_url}";
// have to get new settings
_userSettingsRecorded = false;
_userSettings.UserSettingsRecorded = false;
}
ExecSysproxy(arguments, out str);
Save();
ExecSysproxy(arguments);
}
private static void ExecSysproxy(string arguments, out string queryStr)
private static void ExecSysproxy(string arguments)
{
using (var process = new Process())
{
@@ -107,24 +111,55 @@ namespace Shadowsocks.Util.SystemProxy
throw new ProxyException(stderr);
}
if (arguments == "query" && stdout.IsNullOrWhiteSpace())
{
// we cannot get user settings
throw new ProxyException("failed to query wininet settings");
if (arguments == "query") {
if (stdout.IsNullOrWhiteSpace() || stdout.IsNullOrEmpty()) {
// we cannot get user settings
throw new ProxyException("failed to query wininet settings");
}
_queryStr = stdout;
}
queryStr = stdout;
}
}
private static void Save()
{
try {
using (StreamWriter sw = new StreamWriter(File.Open(_userWininetConfigFile, FileMode.Create))) {
string jsonString = JsonConvert.SerializeObject(_userSettings, Formatting.Indented);
sw.Write(jsonString);
sw.Flush();
}
} catch (IOException e) {
Logging.LogUsefulException(e);
}
}
private static void Read()
{
try {
string configContent = File.ReadAllText(_userWininetConfigFile);
_userSettings = JsonConvert.DeserializeObject<SysproxyConfig>(configContent);
} catch(Exception) {
// Suppress all exceptions. finally block will initialize new user config settings.
} finally {
if (_userSettings == null) _userSettings = new SysproxyConfig();
}
}
private static void ParseQueryStr(string str)
{
_userSettings = str.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
for (var i = 0; i < 4; i++)
{
// handle output from WinINET
if (_userSettings[i] == "(null)")
_userSettings[i] = null;
}
string[] userSettingsArr = str.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
_userSettings.Flags = userSettingsArr[0];
// handle output from WinINET
if (userSettingsArr[1] == "(null)") _userSettings.ProxyServer = null;
else _userSettings.ProxyServer = userSettingsArr[1];
if (userSettingsArr[2] == "(null)") _userSettings.BypassList = null;
else _userSettings.BypassList = userSettingsArr[2];
if (userSettingsArr[3] == "(null)") _userSettings.PacUrl = null;
else _userSettings.PacUrl = userSettingsArr[3];
_userSettings.UserSettingsRecorded = true;
}
}
}
}
+107 -54
View File
@@ -29,6 +29,8 @@
private void InitializeComponent()
{
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.PluginOptionsLabel = new System.Windows.Forms.Label();
this.PluginTextBox = new System.Windows.Forms.TextBox();
this.RemarksTextBox = new System.Windows.Forms.TextBox();
this.RemarksLabel = new System.Windows.Forms.Label();
this.IPLabel = new System.Windows.Forms.Label();
@@ -41,6 +43,8 @@
this.EncryptionSelect = new System.Windows.Forms.ComboBox();
this.TimeoutLabel = new System.Windows.Forms.Label();
this.TimeoutTextBox = new System.Windows.Forms.TextBox();
this.PluginLabel = new System.Windows.Forms.Label();
this.PluginOptionsTextBox = new System.Windows.Forms.TextBox();
this.panel2 = new System.Windows.Forms.Panel();
this.OKButton = new System.Windows.Forms.Button();
this.MyCancelButton = new System.Windows.Forms.Button();
@@ -74,8 +78,10 @@
this.tableLayoutPanel1.ColumnCount = 2;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.Controls.Add(this.RemarksTextBox, 1, 5);
this.tableLayoutPanel1.Controls.Add(this.RemarksLabel, 0, 5);
this.tableLayoutPanel1.Controls.Add(this.PluginOptionsLabel, 0, 5);
this.tableLayoutPanel1.Controls.Add(this.PluginTextBox, 1, 4);
this.tableLayoutPanel1.Controls.Add(this.RemarksTextBox, 1, 7);
this.tableLayoutPanel1.Controls.Add(this.RemarksLabel, 0, 7);
this.tableLayoutPanel1.Controls.Add(this.IPLabel, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.ServerPortLabel, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.PasswordLabel, 0, 2);
@@ -84,13 +90,15 @@
this.tableLayoutPanel1.Controls.Add(this.PasswordTextBox, 1, 2);
this.tableLayoutPanel1.Controls.Add(this.EncryptionLabel, 0, 3);
this.tableLayoutPanel1.Controls.Add(this.EncryptionSelect, 1, 3);
this.tableLayoutPanel1.Controls.Add(this.TimeoutLabel, 0, 6);
this.tableLayoutPanel1.Controls.Add(this.TimeoutTextBox, 1, 6);
this.tableLayoutPanel1.Controls.Add(this.TimeoutLabel, 0, 8);
this.tableLayoutPanel1.Controls.Add(this.TimeoutTextBox, 1, 8);
this.tableLayoutPanel1.Controls.Add(this.PluginLabel, 0, 4);
this.tableLayoutPanel1.Controls.Add(this.PluginOptionsTextBox, 1, 5);
this.tableLayoutPanel1.Location = new System.Drawing.Point(8, 21);
this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(3);
this.tableLayoutPanel1.RowCount = 7;
this.tableLayoutPanel1.RowCount = 9;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
@@ -98,26 +106,48 @@
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.Size = new System.Drawing.Size(255, 167);
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.Size = new System.Drawing.Size(253, 215);
this.tableLayoutPanel1.TabIndex = 0;
//
// PluginOptionsLabel
//
this.PluginOptionsLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.PluginOptionsLabel.AutoSize = true;
this.PluginOptionsLabel.Location = new System.Drawing.Point(6, 140);
this.PluginOptionsLabel.Name = "PluginOptionsLabel";
this.PluginOptionsLabel.Size = new System.Drawing.Size(75, 13);
this.PluginOptionsLabel.TabIndex = 15;
this.PluginOptionsLabel.Text = "Plugin Options";
//
// PluginTextBox
//
this.PluginTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.PluginTextBox.Location = new System.Drawing.Point(87, 111);
this.PluginTextBox.MaxLength = 256;
this.PluginTextBox.Name = "PluginTextBox";
this.PluginTextBox.Size = new System.Drawing.Size(160, 20);
this.PluginTextBox.TabIndex = 4;
this.PluginTextBox.WordWrap = false;
//
// RemarksTextBox
//
this.RemarksTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.RemarksTextBox.Location = new System.Drawing.Point(89, 113);
this.RemarksTextBox.Location = new System.Drawing.Point(87, 163);
this.RemarksTextBox.MaxLength = 32;
this.RemarksTextBox.Name = "RemarksTextBox";
this.RemarksTextBox.Size = new System.Drawing.Size(160, 21);
this.RemarksTextBox.TabIndex = 4;
this.RemarksTextBox.Size = new System.Drawing.Size(160, 20);
this.RemarksTextBox.TabIndex = 6;
this.RemarksTextBox.WordWrap = false;
//
// RemarksLabel
//
this.RemarksLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.RemarksLabel.AutoSize = true;
this.RemarksLabel.Location = new System.Drawing.Point(36, 117);
this.RemarksLabel.Location = new System.Drawing.Point(32, 166);
this.RemarksLabel.Name = "RemarksLabel";
this.RemarksLabel.Size = new System.Drawing.Size(47, 12);
this.RemarksLabel.Size = new System.Drawing.Size(49, 13);
this.RemarksLabel.TabIndex = 9;
this.RemarksLabel.Text = "Remarks";
//
@@ -125,9 +155,9 @@
//
this.IPLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.IPLabel.AutoSize = true;
this.IPLabel.Location = new System.Drawing.Point(24, 10);
this.IPLabel.Location = new System.Drawing.Point(30, 9);
this.IPLabel.Name = "IPLabel";
this.IPLabel.Size = new System.Drawing.Size(59, 12);
this.IPLabel.Size = new System.Drawing.Size(51, 13);
this.IPLabel.TabIndex = 0;
this.IPLabel.Text = "Server IP";
//
@@ -135,9 +165,9 @@
//
this.ServerPortLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.ServerPortLabel.AutoSize = true;
this.ServerPortLabel.Location = new System.Drawing.Point(12, 37);
this.ServerPortLabel.Location = new System.Drawing.Point(21, 35);
this.ServerPortLabel.Name = "ServerPortLabel";
this.ServerPortLabel.Size = new System.Drawing.Size(71, 12);
this.ServerPortLabel.Size = new System.Drawing.Size(60, 13);
this.ServerPortLabel.TabIndex = 1;
this.ServerPortLabel.Text = "Server Port";
//
@@ -145,39 +175,39 @@
//
this.PasswordLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.PasswordLabel.AutoSize = true;
this.PasswordLabel.Location = new System.Drawing.Point(30, 64);
this.PasswordLabel.Location = new System.Drawing.Point(28, 61);
this.PasswordLabel.Name = "PasswordLabel";
this.PasswordLabel.Size = new System.Drawing.Size(53, 12);
this.PasswordLabel.Size = new System.Drawing.Size(53, 13);
this.PasswordLabel.TabIndex = 2;
this.PasswordLabel.Text = "Password";
//
// IPTextBox
//
this.IPTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.IPTextBox.Location = new System.Drawing.Point(89, 6);
this.IPTextBox.Location = new System.Drawing.Point(87, 6);
this.IPTextBox.MaxLength = 512;
this.IPTextBox.Name = "IPTextBox";
this.IPTextBox.Size = new System.Drawing.Size(160, 21);
this.IPTextBox.Size = new System.Drawing.Size(160, 20);
this.IPTextBox.TabIndex = 0;
this.IPTextBox.WordWrap = false;
//
// ServerPortTextBox
//
this.ServerPortTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.ServerPortTextBox.Location = new System.Drawing.Point(89, 33);
this.ServerPortTextBox.Location = new System.Drawing.Point(87, 32);
this.ServerPortTextBox.MaxLength = 10;
this.ServerPortTextBox.Name = "ServerPortTextBox";
this.ServerPortTextBox.Size = new System.Drawing.Size(160, 21);
this.ServerPortTextBox.Size = new System.Drawing.Size(160, 20);
this.ServerPortTextBox.TabIndex = 1;
this.ServerPortTextBox.WordWrap = false;
//
// PasswordTextBox
//
this.PasswordTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.PasswordTextBox.Location = new System.Drawing.Point(89, 60);
this.PasswordTextBox.Location = new System.Drawing.Point(87, 58);
this.PasswordTextBox.MaxLength = 256;
this.PasswordTextBox.Name = "PasswordTextBox";
this.PasswordTextBox.Size = new System.Drawing.Size(160, 21);
this.PasswordTextBox.Size = new System.Drawing.Size(160, 20);
this.PasswordTextBox.TabIndex = 2;
this.PasswordTextBox.UseSystemPasswordChar = true;
this.PasswordTextBox.WordWrap = false;
@@ -186,9 +216,9 @@
//
this.EncryptionLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.EncryptionLabel.AutoSize = true;
this.EncryptionLabel.Location = new System.Drawing.Point(18, 91);
this.EncryptionLabel.Location = new System.Drawing.Point(24, 88);
this.EncryptionLabel.Name = "EncryptionLabel";
this.EncryptionLabel.Size = new System.Drawing.Size(65, 12);
this.EncryptionLabel.Size = new System.Drawing.Size(57, 13);
this.EncryptionLabel.TabIndex = 8;
this.EncryptionLabel.Text = "Encryption";
//
@@ -199,7 +229,7 @@
this.EncryptionSelect.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.EncryptionSelect.FormattingEnabled = true;
this.EncryptionSelect.ImeMode = System.Windows.Forms.ImeMode.NoControl;
this.EncryptionSelect.ItemHeight = 12;
this.EncryptionSelect.ItemHeight = 13;
this.EncryptionSelect.Items.AddRange(new object[] {
"rc4-md5",
"salsa20",
@@ -219,30 +249,50 @@
"aes-192-gcm",
"aes-256-gcm",
"chacha20-ietf-poly1305"});
this.EncryptionSelect.Location = new System.Drawing.Point(89, 87);
this.EncryptionSelect.Location = new System.Drawing.Point(87, 84);
this.EncryptionSelect.Name = "EncryptionSelect";
this.EncryptionSelect.Size = new System.Drawing.Size(160, 20);
this.EncryptionSelect.Size = new System.Drawing.Size(160, 21);
this.EncryptionSelect.TabIndex = 3;
//
// TimeoutLabel
//
this.TimeoutLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.TimeoutLabel.AutoSize = true;
this.TimeoutLabel.Location = new System.Drawing.Point(6, 144);
this.TimeoutLabel.Location = new System.Drawing.Point(11, 192);
this.TimeoutLabel.Name = "TimeoutLabel";
this.TimeoutLabel.RightToLeft = System.Windows.Forms.RightToLeft.No;
this.TimeoutLabel.Size = new System.Drawing.Size(77, 12);
this.TimeoutLabel.Size = new System.Drawing.Size(70, 13);
this.TimeoutLabel.TabIndex = 10;
this.TimeoutLabel.Text = "Timeout(Sec)";
//
// TimeoutTextBox
//
this.TimeoutTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.TimeoutTextBox.Location = new System.Drawing.Point(89, 140);
this.TimeoutTextBox.Location = new System.Drawing.Point(87, 189);
this.TimeoutTextBox.MaxLength = 5;
this.TimeoutTextBox.Name = "TimeoutTextBox";
this.TimeoutTextBox.Size = new System.Drawing.Size(160, 21);
this.TimeoutTextBox.TabIndex = 11;
this.TimeoutTextBox.Size = new System.Drawing.Size(160, 20);
this.TimeoutTextBox.TabIndex = 7;
//
// PluginLabel
//
this.PluginLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.PluginLabel.AutoSize = true;
this.PluginLabel.Location = new System.Drawing.Point(45, 114);
this.PluginLabel.Name = "PluginLabel";
this.PluginLabel.Size = new System.Drawing.Size(36, 13);
this.PluginLabel.TabIndex = 12;
this.PluginLabel.Text = "Plugin";
//
// PluginOptionsTextBox
//
this.PluginOptionsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.PluginOptionsTextBox.Location = new System.Drawing.Point(87, 137);
this.PluginOptionsTextBox.MaxLength = 256;
this.PluginOptionsTextBox.Name = "PluginOptionsTextBox";
this.PluginOptionsTextBox.Size = new System.Drawing.Size(160, 20);
this.PluginOptionsTextBox.TabIndex = 5;
this.PluginOptionsTextBox.WordWrap = false;
//
// panel2
//
@@ -262,7 +312,7 @@
this.OKButton.Margin = new System.Windows.Forms.Padding(3, 3, 3, 0);
this.OKButton.Name = "OKButton";
this.OKButton.Size = new System.Drawing.Size(75, 23);
this.OKButton.TabIndex = 12;
this.OKButton.TabIndex = 15;
this.OKButton.Text = "OK";
this.OKButton.UseVisualStyleBackColor = true;
this.OKButton.Click += new System.EventHandler(this.OKButton_Click);
@@ -275,7 +325,7 @@
this.MyCancelButton.Margin = new System.Windows.Forms.Padding(3, 3, 0, 0);
this.MyCancelButton.Name = "MyCancelButton";
this.MyCancelButton.Size = new System.Drawing.Size(75, 23);
this.MyCancelButton.TabIndex = 13;
this.MyCancelButton.TabIndex = 16;
this.MyCancelButton.Text = "Cancel";
this.MyCancelButton.UseVisualStyleBackColor = true;
this.MyCancelButton.Click += new System.EventHandler(this.CancelButton_Click);
@@ -287,7 +337,7 @@
this.DeleteButton.Margin = new System.Windows.Forms.Padding(3, 6, 0, 3);
this.DeleteButton.Name = "DeleteButton";
this.DeleteButton.Size = new System.Drawing.Size(80, 23);
this.DeleteButton.TabIndex = 9;
this.DeleteButton.TabIndex = 11;
this.DeleteButton.Text = "&Delete";
this.DeleteButton.UseVisualStyleBackColor = true;
this.DeleteButton.Click += new System.EventHandler(this.DeleteButton_Click);
@@ -299,7 +349,7 @@
this.AddButton.Margin = new System.Windows.Forms.Padding(0, 6, 3, 3);
this.AddButton.Name = "AddButton";
this.AddButton.Size = new System.Drawing.Size(80, 23);
this.AddButton.TabIndex = 8;
this.AddButton.TabIndex = 10;
this.AddButton.Text = "&Add";
this.AddButton.UseVisualStyleBackColor = true;
this.AddButton.Click += new System.EventHandler(this.AddButton_Click);
@@ -312,7 +362,7 @@
this.ServerGroupBox.Location = new System.Drawing.Point(178, 0);
this.ServerGroupBox.Margin = new System.Windows.Forms.Padding(12, 0, 0, 0);
this.ServerGroupBox.Name = "ServerGroupBox";
this.ServerGroupBox.Size = new System.Drawing.Size(266, 205);
this.ServerGroupBox.Size = new System.Drawing.Size(264, 252);
this.ServerGroupBox.TabIndex = 0;
this.ServerGroupBox.TabStop = false;
this.ServerGroupBox.Text = "Server";
@@ -321,12 +371,11 @@
//
this.ServersListBox.FormattingEnabled = true;
this.ServersListBox.IntegralHeight = false;
this.ServersListBox.ItemHeight = 12;
this.ServersListBox.Location = new System.Drawing.Point(0, 0);
this.ServersListBox.Margin = new System.Windows.Forms.Padding(0);
this.ServersListBox.Name = "ServersListBox";
this.ServersListBox.Size = new System.Drawing.Size(166, 148);
this.ServersListBox.TabIndex = 7;
this.ServersListBox.TabIndex = 9;
this.ServersListBox.SelectedIndexChanged += new System.EventHandler(this.ServersListBox_SelectedIndexChanged);
//
// tableLayoutPanel2
@@ -349,7 +398,7 @@
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.Size = new System.Drawing.Size(444, 301);
this.tableLayoutPanel2.Size = new System.Drawing.Size(442, 348);
this.tableLayoutPanel2.TabIndex = 7;
//
// tableLayoutPanel6
@@ -362,7 +411,7 @@
this.tableLayoutPanel6.Controls.Add(this.MoveDownButton, 1, 0);
this.tableLayoutPanel6.Controls.Add(this.MoveUpButton, 0, 0);
this.tableLayoutPanel6.Dock = System.Windows.Forms.DockStyle.Top;
this.tableLayoutPanel6.Location = new System.Drawing.Point(0, 269);
this.tableLayoutPanel6.Location = new System.Drawing.Point(0, 316);
this.tableLayoutPanel6.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel6.Name = "tableLayoutPanel6";
this.tableLayoutPanel6.RowCount = 1;
@@ -377,7 +426,7 @@
this.MoveDownButton.Margin = new System.Windows.Forms.Padding(3, 6, 0, 3);
this.MoveDownButton.Name = "MoveDownButton";
this.MoveDownButton.Size = new System.Drawing.Size(80, 23);
this.MoveDownButton.TabIndex = 11;
this.MoveDownButton.TabIndex = 14;
this.MoveDownButton.Text = "Move D&own";
this.MoveDownButton.UseVisualStyleBackColor = true;
this.MoveDownButton.Click += new System.EventHandler(this.MoveDownButton_Click);
@@ -389,7 +438,7 @@
this.MoveUpButton.Margin = new System.Windows.Forms.Padding(0, 6, 3, 3);
this.MoveUpButton.Name = "MoveUpButton";
this.MoveUpButton.Size = new System.Drawing.Size(80, 23);
this.MoveUpButton.TabIndex = 10;
this.MoveUpButton.TabIndex = 13;
this.MoveUpButton.Text = "Move &Up";
this.MoveUpButton.UseVisualStyleBackColor = true;
this.MoveUpButton.Click += new System.EventHandler(this.MoveUpButton_Click);
@@ -405,7 +454,7 @@
this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel5.Controls.Add(this.ProxyPortTextBox, 1, 0);
this.tableLayoutPanel5.Controls.Add(this.ProxyPortLabel, 0, 0);
this.tableLayoutPanel5.Location = new System.Drawing.Point(248, 205);
this.tableLayoutPanel5.Location = new System.Drawing.Point(256, 252);
this.tableLayoutPanel5.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel5.Name = "tableLayoutPanel5";
this.tableLayoutPanel5.Padding = new System.Windows.Forms.Padding(3);
@@ -415,26 +464,26 @@
this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 58F));
this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 58F));
this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 58F));
this.tableLayoutPanel5.Size = new System.Drawing.Size(196, 64);
this.tableLayoutPanel5.Size = new System.Drawing.Size(186, 64);
this.tableLayoutPanel5.TabIndex = 9;
//
// ProxyPortTextBox
//
this.ProxyPortTextBox.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.ProxyPortTextBox.Location = new System.Drawing.Point(77, 21);
this.ProxyPortTextBox.Location = new System.Drawing.Point(67, 22);
this.ProxyPortTextBox.MaxLength = 10;
this.ProxyPortTextBox.Name = "ProxyPortTextBox";
this.ProxyPortTextBox.Size = new System.Drawing.Size(113, 21);
this.ProxyPortTextBox.TabIndex = 6;
this.ProxyPortTextBox.Size = new System.Drawing.Size(113, 20);
this.ProxyPortTextBox.TabIndex = 8;
this.ProxyPortTextBox.WordWrap = false;
//
// ProxyPortLabel
//
this.ProxyPortLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.ProxyPortLabel.AutoSize = true;
this.ProxyPortLabel.Location = new System.Drawing.Point(6, 26);
this.ProxyPortLabel.Location = new System.Drawing.Point(6, 25);
this.ProxyPortLabel.Name = "ProxyPortLabel";
this.ProxyPortLabel.Size = new System.Drawing.Size(65, 12);
this.ProxyPortLabel.Size = new System.Drawing.Size(55, 13);
this.ProxyPortLabel.TabIndex = 3;
this.ProxyPortLabel.Text = "Proxy Port";
//
@@ -449,7 +498,7 @@
this.tableLayoutPanel3.Controls.Add(this.MyCancelButton, 1, 0);
this.tableLayoutPanel3.Controls.Add(this.OKButton, 0, 0);
this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Right;
this.tableLayoutPanel3.Location = new System.Drawing.Point(285, 272);
this.tableLayoutPanel3.Location = new System.Drawing.Point(283, 319);
this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(3, 3, 0, 3);
this.tableLayoutPanel3.Name = "tableLayoutPanel3";
this.tableLayoutPanel3.RowCount = 1;
@@ -468,7 +517,7 @@
this.tableLayoutPanel4.Controls.Add(this.DeleteButton, 1, 0);
this.tableLayoutPanel4.Controls.Add(this.AddButton, 0, 0);
this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Top;
this.tableLayoutPanel4.Location = new System.Drawing.Point(0, 205);
this.tableLayoutPanel4.Location = new System.Drawing.Point(0, 252);
this.tableLayoutPanel4.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel4.Name = "tableLayoutPanel4";
this.tableLayoutPanel4.RowCount = 2;
@@ -484,7 +533,7 @@
this.DuplicateButton.Margin = new System.Windows.Forms.Padding(0, 6, 3, 3);
this.DuplicateButton.Name = "DuplicateButton";
this.DuplicateButton.Size = new System.Drawing.Size(80, 23);
this.DuplicateButton.TabIndex = 10;
this.DuplicateButton.TabIndex = 12;
this.DuplicateButton.Text = "Dupli&cate";
this.DuplicateButton.UseVisualStyleBackColor = true;
this.DuplicateButton.Click += new System.EventHandler(this.DuplicateButton_Click);
@@ -559,6 +608,10 @@
private System.Windows.Forms.Button DuplicateButton;
private System.Windows.Forms.Label TimeoutLabel;
private System.Windows.Forms.TextBox TimeoutTextBox;
private System.Windows.Forms.Label PluginOptionsLabel;
private System.Windows.Forms.TextBox PluginTextBox;
private System.Windows.Forms.Label PluginLabel;
private System.Windows.Forms.TextBox PluginOptionsTextBox;
}
}
+6
View File
@@ -47,6 +47,8 @@ namespace Shadowsocks.View
ServerPortLabel.Text = I18N.GetString("Server Port");
PasswordLabel.Text = I18N.GetString("Password");
EncryptionLabel.Text = I18N.GetString("Encryption");
PluginLabel.Text = I18N.GetString("Plugin");
PluginOptionsLabel.Text = I18N.GetString("Plugin Options");
ProxyPortLabel.Text = I18N.GetString("Proxy Port");
RemarksLabel.Text = I18N.GetString("Remarks");
TimeoutLabel.Text = I18N.GetString("Timeout(Sec)");
@@ -94,6 +96,8 @@ namespace Shadowsocks.View
}
server.password = PasswordTextBox.Text;
server.method = EncryptionSelect.Text;
server.plugin = PluginTextBox.Text;
server.plugin_opts = PluginOptionsTextBox.Text;
server.remarks = RemarksTextBox.Text;
if (!int.TryParse(TimeoutTextBox.Text, out server.timeout))
{
@@ -127,6 +131,8 @@ namespace Shadowsocks.View
PasswordTextBox.Text = server.password;
ProxyPortTextBox.Text = _modifiedConfiguration.localPort.ToString();
EncryptionSelect.Text = server.method ?? "aes-256-cfb";
PluginTextBox.Text = server.plugin;
PluginOptionsTextBox.Text = server.plugin_opts;
RemarksTextBox.Text = server.remarks;
TimeoutTextBox.Text = server.timeout.ToString();
}
+79 -112
View File
@@ -28,70 +28,27 @@
/// </summary>
private void InitializeComponent()
{
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
this.MyCancelButton = new System.Windows.Forms.Button();
this.OKButton = new System.Windows.Forms.Button();
this.UseProxyCheckBox = new System.Windows.Forms.CheckBox();
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
this.ProxyAddrLabel = new System.Windows.Forms.Label();
this.ProxyServerTextBox = new System.Windows.Forms.TextBox();
this.ProxyPortLabel = new System.Windows.Forms.Label();
this.ProxyPortTextBox = new System.Windows.Forms.TextBox();
this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel();
this.ProxyTypeLabel = new System.Windows.Forms.Label();
this.ProxyTypeComboBox = new System.Windows.Forms.ComboBox();
this.ProxyTimeoutTextBox = new System.Windows.Forms.TextBox();
this.ProxyTimeoutLabel = new System.Windows.Forms.Label();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.ProxyNotificationLabel = new System.Windows.Forms.Label();
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
this.tableLayoutPanel1.SuspendLayout();
this.tableLayoutPanel3.SuspendLayout();
this.tableLayoutPanel2.SuspendLayout();
this.tableLayoutPanel4.SuspendLayout();
this.flowLayoutPanel1.SuspendLayout();
this.SuspendLayout();
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.AutoSize = true;
this.tableLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.tableLayoutPanel1.ColumnCount = 1;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel3, 0, 3);
this.tableLayoutPanel1.Controls.Add(this.UseProxyCheckBox, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel2, 0, 2);
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel4, 0, 1);
this.tableLayoutPanel1.Location = new System.Drawing.Point(15, 15);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 4;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.Size = new System.Drawing.Size(395, 123);
this.tableLayoutPanel1.TabIndex = 0;
//
// tableLayoutPanel3
//
this.tableLayoutPanel3.AutoSize = true;
this.tableLayoutPanel3.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.tableLayoutPanel3.ColumnCount = 2;
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel3.Controls.Add(this.MyCancelButton, 1, 0);
this.tableLayoutPanel3.Controls.Add(this.OKButton, 0, 0);
this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Right;
this.tableLayoutPanel3.Location = new System.Drawing.Point(236, 94);
this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(3, 3, 0, 3);
this.tableLayoutPanel3.Name = "tableLayoutPanel3";
this.tableLayoutPanel3.RowCount = 1;
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel3.Size = new System.Drawing.Size(159, 26);
this.tableLayoutPanel3.TabIndex = 9;
//
// MyCancelButton
//
this.MyCancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.MyCancelButton.Dock = System.Windows.Forms.DockStyle.Right;
this.MyCancelButton.Location = new System.Drawing.Point(84, 3);
this.MyCancelButton.Margin = new System.Windows.Forms.Padding(3, 3, 0, 0);
this.MyCancelButton.Name = "MyCancelButton";
@@ -104,7 +61,6 @@
// OKButton
//
this.OKButton.DialogResult = System.Windows.Forms.DialogResult.OK;
this.OKButton.Dock = System.Windows.Forms.DockStyle.Right;
this.OKButton.Location = new System.Drawing.Point(3, 3);
this.OKButton.Margin = new System.Windows.Forms.Padding(3, 3, 3, 0);
this.OKButton.Name = "OKButton";
@@ -117,6 +73,7 @@
// UseProxyCheckBox
//
this.UseProxyCheckBox.AutoSize = true;
this.tableLayoutPanel1.SetColumnSpan(this.UseProxyCheckBox, 2);
this.UseProxyCheckBox.Location = new System.Drawing.Point(3, 3);
this.UseProxyCheckBox.Name = "UseProxyCheckBox";
this.UseProxyCheckBox.Size = new System.Drawing.Size(78, 16);
@@ -125,31 +82,11 @@
this.UseProxyCheckBox.UseVisualStyleBackColor = true;
this.UseProxyCheckBox.CheckedChanged += new System.EventHandler(this.UseProxyCheckBox_CheckedChanged);
//
// tableLayoutPanel2
//
this.tableLayoutPanel2.AutoSize = true;
this.tableLayoutPanel2.ColumnCount = 4;
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel2.Controls.Add(this.ProxyAddrLabel, 0, 0);
this.tableLayoutPanel2.Controls.Add(this.ProxyServerTextBox, 1, 0);
this.tableLayoutPanel2.Controls.Add(this.ProxyPortLabel, 2, 0);
this.tableLayoutPanel2.Controls.Add(this.ProxyPortTextBox, 3, 0);
this.tableLayoutPanel2.Location = new System.Drawing.Point(3, 61);
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
this.tableLayoutPanel2.RowCount = 1;
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 27F));
this.tableLayoutPanel2.Size = new System.Drawing.Size(389, 27);
this.tableLayoutPanel2.TabIndex = 1;
//
// ProxyAddrLabel
//
this.ProxyAddrLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.ProxyAddrLabel.AutoSize = true;
this.ProxyAddrLabel.Location = new System.Drawing.Point(3, 7);
this.ProxyAddrLabel.Location = new System.Drawing.Point(3, 71);
this.ProxyAddrLabel.Name = "ProxyAddrLabel";
this.ProxyAddrLabel.Size = new System.Drawing.Size(65, 12);
this.ProxyAddrLabel.TabIndex = 0;
@@ -158,10 +95,10 @@
// ProxyServerTextBox
//
this.ProxyServerTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.ProxyServerTextBox.Location = new System.Drawing.Point(74, 3);
this.ProxyServerTextBox.Location = new System.Drawing.Point(74, 67);
this.ProxyServerTextBox.MaxLength = 512;
this.ProxyServerTextBox.Name = "ProxyServerTextBox";
this.ProxyServerTextBox.Size = new System.Drawing.Size(135, 21);
this.ProxyServerTextBox.Size = new System.Drawing.Size(142, 21);
this.ProxyServerTextBox.TabIndex = 1;
this.ProxyServerTextBox.WordWrap = false;
//
@@ -169,46 +106,27 @@
//
this.ProxyPortLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.ProxyPortLabel.AutoSize = true;
this.ProxyPortLabel.Location = new System.Drawing.Point(215, 7);
this.ProxyPortLabel.Location = new System.Drawing.Point(222, 71);
this.ProxyPortLabel.Name = "ProxyPortLabel";
this.ProxyPortLabel.Size = new System.Drawing.Size(65, 12);
this.ProxyPortLabel.Size = new System.Drawing.Size(77, 12);
this.ProxyPortLabel.TabIndex = 2;
this.ProxyPortLabel.Text = "Proxy Port";
//
// ProxyPortTextBox
//
this.ProxyPortTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.ProxyPortTextBox.Location = new System.Drawing.Point(286, 3);
this.ProxyPortTextBox.Location = new System.Drawing.Point(305, 67);
this.ProxyPortTextBox.MaxLength = 10;
this.ProxyPortTextBox.Name = "ProxyPortTextBox";
this.ProxyPortTextBox.Size = new System.Drawing.Size(100, 21);
this.ProxyPortTextBox.Size = new System.Drawing.Size(58, 21);
this.ProxyPortTextBox.TabIndex = 3;
this.ProxyPortTextBox.WordWrap = false;
//
// tableLayoutPanel4
//
this.tableLayoutPanel4.AutoSize = true;
this.tableLayoutPanel4.ColumnCount = 4;
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel4.Controls.Add(this.ProxyTypeLabel, 0, 0);
this.tableLayoutPanel4.Controls.Add(this.ProxyTypeComboBox, 1, 0);
this.tableLayoutPanel4.Controls.Add(this.ProxyTimeoutTextBox, 3, 0);
this.tableLayoutPanel4.Controls.Add(this.ProxyTimeoutLabel, 2, 0);
this.tableLayoutPanel4.Location = new System.Drawing.Point(3, 25);
this.tableLayoutPanel4.Name = "tableLayoutPanel4";
this.tableLayoutPanel4.RowCount = 1;
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.Size = new System.Drawing.Size(387, 30);
this.tableLayoutPanel4.TabIndex = 10;
//
// ProxyTypeLabel
//
this.ProxyTypeLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.ProxyTypeLabel.AutoSize = true;
this.ProxyTypeLabel.Location = new System.Drawing.Point(3, 9);
this.ProxyTypeLabel.Location = new System.Drawing.Point(3, 40);
this.ProxyTypeLabel.Name = "ProxyTypeLabel";
this.ProxyTypeLabel.Size = new System.Drawing.Size(65, 12);
this.ProxyTypeLabel.TabIndex = 1;
@@ -222,30 +140,86 @@
this.ProxyTypeComboBox.Items.AddRange(new object[] {
"SOCKS5",
"HTTP"});
this.ProxyTypeComboBox.Location = new System.Drawing.Point(74, 5);
this.ProxyTypeComboBox.Location = new System.Drawing.Point(74, 36);
this.ProxyTypeComboBox.Margin = new System.Windows.Forms.Padding(3, 5, 3, 5);
this.ProxyTypeComboBox.Name = "ProxyTypeComboBox";
this.ProxyTypeComboBox.Size = new System.Drawing.Size(121, 20);
this.ProxyTypeComboBox.Size = new System.Drawing.Size(142, 20);
this.ProxyTypeComboBox.TabIndex = 2;
//
// ProxyTimeoutTextBox
//
this.ProxyTimeoutTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.ProxyTimeoutTextBox.Location = new System.Drawing.Point(284, 4);
this.ProxyTimeoutTextBox.Location = new System.Drawing.Point(305, 36);
this.ProxyTimeoutTextBox.Name = "ProxyTimeoutTextBox";
this.ProxyTimeoutTextBox.Size = new System.Drawing.Size(100, 21);
this.ProxyTimeoutTextBox.Size = new System.Drawing.Size(58, 21);
this.ProxyTimeoutTextBox.TabIndex = 3;
//
// ProxyTimeoutLabel
//
this.ProxyTimeoutLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.ProxyTimeoutLabel.AutoSize = true;
this.ProxyTimeoutLabel.Location = new System.Drawing.Point(201, 9);
this.ProxyTimeoutLabel.Location = new System.Drawing.Point(222, 40);
this.ProxyTimeoutLabel.Name = "ProxyTimeoutLabel";
this.ProxyTimeoutLabel.Size = new System.Drawing.Size(77, 12);
this.ProxyTimeoutLabel.TabIndex = 4;
this.ProxyTimeoutLabel.Text = "Timeout(Sec)";
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.tableLayoutPanel1.ColumnCount = 4;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 70F));
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 30F));
this.tableLayoutPanel1.Controls.Add(this.UseProxyCheckBox, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.ProxyTypeLabel, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.ProxyPortTextBox, 3, 2);
this.tableLayoutPanel1.Controls.Add(this.ProxyTypeComboBox, 1, 1);
this.tableLayoutPanel1.Controls.Add(this.ProxyTimeoutLabel, 2, 1);
this.tableLayoutPanel1.Controls.Add(this.ProxyPortLabel, 2, 2);
this.tableLayoutPanel1.Controls.Add(this.ProxyTimeoutTextBox, 3, 1);
this.tableLayoutPanel1.Controls.Add(this.ProxyServerTextBox, 1, 2);
this.tableLayoutPanel1.Controls.Add(this.ProxyAddrLabel, 0, 2);
this.tableLayoutPanel1.Controls.Add(this.ProxyNotificationLabel, 0, 3);
this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel1, 0, 4);
this.tableLayoutPanel1.Location = new System.Drawing.Point(15, 15);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 5;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 21.95122F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 21.95122F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 21.95122F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 34.14634F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.Size = new System.Drawing.Size(366, 177);
this.tableLayoutPanel1.TabIndex = 14;
//
// ProxyNotificationLabel
//
this.ProxyNotificationLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.ProxyNotificationLabel.AutoSize = true;
this.tableLayoutPanel1.SetColumnSpan(this.ProxyNotificationLabel, 4);
this.ProxyNotificationLabel.ForeColor = System.Drawing.Color.Red;
this.ProxyNotificationLabel.Location = new System.Drawing.Point(3, 111);
this.ProxyNotificationLabel.Name = "ProxyNotificationLabel";
this.ProxyNotificationLabel.Size = new System.Drawing.Size(360, 12);
this.ProxyNotificationLabel.TabIndex = 5;
this.ProxyNotificationLabel.Text = "If server has a plugin, proxy will not be used";
//
// flowLayoutPanel1
//
this.flowLayoutPanel1.AutoSize = true;
this.flowLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.tableLayoutPanel1.SetColumnSpan(this.flowLayoutPanel1, 4);
this.flowLayoutPanel1.Controls.Add(this.MyCancelButton);
this.flowLayoutPanel1.Controls.Add(this.OKButton);
this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Right;
this.flowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft;
this.flowLayoutPanel1.Location = new System.Drawing.Point(204, 145);
this.flowLayoutPanel1.Name = "flowLayoutPanel1";
this.flowLayoutPanel1.Size = new System.Drawing.Size(159, 29);
this.flowLayoutPanel1.TabIndex = 6;
//
// ProxyForm
//
this.AcceptButton = this.OKButton;
@@ -254,7 +228,7 @@
this.AutoSize = true;
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.CancelButton = this.MyCancelButton;
this.ClientSize = new System.Drawing.Size(441, 165);
this.ClientSize = new System.Drawing.Size(448, 231);
this.Controls.Add(this.tableLayoutPanel1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
@@ -266,32 +240,25 @@
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ProxyForm_FormClosed);
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel1.PerformLayout();
this.tableLayoutPanel3.ResumeLayout(false);
this.tableLayoutPanel2.ResumeLayout(false);
this.tableLayoutPanel2.PerformLayout();
this.tableLayoutPanel4.ResumeLayout(false);
this.tableLayoutPanel4.PerformLayout();
this.flowLayoutPanel1.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.CheckBox UseProxyCheckBox;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
private System.Windows.Forms.Label ProxyAddrLabel;
private System.Windows.Forms.TextBox ProxyServerTextBox;
private System.Windows.Forms.Label ProxyPortLabel;
private System.Windows.Forms.TextBox ProxyPortTextBox;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
private System.Windows.Forms.Button MyCancelButton;
private System.Windows.Forms.Button OKButton;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4;
private System.Windows.Forms.Label ProxyTypeLabel;
private System.Windows.Forms.ComboBox ProxyTypeComboBox;
private System.Windows.Forms.TextBox ProxyTimeoutTextBox;
private System.Windows.Forms.Label ProxyTimeoutLabel;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.Label ProxyNotificationLabel;
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
}
}
+1
View File
@@ -36,6 +36,7 @@ namespace Shadowsocks.View
ProxyAddrLabel.Text = I18N.GetString("Proxy Addr");
ProxyPortLabel.Text = I18N.GetString("Proxy Port");
ProxyTimeoutLabel.Text = I18N.GetString("Timeout(Sec)");
ProxyNotificationLabel.Text = I18N.GetString("If server has a plugin, proxy will not be used");
OKButton.Text = I18N.GetString("OK");
MyCancelButton.Text = I18N.GetString("Cancel");
this.Text = I18N.GetString("Edit Proxy");
@@ -110,6 +110,7 @@
<Compile Include="Encryption\Stream\StreamSodiumEncryptor.cs" />
<Compile Include="Model\HotKeyConfig.cs" />
<Compile Include="Model\ProxyConfig.cs" />
<Compile Include="Model\SysproxyConfig.cs" />
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
@@ -144,6 +145,7 @@
<Compile Include="Controller\Strategy\BalancingStrategy.cs" />
<Compile Include="Controller\Strategy\StrategyManager.cs" />
<Compile Include="Controller\Strategy\IStrategy.cs" />
<Compile Include="Controller\Service\Sip003Plugin.cs" />
<Compile Include="Proxy\Socks5Proxy.cs" />
<Compile Include="Settings.cs" />
<Compile Include="StringEx.cs" />
+132
View File
@@ -8,6 +8,7 @@ using System.Threading;
using System.Collections.Generic;
using Shadowsocks.Controller.Hotkeys;
using Shadowsocks.Encryption.Stream;
using Shadowsocks.Model;
namespace test
{
@@ -224,5 +225,136 @@ namespace test
throw;
}
}
[TestMethod]
public void ParseAndGenerateShadowsocksUrl()
{
var server = new Server
{
server = "192.168.100.1",
server_port = 8888,
password = "test",
method = "bf-cfb"
};
var serverCanonUrl = "ss://YmYtY2ZiOnRlc3RAMTkyLjE2OC4xMDAuMTo4ODg4";
var serverWithRemark = new Server
{
server = server.server,
server_port = server.server_port,
password = server.password,
method = server.method,
remarks = "example-server"
};
var serverWithRemarkCanonUrl = "ss://YmYtY2ZiOnRlc3RAMTkyLjE2OC4xMDAuMTo4ODg4#example-server";
var serverWithPlugin = new Server
{
server = server.server,
server_port = server.server_port,
password = server.password,
method = server.method,
plugin = "obfs-local",
plugin_opts = "obfs=http;obfs-host=google.com"
};
var serverWithPluginCanonUrl =
"ss://YmYtY2ZiOnRlc3Q@192.168.100.1:8888/?plugin=obfs-local%3bobfs%3dhttp%3bobfs-host%3dgoogle.com";
var serverWithPluginAndRemark = new Server
{
server = server.server,
server_port = server.server_port,
password = server.password,
method = server.method,
plugin = serverWithPlugin.plugin,
plugin_opts = serverWithPlugin.plugin_opts,
remarks = serverWithRemark.remarks
};
var serverWithPluginAndRemarkCanonUrl =
"ss://YmYtY2ZiOnRlc3Q@192.168.100.1:8888/?plugin=obfs-local%3bobfs%3dhttp%3bobfs-host%3dgoogle.com#example-server";
RunParseShadowsocksUrlTest(
string.Join(
"\r\n",
serverCanonUrl,
"\r\n",
"ss://YmYtY2ZiOnRlc3RAMTkyLjE2OC4xMDAuMTo4ODg4/",
serverWithRemarkCanonUrl,
"ss://YmYtY2ZiOnRlc3RAMTkyLjE2OC4xMDAuMTo4ODg4/#example-server"),
new[]
{
server,
server,
serverWithRemark,
serverWithRemark
});
RunParseShadowsocksUrlTest(
string.Join(
"\r\n",
"ss://YmYtY2ZiOnRlc3Q@192.168.100.1:8888",
"\r\n",
"ss://YmYtY2ZiOnRlc3Q@192.168.100.1:8888/",
"ss://YmYtY2ZiOnRlc3Q@192.168.100.1:8888#example-server",
"ss://YmYtY2ZiOnRlc3Q@192.168.100.1:8888/#example-server",
serverWithPluginCanonUrl,
serverWithPluginAndRemarkCanonUrl,
"ss://YmYtY2ZiOnRlc3Q@192.168.100.1:8888/?plugin=obfs-local%3bobfs%3dhttp%3bobfs-host%3dgoogle.com&unsupported=1#example-server"),
new[]
{
server,
server,
serverWithRemark,
serverWithRemark,
serverWithPlugin,
serverWithPluginAndRemark,
serverWithPluginAndRemark
});
var generateUrlCases = new Dictionary<string, Server>
{
[serverCanonUrl] = server,
[serverWithRemarkCanonUrl] = serverWithRemark,
[serverWithPluginCanonUrl] = serverWithPlugin,
[serverWithPluginAndRemarkCanonUrl] = serverWithPluginAndRemark
};
RunGenerateShadowsocksUrlTest(generateUrlCases);
}
private static void RunParseShadowsocksUrlTest(string testCase, IReadOnlyList<Server> expected)
{
var actual = Server.GetServers(testCase);
if (actual.Count != expected.Count)
{
Assert.Fail("Wrong number of configs. Expected: {0}. Actual: {1}", expected.Count, actual.Count);
}
for (int i = 0; i < expected.Count; i++)
{
var expectedServer = expected[i];
var actualServer = actual[i];
Assert.AreEqual(expectedServer.server, actualServer.server);
Assert.AreEqual(expectedServer.server_port, actualServer.server_port);
Assert.AreEqual(expectedServer.password, actualServer.password);
Assert.AreEqual(expectedServer.method, actualServer.method);
Assert.AreEqual(expectedServer.plugin, actualServer.plugin);
Assert.AreEqual(expectedServer.plugin_opts, actualServer.plugin_opts);
Assert.AreEqual(expectedServer.remarks, actualServer.remarks);
Assert.AreEqual(expectedServer.timeout, actualServer.timeout);
}
}
private static void RunGenerateShadowsocksUrlTest(IReadOnlyDictionary<string, Server> testCases)
{
foreach (var testCase in testCases)
{
string expected = testCase.Key;
Server config = testCase.Value;
var actual = ShadowsocksController.GetQRCode(config);
Assert.AreEqual(expected, actual);
}
}
}
}