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