Compare commits

..
38 Commits
Author SHA1 Message Date
noisyfox b6cd8e0750 Update CHANGES and bump version 2016-12-06 22:43:19 +11:00
noisyfox cc6f77efa5 Refine code 2016-12-06 22:34:17 +11:00
noisyfox 65b9c9f5fa Allow check pre-release version 2016-12-06 22:01:00 +11:00
Syrone Wong 1e7a8de34a Fix privoxy listening port conflict (#920)
Let TCP stack find a free port for us

Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-12-03 03:00:31 +11:00
Syrone Wong 355ab0e63d Use UTF-8 encoding for optional tag in ss url (#918)
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-12-01 00:31:03 +11:00
Syrone Wong 6d01cb074e Add optional tag support for ss url (#917)
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-11-30 22:58:33 +11:00
noisyfox 17c60bf9cc Don't UpdateSystemProxy before SaveConfig.
Otherwise we will update proxy twice.
2016-11-23 03:46:14 +11:00
noisyfox 41827f283e Refine code 2016-11-23 03:22:00 +11:00
noisyfox e7b559f1da Refine code 2016-11-23 02:42:12 +11:00
noisyfox 63816ccdd1 Fix hotkey unregister issue.
Use singleton mode for hotkey callbacks.
2016-11-23 02:34:07 +11:00
noisyfox 206e0b8cb5 Fix a null ref
if user manually deleted the whole 'configs' field in gui-config.json.
Which won't crash the app but will lost all other configs.
2016-11-21 14:12:31 +11:00
noisyfox 86eeba3b7d Fix crash while showing config dialog.
If user manually deleted servers from gui-config.json
2016-11-21 13:50:15 +11:00
noisyfox 6df3250a9f Fix crash on startup when user manually deleted servers from gui-config.json 2016-11-21 13:41:36 +11:00
Noisyfox 011fc253bb Merge pull request #888 from wongsyrone/hotkey
hotkey: Refine system proxy mode switching logic
2016-11-15 22:51:48 +11:00
Syrone Wong c25e70e888 hotkey: Refine system proxy mode switching logic
Merge 'Switch to PAC' and 'Switch to Global'

Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-11-15 18:14:56 +08:00
noisyfox 964f681d3b Fix default font error. 2016-11-15 04:37:51 +11:00
noisyfox b63bab0d1a Refine LogViewerConfig. Don't store window size in main settings file 2016-11-15 04:23:59 +11:00
noisyfox 4b49431800 Parse dest address before connect to SS server.
This gives us the possibility to chose SS server based on dest address.
2016-11-14 09:58:48 +11:00
noisyfox cfc6e674da Catch and log known exceptions in SystemProxy 2016-11-12 19:38:47 +11:00
noisyfox 0101aa3741 Merge branch 'master' of https://github.com/shadowsocks/shadowsocks-windows 2016-11-12 19:23:33 +11:00
Noisyfox 1e9739116f Merge pull request #878 from wongsyrone/minor
Detach static event handler before exiting
2016-11-12 17:55:24 +11:00
Syrone Wong abcf3004ac Detach static event handler before exiting
I hope this is the last one.

Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-11-12 10:42:19 +08:00
Noisyfox 8b7b8d8219 Merge pull request #874 from wongsyrone/misc
Misc
2016-11-10 21:17:22 +11:00
Syrone Wong 199c204b5d Misc
- detach event handler before exiting
- eliminate UI and non-UI exception handling race
- rework exception message

Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-11-10 08:45:13 +08:00
Noisyfox bce876f42e Merge pull request #869 from wongsyrone/master
Refine RNG usage
2016-11-09 22:35:17 +11:00
Syrone Wong 8fcb66b6ff Refine RNG usage
- Create instance once, bind it to ShadowsocksController

Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-11-09 10:28:50 +08:00
noisyfox da6466e247 Improve exception handling 2016-11-08 18:49:09 +11:00
noisyfox 24db6438bd Update CHANGES and bump version 2016-11-07 16:52:28 +11:00
noisyfox c908caa584 Use OpenRegKey 2016-11-06 01:25:22 +11:00
noisyfox a16e80743c Open .net download page automatically 2016-11-06 00:59:03 +11:00
noisyfox aa9fd8ec06 Check .NET Framework version on startup 2016-11-05 23:23:04 +11:00
noisyfox 02124ff3ad Update README.md 2016-11-05 22:07:17 +11:00
Noisyfox eec899b9a3 Merge pull request #847 from celeron533/master
Update README.md
2016-11-04 22:08:18 +11:00
Noisyfox 1979131e12 Merge pull request #857 from wongsyrone/master
Minor update
2016-11-04 21:51:38 +11:00
celeron533 c09af5fe0f Update README.md 2016-10-31 12:30:41 +08:00
Syrone Wong 816e2b351d Update mbed TLS to 2.4.0
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-10-29 22:47:58 +08:00
Syrone Wong 217e818339 Cleanup
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-10-26 16:50:28 +08:00
Syrone Wong f06f6f2fbb Refine power mode handling
- enlarge timeout to 10 seconds
- detach event handler before exiting
- output log if success

Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-10-24 08:27:49 +08:00
44 changed files with 1170 additions and 769 deletions
+16
View File
@@ -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.
+5 -3
View File
@@ -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
+11
View File
@@ -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)]
+124 -59
View File
@@ -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
}
}
@@ -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);
}
}
}
+3 -2
View File
@@ -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.
+7 -6
View File
@@ -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 -6
View File
@@ -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)
+44
View File
@@ -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);
}
}
}
}
+8 -4
View File
@@ -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)
+2 -4
View File
@@ -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 = "";
+61 -72
View File
@@ -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);
}
}
}
+8
View File
@@ -25,5 +25,13 @@ namespace Shadowsocks.Model
proxyPort = 0;
proxyTimeout = DefaultProxyTimeoutSec;
}
public void CheckConfig()
{
if (proxyType < PROXY_SOCKS5 || proxyType > PROXY_HTTP)
{
proxyType = PROXY_SOCKS5;
}
}
}
}
+6 -3
View File
@@ -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;
+49 -22
View File
@@ -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
View File
@@ -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>
+28
View File
@@ -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)
{
}
}
}
+14 -13
View File
@@ -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>
+4 -12
View File
@@ -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)
{
+39 -16
View File
@@ -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;
}
}
}
+21
View File
@@ -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);
}
}
}
+1 -1
View File
@@ -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;
}
+35 -134
View File
@@ -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
View File
@@ -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">
+16 -16
View File
@@ -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);
}
+11 -1
View File
@@ -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());
+24
View File
@@ -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>
+16 -1
View File
@@ -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
View File
@@ -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);
}