/** * Create a flash message for a file that is marked as missing * * @param AbstractFile $file * @return FlashMessage */ public static function getFlashMessageForMissingFile(AbstractFile $file) { /** @var LanguageService $lang */ $lang = $GLOBALS['LANG']; /** @var FlashMessage $flashMessage */ $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $lang->sL('LLL:EXT:lang/locallang_core.xlf:warning.file_missing_text') . ' <abbr title="' . htmlspecialchars($file->getStorage()->getName() . ' :: ' . $file->getIdentifier()) . '">' . htmlspecialchars($file->getName()) . '</abbr>', $lang->sL('LLL:EXT:lang/locallang_core.xlf:warning.file_missing'), FlashMessage::ERROR); return $flashMessage; }
/** * Main function, redering the actual content of the editing page * * @return void */ public function main() { $this->getButtons(); // Hook before compiling the output if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['preOutputProcessingHook'])) { $preOutputProcessingHook =& $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['preOutputProcessingHook']; if (is_array($preOutputProcessingHook)) { $hookParameters = array('content' => &$this->content, 'target' => &$this->target); foreach ($preOutputProcessingHook as $hookFunction) { GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this); } } } $pageContent = '<form action="' . htmlspecialchars(BackendUtility::getModuleUrl('tce_file')) . '" method="post" id="EditFileController" name="editform">'; $pageContent .= '<h1>' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:file_edit.php.pagetitle') . ' ' . htmlspecialchars($this->fileObject->getName()) . '</h1>'; $code = ''; $extList = $GLOBALS['TYPO3_CONF_VARS']['SYS']['textfile_ext']; try { if (!$extList || !GeneralUtility::inList($extList, $this->fileObject->getExtension())) { throw new \Exception('Files with that extension are not editable.'); } // Read file content to edit: $fileContent = $this->fileObject->getContents(); // Making the formfields $hValue = BackendUtility::getModuleUrl('file_edit', array('target' => $this->origTarget, 'returnUrl' => $this->returnUrl)); $code .= ' <div id="c-edit"> <textarea rows="30" name="file[editfile][0][data]" wrap="off" class="form-control text-monospace t3js-enable-tab">' . htmlspecialchars($fileContent) . '</textarea> <input type="hidden" name="file[editfile][0][target]" value="' . $this->fileObject->getUid() . '" /> <input type="hidden" name="redirect" value="' . htmlspecialchars($hValue) . '" /> </div> <br />'; } catch (\Exception $e) { $code .= sprintf($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:file_edit.php.coundNot'), $extList); } // Ending of section and outputting editing form: $pageContent .= $code; // Hook after compiling the output if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['postOutputProcessingHook'])) { $postOutputProcessingHook =& $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['postOutputProcessingHook']; if (is_array($postOutputProcessingHook)) { $hookParameters = array('pageContent' => &$pageContent, 'target' => &$this->target); foreach ($postOutputProcessingHook as $hookFunction) { GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this); } } } $pageContent .= '</form>'; $this->content = $pageContent; $this->moduleTemplate->setContent($this->content); }
/** * Updates the properties of a file object with some that are freshly * fetched from the driver. * * @param \TYPO3\CMS\Core\Resource\AbstractFile $file * @param string $identifier The identifier of the file. If set, this will overwrite the file object's identifier (use e.g. after moving a file) * @param \TYPO3\CMS\Core\Resource\ResourceStorage $storage * @return void */ protected function updateFile(\TYPO3\CMS\Core\Resource\AbstractFile $file, $identifier = '', $storage = NULL) { if ($identifier === '') { $identifier = $file->getIdentifier(); } $fileInfo = $this->driver->getFileInfoByIdentifier($identifier); // TODO extend mapping $newProperties = array('storage' => $fileInfo['storage'], 'identifier' => $fileInfo['identifier'], 'tstamp' => $fileInfo['mtime'], 'crdate' => $fileInfo['ctime'], 'mime_type' => $fileInfo['mimetype'], 'size' => $fileInfo['size'], 'name' => $fileInfo['name']); if ($storage !== NULL) { $newProperties['storage'] = $storage->getUid(); } $file->updateProperties($newProperties); /** @var $fileRepository \TYPO3\CMS\Core\Resource\FileRepository */ $fileRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\FileRepository'); $fileRepository->update($file); }
/** * Main function, redering the actual content of the editing page * * @return void */ public function main() { $docHeaderButtons = $this->getButtons(); $this->content = $this->doc->startPage($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:file_edit.php.pagetitle')); // Hook before compiling the output if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['preOutputProcessingHook'])) { $preOutputProcessingHook =& $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['preOutputProcessingHook']; if (is_array($preOutputProcessingHook)) { $hookParameters = array('content' => &$this->content, 'target' => &$this->target); foreach ($preOutputProcessingHook as $hookFunction) { GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this); } } } $pageContent = $this->doc->header($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:file_edit.php.pagetitle') . ' ' . htmlspecialchars($this->fileObject->getName())); $pageContent .= $this->doc->spacer(2); $code = ''; $extList = $GLOBALS['TYPO3_CONF_VARS']['SYS']['textfile_ext']; try { if (!$extList || !GeneralUtility::inList($extList, $this->fileObject->getExtension())) { throw new \Exception('Files with that extension are not editable.'); } // Read file content to edit: $fileContent = $this->fileObject->getContents(); // Making the formfields $hValue = BackendUtility::getModuleUrl('file_edit', array('target' => $this->origTarget, 'returnUrl' => $this->returnUrl)); // Edit textarea: $code .= ' <div id="c-edit"> <textarea rows="30" name="file[editfile][0][data]" wrap="off" ' . $this->doc->formWidth(48, TRUE, 'width:98%;height:80%') . ' class="text-monospace t3js-enable-tab">' . GeneralUtility::formatForTextarea($fileContent) . '</textarea> <input type="hidden" name="file[editfile][0][target]" value="' . $this->fileObject->getUid() . '" /> <input type="hidden" name="redirect" value="' . htmlspecialchars($hValue) . '" /> ' . \TYPO3\CMS\Backend\Form\FormEngine::getHiddenTokenField('tceAction') . ' </div> <br />'; // Make shortcut: if ($this->getBackendUser()->mayMakeShortcut()) { $docHeaderButtons['shortcut'] = $this->doc->makeShortcutIcon('target', '', 'file_edit', 1); } else { $docHeaderButtons['shortcut'] = ''; } } catch (\Exception $e) { $code .= sprintf($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:file_edit.php.coundNot'), $extList); } // Ending of section and outputting editing form: $pageContent .= $this->doc->sectionEnd(); $pageContent .= $code; // Hook after compiling the output if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['postOutputProcessingHook'])) { $postOutputProcessingHook =& $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['postOutputProcessingHook']; if (is_array($postOutputProcessingHook)) { $hookParameters = array('pageContent' => &$pageContent, 'target' => &$this->target); foreach ($postOutputProcessingHook as $hookFunction) { GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this); } } } // Add the HTML as a section: $markerArray = array('CSH' => $docHeaderButtons['csh'], 'FUNC_MENU' => '', 'BUTTONS' => $docHeaderButtons, 'PATH' => $this->title, 'CONTENT' => $pageContent); $this->content .= $this->doc->moduleBody(array(), $docHeaderButtons, $markerArray); $this->content .= $this->doc->endPage(); $this->content = $this->doc->insertStylesAndJS($this->content); }
/** * Create a flash message for a file that is marked as missing * * @param \TYPO3\CMS\Core\Resource\AbstractFile $file * @return \TYPO3\CMS\Core\Messaging\FlashMessage */ public static function getFlashMessageForMissingFile(\TYPO3\CMS\Core\Resource\AbstractFile $file) { /** @var \TYPO3\CMS\Core\Messaging\FlashMessage $flashMessage */ $flashMessage = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:warning.file_missing_text') . ' <abbr title="' . htmlspecialchars($file->getStorage()->getName() . ' :: ' . $file->getIdentifier()) . '">' . htmlspecialchars($file->getName()) . '</abbr>', $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:warning.file_missing'), \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR); return $flashMessage; }
/** * Adds a file from the local server hard disk to a given path in TYPO3s virtual file system. * * This assumes that the local file exists, so no further check is done here! * * @param string $localFilePath * @param \TYPO3\CMS\Core\Resource\Folder $targetFolder * @param string $fileName The name to add the file under * @param \TYPO3\CMS\Core\Resource\AbstractFile $updateFileObject File object to update (instead of creating a new object). With this parameter, this function can be used to "populate" a dummy file object with a real file underneath. * @todo \TYPO3\CMS\Core\Resource\File $updateFileObject should be \TYPO3\CMS\Core\Resource\FileInterface, but indexer logic is only in \TYPO3\CMS\Core\Resource\File * @return \TYPO3\CMS\Core\Resource\FileInterface */ public function addFile($localFilePath, \TYPO3\CMS\Core\Resource\Folder $targetFolder, $fileName, \TYPO3\CMS\Core\Resource\AbstractFile $updateFileObject = NULL) { // as for the "virtual storage" for backwards-compatibility, this check always fails, as the file probably lies under PATH_site // thus, it is not checked here if (\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($localFilePath, $this->absoluteBasePath) && $this->storage->getUid() > 0) { throw new \InvalidArgumentException('Cannot add a file that is already part of this storage.', 1314778269); } $relativeTargetPath = ltrim($targetFolder->getIdentifier(), '/'); $relativeTargetPath .= $fileName ? $fileName : basename($localFilePath); $targetPath = $this->absoluteBasePath . $relativeTargetPath; if (is_uploaded_file($localFilePath)) { $moveResult = move_uploaded_file($localFilePath, $targetPath); } else { $moveResult = rename($localFilePath, $targetPath); } if ($moveResult !== TRUE) { throw new \RuntimeException('Moving file ' . $localFilePath . ' to ' . $targetPath . ' failed.', 1314803096); } clearstatcache(); // Change the permissions of the file \TYPO3\CMS\Core\Utility\GeneralUtility::fixPermissions($targetPath); $fileInfo = $this->getFileInfoByIdentifier($relativeTargetPath); if ($updateFileObject) { $updateFileObject->updateProperties($fileInfo); return $updateFileObject; } else { $fileObject = $this->getFileObject($fileInfo); return $fileObject; } }
/** * Delete processed file * * @param bool $force * @return bool */ public function delete($force = false) { if (!$force && $this->isUnchanged()) { return false; } // Only delete file when original isn't used if (!$this->usesOriginalFile()) { return parent::delete(); } else { return true; } }
/** * @param $key * @internal Only for use in Repositories and indexer * @return mixed */ public function _getPropertyRaw($key) { return parent::getProperty($key); }
/** * Convert PNG image using pngquant command. * * @param AbstractFile $file */ public function convertPngImage(AbstractFile $file) { try { if (self::EXTENSION_PNG !== $file->getExtension()) { return; } // Ignore processed file which uses original file if ($file instanceof ProcessedFile && $file->usesOriginalFile()) { $this->logger->debug('Do not convert processed file identical with its original file', array('file' => $inputFilePath)); return; } // Set input/output files for pngquant command // Input file is the the specified file we want to quantize // Output file is a temporary file in typo3temp directory $inputFilePath = PATH_site . $file->getPublicUrl(); $outputFilePath = GeneralUtility::tempnam('sg_pngquant_', '.' . self::EXTENSION_PNG); // Build command line $cmd = $this->buildCommand($inputFilePath, $outputFilePath); $result = CommandUtility::exec($cmd, $output, $returnValue); if (0 === $returnValue) { // Replace content if ($file instanceof ProcessedFile) { // For processed file, only convert real processed file (i.e. different than their original file) // Temporary file is automatically removed when updating a processed file $this->logger->debug('Update processed file', array('cmd' => $cmd)); $file->updateWithLocalFile($outputFilePath); } elseif (!$this->confArray['keepOriginal']) { // Convert original files according to extension configuration // After conversion the temporary file is removed $this->logger->debug('Update original file', array('cmd' => $cmd)); $contents = @file_get_contents($outputFilePath); $file->setContents($contents); } } else { $this->logger->error('Convert image', array('cmd' => $cmd, 'result' => $result, 'output' => $output, 'returnValue' => $returnValue)); } } catch (\RuntimeException $e) { $this->logger->error($e->getMessage()); } // Remove temporary file, if exists if (file_exists($outputFilePath)) { $this->removeTemporaryFile($outputFilePath); } }
/** * Retrieve data from a file reference * * @param \TYPO3\CMS\Core\Resource\ResourceInterface|Folder|\TYPO3\CMS\Core\Resource\AbstractFile $originalResource * @return array */ protected function transformFileReference($originalResource) { static $depth = 0; if ($originalResource instanceof AbstractFileFolder) { if (++$depth > 10) { throw new \RuntimeException('Max nesting level'); } $result = $this->transformFileReference($originalResource->getOriginalResource()); $depth--; return $result; } try { if ($originalResource instanceof Folder) { $filesInFolder = array(); foreach ($originalResource->getFiles() as $currentFile) { $filesInFolder[] = $this->transformFileReference($currentFile); } return $filesInFolder; } if ($originalResource instanceof FileReference) { // This would expose all data // return $originalResource->getProperties(); list($title, $description) = $this->getTitleAndDescription($originalResource); return array('name' => $originalResource->getName(), 'mimeType' => $originalResource->getMimeType(), 'url' => $originalResource->getPublicUrl(), 'size' => $originalResource->getSize(), 'title' => $title, 'description' => $description); } if ($originalResource instanceof FileInterface) { return array('name' => $originalResource->getName(), 'mimeType' => $originalResource->getMimeType(), 'url' => $originalResource->getPublicUrl(), 'size' => $originalResource->getSize()); } return array('name' => $originalResource->getName()); } catch (\RuntimeException $exception) { return array(); } }
/** * Saves the modified content to the database and updates the sys_refindex accordingly. * * @param string $modifiedText Original content with the file links replaced * @param array $reference sys_refindex record * @param \TYPO3\CMS\Core\Resource\AbstractFile $file * @return void */ protected function saveChanges($modifiedText, array $reference, $file) { // If DBAL is not installed, we can start a transaction before saving // This ensures that a possible time out doesn't break the database integrity // by occurring between the two needed DB writes. if (!$this->isDbalInstalled) { $GLOBALS['TYPO3_DB']->sql_query('START TRANSACTION'); } // Save the changed field $GLOBALS['TYPO3_DB']->exec_UPDATEquery($reference['tablename'], 'uid = ' . $reference['recuid'], array($reference['field'] => $modifiedText)); $this->queries[] = htmlspecialchars(str_replace(LF, ' ', $GLOBALS['TYPO3_DB']->debug_lastBuiltQuery)); // Finally, update the sys_refindex table as well $GLOBALS['TYPO3_DB']->exec_UPDATEquery('sys_refindex', 'hash = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($reference['hash'], 'sys_refindex'), array('ref_table' => 'sys_file', 'ref_uid' => $file->getUid(), 'ref_string' => '')); $this->queries[] = str_replace(LF, ' ', $GLOBALS['TYPO3_DB']->debug_lastBuiltQuery); // Confirm the transaction if (!$this->isDbalInstalled) { $GLOBALS['TYPO3_DB']->sql_query('COMMIT'); } }
/** * Returns the properties of this object. * * @return array */ public function getProperties() { if ($this->indexed === NULL) { $this->loadIndexRecord(); } return parent::getProperties(); }
/** * Main function, redering the actual content of the editing page * * @return void * @todo Define visibility */ public function main() { //TODO: change locallang*.php to locallang*.xml $docHeaderButtons = $this->getButtons(); $this->content = $this->doc->startPage($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:file_edit.php.pagetitle')); // Hook before compiling the output if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['preOutputProcessingHook'])) { $preOutputProcessingHook =& $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['preOutputProcessingHook']; if (is_array($preOutputProcessingHook)) { $hookParameters = array('content' => &$this->content, 'target' => &$this->target); foreach ($preOutputProcessingHook as $hookFunction) { \TYPO3\CMS\Core\Utility\GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this); } } } $pageContent = $this->doc->header($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:file_edit.php.pagetitle') . ' ' . htmlspecialchars($this->fileObject->getName())); $pageContent .= $this->doc->spacer(2); $code = ''; $extList = $GLOBALS['TYPO3_CONF_VARS']['SYS']['textfile_ext']; if ($extList && \TYPO3\CMS\Core\Utility\GeneralUtility::inList($extList, $this->fileObject->getExtension())) { // Read file content to edit: $fileContent = $this->fileObject->getContents(); // Making the formfields $hValue = 'file_edit.php?target=' . rawurlencode($this->origTarget) . '&returnUrl=' . rawurlencode($this->returnUrl); // Edit textarea: $code .= ' <div id="c-edit"> <textarea rows="30" name="file[editfile][0][data]" wrap="off"' . $this->doc->formWidthText(48, 'width:98%;height:80%', 'off') . ' class="fixed-font enable-tab">' . \TYPO3\CMS\Core\Utility\GeneralUtility::formatForTextarea($fileContent) . '</textarea> <input type="hidden" name="file[editfile][0][target]" value="' . $this->fileObject->getUid() . '" /> <input type="hidden" name="redirect" value="' . htmlspecialchars($hValue) . '" /> </div> <br />'; // Make shortcut: if ($GLOBALS['BE_USER']->mayMakeShortcut()) { $this->MCONF['name'] = 'xMOD_file_edit.php'; $docHeaderButtons['shortcut'] = $this->doc->makeShortcutIcon('target', '', $this->MCONF['name'], 1); } else { $docHeaderButtons['shortcut'] = ''; } } else { $code .= sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:file_edit.php.coundNot'), $extList); } // Ending of section and outputting editing form: $pageContent .= $this->doc->sectionEnd(); $pageContent .= $code; // Hook after compiling the output if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['postOutputProcessingHook'])) { $postOutputProcessingHook =& $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['postOutputProcessingHook']; if (is_array($postOutputProcessingHook)) { $hookParameters = array('pageContent' => &$pageContent, 'target' => &$this->target); foreach ($postOutputProcessingHook as $hookFunction) { \TYPO3\CMS\Core\Utility\GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this); } } } // Add the HTML as a section: $markerArray = array('CSH' => $docHeaderButtons['csh'], 'FUNC_MENU' => \TYPO3\CMS\Backend\Utility\BackendUtility::getFuncMenu($this->id, 'SET[function]', $this->MOD_SETTINGS['function'], $this->MOD_MENU['function']), 'BUTTONS' => $docHeaderButtons, 'PATH' => $this->title, 'CONTENT' => $pageContent); $this->content .= $this->doc->moduleBody(array(), $docHeaderButtons, $markerArray); $this->content .= $this->doc->endPage(); $this->content = $this->doc->insertStylesAndJS($this->content); }