Index: fckeditor.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fckeditor/fckeditor.module,v
retrieving revision 1.19.2.3
diff -u -r1.19.2.3 fckeditor.module
--- fckeditor.module	7 Feb 2007 22:49:52 -0000	1.19.2.3
+++ fckeditor.module	10 Feb 2007 18:26:34 -0000
@@ -47,7 +47,6 @@
             '!fckeditorlink'=>l(t('FCKeditor homepage'), 'http://www.fckeditor.net'),
             '!userguidelink'=>l(t('FCKeditor userguide'), 'http://wiki.fckeditor.net/UsersGuide'))
       );
-      $output .= "<div class=\"more-link\">".l('more help...','admin/help/fckeditor')."</div>";
       break;
     case 'admin/help#fckeditor':
       $output = t("<p>The FCKeditor module allows Drupal to replace textarea fields with a rich text or <acronym title=\"What You See Is What You Get\">WYSIWYG</acronym> editor. This editor brings many of the powerful functionalities of known desktop editors like Word to the web. It's relatively lightweight and doesn't require any kind of installation on the client computer.</p>
@@ -201,39 +200,28 @@
     '#description' => t('Choose a toolbar set for administrators.'),
   );
 
-  $form['fckeditor_exclude_settings'] = array(
+  $form['fckeditor_visbility_settings'] = array(
     '#type' => 'fieldset',
     '#weight' => -15,
-    '#title' => t('Exclusion settings'),
-    '#collapsible' => TRUE,
-    '#collapsed' => FALSE,
+    '#title' => t('Visiblity settings'),
   );
-  $form['fckeditor_exclude_settings']['fckeditor_minimum_rows'] = array(
+  $form['fckeditor_visbility_settings']['fckeditor_minimum_rows'] = array(
     '#type' => 'textfield',
     '#title' => t('Minimum rows'),
     '#default_value' => variable_get('fckeditor_minimum_rows', 5),
     '#description' => t("Textareas must have a minimum of rows before FCKeditor will be triggered. Enter '1' if you do not want to use this feature."),
   );
-  /**
-   * get excluded fields - so we can have normal textareas too
-   * split the phrase by any number of commas or space characters,
-   * which include " ", \r, \t, \n and \f
-   */
-  $form['fckeditor_exclude_settings']['fckeditor_exclude'] = array(
+  $form['fckeditor_visbility_settings']['fckeditor_allowed'] = array(
     '#type' => 'textarea',
-    '#title' => t('Exclude fields'),
+    '#title' => t('Allowed paths/fields'),
     '#cols' => 60,
     '#rows' => 5,
-    '#default_value' => variable_get("fckeditor_exclude", ''),
-    '#description' => t("Names (HTML ID's) of fields that may not have an FCKeditor (separated by commas, spaces or newlines. You may also use * for a wildcard)"),
-  );
-  $form['fckeditor_exclude_settings']['fckeditor_exclude_toggle'] = array(
-    '#type' => 'radios',
-    '#title' => t('Use inclusion or exclusion mode'),
-    '#default_value' => variable_get('fckeditor_exclude_toggle', '0'),
-    '#options' => array('0'=>t('Exclude fields'), '1'=>t('Include fields'), '2'=>t('Path only')),
-    '#description' => t('Choose what to do with the above values. &quot;Exclude fields&quot; wil disable the editor on all fields matching the above, &quot;Include fields&quot; will only load the editor for the fields mentioned above and &quot;Path only&quot; will match the all textareas at the mentioned paths.'),
+    '#default_value' => variable_get("fckeditor_allowed", ''),
+    '#description' => t('Set the textarea IDs and paths that will have FCKeditor. Each line must contain a path (* is a wildcard) and a textarea ID, separated by |. For example: <em>node/add/*|edit-body</em> or <em>node/*/edit|*</em>'),
+    '#wysiwyg' => FALSE,
   );
+  _fckeditor_allowed(NULL, TRUE); // reset the allowed paths/fields list
+
 
   $form['fckeditor_special_settings'] = array(
     '#type' => 'fieldset',
@@ -291,7 +279,6 @@
   return system_settings_form($form);
 }
 
-
 /**
  * This function create the HTML objects required for the FCKeditor
  *
@@ -301,138 +288,181 @@
  *   The same $element with extra FCKeditor markup and initialization
  */
 function fckeditor_process_textarea($element) {
-  $exclude = preg_split("/[\s,]+/", strip_tags(variable_get("fckeditor_exclude", '')));
-  $toggle = variable_get('fckeditor_exclude_toggle', '0');
-  
-  switch ($toggle) {
-    case (1):
-      $enabled = fckeditor_idsearch($element['#id'], $exclude);
-      break;
-    case (2):
-      // This bizarre bit of magic courtesy of block.module
-      $path = drupal_get_path_alias($_GET['q']);
-      $regexp = '/^('. preg_replace(array('/(\r\n?|\n)/', '/\\\\\*/', '/(^|\|)\\\\<front\\\\>($|\|)/'), array('|', '.*', '\1'. preg_quote(variable_get('site_frontpage', 'node'), '/') .'\2'), preg_quote(variable_get("fckeditor_exclude", ''), '/')) .')$/';
-      if(preg_match($regexp, $path)) {
-        $enabled = true;
-      }
-      break;
-    case (0):
-    default:
-      $enabled = !fckeditor_idsearch($element['#id'], $exclude);
-      break;
-  }
+  // set a static variable to avoid multiple insert of the same javascript functions
+  static $fck_js_added = 0;
 
-  if (($element['#rows'] > variable_get('fckeditor_minimum_rows', 5)) && $enabled) {
-    // only replace textarea when it has enough rows and it is not in the exclusion list
+  // Check if fckeditor is allowed for the current textarea
+  if (!_fckeditor_allowed($element)) return $element;
 
-    // setting some variables
-    $module_drupal_path	= drupal_get_path('module', 'fckeditor');
-    $module_full_path	= base_path() . $module_drupal_path;
-    // get the default drupal files path
-    $files_path = base_path() . file_directory_path();
-    // '-' in a javascript id will not work
-    $js_id = 'oFCKeditor_' . str_replace('-', '_', $element['#id']);
-
-    // configured in settings
-    $width = variable_get("fckeditor_width", '100%');
-
-    // sensible default for small toolbars
-    $height = $element['#rows'] * 14 + 100;
-
-    // nessecary because FCKeditor interferes with resize script
-    $element['#resizable'] = FALSE;
-
-    drupal_add_js($module_drupal_path . '/fckeditor/fckeditor.js');
-
-    if (user_access('use advanced fckeditor')) {
-      $toolbar = variable_get("fckeditor_advanced_toolbar", 'DrupalFull');
-      $height += 100; // sensible default for admin toolbars toolbars
+  // Setting some variables
+  $module_drupal_path = drupal_get_path('module', 'fckeditor');
+  $module_full_path = base_path() . $module_drupal_path;
+  // get the default drupal files path
+  $files_path = file_directory_path();
+  // '-' in a javascript id will not work
+  $js_id = 'oFCKeditor_' . str_replace('-', '_', $element['#id']);
+
+  // configured in settings
+  $width = variable_get("fckeditor_width", '100%');
+
+  // sensible default for small toolbars
+  $height = $element['#rows'] * 14 + 100;
+
+  // nessecary because FCKeditor interferes with resize script
+  $element['#resizable'] = FALSE;
+
+  drupal_add_js($module_drupal_path . '/fckeditor/fckeditor.js');
+
+  if (user_access('use advanced fckeditor')) {
+    $toolbar = variable_get("fckeditor_advanced_toolbar", 'DrupalFull');
+    $height += 100; // sensible default for admin toolbars toolbars
+  }
+  else {
+    $toolbar = variable_get("fckeditor_default_toolbar", 'DrupalBasic');
+  }
+
+  // add javascript code
+  $js = '
+    <script type="text/javascript">
+      function fck_textarea_replace(oFCK) {
+        oFCK.BasePath = "%full_path/fckeditor/";
+        oFCK.Config["CustomConfigurationsPath"] = "%full_path/fckeditor.config.js";
+        oFCK.ToolbarSet = "%toolbar";
+        oFCK.Height = "%height";
+  ';
+
+  // code for filebrowser for users that have access
+  if (user_access('allow fckeditor file uploads')) {
+    if (variable_get("fckeditor_upload_advanced", '0')) {
+      $js .= '
+        oFCK.Config["LinkBrowserURL"] = "%full_path/fckeditor/editor/filemanager/browser/default/browser.html?Connector=connectors/php/connector.php&ServerPath=/%files_path";
+        oFCK.Config["ImageBrowserURL"] = "%full_path/fckeditor/editor/filemanager/browser/default/browser.html?Type=Image&Connector=connectors/php/connector.php&ServerPath=/%files_path";
+        oFCK.Config["FlashBrowserURL"] = "%full_path/fckeditor/editor/filemanager/browser/default/browser.html?Type=Flash&Connector=connectors/php/connector.php&ServerPath=/%files_path";
+      ';
     }
     else {
-      $toolbar = variable_get("fckeditor_default_toolbar", 'DrupalBasic');
+      $js .= '
+        oFCK.Config["LinkBrowser"] = false;
+        oFCK.Config["ImageBrowser"] = false;
+        oFCK.Config["FlashBrowser"] = false;
+      ';
     }
-
-  	$element['#suffix'] .= "\n<script type=\"text/javascript\">
-var ".$js_id." = new FCKeditor( '".$element['#id']."' );
-".$js_id.".BasePath	= '".$module_full_path."/fckeditor/';
-".$js_id.".Config['CustomConfigurationsPath'] = '".$module_full_path."/fckeditor.config.js';
-".$js_id.".ToolbarSet = '".$toolbar."';
-".$js_id.".Height = '".$height."';\n";
-
-    // add code for filebrowser for users that have access
-    if (user_access('allow fckeditor file uploads')==1) {
-      if (variable_get("fckeditor_upload_advanced", '0')) {
-        $element['#suffix'] .= $js_id.".Config['LinkBrowserURL'] = '".$module_full_path."/fckeditor/editor/filemanager/browser/default/browser.html?Connector=connectors/php/connector.php&ServerPath=".$files_path."';
-  ".$js_id.".Config['ImageBrowserURL'] = '".$module_full_path."/fckeditor/editor/filemanager/browser/default/browser.html?Type=Image&Connector=connectors/php/connector.php&ServerPath=".$files_path."';
-  ".$js_id.".Config['FlashBrowserURL'] = '".$module_full_path."/fckeditor/editor/filemanager/browser/default/browser.html?Type=Flash&Connector=connectors/php/connector.php&ServerPath=".$files_path."';\n";
-      } else {
-        $element['#suffix'] .= $js_id.".Config['LinkBrowser'] = false;
-".$js_id.".Config['ImageBrowser'] = false;
-".$js_id.".Config['FlashBrowser'] = false;\n";
-      }
-      if (variable_get("fckeditor_upload_basic", '0')==1) {
-        $element['#suffix'] .= $js_id.".Config['LinkUploadURL'] = '".$module_full_path."/fckeditor/editor/filemanager/upload/php/upload.php';
-  ".$js_id.".Config['ImageUploadURL'] = '".$module_full_path."/fckeditor/editor/filemanager/upload/php/upload.php';
-  ".$js_id.".Config['FlashUploadURL'] = '".$module_full_path."/fckeditor/editor/filemanager/upload/php/upload.php';\n";
-      } else {
-        $element['#suffix'] .= $js_id.".Config['LinkUpload'] = false;
-".$js_id.".Config['ImageUpload'] = false;
-".$js_id.".Config['FlashUpload'] = false;\n";
-      }
-    } else {
-      $element['#suffix'] .= $js_id.".Config['LinkBrowser'] = false;
-".$js_id.".Config['ImageBrowser'] = false;
-".$js_id.".Config['FlashBrowser'] = false;
-".$js_id.".Config['LinkUpload'] = false;
-".$js_id.".Config['ImageUpload'] = false;
-".$js_id.".Config['FlashUpload'] = false;\n";
+    if (variable_get("fckeditor_upload_basic", '0')) {
+      $js .= '
+        oFCK.Config["LinkUploadURL"] = "%full_path/fckeditor/editor/filemanager/upload/php/upload.php";
+        oFCK.Config["ImageUploadURL"] = "%full_path/fckeditor/editor/filemanager/upload/php/upload.php";
+        oFCK.Config["FlashUploadURL"] = "%full_path/fckeditor/editor/filemanager/upload/php/upload.php";
+      ';
     }
-    $custom_style = variable_get("fckeditor_stylesheet", "");
-    if (!empty($custom_style) && is_string($custom_style)) {
-      $element['#suffix'] .=  $js_id.".Config['EditorAreaCSS'] = '".$custom_style."';";
-    }
-    $element['#suffix'] .= "</script>\n";
-
-  	if (variable_get('fckeditor_popup', '0')) {
-  		// Add the script file with the popup open function.
-      drupal_add_js($module_drupal_path . '/fckeditor.popup.js');
-  		$element['#suffix'] .= " <span class=\"fckeditor_popuplink\">(<a href=\"#\" onclick=\"FCKeditor_OpenPopup('".$module_full_path."/fckeditor.popup.html?var=".$js_id."&el=".$element['#id']."');return false;\">" . t('Open rich editor') . "</a>)</span>";
-  	}
     else {
-      // if no popup mode, add the editor
-   		$element['#suffix'] .= "<script type=\"text/javascript\">
-  ".$js_id.".ReplaceTextarea();
-</script>\n";
+      $js .= '
+        oFCK.Config["LinkUpload"] = false;
+        oFCK.Config["ImageUpload"] = false;
+        oFCK.Config["FlashUpload"] = false;
+      ';
     }
   }
-  
+  else {
+      $js .= '
+        oFCK.Config["LinkBrowser"] = false;
+        oFCK.Config["ImageBrowser"] = false;
+        oFCK.Config["FlashBrowser"] = false;
+        oFCK.Config["LinkUpload"] = false;
+        oFCK.Config["ImageUpload"] = false;
+        oFCK.Config["FlashUpload"] = false;
+      ';
+  }
+
+  $custom_style = variable_get('fckeditor_stylesheet', '');
+  if ($custom_style) {
+    $js .=  'oFCK.Config["EditorAreaCSS"] = "%custom_style"';
+  }
+
+  $js .= '
+        oFCK.ReplaceTextarea();
+      }
+    </script>
+  ';
+  $variables = array('%toolbar' => $toolbar, '%height' => $height, '%custom_style' => $custom_style,
+    '%full_path' => $module_full_path, '%files_path' => $files_path);
+  if (!$fck_js_added) {
+    drupal_set_html_head(strtr($js, $variables));
+  }
+  $fck_js_added = 1;
+
+  if (variable_get('fckeditor_popup', '0')) {
+    // Add the script file with the popup open function.
+    drupal_add_js($module_drupal_path . '/fckeditor.popup.js');
+    $element['#suffix'] .= " <span class=\"fckeditor_popuplink\">(<a href=\"#\" onclick=\"FCKeditor_OpenPopup('".
+      $module_full_path."/fckeditor.popup.html?var=".$js_id."&el=".$element['#id']."');return false;\">" .
+      t('Open rich editor') . "</a>)</span>";
+  }
+  else {
+    // if no popup mode, add the editor
+    $js = '
+      var %fck_id = new FCKeditor("%element_id");
+      fck_textarea_replace(%fck_id);
+    ';
+    $variables = array('%fck_id' => $js_id, '%element_id' => $element['#id']);
+    $element['#suffix'] = drupal_get_js('header', array('inline' => array(array('code' => strtr($js, $variables)))));
+  }
+
   // display the field id for administrators
   if (user_access('administer site configuration')) {
-    $element['#suffix'] .= '<span class="textarea-identifier">The ID for for excluding or including this element is: '.$element['#id'].' - the path is: '.$_GET['q'].'</span>';
+    $element['#suffix'] .= '<span class="textarea-identifier">'.
+      t('The ID for for excluding or including this element is %id - the path is %path',
+        array('%id' => $element['#id'], '%path' => $_GET['q'])) . '</span>';
   }
 
   return $element;
 }
 
 /**
- * Search the field id for matches in array of matches
+ * Check whether to show fckeditor or not for the current textarea.
  *
- * @param $search
- *   A string representing a form field id
- * @ param $array
- *   An $array with strings to match the $search parameter against
+ * @param $element
+ *   The current textarea.
+ * @param $reset_allow_list
+ *   Whether or not to reset the allowed paths/fields list.
  *
  * @return
  *   TRUE on match, FALSE on no match
  */
-function fckeditor_idsearch($search, $array) {
-  foreach ($array as $key => $value) {
-    if (!empty($value) && preg_match('/^'.str_replace('*','.*',addslashes($value)).'$/i', $search)) {
-      // on any first match we know we're done here so return positive
-      return true;
+function _fckeditor_allowed($element, $reset_allow_list = FALSE) {
+  static $allow_list = array();
+  if ($reset_allow_list) {
+    $allow_list = array();
+    return;
+  }
+
+  // Do not replace textarea if the "wysiwyg" param is set to FALSE
+  if ($element['#wysiwyg'] === FALSE) return FALSE;
+
+  // Do not replace textarea if it has not enough rows
+  if ($element['#rows'] < variable_get('fckeditor_minimum_rows', 5)) return $element;
+
+  // Do not replace textarea if it is not in the allowed list
+  if (empty($allow_list)) {
+    $lines = split("[,\n\r]", variable_get('fckeditor_allowed', ''));
+    foreach ($lines as $line) {
+      if ($line = trim($line)) {
+        list($page, $id) = explode('|', $line);
+	if ($id = trim($id)) {
+	  $allow_list[trim($page)][] = $id;
+	}
+      }
+    }
+  }
+  $path = drupal_get_path_alias($_GET['q']);
+  foreach($allow_list as $page => $id) {
+    $regexp = '/^('.preg_replace(array('/(\r\n?|\n)/', '/\\\\\*/'), array('|', '.*'), preg_quote($page, '/')).')$/';
+    $page_match = !(1 xor preg_match($regexp, $path));
+     if ($page_match) {
+      if (in_array('*', (array)$allow_list[$page])) return TRUE;
+      return (in_array($element['#id'], (array)$allow_list[$page]));
     }
   }
-  return false;
+  return FALSE;
 }
 
 /**
