Browse Source

Merge pull request #10 from clowwindy/master

Merge with upstream
pull/146/head
Sharuru 10 years ago
parent
commit
ba5629e05a
35 changed files with 1215 additions and 514 deletions
  1. +19
    -0
      CHANGES
  2. +15
    -17
      README.md
  3. +42
    -0
      shadowsocks-csharp/Controller/I18N.cs
  4. +14
    -5
      shadowsocks-csharp/Controller/Local.cs
  5. +4
    -0
      shadowsocks-csharp/Controller/Logging.cs
  6. +34
    -16
      shadowsocks-csharp/Controller/PACServer.cs
  7. +81
    -33
      shadowsocks-csharp/Controller/ShadowsocksController.cs
  8. +13
    -4
      shadowsocks-csharp/Controller/SystemProxy.cs
  9. +3
    -1
      shadowsocks-csharp/Controller/UpdateChecker.cs
  10. +41
    -0
      shadowsocks-csharp/Data/cn.txt
  11. BIN
      shadowsocks-csharp/Data/libsscrypto.dll.gz
  12. BIN
      shadowsocks-csharp/Data/polarssl.dll.gz
  13. BIN
      shadowsocks-csharp/Data/polipo.exe.gz
  14. BIN
      shadowsocks-csharp/Data/proxy.pac.txt.gz
  15. +2
    -0
      shadowsocks-csharp/Encrypt/EncryptorBase.cs
  16. +31
    -4
      shadowsocks-csharp/Encrypt/EncryptorFactory.cs
  17. +158
    -0
      shadowsocks-csharp/Encrypt/IVEncryptor.cs
  18. +7
    -4
      shadowsocks-csharp/Encrypt/PolarSSL.cs
  19. +48
    -159
      shadowsocks-csharp/Encrypt/PolarSSLEncryptor.cs
  20. +43
    -0
      shadowsocks-csharp/Encrypt/Sodium.cs
  21. +99
    -0
      shadowsocks-csharp/Encrypt/SodiumEncryptor.cs
  22. +6
    -0
      shadowsocks-csharp/Encrypt/TableEncryptor.cs
  23. +7
    -11
      shadowsocks-csharp/Model/Configuration.cs
  24. +17
    -0
      shadowsocks-csharp/Model/Server.cs
  25. +3
    -1
      shadowsocks-csharp/Program.cs
  26. +3
    -2
      shadowsocks-csharp/Properties/AssemblyInfo.cs
  27. +41
    -2
      shadowsocks-csharp/Properties/Resources.Designer.cs
  28. +5
    -2
      shadowsocks-csharp/Properties/Resources.resx
  29. +181
    -122
      shadowsocks-csharp/View/ConfigForm.Designer.cs
  30. +26
    -3
      shadowsocks-csharp/View/ConfigForm.cs
  31. +128
    -60
      shadowsocks-csharp/View/MenuViewController.cs
  32. +10
    -23
      shadowsocks-csharp/View/QRCodeForm.Designer.cs
  33. +2
    -0
      shadowsocks-csharp/View/QRCodeForm.cs
  34. +6
    -1
      shadowsocks-csharp/shadowsocks-csharp.csproj
  35. +126
    -44
      test/UnitTest.cs

+ 19
- 0
CHANGES View File

@@ -1,3 +1,22 @@
2.1.4 2014-12-20
- Fix crash when remarks are too long

2.1.3 2014-12-20
- Add Chinese Language
- Fix some UI issues on Windows 8
- Fix some UI issues on high DPI screens
- Log bind error more friendly
- Stability issues

2.1.2 2014-12-14
- Fix sometimes Shadowsocks doesn't respond to requests

2.1.1 2014-12-14
- Add global proxy option

2.1 2014-12-12
- Add salsa20 and chacha20 support

2.0.11 2014-11-23 2.0.11 2014-11-23
- Fix a crash - Fix a crash
- Only switch the system proxy off if we have switched it on - Only switch the system proxy off if we have switched it on


+ 15
- 17
README.md View File

@@ -3,36 +3,34 @@ Shadowsocks for Windows


[![Build Status]][Appveyor] [![Build Status]][Appveyor]


### Features
#### Features


1. Native Windows UI
2. Fast system proxy switching
3. Compatible with IE
4. Builtin PAC server with user editable PAC
5. QRCode generation
6. Only a single exe file of 200KB size
1. System proxy configuration
2. Fast profile switching
3. PAC mode and global mode
4. Compatible with IE
5. Only a single exe file of 200KB size


### Download
#### Download


Download [latest release]. Download [latest release].


For Windows 7 and older, please download Shadowsocks-win-x.x.x.zip.
For <= Windows 7, download Shadowsocks-win-x.x.x.zip.


For Windows 8 and newer, please download Shadowsocks-win-dotnet4.0-x.x.x.zip.
For >= Windows 8, download Shadowsocks-win-dotnet4.0-x.x.x.zip.


### Usage
#### Usage


1. Find Shadowsocks icon in notification tray 1. Find Shadowsocks icon in notification tray
2. You can add multiple servers in servers menu 2. You can add multiple servers in servers menu
3. After servers are added, click Enable menu item to enable system proxy
4. After you saved PAC file with any editor, Shadowsocks will notify browsers
3. Select Enable menu to enable system proxy
4. Leave Enable menu unchecked, Shadowsocks will still provide an HTTP proxy at 127.0.0.1:8123
5. After you saved PAC file with any editor, Shadowsocks will notify browsers
about the change automatically about the change automatically
5. Please disable other proxy addons in your browser, or set them to use
6. Please disable other proxy addons in your browser, or set them to use
system proxy system proxy
6. You may need to install VC 2008 Runtime and .Net framework if Shadowsocks
failed to start


### License
#### License


GPLv3 GPLv3




+ 42
- 0
shadowsocks-csharp/Controller/I18N.cs View File

@@ -0,0 +1,42 @@
using Shadowsocks.Properties;
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace Shadowsocks.Controller
{
public class I18N
{
protected static Dictionary<string, string> Strings;
static I18N()
{
Strings = new Dictionary<string, string>();
if (System.Globalization.CultureInfo.CurrentCulture.IetfLanguageTag.ToLowerInvariant().StartsWith("zh"))
{
string[] lines = Regex.Split(Resources.cn, "\r\n|\r|\n");
foreach (string line in lines)
{
string[] kv = Regex.Split(line, "=");
if (kv.Length == 2)
{
Strings[kv[0]] = kv[1];
}
}
}
}
public static string GetString(string key)
{
if (Strings.ContainsKey(key))
{
return Strings[key];
}
else
{
return key;
}
}
}
}

+ 14
- 5
shadowsocks-csharp/Controller/Local.cs View File

@@ -66,16 +66,12 @@ namespace Shadowsocks.Controller
public void AcceptCallback(IAsyncResult ar) public void AcceptCallback(IAsyncResult ar)
{ {
Socket listener = (Socket)ar.AsyncState;
try try
{ {
Socket listener = (Socket)ar.AsyncState;
Socket conn = listener.EndAccept(ar); Socket conn = listener.EndAccept(ar);
conn.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); conn.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
Handler handler = new Handler(); Handler handler = new Handler();
handler.connection = conn; handler.connection = conn;
handler.encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password); handler.encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password);
@@ -87,6 +83,19 @@ namespace Shadowsocks.Controller
{ {
//Console.WriteLine(e.Message); //Console.WriteLine(e.Message);
} }
finally
{
try
{
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
}
catch
{
//Console.WriteLine(e.Message);
}
}
} }
} }


+ 4
- 0
shadowsocks-csharp/Controller/Logging.cs View File

@@ -47,6 +47,10 @@ namespace Shadowsocks.Controller
{ {
// received rst // received rst
} }
else if (se.SocketErrorCode == SocketError.NotConnected)
{
// close when not connected
}
else else
{ {
Console.WriteLine(e); Console.WriteLine(e);


+ 34
- 16
shadowsocks-csharp/Controller/PACServer.cs View File

@@ -58,8 +58,11 @@ namespace Shadowsocks.Controller
public void Stop() public void Stop()
{ {
_listener.Close();
_listener = null;
if (_listener != null)
{
_listener.Close();
_listener = null;
}
} }
public string TouchPACFile() public string TouchPACFile()
@@ -75,24 +78,22 @@ namespace Shadowsocks.Controller
} }
} }
// we don't even use it
static byte[] requestBuf = new byte[2048];
public void AcceptCallback(IAsyncResult ar) public void AcceptCallback(IAsyncResult ar)
{ {
Socket listener = (Socket)ar.AsyncState;
try try
{ {
Socket listener = (Socket)ar.AsyncState;
Socket conn = listener.EndAccept(ar); Socket conn = listener.EndAccept(ar);
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
byte[] buf = new byte[2048];
object[] state = new object[] { object[] state = new object[] {
conn, conn,
buf
requestBuf
}; };
conn.BeginReceive(buf, 0, 1024, 0,
conn.BeginReceive(requestBuf, 0, requestBuf.Length, 0,
new AsyncCallback(ReceiveCallback), state); new AsyncCallback(ReceiveCallback), state);
} }
catch (ObjectDisposedException) catch (ObjectDisposedException)
@@ -102,6 +103,23 @@ namespace Shadowsocks.Controller
{ {
Console.WriteLine(e); Console.WriteLine(e);
} }
finally
{
try
{
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
}
catch (ObjectDisposedException)
{
// do nothing
}
catch (Exception e)
{
Logging.LogUsefulException(e);
}
}
} }
private string GetPACContent() private string GetPACContent()
@@ -113,18 +131,17 @@ namespace Shadowsocks.Controller
else else
{ {
byte[] pacGZ = Resources.proxy_pac_txt; byte[] pacGZ = Resources.proxy_pac_txt;
byte[] buffer = new byte[1024 * 1024]; // builtin pac gzip size: maximum 1M
byte[] buffer = new byte[1024]; // builtin pac gzip size: maximum 100K
MemoryStream sb = new MemoryStream();
int n; int n;
using (GZipStream input = new GZipStream(new MemoryStream(pacGZ), using (GZipStream input = new GZipStream(new MemoryStream(pacGZ),
CompressionMode.Decompress, false)) CompressionMode.Decompress, false))
{ {
n = input.Read(buffer, 0, buffer.Length);
if (n == 0)
while((n = input.Read(buffer, 0, buffer.Length)) > 0)
{ {
throw new IOException("can not decompress pac");
sb.Write(buffer, 0, n);
} }
return System.Text.Encoding.UTF8.GetString(buffer, 0, n);
return System.Text.Encoding.UTF8.GetString(sb.ToArray());
} }
} }
} }
@@ -158,6 +175,7 @@ Connection: Close
", System.Text.Encoding.UTF8.GetBytes(pac).Length) + pac; ", System.Text.Encoding.UTF8.GetBytes(pac).Length) + pac;
byte[] response = System.Text.Encoding.UTF8.GetBytes(text); byte[] response = System.Text.Encoding.UTF8.GetBytes(text);
conn.BeginSend(response, 0, response.Length, 0, new AsyncCallback(SendCallback), conn); conn.BeginSend(response, 0, response.Length, 0, new AsyncCallback(SendCallback), conn);
Util.Util.ReleaseMemory();
} }
else else
{ {


+ 81
- 33
shadowsocks-csharp/Controller/ShadowsocksController.cs View File

@@ -4,6 +4,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Net.Sockets;
namespace Shadowsocks.Controller namespace Shadowsocks.Controller
{ {
@@ -31,38 +32,30 @@ namespace Shadowsocks.Controller
public event EventHandler ConfigChanged; public event EventHandler ConfigChanged;
public event EventHandler EnableStatusChanged; public event EventHandler EnableStatusChanged;
public event EventHandler EnableGlobalChanged;
public event EventHandler ShareOverLANStatusChanged; public event EventHandler ShareOverLANStatusChanged;
// when user clicked Edit PAC, and PAC file has already created // when user clicked Edit PAC, and PAC file has already created
public event EventHandler<PathEventArgs> PACFileReadyToOpen; public event EventHandler<PathEventArgs> PACFileReadyToOpen;
public event ErrorEventHandler Errored;
public ShadowsocksController() public ShadowsocksController()
{ {
_config = Configuration.Load(); _config = Configuration.Load();
polipoRunner = new PolipoRunner();
polipoRunner.Start(_config);
local = new Local(_config);
try
{
local.Start();
}
catch (Exception e)
{
Console.WriteLine(e);
}
try
{
pacServer = new PACServer();
pacServer.PACFileChanged += pacServer_PACFileChanged;
pacServer.Start(_config);
}
catch (Exception e)
}
public void Start()
{
Reload();
}
protected void ReportError(Exception e)
{
if (Errored != null)
{ {
Console.WriteLine(e);
Errored(this, new ErrorEventArgs(e));
} }
UpdateSystemProxy();
StartReleasingMemory();
} }
public Server GetCurrentServer() public Server GetCurrentServer()
@@ -93,6 +86,17 @@ namespace Shadowsocks.Controller
} }
} }
public void ToggleGlobal(bool global)
{
_config.global = global;
UpdateSystemProxy();
SaveConfig(_config);
if (EnableGlobalChanged != null)
{
EnableGlobalChanged(this, new EventArgs());
}
}
public void ToggleShareOverLAN(bool enabled) public void ToggleShareOverLAN(bool enabled)
{ {
_config.shareOverLan = enabled; _config.shareOverLan = enabled;
@@ -116,8 +120,14 @@ namespace Shadowsocks.Controller
return; return;
} }
stopped = true; stopped = true;
local.Stop();
polipoRunner.Stop();
if (local != null)
{
local.Stop();
}
if (polipoRunner != null)
{
polipoRunner.Stop();
}
if (_config.enabled) if (_config.enabled)
{ {
SystemProxy.Disable(); SystemProxy.Disable();
@@ -141,41 +151,79 @@ namespace Shadowsocks.Controller
return "ss://" + base64; return "ss://" + base64;
} }
protected void SaveConfig(Configuration newConfig)
protected void Reload()
{ {
Configuration.Save(newConfig);
// some logic in configuration updated the config when saving, we need to read it again // some logic in configuration updated the config when saving, we need to read it again
_config = Configuration.Load(); _config = Configuration.Load();
if (polipoRunner == null)
{
polipoRunner = new PolipoRunner();
}
if (pacServer == null)
{
pacServer = new PACServer();
pacServer.PACFileChanged += pacServer_PACFileChanged;
}
pacServer.Stop(); pacServer.Stop();
local.Stop();
if (local != null)
{
local.Stop();
}
// don't put polipoRunner.Start() before pacServer.Stop() // don't put polipoRunner.Start() before pacServer.Stop()
// or bind will fail when switching bind address from 0.0.0.0 to 127.0.0.1 // or bind will fail when switching bind address from 0.0.0.0 to 127.0.0.1
// though UseShellExecute is set to true now // though UseShellExecute is set to true now
// http://stackoverflow.com/questions/10235093/socket-doesnt-close-after-application-exits-if-a-launched-process-is-open // http://stackoverflow.com/questions/10235093/socket-doesnt-close-after-application-exits-if-a-launched-process-is-open
polipoRunner.Stop(); polipoRunner.Stop();
polipoRunner.Start(_config);
try
{
polipoRunner.Start(_config);
local = new Local(_config);
local.Start();
pacServer.Start(_config);
local = new Local(_config);
local.Start();
pacServer.Start(_config);
}
catch (Exception e)
{
// translate Microsoft language into human language
// i.e. An attempt was made to access a socket in a way forbidden by its access permissions => Port already in use
if (e is SocketException)
{
SocketException se = (SocketException)e;
if (se.SocketErrorCode == SocketError.AccessDenied)
{
e = new Exception(I18N.GetString("Port already in use"), e);
}
}
Logging.LogUsefulException(e);
ReportError(e);
}
if (ConfigChanged != null) if (ConfigChanged != null)
{ {
ConfigChanged(this, new EventArgs()); ConfigChanged(this, new EventArgs());
} }
UpdateSystemProxy();
Util.Util.ReleaseMemory(); Util.Util.ReleaseMemory();
} }
protected void SaveConfig(Configuration newConfig)
{
Configuration.Save(newConfig);
Reload();
}
private void UpdateSystemProxy() private void UpdateSystemProxy()
{ {
if (_config.enabled) if (_config.enabled)
{ {
SystemProxy.Enable();
SystemProxy.Enable(_config.global);
_systemProxyIsDirty = true; _systemProxyIsDirty = true;
} }
else else


+ 13
- 4
shadowsocks-csharp/Controller/SystemProxy.cs View File

@@ -24,16 +24,25 @@ namespace Shadowsocks.Controller
_refreshReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0); _refreshReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0);
} }
public static void Enable()
public static void Enable(bool global)
{ {
try try
{ {
RegistryKey registry = RegistryKey registry =
Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
true); true);
registry.SetValue("ProxyEnable", 0);
registry.SetValue("ProxyServer", "");
registry.SetValue("AutoConfigURL", "http://127.0.0.1:8093/pac?t=" + GetTimestamp(DateTime.Now));
if (global)
{
registry.SetValue("ProxyEnable", 1);
registry.SetValue("ProxyServer", "127.0.0.1:8123");
registry.SetValue("AutoConfigURL", "");
}
else
{
registry.SetValue("ProxyEnable", 0);
registry.SetValue("ProxyServer", "");
registry.SetValue("AutoConfigURL", "http://127.0.0.1:8093/pac?t=" + GetTimestamp(DateTime.Now));
}
SystemProxy.NotifyIE(); SystemProxy.NotifyIE();
//Must Notify IE first, or the connections do not chanage //Must Notify IE first, or the connections do not chanage
CopyProxySettingFromLan(); CopyProxySettingFromLan();


+ 3
- 1
shadowsocks-csharp/Controller/UpdateChecker.cs View File

@@ -17,6 +17,8 @@ namespace Shadowsocks.Controller
public string LatestVersionURL; public string LatestVersionURL;
public event EventHandler NewVersionFound; public event EventHandler NewVersionFound;
public const string Version = "2.1.4";
public void CheckUpdate() public void CheckUpdate()
{ {
// TODO test failures // TODO test failures
@@ -100,7 +102,7 @@ namespace Shadowsocks.Controller
{ {
return false; return false;
} }
string currentVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
string currentVersion = Version;
return CompareVersion(version, currentVersion) > 0; return CompareVersion(version, currentVersion) > 0;
} }


+ 41
- 0
shadowsocks-csharp/Data/cn.txt View File

@@ -0,0 +1,41 @@
Shadowsocks=Shadowsocks
Enable=启用代理
Mode=代理模式
PAC=PAC 模式
Global=全局模式
Servers=服务器选择
Edit Servers...=编辑服务器...
Start on Boot=自动启动
Share over LAN=在局域网共享代理
Edit PAC File...=编辑 PAC 文件...
Show QRCode...=显示二维码...
Show Logs...=显示日志...
About...=关于...
Quit=退出
Edit Servers=编辑服务器
&Add=添加(&A)
&Delete=删除(&D)
Server=服务器
Server IP=服务器 IP
Server Port=服务器端口
Password=密码
Encryption=加密
Proxy Port=代理端口
Remarks=备注
OK=确定
Cancel=取消
New server=未配置的服务器
QRCode=二维码
Shadowsocks Error: {0}=Shadowsocks 错误: {0}
Port already in use=端口已被占用
Illegal port number format=非法端口格式
Please add at least one server=请添加至少一个服务器
Server IP can not be blank=服务器 IP 不能为空
Password can not be blank=密码不能为空
Port out of range=端口超出范围
Shadowsocks {0} Update Found=Shadowsocks {0} 更新
Click here to download=点击这里下载
Shadowsocks is here=Shadowsocks 在这里
You can turn on/off Shadowsocks in the context menu=可以在右键菜单中开关 Shadowsocks
Enabled=已启用代理
Disabled=已禁用代理

BIN
shadowsocks-csharp/Data/libsscrypto.dll.gz View File


BIN
shadowsocks-csharp/Data/polarssl.dll.gz View File


BIN
shadowsocks-csharp/Data/polipo.exe.gz View File


BIN
shadowsocks-csharp/Data/proxy.pac.txt.gz View File


+ 2
- 0
shadowsocks-csharp/Encrypt/EncryptorBase.cs View File

@@ -6,6 +6,8 @@ namespace Shadowsocks.Encrypt
public abstract class EncryptorBase public abstract class EncryptorBase
: IEncryptor : IEncryptor
{ {
public const int MAX_INPUT_SIZE = 32768;
protected EncryptorBase(string method, string password) protected EncryptorBase(string method, string password)
{ {
Method = method; Method = method;


+ 31
- 4
shadowsocks-csharp/Encrypt/EncryptorFactory.cs View File

@@ -1,16 +1,43 @@
 
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Shadowsocks.Encrypt namespace Shadowsocks.Encrypt
{ {
public static class EncryptorFactory public static class EncryptorFactory
{ {
public static IEncryptor GetEncryptor(string method, string password)
private static Dictionary<string, Type> _registeredEncryptors;
private static Type[] _constructorTypes = new Type[] { typeof(string), typeof(string) };
static EncryptorFactory()
{ {
if (string.IsNullOrEmpty(method) || method.ToLowerInvariant() == "table")
_registeredEncryptors = new Dictionary<string, Type>();
foreach (string method in TableEncryptor.SupportedCiphers())
{
_registeredEncryptors.Add(method, typeof(TableEncryptor));
}
foreach (string method in PolarSSLEncryptor.SupportedCiphers())
{
_registeredEncryptors.Add(method, typeof(PolarSSLEncryptor));
}
foreach (string method in SodiumEncryptor.SupportedCiphers())
{ {
return new TableEncryptor(method, password);
_registeredEncryptors.Add(method, typeof(SodiumEncryptor));
} }
}
return new PolarSSLEncryptor(method, password);
public static IEncryptor GetEncryptor(string method, string password)
{
if (string.IsNullOrEmpty(method))
{
method = "table";
}
method = method.ToLowerInvariant();
Type t = _registeredEncryptors[method];
ConstructorInfo c = t.GetConstructor(_constructorTypes);
IEncryptor result = (IEncryptor)c.Invoke(new object[] { method, password });
return result;
} }
} }
} }

+ 158
- 0
shadowsocks-csharp/Encrypt/IVEncryptor.cs View File

@@ -0,0 +1,158 @@
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
namespace Shadowsocks.Encrypt
{
public abstract class IVEncryptor
: EncryptorBase
{
protected static byte[] tempbuf = new byte[MAX_INPUT_SIZE];
protected Dictionary<string, int[]> ciphers;
private static readonly Dictionary<string, byte[]> CachedKeys = new Dictionary<string, byte[]>();
protected byte[] _encryptIV;
protected byte[] _decryptIV;
protected bool _decryptIVReceived;
protected bool _encryptIVSent;
protected int _encryptIVOffset = 0;
protected int _decryptIVOffset = 0;
protected string _method;
protected int _cipher;
protected int[] _cipherInfo;
protected byte[] _key;
protected int keyLen;
protected int ivLen;
public IVEncryptor(string method, string password)
: base(method, password)
{
InitKey(method, password);
}
protected abstract Dictionary<string, int[]> getCiphers();
protected void InitKey(string method, string password)
{
method = method.ToLower();
_method = method;
string k = method + ":" + password;
ciphers = getCiphers();
_cipherInfo = ciphers[_method];
_cipher = _cipherInfo[2];
if (_cipher == 0)
{
throw new Exception("method not found");
}
keyLen = ciphers[_method][0];
ivLen = ciphers[_method][1];
if (CachedKeys.ContainsKey(k))
{
_key = CachedKeys[k];
}
else
{
byte[] passbuf = Encoding.UTF8.GetBytes(password);
_key = new byte[32];
byte[] iv = new byte[16];
bytesToKey(passbuf, _key);
CachedKeys[k] = _key;
}
}
protected void bytesToKey(byte[] password, byte[] key)
{
byte[] result = new byte[password.Length + 16];
int i = 0;
byte[] md5sum = null;
while (i < key.Length)
{
MD5 md5 = MD5.Create();
if (i == 0)
{
md5sum = md5.ComputeHash(password);
}
else
{
md5sum.CopyTo(result, 0);
password.CopyTo(result, md5sum.Length);
md5sum = md5.ComputeHash(result);
}
md5sum.CopyTo(key, i);
i += md5sum.Length;
}
}
protected static void randBytes(byte[] buf, int length)
{
byte[] temp = new byte[length];
new Random().NextBytes(temp);
temp.CopyTo(buf, 0);
}
protected virtual void initCipher(byte[] iv, bool isCipher)
{
if (ivLen > 0)
{
if (isCipher)
{
_encryptIV = new byte[ivLen];
Array.Copy(iv, _encryptIV, ivLen);
}
else
{
_decryptIV = new byte[ivLen];
Array.Copy(iv, _decryptIV, ivLen);
}
}
}
protected abstract void cipherUpdate(bool isCipher, int length, byte[] buf, byte[] outbuf);
public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength)
{
if (!_encryptIVSent)
{
_encryptIVSent = true;
randBytes(outbuf, ivLen);
initCipher(outbuf, true);
outlength = length + ivLen;
lock (tempbuf)
{
cipherUpdate(true, length, buf, tempbuf);
outlength = length + ivLen;
Buffer.BlockCopy(tempbuf, 0, outbuf, ivLen, length);
}
}
else
{
outlength = length;
cipherUpdate(true, length, buf, outbuf);
}
}
public override void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength)
{
if (!_decryptIVReceived)
{
_decryptIVReceived = true;
initCipher(buf, false);
outlength = length - ivLen;
lock (tempbuf)
{
// C# could be multi-threaded
Buffer.BlockCopy(buf, ivLen, tempbuf, 0, length - ivLen);
cipherUpdate(false, length - ivLen, tempbuf, outbuf);
}
}
else
{
outlength = length;
cipherUpdate(false, length, buf, outbuf);
}
}
}
}

+ 7
- 4
shadowsocks-csharp/Encrypt/PolarSSL.cs View File

@@ -10,7 +10,7 @@ namespace Shadowsocks.Encrypt
{ {
public class PolarSSL public class PolarSSL
{ {
const string DLLNAME = "polarssl";
const string DLLNAME = "libsscrypto";
public const int AES_CTX_SIZE = 8 + 4 * 68; public const int AES_CTX_SIZE = 8 + 4 * 68;
public const int AES_ENCRYPT = 1; public const int AES_ENCRYPT = 1;
@@ -19,12 +19,15 @@ namespace Shadowsocks.Encrypt
static PolarSSL() static PolarSSL()
{ {
string tempPath = Path.GetTempPath(); string tempPath = Path.GetTempPath();
string dllPath = tempPath + "/polarssl.dll";
string dllPath = tempPath + "/libsscrypto.dll";
try try
{ {
FileManager.UncompressFile(dllPath, Resources.polarssl_dll);
FileManager.UncompressFile(dllPath, Resources.libsscrypto_dll);
} }
catch (IOException e)
catch (IOException)
{
}
catch (Exception e)
{ {
Console.WriteLine(e.ToString()); Console.WriteLine(e.ToString());
} }


+ 48
- 159
shadowsocks-csharp/Encrypt/PolarSSLEncryptor.cs View File

@@ -8,32 +8,13 @@ using System.Threading;
namespace Shadowsocks.Encrypt namespace Shadowsocks.Encrypt
{ {
public class PolarSSLEncryptor public class PolarSSLEncryptor
: EncryptorBase, IDisposable
: IVEncryptor, IDisposable
{ {
const int CIPHER_AES = 1; const int CIPHER_AES = 1;
const int CIPHER_RC4 = 2; const int CIPHER_RC4 = 2;
static Dictionary<string, int[]> ciphers = new Dictionary<string, int[]> {
{"aes-128-cfb", new int[]{16, 16, CIPHER_AES, PolarSSL.AES_CTX_SIZE}},
{"aes-192-cfb", new int[]{24, 16, CIPHER_AES, PolarSSL.AES_CTX_SIZE}},
{"aes-256-cfb", new int[]{32, 16, CIPHER_AES, PolarSSL.AES_CTX_SIZE}},
{"rc4", new int[]{16, 0, CIPHER_RC4, PolarSSL.ARC4_CTX_SIZE}},
{"rc4-md5", new int[]{16, 16, CIPHER_RC4, PolarSSL.ARC4_CTX_SIZE}},
};
private static readonly Dictionary<string, byte[]> CachedKeys = new Dictionary<string, byte[]>();
private int _cipher;
private int[] _cipherInfo;
private byte[] _key;
private IntPtr _encryptCtx = IntPtr.Zero; private IntPtr _encryptCtx = IntPtr.Zero;
private IntPtr _decryptCtx = IntPtr.Zero; private IntPtr _decryptCtx = IntPtr.Zero;
private byte[] _encryptIV;
private byte[] _decryptIV;
private int _encryptIVOffset = 0;
private int _decryptIVOffset = 0;
private string _method;
private int keyLen;
private int ivLen;
public PolarSSLEncryptor(string method, string password) public PolarSSLEncryptor(string method, string password)
: base(method, password) : base(method, password)
@@ -41,66 +22,38 @@ namespace Shadowsocks.Encrypt
InitKey(method, password); InitKey(method, password);
} }
private static void randBytes(byte[] buf, int length)
private static Dictionary<string, int[]> _ciphers = new Dictionary<string, int[]> {
{"aes-128-cfb", new int[]{16, 16, CIPHER_AES, PolarSSL.AES_CTX_SIZE}},
{"aes-192-cfb", new int[]{24, 16, CIPHER_AES, PolarSSL.AES_CTX_SIZE}},
{"aes-256-cfb", new int[]{32, 16, CIPHER_AES, PolarSSL.AES_CTX_SIZE}},
{"rc4", new int[]{16, 0, CIPHER_RC4, PolarSSL.ARC4_CTX_SIZE}},
{"rc4-md5", new int[]{16, 16, CIPHER_RC4, PolarSSL.ARC4_CTX_SIZE}},
};
public static List<string> SupportedCiphers()
{ {
byte[] temp = new byte[length];
new Random().NextBytes(temp);
temp.CopyTo(buf, 0);
return new List<string>(_ciphers.Keys);
} }
private void bytesToKey(byte[] password, byte[] key)
protected override Dictionary<string, int[]> getCiphers()
{ {
byte[] result = new byte[password.Length + 16];
int i = 0;
byte[] md5sum = null;
while (i < key.Length)
{
MD5 md5 = MD5.Create();
if (i == 0)
{
md5sum = md5.ComputeHash(password);
}
else
{
md5sum.CopyTo(result, 0);
password.CopyTo(result, md5sum.Length);
md5sum = md5.ComputeHash(result);
}
md5sum.CopyTo(key, i);
i += md5sum.Length;
}
return _ciphers;
} }
private void InitKey(string method, string password)
protected override void initCipher(byte[] iv, bool isCipher)
{ {
method = method.ToLower();
_method = method;
string k = method + ":" + password;
_cipherInfo = ciphers[_method];
_cipher = _cipherInfo[2];
if (_cipher == 0)
{
throw new Exception("method not found");
}
keyLen = ciphers[_method][0];
ivLen = ciphers[_method][1];
if (CachedKeys.ContainsKey(k))
base.initCipher(iv, isCipher);
IntPtr ctx;
ctx = Marshal.AllocHGlobal(_cipherInfo[3]);
if (isCipher)
{ {
_key = CachedKeys[k];
_encryptCtx = ctx;
} }
else else
{ {
byte[] passbuf = Encoding.UTF8.GetBytes(password);
_key = new byte[32];
byte[] iv = new byte[16];
bytesToKey(passbuf, _key);
CachedKeys[k] = _key;
_decryptCtx = ctx;
} }
}
private void InitCipher(ref IntPtr ctx, byte[] iv, bool isCipher)
{
ctx = Marshal.AllocHGlobal(_cipherInfo[3]);
byte[] realkey; byte[] realkey;
if (_method == "rc4-md5") if (_method == "rc4-md5")
{ {
@@ -120,16 +73,6 @@ namespace Shadowsocks.Encrypt
// PolarSSL takes key length by bit // PolarSSL takes key length by bit
// since we'll use CFB mode, here we both do enc, not dec // since we'll use CFB mode, here we both do enc, not dec
PolarSSL.aes_setkey_enc(ctx, realkey, keyLen * 8); PolarSSL.aes_setkey_enc(ctx, realkey, keyLen * 8);
if (isCipher)
{
_encryptIV = new byte[ivLen];
Array.Copy(iv, _encryptIV, ivLen);
}
else
{
_decryptIV = new byte[ivLen];
Array.Copy(iv, _decryptIV, ivLen);
}
} }
else if (_cipher == CIPHER_RC4) else if (_cipher == CIPHER_RC4)
{ {
@@ -139,98 +82,44 @@ namespace Shadowsocks.Encrypt
} }
} }
static byte[] tempbuf = new byte[32768];
public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength)
protected override void cipherUpdate(bool isCipher, int length, byte[] buf, byte[] outbuf)
{ {
if (_encryptCtx == IntPtr.Zero)
// C# could be multi-threaded
if (_disposed)
{ {
randBytes(outbuf, ivLen);
InitCipher(ref _encryptCtx, outbuf, true);
outlength = length + ivLen;
lock (tempbuf)
{
// C# could be multi-threaded
if (_disposed)
{
throw new ObjectDisposedException(this.ToString());
}
switch (_cipher)
{
case CIPHER_AES:
PolarSSL.aes_crypt_cfb128(_encryptCtx, PolarSSL.AES_ENCRYPT, length, ref _encryptIVOffset, _encryptIV, buf, tempbuf);
break;
case CIPHER_RC4:
PolarSSL.arc4_crypt(_encryptCtx, length, buf, tempbuf);
break;
}
outlength = length + ivLen;
Buffer.BlockCopy(tempbuf, 0, outbuf, ivLen, length);
}
throw new ObjectDisposedException(this.ToString());
}
byte[] iv;
int ivOffset;
IntPtr ctx;
if (isCipher)
{
iv = _encryptIV;
ivOffset = _encryptIVOffset;
ctx = _encryptCtx;
} }
else else
{ {
outlength = length;
if (_disposed)
{
throw new ObjectDisposedException(this.ToString());
}
switch (_cipher)
{
case CIPHER_AES:
PolarSSL.aes_crypt_cfb128(_encryptCtx, PolarSSL.AES_ENCRYPT, length, ref _encryptIVOffset, _encryptIV, buf, outbuf);
break;
case CIPHER_RC4:
PolarSSL.arc4_crypt(_encryptCtx, length, buf, outbuf);
break;
}
iv = _decryptIV;
ivOffset = _decryptIVOffset;
ctx = _decryptCtx;
} }
}
public override void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength)
{
if (_decryptCtx == IntPtr.Zero)
switch (_cipher)
{ {
InitCipher(ref _decryptCtx, buf, false);
outlength = length - ivLen;
lock (tempbuf)
{
// C# could be multi-threaded
Buffer.BlockCopy(buf, ivLen, tempbuf, 0, length - ivLen);
if (_disposed)
case CIPHER_AES:
PolarSSL.aes_crypt_cfb128(ctx, isCipher ? PolarSSL.AES_ENCRYPT : PolarSSL.AES_DECRYPT, length, ref ivOffset, iv, buf, outbuf);
if (isCipher)
{ {
throw new ObjectDisposedException(this.ToString());
_encryptIVOffset = ivOffset;
} }
switch (_cipher)
else
{ {
case CIPHER_AES:
PolarSSL.aes_crypt_cfb128(_decryptCtx, PolarSSL.AES_DECRYPT, length - ivLen, ref _decryptIVOffset, _decryptIV, tempbuf, outbuf);
break;
case CIPHER_RC4:
PolarSSL.arc4_crypt(_decryptCtx, length - ivLen, tempbuf, outbuf);
break;
_decryptIVOffset = ivOffset;
} }
}
}
else
{
outlength = length;
if (_disposed)
{
throw new ObjectDisposedException(this.ToString());
}
switch (_cipher)
{
case CIPHER_AES:
PolarSSL.aes_crypt_cfb128(_decryptCtx, PolarSSL.AES_DECRYPT, length, ref _decryptIVOffset, _decryptIV, buf, outbuf);
break;
case CIPHER_RC4:
PolarSSL.arc4_crypt(_decryptCtx, length, buf, outbuf);
break;
}
break;
case CIPHER_RC4:
PolarSSL.arc4_crypt(ctx, length, buf, outbuf);
break;
} }
} }


+ 43
- 0
shadowsocks-csharp/Encrypt/Sodium.cs View File

@@ -0,0 +1,43 @@
using Shadowsocks.Controller;
using Shadowsocks.Properties;
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace Shadowsocks.Encrypt
{
public class Sodium
{
const string DLLNAME = "libsscrypto";
static Sodium()
{
string tempPath = Path.GetTempPath();
string dllPath = tempPath + "/libsscrypto.dll";
try
{
FileManager.UncompressFile(dllPath, Resources.libsscrypto_dll);
LoadLibrary(dllPath);
}
catch (IOException)
{
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
LoadLibrary(dllPath);
}
[DllImport("Kernel32.dll")]
private static extern IntPtr LoadLibrary(string path);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public extern static void crypto_stream_salsa20_xor_ic(byte[] c, byte[] m, ulong mlen, byte[] n, ulong ic, byte[] k);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public extern static void crypto_stream_chacha20_xor_ic(byte[] c, byte[] m, ulong mlen, byte[] n, ulong ic, byte[] k);
}
}

+ 99
- 0
shadowsocks-csharp/Encrypt/SodiumEncryptor.cs View File

@@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Shadowsocks.Encrypt
{
public class SodiumEncryptor
: IVEncryptor, IDisposable
{
const int CIPHER_SALSA20 = 1;
const int CIPHER_CHACHA20 = 2;
const int SODIUM_BLOCK_SIZE = 64;
protected int _encryptBytesRemaining;
protected int _decryptBytesRemaining;
protected ulong _encryptIC;
protected ulong _decryptIC;
protected byte[] _encryptBuf;
protected byte[] _decryptBuf;
public SodiumEncryptor(string method, string password)
: base(method, password)
{
InitKey(method, password);
_encryptBuf = new byte[MAX_INPUT_SIZE + SODIUM_BLOCK_SIZE];
_decryptBuf = new byte[MAX_INPUT_SIZE + SODIUM_BLOCK_SIZE];
}
private static Dictionary<string, int[]> _ciphers = new Dictionary<string, int[]> {
{"salsa20", new int[]{32, 8, CIPHER_SALSA20, PolarSSL.AES_CTX_SIZE}},
{"chacha20", new int[]{32, 8, CIPHER_CHACHA20, PolarSSL.AES_CTX_SIZE}},
};
protected override Dictionary<string, int[]> getCiphers()
{
return _ciphers;
}
public static List<string> SupportedCiphers()
{
return new List<string>(_ciphers.Keys);
}
protected override void cipherUpdate(bool isCipher, int length, byte[] buf, byte[] outbuf)
{
// TODO write a unidirection cipher so we don't have to if if if
int bytesRemaining;
ulong ic;
byte[] sodiumBuf;
byte[] iv;
if (isCipher)
{
bytesRemaining = _encryptBytesRemaining;
ic = _encryptIC;
sodiumBuf = _encryptBuf;
iv = _encryptIV;
}
else
{
bytesRemaining = _decryptBytesRemaining;
ic = _decryptIC;
sodiumBuf = _decryptBuf;
iv = _decryptIV;
}
int padding = bytesRemaining;
Buffer.BlockCopy(buf, 0, sodiumBuf, padding, length);
switch (_cipher)
{
case CIPHER_SALSA20:
Sodium.crypto_stream_salsa20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key);
break;
case CIPHER_CHACHA20:
Sodium.crypto_stream_chacha20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key);
break;
}
Buffer.BlockCopy(sodiumBuf, padding, outbuf, 0, length);
padding += length;
ic += (ulong)padding / SODIUM_BLOCK_SIZE;
bytesRemaining = padding % SODIUM_BLOCK_SIZE;
if (isCipher)
{
_encryptBytesRemaining = bytesRemaining;
_encryptIC = ic;
}
else
{
_decryptBytesRemaining = bytesRemaining;
_decryptIC = ic;
}
}
public override void Dispose()
{
}
}
}

+ 6
- 0
shadowsocks-csharp/Encrypt/TableEncryptor.cs View File

@@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
namespace Shadowsocks.Encrypt namespace Shadowsocks.Encrypt
{ {
@@ -25,6 +26,11 @@ namespace Shadowsocks.Encrypt
} }
} }
public static List<string> SupportedCiphers()
{
return new List<string>(new string[]{"table"});
}
public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength) public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength)
{ {
byte[] result = new byte[length]; byte[] result = new byte[length];


+ 7
- 11
shadowsocks-csharp/Model/Configuration.cs View File

@@ -1,4 +1,5 @@
using System;
using Shadowsocks.Controller;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
@@ -11,6 +12,7 @@ namespace Shadowsocks.Model
{ {
public List<Server> configs; public List<Server> configs;
public int index; public int index;
public bool global;
public bool enabled; public bool enabled;
public bool shareOverLan; public bool shareOverLan;
public bool isDefault; public bool isDefault;
@@ -35,7 +37,6 @@ namespace Shadowsocks.Model
CheckPort(server.server_port); CheckPort(server.server_port);
CheckPassword(server.password); CheckPassword(server.password);
CheckServer(server.server); CheckServer(server.server);
CheckRemark(server.remarks);
} }
public static Configuration Load() public static Configuration Load()
@@ -108,7 +109,7 @@ namespace Shadowsocks.Model
{ {
if (!condition) if (!condition)
{ {
throw new Exception("assertion failure");
throw new Exception(I18N.GetString("assertion failure"));
} }
} }
@@ -116,7 +117,7 @@ namespace Shadowsocks.Model
{ {
if (port <= 0 || port > 65535) if (port <= 0 || port > 65535)
{ {
throw new ArgumentException("port out of range");
throw new ArgumentException(I18N.GetString("Port out of range"));
} }
} }
@@ -124,7 +125,7 @@ namespace Shadowsocks.Model
{ {
if (string.IsNullOrEmpty(password)) if (string.IsNullOrEmpty(password))
{ {
throw new ArgumentException("password can not be blank");
throw new ArgumentException(I18N.GetString("Password can not be blank"));
} }
} }
@@ -132,15 +133,10 @@ namespace Shadowsocks.Model
{ {
if (string.IsNullOrEmpty(server)) if (string.IsNullOrEmpty(server))
{ {
throw new ArgumentException("server IP can not be blank");
throw new ArgumentException(I18N.GetString("Server IP can not be blank"));
} }
} }
private static void CheckRemark(string remark)
{
//remark is optional
}
private class JsonSerializerStrategy : SimpleJson.PocoJsonSerializerStrategy private class JsonSerializerStrategy : SimpleJson.PocoJsonSerializerStrategy
{ {
// convert string to int // convert string to int


+ 17
- 0
shadowsocks-csharp/Model/Server.cs View File

@@ -4,6 +4,7 @@ using System.Text;
using System.IO; using System.IO;
using System.Diagnostics; using System.Diagnostics;
using SimpleJson; using SimpleJson;
using Shadowsocks.Controller;
namespace Shadowsocks.Model namespace Shadowsocks.Model
{ {
@@ -16,5 +17,21 @@ namespace Shadowsocks.Model
public string password; public string password;
public string method; public string method;
public string remarks; public string remarks;
public string FriendlyName()
{
if (string.IsNullOrEmpty(server))
{
return I18N.GetString("New server");
}
if (string.IsNullOrEmpty(remarks))
{
return server + ":" + server_port;
}
else
{
return remarks + " (" + server + ":" + server_port + ")";
}
}
} }
} }

+ 3
- 1
shadowsocks-csharp/Program.cs View File

@@ -41,7 +41,9 @@ namespace Shadowsocks
ShadowsocksController controller = new ShadowsocksController(); ShadowsocksController controller = new ShadowsocksController();
MenuViewController viewController = new MenuViewController(controller); MenuViewController viewController = new MenuViewController(controller);
Util.Util.ReleaseMemory();
controller.Start();
Application.Run(); Application.Run();
} }
} }


+ 3
- 2
shadowsocks-csharp/Properties/AssemblyInfo.cs View File

@@ -1,4 +1,5 @@
using System.Reflection;
using Shadowsocks.Controller;
using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@@ -32,5 +33,5 @@ using System.Runtime.InteropServices;
// 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值, // 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值,
// 方法是按如下所示使用“*”: // 方法是按如下所示使用“*”:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.0.11")]
[assembly: AssemblyVersion(UpdateChecker.Version)]
// [assembly: AssemblyFileVersion("2.0.0")] // [assembly: AssemblyFileVersion("2.0.0")]

+ 41
- 2
shadowsocks-csharp/Properties/Resources.Designer.cs View File

@@ -61,11 +61,50 @@ namespace Shadowsocks.Properties {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Shadowsocks=Shadowsocks
///Enable=启用代理
///Mode=代理模式
///PAC=PAC 模式
///Global=全局模式
///Servers=服务器选择
///Edit Servers...=编辑服务器...
///Start on Boot=自动启动
///Share over LAN=在局域网共享代理
///Edit PAC File...=编辑 PAC 文件...
///Show QRCode...=显示二维码...
///Show Logs...=显示日志...
///About...=关于...
///Quit=退出
///Edit Servers=编辑服务器
///&amp;Add=添加(&amp;A)
///&amp;Delete=删除(&amp;D)
///Server=服务器
///Server IP=服务器 IP
///Server Port=服务器端口
///Password=密码
///Encryption=加密
///Proxy Port=代理端口
///Remarks=备注
///OK=确定
///Cancel=取消
///New server=未配置的服务器
///QRCode=二维码
///Shadowsocks Error: {0}=Shadowsocks 错误: {0}
///Port already in use=端口已被占用
///Il [rest of string was truncated]&quot;;.
/// </summary>
internal static string cn {
get {
return ResourceManager.GetString("cn", resourceCulture);
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[]. /// Looks up a localized resource of type System.Byte[].
/// </summary> /// </summary>
internal static byte[] polarssl_dll {
internal static byte[] libsscrypto_dll {
get { get {
object obj = ResourceManager.GetObject("polarssl_dll", resourceCulture);
object obj = ResourceManager.GetObject("libsscrypto_dll", resourceCulture);
return ((byte[])(obj)); return ((byte[])(obj));
} }
} }


+ 5
- 2
shadowsocks-csharp/Properties/Resources.resx View File

@@ -118,8 +118,11 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="polarssl_dll" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Data\polarssl.dll.gz;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<data name="cn" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\data\cn.txt;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="libsscrypto_dll" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\data\libsscrypto.dll.gz;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data> </data>
<data name="polipo_config" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="polipo_config" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Data\polipo_config.txt;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;gb2312</value> <value>..\Data\polipo_config.txt;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;gb2312</value>


+ 181
- 122
shadowsocks-csharp/View/ConfigForm.Designer.cs View File

@@ -30,30 +30,32 @@
{ {
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.RemarksTextBox = new System.Windows.Forms.TextBox(); this.RemarksTextBox = new System.Windows.Forms.TextBox();
this.label6 = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.RemarksLabel = new System.Windows.Forms.Label();
this.IPLabel = new System.Windows.Forms.Label();
this.ServerPortLabel = new System.Windows.Forms.Label();
this.ProxyPortTextBox = new System.Windows.Forms.TextBox(); this.ProxyPortTextBox = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.ProxyPortLabel = new System.Windows.Forms.Label();
this.PasswordLabel = new System.Windows.Forms.Label();
this.IPTextBox = new System.Windows.Forms.TextBox(); this.IPTextBox = new System.Windows.Forms.TextBox();
this.ServerPortTextBox = new System.Windows.Forms.TextBox(); this.ServerPortTextBox = new System.Windows.Forms.TextBox();
this.PasswordTextBox = new System.Windows.Forms.TextBox(); this.PasswordTextBox = new System.Windows.Forms.TextBox();
this.label5 = new System.Windows.Forms.Label();
this.EncryptionLabel = new System.Windows.Forms.Label();
this.EncryptionSelect = new System.Windows.Forms.ComboBox(); this.EncryptionSelect = new System.Windows.Forms.ComboBox();
this.panel2 = new System.Windows.Forms.Panel(); this.panel2 = new System.Windows.Forms.Panel();
this.OKButton = new System.Windows.Forms.Button(); this.OKButton = new System.Windows.Forms.Button();
this.MyCancelButton = new System.Windows.Forms.Button(); this.MyCancelButton = new System.Windows.Forms.Button();
this.panel1 = new System.Windows.Forms.Panel();
this.panel3 = new System.Windows.Forms.Panel();
this.DeleteButton = new System.Windows.Forms.Button(); this.DeleteButton = new System.Windows.Forms.Button();
this.AddButton = new System.Windows.Forms.Button(); this.AddButton = new System.Windows.Forms.Button();
this.ServerGroupBox = new System.Windows.Forms.GroupBox(); this.ServerGroupBox = new System.Windows.Forms.GroupBox();
this.ServersListBox = new System.Windows.Forms.ListBox(); this.ServersListBox = new System.Windows.Forms.ListBox();
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel();
this.tableLayoutPanel1.SuspendLayout(); this.tableLayoutPanel1.SuspendLayout();
this.panel1.SuspendLayout();
this.panel3.SuspendLayout();
this.ServerGroupBox.SuspendLayout(); this.ServerGroupBox.SuspendLayout();
this.tableLayoutPanel2.SuspendLayout();
this.tableLayoutPanel3.SuspendLayout();
this.tableLayoutPanel4.SuspendLayout();
this.SuspendLayout(); this.SuspendLayout();
// //
// tableLayoutPanel1 // tableLayoutPanel1
@@ -64,21 +66,21 @@
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
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.RemarksTextBox, 1, 5);
this.tableLayoutPanel1.Controls.Add(this.label6, 0, 5);
this.tableLayoutPanel1.Controls.Add(this.label1, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.label2, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.RemarksLabel, 0, 5);
this.tableLayoutPanel1.Controls.Add(this.IPLabel, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.ServerPortLabel, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.ProxyPortTextBox, 1, 4); this.tableLayoutPanel1.Controls.Add(this.ProxyPortTextBox, 1, 4);
this.tableLayoutPanel1.Controls.Add(this.label4, 0, 4);
this.tableLayoutPanel1.Controls.Add(this.label3, 0, 2);
this.tableLayoutPanel1.Controls.Add(this.ProxyPortLabel, 0, 4);
this.tableLayoutPanel1.Controls.Add(this.PasswordLabel, 0, 2);
this.tableLayoutPanel1.Controls.Add(this.IPTextBox, 1, 0); this.tableLayoutPanel1.Controls.Add(this.IPTextBox, 1, 0);
this.tableLayoutPanel1.Controls.Add(this.ServerPortTextBox, 1, 1); this.tableLayoutPanel1.Controls.Add(this.ServerPortTextBox, 1, 1);
this.tableLayoutPanel1.Controls.Add(this.PasswordTextBox, 1, 2); this.tableLayoutPanel1.Controls.Add(this.PasswordTextBox, 1, 2);
this.tableLayoutPanel1.Controls.Add(this.label5, 0, 3);
this.tableLayoutPanel1.Controls.Add(this.EncryptionLabel, 0, 3);
this.tableLayoutPanel1.Controls.Add(this.EncryptionSelect, 1, 3); this.tableLayoutPanel1.Controls.Add(this.EncryptionSelect, 1, 3);
this.tableLayoutPanel1.Location = new System.Drawing.Point(8, 21); this.tableLayoutPanel1.Location = new System.Drawing.Point(8, 21);
this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(5);
this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel1.Name = "tableLayoutPanel1"; this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(5);
this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(3);
this.tableLayoutPanel1.RowCount = 6; this.tableLayoutPanel1.RowCount = 6;
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());
@@ -86,81 +88,84 @@
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.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.Size = new System.Drawing.Size(242, 167);
this.tableLayoutPanel1.Size = new System.Drawing.Size(238, 163);
this.tableLayoutPanel1.TabIndex = 0; this.tableLayoutPanel1.TabIndex = 0;
// //
// RemarksTextBox // RemarksTextBox
// //
this.RemarksTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.RemarksTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.RemarksTextBox.Location = new System.Drawing.Point(74, 139);
this.RemarksTextBox.Location = new System.Drawing.Point(72, 137);
this.RemarksTextBox.MaxLength = 32;
this.RemarksTextBox.Name = "RemarksTextBox"; this.RemarksTextBox.Name = "RemarksTextBox";
this.RemarksTextBox.Size = new System.Drawing.Size(160, 20); this.RemarksTextBox.Size = new System.Drawing.Size(160, 20);
this.RemarksTextBox.TabIndex = 10; this.RemarksTextBox.TabIndex = 10;
this.RemarksTextBox.WordWrap = false; this.RemarksTextBox.WordWrap = false;
// //
// label6
// RemarksLabel
// //
this.label6.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(19, 142);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(49, 13);
this.label6.TabIndex = 9;
this.label6.Text = "Remarks";
this.RemarksLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.RemarksLabel.AutoSize = true;
this.RemarksLabel.Location = new System.Drawing.Point(17, 140);
this.RemarksLabel.Name = "RemarksLabel";
this.RemarksLabel.Size = new System.Drawing.Size(49, 13);
this.RemarksLabel.TabIndex = 9;
this.RemarksLabel.Text = "Remarks";
// //
// label1
// IPLabel
// //
this.label1.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(17, 11);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(51, 13);
this.label1.TabIndex = 0;
this.label1.Text = "Server IP";
this.IPLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.IPLabel.AutoSize = true;
this.IPLabel.Location = new System.Drawing.Point(15, 9);
this.IPLabel.Name = "IPLabel";
this.IPLabel.Size = new System.Drawing.Size(51, 13);
this.IPLabel.TabIndex = 0;
this.IPLabel.Text = "Server IP";
// //
// label2
// ServerPortLabel
// //
this.label2.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(8, 37);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(60, 13);
this.label2.TabIndex = 1;
this.label2.Text = "Server Port";
this.ServerPortLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.ServerPortLabel.AutoSize = true;
this.ServerPortLabel.Location = new System.Drawing.Point(6, 35);
this.ServerPortLabel.Name = "ServerPortLabel";
this.ServerPortLabel.Size = new System.Drawing.Size(60, 13);
this.ServerPortLabel.TabIndex = 1;
this.ServerPortLabel.Text = "Server Port";
// //
// ProxyPortTextBox // ProxyPortTextBox
// //
this.ProxyPortTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.ProxyPortTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.ProxyPortTextBox.Location = new System.Drawing.Point(74, 113);
this.ProxyPortTextBox.Location = new System.Drawing.Point(72, 111);
this.ProxyPortTextBox.MaxLength = 10;
this.ProxyPortTextBox.Name = "ProxyPortTextBox"; this.ProxyPortTextBox.Name = "ProxyPortTextBox";
this.ProxyPortTextBox.Size = new System.Drawing.Size(160, 20); this.ProxyPortTextBox.Size = new System.Drawing.Size(160, 20);
this.ProxyPortTextBox.TabIndex = 4; this.ProxyPortTextBox.TabIndex = 4;
this.ProxyPortTextBox.WordWrap = false; this.ProxyPortTextBox.WordWrap = false;
// //
// label4
// ProxyPortLabel
// //
this.label4.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(13, 116);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(55, 13);
this.label4.TabIndex = 3;
this.label4.Text = "Proxy Port";
this.ProxyPortLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.ProxyPortLabel.AutoSize = true;
this.ProxyPortLabel.Location = new System.Drawing.Point(11, 114);
this.ProxyPortLabel.Name = "ProxyPortLabel";
this.ProxyPortLabel.Size = new System.Drawing.Size(55, 13);
this.ProxyPortLabel.TabIndex = 3;
this.ProxyPortLabel.Text = "Proxy Port";
// //
// label3
// PasswordLabel
// //
this.label3.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(15, 63);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(53, 13);
this.label3.TabIndex = 2;
this.label3.Text = "Password";
this.PasswordLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.PasswordLabel.AutoSize = true;
this.PasswordLabel.Location = new System.Drawing.Point(13, 61);
this.PasswordLabel.Name = "PasswordLabel";
this.PasswordLabel.Size = new System.Drawing.Size(53, 13);
this.PasswordLabel.TabIndex = 2;
this.PasswordLabel.Text = "Password";
// //
// IPTextBox // IPTextBox
// //
this.IPTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.IPTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.IPTextBox.Location = new System.Drawing.Point(74, 8);
this.IPTextBox.Location = new System.Drawing.Point(72, 6);
this.IPTextBox.MaxLength = 512;
this.IPTextBox.Name = "IPTextBox"; this.IPTextBox.Name = "IPTextBox";
this.IPTextBox.Size = new System.Drawing.Size(160, 20); this.IPTextBox.Size = new System.Drawing.Size(160, 20);
this.IPTextBox.TabIndex = 0; this.IPTextBox.TabIndex = 0;
@@ -169,7 +174,8 @@
// ServerPortTextBox // ServerPortTextBox
// //
this.ServerPortTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.ServerPortTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.ServerPortTextBox.Location = new System.Drawing.Point(74, 34);
this.ServerPortTextBox.Location = new System.Drawing.Point(72, 32);
this.ServerPortTextBox.MaxLength = 10;
this.ServerPortTextBox.Name = "ServerPortTextBox"; this.ServerPortTextBox.Name = "ServerPortTextBox";
this.ServerPortTextBox.Size = new System.Drawing.Size(160, 20); this.ServerPortTextBox.Size = new System.Drawing.Size(160, 20);
this.ServerPortTextBox.TabIndex = 1; this.ServerPortTextBox.TabIndex = 1;
@@ -178,22 +184,23 @@
// PasswordTextBox // PasswordTextBox
// //
this.PasswordTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.PasswordTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.PasswordTextBox.Location = new System.Drawing.Point(74, 60);
this.PasswordTextBox.Location = new System.Drawing.Point(72, 58);
this.PasswordTextBox.MaxLength = 256;
this.PasswordTextBox.Name = "PasswordTextBox"; this.PasswordTextBox.Name = "PasswordTextBox";
this.PasswordTextBox.PasswordChar = '*'; this.PasswordTextBox.PasswordChar = '*';
this.PasswordTextBox.Size = new System.Drawing.Size(160, 20); this.PasswordTextBox.Size = new System.Drawing.Size(160, 20);
this.PasswordTextBox.TabIndex = 2; this.PasswordTextBox.TabIndex = 2;
this.PasswordTextBox.WordWrap = false; this.PasswordTextBox.WordWrap = false;
// //
// label5
// EncryptionLabel
// //
this.label5.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(11, 90);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(57, 13);
this.label5.TabIndex = 8;
this.label5.Text = "Encryption";
this.EncryptionLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.EncryptionLabel.AutoSize = true;
this.EncryptionLabel.Location = new System.Drawing.Point(9, 88);
this.EncryptionLabel.Name = "EncryptionLabel";
this.EncryptionLabel.Size = new System.Drawing.Size(57, 13);
this.EncryptionLabel.TabIndex = 8;
this.EncryptionLabel.Text = "Encryption";
// //
// EncryptionSelect // EncryptionSelect
// //
@@ -206,11 +213,13 @@
this.EncryptionSelect.Items.AddRange(new object[] { this.EncryptionSelect.Items.AddRange(new object[] {
"table", "table",
"rc4-md5", "rc4-md5",
"salsa20",
"chacha20",
"aes-256-cfb", "aes-256-cfb",
"aes-192-cfb", "aes-192-cfb",
"aes-128-cfb", "aes-128-cfb",
"rc4"}); "rc4"});
this.EncryptionSelect.Location = new System.Drawing.Point(74, 86);
this.EncryptionSelect.Location = new System.Drawing.Point(72, 84);
this.EncryptionSelect.Name = "EncryptionSelect"; this.EncryptionSelect.Name = "EncryptionSelect";
this.EncryptionSelect.Size = new System.Drawing.Size(160, 21); this.EncryptionSelect.Size = new System.Drawing.Size(160, 21);
this.EncryptionSelect.TabIndex = 3; this.EncryptionSelect.TabIndex = 3;
@@ -220,7 +229,7 @@
this.panel2.Anchor = System.Windows.Forms.AnchorStyles.Top; this.panel2.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.panel2.AutoSize = true; this.panel2.AutoSize = true;
this.panel2.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.panel2.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.panel2.Location = new System.Drawing.Point(164, 175);
this.panel2.Location = new System.Drawing.Point(207, 187);
this.panel2.Name = "panel2"; this.panel2.Name = "panel2";
this.panel2.Size = new System.Drawing.Size(0, 0); this.panel2.Size = new System.Drawing.Size(0, 0);
this.panel2.TabIndex = 1; this.panel2.TabIndex = 1;
@@ -228,7 +237,9 @@
// OKButton // OKButton
// //
this.OKButton.DialogResult = System.Windows.Forms.DialogResult.OK; this.OKButton.DialogResult = System.Windows.Forms.DialogResult.OK;
this.OKButton.Location = new System.Drawing.Point(4, 4);
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"; this.OKButton.Name = "OKButton";
this.OKButton.Size = new System.Drawing.Size(75, 23); this.OKButton.Size = new System.Drawing.Size(75, 23);
this.OKButton.TabIndex = 8; this.OKButton.TabIndex = 8;
@@ -239,7 +250,9 @@
// MyCancelButton // MyCancelButton
// //
this.MyCancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; this.MyCancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.MyCancelButton.Location = new System.Drawing.Point(87, 4);
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"; this.MyCancelButton.Name = "MyCancelButton";
this.MyCancelButton.Size = new System.Drawing.Size(75, 23); this.MyCancelButton.Size = new System.Drawing.Size(75, 23);
this.MyCancelButton.TabIndex = 9; this.MyCancelButton.TabIndex = 9;
@@ -247,34 +260,13 @@
this.MyCancelButton.UseVisualStyleBackColor = true; this.MyCancelButton.UseVisualStyleBackColor = true;
this.MyCancelButton.Click += new System.EventHandler(this.CancelButton_Click); this.MyCancelButton.Click += new System.EventHandler(this.CancelButton_Click);
// //
// panel1
//
this.panel1.AutoSize = true;
this.panel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.panel1.Controls.Add(this.MyCancelButton);
this.panel1.Controls.Add(this.OKButton);
this.panel1.Location = new System.Drawing.Point(313, 247);
this.panel1.Margin = new System.Windows.Forms.Padding(0);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(165, 30);
this.panel1.TabIndex = 1;
//
// panel3
//
this.panel3.AutoSize = true;
this.panel3.Controls.Add(this.DeleteButton);
this.panel3.Controls.Add(this.AddButton);
this.panel3.Location = new System.Drawing.Point(12, 220);
this.panel3.Margin = new System.Windows.Forms.Padding(0);
this.panel3.Name = "panel3";
this.panel3.Size = new System.Drawing.Size(192, 31);
this.panel3.TabIndex = 5;
//
// DeleteButton // DeleteButton
// //
this.DeleteButton.Location = new System.Drawing.Point(100, 4);
this.DeleteButton.Dock = System.Windows.Forms.DockStyle.Right;
this.DeleteButton.Location = new System.Drawing.Point(86, 6);
this.DeleteButton.Margin = new System.Windows.Forms.Padding(3, 6, 0, 3);
this.DeleteButton.Name = "DeleteButton"; this.DeleteButton.Name = "DeleteButton";
this.DeleteButton.Size = new System.Drawing.Size(89, 23);
this.DeleteButton.Size = new System.Drawing.Size(80, 23);
this.DeleteButton.TabIndex = 7; this.DeleteButton.TabIndex = 7;
this.DeleteButton.Text = "&Delete"; this.DeleteButton.Text = "&Delete";
this.DeleteButton.UseVisualStyleBackColor = true; this.DeleteButton.UseVisualStyleBackColor = true;
@@ -282,9 +274,11 @@
// //
// AddButton // AddButton
// //
this.AddButton.Location = new System.Drawing.Point(4, 4);
this.AddButton.Dock = System.Windows.Forms.DockStyle.Left;
this.AddButton.Location = new System.Drawing.Point(0, 6);
this.AddButton.Margin = new System.Windows.Forms.Padding(0, 6, 3, 3);
this.AddButton.Name = "AddButton"; this.AddButton.Name = "AddButton";
this.AddButton.Size = new System.Drawing.Size(89, 23);
this.AddButton.Size = new System.Drawing.Size(80, 23);
this.AddButton.TabIndex = 6; this.AddButton.TabIndex = 6;
this.AddButton.Text = "&Add"; this.AddButton.Text = "&Add";
this.AddButton.UseVisualStyleBackColor = true; this.AddButton.UseVisualStyleBackColor = true;
@@ -292,10 +286,13 @@
// //
// ServerGroupBox // ServerGroupBox
// //
this.ServerGroupBox.AutoSize = true;
this.ServerGroupBox.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.ServerGroupBox.Controls.Add(this.tableLayoutPanel1); this.ServerGroupBox.Controls.Add(this.tableLayoutPanel1);
this.ServerGroupBox.Location = new System.Drawing.Point(223, 12);
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.Name = "ServerGroupBox";
this.ServerGroupBox.Size = new System.Drawing.Size(255, 205);
this.ServerGroupBox.Size = new System.Drawing.Size(249, 200);
this.ServerGroupBox.TabIndex = 6; this.ServerGroupBox.TabIndex = 6;
this.ServerGroupBox.TabStop = false; this.ServerGroupBox.TabStop = false;
this.ServerGroupBox.Text = "Server"; this.ServerGroupBox.Text = "Server";
@@ -303,29 +300,88 @@
// ServersListBox // ServersListBox
// //
this.ServersListBox.FormattingEnabled = true; this.ServersListBox.FormattingEnabled = true;
this.ServersListBox.Location = new System.Drawing.Point(12, 12);
this.ServersListBox.IntegralHeight = false;
this.ServersListBox.Location = new System.Drawing.Point(0, 0);
this.ServersListBox.Margin = new System.Windows.Forms.Padding(0);
this.ServersListBox.Name = "ServersListBox"; this.ServersListBox.Name = "ServersListBox";
this.ServersListBox.Size = new System.Drawing.Size(192, 173);
this.ServersListBox.Size = new System.Drawing.Size(166, 148);
this.ServersListBox.TabIndex = 5; this.ServersListBox.TabIndex = 5;
this.ServersListBox.SelectedIndexChanged += new System.EventHandler(this.ServersListBox_SelectedIndexChanged); this.ServersListBox.SelectedIndexChanged += new System.EventHandler(this.ServersListBox_SelectedIndexChanged);
// //
// tableLayoutPanel2
//
this.tableLayoutPanel2.AutoSize = true;
this.tableLayoutPanel2.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.tableLayoutPanel2.ColumnCount = 2;
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel3, 1, 2);
this.tableLayoutPanel2.Controls.Add(this.ServersListBox, 0, 0);
this.tableLayoutPanel2.Controls.Add(this.ServerGroupBox, 1, 0);
this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel4, 0, 1);
this.tableLayoutPanel2.Location = new System.Drawing.Point(12, 12);
this.tableLayoutPanel2.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
this.tableLayoutPanel2.RowCount = 3;
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(427, 264);
this.tableLayoutPanel2.TabIndex = 7;
//
// 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(268, 235);
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 = 8;
//
// tableLayoutPanel4
//
this.tableLayoutPanel4.AutoSize = true;
this.tableLayoutPanel4.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.tableLayoutPanel4.ColumnCount = 2;
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
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, 200);
this.tableLayoutPanel4.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel4.Name = "tableLayoutPanel4";
this.tableLayoutPanel4.RowCount = 1;
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.Size = new System.Drawing.Size(166, 32);
this.tableLayoutPanel4.TabIndex = 8;
//
// ConfigForm // ConfigForm
// //
this.AcceptButton = this.OKButton; this.AcceptButton = this.OKButton;
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.AutoSize = true; this.AutoSize = true;
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.CancelButton = this.MyCancelButton; this.CancelButton = this.MyCancelButton;
this.ClientSize = new System.Drawing.Size(489, 287);
this.Controls.Add(this.ServersListBox);
this.Controls.Add(this.ServerGroupBox);
this.Controls.Add(this.panel1);
this.Controls.Add(this.panel3);
this.ClientSize = new System.Drawing.Size(574, 367);
this.Controls.Add(this.tableLayoutPanel2);
this.Controls.Add(this.panel2); this.Controls.Add(this.panel2);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false; this.MaximizeBox = false;
this.MinimizeBox = false; this.MinimizeBox = false;
this.Name = "ConfigForm"; this.Name = "ConfigForm";
this.Padding = new System.Windows.Forms.Padding(12, 12, 12, 9);
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Edit Servers"; this.Text = "Edit Servers";
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ConfigForm_FormClosed); this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ConfigForm_FormClosed);
@@ -333,10 +389,12 @@
this.Shown += new System.EventHandler(this.ConfigForm_Shown); this.Shown += new System.EventHandler(this.ConfigForm_Shown);
this.tableLayoutPanel1.ResumeLayout(false); this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel1.PerformLayout(); this.tableLayoutPanel1.PerformLayout();
this.panel1.ResumeLayout(false);
this.panel3.ResumeLayout(false);
this.ServerGroupBox.ResumeLayout(false); this.ServerGroupBox.ResumeLayout(false);
this.ServerGroupBox.PerformLayout(); this.ServerGroupBox.PerformLayout();
this.tableLayoutPanel2.ResumeLayout(false);
this.tableLayoutPanel2.PerformLayout();
this.tableLayoutPanel3.ResumeLayout(false);
this.tableLayoutPanel4.ResumeLayout(false);
this.ResumeLayout(false); this.ResumeLayout(false);
this.PerformLayout(); this.PerformLayout();
@@ -345,27 +403,28 @@
#endregion #endregion
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label IPLabel;
private System.Windows.Forms.Label ServerPortLabel;
private System.Windows.Forms.Label PasswordLabel;
private System.Windows.Forms.Label ProxyPortLabel;
private System.Windows.Forms.TextBox IPTextBox; private System.Windows.Forms.TextBox IPTextBox;
private System.Windows.Forms.TextBox ServerPortTextBox; private System.Windows.Forms.TextBox ServerPortTextBox;
private System.Windows.Forms.TextBox PasswordTextBox; private System.Windows.Forms.TextBox PasswordTextBox;
private System.Windows.Forms.TextBox ProxyPortTextBox; private System.Windows.Forms.TextBox ProxyPortTextBox;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label EncryptionLabel;
private System.Windows.Forms.ComboBox EncryptionSelect; private System.Windows.Forms.ComboBox EncryptionSelect;
private System.Windows.Forms.Panel panel2; private System.Windows.Forms.Panel panel2;
private System.Windows.Forms.Button OKButton; private System.Windows.Forms.Button OKButton;
private System.Windows.Forms.Button MyCancelButton; private System.Windows.Forms.Button MyCancelButton;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Panel panel3;
private System.Windows.Forms.Button DeleteButton; private System.Windows.Forms.Button DeleteButton;
private System.Windows.Forms.Button AddButton; private System.Windows.Forms.Button AddButton;
private System.Windows.Forms.GroupBox ServerGroupBox; private System.Windows.Forms.GroupBox ServerGroupBox;
private System.Windows.Forms.ListBox ServersListBox; private System.Windows.Forms.ListBox ServersListBox;
private System.Windows.Forms.TextBox RemarksTextBox; private System.Windows.Forms.TextBox RemarksTextBox;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.Label RemarksLabel;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4;
} }
} }

+ 26
- 3
shadowsocks-csharp/View/ConfigForm.cs View File

@@ -22,7 +22,14 @@ namespace Shadowsocks.View
public ConfigForm(ShadowsocksController controller) public ConfigForm(ShadowsocksController controller)
{ {
this.Font = System.Drawing.SystemFonts.MessageBoxFont;
InitializeComponent(); InitializeComponent();
// a dirty hack
this.ServersListBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.PerformLayout();
UpdateTexts();
this.Icon = Icon.FromHandle(Resources.ssw128.GetHicon()); this.Icon = Icon.FromHandle(Resources.ssw128.GetHicon());
this.controller = controller; this.controller = controller;
@@ -31,6 +38,22 @@ namespace Shadowsocks.View
LoadCurrentConfiguration(); LoadCurrentConfiguration();
} }
private void UpdateTexts()
{
AddButton.Text = I18N.GetString("&Add");
DeleteButton.Text = I18N.GetString("&Delete");
IPLabel.Text = I18N.GetString("Server IP");
ServerPortLabel.Text = I18N.GetString("Server Port");
PasswordLabel.Text = I18N.GetString("Password");
EncryptionLabel.Text = I18N.GetString("Encryption");
ProxyPortLabel.Text = I18N.GetString("Proxy Port");
RemarksLabel.Text = I18N.GetString("Remarks");
ServerGroupBox.Text = I18N.GetString("Server");
OKButton.Text = I18N.GetString("OK");
MyCancelButton.Text = I18N.GetString("Cancel");
this.Text = I18N.GetString("Edit Servers");
}
private void controller_ConfigChanged(object sender, EventArgs e) private void controller_ConfigChanged(object sender, EventArgs e)
{ {
LoadCurrentConfiguration(); LoadCurrentConfiguration();
@@ -67,7 +90,7 @@ namespace Shadowsocks.View
} }
catch (FormatException) catch (FormatException)
{ {
MessageBox.Show("illegal port number format");
MessageBox.Show(I18N.GetString("Illegal port number format"));
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -102,7 +125,7 @@ namespace Shadowsocks.View
ServersListBox.Items.Clear(); ServersListBox.Items.Clear();
foreach (Server server in _modifiedConfiguration.configs) foreach (Server server in _modifiedConfiguration.configs)
{ {
ServersListBox.Items.Add(string.IsNullOrEmpty(server.server) ? "New server" : string.IsNullOrEmpty(server.remarks)? server.server + ":" + server.server_port : server.server + ":" + server.server_port + " (" + server.remarks + ")");
ServersListBox.Items.Add(server.FriendlyName());
} }
} }
@@ -176,7 +199,7 @@ namespace Shadowsocks.View
} }
if (_modifiedConfiguration.configs.Count == 0) if (_modifiedConfiguration.configs.Count == 0)
{ {
MessageBox.Show("Please add at least one server");
MessageBox.Show(I18N.GetString("Please add at least one server"));
return; return;
} }
controller.SaveServers(_modifiedConfiguration.configs); controller.SaveServers(_modifiedConfiguration.configs);


+ 128
- 60
shadowsocks-csharp/View/MenuViewController.cs View File

@@ -14,12 +14,12 @@ namespace Shadowsocks.View
{ {
// yes this is just a menu view controller // yes this is just a menu view controller
// when config form is closed, it moves away from RAM // when config form is closed, it moves away from RAM
// and it should just does anything related to the config form
// and it should just do anything related to the config form
private ShadowsocksController controller; private ShadowsocksController controller;
private UpdateChecker updateChecker; private UpdateChecker updateChecker;
private NotifyIcon notifyIcon1;
private NotifyIcon _notifyIcon;
private ContextMenu contextMenu1; private ContextMenu contextMenu1;
private bool _isFirstRun; private bool _isFirstRun;
@@ -37,18 +37,29 @@ namespace Shadowsocks.View
private MenuItem menuItem3; private MenuItem menuItem3;
private MenuItem quitItem; private MenuItem quitItem;
private MenuItem menuItem1; private MenuItem menuItem1;
private MenuItem modeItem;
private MenuItem globalModeItem;
private MenuItem PACModeItem;
private ConfigForm configForm; private ConfigForm configForm;
public MenuViewController(ShadowsocksController controller) public MenuViewController(ShadowsocksController controller)
{ {
this.controller = controller;
LoadMenu(); LoadMenu();
LoadTrayIcon();
this.controller = controller;
controller.EnableStatusChanged += controller_EnableStatusChanged; controller.EnableStatusChanged += controller_EnableStatusChanged;
controller.ConfigChanged += controller_ConfigChanged; controller.ConfigChanged += controller_ConfigChanged;
controller.PACFileReadyToOpen += controller_PACFileReadyToOpen; controller.PACFileReadyToOpen += controller_PACFileReadyToOpen;
controller.ShareOverLANStatusChanged += controller_ShareOverLANStatusChanged; controller.ShareOverLANStatusChanged += controller_ShareOverLANStatusChanged;
controller.EnableGlobalChanged += controller_EnableGlobalChanged;
controller.Errored += controller_Errored;
_notifyIcon = new NotifyIcon();
UpdateTrayIcon();
_notifyIcon.Visible = true;
_notifyIcon.ContextMenu = contextMenu1;
_notifyIcon.DoubleClick += notifyIcon1_DoubleClick;
this.updateChecker = new UpdateChecker(); this.updateChecker = new UpdateChecker();
updateChecker.NewVersionFound += updateChecker_NewVersionFound; updateChecker.NewVersionFound += updateChecker_NewVersionFound;
@@ -64,7 +75,12 @@ namespace Shadowsocks.View
} }
} }
private void LoadTrayIcon()
void controller_Errored(object sender, System.IO.ErrorEventArgs e)
{
MessageBox.Show(e.GetException().ToString(), String.Format(I18N.GetString("Shadowsocks Error: {0}"), e.GetException().Message));
}
private void UpdateTrayIcon()
{ {
int dpi; int dpi;
Graphics graphics = Graphics.FromHwnd(IntPtr.Zero); Graphics graphics = Graphics.FromHwnd(IntPtr.Zero);
@@ -85,19 +101,33 @@ namespace Shadowsocks.View
{ {
icon = Resources.ss24; icon = Resources.ss24;
} }
notifyIcon1 = new NotifyIcon();
notifyIcon1.Text = "Shadowsocks";
notifyIcon1.Icon = Icon.FromHandle(icon.GetHicon());
notifyIcon1.Visible = true;
bool enabled = controller.GetConfiguration().enabled;
if (!enabled)
{
Bitmap iconCopy = new Bitmap(icon);
for (int x = 0; x < iconCopy.Width; x++)
{
for (int y = 0; y < iconCopy.Height; y++)
{
Color color = icon.GetPixel(x, y);
iconCopy.SetPixel(x, y , Color.FromArgb((byte)(color.A / 1.25), color.R, color.G, color.B));
}
}
icon = iconCopy;
}
_notifyIcon.Icon = Icon.FromHandle(icon.GetHicon());
notifyIcon1.ContextMenu = contextMenu1;
notifyIcon1.DoubleClick +=notifyIcon1_DoubleClick;
string text = I18N.GetString("Shadowsocks") + " " + UpdateChecker.Version + "\n" + (enabled ? I18N.GetString("Enabled") : I18N.GetString("Disabled")) + "\n" + controller.GetCurrentServer().FriendlyName();
_notifyIcon.Text = text.Substring(0, Math.Min(63, text.Length));
} }
private void LoadMenu() private void LoadMenu()
{ {
this.contextMenu1 = new System.Windows.Forms.ContextMenu(); this.contextMenu1 = new System.Windows.Forms.ContextMenu();
this.enableItem = new System.Windows.Forms.MenuItem(); this.enableItem = new System.Windows.Forms.MenuItem();
this.modeItem = new System.Windows.Forms.MenuItem();
this.PACModeItem = new System.Windows.Forms.MenuItem();
this.globalModeItem = new System.Windows.Forms.MenuItem();
this.AutoStartupItem = new System.Windows.Forms.MenuItem(); this.AutoStartupItem = new System.Windows.Forms.MenuItem();
this.ShareOverLANItem = new System.Windows.Forms.MenuItem(); this.ShareOverLANItem = new System.Windows.Forms.MenuItem();
this.ServersItem = new System.Windows.Forms.MenuItem(); this.ServersItem = new System.Windows.Forms.MenuItem();
@@ -117,6 +147,7 @@ namespace Shadowsocks.View
// //
this.contextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { this.contextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.enableItem, this.enableItem,
this.modeItem,
this.ServersItem, this.ServersItem,
this.menuItem1, this.menuItem1,
this.AutoStartupItem, this.AutoStartupItem,
@@ -132,28 +163,36 @@ namespace Shadowsocks.View
// enableItem // enableItem
// //
this.enableItem.Index = 0; this.enableItem.Index = 0;
this.enableItem.Text = "&Enable";
this.enableItem.Text = I18N.GetString("Enable");
this.enableItem.Click += new System.EventHandler(this.EnableItem_Click); this.enableItem.Click += new System.EventHandler(this.EnableItem_Click);
//
// AutoStartupItem
//
this.AutoStartupItem.Index = 3;
this.AutoStartupItem.Text = "Start on Boot";
this.AutoStartupItem.Click += new System.EventHandler(this.AutoStartupItem_Click);
//
// ShareOverLANItem
//
this.ShareOverLANItem.Index = 4;
this.ShareOverLANItem.Text = "Share over LAN";
this.ShareOverLANItem.Click += new System.EventHandler(this.ShareOverLANItem_Click);
//
// modeMenu
//
this.modeItem.Index = 1;
this.modeItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.PACModeItem,
this.globalModeItem});
this.modeItem.Text = I18N.GetString("Mode");
//
// PACModeItem
//
this.PACModeItem.Index = 0;
this.PACModeItem.Text = I18N.GetString("PAC");
this.PACModeItem.Click += new System.EventHandler(this.PACModeItem_Click);
//
// globalModeItem
//
this.globalModeItem.Index = 1;
this.globalModeItem.Text = I18N.GetString("Global");
this.globalModeItem.Click += new System.EventHandler(this.GlobalModeItem_Click);
// //
// ServersItem // ServersItem
// //
this.ServersItem.Index = 1;
this.ServersItem.Index = 2;
this.ServersItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { this.ServersItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.SeperatorItem, this.SeperatorItem,
this.ConfigItem}); this.ConfigItem});
this.ServersItem.Text = "&Servers";
this.ServersItem.Text = I18N.GetString("Servers");
// //
// SeperatorItem // SeperatorItem
// //
@@ -163,58 +202,71 @@ namespace Shadowsocks.View
// ConfigItem // ConfigItem
// //
this.ConfigItem.Index = 1; this.ConfigItem.Index = 1;
this.ConfigItem.Text = "Edit Servers...";
this.ConfigItem.Text = I18N.GetString("Edit Servers...");
this.ConfigItem.Click += new System.EventHandler(this.Config_Click); this.ConfigItem.Click += new System.EventHandler(this.Config_Click);
// //
// menuItem4
// menuItem1
// //
this.menuItem4.Index = 6;
this.menuItem4.Text = "-";
this.menuItem1.Index = 3;
this.menuItem1.Text = "-";
//
// AutoStartupItem
//
this.AutoStartupItem.Index = 4;
this.AutoStartupItem.Text = I18N.GetString("Start on Boot");
this.AutoStartupItem.Click += new System.EventHandler(this.AutoStartupItem_Click);
//
// ShareOverLANItem
//
this.ShareOverLANItem.Index = 5;
this.ShareOverLANItem.Text = I18N.GetString("Share over LAN");
this.ShareOverLANItem.Click += new System.EventHandler(this.ShareOverLANItem_Click);
// //
// editPACFileItem // editPACFileItem
// //
this.editPACFileItem.Index = 5;
this.editPACFileItem.Text = "Edit &PAC File...";
this.editPACFileItem.Index = 6;
this.editPACFileItem.Text = I18N.GetString("Edit PAC File...");
this.editPACFileItem.Click += new System.EventHandler(this.EditPACFileItem_Click); this.editPACFileItem.Click += new System.EventHandler(this.EditPACFileItem_Click);
// //
// menuItem4
//
this.menuItem4.Index = 7;
this.menuItem4.Text = "-";
//
// QRCodeItem // QRCodeItem
// //
this.QRCodeItem.Index = 7;
this.QRCodeItem.Text = "Show &QRCode...";
this.QRCodeItem.Index = 8;
this.QRCodeItem.Text = I18N.GetString("Show QRCode...");
this.QRCodeItem.Click += new System.EventHandler(this.QRCodeItem_Click); this.QRCodeItem.Click += new System.EventHandler(this.QRCodeItem_Click);
// //
// ShowLogItem // ShowLogItem
// //
this.ShowLogItem.Index = 8;
this.ShowLogItem.Text = "Show Logs...";
this.ShowLogItem.Index = 9;
this.ShowLogItem.Text = I18N.GetString("Show Logs...");
this.ShowLogItem.Click += new System.EventHandler(this.ShowLogItem_Click); this.ShowLogItem.Click += new System.EventHandler(this.ShowLogItem_Click);
// //
// aboutItem // aboutItem
// //
this.aboutItem.Index = 9;
this.aboutItem.Text = "About...";
this.aboutItem.Index = 10;
this.aboutItem.Text = I18N.GetString("About...");
this.aboutItem.Click += new System.EventHandler(this.AboutItem_Click); this.aboutItem.Click += new System.EventHandler(this.AboutItem_Click);
// //
// menuItem3 // menuItem3
// //
this.menuItem3.Index = 10;
this.menuItem3.Index = 11;
this.menuItem3.Text = "-"; this.menuItem3.Text = "-";
// //
// quitItem // quitItem
// //
this.quitItem.Index = 11;
this.quitItem.Text = "&Quit";
this.quitItem.Index = 12;
this.quitItem.Text = I18N.GetString("Quit");
this.quitItem.Click += new System.EventHandler(this.Quit_Click); this.quitItem.Click += new System.EventHandler(this.Quit_Click);
//
// menuItem1
//
this.menuItem1.Index = 2;
this.menuItem1.Text = "-";
} }
private void controller_ConfigChanged(object sender, EventArgs e) private void controller_ConfigChanged(object sender, EventArgs e)
{ {
LoadCurrentConfiguration(); LoadCurrentConfiguration();
UpdateTrayIcon();
} }
private void controller_EnableStatusChanged(object sender, EventArgs e) private void controller_EnableStatusChanged(object sender, EventArgs e)
@@ -227,6 +279,12 @@ namespace Shadowsocks.View
ShareOverLANItem.Checked = controller.GetConfiguration().shareOverLan; ShareOverLANItem.Checked = controller.GetConfiguration().shareOverLan;
} }
void controller_EnableGlobalChanged(object sender, EventArgs e)
{
globalModeItem.Checked = controller.GetConfiguration().global;
PACModeItem.Checked = !globalModeItem.Checked;
}
void controller_PACFileReadyToOpen(object sender, ShadowsocksController.PathEventArgs e) void controller_PACFileReadyToOpen(object sender, ShadowsocksController.PathEventArgs e)
{ {
string argument = @"/select, " + e.Path; string argument = @"/select, " + e.Path;
@@ -236,11 +294,11 @@ namespace Shadowsocks.View
void updateChecker_NewVersionFound(object sender, EventArgs e) void updateChecker_NewVersionFound(object sender, EventArgs e)
{ {
notifyIcon1.BalloonTipTitle = "Shadowsocks " + updateChecker.LatestVersionNumber + " Update Found";
notifyIcon1.BalloonTipText = "Click here to download";
notifyIcon1.BalloonTipIcon = ToolTipIcon.Info;
notifyIcon1.BalloonTipClicked += notifyIcon1_BalloonTipClicked;
notifyIcon1.ShowBalloonTip(5000);
_notifyIcon.BalloonTipTitle = String.Format(I18N.GetString("Shadowsocks {0} Update Found"), updateChecker.LatestVersionNumber);
_notifyIcon.BalloonTipText = I18N.GetString("Click here to download");
_notifyIcon.BalloonTipIcon = ToolTipIcon.Info;
_notifyIcon.BalloonTipClicked += notifyIcon1_BalloonTipClicked;
_notifyIcon.ShowBalloonTip(5000);
_isFirstRun = false; _isFirstRun = false;
} }
@@ -255,6 +313,8 @@ namespace Shadowsocks.View
Configuration config = controller.GetConfiguration(); Configuration config = controller.GetConfiguration();
UpdateServersMenu(); UpdateServersMenu();
enableItem.Checked = config.enabled; enableItem.Checked = config.enabled;
globalModeItem.Checked = config.global;
PACModeItem.Checked = !config.global;
ShareOverLANItem.Checked = config.shareOverLan; ShareOverLANItem.Checked = config.shareOverLan;
AutoStartupItem.Checked = AutoStartup.Check(); AutoStartupItem.Checked = AutoStartup.Check();
} }
@@ -269,7 +329,7 @@ namespace Shadowsocks.View
for (int i = 0; i < configuration.configs.Count; i++) for (int i = 0; i < configuration.configs.Count; i++)
{ {
Server server = configuration.configs[i]; Server server = configuration.configs[i];
MenuItem item = new MenuItem(string.IsNullOrEmpty(server.remarks) ? server.server + ":" + server.server_port : server.server + ":" + server.server_port + " (" + server.remarks + ")");
MenuItem item = new MenuItem(server.FriendlyName());
item.Tag = i; item.Tag = i;
item.Click += AServerItem_Click; item.Click += AServerItem_Click;
items.Add(item); items.Add(item);
@@ -312,7 +372,7 @@ namespace Shadowsocks.View
private void Quit_Click(object sender, EventArgs e) private void Quit_Click(object sender, EventArgs e)
{ {
controller.Stop(); controller.Stop();
notifyIcon1.Visible = false;
_notifyIcon.Visible = false;
Application.Exit(); Application.Exit();
} }
@@ -320,10 +380,10 @@ namespace Shadowsocks.View
{ {
if (_isFirstRun) if (_isFirstRun)
{ {
notifyIcon1.BalloonTipTitle = "Shadowsocks is here";
notifyIcon1.BalloonTipText = "You can turn on/off Shadowsocks in the context menu";
notifyIcon1.BalloonTipIcon = ToolTipIcon.Info;
notifyIcon1.ShowBalloonTip(0);
_notifyIcon.BalloonTipTitle = I18N.GetString("Shadowsocks is here");
_notifyIcon.BalloonTipText = I18N.GetString("You can turn on/off Shadowsocks in the context menu");
_notifyIcon.BalloonTipIcon = ToolTipIcon.Info;
_notifyIcon.ShowBalloonTip(0);
_isFirstRun = false; _isFirstRun = false;
} }
} }
@@ -338,11 +398,19 @@ namespace Shadowsocks.View
ShowConfigForm(); ShowConfigForm();
} }
private void EnableItem_Click(object sender, EventArgs e) private void EnableItem_Click(object sender, EventArgs e)
{ {
enableItem.Checked = !enableItem.Checked;
controller.ToggleEnable(enableItem.Checked);
controller.ToggleEnable(!enableItem.Checked);
}
private void GlobalModeItem_Click(object sender, EventArgs e)
{
controller.ToggleGlobal(true);
}
private void PACModeItem_Click(object sender, EventArgs e)
{
controller.ToggleGlobal(false);
} }
private void ShareOverLANItem_Click(object sender, EventArgs e) private void ShareOverLANItem_Click(object sender, EventArgs e)


+ 10
- 23
shadowsocks-csharp/View/QRCodeForm.Designer.cs View File

@@ -29,49 +29,37 @@
private void InitializeComponent() private void InitializeComponent()
{ {
this.pictureBox1 = new System.Windows.Forms.PictureBox(); this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.panel1 = new System.Windows.Forms.Panel();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.panel1.SuspendLayout();
this.SuspendLayout(); this.SuspendLayout();
// //
// pictureBox1 // pictureBox1
// //
this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.pictureBox1.Location = new System.Drawing.Point(10, 10);
this.pictureBox1.Location = new System.Drawing.Point(9, 9);
this.pictureBox1.Margin = new System.Windows.Forms.Padding(0); this.pictureBox1.Margin = new System.Windows.Forms.Padding(0);
this.pictureBox1.Name = "pictureBox1"; this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(204, 202);
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.pictureBox1.Size = new System.Drawing.Size(210, 210);
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pictureBox1.TabIndex = 1; this.pictureBox1.TabIndex = 1;
this.pictureBox1.TabStop = false; this.pictureBox1.TabStop = false;
// //
// panel1
//
this.panel1.Controls.Add(this.pictureBox1);
this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel1.Location = new System.Drawing.Point(0, 0);
this.panel1.Margin = new System.Windows.Forms.Padding(0);
this.panel1.Name = "panel1";
this.panel1.Padding = new System.Windows.Forms.Padding(10);
this.panel1.Size = new System.Drawing.Size(224, 222);
this.panel1.TabIndex = 2;
//
// QRCodeForm // QRCodeForm
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.AutoSize = true;
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.BackColor = System.Drawing.Color.White; this.BackColor = System.Drawing.Color.White;
this.ClientSize = new System.Drawing.Size(224, 222);
this.Controls.Add(this.panel1);
this.ClientSize = new System.Drawing.Size(338, 274);
this.Controls.Add(this.pictureBox1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false; this.MaximizeBox = false;
this.MinimizeBox = false; this.MinimizeBox = false;
this.Name = "QRCodeForm"; this.Name = "QRCodeForm";
this.Padding = new System.Windows.Forms.Padding(9);
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "QRCode"; this.Text = "QRCode";
this.Load += new System.EventHandler(this.QRCodeForm_Load); this.Load += new System.EventHandler(this.QRCodeForm_Load);
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.panel1.ResumeLayout(false);
this.ResumeLayout(false); this.ResumeLayout(false);
} }
@@ -79,6 +67,5 @@
#endregion #endregion
private System.Windows.Forms.PictureBox pictureBox1; private System.Windows.Forms.PictureBox pictureBox1;
private System.Windows.Forms.Panel panel1;
} }
} }

+ 2
- 0
shadowsocks-csharp/View/QRCodeForm.cs View File

@@ -1,4 +1,5 @@
using QRCode4CS; using QRCode4CS;
using Shadowsocks.Controller;
using Shadowsocks.Properties; using Shadowsocks.Properties;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -21,6 +22,7 @@ namespace Shadowsocks.View
this.code = code; this.code = code;
InitializeComponent(); InitializeComponent();
this.Icon = Icon.FromHandle(Resources.ssw128.GetHicon()); this.Icon = Icon.FromHandle(Resources.ssw128.GetHicon());
this.Text = I18N.GetString("QRCode");
} }
private void GenQR(string ssconfig) private void GenQR(string ssconfig)


+ 6
- 1
shadowsocks-csharp/shadowsocks-csharp.csproj View File

@@ -73,12 +73,16 @@
<Compile Include="3rd\SimpleJson.cs" /> <Compile Include="3rd\SimpleJson.cs" />
<Compile Include="Controller\AutoStartup.cs" /> <Compile Include="Controller\AutoStartup.cs" />
<Compile Include="Controller\FileManager.cs" /> <Compile Include="Controller\FileManager.cs" />
<Compile Include="Controller\I18N.cs" />
<Compile Include="Controller\Logging.cs" /> <Compile Include="Controller\Logging.cs" />
<Compile Include="Controller\UpdateChecker.cs" /> <Compile Include="Controller\UpdateChecker.cs" />
<Compile Include="Encrypt\EncryptorBase.cs" /> <Compile Include="Encrypt\EncryptorBase.cs" />
<Compile Include="Encrypt\EncryptorFactory.cs" /> <Compile Include="Encrypt\EncryptorFactory.cs" />
<Compile Include="Encrypt\IVEncryptor.cs" />
<Compile Include="Encrypt\PolarSSL.cs" /> <Compile Include="Encrypt\PolarSSL.cs" />
<Compile Include="Encrypt\PolarSSLEncryptor.cs" /> <Compile Include="Encrypt\PolarSSLEncryptor.cs" />
<Compile Include="Encrypt\Sodium.cs" />
<Compile Include="Encrypt\SodiumEncryptor.cs" />
<Compile Include="Encrypt\TableEncryptor.cs" /> <Compile Include="Encrypt\TableEncryptor.cs" />
<Compile Include="Encrypt\IEncryptor.cs" /> <Compile Include="Encrypt\IEncryptor.cs" />
<Compile Include="Controller\PACServer.cs" /> <Compile Include="Controller\PACServer.cs" />
@@ -125,7 +129,7 @@
<None Include="app.manifest"> <None Include="app.manifest">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</None> </None>
<None Include="Data\polarssl.dll.gz" />
<None Include="Data\libsscrypto.dll.gz" />
<None Include="Data\polipo.exe.gz" /> <None Include="Data\polipo.exe.gz" />
<None Include="Properties\Settings.settings"> <None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator> <Generator>SettingsSingleFileGenerator</Generator>
@@ -143,6 +147,7 @@
<None Include="Resources\ss16.png" /> <None Include="Resources\ss16.png" />
<None Include="Resources\ss24.png" /> <None Include="Resources\ss24.png" />
<None Include="Resources\ssw128.png" /> <None Include="Resources\ssw128.png" />
<Content Include="Data\cn.txt" />
<Content Include="shadowsocks.ico" /> <Content Include="shadowsocks.ico" />
<None Include="Data\polipo_config.txt" /> <None Include="Data\polipo_config.txt" />
</ItemGroup> </ItemGroup>


+ 126
- 44
test/UnitTest.cs View File

@@ -22,15 +22,50 @@ namespace test
Assert.IsTrue(UpdateChecker.CompareVersion("1.3.2", "1.3.1") > 0); Assert.IsTrue(UpdateChecker.CompareVersion("1.3.2", "1.3.1") > 0);
} }
private void RunEncryptionRound(IEncryptor encryptor, IEncryptor decryptor)
{
byte[] plain = new byte[16384];
byte[] cipher = new byte[plain.Length + 16];
byte[] plain2 = new byte[plain.Length + 16];
int outLen = 0;
int outLen2 = 0;
var random = new Random();
random.NextBytes(plain);
encryptor.Encrypt(plain, plain.Length, cipher, out outLen);
decryptor.Decrypt(cipher, outLen, plain2, out outLen2);
Assert.AreEqual(plain.Length, outLen2);
for (int j = 0; j < plain.Length; j++)
{
Assert.AreEqual(plain[j], plain2[j]);
}
encryptor.Encrypt(plain, 1000, cipher, out outLen);
decryptor.Decrypt(cipher, outLen, plain2, out outLen2);
Assert.AreEqual(1000, outLen2);
for (int j = 0; j < outLen2; j++)
{
Assert.AreEqual(plain[j], plain2[j]);
}
encryptor.Encrypt(plain, 12333, cipher, out outLen);
decryptor.Decrypt(cipher, outLen, plain2, out outLen2);
Assert.AreEqual(12333, outLen2);
for (int j = 0; j < outLen2; j++)
{
Assert.AreEqual(plain[j], plain2[j]);
}
}
private static bool encryptionFailed = false;
private static object locker = new object();
[TestMethod] [TestMethod]
public void TestEncryption()
public void TestPolarSSLEncryption()
{ {
// run it once before the multi-threading test to initialize global tables // run it once before the multi-threading test to initialize global tables
RunSingleEncryptionThread();
RunSinglePolarSSLEncryptionThread();
List<Thread> threads = new List<Thread>(); List<Thread> threads = new List<Thread>();
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
Thread t = new Thread(new ThreadStart(RunSingleEncryptionThread));
Thread t = new Thread(new ThreadStart(RunSinglePolarSSLEncryptionThread));
threads.Add(t); threads.Add(t);
t.Start(); t.Start();
} }
@@ -41,51 +76,98 @@ namespace test
Assert.IsFalse(encryptionFailed); Assert.IsFalse(encryptionFailed);
} }
private static bool encryptionFailed = false;
private static object locker = new object();
private void RunSinglePolarSSLEncryptionThread()
{
try
{
for (int i = 0; i < 100; i++)
{
IEncryptor encryptor;
IEncryptor decryptor;
encryptor = new PolarSSLEncryptor("aes-256-cfb", "barfoo!");
decryptor = new PolarSSLEncryptor("aes-256-cfb", "barfoo!");
RunEncryptionRound(encryptor, decryptor);
}
}
catch
{
encryptionFailed = true;
throw;
}
}
[TestMethod]
public void TestRC4Encryption()
{
// run it once before the multi-threading test to initialize global tables
RunSingleRC4EncryptionThread();
List<Thread> threads = new List<Thread>();
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(RunSingleRC4EncryptionThread));
threads.Add(t);
t.Start();
}
foreach (Thread t in threads)
{
t.Join();
}
Assert.IsFalse(encryptionFailed);
}
private void RunSingleRC4EncryptionThread()
{
try
{
for (int i = 0; i < 100; i++)
{
var random = new Random();
IEncryptor encryptor;
IEncryptor decryptor;
encryptor = new PolarSSLEncryptor("rc4-md5", "barfoo!");
decryptor = new PolarSSLEncryptor("rc4-md5", "barfoo!");
RunEncryptionRound(encryptor, decryptor);
}
}
catch
{
encryptionFailed = true;
throw;
}
}
[TestMethod]
public void TestSodiumEncryption()
{
// run it once before the multi-threading test to initialize global tables
RunSingleSodiumEncryptionThread();
List<Thread> threads = new List<Thread>();
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(RunSingleSodiumEncryptionThread));
threads.Add(t);
t.Start();
}
foreach (Thread t in threads)
{
t.Join();
}
Assert.IsFalse(encryptionFailed);
}
private void RunSingleEncryptionThread()
private void RunSingleSodiumEncryptionThread()
{ {
try try
{ {
for (int i = 0; i < 100; i++)
{
var random = new Random();
IEncryptor encryptor;
IEncryptor decryptor;
encryptor = new PolarSSLEncryptor("aes-256-cfb", "barfoo!");
decryptor = new PolarSSLEncryptor("aes-256-cfb", "barfoo!");
byte[] plain = new byte[16384];
byte[] cipher = new byte[plain.Length + 16];
byte[] plain2 = new byte[plain.Length + 16];
int outLen = 0;
int outLen2 = 0;
random.NextBytes(plain);
//lock (locker)
//{
encryptor.Encrypt(plain, plain.Length, cipher, out outLen);
decryptor.Decrypt(cipher, outLen, plain2, out outLen2);
Assert.AreEqual(plain.Length, outLen2);
for (int j = 0; j < plain.Length; j++)
{
Assert.AreEqual(plain[j], plain2[j]);
}
encryptor.Encrypt(plain, 1000, cipher, out outLen);
decryptor.Decrypt(cipher, outLen, plain2, out outLen2);
Assert.AreEqual(1000, outLen2);
for (int j = 0; j < outLen2; j++)
{
Assert.AreEqual(plain[j], plain2[j]);
}
encryptor.Encrypt(plain, 12333, cipher, out outLen);
decryptor.Decrypt(cipher, outLen, plain2, out outLen2);
Assert.AreEqual(12333, outLen2);
for (int j = 0; j < outLen2; j++)
{
Assert.AreEqual(plain[j], plain2[j]);
}
//}
}
for (int i = 0; i < 100; i++)
{
var random = new Random();
IEncryptor encryptor;
IEncryptor decryptor;
encryptor = new SodiumEncryptor("salsa20", "barfoo!");
decryptor = new SodiumEncryptor("salsa20", "barfoo!");
RunEncryptionRound(encryptor, decryptor);
}
} }
catch catch
{ {


Loading…
Cancel
Save