From 3932c4a3935116c271e496136523b8953e85a058 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 00:11:19 +0800 Subject: [PATCH 01/19] add lock in encryption; #32 --- shadowsocks-csharp/Controller/Local.cs | 5 +-- shadowsocks-csharp/Encrypt/PolarSSLEncryptor.cs | 55 ++++++++++++++----------- 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/shadowsocks-csharp/Controller/Local.cs b/shadowsocks-csharp/Controller/Local.cs index db6c71b8..b5db6c0c 100755 --- a/shadowsocks-csharp/Controller/Local.cs +++ b/shadowsocks-csharp/Controller/Local.cs @@ -189,8 +189,8 @@ namespace Shadowsocks.Controller // Complete the connection. remote.EndConnect(ar); - Console.WriteLine("Socket connected to {0}", - remote.RemoteEndPoint.ToString()); + //Console.WriteLine("Socket connected to {0}", + // remote.RemoteEndPoint.ToString()); handshakeReceive(); } @@ -348,7 +348,6 @@ namespace Shadowsocks.Controller } else { - Console.WriteLine("bytesRead: " + bytesRead.ToString()); this.Close(); } } diff --git a/shadowsocks-csharp/Encrypt/PolarSSLEncryptor.cs b/shadowsocks-csharp/Encrypt/PolarSSLEncryptor.cs index d2270196..fdd7ce19 100755 --- a/shadowsocks-csharp/Encrypt/PolarSSLEncryptor.cs +++ b/shadowsocks-csharp/Encrypt/PolarSSLEncryptor.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; +using System.Threading; namespace Shadowsocks.Encrypt { @@ -166,20 +167,24 @@ namespace Shadowsocks.Encrypt randBytes(outbuf, ivLen); InitCipher(ref _encryptCtx, outbuf, true); outlength = length + ivLen; - switch (_cipher) + lock (tempbuf) { - case CIPHER_AES: - PolarSSL.aes_crypt_cfb128(_encryptCtx, PolarSSL.AES_ENCRYPT, length, ref _encryptIVOffset, _encryptIV, buf, tempbuf); - break; - case CIPHER_BF: - PolarSSL.blowfish_crypt_cfb64(_encryptCtx, PolarSSL.BLOWFISH_ENCRYPT, length, ref _encryptIVOffset, _encryptIV, buf, tempbuf); - break; - case CIPHER_RC4: - PolarSSL.arc4_crypt(_encryptCtx, length, buf, tempbuf); - break; + // C# could be multi-threaded + switch (_cipher) + { + case CIPHER_AES: + PolarSSL.aes_crypt_cfb128(_encryptCtx, PolarSSL.AES_ENCRYPT, length, ref _encryptIVOffset, _encryptIV, buf, tempbuf); + break; + case CIPHER_BF: + PolarSSL.blowfish_crypt_cfb64(_encryptCtx, PolarSSL.BLOWFISH_ENCRYPT, length, ref _encryptIVOffset, _encryptIV, buf, tempbuf); + break; + case CIPHER_RC4: + PolarSSL.arc4_crypt(_encryptCtx, length, buf, tempbuf); + break; + } + outlength = length + ivLen; + Buffer.BlockCopy(tempbuf, 0, outbuf, ivLen, outlength); } - outlength = length + ivLen; - Buffer.BlockCopy(tempbuf, 0, outbuf, ivLen, outlength); } else { @@ -205,18 +210,22 @@ namespace Shadowsocks.Encrypt { InitCipher(ref _decryptCtx, buf, false); outlength = length - ivLen; - Buffer.BlockCopy(buf, ivLen, tempbuf, 0, length - ivLen); - switch (_cipher) + lock (tempbuf) { - case CIPHER_AES: - PolarSSL.aes_crypt_cfb128(_decryptCtx, PolarSSL.AES_DECRYPT, length - ivLen, ref _decryptIVOffset, _decryptIV, tempbuf, outbuf); - break; - case CIPHER_BF: - PolarSSL.blowfish_crypt_cfb64(_decryptCtx, PolarSSL.BLOWFISH_DECRYPT, length - ivLen, ref _decryptIVOffset, _decryptIV, tempbuf, outbuf); - break; - case CIPHER_RC4: - PolarSSL.arc4_crypt(_decryptCtx, length - ivLen, tempbuf, outbuf); - break; + // C# could be multi-threaded + Buffer.BlockCopy(buf, ivLen, tempbuf, 0, length - ivLen); + switch (_cipher) + { + case CIPHER_AES: + PolarSSL.aes_crypt_cfb128(_decryptCtx, PolarSSL.AES_DECRYPT, length - ivLen, ref _decryptIVOffset, _decryptIV, tempbuf, outbuf); + break; + case CIPHER_BF: + PolarSSL.blowfish_crypt_cfb64(_decryptCtx, PolarSSL.BLOWFISH_DECRYPT, length - ivLen, ref _decryptIVOffset, _decryptIV, tempbuf, outbuf); + break; + case CIPHER_RC4: + PolarSSL.arc4_crypt(_decryptCtx, length - ivLen, tempbuf, outbuf); + break; + } } } else From 97eac82c897e1ec172bea1bc6155e10739fae75e Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 01:34:22 +0800 Subject: [PATCH 02/19] remove AnyCPU configuration --- shadowsocks-csharp/shadowsocks-csharp.csproj | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index 22422445..45afa2e7 100755 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -37,26 +37,6 @@ false true - - true - full - false - bin\Debug\ - TRACE;DEBUG;SIMPLE_JSON_NO_LINQ_EXPRESSION - prompt - 4 - false - true - - - pdbonly - true - bin\Release\ - TRACE;SIMPLE_JSON_NO_LINQ_EXPRESSION - prompt - 4 - false - true bin\x86\Debug\ From 8327c0f289d3ade207897b1500331ac90c4213a7 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 01:34:50 +0800 Subject: [PATCH 03/19] remove AnyCPU configuration --- shadowsocks-csharp.sln | 6 ------ 1 file changed, 6 deletions(-) diff --git a/shadowsocks-csharp.sln b/shadowsocks-csharp.sln index c98f328b..46bde1a8 100755 --- a/shadowsocks-csharp.sln +++ b/shadowsocks-csharp.sln @@ -5,19 +5,13 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "shadowsocks-csharp", "shado EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|Any CPU.Build.0 = Debug|Any CPU {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|x86.ActiveCfg = Debug|x86 {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|x86.Build.0 = Debug|x86 {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|x86.Deploy.0 = Debug|x86 - {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Release|Any CPU.Build.0 = Release|Any CPU {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Release|x86.ActiveCfg = Release|x86 {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Release|x86.Build.0 = Release|x86 EndGlobalSection From 2ce10ace53ac7c10f6e024534111b28a5046017f Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 01:38:00 +0800 Subject: [PATCH 04/19] bump --- CHANGES | 4 ++++ shadowsocks-csharp/Properties/AssemblyInfo.cs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 442d5de7..b7838460 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +2.0.4 +- Try to fix data corruption +- Remove all configuration except x86 + 2.0.3 - Support QRCode generation - Fix compatibility issues with some Chrome version diff --git a/shadowsocks-csharp/Properties/AssemblyInfo.cs b/shadowsocks-csharp/Properties/AssemblyInfo.cs index e6316b3a..02c3eba7 100755 --- a/shadowsocks-csharp/Properties/AssemblyInfo.cs +++ b/shadowsocks-csharp/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值, // 方法是按如下所示使用“*”: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.0.3")] +[assembly: AssemblyVersion("2.0.4")] // [assembly: AssemblyFileVersion("2.0.0")] From ac21a0960fea4082d8726c576895034139adfcee Mon Sep 17 00:00:00 2001 From: wzxjohn Date: Sun, 9 Nov 2014 01:50:47 +0800 Subject: [PATCH 05/19] add config lock Add a lock on config form to avoid accidental changes --- shadowsocks-csharp/Model/Configuration.cs | 22 ++-- shadowsocks-csharp/View/ConfigForm.Designer.cs | 38 +++++- shadowsocks-csharp/View/ConfigForm.cs | 164 +++++++++++++++---------- 3 files changed, 147 insertions(+), 77 deletions(-) diff --git a/shadowsocks-csharp/Model/Configuration.cs b/shadowsocks-csharp/Model/Configuration.cs index d5acbe6d..78eb3c29 100755 --- a/shadowsocks-csharp/Model/Configuration.cs +++ b/shadowsocks-csharp/Model/Configuration.cs @@ -16,6 +16,8 @@ namespace Shadowsocks.Model public int index; public bool enabled; public bool isDefault; + public bool lockStatus; + public bool enableLog; private static string CONFIG_FILE = "gui-config.json"; @@ -33,11 +35,11 @@ namespace Shadowsocks.Model public static void CheckServer(Server server) { - checkPort(server.local_port); - checkPort(server.server_port); - checkPassword(server.password); - checkServer(server.server); - checkRemark(server.remarks); + CheckPort(server.local_port); + CheckPort(server.server_port); + CheckPassword(server.password); + CheckServer(server.server); + CheckRemark(server.remarks); } public static Configuration Load() @@ -106,7 +108,7 @@ namespace Shadowsocks.Model }; } - private static void assert(bool condition) + private static void Assert(bool condition) { if (!condition) { @@ -114,7 +116,7 @@ namespace Shadowsocks.Model } } - private static void checkPort(int port) + private static void CheckPort(int port) { if (port <= 0 || port > 65535) { @@ -122,7 +124,7 @@ namespace Shadowsocks.Model } } - private static void checkPassword(string password) + private static void CheckPassword(string password) { if (string.IsNullOrEmpty(password)) { @@ -130,7 +132,7 @@ namespace Shadowsocks.Model } } - private static void checkServer(string server) + private static void CheckServer(string server) { if (string.IsNullOrEmpty(server)) { @@ -138,7 +140,7 @@ namespace Shadowsocks.Model } } - private static void checkRemark(string remark) + private static void CheckRemark(string remark) { //remark is optional } diff --git a/shadowsocks-csharp/View/ConfigForm.Designer.cs b/shadowsocks-csharp/View/ConfigForm.Designer.cs index 6d6f8881..3ad2e1f2 100755 --- a/shadowsocks-csharp/View/ConfigForm.Designer.cs +++ b/shadowsocks-csharp/View/ConfigForm.Designer.cs @@ -55,6 +55,7 @@ this.ConfigItem = new System.Windows.Forms.MenuItem(); this.menuItem4 = new System.Windows.Forms.MenuItem(); this.editPACFileItem = new System.Windows.Forms.MenuItem(); + this.QRCodeItem = new System.Windows.Forms.MenuItem(); this.aboutItem = new System.Windows.Forms.MenuItem(); this.menuItem3 = new System.Windows.Forms.MenuItem(); this.quitItem = new System.Windows.Forms.MenuItem(); @@ -63,11 +64,13 @@ this.AddButton = new System.Windows.Forms.Button(); this.ServerGroupBox = new System.Windows.Forms.GroupBox(); this.ServersListBox = new System.Windows.Forms.ListBox(); - this.QRCodeItem = new System.Windows.Forms.MenuItem(); + this.LockButton = new System.Windows.Forms.Button(); + this.panel4 = new System.Windows.Forms.Panel(); this.tableLayoutPanel1.SuspendLayout(); this.panel1.SuspendLayout(); this.panel3.SuspendLayout(); this.ServerGroupBox.SuspendLayout(); + this.panel4.SuspendLayout(); this.SuspendLayout(); // // tableLayoutPanel1 @@ -329,6 +332,12 @@ this.editPACFileItem.Text = "Edit &PAC File..."; this.editPACFileItem.Click += new System.EventHandler(this.EditPACFileItem_Click); // + // QRCodeItem + // + this.QRCodeItem.Index = 4; + this.QRCodeItem.Text = "Show &QRCode..."; + this.QRCodeItem.Click += new System.EventHandler(this.QRCodeItem_Click); + // // aboutItem // this.aboutItem.Index = 5; @@ -396,11 +405,25 @@ this.ServersListBox.TabIndex = 5; this.ServersListBox.SelectedIndexChanged += new System.EventHandler(this.ServersListBox_SelectedIndexChanged); // - // QRCodeItem + // LockButton // - this.QRCodeItem.Index = 4; - this.QRCodeItem.Text = "Show &QRCode..."; - this.QRCodeItem.Click += new System.EventHandler(this.QRCodeItem_Click); + this.LockButton.Location = new System.Drawing.Point(4, 4); + this.LockButton.Name = "LockButton"; + this.LockButton.Size = new System.Drawing.Size(89, 23); + this.LockButton.TabIndex = 6; + this.LockButton.Text = "&Lock"; + this.LockButton.UseVisualStyleBackColor = true; + this.LockButton.Click += new System.EventHandler(this.LockButton_Click); + // + // panel4 + // + this.panel4.AutoSize = true; + this.panel4.Controls.Add(this.LockButton); + this.panel4.Location = new System.Drawing.Point(12, 251); + this.panel4.Margin = new System.Windows.Forms.Padding(0); + this.panel4.Name = "panel4"; + this.panel4.Size = new System.Drawing.Size(192, 30); + this.panel4.TabIndex = 7; // // ConfigForm // @@ -409,6 +432,7 @@ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.AutoSize = true; this.ClientSize = new System.Drawing.Size(489, 286); + this.Controls.Add(this.panel4); this.Controls.Add(this.ServersListBox); this.Controls.Add(this.ServerGroupBox); this.Controls.Add(this.panel1); @@ -420,6 +444,7 @@ this.Name = "ConfigForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Shadowsocks"; + this.TopMost = true; this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ConfigForm_FormClosed); this.Load += new System.EventHandler(this.ConfigForm_Load); this.Shown += new System.EventHandler(this.ConfigForm_Shown); @@ -429,6 +454,7 @@ this.panel3.ResumeLayout(false); this.ServerGroupBox.ResumeLayout(false); this.ServerGroupBox.PerformLayout(); + this.panel4.ResumeLayout(false); this.ResumeLayout(false); this.PerformLayout(); @@ -470,6 +496,8 @@ private System.Windows.Forms.TextBox RemarksTextBox; private System.Windows.Forms.Label label6; private System.Windows.Forms.MenuItem QRCodeItem; + private System.Windows.Forms.Button LockButton; + private System.Windows.Forms.Panel panel4; } } diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index 174d10fd..17c5c0a0 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Drawing; +using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; using System.Diagnostics; @@ -15,9 +16,10 @@ namespace Shadowsocks.View private ShadowsocksController controller; // this is a copy of configuration that we are working on - private Configuration modifiedConfiguration; - private int oldSelectedIndex = -1; - private bool isFirstRun; + private Configuration _modifiedConfiguration; + private int _oldSelectedIndex = -1; + private bool _isFirstRun; + private bool _lockStatus; public ConfigForm(ShadowsocksController controller) { @@ -29,12 +31,12 @@ namespace Shadowsocks.View controller.ConfigChanged += controller_ConfigChanged; controller.PACFileReadyToOpen += controller_PACFileReadyToOpen; - loadCurrentConfiguration(); + LoadCurrentConfiguration(); } private void controller_ConfigChanged(object sender, EventArgs e) { - loadCurrentConfiguration(); + LoadCurrentConfiguration(); } private void controller_EnableStatusChanged(object sender, EventArgs e) @@ -50,18 +52,31 @@ namespace Shadowsocks.View } - private void showWindow() + private void ShowWindow() { this.Opacity = 1; this.Show(); IPTextBox.Focus(); + if (_lockStatus) + { + IPTextBox.Enabled = false; + ServerPortTextBox.Enabled = false; + PasswordTextBox.Enabled = false; + EncryptionSelect.Enabled = false; + ProxyPortTextBox.Enabled = false; + RemarksTextBox.Enabled = false; + AddButton.Enabled = false; + DeleteButton.Enabled = false; + _lockStatus = true; + LockButton.Text = "&Unlock Settings"; + } } - private bool saveOldSelectedServer() + private bool SaveOldSelectedServer() { try { - if (oldSelectedIndex == -1 || oldSelectedIndex >= modifiedConfiguration.configs.Count) + if (_oldSelectedIndex == -1 || _oldSelectedIndex >= _modifiedConfiguration.configs.Count) { return true; } @@ -75,7 +90,7 @@ namespace Shadowsocks.View remarks = RemarksTextBox.Text }; Configuration.CheckServer(server); - modifiedConfiguration.configs[oldSelectedIndex] = server; + _modifiedConfiguration.configs[_oldSelectedIndex] = server; return true; } catch (FormatException) @@ -89,17 +104,17 @@ namespace Shadowsocks.View return false; } - private void loadSelectedServer() + private void LoadSelectedServer() { - if (ServersListBox.SelectedIndex >= 0 && ServersListBox.SelectedIndex < modifiedConfiguration.configs.Count) + if (ServersListBox.SelectedIndex >= 0 && ServersListBox.SelectedIndex < _modifiedConfiguration.configs.Count) { - Server server = modifiedConfiguration.configs[ServersListBox.SelectedIndex]; + Server server = _modifiedConfiguration.configs[ServersListBox.SelectedIndex]; IPTextBox.Text = server.server; ServerPortTextBox.Text = server.server_port.ToString(); PasswordTextBox.Text = server.password; ProxyPortTextBox.Text = server.local_port.ToString(); - EncryptionSelect.Text = server.method == null ? "aes-256-cfb" : server.method; + EncryptionSelect.Text = server.method ?? "aes-256-cfb"; RemarksTextBox.Text = server.remarks; ServerGroupBox.Visible = true; IPTextBox.Focus(); @@ -110,28 +125,29 @@ namespace Shadowsocks.View } } - private void loadConfiguration(Configuration configuration) + private void LoadConfiguration(Configuration configuration) { ServersListBox.Items.Clear(); - foreach (Server server in modifiedConfiguration.configs) + foreach (Server server in _modifiedConfiguration.configs) { ServersListBox.Items.Add(string.IsNullOrEmpty(server.server) ? "New server" : string.IsNullOrEmpty(server.remarks)? server.server + ":" + server.server_port : server.server + ":" + server.server_port + " (" + server.remarks + ")"); } } - private void loadCurrentConfiguration() + private void LoadCurrentConfiguration() { - modifiedConfiguration = controller.GetConfiguration(); - loadConfiguration(modifiedConfiguration); - oldSelectedIndex = modifiedConfiguration.index; - ServersListBox.SelectedIndex = modifiedConfiguration.index; - loadSelectedServer(); - - updateServersMenu(); - enableItem.Checked = modifiedConfiguration.enabled; + _modifiedConfiguration = controller.GetConfiguration(); + LoadConfiguration(_modifiedConfiguration); + _oldSelectedIndex = _modifiedConfiguration.index; + _lockStatus = _modifiedConfiguration.lockStatus; + ServersListBox.SelectedIndex = _modifiedConfiguration.index; + LoadSelectedServer(); + + UpdateServersMenu(); + enableItem.Checked = _modifiedConfiguration.enabled; } - private void updateServersMenu() + private void UpdateServersMenu() { var items = ServersItem.MenuItems; @@ -157,71 +173,68 @@ namespace Shadowsocks.View private void ConfigForm_Load(object sender, EventArgs e) { - if (!controller.GetConfiguration().isDefault) + if (controller == null || controller.GetConfiguration().isDefault) { - this.Opacity = 0; - BeginInvoke(new MethodInvoker(delegate - { - this.Hide(); - })); + _isFirstRun = true; } else { - isFirstRun = true; + this.Opacity = 0; + BeginInvoke(new MethodInvoker(delegate { this.Hide(); })); } } private void ServersListBox_SelectedIndexChanged(object sender, EventArgs e) { - if (oldSelectedIndex == ServersListBox.SelectedIndex) + if (_oldSelectedIndex == ServersListBox.SelectedIndex) { // we are moving back to oldSelectedIndex or doing a force move return; } - if (!saveOldSelectedServer()) + if (!SaveOldSelectedServer()) { // why this won't cause stack overflow? - ServersListBox.SelectedIndex = oldSelectedIndex; + ServersListBox.SelectedIndex = _oldSelectedIndex; return; } - loadSelectedServer(); - oldSelectedIndex = ServersListBox.SelectedIndex; + LoadSelectedServer(); + _oldSelectedIndex = ServersListBox.SelectedIndex; } private void AddButton_Click(object sender, EventArgs e) { - if (!saveOldSelectedServer()) + if (!SaveOldSelectedServer()) { return; } Server server = Configuration.GetDefaultServer(); - modifiedConfiguration.configs.Add(server); - loadConfiguration(modifiedConfiguration); - ServersListBox.SelectedIndex = modifiedConfiguration.configs.Count - 1; - oldSelectedIndex = ServersListBox.SelectedIndex; + _modifiedConfiguration.configs.Add(server); + LoadConfiguration(_modifiedConfiguration); + ServersListBox.SelectedIndex = _modifiedConfiguration.configs.Count - 1; + _oldSelectedIndex = ServersListBox.SelectedIndex; } private void DeleteButton_Click(object sender, EventArgs e) { - oldSelectedIndex = ServersListBox.SelectedIndex; - if (oldSelectedIndex >= 0 && oldSelectedIndex < modifiedConfiguration.configs.Count) + _oldSelectedIndex = ServersListBox.SelectedIndex; + if (_oldSelectedIndex >= 0 && _oldSelectedIndex < _modifiedConfiguration.configs.Count) { - modifiedConfiguration.configs.RemoveAt(oldSelectedIndex); + _modifiedConfiguration.configs.RemoveAt(_oldSelectedIndex); } - if (oldSelectedIndex >= modifiedConfiguration.configs.Count) + if (_oldSelectedIndex >= _modifiedConfiguration.configs.Count) { // can be -1 - oldSelectedIndex = modifiedConfiguration.configs.Count - 1; + _oldSelectedIndex = _modifiedConfiguration.configs.Count - 1; } - ServersListBox.SelectedIndex = oldSelectedIndex; - loadConfiguration(modifiedConfiguration); - ServersListBox.SelectedIndex = oldSelectedIndex; - loadSelectedServer(); + ServersListBox.SelectedIndex = _oldSelectedIndex; + LoadConfiguration(_modifiedConfiguration); + ServersListBox.SelectedIndex = _oldSelectedIndex; + LoadSelectedServer(); } private void Config_Click(object sender, EventArgs e) { - showWindow(); + ShowWindow(); } private void Quit_Click(object sender, EventArgs e) @@ -229,38 +242,39 @@ namespace Shadowsocks.View this.Close(); } - private void showFirstTimeBalloon() + private void ShowFirstTimeBalloon() { - if (isFirstRun) + if (_isFirstRun) { notifyIcon1.BalloonTipTitle = "Shadowsocks is here"; notifyIcon1.BalloonTipText = "You can turn on/off Shadowsocks in the context menu"; notifyIcon1.ShowBalloonTip(0); - isFirstRun = false; + _isFirstRun = false; } } private void OKButton_Click(object sender, EventArgs e) { - if (!saveOldSelectedServer()) + if (!SaveOldSelectedServer()) { return; } - if (modifiedConfiguration.configs.Count == 0) + if (_modifiedConfiguration.configs.Count == 0) { MessageBox.Show("Please add at least one server"); return; } - controller.SaveConfig(modifiedConfiguration); + _modifiedConfiguration.lockStatus = _lockStatus; + controller.SaveConfig(_modifiedConfiguration); this.Hide(); - showFirstTimeBalloon(); + ShowFirstTimeBalloon(); } private void CancelButton_Click(object sender, EventArgs e) { this.Hide(); - loadCurrentConfiguration(); - showFirstTimeBalloon(); + LoadCurrentConfiguration(); + ShowFirstTimeBalloon(); } private void ConfigForm_FormClosed(object sender, FormClosedEventArgs e) @@ -275,7 +289,7 @@ namespace Shadowsocks.View private void notifyIcon1_DoubleClick(object sender, EventArgs e) { - showWindow(); + ShowWindow(); } @@ -307,5 +321,31 @@ namespace Shadowsocks.View { new QRCodeForm(controller.GetQRCodeForCurrentServer()).Show(); } + + private void ChangeLockStatus(bool lockStatus) + { + IPTextBox.Enabled = lockStatus; + ServerPortTextBox.Enabled = lockStatus; + PasswordTextBox.Enabled = lockStatus; + EncryptionSelect.Enabled = lockStatus; + ProxyPortTextBox.Enabled = lockStatus; + RemarksTextBox.Enabled = lockStatus; + AddButton.Enabled = lockStatus; + DeleteButton.Enabled = lockStatus; + _lockStatus = !lockStatus; + if (lockStatus) + { + LockButton.Text = "&Lock"; + } + else + { + LockButton.Text = "&Unlock"; + } + } + + private void LockButton_Click(object sender, EventArgs e) + { + ChangeLockStatus(_lockStatus); + } } } From 24614ba2a7c0c46092e59ad6bb1d15c5a398949e Mon Sep 17 00:00:00 2001 From: wzxjohn Date: Sun, 9 Nov 2014 02:04:11 +0800 Subject: [PATCH 06/19] add cancel button for config Now can use esc key to cancel, and don't change focus after change server from list --- shadowsocks-csharp/View/ConfigForm.Designer.cs | 11 ++++++----- shadowsocks-csharp/View/ConfigForm.cs | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/shadowsocks-csharp/View/ConfigForm.Designer.cs b/shadowsocks-csharp/View/ConfigForm.Designer.cs index 3ad2e1f2..a661b65a 100755 --- a/shadowsocks-csharp/View/ConfigForm.Designer.cs +++ b/shadowsocks-csharp/View/ConfigForm.Designer.cs @@ -256,7 +256,7 @@ this.OKButton.Location = new System.Drawing.Point(4, 4); this.OKButton.Name = "OKButton"; this.OKButton.Size = new System.Drawing.Size(75, 23); - this.OKButton.TabIndex = 8; + this.OKButton.TabIndex = 6; this.OKButton.Text = "OK"; this.OKButton.UseVisualStyleBackColor = true; this.OKButton.Click += new System.EventHandler(this.OKButton_Click); @@ -267,7 +267,7 @@ this.MyCancelButton.Location = new System.Drawing.Point(86, 4); this.MyCancelButton.Name = "MyCancelButton"; this.MyCancelButton.Size = new System.Drawing.Size(75, 23); - this.MyCancelButton.TabIndex = 9; + this.MyCancelButton.TabIndex = 7; this.MyCancelButton.Text = "Cancel"; this.MyCancelButton.UseVisualStyleBackColor = true; this.MyCancelButton.Click += new System.EventHandler(this.CancelButton_Click); @@ -371,7 +371,7 @@ this.DeleteButton.Location = new System.Drawing.Point(100, 4); this.DeleteButton.Name = "DeleteButton"; this.DeleteButton.Size = new System.Drawing.Size(89, 23); - this.DeleteButton.TabIndex = 7; + this.DeleteButton.TabIndex = 9; this.DeleteButton.Text = "&Delete"; this.DeleteButton.UseVisualStyleBackColor = true; this.DeleteButton.Click += new System.EventHandler(this.DeleteButton_Click); @@ -381,7 +381,7 @@ this.AddButton.Location = new System.Drawing.Point(4, 4); this.AddButton.Name = "AddButton"; this.AddButton.Size = new System.Drawing.Size(89, 23); - this.AddButton.TabIndex = 6; + this.AddButton.TabIndex = 8; this.AddButton.Text = "&Add"; this.AddButton.UseVisualStyleBackColor = true; this.AddButton.Click += new System.EventHandler(this.AddButton_Click); @@ -410,7 +410,7 @@ this.LockButton.Location = new System.Drawing.Point(4, 4); this.LockButton.Name = "LockButton"; this.LockButton.Size = new System.Drawing.Size(89, 23); - this.LockButton.TabIndex = 6; + this.LockButton.TabIndex = 10; this.LockButton.Text = "&Lock"; this.LockButton.UseVisualStyleBackColor = true; this.LockButton.Click += new System.EventHandler(this.LockButton_Click); @@ -431,6 +431,7 @@ this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.AutoSize = true; + this.CancelButton = this.MyCancelButton; this.ClientSize = new System.Drawing.Size(489, 286); this.Controls.Add(this.panel4); this.Controls.Add(this.ServersListBox); diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index 17c5c0a0..68cb861c 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -117,7 +117,7 @@ namespace Shadowsocks.View EncryptionSelect.Text = server.method ?? "aes-256-cfb"; RemarksTextBox.Text = server.remarks; ServerGroupBox.Visible = true; - IPTextBox.Focus(); + //IPTextBox.Focus(); } else { From b5eac341b32a938e7f17b830ceedca9ba1577956 Mon Sep 17 00:00:00 2001 From: wzxjohn Date: Sun, 9 Nov 2014 02:10:43 +0800 Subject: [PATCH 07/19] revert --- shadowsocks-csharp/Model/Configuration.cs | 22 ++-- shadowsocks-csharp/View/ConfigForm.Designer.cs | 47 ++----- shadowsocks-csharp/View/ConfigForm.cs | 164 ++++++++++--------------- 3 files changed, 81 insertions(+), 152 deletions(-) diff --git a/shadowsocks-csharp/Model/Configuration.cs b/shadowsocks-csharp/Model/Configuration.cs index 78eb3c29..d5acbe6d 100755 --- a/shadowsocks-csharp/Model/Configuration.cs +++ b/shadowsocks-csharp/Model/Configuration.cs @@ -16,8 +16,6 @@ namespace Shadowsocks.Model public int index; public bool enabled; public bool isDefault; - public bool lockStatus; - public bool enableLog; private static string CONFIG_FILE = "gui-config.json"; @@ -35,11 +33,11 @@ namespace Shadowsocks.Model public static void CheckServer(Server server) { - CheckPort(server.local_port); - CheckPort(server.server_port); - CheckPassword(server.password); - CheckServer(server.server); - CheckRemark(server.remarks); + checkPort(server.local_port); + checkPort(server.server_port); + checkPassword(server.password); + checkServer(server.server); + checkRemark(server.remarks); } public static Configuration Load() @@ -108,7 +106,7 @@ namespace Shadowsocks.Model }; } - private static void Assert(bool condition) + private static void assert(bool condition) { if (!condition) { @@ -116,7 +114,7 @@ namespace Shadowsocks.Model } } - private static void CheckPort(int port) + private static void checkPort(int port) { if (port <= 0 || port > 65535) { @@ -124,7 +122,7 @@ namespace Shadowsocks.Model } } - private static void CheckPassword(string password) + private static void checkPassword(string password) { if (string.IsNullOrEmpty(password)) { @@ -132,7 +130,7 @@ namespace Shadowsocks.Model } } - private static void CheckServer(string server) + private static void checkServer(string server) { if (string.IsNullOrEmpty(server)) { @@ -140,7 +138,7 @@ namespace Shadowsocks.Model } } - private static void CheckRemark(string remark) + private static void checkRemark(string remark) { //remark is optional } diff --git a/shadowsocks-csharp/View/ConfigForm.Designer.cs b/shadowsocks-csharp/View/ConfigForm.Designer.cs index a661b65a..6d6f8881 100755 --- a/shadowsocks-csharp/View/ConfigForm.Designer.cs +++ b/shadowsocks-csharp/View/ConfigForm.Designer.cs @@ -55,7 +55,6 @@ this.ConfigItem = new System.Windows.Forms.MenuItem(); this.menuItem4 = new System.Windows.Forms.MenuItem(); this.editPACFileItem = new System.Windows.Forms.MenuItem(); - this.QRCodeItem = new System.Windows.Forms.MenuItem(); this.aboutItem = new System.Windows.Forms.MenuItem(); this.menuItem3 = new System.Windows.Forms.MenuItem(); this.quitItem = new System.Windows.Forms.MenuItem(); @@ -64,13 +63,11 @@ this.AddButton = new System.Windows.Forms.Button(); this.ServerGroupBox = new System.Windows.Forms.GroupBox(); this.ServersListBox = new System.Windows.Forms.ListBox(); - this.LockButton = new System.Windows.Forms.Button(); - this.panel4 = new System.Windows.Forms.Panel(); + this.QRCodeItem = new System.Windows.Forms.MenuItem(); this.tableLayoutPanel1.SuspendLayout(); this.panel1.SuspendLayout(); this.panel3.SuspendLayout(); this.ServerGroupBox.SuspendLayout(); - this.panel4.SuspendLayout(); this.SuspendLayout(); // // tableLayoutPanel1 @@ -256,7 +253,7 @@ this.OKButton.Location = new System.Drawing.Point(4, 4); this.OKButton.Name = "OKButton"; this.OKButton.Size = new System.Drawing.Size(75, 23); - this.OKButton.TabIndex = 6; + this.OKButton.TabIndex = 8; this.OKButton.Text = "OK"; this.OKButton.UseVisualStyleBackColor = true; this.OKButton.Click += new System.EventHandler(this.OKButton_Click); @@ -267,7 +264,7 @@ this.MyCancelButton.Location = new System.Drawing.Point(86, 4); this.MyCancelButton.Name = "MyCancelButton"; this.MyCancelButton.Size = new System.Drawing.Size(75, 23); - this.MyCancelButton.TabIndex = 7; + this.MyCancelButton.TabIndex = 9; this.MyCancelButton.Text = "Cancel"; this.MyCancelButton.UseVisualStyleBackColor = true; this.MyCancelButton.Click += new System.EventHandler(this.CancelButton_Click); @@ -332,12 +329,6 @@ this.editPACFileItem.Text = "Edit &PAC File..."; this.editPACFileItem.Click += new System.EventHandler(this.EditPACFileItem_Click); // - // QRCodeItem - // - this.QRCodeItem.Index = 4; - this.QRCodeItem.Text = "Show &QRCode..."; - this.QRCodeItem.Click += new System.EventHandler(this.QRCodeItem_Click); - // // aboutItem // this.aboutItem.Index = 5; @@ -371,7 +362,7 @@ this.DeleteButton.Location = new System.Drawing.Point(100, 4); this.DeleteButton.Name = "DeleteButton"; this.DeleteButton.Size = new System.Drawing.Size(89, 23); - this.DeleteButton.TabIndex = 9; + this.DeleteButton.TabIndex = 7; this.DeleteButton.Text = "&Delete"; this.DeleteButton.UseVisualStyleBackColor = true; this.DeleteButton.Click += new System.EventHandler(this.DeleteButton_Click); @@ -381,7 +372,7 @@ this.AddButton.Location = new System.Drawing.Point(4, 4); this.AddButton.Name = "AddButton"; this.AddButton.Size = new System.Drawing.Size(89, 23); - this.AddButton.TabIndex = 8; + this.AddButton.TabIndex = 6; this.AddButton.Text = "&Add"; this.AddButton.UseVisualStyleBackColor = true; this.AddButton.Click += new System.EventHandler(this.AddButton_Click); @@ -405,25 +396,11 @@ this.ServersListBox.TabIndex = 5; this.ServersListBox.SelectedIndexChanged += new System.EventHandler(this.ServersListBox_SelectedIndexChanged); // - // LockButton - // - this.LockButton.Location = new System.Drawing.Point(4, 4); - this.LockButton.Name = "LockButton"; - this.LockButton.Size = new System.Drawing.Size(89, 23); - this.LockButton.TabIndex = 10; - this.LockButton.Text = "&Lock"; - this.LockButton.UseVisualStyleBackColor = true; - this.LockButton.Click += new System.EventHandler(this.LockButton_Click); - // - // panel4 + // QRCodeItem // - this.panel4.AutoSize = true; - this.panel4.Controls.Add(this.LockButton); - this.panel4.Location = new System.Drawing.Point(12, 251); - this.panel4.Margin = new System.Windows.Forms.Padding(0); - this.panel4.Name = "panel4"; - this.panel4.Size = new System.Drawing.Size(192, 30); - this.panel4.TabIndex = 7; + this.QRCodeItem.Index = 4; + this.QRCodeItem.Text = "Show &QRCode..."; + this.QRCodeItem.Click += new System.EventHandler(this.QRCodeItem_Click); // // ConfigForm // @@ -431,9 +408,7 @@ this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.AutoSize = true; - this.CancelButton = this.MyCancelButton; this.ClientSize = new System.Drawing.Size(489, 286); - this.Controls.Add(this.panel4); this.Controls.Add(this.ServersListBox); this.Controls.Add(this.ServerGroupBox); this.Controls.Add(this.panel1); @@ -445,7 +420,6 @@ this.Name = "ConfigForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Shadowsocks"; - this.TopMost = true; this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ConfigForm_FormClosed); this.Load += new System.EventHandler(this.ConfigForm_Load); this.Shown += new System.EventHandler(this.ConfigForm_Shown); @@ -455,7 +429,6 @@ this.panel3.ResumeLayout(false); this.ServerGroupBox.ResumeLayout(false); this.ServerGroupBox.PerformLayout(); - this.panel4.ResumeLayout(false); this.ResumeLayout(false); this.PerformLayout(); @@ -497,8 +470,6 @@ private System.Windows.Forms.TextBox RemarksTextBox; private System.Windows.Forms.Label label6; private System.Windows.Forms.MenuItem QRCodeItem; - private System.Windows.Forms.Button LockButton; - private System.Windows.Forms.Panel panel4; } } diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index 68cb861c..2631f529 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.ComponentModel; using System.Drawing; -using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; using System.Diagnostics; @@ -16,10 +15,9 @@ namespace Shadowsocks.View private ShadowsocksController controller; // this is a copy of configuration that we are working on - private Configuration _modifiedConfiguration; - private int _oldSelectedIndex = -1; - private bool _isFirstRun; - private bool _lockStatus; + private Configuration modifiedConfiguration; + private int oldSelectedIndex = -1; + private bool isFirstRun; public ConfigForm(ShadowsocksController controller) { @@ -31,12 +29,12 @@ namespace Shadowsocks.View controller.ConfigChanged += controller_ConfigChanged; controller.PACFileReadyToOpen += controller_PACFileReadyToOpen; - LoadCurrentConfiguration(); + loadCurrentConfiguration(); } private void controller_ConfigChanged(object sender, EventArgs e) { - LoadCurrentConfiguration(); + loadCurrentConfiguration(); } private void controller_EnableStatusChanged(object sender, EventArgs e) @@ -52,31 +50,18 @@ namespace Shadowsocks.View } - private void ShowWindow() + private void showWindow() { this.Opacity = 1; this.Show(); IPTextBox.Focus(); - if (_lockStatus) - { - IPTextBox.Enabled = false; - ServerPortTextBox.Enabled = false; - PasswordTextBox.Enabled = false; - EncryptionSelect.Enabled = false; - ProxyPortTextBox.Enabled = false; - RemarksTextBox.Enabled = false; - AddButton.Enabled = false; - DeleteButton.Enabled = false; - _lockStatus = true; - LockButton.Text = "&Unlock Settings"; - } } - private bool SaveOldSelectedServer() + private bool saveOldSelectedServer() { try { - if (_oldSelectedIndex == -1 || _oldSelectedIndex >= _modifiedConfiguration.configs.Count) + if (oldSelectedIndex == -1 || oldSelectedIndex >= modifiedConfiguration.configs.Count) { return true; } @@ -90,7 +75,7 @@ namespace Shadowsocks.View remarks = RemarksTextBox.Text }; Configuration.CheckServer(server); - _modifiedConfiguration.configs[_oldSelectedIndex] = server; + modifiedConfiguration.configs[oldSelectedIndex] = server; return true; } catch (FormatException) @@ -104,17 +89,17 @@ namespace Shadowsocks.View return false; } - private void LoadSelectedServer() + private void loadSelectedServer() { - if (ServersListBox.SelectedIndex >= 0 && ServersListBox.SelectedIndex < _modifiedConfiguration.configs.Count) + if (ServersListBox.SelectedIndex >= 0 && ServersListBox.SelectedIndex < modifiedConfiguration.configs.Count) { - Server server = _modifiedConfiguration.configs[ServersListBox.SelectedIndex]; + Server server = modifiedConfiguration.configs[ServersListBox.SelectedIndex]; IPTextBox.Text = server.server; ServerPortTextBox.Text = server.server_port.ToString(); PasswordTextBox.Text = server.password; ProxyPortTextBox.Text = server.local_port.ToString(); - EncryptionSelect.Text = server.method ?? "aes-256-cfb"; + EncryptionSelect.Text = server.method == null ? "aes-256-cfb" : server.method; RemarksTextBox.Text = server.remarks; ServerGroupBox.Visible = true; //IPTextBox.Focus(); @@ -125,29 +110,28 @@ namespace Shadowsocks.View } } - private void LoadConfiguration(Configuration configuration) + private void loadConfiguration(Configuration configuration) { ServersListBox.Items.Clear(); - foreach (Server server in _modifiedConfiguration.configs) + foreach (Server server in modifiedConfiguration.configs) { ServersListBox.Items.Add(string.IsNullOrEmpty(server.server) ? "New server" : string.IsNullOrEmpty(server.remarks)? server.server + ":" + server.server_port : server.server + ":" + server.server_port + " (" + server.remarks + ")"); } } - private void LoadCurrentConfiguration() + private void loadCurrentConfiguration() { - _modifiedConfiguration = controller.GetConfiguration(); - LoadConfiguration(_modifiedConfiguration); - _oldSelectedIndex = _modifiedConfiguration.index; - _lockStatus = _modifiedConfiguration.lockStatus; - ServersListBox.SelectedIndex = _modifiedConfiguration.index; - LoadSelectedServer(); - - UpdateServersMenu(); - enableItem.Checked = _modifiedConfiguration.enabled; + modifiedConfiguration = controller.GetConfiguration(); + loadConfiguration(modifiedConfiguration); + oldSelectedIndex = modifiedConfiguration.index; + ServersListBox.SelectedIndex = modifiedConfiguration.index; + loadSelectedServer(); + + updateServersMenu(); + enableItem.Checked = modifiedConfiguration.enabled; } - private void UpdateServersMenu() + private void updateServersMenu() { var items = ServersItem.MenuItems; @@ -173,68 +157,71 @@ namespace Shadowsocks.View private void ConfigForm_Load(object sender, EventArgs e) { - if (controller == null || controller.GetConfiguration().isDefault) + if (!controller.GetConfiguration().isDefault) { - _isFirstRun = true; + this.Opacity = 0; + BeginInvoke(new MethodInvoker(delegate + { + this.Hide(); + })); } else { - this.Opacity = 0; - BeginInvoke(new MethodInvoker(delegate { this.Hide(); })); + isFirstRun = true; } } private void ServersListBox_SelectedIndexChanged(object sender, EventArgs e) { - if (_oldSelectedIndex == ServersListBox.SelectedIndex) + if (oldSelectedIndex == ServersListBox.SelectedIndex) { // we are moving back to oldSelectedIndex or doing a force move return; } - if (!SaveOldSelectedServer()) + if (!saveOldSelectedServer()) { // why this won't cause stack overflow? - ServersListBox.SelectedIndex = _oldSelectedIndex; + ServersListBox.SelectedIndex = oldSelectedIndex; return; } - LoadSelectedServer(); - _oldSelectedIndex = ServersListBox.SelectedIndex; + loadSelectedServer(); + oldSelectedIndex = ServersListBox.SelectedIndex; } private void AddButton_Click(object sender, EventArgs e) { - if (!SaveOldSelectedServer()) + if (!saveOldSelectedServer()) { return; } Server server = Configuration.GetDefaultServer(); - _modifiedConfiguration.configs.Add(server); - LoadConfiguration(_modifiedConfiguration); - ServersListBox.SelectedIndex = _modifiedConfiguration.configs.Count - 1; - _oldSelectedIndex = ServersListBox.SelectedIndex; + modifiedConfiguration.configs.Add(server); + loadConfiguration(modifiedConfiguration); + ServersListBox.SelectedIndex = modifiedConfiguration.configs.Count - 1; + oldSelectedIndex = ServersListBox.SelectedIndex; } private void DeleteButton_Click(object sender, EventArgs e) { - _oldSelectedIndex = ServersListBox.SelectedIndex; - if (_oldSelectedIndex >= 0 && _oldSelectedIndex < _modifiedConfiguration.configs.Count) + oldSelectedIndex = ServersListBox.SelectedIndex; + if (oldSelectedIndex >= 0 && oldSelectedIndex < modifiedConfiguration.configs.Count) { - _modifiedConfiguration.configs.RemoveAt(_oldSelectedIndex); + modifiedConfiguration.configs.RemoveAt(oldSelectedIndex); } - if (_oldSelectedIndex >= _modifiedConfiguration.configs.Count) + if (oldSelectedIndex >= modifiedConfiguration.configs.Count) { // can be -1 - _oldSelectedIndex = _modifiedConfiguration.configs.Count - 1; + oldSelectedIndex = modifiedConfiguration.configs.Count - 1; } - ServersListBox.SelectedIndex = _oldSelectedIndex; - LoadConfiguration(_modifiedConfiguration); - ServersListBox.SelectedIndex = _oldSelectedIndex; - LoadSelectedServer(); + ServersListBox.SelectedIndex = oldSelectedIndex; + loadConfiguration(modifiedConfiguration); + ServersListBox.SelectedIndex = oldSelectedIndex; + loadSelectedServer(); } private void Config_Click(object sender, EventArgs e) { - ShowWindow(); + showWindow(); } private void Quit_Click(object sender, EventArgs e) @@ -242,39 +229,38 @@ namespace Shadowsocks.View this.Close(); } - private void ShowFirstTimeBalloon() + private void showFirstTimeBalloon() { - if (_isFirstRun) + if (isFirstRun) { notifyIcon1.BalloonTipTitle = "Shadowsocks is here"; notifyIcon1.BalloonTipText = "You can turn on/off Shadowsocks in the context menu"; notifyIcon1.ShowBalloonTip(0); - _isFirstRun = false; + isFirstRun = false; } } private void OKButton_Click(object sender, EventArgs e) { - if (!SaveOldSelectedServer()) + if (!saveOldSelectedServer()) { return; } - if (_modifiedConfiguration.configs.Count == 0) + if (modifiedConfiguration.configs.Count == 0) { MessageBox.Show("Please add at least one server"); return; } - _modifiedConfiguration.lockStatus = _lockStatus; - controller.SaveConfig(_modifiedConfiguration); + controller.SaveConfig(modifiedConfiguration); this.Hide(); - ShowFirstTimeBalloon(); + showFirstTimeBalloon(); } private void CancelButton_Click(object sender, EventArgs e) { this.Hide(); - LoadCurrentConfiguration(); - ShowFirstTimeBalloon(); + loadCurrentConfiguration(); + showFirstTimeBalloon(); } private void ConfigForm_FormClosed(object sender, FormClosedEventArgs e) @@ -289,7 +275,7 @@ namespace Shadowsocks.View private void notifyIcon1_DoubleClick(object sender, EventArgs e) { - ShowWindow(); + showWindow(); } @@ -321,31 +307,5 @@ namespace Shadowsocks.View { new QRCodeForm(controller.GetQRCodeForCurrentServer()).Show(); } - - private void ChangeLockStatus(bool lockStatus) - { - IPTextBox.Enabled = lockStatus; - ServerPortTextBox.Enabled = lockStatus; - PasswordTextBox.Enabled = lockStatus; - EncryptionSelect.Enabled = lockStatus; - ProxyPortTextBox.Enabled = lockStatus; - RemarksTextBox.Enabled = lockStatus; - AddButton.Enabled = lockStatus; - DeleteButton.Enabled = lockStatus; - _lockStatus = !lockStatus; - if (lockStatus) - { - LockButton.Text = "&Lock"; - } - else - { - LockButton.Text = "&Unlock"; - } - } - - private void LockButton_Click(object sender, EventArgs e) - { - ChangeLockStatus(_lockStatus); - } } } From 9f50a5a34b04b94da529cb4c490544e7287185b3 Mon Sep 17 00:00:00 2001 From: wzxjohn Date: Sun, 9 Nov 2014 02:13:35 +0800 Subject: [PATCH 08/19] add cancel button for config Now can use esc key to cancel, and don't change focus after change server from list --- shadowsocks-csharp/View/ConfigForm.Designer.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/shadowsocks-csharp/View/ConfigForm.Designer.cs b/shadowsocks-csharp/View/ConfigForm.Designer.cs index 6d6f8881..b2d20a84 100755 --- a/shadowsocks-csharp/View/ConfigForm.Designer.cs +++ b/shadowsocks-csharp/View/ConfigForm.Designer.cs @@ -55,6 +55,7 @@ this.ConfigItem = new System.Windows.Forms.MenuItem(); this.menuItem4 = new System.Windows.Forms.MenuItem(); this.editPACFileItem = new System.Windows.Forms.MenuItem(); + this.QRCodeItem = new System.Windows.Forms.MenuItem(); this.aboutItem = new System.Windows.Forms.MenuItem(); this.menuItem3 = new System.Windows.Forms.MenuItem(); this.quitItem = new System.Windows.Forms.MenuItem(); @@ -63,7 +64,6 @@ this.AddButton = new System.Windows.Forms.Button(); this.ServerGroupBox = new System.Windows.Forms.GroupBox(); this.ServersListBox = new System.Windows.Forms.ListBox(); - this.QRCodeItem = new System.Windows.Forms.MenuItem(); this.tableLayoutPanel1.SuspendLayout(); this.panel1.SuspendLayout(); this.panel3.SuspendLayout(); @@ -329,6 +329,12 @@ this.editPACFileItem.Text = "Edit &PAC File..."; this.editPACFileItem.Click += new System.EventHandler(this.EditPACFileItem_Click); // + // QRCodeItem + // + this.QRCodeItem.Index = 4; + this.QRCodeItem.Text = "Show &QRCode..."; + this.QRCodeItem.Click += new System.EventHandler(this.QRCodeItem_Click); + // // aboutItem // this.aboutItem.Index = 5; @@ -396,18 +402,13 @@ this.ServersListBox.TabIndex = 5; this.ServersListBox.SelectedIndexChanged += new System.EventHandler(this.ServersListBox_SelectedIndexChanged); // - // QRCodeItem - // - this.QRCodeItem.Index = 4; - this.QRCodeItem.Text = "Show &QRCode..."; - this.QRCodeItem.Click += new System.EventHandler(this.QRCodeItem_Click); - // // ConfigForm // this.AcceptButton = this.OKButton; this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.AutoSize = true; + this.CancelButton = this.MyCancelButton; this.ClientSize = new System.Drawing.Size(489, 286); this.Controls.Add(this.ServersListBox); this.Controls.Add(this.ServerGroupBox); From fc53a072035909e5fa0aa89ab712bd83abfbb788 Mon Sep 17 00:00:00 2001 From: wzxjohn Date: Sun, 9 Nov 2014 02:18:47 +0800 Subject: [PATCH 09/19] change function to C# style Change the first letter of function to upper case letter to fit C# code style --- shadowsocks-csharp/Controller/Local.cs | 30 +++++++------- shadowsocks-csharp/Controller/PACServer.cs | 28 ++++++------- shadowsocks-csharp/Controller/PolipoRunner.cs | 30 +++++++------- .../Controller/ShadowsocksController.cs | 32 +++++++-------- shadowsocks-csharp/Encrypt/EncryptorFactory.cs | 30 +++++++------- shadowsocks-csharp/Model/Configuration.cs | 20 ++++----- shadowsocks-csharp/View/ConfigForm.cs | 48 +++++++++++----------- 7 files changed, 109 insertions(+), 109 deletions(-) diff --git a/shadowsocks-csharp/Controller/Local.cs b/shadowsocks-csharp/Controller/Local.cs index b5db6c0c..cace2f57 100755 --- a/shadowsocks-csharp/Controller/Local.cs +++ b/shadowsocks-csharp/Controller/Local.cs @@ -13,7 +13,7 @@ namespace Shadowsocks.Controller { private Server config; //private Encryptor encryptor; - Socket listener; + Socket _listener; public Local(Server config) { this.config = config; @@ -25,24 +25,24 @@ namespace Shadowsocks.Controller try { // Create a TCP/IP socket. - listener = new Socket(AddressFamily.InterNetwork, + _listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint localEndPoint = new IPEndPoint(0, config.local_port); // Bind the socket to the local endpoint and listen for incoming connections. - listener.Bind(localEndPoint); - listener.Listen(100); + _listener.Bind(localEndPoint); + _listener.Listen(100); // Start an asynchronous socket to listen for connections. Console.WriteLine("Shadowsocks started"); - listener.BeginAccept( + _listener.BeginAccept( new AsyncCallback(AcceptCallback), - listener); + _listener); } catch(SocketException) { - listener.Close(); + _listener.Close(); throw; } @@ -50,7 +50,7 @@ namespace Shadowsocks.Controller public void Stop() { - listener.Close(); + _listener.Close(); } @@ -90,7 +90,7 @@ namespace Shadowsocks.Controller //handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, // new AsyncCallback(ReadCallback), state); } - catch (Exception) + catch { //Console.WriteLine(e.Message); } @@ -141,7 +141,7 @@ namespace Shadowsocks.Controller // Connect to the remote endpoint. remote.BeginConnect(remoteEP, - new AsyncCallback(connectCallback), null); + new AsyncCallback(ConnectCallback), null); } catch (Exception e) { @@ -182,7 +182,7 @@ namespace Shadowsocks.Controller ((IDisposable)encryptor).Dispose(); } - private void connectCallback(IAsyncResult ar) + private void ConnectCallback(IAsyncResult ar) { try { @@ -192,7 +192,7 @@ namespace Shadowsocks.Controller //Console.WriteLine("Socket connected to {0}", // remote.RemoteEndPoint.ToString()); - handshakeReceive(); + HandshakeReceive(); } catch (Exception e) { @@ -201,12 +201,12 @@ namespace Shadowsocks.Controller } } - private void handshakeReceive() + private void HandshakeReceive() { try { connection.BeginReceive(connetionRecvBuffer, 0, 256, 0, - new AsyncCallback(handshakeReceiveCallback), null); + new AsyncCallback(HandshakeReceiveCallback), null); } catch (Exception e) { @@ -215,7 +215,7 @@ namespace Shadowsocks.Controller } } - private void handshakeReceiveCallback(IAsyncResult ar) + private void HandshakeReceiveCallback(IAsyncResult ar) { try { diff --git a/shadowsocks-csharp/Controller/PACServer.cs b/shadowsocks-csharp/Controller/PACServer.cs index bedce2e4..eab2ff60 100755 --- a/shadowsocks-csharp/Controller/PACServer.cs +++ b/shadowsocks-csharp/Controller/PACServer.cs @@ -33,7 +33,7 @@ namespace Shadowsocks.Controller new AsyncCallback(AcceptCallback), listener); - watchPACFile(); + WatchPacFile(); } public string TouchPACFile() @@ -61,7 +61,7 @@ namespace Shadowsocks.Controller Socket conn = listener.EndAccept(ar); conn.BeginReceive(new byte[1024], 0, 1024, 0, - new AsyncCallback(receiveCallback), conn); + new AsyncCallback(ReceiveCallback), conn); } catch (Exception e) { @@ -69,7 +69,7 @@ namespace Shadowsocks.Controller } } - private string getPACContent() + private string GetPACContent() { if (File.Exists(PAC_FILE)) { @@ -92,17 +92,17 @@ namespace Shadowsocks.Controller return System.Text.Encoding.UTF8.GetString(buffer, 0, n); } } - watchPACFile(); + WatchPacFile(); } - private void receiveCallback(IAsyncResult ar) + private void ReceiveCallback(IAsyncResult ar) { Socket conn = (Socket)ar.AsyncState; try { int bytesRead = conn.EndReceive(ar); - string pac = getPACContent(); + string pac = GetPACContent(); string proxy = "PROXY 127.0.0.1:8123;"; @@ -118,7 +118,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); + conn.BeginSend(response, 0, response.Length, 0, new AsyncCallback(SendCallback), conn); } else { @@ -132,13 +132,13 @@ Connection: Close } } - private void sendCallback(IAsyncResult ar) + private void SendCallback(IAsyncResult ar) { Socket conn = (Socket)ar.AsyncState; conn.Shutdown(SocketShutdown.Send); } - private void watchPACFile() + private void WatchPacFile() { if (watcher != null) { @@ -147,14 +147,14 @@ Connection: Close watcher = new FileSystemWatcher(Directory.GetCurrentDirectory()); watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName; watcher.Filter = PAC_FILE; - watcher.Changed += watcher_Changed; - watcher.Created += watcher_Changed; - watcher.Deleted += watcher_Changed; - watcher.Renamed += watcher_Changed; + watcher.Changed += Watcher_Changed; + watcher.Created += Watcher_Changed; + watcher.Deleted += Watcher_Changed; + watcher.Renamed += Watcher_Changed; watcher.EnableRaisingEvents = true; } - void watcher_Changed(object sender, FileSystemEventArgs e) + private void Watcher_Changed(object sender, FileSystemEventArgs e) { if (PACFileChanged != null) { diff --git a/shadowsocks-csharp/Controller/PolipoRunner.cs b/shadowsocks-csharp/Controller/PolipoRunner.cs index 1f9802cf..9f3c2187 100755 --- a/shadowsocks-csharp/Controller/PolipoRunner.cs +++ b/shadowsocks-csharp/Controller/PolipoRunner.cs @@ -11,11 +11,11 @@ namespace Shadowsocks.Controller { class PolipoRunner { - private Process process; + private Process _process; public void Start(Server config) { - if (process == null) + if (_process == null) { Process[] existingPolipo = Process.GetProcessesByName("ss_polipo"); foreach (Process p in existingPolipo) @@ -36,34 +36,34 @@ namespace Shadowsocks.Controller FileManager.ByteArrayToFile(temppath + "/polipo.conf", System.Text.Encoding.UTF8.GetBytes(polipoConfig)); FileManager.UncompressFile(temppath + "/ss_polipo.exe", Resources.polipo_exe); - process = new Process(); + _process = new Process(); // Configure the process using the StartInfo properties. - process.StartInfo.FileName = temppath + "/ss_polipo.exe"; - process.StartInfo.Arguments = "-c \"" + temppath + "/polipo.conf\""; - process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; - process.StartInfo.UseShellExecute = false; - process.StartInfo.CreateNoWindow = true; - process.StartInfo.RedirectStandardOutput = true; - process.StartInfo.RedirectStandardError = true; + _process.StartInfo.FileName = temppath + "/ss_polipo.exe"; + _process.StartInfo.Arguments = "-c \"" + temppath + "/polipo.conf\""; + _process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; + _process.StartInfo.UseShellExecute = false; + _process.StartInfo.CreateNoWindow = true; + _process.StartInfo.RedirectStandardOutput = true; + _process.StartInfo.RedirectStandardError = true; //process.StandardOutput - process.Start(); + _process.Start(); } } public void Stop() { - if (process != null) + if (_process != null) { try { - process.Kill(); - process.WaitForExit(); + _process.Kill(); + _process.WaitForExit(); } catch (InvalidOperationException) { // do nothing } - process = null; + _process = null; } } } diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index 4111d2b8..5af0bf38 100755 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -14,7 +14,7 @@ namespace Shadowsocks.Controller private Local local; private PACServer pacServer; - private Configuration config; + private Configuration _config; private PolipoRunner polipoRunner; private bool stopped = false; @@ -31,10 +31,10 @@ namespace Shadowsocks.Controller public ShadowsocksController() { - config = Configuration.Load(); + _config = Configuration.Load(); polipoRunner = new PolipoRunner(); - polipoRunner.Start(config.GetCurrentServer()); - local = new Local(config.GetCurrentServer()); + polipoRunner.Start(_config.GetCurrentServer()); + local = new Local(_config.GetCurrentServer()); try { local.Start(); @@ -47,20 +47,20 @@ namespace Shadowsocks.Controller Console.WriteLine(e.Message); } - updateSystemProxy(); + UpdateSystemProxy(); } public void SaveConfig(Configuration newConfig) { Configuration.Save(newConfig); // some logic in configuration updated the config when saving, we need to read it again - config = Configuration.Load(); + _config = Configuration.Load(); local.Stop(); polipoRunner.Stop(); - polipoRunner.Start(config.GetCurrentServer()); + polipoRunner.Start(_config.GetCurrentServer()); - local = new Local(config.GetCurrentServer()); + local = new Local(_config.GetCurrentServer()); local.Start(); if (ConfigChanged != null) @@ -71,7 +71,7 @@ namespace Shadowsocks.Controller public Server GetCurrentServer() { - return config.GetCurrentServer(); + return _config.GetCurrentServer(); } // always return copy @@ -83,9 +83,9 @@ namespace Shadowsocks.Controller public void ToggleEnable(bool enabled) { - config.enabled = enabled; - updateSystemProxy(); - SaveConfig(config); + _config.enabled = enabled; + UpdateSystemProxy(); + SaveConfig(_config); if (EnableStatusChanged != null) { EnableStatusChanged(this, new EventArgs()); @@ -101,7 +101,7 @@ namespace Shadowsocks.Controller stopped = true; local.Stop(); polipoRunner.Stop(); - if (config.enabled) + if (_config.enabled) { SystemProxy.Disable(); } @@ -124,9 +124,9 @@ namespace Shadowsocks.Controller return "ss://" + base64; } - private void updateSystemProxy() + private void UpdateSystemProxy() { - if (config.enabled) + if (_config.enabled) { SystemProxy.Enable(); } @@ -138,7 +138,7 @@ namespace Shadowsocks.Controller private void pacServer_PACFileChanged(object sender, EventArgs e) { - updateSystemProxy(); + UpdateSystemProxy(); } } diff --git a/shadowsocks-csharp/Encrypt/EncryptorFactory.cs b/shadowsocks-csharp/Encrypt/EncryptorFactory.cs index 422e0c2e..59111a69 100644 --- a/shadowsocks-csharp/Encrypt/EncryptorFactory.cs +++ b/shadowsocks-csharp/Encrypt/EncryptorFactory.cs @@ -1,16 +1,16 @@  -namespace Shadowsocks.Encrypt -{ - public static class EncryptorFactory - { - public static IEncryptor GetEncryptor(string method, string password) - { - if (string.IsNullOrEmpty(method) || method.ToLowerInvariant() == "table") - { - return new TableEncryptor(method, password); - } - - return new PolarSSLEncryptor(method, password); - } - } -} +namespace Shadowsocks.Encrypt +{ + public static class EncryptorFactory + { + public static IEncryptor GetEncryptor(string method, string password) + { + if (string.IsNullOrEmpty(method) || method.ToLowerInvariant() == "table") + { + return new TableEncryptor(method, password); + } + + return new PolarSSLEncryptor(method, password); + } + } +} diff --git a/shadowsocks-csharp/Model/Configuration.cs b/shadowsocks-csharp/Model/Configuration.cs index d5acbe6d..c45bb9f4 100755 --- a/shadowsocks-csharp/Model/Configuration.cs +++ b/shadowsocks-csharp/Model/Configuration.cs @@ -33,11 +33,11 @@ namespace Shadowsocks.Model public static void CheckServer(Server server) { - checkPort(server.local_port); - checkPort(server.server_port); - checkPassword(server.password); - checkServer(server.server); - checkRemark(server.remarks); + CheckPort(server.local_port); + CheckPort(server.server_port); + CheckPassword(server.password); + CheckServer(server.server); + CheckRemark(server.remarks); } public static Configuration Load() @@ -106,7 +106,7 @@ namespace Shadowsocks.Model }; } - private static void assert(bool condition) + private static void Assert(bool condition) { if (!condition) { @@ -114,7 +114,7 @@ namespace Shadowsocks.Model } } - private static void checkPort(int port) + private static void CheckPort(int port) { if (port <= 0 || port > 65535) { @@ -122,7 +122,7 @@ namespace Shadowsocks.Model } } - private static void checkPassword(string password) + private static void CheckPassword(string password) { if (string.IsNullOrEmpty(password)) { @@ -130,7 +130,7 @@ namespace Shadowsocks.Model } } - private static void checkServer(string server) + private static void CheckServer(string server) { if (string.IsNullOrEmpty(server)) { @@ -138,7 +138,7 @@ namespace Shadowsocks.Model } } - private static void checkRemark(string remark) + private static void CheckRemark(string remark) { //remark is optional } diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index 2631f529..195d0bc9 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -29,12 +29,12 @@ namespace Shadowsocks.View controller.ConfigChanged += controller_ConfigChanged; controller.PACFileReadyToOpen += controller_PACFileReadyToOpen; - loadCurrentConfiguration(); + LoadCurrentConfiguration(); } private void controller_ConfigChanged(object sender, EventArgs e) { - loadCurrentConfiguration(); + LoadCurrentConfiguration(); } private void controller_EnableStatusChanged(object sender, EventArgs e) @@ -50,14 +50,14 @@ namespace Shadowsocks.View } - private void showWindow() + private void ShowWindow() { this.Opacity = 1; this.Show(); IPTextBox.Focus(); } - private bool saveOldSelectedServer() + private bool SaveOldSelectedServer() { try { @@ -89,7 +89,7 @@ namespace Shadowsocks.View return false; } - private void loadSelectedServer() + private void LoadSelectedServer() { if (ServersListBox.SelectedIndex >= 0 && ServersListBox.SelectedIndex < modifiedConfiguration.configs.Count) { @@ -110,7 +110,7 @@ namespace Shadowsocks.View } } - private void loadConfiguration(Configuration configuration) + private void LoadConfiguration(Configuration configuration) { ServersListBox.Items.Clear(); foreach (Server server in modifiedConfiguration.configs) @@ -119,19 +119,19 @@ namespace Shadowsocks.View } } - private void loadCurrentConfiguration() + private void LoadCurrentConfiguration() { modifiedConfiguration = controller.GetConfiguration(); - loadConfiguration(modifiedConfiguration); + LoadConfiguration(modifiedConfiguration); oldSelectedIndex = modifiedConfiguration.index; ServersListBox.SelectedIndex = modifiedConfiguration.index; - loadSelectedServer(); + LoadSelectedServer(); - updateServersMenu(); + UpdateServersMenu(); enableItem.Checked = modifiedConfiguration.enabled; } - private void updateServersMenu() + private void UpdateServersMenu() { var items = ServersItem.MenuItems; @@ -178,25 +178,25 @@ namespace Shadowsocks.View // we are moving back to oldSelectedIndex or doing a force move return; } - if (!saveOldSelectedServer()) + if (!SaveOldSelectedServer()) { // why this won't cause stack overflow? ServersListBox.SelectedIndex = oldSelectedIndex; return; } - loadSelectedServer(); + LoadSelectedServer(); oldSelectedIndex = ServersListBox.SelectedIndex; } private void AddButton_Click(object sender, EventArgs e) { - if (!saveOldSelectedServer()) + if (!SaveOldSelectedServer()) { return; } Server server = Configuration.GetDefaultServer(); modifiedConfiguration.configs.Add(server); - loadConfiguration(modifiedConfiguration); + LoadConfiguration(modifiedConfiguration); ServersListBox.SelectedIndex = modifiedConfiguration.configs.Count - 1; oldSelectedIndex = ServersListBox.SelectedIndex; } @@ -214,14 +214,14 @@ namespace Shadowsocks.View oldSelectedIndex = modifiedConfiguration.configs.Count - 1; } ServersListBox.SelectedIndex = oldSelectedIndex; - loadConfiguration(modifiedConfiguration); + LoadConfiguration(modifiedConfiguration); ServersListBox.SelectedIndex = oldSelectedIndex; - loadSelectedServer(); + LoadSelectedServer(); } private void Config_Click(object sender, EventArgs e) { - showWindow(); + ShowWindow(); } private void Quit_Click(object sender, EventArgs e) @@ -229,7 +229,7 @@ namespace Shadowsocks.View this.Close(); } - private void showFirstTimeBalloon() + private void ShowFirstTimeBalloon() { if (isFirstRun) { @@ -242,7 +242,7 @@ namespace Shadowsocks.View private void OKButton_Click(object sender, EventArgs e) { - if (!saveOldSelectedServer()) + if (!SaveOldSelectedServer()) { return; } @@ -253,14 +253,14 @@ namespace Shadowsocks.View } controller.SaveConfig(modifiedConfiguration); this.Hide(); - showFirstTimeBalloon(); + ShowFirstTimeBalloon(); } private void CancelButton_Click(object sender, EventArgs e) { this.Hide(); - loadCurrentConfiguration(); - showFirstTimeBalloon(); + LoadCurrentConfiguration(); + ShowFirstTimeBalloon(); } private void ConfigForm_FormClosed(object sender, FormClosedEventArgs e) @@ -275,7 +275,7 @@ namespace Shadowsocks.View private void notifyIcon1_DoubleClick(object sender, EventArgs e) { - showWindow(); + ShowWindow(); } From efefe274a6d4adf532f860e09668fad7ee6143e9 Mon Sep 17 00:00:00 2001 From: wzxjohn Date: Sun, 9 Nov 2014 02:27:44 +0800 Subject: [PATCH 10/19] handle no privilege error Popup an error window when don't have enough privilege to change Registry. --- shadowsocks-csharp/Controller/SystemProxy.cs | 49 ++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/shadowsocks-csharp/Controller/SystemProxy.cs b/shadowsocks-csharp/Controller/SystemProxy.cs index 803a326a..884c7260 100755 --- a/shadowsocks-csharp/Controller/SystemProxy.cs +++ b/shadowsocks-csharp/Controller/SystemProxy.cs @@ -1,4 +1,5 @@ -using Microsoft.Win32; +using System.Windows.Forms; +using Microsoft.Win32; using System; using System.Collections.Generic; using System.Runtime.InteropServices; @@ -13,32 +14,52 @@ namespace Shadowsocks.Controller public static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength); public const int INTERNET_OPTION_SETTINGS_CHANGED = 39; public const int INTERNET_OPTION_REFRESH = 37; - static bool settingsReturn, refreshReturn; + static bool _settingsReturn, _refreshReturn; public static void NotifyIE() { // These lines implement the Interface in the beginning of program // They cause the OS to refresh the settings, causing IP to realy update - settingsReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_SETTINGS_CHANGED, IntPtr.Zero, 0); - refreshReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0); + _settingsReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_SETTINGS_CHANGED, IntPtr.Zero, 0); + _refreshReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0); } public static void Enable() { - RegistryKey registry = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true); - registry.SetValue("ProxyEnable", 0); - registry.SetValue("ProxyServer", ""); - registry.SetValue("AutoConfigURL", "http://127.0.0.1:8090/pac?t=" + GetTimestamp(DateTime.Now)); - SystemProxy.NotifyIE(); + try + { + RegistryKey registry = + Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", + true); + registry.SetValue("ProxyEnable", 0); + registry.SetValue("ProxyServer", ""); + registry.SetValue("AutoConfigURL", "http://127.0.0.1:8090/pac?t=" + GetTimestamp(DateTime.Now)); + SystemProxy.NotifyIE(); + } + catch (Exception) + { + MessageBox.Show("can not change registry!"); + throw; + } } public static void Disable() { - RegistryKey registry = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true); - registry.SetValue("ProxyEnable", 0); - registry.SetValue("ProxyServer", ""); - registry.SetValue("AutoConfigURL", ""); - SystemProxy.NotifyIE(); + try + { + RegistryKey registry = + Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", + true); + registry.SetValue("ProxyEnable", 0); + registry.SetValue("ProxyServer", ""); + registry.SetValue("AutoConfigURL", ""); + SystemProxy.NotifyIE(); + } + catch (Exception) + { + MessageBox.Show("can not change registry!"); + throw; + } } private static String GetTimestamp(DateTime value) From b9bfbe0522f83a6db5ab49c5f959c7ca3e4214e9 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 02:40:21 +0800 Subject: [PATCH 11/19] fix build for .net 4 --- .../Properties/Resources.Designer.cs | 26 +++++++----- shadowsocks-csharp/app.config | 2 +- shadowsocks-csharp/shadowsocks-csharp.csproj | 47 +++++++++++++++++++--- 3 files changed, 58 insertions(+), 17 deletions(-) diff --git a/shadowsocks-csharp/Properties/Resources.Designer.cs b/shadowsocks-csharp/Properties/Resources.Designer.cs index 077a5ff0..36db144e 100755 --- a/shadowsocks-csharp/Properties/Resources.Designer.cs +++ b/shadowsocks-csharp/Properties/Resources.Designer.cs @@ -113,26 +113,30 @@ namespace Shadowsocks.Properties { /// __QRCODELIB__ ///</script> ///<style> - /// body { - /// padding: 10px; - /// margin: 0; + /// html, body, table, div { + /// padding: 0px; + /// margin: 0 !important; /// } + /// div#qrcode { + /// margin: 5px !important; + /// text-align: center; + /// vertical-align: center; + /// } /// #qrcode { - /// width:300px; - /// height:300px; + /// width:190px; + /// height:190px; /// } + /// table { + /// width: 100%; + /// height:100%; + /// } ///</style> ///</head> ///<body> ///<div id="qrcode" name="qrcode"></div> ///<script type="text/javascript"> /// function genCode(code) { - /// new QRCode("qrcode", { - /// text: code, - /// width: 300, - /// height: 300, - /// colorDark : "#000000", - /// colorLig [rest of string was truncated]";. + /// new QRCode("qrcode" [rest of string was truncated]";. /// internal static string qrcode { get { diff --git a/shadowsocks-csharp/app.config b/shadowsocks-csharp/app.config index dde978a0..867ff468 100755 --- a/shadowsocks-csharp/app.config +++ b/shadowsocks-csharp/app.config @@ -1,6 +1,6 @@ - + diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index 45afa2e7..5d4c8262 100755 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -10,7 +10,7 @@ Properties Shadowsocks Shadowsocks - v2.0 + v4.0 512 @@ -21,7 +21,7 @@ 3.5 - + Client publish\ true Disk @@ -45,6 +45,7 @@ x86 prompt ManagedMinimumRules.ruleset + false bin\x86\Release\ @@ -54,15 +55,51 @@ x86 prompt ManagedMinimumRules.ruleset + false + + + true + bin\Debug\ + TRACE;DEBUG + full + x86 + prompt + ManagedMinimumRules.ruleset + true + + + bin\Release\ + TRACE;SIMPLE_JSON_NO_LINQ_EXPRESSION + true + pdbonly + AnyCPU + prompt + ManagedMinimumRules.ruleset + + + true + bin\x64\Debug\ + TRACE;DEBUG + full + x64 + prompt + ManagedMinimumRules.ruleset + true + + + bin\x64\Release\ + TRACE;SIMPLE_JSON_NO_LINQ_EXPRESSION + true + pdbonly + x64 + prompt + ManagedMinimumRules.ruleset - - - From 0bf26002e41220fe06af24ea6d593660dbbd281b Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 02:45:42 +0800 Subject: [PATCH 12/19] change back to 2.0 --- shadowsocks-csharp/shadowsocks-csharp.csproj | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index 5d4c8262..94543fa3 100755 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -10,7 +10,7 @@ Properties Shadowsocks Shadowsocks - v4.0 + v2.0 512 @@ -21,7 +21,8 @@ 3.5 - Client + + publish\ true Disk From 0bdd5d298b0465d273d2ba6077fcdb2dfcb9699a Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 02:47:42 +0800 Subject: [PATCH 13/19] add comments in readme about the .net framework difference --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9be979a6..4f52c919 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,10 @@ Shadowsocks for Windows Download [latest release]. +For Windows 7 and older, please download Shadowsocks-win-x.x.x.zip. + +For Windows 8.1 and newer, please download Shadowsocks-win-dotnet4.0-x.x.x.zip. + ### Usage 1. Find Shadowsocks icon in notification tray @@ -25,8 +29,8 @@ Download [latest release]. about the change automatically 5. Please disable other proxy addons in your browser, or set them to use system proxy -6. You may need to install VC 2008 Runtime and .Net 2.0 if Shadowsocks failed to -start +6. You may need to install VC 2008 Runtime and .Net framework if Shadowsocks +failed to start ### License From 2585f4d615b95eb3c29237a6f362ae928c78cf27 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 02:58:16 +0800 Subject: [PATCH 14/19] remove x64 and AnyCPU again --- shadowsocks-csharp/shadowsocks-csharp.csproj | 38 ---------------------------- 1 file changed, 38 deletions(-) diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index 94543fa3..3d7e20d2 100755 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -58,44 +58,6 @@ ManagedMinimumRules.ruleset false - - true - bin\Debug\ - TRACE;DEBUG - full - x86 - prompt - ManagedMinimumRules.ruleset - true - - - bin\Release\ - TRACE;SIMPLE_JSON_NO_LINQ_EXPRESSION - true - pdbonly - AnyCPU - prompt - ManagedMinimumRules.ruleset - - - true - bin\x64\Debug\ - TRACE;DEBUG - full - x64 - prompt - ManagedMinimumRules.ruleset - true - - - bin\x64\Release\ - TRACE;SIMPLE_JSON_NO_LINQ_EXPRESSION - true - pdbonly - x64 - prompt - ManagedMinimumRules.ruleset - From d28e646ec72a3d2555437f41871bffc64b7e6a8d Mon Sep 17 00:00:00 2001 From: wzxjohn Date: Sun, 9 Nov 2014 03:23:34 +0800 Subject: [PATCH 15/19] change QR code generator Use QRCode4CS as the QR code generator, which is much more fast --- shadowsocks-csharp/3rd/QRCodeCS.cs | 1209 ++++++++++++++++++++++++ shadowsocks-csharp/View/QRCodeForm.Designer.cs | 20 +- shadowsocks-csharp/View/QRCodeForm.cs | 46 +- shadowsocks-csharp/View/QRCodeForm.resx | 329 +++++++ shadowsocks-csharp/shadowsocks-csharp.csproj | 1 + 5 files changed, 1601 insertions(+), 4 deletions(-) create mode 100644 shadowsocks-csharp/3rd/QRCodeCS.cs diff --git a/shadowsocks-csharp/3rd/QRCodeCS.cs b/shadowsocks-csharp/3rd/QRCodeCS.cs new file mode 100644 index 00000000..a380c978 --- /dev/null +++ b/shadowsocks-csharp/3rd/QRCodeCS.cs @@ -0,0 +1,1209 @@ +//--------------------------------------------------------------------- +// QRCode for C#4.0 Silverlight is translation of QRCode for JavaScript +// https://github.com/jeromeetienne/jquery-qrcode/ +// +// Copyright (c) 2009 Kazuhiko Arase +// +// URL: http://www.d-project.com/ +// +// Licensed under the MIT license: +// http://www.opensource.org/licenses/mit-license.php +// +// The word "QR Code" is registered trademark of +// DENSO WAVE INCORPORATED +// http://www.denso-wave.com/qrcode/faqpatent-e.html +// +//--------------------------------------------------------------------- +namespace QRCode4CS +{ + using System; + using System.Collections.Generic; + + + public class Error : Exception + { + public Error() { } + public Error(string message) : base(message) { } + public Error(string message, Exception inner) : base(message, inner) { } + } + + public enum QRMode : int + { + MODE_NUMBER = 1 << 0, + MODE_ALPHA_NUM = 1 << 1, + MODE_8BIT_BYTE = 1 << 2, + MODE_KANJI = 1 << 3 + } + + public enum QRErrorCorrectLevel : int + { + L = 1, + M = 0, + Q = 3, + H = 2 + } + + public enum QRMaskPattern : int + { + PATTERN000 = 0, + PATTERN001 = 1, + PATTERN010 = 2, + PATTERN011 = 3, + PATTERN100 = 4, + PATTERN101 = 5, + PATTERN110 = 6, + PATTERN111 = 7 + } + + public struct Options + { + public int Width { get; set; } + public int Height { get; set; } + public QRErrorCorrectLevel CorrectLevel { get; set; } + public int TypeNumber { get; set; } + public string Text { get; set; } + + public Options(string text) + : this() + { + Width = 256; + Height = 256; + TypeNumber = 4; + CorrectLevel = QRErrorCorrectLevel.H; + Text = text; + } + } + + internal static class QRUtil + { + internal const int G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0); + internal const int G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0); + internal const int G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1); + internal static readonly int[][] PATTERN_POSITION_TABLE = new int[][] { + new int[] {}, + new int [] {6, 18}, + new int [] {6, 22}, + new int [] {6, 26}, + new int [] {6, 30}, + new int [] {6, 34}, + new int [] {6, 22, 38}, + new int [] {6, 24, 42}, + new int [] {6, 26, 46}, + new int [] {6, 28, 50}, + new int [] {6, 30, 54}, + new int [] {6, 32, 58}, + new int [] {6, 34, 62}, + new int [] {6, 26, 46, 66}, + new int [] {6, 26, 48, 70}, + new int [] {6, 26, 50, 74}, + new int [] {6, 30, 54, 78}, + new int [] {6, 30, 56, 82}, + new int [] {6, 30, 58, 86}, + new int [] {6, 34, 62, 90}, + new int [] {6, 28, 50, 72, 94}, + new int [] {6, 26, 50, 74, 98}, + new int [] {6, 30, 54, 78, 102}, + new int [] {6, 28, 54, 80, 106}, + new int [] {6, 32, 58, 84, 110}, + new int [] {6, 30, 58, 86, 114}, + new int [] {6, 34, 62, 90, 118}, + new int [] {6, 26, 50, 74, 98, 122}, + new int [] {6, 30, 54, 78, 102, 126}, + new int [] {6, 26, 52, 78, 104, 130}, + new int [] {6, 30, 56, 82, 108, 134}, + new int [] {6, 34, 60, 86, 112, 138}, + + new int [] {6, 30, 58, 86, 114, 142}, + new int [] {6, 34, 62, 90, 118, 146}, + new int [] {6, 30, 54, 78, 102, 126, 150}, + new int [] {6, 24, 50, 76, 102, 128, 154}, + new int [] {6, 28, 54, 80, 106, 132, 158}, + new int [] {6, 32, 58, 84, 110, 136, 162}, + new int [] {6, 26, 54, 82, 110, 138, 166}, + new int [] {6, 30, 58, 86, 114, 142, 170} + }; + internal static int GetLengthInBits(QRMode mode, int type) + { + + if (1 <= type && type < 10) + { + + // 1 - 9 + + switch (mode) + { + case QRMode.MODE_NUMBER: return 10; + case QRMode.MODE_ALPHA_NUM: return 9; + case QRMode.MODE_8BIT_BYTE: return 8; + case QRMode.MODE_KANJI: return 8; + default: + throw new Error("mode:" + mode); + } + + } + else if (type < 27) + { + + // 10 - 26 + + switch (mode) + { + case QRMode.MODE_NUMBER: return 12; + case QRMode.MODE_ALPHA_NUM: return 11; + case QRMode.MODE_8BIT_BYTE: return 16; + case QRMode.MODE_KANJI: return 10; + default: + throw new Error("mode:" + mode); + } + + } + else if (type < 41) + { + + // 27 - 40 + + switch (mode) + { + case QRMode.MODE_NUMBER: return 14; + case QRMode.MODE_ALPHA_NUM: return 13; + case QRMode.MODE_8BIT_BYTE: return 16; + case QRMode.MODE_KANJI: return 12; + default: + throw new Error("mode:" + mode); + } + + } + else + { + throw new Error("type:" + type); + } + } + + internal static double GetLostPoint(QRCode qrCode) + { + int moduleCount = qrCode.GetModuleCount(); + double lostPoint = 0; + for (int row = 0; row < moduleCount; row++) + { + + for (int col = 0; col < moduleCount; col++) + { + + var sameCount = 0; + var dark = qrCode.IsDark(row, col); + + for (var r = -1; r <= 1; r++) + { + + if (row + r < 0 || moduleCount <= row + r) + { + continue; + } + + for (var c = -1; c <= 1; c++) + { + + if (col + c < 0 || moduleCount <= col + c) + { + continue; + } + + if (r == 0 && c == 0) + { + continue; + } + + if (dark == qrCode.IsDark((int)((int)row + r), (int)((int)col + c))) + { + sameCount++; + } + } + } + + if (sameCount > 5) + { + lostPoint += (int)(3 + sameCount - 5); + } + } + } + + // LEVEL2 + + for (int row = 0; row < moduleCount - 1; row++) + { + for (int col = 0; col < moduleCount - 1; col++) + { + var count = 0; + if (qrCode.IsDark(row, col)) count++; + if (qrCode.IsDark(row + 1, col)) count++; + if (qrCode.IsDark(row, col + 1)) count++; + if (qrCode.IsDark(row + 1, col + 1)) count++; + if (count == 0 || count == 4) + { + lostPoint += 3; + } + } + } + + // LEVEL3 + + for (int row = 0; row < moduleCount; row++) + { + for (int col = 0; col < moduleCount - 6; col++) + { + if (qrCode.IsDark(row, col) + && !qrCode.IsDark(row, col + 1) + && qrCode.IsDark(row, col + 2) + && qrCode.IsDark(row, col + 3) + && qrCode.IsDark(row, col + 4) + && !qrCode.IsDark(row, col + 5) + && qrCode.IsDark(row, col + 6)) + { + lostPoint += 40; + } + } + } + + for (int col = 0; col < moduleCount; col++) + { + for (int row = 0; row < moduleCount - 6; row++) + { + if (qrCode.IsDark(row, col) + && !qrCode.IsDark(row + 1, col) + && qrCode.IsDark(row + 2, col) + && qrCode.IsDark(row + 3, col) + && qrCode.IsDark(row + 4, col) + && !qrCode.IsDark(row + 5, col) + && qrCode.IsDark(row + 6, col)) + { + lostPoint += 40; + } + } + } + + // LEVEL4 + + int darkCount = 0; + + for (int col = 0; col < moduleCount; col++) + { + for (int row = 0; row < moduleCount; row++) + { + if (qrCode.IsDark(row, col)) + { + darkCount++; + } + } + } + + double ratio = Math.Abs(100.0 * darkCount / moduleCount / moduleCount - 50) / 5; + lostPoint += ratio * 10; + + return lostPoint; + + } + + + + + internal static int GetBCHTypeInfo(int data) + { + int d = (data << 10); + int s = 0; + while ((s = (int)(QRUtil.GetBCHDigit(d) - QRUtil.GetBCHDigit(QRUtil.G15))) >= 0) + { + d ^= (Convert.ToInt32(QRUtil.G15) << s); + } + return (int)((data << 10) | d) ^ QRUtil.G15_MASK; + } + + internal static int GetBCHTypeNumber(int data) + { + int d = data << 12; + while (QRUtil.GetBCHDigit(d) - QRUtil.GetBCHDigit(QRUtil.G18) >= 0) + { + d ^= (QRUtil.G18 << (QRUtil.GetBCHDigit(d) - QRUtil.GetBCHDigit(QRUtil.G18))); + } + return (data << 12) | d; + } + + internal static int GetBCHDigit(int dataInt) + { + + int digit = 0; + uint data = Convert.ToUInt32(dataInt); + while (data != 0) + { + digit++; + data >>= 1; + } + + return digit; + } + + internal static int[] GetPatternPosition(int typeNumber) + { + return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1]; + } + + internal static bool GetMask(QRMaskPattern maskPattern, int i, int j) + { + + switch (maskPattern) + { + + case QRMaskPattern.PATTERN000: return (i + j) % 2 == 0; + case QRMaskPattern.PATTERN001: return i % 2 == 0; + case QRMaskPattern.PATTERN010: return j % 3 == 0; + case QRMaskPattern.PATTERN011: return (i + j) % 3 == 0; + case QRMaskPattern.PATTERN100: return (Math.Floor((double) (i / 2)) + Math.Floor((double) (j / 3))) % 2 == 0; + case QRMaskPattern.PATTERN101: return (i * j) % 2 + (i * j) % 3 == 0; + case QRMaskPattern.PATTERN110: return ((i * j) % 2 + (i * j) % 3) % 2 == 0; + case QRMaskPattern.PATTERN111: return ((i * j) % 3 + (i + j) % 2) % 2 == 0; + + default: + throw new Error("bad maskPattern:" + maskPattern); + } + } + + + + internal static QRPolynomial GetErrorCorrectPolynomial(int errorCorrectLength) + { + QRPolynomial a = new QRPolynomial(new DataCache() { 1 }, 0); + + for (int i = 0; i < errorCorrectLength; i++) + { + a = a.Multiply(new QRPolynomial(new DataCache() { 1, QRMath.GExp(i) }, 0)); + } + + return a; + } + } + + internal struct QRPolynomial + { + private int[] m_num; + public QRPolynomial(DataCache num, int shift) + : this() + { + if (num == null) + { + throw new Error(); + } + + int offset = 0; + + while (offset < num.Count && num[offset] == 0) + { + offset++; + } + + this.m_num = new int[num.Count - offset + shift]; + for (int i = 0; i < num.Count - offset; i++) + { + this.m_num[i] = num[(int)(i + offset)]; + } + } + + public int Get(int index) + { + return this.m_num[(int)index]; + } + + public int GetLength() + { + return (int)this.m_num.Length; + } + + public QRPolynomial Multiply(QRPolynomial e) + { + + var num = new DataCache(this.GetLength() + e.GetLength() - 1); + + for (int i = 0; i < this.GetLength(); i++) + { + for (int j = 0; j < e.GetLength(); j++) + { + num[i + j] ^= QRMath.GExp(QRMath.GLog(this.Get(i)) + QRMath.GLog(e.Get(j))); + } + } + + return new QRPolynomial(num, 0); + } + + public QRPolynomial Mod(QRPolynomial e) + { + + if (Convert.ToInt64(this.GetLength()) - Convert.ToInt64(e.GetLength()) < 0) + { + return this; + } + + int ratio = QRMath.GLog(this.Get(0)) - QRMath.GLog(e.Get(0)); + + var num = new DataCache(this.GetLength()); + + for (int i = 0; i < this.GetLength(); i++) + { + num[i] = this.Get(i); + } + + for (int i = 0; i < e.GetLength(); i++) + { + num[i] ^= QRMath.GExp(QRMath.GLog(e.Get(i)) + ratio); + } + + // recursive call + return new QRPolynomial(num, 0).Mod(e); + } + } + + + internal static class QRMath + { + private static readonly int[] EXP_TABLE; + private static readonly int[] LOG_TABLE; + + static QRMath() + { + EXP_TABLE = new int[256]; + LOG_TABLE = new int[256]; + for (int i = 0; i < 8; i++) + { + QRMath.EXP_TABLE[i] = (int)(1 << (int)i); + } + for (int i = 8; i < 256; i++) + { + QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] + ^ QRMath.EXP_TABLE[i - 5] + ^ QRMath.EXP_TABLE[i - 6] + ^ QRMath.EXP_TABLE[i - 8]; + } + for (int i = 0; i < 255; i++) + { + QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i; + } + } + + internal static int GLog(int n) + { + if (n < 1) + { + throw new Error("glog(" + n + ")"); + } + return QRMath.LOG_TABLE[n]; + } + + internal static int GExp(int n) + { + while (n < 0) + { + n += 255; + } + while (n >= 256) + { + n -= 255; + } + return QRMath.EXP_TABLE[n]; + } + } + + public struct QR8bitByte + { + public QRMode Mode { get; private set; } + private string m_data { get; set; } + + public QR8bitByte(string data) + : this() + { + m_data = data; + Mode = QRMode.MODE_8BIT_BYTE; + } + + public int Length + { + get + { + return m_data.Length; + } + } + + public void Write(QRBitBuffer buffer) + { + for (int i = 0; i < m_data.Length; ++i) + { + //item + buffer.Put(m_data[i], 8); + } + ///buffer = Data; + } + + + } + + internal class DataCache : List + { + public DataCache(int capacity) + : base() + { + for (int i = 0; i < capacity; i++) + { + base.Add(0); + } + } + + public DataCache() + : base() + { + + } + + + } + + internal struct QRRSBlock + { + private static readonly int[][] RS_BLOCK_TABLE = new int[][] { + // L + // M + // Q + // H + + // 1 + new int [] {1, 26, 19}, + new int [] {1, 26, 16}, + new int [] {1, 26, 13}, + new int [] {1, 26, 9}, + + // 2 + new int [] {1, 44, 34}, + new int [] {1, 44, 28}, + new int [] {1, 44, 22}, + new int [] {1, 44, 16}, + + // 3 + new int [] {1, 70, 55}, + new int [] {1, 70, 44}, + new int [] {2, 35, 17}, + new int [] {2, 35, 13}, + + // 4 + new int [] {1, 100, 80}, + new int [] {2, 50, 32}, + new int [] {2, 50, 24}, + new int [] {4, 25, 9}, + + // 5 + new int [] {1, 134, 108}, + new int [] {2, 67, 43}, + new int [] {2, 33, 15, 2, 34, 16}, + new int [] {2, 33, 11, 2, 34, 12}, + + // 6 + new int [] {2, 86, 68}, + new int [] {4, 43, 27}, + new int [] {4, 43, 19}, + new int [] {4, 43, 15}, + + // 7 + new int [] {2, 98, 78}, + new int [] {4, 49, 31}, + new int [] {2, 32, 14, 4, 33, 15}, + new int [] {4, 39, 13, 1, 40, 14}, + + // 8 + new int [] {2, 121, 97}, + new int [] {2, 60, 38, 2, 61, 39}, + new int [] {4, 40, 18, 2, 41, 19}, + new int [] {4, 40, 14, 2, 41, 15}, + + // 9 + new int [] {2, 146, 116}, + new int [] {3, 58, 36, 2, 59, 37}, + new int [] {4, 36, 16, 4, 37, 17}, + new int [] {4, 36, 12, 4, 37, 13}, + + // 10 + new int [] {2, 86, 68, 2, 87, 69}, + new int [] {4, 69, 43, 1, 70, 44}, + new int [] {6, 43, 19, 2, 44, 20}, + new int [] {6, 43, 15, 2, 44, 16} + }; + + + public int DataCount { get; private set; } + public int TotalCount { get; set; } + + public QRRSBlock(int totalCount, int dataCount) + : this() + { + TotalCount = totalCount; + DataCount = dataCount; + } + public static List GetRSBlocks(int typeNumber, QRErrorCorrectLevel errorCorrectLevel) + { + + int[] rsBlock = GetRsBlockTable(typeNumber, errorCorrectLevel); + + if (rsBlock == null) + { + throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel); + } + + int length = (int)rsBlock.Length / 3; + + var list = new List(); + + for (int i = 0; i < length; i++) + { + + int count = rsBlock[i * 3 + 0]; + int totalCount = rsBlock[i * 3 + 1]; + int dataCount = rsBlock[i * 3 + 2]; + + for (int j = 0; j < count; j++) + { + list.Add(new QRRSBlock(totalCount, dataCount)); + } + } + + return list; + } + + private static int[] GetRsBlockTable(int typeNumber, QRErrorCorrectLevel errorCorrectLevel) + { + switch (errorCorrectLevel) + { + case QRErrorCorrectLevel.L: + return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0]; + case QRErrorCorrectLevel.M: + return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1]; + case QRErrorCorrectLevel.Q: + return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2]; + case QRErrorCorrectLevel.H: + return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3]; + default: + return null; + } + } + } + + public class QRCode + { + private const int PAD0 = 0xEC; + private const int PAD1 = 0x11; + private List m_dataList = new List(); + private int m_typeNumber; + private DataCache m_dataCache; + private int m_moduleCount; + private bool?[][] m_modules; + private QRErrorCorrectLevel m_errorCorrectLevel; + public QRCode(Options options) + : this(options.TypeNumber, options.CorrectLevel) + { + AddData(options.Text); + } + + public QRCode(int typeNumber, QRErrorCorrectLevel level) + { + m_typeNumber = typeNumber; + m_errorCorrectLevel = level; + m_dataCache = null; + } + + public void AddData(string data) + { + m_dataCache = null; + m_dataList.Add(new QR8bitByte(data)); + } + + public void Make() + { + MakeImpl(false, GetBestMaskPattern()); + } + + private QRMaskPattern GetBestMaskPattern() + { + double minLostPoint = 0; + QRMaskPattern pattern = 0; + for (int i = 0; i < 8; i++) + { + this.MakeImpl(true, (QRMaskPattern)i); + + double lostPoint = QRUtil.GetLostPoint(this); + + if (i == 0 || minLostPoint > lostPoint) + { + minLostPoint = lostPoint; + pattern = (QRMaskPattern)i; + } + } + + return pattern; + } + + + + private void MakeImpl(bool test, QRMaskPattern maskPattern) + { + m_moduleCount = this.m_typeNumber * 4 + 17; + m_modules = new bool?[m_moduleCount][]; + for (int row = 0; row < m_moduleCount; row++) + { + + m_modules[row] = new bool?[(m_moduleCount)]; + + for (var col = 0; col < m_moduleCount; col++) + { + m_modules[row][col] = null; //(col + row) % 3; + } + } + + this.SetupPositionProbePattern(0, 0); + this.SetupPositionProbePattern(m_moduleCount - 7, 0); + this.SetupPositionProbePattern(0, m_moduleCount - 7); + this.SetupPositionAdjustPattern(); + this.SetupTimingPattern(); + this.setupTypeInfo(test, maskPattern); + + if (m_typeNumber >= 7) + { + this.setupTypeNumber(test); + } + + if (this.m_dataCache == null) + { + this.m_dataCache = CreateData(this.m_typeNumber, this.m_errorCorrectLevel, this.m_dataList); + } + + MapData(this.m_dataCache, maskPattern); + + } + + public bool IsDark(int row, int col) + { + return m_modules[(int)row][(int)col].Value; + } + + private void SetupTimingPattern() + { + for (var r = 8; r < this.m_moduleCount - 8; r++) + { + if (this.m_modules[r][6] != null) + { + continue; + } + this.m_modules[r][6] = (r % 2 == 0); + } + + for (var c = 8; c < this.m_moduleCount - 8; c++) + { + if (this.m_modules[6][c] != null) + { + continue; + } + this.m_modules[6][c] = (c % 2 == 0); + } + } + + private void setupTypeNumber(bool test) + { + var bits = QRUtil.GetBCHTypeNumber(m_typeNumber); + + for (var i = 0; i < 18; i++) + { + var mod = (!test && ((bits >> i) & 1) == 1); + this.m_modules[(int)Math.Floor((double) (i / 3))][i % 3 + this.m_moduleCount - 8 - 3] = mod; + } + + for (var i = 0; i < 18; i++) + { + var mod = (!test && ((bits >> i) & 1) == 1); + this.m_modules[i % 3 + this.m_moduleCount - 8 - 3][(int)Math.Floor((double) (i / 3))] = mod; + } + } + private void SetupPositionAdjustPattern() + { + var pos = QRUtil.GetPatternPosition(m_typeNumber); + + for (var i = 0; i < pos.Length; i++) + { + + for (var j = 0; j < pos.Length; j++) + { + + var row = pos[i]; + var col = pos[j]; + + if (this.m_modules[row][col] != null) + { + continue; + } + + for (var r = -2; r <= 2; r++) + { + + for (var c = -2; c <= 2; c++) + { + + if (r == -2 || r == 2 || c == -2 || c == 2 + || (r == 0 && c == 0)) + { + this.m_modules[row + r][col + c] = true; + } + else + { + this.m_modules[row + r][col + c] = false; + } + } + } + } + } + } + + + private void setupTypeInfo(bool test, QRMaskPattern maskPattern) + { + + var data = ((int)this.m_errorCorrectLevel << 3) | (int)maskPattern; + var bits = QRUtil.GetBCHTypeInfo(data); + + // vertical + for (var i = 0; i < 15; i++) + { + + var mod = (!test && ((bits >> i) & 1) == 1); + + if (i < 6) + { + this.m_modules[i][8] = mod; + } + else if (i < 8) + { + this.m_modules[i + 1][8] = mod; + } + else + { + this.m_modules[this.m_moduleCount - 15 + i][8] = mod; + } + } + + // horizontal + for (var i = 0; i < 15; i++) + { + + var mod = (!test && ((bits >> i) & 1) == 1); + + if (i < 8) + { + this.m_modules[8][this.m_moduleCount - i - 1] = mod; + } + else if (i < 9) + { + this.m_modules[8][15 - i - 1 + 1] = mod; + } + else + { + this.m_modules[8][15 - i - 1] = mod; + } + } + + // fixed module + this.m_modules[this.m_moduleCount - 8][8] = (!test); + + } + + private void MapData(DataCache data, QRMaskPattern maskPattern) + { + + int inc = -1; + int row = (int)this.m_moduleCount - 1; + int bitIndex = 7; + int byteIndex = 0; + + for (var col = this.m_moduleCount - 1; col > 0; col -= 2) + { + + if (col == 6) col--; + + while (true) + { + + for (int c = 0; c < 2; c++) + { + + if (this.m_modules[row][col - c] == null) + { + + bool dark = false; + + if (byteIndex < data.Count) + { + dark = (((Convert.ToUInt32(data[byteIndex]) >> bitIndex) & 1) == 1); + } + + bool mask = QRUtil.GetMask(maskPattern, (int)row, col - c); + + if (mask) + { + dark = !dark; + } + + this.m_modules[row][col - c] = dark; + bitIndex--; + + if (bitIndex == -1) + { + byteIndex++; + bitIndex = 7; + } + } + } + + row += inc; + + if (row < 0 || this.m_moduleCount <= row) + { + row -= inc; + inc = -inc; + break; + } + } + } + + } + + private DataCache CreateData(int typeNumber, QRErrorCorrectLevel errorCorrectLevel, List dataList) + { + List rsBlocks = QRRSBlock.GetRSBlocks(typeNumber, errorCorrectLevel); + + var buffer = new QRBitBuffer(); + + for (int i = 0; i < dataList.Count; i++) + { + QR8bitByte data = dataList[i]; + + buffer.Put((int)data.Mode, 4); + buffer.Put(data.Length, QRUtil.GetLengthInBits(data.Mode, typeNumber)); + data.Write(buffer); + } + + // calc num max data. + int totalDataCount = 0; + for (var i = 0; i < rsBlocks.Count; i++) + { + totalDataCount += rsBlocks[i].DataCount; + } + + if (buffer.GetLengthInBits() > totalDataCount * 8) + { + throw new Error("code length overflow. (" + + buffer.GetLengthInBits() + + ">" + + totalDataCount * 8 + + ")"); + } + + // end code + if (buffer.GetLengthInBits() + 4 <= totalDataCount * 8) + { + buffer.Put(0, 4); + } + + // padding + while (buffer.GetLengthInBits() % 8 != 0) + { + buffer.PutBit(false); + } + + // padding + while (true) + { + + if (buffer.GetLengthInBits() >= totalDataCount * 8) + { + break; + } + buffer.Put(QRCode.PAD0, 8); + + if (buffer.GetLengthInBits() >= totalDataCount * 8) + { + break; + } + buffer.Put(QRCode.PAD1, 8); + } + + return CreateBytes(buffer, rsBlocks); + } + + private DataCache CreateBytes(QRBitBuffer buffer, List rsBlocks) + { + + int offset = 0; + + int maxDcCount = 0; + int maxEcCount = 0; + + var dcdata = new DataCache[(rsBlocks.Count)]; + var ecdata = new DataCache[(rsBlocks.Count)]; + + for (int r = 0; r < rsBlocks.Count; r++) + { + + int dcCount = rsBlocks[(int)r].DataCount; + int ecCount = rsBlocks[(int)r].TotalCount - dcCount; + + maxDcCount = Math.Max(maxDcCount, dcCount); + maxEcCount = Math.Max(maxEcCount, ecCount); + + dcdata[r] = new DataCache(dcCount); + + for (int i = 0; i < dcdata[r].Count; i++) + { + dcdata[r][i] = 0xff & buffer.m_buffer[(int)(i + offset)]; + } + offset += dcCount; + + QRPolynomial rsPoly = QRUtil.GetErrorCorrectPolynomial(ecCount); + QRPolynomial rawPoly = new QRPolynomial(dcdata[r], rsPoly.GetLength() - 1); + + var modPoly = rawPoly.Mod(rsPoly); + ecdata[r] = new DataCache(rsPoly.GetLength() - 1); + for (int i = 0; i < ecdata[r].Count; i++) + { + int modIndex = i + modPoly.GetLength() - (int)ecdata[r].Count; + ecdata[r][i] = (modIndex >= 0) ? modPoly.Get(modIndex) : 0; + } + + } + + int totalCodeCount = 0; + for (int i = 0; i < rsBlocks.Count; i++) + { + totalCodeCount += rsBlocks[(int)i].TotalCount; + } + + var data = new DataCache(totalCodeCount); + int index = 0; + + for (int i = 0; i < maxDcCount; i++) + { + for (int r = 0; r < rsBlocks.Count; r++) + { + if (i < dcdata[r].Count) + { + data[index++] = dcdata[r][i]; + } + } + } + + for (int i = 0; i < maxEcCount; i++) + { + for (int r = 0; r < rsBlocks.Count; r++) + { + if (i < ecdata[r].Count) + { + data[index++] = ecdata[r][i]; + } + } + } + + return data; + + } + private void SetupPositionProbePattern(int row, int col) + { + for (int r = -1; r <= 7; r++) + { + + if (row + r <= -1 || this.m_moduleCount <= row + r) continue; + + for (int c = -1; c <= 7; c++) + { + + if (col + c <= -1 || this.m_moduleCount <= col + c) continue; + + if ((0 <= r && r <= 6 && (c == 0 || c == 6)) + || (0 <= c && c <= 6 && (r == 0 || r == 6)) + || (2 <= r && r <= 4 && 2 <= c && c <= 4)) + { + this.m_modules[row + r][col + c] = true; + } + else + { + this.m_modules[row + r][col + c] = false; + } + } + } + } + + public int GetModuleCount() + { + return this.m_moduleCount; + } + + internal int getBestMaskPattern() + { + + double minLostPoint = 0; + int pattern = 0; + + for (int i = 0; i < 8; i++) + { + + this.MakeImpl(true, (QRMaskPattern)i); + + double lostPoint = QRUtil.GetLostPoint(this); + + if (i == 0 || minLostPoint > lostPoint) + { + minLostPoint = lostPoint; + pattern = i; + } + } + + return pattern; + } + } + + public class QRBitBuffer + { + internal List m_buffer = new List(); + private int m_length = 0; + public bool Get(int index) + { + int bufIndex = Convert.ToInt32(Math.Floor((double) (index / 8))); + return ((Convert.ToUInt32(this.m_buffer[bufIndex]) >> (7 - index % 8)) & 1) == 1; + } + + public void Put(int num, int length) + { + for (var i = 0; i < length; i++) + { + this.PutBit(((Convert.ToUInt32(num) >> (length - i - 1)) & 1) == 1); + } + } + + public int GetLengthInBits() + { + return m_length; + } + + public void PutBit(bool bit) + { + + int bufIndex = (int)Math.Floor((double) (this.m_length / 8)); + if (this.m_buffer.Count <= bufIndex) + { + this.m_buffer.Add(0); + } + + if (bit) + { + this.m_buffer[bufIndex] |= (int)(Convert.ToUInt32(0x80) >> (this.m_length % 8)); + } + this.m_length++; + } + } +} diff --git a/shadowsocks-csharp/View/QRCodeForm.Designer.cs b/shadowsocks-csharp/View/QRCodeForm.Designer.cs index 0a934d71..7162c70b 100755 --- a/shadowsocks-csharp/View/QRCodeForm.Designer.cs +++ b/shadowsocks-csharp/View/QRCodeForm.Designer.cs @@ -28,7 +28,10 @@ /// private void InitializeComponent() { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(QRCodeForm)); this.QRCodeWebBrowser = new System.Windows.Forms.WebBrowser(); + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); this.SuspendLayout(); // // QRCodeWebBrowser @@ -42,22 +45,34 @@ this.QRCodeWebBrowser.Name = "QRCodeWebBrowser"; this.QRCodeWebBrowser.ScriptErrorsSuppressed = true; this.QRCodeWebBrowser.ScrollBarsEnabled = false; - this.QRCodeWebBrowser.Size = new System.Drawing.Size(200, 200); + this.QRCodeWebBrowser.Size = new System.Drawing.Size(201, 203); this.QRCodeWebBrowser.TabIndex = 0; // + // pictureBox1 + // + this.pictureBox1.Location = new System.Drawing.Point(0, 0); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Size = new System.Drawing.Size(205, 205); + this.pictureBox1.TabIndex = 1; + this.pictureBox1.TabStop = false; + // // QRCodeForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoSize = true; this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.ClientSize = new System.Drawing.Size(204, 202); + this.ClientSize = new System.Drawing.Size(205, 205); + this.Controls.Add(this.pictureBox1); this.Controls.Add(this.QRCodeWebBrowser); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.MaximizeBox = false; this.Name = "QRCodeForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "QRCode"; this.Load += new System.EventHandler(this.QRCodeForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); this.ResumeLayout(false); } @@ -65,5 +80,6 @@ #endregion private System.Windows.Forms.WebBrowser QRCodeWebBrowser; + private System.Windows.Forms.PictureBox pictureBox1; } } \ No newline at end of file diff --git a/shadowsocks-csharp/View/QRCodeForm.cs b/shadowsocks-csharp/View/QRCodeForm.cs index 36c2c804..f34d8101 100755 --- a/shadowsocks-csharp/View/QRCodeForm.cs +++ b/shadowsocks-csharp/View/QRCodeForm.cs @@ -1,4 +1,5 @@ -using Shadowsocks.Properties; +using QRCode4CS; +using Shadowsocks.Properties; using System; using System.Collections.Generic; using System.ComponentModel; @@ -21,6 +22,46 @@ namespace Shadowsocks.View InitializeComponent(); } + private void GenQR(string ssconfig) + { + string qrText = ssconfig; + QRCode4CS.QRCode qrCoded = new QRCode4CS.QRCode(6, QRErrorCorrectLevel.M); + qrCoded.AddData(qrText); + qrCoded.Make(); + int blockSize = 5; + Bitmap drawArea = new Bitmap((qrCoded.GetModuleCount() * blockSize), (qrCoded.GetModuleCount() * blockSize)); + for (int row = 0; row < qrCoded.GetModuleCount(); row++) + { + for (int col = 0; col < qrCoded.GetModuleCount(); col++) + { + bool isDark = qrCoded.IsDark(row, col); + if (isDark) + { + for (int y = 0; y < blockSize; y++) + { + int myCol = (blockSize * (col - 1)) + (y + blockSize); + for (int x = 0; x < blockSize; x++) + { + drawArea.SetPixel((blockSize * (row - 1)) + (x + blockSize), myCol, Color.Black); + } + } + } + else + { + for (int y = 0; y < blockSize; y++) + { + int myCol = (blockSize * (col - 1)) + (y + blockSize); + for (int x = 0; x < blockSize; x++) + { + drawArea.SetPixel((blockSize * (row - 1)) + (x + blockSize), myCol, Color.White); + } + } + } + } + } + pictureBox1.Image = drawArea; + } + private string QRCodeHTML(string ssURL) { string html = Resources.qrcode; @@ -46,7 +87,8 @@ namespace Shadowsocks.View private void QRCodeForm_Load(object sender, EventArgs e) { - QRCodeWebBrowser.DocumentText = QRCodeHTML(code); + //QRCodeWebBrowser.DocumentText = QRCodeHTML(code); + GenQR(code); } } } diff --git a/shadowsocks-csharp/View/QRCodeForm.resx b/shadowsocks-csharp/View/QRCodeForm.resx index 5ea0895e..a7094c64 100755 --- a/shadowsocks-csharp/View/QRCodeForm.resx +++ b/shadowsocks-csharp/View/QRCodeForm.resx @@ -117,4 +117,333 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + AAABAAQAEBAAAAEAIABoBAAARgAAACAgAAABACAAqBAAAK4EAAAwMAAAAQAgAKglAABWFQAAAAAAAAEA + IADNEAAA/joAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA1qtqDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAMKDJIvXrm8EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAfxy/w4YpewAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwoMjuMOFJ6Po0a4DAAAAAM+dUxPFijBf3bmEBQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODBkQbMl0ckw4UocsGCIsDAfxz8v30Z/8eN + NTgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADTpmEHzJdHKwAAAADFiS+Fv30a/799Gf+/fRn/v30Z/799 + Gf/Dhil3AAAAAAAAAAAAAAAA4cKUAseNNUPChCWdwIAe8MB+G/zFiS5v0KBWC8GCIc6/fRn/v30Z/799 + Gf+/fRn/woIjswAAAAAAAAAAzZlLGcKEJcy/fRn/v30Z/799Gf+/fRn/v30Z/8SHK5fOm04iwYAf5799 + Gf+/fRn/v30Z/8CAHu7r17cCAAAAAAAAAADXrW4MxYoweMGBIOu/fRn/v30Z/799Gf+/fRn/woQlusqT + QUjAfxz2v30Z/799Gf+/fRn/ypNAMAAAAAAAAAAAAAAAAAAAAADXrW4MxYkueMGAH+u/fRn/v30Z/799 + Gf/BgSHWx4w0e79+Gv6/fRn/v30Z/8OFJ2wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADTpmEMxIgseMGA + H+u/fRn/v30Z/8CAHuvFii++v30Z/799Gf/CgySqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AADPnlMMw4YoeMCAHuu/fRn/wH8d+sKDI/y/fRn/wYEg5wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAADPnlMMw4UneMB/Heu/fRn/v30Z/799Gf/Ml0YmAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADLlUQMwoMkeMB/Heu/fRn/xIcrZAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADSpF4PxYkvf8WJL5AAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADmzKQD/v8AAP5/ + AAD+fwAA/iMAAP4DAADyAwAAgAMAAAABAACAAQAA4AEAAPgBAAD+AQAA/4AAAP/gAAD/+AAA//4AACgA + AAAgAAAAQAAAAAEAIAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1qtqMAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAfx1/zJdHTAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL99 + GX/BgiLj165vEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAwH8cf799Gf/FijCfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAADDhSh/v30Z/8B+G//Ml0dMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAMOFKH+/fRn/v30Z/8KEJePo0a4MAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAw4Uof8OGKOPGjDOD1qxsKAAAAAAAAAAAAAAAAAAA + AADx480Iy5VERMaMNJfFiC3j3bmEFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgwZEYAAAAAAAAAAAAAAAAAAAAAN68 + iBDKlEJcxIcsp8KEJfO/fRn/v30Z/799Gf/JkT1QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA165vIMmQ + O3DEhyq7wYEg+799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/8aLMY8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAy5VEUMOF + KM/Afxz/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/xIgszwAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA06ZhHMqTQHzRolswAAAAAAAA + AADbtn4Yw4Qm3799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf/BgiL/376MDAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADfvowUyZA7aMSILcPAgB7/v30Z/8GC + IfPMmElMAAAAAAAAAADQoFYswoIi8799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799 + Gf/LlkVIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOHClAjNmUpcxIcqr8GBIfu/fRn/v30Z/799 + Gf+/fRn/v30Z/8B/HPvLlkV0AAAAAAAAAADNmUpMwH8c+799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799 + Gf+/fRn/v30Z/8eNNIcAAAAAAAAAAAAAAAAAAAAAAAAAAMyYSUDGizGjwoIj8799Gf+/fRn/v30Z/799 + Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf/JkTyb586oBAAAAADMmEl4v30Z/799Gf+/fRn/v30Z/799 + Gf+/fRn/v30Z/799Gf+/fRn/xIcqwwAAAAAAAAAAAAAAAAAAAAAAAAAAzpxPJMSHKp/Afhz7v30Z/799 + Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf/GizK/2LBzEAAAAADIkDufv30Z/799 + Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf/BgSD369e3CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANet + bjDIjzivwYAf/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf/DhSjX161uKN++ + jATFijDDv30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf/OnE9AAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAADXrW4wyI84r8GAH/+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799 + Gf/CgiLrz55TQN69ihjChCXbv30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/8iPOX8AAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA161uMMiPOK/AgB7/v30Z/799Gf+/fRn/v30Z/799 + Gf+/fRn/v30Z/799Gf/BgSH7y5ZFYM+eUyjCgyTzv30Z/799Gf+/fRn/v30Z/799Gf+/fRn/w4UotwAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANOmYTDGjDOvwIAe/799 + Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf/Afhv/yZE9h82ZS0jAfx37v30Z/799Gf+/fRn/v30Z/799 + Gf/CgyPz9+/iBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AADTpmEwxowzr8CAHv+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/x401r82aTHy/fRr/v30Z/799 + Gf+/fRn/v30Z/799Gf/So104AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA06ZhMMaMM6/Afx3/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/xIYqy8qT + QLO/fRn/v30Z/799Gf+/fRn/v30Z/8eON3QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM+eUzDFiS6vwH8d/799Gf+/fRn/v30Z/799 + Gf+/fRn/xIcq68iPOvO/fRn/v30Z/799Gf+/fRn/xIcqrwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADPnlMwxYkur8B/ + Hf+/fRn/v30Z/799Gf+/fRn/wYEh/799Gf+/fRn/v30Z/799Gf/DhSjvAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAz55TMMWJLq/Afx3/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf/XrW4wAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAMuVRDDDhimvwH8c/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/8eM + NGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADLlUQww4Ypr8B/HP+/fRn/v30Z/799 + Gf+/fRn/xYgtpwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAy5VEMMOG + Ka/Afxz/v30Z/799Gf/EhirnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAANKkXjzHjTa/wH4b/799Gv/ZsXYkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADVqWdAx402v8mSPmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5sykDAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///////9 + /////P////x////8f////D////wf///8PB///eAf//8AH//8AB//jAAP/AYAD+ADAA+AAIAPgABAB+AA + AAf4AAAH/gAAB/+AAAP/4AAD//gAA//+AAP//4AD///gAf//+AH///4B////gf///+D////4/////v// + //8oAAAAMAAAAGAAAAABACAAAAAAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1qxtSNSoZiQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv30ZQMeMNMPp07AEAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv30ZQL99 + Gv/MmElwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAv30ZQL99Gf/BgiHz165vJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAv30ZQL99Gf+/fRn/x4w0w9++jAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyJA7QL99Gf+/fRn/v34a/82ZSnEAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAy5ZFQL99Gf+/fRn/v30Z/8KD + I/TXrnAnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADnzqgDzJdHT8SHK8+/fRn/v30Z/799Gf+/fRn/v30Z/799 + Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf/GizLb2LBzJAAA + AAAAAAAA2K9yQ8KDI/m/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799 + Gf/BgiL/69e3EgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPv38QbVqWZmyI844b9+ + Gv+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799 + Gf+/fRn/xIcr8NWqaEQAAAAAAAAAANOlYWbAgB7+v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799 + Gf+/fRn/v30Z/799Gf+/fRn/z55TTgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA9OnYCNSpZmjIjzjfv30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799 + Gf+/fRn/v30Z/799Gf+/fRn/v30Z/8KDJPvPnVJiAAAAAAAAAADPnVKPv30Z/799Gf+/fRn/v30Z/799 + Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/ypNAjwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADt278G1atqasiOOOG/fRn/v30Z/799Gf+/fRn/v30Z/799 + Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf/AgB7/zZpNifv38Qbz59QDyZA7rr99 + Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/yI850QAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPv38QbVqWZmyI844b9+ + Gv+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30a/8qU + QrHcuIEK6NCsD8WILcq/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/woIj9uTH + nA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA9OnYCNSnY2jGizLfv30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799 + Gf+/fRn/v30Z/799Gf/IjzjS2rR7G969iiXChCXiv30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799 + Gf+/fRn/v30Z/8+dUkEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADnz6kG0qRdasaLMuG/fRn/v30Z/799Gf+/fRn/v30Z/799 + Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/xoox6dCgVy3ZsnY/wYIh9r99Gf+/fRn/v30Z/799 + Gf+/fRn/v30Z/799Gf+/fRn/v30Z/8qUQoUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPfv4gbRoVlmxowz4b99 + Gv+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/8OGKPnQoFdS0qReYMB/ + Hf2/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/8eNNsQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA79/GCNGiWmjGizLfv30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799 + Gf/BgiH/zpxQeM6cUIi/fhr/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/8OGKfXlyqILAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADnz6kG0qRdasaLMuG/fRn/v30Z/799Gf+/fRn/v30Z/799 + Gf+/fRn/v30Z/799Gf+/fRn/v34b/syYSKPLlkW0v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799 + Gf/WrGw9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO/exQbNmkxmxYku4b99 + Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf/LlUTSyZI95L99Gf+/fRn/v30Z/799 + Gf+/fRn/v30Z/799Gf/LlUN8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA586pCM2aTWjFiC3fv30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/yZI+/8SH + K/+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf/GjDO3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADfvowGzpxQasWILeG/fRn/v30Z/799Gf+/fRn/v30Z/799 + Gf+/fRn/v30Z/79+G/+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf/EiCzzAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO/exQbNmkxmxYku4b99 + Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/376NPAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA586pCM2ZS2jDhSjfv30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799 + Gf+/fRn/ypRBbwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADXrm8Gy5VDasOFJ+G/fRn/v30Z/799Gf+/fRn/v30Z/799 + Gf+/fRn/v30Z/799Gf+/fRn/xosxqgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOfOqAbJkj5mw4Yp4b99 + Gf+/fRn/v30Z/799Gf+/fRn/v30Z/799Gf+/fRn/xIcq5/Pn1AIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA376MCMqTQGjDhSjfv30Z/799Gf+/fRn/v30Z/799Gf+/fRn/wIAd/9y5gy8AAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADXrm8Gy5VDasOFJ+G/fRn/v30Z/799Gf+/fRn/v30Z/86b + T2sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN++jAbSo1yAxYov7b99 + Gf+/fRn/v30Z/8iPOaYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA69W2EdGhWX/GijHuv30Z/8SHKt3v3sUCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADt278S0KBXf8eON/DduoUiAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPDgyQ/ZsncMAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA////////AAD///////8AAP//+f///wAA///4////AAD///j///8AAP// + +H///wAA///4P///AAD///g///8AAP//+B///wAA///4D///AAD///gP+f8AAP//+D/A/wAA///5/AD/ + AAD////gAP8AAP///wAA/wAA///4AAB/AAD///gAAH8AAP/8PAAAfwAA/8AeAAA/AAD/AA8AAD8AAPgA + BwAAPwAAwAABgAA/AACAAADAAD8AAMAAAGAAHwAA8AAAMAAfAAD8AAAYAB8AAP8AAAAAHwAA/8AAAAAP + AAD/8AAAAA8AAP/8AAAADwAA//8AAAAPAAD//8AAAAcAAP//8AAABwAA///8AAAHAAD///8AAAcAAP// + /8AABwAA////8AADAAD////8AAMAAP////8AAwAA/////8ABAAD/////8AEAAP/////8AQAA//////8B + AAD//////8AAAP//////8AAA///////8AAD///////8AAP///////wAAiVBORw0KGgoAAAANSUhEUgAA + AQAAAAEACAYAAABccqhmAAAQlElEQVR42u3dP0xcZ7rH8R8riikQoqCYlWzJlijMhcJIWwQrxbqIFkrH + 2Vh2t1bcbBXWXRqL7Z11lcYR6TbC+4cSoi24FdyVIkERBIUlkEBXUyDdEaKYAuncwn69h+M5M+fM+ff+ + +X66WEQ54/D8zvM+553zjkVRJABh+lXTFwCgOQQAEDACAAgYAQAEjAAAAkYAAAEjAICAEQBAwAgAIGAE + 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 + sP8HnX+c8U4DeOMAAAAASUVORK5CYII= + + \ No newline at end of file diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index 45afa2e7..8bf700ea 100755 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -65,6 +65,7 @@ + From 165f016a8251c1e01d70c81fa67a7c2687ef233b Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 03:47:53 +0800 Subject: [PATCH 16/19] refine qrcode form --- shadowsocks-csharp/Data/qrcode.htm | 26 +++++++++++++------------- shadowsocks-csharp/View/ConfigForm.cs | 4 +++- shadowsocks-csharp/View/QRCodeForm.Designer.cs | 1 + 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/shadowsocks-csharp/Data/qrcode.htm b/shadowsocks-csharp/Data/qrcode.htm index 581f3a11..b5fba382 100644 --- a/shadowsocks-csharp/Data/qrcode.htm +++ b/shadowsocks-csharp/Data/qrcode.htm @@ -5,19 +5,19 @@ __QRCODELIB__ - - -
- - - diff --git a/shadowsocks-csharp/Data/qrcode.min.js.gz b/shadowsocks-csharp/Data/qrcode.min.js.gz deleted file mode 100644 index 48de1fc93338099581c838b819610ad49c89737a..0000000000000000000000000000000000000000 GIT binary patch literal 0 KcmV+b0RR6000031 literal 7024 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 O{qY~4uR6HLO#lFpynPD* diff --git a/shadowsocks-csharp/Properties/Resources.Designer.cs b/shadowsocks-csharp/Properties/Resources.Designer.cs index 36db144e..8c4f781e 100755 --- a/shadowsocks-csharp/Properties/Resources.Designer.cs +++ b/shadowsocks-csharp/Properties/Resources.Designer.cs @@ -104,54 +104,5 @@ namespace Shadowsocks.Properties { return ((byte[])(obj)); } } - - /// - /// Looks up a localized string similar to <!doctype html> - ///<html> - ///<head> - ///<script> - /// __QRCODELIB__ - ///</script> - ///<style> - /// html, body, table, div { - /// padding: 0px; - /// margin: 0 !important; - /// } - /// div#qrcode { - /// margin: 5px !important; - /// text-align: center; - /// vertical-align: center; - /// } - /// #qrcode { - /// width:190px; - /// height:190px; - /// } - /// table { - /// width: 100%; - /// height:100%; - /// } - ///</style> - ///</head> - ///<body> - ///<div id="qrcode" name="qrcode"></div> - ///<script type="text/javascript"> - /// function genCode(code) { - /// new QRCode("qrcode" [rest of string was truncated]";. - /// - internal static string qrcode { - get { - return ResourceManager.GetString("qrcode", resourceCulture); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] qrcode_min_js { - get { - object obj = ResourceManager.GetObject("qrcode_min_js", resourceCulture); - return ((byte[])(obj)); - } - } } } diff --git a/shadowsocks-csharp/Properties/Resources.resx b/shadowsocks-csharp/Properties/Resources.resx index 520c1732..14c098ec 100755 --- a/shadowsocks-csharp/Properties/Resources.resx +++ b/shadowsocks-csharp/Properties/Resources.resx @@ -130,10 +130,4 @@ ..\Data\proxy.pac.txt.gz;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - ..\Data\qrcode.htm;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;gb2312 - - - ..\Data\qrcode.min.js.gz;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - \ No newline at end of file diff --git a/shadowsocks-csharp/View/QRCodeForm.Designer.cs b/shadowsocks-csharp/View/QRCodeForm.Designer.cs index f09de916..53037e16 100755 --- a/shadowsocks-csharp/View/QRCodeForm.Designer.cs +++ b/shadowsocks-csharp/View/QRCodeForm.Designer.cs @@ -28,42 +28,40 @@ /// private void InitializeComponent() { - this.QRCodeWebBrowser = new System.Windows.Forms.WebBrowser(); this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.panel1 = new System.Windows.Forms.Panel(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.panel1.SuspendLayout(); this.SuspendLayout(); // - // QRCodeWebBrowser - // - this.QRCodeWebBrowser.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.QRCodeWebBrowser.Location = new System.Drawing.Point(0, 0); - this.QRCodeWebBrowser.Margin = new System.Windows.Forms.Padding(0); - this.QRCodeWebBrowser.MinimumSize = new System.Drawing.Size(20, 20); - this.QRCodeWebBrowser.Name = "QRCodeWebBrowser"; - this.QRCodeWebBrowser.ScriptErrorsSuppressed = true; - this.QRCodeWebBrowser.ScrollBarsEnabled = false; - this.QRCodeWebBrowser.Size = new System.Drawing.Size(201, 203); - this.QRCodeWebBrowser.TabIndex = 0; - // // pictureBox1 // - this.pictureBox1.Location = new System.Drawing.Point(0, 0); + this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill; + this.pictureBox1.Location = new System.Drawing.Point(10, 10); + this.pictureBox1.Margin = new System.Windows.Forms.Padding(0); this.pictureBox1.Name = "pictureBox1"; - this.pictureBox1.Size = new System.Drawing.Size(205, 205); + this.pictureBox1.Size = new System.Drawing.Size(204, 202); + this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; this.pictureBox1.TabIndex = 1; this.pictureBox1.TabStop = false; // + // panel1 + // + this.panel1.Controls.Add(this.pictureBox1); + this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panel1.Location = new System.Drawing.Point(0, 0); + this.panel1.Margin = new System.Windows.Forms.Padding(0); + this.panel1.Name = "panel1"; + this.panel1.Padding = new System.Windows.Forms.Padding(10); + this.panel1.Size = new System.Drawing.Size(224, 222); + this.panel1.TabIndex = 2; + // // QRCodeForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.AutoSize = true; - this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.ClientSize = new System.Drawing.Size(205, 205); - this.Controls.Add(this.pictureBox1); - this.Controls.Add(this.QRCodeWebBrowser); + this.ClientSize = new System.Drawing.Size(224, 222); + this.Controls.Add(this.panel1); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.MaximizeBox = false; this.MinimizeBox = false; @@ -72,13 +70,14 @@ this.Text = "QRCode"; this.Load += new System.EventHandler(this.QRCodeForm_Load); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.panel1.ResumeLayout(false); this.ResumeLayout(false); } #endregion - private System.Windows.Forms.WebBrowser QRCodeWebBrowser; private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.Panel panel1; } } \ No newline at end of file diff --git a/shadowsocks-csharp/View/QRCodeForm.cs b/shadowsocks-csharp/View/QRCodeForm.cs index f34d8101..0a0ec840 100755 --- a/shadowsocks-csharp/View/QRCodeForm.cs +++ b/shadowsocks-csharp/View/QRCodeForm.cs @@ -25,7 +25,7 @@ namespace Shadowsocks.View private void GenQR(string ssconfig) { string qrText = ssconfig; - QRCode4CS.QRCode qrCoded = new QRCode4CS.QRCode(6, QRErrorCorrectLevel.M); + QRCode4CS.QRCode qrCoded = new QRCode4CS.QRCode(6, QRErrorCorrectLevel.H); qrCoded.AddData(qrText); qrCoded.Make(); int blockSize = 5; @@ -62,32 +62,8 @@ namespace Shadowsocks.View pictureBox1.Image = drawArea; } - private string QRCodeHTML(string ssURL) - { - string html = Resources.qrcode; - string qrcodeLib; - - byte[] qrcodeGZ = Resources.qrcode_min_js; - byte[] buffer = new byte[1024 * 1024]; // builtin pac gzip size: maximum 1M - int n; - - using (GZipStream input = new GZipStream(new MemoryStream(qrcodeGZ), - CompressionMode.Decompress, false)) - { - n = input.Read(buffer, 0, buffer.Length); - if (n == 0) - { - throw new IOException("can not decompress qrcode lib"); - } - qrcodeLib = System.Text.Encoding.UTF8.GetString(buffer, 0, n); - } - string result = html.Replace("__QRCODELIB__", qrcodeLib); - return result.Replace("__SSURL__", ssURL); - } - private void QRCodeForm_Load(object sender, EventArgs e) { - //QRCodeWebBrowser.DocumentText = QRCodeHTML(code); GenQR(code); } } diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index 9e7c7553..c1c08d22 100755 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -50,7 +50,7 @@ bin\x86\Release\ - TRACE;SIMPLE_JSON_NO_LINQ_EXPRESSION + TRACE true pdbonly x86 @@ -115,7 +115,6 @@ - SettingsSingleFileGenerator Settings.Designer.cs @@ -128,7 +127,6 @@
- From 1f92b48eaf4a4d4d132ce59f850722574e1d4569 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 04:34:08 +0800 Subject: [PATCH 19/19] update license --- LICENSE.txt | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index bc72404d..7801cdf2 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -84,18 +84,17 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. qrcodejs -------- -https://github.com/davidshimjs/qrcodejs +QRCode for C#4.0 Silverlight is translation of QRCode for JavaScript +https://github.com/jeromeetienne/jquery-qrcode/ -Copyright (c) 2012 davidshimjs +Copyright (c) 2009 Kazuhiko Arase -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: +URL: http://www.d-project.com/ -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +Licensed under the MIT license: + http://www.opensource.org/licenses/mit-license.php -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +The word "QR Code" is registered trademark of +DENSO WAVE INCORPORATED + http://www.denso-wave.com/qrcode/faqpatent-e.html