Skip to content

Commit a9ed486

Browse files
authored
Covert to https URLs in known domains in release notes, description (#6408)
* Covert to https URLs in known domains in release notes, description * another UT * PR comments
1 parent 5651317 commit a9ed486

15 files changed

Lines changed: 139 additions & 95 deletions

src/NuGetGallery/App_Start/DefaultDependenciesModule.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ protected override void Load(ContainerBuilder builder)
7777

7878
configuration.SecretInjector = secretInjector;
7979

80-
UrlExtensions.SetConfigurationService(configuration);
80+
UrlHelperExtensions.SetConfigurationService(configuration);
8181

8282
builder.RegisterInstance(configuration)
8383
.AsSelf()

src/NuGetGallery/Controllers/PackagesController.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,8 +1211,8 @@ public virtual async Task<ActionResult> Edit(string id, string version)
12111211
model.VersionSelectList = new SelectList(model.PackageVersions.Select(e => new
12121212
{
12131213
text = NuGetVersion.Parse(e.Version).ToFullString() + (e.IsLatestSemVer2 ? " (Latest)" : string.Empty),
1214-
url = UrlExtensions.EditPackage(Url, model.PackageId, e.NormalizedVersion)
1215-
}), "url", "text", UrlExtensions.EditPackage(Url, model.PackageId, model.Version));
1214+
url = UrlHelperExtensions.EditPackage(Url, model.PackageId, e.NormalizedVersion)
1215+
}), "url", "text", UrlHelperExtensions.EditPackage(Url, model.PackageId, model.Version));
12161216

12171217
model.Edit = new EditPackageVersionReadMeRequest();
12181218

src/NuGetGallery/Helpers/HtmlExtensions.cs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,17 +65,27 @@ public static IHtmlString PreFormattedText(this HtmlHelper self, string text)
6565
// Source: https://stackoverflow.com/a/4750468
6666
string anchorEvaluator(Match match)
6767
{
68+
string trimmedEntityValue = string.Empty;
69+
string trimmedAnchorValue = match.Value;
70+
6871
foreach (var trimmedEntity in _trimmedHtmlEntities)
6972
{
7073
if (match.Value.EndsWith(trimmedEntity))
7174
{
7275
// Remove trailing html entity from anchor URL
73-
var trimmedAnchorValue = match.Value.Substring(0, match.Value.Length - trimmedEntity.Length);
74-
return $"<a href=\"{trimmedAnchorValue}\" rel=\"nofollow\">{trimmedAnchorValue}</a>" + trimmedEntity;
76+
trimmedAnchorValue = match.Value.Substring(0, match.Value.Length - trimmedEntity.Length);
77+
trimmedEntityValue = trimmedEntity;
78+
79+
break;
7580
}
7681
}
7782

78-
return $"<a href=\"{match.Value}\" rel=\"nofollow\">{match.Value}</a>";
83+
if (PackageHelper.TryPrepareUrlForRendering(trimmedAnchorValue, out string formattedUri))
84+
{
85+
return $"<a href=\"{formattedUri}\" rel=\"nofollow\">{formattedUri}</a>" + trimmedEntityValue;
86+
}
87+
88+
return match.Value;
7989
}
8090

8191
encodedText = RegexEx.TryReplaceWithTimeout(

src/NuGetGallery/Helpers/PackageHelper.cs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public static bool ShouldRenderUrl(string url, bool secureOnly = false)
2424
{
2525
if (secureOnly)
2626
{
27-
return IsHttpsProtocol(uri);
27+
return uri.IsHttpsProtocol();
2828
}
2929

3030
return uri.Scheme == Uri.UriSchemeHttps
@@ -34,19 +34,35 @@ public static bool ShouldRenderUrl(string url, bool secureOnly = false)
3434
return false;
3535
}
3636

37-
public static bool IsHttpsProtocol(this Uri uri)
37+
/// <summary>
38+
/// If the input uri is http => check if it's a known domain and convert to https.
39+
/// If the input uri is https => leave as is
40+
/// If the input uri is not a valid uri or not http/https => return false
41+
/// </summary>
42+
public static bool TryPrepareUrlForRendering(string uriString, out string readyUriString)
3843
{
39-
return uri.Scheme == Uri.UriSchemeHttps;
40-
}
44+
Uri returnUri = null;
45+
readyUriString = null;
4146

42-
public static bool IsHttpProtocol(this Uri uri)
43-
{
44-
return uri.Scheme == Uri.UriSchemeHttp;
45-
}
47+
if (Uri.TryCreate(uriString, UriKind.Absolute, out var uri))
48+
{
49+
if (uri.IsHttpProtocol() && uri.IsDomainWithHttpsSupport())
50+
{
51+
returnUri = uri.ToHttps();
52+
}
53+
else if (uri.IsHttpsProtocol() || uri.IsHttpProtocol())
54+
{
55+
returnUri = uri;
56+
}
57+
}
4658

47-
public static bool IsGitProtocol(this Uri uri)
48-
{
49-
return uri.Scheme == Constants.GitRepository;
59+
if (returnUri != null)
60+
{
61+
readyUriString = returnUri.ToString();
62+
return true;
63+
}
64+
65+
return false;
5066
}
5167

5268
public static bool IsGitRepositoryType(string repositoryType)
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
6+
namespace NuGetGallery
7+
{
8+
public static class UriExtensions
9+
{
10+
public static bool IsHttpsProtocol(this Uri uri)
11+
{
12+
return uri.Scheme == Uri.UriSchemeHttps;
13+
}
14+
15+
public static bool IsHttpProtocol(this Uri uri)
16+
{
17+
return uri.Scheme == Uri.UriSchemeHttp;
18+
}
19+
20+
public static bool IsGitProtocol(this Uri uri)
21+
{
22+
return uri.Scheme == Constants.GitRepository;
23+
}
24+
25+
public static bool IsDomainWithHttpsSupport(this Uri uri)
26+
{
27+
return IsGitHubUri(uri) || IsCodeplexUri(uri) || IsMicrosoftUri(uri);
28+
}
29+
30+
public static bool IsGitHubUri(this Uri uri)
31+
{
32+
return string.Equals(uri.Host, "www.github.com", StringComparison.OrdinalIgnoreCase) ||
33+
string.Equals(uri.Host, "github.com", StringComparison.OrdinalIgnoreCase);
34+
}
35+
36+
private static bool IsCodeplexUri(this Uri uri)
37+
{
38+
return uri.Authority.EndsWith(".codeplex.com", StringComparison.OrdinalIgnoreCase) ||
39+
string.Equals(uri.Authority, "codeplex.com", StringComparison.OrdinalIgnoreCase);
40+
}
41+
42+
private static bool IsMicrosoftUri(this Uri uri)
43+
{
44+
return uri.Authority.EndsWith(".microsoft.com", StringComparison.OrdinalIgnoreCase) ||
45+
string.Equals(uri.Authority, "microsoft.com", StringComparison.OrdinalIgnoreCase) ||
46+
string.Equals(uri.Authority, "www.asp.net", StringComparison.OrdinalIgnoreCase) ||
47+
string.Equals(uri.Authority, "asp.net", StringComparison.OrdinalIgnoreCase) ||
48+
uri.Authority.EndsWith(".msdn.com", StringComparison.OrdinalIgnoreCase) ||
49+
string.Equals(uri.Authority, "msdn.com", StringComparison.OrdinalIgnoreCase);
50+
}
51+
52+
public static Uri ToHttps(this Uri uri)
53+
{
54+
var uriBuilder = new UriBuilder(uri);
55+
uriBuilder.Scheme = Uri.UriSchemeHttps;
56+
uriBuilder.Port = -1;
57+
58+
return uriBuilder.Uri;
59+
}
60+
}
61+
}

src/NuGetGallery/NuGetGallery.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@
295295
<Compile Include="Helpers\PermissionsHelpers.cs" />
296296
<Compile Include="Helpers\RegexEx.cs" />
297297
<Compile Include="Helpers\RouteUrlTemplate.cs" />
298+
<Compile Include="Helpers\UriExtensions.cs" />
298299
<Compile Include="Infrastructure\Authentication\ApiKeyV3.cs" />
299300
<Compile Include="Infrastructure\Authentication\ApiKeyV4.cs" />
300301
<Compile Include="Infrastructure\Authentication\Base32Encoder.cs" />
@@ -639,6 +640,7 @@
639640
<Compile Include="Configuration\StorageType.cs" />
640641
<Compile Include="Telemetry\UserPackageDeleteEvent.cs" />
641642
<Compile Include="Telemetry\UserPackageDeleteOutcome.cs" />
643+
<Compile Include="UrlHelperExtensions.cs" />
642644
<Compile Include="ViewModels\AddOrganizationViewModel.cs" />
643645
<Compile Include="ViewModels\DeleteOrganizationViewModel.cs" />
644646
<Compile Include="ViewModels\DeleteUserViewModel.cs" />
@@ -1450,7 +1452,6 @@
14501452
<Compile Include="Properties\AssemblyInfo.*.cs" />
14511453
<Compile Include="RequestModels\SubmitPackageRequest.cs" />
14521454
<Compile Include="RouteName.cs" />
1453-
<Compile Include="UrlExtensions.cs" />
14541455
<Compile Include="App_Start\VersionRouteConstraint.cs" />
14551456
<Compile Include="ViewModels\DisplayPackageViewModel.cs" />
14561457
<Compile Include="ViewModels\IPreviousNextPager.cs" />
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
namespace NuGetGallery
1616
{
17-
public static class UrlExtensions
17+
public static class UrlHelperExtensions
1818
{
1919
private const string Area = "area";
2020
private static IGalleryConfigurationService _configuration;

src/NuGetGallery/ViewModels/DependencySetsViewModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public DependencyViewModel(string id, string versionSpec)
6363

6464
if (HttpContext.Current != null)
6565
{
66-
PackageUrl = UrlExtensions.Package(new UrlHelper(HttpContext.Current.Request.RequestContext), id);
66+
PackageUrl = UrlHelperExtensions.Package(new UrlHelper(HttpContext.Current.Request.RequestContext), id);
6767
}
6868
}
6969

src/NuGetGallery/ViewModels/DisplayPackageViewModel.cs

Lines changed: 7 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,11 @@ public DisplayPackageViewModel(Package package, User currentUser, string pushedB
5757
PushedBy = pushedBy;
5858

5959
InitializeRepositoryMetadata(package.RepositoryUrl, package.RepositoryType);
60-
InitializeProjectUrl(package.ProjectUrl);
60+
61+
if (PackageHelper.TryPrepareUrlForRendering(package.ProjectUrl, out string projectUrl))
62+
{
63+
ProjectUrl = projectUrl;
64+
}
6165
}
6266

6367
public bool ValidatingTooLong { get; set; }
@@ -166,17 +170,14 @@ private void InitializeRepositoryMetadata(string repositoryUrl, string repositor
166170
RepositoryUrl = repositoryUrl;
167171
}
168172

169-
if (IsGitHubUri(repoUri))
173+
if (repoUri.IsGitHubUri())
170174
{
171175
RepositoryType = RepositoryKind.GitHub;
172176

173177
// Fix-up git:// to https:// for GitHub URLs (we should add this fix-up to other repos in the future)
174178
if (repoUri.IsGitProtocol())
175179
{
176-
var uri = new UriBuilder(repoUri);
177-
uri.Scheme = Uri.UriSchemeHttps;
178-
179-
RepositoryUrl = uri.ToString();
180+
RepositoryUrl = repoUri.ToHttps().ToString();
180181
}
181182
}
182183
else if (PackageHelper.IsGitRepositoryType(repositoryType))
@@ -186,54 +187,6 @@ private void InitializeRepositoryMetadata(string repositoryUrl, string repositor
186187
}
187188
}
188189

189-
private void InitializeProjectUrl(string projectUrlString)
190-
{
191-
if (Uri.TryCreate(projectUrlString, UriKind.Absolute, out var projectUrl))
192-
{
193-
if (projectUrl.IsHttpProtocol() && IsDomainWithHttpsSupport(projectUrl))
194-
{
195-
var uri = new UriBuilder(projectUrl);
196-
uri.Scheme = Uri.UriSchemeHttps;
197-
uri.Port = -1;
198-
199-
ProjectUrl = uri.ToString();
200-
}
201-
else if (projectUrl.IsHttpsProtocol() || projectUrl.IsHttpProtocol())
202-
{
203-
ProjectUrl = projectUrl.ToString();
204-
}
205-
}
206-
}
207-
208-
private static bool IsDomainWithHttpsSupport(Uri uri)
209-
{
210-
return IsGitHubUri(uri) || IsCodeplexUri(uri) || IsMicrosoftUri(uri);
211-
}
212-
213-
private static bool IsGitHubUri(Uri uri)
214-
{
215-
return string.Equals(uri.Authority, "www.github.com", StringComparison.OrdinalIgnoreCase) ||
216-
string.Equals(uri.Authority, "github.com", StringComparison.OrdinalIgnoreCase) ||
217-
string.Equals(uri.Authority, "www.github.com:443", StringComparison.OrdinalIgnoreCase) ||
218-
string.Equals(uri.Authority, "github.com:443", StringComparison.OrdinalIgnoreCase);
219-
}
220-
221-
private static bool IsCodeplexUri(Uri uri)
222-
{
223-
return uri.Authority.EndsWith(".codeplex.com", StringComparison.OrdinalIgnoreCase) ||
224-
string.Equals(uri.Authority, "codeplex.com", StringComparison.OrdinalIgnoreCase);
225-
}
226-
227-
private static bool IsMicrosoftUri(Uri uri)
228-
{
229-
return uri.Authority.EndsWith(".microsoft.com", StringComparison.OrdinalIgnoreCase) ||
230-
string.Equals(uri.Authority, "microsoft.com", StringComparison.OrdinalIgnoreCase) ||
231-
string.Equals(uri.Authority, "www.asp.net", StringComparison.OrdinalIgnoreCase) ||
232-
string.Equals(uri.Authority, "asp.net", StringComparison.OrdinalIgnoreCase) ||
233-
uri.Authority.EndsWith(".msdn.com", StringComparison.OrdinalIgnoreCase) ||
234-
string.Equals(uri.Authority, "msdn.com", StringComparison.OrdinalIgnoreCase);
235-
}
236-
237190
public enum RepositoryKind
238191
{
239192
Unknown,

tests/NuGetGallery.Facts/Controllers/PackagesControllerFacts.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1634,7 +1634,7 @@ public void DisplaysFullVersionStringAndUsesNormalizedVersionsInUrlsInSelectList
16341634

16351635
foreach (var pkg in _packageRegistration.Packages)
16361636
{
1637-
var valueField = UrlExtensions.DeletePackage(controller.Url, model);
1637+
var valueField = controller.Url.DeletePackage(model);
16381638
var textField = model.NuGetVersion.ToFullString() + (pkg.IsLatestSemVer2 ? " (Latest)" : string.Empty);
16391639

16401640
var selectListItem = model.VersionSelectList
@@ -2081,7 +2081,7 @@ public async Task UsesNormalizedVersionsInUrlsInSelectList(User currentUser, Use
20812081

20822082
foreach (var pkg in packageRegistration.Packages)
20832083
{
2084-
var valueField = UrlExtensions.EditPackage(controller.Url, model.PackageId, pkg.NormalizedVersion);
2084+
var valueField = controller.Url.EditPackage(model.PackageId, pkg.NormalizedVersion);
20852085
var textField = NuGetVersion.Parse(pkg.Version).ToFullString() + (pkg.IsLatestSemVer2 ? " (Latest)" : string.Empty);
20862086

20872087
var selectListItem = model.VersionSelectList

0 commit comments

Comments
 (0)