Compare commits

...
11 Commits
Author SHA1 Message Date
noisyfox efc486c733 Update CHANGES and bump version 2016-12-13 21:08:32 +11:00
noisyfox b7b92a4af9 Very rarely used regex, do not compile 2016-12-13 20:47:39 +11:00
noisyfox a447feece2 Adjust qrcode display 2016-12-13 20:43:51 +11:00
noisyfox 2a0dd88525 Add import URL from clipboard 2016-12-13 02:52:58 +11:00
noisyfox 5650b1d847 Use compiled regex 2016-12-13 02:42:08 +11:00
noisyfox b972cb250b Don't zoom QRCode 2016-12-13 02:31:01 +11:00
noisyfox f363b94fd6 Show ss URL in QRCode form 2016-12-13 02:22:37 +11:00
noisyfox a08993519f Handle request line correctlly
This coudl fix #937
2016-12-12 23:53:15 +11:00
noisyfox 8a68a3515b Check server url before saving it
Don't clear the textbox, focus it instead. We want the user to see the wrong input instead of a blank textbox.
2016-12-10 01:50:28 +11:00
noisyfox 76fbd808e3 Add menu item to copy local pac url 2016-12-10 01:26:40 +11:00
noisyfox 557c797a9a Refine code 2016-12-10 00:59:57 +11:00
14 changed files with 139 additions and 47 deletions
+7
View File
@@ -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);
} }
+5 -2
View File
@@ -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=请添加至少一个服务器
+5 -2
View File
@@ -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=請新增至少一個伺服器
+1 -1
View File
@@ -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;
+2 -3
View File
@@ -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;
+9 -11
View File
@@ -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;
+20 -3
View File
@@ -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
View File
@@ -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;
} }
} }
+17 -2
View File
@@ -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();
} }
} }
} }