From 4cdd90b0f3955a5b26a7d11cbcbf0b85526d26c9 Mon Sep 17 00:00:00 2001
From: Damian Czepierga <damian@czepierga.pl>
Date: Mon, 30 Jan 2012 12:41:27 +0100
Subject: [PATCH 2/4] [D7] Change security filters policy

---
 ckeditor.css                |   45 ++++++++++++++++++++-
 images/delete.png           |  Bin 0 -> 715 bytes
 images/tick.png             |  Bin 0 -> 537 bytes
 includes/ckeditor.admin.inc |   90 +++++++++++++++++++++++-------------------
 includes/ckeditor.admin.js  |   45 +++++++++++++++-------
 includes/ckeditor.lib.inc   |   75 ++++++++++++++++++++++++++++++++---
 includes/ckeditor.page.inc  |   10 +---
 7 files changed, 193 insertions(+), 72 deletions(-)
 create mode 100644 images/delete.png
 create mode 100644 images/tick.png

diff --git a/ckeditor.css b/ckeditor.css
index 8f3f55f..d2b8d55 100644
--- a/ckeditor.css
+++ b/ckeditor.css
@@ -112,10 +112,49 @@ li.sortableItem {
     z-index: 99;
 }
 
-#security-filters .filter-warning {
-    display: none;
+#security-filters .filter-text-formats {
+    float: left;
+    clear: both;
+    width: 15%;
+    font-size: 11px;
+    font-weight: bold;
+    padding: 10px 0px;
+}
+
+#security-filters .filter-text-formats .filter-text-format-status {
+    float: left;
+    padding-right: 20px;
+}
+
+#security-filters .filter-text-formats .enabled {
+    background: url(images/tick.png) no-repeat right center;
+}
+
+#security-filters .filter-text-formats .disabled {
+    background: url(images/delete.png) no-repeat right center;
+}
+
+#security-filters .filter-info {
+    float: left;
+    width: 85%;
+}
+
+#security-filters .fieldset-legend {
+    background: none;
+    padding-left: 10px;
+}
+
+#security-filters .fieldset-legend a {
+    font-weight: normal;
+    font-size: 10px;
+    padding-left: 5px;
+}
+
+#security-filters .filter-wrapper {
     clear: both;
-    color: red;
+    float: left;
+    border-bottom: 1px solid #CCCCCC;
+    width: 100%;
 }
 
 /* Fix for fieldset for-edit-apperance in Firefox*/
diff --git a/images/delete.png b/images/delete.png
new file mode 100644
index 0000000000000000000000000000000000000000..08f249365afd29594b51210c6e21ba253897505d
GIT binary patch
literal 715
zcmV;+0yO=JP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!T}ebiR5;6}
zllx0kVHn5#Tecsf1c`2hgi%nK^D=kV+T5njvrLa$EMjSnone|mjm2E}L#U;8)yiKo
zO>C4}Mrzlg<+1Y8PEBfUp0jJpx4B>@E+cy3`^(Gw`Mf+2&yxZm<$to~Vpgvg&QKNR
z_f#1(r6svZt%iF?s+n<8X?B&!h3g9Dbb8_=MX}!;HiQSAh`bp^WMl~Z-44teO7W_Y
zV4thSL{h;rJY7!l3%5J4H1!tIzB`Dv+YxO(haWeausGZYkI8^hWj6mzo=L0{%;<E2
z80_Y*w_}NMA$su)e0B@`wrYegSP*HT5w@N{_}&f79VIb*XrKGBY>yxzh{5!Htr?51
zvG|W62MzC8BZ76hRpCyO2zOn<%e)K>NHge!-~)Ap33OdWw6hsLYbCxGNt0%wk_2z7
zfyYvXheSG)5HRK1VB~%mq7Dmurw#bi@hEcOr3&G1ZiF*$M=&9nB#VNf&Q^r$4G5kp
zTURh&s)E0%5&hyVD}sp<72~zmAY`Y(9aqO6CXF%=zFHGzO-A&I(pE}v70YQxCPJ{Y
z4L+?5-crdLn3ZRPEs!A4ehEY3ZRpL~w9>@aMN+{F4dI@v&>(QDHQum!mG~E^$OS8l
z!7?%Uwib*ROP67Hw`ika)gX-(<Pal@1N`)16#~~<@x7jghg9OTS^;mJ8T{oIOsMnG
zla<QHU?S-#Kb7w%o*dlEj!JgnOSKW+hV$`!syc>8Ia`-u_IEhxG7U<13kSsMW+$<e
xd62)I>lbb2dUMm5p6pa}cjgA+U$^mJ^AjD?&bdi)8~y+Q002ovPDHLkV1g8IMc@Dc

literal 0
HcmV?d00001

diff --git a/images/tick.png b/images/tick.png
new file mode 100644
index 0000000000000000000000000000000000000000..a9925a06ab02db30c1e7ead9c701c15bc63145cb
GIT binary patch
literal 537
zcmV+!0_OdRP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzt4TybR5;7M
zli4mqVHAaX=Q!_TZq*o5LaK&TC+g@aMJbINs;8}1t3yf*$E6r*j>Hs{AQG2a)rMyf
zFQK~pm1x3+7!nu%-M`k}``c>^00{o_1pjWJUTfl8mg=3qGEl8H@}^@w`VUx0_$uy4
z2FhRqKX}xI*?Tv<H&*Dj)Tr<j*}f%KtVns|p$^k=7pCG)bZ)nz(p!uYhmcBtGG4MZ
zhBKz;vsk_?<x?$B#+(Sm9B-A&-Qq;?SOJwD!Fa)z^`0_M+_eepu5##IOknYS`&tC<
z#^ArRgWXi2%vG2uvgcE2i2di<+TKw6qc6;1IyMf?mMlSF4apWIQ-(bTzNj7ETMiu?
z3Y3nE5@K5(^<j-YCz?$CVH?a>1DJd8z#F#0c%*~rM30HE1@2o5m~}ZyoWhqv>ql{V
z1ZGE0lgcoK^lx+eqc*rAX1Ky;Xx3U%u#zG!m-;eD1Qsn@kf3|F9qz~|95=&g3(7!X
zB}JAT>RU;a%vaNOGnJ%e1=K6eAh43c(QN8RQ6~GP%O}Jju$~Ld*%`mO1p<rCAIZx2
bmuq|lzM`o-QVIh|00000NkvXXu0mjfO@{7Q

literal 0
HcmV?d00001

diff --git a/includes/ckeditor.admin.inc b/includes/ckeditor.admin.inc
index bacdac8..8e8333c 100644
--- a/includes/ckeditor.admin.inc
+++ b/includes/ckeditor.admin.inc
@@ -377,6 +377,9 @@ function ckeditor_admin_profile_form($form, $form_state, $profile = NULL) {
 
     module_load_include('inc', 'ckeditor', 'includes/ckeditor.lib');
 
+    $editor_path = ckeditor_path(FALSE);
+    $module_drupal_path = drupal_get_path('module', 'ckeditor');
+
     $skin_options = ckeditor_load_skin_options();
     $lang_options = ckeditor_load_lang_options();
 
@@ -441,9 +444,11 @@ function ckeditor_admin_profile_form($form, $form_state, $profile = NULL) {
     }
 
     $formats = array();
+    $input_format_config_links = array();
     foreach ($orig_formats AS $format) {
         if ( (arg(4) == 'edit' && !empty($profile->input_formats) && array_key_exists($format->format, $profile->input_formats)) || !array_key_exists($format->format, $used_formats) ) {
             $formats[$format->format] = $format->name;
+            $input_format_config_links[$format->format] = array("name" => $format->name, "config_url" => url("admin/config/content/formats/" . $format->format));
         }
     }
 
@@ -466,13 +471,15 @@ function ckeditor_admin_profile_form($form, $form_state, $profile = NULL) {
 
     $form['security']['filters'] = array(
         '#id' => 'security-filters',
-        '#type' => 'fieldset',
-        '#title' => t('Security filters'),
-        '#description' => t('Please choose all filters that protect your content (probably not all filters listed below are security filters).'),
-        '#tree' => TRUE,
+        '#type' => 'container'
     );
 
-    $all_filters = filter_get_filters();
+    $form['security']['filters']['__header'] = array(
+        '#type' => 'item',
+        '#title' => t('Security filters'),
+        '#description' => t('Below is a list of security filters along with their status for each text format.<br/><br/>The following statuses are available:</br><img src="!img_enabled"/> - the filter is configured for a given text format and will be run on the content during the filtering proces.<br/><img src="!img_disabled"/> - the filter is disabled for a given text format and will not be run on the content during the filtering process.<br/><br/>In order to modify the security filters settings for each of the text formats, you need to visit the text format configuration sections as listed below: <ul class="text-formats-config"></ul>', array("!img_enabled" => base_path() . $module_drupal_path . "/images/tick.png", "!img_disabled" => base_path() . $module_drupal_path . "/images/delete.png")),
+        '#weight' => -10
+     );
 
     //get text formats filters
     $input_format_filters = array();
@@ -485,22 +492,10 @@ function ckeditor_admin_profile_form($form, $form_state, $profile = NULL) {
             }
         }
     }
-    drupal_add_js(array('text_format_filters' => $input_format_filters), 'setting');
-
-    _ckeditor_admin_profile_form_add_filter($form, 'filter_html', "Limit allowed HTML tags", "Removes the attributes that the built-in \"Limit allowed HTML tags\"
--filter does not allow inside HTML elements/tags", !empty($profile->settings['filters']['filter_html']));
-
-    //load security filters from whitelisted modules
-    $security_modules = array('htmLawed', 'htmltidy', 'htmlpurifier', 'wysiwyg_filter');
-    foreach ($security_modules as $val) {
-        _ckeditor_admin_profile_form_add_module_filters($form, $profile, $val);
-    }
+    drupal_add_js(array('text_format_filters' => $input_format_filters, 'text_formats_config_links' => $input_format_config_links), 'setting');
 
-    //load security filters added by API
-    $external_module_filters = module_invoke_all('ckeditor_security_filter');
-    foreach ($external_module_filters as $module_filter_name => $module_filter_conf) {
-        _ckeditor_admin_profile_form_add_filter($form, $module_filter_name, $module_filter_conf['title'], $module_filter_conf['description'], !empty($profile->settings['filters'][$module_filter_name]));
-    }
+    $security_filters = ckeditor_security_filters();
+    _ckeditor_admin_profile_form_security_filters($form, $profile, $security_filters);
 
     $form['security']['ss'] = array(
         '#type' => 'radios',
@@ -592,8 +587,6 @@ function ckeditor_admin_profile_form($form, $form_state, $profile = NULL) {
         drupal_add_js(array('ckeditor_uicolor' => $color_palette), 'setting');
     }
 
-    $editor_path = ckeditor_path(FALSE);
-    $module_drupal_path = drupal_get_path('module', 'ckeditor');
     drupal_add_js('window.CKEDITOR_BASEPATH = "' . base_path() . $editor_path . '/"', array('type' => 'inline', 'weight' => -100));
     drupal_add_js($editor_path . '/ckeditor.js', array('type' => 'file', 'preprocess' => FALSE));
     drupal_add_js($module_drupal_path . '/ckeditor.config.js', 'file');
@@ -1449,26 +1442,41 @@ function ckeditor_toolbar_buttons_all() {
 }
 
 /**
- * Add security filters from a selected Drupal module to the configuration panel available in the CKEditor profile administration section
+ * Add security filters to the configuration panel available in the CKEditor profile administration section
  */
-function _ckeditor_admin_profile_form_add_module_filters(&$form, $profile, $module_name) {
-    if (module_exists($module_name)) {
-        $module_filters = module_invoke($module_name, 'filter_info');
-        foreach ($module_filters as $module_filter_name => $module_filter_conf) {
-            _ckeditor_admin_profile_form_add_filter($form, $module_filter_name, $module_filter_conf['title'], $module_filter_conf['description'], !empty($profile->settings['filters'][$module_filter_name]));
+function _ckeditor_admin_profile_form_security_filters(&$form, $profile, $security_filters) {
+    foreach ((array) $security_filters['modules'] as $module_name => $module_conf) {
+        if (isset($module_conf['project_page']) && strlen($module_conf['project_page']) > 0) {
+            $form['security']['filters'][$module_name] = array(
+                '#type' => 'fieldset',
+                '#title' => t("!title <a href=\"!link\" target=\"_blank\">project page</a>", array("!title" => $module_conf['title'], "!link" => $module_conf['project_page'])),
+                '#weight' => $module_conf['weight']
+            );
+        }
+        else {
+            $form['security']['filters'][$module_name] = array(
+                '#type' => 'fieldset',
+                '#title' => t("!title", array("!title" => $module_conf['title'])),
+                '#weight' => $module_conf['weight']
+            );
         }
-    }
-}
 
-/**
- *  Add security filter to the configuration panel available in the CKEditor profile administration section
- */
-function _ckeditor_admin_profile_form_add_filter(&$form, $name, $title, $desc, $default) {
-    $warning = '<div class="filter-warning"><strong> Warning:</strong><code> ' . $title . ' </code> is disabled for the following text formats: <span data="text_formats"></span>. In order to use it you have to enable it in the text format configuration.</div>';
-    $form['security']['filters'][$name] = array(
-        '#type' => 'checkbox',
-        '#title' => t("@data", array('@data' => $title)),
-        '#default_value' => $default,
-        '#description' => t("!data !warning", array('!data' => $desc, '!warning' => $warning))
-    );
+        if ($module_conf['installed'] == TRUE) {
+            foreach ((array) $module_conf['filters'] as $filter_name => $filter_conf) {
+                $filter_text_formats = '<div class="filter-text-formats" filter="' . $filter_name . '"></div><div class="filter-info">';
+                $form['security']['filters'][$module_name][$filter_name] = array(
+                    '#type' => 'item',
+                    '#title' => t("@data", array('@data' => $filter_conf['title'])),
+                    '#description' => t("!data", array('!data' => $filter_conf['description'])),
+                    '#prefix' => t("<div class=\"filter-wrapper\"></div>!formats", array("!formats" => $filter_text_formats)),
+                    '#suffix' => "</div>"
+                );
+            }
+        }
+        else {
+            $form['security']['filters'][$module_name]['not_installed'] = array(
+                '#markup' => t("<i>Not installed</i>")
+            );
+        }
+     }
 }
diff --git a/includes/ckeditor.admin.js b/includes/ckeditor.admin.js
index 441fe56..f9d0e46 100644
--- a/includes/ckeditor.admin.js
+++ b/includes/ckeditor.admin.js
@@ -125,24 +125,41 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
 
         $("#input-formats :checkbox").change(function() {
             $('#security-filters .filter-warning').hide();
-            $('#security-filters .filter-warning span[data="text_formats"]').html('');
+            $('#security-filters div.filter-text-formats[filter]').html('');
+            $('#security-filters ul.text-formats-config').html('');
             $('#input-formats :checked').each(function() {
                 var format_name = $(this).val();
                 var format_label = $('label[for="' + $(this).attr('id') + '"]').html();
-                $('#security-filters :checkbox').each(function() {
-                    var filter_name = ($(this).attr('name').match(/^filters\[(.*)\]$/))[1];
+
+                if (typeof(Drupal.settings.text_formats_config_links[format_name]) != 'undefined') {
+                    var text = "<li>" + format_label + " - <a href=\"" + Drupal.settings.text_formats_config_links[format_name].config_url + "\">configure</a></li>";
+                    var dataSel = $('#security-filters ul.text-formats-config');
+                    var html = dataSel.html();
+                    if (html == null || html.length == 0) {
+                        dataSel.html(text);
+                    }
+                    else {
+                        html += text;
+                        dataSel.html(html);
+                    }
+                }
+
+                $('#security-filters div.filter-text-formats[filter]').each(function() {
+                    var filter_name = $(this).attr('filter');
+                    var dataSel = $(this);
+                    var html = dataSel.html();
+                    var status = "enabled";
                     if (typeof Drupal.settings.text_format_filters[format_name][filter_name] == 'undefined') {
-                        var dataSel = $(this).siblings('div.description').find('span[data="text_formats"]');
-                        var html = dataSel.html();
-                        if (html.length == 0) {
-                            dataSel.html(format_label)
-                        }
-                        else {
-                            html += ', ';
-                            html += format_label;
-                            dataSel.html(html);
-                        }
-                        dataSel.parent().show();
+                        status = "disabled";
+                    }
+                    var text = "<span class=\"filter-text-format-status " + status + "\">" + format_label + ': </span><br/>';
+
+                    if (html == null || html.length == 0) {
+                        dataSel.html(text);
+                    }
+                    else {
+                        html += text;
+                        dataSel.html(html);
                     }
                 });
             });
diff --git a/includes/ckeditor.lib.inc b/includes/ckeditor.lib.inc
index dc14992..5e04adf 100644
--- a/includes/ckeditor.lib.inc
+++ b/includes/ckeditor.lib.inc
@@ -1410,20 +1410,81 @@ function ckeditor_load_by_field( $field, $format, $show_toggle = TRUE, $add_fiel
  */
 function ckeditor_security_filters() {
     $security_filters = array();
-    $security_filters['filter_html'] = TRUE;
-    $security_modules = array('htmLawed', 'htmltidy', 'htmlpurifier', 'wysiwyg_filter');
-    foreach ($security_modules as $module_name) {
+
+    $security_filters['modules'] = array(
+        'htmLawed' => array(
+            'title' => 'htmLawed',
+            'project_page' => 'http://drupal.org/project/htmLawed',
+            'weight' => 0,
+            'installed' => FALSE,
+            'filters' => array()
+        ),
+        'htmltidy' => array(
+            'title' => 'Htmltidy',
+            'project_page' => 'http://drupal.org/project/htmltidy',
+            'weight' => 0,
+            'installed' => FALSE,
+            'filters' => array()
+        ),
+        'htmlpurifier' => array(
+            'title' => 'HTML Purifier',
+            'project_page' => 'http://drupal.org/project/htmlpurifier',
+            'weight' => 0,
+            'installed' => FALSE,
+            'filters' => array()
+        ),
+        'wysiwyg_filter' => array(
+            'title' => 'WYSIWYG Filter',
+            'project_page' => 'http://drupal.org/project/wysiwyg_filter',
+            'weight' => 0,
+            'installed' => FALSE,
+            'filters' => array()
+        )
+    );
+
+    $security_filters['filters'] = array();
+
+    foreach ($security_filters['modules'] as $module_name => $module_conf) {
         if (module_exists($module_name)) {
+            $security_filters['modules'][$module_name]['installed'] = TRUE;
             $module_filters = module_invoke($module_name, 'filter_info');
             foreach ($module_filters as $module_filter_name => $module_filter_conf) {
-                $security_filters[$module_filter_name] = TRUE;
+                $security_filters['modules'][$module_name]['filters'][$module_filter_name] = $module_filter_conf;
+                $security_filters['filters'][$module_filter_name] = TRUE;
             }
         }
     }
+
+    //add filters from Drupal core
+    $security_filters['modules']['__drupal'] = array(
+        'title' => 'Drupal core',
+        'project_page' => FALSE,
+        'weight' => -1,
+        'installed' => TRUE,
+        'filters' => array(
+            'filter_html' => array(
+                'title' => 'Limit allowed HTML tags',
+                'description' => 'Removes the attributes that the built-in "Limit allowed HTML tags"-filter does not allow inside HTML elements/tags'
+            )
+        )
+    );
+    $security_filters['filters']['filter_html'] = TRUE;
+
+    //load security filters added by API
     $external_module_filters = module_invoke_all('ckeditor_security_filter');
-    foreach ($external_module_filters as $module_filter_name => $module_filter_conf) {
-        $security_filters[$module_filter_name] = TRUE;
+    if (count($external_module_filters) > 0) {
+        $security_filters['modules']['__external'] = array(
+            'title' => 'External filters',
+            'project_page' => FALSE,
+            'weight' => 1,
+            'installed' => TRUE,
+            'filters' => array()
+        );
+        foreach ($external_module_filters as $module_filter_name => $module_filter_conf) {
+            $security_filters['modules']['__external']['filters'][$module_filter_name] = $module_filter_conf;
+            $security_filters['filters'][$module_filter_name] = TRUE;
+        }
     }
-    
+
     return $security_filters;
 }
diff --git a/includes/ckeditor.page.inc b/includes/ckeditor.page.inc
index c78bfc3..97c3190 100644
--- a/includes/ckeditor.page.inc
+++ b/includes/ckeditor.page.inc
@@ -159,13 +159,9 @@ function ckeditor_filter_xss() {
     module_load_include('inc', 'ckeditor', 'includes/ckeditor.lib');
     $profile = ckeditor_get_profile($_POST['input_format']);
 
-    if ($profile == FALSE) {
-        $settings = array();
-        $settings['filters'] = ckeditor_security_filters();
-    }
-    else {
-        $settings = $profile->settings;
-    }
+    $settings = array();
+    $security_filters = ckeditor_security_filters();
+    $settings['filters'] = $security_filters['filters'];
 
     $text = $_POST['text'];
     $filters = filter_get_filters();
-- 
1.7.4.msysgit.0

