/**
  * @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);
 }
 /**
  * @param string $value
  * @throws Exception
  * @throws \TYPO3\Flow\Resource\Exception
  * @throws \TYPO3\Flow\Utility\Exception
  */
 protected function initializeValue($value)
 {
     if (!is_array($value)) {
         throw new Exception('Value must be an array, with source URI (sourceUri) and filename (filename)', 1425981082);
     }
     if (!isset($value['sourceUri'])) {
         throw new Exception('Missing source URI', 1425981083);
     }
     $sourceUri = trim($value['sourceUri']);
     if (!isset($value['filename'])) {
         throw new Exception('Missing filename URI', 1425981084);
     }
     $filename = trim($value['filename']);
     $overrideFilename = isset($value['overrideFilename']) ? trim($value['overrideFilename']) : $filename;
     if (!isset($this->options['downloadDirectory'])) {
         throw new Exception('Missing download directory data type option', 1425981085);
     }
     Files::createDirectoryRecursively($this->options['downloadDirectory']);
     $temporaryFileAndPathname = trim($this->options['downloadDirectory'] . $filename);
     $this->download($sourceUri, $temporaryFileAndPathname);
     $sha1Hash = sha1_file($temporaryFileAndPathname);
     # Try to add file extenstion if missing
     if (!$this->downloadCache->has($sha1Hash)) {
         $fileExtension = pathinfo($temporaryFileAndPathname, PATHINFO_EXTENSION);
         if (trim($fileExtension) === '') {
             $mimeTypeGuesser = new MimeTypeGuesser();
             $mimeType = $mimeTypeGuesser->guess($temporaryFileAndPathname);
             $this->logger->log(sprintf('Try to guess mime type for "%s" (%s), result: %s', $sourceUri, $filename, $mimeType), LOG_DEBUG);
             $fileExtension = MediaTypes::getFilenameExtensionFromMediaType($mimeType);
             if ($fileExtension !== '') {
                 $oldTemporaryDestination = $temporaryFileAndPathname;
                 $temporaryDestination = $temporaryFileAndPathname . '.' . $fileExtension;
                 copy($oldTemporaryDestination, $temporaryDestination);
                 $this->logger->log(sprintf('Rename "%s" to "%s"', $oldTemporaryDestination, $temporaryDestination), LOG_DEBUG);
             }
         }
     }
     $resource = $this->resourceManager->getResourceBySha1($sha1Hash);
     if ($resource === NULL) {
         $resource = $this->resourceManager->importResource($temporaryFileAndPathname);
         if ($filename !== $overrideFilename) {
             $resource->setFilename($overrideFilename);
         }
     }
     $this->temporaryFileAndPathname = $temporaryFileAndPathname;
     $this->downloadCache->set($sha1Hash, ['sha1Hash' => $sha1Hash, 'filename' => $filename, 'sourceUri' => $sourceUri, 'temporaryFileAndPathname' => $temporaryFileAndPathname]);
     $this->value = $resource;
 }
 /**
  * @param array $source
  * @param PropertyMappingConfigurationInterface $configuration
  * @return Resource|Error
  * @throws Exception
  * @throws InvalidPropertyMappingConfigurationException
  */
 protected function handleHashAndData(array $source, PropertyMappingConfigurationInterface $configuration = null)
 {
     $hash = null;
     $resource = false;
     $givenResourceIdentity = null;
     if (isset($source['__identity'])) {
         $givenResourceIdentity = $source['__identity'];
         unset($source['__identity']);
         $resource = $this->resourceRepository->findByIdentifier($givenResourceIdentity);
         if ($resource instanceof Resource) {
             return $resource;
         }
         if ($configuration->getConfigurationValue(\TYPO3\Flow\Resource\ResourceTypeConverter::class, self::CONFIGURATION_IDENTITY_CREATION_ALLOWED) !== true) {
             throw new InvalidPropertyMappingConfigurationException('Creation of resource objects with identity not allowed. To enable this, you need to set the PropertyMappingConfiguration Value "CONFIGURATION_IDENTITY_CREATION_ALLOWED" to TRUE');
         }
     }
     if (isset($source['hash']) && preg_match('/[0-9a-f]{40}/', $source['hash'])) {
         $hash = $source['hash'];
     }
     if ($hash !== null && count($source) === 1) {
         $resource = $this->resourceManager->getResourceBySha1($hash);
     }
     if ($resource === null) {
         $collectionName = $this->getCollectionName($source, $configuration);
         if (isset($source['data'])) {
             $resource = $this->resourceManager->importResourceFromContent($source['data'], $source['filename'], $collectionName, $givenResourceIdentity);
         } elseif ($hash !== null) {
             $resource = $this->resourceManager->importResource($configuration->getConfigurationValue(\TYPO3\Flow\Resource\ResourceTypeConverter::class, self::CONFIGURATION_RESOURCE_LOAD_PATH) . '/' . $hash, $collectionName, $givenResourceIdentity);
             if (is_array($source) && isset($source['filename'])) {
                 $resource->setFilename($source['filename']);
             }
         }
     }
     if ($resource instanceof Resource) {
         return $resource;
     } else {
         return new Error('The resource manager could not create a Resource instance.', 1404312901);
     }
 }
 /**
  * Evaluates the absolute path and filename of the resource file specified
  * by the given path.
  *
  * @param string $requestedPath
  * @param boolean $checkForExistence Whether a (non-hash) path should be checked for existence before being returned
  * @return mixed The full path and filename or FALSE if the file doesn't exist
  * @throws \InvalidArgumentException|Exception
  */
 protected function evaluateResourcePath($requestedPath, $checkForExistence = true)
 {
     if (substr($requestedPath, 0, strlen(self::SCHEME)) !== self::SCHEME) {
         throw new \InvalidArgumentException('The ' . __CLASS__ . ' only supports the \'' . self::SCHEME . '\' scheme.', 1256052544);
     }
     $uriParts = Functions::parse_url($requestedPath);
     if (!is_array($uriParts) || !isset($uriParts['host'])) {
         return false;
     }
     if (preg_match('/^[0-9a-f]{40}$/i', $uriParts['host']) === 1) {
         $resource = $this->resourceManager->getResourceBySha1($uriParts['host']);
         return $this->resourceManager->getStreamByResource($resource);
     }
     if (!$this->packageManager->isPackageAvailable($uriParts['host'])) {
         throw new Exception(sprintf('Invalid resource URI "%s": Package "%s" is not available.', $requestedPath, $uriParts['host']), 1309269952);
     }
     $package = $this->packageManager->getPackage($uriParts['host']);
     $resourceUri = Files::concatenatePaths(array($package->getResourcesPath(), $uriParts['path']));
     if ($checkForExistence === false || file_exists($resourceUri)) {
         return $resourceUri;
     }
     return false;
 }