Documentation TYPO3 par Ameos |
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 1999-2005 Kasper Skaarhoj (kasperYYYY@typo3.com) 00006 * All rights reserved 00007 * 00008 * This script is part of the TYPO3 project. The TYPO3 project is 00009 * free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * The GNU General Public License can be found at 00015 * http://www.gnu.org/copyleft/gpl.html. 00016 * A copy is found in the textfile GPL.txt and important notices to the license 00017 * from the author is found in LICENSE.txt distributed with these scripts. 00018 * 00019 * 00020 * This script is distributed in the hope that it will be useful, 00021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 * GNU General Public License for more details. 00024 * 00025 * This copyright notice MUST APPEAR in all copies of the script! 00026 ***************************************************************/ 00166 unset($MCONF); 00167 require ('conf.php'); 00168 require ($BACK_PATH.'init.php'); 00169 require ($BACK_PATH.'template.php'); 00170 $BE_USER->modAccess($MCONF,1); 00171 00172 // Include classes needed: 00173 require_once(PATH_t3lib.'class.t3lib_tcemain.php'); 00174 require_once(PATH_t3lib.'class.t3lib_install.php'); 00175 require_once(PATH_t3lib.'class.t3lib_tsstyleconfig.php'); 00176 require_once(PATH_t3lib.'class.t3lib_scbase.php'); 00177 00178 00179 00180 00181 00182 00183 00191 class SC_mod_tools_em_index extends t3lib_SCbase { 00192 00193 // Internal, static: 00194 var $versionDiffFactor = 1000; // This means that version difference testing for import is detected for sub-versions only, not dev-versions. Default: 1000 00195 var $systemInstall = 0; // If "1" then installs in the sysext directory is allowed. Default: 0 00196 var $repositoryUrl = ''; // Default is "http://ter.typo3.com/?id=t3_extrep" configured in config_default.php 00197 var $requiredExt = ''; // List of required extension (from TYPO3_CONF_VARS) 00198 var $maxUploadSize = 6024000; // Max size of extension upload to repository 00199 var $kbMax = 100; // Max size in kilobytes for files to be edited. 00200 00205 var $defaultCategories = Array( 00206 'cat' => Array ( 00207 'be' => array(), 00208 'module' => array(), 00209 'fe' => array(), 00210 'plugin' => array(), 00211 'misc' => array(), 00212 'services' => array(), 00213 'templates' => array(), 00214 'example' => array(), 00215 'doc' => array() 00216 ) 00217 ); 00218 00223 var $categories = Array( 00224 'be' => 'Backend', 00225 'module' => 'Backend Modules', 00226 'fe' => 'Frontend', 00227 'plugin' => 'Frontend Plugins', 00228 'misc' => 'Miscellaneous', 00229 'services' => 'Services', 00230 'templates' => 'Templates', 00231 'example' => 'Examples', 00232 'doc' => 'Documentation' 00233 ); 00234 00239 var $states = Array ( 00240 'alpha' => 'Alpha', 00241 'beta' => 'Beta', 00242 'stable' => 'Stable', 00243 'experimental' => 'Experimental', 00244 'test' => 'Test', 00245 'obsolete' => 'Obsolete', 00246 ); 00247 00251 var $typeLabels = Array ( 00252 'S' => 'System', 00253 'G' => 'Global', 00254 'L' => 'Local', 00255 ); 00256 var $typeDescr = Array ( 00257 'S' => 'System extension (typo3/sysext/) - Always distributed with source code (Static).', 00258 'G' => 'Global extensions (typo3/ext/) - Available for shared source on server (Dynamic).', 00259 'L' => 'Local extensions (typo3conf/ext/) - Local for this TYPO3 installation only (Dynamic).', 00260 ); 00261 var $typePaths = Array(); // Also static, set in init() 00262 var $typeBackPaths = Array(); // Also static, set in init() 00263 00264 var $typeRelPaths = Array ( 00265 'S' => 'sysext/', 00266 'G' => 'ext/', 00267 'L' => '../typo3conf/ext/', 00268 ); 00269 00273 var $remoteAccess = Array ( 00274 'all' => '', 00275 'owner' => 'Owner', 00276 'selected' => 'Selected', 00277 'member' => 'Member', 00278 ); 00279 00280 var $detailCols = Array ( 00281 0 => 2, 00282 1 => 5, 00283 2 => 6, 00284 3 => 6, 00285 4 => 4, 00286 5 => 1 00287 ); 00288 00289 var $fe_user = array( 00290 'username' => '', 00291 'password' => '', 00292 'uploadPass' => '', 00293 ); 00294 00295 var $privacyNotice = 'When ever you interact with the online repository, server information is sent and stored in the repository for statistics. No personal information is sent, only identification of this TYPO3 install. If you want know exactly what is sent, look in typo3/mod/tools/em/index.php, function repTransferParams()'; 00296 var $editTextExtensions = 'html,htm,txt,css,tmpl,inc,php,sql,conf,cnf,pl,pm,sh,xml,ChangeLog'; 00297 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'; 00298 00299 00300 00301 00302 00303 // Default variables for backend modules 00304 var $MCONF = array(); // Module configuration 00305 var $MOD_MENU = array(); // Module menu items 00306 var $MOD_SETTINGS = array(); // Module session settings 00307 var $doc; // Document Template Object 00308 var $content; // Accumulated content 00309 00310 var $inst_keys = array(); // Storage of installed extensions 00311 var $gzcompress = 0; // Is set true, if system support compression. 00312 00313 // GPvars: 00314 var $CMD = array(); // CMD array 00315 var $listRemote; // If set, connects to remote repository 00316 var $lookUpStr; // Search string when listing local extensions 00317 00318 00319 00320 00321 00322 00323 00324 00325 00326 00327 00328 00329 00330 /********************************* 00331 * 00332 * Standard module initialization 00333 * 00334 *********************************/ 00335 00341 function init() { 00342 global $BE_USER,$LANG,$BACK_PATH,$TYPO3_CONF_VARS; 00343 00344 // Setting paths of install scopes: 00345 $this->typePaths = Array ( 00346 'S' => TYPO3_mainDir.'sysext/', 00347 'G' => TYPO3_mainDir.'ext/', 00348 'L' => 'typo3conf/ext/' 00349 ); 00350 $this->typeBackPaths = Array ( 00351 'S' => '../../../', 00352 'G' => '../../../', 00353 'L' => '../../../../'.TYPO3_mainDir 00354 ); 00355 00356 // Setting module configuration: 00357 $this->MCONF = $GLOBALS['MCONF']; 00358 00359 // Setting GPvars: 00360 $this->CMD = t3lib_div::_GP('CMD'); 00361 $this->lookUpStr = t3lib_div::_GP('_lookUp'); 00362 $this->listRemote = t3lib_div::_GP('ter_connect'); 00363 $this->listRemote_search = t3lib_div::_GP('ter_search'); 00364 00365 00366 // Configure menu 00367 $this->menuConfig(); 00368 00369 // Setting internal static: 00370 $this->gzcompress = function_exists('gzcompress'); 00371 if ($TYPO3_CONF_VARS['EXT']['em_devVerUpdate']) $this->versionDiffFactor = 1; 00372 if ($TYPO3_CONF_VARS['EXT']['em_systemInstall']) $this->systemInstall = 1; 00373 $this->repositoryUrl = $TYPO3_CONF_VARS['EXT']['em_TERurls'][0]; 00374 $this->requiredExt = t3lib_div::trimExplode(',',$TYPO3_CONF_VARS['EXT']['requiredExt'],1); 00375 00376 // Initialize Document Template object: 00377 $this->doc = t3lib_div::makeInstance('noDoc'); 00378 $this->doc->backPath = $BACK_PATH; 00379 $this->doc->docType = 'xhtml_trans'; 00380 00381 // JavaScript 00382 $this->doc->JScode = $this->doc->wrapScriptTags(' 00383 script_ended = 0; 00384 function jumpToUrl(URL) { // 00385 document.location = URL; 00386 } 00387 '); 00388 $this->doc->form = '<form action="index.php" method="post" name="pageform">'; 00389 00390 // Descriptions: 00391 $this->descrTable = '_MOD_'.$this->MCONF['name']; 00392 if ($BE_USER->uc['edit_showFieldHelp']) { 00393 $LANG->loadSingleTableDescription($this->descrTable); 00394 } 00395 00396 // Setting username/password etc. for upload-user: 00397 $this->fe_user['username'] = $this->MOD_SETTINGS['fe_u']; 00398 $this->fe_user['password'] = $this->MOD_SETTINGS['fe_p']; 00399 $this->fe_user['uploadPass'] = $this->MOD_SETTINGS['fe_up']; 00400 parent::init(); 00401 $this->handleExternalFunctionValue('singleDetails'); 00402 } 00403 00415 function handleExternalFunctionValue($MM_key='function', $MS_value=NULL) { 00416 $MS_value = is_null($MS_value) ? $this->MOD_SETTINGS[$MM_key] : $MS_value; 00417 $externalItems = $this->getExternalItemConfig($this->MCONF['name'],$MM_key,$MS_value); 00418 if (is_array($externalItems)) $this->extClassConf = array_merge($externalItems,is_array($this->extClassConf)?$this->extClassConf:array()); 00419 if (is_array($this->extClassConf) && $this->extClassConf['path']) { 00420 $this->include_once[]=$this->extClassConf['path']; 00421 } 00422 } 00423 00429 function menuConfig() { 00430 global $BE_USER; 00431 00432 // MENU-ITEMS: 00433 $this->MOD_MENU = array( 00434 'function' => array( 00435 0 => 'Loaded extensions', 00436 1 => 'Available extensions to install', 00437 2 => 'Import extensions from online repository', 00438 3 => 'Settings', 00439 ), 00440 'listOrder' => array( 00441 'cat' => 'Category', 00442 'author_company' => 'Author', 00443 'state' => 'State', 00444 'private' => 'Private', 00445 'type' => 'Type', 00446 'dep' => 'Dependencies', 00447 ), 00448 'display_details' => array( 00449 1 => 'Details', 00450 0 => 'Description', 00451 2 => 'More details', 00452 00453 3 => 'Technical (takes time!)', 00454 4 => 'Validating (takes time!)', 00455 5 => 'Changed? (takes time!)', 00456 ), 00457 'display_shy' => '', 00458 'own_member_only' => '', 00459 'singleDetails' => array( 00460 'info' => 'Information', 00461 'edit' => 'Edit files', 00462 'backup' => 'Backup/Delete', 00463 'dump' => 'Dump DB', 00464 'upload' => 'Upload', 00465 'updateModule' => 'UPDATE!', 00466 ), 00467 'fe_u' => '', 00468 'fe_p' => '', 00469 'fe_up' => '', 00470 ); 00471 00472 $this->MOD_MENU['singleDetails'] = $this->mergeExternalItems($this->MCONF['name'],'singleDetails',$this->MOD_MENU['singleDetails']); 00473 00474 // page/be_user TSconfig settings and blinding of menu-items 00475 if (!$BE_USER->getTSConfigVal('mod.'.$this->MCONF['name'].'.allowTVlisting')) { 00476 unset($this->MOD_MENU['display_details'][3]); 00477 unset($this->MOD_MENU['display_details'][4]); 00478 unset($this->MOD_MENU['display_details'][5]); 00479 } 00480 00481 // CLEANSE SETTINGS 00482 $this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::_GP('SET'), $this->MCONF['name']); 00483 00484 if ($this->MOD_SETTINGS['function']==2) { 00485 // If listing from online repository, certain items are removed though: 00486 unset($this->MOD_MENU['listOrder']['type']); 00487 unset($this->MOD_MENU['listOrder']['private']); 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 $this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::_GP('SET'), $this->MCONF['name']); 00492 } 00493 parent::menuConfig(); 00494 } 00495 00501 function main() { 00502 global $BE_USER,$LANG; 00503 00504 // Starting page: 00505 $this->content.=$this->doc->startPage('Extension Manager'); 00506 $this->content.=$this->doc->header('Extension Manager'); 00507 $this->content.=$this->doc->spacer(5); 00508 00509 00510 // Commands given which is executed regardless of main menu setting: 00511 if ($this->CMD['showExt']) { // Show details for a single extension 00512 $this->showExtDetails($this->CMD['showExt']); 00513 } elseif ($this->CMD['importExt'] || $this->CMD['uploadExt']) { // Imports an extension from online rep. 00514 $err = $this->importExtFromRep($this->CMD['importExt'],$this->CMD['loc'],$this->CMD['uploadExt'],'',$this->CMD['transl'],$this->CMD['inc_manual']); 00515 if ($err) { 00516 $this->content.=$this->doc->section('',$GLOBALS['TBE_TEMPLATE']->rfw($err)); 00517 } 00518 } elseif ($this->CMD['importExtInfo']) { // Gets detailed information of an extension from online rep. 00519 $this->importExtInfo($this->CMD['importExtInfo']); 00520 } else { // No command - we show what the menu setting tells us: 00521 00522 $menu = $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.menu').' '. 00523 t3lib_BEfunc::getFuncMenu(0,'SET[function]',$this->MOD_SETTINGS['function'],$this->MOD_MENU['function']); 00524 00525 if (t3lib_div::inList('0,1,2',$this->MOD_SETTINGS['function'])) { 00526 $menu.=' Order by: '.t3lib_BEfunc::getFuncMenu(0,'SET[listOrder]',$this->MOD_SETTINGS['listOrder'],$this->MOD_MENU['listOrder']). 00527 ' Show: '.t3lib_BEfunc::getFuncMenu(0,'SET[display_details]',$this->MOD_SETTINGS['display_details'],$this->MOD_MENU['display_details']). 00528 '<br />Display shy extensions: '.t3lib_BEfunc::getFuncCheck(0,'SET[display_shy]',$this->MOD_SETTINGS['display_shy']); 00529 } 00530 00531 if ($this->MOD_SETTINGS['function']==2) { 00532 $menu.=' Get own/member/selected extensions only: '. 00533 t3lib_BEfunc::getFuncCheck(0,'SET[own_member_only]',$this->MOD_SETTINGS['own_member_only']); 00534 } 00535 00536 $this->content.=$this->doc->section('','<span class="nobr">'.$menu.'</span>'); 00537 $this->content.=$this->doc->spacer(10); 00538 00539 switch((string)$this->MOD_SETTINGS['function']) { 00540 case '0': 00541 // Lists loaded (installed) extensions 00542 $this->extensionList_loaded(); 00543 break; 00544 case '1': 00545 // Lists the installed (available) extensions 00546 $this->extensionList_installed(); 00547 break; 00548 case '2': 00549 // Lists the extensions available from online rep. 00550 $this->extensionList_import(); 00551 break; 00552 case '3': 00553 // Lists the extensions available from online rep. 00554 $this->alterSettings(); 00555 break; 00556 default: 00557 $this->extObjContent(); 00558 break; 00559 } 00560 } 00561 00562 // Shortcuts: 00563 if ($BE_USER->mayMakeShortcut()) { 00564 $this->content.=$this->doc->spacer(20).$this->doc->section('',$this->doc->makeShortcutIcon('CMD','function',$this->MCONF['name'])); 00565 } 00566 } 00567 00573 function printContent() { 00574 global $SOBE; 00575 00576 $this->content.= $this->doc->endPage(); 00577 echo $this->content; 00578 } 00579 00580 00581 00582 00583 00584 00585 00586 00587 00588 00589 /********************************* 00590 * 00591 * Function Menu Applications 00592 * 00593 *********************************/ 00594 00600 function extensionList_loaded() { 00601 global $TYPO3_LOADED_EXT; 00602 00603 list($list) = $this->getInstalledExtensions(); 00604 00605 // Loaded extensions 00606 $content = ''; 00607 $lines = array(); 00608 $lines[] = $this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="1" height="1" alt="" /></td>')); 00609 00610 foreach($TYPO3_LOADED_EXT as $extKey => $eConf) { 00611 if (strcmp($extKey, '_CACHEFILE')) { 00612 if (($this->MOD_SETTINGS['display_shy'] || !$list[$extKey]['EM_CONF']['shy']) && $this->searchExtension($extKey,$list[$extKey])) { 00613 if (in_array($extKey, $this->requiredExt)) { 00614 $loadUnloadLink = '<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('Rq').'</strong>'; 00615 } else { 00616 $loadUnloadLink = '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1').'">'.$this->removeButton().'</a>'; 00617 } 00618 00619 $lines[] = $this->extensionListRow($extKey,$list[$extKey],array('<td class="bgColor">'.$loadUnloadLink.'</td>')); 00620 } 00621 } 00622 } 00623 00624 $content.= t3lib_BEfunc::cshItem('_MOD_tools_em', 'loaded', $GLOBALS['BACK_PATH'],''); 00625 00626 00627 $content.= 'Look up: <input type="text" name="_lookUp" value="'.htmlspecialchars($this->lookUpStr).'" /><input type="submit" value="Search"/><br/><br/>'; 00628 00629 $content.= ' 00630 00631 <!-- Loaded Extensions List --> 00632 <table border="0" cellpadding="2" cellspacing="1">'.implode('',$lines).'</table>'; 00633 00634 $this->content.=$this->doc->section('Loaded Extensions',$content,0,1); 00635 } 00636 00642 function extensionList_installed() { 00643 global $TYPO3_LOADED_EXT; 00644 00645 list($list,$cat)=$this->getInstalledExtensions(); 00646 00647 // Available extensions 00648 if (is_array($cat[$this->MOD_SETTINGS['listOrder']])) { 00649 $content=''; 00650 $lines=array(); 00651 $lines[]=$this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="18" height="1" alt="" /></td>')); 00652 00653 $allKeys=array(); 00654 foreach($cat[$this->MOD_SETTINGS['listOrder']] as $catName => $extEkeys) { 00655 $allKeys[]=''; 00656 $allKeys[]='TYPE: '.$catName; 00657 00658 $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><br /></td></tr>'; 00659 $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>'; 00660 00661 asort($extEkeys); 00662 reset($extEkeys); 00663 while(list($extKey)=each($extEkeys)) { 00664 $allKeys[]=$extKey; 00665 if (($this->MOD_SETTINGS['display_shy'] || !$list[$extKey]['EM_CONF']['shy']) && $this->searchExtension($extKey,$list[$extKey])) { 00666 $loadUnloadLink = t3lib_extMgm::isLoaded($extKey)? 00667 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->removeButton().'</a>': 00668 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[load]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->installButton().'</a>'; 00669 if (in_array($extKey,$this->requiredExt)) $loadUnloadLink='<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('Rq').'</strong>'; 00670 00671 if ($list[$extKey]['EM_CONF']['private']) { 00672 $theRowClass = 'em-private'; 00673 } else { 00674 $theRowClass = t3lib_extMgm::isLoaded($extKey)? 'em-listbg1' : 'em-listbg2'; 00675 } 00676 $lines[]=$this->extensionListRow($extKey,$list[$extKey],array('<td class="bgColor">'.$loadUnloadLink.'</td>'),$theRowClass); 00677 } 00678 } 00679 } 00680 00681 $content.=' 00682 00683 00684 <!-- 00685 EXTENSION KEYS: 00686 00687 00688 '.trim(implode(chr(10),$allKeys)).' 00689 00690 --> 00691 00692 00693 00694 00695 '; 00696 00697 #debug($this->MOD_SETTINGS['listOrder']); 00698 $content.= t3lib_BEfunc::cshItem('_MOD_tools_em', 'avail', $GLOBALS['BACK_PATH'],'|<br/>'); 00699 $content.= 'If you want to use an extension in TYPO3, you should simply click the "plus" button '.$this->installButton().' . <br /> 00700 Installed extensions can also be removed again - just click the remove button '.$this->removeButton().' .<br /><br />'; 00701 00702 $content.= 'Look up: <input type="text" name="_lookUp" value="'.htmlspecialchars($this->lookUpStr).'" /><input type="submit" value="Search"/><br/><br/>'; 00703 00704 $content.= '<table border="0" cellpadding="2" cellspacing="1">'.implode('',$lines).'</table>'; 00705 00706 $this->content.=$this->doc->section('Available Extensions - Order by: '.$this->MOD_MENU['listOrder'][$this->MOD_SETTINGS['listOrder']],$content,0,1); 00707 } 00708 } 00709 00715 function extensionList_import() { 00716 global $TYPO3_LOADED_EXT; 00717 00718 // Listing from online repository: 00719 if ($this->listRemote) { 00720 list($inst_list,$inst_cat) = $this->getInstalledExtensions(); 00721 $this->inst_keys = array_flip(array_keys($inst_list)); 00722 00723 $this->detailCols[1]+=6; 00724 00725 // Getting data from repository: 00726 $repositoryUrl=$this->repositoryUrl. 00727 $this->repTransferParams(). 00728 '&tx_extrep[cmd]=currentListing'. 00729 ($this->MOD_SETTINGS['own_member_only']?'&tx_extrep[listmode]=1':''). 00730 ($this->listRemote_search ? '&tx_extrep[search]='.rawurlencode($this->listRemote_search) : ''); 00731 00732 $fetchData = $this->fetchServerData($repositoryUrl); 00733 00734 if (is_array($fetchData)) { 00735 $listArr = $fetchData[0]; 00736 list($list,$cat) = $this->getImportExtList($listArr); 00737 00738 // Available extensions 00739 if (is_array($cat[$this->MOD_SETTINGS['listOrder']])) { 00740 $content=''; 00741 $lines=array(); 00742 $lines[]=$this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="18" height="1" alt="" /></td>'),1); 00743 00744 foreach($cat[$this->MOD_SETTINGS['listOrder']] as $catName => $extEkeys) { 00745 if (count($extEkeys)) { 00746 $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><br /></td></tr>'; 00747 $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>'; 00748 00749 asort($extEkeys); 00750 reset($extEkeys); 00751 while(list($extKey)=each($extEkeys)) { 00752 if ($this->MOD_SETTINGS['display_shy'] || !$list[$extKey]['EM_CONF']['shy']) { 00753 $loadUnloadLink=''; 00754 if ($inst_list[$extKey]['type']!='S' && (!isset($inst_list[$extKey]) || $this->versionDifference($list[$extKey]['EM_CONF']['version'],$inst_list[$extKey]['EM_CONF']['version'],$this->versionDiffFactor))) { 00755 if (isset($inst_list[$extKey])) { 00756 // update 00757 $loc= ($inst_list[$extKey]['type']=='G'?'G':'L'); 00758 $aUrl = 'index.php?CMD[importExt]='.$list[$extKey]['extRepUid'].'&CMD[loc]='.$loc.($this->getDocManual($extKey,$loc)?'&CMD[inc_manual]=1':''); 00759 $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>'; 00760 } else { 00761 // import 00762 $aUrl = 'index.php?CMD[importExt]='.$list[$extKey]['extRepUid'].'&CMD[loc]=L'.($this->getDocManual($extKey)?'&CMD[inc_manual]=1':''); 00763 $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>'; 00764 } 00765 } else { 00766 $loadUnloadLink = ' '; 00767 } 00768 00769 if ($list[$extKey]['_MEMBERS_ONLY']) { 00770 $theRowClass = 'em-private'; 00771 } elseif (isset($inst_list[$extKey])) { 00772 $theRowClass = t3lib_extMgm::isLoaded($extKey) ? 'em-listbg1' : 'em-listbg2'; 00773 } else { 00774 $theRowClass = 'em-listbg3'; 00775 } 00776 $lines[]=$this->extensionListRow($extKey,$list[$extKey],array('<td class="bgColor">'.$loadUnloadLink.'</td>'),$theRowClass,$inst_list,1,'index.php?CMD[importExtInfo]='.$list[$extKey]['extRepUid']); 00777 } 00778 } 00779 } 00780 } 00781 00782 // CSH: 00783 $content.= t3lib_BEfunc::cshItem('_MOD_tools_em', 'import_ter', $GLOBALS['BACK_PATH'],'|<br/>'); 00784 00785 $content.= ' 00786 00787 <!-- TER Extensions list --> 00788 <table border="0" cellpadding="2" cellspacing="1">'.implode('',$lines).'</table>'; 00789 00790 $content.= '<br />Data fetched: ['.implode('][',$fetchData[1]).']'; 00791 $content.= '<br /><br /><strong>PRIVACY NOTICE:</strong><br /> '.$this->privacyNotice; 00792 00793 $this->content.=$this->doc->section('Extensions in TYPO3 Extension Repository (online) - Order by: '.$this->MOD_MENU['listOrder'][$this->MOD_SETTINGS['listOrder']],$content,0,1); 00794 00795 if (!$this->MOD_SETTINGS['own_member_only'] && !$this->listRemote_search) { 00796 // Plugins which are NOT uploaded to repository but present on this server. 00797 $content=''; 00798 $lines=array(); 00799 if (count($this->inst_keys)) { 00800 $lines[]=$this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="18" height="1" alt="" /></td>')); 00801 00802 reset($this->inst_keys); 00803 while(list($extKey)=each($this->inst_keys)) { 00804 if ($this->MOD_SETTINGS['display_shy'] || !$inst_list[$extKey]['EM_CONF']['shy']) { 00805 $loadUnloadLink = t3lib_extMgm::isLoaded($extKey)? 00806 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->removeButton().'</a>': 00807 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[load]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->installButton().'</a>'; 00808 if (in_array($extKey,$this->requiredExt)) $loadUnloadLink='<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('Rq').'</strong>'; 00809 $lines[]=$this->extensionListRow($extKey,$inst_list[$extKey],array('<td class="bgColor">'.$loadUnloadLink.'</td>'),t3lib_extMgm::isLoaded($extKey)?'em-listbg1':'em-listbg2'); 00810 } 00811 } 00812 } 00813 00814 $content.= 'This is the list of extensions which are either user-defined (should be prepended user_ then) or which are private (and does not show up in the public list above).<br /><br />'; 00815 $content.= '<table border="0" cellpadding="2" cellspacing="1">'.implode('',$lines).'</table>'; 00816 $this->content.=$this->doc->spacer(20); 00817 $this->content.=$this->doc->section('Extensions found only on this server',$content,0,1); 00818 } 00819 } 00820 } 00821 } else { 00822 // CSH 00823 $content.= t3lib_BEfunc::cshItem('_MOD_tools_em', 'import', $GLOBALS['BACK_PATH'],'|<br/>'); 00824 $content.= 'Click here to connect to "'.$this->repositoryUrl.'" and retrieve the list of publicly available plugins from the TYPO3 Extension Repository.<br />'; 00825 00826 if ($this->fe_user['username']) { 00827 $content.= '<br /><img src="'.$GLOBALS['BACK_PATH'].'gfx/icon_note.gif" width="18" height="16" align="top" alt="" />Repository username "'.$this->fe_user['username'].'" will be sent as authentication.<br />'; 00828 } else { 00829 $content.= '<br /><img src="'.$GLOBALS['BACK_PATH'].'gfx/icon_warning2.gif" width="18" height="16" align="top" alt="" />You have not configured a repository username/password yet. Please <a href="index.php?SET[function]=3">go to "Settings"</a> and do that.<br />'; 00830 } 00831 00832 $onCLick = "document.location='index.php?ter_connect=1&ter_search='+escape(this.form['_lookUp'].value);return false;"; 00833 $content.= '<br /> 00834 Look up: <input type="text" name="_lookUp" value="" /> 00835 <input type="submit" value="Connect to online repository" onclick="'.htmlspecialchars($onCLick).'" /> 00836 <br /><br /><strong>PRIVACY NOTICE:</strong><br /> '.$this->privacyNotice; 00837 00838 $this->content.=$this->doc->section('Extensions in TYPO3 Extension Repository',$content,0,1); 00839 } 00840 00841 // Private lookup: 00842 /* 00843 $onClick = 'document.location=\'index.php?CMD[importExtInfo]=\'+document.pageform.uid_private_key.value+\'&CMD[download_password]=\'+document.pageform.download_password.value; return false;'; 00844 $content= 'Privat lookup key: <input type="text" name="uid_private_key" /> Password, if any: <input type="text" name="download_password" /><input type="submit" value="Lookup" onclick="'.htmlspecialchars($onClick).'" />'; 00845 $this->content.=$this->doc->spacer(20); 00846 $this->content.=$this->doc->section('Private extension lookup:',$content,0,1); 00847 */ 00848 00849 // Upload: 00850 if ($this->importAtAll()) { 00851 $content= '</form><form action="index.php" enctype="'.$GLOBALS['TYPO3_CONF_VARS']['SYS']['form_enctype'].'" method="post"> 00852 Upload extension file (.t3x):<br /> 00853 <input type="file" size="60" name="upload_ext_file" /><br /> 00854 ... in location:<br /> 00855 <select name="CMD[loc]">'; 00856 if ($this->importAsType('L')) $content.='<option value="L">Local (../typo3conf/ext/)</option>'; 00857 if ($this->importAsType('G')) $content.='<option value="G">Global (typo3/ext/)</option>'; 00858 if ($this->importAsType('S')) $content.='<option value="S">System (typo3/sysext/)</option>'; 00859 $content.='</select><br /> 00860 <input type="checkbox" value="1" name="CMD[uploadOverwrite]" /> Overwrite any existing extension!<br /> 00861 <input type="submit" name="CMD[uploadExt]" value="Upload extension file" /><br /> 00862 '; 00863 if (!$this->gzcompress) { 00864 $content.='<br />'.$GLOBALS['TBE_TEMPLATE']->rfw("NOTE: No decompression available! Don't upload a compressed extension - it will not succeed."); 00865 } 00866 } else $content=$this->noImportMsg(); 00867 00868 $this->content.=$this->doc->spacer(20); 00869 $this->content.=$this->doc->section('Upload extension file directly (.t3x):',$content,0,1); 00870 } 00871 00877 function alterSettings() { 00878 $content.= t3lib_BEfunc::cshItem('_MOD_tools_em', 'settings', $GLOBALS['BACK_PATH'],'|<br/>'); 00879 $content.= ' 00880 <table border="0" cellpadding="2" cellspacing="2"> 00881 <tr class="bgColor4"> 00882 <td>Enter repository username:</td> 00883 <td><input type="text" name="SET[fe_u]" value="'.htmlspecialchars($this->MOD_SETTINGS['fe_u']).'" /></td> 00884 </tr> 00885 <tr class="bgColor4"> 00886 <td>Enter repository password:</td> 00887 <td><input type="password" name="SET[fe_p]" value="'.htmlspecialchars($this->MOD_SETTINGS['fe_p']).'" /></td> 00888 </tr> 00889 <tr class="bgColor4"> 00890 <td>Enter default upload password:</td> 00891 <td><input type="password" name="SET[fe_up]" value="'.htmlspecialchars($this->MOD_SETTINGS['fe_up']).'" /></td> 00892 </tr> 00893 </table> 00894 00895 <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!<br /> 00896 <br /> 00897 <input type="submit" value="Update" /> 00898 '; 00899 00900 $this->content.=$this->doc->section('Repository settings',$content,0,1); 00901 } 00902 00903 00904 00905 00906 00907 00908 00909 00910 00911 00912 /********************************* 00913 * 00914 * Command Applications (triggered by GET var) 00915 * 00916 *********************************/ 00917 00924 function importExtInfo($extRepUid) { 00925 00926 // "Go back" link 00927 $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>'; 00928 $this->content.= $this->doc->section('',$content); 00929 $content = ''; 00930 00931 // Create connection URL: 00932 $uidParts = t3lib_div::trimExplode('-',$extRepUid); 00933 if (count($uidParts)==2) { 00934 $extRepUid = $uidParts[0]; 00935 $addParams = '&tx_extrep[pKey]='.rawurlencode(trim($uidParts[1])) 00936 .'&tx_extrep[pPass]='.rawurlencode(trim($this->CMD['download_password'])); 00937 $addImportParams = '&CMD[download_password]='.rawurlencode(trim($this->CMD['download_password'])); 00938 } else $addParams = ''; 00939 00940 $repositoryUrl = $this->repositoryUrl. 00941 $this->repTransferParams(). 00942 $addParams. 00943 '&tx_extrep[cmd]=extensionInfo'. 00944 '&tx_extrep[uid]='.$extRepUid; 00945 00946 // Fetch remote data: 00947 list($fetchData) = $this->fetchServerData($repositoryUrl); 00948 if (is_array($fetchData['_other_versions'])) { 00949 $opt = array(); 00950 $opt[] = '<option value=""></option>'; 00951 $selectWasSet=0; 00952 00953 foreach($fetchData['_other_versions'] as $dat) { 00954 $setSel = ($dat['uid']==$extRepUid?' selected="selected"':''); 00955 if ($setSel) $selectWasSet=1; 00956 $opt[]='<option value="'.$dat['uid'].'"'.$setSel.'>'.$dat['version'].'</option>'; 00957 } 00958 if (!$selectWasSet && $fetchData['emconf_private']) { 00959 $opt[]='<option value="'.$fetchData['uid'].'-'.$fetchData['private_key'].'" selected="selected">'.$fetchData['version'].' (Private)</option>'; 00960 } 00961 00962 // "Select version" box: 00963 $onClick = 'document.location=\'index.php?CMD[importExtInfo]=\'+document.pageform.repUid.options[document.pageform.repUid.selectedIndex].value; return false;'; 00964 $select='<select name="repUid">'.implode('',$opt).'</select> <input type="submit" value="Load details" onclick="'.htmlspecialchars($onClick).'" /> or<br /><br />'; 00965 if ($this->importAtAll()) { 00966 $onClick = ' 00967 document.location=\'index.php?CMD[importExt]=\' 00968 +document.pageform.repUid.options[document.pageform.repUid.selectedIndex].value 00969 +\'&CMD[loc]=\'+document.pageform.loc.options[document.pageform.loc.selectedIndex].value 00970 +\'&CMD[transl]=\'+(document.pageform.transl.checked?1:0) 00971 +\'&CMD[inc_manual]=\'+(document.pageform.inc_manual.checked?1:0) 00972 +\''.$addImportParams.'\'; return false;'; 00973 $select.=' 00974 <input type="submit" value="Import/Update" onclick="'.htmlspecialchars($onClick).'"> to: 00975 <select name="loc">'. 00976 ($this->importAsType('G',$fetchData['emconf_lockType'])?'<option value="G">Global: '.$this->typePaths['G'].$fetchData['extension_key'].'/'.(@is_dir(PATH_site.$this->typePaths['G'].$fetchData['extension_key'])?' (OVERWRITE)':' (empty)').'</option>':''). 00977 ($this->importAsType('L',$fetchData['emconf_lockType'])?'<option value="L">Local: '.$this->typePaths['L'].$fetchData['extension_key'].'/'.(@is_dir(PATH_site.$this->typePaths['L'].$fetchData['extension_key'])?' (OVERWRITE)':' (empty)').'</option>':''). 00978 ($this->importAsType('S',$fetchData['emconf_lockType'])?'<option value="S">System: '.$this->typePaths['S'].$fetchData['extension_key'].'/'.(@is_dir(PATH_site.$this->typePaths['S'].$fetchData['extension_key'])?' (OVERWRITE)':' (empty)').'</option>':''). 00979 #'<option value="fileadmin">'.htmlspecialchars('TEST: fileadmin/_temp_/[extension key name + date]').'</option>'. 00980 '</select> 00981 <br /><input type="checkbox" name="transl" value="1" />Include most recent translations 00982 <br /><input type="checkbox" name="inc_manual" value="1"'.($this->getDocManual($fetchData['extension_key'],@is_dir(PATH_site.$this->typePaths['G'].$fetchData['extension_key'])?'G':'L')?' checked="checked"':'').' />Include "doc/manual.sxw", if any 00983 '; 00984 } else $select.= $this->noImportMsg(); 00985 $content.= $select; 00986 $this->content.= $this->doc->section('Select command',$content,0,1); 00987 } 00988 00989 // Details: 00990 $extKey = $fetchData['extension_key']; 00991 list($xList) = $this->getImportExtList(array($fetchData)); 00992 $eInfo = $xList[$extKey]; 00993 $eInfo['_TECH_INFO'] = unserialize($fetchData['techinfo']); 00994 $tempFiles = unserialize($fetchData['files']); 00995 00996 if (is_array($tempFiles)) { 00997 reset($tempFiles); 00998 while(list($fk)=each($tempFiles)) { 00999 if (!strstr($fk,'/')) $eInfo['files'][]=$fk; 01000 } 01001 } 01002 01003 $content='<strong>'.$fetchData['_ICON'].' '.$eInfo['EM_CONF']['title'].'</strong><br /><br />'; 01004 $content.=$this->extInformationArray($extKey,$eInfo,1); 01005 $this->content.=$this->doc->spacer(10); 01006 $this->content.=$this->doc->section('Remote Extension Details:',$content,0,1); 01007 01008 if (is_array($fetchData['_MESSAGES'])) { 01009 $content = implode('<hr />',$fetchData['_MESSAGES']); 01010 $this->content.=$this->doc->section('Messages from repository server:',$content,0,1,1); 01011 } 01012 } 01013 01026 function importExtFromRep($extRepUid,$loc,$uploadFlag=0,$directInput='',$recentTranslations=0,$incManual=0,$dontDelete=0) { 01027 01028 if (is_array($directInput)) { 01029 $fetchData = array($directInput,''); 01030 $loc = !strcmp($loc,'G')?'G':'L'; 01031 } elseif ($uploadFlag) { 01032 if ($_FILES['upload_ext_file']['tmp_name']) { 01033 01034 // Read uploaded file: 01035 $uploadedTempFile = t3lib_div::upload_to_tempfile($_FILES['upload_ext_file']['tmp_name']); 01036 $fileContent = t3lib_div::getUrl($uploadedTempFile); 01037 t3lib_div::unlink_tempfile($uploadedTempFile); 01038 01039 // Decode file data: 01040 $fetchData = array($this->decodeExchangeData($fileContent),''); 01041 01042 if (is_array($fetchData)) { 01043 $extKey = $fetchData[0]['extKey']; 01044 if ($extKey) { 01045 if (!$this->CMD['uploadOverwrite']) { 01046 $loc = !strcmp($loc,'G')?'G':'L'; 01047 $comingExtPath = PATH_site.$this->typePaths[$loc].$extKey.'/'; 01048 if (@is_dir($comingExtPath)) { 01049 # debug('!'); 01050 return 'Extension was already present in "'.$comingExtPath.'" - and the overwrite flag was not set! So nothing done...'; 01051 } // ... else go on, install... 01052 } // ... else go on, install... 01053 } else return 'No extension key in file. Strange...'; 01054 } else return 'Wrong file format. No data recognized.'; 01055 } else return 'No file uploaded! Probably the file was too large for PHPs internal limit for uploadable files.'; 01056 } else { 01057 01058 // Create link: 01059 $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>'; 01060 $this->content.= $this->doc->section('',$content); 01061 $content = ''; 01062 01063 // Building request URL: 01064 $uidParts = t3lib_div::trimExplode('-',$extRepUid); 01065 if (count($uidParts)==2) { 01066 $extRepUid=$uidParts[0]; 01067 $addParams='&tx_extrep[pKey]='.rawurlencode(trim($uidParts[1])) 01068 .'&tx_extrep[pPass]='.rawurlencode(trim($this->CMD['download_password'])); 01069 } else $addParams=''; 01070 01071 // If most recent translation should be delivered, send this: 01072 if ($recentTranslations) { 01073 $addParams.='&tx_extrep[transl]=1'; 01074 } 01075 01076 // If manual should be included, send this: 01077 if ($incManual) { 01078 $addParams.='&tx_extrep[inc_manual]=1'; 01079 } 01080 01081 $repositoryUrl=$this->repositoryUrl. 01082 $this->repTransferParams(). 01083 $addParams. 01084 '&tx_extrep[cmd]=importExtension'. 01085 '&tx_extrep[uid]='.$extRepUid; 01086 01087 // Fetch extension from TER: 01088 $fetchData = $this->fetchServerData($repositoryUrl); 01089 } 01090 01091 // At this point the extension data should be present; so we want to write it to disc: 01092 if ($this->importAsType($loc)) { 01093 if (is_array($fetchData)) { // There was some data successfully transferred 01094 if ($fetchData[0]['extKey'] && is_array($fetchData[0]['FILES'])) { 01095 $extKey = $fetchData[0]['extKey']; 01096 $EM_CONF = $fetchData[0]['EM_CONF']; 01097 if (!$EM_CONF['lockType'] || !strcmp($EM_CONF['lockType'],$loc)) { 01098 $res = $this->clearAndMakeExtensionDir($fetchData[0],$loc,$dontDelete); 01099 if (is_array($res)) { 01100 $extDirPath = trim($res[0]); 01101 if ($extDirPath && @is_dir($extDirPath) && substr($extDirPath,-1)=='/') { 01102 01103 $emConfFile = $this->construct_ext_emconf_file($extKey,$EM_CONF); 01104 $dirs = $this->extractDirsFromFileList(array_keys($fetchData[0]['FILES'])); 01105 01106 $res = $this->createDirsInPath($dirs,$extDirPath); 01107 if (!$res) { 01108 $writeFiles = $fetchData[0]['FILES']; 01109 $writeFiles['ext_emconf.php']['content'] = $emConfFile; 01110 $writeFiles['ext_emconf.php']['content_md5'] = md5($emConfFile); 01111 01112 // Write files: 01113 foreach($writeFiles as $theFile => $fileData) { 01114 t3lib_div::writeFile($extDirPath.$theFile,$fileData['content']); 01115 if (!@is_file($extDirPath.$theFile)) { 01116 $content.='Error: File "'.$extDirPath.$theFile.'" could not be created!!!<br />'; 01117 } elseif (md5(t3lib_div::getUrl($extDirPath.$theFile)) != $fileData['content_md5']) { 01118 $content.='Error: File "'.$extDirPath.$theFile.'" MD5 was different from the original files MD5 - so the file is corrupted!<br />'; 01119 } elseif (TYPO3_OS!='WIN') { 01120 #chmod ($extDirPath.$theFile, 0755); # SHOULD NOT do that here since writing the file should already have set adequate permissions! 01121 } 01122 } 01123 01124 // No content, no errors. Create success output here: 01125 if (!$content) { 01126 $content='SUCCESS: '.$extDirPath.'<br />'; 01127 01128 // Fix TYPO3_MOD_PATH for backend modules in extension: 01129 $modules = t3lib_div::trimExplode(',',$EM_CONF['module'],1); 01130 if (count($modules)) { 01131 foreach($modules as $mD) { 01132 $confFileName = $extDirPath.$mD.'/conf.php'; 01133 if (@is_file($confFileName)) { 01134 $content.= $this->writeTYPO3_MOD_PATH($confFileName,$loc,$extKey.'/'.$mD.'/').'<br />'; 01135 } else $content.='Error: Couldn\'t find "'.$confFileName.'"<br />'; 01136 } 01137 } 01138 // 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. 01139 // But this order of the code works.... (using the empty Array with type, EMCONF and files hereunder). 01140 01141 // Writing to ext_emconf.php: 01142 $sEMD5A = $this->serverExtensionMD5Array($extKey,array( 01143 'type' => $loc, 01144 'EM_CONF' => array(), 01145 'files' => array() 01146 )); 01147 $EM_CONF['_md5_values_when_last_written'] = serialize($sEMD5A); 01148 $emConfFile = $this->construct_ext_emconf_file($extKey,$EM_CONF); 01149 t3lib_div::writeFile($extDirPath.'ext_emconf.php',$emConfFile); 01150 01151 $content.='ext_emconf.php: '.$extDirPath.'ext_emconf.php<br />'; 01152 $content.='Type: '.$loc.'<br />'; 01153 01154 // Remove cache files: 01155 if (t3lib_extMgm::isLoaded($extKey)) { 01156 if ($this->removeCacheFiles()) { 01157 $content.='Cache-files are removed and will be re-written upon next hit<br />'; 01158 } 01159 01160 list($new_list)=$this->getInstalledExtensions(); 01161 $content.=$this->updatesForm($extKey,$new_list[$extKey],1,'index.php?CMD[showExt]='.$extKey.'&SET[singleDetails]=info'); 01162 } 01163 01164 // Show any messages: 01165 if (is_array($fetchData[0]['_MESSAGES'])) { 01166 $content.='<hr /><strong>Messages from repository:</strong><br /><br />'.implode('<br />',$fetchData[0]['_MESSAGES']); 01167 } 01168 01169 // Install / Uninstall: 01170 $content.='<h3>Install / Uninstall Extension:</h3>'; 01171 $content.= 01172 $new_list[$extKey] ? 01173 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->removeButton().' Uninstall extension</a>' : 01174 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[load]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->installButton().' Install extension</a>'; 01175 01176 } 01177 } else $content = $res; 01178 } else $content = 'Error: The extension path "'.$extDirPath.'" was different than expected...'; 01179 } else $content = $res; 01180 } else $content = 'Error: The extension can only be installed in the path '.$this->typePaths[$EM_CONF['lockType']].' (lockType='.$EM_CONF['lockType'].')'; 01181 } else $content = 'Error: No extension key!!! Why? - nobody knows... (Or no files in the file-array...)'; 01182 } else $content = 'Error: The datatransfer did not succeed...'; 01183 } else $content = 'Error: Installation is not allowed in this path ('.$this->typePaths[$loc].')'; 01184 01185 $this->content.=$this->doc->section('Extension copied to server',$content,0,1); 01186 } 01187 01194 function showExtDetails($extKey) { 01195 global $TYPO3_LOADED_EXT; 01196 01197 list($list,$cat)=$this->getInstalledExtensions(); 01198 $absPath = $this->getExtPath($extKey,$list[$extKey]['type']); 01199 01200 // Check updateModule: 01201 if (@is_file($absPath.'class.ext_update.php')) { 01202 require_once($absPath.'class.ext_update.php'); 01203 $updateObj = new ext_update; 01204 if (!$updateObj->access()) { 01205 unset($this->MOD_MENU['singleDetails']['updateModule']); 01206 } 01207 } else { 01208 unset($this->MOD_MENU['singleDetails']['updateModule']); 01209 } 01210 01211 // Function menu here: 01212 $content = ' 01213 <table border="0" cellpadding="0" cellspacing="0" width="100%"> 01214 <tr> 01215 <td nowrap="nowrap">Extension: <strong>'.$this->extensionTitleIconHeader($extKey,$list[$extKey]).'</strong> ('.$extKey.')</td> 01216 <td align="right" nowrap="nowrap">'. 01217 t3lib_BEfunc::getFuncMenu(0,'SET[singleDetails]',$this->MOD_SETTINGS['singleDetails'],$this->MOD_MENU['singleDetails'],'','&CMD[showExt]='.$extKey).' '. 01218 '<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> 01219 </tr> 01220 </table>'; 01221 $this->content.=$this->doc->section('',$content); 01222 01223 // Show extension details: 01224 if ($list[$extKey]) { 01225 01226 // Checking if a command for install/uninstall is executed: 01227 if (($this->CMD['remove'] || $this->CMD['load']) && !in_array($extKey,$this->requiredExt)) { 01228 01229 // Install / Uninstall extension here: 01230 if (t3lib_extMgm::isLocalconfWritable()) { 01231 if ($this->CMD['remove']) { 01232 $newExtList = $this->removeExtFromList($extKey,$list); 01233 } else { 01234 $newExtList = $this->addExtToList($extKey,$list); 01235 } 01236 01237 // Success-installation: 01238 if ($newExtList!=-1) { 01239 $updates = ''; 01240 if ($this->CMD['load']) { 01241 $updates = $this->updatesForm($extKey,$list[$extKey],1,'','<input type="hidden" name="_do_install" value="1" /><input type="hidden" name="_clrCmd" value="'.$this->CMD['clrCmd'].'" />'); 01242 if ($updates) { 01243 $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; 01244 $this->content.=$this->doc->section('Installing '.$this->extensionTitleIconHeader($extKey,$list[$extKey]).strtoupper(': Database needs to be updated'),$updates,1,1,1,1); 01245 } 01246 # $updates.=$this->checkDBupdates($extKey,$list[$extKey]); 01247 # $updates.= $this->checkClearCache($extKey,$list[$extKey]); 01248 # $updates.= $this->checkUploadFolder($extKey,$list[$extKey]); 01249 /* if ($updates) { 01250 $updates=' 01251 Before the extension can be installed the database needs to be updated with new tables or fields. Please select which operations to perform: 01252 </form><form action="'.t3lib_div::linkThisScript().'" method="post">'.$updates.' 01253 <br /><input type="submit" name="write" value="Update database and install extension" /> 01254 <input type="hidden" name="_do_install" value="1" /> 01255 '; 01256 $this->content.=$this->doc->section('Installing '.$this->extensionTitleIconHeader($extKey,$list[$extKey]).strtoupper(': Database needs to be updated'),$updates,1,1,1); 01257 } 01258 */ } elseif ($this->CMD['remove']) { 01259 $updates.= $this->checkClearCache($extKey,$list[$extKey]); 01260 if ($updates) { 01261 $updates = ' 01262 </form><form action="'.t3lib_div::linkThisScript().'" method="post">'.$updates.' 01263 <br /><input type="submit" name="write" value="Remove extension" /> 01264 <input type="hidden" name="_do_install" value="1" /> 01265 <input type="hidden" name="_clrCmd" value="'.$this->CMD['clrCmd'].'" /> 01266 '; 01267 $this->content.=$this->doc->section('Installing '.$this->extensionTitleIconHeader($extKey,$list[$extKey]).strtoupper(': Database needs to be updated'),$updates,1,1,1,1); 01268 } 01269 } 01270 if (!$updates || t3lib_div::_GP('_do_install')) { 01271 $this->writeNewExtensionList($newExtList); 01272 01273 01274 /* 01275 $content = $newExtList; 01276 $this->content.=$this->doc->section('Active status'," 01277 <strong>Extension list is written to localconf.php!</strong><br /> 01278 It may be necessary to reload TYPO3 depending on the change.<br /> 01279 01280 <em>(".$content.")</em>",0,1); 01281 */ 01282 if ($this->CMD['clrCmd'] || t3lib_div::_GP('_clrCmd')) { 01283 $vA = array('CMD'=>''); 01284 } else { 01285 $vA = array('CMD'=>Array('showExt'=>$extKey)); 01286 } 01287 header('Location: '.t3lib_div::linkThisScript($vA)); 01288 } 01289 } 01290 } else { 01291 $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); 01292 } 01293 01294 } elseif ($this->CMD['downloadFile'] && !in_array($extKey,$this->requiredExt)) { 01295 01296 // Link for downloading extension has been clicked - deliver content stream: 01297 $dlFile = $this->CMD['downloadFile']; 01298 if (t3lib_div::isFirstPartOfStr($dlFile,PATH_site) && t3lib_div::isFirstPartOfStr($dlFile,$absPath) && @is_file($dlFile)) { 01299 $mimeType = 'application/octet-stream'; 01300 Header('Content-Type: '.$mimeType); 01301 Header('Content-Disposition: attachment; filename='.basename($dlFile)); 01302 echo t3lib_div::getUrl($dlFile); 01303 exit; 01304 } else die('error....'); 01305 01306 } elseif ($this->CMD['editFile'] && !in_array($extKey,$this->requiredExt)) { 01307 01308 // Editing extension file: 01309 $editFile = $this->CMD['editFile']; 01310 if (t3lib_div::isFirstPartOfStr($editFile,PATH_site) && t3lib_div::isFirstPartOfStr($editFile,$absPath)) { // Paranoia... 01311 01312 $fI = t3lib_div::split_fileref($editFile); 01313 if (@is_file($editFile) && t3lib_div::inList($this->editTextExtensions,($fI['fileext']?$fI['fileext']:$fI['filebody']))) { 01314 if (filesize($editFile)<($this->kbMax*1024)) { 01315 $outCode = ''; 01316 $info = ''; 01317 $submittedContent = t3lib_div::_POST('edit'); 01318 $saveFlag = 0; 01319 01320 if(isset($submittedContent['file'])) { // Check referer here? 01321 $info.= $GLOBALS['TBE_TEMPLATE']->rfw('<br /><strong>File saved.</strong>').'<br />'; 01322 $oldFileContent = t3lib_div::getUrl($editFile); 01323 $info.= 'MD5: <b>'.md5(str_replace(chr(13),'',$oldFileContent)).'</b> (Previous File)<br />'; 01324 if (!$GLOBALS['TYPO3_CONF_VARS']['EXT']['noEdit']) { 01325 t3lib_div::writeFile($editFile,$submittedContent['file']); 01326 $saveFlag = 1; 01327 } else die('Saving disabled!!!'); 01328 } 01329 01330 $fileContent = t3lib_div::getUrl($editFile); 01331 $numberOfRows = 35; 01332 01333 $outCode.= 'File: <b>'.substr($editFile,strlen($absPath)).'</b> ('.t3lib_div::formatSize(filesize($editFile)).')<br />'; 01334 $info.= 'MD5: <b>'.md5(str_replace(chr(13),'',$fileContent)).'</b> (File)<br />'; 01335 if($saveFlag) $info.= 'MD5: <b>'.md5(str_replace(chr(13),'',$submittedContent['file'])).'</b> (Saved)<br />'; 01336 $outCode.= '<textarea name="edit[file]" rows="'.$numberOfRows.'" wrap="off"'.$this->doc->formWidthText(48,'width:98%;height:70%','off').'>'.t3lib_div::formatForTextarea($fileContent).'</textarea>'; 01337 $outCode.= '<input type="hidden" name="edit[filename]" value="'.$editFile.'" />'; 01338 $outCode.= '<input type="hidden" name="CMD[editFile]" value="'.htmlspecialchars($editFile).'" />'; 01339 $outCode.= '<input type="hidden" name="CMD[showExt]" value="'.$extKey.'" />'; 01340 $outCode.= $info; 01341 01342 if (!$GLOBALS['TYPO3_CONF_VARS']['EXT']['noEdit']) { 01343 $outCode.='<br /><input type="submit" name="save_file" value="Save file" />'; 01344 } else $outCode.=$GLOBALS['TBE_TEMPLATE']->rfw('<br />[SAVING IS DISABLED - can be enabled by the TYPO3_CONF_VARS[EXT][noEdit]-flag] '); 01345 01346 $onClick = 'document.location=\'index.php?CMD[showExt]='.$extKey.'\';return false;'; 01347 $outCode.='<input type="submit" name="cancel" value="Cancel" onclick="'.htmlspecialchars($onClick).'" />'; 01348 01349 $theOutput.=$this->doc->spacer(15); 01350 $theOutput.=$this->doc->section('Edit file:','',0,1); 01351 $theOutput.=$this->doc->sectionEnd().$outCode; 01352 $this->content.=$theOutput; 01353 } else { 01354 $theOutput.=$this->doc->spacer(15); 01355 $theOutput.=$this->doc->section('Filesize exceeded '.$this->kbMax.' Kbytes','Files larger than '.$this->kbMax.' KBytes are not allowed to be edited.'); 01356 } 01357 } 01358 } else die('Fatal Edit error: File "'.$editFile.'" was not inside the correct path of the TYPO3 Extension!'); 01359 } else { 01360 01361 // MAIN: 01362 switch((string)$this->MOD_SETTINGS['singleDetails']) { 01363 case 'info': 01364 // Loaded / Not loaded: 01365 if (!in_array($extKey,$this->requiredExt)) { 01366 if ($TYPO3_LOADED_EXT[$extKey]) { 01367 $content = '<strong>The extension is installed (loaded and running)!</strong><br />'. 01368 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1').'">Click here to remove the extension: '.$this->removeButton().'</a>'; 01369 } else { 01370 $content = 'The extension is <strong>not</strong> installed yet.<br />'. 01371 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[load]=1').'">Click here to install the extension: '.$this->installButton().'</a>'; 01372 } 01373 } else { 01374 $content = 'This extension is entered in the TYPO3_CONF_VARS[SYS][requiredExt] list and is therefore always loaded.'; 01375 } 01376 $this->content.=$this->doc->spacer(10); 01377 $this->content.=$this->doc->section('Active status:',$content,0,1); 01378 01379 if (t3lib_extMgm::isLoaded($extKey)) { 01380 $updates=$this->updatesForm($extKey,$list[$extKey]); 01381 if ($updates) { 01382 $this->content.=$this->doc->spacer(10); 01383 $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); 01384 } 01385 } 01386 01387 // Config: 01388 if (@is_file($absPath.'ext_conf_template.txt')) { 01389 $this->content.=$this->doc->spacer(10); 01390 $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); 01391 $this->tsStyleConfigForm($extKey,$list[$extKey]); 01392 } 01393 01394 // Show details: 01395 $content = t3lib_BEfunc::cshItem('_MOD_tools_em', 'info', $GLOBALS['BACK_PATH'],'|<br/>'); 01396 $content.= $this->extInformationArray($extKey,$list[$extKey]); 01397 01398 $this->content.=$this->doc->spacer(10); 01399 $this->content.=$this->doc->section('Details:',$content,0,1); 01400 break; 01401 case 'upload': 01402 $TER_CMD = t3lib_div::_GP('TER_CMD'); 01403 if (is_array($TER_CMD)) { 01404 $msg = $this->processRepositoryReturnData($TER_CMD); 01405 if ($msg) { 01406 $this->content.=$this->doc->section('Local update of EM_CONF',$msg,0,1,1); 01407 $this->content.=$this->doc->spacer(10); 01408 } 01409 // Must reload this, because EM_CONF information has been updated! 01410 list($list,$cat)=$this->getInstalledExtensions(); 01411 } else { 01412 // CSH: 01413 $content = t3lib_BEfunc::cshItem('_MOD_tools_em', 'upload', $GLOBALS['BACK_PATH'],'|<br/>'); 01414 01415 // Upload: 01416 if (substr($extKey,0,5)!='user_') { 01417 $content.= $this->getRepositoryUploadForm($extKey,$list[$extKey]); 01418 $eC=0; 01419 } else { 01420 $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.<br /> 01421 You are encouraged to register a unique extension key for all your TYPO3 extensions - even if the project is current not official.'; 01422 $eC=2; 01423 } 01424 $this->content.=$this->doc->section('Upload extension to repository',$content,0,1,$eC); 01425 } 01426 break; 01427 case 'download': 01428 break; 01429 case 'backup': 01430 $content = t3lib_BEfunc::cshItem('_MOD_tools_em', 'backup_delete', $GLOBALS['BACK_PATH'],'|<br/>'); 01431 $content.= $this->extBackup($extKey,$list[$extKey]); 01432 $this->content.=$this->doc->section('Backup',$content,0,1); 01433 01434 $content = $this->extDelete($extKey,$list[$extKey]); 01435 $this->content.=$this->doc->section('Delete',$content,0,1); 01436 01437 $content = $this->extUpdateEMCONF($extKey,$list[$extKey]); 01438 $this->content.=$this->doc->section('Update EM_CONF',$content,0,1); 01439 break; 01440 case 'dump': 01441 $this->extDumpTables($extKey,$list[$extKey]); 01442 break; 01443 case 'edit': 01444 // Files: 01445 $content = t3lib_BEfunc::cshItem('_MOD_tools_em', 'editfiles', $GLOBALS['BACK_PATH'],'|<br/>'); 01446 $content.= $this->getFileListOfExtension($extKey,$list[$extKey]); 01447 01448 $this->content.=$this->doc->section('Extension files',$content,0,1); 01449 break; 01450 case 'updateModule': 01451 $this->content.=$this->doc->section('Update:',is_object($updateObj) ? $updateObj->main() : 'No update object',0,1); 01452 break; 01453 default: 01454 $this->extObjContent(); 01455 break; 01456 } 01457 } 01458 } 01459 } 01460 01461 01462 01463 01464 01465 01466 01467 01468 01469 01470 /*********************************** 01471 * 01472 * Application Sub-functions (HTML parts) 01473 * 01474 **********************************/ 01475 01487 function updatesForm($extKey,$extInfo,$notSilent=0,$script='',$addFields='') { 01488 $script = $script ? $script : t3lib_div::linkThisScript(); 01489 $updates.= $this->checkDBupdates($extKey,$extInfo); 01490 $uCache = $this->checkClearCache($extKey,$extInfo); 01491 if ($notSilent) $updates.= $uCache; 01492 $updates.= $this->checkUploadFolder($extKey,$extInfo); 01493 01494 $absPath = $this->getExtPath($extKey,$extInfo['type']); 01495 if ($notSilent && @is_file($absPath.'ext_conf_template.txt')) { 01496 $cForm = $this->tsStyleConfigForm($extKey,$extInfo,1,$script,$updates.$addFields.'<br />'); 01497 } 01498 01499 if ($updates || $cForm) { 01500 if ($cForm) { 01501 $updates = '</form>'.$cForm.'<form>'; 01502 } else { 01503 $updates = '</form><form action="'.htmlspecialchars($script).'" method="post">'.$updates.$addFields.' 01504 <br /><input type="submit" name="write" value="Make updates" /> 01505 '; 01506 } 01507 } 01508 return $updates; 01509 } 01510 01518 function extDumpTables($extKey,$extInfo) { 01519 01520 // Get dbInfo which holds the structure known from the tables.sql file 01521 $techInfo = $this->makeDetailedExtensionAnalysis($extKey,$extInfo); 01522 $absPath = $this->getExtPath($extKey,$extInfo['type']); 01523 01524 // Static tables: 01525 if (is_array($techInfo['static'])) { 01526 if ($this->CMD['writeSTATICdump']) { // Writing static dump: 01527 $writeFile = $absPath.'ext_tables_static+adt.sql'; 01528 if (@is_file($writeFile)) { 01529 $dump_static = $this->dumpStaticTables(implode(',',$techInfo['static'])); 01530 t3lib_div::writeFile($writeFile,$dump_static); 01531 $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); 01532 } 01533 } else { // Showing info about what tables to dump - and giving the link to execute it. 01534 $msg = 'Dumping table content for static tables:<br />'; 01535 $msg.= '<br />'.implode('<br />',$techInfo['static']).'<br />'; 01536 01537 // ... then feed that to this function which will make new CREATE statements of the same fields but based on the current database content. 01538 $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); 01539 $this->content.=$this->doc->spacer(20); 01540 } 01541 } 01542 01543 // Table and field definitions: 01544 if (is_array($techInfo['dump_tf'])) { 01545 $dump_tf_array = $this->getTableAndFieldStructure($techInfo['dump_tf']); 01546 $dump_tf = $this->dumpTableAndFieldStructure($dump_tf_array); 01547 if ($this->CMD['writeTFdump']) { 01548 $writeFile = $absPath.'ext_tables.sql'; 01549 if (@is_file($writeFile)) { 01550 t3lib_div::writeFile($writeFile,$dump_tf); 01551 $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); 01552 } 01553 } else { 01554 $msg = 'Dumping current database structure for:<br />'; 01555 if (is_array($techInfo['tables'])) { 01556 $msg.= '<br /><strong>Tables:</strong><br />'.implode('<br />',$techInfo['tables']).'<br />'; 01557 } 01558 if (is_array($techInfo['fields'])) { 01559 $msg.= '<br /><strong>Solo-fields:</strong><br />'.implode('<br />',$techInfo['fields']).'<br />'; 01560 } 01561 01562 // ... then feed that to this function which will make new CREATE statements of the same fields but based on the current database content. 01563 $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 /> 01564 <pre>'.htmlspecialchars($dump_tf).'</pre>',0,1); 01565 01566 01567 $details = ' This dump is based on two factors:<br /> 01568 <ul> 01569 <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> 01570 <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> 01571 </ul> 01572 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 />'; 01573 $this->content.=$this->doc->section('',$details); 01574 } 01575 } 01576 } 01577 01585 function getFileListOfExtension($extKey,$conf) { 01586 $extPath = $this->getExtPath($extKey,$conf['type']); 01587 01588 if ($extPath) { 01589 // Read files: 01590 $fileArr = array(); 01591 $fileArr = t3lib_div::getAllFilesAndFoldersInPath($fileArr,$extPath); 01592 01593 // Start table: 01594 $lines = array(); 01595 $totalSize = 0; 01596 01597 // Header: 01598 $lines[] = ' 01599 <tr class="bgColor5"> 01600 <td>File:</td> 01601 <td>Size:</td> 01602 <td>Edit:</td> 01603 </tr>'; 01604 01605 foreach($fileArr as $file) { 01606 $fI = t3lib_div::split_fileref($file); 01607 $lines[] = ' 01608 <tr class="bgColor4"> 01609 <td><a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[downloadFile]='.rawurlencode($file)).'" title="Download...">'.substr($file,strlen($extPath)).'</a></td> 01610 <td>'.t3lib_div::formatSize(filesize($file)).'</td> 01611 <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> 01612 </tr>'; 01613 $totalSize+=filesize($file); 01614 } 01615 01616 $lines[] = ' 01617 <tr class="bgColor6"> 01618 <td><strong>Total:</strong></td> 01619 <td><strong>'.t3lib_div::formatSize($totalSize).'</strong></td> 01620 <td> </td> 01621 </tr>'; 01622 01623 return ' 01624 Path: '.$extPath.'<br /><br /> 01625 <table border="0" cellpadding="1" cellspacing="2">'.implode('',$lines).'</table>'; 01626 } 01627 } 01628 01636 function extDelete($extKey,$extInfo) { 01637 $absPath = $this->getExtPath($extKey,$extInfo['type']); 01638 if (t3lib_extMgm::isLoaded($extKey)) { 01639 return 'This extension is currently installed (loaded and active) and so cannot be deleted!'; 01640 } elseif (!$this->deleteAsType($extInfo['type'])) { 01641 return 'You cannot delete (and install/update) extensions in the '.$this->typeLabels[$extInfo['type']].' scope.'; 01642 } elseif (t3lib_div::inList('G,L',$extInfo['type'])) { 01643 if ($this->CMD['doDelete'] && !strcmp($absPath,$this->CMD['absPath'])) { 01644 $res = $this->removeExtDirectory($absPath); 01645 if ($res) { 01646 return 'ERROR: Could not remove extension directory "'.$absPath.'". Had the following errors:<br /><br />'. 01647 nl2br($res); 01648 } else { 01649 return 'Removed extension in path "'.$absPath.'"!'; 01650 } 01651 } else { 01652 $onClick = "if (confirm('Are you sure you want to delete this extension from the server?')) {document.location='index.php?CMD[showExt]=".$extKey.'&CMD[doDelete]=1&CMD[absPath]='.rawurlencode($absPath)."';}"; 01653 $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>'; 01654 $content.= '<br /><br />(Maybe you should make a backup first, see above.)'; 01655 return $content; 01656 } 01657 } else return 'Extension is not a global or local extension and cannot be removed.'; 01658 } 01659 01667 function extUpdateEMCONF($extKey,$extInfo) { 01668 $absPath = $this->getExtPath($extKey,$extInfo['type']); 01669 if ($this->CMD['doUpdateEMCONF']) { 01670 return $this->updateLocalEM_CONF($extKey,$extInfo); 01671 } else { 01672 $onClick = "if (confirm('Are you sure you want to update EM_CONF?')) {document.location='index.php?CMD[showExt]=".$extKey."&CMD[doUpdateEMCONF]=1';}"; 01673 $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>'; 01674 $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 /> 01675 Updating this file will first of all reset this registration.'; 01676 return $content; 01677 } 01678 } 01679 01687 function extBackup($extKey,$extInfo) { 01688 $uArr = $this->makeUploadArray($extKey,$extInfo); 01689 if (is_array($uArr)) { 01690 $local_gzcompress = $this->gzcompress && !$this->CMD['dontCompress']; 01691 $backUpData = $this->makeUploadDataFromArray($uArr,intval($local_gzcompress)); 01692 $filename = 'T3X_'.$extKey.'-'.str_replace('.','_',$extInfo['EM_CONF']['version']).($local_gzcompress?'-z':'').'-'.date('YmdHi').'.t3x'; 01693 if (intval($this->CMD['doBackup'])==1) { 01694 01695 $mimeType = 'application/octet-stream'; 01696 Header('Content-Type: '.$mimeType); 01697 Header('Content-Disposition: attachment; filename='.$filename); 01698 01699 // New headers suggested by Xin: 01700 // For now they are commented out because a) I have seen no official support yet, b) when clicking the back-link in MSIE after download you see ugly binary stuff and c) I couldn't see a BIG difference, in particular not in Moz/Opera. 01701 /* header('Content-Type: application/force-download'); 01702 header('Content-Length: '.strlen($backUpData)); 01703 01704 header('Content-Disposition: attachment; filename='.$filename); 01705 header('Content-Description: File Transfer'); 01706 header('Content-Transfer-Encoding: binary'); 01707 */ 01708 01709 // ANYWAYS! The download is NOT always working - in some cases extensions will never get the same MD5 sum as the one shown at the download link - and they should in order to work! We do NOT know why yet. 01710 01711 echo $backUpData; 01712 exit; 01713 } elseif ($this->CMD['dumpTables']) { 01714 $filename='T3X_'.$extKey; 01715 $cTables = count(explode(',',$this->CMD['dumpTables'])); 01716 if ($cTables>1) { 01717 $filename.='-'.$cTables.'tables'; 01718 } else { 01719 $filename.='-'.$this->CMD['dumpTables']; 01720 } 01721 $filename.='+adt.sql'; 01722 01723 $mimeType = 'application/octet-stream'; 01724 Header('Content-Type: '.$mimeType); 01725 Header('Content-Disposition: attachment; filename='.$filename); 01726 echo $this->dumpStaticTables($this->CMD['dumpTables']); 01727 exit; 01728 } else { 01729 $techInfo = $this->makeDetailedExtensionAnalysis($extKey,$extInfo); 01730 // if ($techInfo['tables']||$techInfo['static']||$techInfo['fields']) { 01731 #debug($techInfo); 01732 $lines=array(); 01733 $lines[]='<tr class="bgColor5"><td colspan="2"><strong>Make selection:</strong></td></tr>'; 01734 $lines[]='<tr class="bgColor4"><td><strong>Extension files:</strong></td><td>'. 01735 '<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 />'. 01736 ($this->gzcompress ? '<br /><a href="'.htmlspecialchars('index.php?CMD[doBackup]=1&CMD[dontCompress]=1&CMD[showExt]='.$extKey).'">(Click here to download extension without compression.)</a>':''). 01737 '</td></tr>'; 01738 01739 if (is_array($techInfo['tables'])) { $lines[]='<tr class="bgColor4"><td><strong>Data tables:</strong></td><td>'.$this->extBackup_dumpDataTablesLine($techInfo['tables'],$extKey).'</td></tr>'; } 01740 if (is_array($techInfo['static'])) { $lines[]='<tr class="bgColor4"><td><strong>Static tables:</strong></td><td>'.$this->extBackup_dumpDataTablesLine($techInfo['static'],$extKey).'</td></tr>'; } 01741 01742 $content = '<table border="0" cellpadding="2" cellspacing="2">'.implode('',$lines).'</table>'; 01743 return $content; 01744 } 01745 } else die('Error...'); 01746 } 01747 01755 function extBackup_dumpDataTablesLine($tablesArray,$extKey) { 01756 $tables = array(); 01757 $tablesNA = array(); 01758 01759 foreach($tablesArray as $tN) { 01760 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('count(*)', $tN, ''); 01761 if (!$GLOBALS['TYPO3_DB']->sql_error()) { 01762 $row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res); 01763 $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>'; 01764 } else { 01765 $tablesNA[$tN]='<tr><td> </td><td>'.$tN.'</td><td> </td><td>Did not exist.</td></tr>'; 01766 } 01767 } 01768 $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... 01769 if (count($tables)) { 01770 $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; 01771 } else $label = 'Nothing to dump...<br /><br />'.$label; 01772 return $label; 01773 } 01774 01783 function extInformationArray($extKey,$extInfo,$remote=0) { 01784 $lines=array(); 01785 $lines[]='<tr class="bgColor5"><td colspan="2"><strong>General information:</strong></td>'.$this->helpCol('').'</tr>'; 01786 $lines[]='<tr class="bgColor4"><td>Title:</td><td>'.$extInfo['EM_CONF']['_icon'].$extInfo['EM_CONF']['title'].'</td>'.$this->helpCol('title').'</tr>'; 01787 $lines[]='<tr class="bgColor4"><td>Description:</td><td>'.nl2br(htmlspecialchars($extInfo['EM_CONF']['description'])).'</td>'.$this->helpCol('description').'</tr>'; 01788 $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']). 01789 ($extInfo['EM_CONF']['author_company']?', '.$extInfo['EM_CONF']['author_company']:''). 01790 '</td>'.$this->helpCol('description').'</tr>'; 01791 01792 $lines[]='<tr class="bgColor4"><td>Version:</td><td>'.$extInfo['EM_CONF']['version'].'</td>'.$this->helpCol('version').'</tr>'; 01793 $lines[]='<tr class="bgColor4"><td>Category:</td><td>'.$this->categories[$extInfo['EM_CONF']['category']].'</td>'.$this->helpCol('category').'</tr>'; 01794 $lines[]='<tr class="bgColor4"><td>State:</td><td>'.$this->states[$extInfo['EM_CONF']['state']].'</td>'.$this->helpCol('state').'</tr>'; 01795 $lines[]='<tr class="bgColor4"><td>Shy?</td><td>'.($extInfo['EM_CONF']['shy']?'Yes':'').'</td>'.$this->helpCol('shy').'</tr>'; 01796 $lines[]='<tr class="bgColor4"><td>Internal?</td><td>'.($extInfo['EM_CONF']['internal']?'Yes':'').'</td>'.$this->helpCol('internal').'</tr>'; 01797 01798 $lines[]='<tr class="bgColor4"><td>Dependencies:</td><td>'.$extInfo['EM_CONF']['dependencies'].'</td>'.$this->helpCol('dependencies').'</tr>'; 01799 if (!$remote) { 01800 $lines[]='<tr class="bgColor4"><td>Conflicts:</td><td>'.$extInfo['EM_CONF']['conflicts'].'</td>'.$this->helpCol('conflicts').'</tr>'; 01801 $lines[]='<tr class="bgColor4"><td>Priority:</td><td>'.$extInfo['EM_CONF']['priority'].'</td>'.$this->helpCol('priority').'</tr>'; 01802 $lines[]='<tr class="bgColor4"><td>Clear cache?</td><td>'.($extInfo['EM_CONF']['clearCacheOnLoad']?'Yes':'').'</td>'.$this->helpCol('clearCacheOnLoad').'</tr>'; 01803 $lines[]='<tr class="bgColor4"><td>Includes modules:</td><td>'.$extInfo['EM_CONF']['module'].'</td>'.$this->helpCol('module').'</tr>'; 01804 } 01805 $lines[]='<tr class="bgColor4"><td>Lock Type?</td><td>'.($extInfo['EM_CONF']['lockType']?$extInfo['EM_CONF']['lockType']:'').'</td>'.$this->helpCol('lockType').'</tr>'; 01806 $lines[]='<tr class="bgColor4"><td>Modifies tables:</td><td>'.$extInfo['EM_CONF']['modify_tables'].'</td>'.$this->helpCol('modify_tables').'</tr>'; 01807 01808 $lines[]='<tr class="bgColor4"><td>Private?</td><td>'.($extInfo['EM_CONF']['private']?'Yes':'').'</td>'.$this->helpCol('private').'</tr>'; 01809 if (!$remote) $lines[]='<tr class="bgColor4"><td>Download password:</td><td>'.$extInfo['EM_CONF']['download_password'].'</td>'.$this->helpCol('download_password').'</tr>'; 01810 01811 // Installation status: 01812 $lines[]='<tr><td> </td><td></td>'.$this->helpCol('').'</tr>'; 01813 $lines[]='<tr class="bgColor5"><td colspan="2"><strong>Installation status:</strong></td>'.$this->helpCol('').'</tr>'; 01814 if (!$remote) { 01815 $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>'; 01816 $lines[]='<tr class="bgColor4"><td>Double installs?</td><td>'.$this->extInformationArray_dbInst($extInfo['doubleInstall'],$extInfo['type']).'</td>'.$this->helpCol('doubleInstall').'</tr>'; 01817 } 01818 if (is_array($extInfo['files'])) { 01819 sort($extInfo['files']); 01820 $lines[]='<tr class="bgColor4"><td>Root files:</td><td>'.implode('<br />',$extInfo['files']).'</td>'.$this->helpCol('rootfiles').'</tr>'; 01821 } 01822 01823 if (!$remote) { 01824 $techInfo = $this->makeDetailedExtensionAnalysis($extKey,$extInfo,1); 01825 } else $techInfo = $extInfo['_TECH_INFO']; 01826 #debug($techInfo); 01827 01828 if ($techInfo['tables']||$techInfo['static']||$techInfo['fields']) { 01829 if (!$remote && t3lib_extMgm::isLoaded($extKey)) { 01830 $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!':''). 01831 ($techInfo['static_error']?'<strong>Static table error!</strong><br />The static tables are missing or empty!':'')); 01832 } else { 01833 $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!'; 01834 } 01835 } 01836 01837 $lines[]='<tr class="bgColor4"><td>Database requirements:</td><td>'.$this->extInformationArray_dbReq($techInfo,1).'</td>'.$this->helpCol('dbReq').'</tr>'; 01838 if (!$remote) $lines[]='<tr class="bgColor4"><td>Database status:</td><td>'.$tableStatus.'</td>'.$this->helpCol('dbStatus').'</tr>'; 01839 $lines[]='<tr class="bgColor4"><td>Flags:</td><td>'.(is_array($techInfo['flags'])?implode('<br />',$techInfo['flags']):'').'</td>'.$this->helpCol('flags').'</tr>'; 01840 $lines[]='<tr class="bgColor4"><td>Config template?</td><td>'.($techInfo['conf']?'Yes':'').'</td>'.$this->helpCol('conf').'</tr>'; 01841 $lines[]='<tr class="bgColor4"><td>TypoScript files:</td><td>'.(is_array($techInfo['TSfiles'])?implode('<br />',$techInfo['TSfiles']):'').'</td>'.$this->helpCol('TSfiles').'</tr>'; 01842 $lines[]='<tr class="bgColor4"><td>Language files:</td><td>'.(is_array($techInfo['locallang'])?implode('<br />',$techInfo['locallang']):'').'</td>'.$this->helpCol('locallang').'</tr>'; 01843 $lines[]='<tr class="bgColor4"><td>Upload folder:</td><td>'.($techInfo['uploadfolder']?$techInfo['uploadfolder']:'').'</td>'.$this->helpCol('uploadfolder').'</tr>'; 01844 $lines[]='<tr class="bgColor4"><td>Create directories:</td><td>'.(is_array($techInfo['createDirs'])?implode('<br />',$techInfo['createDirs']):'').'</td>'.$this->helpCol('createDirs').'</tr>'; 01845 $lines[]='<tr class="bgColor4"><td>Module names:</td><td>'.(is_array($techInfo['moduleNames'])?implode('<br />',$techInfo['moduleNames']):'').'</td>'.$this->helpCol('moduleNames').'</tr>'; 01846 $lines[]='<tr class="bgColor4"><td>Class names:</td><td>'.(is_array($techInfo['classes'])?implode('<br />',$techInfo['classes']):'').'</td>'.$this->helpCol('classNames').'</tr>'; 01847 $lines[]='<tr class="bgColor4"><td>Errors:</td><td>'.(is_array($techInfo['errors'])?$GLOBALS['TBE_TEMPLATE']->rfw(implode('<hr />',$techInfo['errors'])):'').'</td>'.$this->helpCol('errors').'</tr>'; 01848 $lines[]='<tr class="bgColor4"><td>Naming errors:</td><td>'.(is_array($techInfo['NSerrors'])? 01849 (!t3lib_div::inList($this->nameSpaceExceptions,$extKey)?t3lib_div::view_array($techInfo['NSerrors']):$GLOBALS['TBE_TEMPLATE']->dfw('[exception]')) 01850 :'').'</td>'.$this->helpCol('NSerrors').'</tr>'; 01851 01852 01853 if (!$remote) { 01854 $currentMd5Array = $this->serverExtensionMD5Array($extKey,$extInfo); 01855 $affectedFiles=''; 01856 01857 $msgLines=array(); 01858 # $msgLines[] = 'Files: '.count($currentMd5Array); 01859 if (strcmp($extInfo['EM_CONF']['_md5_values_when_last_written'],serialize($currentMd5Array))) { 01860 $msgLines[] = $GLOBALS['TBE_TEMPLATE']->rfw('<br /><strong>A difference between the originally installed version and the current was detected!</strong>'); 01861 $affectedFiles = $this->findMD5ArrayDiff($currentMd5Array,unserialize($extInfo['EM_CONF']['_md5_values_when_last_written'])); 01862 if (count($affectedFiles)) $msgLines[] = '<br /><strong>Modified files:</strong><br />'.$GLOBALS['TBE_TEMPLATE']->rfw(implode('<br />',$affectedFiles)); 01863 } 01864 $lines[]='<tr class="bgColor4"><td>Files changed?</td><td>'.implode('<br />',$msgLines).'</td>'.$this->helpCol('filesChanged').'</tr>'; 01865 } 01866 01867 return '<table border="0" cellpadding="1" cellspacing="2"> 01868 '.implode(' 01869 ',$lines).' 01870 </table>'; 01871 } 01872 01880 function extInformationArray_dbReq($techInfo,$tableHeader=0) { 01881 return nl2br(trim((is_array($techInfo['tables'])?($tableHeader?"\n\n<strong>Tables:</strong>\n":'').implode(chr(10),$techInfo['tables']):''). 01882 (is_array($techInfo['static'])?"\n\n<strong>Static tables:</strong>\n".implode(chr(10),$techInfo['static']):''). 01883 (is_array($techInfo['fields'])?"\n\n<strong>Additional fields:</strong>\n".implode('<hr />',$techInfo['fields']):''))); 01884 } 01885 01893 function extInformationArray_dbInst($dbInst,$current) { 01894 if (strlen($dbInst)>1) { 01895 $others = array(); 01896 for($a=0;$a<strlen($dbInst);$a++) { 01897 if (substr($dbInst,$a,1)!=$current) { 01898 $others[]='"'.$this->typeLabels[substr($dbInst,$a,1)].'"'; 01899 } 01900 } 01901 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.'); 01902 } else return ''; 01903 } 01904 01912 function getRepositoryUploadForm($extKey,$extInfo) { 01913 $uArr = $this->makeUploadArray($extKey,$extInfo); 01914 if (is_array($uArr)) { 01915 $backUpData = $this->makeUploadDataFromArray($uArr); 01916 01917 #debug($this->decodeExchangeData($backUpData)); 01918 $content.='Extension "'.$this->extensionTitleIconHeader($extKey,$extInfo).'" is ready to be uploaded.<br /> 01919 The size of the upload is <strong>'.t3lib_div::formatSize(strlen($backUpData)).'</strong><br /> 01920 '; 01921 01922 $b64data = base64_encode($backUpData); 01923 $content='</form><form action="'.$this->repositoryUrl.'" method="post" enctype="application/x-www-form-urlencoded"> 01924 <input type="hidden" name="tx_extrep[upload][returnUrl]" value="'.htmlspecialchars($this->makeReturnUrl()).'" /> 01925 <input type="hidden" name="tx_extrep[upload][data]" value="'.$b64data.'" /> 01926 <input type="hidden" name="tx_extrep[upload][typo3ver]" value="'.$GLOBALS['TYPO_VERSION'].'" /> 01927 <input type="hidden" name="tx_extrep[upload][os]" value="'.TYPO3_OS.'" /> 01928 <input type="hidden" name="tx_extrep[upload][sapi]" value="'.php_sapi_name().'" /> 01929 <input type="hidden" name="tx_extrep[upload][phpver]" value="'.phpversion().'" /> 01930 <input type="hidden" name="tx_extrep[upload][gzcompressed]" value="'.$this->gzcompress.'" /> 01931 <input type="hidden" name="tx_extrep[upload][data_md5]" value="'.md5($b64data).'" /> 01932 <table border="0" cellpadding="2" cellspacing="1"> 01933 <tr class="bgColor4"> 01934 <td>Repository Username:</td> 01935 <td><input'.$this->doc->formWidth(20).' type="text" name="tx_extrep[user][fe_u]" value="'.$this->fe_user['username'].'" /></td> 01936 </tr> 01937 <tr class="bgColor4"> 01938 <td>Repository Password:</td> 01939 <td><input'.$this->doc->formWidth(20).' type="password" name="tx_extrep[user][fe_p]" value="'.$this->fe_user['password'].'" /></td> 01940 </tr> 01941 <tr class="bgColor4"> 01942 <td>Upload password for this extension:</td> 01943 <td><input'.$this->doc->formWidth(30).' type="password" name="tx_extrep[upload][upload_p]" value="'.$this->fe_user['uploadPass'].'" /></td> 01944 </tr> 01945 <tr class="bgColor4"> 01946 <td>Changelog for upload:</td> 01947 <td><textarea'.$this->doc->formWidth(30,1).' rows="5" name="tx_extrep[upload][comment]"></textarea></td> 01948 </tr> 01949 <tr class="bgColor4"> 01950 <td>Upload command:</td> 01951 <td nowrap="nowrap"> 01952 <input type="radio" name="tx_extrep[upload][mode]" value="new_dev" checked="checked" /> New development version (latest x.x.<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('x+1').'</strong>)<br /> 01953 <input type="radio" name="tx_extrep[upload][mode]" value="latest" /> Override <em>this</em> development version ('.$extInfo['EM_CONF']['version'].')<br /> 01954 <input type="radio" name="tx_extrep[upload][mode]" value="new_sub" /> New sub version (latest x.<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('x+1').'</strong>.0)<br /> 01955 <input type="radio" name="tx_extrep[upload][mode]" value="new_main" /> New main version (latest <strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('x+1').'</strong>.0.0)<br /> 01956 </td> 01957 </tr> 01958 <!-- Removing "private keys" since they are probably not used much. Better option for people is to distribute "private" extensions as files by emails. 01959 <tr class="bgColor4"> 01960 <td>Private?</td> 01961 <td> 01962 <input type="checkbox" name="tx_extrep[upload][private]" value="1"'.($extInfo['EM_CONF']['private'] ? ' checked="checked"' : '').' />Yes, dont show <em>this upload</em> in the public list.<br /> 01963 ("Private" uploads requires you to manually enter a special key (which will be shown to you after the upload has been completed) to be able to import and view details for the upload. This is nice when you are working on something internally which you do not want others to look at.)<br /> 01964 <br /><strong>Additional import password:</strong><br /> 01965 <input'.$this->doc->formWidth(20).' type="text" name="tx_extrep[upload][download_password]" value="'.htmlspecialchars(trim($extInfo['EM_CONF']['download_password'])).'" /> (Textfield!) <br /> 01966 (Anybody who knows the "special key" assigned to the private upload will be able to import it. Specifying an import password allows you to give away the download key for private uploads and also require a password given in addition. The password can be changed later on.)<br /> 01967 </td> 01968 </tr> 01969 --> 01970 <tr class="bgColor4"> 01971 <td> </td> 01972 <td><input type="submit" name="submit" value="Upload extension" /><br /> 01973 '.t3lib_div::formatSize(strlen($b64data)).($this->gzcompress?", compressed":"").', base64<br /> 01974 <br /> 01975 01976 </td> 01977 </tr> 01978 </table> 01979 '; 01980 01981 return $content; 01982 } else { 01983 return $uArr; 01984 } 01985 } 01986 01987 01988 01989 01990 01991 01992 01993 01994 01995 01996 /*********************************** 01997 * 01998 * Extension list rendering 01999 * 02000 **********************************/ 02001 02010 function extensionListRowHeader($trAttrib,$cells,$import=0) { 02011 $cells[] = '<td></td>'; 02012 $cells[] = '<td>Title:</td>'; 02013 02014 if (!$this->MOD_SETTINGS['display_details']) { 02015 $cells[] = '<td>Description:</td>'; 02016 $cells[] = '<td>Author:</td>'; 02017 } elseif ($this->MOD_SETTINGS['display_details']==2) { 02018 $cells[] = '<td>Priority:</td>'; 02019 $cells[] = '<td>Mod.Tables:</td>'; 02020 $cells[] = '<td>Modules:</td>'; 02021 $cells[] = '<td>Cl.Cache?</td>'; 02022 $cells[] = '<td>Internal?</td>'; 02023 $cells[] = '<td>Shy?</td>'; 02024 } elseif ($this->MOD_SETTINGS['display_details']==3) { 02025 $cells[] = '<td>Tables/Fields:</td>'; 02026 $cells[] = '<td>TS-files:</td>'; 02027 $cells[] = '<td>Affects:</td>'; 02028 $cells[] = '<td>Modules:</td>'; 02029 $cells[] = '<td>Config?</td>'; 02030 $cells[] = '<td>Errors:</td>'; 02031 } elseif ($this->MOD_SETTINGS['display_details']==4) { 02032 $cells[] = '<td>locallang:</td>'; 02033 $cells[] = '<td>Classes:</td>'; 02034 $cells[] = '<td>Errors:</td>'; 02035 $cells[] = '<td>NameSpace Errors:</td>'; 02036 } elseif ($this->MOD_SETTINGS['display_details']==5) { 02037 $cells[] = '<td>Changed files:</td>'; 02038 } else { 02039 $cells[] = '<td>Extension key:</td>'; 02040 $cells[] = '<td>Version:</td>'; 02041 if (!$import) { 02042 $cells[] = '<td>DL:</td>'; 02043 $cells[] = '<td>Doc:</td>'; 02044 $cells[] = '<td>Type:</td>'; 02045 } else { 02046 $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>'; 02047 $cells[] = '<td class="bgColor6"'.$this->labelInfo('Current type of installation of the extension on this server.').'>Cur. Type:</td>'; 02048 $cells[] = '<td'.$this->labelInfo('If blank, everyone has access to this extension. "Owner" means that you see it ONLY because you are the owner. "Member" means you see it ONLY because you are among the project members.').'>Access:</td>'; 02049 $cells[] = '<td'.$this->labelInfo('TYPO3 version of last uploading server.').'>T3 ver:</td>'; 02050 $cells[] = '<td'.$this->labelInfo('PHP version of last uploading server.').'>PHP:</td>'; 02051 $cells[] = '<td'.$this->labelInfo('Size of extension, uncompressed / compressed').'>Size:</td>'; 02052 $cells[] = '<td'.$this->labelInfo('Number of downloads, all versions/this version').'>DL:</td>'; 02053 } 02054 $cells[] = '<td>State:</td>'; 02055 $cells[] = '<td>Dependencies:</td>'; 02056 } 02057 return ' 02058 <tr'.$trAttrib.'> 02059 '.implode(' 02060 ',$cells).' 02061 </tr>'; 02062 } 02063 02076 function extensionListRow($extKey,$extInfo,$cells,$bgColorClass='',$inst_list=array(),$import=0,$altLinkUrl='') { 02077 02078 // Initialize: 02079 $style = t3lib_extMgm::isLoaded($extKey) ? '' : ' style="color:#666666;"'; 02080 02081 // Icon: 02082 $imgInfo = @getImageSize($this->getExtPath($extKey,$extInfo['type']).'/ext_icon.gif'); 02083 if (is_array($imgInfo)) { 02084 $cells[] = '<td><img src="'.$GLOBALS['BACK_PATH'].$this->typeRelPaths[$extInfo['type']].$extKey.'/ext_icon.gif'.'" '.$imgInfo[3].' alt="" /></td>'; 02085 } elseif ($extInfo['_ICON']) { 02086 $cells[] = '<td>'.$extInfo['_ICON'].'</td>'; 02087 } else { 02088 $cells[] = '<td><img src="clear.gif" width="1" height="1" alt="" /></td>'; 02089 } 02090 02091 // Extension title: 02092 $cells[] = '<td nowrap="nowrap"><a href="'.htmlspecialchars($altLinkUrl?$altLinkUrl:'index.php?CMD[showExt]='.$extKey.'&SET[singleDetails]=info').'" title="'.$extKey.'"'.$style.'>'.t3lib_div::fixed_lgd($extInfo['EM_CONF']['title']?$extInfo['EM_CONF']['title']:'<em>'.$extKey.'</em>',40).'</a></td>'; 02093 02094 // Unset extension key in installed keys array (for tracking) 02095 if (isset($inst_list[$extKey])) { 02096 unset($this->inst_keys[$extKey]); 02097 } 02098 02099 // Based on which display mode you will see more or less details: 02100 if (!$this->MOD_SETTINGS['display_details']) { 02101 $cells[] = '<td>'.htmlspecialchars(t3lib_div::fixed_lgd($extInfo['EM_CONF']['description'],400)).'<br /><img src="clear.gif" width="300" height="1" alt="" /></td>'; 02102 $cells[] = '<td nowrap="nowrap">'.htmlspecialchars($extInfo['EM_CONF']['author'].($extInfo['EM_CONF']['author_company'] ? '<br />'.$extInfo['EM_CONF']['author_company'] : '')).'</td>'; 02103 } elseif ($this->MOD_SETTINGS['display_details']==2) { 02104 $cells[] = '<td nowrap="nowrap">'.$extInfo['EM_CONF']['priority'].'</td>'; 02105 $cells[] = '<td nowrap="nowrap">'.implode('<br />',t3lib_div::trimExplode(',',$extInfo['EM_CONF']['modify_tables'],1)).'</td>'; 02106 $cells[] = '<td nowrap="nowrap">'.$extInfo['EM_CONF']['module'].'</td>'; 02107 $cells[] = '<td nowrap="nowrap">'.($extInfo['EM_CONF']['clearCacheOnLoad'] ? 'Yes' : '').'</td>'; 02108 $cells[] = '<td nowrap="nowrap">'.($extInfo['EM_CONF']['internal'] ? 'Yes' : '').'</td>'; 02109 $cells[] = '<td nowrap="nowrap">'.($extInfo['EM_CONF']['shy'] ? 'Yes' : '').'</td>'; 02110 } elseif ($this->MOD_SETTINGS['display_details']==3) { 02111 $techInfo = $this->makeDetailedExtensionAnalysis($extKey,$extInfo); 02112 02113 $cells[] = '<td>'.$this->extInformationArray_dbReq($techInfo). 02114 '</td>'; 02115 $cells[] = '<td nowrap="nowrap">'.(is_array($techInfo['TSfiles']) ? implode('<br />',$techInfo['TSfiles']) : '').'</td>'; 02116 $cells[] = '<td nowrap="nowrap">'.(is_array($techInfo['flags']) ? implode('<br />',$techInfo['flags']) : '').'</td>'; 02117 $cells[] = '<td nowrap="nowrap">'.(is_array($techInfo['moduleNames']) ? implode('<br />',$techInfo['moduleNames']) : '').'</td>'; 02118 $cells[] = '<td nowrap="nowrap">'.($techInfo['conf'] ? 'Yes' : '').'</td>'; 02119 $cells[] = '<td>'. 02120 $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!':''). 02121 (t3lib_extMgm::isLoaded($extKey)&&$techInfo['static_error']?'<strong>Static table error!</strong><br />The static tables are missing or empty!':'')). 02122 '</td>'; 02123 } elseif ($this->MOD_SETTINGS['display_details']==4) { 02124 $techInfo=$this->makeDetailedExtensionAnalysis($extKey,$extInfo,1); 02125 02126 $cells[] = '<td>'.(is_array($techInfo['locallang']) ? implode('<br />',$techInfo['locallang']) : '').'</td>'; 02127 $cells[] = '<td>'.(is_array($techInfo['classes']) ? implode('<br />',$techInfo['classes']) : '').'</td>'; 02128 $cells[] = '<td>'.(is_array($techInfo['errors']) ? $GLOBALS['TBE_TEMPLATE']->rfw(implode('<hr />',$techInfo['errors'])) : '').'</td>'; 02129 $cells[] = '<td>'.(is_array($techInfo['NSerrors']) ? (!t3lib_div::inList($this->nameSpaceExceptions,$extKey) ? t3lib_div::view_array($techInfo['NSerrors']) : $GLOBALS['TBE_TEMPLATE']->dfw('[exception]')) :'').'</td>'; 02130 } elseif ($this->MOD_SETTINGS['display_details']==5) { 02131 $currentMd5Array = $this->serverExtensionMD5Array($extKey,$extInfo); 02132 $affectedFiles = ''; 02133 $msgLines = array(); 02134 $msgLines[] = 'Files: '.count($currentMd5Array); 02135 if (strcmp($extInfo['EM_CONF']['_md5_values_when_last_written'],serialize($currentMd5Array))) { 02136 $msgLines[] = $GLOBALS['TBE_TEMPLATE']->rfw('<br /><strong>A difference between the originally installed version and the current was detected!</strong>'); 02137 $affectedFiles = $this->findMD5ArrayDiff($currentMd5Array,unserialize($extInfo['EM_CONF']['_md5_values_when_last_written'])); 02138 if (count($affectedFiles)) $msgLines[] = '<br /><strong>Modified files:</strong><br />'.$GLOBALS['TBE_TEMPLATE']->rfw(implode('<br />',$affectedFiles)); 02139 } 02140 $cells[] = '<td>'.implode('<br />',$msgLines).'</td>'; 02141 } else { 02142 // Default view: 02143 $verDiff = $inst_list[$extKey] && $this->versionDifference($extInfo['EM_CONF']['version'],$inst_list[$extKey]['EM_CONF']['version'],$this->versionDiffFactor); 02144 02145 $cells[] = '<td nowrap="nowrap"><em>'.$extKey.'</em></td>'; 02146 $cells[] = '<td nowrap="nowrap">'.($verDiff ? '<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw(htmlspecialchars($extInfo['EM_CONF']['version'])).'</strong>' : $extInfo['EM_CONF']['version']).'</td>'; 02147 if (!$import) { // Listing extenson on LOCAL server: 02148 // Extension Download: 02149 $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>'; 02150 02151 // Manual download 02152 $fileP = PATH_site.$this->typePaths[$extInfo['type']].$extKey.'/doc/manual.sxw'; 02153 $cells[] = '<td nowrap="nowrap">'. 02154 ($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>':''). 02155 '</td>'; 02156 $cells[] = '<td nowrap="nowrap">'.$this->typeLabels[$extInfo['type']].(strlen($extInfo['doubleInstall'])>1?'<strong> '.$GLOBALS['TBE_TEMPLATE']->rfw($extInfo['doubleInstall']).'</strong>':'').'</td>'; 02157 } else { // Listing extensions from REMOTE repository: 02158 $inst_curVer = $inst_list[$extKey]['EM_CONF']['version']; 02159 if (isset($inst_list[$extKey])) { 02160 if ($verDiff) $inst_curVer = '<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw($inst_curVer).'</strong>'; 02161 } 02162 $cells[] = '<td nowrap="nowrap">'.$inst_curVer.'</td>'; 02163 $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>'; 02164 $cells[] = '<td nowrap="nowrap"><strong>'.$GLOBALS['TBE_TEMPLATE']->rfw($this->remoteAccess[$extInfo['_ACCESS']]).'</strong></td>'; 02165 $cells[] = '<td nowrap="nowrap">'.$extInfo['EM_CONF']['_typo3_ver'].'</td>'; 02166 $cells[] = '<td nowrap="nowrap">'.$extInfo['EM_CONF']['_php_ver'].'</td>'; 02167 $cells[] = '<td nowrap="nowrap">'.$extInfo['EM_CONF']['_size'].'</td>'; 02168 $cells[] = '<td nowrap="nowrap">'.($extInfo['_STAT_IMPORT']['extension_allversions']?$extInfo['_STAT_IMPORT']['extension_allversions']:' ').'/'.($extInfo['_STAT_IMPORT']['extension_thisversion']?$extInfo['_STAT_IMPORT']['extension_thisversion']:' ').'</td>'; 02169 } 02170 $cells[] = '<td nowrap="nowrap">'.$this->states[$extInfo['EM_CONF']['state']].'</td>'; 02171 $cells[] = '<td nowrap="nowrap">'.$extInfo['EM_CONF']['dependencies'].'</td>'; 02172 } 02173 02174 $bgColor = ' class="'.($bgColorClass?$bgColorClass:'bgColor4').'"'; 02175 return ' 02176 <tr'.$bgColor.$style.'> 02177 '.implode(' 02178 ',$cells).' 02179 </tr>'; 02180 } 02181 02182 02183 02184 02185 02186 02187 02188 02189 02190 02191 /************************************ 02192 * 02193 * Output helper functions 02194 * 02195 ************************************/ 02196 02204 function wrapEmail($str,$email) { 02205 if ($email) { 02206 $str = '<a href="mailto:'.htmlspecialchars($email).'">'.htmlspecialchars($str).'</a>'; 02207 } 02208 return $str; 02209 } 02210 02217 function helpCol($key) { 02218 global $BE_USER; 02219 if ($BE_USER->uc['edit_showFieldHelp']) { 02220 $hT = trim(t3lib_BEfunc::helpText($this->descrTable,'emconf_'.$key,$this->doc->backPath)); 02221 return '<td>'.($hT?$hT:t3lib_BEfunc::helpTextIcon($this->descrTable,'emconf_'.$key,$this->doc->backPath)).'</td>'; 02222 } 02223 } 02224 02231 function labelInfo($str) { 02232 return ' title="'.htmlspecialchars($str).'" style="cursor:help;"'; 02233 } 02234 02243 function extensionTitleIconHeader($extKey,$extInfo,$align='top') { 02244 $imgInfo = @getImageSize($this->getExtPath($extKey,$extInfo['type']).'/ext_icon.gif'); 02245 $out = ''; 02246 if (is_array($imgInfo)) { 02247 $out.= '<img src="'.$GLOBALS['BACK_PATH'].$this->typeRelPaths[$extInfo['type']].$extKey.'/ext_icon.gif" '.$imgInfo[3].' align="'.$align.'" alt="" />'; 02248 } 02249 $out.= $extInfo['EM_CONF']['title'] ? htmlspecialchars(t3lib_div::fixed_lgd($extInfo['EM_CONF']['title'],40)) : '<em>'.$extKey.'</em>'; 02250 return $out; 02251 } 02252 02258 function removeButton() { 02259 return '<img src="uninstall.gif" width="16" height="16" title="Remove extension" align="top" alt="" />'; 02260 } 02261 02267 function installButton() { 02268 return '<img src="install.gif" width="16" height="16" title="Install extension..." align="top" alt="" />'; 02269 } 02270 02276 function noImportMsg() { 02277 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>'; 02278 } 02279 02280 02281 02282 02283 02284 02285 02286 02287 02288 02289 /******************************** 02290 * 02291 * Read information about all available extensions 02292 * 02293 *******************************/ 02294 02301 function getInstalledExtensions() { 02302 $list = array(); 02303 $cat = $this->defaultCategories; 02304 02305 $path = PATH_site.TYPO3_mainDir.'sysext/'; 02306 $this->getInstExtList($path,$list,$cat,'S'); 02307 02308 $path = PATH_site.TYPO3_mainDir.'ext/'; 02309 $this->getInstExtList($path,$list,$cat,'G'); 02310 02311 $path = PATH_site.'typo3conf/ext/'; 02312 $this->getInstExtList($path,$list,$cat,'L'); 02313 02314 return array($list,$cat); 02315 } 02316 02328 function getInstExtList($path,&$list,&$cat,$type) { 02329 02330 if (@is_dir($path)) { 02331 $extList = t3lib_div::get_dirs($path); 02332 if (is_array($extList)) { 02333 foreach($extList as $extKey) { 02334 if (@is_file($path.$extKey.'/ext_emconf.php')) { 02335 $emConf = $this->includeEMCONF($path.$extKey.'/ext_emconf.php', $extKey); 02336 if (is_array($emConf)) { 02337 # unset($emConf['_md5_values_when_last_written']); // Trying to save space - hope this doesn't break anything. Shaves of maybe 100K! 02338 # unset($emConf['description']); // Trying to save space - hope this doesn't break anything 02339 if (is_array($list[$extKey])) { 02340 $list[$extKey]=array('doubleInstall'=>$list[$extKey]['doubleInstall']); 02341 } 02342 $list[$extKey]['doubleInstall'].= $type; 02343 $list[$extKey]['type'] = $type; 02344 $list[$extKey]['EM_CONF'] = $emConf; 02345 # $list[$extKey]['files'] = array_keys(array_flip(t3lib_div::getFilesInDir($path.$extKey))); // Shaves off a little by using num-indexes 02346 $list[$extKey]['files'] = t3lib_div::getFilesInDir($path.$extKey); 02347 02348 $this->setCat($cat,$list[$extKey], $extKey); 02349 } 02350 } 02351 } 02352 } 02353 } 02354 } 02355 02362 function getImportExtList($listArr) { 02363 $list = array(); 02364 $cat = $this->defaultCategories; 02365 02366 if (is_array($listArr)) { 02367 02368 foreach($listArr as $dat) { 02369 $extKey = $dat['extension_key']; 02370 $list[$extKey]['type'] = '_'; 02371 $list[$extKey]['extRepUid'] = $dat['uid']; 02372 $list[$extKey]['_STAT_IMPORT'] = $dat['_STAT_IMPORT']; 02373 $list[$extKey]['_ACCESS'] = $dat['_ACCESS']; 02374 $list[$extKey]['_ICON'] = $dat['_ICON']; 02375 $list[$extKey]['_MEMBERS_ONLY'] = $dat['_MEMBERS_ONLY']; 02376 $list[$extKey]['EM_CONF'] = array( 02377 'title' => $dat['emconf_title'], 02378 'description' => $dat['emconf_description'], 02379 'category' => $dat['emconf_category'], 02380 'shy' => $dat['emconf_shy'], 02381 'dependencies' => $dat['emconf_dependencies'], 02382 'state' => $dat['emconf_state'], 02383 'private' => $dat['emconf_private'], 02384 'uploadfolder' => $dat['emconf_uploadfolder'], 02385 'createDirs' => $dat['emconf_createDirs'], 02386 'modify_tables' => $dat['emconf_modify_tables'], 02387 'module' => $dat['emconf_module'], 02388 'lockType' => $dat['emconf_lockType'], 02389 'clearCacheOnLoad' => $dat['emconf_clearCacheOnLoad'], 02390 'priority' => $dat['emconf_priority'], 02391 'version' => $dat['version'], 02392 'internal' => $dat['emconf_internal'], 02393 'author' => $dat['emconf_author'], 02394 'author_company' => $dat['emconf_author_company'], 02395 02396 '_typo3_ver' => $dat['upload_typo3_version'], 02397 '_php_ver' => $dat['upload_php_version'], 02398 '_size' => t3lib_div::formatSize($dat['datasize']).'/'.t3lib_div::formatSize($dat['datasize_gz']), 02399 ); 02400 $this->setCat($cat, $list[$extKey], $extKey); 02401 } 02402 } 02403 return array($list,$cat); 02404 } 02405 02414 function setCat(&$cat,$listArrayPart,$extKey) { 02415 02416 // Getting extension title: 02417 $extTitle = $listArrayPart['EM_CONF']['title']; 02418 02419 // Category index: 02420 $index = $listArrayPart['EM_CONF']['category']; 02421 $cat['cat'][$index][$extKey] = $extTitle; 02422 02423 // Author index: 02424 $index = $listArrayPart['EM_CONF']['author'].($listArrayPart['EM_CONF']['author_company']?', '.$listArrayPart['EM_CONF']['author_company']:''); 02425 $cat['author_company'][$index][$extKey] = $extTitle; 02426 02427 // State index: 02428 $index = $listArrayPart['EM_CONF']['state']; 02429 $cat['state'][$index][$extKey] = $extTitle; 02430 02431 // Private index: 02432 $index = $listArrayPart['EM_CONF']['private'] ? 1 : 0; 02433 $cat['private'][$index][$extKey] = $extTitle; 02434 02435 // Type index: 02436 $index = $listArrayPart['type']; 02437 $cat['type'][$index][$extKey] = $extTitle; 02438 02439 // Dependencies: 02440 if ($list[$extKey]['EM_CONF']['dependencies']) { 02441 $depItems = t3lib_div::trimExplode(',', $list[$extKey]['EM_CONF']['dependencies'], 1); 02442 foreach($depItems as $depKey) { 02443 $cat['dep'][$depKey][$extKey] = $extTitle; 02444 } 02445 } 02446 02447 // Return categories: 02448 return $cat; 02449 } 02450 02451 02452 02453 02454 02455 02456 02457 02458 02459 02460 /******************************* 02461 * 02462 * Extension analyzing (detailed information) 02463 * 02464 ******************************/ 02465 02476 function makeDetailedExtensionAnalysis($extKey,$extInfo,$validity=0) { 02477 02478 // Get absolute path of the extension 02479 $absPath = $this->getExtPath($extKey,$extInfo['type']); 02480 02481 $infoArray = array(); 02482 02483 $table_class_prefix = substr($extKey,0,5)=='user_' ? 'user_' : 'tx_'.str_replace('_','',$extKey).'_'; 02484 $module_prefix = substr($extKey,0,5)=='user_' ? 'u' : 'tx'.str_replace('_','',$extKey); 02485 02486 // Database status: 02487 $dbInfo = $this->checkDBupdates($extKey,$extInfo,1); 02488 02489 // Database structure required: 02490 if (is_array($dbInfo['structure']['tables_fields'])) { 02491 $modify_tables = t3lib_div::trimExplode(',',$extInfo['EM_CONF']['modify_tables'],1); 02492 $infoArray['dump_tf'] = array(); 02493 02494 foreach($dbInfo['structure']['tables_fields'] as $tN => $d) { 02495 if (in_array($tN,$modify_tables)) { 02496 $infoArray['fields'][] = $tN.': <i>'. 02497 (is_array($d['fields']) ? implode(', ',array_keys($d['fields'])) : ''). 02498 (is_array($d['keys']) ? ' + '.count($d['keys']).' keys' : ''). 02499 '</i>'; 02500 if (is_array($d['fields'])) { 02501 reset($d['fields']); 02502 while(list($fN) = each($d['fields'])) { 02503 $infoArray['dump_tf'][] = $tN.'.'.$fN; 02504 if (!t3lib_div::isFirstPartOfStr($fN,$table_class_prefix)) { 02505 $infoArray['NSerrors']['fields'][$fN] = $fN; 02506 } else { 02507 $infoArray['NSok']['fields'][$fN] = $fN; 02508 } 02509 } 02510 } 02511 if (is_array($d['keys'])) { 02512 reset($d['keys']); 02513 while(list($fN)=each($d['keys'])) { 02514 $infoArray['dump_tf'][] = $tN.'.KEY:'.$fN; 02515 } 02516 } 02517 } else { 02518 $infoArray['dump_tf'][] = $tN; 02519 $infoArray['tables'][] = $tN; 02520 if (!t3lib_div::isFirstPartOfStr($tN,$table_class_prefix)) { 02521 $infoArray['NSerrors']['tables'][$tN] = $tN; 02522 } else $infoArray['NSok']['tables'][$tN] = $tN; 02523 } 02524 } 02525 if (count($dbInfo['structure']['diff']['diff']) || count($dbInfo['structure']['diff']['extra'])) { 02526 $msg = array(); 02527 if (count($dbInfo['structure']['diff']['diff'])) $msg[] = 'missing'; 02528 if (count($dbInfo['structure']['diff']['extra'])) $msg[] = 'of wrong type'; 02529 $infoArray['tables_error'] = 1; 02530 if (t3lib_extMgm::isLoaded($extKey)) $infoArray['errors'][] = 'Some tables or fields are '.implode(' and ',$msg).'!'; 02531 } 02532 } 02533 02534 // Static tables? 02535 if (is_array($dbInfo['static'])) { 02536 $infoArray['static'] = array_keys($dbInfo['static']); 02537 02538 foreach($dbInfo['static'] as $tN => $d) { 02539 if (!$d['exists']) { 02540 $infoArray['static_error'] = 1; 02541 if (t3lib_extMgm::isLoaded($extKey)) $infoArray['errors'][] = 'Static table(s) missing!'; 02542 if (!t3lib_div::isFirstPartOfStr($tN,$table_class_prefix)) { 02543 $infoArray['NSerrors']['tables'][$tN] = $tN; 02544 } else $infoArray['NSok']['tables'][$tN] = $tN; 02545 } 02546 } 02547 } 02548 02549 // Backend Module-check: 02550 $knownModuleList = t3lib_div::trimExplode(',',$extInfo['EM_CONF']['module'],1); 02551 foreach($knownModuleList as $mod) { 02552 if (@is_dir($absPath.$mod)) { 02553 if (@is_file($absPath.$mod.'/conf.php')) { 02554 $confFileInfo = $this->modConfFileAnalysis($absPath.$mod.'/conf.php'); 02555 if (is_array($confFileInfo['TYPO3_MOD_PATH'])) { 02556 $shouldBePath = $this->typeRelPaths[$extInfo['type']].$extKey.'/'.$mod.'/'; 02557 if (strcmp($confFileInfo['TYPO3_MOD_PATH'][1][1],$shouldBePath)) { 02558 $infoArray['errors'][] = 'Configured TYPO3_MOD_PATH "'.$confFileInfo['TYPO3_MOD_PATH'][1][1].'" different from "'.$shouldBePath.'"'; 02559 } 02560 } else $infoArray['errors'][] = 'No definition of TYPO3_MOD_PATH constant found inside!'; 02561 if (is_array($confFileInfo['MCONF_name'])) { 02562 $mName = $confFileInfo['MCONF_name'][1][1]; 02563 $mNameParts = explode('_',$mName); 02564 $infoArray['moduleNames'][] = $mName; 02565 if (!t3lib_div::isFirstPartOfStr($mNameParts[0],$module_prefix) && 02566 (!$mNameParts[1] || !t3lib_div::isFirstPartOfStr($mNameParts[1],$module_prefix))) { 02567 $infoArray['NSerrors']['modname'][] = $mName; 02568 } else $infoArray['NSok']['modname'][] = $mName; 02569 } else $infoArray['errors'][] = 'No definition of MCONF[name] variable found inside!'; 02570 } else $infoArray['errors'][] = 'Backend module conf file "'.$mod.'/conf.php" should exist but does not!'; 02571 } else $infoArray['errors'][] = 'Backend module folder "'.$mod.'/" should exist but does not!'; 02572 } 02573 $dirs = t3lib_div::get_dirs($absPath); 02574 if (is_array($dirs)) { 02575 reset($dirs); 02576 while(list(,$mod) = each($dirs)) { 02577 if (!in_array($mod,$knownModuleList) && @is_file($absPath.$mod.'/conf.php')) { 02578 $confFileInfo = $this->modConfFileAnalysis($absPath.$mod.'/conf.php'); 02579 if (is_array($confFileInfo)) { 02580 $infoArray['errors'][] = 'It seems like there is a backend module in "'.$mod.'/conf.php" which is not configured in ext_emconf.php'; 02581 } 02582 } 02583 } 02584 } 02585 02586 // ext_tables.php: 02587 if (@is_file($absPath.'ext_tables.php')) { 02588 $content = t3lib_div::getUrl($absPath.'ext_tables.php'); 02589 if (stristr($content,'t3lib_extMgm::addModule')) $infoArray['flags'][] = 'Module'; 02590 if (stristr($content,'t3lib_extMgm::insertModuleFunction')) $infoArray['flags'][] = 'Module+'; 02591 if (stristr($content,'t3lib_div::loadTCA')) $infoArray['flags'][] = 'loadTCA'; 02592 if (stristr($content,'$TCA[')) $infoArray['flags'][] = 'TCA'; 02593 if (stristr($content,'t3lib_extMgm::addPlugin')) $infoArray['flags'][] = 'Plugin'; 02594 } 02595 02596 // ext_localconf.php: 02597 if (@is_file($absPath.'ext_localconf.php')) { 02598 $content = t3lib_div::getUrl($absPath.'ext_localconf.php'); 02599 if (stristr($content,'t3lib_extMgm::addPItoST43')) $infoArray['flags'][]='Plugin/ST43'; 02600 if (stristr($content,'t3lib_extMgm::addPageTSConfig')) $infoArray['flags'][]='Page-TSconfig'; 02601 if (stristr($content,'t3lib_extMgm::addUserTSConfig')) $infoArray['flags'][]='User-TSconfig'; 02602 if (stristr($content,'t3lib_extMgm::addTypoScriptSetup')) $infoArray['flags'][]='TS/Setup'; 02603 if (stristr($content,'t3lib_extMgm::addTypoScriptConstants')) $infoArray['flags'][]='TS/Constants'; 02604 } 02605 02606 if (@is_file($absPath.'ext_typoscript_constants.txt')) { 02607 $infoArray['TSfiles'][] = 'Constants'; 02608 } 02609 if (@is_file($absPath.'ext_typoscript_setup.txt')) { 02610 $infoArray['TSfiles'][] = 'Setup'; 02611 } 02612 if (@is_file($absPath.'ext_conf_template.txt')) { 02613 $infoArray['conf'] = 1; 02614 } 02615 02616 // Classes: 02617 if ($validity) { 02618 $filesInside = $this->getClassIndexLocallangFiles($absPath,$table_class_prefix,$extKey); 02619 if (is_array($filesInside['errors'])) $infoArray['errors'] = array_merge((array)$infoArray['errors'],$filesInside['errors']); 02620 if (is_array($filesInside['NSerrors'])) $infoArray['NSerrors'] = array_merge((array)$infoArray['NSerrors'],$filesInside['NSerrors']); 02621 if (is_array($filesInside['NSok'])) $infoArray['NSok'] = array_merge((array)$infoArray['NSok'],$filesInside['NSok']); 02622 $infoArray['locallang'] = $filesInside['locallang']; 02623 $infoArray['classes'] = $filesInside['classes']; 02624 } 02625 02626 // Upload folders 02627 if ($extInfo['EM_CONF']['uploadfolder']) { 02628 $infoArray['uploadfolder'] = $this->ulFolder($extKey); 02629 if (!@is_dir(PATH_site.$infoArray['uploadfolder'])) { 02630 $infoArray['errors'][] = 'Error: Upload folder "'.$infoArray['uploadfolder'].'" did not exist!'; 02631 $infoArray['uploadfolder'] = ''; 02632 } 02633 } 02634 02635 // Create directories: 02636 if ($extInfo['EM_CONF']['createDirs']) { 02637 $infoArray['createDirs'] = array_unique(t3lib_div::trimExplode(',',$extInfo['EM_CONF']['createDirs'],1)); 02638 foreach($infoArray['createDirs'] as $crDir) { 02639 if (!@is_dir(PATH_site.$crDir)) { 02640 $infoArray['errors'][]='Error: Upload folder "'.$crDir.'" did not exist!'; 02641 } 02642 } 02643 } 02644 02645 // Return result array: 02646 return $infoArray; 02647 } 02648 02658 function getClassIndexLocallangFiles($absPath,$table_class_prefix,$extKey) { 02659 $filesInside = t3lib_div::removePrefixPathFromList(t3lib_div::getAllFilesAndFoldersInPath(array(),$absPath,'php,inc'),$absPath); 02660 $out = array(); 02661 02662 foreach($filesInside as $fileName) { 02663 if (substr($fileName,0,4)!='ext_') { 02664 $baseName = basename($fileName); 02665 if (substr($baseName,0,9)=='locallang' && substr($baseName,-4)=='.php') { 02666 $out['locallang'][] = $fileName; 02667 } elseif ($baseName!='conf.php') { 02668 if (filesize($absPath.$fileName)<500*1024) { 02669 $fContent = t3lib_div::getUrl($absPath.$fileName); 02670 unset($reg); 02671 if (preg_match('/\n[[:space:]]*class[[:space:]]*([[:alnum:]_]+)([[:alnum:][:space:]_]*)\{/',$fContent,$reg)) { 02672 02673 // Find classes: 02674 $classesInFile=array(); 02675 $lines = explode(chr(10),$fContent); 02676 foreach($lines as $k => $l) { 02677 $line = trim($l); 02678 unset($reg); 02679 if (preg_match('/^class[[:space:]]*([[:alnum:]_]+)([[:alnum:][:space:]_]*)\{/',$line,$reg)) { 02680 $out['classes'][] = $reg[1]; 02681 $out['files'][$fileName]['classes'][] = $reg[1]; 02682 if (substr($reg[1],0,3)!='ux_' && !t3lib_div::isFirstPartOfStr($reg[1],$table_class_prefix) && strcmp(substr($table_class_prefix,0,-1),$reg[1])) { 02683 $out['NSerrors']['classname'][] = $reg[1]; 02684 } else $out['NSok']['classname'][] = $reg[1]; 02685 } 02686 } 02687 // If class file prefixed 'class.'.... 02688 if (substr($baseName,0,6)=='class.') { 02689 $fI = pathinfo($baseName); 02690 $testName=substr($baseName,6,-(1+strlen($fI['extension']))); 02691 if (substr($testName,0,3)!='ux_' && !t3lib_div::isFirstPartOfStr($testName,$table_class_prefix) && strcmp(substr($table_class_prefix,0,-1),$testName)) { 02692 $out['NSerrors']['classfilename'][] = $baseName; 02693 } else { 02694 $out['NSok']['classfilename'][] = $baseName; 02695 if (is_array($out['files'][$fileName]['classes']) && $this->first_in_array($testName,$out['files'][$fileName]['classes'],1)) { 02696 $out['msg'][] = 'Class filename "'.$fileName.'" did contain the class "'.$testName.'" just as it should.'; 02697 } else $out['errors'][] = 'Class filename "'.$fileName.'" did NOT contain the class "'.$testName.'"!'; 02698 } 02699 } 02700 // 02701 $XclassParts = split('if \(defined\([\'"]TYPO3_MODE[\'"]\) && \$TYPO3_CONF_VARS\[TYPO3_MODE\]\[[\'"]XCLASS[\'"]\]',$fContent,2); 02702 if (count($XclassParts)==2) { 02703 unset($reg); 02704 preg_match('/^\[[\'"]([[:alnum:]_\/\.]*)[\'"]\]/',$XclassParts[1],$reg); 02705 if ($reg[1]) { 02706 $cmpF = 'ext/'.$extKey.'/'.$fileName; 02707 if (!strcmp($reg[1],$cmpF)) { 02708 if (preg_match('§_once[[:space:]]*\(\$TYPO3_CONF_VARS\[TYPO3_MODE\]\[[\'"]XCLASS[\'"]\]\[[\'"]'.$cmpF.'[\'"]\]\);§', $XclassParts[1])) { 02709 $out['msg'][] = 'XCLASS OK in '.$fileName; 02710 } else $out['errors'][] = 'Couldn\'t find the include_once statement for XCLASS!'; 02711 } else $out['errors'][] = 'The XCLASS filename-key "'.$reg[1].'" was different from "'.$cmpF.'" which it should have been!'; 02712 } else $out['errors'][] = 'No XCLASS filename-key found in file "'.$fileName.'". Maybe a regex coding error here...'; 02713 } elseif (!$this->first_in_array('ux_',$out['files'][$fileName]['classes'])) $out['errors'][] = 'No XCLASS inclusion code found in file "'.$fileName.'"'; 02714 } 02715 } 02716 } 02717 } 02718 } 02719 return $out; 02720 } 02721 02729 function modConfFileAnalysis($confFilePath) { 02730 $lines = explode(chr(10),t3lib_div::getUrl($confFilePath)); 02731 $confFileInfo = array(); 02732 $confFileInfo['lines'] = $lines; 02733 02734 foreach($lines as $k => $l) { 02735 $line = trim($l); 02736 02737 unset($reg); 02738 if (preg_match('/^define[[:space:]]*\([[:space:]]*["\']TYPO3_MOD_PATH["\'][[:space:]]*,[[:space:]]*["\']([[:alnum:]_\/\.]+)["\'][[:space:]]*\)[[:space:]]*;/',$line,$reg)) { 02739 $confFileInfo['TYPO3_MOD_PATH'] = array($k,$reg); 02740 } 02741 02742 unset($reg); 02743 if (preg_match('/^\$MCONF\[["\']?name["\']?\][[:space:]]*=[[:space:]]*["\']([[:alnum:]_]+)["\'];/',$line,$reg)) { 02744 $confFileInfo['MCONF_name'] = array($k,$reg); 02745 } 02746 } 02747 return $confFileInfo; 02748 } 02749 02757 function serverExtensionMD5Array($extKey,$conf) { 02758 02759 // Creates upload-array - including filelist. 02760 $mUA = $this->makeUploadArray($extKey,$conf); 02761 02762 $md5Array = array(); 02763 if (is_array($mUA['FILES'])) { 02764 02765 // Traverse files. 02766 foreach($mUA['FILES'] as $fN => $d) { 02767 if ($fN!='ext_emconf.php') { 02768 $md5Array[$fN] = substr($d['content_md5'],0,4); 02769 } 02770 } 02771 } else debug($mUA); 02772 return $md5Array; 02773 } 02774 02782 function findMD5ArrayDiff($current,$past) { 02783 if (!is_array($current)) $current = array(); 02784 if (!is_array($past)) $past = array(); 02785 $filesInCommon = array_intersect($current,$past); 02786 $diff1 = array_keys(array_diff($past,$filesInCommon)); 02787 $diff2 = array_keys(array_diff($current,$filesInCommon)); 02788 $affectedFiles = array_unique(array_merge($diff1,$diff2)); 02789 return $affectedFiles; 02790 } 02791 02792 02793 02794 02795 02796 02797 02798 02799 02800 02801 /*********************************** 02802 * 02803 * File system operations 02804 * 02805 **********************************/ 02806 02814 function createDirsInPath($dirs,$extDirPath) { 02815 if (is_array($dirs)) { 02816 foreach($dirs as $dir) { 02817 $allDirs = t3lib_div::trimExplode('/',$dir,1); 02818 $root = ''; 02819 foreach($allDirs as $dirParts) { 02820 $root.=$dirParts.'/'; 02821 if (!is_dir($extDirPath.$root)) { 02822 t3lib_div::mkdir($extDirPath.$root); 02823 if (!@is_dir($extDirPath.$root)) { 02824 return 'Error: The directory "'.$extDirPath.$root.'" could not be created...'; 02825 } 02826 } 02827 } 02828 } 02829 } 02830 } 02831 02839 function removeExtDirectory($removePath,$removeContentOnly=0) { 02840 $errors = array(); 02841 if (@is_dir($removePath) && substr($removePath,-1)=='/' && ( 02842 t3lib_div::isFirstPartOfStr($removePath,PATH_site.$this->typePaths['G']) || 02843 t3lib_div::isFirstPartOfStr($removePath,PATH_site.$this->typePaths['L']) || 02844 (t3lib_div::isFirstPartOfStr($removePath,PATH_site.$this->typePaths['S']) && $this->systemInstall) || 02845 t3lib_div::isFirstPartOfStr($removePath,PATH_site.'fileadmin/_temp_/')) // Playing-around directory... 02846 ) { 02847 02848 // All files in extension directory: 02849 $fileArr = t3lib_div::getAllFilesAndFoldersInPath(array(),$removePath,'',1); 02850 if (is_array($fileArr)) { 02851 02852 // Remove files in dirs: 02853 foreach($fileArr as $removeFile) { 02854 if (!@is_dir($removeFile)) { 02855 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! 02856 @unlink($removeFile); 02857 clearstatcache(); 02858 if (@is_file($removeFile)) { 02859 $errors[] = 'Error: "'.$removeFile.'" could not be deleted!'; 02860 } 02861 } else $errors[] = 'Error: "'.$removeFile.'" was either not a file, or it was equal to the removed directory or simply outside the removed directory "'.$removePath.'"!'; 02862 } 02863 } 02864 02865 // Remove directories: 02866 $remDirs = $this->extractDirsFromFileList(t3lib_div::removePrefixPathFromList($fileArr,$removePath)); 02867 $remDirs = array_reverse($remDirs); // Must delete outer directories first... 02868 foreach($remDirs as $removeRelDir) { 02869 $removeDir = $removePath.$removeRelDir; 02870 if (@is_dir($removeDir)) { 02871 rmdir($removeDir); 02872 clearstatcache(); 02873 if (@is_dir($removeDir)) { 02874 $errors[] = 'Error: "'.$removeDir.'" could not be removed (are there files left?)'; 02875 } 02876 } else $errors[] = 'Error: "'.$removeDir.'" was not a directory!'; 02877 } 02878 02879 // If extension dir should also be removed: 02880 if (!$removeContentOnly) { 02881 rmdir($removePath); 02882 clearstatcache(); 02883 if (@is_dir($removePath)) { 02884 $errors[] = 'Error: Extension directory "'.$removePath.'" could not be removed (are there files or folders left?)'; 02885 } 02886 } 02887 } else $errors[] = 'Error: '.$fileArr; 02888 } else $errors[] = 'Error: Unallowed path to remove: '.$removePath; 02889 02890 // Return errors if any: 02891 return implode(chr(10),$errors); 02892 } 02893 02902 function clearAndMakeExtensionDir($importedData,$type,$dontDelete=0) { 02903 if (!$importedData['extKey']) return 'FATAL ERROR: Extension key was not set for some VERY strange reason. Nothing done...'; 02904 02905 // Setting install path (L, G, S or fileadmin/_temp_/) 02906 $path = ''; 02907 switch((string)$type) { 02908 case 'G': 02909 case 'L': 02910 $path = PATH_site.$this->typePaths[$type]; 02911 $suffix = ''; 02912 02913 // Creates the typo3conf/ext/ directory if it does NOT already exist: 02914 if ((string)$type=='L' && !@is_dir($path)) { 02915 t3lib_div::mkdir($path); 02916 } 02917 break; 02918 default: 02919 if ($this->systemInstall && (string)$type=='S') { 02920 $path = PATH_site.$this->typePaths[$type]; 02921 $suffix = ''; 02922 } else { 02923 $path = PATH_site.'fileadmin/_temp_/'; 02924 $suffix = '_'.date('dmy-His'); 02925 } 02926 break; 02927 } 02928 02929 // If the install path is OK... 02930 if ($path && @is_dir($path)) { 02931 02932 // Set extension directory: 02933 $extDirPath = $path.$importedData['extKey'].$suffix.'/'; 02934 02935 // Install dir was found, remove it then: 02936 if (@is_dir($extDirPath)) { 02937 if($dontDelete) return array($extDirPath); 02938 $res = $this->removeExtDirectory($extDirPath); 02939 if ($res) { 02940 return 'ERROR: Could not remove extension directory "'.$extDirPath.'". Reasons:<br /><br />'.nl2br($res); 02941 } 02942 } 02943 02944 // We go create... 02945 t3lib_div::mkdir($extDirPath); 02946 if (!is_dir($extDirPath)) return 'ERROR: Could not create extension directory "'.$extDirPath.'"'; 02947 return array($extDirPath); 02948 } else return 'ERROR: The extension install path "'.$path.'" was not a directory.'; 02949 } 02950 02956 function removeCacheFiles() { 02957 $cacheFiles = t3lib_extMgm::currentCacheFiles(); 02958 $out = 0; 02959 if (is_array($cacheFiles)) { 02960 reset($cacheFiles); 02961 while(list(,$cfile) = each($cacheFiles)) { 02962 @unlink($cfile); 02963 clearstatcache(); 02964 $out++; 02965 } 02966 } 02967 return $out; 02968 } 02969 02976 function extractDirsFromFileList($files) { 02977 $dirs = array(); 02978 02979 if (is_array($files)) { 02980 // Traverse files / directories array: 02981 foreach($files as $file) { 02982 if (substr($file,-1)=='/') { 02983 $dirs[$file] = $file; 02984 } else { 02985 $pI = pathinfo($file); 02986 if (strcmp($pI['dirname'],'') && strcmp($pI['dirname'],'.')) { 02987 $dirs[$pI['dirname'].'/'] = $pI['dirname'].'/'; 02988 } 02989 } 02990 } 02991 } 02992 return $dirs; 02993 } 02994 03002 function getExtPath($extKey,$type) { 03003 $typeP = $this->typePaths[$type]; 03004 if ($typeP) { 03005 $path = PATH_site.$typeP.$extKey.'/'; 03006 return @is_dir($path) ? $path : ''; 03007 } 03008 } 03009 03010 03011 03012 03013 03014 03015 03016 03017 03018 03019 /******************************* 03020 * 03021 * Writing to "conf.php" and "localconf.php" files 03022 * 03023 ******************************/ 03024 03034 function writeTYPO3_MOD_PATH($confFilePath,$type,$mP) { 03035 $lines = explode(chr(10),t3lib_div::getUrl($confFilePath)); 03036 $confFileInfo = array(); 03037 $confFileInfo['lines'] = $lines; 03038 03039 $flag_M = 0; 03040 $flag_B = 0; 03041 03042 foreach($lines as $k => $l) { 03043 $line = trim($l); 03044 03045 unset($reg); 03046 if (preg_match('/^define[[:space:]]*\([[:space:]]*["\']TYPO3_MOD_PATH["\'][[:space:]]*,[[:space:]]*["\']([[:alnum:]_\/\.]+)["\'][[:space:]]*\)[[:space:]]*;/',$line,$reg)) { 03047 $lines[$k] = str_replace($reg[0], 'define(\'TYPO3_MOD_PATH\', \''.$this->typeRelPaths[$type].$mP.'\');', $lines[$k]); 03048 $flag_M = $k+1; 03049 } 03050 03051 unset($reg); 03052 if (preg_match('/^\$BACK_PATH[[:space:]]*=[[:space:]]*["\']([[:alnum:]_\/\.]+)["\'][[:space:]]*;/',$line,$reg)) { 03053 $lines[$k] = str_replace($reg[0], '$BACK_PATH=\''.$this->typeBackPaths[$type].'\';', $lines[$k]); 03054 $flag_B = $k+1; 03055 } 03056 } 03057 03058 if ($flag_B && $flag_M) { 03059 t3lib_div::writeFile($confFilePath,implode(chr(10),$lines)); 03060 return 'TYPO3_MOD_PATH and $BACK_PATH was updated in "'.substr($confFilePath,strlen(PATH_site)).'"'; 03061 } else return 'Error: Either TYPO3_MOD_PATH or $BACK_PATH was not found in the "'.$confFilePath.'" file. You must manually configure that!'; 03062 } 03063 03071 function writeNewExtensionList($newExtList) { 03072 03073 // Instance of install tool 03074 $instObj = new t3lib_install; 03075 $instObj->allowUpdateLocalConf =1; 03076 $instObj->updateIdentity = 'TYPO3 Extension Manager'; 03077 03078 // Get lines from localconf file 03079 $lines = $instObj->writeToLocalconf_control(); 03080 $instObj->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'EXT\'][\'extList\']', $newExtList); 03081 $instObj->writeToLocalconf_control($lines); 03082 03083 $this->removeCacheFiles(); 03084 } 03085 03094 function writeTsStyleConfig($extKey,$arr) { 03095 03096 // Instance of install tool 03097 $instObj = new t3lib_install; 03098 $instObj->allowUpdateLocalConf =1; 03099 $instObj->updateIdentity = 'TYPO3 Extension Manager'; 03100 03101 // Get lines from localconf file 03102 $lines = $instObj->writeToLocalconf_control(); 03103 $instObj->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'EXT\'][\'extConf\'][\''.$extKey.'\']', serialize($arr)); // This will be saved only if there are no linebreaks in it ! 03104 $instObj->writeToLocalconf_control($lines); 03105 03106 $this->removeCacheFiles(); 03107 } 03108 03116 function updateLocalEM_CONF($extKey,$extInfo) { 03117 $EM_CONF = $extInfo['EM_CONF']; 03118 $EM_CONF['_md5_values_when_last_written'] = serialize($this->serverExtensionMD5Array($extKey,$extInfo)); 03119 $emConfFileContent = $this->construct_ext_emconf_file($extKey,$EM_CONF); 03120 03121 if ($emConfFileContent) { 03122 $absPath = $this->getExtPath($extKey,$extInfo['type']); 03123 $emConfFileName = $absPath.'ext_emconf.php'; 03124 03125 if (@is_file($emConfFileName)) { 03126 t3lib_div::writeFile($emConfFileName,$emConfFileContent); 03127 return '"'.substr($emConfFileName,strlen($absPath)).'" was updated with a cleaned up EM_CONF array.'; 03128 } else die('Error: No file "'.$emConfFileName.'" found.'); 03129 } 03130 } 03131 03132 03133 03134 03135 03136 03137 03138 03139 03140 03141 /******************************************* 03142 * 03143 * Compiling upload information, emconf-file etc. 03144 * 03145 *******************************************/ 03146 03154 function construct_ext_emconf_file($extKey,$EM_CONF) { 03155 03156 $fMsg = array( 03157 'version' => ' // Don\'t modify this! Managed automatically during upload to repository.' 03158 ); 03159 03160 // clean version number: 03161 $vDat = $this->renderVersion($EM_CONF['version']); 03162 $EM_CONF['version']=$vDat['version']; 03163 03164 $lines=array(); 03165 $lines[]='<?php'; 03166 $lines[]=''; 03167 $lines[]='########################################################################'; 03168 $lines[]='# Extension Manager/Repository config file for ext: "'.$extKey.'"'; 03169 $lines[]='# '; 03170 $lines[]='# Auto generated '.date('d-m-Y H:i'); 03171 $lines[]='# '; 03172 $lines[]='# Manual updates:'; 03173 $lines[]='# Only the data in the array - anything else is removed by next write'; 03174 $lines[]='########################################################################'; 03175 $lines[]=''; 03176 $lines[]='$EM_CONF[$_EXTKEY] = Array ('; 03177 03178 foreach($EM_CONF as $k => $v) { 03179 $lines[] = chr(9)."'".$k."' => ".( 03180 t3lib_div::testInt($v)? 03181 intval($v): 03182 "'".t3lib_div::slashJS(trim($v),1)."'" 03183 ).','.$fMsg[$k]; 03184 } 03185 $lines[]=');'; 03186 $lines[]=''; 03187 $lines[]='?>'; 03188 03189 return implode(chr(10),$lines); 03190 } 03191 03199 function makeUploadArray($extKey,$conf) { 03200 $extPath = $this->getExtPath($extKey,$conf['type']); 03201 03202 if ($extPath) { 03203 03204 // Get files for extension: 03205 $fileArr = array(); 03206 $fileArr = t3lib_div::getAllFilesAndFoldersInPath($fileArr,$extPath); 03207 03208 // Calculate the total size of those files: 03209 $totalSize = 0; 03210 foreach($fileArr as $file) { 03211 $totalSize+=filesize($file); 03212 } 03213 03214 // If the total size is less than the upper limit, proceed: 03215 if ($totalSize < $this->maxUploadSize) { 03216 03217 // Initialize output array: 03218 $uploadArray = array(); 03219 $uploadArray['extKey'] = $extKey; 03220 $uploadArray['EM_CONF'] = $conf['EM_CONF']; 03221 $uploadArray['misc']['codelines'] = 0; 03222 $uploadArray['misc']['codebytes'] = 0; 03223 03224 $uploadArray['techInfo'] = $this->makeDetailedExtensionAnalysis($extKey,$conf,1); 03225 03226 // Read all files: 03227 foreach($fileArr as $file) { 03228 $relFileName = substr($file,strlen($extPath)); 03229 $fI = pathinfo($relFileName); 03230 if ($relFileName!='ext_emconf.php') { // This file should be dynamically written... 03231 $uploadArray['FILES'][$relFileName] = array( 03232 'name' => $relFileName, 03233 'size' => filesize($file), 03234 'mtime' => filemtime($file), 03235 'is_executable' => (TYPO3_OS=='WIN' ? 0 : is_executable($file)), 03236 'content' => t3lib_div::getUrl($file) 03237 ); 03238 if (t3lib_div::inList('php,inc',strtolower($fI['extension']))) { 03239 $uploadArray['FILES'][$relFileName]['codelines']=count(explode(chr(10),$uploadArray['FILES'][$relFileName]['content'])); 03240 $uploadArray['misc']['codelines']+=$uploadArray['FILES'][$relFileName]['codelines']; 03241 $uploadArray['misc']['codebytes']+=$uploadArray['FILES'][$relFileName]['size']; 03242 03243 // locallang*.php files: 03244 if (substr($fI['basename'],0,9)=='locallang' && strstr($uploadArray['FILES'][$relFileName]['content'],'$LOCAL_LANG')) { 03245 $uploadArray['FILES'][$relFileName]['LOCAL_LANG']=$this->getSerializedLocalLang($file,$uploadArray['FILES'][$relFileName]['content']); 03246 } 03247 } 03248 $uploadArray['FILES'][$relFileName]['content_md5'] = md5($uploadArray['FILES'][$relFileName]['content']); 03249 } 03250 } 03251 03252 // Return upload-array: 03253 return $uploadArray; 03254 } else return 'Error: Total size of uncompressed upload ('.$totalSize.') exceeds '.t3lib_div::formatSize($this->maxUploadSize); 03255 } 03256 } 03257 03266 function getSerializedLocalLang($file,$content) { 03267 $returnParts = explode('$LOCAL_LANG',$content,2); 03268 03269 include($file); 03270 if (is_array($LOCAL_LANG)) { 03271 $returnParts[1] = serialize($LOCAL_LANG); 03272 return $returnParts; 03273 } 03274 } 03275 03276 03277 03278 03279 03280 03281 03282 03283 03284 03285 /******************************** 03286 * 03287 * Managing dependencies, conflicts, priorities, load order of extension keys 03288 * 03289 *******************************/ 03290 03300 function addExtToList($extKey,$instExtInfo) { 03301 global $TYPO3_LOADED_EXT; 03302 03303 // ext_emconf.php information: 03304 $conf = $instExtInfo[$extKey]['EM_CONF']; 03305 03306 // Check dependencies on other extensions: 03307 if ($conf['dependencies']) { 03308 $dep = t3lib_div::trimExplode(',',$conf['dependencies'],1); 03309 03310 foreach($dep as $depK) { 03311 if (!t3lib_extMgm::isLoaded($depK)) { 03312 if (!isset($instExtInfo[$depK])) { 03313 $msg = 'Extension "'.$depK.'" was not available in the system. Please import it from the TYPO3 Extension Repository.'; 03314 } else { 03315 $msg = 'Extension "'.$depK.'" ('.$instExtInfo[$depK]['EM_CONF']['title'].') was not installed. Please install it first.'; 03316 } 03317 $this->content.= $this->doc->section('Dependency Error',$msg,0,1,2); 03318 return -1; 03319 } 03320 } 03321 } 03322 03323 // Check conflicts with other extensions: 03324 if ($conf['conflicts']) { 03325 $conflict = t3lib_div::trimExplode(',',$conf['conflicts'],1); 03326 03327 foreach($conflict as $conflictK) { 03328 if (t3lib_extMgm::isLoaded($conflictK)) { 03329 $msg = 'The extention "'.$extKey.'" and "'.$conflictK.'" ('.$instExtInfo[$conflictK]['EM_CONF']['title'].') will conflict with each other. Please remove "'.$conflictK.'" if you want to install "'.$extKey.'".'; 03330 $this->content.= $this->doc->section('Conflict Error',$msg,0,1,2); 03331 return -1; 03332 } 03333 } 03334 } 03335 03336 // Get list of installed extensions and add this one. 03337 $listArr = array_keys($TYPO3_LOADED_EXT); 03338 if ($conf['priority']=='top') { 03339 array_unshift($listArr,$extKey); 03340 } else { 03341 $listArr[]=$extKey; 03342 } 03343 03344 // Manage other circumstances: 03345 $listArr = $this->managesPriorities($listArr,$instExtInfo); 03346 $listArr = $this->removeRequiredExtFromListArr($listArr); 03347 03348 // Implode unique list of extensions to load and return: 03349 $list = implode(',',array_unique($listArr)); 03350 return $list; 03351 } 03352 03362 function removeExtFromList($extKey,$instExtInfo) { 03363 global $TYPO3_LOADED_EXT; 03364 03365 // Initialize: 03366 $depList = array(); 03367 $listArr = array_keys($TYPO3_LOADED_EXT); 03368 03369 // 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! 03370 foreach($listArr as $k => $ext) { 03371 if ($instExtInfo[$ext]['EM_CONF']['dependencies']) { 03372 $dep = t3lib_div::trimExplode(',',$instExtInfo[$ext]['EM_CONF']['dependencies'],1); 03373 if (in_array($extKey,$dep)) { 03374 $depList[] = $ext; 03375 } 03376 } 03377 if (!strcmp($ext,$extKey)) unset($listArr[$k]); 03378 } 03379 03380 // Returns either error or the new list 03381 if (count($depList)) { 03382 $msg = 'The extension(s) "'.implode(', ',$depList).'" depends on the extension you are trying to remove. The operation was not completed.'; 03383 $this->content.=$this->doc->section('Dependency Error',$msg,0,1,2); 03384 return -1; 03385 } else { 03386 $listArr = $this->removeRequiredExtFromListArr($listArr); 03387 $list = implode(',',array_unique($listArr)); 03388 return $list; 03389 } 03390 } 03391 03399 function removeRequiredExtFromListArr($listArr) { 03400 foreach($listArr as $k => $ext) { 03401 if (in_array($ext,$this->requiredExt) || !strcmp($ext,'_CACHEFILE')) unset($listArr[$k]); 03402 } 03403 return $listArr; 03404 } 03405 03414 function managesPriorities($listArr,$instExtInfo) { 03415 03416 // Initialize: 03417 $levels = array( 03418 'top' => array(), 03419 'middle' => array(), 03420 'bottom' => array(), 03421 ); 03422 03423 // Traverse list of extensions: 03424 foreach($listArr as $k => $ext) { 03425 $prio = trim($instExtInfo[$ext]['EM_CONF']['priority']); 03426 switch((string)$prio) { 03427 case 'top': 03428 case 'bottom': 03429 $levels[$prio][] = $ext; 03430 break; 03431 default: 03432 $levels['middle'][] = $ext; 03433 break; 03434 } 03435 } 03436 return array_merge( 03437 $levels['top'], 03438 $levels['middle'], 03439 $levels['bottom'] 03440 ); 03441 } 03442 03443 03444 03445 03446 03447 03448 03449 03450 03451 03452 /******************************* 03453 * 03454 * System Update functions (based on extension requirements) 03455 * 03456 ******************************/ 03457 03466 function checkClearCache($extKey,$extInfo) { 03467 if ($extInfo['EM_CONF']['clearCacheOnLoad']) { 03468 if (t3lib_div::_POST('_clear_all_cache')) { // Action: Clearing the cache 03469 $tce = t3lib_div::makeInstance('t3lib_TCEmain'); 03470 $tce->stripslashes_values = 0; 03471 $tce->start(Array(),Array()); 03472 $tce->clear_cacheCmd('all'); 03473 } else { // Show checkbox for clearing cache: 03474 $content.= ' 03475 <br /> 03476 <h3>Clear cache</h3> 03477 <p>This extension requests the cache to be cleared when it is installed/removed.<br /> 03478 Clear all cache: <input type="checkbox" name="_clear_all_cache" checked="checked" value="1" /><br /> 03479 </p> 03480 '; 03481 } 03482 } 03483 return $content; 03484 } 03485 03493 function checkUploadFolder($extKey,$extInfo) { 03494 03495 // Checking for upload folder: 03496 $uploadFolder = PATH_site.$this->ulFolder($extKey); 03497 if ($extInfo['EM_CONF']['uploadfolder'] && !@is_dir($uploadFolder)) { 03498 if (t3lib_div::_POST('_uploadfolder')) { // CREATE dir: 03499 t3lib_div::mkdir($uploadFolder); 03500 $indexContent = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> 03501 <HTML> 03502 <HEAD> 03503 <TITLE></TITLE> 03504 <META http-equiv=Refresh Content="0; Url=../../"> 03505 </HEAD> 03506 </HTML>'; 03507 t3lib_div::writeFile($uploadFolder.'index.html',$indexContent); 03508 } else { // Show checkbox / HTML for creation: 03509 $content.=' 03510 <br /><h3>Create upload folder</h3> 03511 <p>The extension requires the upload folder "'.$this->ulFolder($extKey).'" to exist.<br /> 03512 Create directory "'.$this->ulFolder($extKey).'": <input type="checkbox" name="_uploadfolder" checked="checked" value="1" /><br /> 03513 </p> 03514 '; 03515 } 03516 } 03517 03518 // Additional directories that should be created: 03519 if ($extInfo['EM_CONF']['createDirs']) { 03520 $createDirs = array_unique(t3lib_div::trimExplode(',',$extInfo['EM_CONF']['createDirs'],1)); 03521 03522 foreach($createDirs as $crDir) { 03523 if (!@is_dir(PATH_site.$crDir)) { 03524 if (t3lib_div::_POST('_createDir_'.md5($crDir))) { // CREATE dir: 03525 03526 // Initialize: 03527 $crDirStart = ''; 03528 $dirs_in_path = explode('/',preg_replace('/\/$/','',$crDir)); 03529 03530 // Traverse each part of the dir path and create it one-by-one: 03531 foreach($dirs_in_path as $dirP) { 03532 if (strcmp($dirP,'')) { 03533 $crDirStart.= $dirP.'/'; 03534 if (!@is_dir(PATH_site.$crDirStart)) { 03535 t3lib_div::mkdir(PATH_site.$crDirStart); 03536 $finalDir = PATH_site.$crDirStart; 03537 } 03538 } else { 03539 die('ERROR: The path "'.PATH_site.$crDir.'" could not be created.'); 03540 } 03541 } 03542 if ($finalDir) { 03543 $indexContent = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> 03544 <HTML> 03545 <HEAD> 03546 <TITLE></TITLE> 03547 <META http-equiv=Refresh Content="0; Url=/"> 03548 </HEAD> 03549 </HTML>'; 03550 t3lib_div::writeFile($finalDir.'index.html',$indexContent); 03551 } 03552 } else { // Show checkbox / HTML for creation: 03553 $content.=' 03554 <br /> 03555 <h3>Create folder</h3> 03556 <p>The extension requires the folder "'.$crDir.'" to exist.<br /> 03557 Create directory "'.$crDir.'": <input type="checkbox" name="_createDir_'.md5($crDir).'" checked="checked" value="1" /><br /> 03558 </p> 03559 '; 03560 } 03561 } 03562 } 03563 } 03564 03565 return $content; 03566 } 03567 03578 function checkDBupdates($extKey,$extInfo,$infoOnly=0) { 03579 03580 // Initializing Install Tool object: 03581 $instObj = new t3lib_install; 03582 $instObj->INSTALL = t3lib_div::_GP('TYPO3_INSTALL'); 03583 $dbStatus = array(); 03584 03585 // Updating tables and fields? 03586 if (is_array($extInfo['files']) && in_array('ext_tables.sql',$extInfo['files'])) { 03587 $fileContent = t3lib_div::getUrl($this->getExtPath($extKey,$extInfo['type']).'ext_tables.sql'); 03588 03589 $FDfile = $instObj->getFieldDefinitions_sqlContent($fileContent); 03590 if (count($FDfile)) { 03591 $FDdb = $instObj->getFieldDefinitions_database(TYPO3_db); 03592 $diff = $instObj->getDatabaseExtra($FDfile, $FDdb); 03593 $update_statements = $instObj->getUpdateSuggestions($diff); 03594 03595 $dbStatus['structure']['tables_fields'] = $FDfile; 03596 $dbStatus['structure']['diff'] = $diff; 03597 03598 // Updating database... 03599 if (!$infoOnly && is_array($instObj->INSTALL['database_update'])) { 03600 $instObj->performUpdateQueries($update_statements['add'],$instObj->INSTALL['database_update']); 03601 $instObj->performUpdateQueries($update_statements['change'],$instObj->INSTALL['database_update']); 03602 $instObj->performUpdateQueries($update_statements['create_table'],$instObj->INSTALL['database_update']); 03603 } else { 03604 $content.=$instObj->generateUpdateDatabaseForm_checkboxes($update_statements['add'],'Add fields'); 03605 $content.=$instObj->generateUpdateDatabaseForm_checkboxes($update_statements['change'],'Changing fields',1,0,$update_statements['change_currentValue']); 03606 $content.=$instObj->generateUpdateDatabaseForm_checkboxes($update_statements['create_table'],'Add tables'); 03607 } 03608 } 03609 } 03610 03611 // Importing static tables? 03612 if (is_array($extInfo['files']) && in_array('ext_tables_static+adt.sql',$extInfo['files'])) { 03613 $fileContent = t3lib_div::getUrl($this->getExtPath($extKey,$extInfo['type']).'ext_tables_static+adt.sql'); 03614 03615 $statements = $instObj->getStatementArray($fileContent,1); 03616 list($statements_table, $insertCount) = $instObj->getCreateTables($statements,1); 03617 03618 // Execute import of static table content: 03619 if (!$infoOnly && is_array($instObj->INSTALL['database_import'])) { 03620 03621 // Traverse the tables 03622 foreach($instObj->INSTALL['database_import'] as $table => $md5str) { 03623 if ($md5str == md5($statements_table[$table])) { 03624 $res = $GLOBALS['TYPO3_DB']->admin_query('DROP TABLE IF EXISTS '.$table); 03625 $res = $GLOBALS['TYPO3_DB']->admin_query($statements_table[$table]); 03626 03627 if ($insertCount[$table]) { 03628 $statements_insert = $instObj->getTableInsertStatements($statements, $table); 03629 03630 foreach($statements_insert as $k => $v) { 03631 $res = $GLOBALS['TYPO3_DB']->admin_query($v); 03632 } 03633 } 03634 } 03635 } 03636 } else { 03637 $whichTables = $instObj->getListOfTables(); 03638 if (count($statements_table)) { 03639 $out = ''; 03640 foreach($statements_table as $table => $definition) { 03641 $exist = isset($whichTables[$table]); 03642 03643 $dbStatus['static'][$table]['exists'] = $exist; 03644 $dbStatus['static'][$table]['count'] = $insertCount[$table]; 03645 03646 $out.= '<tr> 03647 <td><input type="checkbox" name="TYPO3_INSTALL[database_import]['.$table.']" checked="checked" value="'.md5($definition).'" /></td> 03648 <td><strong>'.$table.'</strong></td> 03649 <td><img src="clear.gif" width="10" height="1" alt="" /></td> 03650 <td nowrap="nowrap">'.($insertCount[$table]?'Rows: '.$insertCount[$table]:'').'</td> 03651 <td><img src="clear.gif" width="10" height="1" alt="" /></td> 03652 <td nowrap="nowrap">'.($exist?'<img src="'.$GLOBALS['BACK_PATH'].'t3lib/gfx/icon_warning.gif" width="18" height="16" align="top" alt="" />Table exists!':'').'</td> 03653 </tr>'; 03654 } 03655 $content.= ' 03656 <br /> 03657 <h3>Import static data</h3> 03658 <table border="0" cellpadding="0" cellspacing="0">'.$out.'</table>'; 03659 } 03660 } 03661 } 03662 03663 // Return array of information if $infoOnly, otherwise content. 03664 return $infoOnly ? $dbStatus : $content; 03665 } 03666 03677 function tsStyleConfigForm($extKey,$extInfo,$output=0,$script='',$addFields='') { 03678 global $TYPO3_CONF_VARS; 03679 03680 // Initialize: 03681 $absPath = $this->getExtPath($extKey,$extInfo['type']); 03682 $relPath = $this->typeRelPaths[$extInfo['type']].$extKey.'/'; 03683 03684 // Look for template file for form: 03685 if (@is_file($absPath.'ext_conf_template.txt')) { 03686 03687 // Load tsStyleConfig class and parse configuration template: 03688 $tsStyleConfig = t3lib_div::makeInstance('t3lib_tsStyleConfig'); 03689 $tsStyleConfig->doNotSortCategoriesBeforeMakingForm = TRUE; 03690 $theConstants = $tsStyleConfig->ext_initTSstyleConfig( 03691 t3lib_div::getUrl($absPath.'ext_conf_template.txt'), 03692 $relPath, 03693 $absPath, 03694 $GLOBALS['BACK_PATH'] 03695 ); 03696 03697 // Load the list of resources. 03698 $tsStyleConfig->ext_loadResources($absPath.'res/'); 03699 03700 // Load current value: 03701 $arr = unserialize($TYPO3_CONF_VARS['EXT']['extConf'][$extKey]); 03702 $arr = is_array($arr) ? $arr : array(); 03703 03704 // Call processing function for constants config and data before write and form rendering: 03705 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/mod/tools/em/index.php']['tsStyleConfigForm'])) { 03706 $_params = array('fields' => &$theConstants, 'data' => &$arr, 'extKey' => $extKey); 03707 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/mod/tools/em/index.php']['tsStyleConfigForm'] as $_funcRef) { 03708 t3lib_div::callUserFunction($_funcRef,$_params,$this); 03709 } 03710 unset($_params); 03711 } 03712 03713 // If saving operation is done: 03714 if (t3lib_div::_POST('submit')) { 03715 $tsStyleConfig->ext_procesInput(t3lib_div::_POST(),array(),$theConstants,array()); 03716 $arr = $tsStyleConfig->ext_mergeIncomingWithExisting($arr); 03717 $this->writeTsStyleConfig($extKey,$arr); 03718 } 03719 03720 // Setting value array 03721 $tsStyleConfig->ext_setValueArray($theConstants,$arr); 03722 03723 // Getting session data: 03724 $MOD_MENU = array(); 03725 $MOD_MENU['constant_editor_cat'] = $tsStyleConfig->ext_getCategoriesForModMenu(); 03726 $MOD_SETTINGS = t3lib_BEfunc::getModuleData($MOD_MENU, t3lib_div::_GP('SET'), 'xMod_test'); 03727 03728 // Resetting the menu (stop) 03729 if (count($MOD_MENU)>1) { 03730 $menu = 'Category: '.t3lib_BEfunc::getFuncMenu(0,'SET[constant_editor_cat]',$MOD_SETTINGS['constant_editor_cat'],$MOD_MENU['constant_editor_cat'],'','&CMD[showExt]='.$extKey); 03731 $this->content.=$this->doc->section('','<span class="nobr">'.$menu.'</span>'); 03732 $this->content.=$this->doc->spacer(10); 03733 } 03734 03735 // Category and constant editor config: 03736 $form = ' 03737 <table border="0" cellpadding="0" cellspacing="0" width="600"> 03738 <tr> 03739 <td>'.$tsStyleConfig->ext_getForm($MOD_SETTINGS['constant_editor_cat'],$theConstants,$script,$addFields).'</td> 03740 </tr> 03741 </table>'; 03742 if ($output) { 03743 return $form; 03744 } else { 03745 $this->content.=$this->doc->section('','</form>'.$form.'<form>'); 03746 } 03747 } 03748 } 03749 03750 03751 03752 03753 03754 03755 03756 03757 03758 03759 /******************************* 03760 * 03761 * Dumping database (MySQL compliant) 03762 * 03763 ******************************/ 03764 03772 function dumpTableAndFieldStructure($arr) { 03773 $tables = array(); 03774 03775 if (count($arr)) { 03776 03777 // Get file header comment: 03778 $tables[] = $this->dumpHeader(); 03779 03780 // Traverse tables, write each table/field definition: 03781 foreach($arr as $table => $fieldKeyInfo) { 03782 $tables[] = $this->dumpTableHeader($table,$fieldKeyInfo); 03783 } 03784 } 03785 03786 // Return result: 03787 return implode(chr(10).chr(10).chr(10),$tables); 03788 } 03789 03797 function dumpStaticTables($tableList) { 03798 $instObj = new t3lib_install; 03799 $dbFields = $instObj->getFieldDefinitions_database(TYPO3_db); 03800 03801 $out = ''; 03802 $parts = t3lib_div::trimExplode(',',$tableList,1); 03803 03804 // Traverse the table list and dump each: 03805 foreach($parts as $table) { 03806 if (is_array($dbFields[$table]['fields'])) { 03807 $dHeader = $this->dumpHeader(); 03808 $header = $this->dumpTableHeader($table,$dbFields[$table],1); 03809 $insertStatements = $this->dumpTableContent($table,$dbFields[$table]['fields']); 03810 03811 $out.= $dHeader.chr(10).chr(10).chr(10). 03812 $header.chr(10).chr(10).chr(10). 03813 $insertStatements.chr(10).chr(10).chr(10); 03814 } else { 03815 die('Fatal error: Table for dump not found in database...'); 03816 } 03817 } 03818 return $out; 03819 } 03820 03826 function dumpHeader() { 03827 return trim(' 03828 # TYPO3 Extension Manager dump 1.1 03829 # 03830 # Host: '.TYPO3_db_host.' Database: '.TYPO3_db.' 03831 #-------------------------------------------------------- 03832 '); 03833 } 03834 03843 function dumpTableHeader($table,$fieldKeyInfo,$dropTableIfExists=0) { 03844 $lines = array(); 03845 03846 // Create field definitions 03847 if (is_array($fieldKeyInfo['fields'])) { 03848 foreach($fieldKeyInfo['fields'] as $fieldN => $data) { 03849 $lines[]=' '.$fieldN.' '.$data; 03850 } 03851 } 03852 03853 // Create index key definitions 03854 if (is_array($fieldKeyInfo['keys'])) { 03855 foreach($fieldKeyInfo['keys'] as $fieldN => $data) { 03856 $lines[]=' '.$data; 03857 } 03858 } 03859 03860 // Compile final output: 03861 if (count($lines)) { 03862 return trim(' 03863 # 03864 # Table structure for table "'.$table.'" 03865 # 03866 '.($dropTableIfExists ? 'DROP TABLE IF EXISTS '.$table.'; 03867 ' : '').'CREATE TABLE '.$table.' ( 03868 '.implode(','.chr(10),$lines).' 03869 );' 03870 ); 03871 } 03872 } 03873 03882 function dumpTableContent($table,$fieldStructure) { 03883 03884 // Substitution of certain characters (borrowed from phpMySQL): 03885 $search = array('\\', '\'', "\x00", "\x0a", "\x0d", "\x1a"); 03886 $replace = array('\\\\', '\\\'', '\0', '\n', '\r', '\Z'); 03887 03888 $lines = array(); 03889 03890 // Select all rows from the table: 03891 $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $table, ''); 03892 03893 // Traverse the selected rows and dump each row as a line in the file: 03894 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) { 03895 $values = array(); 03896 reset($fieldStructure); 03897 while(list($field) = each($fieldStructure)) { 03898 $values[] = isset($row[$field]) ? "'".str_replace($search, $replace, $row[$field])."'" : 'NULL'; 03899 } 03900 $lines[] = 'INSERT INTO '.$table.' VALUES ('.implode(', ',$values).');'; 03901 } 03902 03903 // Free DB result: 03904 $GLOBALS['TYPO3_DB']->sql_free_result($result); 03905 03906 // Implode lines and return: 03907 return implode(chr(10),$lines); 03908 } 03909 03917 function getTableAndFieldStructure($parts) { 03918 // Instance of install tool 03919 $instObj = new t3lib_install; 03920 $dbFields = $instObj->getFieldDefinitions_database(TYPO3_db); 03921 03922 03923 $outTables = array(); 03924 foreach($parts as $table) { 03925 $tP = explode('.',$table); 03926 if ($tP[0] && isset($dbFields[$tP[0]])) { 03927 if ($tP[1]) { 03928 $kfP = explode('KEY:',$tP[1],2); 03929 if (count($kfP)==2 && !$kfP[0]) { // key: 03930 if (isset($dbFields[$tP[0]]['keys'][$kfP[1]])) $outTables[$tP[0]]['keys'][$kfP[1]] = $dbFields[$tP[0]]['keys'][$kfP[1]]; 03931 } else { 03932 if (isset($dbFields[$tP[0]]['fields'][$tP[1]])) $outTables[$tP[0]]['fields'][$tP[1]] = $dbFields[$tP[0]]['fields'][$tP[1]]; 03933 } 03934 } else { 03935 $outTables[$tP[0]] = $dbFields[$tP[0]]; 03936 } 03937 } 03938 } 03939 03940 return $outTables; 03941 } 03942 03943 03944 03945 03946 03947 03948 03949 03950 03951 03952 /******************************* 03953 * 03954 * TER Communication functions 03955 * 03956 ******************************/ 03957 03965 function fetchServerData($repositoryUrl) { 03966 03967 // Request data from remote: 03968 $ps1 = t3lib_div::milliseconds(); 03969 $externalData = t3lib_div::getUrl($repositoryUrl); 03970 $ps2 = t3lib_div::milliseconds()+1; 03971 #echo $externalData; exit; 03972 #debug(array($externalData));exit; 03973 // Compile statistics array: 03974 $stat = Array( 03975 ($ps2-$ps1), 03976 strlen($externalData), 03977 'Time: '.($ps2-$ps1).'ms', 03978 'Size: '.t3liB_div::formatSize(strlen($externalData)), 03979 'Transfer: '.t3liB_div::formatSize(strlen($externalData) / (($ps2-$ps1)/1000)).'/sec' 03980 ); 03981 03982 // Decode result and return: 03983 return $this->decodeServerData($externalData,$stat); 03984 } 03985 03995 function decodeServerData($externalData,$stat=array()) { 03996 $parts = explode(':',$externalData,4); 03997 $dat = base64_decode($parts[2]); 03998 // compare hashes ignoring any leading whitespace (This makes it work for some broken .t3x files that have leading white space. See bug #0000365. Thanks to Martin T. Kutschker <Martin-no5pam-Kutschker@blackbox.n0spam.net>) 03999 if (preg_replace('/^[\n\r\t ]+/','',$parts[0])==md5($dat)) { 04000 if ($parts[1]=='gzcompress') { 04001 if ($this->gzcompress) { 04002 $dat = gzuncompress($dat); 04003 } else return 'Decoding Error: No decompressor available for compressed content. gzcompress()/gzuncompress() functions are not available!'; 04004 } 04005 $listArr = unserialize($dat); 04006 04007 if (is_array($listArr)) { 04008 return array($listArr,$stat); 04009 } else { 04010 return 'Error: Unserialized information was not an array - strange!'; 04011 } 04012 } else return 'Error: MD5 hashes did not match!'; 04013 } 04014 04022 function decodeExchangeData($str) { 04023 $parts = explode(':',$str,3); 04024 if ($parts[1]=='gzcompress') { 04025 if ($this->gzcompress) { 04026 $parts[2] = gzuncompress($parts[2]); 04027 } else return 'Decoding Error: No decompressor available for compressed content. gzcompress()/gzuncompress() functions are not available!'; 04028 } 04029 if (md5($parts[2]) == $parts[0]) { 04030 $output = unserialize($parts[2]); 04031 if (is_array($output)) { 04032 return $output; 04033 } else return 'Error: Content could not be unserialized to an array. Strange (since MD5 hashes match!)'; 04034 } else return 'Error: MD5 mismatch. Maybe the extension file was downloaded and saved as a text file by the browser and thereby corrupted!? (Always select "All" filetype when saving extensions)'; 04035 } 04036 04044 function makeUploadDataFromArray($uploadArray,$local_gzcompress=-1) { 04045 if (is_array($uploadArray)) { 04046 $serialized = serialize($uploadArray); 04047 $md5 = md5($serialized); 04048 04049 $local_gzcompress = ($local_gzcompress>-1)?$local_gzcompress:$this->gzcompress; 04050 04051 $content = $md5.':'; 04052 if ($local_gzcompress) { 04053 $content.= 'gzcompress:'; 04054 $content.= gzcompress($serialized); 04055 } else { 04056 $content.= ':'; 04057 $content.= $serialized; 04058 } 04059 } 04060 return $content; 04061 } 04062 04069 function repTransferParams() { 04070 return '&tx_extrep[T3instID]='.rawurlencode($this->T3instID()). 04071 '&tx_extrep[TYPO3_ver]='.rawurlencode($GLOBALS['TYPO_VERSION']). 04072 '&tx_extrep[PHP_ver]='.rawurlencode(phpversion()). 04073 '&tx_extrep[returnUrl]='.rawurlencode($this->makeReturnUrl()). 04074 '&tx_extrep[gzcompress]='.$this->gzcompress. 04075 '&tx_extrep[user][fe_u]='.$this->fe_user['username']. 04076 '&tx_extrep[user][fe_p]='.$this->fe_user['password']; 04077 } 04078 04085 function makeReturnUrl() { 04086 return t3lib_div::getIndpEnv('TYPO3_REQUEST_URL'); 04087 } 04088 04095 function T3instID() { 04096 return $GLOBALS['TYPO3_CONF_VARS']['SYS']['T3instID']; 04097 } 04098 04106 function processRepositoryReturnData($TER_CMD) { 04107 switch((string)$TER_CMD['cmd']) { 04108 case 'EM_CONF': 04109 list($list)=$this->getInstalledExtensions(); 04110 $extKey = $TER_CMD['extKey']; 04111 04112 $data = $this->decodeServerData($TER_CMD['returnValue']); 04113 $EM_CONF = $data[0]; 04114 $EM_CONF['_md5_values_when_last_written'] = serialize($this->serverExtensionMD5Array($extKey,$list[$extKey])); 04115 $emConfFileContent = $this->construct_ext_emconf_file($extKey,$EM_CONF); 04116 if (is_array($list[$extKey]) && $emConfFileContent) { 04117 $absPath = $this->getExtPath($extKey,$list[$extKey]['type']); 04118 $emConfFileName = $absPath.'ext_emconf.php'; 04119 if (@is_file($emConfFileName)) { 04120 t3lib_div::writeFile($emConfFileName,$emConfFileContent); 04121 return '"'.substr($emConfFileName,strlen($absPath)).'" was updated with a cleaned up EM_CONF array.'; 04122 } else die('Error: No file "'.$emConfFileName.'" found.'); 04123 } else die('Error: No EM_CONF content prepared...'); 04124 break; 04125 } 04126 } 04127 04128 04129 04130 04131 04132 04133 04134 04135 04136 04137 /************************************ 04138 * 04139 * Various helper functions 04140 * 04141 ************************************/ 04142 04150 function listOrderTitle($listOrder,$key) { 04151 switch($listOrder) { 04152 case 'cat': 04153 return isset($this->categories[$key])?$this->categories[$key]:'<em>['.$key.']</em>'; 04154 break; 04155 case 'author_company': 04156 return $key; 04157 break; 04158 case 'dep': 04159 return $key; 04160 break; 04161 case 'state': 04162 return $this->states[$key]; 04163 break; 04164 case 'private': 04165 return $key?'Private (Password required to download from repository)':'Public (Everyone can download this from Extention repository)'; 04166 break; 04167 case 'type': 04168 return $this->typeDescr[$key]; 04169 break; 04170 } 04171 } 04172 04181 function makeVersion($v,$mode) { 04182 $vDat = $this->renderVersion($v); 04183 return $vDat['version_'.$mode]; 04184 } 04185 04193 function renderVersion($v,$raise='') { 04194 $parts = t3lib_div::intExplode('.',$v.'..'); 04195 $parts[0] = t3lib_div::intInRange($parts[0],0,999); 04196 $parts[1] = t3lib_div::intInRange($parts[1],0,999); 04197 $parts[2] = t3lib_div::intInRange($parts[2],0,999); 04198 04199 switch((string)$raise) { 04200 case 'main': 04201 $parts[0]++; 04202 $parts[1]=0; 04203 $parts[2]=0; 04204 break; 04205 case 'sub': 04206 $parts[1]++; 04207 $parts[2]=0; 04208 break; 04209 case 'dev': 04210 $parts[2]++; 04211 break; 04212 } 04213 04214 $res = array(); 04215 $res['version'] = $parts[0].'.'.$parts[1].'.'.$parts[2]; 04216 $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)); 04217 $res['version_main'] = $parts[0]; 04218 $res['version_sub'] = $parts[1]; 04219 $res['version_dev'] = $parts[2]; 04220 04221 return $res; 04222 } 04223 04230 function ulFolder($extKey) { 04231 return 'uploads/tx_'.str_replace('_','',$extKey).'/'; 04232 } 04233 04239 function importAtAll() { 04240 return ($GLOBALS['TYPO3_CONF_VARS']['EXT']['allowGlobalInstall'] || $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowLocalInstall']); 04241 } 04242 04250 function importAsType($type,$lockType='') { 04251 switch($type) { 04252 case 'G': 04253 return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowGlobalInstall'] && (!$lockType || !strcmp($lockType,$type)); 04254 break; 04255 case 'L': 04256 return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowLocalInstall'] && (!$lockType || !strcmp($lockType,$type)); 04257 break; 04258 case 'S': 04259 return $this->systemInstall; 04260 break; 04261 } 04262 } 04263 04270 function deleteAsType($type) { 04271 switch($type) { 04272 case 'G': 04273 return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowGlobalInstall']; 04274 break; 04275 case 'L': 04276 return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowLocalInstall']; 04277 break; 04278 } 04279 } 04280 04288 function getDocManual($extension_key,$loc='') { 04289 $res = FALSE; 04290 if ($GLOBALS['TYPO3_CONF_VARS']['EXT']['em_alwaysGetOOManual']) $res = TRUE; 04291 if ($loc && $this->typePaths[$loc] && @is_file(PATH_site.$this->typePaths[$loc].$extension_key.'/doc/manual.sxw')) $res = TRUE; 04292 04293 return $res; 04294 } 04295 04304 function versionDifference($v1,$v2,$div=1) { 04305 return floor($this->makeVersion($v1,'int')/$div) > floor($this->makeVersion($v2,'int')/$div); 04306 } 04307 04316 function first_in_array($str,$array,$caseInsensitive=FALSE) { 04317 if ($caseInsensitive) $str = strtolower($str); 04318 if (is_array($array)) { 04319 foreach($array as $cl) { 04320 if ($caseInsensitive) $cl = strtolower($cl); 04321 if (t3lib_div::isFirstPartOfStr($cl,$str)) return 1; 04322 } 04323 } 04324 } 04325 04333 function includeEMCONF($path,$_EXTKEY) { 04334 include($path); 04335 04336 return $EM_CONF[$_EXTKEY]; 04337 } 04338 04346 function searchExtension($extKey,$row) { 04347 if ($this->lookUpStr) { 04348 if ( 04349 stristr($extKey,$this->lookUpStr) || 04350 stristr($row['EM_CONF']['title'],$this->lookUpStr) || 04351 stristr($row['EM_CONF']['description'],$this->lookUpStr) || 04352 stristr($row['EM_CONF']['author'],$this->lookUpStr) || 04353 stristr($row['EM_CONF']['author_company'],$this->lookUpStr) 04354 ) return TRUE; 04355 } else return TRUE; 04356 } 04357 } 04358 04359 // Include extension? 04360 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/mod/tools/em/index.php']) { 04361 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/mod/tools/em/index.php']); 04362 } 04363 04364 04365 04366 04367 04368 04369 04370 04371 04372 // Make instance: 04373 $SOBE = t3lib_div::makeInstance('SC_mod_tools_em_index'); 04374 $SOBE->init(); 04375 foreach($SOBE->include_once as $INC_FILE) { 04376 include_once($INC_FILE); 04377 } 04378 $SOBE->checkExtObj(); 04379 $SOBE->main(); 04380 $SOBE->printContent(); 04381 ?>