Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.512
diff -u -p -r1.512 form.inc
--- includes/form.inc	27 Nov 2010 19:12:56 -0000	1.512
+++ includes/form.inc	30 Nov 2010 05:22:01 -0000
@@ -1069,11 +1069,10 @@ function drupal_validate_form($form_id, 
 
   // If the session token was set by drupal_prepare_form(), ensure that it
   // matches the current user's session.
-  if (isset($form['#token'])) {
-    if (!drupal_valid_token($form_state['values']['form_token'], $form['#token'])) {
-      // Setting this error will cause the form to fail validation.
-      form_set_error('form_token', t('This form is outdated. Reload the page and try again. Contact the site administrator if the problem persists.'));
-    }
+  if (isset($form['#token']) && !drupal_valid_token($form_state['values']['form_token'], $form['#token'])) {
+    // Setting this error will cause the form to fail validation.
+    form_set_error('form_token', t('The form was outdated. If you still want to perform this action, submit the form again.'));
+    $reset_token = TRUE;
   }
 
   _form_validate($form, $form_state, $form_id);
@@ -1118,6 +1117,14 @@ function drupal_validate_form($form_id, 
     }
     $form_state['values'] = $values;
   }
+
+  // Reset the token if we found out above that the submitted one was invalid.
+  if (!empty($reset_token)) {
+    // Setting this value will cause the form to have an up-to-date token
+    // when it is re-rendered, therefore allowing the new copy of the form
+    // to be submitted successfully.
+    $form['form_token']['#value'] = drupal_get_token($form['#token']);
+  }
 }
 
 /**
Index: modules/simpletest/tests/form.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form.test,v
retrieving revision 1.76
diff -u -p -r1.76 form.test
--- modules/simpletest/tests/form.test	21 Nov 2010 10:14:25 -0000	1.76
+++ modules/simpletest/tests/form.test	30 Nov 2010 05:22:01 -0000
@@ -558,6 +558,34 @@ class FormValidationTestCase extends Dru
     $this->assertText(t('!name field is required.', array('!name' => 'Title')));
     $this->assertText('Test element is invalid');
   }
+
+  /**
+   * Tests re-submitting a form that contains an expired session token.
+   */
+  function testExpiredToken() {
+    $this->web_user = $this->drupalCreateUser(array());
+
+    $this->drupalLogin($this->web_user);
+    $this->drupalGet('form-test/validate');
+    $copy = $this->drupalGetContent();
+    $url = $this->getUrl();
+    $this->drupalLogout();
+
+    $this->drupalLogin($this->web_user);
+    $this->drupalSetContent($copy, $url);
+
+    $edit = array(
+      'name' => 'Drupal',
+    );
+    $this->drupalPost(NULL, $edit, 'Save');
+    $this->assertText(t('The form was outdated. If you still want to perform this action, submit the form again.'));
+    $this->assertNoText(t('@label value: @value', array('@label' => 'Name', '@value' => $edit['name'])));
+
+    // Do what it suggests us to do.
+    $this->drupalPost(NULL, array(), 'Save');
+    $this->assertNoText(t('The form was outdated. If you still want to perform this action, submit the form again.'));
+    $this->assertText(t('@label value: @value', array('@label' => 'Name', '@value' => $edit['name'])));
+  }
 }
 
 /**
Index: modules/simpletest/tests/form_test.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form_test.module,v
retrieving revision 1.56
diff -u -p -r1.56 form_test.module
--- modules/simpletest/tests/form_test.module	27 Nov 2010 19:12:56 -0000	1.56
+++ modules/simpletest/tests/form_test.module	30 Nov 2010 05:22:02 -0000
@@ -325,6 +325,17 @@ function form_test_validate_form_validat
 }
 
 /**
+ * Form submit handler for form_test_validate_form().
+ */
+function form_test_validate_form_submit(&$form, &$form_state) {
+  // Output the element's value from $form_state.
+  drupal_set_message(t('@label value: @value', array(
+    '@label' => $form['name']['#title'],
+    '@value' => $form_state['values']['name'],
+  )));
+}
+
+/**
  * Builds a simple form with a button triggering partial validation.
  */
 function form_test_limit_validation_errors_form($form, &$form_state) {
