Archive

Archive for August, 2009

Solving the ‘An illegal choice has been detected. Please contact the site administrator.’ error

August 13th, 2009

After upgrading a couple of client websites to Drupal 6.13, we suddenly noticed several “An illegal choice has been detected. Please contact the site administrator.” errors. These errors popped up all around: Performance settings, User adding, u name it.

Research thought me that the illegal choice error was returned when the posted! value of a checkbox, select or radio form field was not available in the original form-structure array. It all sounds logical as an valid input filter, because you don’t want people posting illegal values in your forms now do you?

I found out that the code generating the radio buttons was the following:

We were able to trace it back to the following piece of code in /includes/form.inc line 1733

1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
/**
 * Roll out a single radios element to a list of radios,
 * using the options array as index.
 */
function expand_radios($element) {
  if (count($element['#options']) > 0) {
    foreach ($element['#options'] as $key => $choice) {
      if (!isset($element[$key])) {
        // Generate the parents as the autogenerator does, so we will have a
        // unique id for each radio button.
        $parents_for_id = array_merge($element['#parents'], array($key));
        $element[$key] = array(
          '#type' => 'radio',
          '#title' => $choice,
          '#return_value' => check_plain($key),
          '#default_value' => isset($element['#default_value']) ? $element['#default_value'] : NULL,
          '#attributes' => $element['#attributes'],
          '#parents' => $element['#parents'],
          '#id' => form_clean_id('edit-'. implode('-', $parents_for_id)),
          '#ahah' => isset($element['#ahah']) ? $element['#ahah'] : NULL,
        );
      }
    }
  }
  return $element;
}

and more specifically this line (1747):

1747
'#return_value' => check_plain($key),

Tracking down further learns us the source of all evil hides in bootstrap.inc line 728!

728
729
730
731
732
733
734
735
736
/**
 * Encode special characters in a plain-text string for display as HTML.
 *
 * Uses drupal_validate_utf8 to prevent cross site scripting attacks on
 * Internet Explorer 6.
 */
function check_plain($text) {
  return drupal_validate_utf8($text) ? htmlspecialchars($text, ENT_QUOTES) : '';
}

This little piece checks if the passed argument is a valid UTF8 string, and if so htmlspecialchars it, or if not, returns nothing! This causes the return values of our radio button items to have an empty value=”" attribute, causing the validation to fail because of the empty value you posted.

Change it to this code to get it back up on it’s feet:

728
729
730
731
732
733
734
735
736
/**
 * Encode special characters in a plain-text string for display as HTML.
 *
 * Uses drupal_validate_utf8 to prevent cross site scripting attacks on
 * Internet Explorer 6.
 */
function check_plain($text) {
  return drupal_validate_utf8($text) ? htmlspecialchars($text, ENT_QUOTES) : $text;
}

Hope to be of any service!

Author: Kim Categories: Drupal, PHP Tags: