Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08f06f7177 | ||
|
|
cb3afafd54 | ||
|
|
05df449826 | ||
|
|
d0e692a491 | ||
|
|
b0a2c2735b | ||
|
|
f239244af2 | ||
|
|
a316b95f45 | ||
|
|
cf5de91acb | ||
|
|
71120e5c3e | ||
|
|
caa96ad334 | ||
|
|
f04b497d79 | ||
|
|
ed31a3cab0 | ||
|
|
081bbaf011 | ||
|
|
0251130fa5 | ||
|
|
f0b196c8c3 | ||
|
|
057b148092 | ||
|
|
101c33d0f1 | ||
|
|
bbfc5d332d | ||
|
|
5d75e19c26 | ||
|
|
816651ebdc | ||
|
|
44afefed71 | ||
|
|
2eeebc29d7 | ||
|
|
0e01f8303c | ||
|
|
2fcf843bba | ||
|
|
3b3a8c9077 |
@@ -1,3 +1,19 @@
|
||||
4.0.6 2017-09-09
|
||||
- SIP002 support
|
||||
- SIP003 support
|
||||
|
||||
4.0.5 2017-08-09
|
||||
- Fix crash when user-wininet.json fail to parse. (#1178)
|
||||
- Bug fixes and improvements.
|
||||
|
||||
4.0.4 2017-06-01
|
||||
- Save user wininet settings as user-wininet.json
|
||||
- Improve performance of aes-256-gcm
|
||||
|
||||
4.0.2 2017-05-19
|
||||
- Fix legacy key derivation
|
||||
- Bug fixes and improvements
|
||||
|
||||
4.0.1 2017-04-08
|
||||
- Fix UDP relay
|
||||
- Allow to add multiple servers via Shadowsocks URL
|
||||
|
||||
@@ -13,11 +13,16 @@ Shadowsocks for Windows
|
||||
4. Supports HTTP proxy
|
||||
5. Supports server auto switching
|
||||
6. Supports UDP relay (see Usage)
|
||||
7. Supports plugins
|
||||
|
||||
#### Download
|
||||
|
||||
Download the [latest release].
|
||||
|
||||
#### Requirements
|
||||
|
||||
Microsoft [.NET Framework 4.6.2] or higher.
|
||||
|
||||
#### Basic
|
||||
|
||||
1. Find Shadowsocks icon in the notification tray
|
||||
@@ -54,11 +59,17 @@ If you want to manage multiple servers using other tools like SwitchyOmega,
|
||||
you can start multiple Shadowsocks instances. To avoid configuration conflicts,
|
||||
copy Shadowsocks to a new directory and choose a different local port.
|
||||
|
||||
#### Plugins
|
||||
|
||||
If you would like to connect to server via a plugin, please set the plugin's
|
||||
path (relative or absolute) on Edit Servers form.
|
||||
Note: Forward Proxy will not be used while a plugin is enabled.
|
||||
|
||||
#### Global hotkeys
|
||||
|
||||
Hotkeys are NOT registered automatically. You should re-register all hotkeys after
|
||||
restarting Shadowsocks. If you are using multiple instances of Shadowsocks,
|
||||
you must set different key combination for other instances.
|
||||
you must set different key combination for each instance.
|
||||
|
||||
##### How to input?
|
||||
|
||||
@@ -98,11 +109,12 @@ Please visit [Servers] for more information.
|
||||
GPLv3
|
||||
|
||||
|
||||
[Appveyor]: https://ci.appveyor.com/project/wongsyrone/shadowsocks-windows-yqdou
|
||||
[Build Status]: https://ci.appveyor.com/api/projects/status/yieb7lo96irmuc28/branch/master?svg=true
|
||||
[Appveyor]: https://ci.appveyor.com/project/celeron533/shadowsocks-windows
|
||||
[Build Status]: https://ci.appveyor.com/api/projects/status/tfw57q6eecippsl5/branch/master?svg=true
|
||||
[latest release]: https://github.com/shadowsocks/shadowsocks-csharp/releases
|
||||
[GFWList]: https://github.com/gfwlist/gfwlist
|
||||
[Servers]: https://github.com/shadowsocks/shadowsocks/wiki/Ports-and-Clients#linux--server-side
|
||||
[中文说明]: https://github.com/shadowsocks/shadowsocks-windows/wiki/Shadowsocks-Windows-%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E
|
||||
[.NET Framework 4.6.2]: https://www.microsoft.com/en-US/download/details.aspx?id=53344
|
||||
[Visual Studio 2015]: https://www.visualstudio.com/downloads/
|
||||
[.NET Framework 4.6.2 Developer Pack]: https://www.microsoft.com/download/details.aspx?id=53321
|
||||
[.NET Framework 4.6.2 Developer Pack]: https://www.microsoft.com/download/details.aspx?id=53321
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Reflection;
|
||||
using Shadowsocks.Model;
|
||||
using Shadowsocks.Util.ProcessManagement;
|
||||
|
||||
namespace Shadowsocks.Controller.Service
|
||||
{
|
||||
// https://github.com/shadowsocks/shadowsocks-org/wiki/Plugin
|
||||
public sealed class Sip003Plugin : IDisposable
|
||||
{
|
||||
public IPEndPoint LocalEndPoint { get; private set; }
|
||||
public int ProcessId => _started ? _pluginProcess.Id : 0;
|
||||
|
||||
private readonly object _startProcessLock = new object();
|
||||
private readonly Job _pluginJob;
|
||||
private readonly Process _pluginProcess;
|
||||
private bool _started;
|
||||
private bool _disposed;
|
||||
|
||||
public static Sip003Plugin CreateIfConfigured(Server server)
|
||||
{
|
||||
if (server == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(server));
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(server.plugin))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Sip003Plugin(server.plugin, server.plugin_opts, server.server, server.server_port);
|
||||
}
|
||||
|
||||
private Sip003Plugin(string plugin, string pluginOpts, string serverAddress, int serverPort)
|
||||
{
|
||||
if (plugin == null) throw new ArgumentNullException(nameof(plugin));
|
||||
if (string.IsNullOrWhiteSpace(serverAddress))
|
||||
{
|
||||
throw new ArgumentException("Value cannot be null or whitespace.", nameof(serverAddress));
|
||||
}
|
||||
if ((ushort)serverPort != serverPort)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("serverPort");
|
||||
}
|
||||
|
||||
var appPath = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().GetName().CodeBase).LocalPath);
|
||||
|
||||
_pluginProcess = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = plugin,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
ErrorDialog = false,
|
||||
WindowStyle = ProcessWindowStyle.Hidden,
|
||||
WorkingDirectory = appPath ?? Environment.CurrentDirectory,
|
||||
Environment =
|
||||
{
|
||||
["SS_REMOTE_HOST"] = serverAddress,
|
||||
["SS_REMOTE_PORT"] = serverPort.ToString(),
|
||||
["SS_PLUGIN_OPTIONS"] = pluginOpts
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_pluginJob = new Job();
|
||||
}
|
||||
|
||||
public bool StartIfNeeded()
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
throw new ObjectDisposedException(GetType().FullName);
|
||||
}
|
||||
|
||||
lock (_startProcessLock)
|
||||
{
|
||||
if (_started && !_pluginProcess.HasExited)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var localPort = GetNextFreeTcpPort();
|
||||
LocalEndPoint = new IPEndPoint(IPAddress.Loopback, localPort);
|
||||
|
||||
_pluginProcess.StartInfo.Environment["SS_LOCAL_HOST"] = LocalEndPoint.Address.ToString();
|
||||
_pluginProcess.StartInfo.Environment["SS_LOCAL_PORT"] = LocalEndPoint.Port.ToString();
|
||||
_pluginProcess.Start();
|
||||
_pluginJob.AddProcess(_pluginProcess.Handle);
|
||||
_started = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int GetNextFreeTcpPort()
|
||||
{
|
||||
var l = new TcpListener(IPAddress.Loopback, 0);
|
||||
l.Start();
|
||||
int port = ((IPEndPoint)l.LocalEndpoint).Port;
|
||||
l.Stop();
|
||||
return port;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (!_pluginProcess.HasExited)
|
||||
{
|
||||
_pluginProcess.Kill();
|
||||
_pluginProcess.WaitForExit();
|
||||
}
|
||||
}
|
||||
catch (Exception) { }
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
_pluginProcess.Dispose();
|
||||
_pluginJob.Dispose();
|
||||
}
|
||||
catch (Exception) { }
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -570,7 +570,15 @@ namespace Shadowsocks.Controller
|
||||
// Setting up proxy
|
||||
IProxy remote;
|
||||
EndPoint proxyEP = null;
|
||||
if (_config.proxy.useProxy)
|
||||
EndPoint serverEP = SocketUtil.GetEndPoint(_server.server, _server.server_port);
|
||||
EndPoint pluginEP = _controller.GetPluginLocalEndPointIfConfigured(_server);
|
||||
|
||||
if (pluginEP != null)
|
||||
{
|
||||
serverEP = pluginEP;
|
||||
remote = new DirectConnect();
|
||||
}
|
||||
else if (_config.proxy.useProxy)
|
||||
{
|
||||
switch (_config.proxy.proxyType)
|
||||
{
|
||||
@@ -607,7 +615,7 @@ namespace Shadowsocks.Controller
|
||||
proxyTimer.Enabled = true;
|
||||
|
||||
proxyTimer.Session = session;
|
||||
proxyTimer.DestEndPoint = SocketUtil.GetEndPoint(_server.server, _server.server_port);
|
||||
proxyTimer.DestEndPoint = serverEP;
|
||||
proxyTimer.Server = _server;
|
||||
|
||||
_proxyConnected = false;
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Shadowsocks.Controller
|
||||
public string LatestVersionLocalName;
|
||||
public event EventHandler CheckUpdateCompleted;
|
||||
|
||||
public const string Version = "4.0.1";
|
||||
public const string Version = "4.0.6";
|
||||
|
||||
private class CheckUpdateTimer : System.Timers.Timer
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
@@ -14,6 +15,8 @@ using Shadowsocks.Model;
|
||||
using Shadowsocks.Properties;
|
||||
using Shadowsocks.Util;
|
||||
using System.Linq;
|
||||
using Shadowsocks.Controller.Service;
|
||||
using Shadowsocks.Proxy;
|
||||
|
||||
namespace Shadowsocks.Controller
|
||||
{
|
||||
@@ -33,6 +36,8 @@ namespace Shadowsocks.Controller
|
||||
private StrategyManager _strategyManager;
|
||||
private PrivoxyRunner privoxyRunner;
|
||||
private GFWListUpdater gfwListUpdater;
|
||||
private readonly ConcurrentDictionary<Server, Sip003Plugin> _pluginsByServer;
|
||||
|
||||
public AvailabilityStatistics availabilityStatistics = AvailabilityStatistics.Instance;
|
||||
public StatisticsStrategyConfiguration StatisticsConfiguration { get; private set; }
|
||||
|
||||
@@ -44,8 +49,6 @@ namespace Shadowsocks.Controller
|
||||
|
||||
private bool stopped = false;
|
||||
|
||||
private bool _systemProxyIsDirty = false;
|
||||
|
||||
public class PathEventArgs : EventArgs
|
||||
{
|
||||
public string Path;
|
||||
@@ -81,6 +84,7 @@ namespace Shadowsocks.Controller
|
||||
_config = Configuration.Load();
|
||||
StatisticsConfiguration = StatisticsStrategyConfiguration.Load();
|
||||
_strategyManager = new StrategyManager(this);
|
||||
_pluginsByServer = new ConcurrentDictionary<Server, Sip003Plugin>();
|
||||
StartReleasingMemory();
|
||||
StartTrafficStatistics(61);
|
||||
}
|
||||
@@ -146,6 +150,31 @@ namespace Shadowsocks.Controller
|
||||
return GetCurrentServer();
|
||||
}
|
||||
|
||||
public EndPoint GetPluginLocalEndPointIfConfigured(Server server)
|
||||
{
|
||||
var plugin = _pluginsByServer.GetOrAdd(server, Sip003Plugin.CreateIfConfigured);
|
||||
if (plugin == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (plugin.StartIfNeeded())
|
||||
{
|
||||
Logging.Info(
|
||||
$"Started SIP003 plugin for {server.Identifier()} on {plugin.LocalEndPoint} - PID: {plugin.ProcessId}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Error("Failed to start SIP003 plugin: " + ex.Message);
|
||||
throw;
|
||||
}
|
||||
|
||||
return plugin.LocalEndPoint;
|
||||
}
|
||||
|
||||
public void SaveServers(List<Server> servers, int localPort)
|
||||
{
|
||||
_config.configs = servers;
|
||||
@@ -261,6 +290,7 @@ namespace Shadowsocks.Controller
|
||||
{
|
||||
_listener.Stop();
|
||||
}
|
||||
StopPlugins();
|
||||
if (privoxyRunner != null)
|
||||
{
|
||||
privoxyRunner.Stop();
|
||||
@@ -272,6 +302,15 @@ namespace Shadowsocks.Controller
|
||||
Encryption.RNG.Close();
|
||||
}
|
||||
|
||||
private void StopPlugins()
|
||||
{
|
||||
foreach (var serverAndPlugin in _pluginsByServer)
|
||||
{
|
||||
serverAndPlugin.Value?.Dispose();
|
||||
}
|
||||
_pluginsByServer.Clear();
|
||||
}
|
||||
|
||||
public void TouchPACFile()
|
||||
{
|
||||
string pacFilename = _pacServer.TouchPACFile();
|
||||
@@ -299,13 +338,41 @@ namespace Shadowsocks.Controller
|
||||
public static string GetQRCode(Server server)
|
||||
{
|
||||
string tag = string.Empty;
|
||||
string parts = $"{server.method}:{server.password}@{server.server}:{server.server_port}";
|
||||
string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts));
|
||||
if(!server.remarks.IsNullOrEmpty())
|
||||
string url = string.Empty;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(server.plugin))
|
||||
{
|
||||
// For backwards compatiblity, if no plugin, use old url format
|
||||
string parts = $"{server.method}:{server.password}@{server.server}:{server.server_port}";
|
||||
string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts));
|
||||
url = base64;
|
||||
}
|
||||
else
|
||||
{
|
||||
// SIP002
|
||||
string parts = $"{server.method}:{server.password}";
|
||||
string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts));
|
||||
string websafeBase64 = base64.Replace('+', '-').Replace('/', '_').TrimEnd('=');
|
||||
|
||||
string pluginPart = server.plugin;
|
||||
if (!string.IsNullOrWhiteSpace(server.plugin_opts))
|
||||
{
|
||||
pluginPart += ";" + server.plugin_opts;
|
||||
}
|
||||
|
||||
url = string.Format(
|
||||
"{0}@{1}:{2}/?plugin={3}",
|
||||
websafeBase64,
|
||||
HttpUtility.UrlEncode(server.server, Encoding.UTF8),
|
||||
server.server_port,
|
||||
HttpUtility.UrlEncode(pluginPart, Encoding.UTF8));
|
||||
}
|
||||
|
||||
if (!server.remarks.IsNullOrEmpty())
|
||||
{
|
||||
tag = $"#{HttpUtility.UrlEncode(server.remarks, Encoding.UTF8)}";
|
||||
}
|
||||
return $"ss://{base64}{tag}";
|
||||
return $"ss://{url}{tag}";
|
||||
}
|
||||
|
||||
public void UpdatePACFromGFWList()
|
||||
@@ -423,6 +490,8 @@ namespace Shadowsocks.Controller
|
||||
|
||||
protected void Reload()
|
||||
{
|
||||
StopPlugins();
|
||||
|
||||
Encryption.RNG.Reload();
|
||||
// some logic in configuration updated the config when saving, we need to read it again
|
||||
_config = Configuration.Load();
|
||||
@@ -465,6 +534,7 @@ namespace Shadowsocks.Controller
|
||||
strategy.ReloadServers();
|
||||
}
|
||||
|
||||
StartPlugins();
|
||||
privoxyRunner.Start(_config);
|
||||
|
||||
TCPRelay tcpRelay = new TCPRelay(this, _config);
|
||||
@@ -502,6 +572,15 @@ namespace Shadowsocks.Controller
|
||||
Utils.ReleaseMemory(true);
|
||||
}
|
||||
|
||||
private void StartPlugins()
|
||||
{
|
||||
foreach (var server in _config.configs)
|
||||
{
|
||||
// Early start plugin processes
|
||||
GetPluginLocalEndPointIfConfigured(server);
|
||||
}
|
||||
}
|
||||
|
||||
protected void SaveConfig(Configuration newConfig)
|
||||
{
|
||||
Configuration.Save(newConfig);
|
||||
@@ -510,20 +589,7 @@ namespace Shadowsocks.Controller
|
||||
|
||||
private void UpdateSystemProxy()
|
||||
{
|
||||
if (_config.enabled)
|
||||
{
|
||||
SystemProxy.Update(_config, false, _pacServer);
|
||||
_systemProxyIsDirty = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// only switch it off if we have switched it on
|
||||
if (_systemProxyIsDirty)
|
||||
{
|
||||
SystemProxy.Update(_config, false, _pacServer);
|
||||
_systemProxyIsDirty = false;
|
||||
}
|
||||
}
|
||||
SystemProxy.Update(_config, false, _pacServer);
|
||||
}
|
||||
|
||||
private void pacServer_PACFileChanged(object sender, EventArgs e)
|
||||
|
||||
@@ -4,40 +4,40 @@ Shadowsocks=Shadowsocks
|
||||
|
||||
# Menu items
|
||||
|
||||
Enable System Proxy=システムの代理を有効にする
|
||||
Enable System Proxy=システム プロキシを有効にする
|
||||
Mode=モード
|
||||
PAC=PAC
|
||||
Global=全般
|
||||
Servers=サーバ
|
||||
Edit Servers...=サーバーを編集する...
|
||||
Servers=サーバー
|
||||
Edit Servers...=サーバーの編集...
|
||||
Statistics Config...=統計情報の設定...
|
||||
Start on Boot=システムと同時に起動
|
||||
Forward Proxy...=代理を転送する...
|
||||
Allow Clients from LAN=LANからのクライアントを許可する
|
||||
Forward Proxy...=フォワードプロキシの設定...
|
||||
Allow Clients from LAN=LAN からのアクセスを許可
|
||||
Local PAC=ローカル PAC
|
||||
Online PAC=オンライン PAC
|
||||
Edit Local PAC File...=ローカル PAC ファイルを編集する...
|
||||
Update Local PAC from GFWList=GFWList から、ローカル PACを更新する
|
||||
Edit User Rule for GFWList...=利用者規則を編集する...
|
||||
Secure Local PAC=安全なローカル PAC
|
||||
Copy Local PAC URL=ローカルのPAC URLをコピー
|
||||
Share Server Config...=サーバーの設定を共有する...
|
||||
Scan QRCode from Screen...=画面からの QRコードをスキャン...
|
||||
Import URL from Clipboard...=クリップボードからの URLを貼り付け...
|
||||
Edit Local PAC File...=ローカル PAC ファイルの編集...
|
||||
Update Local PAC from GFWList=GFWList からローカル PAC を更新
|
||||
Edit User Rule for GFWList...=ユーザールールの編集...
|
||||
Secure Local PAC=ローカル PAC を保護
|
||||
Copy Local PAC URL=ローカル PAC URL をコピー
|
||||
Share Server Config...=サーバーの設定を共有...
|
||||
Scan QRCode from Screen...=画面から QR コードをスキャン...
|
||||
Import URL from Clipboard...=クリップボードから URL をインポート...
|
||||
Availability Statistics=可用性の統計
|
||||
Show Logs...=ログを表示する...
|
||||
Verbose Logging=詳細なログ
|
||||
Show Logs...=ログの表示...
|
||||
Verbose Logging=詳細なログを記録
|
||||
Updates...=更新...
|
||||
Check for Updates...=更新プログラムを確認しています...
|
||||
Check for Updates at Startup=起動と同時に更新プログラムを確認しています
|
||||
Check Pre-release Version=先行開発版の更新を確認しています...
|
||||
Edit Hotkeys...=ホットキーを編集する...
|
||||
About...=について...
|
||||
Check for Updates...=更新プログラムの確認...
|
||||
Check for Updates at Startup=起動時に更新プログラムを確認
|
||||
Check Pre-release Version=先行開発版も確認
|
||||
Edit Hotkeys...=ホットキーの編集...
|
||||
About...=Shadowsocks について...
|
||||
Help=ヘルプ
|
||||
Quit=終了
|
||||
Edit Servers=サーバを編集する
|
||||
Load Balance=バランス
|
||||
High Availability=高パフォーマンス
|
||||
Edit Servers=サーバーの編集
|
||||
Load Balance=負荷分散
|
||||
High Availability=高可用性
|
||||
Choose by statistics=統計で選ぶ
|
||||
|
||||
# Config Form
|
||||
@@ -45,42 +45,45 @@ Choose by statistics=統計で選ぶ
|
||||
&Add=新規 (&A)
|
||||
&Delete=削除 (&D)
|
||||
Dupli&cate=コピー (&C)
|
||||
Server=サーバ
|
||||
Server=サーバー
|
||||
Server Addr=サーバーアドレス
|
||||
Server Port=サーバポート
|
||||
Password=暗証番号
|
||||
Server Port=サーバーポート
|
||||
Password=パスワード
|
||||
Encryption=暗号化
|
||||
Proxy Port=代理ポート
|
||||
Remarks=短評する
|
||||
Plugin=プラグイン
|
||||
Plugin Options=プラグインのオプション
|
||||
Proxy Port=プロキシポート
|
||||
Remarks=付記
|
||||
Timeout(Sec)=タイムアウト (秒)
|
||||
OK=はい
|
||||
Cancel=いいえ
|
||||
New server=新規サーバ
|
||||
OK=OK
|
||||
Cancel=キャンセル
|
||||
New server=新規サーバー
|
||||
Move &Up=上に移動 (&U)
|
||||
Move D&own=下に移動 (&O)
|
||||
|
||||
# Proxy Form
|
||||
|
||||
Edit Proxy=代理を編集する
|
||||
Use Proxy=代理を利用する
|
||||
Proxy Type=代理類型
|
||||
Proxy Addr=代理アドレス
|
||||
Proxy Port=代理ポート
|
||||
Edit Proxy=プロキシの編集
|
||||
Use Proxy=プロキシを利用する
|
||||
Proxy Type=プロキシの種類
|
||||
Proxy Addr=プロキシアドレス
|
||||
Proxy Port=プロキシポート
|
||||
If server has a plugin, proxy will not be used=サーバーにプラグインがある場合、プロキシは利用されません
|
||||
|
||||
# Log Form
|
||||
|
||||
&File=ファイル (&F)
|
||||
&Open Location=この場所を開く (&O)
|
||||
&Open Location=ファイルの場所を開く (&O)
|
||||
E&xit=終了 (&X)
|
||||
&View=ビュー (&V)
|
||||
&Clean Logs=ログを削除する (&C)
|
||||
Change &Font=フォントを変更する (&F)
|
||||
&Wrap Text=文字改行 (&W)
|
||||
&Top Most=一番上 (&T)
|
||||
&Show Toolbar=ツールバーを表示する (&S)
|
||||
&View=表示 (&V)
|
||||
&Clean Logs=ログの削除 (&C)
|
||||
Change &Font=フォント (&F)
|
||||
&Wrap Text=右端で折り返す (&W)
|
||||
&Top Most=常に最前面に表示 (&T)
|
||||
&Show Toolbar=ツールバーの表示 (&S)
|
||||
Log Viewer=ログビューア
|
||||
Inbound=輸入
|
||||
Outbound=輸出
|
||||
Inbound=受信
|
||||
Outbound=送信
|
||||
|
||||
# QRCode Form
|
||||
|
||||
@@ -88,16 +91,16 @@ QRCode and URL=QR コードと URL
|
||||
|
||||
# PAC Url Form
|
||||
|
||||
Edit Online PAC URL=オンライン PAC URLを編集する
|
||||
Edit Online PAC URL...=オンライン PAC URLを編集する...
|
||||
Edit Online PAC URL=オンライン PAC URL の編集
|
||||
Edit Online PAC URL...=オンライン PAC URL の編集...
|
||||
Please input PAC Url=PAC URLを入力して下さい
|
||||
|
||||
# HotkeySettings Form
|
||||
|
||||
Switch system proxy=代理を切換える
|
||||
Switch system proxy mode=代理モードを切換える
|
||||
Switch share over LAN=LAN経由でシェアを切換える
|
||||
Show Logs=ログを表示する
|
||||
Switch system proxy=システム プロキシの状態を切り替える
|
||||
Switch system proxy mode=プロキシモードを切り替える
|
||||
Switch share over LAN=LAN からのアクセスの許可を切り替える
|
||||
Show Logs=ログの表示
|
||||
Switch to prev server=前のサーバーに切り替える
|
||||
Switch to next server=次のサーバーに切り替える
|
||||
Reg All=全部登録する
|
||||
@@ -105,38 +108,38 @@ Reg All=全部登録する
|
||||
# Messages
|
||||
|
||||
Shadowsocks Error: {0}=Shadowsocks エラー: {0}
|
||||
Port already in use=既に使用中のポート
|
||||
Invalid server address=違法なサーバアドレス
|
||||
Illegal port number format=不法なポート番号形式
|
||||
Illegal timeout format=不法なタイムアウト形式
|
||||
Please add at least one server=少なくとも一つのサーバーを追加して下さい
|
||||
Server IP can not be blank=サーバ IP は空欄にできない
|
||||
Password can not be blank=暗証番号は空欄にできない
|
||||
Port out of range=ポートが範囲外
|
||||
Port can't be 8123=ポート8123できない
|
||||
Shadowsocks {0} Update Found=Shadowsocks {0} 更新プログラムを利用できます
|
||||
No update is available=お使いのソフトウェアは最新です
|
||||
Click here to update=プログラムの更新
|
||||
Shadowsocks is here=Shadowsocks 此処です
|
||||
You can turn on/off Shadowsocks in the context menu=コンテキストメニューにshadowsocksを有効化または無効化
|
||||
System Proxy Enabled=システム 代理を有効にする
|
||||
System Proxy Disabled=システム 代理を無効にする
|
||||
Failed to update PAC file =PAC の更新に失敗しました
|
||||
PAC updated=PAC の更新に正しくインストールされました
|
||||
No updates found. Please report to GFWList if you have problems with it.=お使いのソフトウェアは最新です。もし貴方は問題がある、GFWListに報告して下さい。
|
||||
No QRCode found. Try to zoom in or move it to the center of the screen.=QR コードを探し当てていません。ズームインまたはそれが画面の中心に移動して下さい。
|
||||
Shadowsocks is already running.=Shadowsocks 実行中。
|
||||
Find Shadowsocks icon in your notify tray.=shadowsocks通知トレイにアイコンを見つけて下さい。
|
||||
If you want to start multiple Shadowsocks, make a copy in another directory.=同時に起動したい場合は、別のディレクトリにコピーしてもいいと思ってます。
|
||||
Failed to decode QRCode=QR コードの復号化に失敗しました
|
||||
Failed to update registry=登錄の更新に失敗しました
|
||||
System Proxy On: =システム代理をオンにする:
|
||||
Port already in use=ポートは既に使用されています。
|
||||
Invalid server address=サーバーアドレスが無効です。
|
||||
Illegal port number format=ポート番号のフォーマットが無効です。
|
||||
Illegal timeout format=タイムアウト値のフォーマットが無効です。
|
||||
Please add at least one server=少なくとも一つのサーバーを指定して下さい。
|
||||
Server IP can not be blank=サーバー IP が指定されていません。
|
||||
Password can not be blank=パスワードが指定されていません。
|
||||
Port out of range=ポート番号は範囲外です。
|
||||
Port can't be 8123=8123 番以外のポート番号を指定して下さい。
|
||||
Shadowsocks {0} Update Found=Shadowsocks バージョン {0} は利用できます。
|
||||
No update is available=お使いのバージョンは最新です。
|
||||
Click here to update=クリックしてアップデートします。
|
||||
Shadowsocks is here=Shadowsocks はここです。
|
||||
You can turn on/off Shadowsocks in the context menu=コンテキストメニューを使って、Shadowsocks を有効または無効にすることができます。
|
||||
System Proxy Enabled=システム プロキシが有効です。
|
||||
System Proxy Disabled=システム プロキシが無効です。
|
||||
Failed to update PAC file =PAC の更新に失敗しました。
|
||||
PAC updated=PAC を更新しました。
|
||||
No updates found. Please report to GFWList if you have problems with it.=お使いのバージョンは最新です。問題がある場合は、GFWList に報告して下さい。
|
||||
No QRCode found. Try to zoom in or move it to the center of the screen.=QR コードが見つかりませんでした。コードを大きくするか、画面の中央に移動して下さい。
|
||||
Shadowsocks is already running.=Shadowsocks 実行中
|
||||
Find Shadowsocks icon in your notify tray.=通知領域には Shadowsocks のアイコンがあります。
|
||||
If you want to start multiple Shadowsocks, make a copy in another directory.=複数起動したい場合は、プログラムファイルを別のフォルダーにコピーしてから、もう一度実行して下さい。
|
||||
Failed to decode QRCode=QR コードの読み取りに失敗しました。
|
||||
Failed to update registry=レジストリの更新に失敗しました。
|
||||
System Proxy On: =システム プロキシが有効:
|
||||
Running: Port {0}=実行中:ポート {0}
|
||||
Unexpected error, shadowsocks will exit. Please report to=予想外のエラー、Shadowsocks を終了する。この場所を報告して下さい。
|
||||
Unsupported operating system, use Windows Vista at least.=サポートしていないのOS、Windows Vista 以降のOSを利用して下さい。
|
||||
Unsupported .NET Framework, please update to 4.6.2 or later.=サポートしていないの .NET Framework、4.6.2 以降のバンジョーを利用して下さい。
|
||||
Proxy request failed=代理要求が失敗した。
|
||||
Proxy handshake failed=代理の握手に失敗しました
|
||||
Register hotkey failed=ホットキーの登錄に失敗しました
|
||||
Unexpected error, shadowsocks will exit. Please report to=予想外のエラーが発生したため、Shadowsocks を終了します。詳しくは下記までお問い合わせ下さい:
|
||||
Unsupported operating system, use Windows Vista at least.=お使いの OS はサポートされていません。Windows Vista 以降の OS で実行して下さい。
|
||||
Unsupported .NET Framework, please update to 4.6.2 or later.=お使いの .NET Framework はサポートされていません。4.6.2 以降のバンジョーをインストールして下さい。
|
||||
Proxy request failed=プロキシ要求が失敗しました。
|
||||
Proxy handshake failed=プロキシ ハンドシェイクに失敗しました。
|
||||
Register hotkey failed=ホットキーの登錄に失敗しました。
|
||||
Cannot parse hotkey: {0}=ホットキーを解析できません: {0}
|
||||
Timeout is invalid, it should not exceed {0}=タイムアウトが無効であるか、それを超えてはならない {0}
|
||||
Timeout is invalid, it should not exceed {0}=タイムアウト値が無効です。{0} 以下の値を指定して下さい。
|
||||
|
||||
Binary file not shown.
@@ -50,6 +50,8 @@ Server Addr=服务器地址
|
||||
Server Port=服务器端口
|
||||
Password=密码
|
||||
Encryption=加密
|
||||
Plugin=插件
|
||||
Plugin Options=插件选项
|
||||
Proxy Port=代理端口
|
||||
Remarks=备注
|
||||
Timeout(Sec)=超时(秒)
|
||||
@@ -66,6 +68,7 @@ Use Proxy=使用代理
|
||||
Proxy Type=代理类型
|
||||
Proxy Addr=代理地址
|
||||
Proxy Port=代理端口
|
||||
If server has a plugin, proxy will not be used=若服务器含有插件,代理将不被使用
|
||||
|
||||
# Log Form
|
||||
|
||||
|
||||
@@ -50,6 +50,8 @@ Server Addr=伺服器位址
|
||||
Server Port=伺服器連接埠
|
||||
Password=密碼
|
||||
Encryption=加密
|
||||
Plugin=插件
|
||||
Plugin Options=插件選項
|
||||
Proxy Port=Proxy 連接埠
|
||||
Remarks=註解
|
||||
Timeout(Sec)=逾時 (秒)
|
||||
@@ -66,6 +68,7 @@ Use Proxy=使用 Proxy
|
||||
Proxy Type=Proxy 類型
|
||||
Proxy Addr=Proxy 位址
|
||||
Proxy Port=Proxy 連接埠
|
||||
If server has a plugin, proxy will not be used=若伺服器含有插件,Proxy 將不被使用
|
||||
|
||||
# Log Form
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using Cyotek.Collections.Generic;
|
||||
using Shadowsocks.Encryption.CircularBuffer;
|
||||
using Shadowsocks.Controller;
|
||||
using Shadowsocks.Encryption.Exception;
|
||||
using Shadowsocks.Encryption.Stream;
|
||||
@@ -21,8 +21,8 @@ namespace Shadowsocks.Encryption.AEAD
|
||||
protected static byte[] _udpTmpBuf = new byte[65536];
|
||||
|
||||
// every connection should create its own buffer
|
||||
private CircularBuffer<byte> _encCircularBuffer = new CircularBuffer<byte>(MAX_INPUT_SIZE * 2, false);
|
||||
private CircularBuffer<byte> _decCircularBuffer = new CircularBuffer<byte>(MAX_INPUT_SIZE * 2, false);
|
||||
private ByteCircularBuffer _encCircularBuffer = new ByteCircularBuffer(MAX_INPUT_SIZE * 2);
|
||||
private ByteCircularBuffer _decCircularBuffer = new ByteCircularBuffer(MAX_INPUT_SIZE * 2);
|
||||
|
||||
public const int CHUNK_LEN_BYTES = 2;
|
||||
public const uint CHUNK_LEN_MASK = 0x3FFFu;
|
||||
@@ -88,15 +88,15 @@ namespace Shadowsocks.Encryption.AEAD
|
||||
byte[] passbuf = Encoding.UTF8.GetBytes(password);
|
||||
// init master key
|
||||
if (_Masterkey == null) _Masterkey = new byte[keyLen];
|
||||
if (_Masterkey.Length < keyLen) Array.Resize(ref _Masterkey, keyLen);
|
||||
DeriveKey(passbuf, _Masterkey);
|
||||
if (_Masterkey.Length != keyLen) Array.Resize(ref _Masterkey, keyLen);
|
||||
DeriveKey(passbuf, _Masterkey, keyLen);
|
||||
// init session key
|
||||
if (_sessionKey == null) _sessionKey = new byte[keyLen];
|
||||
}
|
||||
|
||||
public void DeriveKey(byte[] password, byte[] key)
|
||||
public void DeriveKey(byte[] password, byte[] key, int keylen)
|
||||
{
|
||||
StreamEncryptor.LegacyDeriveKey(password, key);
|
||||
StreamEncryptor.LegacyDeriveKey(password, key, keylen);
|
||||
}
|
||||
|
||||
public void DeriveSessionKey(byte[] salt, byte[] masterKey, byte[] sessionKey)
|
||||
@@ -254,7 +254,7 @@ namespace Shadowsocks.Encryption.AEAD
|
||||
|
||||
// we have enough data to decrypt one chunk
|
||||
// drop chunk len and its tag from buffer
|
||||
_decCircularBuffer.Get(CHUNK_LEN_BYTES + tagLen);
|
||||
_decCircularBuffer.Skip(CHUNK_LEN_BYTES + tagLen);
|
||||
byte[] encChunkBytes = _decCircularBuffer.Get(chunkLen + tagLen);
|
||||
byte[] decChunkBytes = new byte[chunkLen];
|
||||
uint decChunkLen = 0;
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Shadowsocks.Encryption.AEAD
|
||||
: AEADEncryptor, IDisposable
|
||||
{
|
||||
private const int CIPHER_CHACHA20IETFPOLY1305 = 1;
|
||||
private const int CIPHER_AES256GCM = 2;
|
||||
|
||||
private byte[] _sodiumEncSubkey;
|
||||
private byte[] _sodiumDecSubkey;
|
||||
@@ -24,6 +25,7 @@ namespace Shadowsocks.Encryption.AEAD
|
||||
private static Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
|
||||
{
|
||||
{"chacha20-ietf-poly1305", new EncryptorInfo(32, 32, 12, 16, CIPHER_CHACHA20IETFPOLY1305)},
|
||||
{"aes-256-gcm", new EncryptorInfo(32, 32, 12, 16, CIPHER_AES256GCM)},
|
||||
};
|
||||
|
||||
public static List<string> SupportedCiphers()
|
||||
@@ -63,6 +65,13 @@ namespace Shadowsocks.Encryption.AEAD
|
||||
null, _encNonce,
|
||||
_sodiumEncSubkey);
|
||||
break;
|
||||
case CIPHER_AES256GCM:
|
||||
ret = Sodium.crypto_aead_aes256gcm_encrypt(ciphertext, ref encClen,
|
||||
plaintext, (ulong)plen,
|
||||
null, 0,
|
||||
null, _encNonce,
|
||||
_sodiumEncSubkey);
|
||||
break;
|
||||
default:
|
||||
throw new System.Exception("not implemented");
|
||||
}
|
||||
@@ -91,6 +100,13 @@ namespace Shadowsocks.Encryption.AEAD
|
||||
null, 0,
|
||||
_decNonce, _sodiumDecSubkey);
|
||||
break;
|
||||
case CIPHER_AES256GCM:
|
||||
ret = Sodium.crypto_aead_aes256gcm_decrypt(plaintext, ref decPlen,
|
||||
null,
|
||||
ciphertext, (ulong)clen,
|
||||
null, 0,
|
||||
_decNonce, _sodiumDecSubkey);
|
||||
break;
|
||||
default:
|
||||
throw new System.Exception("not implemented");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,510 @@
|
||||
#region Original License
|
||||
|
||||
//New BSD License(BSD)
|
||||
//
|
||||
//Copyright(c) 2014-2015 Cyotek Ltd
|
||||
//Copyright(c) 2012, Alex Regueiro
|
||||
//All rights reserved.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Cyotek nor the
|
||||
// names of its contributors may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
//DISCLAIMED.IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Shadowsocks.Encryption.CircularBuffer
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a first-in, first-out collection of objects using a fixed buffer.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The capacity of a <see cref="ByteCircularBuffer" /> is the number of elements the <see cref="ByteCircularBuffer"/> can hold. </para>
|
||||
/// <para>ByteCircularBuffer accepts <c>null</c> as a valid value for reference types and allows duplicate elements.</para>
|
||||
/// <para>The <see cref="Get()"/> methods will remove the items that are returned from the ByteCircularBuffer. To view the contents of the ByteCircularBuffer without removing items, use the <see cref="Peek()"/> or <see cref="PeekLast"/> methods.</para>
|
||||
/// </remarks>
|
||||
public class ByteCircularBuffer
|
||||
{
|
||||
// based on http://circularbuffer.codeplex.com/
|
||||
// http://en.wikipedia.org/wiki/Circular_buffer
|
||||
// modified from https://github.com/cyotek/Cyotek.Collections.Generic.CircularBuffer
|
||||
// some code taken from https://github.com/xorxornop/RingBuffer
|
||||
// and https://github.com/xorxornop/PerfCopy
|
||||
|
||||
#region Instance Fields
|
||||
|
||||
private byte[] _buffer;
|
||||
|
||||
private int _capacity;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ByteCircularBuffer"/> class that is empty and has the specified initial capacity.
|
||||
/// </summary>
|
||||
/// <param name="capacity">The maximum capcity of the buffer.</param>
|
||||
/// <exception cref="System.ArgumentException">Thown if the <paramref name="capacity"/> is less than zero.</exception>
|
||||
public ByteCircularBuffer(int capacity)
|
||||
{
|
||||
if (capacity < 0)
|
||||
{
|
||||
throw new ArgumentException("The buffer capacity must be greater than or equal to zero.",
|
||||
nameof(capacity));
|
||||
}
|
||||
|
||||
_buffer = new byte[capacity];
|
||||
this.Capacity = capacity;
|
||||
this.Size = 0;
|
||||
this.Head = 0;
|
||||
this.Tail = 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the total number of elements the internal data structure can hold.
|
||||
/// </summary>
|
||||
/// <value>The total number of elements that the <see cref="ByteCircularBuffer"/> can contain.</value>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">Thrown if the specified new capacity is smaller than the current contents of the buffer.</exception>
|
||||
public int Capacity
|
||||
{
|
||||
get { return _capacity; }
|
||||
set
|
||||
{
|
||||
if (value != _capacity)
|
||||
{
|
||||
if (value < this.Size)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(value), value,
|
||||
"The new capacity must be greater than or equal to the buffer size.");
|
||||
}
|
||||
|
||||
var newBuffer = new byte[value];
|
||||
if (this.Size > 0)
|
||||
{
|
||||
this.CopyTo(newBuffer);
|
||||
}
|
||||
|
||||
_buffer = newBuffer;
|
||||
|
||||
_capacity = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the index of the beginning of the buffer data.
|
||||
/// </summary>
|
||||
/// <value>The index of the first element in the buffer.</value>
|
||||
public int Head { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the buffer is empty.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if buffer is empty; otherwise, <c>false</c>.</value>
|
||||
public virtual bool IsEmpty => this.Size == 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the buffer is full.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if the buffer is full; otherwise, <c>false</c>.</value>
|
||||
/// <remarks>The <see cref="IsFull"/> property always returns <c>false</c> if the <see cref="AllowOverwrite"/> property is set to <c>true</c>.</remarks>
|
||||
public virtual bool IsFull => this.Size == this.Capacity;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of elements contained in the <see cref="ByteCircularBuffer"/>.
|
||||
/// </summary>
|
||||
/// <value>The number of elements contained in the <see cref="ByteCircularBuffer"/>.</value>
|
||||
public int Size { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the index of the end of the buffer data.
|
||||
/// </summary>
|
||||
/// <value>The index of the last element in the buffer.</value>
|
||||
public int Tail { get; protected set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Members
|
||||
|
||||
/// <summary>
|
||||
/// Removes all items from the <see cref="ByteCircularBuffer" />.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
this.Size = 0;
|
||||
this.Head = 0;
|
||||
this.Tail = 0;
|
||||
_buffer = new byte[this.Capacity];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the <see cref="ByteCircularBuffer" /> contains a specific value.
|
||||
/// </summary>
|
||||
/// <param name="item">The object to locate in the <see cref="ByteCircularBuffer" />.</param>
|
||||
/// <returns><c>true</c> if <paramref name="item" /> is found in the <see cref="ByteCircularBuffer" />; otherwise, <c>false</c>.</returns>
|
||||
public bool Contains(byte item)
|
||||
{
|
||||
var bufferIndex = this.Head;
|
||||
var comparer = EqualityComparer<byte>.Default;
|
||||
var result = false;
|
||||
|
||||
for (int i = 0; i < this.Size; i++, bufferIndex++)
|
||||
{
|
||||
if (bufferIndex == this.Capacity)
|
||||
{
|
||||
bufferIndex = 0;
|
||||
}
|
||||
|
||||
if (comparer.Equals(_buffer[bufferIndex], item))
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies the entire <see cref="ByteCircularBuffer"/> to a compatible one-dimensional array, starting at the beginning of the target array.
|
||||
/// </summary>
|
||||
/// <param name="array">The one-dimensional <see cref="Array"/> that is the destination of the elements copied from <see cref="ByteCircularBuffer"/>. The <see cref="Array"/> must have zero-based indexing.</param>
|
||||
public void CopyTo(byte[] array)
|
||||
{
|
||||
this.CopyTo(array, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies the entire <see cref="ByteCircularBuffer"/> to a compatible one-dimensional array, starting at the specified index of the target array.
|
||||
/// </summary>
|
||||
/// <param name="array">The one-dimensional <see cref="Array"/> that is the destination of the elements copied from <see cref="ByteCircularBuffer"/>. The <see cref="Array"/> must have zero-based indexing.</param>
|
||||
/// <param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
|
||||
public void CopyTo(byte[] array, int arrayIndex)
|
||||
{
|
||||
this.CopyTo(this.Head, array, arrayIndex, Math.Min(this.Size, array.Length - arrayIndex));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies a range of elements from the <see cref="ByteCircularBuffer"/> to a compatible one-dimensional array, starting at the specified index of the target array.
|
||||
/// </summary>
|
||||
/// <param name="index">The zero-based index in the source <see cref="ByteCircularBuffer"/> at which copying begins.</param>
|
||||
/// <param name="array">The one-dimensional <see cref="Array"/> that is the destination of the elements copied from <see cref="ByteCircularBuffer"/>. The <see cref="Array"/> must have zero-based indexing.</param>
|
||||
/// <param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
|
||||
/// <param name="count">The number of elements to copy.</param>
|
||||
public virtual void CopyTo(int index, byte[] array, int arrayIndex, int count)
|
||||
{
|
||||
if (count > this.Size)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(count), count,
|
||||
"The read count cannot be greater than the buffer size.");
|
||||
}
|
||||
|
||||
var startAnchor = index;
|
||||
var dstIndex = arrayIndex;
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
int chunk = Math.Min(Capacity - startAnchor, count);
|
||||
Buffer.BlockCopy(_buffer, startAnchor, array, dstIndex, chunk);
|
||||
startAnchor = (startAnchor + chunk == Capacity) ? 0 : startAnchor + chunk;
|
||||
dstIndex += chunk;
|
||||
count -= chunk;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes and returns the specified number of objects from the beginning of the <see cref="ByteCircularBuffer"/>.
|
||||
/// </summary>
|
||||
/// <param name="count">The number of elements to remove and return from the <see cref="ByteCircularBuffer"/>.</param>
|
||||
/// <returns>The objects that are removed from the beginning of the <see cref="ByteCircularBuffer"/>.</returns>
|
||||
public byte[] Get(int count)
|
||||
{
|
||||
if (count <= 0) throw new ArgumentOutOfRangeException("should greater than 0");
|
||||
var result = new byte[count];
|
||||
|
||||
this.Get(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies and removes the specified number elements from the <see cref="ByteCircularBuffer"/> to a compatible one-dimensional array, starting at the beginning of the target array.
|
||||
/// </summary>
|
||||
/// <param name="array">The one-dimensional <see cref="Array"/> that is the destination of the elements copied from <see cref="ByteCircularBuffer"/>. The <see cref="Array"/> must have zero-based indexing.</param>
|
||||
/// <returns>The actual number of elements copied into <paramref name="array"/>.</returns>
|
||||
public int Get(byte[] array)
|
||||
{
|
||||
if (array.Length <= 0) throw new ArgumentOutOfRangeException("should greater than 0");
|
||||
return this.Get(array, 0, array.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies and removes the specified number elements from the <see cref="ByteCircularBuffer"/> to a compatible one-dimensional array, starting at the specified index of the target array.
|
||||
/// </summary>
|
||||
/// <param name="array">The one-dimensional <see cref="Array"/> that is the destination of the elements copied from <see cref="ByteCircularBuffer"/>. The <see cref="Array"/> must have zero-based indexing.</param>
|
||||
/// <param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
|
||||
/// <param name="count">The number of elements to copy.</param>
|
||||
/// <returns>The actual number of elements copied into <paramref name="array"/>.</returns>
|
||||
public virtual int Get(byte[] array, int arrayIndex, int count)
|
||||
{
|
||||
if (arrayIndex < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(arrayIndex), "Negative offset specified. Offsets must be positive.");
|
||||
}
|
||||
if (count < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(count), "Negative count specified. Count must be positive.");
|
||||
}
|
||||
if (count > this.Size)
|
||||
{
|
||||
throw new ArgumentException("Ringbuffer contents insufficient for take/read operation.", nameof(count));
|
||||
}
|
||||
if (array.Length < arrayIndex + count)
|
||||
{
|
||||
throw new ArgumentException("Destination array too small for requested output.");
|
||||
}
|
||||
var bytesCopied = 0;
|
||||
var dstIndex = arrayIndex;
|
||||
while (count > 0)
|
||||
{
|
||||
int chunk = Math.Min(Capacity - this.Head, count);
|
||||
Buffer.BlockCopy(_buffer, this.Head, array, dstIndex, chunk);
|
||||
this.Head = (this.Head + chunk == Capacity) ? 0 : this.Head + chunk;
|
||||
this.Size -= chunk;
|
||||
dstIndex += chunk;
|
||||
bytesCopied += chunk;
|
||||
count -= chunk;
|
||||
}
|
||||
return bytesCopied;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes and returns the object at the beginning of the <see cref="ByteCircularBuffer"/>.
|
||||
/// </summary>
|
||||
/// <returns>The object that is removed from the beginning of the <see cref="ByteCircularBuffer"/>.</returns>
|
||||
/// <exception cref="System.InvalidOperationException">Thrown if the buffer is empty.</exception>
|
||||
/// <remarks>This method is similar to the <see cref="Peek()"/> method, but <c>Peek</c> does not modify the <see cref="ByteCircularBuffer"/>.</remarks>
|
||||
public virtual byte Get()
|
||||
{
|
||||
if (this.IsEmpty)
|
||||
{
|
||||
throw new InvalidOperationException("The buffer is empty.");
|
||||
}
|
||||
|
||||
var item = _buffer[this.Head];
|
||||
if (++this.Head == this.Capacity)
|
||||
{
|
||||
this.Head = 0;
|
||||
}
|
||||
this.Size--;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the object at the beginning of the <see cref="ByteCircularBuffer"/> without removing it.
|
||||
/// </summary>
|
||||
/// <returns>The object at the beginning of the <see cref="ByteCircularBuffer"/>.</returns>
|
||||
/// <exception cref="System.InvalidOperationException">Thrown if the buffer is empty.</exception>
|
||||
public virtual byte Peek()
|
||||
{
|
||||
if (this.IsEmpty)
|
||||
{
|
||||
throw new InvalidOperationException("The buffer is empty.");
|
||||
}
|
||||
|
||||
var item = _buffer[this.Head];
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the specified number of objects from the beginning of the <see cref="ByteCircularBuffer"/>.
|
||||
/// </summary>
|
||||
/// <param name="count">The number of elements to return from the <see cref="ByteCircularBuffer"/>.</param>
|
||||
/// <returns>The objects that from the beginning of the <see cref="ByteCircularBuffer"/>.</returns>
|
||||
/// <exception cref="System.InvalidOperationException">Thrown if the buffer is empty.</exception>
|
||||
public virtual byte[] Peek(int count)
|
||||
{
|
||||
if (this.IsEmpty)
|
||||
{
|
||||
throw new InvalidOperationException("The buffer is empty.");
|
||||
}
|
||||
|
||||
var items = new byte[count];
|
||||
this.CopyTo(items);
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the object at the end of the <see cref="ByteCircularBuffer"/> without removing it.
|
||||
/// </summary>
|
||||
/// <returns>The object at the end of the <see cref="ByteCircularBuffer"/>.</returns>
|
||||
/// <exception cref="System.InvalidOperationException">Thrown if the buffer is empty.</exception>
|
||||
public virtual byte PeekLast()
|
||||
{
|
||||
int bufferIndex;
|
||||
|
||||
if (this.IsEmpty)
|
||||
{
|
||||
throw new InvalidOperationException("The buffer is empty.");
|
||||
}
|
||||
|
||||
if (this.Tail == 0)
|
||||
{
|
||||
bufferIndex = this.Size - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bufferIndex = this.Tail - 1;
|
||||
}
|
||||
|
||||
var item = _buffer[bufferIndex];
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies an entire compatible one-dimensional array to the <see cref="ByteCircularBuffer"/>.
|
||||
/// </summary>
|
||||
/// <param name="array">The one-dimensional <see cref="Array"/> that is the source of the elements copied to <see cref="ByteCircularBuffer"/>. The <see cref="Array"/> must have zero-based indexing.</param>
|
||||
/// <exception cref="System.InvalidOperationException">Thrown if buffer does not have sufficient capacity to put in new items.</exception>
|
||||
/// <remarks>If <see cref="Size"/> plus the size of <paramref name="array"/> exceeds the capacity of the <see cref="ByteCircularBuffer"/> and the <see cref="AllowOverwrite"/> property is <c>true</c>, the oldest items in the <see cref="ByteCircularBuffer"/> are overwritten with <paramref name="array"/>.</remarks>
|
||||
public int Put(byte[] array)
|
||||
{
|
||||
return this.Put(array, 0, array.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies a range of elements from a compatible one-dimensional array to the <see cref="ByteCircularBuffer"/>.
|
||||
/// </summary>
|
||||
/// <param name="array">The one-dimensional <see cref="Array"/> that is the source of the elements copied to <see cref="ByteCircularBuffer"/>. The <see cref="Array"/> must have zero-based indexing.</param>
|
||||
/// <param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
|
||||
/// <param name="count">The number of elements to copy.</param>
|
||||
/// <exception cref="System.InvalidOperationException">Thrown if buffer does not have sufficient capacity to put in new items.</exception>
|
||||
/// <remarks>If <see cref="Size"/> plus <paramref name="count"/> exceeds the capacity of the <see cref="ByteCircularBuffer"/> and the <see cref="AllowOverwrite"/> property is <c>true</c>, the oldest items in the <see cref="ByteCircularBuffer"/> are overwritten with <paramref name="array"/>.</remarks>
|
||||
public virtual int Put(byte[] array, int arrayIndex, int count)
|
||||
{
|
||||
if (count <= 0) throw new ArgumentOutOfRangeException(nameof(count), "Count must be positive.");
|
||||
if (this.Size + count > this.Capacity)
|
||||
{
|
||||
throw new InvalidOperationException("The buffer does not have sufficient capacity to put new items.");
|
||||
}
|
||||
|
||||
if (array.Length < arrayIndex + count)
|
||||
{
|
||||
throw new ArgumentException("Source array too small for requested input.");
|
||||
}
|
||||
var srcIndex = arrayIndex;
|
||||
var bytesToProcess = count;
|
||||
while (bytesToProcess > 0)
|
||||
{
|
||||
int chunk = Math.Min(Capacity - Tail, bytesToProcess);
|
||||
Buffer.BlockCopy(array, srcIndex, _buffer, Tail, chunk);
|
||||
Tail = (Tail + chunk == Capacity) ? 0 : Tail + chunk;
|
||||
this.Size += chunk;
|
||||
srcIndex += chunk;
|
||||
bytesToProcess -= chunk;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a byte to the end of the <see cref="ByteCircularBuffer"/>.
|
||||
/// </summary>
|
||||
/// <param name="item">The byte to add to the <see cref="ByteCircularBuffer"/>. </param>
|
||||
/// <exception cref="System.InvalidOperationException">Thrown if buffer does not have sufficient capacity to put in new items.</exception>
|
||||
public virtual void Put(byte item)
|
||||
{
|
||||
if (IsFull)
|
||||
{
|
||||
throw new InvalidOperationException("The buffer does not have sufficient capacity to put new items.");
|
||||
}
|
||||
|
||||
_buffer[this.Tail] = item;
|
||||
|
||||
this.Tail++;
|
||||
if (this.Size == this.Capacity)
|
||||
{
|
||||
this.Head++;
|
||||
if (this.Head >= this.Capacity)
|
||||
{
|
||||
this.Head -= this.Capacity;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.Tail == this.Capacity)
|
||||
{
|
||||
this.Tail = 0;
|
||||
}
|
||||
|
||||
if (this.Size != this.Capacity)
|
||||
{
|
||||
this.Size++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increments the starting index of the data buffer in the <see cref="ByteCircularBuffer"/>.
|
||||
/// </summary>
|
||||
/// <param name="count">The number of elements to increment the data buffer start index by.</param>
|
||||
public void Skip(int count)
|
||||
{
|
||||
if (count < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(count), "Negative count specified. Count must be positive.");
|
||||
}
|
||||
if (count > this.Size)
|
||||
{
|
||||
throw new ArgumentException("Ringbuffer contents insufficient for operation.", nameof(count));
|
||||
}
|
||||
|
||||
// Modular division gives new offset position
|
||||
this.Head = (this.Head + count) % Capacity;
|
||||
this.Size -= count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies the <see cref="ByteCircularBuffer"/> elements to a new array.
|
||||
/// </summary>
|
||||
/// <returns>A new array containing elements copied from the <see cref="ByteCircularBuffer"/>.</returns>
|
||||
/// <remarks>The <see cref="ByteCircularBuffer"/> is not modified. The order of the elements in the new array is the same as the order of the elements from the beginning of the <see cref="ByteCircularBuffer"/> to its end.</remarks>
|
||||
public byte[] ToArray()
|
||||
{
|
||||
var result = new byte[this.Size];
|
||||
|
||||
this.CopyTo(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -71,6 +71,8 @@
|
||||
public const int ATYP_DOMAIN = 0x03;
|
||||
public const int ATYP_IPv6 = 0x04;
|
||||
|
||||
public const int MD5_LEN = 16;
|
||||
|
||||
protected EncryptorBase(string method, string password)
|
||||
{
|
||||
Method = method;
|
||||
|
||||
@@ -14,6 +14,18 @@ namespace Shadowsocks.Encryption
|
||||
|
||||
static EncryptorFactory()
|
||||
{
|
||||
var AEADMbedTLSEncryptorSupportedCiphers = AEADMbedTLSEncryptor.SupportedCiphers();
|
||||
var AEADSodiumEncryptorSupportedCiphers = AEADSodiumEncryptor.SupportedCiphers();
|
||||
if (Sodium.AES256GCMAvailable)
|
||||
{
|
||||
// prefer to aes-256-gcm in libsodium
|
||||
AEADMbedTLSEncryptorSupportedCiphers.Remove("aes-256-gcm");
|
||||
}
|
||||
else
|
||||
{
|
||||
AEADSodiumEncryptorSupportedCiphers.Remove("aes-256-gcm");
|
||||
}
|
||||
|
||||
foreach (string method in StreamMbedTLSEncryptor.SupportedCiphers())
|
||||
{
|
||||
_registeredEncryptors.Add(method, typeof(StreamMbedTLSEncryptor));
|
||||
@@ -22,11 +34,11 @@ namespace Shadowsocks.Encryption
|
||||
{
|
||||
_registeredEncryptors.Add(method, typeof(StreamSodiumEncryptor));
|
||||
}
|
||||
foreach (string method in AEADMbedTLSEncryptor.SupportedCiphers())
|
||||
foreach (string method in AEADMbedTLSEncryptorSupportedCiphers)
|
||||
{
|
||||
_registeredEncryptors.Add(method, typeof(AEADMbedTLSEncryptor));
|
||||
}
|
||||
foreach (string method in AEADSodiumEncryptor.SupportedCiphers())
|
||||
foreach (string method in AEADSodiumEncryptorSupportedCiphers)
|
||||
{
|
||||
_registeredEncryptors.Add(method, typeof(AEADSodiumEncryptor));
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ namespace Shadowsocks.Encryption
|
||||
private static bool _initialized = false;
|
||||
private static readonly object _initLock = new object();
|
||||
|
||||
public static bool AES256GCMAvailable { get; private set; } = false;
|
||||
|
||||
static Sodium()
|
||||
{
|
||||
string dllPath = Utils.GetTempPath(DLLNAME);
|
||||
@@ -42,6 +44,9 @@ namespace Shadowsocks.Encryption
|
||||
{
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
AES256GCMAvailable = crypto_aead_aes256gcm_is_available() == 1;
|
||||
Logging.Debug($"sodium: AES256GCMAvailable is {AES256GCMAvailable}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,6 +57,9 @@ namespace Shadowsocks.Encryption
|
||||
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int sodium_init();
|
||||
|
||||
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int crypto_aead_aes256gcm_is_available();
|
||||
|
||||
#region AEAD
|
||||
|
||||
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
|
||||
@@ -65,6 +73,14 @@ namespace Shadowsocks.Encryption
|
||||
public static extern int crypto_aead_chacha20poly1305_ietf_decrypt(byte[] m, ref ulong mlen_p,
|
||||
byte[] nsec, byte[] c, ulong clen, byte[] ad, ulong adlen, byte[] npub, byte[] k);
|
||||
|
||||
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int crypto_aead_aes256gcm_encrypt(byte[] c, ref ulong clen_p, byte[] m, ulong mlen,
|
||||
byte[] ad, ulong adlen, byte[] nsec, byte[] npub, byte[] k);
|
||||
|
||||
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int crypto_aead_aes256gcm_decrypt(byte[] m, ref ulong mlen_p, byte[] nsec, byte[] c,
|
||||
ulong clen, byte[] ad, ulong adlen, byte[] npub, byte[] k);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Stream
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using Cyotek.Collections.Generic;
|
||||
using Shadowsocks.Encryption.CircularBuffer;
|
||||
using Shadowsocks.Controller;
|
||||
|
||||
namespace Shadowsocks.Encryption.Stream
|
||||
@@ -14,8 +14,8 @@ namespace Shadowsocks.Encryption.Stream
|
||||
protected static byte[] _udpTmpBuf = new byte[65536];
|
||||
|
||||
// every connection should create its own buffer
|
||||
private CircularBuffer<byte> _encCircularBuffer = new CircularBuffer<byte>(TCPHandler.BufferSize * 2, false);
|
||||
private CircularBuffer<byte> _decCircularBuffer = new CircularBuffer<byte>(TCPHandler.BufferSize * 2, false);
|
||||
private ByteCircularBuffer _encCircularBuffer = new ByteCircularBuffer(TCPHandler.BufferSize * 2);
|
||||
private ByteCircularBuffer _decCircularBuffer = new ByteCircularBuffer(TCPHandler.BufferSize * 2);
|
||||
|
||||
protected Dictionary<string, EncryptorInfo> ciphers;
|
||||
|
||||
@@ -64,25 +64,25 @@ namespace Shadowsocks.Encryption.Stream
|
||||
{
|
||||
byte[] passbuf = Encoding.UTF8.GetBytes(password);
|
||||
if (_key == null) _key = new byte[keyLen];
|
||||
if (_key.Length < keyLen) Array.Resize(ref _key, keyLen);
|
||||
LegacyDeriveKey(passbuf, _key);
|
||||
if (_key.Length != keyLen) Array.Resize(ref _key, keyLen);
|
||||
LegacyDeriveKey(passbuf, _key, keyLen);
|
||||
}
|
||||
|
||||
public static void LegacyDeriveKey(byte[] password, byte[] key)
|
||||
public static void LegacyDeriveKey(byte[] password, byte[] key, int keylen)
|
||||
{
|
||||
byte[] result = new byte[password.Length + 16];
|
||||
byte[] result = new byte[password.Length + MD5_LEN];
|
||||
int i = 0;
|
||||
byte[] md5sum = null;
|
||||
while (i < key.Length) {
|
||||
while (i < keylen) {
|
||||
if (i == 0) {
|
||||
md5sum = MbedTLS.MD5(password);
|
||||
} else {
|
||||
md5sum.CopyTo(result, 0);
|
||||
password.CopyTo(result, md5sum.Length);
|
||||
Array.Copy(md5sum, 0, result, 0, MD5_LEN);
|
||||
Array.Copy(password, 0, result, MD5_LEN, password.Length);
|
||||
md5sum = MbedTLS.MD5(result);
|
||||
}
|
||||
md5sum.CopyTo(key, i);
|
||||
i += md5sum.Length;
|
||||
Array.Copy(md5sum, 0, key, i, Math.Min(MD5_LEN, keylen - i));
|
||||
i += MD5_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +143,8 @@ namespace Shadowsocks.Encryption.Stream
|
||||
}
|
||||
byte[] cipher = _decCircularBuffer.ToArray();
|
||||
cipherUpdate(false, cipher.Length, cipher, outbuf);
|
||||
_decCircularBuffer.Clear();
|
||||
// move pointer only
|
||||
_decCircularBuffer.Skip(_decCircularBuffer.Size);
|
||||
outlength = cipher.Length;
|
||||
// done the decryption
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Weavers>
|
||||
<Caseless StringComparison="Ordinal"/>
|
||||
<Costura/>
|
||||
<Caseless StringComparison="Ordinal" />
|
||||
<Costura />
|
||||
</Weavers>
|
||||
@@ -89,7 +89,10 @@ namespace Shadowsocks.Model
|
||||
configs = new List<Server>()
|
||||
{
|
||||
GetDefaultServer()
|
||||
}
|
||||
},
|
||||
logViewer = new LogViewerConfig(),
|
||||
proxy = new ProxyConfig(),
|
||||
hotkey = new HotkeyConfig()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using Shadowsocks.Controller;
|
||||
|
||||
@@ -10,10 +10,6 @@ namespace Shadowsocks.Model
|
||||
[Serializable]
|
||||
public class Server
|
||||
{
|
||||
public static readonly Regex
|
||||
UrlFinder = new Regex(@"ss://(?<base64>[A-Za-z0-9+-/=_]+)(?:#(?<tag>\S+))?", RegexOptions.IgnoreCase),
|
||||
DetailsParser = new Regex(@"^((?<method>.+?):(?<password>.*)@(?<hostname>.+?):(?<port>\d+?))$", RegexOptions.IgnoreCase);
|
||||
|
||||
private const int DefaultServerTimeoutSec = 5;
|
||||
public const int MaxServerTimeoutSec = 20;
|
||||
|
||||
@@ -21,6 +17,8 @@ namespace Shadowsocks.Model
|
||||
public int server_port;
|
||||
public string password;
|
||||
public string method;
|
||||
public string plugin;
|
||||
public string plugin_opts;
|
||||
public string remarks;
|
||||
public int timeout;
|
||||
|
||||
@@ -65,6 +63,8 @@ namespace Shadowsocks.Model
|
||||
server = "";
|
||||
server_port = 8388;
|
||||
method = "aes-256-cfb";
|
||||
plugin = "";
|
||||
plugin_opts = "";
|
||||
password = "";
|
||||
remarks = "";
|
||||
timeout = DefaultServerTimeoutSec;
|
||||
@@ -72,26 +72,95 @@ namespace Shadowsocks.Model
|
||||
|
||||
public static List<Server> GetServers(string ssURL)
|
||||
{
|
||||
var matches = UrlFinder.Matches(ssURL);
|
||||
if (matches.Count <= 0) return null;
|
||||
var serverUrls = ssURL.Split('\r', '\n');
|
||||
|
||||
List<Server> servers = new List<Server>();
|
||||
foreach (Match match in matches)
|
||||
foreach (string serverUrl in serverUrls)
|
||||
{
|
||||
Server tmp = new Server();
|
||||
var base64 = match.Groups["base64"].Value;
|
||||
var tag = match.Groups["tag"].Value;
|
||||
if (!tag.IsNullOrEmpty())
|
||||
if (string.IsNullOrWhiteSpace(serverUrl))
|
||||
{
|
||||
tmp.remarks = HttpUtility.UrlDecode(tag, Encoding.UTF8);
|
||||
}
|
||||
Match details = DetailsParser.Match(Encoding.UTF8.GetString(Convert.FromBase64String(
|
||||
base64.PadRight(base64.Length + (4 - base64.Length % 4) % 4, '='))));
|
||||
if (!details.Success)
|
||||
continue;
|
||||
tmp.method = details.Groups["method"].Value;
|
||||
tmp.password = details.Groups["password"].Value;
|
||||
tmp.server = details.Groups["hostname"].Value;
|
||||
tmp.server_port = int.Parse(details.Groups["port"].Value);
|
||||
}
|
||||
|
||||
Uri parsedUrl;
|
||||
try
|
||||
{
|
||||
parsedUrl = new Uri(serverUrl);
|
||||
}
|
||||
catch (UriFormatException)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Server tmp = new Server
|
||||
{
|
||||
remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped)
|
||||
};
|
||||
|
||||
string possiblyUnpaddedBase64 = parsedUrl.GetComponents(UriComponents.UserInfo, UriFormat.Unescaped);
|
||||
bool isOldFormatUrl = possiblyUnpaddedBase64.Length == 0;
|
||||
if (isOldFormatUrl)
|
||||
{
|
||||
int prefixLength = "ss://".Length;
|
||||
int indexOfHashOrSlash = serverUrl.LastIndexOfAny(
|
||||
new[] { '/', '#' },
|
||||
serverUrl.Length - 1,
|
||||
serverUrl.Length - prefixLength);
|
||||
|
||||
int substringLength = serverUrl.Length - prefixLength;
|
||||
if (indexOfHashOrSlash >= 0)
|
||||
{
|
||||
substringLength = indexOfHashOrSlash - prefixLength;
|
||||
}
|
||||
|
||||
possiblyUnpaddedBase64 = serverUrl.Substring(prefixLength, substringLength).TrimEnd('/');
|
||||
}
|
||||
else
|
||||
{
|
||||
// Web-safe base64 to normal base64
|
||||
possiblyUnpaddedBase64 = possiblyUnpaddedBase64.Replace('-', '+').Replace('_', '/');
|
||||
}
|
||||
|
||||
string base64 = possiblyUnpaddedBase64.PadRight(
|
||||
possiblyUnpaddedBase64.Length + (4 - possiblyUnpaddedBase64.Length % 4) % 4,
|
||||
'=');
|
||||
|
||||
string innerUserInfoOrUrl = Encoding.UTF8.GetString(Convert.FromBase64String(base64));
|
||||
string userInfo;
|
||||
if (isOldFormatUrl)
|
||||
{
|
||||
Uri innerUrl = new Uri("inner://" + innerUserInfoOrUrl);
|
||||
userInfo = innerUrl.GetComponents(UriComponents.UserInfo, UriFormat.Unescaped);
|
||||
tmp.server = innerUrl.GetComponents(UriComponents.Host, UriFormat.Unescaped);
|
||||
tmp.server_port = innerUrl.Port;
|
||||
}
|
||||
else
|
||||
{
|
||||
userInfo = innerUserInfoOrUrl;
|
||||
tmp.server = parsedUrl.GetComponents(UriComponents.Host, UriFormat.Unescaped);
|
||||
tmp.server_port = parsedUrl.Port;
|
||||
}
|
||||
|
||||
string[] userInfoParts = userInfo.Split(new[] { ':' }, 2);
|
||||
if (userInfoParts.Length != 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
tmp.method = userInfoParts[0];
|
||||
tmp.password = userInfoParts[1];
|
||||
|
||||
NameValueCollection queryParameters = HttpUtility.ParseQueryString(parsedUrl.Query);
|
||||
string[] pluginParts = HttpUtility.UrlDecode(queryParameters["plugin"] ?? "").Split(new[] { ';' }, 2);
|
||||
if (pluginParts.Length > 0)
|
||||
{
|
||||
tmp.plugin = pluginParts[0] ?? "";
|
||||
}
|
||||
|
||||
if (pluginParts.Length > 1)
|
||||
{
|
||||
tmp.plugin_opts = pluginParts[1] ?? "";
|
||||
}
|
||||
|
||||
servers.Add(tmp);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
|
||||
namespace Shadowsocks.Model
|
||||
{
|
||||
/*
|
||||
* Data come from WinINET
|
||||
*/
|
||||
|
||||
[Serializable]
|
||||
public class SysproxyConfig
|
||||
{
|
||||
public bool UserSettingsRecorded;
|
||||
public string Flags;
|
||||
public string ProxyServer;
|
||||
public string BypassList;
|
||||
public string PacUrl;
|
||||
|
||||
public SysproxyConfig()
|
||||
{
|
||||
UserSettingsRecorded = false;
|
||||
Flags = "1";
|
||||
ProxyServer = "";
|
||||
BypassList = "";
|
||||
PacUrl = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,10 @@ namespace Shadowsocks.Util.Sockets
|
||||
arg.Completed += OnTcpConnectCompleted;
|
||||
arg.UserToken = new TcpUserToken(callback, state);
|
||||
|
||||
Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, arg);
|
||||
if(!Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, arg))
|
||||
{
|
||||
OnTcpConnectCompleted(this, arg);
|
||||
}
|
||||
}
|
||||
|
||||
private class FakeAsyncResult : IAsyncResult
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Shadowsocks.Controller;
|
||||
using Shadowsocks.Properties;
|
||||
using Shadowsocks.Model;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Shadowsocks.Util.SystemProxy
|
||||
{
|
||||
public static class Sysproxy
|
||||
{
|
||||
private static bool _userSettingsRecorded = false;
|
||||
private const string _userWininetConfigFile = "user-wininet.json";
|
||||
|
||||
private static string _queryStr;
|
||||
|
||||
// In general, this won't change
|
||||
// format:
|
||||
@@ -17,7 +21,7 @@ namespace Shadowsocks.Util.SystemProxy
|
||||
// <proxy-server><CR-LF>
|
||||
// <bypass-list><CR-LF>
|
||||
// <pac-url>
|
||||
private static string[] _userSettings = new string[4];
|
||||
private static SysproxyConfig _userSettings = null;
|
||||
|
||||
enum RET_ERRORS : int
|
||||
{
|
||||
@@ -31,8 +35,7 @@ namespace Shadowsocks.Util.SystemProxy
|
||||
|
||||
static Sysproxy()
|
||||
{
|
||||
try
|
||||
{
|
||||
try {
|
||||
FileManager.UncompressFile(Utils.GetTempPath("sysproxy.exe"),
|
||||
Environment.Is64BitOperatingSystem ? Resources.sysproxy64_exe : Resources.sysproxy_exe);
|
||||
}
|
||||
@@ -44,16 +47,16 @@ namespace Shadowsocks.Util.SystemProxy
|
||||
|
||||
public static void SetIEProxy(bool enable, bool global, string proxyServer, string pacURL)
|
||||
{
|
||||
string str;
|
||||
if (_userSettingsRecorded == false)
|
||||
Read();
|
||||
|
||||
if (!_userSettings.UserSettingsRecorded)
|
||||
{
|
||||
// record user settings
|
||||
ExecSysproxy("query", out str);
|
||||
ParseQueryStr(str);
|
||||
_userSettingsRecorded = true;
|
||||
ExecSysproxy("query");
|
||||
ParseQueryStr(_queryStr);
|
||||
}
|
||||
string arguments;
|
||||
|
||||
string arguments;
|
||||
if (enable)
|
||||
{
|
||||
arguments = global
|
||||
@@ -63,20 +66,21 @@ namespace Shadowsocks.Util.SystemProxy
|
||||
else
|
||||
{
|
||||
// restore user settings
|
||||
var flags = _userSettings[0];
|
||||
var proxy_server = _userSettings[1] ?? "-";
|
||||
var bypass_list = _userSettings[2] ?? "-";
|
||||
var pac_url = _userSettings[3] ?? "-";
|
||||
var flags = _userSettings.Flags;
|
||||
var proxy_server = _userSettings.ProxyServer ?? "-";
|
||||
var bypass_list = _userSettings.BypassList ?? "-";
|
||||
var pac_url = _userSettings.PacUrl ?? "-";
|
||||
arguments = $"set {flags} {proxy_server} {bypass_list} {pac_url}";
|
||||
|
||||
// have to get new settings
|
||||
_userSettingsRecorded = false;
|
||||
_userSettings.UserSettingsRecorded = false;
|
||||
}
|
||||
|
||||
ExecSysproxy(arguments, out str);
|
||||
Save();
|
||||
ExecSysproxy(arguments);
|
||||
}
|
||||
|
||||
private static void ExecSysproxy(string arguments, out string queryStr)
|
||||
private static void ExecSysproxy(string arguments)
|
||||
{
|
||||
using (var process = new Process())
|
||||
{
|
||||
@@ -107,24 +111,55 @@ namespace Shadowsocks.Util.SystemProxy
|
||||
throw new ProxyException(stderr);
|
||||
}
|
||||
|
||||
if (arguments == "query" && stdout.IsNullOrWhiteSpace())
|
||||
{
|
||||
// we cannot get user settings
|
||||
throw new ProxyException("failed to query wininet settings");
|
||||
if (arguments == "query") {
|
||||
if (stdout.IsNullOrWhiteSpace() || stdout.IsNullOrEmpty()) {
|
||||
// we cannot get user settings
|
||||
throw new ProxyException("failed to query wininet settings");
|
||||
}
|
||||
_queryStr = stdout;
|
||||
}
|
||||
queryStr = stdout;
|
||||
}
|
||||
}
|
||||
|
||||
private static void Save()
|
||||
{
|
||||
try {
|
||||
using (StreamWriter sw = new StreamWriter(File.Open(_userWininetConfigFile, FileMode.Create))) {
|
||||
string jsonString = JsonConvert.SerializeObject(_userSettings, Formatting.Indented);
|
||||
sw.Write(jsonString);
|
||||
sw.Flush();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Logging.LogUsefulException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void Read()
|
||||
{
|
||||
try {
|
||||
string configContent = File.ReadAllText(_userWininetConfigFile);
|
||||
_userSettings = JsonConvert.DeserializeObject<SysproxyConfig>(configContent);
|
||||
} catch(Exception) {
|
||||
// Suppress all exceptions. finally block will initialize new user config settings.
|
||||
} finally {
|
||||
if (_userSettings == null) _userSettings = new SysproxyConfig();
|
||||
}
|
||||
}
|
||||
|
||||
private static void ParseQueryStr(string str)
|
||||
{
|
||||
_userSettings = str.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
// handle output from WinINET
|
||||
if (_userSettings[i] == "(null)")
|
||||
_userSettings[i] = null;
|
||||
}
|
||||
string[] userSettingsArr = str.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
_userSettings.Flags = userSettingsArr[0];
|
||||
|
||||
// handle output from WinINET
|
||||
if (userSettingsArr[1] == "(null)") _userSettings.ProxyServer = null;
|
||||
else _userSettings.ProxyServer = userSettingsArr[1];
|
||||
if (userSettingsArr[2] == "(null)") _userSettings.BypassList = null;
|
||||
else _userSettings.BypassList = userSettingsArr[2];
|
||||
if (userSettingsArr[3] == "(null)") _userSettings.PacUrl = null;
|
||||
else _userSettings.PacUrl = userSettingsArr[3];
|
||||
|
||||
_userSettings.UserSettingsRecorded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+107
-54
@@ -29,6 +29,8 @@
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.PluginOptionsLabel = new System.Windows.Forms.Label();
|
||||
this.PluginTextBox = new System.Windows.Forms.TextBox();
|
||||
this.RemarksTextBox = new System.Windows.Forms.TextBox();
|
||||
this.RemarksLabel = new System.Windows.Forms.Label();
|
||||
this.IPLabel = new System.Windows.Forms.Label();
|
||||
@@ -41,6 +43,8 @@
|
||||
this.EncryptionSelect = new System.Windows.Forms.ComboBox();
|
||||
this.TimeoutLabel = new System.Windows.Forms.Label();
|
||||
this.TimeoutTextBox = new System.Windows.Forms.TextBox();
|
||||
this.PluginLabel = new System.Windows.Forms.Label();
|
||||
this.PluginOptionsTextBox = new System.Windows.Forms.TextBox();
|
||||
this.panel2 = new System.Windows.Forms.Panel();
|
||||
this.OKButton = new System.Windows.Forms.Button();
|
||||
this.MyCancelButton = new System.Windows.Forms.Button();
|
||||
@@ -74,8 +78,10 @@
|
||||
this.tableLayoutPanel1.ColumnCount = 2;
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel1.Controls.Add(this.RemarksTextBox, 1, 5);
|
||||
this.tableLayoutPanel1.Controls.Add(this.RemarksLabel, 0, 5);
|
||||
this.tableLayoutPanel1.Controls.Add(this.PluginOptionsLabel, 0, 5);
|
||||
this.tableLayoutPanel1.Controls.Add(this.PluginTextBox, 1, 4);
|
||||
this.tableLayoutPanel1.Controls.Add(this.RemarksTextBox, 1, 7);
|
||||
this.tableLayoutPanel1.Controls.Add(this.RemarksLabel, 0, 7);
|
||||
this.tableLayoutPanel1.Controls.Add(this.IPLabel, 0, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ServerPortLabel, 0, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.PasswordLabel, 0, 2);
|
||||
@@ -84,13 +90,15 @@
|
||||
this.tableLayoutPanel1.Controls.Add(this.PasswordTextBox, 1, 2);
|
||||
this.tableLayoutPanel1.Controls.Add(this.EncryptionLabel, 0, 3);
|
||||
this.tableLayoutPanel1.Controls.Add(this.EncryptionSelect, 1, 3);
|
||||
this.tableLayoutPanel1.Controls.Add(this.TimeoutLabel, 0, 6);
|
||||
this.tableLayoutPanel1.Controls.Add(this.TimeoutTextBox, 1, 6);
|
||||
this.tableLayoutPanel1.Controls.Add(this.TimeoutLabel, 0, 8);
|
||||
this.tableLayoutPanel1.Controls.Add(this.TimeoutTextBox, 1, 8);
|
||||
this.tableLayoutPanel1.Controls.Add(this.PluginLabel, 0, 4);
|
||||
this.tableLayoutPanel1.Controls.Add(this.PluginOptionsTextBox, 1, 5);
|
||||
this.tableLayoutPanel1.Location = new System.Drawing.Point(8, 21);
|
||||
this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||
this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tableLayoutPanel1.RowCount = 7;
|
||||
this.tableLayoutPanel1.RowCount = 9;
|
||||
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());
|
||||
@@ -98,26 +106,48 @@
|
||||
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(255, 167);
|
||||
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(253, 215);
|
||||
this.tableLayoutPanel1.TabIndex = 0;
|
||||
//
|
||||
// PluginOptionsLabel
|
||||
//
|
||||
this.PluginOptionsLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
|
||||
this.PluginOptionsLabel.AutoSize = true;
|
||||
this.PluginOptionsLabel.Location = new System.Drawing.Point(6, 140);
|
||||
this.PluginOptionsLabel.Name = "PluginOptionsLabel";
|
||||
this.PluginOptionsLabel.Size = new System.Drawing.Size(75, 13);
|
||||
this.PluginOptionsLabel.TabIndex = 15;
|
||||
this.PluginOptionsLabel.Text = "Plugin Options";
|
||||
//
|
||||
// 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(87, 111);
|
||||
this.PluginTextBox.MaxLength = 256;
|
||||
this.PluginTextBox.Name = "PluginTextBox";
|
||||
this.PluginTextBox.Size = new System.Drawing.Size(160, 20);
|
||||
this.PluginTextBox.TabIndex = 4;
|
||||
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(89, 113);
|
||||
this.RemarksTextBox.Location = new System.Drawing.Point(87, 163);
|
||||
this.RemarksTextBox.MaxLength = 32;
|
||||
this.RemarksTextBox.Name = "RemarksTextBox";
|
||||
this.RemarksTextBox.Size = new System.Drawing.Size(160, 21);
|
||||
this.RemarksTextBox.TabIndex = 4;
|
||||
this.RemarksTextBox.Size = new System.Drawing.Size(160, 20);
|
||||
this.RemarksTextBox.TabIndex = 6;
|
||||
this.RemarksTextBox.WordWrap = false;
|
||||
//
|
||||
// RemarksLabel
|
||||
//
|
||||
this.RemarksLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
|
||||
this.RemarksLabel.AutoSize = true;
|
||||
this.RemarksLabel.Location = new System.Drawing.Point(36, 117);
|
||||
this.RemarksLabel.Location = new System.Drawing.Point(32, 166);
|
||||
this.RemarksLabel.Name = "RemarksLabel";
|
||||
this.RemarksLabel.Size = new System.Drawing.Size(47, 12);
|
||||
this.RemarksLabel.Size = new System.Drawing.Size(49, 13);
|
||||
this.RemarksLabel.TabIndex = 9;
|
||||
this.RemarksLabel.Text = "Remarks";
|
||||
//
|
||||
@@ -125,9 +155,9 @@
|
||||
//
|
||||
this.IPLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
|
||||
this.IPLabel.AutoSize = true;
|
||||
this.IPLabel.Location = new System.Drawing.Point(24, 10);
|
||||
this.IPLabel.Location = new System.Drawing.Point(30, 9);
|
||||
this.IPLabel.Name = "IPLabel";
|
||||
this.IPLabel.Size = new System.Drawing.Size(59, 12);
|
||||
this.IPLabel.Size = new System.Drawing.Size(51, 13);
|
||||
this.IPLabel.TabIndex = 0;
|
||||
this.IPLabel.Text = "Server IP";
|
||||
//
|
||||
@@ -135,9 +165,9 @@
|
||||
//
|
||||
this.ServerPortLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
|
||||
this.ServerPortLabel.AutoSize = true;
|
||||
this.ServerPortLabel.Location = new System.Drawing.Point(12, 37);
|
||||
this.ServerPortLabel.Location = new System.Drawing.Point(21, 35);
|
||||
this.ServerPortLabel.Name = "ServerPortLabel";
|
||||
this.ServerPortLabel.Size = new System.Drawing.Size(71, 12);
|
||||
this.ServerPortLabel.Size = new System.Drawing.Size(60, 13);
|
||||
this.ServerPortLabel.TabIndex = 1;
|
||||
this.ServerPortLabel.Text = "Server Port";
|
||||
//
|
||||
@@ -145,39 +175,39 @@
|
||||
//
|
||||
this.PasswordLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
|
||||
this.PasswordLabel.AutoSize = true;
|
||||
this.PasswordLabel.Location = new System.Drawing.Point(30, 64);
|
||||
this.PasswordLabel.Location = new System.Drawing.Point(28, 61);
|
||||
this.PasswordLabel.Name = "PasswordLabel";
|
||||
this.PasswordLabel.Size = new System.Drawing.Size(53, 12);
|
||||
this.PasswordLabel.Size = new System.Drawing.Size(53, 13);
|
||||
this.PasswordLabel.TabIndex = 2;
|
||||
this.PasswordLabel.Text = "Password";
|
||||
//
|
||||
// IPTextBox
|
||||
//
|
||||
this.IPTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.IPTextBox.Location = new System.Drawing.Point(89, 6);
|
||||
this.IPTextBox.Location = new System.Drawing.Point(87, 6);
|
||||
this.IPTextBox.MaxLength = 512;
|
||||
this.IPTextBox.Name = "IPTextBox";
|
||||
this.IPTextBox.Size = new System.Drawing.Size(160, 21);
|
||||
this.IPTextBox.Size = new System.Drawing.Size(160, 20);
|
||||
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(89, 33);
|
||||
this.ServerPortTextBox.Location = new System.Drawing.Point(87, 32);
|
||||
this.ServerPortTextBox.MaxLength = 10;
|
||||
this.ServerPortTextBox.Name = "ServerPortTextBox";
|
||||
this.ServerPortTextBox.Size = new System.Drawing.Size(160, 21);
|
||||
this.ServerPortTextBox.Size = new System.Drawing.Size(160, 20);
|
||||
this.ServerPortTextBox.TabIndex = 1;
|
||||
this.ServerPortTextBox.WordWrap = false;
|
||||
//
|
||||
// PasswordTextBox
|
||||
//
|
||||
this.PasswordTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.PasswordTextBox.Location = new System.Drawing.Point(89, 60);
|
||||
this.PasswordTextBox.Location = new System.Drawing.Point(87, 58);
|
||||
this.PasswordTextBox.MaxLength = 256;
|
||||
this.PasswordTextBox.Name = "PasswordTextBox";
|
||||
this.PasswordTextBox.Size = new System.Drawing.Size(160, 21);
|
||||
this.PasswordTextBox.Size = new System.Drawing.Size(160, 20);
|
||||
this.PasswordTextBox.TabIndex = 2;
|
||||
this.PasswordTextBox.UseSystemPasswordChar = true;
|
||||
this.PasswordTextBox.WordWrap = false;
|
||||
@@ -186,9 +216,9 @@
|
||||
//
|
||||
this.EncryptionLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
|
||||
this.EncryptionLabel.AutoSize = true;
|
||||
this.EncryptionLabel.Location = new System.Drawing.Point(18, 91);
|
||||
this.EncryptionLabel.Location = new System.Drawing.Point(24, 88);
|
||||
this.EncryptionLabel.Name = "EncryptionLabel";
|
||||
this.EncryptionLabel.Size = new System.Drawing.Size(65, 12);
|
||||
this.EncryptionLabel.Size = new System.Drawing.Size(57, 13);
|
||||
this.EncryptionLabel.TabIndex = 8;
|
||||
this.EncryptionLabel.Text = "Encryption";
|
||||
//
|
||||
@@ -199,7 +229,7 @@
|
||||
this.EncryptionSelect.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.EncryptionSelect.FormattingEnabled = true;
|
||||
this.EncryptionSelect.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||
this.EncryptionSelect.ItemHeight = 12;
|
||||
this.EncryptionSelect.ItemHeight = 13;
|
||||
this.EncryptionSelect.Items.AddRange(new object[] {
|
||||
"rc4-md5",
|
||||
"salsa20",
|
||||
@@ -219,30 +249,50 @@
|
||||
"aes-192-gcm",
|
||||
"aes-256-gcm",
|
||||
"chacha20-ietf-poly1305"});
|
||||
this.EncryptionSelect.Location = new System.Drawing.Point(89, 87);
|
||||
this.EncryptionSelect.Location = new System.Drawing.Point(87, 84);
|
||||
this.EncryptionSelect.Name = "EncryptionSelect";
|
||||
this.EncryptionSelect.Size = new System.Drawing.Size(160, 20);
|
||||
this.EncryptionSelect.Size = new System.Drawing.Size(160, 21);
|
||||
this.EncryptionSelect.TabIndex = 3;
|
||||
//
|
||||
// TimeoutLabel
|
||||
//
|
||||
this.TimeoutLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
|
||||
this.TimeoutLabel.AutoSize = true;
|
||||
this.TimeoutLabel.Location = new System.Drawing.Point(6, 144);
|
||||
this.TimeoutLabel.Location = new System.Drawing.Point(11, 192);
|
||||
this.TimeoutLabel.Name = "TimeoutLabel";
|
||||
this.TimeoutLabel.RightToLeft = System.Windows.Forms.RightToLeft.No;
|
||||
this.TimeoutLabel.Size = new System.Drawing.Size(77, 12);
|
||||
this.TimeoutLabel.Size = new System.Drawing.Size(70, 13);
|
||||
this.TimeoutLabel.TabIndex = 10;
|
||||
this.TimeoutLabel.Text = "Timeout(Sec)";
|
||||
//
|
||||
// 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(89, 140);
|
||||
this.TimeoutTextBox.Location = new System.Drawing.Point(87, 189);
|
||||
this.TimeoutTextBox.MaxLength = 5;
|
||||
this.TimeoutTextBox.Name = "TimeoutTextBox";
|
||||
this.TimeoutTextBox.Size = new System.Drawing.Size(160, 21);
|
||||
this.TimeoutTextBox.TabIndex = 11;
|
||||
this.TimeoutTextBox.Size = new System.Drawing.Size(160, 20);
|
||||
this.TimeoutTextBox.TabIndex = 7;
|
||||
//
|
||||
// PluginLabel
|
||||
//
|
||||
this.PluginLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
|
||||
this.PluginLabel.AutoSize = true;
|
||||
this.PluginLabel.Location = new System.Drawing.Point(45, 114);
|
||||
this.PluginLabel.Name = "PluginLabel";
|
||||
this.PluginLabel.Size = new System.Drawing.Size(36, 13);
|
||||
this.PluginLabel.TabIndex = 12;
|
||||
this.PluginLabel.Text = "Plugin";
|
||||
//
|
||||
// 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(87, 137);
|
||||
this.PluginOptionsTextBox.MaxLength = 256;
|
||||
this.PluginOptionsTextBox.Name = "PluginOptionsTextBox";
|
||||
this.PluginOptionsTextBox.Size = new System.Drawing.Size(160, 20);
|
||||
this.PluginOptionsTextBox.TabIndex = 5;
|
||||
this.PluginOptionsTextBox.WordWrap = false;
|
||||
//
|
||||
// panel2
|
||||
//
|
||||
@@ -262,7 +312,7 @@
|
||||
this.OKButton.Margin = new System.Windows.Forms.Padding(3, 3, 3, 0);
|
||||
this.OKButton.Name = "OKButton";
|
||||
this.OKButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.OKButton.TabIndex = 12;
|
||||
this.OKButton.TabIndex = 15;
|
||||
this.OKButton.Text = "OK";
|
||||
this.OKButton.UseVisualStyleBackColor = true;
|
||||
this.OKButton.Click += new System.EventHandler(this.OKButton_Click);
|
||||
@@ -275,7 +325,7 @@
|
||||
this.MyCancelButton.Margin = new System.Windows.Forms.Padding(3, 3, 0, 0);
|
||||
this.MyCancelButton.Name = "MyCancelButton";
|
||||
this.MyCancelButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.MyCancelButton.TabIndex = 13;
|
||||
this.MyCancelButton.TabIndex = 16;
|
||||
this.MyCancelButton.Text = "Cancel";
|
||||
this.MyCancelButton.UseVisualStyleBackColor = true;
|
||||
this.MyCancelButton.Click += new System.EventHandler(this.CancelButton_Click);
|
||||
@@ -287,7 +337,7 @@
|
||||
this.DeleteButton.Margin = new System.Windows.Forms.Padding(3, 6, 0, 3);
|
||||
this.DeleteButton.Name = "DeleteButton";
|
||||
this.DeleteButton.Size = new System.Drawing.Size(80, 23);
|
||||
this.DeleteButton.TabIndex = 9;
|
||||
this.DeleteButton.TabIndex = 11;
|
||||
this.DeleteButton.Text = "&Delete";
|
||||
this.DeleteButton.UseVisualStyleBackColor = true;
|
||||
this.DeleteButton.Click += new System.EventHandler(this.DeleteButton_Click);
|
||||
@@ -299,7 +349,7 @@
|
||||
this.AddButton.Margin = new System.Windows.Forms.Padding(0, 6, 3, 3);
|
||||
this.AddButton.Name = "AddButton";
|
||||
this.AddButton.Size = new System.Drawing.Size(80, 23);
|
||||
this.AddButton.TabIndex = 8;
|
||||
this.AddButton.TabIndex = 10;
|
||||
this.AddButton.Text = "&Add";
|
||||
this.AddButton.UseVisualStyleBackColor = true;
|
||||
this.AddButton.Click += new System.EventHandler(this.AddButton_Click);
|
||||
@@ -312,7 +362,7 @@
|
||||
this.ServerGroupBox.Location = new System.Drawing.Point(178, 0);
|
||||
this.ServerGroupBox.Margin = new System.Windows.Forms.Padding(12, 0, 0, 0);
|
||||
this.ServerGroupBox.Name = "ServerGroupBox";
|
||||
this.ServerGroupBox.Size = new System.Drawing.Size(266, 205);
|
||||
this.ServerGroupBox.Size = new System.Drawing.Size(264, 252);
|
||||
this.ServerGroupBox.TabIndex = 0;
|
||||
this.ServerGroupBox.TabStop = false;
|
||||
this.ServerGroupBox.Text = "Server";
|
||||
@@ -321,12 +371,11 @@
|
||||
//
|
||||
this.ServersListBox.FormattingEnabled = true;
|
||||
this.ServersListBox.IntegralHeight = false;
|
||||
this.ServersListBox.ItemHeight = 12;
|
||||
this.ServersListBox.Location = new System.Drawing.Point(0, 0);
|
||||
this.ServersListBox.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.ServersListBox.Name = "ServersListBox";
|
||||
this.ServersListBox.Size = new System.Drawing.Size(166, 148);
|
||||
this.ServersListBox.TabIndex = 7;
|
||||
this.ServersListBox.TabIndex = 9;
|
||||
this.ServersListBox.SelectedIndexChanged += new System.EventHandler(this.ServersListBox_SelectedIndexChanged);
|
||||
//
|
||||
// tableLayoutPanel2
|
||||
@@ -349,7 +398,7 @@
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel2.Size = new System.Drawing.Size(444, 301);
|
||||
this.tableLayoutPanel2.Size = new System.Drawing.Size(442, 348);
|
||||
this.tableLayoutPanel2.TabIndex = 7;
|
||||
//
|
||||
// tableLayoutPanel6
|
||||
@@ -362,7 +411,7 @@
|
||||
this.tableLayoutPanel6.Controls.Add(this.MoveDownButton, 1, 0);
|
||||
this.tableLayoutPanel6.Controls.Add(this.MoveUpButton, 0, 0);
|
||||
this.tableLayoutPanel6.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.tableLayoutPanel6.Location = new System.Drawing.Point(0, 269);
|
||||
this.tableLayoutPanel6.Location = new System.Drawing.Point(0, 316);
|
||||
this.tableLayoutPanel6.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.tableLayoutPanel6.Name = "tableLayoutPanel6";
|
||||
this.tableLayoutPanel6.RowCount = 1;
|
||||
@@ -377,7 +426,7 @@
|
||||
this.MoveDownButton.Margin = new System.Windows.Forms.Padding(3, 6, 0, 3);
|
||||
this.MoveDownButton.Name = "MoveDownButton";
|
||||
this.MoveDownButton.Size = new System.Drawing.Size(80, 23);
|
||||
this.MoveDownButton.TabIndex = 11;
|
||||
this.MoveDownButton.TabIndex = 14;
|
||||
this.MoveDownButton.Text = "Move D&own";
|
||||
this.MoveDownButton.UseVisualStyleBackColor = true;
|
||||
this.MoveDownButton.Click += new System.EventHandler(this.MoveDownButton_Click);
|
||||
@@ -389,7 +438,7 @@
|
||||
this.MoveUpButton.Margin = new System.Windows.Forms.Padding(0, 6, 3, 3);
|
||||
this.MoveUpButton.Name = "MoveUpButton";
|
||||
this.MoveUpButton.Size = new System.Drawing.Size(80, 23);
|
||||
this.MoveUpButton.TabIndex = 10;
|
||||
this.MoveUpButton.TabIndex = 13;
|
||||
this.MoveUpButton.Text = "Move &Up";
|
||||
this.MoveUpButton.UseVisualStyleBackColor = true;
|
||||
this.MoveUpButton.Click += new System.EventHandler(this.MoveUpButton_Click);
|
||||
@@ -405,7 +454,7 @@
|
||||
this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel5.Controls.Add(this.ProxyPortTextBox, 1, 0);
|
||||
this.tableLayoutPanel5.Controls.Add(this.ProxyPortLabel, 0, 0);
|
||||
this.tableLayoutPanel5.Location = new System.Drawing.Point(248, 205);
|
||||
this.tableLayoutPanel5.Location = new System.Drawing.Point(256, 252);
|
||||
this.tableLayoutPanel5.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.tableLayoutPanel5.Name = "tableLayoutPanel5";
|
||||
this.tableLayoutPanel5.Padding = new System.Windows.Forms.Padding(3);
|
||||
@@ -415,26 +464,26 @@
|
||||
this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 58F));
|
||||
this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 58F));
|
||||
this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 58F));
|
||||
this.tableLayoutPanel5.Size = new System.Drawing.Size(196, 64);
|
||||
this.tableLayoutPanel5.Size = new System.Drawing.Size(186, 64);
|
||||
this.tableLayoutPanel5.TabIndex = 9;
|
||||
//
|
||||
// ProxyPortTextBox
|
||||
//
|
||||
this.ProxyPortTextBox.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.ProxyPortTextBox.Location = new System.Drawing.Point(77, 21);
|
||||
this.ProxyPortTextBox.Location = new System.Drawing.Point(67, 22);
|
||||
this.ProxyPortTextBox.MaxLength = 10;
|
||||
this.ProxyPortTextBox.Name = "ProxyPortTextBox";
|
||||
this.ProxyPortTextBox.Size = new System.Drawing.Size(113, 21);
|
||||
this.ProxyPortTextBox.TabIndex = 6;
|
||||
this.ProxyPortTextBox.Size = new System.Drawing.Size(113, 20);
|
||||
this.ProxyPortTextBox.TabIndex = 8;
|
||||
this.ProxyPortTextBox.WordWrap = false;
|
||||
//
|
||||
// ProxyPortLabel
|
||||
//
|
||||
this.ProxyPortLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
|
||||
this.ProxyPortLabel.AutoSize = true;
|
||||
this.ProxyPortLabel.Location = new System.Drawing.Point(6, 26);
|
||||
this.ProxyPortLabel.Location = new System.Drawing.Point(6, 25);
|
||||
this.ProxyPortLabel.Name = "ProxyPortLabel";
|
||||
this.ProxyPortLabel.Size = new System.Drawing.Size(65, 12);
|
||||
this.ProxyPortLabel.Size = new System.Drawing.Size(55, 13);
|
||||
this.ProxyPortLabel.TabIndex = 3;
|
||||
this.ProxyPortLabel.Text = "Proxy Port";
|
||||
//
|
||||
@@ -449,7 +498,7 @@
|
||||
this.tableLayoutPanel3.Controls.Add(this.MyCancelButton, 1, 0);
|
||||
this.tableLayoutPanel3.Controls.Add(this.OKButton, 0, 0);
|
||||
this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Right;
|
||||
this.tableLayoutPanel3.Location = new System.Drawing.Point(285, 272);
|
||||
this.tableLayoutPanel3.Location = new System.Drawing.Point(283, 319);
|
||||
this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(3, 3, 0, 3);
|
||||
this.tableLayoutPanel3.Name = "tableLayoutPanel3";
|
||||
this.tableLayoutPanel3.RowCount = 1;
|
||||
@@ -468,7 +517,7 @@
|
||||
this.tableLayoutPanel4.Controls.Add(this.DeleteButton, 1, 0);
|
||||
this.tableLayoutPanel4.Controls.Add(this.AddButton, 0, 0);
|
||||
this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.tableLayoutPanel4.Location = new System.Drawing.Point(0, 205);
|
||||
this.tableLayoutPanel4.Location = new System.Drawing.Point(0, 252);
|
||||
this.tableLayoutPanel4.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.tableLayoutPanel4.Name = "tableLayoutPanel4";
|
||||
this.tableLayoutPanel4.RowCount = 2;
|
||||
@@ -484,7 +533,7 @@
|
||||
this.DuplicateButton.Margin = new System.Windows.Forms.Padding(0, 6, 3, 3);
|
||||
this.DuplicateButton.Name = "DuplicateButton";
|
||||
this.DuplicateButton.Size = new System.Drawing.Size(80, 23);
|
||||
this.DuplicateButton.TabIndex = 10;
|
||||
this.DuplicateButton.TabIndex = 12;
|
||||
this.DuplicateButton.Text = "Dupli&cate";
|
||||
this.DuplicateButton.UseVisualStyleBackColor = true;
|
||||
this.DuplicateButton.Click += new System.EventHandler(this.DuplicateButton_Click);
|
||||
@@ -559,6 +608,10 @@
|
||||
private System.Windows.Forms.Button DuplicateButton;
|
||||
private System.Windows.Forms.Label TimeoutLabel;
|
||||
private System.Windows.Forms.TextBox TimeoutTextBox;
|
||||
private System.Windows.Forms.Label PluginOptionsLabel;
|
||||
private System.Windows.Forms.TextBox PluginTextBox;
|
||||
private System.Windows.Forms.Label PluginLabel;
|
||||
private System.Windows.Forms.TextBox PluginOptionsTextBox;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,8 @@ namespace Shadowsocks.View
|
||||
ServerPortLabel.Text = I18N.GetString("Server Port");
|
||||
PasswordLabel.Text = I18N.GetString("Password");
|
||||
EncryptionLabel.Text = I18N.GetString("Encryption");
|
||||
PluginLabel.Text = I18N.GetString("Plugin");
|
||||
PluginOptionsLabel.Text = I18N.GetString("Plugin Options");
|
||||
ProxyPortLabel.Text = I18N.GetString("Proxy Port");
|
||||
RemarksLabel.Text = I18N.GetString("Remarks");
|
||||
TimeoutLabel.Text = I18N.GetString("Timeout(Sec)");
|
||||
@@ -94,6 +96,8 @@ namespace Shadowsocks.View
|
||||
}
|
||||
server.password = PasswordTextBox.Text;
|
||||
server.method = EncryptionSelect.Text;
|
||||
server.plugin = PluginTextBox.Text;
|
||||
server.plugin_opts = PluginOptionsTextBox.Text;
|
||||
server.remarks = RemarksTextBox.Text;
|
||||
if (!int.TryParse(TimeoutTextBox.Text, out server.timeout))
|
||||
{
|
||||
@@ -127,6 +131,8 @@ namespace Shadowsocks.View
|
||||
PasswordTextBox.Text = server.password;
|
||||
ProxyPortTextBox.Text = _modifiedConfiguration.localPort.ToString();
|
||||
EncryptionSelect.Text = server.method ?? "aes-256-cfb";
|
||||
PluginTextBox.Text = server.plugin;
|
||||
PluginOptionsTextBox.Text = server.plugin_opts;
|
||||
RemarksTextBox.Text = server.remarks;
|
||||
TimeoutTextBox.Text = server.timeout.ToString();
|
||||
}
|
||||
|
||||
+79
-112
@@ -28,70 +28,27 @@
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.MyCancelButton = new System.Windows.Forms.Button();
|
||||
this.OKButton = new System.Windows.Forms.Button();
|
||||
this.UseProxyCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.ProxyAddrLabel = new System.Windows.Forms.Label();
|
||||
this.ProxyServerTextBox = new System.Windows.Forms.TextBox();
|
||||
this.ProxyPortLabel = new System.Windows.Forms.Label();
|
||||
this.ProxyPortTextBox = new System.Windows.Forms.TextBox();
|
||||
this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.ProxyTypeLabel = new System.Windows.Forms.Label();
|
||||
this.ProxyTypeComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.ProxyTimeoutTextBox = new System.Windows.Forms.TextBox();
|
||||
this.ProxyTimeoutLabel = new System.Windows.Forms.Label();
|
||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.ProxyNotificationLabel = new System.Windows.Forms.Label();
|
||||
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
this.tableLayoutPanel3.SuspendLayout();
|
||||
this.tableLayoutPanel2.SuspendLayout();
|
||||
this.tableLayoutPanel4.SuspendLayout();
|
||||
this.flowLayoutPanel1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// tableLayoutPanel1
|
||||
//
|
||||
this.tableLayoutPanel1.AutoSize = true;
|
||||
this.tableLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.tableLayoutPanel1.ColumnCount = 1;
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel3, 0, 3);
|
||||
this.tableLayoutPanel1.Controls.Add(this.UseProxyCheckBox, 0, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel2, 0, 2);
|
||||
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel4, 0, 1);
|
||||
this.tableLayoutPanel1.Location = new System.Drawing.Point(15, 15);
|
||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||
this.tableLayoutPanel1.RowCount = 4;
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(395, 123);
|
||||
this.tableLayoutPanel1.TabIndex = 0;
|
||||
//
|
||||
// tableLayoutPanel3
|
||||
//
|
||||
this.tableLayoutPanel3.AutoSize = true;
|
||||
this.tableLayoutPanel3.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.tableLayoutPanel3.ColumnCount = 2;
|
||||
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, 20F));
|
||||
this.tableLayoutPanel3.Controls.Add(this.MyCancelButton, 1, 0);
|
||||
this.tableLayoutPanel3.Controls.Add(this.OKButton, 0, 0);
|
||||
this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Right;
|
||||
this.tableLayoutPanel3.Location = new System.Drawing.Point(236, 94);
|
||||
this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(3, 3, 0, 3);
|
||||
this.tableLayoutPanel3.Name = "tableLayoutPanel3";
|
||||
this.tableLayoutPanel3.RowCount = 1;
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel3.Size = new System.Drawing.Size(159, 26);
|
||||
this.tableLayoutPanel3.TabIndex = 9;
|
||||
//
|
||||
// MyCancelButton
|
||||
//
|
||||
this.MyCancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.MyCancelButton.Dock = System.Windows.Forms.DockStyle.Right;
|
||||
this.MyCancelButton.Location = new System.Drawing.Point(84, 3);
|
||||
this.MyCancelButton.Margin = new System.Windows.Forms.Padding(3, 3, 0, 0);
|
||||
this.MyCancelButton.Name = "MyCancelButton";
|
||||
@@ -104,7 +61,6 @@
|
||||
// OKButton
|
||||
//
|
||||
this.OKButton.DialogResult = System.Windows.Forms.DialogResult.OK;
|
||||
this.OKButton.Dock = System.Windows.Forms.DockStyle.Right;
|
||||
this.OKButton.Location = new System.Drawing.Point(3, 3);
|
||||
this.OKButton.Margin = new System.Windows.Forms.Padding(3, 3, 3, 0);
|
||||
this.OKButton.Name = "OKButton";
|
||||
@@ -117,6 +73,7 @@
|
||||
// UseProxyCheckBox
|
||||
//
|
||||
this.UseProxyCheckBox.AutoSize = true;
|
||||
this.tableLayoutPanel1.SetColumnSpan(this.UseProxyCheckBox, 2);
|
||||
this.UseProxyCheckBox.Location = new System.Drawing.Point(3, 3);
|
||||
this.UseProxyCheckBox.Name = "UseProxyCheckBox";
|
||||
this.UseProxyCheckBox.Size = new System.Drawing.Size(78, 16);
|
||||
@@ -125,31 +82,11 @@
|
||||
this.UseProxyCheckBox.UseVisualStyleBackColor = true;
|
||||
this.UseProxyCheckBox.CheckedChanged += new System.EventHandler(this.UseProxyCheckBox_CheckedChanged);
|
||||
//
|
||||
// tableLayoutPanel2
|
||||
//
|
||||
this.tableLayoutPanel2.AutoSize = true;
|
||||
this.tableLayoutPanel2.ColumnCount = 4;
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel2.Controls.Add(this.ProxyAddrLabel, 0, 0);
|
||||
this.tableLayoutPanel2.Controls.Add(this.ProxyServerTextBox, 1, 0);
|
||||
this.tableLayoutPanel2.Controls.Add(this.ProxyPortLabel, 2, 0);
|
||||
this.tableLayoutPanel2.Controls.Add(this.ProxyPortTextBox, 3, 0);
|
||||
this.tableLayoutPanel2.Location = new System.Drawing.Point(3, 61);
|
||||
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
|
||||
this.tableLayoutPanel2.RowCount = 1;
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 27F));
|
||||
this.tableLayoutPanel2.Size = new System.Drawing.Size(389, 27);
|
||||
this.tableLayoutPanel2.TabIndex = 1;
|
||||
//
|
||||
// ProxyAddrLabel
|
||||
//
|
||||
this.ProxyAddrLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.ProxyAddrLabel.AutoSize = true;
|
||||
this.ProxyAddrLabel.Location = new System.Drawing.Point(3, 7);
|
||||
this.ProxyAddrLabel.Location = new System.Drawing.Point(3, 71);
|
||||
this.ProxyAddrLabel.Name = "ProxyAddrLabel";
|
||||
this.ProxyAddrLabel.Size = new System.Drawing.Size(65, 12);
|
||||
this.ProxyAddrLabel.TabIndex = 0;
|
||||
@@ -158,10 +95,10 @@
|
||||
// ProxyServerTextBox
|
||||
//
|
||||
this.ProxyServerTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.ProxyServerTextBox.Location = new System.Drawing.Point(74, 3);
|
||||
this.ProxyServerTextBox.Location = new System.Drawing.Point(74, 67);
|
||||
this.ProxyServerTextBox.MaxLength = 512;
|
||||
this.ProxyServerTextBox.Name = "ProxyServerTextBox";
|
||||
this.ProxyServerTextBox.Size = new System.Drawing.Size(135, 21);
|
||||
this.ProxyServerTextBox.Size = new System.Drawing.Size(142, 21);
|
||||
this.ProxyServerTextBox.TabIndex = 1;
|
||||
this.ProxyServerTextBox.WordWrap = false;
|
||||
//
|
||||
@@ -169,46 +106,27 @@
|
||||
//
|
||||
this.ProxyPortLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.ProxyPortLabel.AutoSize = true;
|
||||
this.ProxyPortLabel.Location = new System.Drawing.Point(215, 7);
|
||||
this.ProxyPortLabel.Location = new System.Drawing.Point(222, 71);
|
||||
this.ProxyPortLabel.Name = "ProxyPortLabel";
|
||||
this.ProxyPortLabel.Size = new System.Drawing.Size(65, 12);
|
||||
this.ProxyPortLabel.Size = new System.Drawing.Size(77, 12);
|
||||
this.ProxyPortLabel.TabIndex = 2;
|
||||
this.ProxyPortLabel.Text = "Proxy Port";
|
||||
//
|
||||
// ProxyPortTextBox
|
||||
//
|
||||
this.ProxyPortTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.ProxyPortTextBox.Location = new System.Drawing.Point(286, 3);
|
||||
this.ProxyPortTextBox.Location = new System.Drawing.Point(305, 67);
|
||||
this.ProxyPortTextBox.MaxLength = 10;
|
||||
this.ProxyPortTextBox.Name = "ProxyPortTextBox";
|
||||
this.ProxyPortTextBox.Size = new System.Drawing.Size(100, 21);
|
||||
this.ProxyPortTextBox.Size = new System.Drawing.Size(58, 21);
|
||||
this.ProxyPortTextBox.TabIndex = 3;
|
||||
this.ProxyPortTextBox.WordWrap = false;
|
||||
//
|
||||
// tableLayoutPanel4
|
||||
//
|
||||
this.tableLayoutPanel4.AutoSize = true;
|
||||
this.tableLayoutPanel4.ColumnCount = 4;
|
||||
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel4.Controls.Add(this.ProxyTypeLabel, 0, 0);
|
||||
this.tableLayoutPanel4.Controls.Add(this.ProxyTypeComboBox, 1, 0);
|
||||
this.tableLayoutPanel4.Controls.Add(this.ProxyTimeoutTextBox, 3, 0);
|
||||
this.tableLayoutPanel4.Controls.Add(this.ProxyTimeoutLabel, 2, 0);
|
||||
this.tableLayoutPanel4.Location = new System.Drawing.Point(3, 25);
|
||||
this.tableLayoutPanel4.Name = "tableLayoutPanel4";
|
||||
this.tableLayoutPanel4.RowCount = 1;
|
||||
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel4.Size = new System.Drawing.Size(387, 30);
|
||||
this.tableLayoutPanel4.TabIndex = 10;
|
||||
//
|
||||
// ProxyTypeLabel
|
||||
//
|
||||
this.ProxyTypeLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.ProxyTypeLabel.AutoSize = true;
|
||||
this.ProxyTypeLabel.Location = new System.Drawing.Point(3, 9);
|
||||
this.ProxyTypeLabel.Location = new System.Drawing.Point(3, 40);
|
||||
this.ProxyTypeLabel.Name = "ProxyTypeLabel";
|
||||
this.ProxyTypeLabel.Size = new System.Drawing.Size(65, 12);
|
||||
this.ProxyTypeLabel.TabIndex = 1;
|
||||
@@ -222,30 +140,86 @@
|
||||
this.ProxyTypeComboBox.Items.AddRange(new object[] {
|
||||
"SOCKS5",
|
||||
"HTTP"});
|
||||
this.ProxyTypeComboBox.Location = new System.Drawing.Point(74, 5);
|
||||
this.ProxyTypeComboBox.Location = new System.Drawing.Point(74, 36);
|
||||
this.ProxyTypeComboBox.Margin = new System.Windows.Forms.Padding(3, 5, 3, 5);
|
||||
this.ProxyTypeComboBox.Name = "ProxyTypeComboBox";
|
||||
this.ProxyTypeComboBox.Size = new System.Drawing.Size(121, 20);
|
||||
this.ProxyTypeComboBox.Size = new System.Drawing.Size(142, 20);
|
||||
this.ProxyTypeComboBox.TabIndex = 2;
|
||||
//
|
||||
// ProxyTimeoutTextBox
|
||||
//
|
||||
this.ProxyTimeoutTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.ProxyTimeoutTextBox.Location = new System.Drawing.Point(284, 4);
|
||||
this.ProxyTimeoutTextBox.Location = new System.Drawing.Point(305, 36);
|
||||
this.ProxyTimeoutTextBox.Name = "ProxyTimeoutTextBox";
|
||||
this.ProxyTimeoutTextBox.Size = new System.Drawing.Size(100, 21);
|
||||
this.ProxyTimeoutTextBox.Size = new System.Drawing.Size(58, 21);
|
||||
this.ProxyTimeoutTextBox.TabIndex = 3;
|
||||
//
|
||||
// ProxyTimeoutLabel
|
||||
//
|
||||
this.ProxyTimeoutLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.ProxyTimeoutLabel.AutoSize = true;
|
||||
this.ProxyTimeoutLabel.Location = new System.Drawing.Point(201, 9);
|
||||
this.ProxyTimeoutLabel.Location = new System.Drawing.Point(222, 40);
|
||||
this.ProxyTimeoutLabel.Name = "ProxyTimeoutLabel";
|
||||
this.ProxyTimeoutLabel.Size = new System.Drawing.Size(77, 12);
|
||||
this.ProxyTimeoutLabel.TabIndex = 4;
|
||||
this.ProxyTimeoutLabel.Text = "Timeout(Sec)";
|
||||
//
|
||||
// tableLayoutPanel1
|
||||
//
|
||||
this.tableLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.tableLayoutPanel1.ColumnCount = 4;
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 70F));
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 30F));
|
||||
this.tableLayoutPanel1.Controls.Add(this.UseProxyCheckBox, 0, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ProxyTypeLabel, 0, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ProxyPortTextBox, 3, 2);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ProxyTypeComboBox, 1, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ProxyTimeoutLabel, 2, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ProxyPortLabel, 2, 2);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ProxyTimeoutTextBox, 3, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ProxyServerTextBox, 1, 2);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ProxyAddrLabel, 0, 2);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ProxyNotificationLabel, 0, 3);
|
||||
this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel1, 0, 4);
|
||||
this.tableLayoutPanel1.Location = new System.Drawing.Point(15, 15);
|
||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||
this.tableLayoutPanel1.RowCount = 5;
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 21.95122F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 21.95122F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 21.95122F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 34.14634F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(366, 177);
|
||||
this.tableLayoutPanel1.TabIndex = 14;
|
||||
//
|
||||
// ProxyNotificationLabel
|
||||
//
|
||||
this.ProxyNotificationLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.ProxyNotificationLabel.AutoSize = true;
|
||||
this.tableLayoutPanel1.SetColumnSpan(this.ProxyNotificationLabel, 4);
|
||||
this.ProxyNotificationLabel.ForeColor = System.Drawing.Color.Red;
|
||||
this.ProxyNotificationLabel.Location = new System.Drawing.Point(3, 111);
|
||||
this.ProxyNotificationLabel.Name = "ProxyNotificationLabel";
|
||||
this.ProxyNotificationLabel.Size = new System.Drawing.Size(360, 12);
|
||||
this.ProxyNotificationLabel.TabIndex = 5;
|
||||
this.ProxyNotificationLabel.Text = "If server has a plugin, proxy will not be used";
|
||||
//
|
||||
// flowLayoutPanel1
|
||||
//
|
||||
this.flowLayoutPanel1.AutoSize = true;
|
||||
this.flowLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.tableLayoutPanel1.SetColumnSpan(this.flowLayoutPanel1, 4);
|
||||
this.flowLayoutPanel1.Controls.Add(this.MyCancelButton);
|
||||
this.flowLayoutPanel1.Controls.Add(this.OKButton);
|
||||
this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Right;
|
||||
this.flowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft;
|
||||
this.flowLayoutPanel1.Location = new System.Drawing.Point(204, 145);
|
||||
this.flowLayoutPanel1.Name = "flowLayoutPanel1";
|
||||
this.flowLayoutPanel1.Size = new System.Drawing.Size(159, 29);
|
||||
this.flowLayoutPanel1.TabIndex = 6;
|
||||
//
|
||||
// ProxyForm
|
||||
//
|
||||
this.AcceptButton = this.OKButton;
|
||||
@@ -254,7 +228,7 @@
|
||||
this.AutoSize = true;
|
||||
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.CancelButton = this.MyCancelButton;
|
||||
this.ClientSize = new System.Drawing.Size(441, 165);
|
||||
this.ClientSize = new System.Drawing.Size(448, 231);
|
||||
this.Controls.Add(this.tableLayoutPanel1);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||
this.MaximizeBox = false;
|
||||
@@ -266,32 +240,25 @@
|
||||
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ProxyForm_FormClosed);
|
||||
this.tableLayoutPanel1.ResumeLayout(false);
|
||||
this.tableLayoutPanel1.PerformLayout();
|
||||
this.tableLayoutPanel3.ResumeLayout(false);
|
||||
this.tableLayoutPanel2.ResumeLayout(false);
|
||||
this.tableLayoutPanel2.PerformLayout();
|
||||
this.tableLayoutPanel4.ResumeLayout(false);
|
||||
this.tableLayoutPanel4.PerformLayout();
|
||||
this.flowLayoutPanel1.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
|
||||
private System.Windows.Forms.CheckBox UseProxyCheckBox;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
|
||||
private System.Windows.Forms.Label ProxyAddrLabel;
|
||||
private System.Windows.Forms.TextBox ProxyServerTextBox;
|
||||
private System.Windows.Forms.Label ProxyPortLabel;
|
||||
private System.Windows.Forms.TextBox ProxyPortTextBox;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
|
||||
private System.Windows.Forms.Button MyCancelButton;
|
||||
private System.Windows.Forms.Button OKButton;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4;
|
||||
private System.Windows.Forms.Label ProxyTypeLabel;
|
||||
private System.Windows.Forms.ComboBox ProxyTypeComboBox;
|
||||
private System.Windows.Forms.TextBox ProxyTimeoutTextBox;
|
||||
private System.Windows.Forms.Label ProxyTimeoutLabel;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
|
||||
private System.Windows.Forms.Label ProxyNotificationLabel;
|
||||
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,7 @@ namespace Shadowsocks.View
|
||||
ProxyAddrLabel.Text = I18N.GetString("Proxy Addr");
|
||||
ProxyPortLabel.Text = I18N.GetString("Proxy Port");
|
||||
ProxyTimeoutLabel.Text = I18N.GetString("Timeout(Sec)");
|
||||
ProxyNotificationLabel.Text = I18N.GetString("If server has a plugin, proxy will not be used");
|
||||
OKButton.Text = I18N.GetString("OK");
|
||||
MyCancelButton.Text = I18N.GetString("Cancel");
|
||||
this.Text = I18N.GetString("Edit Proxy");
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Caseless.Fody" version="1.4.2" targetFramework="net462" developmentDependency="true" />
|
||||
<package id="Costura.Fody" version="1.3.3.0" targetFramework="net462" developmentDependency="true" />
|
||||
<package id="Cyotek.CircularBuffer" version="1.0.2" targetFramework="net462" />
|
||||
<package id="Fody" version="1.29.4" targetFramework="net462" developmentDependency="true" />
|
||||
<package id="Caseless.Fody" version="1.5.0" targetFramework="net462" developmentDependency="true" />
|
||||
<package id="Costura.Fody" version="1.4.1" targetFramework="net462" developmentDependency="true" />
|
||||
<package id="Fody" version="2.0.9" targetFramework="net462" developmentDependency="true" />
|
||||
<package id="GlobalHotKey" version="1.1.0" targetFramework="net462" />
|
||||
<package id="Newtonsoft.Json" version="10.0.1" targetFramework="net462" />
|
||||
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net462" />
|
||||
<package id="StringEx.CS" version="0.3.1" targetFramework="net462" developmentDependency="true" />
|
||||
<package id="ZXing.Net" version="0.15.0" targetFramework="net462" />
|
||||
</packages>
|
||||
@@ -66,9 +66,6 @@
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Cyotek.Collections.Generic.CircularBuffer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=58daa28b0b2de221, processorArchitecture=MSIL">
|
||||
<HintPath>3rd\Cyotek.CircularBuffer.1.0.2\lib\net20\Cyotek.Collections.Generic.CircularBuffer.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GlobalHotKey, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>3rd\GlobalHotKey.1.1.0\lib\GlobalHotKey.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
@@ -76,7 +73,7 @@
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="Microsoft.VisualBasic" />
|
||||
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>3rd\Newtonsoft.Json.10.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>3rd\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
@@ -100,6 +97,7 @@
|
||||
<Compile Include="Encryption\AEAD\AEADEncryptor.cs" />
|
||||
<Compile Include="Encryption\AEAD\AEADMbedTLSEncryptor.cs" />
|
||||
<Compile Include="Encryption\AEAD\AEADSodiumEncryptor.cs" />
|
||||
<Compile Include="Encryption\CircularBuffer\ByteCircularBuffer.cs" />
|
||||
<Compile Include="Encryption\EncryptorBase.cs" />
|
||||
<Compile Include="Encryption\EncryptorFactory.cs" />
|
||||
<Compile Include="Encryption\Exception\CryptoException.cs" />
|
||||
@@ -112,6 +110,7 @@
|
||||
<Compile Include="Encryption\Stream\StreamSodiumEncryptor.cs" />
|
||||
<Compile Include="Model\HotKeyConfig.cs" />
|
||||
<Compile Include="Model\ProxyConfig.cs" />
|
||||
<Compile Include="Model\SysproxyConfig.cs" />
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
@@ -146,6 +145,7 @@
|
||||
<Compile Include="Controller\Strategy\BalancingStrategy.cs" />
|
||||
<Compile Include="Controller\Strategy\StrategyManager.cs" />
|
||||
<Compile Include="Controller\Strategy\IStrategy.cs" />
|
||||
<Compile Include="Controller\Service\Sip003Plugin.cs" />
|
||||
<Compile Include="Proxy\Socks5Proxy.cs" />
|
||||
<Compile Include="Settings.cs" />
|
||||
<Compile Include="StringEx.cs" />
|
||||
@@ -266,9 +266,9 @@
|
||||
<Content Include="Data\ja.txt" />
|
||||
<Content Include="Data\privoxy_conf.txt" />
|
||||
<Content Include="Data\user-rule.txt" />
|
||||
<Content Include="FodyWeavers.xml">
|
||||
<None Include="FodyWeavers.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
</None>
|
||||
<Content Include="Resources\ssIn24.png" />
|
||||
<Content Include="Resources\ssOut24.png" />
|
||||
<Content Include="shadowsocks.ico" />
|
||||
@@ -342,12 +342,12 @@ foreach (var item in filesToCleanup)
|
||||
<Target Name="CleanReferenceCopyLocalPaths" AfterTargets="AfterBuild;NonWinFodyTarget">
|
||||
<CosturaCleanup Config="FodyWeavers.xml" Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
|
||||
</Target>
|
||||
<Import Project="3rd\Fody.1.29.4\build\dotnet\Fody.targets" Condition="Exists('3rd\Fody.1.29.4\build\dotnet\Fody.targets')" />
|
||||
<Import Project="3rd\Fody.2.0.9\build\netstandard1.4\Fody.targets" Condition="Exists('3rd\Fody.2.0.9\build\netstandard1.4\Fody.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
|
||||
<ErrorText>此项目引用这台计算机上缺少的 NuGet 程序包。使用 NuGet 程序包还原可下载这些程序包。有关详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('3rd\Fody.1.29.4\build\dotnet\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '3rd\Fody.1.29.4\build\dotnet\Fody.targets'))" />
|
||||
<Error Condition="!Exists('3rd\Fody.2.0.9\build\netstandard1.4\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '3rd\Fody.2.0.9\build\netstandard1.4\Fody.targets'))" />
|
||||
</Target>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
using Shadowsocks.Controller.Hotkeys;
|
||||
using Shadowsocks.Encryption.Stream;
|
||||
using Shadowsocks.Model;
|
||||
|
||||
namespace test
|
||||
{
|
||||
@@ -224,5 +225,136 @@ namespace test
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ParseAndGenerateShadowsocksUrl()
|
||||
{
|
||||
var server = new Server
|
||||
{
|
||||
server = "192.168.100.1",
|
||||
server_port = 8888,
|
||||
password = "test",
|
||||
method = "bf-cfb"
|
||||
};
|
||||
var serverCanonUrl = "ss://YmYtY2ZiOnRlc3RAMTkyLjE2OC4xMDAuMTo4ODg4";
|
||||
|
||||
var serverWithRemark = new Server
|
||||
{
|
||||
server = server.server,
|
||||
server_port = server.server_port,
|
||||
password = server.password,
|
||||
method = server.method,
|
||||
remarks = "example-server"
|
||||
};
|
||||
var serverWithRemarkCanonUrl = "ss://YmYtY2ZiOnRlc3RAMTkyLjE2OC4xMDAuMTo4ODg4#example-server";
|
||||
|
||||
var serverWithPlugin = new Server
|
||||
{
|
||||
server = server.server,
|
||||
server_port = server.server_port,
|
||||
password = server.password,
|
||||
method = server.method,
|
||||
plugin = "obfs-local",
|
||||
plugin_opts = "obfs=http;obfs-host=google.com"
|
||||
};
|
||||
var serverWithPluginCanonUrl =
|
||||
"ss://YmYtY2ZiOnRlc3Q@192.168.100.1:8888/?plugin=obfs-local%3bobfs%3dhttp%3bobfs-host%3dgoogle.com";
|
||||
|
||||
var serverWithPluginAndRemark = new Server
|
||||
{
|
||||
server = server.server,
|
||||
server_port = server.server_port,
|
||||
password = server.password,
|
||||
method = server.method,
|
||||
plugin = serverWithPlugin.plugin,
|
||||
plugin_opts = serverWithPlugin.plugin_opts,
|
||||
remarks = serverWithRemark.remarks
|
||||
};
|
||||
var serverWithPluginAndRemarkCanonUrl =
|
||||
"ss://YmYtY2ZiOnRlc3Q@192.168.100.1:8888/?plugin=obfs-local%3bobfs%3dhttp%3bobfs-host%3dgoogle.com#example-server";
|
||||
|
||||
RunParseShadowsocksUrlTest(
|
||||
string.Join(
|
||||
"\r\n",
|
||||
serverCanonUrl,
|
||||
"\r\n",
|
||||
"ss://YmYtY2ZiOnRlc3RAMTkyLjE2OC4xMDAuMTo4ODg4/",
|
||||
serverWithRemarkCanonUrl,
|
||||
"ss://YmYtY2ZiOnRlc3RAMTkyLjE2OC4xMDAuMTo4ODg4/#example-server"),
|
||||
new[]
|
||||
{
|
||||
server,
|
||||
server,
|
||||
serverWithRemark,
|
||||
serverWithRemark
|
||||
});
|
||||
|
||||
RunParseShadowsocksUrlTest(
|
||||
string.Join(
|
||||
"\r\n",
|
||||
"ss://YmYtY2ZiOnRlc3Q@192.168.100.1:8888",
|
||||
"\r\n",
|
||||
"ss://YmYtY2ZiOnRlc3Q@192.168.100.1:8888/",
|
||||
"ss://YmYtY2ZiOnRlc3Q@192.168.100.1:8888#example-server",
|
||||
"ss://YmYtY2ZiOnRlc3Q@192.168.100.1:8888/#example-server",
|
||||
serverWithPluginCanonUrl,
|
||||
serverWithPluginAndRemarkCanonUrl,
|
||||
"ss://YmYtY2ZiOnRlc3Q@192.168.100.1:8888/?plugin=obfs-local%3bobfs%3dhttp%3bobfs-host%3dgoogle.com&unsupported=1#example-server"),
|
||||
new[]
|
||||
{
|
||||
server,
|
||||
server,
|
||||
serverWithRemark,
|
||||
serverWithRemark,
|
||||
serverWithPlugin,
|
||||
serverWithPluginAndRemark,
|
||||
serverWithPluginAndRemark
|
||||
});
|
||||
|
||||
var generateUrlCases = new Dictionary<string, Server>
|
||||
{
|
||||
[serverCanonUrl] = server,
|
||||
[serverWithRemarkCanonUrl] = serverWithRemark,
|
||||
[serverWithPluginCanonUrl] = serverWithPlugin,
|
||||
[serverWithPluginAndRemarkCanonUrl] = serverWithPluginAndRemark
|
||||
};
|
||||
RunGenerateShadowsocksUrlTest(generateUrlCases);
|
||||
}
|
||||
|
||||
private static void RunParseShadowsocksUrlTest(string testCase, IReadOnlyList<Server> expected)
|
||||
{
|
||||
var actual = Server.GetServers(testCase);
|
||||
if (actual.Count != expected.Count)
|
||||
{
|
||||
Assert.Fail("Wrong number of configs. Expected: {0}. Actual: {1}", expected.Count, actual.Count);
|
||||
}
|
||||
|
||||
for (int i = 0; i < expected.Count; i++)
|
||||
{
|
||||
var expectedServer = expected[i];
|
||||
var actualServer = actual[i];
|
||||
|
||||
Assert.AreEqual(expectedServer.server, actualServer.server);
|
||||
Assert.AreEqual(expectedServer.server_port, actualServer.server_port);
|
||||
Assert.AreEqual(expectedServer.password, actualServer.password);
|
||||
Assert.AreEqual(expectedServer.method, actualServer.method);
|
||||
Assert.AreEqual(expectedServer.plugin, actualServer.plugin);
|
||||
Assert.AreEqual(expectedServer.plugin_opts, actualServer.plugin_opts);
|
||||
Assert.AreEqual(expectedServer.remarks, actualServer.remarks);
|
||||
Assert.AreEqual(expectedServer.timeout, actualServer.timeout);
|
||||
}
|
||||
}
|
||||
|
||||
private static void RunGenerateShadowsocksUrlTest(IReadOnlyDictionary<string, Server> testCases)
|
||||
{
|
||||
foreach (var testCase in testCases)
|
||||
{
|
||||
string expected = testCase.Key;
|
||||
Server config = testCase.Value;
|
||||
|
||||
var actual = ShadowsocksController.GetQRCode(config);
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user