diff --git a/QRCoder/PayloadGenerator.cs b/QRCoder/PayloadGenerator.cs index 6275e5be..48336a73 100644 --- a/QRCoder/PayloadGenerator.cs +++ b/QRCoder/PayloadGenerator.cs @@ -2012,6 +2012,7 @@ private void ProcessCommonFields(StringBuilder sb) } string strippedSecret = Secret.Replace(" ", ""); string escapedIssuer = null; + string escapedLabel = null; string label = null; if (!String40Methods.IsNullOrWhiteSpace(Issuer)) @@ -2023,18 +2024,22 @@ private void ProcessCommonFields(StringBuilder sb) escapedIssuer = Uri.EscapeDataString(Issuer); } - if (!String40Methods.IsNullOrWhiteSpace(Label) && Label.Contains(":")) + if (!String40Methods.IsNullOrWhiteSpace(Label)) { - throw new Exception("Label must not have a ':'"); + if (Label.Contains(":")) + { + throw new Exception("Label must not have a ':'"); + } + escapedLabel = Uri.EscapeDataString(Label); } - if (Label != null && Issuer != null) + if (escapedLabel != null && escapedIssuer != null) { - label = Issuer + ":" + Label; + label = escapedIssuer + ":" + escapedLabel; } - else if (Issuer != null) + else if (escapedIssuer != null) { - label = Issuer; + label = escapedIssuer; } if (label != null) diff --git a/QRCoderTests/PayloadGeneratorTests.cs b/QRCoderTests/PayloadGeneratorTests.cs index f4406bb7..2e90e3ce 100644 --- a/QRCoderTests/PayloadGeneratorTests.cs +++ b/QRCoderTests/PayloadGeneratorTests.cs @@ -2656,7 +2656,22 @@ public void one_time_password_generator_time_based_generates_with_standard_optio Label = "test@google.com", }; - pg.ToString().ShouldBe("otpauth://totp/Google:test@google.com?secret=pwq65q55&issuer=Google"); + pg.ToString().ShouldBe("otpauth://totp/Google:test%40google.com?secret=pwq65q55&issuer=Google"); + } + + + [Fact] + [Category("PayloadGenerator/OneTimePassword")] + public void one_time_password_generator_time_based_generates_with_standard_options_escapes_issuer_and_label() + { + var pg = new PayloadGenerator.OneTimePassword + { + Secret = "pwq6 5q55", + Issuer = "Google Google", + Label = "test/test@google.com", + }; + + pg.ToString().ShouldBe("otpauth://totp/Google%20Google:test%2Ftest%40google.com?secret=pwq65q55&issuer=Google%20Google"); } @@ -2673,7 +2688,23 @@ public void one_time_password_generator_hmac_based_generates_with_standard_optio Counter = 500, }; - pg.ToString().ShouldBe("otpauth://hotp/Google:test@google.com?secret=pwq65q55&issuer=Google&counter=500"); + pg.ToString().ShouldBe("otpauth://hotp/Google:test%40google.com?secret=pwq65q55&issuer=Google&counter=500"); + } + + [Fact] + [Category("PayloadGenerator/OneTimePassword")] + public void one_time_password_generator_hmac_based_generates_with_standard_options_escapes_issuer_and_label() + { + var pg = new PayloadGenerator.OneTimePassword + { + Secret = "pwq6 5q55", + Issuer = "Google Google", + Label = "test/test@google.com", + Type = PayloadGenerator.OneTimePassword.OneTimePasswordAuthType.HOTP, + Counter = 500, + }; + + pg.ToString().ShouldBe("otpauth://hotp/Google%20Google:test%2Ftest%40google.com?secret=pwq65q55&issuer=Google%20Google&counter=500"); }