Reputation: 8605
The jQuery form .serialize() method serializes form contents to a string and automatically URL-encodes the string. My server then reverses this process and URL-decodes the string when deserializing it.
But what I need to be able to do is to HTML-encode the form contents before the form is serialized. In other words, if a user enters HTML into a text input in my form, I want this to be made safe using HTML encoding, then transmitted exactly as described above (using URL-encoding as normal).
Let me illustrate with an example:
- User enters
My name is <b>Fred</b>
into a form input with nameDetails
..serialize()
serializes this asDetails=My+name+is+%3Cb%3EFred%3C%2Fb%3E
(URL-encoding)- The server deserializes the string and gets
My name is <b>Fred</b>
(URL-decoding)
- User enters
My name is <b>Fred</b>
into a form input with nameDetails
.- This gets HTML-encoded to
My name is <b>Fred</b>
(HTML-encoding).serialize()
serializes this asDetails=My+name+is+%26lt%3Bb%26gt%3BFred%26lt%3B%2Fb%26gt%3B
(URL-encoding)- The server URL-decodes the string and gets
My name is <b>Fred</b>
(URL-decoding only)
I was hoping that .serialize()
might take an argument to specify that the form contents should be HTML-encoded, but no such luck. A couple of other possible solutions would be:
.serialize()
: I'd rather not have to do this as it will make the code messier and less robust.Is there a simpler solution?
Upvotes: 2
Views: 8775
Reputation: 224
One option might be to update the jquery library directly and call htmlEncode on the dom value, before the uriEncode happens.
I tested this in a ASP.NET/MVC app and the line I updated in jquery-1.8.2.js (line 7222, depending version) was:
s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
to
s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( htmlEncode(value) );
Use whichever htmlEncode method you find suitable, but it appears to work.
Might actually make more sense to extend this method out and call a customSerialize method which does the htmlEncode.
I believe this is the simplest way and means you don't have to iterate through the dom before calling serialize.
Upvotes: 0
Reputation: 8605
The solution is to use jQuery's .serializeArray()
and apply the HTML-encoding to each element in a loop.
In other words, I had to change this:
$.ajax({
url: form.attr('action'),
async: false,
type: 'POST',
data: form.serialize(),
success: function (data) {
//...
}
});
to this:
// HTML-encode form values before submitting
var data = {};
$.each(form.serializeArray(), function() {
data[this.name] = this.value
.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/'/g, ''')
.replace(/</g, '<')
.replace(/>/g, '>');
});
$.ajax({
url: form.attr('action'),
async: false,
type: 'POST',
data: data,
success: function (data) {
//...
}
});
Upvotes: 2
Reputation: 93631
As you are using MVC (see comments), simply apply the [AllowHtml]
attribute above the single property that requires it.
You will need to add the following using
statement if not already present:
using System.Web.Mvc;
Note: If you are also using a MetadataTypeAttribute
it may not work out of the box (but unlikely to be a problem in this case)
From comments, as you cannot modify the form data properties (dynamic forms), you can turn it off in the controller using the following on the controller action
[ValidateInput(false)]
You can also change the setting for the entire server (less secure). See this blog entry:
http://weblogs.asp.net/imranbaloch/handling-validateinputattribute-globally
Upvotes: 1
Reputation: 4426
A string has to be html-encoded after any other changes like url-encoding or the sql string-escape.
So you first serialize your string, use it in links and after deserializing you html-encode it. Just do it as before but use the function below.
Why is this important?
Because I can enter in the url myself a non-html-escaped string and then can give it to you. You would think it's escaped, but it wouldn't. The solution is to escape it just before printing it on the page.
This question describes how to html-escape a string: HtmlSpecialChars equivalent in Javascript?
function escapeHtml(text) {
var map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
return text.replace(/[&<>"']/g, function(m) { return map[m]; });
}
Upvotes: -1
Reputation: 7488
Input values will always get encoded by default. As you stated, you have to iterate through each values to decode first. You can use the following jQuery snippet to do that:
$('<div/>').html(value).text();
Upvotes: 0