/** * Gets the relative path from a source directory to a target directory. * The allowed TYPO3 path is checked as well, thus it's not possible to go to upper levels. * * @param string $sourcePath Absolute source path * @param string $targetPath Absolute target path * @return NULL|string */ public static function getRelativePath($sourcePath, $targetPath) { $relativePath = NULL; $sourcePath = rtrim(GeneralUtility::fixWindowsFilePath($sourcePath), '/'); $targetPath = rtrim(GeneralUtility::fixWindowsFilePath($targetPath), '/'); if ($sourcePath !== $targetPath) { $commonPrefix = self::getCommonPrefix(array($sourcePath, $targetPath)); if ($commonPrefix !== NULL && \TYPO3\CMS\Core\Utility\GeneralUtility::isAllowedAbsPath($commonPrefix)) { $commonPrefixLength = strlen($commonPrefix); $resolvedSourcePath = ''; $resolvedTargetPath = ''; $sourcePathSteps = 0; if (strlen($sourcePath) > $commonPrefixLength) { $resolvedSourcePath = (string) substr($sourcePath, $commonPrefixLength); } if (strlen($targetPath) > $commonPrefixLength) { $resolvedTargetPath = (string) substr($targetPath, $commonPrefixLength); } if ($resolvedSourcePath !== '') { $sourcePathSteps = count(explode('/', $resolvedSourcePath)); } $relativePath = self::sanitizeTrailingSeparator(str_repeat('../', $sourcePathSteps) . $resolvedTargetPath); } } return $relativePath; }
/** * Sets the path to the log file. * * @param string $logFile path to the log file, relative to PATH_site * @return WriterInterface * @throws \InvalidArgumentException */ public function setLogFile($logFile) { // Skip handling if logFile is a stream resource. This is used by unit tests with vfs:// directories if (FALSE === strpos($logFile, '://')) { if (!GeneralUtility::isAllowedAbsPath(PATH_site . $logFile)) { throw new \InvalidArgumentException('Log file path "' . $logFile . '" is not valid!', 1326411176); } $logFile = GeneralUtility::getFileAbsFileName($logFile); } $this->logFile = $logFile; $this->openLogFile(); return $this; }
/** * Makes the given path absolute and ensures that it is allowed. * * The validation verifies that the path is under the web root or in any path allowed by * $GLOBALS['TYPO3_CONF_VARS']['BE']['lockRootPath']. * * @param string $path Path to handle * @return string Modified and validated path * @throws ImportExportException */ public function validatePath($path) { // Make path absolute $localPath = GeneralUtility::getFileAbsFileName($path, FALSE); // Make sure the path has a trailing slash if (strrpos($localPath, '/') !== strlen($localPath) - 1) { $localPath .= '/'; } // Remove double slashes due to user's input mistake $localPath = str_replace('//', '/', $localPath); if (!GeneralUtility::isAllowedAbsPath($localPath)) { throw new ImportExportException(sprintf('Path not allowed (%s)', $localPath), 1389105498); } return $localPath; }
/** * Validates the additional fields' values * * @param array $submittedData An array containing the data submitted by the add/edit task form * @param \TYPO3\CMS\Scheduler\Controller\SchedulerModuleController $schedulerModule Reference to the scheduler backend module * @return boolean TRUE if validation was ok (or selected class is not relevant), FALSE otherwise */ public function validateAdditionalFields(array &$submittedData, SchedulerModuleController $schedulerModule) { $validInput = true; $directoriesToClean = GeneralUtility::trimExplode(LF, $submittedData[$this->fieldPrefix . 'DirectoriesToClean'], true); foreach ($directoriesToClean as $path) { $path = trim($path, DIRECTORY_SEPARATOR); if (!(strlen($path) > 0 && file_exists(PATH_site . $path) && GeneralUtility::isAllowedAbsPath(PATH_site . $path) && GeneralUtility::validPathStr($path) && !GeneralUtility::inList($this->blackList, $path))) { $validInput = false; break; } } if (empty($submittedData[$this->fieldPrefix . 'DirectoriesToClean']) || $validInput === false) { $schedulerModule->addMessage($GLOBALS['LANG']->sL('LLL:EXT:minicleaner/locallang.xml:error.pathNotValid'), FlashMessage::ERROR); $validInput = false; } return $validInput; }
/** * prepare path, resolve relative path and resolve EXT: path * * @param string $path absolute or relative path or EXT:foobar/ * @return string/bool false if path is invalid, else the absolute path */ protected function getPath($path) { // getFileAbsFileName can't handle directory path with trailing / correctly if (substr($path, -1) === '/') { $path = substr($path, 0, -1); } // FIXME remove this hacky part // skip path checks for CLI mode if (defined('TYPO3_cliMode')) { return $path; } $path = \TYPO3\CMS\Core\Utility\GeneralUtility::getFileAbsFileName($path); if (\TYPO3\CMS\Core\Utility\GeneralUtility::isAllowedAbsPath($path)) { return $path; } else { return false; } }
public function execute() { $directories = GeneralUtility::trimExplode(LF, $this->directoriesToClean, true); if (is_array($directories)) { foreach ($directories as $key => $directory) { $path = PATH_site . trim($directory, DIRECTORY_SEPARATOR); if ($path != PATH_site && file_exists($path) && GeneralUtility::isAllowedAbsPath($path) && GeneralUtility::validPathStr($path) && !GeneralUtility::inList($this->blackList, $path)) { $result = GeneralUtility::flushDirectory($path, true); if ($result === false) { GeneralUtility::devLog($GLOBALS['LANG']->sL('LLL:EXT:minicleaner/locallang.xml:error.couldNotFlushDirectory'), 'minicleaner', 3); return false; } } else { GeneralUtility::devLog($GLOBALS['LANG']->sL('LLL:EXT:minicleaner/locallang.xml:error.pathNotFound'), 'minicleaner', 3); return false; } } } return true; }
/** * If it is an URL, nothing to do, if it is a file, check if path is allowed and prepend current url * * @param string $url * @return string * @throws \UnexpectedValueException */ public static function getCorrectUrl($url) { if (empty($url)) { throw new \UnexpectedValueException('An empty url is given'); } $url = self::getFalFilename($url); // check URL $urlInfo = parse_url($url); // means: it is no external url if (!isset($urlInfo['scheme'])) { // resolve paths like ../ $url = GeneralUtility::resolveBackPath($url); // absolute path is used to check path $absoluteUrl = GeneralUtility::getFileAbsFileName($url); if (!GeneralUtility::isAllowedAbsPath($absoluteUrl)) { throw new \UnexpectedValueException('The path "' . $url . '" is not allowed.'); } // append current domain $url = GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . $url; } return $url; }
/** * Creates GET parameters for linking to the export module. * * @return array GET parameters for current clipboard content to be exported */ protected function exportClipElementParameters() { // Init $pad = $this->current; $params = array(); $params['tx_impexp[action]'] = 'export'; // Traverse items: if (is_array($this->clipData[$pad]['el'])) { foreach ($this->clipData[$pad]['el'] as $k => $v) { if ($v) { list($table, $uid) = explode('|', $k); // Rendering files/directories on the clipboard if ($table == '_FILE') { if (file_exists($v) && GeneralUtility::isAllowedAbsPath($v)) { $params['tx_impexp[' . (is_dir($v) ? 'dir' : 'file') . '][]'] = $v; } } else { // Rendering records: $rec = BackendUtility::getRecord($table, $uid); if (is_array($rec)) { $params['tx_impexp[record][]'] = $table . ':' . $uid; } } } } } return $params; }
/** * Write content to a file. * * @param string $content Content to write to the file * @param string $absFile File name to write into. If empty a temp file will be created. * @return string|boolean File name or FALSE * @todo Define visibility */ public function writeFile($content, $absFile = '') { if (!$absFile) { $absFile = $this->tempFile($this->prefixId); } if ($absFile && \TYPO3\CMS\Core\Utility\GeneralUtility::isAllowedAbsPath($absFile)) { if ($fd = @fopen($absFile, 'wb')) { @fwrite($fd, $content); @fclose($fd); } else { $this->errorPush(T3_ERR_SV_FILE_WRITE, 'Can not write to file: ' . $absFile); $absFile = FALSE; } } return $absFile; }
/** * Function to load a HTML template file with markers. * When calling from own extension, use syntax getHtmlTemplate('EXT:extkey/template.html') * * @param string $filename tmpl name, usually in the typo3/template/ directory * @return string HTML of template */ public function getHtmlTemplate($filename) { // setting the name of the original HTML template $this->moduleTemplateFilename = $filename; if ($GLOBALS['TBE_STYLES']['htmlTemplates'][$filename]) { $filename = $GLOBALS['TBE_STYLES']['htmlTemplates'][$filename]; } if (GeneralUtility::isFirstPartOfStr($filename, 'EXT:')) { $filename = GeneralUtility::getFileAbsFileName($filename, true, true); } elseif (!GeneralUtility::isAbsPath($filename)) { $filename = GeneralUtility::resolveBackPath($filename); } elseif (!GeneralUtility::isAllowedAbsPath($filename)) { $filename = ''; } $htmlTemplate = ''; if ($filename !== '') { $htmlTemplate = GeneralUtility::getUrl($filename); } return $htmlTemplate; }
/** * Release the lock * * @return bool Returns TRUE on success or FALSE on failure */ public function release() { if (!$this->isAcquired) { return TRUE; } $success = TRUE; if (GeneralUtility::isAllowedAbsPath($this->filePath) && GeneralUtility::isFirstPartOfStr($this->filePath, PATH_site . self::FILE_LOCK_FOLDER)) { if (@unlink($this->filePath) === FALSE) { $success = FALSE; } } $this->isAcquired = FALSE; return $success; }
/** * If the submitted hash is correct and the user has access to the * related content element the contents of the submitted file will * be output to the user. * * @param string $jumpUrl The URL to the file that should be output to the user * @throws \Exception */ protected function forwardJumpUrlSecureFileData($jumpUrl) { // Set the parameters required for handling a secure jumpUrl link // The locationData GET parameter, containing information about the record that created the URL $locationData = (string) GeneralUtility::_GP('locationData'); // The optional mimeType GET parameter $mimeType = (string) GeneralUtility::_GP('mimeType'); // The jump Url Hash GET parameter $juHash = (string) GeneralUtility::_GP('juHash'); // validate the hash GET parameter against the other parameters if ($juHash !== JumpUrlUtility::calculateHashSecure($jumpUrl, $locationData, $mimeType)) { throw new \Exception('The calculated Jump URL secure hash ("juHash") did not match the submitted "juHash" query parameter.', 1294585196); } if (!$this->isLocationDataValid($locationData)) { throw new \Exception('The calculated secure location data "' . $locationData . '" is not accessible.', 1294585195); } // Allow spaces / special chars in filenames. $jumpUrl = rawurldecode($jumpUrl); // Deny access to files that match TYPO3_CONF_VARS[SYS][fileDenyPattern] and whose parent directory // is typo3conf/ (there could be a backup file in typo3conf/ which does not match against the fileDenyPattern) $absoluteFileName = GeneralUtility::getFileAbsFileName(GeneralUtility::resolveBackPath($jumpUrl), false); if (!GeneralUtility::isAllowedAbsPath($absoluteFileName) || !GeneralUtility::verifyFilenameAgainstDenyPattern($absoluteFileName) || GeneralUtility::isFirstPartOfStr($absoluteFileName, PATH_site . 'typo3conf')) { throw new \Exception('The requested file was not allowed to be accessed through Jump URL. The path or file is not allowed.', 1294585194); } try { $resourceFactory = $this->getResourceFactory(); $file = $resourceFactory->retrieveFileOrFolderObject($absoluteFileName); $this->readFileAndExit($file, $mimeType); } catch (\Exception $e) { throw new \Exception('The requested file "' . $jumpUrl . '" for Jump URL was not found..', 1294585193); } }
/** * Creates GET parameters for linking to the export module. * * @return string GET parameters for current clipboard content to be exported. * @todo Define visibility */ public function exportClipElementParameters() { // Init $pad = $this->current; $params = array(); $params[] = 'tx_impexp[action]=export'; // Traverse items: if (is_array($this->clipData[$pad]['el'])) { foreach ($this->clipData[$pad]['el'] as $k => $v) { if ($v) { list($table, $uid) = explode('|', $k); // Rendering files/directories on the clipboard if ($table == '_FILE') { if (file_exists($v) && \TYPO3\CMS\Core\Utility\GeneralUtility::isAllowedAbsPath($v)) { $params[] = 'tx_impexp[' . (is_dir($v) ? 'dir' : 'file') . '][]=' . rawurlencode($v); } } else { // Rendering records: $rec = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecord($table, $uid); if (is_array($rec)) { $params[] = 'tx_impexp[record][]=' . rawurlencode($table . ':' . $uid); } } } } } return '?' . implode('&', $params); }
/** * Indexing files from fileadmin * * @param array $cfgRec Indexing Configuration Record * @param array $session_data Session data for the indexing session spread over multiple instances of the script. Passed by reference so changes hereto will be saved for the next call! * @param array $params Parameters from the log queue. * @param object $pObj Parent object (from "crawler" extension!) * @return void */ public function crawler_execute_type2($cfgRec, &$session_data, $params, &$pObj) { // Prepare path, making it absolute and checking: $readpath = $params['url']; if (!GeneralUtility::isAbsPath($readpath)) { $readpath = GeneralUtility::getFileAbsFileName($readpath); } if (GeneralUtility::isAllowedAbsPath($readpath)) { if (@is_file($readpath)) { // If file, index it! // Get root line (need to provide this when indexing external files) $rl = $this->getUidRootLineForClosestTemplate($cfgRec['pid']); // (Re)-Indexing file on page. $indexerObj = GeneralUtility::makeInstance(\TYPO3\CMS\IndexedSearch\Indexer::class); $indexerObj->backend_initIndexer($cfgRec['pid'], 0, 0, '', $rl); $indexerObj->backend_setFreeIndexUid($cfgRec['uid'], $cfgRec['set_id']); $indexerObj->hash['phash'] = -1; // EXPERIMENT - but to avoid phash_t3 being written to file sections (otherwise they are removed when page is reindexed!!!) // Index document: $indexerObj->indexRegularDocument(\TYPO3\CMS\Core\Utility\PathUtility::stripPathSitePrefix($readpath), TRUE); } elseif (@is_dir($readpath)) { // If dir, read content and create new pending items for log: // Select files and directories in path: $extList = implode(',', GeneralUtility::trimExplode(',', $cfgRec['extensions'], TRUE)); $fileArr = array(); $files = GeneralUtility::getAllFilesAndFoldersInPath($fileArr, $readpath, $extList, 0, 0); $directoryList = GeneralUtility::get_dirs($readpath); if (is_array($directoryList) && $params['depth'] < $cfgRec['depth']) { foreach ($directoryList as $subdir) { if ((string) $subdir != '') { $files[] = $readpath . $subdir . '/'; } } } $files = GeneralUtility::removePrefixPathFromList($files, PATH_site); // traverse the items and create log entries: foreach ($files as $path) { $this->instanceCounter++; if ($path !== $params['url']) { // Parameters: $nparams = array('indexConfigUid' => $cfgRec['uid'], 'url' => $path, 'procInstructions' => array('[Index Cfg UID#' . $cfgRec['uid'] . ']'), 'depth' => $params['depth'] + 1); $pObj->addQueueEntry_callBack($cfgRec['set_id'], $nparams, $this->callBack, $cfgRec['pid'], $GLOBALS['EXEC_TIME'] + $this->instanceCounter * $this->secondsPerExternalUrl); } } } } }
/** * Loop through all elements and attach the file when the element * is a fileupload * * @param array $elements * @param array $submittedValues * @return void */ protected function addAttachmentsFromElements($elements, $submittedValues) { /** @var $element \TYPO3\CMS\Form\Domain\Model\Element\AbstractElement */ foreach ($elements as $element) { if (is_a($element, 'TYPO3\\CMS\\Form\\Domain\\Model\\Element\\ContainerElement')) { $this->addAttachmentsFromElements($element->getElements(), $submittedValues); continue; } if (is_a($element, 'TYPO3\\CMS\\Form\\Domain\\Model\\Element\\FileuploadElement')) { $elementName = $element->getName(); if (is_array($submittedValues[$elementName]) && isset($submittedValues[$elementName]['tempFilename'])) { $filename = $submittedValues[$elementName]['tempFilename']; if (is_file($filename) && \TYPO3\CMS\Core\Utility\GeneralUtility::isAllowedAbsPath($filename)) { $this->mailMessage->attach(\Swift_Attachment::fromPath($filename)->setFilename($submittedValues[$elementName]['originalFilename'])); } } } } }
/** * Export part of module * * @param array $inData Content of POST VAR tx_impexp[].. * @return void Setting content in $this->content * @todo Define visibility */ public function exportData($inData) { // BUILDING EXPORT DATA: // Processing of InData array values: $inData['pagetree']['maxNumber'] = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($inData['pagetree']['maxNumber'], 1, 10000, 100); $inData['listCfg']['maxNumber'] = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($inData['listCfg']['maxNumber'], 1, 10000, 100); $inData['maxFileSize'] = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($inData['maxFileSize'], 1, 10000, 1000); $inData['filename'] = trim(preg_replace('/[^[:alnum:]._-]*/', '', preg_replace('/\\.(t3d|xml)$/', '', $inData['filename']))); if (strlen($inData['filename'])) { $inData['filename'] .= $inData['filetype'] == 'xml' ? '.xml' : '.t3d'; } // Set exclude fields in export object: if (!is_array($inData['exclude'])) { $inData['exclude'] = array(); } // Saving/Loading/Deleting presets: $this->processPresets($inData); // Create export object and configure it: $this->export = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Impexp\\ImportExport'); $this->export->init(0, 'export'); $this->export->setCharset($GLOBALS['LANG']->charSet); $this->export->maxFileSize = $inData['maxFileSize'] * 1024; $this->export->excludeMap = (array) $inData['exclude']; $this->export->softrefCfg = (array) $inData['softrefCfg']; $this->export->extensionDependencies = (array) $inData['extension_dep']; $this->export->showStaticRelations = $inData['showStaticRelations']; $this->export->includeExtFileResources = !$inData['excludeHTMLfileResources']; // Static tables: if (is_array($inData['external_static']['tables'])) { $this->export->relStaticTables = $inData['external_static']['tables']; } // Configure which tables external relations are included for: if (is_array($inData['external_ref']['tables'])) { $this->export->relOnlyTables = $inData['external_ref']['tables']; } $this->export->setHeaderBasics(); // Meta data setting: $this->export->setMetaData($inData['meta']['title'], $inData['meta']['description'], $inData['meta']['notes'], $GLOBALS['BE_USER']->user['username'], $GLOBALS['BE_USER']->user['realName'], $GLOBALS['BE_USER']->user['email']); if ($inData['meta']['thumbnail']) { $tempDir = $this->userTempFolder(); if ($tempDir) { $thumbnails = \TYPO3\CMS\Core\Utility\GeneralUtility::getFilesInDir($tempDir, 'png,gif,jpg', 1); $theThumb = $thumbnails[$inData['meta']['thumbnail']]; if ($theThumb) { $this->export->addThumbnail($theThumb); } } } // Configure which records to export if (is_array($inData['record'])) { foreach ($inData['record'] as $ref) { $rParts = explode(':', $ref); $this->export->export_addRecord($rParts[0], \TYPO3\CMS\Backend\Utility\BackendUtility::getRecord($rParts[0], $rParts[1])); } } // Configure which tables to export if (is_array($inData['list'])) { foreach ($inData['list'] as $ref) { $rParts = explode(':', $ref); if ($GLOBALS['BE_USER']->check('tables_select', $rParts[0])) { $res = $this->exec_listQueryPid($rParts[0], $rParts[1], \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($inData['listCfg']['maxNumber'], 1)); while ($subTrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { $this->export->export_addRecord($rParts[0], $subTrow); } } } } // Pagetree if (isset($inData['pagetree']['id'])) { // Based on click-expandable tree if ($inData['pagetree']['levels'] == -1) { $pagetree = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Impexp\\LocalPageTree'); $tree = $pagetree->ext_tree($inData['pagetree']['id'], $this->filterPageIds($this->export->excludeMap)); $this->treeHTML = $pagetree->printTree($tree); $idH = $pagetree->buffer_idH; } elseif ($inData['pagetree']['levels'] == -2) { $this->addRecordsForPid($inData['pagetree']['id'], $inData['pagetree']['tables'], $inData['pagetree']['maxNumber']); } else { // Based on depth // Drawing tree: // If the ID is zero, export root if (!$inData['pagetree']['id'] && $GLOBALS['BE_USER']->isAdmin()) { $sPage = array('uid' => 0, 'title' => 'ROOT'); } else { $sPage = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordWSOL('pages', $inData['pagetree']['id'], '*', ' AND ' . $this->perms_clause); } if (is_array($sPage)) { $pid = $inData['pagetree']['id']; $tree = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Tree\\View\\PageTreeView'); $tree->init('AND ' . $this->perms_clause . $this->filterPageIds($this->export->excludeMap)); $HTML = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForRecord('pages', $sPage); $tree->tree[] = array('row' => $sPage, 'HTML' => $HTML); $tree->buffer_idH = array(); if ($inData['pagetree']['levels'] > 0) { $tree->getTree($pid, $inData['pagetree']['levels'], ''); } $idH = array(); $idH[$pid]['uid'] = $pid; if (count($tree->buffer_idH)) { $idH[$pid]['subrow'] = $tree->buffer_idH; } $pagetree = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Impexp\\LocalPageTree'); $this->treeHTML = $pagetree->printTree($tree->tree); } } // In any case we should have a multi-level array, $idH, with the page structure here (and the HTML-code loaded into memory for nice display...) if (is_array($idH)) { // Sets the pagetree and gets a 1-dim array in return with the pages (in correct submission order BTW...) $flatList = $this->export->setPageTree($idH); foreach ($flatList as $k => $value) { $this->export->export_addRecord('pages', \TYPO3\CMS\Backend\Utility\BackendUtility::getRecord('pages', $k)); $this->addRecordsForPid($k, $inData['pagetree']['tables'], $inData['pagetree']['maxNumber']); } } } // After adding ALL records we set relations: for ($a = 0; $a < 10; $a++) { $addR = $this->export->export_addDBRelations($a); if (!count($addR)) { break; } } // Finally files are added: // MUST be after the DBrelations are set so that files from ALL added records are included! $this->export->export_addFilesFromRelations(); // If the download button is clicked, return file if ($inData['download_export'] || $inData['save_export']) { switch ((string) $inData['filetype']) { case 'xml': $out = $this->export->compileMemoryToFileContent('xml'); $fExt = '.xml'; break; case 't3d': $this->export->dontCompress = 1; default: $out = $this->export->compileMemoryToFileContent(); $fExt = ($this->export->doOutputCompress() ? '-z' : '') . '.t3d'; break; } // Filename: $dlFile = $inData['filename'] ? $inData['filename'] : 'T3D_' . substr(preg_replace('/[^[:alnum:]_]/', '-', $inData['download_export_name']), 0, 20) . '_' . date('Y-m-d_H-i') . $fExt; // Export for download: if ($inData['download_export']) { $mimeType = 'application/octet-stream'; Header('Content-Type: ' . $mimeType); Header('Content-Length: ' . strlen($out)); Header('Content-Disposition: attachment; filename=' . basename($dlFile)); echo $out; die; } // Export by saving: if ($inData['save_export']) { $savePath = $this->userSaveFolder(); $fullName = $savePath . $dlFile; if (\TYPO3\CMS\Core\Utility\GeneralUtility::isAllowedAbsPath($savePath) && @is_dir(dirname($fullName)) && \TYPO3\CMS\Core\Utility\GeneralUtility::isAllowedAbsPath($fullName)) { \TYPO3\CMS\Core\Utility\GeneralUtility::writeFile($fullName, $out); $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('exportdata_savedFile'), sprintf($GLOBALS['LANG']->getLL('exportdata_savedInSBytes', 1), substr($savePath . $dlFile, strlen(PATH_site)), \TYPO3\CMS\Core\Utility\GeneralUtility::formatSize(strlen($out))), 0, 1); } else { $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('exportdata_problemsSavingFile'), sprintf($GLOBALS['LANG']->getLL('exportdata_badPathS', 1), $fullName), 0, 1, 2); } } } // OUTPUT to BROWSER: // Now, if we didn't make download file, show configuration form based on export: $menuItems = array(); // Export configuration $row = array(); $this->makeConfigurationForm($inData, $row); $menuItems[] = array('label' => $GLOBALS['LANG']->getLL('tableselec_configuration'), 'content' => ' <table border="0" cellpadding="1" cellspacing="1"> ' . implode(' ', $row) . ' </table> '); // File options $row = array(); $this->makeSaveForm($inData, $row); $menuItems[] = array('label' => $GLOBALS['LANG']->getLL('exportdata_filePreset'), 'content' => ' <table border="0" cellpadding="1" cellspacing="1"> ' . implode(' ', $row) . ' </table> '); // File options $row = array(); $this->makeAdvancedOptionsForm($inData, $row); $menuItems[] = array('label' => $GLOBALS['LANG']->getLL('exportdata_advancedOptions'), 'content' => ' <table border="0" cellpadding="1" cellspacing="1"> ' . implode(' ', $row) . ' </table> '); // Generate overview: $overViewContent = $this->export->displayContentOverview(); // Print errors that might be: $errors = $this->export->printErrorLog(); $menuItems[] = array('label' => $GLOBALS['LANG']->getLL('exportdata_messages'), 'content' => $errors, 'stateIcon' => $errors ? 2 : 0); // Add hidden fields and create tabs: $content = $this->doc->getDynTabMenu($menuItems, 'tx_impexp_export', -1); $content .= '<input type="hidden" name="tx_impexp[action]" value="export" />'; $this->content .= $this->doc->section('', $content, 0, 1); // Output Overview: $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('execlistqu_structureToBeExported'), $overViewContent, 0, 1); }
/** * Sets the directory and checks whether the directory is available. * * @throws \InvalidArgumentException if directory is not found or is not within the PATH_site * @param string $directory The absolute path to the directory in which the file is saved. * @return void */ public function setDirectory($directory) { if (!is_dir($directory)) { throw new \InvalidArgumentException($directory . ' is not a directory', 1312223779); } if (!\TYPO3\CMS\Core\Utility\GeneralUtility::isAllowedAbsPath($directory)) { throw new \InvalidArgumentException($directory . ' is not within the PATH_site' . ' OR within the lockRootPath', 1328734617); } $this->targetDirectory = $directory = rtrim($directory, DIRECTORY_SEPARATOR); }
/** * Collects information about the file * @param string $filename Filename * @return array Array of collected information */ private function getFileInformation($filename, $throwExeptions = TRUE) { $fileProperties = array(); $fileProperties['filename'] = $filename; if (strlen(trim($filename)) == 0 && $throwExeptions) { throw new \Exception(LocalizationUtility::translate('iconFontSelector.exception.missingFilename', 't3kit_extension_tools'), 20); } $fileProperties['absFileName'] = GeneralUtility::getFileAbsFileName($filename); $fileProperties['fileExists'] = file_exists($fileProperties['absFileName']); if (!$fileProperties['fileExists'] && $throwExeptions) { throw new \Exception(LocalizationUtility::translate('iconFontSelector.exception.fileExists', 't3kit_extension_tools') . ' (' . $filename . ')', 21); } $pathInfo = PathUtility::pathinfo($fileProperties['absFileName']); $fileProperties['dirname'] = $pathInfo['dirname']; $fileProperties['basename'] = $pathInfo['basename']; $fileProperties['extension'] = $pathInfo['extension']; $fileProperties['filename'] = $pathInfo['filename']; $fileProperties['isAllowedAbsPath'] = GeneralUtility::isAllowedAbsPath($fileProperties['absFileName']); if (!$fileProperties['isAllowedAbsPath'] && $throwExeptions) { throw new \Exception(LocalizationUtility::translate('iconFontSelector.exception.isAllowedAbsPath', 't3kit_extension_tools'), 22); } $fileProperties['relativePath'] = PathUtility::getRelativePathTo($fileProperties['dirname']); return $fileProperties; }
/** * * @param \EBT\ExtensionBuilder\Domain\Model\Extension $extension * @param string $backupDir * * @return void */ static function backupExtension(Model\Extension $extension, $backupDir) { if (empty($backupDir)) { throw new \Exception('Please define a backup directory in extension configuration!'); } elseif (!GeneralUtility::validPathStr($backupDir)) { throw new \Exception('Backup directory is not a valid path: ' . $backupDir); } elseif (GeneralUtility::isAbsPath($backupDir)) { if (!GeneralUtility::isAllowedAbsPath($backupDir)) { throw new \Exception('Backup directory is not an allowed absolute path: ' . $backupDir); } } else { $backupDir = PATH_site . $backupDir; } if (strrpos($backupDir, '/') < strlen($backupDir) - 1) { $backupDir .= '/'; } if (!is_dir($backupDir)) { throw new \Exception('Backup directory does not exist: ' . $backupDir); } elseif (!is_writable($backupDir)) { throw new \Exception('Backup directory is not writable: ' . $backupDir); } $backupDir .= $extension->getExtensionKey(); // create a subdirectory for this extension if (!is_dir($backupDir)) { GeneralUtility::mkdir($backupDir); } if (strrpos($backupDir, '/') < strlen($backupDir) - 1) { $backupDir .= '/'; } $backupDir .= date('Y-m-d-') . time(); if (!is_dir($backupDir)) { GeneralUtility::mkdir($backupDir); } $extensionDir = substr($extension->getExtensionDir(), 0, strlen($extension->getExtensionDir()) - 1); try { self::recurse_copy($extensionDir, $backupDir); } catch (\Exception $e) { throw new \Exception('Code generation aborted:' . $e->getMessage()); } self::log('Backup created in ' . $backupDir); }
/** * Indexing a regular document given as $file (relative to PATH_site, local file) * * @param string $file Relative Filename, relative to PATH_site. It can also be an absolute path as long as it is inside the lockRootPath (validated with \TYPO3\CMS\Core\Utility\GeneralUtility::isAbsPath()). Finally, if $contentTmpFile is set, this value can be anything, most likely a URL * @param bool $force If set, indexing is forced (despite content hashes, mtime etc). * @param string $contentTmpFile Temporary file with the content to read it from (instead of $file). Used when the $file is a URL. * @param string $altExtension File extension for temporary file. * @return void */ public function indexRegularDocument($file, $force = false, $contentTmpFile = '', $altExtension = '') { // Init $fI = pathinfo($file); $ext = $altExtension ?: strtolower($fI['extension']); // Create abs-path: if (!$contentTmpFile) { if (!GeneralUtility::isAbsPath($file)) { // Relative, prepend PATH_site: $absFile = GeneralUtility::getFileAbsFileName(PATH_site . $file); } else { // Absolute, pass-through: $absFile = $file; } $absFile = GeneralUtility::isAllowedAbsPath($absFile) ? $absFile : ''; } else { $absFile = $contentTmpFile; } // Indexing the document: if ($absFile && @is_file($absFile)) { if ($this->external_parsers[$ext]) { $fileInfo = stat($absFile); $cParts = $this->fileContentParts($ext, $absFile); foreach ($cParts as $cPKey) { $this->internal_log = array(); $this->log_push('Index: ' . str_replace('.', '_', basename($file)) . ($cPKey ? '#' . $cPKey : ''), ''); $Pstart = GeneralUtility::milliseconds(); $subinfo = array('key' => $cPKey); // Setting page range. This is "0" (zero) when no division is made, otherwise a range like "1-3" $phash_arr = $this->file_phash_arr = $this->setExtHashes($file, $subinfo); $check = $this->checkMtimeTstamp($fileInfo['mtime'], $phash_arr['phash']); if ($check > 0 || $force) { if ($check > 0) { $this->log_setTSlogMessage('Indexing needed, reason: ' . $this->reasons[$check], 1); } else { $this->log_setTSlogMessage('Indexing forced by flag', 1); } // Check external file counter: if ($this->externalFileCounter < $this->maxExternalFiles || $force) { // Divide into title,keywords,description and body: $this->log_push('Split content', ''); $contentParts = $this->readFileContent($ext, $absFile, $cPKey); $this->log_pull(); if (is_array($contentParts)) { // Calculating a hash over what is to be the actual content. (see indexTypo3PageContent()) $content_md5h = IndexedSearchUtility::md5inthash(implode($contentParts, '')); if ($this->checkExternalDocContentHash($phash_arr['phash_grouping'], $content_md5h) || $force) { // Increment counter: $this->externalFileCounter++; // Splitting words $this->log_push('Extract words from content', ''); $splitInWords = $this->processWordsInArrays($contentParts); $this->log_pull(); // Analyse the indexed words. $this->log_push('Analyse the extracted words', ''); $indexArr = $this->indexAnalyze($splitInWords); $this->log_pull(); // Submitting page (phash) record $this->log_push('Submitting page', ''); // Unfortunately I cannot determine WHEN a file is originally made - so I must return the modification time... $this->submitFilePage($phash_arr, $file, $subinfo, $ext, $fileInfo['mtime'], $fileInfo['ctime'], $fileInfo['size'], $content_md5h, $contentParts); $this->log_pull(); // Check words and submit to word list if not there $this->log_push('Check word list and submit words', ''); if (IndexedSearchUtility::isTableUsed('index_words')) { $this->checkWordList($indexArr); $this->submitWords($indexArr, $phash_arr['phash']); } $this->log_pull(); // Set parsetime $this->updateParsetime($phash_arr['phash'], GeneralUtility::milliseconds() - $Pstart); } else { // Update the timestamp $this->updateTstamp($phash_arr['phash'], $fileInfo['mtime']); $this->log_setTSlogMessage('Indexing not needed, the contentHash, ' . $content_md5h . ', has not changed. Timestamp updated.'); } } else { $this->log_setTSlogMessage('Could not index file! Unsupported extension.'); } } else { $this->log_setTSlogMessage('The limit of ' . $this->maxExternalFiles . ' has already been exceeded, so no indexing will take place this time.'); } } else { $this->log_setTSlogMessage('Indexing not needed, reason: ' . $this->reasons[$check]); } // Checking and setting sections: $this->submitFile_section($phash_arr['phash']); // Setting a section-record for the file. This is done also if the file is not indexed. Notice that section records are deleted when the page is indexed. $this->log_pull(); } } else { $this->log_setTSlogMessage('Indexing not possible; The extension "' . $ext . '" was not supported.'); } } else { $this->log_setTSlogMessage('Indexing not possible; File "' . $absFile . '" not found or valid.'); } }
/** * Loop through all elements of the session and attach the file * if its a uploaded file * * @return void */ protected function addAttachmentsFromSession() { $sessionData = $this->sessionUtility->getSessionData(); if (is_array($sessionData)) { foreach ($sessionData as $fieldName => $values) { if (is_array($values)) { foreach ($values as $file) { if (isset($file['tempFilename'])) { if (is_file($file['tempFilename']) && GeneralUtility::isAllowedAbsPath($file['tempFilename'])) { $this->mailMessage->attach(\Swift_Attachment::fromPath($file['tempFilename'])->setFilename($file['name'])); } } } } } } }
/** * Inject an view object to be able to set templateRootPath from flexform * * @param \TYPO3\CMS\Extbase\Mvc\View\ViewInterface $view * @return void */ protected function initializeView(\TYPO3\CMS\Extbase\Mvc\View\ViewInterface $view) { if (isset($this->settings['templateRootPath']) && !empty($this->settings['templateRootPath'])) { $templateRootPath = \TYPO3\CMS\Core\Utility\GeneralUtility::getFileAbsFileName($this->settings['templateRootPath'], true); if (\TYPO3\CMS\Core\Utility\GeneralUtility::isAllowedAbsPath($templateRootPath)) { $this->view->setTemplateRootPaths(array($templateRootPath)); } } }
/** * Imports files from Initialisation/Files to fileadmin * via lowlevel copy directory method * * @param string $extensionSiteRelPath relative path to extension dir * @param string $extensionKey */ protected function importInitialFiles($extensionSiteRelPath, $extensionKey) { $importRelFolder = $extensionSiteRelPath . 'Initialisation/Files'; if (!$this->registry->get('extensionDataImport', $importRelFolder)) { $importFolder = PATH_site . $importRelFolder; if (file_exists($importFolder)) { $destinationRelPath = $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'] . $extensionKey; $destinationAbsolutePath = PATH_site . $destinationRelPath; if (!file_exists($destinationAbsolutePath) && \TYPO3\CMS\Core\Utility\GeneralUtility::isAllowedAbsPath($destinationAbsolutePath)) { \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir($destinationAbsolutePath); } \TYPO3\CMS\Core\Utility\GeneralUtility::copyDirectory($importRelFolder, $destinationRelPath); $this->registry->set('extensionDataImport', $importRelFolder, 1); $this->emitAfterExtensionFileImportSignal($destinationAbsolutePath); } } }
/** * Initialize; reading parameters with GPvar and checking file path * Results in internal var, $this->file, being set to the file object * which should be used to make a thumbnail. * * @return void * @todo Define visibility */ public function init() { // Setting GPvars: // Only needed for MD5 sum calculation of backwards-compatibility uploads/ files thumbnails. $size = GeneralUtility::_GP('size'); $filePathOrCombinedFileIdentifier = rawurldecode(GeneralUtility::_GP('file')); $md5sum = GeneralUtility::_GP('md5sum'); // Image extension list is set: // valid extensions. OBS: No spaces in the list, all lowercase... $this->imageList = $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext']; // Check if we got a combined file identifier of the form storageUid:fileIdentifer. // We need to distinguish it from absolute Windows paths by cbecking for an integer as first part. $parts = GeneralUtility::trimExplode(':', $filePathOrCombinedFileIdentifier); // Best case: we get a sys_file UID if (!empty($filePathOrCombinedFileIdentifier) && MathUtility::canBeInterpretedAsInteger($filePathOrCombinedFileIdentifier)) { /** @var File $filePathOrCombinedFileIdentifier */ $fileObject = ResourceFactory::getInstance()->getFileObject($filePathOrCombinedFileIdentifier); } elseif (count($parts) <= 1 || !MathUtility::canBeInterpretedAsInteger($parts[0])) { // TODO: Historically, the input parameter could also be an absolute path. This should be supported again to stay compatible. // We assume the FilePath to be a relative file path (as in backwards compatibility mode) $relativeFilePath = $filePathOrCombinedFileIdentifier; // The incoming relative path is relative to the typo3/ directory, but we need it relative to PATH_site. This is corrected here: if (substr($relativeFilePath, 0, 3) == '../') { $relativeFilePath = substr($relativeFilePath, 3); } else { $relativeFilePath = 'typo3/' . $relativeFilePath; } $relativeFilePath = ltrim($relativeFilePath, '/'); $mTime = 0; // Checking for backpath and double slashes + the thumbnail can be made from files which are in the PATH_site OR the lockRootPath only! if (GeneralUtility::isAllowedAbsPath(PATH_site . $relativeFilePath)) { $mTime = filemtime(PATH_site . $relativeFilePath); } if (strstr($relativeFilePath, '../') !== FALSE) { // Maybe this could be relaxed to not throw an error as long as the path is still within PATH_site $this->errorGif('File path', 'must not contain', '"../"'); } if ($relativeFilePath && file_exists(PATH_site . $relativeFilePath)) { // Check file extension: $reg = array(); if (preg_match('/(.*)\\.([^\\.]*$)/', $relativeFilePath, $reg)) { $ext = strtolower($reg[2]); $ext = $ext == 'jpeg' ? 'jpg' : $ext; if (!GeneralUtility::inList($this->imageList, $ext)) { $this->errorGif('Not imagefile!', $ext, basename($relativeFilePath)); } } else { $this->errorGif('Not imagefile!', 'No ext!', basename($relativeFilePath)); } } else { $this->errorGif('Input file not found.', 'not found in thumbs.php', basename($relativeFilePath)); } // Do an MD5 check to prevent viewing of images without permission $OK = FALSE; if ($mTime) { // Always use the absolute path for this check! $check = basename($relativeFilePath) . ':' . $mTime . ':' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']; if (GeneralUtility::shortMD5($check) === (string) $md5sum) { $OK = TRUE; } } $combinedIdentifier = '0:' . $relativeFilePath; } else { $combinedIdentifier = $filePathOrCombinedFileIdentifier; $OK = FALSE; } if (empty($fileObject)) { $fileObject = ResourceFactory::getInstance()->getFileObjectFromCombinedIdentifier($combinedIdentifier); } if (empty($OK)) { $OK = $fileObject !== NULL && $fileObject->checkActionPermission('read') && $fileObject->calculateChecksum() == $md5sum; } if ($OK) { $this->image = $fileObject; $this->size = $size; } else { // Hide the path to the document root; throw new \RuntimeException('TYPO3 Fatal Error: The requested image does not exist and/or MD5 checksum did not match. If the target file exists and its file name contains special characters, the setting of $TYPO3_CONF_VARS[SYS][systemLocale] might be wrong.', 1270853950); } }
/** * Sends a header "Location" to jumpUrl, if jumpurl is set. * Will exit if a location header is sent (for instance if jumpUrl was triggered) * * "jumpUrl" is a concept where external links are redirected from the index_ts.php script, which first logs the URL. * * @return void * @todo Define visibility */ public function jumpUrl() { if ($this->jumpurl) { if (\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('juSecure')) { $locationData = (string) \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('locationData'); // Need a type cast here because mimeType is optional! $mimeType = (string) \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('mimeType'); $hArr = array($this->jumpurl, $locationData, $mimeType); $calcJuHash = \TYPO3\CMS\Core\Utility\GeneralUtility::hmac(serialize($hArr)); $juHash = (string) \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('juHash'); if ($juHash === $calcJuHash) { if ($this->locDataCheck($locationData)) { // 211002 - goes with cObj->filelink() rawurlencode() of filenames so spaces can be allowed. $this->jumpurl = rawurldecode($this->jumpurl); // Deny access to files that match TYPO3_CONF_VARS[SYS][fileDenyPattern] and whose parent directory is typo3conf/ (there could be a backup file in typo3conf/ which does not match against the fileDenyPattern) $absoluteFileName = \TYPO3\CMS\Core\Utility\GeneralUtility::getFileAbsFileName(\TYPO3\CMS\Core\Utility\GeneralUtility::resolveBackPath($this->jumpurl), FALSE); if (\TYPO3\CMS\Core\Utility\GeneralUtility::isAllowedAbsPath($absoluteFileName) && \TYPO3\CMS\Core\Utility\GeneralUtility::verifyFilenameAgainstDenyPattern($absoluteFileName) && !\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($absoluteFileName, PATH_site . 'typo3conf')) { if (@is_file($absoluteFileName)) { $mimeType = $mimeType ? $mimeType : 'application/octet-stream'; header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Content-Type: ' . $mimeType); header('Content-Disposition: attachment; filename="' . basename($absoluteFileName) . '"'); readfile($absoluteFileName); die; } else { throw new \Exception('jumpurl Secure: "' . $this->jumpurl . '" was not a valid file!', 1294585193); } } else { throw new \Exception('jumpurl Secure: The requested file was not allowed to be accessed through jumpUrl (path or file not allowed)!', 1294585194); } } else { throw new \Exception('jumpurl Secure: locationData, ' . $locationData . ', was not accessible.', 1294585195); } } else { throw new \Exception('jumpurl Secure: Calculated juHash did not match the submitted juHash.', 1294585196); } } else { $TSConf = $this->getPagesTSconfig(); if ($TSConf['TSFE.']['jumpUrl_transferSession']) { $uParts = parse_url($this->jumpurl); $params = '&FE_SESSION_KEY=' . rawurlencode($this->fe_user->id . '-' . md5($this->fe_user->id . '/' . $this->TYPO3_CONF_VARS['SYS']['encryptionKey'])); // Add the session parameter ... $this->jumpurl .= ($uParts['query'] ? '' : '?') . $params; } if ($TSConf['TSFE.']['jumpURL_HTTPStatusCode']) { switch (intval($TSConf['TSFE.']['jumpURL_HTTPStatusCode'])) { case 301: $statusCode = \TYPO3\CMS\Core\Utility\HttpUtility::HTTP_STATUS_301; break; case 302: $statusCode = \TYPO3\CMS\Core\Utility\HttpUtility::HTTP_STATUS_302; break; case 307: $statusCode = \TYPO3\CMS\Core\Utility\HttpUtility::HTTP_STATUS_307; break; case 303: default: $statusCode = \TYPO3\CMS\Core\Utility\HttpUtility::HTTP_STATUS_303; break; } } \TYPO3\CMS\Core\Utility\HttpUtility::redirect($this->jumpurl, $statusCode); } } }
/** * Loads the header section/all of the $filename into memory * * @param string $filename Filename, absolute * @param bool $all If set, all information is loaded (header, records and files). Otherwise the default is to read only the header information * @return bool TRUE if the operation went well */ public function loadFile($filename, $all = false) { if (!@is_file($filename)) { $this->error('Filename not found: ' . $filename); return false; } $fI = pathinfo($filename); if (@is_dir($filename . '.files')) { if (GeneralUtility::isAllowedAbsPath($filename . '.files')) { // copy the folder lowlevel to typo3temp, because the files would be deleted after import $temporaryFolderName = $this->getTemporaryFolderName(); GeneralUtility::copyDirectory($filename . '.files', $temporaryFolderName); $this->filesPathForImport = $temporaryFolderName; } else { $this->error('External import files for the given import source is currently not supported.'); } } if (strtolower($fI['extension']) == 'xml') { // XML: $xmlContent = GeneralUtility::getUrl($filename); if (strlen($xmlContent)) { $this->dat = GeneralUtility::xml2array($xmlContent, '', true); if (is_array($this->dat)) { if ($this->dat['_DOCUMENT_TAG'] === 'T3RecordDocument' && is_array($this->dat['header']) && is_array($this->dat['records'])) { $this->loadInit(); return true; } else { $this->error('XML file did not contain proper XML for TYPO3 Import'); } } else { $this->error('XML could not be parsed: ' . $this->dat); } } else { $this->error('Error opening file: ' . $filename); } } else { // T3D if ($fd = fopen($filename, 'rb')) { $this->dat['header'] = $this->getNextFilePart($fd, 1, 'header'); if ($all) { $this->dat['records'] = $this->getNextFilePart($fd, 1, 'records'); $this->dat['files'] = $this->getNextFilePart($fd, 1, 'files'); $this->dat['files_fal'] = $this->getNextFilePart($fd, 1, 'files_fal'); } $this->loadInit(); return true; } else { $this->error('Error opening file: ' . $filename); } fclose($fd); } return false; }
/** * Do some cleanup at the end (deleting attachment files) */ public function __destruct() { foreach ($this->temporaryFiles as $file) { if (\TYPO3\CMS\Core\Utility\GeneralUtility::isAllowedAbsPath($file) && \TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($file, PATH_site . 'typo3temp/upload_temp_')) { \TYPO3\CMS\Core\Utility\GeneralUtility::unlink_tempfile($file); } } }
/** * Get the url to jump to as set by Direct Mail * * @return void * @throws \Exception */ public function preprocessRequest($parameter, $parentObject) { $db = $this->getDatabaseConnection(); $jumpUrlVariables = GeneralUtility::_GET(); $mid = $jumpUrlVariables['mid']; $rid = $jumpUrlVariables['rid']; $aC = $jumpUrlVariables['aC']; $responseType = 0; if ($mid) { // overwrite the jumpUrl with the one from the &jumpurl= get parameter $jumpurl = $jumpUrlVariables['jumpurl']; // this will split up the "rid=f_13667", where the first part // is the DB table name and the second part the UID of the record in the DB table $recipientTable = ''; $recipientUid = ''; if (!empty($rid)) { list($recipientTable, $recipientUid) = explode('_', $rid); } $urlId = 0; if (MathUtility::canBeInterpretedAsInteger($jumpurl)) { // fetch the direct mail record where the mailing was sent (for this message) $resMailing = $db->exec_SELECTquery('mailContent, page, authcode_fieldList', 'sys_dmail', 'uid = ' . intval($mid)); if ($row = $db->sql_fetch_assoc($resMailing)) { $mailContent = unserialize(base64_decode($row['mailContent'])); $urlId = $jumpurl; if ($jumpurl >= 0) { // Link (number) $responseType = 1; $jumpurl = $mailContent['html']['hrefs'][$urlId]['absRef']; } else { // Link (number, plaintext) $responseType = 2; $jumpurl = $mailContent['plain']['link_ids'][abs($urlId)]; } $jumpurl = htmlspecialchars_decode(urldecode($jumpurl)); switch ($recipientTable) { case 't': $theTable = 'tt_address'; break; case 'f': $theTable = 'fe_users'; break; default: $theTable = ''; } if ($theTable) { $recipRow = $this->getRawRecord($theTable, $recipientUid); if (is_array($recipRow)) { $authCode = GeneralUtility::stdAuthCode($recipRow, $row['authcode_fieldList'] ? $row['authcode_fieldList'] : 'uid'); // check if supplied aC identical with counted authCode if ($aC != '' && $aC == $authCode) { $rowFieldsArray = explode(',', $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['defaultRecipFields']); if ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['addRecipFields']) { $rowFieldsArray = array_merge($rowFieldsArray, explode(',', $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['addRecipFields'])); } reset($rowFieldsArray); foreach ($rowFieldsArray as $substField) { $jumpurl = str_replace('###USER_' . $substField . '###', $recipRow[$substField], $jumpurl); } // Put in the tablename of the userinformation $jumpurl = str_replace('###SYS_TABLE_NAME###', substr($theTable, 0, 1), $jumpurl); // Put in the uid of the mail-record $jumpurl = str_replace('###SYS_MAIL_ID###', $mid, $jumpurl); // If authCode is provided, keep it. $jumpurl = str_replace('###SYS_AUTHCODE###', $aC, $jumpurl); // Auto Login an FE User, only possible if we're allowed to set the $_POST variables and // in the authcode_fieldlist the field "password" is computed in as well // TODO: add a switch in Direct Mail configuration to decide if this option should be enabled by default if ($theTable == 'fe_users' && $aC != '' && $aC == $authCode && GeneralUtility::inList($row['authcode_fieldList'], 'password')) { $_POST['user'] = $recipRow['username']; $_POST['pass'] = $recipRow['password']; $_POST['pid'] = $recipRow['pid']; $_POST['logintype'] = 'login'; } } else { throw new \Exception('authCode: Calculated authCode did not match the submitted authCode.', 1376899631); } } } } $db->sql_free_result($resMailing); if (!$jumpurl) { die('Error: No further link. Please report error to the mail sender.'); } else { // jumpurl has been validated by lookup of id in direct_mail tables // for this reason it is save to set the juHash // set juHash as done for external_url in core: http://forge.typo3.org/issues/46071 GeneralUtility::_GETset(GeneralUtility::hmac($jumpurl, 'jumpurl'), 'juHash'); } } else { // jumpUrl is not an integer -- then this is a URL, that means that the "dmailerping" // functionality was used to count the number of "opened mails" received (url, dmailerping) // Check if jumpurl is a valid link to a "dmailerping.gif" // Make $checkPath an absolute path pointing to dmailerping.gif so it can get checked via ::isAllowedAbsPath() // and remove an eventual "/" at beginning of $jumpurl (because PATH_site already contains "/" at the end) $checkPath = PATH_site . preg_replace('#^/#', '', $jumpurl); // Now check if $checkPath is a valid path and points to a "/dmailerping.gif" if (preg_match('#/dmailerping\\.(gif|png)$#', $checkPath) && GeneralUtility::isAllowedAbsPath($checkPath)) { // set juHash as done for external_url in core: http://forge.typo3.org/issues/46071 GeneralUtility::_GETset(GeneralUtility::hmac($jumpurl, 'jumpurl'), 'juHash'); $responseType = -1; } elseif (GeneralUtility::isValidUrl($jumpurl) && preg_match('#^(http://|https://)#', $jumpurl)) { // Also allow jumpurl to be a valid URL GeneralUtility::_GETset(GeneralUtility::hmac($jumpurl, 'jumpurl'), 'juHash'); $responseType = -1; } // to count the dmailerping correctly, we need something unique $recipientUid = $aC; } if ($responseType != 0) { $insertFields = array('mid' => intval($mid), 'tstamp' => time(), 'url' => $jumpurl, 'response_type' => intval($responseType), 'url_id' => intval($urlId), 'rtbl' => $recipientTable, 'rid' => $recipientUid); $db->exec_INSERTquery('sys_dmail_maillog', $insertFields); } } // finally set the jumpURL to the TSFE object if (!empty($jumpurl)) { GeneralUtility::_GETset($jumpurl, 'jumpurl'); } }
/** * Release the lock * * @return bool Returns TRUE on success or FALSE on failure */ public function release() { if (!$this->isAcquired) { return true; } $success = true; switch ($this->method) { case self::LOCKING_METHOD_SIMPLE: if (GeneralUtility::isAllowedAbsPath($this->resource) && GeneralUtility::isFirstPartOfStr($this->resource, PATH_site . self::FILE_LOCK_FOLDER)) { if (@unlink($this->resource) === false) { $success = false; } } break; case self::LOCKING_METHOD_FLOCK: if (is_resource($this->filePointer)) { if (flock($this->filePointer, LOCK_UN) === false) { $success = false; } fclose($this->filePointer); } break; case self::LOCKING_METHOD_SEMAPHORE: if (!@sem_release($this->resource)) { $success = false; } break; case self::LOCKING_METHOD_DISABLED: break; default: // will never be reached } $this->isAcquired = false; return $success; }
/** * check if a copy exist * * @return boolean */ public function copy_exist() { $copyPath = GeneralUtility::getFileAbsFileName('fileadmin/BootstrapLessConfig/'); $file = $copyPath . 'variables_copy.less'; $copyExist = FALSE; if (@file_exists($file) && GeneralUtility::isAllowedAbsPath($file)) { $copyExist = TRUE; } return $copyExist; }