Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
efc486c733 | ||
|
|
b7b92a4af9 | ||
|
|
a447feece2 | ||
|
|
2a0dd88525 | ||
|
|
5650b1d847 | ||
|
|
b972cb250b | ||
|
|
f363b94fd6 | ||
|
|
a08993519f | ||
|
|
8a68a3515b | ||
|
|
76fbd808e3 | ||
|
|
557c797a9a |
@@ -1,3 +1,10 @@
|
|||||||
|
3.4.1 (pre-release) 2016-12-13
|
||||||
|
- Fix crash if user input an invaild server address. (#933)
|
||||||
|
- Fix ERR_TOO_MANY_REDIRECTS with http proxy. (#937)
|
||||||
|
- Show SS URL in QRCode form.
|
||||||
|
- Add import URL from clipboard.
|
||||||
|
- Bug fixes and improvements.
|
||||||
|
|
||||||
3.4.0 (pre-release) 2016-12-9
|
3.4.0 (pre-release) 2016-12-9
|
||||||
- Replace Privoxy with built-in http proxy.
|
- Replace Privoxy with built-in http proxy.
|
||||||
- Try fix system proxy settings on windows 10 insider preview.
|
- Try fix system proxy settings on windows 10 insider preview.
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ namespace Shadowsocks.Controller.Service
|
|||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Regex HttpRequestHeaderRegex = new Regex(@"^([A-Z]+?) ([^\s]+) HTTP/1\.\d$");
|
private static readonly Regex HttpRequestHeaderRegex = new Regex(@"^(?<method>[A-Z]+?) (?<path>[^\s]+) (?<tail>HTTP/1\.\d)$", RegexOptions.Compiled);
|
||||||
|
|
||||||
private int _requestLineCount = 0;
|
private int _requestLineCount = 0;
|
||||||
private bool _isConnect = false;
|
private bool _isConnect = false;
|
||||||
@@ -101,31 +101,57 @@ namespace Shadowsocks.Controller.Service
|
|||||||
|
|
||||||
Logging.Debug(line);
|
Logging.Debug(line);
|
||||||
|
|
||||||
if (!line.StartsWith("Proxy-"))
|
|
||||||
{
|
|
||||||
_headers.Enqueue(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_requestLineCount == 0)
|
if (_requestLineCount == 0)
|
||||||
{
|
{
|
||||||
var m = HttpRequestHeaderRegex.Match(line);
|
var m = HttpRequestHeaderRegex.Match(line);
|
||||||
if (m.Success)
|
if (m.Success)
|
||||||
{
|
{
|
||||||
var method = m.Groups[1].Value;
|
var method = m.Groups["method"].Value;
|
||||||
|
var path = m.Groups["path"].Value;
|
||||||
|
|
||||||
if (method == "CONNECT")
|
if (method == "CONNECT")
|
||||||
{
|
{
|
||||||
_isConnect = true;
|
_isConnect = true;
|
||||||
|
|
||||||
if (!ParseHost(m.Groups[2].Value))
|
if (!ParseHost(path))
|
||||||
{
|
{
|
||||||
throw new Exception("Bad http header: " + line);
|
throw new Exception("Bad http header: " + line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var targetUrl = new Uri(path);
|
||||||
|
|
||||||
|
if (!ParseHost(targetUrl.Authority))
|
||||||
|
{
|
||||||
|
throw new Exception("Bad http header: " + line);
|
||||||
|
}
|
||||||
|
|
||||||
|
var newRequestLine = $"{method} {targetUrl.PathAndQuery} {m.Groups["tail"].Value}";
|
||||||
|
_headers.Enqueue(newRequestLine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new FormatException("Not a vaild request line");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Handle Proxy-x Headers
|
||||||
|
|
||||||
|
if (!line.StartsWith("Proxy-"))
|
||||||
|
{
|
||||||
|
_headers.Enqueue(line);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (line.StartsWith("Proxy-Connection: "))
|
||||||
|
{
|
||||||
|
_headers.Enqueue(line.Substring(6));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (line.IsNullOrEmpty())
|
if (line.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ namespace Shadowsocks.Controller
|
|||||||
public const string USER_RULE_FILE = "user-rule.txt";
|
public const string USER_RULE_FILE = "user-rule.txt";
|
||||||
public const string USER_ABP_FILE = "abp.txt";
|
public const string USER_ABP_FILE = "abp.txt";
|
||||||
|
|
||||||
public string PacSecret { get; private set; } = "";
|
private string PacSecret { get; set; } = "";
|
||||||
|
|
||||||
|
public string PacUrl { get; private set; } = "";
|
||||||
|
|
||||||
FileSystemWatcher PACFileWatcher;
|
FileSystemWatcher PACFileWatcher;
|
||||||
FileSystemWatcher UserRuleFileWatcher;
|
FileSystemWatcher UserRuleFileWatcher;
|
||||||
@@ -47,6 +49,14 @@ namespace Shadowsocks.Controller
|
|||||||
{
|
{
|
||||||
PacSecret = "";
|
PacSecret = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PacUrl = $"http://127.0.0.1:{config.localPort}/pac?t={GetTimestamp(DateTime.Now)}{PacSecret}";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static string GetTimestamp(DateTime value)
|
||||||
|
{
|
||||||
|
return value.ToString("yyyyMMddHHmmssfff");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Handle(byte[] firstPacket, int length, Socket socket, object state)
|
public override bool Handle(byte[] firstPacket, int length, Socket socket, object state)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace Shadowsocks.Controller
|
|||||||
public string LatestVersionLocalName;
|
public string LatestVersionLocalName;
|
||||||
public event EventHandler CheckUpdateCompleted;
|
public event EventHandler CheckUpdateCompleted;
|
||||||
|
|
||||||
public const string Version = "3.4.0";
|
public const string Version = "3.4.1";
|
||||||
|
|
||||||
private class CheckUpdateTimer : System.Timers.Timer
|
private class CheckUpdateTimer : System.Timers.Timer
|
||||||
{
|
{
|
||||||
@@ -176,10 +176,10 @@ namespace Shadowsocks.Controller
|
|||||||
|
|
||||||
private void SortByVersions(List<Asset> asserts)
|
private void SortByVersions(List<Asset> asserts)
|
||||||
{
|
{
|
||||||
asserts.Sort(new VersionComparer());
|
asserts.Sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Asset
|
public class Asset : IComparable<Asset>
|
||||||
{
|
{
|
||||||
public bool prerelease;
|
public bool prerelease;
|
||||||
public string name;
|
public string name;
|
||||||
@@ -243,14 +243,10 @@ namespace Shadowsocks.Controller
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
class VersionComparer : IComparer<Asset>
|
public int CompareTo(Asset other)
|
||||||
{
|
|
||||||
// Calls CaseInsensitiveComparer.Compare with the parameters reversed.
|
|
||||||
public int Compare(Asset x, Asset y)
|
|
||||||
{
|
{
|
||||||
return Asset.CompareVersion(x.version, y.version);
|
return CompareVersion(version, other.version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using System.Net.Sockets;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
|
using System.Windows.Forms;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Shadowsocks.Controller.Service;
|
using Shadowsocks.Controller.Service;
|
||||||
using Shadowsocks.Controller.Strategy;
|
using Shadowsocks.Controller.Strategy;
|
||||||
@@ -575,6 +576,11 @@ namespace Shadowsocks.Controller
|
|||||||
File.WriteAllText(PACServer.PAC_FILE, abpContent, Encoding.UTF8);
|
File.WriteAllText(PACServer.PAC_FILE, abpContent, Encoding.UTF8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CopyPacUrl()
|
||||||
|
{
|
||||||
|
Clipboard.SetDataObject(_pacServer.PacUrl);
|
||||||
|
}
|
||||||
|
|
||||||
#region Memory Management
|
#region Memory Management
|
||||||
|
|
||||||
private void StartReleasingMemory()
|
private void StartReleasingMemory()
|
||||||
|
|||||||
@@ -38,8 +38,7 @@ namespace Shadowsocks.Controller
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pacUrl =
|
pacUrl = pacSrv.PacUrl;
|
||||||
$"http://127.0.0.1:{config.localPort}/pac?t={GetTimestamp(DateTime.Now)}{pacSrv.PacSecret}";
|
|
||||||
}
|
}
|
||||||
Sysproxy.SetIEProxy(true, false, "", pacUrl);
|
Sysproxy.SetIEProxy(true, false, "", pacUrl);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,8 +20,10 @@ Edit Local PAC File...=编辑本地 PAC 文件...
|
|||||||
Update Local PAC from GFWList=从 GFWList 更新本地 PAC
|
Update Local PAC from GFWList=从 GFWList 更新本地 PAC
|
||||||
Edit User Rule for GFWList...=编辑 GFWList 的用户规则...
|
Edit User Rule for GFWList...=编辑 GFWList 的用户规则...
|
||||||
Secure Local PAC=保护本地 PAC
|
Secure Local PAC=保护本地 PAC
|
||||||
Show QRCode...=显示二维码...
|
Copy Local PAC URL=复制本地 PAC 网址
|
||||||
|
Share Server Config...=分享服务器配置...
|
||||||
Scan QRCode from Screen...=扫描屏幕上的二维码...
|
Scan QRCode from Screen...=扫描屏幕上的二维码...
|
||||||
|
Import URL from Clipboard...=从剪贴板导入URL...
|
||||||
Availability Statistics=统计可用性
|
Availability Statistics=统计可用性
|
||||||
Show Logs...=显示日志...
|
Show Logs...=显示日志...
|
||||||
Verbose Logging=详细记录日志
|
Verbose Logging=详细记录日志
|
||||||
@@ -82,7 +84,7 @@ Outbound=出站
|
|||||||
|
|
||||||
# QRCode Form
|
# QRCode Form
|
||||||
|
|
||||||
QRCode=二维码
|
QRCode and URL=二维码与 URL
|
||||||
|
|
||||||
# PAC Url Form
|
# PAC Url Form
|
||||||
|
|
||||||
@@ -104,6 +106,7 @@ Reg All=注册全部热键
|
|||||||
|
|
||||||
Shadowsocks Error: {0}=Shadowsocks 错误: {0}
|
Shadowsocks Error: {0}=Shadowsocks 错误: {0}
|
||||||
Port already in use=端口已被占用
|
Port already in use=端口已被占用
|
||||||
|
Invalid server address=非法服务器地址
|
||||||
Illegal port number format=非法端口格式
|
Illegal port number format=非法端口格式
|
||||||
Illegal timeout format=非法超时格式
|
Illegal timeout format=非法超时格式
|
||||||
Please add at least one server=请添加至少一个服务器
|
Please add at least one server=请添加至少一个服务器
|
||||||
|
|||||||
@@ -20,8 +20,10 @@ Edit Local PAC File...=編輯本地 PAC 文件...
|
|||||||
Update Local PAC from GFWList=從 GFWList 更新本地 PAC
|
Update Local PAC from GFWList=從 GFWList 更新本地 PAC
|
||||||
Edit User Rule for GFWList...=編輯 GFWList 的用戶規則...
|
Edit User Rule for GFWList...=編輯 GFWList 的用戶規則...
|
||||||
Secure Local PAC=保護本地 PAC
|
Secure Local PAC=保護本地 PAC
|
||||||
Show QRCode...=顯示 QR 碼...
|
Copy Local PAC URL=複製本地 PAC 網址
|
||||||
|
Share Server Config...=分享伺服器配置...
|
||||||
Scan QRCode from Screen...=掃描螢幕上的 QR 碼...
|
Scan QRCode from Screen...=掃描螢幕上的 QR 碼...
|
||||||
|
Import URL from Clipboard...=從剪貼板導入URL...
|
||||||
Availability Statistics=統計可用性
|
Availability Statistics=統計可用性
|
||||||
Show Logs...=顯示日誌...
|
Show Logs...=顯示日誌...
|
||||||
Verbose Logging=詳細記錄日誌
|
Verbose Logging=詳細記錄日誌
|
||||||
@@ -82,7 +84,7 @@ Outbound=出站
|
|||||||
|
|
||||||
# QRCode Form
|
# QRCode Form
|
||||||
|
|
||||||
QRCode=QR 碼
|
QRCode and URL=QR 碼与 URL
|
||||||
|
|
||||||
# PAC Url Form
|
# PAC Url Form
|
||||||
|
|
||||||
@@ -104,6 +106,7 @@ Reg All=註冊全部捷徑鍵
|
|||||||
|
|
||||||
Shadowsocks Error: {0}=Shadowsocks 錯誤: {0}
|
Shadowsocks Error: {0}=Shadowsocks 錯誤: {0}
|
||||||
Port already in use=連接埠號碼已被占用
|
Port already in use=連接埠號碼已被占用
|
||||||
|
Invalid server address=非法伺服器位址
|
||||||
Illegal port number format=非法連接埠號碼格式
|
Illegal port number format=非法連接埠號碼格式
|
||||||
Illegal timeout format=非法超時格式
|
Illegal timeout format=非法超時格式
|
||||||
Please add at least one server=請新增至少一個伺服器
|
Please add at least one server=請新增至少一個伺服器
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ namespace Shadowsocks.ForwardProxy
|
|||||||
st.innerState.ex = ex;
|
st.innerState.ex = ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Regex HttpRespondHeaderRegex = new Regex(@"^(HTTP/1\.\d) (\d{3}) (.+)$");
|
private static readonly Regex HttpRespondHeaderRegex = new Regex(@"^(HTTP/1\.\d) (\d{3}) (.+)$", RegexOptions.Compiled);
|
||||||
private int _respondLineCount = 0;
|
private int _respondLineCount = 0;
|
||||||
private bool _established = false;
|
private bool _established = false;
|
||||||
|
|
||||||
|
|||||||
@@ -10,10 +10,9 @@ namespace Shadowsocks.Model
|
|||||||
public class Server
|
public class Server
|
||||||
{
|
{
|
||||||
public static readonly Regex
|
public static readonly Regex
|
||||||
UrlFinder = new Regex("^(?i)ss://([A-Za-z0-9+-/=_]+)(#(.+))?$",
|
UrlFinder = new Regex("^(?i)ss://([A-Za-z0-9+-/=_]+)(#(.+))?$", RegexOptions.IgnoreCase),
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
|
||||||
DetailsParser = new Regex("^((?<method>.+?)(?<auth>-auth)??:(?<password>.*)@(?<hostname>.+?)" +
|
DetailsParser = new Regex("^((?<method>.+?)(?<auth>-auth)??:(?<password>.*)@(?<hostname>.+?)" +
|
||||||
":(?<port>\\d+?))$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
":(?<port>\\d+?))$", RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
private const int DefaultServerTimeoutSec = 5;
|
private const int DefaultServerTimeoutSec = 5;
|
||||||
public const int MaxServerTimeoutSec = 20;
|
public const int MaxServerTimeoutSec = 20;
|
||||||
|
|||||||
@@ -80,28 +80,26 @@ namespace Shadowsocks.View
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Server server = new Server();
|
Server server = new Server();
|
||||||
server.server = IPTextBox.Text.Trim();
|
|
||||||
try
|
if (Uri.CheckHostName(server.server = IPTextBox.Text.Trim()) == UriHostNameType.Unknown)
|
||||||
{
|
{
|
||||||
server.server_port = int.Parse(ServerPortTextBox.Text);
|
MessageBox.Show(I18N.GetString("Invalid server address"));
|
||||||
|
IPTextBox.Focus();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
catch (FormatException)
|
if (!int.TryParse(ServerPortTextBox.Text, out server.server_port))
|
||||||
{
|
{
|
||||||
MessageBox.Show(I18N.GetString("Illegal port number format"));
|
MessageBox.Show(I18N.GetString("Illegal port number format"));
|
||||||
ServerPortTextBox.Clear();
|
ServerPortTextBox.Focus();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
server.password = PasswordTextBox.Text;
|
server.password = PasswordTextBox.Text;
|
||||||
server.method = EncryptionSelect.Text;
|
server.method = EncryptionSelect.Text;
|
||||||
server.remarks = RemarksTextBox.Text;
|
server.remarks = RemarksTextBox.Text;
|
||||||
try
|
if (!int.TryParse(TimeoutTextBox.Text, out server.timeout))
|
||||||
{
|
|
||||||
server.timeout = int.Parse(TimeoutTextBox.Text);
|
|
||||||
}
|
|
||||||
catch (FormatException)
|
|
||||||
{
|
{
|
||||||
MessageBox.Show(I18N.GetString("Illegal timeout format"));
|
MessageBox.Show(I18N.GetString("Illegal timeout format"));
|
||||||
TimeoutTextBox.Clear();
|
TimeoutTextBox.Focus();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
server.auth = OneTimeAuth.Checked;
|
server.auth = OneTimeAuth.Checked;
|
||||||
|
|||||||
@@ -261,8 +261,10 @@ namespace Shadowsocks.View
|
|||||||
this.SeperatorItem = new MenuItem("-"),
|
this.SeperatorItem = new MenuItem("-"),
|
||||||
this.ConfigItem = CreateMenuItem("Edit Servers...", new EventHandler(this.Config_Click)),
|
this.ConfigItem = CreateMenuItem("Edit Servers...", new EventHandler(this.Config_Click)),
|
||||||
CreateMenuItem("Statistics Config...", StatisticsConfigItem_Click),
|
CreateMenuItem("Statistics Config...", StatisticsConfigItem_Click),
|
||||||
CreateMenuItem("Show QRCode...", new EventHandler(this.QRCodeItem_Click)),
|
new MenuItem("-"),
|
||||||
CreateMenuItem("Scan QRCode from Screen...", new EventHandler(this.ScanQRCodeItem_Click))
|
CreateMenuItem("Share Server Config...", new EventHandler(this.QRCodeItem_Click)),
|
||||||
|
CreateMenuItem("Scan QRCode from Screen...", new EventHandler(this.ScanQRCodeItem_Click)),
|
||||||
|
CreateMenuItem("Import URL from Clipboard...", new EventHandler(this.ImportURLItem_Click))
|
||||||
}),
|
}),
|
||||||
CreateMenuGroup("PAC ", new MenuItem[] {
|
CreateMenuGroup("PAC ", new MenuItem[] {
|
||||||
this.localPACItem = CreateMenuItem("Local PAC", new EventHandler(this.LocalPACItem_Click)),
|
this.localPACItem = CreateMenuItem("Local PAC", new EventHandler(this.LocalPACItem_Click)),
|
||||||
@@ -271,8 +273,9 @@ namespace Shadowsocks.View
|
|||||||
this.editLocalPACItem = CreateMenuItem("Edit Local PAC File...", new EventHandler(this.EditPACFileItem_Click)),
|
this.editLocalPACItem = CreateMenuItem("Edit Local PAC File...", new EventHandler(this.EditPACFileItem_Click)),
|
||||||
this.updateFromGFWListItem = CreateMenuItem("Update Local PAC from GFWList", new EventHandler(this.UpdatePACFromGFWListItem_Click)),
|
this.updateFromGFWListItem = CreateMenuItem("Update Local PAC from GFWList", new EventHandler(this.UpdatePACFromGFWListItem_Click)),
|
||||||
this.editGFWUserRuleItem = CreateMenuItem("Edit User Rule for GFWList...", new EventHandler(this.EditUserRuleFileForGFWListItem_Click)),
|
this.editGFWUserRuleItem = CreateMenuItem("Edit User Rule for GFWList...", new EventHandler(this.EditUserRuleFileForGFWListItem_Click)),
|
||||||
this.editOnlinePACItem = CreateMenuItem("Edit Online PAC URL...", new EventHandler(this.UpdateOnlinePACURLItem_Click)),
|
|
||||||
this.secureLocalPacUrlToggleItem = CreateMenuItem("Secure Local PAC", new EventHandler(this.SecureLocalPacUrlToggleItem_Click)),
|
this.secureLocalPacUrlToggleItem = CreateMenuItem("Secure Local PAC", new EventHandler(this.SecureLocalPacUrlToggleItem_Click)),
|
||||||
|
CreateMenuItem("Copy Local PAC URL", new EventHandler(this.CopyLocalPacUrlItem_Click)),
|
||||||
|
this.editOnlinePACItem = CreateMenuItem("Edit Online PAC URL...", new EventHandler(this.UpdateOnlinePACURLItem_Click)),
|
||||||
}),
|
}),
|
||||||
this.proxyItem = CreateMenuItem("Forward Proxy...", new EventHandler(this.proxyItem_Click)),
|
this.proxyItem = CreateMenuItem("Forward Proxy...", new EventHandler(this.proxyItem_Click)),
|
||||||
new MenuItem("-"),
|
new MenuItem("-"),
|
||||||
@@ -738,6 +741,15 @@ namespace Shadowsocks.View
|
|||||||
MessageBox.Show(I18N.GetString("No QRCode found. Try to zoom in or move it to the center of the screen."));
|
MessageBox.Show(I18N.GetString("No QRCode found. Try to zoom in or move it to the center of the screen."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ImportURLItem_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var success = controller.AddServerBySSURL(Clipboard.GetText(TextDataFormat.Text));
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
ShowConfigForm();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void splash_FormClosed(object sender, FormClosedEventArgs e)
|
void splash_FormClosed(object sender, FormClosedEventArgs e)
|
||||||
{
|
{
|
||||||
ShowConfigForm();
|
ShowConfigForm();
|
||||||
@@ -805,6 +817,11 @@ namespace Shadowsocks.View
|
|||||||
controller.ToggleSecureLocalPac(!configuration.secureLocalPac);
|
controller.ToggleSecureLocalPac(!configuration.secureLocalPac);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CopyLocalPacUrlItem_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
controller.CopyPacUrl();
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdatePACItemsEnabledStatus()
|
private void UpdatePACItemsEnabledStatus()
|
||||||
{
|
{
|
||||||
if (this.localPACItem.Checked)
|
if (this.localPACItem.Checked)
|
||||||
|
|||||||
+16
-3
@@ -30,6 +30,7 @@
|
|||||||
{
|
{
|
||||||
this.pictureBox1 = new System.Windows.Forms.PictureBox();
|
this.pictureBox1 = new System.Windows.Forms.PictureBox();
|
||||||
this.listBox1 = new System.Windows.Forms.ListBox();
|
this.listBox1 = new System.Windows.Forms.ListBox();
|
||||||
|
this.textBoxURL = new System.Windows.Forms.TextBox();
|
||||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
|
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
@@ -39,7 +40,7 @@
|
|||||||
this.pictureBox1.Margin = new System.Windows.Forms.Padding(0);
|
this.pictureBox1.Margin = new System.Windows.Forms.Padding(0);
|
||||||
this.pictureBox1.Name = "pictureBox1";
|
this.pictureBox1.Name = "pictureBox1";
|
||||||
this.pictureBox1.Size = new System.Drawing.Size(210, 210);
|
this.pictureBox1.Size = new System.Drawing.Size(210, 210);
|
||||||
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
|
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
|
||||||
this.pictureBox1.TabIndex = 1;
|
this.pictureBox1.TabIndex = 1;
|
||||||
this.pictureBox1.TabStop = false;
|
this.pictureBox1.TabStop = false;
|
||||||
//
|
//
|
||||||
@@ -56,6 +57,15 @@
|
|||||||
this.listBox1.ValueMember = "Key";
|
this.listBox1.ValueMember = "Key";
|
||||||
this.listBox1.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged);
|
this.listBox1.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged);
|
||||||
//
|
//
|
||||||
|
// textBoxURL
|
||||||
|
//
|
||||||
|
this.textBoxURL.Location = new System.Drawing.Point(10, 227);
|
||||||
|
this.textBoxURL.Name = "textBoxURL";
|
||||||
|
this.textBoxURL.ReadOnly = true;
|
||||||
|
this.textBoxURL.Size = new System.Drawing.Size(441, 21);
|
||||||
|
this.textBoxURL.TabIndex = 3;
|
||||||
|
this.textBoxURL.Click += new System.EventHandler(this.textBoxURL_Click);
|
||||||
|
//
|
||||||
// QRCodeForm
|
// QRCodeForm
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
||||||
@@ -63,7 +73,8 @@
|
|||||||
this.AutoSize = true;
|
this.AutoSize = true;
|
||||||
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||||
this.BackColor = System.Drawing.Color.White;
|
this.BackColor = System.Drawing.Color.White;
|
||||||
this.ClientSize = new System.Drawing.Size(457, 228);
|
this.ClientSize = new System.Drawing.Size(457, 257);
|
||||||
|
this.Controls.Add(this.textBoxURL);
|
||||||
this.Controls.Add(this.listBox1);
|
this.Controls.Add(this.listBox1);
|
||||||
this.Controls.Add(this.pictureBox1);
|
this.Controls.Add(this.pictureBox1);
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||||
@@ -72,10 +83,11 @@
|
|||||||
this.Name = "QRCodeForm";
|
this.Name = "QRCodeForm";
|
||||||
this.Padding = new System.Windows.Forms.Padding(10);
|
this.Padding = new System.Windows.Forms.Padding(10);
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||||
this.Text = "QRCode";
|
this.Text = "QRCode and URL";
|
||||||
this.Load += new System.EventHandler(this.QRCodeForm_Load);
|
this.Load += new System.EventHandler(this.QRCodeForm_Load);
|
||||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
|
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,5 +95,6 @@
|
|||||||
|
|
||||||
private System.Windows.Forms.PictureBox pictureBox1;
|
private System.Windows.Forms.PictureBox pictureBox1;
|
||||||
private System.Windows.Forms.ListBox listBox1;
|
private System.Windows.Forms.ListBox listBox1;
|
||||||
|
private System.Windows.Forms.TextBox textBoxURL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -24,7 +24,7 @@ namespace Shadowsocks.View
|
|||||||
this.code = code;
|
this.code = code;
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
this.Icon = Icon.FromHandle(Resources.ssw128.GetHicon());
|
this.Icon = Icon.FromHandle(Resources.ssw128.GetHicon());
|
||||||
this.Text = I18N.GetString("QRCode");
|
this.Text = I18N.GetString("QRCode and URL");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenQR(string ssconfig)
|
private void GenQR(string ssconfig)
|
||||||
@@ -33,6 +33,14 @@ namespace Shadowsocks.View
|
|||||||
QRCode code = ZXing.QrCode.Internal.Encoder.encode(qrText, ErrorCorrectionLevel.M);
|
QRCode code = ZXing.QrCode.Internal.Encoder.encode(qrText, ErrorCorrectionLevel.M);
|
||||||
ByteMatrix m = code.Matrix;
|
ByteMatrix m = code.Matrix;
|
||||||
int blockSize = Math.Max(pictureBox1.Height/m.Height, 1);
|
int blockSize = Math.Max(pictureBox1.Height/m.Height, 1);
|
||||||
|
|
||||||
|
var qrWidth = m.Width*blockSize;
|
||||||
|
var qrHeight = m.Height*blockSize;
|
||||||
|
var dWidth = pictureBox1.Width - qrWidth;
|
||||||
|
var dHeight = pictureBox1.Height - qrHeight;
|
||||||
|
var maxD = Math.Max(dWidth, dHeight);
|
||||||
|
pictureBox1.SizeMode = maxD >= 7*blockSize ? PictureBoxSizeMode.Zoom : PictureBoxSizeMode.CenterImage;
|
||||||
|
|
||||||
Bitmap drawArea = new Bitmap((m.Width*blockSize), (m.Height*blockSize));
|
Bitmap drawArea = new Bitmap((m.Width*blockSize), (m.Height*blockSize));
|
||||||
using (Graphics g = Graphics.FromImage(drawArea))
|
using (Graphics g = Graphics.FromImage(drawArea))
|
||||||
{
|
{
|
||||||
@@ -69,7 +77,14 @@ namespace Shadowsocks.View
|
|||||||
|
|
||||||
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
|
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
GenQR((sender as ListBox)?.SelectedValue.ToString());
|
var url = (sender as ListBox)?.SelectedValue.ToString();
|
||||||
|
GenQR(url);
|
||||||
|
textBoxURL.Text = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void textBoxURL_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
textBoxURL.SelectAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user