Compare commits

...
31 Commits
Author SHA1 Message Date
Opportunity 70ec5df5b0 Add temp folder path selection (#1827)
* Translation
* Environment Variables support
2018-05-12 20:31:59 +08:00
celeron533 153727b3b7 Fix typo 2018-05-10 23:53:40 +08:00
celeron533 1a56ea23ec Update CHANGES and bump version 2018-05-10 23:29:06 +08:00
Allen Zhu 1c2e135d8e Merge pull request #1818 from celeron533/CLI
Add plugin CLI arguments support
2018-04-26 20:01:14 +08:00
celeron533 9439fc617a Config form UI updates
* Add tooltips
* Translations
2018-04-17 21:24:19 +08:00
celeron533 b7e30318cd Add plugin CLI arguments support 2018-04-17 20:41:57 +08:00
celeron533 2227595998 Update README.md
- Add section "Open Source Components / Libraries"
- Other minor changes
2018-04-12 23:42:51 +08:00
Allen Zhu 7fb75f27b1 Merge pull request #1769 from studentmain/master
[Fix] QRCodeSplashForm.cs无法在窗体设计工具中打开
2018-03-29 19:53:25 +08:00
Allen Zhu 78e46188f6 Merge pull request #1782 from tltltltl/patch-1
Update zh_TW.txt
2018-03-29 19:32:44 +08:00
tltltltl 58f2c3937b Update zh_TW.txt
change some translations
2018-03-29 18:53:07 +08:00
Zch 81dcad5df5 fix #1768
Move PerPixelAlphaForm's code into QRCodeSplashForm to avoid 2 derived class of Form in same file.

Before: QRCodeSplashForm -> PerPixelAlphaForm -> Form
After: QRCodeSplashForm -> Form
2018-03-24 21:32:48 +08:00
celeron533 5a78ee9212 Add square bracket for SIP002 IPv6 (RFC3986) 2018-03-23 22:39:06 +08:00
Max Lv 4431610205 Merge pull request #1762 from celeron533/Server_IPV6_URL
Server address should not be encoded
2018-03-22 22:07:23 +08:00
celeron533 257448a80a Misc 2018-03-20 21:03:20 +08:00
celeron533 c9ead3eee9 Server address should not be encoded 2018-03-20 13:30:44 +08:00
wzxjohn 226ad0cf50 Fix wrong splash on multi display (#1729)
Because the splash is already on the target display, the target rect doesn't need to calculate with the screen position.
2018-03-18 21:23:43 -05:00
Chen Shaoju 5138e43aff "Allow Clients from LAN" Description & Translation optimization (#1753)
"Allow Clients from LAN" --> "Allow other Devices to connect"
2018-03-16 21:15:15 -05:00
celeron533 25c1d02395 Update CHANGES and bump version 2018-03-14 22:32:31 +08:00
celeron533 897934c233 Add comments in app.config 2018-03-11 21:46:01 +08:00
Allen Zhu fdbd3a975b Merge pull request #1732 from wongsyrone/patch-1
add official way to dump network tracing info
2018-03-11 08:34:45 -05:00
Syrone Wong 7fd9ce2bc3 add official way to dump network tracing info
just uncomment the specific node in app.config, no need to recompile
to take effect. It will be shipped as Shadowsocks.exe.config after built.

This is for debugging only.
2018-03-11 16:05:37 +08:00
Allen Zhu c168af6975 Merge pull request #1725 from celeron533/master
add xchacha20-ietf-poly1305
2018-03-07 06:27:57 -06:00
Syrone Wong 3329291ab9 add xchacha20-ietf-poly1305
- update mbedtls to 2.7.0, use new md5 api
- update libsodium to 1.0.16
- static link to openssl 1.1.0g, check libsscrypto repo for detail
2018-03-03 22:22:01 +08:00
celeron533 1e04279d37 Update issue template 2018-03-03 20:37:18 +08:00
celeron533 20fa87ba89 Fix proxy bypass list #1674 2018-02-22 10:29:46 +08:00
celeron533 5db7c79407 Minor changes on Forward Proxy 2018-02-20 18:27:26 +08:00
HYec 85bd65e021 Only start the current server's plugin 2018-02-20 12:32:01 +08:00
HYec 7197e46b53 Close sockets before stop plugins 2018-02-20 12:31:53 +08:00
Allen Zhu b2c0bba953 Merge pull request #1682 from chenshaoju/patch-1
Add new requirement
2018-02-17 09:06:05 -06:00
Chen Shaoju d266ea2e39 fix 2018-02-17 11:28:01 +08:00
Chen Shaoju a5b11aee34 Add new requirements 2018-02-17 11:21:16 +08:00
29 changed files with 1179 additions and 1092 deletions
+9 -8
View File
@@ -1,19 +1,20 @@
Please read Wiki carefully, especially https://github.com/shadowsocks/shadowsocks-windows/wiki/Troubleshooting.
Please answer these questions before submitting your issue. Thanks!
Please read Wiki carefully, especially / 提问前请先阅读wiki https://github.com/shadowsocks/shadowsocks-windows/wiki/Troubleshooting.
Or search from issue board / 或在issue board中搜索 https://github.com/shadowsocks/shadowsocks-windows/issues?utf8=%E2%9C%93&q=is%3Aissue
Please answer these questions before submitting your issue. Thanks! / 请按照以下格式描述你的问题
### Version(release version or AppVeyor link)
### Version(release version or AppVeyor link) / 版本(正式版或基于AppVeyor的链接)
### Environment(Operating system, .NET Framework, etc)
### Environment(Operating system, .NET Framework, etc) / 操作环境(操作系统,.NET Framework等)
### Steps you have tried
### Steps you have tried / 操作步骤
### What did you expect to see?
### What did you expect to see? / 期望的结果
### What did you see instead?
### What did you see instead? / 实际结果
### Config and error log in detail (with all sensitive info masked)
### Config and error log in detail (with all sensitive info masked) / 配置文件和日志文件(请隐去敏感信息)
+14
View File
@@ -1,3 +1,17 @@
4.0.10 2018-05-10
- Add square bracket for SIP002 IPv6 (RFC3986)
- Add plugin CLI arguments support
- Bug fix: Server address should not be encoded (#1758)
- Bug fix: Wrong splash on multi display (#1729)
- Fix PerPixelAlphaForm's issue in designer
- Other minor bug fixes and improvements
4.0.9 2018-03-14
- Fix port occupied issue
- Add xchacha20-ietf-poly1305
- Update cryptographic libraries
- Bug fixes and improvements
4.0.8 2018-02-16
- Add OpenSSL 1.1.0g support #1671
- Update nuget packages
+34 -13
View File
@@ -17,11 +17,11 @@ Shadowsocks for Windows
#### Download
Download the [latest release].
Download the latest release from [release page].
#### Requirements
Microsoft [.NET Framework 4.6.2] or higher.
Microsoft [.NET Framework 4.6.2] or higher, Microsoft [Visual C++ 2015 Redistributable] (x86) .
#### Basic
@@ -63,7 +63,7 @@ copy Shadowsocks to a new directory and choose a different local port.
If you would like to connect to server via a plugin, please set the plugin's
path (relative or absolute) on Edit Servers form.
Note: Forward Proxy will not be used while a plugin is enabled.
_Note_: Forward Proxy will not be used while a plugin is enabled.
#### Global hotkeys
@@ -100,21 +100,42 @@ if you want to deactivate all, please clear all textboxes.
Please visit [Servers] for more information.
#### Develop
#### Development
[Visual Studio 2015] & [.NET Framework 4.6.2 Developer Pack] are required.
1. [Visual Studio 2015] & [.NET Framework 4.6.2 Developer Pack] are required.
2. It is recommended to share your idea on the Issue Board before you start to work,
especially for feature development.
#### License
GPLv3
[GPLv3]
#### Open Source Components / Libraries
```
Caseless.Fody (MIT) https://github.com/Fody/Caseless
Costura.Fody (MIT) https://github.com/Fody/Costura
Fody (MIT) https://github.com/Fody/Fody
GlobalHotKey (GPLv3) https://github.com/kirmir/GlobalHotKey
Newtonsoft.Json (MIT) https://www.newtonsoft.com/json
StringEx.CS () https://github.com/LazyMode/StringEx
ZXing.Net (Apache 2.0) https://github.com/micjahn/ZXing.Net
libsscrypto (GPLv2) https://github.com/shadowsocks/libsscrypto
Privoxy (GPLv2) https://www.privoxy.org
Sysproxy () https://github.com/Noisyfox/sysproxy
```
[Appveyor]: https://ci.appveyor.com/project/celeron533/shadowsocks-windows
[Build Status]: https://ci.appveyor.com/api/projects/status/tfw57q6eecippsl5/branch/master?svg=true
[latest release]: https://github.com/shadowsocks/shadowsocks-csharp/releases
[GFWList]: https://github.com/gfwlist/gfwlist
[Servers]: https://github.com/shadowsocks/shadowsocks/wiki/Ports-and-Clients#linux--server-side
[中文说明]: https://github.com/shadowsocks/shadowsocks-windows/wiki/Shadowsocks-Windows-%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E
[Appveyor]: https://ci.appveyor.com/project/celeron533/shadowsocks-windows
[Build Status]: https://ci.appveyor.com/api/projects/status/tfw57q6eecippsl5/branch/master?svg=true
[release page]: 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]: https://www.microsoft.com/en-US/download/details.aspx?id=53344
[Visual Studio 2015]: https://www.visualstudio.com/downloads/
[.NET Framework 4.6.2 Developer Pack]: https://www.microsoft.com/download/details.aspx?id=53321
[Visual C++ 2015 Redistributable]: https://www.microsoft.com/en-us/download/details.aspx?id=53840
[GPLv3]: https://github.com/shadowsocks/shadowsocks-windows/blob/master/LICENSE.txt
@@ -33,10 +33,10 @@ namespace Shadowsocks.Controller.Service
return null;
}
return new Sip003Plugin(server.plugin, server.plugin_opts, server.server, server.server_port);
return new Sip003Plugin(server.plugin, server.plugin_opts, server.plugin_args, server.server, server.server_port);
}
private Sip003Plugin(string plugin, string pluginOpts, string serverAddress, int serverPort)
private Sip003Plugin(string plugin, string pluginOpts, string pluginArgs, string serverAddress, int serverPort)
{
if (plugin == null) throw new ArgumentNullException(nameof(plugin));
if (string.IsNullOrWhiteSpace(serverAddress))
@@ -55,6 +55,7 @@ namespace Shadowsocks.Controller.Service
StartInfo = new ProcessStartInfo
{
FileName = plugin,
Arguments = pluginArgs,
UseShellExecute = false,
CreateNoWindow = true,
ErrorDialog = false,
@@ -24,7 +24,7 @@ namespace Shadowsocks.Controller
public string LatestVersionLocalName;
public event EventHandler CheckUpdateCompleted;
public const string Version = "4.0.8";
public const string Version = "4.0.10";
private class CheckUpdateTimer : System.Timers.Timer
{
@@ -182,6 +182,12 @@ namespace Shadowsocks.Controller
Configuration.Save(_config);
}
public void SaveTempFolder(string tempFolder)
{
_config.tempFolder = tempFolder;
Configuration.Save(_config);
}
public void SaveStrategyConfigurations(StatisticsStrategyConfiguration configuration)
{
StatisticsConfiguration = configuration;
@@ -240,19 +246,9 @@ namespace Shadowsocks.Controller
}
}
public void DisableProxy()
public void SaveProxy(ProxyConfig proxyConfig)
{
_config.proxy.useProxy = false;
SaveConfig(_config);
}
public void EnableProxy(int type, string proxy, int port, int timeout)
{
_config.proxy.useProxy = true;
_config.proxy.proxyType = type;
_config.proxy.proxyServer = proxy;
_config.proxy.proxyPort = port;
_config.proxy.proxyTimeout = timeout;
_config.proxy = proxyConfig;
SaveConfig(_config);
}
@@ -260,7 +256,8 @@ namespace Shadowsocks.Controller
{
_config.isVerboseLogging = enabled;
SaveConfig(_config);
if ( VerboseLoggingStatusChanged != null ) {
if (VerboseLoggingStatusChanged != null)
{
VerboseLoggingStatusChanged(this, new EventArgs());
}
}
@@ -363,7 +360,7 @@ namespace Shadowsocks.Controller
url = string.Format(
"{0}@{1}:{2}/?plugin={3}",
websafeBase64,
HttpUtility.UrlEncode(server.server, Encoding.UTF8),
server.FormatHostName(server.server),
server.server_port,
HttpUtility.UrlEncode(pluginPart, Encoding.UTF8));
}
@@ -490,8 +487,6 @@ namespace Shadowsocks.Controller
protected void Reload()
{
StopPlugins();
Encryption.RNG.Reload();
// some logic in configuration updated the config when saving, we need to read it again
_config = Configuration.Load();
@@ -521,6 +516,9 @@ namespace Shadowsocks.Controller
{
_listener.Stop();
}
StopPlugins();
// don't put PrivoxyRunner.Start() before pacServer.Stop()
// or bind will fail when switching bind address from 0.0.0.0 to 127.0.0.1
// though UseShellExecute is set to true now
@@ -534,7 +532,7 @@ namespace Shadowsocks.Controller
strategy.ReloadServers();
}
StartPlugins();
StartPlugin();
privoxyRunner.Start(_config);
TCPRelay tcpRelay = new TCPRelay(this, _config);
@@ -572,13 +570,10 @@ namespace Shadowsocks.Controller
Utils.ReleaseMemory(true);
}
private void StartPlugins()
private void StartPlugin()
{
foreach (var server in _config.configs)
{
// Early start plugin processes
GetPluginLocalEndPointIfConfigured(server);
}
var server = _config.GetCurrentServer();
GetPluginLocalEndPointIfConfigured(server);
}
protected void SaveConfig(Configuration newConfig)
@@ -668,7 +663,7 @@ namespace Shadowsocks.Controller
{
previous = trafficPerSecondQueue.Last();
current = new TrafficPerSecond();
current.inboundCounter = InboundCounter;
current.outboundCounter = OutboundCounter;
current.inboundIncreasement = current.inboundCounter - previous.inboundCounter;
+3 -2
View File
@@ -13,7 +13,7 @@ Edit Servers...=サーバーの編集...
Statistics Config...=統計情報の設定...
Start on Boot=システムと同時に起動
Forward Proxy...=フォワードプロキシの設定...
Allow Clients from LAN=LAN からのアクセスを許可
Allow other Devices to connect=他のデバイスからの接続を許可する
Local PAC=ローカル PAC
Online PAC=オンライン PAC
Edit Local PAC File...=ローカル PAC ファイルの編集...
@@ -51,8 +51,9 @@ Server Port=サーバーポート
Password=パスワード
Show Password=パスワードを表示する
Encryption=暗号化
Plugin=プラグイン
Plugin Program=プラグインプログラム
Plugin Options=プラグインのオプション
Plugin Arguments=プラグインの引数
Proxy Port=プロキシポート
Remarks=付記
Timeout(Sec)=タイムアウト (秒)
Binary file not shown.
Binary file not shown.
+5 -3
View File
@@ -13,7 +13,7 @@ Edit Servers...=编辑服务器...
Statistics Config...=统计配置...
Start on Boot=开机启动
Forward Proxy...=正向代理设置...
Allow Clients from LAN=允许来自局域网的连接
Allow other Devices to connect=允许其他设备连入
Local PAC=使用本地 PAC
Online PAC=使用在线 PAC
Edit Local PAC File...=编辑本地 PAC 文件...
@@ -51,8 +51,9 @@ Server Port=服务器端口
Password=密码
Show Password=显示密码
Encryption=加密
Plugin=插件
Plugin Program=插件程序
Plugin Options=插件选项
Plugin Arguments=插件参数
Proxy Port=代理端口
Remarks=备注
Timeout(Sec)=超时(秒)
@@ -61,6 +62,7 @@ Cancel=取消
New server=未配置的服务器
Move &Up=上移(&U)
Move D&own=下移(&O)
Temp Folder=临时文件夹
# Proxy Form
@@ -143,4 +145,4 @@ Proxy request failed=代理请求失败
Proxy handshake failed=代理握手失败
Register hotkey failed=注册热键失败
Cannot parse hotkey: {0}=解析热键失败: {0}
Timeout is invalid, it should not exceed {0}=超时无效,不应超过 {0}
Timeout is invalid, it should not exceed {0}=超时无效,不应超过 {0}
+6 -4
View File
@@ -13,7 +13,7 @@ Edit Servers...=編輯伺服器...
Statistics Config...=統計設定檔...
Start on Boot=開機啟動
Forward Proxy...=正向 Proxy 設定...
Allow Clients from LAN=允許來自區域網路的連線
Allow other Devices to connect=允許其他裝置連入
Local PAC=使用本機 PAC
Online PAC=使用線上 PAC
Edit Local PAC File...=編輯本機 PAC 檔案...
@@ -51,8 +51,9 @@ Server Port=伺服器連接埠
Password=密碼
Show Password=顯示密碼
Encryption=加密
Plugin=插件
Plugin Options=插件選項
Plugin Program=外掛程式
Plugin Options=外掛程式選項
Plugin Arguments=外掛程式參數
Proxy Port=Proxy 連接埠
Remarks=註解
Timeout(Sec)=逾時 (秒)
@@ -61,6 +62,7 @@ Cancel=取消
New server=新伺服器
Move &Up=上移 (&U)
Move D&own=下移 (&O)
Temp Folder=臨時資料夾
# Proxy Form
@@ -69,7 +71,7 @@ Use Proxy=使用 Proxy
Proxy Type=Proxy 類型
Proxy Addr=Proxy 位址
Proxy Port=Proxy 連接埠
If server has a plugin, proxy will not be used=若伺服器含有插件,Proxy 將不被使用
If server has a plugin, proxy will not be used=若伺服器含有外掛程式,Proxy 將不被使用
# Log Form
@@ -10,7 +10,8 @@ namespace Shadowsocks.Encryption.AEAD
: AEADEncryptor, IDisposable
{
private const int CIPHER_CHACHA20IETFPOLY1305 = 1;
private const int CIPHER_AES256GCM = 2;
private const int CIPHER_XCHACHA20IETFPOLY1305 = 2;
private const int CIPHER_AES256GCM = 3;
private byte[] _sodiumEncSubkey;
private byte[] _sodiumDecSubkey;
@@ -25,6 +26,7 @@ namespace Shadowsocks.Encryption.AEAD
private static readonly Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
{
{"chacha20-ietf-poly1305", new EncryptorInfo(32, 32, 12, 16, CIPHER_CHACHA20IETFPOLY1305)},
{"xchacha20-ietf-poly1305", new EncryptorInfo(32, 32, 24, 16, CIPHER_XCHACHA20IETFPOLY1305)},
{"aes-256-gcm", new EncryptorInfo(32, 32, 12, 16, CIPHER_AES256GCM)},
};
@@ -65,6 +67,13 @@ namespace Shadowsocks.Encryption.AEAD
null, _encNonce,
_sodiumEncSubkey);
break;
case CIPHER_XCHACHA20IETFPOLY1305:
ret = Sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(ciphertext, ref encClen,
plaintext, (ulong)plen,
null, 0,
null, _encNonce,
_sodiumEncSubkey);
break;
case CIPHER_AES256GCM:
ret = Sodium.crypto_aead_aes256gcm_encrypt(ciphertext, ref encClen,
plaintext, (ulong)plen,
@@ -99,6 +108,13 @@ namespace Shadowsocks.Encryption.AEAD
null, 0,
_decNonce, _sodiumDecSubkey);
break;
case CIPHER_XCHACHA20IETFPOLY1305:
ret = Sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(plaintext, ref decPlen,
null,
ciphertext, (ulong)clen,
null, 0,
_decNonce, _sodiumDecSubkey);
break;
case CIPHER_AES256GCM:
ret = Sodium.crypto_aead_aes256gcm_decrypt(plaintext, ref decPlen,
null,
+3 -2
View File
@@ -34,7 +34,8 @@ namespace Shadowsocks.Encryption
public static byte[] MD5(byte[] input)
{
byte[] output = new byte[16];
md5(input, (uint) input.Length, output);
if (md5_ret(input, (uint) input.Length, output) != 0)
throw new System.Exception("mbedtls: MD5 failure");
return output;
}
@@ -42,7 +43,7 @@ namespace Shadowsocks.Encryption
private static extern IntPtr LoadLibrary(string path);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern void md5(byte[] input, uint ilen, byte[] output);
public static extern int md5_ret(byte[] input, uint ilen, byte[] output);
/// <summary>
/// Get cipher ctx size for unmanaged memory allocation
+2 -2
View File
@@ -13,7 +13,7 @@ namespace Shadowsocks.Encryption
// XXX: only for OpenSSL 1.1.0 and higher
public static class OpenSSL
{
private const string DLLNAME = "libcrypto-1_1.dll";
private const string DLLNAME = "libsscrypto.dll";
public const int OPENSSL_ENCRYPT = 1;
public const int OPENSSL_DECRYPT = 0;
@@ -27,7 +27,7 @@ namespace Shadowsocks.Encryption
string dllPath = Utils.GetTempPath(DLLNAME);
try
{
FileManager.UncompressFile(dllPath, Resources.libcrypto_1_1_dll);
FileManager.UncompressFile(dllPath, Resources.libsscrypto_dll);
}
catch (IOException)
{
+8
View File
@@ -73,6 +73,14 @@ namespace Shadowsocks.Encryption
public static extern int crypto_aead_chacha20poly1305_ietf_decrypt(byte[] m, ref ulong mlen_p,
byte[] nsec, byte[] c, ulong clen, byte[] ad, ulong adlen, byte[] npub, byte[] k);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int crypto_aead_xchacha20poly1305_ietf_encrypt(byte[] c, ref ulong clen_p, byte[] m, ulong mlen,
byte[] ad, ulong adlen, byte[] nsec, byte[] npub, byte[] k);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int crypto_aead_xchacha20poly1305_ietf_decrypt(byte[] m, ref ulong mlen_p, byte[] nsec, byte[] c,
ulong clen, byte[] ad, ulong adlen, byte[] npub, byte[] k);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int crypto_aead_aes256gcm_encrypt(byte[] c, ref ulong clen_p, byte[] m, ulong mlen,
byte[] ad, ulong adlen, byte[] nsec, byte[] npub, byte[] k);
@@ -30,6 +30,7 @@ namespace Shadowsocks.Model
public LogViewerConfig logViewer;
public ProxyConfig proxy;
public HotkeyConfig hotkey;
public string tempFolder;
private static string CONFIG_FILE = "gui-config.json";
@@ -145,6 +146,13 @@ namespace Shadowsocks.Model
throw new ArgumentException(I18N.GetString("Port can't be 8123"));
}
public static void CheckTempFolder(string tempPath)
{
if (string.IsNullOrWhiteSpace(tempPath))
return;
Path.GetFullPath(tempPath);
}
private static void CheckPassword(string password)
{
if (password.IsNullOrEmpty())
+16 -14
View File
@@ -26,6 +26,7 @@ namespace Shadowsocks.Model
public string method;
public string plugin;
public string plugin_opts;
public string plugin_args;
public string remarks;
public int timeout;
@@ -46,25 +47,25 @@ namespace Shadowsocks.Model
{
return I18N.GetString("New server");
}
string serverStr;
// CheckHostName() won't do a real DNS lookup
var hostType = Uri.CheckHostName(server);
switch (hostType)
{
case UriHostNameType.IPv6:
serverStr = $"[{server}]:{server_port}";
break;
default:
// IPv4 and domain name
serverStr = $"{server}:{server_port}";
break;
}
string serverStr = $"{FormatHostName(server)}:{server_port}";
return remarks.IsNullOrEmpty()
? serverStr
: $"{remarks} ({serverStr})";
}
public string FormatHostName(string hostName)
{
// CheckHostName() won't do a real DNS lookup
switch (Uri.CheckHostName(hostName))
{
case UriHostNameType.IPv6: // Add square bracket when IPv6 (RFC3986)
return $"[{hostName}]";
default: // IPv4 or domain name
return hostName;
}
}
public Server()
{
server = "";
@@ -72,6 +73,7 @@ namespace Shadowsocks.Model
method = "aes-256-cfb";
plugin = "";
plugin_opts = "";
plugin_args = "";
password = "";
remarks = "";
timeout = DefaultServerTimeoutSec;
@@ -141,7 +143,7 @@ namespace Shadowsocks.Model
Server server = new Server
{
remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped),
server = parsedUrl.GetComponents(UriComponents.Host, UriFormat.Unescaped),
server = parsedUrl.IdnHost,
server_port = parsedUrl.Port,
};
-10
View File
@@ -100,16 +100,6 @@ namespace Shadowsocks.Properties {
}
}
/// <summary>
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
internal static byte[] libcrypto_1_1_dll {
get {
object obj = ResourceManager.GetObject("libcrypto_1_1_dll", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
+1 -4
View File
@@ -124,11 +124,8 @@
<data name="ja" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Data\ja.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="libcrypto_1_1_dll" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Data\libcrypto-1_1.dll.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="libsscrypto_dll" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\data\libsscrypto.dll.gz;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>..\Data\libsscrypto.dll.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="mgwz_dll" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\data\mgwz.dll.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+24 -12
View File
@@ -35,7 +35,8 @@ namespace Shadowsocks.Util.SystemProxy
static Sysproxy()
{
try {
try
{
FileManager.UncompressFile(Utils.GetTempPath("sysproxy.exe"),
Environment.Is64BitOperatingSystem ? Resources.sysproxy64_exe : Resources.sysproxy_exe);
}
@@ -60,7 +61,7 @@ namespace Shadowsocks.Util.SystemProxy
if (enable)
{
arguments = global
? $"global {proxyServer} <local>;localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;172.32.*;192.168.*"
? $"global {proxyServer} <local>;localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*"
: $"pac {pacURL}";
}
else
@@ -111,8 +112,10 @@ namespace Shadowsocks.Util.SystemProxy
throw new ProxyException(stderr);
}
if (arguments == "query") {
if (stdout.IsNullOrWhiteSpace() || stdout.IsNullOrEmpty()) {
if (arguments == "query")
{
if (stdout.IsNullOrWhiteSpace() || stdout.IsNullOrEmpty())
{
// we cannot get user settings
throw new ProxyException("failed to query wininet settings");
}
@@ -123,25 +126,34 @@ namespace Shadowsocks.Util.SystemProxy
private static void Save()
{
try {
using (StreamWriter sw = new StreamWriter(File.Open(_userWininetConfigFile, FileMode.Create))) {
try
{
using (StreamWriter sw = new StreamWriter(File.Open(Utils.GetTempPath(_userWininetConfigFile), FileMode.Create)))
{
string jsonString = JsonConvert.SerializeObject(_userSettings, Formatting.Indented);
sw.Write(jsonString);
sw.Flush();
}
} catch (IOException e) {
}
catch (IOException e)
{
Logging.LogUsefulException(e);
}
}
private static void Read()
{
try {
string configContent = File.ReadAllText(_userWininetConfigFile);
try
{
string configContent = File.ReadAllText(Utils.GetTempPath(_userWininetConfigFile));
_userSettings = JsonConvert.DeserializeObject<SysproxyConfig>(configContent);
} catch(Exception) {
// Suppress all exceptions. finally block will initialize new user config settings.
} finally {
}
catch (Exception)
{
// Suppress all exceptions. finally block will initialize new user config settings.
}
finally
{
if (_userSettings == null) _userSettings = new SysproxyConfig();
}
}
+33 -3
View File
@@ -2,10 +2,12 @@
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Microsoft.Win32;
using Shadowsocks.Controller;
using Shadowsocks.Model;
namespace Shadowsocks.Util
{
@@ -26,6 +28,24 @@ namespace Shadowsocks.Util
public static class Utils
{
private static string _tempPath = null;
private const string TEMP_LOG = "temp.log";
private static readonly string[] COMMON_ENV =
{
"%Tmp%",
"%Temp%",
"%AppData%",
"%LocalAppData%",
"%Home%",
"%UserProfile%",
"%Public%",
"%CommonProgramFiles%",
"%CommonProgramFiles(x86)%",
"%CommonProgramW6432%",
"%ProgramFiles%",
"%ProgramFiles(x86)%",
"%ProgramW6432%",
"%ProgramData%",
};
// return path to store temporary files
public static string GetTempPath()
@@ -34,9 +54,19 @@ namespace Shadowsocks.Util
{
try
{
Directory.CreateDirectory(Path.Combine(Application.StartupPath, "ss_win_temp"));
// don't use "/", it will fail when we call explorer /select xxx/ss_win_temp\xxx.log
_tempPath = Path.Combine(Application.StartupPath, "ss_win_temp");
var tempFolder = Configuration.Load().tempFolder;
if (string.IsNullOrWhiteSpace(tempFolder))
// don't use "/", it will fail when we call explorer /select xxx/ss_win_temp\xxx.log
tempFolder = "ss_win_temp";
else if (COMMON_ENV.Contains(tempFolder, StringComparer.OrdinalIgnoreCase))
// add subfolder for these common folders
tempFolder += (@"\Shadowsocks\ss_win_temp_" + Application.ExecutablePath.GetHashCode());
tempFolder = Environment.ExpandEnvironmentVariables(tempFolder);
// If `tempFolder` is an absolute path, `Application.StartupPath` will be ignored.
var tempDirectory = Directory.CreateDirectory(Path.Combine(Application.StartupPath, tempFolder));
_tempPath = tempDirectory.FullName;
File.AppendAllText(Path.Combine(_tempPath, TEMP_LOG), $"[{DateTimeOffset.Now.ToString("u")}] Temp folder used by \"{Application.ExecutablePath}\"{Environment.NewLine}");
}
catch (Exception e)
{
File diff suppressed because it is too large Load Diff
+14 -5
View File
@@ -9,6 +9,7 @@ using Microsoft.Win32;
using Shadowsocks.Controller;
using Shadowsocks.Model;
using Shadowsocks.Properties;
using System.Threading.Tasks;
namespace Shadowsocks.View
{
@@ -22,11 +23,12 @@ namespace Shadowsocks.View
public ConfigForm(ShadowsocksController controller)
{
this.Font = System.Drawing.SystemFonts.MessageBoxFont;
this.Font = SystemFonts.MessageBoxFont;
InitializeComponent();
// a dirty hack
this.ServersListBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.ServersListBox.Dock = DockStyle.Fill;
this.tableLayoutPanel5.Dock = DockStyle.Fill;
this.PerformLayout();
UpdateTexts();
@@ -48,9 +50,11 @@ namespace Shadowsocks.View
PasswordLabel.Text = I18N.GetString("Password");
ShowPasswdCheckBox.Text = I18N.GetString("Show Password");
EncryptionLabel.Text = I18N.GetString("Encryption");
PluginLabel.Text = I18N.GetString("Plugin");
PluginLabel.Text = I18N.GetString("Plugin Program");
PluginOptionsLabel.Text = I18N.GetString("Plugin Options");
PluginArgumentsLabel.Text = I18N.GetString("Plugin Arguments");
ProxyPortLabel.Text = I18N.GetString("Proxy Port");
TempFolderLabel.Text = I18N.GetString("Temp Folder");
RemarksLabel.Text = I18N.GetString("Remarks");
TimeoutLabel.Text = I18N.GetString("Timeout(Sec)");
ServerGroupBox.Text = I18N.GetString("Server");
@@ -99,6 +103,7 @@ namespace Shadowsocks.View
server.method = EncryptionSelect.Text;
server.plugin = PluginTextBox.Text;
server.plugin_opts = PluginOptionsTextBox.Text;
server.plugin_args = PluginArgumentsTextBox.Text;
server.remarks = RemarksTextBox.Text;
if (!int.TryParse(TimeoutTextBox.Text, out server.timeout))
{
@@ -107,6 +112,7 @@ namespace Shadowsocks.View
return false;
}
int localPort = int.Parse(ProxyPortTextBox.Text);
Configuration.CheckTempFolder(TempFolderTextBox.Text);
Configuration.CheckServer(server);
Configuration.CheckLocalPort(localPort);
_modifiedConfiguration.configs[_lastSelectedIndex] = server;
@@ -134,6 +140,7 @@ namespace Shadowsocks.View
EncryptionSelect.Text = server.method ?? "aes-256-cfb";
PluginTextBox.Text = server.plugin;
PluginOptionsTextBox.Text = server.plugin_opts;
PluginArgumentsTextBox.Text = server.plugin_args;
RemarksTextBox.Text = server.remarks;
TimeoutTextBox.Text = server.timeout.ToString();
}
@@ -160,6 +167,7 @@ namespace Shadowsocks.View
ServersListBox.SelectedIndex = _lastSelectedIndex;
UpdateMoveUpAndDownButton();
LoadSelectedServer();
TempFolderTextBox.Text = _modifiedConfiguration.tempFolder;
}
private void ConfigForm_Load(object sender, EventArgs e)
@@ -228,14 +236,14 @@ namespace Shadowsocks.View
_lastSelectedIndex = ServersListBox.SelectedIndex;
}
private void DuplicateButton_Click( object sender, EventArgs e )
private void DuplicateButton_Click(object sender, EventArgs e)
{
if (!SaveOldSelectedServer())
{
return;
}
Server currServer = _modifiedConfiguration.configs[_lastSelectedIndex];
var currIndex = _modifiedConfiguration.configs.IndexOf( currServer );
var currIndex = _modifiedConfiguration.configs.IndexOf(currServer);
_modifiedConfiguration.configs.Insert(currIndex + 1, currServer);
LoadConfiguration(_modifiedConfiguration);
ServersListBox.SelectedIndex = currIndex + 1;
@@ -272,6 +280,7 @@ namespace Shadowsocks.View
return;
}
controller.SaveServers(_modifiedConfiguration.configs, _modifiedConfiguration.localPort);
controller.SaveTempFolder(TempFolderTextBox.Text);
// SelectedIndex remains valid
// We handled this in event handlers, e.g. Add/DeleteButton, SelectedIndexChanged
// and move operations
+122 -227
View File
@@ -1,228 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="tableLayoutPanel1.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="PluginOptionsLabel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="PluginTextBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="RemarksTextBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="RemarksLabel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="IPLabel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ServerPortLabel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="PasswordLabel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="IPTextBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ServerPortTextBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="PasswordTextBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="EncryptionLabel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="EncryptionSelect.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="TimeoutLabel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="TimeoutTextBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="PluginLabel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="PluginOptionsTextBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ShowPasswdCheckBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="panel2.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="OKButton.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="MyCancelButton.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="DeleteButton.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="AddButton.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ServerGroupBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ServersListBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="tableLayoutPanel2.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="tableLayoutPanel6.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="MoveDownButton.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="MoveUpButton.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="tableLayoutPanel5.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ProxyPortTextBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ProxyPortLabel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="tableLayoutPanel3.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="tableLayoutPanel4.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="DuplicateButton.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="$this.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>
@@ -187,6 +187,10 @@ namespace Shadowsocks.View
I18N.GetString("System Proxy On: ") + (global ? I18N.GetString("Global") : I18N.GetString("PAC")) :
String.Format(I18N.GetString("Running: Port {0}"), config.localPort)) // this feedback is very important because they need to know Shadowsocks is running
+ "\n" + serverInfo;
if (text.Length > 127)
{
text = text.Substring(0, 126 - 3) + "...";
}
ViewUtils.SetNotifyIconText(_notifyIcon, text);
}
@@ -286,7 +290,7 @@ namespace Shadowsocks.View
this.proxyItem = CreateMenuItem("Forward Proxy...", new EventHandler(this.proxyItem_Click)),
new MenuItem("-"),
this.AutoStartupItem = CreateMenuItem("Start on Boot", new EventHandler(this.AutoStartupItem_Click)),
this.ShareOverLANItem = CreateMenuItem("Allow Clients from LAN", new EventHandler(this.ShareOverLANItem_Click)),
this.ShareOverLANItem = CreateMenuItem("Allow other Devices to connect", new EventHandler(this.ShareOverLANItem_Click)),
new MenuItem("-"),
this.hotKeyItem = CreateMenuItem("Edit Hotkeys...", new EventHandler(this.hotKeyItem_Click)),
CreateMenuGroup("Help", new MenuItem[] {
@@ -707,7 +711,7 @@ namespace Shadowsocks.View
{
splash.FormClosed += splash_FormClosed;
}
else if (result.Text.StartsWith("http://") || result.Text.StartsWith("https://"))
else if (result.Text.ToLower().StartsWith("http://") || result.Text.ToLower().StartsWith("https://"))
{
_urlToOpen = result.Text;
splash.FormClosed += openURLFromQRCode;
@@ -738,7 +742,7 @@ namespace Shadowsocks.View
splash.Location = new Point(screen.Bounds.X, screen.Bounds.Y);
// we need a panel because a window has a minimal size
// TODO: test on high DPI
splash.TargetRect = new Rectangle((int)minX + screen.Bounds.X, (int)minY + screen.Bounds.Y, (int)maxX - (int)minX, (int)maxY - (int)minY);
splash.TargetRect = new Rectangle((int)minX, (int)minY, (int)maxX - (int)minX, (int)maxY - (int)minY);
splash.Size = new Size(fullImage.Width, fullImage.Height);
splash.Show();
return;
+24 -30
View File
@@ -12,7 +12,7 @@ namespace Shadowsocks.View
private ShadowsocksController controller;
// this is a copy of configuration that we are working on
private ProxyConfig _modifiedConfiguration;
private ProxyConfig _modifiedProxyConfig;
public ProxyForm(ShadowsocksController controller)
{
@@ -49,53 +49,47 @@ namespace Shadowsocks.View
private void LoadCurrentConfiguration()
{
_modifiedConfiguration = controller.GetConfigurationCopy().proxy;
UseProxyCheckBox.Checked = _modifiedConfiguration.useProxy;
ProxyServerTextBox.Text = _modifiedConfiguration.proxyServer;
ProxyPortTextBox.Text = _modifiedConfiguration.proxyPort.ToString();
ProxyTimeoutTextBox.Text = _modifiedConfiguration.proxyTimeout.ToString();
ProxyTypeComboBox.SelectedIndex = _modifiedConfiguration.proxyType;
_modifiedProxyConfig = controller.GetConfigurationCopy().proxy;
UseProxyCheckBox.Checked = _modifiedProxyConfig.useProxy;
ProxyServerTextBox.Text = _modifiedProxyConfig.proxyServer;
ProxyPortTextBox.Text = _modifiedProxyConfig.proxyPort.ToString();
ProxyTimeoutTextBox.Text = _modifiedProxyConfig.proxyTimeout.ToString();
ProxyTypeComboBox.SelectedIndex = _modifiedProxyConfig.proxyType;
}
private void OKButton_Click(object sender, EventArgs e)
{
if (UseProxyCheckBox.Checked)
if (_modifiedProxyConfig.useProxy=UseProxyCheckBox.Checked)
{
int port;
int timeout;
if (!int.TryParse(ProxyPortTextBox.Text, out port))
if (!int.TryParse(ProxyPortTextBox.Text, out _modifiedProxyConfig.proxyPort))
{
MessageBox.Show(I18N.GetString("Illegal port number format"));
return;
}
if (!int.TryParse(ProxyTimeoutTextBox.Text, out timeout))
if (!int.TryParse(ProxyTimeoutTextBox.Text, out _modifiedProxyConfig.proxyTimeout))
{
MessageBox.Show(I18N.GetString("Illegal timeout format"));
return;
}
var type = ProxyTypeComboBox.SelectedIndex;
var proxy = ProxyServerTextBox.Text;
_modifiedProxyConfig.proxyType = ProxyTypeComboBox.SelectedIndex;
try
{
Configuration.CheckServer(proxy);
Configuration.CheckPort(port);
Configuration.CheckTimeout(timeout, ProxyConfig.MaxProxyTimeoutSec);
Configuration.CheckServer(_modifiedProxyConfig.proxyServer = ProxyServerTextBox.Text);
Configuration.CheckPort(_modifiedProxyConfig.proxyPort);
Configuration.CheckTimeout(_modifiedProxyConfig.proxyTimeout, ProxyConfig.MaxProxyTimeoutSec);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
}
controller.EnableProxy(type, proxy, port, timeout);
}
else
{
controller.DisableProxy();
}
controller.SaveProxy(_modifiedProxyConfig);
this.Close();
}
@@ -119,17 +113,17 @@ namespace Shadowsocks.View
{
if (UseProxyCheckBox.Checked)
{
ProxyServerTextBox.Enabled = true;
ProxyPortTextBox.Enabled = true;
ProxyTimeoutTextBox.Enabled = true;
ProxyServerTextBox.Enabled =
ProxyPortTextBox.Enabled =
ProxyTimeoutTextBox.Enabled =
ProxyTypeComboBox.Enabled = true;
}
else
{
ProxyServerTextBox.Enabled = false;
ProxyPortTextBox.Enabled = false;
ProxyTimeoutTextBox.Enabled = false;
ProxyTypeComboBox.Enabled = false;
ProxyServerTextBox.Enabled =
ProxyPortTextBox.Enabled =
ProxyTimeoutTextBox.Enabled =
ProxyTypeComboBox.Enabled = false;
}
}
}
+65 -84
View File
@@ -12,12 +12,13 @@ using System.Diagnostics;
namespace Shadowsocks.View
{
public class QRCodeSplashForm : PerPixelAlphaForm
public class QRCodeSplashForm : Form
{
public Rectangle TargetRect;
public QRCodeSplashForm()
{
FormBorderStyle = FormBorderStyle.None;
this.Load += QRCodeSplashForm_Load;
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.BackColor = System.Drawing.Color.White;
@@ -69,16 +70,6 @@ namespace Shadowsocks.View
brush = new SolidBrush(Color.FromArgb(30, Color.Red));
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x00080000; // This form has to have the WS_EX_LAYERED extended style
return cp;
}
}
void timer_Tick(object sender, EventArgs e)
{
double percent = (double)sw.ElapsedMilliseconds / 1000.0 / (double)ANIMATION_TIME;
@@ -148,6 +139,69 @@ namespace Shadowsocks.View
flashStep++;
}
}
// PerPixelAlphaForm.cs
// http://www.codeproject.com/Articles/1822/Per-Pixel-Alpha-Blend-in-C
// Rui Lopes
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x00080000; // This form has to have the WS_EX_LAYERED extended style
return cp;
}
}
public void SetBitmap(Bitmap bitmap)
{
SetBitmap(bitmap, 255);
}
/// <para>Changes the current bitmap with a custom opacity level. Here is where all happens!</para>
public void SetBitmap(Bitmap bitmap, byte opacity)
{
if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
throw new ApplicationException("The bitmap must be 32ppp with alpha-channel.");
// The idea of this is very simple,
// 1. Create a compatible DC with screen;
// 2. Select the bitmap with 32bpp with alpha-channel in the compatible DC;
// 3. Call the UpdateLayeredWindow.
IntPtr screenDc = Win32.GetDC(IntPtr.Zero);
IntPtr memDc = Win32.CreateCompatibleDC(screenDc);
IntPtr hBitmap = IntPtr.Zero;
IntPtr oldBitmap = IntPtr.Zero;
try
{
hBitmap = bitmap.GetHbitmap(Color.FromArgb(0)); // grab a GDI handle from this GDI+ bitmap
oldBitmap = Win32.SelectObject(memDc, hBitmap);
Win32.Size size = new Win32.Size(bitmap.Width, bitmap.Height);
Win32.Point pointSource = new Win32.Point(0, 0);
Win32.Point topPos = new Win32.Point(Left, Top);
Win32.BLENDFUNCTION blend = new Win32.BLENDFUNCTION();
blend.BlendOp = Win32.AC_SRC_OVER;
blend.BlendFlags = 0;
blend.SourceConstantAlpha = opacity;
blend.AlphaFormat = Win32.AC_SRC_ALPHA;
Win32.UpdateLayeredWindow(Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, Win32.ULW_ALPHA);
}
finally
{
Win32.ReleaseDC(IntPtr.Zero, screenDc);
if (hBitmap != IntPtr.Zero)
{
Win32.SelectObject(memDc, oldBitmap);
//Windows.DeleteObject(hBitmap); // The documentation says that we have to use the Windows.DeleteObject... but since there is no such method I use the normal DeleteObject from Win32 GDI and it's working fine without any resource leak.
Win32.DeleteObject(hBitmap);
}
Win32.DeleteDC(memDc);
}
}
}
@@ -224,77 +278,4 @@ namespace Shadowsocks.View
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern int DeleteObject(IntPtr hObject);
}
public class PerPixelAlphaForm : Form
{
// http://www.codeproject.com/Articles/1822/Per-Pixel-Alpha-Blend-in-C
// Rui Lopes
public PerPixelAlphaForm()
{
// This form should not have a border or else Windows will clip it.
FormBorderStyle = FormBorderStyle.None;
}
public void SetBitmap(Bitmap bitmap)
{
SetBitmap(bitmap, 255);
}
/// <para>Changes the current bitmap with a custom opacity level. Here is where all happens!</para>
public void SetBitmap(Bitmap bitmap, byte opacity)
{
if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
throw new ApplicationException("The bitmap must be 32ppp with alpha-channel.");
// The idea of this is very simple,
// 1. Create a compatible DC with screen;
// 2. Select the bitmap with 32bpp with alpha-channel in the compatible DC;
// 3. Call the UpdateLayeredWindow.
IntPtr screenDc = Win32.GetDC(IntPtr.Zero);
IntPtr memDc = Win32.CreateCompatibleDC(screenDc);
IntPtr hBitmap = IntPtr.Zero;
IntPtr oldBitmap = IntPtr.Zero;
try
{
hBitmap = bitmap.GetHbitmap(Color.FromArgb(0)); // grab a GDI handle from this GDI+ bitmap
oldBitmap = Win32.SelectObject(memDc, hBitmap);
Win32.Size size = new Win32.Size(bitmap.Width, bitmap.Height);
Win32.Point pointSource = new Win32.Point(0, 0);
Win32.Point topPos = new Win32.Point(Left, Top);
Win32.BLENDFUNCTION blend = new Win32.BLENDFUNCTION();
blend.BlendOp = Win32.AC_SRC_OVER;
blend.BlendFlags = 0;
blend.SourceConstantAlpha = opacity;
blend.AlphaFormat = Win32.AC_SRC_ALPHA;
Win32.UpdateLayeredWindow(Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, Win32.ULW_ALPHA);
}
finally
{
Win32.ReleaseDC(IntPtr.Zero, screenDc);
if (hBitmap != IntPtr.Zero)
{
Win32.SelectObject(memDc, oldBitmap);
//Windows.DeleteObject(hBitmap); // The documentation says that we have to use the Windows.DeleteObject... but since there is no such method I use the normal DeleteObject from Win32 GDI and it's working fine without any resource leak.
Win32.DeleteObject(hBitmap);
}
Win32.DeleteDC(memDc);
}
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x00080000; // This form has to have the WS_EX_LAYERED extended style
return cp;
}
}
}
}
+45
View File
@@ -39,4 +39,49 @@
</setting>
</Shadowsocks.Properties.Settings>
</userSettings>
<!-- Uncomment to dump network tracing info
<system.diagnostics>
<sources>
<source name="System.Net" tracemode="includehex" maxdatasize="1024">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Cache">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Http">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Sockets">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.WebSockets">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
</sources>
<switches>
<add name="System.Net" value="Verbose"/>
<add name="System.Net.Cache" value="Verbose"/>
<add name="System.Net.Http" value="Verbose"/>
<add name="System.Net.Sockets" value="Verbose"/>
<add name="System.Net.WebSockets" value="Verbose"/>
</switches>
<sharedListeners>
<add name="System.Net"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="network-tracing.log"
/>
</sharedListeners>
<trace autoflush="true"/>
</system.diagnostics>
-->
</configuration>
@@ -253,7 +253,6 @@
<SubType>Designer</SubType>
</None>
<None Include="Data\abp.js.gz" />
<None Include="Data\libcrypto-1_1.dll.gz" />
<None Include="Data\libsscrypto.dll.gz" />
<None Include="Data\mgwz.dll.gz" />
<None Include="Data\privoxy.exe.gz" />