diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index 5823e448..4111d2b8 100755 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -116,6 +116,14 @@ namespace Shadowsocks.Controller } } + public string GetQRCodeForCurrentServer() + { + Server server = GetCurrentServer(); + string parts = server.method + ":" + server.password + "@" + server.server + ":" + server.server_port; + string base64 = System.Convert.ToBase64String(Encoding.UTF8.GetBytes(parts)); + return "ss://" + base64; + } + private void updateSystemProxy() { if (config.enabled) diff --git a/shadowsocks-csharp/Data/qrcode.htm b/shadowsocks-csharp/Data/qrcode.htm index c792bc35..c8729dba 100644 --- a/shadowsocks-csharp/Data/qrcode.htm +++ b/shadowsocks-csharp/Data/qrcode.htm @@ -1,28 +1,37 @@ - - -
+ + +
\ No newline at end of file + genCode("__SSURL__"); + + + diff --git a/shadowsocks-csharp/Data/qrcode.min.js.gz b/shadowsocks-csharp/Data/qrcode.min.js.gz index 0dbeb459..48de1fc9 100644 Binary files a/shadowsocks-csharp/Data/qrcode.min.js.gz and b/shadowsocks-csharp/Data/qrcode.min.js.gz differ diff --git a/shadowsocks-csharp/Properties/Resources.Designer.cs b/shadowsocks-csharp/Properties/Resources.Designer.cs index 8c4f781e..077a5ff0 100755 --- a/shadowsocks-csharp/Properties/Resources.Designer.cs +++ b/shadowsocks-csharp/Properties/Resources.Designer.cs @@ -104,5 +104,50 @@ namespace Shadowsocks.Properties { return ((byte[])(obj)); } } + + /// + /// Looks up a localized string similar to <!doctype html> + ///<html> + ///<head> + ///<script> + /// __QRCODELIB__ + ///</script> + ///<style> + /// body { + /// padding: 10px; + /// margin: 0; + /// } + /// #qrcode { + /// width:300px; + /// height:300px; + /// } + ///</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]";. + /// + 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 14c098ec..520c1732 100755 --- a/shadowsocks-csharp/Properties/Resources.resx +++ b/shadowsocks-csharp/Properties/Resources.resx @@ -130,4 +130,10 @@ ..\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/ConfigForm.Designer.cs b/shadowsocks-csharp/View/ConfigForm.Designer.cs index 2447e311..6d6f8881 100755 --- a/shadowsocks-csharp/View/ConfigForm.Designer.cs +++ b/shadowsocks-csharp/View/ConfigForm.Designer.cs @@ -63,6 +63,7 @@ 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(); @@ -287,6 +288,7 @@ this.ServersItem, this.menuItem4, this.editPACFileItem, + this.QRCodeItem, this.aboutItem, this.menuItem3, this.quitItem}); @@ -329,18 +331,18 @@ // // aboutItem // - this.aboutItem.Index = 4; + this.aboutItem.Index = 5; this.aboutItem.Text = "About..."; this.aboutItem.Click += new System.EventHandler(this.AboutItem_Click); // // menuItem3 // - this.menuItem3.Index = 5; + this.menuItem3.Index = 6; this.menuItem3.Text = "-"; // // quitItem // - this.quitItem.Index = 6; + this.quitItem.Index = 7; this.quitItem.Text = "&Quit"; this.quitItem.Click += new System.EventHandler(this.Quit_Click); // @@ -394,6 +396,12 @@ 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; @@ -461,6 +469,7 @@ private System.Windows.Forms.MenuItem menuItem4; private System.Windows.Forms.TextBox RemarksTextBox; private System.Windows.Forms.Label label6; + private System.Windows.Forms.MenuItem QRCodeItem; } } diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index 208e683a..174d10fd 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -302,5 +302,10 @@ namespace Shadowsocks.View { IPTextBox.Focus(); } + + private void QRCodeItem_Click(object sender, EventArgs e) + { + new QRCodeForm(controller.GetQRCodeForCurrentServer()).Show(); + } } } diff --git a/shadowsocks-csharp/View/QRCodeForm.Designer.cs b/shadowsocks-csharp/View/QRCodeForm.Designer.cs new file mode 100755 index 00000000..34ca088c --- /dev/null +++ b/shadowsocks-csharp/View/QRCodeForm.Designer.cs @@ -0,0 +1,64 @@ +namespace Shadowsocks.View +{ + partial class QRCodeForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.QRCodeWebBrowser = new System.Windows.Forms.WebBrowser(); + this.SuspendLayout(); + // + // QRCodeWebBrowser + // + this.QRCodeWebBrowser.Dock = System.Windows.Forms.DockStyle.Fill; + this.QRCodeWebBrowser.Location = new System.Drawing.Point(0, 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(184, 182); + this.QRCodeWebBrowser.TabIndex = 0; + // + // QRCodeForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(184, 182); + this.Controls.Add(this.QRCodeWebBrowser); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.Name = "QRCodeForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Load += new System.EventHandler(this.QRCodeForm_Load); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.WebBrowser QRCodeWebBrowser; + } +} \ No newline at end of file diff --git a/shadowsocks-csharp/View/QRCodeForm.cs b/shadowsocks-csharp/View/QRCodeForm.cs new file mode 100755 index 00000000..36c2c804 --- /dev/null +++ b/shadowsocks-csharp/View/QRCodeForm.cs @@ -0,0 +1,52 @@ +using Shadowsocks.Properties; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.IO.Compression; +using System.Text; +using System.Windows.Forms; + +namespace Shadowsocks.View +{ + public partial class QRCodeForm : Form + { + private string code; + + public QRCodeForm(string code) + { + this.code = code; + InitializeComponent(); + } + + 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); + } + } +} diff --git a/shadowsocks-csharp/View/QRCodeForm.resx b/shadowsocks-csharp/View/QRCodeForm.resx new file mode 100755 index 00000000..5ea0895e --- /dev/null +++ b/shadowsocks-csharp/View/QRCodeForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index bc811330..22422445 100755 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -79,8 +79,10 @@ + + @@ -106,6 +108,12 @@ + + Form + + + QRCodeForm.cs + ConfigForm.cs Designer @@ -120,9 +128,13 @@ Resources.resx True + + QRCodeForm.cs + + SettingsSingleFileGenerator Settings.Designer.cs @@ -135,6 +147,7 @@ +