"TYPO3 4.0.1: typo3_src-4.0.1/typo3/mod/tools/em/class.em_index.php Source File", "datetime" => "Sat Dec 2 19:22:21 2006", "date" => "2 Dec 2006", "doxygenversion" => "1.4.6", "projectname" => "TYPO3 4.0.1", "projectnumber" => "4.0.1" ); get_header($doxygen_vars); ?>
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 1999-2005 Kasper Skaarhoj (kasperYYYY@typo3.com) 00006 * (c) 2005-2006 Karsten Dambekalns <karsten@typo3.org> 00007 * All rights reserved 00008 * 00009 * This script is part of the TYPO3 project. The TYPO3 project is 00010 * free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * The GNU General Public License can be found at 00016 * http://www.gnu.org/copyleft/gpl.html. 00017 * A copy is found in the textfile GPL.txt and important notices to the license 00018 * from the author is found in LICENSE.txt distributed with these scripts. 00019 * 00020 * 00021 * This script is distributed in the hope that it will be useful, 00022 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00023 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00024 * GNU General Public License for more details. 00025 * 00026 * This copyright notice MUST APPEAR in all copies of the script! 00027 ***************************************************************/ 00170 // Include classes needed: 00171 require_once(PATH_t3lib.'class.t3lib_tcemain.php'); 00172 require_once(PATH_t3lib.'class.t3lib_install.php'); 00173 require_once(PATH_t3lib.'class.t3lib_tsstyleconfig.php'); 00174 require_once(PATH_t3lib.'class.t3lib_scbase.php'); 00175 00176 require_once('class.em_xmlhandler.php'); 00177 require_once('class.em_terconnection.php'); 00178 require_once('class.em_unzip.php'); 00179 00180 // from tx_ter by Robert Lemke 00181 define('TX_TER_RESULT_EXTENSIONSUCCESSFULLYUPLOADED', '10504'); 00182 00183 define('EM_INSTALL_VERSION_MIN', 1); 00184 define('EM_INSTALL_VERSION_MAX', 2); 00185 define('EM_INSTALL_VERSION_STRICT', 3); 00186 00195 class SC_mod_tools_em_index extends t3lib_SCbase { 00196 00197 // Internal, static: 00198 var $versionDiffFactor = 1; // This means that version difference testing for import is detected for sub-versions only, not dev-versions. Default: 1000 00199 var $systemInstall = 0; // If "1" then installs in the sysext directory is allowed. Default: 0 00200 var $requiredExt = ''; // List of required extension (from TYPO3_CONF_VARS) 00201 var $maxUploadSize = 31457280; // Max size in bytes of extension upload to repository 00202 var $kbMax = 500; // Max size in kilobytes for files to be edited. 00203 var $doPrintContent = true; // If set (default), the function printContent() will echo the content which was collected in $this->content. You can set this to FALSE in order to echo content from elsewhere, fx. when using outbut buffering 00204 00209 var $defaultCategories = Array( 00210 'cat' => Array ( 00211 'be' => array(), 00212 'module' => array(), 00213 'fe' => array(), 00214 'plugin' => array(), 00215 'misc' => array(), 00216 'services' => array(), 00217 'templates' => array(), 00218 'example' => array(), 00219 'doc' => array() 00220 ) 00221 ); 00222 00227 var $categories = Array( 00228 'be' => 'Backend', 00229 'module' => 'Backend Modules', 00230 'fe' => 'Frontend', 00231 'plugin' => 'Frontend Plugins', 00232 'misc' => 'Miscellaneous', 00233 'services' => 'Services', 00234 'templates' => 'Templates', 00235 'example' => 'Examples', 00236 'doc' => 'Documentation' 00237 ); 00238 00243 var $states = Array ( 00244 'alpha' => 'Alpha', 00245 'beta' => 'Beta', 00246 'stable' => 'Stable', 00247 'experimental' => 'Experimental', 00248 'test' => 'Test', 00249 'obsolete' => 'Obsolete', 00250 ); 00251 00255 var $stateColors = Array ( 00256 'alpha' => '#d12438', 00257 'beta' => '#97b17e', 00258 'stable' => '#3bb65c', 00259 'experimental' => '#007eba', 00260 'test' => '#979797', 00261 'obsolete' => '#000000', 00262 ); 00263 00267 var $typeLabels = Array ( 00268 'S' => 'System', 00269 'G' => 'Global', 00270 'L' => 'Local', 00271 ); 00272 var $typeDescr = Array ( 00273 'S' => 'System extension (typo3/sysext/) - Always distributed with source code (Static).', 00274 'G' => 'Global extensions (typo3/ext/) - Available for shared source on server (Dynamic).', 00275 'L' => 'Local extensions (typo3conf/ext/) - Local for this TYPO3 installation only (Dynamic).', 00276 ); 00277 var $typePaths = Array(); // Also static, set in init() 00278 var $typeBackPaths = Array(); // Also static, set in init() 00279 00280 var $typeRelPaths = Array ( 00281 'S' => 'sysext/', 00282 'G' => 'ext/', 00283 'L' => '../typo3conf/ext/', 00284 ); 00285 00286 var $detailCols = Array ( 00287 0 => 2, 00288 1 => 5, 00289 2 => 6, 00290 3 => 6, 00291 4 => 4, 00292 5 => 1 00293 ); 00294 00295 var $fe_user = array( 00296 'username' => '', 00297 'password' => '', 00298 ); 00299 00300 var $privacyNotice = 'When you interact with the online repository, server information may be sent and stored in the repository for statistics.'; 00301 var $editTextExtensions = 'html,htm,txt,css,tmpl,inc,php,sql,conf,cnf,pl,pm,sh,xml,ChangeLog'; 00302 var $nameSpaceExceptions = 'beuser_tracking,design_components,impexp,static_file_edit,cms,freesite,quickhelp,classic_welcome,indexed_search,sys_action,sys_workflows,sys_todos,sys_messages,direct_mail,sys_stat,tt_address,tt_board,tt_calender,tt_guest,tt_links,tt_news,tt_poll,tt_rating,tt_products,setup,taskcenter,tsconfig_help,context_help,sys_note,tstemplate,lowlevel,install,belog,beuser,phpmyadmin,aboutmodules,imagelist,setup,taskcenter,sys_notepad,viewpage,adodb'; 00303 00304 00305 00306 00307 00308 // Default variables for backend modules 00309 var $MCONF = array(); // Module configuration 00310 var $MOD_MENU = array(); // Module menu items 00311 var $MOD_SETTINGS = array(); // Module session settings 00312 var $doc; // Document Template Object 00313 var $content; // Accumulated content 00314 00315 var $inst_keys = array(); // Storage of installed extensions 00316 var $gzcompress = 0; // Is set true, if system support compression. 00317 00318 var $terConnection; // instance of TER connection handler 00319 00320 // GPvars: 00321 var $CMD = array(); // CMD array 00322 var $listRemote; // If set, connects to remote repository 00323 var $lookUpStr; // Search string when listing local extensions 00324 00325 00326 00327 00328 /********************************* 00329 * 00330 * Standard module initialization 00331 * 00332 *********************************/ 00333 00339 function init() { 00340 global $BE_USER,$LANG,$BACK_PATH,$TYPO3_CONF_VARS; 00341 00342 // Setting paths of install scopes: 00343 $this->typePaths = Array ( 00344 'S' => TYPO3_mainDir.'sysext/', 00345 'G' => TYPO3_mainDir.'ext/', 00346 'L' => 'typo3conf/ext/' 00347 ); 00348 $this->typeBackPaths = Array ( 00349 'S' => '../../../', 00350 'G' => '../../../', 00351 'L' => '../../../../'.TYPO3_mainDir 00352 ); 00353 00354 // Setting module configuration: 00355 $this->MCONF = $GLOBALS['MCONF']; 00356 00357 // Setting GPvars: 00358 $this->CMD = t3lib_div::_GP('CMD'); 00359 $this->lookUpStr = t3lib_div::_GP('_lookUp'); 00360 $this->listRemote = t3lib_div::_GP('ter_connect'); 00361 $this->listRemote_search = t3lib_div::_GP('ter_search'); 00362 00363 00364 // Configure menu 00365 $this->menuConfig(); 00366 00367 // Setting internal static: 00368 if ($TYPO3_CONF_VARS['EXT']['allowSystemInstall']) $this->systemInstall = 1; 00369 $this->requiredExt = t3lib_div::trimExplode(',',$TYPO3_CONF_VARS['EXT']['requiredExt'],1); 00370 00371 00372 // Initialize helper object 00373 $this->terConnection = t3lib_div::makeInstance('SC_mod_tools_em_terconnection'); 00374 $this->terConnection->emObj =& $this; 00375 $this->terConnection->wsdlURL = $TYPO3_CONF_VARS['EXT']['em_wsdlURL']; 00376 $this->xmlhandler = t3lib_div::makeInstance('SC_mod_tools_em_xmlhandler'); 00377 $this->xmlhandler->emObj =& $this; 00378 $this->xmlhandler->useUnchecked = $this->MOD_SETTINGS['display_unchecked']; 00379 $this->xmlhandler->useObsolete = $this->MOD_SETTINGS['display_obsolete']; 00380 00381 // Initialize Document Template object: 00382 $this->doc = t3lib_div::makeInstance('noDoc'); 00383 $this->doc->backPath = $BACK_PATH; 00384 $this->doc->docType = 'xhtml_trans'; 00385 00386 // JavaScript 00387 $this->doc->JScode = $this->doc->wrapScriptTags(' 00388 script_ended = 0; 00389 function jumpToUrl(URL) { // 00390 window.location.href = URL; 00391 } 00392 '); 00393 $this->doc->form = '<form action="index.php" method="post" name="pageform">'; 00394 00395 // Descriptions: 00396 $this->descrTable = '_MOD_'.$this->MCONF['name']; 00397 if ($BE_USER->uc['edit_showFieldHelp']) { 00398 $LANG->loadSingleTableDescription($this->descrTable); 00399 } 00400 00401 // Setting username/password etc. for upload-user: 00402 $this->fe_user['username'] = $this->MOD_SETTINGS['fe_u']; 00403 $this->fe_user['password'] = $this->MOD_SETTINGS['fe_p']; 00404 parent::init(); 00405 $this->handleExternalFunctionValue('singleDetails'); 00406 } 00407 00419 function handleExternalFunctionValue($MM_key='function', $MS_value=NULL) { 00420 $MS_value = is_null($MS_value) ? $this->MOD_SETTINGS[$MM_key] : $MS_value; 00421 $externalItems = $this->getExternalItemConfig($this->MCONF['name'],$MM_key,$MS_value); 00422 if (is_array($externalItems)) $this->extClassConf = array_merge($externalItems,is_array($this->extClassConf)?$this->extClassConf:array()); 00423 if (is_array($this->extClassConf) && $this->extClassConf['path']) { 00424 $this->include_once[]=$this->extClassConf['path']; 00425 } 00426 } 00427 00433 function menuConfig() { 00434 global $BE_USER, $TYPO3_CONF_VARS; 00435 00436 // MENU-ITEMS: 00437 $this->MOD_MENU = array( 00438 'function' => array( 00439 0 => 'Loaded extensions', 00440 1 => 'Install extensions', 00441 2 => 'Import extensions', 00442 4 => 'Translation handling', 00443 3 => 'Settings', 00444 ), 00445 'listOrder' => array( 00446 'cat' => 'Category', 00447 'author_company' => 'Author', 00448 'state' => 'State', 00449 'type' => 'Type' 00450 ), 00451 'display_details' => array( 00452 1 => 'Details', 00453 0 => 'Description', 00454 2 => 'More details', 00455 00456 3 => 'Technical (takes time!)', 00457 4 => 'Validating (takes time!)', 00458 5 => 'Changed? (takes time!)', 00459 ), 00460 'display_shy' => '', 00461 'display_own' => '', 00462 'display_unchecked' => '', 00463 'display_obsolete' => '', 00464 00465 'singleDetails' => array( 00466 'info' => 'Information', 00467 'edit' => 'Edit files', 00468 'backup' => 'Backup/Delete', 00469 'dump' => 'Dump DB', 00470 'upload' => 'Upload to TER', 00471 'updateModule' => 'UPDATE!', 00472 ), 00473 'fe_u' => '', 00474 'fe_p' => '', 00475 00476 'mirrorListURL' => '', 00477 'rep_url' => '', 00478 'extMirrors' => '', 00479 'selectedMirror' => '', 00480 00481 'selectedLanguages' => '' 00482 ); 00483 00484 $this->MOD_MENU['singleDetails'] = $this->mergeExternalItems($this->MCONF['name'],'singleDetails',$this->MOD_MENU['singleDetails']); 00485 00486 // page/be_user TSconfig settings and blinding of menu-items 00487 if (!$BE_USER->getTSConfigVal('mod.'.$this->MCONF['name'].'.allowTVlisting')) { 00488 unset($this->MOD_MENU['display_details'][3]); 00489 unset($this->MOD_MENU['display_details'][4]); 00490 unset($this->MOD_MENU['display_details'][5]); 00491 } 00492 00493 // CLEANSE SETTINGS 00494 $this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::_GP('SET'), $this->MCONF['name']); 00495 00496 if ($this->MOD_SETTINGS['function']==2) { 00497 // If listing from online repository, certain items are removed though: 00498 unset($this->MOD_MENU['listOrder']['type']); 00499 unset($this->MOD_MENU['display_details'][2]); 00500 unset($this->MOD_MENU['display_details'][3]); 00501 unset($this->MOD_MENU['display_details'][4]); 00502 unset($this->MOD_MENU['display_details'][5]); 00503 $this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::_GP('SET'), $this->MCONF['name']); 00504 } 00505 parent::menuConfig(); 00506 } 00507 00513 function main() { 00514 global $BE_USER,$LANG,$TYPO3_CONF_VARS; 00515 00516 if (empty($this->MOD_SETTINGS['mirrorListURL'])) $this->MOD_SETTINGS['mirrorListURL'] = $TYPO3_CONF_VARS['EXT']['em_mirrorListURL']; 00517 00518 // Starting page: 00519 $this->content.=$this->doc->startPage('Extension Manager'); 00520 $this->content.=$this->doc->header('Extension Manager'); 00521 $this->content.=$this->doc->spacer(5); 00522 00523 // Commands given which is executed regardless of main menu setting: 00524 if ($this->CMD['showExt']) { // Show details for a single extension 00525 $this->showExtDetails($this->CMD['showExt']); 00526 } elseif ($this->CMD['requestInstallExtensions']) { // Show details for a single extension 00527 $this->requestInstallExtensions($this->CMD['requestInstallExtensions']); 00528 } elseif ($this->CMD['importExt'] || $this->CMD['uploadExt']) { // Imports an extension from online rep. 00529 $err = $this->importExtFromRep($this->CMD['importExt'],$this->CMD['extVersion'],$this->CMD['loc'],$this->CMD['uploadExt']); 00530 if ($err) { 00531 $this->content.=$this->doc->section('',$GLOBALS['TBE_TEMPLATE']->rfw($err)); 00532 } 00533 if(!$err && $this->CMD['importExt']) { 00534 $this->installTranslationsForExtension($this->CMD['importExt'], $this->getMirrorURL()); 00535 } 00536 } elseif ($this->CMD['importExtInfo']) { // Gets detailed information of an extension from online rep. 00537 $this->importExtInfo($this->CMD['importExtInfo'],$this->CMD['extVersion']); 00538 } else { // No command - we show what the menu setting tells us: 00539 00540 $menu = $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.menu').' '. 00541 t3lib_BEfunc::getFuncMenu(0,'SET[function]',$this->MOD_SETTINGS['function'],$this->MOD_MENU['function']); 00542 00543 if (t3lib_div::inList('0,1,2',$this->MOD_SETTINGS['function'])) { 00544 $menu.=' Group by: '.t3lib_BEfunc::getFuncMenu(0,'SET[listOrder]',$this->MOD_SETTINGS['listOrder'],$this->MOD_MENU['listOrder']). 00545 ' Show: '.t3lib_BEfunc::getFuncMenu(0,'SET[display_details]',$this->MOD_SETTINGS['display_details'],$this->MOD_MENU['display_details']).'<br />'; 00546 } 00547 if (t3lib_div::inList('0,1',$this->MOD_SETTINGS['function'])) { 00548 $menu.='Display shy extensions: '.t3lib_BEfunc::getFuncCheck(0,'SET[display_shy]',$this->MOD_SETTINGS['display_shy']); 00549 } 00550 if (t3lib_div::inList('2',$this->MOD_SETTINGS['function']) && strlen($this->fe_user['username'])) { 00551 $menu.='Only my extensions: '.t3lib_BEfunc::getFuncCheck(0,'SET[display_own]',$this->MOD_SETTINGS['display_own']); 00552 } 00553 if (t3lib_div::inList('0,1,2',$this->MOD_SETTINGS['function'])) { 00554 $menu.=' Show obsolete: '.t3lib_BEfunc::getFuncCheck(0,'SET[display_obsolete]',$this->MOD_SETTINGS['display_obsolete']); 00555 } 00556 00557 $this->content.=$this->doc->section('','<span class="nobr">'.$menu.'</span>'); 00558 $this->content.=$this->doc->spacer(10); 00559 00560 switch((string)$this->MOD_SETTINGS['function']) { 00561 case '0': 00562 // Lists loaded (installed) extensions 00563 $this->extensionList_loaded(); 00564 break; 00565 case '1': 00566 // Lists the installed (available) extensions 00567 $this->extensionList_installed(); 00568 break; 00569 case '2': 00570 // Lists the extensions available from online rep. 00571 $this->extensionList_import(); 00572 break; 00573 case '3': 00574 // Shows the settings screen 00575 $this->alterSettings(); 00576 break; 00577 case '4': 00578 // Allows to set the translation preferences and check the status 00579 $this->translationHandling(); 00580 break; 00581 default: 00582 $this->extObjContent(); 00583 break; 00584 } 00585 } 00586 00587 // Shortcuts: 00588 if ($BE_USER->mayMakeShortcut()) { 00589 $this->content.=$this->doc->spacer(20).$this->doc->section('',$this->doc->makeShortcutIcon('CMD','function',$this->MCONF['name'])); 00590 } 00591 } 00592 00598 function printContent() { 00599 if ($this->doPrintContent) { 00600 $this->content.= $this->doc->endPage(); 00601 echo $this->content; 00602 } 00603 } 00604 00605 00606 00607 00608 00609 00610 00611 00612 00613 00614 /********************************* 00615 * 00616 * Function Menu Applications 00617 * 00618 *********************************/ 00619 00625 function extensionList_loaded() { 00626 global $TYPO3_LOADED_EXT; 00627 00628 list($list,$cat) = $this->getInstalledExtensions(); 00629 00630 // Loaded extensions 00631 $content = ''; 00632 $lines = array(); 00633 00634 // Available extensions 00635 if (is_array($cat[$this->MOD_SETTINGS['listOrder']])) { 00636 $content=''; 00637 $lines=array(); 00638 $lines[] = $this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="1" height="1" alt="" /></td>')); 00639 00640 foreach($cat[$this->MOD_SETTINGS['listOrder']] as $catName => $extEkeys) { 00641 natcasesort($extEkeys); 00642 reset($extEkeys); 00643 $extensions = array(); 00644 while(list($extKey)=each($extEkeys)) { 00645 if (array_key_exists($extKey,$TYPO3_LOADED_EXT) && ($this->MOD_SETTINGS['display_shy'] || !$list[$extKey]['EM_CONF']['shy']) && $this->searchExtension($extKey,$list[$extKey])) { 00646 if (in_array($extKey, $this->requiredExt)) { 00647 $loadUnloadLink = '<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('Rq').'</strong>'; 00648 } else { 00649 $loadUnloadLink = '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1').'">'.$this->removeButton().'</a>'; 00650 } 00651 00652 $extensions[] = $this->extensionListRow($extKey,$list[$extKey],array('<td class="bgColor">'.$loadUnloadLink.'</td>')); 00653 } 00654 } 00655 if(count($extensions)) { 00656 $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><br /></td></tr>'; 00657 $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><img src="'.$GLOBALS['BACK_PATH'].'gfx/i/sysf.gif" width="18" height="16" align="top" alt="" /><strong>'.$this->listOrderTitle($this->MOD_SETTINGS['listOrder'],$catName).'</strong></td></tr>'; 00658 $lines[] = implode(chr(10),$extensions); 00659 } 00660 } 00661 } 00662 00663 $content.= t3lib_BEfunc::cshItem('_MOD_tools_em', 'loaded', $GLOBALS['BACK_PATH'],''); 00664 00665 $content.= 'Look up: <input type="text" name="_lookUp" value="'.htmlspecialchars($this->lookUpStr).'" /><input type="submit" value="Search"/><br/><br/>'; 00666 00667 $content.= ' 00668 00669 <!-- Loaded Extensions List --> 00670 <table border="0" cellpadding="2" cellspacing="1">'.implode('',$lines).'</table>'; 00671 00672 $this->content.=$this->doc->section('Loaded Extensions',$content,0,1); 00673 } 00674 00680 function extensionList_installed() { 00681 global $TYPO3_LOADED_EXT; 00682 00683 list($list,$cat)=$this->getInstalledExtensions(); 00684 00685 // Available extensions 00686 if (is_array($cat[$this->MOD_SETTINGS['listOrder']])) { 00687 $content=''; 00688 $lines=array(); 00689 $lines[]=$this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="18" height="1" alt="" /></td>')); 00690 00691 $allKeys=array(); 00692 foreach($cat[$this->MOD_SETTINGS['listOrder']] as $catName => $extEkeys) { 00693 if(!$this->MOD_SETTINGS['display_obsolete'] && $catName=='obsolete') continue; 00694 00695 $allKeys[]=''; 00696 $allKeys[]='TYPE: '.$catName; 00697 00698 natcasesort($extEkeys); 00699 reset($extEkeys); 00700 $extensions = array(); 00701 while(list($extKey)=each($extEkeys)) { 00702 $allKeys[]=$extKey; 00703 if ((!$list[$extKey]['EM_CONF']['shy'] || $this->MOD_SETTINGS['display_shy']) && 00704 ($list[$extKey]['EM_CONF']['state']!='obsolete' || $this->MOD_SETTINGS['display_obsolete']) 00705 && $this->searchExtension($extKey,$list[$extKey])) { 00706 $loadUnloadLink = t3lib_extMgm::isLoaded($extKey)? 00707 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->removeButton().'</a>': 00708 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[load]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->installButton().'</a>'; 00709 if (in_array($extKey,$this->requiredExt)) { 00710 $loadUnloadLink='<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('Rq').'</strong>'; 00711 } 00712 $theRowClass = t3lib_extMgm::isLoaded($extKey)? 'em-listbg1' : 'em-listbg2'; 00713 $extensions[]=$this->extensionListRow($extKey,$list[$extKey],array('<td class="bgColor">'.$loadUnloadLink.'</td>'),$theRowClass); 00714 } 00715 } 00716 if(count($extensions)) { 00717 $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><br /></td></tr>'; 00718 $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><img src="'.$GLOBALS['BACK_PATH'].'gfx/i/sysf.gif" width="18" height="16" align="top" alt="" /><strong>'.$this->listOrderTitle($this->MOD_SETTINGS['listOrder'],$catName).'</strong></td></tr>'; 00719 $lines[] = implode(chr(10),$extensions); 00720 } 00721 } 00722 00723 $content.=' 00724 00725 00726 <!-- 00727 EXTENSION KEYS: 00728 00729 '.trim(implode(chr(10),$allKeys)).' 00730 00731 --> 00732 00733 '; 00734 00735 $content.= t3lib_BEfunc::cshItem('_MOD_tools_em', 'avail', $GLOBALS['BACK_PATH'],'|<br/>'); 00736 $content.= 'If you want to use an extension in TYPO3, you should simply click the "plus" button '.$this->installButton().' . <br /> 00737 Installed extensions can also be removed again - just click the remove button '.$this->removeButton().' .<br /><br />'; 00738 00739 $content.= 'Look up: <input type="text" name="_lookUp" value="'.htmlspecialchars($this->lookUpStr).'" /><input type="submit" value="Search"/><br/><br/>'; 00740 00741 $content.= '<table border="0" cellpadding="2" cellspacing="1">'.implode('',$lines).'</table>'; 00742 00743 $this->content.=$this->doc->section('Available Extensions - Grouped by: '.$this->MOD_MENU['listOrder'][$this->MOD_SETTINGS['listOrder']],$content,0,1); 00744 } 00745 } 00746 00752 function extensionList_import() { 00753 global $TYPO3_LOADED_EXT; 00754 $content=''; 00755 00756 // Listing from online repository: 00757 if ($this->listRemote) { 00758 list($inst_list,) = $this->getInstalledExtensions(); 00759 $this->inst_keys = array_flip(array_keys($inst_list)); 00760 00761 $this->detailCols[1]+=6; 00762 00763 // see if we have an extensionlist at all 00764 $this->xmlhandler->loadExtensionsXML(); 00765 if (!count($this->xmlhandler->extensionsXML)) { 00766 $content .= $this->fetchMetaData('extensions'); 00767 } 00768 00769 if($this->MOD_SETTINGS['display_own'] && strlen($this->fe_user['username'])) { 00770 $this->xmlhandler->searchExtensionsXML($this->listRemote_search, $this->fe_user['username']); 00771 } else { 00772 $this->xmlhandler->searchExtensionsXML($this->listRemote_search); 00773 } 00774 if (count($this->xmlhandler->extensionsXML)) { 00775 list($list,$cat) = $this->prepareImportExtList(); 00776 00777 // Available extensions 00778 if (is_array($cat[$this->MOD_SETTINGS['listOrder']])) { 00779 $lines=array(); 00780 $lines[]=$this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="18" height="1" alt="" /></td>'),1); 00781 00782 foreach($cat[$this->MOD_SETTINGS['listOrder']] as $catName => $extEkeys) { 00783 if (count($extEkeys)) { 00784 $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><br /></td></tr>'; 00785 $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><img src="'.$GLOBALS['BACK_PATH'].'gfx/i/sysf.gif" width="18" height="16" align="top" alt="" /><strong>'.$this->listOrderTitle($this->MOD_SETTINGS['listOrder'],$catName).'</strong></td></tr>'; 00786 00787 natcasesort($extEkeys); 00788 reset($extEkeys); 00789 while(list($extKey)=each($extEkeys)) { 00790 $version = array_keys($list[$extKey]['versions']); 00791 $version = end($version); 00792 $ext = $list[$extKey]['versions'][$version]; 00793 $ext['downloadcounter_all'] = $list[$extKey]['downloadcounter']; 00794 $ext['_ICON'] = $list[$extKey]['_ICON']; 00795 $loadUnloadLink=''; 00796 if ($inst_list[$extKey]['type']!='S' && (!isset($inst_list[$extKey]) || $this->versionDifference($version,$inst_list[$extKey]['EM_CONF']['version'],$this->versionDiffFactor))) { 00797 if (isset($inst_list[$extKey])) { 00798 // update 00799 $loc= ($inst_list[$extKey]['type']=='G'?'G':'L'); 00800 $aUrl = 'index.php?CMD[importExt]='.$extKey.'&CMD[extVersion]='.$version.'&CMD[loc]='.$loc; 00801 $loadUnloadLink.= '<a href="'.htmlspecialchars($aUrl).'"><img src="'.$GLOBALS['BACK_PATH'].'gfx/import_update.gif" width="12" height="12" title="Update the extension in \''.($loc=='G'?'global':'local').'\' from online repository to server" alt="" /></a>'; 00802 } else { 00803 // import 00804 $aUrl = 'index.php?CMD[importExt]='.$extKey.'&CMD[extVersion]='.$version.'&CMD[loc]=L'; 00805 $loadUnloadLink.= '<a href="'.htmlspecialchars($aUrl).'"><img src="'.$GLOBALS['BACK_PATH'].'gfx/import.gif" width="12" height="12" title="Import this extension to \'local\' dir typo3conf/ext/ from online repository." alt="" /></a>'; 00806 } 00807 } else { 00808 $loadUnloadLink = ' '; 00809 } 00810 00811 if (isset($inst_list[$extKey])) { 00812 $theRowClass = t3lib_extMgm::isLoaded($extKey) ? 'em-listbg1' : 'em-listbg2'; 00813 } else { 00814 $theRowClass = 'em-listbg3'; 00815 } 00816 00817 $lines[]=$this->extensionListRow($extKey,$ext,array('<td class="bgColor">'.$loadUnloadLink.'</td>'),$theRowClass,$inst_list,1,'index.php?CMD[importExtInfo]='.rawurlencode($extKey)); 00818 } 00819 } 00820 } 00821 00822 // CSH: 00823 $content.= t3lib_BEfunc::cshItem('_MOD_tools_em', 'import_ter', $GLOBALS['BACK_PATH'],'|<br/>'); 00824 $onsubmit = "window.location.href='index.php?ter_connect=1&ter_search='+escape(this.elements['_lookUp'].value);return false;"; 00825 $content.= '</form><form action="index.php" method="post" onsubmit="'.htmlspecialchars($onsubmit).'">List or look up extensions<br /> 00826 <input type="text" name="_lookUp" value="'.htmlspecialchars($this->listRemote_search).'" /> <input type="submit" value="Look up" /><br /><br />'; 00827 00828 $content.= ' 00829 00830 <!-- TER Extensions list --> 00831 <table border="0" cellpadding="2" cellspacing="1">'.implode(chr(10),$lines).'</table>'; 00832 $content.= '<br /><br /><strong>PRIVACY NOTICE:</strong><br /> '.$this->privacyNotice; 00833 00834 $this->content.=$this->doc->section('Extensions in TYPO3 Extension Repository (online) - Grouped by: '.$this->MOD_MENU['listOrder'][$this->MOD_SETTINGS['listOrder']],$content,0,1); 00835 00836 // Plugins which are NOT uploaded to repository but present on this server. 00837 $content=''; 00838 $lines=array(); 00839 if (count($this->inst_keys)) { 00840 reset($this->inst_keys); 00841 while(list($extKey)=each($this->inst_keys)) { 00842 if(strlen($this->listRemote_search) && !stristr($extKey,$this->listRemote_search)) continue; 00843 00844 $loadUnloadLink = t3lib_extMgm::isLoaded($extKey)? 00845 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->removeButton().'</a>': 00846 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[load]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->installButton().'</a>'; 00847 if (in_array($extKey,$this->requiredExt)) $loadUnloadLink='<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('Rq').'</strong>'; 00848 $lines[]=$this->extensionListRow($extKey,$inst_list[$extKey],array('<td class="bgColor">'.$loadUnloadLink.'</td>'),t3lib_extMgm::isLoaded($extKey)?'em-listbg1':'em-listbg2'); 00849 } 00850 } 00851 if(count($lines)) { 00852 $content.= 'This is the list of extensions which are available locally, but not in the repository.<br />The might be user-defined and should be prepended user_ then.<br /><br />'; 00853 $content.= '<table border="0" cellpadding="2" cellspacing="1">'. 00854 $this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="18" height="1" alt="" /></td>')). 00855 implode('',$lines).'</table>'; 00856 $this->content.=$this->doc->spacer(20); 00857 $this->content.=$this->doc->section('Extensions found only on this server',$content,0,1); 00858 } 00859 } 00860 } else { 00861 $content.= t3lib_BEfunc::cshItem('_MOD_tools_em', 'import_ter', $GLOBALS['BACK_PATH'],'|<br/>'); 00862 $onsubmit = "window.location.href='index.php?ter_connect=1&ter_search='+escape(this.elements['_lookUp'].value);return false;"; 00863 $content.= '</form><form action="index.php" method="post" onsubmit="'.htmlspecialchars($onsubmit).'">List or look up extensions<br /> 00864 <input type="text" name="_lookUp" value="'.htmlspecialchars($this->listRemote_search).'" /> <input type="submit" value="Look up" /><br /><br />'; 00865 00866 $content.= '<p><strong>No matching extensions found.</strong></p>'; 00867 00868 $content.= '<br /><br /><strong>PRIVACY NOTICE:</strong><br /> '.$this->privacyNotice; 00869 $this->content.=$this->doc->section('Extensions in TYPO3 Extension Repository (online) - Grouped by: '.$this->MOD_MENU['listOrder'][$this->MOD_SETTINGS['listOrder']],$content,0,1); 00870 } 00871 } else { 00872 // CSH 00873 $content.= t3lib_BEfunc::cshItem('_MOD_tools_em', 'import', $GLOBALS['BACK_PATH'],'|<br/>'); 00874 00875 $onsubmit = "window.location.href='index.php?ter_connect=1&ter_search='+escape(this.elements['_lookUp'].value);return false;"; 00876 $content.= '</form><form action="index.php" method="post" onsubmit="'.htmlspecialchars($onsubmit).'">List or look up <strong'.($this->MOD_SETTINGS['display_unchecked']?' style="color:#900;">all':' style="color:#090;">reviewed').'</strong> extensions<br /> 00877 <input type="text" name="_lookUp" value="" /> <input type="submit" value="Look up" /><br /><br />'; 00878 00879 if ($this->CMD['fetchMetaData']) { // fetches mirror/extension data from online rep. 00880 $content .= $this->fetchMetaData($this->CMD['fetchMetaData']); 00881 } else { 00882 $onCLick = "window.location.href='index.php?CMD[fetchMetaData]=extensions';return false;"; 00883 $content.= 'Connect to the current mirror and retrieve the current list of available plugins from the TYPO3 Extension Repository.<br /> 00884 <input type="submit" value="Retrieve/Update" onclick="'.htmlspecialchars($onCLick).'" />'; 00885 if(is_file(PATH_site.'typo3temp/extensions.bin')) { 00886 $content .= ' (last update: '.date('Y-m-d H:i',filemtime(PATH_site.'typo3temp/extensions.bin')).')'; 00887 } 00888 } 00889 00890 $content .= '<br /><br /><strong>PRIVACY NOTICE:</strong><br />'.$this->privacyNotice; 00891 00892 $this->content.=$this->doc->section('Extensions in TYPO3 Extension Repository',$content,0,1); 00893 } 00894 00895 // Upload: 00896 if ($this->importAtAll()) { 00897 $content= '</form><form action="index.php" enctype="'.$GLOBALS['TYPO3_CONF_VARS']['SYS']['form_enctype'].'" method="post"> 00898 Upload extension file (.t3x):<br /> 00899 <input type="file" size="60" name="upload_ext_file" /><br /> 00900 ... to location:<br /> 00901 <select name="CMD[loc]">'; 00902 if ($this->importAsType('L')) $content.='<option value="L">Local (../typo3conf/ext/)</option>'; 00903 if ($this->importAsType('G')) $content.='<option value="G">Global (typo3/ext/)</option>'; 00904 if ($this->importAsType('S')) $content.='<option value="S">System (typo3/sysext/)</option>'; 00905 $content.='</select><br /> 00906 <input type="checkbox" value="1" name="CMD[uploadOverwrite]" /> Overwrite any existing extension!<br /> 00907 <input type="submit" name="CMD[uploadExt]" value="Upload extension file" /><br /> 00908 '; 00909 } else $content=$this->noImportMsg(); 00910 00911 $this->content.=$this->doc->spacer(20); 00912 $this->content.=$this->doc->section('Upload extension file directly (.t3x):',$content,0,1); 00913 } 00914 00920 function alterSettings() { 00921 00922 // Prepare the HTML output: 00923 $content.= ' 00924 '.t3lib_BEfunc::cshItem('_MOD_tools_em', 'settings', $GLOBALS['BACK_PATH'],'|<br/>').' 00925 <fieldset><legend>Security Settings</legend> 00926 <table border="0" cellpadding="2" cellspacing="2"> 00927 <tr class="bgColor4"> 00928 <td>Enable extensions without review (basic security check):</td> 00929 <td>'.t3lib_BEfunc::getFuncCheck(0,'SET[display_unchecked]',$this->MOD_SETTINGS['display_unchecked']).'</td> 00930 </tr> 00931 </table> 00932 <strong>Notice:</strong> Make sure you know what consequences enabling this checkbox might have. Check the <a href="http://typo3.org/extensions/what-are-reviews/" target="_blank">information on typo3.org about security reviewing</a>! 00933 </fieldset> 00934 <br /> 00935 <br /> 00936 <fieldset><legend>User Settings</legend> 00937 <table border="0" cellpadding="2" cellspacing="2"> 00938 <tr class="bgColor4"> 00939 <td>Enter repository username:</td> 00940 <td><input type="text" name="SET[fe_u]" value="'.htmlspecialchars($this->MOD_SETTINGS['fe_u']).'" /></td> 00941 </tr> 00942 <tr class="bgColor4"> 00943 <td>Enter repository password:</td> 00944 <td><input type="password" name="SET[fe_p]" value="'.htmlspecialchars($this->MOD_SETTINGS['fe_p']).'" /></td> 00945 </tr> 00946 </table> 00947 <strong>Notice:</strong> This is <em>not</em> your password to the TYPO3 backend! This user information is what is needed to log in at typo3.org with your account there! 00948 </fieldset> 00949 <br /> 00950 <br /> 00951 <fieldset><legend>Mirror selection</legend> 00952 <table border="0" cellpadding="2" cellspacing="2"> 00953 <tr class="bgColor4"> 00954 <td>Enter mirror list URL:</td> 00955 <td><input type="text" size="50" name="SET[mirrorListURL]" value="'.htmlspecialchars($this->MOD_SETTINGS['mirrorListURL']).'" /></td> 00956 </tr> 00957 </table> 00958 <br /> 00959 <p>Select a mirror from below. This list is built from the online mirror list retrieved from the URL above.<br /><br /></p> 00960 <fieldset><legend>Mirror list</legend>'; 00961 if(!empty($this->MOD_SETTINGS['mirrorListURL'])) { 00962 if ($this->CMD['fetchMetaData']) { // fetches mirror/extension data from online rep. 00963 $content .= $this->fetchMetaData($this->CMD['fetchMetaData']); 00964 } else { 00965 $content.= '<a href="index.php?CMD[fetchMetaData]=mirrors">Click here to reload the list.</a>'; 00966 } 00967 } 00968 $content .= '<br /> 00969 <table cellspacing="4" style="text-align:left; vertical-alignment:top;"> 00970 <tr><td>Use</td><td>Name</td><td>URL</td><td>Country</td><td>Sponsored by</td></tr> 00971 '; 00972 00973 if (!strlen($this->MOD_SETTINGS['extMirrors'])) $this->fetchMetaData('mirrors'); 00974 $extMirrors = unserialize($this->MOD_SETTINGS['extMirrors']); 00975 $extMirrors[''] = array('title'=>'Random (recommended!)'); 00976 ksort($extMirrors); 00977 if(is_array($extMirrors)) { 00978 foreach($extMirrors as $k => $v) { 00979 if(isset($v['sponsor'])) { 00980 $sponsor = '<a href="'.htmlspecialchars($v['sponsor']['link']).'" target="_new"><img src="'.$v['sponsor']['logo'].'" title="'.htmlspecialchars($v['sponsor']['name']).'" alt="'.htmlspecialchars($v['sponsor']['name']).'" /></a>'; 00981 } 00982 $selected = ($this->MOD_SETTINGS['selectedMirror']==$k) ? 'checked="checked"' : ''; 00983 $content.='<tr class="bgColor4"> 00984 <td><input type="radio" name="SET[selectedMirror]" value="'.$k.'" '.$selected.'/></td><td>'.htmlspecialchars($v['title']).'</td><td>'.htmlspecialchars($v['host'].$v['path']).'</td><td>'.$v['country'].'</td><td>'.$sponsor.'</td></tr>'; 00985 } 00986 } 00987 $content.= ' 00988 </table> 00989 </fieldset> 00990 <br /> 00991 <table border="0" cellpadding="2" cellspacing="2"> 00992 <tr class="bgColor4"> 00993 <td>Enter repository URL:</td> 00994 <td><input type="text" size="50" name="SET[rep_url]" value="'.htmlspecialchars($this->MOD_SETTINGS['rep_url']).'" /></td> 00995 </tr> 00996 </table> 00997 00998 If you set a repository URL, this overrides the use of a mirror. Use this to select a specific (private) repository.<br /> 00999 </fieldset> 01000 <br /> 01001 <input type="submit" value="Update" /> 01002 '; 01003 01004 $this->content.=$this->doc->section('Repository settings',$content,0,1); 01005 } 01006 01012 function translationHandling() { 01013 global $LANG, $TYPO3_LOADED_EXT; 01014 $LANG->includeLLFile('EXT:setup/mod/locallang.xml'); 01015 01016 $incoming = t3lib_div::_POST('SET'); 01017 if(isset($incoming['selectedLanguages']) && is_array($incoming['selectedLanguages'])) { 01018 t3lib_BEfunc::getModuleData($this->MOD_MENU, array('selectedLanguages' => serialize($incoming['selectedLanguages'])), $this->MCONF['name'], '', 'selectedLanguages'); 01019 $this->MOD_SETTINGS['selectedLanguages'] = serialize($incoming['selectedLanguages']); 01020 } 01021 01022 $selectedLanguages = unserialize($this->MOD_SETTINGS['selectedLanguages']); 01023 if(count($selectedLanguages)==1 && empty($selectedLanguages[0])) $selectedLanguages = array(); 01024 $theLanguages = t3lib_div::trimExplode('|',TYPO3_languages); 01025 foreach($theLanguages as $val) { 01026 if ($val!='default') { 01027 $localLabel = ' - ['.htmlspecialchars($GLOBALS['LOCAL_LANG']['default']['lang_'.$val]).']'; 01028 $selected = (is_array($selectedLanguages) && in_array($val, $selectedLanguages)) ? ' selected="selected"' : ''; 01029 $opt[$GLOBALS['LOCAL_LANG']['default']['lang_'.$val].'--'.$val]=' 01030 <option value="'.$val.'"'.$selected.'>'.$LANG->getLL('lang_'.$val,1).$localLabel.'</option>'; 01031 } 01032 } 01033 ksort($opt); 01034 01035 // Prepare the HTML output: 01036 $content.= ' 01037 '.t3lib_BEfunc::cshItem('_MOD_tools_em', 'translation', $GLOBALS['BACK_PATH'],'|<br/>').' 01038 <fieldset><legend>Translation Settings</legend> 01039 <table border="0" cellpadding="2" cellspacing="2"> 01040 <tr class="bgColor4"> 01041 <td>Languages to fetch:</td> 01042 <td> 01043 <select name="SET[selectedLanguages][]" multiple="multiple" size="10"> 01044 <option></option>'. 01045 implode('',$opt).' 01046 </select> 01047 </td> 01048 </tr> 01049 </table> 01050 <br /> 01051 <p>For the selected languages the EM tries to download and install translation files if available, whenever an extension is installed. (This replaces the <code>csh_*</code> extensions that were used to install core translations before TYPO3 version 4!)<br /> 01052 <br />To request an update/install for already loaded extensions, see below.</p> 01053 </fieldset> 01054 <br /> 01055 <input type="submit" value="Save selection" /> 01056 <br /> 01057 </fieldset>'; 01058 01059 $this->content.=$this->doc->section('Translation settings',$content,0,1); 01060 01061 if(count($selectedLanguages)>0) { 01062 $mirrorURL = $this->getMirrorURL(); 01063 $content = '<input type="button" value="Check status against repository" onclick="document.location.href=\''.t3lib_div::linkThisScript(array('l10n'=>'check')).'\'" /> <input type="button" value="Update from repository" onclick="document.location.href=\''.t3lib_div::linkThisScript(array('l10n'=>'update')).'\'" />'; 01064 01065 if(t3lib_div::_GET('l10n') == 'check') { 01066 $loadedExtensions = array_keys($TYPO3_LOADED_EXT); 01067 $loadedExtensions = array_diff($loadedExtensions,array('_CACHEFILE')); 01068 01069 // Override content output - we now do that ourself: 01070 echo ($this->content . $this->doc->section('Translation status',$content,0,1)); 01071 $this->doPrintContent = FALSE; 01072 flush(); 01073 01074 echo ' 01075 <br /> 01076 <br /> 01077 <p id="progress-message"> 01078 Checking translation status, please wait ... 01079 </p> 01080 <br /> 01081 <div style="width:100%; height:20px; border: 1px solid black;"> 01082 <div id="progress-bar" style="float: left; width: 0%; height: 20px; background-color:green;"> </div> 01083 <div id="transparent-bar" style="float: left; width: 100%; height: 20px; background-color:'.$this->doc->bgColor2.';"> </div> 01084 </div> 01085 <br /> 01086 <br /><p>This table shows the status of the loaded extension\'s translations.</p><br /> 01087 <table border="0" cellpadding="2" cellspacing="2"> 01088 <tr class="bgColor2"><td>Extension key</td> 01089 '; 01090 01091 foreach($selectedLanguages as $lang) { 01092 echo ('<td>'.$LANG->getLL('lang_'.$lang,1).'</td>'); 01093 } 01094 echo ('</tr>'); 01095 01096 $counter = 1; 01097 foreach($loadedExtensions as $extKey) { 01098 01099 $percentDone = intval (($counter / count($loadedExtensions)) * 100); 01100 echo (' 01101 <script> 01102 document.getElementById("progress-bar").style.width = "'.$percentDone.'%"; 01103 document.getElementById("transparent-bar").style.width = "'.(100-$percentDone).'%"; 01104 document.getElementById("progress-message").firstChild.data="Checking translation status for extension \"'.$extKey.'\" ..."; 01105 </script> 01106 '); 01107 01108 flush(); 01109 $translationStatusArr = $this->terConnection->fetchTranslationStatus($extKey,$mirrorURL); 01110 01111 echo ('<tr class="bgColor4"><td>'.$extKey.'</td>'); 01112 foreach($selectedLanguages as $lang) { 01113 // remote unknown -> keine l10n 01114 if(!isset($translationStatusArr[$lang])) { 01115 echo ('<td title="No translation available">N/A</td>'); 01116 continue; 01117 } 01118 // determine local md5 from zip 01119 if(is_file(PATH_site.'typo3temp/'.$extKey.'-l10n-'.$lang.'.zip')) { 01120 $localmd5 = md5_file(PATH_site.'typo3temp/'.$extKey.'-l10n-'.$lang.'.zip'); 01121 } else { 01122 echo ('<td title="Not installed / Unknown" style="background-color:#ff0">???</td>'); 01123 continue; 01124 } 01125 // local!=remote -> needs update 01126 if($localmd5 != $translationStatusArr[$lang]['md5']) { 01127 echo ('<td title="Needs update" style="background-color:#ff0">UPD</td>'); 01128 continue; 01129 } 01130 echo ('<td title="Is up to date" style="background-color:#69a550">OK</td>'); 01131 } 01132 echo ('</tr>'); 01133 01134 $counter ++; 01135 } 01136 echo '</table> 01137 <script> 01138 document.getElementById("progress-message").firstChild.data="Check done."; 01139 </script> 01140 '; 01141 echo $this->doc->endPage(); 01142 return ''; 01143 01144 } elseif(t3lib_div::_GET('l10n') == 'update') { 01145 $loadedExtensions = array_keys($TYPO3_LOADED_EXT); 01146 $loadedExtensions = array_diff($loadedExtensions,array('_CACHEFILE')); 01147 01148 // Override content output - we now do that ourself: 01149 echo ($this->content . $this->doc->section('Translation status',$content,0,1)); 01150 $this->doPrintContent = FALSE; 01151 flush(); 01152 01153 echo (' 01154 <br /> 01155 <br /> 01156 <p id="progress-message"> 01157 Updating translations, please wait ... 01158 </p> 01159 <br /> 01160 <div style="width:100%; height:20px; border: 1px solid black;"> 01161 <div id="progress-bar" style="float: left; width: 0%; height: 20px; background-color:green;"> </div> 01162 <div id="transparent-bar" style="float: left; width: 100%; height: 20px; background-color:'.$this->doc->bgColor2.';"> </div> 01163 </div> 01164 <br /> 01165 <br /><p>This table shows the update results of the loaded extension\'s translations.<br /> 01166 <em>If you want to force a full check/update, delete the l10n zip-files from the typo3temp folder.</em></p><br /> 01167 <table border="0" cellpadding="2" cellspacing="2"> 01168 <tr class="bgColor2"><td>Extension key</td> 01169 '); 01170 01171 foreach($selectedLanguages as $lang) { 01172 echo '<td>'.$LANG->getLL('lang_'.$lang,1).'</td>'; 01173 } 01174 echo '</tr>'; 01175 01176 $counter = 1; 01177 foreach($loadedExtensions as $extKey) { 01178 $percentDone = intval (($counter / count($loadedExtensions)) * 100); 01179 echo (' 01180 <script> 01181 document.getElementById("progress-bar").style.width = "'.$percentDone.'%"; 01182 document.getElementById("transparent-bar").style.width = "'.(100-$percentDone).'%"; 01183 document.getElementById("progress-message").firstChild.data="Updating translation for extension \"'.$extKey.'\" ..."; 01184 </script> 01185 '); 01186 01187 flush(); 01188 $translationStatusArr = $this->terConnection->fetchTranslationStatus($extKey,$mirrorURL); 01189 01190 echo ('<tr class="bgColor4"><td>'.$extKey.'</td>'); 01191 foreach($selectedLanguages as $lang) { 01192 // remote unknown -> no l10n available 01193 if(!isset($translationStatusArr[$lang])) { 01194 echo ('<td title="No translation available">N/A</td>'); 01195 continue; 01196 } 01197 // determine local md5 from zip 01198 if(is_file(PATH_site.'typo3temp/'.$extKey.'-l10n-'.$lang.'.zip')) { 01199 $localmd5 = md5_file(PATH_site.'typo3temp/'.$extKey.'-l10n-'.$lang.'.zip'); 01200 } else { 01201 $localmd5 = 'zzz'; 01202 } 01203 // local!=remote or not installed -> needs update 01204 if($localmd5 != $translationStatusArr[$lang]['md5']) { 01205 $ret = $this->updateTranslation($extKey, $lang, $mirrorURL); 01206 if($ret === true) { 01207 echo ('<td title="Has been updated" style="background-color:#69a550">UPD</td>'); 01208 } else { 01209 echo ('<td title="'.htmlspecialchars($ret).'" style="background-color:#cb3352">ERR</td>'); 01210 } 01211 continue; 01212 } 01213 echo ('<td title="Is up to date" style="background-color:#69a550">OK</td>'); 01214 } 01215 echo ('</tr>'); 01216 01217 $counter++; 01218 } 01219 echo '</table> 01220 <script> 01221 document.getElementById("progress-message").firstChild.data="Update done."; 01222 </script> 01223 '; 01224 echo $this->doc->endPage(); 01225 return ''; 01226 } 01227 01228 $this->content.=$this->doc->section('Translation status',$content,0,1); 01229 } 01230 } 01231 01240 function updateTranslation($extKey, $lang, $mirrorURL) { 01241 $l10n = $this->terConnection->fetchTranslation($extKey, $lang, $mirrorURL); 01242 if(is_array($l10n)) { 01243 $file = PATH_site.'typo3temp/'.$extKey.'-l10n-'.$lang.'.zip'; 01244 $path = 'l10n/'.$lang.'/'; 01245 if(!is_dir(PATH_typo3conf.$path)) t3lib_div::mkdir_deep(PATH_typo3conf,$path); 01246 t3lib_div::writeFile($file, $l10n[0]); 01247 if($this->unzip($file, PATH_typo3conf.$path)) { 01248 return true; 01249 } else { 01250 return 'Unpacking the language pack failed!'; 01251 } 01252 } else { 01253 return $l10n; 01254 } 01255 } 01256 01264 function installTranslationsForExtension($extKey, $mirrorURL) { 01265 $selectedLanguages = unserialize($this->MOD_SETTINGS['selectedLanguages']); 01266 if(!is_array($selectedLanguages)) $selectedLanguages = array(); 01267 foreach($selectedLanguages as $lang) { 01268 $l10n = $this->terConnection->fetchTranslation($extKey, $lang, $mirrorURL); 01269 if(is_array($l10n)) { 01270 $file = PATH_typo3conf.'l10n/'.$extKey.'-l10n-'.$lang.'.zip'; 01271 $path = 'l10n/'.$lang.'/'.$extKey; 01272 t3lib_div::writeFile($file, $l10n[0]); 01273 if(!is_dir(PATH_typo3conf.$path)) t3lib_div::mkdir_deep(PATH_typo3conf,$path); 01274 if($this->unzip($file, PATH_typo3conf.$path)) { 01275 return true; 01276 } else { 01277 return 'Unpacking the language pack failed!'; 01278 } 01279 } else { 01280 return $l10n; 01281 } 01282 } 01283 } 01284 01294 function unzip($file, $path) { 01295 if(strlen($GLOBALS['TYPO3_CONF_VARS']['BE']['unzip_path'])) { 01296 chdir($path); 01297 $cmd = $GLOBALS['TYPO3_CONF_VARS']['BE']['unzip_path'].' -o '.escapeshellarg($file); 01298 exec($cmd, $list, $ret); 01299 return ($ret === 0); 01300 } else { 01301 // we use a pure PHP unzip 01302 $unzip = new em_unzip($file); 01303 $ret = $unzip->extract(array('add_path'=>$path)); 01304 return (is_array($ret)); 01305 } 01306 } 01307 01308 01309 01310 /********************************* 01311 * 01312 * Command Applications (triggered by GET var) 01313 * 01314 *********************************/ 01315 01323 function importExtInfo($extKey, $version='') { 01324 01325 // "Go back" link 01326 $content = '<a href="index.php" class="typo3-goBack"><img'.t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'],'gfx/goback.gif','width="14" height="14"').' alt="" /> Go back</a>'; 01327 $this->content.= $this->doc->section('',$content); 01328 $content = ''; 01329 01330 // Fetch remote data: 01331 $this->xmlhandler->loadExtensionsXML(); 01332 $this->xmlhandler->extensionsXML = array($extKey => $this->xmlhandler->extensionsXML[$extKey]); 01333 list($fetchData,) = $this->prepareImportExtList(); 01334 01335 $versions = array_keys($fetchData[$extKey]['versions']); 01336 $version = ($version == '') ? end($versions) : $version; 01337 01338 $opt = array(); 01339 foreach(array_keys($fetchData[$extKey]['versions']) as $ver) { 01340 $opt[]='<option value="'.$ver.'"'.(($version == $ver) ? ' selected="selected"' : '').'>'.$ver.'</option>'; 01341 } 01342 01343 // "Select version" box: 01344 $onClick = 'window.location.href=\'index.php?CMD[importExtInfo]='.$extKey.'&CMD[extVersion]=\'+document.pageform.extVersion.options[document.pageform.extVersion.selectedIndex].value; return false;'; 01345 $select='<select name="extVersion">'.implode('',$opt).'</select> <input type="submit" value="Load details" onclick="'.htmlspecialchars($onClick).'" /> or<br /><br />'; 01346 01347 if ($this->importAtAll()) { 01348 $onClick = ' 01349 window.location.href=\'index.php?CMD[importExt]='.$extKey.'\' 01350 +\'&CMD[extVersion]=\'+document.pageform.extVersion.options[document.pageform.extVersion.selectedIndex].value 01351 +\'&CMD[loc]=\'+document.pageform.loc.options[document.pageform.loc.selectedIndex].value; 01352 return false;'; 01353 $select.=' 01354 <input type="submit" value="Import/Update" onclick="'.htmlspecialchars($onClick).'"> to: 01355 <select name="loc">'. 01356 ($this->importAsType('G',$fetchData['emconf_lockType'])?'<option value="G">Global: '.$this->typePaths['G'].$extKey.'/'.(@is_dir(PATH_site.$this->typePaths['G'].$extKey)?' (OVERWRITE)':' (empty)').'</option>':''). 01357 ($this->importAsType('L',$fetchData['emconf_lockType'])?'<option value="L">Local: '.$this->typePaths['L'].$extKey.'/'.(@is_dir(PATH_site.$this->typePaths['L'].$extKey)?' (OVERWRITE)':' (empty)').'</option>':''). 01358 ($this->importAsType('S',$fetchData['emconf_lockType'])?'<option value="S">System: '.$this->typePaths['S'].$extKey.'/'.(@is_dir(PATH_site.$this->typePaths['S'].$extKey)?' (OVERWRITE)':' (empty)').'</option>':''). 01359 '</select>'; 01360 } else $select.= $this->noImportMsg(); 01361 $content.= $select; 01362 $this->content.= $this->doc->section('Select command',$content,0,1); 01363 01364 // Details: 01365 $eInfo = $fetchData[$extKey]['versions'][$version]; 01366 $content='<strong>'.$fetchData[$extKey]['_ICON'].' '.$eInfo['EM_CONF']['title'].' ('.$extKey.', '.$version.')</strong><br /><br />'; 01367 $content.=$this->extInformationArray($extKey,$eInfo,1); 01368 $this->content.=$this->doc->spacer(10); 01369 $this->content.=$this->doc->section('Remote Extension Details',$content,0,1); 01370 } 01371 01380 function fetchMetaData($metaType) { 01381 global $TYPO3_CONF_VARS; 01382 01383 switch($metaType) { 01384 case 'mirrors': 01385 $mfile = t3lib_div::tempnam('mirrors'); 01386 $mirrorsFile = t3lib_div::getURL($this->MOD_SETTINGS['mirrorListURL']); 01387 if($mirrorsFile===false) { 01388 t3lib_div::unlink_tempfile($mfile); 01389 $content = '<p>The mirror list was not updated, it could not be fetched from '.$this->MOD_SETTINGS['mirrorListURL'].'. Possible reasons: network problems, allow_url_fopen is off, curl is not enabled in Install tool.</p>'; 01390 } else { 01391 t3lib_div::writeFile($mfile, $mirrorsFile); 01392 $mirrors = implode('',gzfile($mfile)); 01393 t3lib_div::unlink_tempfile($mfile); 01394 01395 $mirrors = $this->xmlhandler->parseMirrorsXML($mirrors); 01396 if(is_array($mirrors) && count($mirrors)) { 01397 t3lib_BEfunc::getModuleData($this->MOD_MENU, array('extMirrors' => serialize($mirrors)), $this->MCONF['name'], '', 'extMirrors'); 01398 $this->MOD_SETTINGS['extMirrors'] = serialize($mirrors); 01399 $content = '<p>The mirror list has been updated and now contains '.count($mirrors).' entries.</p>'; 01400 } 01401 else { 01402 $content = '<p>'.$mirrors.'<br />The mirror list was not updated as it contained no entries.</p>'; 01403 } 01404 } 01405 break; 01406 case 'extensions': 01407 $this->fetchMetaData('mirrors'); // if we fetch the extensions anyway, we can as well keep this up-to-date 01408 01409 $mirror = $this->getMirrorURL(); 01410 $extfile = $mirror.'extensions.xml.gz'; 01411 $extmd5 = t3lib_div::getURL($mirror.'extensions.md5'); 01412 if(is_file(PATH_site.'typo3temp/extensions.xml.gz')) $localmd5 = md5_file(PATH_site.'typo3temp/extensions.xml.gz'); 01413 01414 if($extmd5 === false) { 01415 $content .= '<p>Error: The extension MD5 sum could not be fetched from '.$mirror.'extensions.md5. Possible reasons: network problems, allow_url_fopen is off, curl is not enabled in Install tool.</p>'; 01416 } elseif($extmd5 == $localmd5) { 01417 $content .= '<p>The extension list has not changed remotely, it has thus not been fetched.</p>'; 01418 } else { 01419 $extXML = t3lib_div::getURL($extfile); 01420 if($extXML === false) { 01421 $content .= '<p>Error: The extension list could not be fetched from '.$extfile.'. Possible reasons: network problems, allow_url_fopen is off, curl is not enabled in Install tool.</p>'; 01422 } else { 01423 t3lib_div::writeFile(PATH_site.'typo3temp/extensions.xml.gz', $extXML); 01424 $content .= $this->xmlhandler->parseExtensionsXML(implode('',gzfile(PATH_site.'typo3temp/extensions.xml.gz'))); 01425 $this->xmlhandler->saveExtensionsXML(); 01426 } 01427 } 01428 break; 01429 } 01430 01431 return $content; 01432 } 01433 01439 function getMirrorURL() { 01440 if(strlen($this->MOD_SETTINGS['rep_url'])) return $this->MOD_SETTINGS['rep_url']; 01441 01442 $mirrors = unserialize($this->MOD_SETTINGS['extMirrors']); 01443 if(!is_array($mirrors)) { 01444 $this->fetchMetaData('mirrors'); 01445 $mirrors = unserialize($this->MOD_SETTINGS['extMirrors']); 01446 if(!is_array($mirrors)) return false; 01447 } 01448 if($this->MOD_SETTINGS['selectedMirror']=='') { 01449 srand((float) microtime() * 10000000); // not needed after PHP 4.2.0... 01450 $rand = array_rand($mirrors); 01451 $url = 'http://'.$mirrors[$rand]['host'].$mirrors[$rand]['path']; 01452 } 01453 else { 01454 $url = 'http://'.$mirrors[$this->MOD_SETTINGS['selectedMirror']]['host'].$mirrors[$this->MOD_SETTINGS['selectedMirror']]['path']; 01455 } 01456 01457 return $url; 01458 } 01459 01460 01461 01477 function installExtension($extKey, $version=null, $mode=EM_INSTALL_VERSION_MIN) { 01478 list($inst_list,) = $this->getInstalledExtensions(); 01479 01480 // check if it is already installed and loaded with sufficient version 01481 if(isset($inst_list[$extKey])) { 01482 $currentVersion = $inst_list[$extKey]['EM_CONF']['version']; 01483 01484 if(t3lib_extMgm::isLoaded($extKey)) { 01485 if($version===null) { 01486 return array(true, 'Extension already installed and loaded.'); 01487 } else { 01488 switch($mode) { 01489 case EM_INSTALL_VERSION_STRICT: 01490 if($currentVersion == $version) { 01491 return array(true, 'Extension already installed and loaded.'); 01492 } 01493 break; 01494 case EM_INSTALL_VERSION_MIN: 01495 if(version_compare($currentVersion, $version, '>=')) { 01496 return array(true, 'Extension already installed and loaded.'); 01497 } 01498 break; 01499 case EM_INSTALL_VERSION_MAX: 01500 if(version_compare($currentVersion, $version, '<=')) { 01501 return array(true, 'Extension already installed and loaded.'); 01502 } 01503 break; 01504 } 01505 } 01506 } else { 01507 if (!t3lib_extMgm::isLocalconfWritable()) { 01508 return array(false, 'localconf.php is not writable!'); 01509 } 01510 $newExtList = -1; 01511 switch($mode) { 01512 case EM_INSTALL_VERSION_STRICT: 01513 if($currentVersion == $version) { 01514 $newExtList = $this->addExtToList($extKey, $inst_list); 01515 } 01516 break; 01517 case EM_INSTALL_VERSION_MIN: 01518 if(version_compare($currentVersion, $version, '>=')) { 01519 $newExtList = $this->addExtToList($extKey, $inst_list); 01520 } 01521 break; 01522 case EM_INSTALL_VERSION_MAX: 01523 if(version_compare($currentVersion, $version, '<=')) { 01524 $newExtList = $this->addExtToList($extKey, $inst_list); 01525 } 01526 break; 01527 } 01528 if ($newExtList!=-1) { 01529 $this->writeNewExtensionList($newExtList); 01530 $this->refreshGlobalExtList(); 01531 $this->forceDBupdates($extKey, $inst_list[$extKey]); 01532 return array(true, 'Extension was already installed, it has been loaded.'); 01533 } 01534 } 01535 } 01536 01537 // at this point we know we need to import (a matching version of) the extension from TER2 01538 01539 // see if we have an extensionlist at all 01540 $this->xmlhandler->loadExtensionsXML(); 01541 if (!count($this->xmlhandler->extensionsXML)) { 01542 $this->fetchMetaData('extensions'); 01543 } 01544 01545 // check if extension can be fetched 01546 if(isset($this->xmlhandler->extensionsXML[$extKey])) { 01547 $versions = array_keys($this->xmlhandler->extensionsXML[$extKey]['versions']); 01548 $latestVersion = end($versions); 01549 switch($mode) { 01550 case EM_INSTALL_VERSION_STRICT: 01551 if(!isset($this->xmlhandler->extensionsXML[$extKey]['versions'][$version])) { 01552 return array(false, 'Extension not available in matching version'); 01553 } 01554 break; 01555 case EM_INSTALL_VERSION_MIN: 01556 if(version_compare($latestVersion, $version, '>=')) { 01557 $version = $latestVersion; 01558 } else { 01559 return array(false, 'Extension not available in matching version'); 01560 } 01561 break; 01562 case EM_INSTALL_VERSION_MAX: 01563 while(($v = array_pop($versions)) && version_compare($v, $version, '>=')) {} 01564 if($v !== null && version_compare($v, $version, '<=')) { 01565 $version = $v; 01566 } else { 01567 return array(false, 'Extension not available in matching version'); 01568 } 01569 break; 01570 } 01571 $this->importExtFromRep($extKey, $version, 'L'); 01572 $newExtList = $this->addExtToList($extKey, $inst_list); 01573 if ($newExtList!=-1) { 01574 $this->writeNewExtensionList($newExtList); 01575 $this->refreshGlobalExtList(); 01576 $this->forceDBupdates($extKey, $inst_list[$extKey]); 01577 $this->installTranslationsForExtension($extKey, $this->getMirrorURL()); 01578 return array(true, 'Extension has been imported from repository and loaded.'); 01579 } else { 01580 return array(false, 'Extension is in repository, but could not be loaded.'); 01581 } 01582 } else { 01583 return array(false, 'Extension not available in repository'); 01584 } 01585 } 01586 01587 function refreshGlobalExtList() { 01588 global $TYPO3_LOADED_EXT; 01589 01590 $TYPO3_LOADED_EXT = t3lib_extMgm::typo3_loadExtensions(); 01591 if ($TYPO3_LOADED_EXT['_CACHEFILE']) { 01592 require(PATH_typo3conf.$TYPO3_LOADED_EXT['_CACHEFILE'].'_ext_localconf.php'); 01593 } 01594 return; 01595 01596 $GLOBALS['TYPO3_LOADED_EXT'] = t3lib_extMgm::typo3_loadExtensions(); 01597 if ($TYPO3_LOADED_EXT['_CACHEFILE']) { 01598 require(PATH_typo3conf.$TYPO3_LOADED_EXT['_CACHEFILE'].'_ext_localconf.php'); 01599 } else { 01600 $temp_TYPO3_LOADED_EXT = $TYPO3_LOADED_EXT; 01601 reset($temp_TYPO3_LOADED_EXT); 01602 while(list($_EXTKEY,$temp_lEDat)=each($temp_TYPO3_LOADED_EXT)) { 01603 if (is_array($temp_lEDat) && $temp_lEDat['ext_localconf.php']) { 01604 $_EXTCONF = $TYPO3_CONF_VARS['EXT']['extConf'][$_EXTKEY]; 01605 require($temp_lEDat['ext_localconf.php']); 01606 } 01607 } 01608 } 01609 } 01610 01611 01624 function importExtFromRep($extKey,$version,$loc,$uploadFlag=0,$dontDelete=0,$directInput='') { 01625 01626 $uploadSucceed = false; 01627 $uploadedTempFile = ''; 01628 if (is_array($directInput)) { 01629 $fetchData = array($directInput,''); 01630 $loc = ($loc==='G'||$loc==='S') ? $loc : 'L'; 01631 } elseif ($uploadFlag) { 01632 if (($uploadedTempFile = $this->CMD['alreadyUploaded']) || $_FILES['upload_ext_file']['tmp_name']) { 01633 01634 // Read uploaded file: 01635 if (!$uploadedTempFile) { 01636 if (!is_uploaded_file($_FILES['upload_ext_file']['tmp_name'])) { 01637 t3lib_div::sysLog('Possible file upload attack: '.$_FILES['upload_ext_file']['tmp_name'], 'Extension Manager', 3); 01638 01639 return 'File was not uploaded?!?'; 01640 } 01641 01642 $uploadedTempFile = t3lib_div::upload_to_tempfile($_FILES['upload_ext_file']['tmp_name']); 01643 } 01644 $fileContent = t3lib_div::getUrl($uploadedTempFile); 01645 01646 if (!$fileContent) return 'File is empty!'; 01647 01648 // Decode file data: 01649 $fetchData = $this->terConnection->decodeExchangeData($fileContent); 01650 01651 if (is_array($fetchData)) { 01652 $extKey = $fetchData[0]['extKey']; 01653 if ($extKey) { 01654 if (!$this->CMD['uploadOverwrite']) { 01655 $loc = ($loc==='G'||$loc==='S') ? $loc : 'L'; 01656 $comingExtPath = PATH_site.$this->typePaths[$loc].$extKey.'/'; 01657 if (@is_dir($comingExtPath)) { 01658 return 'Extension was already present in "'.$comingExtPath.'" - and the overwrite flag was not set! So nothing done...'; 01659 } // ... else go on, install... 01660 } // ... else go on, install... 01661 } else return 'No extension key in file. Strange...'; 01662 } else return 'Wrong file format. No data recognized, '.$fetchData; 01663 } else return 'No file uploaded! Probably the file was too large for PHPs internal limit for uploadable files.'; 01664 } else { 01665 $this->xmlhandler->loadExtensionsXML(); 01666 01667 // Fetch extension from TER: 01668 if(!strlen($version)) { 01669 $versions = array_keys($this->xmlhandler->extensionsXML[$extKey]['versions']); 01670 $version = end($versions); 01671 } 01672 $fetchData = $this->terConnection->fetchExtension($extKey, $version, $this->xmlhandler->extensionsXML[$extKey]['versions'][$version]['t3xfilemd5'], $this->getMirrorURL()); 01673 } 01674 01675 // At this point the extension data should be present; so we want to write it to disc: 01676 if ($this->importAsType($loc)) { 01677 if (is_array($fetchData)) { // There was some data successfully transferred 01678 if ($fetchData[0]['extKey'] && is_array($fetchData[0]['FILES'])) { 01679 $extKey = $fetchData[0]['extKey']; 01680 if(!isset($fetchData[0]['EM_CONF']['constraints'])) $fetchData[0]['EM_CONF']['constraints'] = $this->xmlhandler->extensionsXML[$extKey]['versions'][$version]['dependencies']; 01681 $EM_CONF = $this->fixEMCONF($fetchData[0]['EM_CONF']); 01682 if (!$EM_CONF['lockType'] || !strcmp($EM_CONF['lockType'],$loc)) { 01683 // check dependencies, act accordingly if ext is loaded 01684 list($instExtInfo,)=$this->getInstalledExtensions(); 01685 $depStatus = $this->checkDependencies($extKey, $EM_CONF, $instExtInfo); 01686 if(t3lib_extMgm::isLoaded($extKey) && !$depStatus['returnCode']) { 01687 $this->content .= $depStatus['html']; 01688 if ($uploadedTempFile) { 01689 $this->content .= '<input type="hidden" name="CMD[alreadyUploaded]" value="'.$uploadedTempFile.'" />'; 01690 } 01691 } else { 01692 $res = $this->clearAndMakeExtensionDir($fetchData[0],$loc,$dontDelete); 01693 if (is_array($res)) { 01694 $extDirPath = trim($res[0]); 01695 if ($extDirPath && @is_dir($extDirPath) && substr($extDirPath,-1)=='/') { 01696 01697 $emConfFile = $this->construct_ext_emconf_file($extKey,$EM_CONF); 01698 $dirs = $this->extractDirsFromFileList(array_keys($fetchData[0]['FILES'])); 01699 01700 $res = $this->createDirsInPath($dirs,$extDirPath); 01701 if (!$res) { 01702 $writeFiles = $fetchData[0]['FILES']; 01703 $writeFiles['ext_emconf.php']['content'] = $emConfFile; 01704 $writeFiles['ext_emconf.php']['content_md5'] = md5($emConfFile); 01705 01706 // Write files: 01707 foreach($writeFiles as $theFile => $fileData) { 01708 t3lib_div::writeFile($extDirPath.$theFile,$fileData['content']); 01709 if (!@is_file($extDirPath.$theFile)) { 01710 $content.='Error: File "'.$extDirPath.$theFile.'" could not be created!!!<br />'; 01711 } elseif (md5(t3lib_div::getUrl($extDirPath.$theFile)) != $fileData['content_md5']) { 01712 $content.='Error: File "'.$extDirPath.$theFile.'" MD5 was different from the original files MD5 - so the file is corrupted!<br />'; 01713 } 01714 } 01715 01716 // No content, no errors. Create success output here: 01717 if (!$content) { 01718 $content='SUCCESS: '.$extDirPath.'<br />'; 01719 01720 $uploadSucceed = true; 01721 01722 // Fix TYPO3_MOD_PATH for backend modules in extension: 01723 $modules = t3lib_div::trimExplode(',',$EM_CONF['module'],1); 01724 if (count($modules)) { 01725 foreach($modules as $mD) { 01726 $confFileName = $extDirPath.$mD.'/conf.php'; 01727 if (@is_file($confFileName)) { 01728 $content.= $this->writeTYPO3_MOD_PATH($confFileName,$loc,$extKey.'/'.$mD.'/').'<br />'; 01729 } else $content.='Error: Couldn\'t find "'.$confFileName.'"<br />'; 01730 } 01731 } 01732 // NOTICE: I used two hours trying to find out why a script, ext_emconf.php, written twice and in between included by PHP did not update correct the second time. Probably something with PHP-A cache and mtime-stamps. 01733 // But this order of the code works.... (using the empty Array with type, EMCONF and files hereunder). 01734 01735 // Writing to ext_emconf.php: 01736 $sEMD5A = $this->serverExtensionMD5Array($extKey,array('type' => $loc, 'EM_CONF' => array(), 'files' => array())); 01737 $EM_CONF['_md5_values_when_last_written'] = serialize($sEMD5A); 01738 $emConfFile = $this->construct_ext_emconf_file($extKey,$EM_CONF); 01739 t3lib_div::writeFile($extDirPath.'ext_emconf.php',$emConfFile); 01740 01741 $content.='ext_emconf.php: '.$extDirPath.'ext_emconf.php<br />'; 01742 $content.='Type: '.$loc.'<br />'; 01743 01744 // Remove cache files: 01745 if (t3lib_extMgm::isLoaded($extKey)) { 01746 if ($this->removeCacheFiles()) { 01747 $content.='Cache-files are removed and will be re-written upon next hit<br />'; 01748 } 01749 01750 list($new_list)=$this->getInstalledExtensions(); 01751 $content.=$this->updatesForm($extKey,$new_list[$extKey],1,'index.php?CMD[showExt]='.$extKey.'&SET[singleDetails]=info'); 01752 } 01753 01754 // Install / Uninstall: 01755 if(!$this->CMD['standAlone']) { 01756 $content = '<a href="index.php" class="typo3-goBack"><img'.t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'],'gfx/goback.gif','width="14" height="14"').' alt="" /> Go back</a><br />'.$content; 01757 $content.='<h3>Install / Uninstall Extension:</h3>'; 01758 $content.= $new_list[$extKey] ? 01759 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->removeButton().' Uninstall extension</a>' : 01760 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[load]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->installButton().' Install extension</a>'; 01761 } else { 01762 $content = 'Extension has been imported.<br /><br /><a href="javascript:opener.top.content.document.forms[0].submit();window.close();">Close window and recheck dependencies</a>'; 01763 } 01764 01765 } 01766 } else $content = $res; 01767 } else $content = 'Error: The extension path "'.$extDirPath.'" was different than expected...'; 01768 } else $content = $res; 01769 } 01770 } else $content = 'Error: The extension can only be installed in the path '.$this->typePaths[$EM_CONF['lockType']].' (lockType='.$EM_CONF['lockType'].')'; 01771 } else $content = 'Error: No extension key!!! Why? - nobody knows... (Or no files in the file-array...)'; 01772 } else $content = 'Error: The datatransfer did not succeed. '.$fetchData; 01773 } else $content = 'Error: Installation is not allowed in this path ('.$this->typePaths[$loc].')'; 01774 01775 $this->content.=$this->doc->section('Extension import results',$content,0,1); 01776 01777 if ($uploadSucceed && $uploadedTempFile) { 01778 t3lib_div::unlink_tempfile($uploadedTempFile); 01779 } 01780 01781 return false; 01782 } 01783 01790 function showExtDetails($extKey) { 01791 global $TYPO3_LOADED_EXT; 01792 01793 list($list,)=$this->getInstalledExtensions(); 01794 $absPath = $this->getExtPath($extKey,$list[$extKey]['type']); 01795 01796 // Check updateModule: 01797 if (@is_file($absPath.'class.ext_update.php')) { 01798 require_once($absPath.'class.ext_update.php'); 01799 $updateObj = new ext_update; 01800 if (!$updateObj->access()) { 01801 unset($this->MOD_MENU['singleDetails']['updateModule']); 01802 } 01803 } else { 01804 unset($this->MOD_MENU['singleDetails']['updateModule']); 01805 } 01806 01807 if($this->CMD['doDelete']) { 01808 $this->MOD_MENU['singleDetails'] = array(); 01809 } 01810 01811 // Function menu here: 01812 if(!$this->CMD['standAlone'] && !t3lib_div::_GP('standAlone')) { 01813 $content = ' 01814 <table border="0" cellpadding="0" cellspacing="0" width="100%"> 01815 <tr> 01816 <td nowrap="nowrap">Extension: <strong>'.$this->extensionTitleIconHeader($extKey,$list[$extKey]).'</strong> ('.$extKey.')</td> 01817 <td align="right" nowrap="nowrap">'. 01818 t3lib_BEfunc::getFuncMenu(0,'SET[singleDetails]',$this->MOD_SETTINGS['singleDetails'],$this->MOD_MENU['singleDetails'],'','&CMD[showExt]='.$extKey).' '. 01819 '<a href="index.php" class="typo3-goBack"><img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/goback.gif','width="14" height="14"').' class="absmiddle" alt="" /> Go back</a></td> 01820 </tr> 01821 </table>'; 01822 $this->content.=$this->doc->section('',$content); 01823 } 01824 01825 // Show extension details: 01826 if ($list[$extKey]) { 01827 01828 // Checking if a command for install/uninstall is executed: 01829 if (($this->CMD['remove'] || $this->CMD['load']) && !in_array($extKey,$this->requiredExt)) { 01830 01831 // Install / Uninstall extension here: 01832 if (t3lib_extMgm::isLocalconfWritable()) { 01833 // Check dependencies: 01834 $depStatus = $this->checkDependencies($extKey, $list[$extKey]['EM_CONF'], $list); 01835 if(!$this->CMD['remove'] && !$depStatus['returnCode']) { 01836 $this->content .= $depStatus['html']; 01837 $newExtList = -1; 01838 } elseif ($this->CMD['remove']) { 01839 $newExtList = $this->removeExtFromList($extKey,$list); 01840 } else { 01841 $newExtList = $this->addExtToList($extKey,$list); 01842 } 01843 01844 // Success-installation: 01845 if ($newExtList!=-1) { 01846 $updates = ''; 01847 if ($this->CMD['load']) { 01848 if($_SERVER['REQUEST_METHOD'] == 'POST') { 01849 $script = t3lib_div::linkThisScript(array('CMD[showExt]' => $extKey, 'CMD[load]' => 1, 'CMD[clrCmd]' => $this->CMD['clrCmd'], 'SET[singleDetails]' => 'info')); 01850 } else { 01851 $script = ''; 01852 } 01853 $updates = $this->updatesForm($extKey,$list[$extKey],1,$script,'<input type="hidden" name="_do_install" value="1" /><input type="hidden" name="_clrCmd" value="'.$this->CMD['clrCmd'].'" />'); 01854 if ($updates) { 01855 $updates = 'Before the extension can be installed the database needs to be updated with new tables or fields. Please select which operations to perform:'.$updates; 01856 if($this->CMD['standAlone']) $updates .= '<input type="hidden" name="standAlone" value="1" />'; 01857 $depsolver = t3lib_div::_POST('depsolver'); 01858 if(is_array($depsolver['ignore'])) { 01859 foreach($depsolver['ignore'] as $depK => $depV) { 01860 $updates .= '<input type="hidden" name="depsolver[ignore]['.$depK.']" value="1" />'; 01861 } 01862 } 01863 01864 $this->content.=$this->doc->section('Installing '.$this->extensionTitleIconHeader($extKey,$list[$extKey]).strtoupper(': Database needs to be updated'),$updates,1,1,1,1); 01865 } 01866 } elseif ($this->CMD['remove']) { 01867 $updates.= $this->checkClearCache($list[$extKey]); 01868 if ($updates) { 01869 $updates = ' 01870 </form><form action="'.t3lib_div::linkThisScript().'" method="post">'.$updates.' 01871 <br /><input type="submit" name="write" value="Remove extension" /> 01872 <input type="hidden" name="_do_install" value="1" /> 01873 <input type="hidden" name="_clrCmd" value="'.$this->CMD['clrCmd'].'" /> 01874 <input type="hidden" name="standAlone" value="'.$this->CMD['standAlone'].'" /> 01875 '; 01876 $this->content.=$this->doc->section('Removing '.$this->extensionTitleIconHeader($extKey,$list[$extKey]).strtoupper(': Database needs to be updated'),$updates,1,1,1,1); 01877 } 01878 } 01879 if (!$updates || t3lib_div::_GP('_do_install')) { 01880 $this->writeNewExtensionList($newExtList); 01881 $GLOBALS['BE_USER']->writelog(5,1,0,0,'Extension list has been changed, extension %s has been %s',array($extKey,($this->CMD['load']?'installed':'removed'))); 01882 if ($this->CMD['clrCmd'] || t3lib_div::_GP('_clrCmd')) { 01883 $vA = array('CMD'=>''); 01884 } else { 01885 $vA = array('CMD'=>Array('showExt'=>$extKey)); 01886 } 01887 if($this->CMD['standAlone'] || t3lib_div::_GP('standAlone')) { 01888 $this->content .= 'Extension has been '.($this->CMD['load'] ? 'installed' : 'removed').'.<br /><br /><a href="javascript:opener.top.content.document.forms[0].submit();window.close();">Close window and recheck dependencies</a>'; 01889 } else { 01890 header('Location: '.t3lib_div::linkThisScript($vA)); 01891 } 01892 } 01893 } 01894 } else { 01895 $this->content.=$this->doc->section('Installing '.$this->extensionTitleIconHeader($extKey,$list[$extKey]).strtoupper(': Write access error'),'typo3conf/localconf.php seems not to be writable, so the extension cannot be installed automatically!',1,1,2,1); 01896 } 01897 01898 } elseif ($this->CMD['downloadFile'] && !in_array($extKey,$this->requiredExt)) { 01899 01900 // Link for downloading extension has been clicked - deliver content stream: 01901 $dlFile = $this->CMD['downloadFile']; 01902 if (t3lib_div::isFirstPartOfStr($dlFile,PATH_site) && t3lib_div::isFirstPartOfStr($dlFile,$absPath) && @is_file($dlFile)) { 01903 $mimeType = 'application/octet-stream'; 01904 Header('Content-Type: '.$mimeType); 01905 Header('Content-Disposition: attachment; filename='.basename($dlFile)); 01906 echo t3lib_div::getUrl($dlFile); 01907 exit; 01908 } else die('Error while trying to download extension file...'); 01909 01910 } elseif ($this->CMD['editFile'] && !in_array($extKey,$this->requiredExt)) { 01911 01912 // Editing extension file: 01913 $editFile = $this->CMD['editFile']; 01914 if (t3lib_div::isFirstPartOfStr($editFile,PATH_site) && t3lib_div::isFirstPartOfStr($editFile,$absPath)) { // Paranoia... 01915 01916 $fI = t3lib_div::split_fileref($editFile); 01917 if (@is_file($editFile) && t3lib_div::inList($this->editTextExtensions,($fI['fileext']?$fI['fileext']:$fI['filebody']))) { 01918 if (filesize($editFile)<($this->kbMax*1024)) { 01919 $outCode = ''; 01920 $info = ''; 01921 $submittedContent = t3lib_div::_POST('edit'); 01922 $saveFlag = 0; 01923 01924 if(isset($submittedContent['file']) && !$GLOBALS['TYPO3_CONF_VARS']['EXT']['noEdit']) { // Check referer here? 01925 $oldFileContent = t3lib_div::getUrl($editFile); 01926 if($oldFileContent != $submittedContent['file']) { 01927 $oldMD5 = md5(str_replace(chr(13),'',$oldFileContent)); 01928 $info.= 'MD5: <b>'.$oldMD5.'</b> (Previous File)<br />'; 01929 t3lib_div::writeFile($editFile,$submittedContent['file']); 01930 $saveFlag = 1; 01931 } else { 01932 $info .= 'No changes to the file detected!<br />'; 01933 } 01934 } 01935 01936 $fileContent = t3lib_div::getUrl($editFile); 01937 01938 $outCode.= 'File: <b>'.substr($editFile,strlen($absPath)).'</b> ('.t3lib_div::formatSize(filesize($editFile)).')<br />'; 01939 $fileMD5 = md5(str_replace(chr(13),'',$fileContent)); 01940 $info.= 'MD5: <b>'.$fileMD5.'</b> (Current File)<br />'; 01941 if($saveFlag) { 01942 $saveMD5 = md5(str_replace(chr(13),'',$submittedContent['file'])); 01943 $info.= 'MD5: <b>'.$saveMD5.'</b> (Submitted)<br />'; 01944 if($fileMD5!=$saveMD5) $info .= $GLOBALS['TBE_TEMPLATE']->rfw('<br /><strong>Saving failed, the content was not correctly written to disk. Changes have been lost!</strong>').'<br />'; 01945 else $info.= $GLOBALS['TBE_TEMPLATE']->rfw('<br /><strong>File saved.</strong>').'<br />'; 01946 } 01947 01948 $outCode.= '<textarea name="edit[file]" rows="35" wrap="off"'.$this->doc->formWidthText(48,'width:98%;height:70%','off').' class="fixed-font enable-tab">'.t3lib_div::formatForTextarea($fileContent).'</textarea>'; 01949 $outCode.= '<input type="hidden" name="edit[filename]" value="'.$editFile.'" />'; 01950 $outCode.= '<input type="hidden" name="CMD[editFile]" value="'.htmlspecialchars($editFile).'" />'; 01951 $outCode.= '<input type="hidden" name="CMD[showExt]" value="'.$extKey.'" />'; 01952 $outCode.= $info; 01953 01954 if (!$GLOBALS['TYPO3_CONF_VARS']['EXT']['noEdit']) { 01955 $outCode.='<br /><input type="submit" name="save_file" value="Save file" />'; 01956 } else $outCode.=$GLOBALS['TBE_TEMPLATE']->rfw('<br />[SAVING IS DISABLED - can be enabled by the $TYPO3_CONF_VARS[\'EXT\'][\'noEdit\']-flag] '); 01957 01958 $onClick = 'window.location.href=\'index.php?CMD[showExt]='.$extKey.'\';return false;'; 01959 $outCode.='<input type="submit" name="cancel" value="Cancel" onclick="'.htmlspecialchars($onClick).'" />'; 01960 01961 $theOutput.=$this->doc->spacer(15); 01962 $theOutput.=$this->doc->section('Edit file:','',0,1); 01963 $theOutput.=$this->doc->sectionEnd().$outCode; 01964 $this->content.=$theOutput; 01965 } else { 01966 $theOutput.=$this->doc->spacer(15); 01967 $theOutput.=$this->doc->section('Filesize exceeded '.$this->kbMax.' Kbytes','Files larger than '.$this->kbMax.' KBytes are not allowed to be edited.'); 01968 } 01969 } 01970 } else die('Fatal Edit error: File "'.$editFile.'" was not inside the correct path of the TYPO3 Extension!'); 01971 } else { 01972 01973 // MAIN: 01974 switch((string)$this->MOD_SETTINGS['singleDetails']) { 01975 case 'info': 01976 // Loaded / Not loaded: 01977 if (!in_array($extKey,$this->requiredExt)) { 01978 if ($TYPO3_LOADED_EXT[$extKey]) { 01979 $content = '<strong>The extension is installed (loaded and running)!</strong><br />'. 01980 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1').'">Click here to remove the extension: '.$this->removeButton().'</a>'; 01981 } else { 01982 $content = 'The extension is <strong>not</strong> installed yet.<br />'. 01983 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[load]=1').'">Click here to install the extension: '.$this->installButton().'</a>'; 01984 } 01985 } else { 01986 $content = 'This extension is entered in the TYPO3_CONF_VARS[SYS][requiredExt] list and is therefore always loaded.'; 01987 } 01988 $this->content.=$this->doc->spacer(10); 01989 $this->content.=$this->doc->section('Active status:',$content,0,1); 01990 01991 if (t3lib_extMgm::isLoaded($extKey)) { 01992 $updates=$this->updatesForm($extKey,$list[$extKey]); 01993 if ($updates) { 01994 $this->content.=$this->doc->spacer(10); 01995 $this->content.=$this->doc->section('Update needed:',$updates.'<br /><br />Notice: "Static data" may not <em>need</em> to be updated. You will only have to import static data each time you upgrade the extension.',0,1); 01996 } 01997 } 01998 01999 // Config: 02000 if (@is_file($absPath.'ext_conf_template.txt')) { 02001 $this->content.=$this->doc->spacer(10); 02002 $this->content.=$this->doc->section('Configuration:','(<em>Notice: You may need to clear the cache after configuration of the extension. This is required if the extension adds TypoScript depending on these settings.</em>)<br /><br />',0,1); 02003 $this->tsStyleConfigForm($extKey,$list[$extKey]); 02004 } 02005 02006 // Show details: 02007 $content = t3lib_BEfunc::cshItem('_MOD_tools_em', 'info', $GLOBALS['BACK_PATH'],'|<br/>'); 02008 $content.= $this->extInformationArray($extKey,$list[$extKey]); 02009 02010 $this->content.=$this->doc->spacer(10); 02011 $this->content.=$this->doc->section('Details:',$content,0,1); 02012 break; 02013 case 'upload': 02014 $em = t3lib_div::_POST('em'); 02015 if($em['action'] == 'doUpload') { 02016 $em['extKey'] = $extKey; 02017 $em['extInfo'] = $list[$extKey]; 02018 $content = $this->uploadExtensionToTER($em); 02019 $content .= $this->doc->spacer(10); 02020 // Must reload this, because EM_CONF information has been updated! 02021 list($list,)=$this->getInstalledExtensions(); 02022 } else { 02023 // CSH: 02024 $content = t3lib_BEfunc::cshItem('_MOD_tools_em', 'upload', $GLOBALS['BACK_PATH'],'|<br/>'); 02025 02026 // Upload: 02027 if (substr($extKey,0,5)!='user_') { 02028 $content.= $this->getRepositoryUploadForm($extKey,$list[$extKey]); 02029 $eC=0; 02030 } else { 02031 $content.='The extensions has an extension key prefixed "user_" which indicates that it is a user-defined extension with no official unique identification. Therefore it cannot be uploaded.'; 02032 $eC=2; 02033 } 02034 if (!$this->fe_user['username']) { 02035 $content.= '<br /><br /><img src="'.$GLOBALS['BACK_PATH'].'gfx/icon_note.gif" width="18" height="16" align="top" alt="" />You have not configured a default username/password yet. <a href="index.php?SET[function]=3">Go to "Settings"</a> if you want to do that.<br />'; 02036 } 02037 } 02038 $this->content.=$this->doc->section('Upload extension to repository',$content,0,1,$eC); 02039 break; 02040 case 'backup': 02041 if($this->CMD['doDelete']) { 02042 $content = $this->extDelete($extKey,$list[$extKey]); 02043 $this->content.=$this->doc->section('Delete',$content,0,1); 02044 } else { 02045 $content = t3lib_BEfunc::cshItem('_MOD_tools_em', 'backup_delete', $GLOBALS['BACK_PATH'],'|<br/>'); 02046 $content.= $this->extBackup($extKey,$list[$extKey]); 02047 $this->content.=$this->doc->section('Backup',$content,0,1); 02048 02049 $content = $this->extDelete($extKey,$list[$extKey]); 02050 $this->content.=$this->doc->section('Delete',$content,0,1); 02051 02052 $content = $this->extUpdateEMCONF($extKey,$list[$extKey]); 02053 $this->content.=$this->doc->section('Update EM_CONF',$content,0,1); 02054 } 02055 break; 02056 case 'dump': 02057 $this->extDumpTables($extKey,$list[$extKey]); 02058 break; 02059 case 'edit': 02060 $content = t3lib_BEfunc::cshItem('_MOD_tools_em', 'editfiles', $GLOBALS['BACK_PATH'],'|<br/>'); 02061 $content.= $this->getFileListOfExtension($extKey,$list[$extKey]); 02062 02063 $this->content.=$this->doc->section('Extension files',$content,0,1); 02064 break; 02065 case 'updateModule': 02066 $this->content.=$this->doc->section('Update:',is_object($updateObj) ? $updateObj->main() : 'No update object',0,1); 02067 break; 02068 default: 02069 $this->extObjContent(); 02070 break; 02071 } 02072 } 02073 } 02074 } 02075 02083 function requestInstallExtensions($extList) { 02084 02085 // Return URL: 02086 $returnUrl = t3lib_div::_GP('returnUrl'); 02087 $installOrImportExtension = t3lib_div::_POST('installOrImportExtension'); 02088 02089 // Extension List: 02090 $extArray = explode(',',$extList); 02091 $outputRow = array(); 02092 $outputRow[] = ' 02093 <tr class="bgColor5 tableheader"> 02094 <td>Install/Import:</td> 02095 <td>Extension Key:</td> 02096 </tr> 02097 '; 02098 02099 foreach($extArray as $extKey) { 02100 02101 // Check for the request: 02102 if ($installOrImportExtension[$extKey]) { 02103 $this->installExtension($extKey); 02104 } 02105 02106 // Display: 02107 if (!t3lib_extMgm::isLoaded($extKey)) { 02108 $outputRow[] = ' 02109 <tr class="bgColor4"> 02110 <td><input type="checkbox" name="'.htmlspecialchars('installOrImportExtension['.$extKey.']').'" value="1" checked="checked" /></td> 02111 <td>'.htmlspecialchars($extKey).'</td> 02112 </tr> 02113 '; 02114 } 02115 } 02116 02117 if (count($outputRow)>1 || !$returnUrl) { 02118 $content = ' 02119 </form> <!-- ending page form ... --> 02120 <form action="'.htmlspecialchars(t3lib_div::getIndpEnv('REQUEST_URI')).'" method="post"> 02121 <table border="0" cellpadding="1" cellspacing="1">'.implode('',$outputRow).'</table> 02122 <input type="submit" name="_" value="Import and Install selected" /> 02123 </form> 02124 <form> <!-- continuing page form... -->'; 02125 02126 if ($returnUrl) { 02127 $content.= ' 02128 <br/> 02129 <br/> 02130 <a href="'.htmlspecialchars($returnUrl).'">Return</a> 02131 '; 02132 } 02133 02134 $this->content.= $this->doc->section('Import/Install Extensions:',$content,0,1); 02135 } else { 02136 header('Location: '.t3lib_div::locationHeaderUrl($returnUrl)); 02137 } 02138 } 02139 02140 02141 02142 02143 02144 02145 02146 02147 /*********************************** 02148 * 02149 * Application Sub-functions (HTML parts) 02150 * 02151 **********************************/ 02152 02164 function updatesForm($extKey,$extInfo,$notSilent=0,$script='',$addFields='') { 02165 $script = $script ? $script : t3lib_div::linkThisScript(); 02166 $updates.= $this->checkDBupdates($extKey,$extInfo); 02167 $uCache = $this->checkClearCache($extInfo); 02168 if ($notSilent) $updates.= $uCache; 02169 $updates.= $this->checkUploadFolder($extKey,$extInfo); 02170 02171 $absPath = $this->getExtPath($extKey,$extInfo['type']); 02172 if ($notSilent && @is_file($absPath.'ext_conf_template.txt')) { 02173 $cForm = $this->tsStyleConfigForm($extKey,$extInfo,1,$script,$updates.$addFields.'<br />'); 02174 } 02175 02176 if ($updates || $cForm) { 02177 if ($cForm) { 02178 $updates = '</form>'.$cForm.'<form>'; 02179 } else { 02180 $updates = '</form><form action="'.htmlspecialchars($script).'" method="post">'.$updates.$addFields.' 02181 <br /><input type="submit" name="write" value="Make updates" /> 02182 '; 02183 } 02184 } 02185 return $updates; 02186 } 02187 02195 function extDumpTables($extKey,$extInfo) { 02196 02197 // Get dbInfo which holds the structure known from the tables.sql file 02198 $techInfo = $this->makeDetailedExtensionAnalysis($extKey,$extInfo); 02199 $absPath = $this->getExtPath($extKey,$extInfo['type']); 02200 02201 // Static tables: 02202 if (is_array($techInfo['static'])) { 02203 if ($this->CMD['writeSTATICdump']) { // Writing static dump: 02204 $writeFile = $absPath.'ext_tables_static+adt.sql'; 02205 if (@is_file($writeFile)) { 02206 $dump_static = $this->dumpStaticTables(implode(',',$techInfo['static'])); 02207 t3lib_div::writeFile($writeFile,$dump_static); 02208 $this->content.=$this->doc->section('Table and field structure required',t3lib_div::formatSize(strlen($dump_static)).'bytes written to '.substr($writeFile,strlen(PATH_site)),0,1); 02209 } 02210 } else { // Showing info about what tables to dump - and giving the link to execute it. 02211 $msg = 'Dumping table content for static tables:<br />'; 02212 $msg.= '<br />'.implode('<br />',$techInfo['static']).'<br />'; 02213 02214 // ... then feed that to this function which will make new CREATE statements of the same fields but based on the current database content. 02215 $this->content.=$this->doc->section('Static tables',$msg.'<hr /><strong><a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[writeSTATICdump]=1').'">Write current static table contents to ext_tables_static+adt.sql now!</a></strong>',0,1); 02216 $this->content.=$this->doc->spacer(20); 02217 } 02218 } 02219 02220 // Table and field definitions: 02221 if (is_array($techInfo['dump_tf'])) { 02222 $dump_tf_array = $this->getTableAndFieldStructure($techInfo['dump_tf']); 02223 $dump_tf = $this->dumpTableAndFieldStructure($dump_tf_array); 02224 if ($this->CMD['writeTFdump']) { 02225 $writeFile = $absPath.'ext_tables.sql'; 02226 if (@is_file($writeFile)) { 02227 t3lib_div::writeFile($writeFile,$dump_tf); 02228 $this->content.=$this->doc->section('Table and field structure required',t3lib_div::formatSize(strlen($dump_tf)).'bytes written to '.substr($writeFile,strlen(PATH_site)),0,1); 02229 } 02230 } else { 02231 $msg = 'Dumping current database structure for:<br />'; 02232 if (is_array($techInfo['tables'])) { 02233 $msg.= '<br /><strong>Tables:</strong><br />'.implode('<br />',$techInfo['tables']).'<br />'; 02234 } 02235 if (is_array($techInfo['fields'])) { 02236 $msg.= '<br /><strong>Solo-fields:</strong><br />'.implode('<br />',$techInfo['fields']).'<br />'; 02237 } 02238 02239 // ... then feed that to this function which will make new CREATE statements of the same fields but based on the current database content. 02240 $this->content.=$this->doc->section('Table and field structure required',$msg.'<hr /><strong><a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[writeTFdump]=1').'">Write this dump to ext_tables.sql now!</a></strong><hr /> 02241 <pre>'.htmlspecialchars($dump_tf).'</pre>',0,1); 02242 02243 02244 $details = ' This dump is based on two factors:<br /> 02245 <ul> 02246 <li>1) All tablenames in ext_tables.sql which are <em>not</em> found in the "modify_tables" list in ext_emconf.php are dumped with the current database structure.</li> 02247 <li>2) For any tablenames which <em>are</em> listed in "modify_tables" all fields and keys found for the table in ext_tables.sql will be re-dumped with the fresh equalents from the database.</li> 02248 </ul> 02249 Bottomline is: Whole tables are dumped from database with no regard to which fields and keys are defined in ext_tables.sql. But for tables which are only modified, any NEW fields added to the database must in some form or the other exist in the ext_tables.sql file as well.<br />'; 02250 $this->content.=$this->doc->section('',$details); 02251 } 02252 } 02253 } 02254 02262 function getFileListOfExtension($extKey,$conf) { 02263 $content = ''; 02264 $extPath = $this->getExtPath($extKey,$conf['type']); 02265 02266 if ($extPath) { 02267 // Read files: 02268 $fileArr = array(); 02269 $fileArr = t3lib_div::getAllFilesAndFoldersInPath($fileArr,$extPath); 02270 02271 // Start table: 02272 $lines = array(); 02273 $totalSize = 0; 02274 02275 // Header: 02276 $lines[] = ' 02277 <tr class="bgColor5"> 02278 <td>File:</td> 02279 <td>Size:</td> 02280 <td>Edit:</td> 02281 </tr>'; 02282 02283 foreach($fileArr as $file) { 02284 $fI = t3lib_div::split_fileref($file); 02285 $lines[] = ' 02286 <tr class="bgColor4"> 02287 <td><a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[downloadFile]='.rawurlencode($file)).'" title="Download...">'.substr($file,strlen($extPath)).'</a></td> 02288 <td>'.t3lib_div::formatSize(filesize($file)).'</td> 02289 <td>'.(!in_array($extKey,$this->requiredExt)&&t3lib_div::inList($this->editTextExtensions,($fI['fileext']?$fI['fileext']:$fI['filebody']))?'<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[editFile]='.rawurlencode($file)).'">Edit file</a>':'').'</td> 02290 </tr>'; 02291 $totalSize+=filesize($file); 02292 } 02293 02294 $lines[] = ' 02295 <tr class="bgColor6"> 02296 <td><strong>Total:</strong></td> 02297 <td><strong>'.t3lib_div::formatSize($totalSize).'</strong></td> 02298 <td> </td> 02299 </tr>'; 02300 02301 $content = ' 02302 Path: '.$extPath.'<br /><br /> 02303 <table border="0" cellpadding="1" cellspacing="2">'.implode('',$lines).'</table>'; 02304 } 02305 02306 return $content; 02307 } 02308 02316 function extDelete($extKey,$extInfo) { 02317 $absPath = $this->getExtPath($extKey,$extInfo['type']); 02318 if (t3lib_extMgm::isLoaded($extKey)) { 02319 return 'This extension is currently installed (loaded and active) and so cannot be deleted!'; 02320 } elseif (!$this->deleteAsType($extInfo['type'])) { 02321 return 'You cannot delete (and install/update) extensions in the '.$this->typeLabels[$extInfo['type']].' scope.'; 02322 } elseif (t3lib_div::inList('G,L',$extInfo['type'])) { 02323 if ($this->CMD['doDelete'] && !strcmp($absPath,$this->CMD['absPath'])) { 02324 $res = $this->removeExtDirectory($absPath); 02325 if ($res) { 02326 return 'ERROR: Could not remove extension directory "'.$absPath.'". Had the following errors:<br /><br />'. 02327 nl2br($res); 02328 } else { 02329 return 'Removed extension in path "'.$absPath.'"!'; 02330 } 02331 } else { 02332 $onClick = "if (confirm('Are you sure you want to delete this extension from the server?')) {window.location.href='index.php?CMD[showExt]=".$extKey.'&CMD[doDelete]=1&CMD[absPath]='.rawurlencode($absPath)."';}"; 02333 $content.= '<a href="#" onclick="'.htmlspecialchars($onClick).' return false;"><strong>DELETE EXTENSION FROM SERVER</strong> (in the "'.$this->typeLabels[$extInfo['type']].'" location "'.substr($absPath,strlen(PATH_site)).'")!</a>'; 02334 $content.= '<br /><br />(Maybe you should make a backup first, see above.)'; 02335 return $content; 02336 } 02337 } else return 'Extension is not a global or local extension and cannot be removed.'; 02338 } 02339 02347 function extUpdateEMCONF($extKey,$extInfo) { 02348 $absPath = $this->getExtPath($extKey,$extInfo['type']); 02349 if ($this->CMD['doUpdateEMCONF']) { 02350 return $this->updateLocalEM_CONF($extKey,$extInfo); 02351 } else { 02352 $onClick = "if (confirm('Are you sure you want to update EM_CONF?')) {window.location.href='index.php?CMD[showExt]=".$extKey."&CMD[doUpdateEMCONF]=1';}"; 02353 $content.= '<a href="#" onclick="'.htmlspecialchars($onClick).' return false;"><strong>Update extension EM_CONF file</strong> (in the "'.$this->typeLabels[$extInfo['type']].'" location "'.substr($absPath,strlen(PATH_site)).'")!</a>'; 02354 $content.= '<br /><br />If files are changed, added or removed to an extension this is normally detected and displayed so you know that this extension has been locally altered and may need to be uploaded or at least not overridden.<br /> 02355 Updating this file will first of all reset this registration.'; 02356 return $content; 02357 } 02358 } 02359 02367 function extBackup($extKey,$extInfo) { 02368 $uArr = $this->makeUploadArray($extKey,$extInfo); 02369 if (is_array($uArr)) { 02370 $backUpData = $this->terConnection->makeUploadDataFromArray($uArr); 02371 $filename = 'T3X_'.$extKey.'-'.str_replace('.','_',$extInfo['EM_CONF']['version']).'-z-'.date('YmdHi').'.t3x'; 02372 if (intval($this->CMD['doBackup'])==1) { 02373 header('Content-Type: application/octet-stream'); 02374 header('Content-Disposition: attachment; filename='.$filename); 02375 echo $backUpData; 02376 exit; 02377 } elseif ($this->CMD['dumpTables']) { 02378 $filename='T3X_'.$extKey; 02379 $cTables = count(explode(',',$this->CMD['dumpTables'])); 02380 if ($cTables>1) { 02381 $filename.='-'.$cTables.'tables'; 02382 } else { 02383 $filename.='-'.$this->CMD['dumpTables']; 02384 } 02385 $filename.='+adt.sql'; 02386 02387 header('Content-Type: application/octet-stream'); 02388 header('Content-Disposition: attachment; filename='.$filename); 02389 echo $this->dumpStaticTables($this->CMD['dumpTables']); 02390 exit; 02391 } else { 02392 $techInfo = $this->makeDetailedExtensionAnalysis($extKey,$extInfo); 02393 $lines=array(); 02394 $lines[]='<tr class="bgColor5"><td colspan="2"><strong>Make selection:</strong></td></tr>'; 02395 $lines[]='<tr class="bgColor4"><td><strong>Extension files:</strong></td><td>'. 02396 '<a href="'.htmlspecialchars('index.php?CMD[doBackup]=1&CMD[showExt]='.$extKey).'">Download extension "'.$extKey.'" as a file</a><br />('.$filename.', '.t3lib_div::formatSize(strlen($backUpData)).', MD5: '.md5($backUpData).')<br /></td></tr>'; 02397 02398 if (is_array($techInfo['tables'])) { $lines[]='<tr class="bgColor4"><td><strong>Data tables:</strong></td><td>'.$this->extBackup_dumpDataTablesLine($techInfo['tables'],$extKey).'</td></tr>'; } 02399 if (is_array($techInfo['static'])) { $lines[]='<tr class="bgColor4"><td><strong>Static tables:</strong></td><td>'.$this->extBackup_dumpDataTablesLine($techInfo['static'],$extKey).'</td></tr>'; } 02400 02401 $content = '<table border="0" cellpadding="2" cellspacing="2">'.implode('',$lines).'</table>'; 02402 return $content; 02403 } 02404 } else die('Error...'); 02405 } 02406 02414 function extBackup_dumpDataTablesLine($tablesArray,$extKey) { 02415 $tables = array(); 02416 $tablesNA = array(); 02417 02418 foreach($tablesArray as $tN) { 02419 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('count(*)', $tN, ''); 02420 if (!$GLOBALS['TYPO3_DB']->sql_error()) { 02421 $row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res); 02422 $tables[$tN]='<tr><td> </td><td><a href="'.htmlspecialchars('index.php?CMD[dumpTables]='.rawurlencode($tN).'&CMD[showExt]='.$extKey).'" title="Dump table \''.$tN.'\'">'.$tN.'</a></td><td> </td><td>'.$row[0].' records</td></tr>'; 02423 } else { 02424 $tablesNA[$tN]='<tr><td> </td><td>'.$tN.'</td><td> </td><td>Did not exist.</td></tr>'; 02425 } 02426 } 02427 $label = '<table border="0" cellpadding="0" cellspacing="0">'.implode('',array_merge($tables,$tablesNA)).'</table>';// Candidate for t3lib_div::array_merge() if integer-keys will some day make trouble... 02428 if (count($tables)) { 02429 $label = '<a href="'.htmlspecialchars('index.php?CMD[dumpTables]='.rawurlencode(implode(',',array_keys($tables))).'&CMD[showExt]='.$extKey).'" title="Dump all existing tables.">Download all data from:</a><br /><br />'.$label; 02430 } else $label = 'Nothing to dump...<br /><br />'.$label; 02431 return $label; 02432 } 02433 02442 function extInformationArray($extKey,$extInfo,$remote=0) { 02443 $lines=array(); 02444 $lines[]='<tr class="bgColor5"><td colspan="2"><strong>General information:</strong></td>'.$this->helpCol('').'</tr>'; 02445 $lines[]='<tr class="bgColor4"><td>Title:</td><td>'.$extInfo['EM_CONF']['_icon'].$extInfo['EM_CONF']['title'].'</td>'.$this->helpCol('title').'</tr>'; 02446 $lines[]='<tr class="bgColor4"><td>Description:</td><td>'.nl2br(htmlspecialchars($extInfo['EM_CONF']['description'])).'</td>'.$this->helpCol('description').'</tr>'; 02447 $lines[]='<tr class="bgColor4"><td>Author:</td><td>'.$this->wrapEmail($extInfo['EM_CONF']['author'].($extInfo['EM_CONF']['author_email'] ? ' <'.$extInfo['EM_CONF']['author_email'].'>' : ''),$extInfo['EM_CONF']['author_email']).($extInfo['EM_CONF']['author_company']?', '.$extInfo['EM_CONF']['author_company']:''). 02448 '</td>'.$this->helpCol('description').'</tr>'; 02449 02450 $lines[]='<tr class="bgColor4"><td>Version:</td><td>'.$extInfo['EM_CONF']['version'].'</td>'.$this->helpCol('version').'</tr>'; 02451 $lines[]='<tr class="bgColor4"><td>Category:</td><td>'.$this->categories[$extInfo['EM_CONF']['category']].'</td>'.$this->helpCol('category').'</tr>'; 02452 $lines[]='<tr class="bgColor4"><td>State:</td><td>'.$this->states[$extInfo['EM_CONF']['state']].'</td>'.$this->helpCol('state').'</tr>'; 02453 $lines[]='<tr class="bgColor4"><td>Shy?</td><td>'.($extInfo['EM_CONF']['shy']?'Yes':'').'</td>'.$this->helpCol('shy').'</tr>'; 02454 $lines[]='<tr class="bgColor4"><td>Internal?</td><td>'.($extInfo['EM_CONF']['internal']?'Yes':'').'</td>'.$this->helpCol('internal').'</tr>'; 02455 02456 $lines[]='<tr class="bgColor4"><td>Depends on:</td><td>'.$this->depToString($extInfo['EM_CONF']['constraints']).'</td>'.$this->helpCol('dependencies').'</tr>'; 02457 $lines[]='<tr class="bgColor4"><td>Conflicts with:</td><td>'.$this->depToString($extInfo['EM_CONF']['constraints'],'conflicts').'</td>'.$this->helpCol('dependencies').'</tr>'; 02458 $lines[]='<tr class="bgColor4"><td>Suggests:</td><td>'.$this->depToString($extInfo['EM_CONF']['constraints'],'suggests').'</td>'.$this->helpCol('dependencies').'</tr>'; 02459 if (!$remote) { 02460 $lines[]='<tr class="bgColor4"><td>Priority:</td><td>'.$extInfo['EM_CONF']['priority'].'</td>'.$this->helpCol('priority').'</tr>'; 02461 $lines[]='<tr class="bgColor4"><td>Clear cache?</td><td>'.($extInfo['EM_CONF']['clearCacheOnLoad']?'Yes':'').'</td>'.$this->helpCol('clearCacheOnLoad').'</tr>'; 02462 $lines[]='<tr class="bgColor4"><td>Includes modules:</td><td>'.$extInfo['EM_CONF']['module'].'</td>'.$this->helpCol('module').'</tr>'; 02463 $lines[]='<tr class="bgColor4"><td>Lock Type?</td><td>'.($extInfo['EM_CONF']['lockType']?$extInfo['EM_CONF']['lockType']:'').'</td>'.$this->helpCol('lockType').'</tr>'; 02464 $lines[]='<tr class="bgColor4"><td>Modifies tables:</td><td>'.$extInfo['EM_CONF']['modify_tables'].'</td>'.$this->helpCol('modify_tables').'</tr>'; 02465 02466 // Installation status: 02467 $techInfo = $this->makeDetailedExtensionAnalysis($extKey,$extInfo,1); 02468 $lines[]='<tr><td> </td><td></td>'.$this->helpCol('').'</tr>'; 02469 $lines[]='<tr class="bgColor5"><td colspan="2"><strong>Installation status:</strong></td>'.$this->helpCol('').'</tr>'; 02470 $lines[]='<tr class="bgColor4"><td>Type of install:</td><td>'.$this->typeLabels[$extInfo['type']].' - <em>'.$this->typeDescr[$extInfo['type']].'</em></td>'.$this->helpCol('type').'</tr>'; 02471 $lines[]='<tr class="bgColor4"><td>Double installs?</td><td>'.$this->extInformationArray_dbInst($extInfo['doubleInstall'],$extInfo['type']).'</td>'.$this->helpCol('doubleInstall').'</tr>'; 02472 if (is_array($extInfo['files'])) { 02473 sort($extInfo['files']); 02474 $lines[]='<tr class="bgColor4"><td>Root files:</td><td>'.implode('<br />',$extInfo['files']).'</td>'.$this->helpCol('rootfiles').'</tr>'; 02475 } 02476 02477 if ($techInfo['tables']||$techInfo['static']||$techInfo['fields']) { 02478 if (!$remote && t3lib_extMgm::isLoaded($extKey)) { 02479 $tableStatus = $GLOBALS['TBE_TEMPLATE']->rfw(($techInfo['tables_error']?'<strong>Table error!</strong><br />Probably one or more required fields/tables are missing in the database!':''). 02480 ($techInfo['static_error']?'<strong>Static table error!</strong><br />The static tables are missing or empty!':'')); 02481 } else { 02482 $tableStatus = $techInfo['tables_error']||$techInfo['static_error'] ? 'The database will need to be updated when this extension is installed.' : 'All required tables are already in the database!'; 02483 } 02484 } 02485 02486 $lines[]='<tr class="bgColor4"><td>Database requirements:</td><td>'.$this->extInformationArray_dbReq($techInfo,1).'</td>'.$this->helpCol('dbReq').'</tr>'; 02487 $lines[]='<tr class="bgColor4"><td>Database status:</td><td>'.$tableStatus.'</td>'.$this->helpCol('dbStatus').'</tr>'; 02488 $lines[]='<tr class="bgColor4"><td>Flags:</td><td>'.(is_array($techInfo['flags'])?implode('<br />',$techInfo['flags']):'').'</td>'.$this->helpCol('flags').'</tr>'; 02489 $lines[]='<tr class="bgColor4"><td>Config template?</td><td>'.($techInfo['conf']?'Yes':'').'</td>'.$this->helpCol('conf').'</tr>'; 02490 $lines[]='<tr class="bgColor4"><td>TypoScript files:</td><td>'.(is_array($techInfo['TSfiles'])?implode('<br />',$techInfo['TSfiles']):'').'</td>'.$this->helpCol('TSfiles').'</tr>'; 02491 $lines[]='<tr class="bgColor4"><td>Language files:</td><td>'.(is_array($techInfo['locallang'])?implode('<br />',$techInfo['locallang']):'').'</td>'.$this->helpCol('locallang').'</tr>'; 02492 $lines[]='<tr class="bgColor4"><td>Upload folder:</td><td>'.($techInfo['uploadfolder']?$techInfo['uploadfolder']:'').'</td>'.$this->helpCol('uploadfolder').'</tr>'; 02493 $lines[]='<tr class="bgColor4"><td>Create directories:</td><td>'.(is_array($techInfo['createDirs'])?implode('<br />',$techInfo['createDirs']):'').'</td>'.$this->helpCol('createDirs').'</tr>'; 02494 $lines[]='<tr class="bgColor4"><td>Module names:</td><td>'.(is_array($techInfo['moduleNames'])?implode('<br />',$techInfo['moduleNames']):'').'</td>'.$this->helpCol('moduleNames').'</tr>'; 02495 $lines[]='<tr class="bgColor4"><td>Class names:</td><td>'.(is_array($techInfo['classes'])?implode('<br />',$techInfo['classes']):'').'</td>'.$this->helpCol('classNames').'</tr>'; 02496 $lines[]='<tr class="bgColor4"><td>Code warnings:<br />(developer-relevant)</td><td>'.(is_array($techInfo['errors'])?$GLOBALS['TBE_TEMPLATE']->rfw(implode('<br />',$techInfo['errors'])):'').'</td>'.$this->helpCol('errors').'</tr>'; 02497 $lines[]='<tr class="bgColor4"><td>Naming annoyances:<br />(developer-relevant)</td><td>'.(is_array($techInfo['NSerrors']) ? (!t3lib_div::inList($this->nameSpaceExceptions,$extKey)?t3lib_div::view_array($techInfo['NSerrors']):$GLOBALS['TBE_TEMPLATE']->dfw('[exception]')) : '').'</td>'.$this->helpCol('NSerrors').'</tr>'; 02498 02499 $currentMd5Array = $this->serverExtensionMD5Array($extKey,$extInfo); 02500 $affectedFiles=''; 02501 02502 $msgLines=array(); 02503 if (strcmp($extInfo['EM_CONF']['_md5_values_when_last_written'],serialize($currentMd5Array))) { 02504 $msgLines[] = $GLOBALS['TBE_TEMPLATE']->rfw('<br /><strong>A difference between the originally installed version and the current was detected!</strong>'); 02505 $affectedFiles = $this->findMD5ArrayDiff($currentMd5Array,unserialize($extInfo['EM_CONF']['_md5_values_when_last_written'])); 02506 if (count($affectedFiles)) $msgLines[] = '<br /><strong>Modified files:</strong><br />'.$GLOBALS['TBE_TEMPLATE']->rfw(implode('<br />',$affectedFiles)); 02507 } 02508 $lines[]='<tr class="bgColor4"><td>Files changed?</td><td>'.implode('<br />',$msgLines).'</td>'.$this->helpCol('filesChanged').'</tr>'; 02509 } 02510 02511 return '<table border="0" cellpadding="1" cellspacing="2"> 02512 '.implode(' 02513 ',$lines).' 02514 </table>'; 02515 } 02516 02524 function extInformationArray_dbReq($techInfo,$tableHeader=0) { 02525 return nl2br(trim((is_array($techInfo['tables'])?($tableHeader?"\n\n<strong>Tables:</strong>\n":'').implode(chr(10),$techInfo['tables']):''). 02526 (is_array($techInfo['static'])?"\n\n<strong>Static tables:</strong>\n".implode(chr(10),$techInfo['static']):''). 02527 (is_array($techInfo['fields'])?"\n\n<strong>Additional fields:</strong>\n".implode('<hr />',$techInfo['fields']):''))); 02528 } 02529 02537 function extInformationArray_dbInst($dbInst,$current) { 02538 if (strlen($dbInst)>1) { 02539 $others = array(); 02540 for($a=0;$a<strlen($dbInst);$a++) { 02541 if (substr($dbInst,$a,1)!=$current) { 02542 $others[]='"'.$this->typeLabels[substr($dbInst,$a,1)].'"'; 02543 } 02544 } 02545 return $GLOBALS['TBE_TEMPLATE']->rfw('A '.implode(' and ',$others).' extension with this key is also available on the server, but cannot be loaded because the "'.$this->typeLabels[$current].'" version takes precedence.'); 02546 } else return ''; 02547 } 02548 02556 function getRepositoryUploadForm($extKey,$extInfo) { 02557 $content.=' 02558 <input type="hidden" name="CMD[showExt]" value="'.$extKey.'" /> 02559 <input type="hidden" name="em[action]" value="doUpload" /> 02560 <table border="0" cellpadding="2" cellspacing="1"> 02561 <tr class="bgColor4"> 02562 <td>Repository Username:</td> 02563 <td><input'.$this->doc->formWidth(20).' type="text" name="em[user][fe_u]" value="'.$this->fe_user['username'].'" /></td> 02564 </tr> 02565 <tr class="bgColor4"> 02566 <td>Repository Password:</td> 02567 <td><input'.$this->doc->formWidth(20).' type="password" name="em[user][fe_p]" value="'.$this->fe_user['password'].'" /></td> 02568 </tr> 02569 <tr class="bgColor4"> 02570 <td>Changelog for upload:</td> 02571 <td><textarea'.$this->doc->formWidth(30,1).' rows="5" name="em[upload][comment]"></textarea></td> 02572 </tr> 02573 <tr class="bgColor4"> 02574 <td>Upload command:</td> 02575 <td nowrap="nowrap"> 02576 <input type="radio" name="em[upload][mode]" value="new_dev" checked="checked" /> New development version (latest x.x.<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('x+1').'</strong>)<br /> 02577 <input type="radio" name="em[upload][mode]" value="latest" /> Override <em>this</em> development version ('.$extInfo['EM_CONF']['version'].')<br /> 02578 <input type="radio" name="em[upload][mode]" value="new_sub" /> New sub version (latest x.<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('x+1').'</strong>.0)<br /> 02579 <input type="radio" name="em[upload][mode]" value="new_main" /> New main version (latest <strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('x+1').'</strong>.0.0)<br /> 02580 <input type="radio" name="em[upload][mode]" value="custom" /> This version: <input type="text" name="em[upload][version]" /><br /> 02581 </td> 02582 </tr> 02583 <tr class="bgColor4"> 02584 <td> </td> 02585 <td><input type="submit" name="submit" value="Upload extension" /> 02586 </td> 02587 </tr> 02588 </table> 02589 '; 02590 02591 return $content; 02592 } 02593 02594 02595 02596 02597 02598 02599 02600 02601 02602 02603 /*********************************** 02604 * 02605 * Extension list rendering 02606 * 02607 **********************************/ 02608 02617 function extensionListRowHeader($trAttrib,$cells,$import=0) { 02618 $cells[] = '<td></td>'; 02619 $cells[] = '<td>Title:</td>'; 02620 02621 if (!$this->MOD_SETTINGS['display_details']) { 02622 $cells[] = '<td>Description:</td>'; 02623 $cells[] = '<td>Author:</td>'; 02624 } elseif ($this->MOD_SETTINGS['display_details']==2) { 02625 $cells[] = '<td>Priority:</td>'; 02626 $cells[] = '<td>Mod.Tables:</td>'; 02627 $cells[] = '<td>Modules:</td>'; 02628 $cells[] = '<td>Cl.Cache?</td>'; 02629 $cells[] = '<td>Internal?</td>'; 02630 $cells[] = '<td>Shy?</td>'; 02631 } elseif ($this->MOD_SETTINGS['display_details']==3) { 02632 $cells[] = '<td>Tables/Fields:</td>'; 02633 $cells[] = '<td>TS-files:</td>'; 02634 $cells[] = '<td>Affects:</td>'; 02635 $cells[] = '<td>Modules:</td>'; 02636 $cells[] = '<td>Config?</td>'; 02637 $cells[] = '<td>Code warnings:</td>'; 02638 } elseif ($this->MOD_SETTINGS['display_details']==4) { 02639 $cells[] = '<td>locallang:</td>'; 02640 $cells[] = '<td>Classes:</td>'; 02641 $cells[] = '<td>Code warnings:</td>'; 02642 $cells[] = '<td>Nameing annoyances:</td>'; 02643 } elseif ($this->MOD_SETTINGS['display_details']==5) { 02644 $cells[] = '<td>Changed files:</td>'; 02645 } else { 02646 $cells[] = '<td>Extension key:</td>'; 02647 $cells[] = '<td>Version:</td>'; 02648 if (!$import) { 02649 $cells[] = '<td>DL:</td>'; 02650 $cells[] = '<td>Doc:</td>'; 02651 $cells[] = '<td>Type:</td>'; 02652 } else { 02653 $cells[] = '<td class="bgColor6"'.$this->labelInfo('Current version of the extension on this server. If colored red there is a newer version in repository! Then you should upgrade.').'>Cur. Ver:</td>'; 02654 $cells[] = '<td class="bgColor6"'.$this->labelInfo('Current type of installation of the extension on this server.').'>Cur. Type:</td>'; 02655 $cells[] = '<td'.$this->labelInfo('Number of downloads, all versions/this version').'>DL:</td>'; 02656 } 02657 $cells[] = '<td>State:</td>'; 02658 } 02659 return ' 02660 <tr'.$trAttrib.'> 02661 '.implode(' 02662 ',$cells).' 02663 </tr>'; 02664 } 02665 02678 function extensionListRow($extKey,$extInfo,$cells,$bgColorClass='',$inst_list=array(),$import=0,$altLinkUrl='') { 02679 02680 // Icon: 02681 $imgInfo = @getImageSize($this->getExtPath($extKey,$extInfo['type']).'/ext_icon.gif'); 02682 if (is_array($imgInfo)) { 02683 $cells[] = '<td><img src="'.$GLOBALS['BACK_PATH'].$this->typeRelPaths[$extInfo['type']].$extKey.'/ext_icon.gif'.'" '.$imgInfo[3].' alt="" /></td>'; 02684 } elseif ($extInfo['_ICON']) { 02685 $cells[] = '<td>'.$extInfo['_ICON'].'</td>'; 02686 } else { 02687 $cells[] = '<td><img src="clear.gif" width="1" height="1" alt="" /></td>'; 02688 } 02689 02690 // Extension title: 02691 $cells[] = '<td nowrap="nowrap"><a href="'.htmlspecialchars($altLinkUrl?$altLinkUrl:'index.php?CMD[showExt]='.$extKey.'&SET[singleDetails]=info').'" title="'.$extKey.'"'/*.($extInfo['EM_CONF']['shy'] ? ' style="color:#666;" ' : '')*/.'>'.t3lib_div::fixed_lgd($extInfo['EM_CONF']['title']?$extInfo['EM_CONF']['title']:'<em>'.$extKey.'</em>',40).'</a></td>'; 02692 02693 // Based on which display mode you will see more or less details: 02694 if (!$this->MOD_SETTINGS['display_details']) { 02695 $cells[] = '<td>'.htmlspecialchars(t3lib_div::fixed_lgd($extInfo['EM_CONF']['description'],400)).'<br /><img src="clear.gif" width="300" height="1" alt="" /></td>'; 02696 $cells[] = '<td nowrap="nowrap">'.($extInfo['EM_CONF']['author_email'] ? '<a href="mailto:'.htmlspecialchars($extInfo['EM_CONF']['author_email']).'">' : '').htmlspecialchars($extInfo['EM_CONF']['author']).($extInfo['EM_CONF']['author_email'] ? '</a>' : '').($extInfo['EM_CONF']['author_company'] ? '<br />'.htmlspecialchars($extInfo['EM_CONF']['author_company']) : '').'</td>'; 02697 } elseif ($this->MOD_SETTINGS['display_details']==2) { 02698 $cells[] = '<td nowrap="nowrap">'.$extInfo['EM_CONF']['priority'].'</td>'; 02699 $cells[] = '<td nowrap="nowrap">'.implode('<br />',t3lib_div::trimExplode(',',$extInfo['EM_CONF']['modify_tables'],1)).'</td>'; 02700 $cells[] = '<td nowrap="nowrap">'.$extInfo['EM_CONF']['module'].'</td>'; 02701 $cells[] = '<td nowrap="nowrap">'.($extInfo['EM_CONF']['clearCacheOnLoad'] ? 'Yes' : '').'</td>'; 02702 $cells[] = '<td nowrap="nowrap">'.($extInfo['EM_CONF']['internal'] ? 'Yes' : '').'</td>'; 02703 $cells[] = '<td nowrap="nowrap">'.($extInfo['EM_CONF']['shy'] ? 'Yes' : '').'</td>'; 02704 } elseif ($this->MOD_SETTINGS['display_details']==3) { 02705 $techInfo = $this->makeDetailedExtensionAnalysis($extKey,$extInfo); 02706 02707 $cells[] = '<td>'.$this->extInformationArray_dbReq($techInfo). 02708 '</td>'; 02709 $cells[] = '<td nowrap="nowrap">'.(is_array($techInfo['TSfiles']) ? implode('<br />',$techInfo['TSfiles']) : '').'</td>'; 02710 $cells[] = '<td nowrap="nowrap">'.(is_array($techInfo['flags']) ? implode('<br />',$techInfo['flags']) : '').'</td>'; 02711 $cells[] = '<td nowrap="nowrap">'.(is_array($techInfo['moduleNames']) ? implode('<br />',$techInfo['moduleNames']) : '').'</td>'; 02712 $cells[] = '<td nowrap="nowrap">'.($techInfo['conf'] ? 'Yes' : '').'</td>'; 02713 $cells[] = '<td>'. 02714 $GLOBALS['TBE_TEMPLATE']->rfw((t3lib_extMgm::isLoaded($extKey)&&$techInfo['tables_error']?'<strong>Table error!</strong><br />Probably one or more required fields/tables are missing in the database!':''). 02715 (t3lib_extMgm::isLoaded($extKey)&&$techInfo['static_error']?'<strong>Static table error!</strong><br />The static tables are missing or empty!':'')). 02716 '</td>'; 02717 } elseif ($this->MOD_SETTINGS['display_details']==4) { 02718 $techInfo=$this->makeDetailedExtensionAnalysis($extKey,$extInfo,1); 02719 02720 $cells[] = '<td>'.(is_array($techInfo['locallang']) ? implode('<br />',$techInfo['locallang']) : '').'</td>'; 02721 $cells[] = '<td>'.(is_array($techInfo['classes']) ? implode('<br />',$techInfo['classes']) : '').'</td>'; 02722 $cells[] = '<td>'.(is_array($techInfo['errors']) ? $GLOBALS['TBE_TEMPLATE']->rfw(implode('<hr />',$techInfo['errors'])) : '').'</td>'; 02723 $cells[] = '<td>'.(is_array($techInfo['NSerrors']) ? (!t3lib_div::inList($this->nameSpaceExceptions,$extKey) ? t3lib_div::view_array($techInfo['NSerrors']) : $GLOBALS['TBE_TEMPLATE']->dfw('[exception]')) :'').'</td>'; 02724 } elseif ($this->MOD_SETTINGS['display_details']==5) { 02725 $currentMd5Array = $this->serverExtensionMD5Array($extKey,$extInfo); 02726 $affectedFiles = ''; 02727 $msgLines = array(); 02728 $msgLines[] = 'Files: '.count($currentMd5Array); 02729 if (strcmp($extInfo['EM_CONF']['_md5_values_when_last_written'],serialize($currentMd5Array))) { 02730 $msgLines[] = $GLOBALS['TBE_TEMPLATE']->rfw('<br /><strong>A difference between the originally installed version and the current was detected!</strong>'); 02731 $affectedFiles = $this->findMD5ArrayDiff($currentMd5Array,unserialize($extInfo['EM_CONF']['_md5_values_when_last_written'])); 02732 if (count($affectedFiles)) $msgLines[] = '<br /><strong>Modified files:</strong><br />'.$GLOBALS['TBE_TEMPLATE']->rfw(implode('<br />',$affectedFiles)); 02733 } 02734 $cells[] = '<td>'.implode('<br />',$msgLines).'</td>'; 02735 } else { 02736 // Default view: 02737 $verDiff = $inst_list[$extKey] && $this->versionDifference($extInfo['EM_CONF']['version'],$inst_list[$extKey]['EM_CONF']['version'],$this->versionDiffFactor); 02738 02739 $cells[] = '<td nowrap="nowrap"><em>'.$extKey.'</em></td>'; 02740 $cells[] = '<td nowrap="nowrap">'.($verDiff ? '<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw(htmlspecialchars($extInfo['EM_CONF']['version'])).'</strong>' : $extInfo['EM_CONF']['version']).'</td>'; 02741 if (!$import) { // Listing extenson on LOCAL server: 02742 // Extension Download: 02743 $cells[] = '<td nowrap="nowrap"><a href="'.htmlspecialchars('index.php?CMD[doBackup]=1&SET[singleDetails]=backup&CMD[showExt]='.$extKey).'"><img src="download.png" width="13" height="12" title="Download" alt="" /></a></td>'; 02744 02745 // Manual download 02746 $fileP = PATH_site.$this->typePaths[$extInfo['type']].$extKey.'/doc/manual.sxw'; 02747 $cells[] = '<td nowrap="nowrap">'. 02748 ($this->typePaths[$extInfo['type']] && @is_file($fileP)?'<a href="'.htmlspecialchars(t3lib_div::resolveBackPath($this->doc->backPath.'../'.$this->typePaths[$extInfo['type']].$extKey.'/doc/manual.sxw')).'" target="_blank"><img src="oodoc.gif" width="13" height="16" title="Local Open Office Manual" alt="" /></a>':''). 02749 '</td>'; 02750 $cells[] = '<td nowrap="nowrap">'.$this->typeLabels[$extInfo['type']].(strlen($extInfo['doubleInstall'])>1?'<strong> '.$GLOBALS['TBE_TEMPLATE']->rfw($extInfo['doubleInstall']).'</strong>':'').'</td>'; 02751 } else { // Listing extensions from REMOTE repository: 02752 $inst_curVer = $inst_list[$extKey]['EM_CONF']['version']; 02753 if (isset($inst_list[$extKey])) { 02754 if ($verDiff) $inst_curVer = '<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw($inst_curVer).'</strong>'; 02755 } 02756 $cells[] = '<td nowrap="nowrap">'.$inst_curVer.'</td>'; 02757 $cells[] = '<td nowrap="nowrap">'.$this->typeLabels[$inst_list[$extKey]['type']].(strlen($inst_list[$extKey]['doubleInstall'])>1?'<strong> '.$GLOBALS['TBE_TEMPLATE']->rfw($inst_list[$extKey]['doubleInstall']).'</strong>':'').'</td>'; 02758 $cells[] = '<td nowrap="nowrap">'.($extInfo['downloadcounter_all']?$extInfo['downloadcounter_all']:' ').'/'.($extInfo['downloadcounter']?$extInfo['downloadcounter']:' ').'</td>'; 02759 } 02760 $cells[] = '<td nowrap="nowrap" class="extstate" style="background-color:'.$this->stateColors[$extInfo['EM_CONF']['state']].';">'.$this->states[$extInfo['EM_CONF']['state']].'</td>'; 02761 } 02762 02763 if($this->xmlhandler->getReviewState($extKey,$extInfo['EM_CONF']['version'])<1) { 02764 $bgclass = ' class="unsupported-ext"'; 02765 } else { 02766 $bgclass = ' class="'.($bgColorClass?$bgColorClass:'bgColor4').'"'; 02767 } 02768 02769 return ' 02770 <tr'.$bgclass.'> 02771 '.implode(' 02772 ',$cells).' 02773 </tr>'; 02774 } 02775 02776 02777 02778 02779 02780 02781 /************************************ 02782 * 02783 * Output helper functions 02784 * 02785 ************************************/ 02786 02794 function wrapEmail($str,$email) { 02795 if ($email) { 02796 $str = '<a href="mailto:'.htmlspecialchars($email).'">'.htmlspecialchars($str).'</a>'; 02797 } 02798 return $str; 02799 } 02800 02807 function helpCol($key) { 02808 global $BE_USER; 02809 if ($BE_USER->uc['edit_showFieldHelp']) { 02810 $hT = trim(t3lib_BEfunc::helpText($this->descrTable,'emconf_'.$key,$this->doc->backPath)); 02811 return '<td>'.($hT?$hT:t3lib_BEfunc::helpTextIcon($this->descrTable,'emconf_'.$key,$this->doc->backPath)).'</td>'; 02812 } else { 02813 return ''; 02814 } 02815 } 02816 02823 function labelInfo($str) { 02824 return ' title="'.htmlspecialchars($str).'" style="cursor:help;"'; 02825 } 02826 02835 function extensionTitleIconHeader($extKey,$extInfo,$align='top') { 02836 $imgInfo = @getImageSize($this->getExtPath($extKey,$extInfo['type']).'/ext_icon.gif'); 02837 $out = ''; 02838 if (is_array($imgInfo)) { 02839 $out.= '<img src="'.$GLOBALS['BACK_PATH'].$this->typeRelPaths[$extInfo['type']].$extKey.'/ext_icon.gif" '.$imgInfo[3].' align="'.$align.'" alt="" />'; 02840 } 02841 $out.= $extInfo['EM_CONF']['title'] ? htmlspecialchars(t3lib_div::fixed_lgd($extInfo['EM_CONF']['title'],40)) : '<em>'.$extKey.'</em>'; 02842 return $out; 02843 } 02844 02850 function removeButton() { 02851 return '<img src="uninstall.gif" width="16" height="16" title="Remove extension" align="top" alt="" />'; 02852 } 02853 02859 function installButton() { 02860 return '<img src="install.gif" width="16" height="16" title="Install extension..." align="top" alt="" />'; 02861 } 02862 02868 function noImportMsg() { 02869 return '<img src="'.$this->doc->backPath.'gfx/icon_warning2.gif" width="18" height="16" align="top" alt="" /><strong>Import to both local and global path is disabled in TYPO3_CONF_VARS!</strong>'; 02870 } 02871 02881 function depToString($dep,$type='depends') { 02882 if(is_array($dep)) { 02883 unset($dep[$type]['php']); 02884 unset($dep[$type]['typo3']); 02885 $s = (count($dep[$type])) ? implode(',', array_keys($dep[$type])) : ''; 02886 return $s; 02887 } 02888 return ''; 02889 } 02890 02900 function stringToDep($dep) { 02901 $constraint = array(); 02902 if(is_string($dep) && strlen($dep)) { 02903 $dep = explode(',',$dep); 02904 foreach($dep as $v) { 02905 $constraint[$v] = ''; 02906 } 02907 } 02908 return $constraint; 02909 } 02910 02911 02912 02913 02914 02915 02916 02917 02918 /******************************** 02919 * 02920 * Read information about all available extensions 02921 * 02922 *******************************/ 02923 02930 function getInstalledExtensions() { 02931 $list = array(); 02932 $cat = $this->defaultCategories; 02933 02934 $path = PATH_site.TYPO3_mainDir.'sysext/'; 02935 $this->getInstExtList($path,$list,$cat,'S'); 02936 02937 $path = PATH_site.TYPO3_mainDir.'ext/'; 02938 $this->getInstExtList($path,$list,$cat,'G'); 02939 02940 $path = PATH_site.'typo3conf/ext/'; 02941 $this->getInstExtList($path,$list,$cat,'L'); 02942 02943 return array($list,$cat); 02944 } 02945 02957 function getInstExtList($path,&$list,&$cat,$type) { 02958 02959 if (@is_dir($path)) { 02960 $extList = t3lib_div::get_dirs($path); 02961 if (is_array($extList)) { 02962 foreach($extList as $extKey) { 02963 if (@is_file($path.$extKey.'/ext_emconf.php')) { 02964 $emConf = $this->includeEMCONF($path.$extKey.'/ext_emconf.php', $extKey); 02965 if (is_array($emConf)) { 02966 if (is_array($list[$extKey])) { 02967 $list[$extKey]=array('doubleInstall'=>$list[$extKey]['doubleInstall']); 02968 } 02969 $list[$extKey]['doubleInstall'].= $type; 02970 $list[$extKey]['type'] = $type; 02971 $list[$extKey]['EM_CONF'] = $emConf; 02972 $list[$extKey]['files'] = t3lib_div::getFilesInDir($path.$extKey); 02973 02974 $this->setCat($cat,$list[$extKey], $extKey); 02975 } 02976 } 02977 } 02978 } 02979 } 02980 } 02981 02988 function fixEMCONF($emConf) { 02989 if(!isset($emConf['constraints']) || !isset($emConf['constraints']['depends']) || !isset($emConf['constraints']['conflicts']) || !isset($emConf['constraints']['suggests'])) { 02990 if(!isset($emConf['constraints']) || !isset($emConf['constraints']['depends'])) { 02991 $emConf['constraints']['depends'] = $this->stringToDep($emConf['dependencies']); 02992 if(strlen($emConf['PHP_version'])) { 02993 $versionRange = $this->splitVersionRange($emConf['PHP_version']); 02994 if(version_compare($versionRange[0],'3.0.0','<')) $versionRange[0] = '3.0.0'; 02995 if(version_compare($versionRange[1],'3.0.0','<')) $versionRange[1] = ''; 02996 $emConf['constraints']['depends']['php'] = implode('-',$versionRange); 02997 } 02998 if(strlen($emConf['TYPO3_version'])) { 02999 $versionRange = $this->splitVersionRange($emConf['TYPO3_version']); 03000 if(version_compare($versionRange[0],'3.5.0','<')) $versionRange[0] = '3.5.0'; 03001 if(version_compare($versionRange[1],'3.5.0','<')) $versionRange[1] = ''; 03002 $emConf['constraints']['depends']['typo3'] = implode('-',$versionRange); 03003 } 03004 } 03005 if(!isset($emConf['constraints']) || !isset($emConf['constraints']['conflicts'])) { 03006 $emConf['constraints']['conflicts'] = $this->stringToDep($emConf['conflicts']); 03007 } 03008 if(!isset($emConf['constraints']) || !isset($emConf['constraints']['suggests'])) { 03009 $emConf['constraints']['suggests'] = array(); 03010 } 03011 } elseif (isset($emConf['constraints']) && isset($emConf['dependencies'])) { 03012 $emConf['suggests'] = isset($emConf['suggests']) ? $emConf['suggests'] : array(); 03013 $emConf['dependencies'] = $this->depToString($emConf['constraints']); 03014 $emConf['conflicts'] = $this->depToString($emConf['constraints'], 'conflicts'); 03015 } 03016 03017 // sanity check for version numbers, intentionally only checks php and typo3 03018 if(isset($emConf['constraints']['depends']) && isset($emConf['constraints']['depends']['php'])) { 03019 $versionRange = $this->splitVersionRange($emConf['constraints']['depends']['php']); 03020 if(version_compare($versionRange[0],'3.0.0','<')) $versionRange[0] = '3.0.0'; 03021 if(version_compare($versionRange[1],'3.0.0','<')) $versionRange[1] = ''; 03022 $emConf['constraints']['depends']['php'] = implode('-',$versionRange); 03023 } 03024 if(isset($emConf['constraints']['depends']) && isset($emConf['constraints']['depends']['typo3'])) { 03025 $versionRange = $this->splitVersionRange($emConf['constraints']['depends']['typo3']); 03026 if(version_compare($versionRange[0],'3.5.0','<')) $versionRange[0] = '3.0.0'; 03027 if(version_compare($versionRange[1],'3.5.0','<')) $versionRange[1] = ''; 03028 $emConf['constraints']['depends']['typo3'] = implode('-',$versionRange); 03029 } 03030 03031 unset($emConf['private']); 03032 unset($emConf['download_password']); 03033 unset($emConf['TYPO3_version']); 03034 unset($emConf['PHP_version']); 03035 03036 return $emConf; 03037 } 03038 03048 function splitVersionRange($ver) { 03049 $versionRange = array(); 03050 if(strstr($ver, '-')) $versionRange = explode('-', $ver, 2); 03051 else { 03052 $versionRange[0] = $ver; 03053 $versionRange[1] = ''; 03054 } 03055 03056 return $versionRange; 03057 } 03058 03064 function prepareImportExtList() { 03065 $list = array(); 03066 $cat = $this->defaultCategories; 03067 $filepath = $this->getMirrorURL(); 03068 03069 reset($this->xmlhandler->extensionsXML); 03070 while (list($extKey, $data) = each($this->xmlhandler->extensionsXML)) { 03071 $GLOBALS['LANG']->csConvObj->convArray($data,'utf-8',$GLOBALS['LANG']->charSet); // is there a better place for conversion? 03072 $list[$extKey]['type'] = '_'; 03073 $version = array_keys($data['versions']); 03074 $list[$extKey]['_ICON'] = '<img alt="" src="'.$filepath.$extKey{0}.'/'.$extKey{1}.'/'.$extKey.'_'.end($version).'.gif" />'; 03075 $list[$extKey]['downloadcounter'] = $data['downloadcounter']; 03076 03077 foreach(array_keys($data['versions']) as $version) { 03078 $list[$extKey]['versions'][$version]['downloadcounter'] = $data['versions'][$version]['downloadcounter']; 03079 03080 $list[$extKey]['versions'][$version]['EM_CONF'] = array( 03081 'version' => $version, 03082 'title' => $data['versions'][$version]['title'], 03083 'description' => $data['versions'][$version]['description'], 03084 'category' => $data['versions'][$version]['category'], 03085 'constraints' => $data['versions'][$version]['dependencies'], 03086 'state' => $data['versions'][$version]['state'], 03087 'reviewstate' => $data['versions'][$version]['reviewstate'], 03088 'lastuploaddate' => $data['versions'][$version]['lastuploaddate'], 03089 'author' => $data['versions'][$version]['authorname'], 03090 'author_email' => $data['versions'][$version]['authoremail'], 03091 'author_company' => $data['versions'][$version]['authorcompany'], 03092 ); 03093 } 03094 $this->setCat($cat, $list[$extKey]['versions'][$version], $extKey); 03095 } 03096 03097 return array($list,$cat); 03098 } 03099 03108 function setCat(&$cat,$listArrayPart,$extKey) { 03109 03110 // Getting extension title: 03111 $extTitle = $listArrayPart['EM_CONF']['title']; 03112 03113 // Category index: 03114 $index = $listArrayPart['EM_CONF']['category']; 03115 $cat['cat'][$index][$extKey] = $extTitle; 03116 03117 // Author index: 03118 $index = $listArrayPart['EM_CONF']['author'].($listArrayPart['EM_CONF']['author_company']?', '.$listArrayPart['EM_CONF']['author_company']:''); 03119 $cat['author_company'][$index][$extKey] = $extTitle; 03120 03121 // State index: 03122 $index = $listArrayPart['EM_CONF']['state']; 03123 $cat['state'][$index][$extKey] = $extTitle; 03124 03125 // Type index: 03126 $index = $listArrayPart['type']; 03127 $cat['type'][$index][$extKey] = $extTitle; 03128 03129 // Return categories: 03130 return $cat; 03131 } 03132 03133 03134 03135 03136 03137 03138 03139 03140 03141 03142 /******************************* 03143 * 03144 * Extension analyzing (detailed information) 03145 * 03146 ******************************/ 03147 03158 function makeDetailedExtensionAnalysis($extKey,$extInfo,$validity=0) { 03159 03160 // Get absolute path of the extension 03161 $absPath = $this->getExtPath($extKey,$extInfo['type']); 03162 03163 $infoArray = array(); 03164 03165 $table_class_prefix = substr($extKey,0,5)=='user_' ? 'user_' : 'tx_'.str_replace('_','',$extKey).'_'; 03166 $module_prefix = substr($extKey,0,5)=='user_' ? 'u' : 'tx'.str_replace('_','',$extKey); 03167 03168 // Database status: 03169 $dbInfo = $this->checkDBupdates($extKey,$extInfo,1); 03170 03171 // Database structure required: 03172 if (is_array($dbInfo['structure']['tables_fields'])) { 03173 $modify_tables = t3lib_div::trimExplode(',',$extInfo['EM_CONF']['modify_tables'],1); 03174 $infoArray['dump_tf'] = array(); 03175 03176 foreach($dbInfo['structure']['tables_fields'] as $tN => $d) { 03177 if (in_array($tN,$modify_tables)) { 03178 $infoArray['fields'][] = $tN.': <i>'. 03179 (is_array($d['fields']) ? implode(', ',array_keys($d['fields'])) : ''). 03180 (is_array($d['keys']) ? ' + '.count($d['keys']).' keys' : ''). 03181 '</i>'; 03182 if (is_array($d['fields'])) { 03183 reset($d['fields']); 03184 while(list($fN) = each($d['fields'])) { 03185 $infoArray['dump_tf'][] = $tN.'.'.$fN; 03186 if (!t3lib_div::isFirstPartOfStr($fN,$table_class_prefix)) { 03187 $infoArray['NSerrors']['fields'][$fN] = $fN; 03188 } else { 03189 $infoArray['NSok']['fields'][$fN] = $fN; 03190 } 03191 } 03192 } 03193 if (is_array($d['keys'])) { 03194 reset($d['keys']); 03195 while(list($fN)=each($d['keys'])) { 03196 $infoArray['dump_tf'][] = $tN.'.KEY:'.$fN; 03197 } 03198 } 03199 } else { 03200 $infoArray['dump_tf'][] = $tN; 03201 $infoArray['tables'][] = $tN; 03202 if (!t3lib_div::isFirstPartOfStr($tN,$table_class_prefix)) { 03203 $infoArray['NSerrors']['tables'][$tN] = $tN; 03204 } else $infoArray['NSok']['tables'][$tN] = $tN; 03205 } 03206 } 03207 if (count($dbInfo['structure']['diff']['diff']) || count($dbInfo['structure']['diff']['extra'])) { 03208 $msg = array(); 03209 if (count($dbInfo['structure']['diff']['diff'])) $msg[] = 'missing'; 03210 if (count($dbInfo['structure']['diff']['extra'])) $msg[] = 'of wrong type'; 03211 $infoArray['tables_error'] = 1; 03212 if (t3lib_extMgm::isLoaded($extKey)) $infoArray['errors'][] = 'Some tables or fields are '.implode(' and ',$msg).'!'; 03213 } 03214 } 03215 03216 // Static tables? 03217 if (is_array($dbInfo['static'])) { 03218 $infoArray['static'] = array_keys($dbInfo['static']); 03219 03220 foreach($dbInfo['static'] as $tN => $d) { 03221 if (!$d['exists']) { 03222 $infoArray['static_error'] = 1; 03223 if (t3lib_extMgm::isLoaded($extKey)) $infoArray['errors'][] = 'Static table(s) missing!'; 03224 if (!t3lib_div::isFirstPartOfStr($tN,$table_class_prefix)) { 03225 $infoArray['NSerrors']['tables'][$tN] = $tN; 03226 } else $infoArray['NSok']['tables'][$tN] = $tN; 03227 } 03228 } 03229 } 03230 03231 // Backend Module-check: 03232 $knownModuleList = t3lib_div::trimExplode(',',$extInfo['EM_CONF']['module'],1); 03233 foreach($knownModuleList as $mod) { 03234 if (@is_dir($absPath.$mod)) { 03235 if (@is_file($absPath.$mod.'/conf.php')) { 03236 $confFileInfo = $this->modConfFileAnalysis($absPath.$mod.'/conf.php'); 03237 if (is_array($confFileInfo['TYPO3_MOD_PATH'])) { 03238 $shouldBePath = $this->typeRelPaths[$extInfo['type']].$extKey.'/'.$mod.'/'; 03239 if (strcmp($confFileInfo['TYPO3_MOD_PATH'][1][1],$shouldBePath)) { 03240 $infoArray['errors'][] = 'Configured TYPO3_MOD_PATH "'.$confFileInfo['TYPO3_MOD_PATH'][1][1].'" different from "'.$shouldBePath.'"'; 03241 } 03242 } else $infoArray['errors'][] = 'No definition of TYPO3_MOD_PATH constant found inside!'; 03243 if (is_array($confFileInfo['MCONF_name'])) { 03244 $mName = $confFileInfo['MCONF_name'][1][1]; 03245 $mNameParts = explode('_',$mName); 03246 $infoArray['moduleNames'][] = $mName; 03247 if (!t3lib_div::isFirstPartOfStr($mNameParts[0],$module_prefix) && 03248 (!$mNameParts[1] || !t3lib_div::isFirstPartOfStr($mNameParts[1],$module_prefix))) { 03249 $infoArray['NSerrors']['modname'][] = $mName; 03250 } else $infoArray['NSok']['modname'][] = $mName; 03251 } else $infoArray['errors'][] = 'No definition of MCONF[name] variable found inside!'; 03252 } else $infoArray['errors'][] = 'Backend module conf file "'.$mod.'/conf.php" should exist but does not!'; 03253 } else $infoArray['errors'][] = 'Backend module folder "'.$mod.'/" should exist but does not!'; 03254 } 03255 $dirs = t3lib_div::get_dirs($absPath); 03256 if (is_array($dirs)) { 03257 reset($dirs); 03258 while(list(,$mod) = each($dirs)) { 03259 if (!in_array($mod,$knownModuleList) && @is_file($absPath.$mod.'/conf.php')) { 03260 $confFileInfo = $this->modConfFileAnalysis($absPath.$mod.'/conf.php'); 03261 if (is_array($confFileInfo)) { 03262 $infoArray['errors'][] = 'It seems like there is a backend module in "'.$mod.'/conf.php" which is not configured in ext_emconf.php'; 03263 } 03264 } 03265 } 03266 } 03267 03268 // ext_tables.php: 03269 if (@is_file($absPath.'ext_tables.php')) { 03270 $content = t3lib_div::getUrl($absPath.'ext_tables.php'); 03271 if (stristr($content,'t3lib_extMgm::addModule')) $infoArray['flags'][] = 'Module'; 03272 if (stristr($content,'t3lib_extMgm::insertModuleFunction')) $infoArray['flags'][] = 'Module+'; 03273 if (stristr($content,'t3lib_div::loadTCA')) $infoArray['flags'][] = 'loadTCA'; 03274 if (stristr($content,'$TCA[')) $infoArray['flags'][] = 'TCA'; 03275 if (stristr($content,'t3lib_extMgm::addPlugin')) $infoArray['flags'][] = 'Plugin'; 03276 } 03277 03278 // ext_localconf.php: 03279 if (@is_file($absPath.'ext_localconf.php')) { 03280 $content = t3lib_div::getUrl($absPath.'ext_localconf.php'); 03281 if (stristr($content,'t3lib_extMgm::addPItoST43')) $infoArray['flags'][]='Plugin/ST43'; 03282 if (stristr($content,'t3lib_extMgm::addPageTSConfig')) $infoArray['flags'][]='Page-TSconfig'; 03283 if (stristr($content,'t3lib_extMgm::addUserTSConfig')) $infoArray['flags'][]='User-TSconfig'; 03284 if (stristr($content,'t3lib_extMgm::addTypoScriptSetup')) $infoArray['flags'][]='TS/Setup'; 03285 if (stristr($content,'t3lib_extMgm::addTypoScriptConstants')) $infoArray['flags'][]='TS/Constants'; 03286 } 03287 03288 if (@is_file($absPath.'ext_typoscript_constants.txt')) { 03289 $infoArray['TSfiles'][] = 'Constants'; 03290 } 03291 if (@is_file($absPath.'ext_typoscript_setup.txt')) { 03292 $infoArray['TSfiles'][] = 'Setup'; 03293 } 03294 if (@is_file($absPath.'ext_conf_template.txt')) { 03295 $infoArray['conf'] = 1; 03296 } 03297 03298 // Classes: 03299 if ($validity) { 03300 $filesInside = $this->getClassIndexLocallangFiles($absPath,$table_class_prefix,$extKey); 03301 if (is_array($filesInside['errors'])) $infoArray['errors'] = array_merge((array)$infoArray['errors'],$filesInside['errors']); 03302 if (is_array($filesInside['NSerrors'])) $infoArray['NSerrors'] = array_merge((array)$infoArray['NSerrors'],$filesInside['NSerrors']); 03303 if (is_array($filesInside['NSok'])) $infoArray['NSok'] = array_merge((array)$infoArray['NSok'],$filesInside['NSok']); 03304 $infoArray['locallang'] = $filesInside['locallang']; 03305 $infoArray['classes'] = $filesInside['classes']; 03306 } 03307 03308 // Upload folders 03309 if ($extInfo['EM_CONF']['uploadfolder']) { 03310 $infoArray['uploadfolder'] = $this->ulFolder($extKey); 03311 if (!@is_dir(PATH_site.$infoArray['uploadfolder'])) { 03312 $infoArray['errors'][] = 'Error: Upload folder "'.$infoArray['uploadfolder'].'" did not exist!'; 03313 $infoArray['uploadfolder'] = ''; 03314 } 03315 } 03316 03317 // Create directories: 03318 if ($extInfo['EM_CONF']['createDirs']) { 03319 $infoArray['createDirs'] = array_unique(t3lib_div::trimExplode(',',$extInfo['EM_CONF']['createDirs'],1)); 03320 foreach($infoArray['createDirs'] as $crDir) { 03321 if (!@is_dir(PATH_site.$crDir)) { 03322 $infoArray['errors'][]='Error: Upload folder "'.$crDir.'" did not exist!'; 03323 } 03324 } 03325 } 03326 03327 // Return result array: 03328 return $infoArray; 03329 } 03330 03340 function getClassIndexLocallangFiles($absPath,$table_class_prefix,$extKey) { 03341 $filesInside = t3lib_div::removePrefixPathFromList(t3lib_div::getAllFilesAndFoldersInPath(array(),$absPath,'php,inc'),$absPath); 03342 $out = array(); 03343 03344 foreach($filesInside as $fileName) { 03345 if (substr($fileName,0,4)!='ext_' && substr($fileName,0,6)!='tests/') { // ignore supposed-to-be unit tests as well 03346 $baseName = basename($fileName); 03347 if (substr($baseName,0,9)=='locallang' && substr($baseName,-4)=='.php') { 03348 $out['locallang'][] = $fileName; 03349 } elseif ($baseName!='conf.php') { 03350 if (filesize($absPath.$fileName)<500*1024) { 03351 $fContent = t3lib_div::getUrl($absPath.$fileName); 03352 unset($reg); 03353 if (preg_match('/\n[[:space:]]*class[[:space:]]*([[:alnum:]_]+)([[:alnum:][:space:]_]*)/',$fContent,$reg)) { 03354 03355 // Find classes: 03356 $lines = explode(chr(10),$fContent); 03357 foreach($lines as $l) { 03358 $line = trim($l); 03359 unset($reg); 03360 if (preg_match('/^class[[:space:]]*([[:alnum:]_]+)([[:alnum:][:space:]_]*)/',$line,$reg)) { 03361 $out['classes'][] = $reg[1]; 03362 $out['files'][$fileName]['classes'][] = $reg[1]; 03363 if ($reg[1]!=='ext_update' && substr($reg[1],0,3)!='ux_' && !t3lib_div::isFirstPartOfStr($reg[1],$table_class_prefix) && strcmp(substr($table_class_prefix,0,-1),$reg[1])) { 03364 $out['NSerrors']['classname'][] = $reg[1]; 03365 } else $out['NSok']['classname'][] = $reg[1]; 03366 } 03367 } 03368 // If class file prefixed 'class.'.... 03369 if (substr($baseName,0,6)=='class.') { 03370 $fI = pathinfo($baseName); 03371 $testName=substr($baseName,6,-(1+strlen($fI['extension']))); 03372 if ($testName!=='ext_update' && substr($testName,0,3)!='ux_' && !t3lib_div::isFirstPartOfStr($testName,$table_class_prefix) && strcmp(substr($table_class_prefix,0,-1),$testName)) { 03373 $out['NSerrors']['classfilename'][] = $baseName; 03374 } else { 03375 $out['NSok']['classfilename'][] = $baseName; 03376 if (is_array($out['files'][$fileName]['classes']) && $this->first_in_array($testName,$out['files'][$fileName]['classes'],1)) { 03377 $out['msg'][] = 'Class filename "'.$fileName.'" did contain the class "'.$testName.'" just as it should.'; 03378 } else $out['errors'][] = 'Class filename "'.$fileName.'" did NOT contain the class "'.$testName.'"!'; 03379 } 03380 } 03381 // 03382 $XclassParts = split('if \(defined\([\'"]TYPO3_MODE[\'"]\) && \$TYPO3_CONF_VARS\[TYPO3_MODE\]\[[\'"]XCLASS[\'"]\]',$fContent,2); 03383 if (count($XclassParts)==2) { 03384 unset($reg); 03385 preg_match('/^\[[\'"]([[:alnum:]_\/\.]*)[\'"]\]/',$XclassParts[1],$reg); 03386 if ($reg[1]) { 03387 $cmpF = 'ext/'.$extKey.'/'.$fileName; 03388 if (!strcmp($reg[1],$cmpF)) { 03389 if (preg_match('/_once[[:space:]]*\(\$TYPO3_.ONF_VARS\[TYPO3_MODE\]\[[\'"]XCLASS[\'"]\]\[[\'"]'.preg_quote($cmpF,'/').'[\'"]\]\);/', $XclassParts[1])) { 03390 $out['msg'][] = 'XCLASS OK in '.$fileName; 03391 } else $out['errors'][] = 'Couldn\'t find the include_once statement for XCLASS!'; 03392 } else $out['errors'][] = 'The XCLASS filename-key "'.$reg[1].'" was different from "'.$cmpF.'" which it should have been!'; 03393 } else $out['errors'][] = 'No XCLASS filename-key found in file "'.$fileName.'". Maybe a regex coding error here...'; 03394 } elseif (!$this->first_in_array('ux_',$out['files'][$fileName]['classes'])) $out['errors'][] = 'No XCLASS inclusion code found in file "'.$fileName.'"'; 03395 } 03396 } 03397 } 03398 } 03399 } 03400 return $out; 03401 } 03402 03410 function modConfFileAnalysis($confFilePath) { 03411 $lines = explode(chr(10),t3lib_div::getUrl($confFilePath)); 03412 $confFileInfo = array(); 03413 $confFileInfo['lines'] = $lines; 03414 03415 foreach($lines as $k => $l) { 03416 $line = trim($l); 03417 03418 unset($reg); 03419 if (preg_match('/^define[[:space:]]*\([[:space:]]*["\']TYPO3_MOD_PATH["\'][[:space:]]*,[[:space:]]*["\']([[:alnum:]_\/\.]+)["\'][[:space:]]*\)[[:space:]]*;/',$line,$reg)) { 03420 $confFileInfo['TYPO3_MOD_PATH'] = array($k,$reg); 03421 } 03422 03423 unset($reg); 03424 if (preg_match('/^\$MCONF\[["\']?name["\']?\][[:space:]]*=[[:space:]]*["\']([[:alnum:]_]+)["\'];/',$line,$reg)) { 03425 $confFileInfo['MCONF_name'] = array($k,$reg); 03426 } 03427 } 03428 return $confFileInfo; 03429 } 03430 03438 function serverExtensionMD5Array($extKey,$conf) { 03439 03440 // Creates upload-array - including filelist. 03441 $mUA = $this->makeUploadArray($extKey,$conf); 03442 03443 $md5Array = array(); 03444 if (is_array($mUA['FILES'])) { 03445 03446 // Traverse files. 03447 foreach($mUA['FILES'] as $fN => $d) { 03448 if ($fN!='ext_emconf.php') { 03449 $md5Array[$fN] = substr($d['content_md5'],0,4); 03450 } 03451 } 03452 } else debug($mUA); 03453 return $md5Array; 03454 } 03455 03463 function findMD5ArrayDiff($current,$past) { 03464 if (!is_array($current)) $current = array(); 03465 if (!is_array($past)) $past = array(); 03466 $filesInCommon = array_intersect($current,$past); 03467 $diff1 = array_keys(array_diff($past,$filesInCommon)); 03468 $diff2 = array_keys(array_diff($current,$filesInCommon)); 03469 $affectedFiles = array_unique(array_merge($diff1,$diff2)); 03470 return $affectedFiles; 03471 } 03472 03473 03474 03475 03476 03477 03478 03479 03480 03481 03482 /*********************************** 03483 * 03484 * File system operations 03485 * 03486 **********************************/ 03487 03495 function createDirsInPath($dirs,$extDirPath) { 03496 if (is_array($dirs)) { 03497 foreach($dirs as $dir) { 03498 $error = t3lib_div::mkdir_deep($extDirPath,$dir); 03499 if ($error) return $error; 03500 } 03501 } 03502 03503 return false; 03504 } 03505 03513 function removeExtDirectory($removePath,$removeContentOnly=0) { 03514 $errors = array(); 03515 if (@is_dir($removePath) && substr($removePath,-1)=='/' && ( 03516 t3lib_div::isFirstPartOfStr($removePath,PATH_site.$this->typePaths['G']) || 03517 t3lib_div::isFirstPartOfStr($removePath,PATH_site.$this->typePaths['L']) || 03518 (t3lib_div::isFirstPartOfStr($removePath,PATH_site.$this->typePaths['S']) && $this->systemInstall) || 03519 t3lib_div::isFirstPartOfStr($removePath,PATH_site.'fileadmin/_temp_/')) // Playing-around directory... 03520 ) { 03521 03522 // All files in extension directory: 03523 $fileArr = t3lib_div::getAllFilesAndFoldersInPath(array(),$removePath,'',1); 03524 if (is_array($fileArr)) { 03525 03526 // Remove files in dirs: 03527 foreach($fileArr as $removeFile) { 03528 if (!@is_dir($removeFile)) { 03529 if (@is_file($removeFile) && t3lib_div::isFirstPartOfStr($removeFile,$removePath) && strcmp($removeFile,$removePath)) { // ... we are very paranoid, so we check what cannot go wrong: that the file is in fact within the prefix path! 03530 @unlink($removeFile); 03531 clearstatcache(); 03532 if (@is_file($removeFile)) { 03533 $errors[] = 'Error: "'.$removeFile.'" could not be deleted!'; 03534 } 03535 } else $errors[] = 'Error: "'.$removeFile.'" was either not a file, or it was equal to the removed directory or simply outside the removed directory "'.$removePath.'"!'; 03536 } 03537 } 03538 03539 // Remove directories: 03540 $remDirs = $this->extractDirsFromFileList(t3lib_div::removePrefixPathFromList($fileArr,$removePath)); 03541 $remDirs = array_reverse($remDirs); // Must delete outer directories first... 03542 foreach($remDirs as $removeRelDir) { 03543 $removeDir = $removePath.$removeRelDir; 03544 if (@is_dir($removeDir)) { 03545 rmdir($removeDir); 03546 clearstatcache(); 03547 if (@is_dir($removeDir)) { 03548 $errors[] = 'Error: "'.$removeDir.'" could not be removed (are there files left?)'; 03549 } 03550 } else $errors[] = 'Error: "'.$removeDir.'" was not a directory!'; 03551 } 03552 03553 // If extension dir should also be removed: 03554 if (!$removeContentOnly) { 03555 rmdir($removePath); 03556 clearstatcache(); 03557 if (@is_dir($removePath)) { 03558 $errors[] = 'Error: Extension directory "'.$removePath.'" could not be removed (are there files or folders left?)'; 03559 } 03560 } 03561 } else $errors[] = 'Error: '.$fileArr; 03562 } else $errors[] = 'Error: Unallowed path to remove: '.$removePath; 03563 03564 // Return errors if any: 03565 return implode(chr(10),$errors); 03566 } 03567 03576 function clearAndMakeExtensionDir($importedData,$type,$dontDelete=0) { 03577 if (!$importedData['extKey']) return 'FATAL ERROR: Extension key was not set for some VERY strange reason. Nothing done...'; 03578 03579 // Setting install path (L, G, S or fileadmin/_temp_/) 03580 $path = ''; 03581 switch((string)$type) { 03582 case 'G': 03583 case 'L': 03584 $path = PATH_site.$this->typePaths[$type]; 03585 $suffix = ''; 03586 03587 // Creates the typo3conf/ext/ directory if it does NOT already exist: 03588 if ((string)$type=='L' && !@is_dir($path)) { 03589 t3lib_div::mkdir($path); 03590 } 03591 break; 03592 default: 03593 if ($this->systemInstall && (string)$type=='S') { 03594 $path = PATH_site.$this->typePaths[$type]; 03595 $suffix = ''; 03596 } else { 03597 $path = PATH_site.'fileadmin/_temp_/'; 03598 $suffix = '_'.date('dmy-His'); 03599 } 03600 break; 03601 } 03602 03603 // If the install path is OK... 03604 if ($path && @is_dir($path)) { 03605 03606 // Set extension directory: 03607 $extDirPath = $path.$importedData['extKey'].$suffix.'/'; 03608 03609 // Install dir was found, remove it then: 03610 if (@is_dir($extDirPath)) { 03611 if($dontDelete) return array($extDirPath); 03612 $res = $this->removeExtDirectory($extDirPath); 03613 if ($res) { 03614 return 'ERROR: Could not remove extension directory "'.$extDirPath.'". Reasons:<br /><br />'.nl2br($res); 03615 } 03616 } 03617 03618 // We go create... 03619 t3lib_div::mkdir($extDirPath); 03620 if (!is_dir($extDirPath)) return 'ERROR: Could not create extension directory "'.$extDirPath.'"'; 03621 return array($extDirPath); 03622 } else return 'ERROR: The extension install path "'.$path.'" was not a directory.'; 03623 } 03624 03630 function removeCacheFiles() { 03631 return t3lib_extMgm::removeCacheFiles(); 03632 } 03633 03640 function extractDirsFromFileList($files) { 03641 $dirs = array(); 03642 03643 if (is_array($files)) { 03644 // Traverse files / directories array: 03645 foreach($files as $file) { 03646 if (substr($file,-1)=='/') { 03647 $dirs[$file] = $file; 03648 } else { 03649 $pI = pathinfo($file); 03650 if (strcmp($pI['dirname'],'') && strcmp($pI['dirname'],'.')) { 03651 $dirs[$pI['dirname'].'/'] = $pI['dirname'].'/'; 03652 } 03653 } 03654 } 03655 } 03656 return $dirs; 03657 } 03658 03666 function getExtPath($extKey,$type) { 03667 $typeP = $this->typePaths[$type]; 03668 if ($typeP) { 03669 $path = PATH_site.$typeP.$extKey.'/'; 03670 return @is_dir($path) ? $path : ''; 03671 } else { 03672 return ''; 03673 } 03674 } 03675 03676 03677 03678 03679 03680 03681 03682 03683 03684 03685 /******************************* 03686 * 03687 * Writing to "conf.php" and "localconf.php" files 03688 * 03689 ******************************/ 03690 03700 function writeTYPO3_MOD_PATH($confFilePath,$type,$mP) { 03701 $lines = explode(chr(10),t3lib_div::getUrl($confFilePath)); 03702 $confFileInfo = array(); 03703 $confFileInfo['lines'] = $lines; 03704 03705 $flag_M = 0; 03706 $flag_B = 0; 03707 03708 foreach($lines as $k => $l) { 03709 $line = trim($l); 03710 03711 unset($reg); 03712 if (preg_match('/^define[[:space:]]*\([[:space:]]*["\']TYPO3_MOD_PATH["\'][[:space:]]*,[[:space:]]*["\']([[:alnum:]_\/\.]+)["\'][[:space:]]*\)[[:space:]]*;/',$line,$reg)) { 03713 $lines[$k] = str_replace($reg[0], 'define(\'TYPO3_MOD_PATH\', \''.$this->typeRelPaths[$type].$mP.'\');', $lines[$k]); 03714 $flag_M = $k+1; 03715 } 03716 03717 unset($reg); 03718 if (preg_match('/^\$BACK_PATH[[:space:]]*=[[:space:]]*["\']([[:alnum:]_\/\.]+)["\'][[:space:]]*;/',$line,$reg)) { 03719 $lines[$k] = str_replace($reg[0], '$BACK_PATH=\''.$this->typeBackPaths[$type].'\';', $lines[$k]); 03720 $flag_B = $k+1; 03721 } 03722 } 03723 03724 if ($flag_B && $flag_M) { 03725 t3lib_div::writeFile($confFilePath,implode(chr(10),$lines)); 03726 return 'TYPO3_MOD_PATH and $BACK_PATH was updated in "'.substr($confFilePath,strlen(PATH_site)).'"'; 03727 } else return 'Error: Either TYPO3_MOD_PATH or $BACK_PATH was not found in the "'.$confFilePath.'" file. You must manually configure that!'; 03728 } 03729 03737 function writeNewExtensionList($newExtList) { 03738 global $TYPO3_CONF_VARS; 03739 03740 // Instance of install tool 03741 $instObj = new t3lib_install; 03742 $instObj->allowUpdateLocalConf =1; 03743 $instObj->updateIdentity = 'TYPO3 Extension Manager'; 03744 03745 // Get lines from localconf file 03746 $lines = $instObj->writeToLocalconf_control(); 03747 $instObj->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'EXT\'][\'extList\']', $newExtList); 03748 $instObj->writeToLocalconf_control($lines); 03749 03750 $TYPO3_CONF_VARS['EXT']['extList'] = $newExtList; 03751 $this->removeCacheFiles(); 03752 } 03753 03762 function writeTsStyleConfig($extKey,$arr) { 03763 03764 // Instance of install tool 03765 $instObj = new t3lib_install; 03766 $instObj->allowUpdateLocalConf =1; 03767 $instObj->updateIdentity = 'TYPO3 Extension Manager'; 03768 03769 // Get lines from localconf file 03770 $lines = $instObj->writeToLocalconf_control(); 03771 $instObj->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'EXT\'][\'extConf\'][\''.$extKey.'\']', serialize($arr)); // This will be saved only if there are no linebreaks in it ! 03772 $instObj->writeToLocalconf_control($lines); 03773 03774 $this->removeCacheFiles(); 03775 } 03776 03784 function updateLocalEM_CONF($extKey,$extInfo) { 03785 $extInfo['EM_CONF']['_md5_values_when_last_written'] = serialize($this->serverExtensionMD5Array($extKey,$extInfo)); 03786 $emConfFileContent = $this->construct_ext_emconf_file($extKey,$extInfo['EM_CONF']); 03787 03788 if($emConfFileContent) { 03789 $absPath = $this->getExtPath($extKey,$extInfo['type']); 03790 $emConfFileName = $absPath.'ext_emconf.php'; 03791 03792 if(@is_file($emConfFileName)) { 03793 if(t3lib_div::writeFile($emConfFileName,$emConfFileContent) === true) { 03794 return '"'.substr($emConfFileName,strlen($absPath)).'" was updated with a cleaned up EM_CONF array.'; 03795 } else { 03796 return '<strong>Error: "'.$emConfFileName.'" was not writable!</strong>'; 03797 } 03798 } else return('<strong>Error: No file "'.$emConfFileName.'" found. DON\'T PANIC!</strong>'); 03799 } else { 03800 return 'No content to write to "'.substr($emConfFileName,strlen($absPath)).'"!'; 03801 } 03802 } 03803 03804 03805 03806 03807 03808 03809 03810 03811 03812 03813 /******************************************* 03814 * 03815 * Compiling upload information, emconf-file etc. 03816 * 03817 *******************************************/ 03818 03826 function construct_ext_emconf_file($extKey,$EM_CONF) { 03827 03828 // clean version number: 03829 $vDat = $this->renderVersion($EM_CONF['version']); 03830 $EM_CONF['version']=$vDat['version']; 03831 03832 return '<?php 03833 03834 ######################################################################## 03835 # Extension Manager/Repository config file for ext: "'.$extKey.'" 03836 # 03837 # Auto generated '.date('d-m-Y H:i').' 03838 # 03839 # Manual updates: 03840 # Only the data in the array - anything else is removed by next write. 03841 # "version" and "dependencies" must not be touched! 03842 ######################################################################## 03843 03844 $EM_CONF[$_EXTKEY] = '.$this->arrayToCode($EM_CONF, 0).'; 03845 03846 ?>'; 03847 } 03848 03857 function arrayToCode($array, $level=0) { 03858 $lines = 'array('.chr(10); 03859 $level++; 03860 foreach($array as $k => $v) { 03861 if(strlen($k) && is_array($v)) { 03862 $lines .= str_repeat(chr(9),$level)."'".$k."' => ".$this->arrayToCode($v, $level); 03863 } elseif(strlen($k)) { 03864 $lines .= str_repeat(chr(9),$level)."'".$k."' => ".(t3lib_div::testInt($v) ? intval($v) : "'".t3lib_div::slashJS(trim($v),1)."'").','.chr(10); 03865 } 03866 } 03867 03868 $lines .= str_repeat(chr(9),$level-1).')'.($level-1==0 ? '':','.chr(10)); 03869 return $lines; 03870 } 03871 03879 function makeUploadArray($extKey,$conf) { 03880 $extPath = $this->getExtPath($extKey,$conf['type']); 03881 03882 if ($extPath) { 03883 03884 // Get files for extension: 03885 $fileArr = array(); 03886 $fileArr = t3lib_div::getAllFilesAndFoldersInPath($fileArr,$extPath); 03887 03888 // Calculate the total size of those files: 03889 $totalSize = 0; 03890 foreach($fileArr as $file) { 03891 $totalSize+=filesize($file); 03892 } 03893 03894 // If the total size is less than the upper limit, proceed: 03895 if ($totalSize < $this->maxUploadSize) { 03896 03897 // Initialize output array: 03898 $uploadArray = array(); 03899 $uploadArray['extKey'] = $extKey; 03900 $uploadArray['EM_CONF'] = $conf['EM_CONF']; 03901 $uploadArray['misc']['codelines'] = 0; 03902 $uploadArray['misc']['codebytes'] = 0; 03903 03904 $uploadArray['techInfo'] = $this->makeDetailedExtensionAnalysis($extKey,$conf,1); 03905 03906 // Read all files: 03907 foreach($fileArr as $file) { 03908 $relFileName = substr($file,strlen($extPath)); 03909 $fI = pathinfo($relFileName); 03910 if ($relFileName!='ext_emconf.php') { // This file should be dynamically written... 03911 $uploadArray['FILES'][$relFileName] = array( 03912 'name' => $relFileName, 03913 'size' => filesize($file), 03914 'mtime' => filemtime($file), 03915 'is_executable' => (TYPO3_OS=='WIN' ? 0 : is_executable($file)), 03916 'content' => t3lib_div::getUrl($file) 03917 ); 03918 if (t3lib_div::inList('php,inc',strtolower($fI['extension']))) { 03919 $uploadArray['FILES'][$relFileName]['codelines']=count(explode(chr(10),$uploadArray['FILES'][$relFileName]['content'])); 03920 $uploadArray['misc']['codelines']+=$uploadArray['FILES'][$relFileName]['codelines']; 03921 $uploadArray['misc']['codebytes']+=$uploadArray['FILES'][$relFileName]['size']; 03922 03923 // locallang*.php files: 03924 if (substr($fI['basename'],0,9)=='locallang' && strstr($uploadArray['FILES'][$relFileName]['content'],'$LOCAL_LANG')) { 03925 $uploadArray['FILES'][$relFileName]['LOCAL_LANG']=$this->getSerializedLocalLang($file,$uploadArray['FILES'][$relFileName]['content']); 03926 } 03927 } 03928 $uploadArray['FILES'][$relFileName]['content_md5'] = md5($uploadArray['FILES'][$relFileName]['content']); 03929 } 03930 } 03931 03932 // Return upload-array: 03933 return $uploadArray; 03934 } else return 'Error: Total size of uncompressed upload ('.$totalSize.') exceeds '.t3lib_div::formatSize($this->maxUploadSize); 03935 } else { 03936 return 'Error: Extension path for extension "'.$extKey.'" not found'; 03937 } 03938 } 03939 03948 function getSerializedLocalLang($file,$content) { 03949 $returnParts = explode('$LOCAL_LANG',$content,2); 03950 03951 include($file); 03952 if (is_array($LOCAL_LANG)) { 03953 $returnParts[1] = serialize($LOCAL_LANG); 03954 return $returnParts; 03955 } else { 03956 return array(); 03957 } 03958 } 03959 03960 03961 03962 03963 03964 03965 03966 03967 03968 03969 /******************************** 03970 * 03971 * Managing dependencies, conflicts, priorities, load order of extension keys 03972 * 03973 *******************************/ 03974 03984 function addExtToList($extKey,$instExtInfo) { 03985 global $TYPO3_LOADED_EXT; 03986 03987 // ext_emconf.php information: 03988 $conf = $instExtInfo[$extKey]['EM_CONF']; 03989 03990 // Get list of installed extensions and add this one. 03991 $listArr = array_keys($TYPO3_LOADED_EXT); 03992 if ($conf['priority']=='top') { 03993 array_unshift($listArr,$extKey); 03994 } else { 03995 $listArr[]=$extKey; 03996 } 03997 03998 // Manage other circumstances: 03999 $listArr = $this->managesPriorities($listArr,$instExtInfo); 04000 $listArr = $this->removeRequiredExtFromListArr($listArr); 04001 04002 // Implode unique list of extensions to load and return: 04003 $list = implode(',',array_unique($listArr)); 04004 return $list; 04005 } 04006 04015 function checkDependencies($extKey, $conf, $instExtInfo) { 04016 $content = ''; 04017 $depError = false; 04018 $msg = array(); 04019 $depsolver = t3lib_div::_POST('depsolver'); 04020 04021 foreach($conf['constraints']['depends'] as $depK => $depV) { 04022 if($depsolver['ignore'][$depK]) { 04023 $msg[] = '<br />Dependency on '.$depK.' ignored as requested. 04024 <input type="hidden" value="1" name="depsolver[ignore]['.$depK.']" />'; 04025 continue; 04026 } 04027 if($depK == 'php') { 04028 if(!$depV) continue; 04029 $versionRange = $this->splitVersionRange($depV); 04030 $phpv = strstr(PHP_VERSION,'-') ? substr(PHP_VERSION,0,strpos(PHP_VERSION,'-')) : PHP_VERSION; // Linux distributors like to add suffixes, like in 5.1.2-1. Those must be ignored! 04031 if($versionRange[0] && version_compare($phpv,$versionRange[0],'<')) { 04032 $msg[] = '<br />The running PHP version ('.$phpv.') is lower than required ('.$versionRange[0].')'; 04033 $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" /> Ignore this version requirement'; 04034 $depError = true; 04035 continue; 04036 } elseif($versionRange[1] && version_compare($phpv,$versionRange[1],'>')) { 04037 $msg[] = '<br />The running PHP version ('.$phpv.') is higher than allowed ('.$versionRange[1].')'; 04038 $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" /> Ignore this version requirement'; 04039 $depError = true; 04040 continue; 04041 } 04042 } elseif($depK == 'typo3') { 04043 if(!$depV) continue; 04044 $versionRange = $this->splitVersionRange($depV); 04045 if($versionRange[0] && version_compare(TYPO3_version,$versionRange[0],'<')) { 04046 $msg[] = '<br />The running TYPO3 version ('.TYPO3_version.') is lower than required ('.$versionRange[0].')'; 04047 $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" /> Ignore this version requirement'; 04048 $depError = true; 04049 continue; 04050 } elseif($versionRange[1] && version_compare(TYPO3_version,$versionRange[1],'>')) { 04051 $msg[] = '<br />The running TYPO3 version ('.TYPO3_version.') is higher than allowed ('.$versionRange[1].')'; 04052 $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" /> Ignore this version requirement'; 04053 $depError = true; 04054 continue; 04055 } 04056 } elseif (strlen($depK) && !t3lib_extMgm::isLoaded($depK)) { // strlen check for braindead empty dependencies coming from extensions... 04057 if(!isset($instExtInfo[$depK])) { 04058 $msg[] = '<br />Extension "'.$depK.'" was not available in the system. Please import it from the TYPO3 Extension Repository.'; 04059 $msg[] = ' <img src="'.$GLOBALS['BACK_PATH'].'gfx/import.gif" width="12" height="12" title="Import this extension to \'local\' dir typo3conf/ext/ from online repository." alt="" /> <a href="index.php?CMD[importExt]='.$depK.'&CMD[loc]=L&CMD[standAlone]=1" target="_blank">Import now (opens a new window)</a>'; 04060 $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" /> Ignore this extension requirement'; 04061 } else { 04062 $msg[] = '<br />Extension "'.$depK.'" ('.$instExtInfo[$depK]['EM_CONF']['title'].') was not installed. Please install it first.'; 04063 $msg[] = ' '.$this->installButton().' <a href="'.htmlspecialchars('index.php?CMD[showExt]='.$depK.'&CMD[load]=1&CMD[clrCmd]=1&CMD[standAlone]=1&SET[singleDetails]=info').'" target="_blank">Install now (opens a new window)</a>'; 04064 $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" /> Ignore this extension requirement'; 04065 } 04066 $depError = true; 04067 } else { 04068 $versionRange = $this->splitVersionRange($depV); 04069 if($versionRange[0] && version_compare($instExtInfo[$depK]['EM_CONF']['version'],$versionRange[0],'<')) { 04070 $msg[] = '<br />The running version of extension "'.$depK.'" ('.$instExtInfo[$depK]['EM_CONF']['version'].') is lower than required ('.$versionRange[0].')'; 04071 $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" /> Ignore this version requirement'; 04072 $depError = true; 04073 continue; 04074 } elseif($versionRange[1] && version_compare($instExtInfo[$depK]['EM_CONF']['version'],$versionRange[1],'>')) { 04075 $msg[] = '<br />The running version of extension "'.$depK.'" ('.$instExtInfo[$depK]['EM_CONF']['version'].') is higher than allowed ('.$versionRange[1].')'; 04076 $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" /> Ignore this version requirement'; 04077 $depError = true; 04078 continue; 04079 } 04080 } 04081 } 04082 if($depError) { 04083 $content .= $this->doc->section('Dependency Error',implode('<br />',$msg),0,1,2); 04084 } 04085 04086 // Check conflicts with other extensions: 04087 $conflictError = false; 04088 $msg = array(); 04089 foreach((array)$conf['constraints']['conflicts'] as $conflictK => $conflictV) { 04090 if($depsolver['ignore'][$conflictK]) { 04091 $msg[] = '<br />Conflict with '.$conflictK.' ignored as requested. 04092 <input type="hidden" value="1" name="depsolver[ignore]['.$conflictK.']" />'; 04093 continue; 04094 } 04095 if (t3lib_extMgm::isLoaded($conflictK)) { 04096 $msg[] = 'The extensions "'.$extKey.'" and "'.$conflictK.'" ('.$instExtInfo[$conflictK]['EM_CONF']['title'].') will conflict with each other. Please remove "'.$conflictK.'" if you want to install "'.$extKey.'".'; 04097 $msg[] = ' '.$this->removeButton().' <a href="'.htmlspecialchars('index.php?CMD[showExt]='.$conflictK.'&CMD[remove]=1&CMD[clrCmd]=1&CMD[standAlone]=1&SET[singleDetails]=info').'" target="_blank">Remove now (opens a new window)</a>'; 04098 $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore]['.$conflictK.']" /> Ignore this conflict error'; 04099 $conflictError = true; 04100 } 04101 } 04102 if($conflictError) { 04103 $content .= $this->doc->section('Conflict Error',implode('<br />',$msg),0,1,2); 04104 } 04105 04106 // Check suggests on other extensions: 04107 if(is_array($conf['constraints']['suggests'])) { 04108 $suggestion = false; 04109 $msg = array(); 04110 foreach($conf['constraints']['suggests'] as $suggestK => $suggestV) { 04111 if($depsolver['ignore'][$suggestK]) { 04112 $msg[] = '<br />Suggestion of '.$suggestK.' acknowledged. 04113 <input type="hidden" value="1" name="depsolver[ignore]['.$suggestK.']" />'; 04114 continue; 04115 } 04116 if (!t3lib_extMgm::isLoaded($suggestK)) { 04117 if (!isset($instExtInfo[$suggestK])) { 04118 $msg[] = 'Extension "'.$suggestK.'" was not available in the system. You may want to import it from the TYPO3 Extension Repository.'; 04119 $msg[] = ' <img src="'.$GLOBALS['BACK_PATH'].'gfx/import.gif" width="12" height="12" title="Import this extension to \'local\' dir typo3conf/ext/ from online repository." alt="" /> <a href="index.php?CMD[importExt]='.$depK.'&CMD[loc]=L&CMD[standAlone]=1" target="_blank">Import now (opens a new window)</a>'; 04120 $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore]['.$suggestK.']" /> Ignore this suggestion'; 04121 } else { 04122 $msg[] = 'Extension "'.$suggestK.'" ('.$instExtInfo[$suggestK]['EM_CONF']['title'].') was not installed. You may want to install it.'; 04123 $msg[] = ' '.$this->installButton().' <a href="'.htmlspecialchars('index.php?CMD[showExt]='.$suggestK.'&CMD[load]=1&CMD[clrCmd]=1&CMD[standAlone]=1&SET[singleDetails]=info').'" target="_blank">Install now (opens a new window)</a>'; 04124 $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore]['.$suggestK.']" /> Ignore this suggestion'; 04125 } 04126 $suggestion = true; 04127 } 04128 } 04129 if($suggestion) { 04130 $content .= $this->doc->section('Extensions suggested by extension "'.$extKey.'"',implode('<br />',$msg),0,1,1); 04131 } 04132 } 04133 04134 if($depError || $conflictError || $suggestion) { 04135 foreach($this->CMD as $k => $v) { 04136 $content .= '<input type="hidden" name="CMD['.$k.']" value="'.$v.'" />'; 04137 } 04138 $content .= '<br /><br /><input type="submit" value="Try again" />'; 04139 04140 return array('returnCode' => false, 'html' => $content); 04141 } 04142 04143 return array('returnCode' => true); 04144 } 04145 04155 function removeExtFromList($extKey,$instExtInfo) { 04156 global $TYPO3_LOADED_EXT; 04157 04158 // Initialize: 04159 $depList = array(); 04160 $listArr = array_keys($TYPO3_LOADED_EXT); 04161 04162 // Traverse all installed extensions to check if any of them have this extension as dependency since if that is the case it will not work out! 04163 foreach($listArr as $k => $ext) { 04164 if ($instExtInfo[$ext]['EM_CONF']['dependencies']) { 04165 $dep = t3lib_div::trimExplode(',',$instExtInfo[$ext]['EM_CONF']['dependencies'],1); 04166 if (in_array($extKey,$dep)) { 04167 $depList[] = $ext; 04168 } 04169 } 04170 if (!strcmp($ext,$extKey)) unset($listArr[$k]); 04171 } 04172 04173 // Returns either error or the new list 04174 if (count($depList)) { 04175 $msg = 'The extension(s) "'.implode(', ',$depList).'" depends on the extension you are trying to remove. The operation was not completed.'; 04176 $this->content.=$this->doc->section('Dependency Error',$msg,0,1,2); 04177 return -1; 04178 } else { 04179 $listArr = $this->removeRequiredExtFromListArr($listArr); 04180 $list = implode(',',array_unique($listArr)); 04181 return $list; 04182 } 04183 } 04184 04192 function removeRequiredExtFromListArr($listArr) { 04193 foreach($listArr as $k => $ext) { 04194 if (in_array($ext,$this->requiredExt) || !strcmp($ext,'_CACHEFILE')) unset($listArr[$k]); 04195 } 04196 return $listArr; 04197 } 04198 04207 function managesPriorities($listArr,$instExtInfo) { 04208 04209 // Initialize: 04210 $levels = array( 04211 'top' => array(), 04212 'middle' => array(), 04213 'bottom' => array(), 04214 ); 04215 04216 // Traverse list of extensions: 04217 foreach($listArr as $ext) { 04218 $prio = trim($instExtInfo[$ext]['EM_CONF']['priority']); 04219 switch((string)$prio) { 04220 case 'top': 04221 case 'bottom': 04222 $levels[$prio][] = $ext; 04223 break; 04224 default: 04225 $levels['middle'][] = $ext; 04226 break; 04227 } 04228 } 04229 return array_merge( 04230 $levels['top'], 04231 $levels['middle'], 04232 $levels['bottom'] 04233 ); 04234 } 04235 04236 04237 04238 04239 04240 04241 04242 04243 04244 04245 /******************************* 04246 * 04247 * System Update functions (based on extension requirements) 04248 * 04249 ******************************/ 04250 04259 function checkClearCache($extInfo) { 04260 if ($extInfo['EM_CONF']['clearCacheOnLoad']) { 04261 if (t3lib_div::_POST('_clear_all_cache')) { // Action: Clearing the cache 04262 $tce = t3lib_div::makeInstance('t3lib_TCEmain'); 04263 $tce->stripslashes_values = 0; 04264 $tce->start(Array(),Array()); 04265 $tce->clear_cacheCmd('all'); 04266 } else { // Show checkbox for clearing cache: 04267 $content.= ' 04268 <br /> 04269 <h3>Clear cache</h3> 04270 <p>This extension requests the cache to be cleared when it is installed/removed.<br /> 04271 Clear all cache: <input type="checkbox" name="_clear_all_cache" checked="checked" value="1" /><br /> 04272 </p> 04273 '; 04274 } 04275 } 04276 return $content; 04277 } 04278 04286 function checkUploadFolder($extKey,$extInfo) { 04287 04288 // Checking for upload folder: 04289 $uploadFolder = PATH_site.$this->ulFolder($extKey); 04290 if ($extInfo['EM_CONF']['uploadfolder'] && !@is_dir($uploadFolder)) { 04291 if (t3lib_div::_POST('_uploadfolder')) { // CREATE dir: 04292 t3lib_div::mkdir($uploadFolder); 04293 $indexContent = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> 04294 <HTML> 04295 <HEAD> 04296 <TITLE></TITLE> 04297 <META http-equiv=Refresh Content="0; Url=../../"> 04298 </HEAD> 04299 </HTML>'; 04300 t3lib_div::writeFile($uploadFolder.'index.html',$indexContent); 04301 } else { // Show checkbox / HTML for creation: 04302 $content.=' 04303 <br /><h3>Create upload folder</h3> 04304 <p>The extension requires the upload folder "'.$this->ulFolder($extKey).'" to exist.<br /> 04305 Create directory "'.$this->ulFolder($extKey).'": <input type="checkbox" name="_uploadfolder" checked="checked" value="1" /><br /> 04306 </p> 04307 '; 04308 } 04309 } 04310 04311 // Additional directories that should be created: 04312 if ($extInfo['EM_CONF']['createDirs']) { 04313 $createDirs = array_unique(t3lib_div::trimExplode(',',$extInfo['EM_CONF']['createDirs'],1)); 04314 04315 foreach($createDirs as $crDir) { 04316 if (!@is_dir(PATH_site.$crDir)) { 04317 if (t3lib_div::_POST('_createDir_'.md5($crDir))) { // CREATE dir: 04318 04319 // Initialize: 04320 $crDirStart = ''; 04321 $dirs_in_path = explode('/',preg_replace('/\/$/','',$crDir)); 04322 04323 // Traverse each part of the dir path and create it one-by-one: 04324 foreach($dirs_in_path as $dirP) { 04325 if (strcmp($dirP,'')) { 04326 $crDirStart.= $dirP.'/'; 04327 if (!@is_dir(PATH_site.$crDirStart)) { 04328 t3lib_div::mkdir(PATH_site.$crDirStart); 04329 $finalDir = PATH_site.$crDirStart; 04330 } 04331 } else { 04332 die('ERROR: The path "'.PATH_site.$crDir.'" could not be created.'); 04333 } 04334 } 04335 if ($finalDir) { 04336 $indexContent = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> 04337 <HTML> 04338 <HEAD> 04339 <TITLE></TITLE> 04340 <META http-equiv=Refresh Content="0; Url=/"> 04341 </HEAD> 04342 </HTML>'; 04343 t3lib_div::writeFile($finalDir.'index.html',$indexContent); 04344 } 04345 } else { // Show checkbox / HTML for creation: 04346 $content.=' 04347 <br /> 04348 <h3>Create folder</h3> 04349 <p>The extension requires the folder "'.$crDir.'" to exist.<br /> 04350 Create directory "'.$crDir.'": <input type="checkbox" name="_createDir_'.md5($crDir).'" checked="checked" value="1" /><br /> 04351 </p> 04352 '; 04353 } 04354 } 04355 } 04356 } 04357 04358 return $content; 04359 } 04360 04371 function checkDBupdates($extKey,$extInfo,$infoOnly=0) { 04372 04373 // Initializing Install Tool object: 04374 $instObj = new t3lib_install; 04375 $instObj->INSTALL = t3lib_div::_GP('TYPO3_INSTALL'); 04376 $dbStatus = array(); 04377 04378 // Updating tables and fields? 04379 if (is_array($extInfo['files']) && in_array('ext_tables.sql',$extInfo['files'])) { 04380 $fileContent = t3lib_div::getUrl($this->getExtPath($extKey,$extInfo['type']).'ext_tables.sql'); 04381 04382 $FDfile = $instObj->getFieldDefinitions_sqlContent($fileContent); 04383 if (count($FDfile)) { 04384 $FDdb = $instObj->getFieldDefinitions_database(TYPO3_db); 04385 $diff = $instObj->getDatabaseExtra($FDfile, $FDdb); 04386 $update_statements = $instObj->getUpdateSuggestions($diff); 04387 04388 $dbStatus['structure']['tables_fields'] = $FDfile; 04389 $dbStatus['structure']['diff'] = $diff; 04390 04391 // Updating database... 04392 if (!$infoOnly && is_array($instObj->INSTALL['database_update'])) { 04393 $instObj->performUpdateQueries($update_statements['add'],$instObj->INSTALL['database_update']); 04394 $instObj->performUpdateQueries($update_statements['change'],$instObj->INSTALL['database_update']); 04395 $instObj->performUpdateQueries($update_statements['create_table'],$instObj->INSTALL['database_update']); 04396 } else { 04397 $content.=$instObj->generateUpdateDatabaseForm_checkboxes($update_statements['add'],'Add fields'); 04398 $content.=$instObj->generateUpdateDatabaseForm_checkboxes($update_statements['change'],'Changing fields',1,0,$update_statements['change_currentValue']); 04399 $content.=$instObj->generateUpdateDatabaseForm_checkboxes($update_statements['create_table'],'Add tables'); 04400 } 04401 } 04402 } 04403 04404 // Importing static tables? 04405 if (is_array($extInfo['files']) && in_array('ext_tables_static+adt.sql',$extInfo['files'])) { 04406 $fileContent = t3lib_div::getUrl($this->getExtPath($extKey,$extInfo['type']).'ext_tables_static+adt.sql'); 04407 04408 $statements = $instObj->getStatementArray($fileContent,1); 04409 list($statements_table, $insertCount) = $instObj->getCreateTables($statements,1); 04410 04411 // Execute import of static table content: 04412 if (!$infoOnly && is_array($instObj->INSTALL['database_import'])) { 04413 04414 // Traverse the tables 04415 foreach($instObj->INSTALL['database_import'] as $table => $md5str) { 04416 if ($md5str == md5($statements_table[$table])) { 04417 $GLOBALS['TYPO3_DB']->admin_query('DROP TABLE IF EXISTS '.$table); 04418 $GLOBALS['TYPO3_DB']->admin_query($statements_table[$table]); 04419 04420 if ($insertCount[$table]) { 04421 $statements_insert = $instObj->getTableInsertStatements($statements, $table); 04422 04423 foreach($statements_insert as $v) { 04424 $GLOBALS['TYPO3_DB']->admin_query($v); 04425 } 04426 } 04427 } 04428 } 04429 } else { 04430 $whichTables = $instObj->getListOfTables(); 04431 if (count($statements_table)) { 04432 $out = ''; 04433 foreach($statements_table as $table => $definition) { 04434 $exist = isset($whichTables[$table]); 04435 04436 $dbStatus['static'][$table]['exists'] = $exist; 04437 $dbStatus['static'][$table]['count'] = $insertCount[$table]; 04438 04439 $out.= '<tr> 04440 <td><input type="checkbox" name="TYPO3_INSTALL[database_import]['.$table.']" checked="checked" value="'.md5($definition).'" /></td> 04441 <td><strong>'.$table.'</strong></td> 04442 <td><img src="clear.gif" width="10" height="1" alt="" /></td> 04443 <td nowrap="nowrap">'.($insertCount[$table]?'Rows: '.$insertCount[$table]:'').'</td> 04444 <td><img src="clear.gif" width="10" height="1" alt="" /></td> 04445 <td nowrap="nowrap">'.($exist?'<img src="'.$GLOBALS['BACK_PATH'].'gfx/icon_warning.gif" width="18" height="16" align="top" alt="" />Table exists!':'').'</td> 04446 </tr>'; 04447 } 04448 $content.= ' 04449 <br /> 04450 <h3>Import static data</h3> 04451 <table border="0" cellpadding="0" cellspacing="0">'.$out.'</table>'; 04452 } 04453 } 04454 } 04455 04456 // Return array of information if $infoOnly, otherwise content. 04457 return $infoOnly ? $dbStatus : $content; 04458 } 04459 04468 function forceDBupdates($extKey, $extInfo) { 04469 $instObj = new t3lib_install; 04470 04471 // Updating tables and fields? 04472 if (is_array($extInfo['files']) && in_array('ext_tables.sql',$extInfo['files'])) { 04473 $fileContent = t3lib_div::getUrl($this->getExtPath($extKey,$extInfo['type']).'ext_tables.sql'); 04474 04475 $FDfile = $instObj->getFieldDefinitions_sqlContent($fileContent); 04476 if (count($FDfile)) { 04477 $FDdb = $instObj->getFieldDefinitions_database(TYPO3_db); 04478 $diff = $instObj->getDatabaseExtra($FDfile, $FDdb); 04479 $update_statements = $instObj->getUpdateSuggestions($diff); 04480 04481 foreach((array)$update_statements['add'] as $string) { 04482 $GLOBALS['TYPO3_DB']->admin_query($string); 04483 } 04484 foreach((array)$update_statements['change'] as $string) { 04485 $GLOBALS['TYPO3_DB']->admin_query($string); 04486 } 04487 foreach((array)$update_statements['create_table'] as $string) { 04488 $GLOBALS['TYPO3_DB']->admin_query($string); 04489 } 04490 } 04491 } 04492 04493 // Importing static tables? 04494 if (is_array($extInfo['files']) && in_array('ext_tables_static+adt.sql',$extInfo['files'])) { 04495 $fileContent = t3lib_div::getUrl($this->getExtPath($extKey,$extInfo['type']).'ext_tables_static+adt.sql'); 04496 04497 $statements = $instObj->getStatementArray($fileContent,1); 04498 list($statements_table, $insertCount) = $instObj->getCreateTables($statements,1); 04499 04500 // Traverse the tables 04501 foreach($statements_table as $table => $query) { 04502 $GLOBALS['TYPO3_DB']->admin_query('DROP TABLE IF EXISTS '.$table); 04503 $GLOBALS['TYPO3_DB']->admin_query($query); 04504 04505 if ($insertCount[$table]) { 04506 $statements_insert = $instObj->getTableInsertStatements($statements, $table); 04507 04508 foreach($statements_insert as $v) { 04509 $GLOBALS['TYPO3_DB']->admin_query($v); 04510 } 04511 } 04512 } 04513 } 04514 } 04515 04526 function tsStyleConfigForm($extKey,$extInfo,$output=0,$script='',$addFields='') { 04527 global $TYPO3_CONF_VARS; 04528 04529 // Initialize: 04530 $absPath = $this->getExtPath($extKey,$extInfo['type']); 04531 $relPath = $this->typeRelPaths[$extInfo['type']].$extKey.'/'; 04532 04533 // Look for template file for form: 04534 if (@is_file($absPath.'ext_conf_template.txt')) { 04535 04536 // Load tsStyleConfig class and parse configuration template: 04537 $tsStyleConfig = t3lib_div::makeInstance('t3lib_tsStyleConfig'); 04538 $tsStyleConfig->doNotSortCategoriesBeforeMakingForm = TRUE; 04539 $theConstants = $tsStyleConfig->ext_initTSstyleConfig( 04540 t3lib_div::getUrl($absPath.'ext_conf_template.txt'), 04541 $relPath, 04542 $absPath, 04543 $GLOBALS['BACK_PATH'] 04544 ); 04545 04546 // Load the list of resources. 04547 $tsStyleConfig->ext_loadResources($absPath.'res/'); 04548 04549 // Load current value: 04550 $arr = unserialize($TYPO3_CONF_VARS['EXT']['extConf'][$extKey]); 04551 $arr = is_array($arr) ? $arr : array(); 04552 04553 // Call processing function for constants config and data before write and form rendering: 04554 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/mod/tools/em/index.php']['tsStyleConfigForm'])) { 04555 $_params = array('fields' => &$theConstants, 'data' => &$arr, 'extKey' => $extKey); 04556 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/mod/tools/em/index.php']['tsStyleConfigForm'] as $_funcRef) { 04557 t3lib_div::callUserFunction($_funcRef,$_params,$this); 04558 } 04559 unset($_params); 04560 } 04561 04562 // If saving operation is done: 04563 if (t3lib_div::_POST('submit')) { 04564 $tsStyleConfig->ext_procesInput(t3lib_div::_POST(),array(),$theConstants,array()); 04565 $arr = $tsStyleConfig->ext_mergeIncomingWithExisting($arr); 04566 $this->writeTsStyleConfig($extKey,$arr); 04567 } 04568 04569 // Setting value array 04570 $tsStyleConfig->ext_setValueArray($theConstants,$arr); 04571 04572 // Getting session data: 04573 $MOD_MENU = array(); 04574 $MOD_MENU['constant_editor_cat'] = $tsStyleConfig->ext_getCategoriesForModMenu(); 04575 $MOD_SETTINGS = t3lib_BEfunc::getModuleData($MOD_MENU, t3lib_div::_GP('SET'), 'xMod_test'); 04576 04577 // Resetting the menu (stop) 04578 if (count($MOD_MENU)>1) { 04579 $menu = 'Category: '.t3lib_BEfunc::getFuncMenu(0,'SET[constant_editor_cat]',$MOD_SETTINGS['constant_editor_cat'],$MOD_MENU['constant_editor_cat'],'','&CMD[showExt]='.$extKey); 04580 $this->content.=$this->doc->section('','<span class="nobr">'.$menu.'</span>'); 04581 $this->content.=$this->doc->spacer(10); 04582 } 04583 04584 // Category and constant editor config: 04585 $form = ' 04586 <table border="0" cellpadding="0" cellspacing="0" width="600"> 04587 <tr> 04588 <td>'.$tsStyleConfig->ext_getForm($MOD_SETTINGS['constant_editor_cat'],$theConstants,$script,$addFields).'</td> 04589 </tr> 04590 </table>'; 04591 if ($output) { 04592 return $form; 04593 } else { 04594 $this->content.=$this->doc->section('','</form>'.$form.'<form>'); 04595 } 04596 } 04597 } 04598 04599 04600 04601 04602 04603 04604 04605 04606 04607 04608 /******************************* 04609 * 04610 * Dumping database (MySQL compliant) 04611 * 04612 ******************************/ 04613 04621 function dumpTableAndFieldStructure($arr) { 04622 $tables = array(); 04623 04624 if (count($arr)) { 04625 04626 // Get file header comment: 04627 $tables[] = $this->dumpHeader(); 04628 04629 // Traverse tables, write each table/field definition: 04630 foreach($arr as $table => $fieldKeyInfo) { 04631 $tables[] = $this->dumpTableHeader($table,$fieldKeyInfo); 04632 } 04633 } 04634 04635 // Return result: 04636 return implode(chr(10).chr(10).chr(10),$tables); 04637 } 04638 04646 function dumpStaticTables($tableList) { 04647 $instObj = new t3lib_install; 04648 $dbFields = $instObj->getFieldDefinitions_database(TYPO3_db); 04649 04650 $out = ''; 04651 $parts = t3lib_div::trimExplode(',',$tableList,1); 04652 04653 // Traverse the table list and dump each: 04654 foreach($parts as $table) { 04655 if (is_array($dbFields[$table]['fields'])) { 04656 $dHeader = $this->dumpHeader(); 04657 $header = $this->dumpTableHeader($table,$dbFields[$table],1); 04658 $insertStatements = $this->dumpTableContent($table,$dbFields[$table]['fields']); 04659 04660 $out.= $dHeader.chr(10).chr(10).chr(10). 04661 $header.chr(10).chr(10).chr(10). 04662 $insertStatements.chr(10).chr(10).chr(10); 04663 } else { 04664 die('Fatal error: Table for dump not found in database...'); 04665 } 04666 } 04667 return $out; 04668 } 04669 04675 function dumpHeader() { 04676 return trim(' 04677 # TYPO3 Extension Manager dump 1.1 04678 # 04679 # Host: '.TYPO3_db_host.' Database: '.TYPO3_db.' 04680 #-------------------------------------------------------- 04681 '); 04682 } 04683 04692 function dumpTableHeader($table,$fieldKeyInfo,$dropTableIfExists=0) { 04693 $lines = array(); 04694 $dump = ''; 04695 04696 // Create field definitions 04697 if (is_array($fieldKeyInfo['fields'])) { 04698 foreach($fieldKeyInfo['fields'] as $fieldN => $data) { 04699 $lines[]=' '.$fieldN.' '.$data; 04700 } 04701 } 04702 04703 // Create index key definitions 04704 if (is_array($fieldKeyInfo['keys'])) { 04705 foreach($fieldKeyInfo['keys'] as $fieldN => $data) { 04706 $lines[]=' '.$data; 04707 } 04708 } 04709 04710 // Compile final output: 04711 if (count($lines)) { 04712 $dump = trim(' 04713 # 04714 # Table structure for table "'.$table.'" 04715 # 04716 '.($dropTableIfExists ? 'DROP TABLE IF EXISTS '.$table.'; 04717 ' : '').'CREATE TABLE '.$table.' ( 04718 '.implode(','.chr(10),$lines).' 04719 );' 04720 ); 04721 } 04722 04723 return $dump; 04724 } 04725 04734 function dumpTableContent($table,$fieldStructure) { 04735 04736 // Substitution of certain characters (borrowed from phpMySQL): 04737 $search = array('\\', '\'', "\x00", "\x0a", "\x0d", "\x1a"); 04738 $replace = array('\\\\', '\\\'', '\0', '\n', '\r', '\Z'); 04739 04740 $lines = array(); 04741 04742 // Select all rows from the table: 04743 $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $table, ''); 04744 04745 // Traverse the selected rows and dump each row as a line in the file: 04746 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) { 04747 $values = array(); 04748 reset($fieldStructure); 04749 while(list($field) = each($fieldStructure)) { 04750 $values[] = isset($row[$field]) ? "'".str_replace($search, $replace, $row[$field])."'" : 'NULL'; 04751 } 04752 $lines[] = 'INSERT INTO '.$table.' VALUES ('.implode(', ',$values).');'; 04753 } 04754 04755 // Free DB result: 04756 $GLOBALS['TYPO3_DB']->sql_free_result($result); 04757 04758 // Implode lines and return: 04759 return implode(chr(10),$lines); 04760 } 04761 04769 function getTableAndFieldStructure($parts) { 04770 // Instance of install tool 04771 $instObj = new t3lib_install; 04772 $dbFields = $instObj->getFieldDefinitions_database(TYPO3_db); 04773 04774 04775 $outTables = array(); 04776 foreach($parts as $table) { 04777 $tP = explode('.',$table); 04778 if ($tP[0] && isset($dbFields[$tP[0]])) { 04779 if ($tP[1]) { 04780 $kfP = explode('KEY:',$tP[1],2); 04781 if (count($kfP)==2 && !$kfP[0]) { // key: 04782 if (isset($dbFields[$tP[0]]['keys'][$kfP[1]])) $outTables[$tP[0]]['keys'][$kfP[1]] = $dbFields[$tP[0]]['keys'][$kfP[1]]; 04783 } else { 04784 if (isset($dbFields[$tP[0]]['fields'][$tP[1]])) $outTables[$tP[0]]['fields'][$tP[1]] = $dbFields[$tP[0]]['fields'][$tP[1]]; 04785 } 04786 } else { 04787 $outTables[$tP[0]] = $dbFields[$tP[0]]; 04788 } 04789 } 04790 } 04791 04792 return $outTables; 04793 } 04794 04795 04796 04797 04798 04799 04800 04801 04802 04803 04804 /******************************* 04805 * 04806 * TER Communication functions 04807 * 04808 ******************************/ 04809 04810 04811 04819 function uploadExtensionToTER($em) { 04820 $msg = ''; 04821 $response = $this->terConnection->uploadToTER($em); 04822 04823 if(!is_array($response)) return $response; 04824 04825 if($response['resultCode']==TX_TER_RESULT_EXTENSIONSUCCESSFULLYUPLOADED) { 04826 $em['extInfo']['EM_CONF']['version'] = $response['version']; 04827 $response['resultMessages'][] = 'The extension is now version: '.$response['version']; 04828 $response['resultMessages'][] = $this->updateLocalEM_CONF($em['extKey'],$em['extInfo']); 04829 } 04830 04831 $msg = '<ul><li>'.implode('</li><li>',$response['resultMessages']).'</li></ul>'; 04832 return $msg; 04833 } 04834 04835 04836 04837 04838 04839 04840 04841 04842 04843 04844 /************************************ 04845 * 04846 * Various helper functions 04847 * 04848 ************************************/ 04849 04857 function listOrderTitle($listOrder,$key) { 04858 switch($listOrder) { 04859 case 'cat': 04860 return isset($this->categories[$key])?$this->categories[$key]:'<em>['.$key.']</em>'; 04861 break; 04862 case 'author_company': 04863 return $key; 04864 break; 04865 case 'state': 04866 return $this->states[$key]; 04867 break; 04868 case 'type': 04869 return $this->typeDescr[$key]; 04870 break; 04871 } 04872 } 04873 04882 function makeVersion($v,$mode) { 04883 $vDat = $this->renderVersion($v); 04884 return $vDat['version_'.$mode]; 04885 } 04886 04894 function renderVersion($v,$raise='') { 04895 $parts = t3lib_div::intExplode('.',$v.'..'); 04896 $parts[0] = t3lib_div::intInRange($parts[0],0,999); 04897 $parts[1] = t3lib_div::intInRange($parts[1],0,999); 04898 $parts[2] = t3lib_div::intInRange($parts[2],0,999); 04899 04900 switch((string)$raise) { 04901 case 'main': 04902 $parts[0]++; 04903 $parts[1]=0; 04904 $parts[2]=0; 04905 break; 04906 case 'sub': 04907 $parts[1]++; 04908 $parts[2]=0; 04909 break; 04910 case 'dev': 04911 $parts[2]++; 04912 break; 04913 } 04914 04915 $res = array(); 04916 $res['version'] = $parts[0].'.'.$parts[1].'.'.$parts[2]; 04917 $res['version_int'] = intval(str_pad($parts[0],3,'0',STR_PAD_LEFT).str_pad($parts[1],3,'0',STR_PAD_LEFT).str_pad($parts[2],3,'0',STR_PAD_LEFT)); 04918 $res['version_main'] = $parts[0]; 04919 $res['version_sub'] = $parts[1]; 04920 $res['version_dev'] = $parts[2]; 04921 04922 return $res; 04923 } 04924 04931 function ulFolder($extKey) { 04932 return 'uploads/tx_'.str_replace('_','',$extKey).'/'; 04933 } 04934 04940 function importAtAll() { 04941 return ($GLOBALS['TYPO3_CONF_VARS']['EXT']['allowGlobalInstall'] || $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowLocalInstall']); 04942 } 04943 04951 function importAsType($type,$lockType='') { 04952 switch($type) { 04953 case 'G': 04954 return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowGlobalInstall'] && (!$lockType || !strcmp($lockType,$type)); 04955 break; 04956 case 'L': 04957 return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowLocalInstall'] && (!$lockType || !strcmp($lockType,$type)); 04958 break; 04959 case 'S': 04960 return $this->systemInstall; 04961 break; 04962 default: 04963 return false; 04964 } 04965 } 04966 04973 function deleteAsType($type) { 04974 switch($type) { 04975 case 'G': 04976 return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowGlobalInstall']; 04977 break; 04978 case 'L': 04979 return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowLocalInstall']; 04980 break; 04981 default: 04982 return false; 04983 } 04984 } 04985 04994 function versionDifference($v1,$v2,$div=1) { 04995 return floor($this->makeVersion($v1,'int')/$div) > floor($this->makeVersion($v2,'int')/$div); 04996 } 04997 05006 function first_in_array($str,$array,$caseInsensitive=FALSE) { 05007 if ($caseInsensitive) $str = strtolower($str); 05008 if (is_array($array)) { 05009 foreach($array as $cl) { 05010 if ($caseInsensitive) $cl = strtolower($cl); 05011 if (t3lib_div::isFirstPartOfStr($cl,$str)) return true; 05012 } 05013 } 05014 return false; 05015 } 05016 05024 function includeEMCONF($path,$_EXTKEY) { 05025 @include($path); 05026 if(is_array($EM_CONF[$_EXTKEY])) { 05027 return $this->fixEMCONF($EM_CONF[$_EXTKEY]); 05028 } 05029 return false; 05030 } 05031 05039 function searchExtension($extKey,$row) { 05040 if ($this->lookUpStr) { 05041 return ( 05042 stristr($extKey,$this->lookUpStr) || 05043 stristr($row['EM_CONF']['title'],$this->lookUpStr) || 05044 stristr($row['EM_CONF']['description'],$this->lookUpStr) || 05045 stristr($row['EM_CONF']['author'],$this->lookUpStr) || 05046 stristr($row['EM_CONF']['author_company'],$this->lookUpStr) 05047 ); 05048 } else return true; 05049 } 05050 } 05051 05052 // Include extension? 05053 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/mod/tools/em/index.php']) { 05054 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/mod/tools/em/index.php']); 05055 } 05056 05057 ?>