c7dfb9a94ddf40d4163afbd85980db2f382485a6
2 /***************************************************************
5 * (c) 1999-2004 Kasper Skaarhoj (kasper@typo3.com)
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
28 * Module: Extension manager
32 * @author Kasper Skaarhoj <kasper@typo3.com>
35 * [CLASS/FUNCTION INDEX of SCRIPT]
39 * 196: class em_install_class extends t3lib_install
40 * 203: function em_install_class()
43 * 220: class SC_mod_tools_em_index
45 * SECTION: Standard module initialization
46 * 370: function init()
47 * 434: function menuConfig()
48 * 509: function main()
49 * 581: function printContent()
51 * SECTION: Function Menu Applications
52 * 608: function extensionList_loaded()
53 * 643: function extensionList_installed()
54 * 715: function extensionList_import()
55 * 868: function kickstarter()
56 * 885: function alterSettings()
58 * SECTION: Command Applications (triggered by GET var)
59 * 931: function importExtInfo($extRepUid)
60 * 1032: function importExtFromRep($extRepUid,$loc,$uploadFlag=0,$directInput='',$recentTranslations=0,$incManual=0)
61 * 1192: function showExtDetails($extKey)
63 * SECTION: Application Sub-functions (HTML parts)
64 * 1477: function updatesForm($extKey,$extInfo,$notSilent=0,$script='',$addFields='')
65 * 1508: function extDumpTables($extKey,$extInfo)
66 * 1575: function getFileListOfExtension($extKey,$conf)
67 * 1626: function extDelete($extKey,$extInfo)
68 * 1658: function extUpdateEMCONF($extKey,$extInfo)
69 * 1678: function extMakeNewFromFramework($extKey,$extInfo)
70 * 1699: function extBackup($extKey,$extInfo)
71 * 1767: function extBackup_dumpDataTablesLine($tablesArray,$extKey)
72 * 1795: function extInformationArray($extKey,$extInfo,$remote=0)
73 * 1892: function extInformationArray_dbReq($techInfo,$tableHeader=0)
74 * 1905: function extInformationArray_dbInst($dbInst,$current)
75 * 1924: function getRepositoryUploadForm($extKey,$extInfo)
77 * SECTION: Extension list rendering
78 * 2022: function extensionListRowHeader($trAttrib,$cells,$import=0)
79 * 2087: function extensionListRow($extKey,$extInfo,$cells,$bgColorClass='',$inst_list=array(),$import=0,$altLinkUrl='')
81 * SECTION: Output helper functions
82 * 2212: function wrapEmail($str,$email)
83 * 2225: function helpCol($key)
84 * 2239: function labelInfo($str)
85 * 2251: function extensionTitleIconHeader($extKey,$extInfo,$align='top')
86 * 2266: function removeButton()
87 * 2275: function installButton()
88 * 2284: function noImportMsg()
90 * SECTION: Read information about all available extensions
91 * 2309: function getInstalledExtensions()
92 * 2336: function getInstExtList($path,&$list,&$cat,$type)
93 * 2370: function getImportExtList($listArr)
94 * 2422: function setCat(&$cat,$listArrayPart,$extKey)
96 * SECTION: Extension analyzing (detailed information)
97 * 2484: function makeDetailedExtensionAnalysis($extKey,$extInfo,$validity=0)
98 * 2666: function getClassIndexLocallangFiles($absPath,$table_class_prefix,$extKey)
99 * 2737: function modConfFileAnalysis($confFilePath)
100 * 2765: function serverExtensionMD5Array($extKey,$conf)
101 * 2790: function findMD5ArrayDiff($current,$past)
103 * SECTION: File system operations
104 * 2822: function createDirsInPath($dirs,$extDirPath)
105 * 2847: function removeExtDirectory($removePath,$removeContentOnly=0)
106 * 2908: function clearAndMakeExtensionDir($importedData,$type)
107 * 2961: function removeCacheFiles()
108 * 2981: function extractDirsFromFileList($files)
109 * 3007: function getExtPath($extKey,$type)
111 * SECTION: Writing to "conf.php" and "localconf.php" files
112 * 3039: function writeTYPO3_MOD_PATH($confFilePath,$type,$mP)
113 * 3076: function writeNewExtensionList($newExtList)
114 * 3099: function writeTsStyleConfig($extKey,$arr)
115 * 3121: function updateLocalEM_CONF($extKey,$extInfo)
117 * SECTION: Compiling upload information, emconf-file etc.
118 * 3159: function construct_ext_emconf_file($extKey,$EM_CONF)
119 * 3204: function makeUploadArray($extKey,$conf)
120 * 3271: function getSerializedLocalLang($file,$content)
122 * SECTION: Managing dependencies, conflicts, priorities, load order of extension keys
123 * 3305: function addExtToList($extKey,$instExtInfo)
124 * 3367: function removeExtFromList($extKey,$instExtInfo)
125 * 3404: function removeRequiredExtFromListArr($listArr)
126 * 3419: function managesPriorities($listArr,$instExtInfo)
128 * SECTION: System Update functions (based on extension requirements)
129 * 3471: function checkClearCache($extKey,$extInfo)
130 * 3499: function checkUploadFolder($extKey,$extInfo)
131 * 3587: function checkDBupdates($extKey,$extInfo,$infoOnly=0)
132 * 3686: function tsStyleConfigForm($extKey,$extInfo,$output=0,$script='',$addFields='')
134 * SECTION: Dumping database (MySQL compliant)
135 * 3780: function dumpTableAndFieldStructure($arr)
136 * 3805: function dumpStaticTables($tableList)
137 * 3834: function dumpHeader()
138 * 3851: function dumpTableHeader($table,$fieldKeyInfo,$dropTableIfExists=0)
139 * 3890: function dumpTableContent($table,$fieldStructure)
140 * 3925: function getTableAndFieldStructure($parts)
142 * SECTION: TER Communication functions
143 * 3973: function fetchServerData($repositoryUrl)
144 * 4002: function decodeServerData($externalData,$stat=array())
145 * 4028: function decodeExchangeData($str)
146 * 4050: function makeUploadDataFromArray($uploadArray,$local_gzcompress=-1)
147 * 4075: function repTransferParams()
148 * 4089: function makeReturnUrl()
149 * 4099: function T3instID()
150 * 4110: function processRepositoryReturnData($TER_CMD)
152 * SECTION: Various helper functions
153 * 4154: function listOrderTitle($listOrder,$key)
154 * 4185: function makeVersion($v,$mode)
155 * 4197: function renderVersion($v,$raise='')
156 * 4234: function ulFolder($extKey)
157 * 4243: function importAtAll()
158 * 4254: function importAsType($type,$lockType='')
159 * 4274: function deleteAsType($type)
160 * 4292: function getDocManual($extension_key,$loc='')
161 * 4308: function versionDifference($v1,$v2,$div=1)
162 * 4320: function first_in_array($str,$array,$caseInsensitive=FALSE)
163 * 4337: function includeEMCONF($path,$_EXTKEY)
165 * TOTAL FUNCTIONS: 89
166 * (This index is automatically created/updated by the extension "extdeveval")
173 require ('conf.php');
174 require ($BACK_PATH.'init.php');
175 require ($BACK_PATH.'template.php');
176 $BE_USER->modAccess($MCONF,1);
178 // Include classes needed:
179 require_once(PATH_t3lib
.'class.t3lib_tcemain.php');
180 require_once(PATH_t3lib
.'class.t3lib_install.php');
181 require_once(PATH_t3lib
.'class.t3lib_tsstyleconfig.php');
183 // Include kickstarter wrapped class if extension "extrep_wizard" turns out to be loaded!
184 if (t3lib_extMgm
::isLoaded('extrep_wizard')) {
185 require('./class.kickstarter.php');
190 * Extension class of install tool for use in Extension Manager.
192 * @author Kasper Skaarhoj <kasper@typo3.com>
196 class em_install_class
extends t3lib_install
{
199 * Make sure the normal constructor is NOT called:
203 function em_install_class() {
214 * Module: Extension manager
216 * @author Kasper Skaarhoj <kasper@typo3.com>
220 class SC_mod_tools_em_index
{
223 var $versionDiffFactor = 1000; // This means that version difference testing for import is detected for sub-versions only, not dev-versions. Default: 1000
224 var $systemInstall = 0; // If "1" then installs in the sysext directory is allowed. Default: 0
225 var $repositoryUrl = ''; // Default is "http://ter.typo3.com/?id=t3_extrep" configured in config_default.php
226 var $requiredExt = ''; // List of required extension (from TYPO3_CONF_VARS)
227 var $maxUploadSize = 4024000; // Max size of extension upload to repository
228 var $kbMax = 100; // Max size in kilobytes for files to be edited.
231 * Internal variable loaded with extension categories (for display/listing). Should reflect $categories above
234 var $defaultCategories = Array(
241 'services' => array(),
242 'templates' => array(),
243 'example' => array(),
249 * Extension Categories (static var)
250 * Content must be redundant with the same internal variable as in class.tx_extrep.php!
252 var $categories = Array(
254 'module' => 'Backend Modules',
256 'plugin' => 'Frontend Plugins',
257 'misc' => 'Miscellaneous',
258 'services' => 'Services',
259 'templates' => 'Templates',
260 'example' => 'Examples',
261 'doc' => 'Documentation'
266 * Content must be redundant with the same internal variable as in class.tx_extrep.php!
268 var $states = Array (
271 'stable' => 'Stable',
272 'experimental' => 'Experimental',
274 'obsolete' => 'Obsolete',
278 * "TYPE" information; labels, paths, description etc.
280 var $typeLabels = Array (
285 var $typeDescr = Array (
286 'S' => 'System extension (typo3/sysext/) - Always distributed with source code (Static).',
287 'G' => 'Global extensions (typo3/ext/) - Available for shared source on server (Dynamic).',
288 'L' => 'Local extensions (typo3conf/ext/) - Local for this TYPO3 installation only (Dynamic).',
290 var $typePaths = Array(); // Also static, set in init()
291 var $typeBackPaths = Array(); // Also static, set in init()
293 var $typeRelPaths = Array (
296 'L' => '../typo3conf/ext/',
300 * Remote access types (labels)
302 var $remoteAccess = Array (
305 'selected' => 'Selected',
306 'member' => 'Member',
309 var $detailCols = Array (
318 var $fe_user = array(
324 var $privacyNotice = 'When ever you interact with the online repository, server information is sent and stored in the repository for statistics. No personal information is sent, only identification of this TYPO3 install. If you want know exactly what is sent, look in typo3/tools/em/index.php, function repTransferParams()';
325 var $editTextExtensions = 'html,htm,txt,css,tmpl,inc,php,sql,conf,cnf,pl,pm,sh';
326 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,plugin_mgm,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';
332 // Default variables for backend modules
333 var $MCONF = array(); // Module configuration
334 var $MOD_MENU = array(); // Module menu items
335 var $MOD_SETTINGS = array(); // Module session settings
336 var $doc; // Document Template Object
337 var $content; // Accumulated content
339 var $inst_keys = array(); // Storage of installed extensions
340 var $gzcompress = 0; // Is set true, if system support compression.
343 var $CMD = array(); // CMD array
344 var $listRemote; // If set, connects to remote repository
359 /*********************************
361 * Standard module initialization
363 *********************************/
366 * Standard init function of a module.
371 global $BE_USER,$LANG,$BACK_PATH,$TYPO3_CONF_VARS;
373 // Setting paths of install scopes:
374 $this->typePaths
= Array (
375 'S' => TYPO3_mainDir
.'sysext/',
376 'G' => TYPO3_mainDir
.'ext/',
377 'L' => 'typo3conf/ext/'
379 $this->typeBackPaths
= Array (
382 'L' => '../../../../'.TYPO3_mainDir
385 // Setting module configuration:
386 $this->MCONF
= $GLOBALS['MCONF'];
389 $this->CMD
= t3lib_div
::_GP('CMD');
390 $this->listRemote
= t3lib_div
::_GP('ter_connect');
396 // Setting internal static:
397 $this->gzcompress
= function_exists('gzcompress');
398 if ($TYPO3_CONF_VARS['EXT']['em_devVerUpdate']) $this->versionDiffFactor
= 1;
399 if ($TYPO3_CONF_VARS['EXT']['em_systemInstall']) $this->systemInstall
= 1;
400 $this->repositoryUrl
= $TYPO3_CONF_VARS['EXT']['em_TERurls'][0];
401 $this->requiredExt
= t3lib_div
::trimExplode(',',$TYPO3_CONF_VARS['EXT']['requiredExt'],1);
403 // Initialize Document Template object:
404 $this->doc
= t3lib_div
::makeInstance('noDoc');
405 $this->doc
->backPath
= $BACK_PATH;
406 $this->doc
->docType
= 'xhtml_trans';
409 $this->doc
->JScode
= $this->doc
->wrapScriptTags('
411 function jumpToUrl(URL) { //
412 document.location = URL;
415 $this->doc
->form
= '<form action="" method="post" name="pageform">';
418 $this->descrTable
= '_MOD_'.$this->MCONF
['name'];
419 if ($BE_USER->uc
['edit_showFieldHelp']) {
420 $LANG->loadSingleTableDescription($this->descrTable
);
423 // Setting username/password etc. for upload-user:
424 $this->fe_user
['username'] = $this->MOD_SETTINGS
['fe_u'];
425 $this->fe_user
['password'] = $this->MOD_SETTINGS
['fe_p'];
426 $this->fe_user
['uploadPass'] = $this->MOD_SETTINGS
['fe_up'];
430 * Configuration of which mod-menu items can be used
434 function menuConfig() {
438 $this->MOD_MENU
= array(
440 0 => 'Loaded extensions',
441 1 => 'Available extensions to install',
442 2 => 'Import extensions from online repository',
443 4 => 'Make new extension',
446 'listOrder' => array(
448 'author_company' => 'Author',
450 'private' => 'Private',
452 'dep' => 'Dependencies',
454 'display_details' => array(
459 3 => 'Technical (takes time!)',
460 4 => 'Validating (takes time!)',
461 5 => 'Changed? (takes time!)',
464 'own_member_only' => '',
465 'singleDetails' => array(
466 'info' => 'Information',
467 'edit' => 'Edit files',
468 'backup' => 'Backup/Delete',
470 'upload' => 'Upload',
471 'updateModule' => 'UPDATE!',
478 // page/be_user TSconfig settings and blinding of menu-items
479 if (!$BE_USER->getTSConfigVal('mod.'.$this->MCONF
['name'].'.allowTVlisting')) {
480 unset($this->MOD_MENU
['display_details'][3]);
481 unset($this->MOD_MENU
['display_details'][4]);
482 unset($this->MOD_MENU
['display_details'][5]);
485 // Remove kickstarter if extension is not loaded:
486 if (!t3lib_extMgm
::isLoaded('extrep_wizard')) {
487 unset($this->MOD_MENU
['function'][4]);
491 $this->MOD_SETTINGS
= t3lib_BEfunc
::getModuleData($this->MOD_MENU
, t3lib_div
::_GP('SET'), $this->MCONF
['name']);
493 if ($this->MOD_SETTINGS
['function']==2) {
494 // If listing from online repository, certain items are removed though:
495 unset($this->MOD_MENU
['listOrder']['type']);
496 unset($this->MOD_MENU
['listOrder']['private']);
497 unset($this->MOD_MENU
['display_details'][3]);
498 unset($this->MOD_MENU
['display_details'][4]);
499 unset($this->MOD_MENU
['display_details'][5]);
500 $this->MOD_SETTINGS
= t3lib_BEfunc
::getModuleData($this->MOD_MENU
, t3lib_div
::_GP('SET'), $this->MCONF
['name']);
505 * Main function for Extension Manager module.
510 global $BE_USER,$LANG;
513 $this->content
.=$this->doc
->startPage('Extension Manager');
514 $this->content
.=$this->doc
->header('Extension Manager');
515 $this->content
.=$this->doc
->spacer(5);
518 // Commands given which is executed regardless of main menu setting:
519 if ($this->CMD
['showExt']) { // Show details for a single extension
520 $this->showExtDetails($this->CMD
['showExt']);
521 } elseif ($this->CMD
['importExt'] ||
$this->CMD
['uploadExt']) { // Imports an extension from online rep.
522 $err = $this->importExtFromRep($this->CMD
['importExt'],$this->CMD
['loc'],$this->CMD
['uploadExt'],'',$this->CMD
['transl'],$this->CMD
['inc_manual']);
524 $this->content
.=$this->doc
->section('',$GLOBALS['TBE_TEMPLATE']->rfw($err));
526 } elseif ($this->CMD
['importExtInfo']) { // Gets detailed information of an extension from online rep.
527 $this->importExtInfo($this->CMD
['importExtInfo']);
528 } else { // No command - we show what the menu setting tells us:
530 $menu = $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.menu').' '.
531 t3lib_BEfunc
::getFuncMenu(0,'SET[function]',$this->MOD_SETTINGS
['function'],$this->MOD_MENU
['function']);
533 if (t3lib_div
::inList('0,1,2',$this->MOD_SETTINGS
['function'])) {
534 $menu.=' Order by: '.t3lib_BEfunc
::getFuncMenu(0,'SET[listOrder]',$this->MOD_SETTINGS
['listOrder'],$this->MOD_MENU
['listOrder']).
535 ' Show: '.t3lib_BEfunc
::getFuncMenu(0,'SET[display_details]',$this->MOD_SETTINGS
['display_details'],$this->MOD_MENU
['display_details']).
536 '<br />Display shy extensions: '.t3lib_BEfunc
::getFuncCheck(0,'SET[display_shy]',$this->MOD_SETTINGS
['display_shy']);
539 if ($this->MOD_SETTINGS
['function']==2) {
540 $menu.=' Get own/member/selected extensions only: '.
541 t3lib_BEfunc
::getFuncCheck(0,'SET[own_member_only]',$this->MOD_SETTINGS
['own_member_only']);
544 $this->content
.=$this->doc
->section('','<span class="nobr">'.$menu.'</span>');
545 $this->content
.=$this->doc
->spacer(10);
547 switch($this->MOD_SETTINGS
['function']) {
549 // Lists loaded (installed) extensions
550 $this->extensionList_loaded();
553 // Lists the installed (available) extensions
554 $this->extensionList_installed();
557 // Lists the extensions available from online rep.
558 $this->extensionList_import();
561 // Lists the extensions available from online rep.
562 $this->alterSettings();
565 $this->kickstarter();
571 if ($BE_USER->mayMakeShortcut()) {
572 $this->content
.=$this->doc
->spacer(20).$this->doc
->section('',$this->doc
->makeShortcutIcon('CMD','function',$this->MCONF
['name']));
577 * Print module content. Called as last thing in the global scope.
581 function printContent() {
584 $this->content
.= $this->doc
->endPage();
597 /*********************************
599 * Function Menu Applications
601 *********************************/
604 * Listing of loaded (installed) extensions
608 function extensionList_loaded() {
609 global $TYPO3_LOADED_EXT;
611 list($list) = $this->getInstalledExtensions();
616 $lines[] = $this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="1" height="1" alt="" /></td>'));
618 foreach($TYPO3_LOADED_EXT as $extKey => $eConf) {
619 if (strcmp($extKey, '_CACHEFILE')) {
620 if ($this->MOD_SETTINGS
['display_shy'] ||
!$list[$extKey]['EM_CONF']['shy']) {
621 if (in_array($extKey, $this->requiredExt
)) {
622 $loadUnloadLink = '<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('Rq').'</strong>';
624 $loadUnloadLink = '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1').'">'.$this->removeButton().'</a>';
627 $lines[] = $this->extensionListRow($extKey,$list[$extKey],array('<td class="bgColor">'.$loadUnloadLink.'</td>'));
632 $content.= '"Loaded extensions" are currently running on the system. This list shows you which extensions are loaded and in which order.<br />"Shy" extensions are also loaded but "hidden" in this list because they are system related and generally you should just leave them alone unless you know what you are doing.<br /><br />';
633 $content.= '<table border="0" cellpadding="2" cellspacing="1">'.implode('',$lines).'</table>';
635 $this->content
.=$this->doc
->section('Loaded Extensions',$content,0,1);
639 * Listing of available (installed) extensions
643 function extensionList_installed() {
644 global $TYPO3_LOADED_EXT;
646 list($list,$cat)=$this->getInstalledExtensions();
648 // Available extensions
649 if (is_array($cat[$this->MOD_SETTINGS
['listOrder']])) {
652 $lines[]=$this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="18" height="1" alt="" /></td>'));
655 foreach($cat[$this->MOD_SETTINGS
['listOrder']] as $catName => $extEkeys) {
657 $allKeys[]='TYPE: '.$catName;
659 $lines[]='<tr><td colspan="'.(3+
$this->detailCols
[$this->MOD_SETTINGS
['display_details']]).'"><br /></td></tr>';
660 $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>';
664 while(list($extKey)=each($extEkeys)) {
666 if ($this->MOD_SETTINGS
['display_shy'] ||
!$list[$extKey]['EM_CONF']['shy']) {
667 $loadUnloadLink = t3lib_extMgm
::isLoaded($extKey)?
668 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->removeButton().'</a>':
669 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[load]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->installButton().'</a>';
670 if (in_array($extKey,$this->requiredExt
)) $loadUnloadLink='<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('Rq').'</strong>';
672 if ($list[$extKey]['EM_CONF']['private']) {
673 $theBgColor = '#F6CA96';
675 $theBgColor = t3lib_extMgm
::isLoaded($extKey)?
$this->doc
->bgColor4
:t3lib_div
::modifyHTMLcolor($this->doc
->bgColor4
,20,20,20);
677 $lines[]=$this->extensionListRow($extKey,$list[$extKey],array('<td class="bgColor">'.$loadUnloadLink.'</td>'),
690 '.trim(implode(chr(10),$allKeys)).'
699 #debug($this->MOD_SETTINGS['listOrder']);
700 $content.= 'Available extensions are extensions which are present in the extension folders. You can install any of the available extensions in this list. When you install an extension it will be loaded by TYPO3 from that moment.<br />
701 In this list the extensions with dark background are installed (loaded) - the others just available (not loaded), ready to be installed on your request.<br />
702 So if you want to use an extension in TYPO3, you should simply click the "plus" button '.$this->installButton().' . <br />
703 Installed extensions can also be removed again - just click the remove button '.$this->removeButton().' .<br /><br />';
704 $content.= '<table border="0" cellpadding="2" cellspacing="1">'.implode('',$lines).'</table>';
706 $this->content
.=$this->doc
->section('Available Extensions - Order by: '.$this->MOD_MENU
['listOrder'][$this->MOD_SETTINGS
['listOrder']],$content,0,1);
711 * Listing remote extensions from online repository
715 function extensionList_import() {
716 global $TYPO3_LOADED_EXT;
718 // Listing from online repository:
719 if ($this->listRemote
) {
720 list($inst_list,$inst_cat) = $this->getInstalledExtensions();
721 $this->inst_keys
= array_flip(array_keys($inst_list));
723 $this->detailCols
[1]+
=6;
725 // Getting data from repository:
726 $repositoryUrl=$this->repositoryUrl
.
727 $this->repTransferParams().
728 '&tx_extrep[cmd]=currentListing'.
729 ($this->MOD_SETTINGS
['own_member_only']?
'&tx_extrep[listmode]=1':'');
730 $fetchData = $this->fetchServerData($repositoryUrl);
732 if (is_array($fetchData)) {
733 $listArr = $fetchData[0];
734 list($list,$cat) = $this->getImportExtList($listArr);
736 // Available extensions
737 if (is_array($cat[$this->MOD_SETTINGS
['listOrder']])) {
740 $lines[]=$this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="18" height="1" alt="" /></td>'),1);
742 foreach($cat[$this->MOD_SETTINGS
['listOrder']] as $catName => $extEkeys) {
743 $lines[]='<tr><td colspan="'.(3+
$this->detailCols
[$this->MOD_SETTINGS
['display_details']]).'"><br /></td></tr>';
744 $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>';
748 while(list($extKey)=each($extEkeys)) {
749 if ($this->MOD_SETTINGS
['display_shy'] ||
!$list[$extKey]['EM_CONF']['shy']) {
751 if ($inst_list[$extKey]['type']!='S' && (!isset($inst_list[$extKey]) ||
$this->versionDifference($list[$extKey]['EM_CONF']['version'],$inst_list[$extKey]['EM_CONF']['version'],$this->versionDiffFactor
))) {
752 if (isset($inst_list[$extKey])) {
754 $loc= ($inst_list[$extKey]['type']=='G'?
'G':'L');
755 $aUrl = 'index.php?CMD[importExt]='.$list[$extKey]['extRepUid'].'&CMD[loc]='.$loc.($this->getDocManual($extKey,$loc)?
'&CMD[inc_manual]=1':'');
756 $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>';
759 $aUrl = 'index.php?CMD[importExt]='.$list[$extKey]['extRepUid'].'&CMD[loc]=L'.($this->getDocManual($extKey)?
'&CMD[inc_manual]=1':'');
760 $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>';
763 $loadUnloadLink = ' ';
766 if ($list[$extKey]['_MEMBERS_ONLY']) {
767 $theBgColor = '#F6CA96';
768 } elseif (isset($inst_list[$extKey])) {
769 $theBgColor = t3lib_extMgm
::isLoaded($extKey)?
$this->doc
->bgColor4
:t3lib_div
::modifyHTMLcolor($this->doc
->bgColor4
,20,20,20);
771 $theBgColor = t3lib_div
::modifyHTMLcolor($this->doc
->bgColor2
,30,30,30);
773 $lines[]=$this->extensionListRow($extKey,$list[$extKey],array('<td class="bgColor">'.$loadUnloadLink.'</td>'),
774 $theBgColor,$inst_list,1,'index.php?CMD[importExtInfo]='.$list[$extKey]['extRepUid']);
779 $content.= 'Extensions in this list are online for immediate download from the TYPO3 Extension Repository.<br />
780 Extensions with dark background are those already on your server - the others must be imported from the repository to your server before you can use them.<br />
781 So if you want to use an extension from the repository, you should simply click the "import" button.<br /><br />';
783 $content.= '<table border="0" cellpadding="2" cellspacing="1">'.implode('',$lines).'</table>';
785 $content.= '<br />Data fetched: ['.implode('][',$fetchData[1]).']';
786 $content.= '<br /><br /><strong>PRIVACY NOTICE:</strong><br /> '.$this->privacyNotice
;
788 $this->content
.=$this->doc
->section('Extensions in TYPO3 Extension Repository (online) - Order by: '.$this->MOD_MENU
['listOrder'][$this->MOD_SETTINGS
['listOrder']],$content,0,1);
790 if (!$this->MOD_SETTINGS
['own_member_only']) {
791 // Plugins which are NOT uploaded to repository but present on this server.
794 if (count($this->inst_keys
)) {
795 $lines[]=$this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="18" height="1" alt="" /></td>'));
797 reset($this->inst_keys
);
798 while(list($extKey)=each($this->inst_keys
)) {
799 if ($this->MOD_SETTINGS
['display_shy'] ||
!$inst_list[$extKey]['EM_CONF']['shy']) {
800 $loadUnloadLink = t3lib_extMgm
::isLoaded($extKey)?
801 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->removeButton().'</a>':
802 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[load]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->installButton().'</a>';
803 if (in_array($extKey,$this->requiredExt
)) $loadUnloadLink='<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('Rq').'</strong>';
804 $lines[]=$this->extensionListRow($extKey,$inst_list[$extKey],array('<td class="bgColor">'.$loadUnloadLink.'</td>'),
805 t3lib_extMgm
::isLoaded($extKey)?
$this->doc
->bgColor4
:t3lib_div
::modifyHTMLcolor($this->doc
->bgColor4
,20,20,20));
810 $content.= 'This is the list of extensions which are either user-defined (should be prepended user_ then) or which are private (and does not show up in the public list above).<br /><br />';
811 $content.= '<table border="0" cellpadding="2" cellspacing="1">'.implode('',$lines).'</table>';
812 $this->content
.=$this->doc
->spacer(20);
813 $this->content
.=$this->doc
->section('Extensions found only on this server',$content,0,1);
818 $content = 'Click here to connect to "'.$this->repositoryUrl
.'" and retrieve the list of publicly available plugins from the TYPO3 Extension Repository.<br />';
820 if ($this->fe_user
['username']) {
821 $content.= '<br /><img src="'.$GLOBALS['BACK_PATH'].'gfx/icon_note.gif" width="18" height="16" align="top" alt="" />Repository username "'.$this->fe_user
['username'].'" will be sent as authentication.<br />';
823 $content.= '<br /><img src="'.$GLOBALS['BACK_PATH'].'gfx/icon_warning2.gif" width="18" height="16" align="top" alt="" />You have not configured a repository username/password yet. Please <a href="index.php?SET[function]=3">go to "Settings"</a> and do that.<br />';
826 $onCLick = "document.location='index.php?ter_connect=1';return false;";
827 $content.= '<br /><input type="submit" value="Connect to online repository" onclick="'.htmlspecialchars($onCLick).'" />';
829 $this->content
.=$this->doc
->section('Extensions in TYPO3 Extension Repository',$content,0,1);
834 $onClick = 'document.location=\'index.php?CMD[importExtInfo]=\'+document.pageform.uid_private_key.value+\'&CMD[download_password]=\'+document.pageform.download_password.value; return false;';
835 $content= 'Privat lookup key: <input type="text" name="uid_private_key" /> Password, if any: <input type="text" name="download_password" /><input type="submit" value="Lookup" onclick="'.htmlspecialchars($onClick).'" />';
836 $this->content.=$this->doc->spacer(20);
837 $this->content.=$this->doc->section('Private extension lookup:',$content,0,1);
841 if ($this->importAtAll()) {
842 $content= '</form><form action="index.php" enctype="'.$GLOBALS['TYPO3_CONF_VARS']['SYS']['form_enctype'].'" method="post">
843 Upload extension file (.t3x):<br />
844 <input type="file" size="60" name="upload_ext_file" /><br />
845 ... in location:<br />
846 <select name="CMD[loc]">';
847 if ($this->importAsType('L')) $content.='<option value="L">Local (../typo3conf/ext/)</option>';
848 if ($this->importAsType('G')) $content.='<option value="G">Global (typo3/ext/)</option>';
849 if ($this->importAsType('S')) $content.='<option value="S">System (typo3/sysext/)</option>';
850 $content.='</select><br />
851 <input type="checkbox" value="1" name="CMD[uploadOverwrite]" /> Overwrite any existing extension!<br />
852 <input type="submit" name="CMD[uploadExt]" value="Upload extension file" /><br />
854 if (!$this->gzcompress
) {
855 $content.='<br />'.$GLOBALS['TBE_TEMPLATE']->rfw("NOTE: No decompression available! Don't upload a compressed extension - it will not succeed.");
857 } else $content=$this->noImportMsg();
859 $this->content
.=$this->doc
->spacer(20);
860 $this->content
.=$this->doc
->section('Upload extension file directly (.t3x):',$content,0,1);
864 * Making of new extensions with the kickstarter
868 function kickstarter() {
869 $kickstarter = t3lib_div
::makeInstance('em_kickstarter');
870 $kickstarter->getPIdata();
871 $kickstarter->color
= array($this->doc
->bgColor5
,$this->doc
->bgColor4
,$this->doc
->bgColor
);
872 $kickstarter->siteBackPath
= $this->doc
->backPath
.'../';
873 $kickstarter->pObj
= &$this;
874 $kickstarter->EMmode
= 1;
876 $content = $kickstarter->mgm_wizard();
877 $this->content
.='</form>'.$this->doc
->section('Kickstarter wizard',$content,0,1).'<form>';
881 * Allows changing of settings
885 function alterSettings() {
887 <table border="0" cellpadding="2" cellspacing="2">
888 <tr class="bgColor4">
889 <td>Enter repository username:</td>
890 <td><input type="text" name="SET[fe_u]" value="'.htmlspecialchars($this->MOD_SETTINGS
['fe_u']).'" /></td>
892 <tr class="bgColor4">
893 <td>Enter repository password:</td>
894 <td><input type="password" name="SET[fe_p]" value="'.htmlspecialchars($this->MOD_SETTINGS
['fe_p']).'" /></td>
896 <tr class="bgColor4">
897 <td>Enter default upload password:</td>
898 <td><input type="password" name="SET[fe_up]" value="'.htmlspecialchars($this->MOD_SETTINGS
['fe_up']).'" /></td>
902 <strong>Notice:</strong> This is <em>not</em> your password to the TYPO3 backend! This user information is what is needed to log in at typo3.org with your account there!<br />
904 <input type="submit" value="Update" />
907 $this->content
.=$this->doc
->section('Repository settings',$content,0,1);
919 /*********************************
921 * Command Applications (triggered by GET var)
923 *********************************/
926 * Returns detailed info about an extension in the online repository
928 * @param string Extension repository uid + optional "private key": [uid]-[key].
931 function importExtInfo($extRepUid) {
934 $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>';
935 $this->content
.= $this->doc
->section('',$content);
938 // Create connection URL:
939 $uidParts = t3lib_div
::trimExplode('-',$extRepUid);
940 if (count($uidParts)==2) {
941 $extRepUid = $uidParts[0];
942 $addParams = '&tx_extrep[pKey]='.rawurlencode(trim($uidParts[1]))
943 .'&tx_extrep[pPass]='.rawurlencode(trim($this->CMD
['download_password']));
944 $addImportParams = '&CMD[download_password]='.rawurlencode(trim($this->CMD
['download_password']));
945 } else $addParams = '';
947 $repositoryUrl = $this->repositoryUrl
.
948 $this->repTransferParams().
950 '&tx_extrep[cmd]=extensionInfo'.
951 '&tx_extrep[uid]='.$extRepUid;
953 // Fetch remote data:
954 list($fetchData) = $this->fetchServerData($repositoryUrl);
955 if (is_array($fetchData['_other_versions'])) {
957 $opt[] = '<option value=""></option>';
960 foreach($fetchData['_other_versions'] as $dat) {
961 $setSel = ($dat['uid']==$extRepUid?
' selected="selected"':'');
962 if ($setSel) $selectWasSet=1;
963 $opt[]='<option value="'.$dat['uid'].'"'.$setSel.'>'.$dat['version'].'</option>';
965 if (!$selectWasSet && $fetchData['emconf_private']) {
966 $opt[]='<option value="'.$fetchData['uid'].'-'.$fetchData['private_key'].'" selected="selected">'.$fetchData['version'].' (Private)</option>';
969 // "Select version" box:
970 $onClick = 'document.location=\'index.php?CMD[importExtInfo]=\'+document.pageform.repUid.options[document.pageform.repUid.selectedIndex].value; return false;';
971 $select='<select name="repUid">'.implode('',$opt).'</select> <input type="submit" value="Load details" onclick="'.htmlspecialchars($onClick).'" /> or<br /><br />';
972 if ($this->importAtAll()) {
974 document.location=\'index.php?CMD[importExt]=\'
975 +document.pageform.repUid.options[document.pageform.repUid.selectedIndex].value
976 +\'&CMD[loc]=\'+document.pageform.loc.options[document.pageform.loc.selectedIndex].value
977 +\'&CMD[transl]=\'+(document.pageform.transl.checked?1:0)
978 +\'&CMD[inc_manual]=\'+(document.pageform.inc_manual.checked?1:0)
979 +\''.$addImportParams.'\'; return false;';
981 <input type="submit" value="Import/Update" onclick="'.htmlspecialchars($onClick).'"> to:
982 <select name="loc">'.
983 ($this->importAsType('G',$fetchData['emconf_lockType'])?
'<option value="G">Global: '.$this->typePaths
['G'].$fetchData['extension_key'].'/'.(@is_dir
(PATH_site
.$this->typePaths
['G'].$fetchData['extension_key'])?
' (OVERWRITE)':' (empty)').'</option>':'').
984 ($this->importAsType('L',$fetchData['emconf_lockType'])?
'<option value="L">Local: '.$this->typePaths
['L'].$fetchData['extension_key'].'/'.(@is_dir
(PATH_site
.$this->typePaths
['L'].$fetchData['extension_key'])?
' (OVERWRITE)':' (empty)').'</option>':'').
985 ($this->importAsType('S',$fetchData['emconf_lockType'])?
'<option value="S">System: '.$this->typePaths
['S'].$fetchData['extension_key'].'/'.(@is_dir
(PATH_site
.$this->typePaths
['S'].$fetchData['extension_key'])?
' (OVERWRITE)':' (empty)').'</option>':'').
986 #'<option value="fileadmin">'.htmlspecialchars('TEST: fileadmin/_temp_/[extension key name + date]').'</option>'.
988 <br /><input type="checkbox" name="transl" value="1" />Include most recent translations
989 <br /><input type="checkbox" name="inc_manual" value="1"'.($this->getDocManual($fetchData['extension_key'],@is_dir
(PATH_site
.$this->typePaths
['G'].$fetchData['extension_key'])?
'G':'L')?
' checked="checked"':'').' />Include "doc/manual.sxw", if any
991 } else $select.= $this->noImportMsg();
993 $this->content
.= $this->doc
->section('Select command',$content,0,1);
997 $extKey = $fetchData['extension_key'];
998 list($xList) = $this->getImportExtList(array($fetchData));
999 $eInfo = $xList[$extKey];
1000 $eInfo['_TECH_INFO'] = unserialize($fetchData['techinfo']);
1001 $tempFiles = unserialize($fetchData['files']);
1003 if (is_array($tempFiles)) {
1005 while(list($fk)=each($tempFiles)) {
1006 if (!strstr($fk,'/')) $eInfo['files'][]=$fk;
1010 $content='<strong>'.$fetchData['_ICON'].' '.$eInfo['EM_CONF']['title'].'</strong><br /><br />';
1011 $content.=$this->extInformationArray($extKey,$eInfo,1);
1012 $this->content
.=$this->doc
->spacer(10);
1013 $this->content
.=$this->doc
->section('Remote Extension Details:',$content,0,1);
1015 if (is_array($fetchData['_MESSAGES'])) {
1016 $content = implode('<hr />',$fetchData['_MESSAGES']);
1017 $this->content
.=$this->doc
->section('Messages from repository server:',$content,0,1,1);
1022 * Imports an extensions from the online repository
1024 * @param string Extension repository uid + optional "private key": [uid]-[key].
1025 * @param string Install scope: "L" or "G"
1026 * @param boolean If true, extension is uploaded as file
1027 * @param string "Direct input" of the extension stream. Debugging purpuses, it seems.
1028 * @param boolean If true, recent translations are included.
1029 * @param boolean If true, manual is included.
1030 * @return string Return false on success, returns error message if error.
1032 function importExtFromRep($extRepUid,$loc,$uploadFlag=0,$directInput='',$recentTranslations=0,$incManual=0) {
1034 if (is_array($directInput)) {
1035 $fetchData = array($directInput,'');
1036 $loc = !strcmp($loc,'G')?
'G':'L';
1037 } elseif ($uploadFlag) {
1038 if ($GLOBALS['HTTP_POST_FILES']['upload_ext_file']['tmp_name']) {
1040 // Read uploaded file:
1041 $uploadedTempFile = t3lib_div
::upload_to_tempfile($GLOBALS['HTTP_POST_FILES']['upload_ext_file']['tmp_name']);
1042 $fileContent = t3lib_div
::getUrl($uploadedTempFile);
1043 t3lib_div
::unlink_tempfile($uploadedTempFile);
1045 // Decode file data:
1046 $fetchData = array($this->decodeExchangeData($fileContent),'');
1048 if (is_array($fetchData)) {
1049 $extKey = $fetchData[0]['extKey'];
1051 if (!$this->CMD
['uploadOverwrite']) {
1052 $loc = !strcmp($loc,'G')?
'G':'L';
1053 $comingExtPath = PATH_site
.$this->typePaths
[$loc].$extKey.'/';
1054 if (@is_dir
($comingExtPath)) {
1056 return 'Extension was already present in "'.$comingExtPath.'" - and the overwrite flag was not set! So nothing done...';
1057 } // ... else go on, install...
1058 } // ... else go on, install...
1059 } else return 'No extension key in file. Strange...';
1060 } else return 'Wrong file format. No data recognized.';
1061 } else return 'No file uploaded! Probably the file was too large for PHPs internal limit for uploadable files.';
1065 $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>';
1066 $this->content
.= $this->doc
->section('',$content);
1069 // Building request URL:
1070 $uidParts = t3lib_div
::trimExplode('-',$extRepUid);
1071 if (count($uidParts)==2) {
1072 $extRepUid=$uidParts[0];
1073 $addParams='&tx_extrep[pKey]='.rawurlencode(trim($uidParts[1]))
1074 .'&tx_extrep[pPass]='.rawurlencode(trim($this->CMD
['download_password']));
1075 } else $addParams='';
1077 // If most recent translation should be delivered, send this:
1078 if ($recentTranslations) {
1079 $addParams.='&tx_extrep[transl]=1';
1082 // If manual should be included, send this:
1084 $addParams.='&tx_extrep[inc_manual]=1';
1087 $repositoryUrl=$this->repositoryUrl
.
1088 $this->repTransferParams().
1090 '&tx_extrep[cmd]=importExtension'.
1091 '&tx_extrep[uid]='.$extRepUid;
1093 // Fetch extension from TER:
1094 $fetchData = $this->fetchServerData($repositoryUrl);
1097 // At this point the extension data should be present; so we want to write it to disc:
1098 if ($this->importAsType($loc)) {
1099 if (is_array($fetchData)) { // There was some data successfully transferred
1100 if ($fetchData[0]['extKey'] && is_array($fetchData[0]['FILES'])) {
1101 $extKey = $fetchData[0]['extKey'];
1102 $EM_CONF = $fetchData[0]['EM_CONF'];
1103 if (!$EM_CONF['lockType'] ||
!strcmp($EM_CONF['lockType'],$loc)) {
1104 $res = $this->clearAndMakeExtensionDir($fetchData[0],$loc);
1105 if (is_array($res)) {
1106 $extDirPath = trim($res[0]);
1107 if ($extDirPath && @is_dir
($extDirPath) && substr($extDirPath,-1)=='/') {
1109 $emConfFile = $this->construct_ext_emconf_file($extKey,$EM_CONF);
1110 $dirs = $this->extractDirsFromFileList(array_keys($fetchData[0]['FILES']));
1112 $res = $this->createDirsInPath($dirs,$extDirPath);
1114 $writeFiles = $fetchData[0]['FILES'];
1115 $writeFiles['ext_emconf.php']['content'] = $emConfFile;
1116 $writeFiles['ext_emconf.php']['content_md5'] = md5($emConfFile);
1119 foreach($writeFiles as $theFile => $fileData) {
1120 t3lib_div
::writeFile($extDirPath.$theFile,$fileData['content']);
1121 if (!@is_file
($extDirPath.$theFile)) {
1122 $content.='Error: File "'.$extDirPath.$theFile.'" could not be created!!!<br />';
1123 } elseif (md5(t3lib_div
::getUrl($extDirPath.$theFile)) != $fileData['content_md5']) {
1124 $content.='Error: File "'.$extDirPath.$theFile.'" MD5 was different from the original files MD5 - so the file is corrupted!<br />';
1125 } elseif (TYPO3_OS
!='WIN') {
1126 chmod ($extDirPath.$theFile, 0755);
1130 // No content, no errors. Create success output here:
1132 $content='SUCCESS: '.$extDirPath.'<br />';
1134 // Fix TYPO3_MOD_PATH for backend modules in extension:
1135 $modules = t3lib_div
::trimExplode(',',$EM_CONF['module'],1);
1136 if (count($modules)) {
1137 foreach($modules as $mD) {
1138 $confFileName = $extDirPath.$mD.'/conf.php';
1139 if (@is_file
($confFileName)) {
1140 $content.= $this->writeTYPO3_MOD_PATH($confFileName,$loc,$extKey.'/'.$mD.'/').'<br />';
1141 } else $content.='Error: Couldn\'t find "'.$confFileName.'"<br />';
1144 // NOTICE: I used two hours trying to find out why a script, ext_emconf.php, written twice and in between included by PHP did not update correct the second time. Probably something with PHP-A cache and mtime-stamps.
1145 // But this order of the code works.... (using the empty Array with type, EMCONF and files hereunder).
1147 // Writing to ext_emconf.php:
1148 $sEMD5A = $this->serverExtensionMD5Array($extKey,array(
1150 'EM_CONF' => array(),
1153 $EM_CONF['_md5_values_when_last_written'] = serialize($sEMD5A);
1154 $emConfFile = $this->construct_ext_emconf_file($extKey,$EM_CONF);
1155 t3lib_div
::writeFile($extDirPath.'ext_emconf.php',$emConfFile);
1157 $content.='ext_emconf.php: '.$extDirPath.'ext_emconf.php<br />';
1158 $content.='Type: '.$loc.'<br />';
1160 // Remove cache files:
1161 if (t3lib_extMgm
::isLoaded($extKey)) {
1162 if ($this->removeCacheFiles()) {
1163 $content.='Cache-files are removed and will be re-written upon next hit<br />';
1166 list($new_list)=$this->getInstalledExtensions();
1167 $content.=$this->updatesForm($extKey,$new_list[$extKey],1,'index.php?CMD[showExt]='.$extKey.'&SET[singleDetails]=info');
1170 // Show any messages:
1171 if (is_array($fetchData[0]['_MESSAGES'])) {
1172 $content.='<hr /><strong>Messages from repository:</strong><br /><br />'.implode('<br />',$fetchData[0]['_MESSAGES']);
1175 } else $content = $res;
1176 } else $content = 'Error: The extension path "'.$extDirPath.'" was different than expected...';
1177 } else $content = $res;
1178 } else $content = 'Error: The extension can only be installed in the path '.$this->typePaths
[$EM_CONF['lockType']].' (lockType='.$EM_CONF['lockType'].')';
1179 } else $content = 'Error: No extension key!!! Why? - nobody knows... (Or no files in the file-array...)';
1180 } else $content = 'Error: The datatransfer did not succeed...';
1181 } else $content = 'Error: Installation is not allowed in this path ('.$this->typePaths
[$loc].')';
1183 $this->content
.=$this->doc
->section('Extension copied to server',$content,0,1);
1187 * Display extensions details.
1189 * @param string Extension key
1190 * @return void Writes content to $this->content
1192 function showExtDetails($extKey) {
1193 global $TYPO3_LOADED_EXT;
1195 list($list,$cat)=$this->getInstalledExtensions();
1196 $absPath = $this->getExtPath($extKey,$list[$extKey]['type']);
1198 // Check updateModule:
1199 if (@is_file
($absPath.'class.ext_update.php')) {
1200 require_once($absPath.'class.ext_update.php');
1201 $updateObj = new ext_update
;
1202 if (!$updateObj->access()) {
1203 unset($this->MOD_MENU
['singleDetails']['updateModule']);
1206 unset($this->MOD_MENU
['singleDetails']['updateModule']);
1209 // Function menu here:
1211 <table border="0" cellpadding="0" cellspacing="0" width="100%">
1213 <td nowrap="nowrap">Extension: <strong>'.$this->extensionTitleIconHeader($extKey,$list[$extKey],'absmiddle').'</strong> ('.$extKey.')</td>
1214 <td align="right" nowrap="nowrap">'.
1215 t3lib_BEfunc
::getFuncMenu(0,'SET[singleDetails]',$this->MOD_SETTINGS
['singleDetails'],$this->MOD_MENU
['singleDetails'],'','&CMD[showExt]='.$extKey).' '.
1216 '<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>
1219 $this->content
.=$this->doc
->section('',$content);
1221 // Show extension details:
1222 if ($list[$extKey]) {
1224 // Checking if a command for install/uninstall is executed:
1225 if (($this->CMD
['remove'] ||
$this->CMD
['load']) && !in_array($extKey,$this->requiredExt
)) {
1227 // Install / Uninstall extension here:
1228 if (t3lib_extMgm
::isLocalconfWritable()) {
1229 if ($this->CMD
['remove']) {
1230 $newExtList = $this->removeExtFromList($extKey,$list);
1232 $newExtList = $this->addExtToList($extKey,$list);
1235 // Success-installation:
1236 if ($newExtList!=-1) {
1238 if ($this->CMD
['load']) {
1239 $updates = $this->updatesForm($extKey,$list[$extKey],1,'','<input type="hidden" name="_do_install" value="1" /><input type="hidden" name="_clrCmd" value="'.$this->CMD
['clrCmd'].'" />');
1241 $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;
1242 $this->content
.=$this->doc
->section('Installing '.$this->extensionTitleIconHeader($extKey,$list[$extKey]).strtoupper(': Database needs to be updated'),$updates,1,1,1,1);
1244 # $updates.=$this->checkDBupdates($extKey,$list[$extKey]);
1245 # $updates.= $this->checkClearCache($extKey,$list[$extKey]);
1246 # $updates.= $this->checkUploadFolder($extKey,$list[$extKey]);
1249 Before the extension can be installed the database needs to be updated with new tables or fields. Please select which operations to perform:
1250 </form><form action="'.t3lib_div::linkThisScript().'" method="post">'.$updates.'
1251 <br /><input type="submit" name="write" value="Update database and install extension" />
1252 <input type="hidden" name="_do_install" value="1" />
1254 $this->content.=$this->doc->section('Installing '.$this->extensionTitleIconHeader($extKey,$list[$extKey]).strtoupper(': Database needs to be updated'),$updates,1,1,1);
1256 */ } elseif ($this->CMD
['remove']) {
1257 $updates.= $this->checkClearCache($extKey,$list[$extKey]);
1260 </form><form action="'.t3lib_div
::linkThisScript().'" method="post">'.$updates.'
1261 <br /><input type="submit" name="write" value="Remove extension" />
1262 <input type="hidden" name="_do_install" value="1" />
1263 <input type="hidden" name="_clrCmd" value="'.$this->CMD
['clrCmd'].'" />
1265 $this->content
.=$this->doc
->section('Installing '.$this->extensionTitleIconHeader($extKey,$list[$extKey]).strtoupper(': Database needs to be updated'),$updates,1,1,1,1);
1268 if (!$updates || t3lib_div
::_GP('_do_install')) {
1269 $this->writeNewExtensionList($newExtList);
1273 $content = $newExtList;
1274 $this->content.=$this->doc->section('Active status',"
1275 <strong>Extension list is written to localconf.php!</strong><br />
1276 It may be necessary to reload TYPO3 depending on the change.<br />
1278 <em>(".$content.")</em>",0,1);
1280 if ($this->CMD
['clrCmd'] || t3lib_div
::_GP('_clrCmd')) {
1281 $vA = array('CMD'=>'');
1283 $vA = array('CMD'=>Array('showExt'=>$extKey));
1285 header('Location: '.t3lib_div
::linkThisScript($vA));
1289 $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);
1292 } elseif ($this->CMD
['downloadFile'] && !in_array($extKey,$this->requiredExt
)) {
1294 // Link for downloading extension has been clicked - deliver content stream:
1295 $dlFile = $this->CMD
['downloadFile'];
1296 if (t3lib_div
::isFirstPartOfStr($dlFile,PATH_site
) && t3lib_div
::isFirstPartOfStr($dlFile,$absPath) && @is_file
($dlFile)) {
1297 $mimeType = 'application/octet-stream';
1298 Header('Content-Type: '.$mimeType);
1299 Header('Content-Disposition: attachment; filename='.basename($dlFile));
1300 echo t3lib_div
::getUrl($dlFile);
1302 } else die('error....');
1304 } elseif ($this->CMD
['editFile'] && !in_array($extKey,$this->requiredExt
)) {
1306 // Editing extension file:
1307 $editFile = $this->CMD
['editFile'];
1308 if (t3lib_div
::isFirstPartOfStr($editFile,PATH_site
) && t3lib_div
::isFirstPartOfStr($editFile,$absPath)) { // Paranoia...
1310 $fI = t3lib_div
::split_fileref($editFile);
1311 if (@is_file
($editFile) && t3lib_div
::inList($this->editTextExtensions
,$fI['fileext'])) {
1312 if (filesize($editFile)<($this->kbMax
*1024)) {
1315 $submittedContent = t3lib_div
::_POST('edit');
1318 if(isset($submittedContent['file'])) { // Check referer here?
1319 $info.= $GLOBALS['TBE_TEMPLATE']->rfw('<br /><strong>File saved.</strong>').'<br />';
1320 $oldFileContent = t3lib_div
::getUrl($editFile);
1321 $info.= 'MD5: <b>'.md5(str_replace(chr(13),'',$oldFileContent)).'</b> (Previous File)<br />';
1322 if (!$GLOBALS['TYPO3_CONF_VARS']['EXT']['noEdit']) {
1323 t3lib_div
::writeFile($editFile,$submittedContent['file']);
1325 } else die('Saving disabled!!!');
1328 $fileContent = t3lib_div
::getUrl($editFile);
1331 $outCode.= 'File: <b>'.substr($editFile,strlen($absPath)).'</b> ('.t3lib_div
::formatSize(filesize($editFile)).')<br />';
1332 $info.= 'MD5: <b>'.md5(str_replace(chr(13),'',$fileContent)).'</b> (File)<br />';
1333 if($saveFlag) $info.= 'MD5: <b>'.md5(str_replace(chr(13),'',$submittedContent['file'])).'</b> (Saved)<br />';
1334 $outCode.= '<textarea name="edit[file]" rows="'.$numberOfRows.'" wrap="off"'.$this->doc
->formWidthText(48,'width:98%;height:70%','off').'>'.t3lib_div
::formatForTextarea($fileContent).'</textarea>';
1335 $outCode.= '<input type="hidden" name="edit[filename]" value="'.$editFile.'" />';
1336 $outCode.= '<input type="hidden" name="CMD[editFile]" value="'.htmlspecialchars($editFile).'" />';
1337 $outCode.= '<input type="hidden" name="CMD[showExt]" value="'.$extKey.'" />';
1340 if (!$GLOBALS['TYPO3_CONF_VARS']['EXT']['noEdit']) {
1341 $outCode.='<br /><input type="submit" name="save_file" value="Save file" />';
1342 } else $outCode.=$GLOBALS['TBE_TEMPLATE']->rfw('<br />[SAVING IS DISABLED - can be enabled by the TYPO3_CONF_VARS[EXT][noEdit]-flag] ');
1344 $onClick = 'document.location=\'index.php?CMD[showExt]='.$extKey.'\';return false;';
1345 $outCode.='<input type="submit" name="cancel" value="Cancel" onclick="'.htmlspecialchars($onClick).'" />';
1347 $theOutput.=$this->doc
->spacer(15);
1348 $theOutput.=$this->doc
->section('Edit file:','',0,1);
1349 $theOutput.=$this->doc
->sectionEnd().$outCode;
1350 $this->content
.=$theOutput;
1352 $theOutput.=$this->doc
->spacer(15);
1353 $theOutput.=$this->doc
->section('Filesize exceeded '.$this->kbMax
.' Kbytes','Files larger than '.$this->kbMax
.' KBytes are not allowed to be edited.');
1356 } else die('Fatal Edit error: File "'.$editFile.'" was not inside the correct path of the TYPO3 Extension!');
1360 switch((string)$this->MOD_SETTINGS
['singleDetails']) {
1362 // Loaded / Not loaded:
1363 if (!in_array($extKey,$this->requiredExt
)) {
1364 if ($TYPO3_LOADED_EXT[$extKey]) {
1365 $content = '<strong>The extension is installed (loaded and running)!</strong><br />'.
1366 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1').'">Click here to remove the extension: '.$this->removeButton().'</a>';
1368 $content = 'The extension is <strong>not</strong> installed yet.<br />'.
1369 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[load]=1').'">Click here to install the extension: '.$this->installButton().'</a>';
1372 $content = 'This extension is entered in the TYPO3_CONF_VARS[SYS][requiredExt] list and is therefore always loaded.';
1374 $this->content
.=$this->doc
->spacer(10);
1375 $this->content
.=$this->doc
->section('Active status:',$content,0,1);
1377 if (t3lib_extMgm
::isLoaded($extKey)) {
1378 $updates=$this->updatesForm($extKey,$list[$extKey]);
1380 $this->content
.=$this->doc
->spacer(10);
1381 $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);
1386 $content = $this->extInformationArray($extKey,$list[$extKey]);
1387 $this->content
.=$this->doc
->spacer(10);
1388 $this->content
.=$this->doc
->section('Details:',$content,0,1);
1391 if (@is_file
($absPath.'ext_conf_template.txt')) {
1392 $this->content
.=$this->doc
->spacer(10);
1393 $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);
1394 $this->tsStyleConfigForm($extKey,$list[$extKey]);
1398 $TER_CMD = t3lib_div
::_GP('TER_CMD');
1399 if (is_array($TER_CMD)) {
1400 $msg = $this->processRepositoryReturnData($TER_CMD);
1402 $this->content
.=$this->doc
->section('Local update of EM_CONF',$msg,0,1,1);
1403 $this->content
.=$this->doc
->spacer(10);
1405 // Must reload this, because EM_CONF information has been updated!
1406 list($list,$cat)=$this->getInstalledExtensions();
1409 if (substr($extKey,0,5)!='user_') {
1410 $content = $this->getRepositoryUploadForm($extKey,$list[$extKey]);
1413 $content='The extensions has an extension key prefixed "user_" which indicates that it is a user-defined extension with no official unique identification. Therefore it cannot be uploaded.<br />
1414 You are encouraged to register a unique extension key for all your TYPO3 extensions - even if the project is current not official.';
1417 $this->content
.=$this->doc
->section('Upload extension to repository',$content,0,1,$eC);
1423 $content = $this->extBackup($extKey,$list[$extKey]);
1424 $this->content
.=$this->doc
->section('Backup',$content,0,1);
1426 $content = $this->extDelete($extKey,$list[$extKey]);
1427 $this->content
.=$this->doc
->section('Delete',$content,0,1);
1429 $content = $this->extUpdateEMCONF($extKey,$list[$extKey]);
1430 $this->content
.=$this->doc
->section('Update EM_CONF',$content,0,1);
1432 $content = $this->extMakeNewFromFramework($extKey,$list[$extKey]);
1433 if ($content) $this->content
.=$this->doc
->section('Make new extension',$content,0,1);
1436 $this->extDumpTables($extKey,$list[$extKey]);
1440 $content = $this->getFileListOfExtension($extKey,$list[$extKey]);
1441 $this->content
.=$this->doc
->section('Extension files',$content,0,1);
1443 case 'updateModule':
1444 $this->content
.=$this->doc
->section('Update:',$updateObj->main(),0,1);
1460 /***********************************
1462 * Application Sub-functions (HTML parts)
1464 **********************************/
1467 * Creates a form for an extension which contains all options for configuration, updates of database, clearing of cache etc.
1468 * This form is shown when
1470 * @param string Extension key
1471 * @param array Extension information array
1472 * @param boolean If set, the form will ONLY show if fields/tables should be updated (suppressing forms like general configuration and cache clearing).
1473 * @param string Alternative action=""-script
1474 * @param string HTML: Additional form fields
1475 * @return string HTML
1477 function updatesForm($extKey,$extInfo,$notSilent=0,$script='',$addFields='') {
1478 $script = $script ?
$script : t3lib_div
::linkThisScript();
1479 $updates.= $this->checkDBupdates($extKey,$extInfo);
1480 $uCache = $this->checkClearCache($extKey,$extInfo);
1481 if ($notSilent) $updates.= $uCache;
1482 $updates.= $this->checkUploadFolder($extKey,$extInfo);
1484 $absPath = $this->getExtPath($extKey,$extInfo['type']);
1485 if ($notSilent && @is_file
($absPath.'ext_conf_template.txt')) {
1486 $cForm = $this->tsStyleConfigForm($extKey,$extInfo,1,$script,$updates.$addFields.'<br />');
1489 if ($updates ||
$cForm) {
1491 $updates = '</form>'.$cForm.'<form>';
1493 $updates = '</form><form action="'.htmlspecialchars($script).'" method="post">'.$updates.$addFields.'
1494 <br /><input type="submit" name="write" value="Make updates" />
1502 * Creates view for dumping static tables and table/fields structures...
1504 * @param string Extension key
1505 * @param array Extension information array
1508 function extDumpTables($extKey,$extInfo) {
1510 // Get dbInfo which holds the structure known from the tables.sql file
1511 $techInfo = $this->makeDetailedExtensionAnalysis($extKey,$extInfo);
1512 $absPath = $this->getExtPath($extKey,$extInfo['type']);
1515 if (is_array($techInfo['static'])) {
1516 if ($this->CMD
['writeSTATICdump']) { // Writing static dump:
1517 $writeFile = $absPath.'ext_tables_static+adt.sql';
1518 if (@is_file
($writeFile)) {
1519 $dump_static = $this->dumpStaticTables(implode(',',$techInfo['static']));
1520 t3lib_div
::writeFile($writeFile,$dump_static);
1521 $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);
1523 } else { // Showing info about what tables to dump - and giving the link to execute it.
1524 $msg = 'Dumping table content for static tables:<br />';
1525 $msg.= '<br />'.implode('<br />',$techInfo['static']).'<br />';
1527 // ... then feed that to this function which will make new CREATE statements of the same fields but based on the current database content.
1528 $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);
1529 $this->content
.=$this->doc
->spacer(20);
1533 // Table and field definitions:
1534 if (is_array($techInfo['dump_tf'])) {
1535 $dump_tf_array = $this->getTableAndFieldStructure($techInfo['dump_tf']);
1536 $dump_tf = $this->dumpTableAndFieldStructure($dump_tf_array);
1537 if ($this->CMD
['writeTFdump']) {
1538 $writeFile = $absPath.'ext_tables.sql';
1539 if (@is_file
($writeFile)) {
1540 t3lib_div
::writeFile($writeFile,$dump_tf);
1541 $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);
1544 $msg = 'Dumping current database structure for:<br />';
1545 if (is_array($techInfo['tables'])) {
1546 $msg.= '<br /><strong>Tables:</strong><br />'.implode('<br />',$techInfo['tables']).'<br />';
1548 if (is_array($techInfo['fields'])) {
1549 $msg.= '<br /><strong>Solo-fields:</strong><br />'.implode('<br />',$techInfo['fields']).'<br />';
1552 // ... then feed that to this function which will make new CREATE statements of the same fields but based on the current database content.
1553 $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 />
1554 <pre>'.htmlspecialchars($dump_tf).'</pre>',0,1);
1557 $details = ' This dump is based on two factors:<br />
1559 <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>
1560 <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>
1562 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 />';
1563 $this->content
.=$this->doc
->section('',$details);
1569 * Returns file-listing of an extension
1571 * @param string Extension key
1572 * @param array Extension information array
1573 * @return string HTML table.
1575 function getFileListOfExtension($extKey,$conf) {
1576 $extPath = $this->getExtPath($extKey,$conf['type']);
1581 $fileArr = t3lib_div
::getAllFilesAndFoldersInPath($fileArr,$extPath);
1589 <tr class="bgColor5">
1595 foreach($fileArr as $file) {
1596 $fI = t3lib_div
::split_fileref($file);
1598 <tr class="bgColor4">
1599 <td><a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[downloadFile]='.rawurlencode($file)).'" title="Download...">'.substr($file,strlen($extPath)).'</a></td>
1600 <td>'.t3lib_div
::formatSize(filesize($file)).'</td>
1601 <td>'.(!in_array($extKey,$this->requiredExt
)&&t3lib_div
::inList($this->editTextExtensions
,$fI['fileext'])?
'<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[editFile]='.rawurlencode($file)).'">Edit file</a>':'').'</td>
1603 $totalSize+
=filesize($file);
1607 <tr class="bgColor6">
1608 <td><strong>Total:</strong></td>
1609 <td><strong>'.t3lib_div
::formatSize($totalSize).'</strong></td>
1614 Path: '.$extPath.'<br /><br />
1615 <table border="0" cellpadding="1" cellspacing="2">'.implode('',$lines).'</table>';
1620 * Delete extension from the file system
1622 * @param string Extension key
1623 * @param array Extension info array
1624 * @return string Returns message string about the status of the operation
1626 function extDelete($extKey,$extInfo) {
1627 $absPath = $this->getExtPath($extKey,$extInfo['type']);
1628 if (t3lib_extMgm
::isLoaded($extKey)) {
1629 return 'This extension is currently installed (loaded and active) and so cannot be deleted!';
1630 } elseif (!$this->deleteAsType($extInfo['type'])) {
1631 return 'You cannot delete (and install/update) extensions in the '.$this->typeLabels
[$extInfo['type']].' scope.';
1632 } elseif (t3lib_div
::inList('G,L',$extInfo['type'])) {
1633 if ($this->CMD
['doDelete'] && !strcmp($absPath,$this->CMD
['absPath'])) {
1634 $res = $this->removeExtDirectory($absPath);
1636 return 'ERROR: Could not remove extension directory "'.$absPath.'". Had the following errors:<br /><br />'.
1640 return 'Removed extension in path "'.$absPath.'"!';
1643 $onClick = "if (confirm('Are you sure you want to delete this extension from the server?')) {document.location='index.php?CMD[showExt]=".$extKey.'&CMD[doDelete]=1&CMD[absPath]='.rawurlencode($absPath)."';}";
1644 $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>';
1645 $content.= '<br /><br />(Maybe you should make a backup first, see above.)';
1648 } else return 'Extension is not a global or local extension and cannot be removed.';
1652 * Update extension EM_CONF...
1654 * @param string Extension key
1655 * @param array Extension information array
1656 * @return string HTML content.
1658 function extUpdateEMCONF($extKey,$extInfo) {
1659 $absPath = $this->getExtPath($extKey,$extInfo['type']);
1660 if ($this->CMD
['doUpdateEMCONF']) {
1661 return $this->updateLocalEM_CONF($extKey,$extInfo);
1663 $onClick = "if (confirm('Are you sure you want to update EM_CONF?')) {document.location='index.php?CMD[showExt]=".$extKey."&CMD[doUpdateEMCONF]=1';}";
1664 $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>';
1665 $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 />
1666 Updating this file will first of all reset this registration.';
1672 * Reload in Kickstarter Wizard
1674 * @param string Extension key
1675 * @param array Extension information array
1676 * @return string HTML content
1678 function extMakeNewFromFramework($extKey,$extInfo) {
1679 $absPath = $this->getExtPath($extKey,$extInfo['type']);
1680 if (isset($this->MOD_MENU
['function'][4]) && @is_file
($absPath.'doc/wizard_form.dat')) {
1681 $content = "The file '".substr($absPath."doc/wizard_form.dat",strlen(PATH_site
))."' contains the data which this extension was originally made from with the 'Kickstarter' wizard.<br />Pressing this button will allow you to create another extension based on the that framework.<br /><br />";
1683 <form action="index.php?SET[function]=4" method="post">
1684 <input type="submit" value="Start new" />
1685 <input type="hidden" name="tx_extrep[wizArray_ser]" value="'.base64_encode(t3lib_div
::getUrl($absPath.'doc/wizard_form.dat')).'" />
1693 * Download extension as file / make backup
1695 * @param string Extension key
1696 * @param array Extension information array
1697 * @return string HTML content
1699 function extBackup($extKey,$extInfo) {
1700 $uArr = $this->makeUploadArray($extKey,$extInfo);
1701 if (is_array($uArr)) {
1702 $local_gzcompress = $this->gzcompress
&& !$this->CMD
['dontCompress'];
1703 $backUpData = $this->makeUploadDataFromArray($uArr,intval($local_gzcompress));
1704 $filename = 'T3X_'.$extKey.'-'.str_replace('.','_',$extInfo['EM_CONF']['version']).($local_gzcompress?
'-z':'').'-'.date('YmdHi').'.t3x';
1705 if (intval($this->CMD
['doBackup'])==1) {
1707 $mimeType = 'application/octet-stream';
1708 Header('Content-Type: '.$mimeType);
1709 Header('Content-Disposition: attachment; filename='.$filename);
1711 // New headers suggested by Xin:
1712 // For now they are commented out because a) I have seen no official support yet, b) when clicking the back-link in MSIE after download you see ugly binary stuff and c) I couldn't see a BIG difference, in particular not in Moz/Opera.
1713 /* header('Content-Type: application/force-download');
1714 header('Content-Length: '.strlen($backUpData));
1716 header('Content-Disposition: attachment; filename='.$filename);
1717 header('Content-Description: File Transfer');
1718 header('Content-Transfer-Encoding: binary');
1721 // ANYWAYS! The download is NOT always working - in some cases extensions will never get the same MD5 sum as the one shown at the download link - and they should in order to work! We do NOT know why yet.
1725 } elseif ($this->CMD
['dumpTables']) {
1726 $filename='T3X_'.$extKey;
1727 $cTables = count(explode(',',$this->CMD
['dumpTables']));
1729 $filename.='-'.$cTables.'tables';
1731 $filename.='-'.$this->CMD
['dumpTables'];
1733 $filename.='+adt.sql';
1735 $mimeType = 'application/octet-stream';
1736 Header('Content-Type: '.$mimeType);
1737 Header('Content-Disposition: attachment; filename='.$filename);
1738 echo $this->dumpStaticTables($this->CMD
['dumpTables']);
1741 $techInfo = $this->makeDetailedExtensionAnalysis($extKey,$extInfo);
1742 // if ($techInfo['tables']||$techInfo['static']||$techInfo['fields']) {
1745 $lines[]='<tr class="bgColor5"><td colspan="2"><strong>Make selection:</strong></td></tr>';
1746 $lines[]='<tr class="bgColor4"><td><strong>Extension files:</strong></td><td>'.
1747 '<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 />'.
1748 ($this->gzcompress ?
'<br /><a href="'.htmlspecialchars('index.php?CMD[doBackup]=1&CMD[dontCompress]=1&CMD[showExt]='.$extKey).'">(Click here to download extension without compression.)</a>':'').
1751 if (is_array($techInfo['tables'])) { $lines[]='<tr class="bgColor4"><td><strong>Data tables:</strong></td><td>'.$this->extBackup_dumpDataTablesLine($techInfo['tables'],$extKey).'</td></tr>'; }
1752 if (is_array($techInfo['static'])) { $lines[]='<tr class="bgColor4"><td><strong>Static tables:</strong></td><td>'.$this->extBackup_dumpDataTablesLine($techInfo['static'],$extKey).'</td></tr>'; }
1754 $content = '<table border="0" cellpadding="2" cellspacing="2">'.implode('',$lines).'</table>';
1757 } else die('Error...');
1761 * Link to dump of database tables
1763 * @param string Extension key
1764 * @param array Extension information array
1765 * @return string HTML
1767 function extBackup_dumpDataTablesLine($tablesArray,$extKey) {
1769 $tablesNA = array();
1771 foreach($tablesArray as $tN) {
1772 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('count(*)', $tN, '');
1773 if (!$GLOBALS['TYPO3_DB']->sql_error()) {
1774 $row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
1775 $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>';
1777 $tablesNA[$tN]='<tr><td> </td><td>'.$tN.'</td><td> </td><td>Did not exist.</td></tr>';
1780 $label = '<table border="0" cellpadding="0" cellspacing="0">'.implode('',array_merge($tables,$tablesNA)).'</table>';// Candidate for t3lib_div::array_merge() if integer-keys will some day make trouble...
1781 if (count($tables)) {
1782 $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;
1783 } else $label = 'Nothing to dump...<br /><br />'.$label;
1788 * Prints a table with extension information in it.
1790 * @param string Extension key
1791 * @param array Extension information array
1792 * @param boolean If set, the information array shows information for a remote extension in TER, not a local one.
1793 * @return string HTML content.
1795 function extInformationArray($extKey,$extInfo,$remote=0) {
1797 $lines[]='<tr class="bgColor5"><td colspan="2"><strong>General information:</strong></td>'.$this->helpCol('').'</tr>';
1798 $lines[]='<tr class="bgColor4"><td>Title:</td><td>'.$extInfo['EM_CONF']['_icon'].$extInfo['EM_CONF']['title'].'</td>'.$this->helpCol('title').'</tr>';
1799 $lines[]='<tr class="bgColor4"><td>Description:</td><td>'.nl2br(htmlspecialchars($extInfo['EM_CONF']['description'])).'</td>'.$this->helpCol('description').'</tr>';
1800 $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']).
1801 ($extInfo['EM_CONF']['author_company']?
', '.$extInfo['EM_CONF']['author_company']:'').
1802 '</td>'.$this->helpCol('description').'</tr>';
1804 $lines[]='<tr class="bgColor4"><td>Version:</td><td>'.$extInfo['EM_CONF']['version'].'</td>'.$this->helpCol('version').'</tr>';
1805 $lines[]='<tr class="bgColor4"><td>Category:</td><td>'.$this->categories
[$extInfo['EM_CONF']['category']].'</td>'.$this->helpCol('category').'</tr>';
1806 $lines[]='<tr class="bgColor4"><td>State:</td><td>'.$this->states
[$extInfo['EM_CONF']['state']].'</td>'.$this->helpCol('state').'</tr>';
1807 $lines[]='<tr class="bgColor4"><td>Shy?</td><td>'.($extInfo['EM_CONF']['shy']?
'Yes':'').'</td>'.$this->helpCol('shy').'</tr>';
1808 $lines[]='<tr class="bgColor4"><td>Internal?</td><td>'.($extInfo['EM_CONF']['internal']?
'Yes':'').'</td>'.$this->helpCol('internal').'</tr>';
1810 $lines[]='<tr class="bgColor4"><td>Dependencies:</td><td>'.$extInfo['EM_CONF']['dependencies'].'</td>'.$this->helpCol('dependencies').'</tr>';
1812 $lines[]='<tr class="bgColor4"><td>Conflicts:</td><td>'.$extInfo['EM_CONF']['conflicts'].'</td>'.$this->helpCol('conflicts').'</tr>';
1813 $lines[]='<tr class="bgColor4"><td>Priority:</td><td>'.$extInfo['EM_CONF']['priority'].'</td>'.$this->helpCol('priority').'</tr>';
1814 $lines[]='<tr class="bgColor4"><td>Clear cache?</td><td>'.($extInfo['EM_CONF']['clearCacheOnLoad']?
'Yes':'').'</td>'.$this->helpCol('clearCacheOnLoad').'</tr>';
1815 $lines[]='<tr class="bgColor4"><td>Includes modules:</td><td>'.$extInfo['EM_CONF']['module'].'</td>'.$this->helpCol('module').'</tr>';
1817 $lines[]='<tr class="bgColor4"><td>Lock Type?</td><td>'.($extInfo['EM_CONF']['lockType']?
$extInfo['EM_CONF']['lockType']:'').'</td>'.$this->helpCol('lockType').'</tr>';
1818 $lines[]='<tr class="bgColor4"><td>Modifies tables:</td><td>'.$extInfo['EM_CONF']['modify_tables'].'</td>'.$this->helpCol('modify_tables').'</tr>';
1820 $lines[]='<tr class="bgColor4"><td>Private?</td><td>'.($extInfo['EM_CONF']['private']?
'Yes':'').'</td>'.$this->helpCol('private').'</tr>';
1821 if (!$remote) $lines[]='<tr class="bgColor4"><td>Download password:</td><td>'.$extInfo['EM_CONF']['download_password'].'</td>'.$this->helpCol('download_password').'</tr>';
1823 // Installation status:
1824 $lines[]='<tr><td> </td><td></td>'.$this->helpCol('').'</tr>';
1825 $lines[]='<tr class="bgColor5"><td colspan="2"><strong>Installation status:</strong></td>'.$this->helpCol('').'</tr>';
1827 $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>';
1828 $lines[]='<tr class="bgColor4"><td>Double installs?</td><td>'.$this->extInformationArray_dbInst($extInfo['doubleInstall'],$extInfo['type']).'</td>'.$this->helpCol('doubleInstall').'</tr>';
1830 if (is_array($extInfo['files'])) {
1831 sort($extInfo['files']);
1832 $lines[]='<tr class="bgColor4"><td>Root files:</td><td>'.implode('<br />',$extInfo['files']).'</td>'.$this->helpCol('rootfiles').'</tr>';
1836 $techInfo = $this->makeDetailedExtensionAnalysis($extKey,$extInfo,1);
1837 } else $techInfo = $extInfo['_TECH_INFO'];
1840 if ($techInfo['tables']||
$techInfo['static']||
$techInfo['fields']) {
1841 if (!$remote && t3lib_extMgm
::isLoaded($extKey)) {
1842 $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!':'').
1843 ($techInfo['static_error']?
'<strong>Static table error!</strong><br />The static tables are missing or empty!':''));
1845 $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!';
1849 $lines[]='<tr class="bgColor4"><td>Database requirements:</td><td>'.$this->extInformationArray_dbReq($techInfo,1).'</td>'.$this->helpCol('dbReq').'</tr>';
1850 if (!$remote) $lines[]='<tr class="bgColor4"><td>Database status:</td><td>'.$tableStatus.'</td>'.$this->helpCol('dbStatus').'</tr>';
1851 $lines[]='<tr class="bgColor4"><td>Flags:</td><td>'.(is_array($techInfo['flags'])?
implode('<br />',$techInfo['flags']):'').'</td>'.$this->helpCol('flags').'</tr>';
1852 $lines[]='<tr class="bgColor4"><td>Config template?</td><td>'.($techInfo['conf']?
'Yes':'').'</td>'.$this->helpCol('conf').'</tr>';
1853 $lines[]='<tr class="bgColor4"><td>TypoScript files:</td><td>'.(is_array($techInfo['TSfiles'])?
implode('<br />',$techInfo['TSfiles']):'').'</td>'.$this->helpCol('TSfiles').'</tr>';
1854 $lines[]='<tr class="bgColor4"><td>Language files:</td><td>'.(is_array($techInfo['locallang'])?
implode('<br />',$techInfo['locallang']):'').'</td>'.$this->helpCol('locallang').'</tr>';
1855 $lines[]='<tr class="bgColor4"><td>Upload folder:</td><td>'.($techInfo['uploadfolder']?
$techInfo['uploadfolder']:'').'</td>'.$this->helpCol('uploadfolder').'</tr>';
1856 $lines[]='<tr class="bgColor4"><td>Create directories:</td><td>'.(is_array($techInfo['createDirs'])?
implode('<br />',$techInfo['createDirs']):'').'</td>'.$this->helpCol('createDirs').'</tr>';
1857 $lines[]='<tr class="bgColor4"><td>Module names:</td><td>'.(is_array($techInfo['moduleNames'])?
implode('<br />',$techInfo['moduleNames']):'').'</td>'.$this->helpCol('moduleNames').'</tr>';
1858 $lines[]='<tr class="bgColor4"><td>Class names:</td><td>'.(is_array($techInfo['classes'])?
implode('<br />',$techInfo['classes']):'').'</td>'.$this->helpCol('classNames').'</tr>';
1859 $lines[]='<tr class="bgColor4"><td>Errors:</td><td>'.(is_array($techInfo['errors'])?
$GLOBALS['TBE_TEMPLATE']->rfw(implode('<hr />',$techInfo['errors'])):'').'</td>'.$this->helpCol('errors').'</tr>';
1860 $lines[]='<tr class="bgColor4"><td>Naming errors:</td><td>'.(is_array($techInfo['NSerrors'])?
1861 (!t3lib_div
::inList($this->nameSpaceExceptions
,$extKey)?t3lib_div
::view_array($techInfo['NSerrors']):$GLOBALS['TBE_TEMPLATE']->dfw('[exception]'))
1862 :'').'</td>'.$this->helpCol('NSerrors').'</tr>';
1866 $currentMd5Array = $this->serverExtensionMD5Array($extKey,$extInfo);
1870 # $msgLines[] = 'Files: '.count($currentMd5Array);
1871 if (strcmp($extInfo['EM_CONF']['_md5_values_when_last_written'],serialize($currentMd5Array))) {
1872 $msgLines[] = $GLOBALS['TBE_TEMPLATE']->rfw('<br /><strong>A difference between the originally installed version and the current was detected!</strong>');
1873 $affectedFiles = $this->findMD5ArrayDiff($currentMd5Array,unserialize($extInfo['EM_CONF']['_md5_values_when_last_written']));
1874 if (count($affectedFiles)) $msgLines[] = '<br /><strong>Modified files:</strong><br />'.$GLOBALS['TBE_TEMPLATE']->rfw(implode('<br />',$affectedFiles));
1876 $lines[]='<tr class="bgColor4"><td>Files changed?</td><td>'.implode('<br />',$msgLines).'</td>'.$this->helpCol('filesChanged').'</tr>';
1879 return '<table border="0" cellpadding="1" cellspacing="2">
1886 * Returns HTML with information about database requirements
1888 * @param array Technical information array
1889 * @param boolean Table header displayed
1890 * @return string HTML content.
1892 function extInformationArray_dbReq($techInfo,$tableHeader=0) {
1893 return nl2br(trim((is_array($techInfo['tables'])?
($tableHeader?
"\n\n<strong>Tables:</strong>\n":'').implode(chr(10),$techInfo['tables']):'').
1894 (is_array($techInfo['static'])?
"\n\n<strong>Static tables:</strong>\n".implode(chr(10),$techInfo['static']):'').
1895 (is_array($techInfo['fields'])?
"\n\n<strong>Additional fields:</strong>\n".implode('<hr />',$techInfo['fields']):'')));
1899 * Double install warning.
1901 * @param string Double-install string, eg. "LG" etc.
1902 * @param string Current scope, eg. "L" or "G" or "S"
1903 * @return string Message
1905 function extInformationArray_dbInst($dbInst,$current) {
1906 if (strlen($dbInst)>1) {
1908 for($a=0;$a<strlen($dbInst);$a++
) {
1909 if (substr($dbInst,$a,1)!=$current) {
1910 $others[]='"'.$this->typeLabels
[substr($dbInst,$a,1)].'"';
1913 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 precendence.');
1918 * Prints the upload form for extensions
1920 * @param string Extension key
1921 * @param array Extension information array
1922 * @return string HTML content.
1924 function getRepositoryUploadForm($extKey,$extInfo) {
1925 $uArr = $this->makeUploadArray($extKey,$extInfo);
1926 if (is_array($uArr)) {
1927 $backUpData = $this->makeUploadDataFromArray($uArr);
1929 #debug($this->decodeExchangeData($backUpData));
1930 $content.='Extension "'.$this->extensionTitleIconHeader($extKey,$extInfo).'" is ready to be uploaded.<br />
1931 The size of the upload is <strong>'.t3lib_div
::formatSize(strlen($backUpData)).'</strong><br />
1934 $b64data = base64_encode($backUpData);
1935 $content='</form><form action="'.$this->repositoryUrl
.'" method="post" enctype="application/x-www-form-urlencoded">
1936 <input type="hidden" name="tx_extrep[upload][returnUrl]" value="'.htmlspecialchars($this->makeReturnUrl()).'" />
1937 <input type="hidden" name="tx_extrep[upload][data]" value="'.$b64data.'" />
1938 <input type="hidden" name="tx_extrep[upload][typo3ver]" value="'.$GLOBALS['TYPO_VERSION'].'" />
1939 <input type="hidden" name="tx_extrep[upload][os]" value="'.TYPO3_OS
.'" />
1940 <input type="hidden" name="tx_extrep[upload][sapi]" value="'.php_sapi_name().'" />
1941 <input type="hidden" name="tx_extrep[upload][phpver]" value="'.phpversion().'" />
1942 <input type="hidden" name="tx_extrep[upload][gzcompressed]" value="'.$this->gzcompress
.'" />
1943 <input type="hidden" name="tx_extrep[upload][data_md5]" value="'.md5($b64data).'" />
1944 <table border="0" cellpadding="2" cellspacing="1">
1945 <tr class="bgColor4">
1946 <td>Repository Username:</td>
1947 <td><input'.$this->doc
->formWidth(20).' type="text" name="tx_extrep[user][fe_u]" value="'.$this->fe_user
['username'].'" /></td>
1949 <tr class="bgColor4">
1950 <td>Repository Password:</td>
1951 <td><input'.$this->doc
->formWidth(20).' type="password" name="tx_extrep[user][fe_p]" value="'.$this->fe_user
['password'].'" /></td>
1953 <tr class="bgColor4">
1954 <td>Upload password for this extension:</td>
1955 <td><input'.$this->doc
->formWidth(30).' type="password" name="tx_extrep[upload][upload_p]" value="'.$this->fe_user
['uploadPass'].'" /></td>
1957 <tr class="bgColor4">
1958 <td>Changelog for upload:</td>
1959 <td><textarea'.$this->doc
->formWidth(30,1).' rows="5" name="tx_extrep[upload][comment]"></textarea></td>
1961 <tr class="bgColor4">
1962 <td>Upload command:</td>
1963 <td nowrap="nowrap">
1964 <input type="radio" name="tx_extrep[upload][mode]" value="new_dev" checked="checked" /> New development version (latest x.x.<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('x+1').'</strong>)<br />
1965 <input type="radio" name="tx_extrep[upload][mode]" value="latest" /> Override <em>this</em> development version ('.$extInfo['EM_CONF']['version'].')<br />
1966 <input type="radio" name="tx_extrep[upload][mode]" value="new_sub" /> New sub version (latest x.<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('x+1').'</strong>.0)<br />
1967 <input type="radio" name="tx_extrep[upload][mode]" value="new_main" /> New main version (latest <strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('x+1').'</strong>.0.0)<br />
1970 <!-- Removing "private keys" since they are probably not used much. Better option for people is to distribute "private" extensions as files by emails.
1971 <tr class="bgColor4">
1974 <input type="checkbox" name="tx_extrep[upload][private]" value="1"'.($extInfo['EM_CONF']['private'] ?
' checked="checked"' : '').' />Yes, dont show <em>this upload</em> in the public list.<br />
1975 ("Private" uploads requires you to manually enter a special key (which will be shown to you after the upload has been completed) to be able to import and view details for the upload. This is nice when you are working on something internally which you do not want others to look at.)<br />
1976 <br /><strong>Additional import password:</strong><br />
1977 <input'.$this->doc
->formWidth(20).' type="text" name="tx_extrep[upload][download_password]" value="'.htmlspecialchars(trim($extInfo['EM_CONF']['download_password'])).'" /> (Textfield!) <br />
1978 (Anybody who knows the "special key" assigned to the private upload will be able to import it. Specifying an import password allows you to give away the download key for private uploads and also require a password given in addition. The password can be changed later on.)<br />
1982 <tr class="bgColor4">
1984 <td><input type="submit" name="submit" value="Upload extension" /><br />
1985 '.t3lib_div
::formatSize(strlen($b64data)).($this->gzcompress?
", compressed":"").', base64<br />
1987 Clicking "Save as file" will allow you to save the extension as a file. This provides you with a backup copy of your extension which can be imported later if needed. "Save as file" ignores the information entered in this form!
2008 /***********************************
2010 * Extension list rendering
2012 **********************************/
2015 * Prints the header row for the various listings
2017 * @param string Attributes for the <tr> tag
2018 * @param array Preset cells in the beginning of the row. Typically a blank cell with a clear-gif
2019 * @param boolean If set, the list is coming from remote server.
2020 * @return string HTML <tr> table row
2022 function extensionListRowHeader($trAttrib,$cells,$import=0) {
2023 $cells[] = '<td></td>';
2024 $cells[] = '<td>Title:</td>';
2026 if (!$this->MOD_SETTINGS
['display_details']) {
2027 $cells[] = '<td>Description:</td>';
2028 $cells[] = '<td>Author:</td>';
2029 } elseif ($this->MOD_SETTINGS
['display_details']==2) {
2030 $cells[] = '<td>Priority:</td>';
2031 $cells[] = '<td>Mod.Tables:</td>';
2032 $cells[] = '<td>Modules:</td>';
2033 $cells[] = '<td>Cl.Cache?</td>';
2034 $cells[] = '<td>Internal?</td>';
2035 $cells[] = '<td>Shy?</td>';
2036 } elseif ($this->MOD_SETTINGS
['display_details']==3) {
2037 $cells[] = '<td>Tables/Fields:</td>';
2038 $cells[] = '<td>TS-files:</td>';
2039 $cells[] = '<td>Affects:</td>';
2040 $cells[] = '<td>Modules:</td>';
2041 $cells[] = '<td>Config?</td>';
2042 $cells[] = '<td>Errors:</td>';
2043 } elseif ($this->MOD_SETTINGS
['display_details']==4) {
2044 $cells[] = '<td>locallang:</td>';
2045 $cells[] = '<td>Classes:</td>';
2046 $cells[] = '<td>Errors:</td>';
2047 $cells[] = '<td>NameSpace Errors:</td>';
2048 } elseif ($this->MOD_SETTINGS
['display_details']==5) {
2049 $cells[] = '<td>Changed files:</td>';
2051 $cells[] = '<td>Extension key:</td>';
2052 $cells[] = '<td>Version:</td>';
2054 $cells[] = '<td>Doc:</td>';
2055 $cells[] = '<td>Type:</td>';
2057 $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>';
2058 $cells[] = '<td class="bgColor6"'.$this->labelInfo('Current type of installation of the extension on this server.').'>Cur. Type:</td>';
2059 $cells[] = '<td'.$this->labelInfo('If blank, everyone has access to this extension. "Owner" means that you see it ONLY because you are the owner. "Member" means you see it ONLY because you are among the project members.').'>Access:</td>';
2060 $cells[] = '<td'.$this->labelInfo('TYPO3 version of last uploading server.').'>T3 ver:</td>';
2061 $cells[] = '<td'.$this->labelInfo('PHP version of last uploading server.').'>PHP:</td>';
2062 $cells[] = '<td'.$this->labelInfo('Size of extension, uncompressed / compressed').'>Size:</td>';
2063 $cells[] = '<td'.$this->labelInfo('Number of downloads, all versions/this version').'>DL:</td>';
2065 $cells[] = '<td>State:</td>';
2066 $cells[] = '<td>Dependencies:</td>';
2076 * Prints a row with data for the various extension listings
2078 * @param string Extension key
2079 * @param array Extension information array
2080 * @param array Preset table cells, eg. install/uninstall icons.
2081 * @param string <tr> tag class
2082 * @param array Array with installed extension keys (as keys)
2083 * @param boolean If set, the list is coming from remote server.
2084 * @param string Alternative link URL
2085 * @return string HTML <tr> content
2087 function extensionListRow($extKey,$extInfo,$cells,$bgColorClass='',$inst_list=array(),$import=0,$altLinkUrl='') {
2090 $style = t3lib_extMgm
::isLoaded($extKey) ?
'' : ' style="color:#666666;"';
2093 $imgInfo = @getImageSize
($this->getExtPath($extKey,$extInfo['type']).'/ext_icon.gif');
2094 if (is_array($imgInfo)) {
2095 $cells[] = '<td><img src="'.$GLOBALS['BACK_PATH'].$this->typeRelPaths
[$extInfo['type']].$extKey.'/ext_icon.gif'.'" '.$imgInfo[3].' alt="" /></td>';
2096 } elseif ($extInfo['_ICON']) {
2097 $cells[] = '<td>'.$extInfo['_ICON'].'</td>';
2099 $cells[] = '<td><img src="clear.gif" width="1" height="1" alt="" /></td>';
2103 $cells[] = '<td nowrap="nowrap"><a href="'.htmlspecialchars($altLinkUrl?
$altLinkUrl:'index.php?CMD[showExt]='.$extKey.'&SET[singleDetails]=info').'" title="'.$extKey.'"'.$style.'>'.t3lib_div
::fixed_lgd($extInfo['EM_CONF']['title']?
$extInfo['EM_CONF']['title']:'<em>'.$extKey.'</em>',40).'</a></td>';
2105 // Unset extension key in installed keys array (for tracking)
2106 if (isset($inst_list[$extKey])) {
2107 unset($this->inst_keys
[$extKey]);
2110 // Based on which display mode you will see more or less details:
2111 if (!$this->MOD_SETTINGS
['display_details']) {
2112 $cells[] = '<td>'.htmlspecialchars(t3lib_div
::fixed_lgd($extInfo['EM_CONF']['description'],400)).'<br /><img src="clear.gif" width="300" height="1" alt="" /></td>';
2113 $cells[] = '<td nowrap="nowrap">'.htmlspecialchars($extInfo['EM_CONF']['author'].($extInfo['EM_CONF']['author_company'] ?
'<br />'.$extInfo['EM_CONF']['author_company'] : '')).'</td>';
2114 } elseif ($this->MOD_SETTINGS
['display_details']==2) {
2115 $cells[] = '<td nowrap="nowrap">'.$extInfo['EM_CONF']['priority'].'</td>';
2116 $cells[] = '<td nowrap="nowrap">'.implode('<br />',t3lib_div
::trimExplode(',',$extInfo['EM_CONF']['modify_tables'],1)).'</td>';
2117 $cells[] = '<td nowrap="nowrap">'.$extInfo['EM_CONF']['module'].'</td>';
2118 $cells[] = '<td nowrap="nowrap">'.($extInfo['EM_CONF']['clearCacheOnLoad'] ?
'Yes' : '').'</td>';
2119 $cells[] = '<td nowrap="nowrap">'.($extInfo['EM_CONF']['internal'] ?
'Yes' : '').'</td>';
2120 $cells[] = '<td nowrap="nowrap">'.($extInfo['EM_CONF']['shy'] ?
'Yes' : '').'</td>';
2121 } elseif ($this->MOD_SETTINGS
['display_details']==3) {
2122 $techInfo = $this->makeDetailedExtensionAnalysis($extKey,$extInfo);
2124 $cells[] = '<td>'.$this->extInformationArray_dbReq($techInfo).
2126 $cells[] = '<td nowrap="nowrap">'.(is_array($techInfo['TSfiles']) ?
implode('<br />',$techInfo['TSfiles']) : '').'</td>';
2127 $cells[] = '<td nowrap="nowrap">'.(is_array($techInfo['flags']) ?
implode('<br />',$techInfo['flags']) : '').'</td>';
2128 $cells[] = '<td nowrap="nowrap">'.(is_array($techInfo['moduleNames']) ?
implode('<br />',$techInfo['moduleNames']) : '').'</td>';
2129 $cells[] = '<td nowrap="nowrap">'.($techInfo['conf'] ?
'Yes' : '').'</td>';
2131 $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!':'').
2132 (t3lib_extMgm
::isLoaded($extKey)&&$techInfo['static_error']?
'<strong>Static table error!</strong><br />The static tables are missing or empty!':'')).
2134 } elseif ($this->MOD_SETTINGS
['display_details']==4) {
2135 $techInfo=$this->makeDetailedExtensionAnalysis($extKey,$extInfo,1);
2137 $cells[] = '<td>'.(is_array($techInfo['locallang']) ?
implode('<br />',$techInfo['locallang']) : '').'</td>';
2138 $cells[] = '<td>'.(is_array($techInfo['classes']) ?
implode('<br />',$techInfo['classes']) : '').'</td>';
2139 $cells[] = '<td>'.(is_array($techInfo['errors']) ?
$GLOBALS['TBE_TEMPLATE']->rfw(implode('<hr />',$techInfo['errors'])) : '').'</td>';
2140 $cells[] = '<td>'.(is_array($techInfo['NSerrors']) ?
(!t3lib_div
::inList($this->nameSpaceExceptions
,$extKey) ? t3lib_div
::view_array($techInfo['NSerrors']) : $GLOBALS['TBE_TEMPLATE']->dfw('[exception]')) :'').'</td>';
2141 } elseif ($this->MOD_SETTINGS
['display_details']==5) {
2142 $currentMd5Array = $this->serverExtensionMD5Array($extKey,$extInfo);
2143 $affectedFiles = '';
2144 $msgLines = array();
2145 $msgLines[] = 'Files: '.count($currentMd5Array);
2146 if (strcmp($extInfo['EM_CONF']['_md5_values_when_last_written'],serialize($currentMd5Array))) {
2147 $msgLines[] = $GLOBALS['TBE_TEMPLATE']->rfw('<br /><strong>A difference between the originally installed version and the current was detected!</strong>');
2148 $affectedFiles = $this->findMD5ArrayDiff($currentMd5Array,unserialize($extInfo['EM_CONF']['_md5_values_when_last_written']));
2149 if (count($affectedFiles)) $msgLines[] = '<br /><strong>Modified files:</strong><br />'.$GLOBALS['TBE_TEMPLATE']->rfw(implode('<br />',$affectedFiles));
2151 $cells[] = '<td>'.implode('<br />',$msgLines).'</td>';
2154 $verDiff = $inst_list[$extKey] && $this->versionDifference($extInfo['EM_CONF']['version'],$inst_list[$extKey]['EM_CONF']['version'],$this->versionDiffFactor
);
2156 $cells[] = '<td nowrap="nowrap"><em>'.$extKey.'</em></td>';
2157 $cells[] = '<td nowrap="nowrap">'.($verDiff ?
'<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw(htmlspecialchars($extInfo['EM_CONF']['version'])).'</strong>' : $extInfo['EM_CONF']['version']).'</td>';
2158 if (!$import) { // Listing extenson on LOCAL server:
2159 $fileP = PATH_site
.$this->typePaths
[$extInfo['type']].$extKey.'/doc/manual.sxw';
2161 $cells[] = '<td nowrap="nowrap">'.
2162 ($this->typePaths
[$extInfo['type']] && @is_file
($fileP)?
'<img src="oodoc.gif" width="13" height="16" title="Local Open Office Manual" alt="" />':'').
2164 $cells[] = '<td nowrap="nowrap">'.$this->typeLabels
[$extInfo['type']].(strlen($extInfo['doubleInstall'])>1?
'<strong> '.$GLOBALS['TBE_TEMPLATE']->rfw($extInfo['doubleInstall']).'</strong>':'').'</td>';
2165 } else { // Listing extensions from REMOTE repository:
2166 $inst_curVer = $inst_list[$extKey]['EM_CONF']['version'];
2167 if (isset($inst_list[$extKey])) {
2168 if ($verDiff) $inst_curVer = '<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw($inst_curVer).'</strong>';
2170 $cells[] = '<td nowrap="nowrap">'.$inst_curVer.'</td>';
2171 $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>';
2172 $cells[] = '<td nowrap="nowrap"><strong>'.$GLOBALS['TBE_TEMPLATE']->rfw($this->remoteAccess
[$extInfo['_ACCESS']]).'</strong></td>';
2173 $cells[] = '<td nowrap="nowrap">'.$extInfo['EM_CONF']['_typo3_ver'].'</td>';
2174 $cells[] = '<td nowrap="nowrap">'.$extInfo['EM_CONF']['_php_ver'].'</td>';
2175 $cells[] = '<td nowrap="nowrap">'.$extInfo['EM_CONF']['_size'].'</td>';
2176 $cells[] = '<td nowrap="nowrap">'.($extInfo['_STAT_IMPORT']['extension_allversions']?
$extInfo['_STAT_IMPORT']['extension_allversions']:' ').'/'.($extInfo['_STAT_IMPORT']['extension_thisversion']?
$extInfo['_STAT_IMPORT']['extension_thisversion']:' ').'</td>';
2178 $cells[] = '<td nowrap="nowrap">'.$this->states
[$extInfo['EM_CONF']['state']].'</td>';
2179 $cells[] = '<td nowrap="nowrap">'.$extInfo['EM_CONF']['dependencies'].'</td>';
2182 $bgColor = ' class="'.($bgColorClass?
$bgColorClass:'bgColor4').'"';
2184 <tr'.$bgColor.$style.'>
2199 /************************************
2201 * Output helper functions
2203 ************************************/
2206 * Wrapping input string in a link tag with link to email address
2208 * @param string Input string, being wrapped in <a> tags
2209 * @param string Email address for use in link.
2210 * @return string Output
2212 function wrapEmail($str,$email) {
2214 $str = '<a href="mailto:'.htmlspecialchars($email).'">'.htmlspecialchars($str).'</a>';
2220 * Returns help text if applicable.
2222 * @param string Help text key
2223 * @return string HTML table cell
2225 function helpCol($key) {
2227 if ($BE_USER->uc
['edit_showFieldHelp']) {
2228 $hT = trim(t3lib_BEfunc
::helpText($this->descrTable
,'emconf_'.$key,$this->doc
->backPath
));
2229 return '<td>'.($hT?
$hT:t3lib_BEfunc
::helpTextIcon($this->descrTable
,'emconf_'.$key,$this->doc
->backPath
)).'</td>';
2234 * Returns title and style attribute for mouseover help text.
2236 * @param string Help text.
2237 * @return string title="" attribute prepended with a single space
2239 function labelInfo($str) {
2240 return ' title="'.htmlspecialchars($str).'" style="cursor:help;"';
2244 * Returns a header for an extensions including icon if any
2246 * @param string Extension key
2247 * @param array Extension information array
2248 * @param string align-attribute value (for <img> tag)
2249 * @return string HTML; Extension title and image.
2251 function extensionTitleIconHeader($extKey,$extInfo,$align='top') {
2252 $imgInfo = @getImageSize
($this->getExtPath($extKey,$extInfo['type']).'/ext_icon.gif');
2254 if (is_array($imgInfo)) {
2255 $out.= '<img src="'.$GLOBALS['BACK_PATH'].$this->typeRelPaths
[$extInfo['type']].$extKey.'/ext_icon.gif" '.$imgInfo[3].' align="'.$align.'" alt="" />';
2257 $out.= $extInfo['EM_CONF']['title'] ?
htmlspecialchars(t3lib_div
::fixed_lgd($extInfo['EM_CONF']['title'],40)) : '<em>'.$extKey.'</em>';
2262 * Returns image tag for "uninstall"
2264 * @return string <img> tag
2266 function removeButton() {
2267 return '<img src="uninstall.gif" width="16" height="16" title="Remove extension" align="top" alt="" />';
2271 * Returns image for "install"
2273 * @return string <img> tag
2275 function installButton() {
2276 return '<img src="install.gif" width="16" height="16" title="Install extension..." align="top" alt="" />';
2280 * Warning (<img> + text string) message about the impossibility to import extensions (both local and global locations are disabled...)
2282 * @return string <img> + text string.
2284 function noImportMsg() {
2285 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>';
2297 /********************************
2299 * Read information about all available extensions
2301 *******************************/
2304 * Returns the list of available (installed) extensions
2306 * @return array Array with two arrays, list array (all extensions with info) and category index
2307 * @see getInstExtList()
2309 function getInstalledExtensions() {
2311 $cat = $this->defaultCategories
;
2313 $path = PATH_site
.TYPO3_mainDir
.'sysext/';
2314 $this->getInstExtList($path,$list,$cat,'S');
2316 $path = PATH_site
.TYPO3_mainDir
.'ext/';
2317 $this->getInstExtList($path,$list,$cat,'G');
2319 $path = PATH_site
.'typo3conf/ext/';
2320 $this->getInstExtList($path,$list,$cat,'L');
2322 return array($list,$cat);
2326 * Gathers all extensions in $path
2328 * @param string Absolute path to local, global or system extensions
2329 * @param array Array with information for each extension key found. Notice: passed by reference
2330 * @param array Categories index: Contains extension titles grouped by various criteria.
2331 * @param string Path-type: L, G or S
2332 * @return void "Returns" content by reference
2334 * @see getInstalledExtensions()
2336 function getInstExtList($path,&$list,&$cat,$type) {
2338 if (@is_dir
($path)) {
2339 $extList = t3lib_div
::get_dirs($path);
2340 if (is_array($extList)) {
2341 foreach($extList as $extKey) {
2342 if (@is_file
($path.$extKey.'/ext_emconf.php')) {
2343 $emConf = $this->includeEMCONF($path.$extKey.'/ext_emconf.php', $extKey);
2344 if (is_array($emConf)) {
2345 # unset($emConf['_md5_values_when_last_written']); // Trying to save space - hope this doesn't break anything. Shaves of maybe 100K!
2346 # unset($emConf['description']); // Trying to save space - hope this doesn't break anything
2347 if (is_array($list[$extKey])) {
2348 $list[$extKey]=array('doubleInstall'=>$list[$extKey]['doubleInstall']);
2350 $list[$extKey]['doubleInstall'].= $type;
2351 $list[$extKey]['type'] = $type;
2352 $list[$extKey]['EM_CONF'] = $emConf;
2353 # $list[$extKey]['files'] = array_keys(array_flip(t3lib_div::getFilesInDir($path.$extKey))); // Shaves off a little by using num-indexes
2354 $list[$extKey]['files'] = t3lib_div
::getFilesInDir($path.$extKey);
2356 $this->setCat($cat,$list[$extKey], $extKey);
2365 * Maps remote extensions information into $cat/$list arrays for listing
2367 * @param array List of extensions from remote repository
2368 * @return array List array and category index as key 0 / 1 in an array.
2370 function getImportExtList($listArr) {
2372 $cat = $this->defaultCategories
;
2374 if (is_array($listArr)) {
2376 foreach($listArr as $dat) {
2377 $extKey = $dat['extension_key'];
2378 $list[$extKey]['type'] = '_';
2379 $list[$extKey]['extRepUid'] = $dat['uid'];
2380 $list[$extKey]['_STAT_IMPORT'] = $dat['_STAT_IMPORT'];
2381 $list[$extKey]['_ACCESS'] = $dat['_ACCESS'];
2382 $list[$extKey]['_ICON'] = $dat['_ICON'];
2383 $list[$extKey]['_MEMBERS_ONLY'] = $dat['_MEMBERS_ONLY'];
2384 $list[$extKey]['EM_CONF'] = array(
2385 'title' => $dat['emconf_title'],
2386 'description' => $dat['emconf_description'],
2387 'category' => $dat['emconf_category'],
2388 'shy' => $dat['emconf_shy'],
2389 'dependencies' => $dat['emconf_dependencies'],
2390 'state' => $dat['emconf_state'],
2391 'private' => $dat['emconf_private'],
2392 'uploadfolder' => $dat['emconf_uploadfolder'],
2393 'createDirs' => $dat['emconf_createDirs'],
2394 'modify_tables' => $dat['emconf_modify_tables'],
2395 'module' => $dat['emconf_module'],
2396 'lockType' => $dat['emconf_lockType'],
2397 'clearCacheOnLoad' => $dat['emconf_clearCacheOnLoad'],
2398 'priority' => $dat['emconf_priority'],
2399 'version' => $dat['version'],
2400 'internal' => $dat['emconf_internal'],
2401 'author' => $dat['emconf_author'],
2402 'author_company' => $dat['emconf_author_company'],
2404 '_typo3_ver' => $dat['upload_typo3_version'],
2405 '_php_ver' => $dat['upload_php_version'],
2406 '_size' => t3lib_div
::formatSize($dat['datasize']).'/'.t3lib_div
::formatSize($dat['datasize_gz']),
2408 $this->setCat($cat, $list[$extKey], $extKey);
2411 return array($list,$cat);
2415 * Set category array entries for extension
2417 * @param array Category index array
2418 * @param array Part of list array for extension.
2419 * @param string Extension key
2420 * @return array Modified category index array
2422 function setCat(&$cat,$listArrayPart,$extKey) {
2424 // Getting extension title:
2425 $extTitle = $listArrayPart['EM_CONF']['title'];
2428 $index = $listArrayPart['EM_CONF']['category'];
2429 $cat['cat'][$index][$extKey] = $extTitle;
2432 $index = $listArrayPart['EM_CONF']['author'].($listArrayPart['EM_CONF']['author_company']?
', '.$listArrayPart['EM_CONF']['author_company']:'');
2433 $cat['author_company'][$index][$extKey] = $extTitle;
2436 $index = $listArrayPart['EM_CONF']['state'];
2437 $cat['state'][$index][$extKey] = $extTitle;
2440 $index = $listArrayPart['EM_CONF']['private'] ?
1 : 0;
2441 $cat['private'][$index][$extKey] = $extTitle;
2444 $index = $listArrayPart['type'];
2445 $cat['type'][$index][$extKey] = $extTitle;
2448 if ($list[$extKey]['EM_CONF']['dependencies']) {
2449 $depItems = t3lib_div
::trimExplode(',', $list[$extKey]['EM_CONF']['dependencies'], 1);
2450 foreach($depItems as $depKey) {
2451 $cat['dep'][$depKey][$extKey] = $extTitle;
2455 // Return categories:
2468 /*******************************
2470 * Extension analyzing (detailed information)
2472 ******************************/
2475 * Perform a detailed, technical analysis of the available extension on server!
2476 * Includes all kinds of verifications
2477 * Takes some time to process, therfore use with care, in particular in listings.
2479 * @param string Extension key
2480 * @param array Extension information
2481 * @param boolean If set, checks for validity of classes etc.
2482 * @return array Information in an array.
2484 function makeDetailedExtensionAnalysis($extKey,$extInfo,$validity=0) {
2486 // Get absolute path of the extension
2487 $absPath = $this->getExtPath($extKey,$extInfo['type']);
2489 $infoArray = array();
2491 $table_class_prefix = substr($extKey,0,5)=='user_' ?
'user_' : 'tx_'.str_replace('_','',$extKey).'_';
2492 $module_prefix = substr($extKey,0,5)=='user_' ?
'u' : 'tx'.str_replace('_','',$extKey);
2495 $dbInfo = $this->checkDBupdates($extKey,$extInfo,1);
2497 // Database structure required:
2498 if (is_array($dbInfo['structure']['tables_fields'])) {
2499 $modify_tables = t3lib_div
::trimExplode(',',$extInfo['EM_CONF']['modify_tables'],1);
2500 $infoArray['dump_tf'] = array();
2502 foreach($dbInfo['structure']['tables_fields'] as $tN => $d) {
2503 if (in_array($tN,$modify_tables)) {
2504 $infoArray['fields'][] = $tN.': <i>'.
2505 (is_array($d['fields']) ?
implode(', ',array_keys($d['fields'])) : '').
2506 (is_array($d['keys']) ?
' + '.count($d['keys']).' keys' : '').
2508 if (is_array($d['fields'])) {
2509 reset($d['fields']);
2510 while(list($fN) = each($d['fields'])) {
2511 $infoArray['dump_tf'][] = $tN.'.'.$fN;
2512 if (!t3lib_div
::isFirstPartOfStr($fN,$table_class_prefix)) {
2513 $infoArray['NSerrors']['fields'][$fN] = $fN;
2515 $infoArray['NSok']['fields'][$fN] = $fN;
2519 if (is_array($d['keys'])) {
2521 while(list($fN)=each($d['keys'])) {
2522 $infoArray['dump_tf'][] = $tN.'.KEY:'.$fN;
2526 $infoArray['dump_tf'][] = $tN;
2527 $infoArray['tables'][] = $tN;
2528 if (!t3lib_div
::isFirstPartOfStr($tN,$table_class_prefix)) {
2529 $infoArray['NSerrors']['tables'][$tN] = $tN;
2530 } else $infoArray['NSok']['tables'][$tN] = $tN;
2533 if (count($dbInfo['structure']['diff']['diff']) ||
count($dbInfo['structure']['diff']['extra'])) {
2535 if (count($dbInfo['structure']['diff']['diff'])) $msg[] = 'missing';
2536 if (count($dbInfo['structure']['diff']['extra'])) $msg[] = 'of wrong type';
2537 $infoArray['tables_error'] = 1;
2538 if (t3lib_extMgm
::isLoaded($extKey)) $infoArray['errors'][] = 'Some tables or fields are '.implode(' and ',$msg).'!';
2543 if (is_array($dbInfo['static'])) {
2544 $infoArray['static'] = array_keys($dbInfo['static']);
2546 foreach($dbInfo['static'] as $tN => $d) {
2547 if (!$d['exists']) {
2548 $infoArray['static_error'] = 1;
2549 if (t3lib_extMgm
::isLoaded($extKey)) $infoArray['errors'][] = 'Static table(s) missing!';
2550 if (!t3lib_div
::isFirstPartOfStr($tN,$table_class_prefix)) {
2551 $infoArray['NSerrors']['tables'][$tN] = $tN;
2552 } else $infoArray['NSok']['tables'][$tN] = $tN;
2557 // Backend Module-check:
2558 $knownModuleList = t3lib_div
::trimExplode(',',$extInfo['EM_CONF']['module'],1);
2559 foreach($knownModuleList as $mod) {
2560 if (@is_dir
($absPath.$mod)) {
2561 if (@is_file
($absPath.$mod.'/conf.php')) {
2562 $confFileInfo = $this->modConfFileAnalysis($absPath.$mod.'/conf.php');
2563 if (is_array($confFileInfo['TYPO3_MOD_PATH'])) {
2564 $shouldBePath = $this->typeRelPaths
[$extInfo['type']].$extKey.'/'.$mod.'/';
2565 if (strcmp($confFileInfo['TYPO3_MOD_PATH'][1][1],$shouldBePath)) {
2566 $infoArray['errors'][] = 'Configured TYPO3_MOD_PATH "'.$confFileInfo['TYPO3_MOD_PATH'][1][1].'" different from "'.$shouldBePath.'"';
2568 } else $infoArray['errors'][] = 'No definition of TYPO3_MOD_PATH constant found inside!';
2569 if (is_array($confFileInfo['MCONF_name'])) {
2570 $mName = $confFileInfo['MCONF_name'][1][1];
2571 $mNameParts = explode('_',$mName);
2572 $infoArray['moduleNames'][] = $mName;
2573 if (!t3lib_div
::isFirstPartOfStr($mNameParts[0],$module_prefix) &&
2574 (!$mNameParts[1] ||
!t3lib_div
::isFirstPartOfStr($mNameParts[1],$module_prefix))) {
2575 $infoArray['NSerrors']['modname'][] = $mName;
2576 } else $infoArray['NSok']['modname'][] = $mName;
2577 } else $infoArray['errors'][] = 'No definition of MCONF[name] variable found inside!';
2578 } else $infoArray['errors'][] = 'Backend module conf file "'.$mod.'/conf.php" should exist but does not!';
2579 } else $infoArray['errors'][] = 'Backend module folder "'.$mod.'/" should exist but does not!';
2581 $dirs = t3lib_div
::get_dirs($absPath);
2582 if (is_array($dirs)) {
2584 while(list(,$mod) = each($dirs)) {
2585 if (!in_array($mod,$knownModuleList) && @is_file
($absPath.$mod.'/conf.php')) {
2586 $confFileInfo = $this->modConfFileAnalysis($absPath.$mod.'/conf.php');
2587 if (is_array($confFileInfo)) {
2588 $infoArray['errors'][] = 'It seems like there is a backend module in "'.$mod.'/conf.php" which is not configured in ext_emconf.php';
2595 if (@is_file
($absPath.'ext_tables.php')) {
2596 $content = t3lib_div
::getUrl($absPath.'ext_tables.php');
2597 if (eregi('t3lib_extMgm::addModule',$content)) $infoArray['flags'][] = 'Module';
2598 if (eregi('t3lib_extMgm::insertModuleFunction',$content)) $infoArray['flags'][] = 'Module+';
2599 if (stristr($content,'t3lib_div::loadTCA')) $infoArray['flags'][] = 'loadTCA';
2600 if (stristr($content,'$TCA[')) $infoArray['flags'][] = 'TCA';
2601 if (eregi('t3lib_extMgm::addPlugin',$content)) $infoArray['flags'][] = 'Plugin';
2604 // ext_localconf.php:
2605 if (@is_file
($absPath.'ext_localconf.php')) {
2606 $content = t3lib_div
::getUrl($absPath.'ext_localconf.php');
2607 if (eregi('t3lib_extMgm::addPItoST43',$content)) $infoArray['flags'][]='Plugin/ST43';
2608 if (eregi('t3lib_extMgm::addPageTSConfig',$content)) $infoArray['flags'][]='Page-TSconfig';
2609 if (eregi('t3lib_extMgm::addUserTSConfig',$content)) $infoArray['flags'][]='User-TSconfig';
2610 if (eregi('t3lib_extMgm::addTypoScriptSetup',$content)) $infoArray['flags'][]='TS/Setup';
2611 if (eregi('t3lib_extMgm::addTypoScriptConstants',$content)) $infoArray['flags'][]='TS/Constants';
2614 if (@is_file
($absPath.'ext_typoscript_constants.txt')) {
2615 $infoArray['TSfiles'][] = 'Constants';
2617 if (@is_file
($absPath.'ext_typoscript_setup.txt')) {
2618 $infoArray['TSfiles'][] = 'Setup';
2620 if (@is_file
($absPath.'ext_conf_template.txt')) {
2621 $infoArray['conf'] = 1;
2626 $filesInside = $this->getClassIndexLocallangFiles($absPath,$table_class_prefix,$extKey);
2627 if (is_array($filesInside['errors'])) $infoArray['errors'] = array_merge($infoArray['errors'],$filesInside['errors']);
2628 if (is_array($filesInside['NSerrors'])) $infoArray['NSerrors'] = array_merge($infoArray['NSerrors'],$filesInside['NSerrors']);
2629 if (is_array($filesInside['NSok'])) $infoArray['NSok'] = array_merge($infoArray['NSok'],$filesInside['NSok']);
2630 $infoArray['locallang'] = $filesInside['locallang'];
2631 $infoArray['classes'] = $filesInside['classes'];
2635 if ($extInfo['EM_CONF']['uploadfolder']) {
2636 $infoArray['uploadfolder'] = $this->ulFolder($extKey);
2637 if (!@is_dir
(PATH_site
.$infoArray['uploadfolder'