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