Fixed issues with mkdir()
[Packages/TYPO3.CMS.git] / typo3 / mod / tools / em / index.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2003 Kasper Skaarhoj (kasper@typo3.com)
6 * All rights reserved
7 *
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.
13 *
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.
18 *
19 *
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.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Module: Extension manager
29 *
30 * $Id$
31 *
32 * @author Kasper Skaarhoj <kasper@typo3.com>
33 */
34 /**
35 * [CLASS/FUNCTION INDEX of SCRIPT]
36 *
37 *
38 *
39 * 153: class em_install_class extends t3lib_install
40 * 155: function em_install_class()
41 *
42 *
43 * 178: class SC_mod_tools_em_index
44 * 276: function init()
45 * 309: function jumpToUrl(URL)
46 * 333: function menuConfig()
47 * 410: function main()
48 * 481: function printContent()
49 * 495: function kickstarter()
50 * 512: function alterSettings()
51 * 532: function extensionList_loaded()
52 * 568: function extensionList_import()
53 * 719: function extensionList_installed()
54 * 796: function importExtInfo($extRepUid)
55 * 886: function getDocManual($extension_key,$loc="")
56 * 906: function importExtFromRep($extRepUid,$loc,$uploadFlag=0,$directInput="",$recentTranslations=0,$incManual=0)
57 * 1055: function showExtDetails($extKey)
58 * 1300: function updatesForm($extKey,$info,$notSilent=0,$script="",$addFields="")
59 * 1331: function extDumpTables($eKey,$info)
60 * 1396: function extDelete($eKey,$info)
61 * 1422: function extUpdateEMCONF($eKey,$info)
62 * 1442: function extMakeNewFromFramework($eKey,$info)
63 * 1463: function extBackup($eKey,$info)
64 * 1517: function extBackup_dumpDataTablesLine($tablesArray,$eKey)
65 * 1546: function extInformationArray($eKey,$info,$remote=0)
66 * 1640: function extInformationArray_dbReq($techInfo,$tableHeader=0)
67 * 1653: function extInformationArray_dbInst($dbInst,$current)
68 * 1672: function wrapEmail($str,$email)
69 * 1685: function helpCol($key)
70 * 1700: function getRepositoryUploadForm($eKey,$info)
71 * 1771: function extensionListRowHeader($bgColor,$cells,$import=0)
72 * 1833: function extensionListRow($eKey,$eConf,$info,$cells,$bgColor="",$inst_list=array(),$import=0,$altLinkUrl="")
73 * 1933: function labelInfo($str)
74 * 1944: function createDirsInPath($dirs,$extDirPath)
75 * 1971: function removeExtDirectory($removePath,$removeContentOnly=0)
76 * 2031: function extractDirsFromFileList($files)
77 * 2056: function clearAndMakeExtensionDir($importedData,$type)
78 * 2102: function versionDifference($v1,$v2,$div=1)
79 * 2113: function fetchServerData($repositoryUrl)
80 * 2136: function decodeServerData($externalData,$stat=array())
81 * 2155: function addClearCacheFiles()
82 * 2179: function extensionTitleIconHeader($eKey,$info,$align="top")
83 * 2198: function makeDetailedExtensionAnalysis($eKey,$info,$validity=0)
84 * 2371: function getClassIndexLocallangFiles($absPath,$table_class_prefix,$eKey)
85 * 2442: function first_in_array($str,$array)
86 * 2457: function modConfFileAnalysis($confFilePath)
87 * 2485: function writeTYPO3_MOD_PATH($confFilePath,$type,$mP)
88 * 2523: function tsStyleConfigForm($eKey,$info,$output=0,$script="",$addFields="")
89 * 2573: function writeTsStyleConfig($eKey,$arr)
90 * 2594: function dumpStaticTables($tableList)
91 * 2621: function dumpTableAndFieldStructure($arr)
92 * 2638: function dumpHeader()
93 * 2655: function dumpTableHeader($table,$fieldKeyInfo,$dropTableIfExists=0)
94 * 2689: function dumpTableContent($table,$fieldStructure)
95 * 2715: function writeNewExtensionList($newExtList)
96 * 2734: function removeCacheFiles()
97 * 2755: function checkClearCache($eKey,$info)
98 * 2777: function checkUploadFolder($eKey,$info)
99 * 2850: function checkDBupdates($eKey,$info,$infoOnly=0)
100 * 2950: function findMD5ArrayDiff($current,$past)
101 * 2966: function removeCVSentries($arr)
102 * 2981: function serverExtensionMD5Array($extKey,$conf)
103 * 3003: function makeUploadArray($extKey,$conf)
104 * 3061: function getSerializedLocalLang($file,$content)
105 * 3078: function getTableAndFieldStructure($parts)
106 * 3110: function construct_ext_emconf_file($extKey,$EM_CONF)
107 * 3152: function decodeExchangeData($str)
108 * 3171: function makeUploadDataFromArray($uploadArray,$local_gzcompress=-1)
109 * 3197: function getFileListOfExtension($extKey,$conf)
110 * 3245: function getAllFilesAndFoldersInPath($fileArr,$extPath,$extList="",$regDirs=0)
111 * 3268: function removePrefixPathFromList($fileArr,$extPath)
112 * 3285: function getExtPath($extKey,$conf)
113 * 3301: function addExtToList($extKey,$list)
114 * 3352: function removeExtFromList($extKey,$list)
115 * 3385: function removeRequiredExtFromListArr($listArr)
116 * 3400: function managesPriorities($listArr,$list)
117 * 3431: function getInstalledExtensions()
118 * 3456: function getInstExtList($path,$list,$cat,$type)
119 * 3491: function getImportExtList($listArr)
120 * 3543: function setCat($cat,$list,$eKey)
121 * 3566: function processRepositoryReturnData($TER_CMD)
122 * 3595: function updateLocalEM_CONF($extKey,$info)
123 * 3618: function includeEMCONF($path,$_EXTKEY)
124 * 3631: function listOrderTitle($listOrder,$key)
125 * 3661: function makeVersion($v,$mode)
126 * 3673: function renderVersion($v,$raise="")
127 * 3706: function T3instID()
128 * 3715: function makeReturnUrl()
129 * 3724: function repTransferParams()
130 * 3738: function ulFolder($eKey)
131 * 3747: function removeButton()
132 * 3756: function installButton()
133 * 3765: function importAtAll()
134 * 3774: function noImportMsg()
135 * 3785: function importAsType($type,$lockType="")
136 *
137 * TOTAL FUNCTIONS: 93
138 * (This index is automatically created/updated by the extension "extdeveval")
139 *
140 */
141
142
143
144 unset($MCONF);
145 require ('conf.php');
146 require ($BACK_PATH.'init.php');
147 require ($BACK_PATH.'template.php');
148 $BE_USER->modAccess($MCONF,1);
149
150 // Include classes needed:
151 require_once(PATH_t3lib.'class.t3lib_tcemain.php');
152 require_once(PATH_t3lib.'class.t3lib_install.php');
153 class em_install_class extends t3lib_install {
154 # Make sure the normal constructor is not called:
155 function em_install_class() {
156 }
157 }
158 require_once(PATH_t3lib.'class.t3lib_tsstyleconfig.php');
159
160 // Include kickstarter wrapped class if extension "extrep_wizard" turns out to be loaded!
161 if (t3lib_extMgm::isLoaded('extrep_wizard')) {
162 require('./class.kickstarter.php');
163 }
164
165
166
167
168
169
170
171 /**
172 * Module: Extension manager
173 *
174 * @author Kasper Skaarhoj <kasper@typo3.com>
175 * @package TYPO3
176 * @subpackage core
177 */
178 class SC_mod_tools_em_index {
179 var $MCONF=array();
180 var $MOD_MENU=array();
181 var $MOD_SETTINGS=array();
182 var $doc;
183
184 var $CMD=array();
185
186 var $content;
187 var $inst_keys=array();
188
189 var $versionDiffFactor = 1000; // This means that version difference testing for import is detected for sub-versions only. Not dev-versions. Default: 1000
190 var $systemInstall = 0; // If "1" then installs in the sysext directory is allowed. Default: 0
191 var $repositoryUrl = ""; // Default is "http://ter.typo3.com/?id=t3_extrep" configured in config_default.php
192
193 var $maxUploadSize = 4024000; // Max size of plugin upload to repository
194 var $kbMax=100;
195 var $gzcompress=0;
196 var $categories = Array(
197 'fe' => 'Frontend',
198 'plugin' => 'Frontend Plugins',
199 'be' => 'Backend',
200 'module' => 'Backend Modules',
201 'example' => 'Examples',
202 'misc' => 'Miscellaneous',
203 'services' => 'Services',
204 'templates' => 'Templates',
205 'doc' => 'Documentation'
206 );
207 var $states = Array (
208 'alpha' => 'Alpha',
209 'beta' => 'Beta',
210 'stable' => 'Stable',
211 'experimental' => 'Experimental',
212 'test' => 'Test',
213 );
214 var $typeLabels = Array (
215 'S' => 'System',
216 'G' => 'Global',
217 'L' => 'Local',
218 );
219 var $typeDescr = Array (
220 'S' => 'System extension (typo3/sysext/) - Always distributed with source code (Static).',
221 'G' => 'Global extensions (typo3/ext/) - Available for shared source on server (Dynamic).',
222 'L' => 'Local extensions (typo3conf/ext/) - Local for this TYPO3 installation only (Dynamic).',
223 );
224 var $typePaths = Array();
225 var $typeBackPaths = Array();
226
227 var $typeRelPaths = Array (
228 'S' => 'sysext/',
229 'G' => 'ext/',
230 'L' => '../typo3conf/ext/',
231 );
232 var $remoteAccess = Array (
233 'all' => '',
234 'owner' => 'Owner',
235 'selected' => 'Selected',
236 'member' => 'Member',
237 );
238
239 var $defaultCategories = Array(
240 'cat' => Array (
241 'be' => array(),
242 'module' => array(),
243 'fe' => array(),
244 'plugin' => array(),
245 'misc' => array(),
246 'services' => array(),
247 'templates' => array(),
248 'example' => array()
249 )
250 );
251 var $detailCols = Array (
252 0 => 2,
253 1 => 5,
254 2 => 6,
255 3 => 6,
256 4 => 4,
257 5 => 1
258 );
259 var $noCVS=0; // Tried to set it to 1, but then the CVS dir was removed and check in didn't work - there was an error. So now we try to accept that CVS dirs come along with the extension... Maybe it's not a problem at all.
260
261 var $fe_user=array(
262 'username' => '',
263 'password' => '',
264 'uploadPass' => '',
265 );
266
267 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()';
268 var $editTextExtensions = 'html,htm,txt,css,tmpl,inc,php,sql,conf,cnf,pl,pm,sh';
269 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';
270
271 /**
272 * Standard init function of a module.
273 *
274 * @return [type] ...
275 */
276 function init() {
277 global $BE_USER,$LANG,$BACK_PATH,$TCA_DESCR,$TCA,$HTTP_GET_VARS,$HTTP_POST_VARS,$CLIENT,$TYPO3_CONF_VARS;
278
279 #sleep(10);
280
281 $this->typePaths = Array (
282 'S' => TYPO3_mainDir.'sysext/',
283 'G' => TYPO3_mainDir.'ext/',
284 'L' => 'typo3conf/ext/'
285 );
286 $this->typeBackPaths = Array (
287 "S" => "../../../",
288 "G" => "../../../",
289 "L" => "../../../../".TYPO3_mainDir
290 );
291
292
293 $this->MCONF = $GLOBALS["MCONF"];
294 $this->CMD=t3lib_div::GPvar("CMD",1);
295 $this->menuConfig();
296 $this->gzcompress = function_exists('gzcompress');
297 if ($TYPO3_CONF_VARS["EXT"]["em_devVerUpdate"]) $this->versionDiffFactor=1;
298 if ($TYPO3_CONF_VARS["EXT"]["em_systemInstall"]) $this->systemInstall=1;
299 $this->repositoryUrl = $TYPO3_CONF_VARS["EXT"]["em_TERurls"][0];
300
301 $this->requiredExt = t3lib_div::trimExplode(",",$TYPO3_CONF_VARS["EXT"]["requiredExt"],1);
302
303 $this->doc = t3lib_div::makeInstance("noDoc");
304 $this->doc->backPath = $BACK_PATH;
305 // JavaScript
306 $this->doc->JScode = '
307 <script language="javascript" type="text/javascript">
308 script_ended = 0;
309 function jumpToUrl(URL) {
310 document.location = URL;
311 }
312 </script>
313 ';
314
315 $this->doc->form = '<form action="" method="post" name="pageform">';
316
317 // Descriptions:
318 $this->descrTable = "_MOD_".$this->MCONF["name"];
319 if ($BE_USER->uc["edit_showFieldHelp"]) {
320 $LANG->loadSingleTableDescription($this->descrTable);
321 }
322
323 $this->fe_user["username"] = $this->MOD_SETTINGS["fe_u"];
324 $this->fe_user["password"] = $this->MOD_SETTINGS["fe_p"];
325 $this->fe_user["uploadPass"] = $this->MOD_SETTINGS["fe_up"];
326 }
327
328 /**
329 * Configuration of which mod-menu items can be used
330 *
331 * @return [type] ...
332 */
333 function menuConfig() {
334 global $BE_USER,$LANG,$BACK_PATH,$TCA_DESCR,$TCA,$HTTP_GET_VARS,$HTTP_POST_VARS,$CLIENT,$TYPO3_CONF_VARS;
335
336 // MENU-ITEMS:
337 // If array, then it's a selector box menu
338 // If empty string it's just a variable, that'll be saved.
339 // Values NOT in this array will not be saved in the settings-array for the module.
340 $this->MOD_MENU = array(
341 "function" => array(
342 0 => 'Loaded extensions',
343 1 => 'Available extensions to install',
344 2 => 'Import extensions from online repository',
345 4 => 'Make new extension',
346 3 => 'Settings',
347 ),
348 "listOrder" => array(
349 "cat" => 'Category',
350 "author_company" => 'Author',
351 "state" => 'State',
352 "private" => 'Private',
353 "type" => 'Type',
354 "dep" => 'Dependencies',
355 ),
356 "display_details" => array(
357 1 => 'Details',
358 0 => 'Description',
359 2 => 'More details',
360
361 3 => 'Technical (takes time!)',
362 4 => 'Validating (takes time!)',
363 5 => 'Changed? (takes time!)',
364 ),
365 "display_shy" => "",
366 "own_member_only" => "",
367 "singleDetails" => array(
368 "info" => "Information",
369 "edit" => "Edit files",
370 "backup" => "Backup/Delete",
371 "dump" => "Dump DB",
372 "upload" => "Upload",
373 "updateModule" => "UPDATE!",
374 # "download" => "Download",
375 ),
376 "fe_u" => "",
377 "fe_p" => "",
378 "fe_up" => "",
379 );
380
381 // page/be_user TSconfig settings and blinding of menu-items
382 if (!$BE_USER->getTSConfigVal("mod.".$this->MCONF["name"].".allowTVlisting")) {
383 unset($this->MOD_MENU["display_details"][3]);
384 unset($this->MOD_MENU["display_details"][4]);
385 unset($this->MOD_MENU["display_details"][5]);
386 }
387 // Remove kickstarter if extension is not loaded:
388 if (!t3lib_extMgm::isLoaded("extrep_wizard")) {
389 unset($this->MOD_MENU["function"][4]);
390 }
391
392 // CLEANSE SETTINGS
393 $this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::GPvar("SET",1), $this->MCONF["name"]);
394 if ($this->MOD_SETTINGS["function"]==2) {
395 // If listing from online repository, certain items are removed though:
396 unset($this->MOD_MENU["listOrder"]["type"]);
397 unset($this->MOD_MENU["listOrder"]["private"]);
398 unset($this->MOD_MENU["display_details"][3]);
399 unset($this->MOD_MENU["display_details"][4]);
400 unset($this->MOD_MENU["display_details"][5]);
401 $this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::GPvar("SET",1), $this->MCONF["name"]);
402 }
403 }
404
405 /**
406 * Main function.
407 *
408 * @return [type] ...
409 */
410 function main() {
411 global $BE_USER,$LANG,$BACK_PATH,$TCA_DESCR,$TCA,$HTTP_GET_VARS,$HTTP_POST_VARS,$CLIENT,$TYPO3_CONF_VARS;
412
413 $this->content.=$this->doc->startPage('Extension Manager');
414 $this->content.=$this->doc->header('Extension Manager');
415 $this->content.=$this->doc->spacer(5);
416
417 if ($this->CMD['showExt']) {
418 // Show details for a single extension
419 $this->showExtDetails($this->CMD['showExt']);
420 } elseif ($this->CMD['importExt'] || $this->CMD['uploadExt']) {
421 // Imports and extension from online rep.
422 $err = $this->importExtFromRep($this->CMD['importExt'],$this->CMD['loc'],$this->CMD['uploadExt'],'',$this->CMD['transl'],$this->CMD['inc_manual']);
423 if ($err) {
424 $this->content.=$this->doc->section('',$GLOBALS['TBE_TEMPLATE']->rfw($err));
425 }
426 } elseif ($this->CMD['importExtInfo']) {
427 // Gets detailed information of an extension from online rep.
428 $this->importExtInfo($this->CMD['importExtInfo']);
429 } else {
430 $menu = $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.menu').' '.
431 t3lib_BEfunc::getFuncMenu(0,'SET[function]',$this->MOD_SETTINGS['function'],$this->MOD_MENU['function']);
432
433 if (t3lib_div::inList('0,1,2',$this->MOD_SETTINGS['function'])) {
434 $menu.='&nbsp;Order by:&nbsp;'.t3lib_BEfunc::getFuncMenu(0,'SET[listOrder]',$this->MOD_SETTINGS['listOrder'],$this->MOD_MENU['listOrder']).
435 '&nbsp;&nbsp;Show:&nbsp;'.t3lib_BEfunc::getFuncMenu(0,'SET[display_details]',$this->MOD_SETTINGS['display_details'],$this->MOD_MENU['display_details']).
436 '<br />Display shy extensions:&nbsp;&nbsp;'.t3lib_BEfunc::getFuncCheck(0,'SET[display_shy]',$this->MOD_SETTINGS['display_shy']);
437 }
438
439 if ($this->MOD_SETTINGS['function']==2) {
440 $menu.='&nbsp;&nbsp;&nbsp;Get own/member/selected extensions only:&nbsp;&nbsp;'.t3lib_BEfunc::getFuncCheck(0,'SET[own_member_only]',$this->MOD_SETTINGS['own_member_only']);
441 }
442
443 $this->content.=$this->doc->section('','<span class="nobr">'.$menu.'</span>');
444 $this->content.=$this->doc->spacer(10);
445
446 switch($this->MOD_SETTINGS['function']) {
447 case 0:
448 // Lists loaded (installed) extensions
449 $this->extensionList_loaded();
450 break;
451 case 1:
452 // Lists the installed (available) extensions
453 $this->extensionList_installed();
454 break;
455 case 2:
456 // Lists the extensions available from online rep.
457 $this->extensionList_import();
458 break;
459 case 3:
460 // Lists the extensions available from online rep.
461 $this->alterSettings();
462 break;
463 case 4:
464 $this->kickstarter();
465 break;
466 }
467 }
468
469 //debug($GLOBALS['HTTP_GET_VARS']);
470
471 if ($BE_USER->mayMakeShortcut()) {
472 $this->content.=$this->doc->spacer(20).$this->doc->section('',$this->doc->makeShortcutIcon('','function',$this->MCONF['name']));
473 }
474 }
475
476 /**
477 * Print module content. Called as last thing in the global scope.
478 *
479 * @return [type] ...
480 */
481 function printContent() {
482 global $SOBE;
483
484 $this->content.=$this->doc->endPage();
485 echo $this->content;
486 }
487
488
489 /**
490 * Making of new extensions.
491 *
492 * @return [type] ...
493 */
494 function kickstarter() {
495 $kickstarter = t3lib_div::makeInstance('em_kickstarter');
496 $kickstarter->getPIdata();
497 $kickstarter->color = array($this->doc->bgColor5,$this->doc->bgColor4,$this->doc->bgColor);
498 $kickstarter->siteBackPath = $this->doc->backPath.'../';
499 $kickstarter->pObj = &$this;
500 $kickstarter->EMmode=1;
501
502 $content = $kickstarter->mgm_wizard();
503 $this->content.='</form>'.$this->doc->section('Kickstarter wizard',$content,0,1).'<form>';
504 }
505
506 /**
507 * Allows changing of settings
508 *
509 * @return [type] ...
510 */
511 function alterSettings() {
512 $content = '
513 <table border=0 cellpadding=2 cellspacing=2>
514 <tr class="bgColor4"><td>Enter repository username:</td><td><input type="text" name="SET[fe_u]" value="'.htmlspecialchars($this->MOD_SETTINGS['fe_u']).'"></td></tr>
515 <tr class="bgColor4"><td>Enter repository password:</td><td><input type="password" name="SET[fe_p]" value="'.htmlspecialchars($this->MOD_SETTINGS['fe_p']).'"></td></tr>
516 <tr class="bgColor4"><td>Enter default upload password:</td><td><input type="password" name="SET[fe_up]" value="'.htmlspecialchars($this->MOD_SETTINGS['fe_up']).'"></td></tr>
517 </table>
518 <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 />
519 <br />
520 <input type="submit" value="Update">
521 ';
522
523 $this->content.=$this->doc->section('Repository settings',$content,0,1);
524 }
525
526 /**
527 * Listing of loaded (installed) extensions
528 *
529 * @return [type] ...
530 */
531 function extensionList_loaded() {
532 global $TYPO3_LOADED_EXT;
533 list($list,$cat)=$this->getInstalledExtensions();
534
535 // Loaded extensions
536 $content='';
537 $lines=array();
538 $lines[]=$this->extensionListRowHeader(' class="bgColor5"',array('<td><img src=clear.gif width=1 height=1></td>'));
539
540 reset($TYPO3_LOADED_EXT);
541 while(list($eKey,$eConf)=each($TYPO3_LOADED_EXT)) {
542 if (strcmp($eKey,'_CACHEFILE')) {
543 if ($this->MOD_SETTINGS['display_shy'] || !$list[$eKey]['EM_CONF']['shy']) {
544 if (in_array($eKey,$this->requiredExt)) {
545 $loadUnloadLink='<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('Rq').'</strong>';
546 } else {
547 $loadUnloadLink='<a href="index.php?CMD[showExt]='.$eKey.'&CMD[remove]=1">'.$this->removeButton().'</a>';
548 }
549
550 $lines[]=$this->extensionListRow($eKey,$eConf,$list[$eKey],array('<td valign=top class="bgColor">'.$loadUnloadLink.'</td>'));
551 }
552 }
553 }
554
555 $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 />';
556 $content.= '<table border=0 cellpadding=2 cellspacing=1>'.implode('',$lines).'</table>';
557
558 $this->content.=$this->doc->section('Loaded Extensions',$content,0,1);
559 $this->addClearCacheFiles();
560 }
561
562 /**
563 * Listing remote extensions from online repository
564 *
565 * @return [type] ...
566 */
567 function extensionList_import() {
568 global $TYPO3_LOADED_EXT;
569
570 $listRemote = t3lib_div::GPvar('ter_connect');
571
572 if ($listRemote) {
573 list($inst_list,$inst_cat)=$this->getInstalledExtensions();
574 $this->inst_keys=array_flip(array_keys($inst_list));
575
576 $this->detailCols[1]+=6;
577
578 $repositoryUrl=$this->repositoryUrl.
579 $this->repTransferParams().
580 '&tx_extrep[cmd]=currentListing'.
581 ($this->MOD_SETTINGS['own_member_only']?'&tx_extrep[listmode]=1':'');
582 $fetchData = $this->fetchServerData($repositoryUrl);
583 //debug($fetchData);
584 if (is_array($fetchData)) {
585 $listArr=$fetchData[0];
586 list($list,$cat) = $this->getImportExtList($listArr);
587
588 // Available extensions
589 if (is_array($cat[$this->MOD_SETTINGS['listOrder']])) {
590 $content='';
591 $lines=array();
592 $lines[]=$this->extensionListRowHeader(' class="bgColor5"',array('<td><img src=clear.gif width=18 height=1></td>'),1);
593
594 reset($cat[$this->MOD_SETTINGS['listOrder']]);
595 while(list($catName,$extEkeys)=each($cat[$this->MOD_SETTINGS['listOrder']])) {
596 $lines[]='<tr><td colspan='.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'><br /></td></tr>';
597 $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>';
598
599 asort($extEkeys);
600 reset($extEkeys);
601 while(list($eKey)=each($extEkeys)) {
602 if ($this->MOD_SETTINGS["display_shy"] || !$list[$eKey]["EM_CONF"]["shy"]) {
603 $loadUnloadLink="";
604 if ($inst_list[$eKey]["type"]!="S" && (!isset($inst_list[$eKey]) || $this->versionDifference($list[$eKey]["EM_CONF"]["version"],$inst_list[$eKey]["EM_CONF"]["version"],$this->versionDiffFactor))) {
605 if (isset($inst_list[$eKey])) {
606 // update
607 $loc=($inst_list[$eKey]["type"]=="G"?"G":"L");
608 $loadUnloadLink.='<a href="index.php?CMD[importExt]='.$list[$eKey]["extRepUid"].'&CMD[loc]='.$loc.($this->getDocManual($eKey,$loc)?'&CMD[inc_manual]=1':'').'"><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>';
609 } else {
610 // import
611 $loadUnloadLink.='<a href="index.php?CMD[importExt]='.$list[$eKey]["extRepUid"].'&CMD[loc]=L'.($this->getDocManual($eKey)?'&CMD[inc_manual]=1':'').'"><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>';
612 }
613 } else $loadUnloadLink="&nbsp;";
614
615 if ($list[$eKey]["_MEMBERS_ONLY"]) {
616 $theBgColor = "#F6CA96";
617 } elseif (isset($inst_list[$eKey])) {
618 $theBgColor = t3lib_extMgm::isLoaded($eKey)?$this->doc->bgColor4:t3lib_div::modifyHTMLcolor($this->doc->bgColor4,20,20,20);
619 } else {
620 $theBgColor = t3lib_div::modifyHTMLcolor($this->doc->bgColor2,30,30,30);
621 }
622 $lines[]=$this->extensionListRow($eKey,array(),$list[$eKey],array('<td valign=top class="bgColor">'.$loadUnloadLink.'</td>'),
623 $theBgColor,$inst_list,1,'index.php?CMD[importExtInfo]='.$list[$eKey]["extRepUid"]);
624 }
625 }
626 }
627
628 $content.= 'Extensions in this list are online for immediate download from the TYPO3 Extension Repository.<br />
629 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 />
630 So if you want to use an extension from the repository, you should simply click the "import" button.<br /><br />';
631
632 $content.= '<table border=0 cellpadding=2 cellspacing=1>'.implode("",$lines).'</table>';
633
634 $content.= '<br />Data fetched: ['.implode("][",$fetchData[1]).']';
635 $content.= '<br /><br /><strong>PRIVACY NOTICE:</strong><br /> '.$this->privacyNotice;
636
637 $this->content.=$this->doc->section("Extensions in TYPO3 Extension Repository (online) - Order by: ".$this->MOD_MENU["listOrder"][$this->MOD_SETTINGS["listOrder"]],$content,0,1);
638
639 if (!$this->MOD_SETTINGS["own_member_only"]) {
640 // Plugins which are NOT uploaded to repository but present on this server.
641 $content="";
642 $lines=array();
643 if (count($this->inst_keys)) {
644 $lines[]=$this->extensionListRowHeader(' class="bgColor5"',array('<td><img src=clear.gif width=18 height=1></td>'));
645
646 reset($this->inst_keys);
647 while(list($eKey)=each($this->inst_keys)) {
648 if ($this->MOD_SETTINGS["display_shy"] || !$inst_list[$eKey]["EM_CONF"]["shy"]) {
649 $eConf = $TYPO3_LOADED_EXT[$eKey];
650 $loadUnloadLink = t3lib_extMgm::isLoaded($eKey)?
651 '<a href="index.php?CMD[showExt]='.$eKey.'&CMD[remove]=1&CMD[clrCmd]=1&SET[singleDetails]=info">'.$this->removeButton().'</a>':
652 '<a href="index.php?CMD[showExt]='.$eKey.'&CMD[load]=1&CMD[clrCmd]=1&SET[singleDetails]=info">'.$this->installButton().'</a>';
653 if (in_array($eKey,$this->requiredExt)) $loadUnloadLink="<strong>".$GLOBALS["TBE_TEMPLATE"]->rfw("Rq")."</strong>";
654 $lines[]=$this->extensionListRow($eKey,$eConf,$inst_list[$eKey],array('<td valign=top class="bgColor">'.$loadUnloadLink.'</td>'),
655 t3lib_extMgm::isLoaded($eKey)?$this->doc->bgColor4:t3lib_div::modifyHTMLcolor($this->doc->bgColor4,20,20,20));
656 }
657 }
658 }
659
660 $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 />';
661 $content.= '<table border=0 cellpadding=2 cellspacing=1>'.implode("",$lines).'</table>';
662 $this->content.=$this->doc->spacer(20);
663 $this->content.=$this->doc->section("Extensions found only on this server",$content,0,1);
664 }
665 }
666 }
667 } else {
668 $content = 'Click here to connect to "'.$this->repositoryUrl.'" and retrieve the list of publicly available plugins from the TYPO3 Extension Repository.<br />';
669
670 if ($this->fe_user["username"]) {
671 $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 />';
672 } else {
673 $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 />';
674 }
675
676 $onCLick = "document.location='index.php?ter_connect=1';return false;";
677 $content.= '<br /><input type="submit" value="Connect to online repository" onClick="'.$onCLick.'">';
678 # $content.= '<br /><br /><strong>PRIVACY NOTICE:</strong><br /> '.$this->privacyNotice;
679 $this->content.=$this->doc->section("Extensions in TYPO3 Extension Repository",$content,0,1);
680 }
681
682 // Private lookup:
683 $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="document.location=\'index.php?CMD[importExtInfo]=\'+document.pageform.uid_private_key.value+\'&CMD[download_password]=\'+document.pageform.download_password.value; return false;">';
684 $this->content.=$this->doc->spacer(20);
685 $this->content.=$this->doc->section("Private extension lookup:",$content,0,1);
686
687 // Upload:
688 if ($this->importAtAll()) {
689 $content= '</form><form action="index.php" enctype="'.$GLOBALS["TYPO3_CONF_VARS"]["SYS"]["form_enctype"].'" method="post">
690 Upload extension file (.t3x):<br />
691 <input type="file" size="60" name="upload_ext_file"><br />
692 ... in location:<br />
693 <select name="CMD[loc]">';
694 if ($this->importAsType("L")) $content.='<option value="L">Local (../typo3conf/ext/)</option>';
695 if ($this->importAsType("G")) $content.='<option value="G">Global (typo3/ext/)</option>';
696 if ($this->importAsType("S")) $content.='<option value="S">System (typo3/sysext/)</option>';
697 $content.='</select><br />
698 <input type="checkbox" value="1" name="CMD[uploadOverwrite]"> Overwrite any existing extension!<br />
699 <input type="submit" name="CMD[uploadExt]" value="Upload extension file"><br />
700 ';
701 if (!$this->gzcompress) {
702 $content.='<br />'.$GLOBALS["TBE_TEMPLATE"]->rfw("NOTE: No decompression available! Don't upload a compressed extension - it will not succeed.");
703 }
704 } else $content=$this->noImportMsg();
705
706 $this->content.=$this->doc->spacer(20);
707 $this->content.=$this->doc->section("Upload extension file directly (.t3x):",$content,0,1);
708
709 // Clear cache thing...
710 $this->addClearCacheFiles();
711 }
712
713 /**
714 * Listing of available (installed) extensions
715 *
716 * @return [type] ...
717 */
718 function extensionList_installed() {
719 global $TYPO3_LOADED_EXT;
720 list($list,$cat)=$this->getInstalledExtensions();
721 #debug(strlen(serialize(array($list,$cat))));
722 #debug(array($list,$cat));
723
724 // Available extensions
725 if (is_array($cat[$this->MOD_SETTINGS["listOrder"]])) {
726 $content="";
727 $lines=array();
728 $lines[]=$this->extensionListRowHeader(' class="bgColor5"',array('<td><img src=clear.gif width=18 height=1></td>'));
729
730 $allKeys=array();
731 reset($cat[$this->MOD_SETTINGS["listOrder"]]);
732 while(list($catName,$extEkeys)=each($cat[$this->MOD_SETTINGS["listOrder"]])) {
733 $allKeys[]="";
734 $allKeys[]="TYPE: ".$catName;
735
736 $lines[]='<tr><td colspan='.(3+$this->detailCols[$this->MOD_SETTINGS["display_details"]]).'><br /></td></tr>';
737 $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>';
738
739 asort($extEkeys);
740 reset($extEkeys);
741 while(list($eKey)=each($extEkeys)) {
742 $allKeys[]=$eKey;
743 if ($this->MOD_SETTINGS["display_shy"] || !$list[$eKey]["EM_CONF"]["shy"]) {
744 $eConf = $TYPO3_LOADED_EXT[$eKey];
745 $loadUnloadLink = t3lib_extMgm::isLoaded($eKey)?
746 '<a href="index.php?CMD[showExt]='.$eKey.'&CMD[remove]=1&CMD[clrCmd]=1&SET[singleDetails]=info">'.$this->removeButton().'</a>':
747 '<a href="index.php?CMD[showExt]='.$eKey.'&CMD[load]=1&CMD[clrCmd]=1&SET[singleDetails]=info">'.$this->installButton().'</a>';
748 if (in_array($eKey,$this->requiredExt)) $loadUnloadLink="<strong>".$GLOBALS["TBE_TEMPLATE"]->rfw("Rq")."</strong>";
749
750 if ($list[$eKey]["EM_CONF"]["private"]) {
751 $theBgColor = "#F6CA96";
752 } else {
753 $theBgColor = t3lib_extMgm::isLoaded($eKey)?$this->doc->bgColor4:t3lib_div::modifyHTMLcolor($this->doc->bgColor4,20,20,20);
754 }
755 $lines[]=$this->extensionListRow($eKey,$eConf,$list[$eKey],array('<td valign=top class="bgColor">'.$loadUnloadLink.'</td>'),
756 $theBgColor);
757 }
758 }
759 }
760
761 $content.='
762
763
764 <!--
765 EXTENSION KEYS:
766
767
768 '.trim(implode(chr(10),$allKeys)).'
769
770 -->
771
772
773
774
775 ';
776
777 #debug($this->MOD_SETTINGS["listOrder"]);
778 $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 />
779 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 />
780 So if you want to use an extension in TYPO3, you should simply click the "plus" button '.$this->installButton().' . <br />
781 Installed extensions can also be removed again - just click the remove button '.$this->removeButton().' .<br /><br />';
782 $content.= '<table border=0 cellpadding=2 cellspacing=1>'.implode("",$lines).'</table>';
783
784 $this->content.=$this->doc->section("Available Extensions - Order by: ".$this->MOD_MENU["listOrder"][$this->MOD_SETTINGS["listOrder"]],$content,0,1);
785 $this->addClearCacheFiles();
786 }
787 }
788
789 /**
790 * Returns detailed info about an extension in the online repository
791 *
792 * @param [type] $extRepUid: ...
793 * @return [type] ...
794 */
795 function importExtInfo($extRepUid) {
796 $uidParts = t3lib_div::trimExplode("-",$extRepUid);
797 if (count($uidParts)==2) {
798 $extRepUid=$uidParts[0];
799 $addParams="&tx_extrep[pKey]=".rawurlencode(trim($uidParts[1]))
800 ."&tx_extrep[pPass]=".rawurlencode(trim($this->CMD["download_password"]));
801 $addImportParams = "&CMD[download_password]=".rawurlencode(trim($this->CMD["download_password"]));
802 } else $addParams="";
803
804 $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>';
805 $this->content.=$this->doc->section("",$content);
806 $content="";
807
808
809 $repositoryUrl=$this->repositoryUrl.
810 $this->repTransferParams().
811 $addParams.
812 "&tx_extrep[cmd]=extensionInfo".
813 "&tx_extrep[uid]=".$extRepUid;
814
815 list($fetchData) = $this->fetchServerData($repositoryUrl);
816 if (is_array($fetchData["_other_versions"])) {
817 $opt=array();
818 $opt[]='<option value=""></option>';
819 reset($fetchData["_other_versions"]);
820 $selectWasSet=0;
821 while(list(,$dat)=each($fetchData["_other_versions"])) {
822 $setSel = ($dat["uid"]==$extRepUid?" SELECTED":"");
823 if ($setSel) $selectWasSet=1;
824 $opt[]='<option value="'.$dat["uid"].'"'.$setSel.'>'.$dat["version"].'</option>';
825 }
826 if (!$selectWasSet && $fetchData["emconf_private"]) {
827 $opt[]='<option value="'.$fetchData["uid"].'-'.$fetchData["private_key"].'" SELECTED>'.$fetchData["version"].' (Private)</option>';
828 }
829
830 $select='<select name="repUid">'.implode("",$opt).'</select> <input type="submit" value="Load details" onClick="document.location=\'index.php?CMD[importExtInfo]=\'+document.pageform.repUid.options[document.pageform.repUid.selectedIndex].value; return false;"> or<br /><br />';
831 if ($this->importAtAll()) {
832 $select.='
833 <input type="submit" value="Import/Update" onClick="
834 document.location=\'index.php?CMD[importExt]=\'
835 +document.pageform.repUid.options[document.pageform.repUid.selectedIndex].value
836 +\'&CMD[loc]=\'+document.pageform.loc.options[document.pageform.loc.selectedIndex].value
837 +\'&CMD[transl]=\'+(document.pageform.transl.checked?1:0)
838 +\'&CMD[inc_manual]=\'+(document.pageform.inc_manual.checked?1:0)
839 +\''.$addImportParams.'\'; return false;"> to:
840 <select name="loc">'.
841 ($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>':'').
842 ($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>':'').
843 ($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>':'').
844 #'<option value="fileadmin">'.htmlspecialchars("TEST: fileadmin/_temp_/[extension key name + date]").'</option>'.
845 '</select>
846 <br /><input type="checkbox" name="transl" value="1">Include most recent translations
847 <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':'').'>Include "doc/manual.sxw", if any
848 ';
849 } else $select.=$this->noImportMsg();
850 $content.=$select;
851 $this->content.=$this->doc->section("Select command",$content,0,1);
852 }
853
854 // Details:
855 $extKey = $fetchData["extension_key"];
856 list($xList)=$this->getImportExtList(array($fetchData));
857 $eInfo=$xList[$extKey];
858 $eInfo["_TECH_INFO"]=unserialize($fetchData["techinfo"]);
859 $tempFiles=unserialize($fetchData["files"]);
860
861 if (is_array($tempFiles)) {
862 reset($tempFiles);
863 while(list($fk)=each($tempFiles)) {
864 if (!strstr($fk,"/")) $eInfo["files"][]=$fk;
865 }
866 }
867
868 $content='<strong>'.$fetchData["_ICON"]." &nbsp;".$eInfo["EM_CONF"]["title"].'</strong><br /><br />';
869 $content.=$this->extInformationArray($extKey,$eInfo,1);
870 $this->content.=$this->doc->spacer(10);
871 $this->content.=$this->doc->section("Remote Extension Details:",$content,0,1);
872
873 if (is_array($fetchData["_MESSAGES"])) {
874 # $content = t3lib_div::view_array($fetchData["_MESSAGES"]);
875 $content = implode("<HR>",$fetchData["_MESSAGES"]);
876 $this->content.=$this->doc->section("Messages from repository server:",$content,0,1,1);
877 }
878 }
879
880 /**
881 * Returns true if the doc/manual.sxw should be returned
882 *
883 * @param [type] $extension_key: ...
884 * @param [type] $loc: ...
885 * @return [type] ...
886 */
887 function getDocManual($extension_key,$loc="") {
888 $res=0;
889 if ($GLOBALS["TYPO3_CONF_VARS"]["EXT"]["em_alwaysGetOOManual"]) $res=1;
890 if ($loc && $this->typePaths[$loc] && @is_file(PATH_site.$this->typePaths[$loc].$extension_key."/doc/manual.sxw")) $res=1;
891
892 # debug(array($extension_key,$loc,$res));
893 return $res;
894 }
895
896 /**
897 * Imports an extensions from the online repository
898 *
899 * @param [type] $extRepUid: ...
900 * @param [type] $loc: ...
901 * @param [type] $uploadFlag: ...
902 * @param [type] $directInput: ...
903 * @param [type] $recentTranslations: ...
904 * @param [type] $incManual: ...
905 * @return [type] ...
906 */
907 function importExtFromRep($extRepUid,$loc,$uploadFlag=0,$directInput="",$recentTranslations=0,$incManual=0) {
908 if (is_array($directInput)) {
909 $fetchData=array($directInput,"");
910 $loc = !strcmp($loc,"G")?"G":"L";
911 } elseif ($uploadFlag) {
912 if ($GLOBALS["HTTP_POST_FILES"]["upload_ext_file"]["tmp_name"]) {
913
914 $uploadedTempFile = t3lib_div::upload_to_tempfile($GLOBALS["HTTP_POST_FILES"]["upload_ext_file"]["tmp_name"]);
915 $fileContent = t3lib_div::getUrl($uploadedTempFile);
916 t3lib_div::upload_unlink_tempfile($uploadedTempFile);
917
918 $fetchData=array($this->decodeExchangeData($fileContent),"");
919
920 if (is_array($fetchData)) {
921 $extKey = $fetchData[0]["extKey"];
922 if ($extKey) {
923 if (!$this->CMD["uploadOverwrite"]) {
924 $loc = !strcmp($loc,"G")?"G":"L";
925 $comingExtPath = PATH_site.$this->typePaths[$loc].$extKey."/";
926 if (@is_dir($comingExtPath)) {
927 # debug("!");
928 return "Extension was already present in '".$comingExtPath."' - and the overwrite flag was not set! So nothing done...";
929 } // ... else go on, install...
930 } // ... else go on, install...
931 } else return "No extension key in file. Strange...";
932 } else return "Wrong file format. No data recognized.";
933 } else return "No file uploaded! Probably the file was too large for PHPs internal limit for uploadable files.";
934 } else {
935 $uidParts = t3lib_div::trimExplode("-",$extRepUid);
936 if (count($uidParts)==2) {
937 $extRepUid=$uidParts[0];
938 $addParams="&tx_extrep[pKey]=".rawurlencode(trim($uidParts[1]))
939 ."&tx_extrep[pPass]=".rawurlencode(trim($this->CMD["download_password"]));
940 } else $addParams="";
941
942 // If most recent translation should be delivered, send this:
943 if ($recentTranslations) {
944 $addParams.="&tx_extrep[transl]=1";
945 }
946
947 // If manual should be included, send this:
948 if ($incManual) {
949 $addParams.="&tx_extrep[inc_manual]=1";
950 }
951
952
953
954 $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>';
955 $this->content.=$this->doc->section("",$content);
956 $content="";
957
958 $repositoryUrl=$this->repositoryUrl.
959 $this->repTransferParams().
960 $addParams.
961 "&tx_extrep[cmd]=importExtension".
962 "&tx_extrep[uid]=".$extRepUid;
963
964 $fetchData = $this->fetchServerData($repositoryUrl);
965 }
966
967
968 if ($this->importAsType($loc)) {
969 if (is_array($fetchData)) { // There was some data successfully transferred
970 if ($fetchData[0]["extKey"] && is_array($fetchData[0]["FILES"])) {
971 $extKey = $fetchData[0]["extKey"];
972 $EM_CONF=$fetchData[0]["EM_CONF"];
973 if (!$EM_CONF["lockType"] || !strcmp($EM_CONF["lockType"],$loc)) {
974 $res = $this->clearAndMakeExtensionDir($fetchData[0],$loc);
975 if (is_array($res)) {
976 $extDirPath = $res[0];
977 if ($extDirPath && @is_dir($extDirPath) && substr($extDirPath,-1)=="/") {
978
979 $emConfFile = $this->construct_ext_emconf_file($extKey,$EM_CONF);
980 $dirs = $this->extractDirsFromFileList(array_keys($fetchData[0]["FILES"]));
981
982 $res=$this->createDirsInPath($dirs,$extDirPath);
983 if (!$res) {
984 $writeFiles = $fetchData[0]["FILES"];
985 $writeFiles["ext_emconf.php"]["content"] = $emConfFile;
986 $writeFiles["ext_emconf.php"]["content_md5"] = md5($emConfFile);
987
988 while(list($theFile,$fileData)=each($writeFiles)) {
989 t3lib_div::writeFile($extDirPath.$theFile,$fileData["content"]);
990 if (!@is_file($extDirPath.$theFile)) {
991 $content.="Error: File '".$extDirPath.$theFile."' could not be created!!!<br />";
992 } elseif (md5(t3lib_div::getUrl($extDirPath.$theFile)) != $fileData["content_md5"]) {
993 $content.="Error: File '".$extDirPath.$theFile."' MD5 was different from the original files MD5 - so the file is corrupted!<br />";
994 } elseif (TYPO3_OS!="WIN") {
995 #debug($extDirPath.$theFile,1);
996 chmod ($extDirPath.$theFile, 0755);
997 }
998 }
999 if (!$content) {
1000 $content="SUCCESS: ".$extDirPath."<br />";
1001
1002 // Fix TYPO3_MOD_PATH
1003 $modules = t3lib_div::trimExplode(",",$EM_CONF["module"],1);
1004 if (count($modules)) {
1005 reset($modules);
1006 while(list(,$mD)=each($modules)) {
1007 $confFileName = $extDirPath.$mD."/conf.php";
1008 if (@is_file($confFileName)) {
1009 $content.= $this->writeTYPO3_MOD_PATH($confFileName,$loc,$extKey."/".$mD."/")."<br />";
1010 } else $content.="Error: Couldn't find '".$confFileName."'"."<br />";
1011 }
1012 }
1013 // 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.
1014 // But this order of the code works.... (using the empty Array with type, EMCONF and files hereunder).
1015
1016
1017 // Writing to ext_emconf.php:
1018 $sEMD5A = $this->serverExtensionMD5Array($extKey,array(
1019 "type" => $loc,
1020 "EM_CONF" => array(),
1021 "files" => array()
1022 ));
1023 $EM_CONF["_md5_values_when_last_written"] = serialize($sEMD5A);
1024 $emConfFile = $this->construct_ext_emconf_file($extKey,$EM_CONF);
1025 t3lib_div::writeFile($extDirPath."ext_emconf.php",$emConfFile);
1026
1027 $content.="ext_emconf.php: ".$extDirPath."ext_emconf.php<br />";
1028 $content.="Type: ".$loc."<br />";
1029 if (t3lib_extMgm::isLoaded($extKey)) {
1030 if ($this->removeCacheFiles()) {
1031 $content.="Cache-files are removed and will be re-written upon next hit<br />";
1032 }
1033
1034 list($new_list)=$this->getInstalledExtensions();
1035 $content.=$this->updatesForm($extKey,$new_list[$extKey],1,"index.php?CMD[showExt]=".$extKey."&SET[singleDetails]=info");
1036 }
1037
1038 if (is_array($fetchData[0]["_MESSAGES"])) {
1039 $content.="<HR><strong>Messages from repository:</strong><br /><br />".implode("<br />",$fetchData[0]["_MESSAGES"]);
1040 }
1041 }
1042 } else $content=$res;
1043 } else $content = "Error: The extension path '".$extDirPath."' was different than expected...";
1044 } else $content=$res;
1045 } else $content = "Error: The extension can only be installed in the path ".$this->typePaths[$EM_CONF["lockType"]]." (lockType=".$EM_CONF["lockType"].")";
1046 } else $content="Error: No extension key!!! Why? - nobody knows... (Or no files in the file-array...)";
1047 } else $content="Error: The datatransfer did not succeed...";
1048 } else $content="Error: Installation is not allowed in this path (".$this->typePaths[$loc].")";
1049
1050 $this->content.=$this->doc->section("Extension copied to server",$content,0,1);
1051 }
1052
1053 /**
1054 * Display extensions details.
1055 *
1056 * @param [type] $extKey: ...
1057 * @return [type] ...
1058 */
1059 function showExtDetails($extKey) {
1060 global $TYPO3_LOADED_EXT;
1061
1062 list($list,$cat)=$this->getInstalledExtensions();
1063 $absPath = $this->getExtPath($extKey,$list[$extKey]);
1064
1065 // Check updateModule:
1066 if (@is_file($absPath.'class.ext_update.php')) {
1067 require_once($absPath.'class.ext_update.php');
1068 $updateObj = new ext_update;
1069 if (!$updateObj->access()) {
1070 unset($this->MOD_MENU["singleDetails"]['updateModule']);
1071 }
1072 } else {
1073 unset($this->MOD_MENU["singleDetails"]['updateModule']);
1074 }
1075
1076 // Function menu here:
1077 $content='<table border=0 cellpadding=0 cellspacing=0 width="100%"><tr><td nowrap>Extension:&nbsp;<strong>'.$this->extensionTitleIconHeader($extKey,$list[$extKey],"absmiddle").'</strong> ('.$extKey.')</td><td align=right nowrap>'.
1078 t3lib_BEfunc::getFuncMenu(0,"SET[singleDetails]",$this->MOD_SETTINGS["singleDetails"],$this->MOD_MENU["singleDetails"],"","&CMD[showExt]=".$extKey)." &nbsp; &nbsp; ".
1079 '<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></tr></table>';
1080 $this->content.=$this->doc->section("",$content);
1081
1082 if ($list[$extKey]) {
1083 if (($this->CMD["remove"] || $this->CMD["load"]) && !in_array($extKey,$this->requiredExt)) {
1084 if (t3lib_extMgm::isLocalconfWritable()) {
1085 if ($this->CMD["remove"]) {
1086 $newExtList=$this->removeExtFromList($extKey,$list);
1087 } else {
1088 $newExtList=$this->addExtToList($extKey,$list);
1089 }
1090 if ($newExtList!=-1) {
1091 $updates="";
1092 if ($this->CMD["load"]) {
1093 $updates=$this->updatesForm($extKey,$list[$extKey],1,"",'<input type="hidden" name="_do_install" value="1"><input type="hidden" name="_clrCmd" value="'.$this->CMD["clrCmd"].'">');
1094 if ($updates) {
1095 $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;
1096 $this->content.=$this->doc->section("Installing ".$this->extensionTitleIconHeader($extKey,$list[$extKey]).strtoupper(": Database needs to be updated"),$updates,1,1,1,1);
1097 }
1098 # $updates.=$this->checkDBupdates($extKey,$list[$extKey]);
1099 # $updates.= $this->checkClearCache($extKey,$list[$extKey]);
1100 # $updates.= $this->checkUploadFolder($extKey,$list[$extKey]);
1101 /* if ($updates) {
1102 $updates='
1103 Before the extension can be installed the database needs to be updated with new tables or fields. Please select which operations to perform:
1104 </form><form action="'.t3lib_div::linkThisScript().'" method="post">'.$updates.'
1105 <br /><input type="submit" name="write" value="Update database and install extension">
1106 <input type="hidden" name="_do_install" value="1">
1107 ';
1108 $this->content.=$this->doc->section("Installing ".$this->extensionTitleIconHeader($extKey,$list[$extKey]).strtoupper(": Database needs to be updated"),$updates,1,1,1);
1109 }
1110 */ } elseif ($this->CMD["remove"]) {
1111 $updates.= $this->checkClearCache($extKey,$list[$extKey]);
1112 if ($updates) {
1113 $updates='
1114 </form><form action="'.t3lib_div::linkThisScript().'" method="post">'.$updates.'
1115 <br /><input type="submit" name="write" value="Remove extension">
1116 <input type="hidden" name="_do_install" value="1">
1117 <input type="hidden" name="_clrCmd" value="'.$this->CMD["clrCmd"].'">
1118 ';
1119 $this->content.=$this->doc->section("Installing ".$this->extensionTitleIconHeader($extKey,$list[$extKey]).strtoupper(": Database needs to be updated"),$updates,1,1,1,1);
1120 }
1121 }
1122 if (!$updates || t3lib_div::GPvar("_do_install")) {
1123 $this->writeNewExtensionList($newExtList);
1124
1125
1126 /*
1127 $content = $newExtList;
1128 $this->content.=$this->doc->section("Active status","
1129 <strong>Extension list is written to localconf.php!</strong><br />
1130 It may be necessary to reload TYPO3 depending on the change.<br />
1131
1132 <em>(".$content.")</em>",0,1);
1133 */
1134 if ($this->CMD["clrCmd"] || t3lib_div::GPvar("_clrCmd")) {
1135 $vA = array("CMD"=>"");
1136 } else {
1137 $vA = array("CMD"=>Array("showExt"=>$extKey));
1138 }
1139 header("Location: ".t3lib_div::linkThisScript($vA));
1140 }
1141 }
1142 } else {
1143 $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);
1144 }
1145 } elseif ($this->CMD["downloadFile"] && !in_array($extKey,$this->requiredExt)) {
1146 $dlFile = $this->CMD["downloadFile"];
1147 if (t3lib_div::isFirstPartOfStr($dlFile,PATH_site) && t3lib_div::isFirstPartOfStr($dlFile,$absPath) && @is_file($dlFile)) {
1148 $mimeType = "application/octet-stream";
1149 Header("Content-Type: ".$mimeType);
1150 Header("Content-Disposition: attachment; filename=".basename($dlFile));
1151 echo t3lib_div::getUrl($dlFile);
1152 exit;
1153 } else die("error....");
1154 } elseif ($this->CMD["editFile"] && !in_array($extKey,$this->requiredExt)) {
1155 $editFile = $this->CMD["editFile"];
1156 if (t3lib_div::isFirstPartOfStr($editFile,PATH_site) && t3lib_div::isFirstPartOfStr($editFile,$absPath)) { // Paranoia...
1157
1158 $fI=t3lib_div::split_fileref($editFile);
1159 if (@is_file($editFile) && t3lib_div::inList($this->editTextExtensions,$fI["fileext"])) {
1160 if (filesize($editFile)<($this->kbMax*1024)) {
1161 $outCode="";
1162 $info="";
1163 $submittedContent = t3lib_div::GPvar("edit",1);
1164 $saveFlag=0;
1165 if(isset($submittedContent["file"])) {
1166 $info.=$GLOBALS["TBE_TEMPLATE"]->rfw("<br /><strong>File saved.</strong>")."<br />";
1167 $oldFileContent = t3lib_div::getUrl($editFile);
1168 $info.='MD5: <b>'.md5(str_replace(chr(13),"",$oldFileContent)).'</b> (Previous File)<br />';
1169 if (!$GLOBALS["TYPO3_CONF_VARS"]["EXT"]["noEdit"]) {
1170 t3lib_div::writeFile($editFile,$submittedContent["file"]);
1171 $saveFlag=1;
1172 } else die("Saving disabled!!!");
1173 }
1174
1175 $fileContent = t3lib_div::getUrl($editFile);
1176 $numberOfRows = 35;
1177
1178 $outCode.='File: <b>'.substr($editFile,strlen($absPath)).'</b> ('.t3lib_div::formatSize(filesize($editFile)).')<br />';
1179 $info.='MD5: <b>'.md5(str_replace(chr(13),"",$fileContent)).'</b> (File)<br />';
1180 if($saveFlag) $info.='MD5: <b>'.md5(str_replace(chr(13),"",$submittedContent["file"])).'</b> (Saved)<br />';
1181 $outCode.='<textarea name="edit[file]" rows="'.$numberOfRows.'" wrap="off"'.$this->doc->formWidthText(48,"width:98%;height:70%","off").'>'.t3lib_div::formatForTextarea($fileContent).'</textarea>';
1182 $outCode.='<input type="Hidden" name="edit[filename]" value="'.$editFile.'">';
1183 $outCode.='<input type="Hidden" name="CMD[editFile]" value="'.htmlspecialchars($editFile).'">';
1184 $outCode.='<input type="Hidden" name="CMD[showExt]" value="'.$extKey.'">';
1185 $outCode.=$info;
1186 if (!$GLOBALS["TYPO3_CONF_VARS"]["EXT"]["noEdit"]) {
1187 $outCode.='<br /><input type="submit" name="save_file" value="Save file">';
1188 } else $outCode.=$GLOBALS["TBE_TEMPLATE"]->rfw('<br />[SAVING IS DISABLED - can be enabled by the TYPO3_CONF_VARS[EXT][noEdit]-flag] ');
1189 $outCode.='<input type="submit" name="cancel" value="Cancel" onClick="document.location=\'index.php?CMD[showExt]='.$extKey.'\';return false;">';
1190 $theOutput.=$this->doc->spacer(15);
1191 $theOutput.=$this->doc->section("Edit file:","",0,1);
1192 $theOutput.=$this->doc->sectionEnd().$outCode;
1193 $this->content.=$theOutput;
1194 } else {
1195 $theOutput.=$this->doc->spacer(15);
1196 $theOutput.=$this->doc->section('<font color=red>Filesize exceeded '.$this->kbMax.' Kbytes</font>','Files larger than '.$this->kbMax.' KBytes are not allowed to be edited.');
1197 }
1198 }
1199 } else die("Fatal Edit error: File '".$editFile."' was not inside the correct path of the TYPO3 Extension!");
1200 } else { // MAIN:
1201
1202 switch((string)$this->MOD_SETTINGS["singleDetails"]) {
1203 case "info":
1204 // Loaded / Not loaded:
1205 if (!in_array($extKey,$this->requiredExt)) {
1206 if ($TYPO3_LOADED_EXT[$extKey]) {
1207 $content = '<strong>The extension is installed (loaded and running)!</strong><br />'.
1208 '<a href="index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1">Click here to remove the extension: '.$this->removeButton().'</a>';
1209 } else {
1210 $content = 'The extension is <strong>not</strong> installed yet.<br />'.
1211 '<a href="index.php?CMD[showExt]='.$extKey.'&CMD[load]=1">Click here to install the extension: '.$this->installButton().'</a>';
1212 }
1213 } else {
1214 $content = 'This extension is entered in the TYPO3_CONF_VARS[SYS][requiredExt] list and is therefore always loaded.';
1215 }
1216 $this->content.=$this->doc->spacer(10);
1217 $this->content.=$this->doc->section("Active status:",$content,0,1);
1218
1219 if (t3lib_extMgm::isLoaded($extKey)) {
1220 $updates=$this->updatesForm($extKey,$list[$extKey]);
1221 if ($updates) {
1222 $this->content.=$this->doc->spacer(10);
1223 $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);
1224 }
1225 }
1226
1227 // Show details:
1228 $content = $this->extInformationArray($extKey,$list[$extKey]);
1229 $this->content.=$this->doc->spacer(10);
1230 $this->content.=$this->doc->section("Details:",$content,0,1);
1231
1232 // Config:
1233 if (@is_file($absPath."ext_conf_template.txt")) {
1234 $this->content.=$this->doc->spacer(10);
1235 $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);
1236 $this->tsStyleConfigForm($extKey,$list[$extKey]);
1237 }
1238 break;
1239 case "upload":
1240 $TER_CMD = t3lib_div::GPvar("TER_CMD",1);
1241 if (is_array($TER_CMD)) {
1242 $msg = $this->processRepositoryReturnData($TER_CMD);
1243 if ($msg) {
1244 $this->content.=$this->doc->section("Local update of EM_CONF",$msg,0,1,1);
1245 $this->content.=$this->doc->spacer(10);
1246 }
1247 // Must reload this, because EM_CONF information has been updated!
1248 list($list,$cat)=$this->getInstalledExtensions();
1249 }
1250
1251
1252 // Upload:
1253 if (substr($extKey,0,5)!="user_") {
1254 $content = $this->getRepositoryUploadForm($extKey,$list[$extKey]);
1255 $eC=0;
1256 } else {
1257 $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 />
1258 You are encouraged to register a unique extension key for all your TYPO3 extensions - even if the project is current not official.";
1259 $eC=2;
1260 }
1261 $this->content.=$this->doc->section("Upload extension to repository",$content,0,1,$eC);
1262 break;
1263 case "download":
1264 break;
1265 case "backup":
1266 $content = $this->extBackup($extKey,$list[$extKey]);
1267 $this->content.=$this->doc->section("Backup",$content,0,1);
1268
1269 $content = $this->extDelete($extKey,$list[$extKey]);
1270 $this->content.=$this->doc->section("Delete",$content,0,1);
1271
1272 $content = $this->extUpdateEMCONF($extKey,$list[$extKey]);
1273 $this->content.=$this->doc->section("Update EM_CONF",$content,0,1);
1274
1275 $content = $this->extMakeNewFromFramework($extKey,$list[$extKey]);
1276 if ($content) $this->content.=$this->doc->section("Make new extension",$content,0,1);
1277 break;
1278 case "dump":
1279 $this->extDumpTables($extKey,$list[$extKey]);
1280 break;
1281 case "edit":
1282 // Files:
1283 $content = $this->getFileListOfExtension($extKey,$list[$extKey]);
1284 $this->content.=$this->doc->section("Extension files",$content,0,1);
1285 break;
1286 case "updateModule":
1287 $this->content.=$this->doc->section("Update:",$updateObj->main(),0,1);
1288 break;
1289 }
1290 }
1291 }
1292 }
1293
1294 /**
1295 * [Describe function...]
1296 *
1297 * @param [type] $extKey: ...
1298 * @param [type] $info: ...
1299 * @param [type] $notSilent: ...
1300 * @param [type] $script: ...
1301 * @param [type] $addFields: ...
1302 * @return [type] ...
1303 */
1304 function updatesForm($extKey,$info,$notSilent=0,$script="",$addFields="") {
1305 $script = $script ? $script : t3lib_div::linkThisScript();
1306 $updates.=$this->checkDBupdates($extKey,$info);
1307 $uCache = $this->checkClearCache($extKey,$info);
1308 if ($notSilent) $updates.= $uCache;
1309 $updates.= $this->checkUploadFolder($extKey,$info);
1310
1311 $absPath = $this->getExtPath($extKey,$info);
1312 if ($notSilent && @is_file($absPath."ext_conf_template.txt")) {
1313 $cForm=$this->tsStyleConfigForm($extKey,$info,1,$script,$updates.$addFields."<br />");
1314 }
1315
1316 if ($updates || $cForm) {
1317 if ($cForm) {
1318 $updates = '</form>'.$cForm.'<form>';
1319 } else {
1320 $updates='</form><form action="'.$script.'" method="post">'.$updates.$addFields.'
1321 <br /><input type="submit" name="write" value="Make updates">
1322 ';
1323 }
1324 }
1325 return $updates;
1326 }
1327
1328 /**
1329 * Dumping static tables and table/fields structures...
1330 *
1331 * @param [type] $eKey: ...
1332 * @param [type] $info: ...
1333 * @return [type] ...
1334 */
1335 function extDumpTables($eKey,$info) {
1336 // Get dbInfo which holds the structure known from the tables.sql file
1337 $techInfo=$this->makeDetailedExtensionAnalysis($eKey,$info);
1338 $absPath = $this->getExtPath($eKey,$info);
1339
1340 #debug($techInfo);
1341 if (is_array($techInfo["static"])) {
1342 if ($this->CMD["writeSTATICdump"]) {
1343 $writeFile = $absPath."ext_tables_static+adt.sql";
1344 if (@is_file($writeFile)) {
1345 $dump_static = $this->dumpStaticTables(implode(",",$techInfo["static"]));
1346 t3lib_div::writeFile($writeFile,$dump_static);
1347 $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);
1348 }
1349 } else {
1350 $msg = "Dumping table content for static tables:<br />";
1351 $msg.= "<br />".implode("<br />",$techInfo["static"])."<br />";
1352
1353 // ... then feed that to this function which will make new CREATE statements of the same fields but based on the current database content.
1354 $this->content.=$this->doc->section("Static tables",$msg.'<HR><strong><a href="index.php?CMD[showExt]='.$eKey.'&CMD[writeSTATICdump]=1">Write current static table contents to ext_tables_static+adt.sql now!</a></strong>',0,1);
1355 $this->content.=$this->doc->spacer(20);
1356 }
1357 }
1358
1359 if (is_array($techInfo["dump_tf"])) {
1360 $dump_tf_array = $this->getTableAndFieldStructure($techInfo["dump_tf"]);
1361 $dump_tf = $this->dumpTableAndFieldStructure($dump_tf_array);
1362 if ($this->CMD["writeTFdump"]) {
1363 $writeFile = $absPath."ext_tables.sql";
1364 if (@is_file($writeFile)) {
1365 t3lib_div::writeFile($writeFile,$dump_tf);
1366 $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);
1367 }
1368 } else {
1369 $msg = "Dumping current database structure for:<br />";
1370 if (is_array($techInfo["tables"])) {
1371 $msg.= "<br /><strong>Tables:</strong><br />".implode("<br />",$techInfo["tables"])."<br />";
1372 }
1373 if (is_array($techInfo["fields"])) {
1374 $msg.= "<br /><strong>Solo-fields:</strong><br />".implode("<br />",$techInfo["fields"])."<br />";
1375 }
1376
1377 // ... then feed that to this function which will make new CREATE statements of the same fields but based on the current database content.
1378 $this->content.=$this->doc->section("Table and field structure required",$msg.'<HR><strong><a href="index.php?CMD[showExt]='.$eKey.'&CMD[writeTFdump]=1">Write this dump to ext_tables.sql now!</a></strong><HR>
1379 <pre>'.htmlspecialchars($dump_tf).'</pre>',0,1);
1380
1381
1382 $details = ' This dump is based on two factors:<br />
1383 <ul>
1384 <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>
1385 <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>
1386 </ul>
1387 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 />';
1388 $this->content.=$this->doc->section("",$details);
1389 }
1390 }
1391 }
1392
1393 /**
1394 * Delete extension...
1395 *
1396 * @param [type] $eKey: ...
1397 * @param [type] $info: ...
1398 * @return [type] ...
1399 */
1400 function extDelete($eKey,$info) {
1401 $absPath = $this->getExtPath($eKey,$info);
1402 if (t3lib_extMgm::isLoaded($eKey)) {
1403 return "This extension is currently installed (loaded and active) and so cannot be deleted!";
1404 } elseif (t3lib_div::inList("G,L",$info["type"])) {
1405 if ($this->CMD["doDelete"] && !strcmp($absPath,$this->CMD["absPath"])) {
1406 $res = $this->removeExtDirectory($absPath);
1407 @rmdir($absPath);
1408 if ($res) return "ERROR: Could not remove extension directory '".$absPath."'";
1409 return "Removed extension in path '".$absPath."'!";
1410 } else {
1411 $onClick="if (confirm('Are you sure you want to delete this extension from the server?')) {document.location='index.php?CMD[showExt]=".$eKey."&CMD[doDelete]=1&CMD[absPath]=".rawurlencode($absPath)."';}";
1412 $content.= '<a href="#" onClick="'.$onClick.' return false;"><strong>DELETE EXTENSION FROM SERVER</strong> (in the "'.$this->typeLabels[$info["type"]].'" location "'.substr($absPath,strlen(PATH_site)).'")!</a>';
1413 $content.= '<br /><br />(Maybe you should make a backup first, see above.)';
1414 return $content;
1415 }
1416 } else return "Extension is not a global or local extension and cannot be removed.";
1417 }
1418
1419 /**
1420 * Update extension EM_CONF...
1421 *
1422 * @param [type] $eKey: ...
1423 * @param [type] $info: ...
1424 * @return [type] ...
1425 */
1426 function extUpdateEMCONF($eKey,$info) {
1427 $absPath = $this->getExtPath($eKey,$info);
1428 if ($this->CMD["doUpdateEMCONF"]) {
1429 return $this->updateLocalEM_CONF($eKey,$info);
1430 } else {
1431 $onClick="if (confirm('Are you sure you want to update EM_CONF?')) {document.location='index.php?CMD[showExt]=".$eKey."&CMD[doUpdateEMCONF]=1';}";
1432 $content.= '<a href="#" onClick="'.$onClick.' return false;"><strong>Update extension EM_CONF file</strong> (in the "'.$this->typeLabels[$info["type"]].'" location "'.substr($absPath,strlen(PATH_site)).'")!</a>';
1433 $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 />
1434 Updating this file will first of all reset this registration.';
1435 return $content;
1436 }
1437 }
1438
1439 /**
1440 * make from framework
1441 *
1442 * @param [type] $eKey: ...
1443 * @param [type] $info: ...
1444 * @return [type] ...
1445 */
1446 function extMakeNewFromFramework($eKey,$info) {
1447 $absPath = $this->getExtPath($eKey,$info);
1448 if (isset($this->MOD_MENU["function"][4]) && @is_file($absPath."doc/wizard_form.dat")) {
1449 $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 />";
1450 $content.= '</form>
1451 <form action="index.php?SET[function]=4" method="post">
1452 <input type="submit" value="Start new">
1453 <input type="hidden" name="tx_extrep[wizArray_ser]" value="'.base64_encode(t3lib_div::getUrl($absPath."doc/wizard_form.dat")).'">
1454 </form>
1455 <form>';
1456 return $content;
1457 }
1458 }
1459
1460 /**
1461 * Makes Backup files
1462 *
1463 * @param [type] $eKey: ...
1464 * @param [type] $info: ...
1465 * @return [type] ...
1466 */
1467 function extBackup($eKey,$info) {
1468 $uArr = $this->makeUploadArray($eKey,$info);
1469 if (is_array($uArr)) {
1470 $local_gzcompress = $this->gzcompress && !$this->CMD["dontCompress"];
1471 $backUpData = $this->makeUploadDataFromArray($uArr,intval($local_gzcompress));
1472 $filename="T3X_".$eKey."-".str_replace(".","_",$info["EM_CONF"]["version"]).($local_gzcompress?"-z":"").".t3x";
1473 if (intval($this->CMD["doBackup"])==1) {
1474 #die(md5($backUpData));
1475
1476 $mimeType = "application/octet-stream";
1477 Header("Content-Type: ".$mimeType);
1478 Header("Content-Disposition: attachment; filename=".$filename);
1479
1480 // New headers suggested by Xin:
1481 // 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.
1482 /* header('Content-Type: application/force-download');
1483 header('Content-Length: '.strlen($backUpData));
1484
1485 header('Content-Disposition: attachment; filename='.$filename);
1486 header('Content-Description: File Transfer');
1487 header('Content-Transfer-Encoding: binary');
1488 */
1489
1490 // 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.
1491
1492 echo $backUpData;
1493 exit;
1494 } elseif ($this->CMD["dumpTables"]) {
1495 $filename="T3X_".$eKey;
1496 $cTables = count(explode(",",$this->CMD["dumpTables"]));
1497 if ($cTables>1) {
1498 $filename.='-'.$cTables.'tables';
1499 } else {
1500 $filename.='-'.$this->CMD["dumpTables"];
1501 }
1502 $filename.="+adt.sql";
1503
1504 $mimeType = "application/octet-stream";
1505 Header("Content-Type: ".$mimeType);
1506 Header("Content-Disposition: attachment; filename=".$filename);
1507 echo $this->dumpStaticTables($this->CMD["dumpTables"]);
1508 exit;
1509 } else {
1510 $techInfo = $this->makeDetailedExtensionAnalysis($eKey,$info);
1511 // if ($techInfo["tables"]||$techInfo["static"]||$techInfo["fields"]) {
1512 #debug($techInfo);
1513 $lines=array();
1514 $lines[]='<tr class="bgColor5"><td colspan=2><strong>Make selection:</strong></td></tr>';
1515 $lines[]='<tr class="bgColor4"><td><strong>Extension files:</strong></td><td>'.
1516 '<a href="index.php?CMD[doBackup]=1&CMD[showExt]='.$eKey.'">Download extension "'.$eKey.'" as a file</a><br />('.$filename.', '.t3lib_div::formatSize(strlen($backUpData)).', MD5: '.md5($backUpData).')<br />'.
1517 ($this->gzcompress ? '<br /><a href="index.php?CMD[doBackup]=1&CMD[dontCompress]=1&CMD[showExt]='.$eKey.'">(Click here to download extension without compression.)</a>':'').
1518 '</td></tr>';
1519
1520 if (is_array($techInfo["tables"])) { $lines[]='<tr class="bgColor4"><td><strong>Data tables:</strong></td><td>'.$this->extBackup_dumpDataTablesLine($techInfo["tables"],$eKey).'</td></tr>'; }
1521 if (is_array($techInfo["static"])) { $lines[]='<tr class="bgColor4"><td><strong>Static tables:</strong></td><td>'.$this->extBackup_dumpDataTablesLine($techInfo["static"],$eKey).'</td></tr>'; }
1522
1523 $content='<table border=0 cellpadding=2 cellspacing=2>'.implode("",$lines).'</table>';
1524 return $content;
1525 }
1526 } else die("Error...");
1527 }
1528
1529 /**
1530 * [Describe function...]
1531 *
1532 * @param [type] $tablesArray: ...
1533 * @param [type] $eKey: ...
1534 * @return [type] ...
1535 */
1536 function extBackup_dumpDataTablesLine($tablesArray,$eKey) {
1537 reset($tablesArray);
1538 $tables=array();
1539 $tablesNA=array();
1540 while(list(,$tN)=each($tablesArray)) {
1541 $q="SELECT count(*) FROM ".$tN;
1542 $res = @mysql(TYPO3_db,$q);
1543 if (!mysql_error()) {
1544 $row=mysql_fetch_row($res);
1545 $tables[$tN]='<tr><td>&nbsp;</td><td><a href="index.php?CMD[dumpTables]='.rawurlencode($tN).'&CMD[showExt]='.$eKey.'" title="Dump table \''.$tN.'\'">'.$tN."</a></td><td>&nbsp;&nbsp;&nbsp;</td><td>".$row[0]." records</td></tr>";
1546 } else {
1547 $tablesNA[$tN]='<tr><td>&nbsp;</td><td>'.$tN."</td><td>&nbsp;</td><td>Did not exist.</td></tr>";
1548 }
1549 }
1550 $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...
1551 if (count($tables)) {
1552 $label = '<a href="index.php?CMD[dumpTables]='.rawurlencode(implode(",",array_keys($tables))).'&CMD[showExt]='.$eKey.'" title="Dump all existing tables.">Download all data from:</a><br /><br />'.$label;
1553 } else $label = 'Nothing to dump...<br /><br />'.$label;
1554 return $label;
1555 }
1556
1557 /**
1558 * Prints a table with extension information in it.
1559 *
1560 * @param [type] $eKey: ...
1561 * @param [type] $info: ...
1562 * @param [type] $remote: ...
1563 * @return [type] ...
1564 */
1565 function extInformationArray($eKey,$info,$remote=0) {
1566 $lines=array();
1567 $lines[]='<tr class="bgColor5"><td colspan=2><strong>General information:</strong></td>'.$this->helpCol("").'</tr>';
1568 $lines[]='<tr class="bgColor4"><td>Title:</td><td>'.$info["EM_CONF"]["_icon"].$info["EM_CONF"]["title"].'</td>'.$this->helpCol("title").'</tr>';
1569 $lines[]='<tr class="bgColor4"><td>Description:</td><td>'.nl2br(htmlspecialchars($info["EM_CONF"]["description"])).'</td>'.$this->helpCol("description").'</tr>';
1570 $lines[]='<tr class="bgColor4"><td>Author:</td><td>'.
1571 $this->wrapEmail($info["EM_CONF"]["author"].
1572 ($info["EM_CONF"]["author_email"]?htmlspecialchars(" <".$info["EM_CONF"]["author_email"].">"):""),$info["EM_CONF"]["author_email"]).
1573 ($info["EM_CONF"]["author_company"]?", ".$info["EM_CONF"]["author_company"]:"").
1574 '</td>'.$this->helpCol("description").'</tr>';
1575
1576 $lines[]='<tr class="bgColor4"><td>Version:</td><td>'.$info["EM_CONF"]["version"].'</td>'.$this->helpCol("version").'</tr>';
1577 $lines[]='<tr class="bgColor4"><td>Category:</td><td>'.$this->categories[$info["EM_CONF"]["category"]].'</td>'.$this->helpCol("category").'</tr>';
1578 $lines[]='<tr class="bgColor4"><td>State:</td><td>'.$this->states[$info["EM_CONF"]["state"]].'</td>'.$this->helpCol("state").'</tr>';
1579 $lines[]='<tr class="bgColor4"><td>Shy?</td><td>'.($info["EM_CONF"]["shy"]?"Yes":"").'</td>'.$this->helpCol("shy").'</tr>';
1580 $lines[]='<tr class="bgColor4"><td>Internal?</td><td>'.($info["EM_CONF"]["internal"]?"Yes":"").'</td>'.$this->helpCol("internal").'</tr>';
1581
1582 $lines[]='<tr class="bgColor4"><td>Dependencies:</td><td>'.$info["EM_CONF"]["dependencies"].'</td>'.$this->helpCol("dependencies").'</tr>';
1583 if (!$remote) {
1584 $lines[]='<tr class="bgColor4"><td>Conflicts:</td><td>'.$info["EM_CONF"]["conflicts"].'</td>'.$this->helpCol("conflicts").'</tr>';
1585 $lines[]='<tr class="bgColor4"><td>Priority:</td><td>'.$info["EM_CONF"]["priority"].'</td>'.$this->helpCol("priority").'</tr>';
1586 $lines[]='<tr class="bgColor4"><td>Clear cache?</td><td>'.($info["EM_CONF"]["clearCacheOnLoad"]?"Yes":"").'</td>'.$this->helpCol("clearCacheOnLoad").'</tr>';
1587 $lines[]='<tr class="bgColor4"><td>Includes modules:</td><td>'.$info["EM_CONF"]["module"].'</td>'.$this->helpCol("module").'</tr>';
1588 }
1589 $lines[]='<tr class="bgColor4"><td>Lock Type?</td><td>'.($info["EM_CONF"]["lockType"]?$info["EM_CONF"]["lockType"]:"").'</td>'.$this->helpCol("lockType").'</tr>';
1590 $lines[]='<tr class="bgColor4"><td>Modifies tables:</td><td>'.$info["EM_CONF"]["modify_tables"].'</td>'.$this->helpCol("modify_tables").'</tr>';
1591
1592 $lines[]='<tr class="bgColor4"><td>Private?</td><td>'.($info["EM_CONF"]["private"]?"Yes":"").'</td>'.$this->helpCol("private").'</tr>';
1593 if (!$remote) $lines[]='<tr class="bgColor4"><td>Download password:</td><td>'.$info["EM_CONF"]["download_password"].'</td>'.$this->helpCol("download_password").'</tr>';
1594
1595 // Installation status:
1596 $lines[]='<tr><td>&nbsp;</td><td></td>'.$this->helpCol("").'</tr>';
1597 $lines[]='<tr class="bgColor5"><td colspan=2><strong>Installation status:</strong></td>'.$this->helpCol("").'</tr>';
1598 if (!$remote) {
1599 $lines[]='<tr class="bgColor4"><td>Type of install:</td><td>'.$this->typeLabels[$info["type"]].' - <em>'.$this->typeDescr[$info["type"]].'</em></td>'.$this->helpCol("type").'</tr>';
1600 $lines[]='<tr class="bgColor4"><td>Double installs?</td><td>'.$this->extInformationArray_dbInst($info["doubleInstall"],$info["type"]).'</td>'.$this->helpCol("doubleInstall").'</tr>';
1601 }
1602 if (is_array($info["files"])) {
1603 sort($info["files"]);
1604 $lines[]='<tr class="bgColor4"><td>Root files:</td><td>'.implode("<br />",$info["files"]).'</td>'.$this->helpCol("rootfiles").'</tr>';
1605 }
1606
1607 if (!$remote) {
1608 $techInfo = $this->makeDetailedExtensionAnalysis($eKey,$info,1);
1609 } else $techInfo = $info["_TECH_INFO"];
1610 #debug($techInfo);
1611
1612 if ($techInfo["tables"]||$techInfo["static"]||$techInfo["fields"]) {
1613 if (!$remote && t3lib_extMgm::isLoaded($eKey)) {
1614 $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!":"").
1615 ($techInfo["static_error"]?"<strong>Static table error!</strong><br />The static tables are missing or empty!":""));
1616 } else {
1617 $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!";
1618 }
1619 }
1620
1621 $lines[]='<tr class="bgColor4"><td>Database requirements:</td><td>'.$this->extInformationArray_dbReq($techInfo,1).'</td>'.$this->helpCol("dbReq").'</tr>';
1622 if (!$remote) $lines[]='<tr class="bgColor4"><td>Database status:</td><td>'.$tableStatus.'</td>'.$this->helpCol("dbStatus").'</tr>';
1623 $lines[]='<tr class="bgColor4"><td>Flags:</td><td>'.(is_array($techInfo["flags"])?implode("<br />",$techInfo["flags"]):"").'</td>'.$this->helpCol("flags").'</tr>';
1624 $lines[]='<tr class="bgColor4"><td>Config template?</td><td>'.($techInfo["conf"]?"Yes":"").'</td>'.$this->helpCol("conf").'</tr>';
1625 $lines[]='<tr class="bgColor4"><td>TypoScript files:</td><td>'.(is_array($techInfo["TSfiles"])?implode("<br />",$techInfo["TSfiles"]):"").'</td>'.$this->helpCol("TSfiles").'</tr>';
1626 $lines[]='<tr class="bgColor4"><td>Language files:</td><td>'.(is_array($techInfo["locallang"])?implode("<br />",$techInfo["locallang"]):"").'</td>'.$this->helpCol("locallang").'</tr>';
1627 $lines[]='<tr class="bgColor4"><td>Upload folder:</td><td>'.($techInfo["uploadfolder"]?$techInfo["uploadfolder"]:"").'</td>'.$this->helpCol("uploadfolder").'</tr>';
1628 $lines[]='<tr class="bgColor4"><td>Create directories:</td><td>'.(is_array($techInfo["createDirs"])?implode("<br />",$techInfo["createDirs"]):"").'</td>'.$this->helpCol("createDirs").'</tr>';
1629 $lines[]='<tr class="bgColor4"><td>Module names:</td><td>'.(is_array($techInfo["moduleNames"])?implode("<br />",$techInfo["moduleNames"]):"").'</td>'.$this->helpCol("moduleNames").'</tr>';
1630 $lines[]='<tr class="bgColor4"><td>Class names:</td><td>'.(is_array($techInfo["classes"])?implode("<br />",$techInfo["classes"]):"").'</td>'.$this->helpCol("classNames").'</tr>';
1631 $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>';
1632 $lines[]='<tr class="bgColor4"><td>Naming errors:</td><td>'.(is_array($techInfo["NSerrors"])?
1633 (!t3lib_div::inList($this->nameSpaceExceptions,$eKey)?t3lib_div::view_array($techInfo["NSerrors"]):$GLOBALS["TBE_TEMPLATE"]->dfw("[exception]"))
1634 :"").'</td>'.$this->helpCol("NSerrors").'</tr>';
1635
1636
1637 if (!$remote) {
1638 $currentMd5Array = $this->serverExtensionMD5Array($eKey,$info);
1639 $affectedFiles="";
1640
1641 $msgLines=array();
1642 # $msgLines[] = "Files: ".count($currentMd5Array);
1643 if (strcmp($info["EM_CONF"]["_md5_values_when_last_written"],serialize($currentMd5Array))) {
1644 $msgLines[] = $GLOBALS["TBE_TEMPLATE"]->rfw("<br /><strong>A difference between the originally installed version and the current was detected!</strong>");
1645 $affectedFiles = $this->findMD5ArrayDiff($currentMd5Array,unserialize($info["EM_CONF"]["_md5_values_when_last_written"]));
1646 if (count($affectedFiles)) $msgLines[] = "<br /><strong>Modified files:</strong><br />".$GLOBALS["TBE_TEMPLATE"]->rfw(implode("<br />",$affectedFiles));
1647 }
1648 $lines[]='<tr class="bgColor4"><td>Files changed?</td><td>'.implode("<br />",$msgLines).'</td>'.$this->helpCol("filesChanged").'</tr>';
1649 }
1650
1651 return '<table border=0 cellpadding=1 cellspacing=2>'.implode("",$lines).'</table>';
1652 }
1653
1654 /**
1655 * [Describe function...]
1656 *
1657 * @param [type] $techInfo: ...
1658 * @param [type] $tableHeader: ...
1659 * @return [type] ...
1660 */
1661 function extInformationArray_dbReq($techInfo,$tableHeader=0) {
1662 return nl2br(trim((is_array($techInfo["tables"])?($tableHeader?"\n\n<strong>Tables:</strong>\n":"").implode("\n",$techInfo["tables"]):"").
1663 (is_array($techInfo["static"])?"\n\n<strong>Static tables:</strong>\n".implode("\n",$techInfo["static"]):"").
1664 (is_array($techInfo["fields"])?"\n\n<strong>Additional fields:</strong>\n".implode("<HR>",$techInfo["fields"]):"")));
1665 }
1666
1667 /**
1668 * [Describe function...]
1669 *
1670 * @param [type] $dbInst: ...
1671 * @param [type] $current: ...
1672 * @return [type] ...
1673 */
1674 function extInformationArray_dbInst($dbInst,$current) {
1675 if (strlen($dbInst)>1) {
1676 $others=array();
1677 for($a=0;$a<strlen($dbInst);$a++) {
1678 if (substr($dbInst,$a,1)!=$current) {
1679 $others[]="'".$this->typeLabels[substr($dbInst,$a,1)]."'";
1680 }
1681 }
1682 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.");
1683 } else return "";
1684 }
1685
1686 /**
1687 * [Describe function...]
1688 *
1689 * @param [type] $str: ...
1690 * @param [type] $email: ...
1691 * @return [type] ...
1692 */
1693 function wrapEmail($str,$email) {
1694 if ($email) {
1695 $str='<a href="mailto:'.$email.'">'.$str.'</a>';
1696 }
1697 return $str;
1698 }
1699
1700 /**
1701 * [Describe function...]
1702 *
1703 * @param [type] $key: ...
1704 * @return [type] ...
1705 */
1706 function helpCol($key) {
1707 global $BE_USER;
1708 if ($BE_USER->uc["edit_showFieldHelp"]) {
1709 $hT = trim(t3lib_BEfunc::helpText($this->descrTable,"emconf_".$key,$this->doc->backPath));
1710 return '<td>'.($hT?$hT:t3lib_BEfunc::helpTextIcon($this->descrTable,"emconf_".$key,$this->doc->backPath)).'</td>';
1711 }
1712 }
1713
1714 /**
1715 * Prints the upload form for extensions
1716 *
1717 * @param [type] $eKey: ...
1718 * @param [type] $info: ...
1719 * @return [type] ...
1720 */
1721 function getRepositoryUploadForm($eKey,$info) {
1722 $uArr = $this->makeUploadArray($eKey,$info);
1723 if (is_array($uArr)) {
1724 $backUpData = $this->makeUploadDataFromArray($uArr);
1725
1726 #debug($this->decodeExchangeData($backUpData));
1727 $content.='Extension "'.$this->extensionTitleIconHeader($eKey,$info).'" is ready to be uploaded.<br />
1728 The size of the upload is <strong>'.t3lib_div::formatSize(strlen($backUpData)).'</strong><br />
1729 ';
1730
1731 $b64data = base64_encode($backUpData);
1732 $content='</form><form action="'.$this->repositoryUrl.'" method="post" enctype="application/x-www-form-urlencoded">
1733 <input type="hidden" name="tx_extrep[upload][returnUrl]" value="'.htmlspecialchars($this->makeReturnUrl()).'">
1734 <input type="hidden" name="tx_extrep[upload][data]" value="'.$b64data.'">
1735 <input type="hidden" name="tx_extrep[upload][typo3ver]" value="'.$GLOBALS["TYPO_VERSION"].'">
1736 <input type="hidden" name="tx_extrep[upload][os]" value="'.TYPO3_OS.'">
1737 <input type="hidden" name="tx_extrep[upload][sapi]" value="'.php_sapi_name().'">
1738 <input type="hidden" name="tx_extrep[upload][phpver]" value="'.phpversion().'">
1739 <input type="hidden" name="tx_extrep[upload][gzcompressed]" value="'.$this->gzcompress.'">
1740 <input type="hidden" name="tx_extrep[upload][data_md5]" value="'.md5($b64data).'">
1741 <table border=0 cellpadding=2 cellspacing=1>
1742 <tr class="bgColor4"><td>Repository Username:</td><td><input'.$this->doc->formWidth(20).' type="text" name="tx_extrep[user][fe_u]" value="'.$this->fe_user["username"].'"></td></tr>
1743 <tr class="bgColor4"><td>Repository Password:</td><td><input'.$this->doc->formWidth(20).' type="password" name="tx_extrep[user][fe_p]" value="'.$this->fe_user["password"].'"></td></tr>
1744 <tr class="bgColor4"><td>Upload password for this extension:</td><td><input'.$this->doc->formWidth(30).' type="password" name="tx_extrep[upload][upload_p]" value="'.$this->fe_user["uploadPass"].'"></td></tr>
1745 <tr class="bgColor4"><td>Comment to the upload:</td><td><textarea'.$this->doc->formWidth(30,1).' rows="5" name="tx_extrep[upload][comment]"></textarea></td></tr>
1746 <tr class="bgColor4"><td>Upload command:</td><td nowrap>
1747 <input type="radio" name="tx_extrep[upload][mode]" value="new_dev" checked> New development version (latest x.x.<strong>'.$GLOBALS["TBE_TEMPLATE"]->rfw("x+1").'</strong>)<br />
1748 <input type="radio" name="tx_extrep[upload][mode]" value="latest"> Override <em>this</em> development version ('.$info["EM_CONF"]["version"].')<br />
1749 <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 />
1750 <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 />
1751 </td></tr>
1752 <tr class="bgColor4"><td>Private?</td><td>
1753 <input type="checkbox" name="tx_extrep[upload][private]" value="1"'.($info["EM_CONF"]["private"]?" CHECKED":"").'>Yes, dont show <em>this upload</em> in the public list.<br />
1754 ("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 />
1755 <br /><strong>Additional import password:</strong><br />
1756 <input'.$this->doc->formWidth(20).' type="text" name="tx_extrep[upload][download_password]" value="'.htmlspecialchars(trim($info["EM_CONF"]["download_password"])).'"> (Textfield!) <br />
1757 (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 />
1758 </td></tr>
1759 <tr class="bgColor4"><td>&nbsp;</td><td><input type="submit" name="submit" value="Upload extension"><br />
1760 '.t3lib_div::formatSize(strlen($b64data)).($this->gzcompress?", compressed":"").', base64<br />
1761 <br />
1762 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!
1763 </td></tr>
1764 </table>
1765 ';
1766
1767 return $content;
1768 } else {
1769 return $uArr;
1770 }
1771 }
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784 /**
1785 * Prints the header row for the various listings
1786 *
1787 * @param [type] $bgColor: ...
1788 * @param [type] $cells: ...
1789 * @param [type] $import: ...
1790 * @return [type] ...
1791 */
1792 function extensionListRowHeader($bgColor,$cells,$import=0) {
1793 $cells[]='<td></td>';
1794 $cells[]='<td nowrap><strong>Title:</strong></td>';
1795
1796 if (!$this->MOD_SETTINGS["display_details"]) {
1797 $cells[]='<td nowrap><strong>Description:</strong></td>';
1798 $cells[]='<td nowrap><strong>Author:</strong></td>';
1799 } elseif ($this->MOD_SETTINGS["display_details"]==2) {
1800 $cells[]='<td nowrap><strong>Priority:</strong></td>';
1801 $cells[]='<td nowrap><strong>Mod.Tables:</strong></td>';
1802 $cells[]='<td nowrap><strong>Modules:</strong></td>';
1803 $cells[]='<td nowrap><strong>Cl.Cache?</strong></td>';
1804 $cells[]='<td nowrap><strong>Internal?</strong></td>';
1805 $cells[]='<td nowrap><strong>Shy?</strong></td>';
1806 } elseif ($this->MOD_SETTINGS["display_details"]==3) {
1807 $cells[]='<td nowrap><strong>Tables/Fields:</strong></td>';
1808 $cells[]='<td nowrap><strong>TS-files:</strong></td>';
1809 $cells[]='<td nowrap><strong>Affects:</strong></td>';
1810 $cells[]='<td nowrap><strong>Modules:</strong></td>';
1811 $cells[]='<td nowrap><strong>Config?</strong></td>';
1812 $cells[]='<td nowrap><strong>Errors:</strong></td>';
1813 } elseif ($this->MOD_SETTINGS["display_details"]==4) {
1814 $cells[]='<td nowrap><strong>locallang:</strong></td>';
1815 $cells[]='<td nowrap><strong>Classes:</strong></td>';
1816 $cells[]='<td nowrap><strong>Errors:</strong></td>';
1817 $cells[]='<td nowrap><strong>NameSpace Errors:</strong></td>';
1818 } elseif ($this->MOD_SETTINGS["display_details"]==5) {
1819 $cells[]='<td nowrap><strong>Changed files:</strong></td>';
1820 } else {
1821 $cells[]='<td nowrap><strong>Extension key:</strong></td>';
1822 $cells[]='<td nowrap><strong>Version:</strong></td>';
1823 if (!$import) {
1824 $cells[]='<td><strong>Doc:</strong></td>';
1825 $cells[]='<td nowrap><strong>Type:</strong></td>';
1826 } else {
1827 $cells[]='<td nowrap 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.").'><strong>Cur. Ver:</strong></td>';
1828 $cells[]='<td nowrap class="bgColor6"'.$this->labelInfo("Current type of installation of the extension on this server.").'><strong>Cur. Type:</strong></td>';
1829 $cells[]='<td nowrap'.$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.").'><strong>Access:</strong></td>';
1830 $cells[]='<td nowrap'.$this->labelInfo("TYPO3 version of last uploading server.").'><strong>T3 ver:</strong></td>';
1831 $cells[]='<td nowrap'.$this->labelInfo("PHP version of last uploading server.").'><strong>PHP:</strong></td>';
1832 $cells[]='<td nowrap'.$this->labelInfo("Size of extension, uncompressed / compressed").'><strong>Size:</strong></td>';
1833 $cells[]='<td nowrap'.$this->labelInfo("Number of downloads, all versions/this version").'><strong>DL:</strong></td>';
1834 }
1835 $cells[]='<td nowrap><strong>State:</strong></td>';
1836 $cells[]='<td nowrap><strong>Dependencies:</strong></td>';
1837 }
1838 return '<tr'.$bgColor.'>'.implode('',$cells).'</tr>';
1839 }
1840
1841 /**
1842 * Prints a row with data for the various extension listings
1843 *
1844 * @param [type] $eKey: ...
1845 * @param [type] $eConf: ...
1846 * @param [type] $info: ...
1847 * @param [type] $cells: ...
1848 * @param [type] $bgColor: ...
1849 * @param [type] $inst_list: ...
1850 * @param [type] $import: ...
1851 * @param [type] $altLinkUrl: ...
1852 * @return [type] ...
1853 */
1854 function extensionListRow($eKey,$eConf,$info,$cells,$bgColor="",$inst_list=array(),$import=0,$altLinkUrl="") {
1855 $imgInfo = @getImageSize($this->getExtPath($eKey,$info)."/ext_icon.gif");
1856 $style = t3lib_extMgm::isLoaded($eKey) ? '' : ' style="color:#666666;"';
1857
1858 if (is_array($imgInfo)) {
1859 $cells[]='<td valign=top><img src="'.$GLOBALS["BACK_PATH"].$this->typeRelPaths[$info["type"]].$eKey."/ext_icon.gif".'" '.$imgInfo[3].'></td>';
1860 } elseif ($info["_ICON"]) {
1861 $cells[]='<td valign=top>'.$info["_ICON"].'</td>';
1862 } else {
1863 $cells[]='<td><img src="clear.gif" width=1 height=1></td>';
1864 }
1865 $cells[]='<td nowrap valign=top><a href="'.($altLinkUrl?$altLinkUrl:"index.php?CMD[showExt]=".$eKey."&SET[singleDetails]=info").'" title="'.$eKey.'"'.$style.'>'.t3lib_div::fixed_lgd($info["EM_CONF"]["title"]?$info["EM_CONF"]["title"]:"<em>".$eKey."</em>",40).'</a></td>';
1866
1867 if (isset($inst_list[$eKey])) {
1868 unset($this->inst_keys[$eKey]);
1869 }
1870
1871 if (!$this->MOD_SETTINGS["display_details"]) {
1872 $cells[]='<td valign=top>'.t3lib_div::fixed_lgd(htmlspecialchars($info["EM_CONF"]["description"]),400).'<br /><img src=clear.gif width=300 height=></td>';
1873 $cells[]='<td nowrap valign=top>'.$info["EM_CONF"]["author"].($info["EM_CONF"]["author_company"]?"<br />".$info["EM_CONF"]["author_company"]:"").'</td>';
1874 } elseif ($this->MOD_SETTINGS["display_details"]==2) {
1875 $cells[]="<td nowrap valign=top>".$info["EM_CONF"]["priority"]."</td>";
1876 $cells[]="<td nowrap valign=top>".implode("<br />",t3lib_div::trimExplode(",",$info["EM_CONF"]["modify_tables"],1))."</td>";
1877 $cells[]="<td nowrap valign=top>".$info["EM_CONF"]["module"]."</td>";
1878 $cells[]="<td nowrap valign=top>".($info["EM_CONF"]["clearCacheOnLoad"]?"Yes":"")."</td>";
1879 $cells[]="<td nowrap valign=top>".($info["EM_CONF"]["internal"]?"Yes":"")."</td>";
1880 $cells[]="<td nowrap valign=top>".($info["EM_CONF"]["shy"]?"Yes":"")."</td>";
1881 } elseif ($this->MOD_SETTINGS["display_details"]==3) {
1882 $techInfo=$this->makeDetailedExtensionAnalysis($eKey,$info);
1883
1884 $cells[]="<td valign=top>".$this->extInformationArray_dbReq($techInfo).
1885 "</td>";
1886 $cells[]="<td nowrap valign=top>".(is_array($techInfo["TSfiles"])?implode("<br />",$techInfo["TSfiles"]):"")."</td>";
1887 $cells[]="<td nowrap valign=top>".(is_array($techInfo["flags"])?implode("<br />",$techInfo["flags"]):"")."</td>";
1888 $cells[]="<td nowrap valign=top>".(is_array($techInfo["moduleNames"])?implode("<br />",$techInfo["moduleNames"]):"")."</td>";
1889 $cells[]="<td nowrap valign=top>".($techInfo["conf"]?"Yes":"")."</td>";
1890 $cells[]="<td valign=top>".
1891 $GLOBALS["TBE_TEMPLATE"]->rfw((t3lib_extMgm::isLoaded($eKey)&&$techInfo["tables_error"]?"<strong>Table error!</strong><br />Probably one or more required fields/tables are missing in the database!":"").
1892 (t3lib_extMgm::isLoaded($eKey)&&$techInfo["static_error"]?"<strong>Static table error!</strong><br />The static tables are missing or empty!":"")).
1893 "</td>";
1894 } elseif ($this->MOD_SETTINGS["display_details"]==4) {
1895 $techInfo=$this->makeDetailedExtensionAnalysis($eKey,$info,1);
1896
1897 $cells[]="<td valign=top>".(is_array($techInfo["locallang"])?implode("<br />",$techInfo["locallang"]):"")."</td>";
1898 $cells[]="<td valign=top>".(is_array($techInfo["classes"])?implode("<br />",$techInfo["classes"]):"")."</td>";
1899 $cells[]="<td valign=top>".(is_array($techInfo["errors"])?$GLOBALS["TBE_TEMPLATE"]->rfw(implode("<HR>",$techInfo["errors"])):"")."</td>";
1900 $cells[]="<td valign=top>".(is_array($techInfo["NSerrors"])?
1901 (!t3lib_div::inList($this->nameSpaceExceptions,$eKey)?t3lib_div::view_array($techInfo["NSerrors"]):$GLOBALS["TBE_TEMPLATE"]->dfw("[exception]"))
1902 :"")."</td>";
1903 } elseif ($this->MOD_SETTINGS["display_details"]==5) {
1904 # $techInfo=$this->makeDetailedExtensionAnalysis($eKey,$info,1);
1905 $currentMd5Array = $this->serverExtensionMD5Array($eKey,$info);
1906 $affectedFiles="";
1907 $msgLines=array();
1908 $msgLines[] = "Files: ".count($currentMd5Array);
1909 if (strcmp($info["EM_CONF"]["_md5_values_when_last_written"],serialize($currentMd5Array))) {
1910 $msgLines[] = $GLOBALS["TBE_TEMPLATE"]->rfw("<br /><strong>A difference between the originally installed version and the current was detected!</strong>");
1911 $affectedFiles = $this->findMD5ArrayDiff($currentMd5Array,unserialize($info["EM_CONF"]["_md5_values_when_last_written"]));
1912 if (count($affectedFiles)) $msgLines[] = "<br /><strong>Modified files:</strong><br />".$GLOBALS["TBE_TEMPLATE"]->rfw(implode("<br />",$affectedFiles));
1913 }
1914 $cells[]="<td valign=top>".implode("<br />",$msgLines)."</td>";
1915 } else {
1916 $verDiff = $inst_list[$eKey] && $this->versionDifference($info["EM_CONF"]["version"],$inst_list[$eKey]["EM_CONF"]["version"],$this->versionDiffFactor);
1917
1918 $cells[]="<td nowrap valign=top><em>".$eKey."</em></td>";
1919 $cells[]="<td nowrap valign=top>".($verDiff?"<strong>".$GLOBALS["TBE_TEMPLATE"]->rfw($info["EM_CONF"]["version"])."</strong>":$info["EM_CONF"]["version"])."</td>";
1920 if (!$import) {
1921 $fileP = PATH_site.$this->typePaths[$info["type"]].$eKey."/doc/manual.sxw";
1922
1923 $cells[]='<td nowrap>'.
1924 ($this->typePaths[$info["type"]] && @is_file($fileP)?'<img src="oodoc.gif" width="13" height="16" title="Local Open Office Manual" alt="" />':'').
1925 '</td>';
1926 $cells[]="<td nowrap valign=top>".$this->typeLabels[$info["type"]].(strlen($info["doubleInstall"])>1?'<strong> '.$GLOBALS["TBE_TEMPLATE"]->rfw($info["doubleInstall"]).'</strong>':"")."</td>";
1927 } else {
1928 $inst_curVer = $inst_list[$eKey]["EM_CONF"]["version"];
1929 if (isset($inst_list[$eKey])) {
1930 if ($verDiff) $inst_curVer = "<strong>".$GLOBALS["TBE_TEMPLATE"]->rfw($inst_curVer)."</strong>";
1931 }
1932 $cells[]="<td nowrap valign=top>".$inst_curVer."</td>";
1933 $cells[]="<td nowrap valign=top>".$this->typeLabels[$inst_list[$eKey]["type"]].(strlen($inst_list[$eKey]["doubleInstall"])>1?'<strong> '.$GLOBALS["TBE_TEMPLATE"]->rfw($inst_list[$eKey]["doubleInstall"]).'</strong>':"")."</td>";
1934 $cells[]="<td nowrap valign=top><strong>".$GLOBALS["TBE_TEMPLATE"]->rfw($this->remoteAccess[$info["_ACCESS"]])."</strong></td>";
1935 $cells[]="<td nowrap valign=top>".$info["EM_CONF"]["_typo3_ver"]."</td>";
1936 $cells[]="<td nowrap valign=top>".$info["EM_CONF"]["_php_ver"]."</td>";
1937 $cells[]="<td nowrap valign=top>".$info["EM_CONF"]["_size"]."</td>";
1938 $cells[]="<td nowrap valign=top>".($info["_STAT_IMPORT"]["extension_allversions"]?$info["_STAT_IMPORT"]["extension_allversions"]:"&nbsp;&nbsp;")."/".($info["_STAT_IMPORT"]["extension_thisversion"]?$info["_STAT_IMPORT"]["extension_thisversion"]:"&nbsp;")."</td>";
1939 //debug($info);
1940 }
1941 $cells[]="<td nowrap valign=top>".$this->states[$info["EM_CONF"]["state"]]."</td>";
1942 $cells[]="<td nowrap valign=top>".$info["EM_CONF"]["dependencies"]."</td>";
1943 }
1944 $bgColor = ' bgColor="'.($bgColor?$bgColor:$this->doc->bgColor4).'"';
1945 return '<tr'.$bgColor.$style.'>'.implode('',$cells).'</tr>';
1946 }
1947
1948 /**
1949 * Returns title and style attribute for mouseover help text.
1950 *
1951 * @param [type] $str: ...
1952 * @return [type] ...
1953 */
1954 function labelInfo($str) {
1955 return ' title="'.htmlspecialchars($str).'" style="cursor:help;"';
1956 }
1957
1958 /**
1959 * Creates directories in $extDirPath
1960 *
1961 * @param [type] $dirs: ...
1962 * @param [type] $extDirPath: ...
1963 * @return [type] ...
1964 */
1965 function createDirsInPath($dirs,$extDirPath) {
1966 if (is_array($dirs)) {
1967 reset($dirs);
1968 while(list(,$dir)=each($dirs)) {
1969 $allDirs = t3lib_div::trimExplode("/",$dir,1);
1970 reset($allDirs);
1971 $root="";
1972 while(list(,$dirParts)=each($allDirs)) {
1973 $root.=$dirParts.'/';
1974 if (!is_dir($extDirPath.$root)) {
1975 @mkdir(ereg_replace('\/$','',$extDirPath.$root), 0777);
1976 if (!@is_dir($extDirPath.$root)) {
1977 return "Error: The directory '".$extDirPath.$root."' could not be created...";
1978 }
1979 }
1980 }
1981 }
1982 }
1983 }
1984
1985 /**
1986 * Removes the extension directory
1987 *
1988 * @param [type] $removePath: ...
1989 * @param [type] $removeContentOnly: ...
1990 * @return [type] ...
1991 */
1992 function removeExtDirectory($removePath,$removeContentOnly=0) {
1993 if (@is_dir($removePath) && substr($removePath,-1)=="/" && (
1994 t3lib_div::isFirstPartOfStr($removePath,PATH_site.$this->typePaths["G"]) ||
1995 t3lib_div::isFirstPartOfStr($removePath,PATH_site.$this->typePaths["L"]) ||
1996 (t3lib_div::isFirstPartOfStr($removePath,PATH_site.$this->typePaths["S"]) && $this->systemInstall) ||
1997 t3lib_div::isFirstPartOfStr($removePath,PATH_site."fileadmin/_temp_/"))
1998 ) {
1999 $this->noCVS=0;
2000 $fileArr = $this->getAllFilesAndFoldersInPath(array(),$removePath,"",1);
2001 if (is_array($fileArr)) {
2002 // Remove files in dirs:
2003 #debug($fileArr);
2004 reset($fileArr);
2005 while(list(,$removeFile)=each($fileArr)) {
2006 if (!@is_dir($removeFile)) {
2007 if (@is_file($removeFile) && t3lib_div::isFirstPartOfStr($removeFile,$removePath) && strcmp($removeFile,$removePath)) { // ... we are very paranoid, so we check what cannot go wrong: that the file is in fact within the prefix path!
2008 @unlink($removeFile);
2009 #debug($removeFile);
2010 clearstatcache();
2011 if (@is_file($removeFile)) {
2012 debug("Error: '".$removeFile."' could not be deleted!");
2013 }
2014 } else debug("Error: '".$removeFile."' was either not a file, or it was equal to the removed directory or simply outside the removed directory '".$removePath."'!");
2015 }
2016 }
2017
2018 // REmove dirs:
2019 $remDirs = $this->extractDirsFromFileList($this->removePrefixPathFromList($fileArr,$removePath));
2020 #debug($remDirs);
2021 $remDirs = array_reverse($remDirs); // Must delete outer dirs first...
2022 reset($remDirs);
2023 while(list(,$removeRelDir)=each($remDirs)) {
2024 $removeDir = $removePath.$removeRelDir;
2025 if (@is_dir($removeDir)) { // ... we are very paranoid, so we check what cannot go wrong: that the file is in fact within the prefix path!
2026 rmdir($removeDir);
2027 clearstatcache();
2028 if (@is_dir($removeDir)) {
2029 debug("Error: '".$removeDir."' could not be removed (are there files left?)");
2030 }
2031 } else debug("Error: '".$removeDir."' was not a directory!");
2032 }
2033
2034 if (!$removeContentOnly) {
2035 rmdir($removePath);
2036 clearstatcache();
2037 if (@is_dir($removePath)) {
2038 debug("Error: Extension directory '".$removePath."' could not be removed (are there files or folders left?)");
2039 }
2040 }
2041 #debug("ALL REMOVED");
2042 } else debug("Error: ".$fileArr);
2043 } else debug("Error: Unallowed path to remove: ".$removePath);
2044 }
2045
2046 /**
2047 * Extracts the directories in the $files array
2048 *
2049 * @param [type] $files: ...
2050 * @return [type] ...
2051 */
2052 function extractDirsFromFileList($files) {
2053 $dirs = array();
2054 if (is_array($files)) {
2055 reset($files);
2056 while(list(,$file)=each($files)) {
2057 if (substr($file,-1)=="/") {
2058 $dirs[$file]=$file;
2059 } else {
2060 $pI=pathinfo($file);
2061 if (strcmp($pI["dirname"],"") && strcmp($pI["dirname"],".")) {
2062 $dirs[$pI["dirname"]."/"]=$pI["dirname"]."/";
2063 }
2064 }
2065 }
2066 }
2067 return $dirs;
2068 }
2069
2070 /**
2071 * Removes the current extension of $type and creates the base folder for the new one (which is going to be imported)
2072 *
2073 * @param [type] $importedData: ...
2074 * @param [type] $type: ...
2075 * @return [type] ...
2076 */
2077 function clearAndMakeExtensionDir($importedData,$type) {
2078 if (!$importedData["extKey"]) return "FATAL ERROR: Extension key was not set for some VERY strange reason. Nothing done...";
2079
2080 $path="";
2081 switch((string)$type) {
2082 case "G":
2083 case "L":
2084 $path=PATH_site.$this->typePaths[$type];
2085 $suffix="";
2086 if ((string)$type=="L" && !@is_dir($path)) {
2087 @mkdir(ereg_replace('\/$','',$path), 0777);
2088 }
2089 break;
2090 default:
2091 if ($this->systemInstall && (string)$type=="S") {
2092 $path=PATH_site.$this->typePaths[$type];
2093 $suffix="";
2094 } else {
2095 $path=PATH_site."fileadmin/_temp_/";
2096 $suffix="_".date("dmy-His");
2097 }
2098 break;
2099 }
2100 if ($path && @is_dir($path)) {
2101 $extDirPath = $path.$importedData["extKey"].$suffix.'/';
2102 if (@is_dir($extDirPath)) {
2103 // Install dir was found
2104 $res = $this->removeExtDirectory($extDirPath);
2105 if ($res) return "ERROR: Could not remove extension directory '".$extDirPath."'";
2106 }
2107 #die("stop here...");
2108 // we go create...
2109 @mkdir(ereg_replace('\/$','',$extDirPath), 0777);
2110 if (!is_dir($extDirPath)) return "ERROR: Could not create extension directory '".$extDirPath."'";
2111 return array($extDirPath);
2112 } else return "ERROR: The extension install path '".$path."' was not a directory.";
2113 }
2114
2115 /**
2116 * Evaluates differences in version numbers with three parts, x.x.x. Returns true if $v1 is greater than $v2
2117 *
2118 * @param [type] $v1: ...
2119 * @param [type] $v2: ...
2120 * @param [type] $div: ...
2121 * @return [type] ...
2122 */
2123 function versionDifference($v1,$v2,$div=1) {
2124 # debug(array(floor($this->makeVersion($v1,"int")/$div),floor($this->makeVersion($v2,"int")/$div)));
2125 return floor($this->makeVersion($v1,"int")/$div) > floor($this->makeVersion($v2,"int")/$div);
2126 }
2127
2128 /**
2129 * Fetches data from the $repositoryUrl, un-compresses it, unserializes array and returns an array with the content if success.
2130 *
2131 * @param [type] $repositoryUrl: ...
2132 * @return [type] ...
2133 */
2134 function fetchServerData($repositoryUrl) {
2135 $ps1 = t3lib_div::milliseconds();
2136 $externalData = t3lib_div::getUrl($repositoryUrl);
2137 $ps2 = t3lib_div::milliseconds()+1;
2138
2139 $stat=Array(
2140 ($ps2-$ps1),
2141 strlen($externalData),
2142 "Time: ".($ps2-$ps1)."ms",
2143 "Size: ".t3liB_div::formatSize(strlen($externalData)),
2144 "Transfer: ".t3liB_div::formatSize(strlen($externalData) / (($ps2-$ps1)/1000))."/sec"
2145 );
2146
2147 return $this->decodeServerData($externalData,$stat);
2148 }
2149
2150 /**
2151 * Decode server data
2152 *
2153 * @param [type] $externalData: ...
2154 * @param [type] $stat: ...
2155 * @return [type] ...
2156 */
2157 function decodeServerData($externalData,$stat=array()) {
2158 $parts = explode(":",$externalData,4);
2159 $dat = base64_decode($parts[2]);
2160 if ($parts[0]==md5($dat)) {
2161 if ($parts[1]=="gzcompress") {
2162 if ($this->gzcompress) {
2163 $dat=gzuncompress($dat);
2164 } else debug("Decoding Error: No decompressor available for compressed content. gzcompress()/gzuncompress() functions are not available!");
2165 }
2166 $listArr = unserialize($dat);
2167 return array($listArr,$stat);
2168 }
2169 }
2170
2171 /**
2172 * Clearing of cache-files in typo3conf/ + menu
2173 *
2174 * @return [type] ...
2175 */
2176 function addClearCacheFiles() {
2177 global $TYPO3_CONF_VARS;
2178 if ($TYPO3_CONF_VARS["EXT"]["extCache"]) {
2179 if (t3lib_div::GPvar("_clearCacheFiles")) {
2180 $this->removeCacheFiles();
2181 header("Location: ".t3lib_div::linkThisScript(array("_clearCacheFiles"=>0,"_cache_files_are_removed"=>1)));
2182 } else {
2183 $content="";
2184 if (t3lib_div::GPvar("_cache_files_are_removed")) $content.=$GLOBALS["TBE_TEMPLATE"]->rfw("Cache files was removed.").'<br /><br />';
2185 $content.='Click here to <a href="'.t3lib_div::linkThisScript(array("_clearCacheFiles"=>1)).'"><strong>clear cache files in typo3conf/</strong></a>';
2186 $this->content.=$this->doc->spacer(20);
2187 $this->content.=$this->doc->section("Clear cache files",$content,0,1);
2188 }
2189 }
2190 }
2191
2192 /**
2193 * Returns a header for an extensions including icon if any
2194 *
2195 * @param [type] $eKey: ...
2196 * @param [type] $info: ...
2197 * @param [type] $align: ...
2198 * @return [type] ...
2199 */
2200 function extensionTitleIconHeader($eKey,$info,$align="top") {
2201 $imgInfo = @getImageSize($this->getExtPath($eKey,$info)."/ext_icon.gif");
2202 $out="";
2203 if (is_array($imgInfo)) {
2204 $out.='<img src="'.$GLOBALS["BACK_PATH"].$this->typeRelPaths[$info["type"]].$eKey."/ext_icon.gif".'" '.$imgInfo[3].' align='.$align.'>';
2205 }
2206 $out.=t3lib_div::fixed_lgd($info["EM_CONF"]["title"]?$info["EM_CONF"]["title"]:"<em>".$eKey."</em>",40);
2207 return $out;
2208 }
2209
2210 /**
2211 * Perform a detailed, technical analysis of the available extension on server!
2212 * Includes all kinds of verifications
2213 *
2214 * @param [type] $eKey: ...
2215 * @param [type] $info: ...
2216 * @param [type] $validity: ...
2217 * @return [type] ...
2218 */
2219 function makeDetailedExtensionAnalysis($eKey,$info,$validity=0) {
2220 $absPath = $this->getExtPath($eKey,$info);
2221
2222 $infoArray = array();
2223
2224 $table_class_prefix = substr($eKey,0,5)=="user_" ? "user_" : "tx_".str_replace("_","",$eKey)."_";
2225 $module_prefix = substr($eKey,0,5)=="user_" ? "u" : "tx".str_replace("_","",$eKey);
2226
2227 // Tables:
2228 $dbInfo=$this->checkDBupdates($eKey,$info,1);
2229 if (is_array($dbInfo["static"])) {
2230 $infoArray["static"]=array_keys($dbInfo["static"]);
2231 }
2232 if (is_array($dbInfo["structure"]["tables_fields"])) {
2233 $modify_tables = t3lib_div::trimExplode(",",$info["EM_CONF"]["modify_tables"],1);
2234 $infoArray["dump_tf"]=array();
2235 reset($dbInfo["structure"]["tables_fields"]);
2236 while(list($tN,$d)=each($dbInfo["structure"]["tables_fields"])) {
2237 if (in_array($tN,$modify_tables)) {
2238 $infoArray["fields"][]=$tN.": <i>".
2239 (is_array($d["fields"])?implode(", ",array_keys($d["fields"])):"").
2240 (is_array($d["keys"])?" + ".count($d["keys"])." keys":"").
2241 "</i>";
2242 if (is_array($d["fields"])) {
2243 reset($d["fields"]);
2244 while(list($fN)=each($d["fields"])) {
2245 $infoArray["dump_tf"][]=$tN.".".$fN;
2246 if (!t3lib_div::isFirstPartOfStr($fN,$table_class_prefix)) {
2247 $infoArray["NSerrors"]["fields"][$fN]=$fN;
2248 } else $infoArray["NSok"]["fields"][$fN]=$fN;
2249 }
2250 }
2251 if (is_array($d["keys"])) {
2252 reset($d["keys"]);
2253 while(list($fN)=each($d["keys"])) {
2254 $infoArray["dump_tf"][]=$tN.".KEY:".$fN;
2255 }
2256 }
2257 } else {
2258 $infoArray["dump_tf"][]=$tN;
2259 $infoArray["tables"][]=$tN;
2260 if (!t3lib_div::isFirstPartOfStr($tN,$table_class_prefix)) {
2261 $infoArray["NSerrors"]["tables"][$tN]=$tN;
2262 } else $infoArray["NSok"]["tables"][$tN]=$tN;
2263 }
2264 }
2265 if (count($dbInfo["structure"]["diff"]["diff"]) || count($dbInfo["structure"]["diff"]["extra"])) {
2266 $msg=array();
2267 if (count($dbInfo["structure"]["diff"]["diff"])) $msg[]="missing";
2268 if (count($dbInfo["structure"]["diff"]["extra"])) $msg[]="of wrong type";
2269 $infoArray["tables_error"]=1;
2270 if (t3lib_extMgm::isLoaded($eKey)) $infoArray["errors"][]="Some tables or fields are ".implode(" and ",$msg)."!";
2271 }
2272 }
2273 if (is_array($infoArray["static"])) {
2274 reset($dbInfo["static"]);
2275 while(list($tN,$d)=each($dbInfo["static"])) {
2276 if (!$d["exists"]) {
2277 $infoArray["static_error"]=1;
2278 if (t3lib_extMgm::isLoaded($eKey)) $infoArray["errors"][]="Static table(s) missing!";
2279 if (!t3lib_div::isFirstPartOfStr($tN,$table_class_prefix)) {
2280 $infoArray["NSerrors"]["tables"][$tN]=$tN;
2281 } else $infoArray["NSok"]["tables"][$tN]=$tN;
2282 }
2283 }
2284 }
2285
2286 // Module-check:
2287 $knownModuleList = t3lib_div::trimExplode(",",$info["EM_CONF"]["module"],1);
2288 reset($knownModuleList);
2289 while(list(,$mod)=each($knownModuleList)) {
2290 if (@is_dir($absPath.$mod)) {
2291 if (@is_file($absPath.$mod."/conf.php")) {
2292 $confFileInfo = $this->modConfFileAnalysis($absPath.$mod."/conf.php");
2293 if (is_array($confFileInfo["TYPO3_MOD_PATH"])) {
2294 $shouldBePath = $this->typeRelPaths[$info["type"]].$eKey."/".$mod."/";
2295 if (strcmp($confFileInfo["TYPO3_MOD_PATH"][1][1],$shouldBePath)) {
2296 $infoArray["errors"][]="Configured TYPO3_MOD_PATH '".$confFileInfo["TYPO3_MOD_PATH"][1][1]."' different from '".$shouldBePath."'";
2297 }
2298 } else $infoArray["errors"][]="No definition of TYPO3_MOD_PATH constant found inside!";
2299 if (is_array($confFileInfo["MCONF_name"])) {
2300 $mName = $confFileInfo["MCONF_name"][1][1];
2301 $mNameParts = explode("_",$mName);
2302 $infoArray["moduleNames"][]=$mName;
2303 if (!t3lib_div::isFirstPartOfStr($mNameParts[0],$module_prefix) &&
2304 (!$mNameParts[1] || !t3lib_div::isFirstPartOfStr($mNameParts[1],$module_prefix))) {
2305 $infoArray["NSerrors"]["modname"][]=$mName;
2306 } else $infoArray["NSok"]["modname"][]=$mName;
2307 } else $infoArray["errors"][]="No definition of MCONF[name] variable found inside!";
2308 } else $infoArray["errors"][]="Backend module conf file '".$mod."/conf.php' should exist but does not!";
2309 } else $infoArray["errors"][]="Backend module folder '".$mod."/' should exist but does not!";
2310 }
2311 $dirs = t3lib_div::get_dirs($absPath);
2312 if (is_array($dirs)) {
2313 reset($dirs);
2314 while(list(,$mod)=each($dirs)) {
2315 if (!in_array($mod,$knownModuleList) && @is_file($absPath.$mod."/conf.php")) {
2316 $confFileInfo = $this->modConfFileAnalysis($absPath.$mod."/conf.php");
2317 if (is_array($confFileInfo)) {
2318 $infoArray["errors"][]="It seems like there is a backend module in '".$mod."/conf.php"."' which is not configured in ext_emconf.php";
2319 }
2320 }
2321 }
2322 }
2323
2324 // ext_tables.php:
2325 if (@is_file($absPath."ext_tables.php")) {
2326 $content = t3lib_div::getUrl($absPath."ext_tables.php");
2327 if (eregi("t3lib_extMgm::addModule",$content)) $infoArray["flags"][]="Module";
2328 if (eregi("t3lib_extMgm::insertModuleFunction",$content)) $infoArray["flags"][]="Module+";
2329 if (stristr($content,'t3lib_div::loadTCA')) $infoArray["flags"][]='loadTCA';
2330 if (stristr($content,'$TCA[')) $infoArray["flags"][]='TCA';
2331 if (eregi("t3lib_extMgm::addPlugin",$content)) $infoArray["flags"][]="Plugin";
2332 }
2333
2334 // ext_localconf.php:
2335 if (@is_file($absPath."ext_localconf.php")) {
2336 $content = t3lib_div::getUrl($absPath."ext_localconf.php");
2337 if (eregi("t3lib_extMgm::addPItoST43",$content)) $infoArray["flags"][]="Plugin/ST43";
2338 if (eregi("t3lib_extMgm::addPageTSConfig",$content)) $infoArray["flags"][]="Page-TSconfig";
2339 if (eregi("t3lib_extMgm::addUserTSConfig",$content)) $infoArray["flags"][]="User-TSconfig";
2340 if (eregi("t3lib_extMgm::addTypoScriptSetup",$content)) $infoArray["flags"][]="TS/Setup";
2341 if (eregi("t3lib_extMgm::addTypoScriptConstants",$content)) $infoArray["flags"][]="TS/Constants";
2342 }
2343
2344 if (@is_file($absPath."ext_typoscript_constants.txt")) {
2345 $infoArray["TSfiles"][]="Constants";
2346 }
2347 if (@is_file($absPath."ext_typoscript_setup.txt")) {
2348 $infoArray["TSfiles"][]="Setup";
2349 }
2350 if (@is_file($absPath."ext_conf_template.txt")) {
2351 $infoArray["conf"]=1;
2352 }
2353
2354 // Classes:
2355 if ($validity) {
2356 $filesInside = $this->getClassIndexLocallangFiles($absPath,$table_class_prefix,$eKey);
2357 if (is_array($filesInside["errors"])) $infoArray["errors"]=array_merge($infoArray["errors"],$filesInside["errors"]);
2358 if (is_array($filesInside["NSerrors"])) $infoArray["NSerrors"]=array_merge($infoArray["NSerrors"],$filesInside["NSerrors"]);
2359 if (is_array($filesInside["NSok"])) $infoArray["NSok"]=array_merge($infoArray["NSok"],$filesInside["NSok"]);
2360 $infoArray["locallang"]=$filesInside["locallang"];
2361 $infoArray["classes"]=$filesInside["classes"];
2362 }
2363
2364
2365 if ($info["EM_CONF"]["uploadfolder"]) {
2366 $infoArray["uploadfolder"] = $this->ulFolder($eKey);
2367 if (!@is_dir(PATH_site.$infoArray["uploadfolder"])) {
2368 $infoArray["errors"][]="Error: Upload folder '".$infoArray["uploadfolder"]."' did not exist!";
2369 $infoArray["uploadfolder"] = "";
2370 }
2371 }
2372
2373 if ($info["EM_CONF"]["createDirs"]) {
2374 $infoArray["createDirs"] = array_unique(t3lib_div::trimExplode(",",$info["EM_CONF"]["createDirs"],1));
2375 while(list(,$crDir)=each($infoArray["createDirs"])) {
2376 if (!@is_dir(PATH_site.$crDir)) {
2377 $infoArray["errors"][]="Error: Upload folder '".$crDir."' did not exist!";
2378 }
2379 }
2380 }
2381 return $infoArray;
2382 }
2383
2384 /**
2385 * Analyses the php-scripts of an available extension on server
2386 *
2387 * @param [type] $absPath: ...
2388 * @param [type] $table_class_prefix: ...
2389 * @param [type] $eKey: ...
2390 * @return [type] ...
2391 */
2392 function getClassIndexLocallangFiles($absPath,$table_class_prefix,$eKey) {
2393 $filesInside = $this->removePrefixPathFromList($this->getAllFilesAndFoldersInPath(array(),$absPath,"php,inc"),$absPath);
2394 $out=array();
2395 reset($filesInside);
2396 while(list(,$fileName)=each($filesInside)) {
2397 if (substr($fileName,0,4)!="ext_") {
2398 $baseName = basename($fileName);
2399 if (substr($baseName,0,9)=="locallang" && substr($baseName,-4)==".php") {
2400 $out["locallang"][]=$fileName;
2401 } elseif ($baseName!="conf.php") {
2402 if (filesize($absPath.$fileName)<500*1024) {
2403 $fContent = t3lib_div::getUrl($absPath.$fileName);
2404 unset($reg);
2405 if (ereg("\n[[:space:]]*class[[:space:]]*([[:alnum:]_]+)([[:alnum:][:space:]_]*){",$fContent,$reg)) {
2406 // Find classes:
2407 $classesInFile=array();
2408 $lines = explode(chr(10),$fContent);
2409 reset($lines);
2410 while(list($k,$l)=each($lines)) {
2411 $line = trim($l);
2412 unset($reg);
2413 if (ereg("^class[[:space:]]*([[:alnum:]_]+)([[:alnum:][:space:]_]*){",$line,$reg)) {
2414 $out["classes"][]=$reg[1];
2415 $out["files"][$fileName]["classes"][]=$reg[1];
2416 if (substr($reg[1],0,3)!="ux_" && !t3lib_div::isFirstPartOfStr($reg[1],$table_class_prefix) && strcmp(substr($table_class_prefix,0,-1),$reg[1])) {
2417 $out["NSerrors"]["classname"][]=$reg[1];
2418 } else $out["NSok"]["classname"][]=$reg[1];
2419 }
2420 }
2421 // If class file prefixed "class."....
2422 if (substr($baseName,0,6)=="class.") {
2423 $fI=pathinfo($baseName);
2424 $testName=substr($baseName,6,-(1+strlen($fI["extension"])));
2425 if (substr($testName,0,3)!="ux_" && !t3lib_div::isFirstPartOfStr($testName,$table_class_prefix) && strcmp(substr($table_class_prefix,0,-1),$testName)) {
2426 $out["NSerrors"]["classfilename"][]=$baseName;
2427 } else {
2428 $out["NSok"]["classfilename"][]=$baseName;
2429 if (is_array($out["files"][$fileName]["classes"]) && $this->first_in_array($testName,$out["files"][$fileName]["classes"],1)) {
2430 $out["msg"][]="Class filename '".$fileName."' did contain the class '".$testName."' just as it should.";
2431 } else $out["errors"][]="Class filename '".$fileName."' did NOT contain the class '".$testName."'!";
2432 }
2433 }
2434 //
2435 $XclassParts = explode('if (defined(\'TYPO3_MODE\') && $TYPO3_CONF_VARS[TYPO3_MODE][\'XCLASS\']',$fContent,2);
2436 if (count($XclassParts)==2) {
2437 unset($reg);
2438 ereg('^\[\'([[:alnum:]_\/\.]*)\'\]',$XclassParts[1],$reg);
2439 if ($reg[1]) {
2440 $cmpF = "ext/".$eKey."/".$fileName;
2441 if (!strcmp($reg[1],$cmpF)) {
2442 if (strstr($XclassParts[1],'_once($TYPO3_CONF_VARS[TYPO3_MODE][\'XCLASS\'][\''.$cmpF.'\']);')) {
2443 $out["msg"][]="XCLASS OK in ".$fileName;
2444 } else $out["errors"][]="Couldn't find the include_once statement for XCLASS!";
2445 } else $out["errors"][]="The XCLASS filename-key '".$reg[1]."' was different from '".$cmpF."' which it should have been!";
2446 } else $out["errors"][]="No XCLASS filename-key found in file '".$fileName."'. Maybe a regex coding error here...";
2447 } elseif (!$this->first_in_array("ux_",$out["files"][$fileName]["classes"])) $out["errors"][]="No XCLASS inclusion code found in file '".$fileName."'";
2448 }
2449 }
2450 }
2451 }
2452 }
2453 return $out;
2454 }
2455
2456 /**
2457 * Returns true if the $str is found as the first part of a string in $array
2458 *
2459 * @param [type] $str: ...
2460 * @param [type] $array: ...
2461 * @return [type] ...
2462 */
2463 function first_in_array($str,$array,$caseInsensitive=FALSE) {
2464 if ($caseInsensitive) $str = strtolower($str);
2465 if (is_array($array)) {
2466 reset($array);
2467 while(list(,$cl)=each($array)) {
2468 if ($caseInsensitive) $cl = strtolower($cl);
2469 if (t3lib_div::isFirstPartOfStr($cl,$str)) return 1;
2470 }
2471 }
2472 }
2473
2474 /**
2475 * Reads $confFilePath (a module $conf-file) and returns information on the existence of TYPO3_MOD_PATH definition and MCONF_name
2476 *
2477 * @param [type] $confFilePath: ...
2478 * @return [type] ...
2479 */
2480 function modConfFileAnalysis($confFilePath) {
2481 $lines = explode(chr(10),t3lib_div::getUrl($confFilePath));
2482 $confFileInfo=array();
2483 $confFileInfo["lines"]=$lines;
2484
2485 reset($lines);
2486 while(list($k,$l)=each($lines)) {
2487 $line = trim($l);
2488 unset($reg);
2489 if (ereg('^define[[:space:]]*\([[:space:]]*["\']TYPO3_MOD_PATH["\'][[:space:]]*,[[:space:]]*["\']([[:alnum:]_\/\.]+)["\'][[:space:]]*\)[[:space:]]*;',$line,$reg)) {
2490 $confFileInfo["TYPO3_MOD_PATH"]=array($k,$reg);
2491 }
2492 unset($reg);
2493 if (ereg('^\$MCONF\[["\']?name["\']?\][[:space:]]*=[[:space:]]*["\']([[:alnum:]_]+)["\'];',$line,$reg)) {
2494 $confFileInfo["MCONF_name"]=array($k,$reg);
2495 }
2496 }
2497 return $confFileInfo;
2498 }
2499
2500 /**
2501 * Write new TYPO3_MOD_PATH
2502 *
2503 * @param [type] $confFilePath: ...
2504 * @param [type] $type: ...
2505 * @param [type] $mP: ...
2506 * @return [type] ...
2507 */
2508 function writeTYPO3_MOD_PATH($confFilePath,$type,$mP) {
2509