/** * Create a processed file according to some configuration. * * @param File $file * @param array $processingConfiguration * @return string */ public function createAction(File $file, array $processingConfiguration = array()) { $processedFile = $file->process(ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, $processingConfiguration); $response = array('success' => TRUE, 'original' => $file->getUid(), 'title' => $file->getProperty('title') ? $file->getProperty('title') : $file->getName(), 'publicUrl' => $processedFile->getPublicUrl(), 'width' => $processedFile->getProperty('width'), 'height' => $processedFile->getProperty('height')); header("Content-Type: text/json"); return htmlspecialchars(json_encode($response), ENT_NOQUOTES); }
/** * Resize image and garantees a minimum size for each dimension * @param File $file * @return File|ProcessedFile */ public function createProcessedThumbnail(File $file) { $minSize = 84; $width = (int) $file->getProperty('width'); $height = (int) $file->getProperty('height'); $ratio = $width / $height; if ($width > $height) { $configuration = ['maxWidth' => ceil($minSize * $ratio), 'height' => $minSize]; } else { $configuration = ['width' => $minSize, 'maxHeight' => ceil($minSize / $ratio)]; } $file = $file->process(ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, $configuration); return $file; }
/** * renders <f:then> child if the current logged in FE user has access to the given asset * otherwise renders <f:else> child. * * @param Folder $folder * @param File $file * @return bool|string */ public function render(Folder $folder, File $file = NULL) { /** @var $checkPermissionsService \BeechIt\FalSecuredownload\Security\CheckPermissions */ $checkPermissionsService = GeneralUtility::makeInstance('BeechIt\\FalSecuredownload\\Security\\CheckPermissions'); $userFeGroups = $this->getFeUserGroups(); $access = FALSE; // check folder access if ($checkPermissionsService->checkFolderRootLineAccess($folder, $userFeGroups)) { if ($file === NULL) { $access = TRUE; } else { $feGroups = $file->getProperty('fe_groups'); if ($feGroups !== '') { $access = $checkPermissionsService->matchFeGroupsWithFeUser($feGroups, $userFeGroups); } else { $access = TRUE; } } } if ($access) { return $this->renderThenChild(); } else { return $this->renderElseChild(); } }
/** * Checks if the given file can be processed by this Extractor * * @param Resource\File $file * @return boolean */ public function canProcess(Resource\File $file) { // TODO use MIME type instead of extension // tika.jar --list-supported-types -> cache supported types // compare to file's MIME type return in_array($file->getProperty('extension'), $this->supportedFileTypes); }
/** * Main function which creates the image if needed and outputs the HTML code for the page displaying the image. * Accumulates the content in $this->content * * @return void */ public function main() { $processedImage = $this->processImage(); $imageTagMarkers = array('###publicUrl###' => htmlspecialchars($processedImage->getPublicUrl()), '###alt###' => htmlspecialchars($this->file->getProperty('alternative') ?: $this->title), '###title###' => htmlspecialchars($this->file->getProperty('title') ?: $this->title), '###width###' => $processedImage->getProperty('width'), '###height###' => $processedImage->getProperty('height')); $this->imageTag = str_replace(array_keys($imageTagMarkers), array_values($imageTagMarkers), $this->imageTag); $markerArray = array('###TITLE###' => $this->file->getProperty('title') ?: $this->title, '###IMAGE###' => $this->imageTag, '###BODY###' => $this->bodyTag); $this->content = str_replace(array_keys($markerArray), array_values($markerArray), $this->content); }
/** * Getter for file-properties * * @param string $key * * @return mixed */ public function getProperty($key) { // The uid always (!) has to come from this file and never the original file (see getOriginalFile() to get this) if ($this->isUnchanged() && $key !== 'uid') { return $this->originalFile->getProperty($key); } else { return $this->properties[$key]; } }
/** * Gets all properties, falling back to values of the parent. * * @return array */ public function getProperties() { $properties = $this->getReferenceProperties(); $keys = array_keys($properties); foreach ($this->parentFallbackProperties as $localKey => $parentKey) { if (array_key_exists($localKey, $keys) && $properties[$localKey] === NULL) { $properties[$localKey] = $this->originalFile->getProperty($parentKey); } } }
/** * Main function which creates the image if needed and outputs the HTML code for the page displaying the image. * Accumulates the content in $this->content * * @return void */ public function main() { $processedImage = $this->processImage(); $imageTagMarkers = array('###publicUrl###' => htmlspecialchars($processedImage->getPublicUrl()), '###alt###' => htmlspecialchars($this->file->getProperty('alternative') ?: $this->title), '###title###' => htmlspecialchars($this->file->getProperty('title') ?: $this->title)); $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, '###BODY###' => $this->bodyTag); $this->content = str_replace(array_keys($markerArray), array_values($markerArray), $this->content); }
/** * Check file access for given FeGroups combination * * @param \TYPO3\CMS\Core\Resource\File $file * @param bool|array $userFeGroups FALSE = no login, array() fe groups of user * @return bool */ public function checkFileAccess($file, $userFeGroups) { // all files in public storage are accessible if ($file->getStorage()->isPublic()) { return true; // check folder access } elseif ($this->checkFolderRootLineAccess($file->getParentFolder(), $userFeGroups)) { // access to folder then check file privileges if present $feGroups = $file->getProperty('fe_groups'); if ($feGroups !== '') { return $this->matchFeGroupsWithFeUser($feGroups, $userFeGroups); } return true; } return false; }
/** * Updates the index record in the database * * @param File $file * @return void */ public function update(File $file) { $updatedProperties = array_intersect($this->fields, $file->getUpdatedProperties()); $updateRow = array(); foreach ($updatedProperties as $key) { $updateRow[$key] = $file->getProperty($key); } if (count($updateRow) > 0) { $updateRow['tstamp'] = time(); $this->getDatabaseConnection()->exec_UPDATEquery($this->table, $this->getWhereClauseForFile($file), $updateRow); $this->updateRefIndex($file->getUid()); $this->emitRecordUpdatedSignal(array_intersect_key($file->getProperties(), array_flip($this->fields))); } }
/** * Checks if the given file can be processed by this Extractor * * @param File $file * @return boolean */ public function canProcess(File $file) { return in_array($file->getProperty('extension'), $this->supportedFileTypes); }
/** * The actual processing TASK * Should return an array with database properties for sys_file_metadata to write * * @param File $file * @param array $previousExtractedData optional, contains the array of already extracted data * @return array */ public function extractMetaData(File $file, array $previousExtractedData = array()) { $metadata = array(); $title = $file->getProperty('title'); if (empty($title)) { $metadata = array('title' => $this->guessTitle($file->getName())); } return $metadata; }
/** * Insert a plain image * * @param \TYPO3\CMS\Core\Resource\File $fileObject: the image file * @param string $altText: text for the alt attribute of the image * @param string $titleText: text for the title attribute of the image * @param string $additionalParams: text representing more HTML attributes to be added on the img tag * @return void */ public function insertPlainImage(Resource\File $fileObject, $altText = '', $titleText = '', $additionalParams = '') { $width = $fileObject->getProperty('width'); $height = $fileObject->getProperty('height'); if (!$width || !$height) { $filePath = $fileObject->getForLocalProcessing(FALSE); $imageInfo = @getimagesize($filePath); $width = $imageInfo[0]; $height = $imageInfo[1]; } $imageUrl = $fileObject->getPublicUrl(); // If file is local, make the url absolute if (substr($imageUrl, 0, 4) !== 'http') { $imageUrl = $this->siteURL . $imageUrl; } $this->imageInsertJS($imageUrl, $width, $height, $altText, $titleText, $additionalParams); }
/** * Adds a files content from a sys file record to the export memory * * @param \TYPO3\CMS\Core\Resource\File $file * @return void */ public function export_addSysFile(\TYPO3\CMS\Core\Resource\File $file) { if ($file->getProperty('size') >= $this->maxFileSize) { $this->error('File ' . $file->getPublicUrl() . ' was larger (' . GeneralUtility::formatSize($file->getProperty('size')) . ') than the maxFileSize (' . GeneralUtility::formatSize($this->maxFileSize) . ')! Skipping.'); return; } try { $fileContent = $file->getContents(); } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFileAccessPermissionsException $e) { $this->error('File ' . $file->getPublicUrl() . ': ' . $e->getMessage()); return; } catch (\TYPO3\CMS\Core\Resource\Exception\IllegalFileExtensionException $e) { $this->error('File ' . $file->getPublicUrl() . ': ' . $e->getMessage()); return; } $fileUid = $file->getUid(); $fileInfo = $file->getStorage()->getFileInfo($file); // we sadly have to cast it to string here, because the size property is also returning a string $fileSize = (string) $fileInfo['size']; if ($fileSize !== $file->getProperty('size')) { $this->error('File size of ' . $file->getCombinedIdentifier() . ' is not up-to-date in index! File added with current size.'); $this->dat['records']['sys_file:' . $fileUid]['data']['size'] = $fileSize; } $fileSha1 = $file->getStorage()->hashFile($file, 'sha1'); if ($fileSha1 !== $file->getProperty('sha1')) { $this->error('File sha1 hash of ' . $file->getCombinedIdentifier() . ' is not up-to-date in index! File added on current sha1.'); $this->dat['records']['sys_file:' . $fileUid]['data']['sha1'] = $fileSha1; } $fileRec = array(); $fileRec['filesize'] = $fileSize; $fileRec['filename'] = $file->getProperty('name'); $fileRec['filemtime'] = $file->getProperty('modification_date'); // build unique id based on the storage and the file identifier $fileId = md5($file->getStorage()->getUid() . ':' . $file->getProperty('identifier_hash')); // Setting this data in the header $this->dat['header']['files_fal'][$fileId] = $fileRec; // ... and finally add the heavy stuff: $fileRec['content'] = $fileContent; $fileRec['content_sha1'] = $fileSha1; $this->dat['files_fal'][$fileId] = $fileRec; }
/** * Generates a new file name based on an existing file and the format of the new name * * @param \TYPO3\CMS\Core\Resource\File $file original file * @param string $filenameFormat filename format with markers * @return string new file name */ protected function generateFilename(\TYPO3\CMS\Core\Resource\File $file, $filenameFormat) { return $this->cObj->substituteMarkerArray($filenameFormat, array('###NAME###' => basename($file->getProperty('name'), $file->getProperty('extension') ? '.' . $file->getProperty('extension') : ''), '###EXTENSION###' => $file->getProperty('extension'), '###UID###' => $file->getUid(), '###SHA1###' => $file->getProperty('sha1'), '###HASH###' => $file->getProperty('identifier_hash'), '###UNIQUE###' => md5(uniqid($file->getProperty('name'), true)))); }
/** * Creates and returns a TypoScript "imgResource". * The value ($file) can either be a file reference (TypoScript resource) or the string "GIFBUILDER". * In the first case a current image is returned, possibly scaled down or otherwise processed. * In the latter case a GIFBUILDER image is returned; This means an image is made by TYPO3 from layers of elements as GIFBUILDER defines. * In the function IMG_RESOURCE() this function is called like $this->getImgResource($conf['file'], $conf['file.']); * * Structure of the returned info array: * 0 => width * 1 => height * 2 => file extension * 3 => file name * origFile => original file name * origFile_mtime => original file mtime * -- only available if processed via FAL: -- * originalFile => original file object * processedFile => processed file object * fileCacheHash => checksum of processed file * * @param string|File|FileReference $file A "imgResource" TypoScript data type. Either a TypoScript file resource, a file or a file reference object or the string GIFBUILDER. See description above. * @param array $fileArray TypoScript properties for the imgResource type * @return array|NULL Returns info-array * @see IMG_RESOURCE(), cImage(), \TYPO3\CMS\Frontend\Imaging\GifBuilder */ public function getImgResource($file, $fileArray) { if (empty($file) && empty($fileArray)) { return null; } if (!is_array($fileArray)) { $fileArray = (array) $fileArray; } $imageResource = null; $tsfe = $this->getTypoScriptFrontendController(); if ($file === 'GIFBUILDER') { /** @var GifBuilder $gifCreator */ $gifCreator = GeneralUtility::makeInstance(GifBuilder::class); $gifCreator->init(); $theImage = ''; if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib']) { $gifCreator->start($fileArray, $this->data); $theImage = $gifCreator->gifBuild(); } $imageResource = $gifCreator->getImageDimensions($theImage); $imageResource['origFile'] = $theImage; } else { if ($file instanceof File) { $fileObject = $file; } elseif ($file instanceof FileReference) { $fileObject = $file->getOriginalFile(); if (!isset($fileArray['crop'])) { $fileArray['crop'] = $file->getProperty('crop'); } } else { try { if ($fileArray['import.']) { $importedFile = trim($this->stdWrap('', $fileArray['import.'])); if (!empty($importedFile)) { $file = $importedFile; } } if (MathUtility::canBeInterpretedAsInteger($file)) { $treatIdAsReference = isset($fileArray['treatIdAsReference.']) ? $this->stdWrap($fileArray['treatIdAsReference'], $fileArray['treatIdAsReference.']) : $fileArray['treatIdAsReference']; if (!empty($treatIdAsReference)) { $fileReference = $this->getResourceFactory()->getFileReferenceObject($file); $fileObject = $fileReference->getOriginalFile(); if (!isset($fileArray['crop'])) { $fileArray['crop'] = $fileReference->getProperty('crop'); } } else { $fileObject = $this->getResourceFactory()->getFileObject($file); } } elseif (preg_match('/^(0|[1-9][0-9]*):/', $file)) { // combined identifier $fileObject = $this->getResourceFactory()->retrieveFileOrFolderObject($file); } else { if (isset($importedFile) && !empty($importedFile) && !empty($fileArray['import'])) { $file = $fileArray['import'] . $file; } $fileObject = $this->getResourceFactory()->retrieveFileOrFolderObject($file); } } catch (Exception $exception) { /** @var \TYPO3\CMS\Core\Log\Logger $logger */ $logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__); $logger->warning('The image "' . $file . '" could not be found and won\'t be included in frontend output'); return null; } } if ($fileObject instanceof File) { $processingConfiguration = array(); $processingConfiguration['width'] = isset($fileArray['width.']) ? $this->stdWrap($fileArray['width'], $fileArray['width.']) : $fileArray['width']; $processingConfiguration['height'] = isset($fileArray['height.']) ? $this->stdWrap($fileArray['height'], $fileArray['height.']) : $fileArray['height']; $processingConfiguration['fileExtension'] = isset($fileArray['ext.']) ? $this->stdWrap($fileArray['ext'], $fileArray['ext.']) : $fileArray['ext']; $processingConfiguration['maxWidth'] = isset($fileArray['maxW.']) ? (int) $this->stdWrap($fileArray['maxW'], $fileArray['maxW.']) : (int) $fileArray['maxW']; $processingConfiguration['maxHeight'] = isset($fileArray['maxH.']) ? (int) $this->stdWrap($fileArray['maxH'], $fileArray['maxH.']) : (int) $fileArray['maxH']; $processingConfiguration['minWidth'] = isset($fileArray['minW.']) ? (int) $this->stdWrap($fileArray['minW'], $fileArray['minW.']) : (int) $fileArray['minW']; $processingConfiguration['minHeight'] = isset($fileArray['minH.']) ? (int) $this->stdWrap($fileArray['minH'], $fileArray['minH.']) : (int) $fileArray['minH']; $processingConfiguration['noScale'] = isset($fileArray['noScale.']) ? $this->stdWrap($fileArray['noScale'], $fileArray['noScale.']) : $fileArray['noScale']; $processingConfiguration['additionalParameters'] = isset($fileArray['params.']) ? $this->stdWrap($fileArray['params'], $fileArray['params.']) : $fileArray['params']; $processingConfiguration['frame'] = isset($fileArray['frame.']) ? (int) $this->stdWrap($fileArray['frame'], $fileArray['frame.']) : (int) $fileArray['frame']; $processingConfiguration['crop'] = isset($fileArray['crop.']) ? $this->stdWrap($fileArray['crop'], $fileArray['crop.']) : (isset($fileArray['crop']) ? $fileArray['crop'] : null); // Possibility to cancel/force profile extraction // see $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_stripProfileCommand'] if (isset($fileArray['stripProfile'])) { $processingConfiguration['stripProfile'] = $fileArray['stripProfile']; } // Check if we can handle this type of file for editing if (GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileObject->getExtension())) { $maskArray = $fileArray['m.']; // Must render mask images and include in hash-calculating // - otherwise we cannot be sure the filename is unique for the setup! if (is_array($maskArray)) { $mask = $this->getImgResource($maskArray['mask'], $maskArray['mask.']); $bgImg = $this->getImgResource($maskArray['bgImg'], $maskArray['bgImg.']); $bottomImg = $this->getImgResource($maskArray['bottomImg'], $maskArray['bottomImg.']); $bottomImg_mask = $this->getImgResource($maskArray['bottomImg_mask'], $maskArray['bottomImg_mask.']); $processingConfiguration['maskImages']['maskImage'] = $mask['processedFile']; $processingConfiguration['maskImages']['backgroundImage'] = $bgImg['processedFile']; $processingConfiguration['maskImages']['maskBottomImage'] = $bottomImg['processedFile']; $processingConfiguration['maskImages']['maskBottomImageMask'] = $bottomImg_mask['processedFile']; } $processedFileObject = $fileObject->process(ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, $processingConfiguration); $hash = $processedFileObject->calculateChecksum(); // store info in the TSFE template cache (kept for backwards compatibility) if ($processedFileObject->isProcessed() && !isset($tsfe->tmpl->fileCache[$hash])) { $tsfe->tmpl->fileCache[$hash] = array(0 => $processedFileObject->getProperty('width'), 1 => $processedFileObject->getProperty('height'), 2 => $processedFileObject->getExtension(), 3 => $processedFileObject->getPublicUrl(), 'origFile' => $fileObject->getPublicUrl(), 'origFile_mtime' => $fileObject->getModificationTime(), 'originalFile' => $fileObject, 'processedFile' => $processedFileObject, 'fileCacheHash' => $hash); } $imageResource = $tsfe->tmpl->fileCache[$hash]; } } } // If image was processed by GIFBUILDER: // ($imageResource indicates that it was processed the regular way) if (!isset($imageResource)) { $theImage = $tsfe->tmpl->getFileName($file); if ($theImage) { $gifCreator = GeneralUtility::makeInstance(GifBuilder::class); /** @var $gifCreator GifBuilder */ $gifCreator->init(); $info = $gifCreator->imageMagickConvert($theImage, 'WEB'); $info['origFile'] = $theImage; // This is needed by \TYPO3\CMS\Frontend\Imaging\GifBuilder, ln 100ff in order for the setup-array to create a unique filename hash. $info['origFile_mtime'] = @filemtime($theImage); $imageResource = $info; } } // Hook 'getImgResource': Post-processing of image resources if (isset($imageResource)) { /** @var ContentObjectGetImageResourceHookInterface $hookObject */ foreach ($this->getGetImgResourceHookObjects() as $hookObject) { $imageResource = $hookObject->getImgResourcePostProcess($file, (array) $fileArray, $imageResource, $this); } } return $imageResource; }
/** * Adds a files content from a sys file record to the export memory * * @param File $file * @return void */ public function export_addSysFile(File $file) { if ($file->getProperty('size') >= $this->maxFileSize) { $this->error('File ' . $file->getPublicUrl() . ' was larger (' . GeneralUtility::formatSize($file->getProperty('size')) . ') than the maxFileSize (' . GeneralUtility::formatSize($this->maxFileSize) . ')! Skipping.'); return; } $fileContent = ''; try { if (!$this->saveFilesOutsideExportFile) { $fileContent = $file->getContents(); } else { $file->checkActionPermission('read'); } } catch (\Exception $e) { $this->error('Error when trying to add file ' . $file->getCombinedIdentifier() . ': ' . $e->getMessage()); return; } $fileUid = $file->getUid(); $fileInfo = $file->getStorage()->getFileInfo($file); // we sadly have to cast it to string here, because the size property is also returning a string $fileSize = (string) $fileInfo['size']; if ($fileSize !== $file->getProperty('size')) { $this->error('File size of ' . $file->getCombinedIdentifier() . ' is not up-to-date in index! File added with current size.'); $this->dat['records']['sys_file:' . $fileUid]['data']['size'] = $fileSize; } $fileSha1 = $file->getStorage()->hashFile($file, 'sha1'); if ($fileSha1 !== $file->getProperty('sha1')) { $this->error('File sha1 hash of ' . $file->getCombinedIdentifier() . ' is not up-to-date in index! File added on current sha1.'); $this->dat['records']['sys_file:' . $fileUid]['data']['sha1'] = $fileSha1; } $fileRec = array(); $fileRec['filesize'] = $fileSize; $fileRec['filename'] = $file->getProperty('name'); $fileRec['filemtime'] = $file->getProperty('modification_date'); // build unique id based on the storage and the file identifier $fileId = md5($file->getStorage()->getUid() . ':' . $file->getProperty('identifier_hash')); // Setting this data in the header $this->dat['header']['files_fal'][$fileId] = $fileRec; if (!$this->saveFilesOutsideExportFile) { // ... and finally add the heavy stuff: $fileRec['content'] = $fileContent; } else { GeneralUtility::upload_copy_move($file->getForLocalProcessing(false), $this->getTemporaryFilesPathForExport() . $file->getProperty('sha1')); } $fileRec['content_sha1'] = $fileSha1; $this->dat['files_fal'][$fileId] = $fileRec; }
/** * Check if file is marked as missing by indexer * * @return bool */ public function isMissing() { return (bool) $this->originalFile->getProperty('missing'); }