/** * Extracts the WidgetContext from the given $httpRequest. * If the request contains an argument "__widgetId" the context is fetched from the session (AjaxWidgetContextHolder). * Otherwise the argument "__widgetContext" is expected to contain the serialized WidgetContext (protected by a HMAC suffix) * * @param Request $httpRequest * @return WidgetContext */ protected function extractWidgetContext(Request $httpRequest) { if ($httpRequest->hasArgument('__widgetId')) { return $this->ajaxWidgetContextHolder->get($httpRequest->getArgument('__widgetId')); } elseif ($httpRequest->hasArgument('__widgetContext')) { $serializedWidgetContextWithHmac = $httpRequest->getArgument('__widgetContext'); $serializedWidgetContext = $this->hashService->validateAndStripHmac($serializedWidgetContextWithHmac); return unserialize(base64_decode($serializedWidgetContext)); } return null; }
/** * Returns an ActionRequest which referred to this request, if any. * * The referring request is not set or determined automatically but must be * explicitly set through the corresponding internal argument "__referrer". * This mechanism is used by Flow's form and validation mechanisms. * * @return ActionRequest the referring request, or NULL if no referrer found */ public function getReferringRequest() { if ($this->referringRequest !== null) { return $this->referringRequest; } if (!isset($this->internalArguments['__referrer'])) { return null; } if (is_array($this->internalArguments['__referrer'])) { $referrerArray = $this->internalArguments['__referrer']; $referringRequest = new ActionRequest($this->getHttpRequest()); $arguments = array(); if (isset($referrerArray['arguments'])) { $serializedArgumentsWithHmac = $referrerArray['arguments']; $serializedArguments = $this->hashService->validateAndStripHmac($serializedArgumentsWithHmac); $arguments = unserialize(base64_decode($serializedArguments)); unset($referrerArray['arguments']); } $referringRequest->setArguments(Arrays::arrayMergeRecursiveOverrule($arguments, $referrerArray)); return $referringRequest; } else { $this->referringRequest = $this->internalArguments['__referrer']; } return $this->referringRequest; }
/** * @test */ public function validateAndStripHmacReturnsTheStringWithoutHmac() { $string = ' Some arbitrary string with special characters: öäüß!"§$ '; $hashedString = $this->hashService->appendHmac($string); $actualResult = $this->hashService->validateAndStripHmac($hashedString); $this->assertSame($string, $actualResult); }
/** * An advice which intercepts the original route() method if a widget AJAX request * was identified. * * If the HTTP request contains an argument hinting on an AJAX request directed * to a widget, this method will create a matching ActionRequest rather than * invoking the whole routing mechanism. * * @Flow\Around("method(TYPO3\Flow\Mvc\Routing\Router->route())") * @param \TYPO3\Flow\Aop\JoinPointInterface $joinPoint * @return \TYPO3\Flow\Mvc\ActionRequest */ public function routeAjaxWidgetRequestAdvice(JoinPointInterface $joinPoint) { $httpRequest = $joinPoint->getMethodArgument('httpRequest'); if ($httpRequest->hasArgument('__widgetId') || $httpRequest->hasArgument('__widgetContext')) { $actionRequest = $httpRequest->createActionRequest(); $widgetId = $actionRequest->getInternalArgument('__widgetId'); if ($widgetId !== NULL) { $widgetContext = $this->ajaxWidgetContextHolder->get($widgetId); } else { $serializedWidgetContextWithHmac = $actionRequest->getInternalArgument('__widgetContext'); $serializedWidgetContext = $this->hashService->validateAndStripHmac($serializedWidgetContextWithHmac); $widgetContext = unserialize($serializedWidgetContext); } $actionRequest->setArgument('__widgetContext', $widgetContext); $actionRequest->setControllerObjectName($widgetContext->getControllerObjectName()); return $actionRequest; } else { return $joinPoint->getAdviceChain()->proceed($joinPoint); } }
/** * @param ComponentContext $componentContext * @return void * @throws FileNotFoundException|AccessDeniedException|FlowException */ public function handle(ComponentContext $componentContext) { $httpRequest = $componentContext->getHttpRequest(); if (!$httpRequest->hasArgument('__protectedResource')) { return; } try { $encodedResourceData = $this->hashService->validateAndStripHmac($httpRequest->getArgument('__protectedResource')); } catch (InvalidHashException $exception) { throw new AccessDeniedException('Invalid HMAC!', 1421241393, $exception); } $tokenData = json_decode(base64_decode($encodedResourceData), TRUE); $this->verifyExpiration($tokenData); $this->verifySecurityContextHash($tokenData, $httpRequest); $resource = $this->resourceManager->getResourceBySha1($tokenData['resourceIdentifier']); if ($resource === NULL) { throw new FileNotFoundException(sprintf('Unknown resource!%sCould not find resource with identifier "%s"', chr(10), $tokenData['resourceIdentifier']), 1429621743); } // TODO there should be a better way to determine the absolute path of the resource? Resource::createTemporaryLocalCopy() is too expensive $resourcePathAndFilename = Files::concatenatePaths(array($this->options['basePath'], $tokenData['resourceIdentifier'][0], $tokenData['resourceIdentifier'][1], $tokenData['resourceIdentifier'][2], $tokenData['resourceIdentifier'][3], $tokenData['resourceIdentifier'])); if (!is_file($resourcePathAndFilename)) { throw new FileNotFoundException(sprintf('File not found!%sThe file "%s" does not exist', chr(10), $resourcePathAndFilename), 1429702284); } if (!isset($this->options['serveStrategy'])) { throw new FlowException('No "serveStrategy" configured!', 1429704107); } $fileServeStrategy = $this->objectManager->get($this->options['serveStrategy']); if (!$fileServeStrategy instanceof FileServeStrategyInterface) { throw new FlowException(sprintf('The class "%s" does not implement the FileServeStrategyInterface', get_class($fileServeStrategy)), 1429704284); } $httpResponse = $componentContext->getHttpResponse(); $httpResponse->setHeader('Content-Type', $resource->getMediaType()); $this->emitResourceServed($resource, $httpRequest); $fileServeStrategy->serve($resourcePathAndFilename, $httpResponse); $componentContext->setParameter('TYPO3\\Flow\\Http\\Component\\ComponentChain', 'cancel', TRUE); }
/** * Initialize the property mapping configuration in $controllerArguments if * the trusted properties are set inside the request. * * @param \TYPO3\Flow\Mvc\ActionRequest $request * @param \TYPO3\Flow\Mvc\Controller\Arguments $controllerArguments * @return void */ public function initializePropertyMappingConfigurationFromRequest(\TYPO3\Flow\Mvc\ActionRequest $request, \TYPO3\Flow\Mvc\Controller\Arguments $controllerArguments) { $trustedPropertiesToken = $request->getInternalArgument('__trustedProperties'); if (!is_string($trustedPropertiesToken)) { return; } $serializedTrustedProperties = $this->hashService->validateAndStripHmac($trustedPropertiesToken); $trustedProperties = unserialize($serializedTrustedProperties); foreach ($trustedProperties as $propertyName => $propertyConfiguration) { if (!$controllerArguments->hasArgument($propertyName)) { continue; } $propertyMappingConfiguration = $controllerArguments->getArgument($propertyName)->getPropertyMappingConfiguration(); $this->modifyPropertyMappingConfiguration($propertyConfiguration, $propertyMappingConfiguration); } }
/** * @return void * @internal */ protected function initializeFormStateFromRequest() { $serializedFormStateWithHmac = $this->request->getInternalArgument('__state'); if ($serializedFormStateWithHmac === NULL) { $this->formState = new FormState(); } else { $serializedFormState = $this->hashService->validateAndStripHmac($serializedFormStateWithHmac); $this->formState = unserialize(base64_decode($serializedFormState)); } }