Skip to content

Commit d2c21b9

Browse files
authored
Escape @s in namespaces in OSS-Health Tool (#434)
1 parent bc0a736 commit d2c21b9

File tree

3 files changed

+29
-12
lines changed

3 files changed

+29
-12
lines changed

src/Shared.CLI/OSSGadget.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ namespace Microsoft.CST.OpenSource
1111
using System.IO;
1212
using System.Linq;
1313
using System.Reflection;
14+
using System.Text.RegularExpressions;
1415
using static Microsoft.CST.OpenSource.Shared.OutputBuilderFactory;
1516

1617
public class OSSGadget : OssGadgetLib
@@ -202,5 +203,22 @@ private static List<string> GetCommonSupportedHelpTextLines()
202203
{
203204
return GetCommonSupportedHelpText().Split(Environment.NewLine).ToList<string>();
204205
}
206+
207+
private static Regex detectUnencodedNamespace = new Regex("pkg:[^/]+/(@)[^/]+/[^/]+");
208+
/// <summary>
209+
/// This method converts an @ specified in a PackageURL namespace to %40 to comply with the PackageURL specification.
210+
/// This is only intended for use from CLI context where the input is provided by an interactive user to the application to reduce confusion.
211+
/// </summary>
212+
/// <returns>The PackageURL with @ converted to %40 if it appears in as the first character in the namespace specification.</returns>
213+
protected static string EscapeAtSymbolInNameSpace(string originalPackageUrlString)
214+
{
215+
MatchCollection matches = detectUnencodedNamespace.Matches(originalPackageUrlString);
216+
if (matches.Any())
217+
{
218+
var indexOfAt = matches.First().Groups[1].Index;
219+
return originalPackageUrlString[0..indexOfAt] + "%40" + originalPackageUrlString[(indexOfAt +1)..];
220+
}
221+
return originalPackageUrlString;
222+
}
205223
}
206224
}

src/oss-download/DownloadTool.cs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,6 @@ static async Task<int> Main(string[] args)
8989
return (int)(await downloadTool.RunAsync(opts.Value));
9090
}
9191
}
92-
93-
private Regex detectUnencodedNamespace = new Regex("pkg:[^/]+/(@)[^/]+/[^/]+");
9492

9593
private async Task<ErrorCode> RunAsync(Options options)
9694
{
@@ -103,14 +101,8 @@ private async Task<ErrorCode> RunAsync(Options options)
103101
// PackageURL requires the @ in a namespace declaration to be escaped
104102
// We find if the namespace contains an @ in the namespace
105103
// And replace it with %40
106-
string? mutableIterationTarget = target;
107-
MatchCollection matches = detectUnencodedNamespace.Matches(target);
108-
if (matches.Any())
109-
{
110-
var indexOfAt = matches.First().Groups[1].Index;
111-
mutableIterationTarget = target[0..indexOfAt] + "%40" + target[(indexOfAt +1)..];
112-
}
113-
PackageURL? purl = new PackageURL(mutableIterationTarget);
104+
string escapedNameSpaceTarget = EscapeAtSymbolInNameSpace(target);
105+
PackageURL? purl = new PackageURL(escapedNameSpaceTarget);
114106
string downloadDirectory = options.DownloadDirectory == "." ? System.IO.Directory.GetCurrentDirectory() : options.DownloadDirectory;
115107
bool useCache = options.UseCache;
116108
PackageDownloader? packageDownloader = new PackageDownloader(purl, ProjectManagerFactory, downloadDirectory, useCache);

src/oss-health/HealthTool.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ namespace Microsoft.CST.OpenSource
1414
using Contracts;
1515
using Microsoft.CST.OpenSource.PackageManagers;
1616
using PackageUrl;
17+
using System.Linq;
18+
using System.Text.RegularExpressions;
1719

1820
public class HealthTool : OSSGadget
1921
{
@@ -113,18 +115,23 @@ private void AppendOutput(IOutputBuilder outputBuilder, PackageURL purl, HealthM
113115
}
114116
}
115117

118+
116119
private async Task RunAsync(Options options)
117120
{
118121
// select output destination and format
119122
SelectOutput(options.OutputFile);
120123
IOutputBuilder outputBuilder = SelectFormat(options.Format ?? OutputFormat.text.ToString());
121124
if (options.Targets is IList<string> targetList && targetList.Count > 0)
122125
{
123-
foreach (string? target in targetList)
126+
foreach (string target in targetList)
124127
{
125128
try
126129
{
127-
PackageURL? purl = new PackageURL(target);
130+
// PackageURL requires the @ in a namespace declaration to be escaped
131+
// We find if the namespace contains an @ in the namespace
132+
// And replace it with %40
133+
string escapedNameSpaceTarget = EscapeAtSymbolInNameSpace(target);
134+
PackageURL? purl = new PackageURL(escapedNameSpaceTarget);
128135
HealthMetrics? healthMetrics = CheckHealth(purl).Result;
129136
if (healthMetrics == null)
130137
{

0 commit comments

Comments
 (0)