celeron533 6 years ago
parent
commit
f9e00d860b
8 changed files with 388 additions and 231 deletions
  1. +1
    -1
      appveyor.yml
  2. +73
    -99
      shadowsocks-csharp/Controller/ShadowsocksController.cs
  3. +0
    -1
      shadowsocks-csharp/Data/ja.txt
  4. +8
    -1
      shadowsocks-csharp/Data/zh_CN.txt
  5. +0
    -1
      shadowsocks-csharp/Data/zh_TW.txt
  6. +25
    -8
      shadowsocks-csharp/Model/Configuration.cs
  7. +273
    -115
      shadowsocks-csharp/View/ConfigForm.cs
  8. +8
    -5
      shadowsocks-csharp/View/MenuViewController.cs

+ 1
- 1
appveyor.yml View File

@@ -1,5 +1,5 @@
version: 1.0.{build}
image: Visual Studio 2015
image: Visual Studio 2017
environment:
matrix:
- platform: x86


+ 73
- 99
shadowsocks-csharp/Controller/ShadowsocksController.cs View File

@@ -2,21 +2,18 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Web;
using System.Windows.Forms;
using Newtonsoft.Json;
using Shadowsocks.Controller.Service;
using Shadowsocks.Controller.Strategy;
using Shadowsocks.Model;
using Shadowsocks.Properties;
using Shadowsocks.Util;
using System.Linq;
using Shadowsocks.Controller.Service;
using Shadowsocks.Proxy;
namespace Shadowsocks.Controller
{
@@ -100,10 +97,7 @@ namespace Shadowsocks.Controller
protected void ReportError(Exception e)
{
if (Errored != null)
{
Errored(this, new ErrorEventArgs(e));
}
Errored?.Invoke(this, new ErrorEventArgs(e));
}
public Server GetCurrentServer()
@@ -132,7 +126,7 @@ namespace Shadowsocks.Controller
{
foreach (var strategy in _strategyManager.GetStrategies())
{
if (strategy.ID == this._config.strategy)
if (strategy.ID == _config.strategy)
{
return strategy;
}
@@ -197,9 +191,13 @@ namespace Shadowsocks.Controller
{
try
{
if (ssURL.IsNullOrEmpty() || ssURL.IsWhiteSpace()) return false;
if (ssURL.IsNullOrEmpty() || ssURL.IsWhiteSpace())
return false;
var servers = Server.GetServers(ssURL);
if (servers == null || servers.Count == 0) return false;
if (servers == null || servers.Count == 0)
return false;
foreach (var server in servers)
{
_config.configs.Add(server);
@@ -219,30 +217,24 @@ namespace Shadowsocks.Controller
{
_config.enabled = enabled;
SaveConfig(_config);
if (EnableStatusChanged != null)
{
EnableStatusChanged(this, new EventArgs());
}
EnableStatusChanged?.Invoke(this, new EventArgs());
}
public void ToggleGlobal(bool global)
{
_config.global = global;
SaveConfig(_config);
if (EnableGlobalChanged != null)
{
EnableGlobalChanged(this, new EventArgs());
}
EnableGlobalChanged?.Invoke(this, new EventArgs());
}
public void ToggleShareOverLAN(bool enabled)
{
_config.shareOverLan = enabled;
SaveConfig(_config);
if (ShareOverLANStatusChanged != null)
{
ShareOverLANStatusChanged(this, new EventArgs());
}
ShareOverLANStatusChanged?.Invoke(this, new EventArgs());
}
public void SaveProxy(ProxyConfig proxyConfig)
@@ -255,10 +247,8 @@ namespace Shadowsocks.Controller
{
_config.isVerboseLogging = enabled;
SaveConfig(_config);
if (VerboseLoggingStatusChanged != null)
{
VerboseLoggingStatusChanged(this, new EventArgs());
}
VerboseLoggingStatusChanged?.Invoke(this, new EventArgs());
}
public void SelectServerIndex(int index)
@@ -310,19 +300,15 @@ namespace Shadowsocks.Controller
public void TouchPACFile()
{
string pacFilename = _pacServer.TouchPACFile();
if (PACFileReadyToOpen != null)
{
PACFileReadyToOpen(this, new PathEventArgs() { Path = pacFilename });
}
PACFileReadyToOpen?.Invoke(this, new PathEventArgs() { Path = pacFilename });
}
public void TouchUserRuleFile()
{
string userRuleFilename = _pacServer.TouchUserRuleFile();
if (UserRuleFileReadyToOpen != null)
{
UserRuleFileReadyToOpen(this, new PathEventArgs() { Path = userRuleFilename });
}
UserRuleFileReadyToOpen?.Invoke(this, new PathEventArgs() { Path = userRuleFilename });
}
public string GetServerURLForCurrentServer()
@@ -381,60 +367,51 @@ namespace Shadowsocks.Controller
public void UpdateStatisticsConfiguration(bool enabled)
{
if (availabilityStatistics == null) return;
availabilityStatistics.UpdateConfiguration(this);
_config.availabilityStatistics = enabled;
SaveConfig(_config);
if (availabilityStatistics != null)
{
availabilityStatistics.UpdateConfiguration(this);
_config.availabilityStatistics = enabled;
SaveConfig(_config);
}
}
public void SavePACUrl(string pacUrl)
{
_config.pacUrl = pacUrl;
SaveConfig(_config);
if (ConfigChanged != null)
{
ConfigChanged(this, new EventArgs());
}
ConfigChanged?.Invoke(this, new EventArgs());
}
public void UseOnlinePAC(bool useOnlinePac)
{
_config.useOnlinePac = useOnlinePac;
SaveConfig(_config);
if (ConfigChanged != null)
{
ConfigChanged(this, new EventArgs());
}
ConfigChanged?.Invoke(this, new EventArgs());
}
public void ToggleSecureLocalPac(bool enabled)
{
_config.secureLocalPac = enabled;
SaveConfig(_config);
if (ConfigChanged != null)
{
ConfigChanged(this, new EventArgs());
}
ConfigChanged?.Invoke(this, new EventArgs());
}
public void ToggleCheckingUpdate(bool enabled)
{
_config.autoCheckUpdate = enabled;
Configuration.Save(_config);
if (ConfigChanged != null)
{
ConfigChanged(this, new EventArgs());
}
ConfigChanged?.Invoke(this, new EventArgs());
}
public void ToggleCheckingPreRelease(bool enabled)
{
_config.checkPreRelease = enabled;
Configuration.Save(_config);
if (ConfigChanged != null)
{
ConfigChanged(this, new EventArgs());
}
ConfigChanged?.Invoke(this, new EventArgs());
}
public void SaveLogViewerConfig(LogViewerConfig newConfig)
@@ -442,20 +419,16 @@ namespace Shadowsocks.Controller
_config.logViewer = newConfig;
newConfig.SaveSize();
Configuration.Save(_config);
if (ConfigChanged != null)
{
ConfigChanged(this, new EventArgs());
}
ConfigChanged?.Invoke(this, new EventArgs());
}
public void SaveHotkeyConfig(HotkeyConfig newConfig)
{
_config.hotkey = newConfig;
SaveConfig(_config);
if (ConfigChanged != null)
{
ConfigChanged(this, new EventArgs());
}
ConfigChanged?.Invoke(this, new EventArgs());
}
public void UpdateLatency(Server server, TimeSpan latency)
@@ -498,15 +471,15 @@ namespace Shadowsocks.Controller
if (_pacServer == null)
{
_pacServer = new PACServer();
_pacServer.PACFileChanged += pacServer_PACFileChanged;
_pacServer.UserRuleFileChanged += pacServer_UserRuleFileChanged;
_pacServer.PACFileChanged += PacServer_PACFileChanged;
_pacServer.UserRuleFileChanged += PacServer_UserRuleFileChanged;
}
_pacServer.UpdateConfiguration(_config);
if (gfwListUpdater == null)
{
gfwListUpdater = new GFWListUpdater();
gfwListUpdater.UpdateCompleted += pacServer_PACUpdateCompleted;
gfwListUpdater.Error += pacServer_PACUpdateError;
gfwListUpdater.UpdateCompleted += PacServer_PACUpdateCompleted;
gfwListUpdater.Error += PacServer_PACUpdateError;
}
availabilityStatistics.UpdateConfiguration(this);
@@ -536,11 +509,13 @@ namespace Shadowsocks.Controller
TCPRelay tcpRelay = new TCPRelay(this, _config);
UDPRelay udpRelay = new UDPRelay(this);
List<Listener.IService> services = new List<Listener.IService>();
services.Add(tcpRelay);
services.Add(udpRelay);
services.Add(_pacServer);
services.Add(new PortForwarder(privoxyRunner.RunningPort));
List<Listener.IService> services = new List<Listener.IService>
{
tcpRelay,
udpRelay,
_pacServer,
new PortForwarder(privoxyRunner.RunningPort)
};
_listener = new Listener(services);
_listener.Start(_config);
}
@@ -548,9 +523,8 @@ namespace Shadowsocks.Controller
{
// translate Microsoft language into human language
// i.e. An attempt was made to access a socket in a way forbidden by its access permissions => Port already in use
if (e is SocketException)
if (e is SocketException se)
{
SocketException se = (SocketException)e;
if (se.SocketErrorCode == SocketError.AddressAlreadyInUse)
{
e = new Exception(I18N.GetString("Port {0} already in use", _config.localPort), e);
@@ -564,10 +538,7 @@ namespace Shadowsocks.Controller
ReportError(e);
}
if (ConfigChanged != null)
{
ConfigChanged(this, new EventArgs());
}
ConfigChanged?.Invoke(this, new EventArgs());
UpdateSystemProxy();
Utils.ReleaseMemory(true);
@@ -590,25 +561,23 @@ namespace Shadowsocks.Controller
SystemProxy.Update(_config, false, _pacServer);
}
private void pacServer_PACFileChanged(object sender, EventArgs e)
private void PacServer_PACFileChanged(object sender, EventArgs e)
{
UpdateSystemProxy();
}
private void pacServer_PACUpdateCompleted(object sender, GFWListUpdater.ResultEventArgs e)
private void PacServer_PACUpdateCompleted(object sender, GFWListUpdater.ResultEventArgs e)
{
if (UpdatePACFromGFWListCompleted != null)
UpdatePACFromGFWListCompleted(this, e);
UpdatePACFromGFWListCompleted?.Invoke(this, e);
}
private void pacServer_PACUpdateError(object sender, ErrorEventArgs e)
private void PacServer_PACUpdateError(object sender, ErrorEventArgs e)
{
if (UpdatePACFromGFWListError != null)
UpdatePACFromGFWListError(this, e);
UpdatePACFromGFWListError?.Invoke(this, e);
}
private static readonly IEnumerable<char> IgnoredLineBegins = new[] { '!', '[' };
private void pacServer_UserRuleFileChanged(object sender, EventArgs e)
private void PacServer_UserRuleFileChanged(object sender, EventArgs e)
{
if (!File.Exists(Utils.GetTempPath("gfwlist.txt")))
{
@@ -630,8 +599,10 @@ namespace Shadowsocks.Controller
private void StartReleasingMemory()
{
_ramThread = new Thread(new ThreadStart(ReleaseMemory));
_ramThread.IsBackground = true;
_ramThread = new Thread(new ThreadStart(ReleaseMemory))
{
IsBackground = true
};
_ramThread.Start();
}
@@ -655,8 +626,10 @@ namespace Shadowsocks.Controller
{
trafficPerSecondQueue.Enqueue(new TrafficPerSecond());
}
_trafficThread = new Thread(new ThreadStart(() => TrafficStatistics(queueMaxSize)));
_trafficThread.IsBackground = true;
_trafficThread = new Thread(new ThreadStart(() => TrafficStatistics(queueMaxSize)))
{
IsBackground = true
};
_trafficThread.Start();
}
@@ -666,10 +639,11 @@ namespace Shadowsocks.Controller
while (true)
{
previous = trafficPerSecondQueue.Last();
current = new TrafficPerSecond();
current.inboundCounter = InboundCounter;
current.outboundCounter = OutboundCounter;
current = new TrafficPerSecond
{
inboundCounter = InboundCounter,
outboundCounter = OutboundCounter
};
current.inboundIncreasement = current.inboundCounter - previous.inboundCounter;
current.outboundIncreasement = current.outboundCounter - previous.outboundCounter;


+ 0
- 1
shadowsocks-csharp/Data/ja.txt View File

@@ -122,7 +122,6 @@ Port {0} is reserved by system= ポート番号 {0} はシステムによって
Invalid server address=サーバーアドレスが無効です。
Illegal port number format=ポート番号のフォーマットが無効です。
Illegal timeout format=タイムアウト値のフォーマットが無効です。
Please add at least one server=少なくとも一つのサーバーを指定して下さい。
Server IP can not be blank=サーバー IP が指定されていません。
Password can not be blank=パスワードが指定されていません。
Port out of range=ポート番号は範囲外です。


+ 8
- 1
shadowsocks-csharp/Data/zh_CN.txt View File

@@ -123,7 +123,6 @@ Port {0} is reserved by system=端口 {0} 是系统保留端口
Invalid server address=非法服务器地址
Illegal port number format=非法端口格式
Illegal timeout format=非法超时格式
Please add at least one server=请添加至少一个服务器
Server IP can not be blank=服务器 IP 不能为空
Password can not be blank=密码不能为空
Port out of range=端口超出范围
@@ -155,6 +154,14 @@ Register hotkey failed=注册快捷键失败
Cannot parse hotkey: {0}=解析快捷键失败: {0}
Timeout is invalid, it should not exceed {0}=超时无效,不应超过 {0}
Operation failure=操作失败
Auto save failed=自动保存失败
Whether to discard unconfigured servers=是否丢弃未配置的服务器
Invalid server address, Cannot automatically save or discard changes=非法服务器地址,无法自动保存是否丢弃修改
Illegal port number format, Cannot automatically save or discard changes=非法端口格式,无法自动保存是否丢弃修改
Password can not be blank, Cannot automatically save or discard changes=密码不能为空,无法自动保存是否丢弃修改
Illegal timeout format, Cannot automatically save or discard changes=非法超时格式,无法自动保存是否丢弃修改
Error occured when process proxy setting, do you want reset current setting and retry?=处理代理设置时发生错误,是否重置当前代理设置并重试?
Unrecoverable proxy setting error occured, see log for detail=发生不可恢复的代理设置错误,查看日志以取得详情
Auth user can not be blank=认证用户不能为空

+ 0
- 1
shadowsocks-csharp/Data/zh_TW.txt View File

@@ -122,7 +122,6 @@ Port {0} is reserved by system=連接埠號碼 {0} 由系統保留
Invalid server address=無效伺服器位址
Illegal port number format=無效連接埠號碼格式
Illegal timeout format=無效逾時格式
Please add at least one server=請新增至少一個伺服器
Server IP can not be blank=伺服器 IP 不能為空
Password can not be blank=密碼不能為空
Port out of range=連接埠號碼超出範圍


+ 25
- 8
shadowsocks-csharp/Model/Configuration.cs View File

@@ -1,9 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using Shadowsocks.Controller;
using Newtonsoft.Json;
using Shadowsocks.Controller;
namespace Shadowsocks.Model
{
@@ -34,7 +33,7 @@ namespace Shadowsocks.Model
public ProxyConfig proxy;
public HotkeyConfig hotkey;
private static string CONFIG_FILE = "gui-config.json";
private static readonly string CONFIG_FILE = "gui-config.json";
public Server GetCurrentServer()
{
@@ -46,12 +45,25 @@ namespace Shadowsocks.Model
public static void CheckServer(Server server)
{
CheckServer(server.server);
CheckPort(server.server_port);
CheckPassword(server.password);
CheckServer(server.server);
CheckTimeout(server.timeout, Server.MaxServerTimeoutSec);
}
public static bool ChecksServer(Server server)
{
try
{
CheckServer(server);
return true;
}
catch (Exception)
{
return false;
}
}
public static Configuration Load()
{
try
@@ -125,12 +137,18 @@ namespace Shadowsocks.Model
}
}
public static Server AddDefaultServerOrServer(Configuration config, Server server = null)
public static Server AddDefaultServerOrServer(Configuration config, Server server = null, int? index = null)
{
if (config != null && config.configs != null)
{
server = (server ?? GetDefaultServer());
config.configs.Add(server);
config.configs.Insert(index.GetValueOrDefault(config.configs.Count), server);
//if (index.HasValue)
// config.configs.Insert(index.Value, server);
//else
// config.configs.Add(server);
}
return server;
}
@@ -174,8 +192,7 @@ namespace Shadowsocks.Model
public static void CheckTimeout(int timeout, int maxTimeout)
{
if (timeout <= 0 || timeout > maxTimeout)
throw new ArgumentException(
I18N.GetString("Timeout is invalid, it should not exceed {0}", maxTimeout));
throw new ArgumentException(I18N.GetString("Timeout is invalid, it should not exceed {0}", maxTimeout));
}
public static void CheckProxyAuthUser(string user)


+ 273
- 115
shadowsocks-csharp/View/ConfigForm.cs View File

@@ -1,5 +1,6 @@
using System;
using System.Drawing;
using System.Runtime.CompilerServices;
using System.Windows.Forms;
using Shadowsocks.Controller;
using Shadowsocks.Model;
@@ -17,20 +18,20 @@ namespace Shadowsocks.View
public ConfigForm(ShadowsocksController controller)
{
this.Font = SystemFonts.MessageBoxFont;
Font = SystemFonts.MessageBoxFont;
InitializeComponent();
// a dirty hack
this.ServersListBox.Dock = DockStyle.Fill;
this.tableLayoutPanel5.Dock = DockStyle.Fill;
this.PerformLayout();
ServersListBox.Dock = DockStyle.Fill;
tableLayoutPanel5.Dock = DockStyle.Fill;
PerformLayout();
UpdateTexts();
SetupValueChangedListeners();
this.Icon = Icon.FromHandle(Resources.ssw128.GetHicon());
Icon = Icon.FromHandle(Resources.ssw128.GetHicon());
this.controller = controller;
controller.ConfigChanged += controller_ConfigChanged;
controller.ConfigChanged += Controller_ConfigChanged;
LoadCurrentConfiguration();
}
@@ -51,7 +52,7 @@ namespace Shadowsocks.View
NeedPluginArgCheckBox.Text = I18N.GetString("Need Plugin Argument");
ProxyPortLabel.Text = I18N.GetString("Proxy Port");
PortableModeCheckBox.Text = I18N.GetString("Portable Mode");
toolTip1.SetToolTip(this.PortableModeCheckBox, I18N.GetString("Restart required"));
toolTip1.SetToolTip(PortableModeCheckBox, I18N.GetString("Restart required"));
RemarksLabel.Text = I18N.GetString("Remarks");
TimeoutLabel.Text = I18N.GetString("Timeout(Sec)");
ServerGroupBox.Text = I18N.GetString("Server");
@@ -60,7 +61,7 @@ namespace Shadowsocks.View
ApplyButton.Text = I18N.GetString("Apply");
MoveUpButton.Text = I18N.GetString("Move &Up");
MoveDownButton.Text = I18N.GetString("Move D&own");
this.Text = I18N.GetString("Edit Servers");
Text = I18N.GetString("Edit Servers");
}
private void SetupValueChangedListeners()
@@ -78,7 +79,7 @@ namespace Shadowsocks.View
ServerPortTextBox.TextChanged += ConfigValueChanged;
}
private void controller_ConfigChanged(object sender, EventArgs e)
private void Controller_ConfigChanged(object sender, EventArgs e)
{
LoadCurrentConfiguration();
}
@@ -88,7 +89,13 @@ namespace Shadowsocks.View
ApplyButton.Enabled = true;
}
private bool ValidateAndSaveSelectedServerDetails()
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void UpdateIndexToEnd()
{
_lastSelectedIndex = (ServersListBox.SelectedIndex = (_modifiedConfiguration.configs.Count - 1));
}
private bool ValidateAndSaveSelectedServerDetails(bool isSave = false, bool isCopy = false)
{
try
{
@@ -96,15 +103,17 @@ namespace Shadowsocks.View
{
return true;
}
Server server = GetServerDetailsFromUI();
if (server == null)
bool verify = GetServerDetailsFromUI(out Server server, isSave, isCopy);
if (server != null)
{
return false;
}
Configuration.CheckServer(server);
_modifiedConfiguration.configs[_lastSelectedIndex] = server;
if (isSave || isCopy)
Configuration.CheckServer(server);
return true;
_modifiedConfiguration.configs[_lastSelectedIndex] = server;
}
return verify;
}
catch (Exception ex)
{
@@ -113,36 +122,209 @@ namespace Shadowsocks.View
return false;
}
private Server GetServerDetailsFromUI()
private bool GetServerDetailsFromUI(out Server server, bool isSave = false, bool isCopy = false)
{
server = null;
bool? checkIP = false;
bool? checkPort = false;
bool? checkPassword = false;
bool? checkTimeout = false;
if ((checkIP = CheckIPTextBox(out string address, isSave, isCopy)).GetValueOrDefault(false) && address != null
&& (checkPort = CheckServerPortTextBox(out int? addressPort, isSave, isCopy)).GetValueOrDefault(false) && addressPort.HasValue
&& (checkPassword = CheckPasswordTextBox(out string serverPassword, isSave, isCopy)).GetValueOrDefault(false) && serverPassword != null
&& (checkTimeout = CheckTimeoutTextBox(out int? timeout, isSave, isCopy)).GetValueOrDefault(false) && timeout.HasValue)
{
server = new Server()
{
server = address,
server_port = addressPort.Value,
password = serverPassword,
method = EncryptionSelect.Text,
plugin = PluginTextBox.Text,
plugin_opts = PluginOptionsTextBox.Text,
plugin_args = PluginArgumentsTextBox.Text,
remarks = RemarksTextBox.Text,
timeout = timeout.Value,
};
return true;
}
if (checkIP == null || checkPort == null || checkTimeout == null)
{
_modifiedConfiguration.configs.RemoveAt(_lastSelectedIndex);
ServersListBox.SelectedIndexChanged -= ServersListBox_SelectedIndexChanged;
LoadServerNameListToUI(_modifiedConfiguration);
UpdateIndexToEnd();
ServersListBox.SelectedIndexChanged += ServersListBox_SelectedIndexChanged;
return true;
}
else
return false;
}
#region GetServerDetailsFromUI Check
private bool? CheckIPTextBox(out string address, bool isSave, bool isCopy)
{
address = null;
string outAddress;
if (Uri.CheckHostName(outAddress = IPTextBox.Text.Trim()) == UriHostNameType.Unknown)
{
if (!isSave && !isCopy && ServersListBox.Items.Count > 1 && I18N.GetString("New server").Equals(ServersListBox.Items[_lastSelectedIndex].ToString()))
{
DialogResult result = MessageBox.Show(I18N.GetString("Whether to discard unconfigured servers"), I18N.GetString("Operation failure"), MessageBoxButtons.OKCancel);
if (result == DialogResult.OK)
return null;
}
else if (ApplyButton.Enabled && !isSave && !isCopy)
{
var result = MessageBox.Show(I18N.GetString("Invalid server address, Cannot automatically save or discard changes"), I18N.GetString("Auto save failed"), MessageBoxButtons.OKCancel);
if (result == DialogResult.Cancel)
return false;
else
{
address = _modifiedConfiguration.configs[_lastSelectedIndex].server;
return true;
}
}
else
{
MessageBox.Show(I18N.GetString("Invalid server address"), I18N.GetString("Operation failure"));
IPTextBox.Focus();
}
return false;
}
else
{
address = outAddress;
}
return true;
}
private bool? CheckServerPortTextBox(out int? addressPort, bool isSave, bool isCopy)
{
addressPort = null;
if (!int.TryParse(ServerPortTextBox.Text, out int outaddressPort))
{
if (!isSave && !isCopy && ServersListBox.Items.Count > 1 && I18N.GetString("New server").Equals(ServersListBox.Items[_lastSelectedIndex].ToString()))
{
DialogResult result = MessageBox.Show(I18N.GetString("Whether to discard unconfigured servers"), I18N.GetString("Operation failure"), MessageBoxButtons.OKCancel);
if (result == DialogResult.OK)
return null;
}
else if (!isSave && !isCopy)
{
var result = MessageBox.Show(I18N.GetString("Illegal port number format, Cannot automatically save or discard changes"), I18N.GetString("Auto save failed"), MessageBoxButtons.OKCancel);
if (result == DialogResult.Cancel)
return false;
else
{
addressPort = _modifiedConfiguration.configs[_lastSelectedIndex].server_port;
return true;
}
}
else
{
MessageBox.Show(I18N.GetString("Illegal port number format"), I18N.GetString("Operation failure"));
ServerPortTextBox.Focus();
}
return false;
}
else
{
addressPort = outaddressPort;
}
return true;
}
private bool? CheckPasswordTextBox(out string password, bool isSave, bool isCopy)
{
Server server = new Server();
if (Uri.CheckHostName(server.server = IPTextBox.Text.Trim()) == UriHostNameType.Unknown)
password = null;
string outPassword;
if ((outPassword = PasswordTextBox.Text).IsNullOrWhiteSpace())
{
MessageBox.Show(I18N.GetString("Invalid server address"));
IPTextBox.Focus();
return null;
if (!isSave && !isCopy && ServersListBox.Items.Count > 1 && I18N.GetString("New server").Equals(ServersListBox.Items[_lastSelectedIndex].ToString()))
{
DialogResult result = MessageBox.Show(I18N.GetString("Whether to discard unconfigured servers"), I18N.GetString("Operation failure"), MessageBoxButtons.OKCancel);
if (result == DialogResult.OK)
return null;
}
else if (ApplyButton.Enabled && !isSave && !isCopy)
{
var result = MessageBox.Show(I18N.GetString("Password can not be blank, Cannot automatically save or discard changes"), I18N.GetString("Auto save failed"), MessageBoxButtons.OKCancel);
if (result == DialogResult.Cancel)
return false;
else
{
password = _modifiedConfiguration.configs[_lastSelectedIndex].password;
return true;
}
}
else
{
MessageBox.Show(I18N.GetString("Password can not be blank"), I18N.GetString("Operation failure"));
PasswordTextBox.Focus();
}
return false;
}
if (!int.TryParse(ServerPortTextBox.Text, out server.server_port))
else
{
MessageBox.Show(I18N.GetString("Illegal port number format"));
ServerPortTextBox.Focus();
return null;
password = outPassword;
}
server.password = PasswordTextBox.Text;
server.method = EncryptionSelect.Text;
server.plugin = PluginTextBox.Text;
server.plugin_opts = PluginOptionsTextBox.Text;
server.plugin_args = PluginArgumentsTextBox.Text;
server.remarks = RemarksTextBox.Text;
if (!int.TryParse(TimeoutTextBox.Text, out server.timeout))
return true;
}
private bool? CheckTimeoutTextBox(out int? timeout, bool isSave, bool isCopy)
{
timeout = null;
if (!int.TryParse(TimeoutTextBox.Text, out int outTimeout))
{
if (!isSave && !isCopy && ServersListBox.Items.Count > 1 && I18N.GetString("New server").Equals(ServersListBox.Items[_lastSelectedIndex].ToString()))
{
DialogResult result = MessageBox.Show(I18N.GetString("Whether to discard unconfigured servers"), I18N.GetString("Operation failure"), MessageBoxButtons.OKCancel);
if (result == DialogResult.OK)
return null;
}
else if (ApplyButton.Enabled && !isSave && !isCopy)
{
var result = MessageBox.Show(I18N.GetString("Illegal timeout format, Cannot automatically save or discard changes"), I18N.GetString("Auto save failed"), MessageBoxButtons.OKCancel);
if (result == DialogResult.Cancel)
return false;
else
{
timeout = _modifiedConfiguration.configs[_lastSelectedIndex].timeout;
return true;
}
}
else
{
MessageBox.Show(I18N.GetString("Illegal timeout format"), I18N.GetString("Operation failure"));
TimeoutTextBox.Focus();
}
return false;
}
else
{
MessageBox.Show(I18N.GetString("Illegal timeout format"));
TimeoutTextBox.Focus();
return null;
timeout = outTimeout;
}
return server;
return true;
}
#endregion
private void LoadSelectedServerDetails()
{
if (ServersListBox.SelectedIndex >= 0 && ServersListBox.SelectedIndex < _modifiedConfiguration.configs.Count)
@@ -168,6 +350,8 @@ namespace Shadowsocks.View
RemarksTextBox.Text = server.remarks;
TimeoutTextBox.Text = server.timeout.ToString();
ApplyButton.Enabled = false;
}
private void ShowHidePluginArgInput(bool show)
@@ -176,7 +360,6 @@ namespace Shadowsocks.View
PluginArgumentsLabel.Visible = show;
}
private void LoadServerNameListToUI(Configuration configuration)
{
ServersListBox.Items.Clear();
@@ -200,20 +383,17 @@ namespace Shadowsocks.View
ServersListBox.SelectedIndex = _lastSelectedIndex;
UpdateButtons();
LoadSelectedServerDetails();
ProxyPortTextBox.Text = _modifiedConfiguration.localPort.ToString();
PortableModeCheckBox.Checked = _modifiedConfiguration.portableMode;
ApplyButton.Enabled = false;
}
private bool SaveValidConfiguration()
{
if (!ValidateAndSaveSelectedServerDetails())
{
return false;
}
if (_modifiedConfiguration.configs.Count == 0)
if (!ValidateAndSaveSelectedServerDetails(isSave: true))
{
MessageBox.Show(I18N.GetString("Please add at least one server"));
return false;
}
@@ -269,81 +449,62 @@ namespace Shadowsocks.View
private void AddButton_Click(object sender, EventArgs e)
{
if (!ValidateAndSaveSelectedServerDetails())
if (ValidateAndSaveSelectedServerDetails(isSave: true))
{
return;
Configuration.AddDefaultServerOrServer(_modifiedConfiguration);
LoadServerNameListToUI(_modifiedConfiguration);
UpdateIndexToEnd();
}
Configuration.AddDefaultServerOrServer(_modifiedConfiguration);
LoadServerNameListToUI(_modifiedConfiguration);
ServersListBox.SelectedIndex = _modifiedConfiguration.configs.Count - 1;
_lastSelectedIndex = ServersListBox.SelectedIndex;
}
private void DuplicateButton_Click(object sender, EventArgs e)
{
if (_lastSelectedIndex == -1 || _lastSelectedIndex > _modifiedConfiguration.configs.Count
|| !ValidateAndSaveSelectedServerDetails())
if (ValidateAndSaveSelectedServerDetails(isCopy: true))
{
return;
Server currServer = _modifiedConfiguration.configs[_lastSelectedIndex];
Configuration.AddDefaultServerOrServer(_modifiedConfiguration, currServer);
LoadServerNameListToUI(_modifiedConfiguration);
UpdateIndexToEnd();
}
Server currServer = _modifiedConfiguration.configs[_lastSelectedIndex];
var currIndex = _modifiedConfiguration.configs.IndexOf(currServer);
_modifiedConfiguration.configs.Insert(currIndex + 1, currServer);
LoadServerNameListToUI(_modifiedConfiguration);
ServersListBox.SelectedIndex = currIndex + 1;
_lastSelectedIndex = ServersListBox.SelectedIndex;
}
private void DeleteButton_Click(object sender, EventArgs e)
{
_lastSelectedIndex = ServersListBox.SelectedIndex;
if (_lastSelectedIndex >= 0 && _lastSelectedIndex < _modifiedConfiguration.configs.Count)
{
_modifiedConfiguration.configs.RemoveAt(_lastSelectedIndex);
}
_modifiedConfiguration.configs.RemoveAt(_lastSelectedIndex);
if (_modifiedConfiguration.configs.Count == 0)
{
Configuration.AddDefaultServerOrServer(_modifiedConfiguration);
}
if (_lastSelectedIndex >= _modifiedConfiguration.configs.Count)
{
// can be -1
_lastSelectedIndex = _modifiedConfiguration.configs.Count - 1;
}
ServersListBox.SelectedIndex = _lastSelectedIndex;
LoadServerNameListToUI(_modifiedConfiguration);
ServersListBox.SelectedIndex = _lastSelectedIndex;
UpdateIndexToEnd();
LoadSelectedServerDetails();
UpdateButtons();
}
private void OKButton_Click(object sender, EventArgs e)
{
if (SaveValidConfiguration())
{
this.Close();
}
}
private void CancelButton_Click(object sender, EventArgs e)
{
this.Close();
}
private void ApplyButton_Click(object sender, EventArgs e)
private void UpdateButtons()
{
SaveValidConfiguration();
DeleteButton.Enabled = (ServersListBox.Items.Count > 0);
MoveUpButton.Enabled = (ServersListBox.SelectedIndex > 0);
MoveDownButton.Enabled = (ServersListBox.SelectedIndex < ServersListBox.Items.Count - 1);
}
private void ConfigForm_Shown(object sender, EventArgs e)
private void MoveUpButton_Click(object sender, EventArgs e)
{
IPTextBox.Focus();
if (ServersListBox.SelectedIndex > 0)
{
MoveConfigItem(-1); // -1 means move backward
}
}
private void ConfigForm_FormClosed(object sender, FormClosedEventArgs e)
private void MoveDownButton_Click(object sender, EventArgs e)
{
controller.ConfigChanged -= controller_ConfigChanged;
if (ServersListBox.SelectedIndex < ServersListBox.Items.Count - 1)
{
MoveConfigItem(+1); // +1 means move forward
}
}
private void MoveConfigItem(int step)
@@ -368,45 +529,42 @@ namespace Shadowsocks.View
UpdateButtons();
}
private void UpdateButtons()
private void OKButton_Click(object sender, EventArgs e)
{
DeleteButton.Enabled = (ServersListBox.Items.Count > 0);
MoveUpButton.Enabled = (ServersListBox.SelectedIndex > 0);
MoveDownButton.Enabled = (ServersListBox.SelectedIndex < ServersListBox.Items.Count - 1);
if (SaveValidConfiguration())
{
Close();
}
}
private void MoveUpButton_Click(object sender, EventArgs e)
private void CancelButton_Click(object sender, EventArgs e)
{
if (!ValidateAndSaveSelectedServerDetails())
{
return;
}
if (ServersListBox.SelectedIndex > 0)
{
MoveConfigItem(-1); // -1 means move backward
}
Close();
}
private void MoveDownButton_Click(object sender, EventArgs e)
private void ApplyButton_Click(object sender, EventArgs e)
{
if (!ValidateAndSaveSelectedServerDetails())
{
return;
}
if (ServersListBox.SelectedIndex < ServersListBox.Items.Count - 1)
{
MoveConfigItem(+1); // +1 means move forward
}
SaveValidConfiguration();
}
private void ConfigForm_Shown(object sender, EventArgs e)
{
IPTextBox.Focus();
}
private void ConfigForm_FormClosed(object sender, FormClosedEventArgs e)
{
controller.ConfigChanged -= Controller_ConfigChanged;
}
private void ShowPasswdCheckBox_CheckedChanged(object sender, EventArgs e)
{
this.PasswordTextBox.UseSystemPasswordChar = !this.ShowPasswdCheckBox.Checked;
PasswordTextBox.UseSystemPasswordChar = !ShowPasswdCheckBox.Checked;
}
private void UsePluginArgCheckBox_CheckedChanged(object sender, EventArgs e)
{
ShowHidePluginArgInput(this.NeedPluginArgCheckBox.Checked);
ShowHidePluginArgInput(NeedPluginArgCheckBox.Checked);
}
}
}

+ 8
- 5
shadowsocks-csharp/View/MenuViewController.cs View File

@@ -438,11 +438,14 @@ namespace Shadowsocks.View
Configuration configuration = controller.GetConfigurationCopy();
foreach (var server in configuration.configs)
{
MenuItem item = new MenuItem(server.FriendlyName());
item.Tag = i - strategyCount;
item.Click += AServerItem_Click;
items.Add(i, item);
i++;
if (Configuration.ChecksServer(server))
{
MenuItem item = new MenuItem(server.FriendlyName());
item.Tag = i - strategyCount;
item.Click += AServerItem_Click;
items.Add(i, item);
i++;
}
}
foreach (MenuItem item in items)


Loading…
Cancel
Save