Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6cd8e0750 | ||
|
|
cc6f77efa5 | ||
|
|
65b9c9f5fa | ||
|
|
1e7a8de34a | ||
|
|
355ab0e63d | ||
|
|
6d01cb074e | ||
|
|
17c60bf9cc | ||
|
|
41827f283e | ||
|
|
e7b559f1da | ||
|
|
63816ccdd1 | ||
|
|
206e0b8cb5 | ||
|
|
86eeba3b7d | ||
|
|
6df3250a9f | ||
|
|
011fc253bb | ||
|
|
c25e70e888 | ||
|
|
964f681d3b | ||
|
|
b63bab0d1a | ||
|
|
4b49431800 | ||
|
|
cfc6e674da | ||
|
|
0101aa3741 | ||
|
|
1e9739116f | ||
|
|
abcf3004ac | ||
|
|
8b7b8d8219 | ||
|
|
199c204b5d | ||
|
|
bce876f42e | ||
|
|
8fcb66b6ff | ||
|
|
da6466e247 | ||
|
|
24db6438bd | ||
|
|
c908caa584 | ||
|
|
a16e80743c | ||
|
|
aa9fd8ec06 | ||
|
|
02124ff3ad | ||
|
|
eec899b9a3 | ||
|
|
1979131e12 | ||
|
|
c09af5fe0f | ||
|
|
816e2b351d | ||
|
|
217e818339 | ||
|
|
f06f6f2fbb |
@@ -1,3 +1,19 @@
|
||||
3.3.6 2016-12-6
|
||||
- Refine system proxy mode switching logic,
|
||||
merge 'Switch to PAC' and 'Switch to Global' into
|
||||
'Switch system proxy mode'.
|
||||
- Don't store LogViewer window size in config file,
|
||||
now you can sync config between devices with different
|
||||
resolutions.
|
||||
- Add tag support for SS url
|
||||
- Add pre-release channel in update checker
|
||||
- Bug fixes and improvements
|
||||
|
||||
3.3.5 2016-11-7
|
||||
- Improve system power mode handling
|
||||
- Update mbed TLS to 2.4.0
|
||||
- Check .NET Framework version on startup
|
||||
|
||||
3.3.4 2016-10-21
|
||||
- Fix IE dial-up and VPN connection proxy settings
|
||||
not changed since release 3.3.3.
|
||||
|
||||
@@ -96,16 +96,18 @@ system temp folder, create a `shadowsocks_portable_mode.txt` into shadowsocks fo
|
||||
|
||||
#### Develop
|
||||
|
||||
Visual Studio 2015 is required.
|
||||
[Visual Studio 2015] & [.NET Framework 4.6.2 Developer Pack] are required.
|
||||
|
||||
#### License
|
||||
|
||||
GPLv3
|
||||
|
||||
|
||||
[Appveyor]: https://ci.appveyor.com/project/wongsyrone/shadowsocks-windows-0cn3i
|
||||
[Build Status]: https://ci.appveyor.com/api/projects/status/47784ryn365vw56w/branch/master?svg=true
|
||||
[Appveyor]: https://ci.appveyor.com/project/Noisyfox/shadowsocks-windows
|
||||
[Build Status]: https://ci.appveyor.com/api/projects/status/04idbevayrghcrh7/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
|
||||
[Visual Studio 2015]: https://www.visualstudio.com/downloads/
|
||||
[.NET Framework 4.6.2 Developer Pack]: https://www.microsoft.com/download/details.aspx?id=53321
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Net;
|
||||
@@ -123,6 +124,16 @@ namespace Shadowsocks.Controller
|
||||
else if (e is ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
else if (e is Win32Exception)
|
||||
{
|
||||
var ex = (Win32Exception) e;
|
||||
|
||||
// Win32Exception (0x80004005): A 32 bit processes cannot access modules of a 64 bit process.
|
||||
if ((uint) ex.ErrorCode != 0x80004005)
|
||||
{
|
||||
Info(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Info(e);
|
||||
|
||||
@@ -14,9 +14,9 @@ namespace Shadowsocks.Controller
|
||||
{
|
||||
class PACServer : Listener.Service
|
||||
{
|
||||
public static readonly string PAC_FILE = "pac.txt";
|
||||
public static readonly string USER_RULE_FILE = "user-rule.txt";
|
||||
public static readonly string USER_ABP_FILE = "abp.txt";
|
||||
public const string PAC_FILE = "pac.txt";
|
||||
public const string USER_RULE_FILE = "user-rule.txt";
|
||||
public const string USER_ABP_FILE = "abp.txt";
|
||||
|
||||
FileSystemWatcher PACFileWatcher;
|
||||
FileSystemWatcher UserRuleFileWatcher;
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
@@ -41,17 +42,10 @@ namespace Shadowsocks.Controller
|
||||
}
|
||||
}
|
||||
|
||||
public int RunningPort
|
||||
{
|
||||
get
|
||||
{
|
||||
return _runningPort;
|
||||
}
|
||||
}
|
||||
public int RunningPort => _runningPort;
|
||||
|
||||
public void Start(Configuration configuration)
|
||||
{
|
||||
Server server = configuration.GetCurrentServer();
|
||||
if (_process == null)
|
||||
{
|
||||
Process[] existingPrivoxy = Process.GetProcessesByName("ss_privoxy");
|
||||
@@ -90,6 +84,7 @@ namespace Shadowsocks.Controller
|
||||
if (_process != null)
|
||||
{
|
||||
KillProcess(_process);
|
||||
_process.Dispose();
|
||||
_process = null;
|
||||
}
|
||||
RefreshTrayArea();
|
||||
@@ -125,43 +120,32 @@ namespace Shadowsocks.Controller
|
||||
|
||||
private static bool IsChildProcess(Process process)
|
||||
{
|
||||
if (Utils.IsPortableMode())
|
||||
try
|
||||
{
|
||||
/*
|
||||
* Under PortableMode, we could identify it by the path of ss_privoxy.exe.
|
||||
*/
|
||||
try
|
||||
if (Utils.IsPortableMode())
|
||||
{
|
||||
/*
|
||||
* Sometimes Process.GetProcessesByName will return some processes that
|
||||
* are already dead, and that will cause exceptions here.
|
||||
* We could simply ignore those exceptions.
|
||||
* Under PortableMode, we could identify it by the path of ss_privoxy.exe.
|
||||
*/
|
||||
string path = process.MainModule.FileName;
|
||||
var path = process.MainModule.FileName;
|
||||
|
||||
return Utils.GetTempPath("ss_privoxy.exe").Equals(path);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.LogUsefulException(ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
else
|
||||
{
|
||||
var cmd = process.GetCommandLine();
|
||||
|
||||
return cmd.Contains(UniqueConfigFile);
|
||||
}
|
||||
catch (Win32Exception ex)
|
||||
{
|
||||
if ((uint) ex.ErrorCode != 0x80004005)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
/*
|
||||
* Sometimes Process.GetProcessesByName will return some processes that
|
||||
* are already dead, and that will cause exceptions here.
|
||||
* We could simply ignore those exceptions.
|
||||
*/
|
||||
Logging.LogUsefulException(ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -171,21 +155,12 @@ namespace Shadowsocks.Controller
|
||||
int defaultPort = 8123;
|
||||
try
|
||||
{
|
||||
IPGlobalProperties properties = IPGlobalProperties.GetIPGlobalProperties();
|
||||
IPEndPoint[] tcpEndPoints = properties.GetActiveTcpListeners();
|
||||
|
||||
List<int> usedPorts = new List<int>();
|
||||
foreach (IPEndPoint endPoint in IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners())
|
||||
{
|
||||
usedPorts.Add(endPoint.Port);
|
||||
}
|
||||
for (int port = defaultPort; port <= 65535; port++)
|
||||
{
|
||||
if (!usedPorts.Contains(port))
|
||||
{
|
||||
return port;
|
||||
}
|
||||
}
|
||||
// TCP stack please do me a favor
|
||||
TcpListener l = new TcpListener(IPAddress.Loopback, 0);
|
||||
l.Start();
|
||||
var port = ((IPEndPoint)l.LocalEndpoint).Port;
|
||||
l.Stop();
|
||||
return port;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -193,7 +168,6 @@ namespace Shadowsocks.Controller
|
||||
Logging.LogUsefulException(e);
|
||||
return defaultPort;
|
||||
}
|
||||
throw new Exception("No free port found.");
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
|
||||
@@ -168,6 +168,8 @@ namespace Shadowsocks.Controller
|
||||
private DateTime _startReceivingTime;
|
||||
private DateTime _startSendingTime;
|
||||
|
||||
private EndPoint _destEndPoint = null;
|
||||
|
||||
public TCPHandler(ShadowsocksController controller, Configuration config, TCPRelay tcprelay, Socket socket)
|
||||
{
|
||||
_controller = controller;
|
||||
@@ -182,7 +184,7 @@ namespace Shadowsocks.Controller
|
||||
|
||||
public void CreateRemote()
|
||||
{
|
||||
Server server = _controller.GetAServer(IStrategyCallerType.TCP, (IPEndPoint)_connection.RemoteEndPoint);
|
||||
Server server = _controller.GetAServer(IStrategyCallerType.TCP, (IPEndPoint)_connection.RemoteEndPoint, _destEndPoint);
|
||||
if (server == null || server.server == "")
|
||||
throw new ArgumentException("No server configured");
|
||||
lock (_encryptionLock)
|
||||
@@ -286,9 +288,11 @@ namespace Shadowsocks.Controller
|
||||
// +-----+-----+-------+------+----------+----------+
|
||||
// | 1 | 1 | X'00' | 1 | Variable | 2 |
|
||||
// +-----+-----+-------+------+----------+----------+
|
||||
// Skip first 3 bytes
|
||||
// Skip first 3 bytes, and read 2 more bytes to analysis the address.
|
||||
// 2 more bytes is designed if address is domain then we don't need to read once more to get the addr length.
|
||||
// TODO validate
|
||||
_connection.BeginReceive(_connetionRecvBuffer, 0, 3, SocketFlags.None, new AsyncCallback(handshakeReceive2Callback), null);
|
||||
_connection.BeginReceive(_connetionRecvBuffer, 0, 3 + 2, SocketFlags.None,
|
||||
new AsyncCallback(handshakeReceive2Callback), null);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -303,16 +307,36 @@ namespace Shadowsocks.Controller
|
||||
try
|
||||
{
|
||||
int bytesRead = _connection.EndReceive(ar);
|
||||
if (bytesRead >= 3)
|
||||
if (bytesRead >= 5)
|
||||
{
|
||||
_command = _connetionRecvBuffer[1];
|
||||
if (_command == 1)
|
||||
if (_command != 1 && _command != 3)
|
||||
{
|
||||
byte[] response = { 5, 0, 0, 1, 0, 0, 0, 0, 0, 0 };
|
||||
_connection.BeginSend(response, 0, response.Length, SocketFlags.None, new AsyncCallback(ResponseCallback), null);
|
||||
Logging.Debug("Unsupported CMD=" + _command);
|
||||
Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
int atyp = _connetionRecvBuffer[3];
|
||||
|
||||
switch (atyp)
|
||||
{
|
||||
case 1: // IPv4 address, 4 bytes
|
||||
ReadAddress(4 + 2 - 1);
|
||||
break;
|
||||
case 3: // domain name, length + str
|
||||
int len = _connetionRecvBuffer[4];
|
||||
ReadAddress(len + 2);
|
||||
break;
|
||||
case 4: // IPv6 address, 16 bytes
|
||||
ReadAddress(16 + 2 - 1);
|
||||
break;
|
||||
default:
|
||||
Logging.Debug("Unsupported ATYP=" + atyp);
|
||||
Close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (_command == 3)
|
||||
HandleUDPAssociate();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -327,6 +351,79 @@ namespace Shadowsocks.Controller
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadAddress(int bytesRemain)
|
||||
{
|
||||
Array.Copy(_connetionRecvBuffer, 3, _connetionRecvBuffer, 0, 2);
|
||||
|
||||
// Read the remain address bytes
|
||||
_connection.BeginReceive(_connetionRecvBuffer, 2, RecvSize - 2, SocketFlags.None, OnAddressFullyRead, bytesRemain);
|
||||
}
|
||||
|
||||
private void OnAddressFullyRead(IAsyncResult ar)
|
||||
{
|
||||
if (_closed) return;
|
||||
try
|
||||
{
|
||||
int bytesRead = _connection.EndReceive(ar);
|
||||
int bytesRemain = (int) ar.AsyncState;
|
||||
if (bytesRead >= bytesRemain)
|
||||
{
|
||||
_firstPacketLength = bytesRead + 2;
|
||||
|
||||
int atyp = _connetionRecvBuffer[0];
|
||||
|
||||
string dst_addr = "Unknown";
|
||||
int dst_port = -1;
|
||||
switch (atyp)
|
||||
{
|
||||
case 1: // IPv4 address, 4 bytes
|
||||
dst_addr = new IPAddress(_connetionRecvBuffer.Skip(1).Take(4).ToArray()).ToString();
|
||||
dst_port = (_connetionRecvBuffer[5] << 8) + _connetionRecvBuffer[6];
|
||||
|
||||
break;
|
||||
case 3: // domain name, length + str
|
||||
int len = _connetionRecvBuffer[1];
|
||||
dst_addr = System.Text.Encoding.UTF8.GetString(_connetionRecvBuffer, 2, len);
|
||||
dst_port = (_connetionRecvBuffer[len + 2] << 8) + _connetionRecvBuffer[len + 3];
|
||||
|
||||
break;
|
||||
case 4: // IPv6 address, 16 bytes
|
||||
dst_addr = $"[{new IPAddress(_connetionRecvBuffer.Skip(1).Take(16).ToArray())}]";
|
||||
dst_port = (_connetionRecvBuffer[17] << 8) + _connetionRecvBuffer[18];
|
||||
|
||||
break;
|
||||
}
|
||||
if (_config.isVerboseLogging)
|
||||
{
|
||||
Logging.Info($"connect to {dst_addr}:{dst_port}");
|
||||
}
|
||||
|
||||
_destEndPoint = SocketUtil.GetEndPoint(dst_addr, dst_port);
|
||||
|
||||
if (_command == 1)
|
||||
{
|
||||
byte[] response = {5, 0, 0, 1, 0, 0, 0, 0, 0, 0};
|
||||
_connection.BeginSend(response, 0, response.Length, SocketFlags.None,
|
||||
new AsyncCallback(ResponseCallback), null);
|
||||
}
|
||||
else if (_command == 3)
|
||||
{
|
||||
HandleUDPAssociate();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Debug("failed to recv data in Shadowsocks.Controller.TCPHandler.OnAddressFullyRead()");
|
||||
Close();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.LogUsefulException(e);
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleUDPAssociate()
|
||||
{
|
||||
IPEndPoint endPoint = (IPEndPoint)_connection.LocalEndPoint;
|
||||
@@ -612,8 +709,7 @@ namespace Shadowsocks.Controller
|
||||
{
|
||||
_startReceivingTime = DateTime.Now;
|
||||
session.Remote.BeginReceive(_remoteRecvBuffer, 0, RecvSize, SocketFlags.None, new AsyncCallback(PipeRemoteReceiveCallback), session);
|
||||
_connection.BeginReceive(_connetionRecvBuffer, 0, RecvSize, SocketFlags.None, new AsyncCallback(PipeConnectionReceiveCallback),
|
||||
new AsyncSession<bool>(session, true) /* to tell the callback this is the first time reading packet, and we haven't found the header yet. */);
|
||||
SendToServer(_firstPacketLength, session);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -663,59 +759,13 @@ namespace Shadowsocks.Controller
|
||||
try
|
||||
{
|
||||
int bytesRead = _connection.EndReceive(ar);
|
||||
_totalWrite += bytesRead;
|
||||
|
||||
var session = (AsyncSession<bool>) ar.AsyncState;
|
||||
var session = (AsyncSession) ar.AsyncState;
|
||||
var remote = session.Remote;
|
||||
|
||||
if (bytesRead > 0)
|
||||
{
|
||||
/*
|
||||
* Only the first packet contains the socks5 header, it doesn't make sense to parse every packets.
|
||||
* Also it's unnecessary to parse these data if we turn off the VerboseLogging.
|
||||
*/
|
||||
if (session.State && _config.isVerboseLogging)
|
||||
{
|
||||
int atyp = _connetionRecvBuffer[0];
|
||||
string dst_addr;
|
||||
int dst_port;
|
||||
switch (atyp)
|
||||
{
|
||||
case 1: // IPv4 address, 4 bytes
|
||||
dst_addr = new IPAddress(_connetionRecvBuffer.Skip(1).Take(4).ToArray()).ToString();
|
||||
dst_port = (_connetionRecvBuffer[5] << 8) + _connetionRecvBuffer[6];
|
||||
|
||||
Logging.Info($"connect to {dst_addr}:{dst_port}");
|
||||
session.State = false;
|
||||
break;
|
||||
case 3: // domain name, length + str
|
||||
int len = _connetionRecvBuffer[1];
|
||||
dst_addr = System.Text.Encoding.UTF8.GetString(_connetionRecvBuffer, 2, len);
|
||||
dst_port = (_connetionRecvBuffer[len + 2] << 8) + _connetionRecvBuffer[len + 3];
|
||||
|
||||
Logging.Info($"connect to {dst_addr}:{dst_port}");
|
||||
session.State = false;
|
||||
break;
|
||||
case 4: // IPv6 address, 16 bytes
|
||||
dst_addr = new IPAddress(_connetionRecvBuffer.Skip(1).Take(16).ToArray()).ToString();
|
||||
dst_port = (_connetionRecvBuffer[17] << 8) + _connetionRecvBuffer[18];
|
||||
|
||||
Logging.Info($"connect to [{dst_addr}]:{dst_port}");
|
||||
session.State = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int bytesToSend;
|
||||
lock (_encryptionLock)
|
||||
{
|
||||
_encryptor.Encrypt(_connetionRecvBuffer, bytesRead, _connetionSendBuffer, out bytesToSend);
|
||||
}
|
||||
_tcprelay.UpdateOutboundCounter(_server, bytesToSend);
|
||||
_startSendingTime = DateTime.Now;
|
||||
remote.BeginSend(_connetionSendBuffer, 0, bytesToSend, SocketFlags.None, new AsyncCallback(PipeRemoteSendCallback), session);
|
||||
IStrategy strategy = _controller.GetCurrentStrategy();
|
||||
strategy?.UpdateLastWrite(_server);
|
||||
SendToServer(bytesRead, session);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -731,6 +781,21 @@ namespace Shadowsocks.Controller
|
||||
}
|
||||
}
|
||||
|
||||
private void SendToServer(int length, AsyncSession session)
|
||||
{
|
||||
_totalWrite += length;
|
||||
int bytesToSend;
|
||||
lock (_encryptionLock)
|
||||
{
|
||||
_encryptor.Encrypt(_connetionRecvBuffer, length, _connetionSendBuffer, out bytesToSend);
|
||||
}
|
||||
_tcprelay.UpdateOutboundCounter(_server, bytesToSend);
|
||||
_startSendingTime = DateTime.Now;
|
||||
session.Remote.BeginSend(_connetionSendBuffer, 0, bytesToSend, SocketFlags.None, new AsyncCallback(PipeRemoteSendCallback), session);
|
||||
IStrategy strategy = _controller.GetCurrentStrategy();
|
||||
strategy?.UpdateLastWrite(_server);
|
||||
}
|
||||
|
||||
private void PipeRemoteSendCallback(IAsyncResult ar)
|
||||
{
|
||||
if (_closed) return;
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Shadowsocks.Controller
|
||||
UDPHandler handler = _cache.get(remoteEndPoint);
|
||||
if (handler == null)
|
||||
{
|
||||
handler = new UDPHandler(socket, _controller.GetAServer(IStrategyCallerType.UDP, remoteEndPoint), remoteEndPoint);
|
||||
handler = new UDPHandler(socket, _controller.GetAServer(IStrategyCallerType.UDP, remoteEndPoint, null/*TODO: fix this*/), remoteEndPoint);
|
||||
_cache.add(remoteEndPoint, handler);
|
||||
}
|
||||
handler.Send(firstPacket, length);
|
||||
|
||||
@@ -18,12 +18,13 @@ namespace Shadowsocks.Controller
|
||||
private Configuration config;
|
||||
public bool NewVersionFound;
|
||||
public string LatestVersionNumber;
|
||||
public string LatestVersionSuffix;
|
||||
public string LatestVersionName;
|
||||
public string LatestVersionURL;
|
||||
public string LatestVersionLocalName;
|
||||
public event EventHandler CheckUpdateCompleted;
|
||||
|
||||
public const string Version = "3.3.4";
|
||||
public const string Version = "3.3.6";
|
||||
|
||||
private class CheckUpdateTimer : System.Timers.Timer
|
||||
{
|
||||
@@ -83,17 +84,21 @@ namespace Shadowsocks.Controller
|
||||
{
|
||||
foreach (JObject release in result)
|
||||
{
|
||||
if ((bool)release["prerelease"])
|
||||
var isPreRelease = (bool) release["prerelease"];
|
||||
if (isPreRelease && !config.checkPreRelease)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
foreach (JObject asset in (JArray)release["assets"])
|
||||
{
|
||||
Asset ass = new Asset();
|
||||
ass.Parse(asset);
|
||||
if (ass.IsNewVersion(Version))
|
||||
Asset ass = Asset.ParseAsset(asset);
|
||||
if (ass != null)
|
||||
{
|
||||
asserts.Add(ass);
|
||||
ass.prerelease = isPreRelease;
|
||||
if (ass.IsNewVersion(Version, config.checkPreRelease))
|
||||
{
|
||||
asserts.Add(ass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,6 +111,7 @@ namespace Shadowsocks.Controller
|
||||
LatestVersionURL = asset.browser_download_url;
|
||||
LatestVersionNumber = asset.version;
|
||||
LatestVersionName = asset.name;
|
||||
LatestVersionSuffix = asset.suffix == null ? "" : $"-{asset.suffix}";
|
||||
|
||||
startDownload();
|
||||
}
|
||||
@@ -148,7 +154,7 @@ namespace Shadowsocks.Controller
|
||||
Logging.LogUsefulException(e.Error);
|
||||
return;
|
||||
}
|
||||
Logging.Debug($"New version {LatestVersionNumber} found: {LatestVersionLocalName}");
|
||||
Logging.Debug($"New version {LatestVersionNumber}{LatestVersionSuffix} found: {LatestVersionLocalName}");
|
||||
if (CheckUpdateCompleted != null)
|
||||
{
|
||||
CheckUpdateCompleted(this, new EventArgs());
|
||||
@@ -179,10 +185,38 @@ namespace Shadowsocks.Controller
|
||||
public string name;
|
||||
public string version;
|
||||
public string browser_download_url;
|
||||
public string suffix;
|
||||
|
||||
public bool IsNewVersion(string currentVersion)
|
||||
public static Asset ParseAsset(JObject assertJObject)
|
||||
{
|
||||
if (prerelease)
|
||||
var name = (string) assertJObject["name"];
|
||||
Match match = Regex.Match(name, @"^Shadowsocks-(?<version>\d+(?:\.\d+)*)(?:|-(?<suffix>.+))\.\w+$",
|
||||
RegexOptions.IgnoreCase);
|
||||
if (match.Success)
|
||||
{
|
||||
string version = match.Groups["version"].Value;
|
||||
|
||||
var asset = new Asset
|
||||
{
|
||||
browser_download_url = (string) assertJObject["browser_download_url"],
|
||||
name = name,
|
||||
version = version
|
||||
};
|
||||
|
||||
if (match.Groups["suffix"].Success)
|
||||
{
|
||||
asset.suffix = match.Groups["suffix"].Value;
|
||||
}
|
||||
|
||||
return asset;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsNewVersion(string currentVersion, bool checkPreRelease)
|
||||
{
|
||||
if (prerelease && !checkPreRelease)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -190,28 +224,8 @@ namespace Shadowsocks.Controller
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return CompareVersion(version, currentVersion) > 0;
|
||||
}
|
||||
|
||||
public void Parse(JObject asset)
|
||||
{
|
||||
name = (string)asset["name"];
|
||||
browser_download_url = (string)asset["browser_download_url"];
|
||||
version = ParseVersionFromURL(browser_download_url);
|
||||
prerelease = browser_download_url.IndexOf("prerelease", StringComparison.Ordinal) >= 0;
|
||||
}
|
||||
|
||||
private static string ParseVersionFromURL(string url)
|
||||
{
|
||||
Match match = Regex.Match(url, @".*Shadowsocks-win.*?-([\d\.]+)\.\w+", RegexOptions.IgnoreCase);
|
||||
if (match.Success)
|
||||
{
|
||||
if (match.Groups.Count == 2)
|
||||
{
|
||||
return match.Groups[1].Value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
var cmp = CompareVersion(version, currentVersion);
|
||||
return cmp > 0;
|
||||
}
|
||||
|
||||
public static int CompareVersion(string l, string r)
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using Shadowsocks.Controller.Strategy;
|
||||
@@ -139,12 +140,12 @@ namespace Shadowsocks.Controller
|
||||
return null;
|
||||
}
|
||||
|
||||
public Server GetAServer(IStrategyCallerType type, IPEndPoint localIPEndPoint)
|
||||
public Server GetAServer(IStrategyCallerType type, IPEndPoint localIPEndPoint, EndPoint destEndPoint)
|
||||
{
|
||||
IStrategy strategy = GetCurrentStrategy();
|
||||
if (strategy != null)
|
||||
{
|
||||
return strategy.GetAServer(type, localIPEndPoint);
|
||||
return strategy.GetAServer(type, localIPEndPoint, destEndPoint);
|
||||
}
|
||||
if (_config.index < 0)
|
||||
{
|
||||
@@ -186,7 +187,6 @@ namespace Shadowsocks.Controller
|
||||
public void ToggleEnable(bool enabled)
|
||||
{
|
||||
_config.enabled = enabled;
|
||||
UpdateSystemProxy();
|
||||
SaveConfig(_config);
|
||||
if (EnableStatusChanged != null)
|
||||
{
|
||||
@@ -197,7 +197,6 @@ namespace Shadowsocks.Controller
|
||||
public void ToggleGlobal(bool global)
|
||||
{
|
||||
_config.global = global;
|
||||
UpdateSystemProxy();
|
||||
SaveConfig(_config);
|
||||
if (EnableGlobalChanged != null)
|
||||
{
|
||||
@@ -272,6 +271,7 @@ namespace Shadowsocks.Controller
|
||||
{
|
||||
SystemProxy.Update(_config, true);
|
||||
}
|
||||
Encryption.RNG.Close();
|
||||
}
|
||||
|
||||
public void TouchPACFile()
|
||||
@@ -300,11 +300,15 @@ namespace Shadowsocks.Controller
|
||||
|
||||
public static string GetQRCode(Server server)
|
||||
{
|
||||
string parts = server.method;
|
||||
if (server.auth) parts += "-auth";
|
||||
parts += ":" + server.password + "@" + server.server + ":" + server.server_port;
|
||||
string tag = string.Empty;
|
||||
string auth = server.auth ? "-auth" : string.Empty;
|
||||
string parts = $"{server.method}{auth}:{server.password}@{server.server}:{server.server_port}";
|
||||
string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts));
|
||||
return "ss://" + base64;
|
||||
if(!server.remarks.IsNullOrEmpty())
|
||||
{
|
||||
tag = $"#{HttpUtility.UrlEncode(server.remarks, Encoding.UTF8)}";
|
||||
}
|
||||
return $"ss://{base64}{tag}";
|
||||
}
|
||||
|
||||
public void UpdatePACFromGFWList()
|
||||
@@ -326,7 +330,6 @@ namespace Shadowsocks.Controller
|
||||
public void SavePACUrl(string pacUrl)
|
||||
{
|
||||
_config.pacUrl = pacUrl;
|
||||
UpdateSystemProxy();
|
||||
SaveConfig(_config);
|
||||
if (ConfigChanged != null)
|
||||
{
|
||||
@@ -337,7 +340,6 @@ namespace Shadowsocks.Controller
|
||||
public void UseOnlinePAC(bool useOnlinePac)
|
||||
{
|
||||
_config.useOnlinePac = useOnlinePac;
|
||||
UpdateSystemProxy();
|
||||
SaveConfig(_config);
|
||||
if (ConfigChanged != null)
|
||||
{
|
||||
@@ -355,9 +357,20 @@ namespace Shadowsocks.Controller
|
||||
}
|
||||
}
|
||||
|
||||
public void ToggleCheckingPreRelease(bool enabled)
|
||||
{
|
||||
_config.checkPreRelease = enabled;
|
||||
Configuration.Save(_config);
|
||||
if (ConfigChanged != null)
|
||||
{
|
||||
ConfigChanged(this, new EventArgs());
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveLogViewerConfig(LogViewerConfig newConfig)
|
||||
{
|
||||
_config.logViewer = newConfig;
|
||||
newConfig.SaveSize();
|
||||
Configuration.Save(_config);
|
||||
if (ConfigChanged != null)
|
||||
{
|
||||
@@ -413,6 +426,7 @@ namespace Shadowsocks.Controller
|
||||
|
||||
protected void Reload()
|
||||
{
|
||||
Encryption.RNG.Reload();
|
||||
// some logic in configuration updated the config when saving, we need to read it again
|
||||
_config = Configuration.Load();
|
||||
StatisticsConfiguration = StatisticsStrategyConfiguration.Load();
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Shadowsocks.Controller.Strategy
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public Server GetAServer(IStrategyCallerType type, IPEndPoint localIPEndPoint)
|
||||
public Server GetAServer(IStrategyCallerType type, IPEndPoint localIPEndPoint, EndPoint destEndPoint)
|
||||
{
|
||||
var configs = _controller.GetCurrentConfiguration().configs;
|
||||
int index;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Shadowsocks.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
namespace Shadowsocks.Controller.Strategy
|
||||
@@ -78,7 +79,7 @@ namespace Shadowsocks.Controller.Strategy
|
||||
ChooseNewServer();
|
||||
}
|
||||
|
||||
public Server GetAServer(IStrategyCallerType type, System.Net.IPEndPoint localIPEndPoint)
|
||||
public Server GetAServer(IStrategyCallerType type, System.Net.IPEndPoint localIPEndPoint, EndPoint destEndPoint)
|
||||
{
|
||||
if (type == IStrategyCallerType.TCP)
|
||||
{
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Shadowsocks.Controller.Strategy
|
||||
/*
|
||||
* Get a new server to use in TCPRelay or UDPRelay
|
||||
*/
|
||||
Server GetAServer(IStrategyCallerType type, IPEndPoint localIPEndPoint);
|
||||
Server GetAServer(IStrategyCallerType type, IPEndPoint localIPEndPoint, EndPoint destEndPoint);
|
||||
|
||||
/*
|
||||
* TCPRelay will call this when latency of a server detected
|
||||
|
||||
@@ -127,7 +127,7 @@ namespace Shadowsocks.Controller.Strategy
|
||||
|
||||
public string Name => I18N.GetString("Choose by statistics");
|
||||
|
||||
public Server GetAServer(IStrategyCallerType type, IPEndPoint localIPEndPoint)
|
||||
public Server GetAServer(IStrategyCallerType type, IPEndPoint localIPEndPoint, EndPoint destEndPoint)
|
||||
{
|
||||
if (_currentServer == null)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Shadowsocks.Controller.Hotkeys
|
||||
{
|
||||
public class HotkeyCallbacks
|
||||
{
|
||||
|
||||
public static void InitInstance(ShadowsocksController controller)
|
||||
{
|
||||
if (Instance != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Instance = new HotkeyCallbacks(controller);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create hotkey callback handler delegate based on callback name
|
||||
/// </summary>
|
||||
/// <param name="methodname"></param>
|
||||
/// <returns></returns>
|
||||
public static Delegate GetCallback(string methodname)
|
||||
{
|
||||
if (methodname.IsNullOrEmpty()) throw new ArgumentException(nameof(methodname));
|
||||
MethodInfo dynMethod = typeof(HotkeyCallbacks).GetMethod(methodname,
|
||||
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase);
|
||||
return dynMethod == null ? null : Delegate.CreateDelegate(typeof(HotKeys.HotKeyCallBackHandler), Instance, dynMethod);
|
||||
}
|
||||
|
||||
#region Singleton
|
||||
|
||||
private static HotkeyCallbacks Instance { get; set; }
|
||||
|
||||
private readonly ShadowsocksController _controller;
|
||||
|
||||
private HotkeyCallbacks(ShadowsocksController controller)
|
||||
{
|
||||
_controller = controller;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Callbacks
|
||||
|
||||
private void SwitchSystemProxyCallback()
|
||||
{
|
||||
bool enabled = _controller.GetConfigurationCopy().enabled;
|
||||
_controller.ToggleEnable(!enabled);
|
||||
}
|
||||
|
||||
private void SwitchProxyModeCallback()
|
||||
{
|
||||
var config = _controller.GetConfigurationCopy();
|
||||
if (config.enabled == false) return;
|
||||
var currStatus = config.global;
|
||||
_controller.ToggleGlobal(!currStatus);
|
||||
}
|
||||
|
||||
private void SwitchAllowLanCallback()
|
||||
{
|
||||
var status = _controller.GetConfigurationCopy().shareOverLan;
|
||||
_controller.ToggleShareOverLAN(!status);
|
||||
}
|
||||
|
||||
private void ShowLogsCallback()
|
||||
{
|
||||
Program.MenuController.ShowLogForm_HotKey();
|
||||
}
|
||||
|
||||
private void ServerMoveUpCallback()
|
||||
{
|
||||
int currIndex;
|
||||
int serverCount;
|
||||
GetCurrServerInfo(out currIndex, out serverCount);
|
||||
if (currIndex - 1 < 0)
|
||||
{
|
||||
// revert to last server
|
||||
currIndex = serverCount - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
currIndex -= 1;
|
||||
}
|
||||
_controller.SelectServerIndex(currIndex);
|
||||
}
|
||||
|
||||
private void ServerMoveDownCallback()
|
||||
{
|
||||
int currIndex;
|
||||
int serverCount;
|
||||
GetCurrServerInfo(out currIndex, out serverCount);
|
||||
if (currIndex + 1 == serverCount)
|
||||
{
|
||||
// revert to first server
|
||||
currIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
currIndex += 1;
|
||||
}
|
||||
_controller.SelectServerIndex(currIndex);
|
||||
}
|
||||
|
||||
private void GetCurrServerInfo(out int currIndex, out int serverCount)
|
||||
{
|
||||
var currConfig = _controller.GetCurrentConfiguration();
|
||||
currIndex = currConfig.index;
|
||||
serverCount = currConfig.configs.Count;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
+173
-178
@@ -1,179 +1,174 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Input;
|
||||
using GlobalHotKey;
|
||||
|
||||
namespace Shadowsocks.Util
|
||||
{
|
||||
public static class HotKeys
|
||||
{
|
||||
private static HotKeyManager _hotKeyManager;
|
||||
|
||||
public delegate void HotKeyCallBackHandler();
|
||||
// map key and corresponding handler function
|
||||
private static Dictionary<HotKey, HotKeyCallBackHandler> _keymap = new Dictionary<HotKey, HotKeyCallBackHandler>();
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
_hotKeyManager = new HotKeyManager();
|
||||
_hotKeyManager.KeyPressed += HotKeyManagerPressed;
|
||||
}
|
||||
|
||||
public static void Destroy()
|
||||
{
|
||||
_hotKeyManager.KeyPressed -= HotKeyManagerPressed;
|
||||
_hotKeyManager.Dispose();
|
||||
}
|
||||
|
||||
private static void HotKeyManagerPressed(object sender, KeyPressedEventArgs e)
|
||||
{
|
||||
var hotkey = e.HotKey;
|
||||
HotKeyCallBackHandler callback;
|
||||
if (_keymap.TryGetValue(hotkey, out callback))
|
||||
callback();
|
||||
}
|
||||
|
||||
public static bool IsHotkeyExists( HotKey hotKey )
|
||||
{
|
||||
if (hotKey == null) throw new ArgumentNullException(nameof(hotKey));
|
||||
return _keymap.Any( v => v.Key.Equals( hotKey ) );
|
||||
}
|
||||
|
||||
public static bool IsCallbackExists( HotKeyCallBackHandler cb, out HotKey hotkey)
|
||||
{
|
||||
if (cb == null) throw new ArgumentNullException(nameof(cb));
|
||||
try
|
||||
{
|
||||
var key = _keymap.First(x => x.Value == cb).Key;
|
||||
hotkey = key;
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// not found
|
||||
hotkey = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public static string HotKey2Str( HotKey key )
|
||||
{
|
||||
if (key == null) throw new ArgumentNullException(nameof(key));
|
||||
return HotKey2Str( key.Key, key.Modifiers );
|
||||
}
|
||||
|
||||
public static string HotKey2Str( Key key, ModifierKeys modifier )
|
||||
{
|
||||
if (!Enum.IsDefined(typeof(Key), key))
|
||||
throw new InvalidEnumArgumentException(nameof(key), (int) key, typeof(Key));
|
||||
try
|
||||
{
|
||||
ModifierKeysConverter mkc = new ModifierKeysConverter();
|
||||
var keyStr = Enum.GetName(typeof(Key), key);
|
||||
var modifierStr = mkc.ConvertToInvariantString(modifier);
|
||||
|
||||
return $"{modifierStr}+{keyStr}";
|
||||
}
|
||||
catch (NotSupportedException)
|
||||
{
|
||||
// converter exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static HotKey Str2HotKey(string s)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (s.IsNullOrEmpty()) return null;
|
||||
int offset = s.LastIndexOf("+", StringComparison.OrdinalIgnoreCase);
|
||||
if (offset <= 0) return null;
|
||||
string modifierStr = s.Substring(0, offset).Trim();
|
||||
string keyStr = s.Substring(offset + 1).Trim();
|
||||
|
||||
KeyConverter kc = new KeyConverter();
|
||||
ModifierKeysConverter mkc = new ModifierKeysConverter();
|
||||
Key key = (Key) kc.ConvertFrom(keyStr.ToUpper());
|
||||
ModifierKeys modifier = (ModifierKeys) mkc.ConvertFrom(modifierStr.ToUpper());
|
||||
|
||||
return new HotKey(key, modifier);
|
||||
}
|
||||
catch (NotSupportedException)
|
||||
{
|
||||
// converter exception
|
||||
return null;
|
||||
}
|
||||
catch (NullReferenceException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Regist( HotKey key, HotKeyCallBackHandler callBack )
|
||||
{
|
||||
if (key == null)
|
||||
throw new ArgumentNullException(nameof(key));
|
||||
if (callBack == null)
|
||||
throw new ArgumentNullException(nameof(callBack));
|
||||
try
|
||||
{
|
||||
_hotKeyManager.Register(key);
|
||||
_keymap[key] = callBack;
|
||||
return true;
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
// already called this method with the specific hotkey
|
||||
// return success silently
|
||||
return true;
|
||||
}
|
||||
catch (Win32Exception)
|
||||
{
|
||||
// this hotkey already registered by other programs
|
||||
// notify user to change key
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Regist(Key key, ModifierKeys modifiers, HotKeyCallBackHandler callBack)
|
||||
{
|
||||
if (!Enum.IsDefined(typeof(Key), key))
|
||||
throw new InvalidEnumArgumentException(nameof(key), (int) key, typeof(Key));
|
||||
try
|
||||
{
|
||||
var hotkey = _hotKeyManager.Register(key, modifiers);
|
||||
_keymap[hotkey] = callBack;
|
||||
return true;
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
// already called this method with the specific hotkey
|
||||
// return success silently
|
||||
return true;
|
||||
}
|
||||
catch (Win32Exception)
|
||||
{
|
||||
// already registered by other programs
|
||||
// notify user to change key
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void UnRegist(HotKey key)
|
||||
{
|
||||
if (key == null)
|
||||
throw new ArgumentNullException(nameof(key));
|
||||
_hotKeyManager.Unregister(key);
|
||||
if(_keymap.ContainsKey(key))
|
||||
_keymap.Remove(key);
|
||||
}
|
||||
|
||||
public static IEnumerable<TControl> GetChildControls<TControl>(this Control control) where TControl : Control
|
||||
{
|
||||
var children = control.Controls.Count > 0 ? control.Controls.OfType<TControl>() : Enumerable.Empty<TControl>();
|
||||
return children.SelectMany(c => GetChildControls<TControl>(c)).Concat(children);
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Windows.Input;
|
||||
using GlobalHotKey;
|
||||
|
||||
namespace Shadowsocks.Controller.Hotkeys
|
||||
{
|
||||
public static class HotKeys
|
||||
{
|
||||
private static HotKeyManager _hotKeyManager;
|
||||
|
||||
public delegate void HotKeyCallBackHandler();
|
||||
// map key and corresponding handler function
|
||||
private static Dictionary<HotKey, HotKeyCallBackHandler> _keymap = new Dictionary<HotKey, HotKeyCallBackHandler>();
|
||||
|
||||
public static void Init(ShadowsocksController controller)
|
||||
{
|
||||
_hotKeyManager = new HotKeyManager();
|
||||
_hotKeyManager.KeyPressed += HotKeyManagerPressed;
|
||||
|
||||
HotkeyCallbacks.InitInstance(controller);
|
||||
}
|
||||
|
||||
public static void Destroy()
|
||||
{
|
||||
_hotKeyManager.KeyPressed -= HotKeyManagerPressed;
|
||||
_hotKeyManager.Dispose();
|
||||
}
|
||||
|
||||
private static void HotKeyManagerPressed(object sender, KeyPressedEventArgs e)
|
||||
{
|
||||
var hotkey = e.HotKey;
|
||||
HotKeyCallBackHandler callback;
|
||||
if (_keymap.TryGetValue(hotkey, out callback))
|
||||
callback();
|
||||
}
|
||||
|
||||
public static bool IsHotkeyExists( HotKey hotKey )
|
||||
{
|
||||
if (hotKey == null) throw new ArgumentNullException(nameof(hotKey));
|
||||
return _keymap.Any( v => v.Key.Equals( hotKey ) );
|
||||
}
|
||||
|
||||
public static bool IsCallbackExists( HotKeyCallBackHandler cb, out HotKey hotkey)
|
||||
{
|
||||
if (cb == null) throw new ArgumentNullException(nameof(cb));
|
||||
try
|
||||
{
|
||||
var key = _keymap.First(x => x.Value == cb).Key;
|
||||
hotkey = key;
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// not found
|
||||
hotkey = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public static string HotKey2Str( HotKey key )
|
||||
{
|
||||
if (key == null) throw new ArgumentNullException(nameof(key));
|
||||
return HotKey2Str( key.Key, key.Modifiers );
|
||||
}
|
||||
|
||||
public static string HotKey2Str( Key key, ModifierKeys modifier )
|
||||
{
|
||||
if (!Enum.IsDefined(typeof(Key), key))
|
||||
throw new InvalidEnumArgumentException(nameof(key), (int) key, typeof(Key));
|
||||
try
|
||||
{
|
||||
ModifierKeysConverter mkc = new ModifierKeysConverter();
|
||||
var keyStr = Enum.GetName(typeof(Key), key);
|
||||
var modifierStr = mkc.ConvertToInvariantString(modifier);
|
||||
|
||||
return $"{modifierStr}+{keyStr}";
|
||||
}
|
||||
catch (NotSupportedException)
|
||||
{
|
||||
// converter exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static HotKey Str2HotKey(string s)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (s.IsNullOrEmpty()) return null;
|
||||
int offset = s.LastIndexOf("+", StringComparison.OrdinalIgnoreCase);
|
||||
if (offset <= 0) return null;
|
||||
string modifierStr = s.Substring(0, offset).Trim();
|
||||
string keyStr = s.Substring(offset + 1).Trim();
|
||||
|
||||
KeyConverter kc = new KeyConverter();
|
||||
ModifierKeysConverter mkc = new ModifierKeysConverter();
|
||||
Key key = (Key) kc.ConvertFrom(keyStr.ToUpper());
|
||||
ModifierKeys modifier = (ModifierKeys) mkc.ConvertFrom(modifierStr.ToUpper());
|
||||
|
||||
return new HotKey(key, modifier);
|
||||
}
|
||||
catch (NotSupportedException)
|
||||
{
|
||||
// converter exception
|
||||
return null;
|
||||
}
|
||||
catch (NullReferenceException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Regist( HotKey key, HotKeyCallBackHandler callBack )
|
||||
{
|
||||
if (key == null)
|
||||
throw new ArgumentNullException(nameof(key));
|
||||
if (callBack == null)
|
||||
throw new ArgumentNullException(nameof(callBack));
|
||||
try
|
||||
{
|
||||
_hotKeyManager.Register(key);
|
||||
_keymap[key] = callBack;
|
||||
return true;
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
// already called this method with the specific hotkey
|
||||
// return success silently
|
||||
return true;
|
||||
}
|
||||
catch (Win32Exception)
|
||||
{
|
||||
// this hotkey already registered by other programs
|
||||
// notify user to change key
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Regist(Key key, ModifierKeys modifiers, HotKeyCallBackHandler callBack)
|
||||
{
|
||||
if (!Enum.IsDefined(typeof(Key), key))
|
||||
throw new InvalidEnumArgumentException(nameof(key), (int) key, typeof(Key));
|
||||
try
|
||||
{
|
||||
var hotkey = _hotKeyManager.Register(key, modifiers);
|
||||
_keymap[hotkey] = callBack;
|
||||
return true;
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
// already called this method with the specific hotkey
|
||||
// return success silently
|
||||
return true;
|
||||
}
|
||||
catch (Win32Exception)
|
||||
{
|
||||
// already registered by other programs
|
||||
// notify user to change key
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void UnRegist(HotKey key)
|
||||
{
|
||||
if (key == null)
|
||||
throw new ArgumentNullException(nameof(key));
|
||||
_hotKeyManager.Unregister(key);
|
||||
if(_keymap.ContainsKey(key))
|
||||
_keymap.Remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,25 +21,32 @@ namespace Shadowsocks.Controller
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
if (enabled)
|
||||
try
|
||||
{
|
||||
if (global)
|
||||
if (enabled)
|
||||
{
|
||||
WinINet.SetIEProxy(true, true, "127.0.0.1:" + config.localPort.ToString(), "");
|
||||
if (global)
|
||||
{
|
||||
WinINet.SetIEProxy(true, true, "127.0.0.1:" + config.localPort.ToString(), "");
|
||||
}
|
||||
else
|
||||
{
|
||||
string pacUrl;
|
||||
if (config.useOnlinePac && !config.pacUrl.IsNullOrEmpty())
|
||||
pacUrl = config.pacUrl;
|
||||
else
|
||||
pacUrl = $"http://127.0.0.1:{config.localPort}/pac?t={GetTimestamp(DateTime.Now)}";
|
||||
WinINet.SetIEProxy(true, false, "", pacUrl);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string pacUrl;
|
||||
if (config.useOnlinePac && !config.pacUrl.IsNullOrEmpty())
|
||||
pacUrl = config.pacUrl;
|
||||
else
|
||||
pacUrl = $"http://127.0.0.1:{config.localPort}/pac?t={GetTimestamp(DateTime.Now)}";
|
||||
WinINet.SetIEProxy(true, false, "", pacUrl);
|
||||
WinINet.SetIEProxy(false, false, "", "");
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (ProxyException ex)
|
||||
{
|
||||
WinINet.SetIEProxy(false, false, "", "");
|
||||
Logging.LogUsefulException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ Verbose Logging=详细记录日志
|
||||
Updates...=更新...
|
||||
Check for Updates...=检查更新
|
||||
Check for Updates at Startup=启动时检查更新
|
||||
Check Pre-release Version=检查测试版更新
|
||||
Edit Hotkeys...=编辑快捷键...
|
||||
About...=关于...
|
||||
Quit=退出
|
||||
@@ -91,8 +92,7 @@ Please input PAC Url=请输入 PAC 网址
|
||||
# HotkeySettings Form
|
||||
|
||||
Switch system proxy=切换系统代理状态
|
||||
Switch to PAC mode=切换到PAC模式
|
||||
Switch to Global mode=切换到全局模式
|
||||
Switch system proxy mode=切换系统代理模式
|
||||
Switch share over LAN=切换局域网共享
|
||||
Show Logs=显示日志
|
||||
Switch to prev server=切换上个服务器
|
||||
@@ -130,6 +130,7 @@ System Proxy On: =系统代理已启用:
|
||||
Running: Port {0}=正在运行:端口 {0}
|
||||
Unexpected error, shadowsocks will exit. Please report to=非预期错误,Shadowsocks将退出。请提交此错误到
|
||||
Unsupported operating system, use Windows Vista at least.=不支持的操作系统版本,最低需求为Windows Vista。
|
||||
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=注册热键失败
|
||||
|
||||
Binary file not shown.
@@ -27,6 +27,7 @@ Verbose Logging=詳細記錄日誌
|
||||
Updates...=更新...
|
||||
Check for Updates...=檢查更新
|
||||
Check for Updates at Startup=啟動時檢查更新
|
||||
Check Pre-release Version=檢查測試版更新
|
||||
Edit Hotkeys...=編輯捷徑鍵...
|
||||
About...=關於...
|
||||
Quit=退出
|
||||
@@ -90,13 +91,12 @@ Please input PAC Url=請輸入 PAC 網址
|
||||
|
||||
# HotkeySettings Form
|
||||
|
||||
Switch system proxy=切换系統代理狀態
|
||||
Switch to PAC mode=切换為PAC模式
|
||||
Switch to Global mode=切换為全局模式
|
||||
Switch share over LAN=切换區域網路共享
|
||||
Switch system proxy=切換系統代理狀態
|
||||
Switch system proxy mode=切換系統代理模式
|
||||
Switch share over LAN=切換區域網路共享
|
||||
Show Logs=顯示日誌
|
||||
Switch to prev server=切换上個伺服器
|
||||
Switch to next server=切换下個伺服器
|
||||
Switch to prev server=切換上個伺服器
|
||||
Switch to next server=切換下個伺服器
|
||||
Reg All=註冊全部捷徑鍵
|
||||
|
||||
# Messages
|
||||
@@ -130,6 +130,7 @@ System Proxy On: =系統代理已啟用:
|
||||
Running: Port {0}=正在運行:連接埠號碼 {0}
|
||||
Unexpected error, shadowsocks will exit. Please report to=非預期錯誤,Shadowsocks將退出。請提交此錯誤到
|
||||
Unsupported operating system, use Windows Vista at least.=不支持的作業系統版本,最低需求為Windows Vista。
|
||||
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=註冊捷徑鍵失敗
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Net;
|
||||
|
||||
@@ -237,10 +235,7 @@ namespace Shadowsocks.Encryption
|
||||
|
||||
protected static void randBytes(byte[] buf, int length)
|
||||
{
|
||||
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
|
||||
{
|
||||
rng.GetBytes(buf, 0, length);
|
||||
}
|
||||
RNG.GetBytes(buf, length);
|
||||
}
|
||||
|
||||
public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength)
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Shadowsocks.Encryption
|
||||
{
|
||||
public static class RNG
|
||||
{
|
||||
private static RNGCryptoServiceProvider _rng = null;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
if (_rng == null)
|
||||
_rng = new RNGCryptoServiceProvider();
|
||||
}
|
||||
|
||||
public static void Close()
|
||||
{
|
||||
if (_rng == null) return;
|
||||
_rng.Dispose();
|
||||
_rng = null;
|
||||
}
|
||||
|
||||
public static void Reload()
|
||||
{
|
||||
Close();
|
||||
Init();
|
||||
}
|
||||
|
||||
public static void GetBytes(byte[] buf, int len)
|
||||
{
|
||||
try
|
||||
{
|
||||
_rng.GetBytes(buf, 0, len);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// the backup way
|
||||
byte[] tmp = new byte[len];
|
||||
_rng.GetBytes(tmp);
|
||||
Buffer.BlockCopy(tmp, 0, buf, 0, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable → Regular
+8
-4
@@ -24,6 +24,7 @@ namespace Shadowsocks.Model
|
||||
public bool useOnlinePac;
|
||||
public bool availabilityStatistics;
|
||||
public bool autoCheckUpdate;
|
||||
public bool checkPreRelease;
|
||||
public bool isVerboseLogging;
|
||||
public LogViewerConfig logViewer;
|
||||
public ProxyConfig proxy;
|
||||
@@ -54,6 +55,11 @@ namespace Shadowsocks.Model
|
||||
string configContent = File.ReadAllText(CONFIG_FILE);
|
||||
Configuration config = JsonConvert.DeserializeObject<Configuration>(configContent);
|
||||
config.isDefault = false;
|
||||
|
||||
if (config.configs == null)
|
||||
config.configs = new List<Server>();
|
||||
if (config.configs.Count == 0)
|
||||
config.configs.Add(GetDefaultServer());
|
||||
if (config.localPort == 0)
|
||||
config.localPort = 1080;
|
||||
if (config.index == -1 && config.strategy == null)
|
||||
@@ -65,10 +71,8 @@ namespace Shadowsocks.Model
|
||||
if (config.hotkey == null)
|
||||
config.hotkey = new HotkeyConfig();
|
||||
|
||||
if (config.proxy.proxyType < ProxyConfig.PROXY_SOCKS5 || config.proxy.proxyType > ProxyConfig.PROXY_HTTP)
|
||||
{
|
||||
config.proxy.proxyType = ProxyConfig.PROXY_SOCKS5;
|
||||
}
|
||||
config.proxy.CheckConfig();
|
||||
|
||||
return config;
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
@@ -12,8 +12,7 @@ namespace Shadowsocks.Model
|
||||
public class HotkeyConfig
|
||||
{
|
||||
public string SwitchSystemProxy;
|
||||
public string ChangeToPac;
|
||||
public string ChangeToGlobal;
|
||||
public string SwitchSystemProxyMode;
|
||||
public string SwitchAllowLan;
|
||||
public string ShowLogs;
|
||||
public string ServerMoveUp;
|
||||
@@ -22,8 +21,7 @@ namespace Shadowsocks.Model
|
||||
public HotkeyConfig()
|
||||
{
|
||||
SwitchSystemProxy = "";
|
||||
ChangeToPac = "";
|
||||
ChangeToGlobal = "";
|
||||
SwitchSystemProxyMode = "";
|
||||
SwitchAllowLan = "";
|
||||
ShowLogs = "";
|
||||
ServerMoveUp = "";
|
||||
|
||||
@@ -1,105 +1,94 @@
|
||||
using Shadowsocks.View;
|
||||
using System;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Shadowsocks.Model
|
||||
{
|
||||
[Serializable]
|
||||
public class LogViewerConfig
|
||||
{
|
||||
public string fontName;
|
||||
public float fontSize;
|
||||
public string bgColor;
|
||||
public string textColor;
|
||||
public bool topMost;
|
||||
public bool wrapText;
|
||||
public bool toolbarShown;
|
||||
public int width;
|
||||
public int height;
|
||||
public int top;
|
||||
public int left;
|
||||
public bool maximized;
|
||||
|
||||
public Font Font { get; set; } = new Font("Consolas", 8F);
|
||||
|
||||
public Color BackgroundColor { get; set; } = Color.Black;
|
||||
|
||||
public Color TextColor { get; set; } = Color.White;
|
||||
|
||||
public LogViewerConfig()
|
||||
{
|
||||
fontName = "Consolas";
|
||||
fontSize = 8;
|
||||
bgColor = "black";
|
||||
textColor = "white";
|
||||
topMost = false;
|
||||
wrapText = false;
|
||||
toolbarShown = false;
|
||||
width = 600;
|
||||
height = 400;
|
||||
left = GetBestLeft();
|
||||
top = GetBestTop();
|
||||
maximized = true;
|
||||
}
|
||||
|
||||
|
||||
#region Size
|
||||
|
||||
public void SaveSize()
|
||||
{
|
||||
Properties.Settings.Default.Save();
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public int Width
|
||||
{
|
||||
get { return Properties.Settings.Default.LogViewerWidth; }
|
||||
set { Properties.Settings.Default.LogViewerWidth = value; }
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public int Height
|
||||
{
|
||||
get { return Properties.Settings.Default.LogViewerHeight; }
|
||||
set { Properties.Settings.Default.LogViewerHeight = value; }
|
||||
}
|
||||
[JsonIgnore]
|
||||
public int Top
|
||||
{
|
||||
get { return Properties.Settings.Default.LogViewerTop; }
|
||||
set { Properties.Settings.Default.LogViewerTop = value; }
|
||||
}
|
||||
[JsonIgnore]
|
||||
public int Left
|
||||
{
|
||||
get { return Properties.Settings.Default.LogViewerLeft; }
|
||||
set { Properties.Settings.Default.LogViewerLeft = value; }
|
||||
}
|
||||
[JsonIgnore]
|
||||
public bool Maximized
|
||||
{
|
||||
get { return Properties.Settings.Default.LogViewerMaximized; }
|
||||
set { Properties.Settings.Default.LogViewerMaximized = value; }
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
// Use GetBestTop() and GetBestLeft() to ensure the log viwer form can be always display IN screen.
|
||||
public int GetBestLeft()
|
||||
public int BestLeft
|
||||
{
|
||||
width = (width >= 400) ? width : 400; // set up the minimum size
|
||||
return Screen.PrimaryScreen.WorkingArea.Width - width;
|
||||
}
|
||||
|
||||
public int GetBestTop()
|
||||
{
|
||||
height = (height >= 200) ? height : 200; // set up the minimum size
|
||||
return Screen.PrimaryScreen.WorkingArea.Height - height;
|
||||
}
|
||||
|
||||
public Font GetFont()
|
||||
{
|
||||
try
|
||||
get
|
||||
{
|
||||
return new Font(fontName, fontSize, FontStyle.Regular);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return new Font("Console", 8F);
|
||||
int width = Width;
|
||||
width = (width >= 400) ? width : 400; // set up the minimum size
|
||||
return Screen.PrimaryScreen.WorkingArea.Width - width;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetFont(Font font)
|
||||
[JsonIgnore]
|
||||
public int BestTop
|
||||
{
|
||||
fontName = font.Name;
|
||||
fontSize = font.Size;
|
||||
}
|
||||
|
||||
public Color GetBackgroundColor()
|
||||
{
|
||||
try
|
||||
get
|
||||
{
|
||||
return ColorTranslator.FromHtml(bgColor);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return ColorTranslator.FromHtml("black");
|
||||
int height = Height;
|
||||
height = (height >= 200) ? height : 200; // set up the minimum size
|
||||
return Screen.PrimaryScreen.WorkingArea.Height - height;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetBackgroundColor(Color color)
|
||||
{
|
||||
bgColor = ColorTranslator.ToHtml(color);
|
||||
}
|
||||
#endregion
|
||||
|
||||
public Color GetTextColor()
|
||||
{
|
||||
try
|
||||
{
|
||||
return ColorTranslator.FromHtml(textColor);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return ColorTranslator.FromHtml("white");
|
||||
}
|
||||
}
|
||||
|
||||
public void SetTextColor(Color color)
|
||||
{
|
||||
textColor = ColorTranslator.ToHtml(color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,5 +25,13 @@ namespace Shadowsocks.Model
|
||||
proxyPort = 0;
|
||||
proxyTimeout = DefaultProxyTimeoutSec;
|
||||
}
|
||||
|
||||
public void CheckConfig()
|
||||
{
|
||||
if (proxyType < PROXY_SOCKS5 || proxyType > PROXY_HTTP)
|
||||
{
|
||||
proxyType = PROXY_SOCKS5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using System.Web;
|
||||
using Shadowsocks.Controller;
|
||||
|
||||
namespace Shadowsocks.Model
|
||||
@@ -10,8 +10,8 @@ namespace Shadowsocks.Model
|
||||
public class Server
|
||||
{
|
||||
public static readonly Regex
|
||||
UrlFinder = new Regex("^ss://((?:[A-Za-z0-9+/]+)|((?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?))$",
|
||||
RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
UrlFinder = new Regex("^(?i)ss://([A-Za-z0-9+-/=_]+)(#(.+))?$",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
DetailsParser = new Regex("^((?<method>.+?)(?<auth>-auth)??:(?<password>.*)@(?<hostname>.+?)" +
|
||||
":(?<port>\\d+?))$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
@@ -79,6 +79,9 @@ namespace Shadowsocks.Model
|
||||
var match = UrlFinder.Match(ssURL);
|
||||
if (!match.Success) throw new FormatException();
|
||||
var base64 = match.Groups[1].Value;
|
||||
var tag = match.Groups[3].Value;
|
||||
if (!tag.IsNullOrEmpty())
|
||||
remarks = HttpUtility.UrlDecode(tag, Encoding.UTF8);
|
||||
match = DetailsParser.Match(Encoding.UTF8.GetString(Convert.FromBase64String(
|
||||
base64.PadRight(base64.Length + (4 - base64.Length % 4) % 4, '='))));
|
||||
method = match.Groups["method"].Value;
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Windows.Forms;
|
||||
using Microsoft.Win32;
|
||||
|
||||
using Shadowsocks.Controller;
|
||||
using Shadowsocks.Controller.Hotkeys;
|
||||
using Shadowsocks.Util;
|
||||
using Shadowsocks.View;
|
||||
|
||||
@@ -13,9 +14,8 @@ namespace Shadowsocks
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
private static ShadowsocksController _controller;
|
||||
// XXX: Don't change this name
|
||||
private static MenuViewController _viewController;
|
||||
public static ShadowsocksController MainController { get; private set; }
|
||||
public static MenuViewController MenuController { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 应用程序的主入口点。
|
||||
@@ -31,6 +31,17 @@ namespace Shadowsocks
|
||||
return;
|
||||
}
|
||||
|
||||
// Check .NET Framework version
|
||||
if (!Utils.IsSupportedRuntimeVersion())
|
||||
{
|
||||
MessageBox.Show(I18N.GetString("Unsupported .NET Framework, please update to 4.6.2 or later."),
|
||||
"Shadowsocks Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
|
||||
Process.Start(
|
||||
"http://dotnetsocial.cloudapp.net/GetDotnet?tfm=.NETFramework,Version=v4.6.2");
|
||||
return;
|
||||
}
|
||||
|
||||
Utils.ReleaseMemory(true);
|
||||
using (Mutex mutex = new Mutex(false, $"Global\\Shadowsocks_{Application.StartupPath.GetHashCode()}"))
|
||||
{
|
||||
@@ -68,10 +79,10 @@ namespace Shadowsocks
|
||||
#else
|
||||
Logging.OpenLogFile();
|
||||
#endif
|
||||
_controller = new ShadowsocksController();
|
||||
_viewController = new MenuViewController(_controller);
|
||||
HotKeys.Init();
|
||||
_controller.Start();
|
||||
MainController = new ShadowsocksController();
|
||||
MenuController = new MenuViewController(MainController);
|
||||
HotKeys.Init(MainController);
|
||||
MainController.Start();
|
||||
Application.Run();
|
||||
}
|
||||
}
|
||||
@@ -81,9 +92,10 @@ namespace Shadowsocks
|
||||
{
|
||||
if (Interlocked.Increment(ref exited) == 1)
|
||||
{
|
||||
Logging.Error(e.ExceptionObject?.ToString());
|
||||
string errMsg = e.ExceptionObject.ToString();
|
||||
Logging.Error(errMsg);
|
||||
MessageBox.Show(
|
||||
$"{I18N.GetString("Unexpected error, shadowsocks will exit. Please report to")} https://github.com/shadowsocks/shadowsocks-windows/issues {Environment.NewLine}{e.ExceptionObject?.ToString()}",
|
||||
$"{I18N.GetString("Unexpected error, shadowsocks will exit. Please report to")} https://github.com/shadowsocks/shadowsocks-windows/issues {Environment.NewLine}{errMsg}",
|
||||
"Shadowsocks non-UI Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
Application.Exit();
|
||||
}
|
||||
@@ -91,12 +103,15 @@ namespace Shadowsocks
|
||||
|
||||
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
|
||||
{
|
||||
string errorMsg = $"Exception Type: {e.Exception.GetType().Name}{Environment.NewLine}Stack Trace:{Environment.NewLine}{e.Exception.StackTrace}";
|
||||
Logging.Error(errorMsg);
|
||||
MessageBox.Show(
|
||||
$"{I18N.GetString("Unexpected error, shadowsocks will exit. Please report to")} https://github.com/shadowsocks/shadowsocks-windows/issues {Environment.NewLine}{errorMsg}",
|
||||
"Shadowsocks UI Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
Application.Exit();
|
||||
if (Interlocked.Increment(ref exited) == 1)
|
||||
{
|
||||
string errorMsg = $"Exception Detail: {Environment.NewLine}{e.Exception}";
|
||||
Logging.Error(errorMsg);
|
||||
MessageBox.Show(
|
||||
$"{I18N.GetString("Unexpected error, shadowsocks will exit. Please report to")} https://github.com/shadowsocks/shadowsocks-windows/issues {Environment.NewLine}{errorMsg}",
|
||||
"Shadowsocks UI Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
Application.Exit();
|
||||
}
|
||||
}
|
||||
|
||||
private static void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
|
||||
@@ -105,9 +120,9 @@ namespace Shadowsocks
|
||||
{
|
||||
case PowerModes.Resume:
|
||||
Logging.Info("os wake up");
|
||||
if (_controller != null)
|
||||
if (MainController != null)
|
||||
{
|
||||
System.Timers.Timer timer = new System.Timers.Timer(5 * 1000);
|
||||
System.Timers.Timer timer = new System.Timers.Timer(10 * 1000);
|
||||
timer.Elapsed += Timer_Elapsed;
|
||||
timer.AutoReset = false;
|
||||
timer.Enabled = true;
|
||||
@@ -115,7 +130,11 @@ namespace Shadowsocks
|
||||
}
|
||||
break;
|
||||
case PowerModes.Suspend:
|
||||
_controller?.Stop();
|
||||
if (MainController != null)
|
||||
{
|
||||
MainController.Stop();
|
||||
Logging.Info("controller stopped");
|
||||
}
|
||||
Logging.Info("os suspend");
|
||||
break;
|
||||
}
|
||||
@@ -125,7 +144,11 @@ namespace Shadowsocks
|
||||
{
|
||||
try
|
||||
{
|
||||
_controller?.Start();
|
||||
if (MainController != null)
|
||||
{
|
||||
MainController.Start();
|
||||
Logging.Info("controller started");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -149,11 +172,15 @@ namespace Shadowsocks
|
||||
|
||||
private static void Application_ApplicationExit(object sender, EventArgs e)
|
||||
{
|
||||
// detach static event handlers
|
||||
Application.ApplicationExit -= Application_ApplicationExit;
|
||||
SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged;
|
||||
Application.ThreadException -= Application_ThreadException;
|
||||
HotKeys.Destroy();
|
||||
if (_controller != null)
|
||||
if (MainController != null)
|
||||
{
|
||||
_controller.Stop();
|
||||
_controller = null;
|
||||
MainController.Stop();
|
||||
MainController = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 此代码由工具生成。
|
||||
// 运行时版本:4.0.30319.42000
|
||||
//
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果
|
||||
// 重新生成代码,这些更改将会丢失。
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Shadowsocks.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("600")]
|
||||
public int LogViewerWidth {
|
||||
get {
|
||||
return ((int)(this["LogViewerWidth"]));
|
||||
}
|
||||
set {
|
||||
this["LogViewerWidth"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("400")]
|
||||
public int LogViewerHeight {
|
||||
get {
|
||||
return ((int)(this["LogViewerHeight"]));
|
||||
}
|
||||
set {
|
||||
this["LogViewerHeight"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
||||
public bool LogViewerMaximized {
|
||||
get {
|
||||
return ((bool)(this["LogViewerMaximized"]));
|
||||
}
|
||||
set {
|
||||
this["LogViewerMaximized"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("0")]
|
||||
public int LogViewerTop {
|
||||
get {
|
||||
return ((int)(this["LogViewerTop"]));
|
||||
}
|
||||
set {
|
||||
this["LogViewerTop"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("0")]
|
||||
public int LogViewerLeft {
|
||||
get {
|
||||
return ((int)(this["LogViewerLeft"]));
|
||||
}
|
||||
set {
|
||||
this["LogViewerLeft"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="Shadowsocks.Properties" GeneratedClassName="Settings">
|
||||
<Profiles />
|
||||
<Settings>
|
||||
<Setting Name="LogViewerWidth" Type="System.Int32" Scope="User">
|
||||
<Value Profile="(Default)">600</Value>
|
||||
</Setting>
|
||||
<Setting Name="LogViewerHeight" Type="System.Int32" Scope="User">
|
||||
<Value Profile="(Default)">400</Value>
|
||||
</Setting>
|
||||
<Setting Name="LogViewerMaximized" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">True</Value>
|
||||
</Setting>
|
||||
<Setting Name="LogViewerTop" Type="System.Int32" Scope="User">
|
||||
<Value Profile="(Default)">0</Value>
|
||||
</Setting>
|
||||
<Setting Name="LogViewerLeft" Type="System.Int32" Scope="User">
|
||||
<Value Profile="(Default)">0</Value>
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace Shadowsocks.Properties {
|
||||
|
||||
|
||||
// 通过此类可以处理设置类的特定事件:
|
||||
// 在更改某个设置的值之前将引发 SettingChanging 事件。
|
||||
// 在更改某个设置的值之后将引发 PropertyChanged 事件。
|
||||
// 在加载设置值之后将引发 SettingsLoaded 事件。
|
||||
// 在保存设置值之前将引发 SettingsSaving 事件。
|
||||
internal sealed partial class Settings {
|
||||
|
||||
public Settings() {
|
||||
// // 若要为保存和更改设置添加事件处理程序,请取消注释下列行:
|
||||
//
|
||||
// this.SettingChanging += this.SettingChangingEventHandler;
|
||||
//
|
||||
// this.SettingsSaving += this.SettingsSavingEventHandler;
|
||||
//
|
||||
}
|
||||
|
||||
private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) {
|
||||
// 在此处添加用于处理 SettingChangingEvent 事件的代码。
|
||||
}
|
||||
|
||||
private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) {
|
||||
// 在此处添加用于处理 SettingsSaving 事件的代码。
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shadowsocks.Util.SystemProxy
|
||||
{
|
||||
class ProxyException : Exception
|
||||
{
|
||||
public ProxyException()
|
||||
{
|
||||
}
|
||||
|
||||
public ProxyException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public ProxyException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
protected ProxyException(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Shadowsocks.Util.SystemProxy
|
||||
{
|
||||
public static class RAS
|
||||
internal static class RemoteAccessService
|
||||
{
|
||||
private enum RasFieldSizeConstants
|
||||
{
|
||||
@@ -69,22 +64,28 @@ namespace Shadowsocks.Util.SystemProxy
|
||||
#endregion
|
||||
|
||||
public int dwSize;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=(int)RasFieldSizeConstants.RAS_MaxEntryName + 1)]
|
||||
public string szEntryName;
|
||||
|
||||
public int dwFlags;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=(int)RasFieldSizeConstants.RAS_MaxPath + 1)]
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=(int)RasFieldSizeConstants.RAS_MaxPath + 1)]
|
||||
public string szPhonebookPath;
|
||||
}
|
||||
|
||||
[DllImport("rasapi32.dll", CharSet = CharSet.Auto)]
|
||||
private static extern uint RasEnumEntries(
|
||||
string reserved, // reserved, must be NULL
|
||||
string lpszPhonebook, // pointer to full path and file name of phone-book file
|
||||
[In, Out] RasEntryName[] lprasentryname, // buffer to receive phone-book entries
|
||||
ref int lpcb, // size in bytes of buffer
|
||||
out int lpcEntries // number of entries written to buffer
|
||||
// reserved, must be NULL
|
||||
string reserved,
|
||||
// pointer to full path and file name of phone-book file
|
||||
string lpszPhonebook,
|
||||
// buffer to receive phone-book entries
|
||||
[In, Out] RasEntryName[] lprasentryname,
|
||||
// size in bytes of buffer
|
||||
ref int lpcb,
|
||||
// number of entries written to buffer
|
||||
out int lpcEntries
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using Shadowsocks.Controller;
|
||||
@@ -131,20 +132,11 @@ namespace Shadowsocks.Util.SystemProxy
|
||||
// Throw an exception if this operation failed.
|
||||
if (!bReturn)
|
||||
{
|
||||
throw new Exception("InternetSetOption: " + Marshal.GetLastWin32Error());
|
||||
throw new ProxyException("InternetSetOption failed.", new Win32Exception());
|
||||
}
|
||||
|
||||
// Notify the system that the registry settings have been changed and cause
|
||||
// the proxy data to be reread from the registry for a handle.
|
||||
// bReturn = NativeMethods.InternetSetOption(
|
||||
// IntPtr.Zero,
|
||||
// INTERNET_OPTION.INTERNET_OPTION_SETTINGS_CHANGED,
|
||||
// IntPtr.Zero, 0);
|
||||
// if ( ! bReturn )
|
||||
// {
|
||||
// Logging.Error("InternetSetOption:INTERNET_OPTION_SETTINGS_CHANGED");
|
||||
// }
|
||||
|
||||
bReturn = NativeMethods.InternetSetOption(
|
||||
IntPtr.Zero,
|
||||
INTERNET_OPTION.INTERNET_OPTION_PROXY_SETTINGS_CHANGED,
|
||||
@@ -167,10 +159,10 @@ namespace Shadowsocks.Util.SystemProxy
|
||||
public static void SetIEProxy(bool enable, bool global, string proxyServer, string pacURL)
|
||||
{
|
||||
string[] allConnections = null;
|
||||
var ret = RAS.GetAllConns(ref allConnections);
|
||||
var ret = RemoteAccessService.GetAllConns(ref allConnections);
|
||||
|
||||
if (ret == 2)
|
||||
throw new Exception("Cannot get all connections");
|
||||
throw new ProxyException("Cannot get all connections");
|
||||
|
||||
if (ret == 1)
|
||||
{
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.Windows.Forms;
|
||||
using Microsoft.Win32;
|
||||
using Shadowsocks.Controller;
|
||||
@@ -26,7 +23,7 @@ namespace Shadowsocks.Util
|
||||
}
|
||||
}
|
||||
|
||||
public class Utils
|
||||
public static class Utils
|
||||
{
|
||||
private static bool? _portableMode;
|
||||
private static string TempPath = null;
|
||||
@@ -211,7 +208,7 @@ namespace Shadowsocks.Util
|
||||
return new BandwidthScaleInfo(f, unit, scale);
|
||||
}
|
||||
|
||||
public static RegistryKey OpenRegKey( string name, bool writable, RegistryHive hive = RegistryHive.CurrentUser )
|
||||
public static RegistryKey OpenRegKey(string name, bool writable, RegistryHive hive = RegistryHive.CurrentUser)
|
||||
{
|
||||
// we are building x86 binary for both x86 and x64, which will
|
||||
// cause problem when opening registry key
|
||||
@@ -224,24 +221,20 @@ namespace Shadowsocks.Util
|
||||
.OpenSubKey(name, writable);
|
||||
return userKey;
|
||||
}
|
||||
catch (UnauthorizedAccessException uae)
|
||||
{
|
||||
Logging.LogUsefulException(uae);
|
||||
return null;
|
||||
}
|
||||
catch (SecurityException se)
|
||||
{
|
||||
Logging.LogUsefulException(se);
|
||||
return null;
|
||||
}
|
||||
catch (ArgumentException ae)
|
||||
{
|
||||
MessageBox.Show("OpenRegKey: " + ae.ToString());
|
||||
return null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.LogUsefulException(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsWinVistaOrHigher() {
|
||||
public static bool IsWinVistaOrHigher()
|
||||
{
|
||||
return Environment.OSVersion.Version.Major > 5;
|
||||
}
|
||||
|
||||
@@ -249,5 +242,35 @@ namespace Shadowsocks.Util
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool SetProcessWorkingSetSize(IntPtr process,
|
||||
UIntPtr minimumWorkingSetSize, UIntPtr maximumWorkingSetSize);
|
||||
|
||||
|
||||
// See: https://msdn.microsoft.com/en-us/library/hh925568(v=vs.110).aspx
|
||||
public static bool IsSupportedRuntimeVersion()
|
||||
{
|
||||
/*
|
||||
* +-----------------------------------------------------------------+----------------------------+
|
||||
* | Version | Value of the Release DWORD |
|
||||
* +-----------------------------------------------------------------+----------------------------+
|
||||
* | .NET Framework 4.6.2 installed on Windows 10 Anniversary Update | 394802 |
|
||||
* | .NET Framework 4.6.2 installed on all other Windows OS versions | 394806 |
|
||||
* +-----------------------------------------------------------------+----------------------------+
|
||||
*/
|
||||
const int minSupportedRelease = 394802;
|
||||
|
||||
const string subkey = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\";
|
||||
using (var ndpKey = OpenRegKey(subkey, false, RegistryHive.LocalMachine))
|
||||
{
|
||||
if (ndpKey?.GetValue("Release") != null)
|
||||
{
|
||||
var releaseKey = (int)ndpKey.GetValue("Release");
|
||||
|
||||
if (releaseKey >= minSupportedRelease)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Shadowsocks.Util
|
||||
{
|
||||
public static class ViewUtils
|
||||
{
|
||||
public static IEnumerable<TControl> GetChildControls<TControl>(this Control control) where TControl : Control
|
||||
{
|
||||
if (control.Controls.Count == 0)
|
||||
{
|
||||
return Enumerable.Empty<TControl>();
|
||||
}
|
||||
|
||||
var children = control.Controls.OfType<TControl>().ToList();
|
||||
return children.SelectMany(GetChildControls<TControl>).Concat(children);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,7 +151,7 @@ namespace Shadowsocks.View
|
||||
_modifiedConfiguration = controller.GetConfigurationCopy();
|
||||
LoadConfiguration(_modifiedConfiguration);
|
||||
_lastSelectedIndex = _modifiedConfiguration.index;
|
||||
if (_lastSelectedIndex < 0)
|
||||
if (_lastSelectedIndex < 0 || _lastSelectedIndex >= ServersListBox.Items.Count)
|
||||
{
|
||||
_lastSelectedIndex = 0;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using Shadowsocks.Controller;
|
||||
using Shadowsocks.Controller.Hotkeys;
|
||||
using Shadowsocks.Model;
|
||||
using Shadowsocks.Properties;
|
||||
using Shadowsocks.Util;
|
||||
@@ -15,23 +16,18 @@ namespace Shadowsocks.View
|
||||
{
|
||||
public partial class HotkeySettingsForm : Form
|
||||
{
|
||||
private ShadowsocksController _controller;
|
||||
private readonly ShadowsocksController _controller;
|
||||
|
||||
// this is a copy of configuration that we are working on
|
||||
private HotkeyConfig _modifiedConfig;
|
||||
|
||||
private StringBuilder _sb = new StringBuilder();
|
||||
|
||||
private IEnumerable<TextBox> _allTextBoxes;
|
||||
|
||||
private static Label _lb = null;
|
||||
private static HotKeys.HotKeyCallBackHandler _callBack = null;
|
||||
private readonly IEnumerable<TextBox> _allTextBoxes;
|
||||
|
||||
public HotkeySettingsForm(ShadowsocksController controller)
|
||||
{
|
||||
InitializeComponent();
|
||||
UpdateTexts();
|
||||
this.Icon = Icon.FromHandle(Resources.ssw128.GetHicon());
|
||||
Icon = Icon.FromHandle(Resources.ssw128.GetHicon());
|
||||
|
||||
_controller = controller;
|
||||
_controller.ConfigChanged += controller_ConfigChanged;
|
||||
@@ -39,7 +35,7 @@ namespace Shadowsocks.View
|
||||
LoadCurrentConfiguration();
|
||||
|
||||
// get all textboxes belong to this form
|
||||
_allTextBoxes = HotKeys.GetChildControls<TextBox>(this.tableLayoutPanel1);
|
||||
_allTextBoxes = tableLayoutPanel1.GetChildControls<TextBox>();
|
||||
if (!_allTextBoxes.Any()) throw new Exception("Cannot get all textboxes");
|
||||
}
|
||||
|
||||
@@ -57,8 +53,7 @@ namespace Shadowsocks.View
|
||||
private void LoadConfiguration(HotkeyConfig config)
|
||||
{
|
||||
SwitchSystemProxyTextBox.Text = config.SwitchSystemProxy;
|
||||
ChangeToPacTextBox.Text = config.ChangeToPac;
|
||||
ChangeToGlobalTextBox.Text = config.ChangeToGlobal;
|
||||
SwitchProxyModeTextBox.Text = config.SwitchSystemProxyMode;
|
||||
SwitchAllowLanTextBox.Text = config.SwitchAllowLan;
|
||||
ShowLogsTextBox.Text = config.ShowLogs;
|
||||
ServerMoveUpTextBox.Text = config.ServerMoveUp;
|
||||
@@ -69,8 +64,7 @@ namespace Shadowsocks.View
|
||||
{
|
||||
// I18N stuff
|
||||
SwitchSystemProxyLabel.Text = I18N.GetString("Switch system proxy");
|
||||
ChangeToPacLabel.Text = I18N.GetString("Switch to PAC mode");
|
||||
ChangeToGlobalLabel.Text = I18N.GetString("Switch to Global mode");
|
||||
SwitchProxyModeLabel.Text = I18N.GetString("Switch system proxy mode");
|
||||
SwitchAllowLanLabel.Text = I18N.GetString("Switch share over LAN");
|
||||
ShowLogsLabel.Text = I18N.GetString("Show Logs");
|
||||
ServerMoveUpLabel.Text = I18N.GetString("Switch to prev server");
|
||||
@@ -78,7 +72,7 @@ namespace Shadowsocks.View
|
||||
btnOK.Text = I18N.GetString("OK");
|
||||
btnCancel.Text = I18N.GetString("Cancel");
|
||||
btnRegisterAll.Text = I18N.GetString("Reg All");
|
||||
this.Text = I18N.GetString("Edit Hotkeys...");
|
||||
Text = I18N.GetString("Edit Hotkeys...");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -86,7 +80,7 @@ namespace Shadowsocks.View
|
||||
/// </summary>
|
||||
private void HotkeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
_sb.Length = 0;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
//Combination key only
|
||||
if (e.Modifiers != 0)
|
||||
{
|
||||
@@ -94,15 +88,15 @@ namespace Shadowsocks.View
|
||||
// Windows key is reserved by operating system, we deny this key.
|
||||
if (e.Control)
|
||||
{
|
||||
_sb.Append("Ctrl+");
|
||||
sb.Append("Ctrl+");
|
||||
}
|
||||
if (e.Alt)
|
||||
{
|
||||
_sb.Append("Alt+");
|
||||
sb.Append("Alt+");
|
||||
}
|
||||
if (e.Shift)
|
||||
{
|
||||
_sb.Append("Shift+");
|
||||
sb.Append("Shift+");
|
||||
}
|
||||
|
||||
Keys keyvalue = (Keys) e.KeyValue;
|
||||
@@ -110,18 +104,18 @@ namespace Shadowsocks.View
|
||||
(keyvalue >= Keys.A && keyvalue <= Keys.Z) ||
|
||||
(keyvalue >= Keys.F1 && keyvalue <= Keys.F12))
|
||||
{
|
||||
_sb.Append(e.KeyCode);
|
||||
sb.Append(e.KeyCode);
|
||||
}
|
||||
else if (keyvalue >= Keys.D0 && keyvalue <= Keys.D9)
|
||||
{
|
||||
_sb.Append('D').Append((char) e.KeyValue);
|
||||
sb.Append('D').Append((char) e.KeyValue);
|
||||
}
|
||||
else if (keyvalue >= Keys.NumPad0 && keyvalue <= Keys.NumPad9)
|
||||
{
|
||||
_sb.Append("NumPad").Append((char) (e.KeyValue - 48));
|
||||
sb.Append("NumPad").Append((char) (e.KeyValue - 48));
|
||||
}
|
||||
}
|
||||
((TextBox) sender).Text = _sb.ToString();
|
||||
((TextBox) sender).Text = sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -129,8 +123,8 @@ namespace Shadowsocks.View
|
||||
/// </summary>
|
||||
private void HotkeyUp(object sender, KeyEventArgs e)
|
||||
{
|
||||
TextBox tb = sender as TextBox;
|
||||
string content = tb.Text.TrimEnd();
|
||||
var tb = (TextBox) sender;
|
||||
var content = tb.Text.TrimEnd();
|
||||
if (content.Length >= 1 && content[content.Length - 1] == '+')
|
||||
{
|
||||
tb.Text = "";
|
||||
@@ -139,7 +133,7 @@ namespace Shadowsocks.View
|
||||
|
||||
private void TextBox_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
TextBox tb = sender as TextBox;
|
||||
var tb = (TextBox) sender;
|
||||
|
||||
if (tb.Text == "")
|
||||
{
|
||||
@@ -150,15 +144,17 @@ namespace Shadowsocks.View
|
||||
|
||||
private void UnregHotkey(TextBox tb)
|
||||
{
|
||||
HotKeys.HotKeyCallBackHandler callBack;
|
||||
Label lb;
|
||||
|
||||
PrepareForHotkey(tb, out _callBack, out _lb);
|
||||
PrepareForHotkey(tb, out callBack, out lb);
|
||||
|
||||
UnregPrevHotkey(_callBack);
|
||||
UnregPrevHotkey(callBack);
|
||||
}
|
||||
|
||||
private void CancelButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.Close();
|
||||
Close();
|
||||
}
|
||||
|
||||
private void OKButton_Click(object sender, EventArgs e)
|
||||
@@ -179,7 +175,7 @@ namespace Shadowsocks.View
|
||||
|
||||
// All check passed, saving
|
||||
SaveConfig();
|
||||
this.Close();
|
||||
Close();
|
||||
}
|
||||
|
||||
private void RegisterAllButton_Click(object sender, EventArgs e)
|
||||
@@ -204,9 +200,12 @@ namespace Shadowsocks.View
|
||||
return false;
|
||||
}
|
||||
|
||||
PrepareForHotkey(tb, out _callBack, out _lb);
|
||||
HotKeys.HotKeyCallBackHandler callBack;
|
||||
Label lb;
|
||||
|
||||
UnregPrevHotkey(_callBack);
|
||||
PrepareForHotkey(tb, out callBack, out lb);
|
||||
|
||||
UnregPrevHotkey(callBack);
|
||||
|
||||
// try to register keys
|
||||
// if already registered by other progs
|
||||
@@ -219,8 +218,8 @@ namespace Shadowsocks.View
|
||||
// or change to another one
|
||||
// Transparent without color: first run or empty config
|
||||
|
||||
bool regResult = HotKeys.Regist(hotkey, _callBack);
|
||||
_lb.BackColor = regResult ? Color.Green : Color.Yellow;
|
||||
bool regResult = HotKeys.Regist(hotkey, callBack);
|
||||
lb.BackColor = regResult ? Color.Green : Color.Yellow;
|
||||
return regResult;
|
||||
}
|
||||
|
||||
@@ -237,8 +236,7 @@ namespace Shadowsocks.View
|
||||
private void SaveConfig()
|
||||
{
|
||||
_modifiedConfig.SwitchSystemProxy = SwitchSystemProxyTextBox.Text;
|
||||
_modifiedConfig.ChangeToPac = ChangeToPacTextBox.Text;
|
||||
_modifiedConfig.ChangeToGlobal = ChangeToGlobalTextBox.Text;
|
||||
_modifiedConfig.SwitchSystemProxyMode = SwitchProxyModeTextBox.Text;
|
||||
_modifiedConfig.SwitchAllowLan = SwitchAllowLanTextBox.Text;
|
||||
_modifiedConfig.ShowLogs = ShowLogsTextBox.Text;
|
||||
_modifiedConfig.ServerMoveUp = ServerMoveUpTextBox.Text;
|
||||
@@ -246,87 +244,7 @@ namespace Shadowsocks.View
|
||||
_controller.SaveHotkeyConfig(_modifiedConfig);
|
||||
}
|
||||
|
||||
#region Callbacks
|
||||
|
||||
private void SwitchSystemProxyCallback()
|
||||
{
|
||||
bool enabled = _controller.GetConfigurationCopy().enabled;
|
||||
_controller.ToggleEnable(!enabled);
|
||||
}
|
||||
|
||||
private void ChangeToPacCallback()
|
||||
{
|
||||
bool enabled = _controller.GetConfigurationCopy().enabled;
|
||||
if (enabled == false) return;
|
||||
_controller.ToggleGlobal(false);
|
||||
}
|
||||
|
||||
private void ChangeToGlobalCallback()
|
||||
{
|
||||
bool enabled = _controller.GetConfigurationCopy().enabled;
|
||||
if (enabled == false) return;
|
||||
_controller.ToggleGlobal(true);
|
||||
}
|
||||
|
||||
private void SwitchAllowLanCallback()
|
||||
{
|
||||
var status = _controller.GetConfigurationCopy().shareOverLan;
|
||||
_controller.ToggleShareOverLAN(!status);
|
||||
}
|
||||
|
||||
private void ShowLogsCallback()
|
||||
{
|
||||
// Get the current MenuViewController in this program via reflection
|
||||
FieldInfo fi = Assembly.GetExecutingAssembly().GetType("Shadowsocks.Program")
|
||||
.GetField("_viewController",
|
||||
BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.IgnoreCase);
|
||||
// To retrieve the value of a static field, pass null here
|
||||
var mvc = fi.GetValue(null) as MenuViewController;
|
||||
mvc.ShowLogForm_HotKey();
|
||||
}
|
||||
|
||||
private void ServerMoveUpCallback()
|
||||
{
|
||||
int currIndex;
|
||||
int serverCount;
|
||||
GetCurrServerInfo(out currIndex, out serverCount);
|
||||
if (currIndex - 1 < 0)
|
||||
{
|
||||
// revert to last server
|
||||
currIndex = serverCount - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
currIndex -= 1;
|
||||
}
|
||||
_controller.SelectServerIndex(currIndex);
|
||||
}
|
||||
|
||||
private void ServerMoveDownCallback()
|
||||
{
|
||||
int currIndex;
|
||||
int serverCount;
|
||||
GetCurrServerInfo(out currIndex, out serverCount);
|
||||
if (currIndex + 1 == serverCount)
|
||||
{
|
||||
// revert to first server
|
||||
currIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
currIndex += 1;
|
||||
}
|
||||
_controller.SelectServerIndex(currIndex);
|
||||
}
|
||||
|
||||
private void GetCurrServerInfo(out int currIndex, out int serverCount)
|
||||
{
|
||||
var currConfig = _controller.GetCurrentConfiguration();
|
||||
currIndex = currConfig.index;
|
||||
serverCount = currConfig.configs.Count;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Prepare hotkey
|
||||
|
||||
@@ -352,14 +270,14 @@ namespace Shadowsocks.View
|
||||
var labelName = rawName + "Label";
|
||||
var callbackName = rawName + "Callback";
|
||||
|
||||
var callback = GetDelegateViaMethodName(this.GetType(), callbackName);
|
||||
var callback = HotkeyCallbacks.GetCallback(callbackName);
|
||||
if (callback == null)
|
||||
{
|
||||
throw new Exception($"{callbackName} not found");
|
||||
}
|
||||
cb = callback as HotKeys.HotKeyCallBackHandler;
|
||||
|
||||
object label = GetFieldViaName(this.GetType(), labelName, this);
|
||||
var label = GetFieldViaName(GetType(), labelName, this);
|
||||
if (label == null)
|
||||
{
|
||||
throw new Exception($"{labelName} not found");
|
||||
@@ -384,23 +302,6 @@ namespace Shadowsocks.View
|
||||
return fi == null ? null : fi.GetValue(obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create hotkey callback handler delegate based on callback name
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="methodname"></param>
|
||||
/// <returns></returns>
|
||||
private Delegate GetDelegateViaMethodName(Type type, string methodname)
|
||||
{
|
||||
if (type == null) throw new ArgumentNullException(nameof(type));
|
||||
if (methodname.IsNullOrEmpty()) throw new ArgumentException(nameof(methodname));
|
||||
//HotkeySettingsForm form = new HotkeySettingsForm(_controller);
|
||||
Type delegateType = Type.GetType("Shadowsocks.Util.HotKeys").GetNestedType("HotKeyCallBackHandler");
|
||||
MethodInfo dynMethod = type.GetMethod(methodname,
|
||||
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase);
|
||||
return dynMethod == null ? null : Delegate.CreateDelegate(delegateType, this, dynMethod);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
+66
-97
@@ -34,15 +34,13 @@
|
||||
this.btnRegisterAll = new System.Windows.Forms.Button();
|
||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.SwitchSystemProxyLabel = new System.Windows.Forms.Label();
|
||||
this.ChangeToPacLabel = new System.Windows.Forms.Label();
|
||||
this.ChangeToGlobalLabel = new System.Windows.Forms.Label();
|
||||
this.SwitchProxyModeLabel = new System.Windows.Forms.Label();
|
||||
this.SwitchAllowLanLabel = new System.Windows.Forms.Label();
|
||||
this.ShowLogsLabel = new System.Windows.Forms.Label();
|
||||
this.ServerMoveUpLabel = new System.Windows.Forms.Label();
|
||||
this.ServerMoveDownLabel = new System.Windows.Forms.Label();
|
||||
this.SwitchSystemProxyTextBox = new System.Windows.Forms.TextBox();
|
||||
this.ChangeToPacTextBox = new System.Windows.Forms.TextBox();
|
||||
this.ChangeToGlobalTextBox = new System.Windows.Forms.TextBox();
|
||||
this.SwitchProxyModeTextBox = new System.Windows.Forms.TextBox();
|
||||
this.SwitchAllowLanTextBox = new System.Windows.Forms.TextBox();
|
||||
this.ShowLogsTextBox = new System.Windows.Forms.TextBox();
|
||||
this.ServerMoveUpTextBox = new System.Windows.Forms.TextBox();
|
||||
@@ -59,18 +57,18 @@
|
||||
flowLayoutPanel1.Controls.Add(this.btnCancel);
|
||||
flowLayoutPanel1.Controls.Add(this.btnRegisterAll);
|
||||
flowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.BottomUp;
|
||||
flowLayoutPanel1.Location = new System.Drawing.Point(0, 227);
|
||||
flowLayoutPanel1.Location = new System.Drawing.Point(0, 205);
|
||||
flowLayoutPanel1.Margin = new System.Windows.Forms.Padding(0);
|
||||
flowLayoutPanel1.Name = "flowLayoutPanel1";
|
||||
flowLayoutPanel1.Padding = new System.Windows.Forms.Padding(0, 0, 16, 0);
|
||||
flowLayoutPanel1.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
|
||||
flowLayoutPanel1.Size = new System.Drawing.Size(475, 44);
|
||||
flowLayoutPanel1.Size = new System.Drawing.Size(475, 43);
|
||||
flowLayoutPanel1.TabIndex = 6;
|
||||
//
|
||||
// btnOK
|
||||
//
|
||||
this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK;
|
||||
this.btnOK.Location = new System.Drawing.Point(333, 10);
|
||||
this.btnOK.Location = new System.Drawing.Point(333, 9);
|
||||
this.btnOK.Name = "btnOK";
|
||||
this.btnOK.Size = new System.Drawing.Size(123, 31);
|
||||
this.btnOK.TabIndex = 0;
|
||||
@@ -81,7 +79,7 @@
|
||||
// btnCancel
|
||||
//
|
||||
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.btnCancel.Location = new System.Drawing.Point(204, 10);
|
||||
this.btnCancel.Location = new System.Drawing.Point(204, 9);
|
||||
this.btnCancel.Name = "btnCancel";
|
||||
this.btnCancel.Size = new System.Drawing.Size(123, 31);
|
||||
this.btnCancel.TabIndex = 1;
|
||||
@@ -92,7 +90,7 @@
|
||||
// btnRegisterAll
|
||||
//
|
||||
this.btnRegisterAll.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.btnRegisterAll.Location = new System.Drawing.Point(75, 10);
|
||||
this.btnRegisterAll.Location = new System.Drawing.Point(75, 9);
|
||||
this.btnRegisterAll.Name = "btnRegisterAll";
|
||||
this.btnRegisterAll.Size = new System.Drawing.Size(123, 31);
|
||||
this.btnRegisterAll.TabIndex = 2;
|
||||
@@ -106,79 +104,65 @@
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel1.Controls.Add(this.SwitchSystemProxyLabel, 0, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ChangeToPacLabel, 0, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ChangeToGlobalLabel, 0, 2);
|
||||
this.tableLayoutPanel1.Controls.Add(this.SwitchAllowLanLabel, 0, 3);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ShowLogsLabel, 0, 4);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ServerMoveUpLabel, 0, 5);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ServerMoveDownLabel, 0, 6);
|
||||
this.tableLayoutPanel1.Controls.Add(flowLayoutPanel1, 0, 7);
|
||||
this.tableLayoutPanel1.Controls.Add(this.SwitchProxyModeLabel, 0, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.SwitchAllowLanLabel, 0, 2);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ShowLogsLabel, 0, 3);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ServerMoveUpLabel, 0, 4);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ServerMoveDownLabel, 0, 5);
|
||||
this.tableLayoutPanel1.Controls.Add(flowLayoutPanel1, 0, 6);
|
||||
this.tableLayoutPanel1.Controls.Add(this.SwitchSystemProxyTextBox, 1, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ChangeToPacTextBox, 1, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ChangeToGlobalTextBox, 1, 2);
|
||||
this.tableLayoutPanel1.Controls.Add(this.SwitchAllowLanTextBox, 1, 3);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ShowLogsTextBox, 1, 4);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ServerMoveUpTextBox, 1, 5);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ServerMoveDownTextBox, 1, 6);
|
||||
this.tableLayoutPanel1.Controls.Add(this.SwitchProxyModeTextBox, 1, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.SwitchAllowLanTextBox, 1, 2);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ShowLogsTextBox, 1, 3);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ServerMoveUpTextBox, 1, 4);
|
||||
this.tableLayoutPanel1.Controls.Add(this.ServerMoveDownTextBox, 1, 5);
|
||||
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
|
||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||
this.tableLayoutPanel1.RowCount = 8;
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.16667F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.16667F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.16667F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.16667F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.16667F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.77778F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.38889F));
|
||||
this.tableLayoutPanel1.RowCount = 7;
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.50485F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.50485F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.50485F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.50485F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 17.21683F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.76375F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F));
|
||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(475, 271);
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(491, 248);
|
||||
this.tableLayoutPanel1.TabIndex = 0;
|
||||
//
|
||||
// SwitchSystemProxyLabel
|
||||
//
|
||||
this.SwitchSystemProxyLabel.AutoSize = true;
|
||||
this.SwitchSystemProxyLabel.Dock = System.Windows.Forms.DockStyle.Right;
|
||||
this.SwitchSystemProxyLabel.Location = new System.Drawing.Point(25, 0);
|
||||
this.SwitchSystemProxyLabel.Location = new System.Drawing.Point(50, 0);
|
||||
this.SwitchSystemProxyLabel.Margin = new System.Windows.Forms.Padding(8, 0, 8, 0);
|
||||
this.SwitchSystemProxyLabel.Name = "SwitchSystemProxyLabel";
|
||||
this.SwitchSystemProxyLabel.Size = new System.Drawing.Size(147, 32);
|
||||
this.SwitchSystemProxyLabel.Size = new System.Drawing.Size(147, 34);
|
||||
this.SwitchSystemProxyLabel.TabIndex = 0;
|
||||
this.SwitchSystemProxyLabel.Text = "Enable System Proxy";
|
||||
this.SwitchSystemProxyLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
//
|
||||
// ChangeToPacLabel
|
||||
// SwitchProxyModeLabel
|
||||
//
|
||||
this.ChangeToPacLabel.AutoSize = true;
|
||||
this.ChangeToPacLabel.Dock = System.Windows.Forms.DockStyle.Right;
|
||||
this.ChangeToPacLabel.Location = new System.Drawing.Point(135, 32);
|
||||
this.ChangeToPacLabel.Margin = new System.Windows.Forms.Padding(8, 0, 8, 0);
|
||||
this.ChangeToPacLabel.Name = "ChangeToPacLabel";
|
||||
this.ChangeToPacLabel.Size = new System.Drawing.Size(37, 32);
|
||||
this.ChangeToPacLabel.TabIndex = 1;
|
||||
this.ChangeToPacLabel.Text = "PAC";
|
||||
this.ChangeToPacLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
//
|
||||
// ChangeToGlobalLabel
|
||||
//
|
||||
this.ChangeToGlobalLabel.AutoSize = true;
|
||||
this.ChangeToGlobalLabel.Dock = System.Windows.Forms.DockStyle.Right;
|
||||
this.ChangeToGlobalLabel.Location = new System.Drawing.Point(119, 64);
|
||||
this.ChangeToGlobalLabel.Margin = new System.Windows.Forms.Padding(8, 0, 8, 0);
|
||||
this.ChangeToGlobalLabel.Name = "ChangeToGlobalLabel";
|
||||
this.ChangeToGlobalLabel.Size = new System.Drawing.Size(53, 32);
|
||||
this.ChangeToGlobalLabel.TabIndex = 2;
|
||||
this.ChangeToGlobalLabel.Text = "Global";
|
||||
this.ChangeToGlobalLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
this.SwitchProxyModeLabel.AutoSize = true;
|
||||
this.SwitchProxyModeLabel.Dock = System.Windows.Forms.DockStyle.Right;
|
||||
this.SwitchProxyModeLabel.Location = new System.Drawing.Point(8, 34);
|
||||
this.SwitchProxyModeLabel.Margin = new System.Windows.Forms.Padding(8, 0, 8, 0);
|
||||
this.SwitchProxyModeLabel.Name = "SwitchProxyModeLabel";
|
||||
this.SwitchProxyModeLabel.Size = new System.Drawing.Size(189, 34);
|
||||
this.SwitchProxyModeLabel.TabIndex = 1;
|
||||
this.SwitchProxyModeLabel.Text = "Switch System Proxy Mode";
|
||||
this.SwitchProxyModeLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
//
|
||||
// SwitchAllowLanLabel
|
||||
//
|
||||
this.SwitchAllowLanLabel.AutoSize = true;
|
||||
this.SwitchAllowLanLabel.Dock = System.Windows.Forms.DockStyle.Right;
|
||||
this.SwitchAllowLanLabel.Location = new System.Drawing.Point(8, 96);
|
||||
this.SwitchAllowLanLabel.Location = new System.Drawing.Point(33, 68);
|
||||
this.SwitchAllowLanLabel.Margin = new System.Windows.Forms.Padding(8, 0, 8, 0);
|
||||
this.SwitchAllowLanLabel.Name = "SwitchAllowLanLabel";
|
||||
this.SwitchAllowLanLabel.Size = new System.Drawing.Size(164, 32);
|
||||
this.SwitchAllowLanLabel.Size = new System.Drawing.Size(164, 34);
|
||||
this.SwitchAllowLanLabel.TabIndex = 3;
|
||||
this.SwitchAllowLanLabel.Text = "Allow Clients from LAN";
|
||||
this.SwitchAllowLanLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
@@ -187,10 +171,10 @@
|
||||
//
|
||||
this.ShowLogsLabel.AutoSize = true;
|
||||
this.ShowLogsLabel.Dock = System.Windows.Forms.DockStyle.Right;
|
||||
this.ShowLogsLabel.Location = new System.Drawing.Point(82, 128);
|
||||
this.ShowLogsLabel.Location = new System.Drawing.Point(107, 102);
|
||||
this.ShowLogsLabel.Margin = new System.Windows.Forms.Padding(8, 0, 8, 0);
|
||||
this.ShowLogsLabel.Name = "ShowLogsLabel";
|
||||
this.ShowLogsLabel.Size = new System.Drawing.Size(90, 32);
|
||||
this.ShowLogsLabel.Size = new System.Drawing.Size(90, 34);
|
||||
this.ShowLogsLabel.TabIndex = 4;
|
||||
this.ShowLogsLabel.Text = "Show Logs...";
|
||||
this.ShowLogsLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
@@ -199,10 +183,10 @@
|
||||
//
|
||||
this.ServerMoveUpLabel.AutoSize = true;
|
||||
this.ServerMoveUpLabel.Dock = System.Windows.Forms.DockStyle.Right;
|
||||
this.ServerMoveUpLabel.Location = new System.Drawing.Point(103, 160);
|
||||
this.ServerMoveUpLabel.Location = new System.Drawing.Point(128, 136);
|
||||
this.ServerMoveUpLabel.Margin = new System.Windows.Forms.Padding(8, 0, 8, 0);
|
||||
this.ServerMoveUpLabel.Name = "ServerMoveUpLabel";
|
||||
this.ServerMoveUpLabel.Size = new System.Drawing.Size(69, 34);
|
||||
this.ServerMoveUpLabel.Size = new System.Drawing.Size(69, 35);
|
||||
this.ServerMoveUpLabel.TabIndex = 4;
|
||||
this.ServerMoveUpLabel.Text = "Move up";
|
||||
this.ServerMoveUpLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
@@ -211,10 +195,10 @@
|
||||
//
|
||||
this.ServerMoveDownLabel.AutoSize = true;
|
||||
this.ServerMoveDownLabel.Dock = System.Windows.Forms.DockStyle.Right;
|
||||
this.ServerMoveDownLabel.Location = new System.Drawing.Point(81, 194);
|
||||
this.ServerMoveDownLabel.Location = new System.Drawing.Point(106, 171);
|
||||
this.ServerMoveDownLabel.Margin = new System.Windows.Forms.Padding(8, 0, 8, 0);
|
||||
this.ServerMoveDownLabel.Name = "ServerMoveDownLabel";
|
||||
this.ServerMoveDownLabel.Size = new System.Drawing.Size(91, 33);
|
||||
this.ServerMoveDownLabel.Size = new System.Drawing.Size(91, 34);
|
||||
this.ServerMoveDownLabel.TabIndex = 4;
|
||||
this.ServerMoveDownLabel.Text = "Move Down";
|
||||
this.ServerMoveDownLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
@@ -222,7 +206,7 @@
|
||||
// SwitchSystemProxyTextBox
|
||||
//
|
||||
this.SwitchSystemProxyTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.SwitchSystemProxyTextBox.Location = new System.Drawing.Point(183, 3);
|
||||
this.SwitchSystemProxyTextBox.Location = new System.Drawing.Point(208, 3);
|
||||
this.SwitchSystemProxyTextBox.Margin = new System.Windows.Forms.Padding(3, 3, 16, 3);
|
||||
this.SwitchSystemProxyTextBox.Name = "SwitchSystemProxyTextBox";
|
||||
this.SwitchSystemProxyTextBox.ReadOnly = true;
|
||||
@@ -232,36 +216,23 @@
|
||||
this.SwitchSystemProxyTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.HotkeyDown);
|
||||
this.SwitchSystemProxyTextBox.KeyUp += new System.Windows.Forms.KeyEventHandler(this.HotkeyUp);
|
||||
//
|
||||
// ChangeToPacTextBox
|
||||
// SwitchProxyModeTextBox
|
||||
//
|
||||
this.ChangeToPacTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.ChangeToPacTextBox.Location = new System.Drawing.Point(183, 35);
|
||||
this.ChangeToPacTextBox.Margin = new System.Windows.Forms.Padding(3, 3, 16, 3);
|
||||
this.ChangeToPacTextBox.Name = "ChangeToPacTextBox";
|
||||
this.ChangeToPacTextBox.ReadOnly = true;
|
||||
this.ChangeToPacTextBox.Size = new System.Drawing.Size(276, 25);
|
||||
this.ChangeToPacTextBox.TabIndex = 8;
|
||||
this.ChangeToPacTextBox.TextChanged += new System.EventHandler(this.TextBox_TextChanged);
|
||||
this.ChangeToPacTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.HotkeyDown);
|
||||
this.ChangeToPacTextBox.KeyUp += new System.Windows.Forms.KeyEventHandler(this.HotkeyUp);
|
||||
//
|
||||
// ChangeToGlobalTextBox
|
||||
//
|
||||
this.ChangeToGlobalTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.ChangeToGlobalTextBox.Location = new System.Drawing.Point(183, 67);
|
||||
this.ChangeToGlobalTextBox.Margin = new System.Windows.Forms.Padding(3, 3, 16, 3);
|
||||
this.ChangeToGlobalTextBox.Name = "ChangeToGlobalTextBox";
|
||||
this.ChangeToGlobalTextBox.ReadOnly = true;
|
||||
this.ChangeToGlobalTextBox.Size = new System.Drawing.Size(276, 25);
|
||||
this.ChangeToGlobalTextBox.TabIndex = 9;
|
||||
this.ChangeToGlobalTextBox.TextChanged += new System.EventHandler(this.TextBox_TextChanged);
|
||||
this.ChangeToGlobalTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.HotkeyDown);
|
||||
this.ChangeToGlobalTextBox.KeyUp += new System.Windows.Forms.KeyEventHandler(this.HotkeyUp);
|
||||
this.SwitchProxyModeTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.SwitchProxyModeTextBox.Location = new System.Drawing.Point(208, 37);
|
||||
this.SwitchProxyModeTextBox.Margin = new System.Windows.Forms.Padding(3, 3, 16, 3);
|
||||
this.SwitchProxyModeTextBox.Name = "SwitchProxyModeTextBox";
|
||||
this.SwitchProxyModeTextBox.ReadOnly = true;
|
||||
this.SwitchProxyModeTextBox.Size = new System.Drawing.Size(276, 25);
|
||||
this.SwitchProxyModeTextBox.TabIndex = 8;
|
||||
this.SwitchProxyModeTextBox.TextChanged += new System.EventHandler(this.TextBox_TextChanged);
|
||||
this.SwitchProxyModeTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.HotkeyDown);
|
||||
this.SwitchProxyModeTextBox.KeyUp += new System.Windows.Forms.KeyEventHandler(this.HotkeyUp);
|
||||
//
|
||||
// SwitchAllowLanTextBox
|
||||
//
|
||||
this.SwitchAllowLanTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.SwitchAllowLanTextBox.Location = new System.Drawing.Point(183, 99);
|
||||
this.SwitchAllowLanTextBox.Location = new System.Drawing.Point(208, 71);
|
||||
this.SwitchAllowLanTextBox.Margin = new System.Windows.Forms.Padding(3, 3, 16, 3);
|
||||
this.SwitchAllowLanTextBox.Name = "SwitchAllowLanTextBox";
|
||||
this.SwitchAllowLanTextBox.ReadOnly = true;
|
||||
@@ -274,7 +245,7 @@
|
||||
// ShowLogsTextBox
|
||||
//
|
||||
this.ShowLogsTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.ShowLogsTextBox.Location = new System.Drawing.Point(183, 131);
|
||||
this.ShowLogsTextBox.Location = new System.Drawing.Point(208, 105);
|
||||
this.ShowLogsTextBox.Margin = new System.Windows.Forms.Padding(3, 3, 16, 3);
|
||||
this.ShowLogsTextBox.Name = "ShowLogsTextBox";
|
||||
this.ShowLogsTextBox.ReadOnly = true;
|
||||
@@ -287,7 +258,7 @@
|
||||
// ServerMoveUpTextBox
|
||||
//
|
||||
this.ServerMoveUpTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.ServerMoveUpTextBox.Location = new System.Drawing.Point(183, 163);
|
||||
this.ServerMoveUpTextBox.Location = new System.Drawing.Point(208, 139);
|
||||
this.ServerMoveUpTextBox.Margin = new System.Windows.Forms.Padding(3, 3, 16, 3);
|
||||
this.ServerMoveUpTextBox.Name = "ServerMoveUpTextBox";
|
||||
this.ServerMoveUpTextBox.ReadOnly = true;
|
||||
@@ -300,7 +271,7 @@
|
||||
// ServerMoveDownTextBox
|
||||
//
|
||||
this.ServerMoveDownTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.ServerMoveDownTextBox.Location = new System.Drawing.Point(183, 197);
|
||||
this.ServerMoveDownTextBox.Location = new System.Drawing.Point(208, 174);
|
||||
this.ServerMoveDownTextBox.Margin = new System.Windows.Forms.Padding(3, 3, 16, 3);
|
||||
this.ServerMoveDownTextBox.Name = "ServerMoveDownTextBox";
|
||||
this.ServerMoveDownTextBox.ReadOnly = true;
|
||||
@@ -314,7 +285,7 @@
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
|
||||
this.ClientSize = new System.Drawing.Size(475, 271);
|
||||
this.ClientSize = new System.Drawing.Size(491, 248);
|
||||
this.Controls.Add(this.tableLayoutPanel1);
|
||||
this.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
|
||||
@@ -333,8 +304,7 @@
|
||||
|
||||
#endregion
|
||||
private System.Windows.Forms.Label SwitchSystemProxyLabel;
|
||||
private System.Windows.Forms.Label ChangeToPacLabel;
|
||||
private System.Windows.Forms.Label ChangeToGlobalLabel;
|
||||
private System.Windows.Forms.Label SwitchProxyModeLabel;
|
||||
private System.Windows.Forms.Label SwitchAllowLanLabel;
|
||||
private System.Windows.Forms.Label ShowLogsLabel;
|
||||
private System.Windows.Forms.Label ServerMoveUpLabel;
|
||||
@@ -343,8 +313,7 @@
|
||||
private System.Windows.Forms.Button btnCancel;
|
||||
private System.Windows.Forms.TextBox ShowLogsTextBox;
|
||||
private System.Windows.Forms.TextBox SwitchAllowLanTextBox;
|
||||
private System.Windows.Forms.TextBox ChangeToGlobalTextBox;
|
||||
private System.Windows.Forms.TextBox ChangeToPacTextBox;
|
||||
private System.Windows.Forms.TextBox SwitchProxyModeTextBox;
|
||||
private System.Windows.Forms.TextBox SwitchSystemProxyTextBox;
|
||||
private System.Windows.Forms.TextBox ServerMoveUpTextBox;
|
||||
private System.Windows.Forms.TextBox ServerMoveDownTextBox;
|
||||
|
||||
@@ -129,10 +129,7 @@
|
||||
<metadata name="SwitchSystemProxyLabel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="ChangeToPacLabel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="ChangeToGlobalLabel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<metadata name="SwitchProxyModeLabel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="SwitchAllowLanLabel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
@@ -150,10 +147,7 @@
|
||||
<metadata name="SwitchSystemProxyTextBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="ChangeToPacTextBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="ChangeToGlobalTextBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<metadata name="SwitchProxyModeTextBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="SwitchAllowLanTextBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
|
||||
@@ -54,9 +54,9 @@ namespace Shadowsocks.View
|
||||
topMostTrigger = config.topMost;
|
||||
wrapTextTrigger = config.wrapText;
|
||||
toolbarTrigger = config.toolbarShown;
|
||||
LogMessageTextBox.BackColor = config.GetBackgroundColor();
|
||||
LogMessageTextBox.ForeColor = config.GetTextColor();
|
||||
LogMessageTextBox.Font = config.GetFont();
|
||||
LogMessageTextBox.BackColor = config.BackgroundColor;
|
||||
LogMessageTextBox.ForeColor = config.TextColor;
|
||||
LogMessageTextBox.Font = config.Font;
|
||||
|
||||
controller.TrafficChanged += controller_TrafficChanged;
|
||||
|
||||
@@ -229,11 +229,11 @@ namespace Shadowsocks.View
|
||||
|
||||
LogViewerConfig config = controller.GetConfigurationCopy().logViewer;
|
||||
|
||||
Height = config.height;
|
||||
Width = config.width;
|
||||
Top = config.GetBestTop();
|
||||
Left = config.GetBestLeft();
|
||||
if (config.maximized)
|
||||
Height = config.Height;
|
||||
Width = config.Width;
|
||||
Top = config.BestTop;
|
||||
Left = config.BestLeft;
|
||||
if (config.Maximized)
|
||||
{
|
||||
WindowState = FormWindowState.Maximized;
|
||||
}
|
||||
@@ -258,15 +258,15 @@ namespace Shadowsocks.View
|
||||
config.topMost = topMostTrigger;
|
||||
config.wrapText = wrapTextTrigger;
|
||||
config.toolbarShown = toolbarTrigger;
|
||||
config.SetFont(LogMessageTextBox.Font);
|
||||
config.SetBackgroundColor(LogMessageTextBox.BackColor);
|
||||
config.SetTextColor(LogMessageTextBox.ForeColor);
|
||||
if (WindowState != FormWindowState.Minimized && !(config.maximized = WindowState == FormWindowState.Maximized))
|
||||
config.Font=LogMessageTextBox.Font;
|
||||
config.BackgroundColor=LogMessageTextBox.BackColor;
|
||||
config.TextColor=LogMessageTextBox.ForeColor;
|
||||
if (WindowState != FormWindowState.Minimized && !(config.Maximized = WindowState == FormWindowState.Maximized))
|
||||
{
|
||||
config.top = Top;
|
||||
config.left = Left;
|
||||
config.height = Height;
|
||||
config.width = Width;
|
||||
config.Top = Top;
|
||||
config.Left = Left;
|
||||
config.Height = Height;
|
||||
config.Width = Width;
|
||||
}
|
||||
controller.SaveLogViewerConfig(config);
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ namespace Shadowsocks.View
|
||||
private MenuItem editGFWUserRuleItem;
|
||||
private MenuItem editOnlinePACItem;
|
||||
private MenuItem autoCheckUpdatesToggleItem;
|
||||
private MenuItem checkPreReleaseToggleItem;
|
||||
private MenuItem proxyItem;
|
||||
private MenuItem hotKeyItem;
|
||||
private MenuItem VerboseLoggingToggleItem;
|
||||
@@ -283,6 +284,7 @@ namespace Shadowsocks.View
|
||||
CreateMenuItem("Check for Updates...", new EventHandler(this.checkUpdatesItem_Click)),
|
||||
new MenuItem("-"),
|
||||
this.autoCheckUpdatesToggleItem = CreateMenuItem("Check for Updates at Startup", new EventHandler(this.autoCheckUpdatesToggleItem_Click)),
|
||||
this.checkPreReleaseToggleItem = CreateMenuItem("Check Pre-release Version", new EventHandler(this.checkPreReleaseToggleItem_Click)),
|
||||
}),
|
||||
CreateMenuItem("About...", new EventHandler(this.AboutItem_Click)),
|
||||
new MenuItem("-"),
|
||||
@@ -352,7 +354,7 @@ namespace Shadowsocks.View
|
||||
{
|
||||
if (updateChecker.NewVersionFound)
|
||||
{
|
||||
ShowBalloonTip(String.Format(I18N.GetString("Shadowsocks {0} Update Found"), updateChecker.LatestVersionNumber), I18N.GetString("Click here to update"), ToolTipIcon.Info, 5000);
|
||||
ShowBalloonTip(String.Format(I18N.GetString("Shadowsocks {0} Update Found"), updateChecker.LatestVersionNumber + updateChecker.LatestVersionSuffix), I18N.GetString("Click here to update"), ToolTipIcon.Info, 5000);
|
||||
}
|
||||
else if (!_isStartupChecking)
|
||||
{
|
||||
@@ -816,6 +818,7 @@ namespace Shadowsocks.View
|
||||
{
|
||||
Configuration configuration = controller.GetConfigurationCopy();
|
||||
autoCheckUpdatesToggleItem.Checked = configuration.autoCheckUpdate;
|
||||
checkPreReleaseToggleItem.Checked = configuration.checkPreRelease;
|
||||
}
|
||||
|
||||
private void autoCheckUpdatesToggleItem_Click(object sender, EventArgs e)
|
||||
@@ -825,6 +828,13 @@ namespace Shadowsocks.View
|
||||
UpdateUpdateMenu();
|
||||
}
|
||||
|
||||
private void checkPreReleaseToggleItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Configuration configuration = controller.GetConfigurationCopy();
|
||||
controller.ToggleCheckingPreRelease(!configuration.checkPreRelease);
|
||||
UpdateUpdateMenu();
|
||||
}
|
||||
|
||||
private void checkUpdatesItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
updateChecker.CheckUpdate(controller.GetConfigurationCopy());
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
|
||||
<section name="Shadowsocks.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
|
||||
</startup>
|
||||
@@ -15,4 +20,23 @@
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
<userSettings>
|
||||
<Shadowsocks.Properties.Settings>
|
||||
<setting name="LogViewerWidth" serializeAs="String">
|
||||
<value>600</value>
|
||||
</setting>
|
||||
<setting name="LogViewerHeight" serializeAs="String">
|
||||
<value>400</value>
|
||||
</setting>
|
||||
<setting name="LogViewerMaximized" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="LogViewerTop" serializeAs="String">
|
||||
<value>0</value>
|
||||
</setting>
|
||||
<setting name="LogViewerLeft" serializeAs="String">
|
||||
<value>0</value>
|
||||
</setting>
|
||||
</Shadowsocks.Properties.Settings>
|
||||
</userSettings>
|
||||
</configuration>
|
||||
|
||||
@@ -81,6 +81,7 @@
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Management" />
|
||||
<Reference Include="System.Net" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Windows.Forms.DataVisualization" />
|
||||
<Reference Include="System.XML" />
|
||||
@@ -139,8 +140,14 @@
|
||||
<Compile Include="3rd\zxing\ResultPoint.cs" />
|
||||
<Compile Include="3rd\zxing\ResultPointCallback.cs" />
|
||||
<Compile Include="3rd\zxing\WriterException.cs" />
|
||||
<Compile Include="Controller\System\Hotkeys\HotkeyCallbacks.cs" />
|
||||
<Compile Include="Model\HotKeyConfig.cs" />
|
||||
<Compile Include="Model\ProxyConfig.cs" />
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Proxy\DirectConnect.cs" />
|
||||
<Compile Include="Proxy\HttpProxy.cs" />
|
||||
<Compile Include="Proxy\IProxy.cs" />
|
||||
@@ -179,10 +186,12 @@
|
||||
<Compile Include="Controller\Strategy\StrategyManager.cs" />
|
||||
<Compile Include="Controller\Strategy\IStrategy.cs" />
|
||||
<Compile Include="Proxy\Socks5Proxy.cs" />
|
||||
<Compile Include="Settings.cs" />
|
||||
<Compile Include="StringEx.cs" />
|
||||
<Compile Include="Util\Hotkeys.cs" />
|
||||
<Compile Include="Controller\System\Hotkeys\Hotkeys.cs" />
|
||||
<Compile Include="Util\ProcessManagement\Job.cs" />
|
||||
<Compile Include="Util\ProcessManagement\ThreadUtil.cs" />
|
||||
<Compile Include="Encryption\RNG.cs" />
|
||||
<Compile Include="Util\Sockets\LineReader.cs" />
|
||||
<Compile Include="Util\Sockets\SocketUtil.cs" />
|
||||
<Compile Include="Util\Sockets\WrappedSocket.cs" />
|
||||
@@ -190,9 +199,11 @@
|
||||
<Compile Include="Util\SystemProxy\INTERNET_PER_CONN_OPTION.cs" />
|
||||
<Compile Include="Util\SystemProxy\INTERNET_PER_CONN_OPTION_LIST.cs" />
|
||||
<Compile Include="Util\SystemProxy\NativeMethods.cs" />
|
||||
<Compile Include="Util\SystemProxy\ProxyException.cs" />
|
||||
<Compile Include="Util\SystemProxy\RAS.cs" />
|
||||
<Compile Include="Util\SystemProxy\WinINet.cs" />
|
||||
<Compile Include="Util\Util.cs" />
|
||||
<Compile Include="Util\ViewUtils.cs" />
|
||||
<Compile Include="View\ConfigForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
@@ -285,6 +296,10 @@
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="Properties\DataSources\Shadowsocks.Model.StatisticsStrategyConfiguration.datasource" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<None Include="Resources\ss20.png" />
|
||||
<None Include="Resources\ss16.png" />
|
||||
<None Include="Resources\ss24.png" />
|
||||
|
||||
+5
-1
@@ -2,11 +2,11 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Shadowsocks.Controller;
|
||||
using Shadowsocks.Encryption;
|
||||
using Shadowsocks.Util;
|
||||
using GlobalHotKey;
|
||||
using System.Windows.Input;
|
||||
using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
using Shadowsocks.Controller.Hotkeys;
|
||||
|
||||
namespace test
|
||||
{
|
||||
@@ -68,6 +68,7 @@ namespace test
|
||||
|
||||
private void RunEncryptionRound(IEncryptor encryptor, IEncryptor decryptor)
|
||||
{
|
||||
RNG.Reload();
|
||||
byte[] plain = new byte[16384];
|
||||
byte[] cipher = new byte[plain.Length + 16 + IVEncryptor.ONETIMEAUTH_BYTES + IVEncryptor.AUTH_BYTES];
|
||||
byte[] plain2 = new byte[plain.Length + 16];
|
||||
@@ -117,6 +118,7 @@ namespace test
|
||||
{
|
||||
t.Join();
|
||||
}
|
||||
RNG.Close();
|
||||
Assert.IsFalse(encryptionFailed);
|
||||
}
|
||||
|
||||
@@ -156,6 +158,7 @@ namespace test
|
||||
{
|
||||
t.Join();
|
||||
}
|
||||
RNG.Close();
|
||||
Assert.IsFalse(encryptionFailed);
|
||||
}
|
||||
|
||||
@@ -196,6 +199,7 @@ namespace test
|
||||
{
|
||||
t.Join();
|
||||
}
|
||||
RNG.Close();
|
||||
Assert.IsFalse(encryptionFailed);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user