Index: components/select.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/webform/components/select.inc,v
retrieving revision 1.33
diff -u -r1.33 select.inc
--- components/select.inc	25 Jan 2010 04:48:51 -0000	1.33
+++ components/select.inc	7 Feb 2010 01:17:19 -0000
@@ -230,11 +230,12 @@
       // Set display as a checkbox set.
       $element['#type'] = 'checkboxes';
       // Drupal 6 hack to properly render on multipage forms.
-      $element['#process'] = array('webform_expand_checkboxes');
+      $element['#process'] = array('webform_expand_checkboxes', 'webform_expand_select_ids');
     }
     else {
       // Set display as a radio set.
       $element['#type'] = 'radios';
+      $element['#process'] = array('expand_radios', 'webform_expand_select_ids');
     }
   }
   return $element;
@@ -256,16 +257,41 @@
   }
 
   $element = expand_checkboxes($element);
-  foreach ($default_value as $key=>$val) {
+
+  // Escape the values of checkboxes.
+  foreach (element_children($element) as $key) {
+    $element[$key]['#return_value'] = check_plain($element[$key]['#return_value']);
+    $element[$key]['#name'] = $element['#name'] . '[' . $element[$key]['#return_value'] . ']';
+  }
+
+  foreach ($default_value as $key => $val) {
     $element[$key]['#default_value'] = $val;
   }
   return $element;
 }
 
 /**
+ * FAPI process function to rename IDs attached to checkboxes and radios.
+ */
+function webform_expand_select_ids($element) {
+  $id = $element['#id'] = str_replace('_', '-', _webform_safe_name(strip_tags($element['#id'])));
+  $delta = 0;
+  foreach (element_children($element) as $key) {
+    $delta++;
+    // Convert the #id for each child to a safe name, regardless of key.
+    $element[$key]['#id'] = $id . '-' . $delta;
+
+    // Prevent scripts or CSS in the labels for each checkbox or radio.
+    $element[$key]['#title'] = _webform_filter_xss($element[$key]['#title']);
+  }
+  return $element;
+}
+
+/**
  * Implementation of _webform_display_component().
  */
 function _webform_display_select($component, $value, $format = 'html') {
+  $value = (array) $value;
   ksort($value);
   return array(
     '#title' => $component['name'],
@@ -312,8 +338,6 @@
     if (empty($value)) {
       $value[0] = '';
     }
-
-    $value = array_values($value);
   }
 
   return $value;
@@ -433,7 +457,7 @@
       if ($option_value !== '') {
         // Administer provided values.
         if (isset($options[$option_value])) {
-          $items[] = $options[$option_value];
+          $items[] = _webform_filter_xss($options[$option_value]);
         }
         // User-specified in the "other" field.
         else {
@@ -446,17 +470,16 @@
     if (isset($element['#value'][0]) && $element['#value'][0] !== '') {
       // Administer provided values.
       if (isset($options[$element['#value'][0]])) {
-        $items[] = $options[$element['#value'][0]];
+        $items[] = $element['#format'] == 'html' ? _webform_filter_xss($options[$element['#value'][0]]) : $options[$element['#value'][0]];
       }
       // User-specified in the "other" field.
       else {
-        $items[] = $element['#value'][0];
+        $items[] = $element['#format'] == 'html' ? check_plain($element['#value'][0]) : $element['#value'][0];
       }
     }
   }
 
   if ($element['#format'] == 'html') {
-    array_walk($items, 'check_plain');
     $output = count($items) > 1 ? theme('item_list', $items) : (isset($items[0]) ? $items[0] : ' ');
   }
   else {
@@ -505,7 +528,7 @@
   $normal_count = 0;
   while ($data = db_fetch_array($result)) {
     $display_option = $single ? $data['data'] : $options[$data['data']];
-    $rows[$data['data']] = array(check_plain($display_option), $data['datacount']);
+    $rows[$data['data']] = array(_webform_filter_xss($display_option), $data['datacount']);
     $normal_count += $data['datacount'];
   }
 
@@ -540,12 +563,12 @@
   if (is_array($value)) {
     foreach ($value as $option_value) {
       if ($option_value !== '') {
-        $output .= check_plain($option_value) .'<br />';
+        $output .= _webform_filter_xss($option_value) .'<br />';
       }
     }
   }
   else {
-    $output .= check_plain(empty($value[0]) ? '' : $value[0]);
+    $output .= empty($value[0]) ? '' : _webform_filter_xss($value[0]);
   }
   return $output;
 }
Index: components/grid.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/webform/components/grid.inc,v
retrieving revision 1.9
diff -u -r1.9 grid.inc
--- components/grid.inc	23 Jan 2010 22:56:02 -0000	1.9
+++ components/grid.inc	7 Feb 2010 01:17:18 -0000
@@ -6,6 +6,9 @@
  * Webform module grid component.
  */
 
+// Grid depends on functions provided by select.
+webform_component_include('select');
+
 /**
  * Implementation of _webform_defaults_component().
  */
@@ -109,26 +112,17 @@
     }
     $options = $aux;
   }
-  if ($component['extra']['qrand']) {
-    $aux = array();
-    $keys = array_keys($questions);
-    shuffle($keys);
-    foreach ($keys as $key) {
-      $aux[$key] = $questions[$key];
-      unset($questions[$key]);
-    }
-    $questions = $aux;
-  }
+
+  $delta = 0;
   foreach ($questions as $question) {
+    $delta++;
     if ($question != '') {
-      // Remove quotes from keys to prevent HTML breakage.
-      $element[str_replace(array('"', "'"), '', $question)] = array(
+      $element['q' . $delta] = array(
         '#title'         => $question,
         '#required'      => $component['mandatory'],
-        '#prefix'        => '<div class="webform-component-'. $component['type'] .'" id="webform-component-'. $component['form_key'] .'">',
-        '#suffix'        => '</div>',
         '#options'       => $options,
         '#type'          => 'radios',
+        '#process'       => array('expand_radios', 'webform_expand_select_ids'),
       );
     }
   }
@@ -140,6 +134,17 @@
     }
   }
 
+  // Shuffle questions if needed.
+  if ($component['extra']['qrand']) {
+    $aux = array();
+    $keys = element_children($element);
+    shuffle($keys);
+    foreach ($keys as $key) {
+      $aux[$key] = array();
+    }
+    $element = array_merge($aux, $element);
+  }
+
   return $element;
 }
 
@@ -160,13 +165,13 @@
     '#theme' => 'webform_display_grid',
     '#theme_wrappers' => $format == 'html' ? array('webform_element') : array('webform_element_text'),
     '#post_render' => array('webform_element_wrapper'),
+    '#sorted' => TRUE,
   );
 
   $cid = 0;
   foreach ($questions as $question) {
     if ($question != '') {
-      // Remove quotes from keys to prevent HTML breakage.
-      $element[str_replace(array('"', "'"), '', $question)] = array(
+      $element[$question] = array(
         '#title' => $question,
         '#value' => isset($value[$cid]) ? $value[$cid] : NULL,
       );
@@ -188,11 +193,11 @@
     $rows = array();
     $header = array('');
     foreach ($element['#options'] as $option) {
-      $header[] = array('data' => check_plain($option), 'class' => 'checkbox');
+      $header[] = array('data' => _webform_filter_xss($option), 'class' => 'checkbox');
     }
     foreach (element_children($element) as $key) {
       $row = array();
-      $row[] = check_plain($element[$key]['#title']);
+      $row[] = _webform_filter_xss($element[$key]['#title']);
       foreach ($element['#options'] as $option_value => $option_label) {
         if ($option_value == $element[$key]['#value']) {
           $row[] = array('data' => '<strong>X</strong>', 'class' => 'checkbox');
@@ -220,35 +225,17 @@
 /**
  * Implementation of _webform_submit_component().
  */
-function _webform_submit_grid($component, $value) {;
+function _webform_submit_grid($component, $value) {
   $options = drupal_map_assoc(array_flip(_webform_grid_options($component['extra']['options'])));
-
-  // Questions are a bit more tricky, since quotes were removed from them in
-  // _webform_render_grid(). Build a list of no_quotes => with_qoutes questions.
-  $questions = array();
-  foreach (_webform_grid_options($component['extra']['questions']) as $key => $question) {
-    $safe_question = str_replace(array('"', "'"), '', $question);
-    $questions[$safe_question] = $question;
-  }
-
-  if (is_array($value)) {
-    foreach ($value as $key => $option_value) {
-      if ($option_value !== '') {
-        $value[$key] = $options[$option_value];
-      }
-    }
-  }
-  elseif ($value !== '') {
-    $value = $options[$value];
-  }
+  $questions = _webform_grid_options($component['extra']['questions']);
 
   // Put the form in the original option order before saving.
   // Return the final data with the quotes back in place.
   $ordered_value = array();
+  $delta = 0;
   foreach ($questions as $safe_question => $question) {
-    if (isset($value[$safe_question])) {
-      $ordered_value[$question] = $value[$safe_question];
-    }
+    $delta++;
+    $ordered_value['q' . $delta] = isset($value['q' . $delta]) ? $value['q' . $delta] : '';
   }
 
   return $ordered_value;
@@ -283,12 +270,12 @@
 
   // Add options as a header row.
   foreach ($options as $option) {
-    $header[] = $option;
+    $header[] = _webform_filter_xss($option);
   }
 
   // Add questions as each row.
   foreach ($questions as $qkey => $question) {
-    $row = array($question);
+    $row = array(_webform_filter_xss($question));
     foreach ($options as $okey => $option) {
       $row[] = !empty($counts[$qkey][$okey]) ? $counts[$qkey][$okey] : 0;
     }
@@ -309,12 +296,12 @@
   if (is_array($value)) {
     foreach ($value as $item => $value) {
       if ($value !== '') {
-        $output .= $questions[$item] .': '. check_plain($value) .'<br />';
+        $output .= _webform_filter_xss($questions[$item]) .': '. _webform_filter_xss($value) .'<br />';
       }
     }
   }
   else {
-    $output = check_plain(!isset($value[0]) ? '' : $value[0]);
+    $output = !isset($value[0]) ? '' : _webform_filter_xss($value[0]);
   }
   return $output;
 }
@@ -364,13 +351,13 @@
     // Set the header for the table.
     if ($first) {
       foreach ($question_element['#options'] as $option) {
-        $header[] = array('data' => $option, 'class' => 'checkbox');
+        $header[] = array('data' => _webform_filter_xss($option), 'class' => 'checkbox');
       }
       $first = FALSE;
     }
 
     // Create a row with the question title.
-    $row = array(check_plain($question_element['#title']));
+    $row = array(_webform_filter_xss($question_element['#title']));
 
     // Render each radio button in the row.
     $radios = expand_radios($question_element);
@@ -389,7 +376,8 @@
  */
 function _webform_grid_options($text) {
   $options = array();
-  $rows = array_filter(explode("\n", _webform_filter_values(trim($text))));
+  $rows = array_filter(explode("\n", _webform_filter_values(trim($text), NULL, NULL, NULL, FALSE)));
+
   foreach ($rows as $option) {
     $option = trim($option);
     if (preg_match('/^([^|]+)\|(.*)$/', $option, $matches)) {
