diff --git a/shadowsocks-csharp/Controller/Service/TCPRelay.cs b/shadowsocks-csharp/Controller/Service/TCPRelay.cs index bf0497d4..eef5948c 100644 --- a/shadowsocks-csharp/Controller/Service/TCPRelay.cs +++ b/shadowsocks-csharp/Controller/Service/TCPRelay.cs @@ -93,17 +93,18 @@ namespace Shadowsocks.Controller private int _firstPacketLength; // Size of receive buffer. public const int RecvSize = 8192; - public const int BufferSize = RecvSize + 32; + public const int RecvReserveSize = IVEncryptor.ONETIMEAUTH_BYTES + IVEncryptor.AUTH_BYTES; // reserve for one-time auth + public const int BufferSize = RecvSize + RecvReserveSize + 32; private int totalRead = 0; private int totalWrite = 0; // remote receive buffer - private byte[] remoteRecvBuffer = new byte[RecvSize]; + private byte[] remoteRecvBuffer = new byte[BufferSize]; // remote send buffer private byte[] remoteSendBuffer = new byte[BufferSize]; // connection receive buffer - private byte[] connetionRecvBuffer = new byte[RecvSize]; + private byte[] connetionRecvBuffer = new byte[BufferSize]; // connection send buffer private byte[] connetionSendBuffer = new byte[BufferSize]; // Received data string. @@ -124,7 +125,7 @@ namespace Shadowsocks.Controller { throw new ArgumentException("No server configured"); } - this.encryptor = EncryptorFactory.GetEncryptor(server.method, server.password); + this.encryptor = EncryptorFactory.GetEncryptor(server.method, server.password, server.one_time_auth, false); this.server = server; } diff --git a/shadowsocks-csharp/Controller/Service/UDPRelay.cs b/shadowsocks-csharp/Controller/Service/UDPRelay.cs index a0662dd2..b449c412 100644 --- a/shadowsocks-csharp/Controller/Service/UDPRelay.cs +++ b/shadowsocks-csharp/Controller/Service/UDPRelay.cs @@ -74,13 +74,13 @@ namespace Shadowsocks.Controller } public void Send(byte[] data, int length) { - IEncryptor encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password); - byte[] dataIn = new byte[length - 3]; + IEncryptor encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password, _server.one_time_auth, true); + byte[] dataIn = new byte[length - 3 + IVEncryptor.ONETIMEAUTH_BYTES]; Array.Copy(data, 3, dataIn, 0, length - 3); - byte[] dataOut = new byte[length - 3 + 16]; + byte[] dataOut = new byte[length - 3 + 16 + IVEncryptor.ONETIMEAUTH_BYTES]; int outlen; - encryptor.Encrypt(dataIn, dataIn.Length, dataOut, out outlen); - _remote.SendTo(dataOut, _remoteEndPoint); + encryptor.Encrypt(dataIn, length - 3, dataOut, out outlen); + _remote.SendTo(dataOut, outlen, SocketFlags.None, _remoteEndPoint); } public void Receive() { @@ -97,7 +97,7 @@ namespace Shadowsocks.Controller byte[] dataOut = new byte[bytesRead]; int outlen; - IEncryptor encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password); + IEncryptor encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password, _server.one_time_auth, true); encryptor.Decrypt(_buffer, bytesRead, dataOut, out outlen); byte[] sendBuf = new byte[outlen + 3]; diff --git a/shadowsocks-csharp/Controller/Service/UpdateChecker.cs b/shadowsocks-csharp/Controller/Service/UpdateChecker.cs index d48c0aae..643c7014 100644 --- a/shadowsocks-csharp/Controller/Service/UpdateChecker.cs +++ b/shadowsocks-csharp/Controller/Service/UpdateChecker.cs @@ -1,137 +1,212 @@ -using Shadowsocks.Model; -using System; +using System; using System.Collections; using System.Collections.Generic; using System.Net; using System.Reflection; using System.Text; using System.Text.RegularExpressions; +using System.IO; using SimpleJson; +using Shadowsocks.Model; +using Shadowsocks.Util; + namespace Shadowsocks.Controller { public class UpdateChecker { private const string UpdateURL = "https://api.github.com/repos/shadowsocks/shadowsocks-windows/releases"; + private const string UserAgent = "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.3319.102 Safari/537.36"; + private Configuration config; + public bool NewVersionFound; public string LatestVersionNumber; + public string LatestVersionName; public string LatestVersionURL; - public event EventHandler NewVersionFound; + public string LatestVersionLocalName; + public event EventHandler CheckUpdateCompleted; public const string Version = "2.5.8"; public void CheckUpdate(Configuration config) { - // TODO test failures - WebClient http = new WebClient(); - http.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.3319.102 Safari/537.36"); - http.Proxy = new WebProxy(IPAddress.Loopback.ToString(), config.localPort); - http.DownloadStringCompleted += http_DownloadStringCompleted; - http.DownloadStringAsync(new Uri(UpdateURL)); + this.config = config; + + try + { + WebClient http = CreateWebClient(); + http.DownloadStringCompleted += http_DownloadStringCompleted; + http.DownloadStringAsync(new Uri(UpdateURL)); + } + catch (Exception ex) + { + Logging.LogUsefulException(ex); + } } - public static int CompareVersion(string l, string r) + private void http_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { - var ls = l.Split('.'); - var rs = r.Split('.'); - for (int i = 0; i < Math.Max(ls.Length, rs.Length); i++) + try { - int lp = (i < ls.Length) ? int.Parse(ls[i]) : 0; - int rp = (i < rs.Length) ? int.Parse(rs[i]) : 0; - if (lp != rp) + string response = e.Result; + + JsonArray result = (JsonArray)SimpleJson.SimpleJson.DeserializeObject(e.Result); + + List asserts = new List(); + foreach (JsonObject release in result) + { + if ((bool)release["prerelease"]) + { + continue; + } + foreach (JsonObject asset in (JsonArray)release["assets"]) + { + Asset ass = new Asset(); + ass.Parse(asset); + if (ass.IsNewVersion(Version)) + { + asserts.Add(ass); + } + } + } + + if (asserts.Count != 0) { - return lp - rp; + SortByVersions(asserts); + Asset asset = asserts[asserts.Count - 1]; + NewVersionFound = true; + LatestVersionURL = asset.browser_download_url; + LatestVersionNumber = asset.version; + LatestVersionName = asset.name; + + startDownload(); } + else if (CheckUpdateCompleted != null) + { + CheckUpdateCompleted(this, new EventArgs()); + } + } + catch (Exception ex) + { + Logging.LogUsefulException(ex); } - return 0; } - public class VersionComparer : IComparer + private void startDownload() { - // Calls CaseInsensitiveComparer.Compare with the parameters reversed. - public int Compare(string x, string y) + try { - return CompareVersion(ParseVersionFromURL(x), ParseVersionFromURL(y)); + string temppath = Utils.GetTempPath(); + LatestVersionLocalName = Path.Combine(temppath, LatestVersionName); + WebClient http = CreateWebClient(); + http.DownloadFileCompleted += Http_DownloadFileCompleted; + http.DownloadFileAsync(new Uri(LatestVersionURL), LatestVersionLocalName); + } + catch (Exception ex) + { + Logging.LogUsefulException(ex); } } - private static string ParseVersionFromURL(string url) + private void Http_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) { - Match match = Regex.Match(url, @".*Shadowsocks-win.*?-([\d\.]+)\.\w+", RegexOptions.IgnoreCase); - if (match.Success) + try { - if (match.Groups.Count == 2) + if(e.Error != null) + { + Logging.LogUsefulException(e.Error); + return; + } + if (CheckUpdateCompleted != null) { - return match.Groups[1].Value; + CheckUpdateCompleted(this, new EventArgs()); } } - return null; + catch (Exception ex) + { + Logging.LogUsefulException(ex); + } } - private void SortVersions(List versions) + private WebClient CreateWebClient() { - versions.Sort(new VersionComparer()); + WebClient http = new WebClient(); + http.Headers.Add("User-Agent", UserAgent); + http.Proxy = new WebProxy(IPAddress.Loopback.ToString(), config.localPort); + return http; } - private bool IsNewVersion(string url) + private void SortByVersions(List asserts) { - if (url.IndexOf("prerelease") >= 0) - { - return false; - } - string version = ParseVersionFromURL(url); - if (version == null) - { - return false; - } - string currentVersion = Version; - - return CompareVersion(version, currentVersion) > 0; + asserts.Sort(new VersionComparer()); } - private void http_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) + public class Asset { - try + public bool prerelease; + public string name; + public string version; + public string browser_download_url; + + public bool IsNewVersion(string currentVersion) { - string response = e.Result; + if (prerelease) + { + return false; + } + if (version == null) + { + return false; + } + return CompareVersion(version, currentVersion) > 0; + } - JsonArray result = (JsonArray)SimpleJson.SimpleJson.DeserializeObject(e.Result); + public void Parse(JsonObject asset) + { + name = (string)asset["name"]; + browser_download_url = (string)asset["browser_download_url"]; + version = ParseVersionFromURL(browser_download_url); + prerelease = browser_download_url.IndexOf("prerelease") >= 0; + } - List versions = new List(); - foreach (JsonObject release in result) + private static string ParseVersionFromURL(string url) + { + Match match = Regex.Match(url, @".*Shadowsocks-win.*?-([\d\.]+)\.\w+", RegexOptions.IgnoreCase); + if (match.Success) { - if ((bool)release["prerelease"]) + if (match.Groups.Count == 2) { - continue; - } - foreach (JsonObject asset in (JsonArray)release["assets"]) - { - string url = (string)asset["browser_download_url"]; - if (IsNewVersion(url)) - { - versions.Add(url); - } + return match.Groups[1].Value; } } + return null; + } - if (versions.Count == 0) - { - return; - } - // sort versions - SortVersions(versions); - LatestVersionURL = versions[versions.Count - 1]; - LatestVersionNumber = ParseVersionFromURL(LatestVersionURL); - if (NewVersionFound != null) + public static int CompareVersion(string l, string r) + { + var ls = l.Split('.'); + var rs = r.Split('.'); + for (int i = 0; i < Math.Max(ls.Length, rs.Length); i++) { - NewVersionFound(this, new EventArgs()); + int lp = (i < ls.Length) ? int.Parse(ls[i]) : 0; + int rp = (i < rs.Length) ? int.Parse(rs[i]) : 0; + if (lp != rp) + { + return lp - rp; + } } + return 0; } - catch (Exception ex) + } + + class VersionComparer : IComparer + { + // Calls CaseInsensitiveComparer.Compare with the parameters reversed. + public int Compare(Asset x, Asset y) { - Logging.Debug(ex.ToString()); - return; + return Asset.CompareVersion(x.version, y.version); } } + } } diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index 7ef97eed..7761e3f8 100755 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -126,7 +126,7 @@ namespace Shadowsocks.Controller { _config.configs = servers; _config.localPort = localPort; - SaveConfig(_config); + Configuration.Save(_config); } public void SaveStrategyConfigurations(StatisticsStrategyConfiguration configuration) @@ -288,6 +288,18 @@ namespace Shadowsocks.Controller } } + public void ToggleCheckingUpdate(bool enabled) + { + _config.autoCheckUpdate = enabled; + Configuration.Save(_config); + } + + public void SaveLogViewerConfig(LogViewerConfig newConfig) + { + _config.logViewer = newConfig; + Configuration.Save(_config); + } + protected void Reload() { // some logic in configuration updated the config when saving, we need to read it again diff --git a/shadowsocks-csharp/Data/cn.txt b/shadowsocks-csharp/Data/cn.txt index 81022f99..b71a2803 100644 --- a/shadowsocks-csharp/Data/cn.txt +++ b/shadowsocks-csharp/Data/cn.txt @@ -21,6 +21,9 @@ Show QRCode...=显示二维码... Scan QRCode from Screen...=扫描屏幕上的二维码... Availability Statistics=统计可用性 Show Logs...=显示日志... +Updates...=更新... +Check for Updates...=检查更新 +Check for Updates at Startup=启动时检查更新 About...=关于... Quit=退出 Edit Servers=编辑服务器 @@ -39,6 +42,7 @@ Password=密码 Encryption=加密 Proxy Port=代理端口 Remarks=备注 +Onetime Authentication (Experimental)=一次性认证(实验性) OK=确定 Cancel=取消 New server=未配置的服务器 @@ -50,10 +54,12 @@ Move D&own=下移(&O) &File=文件(&F) &Open Location=在资源管理器中打开(&O) E&xit=退出(&X) -&Clean logs=清空(&C) -&Font=字体(&F) -&Wrap text=自动换行(&W) -&Top most=置顶(&T) +&View=视图(&V) +&Clean Logs=清空日志(&C) +Change &Font=设置字体(&F) +&Wrap Text=自动换行(&W) +&Top Most=置顶(&T) +&Show Toolbar=显示工具栏(&S) Log Viewer=日志查看器 # QRCode Form @@ -77,7 +83,8 @@ Password can not be blank=密码不能为空 Port out of range=端口超出范围 Port can't be 8123=端口不能为 8123 Shadowsocks {0} Update Found=Shadowsocks {0} 更新 -Click here to download=点击这里下载 +No update is available=没有可用的更新 +Click here to update=点击这里升级 Shadowsocks is here=Shadowsocks 在这里 You can turn on/off Shadowsocks in the context menu=可以在右键菜单中开关 Shadowsocks System Proxy Enabled=系统代理已启用 diff --git a/shadowsocks-csharp/Data/libsscrypto.dll.gz b/shadowsocks-csharp/Data/libsscrypto.dll.gz index 66a1185e..b0429860 100755 Binary files a/shadowsocks-csharp/Data/libsscrypto.dll.gz and b/shadowsocks-csharp/Data/libsscrypto.dll.gz differ diff --git a/shadowsocks-csharp/Encryption/EncryptorBase.cs b/shadowsocks-csharp/Encryption/EncryptorBase.cs index 8b5cd61a..8285f165 100644 --- a/shadowsocks-csharp/Encryption/EncryptorBase.cs +++ b/shadowsocks-csharp/Encryption/EncryptorBase.cs @@ -8,14 +8,18 @@ namespace Shadowsocks.Encryption { public const int MAX_INPUT_SIZE = 32768; - protected EncryptorBase(string method, string password) + protected EncryptorBase(string method, string password, bool onetimeauth, bool isudp) { Method = method; Password = password; + OnetimeAuth = onetimeauth; + IsUDP = isudp; } protected string Method; protected string Password; + protected bool OnetimeAuth; + protected bool IsUDP; protected byte[] GetPasswordHash() { diff --git a/shadowsocks-csharp/Encryption/EncryptorFactory.cs b/shadowsocks-csharp/Encryption/EncryptorFactory.cs index d5ff15e3..f0e2d284 100644 --- a/shadowsocks-csharp/Encryption/EncryptorFactory.cs +++ b/shadowsocks-csharp/Encryption/EncryptorFactory.cs @@ -8,7 +8,7 @@ namespace Shadowsocks.Encryption { private static Dictionary _registeredEncryptors; - private static Type[] _constructorTypes = new Type[] { typeof(string), typeof(string) }; + private static Type[] _constructorTypes = new Type[] { typeof(string), typeof(string), typeof(bool), typeof(bool) }; static EncryptorFactory() { @@ -27,7 +27,7 @@ namespace Shadowsocks.Encryption } } - public static IEncryptor GetEncryptor(string method, string password) + public static IEncryptor GetEncryptor(string method, string password, bool onetimeauth, bool isudp) { if (string.IsNullOrEmpty(method)) { @@ -36,7 +36,7 @@ namespace Shadowsocks.Encryption method = method.ToLowerInvariant(); Type t = _registeredEncryptors[method]; ConstructorInfo c = t.GetConstructor(_constructorTypes); - IEncryptor result = (IEncryptor)c.Invoke(new object[] { method, password }); + IEncryptor result = (IEncryptor)c.Invoke(new object[] { method, password, onetimeauth, isudp }); return result; } } diff --git a/shadowsocks-csharp/Encryption/IVEncryptor.cs b/shadowsocks-csharp/Encryption/IVEncryptor.cs index b82d3adf..52d1970b 100755 --- a/shadowsocks-csharp/Encryption/IVEncryptor.cs +++ b/shadowsocks-csharp/Encryption/IVEncryptor.cs @@ -2,12 +2,24 @@ using System.Collections.Generic; using System.Security.Cryptography; using System.Text; +using System.Net; namespace Shadowsocks.Encryption { public abstract class IVEncryptor : EncryptorBase { + public const int MAX_KEY_LENGTH = 64; + public const int MAX_IV_LENGTH = 16; + + public const int ONETIMEAUTH_FLAG = 0x10; + public const int ADDRTYPE_MASK = 0xF; + + public const int ONETIMEAUTH_BYTES = 10; + + public const int CLEN_BYTES = 2; + public const int AUTH_BYTES = ONETIMEAUTH_BYTES + CLEN_BYTES; + protected static byte[] tempbuf = new byte[MAX_INPUT_SIZE]; protected Dictionary ciphers; @@ -25,9 +37,11 @@ namespace Shadowsocks.Encryption protected byte[] _key; protected int keyLen; protected int ivLen; + protected uint counter = 0; + protected byte[] _keyBuffer = null; - public IVEncryptor(string method, string password) - : base(method, password) + public IVEncryptor(string method, string password, bool onetimeauth, bool isudp) + : base(method, password, onetimeauth, isudp) { InitKey(method, password); } @@ -112,14 +126,122 @@ namespace Shadowsocks.Encryption protected abstract void cipherUpdate(bool isCipher, int length, byte[] buf, byte[] outbuf); + protected int getHeadLen(byte[] buf, int length) + { + int len = 0; + int atyp = length > 0 ? (buf[0] & ADDRTYPE_MASK) : 0; + if (atyp == 1) + { + len = 7; // atyp (1 bytes) + ipv4 (4 bytes) + port (2 bytes) + } + else if (atyp == 3 && length > 1) + { + int nameLen = buf[1]; + len = 4 + nameLen; // atyp (1 bytes) + name length (1 bytes) + name (n bytes) + port (2 bytes) + } + else if (atyp == 4) + { + len = 19; // atyp (1 bytes) + ipv6 (16 bytes) + port (2 bytes) + } + if (len == 0 || len > length) + throw new Exception($"invalid header with addr type {atyp}"); + return len; + } + + protected byte[] genOnetimeAuthHash(byte[] msg, int msg_len) + { + byte[] auth = new byte[ONETIMEAUTH_BYTES]; + byte[] hash = new byte[20]; + byte[] auth_key = new byte[MAX_IV_LENGTH + MAX_KEY_LENGTH]; + Buffer.BlockCopy(_encryptIV, 0, auth_key, 0, ivLen); + Buffer.BlockCopy(_key, 0, auth_key, ivLen, keyLen); + Sodium.ss_sha1_hmac_ex(auth_key, (uint)(ivLen + keyLen), + msg, 0, (uint)msg_len, hash); + Buffer.BlockCopy(hash, 0, auth, 0, ONETIMEAUTH_BYTES); + return auth; + } + + protected void updateKeyBuffer() + { + if (_keyBuffer == null) + { + _keyBuffer = new byte[MAX_IV_LENGTH + 4]; + Buffer.BlockCopy(_encryptIV, 0, _keyBuffer, 0, ivLen); + } + + byte[] counter_bytes = BitConverter.GetBytes((uint)IPAddress.HostToNetworkOrder((int)counter)); + Buffer.BlockCopy(counter_bytes, 0, _keyBuffer, ivLen, 4); + counter++; + } + + protected byte[] genHash(byte[] buf, int offset, int len) + { + byte[] hash = new byte[20]; + updateKeyBuffer(); + Sodium.ss_sha1_hmac_ex(_keyBuffer, (uint)_keyBuffer.Length, + buf, offset, (uint)len, hash); + return hash; + } + + protected void reactBuffer4TCP(byte[] buf, ref int length) + { + if (!_encryptIVSent) + { + int headLen = getHeadLen(buf, length); + int dataLen = length - headLen; + buf[0] |= ONETIMEAUTH_FLAG; + byte[] hash = genOnetimeAuthHash(buf, headLen); + Buffer.BlockCopy(buf, headLen, buf, headLen + ONETIMEAUTH_BYTES + AUTH_BYTES, dataLen); + Buffer.BlockCopy(hash, 0, buf, headLen, ONETIMEAUTH_BYTES); + hash = genHash(buf, headLen + ONETIMEAUTH_BYTES + AUTH_BYTES, dataLen); + Buffer.BlockCopy(hash, 0, buf, headLen + ONETIMEAUTH_BYTES + CLEN_BYTES, ONETIMEAUTH_BYTES); + byte[] lenBytes = BitConverter.GetBytes((ushort)IPAddress.HostToNetworkOrder((short)dataLen)); + Buffer.BlockCopy(lenBytes, 0, buf, headLen + ONETIMEAUTH_BYTES, CLEN_BYTES); + length = headLen + ONETIMEAUTH_BYTES + AUTH_BYTES + dataLen; + } + else + { + byte[] hash = genHash(buf, 0, length); + Buffer.BlockCopy(buf, 0, buf, AUTH_BYTES, length); + byte[] lenBytes = BitConverter.GetBytes((ushort)IPAddress.HostToNetworkOrder((short)length)); + Buffer.BlockCopy(lenBytes, 0, buf, 0, CLEN_BYTES); + Buffer.BlockCopy(hash, 0, buf, CLEN_BYTES, ONETIMEAUTH_BYTES); + length += AUTH_BYTES; + } + } + + protected void reactBuffer4UDP(byte[] buf, ref int length) + { + buf[0] |= ONETIMEAUTH_FLAG; + byte[] hash = genOnetimeAuthHash(buf, length); + Buffer.BlockCopy(hash, 0, buf, length, ONETIMEAUTH_BYTES); + length += ONETIMEAUTH_BYTES; + } + + protected void reactBuffer(byte[] buf, ref int length) + { + if (OnetimeAuth && ivLen > 0) + { + if (!IsUDP) + { + reactBuffer4TCP(buf, ref length); + } + else + { + reactBuffer4UDP(buf, ref length); + } + } + } + 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; + reactBuffer(buf, ref length); + _encryptIVSent = true; lock (tempbuf) { cipherUpdate(true, length, buf, tempbuf); @@ -129,6 +251,7 @@ namespace Shadowsocks.Encryption } else { + reactBuffer(buf, ref length); outlength = length; cipherUpdate(true, length, buf, outbuf); } @@ -154,5 +277,6 @@ namespace Shadowsocks.Encryption cipherUpdate(false, length, buf, outbuf); } } + } } diff --git a/shadowsocks-csharp/Encryption/PolarSSLEncryptor.cs b/shadowsocks-csharp/Encryption/PolarSSLEncryptor.cs index 6216c24d..3b3331f9 100755 --- a/shadowsocks-csharp/Encryption/PolarSSLEncryptor.cs +++ b/shadowsocks-csharp/Encryption/PolarSSLEncryptor.cs @@ -16,8 +16,8 @@ namespace Shadowsocks.Encryption private IntPtr _encryptCtx = IntPtr.Zero; private IntPtr _decryptCtx = IntPtr.Zero; - public PolarSSLEncryptor(string method, string password) - : base(method, password) + public PolarSSLEncryptor(string method, string password, bool onetimeauth, bool isudp) + : base(method, password, onetimeauth, isudp) { InitKey(method, password); } diff --git a/shadowsocks-csharp/Encryption/Sodium.cs b/shadowsocks-csharp/Encryption/Sodium.cs index 564aaeda..8d690dd2 100755 --- a/shadowsocks-csharp/Encryption/Sodium.cs +++ b/shadowsocks-csharp/Encryption/Sodium.cs @@ -20,7 +20,6 @@ namespace Shadowsocks.Encryption try { FileManager.UncompressFile(dllPath, Resources.libsscrypto_dll); - LoadLibrary(dllPath); } catch (IOException) { @@ -36,9 +35,16 @@ namespace Shadowsocks.Encryption 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); + public extern static int 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); + public extern static int crypto_stream_chacha20_xor_ic(byte[] c, byte[] m, ulong mlen, byte[] n, ulong ic, byte[] k); + + [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] + public extern static void ss_sha1_hmac_ex(byte[] key, uint keylen, + byte[] input, int ioff, uint ilen, + byte[] output); + } } + diff --git a/shadowsocks-csharp/Encryption/SodiumEncryptor.cs b/shadowsocks-csharp/Encryption/SodiumEncryptor.cs index af51d0ac..a18d2a69 100755 --- a/shadowsocks-csharp/Encryption/SodiumEncryptor.cs +++ b/shadowsocks-csharp/Encryption/SodiumEncryptor.cs @@ -20,8 +20,8 @@ namespace Shadowsocks.Encryption protected ulong _encryptIC; protected ulong _decryptIC; - public SodiumEncryptor(string method, string password) - : base(method, password) + public SodiumEncryptor(string method, string password, bool onetimeauth, bool isudp) + : base(method, password, onetimeauth, isudp) { InitKey(method, password); } diff --git a/shadowsocks-csharp/Encryption/TableEncryptor.cs b/shadowsocks-csharp/Encryption/TableEncryptor.cs index db0a7db0..4b6c8fe3 100644 --- a/shadowsocks-csharp/Encryption/TableEncryptor.cs +++ b/shadowsocks-csharp/Encryption/TableEncryptor.cs @@ -6,8 +6,8 @@ namespace Shadowsocks.Encryption public class TableEncryptor : EncryptorBase { - public TableEncryptor(string method, string password) - : base(method, password) + public TableEncryptor(string method, string password, bool onetimeauth, bool isudp) + : base(method, password, onetimeauth, isudp) { byte[] hash = GetPasswordHash(); // TODO endian diff --git a/shadowsocks-csharp/Model/Configuration.cs b/shadowsocks-csharp/Model/Configuration.cs index ea8ff27f..58f9f941 100755 --- a/shadowsocks-csharp/Model/Configuration.cs +++ b/shadowsocks-csharp/Model/Configuration.cs @@ -24,6 +24,8 @@ namespace Shadowsocks.Model public string pacUrl; public bool useOnlinePac; public bool availabilityStatistics; + public bool autoCheckUpdate; + public LogViewerConfig logViewer; private static string CONFIG_FILE = "gui-config.json"; @@ -77,6 +79,7 @@ namespace Shadowsocks.Model index = 0, isDefault = true, localPort = 1080, + autoCheckUpdate = true, configs = new List() { GetDefaultServer() diff --git a/shadowsocks-csharp/Model/LogViewerConfig.cs b/shadowsocks-csharp/Model/LogViewerConfig.cs new file mode 100644 index 00000000..c82f1b22 --- /dev/null +++ b/shadowsocks-csharp/Model/LogViewerConfig.cs @@ -0,0 +1,80 @@ +using System; +using System.Drawing; + +namespace Shadowsocks.Model +{ + [Serializable] + public class LogViewerConfig + { + public string fontName; + public float fontSize; + public string bgColor; + public string textColor; + public bool topMost; + public bool wrapText; + public bool toolbarShown; + + public LogViewerConfig() + { + this.fontName = "Consolas"; + this.fontSize = 8; + this.bgColor = "black"; + this.textColor = "white"; + this.topMost = false; + this.wrapText = false; + this.toolbarShown = false; + } + + public Font GetFont() + { + try + { + return new Font(fontName, fontSize, FontStyle.Regular); + } + catch (Exception) + { + return new Font("Console", 8F); + } + } + + public void SetFont(Font font) + { + fontName = font.Name; + fontSize = font.Size; + } + + public Color GetBackgroundColor() + { + try + { + return ColorTranslator.FromHtml(bgColor); + } + catch (Exception) + { + return ColorTranslator.FromHtml("black"); + } + } + + public void SetBackgroundColor(Color color) + { + bgColor = ColorTranslator.ToHtml(color); + } + + public Color GetTextColor() + { + try + { + return ColorTranslator.FromHtml(textColor); + } + catch (Exception) + { + return ColorTranslator.FromHtml("white"); + } + } + + public void SetTextColor(Color color) + { + textColor = ColorTranslator.ToHtml(color); + } + } +} diff --git a/shadowsocks-csharp/Model/Server.cs b/shadowsocks-csharp/Model/Server.cs index 24dd1162..55134335 100755 --- a/shadowsocks-csharp/Model/Server.cs +++ b/shadowsocks-csharp/Model/Server.cs @@ -17,6 +17,7 @@ namespace Shadowsocks.Model public string password; public string method; public string remarks; + public bool one_time_auth; public override int GetHashCode() { @@ -52,6 +53,7 @@ namespace Shadowsocks.Model this.method = "aes-256-cfb"; this.password = ""; this.remarks = ""; + this.one_time_auth = false; } public Server(string ssURL) : this() @@ -88,6 +90,9 @@ namespace Shadowsocks.Model string[] parts = beforeAt.Split(new[] { ':' }); this.method = parts[0]; this.password = parts[1]; + + //TODO: read one_time_auth + } catch (IndexOutOfRangeException) { diff --git a/shadowsocks-csharp/Properties/Resources.Designer.cs b/shadowsocks-csharp/Properties/Resources.Designer.cs index 198e9f48..1205845f 100644 --- a/shadowsocks-csharp/Properties/Resources.Designer.cs +++ b/shadowsocks-csharp/Properties/Resources.Designer.cs @@ -10,8 +10,8 @@ namespace Shadowsocks.Properties { using System; - - + + /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -31,7 +31,7 @@ namespace Shadowsocks.Properties { [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resources() { } - + /// /// Returns the cached ResourceManager instance used by this class. /// @@ -45,7 +45,7 @@ namespace Shadowsocks.Properties { return resourceMan; } } - + /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. @@ -59,7 +59,7 @@ namespace Shadowsocks.Properties { resourceCulture = value; } } - + /// /// Looks up a localized resource of type System.Byte[]. /// @@ -69,39 +69,37 @@ namespace Shadowsocks.Properties { return ((byte[])(obj)); } } - + /// - /// Looks up a localized string similar to # translation for Simplified Chinese - /// - ///Shadowsocks=Shadowsocks - /// - ///# Menu items - /// - ///Enable System Proxy=启用系统代理 - ///Mode=系统代理模式 - ///PAC=PAC 模式 - ///Global=全局模式 - ///Servers=服务器 - ///Edit Servers...=编辑服务器... - ///Start on Boot=开机启动 - ///Allow Clients from LAN=允许来自局域网的连接 - ///Local PAC=使用本地 PAC - ///Online PAC=使用在线 PAC - ///Edit Local PAC File...=编辑本地 PAC 文件... - ///Update Local PAC from GFWList=从 GFWList 更新本地 PAC - ///Edit User Rule for GFWList...=编辑 GFWList 的用户规则... - ///Show QRCode...=显示二维码... - ///Scan QRCode from Screen...=扫描屏幕上的二维码... - ///Show Logs...=显示日志... - ///About...=关于... - ///Quit=退出 [rest of string was truncated]";. + /// Looks up a localized string similar to # translation for Simplified Chinese + /// + ///Shadowsocks=Shadowsocks + /// + ///# Menu items + /// + ///Enable System Proxy=启用系统代理 + ///Mode=系统代理模式 + ///PAC=PAC 模式 + ///Global=全局模式 + ///Servers=服务器 + ///Edit Servers...=编辑服务器... + ///Start on Boot=开机启动 + ///Allow Clients from LAN=允许来自局域网的连接 + ///Local PAC=使用本地 PAC + ///Online PAC=使用在线 PAC + ///Edit Local PAC File...=编辑本地 PAC 文件... + ///Update Local PAC from GFWList=从 GFWList 更新本地 PAC + ///Edit User Rule for GFWList...=编辑 GFWList 的用户规则... + ///Show QRCode...=显示二维码... + ///Scan QRCode from Screen...=扫描屏幕上的二维码... + ///Availability Statistic [rest of string was truncated]";. /// internal static string cn { get { return ResourceManager.GetString("cn", resourceCulture); } } - + /// /// Looks up a localized resource of type System.Byte[]. /// @@ -111,7 +109,7 @@ namespace Shadowsocks.Properties { return ((byte[])(obj)); } } - + /// /// Looks up a localized resource of type System.Byte[]. /// @@ -121,7 +119,7 @@ namespace Shadowsocks.Properties { return ((byte[])(obj)); } } - + /// /// Looks up a localized string similar to listen-address __POLIPO_BIND_IP__:8123 ///show-on-task-bar 0 @@ -134,7 +132,7 @@ namespace Shadowsocks.Properties { return ResourceManager.GetString("privoxy_conf", resourceCulture); } } - + /// /// Looks up a localized resource of type System.Byte[]. /// @@ -144,7 +142,7 @@ namespace Shadowsocks.Properties { return ((byte[])(obj)); } } - + /// /// Looks up a localized resource of type System.Byte[]. /// @@ -154,7 +152,7 @@ namespace Shadowsocks.Properties { return ((byte[])(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -164,7 +162,7 @@ namespace Shadowsocks.Properties { return ((System.Drawing.Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -174,7 +172,7 @@ namespace Shadowsocks.Properties { return ((System.Drawing.Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -184,7 +182,7 @@ namespace Shadowsocks.Properties { return ((System.Drawing.Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -194,7 +192,7 @@ namespace Shadowsocks.Properties { return ((System.Drawing.Bitmap)(obj)); } } - + /// /// Looks up a localized string similar to ! Put user rules line by line in this file. ///! See https://adblockplus.org/en/filter-cheatsheet diff --git a/shadowsocks-csharp/View/ConfigForm.Designer.cs b/shadowsocks-csharp/View/ConfigForm.Designer.cs index f8b5940a..8c5334d0 100755 --- a/shadowsocks-csharp/View/ConfigForm.Designer.cs +++ b/shadowsocks-csharp/View/ConfigForm.Designer.cs @@ -3,14 +3,14 @@ partial class ConfigForm { /// - /// 必需的设计器变量。 + /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// - /// 清理所有正在使用的资源。 + /// Clean up any resources being used. /// - /// 如果应释放托管资源,为 true;否则为 false。 + /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) @@ -20,11 +20,11 @@ base.Dispose(disposing); } - #region Windows 窗体设计器生成的代码 + #region Windows Form Designer generated code /// - /// 设计器支持所需的方法 - 不要 - /// 使用代码编辑器修改此方法的内容。 + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. /// private void InitializeComponent() { @@ -39,6 +39,7 @@ this.PasswordTextBox = new System.Windows.Forms.TextBox(); this.EncryptionLabel = new System.Windows.Forms.Label(); this.EncryptionSelect = new System.Windows.Forms.ComboBox(); + this.OneTimeAuth = new System.Windows.Forms.CheckBox(); this.panel2 = new System.Windows.Forms.Panel(); this.OKButton = new System.Windows.Forms.Button(); this.MyCancelButton = new System.Windows.Forms.Button(); @@ -81,37 +82,39 @@ this.tableLayoutPanel1.Controls.Add(this.PasswordTextBox, 1, 2); this.tableLayoutPanel1.Controls.Add(this.EncryptionLabel, 0, 3); this.tableLayoutPanel1.Controls.Add(this.EncryptionSelect, 1, 3); + this.tableLayoutPanel1.Controls.Add(this.OneTimeAuth, 1, 6); this.tableLayoutPanel1.Location = new System.Drawing.Point(8, 21); this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(3); - this.tableLayoutPanel1.RowCount = 6; + this.tableLayoutPanel1.RowCount = 7; 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(238, 137); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.Size = new System.Drawing.Size(249, 162); 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(72, 111); + this.RemarksTextBox.Location = new System.Drawing.Point(83, 113); this.RemarksTextBox.MaxLength = 32; this.RemarksTextBox.Name = "RemarksTextBox"; - this.RemarksTextBox.Size = new System.Drawing.Size(160, 20); - this.RemarksTextBox.TabIndex = 10; + this.RemarksTextBox.Size = new System.Drawing.Size(160, 21); + this.RemarksTextBox.TabIndex = 4; this.RemarksTextBox.WordWrap = false; // // RemarksLabel // this.RemarksLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.RemarksLabel.AutoSize = true; - this.RemarksLabel.Location = new System.Drawing.Point(17, 114); + this.RemarksLabel.Location = new System.Drawing.Point(30, 117); this.RemarksLabel.Name = "RemarksLabel"; - this.RemarksLabel.Size = new System.Drawing.Size(49, 13); + this.RemarksLabel.Size = new System.Drawing.Size(47, 12); this.RemarksLabel.TabIndex = 9; this.RemarksLabel.Text = "Remarks"; // @@ -119,9 +122,9 @@ // this.IPLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.IPLabel.AutoSize = true; - this.IPLabel.Location = new System.Drawing.Point(15, 9); + this.IPLabel.Location = new System.Drawing.Point(18, 10); this.IPLabel.Name = "IPLabel"; - this.IPLabel.Size = new System.Drawing.Size(51, 13); + this.IPLabel.Size = new System.Drawing.Size(59, 12); this.IPLabel.TabIndex = 0; this.IPLabel.Text = "Server IP"; // @@ -129,9 +132,9 @@ // this.ServerPortLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.ServerPortLabel.AutoSize = true; - this.ServerPortLabel.Location = new System.Drawing.Point(6, 35); + this.ServerPortLabel.Location = new System.Drawing.Point(6, 37); this.ServerPortLabel.Name = "ServerPortLabel"; - this.ServerPortLabel.Size = new System.Drawing.Size(60, 13); + this.ServerPortLabel.Size = new System.Drawing.Size(71, 12); this.ServerPortLabel.TabIndex = 1; this.ServerPortLabel.Text = "Server Port"; // @@ -139,40 +142,40 @@ // this.PasswordLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.PasswordLabel.AutoSize = true; - this.PasswordLabel.Location = new System.Drawing.Point(13, 61); + this.PasswordLabel.Location = new System.Drawing.Point(24, 64); this.PasswordLabel.Name = "PasswordLabel"; - this.PasswordLabel.Size = new System.Drawing.Size(53, 13); + this.PasswordLabel.Size = new System.Drawing.Size(53, 12); 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(72, 6); + this.IPTextBox.Location = new System.Drawing.Point(83, 6); this.IPTextBox.MaxLength = 512; this.IPTextBox.Name = "IPTextBox"; - this.IPTextBox.Size = new System.Drawing.Size(160, 20); + this.IPTextBox.Size = new System.Drawing.Size(160, 21); this.IPTextBox.TabIndex = 0; this.IPTextBox.WordWrap = false; // // ServerPortTextBox // this.ServerPortTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.ServerPortTextBox.Location = new System.Drawing.Point(72, 32); + this.ServerPortTextBox.Location = new System.Drawing.Point(83, 33); this.ServerPortTextBox.MaxLength = 10; this.ServerPortTextBox.Name = "ServerPortTextBox"; - this.ServerPortTextBox.Size = new System.Drawing.Size(160, 20); + this.ServerPortTextBox.Size = new System.Drawing.Size(160, 21); this.ServerPortTextBox.TabIndex = 1; this.ServerPortTextBox.WordWrap = false; // // PasswordTextBox // this.PasswordTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.PasswordTextBox.Location = new System.Drawing.Point(72, 58); + this.PasswordTextBox.Location = new System.Drawing.Point(83, 60); this.PasswordTextBox.MaxLength = 256; this.PasswordTextBox.Name = "PasswordTextBox"; this.PasswordTextBox.PasswordChar = '*'; - this.PasswordTextBox.Size = new System.Drawing.Size(160, 20); + this.PasswordTextBox.Size = new System.Drawing.Size(160, 21); this.PasswordTextBox.TabIndex = 2; this.PasswordTextBox.WordWrap = false; // @@ -180,20 +183,20 @@ // this.EncryptionLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.EncryptionLabel.AutoSize = true; - this.EncryptionLabel.Location = new System.Drawing.Point(9, 88); + this.EncryptionLabel.Location = new System.Drawing.Point(12, 91); this.EncryptionLabel.Name = "EncryptionLabel"; - this.EncryptionLabel.Size = new System.Drawing.Size(57, 13); + this.EncryptionLabel.Size = new System.Drawing.Size(65, 12); this.EncryptionLabel.TabIndex = 8; this.EncryptionLabel.Text = "Encryption"; // // EncryptionSelect // - this.EncryptionSelect.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + this.EncryptionSelect.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.EncryptionSelect.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.EncryptionSelect.FormattingEnabled = true; this.EncryptionSelect.ImeMode = System.Windows.Forms.ImeMode.NoControl; - this.EncryptionSelect.ItemHeight = 13; + this.EncryptionSelect.ItemHeight = 12; this.EncryptionSelect.Items.AddRange(new object[] { "table", "rc4-md5", @@ -203,10 +206,21 @@ "aes-192-cfb", "aes-128-cfb", "rc4"}); - this.EncryptionSelect.Location = new System.Drawing.Point(72, 84); + this.EncryptionSelect.Location = new System.Drawing.Point(83, 87); this.EncryptionSelect.Name = "EncryptionSelect"; - this.EncryptionSelect.Size = new System.Drawing.Size(160, 21); + this.EncryptionSelect.Size = new System.Drawing.Size(160, 20); this.EncryptionSelect.TabIndex = 3; + this.EncryptionSelect.SelectedIndexChanged += new System.EventHandler(this.EncryptionSelect_SelectedIndexChanged); + // + // OneTimeAuth + // + this.OneTimeAuth.AutoSize = true; + this.OneTimeAuth.Location = new System.Drawing.Point(83, 140); + this.OneTimeAuth.Name = "OneTimeAuth"; + this.OneTimeAuth.Size = new System.Drawing.Size(156, 16); + this.OneTimeAuth.TabIndex = 5; + this.OneTimeAuth.Text = "Onetime Authentication"; + this.OneTimeAuth.UseVisualStyleBackColor = true; // // panel2 // @@ -226,7 +240,7 @@ this.OKButton.Margin = new System.Windows.Forms.Padding(3, 3, 3, 0); this.OKButton.Name = "OKButton"; this.OKButton.Size = new System.Drawing.Size(75, 23); - this.OKButton.TabIndex = 8; + this.OKButton.TabIndex = 12; this.OKButton.Text = "OK"; this.OKButton.UseVisualStyleBackColor = true; this.OKButton.Click += new System.EventHandler(this.OKButton_Click); @@ -239,7 +253,7 @@ this.MyCancelButton.Margin = new System.Windows.Forms.Padding(3, 3, 0, 0); this.MyCancelButton.Name = "MyCancelButton"; this.MyCancelButton.Size = new System.Drawing.Size(75, 23); - this.MyCancelButton.TabIndex = 9; + this.MyCancelButton.TabIndex = 13; this.MyCancelButton.Text = "Cancel"; this.MyCancelButton.UseVisualStyleBackColor = true; this.MyCancelButton.Click += new System.EventHandler(this.CancelButton_Click); @@ -251,7 +265,7 @@ this.DeleteButton.Margin = new System.Windows.Forms.Padding(3, 6, 0, 3); this.DeleteButton.Name = "DeleteButton"; this.DeleteButton.Size = new System.Drawing.Size(80, 23); - this.DeleteButton.TabIndex = 7; + this.DeleteButton.TabIndex = 9; this.DeleteButton.Text = "&Delete"; this.DeleteButton.UseVisualStyleBackColor = true; this.DeleteButton.Click += new System.EventHandler(this.DeleteButton_Click); @@ -263,7 +277,7 @@ this.AddButton.Margin = new System.Windows.Forms.Padding(0, 6, 3, 3); this.AddButton.Name = "AddButton"; this.AddButton.Size = new System.Drawing.Size(80, 23); - this.AddButton.TabIndex = 6; + this.AddButton.TabIndex = 8; this.AddButton.Text = "&Add"; this.AddButton.UseVisualStyleBackColor = true; this.AddButton.Click += new System.EventHandler(this.AddButton_Click); @@ -276,8 +290,8 @@ 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(249, 174); - this.ServerGroupBox.TabIndex = 6; + this.ServerGroupBox.Size = new System.Drawing.Size(260, 200); + this.ServerGroupBox.TabIndex = 0; this.ServerGroupBox.TabStop = false; this.ServerGroupBox.Text = "Server"; // @@ -290,7 +304,7 @@ this.ServersListBox.Margin = new System.Windows.Forms.Padding(0); this.ServersListBox.Name = "ServersListBox"; this.ServersListBox.Size = new System.Drawing.Size(166, 148); - this.ServersListBox.TabIndex = 5; + this.ServersListBox.TabIndex = 7; this.ServersListBox.SelectedIndexChanged += new System.EventHandler(this.ServersListBox_SelectedIndexChanged); // // tableLayoutPanel2 @@ -313,7 +327,7 @@ this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel2.Size = new System.Drawing.Size(427, 238); + this.tableLayoutPanel2.Size = new System.Drawing.Size(438, 265); this.tableLayoutPanel2.TabIndex = 7; // // tableLayoutPanel6 @@ -326,7 +340,7 @@ this.tableLayoutPanel6.Controls.Add(this.MoveDownButton, 1, 0); this.tableLayoutPanel6.Controls.Add(this.MoveUpButton, 0, 0); this.tableLayoutPanel6.Dock = System.Windows.Forms.DockStyle.Top; - this.tableLayoutPanel6.Location = new System.Drawing.Point(0, 211); + this.tableLayoutPanel6.Location = new System.Drawing.Point(0, 233); this.tableLayoutPanel6.Margin = new System.Windows.Forms.Padding(0); this.tableLayoutPanel6.Name = "tableLayoutPanel6"; this.tableLayoutPanel6.RowCount = 1; @@ -341,7 +355,7 @@ this.MoveDownButton.Margin = new System.Windows.Forms.Padding(3, 6, 0, 3); this.MoveDownButton.Name = "MoveDownButton"; this.MoveDownButton.Size = new System.Drawing.Size(80, 23); - this.MoveDownButton.TabIndex = 7; + this.MoveDownButton.TabIndex = 11; this.MoveDownButton.Text = "Move D&own"; this.MoveDownButton.UseVisualStyleBackColor = true; this.MoveDownButton.Click += new System.EventHandler(this.MoveDownButton_Click); @@ -353,7 +367,7 @@ this.MoveUpButton.Margin = new System.Windows.Forms.Padding(0, 6, 3, 3); this.MoveUpButton.Name = "MoveUpButton"; this.MoveUpButton.Size = new System.Drawing.Size(80, 23); - this.MoveUpButton.TabIndex = 6; + this.MoveUpButton.TabIndex = 10; this.MoveUpButton.Text = "Move &Up"; this.MoveUpButton.UseVisualStyleBackColor = true; this.MoveUpButton.Click += new System.EventHandler(this.MoveUpButton_Click); @@ -369,36 +383,36 @@ this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); this.tableLayoutPanel5.Controls.Add(this.ProxyPortTextBox, 1, 0); this.tableLayoutPanel5.Controls.Add(this.ProxyPortLabel, 0, 0); - this.tableLayoutPanel5.Location = new System.Drawing.Point(241, 174); + this.tableLayoutPanel5.Location = new System.Drawing.Point(242, 200); this.tableLayoutPanel5.Margin = new System.Windows.Forms.Padding(0); this.tableLayoutPanel5.Name = "tableLayoutPanel5"; this.tableLayoutPanel5.Padding = new System.Windows.Forms.Padding(3); this.tableLayoutPanel5.RowCount = 1; this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 26F)); - this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 26F)); - this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 26F)); - this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 26F)); - this.tableLayoutPanel5.Size = new System.Drawing.Size(186, 32); + this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 27F)); + this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 27F)); + this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 27F)); + this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 27F)); + this.tableLayoutPanel5.Size = new System.Drawing.Size(196, 33); this.tableLayoutPanel5.TabIndex = 9; // // ProxyPortTextBox // this.ProxyPortTextBox.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.ProxyPortTextBox.Location = new System.Drawing.Point(67, 6); + this.ProxyPortTextBox.Location = new System.Drawing.Point(77, 6); this.ProxyPortTextBox.MaxLength = 10; this.ProxyPortTextBox.Name = "ProxyPortTextBox"; - this.ProxyPortTextBox.Size = new System.Drawing.Size(113, 20); - this.ProxyPortTextBox.TabIndex = 4; + this.ProxyPortTextBox.Size = new System.Drawing.Size(113, 21); + this.ProxyPortTextBox.TabIndex = 6; this.ProxyPortTextBox.WordWrap = false; // // ProxyPortLabel // this.ProxyPortLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.ProxyPortLabel.AutoSize = true; - this.ProxyPortLabel.Location = new System.Drawing.Point(6, 9); + this.ProxyPortLabel.Location = new System.Drawing.Point(6, 10); this.ProxyPortLabel.Name = "ProxyPortLabel"; - this.ProxyPortLabel.Size = new System.Drawing.Size(55, 13); + this.ProxyPortLabel.Size = new System.Drawing.Size(65, 12); this.ProxyPortLabel.TabIndex = 3; this.ProxyPortLabel.Text = "Proxy Port"; // @@ -413,7 +427,7 @@ this.tableLayoutPanel3.Controls.Add(this.MyCancelButton, 1, 0); this.tableLayoutPanel3.Controls.Add(this.OKButton, 0, 0); this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Right; - this.tableLayoutPanel3.Location = new System.Drawing.Point(268, 209); + this.tableLayoutPanel3.Location = new System.Drawing.Point(279, 236); this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(3, 3, 0, 3); this.tableLayoutPanel3.Name = "tableLayoutPanel3"; this.tableLayoutPanel3.RowCount = 1; @@ -431,7 +445,7 @@ this.tableLayoutPanel4.Controls.Add(this.DeleteButton, 1, 0); this.tableLayoutPanel4.Controls.Add(this.AddButton, 0, 0); this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Top; - this.tableLayoutPanel4.Location = new System.Drawing.Point(0, 174); + 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; @@ -505,6 +519,7 @@ private System.Windows.Forms.TableLayoutPanel tableLayoutPanel6; private System.Windows.Forms.Button MoveDownButton; private System.Windows.Forms.Button MoveUpButton; + private System.Windows.Forms.CheckBox OneTimeAuth; } } diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index dc290249..9ae26583 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -48,6 +48,7 @@ namespace Shadowsocks.View EncryptionLabel.Text = I18N.GetString("Encryption"); ProxyPortLabel.Text = I18N.GetString("Proxy Port"); RemarksLabel.Text = I18N.GetString("Remarks"); + OneTimeAuth.Text = I18N.GetString("Onetime Authentication (Experimental)"); ServerGroupBox.Text = I18N.GetString("Server"); OKButton.Text = I18N.GetString("OK"); MyCancelButton.Text = I18N.GetString("Cancel"); @@ -82,7 +83,8 @@ namespace Shadowsocks.View server_port = int.Parse(ServerPortTextBox.Text), password = PasswordTextBox.Text, method = EncryptionSelect.Text, - remarks = RemarksTextBox.Text + remarks = RemarksTextBox.Text, + one_time_auth = OneTimeAuth.Checked }; int localPort = int.Parse(ProxyPortTextBox.Text); Configuration.CheckServer(server); @@ -115,6 +117,7 @@ namespace Shadowsocks.View ProxyPortTextBox.Text = _modifiedConfiguration.localPort.ToString(); EncryptionSelect.Text = server.method ?? "aes-256-cfb"; RemarksTextBox.Text = server.remarks; + OneTimeAuth.Checked = server.one_time_auth; } } @@ -319,5 +322,18 @@ namespace Shadowsocks.View MoveConfigItem(+1); // +1 means move forward } } + + private void EncryptionSelect_SelectedIndexChanged(object sender, EventArgs e) + { + if (EncryptionSelect.Text == "rc4" || EncryptionSelect.Text == "table") + { + OneTimeAuth.Enabled = false; + OneTimeAuth.Checked = false; + } + else + { + OneTimeAuth.Enabled = true; + } + } } } diff --git a/shadowsocks-csharp/View/LogForm.Designer.cs b/shadowsocks-csharp/View/LogForm.Designer.cs index d0913d16..a4fcfad1 100644 --- a/shadowsocks-csharp/View/LogForm.Designer.cs +++ b/shadowsocks-csharp/View/LogForm.Designer.cs @@ -30,19 +30,25 @@ { this.components = new System.ComponentModel.Container(); this.LogMessageTextBox = new System.Windows.Forms.TextBox(); - this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); - this.mainMenu1 = new System.Windows.Forms.MainMenu(this.components); + this.MainMenu = new System.Windows.Forms.MainMenu(this.components); this.FileMenuItem = new System.Windows.Forms.MenuItem(); this.OpenLocationMenuItem = new System.Windows.Forms.MenuItem(); this.ExitMenuItem = new System.Windows.Forms.MenuItem(); - this.panel1 = new System.Windows.Forms.Panel(); + this.ViewMenuItem = new System.Windows.Forms.MenuItem(); + this.CleanLogsMenuItem = new System.Windows.Forms.MenuItem(); + this.ChangeFontMenuItem = new System.Windows.Forms.MenuItem(); + this.WrapTextMenuItem = new System.Windows.Forms.MenuItem(); + this.TopMostMenuItem = new System.Windows.Forms.MenuItem(); + this.MenuItemSeparater = new System.Windows.Forms.MenuItem(); + this.ShowToolbarMenuItem = new System.Windows.Forms.MenuItem(); + this.TopMostCheckBox = new System.Windows.Forms.CheckBox(); this.ChangeFontButton = new System.Windows.Forms.Button(); this.CleanLogsButton = new System.Windows.Forms.Button(); this.WrapTextCheckBox = new System.Windows.Forms.CheckBox(); this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); - this.TopMostCheckBox = new System.Windows.Forms.CheckBox(); - this.panel1.SuspendLayout(); + this.ToolbarFlowLayoutPanel = new System.Windows.Forms.FlowLayoutPanel(); this.tableLayoutPanel1.SuspendLayout(); + this.ToolbarFlowLayoutPanel.SuspendLayout(); this.SuspendLayout(); // // LogMessageTextBox @@ -51,25 +57,20 @@ this.LogMessageTextBox.Dock = System.Windows.Forms.DockStyle.Fill; this.LogMessageTextBox.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.LogMessageTextBox.ForeColor = System.Drawing.Color.White; - this.LogMessageTextBox.Location = new System.Drawing.Point(3, 43); + this.LogMessageTextBox.Location = new System.Drawing.Point(3, 38); this.LogMessageTextBox.MaxLength = 2147483647; this.LogMessageTextBox.Multiline = true; this.LogMessageTextBox.Name = "LogMessageTextBox"; this.LogMessageTextBox.ReadOnly = true; this.LogMessageTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; - this.LogMessageTextBox.Size = new System.Drawing.Size(541, 307); + this.LogMessageTextBox.Size = new System.Drawing.Size(584, 377); this.LogMessageTextBox.TabIndex = 0; - this.LogMessageTextBox.WordWrap = false; - // - // contextMenuStrip1 - // - this.contextMenuStrip1.Name = "contextMenuStrip1"; - this.contextMenuStrip1.Size = new System.Drawing.Size(61, 4); // - // mainMenu1 + // MainMenu // - this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { - this.FileMenuItem}); + this.MainMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { + this.FileMenuItem, + this.ViewMenuItem}); // // FileMenuItem // @@ -91,21 +92,70 @@ this.ExitMenuItem.Text = "E&xit"; this.ExitMenuItem.Click += new System.EventHandler(this.ExitMenuItem_Click); // - // panel1 + // ViewMenuItem + // + this.ViewMenuItem.Index = 1; + this.ViewMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { + this.CleanLogsMenuItem, + this.ChangeFontMenuItem, + this.WrapTextMenuItem, + this.TopMostMenuItem, + this.MenuItemSeparater, + this.ShowToolbarMenuItem}); + this.ViewMenuItem.Text = "&View"; + // + // CleanLogsMenuItem + // + this.CleanLogsMenuItem.Index = 0; + this.CleanLogsMenuItem.Text = "&Clean Logs"; + this.CleanLogsMenuItem.Click += new System.EventHandler(this.CleanLogsMenuItem_Click); + // + // ChangeFontMenuItem + // + this.ChangeFontMenuItem.Index = 1; + this.ChangeFontMenuItem.Text = "Change &Font"; + this.ChangeFontMenuItem.Click += new System.EventHandler(this.ChangeFontMenuItem_Click); + // + // WrapTextMenuItem + // + this.WrapTextMenuItem.Index = 2; + this.WrapTextMenuItem.Text = "&Wrap Text"; + this.WrapTextMenuItem.Click += new System.EventHandler(this.WrapTextMenuItem_Click); + // + // TopMostMenuItem + // + this.TopMostMenuItem.Index = 3; + this.TopMostMenuItem.Text = "&Top Most"; + this.TopMostMenuItem.Click += new System.EventHandler(this.TopMostMenuItem_Click); + // + // MenuItemSeparater + // + this.MenuItemSeparater.Index = 4; + this.MenuItemSeparater.Text = "-"; + // + // ShowToolbarMenuItem // - this.panel1.Controls.Add(this.TopMostCheckBox); - this.panel1.Controls.Add(this.ChangeFontButton); - this.panel1.Controls.Add(this.CleanLogsButton); - this.panel1.Controls.Add(this.WrapTextCheckBox); - this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; - this.panel1.Location = new System.Drawing.Point(3, 3); - this.panel1.Name = "panel1"; - this.panel1.Size = new System.Drawing.Size(541, 34); - this.panel1.TabIndex = 1; + this.ShowToolbarMenuItem.Index = 5; + this.ShowToolbarMenuItem.Text = "&Show Toolbar"; + this.ShowToolbarMenuItem.Click += new System.EventHandler(this.ShowToolbarMenuItem_Click); + // + // TopMostCheckBox + // + this.TopMostCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.TopMostCheckBox.AutoSize = true; + this.TopMostCheckBox.Location = new System.Drawing.Point(249, 3); + this.TopMostCheckBox.Name = "TopMostCheckBox"; + this.TopMostCheckBox.Size = new System.Drawing.Size(72, 23); + this.TopMostCheckBox.TabIndex = 3; + this.TopMostCheckBox.Text = "&Top Most"; + this.TopMostCheckBox.UseVisualStyleBackColor = true; + this.TopMostCheckBox.CheckedChanged += new System.EventHandler(this.TopMostCheckBox_CheckedChanged); // // ChangeFontButton // - this.ChangeFontButton.Location = new System.Drawing.Point(107, 4); + this.ChangeFontButton.AutoSize = true; + this.ChangeFontButton.Location = new System.Drawing.Point(84, 3); this.ChangeFontButton.Name = "ChangeFontButton"; this.ChangeFontButton.Size = new System.Drawing.Size(75, 23); this.ChangeFontButton.TabIndex = 2; @@ -115,22 +165,25 @@ // // CleanLogsButton // - this.CleanLogsButton.Location = new System.Drawing.Point(9, 4); + this.CleanLogsButton.AutoSize = true; + this.CleanLogsButton.Location = new System.Drawing.Point(3, 3); this.CleanLogsButton.Name = "CleanLogsButton"; this.CleanLogsButton.Size = new System.Drawing.Size(75, 23); this.CleanLogsButton.TabIndex = 1; - this.CleanLogsButton.Text = "&Clean logs"; + this.CleanLogsButton.Text = "&Clean Logs"; this.CleanLogsButton.UseVisualStyleBackColor = true; this.CleanLogsButton.Click += new System.EventHandler(this.CleanLogsButton_Click); // // WrapTextCheckBox // + this.WrapTextCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); this.WrapTextCheckBox.AutoSize = true; - this.WrapTextCheckBox.Location = new System.Drawing.Point(209, 9); + this.WrapTextCheckBox.Location = new System.Drawing.Point(165, 3); this.WrapTextCheckBox.Name = "WrapTextCheckBox"; - this.WrapTextCheckBox.Size = new System.Drawing.Size(78, 16); + this.WrapTextCheckBox.Size = new System.Drawing.Size(78, 23); this.WrapTextCheckBox.TabIndex = 0; - this.WrapTextCheckBox.Text = "&Wrap text"; + this.WrapTextCheckBox.Text = "&Wrap Text"; this.WrapTextCheckBox.UseVisualStyleBackColor = true; this.WrapTextCheckBox.CheckedChanged += new System.EventHandler(this.WrapTextCheckBox_CheckedChanged); // @@ -138,45 +191,47 @@ // this.tableLayoutPanel1.ColumnCount = 1; this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel1.Controls.Add(this.panel1, 0, 0); this.tableLayoutPanel1.Controls.Add(this.LogMessageTextBox, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.ToolbarFlowLayoutPanel, 0, 0); this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; this.tableLayoutPanel1.RowCount = 2; - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F)); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel1.Size = new System.Drawing.Size(547, 353); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.Size = new System.Drawing.Size(590, 418); this.tableLayoutPanel1.TabIndex = 2; // - // TopMostCheckBox + // ToolbarFlowLayoutPanel // - this.TopMostCheckBox.AutoSize = true; - this.TopMostCheckBox.Location = new System.Drawing.Point(311, 9); - this.TopMostCheckBox.Name = "TopMostCheckBox"; - this.TopMostCheckBox.Size = new System.Drawing.Size(72, 16); - this.TopMostCheckBox.TabIndex = 3; - this.TopMostCheckBox.Text = "&Top most"; - this.TopMostCheckBox.UseVisualStyleBackColor = true; - this.TopMostCheckBox.CheckedChanged += new System.EventHandler(this.TopMostCheckBox_CheckedChanged); + this.ToolbarFlowLayoutPanel.AutoSize = true; + this.ToolbarFlowLayoutPanel.Controls.Add(this.CleanLogsButton); + this.ToolbarFlowLayoutPanel.Controls.Add(this.ChangeFontButton); + this.ToolbarFlowLayoutPanel.Controls.Add(this.WrapTextCheckBox); + this.ToolbarFlowLayoutPanel.Controls.Add(this.TopMostCheckBox); + this.ToolbarFlowLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; + this.ToolbarFlowLayoutPanel.Location = new System.Drawing.Point(3, 3); + this.ToolbarFlowLayoutPanel.Name = "ToolbarFlowLayoutPanel"; + this.ToolbarFlowLayoutPanel.Size = new System.Drawing.Size(584, 29); + this.ToolbarFlowLayoutPanel.TabIndex = 2; // // LogForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(547, 353); + this.ClientSize = new System.Drawing.Size(590, 418); this.Controls.Add(this.tableLayoutPanel1); - this.Menu = this.mainMenu1; + this.Menu = this.MainMenu; this.Name = "LogForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Log Viewer"; this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.LogForm_FormClosing); this.Load += new System.EventHandler(this.LogForm_Load); this.Shown += new System.EventHandler(this.LogForm_Shown); - this.panel1.ResumeLayout(false); - this.panel1.PerformLayout(); this.tableLayoutPanel1.ResumeLayout(false); this.tableLayoutPanel1.PerformLayout(); + this.ToolbarFlowLayoutPanel.ResumeLayout(false); + this.ToolbarFlowLayoutPanel.PerformLayout(); this.ResumeLayout(false); } @@ -184,16 +239,22 @@ #endregion private System.Windows.Forms.TextBox LogMessageTextBox; - private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; - private System.Windows.Forms.MainMenu mainMenu1; + private System.Windows.Forms.MainMenu MainMenu; private System.Windows.Forms.MenuItem FileMenuItem; private System.Windows.Forms.MenuItem OpenLocationMenuItem; private System.Windows.Forms.MenuItem ExitMenuItem; - private System.Windows.Forms.Panel panel1; private System.Windows.Forms.CheckBox WrapTextCheckBox; private System.Windows.Forms.Button CleanLogsButton; private System.Windows.Forms.Button ChangeFontButton; private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; private System.Windows.Forms.CheckBox TopMostCheckBox; + private System.Windows.Forms.MenuItem ViewMenuItem; + private System.Windows.Forms.MenuItem CleanLogsMenuItem; + private System.Windows.Forms.MenuItem ChangeFontMenuItem; + private System.Windows.Forms.MenuItem WrapTextMenuItem; + private System.Windows.Forms.MenuItem TopMostMenuItem; + private System.Windows.Forms.FlowLayoutPanel ToolbarFlowLayoutPanel; + private System.Windows.Forms.MenuItem MenuItemSeparater; + private System.Windows.Forms.MenuItem ShowToolbarMenuItem; } } \ No newline at end of file diff --git a/shadowsocks-csharp/View/LogForm.cs b/shadowsocks-csharp/View/LogForm.cs index c4fcaf51..e2bf9fdd 100644 --- a/shadowsocks-csharp/View/LogForm.cs +++ b/shadowsocks-csharp/View/LogForm.cs @@ -1,6 +1,4 @@ -using Shadowsocks.Controller; -using Shadowsocks.Properties; -using System; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; @@ -10,6 +8,10 @@ using System.Linq; using System.Text; using System.Windows.Forms; +using Shadowsocks.Controller; +using Shadowsocks.Properties; +using Shadowsocks.Model; + namespace Shadowsocks.View { public partial class LogForm : Form @@ -18,13 +20,25 @@ namespace Shadowsocks.View string filename; Timer timer; const int BACK_OFFSET = 65536; + ShadowsocksController controller; - public LogForm(string filename) + public LogForm(ShadowsocksController controller, string filename) { + this.controller = controller; this.filename = filename; InitializeComponent(); this.Icon = Icon.FromHandle(Resources.ssw128.GetHicon()); + LogViewerConfig config = controller.GetConfigurationCopy().logViewer; + if (config == null) + config = new LogViewerConfig(); + topMostTrigger = config.topMost; + wrapTextTrigger = config.wrapText; + toolbarTrigger = config.toolbarShown; + LogMessageTextBox.BackColor = config.GetBackgroundColor(); + LogMessageTextBox.ForeColor = config.GetTextColor(); + LogMessageTextBox.Font = config.GetFont(); + UpdateTexts(); } @@ -33,10 +47,16 @@ namespace Shadowsocks.View FileMenuItem.Text = I18N.GetString("&File"); OpenLocationMenuItem.Text = I18N.GetString("&Open Location"); ExitMenuItem.Text = I18N.GetString("E&xit"); - CleanLogsButton.Text = I18N.GetString("&Clean logs"); - ChangeFontButton.Text = I18N.GetString("&Font"); - WrapTextCheckBox.Text = I18N.GetString("&Wrap text"); - TopMostCheckBox.Text = I18N.GetString("&Top most"); + CleanLogsButton.Text = I18N.GetString("&Clean Logs"); + ChangeFontButton.Text = I18N.GetString("Change &Font"); + WrapTextCheckBox.Text = I18N.GetString("&Wrap Text"); + TopMostCheckBox.Text = I18N.GetString("&Top Most"); + ViewMenuItem.Text = I18N.GetString("&View"); + CleanLogsMenuItem.Text = I18N.GetString("&Clean Logs"); + ChangeFontMenuItem.Text = I18N.GetString("Change &Font"); + WrapTextMenuItem.Text = I18N.GetString("&Wrap Text"); + TopMostMenuItem.Text = I18N.GetString("&Top Most"); + ShowToolbarMenuItem.Text = I18N.GetString("&Show Toolbar"); this.Text = I18N.GetString("Log Viewer"); } @@ -58,7 +78,7 @@ namespace Shadowsocks.View string line = ""; while ((line = reader.ReadLine()) != null) - LogMessageTextBox.AppendText(line + "\r\n"); + LogMessageTextBox.AppendText(line + Environment.NewLine); LogMessageTextBox.ScrollToCaret(); @@ -78,7 +98,7 @@ namespace Shadowsocks.View while ((line = reader.ReadLine()) != null) { changed = true; - LogMessageTextBox.AppendText(line + "\r\n"); + LogMessageTextBox.AppendText(line + Environment.NewLine); } if (changed) @@ -97,11 +117,31 @@ namespace Shadowsocks.View timer.Interval = 300; timer.Tick += Timer_Tick; timer.Start(); + + topMostTriggerLock = true; + this.TopMost = TopMostMenuItem.Checked = TopMostCheckBox.Checked = topMostTrigger; + topMostTriggerLock = false; + + wrapTextTriggerLock = true; + LogMessageTextBox.WordWrap = WrapTextMenuItem.Checked = WrapTextCheckBox.Checked = wrapTextTrigger; + wrapTextTriggerLock = false; + + ToolbarFlowLayoutPanel.Visible = ShowToolbarMenuItem.Checked = toolbarTrigger; } private void LogForm_FormClosing(object sender, FormClosingEventArgs e) { timer.Stop(); + LogViewerConfig config = controller.GetConfigurationCopy().logViewer; + if (config == null) + config = new LogViewerConfig(); + config.topMost = topMostTrigger; + config.wrapText = wrapTextTrigger; + config.toolbarShown = toolbarTrigger; + config.SetFont(LogMessageTextBox.Font); + config.SetBackgroundColor(LogMessageTextBox.BackColor); + config.SetTextColor(LogMessageTextBox.ForeColor); + controller.SaveLogViewerConfig(config); } private void OpenLocationMenuItem_Click(object sender, EventArgs e) @@ -121,30 +161,125 @@ namespace Shadowsocks.View LogMessageTextBox.ScrollToCaret(); } - private void WrapTextCheckBox_CheckedChanged(object sender, EventArgs e) + #region Clean up the content in LogMessageTextBox. + private void DoCleanLogs() { - LogMessageTextBox.WordWrap = WrapTextCheckBox.Checked; - LogMessageTextBox.ScrollToCaret(); + LogMessageTextBox.Clear(); + } + + private void CleanLogsMenuItem_Click(object sender, EventArgs e) + { + DoCleanLogs(); } private void CleanLogsButton_Click(object sender, EventArgs e) { - LogMessageTextBox.Clear(); + DoCleanLogs(); + } + #endregion + + #region Change the font settings applied in LogMessageTextBox. + private void DoChangeFont() + { + try + { + FontDialog fd = new FontDialog(); + fd.Font = LogMessageTextBox.Font; + if (fd.ShowDialog() == DialogResult.OK) + { + LogMessageTextBox.Font = new Font(fd.Font.FontFamily, fd.Font.Size, fd.Font.Style); + } + } + catch (Exception ex) + { + Logging.LogUsefulException(ex); + MessageBox.Show(ex.Message); + } + } + + private void ChangeFontMenuItem_Click(object sender, EventArgs e) + { + DoChangeFont(); } private void ChangeFontButton_Click(object sender, EventArgs e) { - FontDialog fd = new FontDialog(); - fd.Font = LogMessageTextBox.Font; - if (fd.ShowDialog() == DialogResult.OK) + DoChangeFont(); + } + #endregion + + #region Trigger the log messages wrapable, or not. + bool wrapTextTrigger = false; + bool wrapTextTriggerLock = false; + + private void TriggerWrapText() + { + wrapTextTriggerLock = true; + + wrapTextTrigger = !wrapTextTrigger; + LogMessageTextBox.WordWrap = wrapTextTrigger; + LogMessageTextBox.ScrollToCaret(); + WrapTextMenuItem.Checked = WrapTextCheckBox.Checked = wrapTextTrigger; + + wrapTextTriggerLock = false; + } + + private void WrapTextMenuItem_Click(object sender, EventArgs e) + { + if (!wrapTextTriggerLock) { - LogMessageTextBox.Font = fd.Font; + TriggerWrapText(); } } + private void WrapTextCheckBox_CheckedChanged(object sender, EventArgs e) + { + if (!wrapTextTriggerLock) + { + TriggerWrapText(); + } + } + #endregion + + #region Trigger this window top most, or not. + bool topMostTrigger = false; + bool topMostTriggerLock = false; + + private void TriggerTopMost() + { + topMostTriggerLock = true; + + topMostTrigger = !topMostTrigger; + this.TopMost = topMostTrigger; + TopMostMenuItem.Checked = TopMostCheckBox.Checked = topMostTrigger; + + topMostTriggerLock = false; + } + private void TopMostCheckBox_CheckedChanged(object sender, EventArgs e) { - this.TopMost = TopMostCheckBox.Checked; + if (!topMostTriggerLock) + { + TriggerTopMost(); + } + } + + private void TopMostMenuItem_Click(object sender, EventArgs e) + { + if (!topMostTriggerLock) + { + TriggerTopMost(); + } + } + #endregion + + private bool toolbarTrigger = false; + + private void ShowToolbarMenuItem_Click(object sender, EventArgs e) + { + toolbarTrigger = !toolbarTrigger; + ToolbarFlowLayoutPanel.Visible = toolbarTrigger; + ShowToolbarMenuItem.Checked = toolbarTrigger; } } } diff --git a/shadowsocks-csharp/View/LogForm.resx b/shadowsocks-csharp/View/LogForm.resx index 34b690ce..e8bf04bf 100644 --- a/shadowsocks-csharp/View/LogForm.resx +++ b/shadowsocks-csharp/View/LogForm.resx @@ -117,10 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + 17, 17 - - 172, 17 - \ No newline at end of file diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index 05c0ba2d..b19a244f 100755 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -26,6 +26,7 @@ namespace Shadowsocks.View private ContextMenu contextMenu1; private bool _isFirstRun; + private bool _isStartupChecking; private MenuItem enableItem; private MenuItem modeItem; private MenuItem AutoStartupItem; @@ -41,6 +42,7 @@ namespace Shadowsocks.View private MenuItem updateFromGFWListItem; private MenuItem editGFWUserRuleItem; private MenuItem editOnlinePACItem; + private MenuItem autoCheckUpdatesToggleItem; private ConfigForm configForm; private string _urlToOpen; @@ -67,13 +69,19 @@ namespace Shadowsocks.View _notifyIcon.MouseDoubleClick += notifyIcon1_DoubleClick; this.updateChecker = new UpdateChecker(); - updateChecker.NewVersionFound += updateChecker_NewVersionFound; + updateChecker.CheckUpdateCompleted += updateChecker_CheckUpdateCompleted; LoadCurrentConfiguration(); - updateChecker.CheckUpdate(controller.GetConfigurationCopy()); + Configuration config = controller.GetConfigurationCopy(); - if (controller.GetConfigurationCopy().isDefault) + if (config.autoCheckUpdate) + { + _isStartupChecking = true; + updateChecker.CheckUpdate(config); + } + + if (config.isDefault) { _isFirstRun = true; ShowConfigForm(); @@ -181,6 +189,11 @@ namespace Shadowsocks.View this.ShareOverLANItem = CreateMenuItem("Allow Clients from LAN", new EventHandler(this.ShareOverLANItem_Click)), new MenuItem("-"), CreateMenuItem("Show Logs...", new EventHandler(this.ShowLogItem_Click)), + CreateMenuGroup("Updates...", new MenuItem[] { + CreateMenuItem("Check for Updates...", new EventHandler(this.checkUpdatesItem_Click)), + new MenuItem("-"), + this.autoCheckUpdatesToggleItem = CreateMenuItem("Check for Updates at Startup", new EventHandler(this.autoCheckUpdatesToggleItem_Click)), + }), CreateMenuItem("About...", new EventHandler(this.AboutItem_Click)), new MenuItem("-"), CreateMenuItem("Quit", new EventHandler(this.Quit_Click)) @@ -238,17 +251,27 @@ namespace Shadowsocks.View ShowBalloonTip(I18N.GetString("Shadowsocks"), result, ToolTipIcon.Info, 1000); } - void updateChecker_NewVersionFound(object sender, EventArgs e) + void updateChecker_CheckUpdateCompleted(object sender, EventArgs e) { - ShowBalloonTip(String.Format(I18N.GetString("Shadowsocks {0} Update Found"), updateChecker.LatestVersionNumber), I18N.GetString("Click here to download"), ToolTipIcon.Info, 5000); - _notifyIcon.BalloonTipClicked += notifyIcon1_BalloonTipClicked; - _isFirstRun = false; + if (updateChecker.NewVersionFound) + { + ShowBalloonTip(String.Format(I18N.GetString("Shadowsocks {0} Update Found"), updateChecker.LatestVersionNumber), I18N.GetString("Click here to update"), ToolTipIcon.Info, 5000); + _notifyIcon.BalloonTipClicked += notifyIcon1_BalloonTipClicked; + _isFirstRun = false; + } + else if (!_isStartupChecking) + { + ShowBalloonTip(I18N.GetString("Shadowsocks"), I18N.GetString("No update is available"), ToolTipIcon.Info, 5000); + _isFirstRun = false; + } + _isStartupChecking = false; } void notifyIcon1_BalloonTipClicked(object sender, EventArgs e) { - System.Diagnostics.Process.Start(updateChecker.LatestVersionURL); _notifyIcon.BalloonTipClicked -= notifyIcon1_BalloonTipClicked; + string argument = "/select, \"" + updateChecker.LatestVersionLocalName + "\""; + System.Diagnostics.Process.Start("explorer.exe", argument); } @@ -265,6 +288,7 @@ namespace Shadowsocks.View onlinePACItem.Checked = onlinePACItem.Enabled && config.useOnlinePac; localPACItem.Checked = !onlinePACItem.Checked; UpdatePACItemsEnabledStatus(); + UpdateUpdateMenu(); } private void UpdateServersMenu() @@ -342,7 +366,7 @@ namespace Shadowsocks.View if (_isFirstRun) { _notifyIcon.BalloonTipTitle = I18N.GetString("Shadowsocks is here"); - _notifyIcon.BalloonTipText = I18N.GetString("You can turn on/off Shadowsocks in the context menu"); + _notifyIcon.BalloonTipText = I18N.GetString("You can turn on/off Shadowsocks in the context menu"); _notifyIcon.BalloonTipIcon = ToolTipIcon.Info; _notifyIcon.ShowBalloonTip(0); _isFirstRun = false; @@ -414,7 +438,7 @@ namespace Shadowsocks.View { string argument = Logging.LogFile; - new LogForm(argument).Show(); + new LogForm(controller, argument).Show(); } private void StatisticsConfigItem_Click(object sender, EventArgs e) @@ -591,5 +615,23 @@ namespace Shadowsocks.View this.editOnlinePACItem.Enabled = true; } } + + private void UpdateUpdateMenu() + { + Configuration configuration = controller.GetConfigurationCopy(); + autoCheckUpdatesToggleItem.Checked = configuration.autoCheckUpdate; + } + + private void autoCheckUpdatesToggleItem_Click(object sender, EventArgs e) + { + Configuration configuration = controller.GetConfigurationCopy(); + controller.ToggleCheckingUpdate(!configuration.autoCheckUpdate); + UpdateUpdateMenu(); + } + + private void checkUpdatesItem_Click(object sender, EventArgs e) + { + updateChecker.CheckUpdate(controller.GetConfigurationCopy()); + } } } diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index 61660623..423268d8 100644 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -191,6 +191,7 @@ + diff --git a/test/UnitTest.cs b/test/UnitTest.cs index 8fdf3f28..1970e85f 100755 --- a/test/UnitTest.cs +++ b/test/UnitTest.cs @@ -13,19 +13,19 @@ namespace test [TestMethod] public void TestCompareVersion() { - Assert.IsTrue(UpdateChecker.CompareVersion("2.3.1.0", "2.3.1") == 0); - Assert.IsTrue(UpdateChecker.CompareVersion("1.2", "1.3") < 0); - Assert.IsTrue(UpdateChecker.CompareVersion("1.3", "1.2") > 0); - Assert.IsTrue(UpdateChecker.CompareVersion("1.3", "1.3") == 0); - Assert.IsTrue(UpdateChecker.CompareVersion("1.2.1", "1.2") > 0); - Assert.IsTrue(UpdateChecker.CompareVersion("2.3.1", "2.4") < 0); - Assert.IsTrue(UpdateChecker.CompareVersion("1.3.2", "1.3.1") > 0); + Assert.IsTrue(UpdateChecker.Asset.CompareVersion("2.3.1.0", "2.3.1") == 0); + Assert.IsTrue(UpdateChecker.Asset.CompareVersion("1.2", "1.3") < 0); + Assert.IsTrue(UpdateChecker.Asset.CompareVersion("1.3", "1.2") > 0); + Assert.IsTrue(UpdateChecker.Asset.CompareVersion("1.3", "1.3") == 0); + Assert.IsTrue(UpdateChecker.Asset.CompareVersion("1.2.1", "1.2") > 0); + Assert.IsTrue(UpdateChecker.Asset.CompareVersion("2.3.1", "2.4") < 0); + Assert.IsTrue(UpdateChecker.Asset.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[] cipher = new byte[plain.Length + 16 + IVEncryptor.ONETIMEAUTH_BYTES + IVEncryptor.AUTH_BYTES]; byte[] plain2 = new byte[plain.Length + 16]; int outLen = 0; int outLen2 = 0; @@ -84,8 +84,8 @@ namespace test { IEncryptor encryptor; IEncryptor decryptor; - encryptor = new PolarSSLEncryptor("aes-256-cfb", "barfoo!"); - decryptor = new PolarSSLEncryptor("aes-256-cfb", "barfoo!"); + encryptor = new PolarSSLEncryptor("aes-256-cfb", "barfoo!", false, false); + decryptor = new PolarSSLEncryptor("aes-256-cfb", "barfoo!", false, false); RunEncryptionRound(encryptor, decryptor); } } @@ -124,8 +124,8 @@ namespace test var random = new Random(); IEncryptor encryptor; IEncryptor decryptor; - encryptor = new PolarSSLEncryptor("rc4-md5", "barfoo!"); - decryptor = new PolarSSLEncryptor("rc4-md5", "barfoo!"); + encryptor = new PolarSSLEncryptor("rc4-md5", "barfoo!", false, false); + decryptor = new PolarSSLEncryptor("rc4-md5", "barfoo!", false, false); RunEncryptionRound(encryptor, decryptor); } } @@ -164,8 +164,8 @@ namespace test var random = new Random(); IEncryptor encryptor; IEncryptor decryptor; - encryptor = new SodiumEncryptor("salsa20", "barfoo!"); - decryptor = new SodiumEncryptor("salsa20", "barfoo!"); + encryptor = new SodiumEncryptor("salsa20", "barfoo!", false, false); + decryptor = new SodiumEncryptor("salsa20", "barfoo!", false, false); RunEncryptionRound(encryptor, decryptor); } }