Index: modules/block/block.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.module,v
retrieving revision 1.312
diff -u -r1.312 block.module
--- modules/block/block.module	9 Oct 2008 15:15:50 -0000	1.312
+++ modules/block/block.module	6 Nov 2008 04:33:48 -0000
@@ -198,7 +198,7 @@
       return $blocks;
 
     case 'configure':
-      $box = array('format' => FILTER_FORMAT_DEFAULT);
+      $box = array('format' => filter_default_format());
       if ($delta) {
         $box = block_box_get($delta);
       }
@@ -321,7 +321,7 @@
     '#type' => 'textarea',
     '#title' => t('Block body'),
     '#default_value' => $edit['body'],
-    '#input_format' => isset($edit['format']) ? $edit['format'] : FILTER_FORMAT_DEFAULT,
+    '#input_format' => isset($edit['format']) ? $edit['format'] : filter_default_format(),
     '#rows' => 15,
     '#description' => t('The content of the block as shown to the user.'),
     '#weight' => -17,
@@ -332,7 +332,7 @@
 
 function block_box_save($edit, $delta) {
   if (!filter_access($edit['body_format'])) {
-    $edit['body_format'] = FILTER_FORMAT_DEFAULT;
+    $edit['body_format'] = filter_default_format();
   }
 
   db_query("UPDATE {boxes} SET body = '%s', info = '%s', format = %d WHERE bid = %d", $edit['body'], $edit['info'], $edit['body_format'], $delta);
Index: modules/filter/filter.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.module,v
retrieving revision 1.231
diff -u -r1.231 filter.module
--- modules/filter/filter.module	1 Nov 2008 19:51:06 -0000	1.231
+++ modules/filter/filter.module	6 Nov 2008 04:33:50 -0000
@@ -12,7 +12,7 @@
  * This value can be passed to the filter APIs as a format ID: this is
  * equivalent to not passing an explicit format at all.
  */
-define('FILTER_FORMAT_DEFAULT', 0);
+define('FILTER_FORMAT_FALLBACK', 0);
 
 /**
  * Implementation of hook_help().
@@ -22,12 +22,12 @@
     case 'admin/help#filter':
       $output = '<p>' . t("The filter module allows administrators to configure text input formats for use on your site. An input format defines the HTML tags, codes, and other input allowed in both content and comments, and is a key feature in guarding against potentially damaging input from malicious users. Two input formats included by default are <em>Filtered HTML</em> (which allows only an administrator-approved subset of HTML tags) and <em>Full HTML</em> (which allows the full set of HTML tags). Additional input formats may be created by an administrator.") . '</p>';
       $output .= '<p>' . t('Each input format uses filters to manipulate text, and most input formats apply several different filters to text in a specific order. Each filter is designed for a specific purpose, and generally either adds, removes or transforms elements within user-entered text before it is displayed. A filter does not change the actual content of a post, but instead, modifies it temporarily before it is displayed. A filter may remove unapproved HTML tags, for instance, while another automatically adds HTML to make links referenced in text clickable.') . '</p>';
-      $output .= '<p>' . t('Users with access to more than one input format can use the <em>Input format</em> fieldset to choose between available input formats when creating or editing multi-line content. Administrators determine the input formats available to each user role, select a default input format, and control the order of formats listed in the <em>Input format</em> fieldset.') . '</p>';
-      $output .= '<p>' . t('For more information, see the online handbook entry for <a href="@filter">Filter module</a>.', array('@filter' => 'http://drupal.org/handbook/modules/filter/')) . '</p>';
+      $output .= '<p>' . t('Users with access to more than one input format can use the <em>Input format</em> fieldset to choose between available input formats when creating or editing multi-line content. Administrators determine the input formats available to each user role and control the order of formats listed in the <em>Input format</em> fieldset.') . '</p>';
+      $output .= '<p>' . t('The special %plain_text input format is available to users that don\'t have access to any other input formats. Content with this format will be displayed with line and paragraph breaks preserved but otherwise without any visible formatting.', array('%plain_text' => filter_admin_format_title(filter_format_load(FILTER_FORMAT_FALLBACK)))) . '</p>';
       return $output;
     case 'admin/settings/filters':
-      $output = '<p>' . t('Use the list below to review the input formats available to each user role, to select a default input format, and to control the order of formats listed in the <em>Input format</em> fieldset. (The <em>Input format</em> fieldset is displayed below textareas when users with access to more than one input format create multi-line content.) The input format selected as <em>Default</em> is available to all users and, unless another format is selected, is applied to all content. All input formats are available to users in roles with the "administer filters" permission.') . '</p>';
-      $output .= '<p>' . t('Since input formats, if available, are presented in the same order as the list below, it may be helpful to arrange the formats in descending order of your preference for their use. To change the order of an input format, grab a drag-and-drop handle under the <em>Name</em> column and drag to a new location in the list. (Grab a handle by clicking and holding the mouse while hovering over a handle icon.) Remember that your changes will not be saved until you click the <em>Save changes</em> button at the bottom of the page.') . '</p>';
+      $output = '<p>' . t('Use the list below to review the input formats available to each user role and to control the order of formats listed in the <em>Input format</em> fieldset. (The <em>Input format</em> fieldset is displayed below textareas when users with access to more than one input format create multi-line content.) All input formats are available to users in roles with the "Administer filters" permission.') . '</p>';
+      $output .= '<p>' . t('It may be helpful to arrange the formats in order of your preference for their use, since the default input format for each user is the first one in the list for which that user has access. To change the order of an input format, grab a drag-and-drop handle under the <em>Name</em> column and drag to a new location in the list. (Grab a handle by clicking and holding the mouse while hovering over a handle icon.) Remember that your changes will not be saved until you click the <em>Save changes</em> button at the bottom of the page.') . '</p>';
       return $output;
     case 'admin/settings/filters/%':
       return '<p>' . t('Every <em>filter</em> performs one particular change on the user input, for example stripping out malicious HTML or making URLs clickable. Choose which filters you want to apply to text in this input format. If you notice some filters are causing conflicts in the output, you can <a href="@rearrange">rearrange them</a>.', array('@rearrange' => url('admin/settings/filters/' . $arg[3] . '/order'))) . '</p>';
@@ -131,7 +131,11 @@
 }
 
 function filter_format_load($arg) {
-  return filter_formats($arg);
+  $formats = filter_formats();
+  if (isset($formats[$arg])) {
+    return $formats[$arg];
+  }
+  return FALSE;
 }
 
 /**
@@ -145,12 +149,43 @@
  * Implementation of hook_perm().
  */
 function filter_perm() {
-  return array(
-    'administer filters' => array(
-      'title' => t('Administer filters'),
-      'description' => t('Manage input formats and filters, and select which roles may use them. %warning', array('%warning' => t('Warning: Give to trusted roles only; this permission has security implications.'))),
-    ),
+  $perms['administer filters'] = array(
+    'title' => t('Administer filters'),
+    'description' => t('Manage input formats and filters, and use any of them, without restriction, when entering or editing content. %warning', array('%warning' => t('Warning: Give to trusted roles only; this permission has security implications.'))),
   );
+
+  // Generate permissions for each input format. Warn the administrator that
+  // any of them are potentially unsafe.
+  foreach (filter_formats(NULL, FALSE) as $format) {
+    $name = filter_permission_name($format);
+    if ($name) {
+      // Only link to the input format configuration page if the user who is
+      // viewing this will have access to that page.
+      $format_name_replacement = user_access('administer filters') ? l($format->name, 'admin/settings/filters/' . $format->format) : theme('placeholder', $format->name);
+      $perms[$name] = array(
+        'title' => t("Use the '@input_format' input format", array('@input_format' => $format->name)),
+        'description' => t('Use !input_format in forms when entering or editing content. %warning', array('!input_format' => $format_name_replacement, '%warning' => t('Warning: This permission may have security implications depending on how the input format is configured.'))),
+      );
+    }
+  }
+  return $perms;
+}
+
+/**
+ * Returns the machine-readable permission name for the provided input format.
+ *
+ * @param $format
+ *   An object representing the input format.
+ * @return
+ *   The machine-readable permission name, or FALSE if the provided input
+ *   format is either (a) malformed, or (b) the fallback format available
+ *   to all users (and therefore not controlled by the permission system).
+ */
+function filter_permission_name($format) {
+  if (isset($format->format) && $format->format != FILTER_FORMAT_FALLBACK) {
+    return 'use input format '. $format->format;
+  }
+  return FALSE;
 }
 
 /**
@@ -283,41 +318,75 @@
 }
 
 /**
- * Retrieve a list of input formats.
- */
-function filter_formats($index = NULL) {
-  global $user;
-  static $formats;
-
-  // Administrators can always use all input formats.
-  $all = user_access('administer filters');
-
-  if (!isset($formats)) {
-    $formats = array();
+ * Retrieve a list of input formats, ordered by weight.
+ *
+ * @param $account
+ *   Optional. If provided, only those formats that are allowed for this
+ *   user account will be returned. All formats will be returned otherwise.
+ * @param $include_fallback
+ *   Optional. If set to FALSE then the fallback format (plain text) will be
+ *   not be included in the list.
+ */
+function filter_formats($account = NULL, $include_fallback = TRUE) {
+  static $formats = array();
+
+  // Check if we've already loaded format data before doing a query.
+  if (!isset($formats['all'])) {
+    $formats['all'] = array();
+    $result = db_select('SELECT * FROM {filter_formats} ORDER BY weight');
+    while ($format = db_fetch_object($result)) {
+      $formats['all'][$format->format] = $format;
+    }
+  }
 
-    $query = db_select('filter_formats', 'f');
-    $query->addField('f', 'format', 'format');
-    $query->addField('f', 'name', 'name');
-    $query->addField('f', 'roles', 'roles');
-    $query->addField('f', 'cache', 'cache');
-    $query->addField('f', 'weight', 'weight');
-    $query->orderBy('weight');
-
-    // Build query for selecting the format(s) based on the user's roles.
-    if (!$all) {
-      $or = db_or()->condition('format', variable_get('filter_default_format', 1));
-      foreach ($user->roles as $rid => $role) {
-        $or->condition('roles', '%'. (int)$rid .'%', 'LIKE');
+  // Build a list of user-specific formats if not already set.
+  if (isset($account) && !isset($formats['user'][$account->uid])) {
+    $formats['user'][$account->uid] = array();
+    foreach ($formats['all'] as $format) {
+      if (filter_access($format, $account)) {
+        $formats['user'][$account->uid][$format->format] = $format;
       }
-      $query->condition($or);
     }
+  }
+
+  // Build the list of formats to be returned.
+  $return_formats = isset($account) ? $formats['user'][$account->uid] : $formats['all'];
 
-    $formats = $query->execute()->fetchAllAssoc('format');
+  // Add the default format if necessary.
+  if ($include_fallback) {
+    $return_formats[0] = new stdClass();
+    $return_formats[0]->format = FILTER_FORMAT_FALLBACK;
+    $return_formats[0]->name = 'Plain text';
+    $return_formats[0]->cache = 1;
+    $return_formats[0]->weight = 100;
   }
-  if (isset($index)) {
-    return isset($formats[$index]) ? $formats[$index] : FALSE;
+
+  return $return_formats;
+}
+
+/**
+ * Return the ID of the default input format for a particular user.
+ *
+ * @param $account
+ *   Optional. The user account to check. Defaults to the current logged-in
+ *   user.
+ */
+function filter_default_format($account = NULL) {
+  global $user;
+  if (!isset($account)) {
+    $account = $user;
   }
-  return $formats;
+  // Get a list of formats for this user, ordered by weight. The first one
+  // available is that user's default format.
+  $formats = filter_formats($account);
+  $first_format = array_shift($formats);
+  if (isset($first_format) && isset($first_format->format)) {
+    return $first_format->format;
+  }
+  // All users have access to the fallback format, so we fall back on it
+  // here too (however, under normal circumstances this code should never
+  // be reached).
+  return FILTER_FORMAT_FALLBACK;
 }
 
 /**
@@ -348,17 +417,10 @@
 }
 
 /**
- * Resolve a format id, including the default format.
- */
-function filter_resolve_format($format) {
-  return $format == FILTER_FORMAT_DEFAULT ? variable_get('filter_default_format', 1) : $format;
-}
-/**
  * Check if text in a certain input format is allowed to be cached.
  */
 function filter_format_allowcache($format) {
   static $cache = array();
-  $format = filter_resolve_format($format);
   if (!isset($cache[$format])) {
     $cache[$format] = db_result(db_query('SELECT cache FROM {filter_formats} WHERE format = %d', $format));
   }
@@ -381,6 +443,25 @@
         $filters[$format][$filter->module . '/' . $filter->delta] = $filter;
       }
     }
+
+    // Add the fallback plain text format filters.
+    // This format is only used when a user has no access to other formats.
+    if ($format == FILTER_FORMAT_FALLBACK) {
+      $filters[FILTER_FORMAT_FALLBACK] = array(
+        // Escape all HTML tags.
+        'filter/4' => (object) array(
+          'module' => 'filter',
+          'delta' => 4,
+          'weight' => 0,
+        ),
+        // Add line breaks.
+        'filter/1' => (object) array(
+          'module' => 'filter',
+          'delta' => 1,
+          'weight' => 1,
+        ),
+      );
+    }
   }
 
   return $filters[$format];
@@ -407,8 +488,8 @@
  * @param $text
  *    The text to be filtered.
  * @param $format
- *    The format of the text to be filtered. Specify FILTER_FORMAT_DEFAULT for
- *    the default format.
+ *    The format of the text to be filtered. If no format is provided, the
+ *    fallback "plain text" format will be used.
  * @param $check
  *    Whether to check the $format with filter_access() first. Defaults to TRUE.
  *    Note that this will check the permissions of the current user, so you
@@ -416,11 +497,9 @@
  *    showing content that is not (yet) stored in the database (eg. upon preview),
  *    set to TRUE so the user's permissions are checked.
  */
-function check_markup($text, $format = FILTER_FORMAT_DEFAULT, $check = TRUE) {
+function check_markup($text, $format = FILTER_FORMAT_FALLBACK, $check = TRUE) {
   // When $check = TRUE, do an access check on $format.
   if (isset($text) && (!$check || filter_access($format))) {
-    $format = filter_resolve_format($format);
-
     // Check for a cached version of this piece of text.
     $cache_id = $format . ':' . md5($text);
     if ($cached = cache_get($cache_id, 'cache_filter')) {
@@ -473,9 +552,19 @@
  * @return
  *   HTML for the form element.
  */
-function filter_form($value = FILTER_FORMAT_DEFAULT, $weight = NULL, $parents = array('format')) {
-  $value = filter_resolve_format($value);
-  $formats = filter_formats();
+function filter_form($value = NULL, $weight = NULL, $parents = array('format')) {
+  global $user;
+
+  // Get a list of filters that the current user has access to.
+  $formats = filter_formats($user);
+
+  // Use the default format for this user if none was selected.
+  $value = !isset($value) ? filter_default_format($user) : $value;
+
+  // If the user has access to any custom input formats, hide the fallback format.
+  if (count($formats) > 2) {
+    unset($formats[FILTER_FORMAT_FALLBACK]);
+  }
 
   $extra = theme('filter_tips_more_info');
 
@@ -506,15 +595,19 @@
   }
   else {
     // Only one format available: use a hidden form item and only show tips.
-    $format = array_shift($formats);
+    $format = reset($formats);
     $form[$format->format] = array('#type' => 'value', '#value' => $format->format, '#parents' => $parents);
-    $tips = _filter_tips(variable_get('filter_default_format', 1), FALSE);
+    $tips = _filter_tips($format->format, FALSE);
     $form['format']['guidelines'] = array(
       '#title' => t('Formatting guidelines'),
       '#markup' => theme('filter_tips', $tips, FALSE, $extra),
     );
   }
-  $form[] = array('#markup' => $extra);
+  // Show more information link if not using the fallback format.
+  $form['more_information'] = array(
+    '#markup' => $extra,
+    '#access' => !isset($formats[FILTER_FORMAT_FALLBACK]),
+  );
   return $form;
 }
 
@@ -529,17 +622,71 @@
 }
 
 /**
- * Returns TRUE if the user is allowed to access this format.
+ * Check if a user has access to a particular input format.
+ *
+ * @param $format
+ *   Either the format ID or format object that will be checked for access.
+ * @param $account
+ *   The user object that access will be checked against. Defaults to the
+ *   current logged-in user.
+ *
+ * @return
+ *   Boolean TRUE if the user has access to the requested filter.
  */
-function filter_access($format) {
-  $format = filter_resolve_format($format);
-  if (user_access('administer filters') || ($format == variable_get('filter_default_format', 1))) {
+function filter_access($format, $account = NULL) {
+  global $user;
+  if (!isset($account)) {
+    $account = $user;
+  }
+  // Handle special cases up front. All users have access to the fallback
+  // format, and administrators have access to all formats.
+  $format_id = isset($format->format) ? $format->format : $format;
+  if (user_access('administer filters', $account) || $format_id == FILTER_FORMAT_FALLBACK) {
     return TRUE;
   }
+  // Otherwise, retrieve the full format object if one was not provided.
+  if (!isset($format->format)) {
+    $format = filter_format_load($format);
+  }
+  // Check the permission if one exists; otherwise, we have a nonexistent
+  // format so we return FALSE.
+  $permission = filter_permission_name($format);
+  return $permission && user_access($permission, $account);
+}
+
+/**
+ * Retrieve a list of a roles that are allowed to use a particular format.
+ *
+ * @param $format
+ *   The format object that will be checked for access.
+ *
+ * @return
+ *   An array of roles structured $rid => $role_name.
+ */
+function filter_format_roles($format) {
+  $name = filter_permission_name($format);
+  if ($name) {
+    return user_roles(FALSE, $name);
+  }
+  // Don't list any roles if the permission doesn't exist, unless it's for
+  // the fallback format (which all roles have access to).
   else {
-    $formats = filter_formats();
-    return isset($formats[$format]);
+    return $format->format == FILTER_FORMAT_FALLBACK ? user_roles() : array();
+  }
+}
+
+/**
+ * Retrieve a list of formats that are allowed for a particular role.
+ */
+function filter_role_formats($rid) {
+  $formats = array();
+  foreach (filter_formats() as $format) {
+    $roles = filter_format_roles($format);
+    if (isset($roles[$rid])) {
+      $formats[$format->format] = $format->name;
+    }
   }
+  return $formats;
 }
 
 /**
@@ -551,11 +698,18 @@
  * Helper function for fetching filter tips.
  */
 function _filter_tips($format, $long = FALSE) {
+  global $user;
+
   if ($format == -1) {
-    $formats = filter_formats();
+    $formats = filter_formats($user);
   }
   else {
-    $formats = array(db_fetch_object(db_query("SELECT * FROM {filter_formats} WHERE format = %d", $format)));
+    $formats = array(filter_format_load($format));
+  }
+
+  // Only show the fallback format if the user has access to no other formats.
+  if (count($formats) > 1) {
+    unset($formats[FILTER_FORMAT_FALLBACK]);
   }
 
   $tips = array();
Index: modules/filter/filter.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.install,v
retrieving revision 1.9
diff -u -r1.9 filter.install
--- modules/filter/filter.install	14 Apr 2008 17:48:37 -0000	1.9
+++ modules/filter/filter.install	6 Nov 2008 04:33:49 -0000
@@ -64,13 +64,6 @@
         'default' => '',
         'description' => t('Name of the input format (Filtered HTML).'),
       ),
-      'roles' => array(
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => '',
-        'description' => t('A comma-separated string of roles; references {role}.rid.'), // This is bad since you can't use joins, nor index.
-      ),
       'cache' => array(
         'type' => 'int',
         'not null' => TRUE,
@@ -99,6 +92,11 @@
 }
 
 /**
+ * @defgroup updates-6.x-to-7.x Filter updates from 6.x to 7.x
+ * @{
+ */
+
+/**
  * Add a weight column to the filter formats table.
  */
 function filter_update_7000() {
@@ -122,3 +120,31 @@
   }
   return $ret;
 }
+
+/**
+ * Move filter format access to the user permissions handler.
+ */
+function filter_update_7002() {
+  $ret = array();
+
+  // Move role data from filter_formats to user permissions.
+  $all_roles = array_keys(user_roles());
+  $result = db_query("SELECT format, roles FROM {filter_formats}");
+  while ($format = db_fetch_object($result)) {
+    $format_roles = explode(',', $format->roles);
+    foreach ($format_roles as $format_role) {
+      if (in_array($format_role, $all_roles)) {
+        $ret[] = update_sql("INSERT INTO {role_permission} (rid, permission) VALUES (" . $format_role . ", " . filter_permission_name($format) . ")");
+      }
+    }
+  }
+  // Drop the roles field from filter_formats.
+  db_drop_field($ret, 'filter_formats', 'roles');
+
+  return $ret;
+}
+
+/**
+ * @} End of "defgroup updates-6.x-to-7.x"
+ * The next series of updates should start at 8000.
+ */
Index: modules/filter/filter.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.admin.inc,v
retrieving revision 1.16
diff -u -r1.16 filter.admin.inc
--- modules/filter/filter.admin.inc	13 Oct 2008 00:33:02 -0000	1.16
+++ modules/filter/filter.admin.inc	6 Nov 2008 04:33:49 -0000
@@ -16,37 +16,24 @@
 function filter_admin_overview() {
 
   // Overview of all formats.
-  $formats = filter_formats();
+  $formats = filter_formats(NULL, FALSE);
   $error = FALSE;
 
   $form = array('#tree' => TRUE);
   foreach ($formats as $id => $format) {
-    $roles = array();
-    foreach (user_roles() as $rid => $name) {
-      // Prepare a roles array with roles that may access the filter.
-      if (strstr($format->roles, ",$rid,")) {
-        $roles[] = $name;
-      }
-    }
-    $default = ($id == variable_get('filter_default_format', 1));
+    $roles = filter_format_roles($format);
     $options[$id] = '';
     $form[$id]['name'] = array('#markup' => $format->name);
-    $form[$id]['roles'] = array('#markup' => $default ? t('All roles may use default format') : ($roles ? implode(', ', $roles) : t('No roles may use this format')));
+    $form[$id]['roles'] = array('#markup' => $roles ? implode(', ', $roles) : t('No roles may use this format'));
     $form[$id]['configure'] = array('#markup' => l(t('configure'), 'admin/settings/filters/' . $id));
-    $form[$id]['delete'] = array('#markup' => $default ? '' : l(t('delete'), 'admin/settings/filters/delete/' . $id));
+    $form[$id]['delete'] = array('#markup' => l(t('delete'), 'admin/settings/filters/delete/' . $id));
     $form[$id]['weight'] = array('#type' => 'weight', '#default_value' => $format->weight);
   }
-  $form['default'] = array('#type' => 'radios', '#options' => $options, '#default_value' => variable_get('filter_default_format', 1));
   $form['submit'] = array('#type' => 'submit', '#value' => t('Save changes'));
   return $form;
 }
 
 function filter_admin_overview_submit($form, &$form_state) {
-  // Process form submission to set the default format.
-  if (is_numeric($form_state['values']['default'])) {
-    drupal_set_message(t('Default format updated.'));
-    variable_set('filter_default_format', $form_state['values']['default']);
-  }
   foreach ($form_state['values'] as $id => $data) {
     if (is_array($data) && isset($data['weight'])) {
       // Only update if this is a form element with weight.
@@ -70,7 +57,6 @@
         'data' => array(
           check_plain($element['name']['#markup']),
           drupal_render($element['roles']),
-          drupal_render($form['default'][$id]),
           drupal_render($element['weight']),
           drupal_render($element['configure']),
           drupal_render($element['delete']),
@@ -80,7 +66,7 @@
       unset($form[$id]);
     }
   }
-  $header = array(t('Name'), t('Roles'), t('Default'), t('Weight'), array('data' => t('Operations'), 'colspan' => 2));
+  $header = array(t('Name'), t('Roles'), t('Weight'), array('data' => t('Operations'), 'colspan' => 2));
   $output = theme('table', $header, $rows, array('id' => 'input-format-order'));
   $output .= drupal_render($form);
 
@@ -95,7 +81,7 @@
 function filter_admin_format_page($format = NULL) {
   if (!isset($format->name)) {
     drupal_set_title(t('Add input format'), PASS_THROUGH);
-    $format = (object)array('name' => '', 'roles' => '', 'format' => '');
+    $format = (object)array('name' => '', 'format' => '');
   }
   return drupal_get_form('filter_admin_format_form', $format);
 }
@@ -108,12 +94,6 @@
  * @see filter_admin_format_form_submit()
  */
 function filter_admin_format_form(&$form_state, $format) {
-  $default = ($format->format == variable_get('filter_default_format', 1));
-  if ($default) {
-    $help = t('All roles for the default format must be enabled and cannot be changed.');
-    $form['default_format'] = array('#type' => 'hidden', '#value' => 1);
-  }
-
   $form['name'] = array('#type' => 'textfield',
     '#title' => t('Name'),
     '#default_value' => $format->name,
@@ -121,23 +101,6 @@
     '#required' => TRUE,
   );
 
-  // Add a row of checkboxes for form group.
-  $form['roles'] = array('#type' => 'fieldset',
-    '#title' => t('Roles'),
-    '#description' => $default ? $help : t('Choose which roles may use this filter format. Note that roles with the "administer filters" permission can always use all the filter formats.'),
-    '#tree' => TRUE,
-  );
-
-  foreach (user_roles() as $rid => $name) {
-    $checked = strstr($format->roles, ",$rid,");
-    $form['roles'][$rid] = array('#type' => 'checkbox',
-      '#title' => $name,
-      '#default_value' => ($default || $checked),
-    );
-    if ($default) {
-      $form['roles'][$rid]['#disabled'] = TRUE;
-    }
-  }
   // Table with filters
   $all = filter_list_all();
   $enabled = filter_list_format($format->format);
@@ -195,7 +158,7 @@
   $name = trim($form_state['values']['name']);
   $cache = TRUE;
 
-  // Add a new filter format.
+  // Add a new input format.
   if (!$format) {
     $new = TRUE;
     db_query("INSERT INTO {filter_formats} (name) VALUES ('%s')", $name);
@@ -219,25 +182,7 @@
     }
   }
 
-  // We store the roles as a string for ease of use.
-  // We should always set all roles to TRUE when saving a default role.
-  // We use leading and trailing comma's to allow easy substring matching.
-  $roles = array();
-  if (isset($form_state['values']['roles'])) {
-    foreach ($form_state['values']['roles'] as $id => $checked) {
-      if ($checked) {
-        $roles[] = $id;
-      }
-    }
-  }
-  if (!empty($form_state['values']['default_format'])) {
-    $roles = ',' . implode(',', array_keys(user_roles())) . ',';
-  }
-  else {
-    $roles = ',' . implode(',', $roles) . ',';
-  }
-
-  db_query("UPDATE {filter_formats} SET cache = %d, name='%s', roles = '%s' WHERE format = %d", $cache, $name, $roles, $format);
+  db_query("UPDATE {filter_formats} SET cache = %d, name='%s' WHERE format = %d", $cache, $name, $format);
 
   cache_clear_all($format . ':', 'cache_filter', TRUE);
 
@@ -261,15 +206,11 @@
   $format = db_fetch_object(db_query('SELECT * FROM {filter_formats} WHERE format = %d', $format));
 
   if ($format) {
-    if ($format->format != variable_get('filter_default_format', 1)) {
+    if ($format->format != FILTER_FORMAT_FALLBACK) {
       $form['format'] = array('#type' => 'hidden', '#value' => $format->format);
       $form['name'] = array('#type' => 'hidden', '#value' => $format->name);
 
-      return confirm_form($form, t('Are you sure you want to delete the input format %format?', array('%format' => $format->name)), 'admin/settings/filters', t('If you have any content left in this input format, it will be switched to the default input format. This action cannot be undone.'), t('Delete'), t('Cancel'));
-    }
-    else {
-      drupal_set_message(t('The default format cannot be deleted.'));
-      drupal_goto('admin/settings/filters');
+      return confirm_form($form, t('Are you sure you want to delete the input format %format?', array('%format' => $format->name)), 'admin/settings/filters', t('If you have any content left in this input format, it will be converted to plain text. This action cannot be undone.'), t('Delete'), t('Cancel'));
     }
   }
   else {
@@ -284,7 +225,7 @@
   db_query("DELETE FROM {filter_formats} WHERE format = %d", $form_state['values']['format']);
   db_query("DELETE FROM {filters} WHERE format = %d", $form_state['values']['format']);
 
-  $default = variable_get('filter_default_format', 1);
+  $default = FILTER_FORMAT_FALLBACK;
   // Replace existing instances of the deleted format with the default format.
   db_query("UPDATE {node_revisions} SET format = %d WHERE format = %d", $default, $form_state['values']['format']);
   db_query("UPDATE {comments} SET format = %d WHERE format = %d", $default, $form_state['values']['format']);
Index: modules/simpletest/drupal_web_test_case.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/drupal_web_test_case.php,v
retrieving revision 1.53
diff -u -r1.53 drupal_web_test_case.php
--- modules/simpletest/drupal_web_test_case.php	1 Nov 2008 21:21:35 -0000	1.53
+++ modules/simpletest/drupal_web_test_case.php	6 Nov 2008 04:33:52 -0000
@@ -371,7 +371,7 @@
       'title'     => $this->randomName(8),
       'comment'   => 2,
       'changed'   => REQUEST_TIME,
-      'format'    => FILTER_FORMAT_DEFAULT,
+      'format'    => filter_default_format(),
       'moderate'  => 0,
       'promote'   => 0,
       'revision'  => 1,
Index: modules/system/system.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.install,v
retrieving revision 1.277
diff -u -r1.277 system.install
--- modules/system/system.install	3 Nov 2008 06:33:21 -0000	1.277
+++ modules/system/system.install	6 Nov 2008 04:33:53 -0000
@@ -385,12 +385,14 @@
 
   // Anonymous role permissions.
   db_query("INSERT INTO {role_permission} (rid, permission) VALUES (%d, '%s')", 1, 'access content');
+  db_query("INSERT INTO {role_permission} (rid, permission) VALUES (%d, '%s')", 1, 'use input format 1'); // Filtered HTML
 
   // Authenticated role permissions.
   db_query("INSERT INTO {role_permission} (rid, permission) VALUES (%d, '%s')", 2, 'access comments');
   db_query("INSERT INTO {role_permission} (rid, permission) VALUES (%d, '%s')", 2, 'access content');
   db_query("INSERT INTO {role_permission} (rid, permission) VALUES (%d, '%s')", 2, 'post comments');
   db_query("INSERT INTO {role_permission} (rid, permission) VALUES (%d, '%s')", 2, 'post comments without approval');
+  db_query("INSERT INTO {role_permission} (rid, permission) VALUES (%d, '%s')", 2, 'use input format 1'); // Filtered HTML
 
   db_query("INSERT INTO {variable} (name, value) VALUES ('%s', '%s')", 'theme_default', 's:7:"garland";');
   db_query("UPDATE {system} SET status = %d WHERE type = '%s' AND name = '%s'", 1, 'theme', 'garland');
@@ -401,8 +403,8 @@
   db_query("INSERT INTO {node_access} (nid, gid, realm, grant_view, grant_update, grant_delete) VALUES (%d, %d, '%s', %d, %d, %d)", 0, 0, 'all', 1, 0, 0);
 
   // Add input formats.
-  db_query("INSERT INTO {filter_formats} (name, roles, cache) VALUES ('%s', '%s', %d)", 'Filtered HTML', ',1,2,', 1);
-  db_query("INSERT INTO {filter_formats} (name, roles, cache) VALUES ('%s', '%s', %d)", 'Full HTML', '', 1);
+  db_query("INSERT INTO {filter_formats} (name, cache, weight) VALUES ('%s', %d, %d)", 'Filtered HTML', 1, 0);
+  db_query("INSERT INTO {filter_formats} (name, cache, weight) VALUES ('%s', %d, %d)", 'Full HTML', 1, 0);
 
   // Enable filters for each input format.
 
Index: CHANGELOG.txt
===================================================================
RCS file: /cvs/drupal/drupal/CHANGELOG.txt,v
retrieving revision 1.285
diff -u -r1.285 CHANGELOG.txt
--- CHANGELOG.txt	2 Nov 2008 10:52:53 -0000	1.285
+++ CHANGELOG.txt	6 Nov 2008 04:33:47 -0000
@@ -20,6 +20,7 @@
     * Implemented drag-and-drop positioning for language listing.
     * Implemented drag-and-drop positioning for poll options.
     * Provided descriptions and human-readable names for user permissions.
+    * Moved filter permissions to the main permissions page.
     * Removed comment controls for users.
     * Removed display order settings for comment module. Comment display
       order can now be customised using the Views module.
Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.301
diff -u -r1.301 form.inc
--- includes/form.inc	3 Nov 2008 09:54:43 -0000	1.301
+++ includes/form.inc	6 Nov 2008 04:33:48 -0000
@@ -1790,7 +1790,7 @@
  *   $form['body'] = array(
  *     '#type' => 'textarea',
  *     '#title' => t('Body'),
- *     '#input_format' => isset($node->format) ? $node->format : FILTER_FORMAT_DEFAULT,
+ *     '#input_format' => isset($node->format) ? $node->format : filter_default_format(),
  *   );
  * @endcode
  *
Index: modules/blogapi/blogapi.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/blogapi/blogapi.module,v
retrieving revision 1.132
diff -u -r1.132 blogapi.module
--- modules/blogapi/blogapi.module	12 Oct 2008 02:58:23 -0000	1.132
+++ modules/blogapi/blogapi.module	6 Nov 2008 04:33:49 -0000
@@ -202,7 +202,7 @@
   $edit['promote'] = in_array('promote', $node_type_default);
   $edit['comment'] = variable_get('comment_' . $edit['type'], 2);
   $edit['revision'] = in_array('revision', $node_type_default);
-  $edit['format'] = FILTER_FORMAT_DEFAULT;
+  $edit['format'] = filter_default_format($user);
   $edit['status'] = $publish;
 
   // Check for bloggerAPI vs. metaWeblogAPI.
@@ -622,7 +622,7 @@
 function blogapi_mt_supported_text_filters() {
   // NOTE: we're only using anonymous' formats because the MT spec
   // does not allow for per-user formats.
-  $formats = filter_formats();
+  $formats = filter_formats(drupal_anonymous_user());
 
   $filters = array();
   foreach ($formats as $format) {
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.993
diff -u -r1.993 node.module
--- modules/node/node.module	3 Nov 2008 05:55:56 -0000	1.993
+++ modules/node/node.module	6 Nov 2008 04:33:51 -0000
@@ -870,7 +870,7 @@
   // module-provided 'teaser' form item).
   if (!isset($node->teaser)) {
     if (isset($node->body)) {
-      $node->format = (!empty($node->body_format) ? $node->body_format : FILTER_FORMAT_DEFAULT);
+      $node->format = (!empty($node->body_format) ? $node->body_format : filter_default_format());
       $node->teaser = node_teaser($node->body, isset($node->format) ? $node->format : NULL);
       // Chop off the teaser from the body if needed. The teaser_include
       // property might not be set (eg. in Blog API postings), so only act on
Index: modules/node/node.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.pages.inc,v
retrieving revision 1.45
diff -u -r1.45 node.pages.inc
--- modules/node/node.pages.inc	13 Oct 2008 00:33:03 -0000	1.45
+++ modules/node/node.pages.inc	6 Nov 2008 04:33:51 -0000
@@ -297,7 +297,7 @@
     '#default_value' => $include ? $node->body : ($node->teaser . $node->body),
     '#rows' => 20,
     '#required' => ($word_count > 0),
-    '#input_format' => isset($node->format) ? $node->format : FILTER_FORMAT_DEFAULT,
+    '#input_format' => isset($node->format) ? $node->format : filter_default_format(),
   );
 
   return $form;
Index: modules/profile/profile.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/profile/profile.module,v
retrieving revision 1.246
diff -u -r1.246 profile.module
--- modules/profile/profile.module	12 Oct 2008 04:30:08 -0000	1.246
+++ modules/profile/profile.module	6 Nov 2008 04:33:51 -0000
@@ -289,7 +289,7 @@
   if (isset($user->{$field->name}) && $value = $user->{$field->name}) {
     switch ($field->type) {
       case 'textarea':
-        return check_markup($value);
+        return check_markup($value, filter_default_format($user), FALSE);
       case 'textfield':
       case 'selection':
         return $browse ? l($value, 'profile/' . $field->name . '/' . $value) : check_plain($value);
Index: modules/comment/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v
retrieving revision 1.660
diff -u -r1.660 comment.module
--- modules/comment/comment.module	1 Nov 2008 19:51:06 -0000	1.660
+++ modules/comment/comment.module	6 Nov 2008 04:33:49 -0000
@@ -1371,7 +1371,7 @@
     '#title' => t('Comment'),
     '#rows' => 15,
     '#default_value' => $default,
-    '#input_format' => isset($edit['format']) ? $edit['format'] : FILTER_FORMAT_DEFAULT,
+    '#input_format' => isset($edit['format']) ? $edit['format'] : filter_default_format(),
     '#required' => TRUE,
   );
 
