Index: t3lib/class.t3lib_beuserauth.php
===================================================================
--- t3lib/class.t3lib_beuserauth.php (revision 8881)
+++ t3lib/class.t3lib_beuserauth.php (working copy)
@@ -393,6 +393,16 @@
return $isUserAllowedToLogin;
}
+
+ /**
+ * Logs out the current user and clears the form protection tokens.
+ */
+ public function logoff() {
+ t3lib_formProtection_Factory::get(
+ 't3lib_formProtection_Backend'
+ )->clean();
+ parent::logoff();
+ }
}
Index: t3lib/core_autoload.php
===================================================================
--- t3lib/core_autoload.php (revision 8881)
+++ t3lib/core_autoload.php (working copy)
@@ -116,6 +116,9 @@
't3lib_error_exceptionhandlerinterface' => PATH_t3lib . 'error/interface.t3lib_error_exceptionhandlerinterface.php',
't3lib_browselinkshook' => PATH_t3lib . 'interfaces/interface.t3lib_browselinkshook.php',
't3lib_extfilefunctions_processdatahook' => PATH_t3lib . 'interfaces/interface.t3lib_extfilefunctions_processdatahook.php',
+ 't3lib_formprotection_factory' => PATH_t3lib . 'formprotection/class.t3lib_formprotection_factory.php',
+ 't3lib_formprotection_abstract' => PATH_t3lib . 'formprotection/class.t3lib_formprotection_abstract.php',
+ 't3lib_formprotection_backend' => PATH_t3lib . 'formprotection/class.t3lib_formprotection_backend.php',
't3lib_localrecordlistgettablehook' => PATH_t3lib . 'interfaces/interface.t3lib_localrecordlistgettablehook.php',
't3lib_pageselect_getpagehook' => PATH_t3lib . 'interfaces/interface.t3lib_pageselect_getpagehook.php',
't3lib_pageselect_getrecordoverlayhook' => PATH_t3lib . 'interfaces/interface.t3lib_pageselect_getrecordoverlayhook.php',
Index: t3lib/formprotection/class.t3lib_formprotection_backend.php
===================================================================
--- t3lib/formprotection/class.t3lib_formprotection_backend.php (revision 0)
+++ t3lib/formprotection/class.t3lib_formprotection_backend.php (revision 0)
@@ -0,0 +1,179 @@
+
+* All rights reserved
+*
+* This script is part of the TYPO3 project. The TYPO3 project is
+* free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* The GNU General Public License can be found at
+* http://www.gnu.org/copyleft/gpl.html.
+*
+* This script is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+
+/**
+ * Class t3lib_formProtection_Backend.
+ *
+ * This class provides protection against cross-site request forgery (XSRF/CSRF)
+ * for forms in the BE.
+ *
+ * How to use:
+ *
+ * For each form in the BE (or link that changes some data), create a token and
+ * insert is as a hidden form element. The name of the form element does not
+ * matter; you only need it to get the form token for verifying it.
+ *
+ *
+ *
+ * The three parameters $formName, $action and $formInstanceName can be
+ * arbitrary strings, but they should make the form token as specific as
+ * possible. For different forms (e.g. BE user setup and editing a tt_content
+ * record) or different records (with different UIDs) from the same table,
+ * those values should be different.
+ *
+ * For editing a tt_content record, the call could look like this:
+ *
+ *
+ *
+ * At the end of the form, you need to persist the tokens. This makes sure that
+ * generated tokens get saved, and also that removed tokens stay removed:
+ *
+ *
+ *
+ * In BE lists, it might be necessary to generate hundreds of tokens. So the
+ * tokens do not get automatically persisted after creation for performance
+ * reasons.
+ *
+ *
+ * When processing the data that has been submitted by the form, you can check
+ * that the form token is valid like this:
+ *
+ *
+ * if ($dataHasBeenSubmitted && t3lib_formProtection_Factory::get(
+ * t3lib_formProtection_Factory::TYPE_BACK_END
+ * )->validateToken(
+ * (string) t3lib_div::_POST('formToken'),
+ * 'BE user setup', 'edit
+ * )
+ * ) {
+ * // processes the data
+ * } else {
+ * // no need to do anything here as the BE form protection will create a
+ * // flash message for an invalid token
+ * }
+ *
+ *
+ * Note that validateToken invalidates the token with the token ID. So calling
+ * validate with the same parameters two times in a row will always return FALSE
+ * for the second call.
+ *
+ * It is important that the tokens get validated before the tokens are
+ * persisted. This makes sure that the tokens that get invalidated by
+ * validateToken cannot be used again.
+ *
+ * $Id$
+ *
+ * @package TYPO3
+ * @subpackage t3lib
+ *
+ * @author Oliver Klee
+ */
+class t3lib_formProtection_Backend extends t3lib_formProtection_Abstract {
+ /**
+ * the maximum number of tokens that can exist at the same time
+ *
+ * @var integer
+ */
+ protected $maximumNumberOfTokens = 20000;
+
+ /**
+ * Only allow construction if we have a backend session
+ */
+ public function __construct() {
+ if (!isset($GLOBALS['BE_USER'])) {
+ throw new t3lib_error_Exception(
+ 'A back-end form protection may only be instantiated if there' .
+ ' is an active back-end session.',
+ 1285067843
+ );
+ }
+ parent::__construct();
+ }
+
+ /**
+ * Creates or displayes an error message telling the user that the submitted
+ * form token is invalid.
+ *
+ * @return void
+ */
+ protected function createValidationErrorMessage() {
+ $message = t3lib_div::makeInstance(
+ 't3lib_FlashMessage',
+ $GLOBALS['LANG']->sL(
+ 'LLL:EXT:lang/locallang_core.xml:error.formProtection.tokenInvalid'
+ ),
+ '',
+ t3lib_FlashMessage::ERROR
+ );
+ t3lib_FlashMessageQueue::addMessage($message);
+ }
+
+ /**
+ * Retrieves all saved tokens.
+ *
+ * @return array
+ * the saved tokens as, will be empty if no tokens have been saved
+ */
+ protected function retrieveTokens() {
+ $tokens = $GLOBALS['BE_USER']->getSessionData('formTokens');
+ if (!is_array($tokens)) {
+ $tokens = array();
+ }
+
+ $this->tokens = $tokens;
+ }
+
+ /**
+ * Saves the tokens so that they can be used by a later incarnation of this
+ * class.
+ *
+ * @return void
+ */
+ public function persistTokens() {
+ $GLOBALS['BE_USER']->setAndSaveSessionData('formTokens', $this->tokens);
+ }
+}
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/formprotection/class.t3lib_formprotection_backend.php']) {
+ include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/formprotection/class.t3lib_formprotection_backend.php']);
+}
+?>
\ No newline at end of file
Property changes on: t3lib/formprotection/class.t3lib_formprotection_backend.php
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Index: t3lib/formprotection/class.t3lib_formprotection_factory.php
===================================================================
--- t3lib/formprotection/class.t3lib_formprotection_factory.php (revision 0)
+++ t3lib/formprotection/class.t3lib_formprotection_factory.php (revision 0)
@@ -0,0 +1,143 @@
+
+* All rights reserved
+*
+* This script is part of the TYPO3 project. The TYPO3 project is
+* free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* The GNU General Public License can be found at
+* http://www.gnu.org/copyleft/gpl.html.
+*
+* This script is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+
+/**
+ * Class t3lib_formProtection_Factory.
+ *
+ * This class creates and manages instances of the various form protection
+ * classes.
+ *
+ * This class provides only static methods. It can not be instantiated.
+ *
+ * Usage for the back-end form protection:
+ *
+ *
+ *
+ * $Id$
+ *
+ * @package TYPO3
+ * @subpackage t3lib
+ *
+ * @author Oliver Klee
+ * @author Ernesto Baschny
+ */
+final class t3lib_formProtection_Factory {
+ /**
+ * created instances of form protections using the type as array key
+ *
+ * @var array
+ */
+ static protected $instances = array();
+
+ /**
+ * Private constructor to prevent instantiation.
+ */
+ private function __construct() {}
+
+ /**
+ * Gets a form protection instance for the requested class $className.
+ *
+ * If there already is an existing instance of the requested $className, the
+ * existing instance will be returned.
+ *
+ * @param string $className
+ * the name of the class for which to return an instance, must be
+ * "t3lib_formProtection_BackEnd" or "tx_install_FormProtection"
+ *
+ * @return t3lib_formProtection_Abstract the requested instance
+ */
+ static public function get($className) {
+ if (!isset(self::$instances[$className])) {
+ if (!class_exists($className, TRUE)) {
+ throw new InvalidArgumentException(
+ '$className must be the name of an existing class, but ' .
+ 'actually was "' . $className . '".',
+ 1285352962
+ );
+ }
+
+ $instance = t3lib_div::makeInstance($className);
+ if (!$instance instanceof t3lib_formProtection_Abstract) {
+ throw new InvalidArgumentException(
+ '$className must be a subclass of ' .
+ 't3lib_formProtection_Abstract, but actually was "' .
+ $className . '".',
+ 1285353026
+ );
+ }
+ self::$instances[$className] = $instance;
+ }
+ return self::$instances[$className];
+ }
+
+ /**
+ * Sets the instance that will be returned by get() for a specific class
+ * name.
+ *
+ * Note: This function is intended for testing purposes only.
+ *
+ * @param string $className
+ * the name of the class for which to set an instance, must be
+ * "t3lib_formProtection_BackEnd" or "tx_install_FormProtection"
+ * @param t3lib_formProtection_Abstract $instance
+ * the instance to set
+ *
+ * @return void
+ */
+ static public function set($className, t3lib_formProtection_Abstract $instance) {
+ self::$instances[$className] = $instance;
+ }
+
+ /**
+ * Purges all existing instances.
+ *
+ * This function is particularly useful when cleaning up in unit testing.
+ *
+ * @return void
+ */
+ static public function purgeInstances() {
+ foreach (self::$instances as $key => $instance) {
+ $instance->__destruct();
+ unset(self::$instances[$key]);
+ }
+ }
+}
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/formprotection/class.t3lib_formprotection_factory.php']) {
+ include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/formprotection/class.t3lib_formprotection_factory.php']);
+}
+?>
\ No newline at end of file
Property changes on: t3lib/formprotection/class.t3lib_formprotection_factory.php
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Index: t3lib/formprotection/class.t3lib_formprotection_abstract.php
===================================================================
--- t3lib/formprotection/class.t3lib_formprotection_abstract.php (revision 0)
+++ t3lib/formprotection/class.t3lib_formprotection_abstract.php (revision 0)
@@ -0,0 +1,247 @@
+
+* All rights reserved
+*
+* This script is part of the TYPO3 project. The TYPO3 project is
+* free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* The GNU General Public License can be found at
+* http://www.gnu.org/copyleft/gpl.html.
+*
+* This script is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+
+/**
+ * Class t3lib_formProtection_Abstract.
+ *
+ * This class provides protection against cross-site request forgery (XSRF/CSRF)
+ * for forms.
+ *
+ * For documentation on how to use this class, please see the documentation of
+ * the corresponding subclasses, e.g. t3lib_formProtection_Backend.
+ *
+ * $Id$
+ *
+ * @package TYPO3
+ * @subpackage t3lib
+ *
+ * @author Oliver Klee
+ */
+abstract class t3lib_formProtection_Abstract {
+ /**
+ * the maximum number of tokens that can exist at the same time
+ *
+ * @var integer
+ */
+ protected $maximumNumberOfTokens = 0;
+
+ /**
+ * Valid tokens sorted from oldest to newest.
+ *
+ * [tokenId] => array(formName, formInstanceName)
+ *
+ * @var array
+ */
+ protected $tokens = array();
+
+ /**
+ * Constructor. Makes sure existing tokens are read and available for
+ * checking.
+ */
+ public function __construct() {
+ $this->retrieveTokens();
+ }
+
+ /**
+ * Frees as much memory as possible.
+ */
+ public function __destruct() {
+ $this->tokens = array();
+ }
+
+ /**
+ * Deletes all existing tokens and persists the (empty) token table.
+ *
+ * This function is intended to be called when a user logs on or off.
+ *
+ * @return void
+ */
+ public function clean() {
+ $this->tokens = array();
+ $this->persistTokens();
+ }
+
+ /**
+ * Generates and stores a token for a form.
+ *
+ * Calling this function two times with the same parameters will create
+ * two valid, different tokens.
+ *
+ * Generating more tokens than $maximumNumberOfEntries will cause the oldest
+ * tokens to get dropped.
+ *
+ * Note: This function does not persist the tokens.
+ *
+ * @param string $formName
+ * the name of the form, for example a table name like "tt_content",
+ * or some other identifier like "install_tool_password", must not be
+ * empty
+ * @param string $action
+ * the name of the action of the form, for example "new", "delete" or
+ * "edit", may also be empty
+ * @param string $formInstanceName
+ * a string used to differentiate two instances of the same form,
+ * form example a record UID or a comma-separated list of UIDs,
+ * may also be empty
+ *
+ * @return string the 32-character hex ID of the generated token
+ */
+ public function generateToken(
+ $formName, $action = '', $formInstanceName = ''
+ ) {
+ if ($formName == '') {
+ throw new InvalidArgumentException('$formName must not be empty.');
+ }
+
+ do {
+ $tokenId = bin2hex(t3lib_div::generateRandomBytes(16));
+ } while (isset($this->tokens[$tokenId]));
+
+ $this->tokens[$tokenId] = array(
+ 'formName' => $formName,
+ 'action' => $action,
+ 'formInstanceName' => $formInstanceName,
+ );
+ $this->preventOverflow();
+
+ return $tokenId;
+ }
+
+ /**
+ * Checks whether the token $tokenId is valid in the form $formName with
+ * $formInstanceName.
+ *
+ * A token is valid if $tokenId, $formName and $formInstanceName match and
+ * the token has not been used yet.
+ *
+ * Calling this function will mark the token $tokenId as invalud (if it
+ * exists).
+ *
+ * So calling this function with the same parameters two times will return
+ * FALSE the second time.
+ *
+ * @param string $tokenId
+ * a form token to check, may also be empty or utterly misformed
+ * @param string $formName
+ * the name of the form to check, for example "tt_content",
+ * may also be empty or utterly misformed
+ * @param string $action
+ * the action of the form to check, for example "edit",
+ * may also be empty or utterly misformed
+ * @param string $formInstanceName
+ * the instance name of the form to check, for example "42" or "foo"
+ * or "31,42", may also be empty or utterly misformed
+ *
+ * @return boolean
+ * TRUE if $tokenId, $formName, $action and $formInstanceName match
+ * and the token has not been used yet, FALSE otherwise
+ */
+ public function validateToken(
+ $tokenId, $formName, $action = '', $formInstanceName = ''
+ ) {
+ if (isset($this->tokens[$tokenId])) {
+ $token = $this->tokens[$tokenId];
+ $isValid = ($token['formName'] == $formName)
+ && ($token['action'] == $action)
+ && ($token['formInstanceName'] == $formInstanceName);
+ $this->dropToken($tokenId);
+ } else {
+ $isValid = FALSE;
+ }
+
+ if (!$isValid) {
+ $this->createValidationErrorMessage();
+ }
+
+ return $isValid;
+ }
+
+ /**
+ * Creates or displayes an error message telling the user that the submitted
+ * form token is invalid.
+ *
+ * This function may also be empty if the validation error should be handled
+ * silently.
+ *
+ * @return void
+ */
+ abstract protected function createValidationErrorMessage();
+
+ /**
+ * Retrieves all saved tokens.
+ *
+ * @return array
+ * the saved tokens, will be empty if no tokens have been saved
+ */
+ abstract protected function retrieveTokens();
+
+ /**
+ * Saves the tokens so that they can be used by a later incarnation of this
+ * class.
+ *
+ * @return void
+ */
+ abstract public function persistTokens();
+
+ /**
+ * Drops the token with the ID $tokenId.
+ *
+ * If there is no token with that ID, this function is a no-op.
+ *
+ * Note: This function does not persist the tokens.
+ *
+ * @param string $tokenId
+ * the 32-character ID of an existing token, must not be empty
+ *
+ * @return void
+ */
+ protected function dropToken($tokenId) {
+ if (isset($this->tokens[$tokenId])) {
+ unset($this->tokens[$tokenId]);
+ }
+ }
+
+ /**
+ * Checks whether the number of current tokens still is at most
+ * $this->maximumNumberOfTokens.
+ *
+ * If there are more tokens, the oldest tokens are removed until the number
+ * of tokens is low enough.
+ *
+ * Note: This function does not persist the tokens.
+ *
+ * @return void
+ */
+ protected function preventOverflow() {
+ if (empty($this->tokens)) {
+ return;
+ }
+
+ while (count($this->tokens) > $this->maximumNumberOfTokens) {
+ reset($this->tokens);
+ $this->dropToken(key($this->tokens));
+ }
+ }
+}
+?>
\ No newline at end of file
Property changes on: t3lib/formprotection/class.t3lib_formprotection_abstract.php
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Index: typo3/sysext/install/Resources/Private/Templates/AlterPasswordForm.html
===================================================================
--- typo3/sysext/install/Resources/Private/Templates/AlterPasswordForm.html (revision 8881)
+++ typo3/sysext/install/Resources/Private/Templates/AlterPasswordForm.html (working copy)
@@ -23,6 +23,7 @@
+
Index: typo3/sysext/install/mod/class.tx_install_formprotection.php
===================================================================
--- typo3/sysext/install/mod/class.tx_install_formprotection.php (revision 0)
+++ typo3/sysext/install/mod/class.tx_install_formprotection.php (revision 0)
@@ -0,0 +1,168 @@
+
+* All rights reserved
+*
+* This script is part of the TYPO3 project. The TYPO3 project is
+* free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* The GNU General Public License can be found at
+* http://www.gnu.org/copyleft/gpl.html.
+*
+* This script is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+
+/**
+ * Class tx_install_FormProtection.
+ *
+ * This class provides protection against cross-site request forgery (XSRF/CSRF)
+ * in the install tool.
+ *
+ *
+ * How to use this in the install tool:
+ *
+ * For each form in the install tool (or link that changes some data), create a
+ * token and insert is as a hidden form element. The name of the form element
+ * does not matter; you only need it to get the form token for verifying it.
+ *
+ *
+ * $formToken = $this->formProtection->generateToken(
+ * 'installToolPassword', 'change'
+ * );
+ * // then puts the generated form token in a hidden field in the template
+ *
+ *
+ * The three parameters $formName, $action and $formInstanceName can be
+ * arbitrary strings, but they should make the form token as specific as
+ * possible. For different forms (e.g. the password change and editing a the
+ * configuration), those values should be different.
+ *
+ * At the end of the form, you need to persist the tokens. This makes sure that
+ * generated tokens get saved, and also that removed tokens stay removed:
+ *
+ *
+ * $this->formProtection()->persistTokens();
+ *
+ *
+ *
+ * When processing the data that has been submitted by the form, you can check
+ * that the form token is valid like this:
+ *
+ *
+ * if ($dataHasBeenSubmitted && $this->formProtection()->validateToken(
+ * (string) $_POST['formToken'],
+ * 'installToolPassword',
+ * 'change'
+ * ) {
+ * // processes the data
+ * } else {
+ * // no need to do anything here as the install tool form protection will
+ * // create an error message for an invalid token
+ * }
+ *
+ *
+ * Note that validateToken invalidates the token with the token ID. So calling
+ * validate with the same parameters two times in a row will always return FALSE
+ * for the second call.
+ *
+ * It is important that the tokens get validated before the tokens are
+ * persisted. This makes sure that the tokens that get invalidated by
+ * validateToken cannot be used again.
+ *
+ * $Id$
+ *
+ * @package TYPO3
+ * @subpackage t3lib
+ *
+ * @author Oliver Klee
+ */
+class tx_install_FormProtection extends t3lib_formProtection_Abstract {
+ /**
+ * the maximum number of tokens that can exist at the same time
+ *
+ * @var integer
+ */
+ protected $maximumNumberOfTokens = 100;
+
+ /**
+ * an instance of the install tool used for displaying messages
+ *
+ * @var tx_install
+ */
+ protected $installTool = NULL;
+
+ /**
+ * Frees as much memory as possible.
+ */
+ public function __destruct() {
+ $this->installTool = NULL;
+ parent::__destruct();
+ }
+
+ /**
+ * Injects the current instance of the install tool.
+ *
+ * This instance will be used for displaying messages.
+ *
+ * @param tx_install $installTool the current instance of the install tool
+ *
+ * @return void
+ */
+ public function injectInstallTool(tx_install $installTool) {
+ $this->installTool = $installTool;
+ }
+
+ /**
+ * Creates or displayes an error message telling the user that the submitted
+ * form token is invalid.
+ *
+ * @return void
+ */
+ protected function createValidationErrorMessage() {
+ $this->installTool->addErrorMessage(
+ 'Validating the security token of this form has failed. ' .
+ 'Please reload the form and submit it again.'
+ );
+ }
+
+ /**
+ * Retrieves all saved tokens.
+ *
+ * @return array
+ * the saved tokens, will be empty if no tokens have been saved
+ */
+ protected function retrieveTokens() {
+ if (isset($_SESSION['installToolFormTokens'])
+ && is_array($_SESSION['installToolFormTokens'])
+ ) {
+ $this->tokens = $_SESSION['installToolFormTokens'];
+ } else {
+ $this->tokens = array();
+ }
+ }
+
+ /**
+ * Saves the tokens so that they can be used by a later incarnation of this
+ * class.
+ *
+ * @return void
+ */
+ public function persistTokens() {
+ $_SESSION['installToolFormTokens'] = $this->tokens;
+ }
+}
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/install/mod/class.tx_install_formprotection.php']) {
+ include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/install/mod/class.tx_install_formprotection.php']);
+}
+?>
\ No newline at end of file
Property changes on: typo3/sysext/install/mod/class.tx_install_formprotection.php
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Index: typo3/sysext/install/mod/class.tx_install.php
===================================================================
--- typo3/sysext/install/mod/class.tx_install.php (revision 8881)
+++ typo3/sysext/install/mod/class.tx_install.php (working copy)
@@ -159,6 +159,8 @@
/**
* Install Tool module
*
+ * $Id$
+ *
* @author Kasper Skårhøj
* @author Ingmar Schlecht
* @package TYPO3
@@ -218,6 +220,13 @@
*/
protected $session = NULL;
+ /**
+ * the form protection instance used for creating and verifying form tokens
+ *
+ * @var tx_install_FormProtection
+ */
+ protected $formProtection = NULL;
+
var $menuitems = array(
'config' => 'Basic Configuration',
'database' => 'Database Analyser',
@@ -349,6 +358,11 @@
if($this->redirect_url) {
t3lib_utility_Http::redirect($this->redirect_url);
}
+
+ $this->formProtection = t3lib_formProtection_Factory::get(
+ 'tx_install_FormProtection'
+ );
+ $this->formProtection->injectInstallTool($this);
} else {
$this->loginForm();
}
@@ -503,6 +517,7 @@
TRUE,
TRUE
);
+
// Send content to the page wrapper function
$this->output($this->outputWrapper($content));
}
@@ -729,6 +744,7 @@
if (is_file($enableInstallToolFile) && trim(file_get_contents($enableInstallToolFile)) !== 'KEEP_FILE') {
unlink(PATH_typo3conf . 'ENABLE_INSTALL_TOOL');
}
+ $this->formProtection->clean();
$this->session->destroySession();
t3lib_utility_Http::redirect($this->scriptSelf);
break;
@@ -882,6 +898,8 @@
break;
}
}
+
+ $this->formProtection->persistTokens();
}
/**
@@ -2072,13 +2090,24 @@
$doit=1;
if ($k=='BE' && $vk=='installToolPassword') {
if ($value) {
- if (isset($_POST['installToolPassword_check']) && (!t3lib_div::_GP('installToolPassword_check') || strcmp(t3lib_div::_GP('installToolPassword_check'),$value))) {
- $doit=0;
- $this->errorMessages[] = '
- The two passwords did not
- match! The password was not
- changed.
- ';
+ if (isset($_POST['installToolPassword_check'])) {
+ if (!$this->formProtection->validateToken(
+ (string) $_POST['formToken'],
+ 'installToolPassword',
+ 'change'
+ )) {
+ $doit = FALSE;
+ break;
+ }
+
+ if (!t3lib_div::_GP('installToolPassword_check')
+ || strcmp(t3lib_div::_GP('installToolPassword_check'), $value)
+ ) {
+ $doit = FALSE;
+ $this->errorMessages[]
+ = 'The two passwords did not ' .
+ 'match! The password was not changed.';
+ }
}
if (t3lib_div::_GP('installToolPassword_md5')) $value =md5($value);
} else $doit=0;
@@ -7921,7 +7950,10 @@
'action' => $this->scriptSelf.'?TYPO3_INSTALL[type]=extConfig',
'enterPassword' => 'Enter new password:',
'enterAgain' => 'Enter again:',
- 'submit' => 'Set new password'
+ 'submit' => 'Set new password',
+ 'formToken' => $this->formProtection->generateToken(
+ 'installToolPassword', 'change'
+ ),
);
// Fill the markers
$content = t3lib_parsehtml::substituteMarkerArray(
@@ -8276,6 +8308,20 @@
$bytes = t3lib_div::generateRandomBytes($keyLength);
return substr(bin2hex($bytes), -96);
}
+
+ /**
+ * Adds an error message that should be displayed.
+ *
+ * @param string $messageText
+ * the text of the message to display, must not be empty
+ */
+ public function addErrorMessage($messageText) {
+ if ($messageText == '') {
+ throw new InvalidArgumentException('$messageText must not be empty.');
+ }
+
+ $this->errorMessages[] = $messageText;
+ }
}
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/install/mod/class.tx_install.php']) {
Index: typo3/sysext/install/ext_autoload.php
===================================================================
--- typo3/sysext/install/ext_autoload.php (revision 8881)
+++ typo3/sysext/install/ext_autoload.php (working copy)
@@ -1,10 +1,13 @@
t3lib_extMgm::extPath('install', 'report/class.tx_install_report_installstatus.php'),
+ 'tx_install' => $extensionPath . 'mod/class.tx_install.php',
+ 'tx_install_ajax' => $extensionPath . 'mod/class.tx_install_ajax.php',
+ 'tx_install_formprotection' => $extensionPath . 'mod/class.tx_install_formprotection.php',
+ 'tx_install_session' => $extensionPath . 'mod/class.tx_install_session.php',
+ 'tx_install_report_installstatus' => $extensionPath . 'report/class.tx_install_report_installstatus.php',
);
?>
\ No newline at end of file
Index: typo3/sysext/setup/mod/index.php
===================================================================
--- typo3/sysext/setup/mod/index.php (revision 8881)
+++ typo3/sysext/setup/mod/index.php (working copy)
@@ -127,11 +127,10 @@
/**
* If settings are submitted to _POST[DATA], store them
- * NOTICE: This method is called before the template.php is included. See buttom of document
- *
- * @return void
+ * NOTICE: This method is called before the template.php is included. See
+ * bottom of document.
*/
- function storeIncomingData() {
+ public function storeIncomingData() {
/* @var $BE_USER t3lib_beUserAuth */
global $BE_USER;
@@ -142,8 +141,14 @@
$storeRec = array();
$fieldList = $this->getFieldsFromShowItem();
- if (is_array($d)) {
-
+ $formProtection = t3lib_formProtection_Factory::get(
+ 't3lib_formProtection_Backend'
+ );
+ if (is_array($d) && $formProtection->validateToken(
+ (string) t3lib_div::_POST('formToken'),
+ 'BE user setup', 'edit'
+ )
+ ) {
// UC hashed before applying changes
$save_before = md5(serialize($BE_USER->uc));
@@ -414,19 +419,22 @@
$this->content .= $this->doc->spacer(20) . $this->doc->getDynTabMenu($menuItems, 'user-setup', false, false, 100, 1, false, 1, $this->dividers2tabs);
+ $formProtection = t3lib_formProtection_Factory::get(
+ 't3lib_formProtection_Backend'
+ );
+ $formToken = $formProtection->generateToken('BE user setup', 'edit');
// Submit and reset buttons
$this->content .= $this->doc->spacer(20);
$this->content .= $this->doc->section('',
t3lib_BEfunc::cshItem('_MOD_user_setup', 'reset', $BACK_PATH) . '
+
'
);
-
-
// Notice
$this->content .= $this->doc->spacer(30);
$flashMessage = t3lib_div::makeInstance(
@@ -935,4 +943,6 @@
$SOBE->main();
$SOBE->printContent();
+t3lib_formProtection_Factory::get('t3lib_formProtection_Backend')
+ ->persistTokens();
?>
\ No newline at end of file
Index: typo3/sysext/lang/locallang_core.xml
===================================================================
--- typo3/sysext/lang/locallang_core.xml (revision 8881)
+++ typo3/sysext/lang/locallang_core.xml (working copy)
@@ -265,6 +265,7 @@
+
Index: tests/t3lib/t3lib_beuserauthTest.php
===================================================================
--- tests/t3lib/t3lib_beuserauthTest.php (revision 0)
+++ tests/t3lib/t3lib_beuserauthTest.php (revision 0)
@@ -0,0 +1,69 @@
+
+ */
+class t3lib_beUserAuthTest extends tx_phpunit_testcase {
+ /**
+ * @var t3lib_beUserAuth
+ */
+ private $fixture = NULL;
+
+ public function setUp() {
+ $this->fixture = new t3lib_beUserAuth();
+ }
+
+ public function tearDown() {
+ unset($this->fixture);
+
+ t3lib_formProtection_Factory::purgeInstances();
+ }
+
+
+ /////////////////////////////////////////
+ // Tests concerning the form protection
+ /////////////////////////////////////////
+
+ /**
+ * @test
+ */
+ public function logoffCleansFormProtection() {
+ $formProtection = $this->getMock(
+ 't3lib_formProtection_Backend', array('clean')
+ );
+ $formProtection->expects($this->atLeastOnce())->method('clean');
+ t3lib_formProtection_Factory::set(
+ 't3lib_formProtection_Backend', $formProtection
+ );
+
+ $this->fixture->logoff();
+ }
+}
+?>
Index: tests/t3lib/formprotection/t3lib_formProtection_FactoryTest.php
===================================================================
--- tests/t3lib/formprotection/t3lib_formProtection_FactoryTest.php (revision 0)
+++ tests/t3lib/formprotection/t3lib_formProtection_FactoryTest.php (revision 0)
@@ -0,0 +1,172 @@
+
+ * @author Ernesto Baschny
+ */
+class t3lib_formProtection_FactoryTest extends tx_phpunit_testcase {
+ public function setUp() {
+ }
+
+ public function tearDown() {
+ t3lib_formProtection_Factory::purgeInstances();
+ }
+
+
+ /////////////////////////
+ // Tests concerning get
+ /////////////////////////
+
+ /**
+ * @test
+ *
+ * @expectedException InvalidArgumentException
+ */
+ public function getForInexistentClassThrowsException() {
+ t3lib_formProtection_Factory::get('noSuchClass');
+ }
+
+ /**
+ * @test
+ *
+ * @expectedException InvalidArgumentException
+ */
+ public function getForClassThatIsNoFormProtectionSubclassThrowsException() {
+ t3lib_formProtection_Factory::get('t3lib_formProtection_FactoryTest');
+ }
+
+ /**
+ * @test
+ */
+ public function getForTypeBackEndWithExistingBackEndReturnsBackEndFormProtection() {
+ $this->assertTrue(
+ t3lib_formProtection_Factory::get(
+ 't3lib_formProtection_Backend'
+ ) instanceof t3lib_formProtection_Backend
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getForTypeBackEndCalledTwoTimesReturnsTheSameInstance() {
+ $this->assertSame(
+ t3lib_formProtection_Factory::get(
+ 't3lib_formProtection_Backend'
+ ),
+ t3lib_formProtection_Factory::get(
+ 't3lib_formProtection_Backend'
+ )
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getForTypeInstallToolReturnsInstallToolFormProtection() {
+ $this->assertTrue(
+ t3lib_formProtection_Factory::get(
+ 'tx_install_FormProtection'
+ ) instanceof tx_install_FormProtection
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getForTypeInstallToolCalledTwoTimesReturnsTheSameInstance() {
+ $this->assertSame(
+ t3lib_formProtection_Factory::get(
+ 'tx_install_FormProtection'
+ ),
+ t3lib_formProtection_Factory::get(
+ 'tx_install_FormProtection'
+ )
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getForTypesInstallToolAndBackEndReturnsDifferentInstances() {
+ $this->assertNotSame(
+ t3lib_formProtection_Factory::get(
+ 'tx_install_FormProtection'
+ ),
+ t3lib_formProtection_Factory::get(
+ 't3lib_formProtection_Backend'
+ )
+ );
+ }
+
+
+ /////////////////////////
+ // Tests concerning set
+ /////////////////////////
+
+ /**
+ * @test
+ */
+ public function setSetsInstanceForType() {
+ $instance = new t3lib_formProtection_Testing();
+ t3lib_formProtection_Factory::set(
+ 't3lib_formProtection_Backend', $instance
+ );
+
+ $this->assertSame(
+ $instance,
+ t3lib_formProtection_Factory::get(
+ 't3lib_formProtection_Backend'
+ )
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setNotSetsInstanceForOtherType() {
+ $instance = new t3lib_formProtection_Testing();
+ t3lib_formProtection_Factory::set(
+ 't3lib_formProtection_Backend', $instance
+ );
+
+ $this->assertNotSame(
+ $instance,
+ t3lib_formProtection_Factory::get(
+ 'tx_install_FormProtection'
+ )
+ );
+ }
+}
+?>
\ No newline at end of file
Property changes on: tests/t3lib/formprotection/t3lib_formProtection_FactoryTest.php
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Index: tests/t3lib/formprotection/t3lib_formProtection_AbstractTest.php
===================================================================
--- tests/t3lib/formprotection/t3lib_formProtection_AbstractTest.php (revision 0)
+++ tests/t3lib/formprotection/t3lib_formProtection_AbstractTest.php (revision 0)
@@ -0,0 +1,475 @@
+
+ */
+class t3lib_formProtection_AbstractTest extends tx_phpunit_testcase {
+ /**
+ * @var t3lib_formProtection_Testing
+ */
+ private $fixture;
+
+ public function setUp() {
+ $this->fixture = new t3lib_formProtection_Testing();
+ }
+
+ public function tearDown() {
+ $this->fixture->__destruct();
+ unset($this->fixture);
+ }
+
+
+ /////////////////////////////////////////
+ // Tests concerning the basic functions
+ /////////////////////////////////////////
+
+ /**
+ * @test
+ */
+ public function constructionRetrievesTokens() {
+ $className = uniqid('t3lib_formProtection');
+ eval(
+ 'class ' . $className . ' extends t3lib_formProtection_Testing {' .
+ 'public $tokensHaveBeenRetrieved = FALSE; ' .
+ 'protected function retrieveTokens() {' .
+ '$this->tokensHaveBeenRetrieved = TRUE;' .
+ '}' .
+ '}'
+ );
+
+ $fixture = new $className();
+
+ $this->assertTrue(
+ $fixture->tokensHaveBeenRetrieved
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function cleanMakesTokenInvalid() {
+ $formName = 'foo';
+ $tokenId = $this->fixture->generateToken($formName);
+
+ $this->fixture->clean();
+
+ $this->assertFalse(
+ $this->fixture->validateToken($tokenId, $formName)
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function cleanPersistsTokens() {
+ $fixture = $this->getMock(
+ 't3lib_formProtection_Testing', array('persistTokens')
+ );
+ $fixture->expects($this->once())->method('persistTokens');
+
+ $fixture->clean();
+ }
+
+
+ ///////////////////////////////////
+ // Tests concerning generateToken
+ ///////////////////////////////////
+
+ /**
+ * @test
+ */
+ public function generateTokenFormForEmptyFormNameThrowsException() {
+ $this->setExpectedException(
+ 'InvalidArgumentException', '$formName must not be empty.'
+ );
+
+ $this->fixture->generateToken('', 'edit', 'bar');
+ }
+
+ /**
+ * @test
+ */
+ public function generateTokenFormForEmptyActionNotThrowsException() {
+ $this->fixture->generateToken('foo', '', '42');
+ }
+
+ /**
+ * @test
+ */
+ public function generateTokenFormForEmptyFormInstanceNameNotThrowsException() {
+ $this->fixture->generateToken('foo', 'edit', '');
+ }
+
+ /**
+ * @test
+ */
+ public function generateTokenFormForOmittedActionAndFormInstanceNameNotThrowsException() {
+ $this->fixture->generateToken('foo');
+ }
+
+ /**
+ * @test
+ */
+ public function generateTokenReturns32CharacterHexToken() {
+ $this->assertRegexp(
+ '/^[0-9a-f]{32}$/',
+ $this->fixture->generateToken('foo')
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function generateTokenCalledTwoTimesWithSameParametersReturnsDifferentTokens() {
+ $this->assertNotEquals(
+ $this->fixture->generateToken('foo', 'edit', 'bar'),
+ $this->fixture->generateToken('foo', 'edit', 'bar')
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function generatingTooManyTokensInvalidatesOldestToken() {
+ $this->fixture->setMaximumNumberOfTokens(2);
+
+ $formName = 'foo';
+
+ $token1 = $this->fixture->generateToken($formName);
+ $token2 = $this->fixture->generateToken($formName);
+ $token3 = $this->fixture->generateToken($formName);
+
+ $this->assertFalse(
+ $this->fixture->validateToken($token1, $formName)
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function generatingTooManyTokensNotInvalidatesNewestToken() {
+ $this->fixture->setMaximumNumberOfTokens(2);
+
+ $formName = 'foo';
+ $formInstanceName = 'bar';
+
+ $token1 = $this->fixture->generateToken($formName);
+ $token2 = $this->fixture->generateToken($formName);
+ $token3 = $this->fixture->generateToken($formName);
+
+ $this->assertTrue(
+ $this->fixture->validateToken($token3, $formName)
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function generatingTooManyTokensNotInvalidatesTokenInTheMiddle() {
+ $this->fixture->setMaximumNumberOfTokens(2);
+
+ $formName = 'foo';
+ $formInstanceName = 'bar';
+
+ $token1 = $this->fixture->generateToken($formName);
+ $token2 = $this->fixture->generateToken($formName);
+ $token3 = $this->fixture->generateToken($formName);
+
+ $this->assertTrue(
+ $this->fixture->validateToken($token2, $formName)
+ );
+ }
+
+
+ ///////////////////////////////////
+ // Tests concerning validateToken
+ ///////////////////////////////////
+
+ /**
+ * @test
+ */
+ public function validateTokenWithFourEmptyParametersNotThrowsException() {
+ $this->fixture->validateToken('', '', '', '');
+ }
+
+ /**
+ * @test
+ */
+ public function validateTokenWithTwoEmptyAndTwoMissingParametersNotThrowsException() {
+ $this->fixture->validateToken('', '');
+ }
+
+ /**
+ * @test
+ */
+ public function validateTokenWithDataFromGenerateTokenWithFormInstanceNameReturnsTrue() {
+ $formName = 'foo';
+ $action = 'edit';
+ $formInstanceName = 'bar';
+
+ $this->assertTrue(
+ $this->fixture->validateToken(
+ $this->fixture->generateToken($formName, $action, $formInstanceName),
+ $formName,
+ $action,
+ $formInstanceName
+ )
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function validateTokenWithDataFromGenerateTokenWithMissingActionAndFormInstanceNameReturnsTrue() {
+ $formName = 'foo';
+
+ $this->assertTrue(
+ $this->fixture->validateToken(
+ $this->fixture->generateToken($formName), $formName
+ )
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function validateTokenWithValidDataDropsToken() {
+ $formName = 'foo';
+
+ $fixture = $this->getMock(
+ 't3lib_formProtection_Testing', array('dropToken')
+ );
+
+ $tokenId = $fixture->generateToken($formName);
+ $fixture->expects($this->once())->method('dropToken')
+ ->with($tokenId);
+
+ $fixture->validateToken($tokenId, $formName);
+ }
+
+ /**
+ * @test
+ */
+ public function validateTokenWithValidDataCalledTwoTimesReturnsFalseOnSecondCall() {
+ $formName = 'foo';
+ $action = 'edit';
+ $formInstanceName = 'bar';
+
+ $tokenId = $this->fixture->generateToken($formName, $action, $formInstanceName);
+
+ $this->fixture->validateToken($tokenId, $formName, $action, $formInstanceName);
+
+ $this->assertFalse(
+ $this->fixture->validateToken($tokenId, $formName, $action, $formInstanceName)
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function validateTokenWithMismatchingTokenIdReturnsFalse() {
+ $formName = 'foo';
+ $action = 'edit';
+ $formInstanceName = 'bar';
+
+ $this->fixture->generateToken($formName, $action, $formInstanceName);
+
+ $this->assertFalse(
+ $this->fixture->validateToken(
+ 'Hello world!', $formName, $action, $formInstanceName
+ )
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function validateTokenWithMismatchingFormNameReturnsFalse() {
+ $formName = 'foo';
+ $action = 'edit';
+ $formInstanceName = 'bar';
+
+ $tokenId = $this->fixture->generateToken($formName, $action, $formInstanceName);
+
+ $this->assertFalse(
+ $this->fixture->validateToken(
+ $tokenId, 'espresso', $action, $formInstanceName
+ )
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function validateTokenWithMismatchingActionReturnsFalse() {
+ $formName = 'foo';
+ $action = 'edit';
+ $formInstanceName = 'bar';
+
+ $tokenId = $this->fixture->generateToken($formName, $action, $formInstanceName);
+
+ $this->assertFalse(
+ $this->fixture->validateToken(
+ $tokenId, $formName, 'delete', $formInstanceName
+ )
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function validateTokenWithMismatchingFormInstanceNameReturnsFalse() {
+ $formName = 'foo';
+ $action = 'edit';
+ $formInstanceName = 'bar';
+
+ $tokenId = $this->fixture->generateToken($formName, $action, $formInstanceName);
+
+ $this->assertFalse(
+ $this->fixture->validateToken(
+ $tokenId, $formName, $action, 'beer'
+ )
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function validateTokenWithTwoTokensForSameFormNameAndActionAndFormInstanceNameReturnsTrueForBoth() {
+ $formName = 'foo';
+ $action = 'edit';
+ $formInstanceName = 'bar';
+
+ $tokenId1 = $this->fixture->generateToken($formName, $action, $formInstanceName);
+ $tokenId2 = $this->fixture->generateToken($formName, $action, $formInstanceName);
+
+ $this->assertTrue(
+ $this->fixture->validateToken(
+ $tokenId1, $formName, $action, $formInstanceName
+ )
+ );
+ $this->assertTrue(
+ $this->fixture->validateToken(
+ $tokenId2, $formName, $action, $formInstanceName
+ )
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function validateTokenWithTwoTokensForSameFormNameAndActionAndFormInstanceNameCalledInReverseOrderReturnsTrueForBoth() {
+ $formName = 'foo';
+ $action = 'edit';
+ $formInstanceName = 'bar';
+
+ $tokenId1 = $this->fixture->generateToken($formName, $action, $formInstanceName);
+ $tokenId2 = $this->fixture->generateToken($formName, $action, $formInstanceName);
+
+ $this->assertTrue(
+ $this->fixture->validateToken(
+ $tokenId2, $formName, $action, $formInstanceName
+ )
+ );
+ $this->assertTrue(
+ $this->fixture->validateToken(
+ $tokenId1, $formName, $action, $formInstanceName
+ )
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function validateTokenForValidTokenNotCallsCreateValidationErrorMessage() {
+ $fixture = $this->getMock(
+ 't3lib_formProtection_Testing', array('createValidationErrorMessage')
+ );
+ $fixture->expects($this->never())->method('createValidationErrorMessage');
+
+ $formName = 'foo';
+ $action = 'edit';
+ $formInstanceName = 'bar';
+
+ $token = $fixture->generateToken($formName, $action, $formInstanceName);
+ $fixture->validateToken(
+ $token, $formName, $action, $formInstanceName
+ );
+
+ $fixture->__destruct();
+ }
+
+ /**
+ * @test
+ */
+ public function validateTokenForInvalidTokenCallsCreateValidationErrorMessage() {
+ $fixture = $this->getMock(
+ 't3lib_formProtection_Testing', array('createValidationErrorMessage')
+ );
+ $fixture->expects($this->once())->method('createValidationErrorMessage');
+
+ $formName = 'foo';
+ $action = 'edit';
+ $formInstanceName = 'bar';
+
+ $fixture->generateToken($formName, $action, $formInstanceName);
+ $fixture->validateToken(
+ 'an invalid token ...', $formName, $action, $formInstanceName
+ );
+
+ $fixture->__destruct();
+ }
+
+ /**
+ * @test
+ */
+ public function validateTokenForInvalidFormNameCallsCreateValidationErrorMessage() {
+ $fixture = $this->getMock(
+ 't3lib_formProtection_Testing', array('createValidationErrorMessage')
+ );
+ $fixture->expects($this->once())->method('createValidationErrorMessage');
+
+ $formName = 'foo';
+ $action = 'edit';
+ $formInstanceName = 'bar';
+
+ $token = $fixture->generateToken($formName, $action, $formInstanceName);
+ $fixture->validateToken(
+ $token, 'another form name', $action, $formInstanceName
+ );
+
+ $fixture->__destruct();
+ }
+}
+?>
\ No newline at end of file
Property changes on: tests/t3lib/formprotection/t3lib_formProtection_AbstractTest.php
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Index: tests/t3lib/formprotection/fixtures/class.t3lib_formprotection_testing.php
===================================================================
--- tests/t3lib/formprotection/fixtures/class.t3lib_formprotection_testing.php (revision 0)
+++ tests/t3lib/formprotection/fixtures/class.t3lib_formprotection_testing.php (revision 0)
@@ -0,0 +1,99 @@
+
+* All rights reserved
+*
+* This script is part of the TYPO3 project. The TYPO3 project is
+* free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* The GNU General Public License can be found at
+* http://www.gnu.org/copyleft/gpl.html.
+*
+* This script is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+
+/**
+ * Class t3lib_formProtection_Testing.
+ *
+ * This is a testing subclass of the abstract t3lib_formProtection_Abstract
+ * class.
+ *
+ * $Id$
+ *
+ * @package TYPO3
+ * @subpackage t3lib
+ *
+ * @author Oliver Klee
+ */
+class t3lib_formProtection_Testing extends t3lib_formProtection_Abstract {
+ /**
+ * the maximum number of tokens that can exist at the same time
+ *
+ * @var integer
+ */
+ protected $maximumNumberOfTokens = 100;
+
+ /**
+ * Sets the maximum number of tokens that can exist at the same time.
+ *
+ * @param integer $number maximum number of tokens, must be > 0
+ *
+ * @return void
+ */
+ public function setMaximumNumberOfTokens($number) {
+ $this->maximumNumberOfTokens = $number;
+ }
+
+ /**
+ * Creates or displayes an error message telling the user that the submitted
+ * form token is invalid.
+ *
+ * @return void
+ */
+ protected function createValidationErrorMessage() {}
+
+ /**
+ * Retrieves all saved tokens.
+ *
+ * @return array the saved tokens as a two-dimensional array, will be empty
+ * if no tokens have been saved
+ */
+ protected function retrieveTokens() {}
+
+ /**
+ * Saves the tokens so that they can be used by a later incarnation of this
+ * class.
+ *
+ * @return void
+ */
+ public function persistTokens() {}
+
+ /**
+ * Drops the token with the ID $tokenId and persists all tokens.
+ *
+ * If there is no token with that ID, this function is a no-op.
+ *
+ * @param string $tokenId
+ * the 32-character ID of an existing token, must not be empty
+ *
+ * @return void
+ */
+ public function dropToken($tokenId) {
+ parent::dropToken($tokenId);
+ }
+}
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/formprotection/class.t3lib_formprotection_testing.php']) {
+ include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/formprotection/class.t3lib_formprotection_testing.php']);
+}
+?>
\ No newline at end of file
Property changes on: tests/t3lib/formprotection/fixtures/class.t3lib_formprotection_testing.php
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Index: tests/t3lib/formprotection/t3lib_formProtection_BackendTest.php
===================================================================
--- tests/t3lib/formprotection/t3lib_formProtection_BackendTest.php (revision 0)
+++ tests/t3lib/formprotection/t3lib_formProtection_BackendTest.php (revision 0)
@@ -0,0 +1,198 @@
+
+ */
+class t3lib_formProtection_BackendTest extends tx_phpunit_testcase {
+ /**
+ * a backup of the current BE user
+ *
+ * @var t3lib_beUserAuth
+ */
+ private $backEndUserBackup = NULL;
+
+ /**
+ * @var t3lib_formProtection_Backend
+ */
+ private $fixture;
+
+ public function setUp() {
+ $this->backEndUserBackup = $GLOBALS['BE_USER'];
+ $GLOBALS['BE_USER'] = $this->getMock(
+ 't3lib_beUserAuth',
+ array('getSessionData', 'setAndSaveSessionData')
+ );
+
+ $className = $this->createAccessibleProxyClass();
+ $this->fixture = new $className;
+ }
+
+ public function tearDown() {
+ $this->fixture->__destruct();
+ unset($this->fixture);
+
+ $GLOBALS['BE_USER'] = $this->backEndUserBackup;
+
+ t3lib_FlashMessageQueue::getAllMessagesAndFlush();
+ }
+
+
+ //////////////////////
+ // Utility functions
+ //////////////////////
+
+ /**
+ * Creates a subclass t3lib_formProtection_Backend with retrieveTokens made
+ * public.
+ *
+ * @return string the name of the created class, will not be empty
+ */
+ private function createAccessibleProxyClass() {
+ $className = 't3lib_formProtection_BackendAccessibleProxy';
+ if (!class_exists($className)) {
+ eval(
+ 'class ' . $className . ' extends t3lib_formProtection_Backend {' .
+ ' public function createValidationErrorMessage() {' .
+ ' parent::createValidationErrorMessage();' .
+ ' }' .
+ ' public function retrieveTokens() {' .
+ ' return parent::retrieveTokens();' .
+ ' }' .
+ '}'
+ );
+ }
+
+ return $className;
+ }
+
+
+ ////////////////////////////////////
+ // Tests for the utility functions
+ ////////////////////////////////////
+
+ /**
+ * @test
+ */
+ public function createAccessibleProxyCreatesBackendFormProtectionSubclass() {
+ $className = $this->createAccessibleProxyClass();
+
+ $this->assertTrue(
+ (new $className()) instanceof t3lib_formProtection_Backend
+ );
+ }
+
+
+ //////////////////////////////////////////////////////////
+ // Tests concerning the reading and saving of the tokens
+ //////////////////////////////////////////////////////////
+
+ /**
+ * @test
+ */
+ public function retrieveTokensReadsTokensFromSessionData() {
+ $GLOBALS['BE_USER']->expects($this->once())->method('getSessionData')
+ ->with('formTokens')->will($this->returnValue(array()));
+
+ $this->fixture->retrieveTokens();
+ }
+
+ /**
+ * @test
+ */
+ public function tokensFromSessionDataAreAvailableForValidateToken() {
+ $tokenId = '51a655b55c54d54e5454c5f521f6552a';
+ $formName = 'foo';
+ $action = 'edit';
+ $formInstanceName = '42';
+
+ $GLOBALS['BE_USER']->expects($this->once())->method('getSessionData')
+ ->with('formTokens')->will($this->returnValue(array(
+ $tokenId => array(
+ 'formName' => $formName,
+ 'action' => $action,
+ 'formInstanceName' => $formInstanceName,
+ ),
+ )));
+
+ $this->fixture->retrieveTokens();
+
+ $this->assertTrue(
+ $this->fixture->validateToken($tokenId, $formName, $action, $formInstanceName)
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function persistTokensWritesTokensToSession() {
+ $formName = 'foo';
+ $action = 'edit';
+ $formInstanceName = '42';
+
+ $tokenId = $this->fixture->generateToken(
+ $formName, $action, $formInstanceName
+ );
+ $allTokens = array(
+ $tokenId => array(
+ 'formName' => $formName,
+ 'action' => $action,
+ 'formInstanceName' => $formInstanceName,
+ ),
+ );
+
+ $GLOBALS['BE_USER']->expects($this->once())
+ ->method('setAndSaveSessionData')->with('formTokens', $allTokens);
+
+ $this->fixture->persistTokens();
+ }
+
+
+ //////////////////////////////////////////////////
+ // Tests concerning createValidationErrorMessage
+ //////////////////////////////////////////////////
+
+ /**
+ * @test
+ */
+ public function createValidationErrorMessageAddsErrorFlashMessage() {
+ $this->fixture->createValidationErrorMessage();
+
+ $messages = t3lib_FlashMessageQueue::getAllMessagesAndFlush();
+ $this->assertContains(
+ $GLOBALS['LANG']->sL(
+ 'LLL:EXT:lang/locallang_core.xml:error.formProtection.tokenInvalid'
+ ),
+ $messages[0]->render()
+ );
+ }
+}
+?>
\ No newline at end of file
Property changes on: tests/t3lib/formprotection/t3lib_formProtection_BackendTest.php
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Index: tests/typo3/sysext/install/tx_install_FormProtectionTest.php
===================================================================
--- tests/typo3/sysext/install/tx_install_FormProtectionTest.php (revision 0)
+++ tests/typo3/sysext/install/tx_install_FormProtectionTest.php (revision 0)
@@ -0,0 +1,190 @@
+
+ */
+class tx_install_FormProtectionTest extends tx_phpunit_testcase {
+ /**
+ * @var tx_install_FormProtection
+ */
+ private $fixture;
+
+ /**
+ * backup of $_SESSION
+ *
+ * @var array
+ */
+ private $sessionBackup;
+
+ public function setUp() {
+ $this->sessionBackup = $_SESSION;
+
+ $className = $this->createAccessibleProxyClass();
+ $this->fixture = new $className();
+ }
+
+ public function tearDown() {
+ $this->fixture->__destruct();
+ unset($this->fixture);
+
+ t3lib_FlashMessageQueue::getAllMessagesAndFlush();
+
+ $_SESSION = $this->sessionBackup;
+ }
+
+
+ //////////////////////
+ // Utility functions
+ //////////////////////
+
+ /**
+ * Creates a subclass tx_install_FormProtection with retrieveTokens made
+ * public.
+ *
+ * @return string the name of the created class, will not be empty
+ */
+ private function createAccessibleProxyClass() {
+ $className = 'tx_install_FormProtectionAccessibleProxy';
+ if (!class_exists($className)) {
+ eval(
+ 'class ' . $className . ' extends tx_install_FormProtection {' .
+ ' public function createValidationErrorMessage() {' .
+ ' parent::createValidationErrorMessage();' .
+ ' }' .
+ ' public function retrieveTokens() {' .
+ ' return parent::retrieveTokens();' .
+ ' }' .
+ '}'
+ );
+ }
+
+ return $className;
+ }
+
+
+ ////////////////////////////////////
+ // Tests for the utility functions
+ ////////////////////////////////////
+
+ /**
+ * @test
+ */
+ public function createAccessibleProxyCreatesInstallToolFormProtectionSubclass() {
+ $className = $this->createAccessibleProxyClass();
+
+ $this->assertTrue(
+ (new $className()) instanceof tx_install_FormProtection
+ );
+ }
+
+
+ //////////////////////////////////////////////////////////
+ // Tests concerning the reading and saving of the tokens
+ //////////////////////////////////////////////////////////
+
+ /**
+ * @test
+ */
+ public function tokensFromSessionDataAreAvailableForValidateToken() {
+ $tokenId = '51a655b55c54d54e5454c5f521f6552a';
+ $formName = 'foo';
+ $action = 'edit';
+ $formInstanceName = '42';
+
+ $_SESSION['installToolFormTokens'] = array(
+ $tokenId => array(
+ 'formName' => $formName,
+ 'action' => $action,
+ 'formInstanceName' => $formInstanceName,
+ ),
+ );
+
+ $this->fixture->retrieveTokens();
+
+ $this->assertTrue(
+ $this->fixture->validateToken(
+ $tokenId, $formName, $action, $formInstanceName
+ )
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function persistTokensWritesTokensToSession() {
+ $formName = 'foo';
+ $action = 'edit';
+ $formInstanceName = '42';
+
+ $tokenId = $this->fixture->generateToken(
+ $formName, $action, $formInstanceName
+ );
+
+ $this->fixture->persistTokens();
+
+ $this->assertEquals(
+ array(
+ $tokenId => array(
+ 'formName' => $formName,
+ 'action' => $action,
+ 'formInstanceName' => $formInstanceName,
+ ),
+ ),
+ $_SESSION['installToolFormTokens']
+ );
+ }
+
+
+ //////////////////////////////////////////////////
+ // Tests concerning createValidationErrorMessage
+ //////////////////////////////////////////////////
+
+ /**
+ * @test
+ */
+ public function createValidationErrorMessageAddsErrorMessage() {
+ $installTool = $this->getMock(
+ 'tx_install', array('addErrorMessage'), array(), '', FALSE
+ );
+ $installTool->expects($this->once())->method('addErrorMessage')
+ ->with(
+ 'Validating the security token of this form has failed. ' .
+ 'Please reload the form and submit it again.'
+ );
+ $this->fixture->injectInstallTool($installTool);
+
+ $this->fixture->createValidationErrorMessage();
+ }
+}
+?>
\ No newline at end of file
Property changes on: tests/typo3/sysext/install/tx_install_FormProtectionTest.php
___________________________________________________________________
Added: svn:mime-type
+ text/plain