<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -1,5 +1,7 @@
 *2.2.1 [RC2 or 2.2 final]*
 
+* Fixed that FormTagHelper generated illegal html if name contained square brackets #1238 [Vladimir Dobriakov]
+
 * Fix regression bug that made date_select and datetime_select raise a Null Pointer Exception when a nil date/datetime was passed and only month and year were displayed #1289 [Bernardo Padua/Tor Erik]
 
 * Simplified the logging format for parameters (don't include controller, action, and format as duplicates) [DHH]</diff>
      <filename>actionpack/CHANGELOG</filename>
    </modified>
    <modified>
      <diff>@@ -78,7 +78,7 @@ module ActionView
       #   #    &lt;option&gt;Paris&lt;/option&gt;&lt;option&gt;Rome&lt;/option&gt;&lt;/select&gt;
       def select_tag(name, option_tags = nil, options = {})
         html_name = (options[:multiple] == true &amp;&amp; !name.to_s.ends_with?(&quot;[]&quot;)) ? &quot;#{name}[]&quot; : name
-        content_tag :select, option_tags, { &quot;name&quot; =&gt; html_name, &quot;id&quot; =&gt; name }.update(options.stringify_keys)
+        content_tag :select, option_tags, { &quot;name&quot; =&gt; html_name, &quot;id&quot; =&gt; sanitize_to_id(name) }.update(options.stringify_keys)
       end
 
       # Creates a standard text field; use these text fields to input smaller chunks of text like a username
@@ -112,7 +112,7 @@ module ActionView
       #   text_field_tag 'ip', '0.0.0.0', :maxlength =&gt; 15, :size =&gt; 20, :class =&gt; &quot;ip-input&quot;
       #   # =&gt; &lt;input class=&quot;ip-input&quot; id=&quot;ip&quot; maxlength=&quot;15&quot; name=&quot;ip&quot; size=&quot;20&quot; type=&quot;text&quot; value=&quot;0.0.0.0&quot; /&gt;
       def text_field_tag(name, value = nil, options = {})
-        tag :input, { &quot;type&quot; =&gt; &quot;text&quot;, &quot;name&quot; =&gt; name, &quot;id&quot; =&gt; name, &quot;value&quot; =&gt; value }.update(options.stringify_keys)
+        tag :input, { &quot;type&quot; =&gt; &quot;text&quot;, &quot;name&quot; =&gt; name, &quot;id&quot; =&gt; sanitize_to_id(name), &quot;value&quot; =&gt; value }.update(options.stringify_keys)
       end
 
       # Creates a label field
@@ -130,7 +130,7 @@ module ActionView
       #   label_tag 'name', nil, :class =&gt; 'small_label'
       #   # =&gt; &lt;label for=&quot;name&quot; class=&quot;small_label&quot;&gt;Name&lt;/label&gt;
       def label_tag(name, text = nil, options = {})
-        content_tag :label, text || name.to_s.humanize, { &quot;for&quot; =&gt; name }.update(options.stringify_keys)
+        content_tag :label, text || name.to_s.humanize, { &quot;for&quot; =&gt; sanitize_to_id(name) }.update(options.stringify_keys)
       end
 
       # Creates a hidden form input field used to transmit data that would be lost due to HTTP's statelessness or
@@ -282,7 +282,7 @@ module ActionView
       #   check_box_tag 'eula', 'accepted', false, :disabled =&gt; true
       #   # =&gt; &lt;input disabled=&quot;disabled&quot; id=&quot;eula&quot; name=&quot;eula&quot; type=&quot;checkbox&quot; value=&quot;accepted&quot; /&gt;
       def check_box_tag(name, value = &quot;1&quot;, checked = false, options = {})
-        html_options = { &quot;type&quot; =&gt; &quot;checkbox&quot;, &quot;name&quot; =&gt; name, &quot;id&quot; =&gt; name, &quot;value&quot; =&gt; value }.update(options.stringify_keys)
+        html_options = { &quot;type&quot; =&gt; &quot;checkbox&quot;, &quot;name&quot; =&gt; name, &quot;id&quot; =&gt; sanitize_to_id(name), &quot;value&quot; =&gt; value }.update(options.stringify_keys)
         html_options[&quot;checked&quot;] = &quot;checked&quot; if checked
         tag :input, html_options
       end
@@ -470,6 +470,12 @@ module ActionView
             tag(:input, :type =&gt; &quot;hidden&quot;, :name =&gt; request_forgery_protection_token.to_s, :value =&gt; form_authenticity_token)
           end
         end
+
+        # see http://www.w3.org/TR/html4/types.html#type-name
+        def sanitize_to_id(name)
+          name.to_s.gsub(']','').gsub(/[^-a-zA-Z0-9:.]/, &quot;_&quot;)
+        end
+
     end
   end
 end</diff>
      <filename>actionpack/lib/action_view/helpers/form_tag_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -12,12 +12,19 @@ class FormTagHelperTest &lt; ActionView::TestCase
     @controller = @controller.new
   end
 
+  VALID_HTML_ID = /^[A-Za-z][-_:.A-Za-z0-9]*$/ # see http://www.w3.org/TR/html4/types.html#type-name
+
   def test_check_box_tag
     actual = check_box_tag &quot;admin&quot;
     expected = %(&lt;input id=&quot;admin&quot; name=&quot;admin&quot; type=&quot;checkbox&quot; value=&quot;1&quot; /&gt;)
     assert_dom_equal expected, actual
   end
 
+  def test_check_box_tag_id_sanitized
+    label_elem = root_elem(check_box_tag(&quot;project[2][admin]&quot;))
+    assert_match VALID_HTML_ID, label_elem['id']
+  end
+
   def test_form_tag
     actual = form_tag
     expected = %(&lt;form action=&quot;http://www.example.com&quot; method=&quot;post&quot;&gt;)
@@ -64,6 +71,11 @@ class FormTagHelperTest &lt; ActionView::TestCase
     assert_dom_equal expected, actual
   end
 
+  def test_hidden_field_tag_id_sanitized
+    input_elem = root_elem(hidden_field_tag(&quot;item[][title]&quot;))
+    assert_match VALID_HTML_ID, input_elem['id']
+  end
+
   def test_file_field_tag
     assert_dom_equal &quot;&lt;input name=\&quot;picsplz\&quot; type=\&quot;file\&quot; id=\&quot;picsplz\&quot; /&gt;&quot;, file_field_tag(&quot;picsplz&quot;)
   end
@@ -118,6 +130,11 @@ class FormTagHelperTest &lt; ActionView::TestCase
     assert_dom_equal expected, actual
   end
 
+  def test_select_tag_id_sanitized
+    input_elem = root_elem(select_tag(&quot;project[1]people&quot;, &quot;&lt;option&gt;david&lt;/option&gt;&quot;))
+    assert_match VALID_HTML_ID, input_elem['id']
+  end
+
   def test_text_area_tag_size_string
     actual = text_area_tag &quot;body&quot;, &quot;hello world&quot;, &quot;size&quot; =&gt; &quot;20x40&quot;
     expected = %(&lt;textarea cols=&quot;20&quot; id=&quot;body&quot; name=&quot;body&quot; rows=&quot;40&quot;&gt;hello world&lt;/textarea&gt;)
@@ -184,6 +201,11 @@ class FormTagHelperTest &lt; ActionView::TestCase
     assert_dom_equal expected, actual
   end
 
+  def test_text_field_tag_id_sanitized
+    input_elem = root_elem(text_field_tag(&quot;item[][title]&quot;))
+    assert_match VALID_HTML_ID, input_elem['id']
+  end
+
   def test_label_tag_without_text
     actual = label_tag &quot;title&quot;
     expected = %(&lt;label for=&quot;title&quot;&gt;Title&lt;/label&gt;)
@@ -208,11 +230,16 @@ class FormTagHelperTest &lt; ActionView::TestCase
     assert_dom_equal expected, actual
   end
 
+  def test_label_tag_id_sanitized
+    label_elem = root_elem(label_tag(&quot;item[title]&quot;))
+    assert_match VALID_HTML_ID, label_elem['for']
+  end
+
   def test_boolean_optios
     assert_dom_equal %(&lt;input checked=&quot;checked&quot; disabled=&quot;disabled&quot; id=&quot;admin&quot; name=&quot;admin&quot; readonly=&quot;readonly&quot; type=&quot;checkbox&quot; value=&quot;1&quot; /&gt;), check_box_tag(&quot;admin&quot;, 1, true, 'disabled' =&gt; true, :readonly =&gt; &quot;yes&quot;)
     assert_dom_equal %(&lt;input checked=&quot;checked&quot; id=&quot;admin&quot; name=&quot;admin&quot; type=&quot;checkbox&quot; value=&quot;1&quot; /&gt;), check_box_tag(&quot;admin&quot;, 1, true, :disabled =&gt; false, :readonly =&gt; nil)
     assert_dom_equal %(&lt;select id=&quot;people&quot; multiple=&quot;multiple&quot; name=&quot;people[]&quot;&gt;&lt;option&gt;david&lt;/option&gt;&lt;/select&gt;), select_tag(&quot;people&quot;, &quot;&lt;option&gt;david&lt;/option&gt;&quot;, :multiple =&gt; true)
-    assert_dom_equal %(&lt;select id=&quot;people[]&quot; multiple=&quot;multiple&quot; name=&quot;people[]&quot;&gt;&lt;option&gt;david&lt;/option&gt;&lt;/select&gt;), select_tag(&quot;people[]&quot;, &quot;&lt;option&gt;david&lt;/option&gt;&quot;, :multiple =&gt; true)
+    assert_dom_equal %(&lt;select id=&quot;people_&quot; multiple=&quot;multiple&quot; name=&quot;people[]&quot;&gt;&lt;option&gt;david&lt;/option&gt;&lt;/select&gt;), select_tag(&quot;people[]&quot;, &quot;&lt;option&gt;david&lt;/option&gt;&quot;, :multiple =&gt; true)
     assert_dom_equal %(&lt;select id=&quot;people&quot; name=&quot;people&quot;&gt;&lt;option&gt;david&lt;/option&gt;&lt;/select&gt;), select_tag(&quot;people&quot;, &quot;&lt;option&gt;david&lt;/option&gt;&quot;, :multiple =&gt; nil)
   end
 
@@ -283,4 +310,10 @@ class FormTagHelperTest &lt; ActionView::TestCase
   def protect_against_forgery?
     false
   end
+
+  private
+
+  def root_elem(rendered_content)
+    HTML::Document.new(rendered_content).root.children[0]
+  end
 end</diff>
      <filename>actionpack/test/template/form_tag_helper_test.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>b2cd318c2e3f4d19813a5c62903319a6683aa561</id>
    </parent>
  </parents>
  <author>
    <name>Vladimir Dobriakov</name>
    <email>vladimir@geekq.net</email>
  </author>
  <url>http://github.com/rails/rails/commit/5fad229e43e2b2541ed39c6ef571975176e6a8d2</url>
  <id>5fad229e43e2b2541ed39c6ef571975176e6a8d2</id>
  <committed-date>2008-11-04T09:24:52-08:00</committed-date>
  <authored-date>2008-11-04T04:46:36-08:00</authored-date>
  <message>Fixed that FormTagHelper generates illegal html if name contains e.g. square brackets [#1238 state:committed]

Signed-off-by: David Heinemeier Hansson &lt;david@loudthinking.com&gt;</message>
  <tree>823af789d18ef67d0290fab2531ddf70c7ffe79e</tree>
  <committer>
    <name>David Heinemeier Hansson</name>
    <email>david@loudthinking.com</email>
  </committer>
</commit>
