/** * Prints a row with data for the various extension listings * * @param string Extension key * @param array Extension information array * @param array Preset table cells, eg. install/uninstall icons. * @param string <tr> tag class * @param array Array with installed extension keys (as keys) * @param boolean If set, the list is coming from remote server. * @param string Alternative link URL * @return string HTML <tr> content */ function extensionListRow($extKey, $extInfo, $cells, $bgColorClass = '', $inst_list = array(), $import = 0, $altLinkUrl = '') { $stateColors = tx_em_Tools::getStateColors(); // Icon: $imgInfo = @getImageSize(tx_em_Tools::getExtPath($extKey, $extInfo['type']) . '/ext_icon.gif'); if (is_array($imgInfo)) { $cells[] = '<td><img src="' . $GLOBALS['BACK_PATH'] . tx_em_Tools::typeRelPath($extInfo['type']) . $extKey . '/ext_icon.gif' . '" ' . $imgInfo[3] . ' alt="" /></td>'; } elseif ($extInfo['_ICON']) { $cells[] = '<td>' . $extInfo['_ICON'] . '</td>'; } else { $cells[] = '<td><img src="clear.gif" width="1" height="1" alt="" /></td>'; } // Extension title: $cells[] = '<td nowrap="nowrap"><a href="' . htmlspecialchars($altLinkUrl ? $altLinkUrl : t3lib_div::linkThisScript(array('CMD[showExt]' => $extKey, 'SET[singleDetails]' => 'info'))) . '" title="' . htmlspecialchars($extInfo['EM_CONF']['description']) . '">' . t3lib_div::fixed_lgd_cs($extInfo['EM_CONF']['title'] ? htmlspecialchars($extInfo['EM_CONF']['title']) : '<em>' . $extKey . '</em>', 40) . '</a></td>'; // Based on the display mode you will see more or less details: if (!$this->parentObject->MOD_SETTINGS['display_details']) { $cells[] = '<td>' . htmlspecialchars(t3lib_div::fixed_lgd_cs($extInfo['EM_CONF']['description'], 400)) . '<br /><img src="clear.gif" width="300" height="1" alt="" /></td>'; $cells[] = '<td nowrap="nowrap">' . ($extInfo['EM_CONF']['author_email'] ? '<a href="mailto:' . htmlspecialchars($extInfo['EM_CONF']['author_email']) . '">' : '') . htmlspecialchars($extInfo['EM_CONF']['author']) . (htmlspecialchars($extInfo['EM_CONF']['author_email']) ? '</a>' : '') . ($extInfo['EM_CONF']['author_company'] ? '<br />' . htmlspecialchars($extInfo['EM_CONF']['author_company']) : '') . '</td>'; } elseif ($this->parentObject->MOD_SETTINGS['display_details'] == 2) { $cells[] = '<td nowrap="nowrap">' . $extInfo['EM_CONF']['priority'] . '</td>'; $cells[] = '<td nowrap="nowrap">' . implode('<br />', t3lib_div::trimExplode(',', $extInfo['EM_CONF']['modify_tables'], 1)) . '</td>'; $cells[] = '<td nowrap="nowrap">' . $extInfo['EM_CONF']['module'] . '</td>'; $cells[] = '<td nowrap="nowrap">' . ($extInfo['EM_CONF']['clearCacheOnLoad'] ? $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:yes') : '') . '</td>'; $cells[] = '<td nowrap="nowrap">' . ($extInfo['EM_CONF']['internal'] ? $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:yes') : '') . '</td>'; $cells[] = '<td nowrap="nowrap">' . ($extInfo['EM_CONF']['shy'] ? $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:yes') : '') . '</td>'; } elseif ($this->parentObject->MOD_SETTINGS['display_details'] == 3) { $techInfo = $this->install->makeDetailedExtensionAnalysis($extKey, $extInfo); $cells[] = '<td>' . $this->parentObject->extensionDetails->extInformationArray_dbReq($techInfo) . '</td>'; $cells[] = '<td nowrap="nowrap">' . (is_array($techInfo['TSfiles']) ? implode('<br />', $techInfo['TSfiles']) : '') . '</td>'; $cells[] = '<td nowrap="nowrap">' . (is_array($techInfo['flags']) ? implode('<br />', $techInfo['flags']) : '') . '</td>'; $cells[] = '<td nowrap="nowrap">' . (is_array($techInfo['moduleNames']) ? implode('<br />', $techInfo['moduleNames']) : '') . '</td>'; $cells[] = '<td nowrap="nowrap">' . ($techInfo['conf'] ? $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:yes') : '') . '</td>'; $cells[] = '<td>' . tx_em_Tools::rfw((t3lib_extMgm::isLoaded($extKey) && $techInfo['tables_error'] ? '<strong>' . $GLOBALS['LANG']->getLL('extInfoArray_table_error') . '</strong><br />' . $GLOBALS['LANG']->getLL('extInfoArray_missing_fields') : '') . (t3lib_extMgm::isLoaded($extKey) && $techInfo['static_error'] ? '<strong>' . $GLOBALS['LANG']->getLL('extInfoArray_static_table_error') . '</strong><br />' . $GLOBALS['LANG']->getLL('extInfoArray_static_tables_missing_empty') : '')) . '</td>'; } elseif ($this->parentObject->MOD_SETTINGS['display_details'] == 4) { $techInfo = $this->install->makeDetailedExtensionAnalysis($extKey, $extInfo, 1); $cells[] = '<td>' . (is_array($techInfo['locallang']) ? implode('<br />', $techInfo['locallang']) : '') . '</td>'; $cells[] = '<td>' . (is_array($techInfo['classes']) ? implode('<br />', $techInfo['classes']) : '') . '</td>'; $cells[] = '<td>' . (is_array($techInfo['errors']) ? tx_em_Tools::rfw(implode('<hr />', $techInfo['errors'])) : '') . '</td>'; $cells[] = '<td>' . (is_array($techInfo['NSerrors']) ? !t3lib_div::inList($this->parentObject->nameSpaceExceptions, $extKey) ? t3lib_utility_Debug::viewarray($techInfo['NSerrors']) : tx_em_Tools::dfw($GLOBALS['LANG']->getLL('extInfoArray_exception')) : '') . '</td>'; } elseif ($this->parentObject->MOD_SETTINGS['display_details'] == 5) { $currentMd5Array = $this->parentObject->extensionDetails->serverExtensionMD5array($extKey, $extInfo); $affectedFiles = ''; $msgLines = array(); $msgLines[] = $GLOBALS['LANG']->getLL('listRow_files') . ' ' . count($currentMd5Array); if (strcmp($extInfo['EM_CONF']['_md5_values_when_last_written'], serialize($currentMd5Array))) { $msgLines[] = tx_em_Tools::rfw('<br /><strong>' . $GLOBALS['LANG']->getLL('extInfoArray_difference_detected') . '</strong>'); $affectedFiles = tx_em_Tools::findMD5ArrayDiff($currentMd5Array, unserialize($extInfo['EM_CONF']['_md5_values_when_last_written'])); if (count($affectedFiles)) { $msgLines[] = '<br /><strong>' . $GLOBALS['LANG']->getLL('extInfoArray_modified_files') . '</strong><br />' . tx_em_Tools::rfw(implode('<br />', $affectedFiles)); } } $cells[] = '<td>' . implode('<br />', $msgLines) . '</td>'; } else { // Default view: $verDiff = $inst_list[$extKey] && tx_em_Tools::versionDifference($extInfo['EM_CONF']['version'], $inst_list[$extKey]['EM_CONF']['version'], $this->parentObject->versionDiffFactor); $cells[] = '<td nowrap="nowrap"><em>' . $extKey . '</em></td>'; $cells[] = '<td nowrap="nowrap">' . ($verDiff ? '<strong>' . tx_em_Tools::rfw(htmlspecialchars($extInfo['EM_CONF']['version'])) . '</strong>' : $extInfo['EM_CONF']['version']) . '</td>'; if (!$import) { // Listing extension on LOCAL server: // Extension Download: $cells[] = '<td nowrap="nowrap"><a href="' . htmlspecialchars(t3lib_div::linkThisScript(array('CMD[doBackup]' => 1, 'SET[singleDetails]' => 'backup', 'CMD[showExt]' => $extKey))) . '" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:download') . '">' . t3lib_iconWorks::getSpriteIcon('actions-system-extension-download') . '</a></td>'; // Manual download $manual = tx_em_Tools::typePath($extInfo['type']) . $extKey . '/doc/manual.sxw'; $manualRelPath = t3lib_div::resolveBackPath($this->parentObject->doc->backPath . tx_em_Tools::typeRelPath($extInfo['type'])) . $extKey . '/doc/manual.sxw'; if ($extInfo['EM_CONF']['docPath']) { $manual = tx_em_Tools::typePath($extInfo['type']) . $extKey . '/' . $extInfo['EM_CONF']['docPath'] . '/manual.sxw'; $manualRelPath = t3lib_div::resolveBackPath($this->parentObject->doc->backPath . tx_em_Tools::typeRelPath($extInfo['type'])) . $extKey . '/' . $extInfo['EM_CONF']['docPath'] . '/manual.sxw'; } $cells[] = '<td nowrap="nowrap">' . (tx_em_Tools::typePath($extInfo['type']) && @is_file($manual) ? '<a href="' . htmlspecialchars($manualRelPath) . '" target="_blank" title="' . $GLOBALS['LANG']->getLL('listRow_local_manual') . '">' . t3lib_iconWorks::getSpriteIcon('actions-system-extension-documentation') . '</a>' : '') . '</td>'; // Double installation (inclusion of an extension in more than one of system, global or local scopes) $doubleInstall = ''; if (strlen($extInfo['doubleInstall']) > 1) { // Separate the "SL" et al. string into an array and replace L by Local, G by Global etc. $doubleInstallations = str_replace(array('S', 'G', 'L'), array($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:sysext'), $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:globalext'), $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:localext')), str_split($extInfo['doubleInstall'])); // Last extension is the one actually used $usedExtension = array_pop($doubleInstallations); // Next extension is overridden $overriddenExtensions = array_pop($doubleInstallations); // If the array is not yet empty, the extension is actually installed 3 times (SGL) if (count($doubleInstallations) > 0) { $lastExtension = array_pop($doubleInstallations); $overriddenExtensions .= ' ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:and') . ' ' . $lastExtension; } $doubleInstallTitle = sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:double_inclusion'), $usedExtension, $overriddenExtensions); $doubleInstall = ' <strong><abbr title="' . $doubleInstallTitle . '">' . tx_em_Tools::rfw($extInfo['doubleInstall']) . '</abbr></strong>'; } $cells[] = '<td nowrap="nowrap">' . $this->types[$extInfo['type']] . $doubleInstall . '</td>'; } else { // Listing extensions from REMOTE repository: $inst_curVer = $inst_list[$extKey]['EM_CONF']['version']; if (isset($inst_list[$extKey])) { if ($verDiff) { $inst_curVer = '<strong>' . tx_em_Tools::rfw($inst_curVer) . '</strong>'; } } $cells[] = '<td nowrap="nowrap">' . t3lib_befunc::date($extInfo['EM_CONF']['lastuploaddate']) . '</td>'; $cells[] = '<td nowrap="nowrap">' . htmlspecialchars(t3lib_div::fixed_lgd_cs($extInfo['EM_CONF']['author'], $GLOBALS['BE_USER']->uc[titleLen])) . '</td>'; $cells[] = '<td nowrap="nowrap">' . $inst_curVer . '</td>'; $cells[] = '<td nowrap="nowrap">' . $this->api->typeLabels[$inst_list[$extKey]['type']] . (strlen($inst_list[$extKey]['doubleInstall']) > 1 ? '<strong> ' . tx_em_Tools::rfw($inst_list[$extKey]['doubleInstall']) . '</strong>' : '') . '</td>'; $cells[] = '<td nowrap="nowrap">' . ($extInfo['downloadcounter_all'] ? $extInfo['downloadcounter_all'] : ' ') . '/' . ($extInfo['downloadcounter'] ? $extInfo['downloadcounter'] : ' ') . '</td>'; } $cells[] = '<td nowrap="nowrap" class="extstate" style="background-color:' . $stateColors[$extInfo['EM_CONF']['state']] . ';">' . $this->states[$extInfo['EM_CONF']['state']] . '</td>'; } // show a different background through a different class for insecure (-1) extensions, // for unreviewed (0) and reviewed extensions (1), just use the regular class if ($this->xmlHandler->getReviewState($extKey, $extInfo['EM_CONF']['version']) < 0) { $bgclass = ' class="unsupported-ext"'; } else { $bgclass = ' class="' . ($bgColorClass ? $bgColorClass : 'em-listbg1') . '"'; } return ' <tr' . $bgclass . '> ' . implode(' ', $cells) . ' </tr>'; }
/** * Removes the current extension of $type and creates the base folder for the new one (which is going to be imported) * * @param array Data for imported extension * @param string Extension installation scope (L,G,S) * @param boolean If set, nothing will be deleted (neither directory nor files) * @return mixed Returns array on success (with extension directory), otherwise an error string. */ function clearAndMakeExtensionDir($importedData, $type, $dontDelete = 0) { if (!$importedData['extKey']) { return $GLOBALS['LANG']->getLL('clearMakeExtDir_no_ext_key'); } // Setting install path (L, G, S or fileadmin/_temp_/) $path = ''; switch ((string) $type) { case 'G': case 'L': $path = tx_em_Tools::typePath($type); $suffix = ''; // Creates the typo3conf/ext/ directory if it does NOT already exist: if ((string) $type == 'L' && !@is_dir($path)) { t3lib_div::mkdir($path); } break; default: if ($this->systemInstall && (string) $type == 'S') { $path = tx_em_Tools::typePath($type); $suffix = ''; } else { $path = PATH_site . $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'] . '_temp_/'; $suffix = '_' . date('dmy-His'); } break; } // If the install path is OK... if ($path && @is_dir($path)) { // Set extension directory: $extDirPath = $path . $importedData['extKey'] . $suffix . '/'; // Install dir was found, remove it then: if (@is_dir($extDirPath)) { if ($dontDelete) { return array($extDirPath); } $res = $this->removeExtDirectory($extDirPath); if ($res) { if (!$this->silentMode) { $flashMessage = t3lib_div::makeInstance('t3lib_FlashMessage', nl2br($res), sprintf($GLOBALS['LANG']->getLL('clearMakeExtDir_could_not_remove_dir'), $extDirPath), t3lib_FlashMessage::ERROR); return $flashMessage->render(); } return ''; } } // We go create... t3lib_div::mkdir($extDirPath); if (!is_dir($extDirPath)) { return sprintf($GLOBALS['LANG']->getLL('clearMakeExtDir_could_not_create_dir'), $extDirPath); } return array($extDirPath); } else { return sprintf($GLOBALS['LANG']->getLL('clearMakeExtDir_no_dir'), $path); } }
/** * Imports an extensions from the online repository * NOTICE: in version 4.0 this changed from "importExtFromRep_old($extRepUid,$loc,$uploadFlag=0,$directInput='',$recentTranslations=0,$incManual=0,$dontDelete=0)" * * @param string Extension key * @param string Version * @param string Install scope: "L" or "G" or "S" * @param boolean If true, extension is uploaded as file * @param boolean If true, extension directory+files will not be deleted before writing the new ones. That way custom files stored in the extension folder will be kept. * @param array Direct input array (like from kickstarter) * @return string Return false on success, returns error message if error. */ function importExtFromRep($extKey, $version, $loc, $uploadFlag = 0, $dontDelete = 0, $directInput = '') { $uploadSucceed = false; $uploadedTempFile = ''; if (is_array($directInput)) { $fetchData = array($directInput, ''); $loc = $loc === 'G' || $loc === 'S' ? $loc : 'L'; } elseif ($uploadFlag) { if (($uploadedTempFile = $this->CMD['alreadyUploaded']) || $_FILES['upload_ext_file']['tmp_name']) { // Read uploaded file: if (!$uploadedTempFile) { if (!is_uploaded_file($_FILES['upload_ext_file']['tmp_name'])) { t3lib_div::sysLog('Possible file upload attack: ' . $_FILES['upload_ext_file']['tmp_name'], 'Extension Manager', 3); $flashMessage = t3lib_div::makeInstance('t3lib_FlashMessage', $GLOBALS['LANG']->getLL('ext_import_file_not_uploaded'), '', t3lib_FlashMessage::ERROR); return $flashMessage->render(); } $uploadedTempFile = t3lib_div::upload_to_tempfile($_FILES['upload_ext_file']['tmp_name']); } $fileContent = t3lib_div::getUrl($uploadedTempFile); if (!$fileContent) { $flashMessage = t3lib_div::makeInstance('t3lib_FlashMessage', $GLOBALS['LANG']->getLL('ext_import_file_empty'), '', t3lib_FlashMessage::ERROR); return $flashMessage->render(); } // Decode file data: $fetchData = $this->terConnection->decodeExchangeData($fileContent); if (is_array($fetchData)) { $extKey = $fetchData[0]['extKey']; if ($extKey) { if (!$this->CMD['uploadOverwrite']) { $loc = $loc === 'G' || $loc === 'S' ? $loc : 'L'; $comingExtPath = tx_em_Tools::typePath($loc) . $extKey . '/'; if (@is_dir($comingExtPath)) { $flashMessage = t3lib_div::makeInstance('t3lib_FlashMessage', sprintf($GLOBALS['LANG']->getLL('ext_import_ext_present_no_overwrite'), $comingExtPath) . '<br />' . $GLOBALS['LANG']->getLL('ext_import_ext_present_nothing_done'), '', t3lib_FlashMessage::ERROR); return $flashMessage->render(); } // ... else go on, install... } // ... else go on, install... } else { $flashMessage = t3lib_div::makeInstance('t3lib_FlashMessage', $GLOBALS['LANG']->getLL('ext_import_no_key'), '', t3lib_FlashMessage::ERROR); return $flashMessage->render(); } } else { $flashMessage = t3lib_div::makeInstance('t3lib_FlashMessage', sprintf($GLOBALS['LANG']->getLL('ext_import_wrong_file_format'), $fetchData), '', t3lib_FlashMessage::ERROR); return $flashMessage->render(); } } else { $flashMessage = t3lib_div::makeInstance('t3lib_FlashMessage', $GLOBALS['LANG']->getLL('ext_import_no_file'), '', t3lib_FlashMessage::ERROR); return $flashMessage->render(); } } else { $this->xmlHandler->searchExtensionsXMLExact($extKey, '', '', true, true); // Fetch extension from TER: if (!strlen($version)) { $versions = array_keys($this->xmlHandler->extensionsXML[$extKey]['versions']); $version = end($versions); } $fetchData = $this->terConnection->fetchExtension($extKey, $version, $this->xmlHandler->extensionsXML[$extKey]['versions'][$version]['t3xfilemd5'], $this->getMirrorURL()); } // At this point the extension data should be present; so we want to write it to disc: $content = $this->install->installExtension($fetchData, $loc, $version, $uploadedTempFile, $dontDelete); $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('ext_import_results'), $content, 0, 1); if ($uploadSucceed && $uploadedTempFile) { t3lib_div::unlink_tempfile($uploadedTempFile); } return false; }
/** * Render extension update * * @var string $extKey * @return string $content */ public function getExtensionUpdate($extKey) { if (isset($GLOBALS['TYPO3_LOADED_EXT'][$extKey])) { /** @var $install tx_em_Install */ $install = t3lib_div::makeInstance('tx_em_Install'); /** @var $extension tx_em_Extensions_List */ $extension = t3lib_div::makeInstance('tx_em_Extensions_List'); $extPath = t3lib_extMgm::extPath($extKey); $type = tx_em_Tools::getExtTypeFromPath($extPath); $typePath = tx_em_Tools::typePath($type); $extInfo = array(); $extension->singleExtInfo($extKey, $typePath, $extInfo); $extInfo = $extInfo[0]; $extInfo['type'] = $extInfo['typeShort']; $update = $install->checkDBupdates($extKey, $extInfo); if ($update) { $update = $GLOBALS['LANG']->getLL('ext_details_new_tables_fields_select') . $update . '<br /><input type="submit" name="write" id="update-submit-' . htmlspecialchars($extKey) . '" value="' . htmlspecialchars($GLOBALS['LANG']->getLL('updatesForm_make_updates')) . '" />'; } return $update ? $update : $GLOBALS['LANG']->sL('LLL:EXT:em/language/locallang.xml:ext_details_dbUpToDate'); } else { return sprintf($GLOBALS['LANG']->sL('LLL:EXT:em/language/locallang.xml:msg_extNotInstalled'), htmlspecialchars($extKey)); } }