From 23b90b8697198de489060bc4c45018b89edcdc70 Mon Sep 17 00:00:00 2001 From: Christopher Meng Date: Mon, 17 Aug 2015 08:43:03 +0800 Subject: [PATCH 01/29] Add gfwlist links Various fixes accompanied. --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index bcd3f5cf..ae480278 100644 --- a/README.md +++ b/README.md @@ -7,30 +7,30 @@ Shadowsocks for Windows 1. System proxy configuration 2. PAC mode and global mode -3. GFWList and user rules +3. [GFWList](https://github.com/gfwlist/gfwlist) and user rules 4. Supports HTTP proxy 5. Supports server auto switching 6. Supports UDP relay (see Usage) #### Download -Download a [latest release]. +Download the [latest release]. #### Basic 1. Find Shadowsocks icon in the notification tray 2. You can add multiple servers in servers menu -3. Select Enable System Proxy menu to enable system proxy. Please disable other +3. Select `Enable System Proxy` menu to enable system proxy. Please disable other proxy addons in your browser, or set them to use system proxy 4. You can also configure your browser proxy manually if you don't want to enable system proxy. Set Socks5 or HTTP proxy to 127.0.0.1:1080. You can change this -port in Server -> Edit Servers +port in `Servers -> Edit Servers` #### PAC 1. You can change PAC rules by editing the PAC file. When you save the PAC file with any editor, Shadowsocks will notify browsers about the change automatically -2. You can also update PAC file from GFWList (maintained by 3rd party) +2. You can also update PAC file from [GFWList](https://github.com/gfwlist/gfwlist) (maintained by 3rd party) 3. You can also use online PAC URL #### Server Auto Switching @@ -44,7 +44,7 @@ with any editor, Shadowsocks will notify browsers about the change automatically #### UDP For UDP, you need to use SocksCap or ProxyCap to force programs you want -to proxy to tunnel over Shadowsocks +to be proxied to tunnel over Shadowsocks #### Develop From 1b8584e6e14b3d678e660bb512f1706ff01856a4 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Mon, 17 Aug 2015 10:57:59 +0800 Subject: [PATCH 02/29] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ae480278..4dedf567 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Shadowsocks for Windows 1. System proxy configuration 2. PAC mode and global mode -3. [GFWList](https://github.com/gfwlist/gfwlist) and user rules +3. [GFWList] and user rules 4. Supports HTTP proxy 5. Supports server auto switching 6. Supports UDP relay (see Usage) @@ -30,7 +30,7 @@ port in `Servers -> Edit Servers` 1. You can change PAC rules by editing the PAC file. When you save the PAC file with any editor, Shadowsocks will notify browsers about the change automatically -2. You can also update PAC file from [GFWList](https://github.com/gfwlist/gfwlist) (maintained by 3rd party) +2. You can also update PAC file from [GFWList] (maintained by 3rd party) 3. You can also use online PAC URL #### Server Auto Switching @@ -58,3 +58,4 @@ GPLv3 [Appveyor]: https://ci.appveyor.com/project/clowwindy/shadowsocks-csharp [Build Status]: https://ci.appveyor.com/api/projects/status/gknc8l1lxy423ehv/branch/master [latest release]: https://github.com/shadowsocks/shadowsocks-csharp/releases +[GFWList]: https://github.com/gfwlist/gfwlist From 7978817492119307cd35d4ba5940c8337edfddb2 Mon Sep 17 00:00:00 2001 From: icylogic Date: Mon, 17 Aug 2015 11:32:03 +0800 Subject: [PATCH 03/29] fixed #280, log "No such host is known" and other PingException --- .../Service/AvailabilityStatistics.cs | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs b/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs index 5a95dbc2..0d8463a6 100644 --- a/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs +++ b/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs @@ -67,14 +67,21 @@ namespace Shadowsocks.Controller string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); //ICMP echo. we can also set options and special bytes //seems no need to use SendPingAsync - PingReply reply = ping.Send(server.server, Timeout); - state.data = new List>(); - state.data.Add(new KeyValuePair("Timestamp", timestamp)); - state.data.Add(new KeyValuePair("Server", server.FriendlyName())); - state.data.Add(new KeyValuePair("Status", reply.Status.ToString())); - state.data.Add(new KeyValuePair("RoundtripTime", reply.RoundtripTime.ToString())); - //state.data.Add(new KeyValuePair("data", reply.Buffer.ToString())); // The data of reply - Append(state.data); + try + { + PingReply reply = ping.Send(server.server, Timeout); + state.data = new List>(); + state.data.Add(new KeyValuePair("Timestamp", timestamp)); + state.data.Add(new KeyValuePair("Server", server.FriendlyName())); + state.data.Add(new KeyValuePair("Status", reply.Status.ToString())); + state.data.Add(new KeyValuePair("RoundtripTime", reply.RoundtripTime.ToString())); + //state.data.Add(new KeyValuePair("data", reply.Buffer.ToString())); // The data of reply + Append(state.data); + } + catch (Exception e) + { + Logging.LogUsefulException(e); + } } } } From 9522d1d17b6ac52e93541d47a174ce0437a73600 Mon Sep 17 00:00:00 2001 From: Pink Floyd Date: Mon, 17 Aug 2015 17:24:35 +0800 Subject: [PATCH 04/29] Update UpdateChecker.cs Update UpdateURL --- shadowsocks-csharp/Controller/Service/UpdateChecker.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadowsocks-csharp/Controller/Service/UpdateChecker.cs b/shadowsocks-csharp/Controller/Service/UpdateChecker.cs index c6f65121..0ab86dd7 100644 --- a/shadowsocks-csharp/Controller/Service/UpdateChecker.cs +++ b/shadowsocks-csharp/Controller/Service/UpdateChecker.cs @@ -12,7 +12,7 @@ namespace Shadowsocks.Controller { public class UpdateChecker { - private const string UpdateURL = "https://api.github.com/repos/shadowsocks/shadowsocks-csharp/releases"; + private const string UpdateURL = "https://api.github.com/repos/shadowsocks/shadowsocks-windows/releases"; public string LatestVersionNumber; public string LatestVersionURL; From ab38538b343d200f0dc1840bf9a65ad268139306 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Mon, 17 Aug 2015 19:49:49 -0700 Subject: [PATCH 05/29] allow multiple instances --- shadowsocks-csharp/Data/cn.txt | 4 ++++ shadowsocks-csharp/Program.cs | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/shadowsocks-csharp/Data/cn.txt b/shadowsocks-csharp/Data/cn.txt index b4c7a6ee..751d1101 100644 --- a/shadowsocks-csharp/Data/cn.txt +++ b/shadowsocks-csharp/Data/cn.txt @@ -19,6 +19,7 @@ Update Local PAC from GFWList=从 GFWList 更新本地 PAC Edit User Rule for GFWList...=编辑 GFWList 的用户规则... Show QRCode...=显示二维码... Scan QRCode from Screen...=扫描屏幕上的二维码... +Availability Statistics=统计可用性 Show Logs...=显示日志... About...=关于... Quit=退出 @@ -72,6 +73,9 @@ Failed to update PAC file =更新 PAC 文件失败 PAC updated=更新 PAC 成功 No updates found. Please report to GFWList if you have problems with it.=未发现更新。如有问题请提交给 GFWList。 No QRCode found. Try to zoom in or move it to the center of the screen.=未发现二维码,尝试把它放大或移动到靠近屏幕中间的位置 +Shadowsocks is already running.=Shadowsocks 已经在运行。 +Find Shadowsocks icon in your notify tray.=请在任务栏里寻找 Shadowsocks 图标。 +If you want to start multiple Shadowsocks, make a copy in another directory.=如果想启动多份,可以另外复制一份到别的目录。 Failed to decode QRCode=无法解析二维码 Failed to update registry=无法修改注册表 System Proxy On: =系统代理已启用: diff --git a/shadowsocks-csharp/Program.cs b/shadowsocks-csharp/Program.cs index 8ca485d7..f840106a 100755 --- a/shadowsocks-csharp/Program.cs +++ b/shadowsocks-csharp/Program.cs @@ -19,7 +19,7 @@ namespace Shadowsocks static void Main() { Util.Utils.ReleaseMemory(); - using (Mutex mutex = new Mutex(false, "Global\\" + "71981632-A427-497F-AB91-241CD227EC1F")) + using (Mutex mutex = new Mutex(false, "Global\\Shadowsocks_" + Application.StartupPath.GetHashCode())) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); @@ -31,7 +31,9 @@ namespace Shadowsocks { Process oldProcess = oldProcesses[0]; } - MessageBox.Show("Shadowsocks is already running.\n\nFind Shadowsocks icon in your notify tray."); + MessageBox.Show(I18N.GetString("Find Shadowsocks icon in your notify tray.") + "\n" + + I18N.GetString("If you want to start multiple Shadowsocks, make a copy in another directory."), + I18N.GetString("Shadowsocks is already running.")); return; } Directory.SetCurrentDirectory(Application.StartupPath); From 05726cdb67e43d3e0bc7246aac0dc05e733b2ee2 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Mon, 17 Aug 2015 20:00:24 -0700 Subject: [PATCH 06/29] revert part of #257 --- shadowsocks-csharp/Controller/System/SystemProxy.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/shadowsocks-csharp/Controller/System/SystemProxy.cs b/shadowsocks-csharp/Controller/System/SystemProxy.cs index 84a26d06..74e4beb4 100644 --- a/shadowsocks-csharp/Controller/System/SystemProxy.cs +++ b/shadowsocks-csharp/Controller/System/SystemProxy.cs @@ -56,18 +56,14 @@ namespace Shadowsocks.Controller pacUrl = "http://127.0.0.1:" + config.localPort.ToString() + "/pac?t=" + GetTimestamp(DateTime.Now); registry.SetValue("ProxyEnable", 0); var readProxyServer = registry.GetValue("ProxyServer"); - if (readProxyServer != null && readProxyServer.Equals("127.0.0.1:" + config.localPort.ToString())) - registry.SetValue("ProxyServer", ""); + registry.SetValue("ProxyServer", ""); registry.SetValue("AutoConfigURL", pacUrl); } } else { registry.SetValue("ProxyEnable", 0); - if (global) - { - registry.SetValue("ProxyServer", ""); - } + registry.SetValue("ProxyServer", ""); registry.SetValue("AutoConfigURL", ""); } //Set AutoDetectProxy Off From e84825c25d09047093fcdbec6b0332065c32449c Mon Sep 17 00:00:00 2001 From: clowwindy Date: Mon, 17 Aug 2015 20:19:21 -0700 Subject: [PATCH 07/29] fix a path problem --- shadowsocks-csharp/Controller/Service/PolipoRunner.cs | 7 +++++-- shadowsocks-csharp/Controller/Service/UpdateChecker.cs | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/shadowsocks-csharp/Controller/Service/PolipoRunner.cs b/shadowsocks-csharp/Controller/Service/PolipoRunner.cs index 261436be..9581e05f 100644 --- a/shadowsocks-csharp/Controller/Service/PolipoRunner.cs +++ b/shadowsocks-csharp/Controller/Service/PolipoRunner.cs @@ -65,10 +65,13 @@ namespace Shadowsocks.Controller polipoConfig = polipoConfig.Replace("__POLIPO_BIND_IP__", configuration.shareOverLan ? "0.0.0.0" : "127.0.0.1"); FileManager.ByteArrayToFile(temppath + "/privoxy.conf", System.Text.Encoding.UTF8.GetBytes(polipoConfig)); + if (!(temppath.EndsWith("\\") || temppath.EndsWith("/"))) { + temppath = temppath + "\\"; + } _process = new Process(); // Configure the process using the StartInfo properties. - _process.StartInfo.FileName = temppath + "/ss_privoxy.exe"; - _process.StartInfo.Arguments = " \"" + temppath + "/privoxy.conf\""; + _process.StartInfo.FileName = temppath + "ss_privoxy.exe"; + _process.StartInfo.Arguments = " \"" + temppath + "privoxy.conf\""; _process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; _process.StartInfo.UseShellExecute = true; _process.StartInfo.CreateNoWindow = true; diff --git a/shadowsocks-csharp/Controller/Service/UpdateChecker.cs b/shadowsocks-csharp/Controller/Service/UpdateChecker.cs index 0ab86dd7..22aa2916 100644 --- a/shadowsocks-csharp/Controller/Service/UpdateChecker.cs +++ b/shadowsocks-csharp/Controller/Service/UpdateChecker.cs @@ -18,7 +18,7 @@ namespace Shadowsocks.Controller public string LatestVersionURL; public event EventHandler NewVersionFound; - public const string Version = "2.5.4"; + public const string Version = "2.5.5"; public void CheckUpdate(Configuration config) { From fe692f89e1d68fefd564bffd1432d2622f237a05 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Mon, 17 Aug 2015 20:46:51 +0800 Subject: [PATCH 08/29] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 4dedf567..ae78f59b 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ Shadowsocks for Windows [![Build Status]][Appveyor] +[中文说明] + #### Features 1. System proxy configuration @@ -59,3 +61,4 @@ GPLv3 [Build Status]: https://ci.appveyor.com/api/projects/status/gknc8l1lxy423ehv/branch/master [latest release]: https://github.com/shadowsocks/shadowsocks-csharp/releases [GFWList]: https://github.com/gfwlist/gfwlist +[中文说明]: https://github.com/shadowsocks/shadowsocks-windows/wiki/Shadowsocks-Windows-%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E From 85dc46d11e4e7e7809eee795e6a68eb6b43b4932 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Mon, 17 Aug 2015 20:55:01 +0800 Subject: [PATCH 09/29] Update README.md --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index ae78f59b..c97461fe 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,15 @@ with any editor, Shadowsocks will notify browsers about the change automatically For UDP, you need to use SocksCap or ProxyCap to force programs you want to be proxied to tunnel over Shadowsocks +#### Multiple Instances + +If you want to manage multiple servers using other tools like SwitchyOmega, +you can start multiple Shadowsocks instances. To avoid configuration conflicts, +copy Shadowsocks to a new directory and choose a different local port. + +Also, make sure to use `SOCKS5` proxy in SwitchyOmega, since we have only +one HTTP proxy instance. + #### Develop Visual Studio 2015 is required. From 3b90b2124f68cb855064e863ddd9b660602144aa Mon Sep 17 00:00:00 2001 From: clowwindy Date: Mon, 17 Aug 2015 21:03:11 +0800 Subject: [PATCH 10/29] Update README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index c97461fe..54d604bf 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,10 @@ copy Shadowsocks to a new directory and choose a different local port. Also, make sure to use `SOCKS5` proxy in SwitchyOmega, since we have only one HTTP proxy instance. +#### Server Configuration + +Please visit [Servers] for more information. + #### Develop Visual Studio 2015 is required. @@ -70,4 +74,5 @@ GPLv3 [Build Status]: https://ci.appveyor.com/api/projects/status/gknc8l1lxy423ehv/branch/master [latest release]: https://github.com/shadowsocks/shadowsocks-csharp/releases [GFWList]: https://github.com/gfwlist/gfwlist +[Servers]: https://github.com/shadowsocks/shadowsocks/wiki/Ports-and-Clients#linux--server-side [中文说明]: https://github.com/shadowsocks/shadowsocks-windows/wiki/Shadowsocks-Windows-%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E From 71bd0d2b5af0fdcedfdbbd2ef266d3f099f823ad Mon Sep 17 00:00:00 2001 From: clowwindy Date: Tue, 18 Aug 2015 04:25:27 -0700 Subject: [PATCH 11/29] improve user experience for some users --- .../Controller/Service/PACServer.cs | 2 +- .../Controller/ShadowsocksController.cs | 4 +-- shadowsocks-csharp/Program.cs | 2 +- shadowsocks-csharp/Util/Util.cs | 27 ++++++++++++++++--- shadowsocks-csharp/View/MenuViewController.cs | 2 +- 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/shadowsocks-csharp/Controller/Service/PACServer.cs b/shadowsocks-csharp/Controller/Service/PACServer.cs index 038ead8c..e915681e 100644 --- a/shadowsocks-csharp/Controller/Service/PACServer.cs +++ b/shadowsocks-csharp/Controller/Service/PACServer.cs @@ -146,7 +146,7 @@ Connection: Close ", System.Text.Encoding.UTF8.GetBytes(pac).Length) + pac; byte[] response = System.Text.Encoding.UTF8.GetBytes(text); socket.BeginSend(response, 0, response.Length, 0, new AsyncCallback(SendCallback), socket); - Util.Utils.ReleaseMemory(); + Util.Utils.ReleaseMemory(true); } catch (Exception e) { diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index aac1419a..b02771f1 100755 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -360,7 +360,7 @@ namespace Shadowsocks.Controller } UpdateSystemProxy(); - Util.Utils.ReleaseMemory(); + Util.Utils.ReleaseMemory(true); } @@ -417,7 +417,7 @@ namespace Shadowsocks.Controller { while (true) { - Util.Utils.ReleaseMemory(); + Util.Utils.ReleaseMemory(false); Thread.Sleep(30 * 1000); } } diff --git a/shadowsocks-csharp/Program.cs b/shadowsocks-csharp/Program.cs index f840106a..cb40cb23 100755 --- a/shadowsocks-csharp/Program.cs +++ b/shadowsocks-csharp/Program.cs @@ -18,7 +18,7 @@ namespace Shadowsocks [STAThread] static void Main() { - Util.Utils.ReleaseMemory(); + Util.Utils.ReleaseMemory(true); using (Mutex mutex = new Mutex(false, "Global\\Shadowsocks_" + Application.StartupPath.GetHashCode())) { Application.EnableVisualStyles(); diff --git a/shadowsocks-csharp/Util/Util.cs b/shadowsocks-csharp/Util/Util.cs index 15463a3a..004128af 100755 --- a/shadowsocks-csharp/Util/Util.cs +++ b/shadowsocks-csharp/Util/Util.cs @@ -10,7 +10,7 @@ namespace Shadowsocks.Util { public class Utils { - public static void ReleaseMemory() + public static void ReleaseMemory(bool removePages) { // release any unused pages // making the numbers look good in task manager @@ -20,8 +20,29 @@ namespace Shadowsocks.Util // which is part of user experience GC.Collect(GC.MaxGeneration); GC.WaitForPendingFinalizers(); - SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, - (UIntPtr)0xFFFFFFFF, (UIntPtr)0xFFFFFFFF); + if (removePages) + { + // as some users have pointed out + // removing pages from working set will cause some IO + // which lowered user experience for another group of users + // + // so we do 2 more things here to satisfy them: + // 1. only remove pages once when configuration is changed + // 2. add more comments here to tell users that calling + // this function will not be more frequent than + // IM apps writing chat logs, or web browsers writing cache files + // if they're so concerned about their disk, they should + // uninstall all IM apps and web browsers + // + // please open an issue if you're worried about anything else in your computer + // no matter it's GPU performance, monitor contrast, audio fidelity + // or anything else in the task manager + // we'll do as much as we can to help you + // + // just kidding + SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, + (UIntPtr)0xFFFFFFFF, (UIntPtr)0xFFFFFFFF); + } } public static string UnGzip(byte[] buf) diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index b8c9bb81..5081ec35 100755 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -322,7 +322,7 @@ namespace Shadowsocks.View void configForm_FormClosed(object sender, FormClosedEventArgs e) { configForm = null; - Util.Utils.ReleaseMemory(); + Util.Utils.ReleaseMemory(true); ShowFirstTimeBalloon(); } From 590322bca2b1b0b305674799901d8fe9c1c4385c Mon Sep 17 00:00:00 2001 From: clowwindy Date: Tue, 18 Aug 2015 05:07:04 +0800 Subject: [PATCH 12/29] fix some translation --- shadowsocks-csharp/Data/cn.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shadowsocks-csharp/Data/cn.txt b/shadowsocks-csharp/Data/cn.txt index 751d1101..92cc868c 100644 --- a/shadowsocks-csharp/Data/cn.txt +++ b/shadowsocks-csharp/Data/cn.txt @@ -75,8 +75,8 @@ No updates found. Please report to GFWList if you have problems with it.=未发 No QRCode found. Try to zoom in or move it to the center of the screen.=未发现二维码,尝试把它放大或移动到靠近屏幕中间的位置 Shadowsocks is already running.=Shadowsocks 已经在运行。 Find Shadowsocks icon in your notify tray.=请在任务栏里寻找 Shadowsocks 图标。 -If you want to start multiple Shadowsocks, make a copy in another directory.=如果想启动多份,可以另外复制一份到别的目录。 +If you want to start multiple Shadowsocks, make a copy in another directory.=如果想同时启动多份,可以另外复制一份到别的目录。 Failed to decode QRCode=无法解析二维码 Failed to update registry=无法修改注册表 System Proxy On: =系统代理已启用: -Running: Port {0}=正在运行:端口 {0} \ No newline at end of file +Running: Port {0}=正在运行:端口 {0} From 63b31f5abaad3db3df4ae0a9913004c518906ad8 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Tue, 18 Aug 2015 05:07:38 +0800 Subject: [PATCH 13/29] fix translation --- shadowsocks-csharp/Data/cn.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadowsocks-csharp/Data/cn.txt b/shadowsocks-csharp/Data/cn.txt index 92cc868c..9dc07328 100644 --- a/shadowsocks-csharp/Data/cn.txt +++ b/shadowsocks-csharp/Data/cn.txt @@ -75,7 +75,7 @@ No updates found. Please report to GFWList if you have problems with it.=未发 No QRCode found. Try to zoom in or move it to the center of the screen.=未发现二维码,尝试把它放大或移动到靠近屏幕中间的位置 Shadowsocks is already running.=Shadowsocks 已经在运行。 Find Shadowsocks icon in your notify tray.=请在任务栏里寻找 Shadowsocks 图标。 -If you want to start multiple Shadowsocks, make a copy in another directory.=如果想同时启动多份,可以另外复制一份到别的目录。 +If you want to start multiple Shadowsocks, make a copy in another directory.=如果想同时启动多个,可以另外复制一份到别的目录。 Failed to decode QRCode=无法解析二维码 Failed to update registry=无法修改注册表 System Proxy On: =系统代理已启用: From f33fb04b892509854899b6603ff2e0f29d997ecf Mon Sep 17 00:00:00 2001 From: kimw Date: Tue, 18 Aug 2015 23:44:17 +0800 Subject: [PATCH 14/29] support customize the server order --- shadowsocks-csharp/Data/cn.txt | 2 + .../View/ConfigForm.Designer.cs | 54 +++++++++++++- shadowsocks-csharp/View/ConfigForm.cs | 72 ++++++++++++++++--- shadowsocks-csharp/View/ConfigForm.resx | 4 +- 4 files changed, 121 insertions(+), 11 deletions(-) diff --git a/shadowsocks-csharp/Data/cn.txt b/shadowsocks-csharp/Data/cn.txt index 9dc07328..fd09606d 100644 --- a/shadowsocks-csharp/Data/cn.txt +++ b/shadowsocks-csharp/Data/cn.txt @@ -42,6 +42,8 @@ Remarks=备注 OK=确定 Cancel=取消 New server=未配置的服务器 +Move &Up=上移 +Move D&own=下移 # QRCode Form diff --git a/shadowsocks-csharp/View/ConfigForm.Designer.cs b/shadowsocks-csharp/View/ConfigForm.Designer.cs index 83dae64a..f8b5940a 100755 --- a/shadowsocks-csharp/View/ConfigForm.Designer.cs +++ b/shadowsocks-csharp/View/ConfigForm.Designer.cs @@ -47,6 +47,9 @@ this.ServerGroupBox = new System.Windows.Forms.GroupBox(); this.ServersListBox = new System.Windows.Forms.ListBox(); this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); + this.tableLayoutPanel6 = new System.Windows.Forms.TableLayoutPanel(); + this.MoveDownButton = new System.Windows.Forms.Button(); + this.MoveUpButton = new System.Windows.Forms.Button(); this.tableLayoutPanel5 = new System.Windows.Forms.TableLayoutPanel(); this.ProxyPortTextBox = new System.Windows.Forms.TextBox(); this.ProxyPortLabel = new System.Windows.Forms.Label(); @@ -55,6 +58,7 @@ this.tableLayoutPanel1.SuspendLayout(); this.ServerGroupBox.SuspendLayout(); this.tableLayoutPanel2.SuspendLayout(); + this.tableLayoutPanel6.SuspendLayout(); this.tableLayoutPanel5.SuspendLayout(); this.tableLayoutPanel3.SuspendLayout(); this.tableLayoutPanel4.SuspendLayout(); @@ -184,7 +188,7 @@ // // 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; @@ -281,6 +285,7 @@ // this.ServersListBox.FormattingEnabled = true; this.ServersListBox.IntegralHeight = false; + this.ServersListBox.ItemHeight = 12; this.ServersListBox.Location = new System.Drawing.Point(0, 0); this.ServersListBox.Margin = new System.Windows.Forms.Padding(0); this.ServersListBox.Name = "ServersListBox"; @@ -295,6 +300,7 @@ 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.tableLayoutPanel6, 0, 2); this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel5, 1, 1); this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel3, 1, 2); this.tableLayoutPanel2.Controls.Add(this.ServersListBox, 0, 0); @@ -310,6 +316,48 @@ this.tableLayoutPanel2.Size = new System.Drawing.Size(427, 238); this.tableLayoutPanel2.TabIndex = 7; // + // tableLayoutPanel6 + // + this.tableLayoutPanel6.AutoSize = true; + this.tableLayoutPanel6.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.tableLayoutPanel6.ColumnCount = 2; + this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + 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.Margin = new System.Windows.Forms.Padding(0); + this.tableLayoutPanel6.Name = "tableLayoutPanel6"; + this.tableLayoutPanel6.RowCount = 1; + this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel6.Size = new System.Drawing.Size(166, 32); + this.tableLayoutPanel6.TabIndex = 10; + // + // MoveDownButton + // + this.MoveDownButton.Dock = System.Windows.Forms.DockStyle.Right; + this.MoveDownButton.Location = new System.Drawing.Point(86, 6); + 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.Text = "Move D&own"; + this.MoveDownButton.UseVisualStyleBackColor = true; + this.MoveDownButton.Click += new System.EventHandler(this.MoveDownButton_Click); + // + // MoveUpButton + // + this.MoveUpButton.Dock = System.Windows.Forms.DockStyle.Left; + this.MoveUpButton.Location = new System.Drawing.Point(0, 6); + 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.Text = "Move &Up"; + this.MoveUpButton.UseVisualStyleBackColor = true; + this.MoveUpButton.Click += new System.EventHandler(this.MoveUpButton_Click); + // // tableLayoutPanel5 // this.tableLayoutPanel5.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) @@ -418,6 +466,7 @@ this.ServerGroupBox.PerformLayout(); this.tableLayoutPanel2.ResumeLayout(false); this.tableLayoutPanel2.PerformLayout(); + this.tableLayoutPanel6.ResumeLayout(false); this.tableLayoutPanel5.ResumeLayout(false); this.tableLayoutPanel5.PerformLayout(); this.tableLayoutPanel3.ResumeLayout(false); @@ -453,6 +502,9 @@ private System.Windows.Forms.TableLayoutPanel tableLayoutPanel5; private System.Windows.Forms.TextBox ProxyPortTextBox; private System.Windows.Forms.Label ProxyPortLabel; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel6; + private System.Windows.Forms.Button MoveDownButton; + private System.Windows.Forms.Button MoveUpButton; } } diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index 675aa23e..edcb405e 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -51,6 +51,8 @@ namespace Shadowsocks.View ServerGroupBox.Text = I18N.GetString("Server"); OKButton.Text = I18N.GetString("OK"); MyCancelButton.Text = I18N.GetString("Cancel"); + MoveUpButton.Text = I18N.GetString("Move &Up"); + MoveDownButton.Text = I18N.GetString("Move D&own"); this.Text = I18N.GetString("Edit Servers"); } @@ -58,7 +60,7 @@ namespace Shadowsocks.View { LoadCurrentConfiguration(); } - + private void ShowWindow() { this.Opacity = 1; @@ -87,7 +89,7 @@ namespace Shadowsocks.View Configuration.CheckLocalPort(localPort); _modifiedConfiguration.configs[_oldSelectedIndex] = server; _modifiedConfiguration.localPort = localPort; - + return true; } catch (FormatException) @@ -113,12 +115,6 @@ namespace Shadowsocks.View ProxyPortTextBox.Text = _modifiedConfiguration.localPort.ToString(); EncryptionSelect.Text = server.method ?? "aes-256-cfb"; RemarksTextBox.Text = server.remarks; - ServerGroupBox.Visible = true; - //IPTextBox.Focus(); - } - else - { - ServerGroupBox.Visible = false; } } @@ -141,6 +137,7 @@ namespace Shadowsocks.View _oldSelectedIndex = 0; } ServersListBox.SelectedIndex = _oldSelectedIndex; + UpdateMoveUpAndDownButton(); LoadSelectedServer(); } @@ -162,6 +159,7 @@ namespace Shadowsocks.View ServersListBox.SelectedIndex = _oldSelectedIndex; return; } + UpdateMoveUpAndDownButton(); LoadSelectedServer(); _oldSelectedIndex = ServersListBox.SelectedIndex; } @@ -208,7 +206,9 @@ namespace Shadowsocks.View MessageBox.Show(I18N.GetString("Please add at least one server")); return; } + int index = _modifiedConfiguration.index; controller.SaveServers(_modifiedConfiguration.configs, _modifiedConfiguration.localPort); + controller.SelectServerIndex(index); this.Close(); } @@ -227,5 +227,61 @@ namespace Shadowsocks.View controller.ConfigChanged -= controller_ConfigChanged; } + private void MoveConfigItem(int step) + { + int index = ServersListBox.SelectedIndex; + Server server = _modifiedConfiguration.configs[index]; + object item = ServersListBox.SelectedItem; + + _modifiedConfiguration.configs.Remove(server); + _modifiedConfiguration.configs.Insert(index + step, server); + _modifiedConfiguration.index += step; + + ServersListBox.BeginUpdate(); + _oldSelectedIndex = index + step; + ServersListBox.Items.Remove(item); + ServersListBox.Items.Insert(index + step, item); + ServersListBox.SelectedIndex = index + step; + ServersListBox.EndUpdate(); + + UpdateMoveUpAndDownButton(); + } + + private void UpdateMoveUpAndDownButton() + { + if (ServersListBox.SelectedIndex == 0) + { + MoveUpButton.Enabled = false; + } + else + { + MoveUpButton.Enabled = true; + } + if (ServersListBox.SelectedIndex == ServersListBox.Items.Count - 1) + { + MoveDownButton.Enabled = false; + } + else + { + MoveDownButton.Enabled = true; + } + } + + private void MoveUpButton_Click(object sender, EventArgs e) + { + if (ServersListBox.SelectedIndex > 0) + { + MoveConfigItem(-1); // -1 means move backward + } + } + + private void MoveDownButton_Click(object sender, EventArgs e) + { + if (ServersListBox.SelectedIndex < ServersListBox.Items.Count - 1) + { + MoveConfigItem(+1); // +1 means move forward + } + } + } } diff --git a/shadowsocks-csharp/View/ConfigForm.resx b/shadowsocks-csharp/View/ConfigForm.resx index ff31a6db..c7e0d4bd 100755 --- a/shadowsocks-csharp/View/ConfigForm.resx +++ b/shadowsocks-csharp/View/ConfigForm.resx @@ -112,9 +112,9 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 \ No newline at end of file From 3bc77d212a711d9482a864b49eae59203a79340b Mon Sep 17 00:00:00 2001 From: clowwindy Date: Tue, 18 Aug 2015 20:58:53 -0700 Subject: [PATCH 15/29] reduce cache size --- .../Controller/Service/TCPRelay.cs | 22 ++++- .../Encryption/SodiumEncryptor.cs | 86 ++++++++++--------- 2 files changed, 65 insertions(+), 43 deletions(-) diff --git a/shadowsocks-csharp/Controller/Service/TCPRelay.cs b/shadowsocks-csharp/Controller/Service/TCPRelay.cs index 5c9de444..3fc27e39 100644 --- a/shadowsocks-csharp/Controller/Service/TCPRelay.cs +++ b/shadowsocks-csharp/Controller/Service/TCPRelay.cs @@ -14,9 +14,16 @@ namespace Shadowsocks.Controller class TCPRelay : Listener.Service { private ShadowsocksController _controller; + + public ISet Handlers + { + get; set; + } + public TCPRelay(ShadowsocksController controller) { this._controller = controller; + this.Handlers = new HashSet(); } public bool Handle(byte[] firstPacket, int length, Socket socket, object state) @@ -33,8 +40,14 @@ namespace Shadowsocks.Controller Handler handler = new Handler(); handler.connection = socket; handler.controller = _controller; + handler.relay = this; handler.Start(firstPacket, length); + lock (this.Handlers) + { + this.Handlers.Add(handler); + Logging.Debug($"connections: {Handlers.Count}"); + } return true; } } @@ -48,6 +61,8 @@ namespace Shadowsocks.Controller public Socket remote; public Socket connection; public ShadowsocksController controller; + public TCPRelay relay; + private int retryCount = 0; private bool connected; @@ -55,7 +70,7 @@ namespace Shadowsocks.Controller private byte[] _firstPacket; private int _firstPacketLength; // Size of receive buffer. - public const int RecvSize = 16384; + public const int RecvSize = 8192; public const int BufferSize = RecvSize + 32; private int totalRead = 0; @@ -108,6 +123,11 @@ namespace Shadowsocks.Controller public void Close() { + lock (relay.Handlers) + { + Logging.Debug($"connections: {relay.Handlers.Count}"); + relay.Handlers.Remove(this); + } lock (this) { if (closed) diff --git a/shadowsocks-csharp/Encryption/SodiumEncryptor.cs b/shadowsocks-csharp/Encryption/SodiumEncryptor.cs index 5d6165eb..af51d0ac 100755 --- a/shadowsocks-csharp/Encryption/SodiumEncryptor.cs +++ b/shadowsocks-csharp/Encryption/SodiumEncryptor.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Text; +using System.Threading; namespace Shadowsocks.Encryption { @@ -12,19 +13,17 @@ namespace Shadowsocks.Encryption const int SODIUM_BLOCK_SIZE = 64; + static byte[] sodiumBuf = new byte[MAX_INPUT_SIZE + SODIUM_BLOCK_SIZE]; + 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 _ciphers = new Dictionary { @@ -47,48 +46,51 @@ namespace Shadowsocks.Encryption // 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) + // I'm tired. just add a big lock + // let's optimize for RAM instead of CPU + lock(sodiumBuf) { - 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) + { + bytesRemaining = _encryptBytesRemaining; + ic = _encryptIC; + iv = _encryptIV; + } + else + { + bytesRemaining = _decryptBytesRemaining; + ic = _decryptIC; + iv = _decryptIV; + } + int padding = bytesRemaining; + Buffer.BlockCopy(buf, 0, sodiumBuf, padding, length); - if (isCipher) - { - _encryptBytesRemaining = bytesRemaining; - _encryptIC = ic; - } - else - { - _decryptBytesRemaining = bytesRemaining; - _decryptIC = ic; + 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; + } } } From 750ee4fa5ffb2e7dd63f675438e6296333410553 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Tue, 18 Aug 2015 21:31:50 -0700 Subject: [PATCH 16/29] add handler timeout --- .../Controller/Service/TCPRelay.cs | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/shadowsocks-csharp/Controller/Service/TCPRelay.cs b/shadowsocks-csharp/Controller/Service/TCPRelay.cs index 3fc27e39..667a11a6 100644 --- a/shadowsocks-csharp/Controller/Service/TCPRelay.cs +++ b/shadowsocks-csharp/Controller/Service/TCPRelay.cs @@ -14,6 +14,7 @@ namespace Shadowsocks.Controller class TCPRelay : Listener.Service { private ShadowsocksController _controller; + private DateTime _lastSweepTime; public ISet Handlers { @@ -24,6 +25,7 @@ namespace Shadowsocks.Controller { this._controller = controller; this.Handlers = new HashSet(); + this._lastSweepTime = DateTime.Now; } public bool Handle(byte[] firstPacket, int length, Socket socket, object state) @@ -43,12 +45,30 @@ namespace Shadowsocks.Controller handler.relay = this; handler.Start(firstPacket, length); + IList handlersToClose = new List(); lock (this.Handlers) { this.Handlers.Add(handler); Logging.Debug($"connections: {Handlers.Count}"); + DateTime now = DateTime.Now; + if (now - _lastSweepTime > TimeSpan.FromSeconds(1)) + { + _lastSweepTime = now; + foreach (Handler handler1 in this.Handlers) + { + if (now - handler1.lastActivity > TimeSpan.FromSeconds(1800)) + { + handlersToClose.Add(handler1); + } + } + } + } + foreach (Handler handler1 in handlersToClose) + { + Logging.Debug("Closing timed out connection"); + handler1.Close(); } - return true; + return true; } } @@ -63,6 +83,8 @@ namespace Shadowsocks.Controller public ShadowsocksController controller; public TCPRelay relay; + public DateTime lastActivity; + private int retryCount = 0; private bool connected; @@ -111,6 +133,7 @@ namespace Shadowsocks.Controller this._firstPacket = firstPacket; this._firstPacketLength = length; this.HandshakeReceive(); + this.lastActivity = DateTime.Now; } private void CheckClose() @@ -505,6 +528,7 @@ namespace Shadowsocks.Controller if (bytesRead > 0) { + this.lastActivity = DateTime.Now; int bytesToSend; lock (decryptionLock) { From feaf7f70d0440874e9687877e34f2da2305ecc66 Mon Sep 17 00:00:00 2001 From: kimw Date: Wed, 19 Aug 2015 00:20:39 +0800 Subject: [PATCH 17/29] fix translation typo --- shadowsocks-csharp/Data/cn.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shadowsocks-csharp/Data/cn.txt b/shadowsocks-csharp/Data/cn.txt index fd09606d..b4217a85 100644 --- a/shadowsocks-csharp/Data/cn.txt +++ b/shadowsocks-csharp/Data/cn.txt @@ -42,8 +42,8 @@ Remarks=备注 OK=确定 Cancel=取消 New server=未配置的服务器 -Move &Up=上移 -Move D&own=下移 +Move &Up=上移(&U) +Move D&own=下移(&O) # QRCode Form From 3e1044fc41df20bcbef8b3c4292b592e31572820 Mon Sep 17 00:00:00 2001 From: kimw Date: Wed, 19 Aug 2015 00:22:23 +0800 Subject: [PATCH 18/29] rename variable `_oldSelectedIndex` to `_lastSelectedIndex` --- shadowsocks-csharp/View/ConfigForm.cs | 39 +++++++++++++-------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index edcb405e..d20a7d28 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -18,7 +18,7 @@ namespace Shadowsocks.View // this is a copy of configuration that we are working on private Configuration _modifiedConfiguration; - private int _oldSelectedIndex = -1; + private int _lastSelectedIndex = -1; public ConfigForm(ShadowsocksController controller) { @@ -72,7 +72,7 @@ namespace Shadowsocks.View { try { - if (_oldSelectedIndex == -1 || _oldSelectedIndex >= _modifiedConfiguration.configs.Count) + if (_lastSelectedIndex == -1 || _lastSelectedIndex >= _modifiedConfiguration.configs.Count) { return true; } @@ -87,7 +87,7 @@ namespace Shadowsocks.View int localPort = int.Parse(ProxyPortTextBox.Text); Configuration.CheckServer(server); Configuration.CheckLocalPort(localPort); - _modifiedConfiguration.configs[_oldSelectedIndex] = server; + _modifiedConfiguration.configs[_lastSelectedIndex] = server; _modifiedConfiguration.localPort = localPort; return true; @@ -131,12 +131,12 @@ namespace Shadowsocks.View { _modifiedConfiguration = controller.GetConfigurationCopy(); LoadConfiguration(_modifiedConfiguration); - _oldSelectedIndex = _modifiedConfiguration.index; - if (_oldSelectedIndex < 0) + _lastSelectedIndex = _modifiedConfiguration.index; + if (_lastSelectedIndex < 0) { - _oldSelectedIndex = 0; + _lastSelectedIndex = 0; } - ServersListBox.SelectedIndex = _oldSelectedIndex; + ServersListBox.SelectedIndex = _lastSelectedIndex; UpdateMoveUpAndDownButton(); LoadSelectedServer(); } @@ -148,7 +148,7 @@ namespace Shadowsocks.View private void ServersListBox_SelectedIndexChanged(object sender, EventArgs e) { - if (_oldSelectedIndex == ServersListBox.SelectedIndex) + if (_lastSelectedIndex == ServersListBox.SelectedIndex) { // we are moving back to oldSelectedIndex or doing a force move return; @@ -156,12 +156,12 @@ namespace Shadowsocks.View if (!SaveOldSelectedServer()) { // why this won't cause stack overflow? - ServersListBox.SelectedIndex = _oldSelectedIndex; + ServersListBox.SelectedIndex = _lastSelectedIndex; return; } UpdateMoveUpAndDownButton(); LoadSelectedServer(); - _oldSelectedIndex = ServersListBox.SelectedIndex; + _lastSelectedIndex = ServersListBox.SelectedIndex; } private void AddButton_Click(object sender, EventArgs e) @@ -174,24 +174,24 @@ namespace Shadowsocks.View _modifiedConfiguration.configs.Add(server); LoadConfiguration(_modifiedConfiguration); ServersListBox.SelectedIndex = _modifiedConfiguration.configs.Count - 1; - _oldSelectedIndex = ServersListBox.SelectedIndex; + _lastSelectedIndex = ServersListBox.SelectedIndex; } private void DeleteButton_Click(object sender, EventArgs e) { - _oldSelectedIndex = ServersListBox.SelectedIndex; - if (_oldSelectedIndex >= 0 && _oldSelectedIndex < _modifiedConfiguration.configs.Count) + _lastSelectedIndex = ServersListBox.SelectedIndex; + if (_lastSelectedIndex >= 0 && _lastSelectedIndex < _modifiedConfiguration.configs.Count) { - _modifiedConfiguration.configs.RemoveAt(_oldSelectedIndex); + _modifiedConfiguration.configs.RemoveAt(_lastSelectedIndex); } - if (_oldSelectedIndex >= _modifiedConfiguration.configs.Count) + if (_lastSelectedIndex >= _modifiedConfiguration.configs.Count) { // can be -1 - _oldSelectedIndex = _modifiedConfiguration.configs.Count - 1; + _lastSelectedIndex = _modifiedConfiguration.configs.Count - 1; } - ServersListBox.SelectedIndex = _oldSelectedIndex; + ServersListBox.SelectedIndex = _lastSelectedIndex; LoadConfiguration(_modifiedConfiguration); - ServersListBox.SelectedIndex = _oldSelectedIndex; + ServersListBox.SelectedIndex = _lastSelectedIndex; LoadSelectedServer(); } @@ -238,7 +238,7 @@ namespace Shadowsocks.View _modifiedConfiguration.index += step; ServersListBox.BeginUpdate(); - _oldSelectedIndex = index + step; + _lastSelectedIndex = index + step; ServersListBox.Items.Remove(item); ServersListBox.Items.Insert(index + step, item); ServersListBox.SelectedIndex = index + step; @@ -282,6 +282,5 @@ namespace Shadowsocks.View MoveConfigItem(+1); // +1 means move forward } } - } } From 758c497eba64e4107718aef84367d0525e0c0f84 Mon Sep 17 00:00:00 2001 From: kimw Date: Wed, 19 Aug 2015 00:24:08 +0800 Subject: [PATCH 19/29] same the source code format. 1/ removed dual empty line 2/ removed tailing spaces 3/ converted tabs into spaces 4/ added some TODO comments --- shadowsocks-csharp/Controller/I18N.cs | 2 +- shadowsocks-csharp/Controller/Logging.cs | 3 +-- .../Controller/Service/Listener.cs | 2 -- .../Controller/Service/PACServer.cs | 1 - .../Controller/Service/PolipoRunner.cs | 2 -- .../Controller/Service/PortForwarder.cs | 1 - .../Controller/Service/TCPRelay.cs | 9 ++------- .../Controller/Service/UDPRelay.cs | 7 ++++++- .../Controller/Service/UpdateChecker.cs | 1 - .../Controller/ShadowsocksController.cs | 4 +--- .../Controller/Strategy/IStrategy.cs | 6 +++--- .../SimplyChooseByStatisticsStrategy.cs | 2 +- shadowsocks-csharp/Encryption/IVEncryptor.cs | 1 - shadowsocks-csharp/Encryption/PolarSSL.cs | 1 - .../Encryption/TableEncryptor.cs | 2 -- shadowsocks-csharp/View/MenuViewController.cs | 20 +++++++++---------- shadowsocks-csharp/View/QRCodeSplashForm.cs | 2 -- 17 files changed, 25 insertions(+), 41 deletions(-) diff --git a/shadowsocks-csharp/Controller/I18N.cs b/shadowsocks-csharp/Controller/I18N.cs index 76c51749..c99d0f14 100755 --- a/shadowsocks-csharp/Controller/I18N.cs +++ b/shadowsocks-csharp/Controller/I18N.cs @@ -12,7 +12,7 @@ namespace Shadowsocks.Controller static I18N() { Strings = new Dictionary(); - + if (System.Globalization.CultureInfo.CurrentCulture.IetfLanguageTag.ToLowerInvariant().StartsWith("zh")) { string[] lines = Regex.Split(Resources.cn, "\r\n|\r|\n"); diff --git a/shadowsocks-csharp/Controller/Logging.cs b/shadowsocks-csharp/Controller/Logging.cs index 354df7a5..126dab70 100755 --- a/shadowsocks-csharp/Controller/Logging.cs +++ b/shadowsocks-csharp/Controller/Logging.cs @@ -21,7 +21,7 @@ namespace Shadowsocks.Controller sw.AutoFlush = true; Console.SetOut(sw); Console.SetError(sw); - + return true; } catch (IOException e) @@ -71,7 +71,6 @@ namespace Shadowsocks.Controller Console.WriteLine(e); } } - } // Simply extended System.IO.StreamWriter for adding timestamp workaround diff --git a/shadowsocks-csharp/Controller/Service/Listener.cs b/shadowsocks-csharp/Controller/Service/Listener.cs index f14bc79c..fe59fe98 100644 --- a/shadowsocks-csharp/Controller/Service/Listener.cs +++ b/shadowsocks-csharp/Controller/Service/Listener.cs @@ -77,7 +77,6 @@ namespace Shadowsocks.Controller _udpSocket.Bind(localEndPoint); _tcpSocket.Listen(1024); - // Start an asynchronous socket to listen for connections. Console.WriteLine("Shadowsocks started"); _tcpSocket.BeginAccept( @@ -185,7 +184,6 @@ namespace Shadowsocks.Controller } } - private void ReceiveCallback(IAsyncResult ar) { object[] state = (object[])ar.AsyncState; diff --git a/shadowsocks-csharp/Controller/Service/PACServer.cs b/shadowsocks-csharp/Controller/Service/PACServer.cs index e915681e..f8fc80e8 100644 --- a/shadowsocks-csharp/Controller/Service/PACServer.cs +++ b/shadowsocks-csharp/Controller/Service/PACServer.cs @@ -86,7 +86,6 @@ namespace Shadowsocks.Controller } } - public string TouchPACFile() { if (File.Exists(PAC_FILE)) diff --git a/shadowsocks-csharp/Controller/Service/PolipoRunner.cs b/shadowsocks-csharp/Controller/Service/PolipoRunner.cs index 9581e05f..3b3a5a4c 100644 --- a/shadowsocks-csharp/Controller/Service/PolipoRunner.cs +++ b/shadowsocks-csharp/Controller/Service/PolipoRunner.cs @@ -147,7 +147,6 @@ namespace Shadowsocks.Controller [DllImport("user32.dll")] public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam); - public void RefreshTrayArea() { IntPtr systemTrayContainerHandle = FindWindow("Shell_TrayWnd", null); @@ -164,7 +163,6 @@ namespace Shadowsocks.Controller RefreshTrayArea(notificationAreaHandle); } - private static void RefreshTrayArea(IntPtr windowHandle) { const uint wmMousemove = 0x0200; diff --git a/shadowsocks-csharp/Controller/Service/PortForwarder.cs b/shadowsocks-csharp/Controller/Service/PortForwarder.cs index e0b05aea..63848079 100644 --- a/shadowsocks-csharp/Controller/Service/PortForwarder.cs +++ b/shadowsocks-csharp/Controller/Service/PortForwarder.cs @@ -103,7 +103,6 @@ namespace Shadowsocks.Controller } } - private void StartPipe(IAsyncResult ar) { if (_closed) diff --git a/shadowsocks-csharp/Controller/Service/TCPRelay.cs b/shadowsocks-csharp/Controller/Service/TCPRelay.cs index 667a11a6..80464c6b 100644 --- a/shadowsocks-csharp/Controller/Service/TCPRelay.cs +++ b/shadowsocks-csharp/Controller/Service/TCPRelay.cs @@ -111,7 +111,7 @@ namespace Shadowsocks.Controller private bool connectionShutdown = false; private bool remoteShutdown = false; private bool closed = false; - + private object encryptionLock = new object(); private object decryptionLock = new object(); @@ -195,7 +195,6 @@ namespace Shadowsocks.Controller } } - private void HandshakeReceive() { if (closed) @@ -265,7 +264,7 @@ namespace Shadowsocks.Controller try { int bytesRead = connection.EndReceive(ar); - + if (bytesRead >= 3) { command = connetionRecvBuffer[1]; @@ -315,7 +314,6 @@ namespace Shadowsocks.Controller private void ReadAll(IAsyncResult ar) { - if (closed) { return; @@ -390,7 +388,6 @@ namespace Shadowsocks.Controller } IPEndPoint remoteEP = new IPEndPoint(ipAddress, server.server_port); - remote = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); remote.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); @@ -592,7 +589,6 @@ namespace Shadowsocks.Controller } remote.BeginSend(connetionSendBuffer, 0, bytesToSend, 0, new AsyncCallback(PipeRemoteSendCallback), null); - IStrategy strategy = controller.GetCurrentStrategy(); if (strategy != null) { @@ -651,5 +647,4 @@ namespace Shadowsocks.Controller } } } - } diff --git a/shadowsocks-csharp/Controller/Service/UDPRelay.cs b/shadowsocks-csharp/Controller/Service/UDPRelay.cs index 83a8c5b2..a0662dd2 100644 --- a/shadowsocks-csharp/Controller/Service/UDPRelay.cs +++ b/shadowsocks-csharp/Controller/Service/UDPRelay.cs @@ -108,9 +108,11 @@ namespace Shadowsocks.Controller } catch (ObjectDisposedException) { + // TODO: handle the ObjectDisposedException } catch (Exception) { + // TODO: need more think about handle other Exceptions, or should remove this catch(). } finally { @@ -124,9 +126,11 @@ namespace Shadowsocks.Controller } catch (ObjectDisposedException) { + // TODO: handle the ObjectDisposedException } catch (Exception) { + // TODO: need more think about handle other Exceptions, or should remove this catch(). } finally { @@ -134,6 +138,8 @@ namespace Shadowsocks.Controller } } } + + // cc by-sa 3.0 http://stackoverflow.com/a/3719378/1124054 class LRUCache where V : UDPRelay.UDPHandler { @@ -196,5 +202,4 @@ namespace Shadowsocks.Controller public K key; public V value; } - } diff --git a/shadowsocks-csharp/Controller/Service/UpdateChecker.cs b/shadowsocks-csharp/Controller/Service/UpdateChecker.cs index 22aa2916..9a3f832c 100644 --- a/shadowsocks-csharp/Controller/Service/UpdateChecker.cs +++ b/shadowsocks-csharp/Controller/Service/UpdateChecker.cs @@ -53,7 +53,6 @@ namespace Shadowsocks.Controller { return CompareVersion(ParseVersionFromURL(x), ParseVersionFromURL(y)); } - } private static string ParseVersionFromURL(string url) diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index b02771f1..2e2f5528 100755 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -39,7 +39,7 @@ namespace Shadowsocks.Controller 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 PACFileReadyToOpen; public event EventHandler UserRuleFileReadyToOpen; @@ -363,14 +363,12 @@ namespace Shadowsocks.Controller Util.Utils.ReleaseMemory(true); } - protected void SaveConfig(Configuration newConfig) { Configuration.Save(newConfig); Reload(); } - private void UpdateSystemProxy() { if (_config.enabled) diff --git a/shadowsocks-csharp/Controller/Strategy/IStrategy.cs b/shadowsocks-csharp/Controller/Strategy/IStrategy.cs index ca3036fb..36962e4e 100644 --- a/shadowsocks-csharp/Controller/Strategy/IStrategy.cs +++ b/shadowsocks-csharp/Controller/Strategy/IStrategy.cs @@ -14,17 +14,17 @@ namespace Shadowsocks.Controller.Strategy /* * IStrategy - * + * * Subclasses must be thread-safe */ public interface IStrategy { string Name { get; } - + string ID { get; } /* - * Called when servers need to be reloaded, i.e. new configuration saved + * Called when servers need to be reloaded, i.e. new configuration saved */ void ReloadServers(); diff --git a/shadowsocks-csharp/Controller/Strategy/SimplyChooseByStatisticsStrategy.cs b/shadowsocks-csharp/Controller/Strategy/SimplyChooseByStatisticsStrategy.cs index dc098b8b..0cdfcfc5 100644 --- a/shadowsocks-csharp/Controller/Strategy/SimplyChooseByStatisticsStrategy.cs +++ b/shadowsocks-csharp/Controller/Strategy/SimplyChooseByStatisticsStrategy.cs @@ -112,7 +112,7 @@ namespace Shadowsocks.Controller.Strategy ).Aggregate((result1, result2) => result1.score > result2.score ? result1 : result2); if (_controller.GetCurrentStrategy().ID == ID && _currentServer != bestResult.server) //output when enabled - { + { Console.WriteLine("Switch to server: {0} by package loss:{1}", bestResult.server.FriendlyName(), 1 - bestResult.score); } _currentServer = bestResult.server; diff --git a/shadowsocks-csharp/Encryption/IVEncryptor.cs b/shadowsocks-csharp/Encryption/IVEncryptor.cs index 0a59a0df..32948d6b 100755 --- a/shadowsocks-csharp/Encryption/IVEncryptor.cs +++ b/shadowsocks-csharp/Encryption/IVEncryptor.cs @@ -26,7 +26,6 @@ namespace Shadowsocks.Encryption protected int keyLen; protected int ivLen; - public IVEncryptor(string method, string password) : base(method, password) { diff --git a/shadowsocks-csharp/Encryption/PolarSSL.cs b/shadowsocks-csharp/Encryption/PolarSSL.cs index 93b662a8..f5c2626d 100755 --- a/shadowsocks-csharp/Encryption/PolarSSL.cs +++ b/shadowsocks-csharp/Encryption/PolarSSL.cs @@ -49,7 +49,6 @@ namespace Shadowsocks.Encryption [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] public extern static int aes_crypt_cfb128(IntPtr ctx, int mode, int length, ref int iv_off, byte[] iv, byte[] input, byte[] output); - public const int ARC4_CTX_SIZE = 264; [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] diff --git a/shadowsocks-csharp/Encryption/TableEncryptor.cs b/shadowsocks-csharp/Encryption/TableEncryptor.cs index 3dd526d4..db0a7db0 100644 --- a/shadowsocks-csharp/Encryption/TableEncryptor.cs +++ b/shadowsocks-csharp/Encryption/TableEncryptor.cs @@ -41,7 +41,6 @@ namespace Shadowsocks.Encryption outlength = length; } - public override void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength) { byte[] result = new byte[length]; @@ -100,7 +99,6 @@ namespace Shadowsocks.Encryption return sorted; } - public override void Dispose() { } diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index 5081ec35..c8a4c0eb 100755 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -18,7 +18,7 @@ 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 do anything related to the config form - + private ShadowsocksController controller; private UpdateChecker updateChecker; @@ -520,17 +520,17 @@ namespace Shadowsocks.View Process.Start(_urlToOpen); } - private void AutoStartupItem_Click(object sender, EventArgs e) { - AutoStartupItem.Checked = !AutoStartupItem.Checked; - if (!AutoStartup.Set(AutoStartupItem.Checked)) { - MessageBox.Show(I18N.GetString("Failed to update registry")); - } - } + private void AutoStartupItem_Click(object sender, EventArgs e) { + AutoStartupItem.Checked = !AutoStartupItem.Checked; + if (!AutoStartup.Set(AutoStartupItem.Checked)) { + MessageBox.Show(I18N.GetString("Failed to update registry")); + } + } - private void AvailabilityStatisticsItem_Click(object sender, EventArgs e) { - AvailabilityStatistics.Checked = !AvailabilityStatistics.Checked; + private void AvailabilityStatisticsItem_Click(object sender, EventArgs e) { + AvailabilityStatistics.Checked = !AvailabilityStatistics.Checked; controller.ToggleAvailabilityStatistics(AvailabilityStatistics.Checked); - } + } private void LocalPACItem_Click(object sender, EventArgs e) { diff --git a/shadowsocks-csharp/View/QRCodeSplashForm.cs b/shadowsocks-csharp/View/QRCodeSplashForm.cs index ac9828e4..3bf48888 100755 --- a/shadowsocks-csharp/View/QRCodeSplashForm.cs +++ b/shadowsocks-csharp/View/QRCodeSplashForm.cs @@ -242,7 +242,6 @@ namespace Shadowsocks.View SetBitmap(bitmap, 255); } - /// Changes the current bitmap with a custom opacity level. Here is where all happens! public void SetBitmap(Bitmap bitmap, byte opacity) { @@ -288,7 +287,6 @@ namespace Shadowsocks.View } } - protected override CreateParams CreateParams { get From 70818193908808f5c611597736677f20bb7f6484 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Wed, 19 Aug 2015 13:05:12 +0800 Subject: [PATCH 20/29] timeout 30min -> 15min --- shadowsocks-csharp/Controller/Service/TCPRelay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadowsocks-csharp/Controller/Service/TCPRelay.cs b/shadowsocks-csharp/Controller/Service/TCPRelay.cs index 667a11a6..c750f644 100644 --- a/shadowsocks-csharp/Controller/Service/TCPRelay.cs +++ b/shadowsocks-csharp/Controller/Service/TCPRelay.cs @@ -56,7 +56,7 @@ namespace Shadowsocks.Controller _lastSweepTime = now; foreach (Handler handler1 in this.Handlers) { - if (now - handler1.lastActivity > TimeSpan.FromSeconds(1800)) + if (now - handler1.lastActivity > TimeSpan.FromSeconds(900)) { handlersToClose.Add(handler1); } From 0b6dd0d6533e38238204ea24cd3e833d2cb8c279 Mon Sep 17 00:00:00 2001 From: kimw Date: Wed, 19 Aug 2015 01:49:57 +0800 Subject: [PATCH 21/29] refresh server list with friendly name --- shadowsocks-csharp/View/ConfigForm.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index d20a7d28..8bb494de 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -148,6 +148,10 @@ namespace Shadowsocks.View private void ServersListBox_SelectedIndexChanged(object sender, EventArgs e) { + if (!ServersListBox.CanSelect) + { + return; + } if (_lastSelectedIndex == ServersListBox.SelectedIndex) { // we are moving back to oldSelectedIndex or doing a force move @@ -159,6 +163,7 @@ namespace Shadowsocks.View ServersListBox.SelectedIndex = _lastSelectedIndex; return; } + ServersListBox.Items[_lastSelectedIndex] = _modifiedConfiguration.configs[_lastSelectedIndex].FriendlyName(); UpdateMoveUpAndDownButton(); LoadSelectedServer(); _lastSelectedIndex = ServersListBox.SelectedIndex; @@ -197,6 +202,7 @@ namespace Shadowsocks.View private void OKButton_Click(object sender, EventArgs e) { + Server server = controller.GetCurrentServer(); if (!SaveOldSelectedServer()) { return; @@ -206,9 +212,8 @@ namespace Shadowsocks.View MessageBox.Show(I18N.GetString("Please add at least one server")); return; } - int index = _modifiedConfiguration.index; controller.SaveServers(_modifiedConfiguration.configs, _modifiedConfiguration.localPort); - controller.SelectServerIndex(index); + controller.SelectServerIndex(_modifiedConfiguration.configs.IndexOf(server)); this.Close(); } @@ -238,9 +243,11 @@ namespace Shadowsocks.View _modifiedConfiguration.index += step; ServersListBox.BeginUpdate(); + ServersListBox.Enabled = false; _lastSelectedIndex = index + step; ServersListBox.Items.Remove(item); ServersListBox.Items.Insert(index + step, item); + ServersListBox.Enabled = true; ServersListBox.SelectedIndex = index + step; ServersListBox.EndUpdate(); From b1ebfe77724533996c36981b48c1ce0ff8890270 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Wed, 19 Aug 2015 19:35:37 -0700 Subject: [PATCH 22/29] prevent moving up and down when unsaved --- shadowsocks-csharp/View/ConfigForm.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index edcb405e..6e4e98ef 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -269,6 +269,10 @@ namespace Shadowsocks.View private void MoveUpButton_Click(object sender, EventArgs e) { + if (!SaveOldSelectedServer()) + { + return; + } if (ServersListBox.SelectedIndex > 0) { MoveConfigItem(-1); // -1 means move backward @@ -277,6 +281,10 @@ namespace Shadowsocks.View private void MoveDownButton_Click(object sender, EventArgs e) { + if (!SaveOldSelectedServer()) + { + return; + } if (ServersListBox.SelectedIndex < ServersListBox.Items.Count - 1) { MoveConfigItem(+1); // +1 means move forward From cec6f79e7e908c411a6aca24a5d89cc300aef42a Mon Sep 17 00:00:00 2001 From: kimw <1@kimwong.me> Date: Wed, 19 Aug 2015 21:52:16 +0800 Subject: [PATCH 23/29] improved `log viewer`: 1. add `clean log` feature 2. add `change font` feature 3. add `wrap text` feature 4. add `top most` feature --- shadowsocks-csharp/Data/cn.txt | 11 ++ shadowsocks-csharp/View/LogForm.Designer.cs | 170 +++++++++++++++----- shadowsocks-csharp/View/LogForm.cs | 58 +++++-- 3 files changed, 186 insertions(+), 53 deletions(-) diff --git a/shadowsocks-csharp/Data/cn.txt b/shadowsocks-csharp/Data/cn.txt index b4217a85..81022f99 100644 --- a/shadowsocks-csharp/Data/cn.txt +++ b/shadowsocks-csharp/Data/cn.txt @@ -45,6 +45,17 @@ New server=未配置的服务器 Move &Up=上移(&U) Move D&own=下移(&O) +# Log Form + +&File=文件(&F) +&Open Location=在资源管理器中打开(&O) +E&xit=退出(&X) +&Clean logs=清空(&C) +&Font=字体(&F) +&Wrap text=自动换行(&W) +&Top most=置顶(&T) +Log Viewer=日志查看器 + # QRCode Form QRCode=二维码 diff --git a/shadowsocks-csharp/View/LogForm.Designer.cs b/shadowsocks-csharp/View/LogForm.Designer.cs index 7eb921ed..d0913d16 100644 --- a/shadowsocks-csharp/View/LogForm.Designer.cs +++ b/shadowsocks-csharp/View/LogForm.Designer.cs @@ -29,29 +29,37 @@ private void InitializeComponent() { this.components = new System.ComponentModel.Container(); - this.textBox1 = new System.Windows.Forms.TextBox(); + 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.menuItem1 = new System.Windows.Forms.MenuItem(); - this.menuItem2 = new System.Windows.Forms.MenuItem(); - this.menuItem4 = new System.Windows.Forms.MenuItem(); + 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.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.tableLayoutPanel1.SuspendLayout(); this.SuspendLayout(); // - // textBox1 - // - this.textBox1.BackColor = System.Drawing.Color.Black; - this.textBox1.Dock = System.Windows.Forms.DockStyle.Fill; - this.textBox1.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.textBox1.ForeColor = System.Drawing.Color.White; - this.textBox1.Location = new System.Drawing.Point(0, 0); - this.textBox1.MaxLength = 2147483647; - this.textBox1.Multiline = true; - this.textBox1.Name = "textBox1"; - this.textBox1.ReadOnly = true; - this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Both; - this.textBox1.Size = new System.Drawing.Size(547, 382); - this.textBox1.TabIndex = 0; - this.textBox1.WordWrap = false; + // LogMessageTextBox + // + this.LogMessageTextBox.BackColor = System.Drawing.Color.Black; + 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.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.TabIndex = 0; + this.LogMessageTextBox.WordWrap = false; // // contextMenuStrip1 // @@ -61,34 +69,103 @@ // mainMenu1 // this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { - this.menuItem1}); + this.FileMenuItem}); + // + // FileMenuItem + // + this.FileMenuItem.Index = 0; + this.FileMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { + this.OpenLocationMenuItem, + this.ExitMenuItem}); + this.FileMenuItem.Text = "&File"; + // + // OpenLocationMenuItem + // + this.OpenLocationMenuItem.Index = 0; + this.OpenLocationMenuItem.Text = "&Open Location"; + this.OpenLocationMenuItem.Click += new System.EventHandler(this.OpenLocationMenuItem_Click); + // + // ExitMenuItem + // + this.ExitMenuItem.Index = 1; + this.ExitMenuItem.Text = "E&xit"; + this.ExitMenuItem.Click += new System.EventHandler(this.ExitMenuItem_Click); + // + // panel1 + // + 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; + // + // ChangeFontButton + // + this.ChangeFontButton.Location = new System.Drawing.Point(107, 4); + this.ChangeFontButton.Name = "ChangeFontButton"; + this.ChangeFontButton.Size = new System.Drawing.Size(75, 23); + this.ChangeFontButton.TabIndex = 2; + this.ChangeFontButton.Text = "&Font"; + this.ChangeFontButton.UseVisualStyleBackColor = true; + this.ChangeFontButton.Click += new System.EventHandler(this.ChangeFontButton_Click); + // + // CleanLogsButton + // + this.CleanLogsButton.Location = new System.Drawing.Point(9, 4); + this.CleanLogsButton.Name = "CleanLogsButton"; + this.CleanLogsButton.Size = new System.Drawing.Size(75, 23); + this.CleanLogsButton.TabIndex = 1; + this.CleanLogsButton.Text = "&Clean logs"; + this.CleanLogsButton.UseVisualStyleBackColor = true; + this.CleanLogsButton.Click += new System.EventHandler(this.CleanLogsButton_Click); // - // menuItem1 + // WrapTextCheckBox // - this.menuItem1.Index = 0; - this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { - this.menuItem2, - this.menuItem4}); - this.menuItem1.Text = "&File"; + this.WrapTextCheckBox.AutoSize = true; + this.WrapTextCheckBox.Location = new System.Drawing.Point(209, 9); + this.WrapTextCheckBox.Name = "WrapTextCheckBox"; + this.WrapTextCheckBox.Size = new System.Drawing.Size(78, 16); + this.WrapTextCheckBox.TabIndex = 0; + this.WrapTextCheckBox.Text = "&Wrap text"; + this.WrapTextCheckBox.UseVisualStyleBackColor = true; + this.WrapTextCheckBox.CheckedChanged += new System.EventHandler(this.WrapTextCheckBox_CheckedChanged); // - // menuItem2 + // tableLayoutPanel1 // - this.menuItem2.Index = 0; - this.menuItem2.Text = "&Open Location"; - this.menuItem2.Click += new System.EventHandler(this.menuItem2_Click); + 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.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.TabIndex = 2; // - // menuItem4 + // TopMostCheckBox // - this.menuItem4.Index = 1; - this.menuItem4.Text = "E&xit"; - this.menuItem4.Click += new System.EventHandler(this.menuItem4_Click); + 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); // // LogForm // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(547, 382); - this.Controls.Add(this.textBox1); + this.ClientSize = new System.Drawing.Size(547, 353); + this.Controls.Add(this.tableLayoutPanel1); this.Menu = this.mainMenu1; this.Name = "LogForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; @@ -96,18 +173,27 @@ 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.ResumeLayout(false); - this.PerformLayout(); } #endregion - private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.TextBox LogMessageTextBox; private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; private System.Windows.Forms.MainMenu mainMenu1; - private System.Windows.Forms.MenuItem menuItem1; - private System.Windows.Forms.MenuItem menuItem2; - private System.Windows.Forms.MenuItem menuItem4; + 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; } } \ No newline at end of file diff --git a/shadowsocks-csharp/View/LogForm.cs b/shadowsocks-csharp/View/LogForm.cs index bdb9ad5c..c01c9c6b 100644 --- a/shadowsocks-csharp/View/LogForm.cs +++ b/shadowsocks-csharp/View/LogForm.cs @@ -1,4 +1,5 @@ -using Shadowsocks.Properties; +using Shadowsocks.Controller; +using Shadowsocks.Properties; using System; using System.Collections.Generic; using System.ComponentModel; @@ -23,6 +24,20 @@ namespace Shadowsocks.View this.filename = filename; InitializeComponent(); this.Icon = Icon.FromHandle(Resources.ssw128.GetHicon()); + + UpdateTexts(); + } + + private void UpdateTexts() + { + 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"); + this.Text = I18N.GetString("Log Viewer"); } private void Timer_Tick(object sender, EventArgs e) @@ -43,9 +58,9 @@ namespace Shadowsocks.View string line = ""; while ((line = reader.ReadLine()) != null) - textBox1.AppendText(line + "\r\n"); + LogMessageTextBox.AppendText(line + "\r\n"); - textBox1.ScrollToCaret(); + LogMessageTextBox.ScrollToCaret(); lastOffset = reader.BaseStream.Position; } @@ -63,12 +78,12 @@ namespace Shadowsocks.View while ((line = reader.ReadLine()) != null) { changed = true; - textBox1.AppendText(line + "\r\n"); + LogMessageTextBox.AppendText(line + "\r\n"); } if (changed) { - textBox1.ScrollToCaret(); + LogMessageTextBox.ScrollToCaret(); } lastOffset = reader.BaseStream.Position; @@ -89,25 +104,46 @@ namespace Shadowsocks.View timer.Stop(); } - private void menuItem2_Click(object sender, EventArgs e) + private void OpenLocationMenuItem_Click(object sender, EventArgs e) { string argument = @"/select, " + filename; System.Diagnostics.Process.Start("explorer.exe", argument); } - private void menuItem3_Click(object sender, EventArgs e) + private void ExitMenuItem_Click(object sender, EventArgs e) { + this.Close(); + } + private void LogForm_Shown(object sender, EventArgs e) + { + LogMessageTextBox.ScrollToCaret(); } - private void menuItem4_Click(object sender, EventArgs e) + private void WrapTextCheckBox_CheckedChanged(object sender, EventArgs e) { - this.Close(); + LogMessageTextBox.WordWrap = WrapTextCheckBox.Checked; + LogMessageTextBox.ScrollToCaret(); } - private void LogForm_Shown(object sender, EventArgs e) + private void CleanLogsButton_Click(object sender, EventArgs e) + { + LogMessageTextBox.Clear(); + } + + private void ChangeFontButton_Click(object sender, EventArgs e) + { + FontDialog fd = new FontDialog(); + fd.Font = LogMessageTextBox.Font; + if (fd.ShowDialog() == DialogResult.OK) + { + LogMessageTextBox.Font = fd.Font; + } + } + + private void TopMostCheckBox_CheckedChanged(object sender, EventArgs e) { - textBox1.ScrollToCaret(); + this.TopMost = TopMostCheckBox.Checked; } } } From 14381cf887004227288d2846eb49852b9d0e4d34 Mon Sep 17 00:00:00 2001 From: kimw <1@kimwong.me> Date: Wed, 19 Aug 2015 22:23:54 +0800 Subject: [PATCH 24/29] update version number --- shadowsocks-csharp/Controller/Service/UpdateChecker.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadowsocks-csharp/Controller/Service/UpdateChecker.cs b/shadowsocks-csharp/Controller/Service/UpdateChecker.cs index 9a3f832c..b2ef20dc 100644 --- a/shadowsocks-csharp/Controller/Service/UpdateChecker.cs +++ b/shadowsocks-csharp/Controller/Service/UpdateChecker.cs @@ -18,7 +18,7 @@ namespace Shadowsocks.Controller public string LatestVersionURL; public event EventHandler NewVersionFound; - public const string Version = "2.5.5"; + public const string Version = "2.5.6"; public void CheckUpdate(Configuration config) { From c767f55b3c3612b751caed8f94b4c048f5e31190 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Wed, 19 Aug 2015 21:39:06 -0700 Subject: [PATCH 25/29] add portable mode --- shadowsocks-csharp/Controller/Logging.cs | 5 +++-- .../Service/AvailabilityStatistics.cs | 5 +++-- .../Controller/Service/PolipoRunner.cs | 3 ++- shadowsocks-csharp/Encryption/PolarSSL.cs | 3 ++- shadowsocks-csharp/Encryption/Sodium.cs | 3 ++- shadowsocks-csharp/Util/Util.cs | 18 ++++++++++++++++++ 6 files changed, 30 insertions(+), 7 deletions(-) diff --git a/shadowsocks-csharp/Controller/Logging.cs b/shadowsocks-csharp/Controller/Logging.cs index 126dab70..d77a3fbe 100755 --- a/shadowsocks-csharp/Controller/Logging.cs +++ b/shadowsocks-csharp/Controller/Logging.cs @@ -1,4 +1,5 @@ -using System; +using Shadowsocks.Util; +using System; using System.Collections.Generic; using System.IO; using System.Net.Sockets; @@ -14,7 +15,7 @@ namespace Shadowsocks.Controller { try { - string temppath = Path.GetTempPath(); + string temppath = Utils.GetTempPath(); LogFile = Path.Combine(temppath, "shadowsocks.log"); FileStream fs = new FileStream(LogFile, FileMode.Append); StreamWriterWithTimestamp sw = new StreamWriterWithTimestamp(fs); diff --git a/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs b/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs index 0d8463a6..f3d088c5 100644 --- a/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs +++ b/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs @@ -6,7 +6,8 @@ using System.Net.NetworkInformation; using System.Threading; using Shadowsocks.Model; using System.Reflection; - +using Shadowsocks.Util; + namespace Shadowsocks.Controller { class AvailabilityStatistics @@ -25,7 +26,7 @@ namespace Shadowsocks.Controller //static constructor to initialize every public static fields before refereced static AvailabilityStatistics() { - string temppath = Path.GetTempPath(); + string temppath = Utils.GetTempPath(); AvailabilityStatisticsFile = Path.Combine(temppath, StatisticsFilesName); } diff --git a/shadowsocks-csharp/Controller/Service/PolipoRunner.cs b/shadowsocks-csharp/Controller/Service/PolipoRunner.cs index 3b3a5a4c..5b784bcd 100644 --- a/shadowsocks-csharp/Controller/Service/PolipoRunner.cs +++ b/shadowsocks-csharp/Controller/Service/PolipoRunner.cs @@ -9,6 +9,7 @@ using System.Text; using System.Net.NetworkInformation; using System.Net; using System.Runtime.InteropServices; +using Shadowsocks.Util; namespace Shadowsocks.Controller { @@ -20,7 +21,7 @@ namespace Shadowsocks.Controller static PolipoRunner() { - temppath = Path.GetTempPath(); + temppath = Utils.GetTempPath(); try { FileManager.UncompressFile(temppath + "/ss_privoxy.exe", Resources.privoxy_exe); diff --git a/shadowsocks-csharp/Encryption/PolarSSL.cs b/shadowsocks-csharp/Encryption/PolarSSL.cs index f5c2626d..42ce5bf7 100755 --- a/shadowsocks-csharp/Encryption/PolarSSL.cs +++ b/shadowsocks-csharp/Encryption/PolarSSL.cs @@ -1,5 +1,6 @@ using Shadowsocks.Controller; using Shadowsocks.Properties; +using Shadowsocks.Util; using System; using System.Collections.Generic; using System.IO; @@ -18,7 +19,7 @@ namespace Shadowsocks.Encryption static PolarSSL() { - string tempPath = Path.GetTempPath(); + string tempPath = Utils.GetTempPath(); string dllPath = tempPath + "/libsscrypto.dll"; try { diff --git a/shadowsocks-csharp/Encryption/Sodium.cs b/shadowsocks-csharp/Encryption/Sodium.cs index 9bc72d32..564aaeda 100755 --- a/shadowsocks-csharp/Encryption/Sodium.cs +++ b/shadowsocks-csharp/Encryption/Sodium.cs @@ -1,5 +1,6 @@ using Shadowsocks.Controller; using Shadowsocks.Properties; +using Shadowsocks.Util; using System; using System.Collections.Generic; using System.IO; @@ -14,7 +15,7 @@ namespace Shadowsocks.Encryption static Sodium() { - string tempPath = Path.GetTempPath(); + string tempPath = Utils.GetTempPath(); string dllPath = tempPath + "/libsscrypto.dll"; try { diff --git a/shadowsocks-csharp/Util/Util.cs b/shadowsocks-csharp/Util/Util.cs index 004128af..8cbdb31d 100755 --- a/shadowsocks-csharp/Util/Util.cs +++ b/shadowsocks-csharp/Util/Util.cs @@ -5,11 +5,29 @@ using System.IO; using System.IO.Compression; using System.Runtime.InteropServices; using System.Text; +using System.Windows.Forms; namespace Shadowsocks.Util { public class Utils { + // return path to store temporary files + public static string GetTempPath() + { + if (File.Exists(Application.StartupPath + "/shadowsocks_portable_mode.txt")) + { + try + { + Directory.CreateDirectory(Application.StartupPath + "/temp"); + } catch (Exception e) + { + Console.WriteLine(e); + } + return Application.StartupPath + "/temp"; + } + return Path.GetTempPath(); + } + public static void ReleaseMemory(bool removePages) { // release any unused pages From 765720dbd944f9dea5c1b076b6efc743cda86756 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Wed, 19 Aug 2015 21:51:28 -0700 Subject: [PATCH 26/29] small fix --- CHANGES | 9 +++++++++ shadowsocks-csharp/Util/Util.cs | 7 ++++--- shadowsocks-csharp/View/LogForm.cs | 3 ++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 2ddecc94..647c146f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,12 @@ +2.5.6 2015-08-19 +- Add portable mode +- Support server reorder + +2.5.5 2015-08-17 +- Fix crash when enabling Availability Statistics and some servers can not be resolved +- Allow multiple instances +- Other fixes + 2.5.4 2015-08-16 - Hide Privoxy icon diff --git a/shadowsocks-csharp/Util/Util.cs b/shadowsocks-csharp/Util/Util.cs index 8cbdb31d..1858ee90 100755 --- a/shadowsocks-csharp/Util/Util.cs +++ b/shadowsocks-csharp/Util/Util.cs @@ -14,16 +14,17 @@ namespace Shadowsocks.Util // return path to store temporary files public static string GetTempPath() { - if (File.Exists(Application.StartupPath + "/shadowsocks_portable_mode.txt")) + if (File.Exists(Application.StartupPath + "\\shadowsocks_portable_mode.txt")) { try { - Directory.CreateDirectory(Application.StartupPath + "/temp"); + Directory.CreateDirectory(Application.StartupPath + "\\temp"); } catch (Exception e) { Console.WriteLine(e); } - return Application.StartupPath + "/temp"; + // don't use "/", it will fail when we call explorer /select xxx/temp\xxx.log + return Application.StartupPath + "\\temp"; } return Path.GetTempPath(); } diff --git a/shadowsocks-csharp/View/LogForm.cs b/shadowsocks-csharp/View/LogForm.cs index bdb9ad5c..d9255853 100644 --- a/shadowsocks-csharp/View/LogForm.cs +++ b/shadowsocks-csharp/View/LogForm.cs @@ -91,7 +91,8 @@ namespace Shadowsocks.View private void menuItem2_Click(object sender, EventArgs e) { - string argument = @"/select, " + filename; + string argument = "/select, \"" + filename + "\""; + Console.WriteLine(argument); System.Diagnostics.Process.Start("explorer.exe", argument); } From 726200c0f196f26dd6073604fc2083bbfff278d7 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Wed, 19 Aug 2015 21:56:31 -0700 Subject: [PATCH 27/29] update CHANGES --- CHANGES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 647c146f..5c5aba5f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,5 @@ 2.5.6 2015-08-19 -- Add portable mode +- Add portable mode. Create shadowsocks_portable_mode.txt to use it - Support server reorder 2.5.5 2015-08-17 From b8858c4f8d74359b01570bee0ca2d1407609d11e Mon Sep 17 00:00:00 2001 From: clowwindy Date: Wed, 19 Aug 2015 22:19:20 -0700 Subject: [PATCH 28/29] bump 2.5.6 --- shadowsocks-csharp/Controller/Service/UpdateChecker.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadowsocks-csharp/Controller/Service/UpdateChecker.cs b/shadowsocks-csharp/Controller/Service/UpdateChecker.cs index 9a3f832c..b2ef20dc 100644 --- a/shadowsocks-csharp/Controller/Service/UpdateChecker.cs +++ b/shadowsocks-csharp/Controller/Service/UpdateChecker.cs @@ -18,7 +18,7 @@ namespace Shadowsocks.Controller public string LatestVersionURL; public event EventHandler NewVersionFound; - public const string Version = "2.5.5"; + public const string Version = "2.5.6"; public void CheckUpdate(Configuration config) { From c095030041d99baca9d284beff95dda8ade6bf85 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Wed, 19 Aug 2015 22:36:38 +0800 Subject: [PATCH 29/29] Update README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 54d604bf..83bff1ef 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,11 @@ one HTTP proxy instance. Please visit [Servers] for more information. +#### Portable Mode + +If you want to put all temporary files into shadowsocks/temp folder instead of +system temp folder, create a `shadowsocks_portable_mode.txt` into shadowsocks folder. + #### Develop Visual Studio 2015 is required.