diff --git a/shadowsocks-csharp/Controller/Service/OnlineConfigResolver.cs b/shadowsocks-csharp/Controller/Service/OnlineConfigResolver.cs new file mode 100644 index 00000000..ee48fdf5 --- /dev/null +++ b/shadowsocks-csharp/Controller/Service/OnlineConfigResolver.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Newtonsoft.Json.Linq; +using Shadowsocks.Model; + +namespace Shadowsocks.Controller.Service +{ + public class OnlineConfigResolver + { + public static async Task> GetOnline(string url, IWebProxy proxy = null) + { + var httpClientHandler = new HttpClientHandler() + { + Proxy = proxy + }; + var httpClient = new HttpClient(httpClientHandler) + { + Timeout = TimeSpan.FromSeconds(15) + }; + + string server_json = await httpClient.GetStringAsync(url); + + var servers = server_json.GetServers(); + + foreach (var server in servers) + { + server.group = url; + } + + return servers.ToList(); + } + } + + internal static class OnlineConfigResolverEx + { + private static readonly string[] BASIC_FORMAT = new[] { "server", "server_port", "password", "method" }; + + private static readonly IEnumerable EMPTY_SERVERS = Array.Empty(); + + internal static IEnumerable GetServers(this string json) => + JToken.Parse(json).SearchJToken().AsEnumerable(); + + private static IEnumerable SearchJArray(JArray array) => + array == null ? EMPTY_SERVERS : array.SelectMany(SearchJToken).ToList(); + + private static IEnumerable SearchJObject(JObject obj) + { + if (obj == null) + return EMPTY_SERVERS; + + if (BASIC_FORMAT.All(field => obj.ContainsKey(field))) + return new[] { obj.ToObject() }; + + var servers = new List(); + foreach (var kv in obj) + { + var token = kv.Value; + servers.AddRange(SearchJToken(token)); + } + return servers; + } + + private static IEnumerable SearchJToken(this JToken token) + { + switch (token.Type) + { + default: + return Array.Empty(); + case JTokenType.Object: + return SearchJObject(token as JObject); + case JTokenType.Array: + return SearchJArray(token as JArray); + } + } + } +} diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index a4e8e4ae..f602ef7a 100644 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -7,6 +7,7 @@ using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; +using System.Threading.Tasks; using System.Web; using System.Windows.Forms; using NLog; @@ -25,7 +26,7 @@ namespace Shadowsocks.Controller // handle user actions // manipulates UI // interacts with low level logic - + #region Member definition private Thread _trafficThread; private TCPListener _tcpListener; @@ -87,6 +88,7 @@ namespace Shadowsocks.Controller // Invoked when controller.Start(); public event EventHandler ProgramUpdated; + #endregion public ShadowsocksController() { @@ -102,6 +104,8 @@ namespace Shadowsocks.Controller }; } + #region Basic + public void Start(bool regHotkeys = true) { if (_config.updated && regHotkeys) @@ -121,6 +125,115 @@ namespace Shadowsocks.Controller } } + public void Stop() + { + if (stopped) + { + return; + } + stopped = true; + _tcpListener?.Stop(); + _udpListener?.Stop(); + StopPlugins(); + if (privoxyRunner != null) + { + privoxyRunner.Stop(); + } + if (_config.enabled) + { + SystemProxy.Update(_config, true, null); + } + } + + protected void Reload() + { + Encryption.RNG.Reload(); + // some logic in configuration updated the config when saving, we need to read it again + _config = Configuration.Load(); + + NLogConfig.LoadConfiguration(); + + StatisticsConfiguration = StatisticsStrategyConfiguration.Load(); + + privoxyRunner = privoxyRunner ?? new PrivoxyRunner(); + + _pacDaemon = _pacDaemon ?? new PACDaemon(_config); + _pacDaemon.PACFileChanged += PacDaemon_PACFileChanged; + _pacDaemon.UserRuleFileChanged += PacDaemon_UserRuleFileChanged; + _pacServer = _pacServer ?? new PACServer(_pacDaemon); + _pacServer.UpdatePACURL(_config); // So PACServer works when system proxy disabled. + + GeositeUpdater.ResetEvent(); + GeositeUpdater.UpdateCompleted += PacServer_PACUpdateCompleted; + GeositeUpdater.Error += PacServer_PACUpdateError; + + availabilityStatistics.UpdateConfiguration(this); + _tcpListener?.Stop(); + _udpListener?.Stop(); + StopPlugins(); + + // don't put PrivoxyRunner.Start() before pacServer.Stop() + // or bind will fail when switching bind address from 0.0.0.0 to 127.0.0.1 + // though UseShellExecute is set to true now + // http://stackoverflow.com/questions/10235093/socket-doesnt-close-after-application-exits-if-a-launched-process-is-open + privoxyRunner.Stop(); + try + { + var strategy = GetCurrentStrategy(); + strategy?.ReloadServers(); + + StartPlugin(); + privoxyRunner.Start(_config); + + TCPRelay tcpRelay = new TCPRelay(this, _config); + tcpRelay.OnConnected += UpdateLatency; + tcpRelay.OnInbound += UpdateInboundCounter; + tcpRelay.OnOutbound += UpdateOutboundCounter; + tcpRelay.OnFailed += (o, e) => GetCurrentStrategy()?.SetFailure(e.server); + + UDPRelay udpRelay = new UDPRelay(this); + _tcpListener = new TCPListener(_config, new List + { + tcpRelay, + _pacServer, + new PortForwarder(privoxyRunner.RunningPort), + }); + _tcpListener.Start(); + _udpListener = new UDPListener(_config, new List + { + udpRelay, + }); + _udpListener.Start(); + } + catch (Exception e) + { + // translate Microsoft language into human language + // i.e. An attempt was made to access a socket in a way forbidden by its access permissions => Port already in use + if (e is SocketException se) + { + if (se.SocketErrorCode == SocketError.AddressAlreadyInUse) + { + e = new Exception(I18N.GetString("Port {0} already in use", _config.localPort), e); + } + else if (se.SocketErrorCode == SocketError.AccessDenied) + { + e = new Exception(I18N.GetString("Port {0} is reserved by system", _config.localPort), e); + } + } + logger.LogUsefulException(e); + ReportError(e); + } + + ConfigChanged?.Invoke(this, new EventArgs()); + UpdateSystemProxy(); + } + + protected void SaveConfig(Configuration newConfig) + { + Configuration.Save(newConfig); + Reload(); + } + protected void ReportError(Exception e) { Errored?.Invoke(this, new ErrorEventArgs(e)); @@ -143,23 +256,6 @@ namespace Shadowsocks.Controller return _config; } - public IList GetStrategies() - { - return _strategyManager.GetStrategies(); - } - - public IStrategy GetCurrentStrategy() - { - foreach (var strategy in _strategyManager.GetStrategies()) - { - if (strategy.ID == _config.strategy) - { - return strategy; - } - } - return null; - } - public Server GetAServer(IStrategyCallerType type, IPEndPoint localIPEndPoint, EndPoint destEndPoint) { IStrategy strategy = GetCurrentStrategy(); @@ -174,32 +270,11 @@ namespace Shadowsocks.Controller return GetCurrentServer(); } - public EndPoint GetPluginLocalEndPointIfConfigured(Server server) + public void SelectServerIndex(int index) { - var plugin = _pluginsByServer.GetOrAdd( - server, - x => Sip003Plugin.CreateIfConfigured(x, _config.showPluginOutput)); - - if (plugin == null) - { - return null; - } - - try - { - if (plugin.StartIfNeeded()) - { - logger.Info( - $"Started SIP003 plugin for {server.Identifier()} on {plugin.LocalEndPoint} - PID: {plugin.ProcessId}"); - } - } - catch (Exception ex) - { - logger.Error("Failed to start SIP003 plugin: " + ex.Message); - throw; - } - - return plugin.LocalEndPoint; + _config.index = index; + _config.strategy = null; + SaveConfig(_config); } public void SaveServers(List servers, int localPort, bool portableMode) @@ -210,56 +285,17 @@ namespace Shadowsocks.Controller Configuration.Save(_config); } - public void SaveStrategyConfigurations(StatisticsStrategyConfiguration configuration) + public void ToggleShareOverLAN(bool enabled) { - StatisticsConfiguration = configuration; - StatisticsStrategyConfiguration.Save(configuration); - } + _config.shareOverLan = enabled; + SaveConfig(_config); - public bool AskAddServerBySSURL(string ssURL) - { - var dr = MessageBox.Show(I18N.GetString("Import from URL: {0} ?", ssURL), I18N.GetString("Shadowsocks"), MessageBoxButtons.YesNo); - if (dr == DialogResult.Yes) - { - if (AddServerBySSURL(ssURL)) - { - MessageBox.Show(I18N.GetString("Successfully imported from {0}", ssURL)); - return true; - } - else - { - MessageBox.Show(I18N.GetString("Failed to import. Please check if the link is valid.")); - } - } - return false; + ShareOverLANStatusChanged?.Invoke(this, new EventArgs()); } + #endregion - public bool AddServerBySSURL(string ssURL) - { - try - { - if (ssURL.IsNullOrEmpty() || ssURL.IsWhiteSpace()) - return false; - - var servers = Server.GetServers(ssURL); - if (servers == null || servers.Count == 0) - return false; - - foreach (var server in servers) - { - _config.configs.Add(server); - } - _config.index = _config.configs.Count - 1; - SaveConfig(_config); - return true; - } - catch (Exception e) - { - logger.LogUsefulException(e); - return false; - } - } + #region OS Proxy public void ToggleEnable(bool enabled) { @@ -277,78 +313,62 @@ namespace Shadowsocks.Controller EnableGlobalChanged?.Invoke(this, new EventArgs()); } - public void ToggleShareOverLAN(bool enabled) - { - _config.shareOverLan = enabled; - SaveConfig(_config); - - ShareOverLANStatusChanged?.Invoke(this, new EventArgs()); - } - public void SaveProxy(ProxyConfig proxyConfig) { _config.proxy = proxyConfig; SaveConfig(_config); } - public void ToggleVerboseLogging(bool enabled) + private void UpdateSystemProxy() { - _config.isVerboseLogging = enabled; - SaveConfig(_config); - NLogConfig.LoadConfiguration(); // reload nlog + SystemProxy.Update(_config, false, _pacServer); + } - VerboseLoggingStatusChanged?.Invoke(this, new EventArgs()); + #endregion + + #region PAC + + private void PacDaemon_PACFileChanged(object sender, EventArgs e) + { + UpdateSystemProxy(); } - public void ToggleShowPluginOutput(bool enabled) + private void PacServer_PACUpdateCompleted(object sender, GeositeResultEventArgs e) { - _config.showPluginOutput = enabled; - SaveConfig(_config); + UpdatePACFromGeositeCompleted?.Invoke(this, e); + } - ShowPluginOutputChanged?.Invoke(this, new EventArgs()); + private void PacServer_PACUpdateError(object sender, ErrorEventArgs e) + { + UpdatePACFromGeositeError?.Invoke(this, e); } - public void SelectServerIndex(int index) + private static readonly IEnumerable IgnoredLineBegins = new[] { '!', '[' }; + private void PacDaemon_UserRuleFileChanged(object sender, EventArgs e) { - _config.index = index; - _config.strategy = null; - SaveConfig(_config); + GeositeUpdater.MergeAndWritePACFile(_config.geositeGroup, _config.geositeBlacklistMode); + UpdateSystemProxy(); } - public void SelectStrategy(string strategyID) + public void CopyPacUrl() { - _config.index = -1; - _config.strategy = strategyID; - SaveConfig(_config); + Clipboard.SetDataObject(_pacServer.PacUrl); } - public void Stop() + public void SavePACUrl(string pacUrl) { - if (stopped) - { - return; - } - stopped = true; - _tcpListener?.Stop(); - _udpListener?.Stop(); - StopPlugins(); - if (privoxyRunner != null) - { - privoxyRunner.Stop(); - } - if (_config.enabled) - { - SystemProxy.Update(_config, true, null); - } + _config.pacUrl = pacUrl; + SaveConfig(_config); + + ConfigChanged?.Invoke(this, new EventArgs()); } - private void StopPlugins() + public void UseOnlinePAC(bool useOnlinePac) { - foreach (var serverAndPlugin in _pluginsByServer) - { - serverAndPlugin.Value?.Dispose(); - } - _pluginsByServer.Clear(); + _config.useOnlinePac = useOnlinePac; + SaveConfig(_config); + + ConfigChanged?.Invoke(this, new EventArgs()); } public void TouchPACFile() @@ -365,43 +385,78 @@ namespace Shadowsocks.Controller UserRuleFileReadyToOpen?.Invoke(this, new PathEventArgs() { Path = userRuleFilename }); } - public string GetServerURLForCurrentServer() + public void ToggleSecureLocalPac(bool enabled) { - return GetCurrentServer().GetURL(_config.generateLegacyUrl); + _config.secureLocalPac = enabled; + SaveConfig(_config); + + ConfigChanged?.Invoke(this, new EventArgs()); } - public void UpdateStatisticsConfiguration(bool enabled) + #endregion + + #region SIP002 + + public bool AskAddServerBySSURL(string ssURL) { - if (availabilityStatistics != null) + var dr = MessageBox.Show(I18N.GetString("Import from URL: {0} ?", ssURL), I18N.GetString("Shadowsocks"), MessageBoxButtons.YesNo); + if (dr == DialogResult.Yes) { - availabilityStatistics.UpdateConfiguration(this); - _config.availabilityStatistics = enabled; - SaveConfig(_config); + if (AddServerBySSURL(ssURL)) + { + MessageBox.Show(I18N.GetString("Successfully imported from {0}", ssURL)); + return true; + } + else + { + MessageBox.Show(I18N.GetString("Failed to import. Please check if the link is valid.")); + } } + return false; } - public void SavePACUrl(string pacUrl) + public bool AddServerBySSURL(string ssURL) { - _config.pacUrl = pacUrl; - SaveConfig(_config); + try + { + if (ssURL.IsNullOrEmpty() || ssURL.IsWhiteSpace()) + return false; - ConfigChanged?.Invoke(this, new EventArgs()); + var servers = Server.GetServers(ssURL); + if (servers == null || servers.Count == 0) + return false; + + foreach (var server in servers) + { + _config.configs.Add(server); + } + _config.index = _config.configs.Count - 1; + SaveConfig(_config); + return true; + } + catch (Exception e) + { + logger.LogUsefulException(e); + return false; + } } - public void UseOnlinePAC(bool useOnlinePac) + public string GetServerURLForCurrentServer() { - _config.useOnlinePac = useOnlinePac; - SaveConfig(_config); - - ConfigChanged?.Invoke(this, new EventArgs()); + return GetCurrentServer().GetURL(_config.generateLegacyUrl); } - public void ToggleSecureLocalPac(bool enabled) + #endregion + + #region Misc + + public void ToggleVerboseLogging(bool enabled) { - _config.secureLocalPac = enabled; + _config.isVerboseLogging = enabled; SaveConfig(_config); + NLogConfig.LoadConfiguration(); // reload nlog - ConfigChanged?.Invoke(this, new EventArgs()); + VerboseLoggingStatusChanged?.Invoke(this, new EventArgs()); } public void ToggleCheckingUpdate(bool enabled) @@ -436,6 +491,50 @@ namespace Shadowsocks.Controller ConfigChanged?.Invoke(this, new EventArgs()); } + #endregion + + #region Statistic + + public void SelectStrategy(string strategyID) + { + _config.index = -1; + _config.strategy = strategyID; + SaveConfig(_config); + } + + public void SaveStrategyConfigurations(StatisticsStrategyConfiguration configuration) + { + StatisticsConfiguration = configuration; + StatisticsStrategyConfiguration.Save(configuration); + } + + public IList GetStrategies() + { + return _strategyManager.GetStrategies(); + } + + public IStrategy GetCurrentStrategy() + { + foreach (var strategy in _strategyManager.GetStrategies()) + { + if (strategy.ID == _config.strategy) + { + return strategy; + } + } + return null; + } + + public void UpdateStatisticsConfiguration(bool enabled) + { + if (availabilityStatistics != null) + { + availabilityStatistics.UpdateConfiguration(this); + _config.availabilityStatistics = enabled; + SaveConfig(_config); + } + } + public void UpdateLatency(object sender, SSTCPConnectedEventArgs args) { GetCurrentStrategy()?.UpdateLatency(args.server, args.latency); @@ -465,88 +564,9 @@ namespace Shadowsocks.Controller } } - protected void Reload() - { - Encryption.RNG.Reload(); - // some logic in configuration updated the config when saving, we need to read it again - _config = Configuration.Load(); - - NLogConfig.LoadConfiguration(); - - StatisticsConfiguration = StatisticsStrategyConfiguration.Load(); - - privoxyRunner = privoxyRunner ?? new PrivoxyRunner(); - - _pacDaemon = _pacDaemon ?? new PACDaemon(_config); - _pacDaemon.PACFileChanged += PacDaemon_PACFileChanged; - _pacDaemon.UserRuleFileChanged += PacDaemon_UserRuleFileChanged; - _pacServer = _pacServer ?? new PACServer(_pacDaemon); - _pacServer.UpdatePACURL(_config); // So PACServer works when system proxy disabled. - - GeositeUpdater.ResetEvent(); - GeositeUpdater.UpdateCompleted += PacServer_PACUpdateCompleted; - GeositeUpdater.Error += PacServer_PACUpdateError; - - availabilityStatistics.UpdateConfiguration(this); - _tcpListener?.Stop(); - _udpListener?.Stop(); - StopPlugins(); - - // don't put PrivoxyRunner.Start() before pacServer.Stop() - // or bind will fail when switching bind address from 0.0.0.0 to 127.0.0.1 - // though UseShellExecute is set to true now - // http://stackoverflow.com/questions/10235093/socket-doesnt-close-after-application-exits-if-a-launched-process-is-open - privoxyRunner.Stop(); - try - { - var strategy = GetCurrentStrategy(); - strategy?.ReloadServers(); - - StartPlugin(); - privoxyRunner.Start(_config); - - TCPRelay tcpRelay = new TCPRelay(this, _config); - tcpRelay.OnConnected += UpdateLatency; - tcpRelay.OnInbound += UpdateInboundCounter; - tcpRelay.OnOutbound += UpdateOutboundCounter; - tcpRelay.OnFailed += (o, e) => GetCurrentStrategy()?.SetFailure(e.server); - - UDPRelay udpRelay = new UDPRelay(this); - _tcpListener = new TCPListener(_config, new List - { - tcpRelay, - _pacServer, - new PortForwarder(privoxyRunner.RunningPort), - }); - _tcpListener.Start(); - _udpListener = new UDPListener(_config, new List - { - udpRelay, - }); - _udpListener.Start(); - } - catch (Exception e) - { - // translate Microsoft language into human language - // i.e. An attempt was made to access a socket in a way forbidden by its access permissions => Port already in use - if (e is SocketException se) - { - if (se.SocketErrorCode == SocketError.AddressAlreadyInUse) - { - e = new Exception(I18N.GetString("Port {0} already in use", _config.localPort), e); - } - else if (se.SocketErrorCode == SocketError.AccessDenied) - { - e = new Exception(I18N.GetString("Port {0} is reserved by system", _config.localPort), e); - } - } - logger.LogUsefulException(e); - ReportError(e); - } + #endregion - ConfigChanged?.Invoke(this, new EventArgs()); - UpdateSystemProxy(); - } + #region SIP003 private void StartPlugin() { @@ -554,44 +574,53 @@ namespace Shadowsocks.Controller GetPluginLocalEndPointIfConfigured(server); } - protected void SaveConfig(Configuration newConfig) + private void StopPlugins() { - Configuration.Save(newConfig); - Reload(); + foreach (var serverAndPlugin in _pluginsByServer) + { + serverAndPlugin.Value?.Dispose(); + } + _pluginsByServer.Clear(); } - private void UpdateSystemProxy() + public EndPoint GetPluginLocalEndPointIfConfigured(Server server) { - SystemProxy.Update(_config, false, _pacServer); - } + var plugin = _pluginsByServer.GetOrAdd( + server, + x => Sip003Plugin.CreateIfConfigured(x, _config.showPluginOutput)); - private void PacDaemon_PACFileChanged(object sender, EventArgs e) - { - UpdateSystemProxy(); - } + if (plugin == null) + { + return null; + } - private void PacServer_PACUpdateCompleted(object sender, GeositeResultEventArgs e) - { - UpdatePACFromGeositeCompleted?.Invoke(this, e); - } + try + { + if (plugin.StartIfNeeded()) + { + logger.Info( + $"Started SIP003 plugin for {server.Identifier()} on {plugin.LocalEndPoint} - PID: {plugin.ProcessId}"); + } + } + catch (Exception ex) + { + logger.Error("Failed to start SIP003 plugin: " + ex.Message); + throw; + } - private void PacServer_PACUpdateError(object sender, ErrorEventArgs e) - { - UpdatePACFromGeositeError?.Invoke(this, e); + return plugin.LocalEndPoint; } - private static readonly IEnumerable IgnoredLineBegins = new[] { '!', '[' }; - private void PacDaemon_UserRuleFileChanged(object sender, EventArgs e) + public void ToggleShowPluginOutput(bool enabled) { - GeositeUpdater.MergeAndWritePACFile(_config.geositeGroup, _config.geositeBlacklistMode); - UpdateSystemProxy(); - } + _config.showPluginOutput = enabled; + SaveConfig(_config); - public void CopyPacUrl() - { - Clipboard.SetDataObject(_pacServer.PacUrl); + ShowPluginOutputChanged?.Invoke(this, new EventArgs()); } + #endregion + #region Traffic Statistics private void StartTrafficStatistics(int queueMaxSize) @@ -634,5 +663,75 @@ namespace Shadowsocks.Controller #endregion + #region SIP008 + + + public async Task UpdateOnlineConfigInternal(string url) + { + var onlineServer = await OnlineConfigResolver.GetOnline(url, _config.WebProxy); + _config.configs = Configuration.SortByOnlineConfig( + _config.configs + .Where(c => c.group != url) + .Concat(onlineServer) + ); + logger.Info($"updated {onlineServer.Count} server from {url}"); + return onlineServer.Count; + } + + public async Task UpdateOnlineConfig(string url) + { + var selected = GetCurrentServer(); + try + { + int count = await UpdateOnlineConfigInternal(url); + } + catch (Exception e) + { + logger.LogUsefulException(e); + return false; + } + _config.index = _config.configs.IndexOf(selected); + SaveConfig(_config); + return true; + } + + public async Task UpdateAllOnlineConfig() + { + var selected = GetCurrentServer(); + int failCount = 0; + foreach (var url in _config.onlineConfigSource) + { + try + { + await UpdateOnlineConfigInternal(url); + } + catch (Exception e) + { + logger.LogUsefulException(e); + failCount++; + } + } + + _config.index = _config.configs.IndexOf(selected); + SaveConfig(_config); + return failCount; + } + + public void SaveOnlineConfigSource(IEnumerable vs) + { + _config.onlineConfigSource = vs.ToList(); + SaveConfig(_config); + } + + public void RemoveOnlineConfig(string url) + { + _config.onlineConfigSource.RemoveAll(v => v == url); + _config.configs = Configuration.SortByOnlineConfig( + _config.configs.Where(c => c.group != url) + ); + SaveConfig(_config); + } + + #endregion } } diff --git a/shadowsocks-csharp/Data/i18n.csv b/shadowsocks-csharp/Data/i18n.csv index 6b345149..bc9c1f95 100644 --- a/shadowsocks-csharp/Data/i18n.csv +++ b/shadowsocks-csharp/Data/i18n.csv @@ -17,6 +17,7 @@ Global,Для всей системы,全局模式,全局模式,グローバル Servers,Серверы,服务器,伺服器,サーバー,서버,Serveurs Edit Servers...,Редактировать серверы…,编辑服务器...,編輯伺服器...,サーバーの編集...,서버 수정…,Éditer serveurs… Statistics Config...,Настройки статистики…,统计配置...,統計設定檔...,統計情報の設定...,통계 설정,Configuration des statistiques… +Online Config...,,在线配置...,線上配置...,,, Start on Boot,Автозагрузка,开机启动,開機啟動,システム起動時に実行,시스템 시작 시에 시작하기,Démarrage automatique Associate ss:// Links,Ассоциированный ss:// Ссылки,关联 ss:// 链接,關聯 ss:// 鏈接,ss:// リンクの関連付け,ss:// 링크 연결, Forward Proxy...,Прямой прокси…,正向代理设置...,正向 Proxy 設定...,フォワードプロキシの設定...,포워드 프록시,Forward-proxy… @@ -79,6 +80,13 @@ Move D&own,Ниже,下移(&O),下移 (&O),下に移動 (&O),아래로 (&O),Desc deprecated,Устаревшее,不推荐,不推薦,非推奨,더 이상 사용되지 않음,Obsolète "Encryption method {0} not exist, will replace with {1}",,加密方法{0}不存在,将使用{1}代替,,暗号化方式{0}が存在しません,{1}に置換します,{0} 암호화 방식이 존재하지 않으므로 {1}로 대체될 것입니다.,"Méthode de chiffrement {0} n'existe pas, sera remplacée par {1}" ,,,,,, +# Online Config Form,,,,,, +,,,,,, +Online config,,在线配置,線上配置,,, +Online config URL,,在线配置链接,線上配置鏈接,,, +&Update,,更新,更新,,, +U&pdate All,,全部更新,全部更新,,, +,,,,,, #Statistics Config,,,,,, ,,,,,, Enable Statistics,Включить сбор статистики,启用统计,,統計を有効にする,통계 활성화,Activer statistiques diff --git a/shadowsocks-csharp/Model/Configuration.cs b/shadowsocks-csharp/Model/Configuration.cs index f712653e..60df5410 100644 --- a/shadowsocks-csharp/Model/Configuration.cs +++ b/shadowsocks-csharp/Model/Configuration.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; +using System.Net; using Newtonsoft.Json; using NLog; using Shadowsocks.Controller; @@ -17,6 +19,8 @@ namespace Shadowsocks.Model public List configs; + public List onlineConfigSource; + // when strategy is set, index is ignored public string strategy; public int index; @@ -25,30 +29,69 @@ namespace Shadowsocks.Model public bool shareOverLan; public bool isDefault; public int localPort; - public bool portableMode = true; + public bool portableMode; public bool showPluginOutput; public string pacUrl; public bool useOnlinePac; - public bool secureLocalPac = true; + public bool secureLocalPac; public bool availabilityStatistics; public bool autoCheckUpdate; public bool checkPreRelease; public bool isVerboseLogging; // hidden options - public bool isIPv6Enabled = false; // for experimental ipv6 support + public bool isIPv6Enabled; // for experimental ipv6 support public bool generateLegacyUrl = false; // for pre-sip002 url compatibility public string geositeUrl; // for custom geosite source (and rule group) - public string geositeGroup = "geolocation-!cn"; - public bool geositeBlacklistMode = true; - + public string geositeGroup; + public bool geositeBlacklistMode; //public NLogConfig.LogLevel logLevel; public LogViewerConfig logViewer; public ProxyConfig proxy; public HotkeyConfig hotkey; + [JsonIgnore] + public bool updated; + + public Configuration() + { + version = UpdateChecker.Version; + strategy = ""; + index = 0; + global = false; + enabled = false; + shareOverLan = false; + isDefault = true; + localPort = 1080; + portableMode = true; + showPluginOutput = false; + pacUrl = ""; + useOnlinePac = false; + secureLocalPac = true; + availabilityStatistics = false; + autoCheckUpdate = false; + checkPreRelease = false; + isVerboseLogging = false; + + // hidden options + isIPv6Enabled = false; + generateLegacyUrl = false; + geositeUrl = ""; + geositeGroup = "geolocation-!cn"; + geositeBlacklistMode = true; + + logViewer = new LogViewerConfig(); + proxy = new ProxyConfig(); + hotkey = new HotkeyConfig(); + + updated = false; + + configs = new List(); + onlineConfigSource = new List(); + } + [JsonIgnore] NLogConfig nLogConfig; @@ -59,10 +102,6 @@ namespace Shadowsocks.Model private static readonly NLogConfig.LogLevel verboseLogLevel = NLogConfig.LogLevel.Debug; #endif - - [JsonIgnore] - public bool updated = false; - [JsonIgnore] public string localHost => GetLocalHost(); private string GetLocalHost() @@ -77,6 +116,14 @@ namespace Shadowsocks.Model return GetDefaultServer(); } + public WebProxy WebProxy => enabled + ? new WebProxy( + isIPv6Enabled + ? $"[{IPAddress.IPv6Loopback}]" + : IPAddress.Loopback.ToString(), + localPort) + : null; + public static void CheckServer(Server server) { CheckServer(server.server); @@ -111,20 +158,10 @@ namespace Shadowsocks.Model config.updated = true; } - if (config.configs == null) - config.configs = new List(); if (config.configs.Count == 0) config.configs.Add(GetDefaultServer()); - if (config.localPort == 0) - config.localPort = 1080; - if (config.index == -1 && config.strategy == null) + if (config.index == -1 && string.IsNullOrEmpty(config.strategy)) config.index = 0; - if (config.logViewer == null) - config.logViewer = new LogViewerConfig(); - if (config.proxy == null) - config.proxy = new ProxyConfig(); - if (config.hotkey == null) - config.hotkey = new HotkeyConfig(); if (!System.Net.Sockets.Socket.OSSupportsIPv6) { config.isIPv6Enabled = false; // disable IPv6 if os not support @@ -137,20 +174,8 @@ namespace Shadowsocks.Model { if (!(e is FileNotFoundException)) logger.LogUsefulException(e); - config = new Configuration - { - index = 0, - isDefault = true, - localPort = 1080, - autoCheckUpdate = true, - configs = new List() - { - GetDefaultServer() - }, - logViewer = new LogViewerConfig(), - proxy = new ProxyConfig(), - hotkey = new HotkeyConfig(), - }; + config = new Configuration(); + config.configs.Add(GetDefaultServer()); } try @@ -181,12 +206,12 @@ namespace Shadowsocks.Model public static void Save(Configuration config) { - config.version = UpdateChecker.Version; + config.configs = SortByOnlineConfig(config.configs); if (config.index >= config.configs.Count) config.index = config.configs.Count - 1; if (config.index < -1) config.index = -1; - if (config.index == -1 && config.strategy == null) + if (config.index == -1 && string.IsNullOrEmpty(config.strategy)) config.index = 0; config.isDefault = false; try @@ -214,6 +239,15 @@ namespace Shadowsocks.Model } } + public static List SortByOnlineConfig(IEnumerable servers) + { + var groups = servers.GroupBy(s => s.group); + List ret = new List(); + ret.AddRange(groups.Where(g => string.IsNullOrEmpty(g.Key)).SelectMany(g => g)); + ret.AddRange(groups.Where(g => !string.IsNullOrEmpty(g.Key)).SelectMany(g => g)); + return ret; + } + public static Server AddDefaultServerOrServer(Configuration config, Server server = null, int? index = null) { if (config?.configs != null) diff --git a/shadowsocks-csharp/Model/Server.cs b/shadowsocks-csharp/Model/Server.cs index 8471c837..32a98c36 100755 --- a/shadowsocks-csharp/Model/Server.cs +++ b/shadowsocks-csharp/Model/Server.cs @@ -44,6 +44,10 @@ namespace Shadowsocks.Model [JsonProperty(NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public string remarks; + [DefaultValue("")] + [JsonProperty(NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] + public string group; + public int timeout; public override int GetHashCode() diff --git a/shadowsocks-csharp/Program.cs b/shadowsocks-csharp/Program.cs index 4538cd40..52dac1cc 100755 --- a/shadowsocks-csharp/Program.cs +++ b/shadowsocks-csharp/Program.cs @@ -101,7 +101,14 @@ namespace Shadowsocks HotKeys.Init(MainController); MainController.Start(); - #region IPC Handler and Arguement Process + // Update online config + Task.Run(async () => + { + await Task.Delay(10 * 1000); + await MainController.UpdateAllOnlineConfig(); + }); + +#region IPC Handler and Arguement Process IPCService ipcService = new IPCService(); Task.Run(() => ipcService.RunServer()); ipcService.OpenUrlRequested += (_1, e) => MainController.AskAddServerBySSURL(e.Url); @@ -110,7 +117,7 @@ namespace Shadowsocks { MainController.AskAddServerBySSURL(Options.OpenUrl); } - #endregion +#endregion Application.Run(); diff --git a/shadowsocks-csharp/View/ConfigForm.Designer.cs b/shadowsocks-csharp/View/ConfigForm.Designer.cs index 3651a33c..3d5794a7 100755 --- a/shadowsocks-csharp/View/ConfigForm.Designer.cs +++ b/shadowsocks-csharp/View/ConfigForm.Designer.cs @@ -58,25 +58,19 @@ this.AddButton = new System.Windows.Forms.Button(); this.ServerGroupBox = new System.Windows.Forms.GroupBox(); this.ServersListBox = new System.Windows.Forms.ListBox(); - this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); - this.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(); this.PortableModeCheckBox = new System.Windows.Forms.CheckBox(); - this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); - this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel(); this.DuplicateButton = new System.Windows.Forms.Button(); this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); + this.tableLayoutPanel7 = new System.Windows.Forms.TableLayoutPanel(); + this.GroupLabel = new System.Windows.Forms.Label(); + this.GroupTextBox = new System.Windows.Forms.TextBox(); this.tableLayoutPanel1.SuspendLayout(); this.ServerGroupBox.SuspendLayout(); - this.tableLayoutPanel2.SuspendLayout(); - this.tableLayoutPanel6.SuspendLayout(); - this.tableLayoutPanel5.SuspendLayout(); - this.tableLayoutPanel3.SuspendLayout(); - this.tableLayoutPanel4.SuspendLayout(); + this.tableLayoutPanel7.SuspendLayout(); this.SuspendLayout(); // // tableLayoutPanel1 @@ -85,7 +79,7 @@ this.tableLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.tableLayoutPanel1.ColumnCount = 2; this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.tableLayoutPanel1.Controls.Add(this.PluginOptionsLabel, 0, 6); this.tableLayoutPanel1.Controls.Add(this.PluginTextBox, 1, 5); this.tableLayoutPanel1.Controls.Add(this.RemarksTextBox, 1, 10); @@ -104,13 +98,16 @@ this.tableLayoutPanel1.Controls.Add(this.ShowPasswdCheckBox, 1, 3); this.tableLayoutPanel1.Controls.Add(this.PluginArgumentsTextBox, 1, 8); this.tableLayoutPanel1.Controls.Add(this.PluginArgumentsLabel, 0, 8); - this.tableLayoutPanel1.Controls.Add(this.RemarksLabel, 0, 10); this.tableLayoutPanel1.Controls.Add(this.NeedPluginArgCheckBox, 1, 7); - this.tableLayoutPanel1.Location = new System.Drawing.Point(10, 26); + this.tableLayoutPanel1.Controls.Add(this.GroupTextBox, 1, 12); + this.tableLayoutPanel1.Controls.Add(this.GroupLabel, 0, 12); + this.tableLayoutPanel1.Controls.Add(this.RemarksLabel, 0, 10); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(4, 22); this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(4); - this.tableLayoutPanel1.RowCount = 12; + this.tableLayoutPanel1.RowCount = 14; this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); @@ -123,14 +120,16 @@ this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel1.Size = new System.Drawing.Size(394, 357); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(362, 399); this.tableLayoutPanel1.TabIndex = 0; // // PluginOptionsLabel // this.PluginOptionsLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.PluginOptionsLabel.AutoSize = true; - this.PluginOptionsLabel.Location = new System.Drawing.Point(24, 203); + this.PluginOptionsLabel.Location = new System.Drawing.Point(24, 199); this.PluginOptionsLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.PluginOptionsLabel.Name = "PluginOptionsLabel"; this.PluginOptionsLabel.Size = new System.Drawing.Size(119, 15); @@ -140,23 +139,21 @@ // // PluginTextBox // - this.PluginTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.PluginTextBox.Location = new System.Drawing.Point(151, 165); - this.PluginTextBox.Margin = new System.Windows.Forms.Padding(4); + this.PluginTextBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.PluginTextBox.Location = new System.Drawing.Point(150, 163); this.PluginTextBox.MaxLength = 256; this.PluginTextBox.Name = "PluginTextBox"; - this.PluginTextBox.Size = new System.Drawing.Size(235, 25); + this.PluginTextBox.Size = new System.Drawing.Size(205, 25); this.PluginTextBox.TabIndex = 5; this.PluginTextBox.WordWrap = false; // // RemarksTextBox // - this.RemarksTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.RemarksTextBox.Location = new System.Drawing.Point(151, 291); - this.RemarksTextBox.Margin = new System.Windows.Forms.Padding(4); + this.RemarksTextBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.RemarksTextBox.Location = new System.Drawing.Point(150, 283); this.RemarksTextBox.MaxLength = 32; this.RemarksTextBox.Name = "RemarksTextBox"; - this.RemarksTextBox.Size = new System.Drawing.Size(235, 25); + this.RemarksTextBox.Size = new System.Drawing.Size(205, 25); this.RemarksTextBox.TabIndex = 8; this.RemarksTextBox.WordWrap = false; // @@ -164,7 +161,7 @@ // this.IPLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.IPLabel.AutoSize = true; - this.IPLabel.Location = new System.Drawing.Point(64, 13); + this.IPLabel.Location = new System.Drawing.Point(64, 12); this.IPLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.IPLabel.Name = "IPLabel"; this.IPLabel.Size = new System.Drawing.Size(79, 15); @@ -175,7 +172,7 @@ // this.ServerPortLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.ServerPortLabel.AutoSize = true; - this.ServerPortLabel.Location = new System.Drawing.Point(48, 46); + this.ServerPortLabel.Location = new System.Drawing.Point(48, 43); this.ServerPortLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.ServerPortLabel.Name = "ServerPortLabel"; this.ServerPortLabel.Size = new System.Drawing.Size(95, 15); @@ -186,7 +183,7 @@ // this.PasswordLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.PasswordLabel.AutoSize = true; - this.PasswordLabel.Location = new System.Drawing.Point(72, 79); + this.PasswordLabel.Location = new System.Drawing.Point(72, 74); this.PasswordLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.PasswordLabel.Name = "PasswordLabel"; this.PasswordLabel.Size = new System.Drawing.Size(71, 15); @@ -196,35 +193,32 @@ // // IPTextBox // - this.IPTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.IPTextBox.Location = new System.Drawing.Point(151, 8); - this.IPTextBox.Margin = new System.Windows.Forms.Padding(4); + this.IPTextBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.IPTextBox.Location = new System.Drawing.Point(150, 7); this.IPTextBox.MaxLength = 512; this.IPTextBox.Name = "IPTextBox"; - this.IPTextBox.Size = new System.Drawing.Size(235, 25); + this.IPTextBox.Size = new System.Drawing.Size(205, 25); this.IPTextBox.TabIndex = 0; this.IPTextBox.WordWrap = false; // // ServerPortTextBox // - this.ServerPortTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.ServerPortTextBox.Location = new System.Drawing.Point(151, 41); - this.ServerPortTextBox.Margin = new System.Windows.Forms.Padding(4); + this.ServerPortTextBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.ServerPortTextBox.Location = new System.Drawing.Point(150, 38); this.ServerPortTextBox.MaxLength = 10; this.ServerPortTextBox.Name = "ServerPortTextBox"; - this.ServerPortTextBox.Size = new System.Drawing.Size(235, 25); + this.ServerPortTextBox.Size = new System.Drawing.Size(205, 25); this.ServerPortTextBox.TabIndex = 1; this.ServerPortTextBox.WordWrap = false; // // PasswordTextBox // - this.PasswordTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.PasswordTextBox.Dock = System.Windows.Forms.DockStyle.Fill; this.PasswordTextBox.Font = new System.Drawing.Font("Consolas", 9F); - this.PasswordTextBox.Location = new System.Drawing.Point(151, 74); - this.PasswordTextBox.Margin = new System.Windows.Forms.Padding(4); + this.PasswordTextBox.Location = new System.Drawing.Point(150, 69); this.PasswordTextBox.MaxLength = 256; this.PasswordTextBox.Name = "PasswordTextBox"; - this.PasswordTextBox.Size = new System.Drawing.Size(235, 25); + this.PasswordTextBox.Size = new System.Drawing.Size(205, 25); this.PasswordTextBox.TabIndex = 2; this.PasswordTextBox.UseSystemPasswordChar = true; this.PasswordTextBox.WordWrap = false; @@ -233,7 +227,7 @@ // this.EncryptionLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.EncryptionLabel.AutoSize = true; - this.EncryptionLabel.Location = new System.Drawing.Point(56, 138); + this.EncryptionLabel.Location = new System.Drawing.Point(56, 134); this.EncryptionLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.EncryptionLabel.Name = "EncryptionLabel"; this.EncryptionLabel.Size = new System.Drawing.Size(87, 15); @@ -242,23 +236,22 @@ // // EncryptionSelect // - this.EncryptionSelect.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); + this.EncryptionSelect.Dock = System.Windows.Forms.DockStyle.Fill; this.EncryptionSelect.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.EncryptionSelect.FormattingEnabled = true; this.EncryptionSelect.ImeMode = System.Windows.Forms.ImeMode.NoControl; this.EncryptionSelect.ItemHeight = 15; - this.EncryptionSelect.Location = new System.Drawing.Point(151, 134); - this.EncryptionSelect.Margin = new System.Windows.Forms.Padding(4); + this.EncryptionSelect.Location = new System.Drawing.Point(150, 129); + this.EncryptionSelect.Margin = new System.Windows.Forms.Padding(3, 5, 3, 8); this.EncryptionSelect.Name = "EncryptionSelect"; - this.EncryptionSelect.Size = new System.Drawing.Size(235, 23); + this.EncryptionSelect.Size = new System.Drawing.Size(205, 23); this.EncryptionSelect.TabIndex = 4; // // TimeoutLabel // this.TimeoutLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.TimeoutLabel.AutoSize = true; - this.TimeoutLabel.Location = new System.Drawing.Point(40, 329); + this.TimeoutLabel.Location = new System.Drawing.Point(40, 319); this.TimeoutLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.TimeoutLabel.Name = "TimeoutLabel"; this.TimeoutLabel.RightToLeft = System.Windows.Forms.RightToLeft.No; @@ -268,19 +261,18 @@ // // TimeoutTextBox // - this.TimeoutTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.TimeoutTextBox.Location = new System.Drawing.Point(151, 324); - this.TimeoutTextBox.Margin = new System.Windows.Forms.Padding(4); + this.TimeoutTextBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.TimeoutTextBox.Location = new System.Drawing.Point(150, 314); this.TimeoutTextBox.MaxLength = 5; this.TimeoutTextBox.Name = "TimeoutTextBox"; - this.TimeoutTextBox.Size = new System.Drawing.Size(235, 25); + this.TimeoutTextBox.Size = new System.Drawing.Size(205, 25); this.TimeoutTextBox.TabIndex = 9; // // PluginLabel // this.PluginLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.PluginLabel.AutoSize = true; - this.PluginLabel.Location = new System.Drawing.Point(24, 170); + this.PluginLabel.Location = new System.Drawing.Point(24, 168); this.PluginLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.PluginLabel.Name = "PluginLabel"; this.PluginLabel.Size = new System.Drawing.Size(119, 15); @@ -289,12 +281,11 @@ // // PluginOptionsTextBox // - this.PluginOptionsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.PluginOptionsTextBox.Location = new System.Drawing.Point(151, 198); - this.PluginOptionsTextBox.Margin = new System.Windows.Forms.Padding(4); + this.PluginOptionsTextBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.PluginOptionsTextBox.Location = new System.Drawing.Point(150, 194); this.PluginOptionsTextBox.MaxLength = 256; this.PluginOptionsTextBox.Name = "PluginOptionsTextBox"; - this.PluginOptionsTextBox.Size = new System.Drawing.Size(235, 25); + this.PluginOptionsTextBox.Size = new System.Drawing.Size(205, 25); this.PluginOptionsTextBox.TabIndex = 6; this.PluginOptionsTextBox.WordWrap = false; // @@ -303,7 +294,7 @@ this.ShowPasswdCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left))); this.ShowPasswdCheckBox.AutoSize = true; - this.ShowPasswdCheckBox.Location = new System.Drawing.Point(151, 107); + this.ShowPasswdCheckBox.Location = new System.Drawing.Point(151, 101); this.ShowPasswdCheckBox.Margin = new System.Windows.Forms.Padding(4); this.ShowPasswdCheckBox.Name = "ShowPasswdCheckBox"; this.ShowPasswdCheckBox.Size = new System.Drawing.Size(133, 19); @@ -315,12 +306,11 @@ // // PluginArgumentsTextBox // - this.PluginArgumentsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.PluginArgumentsTextBox.Location = new System.Drawing.Point(151, 258); - this.PluginArgumentsTextBox.Margin = new System.Windows.Forms.Padding(4); + this.PluginArgumentsTextBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.PluginArgumentsTextBox.Location = new System.Drawing.Point(150, 252); this.PluginArgumentsTextBox.MaxLength = 512; this.PluginArgumentsTextBox.Name = "PluginArgumentsTextBox"; - this.PluginArgumentsTextBox.Size = new System.Drawing.Size(235, 25); + this.PluginArgumentsTextBox.Size = new System.Drawing.Size(205, 25); this.PluginArgumentsTextBox.TabIndex = 7; this.PluginArgumentsTextBox.WordWrap = false; // @@ -328,7 +318,7 @@ // this.PluginArgumentsLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.PluginArgumentsLabel.AutoSize = true; - this.PluginArgumentsLabel.Location = new System.Drawing.Point(8, 263); + this.PluginArgumentsLabel.Location = new System.Drawing.Point(8, 257); this.PluginArgumentsLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.PluginArgumentsLabel.Name = "PluginArgumentsLabel"; this.PluginArgumentsLabel.Size = new System.Drawing.Size(135, 15); @@ -341,7 +331,7 @@ // this.RemarksLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.RemarksLabel.AutoSize = true; - this.RemarksLabel.Location = new System.Drawing.Point(80, 296); + this.RemarksLabel.Location = new System.Drawing.Point(80, 288); this.RemarksLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.RemarksLabel.Name = "RemarksLabel"; this.RemarksLabel.Size = new System.Drawing.Size(63, 15); @@ -351,7 +341,7 @@ // NeedPluginArgCheckBox // this.NeedPluginArgCheckBox.AutoSize = true; - this.NeedPluginArgCheckBox.Location = new System.Drawing.Point(151, 231); + this.NeedPluginArgCheckBox.Location = new System.Drawing.Point(151, 226); this.NeedPluginArgCheckBox.Margin = new System.Windows.Forms.Padding(4); this.NeedPluginArgCheckBox.Name = "NeedPluginArgCheckBox"; this.NeedPluginArgCheckBox.Size = new System.Drawing.Size(189, 19); @@ -365,7 +355,7 @@ this.panel2.Anchor = System.Windows.Forms.AnchorStyles.Top; this.panel2.AutoSize = true; this.panel2.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.panel2.Location = new System.Drawing.Point(206, 234); + this.panel2.Location = new System.Drawing.Point(190, 229); this.panel2.Margin = new System.Windows.Forms.Padding(4); this.panel2.Name = "panel2"; this.panel2.Size = new System.Drawing.Size(0, 0); @@ -374,11 +364,10 @@ // OKButton // this.OKButton.DialogResult = System.Windows.Forms.DialogResult.OK; - this.OKButton.Dock = System.Windows.Forms.DockStyle.Right; - this.OKButton.Location = new System.Drawing.Point(4, 4); - this.OKButton.Margin = new System.Windows.Forms.Padding(4, 4, 4, 0); + this.OKButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.OKButton.Location = new System.Drawing.Point(282, 501); this.OKButton.Name = "OKButton"; - this.OKButton.Size = new System.Drawing.Size(94, 29); + this.OKButton.Size = new System.Drawing.Size(87, 29); this.OKButton.TabIndex = 17; this.OKButton.Text = "OK"; this.OKButton.UseVisualStyleBackColor = true; @@ -387,11 +376,10 @@ // MyCancelButton // this.MyCancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.MyCancelButton.Dock = System.Windows.Forms.DockStyle.Right; - this.MyCancelButton.Location = new System.Drawing.Point(106, 4); - this.MyCancelButton.Margin = new System.Windows.Forms.Padding(4, 4, 4, 0); + this.MyCancelButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.MyCancelButton.Location = new System.Drawing.Point(375, 501); this.MyCancelButton.Name = "MyCancelButton"; - this.MyCancelButton.Size = new System.Drawing.Size(94, 29); + this.MyCancelButton.Size = new System.Drawing.Size(87, 29); this.MyCancelButton.TabIndex = 18; this.MyCancelButton.Text = "Cancel"; this.MyCancelButton.UseVisualStyleBackColor = true; @@ -399,12 +387,11 @@ // // ApplyButton // - this.ApplyButton.Dock = System.Windows.Forms.DockStyle.Right; + this.ApplyButton.Dock = System.Windows.Forms.DockStyle.Fill; this.ApplyButton.Enabled = false; - this.ApplyButton.Location = new System.Drawing.Point(208, 4); - this.ApplyButton.Margin = new System.Windows.Forms.Padding(4, 4, 0, 0); + this.ApplyButton.Location = new System.Drawing.Point(468, 501); this.ApplyButton.Name = "ApplyButton"; - this.ApplyButton.Size = new System.Drawing.Size(94, 29); + this.ApplyButton.Size = new System.Drawing.Size(91, 29); this.ApplyButton.TabIndex = 19; this.ApplyButton.Text = "Apply"; this.ApplyButton.UseVisualStyleBackColor = true; @@ -412,11 +399,10 @@ // // DeleteButton // - this.DeleteButton.Dock = System.Windows.Forms.DockStyle.Right; - this.DeleteButton.Location = new System.Drawing.Point(108, 8); - this.DeleteButton.Margin = new System.Windows.Forms.Padding(4, 8, 0, 4); + this.DeleteButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.DeleteButton.Location = new System.Drawing.Point(96, 431); this.DeleteButton.Name = "DeleteButton"; - this.DeleteButton.Size = new System.Drawing.Size(100, 29); + this.DeleteButton.Size = new System.Drawing.Size(87, 29); this.DeleteButton.TabIndex = 13; this.DeleteButton.Text = "&Delete"; this.DeleteButton.UseVisualStyleBackColor = true; @@ -424,11 +410,10 @@ // // AddButton // - this.AddButton.Dock = System.Windows.Forms.DockStyle.Left; - this.AddButton.Location = new System.Drawing.Point(0, 8); - this.AddButton.Margin = new System.Windows.Forms.Padding(0, 8, 4, 4); + this.AddButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.AddButton.Location = new System.Drawing.Point(3, 431); this.AddButton.Name = "AddButton"; - this.AddButton.Size = new System.Drawing.Size(100, 29); + this.AddButton.Size = new System.Drawing.Size(87, 29); this.AddButton.TabIndex = 12; this.AddButton.Text = "&Add"; this.AddButton.UseVisualStyleBackColor = true; @@ -438,76 +423,37 @@ // this.ServerGroupBox.AutoSize = true; this.ServerGroupBox.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.tableLayoutPanel7.SetColumnSpan(this.ServerGroupBox, 4); this.ServerGroupBox.Controls.Add(this.tableLayoutPanel1); - this.ServerGroupBox.Location = new System.Drawing.Point(223, 0); - this.ServerGroupBox.Margin = new System.Windows.Forms.Padding(15, 0, 0, 0); + this.ServerGroupBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.ServerGroupBox.Location = new System.Drawing.Point(189, 0); + this.ServerGroupBox.Margin = new System.Windows.Forms.Padding(3, 0, 3, 3); this.ServerGroupBox.Name = "ServerGroupBox"; this.ServerGroupBox.Padding = new System.Windows.Forms.Padding(4); - this.ServerGroupBox.Size = new System.Drawing.Size(408, 405); + this.ServerGroupBox.Size = new System.Drawing.Size(370, 425); this.ServerGroupBox.TabIndex = 0; this.ServerGroupBox.TabStop = false; this.ServerGroupBox.Text = "Server"; // // ServersListBox // + this.tableLayoutPanel7.SetColumnSpan(this.ServersListBox, 2); + this.ServersListBox.Dock = System.Windows.Forms.DockStyle.Fill; this.ServersListBox.FormattingEnabled = true; this.ServersListBox.IntegralHeight = false; this.ServersListBox.ItemHeight = 15; - this.ServersListBox.Location = new System.Drawing.Point(0, 0); - this.ServersListBox.Margin = new System.Windows.Forms.Padding(0); + this.ServersListBox.Location = new System.Drawing.Point(3, 3); this.ServersListBox.Name = "ServersListBox"; - this.ServersListBox.Size = new System.Drawing.Size(206, 184); + this.ServersListBox.Size = new System.Drawing.Size(180, 422); this.ServersListBox.TabIndex = 11; this.ServersListBox.SelectedIndexChanged += new System.EventHandler(this.ServersListBox_SelectedIndexChanged); // - // tableLayoutPanel2 - // - this.tableLayoutPanel2.AutoSize = true; - this.tableLayoutPanel2.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.tableLayoutPanel2.ColumnCount = 2; - this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel2.Controls.Add(this.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); - this.tableLayoutPanel2.Controls.Add(this.ServerGroupBox, 1, 0); - this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel4, 0, 1); - this.tableLayoutPanel2.Location = new System.Drawing.Point(15, 15); - this.tableLayoutPanel2.Margin = new System.Windows.Forms.Padding(0); - this.tableLayoutPanel2.Name = "tableLayoutPanel2"; - this.tableLayoutPanel2.RowCount = 3; - this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel2.Size = new System.Drawing.Size(631, 528); - 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, 487); - 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(208, 41); - this.tableLayoutPanel6.TabIndex = 10; - // // MoveDownButton // - this.MoveDownButton.Dock = System.Windows.Forms.DockStyle.Right; - this.MoveDownButton.Location = new System.Drawing.Point(108, 8); - this.MoveDownButton.Margin = new System.Windows.Forms.Padding(4, 8, 0, 4); + this.MoveDownButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.MoveDownButton.Location = new System.Drawing.Point(96, 501); this.MoveDownButton.Name = "MoveDownButton"; - this.MoveDownButton.Size = new System.Drawing.Size(100, 29); + this.MoveDownButton.Size = new System.Drawing.Size(87, 29); this.MoveDownButton.TabIndex = 16; this.MoveDownButton.Text = "Move D&own"; this.MoveDownButton.UseVisualStyleBackColor = true; @@ -515,144 +461,135 @@ // // MoveUpButton // - this.MoveUpButton.Dock = System.Windows.Forms.DockStyle.Left; - this.MoveUpButton.Location = new System.Drawing.Point(0, 8); - this.MoveUpButton.Margin = new System.Windows.Forms.Padding(0, 8, 4, 4); + this.MoveUpButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.MoveUpButton.Location = new System.Drawing.Point(3, 501); this.MoveUpButton.Name = "MoveUpButton"; - this.MoveUpButton.Size = new System.Drawing.Size(100, 29); + this.MoveUpButton.Size = new System.Drawing.Size(87, 29); this.MoveUpButton.TabIndex = 15; 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) - | System.Windows.Forms.AnchorStyles.Left))); - this.tableLayoutPanel5.AutoSize = true; - this.tableLayoutPanel5.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.tableLayoutPanel5.ColumnCount = 2; - this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel5.Controls.Add(this.ProxyPortTextBox, 1, 0); - this.tableLayoutPanel5.Controls.Add(this.ProxyPortLabel, 0, 0); - this.tableLayoutPanel5.Controls.Add(this.PortableModeCheckBox, 0, 1); - this.tableLayoutPanel5.Location = new System.Drawing.Point(208, 405); - this.tableLayoutPanel5.Margin = new System.Windows.Forms.Padding(0); - this.tableLayoutPanel5.Name = "tableLayoutPanel5"; - this.tableLayoutPanel5.Padding = new System.Windows.Forms.Padding(4); - this.tableLayoutPanel5.RowCount = 2; - this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel5.Size = new System.Drawing.Size(251, 82); - this.tableLayoutPanel5.TabIndex = 9; - // // ProxyPortTextBox // - this.ProxyPortTextBox.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.ProxyPortTextBox.Location = new System.Drawing.Point(103, 8); + this.tableLayoutPanel7.SetColumnSpan(this.ProxyPortTextBox, 2); + this.ProxyPortTextBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.ProxyPortTextBox.Location = new System.Drawing.Point(283, 432); this.ProxyPortTextBox.Margin = new System.Windows.Forms.Padding(4); this.ProxyPortTextBox.MaxLength = 10; this.ProxyPortTextBox.Name = "ProxyPortTextBox"; - this.ProxyPortTextBox.Size = new System.Drawing.Size(140, 25); + this.ProxyPortTextBox.Size = new System.Drawing.Size(178, 25); this.ProxyPortTextBox.TabIndex = 10; this.ProxyPortTextBox.WordWrap = false; // // ProxyPortLabel // - this.ProxyPortLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.ProxyPortLabel.AutoSize = true; - this.ProxyPortLabel.Location = new System.Drawing.Point(8, 13); + this.ProxyPortLabel.Dock = System.Windows.Forms.DockStyle.Fill; + this.ProxyPortLabel.Location = new System.Drawing.Point(190, 428); this.ProxyPortLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.ProxyPortLabel.Name = "ProxyPortLabel"; - this.ProxyPortLabel.Size = new System.Drawing.Size(87, 15); + this.ProxyPortLabel.Size = new System.Drawing.Size(85, 35); this.ProxyPortLabel.TabIndex = 10; this.ProxyPortLabel.Text = "Proxy Port"; + this.ProxyPortLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // PortableModeCheckBox // - this.PortableModeCheckBox.Anchor = System.Windows.Forms.AnchorStyles.Left; this.PortableModeCheckBox.AutoSize = true; - this.tableLayoutPanel5.SetColumnSpan(this.PortableModeCheckBox, 2); - this.PortableModeCheckBox.Location = new System.Drawing.Point(8, 48); + this.tableLayoutPanel7.SetColumnSpan(this.PortableModeCheckBox, 2); + this.PortableModeCheckBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.PortableModeCheckBox.Location = new System.Drawing.Point(283, 467); this.PortableModeCheckBox.Margin = new System.Windows.Forms.Padding(4); this.PortableModeCheckBox.Name = "PortableModeCheckBox"; - this.PortableModeCheckBox.Size = new System.Drawing.Size(133, 19); + this.PortableModeCheckBox.Size = new System.Drawing.Size(178, 27); this.PortableModeCheckBox.TabIndex = 11; this.PortableModeCheckBox.Text = "Portable Mode"; this.toolTip1.SetToolTip(this.PortableModeCheckBox, "restart required"); this.PortableModeCheckBox.UseVisualStyleBackColor = true; // - // tableLayoutPanel3 - // - this.tableLayoutPanel3.AutoSize = true; - this.tableLayoutPanel3.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.tableLayoutPanel3.ColumnCount = 3; - this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 25F)); - this.tableLayoutPanel3.Controls.Add(this.MyCancelButton, 1, 0); - this.tableLayoutPanel3.Controls.Add(this.OKButton, 0, 0); - this.tableLayoutPanel3.Controls.Add(this.ApplyButton, 2, 0); - this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Right; - this.tableLayoutPanel3.Location = new System.Drawing.Point(329, 491); - this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(4, 4, 0, 4); - this.tableLayoutPanel3.Name = "tableLayoutPanel3"; - this.tableLayoutPanel3.RowCount = 1; - this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel3.Size = new System.Drawing.Size(302, 33); - this.tableLayoutPanel3.TabIndex = 8; - // - // tableLayoutPanel4 - // - this.tableLayoutPanel4.AutoSize = true; - this.tableLayoutPanel4.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.tableLayoutPanel4.ColumnCount = 2; - this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel4.Controls.Add(this.DuplicateButton, 0, 1); - this.tableLayoutPanel4.Controls.Add(this.DeleteButton, 1, 0); - this.tableLayoutPanel4.Controls.Add(this.AddButton, 0, 0); - this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Top; - this.tableLayoutPanel4.Location = new System.Drawing.Point(0, 405); - this.tableLayoutPanel4.Margin = new System.Windows.Forms.Padding(0); - this.tableLayoutPanel4.Name = "tableLayoutPanel4"; - this.tableLayoutPanel4.RowCount = 2; - this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel4.Size = new System.Drawing.Size(208, 82); - this.tableLayoutPanel4.TabIndex = 8; - // // DuplicateButton // - this.DuplicateButton.Dock = System.Windows.Forms.DockStyle.Left; - this.DuplicateButton.Location = new System.Drawing.Point(0, 49); - this.DuplicateButton.Margin = new System.Windows.Forms.Padding(0, 8, 4, 4); + this.DuplicateButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.DuplicateButton.Location = new System.Drawing.Point(3, 466); this.DuplicateButton.Name = "DuplicateButton"; - this.DuplicateButton.Size = new System.Drawing.Size(100, 29); + this.DuplicateButton.Size = new System.Drawing.Size(87, 29); this.DuplicateButton.TabIndex = 14; this.DuplicateButton.Text = "Dupli&cate"; this.DuplicateButton.UseVisualStyleBackColor = true; this.DuplicateButton.Click += new System.EventHandler(this.DuplicateButton_Click); // + // tableLayoutPanel7 + // + this.tableLayoutPanel7.AutoSize = true; + this.tableLayoutPanel7.ColumnCount = 6; + this.tableLayoutPanel7.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 16.66667F)); + this.tableLayoutPanel7.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 16.66667F)); + this.tableLayoutPanel7.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 16.66667F)); + this.tableLayoutPanel7.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 16.66667F)); + this.tableLayoutPanel7.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 16.66667F)); + this.tableLayoutPanel7.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 16.66667F)); + this.tableLayoutPanel7.Controls.Add(this.ApplyButton, 5, 3); + this.tableLayoutPanel7.Controls.Add(this.MyCancelButton, 4, 3); + this.tableLayoutPanel7.Controls.Add(this.OKButton, 3, 3); + this.tableLayoutPanel7.Controls.Add(this.ProxyPortTextBox, 3, 1); + this.tableLayoutPanel7.Controls.Add(this.MoveDownButton, 1, 3); + this.tableLayoutPanel7.Controls.Add(this.ProxyPortLabel, 2, 1); + this.tableLayoutPanel7.Controls.Add(this.MoveUpButton, 0, 3); + this.tableLayoutPanel7.Controls.Add(this.AddButton, 0, 1); + this.tableLayoutPanel7.Controls.Add(this.DeleteButton, 1, 1); + this.tableLayoutPanel7.Controls.Add(this.DuplicateButton, 0, 2); + this.tableLayoutPanel7.Controls.Add(this.ServersListBox, 0, 0); + this.tableLayoutPanel7.Controls.Add(this.ServerGroupBox, 2, 0); + this.tableLayoutPanel7.Controls.Add(this.PortableModeCheckBox, 3, 2); + this.tableLayoutPanel7.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel7.GrowStyle = System.Windows.Forms.TableLayoutPanelGrowStyle.FixedSize; + this.tableLayoutPanel7.Location = new System.Drawing.Point(10, 10); + this.tableLayoutPanel7.Name = "tableLayoutPanel7"; + this.tableLayoutPanel7.RowCount = 4; + this.tableLayoutPanel7.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel7.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel7.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel7.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel7.Size = new System.Drawing.Size(562, 533); + this.tableLayoutPanel7.TabIndex = 8; + // + // GroupLabel + // + this.GroupLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.GroupLabel.AutoSize = true; + this.GroupLabel.Location = new System.Drawing.Point(96, 350); + this.GroupLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.GroupLabel.Name = "GroupLabel"; + this.GroupLabel.RightToLeft = System.Windows.Forms.RightToLeft.No; + this.GroupLabel.Size = new System.Drawing.Size(47, 15); + this.GroupLabel.TabIndex = 11; + this.GroupLabel.Text = "Group"; + // + // GroupTextBox + // + this.GroupTextBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.GroupTextBox.Location = new System.Drawing.Point(150, 345); + this.GroupTextBox.MaxLength = 5; + this.GroupTextBox.Name = "GroupTextBox"; + this.GroupTextBox.ReadOnly = true; + this.GroupTextBox.Size = new System.Drawing.Size(205, 25); + this.GroupTextBox.TabIndex = 12; + // // ConfigForm // this.AcceptButton = this.OKButton; this.AutoScaleDimensions = new System.Drawing.SizeF(120F, 120F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.AutoSize = true; - this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.CancelButton = this.MyCancelButton; - this.ClientSize = new System.Drawing.Size(614, 548); - this.Controls.Add(this.tableLayoutPanel2); + this.ClientSize = new System.Drawing.Size(582, 553); + this.Controls.Add(this.tableLayoutPanel7); this.Controls.Add(this.panel2); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.Margin = new System.Windows.Forms.Padding(4); - this.MaximizeBox = false; this.MinimizeBox = false; + this.MinimumSize = new System.Drawing.Size(400, 575); this.Name = "ConfigForm"; - this.Padding = new System.Windows.Forms.Padding(15, 15, 15, 11); + this.Padding = new System.Windows.Forms.Padding(10); this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Edit Servers"; this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ConfigForm_FormClosed); @@ -662,13 +599,8 @@ this.tableLayoutPanel1.PerformLayout(); this.ServerGroupBox.ResumeLayout(false); 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); - this.tableLayoutPanel4.ResumeLayout(false); + this.tableLayoutPanel7.ResumeLayout(false); + this.tableLayoutPanel7.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); @@ -694,13 +626,8 @@ private System.Windows.Forms.ListBox ServersListBox; private System.Windows.Forms.TextBox RemarksTextBox; private System.Windows.Forms.Label RemarksLabel; - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2; - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4; - 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; private System.Windows.Forms.Button DuplicateButton; @@ -717,6 +644,9 @@ private System.Windows.Forms.ToolTip toolTip1; private System.Windows.Forms.CheckBox PortableModeCheckBox; private System.Windows.Forms.CheckBox NeedPluginArgCheckBox; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel7; + private System.Windows.Forms.Label GroupLabel; + private System.Windows.Forms.TextBox GroupTextBox; } } diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index 2bfdb25b..f8b051c1 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -26,9 +26,6 @@ namespace Shadowsocks.View InitializeComponent(); EncryptionSelect.Items.AddRange(EncryptorFactory.ListAvaliableCiphers().ToArray()); - // a dirty hack - ServersListBox.Dock = DockStyle.Fill; - tableLayoutPanel5.Dock = DockStyle.Fill; PerformLayout(); UpdateTexts(); @@ -125,6 +122,7 @@ namespace Shadowsocks.View plugin_args = PluginArgumentsTextBox.Text, remarks = RemarksTextBox.Text, timeout = timeout.Value, + group = GroupTextBox.Text }; return true; @@ -332,6 +330,8 @@ namespace Shadowsocks.View RemarksTextBox.Text = server.remarks; TimeoutTextBox.Text = server.timeout.ToString(); + GroupTextBox.Text = server.group; + isChange = false; } diff --git a/shadowsocks-csharp/View/ConfigForm.resx b/shadowsocks-csharp/View/ConfigForm.resx index 80d77309..6dfd76d8 100755 --- a/shadowsocks-csharp/View/ConfigForm.resx +++ b/shadowsocks-csharp/View/ConfigForm.resx @@ -120,4 +120,7 @@ 17, 17 + + 17, 17 + \ No newline at end of file diff --git a/shadowsocks-csharp/View/HotkeySettingsForm.designer.cs b/shadowsocks-csharp/View/HotkeySettingsForm.designer.cs index 4c9f4608..47f89946 100644 --- a/shadowsocks-csharp/View/HotkeySettingsForm.designer.cs +++ b/shadowsocks-csharp/View/HotkeySettingsForm.designer.cs @@ -59,7 +59,7 @@ flowLayoutPanel1.Controls.Add(this.btnCancel); flowLayoutPanel1.Controls.Add(this.btnRegisterAll); flowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.BottomUp; - flowLayoutPanel1.Location = new System.Drawing.Point(0, 274); + flowLayoutPanel1.Location = new System.Drawing.Point(0, 248); flowLayoutPanel1.Margin = new System.Windows.Forms.Padding(0); flowLayoutPanel1.Name = "flowLayoutPanel1"; flowLayoutPanel1.Padding = new System.Windows.Forms.Padding(0, 0, 20, 0); @@ -138,17 +138,17 @@ this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); - this.tableLayoutPanel1.Size = new System.Drawing.Size(614, 326); + this.tableLayoutPanel1.Size = new System.Drawing.Size(582, 303); this.tableLayoutPanel1.TabIndex = 0; // // RegHotkeysAtStartupLabel // this.RegHotkeysAtStartupLabel.AutoSize = true; this.RegHotkeysAtStartupLabel.Dock = System.Windows.Forms.DockStyle.Right; - this.RegHotkeysAtStartupLabel.Location = new System.Drawing.Point(40, 235); + this.RegHotkeysAtStartupLabel.Location = new System.Drawing.Point(40, 213); this.RegHotkeysAtStartupLabel.Margin = new System.Windows.Forms.Padding(10, 0, 10, 0); this.RegHotkeysAtStartupLabel.Name = "RegHotkeysAtStartupLabel"; - this.RegHotkeysAtStartupLabel.Size = new System.Drawing.Size(199, 39); + this.RegHotkeysAtStartupLabel.Size = new System.Drawing.Size(199, 35); this.RegHotkeysAtStartupLabel.TabIndex = 16; this.RegHotkeysAtStartupLabel.Text = "Reg Hotkeys At Startup"; this.RegHotkeysAtStartupLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; @@ -160,7 +160,7 @@ this.SwitchSystemProxyLabel.Location = new System.Drawing.Point(63, 0); this.SwitchSystemProxyLabel.Margin = new System.Windows.Forms.Padding(10, 0, 10, 0); this.SwitchSystemProxyLabel.Name = "SwitchSystemProxyLabel"; - this.SwitchSystemProxyLabel.Size = new System.Drawing.Size(176, 39); + this.SwitchSystemProxyLabel.Size = new System.Drawing.Size(176, 35); this.SwitchSystemProxyLabel.TabIndex = 0; this.SwitchSystemProxyLabel.Text = "Switch system proxy"; this.SwitchSystemProxyLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; @@ -169,10 +169,10 @@ // this.SwitchProxyModeLabel.AutoSize = true; this.SwitchProxyModeLabel.Dock = System.Windows.Forms.DockStyle.Right; - this.SwitchProxyModeLabel.Location = new System.Drawing.Point(10, 39); + this.SwitchProxyModeLabel.Location = new System.Drawing.Point(10, 35); this.SwitchProxyModeLabel.Margin = new System.Windows.Forms.Padding(10, 0, 10, 0); this.SwitchProxyModeLabel.Name = "SwitchProxyModeLabel"; - this.SwitchProxyModeLabel.Size = new System.Drawing.Size(229, 39); + this.SwitchProxyModeLabel.Size = new System.Drawing.Size(229, 35); this.SwitchProxyModeLabel.TabIndex = 1; this.SwitchProxyModeLabel.Text = "Switch system proxy mode"; this.SwitchProxyModeLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; @@ -181,10 +181,10 @@ // this.SwitchAllowLanLabel.AutoSize = true; this.SwitchAllowLanLabel.Dock = System.Windows.Forms.DockStyle.Right; - this.SwitchAllowLanLabel.Location = new System.Drawing.Point(39, 78); + this.SwitchAllowLanLabel.Location = new System.Drawing.Point(39, 70); this.SwitchAllowLanLabel.Margin = new System.Windows.Forms.Padding(10, 0, 10, 0); this.SwitchAllowLanLabel.Name = "SwitchAllowLanLabel"; - this.SwitchAllowLanLabel.Size = new System.Drawing.Size(200, 39); + this.SwitchAllowLanLabel.Size = new System.Drawing.Size(200, 35); this.SwitchAllowLanLabel.TabIndex = 3; this.SwitchAllowLanLabel.Text = "Allow Clients from LAN"; this.SwitchAllowLanLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; @@ -193,10 +193,10 @@ // this.ShowLogsLabel.AutoSize = true; this.ShowLogsLabel.Dock = System.Windows.Forms.DockStyle.Right; - this.ShowLogsLabel.Location = new System.Drawing.Point(129, 117); + this.ShowLogsLabel.Location = new System.Drawing.Point(129, 105); this.ShowLogsLabel.Margin = new System.Windows.Forms.Padding(10, 0, 10, 0); this.ShowLogsLabel.Name = "ShowLogsLabel"; - this.ShowLogsLabel.Size = new System.Drawing.Size(110, 39); + this.ShowLogsLabel.Size = new System.Drawing.Size(110, 35); this.ShowLogsLabel.TabIndex = 4; this.ShowLogsLabel.Text = "Show Logs..."; this.ShowLogsLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; @@ -205,10 +205,10 @@ // this.ServerMoveUpLabel.AutoSize = true; this.ServerMoveUpLabel.Dock = System.Windows.Forms.DockStyle.Right; - this.ServerMoveUpLabel.Location = new System.Drawing.Point(25, 156); + this.ServerMoveUpLabel.Location = new System.Drawing.Point(25, 140); this.ServerMoveUpLabel.Margin = new System.Windows.Forms.Padding(10, 0, 10, 0); this.ServerMoveUpLabel.Name = "ServerMoveUpLabel"; - this.ServerMoveUpLabel.Size = new System.Drawing.Size(214, 40); + this.ServerMoveUpLabel.Size = new System.Drawing.Size(214, 37); this.ServerMoveUpLabel.TabIndex = 4; this.ServerMoveUpLabel.Text = "Switch to previous server"; this.ServerMoveUpLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; @@ -217,10 +217,10 @@ // this.ServerMoveDownLabel.AutoSize = true; this.ServerMoveDownLabel.Dock = System.Windows.Forms.DockStyle.Right; - this.ServerMoveDownLabel.Location = new System.Drawing.Point(60, 196); + this.ServerMoveDownLabel.Location = new System.Drawing.Point(60, 177); this.ServerMoveDownLabel.Margin = new System.Windows.Forms.Padding(10, 0, 10, 0); this.ServerMoveDownLabel.Name = "ServerMoveDownLabel"; - this.ServerMoveDownLabel.Size = new System.Drawing.Size(179, 39); + this.ServerMoveDownLabel.Size = new System.Drawing.Size(179, 36); this.ServerMoveDownLabel.TabIndex = 4; this.ServerMoveDownLabel.Text = "Switch to next server"; this.ServerMoveDownLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; @@ -228,11 +228,10 @@ // SwitchSystemProxyTextBox // this.SwitchSystemProxyTextBox.Dock = System.Windows.Forms.DockStyle.Fill; - this.SwitchSystemProxyTextBox.Location = new System.Drawing.Point(253, 4); - this.SwitchSystemProxyTextBox.Margin = new System.Windows.Forms.Padding(4, 4, 20, 4); + this.SwitchSystemProxyTextBox.Location = new System.Drawing.Point(252, 3); this.SwitchSystemProxyTextBox.Name = "SwitchSystemProxyTextBox"; this.SwitchSystemProxyTextBox.ReadOnly = true; - this.SwitchSystemProxyTextBox.Size = new System.Drawing.Size(344, 29); + this.SwitchSystemProxyTextBox.Size = new System.Drawing.Size(339, 29); this.SwitchSystemProxyTextBox.TabIndex = 7; this.SwitchSystemProxyTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.HotkeyDown); this.SwitchSystemProxyTextBox.KeyUp += new System.Windows.Forms.KeyEventHandler(this.HotkeyUp); @@ -240,11 +239,10 @@ // SwitchProxyModeTextBox // this.SwitchProxyModeTextBox.Dock = System.Windows.Forms.DockStyle.Fill; - this.SwitchProxyModeTextBox.Location = new System.Drawing.Point(253, 43); - this.SwitchProxyModeTextBox.Margin = new System.Windows.Forms.Padding(4, 4, 20, 4); + this.SwitchProxyModeTextBox.Location = new System.Drawing.Point(252, 38); this.SwitchProxyModeTextBox.Name = "SwitchProxyModeTextBox"; this.SwitchProxyModeTextBox.ReadOnly = true; - this.SwitchProxyModeTextBox.Size = new System.Drawing.Size(344, 29); + this.SwitchProxyModeTextBox.Size = new System.Drawing.Size(339, 29); this.SwitchProxyModeTextBox.TabIndex = 8; this.SwitchProxyModeTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.HotkeyDown); this.SwitchProxyModeTextBox.KeyUp += new System.Windows.Forms.KeyEventHandler(this.HotkeyUp); @@ -252,11 +250,10 @@ // SwitchAllowLanTextBox // this.SwitchAllowLanTextBox.Dock = System.Windows.Forms.DockStyle.Fill; - this.SwitchAllowLanTextBox.Location = new System.Drawing.Point(253, 82); - this.SwitchAllowLanTextBox.Margin = new System.Windows.Forms.Padding(4, 4, 20, 4); + this.SwitchAllowLanTextBox.Location = new System.Drawing.Point(252, 73); this.SwitchAllowLanTextBox.Name = "SwitchAllowLanTextBox"; this.SwitchAllowLanTextBox.ReadOnly = true; - this.SwitchAllowLanTextBox.Size = new System.Drawing.Size(344, 29); + this.SwitchAllowLanTextBox.Size = new System.Drawing.Size(339, 29); this.SwitchAllowLanTextBox.TabIndex = 10; this.SwitchAllowLanTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.HotkeyDown); this.SwitchAllowLanTextBox.KeyUp += new System.Windows.Forms.KeyEventHandler(this.HotkeyUp); @@ -264,11 +261,10 @@ // ShowLogsTextBox // this.ShowLogsTextBox.Dock = System.Windows.Forms.DockStyle.Fill; - this.ShowLogsTextBox.Location = new System.Drawing.Point(253, 121); - this.ShowLogsTextBox.Margin = new System.Windows.Forms.Padding(4, 4, 20, 4); + this.ShowLogsTextBox.Location = new System.Drawing.Point(252, 108); this.ShowLogsTextBox.Name = "ShowLogsTextBox"; this.ShowLogsTextBox.ReadOnly = true; - this.ShowLogsTextBox.Size = new System.Drawing.Size(344, 29); + this.ShowLogsTextBox.Size = new System.Drawing.Size(339, 29); this.ShowLogsTextBox.TabIndex = 11; this.ShowLogsTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.HotkeyDown); this.ShowLogsTextBox.KeyUp += new System.Windows.Forms.KeyEventHandler(this.HotkeyUp); @@ -276,11 +272,10 @@ // ServerMoveUpTextBox // this.ServerMoveUpTextBox.Dock = System.Windows.Forms.DockStyle.Fill; - this.ServerMoveUpTextBox.Location = new System.Drawing.Point(253, 160); - this.ServerMoveUpTextBox.Margin = new System.Windows.Forms.Padding(4, 4, 20, 4); + this.ServerMoveUpTextBox.Location = new System.Drawing.Point(252, 143); this.ServerMoveUpTextBox.Name = "ServerMoveUpTextBox"; this.ServerMoveUpTextBox.ReadOnly = true; - this.ServerMoveUpTextBox.Size = new System.Drawing.Size(344, 29); + this.ServerMoveUpTextBox.Size = new System.Drawing.Size(339, 29); this.ServerMoveUpTextBox.TabIndex = 12; this.ServerMoveUpTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.HotkeyDown); this.ServerMoveUpTextBox.KeyUp += new System.Windows.Forms.KeyEventHandler(this.HotkeyUp); @@ -288,11 +283,10 @@ // ServerMoveDownTextBox // this.ServerMoveDownTextBox.Dock = System.Windows.Forms.DockStyle.Fill; - this.ServerMoveDownTextBox.Location = new System.Drawing.Point(253, 200); - this.ServerMoveDownTextBox.Margin = new System.Windows.Forms.Padding(4, 4, 20, 4); + this.ServerMoveDownTextBox.Location = new System.Drawing.Point(252, 180); this.ServerMoveDownTextBox.Name = "ServerMoveDownTextBox"; this.ServerMoveDownTextBox.ReadOnly = true; - this.ServerMoveDownTextBox.Size = new System.Drawing.Size(344, 29); + this.ServerMoveDownTextBox.Size = new System.Drawing.Size(339, 29); this.ServerMoveDownTextBox.TabIndex = 13; this.ServerMoveDownTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.HotkeyDown); this.ServerMoveDownTextBox.KeyUp += new System.Windows.Forms.KeyEventHandler(this.HotkeyUp); @@ -300,10 +294,10 @@ // RegHotkeysAtStartupCheckBox // this.RegHotkeysAtStartupCheckBox.AutoSize = true; - this.RegHotkeysAtStartupCheckBox.Location = new System.Drawing.Point(253, 246); - this.RegHotkeysAtStartupCheckBox.Margin = new System.Windows.Forms.Padding(4, 11, 11, 11); + this.RegHotkeysAtStartupCheckBox.Dock = System.Windows.Forms.DockStyle.Left; + this.RegHotkeysAtStartupCheckBox.Location = new System.Drawing.Point(252, 216); this.RegHotkeysAtStartupCheckBox.Name = "RegHotkeysAtStartupCheckBox"; - this.RegHotkeysAtStartupCheckBox.Size = new System.Drawing.Size(18, 17); + this.RegHotkeysAtStartupCheckBox.Size = new System.Drawing.Size(18, 29); this.RegHotkeysAtStartupCheckBox.TabIndex = 17; this.RegHotkeysAtStartupCheckBox.UseVisualStyleBackColor = true; // @@ -311,9 +305,10 @@ // this.AutoScaleDimensions = new System.Drawing.SizeF(120F, 120F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.ClientSize = new System.Drawing.Size(614, 326); + this.ClientSize = new System.Drawing.Size(582, 303); this.Controls.Add(this.tableLayoutPanel1); this.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.Margin = new System.Windows.Forms.Padding(5, 6, 5, 6); this.MaximizeBox = false; this.MinimizeBox = false; diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index 0107f94c..bea69330 100644 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -59,11 +59,13 @@ namespace Shadowsocks.View private ToolStripMenuItem VerboseLoggingToggleItem; private ToolStripMenuItem ShowPluginOutputToggleItem; private ToolStripMenuItem WriteI18NFileItem; + private ToolStripMenuItem onlineConfigItem; private ConfigForm configForm; private ProxyForm proxyForm; private LogForm logForm; private HotkeySettingsForm hotkeySettingsForm; + private OnlineConfigForm onlineConfigForm; @@ -120,37 +122,6 @@ namespace Shadowsocks.View } } - private void controller_TrafficChanged(object sender, EventArgs e) - { - if (icon == null) - return; - - Icon newIcon; - - bool hasInbound = controller.trafficPerSecondQueue.Last().inboundIncreasement > 0; - bool hasOutbound = controller.trafficPerSecondQueue.Last().outboundIncreasement > 0; - - if (hasInbound && hasOutbound) - newIcon = icon_both; - else if (hasInbound) - newIcon = icon_in; - else if (hasOutbound) - newIcon = icon_out; - else - newIcon = icon; - - if (newIcon != this.previousIcon) - { - this.previousIcon = newIcon; - _notifyIcon.Icon = newIcon; - } - } - - void controller_Errored(object sender, System.IO.ErrorEventArgs e) - { - MessageBox.Show(e.GetException().ToString(), I18N.GetString("Shadowsocks Error: {0}", e.GetException().Message)); - } - #region Tray Icon private void UpdateTrayIconAndNotifyText() @@ -317,7 +288,8 @@ namespace Shadowsocks.View this.editOnlinePACItem = CreateToolStripMenuItem("Edit Online PAC URL...", new EventHandler(this.UpdateOnlinePACURLItem_Click)), }), this.proxyItem = CreateToolStripMenuItem("Forward Proxy...", new EventHandler(this.proxyItem_Click)), - new ToolStripSeparator( ), + this.onlineConfigItem = CreateToolStripMenuItem("Online Config...", new EventHandler(this.OnlineConfig_Click)), + new ToolStripSeparator( ), this.AutoStartupItem = CreateToolStripMenuItem("Start on Boot", new EventHandler(this.AutoStartupItem_Click)), this.ProtocolHandlerItem = CreateToolStripMenuItem("Associate ss:// Links", new EventHandler(this.ProtocolHandlerItem_Click)), this.ShareOverLANItem = CreateToolStripMenuItem("Allow other Devices to connect", new EventHandler(this.ShareOverLANItem_Click)), @@ -343,99 +315,41 @@ namespace Shadowsocks.View #endregion - private void controller_ConfigChanged(object sender, EventArgs e) - { - LoadCurrentConfiguration(); - UpdateTrayIconAndNotifyText(); - } - - private void controller_EnableStatusChanged(object sender, EventArgs e) - { - disableItem.Checked = !controller.GetConfigurationCopy().enabled; - } - - void controller_ShareOverLANStatusChanged(object sender, EventArgs e) - { - ShareOverLANItem.Checked = controller.GetConfigurationCopy().shareOverLan; - } - - void controller_VerboseLoggingStatusChanged(object sender, EventArgs e) - { - VerboseLoggingToggleItem.Checked = controller.GetConfigurationCopy().isVerboseLogging; - } - - void controller_ShowPluginOutputChanged(object sender, EventArgs e) - { - ShowPluginOutputToggleItem.Checked = controller.GetConfigurationCopy().showPluginOutput; - } - - void controller_EnableGlobalChanged(object sender, EventArgs e) - { - globalModeItem.Checked = controller.GetConfigurationCopy().global; - PACModeItem.Checked = !globalModeItem.Checked; - } - - void controller_FileReadyToOpen(object sender, ShadowsocksController.PathEventArgs e) + private void controller_TrafficChanged(object sender, EventArgs e) { - string argument = @"/select, " + e.Path; - - Process.Start("explorer.exe", argument); - } + if (icon == null) + return; - void ShowBalloonTip(string title, string content, ToolTipIcon icon, int timeout) - { - _notifyIcon.BalloonTipTitle = title; - _notifyIcon.BalloonTipText = content; - _notifyIcon.BalloonTipIcon = icon; - _notifyIcon.ShowBalloonTip(timeout); - } + Icon newIcon; - void controller_UpdatePACFromGeositeError(object sender, System.IO.ErrorEventArgs e) - { - ShowBalloonTip(I18N.GetString("Failed to update PAC file"), e.GetException().Message, ToolTipIcon.Error, 5000); - logger.LogUsefulException(e.GetException()); - } + bool hasInbound = controller.trafficPerSecondQueue.Last().inboundIncreasement > 0; + bool hasOutbound = controller.trafficPerSecondQueue.Last().outboundIncreasement > 0; - void controller_UpdatePACFromGeositeCompleted(object sender, GeositeResultEventArgs e) - { - string result = e.Success - ? I18N.GetString("PAC updated") - : I18N.GetString("No updates found. Please report to Geosite if you have problems with it."); - ShowBalloonTip(I18N.GetString("Shadowsocks"), result, ToolTipIcon.Info, 1000); - } + if (hasInbound && hasOutbound) + newIcon = icon_both; + else if (hasInbound) + newIcon = icon_in; + else if (hasOutbound) + newIcon = icon_out; + else + newIcon = icon; - void updateChecker_CheckUpdateCompleted(object sender, EventArgs e) - { - if (updateChecker.NewVersionFound) - { - ShowBalloonTip(I18N.GetString("Shadowsocks {0} Update Found", updateChecker.LatestVersionNumber + updateChecker.LatestVersionSuffix), I18N.GetString("Click here to update"), ToolTipIcon.Info, 5000); - } - else if (!_isStartupChecking) + if (newIcon != this.previousIcon) { - ShowBalloonTip(I18N.GetString("Shadowsocks"), I18N.GetString("No update is available"), ToolTipIcon.Info, 5000); + this.previousIcon = newIcon; + _notifyIcon.Icon = newIcon; } - _isStartupChecking = false; } - void notifyIcon1_BalloonTipClicked(object sender, EventArgs e) + void controller_Errored(object sender, System.IO.ErrorEventArgs e) { - if (updateChecker.NewVersionFound) - { - updateChecker.NewVersionFound = false; /* Reset the flag */ - if (File.Exists(updateChecker.LatestVersionLocalName)) - { - string argument = "/select, \"" + updateChecker.LatestVersionLocalName + "\""; - Process.Start("explorer.exe", argument); - } - } + MessageBox.Show(e.GetException().ToString(), I18N.GetString("Shadowsocks Error: {0}", e.GetException().Message)); } - private void _notifyIcon_BalloonTipClosed(object sender, EventArgs e) + private void controller_ConfigChanged(object sender, EventArgs e) { - if (updateChecker.NewVersionFound) - { - updateChecker.NewVersionFound = false; /* Reset the flag */ - } + LoadCurrentConfiguration(); + UpdateTrayIconAndNotifyText(); } private void LoadCurrentConfiguration() @@ -455,66 +369,7 @@ namespace Shadowsocks.View UpdateUpdateMenu(); } - private void UpdateServersMenu() - { - var items = ServersItem.DropDownItems; - while (items[0] != SeperatorItem) - { - items.RemoveAt(0); - } - int strategyCount = 0; - foreach (var strategy in controller.GetStrategies()) - { - if (!items.OfType().Any(ts => ts.Text == strategy.Name)) - { - ToolStripMenuItem item = new ToolStripMenuItem(strategy.Name); - item.Tag = strategy.ID; - item.Click += AStrategyItem_Click; - items.Add(item); - strategyCount++; - } - } - if (!items.OfType().Any(ts => ts.Tag?.ToString() == "-server-")) - { - // user wants a seperator item between strategy and servers menugroup - items.Add(new ToolStripSeparator() { Tag = "-server-" }); - } - int serverCount = 0; - Configuration configuration = controller.GetConfigurationCopy(); - foreach (var server in configuration.configs) - { - if (Configuration.ChecksServer(server)) - { - var name = server.ToString(); - if (!items.OfType().Any(ts => ts.Text == name)) - { - ToolStripMenuItem item = new ToolStripMenuItem(name); - item.Tag = configuration.configs.FindIndex(s => s == server); - item.Click += AServerItem_Click; - items.Add(item); - serverCount++; - } - } - } - - foreach (var item in items) - { - var menuItem = item as ToolStripMenuItem; - if (menuItem == null || menuItem.Tag == null) continue; - - if ( - menuItem.Tag.ToString() == configuration.index.ToString() - || menuItem.Tag.ToString() == configuration.strategy - ) - { - menuItem.Checked = true; - } - else - { - menuItem.Checked = false; - } - } - } + #region Forms private void ShowConfigForm() { @@ -576,6 +431,22 @@ namespace Shadowsocks.View } } + private void ShowOnlineConfigForm() + { + + if (onlineConfigForm != null) + { + onlineConfigForm.Activate(); + } + else + { + onlineConfigForm = new OnlineConfigForm(controller); + onlineConfigForm.Show(); + onlineConfigForm.Activate(); + onlineConfigForm.FormClosed += onlineConfigForm_FormClosed; + } + } + void logForm_FormClosed(object sender, FormClosedEventArgs e) { logForm.Dispose(); @@ -611,29 +482,43 @@ namespace Shadowsocks.View hotkeySettingsForm = null; } - private void Config_Click(object sender, EventArgs e) + void onlineConfigForm_FormClosed(object sender, FormClosedEventArgs e) { - ShowConfigForm(); + onlineConfigForm.Dispose(); + onlineConfigForm = null; } - private void Quit_Click(object sender, EventArgs e) + #endregion + + #region Misc + + void ShowBalloonTip(string title, string content, ToolTipIcon icon, int timeout) { - controller.Stop(); - _notifyIcon.Visible = false; - Application.Exit(); + _notifyIcon.BalloonTipTitle = title; + _notifyIcon.BalloonTipText = content; + _notifyIcon.BalloonTipIcon = icon; + _notifyIcon.ShowBalloonTip(timeout); } - private void CheckUpdateForFirstRun() + void notifyIcon1_BalloonTipClicked(object sender, EventArgs e) { - Configuration config = controller.GetConfigurationCopy(); - if (config.isDefault) return; - _isStartupChecking = true; - updateChecker.CheckUpdate(config, 3000); + if (updateChecker.NewVersionFound) + { + updateChecker.NewVersionFound = false; /* Reset the flag */ + if (File.Exists(updateChecker.LatestVersionLocalName)) + { + string argument = "/select, \"" + updateChecker.LatestVersionLocalName + "\""; + Process.Start("explorer.exe", argument); + } + } } - private void AboutItem_Click(object sender, EventArgs e) + private void _notifyIcon_BalloonTipClosed(object sender, EventArgs e) { - Utils.OpenInBrowser("https://github.com/shadowsocks/shadowsocks-windows"); + if (updateChecker.NewVersionFound) + { + updateChecker.NewVersionFound = false; /* Reset the flag */ + } } private void notifyIcon1_Click(object sender, MouseEventArgs e) @@ -653,24 +538,109 @@ namespace Shadowsocks.View } } - private void EnableItem_Click(object sender, EventArgs e) + private void CheckUpdateForFirstRun() { - controller.ToggleEnable(false); Configuration config = controller.GetConfigurationCopy(); - UpdateSystemProxyItemsEnabledStatus(config); + if (config.isDefault) return; + _isStartupChecking = true; + updateChecker.CheckUpdate(config, 3000); } - private void UpdateSystemProxyItemsEnabledStatus(Configuration config) + public void ShowLogForm_HotKey() { - disableItem.Checked = !config.enabled; - if (!config.enabled) - { - globalModeItem.Checked = false; - PACModeItem.Checked = false; - } - else - { - globalModeItem.Checked = config.global; + ShowLogForm(); + } + + #endregion + + #region Main menu + + void controller_ShareOverLANStatusChanged(object sender, EventArgs e) + { + ShareOverLANItem.Checked = controller.GetConfigurationCopy().shareOverLan; + } + + private void proxyItem_Click(object sender, EventArgs e) + { + ShowProxyForm(); + } + + private void OnlineConfig_Click(object sender, EventArgs e) + { + ShowOnlineConfigForm(); + } + + private void hotKeyItem_Click(object sender, EventArgs e) + { + ShowHotKeySettingsForm(); + } + + private void ShareOverLANItem_Click(object sender, EventArgs e) + { + ShareOverLANItem.Checked = !ShareOverLANItem.Checked; + controller.ToggleShareOverLAN(ShareOverLANItem.Checked); + } + + 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")); + } + LoadCurrentConfiguration(); + } + + private void ProtocolHandlerItem_Click(object sender, EventArgs e) + { + ProtocolHandlerItem.Checked = !ProtocolHandlerItem.Checked; + if (!ProtocolHandler.Set(ProtocolHandlerItem.Checked)) + { + MessageBox.Show(I18N.GetString("Failed to update registry")); + } + LoadCurrentConfiguration(); + } + + private void Quit_Click(object sender, EventArgs e) + { + controller.Stop(); + _notifyIcon.Visible = false; + Application.Exit(); + } + + #endregion + + #region System proxy + + private void controller_EnableStatusChanged(object sender, EventArgs e) + { + disableItem.Checked = !controller.GetConfigurationCopy().enabled; + } + + private void EnableItem_Click(object sender, EventArgs e) + { + controller.ToggleEnable(false); + Configuration config = controller.GetConfigurationCopy(); + UpdateSystemProxyItemsEnabledStatus(config); + } + + void controller_EnableGlobalChanged(object sender, EventArgs e) + { + globalModeItem.Checked = controller.GetConfigurationCopy().global; + PACModeItem.Checked = !globalModeItem.Checked; + } + + private void UpdateSystemProxyItemsEnabledStatus(Configuration config) + { + disableItem.Checked = !config.enabled; + if (!config.enabled) + { + globalModeItem.Checked = false; + PACModeItem.Checked = false; + } + else + { + globalModeItem.Checked = config.global; PACModeItem.Checked = !config.global; } @@ -694,25 +664,69 @@ namespace Shadowsocks.View UpdateSystemProxyItemsEnabledStatus(config); } - private void ShareOverLANItem_Click(object sender, EventArgs e) - { - ShareOverLANItem.Checked = !ShareOverLANItem.Checked; - controller.ToggleShareOverLAN(ShareOverLANItem.Checked); - } + #endregion - private void EditPACFileItem_Click(object sender, EventArgs e) - { - controller.TouchPACFile(); - } + #region Server - private async void UpdatePACFromGeositeItem_Click(object sender, EventArgs e) + private void UpdateServersMenu() { - await GeositeUpdater.UpdatePACFromGeosite(); - } + var items = ServersItem.DropDownItems; + while (items[0] != SeperatorItem) + { + items.RemoveAt(0); + } + int strategyCount = 0; + foreach (var strategy in controller.GetStrategies()) + { + if (!items.OfType().Any(ts => ts.Text == strategy.Name)) + { + ToolStripMenuItem item = new ToolStripMenuItem(strategy.Name); + item.Tag = strategy.ID; + item.Click += AStrategyItem_Click; + items.Add(item); + strategyCount++; + } + } + if (!items.OfType().Any(ts => ts.Tag?.ToString() == "-server-")) + { + // user wants a seperator item between strategy and servers menugroup + items.Add(new ToolStripSeparator() { Tag = "-server-" }); + } + int serverCount = 0; + Configuration configuration = controller.GetConfigurationCopy(); + foreach (var server in configuration.configs) + { + if (Configuration.ChecksServer(server)) + { + var name = server.ToString(); + if (!items.OfType().Any(ts => ts.Text == name)) + { + ToolStripMenuItem item = new ToolStripMenuItem(name); + item.Tag = configuration.configs.FindIndex(s => s == server); + item.Click += AServerItem_Click; + items.Add(item); + serverCount++; + } + } + } - private void EditUserRuleFileForGeositeItem_Click(object sender, EventArgs e) - { - controller.TouchUserRuleFile(); + foreach (var item in items) + { + var menuItem = item as ToolStripMenuItem; + if (menuItem == null || menuItem.Tag == null) continue; + + if ( + menuItem.Tag.ToString() == configuration.index.ToString() + || menuItem.Tag.ToString() == configuration.strategy + ) + { + menuItem.Checked = true; + } + else + { + menuItem.Checked = false; + } + } } private void AServerItem_Click(object sender, EventArgs e) @@ -727,21 +741,19 @@ namespace Shadowsocks.View controller.SelectStrategy((string)item.Tag); } - private void VerboseLoggingToggleItem_Click(object sender, EventArgs e) + private void Config_Click(object sender, EventArgs e) { - VerboseLoggingToggleItem.Checked = !VerboseLoggingToggleItem.Checked; - controller.ToggleVerboseLogging(VerboseLoggingToggleItem.Checked); + ShowConfigForm(); } - private void ShowPluginOutputToggleItem_Click(object sender, EventArgs e) + void splash_FormClosed(object sender, FormClosedEventArgs e) { - ShowPluginOutputToggleItem.Checked = !ShowPluginOutputToggleItem.Checked; - controller.ToggleShowPluginOutput(ShowPluginOutputToggleItem.Checked); + ShowConfigForm(); } - private void WriteI18NFileItem_Click(object sender, EventArgs e) + void openURLFromQRCode(object sender, FormClosedEventArgs e) { - File.WriteAllText(I18N.I18N_FILE, Resources.i18n_csv, Encoding.UTF8); + Utils.OpenInBrowser(_urlToOpen); } private void StatisticsConfigItem_Click(object sender, EventArgs e) @@ -850,34 +862,9 @@ namespace Shadowsocks.View } } - void splash_FormClosed(object sender, FormClosedEventArgs e) - { - ShowConfigForm(); - } - - void openURLFromQRCode(object sender, FormClosedEventArgs e) - { - Utils.OpenInBrowser(_urlToOpen); - } + #endregion - 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")); - } - LoadCurrentConfiguration(); - } - private void ProtocolHandlerItem_Click(object sender, EventArgs e) - { - ProtocolHandlerItem.Checked = !ProtocolHandlerItem.Checked; - if (!ProtocolHandler.Set(ProtocolHandlerItem.Checked)) - { - MessageBox.Show(I18N.GetString("Failed to update registry")); - } - LoadCurrentConfiguration(); - } + #region PAC private void LocalPACItem_Click(object sender, EventArgs e) { @@ -911,17 +898,10 @@ namespace Shadowsocks.View private void UpdateOnlinePACURLItem_Click(object sender, EventArgs e) { string origPacUrl = controller.GetConfigurationCopy().pacUrl; -#if NET472 - string pacUrl = Microsoft.VisualBasic.Interaction.InputBox( - I18N.GetString("Please input PAC Url"), - I18N.GetString("Edit Online PAC URL"), - origPacUrl, -1, -1); -#else string pacUrl = ViewUtils.InputBox( I18N.GetString("Please input PAC Url"), I18N.GetString("Edit Online PAC URL"), origPacUrl, -1, -1); -#endif if (!pacUrl.IsNullOrEmpty() && pacUrl != origPacUrl) { controller.SavePACUrl(pacUrl); @@ -958,6 +938,95 @@ namespace Shadowsocks.View } + private void EditPACFileItem_Click(object sender, EventArgs e) + { + controller.TouchPACFile(); + } + + private async void UpdatePACFromGeositeItem_Click(object sender, EventArgs e) + { + await GeositeUpdater.UpdatePACFromGeosite(); + } + + private void EditUserRuleFileForGeositeItem_Click(object sender, EventArgs e) + { + controller.TouchUserRuleFile(); + } + + void controller_FileReadyToOpen(object sender, ShadowsocksController.PathEventArgs e) + { + string argument = @"/select, " + e.Path; + + Process.Start("explorer.exe", argument); + } + + void controller_UpdatePACFromGeositeError(object sender, System.IO.ErrorEventArgs e) + { + ShowBalloonTip(I18N.GetString("Failed to update PAC file"), e.GetException().Message, ToolTipIcon.Error, 5000); + logger.LogUsefulException(e.GetException()); + } + + void controller_UpdatePACFromGeositeCompleted(object sender, GeositeResultEventArgs e) + { + string result = e.Success + ? I18N.GetString("PAC updated") + : I18N.GetString("No updates found. Please report to Geosite if you have problems with it."); + ShowBalloonTip(I18N.GetString("Shadowsocks"), result, ToolTipIcon.Info, 1000); + } + + #endregion + + #region Help + + void controller_VerboseLoggingStatusChanged(object sender, EventArgs e) + { + VerboseLoggingToggleItem.Checked = controller.GetConfigurationCopy().isVerboseLogging; + } + + void controller_ShowPluginOutputChanged(object sender, EventArgs e) + { + ShowPluginOutputToggleItem.Checked = controller.GetConfigurationCopy().showPluginOutput; + } + + private void VerboseLoggingToggleItem_Click(object sender, EventArgs e) + { + VerboseLoggingToggleItem.Checked = !VerboseLoggingToggleItem.Checked; + controller.ToggleVerboseLogging(VerboseLoggingToggleItem.Checked); + } + + private void ShowLogItem_Click(object sender, EventArgs e) + { + ShowLogForm(); + } + + private void ShowPluginOutputToggleItem_Click(object sender, EventArgs e) + { + ShowPluginOutputToggleItem.Checked = !ShowPluginOutputToggleItem.Checked; + controller.ToggleShowPluginOutput(ShowPluginOutputToggleItem.Checked); + } + + private void WriteI18NFileItem_Click(object sender, EventArgs e) + { + File.WriteAllText(I18N.I18N_FILE, Resources.i18n_csv, Encoding.UTF8); + } + + #endregion + + #region Update + + void updateChecker_CheckUpdateCompleted(object sender, EventArgs e) + { + if (updateChecker.NewVersionFound) + { + ShowBalloonTip(I18N.GetString("Shadowsocks {0} Update Found", updateChecker.LatestVersionNumber + updateChecker.LatestVersionSuffix), I18N.GetString("Click here to update"), ToolTipIcon.Info, 5000); + } + else if (!_isStartupChecking) + { + ShowBalloonTip(I18N.GetString("Shadowsocks"), I18N.GetString("No update is available"), ToolTipIcon.Info, 5000); + } + _isStartupChecking = false; + } + private void UpdateUpdateMenu() { Configuration configuration = controller.GetConfigurationCopy(); @@ -984,24 +1053,11 @@ namespace Shadowsocks.View updateChecker.CheckUpdate(controller.GetConfigurationCopy()); } - private void proxyItem_Click(object sender, EventArgs e) - { - ShowProxyForm(); - } - - private void hotKeyItem_Click(object sender, EventArgs e) - { - ShowHotKeySettingsForm(); - } - - private void ShowLogItem_Click(object sender, EventArgs e) + private void AboutItem_Click(object sender, EventArgs e) { - ShowLogForm(); + Utils.OpenInBrowser("https://github.com/shadowsocks/shadowsocks-windows"); } - public void ShowLogForm_HotKey() - { - ShowLogForm(); - } + #endregion } } diff --git a/shadowsocks-csharp/View/OnlineConfigForm.Designer.cs b/shadowsocks-csharp/View/OnlineConfigForm.Designer.cs new file mode 100644 index 00000000..d9787dde --- /dev/null +++ b/shadowsocks-csharp/View/OnlineConfigForm.Designer.cs @@ -0,0 +1,218 @@ +namespace Shadowsocks.View +{ + partial class OnlineConfigForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.UrlListBox = new System.Windows.Forms.ListBox(); + this.label1 = new System.Windows.Forms.Label(); + this.UrlTextBox = new System.Windows.Forms.TextBox(); + this.UpdateButton = new System.Windows.Forms.Button(); + this.AddButton = new System.Windows.Forms.Button(); + this.DeleteButton = new System.Windows.Forms.Button(); + this.OkButton = new System.Windows.Forms.Button(); + this.UpdateAllButton = new System.Windows.Forms.Button(); + this.CancelButton = new System.Windows.Forms.Button(); + this.tableLayoutPanel1.SuspendLayout(); + this.SuspendLayout(); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 3; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); + this.tableLayoutPanel1.Controls.Add(this.UrlListBox, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.label1, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.UrlTextBox, 1, 1); + this.tableLayoutPanel1.Controls.Add(this.UpdateButton, 0, 2); + this.tableLayoutPanel1.Controls.Add(this.AddButton, 1, 2); + this.tableLayoutPanel1.Controls.Add(this.DeleteButton, 2, 2); + this.tableLayoutPanel1.Controls.Add(this.OkButton, 1, 3); + this.tableLayoutPanel1.Controls.Add(this.UpdateAllButton, 0, 3); + this.tableLayoutPanel1.Controls.Add(this.CancelButton, 2, 3); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(3); + this.tableLayoutPanel1.RowCount = 4; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.Size = new System.Drawing.Size(482, 453); + this.tableLayoutPanel1.TabIndex = 0; + // + // UrlListBox + // + this.tableLayoutPanel1.SetColumnSpan(this.UrlListBox, 3); + this.UrlListBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.UrlListBox.FormattingEnabled = true; + this.UrlListBox.ItemHeight = 15; + this.UrlListBox.Location = new System.Drawing.Point(13, 13); + this.UrlListBox.Margin = new System.Windows.Forms.Padding(10); + this.UrlListBox.Name = "UrlListBox"; + this.UrlListBox.Size = new System.Drawing.Size(456, 334); + this.UrlListBox.TabIndex = 0; + this.UrlListBox.SelectedIndexChanged += new System.EventHandler(this.UrlListBox_SelectedIndexChanged); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Dock = System.Windows.Forms.DockStyle.Fill; + this.label1.Location = new System.Drawing.Point(6, 357); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(152, 31); + this.label1.TabIndex = 1; + this.label1.Text = "Online config URL"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // UrlTextBox + // + this.tableLayoutPanel1.SetColumnSpan(this.UrlTextBox, 2); + this.UrlTextBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.UrlTextBox.Location = new System.Drawing.Point(164, 360); + this.UrlTextBox.Margin = new System.Windows.Forms.Padding(3, 3, 15, 3); + this.UrlTextBox.Name = "UrlTextBox"; + this.UrlTextBox.Size = new System.Drawing.Size(300, 25); + this.UrlTextBox.TabIndex = 2; + // + // UpdateButton + // + this.UpdateButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.UpdateButton.Location = new System.Drawing.Point(23, 391); + this.UpdateButton.Margin = new System.Windows.Forms.Padding(20, 3, 20, 3); + this.UpdateButton.MaximumSize = new System.Drawing.Size(0, 25); + this.UpdateButton.MinimumSize = new System.Drawing.Size(0, 25); + this.UpdateButton.Name = "UpdateButton"; + this.UpdateButton.Size = new System.Drawing.Size(118, 25); + this.UpdateButton.TabIndex = 3; + this.UpdateButton.Text = "&Update"; + this.UpdateButton.UseVisualStyleBackColor = true; + this.UpdateButton.Click += new System.EventHandler(this.UpdateButton_Click); + // + // AddButton + // + this.AddButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.AddButton.Location = new System.Drawing.Point(181, 391); + this.AddButton.Margin = new System.Windows.Forms.Padding(20, 3, 20, 3); + this.AddButton.MaximumSize = new System.Drawing.Size(0, 25); + this.AddButton.MinimumSize = new System.Drawing.Size(0, 25); + this.AddButton.Name = "AddButton"; + this.AddButton.Size = new System.Drawing.Size(118, 25); + this.AddButton.TabIndex = 4; + this.AddButton.Text = "&Add"; + this.AddButton.UseVisualStyleBackColor = true; + this.AddButton.Click += new System.EventHandler(this.AddButton_Click); + // + // DeleteButton + // + this.DeleteButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.DeleteButton.Location = new System.Drawing.Point(339, 391); + this.DeleteButton.Margin = new System.Windows.Forms.Padding(20, 3, 20, 3); + this.DeleteButton.MaximumSize = new System.Drawing.Size(0, 25); + this.DeleteButton.MinimumSize = new System.Drawing.Size(0, 25); + this.DeleteButton.Name = "DeleteButton"; + this.DeleteButton.Size = new System.Drawing.Size(120, 25); + this.DeleteButton.TabIndex = 5; + this.DeleteButton.Text = "&Delete"; + this.DeleteButton.UseVisualStyleBackColor = true; + this.DeleteButton.Click += new System.EventHandler(this.DeleteButton_Click); + // + // OkButton + // + this.OkButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.OkButton.Location = new System.Drawing.Point(181, 422); + this.OkButton.Margin = new System.Windows.Forms.Padding(20, 3, 20, 3); + this.OkButton.MaximumSize = new System.Drawing.Size(0, 25); + this.OkButton.MinimumSize = new System.Drawing.Size(0, 25); + this.OkButton.Name = "OkButton"; + this.OkButton.Size = new System.Drawing.Size(118, 25); + this.OkButton.TabIndex = 7; + this.OkButton.Text = "OK"; + this.OkButton.UseVisualStyleBackColor = true; + this.OkButton.Click += new System.EventHandler(this.OkButton_Click); + // + // UpdateAllButton + // + this.UpdateAllButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.UpdateAllButton.Location = new System.Drawing.Point(23, 422); + this.UpdateAllButton.Margin = new System.Windows.Forms.Padding(20, 3, 20, 3); + this.UpdateAllButton.MaximumSize = new System.Drawing.Size(0, 25); + this.UpdateAllButton.MinimumSize = new System.Drawing.Size(0, 25); + this.UpdateAllButton.Name = "UpdateAllButton"; + this.UpdateAllButton.Size = new System.Drawing.Size(118, 25); + this.UpdateAllButton.TabIndex = 6; + this.UpdateAllButton.Text = "U&pdate All"; + this.UpdateAllButton.UseVisualStyleBackColor = true; + this.UpdateAllButton.Click += new System.EventHandler(this.UpdateAllButton_Click); + // + // CancelButton + // + this.CancelButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.CancelButton.Location = new System.Drawing.Point(339, 422); + this.CancelButton.Margin = new System.Windows.Forms.Padding(20, 3, 20, 3); + this.CancelButton.MaximumSize = new System.Drawing.Size(0, 25); + this.CancelButton.MinimumSize = new System.Drawing.Size(0, 25); + this.CancelButton.Name = "CancelButton"; + this.CancelButton.Size = new System.Drawing.Size(120, 25); + this.CancelButton.TabIndex = 8; + this.CancelButton.Text = "Cancel"; + this.CancelButton.UseVisualStyleBackColor = true; + this.CancelButton.Click += new System.EventHandler(this.CancelButton_Click); + // + // OnlineConfigForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(482, 453); + this.Controls.Add(this.tableLayoutPanel1); + this.MinimizeBox = false; + this.MinimumSize = new System.Drawing.Size(400, 400); + this.Name = "OnlineConfigForm"; + this.Text = "Online config"; + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.ListBox UrlListBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox UrlTextBox; + private System.Windows.Forms.Button UpdateButton; + private System.Windows.Forms.Button AddButton; + private System.Windows.Forms.Button DeleteButton; + private System.Windows.Forms.Button OkButton; + private System.Windows.Forms.Button UpdateAllButton; + private System.Windows.Forms.Button CancelButton; + } +} \ No newline at end of file diff --git a/shadowsocks-csharp/View/OnlineConfigForm.cs b/shadowsocks-csharp/View/OnlineConfigForm.cs new file mode 100644 index 00000000..fca0ed57 --- /dev/null +++ b/shadowsocks-csharp/View/OnlineConfigForm.cs @@ -0,0 +1,153 @@ +using System; +using System.Data; +using System.Linq; +using System.Windows.Forms; +using Shadowsocks.Controller; +using Shadowsocks.Model; +using Shadowsocks.Properties; + +namespace Shadowsocks.View +{ + public partial class OnlineConfigForm : Form + { + private ShadowsocksController controller; + private Configuration config; + + public OnlineConfigForm(ShadowsocksController controller) + { + this.controller = controller; + InitializeComponent(); + LoadConfig(); + Icon = System.Drawing.Icon.FromHandle(Resources.ssw128.GetHicon()); + I18N.TranslateForm(this); + } + + private void LoadConfig() + { + config = controller.GetConfigurationCopy(); + var idx = UrlListBox.SelectedIndex; + UrlListBox.Items.Clear(); + + foreach (var item in config.onlineConfigSource) + { + UrlListBox.Items.Add(item); + } + + if (idx >= UrlListBox.Items.Count) idx = 0; + if (idx < 0 && UrlListBox.Items.Count > 0) idx = 0; + if (UrlListBox.Items.Count == 0) return; + UrlListBox.SelectedIndex = idx; + SelectItem(); + } + + private void SelectItem() + { + UrlTextBox.Text = (string)UrlListBox.SelectedItem; + } + + private bool ValidateUrl() + { + try + { + var scheme = new Uri(UrlTextBox.Text).Scheme; + if (scheme != "http" && scheme != "https") return false; + if (UrlListBox.Items.OfType().Contains(UrlTextBox.Text)) return false; + } + catch + { + return false; + } + return true; + } + + private void Commit() + { + if (UrlListBox.SelectedIndex < 0) return; + if ((string)UrlListBox.SelectedItem == UrlTextBox.Text) + { + LoadConfig(); + return; + } + + if (ValidateUrl()) + { + + UrlListBox.Items[UrlListBox.SelectedIndex] = UrlTextBox.Text; + } + controller.SaveOnlineConfigSource(UrlListBox.Items.OfType().Where(s => !string.IsNullOrWhiteSpace(s)).Distinct()); + LoadConfig(); + return; + } + + private void AddButton_Click(object sender, EventArgs e) + { + if (string.IsNullOrWhiteSpace(UrlTextBox.Text)) return; + UrlListBox.Items.Add(UrlTextBox.Text); + UrlListBox.SelectedIndex = UrlListBox.Items.Count - 1; + UrlTextBox.Text = ""; + Commit(); + } + + private async void UpdateButton_Click(object sender, EventArgs e) + { + string old = (string)UrlListBox.SelectedItem; + // update content, also update online config + Commit(); + string current = (string)UrlListBox.SelectedItem; + if (UrlListBox.Items.Count == 0) return; + tableLayoutPanel1.Enabled = false; + bool ok = await controller.UpdateOnlineConfig(current); + if (!ok) + { + MessageBox.Show(I18N.GetString("online config failed to update")); + tableLayoutPanel1.Enabled = true; + return; + } + if (old != current) controller.RemoveOnlineConfig(old); + tableLayoutPanel1.Enabled = true; + } + + private void UrlListBox_SelectedIndexChanged(object sender, EventArgs e) + { + if (!UrlListBox.CanSelect) + { + return; + } + SelectItem(); + } + + private void DeleteButton_Click(object sender, EventArgs e) + { + if (UrlListBox.Items.Count == 0) return; + string url = (string)UrlListBox.SelectedItem; + if (!string.IsNullOrWhiteSpace(url)) + { + controller.RemoveOnlineConfig(url); + } + LoadConfig(); + } + + private async void UpdateAllButton_Click(object sender, EventArgs e) + { + if (UrlListBox.Items.Count == 0) return; + tableLayoutPanel1.Enabled = false; + int fail = await controller.UpdateAllOnlineConfig(); + if (fail > 0) + { + MessageBox.Show(I18N.GetString("{0} online config failed to update", fail)); + } + tableLayoutPanel1.Enabled = true; + } + + private void OkButton_Click(object sender, EventArgs e) + { + Commit(); + Close(); + } + + private void CancelButton_Click(object sender, EventArgs e) + { + Close(); + } + } +} diff --git a/shadowsocks-csharp/View/OnlineConfigForm.resx b/shadowsocks-csharp/View/OnlineConfigForm.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/shadowsocks-csharp/View/OnlineConfigForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.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