Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.326
diff -u -p -r1.326 form.inc
--- includes/form.inc	30 Mar 2009 03:15:40 -0000	1.326
+++ includes/form.inc	3 Apr 2009 07:48:07 -0000
@@ -1929,10 +1929,39 @@ function form_process_text_format($eleme
     $element['value'] = (array)$element;
     $element['value']['#weight'] = 0;
     unset($element['value']['#description']);
-    $element['#type'] = 'markup';
-    $element['#theme'] = NULL;
-    $element['#theme_wrapper'] = 'text_format_wrapper';
-    $element['format'] = filter_form($element['#text_format'], 1, $element_parents);
+
+    if (filter_access($element['#text_format'])) {
+      $element['#type'] = 'markup';
+      $element['#theme'] = NULL;
+      $element['#theme_wrapper'] = 'text_format_wrapper';
+      $element['format'] = filter_form($element['#text_format'], 1, $element_parents);
+    }
+    else {
+      $element['value']['#access'] = FALSE;
+
+      $element['#default_value'] = t('This field has been disabled because you do not have sufficient permissions to edit it.');
+      $element['#name'] = $element['value']['#name'] . '_denied';
+      $element['value']['#value_callback'] = 'form_text_format_default_value';
+
+      // Disable field, ensure #value is the #default_value and limit height
+      $element['#disabled'] = TRUE;
+      $element['#value'] = $element['#default_value'];
+      if (isset($element['#rows']) && $element['#rows'] > 5) {
+        $element['#rows'] = 5;
+      }
+      // Disabled attribute is needed because #disabled has already been processed.
+      $element['#attributes']['disabled'] = 'disabled';
+
+      // Disable unecessary resizable.
+      $element['#resizable'] = FALSE;
+
+      // Add fixed format.
+      $element['format'] = array(
+        '#type' => 'value',
+        '#value' => $element['#text_format'],
+        '#parents' => $element_parents,
+      );
+    }
 
     // We need to clear the #text_format from the new child otherwise we
     // would get into an infinite loop.
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1033
diff -u -p -r1.1033 node.module
--- modules/node/node.module	26 Mar 2009 13:31:25 -0000	1.1033
+++ modules/node/node.module	3 Apr 2009 07:48:08 -0000
@@ -291,8 +291,17 @@ function node_mark($nid, $timestamp) {
 
 /**
  * See if the user used JS to submit a teaser.
+ *
+ * Disables teaser feature if body field is disabled.
  */
 function node_teaser_js(&$form, &$form_state) {
+
+  // Disable teaser fields when body is disabled
+  if (isset($form['body']['value']['#access']) && $form['body']['value']['#access'] == FALSE) {
+    $form['teaser_js']['#access'] = FALSE;
+    unset($form_state['values']['teaser_js']);
+  }
+  
   if (isset($form_state['input']['teaser_js'])) {
     // Glue the teaser to the body.
     if (trim($form_state['values']['teaser_js'])) {
@@ -330,6 +339,12 @@ function node_teaser_js(&$form, &$form_s
 function node_teaser_include_verify(&$form, &$form_state) {
   $message = '';
 
+  // Disable teaser fields when body is disabled, form state needs to be unset so that it is ignored
+  if (isset($form['body']['value']['#access']) && $form['body']['value']['#access'] == FALSE) {
+    $form['teaser_include']['#access'] = FALSE;
+    unset($form_state['values']['teaser_include']);
+  }
+
   // $form_state['input'] is set only when the form is built for preview/submit.
   if (isset($form_state['input']['body']) && isset($form_state['values']['teaser_include']) && !$form_state['values']['teaser_include']) {
     // "teaser_include" checkbox is present and unchecked.
@@ -1944,7 +1959,7 @@ function node_feed($nids = FALSE, $chann
         $item->body = $content;
         unset($item->teaser);
       }
-    
+
       // Allow modules to modify the fully-built node.
       node_invoke_node($item, 'alter', $teaser, FALSE);
     }
@@ -2309,11 +2324,6 @@ function node_access($op, $node, $accoun
   if (empty($account)) {
     $account = $user;
   }
-  // If the node is in a restricted format, disallow editing.
-  if ($op == 'update' && !filter_access($node->format)) {
-    return FALSE;
-  }
-
   if (user_access('bypass node access', $account)) {
     return TRUE;
   }
Index: modules/node/node.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.test,v
retrieving revision 1.19
diff -u -p -r1.19 node.test
--- modules/node/node.test	31 Mar 2009 01:49:52 -0000	1.19
+++ modules/node/node.test	3 Apr 2009 07:48:08 -0000
@@ -363,6 +363,104 @@ class PageEditTestCase extends DrupalWeb
     $this->assertText($edit['title'], t('Title displayed.'));
     $this->assertText($edit['body'], t('Body displayed.'));
   }
+  /**
+   * Test edit page with special text format.
+   *
+   * Test if a normal user is able to edit the page but is not allowed to change
+   * the fields which use a text format he's not allowed to use.
+   */
+  function testPageEditLimitedPermission() {
+    $admin_user = $this->drupalCreateUser(array('administer filters', 'edit any page content', 'create page content'));
+    $normal_user = $this->drupalCreateUser(array('edit any page content', 'create page content'));
+
+    $this->drupalLogout();
+    $this->drupalLogin($admin_user);
+
+    list($filtered, $full) = $this->checkFilterFormats();
+
+    // Create node to edit.
+    $edit = array();
+    $edit['title'] = $this->randomName(8);
+    $edit['body'] = $this->randomName(16);
+    $edit['body_format'] = $full;
+    $this->drupalPost('node/add/page', $edit, t('Save'));
+
+    // Check that the node exists in the database.
+    $node = $this->drupalGetNodeByTitle($edit['title']);
+    $this->assertTrue($node, t('Node found in database.'));
+
+    // Check that "edit" link points to correct page.
+    $this->clickLink(t('Edit'));
+    $edit_url = url("node/$node->nid/edit", array('absolute' => true));
+    $actual_url = $this->getURL();
+    $this->assertEqual($edit_url, $actual_url, t('On edit page.'));
+
+    // Check that the title and body fields are displayed with the correct values.
+    $this->assertLink(t('Edit'), 0, t('Edit tab found.'));
+    $this->assertFieldByName('title', $edit['title'], t('Title field displayed.'));
+    $this->assertFieldByName('body', '<!--break-->' . $edit['body'], t('Body field displayed.'));
+
+    // Edit the content of the node.
+    $edit = array();
+    $edit['title'] = $this->randomName(8);
+    $edit['body'] = $this->randomName(16);
+    // Stay on the current page, without reloading.
+    $this->drupalPost(NULL, $edit, t('Save'));
+
+    // Check that the title and body fields are displayed with the updated values.
+    $this->assertText($edit['title'], t('Title displayed.'));
+    $this->assertText($edit['body'], t('Body displayed.'));
+
+    // Try to edit with normal user
+    $this->drupalLogout();
+    $this->drupalLogin($normal_user);
+
+    $this->drupalGet("node/$node->nid");
+
+    // Check that "edit" link points to correct page.
+    $this->clickLink(t('Edit'));
+    $edit_url = url("node/$node->nid/edit", array('absolute' => true));
+    $actual_url = $this->getURL();
+    $this->assertEqual($edit_url, $actual_url, t('On edit page.'));
+
+    // Check if body field is read only
+    $this->assertFieldByXPath("//textarea[@id='edit-body' 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'));
+
+    // Check if teaser is disabled
+    $this->assertNoField('teaser_js', t('Teaser field is not available'));
+    $this->assertNoField('teaser_include', t('Teaser include checkbox is not available'));
+
+    // Try to "force" the change
+    $new_edit = array();
+    $new_edit['title'] = $this->randomName(8);
+    $this->drupalPost("node/$node->nid/edit", $new_edit, t('Save'));
+
+    // Check that only the title is displayed with the updated values, the body should use the old values
+    $this->assertText($new_edit['title'], t('New title displayed.'));
+    $this->assertText($edit['body'], t('Old body displayed.'));
+  }
+
+    /**
+   * Query the database to get the two basic formats.
+   *
+   * @return Array Array containing filtered and full filter ids.
+   */
+  function checkFilterFormats() {
+    $result = db_query('SELECT format, name FROM {filter_format}');
+
+    $filtered = -1;
+    $full = -1;
+    while ($format = db_fetch_object($result)) {
+      if ($format->name == 'Filtered HTML') {
+        $filtered = $format->format;
+      }
+      elseif ($format->name == 'Full HTML') {
+        $full = $format->format;
+      }
+    }
+
+    return array($filtered, $full);
+  }
 }
 
 class PagePreviewTestCase extends DrupalWebTestCase {
