/** * Creates an instance of this class. It obtains a path to the OpenSSL * binary. * * @return void */ public function __construct() { $this->opensslPath = t3lib_exec::getCommand('openssl'); $this->temporaryDirectory = PATH_site . 'typo3temp'; // Get temporary directory from the configuration $extconf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['rsaauth']); if ($extconf['temporaryDirectory'] != '' && $extconf['temporaryDirectory'][0] == '/' && @is_dir($extconf['temporaryDirectory']) && is_writable($extconf['temporaryDirectory'])) { $this->temporaryDirectory = $extconf['temporaryDirectory']; } }
/** * performs the service processing * * @param string Content which should be processed. * @param string Content type * @param array Configuration array * @return boolean */ function process($content = '', $type = '', $conf = array()) { $this->conf = $conf; $this->out = array(); $this->out['fields'] = array(); $this->exif = array(); if ($content) { $this->setInput($content, $type); } if ($inputFile = $this->getInputFile()) { $cmd = t3lib_exec::getCommand($this->info['exec']) . ' ' . escapeshellarg($inputFile); $exif = $ret = NULL; exec($cmd, $exif, $ret); if (!$ret and is_array($exif)) { foreach ($exif as $line) { list($name, $value) = t3lib_div::trimExplode(':', $line); if ($value) { // ignore empty lines headers and emtpy entries $name = str_replace('-', '', $name); $name = str_replace(' ', '', $name); // add to exif table $this->exif[$name] = $value; // add to DAM table switch ($name) { case 'CameraModel': $this->out['fields']['file_creator'] = $value; break; case 'ImageCreated': $this->out['fields']['date_cr'] = tx_svmetaextract_lib::parseDate($value); break; case 'HorizontalResolution': $this->out['fields']['hres'] = intval($value); break; case 'VerticalResolution': $this->out['fields']['vres'] = intval($value); break; case 'ColorSpaceInformation': $this->out['fields']['color_space'] = $value; break; case 'Title': $this->out['fields']['title'] = $value; break; } } } } $this->postProcess(); $this->out['fields']['meta']['EXIF'] = $this->exif; } else { $this->errorPush(T3_ERR_SV_NO_INPUT, 'No or empty input.'); } return $this->getLastError(); }
/** * Initializes and extends the preset paths with own * * @param string Comma seperated list of extra paths where a command should be searched. Relative paths (without leading "/") are prepend with site root path (PATH_site). * @return void */ protected static function initPaths($paths = '') { $doCheck = FALSE; // init global paths array if not already done if (!is_array(self::$paths)) { self::$paths = self::getPathsInternal(); $doCheck = TRUE; } // merge the submitted paths array to the global if ($paths) { $paths = t3lib_div::trimExplode(',', $paths, 1); if (is_array($paths)) { foreach ($paths as $path) { // make absolute path of relative if (!preg_match('#^/#', $path)) { $path = PATH_site . $path; } if (!isset(self::$paths[$path])) { if (@is_dir($path)) { self::$paths[$path] = $path; } else { self::$paths[$path] = FALSE; } } } } } // check if new paths are invalid if ($doCheck) { foreach (self::$paths as $path => $valid) { // ignore invalid (false) paths if ($valid and !@is_dir($path)) { self::$paths[$path] = FALSE; } } } }
/** * performs the service processing * * @param string Content which should be processed. * @param string Content type * @param array Configuration array * @return boolean */ function process($content = '', $type = '', $conf = array()) { $this->conf = $conf; $this->out = array(); $this->out['fields'] = array(); $this->exif = array(); if ($content) { $this->setInput($content, $type); } if ($inputFile = $this->getInputFile()) { $cmd = t3lib_exec::getCommand($this->info['exec']) . ' -q -m -g -S ' . escapeshellarg($inputFile); $exif = $ret = NULL; exec($cmd, $exif, $ret); if (!$ret and is_array($exif)) { $section = 'EXIF'; array_shift($exif); // ---- ExifTool ---- array_shift($exif); // ExifToolVersion : 6.57 foreach ($exif as $line) { if (preg_match('#---- ([^ ]*) ----#', $line, $matches)) { $section = $matches[1]; } // Only request 2 elements because exiftool output contains colons in $value list($name, $value) = explode(':', $line, 2); $name = trim($name); $value = trim($value); if ($value) { // ignore empty lines headers and empty entries $name = str_replace('-', '', $name); $name = str_replace(' ', '', $name); // add to exif table $this->exif[$section][$name] = $value; // add to DAM table switch ($name) { case 'CameraModel': $this->out['fields']['file_creator'] = $value; break; case 'XResolution': case 'HorizontalResolution': $this->out['fields']['hres'] = intval($value); break; case 'YResolution': case 'VerticalResolution': $this->out['fields']['vres'] = intval($value); break; case 'Title': case 'Headline': case 'XPTitle': $this->out['fields']['title'] = $value; break; case 'Keywords': case 'XPKeywords': $this->out['fields']['keywords'] = $value; break; case 'Subject': case 'ImageDescription': case 'Description': $this->out['fields']['description'] = $value; break; case 'CaptionAbstract': $this->out['fields']['caption'] = $value; break; case 'ModifyDate': $this->out['fields']['date_mod'] = tx_svmetaextract_lib::parseDate($value); $this->out['fields']['file_mtime'] = tx_svmetaextract_lib::parseDate($value); break; case 'ImageCreated': case 'CreateDate': case 'DateTimeOriginal': $this->out['fields']['date_cr'] = tx_svmetaextract_lib::parseDate($value); $this->out['fields']['file_ctime'] = tx_svmetaextract_lib::parseDate($value); break; case 'CreatorTool': case 'Software': $this->out['fields']['file_creator'] = $value; break; case 'City': $this->out['fields']['loc_city'] = $value; break; case 'Country': // TODO format? # $this->out['fields']['loc_country'] = $value; break; case 'CountryCode': if (strlen($value) == 2) { $isoCodeField = tx_staticinfotables_div::getIsoCodeField('static_countries', $value); $enableFields = t3lib_BEfunc::deleteClause('static_countries'); $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('cn_iso_3', 'static_countries', $isoCodeField . '=' . $GLOBALS['TYPO3_DB']->fullQuoteStr(strtoupper($value), 'static_countries') . $enableFields); if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { $this->out['fields']['loc_country'] = $row['cn_iso_3']; } } break; case 'Artist': case 'Creator': $this->out['fields']['creator'] = $value; break; case 'Copyright': case 'CopyrightNotice': $this->out['fields']['copyright'] = $value; break; case 'Rights': $this->out['fields']['copyright'] = $value; break; case 'RightsUsageTerms': case 'UsageTerms': $this->out['fields']['instructions'] = $value; break; case 'Credit': $this->out['fields']['copyright'] = $value; break; case 'Instructions': $this->out['fields']['instructions'] = $value; break; } } } } // TODO read XMP XML // $this->out['fields']['meta']['XMP_XML'] = $this->xmpRaw; unset($this->exif['File']); unset($this->exif['Composite']); $this->postProcess(); $this->out['fields']['meta'] = $this->exif; $this->out['exif_done'] = true; $this->out['iptc_done'] = true; $this->out['xmp_done'] = true; } else { $this->errorPush(T3_ERR_SV_NO_INPUT, 'No or empty input.'); } return $this->getLastError(); }
/** * Display paths where binaries are searched for * * @return string HTML content */ function showSearchPaths() { if (is_callable(array('t3lib_exec', 'getPaths'))) { // v 3.8 if (count($paths = t3lib_exec::getPaths(true))) { $lines = array(); $lines[] = '<tr class="bgColor5"><td><strong>Path:</strong></td><td><strong>valid:</strong></td></tr>'; foreach ($paths as $path => $valid) { if ($valid) { $icon = '<img ' . t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'], 'gfx/icon_ok.gif') . ' vspace="4" />'; } else { $icon = '<img ' . t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'], 'gfx/icon_fatalerror.gif') . ' vspace="4" />'; } $lines[] = '<tr class="bgColor' . ($valid ? '4' : '2') . '"><td>' . htmlspecialchars($path) . '</td><td align="center">' . $icon . '</td></tr>'; } $content .= '<table border="0" cellpadding="2" cellspacing="1">' . implode('', $lines) . '</table><br />'; } } return $content; }
/** * Calculates a hash value from a file. * The hash is used to identify file changes or a file itself. * Remember that a file can occur multiple times in the file system, therefore you can detect only that it is the same file. But you have to take the location (path) into account to identify the right file. * * @param mixed $fileInfo Is a file path or an array containing a file info from tx_dam::file_compileInfo(). * @return string hash value */ function file_calcHash($fileInfo) { $hash = false; $filename = tx_dam::file_absolutePath($fileInfo); if (function_exists('md5_file')) { $hash = @md5_file($filename); } else { if (filesize($filename) > 0xfffff) { // 1MB $cmd = t3lib_exec::getCommand('md5sum'); $output = array(); $retval = 0; exec($cmd . ' -b ' . escapeshellcmd($filename), $output, $retval); $output = explode(' ', $output[0]); $match = array(); if (preg_match('#[0-9a-f]{32}#', $output[0], $match)) { $hash = $match[0]; } } else { $file_string = t3lib_div::getUrl($filename); $hash = md5($file_string); } } return $hash; }
/** * Find the available service with highest priority * * @param string Service type * @param string Service sub type * @param mixed Service keys that should be excluded in the search for a service. Array or comma list. * @return mixed Service info array if a service was found, FLASE otherwise * @author Rene Fritz <*****@*****.**> */ public static function findService($serviceType, $serviceSubType = '', $excludeServiceKeys = array()) { global $T3_SERVICES, $TYPO3_CONF_VARS; $serviceKey = FALSE; $serviceInfo = FALSE; $priority = 0; $quality = 0; if (!is_array($excludeServiceKeys)) { $excludeServiceKeys = t3lib_div::trimExplode(',', $excludeServiceKeys, 1); } if (is_array($T3_SERVICES[$serviceType])) { foreach ($T3_SERVICES[$serviceType] as $key => $info) { if (in_array($key, $excludeServiceKeys)) { continue; } // select a subtype randomly // usefull to start a service by service key without knowing his subtypes - for testing purposes if ($serviceSubType == '*') { $serviceSubType = key($info['serviceSubTypes']); } // this matches empty subtype too if ($info['available'] && ($info['subtype'] == $serviceSubType || $info['serviceSubTypes'][$serviceSubType]) && $info['priority'] >= $priority) { // has a lower quality than the already found, therefore we skip this service if ($info['priority'] == $priority && $info['quality'] < $quality) { continue; } // service depends on external programs - check if they exists if (trim($info['exec'])) { $executables = t3lib_div::trimExplode(',', $info['exec'], 1); foreach ($executables as $executable) { if (!t3lib_exec::checkCommand($executable)) { self::deactivateService($serviceType, $key); $info['available'] = FALSE; break; } } } // still available after exec check? if ($info['available']) { $serviceKey = $key; $priority = $info['priority']; $quality = $info['quality']; } } } } if ($serviceKey) { $serviceInfo = $T3_SERVICES[$serviceType][$serviceKey]; } return $serviceInfo; }
/** * tx_dam::file_calcHash() */ public function test_file_calcHash() { $filename = $this->getFixtureFilename(); $hash = array(); $hash['file_calcHash'] = tx_dam::file_calcHash($filename); $compareHash = '4e231415019b6593f0266b99b7704bc2'; if (function_exists('md5_file')) { $hash['md5_file'] = @md5_file($filename); } $cmd = t3lib_exec::getCommand('md5sum'); $output = array(); $retval = ''; exec($cmd . ' -b ' . escapeshellcmd($filename), $output, $retval); $output = explode(' ', $output[0]); $match = array(); if (preg_match('#[0-9a-f]{32}#', $output[0], $match)) { $hash['md5sum'] = $match[0]; } $file_string = t3lib_div::getUrl($filename); $hash['md5'] = md5($file_string); foreach ($hash as $key => $value) { self::assertEquals($compareHash, $value, 'Wrong hash: ' . $value . ' (' . $key . ')'); } }
/** * get the mime type of a file with full path * * @param string $pathname absolute path to file * @return array file information */ function getFileMimeType($pathname) { // this will be called from tx_dam therefore $pathname can be a fileInfo array $pathname = tx_dam::file_absolutePath($pathname); $TX_DAM = $GLOBALS['T3_VAR']['ext']['dam']; $mimeType = array(); $mimeType['fulltype'] = ''; $mimeType['file_mime_type'] = ''; $mimeType['file_mime_subtype'] = ''; $mimeType['file_type'] = ''; $path_parts = t3lib_div::split_fileref($pathname); $mimeType['file_type'] = strtolower($path_parts['realFileext']); // cleanup bakup files extension $mimeType['file_type'] = preg_replace('#\\~$#', '', $mimeType['file_type']); $this->setup['useInternalMimeList'] = tx_dam::config_checkValueEnabled('setup.indexing.useInternalMimeList', true); $this->setup['useMimeContentType'] = tx_dam::config_checkValueEnabled('setup.indexing.useMimeContentType', true); $this->setup['useFileCommand'] = tx_dam::config_checkValueEnabled('setup.indexing.useFileCommand', true); // Get the mimetype info from the DB $file_type = tx_dam_db::getMediaExtension($mimeType['file_type']); // try first to get the mime type by extension with own array // I made the experience that it is a bit safer than with 'file' if ($this->setup['useInternalMimeList'] and $mimeType['file_type'] and isset($file_type['mime'])) { $mt = $file_type['mime']; if ($this->writeDevLog) { t3lib_div::devLog('getFileMimeType(): used builtin conversion table', 'tx_dam_indexing'); } // next try } elseif ($this->setup['useMimeContentType'] and function_exists('mime_content_type')) { // available in PHP 4.3.0 $mt = mime_content_type($pathname); if ($this->writeDevLog) { t3lib_div::devLog('getFileMimeType(): used mime_content_type()', 'tx_dam_indexing'); } } // last chance if ($this->setup['useFileCommand'] and (!$mt or $mt === 'application/octet-stream')) { $osType = TYPO3_OS; if (!($osType === 'WIN')) { if ($cmd = t3lib_exec::getCommand('file')) { $dummy = array(); $ret = false; $mimeTypeTxt = trim(exec($cmd . ' --mime ' . escapeshellarg($pathname), $dummy, $ret)); if (!$ret and strstr($mimeTypeTxt, tx_dam::file_basename($pathname) . ':')) { $a = explode(':', $mimeTypeTxt); $a = explode(';', trim($a[1])); //a[1]: text/plain, English; charset=iso-8859-1 $a = explode(',', trim($a[0])); $a = explode(' ', trim($a[0])); $mt = trim($a[0]); } } } if ($this->writeDevLog) { t3lib_div::devLog('getFileMimeType(): used t3lib_exec::getCommand(\'file\')', 'tx_dam_indexing'); } } $mtarr = explode('/', $mt); if (is_array($mtarr) && count($mtarr) == 2) { $mimeType['fulltype'] = $mt; $mimeType['file_mime_type'] = $mtarr[0]; $mimeType['file_mime_subtype'] = $mtarr[1]; } if ($mimeType['file_type'] == '') { $file_type = tx_dam_db::getMediaExtension('', $mimeType['fulltype']); $mimeType['file_type'] = $file_type['mime']; } if ($this->writeDevLog) { t3lib_div::devLog('getFileMimeType()', 'tx_dam_indexing', 0, $mimeType); } unset($mimeType['fulltype']); return $mimeType; }
/** * check the availability of external programs * * @param string comma list of programs 'perl,python,pdftotext' * @return boolean return FALSE if one program was not found */ function checkExec($progList) { $ret = TRUE; $progList = t3lib_div::trimExplode(',', $progList, 1); foreach ($progList as $prog) { if (!t3lib_exec::checkCommand($prog)) { // program not found $this->errorPush('External program not found: ' . $prog, T3_ERR_SV_PROG_NOT_FOUND); $ret = FALSE; } } return $ret; }
/** * Extracts PDF metadata using 'pdfinfo' * performs the service processing * * @param string Content which should be processed. * @param string Content type * @param array Configuration array * @return boolean */ function process($content = '', $type = '', $conf = array()) { $this->out = array(); if ($content) { $this->setInput($content, $type); } if ($inputFile = $this->getInputFile()) { $cmd = t3lib_exec::getCommand($this->info['exec']) . ' "' . $inputFile . '"'; $pdfmeta = ''; $ret = ''; exec($cmd, $pdfmeta, $ret); if (!$ret and is_array($pdfmeta)) { foreach ($pdfmeta as $line) { // Only request 2 elements because pdfinfo output might contain colons in $value list($name, $value) = explode(':', $line, 2); $name = trim($name); $value = trim($value); if ($value) { // ignore empty lines headers and empty entries switch ($name) { case 'Author': $this->out['fields']['creator'] = tx_svmetaextract_lib::forceUtf8($value); break; case 'Producer': $this->out['fields']['file_creator'] = tx_svmetaextract_lib::forceUtf8($value); break; case 'Title': $this->out['fields']['title'] = tx_svmetaextract_lib::forceUtf8($value); break; case 'Subject': $this->out['fields']['description'] = tx_svmetaextract_lib::forceUtf8($value); break; case 'Keywords': $this->out['fields']['keywords'] = tx_svmetaextract_lib::forceUtf8($value); break; case 'CreationDate': $this->out['fields']['date_cr'] = tx_svmetaextract_lib::parseDate($value); $this->out['fields']['file_ctime'] = tx_svmetaextract_lib::parseDate($value); break; case 'ModDate': $this->out['fields']['date_mod'] = tx_svmetaextract_lib::parseDate($value); $this->out['fields']['file_mtime'] = tx_svmetaextract_lib::parseDate($value); break; case 'Pages': case 'PageCount': $this->out['fields']['pages'] = intval($value); break; case 'Page Size': case 'Page size': // 595 x 842 pts (A4) $v = explode(' ', $value); $unitFrom = $v[3]; // TODO: create TCA to let user choose imperial/metric unit $unitTo = 'cm'; $this->out['fields']['width'] = (double) tx_svmetaextract_lib::convertUnit($v[0], $unitFrom, $unitTo); $this->out['fields']['height'] = (double) tx_svmetaextract_lib::convertUnit($v[2], $unitFrom, $unitTo); $this->out['fields']['width_unit'] = $unitTo; $this->out['fields']['height_unit'] = $unitTo; break; case 'PDF version': $this->out['fields']['file_type_version'] = $value; break; } } } } } else { $this->errorPush(T3_ERR_SV_NO_INPUT, 'No or empty input.'); } return $this->getLastError(); }
/** * This method assembles a list of all defined search paths * * @return string HTML to display */ protected function displaySearchPaths() { $content = '<h3 class="uppercase">' . $GLOBALS['LANG']->getLL('search_paths') . '</h3>'; $searchPaths = t3lib_exec::getPaths(true); if (count($searchPaths) == 0) { $content .= '<p>' . $GLOBALS['LANG']->getLL('no_search_paths') . '</p>'; } else { $content .= '<table cellspacing="1" cellpadding="2" border="0" class="tx_sv_reportlist">'; $content .= '<thead>'; $content .= '<tr class="bgColor2">'; $content .= '<td class="cell">' . $GLOBALS['LANG']->getLL('path') . '</td>'; $content .= '<td class="cell">' . $GLOBALS['LANG']->getLL('valid') . '</td>'; $content .= '</tr>'; $content .= '</thead>'; $content .= '<tbody>'; foreach ($searchPaths as $path => $isValid) { $content .= '<tr class="bgColor3-20">'; $content .= '<td class="cell">' . t3lib_div::fixWindowsFilePath($path) . '</td>'; $class = 'typo3-message message-error'; $message = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:no'); if ($isValid) { $class = 'typo3-message message-ok'; $message = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:yes'); } $content .= '<td class="cell ' . $class . '">' . $message . '</td>'; $content .= '</tr>'; } $content .= '</tbody>'; $content .= '</table>'; } return $content; }
/** * This method assembles a list of all defined executables search paths * * @return string HTML to display */ protected function renderExecutablesSearchPathList() { $searchPaths = t3lib_exec::getPaths(TRUE); $content = '<h3 class="divider">' . $GLOBALS['LANG']->getLL('search_paths') . '</h3>'; if (count($searchPaths) == 0) { $content .= '<p>' . $GLOBALS['LANG']->getLL('no_search_paths') . '</p>'; } else { $content .= ' <table cellspacing="1" cellpadding="2" border="0" class="tx_sv_reportlist paths"> <thead> <tr class="t3-row-header"> <td>' . $GLOBALS['LANG']->getLL('path') . '</td> <td>' . $GLOBALS['LANG']->getLL('valid') . '</td> </tr> </thead> <tbody>'; foreach ($searchPaths as $path => $isValid) { $pathAccessibleClass = 'typo3-message message-error'; $pathAccessible = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:no'); if ($isValid) { $pathAccessibleClass = 'typo3-message message-ok'; $pathAccessible = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:yes'); } $content .= ' <tr> <td class="first-cell ' . $pathAccessibleClass . '">' . t3lib_div::fixWindowsFilePath($path) . '</td> <td class="last-cell ' . $pathAccessibleClass . '">' . $pathAccessible . '</td> </tr>'; } $content .= ' </tbody> </table>'; } return $content; }