Index: includes/form.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/form.inc,v retrieving revision 1.493 diff -u -p -r1.493 form.inc --- includes/form.inc 16 Sep 2010 20:14:49 -0000 1.493 +++ includes/form.inc 20 Sep 2010 21:15:38 -0000 @@ -986,13 +986,11 @@ 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('This form was outdated and has been reloaded automatically. Try to submit it again. Contact the site administrator if the problem persists.')); + $reset_token = TRUE; } - _form_validate($form, $form_state, $form_id); $validated_forms[$form_id] = TRUE; @@ -1016,6 +1014,15 @@ function drupal_validate_form($form_id, } $form_state['values'] = $values; } + + // If the session token did not match the current user's session, reset the + // token, so the user is able to submit the form by submitting it again. + if (isset($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.67 diff -u -p -r1.67 form.test --- modules/simpletest/tests/form.test 19 Sep 2010 18:39:18 -0000 1.67 +++ modules/simpletest/tests/form.test 20 Sep 2010 21:15:58 -0000 @@ -417,6 +417,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('This form was outdated and has been reloaded automatically. Try to submit it again. Contact the site administrator if the problem persists.')); + $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('This form was outdated and has been reloaded automatically. Try to submit it again. Contact the site administrator if the problem persists.')); + $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.48 diff -u -p -r1.48 form_test.module --- modules/simpletest/tests/form_test.module 27 Aug 2010 11:54:32 -0000 1.48 +++ modules/simpletest/tests/form_test.module 20 Sep 2010 21:15:38 -0000 @@ -298,6 +298,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) {