Documentation TYPO3 par Ameos |
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 var $listingLimit = 500; // List that many extension maximally at one time (fixing memory problems) 00205 var $listingLimitAuthor = 250; // List that many extension maximally at one time (fixing memory problems) 00206 00211 var $defaultCategories = Array( 00212 'cat' => Array ( 00213 'be' => array(), 00214 'module' => array(), 00215 'fe' => array(), 00216 'plugin' => array(), 00217 'misc' => array(), 00218 'services' => array(), 00219 'templates' => array(), 00220 'example' => array(), 00221 'doc' => array() 00222 ) 00223 ); 00224 00229 var $categories = Array( 00230 'be' => 'Backend', 00231 'module' => 'Backend Modules', 00232 'fe' => 'Frontend', 00233 'plugin' => 'Frontend Plugins', 00234 'misc' => 'Miscellaneous', 00235 'services' => 'Services', 00236 'templates' => 'Templates', 00237 'example' => 'Examples', 00238 'doc' => 'Documentation' 00239 ); 00240 00245 var $states = Array ( 00246 'alpha' => 'Alpha', 00247 'beta' => 'Beta', 00248 'stable' => 'Stable', 00249 'experimental' => 'Experimental', 00250 'test' => 'Test', 00251 'obsolete' => 'Obsolete', 00252 ); 00253 00257 var $stateColors = Array ( 00258 'alpha' => '#d12438', 00259 'beta' => '#97b17e', 00260 'stable' => '#3bb65c', 00261 'experimental' => '#007eba', 00262 'test' => '#979797', 00263 'obsolete' => '#000000', 00264 ); 00265 00269 var $typeLabels = Array ( 00270 'S' => 'System', 00271 'G' => 'Global', 00272 'L' => 'Local', 00273 ); 00274 var $typeDescr = Array ( 00275 'S' => 'System extension (typo3/sysext/) - Always distributed with source code (Static).', 00276 'G' => 'Global extensions (typo3/ext/) - Available for shared source on server (Dynamic).', 00277 'L' => 'Local extensions (typo3conf/ext/) - Local for this TYPO3 installation only (Dynamic).', 00278 ); 00279 var $typePaths = Array(); // Also static, set in init() 00280 var $typeBackPaths = Array(); // Also static, set in init() 00281 00282 var $typeRelPaths = Array ( 00283 'S' => 'sysext/', 00284 'G' => 'ext/', 00285 'L' => '../typo3conf/ext/', 00286 ); 00287 00288 var $detailCols = Array ( 00289 0 => 2, 00290 1 => 5, 00291 2 => 6, 00292 3 => 6, 00293 4 => 4, 00294 5 => 1 00295 ); 00296 00297 var $fe_user = array( 00298 'username' => '', 00299 'password' => '', 00300 ); 00301 00302 var $privacyNotice = 'When you interact with the online repository, server information may be sent and stored in the repository for statistics.'; 00303 var $securityHint = '<strong>Found a security problem? Please get in touch with us!</strong><br />If you think you have found a security issue in TYPO3 or an extension, please contact the <a href="http://typo3.org/teams/security/" target="_blank">TYPO3 security team</a>! Thank you!'; 00304 var $editTextExtensions = 'html,htm,txt,css,tmpl,inc,php,sql,conf,cnf,pl,pm,sh,xml,ChangeLog'; 00305 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'; 00306 00307 00308 00309 00310 00311 // Default variables for backend modules 00312 var $MCONF = array(); // Module configuration 00313 var $MOD_MENU = array(); // Module menu items 00314 var $MOD_SETTINGS = array(); // Module session settings 00315 var $doc; // Document Template Object 00316 var $content; // Accumulated content 00317 00318 var $inst_keys = array(); // Storage of installed extensions 00319 var $gzcompress = 0; // Is set true, if system support compression. 00320 00321 var $terConnection; // instance of TER connection handler 00322 00323 // GPvars: 00324 var $CMD = array(); // CMD array 00325 var $listRemote; // If set, connects to remote repository 00326 var $lookUpStr; // Search string when listing local extensions 00327 00328 00329 00330 00331 /********************************* 00332 * 00333 * Standard module initialization 00334 * 00335 *********************************/ 00336 00342 function init() { 00343 global $BE_USER,$LANG,$BACK_PATH,$TYPO3_CONF_VARS; 00344 00345 // Setting paths of install scopes: 00346 $this->typePaths = Array ( 00347 'S' => TYPO3_mainDir.'sysext/', 00348 'G' => TYPO3_mainDir.'ext/', 00349 'L' => 'typo3conf/ext/' 00350 ); 00351 $this->typeBackPaths = Array ( 00352 'S' => '../../../', 00353 'G' => '../../../', 00354 'L' => '../../../../'.TYPO3_mainDir 00355 ); 00356 00357 $this->excludeForPackaging = $GLOBALS['TYPO3_CONF_VARS']['EXT']['excludeForPackaging']; 00358 00359 // Setting module configuration: 00360 $this->MCONF = $GLOBALS['MCONF']; 00361 00362 // Setting GPvars: 00363 $this->CMD = t3lib_div::_GP('CMD'); 00364 $this->lookUpStr = trim(t3lib_div::_GP('_lookUp')); 00365 $this->listRemote = t3lib_div::_GP('ter_connect'); 00366 $this->listRemote_search = trim(t3lib_div::_GP('ter_search')); 00367 00368 00369 // Configure menu 00370 $this->menuConfig(); 00371 00372 // Setting internal static: 00373 if ($TYPO3_CONF_VARS['EXT']['allowSystemInstall']) $this->systemInstall = 1; 00374 $this->requiredExt = t3lib_div::trimExplode(',',$TYPO3_CONF_VARS['EXT']['requiredExt'],1); 00375 00376 00377 // Initialize helper object 00378 $this->terConnection = t3lib_div::makeInstance('SC_mod_tools_em_terconnection'); 00379 $this->terConnection->emObj =& $this; 00380 $this->terConnection->wsdlURL = $TYPO3_CONF_VARS['EXT']['em_wsdlURL']; 00381 $this->xmlhandler = t3lib_div::makeInstance('SC_mod_tools_em_xmlhandler'); 00382 $this->xmlhandler->emObj =& $this; 00383 $this->xmlhandler->useUnchecked = $this->MOD_SETTINGS['display_unchecked']; 00384 $this->xmlhandler->useObsolete = $this->MOD_SETTINGS['display_obsolete']; 00385 00386 // Initialize Document Template object: 00387 $this->doc = t3lib_div::makeInstance('noDoc'); 00388 $this->doc->backPath = $BACK_PATH; 00389 $this->doc->docType = 'xhtml_trans'; 00390 00391 // JavaScript 00392 $this->doc->JScode = $this->doc->wrapScriptTags(' 00393 script_ended = 0; 00394 function jumpToUrl(URL) { // 00395 window.location.href = URL; 00396 } 00397 '); 00398 $this->doc->form = '<form action="index.php" method="post" name="pageform">'; 00399 00400 // Descriptions: 00401 $this->descrTable = '_MOD_'.$this->MCONF['name']; 00402 if ($BE_USER->uc['edit_showFieldHelp']) { 00403 $LANG->loadSingleTableDescription($this->descrTable); 00404 } 00405 00406 // Setting username/password etc. for upload-user: 00407 $this->fe_user['username'] = $this->MOD_SETTINGS['fe_u']; 00408 $this->fe_user['password'] = $this->MOD_SETTINGS['fe_p']; 00409 parent::init(); 00410 $this->handleExternalFunctionValue('singleDetails'); 00411 } 00412 00424 function handleExternalFunctionValue($MM_key='function', $MS_value=NULL) { 00425 $MS_value = is_null($MS_value) ? $this->MOD_SETTINGS[$MM_key] : $MS_value; 00426 $externalItems = $this->getExternalItemConfig($this->MCONF['name'],$MM_key,$MS_value); 00427 if (is_array($externalItems)) $this->extClassConf = array_merge($externalItems,is_array($this->extClassConf)?$this->extClassConf:array()); 00428 if (is_array($this->extClassConf) && $this->extClassConf['path']) { 00429 $this->include_once[]=$this->extClassConf['path']; 00430 } 00431 } 00432 00438 function menuConfig() { 00439 global $BE_USER, $TYPO3_CONF_VARS; 00440 00441 // MENU-ITEMS: 00442 $this->MOD_MENU = array( 00443 'function' => array( 00444 0 => 'Loaded extensions', 00445 1 => 'Install extensions', 00446 2 => 'Import extensions', 00447 4 => 'Translation handling', 00448 3 => 'Settings', 00449 ), 00450 'listOrder' => array( 00451 'cat' => 'Category', 00452 'author_company' => 'Author', 00453 'state' => 'State', 00454 'type' => 'Type' 00455 ), 00456 'display_details' => array( 00457 1 => 'Details', 00458 0 => 'Description', 00459 2 => 'More details', 00460 00461 3 => 'Technical (takes time!)', 00462 4 => 'Validating (takes time!)', 00463 5 => 'Changed? (takes time!)', 00464 ), 00465 'display_shy' => '', 00466 'display_own' => '', 00467 'display_unchecked' => '', 00468 'display_obsolete' => '', 00469 00470 'singleDetails' => array( 00471 'info' => 'Information', 00472 'edit' => 'Edit files', 00473 'backup' => 'Backup/Delete', 00474 'dump' => 'Dump DB', 00475 'upload' => 'Upload to TER', 00476 'updateModule' => 'UPDATE!', 00477 ), 00478 'fe_u' => '', 00479 'fe_p' => '', 00480 00481 'mirrorListURL' => '', 00482 'rep_url' => '', 00483 'extMirrors' => '', 00484 'selectedMirror' => '', 00485 00486 'selectedLanguages' => '' 00487 ); 00488 00489 $this->MOD_MENU['singleDetails'] = $this->mergeExternalItems($this->MCONF['name'],'singleDetails',$this->MOD_MENU['singleDetails']); 00490 00491 // page/be_user TSconfig settings and blinding of menu-items 00492 if (!$BE_USER->getTSConfigVal('mod.'.$this->MCONF['name'].'.allowTVlisting')) { 00493 unset($this->MOD_MENU['display_details'][3]); 00494 unset($this->MOD_MENU['display_details'][4]); 00495 unset($this->MOD_MENU['display_details'][5]); 00496 } 00497 00498 // CLEANSE SETTINGS 00499 $this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::_GP('SET'), $this->MCONF['name']); 00500 00501 if ($this->MOD_SETTINGS['function']==2) { 00502 // If listing from online repository, certain items are removed though: 00503 unset($this->MOD_MENU['listOrder']['type']); 00504 unset($this->MOD_MENU['display_details'][2]); 00505 unset($this->MOD_MENU['display_details'][3]); 00506 unset($this->MOD_MENU['display_details'][4]); 00507 unset($this->MOD_MENU['display_details'][5]); 00508 $this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::_GP('SET'), $this->MCONF['name']); 00509 } 00510 parent::menuConfig(); 00511 } 00512 00518 function main() { 00519 global $BE_USER,$LANG,$TYPO3_CONF_VARS; 00520 00521 if (empty($this->MOD_SETTINGS['mirrorListURL'])) $this->MOD_SETTINGS['mirrorListURL'] = $TYPO3_CONF_VARS['EXT']['em_mirrorListURL']; 00522 00523 // Starting page: 00524 $this->content.=$this->doc->startPage('Extension Manager'); 00525 $this->content.=$this->doc->header('Extension Manager'); 00526 $this->content.=$this->doc->spacer(5); 00527 00528 // Commands given which is executed regardless of main menu setting: 00529 if ($this->CMD['showExt']) { // Show details for a single extension 00530 $this->showExtDetails($this->CMD['showExt']); 00531 } elseif ($this->CMD['requestInstallExtensions']) { // Show details for a single extension 00532 $this->requestInstallExtensions($this->CMD['requestInstallExtensions']); 00533 } elseif ($this->CMD['importExt'] || $this->CMD['uploadExt']) { // Imports an extension from online rep. 00534 $err = $this->importExtFromRep($this->CMD['importExt'],$this->CMD['extVersion'],$this->CMD['loc'],$this->CMD['uploadExt']); 00535 if ($err) { 00536 $this->content.=$this->doc->section('',$GLOBALS['TBE_TEMPLATE']->rfw($err)); 00537 } 00538 if(!$err && $this->CMD['importExt']) { 00539 $this->installTranslationsForExtension($this->CMD['importExt'], $this->getMirrorURL()); 00540 } 00541 } elseif ($this->CMD['importExtInfo']) { // Gets detailed information of an extension from online rep. 00542 $this->importExtInfo($this->CMD['importExtInfo'],$this->CMD['extVersion']); 00543 } else { // No command - we show what the menu setting tells us: 00544 00545 $menu = $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.menu').' '. 00546 t3lib_BEfunc::getFuncMenu(0,'SET[function]',$this->MOD_SETTINGS['function'],$this->MOD_MENU['function']); 00547 00548 if (t3lib_div::inList('0,1,2',$this->MOD_SETTINGS['function'])) { 00549 $menu.=' Group by: '.t3lib_BEfunc::getFuncMenu(0,'SET[listOrder]',$this->MOD_SETTINGS['listOrder'],$this->MOD_MENU['listOrder']). 00550 ' Show: '.t3lib_BEfunc::getFuncMenu(0,'SET[display_details]',$this->MOD_SETTINGS['display_details'],$this->MOD_MENU['display_details']).'<br />'; 00551 } 00552 if (t3lib_div::inList('0,1',$this->MOD_SETTINGS['function'])) { 00553 $menu.='<label for="checkDisplayShy">Display shy extensions:</label> '.t3lib_BEfunc::getFuncCheck(0,'SET[display_shy]',$this->MOD_SETTINGS['display_shy'],'','','id="checkDisplayShy"'); 00554 } 00555 if (t3lib_div::inList('2',$this->MOD_SETTINGS['function']) && strlen($this->fe_user['username'])) { 00556 $menu.='<label for="checkDisplayOwn">Only my extensions:</label> '.t3lib_BEfunc::getFuncCheck(0,'SET[display_own]',$this->MOD_SETTINGS['display_own'],'','','id="checkDisplayOwn"'); 00557 } 00558 if (t3lib_div::inList('0,1,2',$this->MOD_SETTINGS['function'])) { 00559 $menu.=' <label for="checkDisplayObsolete">Show obsolete:</label> '.t3lib_BEfunc::getFuncCheck(0,'SET[display_obsolete]',$this->MOD_SETTINGS['display_obsolete'],'','','id="checkDisplayObsolete"'); 00560 } 00561 00562 $this->content.=$this->doc->section('','<span class="nobr">'.$menu.'</span>'); 00563 $this->content.=$this->doc->spacer(10); 00564 00565 switch((string)$this->MOD_SETTINGS['function']) { 00566 case '0': 00567 // Lists loaded (installed) extensions 00568 $this->extensionList_loaded(); 00569 break; 00570 case '1': 00571 // Lists the installed (available) extensions 00572 $this->extensionList_installed(); 00573 break; 00574 case '2': 00575 // Lists the extensions available from online rep. 00576 $this->extensionList_import(); 00577 break; 00578 case '3': 00579 // Shows the settings screen 00580 $this->alterSettings(); 00581 break; 00582 case '4': 00583 // Allows to set the translation preferences and check the status 00584 $this->translationHandling(); 00585 break; 00586 default: 00587 $this->extObjContent(); 00588 break; 00589 } 00590 } 00591 00592 // Shortcuts: 00593 if ($BE_USER->mayMakeShortcut()) { 00594 $this->content.=$this->doc->spacer(20).$this->doc->section('',$this->doc->makeShortcutIcon('CMD','function',$this->MCONF['name'])); 00595 } 00596 } 00597 00603 function printContent() { 00604 if ($this->doPrintContent) { 00605 $this->content.= $this->doc->endPage(); 00606 echo $this->content; 00607 } 00608 } 00609 00610 00611 00612 00613 00614 00615 00616 00617 00618 00619 /********************************* 00620 * 00621 * Function Menu Applications 00622 * 00623 *********************************/ 00624 00630 function extensionList_loaded() { 00631 global $TYPO3_LOADED_EXT; 00632 00633 list($list,$cat) = $this->getInstalledExtensions(); 00634 00635 // Loaded extensions 00636 $content = ''; 00637 $lines = array(); 00638 00639 // Available extensions 00640 if (is_array($cat[$this->MOD_SETTINGS['listOrder']])) { 00641 $content=''; 00642 $lines=array(); 00643 $lines[] = $this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="1" height="1" alt="" /></td>')); 00644 00645 foreach($cat[$this->MOD_SETTINGS['listOrder']] as $catName => $extEkeys) { 00646 natcasesort($extEkeys); 00647 reset($extEkeys); 00648 $extensions = array(); 00649 while(list($extKey)=each($extEkeys)) { 00650 if (array_key_exists($extKey,$TYPO3_LOADED_EXT) && ($this->MOD_SETTINGS['display_shy'] || !$list[$extKey]['EM_CONF']['shy']) && $this->searchExtension($extKey,$list[$extKey])) { 00651 if (in_array($extKey, $this->requiredExt)) { 00652 $loadUnloadLink = '<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('Rq').'</strong>'; 00653 } else { 00654 $loadUnloadLink = '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1').'">'.$this->removeButton().'</a>'; 00655 } 00656 00657 $extensions[] = $this->extensionListRow($extKey,$list[$extKey],array('<td class="bgColor">'.$loadUnloadLink.'</td>')); 00658 } 00659 } 00660 if(count($extensions)) { 00661 $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><br /></td></tr>'; 00662 $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>'; 00663 $lines[] = implode(chr(10),$extensions); 00664 } 00665 } 00666 } 00667 00668 $content.= t3lib_BEfunc::cshItem('_MOD_tools_em', 'loaded', $GLOBALS['BACK_PATH'],''); 00669 00670 $content.= 'Look up: <input type="text" name="_lookUp" value="'.htmlspecialchars($this->lookUpStr).'" /><input type="submit" value="Search"/><br/><br/>'; 00671 00672 $content.= ' 00673 00674 <!-- Loaded Extensions List --> 00675 <table border="0" cellpadding="2" cellspacing="1">'.implode('',$lines).'</table>'; 00676 00677 $this->content.=$this->doc->section('Loaded Extensions',$content,0,1); 00678 } 00679 00685 function extensionList_installed() { 00686 global $TYPO3_LOADED_EXT; 00687 00688 list($list,$cat)=$this->getInstalledExtensions(); 00689 00690 // Available extensions 00691 if (is_array($cat[$this->MOD_SETTINGS['listOrder']])) { 00692 $content=''; 00693 $lines=array(); 00694 $lines[]=$this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="18" height="1" alt="" /></td>')); 00695 00696 $allKeys=array(); 00697 foreach($cat[$this->MOD_SETTINGS['listOrder']] as $catName => $extEkeys) { 00698 if(!$this->MOD_SETTINGS['display_obsolete'] && $catName=='obsolete') continue; 00699 00700 $allKeys[]=''; 00701 $allKeys[]='TYPE: '.$catName; 00702 00703 natcasesort($extEkeys); 00704 reset($extEkeys); 00705 $extensions = array(); 00706 while(list($extKey)=each($extEkeys)) { 00707 $allKeys[]=$extKey; 00708 if ((!$list[$extKey]['EM_CONF']['shy'] || $this->MOD_SETTINGS['display_shy']) && 00709 ($list[$extKey]['EM_CONF']['state']!='obsolete' || $this->MOD_SETTINGS['display_obsolete']) 00710 && $this->searchExtension($extKey,$list[$extKey])) { 00711 $loadUnloadLink = t3lib_extMgm::isLoaded($extKey)? 00712 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->removeButton().'</a>': 00713 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[load]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->installButton().'</a>'; 00714 if (in_array($extKey,$this->requiredExt)) { 00715 $loadUnloadLink='<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('Rq').'</strong>'; 00716 } 00717 $theRowClass = t3lib_extMgm::isLoaded($extKey)? 'em-listbg1' : 'em-listbg2'; 00718 $extensions[]=$this->extensionListRow($extKey,$list[$extKey],array('<td class="bgColor">'.$loadUnloadLink.'</td>'),$theRowClass); 00719 } 00720 } 00721 if(count($extensions)) { 00722 $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><br /></td></tr>'; 00723 $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>'; 00724 $lines[] = implode(chr(10),$extensions); 00725 } 00726 } 00727 00728 $content.=' 00729 00730 00731 <!-- 00732 EXTENSION KEYS: 00733 00734 '.trim(implode(chr(10),$allKeys)).' 00735 00736 --> 00737 00738 '; 00739 00740 $content.= t3lib_BEfunc::cshItem('_MOD_tools_em', 'avail', $GLOBALS['BACK_PATH'],'|<br/>'); 00741 $content.= 'If you want to use an extension in TYPO3, you should simply click the "plus" button '.$this->installButton().' . <br /> 00742 Installed extensions can also be removed again - just click the remove button '.$this->removeButton().' .<br /><br />'; 00743 00744 $content.= 'Look up: <input type="text" name="_lookUp" value="'.htmlspecialchars($this->lookUpStr).'" /><input type="submit" value="Search"/><br/><br/>'; 00745 $content.= $this->securityHint.'<br /><br />'; 00746 00747 $content.= '<table border="0" cellpadding="2" cellspacing="1">'.implode('',$lines).'</table>'; 00748 00749 $this->content.=$this->doc->section('Available Extensions - Grouped by: '.$this->MOD_MENU['listOrder'][$this->MOD_SETTINGS['listOrder']],$content,0,1); 00750 } 00751 } 00752 00758 function extensionList_import() { 00759 global $TYPO3_LOADED_EXT; 00760 $content=''; 00761 00762 // Listing from online repository: 00763 if ($this->listRemote) { 00764 list($inst_list,) = $this->getInstalledExtensions(); 00765 $this->inst_keys = array_flip(array_keys($inst_list)); 00766 00767 $this->detailCols[1]+=6; 00768 00769 // see if we have an extensionlist at all 00770 $this->extensionCount = $this->xmlhandler->countExtensions(); 00771 if (!$this->extensionCount) { 00772 $content .= $this->fetchMetaData('extensions'); 00773 } 00774 00775 if($this->MOD_SETTINGS['listOrder']=='author_company') { 00776 $this->listingLimit = $this->listingLimitAuthor; 00777 } 00778 00779 $this->pointer = intval(t3lib_div::_GP('pointer')); 00780 $offset = $this->listingLimit*$this->pointer; 00781 00782 if($this->MOD_SETTINGS['display_own'] && strlen($this->fe_user['username'])) { 00783 $this->xmlhandler->searchExtensionsXML($this->listRemote_search, $this->fe_user['username'], $this->MOD_SETTINGS['listOrder']); 00784 } else { 00785 $this->xmlhandler->searchExtensionsXML($this->listRemote_search, '', $this->MOD_SETTINGS['listOrder'], false, false, $offset, $this->listingLimit); 00786 } 00787 if (count($this->xmlhandler->extensionsXML)) { 00788 list($list,$cat) = $this->prepareImportExtList(true); 00789 00790 // Available extensions 00791 if (is_array($cat[$this->MOD_SETTINGS['listOrder']])) { 00792 $lines=array(); 00793 $lines[]=$this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="18" height="1" alt="" /></td>'),1); 00794 00795 foreach($cat[$this->MOD_SETTINGS['listOrder']] as $catName => $extEkeys) { 00796 if (count($extEkeys)) { 00797 $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><br /></td></tr>'; 00798 $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>'; 00799 00800 natcasesort($extEkeys); 00801 reset($extEkeys); 00802 while(list($extKey)=each($extEkeys)) { 00803 $version = array_keys($list[$extKey]['versions']); 00804 $version = end($version); 00805 $ext = $list[$extKey]['versions'][$version]; 00806 $ext['downloadcounter_all'] = $list[$extKey]['downloadcounter']; 00807 $ext['_ICON'] = $list[$extKey]['_ICON']; 00808 $loadUnloadLink=''; 00809 if ($inst_list[$extKey]['type']!='S' && (!isset($inst_list[$extKey]) || $this->versionDifference($version,$inst_list[$extKey]['EM_CONF']['version'],$this->versionDiffFactor))) { 00810 if (isset($inst_list[$extKey])) { 00811 // update 00812 $loc= ($inst_list[$extKey]['type']=='G'?'G':'L'); 00813 $aUrl = 'index.php?CMD[importExt]='.$extKey.'&CMD[extVersion]='.$version.'&CMD[loc]='.$loc; 00814 $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>'; 00815 } else { 00816 // import 00817 $aUrl = 'index.php?CMD[importExt]='.$extKey.'&CMD[extVersion]='.$version.'&CMD[loc]=L'; 00818 $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>'; 00819 } 00820 } else { 00821 $loadUnloadLink = ' '; 00822 } 00823 00824 if (isset($inst_list[$extKey])) { 00825 $theRowClass = t3lib_extMgm::isLoaded($extKey) ? 'em-listbg1' : 'em-listbg2'; 00826 } else { 00827 $theRowClass = 'em-listbg3'; 00828 } 00829 00830 $lines[]=$this->extensionListRow($extKey,$ext,array('<td class="bgColor">'.$loadUnloadLink.'</td>'),$theRowClass,$inst_list,1,'index.php?CMD[importExtInfo]='.rawurlencode($extKey)); 00831 unset($list[$extKey]); 00832 } 00833 } 00834 } 00835 unset($list); 00836 00837 // CSH: 00838 $content.= t3lib_BEfunc::cshItem('_MOD_tools_em', 'import_ter', $GLOBALS['BACK_PATH'],'|<br/>'); 00839 $onsubmit = "window.location.href='index.php?ter_connect=1&ter_search='+escape(this.elements['_lookUp'].value);return false;"; 00840 $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 /> 00841 <input type="text" name="_lookUp" value="'.htmlspecialchars($this->listRemote_search).'" /> <input type="submit" value="Look up" /><br /><br />'; 00842 00843 $content .= $this->browseLinks(); 00844 00845 $content.= ' 00846 00847 <!-- TER Extensions list --> 00848 <table border="0" cellpadding="2" cellspacing="1">'.implode(chr(10),$lines).'</table>'; 00849 $content .= '<br />'.$this->browseLinks(); 00850 $content.= '<br /><br />'.$this->securityHint; 00851 $content.= '<br /><br /><strong>PRIVACY NOTICE:</strong><br /> '.$this->privacyNotice; 00852 00853 $this->content.=$this->doc->section('Extensions in TYPO3 Extension Repository (online) - Grouped by: '.$this->MOD_MENU['listOrder'][$this->MOD_SETTINGS['listOrder']],$content,0,1); 00854 00855 // Plugins which are NOT uploaded to repository but present on this server. 00856 $content=''; 00857 $lines=array(); 00858 if (count($this->inst_keys)) { 00859 reset($this->inst_keys); 00860 while(list($extKey)=each($this->inst_keys)) { 00861 $this->xmlhandler->searchExtensionsXML($extKey, '', '', true); 00862 if((strlen($this->listRemote_search) && !stristr($extKey,$this->listRemote_search)) || isset($this->xmlhandler->extensionsXML[$extKey])) continue; 00863 00864 $loadUnloadLink = t3lib_extMgm::isLoaded($extKey)? 00865 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->removeButton().'</a>': 00866 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[load]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->installButton().'</a>'; 00867 if (in_array($extKey,$this->requiredExt)) $loadUnloadLink='<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('Rq').'</strong>'; 00868 $lines[]=$this->extensionListRow($extKey,$inst_list[$extKey],array('<td class="bgColor">'.$loadUnloadLink.'</td>'),t3lib_extMgm::isLoaded($extKey)?'em-listbg1':'em-listbg2'); 00869 } 00870 } 00871 if(count($lines)) { 00872 $content.= 'This is the list of extensions which are available locally, but not in the repository.<br />They might be user-defined and should be prepended user_ then.<br /><br />'; 00873 $content.= '<table border="0" cellpadding="2" cellspacing="1">'. 00874 $this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="18" height="1" alt="" /></td>')). 00875 implode('',$lines).'</table>'; 00876 $this->content.=$this->doc->spacer(20); 00877 $this->content.=$this->doc->section('Extensions found only on this server',$content,0,1); 00878 } 00879 } 00880 } else { 00881 $content.= t3lib_BEfunc::cshItem('_MOD_tools_em', 'import_ter', $GLOBALS['BACK_PATH'],'|<br/>'); 00882 $onsubmit = "window.location.href='index.php?ter_connect=1&ter_search='+escape(this.elements['_lookUp'].value);return false;"; 00883 $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 /> 00884 <input type="text" name="_lookUp" value="'.htmlspecialchars($this->listRemote_search).'" /> <input type="submit" value="Look up" /><br /><br />'; 00885 00886 $content.= '<p><strong>No matching extensions found.</strong></p>'; 00887 00888 $content.= '<br /><br /><strong>PRIVACY NOTICE:</strong><br /> '.$this->privacyNotice; 00889 $this->content.=$this->doc->section('Extensions in TYPO3 Extension Repository (online) - Grouped by: '.$this->MOD_MENU['listOrder'][$this->MOD_SETTINGS['listOrder']],$content,0,1); 00890 } 00891 } else { 00892 // CSH 00893 $content.= t3lib_BEfunc::cshItem('_MOD_tools_em', 'import', $GLOBALS['BACK_PATH'],'|<br/>'); 00894 00895 $onsubmit = "window.location.href='index.php?ter_connect=1&ter_search='+escape(this.elements['_lookUp'].value);return false;"; 00896 $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 /> 00897 <input type="text" name="_lookUp" value="" /> <input type="submit" value="Look up" /><br /><br />'; 00898 00899 if ($this->CMD['fetchMetaData']) { // fetches mirror/extension data from online rep. 00900 $content .= $this->fetchMetaData($this->CMD['fetchMetaData']); 00901 } else { 00902 $onCLick = "window.location.href='index.php?CMD[fetchMetaData]=extensions';return false;"; 00903 $content.= 'Connect to the current mirror and retrieve the current list of available plugins from the TYPO3 Extension Repository.<br /> 00904 <input type="submit" value="Retrieve/Update" onclick="'.htmlspecialchars($onCLick).'" />'; 00905 if (is_file(PATH_site.'typo3temp/extensions.xml.gz')) { 00906 $dateFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy']; 00907 $timeFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm']; 00908 $content.= ' (last update: '.date($dateFormat.' '.$timeFormat,filemtime(PATH_site.'typo3temp/extensions.xml.gz')).')'; 00909 } 00910 } 00911 $content.= '<br /><br />'.$this->securityHint; 00912 $content.= '<br /><br /><strong>PRIVACY NOTICE:</strong><br />'.$this->privacyNotice; 00913 00914 $this->content.=$this->doc->section('Extensions in TYPO3 Extension Repository',$content,0,1); 00915 } 00916 00917 // Upload: 00918 if ($this->importAtAll()) { 00919 $content= '</form><form action="index.php" enctype="'.$GLOBALS['TYPO3_CONF_VARS']['SYS']['form_enctype'].'" method="post"> 00920 Upload extension file (.t3x):<br /> 00921 <input type="file" size="60" name="upload_ext_file" /><br /> 00922 ... to location:<br /> 00923 <select name="CMD[loc]">'; 00924 if ($this->importAsType('L')) $content.='<option value="L">Local (../typo3conf/ext/)</option>'; 00925 if ($this->importAsType('G')) $content.='<option value="G">Global (typo3/ext/)</option>'; 00926 if ($this->importAsType('S')) $content.='<option value="S">System (typo3/sysext/)</option>'; 00927 $content.='</select><br /> 00928 <input type="checkbox" value="1" name="CMD[uploadOverwrite]" id="checkUploadOverwrite" /> <label for="checkUploadOverwrite">Overwrite any existing extension!</label><br /> 00929 <input type="submit" name="CMD[uploadExt]" value="Upload extension file" /><br /> 00930 '; 00931 } else $content=$this->noImportMsg(); 00932 00933 $this->content.=$this->doc->spacer(20); 00934 $this->content.=$this->doc->section('Upload extension file directly (.t3x):',$content,0,1); 00935 } 00936 00942 function browseLinks() { 00943 $content = ''; 00944 if ($this->pointer) { 00945 $content .= '<a href="'.t3lib_div::linkThisScript(array('pointer' => $this->pointer-1)).'" class="typo3-prevPage"><img'.t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'],'gfx/pilleft_n.gif','width="14" height="14"').' alt="Prev page" /> Prev page</a>'; 00946 } 00947 if ($content) $content .= ' '; 00948 if (intval($this->xmlhandler->matchingCount/$this->listingLimit)>$this->pointer) { 00949 $content .= '<a href="'.t3lib_div::linkThisScript(array('pointer' => $this->pointer+1)).'" class="typo3-nextPage"><img'.t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'],'gfx/pilright_n.gif','width="14" height="14"').' alt="Next page" /> Next page</a>'; 00950 } 00951 $upper = (($this->pointer+1)*$this->listingLimit); 00952 if ($upper>$this->xmlhandler->matchingCount) { 00953 $upper = $this->xmlhandler->matchingCount; 00954 } 00955 if ($content) $content .= '<br /><br />Showing extensions <strong>'.($this->pointer*$this->listingLimit+1).'</strong> to <strong>'.$upper.'</strong>'; 00956 if ($content) $content .= '<br /><br />'; 00957 return $content; 00958 } 00959 00965 function alterSettings() { 00966 00967 // Prepare the HTML output: 00968 $content.= ' 00969 '.t3lib_BEfunc::cshItem('_MOD_tools_em', 'settings', $GLOBALS['BACK_PATH'],'|<br/>').' 00970 <fieldset><legend>Security Settings</legend> 00971 <table border="0" cellpadding="2" cellspacing="2"> 00972 <tr class="bgColor4"> 00973 <td><label for="display_unchecked">Enable extensions without review (basic security check):</label></td> 00974 <td>'.t3lib_BEfunc::getFuncCheck(0,'SET[display_unchecked]',$this->MOD_SETTINGS['display_unchecked'],'','','id="display_unchecked"').'</td> 00975 </tr> 00976 </table> 00977 <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>! 00978 </fieldset> 00979 <br /> 00980 <br /> 00981 <fieldset><legend>User Settings</legend> 00982 <table border="0" cellpadding="2" cellspacing="2"> 00983 <tr class="bgColor4"> 00984 <td>Enter repository username:</td> 00985 <td><input type="text" name="SET[fe_u]" value="'.htmlspecialchars($this->MOD_SETTINGS['fe_u']).'" /></td> 00986 </tr> 00987 <tr class="bgColor4"> 00988 <td>Enter repository password:</td> 00989 <td><input type="password" name="SET[fe_p]" value="'.htmlspecialchars($this->MOD_SETTINGS['fe_p']).'" /></td> 00990 </tr> 00991 </table> 00992 <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! 00993 </fieldset> 00994 <br /> 00995 <br /> 00996 <fieldset><legend>Mirror selection</legend> 00997 <table border="0" cellpadding="2" cellspacing="2"> 00998 <tr class="bgColor4"> 00999 <td>Enter mirror list URL:</td> 01000 <td><input type="text" size="50" name="SET[mirrorListURL]" value="'.htmlspecialchars($this->MOD_SETTINGS['mirrorListURL']).'" /></td> 01001 </tr> 01002 </table> 01003 <br /> 01004 <p>Select a mirror from below. This list is built from the online mirror list retrieved from the URL above.<br /><br /></p> 01005 <fieldset><legend>Mirror list</legend>'; 01006 if(!empty($this->MOD_SETTINGS['mirrorListURL'])) { 01007 if ($this->CMD['fetchMetaData']) { // fetches mirror/extension data from online rep. 01008 $content .= $this->fetchMetaData($this->CMD['fetchMetaData']); 01009 } else { 01010 $content.= '<a href="index.php?CMD[fetchMetaData]=mirrors">Click here to reload the list.</a>'; 01011 } 01012 } 01013 $content .= '<br /> 01014 <table cellspacing="4" style="text-align:left; vertical-alignment:top;"> 01015 <tr><td>Use</td><td>Name</td><td>URL</td><td>Country</td><td>Sponsored by</td></tr> 01016 '; 01017 01018 if (!strlen($this->MOD_SETTINGS['extMirrors'])) $this->fetchMetaData('mirrors'); 01019 $extMirrors = unserialize($this->MOD_SETTINGS['extMirrors']); 01020 $extMirrors[''] = array('title'=>'Random (recommended!)'); 01021 ksort($extMirrors); 01022 if(is_array($extMirrors)) { 01023 foreach($extMirrors as $k => $v) { 01024 if(isset($v['sponsor'])) { 01025 $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>'; 01026 } 01027 $selected = ($this->MOD_SETTINGS['selectedMirror']==$k) ? 'checked="checked"' : ''; 01028 $content.='<tr class="bgColor4"> 01029 <td><input type="radio" name="SET[selectedMirror]" id="selectedMirror'.$k.'" value="'.$k.'" '.$selected.'/></td><td><label for="selectedMirror'.$k.'">'.htmlspecialchars($v['title']).'</label></td><td>'.htmlspecialchars($v['host'].$v['path']).'</td><td>'.$v['country'].'</td><td>'.$sponsor.'</td></tr>'; 01030 } 01031 } 01032 $content.= ' 01033 </table> 01034 </fieldset> 01035 <br /> 01036 <table border="0" cellpadding="2" cellspacing="2"> 01037 <tr class="bgColor4"> 01038 <td>Enter repository URL:</td> 01039 <td><input type="text" size="50" name="SET[rep_url]" value="'.htmlspecialchars($this->MOD_SETTINGS['rep_url']).'" /></td> 01040 </tr> 01041 </table> 01042 01043 If you set a repository URL, this overrides the use of a mirror. Use this to select a specific (private) repository.<br /> 01044 </fieldset> 01045 <br /> 01046 <input type="submit" value="Update" /> 01047 '; 01048 01049 $this->content.=$this->doc->section('Repository settings',$content,0,1); 01050 } 01051 01057 function translationHandling() { 01058 global $LANG, $TYPO3_LOADED_EXT; 01059 $LANG->includeLLFile('EXT:setup/mod/locallang.xml'); 01060 01061 $incoming = t3lib_div::_POST('SET'); 01062 if(isset($incoming['selectedLanguages']) && is_array($incoming['selectedLanguages'])) { 01063 t3lib_BEfunc::getModuleData($this->MOD_MENU, array('selectedLanguages' => serialize($incoming['selectedLanguages'])), $this->MCONF['name'], '', 'selectedLanguages'); 01064 $this->MOD_SETTINGS['selectedLanguages'] = serialize($incoming['selectedLanguages']); 01065 } 01066 01067 $selectedLanguages = unserialize($this->MOD_SETTINGS['selectedLanguages']); 01068 if(count($selectedLanguages)==1 && empty($selectedLanguages[0])) $selectedLanguages = array(); 01069 $theLanguages = t3lib_div::trimExplode('|',TYPO3_languages); 01070 foreach($theLanguages as $val) { 01071 if ($val!='default') { 01072 $localLabel = ' - ['.htmlspecialchars($GLOBALS['LOCAL_LANG']['default']['lang_'.$val]).']'; 01073 $selected = (is_array($selectedLanguages) && in_array($val, $selectedLanguages)) ? ' selected="selected"' : ''; 01074 $opt[$GLOBALS['LOCAL_LANG']['default']['lang_'.$val].'--'.$val]=' 01075 <option value="'.$val.'"'.$selected.'>'.$LANG->getLL('lang_'.$val,1).$localLabel.'</option>'; 01076 } 01077 } 01078 ksort($opt); 01079 01080 // Prepare the HTML output: 01081 $content.= ' 01082 '.t3lib_BEfunc::cshItem('_MOD_tools_em', 'translation', $GLOBALS['BACK_PATH'],'|<br/>').' 01083 <fieldset><legend>Translation Settings</legend> 01084 <table border="0" cellpadding="2" cellspacing="2"> 01085 <tr class="bgColor4"> 01086 <td>Languages to fetch:</td> 01087 <td> 01088 <select name="SET[selectedLanguages][]" multiple="multiple" size="10"> 01089 <option></option>'. 01090 implode('',$opt).' 01091 </select> 01092 </td> 01093 </tr> 01094 </table> 01095 <br /> 01096 <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 /> 01097 <br />To request an update/install for already loaded extensions, see below.</p> 01098 </fieldset> 01099 <br /> 01100 <input type="submit" value="Save selection" /> 01101 <br /> 01102 </fieldset>'; 01103 01104 $this->content.=$this->doc->section('Translation settings',$content,0,1); 01105 01106 if(count($selectedLanguages)>0) { 01107 $mirrorURL = $this->getMirrorURL(); 01108 $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')).'\'" />'; 01109 01110 if(t3lib_div::_GET('l10n') == 'check') { 01111 $loadedExtensions = array_keys($TYPO3_LOADED_EXT); 01112 $loadedExtensions = array_diff($loadedExtensions,array('_CACHEFILE')); 01113 01114 // Override content output - we now do that ourself: 01115 echo ($this->content . $this->doc->section('Translation status',$content,0,1)); 01116 $this->doPrintContent = FALSE; 01117 flush(); 01118 01119 echo ' 01120 <br /> 01121 <br /> 01122 <p id="progress-message"> 01123 Checking translation status, please wait ... 01124 </p> 01125 <br /> 01126 <div style="width:100%; height:20px; border: 1px solid black;"> 01127 <div id="progress-bar" style="float: left; width: 0%; height: 20px; background-color:green;"> </div> 01128 <div id="transparent-bar" style="float: left; width: 100%; height: 20px; background-color:'.$this->doc->bgColor2.';"> </div> 01129 </div> 01130 <br /> 01131 <br /><p>This table shows the status of the loaded extension\'s translations.</p><br /> 01132 <table border="0" cellpadding="2" cellspacing="2"> 01133 <tr class="bgColor2"><td>Extension key</td> 01134 '; 01135 01136 foreach($selectedLanguages as $lang) { 01137 echo ('<td>'.$LANG->getLL('lang_'.$lang,1).'</td>'); 01138 } 01139 echo ('</tr>'); 01140 01141 $counter = 1; 01142 foreach($loadedExtensions as $extKey) { 01143 01144 $percentDone = intval (($counter / count($loadedExtensions)) * 100); 01145 echo (' 01146 <script> 01147 document.getElementById("progress-bar").style.width = "'.$percentDone.'%"; 01148 document.getElementById("transparent-bar").style.width = "'.(100-$percentDone).'%"; 01149 document.getElementById("progress-message").firstChild.data="Checking translation status for extension \"'.$extKey.'\" ..."; 01150 </script> 01151 '); 01152 01153 flush(); 01154 $translationStatusArr = $this->terConnection->fetchTranslationStatus($extKey,$mirrorURL); 01155 01156 echo ('<tr class="bgColor4"><td>'.$extKey.'</td>'); 01157 foreach($selectedLanguages as $lang) { 01158 // remote unknown -> keine l10n 01159 if(!isset($translationStatusArr[$lang])) { 01160 echo ('<td title="No translation available">N/A</td>'); 01161 continue; 01162 } 01163 // determine local md5 from zip 01164 if(is_file(PATH_site.'typo3temp/'.$extKey.'-l10n-'.$lang.'.zip')) { 01165 $localmd5 = md5_file(PATH_site.'typo3temp/'.$extKey.'-l10n-'.$lang.'.zip'); 01166 } else { 01167 echo ('<td title="Not installed / Unknown" style="background-color:#ff0">???</td>'); 01168 continue; 01169 } 01170 // local!=remote -> needs update 01171 if($localmd5 != $translationStatusArr[$lang]['md5']) { 01172 echo ('<td title="Needs update" style="background-color:#ff0">UPD</td>'); 01173 continue; 01174 } 01175 echo ('<td title="Is up to date" style="background-color:#69a550">OK</td>'); 01176 } 01177 echo ('</tr>'); 01178 01179 $counter ++; 01180 } 01181 echo '</table> 01182 <script> 01183 document.getElementById("progress-message").firstChild.data="Check done."; 01184 </script> 01185 '; 01186 echo $this->doc->endPage(); 01187 return ''; 01188 01189 } elseif(t3lib_div::_GET('l10n') == 'update') { 01190 $loadedExtensions = array_keys($TYPO3_LOADED_EXT); 01191 $loadedExtensions = array_diff($loadedExtensions,array('_CACHEFILE')); 01192 01193 // Override content output - we now do that ourself: 01194 echo ($this->content . $this->doc->section('Translation status',$content,0,1)); 01195 $this->doPrintContent = FALSE; 01196 flush(); 01197 01198 echo (' 01199 <br /> 01200 <br /> 01201 <p id="progress-message"> 01202 Updating translations, please wait ... 01203 </p> 01204 <br /> 01205 <div style="width:100%; height:20px; border: 1px solid black;"> 01206 <div id="progress-bar" style="float: left; width: 0%; height: 20px; background-color:green;"> </div> 01207 <div id="transparent-bar" style="float: left; width: 100%; height: 20px; background-color:'.$this->doc->bgColor2.';"> </div> 01208 </div> 01209 <br /> 01210 <br /><p>This table shows the update results of the loaded extension\'s translations.<br /> 01211 <em>If you want to force a full check/update, delete the l10n zip-files from the typo3temp folder.</em></p><br /> 01212 <table border="0" cellpadding="2" cellspacing="2"> 01213 <tr class="bgColor2"><td>Extension key</td> 01214 '); 01215 01216 foreach($selectedLanguages as $lang) { 01217 echo '<td>'.$LANG->getLL('lang_'.$lang,1).'</td>'; 01218 } 01219 echo '</tr>'; 01220 01221 $counter = 1; 01222 foreach($loadedExtensions as $extKey) { 01223 $percentDone = intval (($counter / count($loadedExtensions)) * 100); 01224 echo (' 01225 <script> 01226 document.getElementById("progress-bar").style.width = "'.$percentDone.'%"; 01227 document.getElementById("transparent-bar").style.width = "'.(100-$percentDone).'%"; 01228 document.getElementById("progress-message").firstChild.data="Updating translation for extension \"'.$extKey.'\" ..."; 01229 </script> 01230 '); 01231 01232 flush(); 01233 $translationStatusArr = $this->terConnection->fetchTranslationStatus($extKey,$mirrorURL); 01234 01235 echo ('<tr class="bgColor4"><td>'.$extKey.'</td>'); 01236 if(is_array($translationStatusArr)) { 01237 foreach($selectedLanguages as $lang) { 01238 // remote unknown -> no l10n available 01239 if(!isset($translationStatusArr[$lang])) { 01240 echo ('<td title="No translation available">N/A</td>'); 01241 continue; 01242 } 01243 // determine local md5 from zip 01244 if(is_file(PATH_site.'typo3temp/'.$extKey.'-l10n-'.$lang.'.zip')) { 01245 $localmd5 = md5_file(PATH_site.'typo3temp/'.$extKey.'-l10n-'.$lang.'.zip'); 01246 } else { 01247 $localmd5 = 'zzz'; 01248 } 01249 // local!=remote or not installed -> needs update 01250 if($localmd5 != $translationStatusArr[$lang]['md5']) { 01251 $ret = $this->updateTranslation($extKey, $lang, $mirrorURL); 01252 if($ret === true) { 01253 echo ('<td title="Has been updated" style="background-color:#69a550">UPD</td>'); 01254 } else { 01255 echo ('<td title="'.htmlspecialchars($ret).'" style="background-color:#cb3352">ERR</td>'); 01256 } 01257 continue; 01258 } 01259 echo ('<td title="Is up to date" style="background-color:#69a550">OK</td>'); 01260 } 01261 } else { 01262 echo ('<td colspan="'.count($selectedLanguages).'" title="Possible reasons: network problems, allow_url_fopen off, curl not enabled in Install tool.">Could not fetch translation status</td>'); 01263 } 01264 echo ('</tr>'); 01265 $counter++; 01266 } 01267 echo '</table> 01268 <script> 01269 document.getElementById("progress-message").firstChild.data="Update done."; 01270 </script> 01271 '; 01272 echo $this->doc->endPage(); 01273 return ''; 01274 } 01275 01276 $this->content.=$this->doc->section('Translation status',$content,0,1); 01277 } 01278 } 01279 01288 function updateTranslation($extKey, $lang, $mirrorURL) { 01289 $l10n = $this->terConnection->fetchTranslation($extKey, $lang, $mirrorURL); 01290 if(is_array($l10n)) { 01291 $file = PATH_site.'typo3temp/'.$extKey.'-l10n-'.$lang.'.zip'; 01292 $path = 'l10n/'.$lang.'/'; 01293 if(!is_dir(PATH_typo3conf.$path)) t3lib_div::mkdir_deep(PATH_typo3conf,$path); 01294 t3lib_div::writeFile($file, $l10n[0]); 01295 if($this->unzip($file, PATH_typo3conf.$path)) { 01296 return true; 01297 } else { 01298 return 'Unpacking the language pack failed!'; 01299 } 01300 } else { 01301 return $l10n; 01302 } 01303 } 01304 01312 function installTranslationsForExtension($extKey, $mirrorURL) { 01313 $selectedLanguages = unserialize($this->MOD_SETTINGS['selectedLanguages']); 01314 if(!is_array($selectedLanguages)) $selectedLanguages = array(); 01315 foreach($selectedLanguages as $lang) { 01316 $l10n = $this->terConnection->fetchTranslation($extKey, $lang, $mirrorURL); 01317 if(is_array($l10n)) { 01318 $file = PATH_typo3conf.'l10n/'.$extKey.'-l10n-'.$lang.'.zip'; 01319 $path = 'l10n/'.$lang.'/'.$extKey; 01320 t3lib_div::writeFile($file, $l10n[0]); 01321 if(!is_dir(PATH_typo3conf.$path)) t3lib_div::mkdir_deep(PATH_typo3conf,$path); 01322 if($this->unzip($file, PATH_typo3conf.$path)) { 01323 return true; 01324 } else { 01325 return 'Unpacking the language pack failed!'; 01326 } 01327 } else { 01328 return $l10n; 01329 } 01330 } 01331 } 01332 01342 function unzip($file, $path) { 01343 if(strlen($GLOBALS['TYPO3_CONF_VARS']['BE']['unzip_path'])) { 01344 chdir($path); 01345 $cmd = $GLOBALS['TYPO3_CONF_VARS']['BE']['unzip_path'].' -o '.escapeshellarg($file); 01346 exec($cmd, $list, $ret); 01347 return ($ret === 0); 01348 } else { 01349 // we use a pure PHP unzip 01350 $unzip = new em_unzip($file); 01351 $ret = $unzip->extract(array('add_path'=>$path)); 01352 return (is_array($ret)); 01353 } 01354 } 01355 01356 01357 01358 /********************************* 01359 * 01360 * Command Applications (triggered by GET var) 01361 * 01362 *********************************/ 01363 01371 function importExtInfo($extKey, $version='') { 01372 01373 // "Go back" link 01374 $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>'; 01375 $this->content.= $this->doc->section('',$content); 01376 $content = ''; 01377 01378 // Fetch remote data: 01379 $this->xmlhandler->searchExtensionsXML($extKey, '', '', true, true); 01380 list($fetchData,) = $this->prepareImportExtList(true); 01381 01382 $versions = array_keys($fetchData[$extKey]['versions']); 01383 $version = ($version == '') ? end($versions) : $version; 01384 01385 $opt = array(); 01386 foreach(array_keys($fetchData[$extKey]['versions']) as $ver) { 01387 $opt[]='<option value="'.$ver.'"'.(($version == $ver) ? ' selected="selected"' : '').'>'.$ver.'</option>'; 01388 } 01389 01390 // "Select version" box: 01391 $onClick = 'window.location.href=\'index.php?CMD[importExtInfo]='.$extKey.'&CMD[extVersion]=\'+document.pageform.extVersion.options[document.pageform.extVersion.selectedIndex].value; return false;'; 01392 $select='<select name="extVersion">'.implode('',$opt).'</select> <input type="submit" value="Load details" onclick="'.htmlspecialchars($onClick).'" /> or<br /><br />'; 01393 01394 if ($this->importAtAll()) { 01395 $onClick = ' 01396 window.location.href=\'index.php?CMD[importExt]='.$extKey.'\' 01397 +\'&CMD[extVersion]=\'+document.pageform.extVersion.options[document.pageform.extVersion.selectedIndex].value 01398 +\'&CMD[loc]=\'+document.pageform.loc.options[document.pageform.loc.selectedIndex].value; 01399 return false;'; 01400 $select.=' 01401 <input type="submit" value="Import/Update" onclick="'.htmlspecialchars($onClick).'"> to: 01402 <select name="loc">'. 01403 ($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>':''). 01404 ($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>':''). 01405 ($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>':''). 01406 '</select>'; 01407 } else $select.= $this->noImportMsg(); 01408 $content.= $select; 01409 $this->content.= $this->doc->section('Select command',$content,0,1); 01410 01411 // Details: 01412 $eInfo = $fetchData[$extKey]['versions'][$version]; 01413 $content='<strong>'.$fetchData[$extKey]['_ICON'].' '.$eInfo['EM_CONF']['title'].' ('.$extKey.', '.$version.')</strong><br /><br />'; 01414 $content.=$this->extInformationArray($extKey,$eInfo,1); 01415 $this->content.=$this->doc->spacer(10); 01416 $this->content.=$this->doc->section('Remote Extension Details',$content,0,1); 01417 } 01418 01427 function fetchMetaData($metaType) { 01428 global $TYPO3_CONF_VARS; 01429 01430 switch($metaType) { 01431 case 'mirrors': 01432 $mfile = t3lib_div::tempnam('mirrors'); 01433 $mirrorsFile = t3lib_div::getURL($this->MOD_SETTINGS['mirrorListURL']); 01434 if($mirrorsFile===false) { 01435 t3lib_div::unlink_tempfile($mfile); 01436 $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>'; 01437 } else { 01438 t3lib_div::writeFile($mfile, $mirrorsFile); 01439 $mirrors = implode('',gzfile($mfile)); 01440 t3lib_div::unlink_tempfile($mfile); 01441 01442 $mirrors = $this->xmlhandler->parseMirrorsXML($mirrors); 01443 if(is_array($mirrors) && count($mirrors)) { 01444 t3lib_BEfunc::getModuleData($this->MOD_MENU, array('extMirrors' => serialize($mirrors)), $this->MCONF['name'], '', 'extMirrors'); 01445 $this->MOD_SETTINGS['extMirrors'] = serialize($mirrors); 01446 $content = '<p>The mirror list has been updated and now contains '.count($mirrors).' entries.</p>'; 01447 } 01448 else { 01449 $content = '<p>'.$mirrors.'<br />The mirror list was not updated as it contained no entries.</p>'; 01450 } 01451 } 01452 break; 01453 case 'extensions': 01454 $this->fetchMetaData('mirrors'); // if we fetch the extensions anyway, we can as well keep this up-to-date 01455 01456 $mirror = $this->getMirrorURL(); 01457 $extfile = $mirror.'extensions.xml.gz'; 01458 $extmd5 = t3lib_div::getURL($mirror.'extensions.md5'); 01459 if(is_file(PATH_site.'typo3temp/extensions.xml.gz')) $localmd5 = md5_file(PATH_site.'typo3temp/extensions.xml.gz'); 01460 01461 if($extmd5 === false) { 01462 $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>'; 01463 } elseif($extmd5 == $localmd5) { 01464 $content .= '<p>The extension list has not changed remotely, it has thus not been fetched.</p>'; 01465 } else { 01466 $extXML = t3lib_div::getURL($extfile); 01467 if($extXML === false) { 01468 $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>'; 01469 } else { 01470 t3lib_div::writeFile(PATH_site.'typo3temp/extensions.xml.gz', $extXML); 01471 $content .= $this->xmlhandler->parseExtensionsXML(PATH_site.'typo3temp/extensions.xml.gz'); 01472 } 01473 } 01474 break; 01475 } 01476 01477 return $content; 01478 } 01479 01485 function getMirrorURL() { 01486 if(strlen($this->MOD_SETTINGS['rep_url'])) return $this->MOD_SETTINGS['rep_url']; 01487 01488 $mirrors = unserialize($this->MOD_SETTINGS['extMirrors']); 01489 if(!is_array($mirrors)) { 01490 $this->fetchMetaData('mirrors'); 01491 $mirrors = unserialize($this->MOD_SETTINGS['extMirrors']); 01492 if(!is_array($mirrors)) return false; 01493 } 01494 if($this->MOD_SETTINGS['selectedMirror']=='') { 01495 srand((float) microtime() * 10000000); // not needed after PHP 4.2.0... 01496 $rand = array_rand($mirrors); 01497 $url = 'http://'.$mirrors[$rand]['host'].$mirrors[$rand]['path']; 01498 } 01499 else { 01500 $url = 'http://'.$mirrors[$this->MOD_SETTINGS['selectedMirror']]['host'].$mirrors[$this->MOD_SETTINGS['selectedMirror']]['path']; 01501 } 01502 01503 return $url; 01504 } 01505 01506 01507 01523 function installExtension($extKey, $version=null, $mode=EM_INSTALL_VERSION_MIN) { 01524 list($inst_list,) = $this->getInstalledExtensions(); 01525 01526 // check if it is already installed and loaded with sufficient version 01527 if(isset($inst_list[$extKey])) { 01528 $currentVersion = $inst_list[$extKey]['EM_CONF']['version']; 01529 01530 if(t3lib_extMgm::isLoaded($extKey)) { 01531 if($version===null) { 01532 return array(true, 'Extension already installed and loaded.'); 01533 } else { 01534 switch($mode) { 01535 case EM_INSTALL_VERSION_STRICT: 01536 if ($currentVersion == $version) { 01537 return array(true, 'Extension already installed and loaded.'); 01538 } 01539 break; 01540 case EM_INSTALL_VERSION_MIN: 01541 if (version_compare($currentVersion, $version, '>=')) { 01542 return array(true, 'Extension already installed and loaded.'); 01543 } 01544 break; 01545 case EM_INSTALL_VERSION_MAX: 01546 if (version_compare($currentVersion, $version, '<=')) { 01547 return array(true, 'Extension already installed and loaded.'); 01548 } 01549 break; 01550 } 01551 } 01552 } else { 01553 if (!t3lib_extMgm::isLocalconfWritable()) { 01554 return array(false, 'localconf.php is not writable!'); 01555 } 01556 $newExtList = -1; 01557 switch($mode) { 01558 case EM_INSTALL_VERSION_STRICT: 01559 if ($currentVersion == $version) { 01560 $newExtList = $this->addExtToList($extKey, $inst_list); 01561 } 01562 break; 01563 case EM_INSTALL_VERSION_MIN: 01564 if (version_compare($currentVersion, $version, '>=')) { 01565 $newExtList = $this->addExtToList($extKey, $inst_list); 01566 } 01567 break; 01568 case EM_INSTALL_VERSION_MAX: 01569 if (version_compare($currentVersion, $version, '<=')) { 01570 $newExtList = $this->addExtToList($extKey, $inst_list); 01571 } 01572 break; 01573 } 01574 if ($newExtList!=-1) { 01575 $this->writeNewExtensionList($newExtList); 01576 $this->refreshGlobalExtList(); 01577 $this->forceDBupdates($extKey, $inst_list[$extKey]); 01578 return array(true, 'Extension was already installed, it has been loaded.'); 01579 } 01580 } 01581 } 01582 01583 // at this point we know we need to import (a matching version of) the extension from TER2 01584 01585 // see if we have an extensionlist at all 01586 if (!$this->xmlhandler->countExtensions()) { 01587 $this->fetchMetaData('extensions'); 01588 } 01589 $this->xmlhandler->searchExtensionsXML($extKey, '', '', true); 01590 01591 // check if extension can be fetched 01592 if(isset($this->xmlhandler->extensionsXML[$extKey])) { 01593 $versions = array_keys($this->xmlhandler->extensionsXML[$extKey]['versions']); 01594 $latestVersion = end($versions); 01595 switch($mode) { 01596 case EM_INSTALL_VERSION_STRICT: 01597 if(!isset($this->xmlhandler->extensionsXML[$extKey]['versions'][$version])) { 01598 return array(false, 'Extension not available in matching version'); 01599 } 01600 break; 01601 case EM_INSTALL_VERSION_MIN: 01602 if (version_compare($latestVersion, $version, '>=')) { 01603 $version = $latestVersion; 01604 } else { 01605 return array(false, 'Extension not available in matching version'); 01606 } 01607 break; 01608 case EM_INSTALL_VERSION_MAX: 01609 while (($v = array_pop($versions)) && version_compare($v, $version, '>=')) { 01610 // Loop until a version is found 01611 } 01612 01613 if ($v !== null && version_compare($v, $version, '<=')) { 01614 $version = $v; 01615 } else { 01616 return array(false, 'Extension not available in matching version'); 01617 } 01618 break; 01619 } 01620 $this->importExtFromRep($extKey, $version, 'L'); 01621 $newExtList = $this->addExtToList($extKey, $inst_list); 01622 if ($newExtList!=-1) { 01623 $this->writeNewExtensionList($newExtList); 01624 $this->refreshGlobalExtList(); 01625 $this->forceDBupdates($extKey, $inst_list[$extKey]); 01626 $this->installTranslationsForExtension($extKey, $this->getMirrorURL()); 01627 return array(true, 'Extension has been imported from repository and loaded.'); 01628 } else { 01629 return array(false, 'Extension is in repository, but could not be loaded.'); 01630 } 01631 } else { 01632 return array(false, 'Extension not available in repository'); 01633 } 01634 } 01635 01636 function refreshGlobalExtList() { 01637 global $TYPO3_LOADED_EXT; 01638 01639 $TYPO3_LOADED_EXT = t3lib_extMgm::typo3_loadExtensions(); 01640 if ($TYPO3_LOADED_EXT['_CACHEFILE']) { 01641 require(PATH_typo3conf.$TYPO3_LOADED_EXT['_CACHEFILE'].'_ext_localconf.php'); 01642 } 01643 return; 01644 01645 $GLOBALS['TYPO3_LOADED_EXT'] = t3lib_extMgm::typo3_loadExtensions(); 01646 if ($TYPO3_LOADED_EXT['_CACHEFILE']) { 01647 require(PATH_typo3conf.$TYPO3_LOADED_EXT['_CACHEFILE'].'_ext_localconf.php'); 01648 } else { 01649 $temp_TYPO3_LOADED_EXT = $TYPO3_LOADED_EXT; 01650 reset($temp_TYPO3_LOADED_EXT); 01651 while(list($_EXTKEY,$temp_lEDat)=each($temp_TYPO3_LOADED_EXT)) { 01652 if (is_array($temp_lEDat) && $temp_lEDat['ext_localconf.php']) { 01653 $_EXTCONF = $TYPO3_CONF_VARS['EXT']['extConf'][$_EXTKEY]; 01654 require($temp_lEDat['ext_localconf.php']); 01655 } 01656 } 01657 } 01658 } 01659 01660 01673 function importExtFromRep($extKey,$version,$loc,$uploadFlag=0,$dontDelete=0,$directInput='') { 01674 01675 $uploadSucceed = false; 01676 $uploadedTempFile = ''; 01677 if (is_array($directInput)) { 01678 $fetchData = array($directInput,''); 01679 $loc = ($loc==='G'||$loc==='S') ? $loc : 'L'; 01680 } elseif ($uploadFlag) { 01681 if (($uploadedTempFile = $this->CMD['alreadyUploaded']) || $_FILES['upload_ext_file']['tmp_name']) { 01682 01683 // Read uploaded file: 01684 if (!$uploadedTempFile) { 01685 if (!is_uploaded_file($_FILES['upload_ext_file']['tmp_name'])) { 01686 t3lib_div::sysLog('Possible file upload attack: '.$_FILES['upload_ext_file']['tmp_name'], 'Extension Manager', 3); 01687 01688 return 'File was not uploaded?!?'; 01689 } 01690 01691 $uploadedTempFile = t3lib_div::upload_to_tempfile($_FILES['upload_ext_file']['tmp_name']); 01692 } 01693 $fileContent = t3lib_div::getUrl($uploadedTempFile); 01694 01695 if (!$fileContent) return 'File is empty!'; 01696 01697 // Decode file data: 01698 $fetchData = $this->terConnection->decodeExchangeData($fileContent); 01699 01700 if (is_array($fetchData)) { 01701 $extKey = $fetchData[0]['extKey']; 01702 if ($extKey) { 01703 if (!$this->CMD['uploadOverwrite']) { 01704 $loc = ($loc==='G'||$loc==='S') ? $loc : 'L'; 01705 $comingExtPath = PATH_site.$this->typePaths[$loc].$extKey.'/'; 01706 if (@is_dir($comingExtPath)) { 01707 return 'Extension was already present in "'.$comingExtPath.'" - and the overwrite flag was not set! So nothing done...'; 01708 } // ... else go on, install... 01709 } // ... else go on, install... 01710 } else return 'No extension key in file. Strange...'; 01711 } else return 'Wrong file format. No data recognized, '.$fetchData; 01712 } else return 'No file uploaded! Probably the file was too large for PHPs internal limit for uploadable files.'; 01713 } else { 01714 $this->xmlhandler->searchExtensionsXML($extKey, '', '', true); 01715 01716 // Fetch extension from TER: 01717 if(!strlen($version)) { 01718 $versions = array_keys($this->xmlhandler->extensionsXML[$extKey]['versions']); 01719 $version = end($versions); 01720 } 01721 $fetchData = $this->terConnection->fetchExtension($extKey, $version, $this->xmlhandler->extensionsXML[$extKey]['versions'][$version]['t3xfilemd5'], $this->getMirrorURL()); 01722 } 01723 01724 // At this point the extension data should be present; so we want to write it to disc: 01725 if ($this->importAsType($loc)) { 01726 if (is_array($fetchData)) { // There was some data successfully transferred 01727 if ($fetchData[0]['extKey'] && is_array($fetchData[0]['FILES'])) { 01728 $extKey = $fetchData[0]['extKey']; 01729 if(!isset($fetchData[0]['EM_CONF']['constraints'])) $fetchData[0]['EM_CONF']['constraints'] = $this->xmlhandler->extensionsXML[$extKey]['versions'][$version]['dependencies']; 01730 $EM_CONF = $this->fixEMCONF($fetchData[0]['EM_CONF']); 01731 if (!$EM_CONF['lockType'] || !strcmp($EM_CONF['lockType'],$loc)) { 01732 // check dependencies, act accordingly if ext is loaded 01733 list($instExtInfo,)=$this->getInstalledExtensions(); 01734 $depStatus = $this->checkDependencies($extKey, $EM_CONF, $instExtInfo); 01735 if(t3lib_extMgm::isLoaded($extKey) && !$depStatus['returnCode']) { 01736 $this->content .= $depStatus['html']; 01737 if ($uploadedTempFile) { 01738 $this->content .= '<input type="hidden" name="CMD[alreadyUploaded]" value="'.$uploadedTempFile.'" />'; 01739 } 01740 } else { 01741 $res = $this->clearAndMakeExtensionDir($fetchData[0],$loc,$dontDelete); 01742 if (is_array($res)) { 01743 $extDirPath = trim($res[0]); 01744 if ($extDirPath && @is_dir($extDirPath) && substr($extDirPath,-1)=='/') { 01745 01746 $emConfFile = $this->construct_ext_emconf_file($extKey,$EM_CONF); 01747 $dirs = $this->extractDirsFromFileList(array_keys($fetchData[0]['FILES'])); 01748 01749 $res = $this->createDirsInPath($dirs,$extDirPath); 01750 if (!$res) { 01751 $writeFiles = $fetchData[0]['FILES']; 01752 $writeFiles['ext_emconf.php']['content'] = $emConfFile; 01753 $writeFiles['ext_emconf.php']['content_md5'] = md5($emConfFile); 01754 01755 // Write files: 01756 foreach($writeFiles as $theFile => $fileData) { 01757 t3lib_div::writeFile($extDirPath.$theFile,$fileData['content']); 01758 if (!@is_file($extDirPath.$theFile)) { 01759 $content.='Error: File "'.$extDirPath.$theFile.'" could not be created!!!<br />'; 01760 } elseif (md5(t3lib_div::getUrl($extDirPath.$theFile)) != $fileData['content_md5']) { 01761 $content.='Error: File "'.$extDirPath.$theFile.'" MD5 was different from the original files MD5 - so the file is corrupted!<br />'; 01762 } 01763 } 01764 01765 // No content, no errors. Create success output here: 01766 if (!$content) { 01767 $content='SUCCESS: '.$extDirPath.'<br />'; 01768 01769 $uploadSucceed = true; 01770 01771 // Fix TYPO3_MOD_PATH for backend modules in extension: 01772 $modules = t3lib_div::trimExplode(',',$EM_CONF['module'],1); 01773 if (count($modules)) { 01774 foreach($modules as $mD) { 01775 $confFileName = $extDirPath.$mD.'/conf.php'; 01776 if (@is_file($confFileName)) { 01777 $content.= $this->writeTYPO3_MOD_PATH($confFileName,$loc,$extKey.'/'.$mD.'/').'<br />'; 01778 } else $content.='Error: Couldn\'t find "'.$confFileName.'"<br />'; 01779 } 01780 } 01781 // 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. 01782 // But this order of the code works.... (using the empty Array with type, EMCONF and files hereunder). 01783 01784 // Writing to ext_emconf.php: 01785 $sEMD5A = $this->serverExtensionMD5Array($extKey,array('type' => $loc, 'EM_CONF' => array(), 'files' => array())); 01786 $EM_CONF['_md5_values_when_last_written'] = serialize($sEMD5A); 01787 $emConfFile = $this->construct_ext_emconf_file($extKey,$EM_CONF); 01788 t3lib_div::writeFile($extDirPath.'ext_emconf.php',$emConfFile); 01789 01790 $content.='ext_emconf.php: '.$extDirPath.'ext_emconf.php<br />'; 01791 $content.='Type: '.$loc.'<br />'; 01792 01793 // Remove cache files: 01794 if (t3lib_extMgm::isLoaded($extKey)) { 01795 if ($this->removeCacheFiles()) { 01796 $content.='Cache-files are removed and will be re-written upon next hit<br />'; 01797 } 01798 01799 list($new_list)=$this->getInstalledExtensions(); 01800 $content.=$this->updatesForm($extKey,$new_list[$extKey],1,'index.php?CMD[showExt]='.$extKey.'&SET[singleDetails]=info'); 01801 } 01802 01803 // Install / Uninstall: 01804 if(!$this->CMD['standAlone']) { 01805 $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; 01806 $content.='<h3>Install / Uninstall Extension:</h3>'; 01807 $content.= $new_list[$extKey] ? 01808 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->removeButton().' Uninstall extension</a>' : 01809 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[load]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->installButton().' Install extension</a>'; 01810 } else { 01811 $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>'; 01812 } 01813 01814 } 01815 } else $content = $res; 01816 } else $content = 'Error: The extension path "'.$extDirPath.'" was different than expected...'; 01817 } else $content = $res; 01818 } 01819 } else $content = 'Error: The extension can only be installed in the path '.$this->typePaths[$EM_CONF['lockType']].' (lockType='.$EM_CONF['lockType'].')'; 01820 } else $content = 'Error: No extension key!!! Why? - nobody knows... (Or no files in the file-array...)'; 01821 } else $content = 'Error: The datatransfer did not succeed. '.$fetchData; 01822 } else $content = 'Error: Installation is not allowed in this path ('.$this->typePaths[$loc].')'; 01823 01824 $this->content.=$this->doc->section('Extension import results',$content,0,1); 01825 01826 if ($uploadSucceed && $uploadedTempFile) { 01827 t3lib_div::unlink_tempfile($uploadedTempFile); 01828 } 01829 01830 return false; 01831 } 01832 01839 function showExtDetails($extKey) { 01840 global $TYPO3_LOADED_EXT; 01841 01842 list($list,)=$this->getInstalledExtensions(); 01843 $absPath = $this->getExtPath($extKey,$list[$extKey]['type']); 01844 01845 // Check updateModule: 01846 if (@is_file($absPath.'class.ext_update.php')) { 01847 require_once($absPath.'class.ext_update.php'); 01848 $updateObj = new ext_update; 01849 if (!$updateObj->access()) { 01850 unset($this->MOD_MENU['singleDetails']['updateModule']); 01851 } 01852 } else { 01853 unset($this->MOD_MENU['singleDetails']['updateModule']); 01854 } 01855 01856 if($this->CMD['doDelete']) { 01857 $this->MOD_MENU['singleDetails'] = array(); 01858 } 01859 01860 // Function menu here: 01861 if(!$this->CMD['standAlone'] && !t3lib_div::_GP('standAlone')) { 01862 $content = ' 01863 <table border="0" cellpadding="0" cellspacing="0" width="100%"> 01864 <tr> 01865 <td nowrap="nowrap">Extension: <strong>'.$this->extensionTitleIconHeader($extKey,$list[$extKey]).'</strong> ('.$extKey.')</td> 01866 <td align="right" nowrap="nowrap">'. 01867 t3lib_BEfunc::getFuncMenu(0,'SET[singleDetails]',$this->MOD_SETTINGS['singleDetails'],$this->MOD_MENU['singleDetails'],'','&CMD[showExt]='.$extKey).' '. 01868 '<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> 01869 </tr> 01870 </table>'; 01871 $this->content.=$this->doc->section('',$content); 01872 } 01873 01874 // Show extension details: 01875 if ($list[$extKey]) { 01876 01877 // Checking if a command for install/uninstall is executed: 01878 if (($this->CMD['remove'] || $this->CMD['load']) && !in_array($extKey,$this->requiredExt)) { 01879 01880 // Install / Uninstall extension here: 01881 if (t3lib_extMgm::isLocalconfWritable()) { 01882 // Check dependencies: 01883 $depStatus = $this->checkDependencies($extKey, $list[$extKey]['EM_CONF'], $list); 01884 if(!$this->CMD['remove'] && !$depStatus['returnCode']) { 01885 $this->content .= $depStatus['html']; 01886 $newExtList = -1; 01887 } elseif ($this->CMD['remove']) { 01888 $newExtList = $this->removeExtFromList($extKey,$list); 01889 } else { 01890 $newExtList = $this->addExtToList($extKey,$list); 01891 } 01892 01893 // Success-installation: 01894 if ($newExtList!=-1) { 01895 $updates = ''; 01896 if ($this->CMD['load']) { 01897 if($_SERVER['REQUEST_METHOD'] == 'POST') { 01898 $script = t3lib_div::linkThisScript(array('CMD[showExt]' => $extKey, 'CMD[load]' => 1, 'CMD[clrCmd]' => $this->CMD['clrCmd'], 'SET[singleDetails]' => 'info')); 01899 } else { 01900 $script = ''; 01901 } 01902 $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'].'" />'); 01903 if ($updates) { 01904 $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; 01905 if($this->CMD['standAlone']) $updates .= '<input type="hidden" name="standAlone" value="1" />'; 01906 $depsolver = t3lib_div::_POST('depsolver'); 01907 if(is_array($depsolver['ignore'])) { 01908 foreach($depsolver['ignore'] as $depK => $depV) { 01909 $updates .= '<input type="hidden" name="depsolver[ignore]['.$depK.']" value="1" />'; 01910 } 01911 } 01912 01913 $this->content.=$this->doc->section('Installing '.$this->extensionTitleIconHeader($extKey,$list[$extKey]).strtoupper(': Database needs to be updated'),$updates,1,1,1,1); 01914 } 01915 } elseif ($this->CMD['remove']) { 01916 $updates.= $this->checkClearCache($list[$extKey]); 01917 if ($updates) { 01918 $updates = ' 01919 </form><form action="'.t3lib_div::linkThisScript().'" method="post">'.$updates.' 01920 <br /><input type="submit" name="write" value="Remove extension" /> 01921 <input type="hidden" name="_do_install" value="1" /> 01922 <input type="hidden" name="_clrCmd" value="'.$this->CMD['clrCmd'].'" /> 01923 <input type="hidden" name="standAlone" value="'.$this->CMD['standAlone'].'" /> 01924 '; 01925 $this->content.=$this->doc->section('Removing '.$this->extensionTitleIconHeader($extKey,$list[$extKey]).strtoupper(': Database needs to be updated'),$updates,1,1,1,1); 01926 } 01927 } 01928 if (!$updates || t3lib_div::_GP('_do_install')) { 01929 $this->writeNewExtensionList($newExtList); 01930 $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'))); 01931 if ($this->CMD['clrCmd'] || t3lib_div::_GP('_clrCmd')) { 01932 $vA = array('CMD'=>''); 01933 } else { 01934 $vA = array('CMD'=>Array('showExt'=>$extKey)); 01935 } 01936 if($this->CMD['standAlone'] || t3lib_div::_GP('standAlone')) { 01937 $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>'; 01938 } else { 01939 header('Location: '.t3lib_div::linkThisScript($vA)); 01940 } 01941 } 01942 } 01943 } else { 01944 $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); 01945 } 01946 01947 } elseif ($this->CMD['downloadFile'] && !in_array($extKey,$this->requiredExt)) { 01948 01949 // Link for downloading extension has been clicked - deliver content stream: 01950 $dlFile = $this->CMD['downloadFile']; 01951 if (t3lib_div::isFirstPartOfStr($dlFile,PATH_site) && t3lib_div::isFirstPartOfStr($dlFile,$absPath) && @is_file($dlFile)) { 01952 $mimeType = 'application/octet-stream'; 01953 Header('Content-Type: '.$mimeType); 01954 Header('Content-Disposition: attachment; filename='.basename($dlFile)); 01955 echo t3lib_div::getUrl($dlFile); 01956 exit; 01957 } else die('Error while trying to download extension file...'); 01958 01959 } elseif ($this->CMD['editFile'] && !in_array($extKey,$this->requiredExt)) { 01960 01961 // Editing extension file: 01962 $editFile = $this->CMD['editFile']; 01963 if (t3lib_div::isFirstPartOfStr($editFile,PATH_site) && t3lib_div::isFirstPartOfStr($editFile,$absPath)) { // Paranoia... 01964 01965 $fI = t3lib_div::split_fileref($editFile); 01966 if (@is_file($editFile) && t3lib_div::inList($this->editTextExtensions,($fI['fileext']?$fI['fileext']:$fI['filebody']))) { 01967 if (filesize($editFile)<($this->kbMax*1024)) { 01968 $outCode = ''; 01969 $info = ''; 01970 $submittedContent = t3lib_div::_POST('edit'); 01971 $saveFlag = 0; 01972 01973 if(isset($submittedContent['file']) && !$GLOBALS['TYPO3_CONF_VARS']['EXT']['noEdit']) { // Check referer here? 01974 $oldFileContent = t3lib_div::getUrl($editFile); 01975 if($oldFileContent != $submittedContent['file']) { 01976 $oldMD5 = md5(str_replace(chr(13),'',$oldFileContent)); 01977 $info.= 'MD5: <b>'.$oldMD5.'</b> (Previous File)<br />'; 01978 t3lib_div::writeFile($editFile,$submittedContent['file']); 01979 $saveFlag = 1; 01980 } else { 01981 $info .= 'No changes to the file detected!<br />'; 01982 } 01983 } 01984 01985 $fileContent = t3lib_div::getUrl($editFile); 01986 01987 $outCode.= 'File: <b>'.substr($editFile,strlen($absPath)).'</b> ('.t3lib_div::formatSize(filesize($editFile)).')<br />'; 01988 $fileMD5 = md5(str_replace(chr(13),'',$fileContent)); 01989 $info.= 'MD5: <b>'.$fileMD5.'</b> (Current File)<br />'; 01990 if($saveFlag) { 01991 $saveMD5 = md5(str_replace(chr(13),'',$submittedContent['file'])); 01992 $info.= 'MD5: <b>'.$saveMD5.'</b> (Submitted)<br />'; 01993 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 />'; 01994 else $info.= $GLOBALS['TBE_TEMPLATE']->rfw('<br /><strong>File saved.</strong>').'<br />'; 01995 } 01996 01997 $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>'; 01998 $outCode.= '<input type="hidden" name="edit[filename]" value="'.$editFile.'" />'; 01999 $outCode.= '<input type="hidden" name="CMD[editFile]" value="'.htmlspecialchars($editFile).'" />'; 02000 $outCode.= '<input type="hidden" name="CMD[showExt]" value="'.$extKey.'" />'; 02001 $outCode.= $info; 02002 02003 if (!$GLOBALS['TYPO3_CONF_VARS']['EXT']['noEdit']) { 02004 $outCode.='<br /><input type="submit" name="save_file" value="Save file" />'; 02005 } else $outCode.=$GLOBALS['TBE_TEMPLATE']->rfw('<br />[SAVING IS DISABLED - can be enabled by the $TYPO3_CONF_VARS[\'EXT\'][\'noEdit\']-flag] '); 02006 02007 $onClick = 'window.location.href=\'index.php?CMD[showExt]='.$extKey.'\';return false;'; 02008 $outCode.='<input type="submit" name="cancel" value="Cancel" onclick="'.htmlspecialchars($onClick).'" />'; 02009 02010 $theOutput.=$this->doc->spacer(15); 02011 $theOutput.=$this->doc->section('Edit file:','',0,1); 02012 $theOutput.=$this->doc->sectionEnd().$outCode; 02013 $this->content.=$theOutput; 02014 } else { 02015 $theOutput.=$this->doc->spacer(15); 02016 $theOutput.=$this->doc->section('Filesize exceeded '.$this->kbMax.' Kbytes','Files larger than '.$this->kbMax.' KBytes are not allowed to be edited.'); 02017 } 02018 } 02019 } else die('Fatal Edit error: File "'.$editFile.'" was not inside the correct path of the TYPO3 Extension!'); 02020 } else { 02021 02022 // MAIN: 02023 switch((string)$this->MOD_SETTINGS['singleDetails']) { 02024 case 'info': 02025 // Loaded / Not loaded: 02026 if (!in_array($extKey,$this->requiredExt)) { 02027 if ($TYPO3_LOADED_EXT[$extKey]) { 02028 $content = '<strong>The extension is installed (loaded and running)!</strong><br />'. 02029 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1').'">Click here to remove the extension: '.$this->removeButton().'</a>'; 02030 } else { 02031 $content = 'The extension is <strong>not</strong> installed yet.<br />'. 02032 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[load]=1').'">Click here to install the extension: '.$this->installButton().'</a>'; 02033 } 02034 } else { 02035 $content = 'This extension is entered in the TYPO3_CONF_VARS[SYS][requiredExt] list and is therefore always loaded.'; 02036 } 02037 $this->content.=$this->doc->spacer(10); 02038 $this->content.=$this->doc->section('Active status:',$content,0,1); 02039 02040 if (t3lib_extMgm::isLoaded($extKey)) { 02041 $updates=$this->updatesForm($extKey,$list[$extKey]); 02042 if ($updates) { 02043 $this->content.=$this->doc->spacer(10); 02044 $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); 02045 } 02046 } 02047 02048 // Config: 02049 if (@is_file($absPath.'ext_conf_template.txt')) { 02050 $this->content.=$this->doc->spacer(10); 02051 $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); 02052 $this->tsStyleConfigForm($extKey,$list[$extKey]); 02053 } 02054 02055 // Show details: 02056 $content = t3lib_BEfunc::cshItem('_MOD_tools_em', 'info', $GLOBALS['BACK_PATH'],'|<br/>'); 02057 $content.= $this->extInformationArray($extKey,$list[$extKey]); 02058 02059 $this->content.=$this->doc->spacer(10); 02060 $this->content.=$this->doc->section('Details:',$content,0,1); 02061 break; 02062 case 'upload': 02063 $em = t3lib_div::_POST('em'); 02064 if($em['action'] == 'doUpload') { 02065 $em['extKey'] = $extKey; 02066 $em['extInfo'] = $list[$extKey]; 02067 $content = $this->uploadExtensionToTER($em); 02068 $content .= $this->doc->spacer(10); 02069 // Must reload this, because EM_CONF information has been updated! 02070 list($list,)=$this->getInstalledExtensions(); 02071 } else { 02072 // CSH: 02073 $content = t3lib_BEfunc::cshItem('_MOD_tools_em', 'upload', $GLOBALS['BACK_PATH'],'|<br/>'); 02074 02075 // Upload: 02076 if (substr($extKey,0,5)!='user_') { 02077 $content.= $this->getRepositoryUploadForm($extKey,$list[$extKey]); 02078 $eC=0; 02079 } else { 02080 $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.'; 02081 $eC=2; 02082 } 02083 if (!$this->fe_user['username']) { 02084 $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 />'; 02085 } 02086 } 02087 $this->content.=$this->doc->section('Upload extension to repository',$content,0,1,$eC); 02088 break; 02089 case 'backup': 02090 if($this->CMD['doDelete']) { 02091 $content = $this->extDelete($extKey,$list[$extKey]); 02092 $this->content.=$this->doc->section('Delete',$content,0,1); 02093 } else { 02094 $content = t3lib_BEfunc::cshItem('_MOD_tools_em', 'backup_delete', $GLOBALS['BACK_PATH'],'|<br/>'); 02095 $content.= $this->extBackup($extKey,$list[$extKey]); 02096 $this->content.=$this->doc->section('Backup',$content,0,1); 02097 02098 $content = $this->extDelete($extKey,$list[$extKey]); 02099 $this->content.=$this->doc->section('Delete',$content,0,1); 02100 02101 $content = $this->extUpdateEMCONF($extKey,$list[$extKey]); 02102 $this->content.=$this->doc->section('Update EM_CONF',$content,0,1); 02103 } 02104 break; 02105 case 'dump': 02106 $this->extDumpTables($extKey,$list[$extKey]); 02107 break; 02108 case 'edit': 02109 $content = t3lib_BEfunc::cshItem('_MOD_tools_em', 'editfiles', $GLOBALS['BACK_PATH'],'|<br/>'); 02110 $content.= $this->getFileListOfExtension($extKey,$list[$extKey]); 02111 02112 $this->content.=$this->doc->section('Extension files',$content,0,1); 02113 break; 02114 case 'updateModule': 02115 $this->content.=$this->doc->section('Update:',is_object($updateObj) ? $updateObj->main() : 'No update object',0,1); 02116 break; 02117 default: 02118 $this->extObjContent(); 02119 break; 02120 } 02121 } 02122 } 02123 } 02124 02132 function requestInstallExtensions($extList) { 02133 02134 // Return URL: 02135 $returnUrl = t3lib_div::_GP('returnUrl'); 02136 $installOrImportExtension = t3lib_div::_POST('installOrImportExtension'); 02137 02138 // Extension List: 02139 $extArray = explode(',',$extList); 02140 $outputRow = array(); 02141 $outputRow[] = ' 02142 <tr class="bgColor5 tableheader"> 02143 <td>Install/Import:</td> 02144 <td>Extension Key:</td> 02145 </tr> 02146 '; 02147 02148 foreach($extArray as $extKey) { 02149 02150 // Check for the request: 02151 if ($installOrImportExtension[$extKey]) { 02152 $this->installExtension($extKey); 02153 } 02154 02155 // Display: 02156 if (!t3lib_extMgm::isLoaded($extKey)) { 02157 $outputRow[] = ' 02158 <tr class="bgColor4"> 02159 <td><input type="checkbox" name="'.htmlspecialchars('installOrImportExtension['.$extKey.']').'" value="1" checked="checked" id="check_'.$extKey.'" /></td> 02160 <td><label for="check_'.$extKey.'">'.htmlspecialchars($extKey).'</label></td> 02161 </tr> 02162 '; 02163 } 02164 } 02165 02166 if (count($outputRow)>1 || !$returnUrl) { 02167 $content = ' 02168 </form> <!-- ending page form ... --> 02169 <form action="'.htmlspecialchars(t3lib_div::getIndpEnv('REQUEST_URI')).'" method="post"> 02170 <table border="0" cellpadding="1" cellspacing="1">'.implode('',$outputRow).'</table> 02171 <input type="submit" name="_" value="Import and Install selected" /> 02172 </form> 02173 <form> <!-- continuing page form... -->'; 02174 02175 if ($returnUrl) { 02176 $content.= ' 02177 <br/> 02178 <br/> 02179 <a href="'.htmlspecialchars($returnUrl).'">Return</a> 02180 '; 02181 } 02182 02183 $this->content.= $this->doc->section('Import/Install Extensions:',$content,0,1); 02184 } else { 02185 header('Location: '.t3lib_div::locationHeaderUrl($returnUrl)); 02186 } 02187 } 02188 02189 02190 02191 02192 02193 02194 02195 02196 /*********************************** 02197 * 02198 * Application Sub-functions (HTML parts) 02199 * 02200 **********************************/ 02201 02213 function updatesForm($extKey,$extInfo,$notSilent=0,$script='',$addFields='') { 02214 $script = $script ? $script : t3lib_div::linkThisScript(); 02215 $updates.= $this->checkDBupdates($extKey,$extInfo); 02216 $uCache = $this->checkClearCache($extInfo); 02217 if ($notSilent) $updates.= $uCache; 02218 $updates.= $this->checkUploadFolder($extKey,$extInfo); 02219 02220 $absPath = $this->getExtPath($extKey,$extInfo['type']); 02221 if ($notSilent && @is_file($absPath.'ext_conf_template.txt')) { 02222 $cForm = $this->tsStyleConfigForm($extKey,$extInfo,1,$script,$updates.$addFields.'<br />'); 02223 } 02224 02225 if ($updates || $cForm) { 02226 if ($cForm) { 02227 $updates = '</form>'.$cForm.'<form>'; 02228 } else { 02229 $updates = '</form><form action="'.htmlspecialchars($script).'" method="post">'.$updates.$addFields.' 02230 <br /><input type="submit" name="write" value="Make updates" /> 02231 '; 02232 } 02233 } 02234 return $updates; 02235 } 02236 02244 function extDumpTables($extKey,$extInfo) { 02245 02246 // Get dbInfo which holds the structure known from the tables.sql file 02247 $techInfo = $this->makeDetailedExtensionAnalysis($extKey,$extInfo); 02248 $absPath = $this->getExtPath($extKey,$extInfo['type']); 02249 02250 // Static tables: 02251 if (is_array($techInfo['static'])) { 02252 if ($this->CMD['writeSTATICdump']) { // Writing static dump: 02253 $writeFile = $absPath.'ext_tables_static+adt.sql'; 02254 if (@is_file($writeFile)) { 02255 $dump_static = $this->dumpStaticTables(implode(',',$techInfo['static'])); 02256 t3lib_div::writeFile($writeFile,$dump_static); 02257 $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); 02258 } 02259 } else { // Showing info about what tables to dump - and giving the link to execute it. 02260 $msg = 'Dumping table content for static tables:<br />'; 02261 $msg.= '<br />'.implode('<br />',$techInfo['static']).'<br />'; 02262 02263 // ... then feed that to this function which will make new CREATE statements of the same fields but based on the current database content. 02264 $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); 02265 $this->content.=$this->doc->spacer(20); 02266 } 02267 } 02268 02269 // Table and field definitions: 02270 if (is_array($techInfo['dump_tf'])) { 02271 $dump_tf_array = $this->getTableAndFieldStructure($techInfo['dump_tf']); 02272 $dump_tf = $this->dumpTableAndFieldStructure($dump_tf_array); 02273 if ($this->CMD['writeTFdump']) { 02274 $writeFile = $absPath.'ext_tables.sql'; 02275 if (@is_file($writeFile)) { 02276 t3lib_div::writeFile($writeFile,$dump_tf); 02277 $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); 02278 } 02279 } else { 02280 $msg = 'Dumping current database structure for:<br />'; 02281 if (is_array($techInfo['tables'])) { 02282 $msg.= '<br /><strong>Tables:</strong><br />'.implode('<br />',$techInfo['tables']).'<br />'; 02283 } 02284 if (is_array($techInfo['fields'])) { 02285 $msg.= '<br /><strong>Solo-fields:</strong><br />'.implode('<br />',$techInfo['fields']).'<br />'; 02286 } 02287 02288 // ... then feed that to this function which will make new CREATE statements of the same fields but based on the current database content. 02289 $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 /> 02290 <pre>'.htmlspecialchars($dump_tf).'</pre>',0,1); 02291 02292 02293 $details = ' This dump is based on two factors:<br /> 02294 <ul> 02295 <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> 02296 <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> 02297 </ul> 02298 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 />'; 02299 $this->content.=$this->doc->section('',$details); 02300 } 02301 } 02302 } 02303 02311 function getFileListOfExtension($extKey,$conf) { 02312 $content = ''; 02313 $extPath = $this->getExtPath($extKey,$conf['type']); 02314 02315 if ($extPath) { 02316 // Read files: 02317 $fileArr = array(); 02318 $fileArr = t3lib_div::getAllFilesAndFoldersInPath($fileArr,$extPath,'',0,99,$this->excludeForPackaging); 02319 02320 // Start table: 02321 $lines = array(); 02322 $totalSize = 0; 02323 02324 // Header: 02325 $lines[] = ' 02326 <tr class="bgColor5"> 02327 <td>File:</td> 02328 <td>Size:</td> 02329 <td>Edit:</td> 02330 </tr>'; 02331 02332 foreach($fileArr as $file) { 02333 $fI = t3lib_div::split_fileref($file); 02334 $lines[] = ' 02335 <tr class="bgColor4"> 02336 <td><a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[downloadFile]='.rawurlencode($file)).'" title="Download...">'.substr($file,strlen($extPath)).'</a></td> 02337 <td>'.t3lib_div::formatSize(filesize($file)).'</td> 02338 <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> 02339 </tr>'; 02340 $totalSize+=filesize($file); 02341 } 02342 02343 $lines[] = ' 02344 <tr class="bgColor6"> 02345 <td><strong>Total:</strong></td> 02346 <td><strong>'.t3lib_div::formatSize($totalSize).'</strong></td> 02347 <td> </td> 02348 </tr>'; 02349 02350 $content = ' 02351 Path: '.$extPath.'<br /><br /> 02352 <table border="0" cellpadding="1" cellspacing="2">'.implode('',$lines).'</table>'; 02353 } 02354 02355 return $content; 02356 } 02357 02365 function extDelete($extKey,$extInfo) { 02366 $absPath = $this->getExtPath($extKey,$extInfo['type']); 02367 if (t3lib_extMgm::isLoaded($extKey)) { 02368 return 'This extension is currently installed (loaded and active) and so cannot be deleted!'; 02369 } elseif (!$this->deleteAsType($extInfo['type'])) { 02370 return 'You cannot delete (and install/update) extensions in the '.$this->typeLabels[$extInfo['type']].' scope.'; 02371 } elseif (t3lib_div::inList('G,L',$extInfo['type'])) { 02372 if ($this->CMD['doDelete'] && !strcmp($absPath,$this->CMD['absPath'])) { 02373 $res = $this->removeExtDirectory($absPath); 02374 if ($res) { 02375 return 'ERROR: Could not remove extension directory "'.$absPath.'". Had the following errors:<br /><br />'. 02376 nl2br($res); 02377 } else { 02378 return 'Removed extension in path "'.$absPath.'"!'; 02379 } 02380 } else { 02381 $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)."';}"; 02382 $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>'; 02383 $content.= '<br /><br />(Maybe you should make a backup first, see above.)'; 02384 return $content; 02385 } 02386 } else return 'Extension is not a global or local extension and cannot be removed.'; 02387 } 02388 02396 function extUpdateEMCONF($extKey,$extInfo) { 02397 $absPath = $this->getExtPath($extKey,$extInfo['type']); 02398 if ($this->CMD['doUpdateEMCONF']) { 02399 return $this->updateLocalEM_CONF($extKey,$extInfo); 02400 } else { 02401 $onClick = "if (confirm('Are you sure you want to update EM_CONF?')) {window.location.href='index.php?CMD[showExt]=".$extKey."&CMD[doUpdateEMCONF]=1';}"; 02402 $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>'; 02403 $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 /> 02404 Updating this file will first of all reset this registration.'; 02405 return $content; 02406 } 02407 } 02408 02416 function extBackup($extKey,$extInfo) { 02417 $uArr = $this->makeUploadArray($extKey,$extInfo); 02418 if (is_array($uArr)) { 02419 $backUpData = $this->terConnection->makeUploadDataFromArray($uArr); 02420 $filename = 'T3X_'.$extKey.'-'.str_replace('.','_',$extInfo['EM_CONF']['version']).'-z-'.date('YmdHi').'.t3x'; 02421 if (intval($this->CMD['doBackup'])==1) { 02422 header('Content-Type: application/octet-stream'); 02423 header('Content-Disposition: attachment; filename='.$filename); 02424 echo $backUpData; 02425 exit; 02426 } elseif ($this->CMD['dumpTables']) { 02427 $filename='T3X_'.$extKey; 02428 $cTables = count(explode(',',$this->CMD['dumpTables'])); 02429 if ($cTables>1) { 02430 $filename.='-'.$cTables.'tables'; 02431 } else { 02432 $filename.='-'.$this->CMD['dumpTables']; 02433 } 02434 $filename.='+adt.sql'; 02435 02436 header('Content-Type: application/octet-stream'); 02437 header('Content-Disposition: attachment; filename='.$filename); 02438 echo $this->dumpStaticTables($this->CMD['dumpTables']); 02439 exit; 02440 } else { 02441 $techInfo = $this->makeDetailedExtensionAnalysis($extKey,$extInfo); 02442 $lines=array(); 02443 $lines[]='<tr class="bgColor5"><td colspan="2"><strong>Make selection:</strong></td></tr>'; 02444 $lines[]='<tr class="bgColor4"><td><strong>Extension files:</strong></td><td>'. 02445 '<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>'; 02446 02447 if (is_array($techInfo['tables'])) { $lines[]='<tr class="bgColor4"><td><strong>Data tables:</strong></td><td>'.$this->extBackup_dumpDataTablesLine($techInfo['tables'],$extKey).'</td></tr>'; } 02448 if (is_array($techInfo['static'])) { $lines[]='<tr class="bgColor4"><td><strong>Static tables:</strong></td><td>'.$this->extBackup_dumpDataTablesLine($techInfo['static'],$extKey).'</td></tr>'; } 02449 02450 $content = '<table border="0" cellpadding="2" cellspacing="2">'.implode('',$lines).'</table>'; 02451 return $content; 02452 } 02453 } else die('Error...'); 02454 } 02455 02463 function extBackup_dumpDataTablesLine($tablesArray,$extKey) { 02464 $tables = array(); 02465 $tablesNA = array(); 02466 02467 foreach($tablesArray as $tN) { 02468 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('count(*)', $tN, ''); 02469 if (!$GLOBALS['TYPO3_DB']->sql_error()) { 02470 $row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res); 02471 $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>'; 02472 } else { 02473 $tablesNA[$tN]='<tr><td> </td><td>'.$tN.'</td><td> </td><td>Did not exist.</td></tr>'; 02474 } 02475 } 02476 $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... 02477 if (count($tables)) { 02478 $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; 02479 } else $label = 'Nothing to dump...<br /><br />'.$label; 02480 return $label; 02481 } 02482 02491 function extInformationArray($extKey,$extInfo,$remote=0) { 02492 $lines=array(); 02493 $lines[]='<tr class="bgColor5"><td colspan="2"><strong>General information:</strong></td>'.$this->helpCol('').'</tr>'; 02494 $lines[]='<tr class="bgColor4"><td>Title:</td><td>'.$extInfo['EM_CONF']['_icon'].$extInfo['EM_CONF']['title'].'</td>'.$this->helpCol('title').'</tr>'; 02495 $lines[]='<tr class="bgColor4"><td>Description:</td><td>'.nl2br(htmlspecialchars($extInfo['EM_CONF']['description'])).'</td>'.$this->helpCol('description').'</tr>'; 02496 $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']:''). 02497 '</td>'.$this->helpCol('description').'</tr>'; 02498 02499 $lines[]='<tr class="bgColor4"><td>Version:</td><td>'.$extInfo['EM_CONF']['version'].'</td>'.$this->helpCol('version').'</tr>'; 02500 $lines[]='<tr class="bgColor4"><td>Category:</td><td>'.$this->categories[$extInfo['EM_CONF']['category']].'</td>'.$this->helpCol('category').'</tr>'; 02501 $lines[]='<tr class="bgColor4"><td>State:</td><td>'.$this->states[$extInfo['EM_CONF']['state']].'</td>'.$this->helpCol('state').'</tr>'; 02502 $lines[]='<tr class="bgColor4"><td>Shy?</td><td>'.($extInfo['EM_CONF']['shy']?'Yes':'').'</td>'.$this->helpCol('shy').'</tr>'; 02503 $lines[]='<tr class="bgColor4"><td>Internal?</td><td>'.($extInfo['EM_CONF']['internal']?'Yes':'').'</td>'.$this->helpCol('internal').'</tr>'; 02504 02505 $lines[]='<tr class="bgColor4"><td>Depends on:</td><td>'.$this->depToString($extInfo['EM_CONF']['constraints']).'</td>'.$this->helpCol('dependencies').'</tr>'; 02506 $lines[]='<tr class="bgColor4"><td>Conflicts with:</td><td>'.$this->depToString($extInfo['EM_CONF']['constraints'],'conflicts').'</td>'.$this->helpCol('dependencies').'</tr>'; 02507 $lines[]='<tr class="bgColor4"><td>Suggests:</td><td>'.$this->depToString($extInfo['EM_CONF']['constraints'],'suggests').'</td>'.$this->helpCol('dependencies').'</tr>'; 02508 if (!$remote) { 02509 $lines[]='<tr class="bgColor4"><td>Priority:</td><td>'.$extInfo['EM_CONF']['priority'].'</td>'.$this->helpCol('priority').'</tr>'; 02510 $lines[]='<tr class="bgColor4"><td>Clear cache?</td><td>'.($extInfo['EM_CONF']['clearCacheOnLoad']?'Yes':'').'</td>'.$this->helpCol('clearCacheOnLoad').'</tr>'; 02511 $lines[]='<tr class="bgColor4"><td>Includes modules:</td><td>'.$extInfo['EM_CONF']['module'].'</td>'.$this->helpCol('module').'</tr>'; 02512 $lines[]='<tr class="bgColor4"><td>Lock Type?</td><td>'.($extInfo['EM_CONF']['lockType']?$extInfo['EM_CONF']['lockType']:'').'</td>'.$this->helpCol('lockType').'</tr>'; 02513 $lines[]='<tr class="bgColor4"><td>Modifies tables:</td><td>'.$extInfo['EM_CONF']['modify_tables'].'</td>'.$this->helpCol('modify_tables').'</tr>'; 02514 02515 // Installation status: 02516 $techInfo = $this->makeDetailedExtensionAnalysis($extKey,$extInfo,1); 02517 $lines[]='<tr><td> </td><td></td>'.$this->helpCol('').'</tr>'; 02518 $lines[]='<tr class="bgColor5"><td colspan="2"><strong>Installation status:</strong></td>'.$this->helpCol('').'</tr>'; 02519 $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>'; 02520 $lines[]='<tr class="bgColor4"><td>Double installs?</td><td>'.$this->extInformationArray_dbInst($extInfo['doubleInstall'],$extInfo['type']).'</td>'.$this->helpCol('doubleInstall').'</tr>'; 02521 if (is_array($extInfo['files'])) { 02522 sort($extInfo['files']); 02523 $lines[]='<tr class="bgColor4"><td>Root files:</td><td>'.implode('<br />',$extInfo['files']).'</td>'.$this->helpCol('rootfiles').'</tr>'; 02524 } 02525 02526 if ($techInfo['tables']||$techInfo['static']||$techInfo['fields']) { 02527 if (!$remote && t3lib_extMgm::isLoaded($extKey)) { 02528 $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!':''). 02529 ($techInfo['static_error']?'<strong>Static table error!</strong><br />The static tables are missing or empty!':'')); 02530 } else { 02531 $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!'; 02532 } 02533 } 02534 02535 $lines[]='<tr class="bgColor4"><td>Database requirements:</td><td>'.$this->extInformationArray_dbReq($techInfo,1).'</td>'.$this->helpCol('dbReq').'</tr>'; 02536 $lines[]='<tr class="bgColor4"><td>Database status:</td><td>'.$tableStatus.'</td>'.$this->helpCol('dbStatus').'</tr>'; 02537 $lines[]='<tr class="bgColor4"><td>Flags:</td><td>'.(is_array($techInfo['flags'])?implode('<br />',$techInfo['flags']):'').'</td>'.$this->helpCol('flags').'</tr>'; 02538 $lines[]='<tr class="bgColor4"><td>Config template?</td><td>'.($techInfo['conf']?'Yes':'').'</td>'.$this->helpCol('conf').'</tr>'; 02539 $lines[]='<tr class="bgColor4"><td>TypoScript files:</td><td>'.(is_array($techInfo['TSfiles'])?implode('<br />',$techInfo['TSfiles']):'').'</td>'.$this->helpCol('TSfiles').'</tr>'; 02540 $lines[]='<tr class="bgColor4"><td>Language files:</td><td>'.(is_array($techInfo['locallang'])?implode('<br />',$techInfo['locallang']):'').'</td>'.$this->helpCol('locallang').'</tr>'; 02541 $lines[]='<tr class="bgColor4"><td>Upload folder:</td><td>'.($techInfo['uploadfolder']?$techInfo['uploadfolder']:'').'</td>'.$this->helpCol('uploadfolder').'</tr>'; 02542 $lines[]='<tr class="bgColor4"><td>Create directories:</td><td>'.(is_array($techInfo['createDirs'])?implode('<br />',$techInfo['createDirs']):'').'</td>'.$this->helpCol('createDirs').'</tr>'; 02543 $lines[]='<tr class="bgColor4"><td>Module names:</td><td>'.(is_array($techInfo['moduleNames'])?implode('<br />',$techInfo['moduleNames']):'').'</td>'.$this->helpCol('moduleNames').'</tr>'; 02544 $lines[]='<tr class="bgColor4"><td>Class names:</td><td>'.(is_array($techInfo['classes'])?implode('<br />',$techInfo['classes']):'').'</td>'.$this->helpCol('classNames').'</tr>'; 02545 $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>'; 02546 $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>'; 02547 02548 $currentMd5Array = $this->serverExtensionMD5Array($extKey,$extInfo); 02549 $affectedFiles=''; 02550 02551 $msgLines=array(); 02552 if (strcmp($extInfo['EM_CONF']['_md5_values_when_last_written'],serialize($currentMd5Array))) { 02553 $msgLines[] = $GLOBALS['TBE_TEMPLATE']->rfw('<br /><strong>A difference between the originally installed version and the current was detected!</strong>'); 02554 $affectedFiles = $this->findMD5ArrayDiff($currentMd5Array,unserialize($extInfo['EM_CONF']['_md5_values_when_last_written'])); 02555 if (count($affectedFiles)) $msgLines[] = '<br /><strong>Modified files:</strong><br />'.$GLOBALS['TBE_TEMPLATE']->rfw(implode('<br />',$affectedFiles)); 02556 } 02557 $lines[]='<tr class="bgColor4"><td>Files changed?</td><td>'.implode('<br />',$msgLines).'</td>'.$this->helpCol('filesChanged').'</tr>'; 02558 } 02559 02560 return '<table border="0" cellpadding="1" cellspacing="2"> 02561 '.implode(' 02562 ',$lines).' 02563 </table>'; 02564 } 02565 02573 function extInformationArray_dbReq($techInfo,$tableHeader=0) { 02574 return nl2br(trim((is_array($techInfo['tables'])?($tableHeader?"\n\n<strong>Tables:</strong>\n":'').implode(chr(10),$techInfo['tables']):''). 02575 (is_array($techInfo['static'])?"\n\n<strong>Static tables:</strong>\n".implode(chr(10),$techInfo['static']):''). 02576 (is_array($techInfo['fields'])?"\n\n<strong>Additional fields:</strong>\n".implode('<hr />',$techInfo['fields']):''))); 02577 } 02578 02586 function extInformationArray_dbInst($dbInst,$current) { 02587 if (strlen($dbInst)>1) { 02588 $others = array(); 02589 for($a=0;$a<strlen($dbInst);$a++) { 02590 if (substr($dbInst,$a,1)!=$current) { 02591 $others[]='"'.$this->typeLabels[substr($dbInst,$a,1)].'"'; 02592 } 02593 } 02594 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.'); 02595 } else return ''; 02596 } 02597 02605 function getRepositoryUploadForm($extKey,$extInfo) { 02606 $content.=' 02607 <input type="hidden" name="CMD[showExt]" value="'.$extKey.'" /> 02608 <input type="hidden" name="em[action]" value="doUpload" /> 02609 <table border="0" cellpadding="2" cellspacing="1"> 02610 <tr class="bgColor4"> 02611 <td>Repository Username:</td> 02612 <td><input'.$this->doc->formWidth(20).' type="text" name="em[user][fe_u]" value="'.$this->fe_user['username'].'" /></td> 02613 </tr> 02614 <tr class="bgColor4"> 02615 <td>Repository Password:</td> 02616 <td><input'.$this->doc->formWidth(20).' type="password" name="em[user][fe_p]" value="'.$this->fe_user['password'].'" /></td> 02617 </tr> 02618 <tr class="bgColor4"> 02619 <td>Changelog for upload:</td> 02620 <td><textarea'.$this->doc->formWidth(30,1).' rows="5" name="em[upload][comment]"></textarea></td> 02621 </tr> 02622 <tr class="bgColor4"> 02623 <td>Upload command:</td> 02624 <td nowrap="nowrap"> 02625 <input type="radio" name="em[upload][mode]" id="new_dev" value="new_dev" checked="checked" /> <label for="new_dev">New development version (latest x.x.<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('x+1').'</strong>)</label><br /> 02626 <input type="radio" name="em[upload][mode]" id="latest" value="latest" /> <label for="latest">Override <em>this</em> development version ('.$extInfo['EM_CONF']['version'].')</label><br /> 02627 <input type="radio" name="em[upload][mode]" id="new_sub" value="new_sub" /> <label for="new_sub">New sub version (latest x.<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('x+1').'</strong>.0)</label><br /> 02628 <input type="radio" name="em[upload][mode]" id="new_main" value="new_main" /> <label for="new_main">New main version (latest <strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('x+1').'</strong>.0.0)</label><br /> 02629 <input type="radio" name="em[upload][mode]" id="custom" value="custom" /> <label for="custom">This version: <input type="text" name="em[upload][version]" /></label><br /> 02630 </td> 02631 </tr> 02632 <tr class="bgColor4"> 02633 <td> </td> 02634 <td><input type="submit" name="submit" value="Upload extension" /> 02635 </td> 02636 </tr> 02637 </table> 02638 '; 02639 02640 return $content; 02641 } 02642 02643 02644 02645 02646 02647 02648 02649 02650 02651 02652 /*********************************** 02653 * 02654 * Extension list rendering 02655 * 02656 **********************************/ 02657 02666 function extensionListRowHeader($trAttrib,$cells,$import=0) { 02667 $cells[] = '<td></td>'; 02668 $cells[] = '<td>Title:</td>'; 02669 02670 if (!$this->MOD_SETTINGS['display_details']) { 02671 $cells[] = '<td>Description:</td>'; 02672 $cells[] = '<td>Author:</td>'; 02673 } elseif ($this->MOD_SETTINGS['display_details']==2) { 02674 $cells[] = '<td>Priority:</td>'; 02675 $cells[] = '<td>Mod.Tables:</td>'; 02676 $cells[] = '<td>Modules:</td>'; 02677 $cells[] = '<td>Cl.Cache?</td>'; 02678 $cells[] = '<td>Internal?</td>'; 02679 $cells[] = '<td>Shy?</td>'; 02680 } elseif ($this->MOD_SETTINGS['display_details']==3) { 02681 $cells[] = '<td>Tables/Fields:</td>'; 02682 $cells[] = '<td>TS-files:</td>'; 02683 $cells[] = '<td>Affects:</td>'; 02684 $cells[] = '<td>Modules:</td>'; 02685 $cells[] = '<td>Config?</td>'; 02686 $cells[] = '<td>Code warnings:</td>'; 02687 } elseif ($this->MOD_SETTINGS['display_details']==4) { 02688 $cells[] = '<td>locallang:</td>'; 02689 $cells[] = '<td>Classes:</td>'; 02690 $cells[] = '<td>Code warnings:</td>'; 02691 $cells[] = '<td>Nameing annoyances:</td>'; 02692 } elseif ($this->MOD_SETTINGS['display_details']==5) { 02693 $cells[] = '<td>Changed files:</td>'; 02694 } else { 02695 $cells[] = '<td>Extension key:</td>'; 02696 $cells[] = '<td>Version:</td>'; 02697 if (!$import) { 02698 $cells[] = '<td>DL:</td>'; 02699 $cells[] = '<td>Doc:</td>'; 02700 $cells[] = '<td>Type:</td>'; 02701 } else { 02702 $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>'; 02703 $cells[] = '<td class="bgColor6"'.$this->labelInfo('Current type of installation of the extension on this server.').'>Cur. Type:</td>'; 02704 $cells[] = '<td'.$this->labelInfo('Number of downloads, all versions/this version').'>DL:</td>'; 02705 } 02706 $cells[] = '<td>State:</td>'; 02707 } 02708 return ' 02709 <tr'.$trAttrib.'> 02710 '.implode(' 02711 ',$cells).' 02712 </tr>'; 02713 } 02714 02727 function extensionListRow($extKey,$extInfo,$cells,$bgColorClass='',$inst_list=array(),$import=0,$altLinkUrl='') { 02728 02729 // Icon: 02730 $imgInfo = @getImageSize($this->getExtPath($extKey,$extInfo['type']).'/ext_icon.gif'); 02731 if (is_array($imgInfo)) { 02732 $cells[] = '<td><img src="'.$GLOBALS['BACK_PATH'].$this->typeRelPaths[$extInfo['type']].$extKey.'/ext_icon.gif'.'" '.$imgInfo[3].' alt="" /></td>'; 02733 } elseif ($extInfo['_ICON']) { 02734 $cells[] = '<td>'.$extInfo['_ICON'].'</td>'; 02735 } else { 02736 $cells[] = '<td><img src="clear.gif" width="1" height="1" alt="" /></td>'; 02737 } 02738 02739 // Extension title: 02740 $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>'; 02741 02742 // Based on which display mode you will see more or less details: 02743 if (!$this->MOD_SETTINGS['display_details']) { 02744 $cells[] = '<td>'.htmlspecialchars(t3lib_div::fixed_lgd($extInfo['EM_CONF']['description'],400)).'<br /><img src="clear.gif" width="300" height="1" alt="" /></td>'; 02745 $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>'; 02746 } elseif ($this->MOD_SETTINGS['display_details']==2) { 02747 $cells[] = '<td nowrap="nowrap">'.$extInfo['EM_CONF']['priority'].'</td>'; 02748 $cells[] = '<td nowrap="nowrap">'.implode('<br />',t3lib_div::trimExplode(',',$extInfo['EM_CONF']['modify_tables'],1)).'</td>'; 02749 $cells[] = '<td nowrap="nowrap">'.$extInfo['EM_CONF']['module'].'</td>'; 02750 $cells[] = '<td nowrap="nowrap">'.($extInfo['EM_CONF']['clearCacheOnLoad'] ? 'Yes' : '').'</td>'; 02751 $cells[] = '<td nowrap="nowrap">'.($extInfo['EM_CONF']['internal'] ? 'Yes' : '').'</td>'; 02752 $cells[] = '<td nowrap="nowrap">'.($extInfo['EM_CONF']['shy'] ? 'Yes' : '').'</td>'; 02753 } elseif ($this->MOD_SETTINGS['display_details']==3) { 02754 $techInfo = $this->makeDetailedExtensionAnalysis($extKey,$extInfo); 02755 02756 $cells[] = '<td>'.$this->extInformationArray_dbReq($techInfo). 02757 '</td>'; 02758 $cells[] = '<td nowrap="nowrap">'.(is_array($techInfo['TSfiles']) ? implode('<br />',$techInfo['TSfiles']) : '').'</td>'; 02759 $cells[] = '<td nowrap="nowrap">'.(is_array($techInfo['flags']) ? implode('<br />',$techInfo['flags']) : '').'</td>'; 02760 $cells[] = '<td nowrap="nowrap">'.(is_array($techInfo['moduleNames']) ? implode('<br />',$techInfo['moduleNames']) : '').'</td>'; 02761 $cells[] = '<td nowrap="nowrap">'.($techInfo['conf'] ? 'Yes' : '').'</td>'; 02762 $cells[] = '<td>'. 02763 $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!':''). 02764 (t3lib_extMgm::isLoaded($extKey)&&$techInfo['static_error']?'<strong>Static table error!</strong><br />The static tables are missing or empty!':'')). 02765 '</td>'; 02766 } elseif ($this->MOD_SETTINGS['display_details']==4) { 02767 $techInfo=$this->makeDetailedExtensionAnalysis($extKey,$extInfo,1); 02768 02769 $cells[] = '<td>'.(is_array($techInfo['locallang']) ? implode('<br />',$techInfo['locallang']) : '').'</td>'; 02770 $cells[] = '<td>'.(is_array($techInfo['classes']) ? implode('<br />',$techInfo['classes']) : '').'</td>'; 02771 $cells[] = '<td>'.(is_array($techInfo['errors']) ? $GLOBALS['TBE_TEMPLATE']->rfw(implode('<hr />',$techInfo['errors'])) : '').'</td>'; 02772 $cells[] = '<td>'.(is_array($techInfo['NSerrors']) ? (!t3lib_div::inList($this->nameSpaceExceptions,$extKey) ? t3lib_div::view_array($techInfo['NSerrors']) : $GLOBALS['TBE_TEMPLATE']->dfw('[exception]')) :'').'</td>'; 02773 } elseif ($this->MOD_SETTINGS['display_details']==5) { 02774 $currentMd5Array = $this->serverExtensionMD5Array($extKey,$extInfo); 02775 $affectedFiles = ''; 02776 $msgLines = array(); 02777 $msgLines[] = 'Files: '.count($currentMd5Array); 02778 if (strcmp($extInfo['EM_CONF']['_md5_values_when_last_written'],serialize($currentMd5Array))) { 02779 $msgLines[] = $GLOBALS['TBE_TEMPLATE']->rfw('<br /><strong>A difference between the originally installed version and the current was detected!</strong>'); 02780 $affectedFiles = $this->findMD5ArrayDiff($currentMd5Array,unserialize($extInfo['EM_CONF']['_md5_values_when_last_written'])); 02781 if (count($affectedFiles)) $msgLines[] = '<br /><strong>Modified files:</strong><br />'.$GLOBALS['TBE_TEMPLATE']->rfw(implode('<br />',$affectedFiles)); 02782 } 02783 $cells[] = '<td>'.implode('<br />',$msgLines).'</td>'; 02784 } else { 02785 // Default view: 02786 $verDiff = $inst_list[$extKey] && $this->versionDifference($extInfo['EM_CONF']['version'],$inst_list[$extKey]['EM_CONF']['version'],$this->versionDiffFactor); 02787 02788 $cells[] = '<td nowrap="nowrap"><em>'.$extKey.'</em></td>'; 02789 $cells[] = '<td nowrap="nowrap">'.($verDiff ? '<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw(htmlspecialchars($extInfo['EM_CONF']['version'])).'</strong>' : $extInfo['EM_CONF']['version']).'</td>'; 02790 if (!$import) { // Listing extenson on LOCAL server: 02791 // Extension Download: 02792 $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>'; 02793 02794 // Manual download 02795 $fileP = PATH_site.$this->typePaths[$extInfo['type']].$extKey.'/doc/manual.sxw'; 02796 $cells[] = '<td nowrap="nowrap">'. 02797 ($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>':''). 02798 '</td>'; 02799 $cells[] = '<td nowrap="nowrap">'.$this->typeLabels[$extInfo['type']].(strlen($extInfo['doubleInstall'])>1?'<strong> '.$GLOBALS['TBE_TEMPLATE']->rfw($extInfo['doubleInstall']).'</strong>':'').'</td>'; 02800 } else { // Listing extensions from REMOTE repository: 02801 $inst_curVer = $inst_list[$extKey]['EM_CONF']['version']; 02802 if (isset($inst_list[$extKey])) { 02803 if ($verDiff) $inst_curVer = '<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw($inst_curVer).'</strong>'; 02804 } 02805 $cells[] = '<td nowrap="nowrap">'.$inst_curVer.'</td>'; 02806 $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>'; 02807 $cells[] = '<td nowrap="nowrap">'.($extInfo['downloadcounter_all']?$extInfo['downloadcounter_all']:' ').'/'.($extInfo['downloadcounter']?$extInfo['downloadcounter']:' ').'</td>'; 02808 } 02809 $cells[] = '<td nowrap="nowrap" class="extstate" style="background-color:'.$this->stateColors[$extInfo['EM_CONF']['state']].';">'.$this->states[$extInfo['EM_CONF']['state']].'</td>'; 02810 } 02811 02812 if($this->xmlhandler->getReviewState($extKey,$extInfo['EM_CONF']['version'])<1) { 02813 $bgclass = ' class="unsupported-ext"'; 02814 } else { 02815 $bgclass = ' class="'.($bgColorClass?$bgColorClass:'bgColor4').'"'; 02816 } 02817 02818 return ' 02819 <tr'.$bgclass.'> 02820 '.implode(' 02821 ',$cells).' 02822 </tr>'; 02823 } 02824 02825 02826 02827 02828 02829 02830 /************************************ 02831 * 02832 * Output helper functions 02833 * 02834 ************************************/ 02835 02843 function wrapEmail($str,$email) { 02844 if ($email) { 02845 $str = '<a href="mailto:'.htmlspecialchars($email).'">'.htmlspecialchars($str).'</a>'; 02846 } 02847 return $str; 02848 } 02849 02856 function helpCol($key) { 02857 global $BE_USER; 02858 if ($BE_USER->uc['edit_showFieldHelp']) { 02859 $hT = trim(t3lib_BEfunc::helpText($this->descrTable,'emconf_'.$key,$this->doc->backPath)); 02860 return '<td>'.($hT?$hT:t3lib_BEfunc::helpTextIcon($this->descrTable,'emconf_'.$key,$this->doc->backPath)).'</td>'; 02861 } else { 02862 return ''; 02863 } 02864 } 02865 02872 function labelInfo($str) { 02873 return ' title="'.htmlspecialchars($str).'" style="cursor:help;"'; 02874 } 02875 02884 function extensionTitleIconHeader($extKey,$extInfo,$align='top') { 02885 $imgInfo = @getImageSize($this->getExtPath($extKey,$extInfo['type']).'/ext_icon.gif'); 02886 $out = ''; 02887 if (is_array($imgInfo)) { 02888 $out.= '<img src="'.$GLOBALS['BACK_PATH'].$this->typeRelPaths[$extInfo['type']].$extKey.'/ext_icon.gif" '.$imgInfo[3].' align="'.$align.'" alt="" />'; 02889 } 02890 $out.= $extInfo['EM_CONF']['title'] ? htmlspecialchars(t3lib_div::fixed_lgd($extInfo['EM_CONF']['title'],40)) : '<em>'.$extKey.'</em>'; 02891 return $out; 02892 } 02893 02899 function removeButton() { 02900 return '<img src="uninstall.gif" width="16" height="16" title="Remove extension" align="top" alt="" />'; 02901 } 02902 02908 function installButton() { 02909 return '<img src="install.gif" width="16" height="16" title="Install extension..." align="top" alt="" />'; 02910 } 02911 02917 function noImportMsg() { 02918 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>'; 02919 } 02920 02930 function depToString($dep,$type='depends') { 02931 if(is_array($dep)) { 02932 unset($dep[$type]['php']); 02933 unset($dep[$type]['typo3']); 02934 $s = (count($dep[$type])) ? implode(',', array_keys($dep[$type])) : ''; 02935 return $s; 02936 } 02937 return ''; 02938 } 02939 02949 function stringToDep($dep) { 02950 $constraint = array(); 02951 if(is_string($dep) && strlen($dep)) { 02952 $dep = explode(',',$dep); 02953 foreach($dep as $v) { 02954 $constraint[$v] = ''; 02955 } 02956 } 02957 return $constraint; 02958 } 02959 02960 02961 02962 02963 02964 02965 02966 02967 /******************************** 02968 * 02969 * Read information about all available extensions 02970 * 02971 *******************************/ 02972 02979 function getInstalledExtensions() { 02980 $list = array(); 02981 $cat = $this->defaultCategories; 02982 02983 $path = PATH_typo3.'sysext/'; 02984 $this->getInstExtList($path,$list,$cat,'S'); 02985 02986 $path = PATH_typo3.'ext/'; 02987 $this->getInstExtList($path,$list,$cat,'G'); 02988 02989 $path = PATH_typo3conf.'ext/'; 02990 $this->getInstExtList($path,$list,$cat,'L'); 02991 02992 return array($list,$cat); 02993 } 02994 03006 function getInstExtList($path,&$list,&$cat,$type) { 03007 03008 if (@is_dir($path)) { 03009 $extList = t3lib_div::get_dirs($path); 03010 if (is_array($extList)) { 03011 foreach($extList as $extKey) { 03012 if (@is_file($path.$extKey.'/ext_emconf.php')) { 03013 $emConf = $this->includeEMCONF($path.$extKey.'/ext_emconf.php', $extKey); 03014 if (is_array($emConf)) { 03015 if (is_array($list[$extKey])) { 03016 $list[$extKey]=array('doubleInstall'=>$list[$extKey]['doubleInstall']); 03017 } 03018 $list[$extKey]['doubleInstall'].= $type; 03019 $list[$extKey]['type'] = $type; 03020 $list[$extKey]['EM_CONF'] = $emConf; 03021 $list[$extKey]['files'] = t3lib_div::getFilesInDir($path.$extKey, '', 0, '', $this->excludeForPackaging); 03022 03023 $this->setCat($cat,$list[$extKey], $extKey); 03024 } 03025 } 03026 } 03027 } 03028 } 03029 } 03030 03037 function fixEMCONF($emConf) { 03038 if(!isset($emConf['constraints']) || !isset($emConf['constraints']['depends']) || !isset($emConf['constraints']['conflicts']) || !isset($emConf['constraints']['suggests'])) { 03039 if(!isset($emConf['constraints']) || !isset($emConf['constraints']['depends'])) { 03040 $emConf['constraints']['depends'] = $this->stringToDep($emConf['dependencies']); 03041 if(strlen($emConf['PHP_version'])) { 03042 $versionRange = $this->splitVersionRange($emConf['PHP_version']); 03043 if (version_compare($versionRange[0],'3.0.0','<')) $versionRange[0] = '3.0.0'; 03044 if (version_compare($versionRange[1],'3.0.0','<')) $versionRange[1] = '0.0.0'; 03045 $emConf['constraints']['depends']['php'] = implode('-',$versionRange); 03046 } 03047 if(strlen($emConf['TYPO3_version'])) { 03048 $versionRange = $this->splitVersionRange($emConf['TYPO3_version']); 03049 if (version_compare($versionRange[0],'3.5.0','<')) $versionRange[0] = '3.5.0'; 03050 if (version_compare($versionRange[1],'3.5.0','<')) $versionRange[1] = '0.0.0'; 03051 $emConf['constraints']['depends']['typo3'] = implode('-',$versionRange); 03052 } 03053 } 03054 if(!isset($emConf['constraints']) || !isset($emConf['constraints']['conflicts'])) { 03055 $emConf['constraints']['conflicts'] = $this->stringToDep($emConf['conflicts']); 03056 } 03057 if(!isset($emConf['constraints']) || !isset($emConf['constraints']['suggests'])) { 03058 $emConf['constraints']['suggests'] = array(); 03059 } 03060 } elseif (isset($emConf['constraints']) && isset($emConf['dependencies'])) { 03061 $emConf['suggests'] = isset($emConf['suggests']) ? $emConf['suggests'] : array(); 03062 $emConf['dependencies'] = $this->depToString($emConf['constraints']); 03063 $emConf['conflicts'] = $this->depToString($emConf['constraints'], 'conflicts'); 03064 } 03065 03066 // sanity check for version numbers, intentionally only checks php and typo3 03067 if(isset($emConf['constraints']['depends']) && isset($emConf['constraints']['depends']['php'])) { 03068 $versionRange = $this->splitVersionRange($emConf['constraints']['depends']['php']); 03069 if (version_compare($versionRange[0],'3.0.0','<')) $versionRange[0] = '3.0.0'; 03070 if (version_compare($versionRange[1],'3.0.0','<')) $versionRange[1] = '0.0.0'; 03071 $emConf['constraints']['depends']['php'] = implode('-',$versionRange); 03072 } 03073 if(isset($emConf['constraints']['depends']) && isset($emConf['constraints']['depends']['typo3'])) { 03074 $versionRange = $this->splitVersionRange($emConf['constraints']['depends']['typo3']); 03075 if (version_compare($versionRange[0],'3.5.0','<')) $versionRange[0] = '3.5.0'; 03076 if (version_compare($versionRange[1],'3.5.0','<')) $versionRange[1] = '0.0.0'; 03077 $emConf['constraints']['depends']['typo3'] = implode('-',$versionRange); 03078 } 03079 03080 unset($emConf['private']); 03081 unset($emConf['download_password']); 03082 unset($emConf['TYPO3_version']); 03083 unset($emConf['PHP_version']); 03084 03085 return $emConf; 03086 } 03087 03097 function splitVersionRange($ver) { 03098 $versionRange = array(); 03099 if (strstr($ver, '-')) { 03100 $versionRange = explode('-', $ver, 2); 03101 } else { 03102 $versionRange[0] = $ver; 03103 $versionRange[1] = ''; 03104 } 03105 03106 if (!$versionRange[0]) { $versionRange[0] = '0.0.0'; } 03107 if (!$versionRange[1]) { $versionRange[1] = '0.0.0'; } 03108 03109 return $versionRange; 03110 } 03111 03118 function prepareImportExtList($unsetProc = false) { 03119 $list = array(); 03120 $cat = $this->defaultCategories; 03121 $filepath = $this->getMirrorURL(); 03122 03123 reset($this->xmlhandler->extensionsXML); 03124 while (list($extKey, $data) = each($this->xmlhandler->extensionsXML)) { 03125 $GLOBALS['LANG']->csConvObj->convArray($data,'utf-8',$GLOBALS['LANG']->charSet); // is there a better place for conversion? 03126 $list[$extKey]['type'] = '_'; 03127 $version = array_keys($data['versions']); 03128 $list[$extKey]['_ICON'] = '<img alt="" src="'.$filepath.$extKey{0}.'/'.$extKey{1}.'/'.$extKey.'_'.end($version).'.gif" />'; 03129 $list[$extKey]['downloadcounter'] = $data['downloadcounter']; 03130 03131 foreach(array_keys($data['versions']) as $version) { 03132 $list[$extKey]['versions'][$version]['downloadcounter'] = $data['versions'][$version]['downloadcounter']; 03133 03134 $list[$extKey]['versions'][$version]['EM_CONF'] = array( 03135 'version' => $version, 03136 'title' => $data['versions'][$version]['title'], 03137 'description' => $data['versions'][$version]['description'], 03138 'category' => $data['versions'][$version]['category'], 03139 'constraints' => $data['versions'][$version]['dependencies'], 03140 'state' => $data['versions'][$version]['state'], 03141 'reviewstate' => $data['versions'][$version]['reviewstate'], 03142 'lastuploaddate' => $data['versions'][$version]['lastuploaddate'], 03143 'author' => $data['versions'][$version]['authorname'], 03144 'author_email' => $data['versions'][$version]['authoremail'], 03145 'author_company' => $data['versions'][$version]['authorcompany'], 03146 ); 03147 } 03148 $this->setCat($cat, $list[$extKey]['versions'][$version], $extKey); 03149 if ($unsetProc) { 03150 unset($this->xmlhandler->extensionsXML[$extKey]); 03151 } 03152 } 03153 03154 return array($list,$cat); 03155 } 03156 03165 function setCat(&$cat,$listArrayPart,$extKey) { 03166 03167 // Getting extension title: 03168 $extTitle = $listArrayPart['EM_CONF']['title']; 03169 03170 // Category index: 03171 $index = $listArrayPart['EM_CONF']['category']; 03172 $cat['cat'][$index][$extKey] = $extTitle; 03173 03174 // Author index: 03175 $index = $listArrayPart['EM_CONF']['author'].($listArrayPart['EM_CONF']['author_company']?', '.$listArrayPart['EM_CONF']['author_company']:''); 03176 $cat['author_company'][$index][$extKey] = $extTitle; 03177 03178 // State index: 03179 $index = $listArrayPart['EM_CONF']['state']; 03180 $cat['state'][$index][$extKey] = $extTitle; 03181 03182 // Type index: 03183 $index = $listArrayPart['type']; 03184 $cat['type'][$index][$extKey] = $extTitle; 03185 03186 // Return categories: 03187 return $cat; 03188 } 03189 03190 03191 03192 03193 03194 03195 03196 03197 03198 03199 /******************************* 03200 * 03201 * Extension analyzing (detailed information) 03202 * 03203 ******************************/ 03204 03215 function makeDetailedExtensionAnalysis($extKey,$extInfo,$validity=0) { 03216 03217 // Get absolute path of the extension 03218 $absPath = $this->getExtPath($extKey,$extInfo['type']); 03219 03220 $infoArray = array(); 03221 03222 $table_class_prefix = substr($extKey,0,5)=='user_' ? 'user_' : 'tx_'.str_replace('_','',$extKey).'_'; 03223 $module_prefix = substr($extKey,0,5)=='user_' ? 'u' : 'tx'.str_replace('_','',$extKey); 03224 03225 // Database status: 03226 $dbInfo = $this->checkDBupdates($extKey,$extInfo,1); 03227 03228 // Database structure required: 03229 if (is_array($dbInfo['structure']['tables_fields'])) { 03230 $modify_tables = t3lib_div::trimExplode(',',$extInfo['EM_CONF']['modify_tables'],1); 03231 $infoArray['dump_tf'] = array(); 03232 03233 foreach($dbInfo['structure']['tables_fields'] as $tN => $d) { 03234 if (in_array($tN,$modify_tables)) { 03235 $infoArray['fields'][] = $tN.': <i>'. 03236 (is_array($d['fields']) ? implode(', ',array_keys($d['fields'])) : ''). 03237 (is_array($d['keys']) ? ' + '.count($d['keys']).' keys' : ''). 03238 '</i>'; 03239 if (is_array($d['fields'])) { 03240 reset($d['fields']); 03241 while(list($fN) = each($d['fields'])) { 03242 $infoArray['dump_tf'][] = $tN.'.'.$fN; 03243 if (!t3lib_div::isFirstPartOfStr($fN,$table_class_prefix)) { 03244 $infoArray['NSerrors']['fields'][$fN] = $fN; 03245 } else { 03246 $infoArray['NSok']['fields'][$fN] = $fN; 03247 } 03248 } 03249 } 03250 if (is_array($d['keys'])) { 03251 reset($d['keys']); 03252 while(list($fN)=each($d['keys'])) { 03253 $infoArray['dump_tf'][] = $tN.'.KEY:'.$fN; 03254 } 03255 } 03256 } else { 03257 $infoArray['dump_tf'][] = $tN; 03258 $infoArray['tables'][] = $tN; 03259 if (!t3lib_div::isFirstPartOfStr($tN,$table_class_prefix)) { 03260 $infoArray['NSerrors']['tables'][$tN] = $tN; 03261 } else $infoArray['NSok']['tables'][$tN] = $tN; 03262 } 03263 } 03264 if (count($dbInfo['structure']['diff']['diff']) || count($dbInfo['structure']['diff']['extra'])) { 03265 $msg = array(); 03266 if (count($dbInfo['structure']['diff']['diff'])) $msg[] = 'missing'; 03267 if (count($dbInfo['structure']['diff']['extra'])) $msg[] = 'of wrong type'; 03268 $infoArray['tables_error'] = 1; 03269 if (t3lib_extMgm::isLoaded($extKey)) $infoArray['errors'][] = 'Some tables or fields are '.implode(' and ',$msg).'!'; 03270 } 03271 } 03272 03273 // Static tables? 03274 if (is_array($dbInfo['static'])) { 03275 $infoArray['static'] = array_keys($dbInfo['static']); 03276 03277 foreach($dbInfo['static'] as $tN => $d) { 03278 if (!$d['exists']) { 03279 $infoArray['static_error'] = 1; 03280 if (t3lib_extMgm::isLoaded($extKey)) $infoArray['errors'][] = 'Static table(s) missing!'; 03281 if (!t3lib_div::isFirstPartOfStr($tN,$table_class_prefix)) { 03282 $infoArray['NSerrors']['tables'][$tN] = $tN; 03283 } else $infoArray['NSok']['tables'][$tN] = $tN; 03284 } 03285 } 03286 } 03287 03288 // Backend Module-check: 03289 $knownModuleList = t3lib_div::trimExplode(',',$extInfo['EM_CONF']['module'],1); 03290 foreach($knownModuleList as $mod) { 03291 if (@is_dir($absPath.$mod)) { 03292 if (@is_file($absPath.$mod.'/conf.php')) { 03293 $confFileInfo = $this->modConfFileAnalysis($absPath.$mod.'/conf.php'); 03294 if (is_array($confFileInfo['TYPO3_MOD_PATH'])) { 03295 $shouldBePath = $this->typeRelPaths[$extInfo['type']].$extKey.'/'.$mod.'/'; 03296 if (strcmp($confFileInfo['TYPO3_MOD_PATH'][1][1],$shouldBePath)) { 03297 $infoArray['errors'][] = 'Configured TYPO3_MOD_PATH "'.$confFileInfo['TYPO3_MOD_PATH'][1][1].'" different from "'.$shouldBePath.'"'; 03298 } 03299 } else $infoArray['errors'][] = 'No definition of TYPO3_MOD_PATH constant found inside!'; 03300 if (is_array($confFileInfo['MCONF_name'])) { 03301 $mName = $confFileInfo['MCONF_name'][1][1]; 03302 $mNameParts = explode('_',$mName); 03303 $infoArray['moduleNames'][] = $mName; 03304 if (!t3lib_div::isFirstPartOfStr($mNameParts[0],$module_prefix) && 03305 (!$mNameParts[1] || !t3lib_div::isFirstPartOfStr($mNameParts[1],$module_prefix))) { 03306 $infoArray['NSerrors']['modname'][] = $mName; 03307 } else $infoArray['NSok']['modname'][] = $mName; 03308 } else $infoArray['errors'][] = 'No definition of MCONF[name] variable found inside!'; 03309 } else $infoArray['errors'][] = 'Backend module conf file "'.$mod.'/conf.php" should exist but does not!'; 03310 } else $infoArray['errors'][] = 'Backend module folder "'.$mod.'/" should exist but does not!'; 03311 } 03312 $dirs = t3lib_div::get_dirs($absPath); 03313 if (is_array($dirs)) { 03314 reset($dirs); 03315 while(list(,$mod) = each($dirs)) { 03316 if (!in_array($mod,$knownModuleList) && @is_file($absPath.$mod.'/conf.php')) { 03317 $confFileInfo = $this->modConfFileAnalysis($absPath.$mod.'/conf.php'); 03318 if (is_array($confFileInfo)) { 03319 $infoArray['errors'][] = 'It seems like there is a backend module in "'.$mod.'/conf.php" which is not configured in ext_emconf.php'; 03320 } 03321 } 03322 } 03323 } 03324 03325 // ext_tables.php: 03326 if (@is_file($absPath.'ext_tables.php')) { 03327 $content = t3lib_div::getUrl($absPath.'ext_tables.php'); 03328 if (stristr($content,'t3lib_extMgm::addModule')) $infoArray['flags'][] = 'Module'; 03329 if (stristr($content,'t3lib_extMgm::insertModuleFunction')) $infoArray['flags'][] = 'Module+'; 03330 if (stristr($content,'t3lib_div::loadTCA')) $infoArray['flags'][] = 'loadTCA'; 03331 if (stristr($content,'$TCA[')) $infoArray['flags'][] = 'TCA'; 03332 if (stristr($content,'t3lib_extMgm::addPlugin')) $infoArray['flags'][] = 'Plugin'; 03333 } 03334 03335 // ext_localconf.php: 03336 if (@is_file($absPath.'ext_localconf.php')) { 03337 $content = t3lib_div::getUrl($absPath.'ext_localconf.php'); 03338 if (stristr($content,'t3lib_extMgm::addPItoST43')) $infoArray['flags'][]='Plugin/ST43'; 03339 if (stristr($content,'t3lib_extMgm::addPageTSConfig')) $infoArray['flags'][]='Page-TSconfig'; 03340 if (stristr($content,'t3lib_extMgm::addUserTSConfig')) $infoArray['flags'][]='User-TSconfig'; 03341 if (stristr($content,'t3lib_extMgm::addTypoScriptSetup')) $infoArray['flags'][]='TS/Setup'; 03342 if (stristr($content,'t3lib_extMgm::addTypoScriptConstants')) $infoArray['flags'][]='TS/Constants'; 03343 } 03344 03345 if (@is_file($absPath.'ext_typoscript_constants.txt')) { 03346 $infoArray['TSfiles'][] = 'Constants'; 03347 } 03348 if (@is_file($absPath.'ext_typoscript_setup.txt')) { 03349 $infoArray['TSfiles'][] = 'Setup'; 03350 } 03351 if (@is_file($absPath.'ext_conf_template.txt')) { 03352 $infoArray['conf'] = 1; 03353 } 03354 03355 // Classes: 03356 if ($validity) { 03357 $filesInside = $this->getClassIndexLocallangFiles($absPath,$table_class_prefix,$extKey); 03358 if (is_array($filesInside['errors'])) $infoArray['errors'] = array_merge((array)$infoArray['errors'],$filesInside['errors']); 03359 if (is_array($filesInside['NSerrors'])) $infoArray['NSerrors'] = array_merge((array)$infoArray['NSerrors'],$filesInside['NSerrors']); 03360 if (is_array($filesInside['NSok'])) $infoArray['NSok'] = array_merge((array)$infoArray['NSok'],$filesInside['NSok']); 03361 $infoArray['locallang'] = $filesInside['locallang']; 03362 $infoArray['classes'] = $filesInside['classes']; 03363 } 03364 03365 // Upload folders 03366 if ($extInfo['EM_CONF']['uploadfolder']) { 03367 $infoArray['uploadfolder'] = $this->ulFolder($extKey); 03368 if (!@is_dir(PATH_site.$infoArray['uploadfolder'])) { 03369 $infoArray['errors'][] = 'Error: Upload folder "'.$infoArray['uploadfolder'].'" did not exist!'; 03370 $infoArray['uploadfolder'] = ''; 03371 } 03372 } 03373 03374 // Create directories: 03375 if ($extInfo['EM_CONF']['createDirs']) { 03376 $infoArray['createDirs'] = array_unique(t3lib_div::trimExplode(',',$extInfo['EM_CONF']['createDirs'],1)); 03377 foreach($infoArray['createDirs'] as $crDir) { 03378 if (!@is_dir(PATH_site.$crDir)) { 03379 $infoArray['errors'][]='Error: Upload folder "'.$crDir.'" did not exist!'; 03380 } 03381 } 03382 } 03383 03384 // Return result array: 03385 return $infoArray; 03386 } 03387 03397 function getClassIndexLocallangFiles($absPath,$table_class_prefix,$extKey) { 03398 $filesInside = t3lib_div::removePrefixPathFromList(t3lib_div::getAllFilesAndFoldersInPath(array(),$absPath,'php,inc',0,99,$this->excludeForPackaging),$absPath); 03399 $out = array(); 03400 03401 foreach($filesInside as $fileName) { 03402 if (substr($fileName,0,4)!='ext_' && substr($fileName,0,6)!='tests/') { // ignore supposed-to-be unit tests as well 03403 $baseName = basename($fileName); 03404 if (substr($baseName,0,9)=='locallang' && substr($baseName,-4)=='.php') { 03405 $out['locallang'][] = $fileName; 03406 } elseif ($baseName!='conf.php') { 03407 if (filesize($absPath.$fileName)<500*1024) { 03408 $fContent = t3lib_div::getUrl($absPath.$fileName); 03409 unset($reg); 03410 if (preg_match('/\n[[:space:]]*class[[:space:]]*([[:alnum:]_]+)([[:alnum:][:space:]_]*)/',$fContent,$reg)) { 03411 03412 // Find classes: 03413 $lines = explode(chr(10),$fContent); 03414 foreach($lines as $l) { 03415 $line = trim($l); 03416 unset($reg); 03417 if (preg_match('/^class[[:space:]]*([[:alnum:]_]+)([[:alnum:][:space:]_]*)/',$line,$reg)) { 03418 $out['classes'][] = $reg[1]; 03419 $out['files'][$fileName]['classes'][] = $reg[1]; 03420 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])) { 03421 $out['NSerrors']['classname'][] = $reg[1]; 03422 } else $out['NSok']['classname'][] = $reg[1]; 03423 } 03424 } 03425 // If class file prefixed 'class.'.... 03426 if (substr($baseName,0,6)=='class.') { 03427 $fI = pathinfo($baseName); 03428 $testName=substr($baseName,6,-(1+strlen($fI['extension']))); 03429 if ($testName!=='ext_update' && substr($testName,0,3)!='ux_' && !t3lib_div::isFirstPartOfStr($testName,$table_class_prefix) && strcmp(substr($table_class_prefix,0,-1),$testName)) { 03430 $out['NSerrors']['classfilename'][] = $baseName; 03431 } else { 03432 $out['NSok']['classfilename'][] = $baseName; 03433 if (is_array($out['files'][$fileName]['classes']) && $this->first_in_array($testName,$out['files'][$fileName]['classes'],1)) { 03434 $out['msg'][] = 'Class filename "'.$fileName.'" did contain the class "'.$testName.'" just as it should.'; 03435 } else $out['errors'][] = 'Class filename "'.$fileName.'" did NOT contain the class "'.$testName.'"!'; 03436 } 03437 } 03438 // 03439 $XclassParts = split('if \(defined\([\'"]TYPO3_MODE[\'"]\) && \$TYPO3_CONF_VARS\[TYPO3_MODE\]\[[\'"]XCLASS[\'"]\]',$fContent,2); 03440 if (count($XclassParts)==2) { 03441 unset($reg); 03442 preg_match('/^\[[\'"]([[:alnum:]_\/\.]*)[\'"]\]/',$XclassParts[1],$reg); 03443 if ($reg[1]) { 03444 $cmpF = 'ext/'.$extKey.'/'.$fileName; 03445 if (!strcmp($reg[1],$cmpF)) { 03446 if (preg_match('/_once[[:space:]]*\(\$TYPO3_.ONF_VARS\[TYPO3_MODE\]\[[\'"]XCLASS[\'"]\]\[[\'"]'.preg_quote($cmpF,'/').'[\'"]\]\);/', $XclassParts[1])) { 03447 $out['msg'][] = 'XCLASS OK in '.$fileName; 03448 } else $out['errors'][] = 'Couldn\'t find the include_once statement for XCLASS!'; 03449 } else $out['errors'][] = 'The XCLASS filename-key "'.$reg[1].'" was different from "'.$cmpF.'" which it should have been!'; 03450 } else $out['errors'][] = 'No XCLASS filename-key found in file "'.$fileName.'". Maybe a regex coding error here...'; 03451 } elseif (!$this->first_in_array('ux_',$out['files'][$fileName]['classes'])) $out['errors'][] = 'No XCLASS inclusion code found in file "'.$fileName.'"'; 03452 } 03453 } 03454 } 03455 } 03456 } 03457 return $out; 03458 } 03459 03467 function modConfFileAnalysis($confFilePath) { 03468 $lines = explode(chr(10),t3lib_div::getUrl($confFilePath)); 03469 $confFileInfo = array(); 03470 $confFileInfo['lines'] = $lines; 03471 03472 foreach($lines as $k => $l) { 03473 $line = trim($l); 03474 03475 unset($reg); 03476 if (preg_match('/^define[[:space:]]*\([[:space:]]*["\']TYPO3_MOD_PATH["\'][[:space:]]*,[[:space:]]*["\']([[:alnum:]_\/\.]+)["\'][[:space:]]*\)[[:space:]]*;/',$line,$reg)) { 03477 $confFileInfo['TYPO3_MOD_PATH'] = array($k,$reg); 03478 } 03479 03480 unset($reg); 03481 if (preg_match('/^\$MCONF\[["\']?name["\']?\][[:space:]]*=[[:space:]]*["\']([[:alnum:]_]+)["\'];/',$line,$reg)) { 03482 $confFileInfo['MCONF_name'] = array($k,$reg); 03483 } 03484 } 03485 return $confFileInfo; 03486 } 03487 03495 function serverExtensionMD5Array($extKey,$conf) { 03496 03497 // Creates upload-array - including filelist. 03498 $mUA = $this->makeUploadArray($extKey,$conf); 03499 03500 $md5Array = array(); 03501 if (is_array($mUA['FILES'])) { 03502 03503 // Traverse files. 03504 foreach($mUA['FILES'] as $fN => $d) { 03505 if ($fN!='ext_emconf.php') { 03506 $md5Array[$fN] = substr($d['content_md5'],0,4); 03507 } 03508 } 03509 } else debug($mUA); 03510 return $md5Array; 03511 } 03512 03520 function findMD5ArrayDiff($current,$past) { 03521 if (!is_array($current)) $current = array(); 03522 if (!is_array($past)) $past = array(); 03523 $filesInCommon = array_intersect($current,$past); 03524 $diff1 = array_keys(array_diff($past,$filesInCommon)); 03525 $diff2 = array_keys(array_diff($current,$filesInCommon)); 03526 $affectedFiles = array_unique(array_merge($diff1,$diff2)); 03527 return $affectedFiles; 03528 } 03529 03530 03531 03532 03533 03534 03535 03536 03537 03538 03539 /*********************************** 03540 * 03541 * File system operations 03542 * 03543 **********************************/ 03544 03552 function createDirsInPath($dirs,$extDirPath) { 03553 if (is_array($dirs)) { 03554 foreach($dirs as $dir) { 03555 $error = t3lib_div::mkdir_deep($extDirPath,$dir); 03556 if ($error) return $error; 03557 } 03558 } 03559 03560 return false; 03561 } 03562 03570 function removeExtDirectory($removePath,$removeContentOnly=0) { 03571 $errors = array(); 03572 if (@is_dir($removePath) && substr($removePath,-1)=='/' && ( 03573 t3lib_div::isFirstPartOfStr($removePath,PATH_site.$this->typePaths['G']) || 03574 t3lib_div::isFirstPartOfStr($removePath,PATH_site.$this->typePaths['L']) || 03575 (t3lib_div::isFirstPartOfStr($removePath,PATH_site.$this->typePaths['S']) && $this->systemInstall) || 03576 t3lib_div::isFirstPartOfStr($removePath,PATH_site.'fileadmin/_temp_/')) // Playing-around directory... 03577 ) { 03578 03579 // All files in extension directory: 03580 $fileArr = t3lib_div::getAllFilesAndFoldersInPath(array(),$removePath,'',1); 03581 if (is_array($fileArr)) { 03582 03583 // Remove files in dirs: 03584 foreach($fileArr as $removeFile) { 03585 if (!@is_dir($removeFile)) { 03586 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! 03587 @unlink($removeFile); 03588 clearstatcache(); 03589 if (@is_file($removeFile)) { 03590 $errors[] = 'Error: "'.$removeFile.'" could not be deleted!'; 03591 } 03592 } else $errors[] = 'Error: "'.$removeFile.'" was either not a file, or it was equal to the removed directory or simply outside the removed directory "'.$removePath.'"!'; 03593 } 03594 } 03595 03596 // Remove directories: 03597 $remDirs = $this->extractDirsFromFileList(t3lib_div::removePrefixPathFromList($fileArr,$removePath)); 03598 $remDirs = array_reverse($remDirs); // Must delete outer directories first... 03599 foreach($remDirs as $removeRelDir) { 03600 $removeDir = $removePath.$removeRelDir; 03601 if (@is_dir($removeDir)) { 03602 rmdir($removeDir); 03603 clearstatcache(); 03604 if (@is_dir($removeDir)) { 03605 $errors[] = 'Error: "'.$removeDir.'" could not be removed (are there files left?)'; 03606 } 03607 } else $errors[] = 'Error: "'.$removeDir.'" was not a directory!'; 03608 } 03609 03610 // If extension dir should also be removed: 03611 if (!$removeContentOnly) { 03612 rmdir($removePath); 03613 clearstatcache(); 03614 if (@is_dir($removePath)) { 03615 $errors[] = 'Error: Extension directory "'.$removePath.'" could not be removed (are there files or folders left?)'; 03616 } 03617 } 03618 } else $errors[] = 'Error: '.$fileArr; 03619 } else $errors[] = 'Error: Unallowed path to remove: '.$removePath; 03620 03621 // Return errors if any: 03622 return implode(chr(10),$errors); 03623 } 03624 03633 function clearAndMakeExtensionDir($importedData,$type,$dontDelete=0) { 03634 if (!$importedData['extKey']) return 'FATAL ERROR: Extension key was not set for some VERY strange reason. Nothing done...'; 03635 03636 // Setting install path (L, G, S or fileadmin/_temp_/) 03637 $path = ''; 03638 switch((string)$type) { 03639 case 'G': 03640 case 'L': 03641 $path = PATH_site.$this->typePaths[$type]; 03642 $suffix = ''; 03643 03644 // Creates the typo3conf/ext/ directory if it does NOT already exist: 03645 if ((string)$type=='L' && !@is_dir($path)) { 03646 t3lib_div::mkdir($path); 03647 } 03648 break; 03649 default: 03650 if ($this->systemInstall && (string)$type=='S') { 03651 $path = PATH_site.$this->typePaths[$type]; 03652 $suffix = ''; 03653 } else { 03654 $path = PATH_site.'fileadmin/_temp_/'; 03655 $suffix = '_'.date('dmy-His'); 03656 } 03657 break; 03658 } 03659 03660 // If the install path is OK... 03661 if ($path && @is_dir($path)) { 03662 03663 // Set extension directory: 03664 $extDirPath = $path.$importedData['extKey'].$suffix.'/'; 03665 03666 // Install dir was found, remove it then: 03667 if (@is_dir($extDirPath)) { 03668 if($dontDelete) return array($extDirPath); 03669 $res = $this->removeExtDirectory($extDirPath); 03670 if ($res) { 03671 return 'ERROR: Could not remove extension directory "'.$extDirPath.'". Reasons:<br /><br />'.nl2br($res); 03672 } 03673 } 03674 03675 // We go create... 03676 t3lib_div::mkdir($extDirPath); 03677 if (!is_dir($extDirPath)) return 'ERROR: Could not create extension directory "'.$extDirPath.'"'; 03678 return array($extDirPath); 03679 } else return 'ERROR: The extension install path "'.$path.'" was not a directory.'; 03680 } 03681 03687 function removeCacheFiles() { 03688 return t3lib_extMgm::removeCacheFiles(); 03689 } 03690 03697 function extractDirsFromFileList($files) { 03698 $dirs = array(); 03699 03700 if (is_array($files)) { 03701 // Traverse files / directories array: 03702 foreach($files as $file) { 03703 if (substr($file,-1)=='/') { 03704 $dirs[$file] = $file; 03705 } else { 03706 $pI = pathinfo($file); 03707 if (strcmp($pI['dirname'],'') && strcmp($pI['dirname'],'.')) { 03708 $dirs[$pI['dirname'].'/'] = $pI['dirname'].'/'; 03709 } 03710 } 03711 } 03712 } 03713 return $dirs; 03714 } 03715 03723 function getExtPath($extKey,$type) { 03724 $typeP = $this->typePaths[$type]; 03725 if ($typeP) { 03726 $path = PATH_site.$typeP.$extKey.'/'; 03727 return @is_dir($path) ? $path : ''; 03728 } else { 03729 return ''; 03730 } 03731 } 03732 03733 03734 03735 03736 03737 03738 03739 03740 03741 03742 /******************************* 03743 * 03744 * Writing to "conf.php" and "localconf.php" files 03745 * 03746 ******************************/ 03747 03757 function writeTYPO3_MOD_PATH($confFilePath,$type,$mP) { 03758 $lines = explode(chr(10),t3lib_div::getUrl($confFilePath)); 03759 $confFileInfo = array(); 03760 $confFileInfo['lines'] = $lines; 03761 03762 $flag_M = 0; 03763 $flag_B = 0; 03764 03765 foreach($lines as $k => $l) { 03766 $line = trim($l); 03767 03768 unset($reg); 03769 if (preg_match('/^define[[:space:]]*\([[:space:]]*["\']TYPO3_MOD_PATH["\'][[:space:]]*,[[:space:]]*["\']([[:alnum:]_\/\.]+)["\'][[:space:]]*\)[[:space:]]*;/',$line,$reg)) { 03770 $lines[$k] = str_replace($reg[0], 'define(\'TYPO3_MOD_PATH\', \''.$this->typeRelPaths[$type].$mP.'\');', $lines[$k]); 03771 $flag_M = $k+1; 03772 } 03773 03774 unset($reg); 03775 if (preg_match('/^\$BACK_PATH[[:space:]]*=[[:space:]]*["\']([[:alnum:]_\/\.]+)["\'][[:space:]]*;/',$line,$reg)) { 03776 $lines[$k] = str_replace($reg[0], '$BACK_PATH=\''.$this->typeBackPaths[$type].'\';', $lines[$k]); 03777 $flag_B = $k+1; 03778 } 03779 } 03780 03781 if ($flag_B && $flag_M) { 03782 t3lib_div::writeFile($confFilePath,implode(chr(10),$lines)); 03783 return 'TYPO3_MOD_PATH and $BACK_PATH was updated in "'.substr($confFilePath,strlen(PATH_site)).'"'; 03784 } else return 'Error: Either TYPO3_MOD_PATH or $BACK_PATH was not found in the "'.$confFilePath.'" file. You must manually configure that!'; 03785 } 03786 03794 function writeNewExtensionList($newExtList) { 03795 global $TYPO3_CONF_VARS; 03796 03797 // Instance of install tool 03798 $instObj = new t3lib_install; 03799 $instObj->allowUpdateLocalConf =1; 03800 $instObj->updateIdentity = 'TYPO3 Extension Manager'; 03801 03802 // Get lines from localconf file 03803 $lines = $instObj->writeToLocalconf_control(); 03804 $instObj->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'EXT\'][\'extList\']', $newExtList); 03805 $instObj->writeToLocalconf_control($lines); 03806 03807 $TYPO3_CONF_VARS['EXT']['extList'] = $newExtList; 03808 $this->removeCacheFiles(); 03809 } 03810 03819 function writeTsStyleConfig($extKey,$arr) { 03820 03821 // Instance of install tool 03822 $instObj = new t3lib_install; 03823 $instObj->allowUpdateLocalConf =1; 03824 $instObj->updateIdentity = 'TYPO3 Extension Manager'; 03825 03826 // Get lines from localconf file 03827 $lines = $instObj->writeToLocalconf_control(); 03828 $instObj->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'EXT\'][\'extConf\'][\''.$extKey.'\']', serialize($arr)); // This will be saved only if there are no linebreaks in it ! 03829 $instObj->writeToLocalconf_control($lines); 03830 03831 $this->removeCacheFiles(); 03832 } 03833 03841 function updateLocalEM_CONF($extKey,$extInfo) { 03842 $extInfo['EM_CONF']['_md5_values_when_last_written'] = serialize($this->serverExtensionMD5Array($extKey,$extInfo)); 03843 $emConfFileContent = $this->construct_ext_emconf_file($extKey,$extInfo['EM_CONF']); 03844 03845 $absPath = $this->getExtPath($extKey,$extInfo['type']); 03846 $emConfFileName = $absPath.'ext_emconf.php'; 03847 if($emConfFileContent) { 03848 03849 if(@is_file($emConfFileName)) { 03850 if(t3lib_div::writeFile($emConfFileName,$emConfFileContent) === true) { 03851 return '"'.substr($emConfFileName,strlen($absPath)).'" was updated with a cleaned up EM_CONF array.'; 03852 } else { 03853 return '<strong>Error: "'.$emConfFileName.'" was not writable!</strong>'; 03854 } 03855 } else return('<strong>Error: No file "'.$emConfFileName.'" found. DON\'T PANIC!</strong>'); 03856 } else { 03857 return 'No content to write to "'.substr($emConfFileName,strlen($absPath)).'"!'; 03858 } 03859 } 03860 03861 03862 03863 03864 03865 03866 03867 03868 03869 03870 /******************************************* 03871 * 03872 * Compiling upload information, emconf-file etc. 03873 * 03874 *******************************************/ 03875 03883 function construct_ext_emconf_file($extKey,$EM_CONF) { 03884 03885 // clean version number: 03886 $vDat = $this->renderVersion($EM_CONF['version']); 03887 $EM_CONF['version']=$vDat['version']; 03888 03889 $code = '<?php 03890 03891 ######################################################################## 03892 # Extension Manager/Repository config file for ext: "'.$extKey.'" 03893 # 03894 # Auto generated '.date('d-m-Y H:i').' 03895 # 03896 # Manual updates: 03897 # Only the data in the array - anything else is removed by next write. 03898 # "version" and "dependencies" must not be touched! 03899 ######################################################################## 03900 03901 $EM_CONF[$_EXTKEY] = '.$this->arrayToCode($EM_CONF, 0).'; 03902 03903 ?>'; 03904 return str_replace(chr(13), '', $code); 03905 } 03906 03915 function arrayToCode($array, $level=0) { 03916 $lines = 'array('.chr(10); 03917 $level++; 03918 foreach($array as $k => $v) { 03919 if(strlen($k) && is_array($v)) { 03920 $lines .= str_repeat(chr(9),$level)."'".$k."' => ".$this->arrayToCode($v, $level); 03921 } elseif(strlen($k)) { 03922 $lines .= str_repeat(chr(9),$level)."'".$k."' => ".(t3lib_div::testInt($v) ? intval($v) : "'".t3lib_div::slashJS(trim($v),1)."'").','.chr(10); 03923 } 03924 } 03925 03926 $lines .= str_repeat(chr(9),$level-1).')'.($level-1==0 ? '':','.chr(10)); 03927 return $lines; 03928 } 03929 03937 function makeUploadArray($extKey,$conf) { 03938 $extPath = $this->getExtPath($extKey,$conf['type']); 03939 03940 if ($extPath) { 03941 03942 // Get files for extension: 03943 $fileArr = array(); 03944 $fileArr = t3lib_div::getAllFilesAndFoldersInPath($fileArr,$extPath,'',0,99,$this->excludeForPackaging); 03945 03946 // Calculate the total size of those files: 03947 $totalSize = 0; 03948 foreach($fileArr as $file) { 03949 $totalSize+=filesize($file); 03950 } 03951 03952 // If the total size is less than the upper limit, proceed: 03953 if ($totalSize < $this->maxUploadSize) { 03954 03955 // Initialize output array: 03956 $uploadArray = array(); 03957 $uploadArray['extKey'] = $extKey; 03958 $uploadArray['EM_CONF'] = $conf['EM_CONF']; 03959 $uploadArray['misc']['codelines'] = 0; 03960 $uploadArray['misc']['codebytes'] = 0; 03961 03962 $uploadArray['techInfo'] = $this->makeDetailedExtensionAnalysis($extKey,$conf,1); 03963 03964 // Read all files: 03965 foreach($fileArr as $file) { 03966 $relFileName = substr($file,strlen($extPath)); 03967 $fI = pathinfo($relFileName); 03968 if ($relFileName!='ext_emconf.php') { // This file should be dynamically written... 03969 $uploadArray['FILES'][$relFileName] = array( 03970 'name' => $relFileName, 03971 'size' => filesize($file), 03972 'mtime' => filemtime($file), 03973 'is_executable' => (TYPO3_OS=='WIN' ? 0 : is_executable($file)), 03974 'content' => t3lib_div::getUrl($file) 03975 ); 03976 if (t3lib_div::inList('php,inc',strtolower($fI['extension']))) { 03977 $uploadArray['FILES'][$relFileName]['codelines']=count(explode(chr(10),$uploadArray['FILES'][$relFileName]['content'])); 03978 $uploadArray['misc']['codelines']+=$uploadArray['FILES'][$relFileName]['codelines']; 03979 $uploadArray['misc']['codebytes']+=$uploadArray['FILES'][$relFileName]['size']; 03980 03981 // locallang*.php files: 03982 if (substr($fI['basename'],0,9)=='locallang' && strstr($uploadArray['FILES'][$relFileName]['content'],'$LOCAL_LANG')) { 03983 $uploadArray['FILES'][$relFileName]['LOCAL_LANG']=$this->getSerializedLocalLang($file,$uploadArray['FILES'][$relFileName]['content']); 03984 } 03985 } 03986 $uploadArray['FILES'][$relFileName]['content_md5'] = md5($uploadArray['FILES'][$relFileName]['content']); 03987 } 03988 } 03989 03990 // Return upload-array: 03991 return $uploadArray; 03992 } else return 'Error: Total size of uncompressed upload ('.$totalSize.') exceeds '.t3lib_div::formatSize($this->maxUploadSize); 03993 } else { 03994 return 'Error: Extension path for extension "'.$extKey.'" not found'; 03995 } 03996 } 03997 04006 function getSerializedLocalLang($file,$content) { 04007 $returnParts = explode('$LOCAL_LANG',$content,2); 04008 04009 include($file); 04010 if (is_array($LOCAL_LANG)) { 04011 $returnParts[1] = serialize($LOCAL_LANG); 04012 return $returnParts; 04013 } else { 04014 return array(); 04015 } 04016 } 04017 04018 04019 04020 04021 04022 04023 04024 04025 04026 04027 /******************************** 04028 * 04029 * Managing dependencies, conflicts, priorities, load order of extension keys 04030 * 04031 *******************************/ 04032 04042 function addExtToList($extKey,$instExtInfo) { 04043 global $TYPO3_LOADED_EXT; 04044 04045 // ext_emconf.php information: 04046 $conf = $instExtInfo[$extKey]['EM_CONF']; 04047 04048 // Get list of installed extensions and add this one. 04049 $listArr = array_keys($TYPO3_LOADED_EXT); 04050 if ($conf['priority']=='top') { 04051 array_unshift($listArr,$extKey); 04052 } else { 04053 $listArr[]=$extKey; 04054 } 04055 04056 // Manage other circumstances: 04057 $listArr = $this->managesPriorities($listArr,$instExtInfo); 04058 $listArr = $this->removeRequiredExtFromListArr($listArr); 04059 04060 // Implode unique list of extensions to load and return: 04061 $list = implode(',',array_unique($listArr)); 04062 return $list; 04063 } 04064 04073 function checkDependencies($extKey, $conf, $instExtInfo) { 04074 $content = ''; 04075 $depError = false; 04076 $msg = array(); 04077 $depsolver = t3lib_div::_POST('depsolver'); 04078 04079 foreach($conf['constraints']['depends'] as $depK => $depV) { 04080 if($depsolver['ignore'][$depK]) { 04081 $msg[] = '<br />Dependency on '.$depK.' ignored as requested. 04082 <input type="hidden" value="1" name="depsolver[ignore]['.$depK.']" />'; 04083 continue; 04084 } 04085 if($depK == 'php') { 04086 if(!$depV) continue; 04087 $versionRange = $this->splitVersionRange($depV); 04088 $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! 04089 if ($versionRange[0]!='0.0.0' && version_compare($phpv,$versionRange[0],'<')) { 04090 $msg[] = '<br />The running PHP version ('.$phpv.') is lower than required ('.$versionRange[0].')'; 04091 $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" id="checkIgnore_'.$depK.'" /> <label for="checkIgnore_'.$depK.'">Ignore this version requirement</label>'; 04092 $depError = true; 04093 continue; 04094 } elseif ($versionRange[1]!='0.0.0' && version_compare($phpv,$versionRange[1],'>')) { 04095 $msg[] = '<br />The running PHP version ('.$phpv.') is higher than allowed ('.$versionRange[1].')'; 04096 $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" id="checkIgnore_'.$depK.'" /> <label for="checkIgnore_'.$depK.'">Ignore this version requirement</label>'; 04097 $depError = true; 04098 continue; 04099 } 04100 04101 } elseif ($depK == 'typo3') { 04102 if (!$depV) continue; 04103 04104 $versionRange = $this->splitVersionRange($depV); 04105 if ($versionRange[0]!='0.0.0' && version_compare(TYPO3_version,$versionRange[0],'<')) { 04106 $msg[] = '<br />The running TYPO3 version ('.TYPO3_version.') is lower than required ('.$versionRange[0].')'; 04107 $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" id="checkIgnore_'.$depK.'" /> <label for="checkIgnore_'.$depK.'">Ignore this version requirement</label>'; 04108 $depError = true; 04109 continue; 04110 } elseif ($versionRange[1]!='0.0.0' && version_compare(TYPO3_version,$versionRange[1],'>')) { 04111 $msg[] = '<br />The running TYPO3 version ('.TYPO3_version.') is higher than allowed ('.$versionRange[1].')'; 04112 $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" id="checkIgnore_'.$depK.'" /> <label for="checkIgnore_'.$depK.'">Ignore this version requirement</label>'; 04113 $depError = true; 04114 continue; 04115 } 04116 } elseif (strlen($depK) && !t3lib_extMgm::isLoaded($depK)) { // strlen check for braindead empty dependencies coming from extensions... 04117 if(!isset($instExtInfo[$depK])) { 04118 $msg[] = '<br />Extension "'.$depK.'" was not available in the system. Please 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]['.$depK.']" id="checkIgnore_'.$depK.'" /> <label for="checkIgnore_'.$depK.'">Ignore this extension requirement</label>'; 04121 } else { 04122 $msg[] = '<br />Extension "'.$depK.'" ('.$instExtInfo[$depK]['EM_CONF']['title'].') was not installed. Please install it first.'; 04123 $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>'; 04124 $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" id="checkIgnore_'.$depK.'" /> <label for="checkIgnore_'.$depK.'">Ignore this extension requirement</label>'; 04125 } 04126 $depError = true; 04127 } else { 04128 $versionRange = $this->splitVersionRange($depV); 04129 if ($versionRange[0]!='0.0.0' && version_compare($instExtInfo[$depK]['EM_CONF']['version'],$versionRange[0],'<')) { 04130 $msg[] = '<br />The running version of extension "'.$depK.'" ('.$instExtInfo[$depK]['EM_CONF']['version'].') is lower than required ('.$versionRange[0].')'; 04131 $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" id="checkIgnore_'.$depK.'" /> <label for="checkIgnore_'.$depK.'">Ignore this version requirement</label>'; 04132 $depError = true; 04133 continue; 04134 } elseif ($versionRange[1]!='0.0.0' && version_compare($instExtInfo[$depK]['EM_CONF']['version'],$versionRange[1],'>')) { 04135 $msg[] = '<br />The running version of extension "'.$depK.'" ('.$instExtInfo[$depK]['EM_CONF']['version'].') is higher than allowed ('.$versionRange[1].')'; 04136 $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" id="checkIgnore_'.$depK.'" /> <label for="checkIgnore_'.$depK.'">Ignore this version requirement</label>'; 04137 $depError = true; 04138 continue; 04139 } 04140 } 04141 } 04142 if($depError) { 04143 $content.= $this->doc->section('Dependency Error',implode('<br />',$msg),0,1,2); 04144 } 04145 04146 // Check conflicts with other extensions: 04147 $conflictError = false; 04148 $msg = array(); 04149 foreach((array)$conf['constraints']['conflicts'] as $conflictK => $conflictV) { 04150 if($depsolver['ignore'][$conflictK]) { 04151 $msg[] = '<br />Conflict with '.$conflictK.' ignored as requested. 04152 <input type="hidden" value="1" name="depsolver[ignore]['.$conflictK.']" />'; 04153 continue; 04154 } 04155 if (t3lib_extMgm::isLoaded($conflictK)) { 04156 $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.'".'; 04157 $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>'; 04158 $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore]['.$conflictK.']" id="checkIgnore_'.$conflictK.'" /> <label for="checkIgnore_'.$conflictK.'">Ignore this conflict error</label>'; 04159 $conflictError = true; 04160 } 04161 } 04162 if($conflictError) { 04163 $content.= $this->doc->section('Conflict Error',implode('<br />',$msg),0,1,2); 04164 } 04165 04166 // Check suggests on other extensions: 04167 if(is_array($conf['constraints']['suggests'])) { 04168 $suggestion = false; 04169 $msg = array(); 04170 foreach($conf['constraints']['suggests'] as $suggestK => $suggestV) { 04171 if($depsolver['ignore'][$suggestK]) { 04172 $msg[] = '<br />Suggestion of '.$suggestK.' acknowledged. 04173 <input type="hidden" value="1" name="depsolver[ignore]['.$suggestK.']" />'; 04174 continue; 04175 } 04176 if (!t3lib_extMgm::isLoaded($suggestK)) { 04177 if (!isset($instExtInfo[$suggestK])) { 04178 $msg[] = 'Extension "'.$suggestK.'" was not available in the system. You may want to import it from the TYPO3 Extension Repository.'; 04179 $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>'; 04180 $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore]['.$suggestK.']" id="checkIgnore_'.$suggestK.'" /> <label for="checkIgnore_'.$suggestK.'">Ignore this suggestion</label>'; 04181 } else { 04182 $msg[] = 'Extension "'.$suggestK.'" ('.$instExtInfo[$suggestK]['EM_CONF']['title'].') was not installed. You may want to install it.'; 04183 $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>'; 04184 $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore]['.$suggestK.']" id="checkIgnore_'.$suggestK.'" /> <label for="checkIgnore_'.$suggestK.'">Ignore this suggestion</label>'; 04185 } 04186 $suggestion = true; 04187 } 04188 } 04189 if($suggestion) { 04190 $content .= $this->doc->section('Extensions suggested by extension "'.$extKey.'"',implode('<br />',$msg),0,1,1); 04191 } 04192 } 04193 04194 if($depError || $conflictError || $suggestion) { 04195 foreach($this->CMD as $k => $v) { 04196 $content .= '<input type="hidden" name="CMD['.$k.']" value="'.$v.'" />'; 04197 } 04198 $content .= '<br /><br /><input type="submit" value="Try again" />'; 04199 04200 return array('returnCode' => false, 'html' => $content); 04201 } 04202 04203 return array('returnCode' => true); 04204 } 04205 04215 function removeExtFromList($extKey,$instExtInfo) { 04216 global $TYPO3_LOADED_EXT; 04217 04218 // Initialize: 04219 $depList = array(); 04220 $listArr = array_keys($TYPO3_LOADED_EXT); 04221 04222 // 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! 04223 foreach($listArr as $k => $ext) { 04224 if ($instExtInfo[$ext]['EM_CONF']['dependencies']) { 04225 $dep = t3lib_div::trimExplode(',',$instExtInfo[$ext]['EM_CONF']['dependencies'],1); 04226 if (in_array($extKey,$dep)) { 04227 $depList[] = $ext; 04228 } 04229 } 04230 if (!strcmp($ext,$extKey)) unset($listArr[$k]); 04231 } 04232 04233 // Returns either error or the new list 04234 if (count($depList)) { 04235 $msg = 'The extension(s) "'.implode(', ',$depList).'" depends on the extension you are trying to remove. The operation was not completed.'; 04236 $this->content.=$this->doc->section('Dependency Error',$msg,0,1,2); 04237 return -1; 04238 } else { 04239 $listArr = $this->removeRequiredExtFromListArr($listArr); 04240 $list = implode(',',array_unique($listArr)); 04241 return $list; 04242 } 04243 } 04244 04252 function removeRequiredExtFromListArr($listArr) { 04253 foreach($listArr as $k => $ext) { 04254 if (in_array($ext,$this->requiredExt) || !strcmp($ext,'_CACHEFILE')) unset($listArr[$k]); 04255 } 04256 return $listArr; 04257 } 04258 04267 function managesPriorities($listArr,$instExtInfo) { 04268 04269 // Initialize: 04270 $levels = array( 04271 'top' => array(), 04272 'middle' => array(), 04273 'bottom' => array(), 04274 ); 04275 04276 // Traverse list of extensions: 04277 foreach($listArr as $ext) { 04278 $prio = trim($instExtInfo[$ext]['EM_CONF']['priority']); 04279 switch((string)$prio) { 04280 case 'top': 04281 case 'bottom': 04282 $levels[$prio][] = $ext; 04283 break; 04284 default: 04285 $levels['middle'][] = $ext; 04286 break; 04287 } 04288 } 04289 return array_merge( 04290 $levels['top'], 04291 $levels['middle'], 04292 $levels['bottom'] 04293 ); 04294 } 04295 04296 04297 04298 04299 04300 04301 04302 04303 04304 04305 /******************************* 04306 * 04307 * System Update functions (based on extension requirements) 04308 * 04309 ******************************/ 04310 04319 function checkClearCache($extInfo) { 04320 if ($extInfo['EM_CONF']['clearCacheOnLoad']) { 04321 if (t3lib_div::_POST('_clear_all_cache')) { // Action: Clearing the cache 04322 $tce = t3lib_div::makeInstance('t3lib_TCEmain'); 04323 $tce->stripslashes_values = 0; 04324 $tce->start(Array(),Array()); 04325 $tce->clear_cacheCmd('all'); 04326 } else { // Show checkbox for clearing cache: 04327 $content.= ' 04328 <br /> 04329 <h3>Clear cache</h3> 04330 <p>This extension requests the cache to be cleared when it is installed/removed.<br /> 04331 <label for="check_clear_all_cache">Clear all cache:</label> <input type="checkbox" name="_clear_all_cache" id="check_clear_all_cache" checked="checked" value="1" /><br /> 04332 </p> 04333 '; 04334 } 04335 } 04336 return $content; 04337 } 04338 04346 function checkUploadFolder($extKey,$extInfo) { 04347 04348 // Checking for upload folder: 04349 $uploadFolder = PATH_site.$this->ulFolder($extKey); 04350 if ($extInfo['EM_CONF']['uploadfolder'] && !@is_dir($uploadFolder)) { 04351 if (t3lib_div::_POST('_uploadfolder')) { // CREATE dir: 04352 t3lib_div::mkdir($uploadFolder); 04353 $indexContent = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> 04354 <HTML> 04355 <HEAD> 04356 <TITLE></TITLE> 04357 <META http-equiv=Refresh Content="0; Url=../../"> 04358 </HEAD> 04359 </HTML>'; 04360 t3lib_div::writeFile($uploadFolder.'index.html',$indexContent); 04361 } else { // Show checkbox / HTML for creation: 04362 $content.=' 04363 <br /><h3>Create upload folder</h3> 04364 <p>The extension requires the upload folder "'.$this->ulFolder($extKey).'" to exist.<br /> 04365 <label for="check_uploadfolder">Create directory "'.$this->ulFolder($extKey).'":</label> <input type="checkbox" name="_uploadfolder" id="check_uploadfolder" checked="checked" value="1" /><br /> 04366 </p> 04367 '; 04368 } 04369 } 04370 04371 // Additional directories that should be created: 04372 if ($extInfo['EM_CONF']['createDirs']) { 04373 $createDirs = array_unique(t3lib_div::trimExplode(',',$extInfo['EM_CONF']['createDirs'],1)); 04374 04375 foreach($createDirs as $crDir) { 04376 if (!@is_dir(PATH_site.$crDir)) { 04377 if (t3lib_div::_POST('_createDir_'.md5($crDir))) { // CREATE dir: 04378 04379 // Initialize: 04380 $crDirStart = ''; 04381 $dirs_in_path = explode('/',preg_replace('/\/$/','',$crDir)); 04382 04383 // Traverse each part of the dir path and create it one-by-one: 04384 foreach($dirs_in_path as $dirP) { 04385 if (strcmp($dirP,'')) { 04386 $crDirStart.= $dirP.'/'; 04387 if (!@is_dir(PATH_site.$crDirStart)) { 04388 t3lib_div::mkdir(PATH_site.$crDirStart); 04389 $finalDir = PATH_site.$crDirStart; 04390 } 04391 } else { 04392 die('ERROR: The path "'.PATH_site.$crDir.'" could not be created.'); 04393 } 04394 } 04395 if ($finalDir) { 04396 $indexContent = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> 04397 <HTML> 04398 <HEAD> 04399 <TITLE></TITLE> 04400 <META http-equiv=Refresh Content="0; Url=/"> 04401 </HEAD> 04402 </HTML>'; 04403 t3lib_div::writeFile($finalDir.'index.html',$indexContent); 04404 } 04405 } else { // Show checkbox / HTML for creation: 04406 $md5CrDir = md5($crDir); 04407 $content.=' 04408 <br /> 04409 <h3>Create folder</h3> 04410 <p>The extension requires the folder "'.$crDir.'" to exist.<br /> 04411 <label for="check_createDir_'.$md5CrDir.'">Create directory "'.$crDir.'":</label> <input type="checkbox" name="_createDir_'.$md5CrDir.'" id="check_createDir_'.$md5CrDir.'" checked="checked" value="1" /><br /> 04412 </p> 04413 '; 04414 } 04415 } 04416 } 04417 } 04418 04419 return $content; 04420 } 04421 04432 function checkDBupdates($extKey,$extInfo,$infoOnly=0) { 04433 04434 // Initializing Install Tool object: 04435 $instObj = new t3lib_install; 04436 $instObj->INSTALL = t3lib_div::_GP('TYPO3_INSTALL'); 04437 $dbStatus = array(); 04438 04439 // Updating tables and fields? 04440 if (is_array($extInfo['files']) && in_array('ext_tables.sql',$extInfo['files'])) { 04441 $fileContent = t3lib_div::getUrl($this->getExtPath($extKey,$extInfo['type']).'ext_tables.sql'); 04442 04443 $FDfile = $instObj->getFieldDefinitions_sqlContent($fileContent); 04444 if (count($FDfile)) { 04445 $FDdb = $instObj->getFieldDefinitions_database(TYPO3_db); 04446 $diff = $instObj->getDatabaseExtra($FDfile, $FDdb); 04447 $update_statements = $instObj->getUpdateSuggestions($diff); 04448 04449 $dbStatus['structure']['tables_fields'] = $FDfile; 04450 $dbStatus['structure']['diff'] = $diff; 04451 04452 // Updating database... 04453 if (!$infoOnly && is_array($instObj->INSTALL['database_update'])) { 04454 $instObj->performUpdateQueries($update_statements['add'],$instObj->INSTALL['database_update']); 04455 $instObj->performUpdateQueries($update_statements['change'],$instObj->INSTALL['database_update']); 04456 $instObj->performUpdateQueries($update_statements['create_table'],$instObj->INSTALL['database_update']); 04457 } else { 04458 $content.=$instObj->generateUpdateDatabaseForm_checkboxes($update_statements['add'],'Add fields'); 04459 $content.=$instObj->generateUpdateDatabaseForm_checkboxes($update_statements['change'],'Changing fields',1,0,$update_statements['change_currentValue']); 04460 $content.=$instObj->generateUpdateDatabaseForm_checkboxes($update_statements['create_table'],'Add tables'); 04461 } 04462 } 04463 } 04464 04465 // Importing static tables? 04466 if (is_array($extInfo['files']) && in_array('ext_tables_static+adt.sql',$extInfo['files'])) { 04467 $fileContent = t3lib_div::getUrl($this->getExtPath($extKey,$extInfo['type']).'ext_tables_static+adt.sql'); 04468 04469 $statements = $instObj->getStatementArray($fileContent,1); 04470 list($statements_table, $insertCount) = $instObj->getCreateTables($statements,1); 04471 04472 // Execute import of static table content: 04473 if (!$infoOnly && is_array($instObj->INSTALL['database_import'])) { 04474 04475 // Traverse the tables 04476 foreach($instObj->INSTALL['database_import'] as $table => $md5str) { 04477 if ($md5str == md5($statements_table[$table])) { 04478 $GLOBALS['TYPO3_DB']->admin_query('DROP TABLE IF EXISTS '.$table); 04479 $GLOBALS['TYPO3_DB']->admin_query($statements_table[$table]); 04480 04481 if ($insertCount[$table]) { 04482 $statements_insert = $instObj->getTableInsertStatements($statements, $table); 04483 04484 foreach($statements_insert as $v) { 04485 $GLOBALS['TYPO3_DB']->admin_query($v); 04486 } 04487 } 04488 } 04489 } 04490 } else { 04491 $whichTables = $instObj->getListOfTables(); 04492 if (count($statements_table)) { 04493 $out = ''; 04494 foreach($statements_table as $table => $definition) { 04495 $exist = isset($whichTables[$table]); 04496 04497 $dbStatus['static'][$table]['exists'] = $exist; 04498 $dbStatus['static'][$table]['count'] = $insertCount[$table]; 04499 04500 $out.= '<tr> 04501 <td><input type="checkbox" name="TYPO3_INSTALL[database_import]['.$table.']" checked="checked" value="'.md5($definition).'" /></td> 04502 <td><strong>'.$table.'</strong></td> 04503 <td><img src="clear.gif" width="10" height="1" alt="" /></td> 04504 <td nowrap="nowrap">'.($insertCount[$table]?'Rows: '.$insertCount[$table]:'').'</td> 04505 <td><img src="clear.gif" width="10" height="1" alt="" /></td> 04506 <td nowrap="nowrap">'.($exist?'<img src="'.$GLOBALS['BACK_PATH'].'gfx/icon_warning.gif" width="18" height="16" align="top" alt="" />Table exists!':'').'</td> 04507 </tr>'; 04508 } 04509 $content.= ' 04510 <br /> 04511 <h3>Import static data</h3> 04512 <table border="0" cellpadding="0" cellspacing="0">'.$out.'</table>'; 04513 } 04514 } 04515 } 04516 04517 // Return array of information if $infoOnly, otherwise content. 04518 return $infoOnly ? $dbStatus : $content; 04519 } 04520 04529 function forceDBupdates($extKey, $extInfo) { 04530 $instObj = new t3lib_install; 04531 04532 // Updating tables and fields? 04533 if (is_array($extInfo['files']) && in_array('ext_tables.sql',$extInfo['files'])) { 04534 $fileContent = t3lib_div::getUrl($this->getExtPath($extKey,$extInfo['type']).'ext_tables.sql'); 04535 04536 $FDfile = $instObj->getFieldDefinitions_sqlContent($fileContent); 04537 if (count($FDfile)) { 04538 $FDdb = $instObj->getFieldDefinitions_database(TYPO3_db); 04539 $diff = $instObj->getDatabaseExtra($FDfile, $FDdb); 04540 $update_statements = $instObj->getUpdateSuggestions($diff); 04541 04542 foreach((array)$update_statements['add'] as $string) { 04543 $GLOBALS['TYPO3_DB']->admin_query($string); 04544 } 04545 foreach((array)$update_statements['change'] as $string) { 04546 $GLOBALS['TYPO3_DB']->admin_query($string); 04547 } 04548 foreach((array)$update_statements['create_table'] as $string) { 04549 $GLOBALS['TYPO3_DB']->admin_query($string); 04550 } 04551 } 04552 } 04553 04554 // Importing static tables? 04555 if (is_array($extInfo['files']) && in_array('ext_tables_static+adt.sql',$extInfo['files'])) { 04556 $fileContent = t3lib_div::getUrl($this->getExtPath($extKey,$extInfo['type']).'ext_tables_static+adt.sql'); 04557 04558 $statements = $instObj->getStatementArray($fileContent,1); 04559 list($statements_table, $insertCount) = $instObj->getCreateTables($statements,1); 04560 04561 // Traverse the tables 04562 foreach($statements_table as $table => $query) { 04563 $GLOBALS['TYPO3_DB']->admin_query('DROP TABLE IF EXISTS '.$table); 04564 $GLOBALS['TYPO3_DB']->admin_query($query); 04565 04566 if ($insertCount[$table]) { 04567 $statements_insert = $instObj->getTableInsertStatements($statements, $table); 04568 04569 foreach($statements_insert as $v) { 04570 $GLOBALS['TYPO3_DB']->admin_query($v); 04571 } 04572 } 04573 } 04574 } 04575 } 04576 04587 function tsStyleConfigForm($extKey,$extInfo,$output=0,$script='',$addFields='') { 04588 global $TYPO3_CONF_VARS; 04589 04590 // Initialize: 04591 $absPath = $this->getExtPath($extKey,$extInfo['type']); 04592 $relPath = $this->typeRelPaths[$extInfo['type']].$extKey.'/'; 04593 04594 // Look for template file for form: 04595 if (@is_file($absPath.'ext_conf_template.txt')) { 04596 04597 // Load tsStyleConfig class and parse configuration template: 04598 $tsStyleConfig = t3lib_div::makeInstance('t3lib_tsStyleConfig'); 04599 $tsStyleConfig->doNotSortCategoriesBeforeMakingForm = TRUE; 04600 $theConstants = $tsStyleConfig->ext_initTSstyleConfig( 04601 t3lib_div::getUrl($absPath.'ext_conf_template.txt'), 04602 $relPath, 04603 $absPath, 04604 $GLOBALS['BACK_PATH'] 04605 ); 04606 04607 // Load the list of resources. 04608 $tsStyleConfig->ext_loadResources($absPath.'res/'); 04609 04610 // Load current value: 04611 $arr = unserialize($TYPO3_CONF_VARS['EXT']['extConf'][$extKey]); 04612 $arr = is_array($arr) ? $arr : array(); 04613 04614 // Call processing function for constants config and data before write and form rendering: 04615 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/mod/tools/em/index.php']['tsStyleConfigForm'])) { 04616 $_params = array('fields' => &$theConstants, 'data' => &$arr, 'extKey' => $extKey); 04617 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/mod/tools/em/index.php']['tsStyleConfigForm'] as $_funcRef) { 04618 t3lib_div::callUserFunction($_funcRef,$_params,$this); 04619 } 04620 unset($_params); 04621 } 04622 04623 // If saving operation is done: 04624 if (t3lib_div::_POST('submit')) { 04625 $tsStyleConfig->ext_procesInput(t3lib_div::_POST(),array(),$theConstants,array()); 04626 $arr = $tsStyleConfig->ext_mergeIncomingWithExisting($arr); 04627 $this->writeTsStyleConfig($extKey,$arr); 04628 } 04629 04630 // Setting value array 04631 $tsStyleConfig->ext_setValueArray($theConstants,$arr); 04632 04633 // Getting session data: 04634 $MOD_MENU = array(); 04635 $MOD_MENU['constant_editor_cat'] = $tsStyleConfig->ext_getCategoriesForModMenu(); 04636 $MOD_SETTINGS = t3lib_BEfunc::getModuleData($MOD_MENU, t3lib_div::_GP('SET'), 'xMod_test'); 04637 04638 // Resetting the menu (stop) 04639 if (count($MOD_MENU)>1) { 04640 $menu = 'Category: '.t3lib_BEfunc::getFuncMenu(0,'SET[constant_editor_cat]',$MOD_SETTINGS['constant_editor_cat'],$MOD_MENU['constant_editor_cat'],'','&CMD[showExt]='.$extKey); 04641 $this->content.=$this->doc->section('','<span class="nobr">'.$menu.'</span>'); 04642 $this->content.=$this->doc->spacer(10); 04643 } 04644 04645 // Category and constant editor config: 04646 $form = ' 04647 <table border="0" cellpadding="0" cellspacing="0" width="600"> 04648 <tr> 04649 <td>'.$tsStyleConfig->ext_getForm($MOD_SETTINGS['constant_editor_cat'],$theConstants,$script,$addFields).'</td> 04650 </tr> 04651 </table>'; 04652 if ($output) { 04653 return $form; 04654 } else { 04655 $this->content.=$this->doc->section('','</form>'.$form.'<form>'); 04656 } 04657 } 04658 } 04659 04660 04661 04662 04663 04664 04665 04666 04667 04668 04669 /******************************* 04670 * 04671 * Dumping database (MySQL compliant) 04672 * 04673 ******************************/ 04674 04682 function dumpTableAndFieldStructure($arr) { 04683 $tables = array(); 04684 04685 if (count($arr)) { 04686 04687 // Get file header comment: 04688 $tables[] = $this->dumpHeader(); 04689 04690 // Traverse tables, write each table/field definition: 04691 foreach($arr as $table => $fieldKeyInfo) { 04692 $tables[] = $this->dumpTableHeader($table,$fieldKeyInfo); 04693 } 04694 } 04695 04696 // Return result: 04697 return implode(chr(10).chr(10).chr(10),$tables); 04698 } 04699 04707 function dumpStaticTables($tableList) { 04708 $instObj = new t3lib_install; 04709 $dbFields = $instObj->getFieldDefinitions_database(TYPO3_db); 04710 04711 $out = ''; 04712 $parts = t3lib_div::trimExplode(',',$tableList,1); 04713 04714 // Traverse the table list and dump each: 04715 foreach($parts as $table) { 04716 if (is_array($dbFields[$table]['fields'])) { 04717 $dHeader = $this->dumpHeader(); 04718 $header = $this->dumpTableHeader($table,$dbFields[$table],1); 04719 $insertStatements = $this->dumpTableContent($table,$dbFields[$table]['fields']); 04720 04721 $out.= $dHeader.chr(10).chr(10).chr(10). 04722 $header.chr(10).chr(10).chr(10). 04723 $insertStatements.chr(10).chr(10).chr(10); 04724 } else { 04725 die('Fatal error: Table for dump not found in database...'); 04726 } 04727 } 04728 return $out; 04729 } 04730 04736 function dumpHeader() { 04737 return trim(' 04738 # TYPO3 Extension Manager dump 1.1 04739 # 04740 # Host: '.TYPO3_db_host.' Database: '.TYPO3_db.' 04741 #-------------------------------------------------------- 04742 '); 04743 } 04744 04753 function dumpTableHeader($table,$fieldKeyInfo,$dropTableIfExists=0) { 04754 $lines = array(); 04755 $dump = ''; 04756 04757 // Create field definitions 04758 if (is_array($fieldKeyInfo['fields'])) { 04759 foreach($fieldKeyInfo['fields'] as $fieldN => $data) { 04760 $lines[]=' '.$fieldN.' '.$data; 04761 } 04762 } 04763 04764 // Create index key definitions 04765 if (is_array($fieldKeyInfo['keys'])) { 04766 foreach($fieldKeyInfo['keys'] as $fieldN => $data) { 04767 $lines[]=' '.$data; 04768 } 04769 } 04770 04771 // Compile final output: 04772 if (count($lines)) { 04773 $dump = trim(' 04774 # 04775 # Table structure for table "'.$table.'" 04776 # 04777 '.($dropTableIfExists ? 'DROP TABLE IF EXISTS '.$table.'; 04778 ' : '').'CREATE TABLE '.$table.' ( 04779 '.implode(','.chr(10),$lines).' 04780 );' 04781 ); 04782 } 04783 04784 return $dump; 04785 } 04786 04795 function dumpTableContent($table,$fieldStructure) { 04796 04797 // Substitution of certain characters (borrowed from phpMySQL): 04798 $search = array('\\', '\'', "\x00", "\x0a", "\x0d", "\x1a"); 04799 $replace = array('\\\\', '\\\'', '\0', '\n', '\r', '\Z'); 04800 04801 $lines = array(); 04802 04803 // Select all rows from the table: 04804 $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $table, ''); 04805 04806 // Traverse the selected rows and dump each row as a line in the file: 04807 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) { 04808 $values = array(); 04809 reset($fieldStructure); 04810 while(list($field) = each($fieldStructure)) { 04811 $values[] = isset($row[$field]) ? "'".str_replace($search, $replace, $row[$field])."'" : 'NULL'; 04812 } 04813 $lines[] = 'INSERT INTO '.$table.' VALUES ('.implode(', ',$values).');'; 04814 } 04815 04816 // Free DB result: 04817 $GLOBALS['TYPO3_DB']->sql_free_result($result); 04818 04819 // Implode lines and return: 04820 return implode(chr(10),$lines); 04821 } 04822 04830 function getTableAndFieldStructure($parts) { 04831 // Instance of install tool 04832 $instObj = new t3lib_install; 04833 $dbFields = $instObj->getFieldDefinitions_database(TYPO3_db); 04834 04835 04836 $outTables = array(); 04837 foreach($parts as $table) { 04838 $tP = explode('.',$table); 04839 if ($tP[0] && isset($dbFields[$tP[0]])) { 04840 if ($tP[1]) { 04841 $kfP = explode('KEY:',$tP[1],2); 04842 if (count($kfP)==2 && !$kfP[0]) { // key: 04843 if (isset($dbFields[$tP[0]]['keys'][$kfP[1]])) $outTables[$tP[0]]['keys'][$kfP[1]] = $dbFields[$tP[0]]['keys'][$kfP[1]]; 04844 } else { 04845 if (isset($dbFields[$tP[0]]['fields'][$tP[1]])) $outTables[$tP[0]]['fields'][$tP[1]] = $dbFields[$tP[0]]['fields'][$tP[1]]; 04846 } 04847 } else { 04848 $outTables[$tP[0]] = $dbFields[$tP[0]]; 04849 } 04850 } 04851 } 04852 04853 return $outTables; 04854 } 04855 04856 04857 04858 04859 04860 04861 04862 04863 04864 04865 /******************************* 04866 * 04867 * TER Communication functions 04868 * 04869 ******************************/ 04870 04871 04872 04880 function uploadExtensionToTER($em) { 04881 $msg = ''; 04882 $response = $this->terConnection->uploadToTER($em); 04883 04884 if(!is_array($response)) return $response; 04885 04886 if($response['resultCode']==TX_TER_RESULT_EXTENSIONSUCCESSFULLYUPLOADED) { 04887 $em['extInfo']['EM_CONF']['version'] = $response['version']; 04888 $response['resultMessages'][] = 'The extension is now version: '.$response['version']; 04889 $response['resultMessages'][] = $this->updateLocalEM_CONF($em['extKey'],$em['extInfo']); 04890 } 04891 04892 $msg = '<ul><li>'.implode('</li><li>',$response['resultMessages']).'</li></ul>'; 04893 return $msg; 04894 } 04895 04896 04897 04898 04899 04900 04901 04902 04903 04904 04905 /************************************ 04906 * 04907 * Various helper functions 04908 * 04909 ************************************/ 04910 04918 function listOrderTitle($listOrder,$key) { 04919 switch($listOrder) { 04920 case 'cat': 04921 return isset($this->categories[$key])?$this->categories[$key]:'<em>['.$key.']</em>'; 04922 break; 04923 case 'author_company': 04924 return $key; 04925 break; 04926 case 'state': 04927 return $this->states[$key]; 04928 break; 04929 case 'type': 04930 return $this->typeDescr[$key]; 04931 break; 04932 } 04933 } 04934 04943 function makeVersion($v,$mode) { 04944 $vDat = $this->renderVersion($v); 04945 return $vDat['version_'.$mode]; 04946 } 04947 04955 function renderVersion($v,$raise='') { 04956 $parts = t3lib_div::intExplode('.',$v.'..'); 04957 $parts[0] = t3lib_div::intInRange($parts[0],0,999); 04958 $parts[1] = t3lib_div::intInRange($parts[1],0,999); 04959 $parts[2] = t3lib_div::intInRange($parts[2],0,999); 04960 04961 switch((string)$raise) { 04962 case 'main': 04963 $parts[0]++; 04964 $parts[1]=0; 04965 $parts[2]=0; 04966 break; 04967 case 'sub': 04968 $parts[1]++; 04969 $parts[2]=0; 04970 break; 04971 case 'dev': 04972 $parts[2]++; 04973 break; 04974 } 04975 04976 $res = array(); 04977 $res['version'] = $parts[0].'.'.$parts[1].'.'.$parts[2]; 04978 $res['version_int'] = intval($parts[0]*1000000+$parts[1]*1000+$parts[2]); 04979 $res['version_main'] = $parts[0]; 04980 $res['version_sub'] = $parts[1]; 04981 $res['version_dev'] = $parts[2]; 04982 04983 return $res; 04984 } 04985 04992 function ulFolder($extKey) { 04993 return 'uploads/tx_'.str_replace('_','',$extKey).'/'; 04994 } 04995 05001 function importAtAll() { 05002 return ($GLOBALS['TYPO3_CONF_VARS']['EXT']['allowGlobalInstall'] || $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowLocalInstall']); 05003 } 05004 05012 function importAsType($type,$lockType='') { 05013 switch($type) { 05014 case 'G': 05015 return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowGlobalInstall'] && (!$lockType || !strcmp($lockType,$type)); 05016 break; 05017 case 'L': 05018 return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowLocalInstall'] && (!$lockType || !strcmp($lockType,$type)); 05019 break; 05020 case 'S': 05021 return $this->systemInstall; 05022 break; 05023 default: 05024 return false; 05025 } 05026 } 05027 05034 function deleteAsType($type) { 05035 switch($type) { 05036 case 'G': 05037 return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowGlobalInstall']; 05038 break; 05039 case 'L': 05040 return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowLocalInstall']; 05041 break; 05042 default: 05043 return false; 05044 } 05045 } 05046 05055 function versionDifference($v1,$v2,$div=1) { 05056 return floor($this->makeVersion($v1,'int')/$div) > floor($this->makeVersion($v2,'int')/$div); 05057 } 05058 05067 function first_in_array($str,$array,$caseInsensitive=FALSE) { 05068 if ($caseInsensitive) $str = strtolower($str); 05069 if (is_array($array)) { 05070 foreach($array as $cl) { 05071 if ($caseInsensitive) $cl = strtolower($cl); 05072 if (t3lib_div::isFirstPartOfStr($cl,$str)) return true; 05073 } 05074 } 05075 return false; 05076 } 05077 05085 function includeEMCONF($path,$_EXTKEY) { 05086 @include($path); 05087 if(is_array($EM_CONF[$_EXTKEY])) { 05088 return $this->fixEMCONF($EM_CONF[$_EXTKEY]); 05089 } 05090 return false; 05091 } 05092 05100 function searchExtension($extKey,$row) { 05101 if ($this->lookUpStr) { 05102 return ( 05103 stristr($extKey,$this->lookUpStr) || 05104 stristr($row['EM_CONF']['title'],$this->lookUpStr) || 05105 stristr($row['EM_CONF']['description'],$this->lookUpStr) || 05106 stristr($row['EM_CONF']['author'],$this->lookUpStr) || 05107 stristr($row['EM_CONF']['author_company'],$this->lookUpStr) 05108 ); 05109 } else return true; 05110 } 05111 } 05112 05113 // Include extension? 05114 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/mod/tools/em/index.php']) { 05115 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/mod/tools/em/index.php']); 05116 } 05117 05118 ?>