Skip to content

Commit f0a7865

Browse files
authored
Merge branch 'master' into wpa2
2 parents f74e547 + 56ace43 commit f0a7865

10 files changed

+184
-29
lines changed

.github/workflows/wf-build-release-ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ jobs:
123123
needs: test
124124
runs-on: windows-2019
125125
env:
126-
GH_PKG_SEC: ${{ secrets.GH_PKG_REPO }}
126+
GH_PKG_SEC: ${{ secrets.GITHUB_TOKEN }}
127127
steps:
128128
- name: Download artifacts
129129
uses: actions/download-artifact@v4

.github/workflows/wf-build-release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ jobs:
123123
needs: test
124124
runs-on: windows-2019
125125
env:
126-
GH_PKG_SEC: ${{ secrets.GH_PKG_REPO }}
126+
GH_PKG_SEC: ${{ secrets.GITHUB_TOKEN }}
127127
steps:
128128
- name: Download artifacts
129129
uses: actions/download-artifact@v4

QRCoder/ASCIIQRCode.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public string[] GetLineByLineGraphic(int repeatPerModule, string darkColorString
5252
var lineBuilder = new StringBuilder();
5353
for (var x = 0; x < QrCodeData.ModuleMatrix.Count - quietZonesModifier; x++)
5454
{
55-
var module = QrCodeData.ModuleMatrix[x + quietZonesOffset][((y + verticalNumberOfRepeats) / verticalNumberOfRepeats - 1)+quietZonesOffset];
55+
var module = QrCodeData.ModuleMatrix[((y + verticalNumberOfRepeats) / verticalNumberOfRepeats - 1)+quietZonesOffset][x + quietZonesOffset];
5656
for (var i = 0; i < repeatPerModule; i++)
5757
{
5858
lineBuilder.Append(module ? darkColorString : whiteSpaceString);
@@ -75,4 +75,4 @@ public static string GetQRCode(string plainText, int pixelsPerModule, string dar
7575
return qrCode.GetGraphic(pixelsPerModule, darkColorString, whiteSpaceString, drawQuietZones, endOfLine);
7676
}
7777
}
78-
}
78+
}

QRCoder/PayloadGenerator.cs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2013,6 +2013,7 @@ private void ProcessCommonFields(StringBuilder sb)
20132013
}
20142014
string strippedSecret = Secret.Replace(" ", "");
20152015
string escapedIssuer = null;
2016+
string escapedLabel = null;
20162017
string label = null;
20172018

20182019
if (!String40Methods.IsNullOrWhiteSpace(Issuer))
@@ -2024,18 +2025,22 @@ private void ProcessCommonFields(StringBuilder sb)
20242025
escapedIssuer = Uri.EscapeDataString(Issuer);
20252026
}
20262027

2027-
if (!String40Methods.IsNullOrWhiteSpace(Label) && Label.Contains(":"))
2028+
if (!String40Methods.IsNullOrWhiteSpace(Label))
20282029
{
2029-
throw new Exception("Label must not have a ':'");
2030+
if (Label.Contains(":"))
2031+
{
2032+
throw new Exception("Label must not have a ':'");
2033+
}
2034+
escapedLabel = Uri.EscapeDataString(Label);
20302035
}
20312036

2032-
if (Label != null && Issuer != null)
2037+
if (escapedLabel != null && escapedIssuer != null)
20332038
{
2034-
label = Issuer + ":" + Label;
2039+
label = escapedIssuer + ":" + escapedLabel;
20352040
}
2036-
else if (Issuer != null)
2041+
else if (escapedIssuer != null)
20372042
{
2038-
label = Issuer;
2043+
label = escapedIssuer;
20392044
}
20402045

20412046
if (label != null)

QRCoder/PostscriptQRCode.cs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
1-
#if NETFRAMEWORK || NETSTANDARD2_0 || NET5_0 || NET6_0_WINDOWS
1+
#if !NETSTANDARD1_3
22
using System;
33
using System.Drawing;
44
using static QRCoder.QRCodeGenerator;
55

66
namespace QRCoder
77
{
88

9-
#if NET6_0_WINDOWS
10-
[System.Runtime.Versioning.SupportedOSPlatform("windows")]
11-
#endif
129
public class PostscriptQRCode : AbstractQRCode, IDisposable
1310
{
1411
/// <summary>
@@ -143,9 +140,6 @@ sc sc scale
143140
";
144141
}
145142

146-
#if NET6_0_WINDOWS
147-
[System.Runtime.Versioning.SupportedOSPlatform("windows")]
148-
#endif
149143
public static class PostscriptQRCodeHelper
150144
{
151145
public static string GetQRCode(string plainText, int pointsPerModule, string darkColorHex, string lightColorHex, ECCLevel eccLevel, bool forceUtf8 = false, bool utf8BOM = false, EciMode eciMode = EciMode.Default, int requestedVersion = -1, bool drawQuietZones = true, bool epsFormat = false)
@@ -157,5 +151,4 @@ public static string GetQRCode(string plainText, int pointsPerModule, string dar
157151
}
158152
}
159153
}
160-
161154
#endif

QRCoder/SvgQRCode.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ public SvgLogo(Bitmap iconRasterized, int iconSizePercent = 15, bool fillLogoBac
285285
using (var bitmap = new Bitmap(iconRasterized))
286286
{
287287
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
288-
_logoData = Convert.ToBase64String(ms.GetBuffer(), Base64FormattingOptions.None);
288+
_logoData = Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length, Base64FormattingOptions.None);
289289
}
290290
}
291291
_mediaType = MediaType.PNG;
@@ -312,6 +312,22 @@ public SvgLogo(string iconVectorized, int iconSizePercent = 15, bool fillLogoBac
312312
_isEmbedded = iconEmbedded;
313313
}
314314

315+
/// <summary>
316+
/// Create a logo object to be used in SvgQRCode renderer
317+
/// </summary>
318+
/// <param name="iconRasterized">Logo to be rendered as PNG</param>
319+
/// <param name="iconSizePercent">Degree of percentage coverage of the QR code by the logo</param>
320+
/// <param name="fillLogoBackground">If true, the background behind the logo will be cleaned</param>
321+
public SvgLogo(byte[] iconRasterized, int iconSizePercent = 15, bool fillLogoBackground = true)
322+
{
323+
_iconSizePercent = iconSizePercent;
324+
_logoData = Convert.ToBase64String(iconRasterized, Base64FormattingOptions.None);
325+
_mediaType = MediaType.PNG;
326+
_fillLogoBackground = fillLogoBackground;
327+
_logoRaw = iconRasterized;
328+
_isEmbedded = false;
329+
}
330+
315331
/// <summary>
316332
/// Returns the raw logo's data
317333
/// </summary>

QRCoderTests/AsciiQRCodeRendererTests.cs

Lines changed: 6 additions & 6 deletions
Large diffs are not rendered by default.

QRCoderTests/PayloadGeneratorTests.cs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2669,7 +2669,22 @@ public void one_time_password_generator_time_based_generates_with_standard_optio
26692669
Label = "[email protected]",
26702670
};
26712671

2672-
pg.ToString().ShouldBe("otpauth://totp/Google:[email protected]?secret=pwq65q55&issuer=Google");
2672+
pg.ToString().ShouldBe("otpauth://totp/Google:test%40google.com?secret=pwq65q55&issuer=Google");
2673+
}
2674+
2675+
2676+
[Fact]
2677+
[Category("PayloadGenerator/OneTimePassword")]
2678+
public void one_time_password_generator_time_based_generates_with_standard_options_escapes_issuer_and_label()
2679+
{
2680+
var pg = new PayloadGenerator.OneTimePassword
2681+
{
2682+
Secret = "pwq6 5q55",
2683+
Issuer = "Google Google",
2684+
Label = "test/[email protected]",
2685+
};
2686+
2687+
pg.ToString().ShouldBe("otpauth://totp/Google%20Google:test%2Ftest%40google.com?secret=pwq65q55&issuer=Google%20Google");
26732688
}
26742689

26752690

@@ -2686,7 +2701,23 @@ public void one_time_password_generator_hmac_based_generates_with_standard_optio
26862701
Counter = 500,
26872702
};
26882703

2689-
pg.ToString().ShouldBe("otpauth://hotp/Google:[email protected]?secret=pwq65q55&issuer=Google&counter=500");
2704+
pg.ToString().ShouldBe("otpauth://hotp/Google:test%40google.com?secret=pwq65q55&issuer=Google&counter=500");
2705+
}
2706+
2707+
[Fact]
2708+
[Category("PayloadGenerator/OneTimePassword")]
2709+
public void one_time_password_generator_hmac_based_generates_with_standard_options_escapes_issuer_and_label()
2710+
{
2711+
var pg = new PayloadGenerator.OneTimePassword
2712+
{
2713+
Secret = "pwq6 5q55",
2714+
Issuer = "Google Google",
2715+
Label = "test/[email protected]",
2716+
Type = PayloadGenerator.OneTimePassword.OneTimePasswordAuthType.HOTP,
2717+
Counter = 500,
2718+
};
2719+
2720+
pg.ToString().ShouldBe("otpauth://hotp/Google%20Google:test%2Ftest%40google.com?secret=pwq65q55&issuer=Google%20Google&counter=500");
26902721
}
26912722

26922723

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#if !NETCOREAPP1_1
2+
using QRCoder;
3+
using QRCoderTests.Helpers;
4+
using QRCoderTests.Helpers.XUnitExtenstions;
5+
using Shouldly;
6+
using System;
7+
using System.Drawing;
8+
using System.IO;
9+
using System.Text.RegularExpressions;
10+
using Xunit;
11+
12+
namespace QRCoderTests
13+
{
14+
public class PostscriptQRCodeRendererTests
15+
{
16+
[Fact]
17+
[Category("QRRenderer/PostscriptQRCode")]
18+
public void can_render_postscript_qrcode_simple()
19+
{
20+
//Create QR code
21+
var gen = new QRCodeGenerator();
22+
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.L);
23+
var ps = new PostscriptQRCode(data).GetGraphic(5);
24+
25+
var result = HelperFunctions.StringToHash(RemoveCreationDate(ps));
26+
result.ShouldBe("06b90d1e64bf022a248453e5f91101a0");
27+
}
28+
29+
[Fact]
30+
[Category("QRRenderer/PostscriptQRCode")]
31+
public void can_render_postscript_qrcode_eps()
32+
{
33+
//Create QR code
34+
var gen = new QRCodeGenerator();
35+
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.L);
36+
var ps = new PostscriptQRCode(data).GetGraphic(5, true);
37+
38+
var result = HelperFunctions.StringToHash(RemoveCreationDate(ps));
39+
result.ShouldBe("50f6152cdb0b685595d80e7888712d3b");
40+
}
41+
42+
[Fact]
43+
[Category("QRRenderer/PostscriptQRCode")]
44+
public void can_render_postscript_qrcode_size()
45+
{
46+
//Create QR code
47+
var gen = new QRCodeGenerator();
48+
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.L);
49+
var ps = new PostscriptQRCode(data).GetGraphic(new Size(33, 33));
50+
51+
var result = HelperFunctions.StringToHash(RemoveCreationDate(ps));
52+
result.ShouldBe("49c7faaafef312eb4b6ea1fec195e63d");
53+
}
54+
55+
[Fact]
56+
[Category("QRRenderer/PostscriptQRCode")]
57+
public void can_render_postscript_qrcode_size_no_quiet_zones()
58+
{
59+
//Create QR code
60+
var gen = new QRCodeGenerator();
61+
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.L);
62+
var ps = new PostscriptQRCode(data).GetGraphic(new Size(50, 50), false);
63+
64+
var result = HelperFunctions.StringToHash(RemoveCreationDate(ps));
65+
result.ShouldBe("9bfa0468e125d9815a39902133a10762");
66+
}
67+
68+
[Fact]
69+
[Category("QRRenderer/PostscriptQRCode")]
70+
public void can_render_postscript_qrcode_colors()
71+
{
72+
//Create QR code
73+
var gen = new QRCodeGenerator();
74+
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.L);
75+
var ps = new PostscriptQRCode(data).GetGraphic(5, Color.Red, Color.Blue);
76+
77+
var result = HelperFunctions.StringToHash(RemoveCreationDate(ps));
78+
result.ShouldBe("2e001d7f67a446eb1b5df32ff5321808");
79+
}
80+
81+
private static string RemoveCreationDate(string text)
82+
{
83+
// Regex pattern to match lines that start with %%CreationDate: followed by any characters until the end of the line
84+
string pattern = @"%%CreationDate:.*\r?\n?";
85+
86+
// Use Regex.Replace to remove matching lines
87+
return Regex.Replace(text, pattern, string.Empty, RegexOptions.Multiline);
88+
}
89+
}
90+
}
91+
#endif

QRCoderTests/SvgQRCodeRendererTests.cs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ public void can_render_svg_qrcode_without_quietzones_hex()
106106
#if NETFRAMEWORK || NETSTANDARD2_0 || NET5_0 || NET6_0_WINDOWS
107107
[Fact]
108108
[Category("QRRenderer/SvgQRCode")]
109-
public void can_render_svg_qrcode_with_png_logo()
109+
public void can_render_svg_qrcode_with_png_logo_bitmap()
110110
{
111111
//Create QR code
112112
var gen = new QRCodeGenerator();
@@ -120,10 +120,29 @@ public void can_render_svg_qrcode_with_png_logo()
120120
var svg = new SvgQRCode(data).GetGraphic(10, Color.DarkGray, Color.White, logo: logoObj);
121121

122122
var result = HelperFunctions.StringToHash(svg);
123-
result.ShouldBe("78e02e8ba415f15817d5ed88c4afca31");
123+
result.ShouldBe("78e02e8ba415f15817d5ed88c4afca31");
124124
}
125125
#endif
126126

127+
[Fact]
128+
[Category("QRRenderer/SvgQRCode")]
129+
public void can_render_svg_qrcode_with_png_logo_bytearray()
130+
{
131+
//Create QR code
132+
var gen = new QRCodeGenerator();
133+
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H);
134+
135+
//Used logo is licensed under public domain. Ref.: https://thenounproject.com/Iconathon1/collection/redefining-women/?i=2909346
136+
var logoBitmap = System.IO.File.ReadAllBytes(GetAssemblyPath() + "\\assets\\noun_software engineer_2909346.png");
137+
var logoObj = new SvgQRCode.SvgLogo(iconRasterized: logoBitmap, 15);
138+
logoObj.GetMediaType().ShouldBe<SvgQRCode.SvgLogo.MediaType>(SvgQRCode.SvgLogo.MediaType.PNG);
139+
140+
var svg = new SvgQRCode(data).GetGraphic(10, Color.DarkGray, Color.White, logo: logoObj);
141+
142+
var result = HelperFunctions.StringToHash(svg);
143+
result.ShouldBe("7d53f25af04e52b20550deb2e3589e96");
144+
}
145+
127146
[Fact]
128147
[Category("QRRenderer/SvgQRCode")]
129148
public void can_render_svg_qrcode_with_svg_logo_embedded()

0 commit comments

Comments
 (0)