Browse Source

port sip008 to v5/master

pull/2980/head
Student Main 4 years ago
parent
commit
637937ff05
No known key found for this signature in database GPG Key ID: AA78519C208C8742
14 changed files with 1553 additions and 846 deletions
  1. +80
    -0
      shadowsocks-csharp/Controller/Service/OnlineConfigResolver.cs
  2. +360
    -261
      shadowsocks-csharp/Controller/ShadowsocksController.cs
  3. +8
    -0
      shadowsocks-csharp/Data/i18n.csv
  4. +71
    -37
      shadowsocks-csharp/Model/Configuration.cs
  5. +4
    -0
      shadowsocks-csharp/Model/Server.cs
  6. +9
    -2
      shadowsocks-csharp/Program.cs
  7. +165
    -235
      shadowsocks-csharp/View/ConfigForm.Designer.cs
  8. +3
    -3
      shadowsocks-csharp/View/ConfigForm.cs
  9. +3
    -0
      shadowsocks-csharp/View/ConfigForm.resx
  10. +32
    -37
      shadowsocks-csharp/View/HotkeySettingsForm.designer.cs
  11. +327
    -271
      shadowsocks-csharp/View/MenuViewController.cs
  12. +218
    -0
      shadowsocks-csharp/View/OnlineConfigForm.Designer.cs
  13. +153
    -0
      shadowsocks-csharp/View/OnlineConfigForm.cs
  14. +120
    -0
      shadowsocks-csharp/View/OnlineConfigForm.resx

+ 80
- 0
shadowsocks-csharp/Controller/Service/OnlineConfigResolver.cs View File

@@ -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<List<Server>> 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<Server> EMPTY_SERVERS = Array.Empty<Server>();

internal static IEnumerable<Server> GetServers(this string json) =>
JToken.Parse(json).SearchJToken().AsEnumerable();

private static IEnumerable<Server> SearchJArray(JArray array) =>
array == null ? EMPTY_SERVERS : array.SelectMany(SearchJToken).ToList();

private static IEnumerable<Server> SearchJObject(JObject obj)
{
if (obj == null)
return EMPTY_SERVERS;

if (BASIC_FORMAT.All(field => obj.ContainsKey(field)))
return new[] { obj.ToObject<Server>() };

var servers = new List<Server>();
foreach (var kv in obj)
{
var token = kv.Value;
servers.AddRange(SearchJToken(token));
}
return servers;
}

private static IEnumerable<Server> SearchJToken(this JToken token)
{
switch (token.Type)
{
default:
return Array.Empty<Server>();
case JTokenType.Object:
return SearchJObject(token as JObject);
case JTokenType.Array:
return SearchJArray(token as JArray);
}
}
}
}

+ 360
- 261
shadowsocks-csharp/Controller/ShadowsocksController.cs View File

@@ -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<UpdatedEventArgs> 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<IStreamService>
{
tcpRelay,
_pacServer,
new PortForwarder(privoxyRunner.RunningPort),
});
_tcpListener.Start();
_udpListener = new UDPListener(_config, new List<IDatagramService>
{
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<IStrategy> 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<Server> 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<char> 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<IStrategy> 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<IStreamService>
{
tcpRelay,
_pacServer,
new PortForwarder(privoxyRunner.RunningPort),
});
_tcpListener.Start();
_udpListener = new UDPListener(_config, new List<IDatagramService>
{
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<char> 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<int> 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<bool> 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<int> 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<string> 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
}
}

+ 8
- 0
shadowsocks-csharp/Data/i18n.csv View File

@@ -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


+ 71
- 37
shadowsocks-csharp/Model/Configuration.cs View File

@@ -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<Server> configs;
public List<string> 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<Server>();
onlineConfigSource = new List<string>();
}
[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<Server>();
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<Server>()
{
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<Server> SortByOnlineConfig(IEnumerable<Server> servers)
{
var groups = servers.GroupBy(s => s.group);
List<Server> ret = new List<Server>();
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)


+ 4
- 0
shadowsocks-csharp/Model/Server.cs View File

@@ -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()


+ 9
- 2
shadowsocks-csharp/Program.cs View File

@@ -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();


+ 165
- 235
shadowsocks-csharp/View/ConfigForm.Designer.cs View File

@@ -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;
}
}

+ 3
- 3
shadowsocks-csharp/View/ConfigForm.cs View File

@@ -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;
}


+ 3
- 0
shadowsocks-csharp/View/ConfigForm.resx View File

@@ -120,4 +120,7 @@
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

+ 32
- 37
shadowsocks-csharp/View/HotkeySettingsForm.designer.cs View File

@@ -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;


+ 327
- 271
shadowsocks-csharp/View/MenuViewController.cs View File

@@ -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<ToolStripItem>().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<ToolStripSeparator>().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<ToolStripMenuItem>().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<ToolStripItem>().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<ToolStripSeparator>().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<ToolStripMenuItem>().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
}
}

+ 218
- 0
shadowsocks-csharp/View/OnlineConfigForm.Designer.cs View File

@@ -0,0 +1,218 @@
namespace Shadowsocks.View
{
partial class OnlineConfigForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}

#region Windows Form Designer generated code

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

+ 153
- 0
shadowsocks-csharp/View/OnlineConfigForm.cs View File

@@ -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<string>().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<string>().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();
}
}
}

+ 120
- 0
shadowsocks-csharp/View/OnlineConfigForm.resx View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

Loading…
Cancel
Save