[TASK] Migrate eID scripts to use PSR-7 45/41145/8
authorBenjamin Mack <benni@typo3.org>
Mon, 13 Jul 2015 19:41:11 +0000 (21:41 +0200)
committerChristian Kuhn <lolli@schwarzbu.ch>
Thu, 16 Jul 2015 19:12:48 +0000 (21:12 +0200)
Move all eID scripts to use the request/response model from PSR-7.

A fallback is in place to handle old-style eID scripts.

Releases: master
Resolves: #68186
Change-Id: I17d7b6c1eb9c7892b92c2a19c26de82a9875db6b
Reviewed-on: http://review.typo3.org/41145
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Tested-by: Markus Klein <markus.klein@typo3.org>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
20 files changed:
typo3/sysext/backend/Classes/Controller/LoginController.php
typo3/sysext/backend/Classes/Http/AjaxRequestHandler.php
typo3/sysext/core/Classes/Controller/FileDumpController.php [new file with mode: 0644]
typo3/sysext/core/Classes/Core/Bootstrap.php
typo3/sysext/core/Classes/Http/AjaxRequestHandler.php
typo3/sysext/core/Classes/Http/ControllerInterface.php
typo3/sysext/core/Documentation/Changelog/master/Breaking-68186-AdjustedAndRemovedMethodsInEIDArea.rst [new file with mode: 0644]
typo3/sysext/core/Documentation/Changelog/master/Feature-68186-PSR-7SupportForEIDAdded.rst [new file with mode: 0644]
typo3/sysext/core/Resources/PHP/FileDumpEID.php [deleted file]
typo3/sysext/core/ext_localconf.php
typo3/sysext/frontend/Classes/Controller/ExtDirectEidController.php
typo3/sysext/frontend/Classes/Controller/ShowImageController.php
typo3/sysext/frontend/Classes/Http/EidRequestHandler.php
typo3/sysext/frontend/Classes/Utility/EidUtility.php
typo3/sysext/frontend/Resources/PHP/Eid/ExtDirect.php [deleted file]
typo3/sysext/frontend/Resources/PHP/Eid/ShowPic.php [deleted file]
typo3/sysext/frontend/ext_localconf.php
typo3/sysext/rtehtmlarea/Classes/Controller/SpellCheckingController.php
typo3/sysext/rtehtmlarea/Resources/Private/PHP/SpellCheckerEid.php [deleted file]
typo3/sysext/rtehtmlarea/ext_localconf.php

index 6647c04..6a42e98 100644 (file)
@@ -14,12 +14,14 @@ namespace TYPO3\CMS\Backend\Controller;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Psr\Http\Message\ServerRequestInterface;
 use TYPO3\CMS\Backend\Exception;
 use TYPO3\CMS\Backend\LoginProvider\LoginProviderInterface;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\FormProtection\BackendFormProtection;
 use TYPO3\CMS\Core\FormProtection\FormProtectionFactory;
+use TYPO3\CMS\Core\Http\Response;
 use TYPO3\CMS\Core\Page\PageRenderer;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\HttpUtility;
@@ -124,13 +126,13 @@ class LoginController implements \TYPO3\CMS\Core\Http\ControllerInterface {
         * As this controller goes only through the main() method, it is rather simple for now
         * This will be split up in an abstract controller once proper routing/dispatcher is in place.
         *
-        * @param \Psr\Http\Message\RequestInterface $request
+        * @param ServerRequestInterface $request
         * @return \Psr\Http\Message\ResponseInterface $response
         */
-       public function processRequest(\Psr\Http\Message\RequestInterface $request) {
+       public function processRequest(ServerRequestInterface $request) {
                $content = $this->main();
-               /** @var \TYPO3\CMS\Core\Http\Response $response */
-               $response = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Http\Response::class);
+               /** @var Response $response */
+               $response = GeneralUtility::makeInstance(Response::class);
                $response->getBody()->write($content);
                return $response;
        }
index b85ba12..bfb7412 100644 (file)
@@ -87,7 +87,7 @@ class AjaxRequestHandler implements RequestHandlerInterface {
 
                // Instantiating the AJAX object
                $ajaxObj = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Http\AjaxRequestHandler::class, $ajaxID);
-               $ajaxParams = array();
+               $ajaxParams = array('request' => $request);
 
                // Evaluating the arguments and calling the AJAX method/function
                if (empty($ajaxID)) {
@@ -114,9 +114,7 @@ class AjaxRequestHandler implements RequestHandlerInterface {
                }
 
                // Outputting the content (and setting the X-JSON-Header)
-               $ajaxObj->render();
-
-               return NULL;
+               return $ajaxObj->render();
        }
 
        /**
diff --git a/typo3/sysext/core/Classes/Controller/FileDumpController.php b/typo3/sysext/core/Classes/Controller/FileDumpController.php
new file mode 100644 (file)
index 0000000..d93bdcc
--- /dev/null
@@ -0,0 +1,102 @@
+<?php
+namespace TYPO3\CMS\Core\Controller;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Core\Http\ControllerInterface;
+use TYPO3\CMS\Core\Http\Response;
+use TYPO3\CMS\Core\Resource\Hook\FileDumpEIDHookInterface;
+use TYPO3\CMS\Core\Resource\ProcessedFileRepository;
+use TYPO3\CMS\Core\Resource\ResourceFactory;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\HttpUtility;
+
+/**
+ * Class FileDumpController
+ */
+class FileDumpController implements ControllerInterface {
+
+       /**
+        * @param ServerRequestInterface $request
+        * @return NULL|Response
+        *
+        * @throws \InvalidArgumentException
+        * @throws \RuntimeException
+        * @throws \TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException
+        * @throws \UnexpectedValueException
+        */
+       public function processRequest(ServerRequestInterface $request) {
+               $parameters = array('eID' => 'dumpFile');
+               $t = $this->getGetOrPost($request, 't');
+               if ($t) {
+                       $parameters['t'] = $t;
+               }
+               $f = $this->getGetOrPost($request, 'f');
+               if ($f) {
+                       $parameters['f'] = $f;
+               }
+               $p = $this->getGetOrPost($request, 'p');
+               if ($p) {
+                       $parameters['p'] = $p;
+               }
+
+               if (GeneralUtility::hmac(implode('|', $parameters), 'resourceStorageDumpFile') === $this->getGetOrPost($request, 'token')) {
+                       if (isset($parameters['f'])) {
+                               $file = ResourceFactory::getInstance()->getFileObject($parameters['f']);
+                               if ($file->isDeleted() || $file->isMissing()) {
+                                       $file = NULL;
+                               }
+                       } else {
+                               $file = GeneralUtility::makeInstance(ProcessedFileRepository::class)->findByUid($parameters['p']);
+                               if ($file->isDeleted()) {
+                                       $file = NULL;
+                               }
+                       }
+
+                       if ($file === NULL) {
+                               HttpUtility::setResponseCodeAndExit(HttpUtility::HTTP_STATUS_404);
+                       }
+
+                       // Hook: allow some other process to do some security/access checks. Hook should issue 403 if access is rejected
+                       if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['FileDumpEID.php']['checkFileAccess'])) {
+                               foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['FileDumpEID.php']['checkFileAccess'] as $classRef) {
+                                       $hookObject = GeneralUtility::getUserObj($classRef);
+                                       if (!$hookObject instanceof FileDumpEIDHookInterface) {
+                                               throw new \UnexpectedValueException('FileDump hook object must implement interface ' . FileDumpEIDHookInterface::class, 1394442417);
+                                       }
+                                       $hookObject->checkFileAccess($file);
+                               }
+                       }
+                       $file->getStorage()->dumpFileContents($file);
+                       // @todo Refactor FAL to not echo directly, but to implement a stream for output here and use response
+                       return NULL;
+               } else {
+                       $response = GeneralUtility::makeInstance(Response::class);
+                       return $response->withStatus(403);
+               }
+       }
+
+       /**
+        * @param ServerRequestInterface $request
+        * @param string $parameter
+        * @return NULL|mixed
+        */
+       protected function getGetOrPost(ServerRequestInterface $request, $parameter) {
+               return isset($request->getParsedBody()[$parameter])
+                       ? $request->getParsedBody()[$parameter]
+                       : isset($request->getQueryParams()[$parameter]) ? $request->getQueryParams()[$parameter] : NULL;
+       }
+
+}
index b05e141..f9a692d 100644 (file)
@@ -245,7 +245,7 @@ class Bootstrap {
         * Be sure to always have the constants that are defined in $this->defineTypo3RequestTypes() are set,
         * so most RequestHandlers can check if they can handle the request.
         *
-        * @param \Psr\Http\Message\RequestInterface|\Symfony\Component\Console\Input\InputInterface $request
+        * @param \Psr\Http\Message\ServerRequestInterface|\Symfony\Component\Console\Input\InputInterface $request
         * @return \TYPO3\CMS\Core\Http\RequestHandlerInterface|\TYPO3\CMS\Core\Console\RequestHandlerInterface
         * @throws \TYPO3\CMS\Core\Exception
         * @internal This is not a public API method, do not use in own extensions
@@ -253,6 +253,7 @@ class Bootstrap {
        protected function resolveRequestHandler($request) {
                $suitableRequestHandlers = array();
                foreach ($this->availableRequestHandlers as $requestHandlerClassName) {
+                       /** @var \TYPO3\CMS\Core\Http\RequestHandlerInterface|\TYPO3\CMS\Core\Console\RequestHandlerInterface $requestHandler */
                        $requestHandler = GeneralUtility::makeInstance($requestHandlerClassName, $this);
                        if ($requestHandler->canHandleRequest($request)) {
                                $priority = $requestHandler->getPriority();
@@ -299,6 +300,8 @@ class Bootstrap {
                                foreach ($this->response->getHeaders() as $name => $values) {
                                        header($name . ': ' . implode(', ', $values), FALSE);
                                }
+                               // send the response type
+                               header('HTTP/' . $this->response->getProtocolVersion() . ' ' . $this->response->getStatusCode() . ' ' . $this->response->getReasonPhrase());
                        }
                        echo $this->response->getBody()->__toString();
                }
index a7d854b..a88cb5f 100644 (file)
@@ -14,7 +14,10 @@ namespace TYPO3\CMS\Core\Http;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
 use TYPO3\CMS\Core\Utility\ArrayUtility;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
  * Class to hold all the information about an AJAX call and send
@@ -169,66 +172,81 @@ class AjaxRequestHandler {
        /**
         * Renders the AJAX call based on the $contentFormat variable and exits the request
         *
-        * @return void
+        * @return ResponseInterface|NULL
         */
        public function render() {
                if ($this->isError) {
-                       $this->renderAsError();
-                       die;
+                       return $this->renderAsError();
                }
                switch ($this->contentFormat) {
                        case 'jsonhead':
                        case 'jsonbody':
                        case 'json':
-                               $this->renderAsJSON();
+                               return $this->renderAsJSON();
                                break;
                        case 'javascript':
-                               $this->renderAsJavascript();
+                               return $this->renderAsJavascript();
                                break;
                        case 'xml':
-                               $this->renderAsXML();
+                               return $this->renderAsXML();
                                break;
                        default:
-                               $this->renderAsPlain();
+                               return $this->renderAsPlain();
                }
-               die;
        }
 
        /**
         * Renders the AJAX call in XML error style to handle with JS
         * the "responseXML" of the transport object will be filled with the error message then
         *
-        * @return void
+        * @return ResponseInterface
         */
        protected function renderAsError() {
-               header(\TYPO3\CMS\Core\Utility\HttpUtility::HTTP_STATUS_500 . ' (AJAX)');
-               header('Content-type: text/xml; charset=utf-8');
-               header('X-JSON: false');
-               die('<t3err>' . htmlspecialchars($this->errorMessage) . '</t3err>');
+               /** @var Response $response */
+               $response = GeneralUtility::makeInstance(Response::class);
+               $response = $response
+                       ->withStatus(500, ' (AJAX)')
+                       ->withHeader('Content-type', 'text/xml; charset=utf-8')
+                       ->withHeader('X-JSON', 'false');
+
+               $response->getBody()->write('<t3err>' . htmlspecialchars($this->errorMessage) . '</t3err>');
+               return $response;
        }
 
        /**
         * Renders the AJAX call with text/html headers
         * the content will be available in the "responseText" value of the transport object
         *
-        * @return void
+        * @return ResponseInterface
+        * @throws \InvalidArgumentException
         */
        protected function renderAsPlain() {
-               header('Content-type: text/html; charset=utf-8');
-               header('X-JSON: true');
-               echo implode('', $this->content);
+               /** @var Response $response */
+               $response = GeneralUtility::makeInstance(Response::class);
+               $response = $response
+                       ->withHeader('Content-type', 'text/html; charset=utf-8')
+                       ->withHeader('X-JSON', 'true');
+
+               $response->getBody()->write(implode('', $this->content));
+               return $response;
        }
 
        /**
         * Renders the AJAX call with text/xml headers
         * the content will be available in the "responseXML" value of the transport object
         *
-        * @return void
+        * @return ResponseInterface
+        * @throws \InvalidArgumentException
         */
        protected function renderAsXML() {
-               header('Content-type: text/xml; charset=utf-8');
-               header('X-JSON: true');
-               echo implode('', $this->content);
+               /** @var Response $response */
+               $response = GeneralUtility::makeInstance(Response::class);
+               $response = $response
+                       ->withHeader('Content-type', 'text/xml; charset=utf-8')
+                       ->withHeader('X-JSON', 'true');
+
+               $response->getBody()->write(implode('', $this->content));
+               return $response;
        }
 
        /**
@@ -241,30 +259,37 @@ class AjaxRequestHandler {
         * - and in the xhr.responseText as a string (except when contentFormat = 'jsonhead')
         * you can evaluate this in JS with xhr.responseText.evalJSON();
         *
-        * @return void
+        * @return ResponseInterface
+        * @throws \InvalidArgumentException
         */
        protected function renderAsJSON() {
+               /** @var Response $response */
+               $response = GeneralUtility::makeInstance(Response::class);
+               $response = $response->withHeader('Content-type', 'application/json; charset=utf-8');
+
                $content = json_encode($this->content);
-               header('Content-type: application/json; charset=utf-8');
                // Bring content in xhr.responseText except when in "json head only" mode
                if ($this->contentFormat === 'jsonhead') {
-                       header('X-JSON: ' . $content);
+                       $response = $response->withHeader('X-JSON', $content);
                } else {
-                       header('X-JSON: true');
-                       echo $content;
+                       $response = $response->withHeader('X-JSON', 'true');
+                       $response->getBody()->write($content);
                }
+               return $response;
        }
 
        /**
         * Renders the AJAX call as inline JSON inside a script tag. This is useful
         * when an iframe is used as the AJAX transport.
         *
-        * @return void
+        * @return ResponseInterface
+        * @throws \InvalidArgumentException
         */
        protected function renderAsJavascript() {
-               $content = str_replace('|', json_encode($this->content), $this->javascriptCallbackWrap);
-               header('Content-type: text/html; charset=utf-8');
-               echo $content;
+               $response = GeneralUtility::makeInstance(Response::class);
+               $response = $response->withHeader('Content-type', 'text/html; charset=utf-8');
+               $response->getBody()->write(str_replace('|', json_encode($this->content), $this->javascriptCallbackWrap));
+               return $response;
        }
 
 }
index e2d275e..3601ac0 100644 (file)
@@ -15,7 +15,7 @@ namespace TYPO3\CMS\Core\Http;
  */
 
 use Psr\Http\Message\ResponseInterface;
-use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ServerRequestInterface;
 
 /**
  * An interface every controller should implement
@@ -28,10 +28,10 @@ interface ControllerInterface {
        /**
         * Processes a typical request.
         *
-        * @param RequestInterface $request The request object
+        * @param ServerRequestInterface $request The request object
         * @return ResponseInterface $response The response, created by the controller
         * @api
         */
-       public function processRequest(RequestInterface $request);
+       public function processRequest(ServerRequestInterface $request);
 
 }
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-68186-AdjustedAndRemovedMethodsInEIDArea.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-68186-AdjustedAndRemovedMethodsInEIDArea.rst
new file mode 100644 (file)
index 0000000..30ed749
--- /dev/null
@@ -0,0 +1,38 @@
+===========================================================
+Breaking: #68186 - Adjusted and removed methods in eID area
+===========================================================
+
+Description
+===========
+
+eID scripts now use Request and Response objects to retrieve and output data.
+
+Due to adjustments of the Core eID scripts a few methods have been adjusted.
+
+``ExtDirectEidController::routeAction`` is now protected and has a changed signature.
+
+The following methods are removed:
+
+* ``ExtDirectEidController::actionIsAllowed``
+* ``ExtDirectEidController::render``
+* ``EidUtility::isEidRequest``
+* ``EidUtility::getEidScriptPath``
+
+Additionally every call to a not registered eID key will result in a fatal error.
+
+Impact
+======
+
+All third party code using those methods will cause a fatal PHP error.
+
+
+Affected Installations
+======================
+
+All installations using third party code accessing one of the adjusted (removed) methods.
+
+
+Migration
+=========
+
+No replacement for the mentioned methods is provided. Consider migrating your eID script to the new PSR-7 compliant model.
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-68186-PSR-7SupportForEIDAdded.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-68186-PSR-7SupportForEIDAdded.rst
new file mode 100644 (file)
index 0000000..8fd700f
--- /dev/null
@@ -0,0 +1,8 @@
+=============================================
+Feature: #68186 - PSR-7 support for eID added
+=============================================
+
+Description
+===========
+
+The eID dispatcher now supports eID scripts using the ``TYPO3\CMS\Core\Http\ControllerInterface``. This allows to handle the request using the Request and Response objects.
diff --git a/typo3/sysext/core/Resources/PHP/FileDumpEID.php b/typo3/sysext/core/Resources/PHP/FileDumpEID.php
deleted file mode 100644 (file)
index 4356c93..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-<?php
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-$parameters = array('eID' => 'dumpFile');
-if (\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('t')) {
-       $parameters['t'] = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('t');
-}
-if (\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('f')) {
-       $parameters['f'] = (int)\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('f');
-}
-if (\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('p')) {
-       $parameters['p'] = (int)\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('p');
-}
-
-if (\TYPO3\CMS\Core\Utility\GeneralUtility::hmac(implode('|', $parameters), 'resourceStorageDumpFile') === \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('token')) {
-       if (isset($parameters['f'])) {
-               $file = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->getFileObject($parameters['f']);
-               if ($file->isDeleted() || $file->isMissing()) {
-                       $file = NULL;
-               }
-       } else {
-               $file = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\ProcessedFileRepository::class)->findByUid($parameters['p']);
-               if ($file->isDeleted()) {
-                       $file = NULL;
-               }
-       }
-
-       if ($file === NULL) {
-               \TYPO3\CMS\Core\Utility\HttpUtility::setResponseCodeAndExit(\TYPO3\CMS\Core\Utility\HttpUtility::HTTP_STATUS_404);
-       }
-
-       // Hook: allow some other process to do some security/access checks. Hook should issue 403 if access is rejected
-       if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['FileDumpEID.php']['checkFileAccess'])) {
-               foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['FileDumpEID.php']['checkFileAccess'] as $classRef) {
-                       $hookObject = \TYPO3\CMS\Core\Utility\GeneralUtility::getUserObj($classRef);
-                       if (!$hookObject instanceof \TYPO3\CMS\Core\Resource\Hook\FileDumpEIDHookInterface) {
-                               throw new \UnexpectedValueException('$hookObject must implement interface TYPO3\\CMS\\Core\\Resource\\FileDumpEIDHookInterface', 1394442417);
-                       }
-                       $hookObject->checkFileAccess($file);
-               }
-       }
-       $file->getStorage()->dumpFileContents($file);
-} else {
-       \TYPO3\CMS\Core\Utility\HttpUtility::setResponseCodeAndExit(\TYPO3\CMS\Core\Utility\HttpUtility::HTTP_STATUS_403);
-}
\ No newline at end of file
index 6e2b5e3..f9fd79d 100644 (file)
@@ -65,7 +65,7 @@ if (!\TYPO3\CMS\Core\Core\Bootstrap::usesComposerClassLoading()) {
 
 unset($signalSlotDispatcher);
 
-$GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include']['dumpFile'] = 'EXT:core/Resources/PHP/FileDumpEID.php';
+$GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include']['dumpFile'] = \TYPO3\CMS\Core\Controller\FileDumpController::class;
 
 /** @var \TYPO3\CMS\Core\Resource\Rendering\RendererRegistry $rendererRegistry */
 $rendererRegistry = \TYPO3\CMS\Core\Resource\Rendering\RendererRegistry::getInstance();
index 1b19cd1..eb5c556 100644 (file)
@@ -14,6 +14,9 @@ namespace TYPO3\CMS\Frontend\Controller;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Core\Http\ControllerInterface;
 use TYPO3\CMS\Frontend\Utility\EidUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Http\AjaxRequestHandler;
@@ -21,7 +24,7 @@ use TYPO3\CMS\Core\Http\AjaxRequestHandler;
 /**
  * eID controller for ExtDirect
  */
-class ExtDirectEidController {
+class ExtDirectEidController implements ControllerInterface {
 
        /**
         * Ajax Instance
@@ -34,11 +37,11 @@ class ExtDirectEidController {
         * Routes the given eID action to the related ExtDirect method with the necessary
         * ajax object.
         *
+        * @param string $ajaxID
         * @return void
         */
-       public function routeAction() {
+       protected function routeAction($ajaxID) {
                EidUtility::initLanguage();
-               $ajaxID = GeneralUtility::_GP('action');
                $ajaxScript = $GLOBALS['TYPO3_CONF_VARS']['BE']['AJAX']['ExtDirect::' . $ajaxID]['callbackMethod'];
                $this->ajaxObject = GeneralUtility::makeInstance(AjaxRequestHandler::class, 'ExtDirect::' . $ajaxID);
                $parameters = array();
@@ -46,24 +49,21 @@ class ExtDirectEidController {
        }
 
        /**
-        * Returns TRUE if the associated action in _GET is allowed.
-        *
-        * @return bool
-        */
-       public function actionIsAllowed() {
-               if (!in_array(GeneralUtility::_GP('action'), array('route', 'getAPI'))) {
-                       return FALSE;
-               }
-               return TRUE;
-       }
-
-       /**
         * Renders/Echoes the ajax output
         *
-        * @return void
+        * @param ServerRequestInterface $request
+        * @return ResponseInterface|NULL
+        * @throws \InvalidArgumentException
         */
-       public function render() {
-               $this->ajaxObject->render();
+       public function processRequest(ServerRequestInterface $request) {
+               $action = isset($request->getParsedBody()['action'])
+                       ? $request->getParsedBody()['action']
+                       : isset($request->getQueryParams()['action']) ? $request->getQueryParams()['action'] : '';
+               if (!in_array($action, array('route', 'getAPI'), TRUE)) {
+                       return NULL;
+               }
+               $this->routeAction($action);
+               return $this->ajaxObject->render();
        }
 
 }
index f824c4b..47e6afc 100644 (file)
@@ -14,20 +14,35 @@ namespace TYPO3\CMS\Frontend\Controller;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Core\Exception;
+use TYPO3\CMS\Core\Http\ControllerInterface;
+use TYPO3\CMS\Core\Http\Response;
 use TYPO3\CMS\Core\Resource\ResourceFactory;
-use TYPO3\CMS\Core\Utility\HttpUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
 
 /**
- * Script Class, generating the page output.
- * Instantiated in the bottom of this script.
+ * eID-Script "tx_cms_showpic"
+ *
+ * Shows a picture from FAL in enlarged format in a separate window.
+ * Picture file and settings is supplied by GET-parameters:
+ *
+ *  - file = fileUid or Combined Identifier
+ *  - encoded in an parameter Array (with weird format - see ContentObjectRenderer about ll. 1500)
+ *  - width, height = usual width an height, m/c supported
+ *  - frame
+ *  - bodyTag
+ *  - title
  */
-class ShowImageController {
+class ShowImageController implements ControllerInterface {
+
+       /**
+        * @var \Psr\Http\Message\ServerRequestInterface
+        */
+       protected $request;
 
        /**
-        * Parameters loaded into these internal variables:
-        *
         * @var \TYPO3\CMS\Core\Resource\File
         */
        protected $file;
@@ -43,16 +58,6 @@ class ShowImageController {
        protected $height;
 
        /**
-        * @var string
-        */
-       protected $sample;
-
-       /**
-        * @var string
-        */
-       protected $effects;
-
-       /**
         * @var int
         */
        protected $frame;
@@ -60,21 +65,11 @@ class ShowImageController {
        /**
         * @var string
         */
-       protected $hmac;
-
-       /**
-        * @var string
-        */
        protected $bodyTag = '<body>';
 
        /**
         * @var string
         */
-       protected $wrap = '|';
-
-       /**
-        * @var string
-        */
        protected $title = 'Image';
 
        /**
@@ -102,27 +97,26 @@ EOF;
         * Init function, setting the input vars in the global space.
         *
         * @return void
+        * @throws \InvalidArgumentException
+        * @throws \TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException
         */
-       public function init() {
-               // Loading internal vars with the GET/POST parameters from outside:
-               $fileUid = GeneralUtility::_GP('file');
-               $this->frame = GeneralUtility::_GP('frame');
-               /* For backwards compatibility the HMAC is transported within the md5 param */
-               $this->hmac = GeneralUtility::_GP('md5');
-
-               $parametersArray = GeneralUtility::_GP('parameters');
+       public function initialize() {
+               $fileUid = isset($this->request->getQueryParams()['file']) ? $this->request->getQueryParams()['file'] : NULL;
+               $parametersArray = isset($this->request->getQueryParams()['parameters']) ? $this->request->getQueryParams()['parameters'] : NULL;
 
                // If no file-param or parameters are given, we must exit
                if (!$fileUid || !isset($parametersArray) || !is_array($parametersArray)) {
-                       HttpUtility::setResponseCodeAndExit(HttpUtility::HTTP_STATUS_410);
+                       throw new \InvalidArgumentException('No valid fileUid given');
                }
 
                // rebuild the parameter array and check if the HMAC is correct
                $parametersEncoded = implode('', $parametersArray);
-               $hmac = GeneralUtility::hmac(implode('|', array($fileUid, $parametersEncoded)));
-               if ($hmac !== $this->hmac) {
-                       HttpUtility::setResponseCodeAndExit(HttpUtility::HTTP_STATUS_410);
 
+               /* For backwards compatibility the HMAC is transported within the md5 param */
+               $hmacParameter = isset($this->request->getQueryParams()['md5']) ? $this->request->getQueryParams()['md5'] : NULL;
+               $hmac = GeneralUtility::hmac(implode('|', array($fileUid, $parametersEncoded)));
+               if ($hmac !== $hmacParameter) {
+                       throw new \InvalidArgumentException('hash does not match');
                }
 
                // decode the parameters Array
@@ -131,15 +125,12 @@ EOF;
                        $this->{$parameterName} = $parameterValue;
                }
 
-               try {
-                       if (MathUtility::canBeInterpretedAsInteger($fileUid)) {
-                               $this->file = ResourceFactory::getInstance()->getFileObject((int)$fileUid);
-                       } else {
-                               $this->file = ResourceFactory::getInstance()->retrieveFileOrFolderObject($fileUid);
-                       }
-               } catch (\TYPO3\CMS\Core\Exception $e) {
-                       HttpUtility::setResponseCodeAndExit(HttpUtility::HTTP_STATUS_404);
+               if (MathUtility::canBeInterpretedAsInteger($fileUid)) {
+                       $this->file = ResourceFactory::getInstance()->getFileObject((int)$fileUid);
+               } else {
+                       $this->file = ResourceFactory::getInstance()->retrieveFileOrFolderObject($fileUid);
                }
+               $this->frame = isset($this->request->getQueryParams()['frame']) ? $this->request->getQueryParams()['frame'] : NULL;
        }
 
        /**
@@ -158,10 +149,6 @@ EOF;
                        '###height###' => $processedImage->getProperty('height')
                );
                $this->imageTag = str_replace(array_keys($imageTagMarkers), array_values($imageTagMarkers), $this->imageTag);
-               if ($this->wrap !== '|') {
-                       $wrapParts = explode('|', $this->wrap, 2);
-                       $this->imageTag = $wrapParts[0] . $this->imageTag . $wrapParts[1];
-               }
                $markerArray = array(
                        '###TITLE###' => ($this->file->getProperty('title') ?: $this->title),
                        '###IMAGE###' => $this->imageTag,
@@ -169,7 +156,6 @@ EOF;
                );
 
                $this->content = str_replace(array_keys($markerArray), array_values($markerArray), $this->content);
-
        }
 
        /**
@@ -194,25 +180,30 @@ EOF;
                );
                return $this->file->process('Image.CropScaleMask', $processingConfiguration);
        }
-       /**
-        * Outputs the content from $this->content
-        *
-        * @return void
-        */
-       public function printContent() {
-               echo $this->content;
-               HttpUtility::setResponseCodeAndExit(HttpUtility::HTTP_STATUS_200);
-       }
 
        /**
-        * Execute
+        * Fetches the content and builds a content file out of it
         *
-        * @return void
+        * @param \Psr\Http\Message\ServerRequestInterface $request
+        * @return \Psr\Http\Message\ResponseInterface
         */
-       public function execute() {
-               $this->init();
-               $this->main();
-               $this->printContent();
+       public function processRequest(ServerRequestInterface $request) {
+               $this->request = $request;
+
+               /** @var Response $response */
+               $response = GeneralUtility::makeInstance(Response::class);
+
+               try {
+                       $this->initialize();
+                       $this->main();
+                       $response->getBody()->write($this->content);
+                       return $response;
+               } catch (\InvalidArgumentException $e) {
+                       // add a 410 "gone" if invalid parameters given
+                       return $response->withStatus(410);
+               } catch (Exception $e) {
+                       return $response->withStatus(404);
+               }
        }
 
 }
index 09dcbc6..06d7485 100644 (file)
@@ -15,9 +15,11 @@ namespace TYPO3\CMS\Frontend\Http;
  */
 
 use TYPO3\CMS\Core\Core\Bootstrap;
+use TYPO3\CMS\Core\Exception;
+use TYPO3\CMS\Core\Http\ControllerInterface;
+use TYPO3\CMS\Core\Http\Response;
 use TYPO3\CMS\Core\TimeTracker\NullTimeTracker;
 use TYPO3\CMS\Core\TimeTracker\TimeTracker;
-use TYPO3\CMS\Frontend\Utility\EidUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Http\RequestHandlerInterface;
 use Psr\Http\Message\ServerRequestInterface;
@@ -50,7 +52,6 @@ class EidRequestHandler implements RequestHandlerInterface {
         * @return NULL|\Psr\Http\Message\ResponseInterface
         */
        public function handleRequest(ServerRequestInterface $request) {
-               $response = NULL;
                // Timetracking started
                $configuredCookieName = trim($GLOBALS['TYPO3_CONF_VARS']['BE']['cookieName']);
                if (empty($configuredCookieName)) {
@@ -76,9 +77,7 @@ class EidRequestHandler implements RequestHandlerInterface {
 
                // Remove any output produced until now
                $this->bootstrap->endOutputBufferingAndCleanPreviousOutput();
-               require EidUtility::getEidScriptPath();
-
-               return $response;
+               return $this->dispatch($request);
        }
 
        /**
@@ -88,7 +87,7 @@ class EidRequestHandler implements RequestHandlerInterface {
         * @return bool If the request is not an eID request, TRUE otherwise FALSE
         */
        public function canHandleRequest(ServerRequestInterface $request) {
-               return $request->getQueryParams()['eID'] || $request->getParsedBody()['eID'];
+               return !empty($request->getQueryParams()['eID']) || !empty($request->getParsedBody()['eID']);
        }
 
        /**
@@ -101,4 +100,37 @@ class EidRequestHandler implements RequestHandlerInterface {
                return 80;
        }
 
+       /**
+        * Dispatches the request to the corresponding eID class or eID script
+        *
+        * @param ServerRequestInterface $request
+        * @return NULL|\Psr\Http\Message\ResponseInterface
+        * @throws Exception
+        */
+       protected function dispatch($request) {
+               $eID = isset($request->getParsedBody()['eID'])
+                       ? $request->getParsedBody()['eID']
+                       : isset($request->getQueryParams()['eID']) ? $request->getQueryParams()['eID'] : '';
+
+               if (empty($eID) || !isset($GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include'][$eID])) {
+                       return GeneralUtility::makeInstance(Response::class)->withStatus(404, 'eID not registered');
+               }
+
+               $configuration = $GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include'][$eID];
+               if (class_exists($configuration)) {
+                       $controller = GeneralUtility::makeInstance($configuration);
+                       if (!$controller instanceof ControllerInterface) {
+                               throw new Exception('The provided eID class "' . $configuration . '" does not implement "ControllerInterface".', 1436909478);
+                       }
+                       return $controller->processRequest($request);
+               }
+
+               $scriptPath = GeneralUtility::getFileAbsFileName($configuration);
+               if ($scriptPath === '') {
+                       throw new Exception('Registered eID has invalid script path.', 1416391467);
+               }
+               include $scriptPath;
+               return NULL;
+       }
+
 }
index eb5c21a..76a5823 100644 (file)
@@ -33,33 +33,6 @@ use TYPO3\CMS\Lang\LanguageService;
 class EidUtility {
 
        /**
-        * Returns true if within an eID-request. False if not.
-        *
-        * @return bool
-        */
-       static public function isEidRequest() {
-               return (bool)GeneralUtility::_GP('eID');
-       }
-
-       /**
-        * Returns the script path associated with the requested eID identifier.
-        *
-        * @return string eID associated script path
-        * @throws \TYPO3\CMS\Core\Exception
-        */
-       static public function getEidScriptPath() {
-               $eID = GeneralUtility::_GP('eID');
-               if (!$eID || !isset($GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include'][$eID])) {
-                       throw new \TYPO3\CMS\Core\Exception('eID not registered in $GLOBALS[\'TYPO3_CONF_VARS\'][\'FE\'][\'eID_include\'].', 1415714161);
-               }
-               $scriptPath = GeneralUtility::getFileAbsFileName($GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include'][$eID]);
-               if ($scriptPath === '') {
-                       throw new \TYPO3\CMS\Core\Exception('Registered eID has invalid script path.', 1416391467);
-               }
-               return $scriptPath;
-       }
-
-       /**
         * Load and initialize Frontend User. Note, this process is slow because
         * it creates a calls many objects. Call this method only if necessary!
         *
diff --git a/typo3/sysext/frontend/Resources/PHP/Eid/ExtDirect.php b/typo3/sysext/frontend/Resources/PHP/Eid/ExtDirect.php
deleted file mode 100644 (file)
index 67fef2c..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-if (!defined('PATH_typo3conf')) {
-       die('Could not access this script directly!');
-}
-$extDirectEidInstance = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Frontend\Controller\ExtDirectEidController::class);
-if ($extDirectEidInstance->actionIsAllowed()) {
-       $extDirectEidInstance->routeAction();
-       $extDirectEidInstance->render();
-}
diff --git a/typo3/sysext/frontend/Resources/PHP/Eid/ShowPic.php b/typo3/sysext/frontend/Resources/PHP/Eid/ShowPic.php
deleted file mode 100644 (file)
index 85bb4e5..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-/**
- * eID-Script for tx_cms_showpic
- *
- * Shows a picture from FAL in enlarged format in a separate window.
- * Picture file and settings is supplied by GET-parameters:
- *  - file = fileUid or Combined Identifier
- *  - encoded in an parameter Array (with weird format - see ContentObjectRenderer about ll. 1500)
- *     - width, height = usual width an height, m/c supported
- *     - sample = 0/1
- *     - effects
- *     - frame
- *     - bodyTag
- *     - title
- *     - wrap
- *  - md5 = actually contains an hmac
- */
-
-if (!defined('PATH_typo3conf')) {
-       die('The configuration path was not properly defined!');
-}
-
-// Make instance:
-$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Frontend\Controller\ShowImageController::class);
-$GLOBALS['SOBE']->execute();
index 522ff4f..be2c83b 100644 (file)
@@ -36,9 +36,9 @@ $GLOBALS['TYPO3_CONF_VARS']['FE']['ContentObjects'] = array_merge($GLOBALS['TYPO
 if (TYPO3_MODE === 'FE') {
 
        // Register eID provider for showpic
-       $GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include']['tx_cms_showpic'] = 'EXT:frontend/Resources/PHP/Eid/ShowPic.php';
+       $GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include']['tx_cms_showpic'] = \TYPO3\CMS\Frontend\Controller\ShowImageController::class;
        // Register eID provider for ExtDirect for the frontend
-       $GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include']['ExtDirect'] = 'EXT:frontend/Resources/PHP/Eid/ExtDirect.php';
+       $GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include']['ExtDirect'] = \TYPO3\CMS\Frontend\Controller\ExtDirectEidController::class;
 
 }
 
index ed6c8e0..4f1188b 100644 (file)
@@ -14,12 +14,16 @@ namespace TYPO3\CMS\Rtehtmlarea\Controller;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Core\Http\ControllerInterface;
+use TYPO3\CMS\Core\Http\Response;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
  * Spell checking plugin 'tx_rtehtmlarea_pi1' for the htmlArea RTE extension.
  */
-class SpellCheckingController {
+class SpellCheckingController implements ControllerInterface {
 
        /**
         * @var \TYPO3\CMS\Core\Charset\CharsetConverter
@@ -141,12 +145,29 @@ class SpellCheckingController {
         */
        public $xmlCharacterData = '';
 
+
+       /**
+        * AJAX entry point
+        *
+        * @param array $ajaxParams
+        * @return void
+        * @throws \UnexpectedValueException
+        */
+       public function main(array $ajaxParams) {
+               $this->processRequest($ajaxParams['request']);
+               header('Content-Type: text/html; charset=' . strtoupper($this->parserCharset));
+               echo $this->result;
+       }
+
        /**
         * Main class of Spell Checker plugin for Typo3 CMS
         *
-        * @return string content produced by the plugin
+        * @param ServerRequestInterface $request
+        * @return ResponseInterface
+        * @throws \InvalidArgumentException
+        * @throws \UnexpectedValueException
         */
-       public function main() {
+       public function processRequest(ServerRequestInterface $request) {
                $this->csConvObj = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Charset\CharsetConverter::class);
                // Setting start time
                $time_start = microtime(TRUE);
@@ -311,7 +332,7 @@ class SpellCheckingController {
                                echo 'Bad parsing';
                        }
                        if (xml_get_error_code($parser)) {
-                               throw new \UnexpectedException('Line ' . xml_get_current_line_number($parser) . ': ' . xml_error_string(xml_get_error_code($parser)), 1294585788);
+                               throw new \UnexpectedValueException('Line ' . xml_get_current_line_number($parser) . ': ' . xml_error_string(xml_get_error_code($parser)), 1294585788);
                        }
                        xml_parser_free($parser);
                        if ($this->pspell_is_available && !$this->forceCommandMode) {
@@ -337,8 +358,10 @@ var selectedDictionary = "' . $this->dictionary . '";
                        $this->result .= '
 </body></html>';
                        // Outputting
-                       header('Content-Type: text/html; charset=' . strtoupper($this->parserCharset));
-                       echo $this->result;
+                       $response = GeneralUtility::makeInstance(Response::class);
+                       $response = $response->withHeader('Content-Type', 'text/html; charset=' . strtoupper($this->parserCharset));
+                       $response->getBody()->write($this->result);
+                       return $response;
                }
        }
 
diff --git a/typo3/sysext/rtehtmlarea/Resources/Private/PHP/SpellCheckerEid.php b/typo3/sysext/rtehtmlarea/Resources/Private/PHP/SpellCheckerEid.php
deleted file mode 100644 (file)
index 2039f6d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-namespace TYPO3\CMS\Rtehtmlarea\Controller;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-if (TYPO3_MODE === 'FE') {
-       $spellChecker = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Rtehtmlarea\Controller\SpellCheckingController::class);
-       $spellChecker->main();
-}
\ No newline at end of file
index 6e7ef81..d0c75cd 100644 (file)
@@ -157,7 +157,7 @@ $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['plugins']['Language']['ob
 $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['plugins']['Language']['disableInFE'] = 0;
 
 // Spell checking configuration
-$GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include']['rtehtmlarea_spellchecker'] = 'EXT:rtehtmlarea/Resources/Private/PHP/SpellCheckerEid.php';
+$GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include']['rtehtmlarea_spellchecker'] = \TYPO3\CMS\Rtehtmlarea\Controller\SpellCheckingController::class;
 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::registerAjaxHandler('rtehtmlarea::spellchecker', \TYPO3\CMS\Rtehtmlarea\Controller\SpellCheckingController::class . '->main');
 
 $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['plugins']['SpellChecker'] = array();