#1134 ✓resolved
Bas van Klinkenberg

Form.serialize textarea with single quote + newline = bug

Reported by Bas van Klinkenberg | September 3rd, 2010 @ 02:06 PM | in 1.7.0.1

Problem

When using single quotes followed by newline in a textarea, and submitting it with ajax via Form.serialize, all text except the quoted text is ignored by the webserver (nginx, webrick, apache).

How to reproduce:

  1. create an html form containing a textarea
  2. on a computer running linux or unix type a text in the textarea containing (among others) single quotes, followed by newline
    for example this text:
    an arbitrary line
    'something in single quotes followed by a newline'
    and more text eventually
    
  3. post this form with Ajax.updater, serializing the parameters with Form.serialize, for example like so:
    new Ajax.Updater('result_text', '/test', {asynchronous:true, evalScripts:true, parameters:Form.serialize($('my_form'))})
    
  4. let the server post back the exact contents of the textarea to the page.

Expected result:

The same text should be returned from the server.

Actual result:

Only the text within quotes is returned by the server, the rest is discarded.

Why is this happening:

This behavior does not appear when submitting the form via the browser instead of via ajax. The difference between the posted forms is that the browser encodes newlines as %0D%0A while prototype encodes the newlines as %0A (in browsers running on linux/unix machines). The server (nginx, webrick, apache) cannot cope with single quotes followed by %0A, but it does fine with single quotes followed by %0D%0A.

According to http://www.w3.org/TR/1999/REC-html401-19991224/interact/forms.html#... newlines should always be encoded as '%0D%0A' (and spaces should be encoded as '+').

For as far as I can see, prototype is using encodeURIComponent to encode key value pairs. The problem with encodeURIComponent is that it encodes newlines following the OS standards (so newline on windows is \r\n and encoded as %0D%0A while newline on unix/linux is \n encoded as '%0A'. It does not encode spaces as '+' either.
This results in a non compliant post header being send to the server, with the described result.

Possible solution

After encoding with encodeURIComponent, use replace or gsub to add the missing %0D in front of any %0A that does not have it already, and replace whitespace by '+' characters. I don't know if there is a faster way though.

Example in Rails

Create an empty rails project with the following controller and view and make sure to run it on a linux or unix machine. retrieve the page by pointing your browser to <your domain>/test and play around with the textarea:

controller app/controllers/test_controller.rb:

class MyTestController < ApplicationController
  def index
    if request.xhr?
      render :text => params[:text]
    else
      render :action => 'index'
    end
  end
end

view app/views/test/index.html.erb:

<head>
  <%= javascript_include_tag(:defaults) %>
</head>
<body>
  <% form_remote_tag(:url => {:action => :index}, :update => 'result_text') do %>
    <%= text_area_tag(:text) %>
    <%= submit_tag('send') %>
  <% end %>
  <p>
    You just posted:<br />
    <span id="result_text"></span>
  </p>
</body>

Comments and changes to this ticket

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile ยป

The Prototype JavaScript library.

Shared Ticket Bins

Pages