/** * Matches a \TYPO3\Flow\Mvc\RequestInterface against its set controller object name pattern rules * * @param RequestInterface $request The request that should be matched * @return boolean TRUE if the pattern matched, FALSE otherwise * @throws InvalidRequestPatternException */ public function matchRequest(RequestInterface $request) { if (!isset($this->options['controllerObjectNamePattern'])) { throw new InvalidRequestPatternException('Missing option "controllerObjectNamePattern" in the ControllerObjectName request pattern configuration', 1446224501); } return (bool) preg_match('/^' . str_replace('\\', '\\\\', $this->options['controllerObjectNamePattern']) . '$/', $request->getControllerObjectName()); }
/** * Matches the current request for an unverified signed request. * * This pattern will return TRUE if the request is not signed or * the signature of the request is invalid. * * @param \TYPO3\Flow\Mvc\RequestInterface $request The request that should be matched * @return boolean TRUE if the pattern matched, FALSE otherwise */ public function matchRequest(\TYPO3\Flow\Mvc\RequestInterface $request) { /** @var \TYPO3\Flow\Http\Request $httpRequest */ $httpRequest = $request->getHttpRequest(); if ($httpRequest->hasHeader('X-Request-Signature')) { $identifierAndSignature = explode(':', $httpRequest->getHeader('X-Request-Signature'), 2); if (count($identifierAndSignature) !== 2) { throw new \TYPO3\Flow\Exception('Invalid signature header format, expected "identifier:base64(signature)"', 1354287886); } $identifier = $identifierAndSignature[0]; $signature = base64_decode($identifierAndSignature[1]); $signData = $this->requestSigner->getSignatureContent($httpRequest); $publicKeyFingerprint = $this->publicKeyResolver->resolveFingerprintByIdentifier($identifier); if ($publicKeyFingerprint === NULL) { throw new \TYPO3\Flow\Exception('Cannot resolve identifier "' . $identifier . '"', 1354288898); } if ($this->rsaWalletService->verifySignature($signData, $signature, $publicKeyFingerprint)) { return FALSE; } else { $this->emitSignatureNotVerified($request, $identifier, $signData, $signature, $publicKeyFingerprint); } } else { $this->emitSignatureHeaderMissing($request); } return TRUE; }
/** * Matches a \TYPO3\Flow\Mvc\RequestInterface against its set host pattern rules * * @param RequestInterface $request The request that should be matched * @return boolean TRUE if the pattern matched, FALSE otherwise */ public function matchRequest(RequestInterface $request) { if (!$request instanceof ActionRequest) { return false; } $hostPattern = str_replace('\\*', '.*', preg_quote($this->hostPattern, '/')); return preg_match('/^' . $hostPattern . '$/', $request->getHttpRequest()->getUri()->getHost()) === 1; }
/** * Matches a \TYPO3\Flow\Mvc\RequestInterface against its set pattern rules * * @param RequestInterface $request The request that should be matched * @return boolean TRUE if the pattern matched, FALSE otherwise */ public function matchRequest(RequestInterface $request) { if (!$request instanceof ActionRequest) { return FALSE; } $requestPath = $request->getHttpRequest()->getUri()->getPath(); $requestPathMatchesBackend = substr($requestPath, 0, 5) === '/neos' || strpos($requestPath, '@') !== FALSE; return $this->shouldMatchBackend === $requestPathMatchesBackend; }
/** * Handles a request. The result output is returned by altering the given response. * * @param \TYPO3\Flow\Mvc\ActionRequest $request The request object * @param \TYPO3\Flow\Http\Response $response The response, modified by this handler * @return void * @throws \TYPO3\Fluid\Core\Widget\Exception\WidgetContextNotFoundException * @api */ public function processRequest(\TYPO3\Flow\Mvc\RequestInterface $request, \TYPO3\Flow\Mvc\ResponseInterface $response) { $widgetContext = $request->getInternalArgument('__widgetContext'); if ($widgetContext === NULL) { throw new \TYPO3\Fluid\Core\Widget\Exception\WidgetContextNotFoundException('The widget context could not be found in the request.', 1307450180); } $this->widgetConfiguration = $widgetContext->getWidgetConfiguration(); parent::processRequest($request, $response); }
/** * Matches a \TYPO3\Flow\Mvc\RequestInterface against the set IP pattern rules * * @param RequestInterface $request The request that should be matched * @return boolean TRUE if the pattern matched, FALSE otherwise * @throws InvalidRequestPatternException */ public function matchRequest(RequestInterface $request) { if (!isset($this->options['cidrPattern'])) { throw new InvalidRequestPatternException('Missing option "cidrPattern" in the Ip request pattern configuration', 1446224520); } if (!$request instanceof ActionRequest) { return false; } return (bool) IpUtility::cidrMatch($request->getHttpRequest()->getClientIpAddress(), $this->options['cidrPattern']); }
/** * Matches a \TYPO3\Flow\Mvc\RequestInterface against its set pattern rules * * @param RequestInterface $request The request that should be matched * @return boolean TRUE if the pattern matched, FALSE otherwise */ public function matchRequest(RequestInterface $request) { $shouldMatchBackend = $this->options['area'] === self::AREA_FRONTEND ? false : true; if (!$request instanceof ActionRequest) { return false; } $requestPath = $request->getHttpRequest()->getUri()->getPath(); $requestPathMatchesBackend = substr($requestPath, 0, 5) === '/neos' || strpos($requestPath, '@') !== false; return $shouldMatchBackend === $requestPathMatchesBackend; }
/** * Matches a \TYPO3\Flow\Mvc\RequestInterface against its set URL pattern rules * * @param RequestInterface $request The request that should be matched * @return boolean TRUE if the pattern matched, FALSE otherwise * @throws InvalidRequestPatternException */ public function matchRequest(RequestInterface $request) { if (!$request instanceof ActionRequest) { return false; } if (!isset($this->options['uriPattern'])) { throw new InvalidRequestPatternException('Missing option "uriPattern" in the Uri request pattern configuration', 1446224530); } return (bool) preg_match('/^' . str_replace('/', '\\/', $this->options['uriPattern']) . '$/', $request->getHttpRequest()->getUri()->getPath()); }
/** * Handles a request. The result output is returned by altering the given response. * * @param RequestInterface $request The request object * @param ResponseInterface $response The response, modified by this handler * @return void * @throws WidgetContextNotFoundException * @api */ public function processRequest(RequestInterface $request, ResponseInterface $response) { /** @var $request \TYPO3\Flow\Mvc\ActionRequest */ /** @var $widgetContext WidgetContext */ $widgetContext = $request->getInternalArgument('__widgetContext'); if ($widgetContext === NULL) { throw new WidgetContextNotFoundException('The widget context could not be found in the request.', 1307450180); } $this->widgetConfiguration = $widgetContext->getWidgetConfiguration(); parent::processRequest($request, $response); }
/** * Matches a \TYPO3\Flow\Mvc\RequestInterface against its set controller object name pattern rules * * @param \TYPO3\Flow\Mvc\RequestInterface $request The request that should be matched * @return boolean TRUE if the pattern matched, FALSE otherwise */ public function matchRequest(RequestInterface $request) { if (!$request instanceof ActionRequest) { return FALSE; } foreach ($this->getPattern() as $method) { if ($request->getHttpRequest()->getMethod() === $method) { return TRUE; } } }
/** * Matches a \TYPO3\Flow\Mvc\RequestInterface against its set host pattern rules * * @param RequestInterface $request The request that should be matched * @return boolean TRUE if the pattern matched, FALSE otherwise * @throws InvalidRequestPatternException */ public function matchRequest(RequestInterface $request) { if (!isset($this->options['hostPattern'])) { throw new InvalidRequestPatternException('Missing option "hostPattern" in the Host request pattern configuration', 1446224510); } if (!$request instanceof ActionRequest) { return false; } $hostPattern = str_replace('\\*', '.*', preg_quote($this->options['hostPattern'], '/')); return preg_match('/^' . $hostPattern . '$/', $request->getHttpRequest()->getUri()->getHost()) === 1; }
/** * Returns the locale item for the current request * * @param \Aimeos\MShop\Context\Item\Iface $context Context object * @param \TYPO3\Flow\Mvc\RequestInterface $request Request object * @return \Aimeos\MShop\Locale\Item\Iface Locale item object */ public function get(\Aimeos\MShop\Context\Item\Iface $context, \TYPO3\Flow\Mvc\RequestInterface $request) { if ($this->locale === null) { $params = $request->getArguments(); $site = isset($params['site']) ? $params['site'] : 'default'; $lang = isset($params['locale']) ? $params['locale'] : ''; $currency = isset($params['currency']) ? $params['currency'] : ''; $disableSites = (bool) (isset($this->settings['flow']['disableSites']) ? $this->settings['flow']['disableSites'] : true); $localeManager = \Aimeos\MShop\Locale\Manager\Factory::createManager($context); $this->locale = $localeManager->bootstrap($site, $lang, $currency, $disableSites); } return $this->locale; }
/** * Returns the fixed parameters that should be included in every URL * * @param \TYPO3\Flow\Mvc\RequestInterface $request Request object * @return array Associative list of site, language and currency if available */ protected function getFixedParams(\TYPO3\Flow\Mvc\RequestInterface $request) { $fixed = array(); $params = $request->getArguments(); if (isset($params['site'])) { $fixed['site'] = $params['site']; } if (isset($params['locale'])) { $fixed['locale'] = $params['locale']; } if (isset($params['currency'])) { $fixed['currency'] = $params['currency']; } return $fixed; }
/** * Matches a \TYPO3\Flow\Mvc\RequestInterface against the configured CSRF pattern rules and * searches for invalid csrf tokens. If this returns TRUE, the request is invalid! * * @param RequestInterface $request The request that should be matched * @return boolean TRUE if the pattern matched, FALSE otherwise * @throws AuthenticationRequiredException */ public function matchRequest(RequestInterface $request) { if (!$request instanceof ActionRequest || $request->getHttpRequest()->isMethodSafe()) { $this->systemLogger->log('CSRF: No token required, safe request', LOG_DEBUG); return false; } if ($this->authenticationManager->isAuthenticated() === false) { $this->systemLogger->log('CSRF: No token required, not authenticated', LOG_DEBUG); return false; } if ($this->securityContext->areAuthorizationChecksDisabled() === true) { $this->systemLogger->log('CSRF: No token required, authorization checks are disabled', LOG_DEBUG); return false; } $controllerClassName = $this->objectManager->getClassNameByObjectName($request->getControllerObjectName()); $actionMethodName = $request->getControllerActionName() . 'Action'; if (!$this->hasPolicyEntryForMethod($controllerClassName, $actionMethodName)) { $this->systemLogger->log(sprintf('CSRF: No token required, method %s::%s() is not restricted by a policy.', $controllerClassName, $actionMethodName), LOG_DEBUG); return false; } if ($this->reflectionService->isMethodTaggedWith($controllerClassName, $actionMethodName, 'skipcsrfprotection')) { $this->systemLogger->log(sprintf('CSRF: No token required, method %s::%s() is tagged with a "skipcsrfprotection" annotation', $controllerClassName, $actionMethodName), LOG_DEBUG); return false; } $httpRequest = $request->getHttpRequest(); if ($httpRequest->hasHeader('X-Flow-Csrftoken')) { $csrfToken = $httpRequest->getHeader('X-Flow-Csrftoken'); } else { $internalArguments = $request->getMainRequest()->getInternalArguments(); $csrfToken = isset($internalArguments['__csrfToken']) ? $internalArguments['__csrfToken'] : null; } if (empty($csrfToken)) { $this->systemLogger->log(sprintf('CSRF: token was empty but a valid token is required for %s::%s()', $controllerClassName, $actionMethodName), LOG_DEBUG); return true; } if (!$this->securityContext->hasCsrfProtectionTokens()) { throw new AuthenticationRequiredException(sprintf('CSRF: No CSRF tokens in security context, possible session timeout. A valid token is required for %s::%s()', $controllerClassName, $actionMethodName), 1317309673); } if ($this->securityContext->isCsrfProtectionTokenValid($csrfToken) === false) { $this->systemLogger->log(sprintf('CSRF: token was invalid but a valid token is required for %s::%s()', $controllerClassName, $actionMethodName), LOG_DEBUG); return true; } $this->systemLogger->log(sprintf('CSRF: Successfully verified token for %s::%s()', $controllerClassName, $actionMethodName), LOG_DEBUG); return false; }
/** * @test * @expectedException \TYPO3\Flow\Mvc\Exception\InfiniteLoopException */ public function dispatchThrowsAnInfiniteLoopExceptionIfTheRequestCouldNotBeDispachedAfter99Iterations() { $requestCallCounter = 0; $requestCallBack = function () use(&$requestCallCounter) { return $requestCallCounter++ < 101 ? FALSE : TRUE; }; $this->mockRequest->expects($this->any())->method('isDispatched')->will($this->returnCallBack($requestCallBack, '__invoke')); $this->dispatcher->dispatch($this->mockRequest, $this->mockResponse); }
/** * Matches a \TYPO3\Flow\Mvc\RequestInterface against the configured CSRF pattern rules and * searches for invalid csrf tokens. If this returns TRUE, the request is invalid! * * @param \TYPO3\Flow\Mvc\RequestInterface $request The request that should be matched * @return boolean TRUE if the pattern matched, FALSE otherwise * @throws \TYPO3\Flow\Security\Exception\AuthenticationRequiredException */ public function matchRequest(\TYPO3\Flow\Mvc\RequestInterface $request) { if (!$request instanceof ActionRequest || $request->getHttpRequest()->isMethodSafe()) { $this->systemLogger->log('No CSRF required, safe request', LOG_DEBUG); return FALSE; } if ($this->authenticationManager->isAuthenticated() === FALSE) { $this->systemLogger->log('No CSRF required, not authenticated', LOG_DEBUG); return FALSE; } if ($this->securityContext->areAuthorizationChecksDisabled() === TRUE) { $this->systemLogger->log('No CSRF required, authorization checks are disabled', LOG_DEBUG); return FALSE; } $controllerClassName = $this->objectManager->getClassNameByObjectName($request->getControllerObjectName()); $actionName = $request->getControllerActionName() . 'Action'; if (!$this->policyService->hasPolicyEntryForMethod($controllerClassName, $actionName)) { $this->systemLogger->log(sprintf('CSRF protection filter: allowed %s request without requiring CSRF token because action "%s" in controller "%s" is not restricted by a policy.', $request->getHttpRequest()->getMethod(), $actionName, $controllerClassName), LOG_NOTICE); return FALSE; } if ($this->reflectionService->isMethodTaggedWith($controllerClassName, $actionName, 'skipcsrfprotection')) { return FALSE; } $httpRequest = $request->getHttpRequest(); if ($httpRequest->hasHeader('X-Flow-Csrftoken')) { $csrfToken = $httpRequest->getHeader('X-Flow-Csrftoken'); } else { $internalArguments = $request->getMainRequest()->getInternalArguments(); $csrfToken = isset($internalArguments['__csrfToken']) ? $internalArguments['__csrfToken'] : NULL; } if (empty($csrfToken)) { $this->systemLogger->log('CSRF token was empty', LOG_DEBUG); return TRUE; } if (!$this->securityContext->hasCsrfProtectionTokens()) { throw new \TYPO3\Flow\Security\Exception\AuthenticationRequiredException('No tokens in security context, possible session timeout', 1317309673); } if ($this->securityContext->isCsrfProtectionTokenValid($csrfToken) === FALSE) { $this->systemLogger->log('CSRF token was invalid', LOG_DEBUG); return TRUE; } // the CSRF token was necessary and is valid return FALSE; }
/** * Dispatches a request to a controller * * @param \TYPO3\Flow\Mvc\RequestInterface $request The request to dispatch * @param \TYPO3\Flow\Mvc\ResponseInterface $response The response, to be modified by the controller * @return void * @throws \TYPO3\Flow\Mvc\Exception\InfiniteLoopException * @api */ public function dispatch(RequestInterface $request, ResponseInterface $response) { $dispatchLoopCount = 0; while (!$request->isDispatched()) { if ($dispatchLoopCount++ > 99) { throw new \TYPO3\Flow\Mvc\Exception\InfiniteLoopException('Could not ultimately dispatch the request after ' . $dispatchLoopCount . ' iterations.', 1217839467); } $controller = $this->resolveController($request); try { $this->emitBeforeControllerInvocation($request, $response, $controller); $controller->processRequest($request, $response); $this->emitAfterControllerInvocation($request, $response, $controller); } catch (StopActionException $exception) { $this->emitAfterControllerInvocation($request, $response, $controller); if ($exception instanceof ForwardException) { $request = $exception->getNextRequest(); } elseif ($request->isMainRequest() === FALSE) { $request = $request->getParentRequest(); } } } }
/** * Returns the locale item for the current request * * @param \MShop_Context_Item_Interface $context Context object * @param \TYPO3\Flow\Mvc\RequestInterface $request Request object * @return \MShop_Locale_Item_Interface Locale item object */ protected function getLocale(\MShop_Context_Item_Interface $context, \TYPO3\Flow\Mvc\RequestInterface $request) { if ($this->locale === null) { $params = $request->getArguments(); $site = isset($params['site']) ? $params['site'] : 'default'; $lang = isset($params['locale']) ? $params['locale'] : ''; $currency = isset($params['currency']) ? $params['currency'] : ''; $disableSites = (bool) (isset($this->settings['flow']['disableSites']) ? $this->settings['flow']['disableSites'] : false); $localeManager = \MShop_Locale_Manager_Factory::createManager($context); $this->locale = $localeManager->bootstrap($site, $lang, $currency, $disableSites); } return $this->locale; }
/** * Create a complete cache identifier for the given * request that conforms to cache identifier syntax * * @param \TYPO3\Flow\Mvc\RequestInterface $request * @return string */ protected function createCacheIdentifier($request) { $cacheIdentifiersParts = array(); do { $cacheIdentifiersParts[] = $request->getControllerPackageKey(); $cacheIdentifiersParts[] = $request->getControllerSubpackageKey(); $cacheIdentifiersParts[] = $request->getControllerName(); $cacheIdentifiersParts[] = $request->getControllerActionName(); $cacheIdentifiersParts[] = $request->getFormat(); $request = $request->getParentRequest(); } while ($request instanceof ActionRequest); return md5(implode('-', $cacheIdentifiersParts)); }
/** * Adds the argument namespace of the current request to the specified arguments. * This happens recursively iterating through the nested requests in case of a subrequest. * For example if this is executed inside a widget sub request in a plugin sub request, the result would be: * array( * 'pluginRequestNamespace' => array( * 'widgetRequestNamespace => $arguments * ) * ) * * @param array $arguments arguments * @param \TYPO3\Flow\Mvc\RequestInterface $currentRequest * @return array arguments with namespace */ protected function addNamespaceToArguments(array $arguments, \TYPO3\Flow\Mvc\RequestInterface $currentRequest) { while (!$currentRequest->isMainRequest()) { $argumentNamespace = $currentRequest->getArgumentNamespace(); if ($argumentNamespace !== '') { $arguments = array($argumentNamespace => $arguments); } $currentRequest = $currentRequest->getParentRequest(); } return $arguments; }
/** * Matches a \TYPO3\Flow\Mvc\RequestInterface against its set controller object name pattern rules * * @param \TYPO3\Flow\Mvc\RequestInterface $request The request that should be matched * @return boolean TRUE if the pattern matched, FALSE otherwise */ public function matchRequest(\TYPO3\Flow\Mvc\RequestInterface $request) { return (bool) preg_match('/^' . str_replace('\\', '\\\\', $this->controllerObjectNamePattern) . '$/', $request->getControllerObjectName()); }
/** * Finds and instantiates a controller that matches the current request. * If no controller can be found, an instance of NotFoundControllerInterface is returned. * * @param RequestInterface $request The request to dispatch * @return ControllerInterface * @throws NoSuchOptionException * @throws Controller\Exception\InvalidControllerException */ protected function resolveController(RequestInterface $request) { /** @var ActionRequest $request */ $controllerObjectName = $request->getControllerObjectName(); if ($controllerObjectName === '') { if (isset($this->settings['mvc']['notFoundController'])) { throw new NoSuchOptionException('The configuration option TYPO3.Flow:mvc:notFoundController is deprecated since Flow 2.0. Use the "renderingGroups" option of the production exception handler instead in order to render custom error messages.', 1346949795); } $exceptionMessage = 'No controller could be resolved which would match your request'; if ($request instanceof ActionRequest) { $exceptionMessage .= sprintf('. Package key: "%s", controller name: "%s"', $request->getControllerPackageKey(), $request->getControllerName()); if ($request->getControllerSubpackageKey() !== null) { $exceptionMessage .= sprintf(', SubPackage key: "%s"', $request->getControllerSubpackageKey()); } $exceptionMessage .= sprintf('. (%s %s)', $request->getHttpRequest()->getMethod(), $request->getHttpRequest()->getUri()); } throw new Controller\Exception\InvalidControllerException($exceptionMessage, 1303209195, null, $request); } $controller = $this->objectManager->get($controllerObjectName); if (!$controller instanceof ControllerInterface) { throw new Controller\Exception\InvalidControllerException('Invalid controller "' . $request->getControllerObjectName() . '". The controller must be a valid request handling controller, ' . (is_object($controller) ? get_class($controller) : gettype($controller)) . ' given.', 1202921619, null, $request); } return $controller; }
/** * Matches a \TYPO3\Flow\Mvc\RequestInterface against the set IP pattern rules * * @param RequestInterface $request The request that should be matched * @return boolean TRUE if the pattern matched, FALSE otherwise */ public function matchRequest(RequestInterface $request) { if (!$request instanceof ActionRequest) { return false; } return (bool) $this->cidrMatch($request->getHttpRequest()->getClientIpAddress(), $this->ipPattern); }
/** * Matches a \TYPO3\Flow\Mvc\RequestInterface against its set URL pattern rules * * @param \TYPO3\Flow\Mvc\RequestInterface $request The request that should be matched * @return boolean TRUE if the pattern matched, FALSE otherwise */ public function matchRequest(\TYPO3\Flow\Mvc\RequestInterface $request) { return (bool) preg_match('/^' . $this->uriPattern . '$/', $request->getHttpRequest()->getUri()->getPath()); }
/** * Adds the "url" helper to the view object * * @param \Aimeos\MW\View\Iface $view View object * @param \TYPO3\Flow\Mvc\Routing\UriBuilder $uriBuilder URL builder object * @param \TYPO3\Flow\Mvc\RequestInterface|null $request Request object * @return \Aimeos\MW\View\Iface Modified view object */ protected function addUrl(\Aimeos\MW\View\Iface $view, \TYPO3\Flow\Mvc\Routing\UriBuilder $uriBuilder, \TYPO3\Flow\Mvc\RequestInterface $request = null) { $fixed = array(); if ($request !== null) { $params = $request->getArguments(); if (isset($params['site'])) { $fixed['site'] = $params['site']; } if (isset($params['locale'])) { $fixed['locale'] = $params['locale']; } if (isset($params['currency'])) { $fixed['currency'] = $params['currency']; } } $helper = new \Aimeos\MW\View\Helper\Url\Flow($view, $uriBuilder, $fixed); $view->addHelper('url', $helper); return $view; }