Index: modules/block/block.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.module,v
retrieving revision 1.415
diff -u -p -r1.415 block.module
--- modules/block/block.module	28 Mar 2010 11:16:29 -0000	1.415
+++ modules/block/block.module	29 Mar 2010 14:04:00 -0000
@@ -438,7 +438,6 @@ function block_custom_block_form($edit =
     '#description' => t('The content of the block as shown to the user.'),
     '#required' => TRUE,
     '#weight' => -17,
-    '#access' => filter_access(filter_format_load($edit['format'])),
   );
 
   return $form;
Index: modules/block/block.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.test,v
retrieving revision 1.47
diff -u -p -r1.47 block.test
--- modules/block/block.test	12 Mar 2010 05:14:14 -0000	1.47
+++ modules/block/block.test	29 Mar 2010 14:04:00 -0000
@@ -132,7 +132,7 @@ class BlockTestCase extends DrupalWebTes
     $block_admin = $this->drupalCreateUser(array('administer blocks'));
     $this->drupalLogin($block_admin);
     $this->drupalGet('admin/structure/block/manage/block/' . $bid . '/configure');
-    $this->assertNoText(t('Block body'));
+    $this->assertFieldByXPath("//textarea[@name='body[value]' and @disabled='disabled']", t('This field has been disabled because you do not have sufficient permissions to edit it.'), t('Body field contains denied message'));
     $this->drupalPost('admin/structure/block/manage/block/' . $bid . '/configure', array(), t('Save block'));
     $this->assertNoText(t('Ensure that each block description is unique.'));
 
Index: modules/filter/filter.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.module,v
retrieving revision 1.324
diff -u -p -r1.324 filter.module
--- modules/filter/filter.module	26 Mar 2010 17:14:45 -0000	1.324
+++ modules/filter/filter.module	29 Mar 2010 14:50:48 -0000
@@ -849,6 +849,38 @@ function filter_process_format($element)
     '#weight' => 0,
   );
 
+  // Lastly, disallow editing of this field if the user is not allowed to use
+  // the stored and preselected text format. But only, if that format actually
+  // exists.
+  $all_formats = filter_formats();
+  if (!isset($formats[$element['#format']]) && isset($all_formats[$element['#format']])) {
+    // Overload default values into #value to make them unalterable.
+    $element['value']['#value'] = $element['value']['#default_value'];
+    $element['format']['format']['#value'] = $element['format']['format']['#default_value'];
+
+    // Prepend #pre_render callback to replace field value with user notice
+    // prior to rendering.
+    if (!isset($element['value']['#pre_render'])) {
+      $element['value']['#pre_render'] = array();
+    }
+    array_unshift($element['value']['#pre_render'], 'filter_form_access_denied');
+
+    // Cosmetic adjustments.
+    if (isset($element['value']['#rows'])) {
+      $element['value']['#rows'] = 3;
+    }
+    $element['value']['#disabled'] = TRUE;
+    $element['value']['#resizable'] = FALSE;
+
+    // Hide the text format selector and any other child element (such as text
+    // field's summary).
+    foreach (element_children($element) as $key) {
+      if ($key != 'value') {
+        $element[$key]['#access'] = FALSE;
+      }
+    }
+  }
+
   return $element;
 }
 
@@ -885,6 +917,22 @@ function filter_form_after_build($elemen
 }
 
 /**
+ * #pre_render callback for #type 'text_format' to hide field value from prying eyes.
+ *
+ * To not break form processing and previews if a user does not have access to a
+ * stored text format, the expanded form elements in filter_process_format() are
+ * forced to take over the stored #default_values for 'value' and 'format'.
+ * However, to prevent the unfiltered, original #value from being displayed to
+ * the user, we replace it with a friendly notice here.
+ *
+ * @see filter_process_format()
+ */
+function filter_form_access_denied($element) {
+  $element['#value'] = t('This field has been disabled because you do not have sufficient permissions to edit it.');
+  return $element;
+}
+
+/**
  * Render a text format-enabled form element.
  *
  * @param $variables
Index: modules/filter/filter.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.test,v
retrieving revision 1.62
diff -u -p -r1.62 filter.test
--- modules/filter/filter.test	7 Mar 2010 23:14:20 -0000	1.62
+++ modules/filter/filter.test	29 Mar 2010 14:52:31 -0000
@@ -389,7 +389,7 @@ class FilterAdminTestCase extends Drupal
   }
 }
 
-class FilterAccessTestCase extends DrupalWebTestCase {
+class FilterFormatAccessTestCase extends DrupalWebTestCase {
   protected $admin_user;
   protected $web_user;
   protected $allowed_format;
@@ -397,8 +397,8 @@ class FilterAccessTestCase extends Drupa
 
   public static function getInfo() {
     return array(
-      'name' => 'Filter access functionality',
-      'description' => 'Test the filter access system.',
+      'name' => 'Filter format access',
+      'description' => 'Tests access to text formats.',
       'group' => 'Filter',
     );
   }
@@ -406,8 +406,15 @@ class FilterAccessTestCase extends Drupa
   function setUp() {
     parent::setUp();
 
+    $this->full_html_format = db_query_range('SELECT * FROM {filter_format} WHERE name = :name', 0, 1, array(':name' => 'Full HTML'))->fetchObject();
+
     // Create two text formats and grant a regular user access to one of them.
-    $this->admin_user = $this->drupalCreateUser(array('administer filters'));
+    $this->admin_user = $this->drupalCreateUser(array(
+      'administer filters',
+      'create page content',
+      'edit any page content',
+      filter_permission_name($this->full_html_format),
+    ));
     $this->drupalLogin($this->admin_user);
     $formats = array();
     for ($i = 0; $i < 2; $i++) {
@@ -418,7 +425,11 @@ class FilterAccessTestCase extends Drupa
       $formats[] = filter_format_load($format_id);
     }
     list($this->allowed_format, $this->disallowed_format) = $formats;
-    $this->web_user = $this->drupalCreateUser(array('create page content', filter_permission_name($this->allowed_format)));
+
+    $this->web_user = $this->drupalCreateUser(array(
+      'create page content',
+      filter_permission_name($this->allowed_format),
+    ));
   }
 
   function testFormatPermissions() {
@@ -469,6 +480,61 @@ class FilterAccessTestCase extends Drupa
   }
 
   /**
+   * Test editing a page using a disallowed text format.
+   *
+   * Verifies that a regular user is able to edit a page, but is not allowed to
+   * change the fields which use an inaccessible text format.
+   */
+  function testFormatWidgetPermissions() {
+    $langcode = LANGUAGE_NONE;
+    $title_key = "title";
+    $body_value_key = "body[$langcode][0][value]";
+    $body_format_key = "body[$langcode][0][format]";
+
+    // Create node to edit.
+    $this->drupalLogin($this->admin_user);
+    $edit = array();
+    $edit['title'] = $this->randomName(8);
+    $edit[$body_value_key] = $this->randomName(16);
+    $edit[$body_format_key] = $this->full_html_format->format;
+    $this->drupalPost('node/add/page', $edit, t('Save'));
+    $node = $this->drupalGetNodeByTitle($edit['title']);
+
+    // Try to edit with a less privileged user.
+    $this->moderator = $this->drupalCreateUser(array(
+      'edit any page content',
+      'create page content',
+    ));
+    $this->drupalLogin($this->moderator);
+    $this->drupalGet('node/' . $node->nid);
+    $this->clickLink(t('Edit'));
+
+    // Verify that body field is read-only and contains replacement value.
+    $this->assertFieldByXPath("//textarea[@name='$body_value_key' and @disabled='disabled']", t('This field has been disabled because you do not have sufficient permissions to edit it.'), t('Text format access denied message found.'));
+
+    // Verify that title can be changed, but preview displays original body.
+    $new_edit = array();
+    $new_edit['title'] = $this->randomName(8);
+    $this->drupalPost(NULL, $new_edit, t('Preview'));
+    $this->assertText($edit[$body_value_key], t('Old body found in preview.'));
+
+    // Save and verify that only the title was changed.
+    $this->drupalPost(NULL, $new_edit, t('Save'));
+    $this->assertNoText($edit['title'], t('Old title not found.'));
+    $this->assertText($new_edit['title'], t('New title found.'));
+    $this->assertText($edit[$body_value_key], t('Old body found.'));
+
+    // Delete the Full HTML text format.
+    filter_format_delete($this->full_html_format);
+    $this->resetFilterCaches();
+
+    // Verify that body field can be edited and a new format can be selected.
+    $this->drupalGet('node/' . $node->nid . '/edit');
+    $this->assertNoFieldByXPath("//textarea[@name='$body_value_key' and @disabled='disabled']", NULL, t('Text format access denied message not found.'));
+    $this->assertFieldByXPath("//select[@name='$body_format_key']", NULL, t('Text format selector found.'));
+  }
+
+  /**
    * Returns the expected HTML for a particular text format selector.
    *
    * @param $format
