diff --git a/finder.install b/finder.install index 171e814a011d991c60713fc5e448d3331adb864d..b1d38d6effbe8bccda189d074622d176c8cbe6c2 100755 --- a/finder.install +++ b/finder.install @@ -450,6 +450,7 @@ function finder_update_7203() { 'table' => $table, 'field' => $field_name, 'relationship' => NULL, + 'format' => isset($element->settings['choices']['sanitization']['format']) ? $element->settings['choices']['sanitization']['format'] : 'filter_xss', ); if (isset($relationships[$field])) { $new_field->relationship = $relationships[$field]; diff --git a/includes/build.inc b/includes/build.inc index 8f8169ca1d145946c52d34eed9da86e5f9f25232..e39d7213356dd43fd5bdefac2c5d2f4f67dc25f7 100644 --- a/includes/build.inc +++ b/includes/build.inc @@ -235,6 +235,7 @@ function finder_build_style_render(&$style_plugin) { foreach ($records as $label => $row) { if ($mode == 'choices') { foreach ($field_info[$element->id] as $key => $field) { + $format = isset($field->format) ? $field->format : 'filter_xss'; foreach (array_keys($field->field_alias) as $delta) { // If there is no match field, or if there is and it's set. if (!isset($field->field_matched[$delta]) || (!empty($field->field_matched[$delta]) && !empty($row->{$field->field_matched[$delta]}))) { @@ -255,7 +256,7 @@ function finder_build_style_render(&$style_plugin) { $display = finder_eval($finder->esetting($element, 'choices_rewrite'), $variables); } - $results[$value] = $display; + $results[$value] = finder_sanitize($display, $format); $style_plugin->view->row_index++; } } @@ -370,3 +371,30 @@ function finder_alias($type, $eid, $table = NULL, $field = NULL, $delta = NULL) return 'finder_' . $type . '_' . $alias; } +/** + * Sanitize a finder choice. + * + * @param $option + * The option object with unsanitized display field. + * @param $filter + * The filter to use. + * @return + * The option object with sanitized display field. + */ +function finder_sanitize($option, $filter = 'filter_xss') { + switch ($filter) { + case 'filter_xss': + case 'filter_xss_admin': + case 'check_plain': + case 'check_url': + $option = $filter($option); + break; + default: + $option = check_markup($option, $filter, FALSE); + } + return $option; +} + + + + diff --git a/includes/theme.inc b/includes/theme.inc index d2d504c106270641520f5187e8ae7d3257e7889c..0bc6abcddae59a137e66567b1e7c9c8c21ac4be4 100644 --- a/includes/theme.inc +++ b/includes/theme.inc @@ -78,7 +78,11 @@ function theme_finder_results($variables) { // stored as an array, so we always act as though they were multiple. foreach (array_keys($field->field_alias) as $delta) { if (!empty($result->{$field->field_alias[$delta]})) { - $values[] = $result->{$field->field_alias[$delta]}; + // Use finder_sanitize() when outputting a result item in HTML, + // especially if the expected value is user-supplied. You can of + // course just hard code other sanitization techniques: + // http://api.drupal.org/api/drupal/includes--common.inc/group/sanitization/7 + $values[] = finder_sanitize($result->{$field->field_alias[$delta]}, $field->format); } } // Output the values separated by a comma. diff --git a/modules/finder_ui/includes/field.inc b/modules/finder_ui/includes/field.inc index 049ce1e9c83e13f9820d40c22f3995db45d1ea1c..b00d0be094821d1566f3908f05224dff02038b4e 100644 --- a/modules/finder_ui/includes/field.inc +++ b/modules/finder_ui/includes/field.inc @@ -45,6 +45,7 @@ function finder_ui_field_page($finder, $feid, $field_key, $js) { $element = &$finder->elements[$feid]; $field_key = $form_state['values']['field']; $relationship = $form_state['values']['relationship']; + $format = $form_state['values']['format']; list($table, $field) = explode('.', $field_key); @@ -52,6 +53,7 @@ function finder_ui_field_page($finder, $feid, $field_key, $js) { 'table' => $table, 'field' => $field, 'relationship' => $relationship, + 'format' => $format, ); ctools_object_cache_set('finder', $finder->name, $finder); @@ -148,10 +150,51 @@ function finder_ui_field_form($form, &$form_state) { ); } - if ($field_key != 'new' && empty($relationships)) { - $form['no_config']['#markup'] = t('There is nothing to configure for this field.'); + $form['sanitization'] = array( + '#type' => 'fieldset', + '#title' => t('Sanitization'), + '#description' => t('No piece of user-submitted content should ever be placed as-is into HTML.'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + + $format_options = array( + 'filter_xss' => t('Filter XSS') . theme('filter_tips', array('tips' => array(array( + array('tip' => t('Filters HTML to prevent cross-site-scripting (XSS) vulnerabilities.')), + array('tip' => t('Allowed HTML tags') . check_plain(':
    1. ')), + array('tip' => '' . t('Recommended for finder fields that contain only plain values or the above HTML tags.') . '') + ))), FALSE), + 'filter_xss_admin' => t('Filter XSS permissive') . theme('filter_tips', array('tips' => array(array( + array('tip' => t('Allows all tags that can be used inside an HTML body, save for scripts and styles.')), + array('tip' => '' . t('Recommended for finder fields that contain HTML.') . '') + ))), FALSE), + 'check_plain' => t('Check plain') . theme('filter_tips', array('tips' => array(array( + array('tip' => t('Encodes special characters in a plain-text string for display as HTML.')), + array('tip' => '' . t('Approved for finder fields that contain only plain values.') . '') + ))), FALSE), + 'check_url' => t('Check URL') . theme('filter_tips', array('tips' => array(array( + array('tip' => t('Strips dangerous protocols from a URI and encodes it for output to HTML.')), + array('tip' => '' . t('Approved for finder fields where the value is a URL.') . '') + ))), FALSE), + ); + $filter_formats = filter_formats(); + foreach ($filter_formats as $filter_format) { + $tips = _filter_tips($filter_format->format, FALSE); + $tips[$filter_format->name]['finder'] = array('tip' => t('Not pre-approved for finder fields, use with caution.')); + $format_options[$filter_format->format] = $filter_format->name . theme('filter_tips', array('tips' => $tips)); } + $form['sanitization']['format'] = array( + '#type' => 'radios', + '#title' => t('Sanitization filter'), + '#default_value' => !empty($field->format) ? $field->format : 'filter_xss', + '#options' => $format_options, + ); + + //if ($field_key != 'new' && empty($relationships)) { + // $form['no_config']['#markup'] = t('There is nothing to configure for this field.'); + //} + // Add buttons. $form['actions']['submit'] = array( '#type' => 'submit', diff --git a/plugins/element_handler/autocomplete.inc b/plugins/element_handler/autocomplete.inc index 50a19769df862e516b75df23eba7dfb116626018..bb2f1327c962950fa02867b0bf1ced01e8de8b6a 100644 --- a/plugins/element_handler/autocomplete.inc +++ b/plugins/element_handler/autocomplete.inc @@ -364,10 +364,6 @@ function finder_autocomplete_autocomplete($finder_name, $element_id, $keywords = $finder->find(); $choices = !empty($finder->find['results']) ? $finder->find['results'] : array(); - foreach (array_keys($choices) as $autofill) { - $choices[$autofill] = filter_xss($choices[$autofill]); - } - drupal_json_output($choices); }