Compare commits

...
40 Commits
Author SHA1 Message Date
icylogic 391b1de2cf Merge pull request #316 from icylogic/release/2.5.7
Release/2.5.7
2015-09-19 16:24:24 +08:00
icylogic 8d2574b003 bump 2.5.7 2015-09-19 16:16:05 +08:00
icylogic 8e1c2193e4 replace Appveyor badges 2015-09-19 16:15:45 +08:00
icylogic 86bf0b3b2c Merge pull request #315 from icylogic/hotfix/repeated_iv
no repeat random number generator by GangZhuo
2015-09-19 15:53:01 +08:00
Gang Zhuo 72ea01d566 no repeat random number generator
The stock code use class Random to generate IV, the Random is pseudo random number generator. The IV maybe repeat, this will cause shadowsocks-libev closed the sockets with the error message 'invalid password or cipher'. Reference https://github.com/shadowsocks/shadowsocks-libev/issues/389

Solution is use class RNGCryptoServiceProvider to generate IV, of course it's lower performance, but a little bit.
2015-09-19 15:49:19 +08:00
icylogic b4699492ad Merge pull request #309 from huhu2207/master
Fix a tiny bug
2015-09-04 18:58:40 +08:00
Jackson Ming Hu 2fdb26c063 Fix a tiny bug
Sometimes the users may hit enter key by mistake, and the form will
close without saving entries.
2015-09-04 11:59:23 +10:00
icylogic 0f72ba1e48 Merge pull request #308 from icylogic/master
Add more clear log for exceptions occured in ICMP tests
2015-09-02 01:47:08 +08:00
icylogic 968c9deca0 Merge branch 'hotfix/more_clear_log' 2015-09-02 01:38:12 +08:00
icylogic 879163dc2b Add more clear log 2015-09-02 01:23:32 +08:00
clowwindy b07a9ef3b0 Merge pull request #300 from kimw/master
improved `log viewer` windows
2015-08-19 07:42:45 -07:00
clowwindy c095030041 Update README.md 2015-08-19 22:36:38 +08:00
clowwindy b8858c4f8d bump 2.5.6 2015-08-19 22:19:20 -07:00
clowwindy 726200c0f1 update CHANGES 2015-08-19 21:56:31 -07:00
clowwindy 765720dbd9 small fix 2015-08-19 21:51:28 -07:00
clowwindy c767f55b3c add portable mode 2015-08-19 21:39:06 -07:00
kimw 14381cf887 update version number 2015-08-19 22:23:54 +08:00
kimw e8fd92b9f7 Merge remote-tracking branch 'upstream/master' 2015-08-19 21:59:01 +08:00
kimw 99fe540e53 Merge remote-tracking branch 'upstream/master' 2015-08-19 21:55:40 +08:00
kimw cec6f79e7e improved log viewer:
1. add `clean log` feature
2. add `change font` feature
3. add `wrap text` feature
4. add `top most` feature
2015-08-19 21:52:16 +08:00
clowwindy 7ab5eae64c Merge pull request #297 from kimw/master
2 fixes, 1 feature, 1 code beautify
2015-08-19 04:39:49 -07:00
clowwindy b1ebfe7772 prevent moving up and down when unsaved 2015-08-19 19:35:37 -07:00
kimw f6085d9362 Merge remote-tracking branch 'upstream/master' 2015-08-19 18:39:23 +08:00
kimw 0b6dd0d653 refresh server list with friendly name 2015-08-19 18:38:11 +08:00
clowwindy 7081819390 timeout 30min -> 15min 2015-08-19 13:05:12 +08:00
kimw 1df5e4eb8a Merge remote-tracking branch 'upstream/master' 2015-08-19 00:30:29 +08:00
kimw 758c497eba same the source code format.
1/ removed dual empty line
2/ removed tailing spaces
3/ converted tabs into spaces
4/ added some TODO comments
2015-08-19 00:24:08 +08:00
kimw 3e1044fc41 rename variable _oldSelectedIndex to _lastSelectedIndex 2015-08-19 00:22:23 +08:00
kimw feaf7f70d0 fix translation typo 2015-08-19 00:20:39 +08:00
clowwindy e21eac1e40 Merge pull request #296 from kimw/master
support customize the server order
2015-08-18 08:55:38 -07:00
clowwindy 750ee4fa5f add handler timeout 2015-08-18 21:34:05 -07:00
clowwindy 3bc77d212a reduce cache size 2015-08-18 21:34:04 -07:00
kimw b623216af3 Merge remote-tracking branch 'upstream/master' 2015-08-18 23:51:53 +08:00
kimw f33fb04b89 support customize the server order 2015-08-18 23:48:52 +08:00
clowwindy 63b31f5aba fix translation 2015-08-18 05:07:38 +08:00
clowwindy 590322bca2 fix some translation 2015-08-18 05:07:04 +08:00
clowwindy 71bd0d2b5a improve user experience for some users 2015-08-18 04:26:11 -07:00
clowwindy 3b90b2124f Update README.md 2015-08-17 21:03:11 +08:00
clowwindy 85dc46d11e Update README.md 2015-08-17 20:55:01 +08:00
clowwindy fe692f89e1 Update README.md 2015-08-17 20:46:51 +08:00
30 changed files with 580 additions and 189 deletions
+12
View File
@@ -1,3 +1,15 @@
2.5.7 2015-09-19
- Fix repeated IV.
2.5.6 2015-08-19
- Add portable mode. Create shadowsocks_portable_mode.txt to use it
- Support server reorder
2.5.5 2015-08-17
- Fix crash when enabling Availability Statistics and some servers can not be resolved
- Allow multiple instances
- Other fixes
2.5.4 2015-08-16
- Hide Privoxy icon
+24 -2
View File
@@ -3,6 +3,8 @@ Shadowsocks for Windows
[![Build Status]][Appveyor]
[中文说明]
#### Features
1. System proxy configuration
@@ -46,6 +48,24 @@ with any editor, Shadowsocks will notify browsers about the change automatically
For UDP, you need to use SocksCap or ProxyCap to force programs you want
to be proxied to tunnel over Shadowsocks
#### Multiple Instances
If you want to manage multiple servers using other tools like SwitchyOmega,
you can start multiple Shadowsocks instances. To avoid configuration conflicts,
copy Shadowsocks to a new directory and choose a different local port.
Also, make sure to use `SOCKS5` proxy in SwitchyOmega, since we have only
one HTTP proxy instance.
#### Server Configuration
Please visit [Servers] for more information.
#### Portable Mode
If you want to put all temporary files into shadowsocks/temp folder instead of
system temp folder, create a `shadowsocks_portable_mode.txt` into shadowsocks folder.
#### Develop
Visual Studio 2015 is required.
@@ -55,7 +75,9 @@ Visual Studio 2015 is required.
GPLv3
[Appveyor]: https://ci.appveyor.com/project/clowwindy/shadowsocks-csharp
[Build Status]: https://ci.appveyor.com/api/projects/status/gknc8l1lxy423ehv/branch/master
[Appveyor]: https://ci.appveyor.com/project/icylogic/shadowsocks-windows-l9mwe
[Build Status]: https://ci.appveyor.com/api/projects/status/ytllr9yjkbpc2tu2/branch/master
[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
+1 -1
View File
@@ -12,7 +12,7 @@ namespace Shadowsocks.Controller
static I18N()
{
Strings = new Dictionary<string, string>();
if (System.Globalization.CultureInfo.CurrentCulture.IetfLanguageTag.ToLowerInvariant().StartsWith("zh"))
{
string[] lines = Regex.Split(Resources.cn, "\r\n|\r|\n");
+4 -4
View File
@@ -1,4 +1,5 @@
using System;
using Shadowsocks.Util;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
@@ -14,14 +15,14 @@ namespace Shadowsocks.Controller
{
try
{
string temppath = Path.GetTempPath();
string temppath = Utils.GetTempPath();
LogFile = Path.Combine(temppath, "shadowsocks.log");
FileStream fs = new FileStream(LogFile, FileMode.Append);
StreamWriterWithTimestamp sw = new StreamWriterWithTimestamp(fs);
sw.AutoFlush = true;
Console.SetOut(sw);
Console.SetError(sw);
return true;
}
catch (IOException e)
@@ -71,7 +72,6 @@ namespace Shadowsocks.Controller
Console.WriteLine(e);
}
}
}
// Simply extended System.IO.StreamWriter for adding timestamp workaround
@@ -6,6 +6,7 @@ using System.Net.NetworkInformation;
using System.Threading;
using Shadowsocks.Model;
using System.Reflection;
using Shadowsocks.Util;
namespace Shadowsocks.Controller
{
@@ -25,7 +26,7 @@ namespace Shadowsocks.Controller
//static constructor to initialize every public static fields before refereced
static AvailabilityStatistics()
{
string temppath = Path.GetTempPath();
string temppath = Utils.GetTempPath();
AvailabilityStatisticsFile = Path.Combine(temppath, StatisticsFilesName);
}
@@ -80,6 +81,7 @@ namespace Shadowsocks.Controller
}
catch (Exception e)
{
Console.WriteLine($"An exception occured when eveluating {server.FriendlyName()}");
Logging.LogUsefulException(e);
}
}
@@ -77,7 +77,6 @@ namespace Shadowsocks.Controller
_udpSocket.Bind(localEndPoint);
_tcpSocket.Listen(1024);
// Start an asynchronous socket to listen for connections.
Console.WriteLine("Shadowsocks started");
_tcpSocket.BeginAccept(
@@ -185,7 +184,6 @@ namespace Shadowsocks.Controller
}
}
private void ReceiveCallback(IAsyncResult ar)
{
object[] state = (object[])ar.AsyncState;
@@ -86,7 +86,6 @@ namespace Shadowsocks.Controller
}
}
public string TouchPACFile()
{
if (File.Exists(PAC_FILE))
@@ -146,7 +145,7 @@ Connection: Close
", System.Text.Encoding.UTF8.GetBytes(pac).Length) + pac;
byte[] response = System.Text.Encoding.UTF8.GetBytes(text);
socket.BeginSend(response, 0, response.Length, 0, new AsyncCallback(SendCallback), socket);
Util.Utils.ReleaseMemory();
Util.Utils.ReleaseMemory(true);
}
catch (Exception e)
{
@@ -9,6 +9,7 @@ using System.Text;
using System.Net.NetworkInformation;
using System.Net;
using System.Runtime.InteropServices;
using Shadowsocks.Util;
namespace Shadowsocks.Controller
{
@@ -20,7 +21,7 @@ namespace Shadowsocks.Controller
static PolipoRunner()
{
temppath = Path.GetTempPath();
temppath = Utils.GetTempPath();
try
{
FileManager.UncompressFile(temppath + "/ss_privoxy.exe", Resources.privoxy_exe);
@@ -147,7 +148,6 @@ namespace Shadowsocks.Controller
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
public void RefreshTrayArea()
{
IntPtr systemTrayContainerHandle = FindWindow("Shell_TrayWnd", null);
@@ -164,7 +164,6 @@ namespace Shadowsocks.Controller
RefreshTrayArea(notificationAreaHandle);
}
private static void RefreshTrayArea(IntPtr windowHandle)
{
const uint wmMousemove = 0x0200;
@@ -103,7 +103,6 @@ namespace Shadowsocks.Controller
}
}
private void StartPipe(IAsyncResult ar)
{
if (_closed)
@@ -14,9 +14,18 @@ namespace Shadowsocks.Controller
class TCPRelay : Listener.Service
{
private ShadowsocksController _controller;
private DateTime _lastSweepTime;
public ISet<Handler> Handlers
{
get; set;
}
public TCPRelay(ShadowsocksController controller)
{
this._controller = controller;
this.Handlers = new HashSet<Handler>();
this._lastSweepTime = DateTime.Now;
}
public bool Handle(byte[] firstPacket, int length, Socket socket, object state)
@@ -33,9 +42,33 @@ namespace Shadowsocks.Controller
Handler handler = new Handler();
handler.connection = socket;
handler.controller = _controller;
handler.relay = this;
handler.Start(firstPacket, length);
return true;
IList<Handler> handlersToClose = new List<Handler>();
lock (this.Handlers)
{
this.Handlers.Add(handler);
Logging.Debug($"connections: {Handlers.Count}");
DateTime now = DateTime.Now;
if (now - _lastSweepTime > TimeSpan.FromSeconds(1))
{
_lastSweepTime = now;
foreach (Handler handler1 in this.Handlers)
{
if (now - handler1.lastActivity > TimeSpan.FromSeconds(900))
{
handlersToClose.Add(handler1);
}
}
}
}
foreach (Handler handler1 in handlersToClose)
{
Logging.Debug("Closing timed out connection");
handler1.Close();
}
return true;
}
}
@@ -48,6 +81,10 @@ namespace Shadowsocks.Controller
public Socket remote;
public Socket connection;
public ShadowsocksController controller;
public TCPRelay relay;
public DateTime lastActivity;
private int retryCount = 0;
private bool connected;
@@ -55,7 +92,7 @@ namespace Shadowsocks.Controller
private byte[] _firstPacket;
private int _firstPacketLength;
// Size of receive buffer.
public const int RecvSize = 16384;
public const int RecvSize = 8192;
public const int BufferSize = RecvSize + 32;
private int totalRead = 0;
@@ -74,7 +111,7 @@ namespace Shadowsocks.Controller
private bool connectionShutdown = false;
private bool remoteShutdown = false;
private bool closed = false;
private object encryptionLock = new object();
private object decryptionLock = new object();
@@ -96,6 +133,7 @@ namespace Shadowsocks.Controller
this._firstPacket = firstPacket;
this._firstPacketLength = length;
this.HandshakeReceive();
this.lastActivity = DateTime.Now;
}
private void CheckClose()
@@ -108,6 +146,11 @@ namespace Shadowsocks.Controller
public void Close()
{
lock (relay.Handlers)
{
Logging.Debug($"connections: {relay.Handlers.Count}");
relay.Handlers.Remove(this);
}
lock (this)
{
if (closed)
@@ -152,7 +195,6 @@ namespace Shadowsocks.Controller
}
}
private void HandshakeReceive()
{
if (closed)
@@ -222,7 +264,7 @@ namespace Shadowsocks.Controller
try
{
int bytesRead = connection.EndReceive(ar);
if (bytesRead >= 3)
{
command = connetionRecvBuffer[1];
@@ -272,7 +314,6 @@ namespace Shadowsocks.Controller
private void ReadAll(IAsyncResult ar)
{
if (closed)
{
return;
@@ -347,7 +388,6 @@ namespace Shadowsocks.Controller
}
IPEndPoint remoteEP = new IPEndPoint(ipAddress, server.server_port);
remote = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
remote.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
@@ -485,6 +525,7 @@ namespace Shadowsocks.Controller
if (bytesRead > 0)
{
this.lastActivity = DateTime.Now;
int bytesToSend;
lock (decryptionLock)
{
@@ -548,7 +589,6 @@ namespace Shadowsocks.Controller
}
remote.BeginSend(connetionSendBuffer, 0, bytesToSend, 0, new AsyncCallback(PipeRemoteSendCallback), null);
IStrategy strategy = controller.GetCurrentStrategy();
if (strategy != null)
{
@@ -607,5 +647,4 @@ namespace Shadowsocks.Controller
}
}
}
}
@@ -108,9 +108,11 @@ namespace Shadowsocks.Controller
}
catch (ObjectDisposedException)
{
// TODO: handle the ObjectDisposedException
}
catch (Exception)
{
// TODO: need more think about handle other Exceptions, or should remove this catch().
}
finally
{
@@ -124,9 +126,11 @@ namespace Shadowsocks.Controller
}
catch (ObjectDisposedException)
{
// TODO: handle the ObjectDisposedException
}
catch (Exception)
{
// TODO: need more think about handle other Exceptions, or should remove this catch().
}
finally
{
@@ -134,6 +138,8 @@ namespace Shadowsocks.Controller
}
}
}
// cc by-sa 3.0 http://stackoverflow.com/a/3719378/1124054
class LRUCache<K, V> where V : UDPRelay.UDPHandler
{
@@ -196,5 +202,4 @@ namespace Shadowsocks.Controller
public K key;
public V value;
}
}
@@ -18,7 +18,7 @@ namespace Shadowsocks.Controller
public string LatestVersionURL;
public event EventHandler NewVersionFound;
public const string Version = "2.5.5";
public const string Version = "2.5.7";
public void CheckUpdate(Configuration config)
{
@@ -53,7 +53,6 @@ namespace Shadowsocks.Controller
{
return CompareVersion(ParseVersionFromURL(x), ParseVersionFromURL(y));
}
}
private static string ParseVersionFromURL(string url)
@@ -39,7 +39,7 @@ namespace Shadowsocks.Controller
public event EventHandler EnableStatusChanged;
public event EventHandler EnableGlobalChanged;
public event EventHandler ShareOverLANStatusChanged;
// when user clicked Edit PAC, and PAC file has already created
public event EventHandler<PathEventArgs> PACFileReadyToOpen;
public event EventHandler<PathEventArgs> UserRuleFileReadyToOpen;
@@ -360,17 +360,15 @@ namespace Shadowsocks.Controller
}
UpdateSystemProxy();
Util.Utils.ReleaseMemory();
Util.Utils.ReleaseMemory(true);
}
protected void SaveConfig(Configuration newConfig)
{
Configuration.Save(newConfig);
Reload();
}
private void UpdateSystemProxy()
{
if (_config.enabled)
@@ -417,7 +415,7 @@ namespace Shadowsocks.Controller
{
while (true)
{
Util.Utils.ReleaseMemory();
Util.Utils.ReleaseMemory(false);
Thread.Sleep(30 * 1000);
}
}
@@ -14,17 +14,17 @@ namespace Shadowsocks.Controller.Strategy
/*
* IStrategy
*
*
* Subclasses must be thread-safe
*/
public interface IStrategy
{
string Name { get; }
string ID { get; }
/*
* Called when servers need to be reloaded, i.e. new configuration saved
* Called when servers need to be reloaded, i.e. new configuration saved
*/
void ReloadServers();
@@ -112,7 +112,7 @@ namespace Shadowsocks.Controller.Strategy
).Aggregate((result1, result2) => result1.score > result2.score ? result1 : result2);
if (_controller.GetCurrentStrategy().ID == ID && _currentServer != bestResult.server) //output when enabled
{
{
Console.WriteLine("Switch to server: {0} by package loss:{1}", bestResult.server.FriendlyName(), 1 - bestResult.score);
}
_currentServer = bestResult.server;
+15 -2
View File
@@ -42,6 +42,19 @@ Remarks=备注
OK=确定
Cancel=取消
New server=未配置的服务器
Move &Up=上移(&U)
Move D&own=下移(&O)
# Log Form
&File=文件(&F)
&Open Location=在资源管理器中打开(&O)
E&xit=退出(&X)
&Clean logs=清空(&C)
&Font=字体(&F)
&Wrap text=自动换行(&W)
&Top most=置顶(&T)
Log Viewer=日志查看器
# QRCode Form
@@ -75,8 +88,8 @@ No updates found. Please report to GFWList if you have problems with it.=未发
No QRCode found. Try to zoom in or move it to the center of the screen.=未发现二维码,尝试把它放大或移动到靠近屏幕中间的位置
Shadowsocks is already running.=Shadowsocks 已经在运行。
Find Shadowsocks icon in your notify tray.=请在任务栏里寻找 Shadowsocks 图标。
If you want to start multiple Shadowsocks, make a copy in another directory.=如果想启动多份,可以另外复制一份到别的目录。
If you want to start multiple Shadowsocks, make a copy in another directory.=如果想同时启动多个,可以另外复制一份到别的目录。
Failed to decode QRCode=无法解析二维码
Failed to update registry=无法修改注册表
System Proxy On: =系统代理已启用:
Running: Port {0}=正在运行:端口 {0}
Running: Port {0}=正在运行:端口 {0}
+2 -2
View File
@@ -26,7 +26,6 @@ namespace Shadowsocks.Encryption
protected int keyLen;
protected int ivLen;
public IVEncryptor(string method, string password)
: base(method, password)
{
@@ -89,7 +88,8 @@ namespace Shadowsocks.Encryption
protected static void randBytes(byte[] buf, int length)
{
byte[] temp = new byte[length];
new Random().NextBytes(temp);
RNGCryptoServiceProvider rngServiceProvider = new RNGCryptoServiceProvider();
rngServiceProvider.GetBytes(temp);
temp.CopyTo(buf, 0);
}
+2 -2
View File
@@ -1,5 +1,6 @@
using Shadowsocks.Controller;
using Shadowsocks.Properties;
using Shadowsocks.Util;
using System;
using System.Collections.Generic;
using System.IO;
@@ -18,7 +19,7 @@ namespace Shadowsocks.Encryption
static PolarSSL()
{
string tempPath = Path.GetTempPath();
string tempPath = Utils.GetTempPath();
string dllPath = tempPath + "/libsscrypto.dll";
try
{
@@ -49,7 +50,6 @@ namespace Shadowsocks.Encryption
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public extern static int aes_crypt_cfb128(IntPtr ctx, int mode, int length, ref int iv_off, byte[] iv, byte[] input, byte[] output);
public const int ARC4_CTX_SIZE = 264;
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
+2 -1
View File
@@ -1,5 +1,6 @@
using Shadowsocks.Controller;
using Shadowsocks.Properties;
using Shadowsocks.Util;
using System;
using System.Collections.Generic;
using System.IO;
@@ -14,7 +15,7 @@ namespace Shadowsocks.Encryption
static Sodium()
{
string tempPath = Path.GetTempPath();
string tempPath = Utils.GetTempPath();
string dllPath = tempPath + "/libsscrypto.dll";
try
{
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace Shadowsocks.Encryption
{
@@ -12,19 +13,17 @@ namespace Shadowsocks.Encryption
const int SODIUM_BLOCK_SIZE = 64;
static byte[] sodiumBuf = new byte[MAX_INPUT_SIZE + SODIUM_BLOCK_SIZE];
protected int _encryptBytesRemaining;
protected int _decryptBytesRemaining;
protected ulong _encryptIC;
protected ulong _decryptIC;
protected byte[] _encryptBuf;
protected byte[] _decryptBuf;
public SodiumEncryptor(string method, string password)
: base(method, password)
{
InitKey(method, password);
_encryptBuf = new byte[MAX_INPUT_SIZE + SODIUM_BLOCK_SIZE];
_decryptBuf = new byte[MAX_INPUT_SIZE + SODIUM_BLOCK_SIZE];
}
private static Dictionary<string, int[]> _ciphers = new Dictionary<string, int[]> {
@@ -47,48 +46,51 @@ namespace Shadowsocks.Encryption
// TODO write a unidirection cipher so we don't have to if if if
int bytesRemaining;
ulong ic;
byte[] sodiumBuf;
byte[] iv;
if (isCipher)
{
bytesRemaining = _encryptBytesRemaining;
ic = _encryptIC;
sodiumBuf = _encryptBuf;
iv = _encryptIV;
}
else
{
bytesRemaining = _decryptBytesRemaining;
ic = _decryptIC;
sodiumBuf = _decryptBuf;
iv = _decryptIV;
}
int padding = bytesRemaining;
Buffer.BlockCopy(buf, 0, sodiumBuf, padding, length);
switch (_cipher)
// I'm tired. just add a big lock
// let's optimize for RAM instead of CPU
lock(sodiumBuf)
{
case CIPHER_SALSA20:
Sodium.crypto_stream_salsa20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key);
break;
case CIPHER_CHACHA20:
Sodium.crypto_stream_chacha20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key);
break;
}
Buffer.BlockCopy(sodiumBuf, padding, outbuf, 0, length);
padding += length;
ic += (ulong)padding / SODIUM_BLOCK_SIZE;
bytesRemaining = padding % SODIUM_BLOCK_SIZE;
if (isCipher)
{
bytesRemaining = _encryptBytesRemaining;
ic = _encryptIC;
iv = _encryptIV;
}
else
{
bytesRemaining = _decryptBytesRemaining;
ic = _decryptIC;
iv = _decryptIV;
}
int padding = bytesRemaining;
Buffer.BlockCopy(buf, 0, sodiumBuf, padding, length);
if (isCipher)
{
_encryptBytesRemaining = bytesRemaining;
_encryptIC = ic;
}
else
{
_decryptBytesRemaining = bytesRemaining;
_decryptIC = ic;
switch (_cipher)
{
case CIPHER_SALSA20:
Sodium.crypto_stream_salsa20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key);
break;
case CIPHER_CHACHA20:
Sodium.crypto_stream_chacha20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key);
break;
}
Buffer.BlockCopy(sodiumBuf, padding, outbuf, 0, length);
padding += length;
ic += (ulong)padding / SODIUM_BLOCK_SIZE;
bytesRemaining = padding % SODIUM_BLOCK_SIZE;
if (isCipher)
{
_encryptBytesRemaining = bytesRemaining;
_encryptIC = ic;
}
else
{
_decryptBytesRemaining = bytesRemaining;
_decryptIC = ic;
}
}
}
@@ -41,7 +41,6 @@ namespace Shadowsocks.Encryption
outlength = length;
}
public override void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength)
{
byte[] result = new byte[length];
@@ -100,7 +99,6 @@ namespace Shadowsocks.Encryption
return sorted;
}
public override void Dispose()
{
}
+1 -1
View File
@@ -18,7 +18,7 @@ namespace Shadowsocks
[STAThread]
static void Main()
{
Util.Utils.ReleaseMemory();
Util.Utils.ReleaseMemory(true);
using (Mutex mutex = new Mutex(false, "Global\\Shadowsocks_" + Application.StartupPath.GetHashCode()))
{
Application.EnableVisualStyles();
+43 -3
View File
@@ -5,12 +5,31 @@ using System.IO;
using System.IO.Compression;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
namespace Shadowsocks.Util
{
public class Utils
{
public static void ReleaseMemory()
// return path to store temporary files
public static string GetTempPath()
{
if (File.Exists(Application.StartupPath + "\\shadowsocks_portable_mode.txt"))
{
try
{
Directory.CreateDirectory(Application.StartupPath + "\\temp");
} catch (Exception e)
{
Console.WriteLine(e);
}
// don't use "/", it will fail when we call explorer /select xxx/temp\xxx.log
return Application.StartupPath + "\\temp";
}
return Path.GetTempPath();
}
public static void ReleaseMemory(bool removePages)
{
// release any unused pages
// making the numbers look good in task manager
@@ -20,8 +39,29 @@ namespace Shadowsocks.Util
// which is part of user experience
GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers();
SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle,
(UIntPtr)0xFFFFFFFF, (UIntPtr)0xFFFFFFFF);
if (removePages)
{
// as some users have pointed out
// removing pages from working set will cause some IO
// which lowered user experience for another group of users
//
// so we do 2 more things here to satisfy them:
// 1. only remove pages once when configuration is changed
// 2. add more comments here to tell users that calling
// this function will not be more frequent than
// IM apps writing chat logs, or web browsers writing cache files
// if they're so concerned about their disk, they should
// uninstall all IM apps and web browsers
//
// please open an issue if you're worried about anything else in your computer
// no matter it's GPU performance, monitor contrast, audio fidelity
// or anything else in the task manager
// we'll do as much as we can to help you
//
// just kidding
SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle,
(UIntPtr)0xFFFFFFFF, (UIntPtr)0xFFFFFFFF);
}
}
public static string UnGzip(byte[] buf)
+53 -1
View File
@@ -47,6 +47,9 @@
this.ServerGroupBox = new System.Windows.Forms.GroupBox();
this.ServersListBox = new System.Windows.Forms.ListBox();
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
this.tableLayoutPanel6 = new System.Windows.Forms.TableLayoutPanel();
this.MoveDownButton = new System.Windows.Forms.Button();
this.MoveUpButton = new System.Windows.Forms.Button();
this.tableLayoutPanel5 = new System.Windows.Forms.TableLayoutPanel();
this.ProxyPortTextBox = new System.Windows.Forms.TextBox();
this.ProxyPortLabel = new System.Windows.Forms.Label();
@@ -55,6 +58,7 @@
this.tableLayoutPanel1.SuspendLayout();
this.ServerGroupBox.SuspendLayout();
this.tableLayoutPanel2.SuspendLayout();
this.tableLayoutPanel6.SuspendLayout();
this.tableLayoutPanel5.SuspendLayout();
this.tableLayoutPanel3.SuspendLayout();
this.tableLayoutPanel4.SuspendLayout();
@@ -184,7 +188,7 @@
//
// EncryptionSelect
//
this.EncryptionSelect.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
this.EncryptionSelect.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.EncryptionSelect.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.EncryptionSelect.FormattingEnabled = true;
@@ -281,6 +285,7 @@
//
this.ServersListBox.FormattingEnabled = true;
this.ServersListBox.IntegralHeight = false;
this.ServersListBox.ItemHeight = 12;
this.ServersListBox.Location = new System.Drawing.Point(0, 0);
this.ServersListBox.Margin = new System.Windows.Forms.Padding(0);
this.ServersListBox.Name = "ServersListBox";
@@ -295,6 +300,7 @@
this.tableLayoutPanel2.ColumnCount = 2;
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel6, 0, 2);
this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel5, 1, 1);
this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel3, 1, 2);
this.tableLayoutPanel2.Controls.Add(this.ServersListBox, 0, 0);
@@ -310,6 +316,48 @@
this.tableLayoutPanel2.Size = new System.Drawing.Size(427, 238);
this.tableLayoutPanel2.TabIndex = 7;
//
// tableLayoutPanel6
//
this.tableLayoutPanel6.AutoSize = true;
this.tableLayoutPanel6.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.tableLayoutPanel6.ColumnCount = 2;
this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel6.Controls.Add(this.MoveDownButton, 1, 0);
this.tableLayoutPanel6.Controls.Add(this.MoveUpButton, 0, 0);
this.tableLayoutPanel6.Dock = System.Windows.Forms.DockStyle.Top;
this.tableLayoutPanel6.Location = new System.Drawing.Point(0, 211);
this.tableLayoutPanel6.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel6.Name = "tableLayoutPanel6";
this.tableLayoutPanel6.RowCount = 1;
this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel6.Size = new System.Drawing.Size(166, 32);
this.tableLayoutPanel6.TabIndex = 10;
//
// MoveDownButton
//
this.MoveDownButton.Dock = System.Windows.Forms.DockStyle.Right;
this.MoveDownButton.Location = new System.Drawing.Point(86, 6);
this.MoveDownButton.Margin = new System.Windows.Forms.Padding(3, 6, 0, 3);
this.MoveDownButton.Name = "MoveDownButton";
this.MoveDownButton.Size = new System.Drawing.Size(80, 23);
this.MoveDownButton.TabIndex = 7;
this.MoveDownButton.Text = "Move D&own";
this.MoveDownButton.UseVisualStyleBackColor = true;
this.MoveDownButton.Click += new System.EventHandler(this.MoveDownButton_Click);
//
// MoveUpButton
//
this.MoveUpButton.Dock = System.Windows.Forms.DockStyle.Left;
this.MoveUpButton.Location = new System.Drawing.Point(0, 6);
this.MoveUpButton.Margin = new System.Windows.Forms.Padding(0, 6, 3, 3);
this.MoveUpButton.Name = "MoveUpButton";
this.MoveUpButton.Size = new System.Drawing.Size(80, 23);
this.MoveUpButton.TabIndex = 6;
this.MoveUpButton.Text = "Move &Up";
this.MoveUpButton.UseVisualStyleBackColor = true;
this.MoveUpButton.Click += new System.EventHandler(this.MoveUpButton_Click);
//
// tableLayoutPanel5
//
this.tableLayoutPanel5.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
@@ -418,6 +466,7 @@
this.ServerGroupBox.PerformLayout();
this.tableLayoutPanel2.ResumeLayout(false);
this.tableLayoutPanel2.PerformLayout();
this.tableLayoutPanel6.ResumeLayout(false);
this.tableLayoutPanel5.ResumeLayout(false);
this.tableLayoutPanel5.PerformLayout();
this.tableLayoutPanel3.ResumeLayout(false);
@@ -453,6 +502,9 @@
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel5;
private System.Windows.Forms.TextBox ProxyPortTextBox;
private System.Windows.Forms.Label ProxyPortLabel;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel6;
private System.Windows.Forms.Button MoveDownButton;
private System.Windows.Forms.Button MoveUpButton;
}
}
+118 -26
View File
@@ -18,7 +18,7 @@ namespace Shadowsocks.View
// this is a copy of configuration that we are working on
private Configuration _modifiedConfiguration;
private int _oldSelectedIndex = -1;
private int _lastSelectedIndex = -1;
public ConfigForm(ShadowsocksController controller)
{
@@ -51,6 +51,8 @@ namespace Shadowsocks.View
ServerGroupBox.Text = I18N.GetString("Server");
OKButton.Text = I18N.GetString("OK");
MyCancelButton.Text = I18N.GetString("Cancel");
MoveUpButton.Text = I18N.GetString("Move &Up");
MoveDownButton.Text = I18N.GetString("Move D&own");
this.Text = I18N.GetString("Edit Servers");
}
@@ -58,7 +60,7 @@ namespace Shadowsocks.View
{
LoadCurrentConfiguration();
}
private void ShowWindow()
{
this.Opacity = 1;
@@ -70,7 +72,7 @@ namespace Shadowsocks.View
{
try
{
if (_oldSelectedIndex == -1 || _oldSelectedIndex >= _modifiedConfiguration.configs.Count)
if (_lastSelectedIndex == -1 || _lastSelectedIndex >= _modifiedConfiguration.configs.Count)
{
return true;
}
@@ -85,9 +87,9 @@ namespace Shadowsocks.View
int localPort = int.Parse(ProxyPortTextBox.Text);
Configuration.CheckServer(server);
Configuration.CheckLocalPort(localPort);
_modifiedConfiguration.configs[_oldSelectedIndex] = server;
_modifiedConfiguration.configs[_lastSelectedIndex] = server;
_modifiedConfiguration.localPort = localPort;
return true;
}
catch (FormatException)
@@ -113,12 +115,6 @@ namespace Shadowsocks.View
ProxyPortTextBox.Text = _modifiedConfiguration.localPort.ToString();
EncryptionSelect.Text = server.method ?? "aes-256-cfb";
RemarksTextBox.Text = server.remarks;
ServerGroupBox.Visible = true;
//IPTextBox.Focus();
}
else
{
ServerGroupBox.Visible = false;
}
}
@@ -135,12 +131,13 @@ namespace Shadowsocks.View
{
_modifiedConfiguration = controller.GetConfigurationCopy();
LoadConfiguration(_modifiedConfiguration);
_oldSelectedIndex = _modifiedConfiguration.index;
if (_oldSelectedIndex < 0)
_lastSelectedIndex = _modifiedConfiguration.index;
if (_lastSelectedIndex < 0)
{
_oldSelectedIndex = 0;
_lastSelectedIndex = 0;
}
ServersListBox.SelectedIndex = _oldSelectedIndex;
ServersListBox.SelectedIndex = _lastSelectedIndex;
UpdateMoveUpAndDownButton();
LoadSelectedServer();
}
@@ -149,9 +146,35 @@ namespace Shadowsocks.View
}
private void ConfigForm_KeyDown(object sender, KeyEventArgs e)
{
// Sometimes the users may hit enter key by mistake, and the form will close without saving entries.
if (e.KeyCode == Keys.Enter)
{
Server server = controller.GetCurrentServer();
if (!SaveOldSelectedServer())
{
return;
}
if (_modifiedConfiguration.configs.Count == 0)
{
MessageBox.Show(I18N.GetString("Please add at least one server"));
return;
}
controller.SaveServers(_modifiedConfiguration.configs, _modifiedConfiguration.localPort);
controller.SelectServerIndex(_modifiedConfiguration.configs.IndexOf(server));
}
}
private void ServersListBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (_oldSelectedIndex == ServersListBox.SelectedIndex)
if (!ServersListBox.CanSelect)
{
return;
}
if (_lastSelectedIndex == ServersListBox.SelectedIndex)
{
// we are moving back to oldSelectedIndex or doing a force move
return;
@@ -159,11 +182,13 @@ namespace Shadowsocks.View
if (!SaveOldSelectedServer())
{
// why this won't cause stack overflow?
ServersListBox.SelectedIndex = _oldSelectedIndex;
ServersListBox.SelectedIndex = _lastSelectedIndex;
return;
}
ServersListBox.Items[_lastSelectedIndex] = _modifiedConfiguration.configs[_lastSelectedIndex].FriendlyName();
UpdateMoveUpAndDownButton();
LoadSelectedServer();
_oldSelectedIndex = ServersListBox.SelectedIndex;
_lastSelectedIndex = ServersListBox.SelectedIndex;
}
private void AddButton_Click(object sender, EventArgs e)
@@ -176,29 +201,30 @@ namespace Shadowsocks.View
_modifiedConfiguration.configs.Add(server);
LoadConfiguration(_modifiedConfiguration);
ServersListBox.SelectedIndex = _modifiedConfiguration.configs.Count - 1;
_oldSelectedIndex = ServersListBox.SelectedIndex;
_lastSelectedIndex = ServersListBox.SelectedIndex;
}
private void DeleteButton_Click(object sender, EventArgs e)
{
_oldSelectedIndex = ServersListBox.SelectedIndex;
if (_oldSelectedIndex >= 0 && _oldSelectedIndex < _modifiedConfiguration.configs.Count)
_lastSelectedIndex = ServersListBox.SelectedIndex;
if (_lastSelectedIndex >= 0 && _lastSelectedIndex < _modifiedConfiguration.configs.Count)
{
_modifiedConfiguration.configs.RemoveAt(_oldSelectedIndex);
_modifiedConfiguration.configs.RemoveAt(_lastSelectedIndex);
}
if (_oldSelectedIndex >= _modifiedConfiguration.configs.Count)
if (_lastSelectedIndex >= _modifiedConfiguration.configs.Count)
{
// can be -1
_oldSelectedIndex = _modifiedConfiguration.configs.Count - 1;
_lastSelectedIndex = _modifiedConfiguration.configs.Count - 1;
}
ServersListBox.SelectedIndex = _oldSelectedIndex;
ServersListBox.SelectedIndex = _lastSelectedIndex;
LoadConfiguration(_modifiedConfiguration);
ServersListBox.SelectedIndex = _oldSelectedIndex;
ServersListBox.SelectedIndex = _lastSelectedIndex;
LoadSelectedServer();
}
private void OKButton_Click(object sender, EventArgs e)
{
Server server = controller.GetCurrentServer();
if (!SaveOldSelectedServer())
{
return;
@@ -209,6 +235,7 @@ namespace Shadowsocks.View
return;
}
controller.SaveServers(_modifiedConfiguration.configs, _modifiedConfiguration.localPort);
controller.SelectServerIndex(_modifiedConfiguration.configs.IndexOf(server));
this.Close();
}
@@ -227,5 +254,70 @@ namespace Shadowsocks.View
controller.ConfigChanged -= controller_ConfigChanged;
}
private void MoveConfigItem(int step)
{
int index = ServersListBox.SelectedIndex;
Server server = _modifiedConfiguration.configs[index];
object item = ServersListBox.SelectedItem;
_modifiedConfiguration.configs.Remove(server);
_modifiedConfiguration.configs.Insert(index + step, server);
_modifiedConfiguration.index += step;
ServersListBox.BeginUpdate();
ServersListBox.Enabled = false;
_lastSelectedIndex = index + step;
ServersListBox.Items.Remove(item);
ServersListBox.Items.Insert(index + step, item);
ServersListBox.Enabled = true;
ServersListBox.SelectedIndex = index + step;
ServersListBox.EndUpdate();
UpdateMoveUpAndDownButton();
}
private void UpdateMoveUpAndDownButton()
{
if (ServersListBox.SelectedIndex == 0)
{
MoveUpButton.Enabled = false;
}
else
{
MoveUpButton.Enabled = true;
}
if (ServersListBox.SelectedIndex == ServersListBox.Items.Count - 1)
{
MoveDownButton.Enabled = false;
}
else
{
MoveDownButton.Enabled = true;
}
}
private void MoveUpButton_Click(object sender, EventArgs e)
{
if (!SaveOldSelectedServer())
{
return;
}
if (ServersListBox.SelectedIndex > 0)
{
MoveConfigItem(-1); // -1 means move backward
}
}
private void MoveDownButton_Click(object sender, EventArgs e)
{
if (!SaveOldSelectedServer())
{
return;
}
if (ServersListBox.SelectedIndex < ServersListBox.Items.Count - 1)
{
MoveConfigItem(+1); // +1 means move forward
}
}
}
}
+2 -2
View File
@@ -112,9 +112,9 @@
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<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=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
+127 -41
View File
@@ -29,29 +29,37 @@
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.textBox1 = new System.Windows.Forms.TextBox();
this.LogMessageTextBox = new System.Windows.Forms.TextBox();
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
this.mainMenu1 = new System.Windows.Forms.MainMenu(this.components);
this.menuItem1 = new System.Windows.Forms.MenuItem();
this.menuItem2 = new System.Windows.Forms.MenuItem();
this.menuItem4 = new System.Windows.Forms.MenuItem();
this.FileMenuItem = new System.Windows.Forms.MenuItem();
this.OpenLocationMenuItem = new System.Windows.Forms.MenuItem();
this.ExitMenuItem = new System.Windows.Forms.MenuItem();
this.panel1 = new System.Windows.Forms.Panel();
this.ChangeFontButton = new System.Windows.Forms.Button();
this.CleanLogsButton = new System.Windows.Forms.Button();
this.WrapTextCheckBox = new System.Windows.Forms.CheckBox();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.TopMostCheckBox = new System.Windows.Forms.CheckBox();
this.panel1.SuspendLayout();
this.tableLayoutPanel1.SuspendLayout();
this.SuspendLayout();
//
// textBox1
// LogMessageTextBox
//
this.textBox1.BackColor = System.Drawing.Color.Black;
this.textBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.textBox1.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.textBox1.ForeColor = System.Drawing.Color.White;
this.textBox1.Location = new System.Drawing.Point(0, 0);
this.textBox1.MaxLength = 2147483647;
this.textBox1.Multiline = true;
this.textBox1.Name = "textBox1";
this.textBox1.ReadOnly = true;
this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.textBox1.Size = new System.Drawing.Size(547, 382);
this.textBox1.TabIndex = 0;
this.textBox1.WordWrap = false;
this.LogMessageTextBox.BackColor = System.Drawing.Color.Black;
this.LogMessageTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.LogMessageTextBox.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.LogMessageTextBox.ForeColor = System.Drawing.Color.White;
this.LogMessageTextBox.Location = new System.Drawing.Point(3, 43);
this.LogMessageTextBox.MaxLength = 2147483647;
this.LogMessageTextBox.Multiline = true;
this.LogMessageTextBox.Name = "LogMessageTextBox";
this.LogMessageTextBox.ReadOnly = true;
this.LogMessageTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.LogMessageTextBox.Size = new System.Drawing.Size(541, 307);
this.LogMessageTextBox.TabIndex = 0;
this.LogMessageTextBox.WordWrap = false;
//
// contextMenuStrip1
//
@@ -61,34 +69,103 @@
// mainMenu1
//
this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.menuItem1});
this.FileMenuItem});
//
// menuItem1
// FileMenuItem
//
this.menuItem1.Index = 0;
this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.menuItem2,
this.menuItem4});
this.menuItem1.Text = "&File";
this.FileMenuItem.Index = 0;
this.FileMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.OpenLocationMenuItem,
this.ExitMenuItem});
this.FileMenuItem.Text = "&File";
//
// menuItem2
// OpenLocationMenuItem
//
this.menuItem2.Index = 0;
this.menuItem2.Text = "&Open Location";
this.menuItem2.Click += new System.EventHandler(this.menuItem2_Click);
this.OpenLocationMenuItem.Index = 0;
this.OpenLocationMenuItem.Text = "&Open Location";
this.OpenLocationMenuItem.Click += new System.EventHandler(this.OpenLocationMenuItem_Click);
//
// menuItem4
// ExitMenuItem
//
this.menuItem4.Index = 1;
this.menuItem4.Text = "E&xit";
this.menuItem4.Click += new System.EventHandler(this.menuItem4_Click);
this.ExitMenuItem.Index = 1;
this.ExitMenuItem.Text = "E&xit";
this.ExitMenuItem.Click += new System.EventHandler(this.ExitMenuItem_Click);
//
// panel1
//
this.panel1.Controls.Add(this.TopMostCheckBox);
this.panel1.Controls.Add(this.ChangeFontButton);
this.panel1.Controls.Add(this.CleanLogsButton);
this.panel1.Controls.Add(this.WrapTextCheckBox);
this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel1.Location = new System.Drawing.Point(3, 3);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(541, 34);
this.panel1.TabIndex = 1;
//
// ChangeFontButton
//
this.ChangeFontButton.Location = new System.Drawing.Point(107, 4);
this.ChangeFontButton.Name = "ChangeFontButton";
this.ChangeFontButton.Size = new System.Drawing.Size(75, 23);
this.ChangeFontButton.TabIndex = 2;
this.ChangeFontButton.Text = "&Font";
this.ChangeFontButton.UseVisualStyleBackColor = true;
this.ChangeFontButton.Click += new System.EventHandler(this.ChangeFontButton_Click);
//
// CleanLogsButton
//
this.CleanLogsButton.Location = new System.Drawing.Point(9, 4);
this.CleanLogsButton.Name = "CleanLogsButton";
this.CleanLogsButton.Size = new System.Drawing.Size(75, 23);
this.CleanLogsButton.TabIndex = 1;
this.CleanLogsButton.Text = "&Clean logs";
this.CleanLogsButton.UseVisualStyleBackColor = true;
this.CleanLogsButton.Click += new System.EventHandler(this.CleanLogsButton_Click);
//
// WrapTextCheckBox
//
this.WrapTextCheckBox.AutoSize = true;
this.WrapTextCheckBox.Location = new System.Drawing.Point(209, 9);
this.WrapTextCheckBox.Name = "WrapTextCheckBox";
this.WrapTextCheckBox.Size = new System.Drawing.Size(78, 16);
this.WrapTextCheckBox.TabIndex = 0;
this.WrapTextCheckBox.Text = "&Wrap text";
this.WrapTextCheckBox.UseVisualStyleBackColor = true;
this.WrapTextCheckBox.CheckedChanged += new System.EventHandler(this.WrapTextCheckBox_CheckedChanged);
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.ColumnCount = 1;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Controls.Add(this.panel1, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.LogMessageTextBox, 0, 1);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 2;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.Size = new System.Drawing.Size(547, 353);
this.tableLayoutPanel1.TabIndex = 2;
//
// TopMostCheckBox
//
this.TopMostCheckBox.AutoSize = true;
this.TopMostCheckBox.Location = new System.Drawing.Point(311, 9);
this.TopMostCheckBox.Name = "TopMostCheckBox";
this.TopMostCheckBox.Size = new System.Drawing.Size(72, 16);
this.TopMostCheckBox.TabIndex = 3;
this.TopMostCheckBox.Text = "&Top most";
this.TopMostCheckBox.UseVisualStyleBackColor = true;
this.TopMostCheckBox.CheckedChanged += new System.EventHandler(this.TopMostCheckBox_CheckedChanged);
//
// LogForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(547, 382);
this.Controls.Add(this.textBox1);
this.ClientSize = new System.Drawing.Size(547, 353);
this.Controls.Add(this.tableLayoutPanel1);
this.Menu = this.mainMenu1;
this.Name = "LogForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
@@ -96,18 +173,27 @@
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.LogForm_FormClosing);
this.Load += new System.EventHandler(this.LogForm_Load);
this.Shown += new System.EventHandler(this.LogForm_Shown);
this.panel1.ResumeLayout(false);
this.panel1.PerformLayout();
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.TextBox LogMessageTextBox;
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
private System.Windows.Forms.MainMenu mainMenu1;
private System.Windows.Forms.MenuItem menuItem1;
private System.Windows.Forms.MenuItem menuItem2;
private System.Windows.Forms.MenuItem menuItem4;
private System.Windows.Forms.MenuItem FileMenuItem;
private System.Windows.Forms.MenuItem OpenLocationMenuItem;
private System.Windows.Forms.MenuItem ExitMenuItem;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.CheckBox WrapTextCheckBox;
private System.Windows.Forms.Button CleanLogsButton;
private System.Windows.Forms.Button ChangeFontButton;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.CheckBox TopMostCheckBox;
}
}
+51 -14
View File
@@ -1,4 +1,5 @@
using Shadowsocks.Properties;
using Shadowsocks.Controller;
using Shadowsocks.Properties;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@@ -23,6 +24,20 @@ namespace Shadowsocks.View
this.filename = filename;
InitializeComponent();
this.Icon = Icon.FromHandle(Resources.ssw128.GetHicon());
UpdateTexts();
}
private void UpdateTexts()
{
FileMenuItem.Text = I18N.GetString("&File");
OpenLocationMenuItem.Text = I18N.GetString("&Open Location");
ExitMenuItem.Text = I18N.GetString("E&xit");
CleanLogsButton.Text = I18N.GetString("&Clean logs");
ChangeFontButton.Text = I18N.GetString("&Font");
WrapTextCheckBox.Text = I18N.GetString("&Wrap text");
TopMostCheckBox.Text = I18N.GetString("&Top most");
this.Text = I18N.GetString("Log Viewer");
}
private void Timer_Tick(object sender, EventArgs e)
@@ -43,9 +58,9 @@ namespace Shadowsocks.View
string line = "";
while ((line = reader.ReadLine()) != null)
textBox1.AppendText(line + "\r\n");
LogMessageTextBox.AppendText(line + "\r\n");
textBox1.ScrollToCaret();
LogMessageTextBox.ScrollToCaret();
lastOffset = reader.BaseStream.Position;
}
@@ -63,12 +78,12 @@ namespace Shadowsocks.View
while ((line = reader.ReadLine()) != null)
{
changed = true;
textBox1.AppendText(line + "\r\n");
LogMessageTextBox.AppendText(line + "\r\n");
}
if (changed)
{
textBox1.ScrollToCaret();
LogMessageTextBox.ScrollToCaret();
}
lastOffset = reader.BaseStream.Position;
@@ -89,25 +104,47 @@ namespace Shadowsocks.View
timer.Stop();
}
private void menuItem2_Click(object sender, EventArgs e)
private void OpenLocationMenuItem_Click(object sender, EventArgs e)
{
string argument = @"/select, " + filename;
string argument = "/select, \"" + filename + "\"";
Console.WriteLine(argument);
System.Diagnostics.Process.Start("explorer.exe", argument);
}
private void menuItem3_Click(object sender, EventArgs e)
{
}
private void menuItem4_Click(object sender, EventArgs e)
private void ExitMenuItem_Click(object sender, EventArgs e)
{
this.Close();
}
private void LogForm_Shown(object sender, EventArgs e)
{
textBox1.ScrollToCaret();
LogMessageTextBox.ScrollToCaret();
}
private void WrapTextCheckBox_CheckedChanged(object sender, EventArgs e)
{
LogMessageTextBox.WordWrap = WrapTextCheckBox.Checked;
LogMessageTextBox.ScrollToCaret();
}
private void CleanLogsButton_Click(object sender, EventArgs e)
{
LogMessageTextBox.Clear();
}
private void ChangeFontButton_Click(object sender, EventArgs e)
{
FontDialog fd = new FontDialog();
fd.Font = LogMessageTextBox.Font;
if (fd.ShowDialog() == DialogResult.OK)
{
LogMessageTextBox.Font = fd.Font;
}
}
private void TopMostCheckBox_CheckedChanged(object sender, EventArgs e)
{
this.TopMost = TopMostCheckBox.Checked;
}
}
}
+11 -11
View File
@@ -18,7 +18,7 @@ namespace Shadowsocks.View
// yes this is just a menu view controller
// when config form is closed, it moves away from RAM
// and it should just do anything related to the config form
private ShadowsocksController controller;
private UpdateChecker updateChecker;
@@ -322,7 +322,7 @@ namespace Shadowsocks.View
void configForm_FormClosed(object sender, FormClosedEventArgs e)
{
configForm = null;
Util.Utils.ReleaseMemory();
Util.Utils.ReleaseMemory(true);
ShowFirstTimeBalloon();
}
@@ -520,17 +520,17 @@ namespace Shadowsocks.View
Process.Start(_urlToOpen);
}
private void AutoStartupItem_Click(object sender, EventArgs e) {
AutoStartupItem.Checked = !AutoStartupItem.Checked;
if (!AutoStartup.Set(AutoStartupItem.Checked)) {
MessageBox.Show(I18N.GetString("Failed to update registry"));
}
}
private void AutoStartupItem_Click(object sender, EventArgs e) {
AutoStartupItem.Checked = !AutoStartupItem.Checked;
if (!AutoStartup.Set(AutoStartupItem.Checked)) {
MessageBox.Show(I18N.GetString("Failed to update registry"));
}
}
private void AvailabilityStatisticsItem_Click(object sender, EventArgs e) {
AvailabilityStatistics.Checked = !AvailabilityStatistics.Checked;
private void AvailabilityStatisticsItem_Click(object sender, EventArgs e) {
AvailabilityStatistics.Checked = !AvailabilityStatistics.Checked;
controller.ToggleAvailabilityStatistics(AvailabilityStatistics.Checked);
}
}
private void LocalPACItem_Click(object sender, EventArgs e)
{
@@ -242,7 +242,6 @@ namespace Shadowsocks.View
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)
{
@@ -288,7 +287,6 @@ namespace Shadowsocks.View
}
}
protected override CreateParams CreateParams
{
get