diff --git a/forms/Form.php b/forms/Form.php index 537b36fd52e..edd3181763e 100644 --- a/forms/Form.php +++ b/forms/Form.php @@ -277,10 +277,20 @@ public function httpSubmission($request) { // Protection against CSRF attacks $token = $this->getSecurityToken(); - if(!$token->checkRequest($request)) { - $this->httpError(400, _t("Form.CSRF_FAILED_MESSAGE", - "There seems to have been a technical problem. Please click the back button," - . " refresh your browser, and try again.")); + if( ! $token->checkRequest($request)) { + if (empty($vars['SecurityID'])) { + $this->httpError(400, _t("Form.CSRF_FAILED_MESSAGE", + "There seems to have been a technical problem. Please click the back button, + refresh your browser, and try again.")); + } else { + Session::set("FormInfo.{$this->FormName()}.data", $this->getData()); + Session::set("FormInfo.{$this->FormName()}.errors", array()); + $this->sessionMessage( + _t("Form.CSRF_EXPIRED_MESSAGE", "Your session has expired. Please re-submit the form."), + "warning" + ); + return $this->controller->redirectBack(); + } } // Determine the action button clicked diff --git a/tests/forms/FormTest.php b/tests/forms/FormTest.php index 0a7fb807cbf..5ac98719ec1 100644 --- a/tests/forms/FormTest.php +++ b/tests/forms/FormTest.php @@ -311,7 +311,22 @@ public function testDisableSecurityTokenAcceptsSubmissionWithoutToken() { ) ); $this->assertEquals(400, $response->getStatusCode(), 'Submission fails without security token'); - + + $response = $this->get('FormTest_ControllerWithSecurityToken'); + $response = $this->post( + 'FormTest_ControllerWithSecurityToken/Form', + array( + 'Email' => 'test@test.com', + 'action_doSubmit' => 1, + 'SecurityID' => -1 + ) + ); + $this->assertEquals(200, $response->getStatusCode(), 'Submission reloads form if security token invalid'); + + $matched = $this->cssParser()->getBySelector('#Form_Form_Email'); + $attrs = $matched[0]->attributes(); + $this->assertEquals('test@test.com', (string)$attrs['value'], 'Submitted data is preserved'); + $response = $this->get('FormTest_ControllerWithSecurityToken'); $tokenEls = $this->cssParser()->getBySelector('#Form_Form_SecurityID'); $this->assertEquals(