Skip to content

Commit 5019705

Browse files
authored
Merge pull request #8050 from NuGet/master
[ReleasePrep][2020.06.15]FI of master into dev
2 parents 0f52bc9 + eb15a10 commit 5019705

12 files changed

Lines changed: 146 additions & 55 deletions

File tree

src/Bootstrap/dist/css/bootstrap-theme.css

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Bootstrap/less/theme/base.less

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,11 @@ body {
230230
&.banner-info {
231231
background: @info-bg;
232232
}
233+
234+
&.banner-blm {
235+
background-color: #000;
236+
color: #fff;
237+
}
233238
}
234239

235240
.alert {

src/NuGetGallery/Controllers/AuthenticationController.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Net.Mail;
1010
using System.Security.Claims;
1111
using System.Threading.Tasks;
12+
using System.Web;
1213
using System.Web.Mvc;
1314
using NuGet.Services.Entities;
1415
using NuGet.Services.Messaging.Email;
@@ -527,7 +528,7 @@ public virtual async Task<ActionResult> LinkOrChangeExternalCredential(string re
527528
// The identity value contains cookie non-compliant characters like `<, >`(eg: John Doe <[email protected]>),
528529
// These need to be replaced so that they are not treated as HTML tags
529530
TempData["RawErrorMessage"] = string.Format(Strings.ChangeCredential_Failed,
530-
newCredential.Identity.Replace("<", "&lt;").Replace(">", "&gt;"),
531+
HttpUtility.HtmlEncode(newCredential.Identity),
531532
UriExtensions.GetExternalUrlAnchorTag("FAQs page", GalleryConstants.FAQLinks.MSALinkedToAnotherAccount));
532533
}
533534

src/NuGetGallery/Helpers/HtmlExtensions.cs

Lines changed: 69 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Diagnostics;
77
using System.Linq;
88
using System.Linq.Expressions;
9+
using System.Text;
910
using System.Text.RegularExpressions;
1011
using System.Web;
1112
using System.Web.Mvc;
@@ -60,21 +61,34 @@ public static IHtmlString BreakWord(this HtmlHelper self, string text)
6061

6162
public static IHtmlString PreFormattedText(this HtmlHelper self, string text, IGalleryConfigurationService configurationService)
6263
{
63-
// Encode HTML entities. Important! Security!
64-
var encodedText = HttpUtility.HtmlEncode(text);
65-
// Turn HTTP and HTTPS URLs into links.
66-
// Source: https://stackoverflow.com/a/4750468
67-
string anchorEvaluator(Match match)
64+
void appendText(StringBuilder builder, string inputText)
65+
{
66+
var encodedText = HttpUtility.HtmlEncode(inputText);
67+
68+
// Replace new lines with the <br /> tag.
69+
encodedText = encodedText.Replace("\n", "<br />");
70+
71+
// Replace more than one space in a row with a space then &nbsp;.
72+
encodedText = RegexEx.TryReplaceWithTimeout(
73+
encodedText,
74+
" +",
75+
match => " " + string.Join(string.Empty, Enumerable.Repeat("&nbsp;", match.Value.Length - 1)),
76+
RegexOptions.None);
77+
78+
builder.Append(encodedText);
79+
}
80+
81+
void appendUrl(StringBuilder builder, string inputText)
6882
{
6983
string trimmedEntityValue = string.Empty;
70-
string trimmedAnchorValue = match.Value;
84+
string trimmedAnchorValue = inputText;
7185

7286
foreach (var trimmedEntity in _trimmedHtmlEntities)
7387
{
74-
if (match.Value.EndsWith(trimmedEntity))
88+
if (inputText.EndsWith(trimmedEntity))
7589
{
7690
// Remove trailing html entity from anchor URL
77-
trimmedAnchorValue = match.Value.Substring(0, match.Value.Length - trimmedEntity.Length);
91+
trimmedAnchorValue = inputText.Substring(0, inputText.Length - trimmedEntity.Length);
7892
trimmedEntityValue = trimmedEntity;
7993

8094
break;
@@ -85,36 +99,67 @@ string anchorEvaluator(Match match)
8599
{
86100
string anchorText = formattedUri;
87101
string siteRoot = configurationService.GetSiteRoot(useHttps: true);
102+
88103
// Format links to NuGet packages
89-
Match packageMatch = RegexEx.MatchWithTimeout(formattedUri, $@"({Regex.Escape(siteRoot)}\/packages\/(?<name>\w+([_.-]\w+)*(\/[0-9a-zA-Z-.]+)?)\/?$)", RegexOptions.IgnoreCase);
104+
Match packageMatch = RegexEx.MatchWithTimeout(
105+
formattedUri,
106+
$@"({Regex.Escape(siteRoot)}\/packages\/(?<name>\w+([_.-]\w+)*(\/[0-9a-zA-Z-.]+)?)\/?$)",
107+
RegexOptions.IgnoreCase);
90108
if (packageMatch != null && packageMatch.Groups["name"].Success)
91109
{
92110
anchorText = packageMatch.Groups["name"].Value;
93111
}
94112

95-
return $"<a href=\"{formattedUri}\" rel=\"nofollow\">{anchorText}</a>" + trimmedEntityValue;
113+
builder.AppendFormat(
114+
"<a href=\"{0}\" rel=\"nofollow\">{1}</a>{2}",
115+
HttpUtility.HtmlEncode(formattedUri),
116+
HttpUtility.HtmlEncode(anchorText),
117+
HttpUtility.HtmlEncode(trimmedEntityValue));
118+
}
119+
else
120+
{
121+
builder.Append(HttpUtility.HtmlEncode(inputText));
96122
}
97-
98-
return match.Value;
99123
}
100124

101-
encodedText = RegexEx.TryReplaceWithTimeout(
102-
encodedText,
125+
// Turn HTTP and HTTPS URLs into links.
126+
// Source: https://stackoverflow.com/a/4750468
127+
var matches = RegexEx.MatchesWithTimeout(
128+
text,
103129
@"((http|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?)",
104-
anchorEvaluator,
105130
RegexOptions.IgnoreCase);
106131

107-
// Replace new lines with the <br /> tag.
108-
encodedText = encodedText.Replace("\n", "<br />");
132+
var output = new StringBuilder(text.Length);
133+
var currentIndex = 0;
134+
135+
if (matches != null && matches.Count > 0)
136+
{
137+
foreach (Match match in matches)
138+
{
139+
// Encode the text literal before the URL, if any.
140+
var literalLength = match.Index - currentIndex;
141+
if (literalLength > 0)
142+
{
143+
var literal = text.Substring(currentIndex, literalLength);
144+
appendText(output, literal);
145+
}
146+
147+
// Encode the URL.
148+
var url = match.Value;
149+
appendUrl(output, url);
150+
151+
currentIndex = match.Index + match.Length;
152+
}
153+
}
109154

110-
// Replace more than one space in a row with a space then &nbsp;.
111-
encodedText = RegexEx.TryReplaceWithTimeout(
112-
encodedText,
113-
" +",
114-
match => " " + string.Join(string.Empty, Enumerable.Repeat("&nbsp;", match.Value.Length - 1)),
115-
RegexOptions.None);
155+
// Encode the text literal appearing after the last URL, if any.
156+
if (currentIndex < text.Length)
157+
{
158+
var literal = text.Substring(currentIndex, text.Length - currentIndex);
159+
appendText(output, literal);
160+
}
116161

117-
return self.Raw(encodedText);
162+
return self.Raw(output.ToString());
118163
}
119164

120165
public static IHtmlString ValidationSummaryFor(this HtmlHelper html, string key)

src/NuGetGallery/Helpers/RegexEx.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,20 @@ public static Match MatchWithTimeout(
4040
return null;
4141
}
4242
}
43+
44+
public static MatchCollection MatchesWithTimeout(
45+
string input,
46+
string pattern,
47+
RegexOptions options)
48+
{
49+
try
50+
{
51+
return Regex.Matches(input, pattern, options, Timeout);
52+
}
53+
catch (RegexMatchTimeoutException)
54+
{
55+
return null;
56+
}
57+
}
4358
}
4459
}

src/NuGetGallery/Views/Organizations/ManageOrganization.cshtml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@
101101

102102
@section BottomScripts {
103103
<script type="text/javascript">
104-
var initialData = @Html.Raw(JsonConvert.SerializeObject(new
104+
var initialData = @Html.ToJson(new
105105
{
106106
AccountName = Model.AccountName,
107107
Members = Model.Members.Select(m => new
@@ -117,7 +117,7 @@
117117
UpdateMemberUrl = Url.UpdateOrganizationMember(Model.AccountName),
118118
DeleteMemberUrl = Url.DeleteOrganizationMember(Model.AccountName),
119119
ProfileUrlTemplate = Url.UserTemplate().LinkTemplate
120-
}));
120+
});
121121
</script>
122122
@ViewHelpers.SectionsScript(this)
123123
@Scripts.Render("~/Scripts/gallery/page-manage-organization.min.js")

src/NuGetGallery/Views/Packages/DisplayPackage.cshtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1139,7 +1139,7 @@
11391139
</style>
11401140

11411141
<script type="text/javascript">
1142-
var packageManagers = [@Html.Raw(string.Join(",", packageManagers.Select(pm => "\"" + pm.Id + "\"")))];
1142+
var packageManagers = @Html.ToJson(packageManagers.Select(pm => pm.Id).ToList());
11431143
</script>
11441144

11451145
@Scripts.Render("~/Scripts/gallery/page-display-package.min.js")

src/NuGetGallery/Views/Packages/Manage.cshtml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,19 +80,20 @@
8080
var strings_RemovingOrganization = "@Html.Raw(Strings.ManagePackageOwners_RemovingOrganization)";
8181
var strings_RemovingSelf = "@Html.Raw(Strings.ManagePackageOwners_RemovingSelf)";
8282
83-
// We are using JsonConvert instead of Json to serialize JSON in this CSHTML file because otherwise, with a large number of versions, this will overflow the maximum output JSON length limit for Json.
83+
// We are using ToJson (which uses Newtonsoft.Json) instead of Json.Encode to serialize JSON in this CSHTML
84+
// file because otherwise, with a large number of versions, this will overflow the maximum output JSON length limit for Json.
8485
8586
// Set up delete section
86-
var versionListedState = @Html.Raw(JsonConvert.SerializeObject(Model.VersionListedStateDictionary));
87+
var versionListedState = @Html.ToJson(Model.VersionListedStateDictionary);
8788
8889
// Set up deprecation section
8990
var strings_SelectAlternateVersionOption = "Latest";
90-
var versionDeprecationState = @Html.Raw(JsonConvert.SerializeObject(Model.VersionDeprecationStateDictionary));
91+
var versionDeprecationState = @Html.ToJson(Model.VersionDeprecationStateDictionary);
9192
9293
$(function () {
9394
// Set up documentation section
9495
var readMeModel = {
95-
"Versions": @Html.Raw(JsonConvert.SerializeObject(Model.VersionReadMeStateDictionary)),
96+
"Versions": @Html.ToJson(Model.VersionReadMeStateDictionary),
9697
"Edit": @Html.Raw(Json.Encode(Model.ReadMe))
9798
};
9899

src/NuGetGallery/Views/Shared/Gallery/Header.cshtml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,22 @@
88
var rawErrorMessage = TempData.ContainsKey("RawErrorMessage") ? TempData["RawErrorMessage"].ToString() : null;
99
}
1010

11+
<div class="container-fluid banner banner-blm text-center">
12+
<div class="row">
13+
<div class="col-sm-12">
14+
<span>
15+
Black Lives Matter.
16+
</span>
17+
</div>
18+
</div>
19+
</div>
20+
1121
<div class="container-fluid banner banner-info text-center">
1222
<div class="row">
1323
<div class="col-sm-12">
1424
<i class="ms-Icon ms-Icon--Warning" aria-hidden="true"></i>
1525
<span>
16-
NuGet.org will permanently <a href="https://devblogs.microsoft.com/nuget/nuget-org-will-permanently-remove-support-for-tls-1-0-and-1-1-on-june-15th/">
17-
remove support</a> for TLS 1.0 and 1.1 on June 15th. Please ensure that your systems use TLS 1.2.
26+
NuGet.org had TLS 1.0 and 1.1 disabled. Please refer to our <a href="https://devblogs.microsoft.com/nuget/deprecating-tls-1-0-and-1-1-on-nuget-org/">blog post</a> if you are having connection issues.
1827
</span>
1928
</div>
2029
</div>
@@ -266,4 +275,4 @@
266275
</div>
267276
</div>
268277
</div>
269-
}
278+
}

src/NuGetGallery/Views/Users/ApiKeys.cshtml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@
503503

504504
@section bottomScripts {
505505
<script type="text/javascript">
506-
var initialData = @Html.Raw(JsonConvert.SerializeObject(new
506+
var initialData = @Html.ToJson(new
507507
{
508508
ApiKeys = Model.ApiKeys,
509509
PackageOwners = Model.PackageOwners,
@@ -524,7 +524,7 @@
524524
ApiKeyNew = Url.Absolute("~/Content/gallery/img/api-key-new.svg"),
525525
ApiKeyNewFallback = Url.Absolute("~/Content/gallery/img/api-key-new-256x256.png"),
526526
}
527-
}));
527+
});
528528
</script>
529529
@Scripts.Render("~/Scripts/gallery/page-api-keys.min.js")
530530
}

0 commit comments

Comments
 (0)