Skip to content

Commit

Permalink
Do not use FormattedModelValue in password editor template
Browse files Browse the repository at this point in the history
- #135
- see also PR aspnet/Mvc#7430
- add quirk switch to reverse this if necessary
  • Loading branch information
dougbu committed Mar 3, 2018
1 parent f9e06d6 commit 2b7ac74
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 12 deletions.
30 changes: 22 additions & 8 deletions src/System.Web.Mvc/Html/DefaultEditorTemplates.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Globalization;
using System.Linq;
using System.Text;
using System.Web.Configuration;
using System.Web.Mvc.Properties;
using System.Web.Routing;
using System.Web.UI.WebControls;
Expand All @@ -18,6 +19,7 @@ namespace System.Web.Mvc.Html
internal static class DefaultEditorTemplates
{
private const string HtmlAttributeKey = "htmlAttributes";
private const string UsePasswordValue = "Switch.System.Web.Mvc.UsePasswordValue";

internal static string BooleanTemplate(HtmlHelper html)
{
Expand Down Expand Up @@ -149,11 +151,11 @@ internal static string HiddenInputTemplate(HtmlHelper html)

MvcHtmlString hiddenResult;

if (htmlAttributesDict != null)
if (htmlAttributesDict != null)
{
hiddenResult = html.Hidden(String.Empty, model, htmlAttributesDict);
}
else
}
else
{
hiddenResult = html.Hidden(String.Empty, model, htmlAttributesObject);
}
Expand All @@ -178,9 +180,9 @@ private static IDictionary<string, object> CreateHtmlAttributes(HtmlHelper html,
{
return MergeHtmlAttributes(htmlAttributesObject, className, inputType);
}

var htmlAttributes = new Dictionary<string, object>()
{
{
{ "class", className }
};
if (inputType != null)
Expand Down Expand Up @@ -274,9 +276,21 @@ internal static string ObjectTemplate(HtmlHelper html, TemplateHelpers.TemplateH

internal static string PasswordTemplate(HtmlHelper html)
{
return html.Password(String.Empty,
html.ViewContext.ViewData.TemplateInfo.FormattedModelValue,
CreateHtmlAttributes(html, "text-box single-line password")).ToHtmlString();
object value = null;
var usePasswordStrings = WebConfigurationManager.AppSettings.GetValues(UsePasswordValue);
bool usePasswordValue;
if (usePasswordStrings != null &&
usePasswordStrings.Length > 0 &&
bool.TryParse(usePasswordStrings[0], out usePasswordValue) &&
usePasswordValue)
{
value = html.ViewContext.ViewData.TemplateInfo.FormattedModelValue;
}

return html.Password(
name: String.Empty,
value: value,
htmlAttributes: CreateHtmlAttributes(html, "text-box single-line password")).ToHtmlString();
}

private static bool ShouldShow(ModelMetadata metadata, TemplateInfo templateInfo)
Expand Down
57 changes: 53 additions & 4 deletions test/System.Web.Mvc.Test/Html/Test/DefaultEditorTemplatesTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -731,14 +731,63 @@ public void ObjectTemplateDisplaysSimpleDisplayTextWithNonNullModelTemplateDepth
public void PasswordTemplateTests()
{
Assert.Equal(
"<input class=\"text-box single-line password\" id=\"FieldPrefix\" name=\"FieldPrefix\" type=\"password\" value=\"Value\" />",
"<input class=\"text-box single-line password\" id=\"FieldPrefix\" name=\"FieldPrefix\" type=\"password\" />",
DefaultEditorTemplates.PasswordTemplate(MakeHtmlHelper<string>("Value")));

Assert.Equal(
"<input class=\"text-box single-line password\" id=\"FieldPrefix\" name=\"FieldPrefix\" type=\"password\" value=\"&lt;script>alert(&#39;XSS!&#39;)&lt;/script>\" />",
"<input class=\"text-box single-line password\" id=\"FieldPrefix\" name=\"FieldPrefix\" type=\"password\" />",
DefaultEditorTemplates.PasswordTemplate(MakeHtmlHelper<string>("<script>alert('XSS!')</script>")));
}

[Fact]
public void PasswordTemplate_ReturnsInputElement_IgnoresValues()
{
// Arrange
var expected = "<input class=\"text-box single-line password\" id=\"FieldPrefix\" name=\"FieldPrefix\" " +
"type=\"password\" />";

// Template ignores Model and FormattedModelValue.
var helper = MakeHtmlHelper<string>(model: "Model string", formattedModelValue: "Formatted string");

var viewData = helper.ViewData;
var templateInfo = viewData.TemplateInfo;
templateInfo.HtmlFieldPrefix = "FieldPrefix";

// Template ignores ModelState and ViewData.
var valueProviderResult = new ValueProviderResult(
"Raw model string",
"Attempted model string",
CultureInfo.InvariantCulture);
viewData.ModelState.SetModelValue("FieldPrefix", valueProviderResult);
viewData["FieldPrefix"] = "ViewData string";

// Act
var result = DefaultEditorTemplates.PasswordTemplate(helper);

// Assert
Assert.Equal(expected, result);
}

[Fact]
public void PasswordTemplate_ReturnsInputElement_UsesHtmlAttributes()
{
// Arrange
var expected = "<input class=\"super text-box single-line password\" id=\"FieldPrefix\" " +
"name=\"FieldPrefix\" type=\"password\" value=\"Html attributes string\" />";
var helper = MakeHtmlHelper<string>(model: null);
var viewData = helper.ViewData;
var templateInfo = viewData.TemplateInfo;
templateInfo.HtmlFieldPrefix = "FieldPrefix";

viewData["htmlAttributes"] = new { @class = "super", value = "Html attributes string" };

// Act
var result = DefaultEditorTemplates.PasswordTemplate(helper);

// Assert
Assert.Equal(expected, result);
}

public static TheoryDataSet<object, string> PasswordTemplateHtmlAttributeData
{
get
Expand All @@ -747,11 +796,11 @@ public static TheoryDataSet<object, string> PasswordTemplateHtmlAttributeData
{
{
new { @class = "form-control" },
"<input class=\"form-control text-box single-line password\" id=\"FieldPrefix\" name=\"FieldPrefix\" type=\"password\" value=\"Value\" />"
"<input class=\"form-control text-box single-line password\" id=\"FieldPrefix\" name=\"FieldPrefix\" type=\"password\" />"
},
{
new { @class = "form-control", custom = "foo" },
"<input class=\"form-control text-box single-line password\" custom=\"foo\" id=\"FieldPrefix\" name=\"FieldPrefix\" type=\"password\" value=\"Value\" />"
"<input class=\"form-control text-box single-line password\" custom=\"foo\" id=\"FieldPrefix\" name=\"FieldPrefix\" type=\"password\" />"
}
};
}
Expand Down

0 comments on commit 2b7ac74

Please sign in to comment.