Mark Whitaker
Mark Whitaker

Reputation: 8605

How can I *HTML*-encode form contents when serializing with jQuery.serialize()?

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:

Current implementation using .serialize()

  1. User enters My name is <b>Fred</b> into a form input with name Details.
  2. .serialize() serializes this as Details=My+name+is+%3Cb%3EFred%3C%2Fb%3E (URL-encoding)
  3. The server deserializes the string and gets My name is <b>Fred</b> (URL-decoding)

What I want to happen

  1. User enters My name is <b>Fred</b> into a form input with name Details.
  2. This gets HTML-encoded to My name is &lt;b&gt;Fred&lt;/b&gt; (HTML-encoding)
  3. .serialize() serializes this as Details=My+name+is+%26lt%3Bb%26gt%3BFred%26lt%3B%2Fb%26gt%3B (URL-encoding)
  4. The server URL-decodes the string and gets My name is &lt;b&gt;Fred&lt;/b&gt; (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:

  1. Iterate through the form inputs and HTML-encode them "by hand" before calling .serialize(): I'd rather not have to do this as it will make the code messier and less robust.
  2. Modify my server to accept non-HTML-encoded values: for various reasons I won't go into this is problematic and not a practical solution.

Is there a simpler solution?

Upvotes: 2

Views: 8775

Answers (5)

uv_man
uv_man

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

Mark Whitaker
Mark Whitaker

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, '&amp;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#39;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;');
});

$.ajax({
    url: form.attr('action'),
    async: false,
    type: 'POST',
    data: data,
    success: function (data) {
        //...
    }
});

Upvotes: 2

iCollect.it Ltd
iCollect.it Ltd

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)

Update

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

Al.G.
Al.G.

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 = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#039;'
  };

  return text.replace(/[&<>"']/g, function(m) { return map[m]; });
}

Upvotes: -1

wintercounter
wintercounter

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

Related Questions