From 06176258ebeb617bd8789d7c838777b2ea40fe0e Mon Sep 17 00:00:00 2001 From: Robin van Poppel Date: Sat, 11 Apr 2020 15:21:07 +0200 Subject: [PATCH] Refactor QR Dialog (#101) * Refactor QR portion * Use UIUtil.ShowDialogAndDestroy * Renamed caption of the form and set a minimal size Co-authored-by: dannoe --- KeeTrayTOTP/KeeTrayTOTP.csproj | 1 - KeeTrayTOTP/Libraries/QRCoder/QRCode.cs | 129 +++------------- KeeTrayTOTP/Libraries/QRCoder/QRCodeData.cs | 142 +----------------- .../Libraries/QRCoder/QRCodeGenerator.cs | 93 ++++-------- .../Libraries/QRCoder/Stream4Methods.cs | 40 ----- KeeTrayTOTP/ShowQR.Designer.cs | 33 ++-- KeeTrayTOTP/ShowQR.cs | 47 ++++-- KeeTrayTOTP/TrayTOTP_Plugin.cs | 11 +- 8 files changed, 104 insertions(+), 392 deletions(-) delete mode 100644 KeeTrayTOTP/Libraries/QRCoder/Stream4Methods.cs diff --git a/KeeTrayTOTP/KeeTrayTOTP.csproj b/KeeTrayTOTP/KeeTrayTOTP.csproj index f00d145..29e911e 100644 --- a/KeeTrayTOTP/KeeTrayTOTP.csproj +++ b/KeeTrayTOTP/KeeTrayTOTP.csproj @@ -103,7 +103,6 @@ ShowQR.cs - diff --git a/KeeTrayTOTP/Libraries/QRCoder/QRCode.cs b/KeeTrayTOTP/Libraries/QRCoder/QRCode.cs index 41f342b..64ff64a 100644 --- a/KeeTrayTOTP/Libraries/QRCoder/QRCode.cs +++ b/KeeTrayTOTP/Libraries/QRCoder/QRCode.cs @@ -22,145 +22,56 @@ 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. */ - -using System.Drawing; -using System.Drawing.Drawing2D; - namespace QRCoder { using System; + using System.Drawing; public sealed class QRCode : IDisposable { - public QRCodeData QrCodeData { get; private set; } - - public void Dispose() - { - this.QrCodeData = null; - } - /// - /// Constructor without params to be used in COM Objects connections - /// - public QRCode() { } + private QRCodeData QrCodeData; + private static readonly SolidBrush darkBrush = new SolidBrush(Color.Black); + private static readonly SolidBrush lightBrush = new SolidBrush(Color.White); public QRCode(QRCodeData data) { this.QrCodeData = data; } - public Bitmap GetGraphic(int pixelsPerModule) - { - return this.GetGraphic(pixelsPerModule, Color.Black, Color.White, true); - } - - public Bitmap GetGraphic(int pixelsPerModule, string darkColorHtmlHex, string lightColorHtmlHex, bool drawQuietZones = true) - { - return this.GetGraphic(pixelsPerModule, ColorTranslator.FromHtml(darkColorHtmlHex), ColorTranslator.FromHtml(lightColorHtmlHex), drawQuietZones); - } - - public Bitmap GetGraphic(int pixelsPerModule, Color darkColor, Color lightColor, bool drawQuietZones = true) + public Bitmap GetGraphic(int pixelsPerModule, bool drawQuietZones = true) { var size = (this.QrCodeData.ModuleMatrix.Count - (drawQuietZones ? 0 : 8)) * pixelsPerModule; var offset = drawQuietZones ? 0 : 4 * pixelsPerModule; var bmp = new Bitmap(size, size); - var gfx = Graphics.FromImage(bmp); - for (var x = 0; x < size + offset; x = x + pixelsPerModule) + using (var gfx = Graphics.FromImage(bmp)) { - for (var y = 0; y < size + offset; y = y + pixelsPerModule) + for (var x = 0; x < size + offset; x += pixelsPerModule) { - var module = this.QrCodeData.ModuleMatrix[(y + pixelsPerModule) / pixelsPerModule - 1][(x + pixelsPerModule) / pixelsPerModule - 1]; - var rect = new Rectangle(x - offset, y - offset, pixelsPerModule, pixelsPerModule); - var brush = module ? new SolidBrush(darkColor) : new SolidBrush(lightColor); - gfx.FillRectangle(brush, rect); - } - } - - gfx.Save(); - return bmp; - } - - public Bitmap GetGraphic(int pixelsPerModule, Color darkColor, Color lightColor, Bitmap icon = null, int iconSizePercent = 15, int iconBorderWidth = 6, bool drawQuietZones = true) - { - var size = (this.QrCodeData.ModuleMatrix.Count - (drawQuietZones ? 0 : 8)) * pixelsPerModule; - var offset = drawQuietZones ? 0 : 4 * pixelsPerModule; - - var bmp = new Bitmap(size, size, System.Drawing.Imaging.PixelFormat.Format24bppRgb); - - var gfx = Graphics.FromImage(bmp); - gfx.InterpolationMode = InterpolationMode.HighQualityBicubic; - gfx.CompositingQuality = CompositingQuality.HighQuality; - gfx.Clear(lightColor); - - var drawIconFlag = icon != null && iconSizePercent > 0 && iconSizePercent <= 100; - - GraphicsPath iconPath = null; - float iconDestWidth = 0, iconDestHeight = 0, iconX = 0, iconY = 0; - - if (drawIconFlag) - { - iconDestWidth = iconSizePercent * bmp.Width / 100f; - iconDestHeight = iconDestWidth * icon.Height / icon.Width; - iconX = (bmp.Width - iconDestWidth) / 2; - iconY = (bmp.Height - iconDestHeight) / 2; - - var centerDest = new RectangleF(iconX - iconBorderWidth, iconY - iconBorderWidth, iconDestWidth + iconBorderWidth * 2, iconDestHeight + iconBorderWidth * 2); - iconPath = this.CreateRoundedRectanglePath(centerDest, iconBorderWidth * 2); - } - - var lightBrush = new SolidBrush(lightColor); - var darkBrush = new SolidBrush(darkColor); - - for (var x = 0; x < size + offset; x = x + pixelsPerModule) - { - for (var y = 0; y < size + offset; y = y + pixelsPerModule) - { - var module = this.QrCodeData.ModuleMatrix[(y + pixelsPerModule) / pixelsPerModule - 1][(x + pixelsPerModule) / pixelsPerModule - 1]; - if (module) + for (var y = 0; y < size + offset; y += pixelsPerModule) { - var r = new Rectangle(x - offset, y - offset, pixelsPerModule, pixelsPerModule); + var module = this.QrCodeData.ModuleMatrix[(y + pixelsPerModule) / pixelsPerModule - 1][(x + pixelsPerModule) / pixelsPerModule - 1]; + var rect = new Rectangle(x - offset, y - offset, pixelsPerModule, pixelsPerModule); + var brush = module ? darkBrush : lightBrush; - if (drawIconFlag) - { - var region = new Region(r); - region.Exclude(iconPath); - gfx.FillRegion(darkBrush, region); - } - else - { - gfx.FillRectangle(darkBrush, r); - } - } - else - { - gfx.FillRectangle(lightBrush, new Rectangle(x - offset, y - offset, pixelsPerModule, pixelsPerModule)); + gfx.FillRectangle(brush, rect); } } - } - if (drawIconFlag) - { - var iconDestRect = new RectangleF(iconX, iconY, iconDestWidth, iconDestHeight); - gfx.DrawImage(icon, iconDestRect, new RectangleF(0, 0, icon.Width, icon.Height), GraphicsUnit.Pixel); + gfx.Save(); } - gfx.Save(); return bmp; } - internal GraphicsPath CreateRoundedRectanglePath(RectangleF rect, int cornerRadius) + public void Dispose() { - var roundedRect = new GraphicsPath(); - roundedRect.AddArc(rect.X, rect.Y, cornerRadius * 2, cornerRadius * 2, 180, 90); - roundedRect.AddLine(rect.X + cornerRadius, rect.Y, rect.Right - cornerRadius * 2, rect.Y); - roundedRect.AddArc(rect.X + rect.Width - cornerRadius * 2, rect.Y, cornerRadius * 2, cornerRadius * 2, 270, 90); - roundedRect.AddLine(rect.Right, rect.Y + cornerRadius * 2, rect.Right, rect.Y + rect.Height - cornerRadius * 2); - roundedRect.AddArc(rect.X + rect.Width - cornerRadius * 2, rect.Y + rect.Height - cornerRadius * 2, cornerRadius * 2, cornerRadius * 2, 0, 90); - roundedRect.AddLine(rect.Right - cornerRadius * 2, rect.Bottom, rect.X + cornerRadius * 2, rect.Bottom); - roundedRect.AddArc(rect.X, rect.Bottom - cornerRadius * 2, cornerRadius * 2, cornerRadius * 2, 90, 90); - roundedRect.AddLine(rect.X, rect.Bottom - cornerRadius * 2, rect.X, rect.Y + cornerRadius * 2); - roundedRect.CloseFigure(); - return roundedRect; + if (this.QrCodeData != null) + { + QrCodeData.Dispose(); + } + + this.QrCodeData = null; } } } diff --git a/KeeTrayTOTP/Libraries/QRCoder/QRCodeData.cs b/KeeTrayTOTP/Libraries/QRCoder/QRCodeData.cs index 70b02ce..982c86b 100644 --- a/KeeTrayTOTP/Libraries/QRCoder/QRCodeData.cs +++ b/KeeTrayTOTP/Libraries/QRCoder/QRCodeData.cs @@ -25,17 +25,14 @@ using System.Collections; using System.Collections.Generic; -using QRCoder.Framework4._0Methods; namespace QRCoder { using System; - using System.IO; - using System.IO.Compression; - public class QRCodeData : IDisposable + public sealed class QRCodeData : IDisposable { - public List ModuleMatrix { get; set; } + public List ModuleMatrix { get; private set; } public QRCodeData(int version) { @@ -47,134 +44,6 @@ public QRCodeData(int version) this.ModuleMatrix.Add(new BitArray(size)); } } - public QRCodeData(byte[] rawData, Compression compressMode) - { - var bytes = new List(rawData); - - //Decompress - if (compressMode.Equals(Compression.Deflate)) - { - using (var input = new MemoryStream(bytes.ToArray())) - { - using (var output = new MemoryStream()) - { - using (var dstream = new DeflateStream(input, CompressionMode.Decompress)) - { - Stream4Methods.CopyTo(dstream, output); - } - bytes = new List(output.ToArray()); - } - } - } - else if (compressMode.Equals(Compression.GZip)) - { - using (var input = new MemoryStream(bytes.ToArray())) - { - using (var output = new MemoryStream()) - { - using (var dstream = new GZipStream(input, CompressionMode.Decompress)) - { - Stream4Methods.CopyTo(dstream, output); - } - bytes = new List(output.ToArray()); - } - } - } - - if (bytes[0] != 0x51 || bytes[1] != 0x52 || bytes[2] != 0x52) - { - throw new Exception("Invalid raw data file. Filetype doesn't match \"QRR\"."); - } - - //Set QR code version - var sideLen = (int)bytes[4]; - bytes.RemoveRange(0, 5); - this.Version = (sideLen - 21 - 8) / 4 + 1; - - //Unpack - var modules = new Queue(); - foreach (var b in bytes) - { - var bArr = new BitArray(new byte[] { b }); - for (int i = 7; i >= 0; i--) - { - modules.Enqueue((b & (1 << i)) != 0); - } - } - - //Build module matrix - this.ModuleMatrix = new List(); - for (int y = 0; y < sideLen; y++) - { - this.ModuleMatrix.Add(new BitArray(sideLen)); - for (int x = 0; x < sideLen; x++) - { - this.ModuleMatrix[y][x] = modules.Dequeue(); - } - } - } - - public byte[] GetRawData(Compression compressMode) - { - var bytes = new List(); - - //Add header - signature ("QRR") - bytes.AddRange(new byte[] { 0x51, 0x52, 0x52, 0x00 }); - - //Add header - rowsize - bytes.Add((byte)ModuleMatrix.Count); - - //Build data queue - var dataQueue = new Queue(); - foreach (var row in ModuleMatrix) - { - foreach (var module in row) - { - dataQueue.Enqueue((bool)module ? 1 : 0); - } - } - for (int i = 0; i < 8 - (ModuleMatrix.Count * ModuleMatrix.Count) % 8; i++) - { - dataQueue.Enqueue(0); - } - - //Process queue - while (dataQueue.Count > 0) - { - byte b = 0; - for (int i = 7; i >= 0; i--) - { - b += (byte)(dataQueue.Dequeue() << i); - } - bytes.Add(b); - } - var rawData = bytes.ToArray(); - - //Compress stream (optional) - if (compressMode.Equals(Compression.Deflate)) - { - using (var output = new MemoryStream()) - { - using (var dstream = new DeflateStream(output, CompressionMode.Compress)) - { - dstream.Write(rawData, 0, rawData.Length); - } - rawData = output.ToArray(); - } - } - else if (compressMode.Equals(Compression.GZip)) - { - using (var output = new MemoryStream()) - { - using (GZipStream gzipStream = new GZipStream(output, CompressionMode.Compress, true)) - { - gzipStream.Write(rawData, 0, rawData.Length); - } - rawData = output.ToArray(); - } - } - return rawData; - } public int Version { get; private set; } @@ -188,12 +57,5 @@ public void Dispose() this.ModuleMatrix = null; this.Version = 0; } - - public enum Compression - { - Uncompressed, - Deflate, - GZip - } } } diff --git a/KeeTrayTOTP/Libraries/QRCoder/QRCodeGenerator.cs b/KeeTrayTOTP/Libraries/QRCoder/QRCodeGenerator.cs index f2b2929..4f04512 100644 --- a/KeeTrayTOTP/Libraries/QRCoder/QRCodeGenerator.cs +++ b/KeeTrayTOTP/Libraries/QRCoder/QRCodeGenerator.cs @@ -31,7 +31,7 @@ namespace QRCoder { - public class QRCodeGenerator : IDisposable + public sealed class QRCodeGenerator : IDisposable { private static readonly char[] numTable = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; private static readonly char[] alphanumEncTable = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', '$', '%', '*', '+', '-', '.', '/', ':' }; @@ -63,7 +63,7 @@ public QRCodeGenerator() this.CreateAlignmentPatternTable(); } - public QRCodeData CreateQrCode(string plainText, ECCLevel eccLevel, bool forceUtf8 = false, bool utf8BOM = false, EciMode eciMode = EciMode.Default, int requestedVersion = -1) + public QRCodeData CreateQrCode(string plainText, ECCLevel eccLevel = QRCodeGenerator.ECCLevel.Q, bool forceUtf8 = false, bool utf8BOM = false, EciMode eciMode = EciMode.Default, int requestedVersion = -1) { EncodingMode encoding = GetEncodingFromPlaintext(plainText, forceUtf8); var codedText = this.PlainTextToBinary(plainText, encoding, eciMode, utf8BOM, forceUtf8); @@ -110,7 +110,7 @@ public QRCodeData CreateQrCode(string plainText, ECCLevel eccLevel, bool forceUt bitString = bitString.Substring(0, dataLength); } - //Calculate error correction words + // Calculate error correction words var codeWordWithECC = new List(); for (var i = 0; i < eccInfo.BlocksInGroup1; i++) { @@ -471,6 +471,7 @@ public static void ReserveVersionAreas(int size, int version, ref List blockedModules) { qrCode.ModuleMatrix[4 * version + 9][8] = true; @@ -612,8 +613,7 @@ public static int Score(ref QRCodeData qrCode) { int score1 = 0, score2 = 0, - score3 = 0, - score4 = 0; + score3 = 0; var size = qrCode.ModuleMatrix.Count; //Penalty 1 @@ -756,7 +756,7 @@ public static int Score(ref QRCodeData qrCode) var percent = (blackModules / (qrCode.ModuleMatrix.Count * qrCode.ModuleMatrix.Count)) * 100; var prevMultipleOf5 = Math.Abs((int)Math.Floor(percent / 5) * 5 - 50) / 5; var nextMultipleOf5 = Math.Abs((int)Math.Floor(percent / 5) * 5 - 45) / 5; - score4 = Math.Min(prevMultipleOf5, nextMultipleOf5) * 10; + var score4 = Math.Min(prevMultipleOf5, nextMultipleOf5) * 10; return score1 + score2 + score3 + score4; } @@ -934,55 +934,42 @@ private int GetCountIndicatorLength(int version, EncodingMode encMode) { if (version < 10) { - if (encMode.Equals(EncodingMode.Numeric)) - { - return 10; - } - else if (encMode.Equals(EncodingMode.Alphanumeric)) - { - return 9; - } - else + switch (encMode) { - return 8; + case EncodingMode.Numeric: + return 10; + case EncodingMode.Alphanumeric: + return 9; + default: + return 8; } } else if (version < 27) { - if (encMode.Equals(EncodingMode.Numeric)) + switch (encMode) { - return 12; - } - else if (encMode.Equals(EncodingMode.Alphanumeric)) - { - return 11; - } - else if (encMode.Equals(EncodingMode.Byte)) - { - return 16; - } - else - { - return 10; + case EncodingMode.Numeric: + return 12; + case EncodingMode.Alphanumeric: + return 11; + case EncodingMode.Byte: + return 16; + default: + return 10; } } else { - if (encMode.Equals(EncodingMode.Numeric)) - { - return 14; - } - else if (encMode.Equals(EncodingMode.Alphanumeric)) - { - return 13; - } - else if (encMode.Equals(EncodingMode.Byte)) - { - return 16; - } - else + switch (encMode) { - return 12; + case EncodingMode.Numeric: + return 14; + case EncodingMode.Alphanumeric: + return 13; + case EncodingMode.Byte: + return 16; + default: + return 12; } } } @@ -1062,27 +1049,14 @@ private string PlainTextToBinaryAlphanumeric(string plainText) return codeText; } - private string PlainTextToBinaryECI(string plainText) - { - var codeText = string.Empty; - foreach (byte _byte in Encoding.GetEncoding("ascii").GetBytes(plainText)) - { - codeText += DecToBin(_byte, 8); - } - return codeText; - } - private string ConvertToIso8859(string value, string Iso = "ISO-8859-2") { Encoding iso = Encoding.GetEncoding(Iso); Encoding utf8 = Encoding.UTF8; byte[] utfBytes = utf8.GetBytes(value); byte[] isoBytes = Encoding.Convert(utf8, iso, utfBytes); -#if !PCL + return iso.GetString(isoBytes); -#else - return iso.GetString(isoBytes, 0, isoBytes.Length); -#endif } private string PlainTextToBinaryByte(string plainText, EciMode eciMode, bool utf8BOM, bool forceUtf8) @@ -1104,8 +1078,6 @@ private string PlainTextToBinaryByte(string plainText, EciMode eciMode, bool utf case EciMode.Iso8859_2: codeBytes = Encoding.GetEncoding("ISO-8859-2").GetBytes(ConvertToIso8859(plainText, "ISO-8859-2")); break; - case EciMode.Default: - case EciMode.Utf8: default: codeBytes = utf8BOM ? Encoding.UTF8.GetPreamble().Concat(Encoding.UTF8.GetBytes(plainText)).ToArray() : Encoding.UTF8.GetBytes(plainText); break; @@ -1536,7 +1508,6 @@ public Polynom() public override string ToString() { var sb = new StringBuilder(); - //this.PolyItems.ForEach(x => sb.Append("a^" + x.Coefficient + "*x^" + x.Exponent + " + ")); foreach (var polyItem in this.PolyItems) { sb.Append("a^" + polyItem.Coefficient + "*x^" + polyItem.Exponent + " + "); diff --git a/KeeTrayTOTP/Libraries/QRCoder/Stream4Methods.cs b/KeeTrayTOTP/Libraries/QRCoder/Stream4Methods.cs deleted file mode 100644 index ad6ac89..0000000 --- a/KeeTrayTOTP/Libraries/QRCoder/Stream4Methods.cs +++ /dev/null @@ -1,40 +0,0 @@ -/* -This file was taken from https://github.com/codebude/QRCoder and is licensed under the MIT license. ---------------------- -The MIT License (MIT) - -Copyright (c) 2013-2015 Raffael Herrmann - -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: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. - */ - -namespace QRCoder.Framework4._0Methods -{ - static class Stream4Methods - { - public static void CopyTo(System.IO.Stream input, System.IO.Stream output) - { - byte[] buffer = new byte[16 * 1024]; - int bytesRead; - while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0) - { - output.Write(buffer, 0, bytesRead); - } - } - } -} diff --git a/KeeTrayTOTP/ShowQR.Designer.cs b/KeeTrayTOTP/ShowQR.Designer.cs index a22afd3..670b4f4 100644 --- a/KeeTrayTOTP/ShowQR.Designer.cs +++ b/KeeTrayTOTP/ShowQR.Designer.cs @@ -34,7 +34,6 @@ private void InitializeComponent() this.UsernameText = new System.Windows.Forms.TextBox(); this.IssuerLabel = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label(); - this.RegenerateButton = new System.Windows.Forms.Button(); ((System.ComponentModel.ISupportInitialize)(this.QROutputPicture)).BeginInit(); this.SuspendLayout(); // @@ -58,6 +57,7 @@ private void InitializeComponent() | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.QROutputPicture.Location = new System.Drawing.Point(12, 118); + this.QROutputPicture.MinimumSize = new System.Drawing.Size(60, 60); this.QROutputPicture.Name = "QROutputPicture"; this.QROutputPicture.Size = new System.Drawing.Size(360, 360); this.QROutputPicture.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; @@ -68,24 +68,26 @@ private void InitializeComponent() // this.IssuerText.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.IssuerText.Location = new System.Drawing.Point(107, 65); + this.IssuerText.Location = new System.Drawing.Point(107, 69); this.IssuerText.Name = "IssuerText"; - this.IssuerText.Size = new System.Drawing.Size(100, 20); + this.IssuerText.Size = new System.Drawing.Size(265, 20); this.IssuerText.TabIndex = 14; + this.IssuerText.TextChanged += new System.EventHandler(this.OnTextChanged); // // UsernameText // this.UsernameText.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.UsernameText.Location = new System.Drawing.Point(107, 92); + this.UsernameText.Location = new System.Drawing.Point(107, 93); this.UsernameText.Name = "UsernameText"; - this.UsernameText.Size = new System.Drawing.Size(100, 20); + this.UsernameText.Size = new System.Drawing.Size(265, 20); this.UsernameText.TabIndex = 15; + this.UsernameText.TextChanged += new System.EventHandler(this.OnTextChanged); // // IssuerLabel // this.IssuerLabel.AutoSize = true; - this.IssuerLabel.Location = new System.Drawing.Point(13, 72); + this.IssuerLabel.Location = new System.Drawing.Point(15, 72); this.IssuerLabel.Name = "IssuerLabel"; this.IssuerLabel.Size = new System.Drawing.Size(64, 13); this.IssuerLabel.TabIndex = 16; @@ -94,29 +96,17 @@ private void InitializeComponent() // label2 // this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(16, 99); + this.label2.Location = new System.Drawing.Point(15, 96); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(73, 13); this.label2.TabIndex = 17; this.label2.Text = "User (Subtitle)"; // - // RegenerateButton - // - this.RegenerateButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.RegenerateButton.Location = new System.Drawing.Point(224, 72); - this.RegenerateButton.Name = "RegenerateButton"; - this.RegenerateButton.Size = new System.Drawing.Size(148, 40); - this.RegenerateButton.TabIndex = 18; - this.RegenerateButton.Text = "&Regenerate"; - this.RegenerateButton.UseVisualStyleBackColor = true; - this.RegenerateButton.Click += new System.EventHandler(this.RegenerateButton_Click); - // // ShowQR // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(384, 490); - this.Controls.Add(this.RegenerateButton); this.Controls.Add(this.label2); this.Controls.Add(this.IssuerLabel); this.Controls.Add(this.UsernameText); @@ -126,11 +116,13 @@ private void InitializeComponent() this.HelpButton = true; this.MaximizeBox = false; this.MinimizeBox = false; + this.MinimumSize = new System.Drawing.Size(200, 330); this.Name = "ShowQR"; this.ShowInTaskbar = false; - this.Text = "ShowQR"; + this.Text = "QR Code"; this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ShowQR_FormClosed); this.Load += new System.EventHandler(this.ShowQR_Load); + this.ResizeEnd += new System.EventHandler(this.OnResizeEnd); ((System.ComponentModel.ISupportInitialize)(this.QROutputPicture)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -143,7 +135,6 @@ private void InitializeComponent() private System.Windows.Forms.PictureBox QROutputPicture; private System.Windows.Forms.Label IssuerLabel; private System.Windows.Forms.Label label2; - private System.Windows.Forms.Button RegenerateButton; public System.Windows.Forms.TextBox IssuerText; public System.Windows.Forms.TextBox UsernameText; } diff --git a/KeeTrayTOTP/ShowQR.cs b/KeeTrayTOTP/ShowQR.cs index 444244b..76e3fbf 100644 --- a/KeeTrayTOTP/ShowQR.cs +++ b/KeeTrayTOTP/ShowQR.cs @@ -7,11 +7,15 @@ namespace KeeTrayTOTP { public partial class ShowQR : Form { - public string Seed { get; set; } + private readonly string seed; - public ShowQR() + public ShowQR(string seed, string issuer, string username) { InitializeComponent(); + + this.seed = seed; + this.IssuerText.Text = issuer; + this.UsernameText.Text = username; } private void ShowQR_Load(object sender, EventArgs e) @@ -23,22 +27,31 @@ private void ShowQR_Load(object sender, EventArgs e) private void GenerateQRCode() { - var code = string.Format("otpauth://totp/{0}:{1}?secret={2}&issuer={0}", Uri.EscapeDataString(IssuerText.Text), - Uri.EscapeDataString(UsernameText.Text), Seed); + + + var code = string.Format("otpauth://totp/{0}:{1}?secret={2}&issuer={0}", Uri.EscapeDataString(IssuerText.Text), Uri.EscapeDataString(UsernameText.Text), this.seed); using (var qrGenerator = new QRCodeGenerator()) { - var qrCodeData = qrGenerator.CreateQrCode(code, QRCodeGenerator.ECCLevel.Q); - var qrCode = new QRCode(qrCodeData); - QROutputPicture.Image = qrCode.GetGraphic(6); + using (var qrCodeData = qrGenerator.CreateQrCode(code)) + { + using (var qrCode = new QRCode(qrCodeData)) + { + // default width = 360, resulting in 6 pixels per module + int pixelsPerModule = Math.Max(3, QROutputPicture.Width / 60); + var oldImage = QROutputPicture.Image; + + QROutputPicture.Image = qrCode.GetGraphic(pixelsPerModule); + + if (oldImage != null) + { + oldImage.Dispose(); + } + } + } } } - private void RegenerateButton_Click(object sender, EventArgs e) - { - GenerateQRCode(); - } - protected override bool ProcessDialogKey(Keys keyData) { if (ModifierKeys == Keys.None && keyData == Keys.Escape) @@ -54,5 +67,15 @@ private void ShowQR_FormClosed(object sender, FormClosedEventArgs e) { GlobalWindowManager.RemoveWindow(this); } + + private void OnTextChanged(object sender, EventArgs e) + { + GenerateQRCode(); + } + + private void OnResizeEnd(object sender, EventArgs e) + { + GenerateQRCode(); + } } } diff --git a/KeeTrayTOTP/TrayTOTP_Plugin.cs b/KeeTrayTOTP/TrayTOTP_Plugin.cs index 2c22364..11f59e9 100644 --- a/KeeTrayTOTP/TrayTOTP_Plugin.cs +++ b/KeeTrayTOTP/TrayTOTP_Plugin.cs @@ -402,14 +402,9 @@ private void OnEntryMenuShowQRClick(object sender, EventArgs e) var rawSeed = this.SeedGet(entry).ReadString(); var cleanSeed = Regex.Replace(rawSeed, @"\s+", ""); - - var showQr = new ShowQR - { - Seed = cleanSeed, - IssuerText = { Text = entry.Strings.Get("Title").ReadString() }, - UsernameText = { Text = entry.Strings.Get("UserName").ReadString() }, - }; - showQr.ShowDialog(); + var issuer = entry.Strings.Get("Title").ReadString(); + var username = entry.Strings.Get("UserName").ReadString(); + UIUtil.ShowDialogAndDestroy(new ShowQR(cleanSeed, issuer, username)); PluginHost.MainWindow.RefreshEntriesList(); }