@@ -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 | |||
- Fix a crash | |||
- Only switch the system proxy off if we have switched it on | |||
@@ -3,36 +3,34 @@ Shadowsocks for Windows | |||
[![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]. | |||
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 | |||
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 | |||
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 | |||
6. You may need to install VC 2008 Runtime and .Net framework if Shadowsocks | |||
failed to start | |||
### License | |||
#### License | |||
GPLv3 | |||
@@ -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; | |||
} | |||
} | |||
} | |||
} |
@@ -66,16 +66,12 @@ namespace Shadowsocks.Controller | |||
public void AcceptCallback(IAsyncResult ar) | |||
{ | |||
Socket listener = (Socket)ar.AsyncState; | |||
try | |||
{ | |||
Socket listener = (Socket)ar.AsyncState; | |||
Socket conn = listener.EndAccept(ar); | |||
conn.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); | |||
listener.BeginAccept( | |||
new AsyncCallback(AcceptCallback), | |||
listener); | |||
Handler handler = new Handler(); | |||
handler.connection = conn; | |||
handler.encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password); | |||
@@ -87,6 +83,19 @@ namespace Shadowsocks.Controller | |||
{ | |||
//Console.WriteLine(e.Message); | |||
} | |||
finally | |||
{ | |||
try | |||
{ | |||
listener.BeginAccept( | |||
new AsyncCallback(AcceptCallback), | |||
listener); | |||
} | |||
catch | |||
{ | |||
//Console.WriteLine(e.Message); | |||
} | |||
} | |||
} | |||
} | |||
@@ -47,6 +47,10 @@ namespace Shadowsocks.Controller | |||
{ | |||
// received rst | |||
} | |||
else if (se.SocketErrorCode == SocketError.NotConnected) | |||
{ | |||
// close when not connected | |||
} | |||
else | |||
{ | |||
Console.WriteLine(e); | |||
@@ -58,8 +58,11 @@ namespace Shadowsocks.Controller | |||
public void Stop() | |||
{ | |||
_listener.Close(); | |||
_listener = null; | |||
if (_listener != null) | |||
{ | |||
_listener.Close(); | |||
_listener = null; | |||
} | |||
} | |||
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) | |||
{ | |||
Socket listener = (Socket)ar.AsyncState; | |||
try | |||
{ | |||
Socket listener = (Socket)ar.AsyncState; | |||
Socket conn = listener.EndAccept(ar); | |||
listener.BeginAccept( | |||
new AsyncCallback(AcceptCallback), | |||
listener); | |||
byte[] buf = new byte[2048]; | |||
object[] state = new object[] { | |||
conn, | |||
buf | |||
requestBuf | |||
}; | |||
conn.BeginReceive(buf, 0, 1024, 0, | |||
conn.BeginReceive(requestBuf, 0, requestBuf.Length, 0, | |||
new AsyncCallback(ReceiveCallback), state); | |||
} | |||
catch (ObjectDisposedException) | |||
@@ -102,6 +103,23 @@ namespace Shadowsocks.Controller | |||
{ | |||
Console.WriteLine(e); | |||
} | |||
finally | |||
{ | |||
try | |||
{ | |||
listener.BeginAccept( | |||
new AsyncCallback(AcceptCallback), | |||
listener); | |||
} | |||
catch (ObjectDisposedException) | |||
{ | |||
// do nothing | |||
} | |||
catch (Exception e) | |||
{ | |||
Logging.LogUsefulException(e); | |||
} | |||
} | |||
} | |||
private string GetPACContent() | |||
@@ -113,18 +131,17 @@ namespace Shadowsocks.Controller | |||
else | |||
{ | |||
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; | |||
using (GZipStream input = new GZipStream(new MemoryStream(pacGZ), | |||
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; | |||
byte[] response = System.Text.Encoding.UTF8.GetBytes(text); | |||
conn.BeginSend(response, 0, response.Length, 0, new AsyncCallback(SendCallback), conn); | |||
Util.Util.ReleaseMemory(); | |||
} | |||
else | |||
{ | |||
@@ -4,6 +4,7 @@ using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Threading; | |||
using System.Net.Sockets; | |||
namespace Shadowsocks.Controller | |||
{ | |||
@@ -31,38 +32,30 @@ namespace Shadowsocks.Controller | |||
public event EventHandler ConfigChanged; | |||
public event EventHandler EnableStatusChanged; | |||
public event EventHandler EnableGlobalChanged; | |||
public event EventHandler ShareOverLANStatusChanged; | |||
// when user clicked Edit PAC, and PAC file has already created | |||
public event EventHandler<PathEventArgs> PACFileReadyToOpen; | |||
public event ErrorEventHandler Errored; | |||
public ShadowsocksController() | |||
{ | |||
_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() | |||
@@ -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) | |||
{ | |||
_config.shareOverLan = enabled; | |||
@@ -116,8 +120,14 @@ namespace Shadowsocks.Controller | |||
return; | |||
} | |||
stopped = true; | |||
local.Stop(); | |||
polipoRunner.Stop(); | |||
if (local != null) | |||
{ | |||
local.Stop(); | |||
} | |||
if (polipoRunner != null) | |||
{ | |||
polipoRunner.Stop(); | |||
} | |||
if (_config.enabled) | |||
{ | |||
SystemProxy.Disable(); | |||
@@ -141,41 +151,79 @@ namespace Shadowsocks.Controller | |||
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 | |||
_config = Configuration.Load(); | |||
if (polipoRunner == null) | |||
{ | |||
polipoRunner = new PolipoRunner(); | |||
} | |||
if (pacServer == null) | |||
{ | |||
pacServer = new PACServer(); | |||
pacServer.PACFileChanged += pacServer_PACFileChanged; | |||
} | |||
pacServer.Stop(); | |||
local.Stop(); | |||
if (local != null) | |||
{ | |||
local.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 | |||
// though UseShellExecute is set to true now | |||
// http://stackoverflow.com/questions/10235093/socket-doesnt-close-after-application-exits-if-a-launched-process-is-open | |||
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) | |||
{ | |||
ConfigChanged(this, new EventArgs()); | |||
} | |||
UpdateSystemProxy(); | |||
Util.Util.ReleaseMemory(); | |||
} | |||
protected void SaveConfig(Configuration newConfig) | |||
{ | |||
Configuration.Save(newConfig); | |||
Reload(); | |||
} | |||
private void UpdateSystemProxy() | |||
{ | |||
if (_config.enabled) | |||
{ | |||
SystemProxy.Enable(); | |||
SystemProxy.Enable(_config.global); | |||
_systemProxyIsDirty = true; | |||
} | |||
else | |||
@@ -24,16 +24,25 @@ namespace Shadowsocks.Controller | |||
_refreshReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0); | |||
} | |||
public static void Enable() | |||
public static void Enable(bool global) | |||
{ | |||
try | |||
{ | |||
RegistryKey registry = | |||
Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", | |||
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(); | |||
//Must Notify IE first, or the connections do not chanage | |||
CopyProxySettingFromLan(); | |||
@@ -17,6 +17,8 @@ namespace Shadowsocks.Controller | |||
public string LatestVersionURL; | |||
public event EventHandler NewVersionFound; | |||
public const string Version = "2.1.4"; | |||
public void CheckUpdate() | |||
{ | |||
// TODO test failures | |||
@@ -100,7 +102,7 @@ namespace Shadowsocks.Controller | |||
{ | |||
return false; | |||
} | |||
string currentVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(); | |||
string currentVersion = Version; | |||
return CompareVersion(version, currentVersion) > 0; | |||
} | |||
@@ -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=已禁用代理 |
@@ -6,6 +6,8 @@ namespace Shadowsocks.Encrypt | |||
public abstract class EncryptorBase | |||
: IEncryptor | |||
{ | |||
public const int MAX_INPUT_SIZE = 32768; | |||
protected EncryptorBase(string method, string password) | |||
{ | |||
Method = method; | |||
@@ -1,16 +1,43 @@ | |||
| |||
using System; | |||
using System.Collections.Generic; | |||
using System.Reflection; | |||
namespace Shadowsocks.Encrypt | |||
{ | |||
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; | |||
} | |||
} | |||
} |
@@ -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); | |||
} | |||
} | |||
} | |||
} |
@@ -10,7 +10,7 @@ namespace Shadowsocks.Encrypt | |||
{ | |||
public class PolarSSL | |||
{ | |||
const string DLLNAME = "polarssl"; | |||
const string DLLNAME = "libsscrypto"; | |||
public const int AES_CTX_SIZE = 8 + 4 * 68; | |||
public const int AES_ENCRYPT = 1; | |||
@@ -19,12 +19,15 @@ namespace Shadowsocks.Encrypt | |||
static PolarSSL() | |||
{ | |||
string tempPath = Path.GetTempPath(); | |||
string dllPath = tempPath + "/polarssl.dll"; | |||
string dllPath = tempPath + "/libsscrypto.dll"; | |||
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()); | |||
} | |||
@@ -8,32 +8,13 @@ using System.Threading; | |||
namespace Shadowsocks.Encrypt | |||
{ | |||
public class PolarSSLEncryptor | |||
: EncryptorBase, IDisposable | |||
: IVEncryptor, IDisposable | |||
{ | |||
const int CIPHER_AES = 1; | |||
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 _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) | |||
: base(method, password) | |||
@@ -41,66 +22,38 @@ namespace Shadowsocks.Encrypt | |||
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 | |||
{ | |||
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; | |||
if (_method == "rc4-md5") | |||
{ | |||
@@ -120,16 +73,6 @@ namespace Shadowsocks.Encrypt | |||
// PolarSSL takes key length by bit | |||
// since we'll use CFB mode, here we both do enc, not dec | |||
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) | |||
{ | |||
@@ -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 | |||
{ | |||
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; | |||
} | |||
} | |||
@@ -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); | |||
} | |||
} |
@@ -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() | |||
{ | |||
} | |||
} | |||
} |
@@ -1,4 +1,5 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
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) | |||
{ | |||
byte[] result = new byte[length]; | |||
@@ -1,4 +1,5 @@ | |||
using System; | |||
using Shadowsocks.Controller; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.IO; | |||
using System.Text; | |||
@@ -11,6 +12,7 @@ namespace Shadowsocks.Model | |||
{ | |||
public List<Server> configs; | |||
public int index; | |||
public bool global; | |||
public bool enabled; | |||
public bool shareOverLan; | |||
public bool isDefault; | |||
@@ -35,7 +37,6 @@ namespace Shadowsocks.Model | |||
CheckPort(server.server_port); | |||
CheckPassword(server.password); | |||
CheckServer(server.server); | |||
CheckRemark(server.remarks); | |||
} | |||
public static Configuration Load() | |||
@@ -108,7 +109,7 @@ namespace Shadowsocks.Model | |||
{ | |||
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) | |||
{ | |||
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)) | |||
{ | |||
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)) | |||
{ | |||
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 | |||
{ | |||
// convert string to int | |||
@@ -4,6 +4,7 @@ using System.Text; | |||
using System.IO; | |||
using System.Diagnostics; | |||
using SimpleJson; | |||
using Shadowsocks.Controller; | |||
namespace Shadowsocks.Model | |||
{ | |||
@@ -16,5 +17,21 @@ namespace Shadowsocks.Model | |||
public string password; | |||
public string method; | |||
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 + ")"; | |||
} | |||
} | |||
} | |||
} |
@@ -41,7 +41,9 @@ namespace Shadowsocks | |||
ShadowsocksController controller = new ShadowsocksController(); | |||
MenuViewController viewController = new MenuViewController(controller); | |||
Util.Util.ReleaseMemory(); | |||
controller.Start(); | |||
Application.Run(); | |||
} | |||
} | |||
@@ -1,4 +1,5 @@ | |||
using System.Reflection; | |||
using Shadowsocks.Controller; | |||
using System.Reflection; | |||
using System.Runtime.CompilerServices; | |||
using System.Runtime.InteropServices; | |||
@@ -32,5 +33,5 @@ using System.Runtime.InteropServices; | |||
// 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值, | |||
// 方法是按如下所示使用“*”: | |||
// [assembly: AssemblyVersion("1.0.*")] | |||
[assembly: AssemblyVersion("2.0.11")] | |||
[assembly: AssemblyVersion(UpdateChecker.Version)] | |||
// [assembly: AssemblyFileVersion("2.0.0")] |
@@ -61,11 +61,50 @@ namespace Shadowsocks.Properties { | |||
} | |||
/// <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=编辑服务器 | |||
///&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=端口已被占用 | |||
///Il [rest of string was truncated]";. | |||
/// </summary> | |||
internal static string cn { | |||
get { | |||
return ResourceManager.GetString("cn", resourceCulture); | |||
} | |||
} | |||
/// <summary> | |||
/// Looks up a localized resource of type System.Byte[]. | |||
/// </summary> | |||
internal static byte[] polarssl_dll { | |||
internal static byte[] libsscrypto_dll { | |||
get { | |||
object obj = ResourceManager.GetObject("polarssl_dll", resourceCulture); | |||
object obj = ResourceManager.GetObject("libsscrypto_dll", resourceCulture); | |||
return ((byte[])(obj)); | |||
} | |||
} | |||
@@ -118,8 +118,11 @@ | |||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
</resheader> | |||
<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 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> | |||
@@ -30,30 +30,32 @@ | |||
{ | |||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); | |||
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.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.ServerPortTextBox = 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.panel2 = new System.Windows.Forms.Panel(); | |||
this.OKButton = 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.AddButton = new System.Windows.Forms.Button(); | |||
this.ServerGroupBox = new System.Windows.Forms.GroupBox(); | |||
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.panel1.SuspendLayout(); | |||
this.panel3.SuspendLayout(); | |||
this.ServerGroupBox.SuspendLayout(); | |||
this.tableLayoutPanel2.SuspendLayout(); | |||
this.tableLayoutPanel3.SuspendLayout(); | |||
this.tableLayoutPanel4.SuspendLayout(); | |||
this.SuspendLayout(); | |||
// | |||
// 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.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.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.ServerPortTextBox, 1, 1); | |||
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.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.Padding = new System.Windows.Forms.Padding(5); | |||
this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(3); | |||
this.tableLayoutPanel1.RowCount = 6; | |||
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.Size = new System.Drawing.Size(242, 167); | |||
this.tableLayoutPanel1.Size = new System.Drawing.Size(238, 163); | |||
this.tableLayoutPanel1.TabIndex = 0; | |||
// | |||
// RemarksTextBox | |||
// | |||
this.RemarksTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); | |||
this.RemarksTextBox.Location = new System.Drawing.Point(74, 139); | |||
this.RemarksTextBox.Location = new System.Drawing.Point(72, 137); | |||
this.RemarksTextBox.MaxLength = 32; | |||
this.RemarksTextBox.Name = "RemarksTextBox"; | |||
this.RemarksTextBox.Size = new System.Drawing.Size(160, 20); | |||
this.RemarksTextBox.TabIndex = 10; | |||
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 | |||
// | |||
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.Size = new System.Drawing.Size(160, 20); | |||
this.ProxyPortTextBox.TabIndex = 4; | |||
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 | |||
// | |||
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.Size = new System.Drawing.Size(160, 20); | |||
this.IPTextBox.TabIndex = 0; | |||
@@ -169,7 +174,8 @@ | |||
// ServerPortTextBox | |||
// | |||
this.ServerPortTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); | |||
this.ServerPortTextBox.Location = new System.Drawing.Point(74, 34); | |||
this.ServerPortTextBox.Location = new System.Drawing.Point(72, 32); | |||
this.ServerPortTextBox.MaxLength = 10; | |||
this.ServerPortTextBox.Name = "ServerPortTextBox"; | |||
this.ServerPortTextBox.Size = new System.Drawing.Size(160, 20); | |||
this.ServerPortTextBox.TabIndex = 1; | |||
@@ -178,22 +184,23 @@ | |||
// PasswordTextBox | |||
// | |||
this.PasswordTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); | |||
this.PasswordTextBox.Location = new System.Drawing.Point(74, 60); | |||
this.PasswordTextBox.Location = new System.Drawing.Point(72, 58); | |||
this.PasswordTextBox.MaxLength = 256; | |||
this.PasswordTextBox.Name = "PasswordTextBox"; | |||
this.PasswordTextBox.PasswordChar = '*'; | |||
this.PasswordTextBox.Size = new System.Drawing.Size(160, 20); | |||
this.PasswordTextBox.TabIndex = 2; | |||
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 | |||
// | |||
@@ -206,11 +213,13 @@ | |||
this.EncryptionSelect.Items.AddRange(new object[] { | |||
"table", | |||
"rc4-md5", | |||
"salsa20", | |||
"chacha20", | |||
"aes-256-cfb", | |||
"aes-192-cfb", | |||
"aes-128-cfb", | |||
"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.Size = new System.Drawing.Size(160, 21); | |||
this.EncryptionSelect.TabIndex = 3; | |||
@@ -220,7 +229,7 @@ | |||
this.panel2.Anchor = System.Windows.Forms.AnchorStyles.Top; | |||
this.panel2.AutoSize = true; | |||
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.Size = new System.Drawing.Size(0, 0); | |||
this.panel2.TabIndex = 1; | |||
@@ -228,7 +237,9 @@ | |||
// OKButton | |||
// | |||
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.Size = new System.Drawing.Size(75, 23); | |||
this.OKButton.TabIndex = 8; | |||
@@ -239,7 +250,9 @@ | |||
// MyCancelButton | |||
// | |||
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.Size = new System.Drawing.Size(75, 23); | |||
this.MyCancelButton.TabIndex = 9; | |||
@@ -247,34 +260,13 @@ | |||
this.MyCancelButton.UseVisualStyleBackColor = true; | |||
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 | |||
// | |||
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.Size = new System.Drawing.Size(89, 23); | |||
this.DeleteButton.Size = new System.Drawing.Size(80, 23); | |||
this.DeleteButton.TabIndex = 7; | |||
this.DeleteButton.Text = "&Delete"; | |||
this.DeleteButton.UseVisualStyleBackColor = true; | |||
@@ -282,9 +274,11 @@ | |||
// | |||
// 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.Size = new System.Drawing.Size(89, 23); | |||
this.AddButton.Size = new System.Drawing.Size(80, 23); | |||
this.AddButton.TabIndex = 6; | |||
this.AddButton.Text = "&Add"; | |||
this.AddButton.UseVisualStyleBackColor = true; | |||
@@ -292,10 +286,13 @@ | |||
// | |||
// ServerGroupBox | |||
// | |||
this.ServerGroupBox.AutoSize = true; | |||
this.ServerGroupBox.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; | |||
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.Size = new System.Drawing.Size(255, 205); | |||
this.ServerGroupBox.Size = new System.Drawing.Size(249, 200); | |||
this.ServerGroupBox.TabIndex = 6; | |||
this.ServerGroupBox.TabStop = false; | |||
this.ServerGroupBox.Text = "Server"; | |||
@@ -303,29 +300,88 @@ | |||
// ServersListBox | |||
// | |||
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.Size = new System.Drawing.Size(192, 173); | |||
this.ServersListBox.Size = new System.Drawing.Size(166, 148); | |||
this.ServersListBox.TabIndex = 5; | |||
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 | |||
// | |||
this.AcceptButton = this.OKButton; | |||
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.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.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; | |||
this.MaximizeBox = false; | |||
this.MinimizeBox = false; | |||
this.Name = "ConfigForm"; | |||
this.Padding = new System.Windows.Forms.Padding(12, 12, 12, 9); | |||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; | |||
this.Text = "Edit Servers"; | |||
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ConfigForm_FormClosed); | |||
@@ -333,10 +389,12 @@ | |||
this.Shown += new System.EventHandler(this.ConfigForm_Shown); | |||
this.tableLayoutPanel1.ResumeLayout(false); | |||
this.tableLayoutPanel1.PerformLayout(); | |||
this.panel1.ResumeLayout(false); | |||
this.panel3.ResumeLayout(false); | |||
this.ServerGroupBox.ResumeLayout(false); | |||
this.ServerGroupBox.PerformLayout(); | |||
this.tableLayoutPanel2.ResumeLayout(false); | |||
this.tableLayoutPanel2.PerformLayout(); | |||
this.tableLayoutPanel3.ResumeLayout(false); | |||
this.tableLayoutPanel4.ResumeLayout(false); | |||
this.ResumeLayout(false); | |||
this.PerformLayout(); | |||
@@ -345,27 +403,28 @@ | |||
#endregion | |||
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 ServerPortTextBox; | |||
private System.Windows.Forms.TextBox PasswordTextBox; | |||
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.Panel panel2; | |||
private System.Windows.Forms.Button OKButton; | |||
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 AddButton; | |||
private System.Windows.Forms.GroupBox ServerGroupBox; | |||
private System.Windows.Forms.ListBox ServersListBox; | |||
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; | |||
} | |||
} | |||
@@ -22,7 +22,14 @@ namespace Shadowsocks.View | |||
public ConfigForm(ShadowsocksController controller) | |||
{ | |||
this.Font = System.Drawing.SystemFonts.MessageBoxFont; | |||
InitializeComponent(); | |||
// a dirty hack | |||
this.ServersListBox.Dock = System.Windows.Forms.DockStyle.Fill; | |||
this.PerformLayout(); | |||
UpdateTexts(); | |||
this.Icon = Icon.FromHandle(Resources.ssw128.GetHicon()); | |||
this.controller = controller; | |||
@@ -31,6 +38,22 @@ namespace Shadowsocks.View | |||
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) | |||
{ | |||
LoadCurrentConfiguration(); | |||
@@ -67,7 +90,7 @@ namespace Shadowsocks.View | |||
} | |||
catch (FormatException) | |||
{ | |||
MessageBox.Show("illegal port number format"); | |||
MessageBox.Show(I18N.GetString("Illegal port number format")); | |||
} | |||
catch (Exception ex) | |||
{ | |||
@@ -102,7 +125,7 @@ namespace Shadowsocks.View | |||
ServersListBox.Items.Clear(); | |||
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) | |||
{ | |||
MessageBox.Show("Please add at least one server"); | |||
MessageBox.Show(I18N.GetString("Please add at least one server")); | |||
return; | |||
} | |||
controller.SaveServers(_modifiedConfiguration.configs); | |||
@@ -14,12 +14,12 @@ namespace Shadowsocks.View | |||
{ | |||
// yes this is just a menu view controller | |||
// 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 UpdateChecker updateChecker; | |||
private NotifyIcon notifyIcon1; | |||
private NotifyIcon _notifyIcon; | |||
private ContextMenu contextMenu1; | |||
private bool _isFirstRun; | |||
@@ -37,18 +37,29 @@ namespace Shadowsocks.View | |||
private MenuItem menuItem3; | |||
private MenuItem quitItem; | |||
private MenuItem menuItem1; | |||
private MenuItem modeItem; | |||
private MenuItem globalModeItem; | |||
private MenuItem PACModeItem; | |||
private ConfigForm configForm; | |||
public MenuViewController(ShadowsocksController controller) | |||
{ | |||
this.controller = controller; | |||
LoadMenu(); | |||
LoadTrayIcon(); | |||
this.controller = controller; | |||
controller.EnableStatusChanged += controller_EnableStatusChanged; | |||
controller.ConfigChanged += controller_ConfigChanged; | |||
controller.PACFileReadyToOpen += controller_PACFileReadyToOpen; | |||
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(); | |||
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; | |||
Graphics graphics = Graphics.FromHwnd(IntPtr.Zero); | |||
@@ -85,19 +101,33 @@ namespace Shadowsocks.View | |||
{ | |||
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() | |||
{ | |||
this.contextMenu1 = new System.Windows.Forms.ContextMenu(); | |||
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.ShareOverLANItem = 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.enableItem, | |||
this.modeItem, | |||
this.ServersItem, | |||
this.menuItem1, | |||
this.AutoStartupItem, | |||
@@ -132,28 +163,36 @@ namespace Shadowsocks.View | |||
// enableItem | |||
// | |||
this.enableItem.Index = 0; | |||
this.enableItem.Text = "&Enable"; | |||
this.enableItem.Text = I18N.GetString("Enable"); | |||
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 | |||
// | |||
this.ServersItem.Index = 1; | |||
this.ServersItem.Index = 2; | |||
this.ServersItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { | |||
this.SeperatorItem, | |||
this.ConfigItem}); | |||
this.ServersItem.Text = "&Servers"; | |||
this.ServersItem.Text = I18N.GetString("Servers"); | |||
// | |||
// SeperatorItem | |||
// | |||
@@ -163,58 +202,71 @@ namespace Shadowsocks.View | |||
// ConfigItem | |||
// | |||
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); | |||
// | |||
// 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 | |||
// | |||
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); | |||
// | |||
// menuItem4 | |||
// | |||
this.menuItem4.Index = 7; | |||
this.menuItem4.Text = "-"; | |||
// | |||
// 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); | |||
// | |||
// 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); | |||
// | |||
// 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); | |||
// | |||
// menuItem3 | |||
// | |||
this.menuItem3.Index = 10; | |||
this.menuItem3.Index = 11; | |||
this.menuItem3.Text = "-"; | |||
// | |||
// 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); | |||
// | |||
// menuItem1 | |||
// | |||
this.menuItem1.Index = 2; | |||
this.menuItem1.Text = "-"; | |||
} | |||
private void controller_ConfigChanged(object sender, EventArgs e) | |||
{ | |||
LoadCurrentConfiguration(); | |||
UpdateTrayIcon(); | |||
} | |||
private void controller_EnableStatusChanged(object sender, EventArgs e) | |||
@@ -227,6 +279,12 @@ namespace Shadowsocks.View | |||
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) | |||
{ | |||
string argument = @"/select, " + e.Path; | |||
@@ -236,11 +294,11 @@ namespace Shadowsocks.View | |||
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; | |||
} | |||
@@ -255,6 +313,8 @@ namespace Shadowsocks.View | |||
Configuration config = controller.GetConfiguration(); | |||
UpdateServersMenu(); | |||
enableItem.Checked = config.enabled; | |||
globalModeItem.Checked = config.global; | |||
PACModeItem.Checked = !config.global; | |||
ShareOverLANItem.Checked = config.shareOverLan; | |||
AutoStartupItem.Checked = AutoStartup.Check(); | |||
} | |||
@@ -269,7 +329,7 @@ namespace Shadowsocks.View | |||
for (int i = 0; i < configuration.configs.Count; 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.Click += AServerItem_Click; | |||
items.Add(item); | |||
@@ -312,7 +372,7 @@ namespace Shadowsocks.View | |||
private void Quit_Click(object sender, EventArgs e) | |||
{ | |||
controller.Stop(); | |||
notifyIcon1.Visible = false; | |||
_notifyIcon.Visible = false; | |||
Application.Exit(); | |||
} | |||
@@ -320,10 +380,10 @@ namespace Shadowsocks.View | |||
{ | |||
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; | |||
} | |||
} | |||
@@ -338,11 +398,19 @@ namespace Shadowsocks.View | |||
ShowConfigForm(); | |||
} | |||
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) | |||
@@ -29,49 +29,37 @@ | |||
private void InitializeComponent() | |||
{ | |||
this.pictureBox1 = new System.Windows.Forms.PictureBox(); | |||
this.panel1 = new System.Windows.Forms.Panel(); | |||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); | |||
this.panel1.SuspendLayout(); | |||
this.SuspendLayout(); | |||
// | |||
// 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.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.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 | |||
// | |||
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.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.MaximizeBox = false; | |||
this.MinimizeBox = false; | |||
this.Name = "QRCodeForm"; | |||
this.Padding = new System.Windows.Forms.Padding(9); | |||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; | |||
this.Text = "QRCode"; | |||
this.Load += new System.EventHandler(this.QRCodeForm_Load); | |||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); | |||
this.panel1.ResumeLayout(false); | |||
this.ResumeLayout(false); | |||
} | |||
@@ -79,6 +67,5 @@ | |||
#endregion | |||
private System.Windows.Forms.PictureBox pictureBox1; | |||
private System.Windows.Forms.Panel panel1; | |||
} | |||
} |
@@ -1,4 +1,5 @@ | |||
using QRCode4CS; | |||
using Shadowsocks.Controller; | |||
using Shadowsocks.Properties; | |||
using System; | |||
using System.Collections.Generic; | |||
@@ -21,6 +22,7 @@ namespace Shadowsocks.View | |||
this.code = code; | |||
InitializeComponent(); | |||
this.Icon = Icon.FromHandle(Resources.ssw128.GetHicon()); | |||
this.Text = I18N.GetString("QRCode"); | |||
} | |||
private void GenQR(string ssconfig) | |||
@@ -73,12 +73,16 @@ | |||
<Compile Include="3rd\SimpleJson.cs" /> | |||
<Compile Include="Controller\AutoStartup.cs" /> | |||
<Compile Include="Controller\FileManager.cs" /> | |||
<Compile Include="Controller\I18N.cs" /> | |||
<Compile Include="Controller\Logging.cs" /> | |||
<Compile Include="Controller\UpdateChecker.cs" /> | |||
<Compile Include="Encrypt\EncryptorBase.cs" /> | |||
<Compile Include="Encrypt\EncryptorFactory.cs" /> | |||
<Compile Include="Encrypt\IVEncryptor.cs" /> | |||
<Compile Include="Encrypt\PolarSSL.cs" /> | |||
<Compile Include="Encrypt\PolarSSLEncryptor.cs" /> | |||
<Compile Include="Encrypt\Sodium.cs" /> | |||
<Compile Include="Encrypt\SodiumEncryptor.cs" /> | |||
<Compile Include="Encrypt\TableEncryptor.cs" /> | |||
<Compile Include="Encrypt\IEncryptor.cs" /> | |||
<Compile Include="Controller\PACServer.cs" /> | |||
@@ -125,7 +129,7 @@ | |||
<None Include="app.manifest"> | |||
<SubType>Designer</SubType> | |||
</None> | |||
<None Include="Data\polarssl.dll.gz" /> | |||
<None Include="Data\libsscrypto.dll.gz" /> | |||
<None Include="Data\polipo.exe.gz" /> | |||
<None Include="Properties\Settings.settings"> | |||
<Generator>SettingsSingleFileGenerator</Generator> | |||
@@ -143,6 +147,7 @@ | |||
<None Include="Resources\ss16.png" /> | |||
<None Include="Resources\ss24.png" /> | |||
<None Include="Resources\ssw128.png" /> | |||
<Content Include="Data\cn.txt" /> | |||
<Content Include="shadowsocks.ico" /> | |||
<None Include="Data\polipo_config.txt" /> | |||
</ItemGroup> | |||
@@ -22,15 +22,50 @@ namespace test | |||
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] | |||
public void TestEncryption() | |||
public void TestPolarSSLEncryption() | |||
{ | |||
// run it once before the multi-threading test to initialize global tables | |||
RunSingleEncryptionThread(); | |||
RunSinglePolarSSLEncryptionThread(); | |||
List<Thread> threads = new List<Thread>(); | |||
for (int i = 0; i < 10; i++) | |||
{ | |||
Thread t = new Thread(new ThreadStart(RunSingleEncryptionThread)); | |||
Thread t = new Thread(new ThreadStart(RunSinglePolarSSLEncryptionThread)); | |||
threads.Add(t); | |||
t.Start(); | |||
} | |||
@@ -41,51 +76,98 @@ namespace test | |||
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 | |||
{ | |||
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 | |||
{ | |||