Browse Source

Merge remote-tracking branch 'refs/remotes/shadowsocks/master'

Conflicts:
	shadowsocks-csharp/Data/cn.txt
pull/76/head
sui 10 years ago
parent
commit
578c386ada
15 changed files with 219 additions and 39 deletions
  1. +4
    -0
      README.md
  2. +3
    -3
      shadowsocks-csharp/3rd/SimpleJson.cs
  3. +68
    -0
      shadowsocks-csharp/Controller/GfwListUpdater.cs
  4. +26
    -2
      shadowsocks-csharp/Controller/Logging.cs
  5. +4
    -15
      shadowsocks-csharp/Controller/PACServer.cs
  6. +33
    -2
      shadowsocks-csharp/Controller/ShadowsocksController.cs
  7. +2
    -1
      shadowsocks-csharp/Controller/UpdateChecker.cs
  8. BIN
      shadowsocks-csharp/Data/abp.js.gz
  9. +5
    -2
      shadowsocks-csharp/Data/cn.txt
  10. +1
    -1
      shadowsocks-csharp/Program.cs
  11. +11
    -1
      shadowsocks-csharp/Properties/Resources.Designer.cs
  12. +3
    -0
      shadowsocks-csharp/Properties/Resources.resx
  13. +21
    -1
      shadowsocks-csharp/Util/Util.cs
  14. +30
    -5
      shadowsocks-csharp/View/MenuViewController.cs
  15. +8
    -6
      shadowsocks-csharp/shadowsocks-csharp.csproj

+ 4
- 0
README.md View File

@@ -30,6 +30,10 @@ about the change automatically
6. Please disable other proxy addons in your browser, or set them to use
system proxy

### Develop

Visual Studio Express 2012 is recommended.

#### License

GPLv3


+ 3
- 3
shadowsocks-csharp/3rd/SimpleJson.cs View File

@@ -1035,13 +1035,13 @@ namespace SimpleJson
protected static bool SerializeArray(IJsonSerializerStrategy jsonSerializerStrategy, IEnumerable anArray, StringBuilder builder)
{
builder.Append("[");
builder.Append("[\r\n ");
bool first = true;
foreach (object value in anArray)
{
if (!first)
builder.Append(",");
builder.Append(",\r\n ");
if (!SerializeValue(jsonSerializerStrategy, value, builder))
return false;
@@ -1049,7 +1049,7 @@ namespace SimpleJson
first = false;
}
builder.Append("]");
builder.Append("\r\n]");
return true;
}


+ 68
- 0
shadowsocks-csharp/Controller/GfwListUpdater.cs View File

@@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using Shadowsocks.Properties;
using SimpleJson;
using Shadowsocks.Util;
namespace Shadowsocks.Controller
{
public class GFWListUpdater
{
private const string GFWLIST_URL = "https://autoproxy-gfwlist.googlecode.com/svn/trunk/gfwlist.txt";
private static string PAC_FILE = PACServer.PAC_FILE;
public event EventHandler UpdateCompleted;
public event ErrorEventHandler Error;
private void http_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
try
{
List<string> lines = ParseResult(e.Result);
string abpContent = Utils.UnGzip(Resources.abp_js);
abpContent = abpContent.Replace("__RULES__", SimpleJson.SimpleJson.SerializeObject(lines));
File.WriteAllText(PAC_FILE, abpContent, Encoding.UTF8);
if (UpdateCompleted != null)
{
UpdateCompleted(this, new EventArgs());
}
}
catch (Exception ex)
{
if (Error != null)
{
Error(this, new ErrorEventArgs(ex));
}
}
}
public void UpdatePACFromGFWList()
{
WebClient http = new WebClient();
http.Proxy = new WebProxy(IPAddress.Loopback.ToString(), 8123);
http.DownloadStringCompleted += http_DownloadStringCompleted;
http.DownloadStringAsync(new Uri(GFWLIST_URL));
}
public List<string> ParseResult(string response)
{
byte[] bytes = Convert.FromBase64String(response);
string content = Encoding.ASCII.GetString(bytes);
string[] lines = content.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
List<string> valid_lines = new List<string>(lines.Length);
foreach (string line in lines)
{
if (line.StartsWith("!") || line.StartsWith("["))
continue;
valid_lines.Add(line);
}
return valid_lines;
}
}
}

+ 26
- 2
shadowsocks-csharp/Controller/Logging.cs View File

@@ -17,8 +17,7 @@ namespace Shadowsocks.Controller
string temppath = Path.GetTempPath();
LogFile = Path.Combine(temppath, "shadowsocks.log");
FileStream fs = new FileStream(LogFile, FileMode.Append);
TextWriter tmp = Console.Out;
StreamWriter sw = new StreamWriter(fs);
StreamWriterWithTimestamp sw = new StreamWriterWithTimestamp(fs);
sw.AutoFlush = true;
Console.SetOut(sw);
Console.SetError(sw);
@@ -61,5 +60,30 @@ namespace Shadowsocks.Controller
Console.WriteLine(e);
}
}
}
// Simply extended System.IO.StreamWriter for adding timestamp workaround
public class StreamWriterWithTimestamp : StreamWriter
{
public StreamWriterWithTimestamp(Stream stream) : base(stream)
{
}
private string GetTimestamp()
{
return "[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "] ";
}
public override void WriteLine(string value)
{
base.WriteLine(GetTimestamp() + value);
}
public override void Write(string value)
{
base.Write(GetTimestamp() + value);
}
}
}

+ 4
- 15
shadowsocks-csharp/Controller/PACServer.cs View File

@@ -1,5 +1,6 @@
using Shadowsocks.Model;
using Shadowsocks.Properties;
using Shadowsocks.Util;
using System;
using System.Collections.Generic;
using System.Diagnostics;
@@ -14,7 +15,7 @@ namespace Shadowsocks.Controller
class PACServer
{
private static int PORT = 8093;
private static string PAC_FILE = "pac.txt";
public static string PAC_FILE = "pac.txt";
private static Configuration config;
Socket _listener;
@@ -130,19 +131,7 @@ namespace Shadowsocks.Controller
}
else
{
byte[] pacGZ = Resources.proxy_pac_txt;
byte[] buffer = new byte[1024]; // builtin pac gzip size: maximum 100K
MemoryStream sb = new MemoryStream();
int n;
using (GZipStream input = new GZipStream(new MemoryStream(pacGZ),
CompressionMode.Decompress, false))
{
while((n = input.Read(buffer, 0, buffer.Length)) > 0)
{
sb.Write(buffer, 0, n);
}
return System.Text.Encoding.UTF8.GetString(sb.ToArray());
}
return Utils.UnGzip(Resources.proxy_pac_txt);
}
}
@@ -175,7 +164,7 @@ Connection: Close
", System.Text.Encoding.UTF8.GetBytes(pac).Length) + pac;
byte[] response = System.Text.Encoding.UTF8.GetBytes(text);
conn.BeginSend(response, 0, response.Length, 0, new AsyncCallback(SendCallback), conn);
Util.Util.ReleaseMemory();
Util.Utils.ReleaseMemory();
}
else
{


+ 33
- 2
shadowsocks-csharp/Controller/ShadowsocksController.cs View File

@@ -21,6 +21,7 @@ namespace Shadowsocks.Controller
private PACServer pacServer;
private Configuration _config;
private PolipoRunner polipoRunner;
private GFWListUpdater gfwListUpdater;
private bool stopped = false;
private bool _systemProxyIsDirty = false;
@@ -38,6 +39,10 @@ namespace Shadowsocks.Controller
// when user clicked Edit PAC, and PAC file has already created
public event EventHandler<PathEventArgs> PACFileReadyToOpen;
public event EventHandler UpdatePACFromGFWListCompleted;
public event ErrorEventHandler UpdatePACFromGFWListError;
public event ErrorEventHandler Errored;
public ShadowsocksController()
@@ -151,6 +156,14 @@ namespace Shadowsocks.Controller
return "ss://" + base64;
}
public void UpdatePACFromGFWList()
{
if (gfwListUpdater != null)
{
gfwListUpdater.UpdatePACFromGFWList();
}
}
protected void Reload()
{
// some logic in configuration updated the config when saving, we need to read it again
@@ -165,6 +178,12 @@ namespace Shadowsocks.Controller
pacServer = new PACServer();
pacServer.PACFileChanged += pacServer_PACFileChanged;
}
if (gfwListUpdater == null)
{
gfwListUpdater = new GFWListUpdater();
gfwListUpdater.UpdateCompleted += pacServer_PACUpdateCompleted;
gfwListUpdater.Error += pacServer_PACUpdateError;
}
pacServer.Stop();
@@ -208,7 +227,7 @@ namespace Shadowsocks.Controller
}
UpdateSystemProxy();
Util.Util.ReleaseMemory();
Util.Utils.ReleaseMemory();
}
@@ -242,6 +261,18 @@ namespace Shadowsocks.Controller
UpdateSystemProxy();
}
private void pacServer_PACUpdateCompleted(object sender, EventArgs e)
{
if (UpdatePACFromGFWListCompleted != null)
UpdatePACFromGFWListCompleted(this, e);
}
private void pacServer_PACUpdateError(object sender, ErrorEventArgs e)
{
if (UpdatePACFromGFWListError != null)
UpdatePACFromGFWListError(this, e);
}
private void StartReleasingMemory()
{
_ramThread = new Thread(new ThreadStart(ReleaseMemory));
@@ -253,7 +284,7 @@ namespace Shadowsocks.Controller
{
while (true)
{
Util.Util.ReleaseMemory();
Util.Utils.ReleaseMemory();
Thread.Sleep(30 * 1000);
}
}


+ 2
- 1
shadowsocks-csharp/Controller/UpdateChecker.cs View File

@@ -23,6 +23,7 @@ namespace Shadowsocks.Controller
{
// TODO test failures
WebClient http = new WebClient();
http.Proxy = new WebProxy(IPAddress.Loopback.ToString(), 8123);
http.DownloadStringCompleted += http_DownloadStringCompleted;
http.DownloadStringAsync(new Uri(UpdateURL));
}
@@ -145,7 +146,7 @@ namespace Shadowsocks.Controller
}
catch (Exception ex)
{
Console.Write(ex.ToString());
Console.WriteLine(ex.ToString());
return;
}
}


BIN
shadowsocks-csharp/Data/abp.js.gz View File


+ 5
- 2
shadowsocks-csharp/Data/cn.txt View File

@@ -4,8 +4,8 @@ Mode=代理模式
PAC=PAC 模式
Global=全局模式
Servers=服务器选择
Edit Servers...=编辑Shadowsocks服务器...
Start on Boot=开机启动
Edit Servers...=编辑Shadowsocks服务器...
Start on Boot=开机启动
Share over LAN=在局域网共享代理
Edit PAC File...=编辑 PAC 文件...
Show QRCode...=显示二维码...
@@ -39,6 +39,9 @@ Shadowsocks is here=Shadowsocks 在这里
You can turn on/off Shadowsocks in the context menu=可以在右键菜单中开关 Shadowsocks
Enabled=已启用代理
Disabled=已禁用代理
Update PAC from GFWList=从 GFWList 更新 PAC
Failed to update PAC file =更新 PAC 文件失败
PAC updated=更新 PAC 成功
&Parse=解析(&P)
Shadowsocks URI=Shadowsocks URI
Shadowsocks URI Parse=Shadowsocks URI解析


+ 1
- 1
shadowsocks-csharp/Program.cs View File

@@ -18,7 +18,7 @@ namespace Shadowsocks
[STAThread]
static void Main()
{
Util.Util.ReleaseMemory();
Util.Utils.ReleaseMemory();
using (Mutex mutex = new Mutex(false, "Global\\" + "71981632-A427-497F-AB91-241CD227EC1F"))
{
Application.EnableVisualStyles();


+ 11
- 1
shadowsocks-csharp/Properties/Resources.Designer.cs View File

@@ -61,6 +61,16 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] abp_js {
get {
object obj = ResourceManager.GetObject("abp_js", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized string similar to Shadowsocks=Shadowsocks
///Enable=启用代理
///Mode=代理模式
@@ -68,7 +78,7 @@ namespace Shadowsocks.Properties {
///Global=全局模式
///Servers=服务器选择
///Edit Servers...=编辑服务器...
///Start on Boot=自动启动
///Start on Boot=开机启动
///Share over LAN=在局域网共享代理
///Edit PAC File...=编辑 PAC 文件...
///Show QRCode...=显示二维码...


+ 3
- 0
shadowsocks-csharp/Properties/Resources.resx View File

@@ -118,6 +118,9 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="abp_js" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Data\abp.js.gz;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="cn" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\data\cn.txt;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>


+ 21
- 1
shadowsocks-csharp/Util/Util.cs View File

@@ -1,12 +1,14 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Runtime.InteropServices;
using System.Text;
namespace Shadowsocks.Util
{
public class Util
public class Utils
{
public static void ReleaseMemory()
{
@@ -22,6 +24,24 @@ namespace Shadowsocks.Util
(UIntPtr)0xFFFFFFFF, (UIntPtr)0xFFFFFFFF);
}
public static string UnGzip(byte[] buf)
{
byte[] buffer = new byte[1024];
int n;
using (MemoryStream sb = new MemoryStream())
{
using (GZipStream input = new GZipStream(new MemoryStream(buf),
CompressionMode.Decompress, false))
{
while ((n = input.Read(buffer, 0, buffer.Length)) > 0)
{
sb.Write(buffer, 0, n);
}
}
return System.Text.Encoding.UTF8.GetString(sb.ToArray());
}
}
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetProcessWorkingSetSize(IntPtr process,


+ 30
- 5
shadowsocks-csharp/View/MenuViewController.cs View File

@@ -45,6 +45,8 @@ namespace Shadowsocks.View
controller.ShareOverLANStatusChanged += controller_ShareOverLANStatusChanged;
controller.EnableGlobalChanged += controller_EnableGlobalChanged;
controller.Errored += controller_Errored;
controller.UpdatePACFromGFWListCompleted += controller_UpdatePACFromGFWListCompleted;
controller.UpdatePACFromGFWListError += controller_UpdatePACFromGFWListError;
_notifyIcon = new NotifyIcon();
UpdateTrayIcon();
@@ -138,6 +140,7 @@ namespace Shadowsocks.View
this.AutoStartupItem = CreateMenuItem("Start on Boot", new EventHandler(this.AutoStartupItem_Click)),
this.ShareOverLANItem = CreateMenuItem("Share over LAN", new EventHandler(this.ShareOverLANItem_Click)),
CreateMenuItem("Edit PAC File...", new EventHandler(this.EditPACFileItem_Click)),
CreateMenuItem("Update PAC from GFWList", new EventHandler(this.UpdatePACFromGFWListItem_Click)),
new MenuItem("-"),
CreateMenuItem("Show QRCode...", new EventHandler(this.QRCodeItem_Click)),
CreateMenuItem("Show Logs...", new EventHandler(this.ShowLogItem_Click)),
@@ -176,19 +179,36 @@ namespace Shadowsocks.View
System.Diagnostics.Process.Start("explorer.exe", argument);
}
void ShowBalloonTip(string title, string content, ToolTipIcon icon, int timeout)
{
_notifyIcon.BalloonTipTitle = title;
_notifyIcon.BalloonTipText = content;
_notifyIcon.BalloonTipIcon = icon;
_notifyIcon.ShowBalloonTip(timeout);
}
void controller_UpdatePACFromGFWListError(object sender, System.IO.ErrorEventArgs e)
{
ShowBalloonTip(I18N.GetString("Failed to update PAC file"), e.GetException().Message, ToolTipIcon.Error, 5000);
Logging.LogUsefulException(e.GetException());
}
void controller_UpdatePACFromGFWListCompleted(object sender, EventArgs e)
{
ShowBalloonTip(I18N.GetString("Shadowsocks"), I18N.GetString("PAC updated"), ToolTipIcon.Info, 1000);
}
void updateChecker_NewVersionFound(object sender, EventArgs e)
{
_notifyIcon.BalloonTipTitle = String.Format(I18N.GetString("Shadowsocks {0} Update Found"), updateChecker.LatestVersionNumber);
_notifyIcon.BalloonTipText = I18N.GetString("Click here to download");
_notifyIcon.BalloonTipIcon = ToolTipIcon.Info;
ShowBalloonTip(String.Format(I18N.GetString("Shadowsocks {0} Update Found"), updateChecker.LatestVersionNumber), I18N.GetString("Click here to download"), ToolTipIcon.Info, 5000);
_notifyIcon.BalloonTipClicked += notifyIcon1_BalloonTipClicked;
_notifyIcon.ShowBalloonTip(5000);
_isFirstRun = false;
}
void notifyIcon1_BalloonTipClicked(object sender, EventArgs e)
{
System.Diagnostics.Process.Start(updateChecker.LatestVersionURL);
_notifyIcon.BalloonTipClicked -= notifyIcon1_BalloonTipClicked;
}
@@ -245,7 +265,7 @@ namespace Shadowsocks.View
void configForm_FormClosed(object sender, FormClosedEventArgs e)
{
configForm = null;
Util.Util.ReleaseMemory();
Util.Utils.ReleaseMemory();
ShowFirstTimeBalloon();
}
@@ -312,6 +332,11 @@ namespace Shadowsocks.View
controller.TouchPACFile();
}
private void UpdatePACFromGFWListItem_Click(object sender, EventArgs e)
{
controller.UpdatePACFromGFWList();
}
private void AServerItem_Click(object sender, EventArgs e)
{
MenuItem item = (MenuItem)sender;


+ 8
- 6
shadowsocks-csharp/shadowsocks-csharp.csproj View File

@@ -86,6 +86,7 @@
<Compile Include="3rd\zxing\Version.cs" />
<Compile Include="Controller\AutoStartup.cs" />
<Compile Include="Controller\FileManager.cs" />
<Compile Include="Controller\GFWListUpdater.cs" />
<Compile Include="Controller\I18N.cs" />
<Compile Include="Controller\Logging.cs" />
<Compile Include="Controller\UpdateChecker.cs" />
@@ -101,6 +102,11 @@
<Compile Include="Controller\PACServer.cs" />
<Compile Include="Model\Server.cs" />
<Compile Include="Model\Configuration.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Util\Util.cs" />
<Compile Include="View\ConfigForm.cs">
<SubType>Form</SubType>
@@ -133,14 +139,9 @@
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<EmbeddedResource Include="View\QRCodeForm.resx">
<DependentUpon>QRCodeForm.cs</DependentUpon>
</EmbeddedResource>
@@ -151,6 +152,7 @@
<None Include="app.manifest">
<SubType>Designer</SubType>
</None>
<None Include="Data\abp.js.gz" />
<None Include="Data\libsscrypto.dll.gz" />
<None Include="Data\polipo.exe.gz" />
<None Include="Data\proxy.pac.txt.gz" />


Loading…
Cancel
Save