Skip to content

Commit 9644bd9

Browse files
authored
Ensure URI creation is cross platform compatible (#421)
* change URI creation, and resolve Unix tests
1 parent fd53fbb commit 9644bd9

File tree

3 files changed

+99
-54
lines changed

3 files changed

+99
-54
lines changed

src/code/RegisterPSResourceRepository.cs

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class RegisterPSResourceRepository : PSCmdlet
3434
private const string NameParameterSet = "NameParameterSet";
3535
private const string PSGalleryParameterSet = "PSGalleryParameterSet";
3636
private const string RepositoriesParameterSet = "RepositoriesParameterSet";
37+
private Uri _url;
3738

3839
#endregion
3940

@@ -51,25 +52,7 @@ class RegisterPSResourceRepository : PSCmdlet
5152
/// </summary>
5253
[Parameter(Mandatory = true, Position = 1, ParameterSetName = NameParameterSet)]
5354
[ValidateNotNullOrEmpty]
54-
public Uri URL
55-
{
56-
get
57-
{ return _url; }
58-
59-
set
60-
{
61-
if (!Uri.TryCreate(value, string.Empty, out Uri url))
62-
{
63-
var message = string.Format(CultureInfo.InvariantCulture, "The URL provided is not valid: {0}", value);
64-
var ex = new ArgumentException(message);
65-
var moduleManifestNotFound = new ErrorRecord(ex, "InvalidUrl", ErrorCategory.InvalidArgument, null);
66-
ThrowTerminatingError(moduleManifestNotFound);
67-
}
68-
69-
_url = url;
70-
}
71-
}
72-
private Uri _url;
55+
public string URL { get; set; }
7356

7457
/// <summary>
7558
/// When specified, registers PSGallery repository.
@@ -156,9 +139,17 @@ protected override void ProcessRecord()
156139
switch (ParameterSetName)
157140
{
158141
case NameParameterSet:
142+
if (!Utils.TryCreateValidUrl(urlString: URL,
143+
cmdletPassedIn: this,
144+
urlResult: out _url,
145+
errorRecord: out ErrorRecord errorRecord))
146+
{
147+
ThrowTerminatingError(errorRecord);
148+
}
149+
159150
try
160151
{
161-
items.Add(NameParameterSetHelper(Name, URL, Priority, Trusted));
152+
items.Add(NameParameterSetHelper(Name, _url, Priority, Trusted));
162153
}
163154
catch (Exception e)
164155
{
@@ -334,13 +325,12 @@ private PSRepositoryInfo RepoValidationHelper(Hashtable repo)
334325
return null;
335326
}
336327

337-
if (!Uri.TryCreate(repo["URL"].ToString(), UriKind.Absolute, out Uri repoURL))
328+
if (!Utils.TryCreateValidUrl(urlString: repo["Url"].ToString(),
329+
cmdletPassedIn: this,
330+
urlResult: out Uri repoURL,
331+
errorRecord: out ErrorRecord errorRecord))
338332
{
339-
WriteError(new ErrorRecord(
340-
new PSInvalidOperationException("Invalid url, unable to create"),
341-
"InvalidUrlScheme",
342-
ErrorCategory.InvalidArgument,
343-
this));
333+
WriteError(errorRecord);
344334
return null;
345335
}
346336

@@ -372,6 +362,6 @@ private PSRepositoryInfo RepoValidationHelper(Hashtable repo)
372362
}
373363
}
374364

375-
#endregion
365+
#endregion
376366
}
377367
}

src/code/SetPSResourceRepository.cs

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class SetPSResourceRepository : PSCmdlet
2727
private const string NameParameterSet = "NameParameterSet";
2828
private const string RepositoriesParameterSet = "RepositoriesParameterSet";
2929
private const int DefaultPriority = -1;
30+
private Uri _url;
3031
#endregion
3132

3233
#region Parameters
@@ -45,25 +46,7 @@ class SetPSResourceRepository : PSCmdlet
4546
/// </sumamry>
4647
[Parameter(ParameterSetName = NameParameterSet)]
4748
[ValidateNotNullOrEmpty]
48-
public Uri URL
49-
{
50-
get
51-
{ return _url; }
52-
53-
set
54-
{
55-
if (!Uri.TryCreate(value, string.Empty, out Uri url))
56-
{
57-
var message = string.Format(CultureInfo.InvariantCulture, "The URL provided is not a valid url: {0}", value);
58-
var ex = new ArgumentException(message);
59-
var urlErrorRecord = new ErrorRecord(ex, "InvalidUrl", ErrorCategory.InvalidArgument, null);
60-
ThrowTerminatingError(urlErrorRecord);
61-
}
62-
63-
_url = url;
64-
}
65-
}
66-
private Uri _url;
49+
public string URL { get; set; }
6750

6851
/// <summary>
6952
/// Specifies a hashtable of repositories and is used to register multiple repositories at once.
@@ -129,14 +112,23 @@ protected override void BeginProcessing()
129112

130113
protected override void ProcessRecord()
131114
{
115+
if (MyInvocation.BoundParameters.ContainsKey(nameof(URL)))
116+
{
117+
bool isUrlValid = Utils.TryCreateValidUrl(URL, this, out _url, out ErrorRecord errorRecord);
118+
if (!isUrlValid)
119+
{
120+
ThrowTerminatingError(errorRecord);
121+
}
122+
}
123+
132124
List<PSRepositoryInfo> items = new List<PSRepositoryInfo>();
133125

134126
switch(ParameterSetName)
135127
{
136128
case NameParameterSet:
137129
try
138130
{
139-
items.Add(UpdateRepositoryStoreHelper(Name, URL, Priority, Trusted));
131+
items.Add(UpdateRepositoryStoreHelper(Name, _url, Priority, Trusted));
140132
}
141133
catch (Exception e)
142134
{
@@ -243,15 +235,28 @@ private List<PSRepositoryInfo> RepositoriesParameterSetHelper()
243235
private PSRepositoryInfo RepoValidationHelper(Hashtable repo)
244236
{
245237
WriteDebug(String.Format("Parsing through repository: {0}", repo["Name"]));
238+
246239
Uri repoURL = null;
247-
if (repo.ContainsKey("Url") && !Uri.TryCreate(repo["URL"].ToString(), UriKind.Absolute, out repoURL))
240+
if (repo.ContainsKey("Url"))
248241
{
249-
WriteError(new ErrorRecord(
250-
new PSInvalidOperationException("Invalid Url, unable to parse and create Uri"),
251-
"InvalidUrl",
252-
ErrorCategory.InvalidArgument,
253-
this));
254-
return null;
242+
if (String.IsNullOrEmpty(repo["Url"].ToString()))
243+
{
244+
WriteError(new ErrorRecord(
245+
new PSInvalidOperationException("Repository url cannot be null if provided"),
246+
"NullURLForRepositoriesParameterSetUpdate",
247+
ErrorCategory.InvalidArgument,
248+
this));
249+
return null;
250+
}
251+
252+
if (!Utils.TryCreateValidUrl(urlString: repo["Url"].ToString(),
253+
cmdletPassedIn: this,
254+
urlResult: out repoURL,
255+
errorRecord: out ErrorRecord errorRecord))
256+
{
257+
WriteError(errorRecord);
258+
return null;
259+
}
255260
}
256261

257262
bool repoTrusted = false;

src/code/Utils.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using System.Management.Automation.Language;
1212
using System.Runtime.InteropServices;
1313
using NuGet.Versioning;
14+
using System.Globalization;
1415

1516
namespace Microsoft.PowerShell.PowerShellGet.UtilClasses
1617
{
@@ -171,6 +172,55 @@ public static bool TryParseVersionOrVersionRange(
171172
return VersionRange.TryParse(version, out versionRange);
172173
}
173174

175+
#endregion
176+
177+
#region Url methods
178+
179+
public static bool TryCreateValidUrl(
180+
string urlString,
181+
PSCmdlet cmdletPassedIn,
182+
out Uri urlResult,
183+
out ErrorRecord errorRecord
184+
)
185+
{
186+
errorRecord = null;
187+
188+
if (!urlString.StartsWith(Uri.UriSchemeHttps) &&
189+
!urlString.StartsWith(Uri.UriSchemeHttp) &&
190+
!urlString.StartsWith(Uri.UriSchemeFtp))
191+
{
192+
// url string could be of type (potentially) UriSchemeFile or invalid type
193+
// can't check for UriSchemeFile because relative paths don't qualify as UriSchemeFile
194+
try
195+
{
196+
// this is needed for a relative path urlstring. Does not throw error for an absolute path
197+
urlString = cmdletPassedIn.SessionState.Path.GetResolvedPSPathFromPSPath(urlString)[0].Path;
198+
199+
}
200+
catch (Exception)
201+
{
202+
// this should only be reached if the url string is invalid
203+
// i.e www.google.com
204+
var message = string.Format(CultureInfo.InvariantCulture, "The URL provided is not valid: {0} and must be of Uri Scheme: HTTP, HTTPS, FTP or File", urlString);
205+
var ex = new ArgumentException(message);
206+
errorRecord = new ErrorRecord(ex, "InvalidUrl", ErrorCategory.InvalidArgument, null);
207+
urlResult = null;
208+
return false;
209+
}
210+
}
211+
212+
bool tryCreateResult = Uri.TryCreate(urlString, UriKind.Absolute, out urlResult);
213+
if (!tryCreateResult)
214+
{
215+
var message = string.Format(CultureInfo.InvariantCulture, "The URL provided is not valid: {0}", urlString);
216+
var ex = new ArgumentException(message);
217+
errorRecord = new ErrorRecord(ex, "InvalidUrl", ErrorCategory.InvalidArgument, null);
218+
urlResult = null;
219+
}
220+
221+
return tryCreateResult;
222+
}
223+
174224
#endregion
175225

176226
#region Path methods

0 commit comments

Comments
 (0)