Fixed open_basedir issues with uploading of files in the whole core. Should work...
[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::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 $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>';
953 $this->content.=$this->doc->section("",$content);
954 $content="";
955
956 $repositoryUrl=$this->repositoryUrl.
957 $this->repTransferParams().
958 $addParams.
959 "&tx_extrep[cmd]=importExtension".
960 "&tx_extrep[uid]=".$extRepUid;
961
962 $fetchData = $this->fetchServerData($repositoryUrl);
963 }
964
965
966 if ($this->importAsType($loc)) {
967 if (is_array($fetchData)) { // There was some data successfully transferred
968 if ($fetchData[0]["extKey"] && is_array($fetchData[0]["FILES"])) {
969 $extKey = $fetchData[0]["extKey"];
970 $EM_CONF=$fetchData[0]["EM_CONF"];
971 if (!$EM_CONF["lockType"] || !strcmp($EM_CONF["lockType"],$loc)) {
972 $res = $this->clearAndMakeExtensionDir($fetchData[0],$loc);
973 if (is_array($res)) {
974 $extDirPath = $res[0];
975 if ($extDirPath && @is_dir($extDirPath) && substr($extDirPath,-1)=="/") {
976
977 $emConfFile = $this->construct_ext_emconf_file($extKey,$EM_CONF);
978 $dirs = $this->extractDirsFromFileList(array_keys($fetchData[0]["FILES"]));
979
980 $res=$this->createDirsInPath($dirs,$extDirPath);
981 if (!$res) {
982 $writeFiles = $fetchData[0]["FILES"];
983 $writeFiles["ext_emconf.php"]["content"] = $emConfFile;
984 $writeFiles["ext_emconf.php"]["content_md5"] = md5($emConfFile);
985
986 while(list($theFile,$fileData)=each($writeFiles)) {
987 t3lib_div::writeFile($extDirPath.$theFile,$fileData["content"]);
988 if (!@is_file($extDirPath.$theFile)) {
989 $content.="Error: File '".$extDirPath.$theFile."' could not be created!!!<br />";
990 } elseif (md5(t3lib_div::getUrl($extDirPath.$theFile)) != $fileData["content_md5"]) {
991 $content.="Error: File '".$extDirPath.$theFile."' MD5 was different from the original files MD5 - so the file is corrupted!<br />";
992 } elseif (TYPO3_OS!="WIN") {
993 #debug($extDirPath.$theFile,1);
994 chmod ($extDirPath.$theFile, 0755);
995 }
996 }
997 if (!$content) {
998 $content="SUCCESS: ".$extDirPath."<br />";
999
1000 // Fix TYPO3_MOD_PATH
1001 $modules = t3lib_div::trimExplode(",",$EM_CONF["module"],1);
1002 if (count($modules)) {
1003 reset($modules);
1004 while(list(,$mD)=each($modules)) {
1005 $confFileName = $extDirPath.$mD."/conf.php";
1006 if (@is_file($confFileName)) {
1007 $content.= $this->writeTYPO3_MOD_PATH($confFileName,$loc,$extKey."/".$mD."/")."<br />";
1008 } else $content.="Error: Couldn't find '".$confFileName."'"."<br />";
1009 }
1010 }
1011 // 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.
1012 // But this order of the code works.... (using the empty Array with type, EMCONF and files hereunder).
1013
1014
1015 // Writing to ext_emconf.php:
1016 $sEMD5A = $this->serverExtensionMD5Array($extKey,array(
1017 "type" => $loc,
1018 "EM_CONF" => array(),
1019 "files" => array()
1020 ));
1021 $EM_CONF["_md5_values_when_last_written"] = serialize($sEMD5A);
1022 $emConfFile = $this->construct_ext_emconf_file($extKey,$EM_CONF);
1023 t3lib_div::writeFile($extDirPath."ext_emconf.php",$emConfFile);
1024
1025 $content.="ext_emconf.php: ".$extDirPath."ext_emconf.php<br />";
1026 $content.="Type: ".$loc."<br />";
1027 if (t3lib_extMgm::isLoaded($extKey)) {
1028 if ($this->removeCacheFiles()) {
1029 $content.="Cache-files are removed and will be re-written upon next hit<br />";
1030 }
1031
1032 list($new_list)=$this->getInstalledExtensions();
1033 $content.=$this->updatesForm($extKey,$new_list[$extKey],1,"index.php?CMD[showExt]=".$extKey."&SET[singleDetails]=info");
1034 }
1035
1036 if (is_array($fetchData[0]["_MESSAGES"])) {
1037 $content.="<HR><strong>Messages from repository:</strong><br /><br />".implode("<br />",$fetchData[0]["_MESSAGES"]);
1038 }
1039 }
1040 } else $content=$res;
1041 } else $content = "Error: The extension path '".$extDirPath."' was different than expected...";
1042 } else $content=$res;
1043 } else $content = "Error: The extension can only be installed in the path ".$this->typePaths[$EM_CONF["lockType"]]." (lockType=".$EM_CONF["lockType"].")";
1044 } else $content="Error: No extension key!!! Why? - nobody knows... (Or no files in the file-array...)";
1045 } else $content="Error: The datatransfer did not succeed...";
1046 } else $content="Error: Installation is not allowed in this path (".$this->typePaths[$loc].")";
1047
1048 $this->content.=$this->doc->section("Extension copied to server",$content,0,1);
1049 }
1050
1051 /**
1052 * Display extensions details.
1053 *
1054 * @param [type] $extKey: ...
1055 * @return [type] ...
1056 */
1057 function showExtDetails($extKey) {
1058 global $TYPO3_LOADED_EXT;
1059
1060 list($list,$cat)=$this->getInstalledExtensions();
1061 $absPath = $this->getExtPath($extKey,$list[$extKey]);
1062
1063 // Check updateModule:
1064 if (@is_file($absPath.'class.ext_update.php')) {
1065 require_once($absPath.'class.ext_update.php');
1066 $updateObj = new ext_update;
1067 if (!$updateObj->access()) {
1068 unset($this->MOD_MENU["singleDetails"]['updateModule']);
1069 }
1070 } else {
1071 unset($this->MOD_MENU["singleDetails"]['updateModule']);
1072 }
1073
1074 // Function menu here:
1075 $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>'.
1076 t3lib_BEfunc::getFuncMenu(0,"SET[singleDetails]",$this->MOD_SETTINGS["singleDetails"],$this->MOD_MENU["singleDetails"],"","&CMD[showExt]=".$extKey)." &nbsp; &nbsp; ".
1077 '<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>';
1078 $this->content.=$this->doc->section("",$content);
1079
1080 if ($list[$extKey]) {
1081 if (($this->CMD["remove"] || $this->CMD["load"]) && !in_array($extKey,$this->requiredExt)) {
1082 if (t3lib_extMgm::isLocalconfWritable()) {
1083 if ($this->CMD["remove"]) {
1084 $newExtList=$this->removeExtFromList($extKey,$list);
1085 } else {
1086 $newExtList=$this->addExtToList($extKey,$list);
1087 }
1088 if ($newExtList!=-1) {
1089 $updates="";
1090 if ($this->CMD["load"]) {
1091 $updates=$this->updatesForm($extKey,$list[$extKey],1,"",'<input type="hidden" name="_do_install" value="1"><input type="hidden" name="_clrCmd" value="'.$this->CMD["clrCmd"].'">');
1092 if ($updates) {
1093 $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;
1094 $this->content.=$this->doc->section("Installing ".$this->extensionTitleIconHeader($extKey,$list[$extKey]).strtoupper(": Database needs to be updated"),$updates,1,1,1,1);
1095 }
1096 # $updates.=$this->checkDBupdates($extKey,$list[$extKey]);
1097 # $updates.= $this->checkClearCache($extKey,$list[$extKey]);
1098 # $updates.= $this->checkUploadFolder($extKey,$list[$extKey]);
1099 /* if ($updates) {
1100 $updates='
1101 Before the extension can be installed the database needs to be updated with new tables or fields. Please select which operations to perform:
1102 </form><form action="'.t3lib_div::linkThisScript().'" method="post">'.$updates.'
1103 <br /><input type="submit" name="write" value="Update database and install extension">
1104 <input type="hidden" name="_do_install" value="1">
1105 ';
1106 $this->content.=$this->doc->section("Installing ".$this->extensionTitleIconHeader($extKey,$list[$extKey]).strtoupper(": Database needs to be updated"),$updates,1,1,1);
1107 }
1108 */ } elseif ($this->CMD["remove"]) {
1109 $updates.= $this->checkClearCache($extKey,$list[$extKey]);
1110 if ($updates) {
1111 $updates='
1112 </form><form action="'.t3lib_div::linkThisScript().'" method="post">'.$updates.'
1113 <br /><input type="submit" name="write" value="Remove extension">
1114 <input type="hidden" name="_do_install" value="1">
1115 <input type="hidden" name="_clrCmd" value="'.$this->CMD["clrCmd"].'">
1116 ';
1117 $this->content.=$this->doc->section("Installing ".$this->extensionTitleIconHeader($extKey,$list[$extKey]).strtoupper(": Database needs to be updated"),$updates,1,1,1,1);
1118 }
1119 }
1120 if (!$updates || t3lib_div::GPvar("_do_install")) {
1121 $this->writeNewExtensionList($newExtList);
1122
1123
1124 /*
1125 $content = $newExtList;
1126 $this->content.=$this->doc->section("Active status","
1127 <strong>Extension list is written to localconf.php!</strong><br />
1128 It may be necessary to reload TYPO3 depending on the change.<br />
1129
1130 <em>(".$content.")</em>",0,1);
1131 */
1132 if ($this->CMD["clrCmd"] || t3lib_div::GPvar("_clrCmd")) {
1133 $vA = array("CMD"=>"");
1134 } else {
1135 $vA = array("CMD"=>Array("showExt"=>$extKey));
1136 }
1137 header("Location: ".t3lib_div::linkThisScript($vA));
1138 }
1139 }
1140 } else {
1141 $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);
1142 }
1143 } elseif ($this->CMD["downloadFile"] && !in_array($extKey,$this->requiredExt)) {
1144 $dlFile = $this->CMD["downloadFile"];
1145 if (t3lib_div::isFirstPartOfStr($dlFile,PATH_site) && t3lib_div::isFirstPartOfStr($dlFile,$absPath) && @is_file($dlFile)) {
1146 $mimeType = "application/octet-stream";
1147 Header("Content-Type: ".$mimeType);
1148 Header("Content-Disposition: attachment; filename=".basename($dlFile));
1149 echo t3lib_div::getUrl($dlFile);
1150 exit;
1151 } else die("error....");
1152 } elseif ($this->CMD["editFile"] && !in_array($extKey,$this->requiredExt)) {
1153 $editFile = $this->CMD["editFile"];
1154 if (t3lib_div::isFirstPartOfStr($editFile,PATH_site) && t3lib_div::isFirstPartOfStr($editFile,$absPath)) { // Paranoia...
1155
1156 $fI=t3lib_div::split_fileref($editFile);
1157 if (@is_file($editFile) && t3lib_div::inList($this->editTextExtensions,$fI["fileext"])) {
1158 if (filesize($editFile)<($this->kbMax*1024)) {
1159 $outCode="";
1160 $info="";
1161 $submittedContent = t3lib_div::GPvar("edit",1);
1162 $saveFlag=0;
1163 if(isset($submittedContent["file"])) {
1164 $info.=$GLOBALS["TBE_TEMPLATE"]->rfw("<br /><strong>File saved.</strong>")."<br />";
1165 $oldFileContent = t3lib_div::getUrl($editFile);
1166 $info.='MD5: <b>'.md5(str_replace(chr(13),"",$oldFileContent)).'</b> (Previous File)<br />';
1167 if (!$GLOBALS["TYPO3_CONF_VARS"]["EXT"]["noEdit"]) {
1168 t3lib_div::writeFile($editFile,$submittedContent["file"]);
1169 $saveFlag=1;
1170 } else die("Saving disabled!!!");
1171 }
1172
1173 $fileContent = t3lib_div::getUrl($editFile);
1174 $numberOfRows = 35;
1175
1176 $outCode.='File: <b>'.substr($editFile,strlen($absPath)).'</b> ('.t3lib_div::formatSize(filesize($editFile)).')<br />';
1177 $info.='MD5: <b>'.md5(str_replace(chr(13),"",$fileContent)).'</b> (File)<br />';
1178 if($saveFlag) $info.='MD5: <b>'.md5(str_replace(chr(13),"",$submittedContent["file"])).'</b> (Saved)<br />';
1179 $outCode.='<textarea name="edit[file]" rows="'.$numberOfRows.'" wrap="off"'.$this->doc->formWidthText(48,"width:98%;height:70%","off").'>'.t3lib_div::formatForTextarea($fileContent).'</textarea>';
1180 $outCode.='<input type="Hidden" name="edit[filename]" value="'.$editFile.'">';
1181 $outCode.='<input type="Hidden" name="CMD[editFile]" value="'.htmlspecialchars($editFile).'">';
1182 $outCode.='<input type="Hidden" name="CMD[showExt]" value="'.$extKey.'">';
1183 $outCode.=$info;
1184 if (!$GLOBALS["TYPO3_CONF_VARS"]["EXT"]["noEdit"]) {
1185 $outCode.='<br /><input type="submit" name="save_file" value="Save file">';
1186 } else $outCode.=$GLOBALS["TBE_TEMPLATE"]->rfw('<br />[SAVING IS DISABLED - can be enabled by the TYPO3_CONF_VARS[EXT][noEdit]-flag] ');
1187 $outCode.='<input type="submit" name="cancel" value="Cancel" onClick="document.location=\'index.php?CMD[showExt]='.$extKey.'\';return false;">';
1188 $theOutput.=$this->doc->spacer(15);
1189 $theOutput.=$this->doc->section("Edit file:","",0,1);
1190 $theOutput.=$this->doc->sectionEnd().$outCode;
1191 $this->content.=$theOutput;
1192 } else {
1193 $theOutput.=$this->doc->spacer(15);
1194 $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.');
1195 }
1196 }
1197 } else die("Fatal Edit error: File '".$editFile."' was not inside the correct path of the TYPO3 Extension!");
1198 } else { // MAIN:
1199
1200 switch((string)$this->MOD_SETTINGS["singleDetails"]) {
1201 case "info":
1202 // Loaded / Not loaded:
1203 if (!in_array($extKey,$this->requiredExt)) {
1204 if ($TYPO3_LOADED_EXT[$extKey]) {
1205 $content = '<strong>The extension is installed (loaded and running)!</strong><br />'.
1206 '<a href="index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1">Click here to remove the extension: '.$this->removeButton().'</a>';
1207 } else {
1208 $content = 'The extension is <strong>not</strong> installed yet.<br />'.
1209 '<a href="index.php?CMD[showExt]='.$extKey.'&CMD[load]=1">Click here to install the extension: '.$this->installButton().'</a>';
1210 }
1211 } else {
1212 $content = 'This extension is entered in the TYPO3_CONF_VARS[SYS][requiredExt] list and is therefore always loaded.';
1213 }
1214 $this->content.=$this->doc->spacer(10);
1215 $this->content.=$this->doc->section("Active status:",$content,0,1);
1216
1217 if (t3lib_extMgm::isLoaded($extKey)) {
1218 $updates=$this->updatesForm($extKey,$list[$extKey]);
1219 if ($updates) {
1220 $this->content.=$this->doc->spacer(10);
1221 $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);
1222 }
1223 }
1224
1225 // Show details:
1226 $content = $this->extInformationArray($extKey,$list[$extKey]);
1227 $this->content.=$this->doc->spacer(10);
1228 $this->content.=$this->doc->section("Details:",$content,0,1);
1229
1230 // Config:
1231 if (@is_file($absPath."ext_conf_template.txt")) {
1232 $this->content.=$this->doc->spacer(10);
1233 $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);
1234 $this->tsStyleConfigForm($extKey,$list[$extKey]);
1235 }
1236 break;
1237 case "upload":
1238 $TER_CMD = t3lib_div::GPvar("TER_CMD",1);
1239 if (is_array($TER_CMD)) {
1240 $msg = $this->processRepositoryReturnData($TER_CMD);
1241 if ($msg) {
1242 $this->content.=$this->doc->section("Local update of EM_CONF",$msg,0,1,1);
1243 $this->content.=$this->doc->spacer(10);
1244 }
1245 // Must reload this, because EM_CONF information has been updated!
1246 list($list,$cat)=$this->getInstalledExtensions();
1247 }
1248
1249
1250 // Upload:
1251 if (substr($extKey,0,5)!="user_") {
1252 $content = $this->getRepositoryUploadForm($extKey,$list[$extKey]);
1253 $eC=0;
1254 } else {
1255 $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 />
1256 You are encouraged to register a unique extension key for all your TYPO3 extensions - even if the project is current not official.";
1257 $eC=2;
1258 }
1259 $this->content.=$this->doc->section("Upload extension to repository",$content,0,1,$eC);
1260 break;
1261 case "download":
1262 break;
1263 case "backup":
1264 $content = $this->extBackup($extKey,$list[$extKey]);
1265 $this->content.=$this->doc->section("Backup",$content,0,1);
1266
1267 $content = $this->extDelete($extKey,$list[$extKey]);
1268 $this->content.=$this->doc->section("Delete",$content,0,1);
1269
1270 $content = $this->extUpdateEMCONF($extKey,$list[$extKey]);
1271 $this->content.=$this->doc->section("Update EM_CONF",$content,0,1);
1272
1273 $content = $this->extMakeNewFromFramework($extKey,$list[$extKey]);
1274 if ($content) $this->content.=$this->doc->section("Make new extension",$content,0,1);
1275 break;
1276 case "dump":
1277 $this->extDumpTables($extKey,$list[$extKey]);
1278 break;
1279 case "edit":
1280 // Files:
1281 $content = $this->getFileListOfExtension($extKey,$list[$extKey]);
1282 $this->content.=$this->doc->section("Extension files",$content,0,1);
1283 break;
1284 case "updateModule":
1285 $this->content.=$this->doc->section("Update:",$updateObj->main(),0,1);
1286 break;
1287 }
1288 }
1289 }
1290 }
1291
1292 /**
1293 * [Describe function...]
1294 *
1295 * @param [type] $extKey: ...
1296 * @param [type] $info: ...
1297 * @param [type] $notSilent: ...
1298 * @param [type] $script: ...
1299 * @param [type] $addFields: ...
1300 * @return [type] ...
1301 */
1302 function updatesForm($extKey,$info,$notSilent=0,$script="",$addFields="") {
1303 $script = $script ? $script : t3lib_div::linkThisScript();
1304 $updates.=$this->checkDBupdates($extKey,$info);
1305 $uCache = $this->checkClearCache($extKey,$info);
1306 if ($notSilent) $updates.= $uCache;
1307 $updates.= $this->checkUploadFolder($extKey,$info);
1308
1309 $absPath = $this->getExtPath($extKey,$info);
1310 if ($notSilent && @is_file($absPath."ext_conf_template.txt")) {
1311 $cForm=$this->tsStyleConfigForm($extKey,$info,1,$script,$updates.$addFields."<br />");
1312 }
1313
1314 if ($updates || $cForm) {
1315 if ($cForm) {
1316 $updates = '</form>'.$cForm.'<form>';
1317 } else {
1318 $updates='</form><form action="'.$script.'" method="post">'.$updates.$addFields.'
1319 <br /><input type="submit" name="write" value="Make updates">
1320 ';
1321 }
1322 }
1323 return $updates;
1324 }
1325
1326 /**
1327 * Dumping static tables and table/fields structures...
1328 *
1329 * @param [type] $eKey: ...
1330 * @param [type] $info: ...
1331 * @return [type] ...
1332 */
1333 function extDumpTables($eKey,$info) {
1334 // Get dbInfo which holds the structure known from the tables.sql file
1335 $techInfo=$this->makeDetailedExtensionAnalysis($eKey,$info);
1336 $absPath = $this->getExtPath($eKey,$info);
1337
1338 #debug($techInfo);
1339 if (is_array($techInfo["static"])) {
1340 if ($this->CMD["writeSTATICdump"]) {
1341 $writeFile = $absPath."ext_tables_static+adt.sql";
1342 if (@is_file($writeFile)) {
1343 $dump_static = $this->dumpStaticTables(implode(",",$techInfo["static"]));
1344 t3lib_div::writeFile($writeFile,$dump_static);
1345 $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);
1346 }
1347 } else {
1348 $msg = "Dumping table content for static tables:<br />";
1349 $msg.= "<br />".implode("<br />",$techInfo["static"])."<br />";
1350
1351 // ... then feed that to this function which will make new CREATE statements of the same fields but based on the current database content.
1352 $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);
1353 $this->content.=$this->doc->spacer(20);
1354 }
1355 }
1356
1357 if (is_array($techInfo["dump_tf"])) {
1358 $dump_tf_array = $this->getTableAndFieldStructure($techInfo["dump_tf"]);
1359 $dump_tf = $this->dumpTableAndFieldStructure($dump_tf_array);
1360 if ($this->CMD["writeTFdump"]) {
1361 $writeFile = $absPath."ext_tables.sql";
1362 if (@is_file($writeFile)) {
1363 t3lib_div::writeFile($writeFile,$dump_tf);
1364 $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);
1365 }
1366 } else {
1367 $msg = "Dumping current database structure for:<br />";
1368 if (is_array($techInfo["tables"])) {
1369 $msg.= "<br /><strong>Tables:</strong><br />".implode("<br />",$techInfo["tables"])."<br />";
1370 }
1371 if (is_array($techInfo["fields"])) {
1372 $msg.= "<br /><strong>Solo-fields:</strong><br />".implode("<br />",$techInfo["fields"])."<br />";
1373 }
1374
1375 // ... then feed that to this function which will make new CREATE statements of the same fields but based on the current database content.
1376 $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>
1377 <pre>'.htmlspecialchars($dump_tf).'</pre>',0,1);
1378
1379
1380 $details = ' This dump is based on two factors:<br />
1381 <ul>
1382 <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>
1383 <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>
1384 </ul>
1385 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 />';
1386 $this->content.=$this->doc->section("",$details);
1387 }
1388 }
1389 }
1390
1391 /**
1392 * Delete extension...
1393 *
1394 * @param [type] $eKey: ...
1395 * @param [type] $info: ...
1396 * @return [type] ...
1397 */
1398 function extDelete($eKey,$info) {
1399 $absPath = $this->getExtPath($eKey,$info);
1400 if (t3lib_extMgm::isLoaded($eKey)) {
1401 return "This extension is currently installed (loaded and active) and so cannot be deleted!";
1402 } elseif (t3lib_div::inList("G,L",$info["type"])) {
1403 if ($this->CMD["doDelete"] && !strcmp($absPath,$this->CMD["absPath"])) {
1404 $res = $this->removeExtDirectory($absPath);
1405 @rmdir($absPath);
1406 if ($res) return "ERROR: Could not remove extension directory '".$absPath."'";
1407 return "Removed extension in path '".$absPath."'!";
1408 } else {
1409 $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)."';}";
1410 $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>';
1411 $content.= '<br /><br />(Maybe you should make a backup first, see above.)';
1412 return $content;
1413 }
1414 } else return "Extension is not a global or local extension and cannot be removed.";
1415 }
1416
1417 /**
1418 * Update extension EM_CONF...
1419 *
1420 * @param [type] $eKey: ...
1421 * @param [type] $info: ...
1422 * @return [type] ...
1423 */
1424 function extUpdateEMCONF($eKey,$info) {
1425 $absPath = $this->getExtPath($eKey,$info);
1426 if ($this->CMD["doUpdateEMCONF"]) {
1427 return $this->updateLocalEM_CONF($eKey,$info);
1428 } else {
1429 $onClick="if (confirm('Are you sure you want to update EM_CONF?')) {document.location='index.php?CMD[showExt]=".$eKey."&CMD[doUpdateEMCONF]=1';}";
1430 $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>';
1431 $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 />
1432 Updating this file will first of all reset this registration.';
1433 return $content;
1434 }
1435 }
1436
1437 /**
1438 * make from framework
1439 *
1440 * @param [type] $eKey: ...
1441 * @param [type] $info: ...
1442 * @return [type] ...
1443 */
1444 function extMakeNewFromFramework($eKey,$info) {
1445 $absPath = $this->getExtPath($eKey,$info);
1446 if (isset($this->MOD_MENU["function"][4]) && @is_file($absPath."doc/wizard_form.dat")) {
1447 $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 />";
1448 $content.= '</form>
1449 <form action="index.php?SET[function]=4" method="post">
1450 <input type="submit" value="Start new">
1451 <input type="hidden" name="tx_extrep[wizArray_ser]" value="'.base64_encode(t3lib_div::getUrl($absPath."doc/wizard_form.dat")).'">
1452 </form>
1453 <form>';
1454 return $content;
1455 }
1456 }
1457
1458 /**
1459 * Makes Backup files
1460 *
1461 * @param [type] $eKey: ...
1462 * @param [type] $info: ...
1463 * @return [type] ...
1464 */
1465 function extBackup($eKey,$info) {
1466 $uArr = $this->makeUploadArray($eKey,$info);
1467 if (is_array($uArr)) {
1468 $local_gzcompress = $this->gzcompress && !$this->CMD["dontCompress"];
1469 $backUpData = $this->makeUploadDataFromArray($uArr,intval($local_gzcompress));
1470 $filename="T3X_".$eKey."-".str_replace(".","_",$info["EM_CONF"]["version"]).($local_gzcompress?"-z":"").".t3x";
1471 if (intval($this->CMD["doBackup"])==1) {
1472 #die(md5($backUpData));
1473
1474 $mimeType = "application/octet-stream";
1475 Header("Content-Type: ".$mimeType);
1476 Header("Content-Disposition: attachment; filename=".$filename);
1477
1478 // New headers suggested by Xin:
1479 // 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.
1480 /* header('Content-Type: application/force-download');
1481 header('Content-Length: '.strlen($backUpData));
1482
1483 header('Content-Disposition: attachment; filename='.$filename);
1484 header('Content-Description: File Transfer');
1485 header('Content-Transfer-Encoding: binary');
1486 */
1487
1488 // 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.
1489
1490 echo $backUpData;
1491 exit;
1492 } elseif ($this->CMD["dumpTables"]) {
1493 $filename="T3X_".$eKey;
1494 $cTables = count(explode(",",$this->CMD["dumpTables"]));
1495 if ($cTables>1) {
1496 $filename.='-'.$cTables.'tables';
1497 } else {
1498 $filename.='-'.$this->CMD["dumpTables"];
1499 }
1500 $filename.="+adt.sql";
1501
1502 $mimeType = "application/octet-stream";
1503 Header("Content-Type: ".$mimeType);
1504 Header("Content-Disposition: attachment; filename=".$filename);
1505 echo $this->dumpStaticTables($this->CMD["dumpTables"]);
1506 exit;
1507 } else {
1508 $techInfo = $this->makeDetailedExtensionAnalysis($eKey,$info);
1509 // if ($techInfo["tables"]||$techInfo["static"]||$techInfo["fields"]) {
1510 #debug($techInfo);
1511 $lines=array();
1512 $lines[]='<tr class="bgColor5"><td colspan=2><strong>Make selection:</strong></td></tr>';
1513 $lines[]='<tr class="bgColor4"><td><strong>Extension files:</strong></td><td>'.
1514 '<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 />'.
1515 ($this->gzcompress ? '<br /><a href="index.php?CMD[doBackup]=1&CMD[dontCompress]=1&CMD[showExt]='.$eKey.'">(Click here to download extension without compression.)</a>':'').
1516 '</td></tr>';
1517
1518 if (is_array($techInfo["tables"])) { $lines[]='<tr class="bgColor4"><td><strong>Data tables:</strong></td><td>'.$this->extBackup_dumpDataTablesLine($techInfo["tables"],$eKey).'</td></tr>'; }
1519 if (is_array($techInfo["static"])) { $lines[]='<tr class="bgColor4"><td><strong>Static tables:</strong></td><td>'.$this->extBackup_dumpDataTablesLine($techInfo["static"],$eKey).'</td></tr>'; }
1520
1521 $content='<table border=0 cellpadding=2 cellspacing=2>'.implode("",$lines).'</table>';
1522 return $content;
1523 }
1524 } else die("Error...");
1525 }
1526
1527 /**
1528 * [Describe function...]
1529 *
1530 * @param [type] $tablesArray: ...
1531 * @param [type] $eKey: ...
1532 * @return [type] ...
1533 */
1534 function extBackup_dumpDataTablesLine($tablesArray,$eKey) {
1535 reset($tablesArray);
1536 $tables=array();
1537 $tablesNA=array();
1538 while(list(,$tN)=each($tablesArray)) {
1539 $q="SELECT count(*) FROM ".$tN;
1540 $res = @mysql(TYPO3_db,$q);
1541 if (!mysql_error()) {
1542 $row=mysql_fetch_row($res);
1543 $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>";
1544 } else {
1545 $tablesNA[$tN]='<tr><td>&nbsp;</td><td>'.$tN."</td><td>&nbsp;</td><td>Did not exist.</td></tr>";
1546 }
1547 }
1548 $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...
1549 if (count($tables)) {
1550 $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;
1551 } else $label = 'Nothing to dump...<br /><br />'.$label;
1552 return $label;
1553 }
1554
1555 /**
1556 * Prints a table with extension information in it.
1557 *
1558 * @param [type] $eKey: ...
1559 * @param [type] $info: ...
1560 * @param [type] $remote: ...
1561 * @return [type] ...
1562 */
1563 function extInformationArray($eKey,$info,$remote=0) {
1564 $lines=array();
1565 $lines[]='<tr class="bgColor5"><td colspan=2><strong>General information:</strong></td>'.$this->helpCol("").'</tr>';
1566 $lines[]='<tr class="bgColor4"><td>Title:</td><td>'.$info["EM_CONF"]["_icon"].$info["EM_CONF"]["title"].'</td>'.$this->helpCol("title").'</tr>';
1567 $lines[]='<tr class="bgColor4"><td>Description:</td><td>'.nl2br(htmlspecialchars($info["EM_CONF"]["description"])).'</td>'.$this->helpCol("description").'</tr>';
1568 $lines[]='<tr class="bgColor4"><td>Author:</td><td>'.
1569 $this->wrapEmail($info["EM_CONF"]["author"].
1570 ($info["EM_CONF"]["author_email"]?htmlspecialchars(" <".$info["EM_CONF"]["author_email"].">"):""),$info["EM_CONF"]["author_email"]).
1571 ($info["EM_CONF"]["author_company"]?", ".$info["EM_CONF"]["author_company"]:"").
1572 '</td>'.$this->helpCol("description").'</tr>';
1573
1574 $lines[]='<tr class="bgColor4"><td>Version:</td><td>'.$info["EM_CONF"]["version"].'</td>'.$this->helpCol("version").'</tr>';
1575 $lines[]='<tr class="bgColor4"><td>Category:</td><td>'.$this->categories[$info["EM_CONF"]["category"]].'</td>'.$this->helpCol("category").'</tr>';
1576 $lines[]='<tr class="bgColor4"><td>State:</td><td>'.$this->states[$info["EM_CONF"]["state"]].'</td>'.$this->helpCol("state").'</tr>';
1577 $lines[]='<tr class="bgColor4"><td>Shy?</td><td>'.($info["EM_CONF"]["shy"]?"Yes":"").'</td>'.$this->helpCol("shy").'</tr>';
1578 $lines[]='<tr class="bgColor4"><td>Internal?</td><td>'.($info["EM_CONF"]["internal"]?"Yes":"").'</td>'.$this->helpCol("internal").'</tr>';
1579
1580 $lines[]='<tr class="bgColor4"><td>Dependencies:</td><td>'.$info["EM_CONF"]["dependencies"].'</td>'.$this->helpCol("dependencies").'</tr>';
1581 if (!$remote) {
1582 $lines[]='<tr class="bgColor4"><td>Conflicts:</td><td>'.$info["EM_CONF"]["conflicts"].'</td>'.$this->helpCol("conflicts").'</tr>';
1583 $lines[]='<tr class="bgColor4"><td>Priority:</td><td>'.$info["EM_CONF"]["priority"].'</td>'.$this->helpCol("priority").'</tr>';
1584 $lines[]='<tr class="bgColor4"><td>Clear cache?</td><td>'.($info["EM_CONF"]["clearCacheOnLoad"]?"Yes":"").'</td>'.$this->helpCol("clearCacheOnLoad").'</tr>';
1585 $lines[]='<tr class="bgColor4"><td>Includes modules:</td><td>'.$info["EM_CONF"]["module"].'</td>'.$this->helpCol("module").'</tr>';
1586 }
1587 $lines[]='<tr class="bgColor4"><td>Lock Type?</td><td>'.($info["EM_CONF"]["lockType"]?$info["EM_CONF"]["lockType"]:"").'</td>'.$this->helpCol("lockType").'</tr>';
1588 $lines[]='<tr class="bgColor4"><td>Modifies tables:</td><td>'.$info["EM_CONF"]["modify_tables"].'</td>'.$this->helpCol("modify_tables").'</tr>';
1589
1590 $lines[]='<tr class="bgColor4"><td>Private?</td><td>'.($info["EM_CONF"]["private"]?"Yes":"").'</td>'.$this->helpCol("private").'</tr>';
1591 if (!$remote) $lines[]='<tr class="bgColor4"><td>Download password:</td><td>'.$info["EM_CONF"]["download_password"].'</td>'.$this->helpCol("download_password").'</tr>';
1592
1593 // Installation status:
1594 $lines[]='<tr><td>&nbsp;</td><td></td>'.$this->helpCol("").'</tr>';
1595 $lines[]='<tr class="bgColor5"><td colspan=2><strong>Installation status:</strong></td>'.$this->helpCol("").'</tr>';
1596 if (!$remote) {
1597 $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>';
1598 $lines[]='<tr class="bgColor4"><td>Double installs?</td><td>'.$this->extInformationArray_dbInst($info["doubleInstall"],$info["type"]).'</td>'.$this->helpCol("doubleInstall").'</tr>';
1599 }
1600 if (is_array($info["files"])) {
1601 sort($info["files"]);
1602 $lines[]='<tr class="bgColor4"><td>Root files:</td><td>'.implode("<br />",$info["files"]).'</td>'.$this->helpCol("rootfiles").'</tr>';
1603 }
1604
1605 if (!$remote) {
1606 $techInfo = $this->makeDetailedExtensionAnalysis($eKey,$info,1);
1607 } else $techInfo = $info["_TECH_INFO"];
1608 #debug($techInfo);
1609
1610 if ($techInfo["tables"]||$techInfo["static"]||$techInfo["fields"]) {
1611 if (!$remote && t3lib_extMgm::isLoaded($eKey)) {
1612 $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!":"").
1613 ($techInfo["static_error"]?"<strong>Static table error!</strong><br />The static tables are missing or empty!":""));
1614 } else {
1615 $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!";
1616 }
1617 }
1618
1619 $lines[]='<tr class="bgColor4"><td>Database requirements:</td><td>'.$this->extInformationArray_dbReq($techInfo,1).'</td>'.$this->helpCol("dbReq").'</tr>';
1620 if (!$remote) $lines[]='<tr class="bgColor4"><td>Database status:</td><td>'.$tableStatus.'</td>'.$this->helpCol("dbStatus").'</tr>';
1621 $lines[]='<tr class="bgColor4"><td>Flags:</td><td>'.(is_array($techInfo["flags"])?implode("<br />",$techInfo["flags"]):"").'</td>'.$this->helpCol("flags").'</tr>';
1622 $lines[]='<tr class="bgColor4"><td>Config template?</td><td>'.($techInfo["conf"]?"Yes":"").'</td>'.$this->helpCol("conf").'</tr>';
1623 $lines[]='<tr class="bgColor4"><td>TypoScript files:</td><td>'.(is_array($techInfo["TSfiles"])?implode("<br />",$techInfo["TSfiles"]):"").'</td>'.$this->helpCol("TSfiles").'</tr>';
1624 $lines[]='<tr class="bgColor4"><td>Language files:</td><td>'.(is_array($techInfo["locallang"])?implode("<br />",$techInfo["locallang"]):"").'</td>'.$this->helpCol("locallang").'</tr>';
1625 $lines[]='<tr class="bgColor4"><td>Upload folder:</td><td>'.($techInfo["uploadfolder"]?$techInfo["uploadfolder"]:"").'</td>'.$this->helpCol("uploadfolder").'</tr>';
1626 $lines[]='<tr class="bgColor4"><td>Create directories:</td><td>'.(is_array($techInfo["createDirs"])?implode("<br />",$techInfo["createDirs"]):"").'</td>'.$this->helpCol("createDirs").'</tr>';
1627 $lines[]='<tr class="bgColor4"><td>Module names:</td><td>'.(is_array($techInfo["moduleNames"])?implode("<br />",$techInfo["moduleNames"]):"").'</td>'.$this->helpCol("moduleNames").'</tr>';
1628 $lines[]='<tr class="bgColor4"><td>Class names:</td><td>'.(is_array($techInfo["classes"])?implode("<br />",$techInfo["classes"]):"").'</td>'.$this->helpCol("classNames").'</tr>';
1629 $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>';
1630 $lines[]='<tr class="bgColor4"><td>Naming errors:</td><td>'.(is_array($techInfo["NSerrors"])?
1631 (!t3lib_div::inList($this->nameSpaceExceptions,$eKey)?t3lib_div::view_array($techInfo["NSerrors"]):$GLOBALS["TBE_TEMPLATE"]->dfw("[exception]"))
1632 :"").'</td>'.$this->helpCol("NSerrors").'</tr>';
1633
1634
1635 if (!$remote) {
1636 $currentMd5Array = $this->serverExtensionMD5Array($eKey,$info);
1637 $affectedFiles="";
1638
1639 $msgLines=array();
1640 # $msgLines[] = "Files: ".count($currentMd5Array);
1641 if (strcmp($info["EM_CONF"]["_md5_values_when_last_written"],serialize($currentMd5Array))) {
1642 $msgLines[] = $GLOBALS["TBE_TEMPLATE"]->rfw("<br /><strong>A difference between the originally installed version and the current was detected!</strong>");
1643 $affectedFiles = $this->findMD5ArrayDiff($currentMd5Array,unserialize($info["EM_CONF"]["_md5_values_when_last_written"]));
1644 if (count($affectedFiles)) $msgLines[] = "<br /><strong>Modified files:</strong><br />".$GLOBALS["TBE_TEMPLATE"]->rfw(implode("<br />",$affectedFiles));
1645 }
1646 $lines[]='<tr class="bgColor4"><td>Files changed?</td><td>'.implode("<br />",$msgLines).'</td>'.$this->helpCol("filesChanged").'</tr>';
1647 }
1648
1649 return '<table border=0 cellpadding=1 cellspacing=2>'.implode("",$lines).'</table>';
1650 }
1651
1652 /**
1653 * [Describe function...]
1654 *
1655 * @param [type] $techInfo: ...
1656 * @param [type] $tableHeader: ...
1657 * @return [type] ...
1658 */
1659 function extInformationArray_dbReq($techInfo,$tableHeader=0) {
1660 return nl2br(trim((is_array($techInfo["tables"])?($tableHeader?"\n\n<strong>Tables:</strong>\n":"").implode("\n",$techInfo["tables"]):"").
1661 (is_array($techInfo["static"])?"\n\n<strong>Static tables:</strong>\n".implode("\n",$techInfo["static"]):"").
1662 (is_array($techInfo["fields"])?"\n\n<strong>Additional fields:</strong>\n".implode("<HR>",$techInfo["fields"]):"")));
1663 }
1664
1665 /**
1666 * [Describe function...]
1667 *
1668 * @param [type] $dbInst: ...
1669 * @param [type] $current: ...
1670 * @return [type] ...
1671 */
1672 function extInformationArray_dbInst($dbInst,$current) {
1673 if (strlen($dbInst)>1) {
1674 $others=array();
1675 for($a=0;$a<strlen($dbInst);$a++) {
1676 if (substr($dbInst,$a,1)!=$current) {
1677 $others[]="'".$this->typeLabels[substr($dbInst,$a,1)]."'";
1678 }
1679 }
1680 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.");
1681 } else return "";
1682 }
1683
1684 /**
1685 * [Describe function...]
1686 *
1687 * @param [type] $str: ...
1688 * @param [type] $email: ...
1689 * @return [type] ...
1690 */
1691 function wrapEmail($str,$email) {
1692 if ($email) {
1693 $str='<a href="mailto:'.$email.'">'.$str.'</a>';
1694 }
1695 return $str;
1696 }
1697
1698 /**
1699 * [Describe function...]
1700 *
1701 * @param [type] $key: ...
1702 * @return [type] ...
1703 */
1704 function helpCol($key) {
1705 global $BE_USER;
1706 if ($BE_USER->uc["edit_showFieldHelp"]) {
1707 $hT = trim(t3lib_BEfunc::helpText($this->descrTable,"emconf_".$key,$this->doc->backPath));
1708 return '<td>'.($hT?$hT:t3lib_BEfunc::helpTextIcon($this->descrTable,"emconf_".$key,$this->doc->backPath)).'</td>';
1709 }
1710 }
1711
1712 /**
1713 * Prints the upload form for extensions
1714 *
1715 * @param [type] $eKey: ...
1716 * @param [type] $info: ...
1717 * @return [type] ...
1718 */
1719 function getRepositoryUploadForm($eKey,$info) {
1720 $uArr = $this->makeUploadArray($eKey,$info);
1721 if (is_array($uArr)) {
1722 $backUpData = $this->makeUploadDataFromArray($uArr);
1723
1724 #debug($this->decodeExchangeData($backUpData));
1725 $content.='Extension "'.$this->extensionTitleIconHeader($eKey,$info).'" is ready to be uploaded.<br />
1726 The size of the upload is <strong>'.t3lib_div::formatSize(strlen($backUpData)).'</strong><br />
1727 ';
1728
1729 $b64data = base64_encode($backUpData);
1730 $content='</form><form action="'.$this->repositoryUrl.'" method="post" enctype="application/x-www-form-urlencoded">
1731 <input type="hidden" name="tx_extrep[upload][returnUrl]" value="'.htmlspecialchars($this->makeReturnUrl()).'">
1732 <input type="hidden" name="tx_extrep[upload][data]" value="'.$b64data.'">
1733 <input type="hidden" name="tx_extrep[upload][typo3ver]" value="'.$GLOBALS["TYPO_VERSION"].'">
1734 <input type="hidden" name="tx_extrep[upload][os]" value="'.TYPO3_OS.'">
1735 <input type="hidden" name="tx_extrep[upload][sapi]" value="'.php_sapi_name().'">
1736 <input type="hidden" name="tx_extrep[upload][phpver]" value="'.phpversion().'">
1737 <input type="hidden" name="tx_extrep[upload][gzcompressed]" value="'.$this->gzcompress.'">
1738 <input type="hidden" name="tx_extrep[upload][data_md5]" value="'.md5($b64data).'">
1739 <table border=0 cellpadding=2 cellspacing=1>
1740 <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>
1741 <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>
1742 <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>
1743 <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>
1744 <tr class="bgColor4"><td>Upload command:</td><td nowrap>
1745 <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 />
1746 <input type="radio" name="tx_extrep[upload][mode]" value="latest"> Override <em>this</em> development version ('.$info["EM_CONF"]["version"].')<br />
1747 <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 />
1748 <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 />
1749 </td></tr>
1750 <tr class="bgColor4"><td>Private?</td><td>
1751 <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 />
1752 ("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 />
1753 <br /><strong>Additional import password:</strong><br />
1754 <input'.$this->doc->formWidth(20).' type="text" name="tx_extrep[upload][download_password]" value="'.htmlspecialchars(trim($info["EM_CONF"]["download_password"])).'"> (Textfield!) <br />
1755 (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 />
1756 </td></tr>
1757 <tr class="bgColor4"><td>&nbsp;</td><td><input type="submit" name="submit" value="Upload extension"><br />
1758 '.t3lib_div::formatSize(strlen($b64data)).($this->gzcompress?", compressed":"").', base64<br />
1759 <br />
1760 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!
1761 </td></tr>
1762 </table>
1763 ';
1764
1765 return $content;
1766 } else {
1767 return $uArr;
1768 }
1769 }
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782 /**
1783 * Prints the header row for the various listings
1784 *
1785 * @param [type] $bgColor: ...
1786 * @param [type] $cells: ...
1787 * @param [type] $import: ...
1788 * @return [type] ...
1789 */
1790 function extensionListRowHeader($bgColor,$cells,$import=0) {
1791 $cells[]='<td></td>';
1792 $cells[]='<td nowrap><strong>Title:</strong></td>';
1793
1794 if (!$this->MOD_SETTINGS["display_details"]) {
1795 $cells[]='<td nowrap><strong>Description:</strong></td>';
1796 $cells[]='<td nowrap><strong>Author:</strong></td>';
1797 } elseif ($this->MOD_SETTINGS["display_details"]==2) {
1798 $cells[]='<td nowrap><strong>Priority:</strong></td>';
1799 $cells[]='<td nowrap><strong>Mod.Tables:</strong></td>';
1800 $cells[]='<td nowrap><strong>Modules:</strong></td>';
1801 $cells[]='<td nowrap><strong>Cl.Cache?</strong></td>';
1802 $cells[]='<td nowrap><strong>Internal?</strong></td>';
1803 $cells[]='<td nowrap><strong>Shy?</strong></td>';
1804 } elseif ($this->MOD_SETTINGS["display_details"]==3) {
1805 $cells[]='<td nowrap><strong>Tables/Fields:</strong></td>';
1806 $cells[]='<td nowrap><strong>TS-files:</strong></td>';
1807 $cells[]='<td nowrap><strong>Affects:</strong></td>';
1808 $cells[]='<td nowrap><strong>Modules:</strong></td>';
1809 $cells[]='<td nowrap><strong>Config?</strong></td>';
1810 $cells[]='<td nowrap><strong>Errors:</strong></td>';
1811 } elseif ($this->MOD_SETTINGS["display_details"]==4) {
1812 $cells[]='<td nowrap><strong>locallang:</strong></td>';
1813 $cells[]='<td nowrap><strong>Classes:</strong></td>';
1814 $cells[]='<td nowrap><strong>Errors:</strong></td>';
1815 $cells[]='<td nowrap><strong>NameSpace Errors:</strong></td>';
1816 } elseif ($this->MOD_SETTINGS["display_details"]==5) {
1817 $cells[]='<td nowrap><strong>Changed files:</strong></td>';
1818 } else {
1819 $cells[]='<td nowrap><strong>Extension key:</strong></td>';
1820 $cells[]='<td nowrap><strong>Version:</strong></td>';
1821 if (!$import) {
1822 $cells[]='<td><strong>Doc:</strong></td>';
1823 $cells[]='<td nowrap><strong>Type:</strong></td>';
1824 } else {
1825 $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>';
1826 $cells[]='<td nowrap class="bgColor6"'.$this->labelInfo("Current type of installation of the extension on this server.").'><strong>Cur. Type:</strong></td>';
1827 $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>';
1828 $cells[]='<td nowrap'.$this->labelInfo("TYPO3 version of last uploading server.").'><strong>T3 ver:</strong></td>';
1829 $cells[]='<td nowrap'.$this->labelInfo("PHP version of last uploading server.").'><strong>PHP:</strong></td>';
1830 $cells[]='<td nowrap'.$this->labelInfo("Size of extension, uncompressed / compressed").'><strong>Size:</strong></td>';
1831 $cells[]='<td nowrap'.$this->labelInfo("Number of downloads, all versions/this version").'><strong>DL:</strong></td>';
1832 }
1833 $cells[]='<td nowrap><strong>State:</strong></td>';
1834 $cells[]='<td nowrap><strong>Dependencies:</strong></td>';
1835 }
1836 return '<tr'.$bgColor.'>'.implode('',$cells).'</tr>';
1837 }
1838
1839 /**
1840 * Prints a row with data for the various extension listings
1841 *
1842 * @param [type] $eKey: ...
1843 * @param [type] $eConf: ...
1844 * @param [type] $info: ...
1845 * @param [type] $cells: ...
1846 * @param [type] $bgColor: ...
1847 * @param [type] $inst_list: ...
1848 * @param [type] $import: ...
1849 * @param [type] $altLinkUrl: ...
1850 * @return [type] ...
1851 */
1852 function extensionListRow($eKey,$eConf,$info,$cells,$bgColor="",$inst_list=array(),$import=0,$altLinkUrl="") {
1853 $imgInfo = @getImageSize($this->getExtPath($eKey,$info)."/ext_icon.gif");
1854 $style = t3lib_extMgm::isLoaded($eKey) ? '' : ' style="color:#666666;"';
1855
1856 if (is_array($imgInfo)) {
1857 $cells[]='<td valign=top><img src="'.$GLOBALS["BACK_PATH"].$this->typeRelPaths[$info["type"]].$eKey."/ext_icon.gif".'" '.$imgInfo[3].'></td>';
1858 } elseif ($info["_ICON"]) {
1859 $cells[]='<td valign=top>'.$info["_ICON"].'</td>';
1860 } else {
1861 $cells[]='<td><img src="clear.gif" width=1 height=1></td>';
1862 }
1863 $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>';
1864
1865 if (isset($inst_list[$eKey])) {
1866 unset($this->inst_keys[$eKey]);
1867 }
1868
1869 if (!$this->MOD_SETTINGS["display_details"]) {
1870 $cells[]='<td valign=top>'.t3lib_div::fixed_lgd(htmlspecialchars($info["EM_CONF"]["description"]),400).'<br /><img src=clear.gif width=300 height=></td>';
1871 $cells[]='<td nowrap valign=top>'.$info["EM_CONF"]["author"].($info["EM_CONF"]["author_company"]?"<br />".$info["EM_CONF"]["author_company"]:"").'</td>';
1872 } elseif ($this->MOD_SETTINGS["display_details"]==2) {
1873 $cells[]="<td nowrap valign=top>".$info["EM_CONF"]["priority"]."</td>";
1874 $cells[]="<td nowrap valign=top>".implode("<br />",t3lib_div::trimExplode(",",$info["EM_CONF"]["modify_tables"],1))."</td>";
1875 $cells[]="<td nowrap valign=top>".$info["EM_CONF"]["module"]."</td>";
1876 $cells[]="<td nowrap valign=top>".($info["EM_CONF"]["clearCacheOnLoad"]?"Yes":"")."</td>";
1877 $cells[]="<td nowrap valign=top>".($info["EM_CONF"]["internal"]?"Yes":"")."</td>";
1878 $cells[]="<td nowrap valign=top>".($info["EM_CONF"]["shy"]?"Yes":"")."</td>";
1879 } elseif ($this->MOD_SETTINGS["display_details"]==3) {
1880 $techInfo=$this->makeDetailedExtensionAnalysis($eKey,$info);
1881
1882 $cells[]="<td valign=top>".$this->extInformationArray_dbReq($techInfo).
1883 "</td>";
1884 $cells[]="<td nowrap valign=top>".(is_array($techInfo["TSfiles"])?implode("<br />",$techInfo["TSfiles"]):"")."</td>";
1885 $cells[]="<td nowrap valign=top>".(is_array($techInfo["flags"])?implode("<br />",$techInfo["flags"]):"")."</td>";
1886 $cells[]="<td nowrap valign=top>".(is_array($techInfo["moduleNames"])?implode("<br />",$techInfo["moduleNames"]):"")."</td>";
1887 $cells[]="<td nowrap valign=top>".($techInfo["conf"]?"Yes":"")."</td>";
1888 $cells[]="<td valign=top>".
1889 $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!":"").
1890 (t3lib_extMgm::isLoaded($eKey)&&$techInfo["static_error"]?"<strong>Static table error!</strong><br />The static tables are missing or empty!":"")).
1891 "</td>";
1892 } elseif ($this->MOD_SETTINGS["display_details"]==4) {
1893 $techInfo=$this->makeDetailedExtensionAnalysis($eKey,$info,1);
1894
1895 $cells[]="<td valign=top>".(is_array($techInfo["locallang"])?implode("<br />",$techInfo["locallang"]):"")."</td>";
1896 $cells[]="<td valign=top>".(is_array($techInfo["classes"])?implode("<br />",$techInfo["classes"]):"")."</td>";
1897 $cells[]="<td valign=top>".(is_array($techInfo["errors"])?$GLOBALS["TBE_TEMPLATE"]->rfw(implode("<HR>",$techInfo["errors"])):"")."</td>";
1898 $cells[]="<td valign=top>".(is_array($techInfo["NSerrors"])?
1899 (!t3lib_div::inList($this->nameSpaceExceptions,$eKey)?t3lib_div::view_array($techInfo["NSerrors"]):$GLOBALS["TBE_TEMPLATE"]->dfw("[exception]"))
1900 :"")."</td>";
1901 } elseif ($this->MOD_SETTINGS["display_details"]==5) {
1902 # $techInfo=$this->makeDetailedExtensionAnalysis($eKey,$info,1);
1903 $currentMd5Array = $this->serverExtensionMD5Array($eKey,$info);
1904 $affectedFiles="";
1905 $msgLines=array();
1906 $msgLines[] = "Files: ".count($currentMd5Array);
1907 if (strcmp($info["EM_CONF"]["_md5_values_when_last_written"],serialize($currentMd5Array))) {
1908 $msgLines[] = $GLOBALS["TBE_TEMPLATE"]->rfw("<br /><strong>A difference between the originally installed version and the current was detected!</strong>");
1909 $affectedFiles = $this->findMD5ArrayDiff($currentMd5Array,unserialize($info["EM_CONF"]["_md5_values_when_last_written"]));
1910 if (count($affectedFiles)) $msgLines[] = "<br /><strong>Modified files:</strong><br />".$GLOBALS["TBE_TEMPLATE"]->rfw(implode("<br />",$affectedFiles));
1911 }
1912 $cells[]="<td valign=top>".implode("<br />",$msgLines)."</td>";
1913 } else {
1914 $verDiff = $inst_list[$eKey] && $this->versionDifference($info["EM_CONF"]["version"],$inst_list[$eKey]["EM_CONF"]["version"],$this->versionDiffFactor);
1915
1916 $cells[]="<td nowrap valign=top><em>".$eKey."</em></td>";
1917 $cells[]="<td nowrap valign=top>".($verDiff?"<strong>".$GLOBALS["TBE_TEMPLATE"]->rfw($info["EM_CONF"]["version"])."</strong>":$info["EM_CONF"]["version"])."</td>";
1918 if (!$import) {
1919 $fileP = PATH_site.$this->typePaths[$info["type"]].$eKey."/doc/manual.sxw";
1920
1921 $cells[]='<td nowrap>'.
1922 ($this->typePaths[$info["type"]] && @is_file($fileP)?'<img src="oodoc.gif" width="13" height="16" title="Local Open Office Manual" alt="" />':'').
1923 '</td>';
1924 $cells[]="<td nowrap valign=top>".$this->typeLabels[$info["type"]].(strlen($info["doubleInstall"])>1?'<strong> '.$GLOBALS["TBE_TEMPLATE"]->rfw($info["doubleInstall"]).'</strong>':"")."</td>";
1925 } else {
1926 $inst_curVer = $inst_list[$eKey]["EM_CONF"]["version"];
1927 if (isset($inst_list[$eKey])) {
1928 if ($verDiff) $inst_curVer = "<strong>".$GLOBALS["TBE_TEMPLATE"]->rfw($inst_curVer)."</strong>";
1929 }
1930 $cells[]="<td nowrap valign=top>".$inst_curVer."</td>";
1931 $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>";
1932 $cells[]="<td nowrap valign=top><strong>".$GLOBALS["TBE_TEMPLATE"]->rfw($this->remoteAccess[$info["_ACCESS"]])."</strong></td>";
1933 $cells[]="<td nowrap valign=top>".$info["EM_CONF"]["_typo3_ver"]."</td>";
1934 $cells[]="<td nowrap valign=top>".$info["EM_CONF"]["_php_ver"]."</td>";
1935 $cells[]="<td nowrap valign=top>".$info["EM_CONF"]["_size"]."</td>";
1936 $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>";
1937 //debug($info);
1938 }
1939 $cells[]="<td nowrap valign=top>".$this->states[$info["EM_CONF"]["state"]]."</td>";
1940 $cells[]="<td nowrap valign=top>".$info["EM_CONF"]["dependencies"]."</td>";
1941 }
1942 $bgColor = ' bgColor="'.($bgColor?$bgColor:$this->doc->bgColor4).'"';
1943 return '<tr'.$bgColor.$style.'>'.implode('',$cells).'</tr>';
1944 }
1945
1946 /**
1947 * Returns title and style attribute for mouseover help text.
1948 *
1949 * @param [type] $str: ...
1950 * @return [type] ...
1951 */
1952 function labelInfo($str) {
1953 return ' title="'.htmlspecialchars($str).'" style="cursor:help;"';
1954 }
1955
1956 /**
1957 * Creates directories in $extDirPath
1958 *
1959 * @param [type] $dirs: ...
1960 * @param [type] $extDirPath: ...
1961 * @return [type] ...
1962 */
1963 function createDirsInPath($dirs,$extDirPath) {
1964 if (is_array($dirs)) {
1965 reset($dirs);
1966 while(list(,$dir)=each($dirs)) {
1967 $allDirs = t3lib_div::trimExplode("/",$dir,1);
1968 reset($allDirs);
1969 $root="";
1970 while(list(,$dirParts)=each($allDirs)) {
1971 $root.=$dirParts.'/';
1972 if (!is_dir($extDirPath.$root)) {
1973 @mkdir(ereg_replace('\/$','',$extDirPath.$root), 0777);
1974 if (!@is_dir($extDirPath.$root)) {
1975 return "Error: The directory '".$extDirPath.$root."' could not be created...";
1976 }
1977 }
1978 }
1979 }
1980 }
1981 }
1982
1983 /**
1984 * Removes the extension directory
1985 *
1986 * @param [type] $removePath: ...
1987 * @param [type] $removeContentOnly: ...
1988 * @return [type] ...
1989 */
1990 function removeExtDirectory($removePath,$removeContentOnly=0) {
1991 if (@is_dir($removePath) && substr($removePath,-1)=="/" && (
1992 t3lib_div::isFirstPartOfStr($removePath,PATH_site.$this->typePaths["G"]) ||
1993 t3lib_div::isFirstPartOfStr($removePath,PATH_site.$this->typePaths["L"]) ||
1994 (t3lib_div::isFirstPartOfStr($removePath,PATH_site.$this->typePaths["S"]) && $this->systemInstall) ||
1995 t3lib_div::isFirstPartOfStr($removePath,PATH_site."fileadmin/_temp_/"))
1996 ) {
1997 $this->noCVS=0;
1998 $fileArr = $this->getAllFilesAndFoldersInPath(array(),$removePath,"",1);
1999 if (is_array($fileArr)) {
2000 // Remove files in dirs:
2001 #debug($fileArr);
2002 reset($fileArr);
2003 while(list(,$removeFile)=each($fileArr)) {
2004 if (!@is_dir($removeFile)) {
2005 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!
2006 @unlink($removeFile);
2007 #debug($removeFile);
2008 clearstatcache();
2009 if (@is_file($removeFile)) {
2010 debug("Error: '".$removeFile."' could not be deleted!");
2011 }
2012 } else debug("Error: '".$removeFile."' was either not a file, or it was equal to the removed directory or simply outside the removed directory '".$removePath."'!");
2013 }
2014 }
2015
2016 // REmove dirs:
2017 $remDirs = $this->extractDirsFromFileList($this->removePrefixPathFromList($fileArr,$removePath));
2018 #debug($remDirs);
2019 $remDirs = array_reverse($remDirs); // Must delete outer dirs first...
2020 reset($remDirs);
2021 while(list(,$removeRelDir)=each($remDirs)) {
2022 $removeDir = $removePath.$removeRelDir;
2023 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!
2024 rmdir($removeDir);
2025 clearstatcache();
2026 if (@is_dir($removeDir)) {
2027 debug("Error: '".$removeDir."' could not be removed (are there files left?)");
2028 }
2029 } else debug("Error: '".$removeDir."' was not a directory!");
2030 }
2031
2032 if (!$removeContentOnly) {
2033 rmdir($removePath);
2034 clearstatcache();
2035 if (@is_dir($removePath)) {
2036 debug("Error: Extension directory '".$removePath."' could not be removed (are there files or folders left?)");
2037 }
2038 }
2039 #debug("ALL REMOVED");
2040 } else debug("Error: ".$fileArr);
2041 } else debug("Error: Unallowed path to remove: ".$removePath);
2042 }
2043
2044 /**
2045 * Extracts the directories in the $files array
2046 *
2047 * @param [type] $files: ...
2048 * @return [type] ...
2049 */
2050 function extractDirsFromFileList($files) {
2051 $dirs = array();
2052 if (is_array($files)) {
2053 reset($files);
2054 while(list(,$file)=each($files)) {
2055 if (substr($file,-1)=="/") {
2056 $dirs[$file]=$file;
2057 } else {
2058 $pI=pathinfo($file);
2059 if (strcmp($pI["dirname"],"") && strcmp($pI["dirname"],".")) {
2060 $dirs[$pI["dirname"]."/"]=$pI["dirname"]."/";
2061 }
2062 }
2063 }
2064 }
2065 return $dirs;
2066 }
2067
2068 /**
2069 * Removes the current extension of $type and creates the base folder for the new one (which is going to be imported)
2070 *
2071 * @param [type] $importedData: ...
2072 * @param [type] $type: ...
2073 * @return [type] ...
2074 */
2075 function clearAndMakeExtensionDir($importedData,$type) {
2076 if (!$importedData["extKey"]) return "FATAL ERROR: Extension key was not set for some VERY strange reason. Nothing done...";
2077
2078 $path="";
2079 switch((string)$type) {
2080 case "G":
2081 case "L":
2082 $path=PATH_site.$this->typePaths[$type];
2083 $suffix="";
2084 if ((string)$type=="L" && !@is_dir($path)) {
2085 @mkdir(ereg_replace('\/$','',$path), 0777);
2086 }
2087 break;
2088 default:
2089 if ($this->systemInstall && (string)$type=="S") {
2090 $path=PATH_site.$this->typePaths[$type];
2091 $suffix="";
2092 } else {
2093 $path=PATH_site."fileadmin/_temp_/";
2094 $suffix="_".date("dmy-His");
2095 }
2096 break;
2097 }
2098 if ($path && @is_dir($path)) {
2099 $extDirPath = $path.$importedData["extKey"].$suffix.'/';
2100 if (@is_dir($extDirPath)) {
2101 // Install dir was found
2102 $res = $this->removeExtDirectory($extDirPath);
2103 if ($res) return "ERROR: Could not remove extension directory '".$extDirPath."'";
2104 }
2105 #die("stop here...");
2106 // we go create...
2107 @mkdir(ereg_replace('\/$','',$extDirPath), 0777);
2108 if (!is_dir($extDirPath)) return "ERROR: Could not create extension directory '".$extDirPath."'";
2109 return array($extDirPath);
2110 } else return "ERROR: The extension install path '".$path."' was not a directory.";
2111 }
2112
2113 /**
2114 * Evaluates differences in version numbers with three parts, x.x.x. Returns true if $v1 is greater than $v2
2115 *
2116 * @param [type] $v1: ...
2117 * @param [type] $v2: ...
2118 * @param [type] $div: ...
2119 * @return [type] ...
2120 */
2121 function versionDifference($v1,$v2,$div=1) {
2122 # debug(array(floor($this->makeVersion($v1,"int")/$div),floor($this->makeVersion($v2,"int")/$div)));
2123 return floor($this->makeVersion($v1,"int")/$div) > floor($this->makeVersion($v2,"int")/$div);
2124 }
2125
2126 /**
2127 * Fetches data from the $repositoryUrl, un-compresses it, unserializes array and returns an array with the content if success.
2128 *
2129 * @param [type] $repositoryUrl: ...
2130 * @return [type] ...
2131 */
2132 function fetchServerData($repositoryUrl) {
2133 $ps1 = t3lib_div::milliseconds();
2134 $externalData = t3lib_div::getUrl($repositoryUrl);
2135 $ps2 = t3lib_div::milliseconds()+1;
2136
2137 $stat=Array(
2138 ($ps2-$ps1),
2139 strlen($externalData),
2140 "Time: ".($ps2-$ps1)."ms",
2141 "Size: ".t3liB_div::formatSize(strlen($externalData)),
2142 "Transfer: ".t3liB_div::formatSize(strlen($externalData) / (($ps2-$ps1)/1000))."/sec"
2143 );
2144
2145 return $this->decodeServerData($externalData,$stat);
2146 }
2147
2148 /**
2149 * Decode server data
2150 *
2151 * @param [type] $externalData: ...
2152 * @param [type] $stat: ...
2153 * @return [type] ...
2154 */
2155 function decodeServerData($externalData,$stat=array()) {
2156 $parts = explode(":",$externalData,4);
2157 $dat = base64_decode($parts[2]);
2158 if ($parts[0]==md5($dat)) {
2159 if ($parts[1]=="gzcompress") {
2160 if ($this->gzcompress) {
2161 $dat=gzuncompress($dat);
2162 } else debug("Decoding Error: No decompressor available for compressed content. gzcompress()/gzuncompress() functions are not available!");
2163 }
2164 $listArr = unserialize($dat);
2165 return array($listArr,$stat);
2166 }
2167 }
2168
2169 /**
2170 * Clearing of cache-files in typo3conf/ + menu
2171 *
2172 * @return [type] ...
2173 */
2174 function addClearCacheFiles() {
2175 global $TYPO3_CONF_VARS;
2176 if ($TYPO3_CONF_VARS["EXT"]["extCache"]) {
2177 if (t3lib_div::GPvar("_clearCacheFiles")) {
2178 $this->removeCacheFiles();
2179 header("Location: ".t3lib_div::linkThisScript(array("_clearCacheFiles"=>0,"_cache_files_are_removed"=>1)));
2180 } else {
2181 $content="";
2182 if (t3lib_div::GPvar("_cache_files_are_removed")) $content.=$GLOBALS["TBE_TEMPLATE"]->rfw("Cache files was removed.").'<br /><br />';
2183 $content.='Click here to <a href="'.t3lib_div::linkThisScript(array("_clearCacheFiles"=>1)).'"><strong>clear cache files in typo3conf/</strong></a>';
2184 $this->content.=$this->doc->spacer(20);
2185 $this->content.=$this->doc->section("Clear cache files",$content,0,1);
2186 }
2187 }
2188 }
2189
2190 /**
2191 * Returns a header for an extensions including icon if any
2192 *
2193 * @param [type] $eKey: ...
2194 * @param [type] $info: ...
2195 * @param [type] $align: ...
2196 * @return [type] ...
2197 */
2198 function extensionTitleIconHeader($eKey,$info,$align="top") {
2199 $imgInfo = @getImageSize($this->getExtPath($eKey,$info)."/ext_icon.gif");
2200 $out="";
2201 if (is_array($imgInfo)) {
2202 $out.='<img src="'.$GLOBALS["BACK_PATH"].$this->typeRelPaths[$info["type"]].$eKey."/ext_icon.gif".'" '.$imgInfo[3].' align='.$align.'>';
2203 }
2204 $out.=t3lib_div::fixed_lgd($info["EM_CONF"]["title"]?$info["EM_CONF"]["title"]:"<em>".$eKey."</em>",40);
2205 return $out;
2206 }
2207
2208 /**
2209 * Perform a detailed, technical analysis of the available extension on server!
2210 * Includes all kinds of verifications
2211 *
2212 * @param [type] $eKey: ...
2213 * @param [type] $info: ...
2214 * @param [type] $validity: ...
2215 * @return [type] ...
2216 */
2217 function makeDetailedExtensionAnalysis($eKey,$info,$validity=0) {
2218 $absPath = $this->getExtPath($eKey,$info);
2219
2220 $infoArray = array();
2221
2222 $table_class_prefix = substr($eKey,0,5)=="user_" ? "user_" : "tx_".str_replace("_","",$eKey)."_";
2223 $module_prefix = substr($eKey,0,5)=="user_" ? "u" : "tx".str_replace("_","",$eKey);
2224
2225 // Tables:
2226 $dbInfo=$this->checkDBupdates($eKey,$info,1);
2227 if (is_array($dbInfo["static"])) {
2228 $infoArray["static"]=array_keys($dbInfo["static"]);
2229 }
2230 if (is_array($dbInfo["structure"]["tables_fields"])) {
2231 $modify_tables = t3lib_div::trimExplode(",",$info["EM_CONF"]["modify_tables"],1);
2232 $infoArray["dump_tf"]=array();
2233 reset($dbInfo["structure"]["tables_fields"]);
2234 while(list($tN,$d)=each($dbInfo["structure"]["tables_fields"])) {
2235 if (in_array($tN,$modify_tables)) {
2236 $infoArray["fields"][]=$tN.": <i>".
2237 (is_array($d["fields"])?implode(", ",array_keys($d["fields"])):"").
2238 (is_array($d["keys"])?" + ".count($d["keys"])." keys":"").
2239 "</i>";
2240 if (is_array($d["fields"])) {
2241 reset($d["fields"]);
2242 while(list($fN)=each($d["fields"])) {
2243 $infoArray["dump_tf"][]=$tN.".".$fN;
2244 if (!t3lib_div::isFirstPartOfStr($fN,$table_class_prefix)) {
2245 $infoArray["NSerrors"]["fields"][$fN]=$fN;
2246 } else $infoArray["NSok"]["fields"][$fN]=$fN;
2247 }
2248 }
2249 if (is_array($d["keys"])) {
2250 reset($d["keys"]);
2251 while(list($fN)=each($d["keys"])) {
2252 $infoArray["dump_tf"][]=$tN.".KEY:".$fN;
2253 }
2254 }
2255 } else {
2256 $infoArray["dump_tf"][]=$tN;
2257 $infoArray["tables"][]=$tN;
2258 if (!t3lib_div::isFirstPartOfStr($tN,$table_class_prefix)) {
2259 $infoArray["NSerrors"]["tables"][$tN]=$tN;
2260 } else $infoArray["NSok"]["tables"][$tN]=$tN;
2261 }
2262 }
2263 if (count($dbInfo["structure"]["diff"]["diff"]) || count($dbInfo["structure"]["diff"]["extra"])) {
2264 $msg=array();
2265 if (count($dbInfo["structure"]["diff"]["diff"])) $msg[]="missing";
2266 if (count($dbInfo["structure"]["diff"]["extra"])) $msg[]="of wrong type";
2267 $infoArray["tables_error"]=1;
2268 if (t3lib_extMgm::isLoaded($eKey)) $infoArray["errors"][]="Some tables or fields are ".implode(" and ",$msg)."!";
2269 }
2270 }
2271 if (is_array($infoArray["static"])) {
2272 reset($dbInfo["static"]);
2273 while(list($tN,$d)=each($dbInfo["static"])) {
2274 if (!$d["exists"]) {
2275 $infoArray["static_error"]=1;
2276 if (t3lib_extMgm::isLoaded($eKey)) $infoArray["errors"][]="Static table(s) missing!";
2277 if (!t3lib_div::isFirstPartOfStr($tN,$table_class_prefix)) {
2278 $infoArray["NSerrors"]["tables"][$tN]=$tN;
2279 } else $infoArray["NSok"]["tables"][$tN]=$tN;
2280 }
2281 }
2282 }
2283
2284 // Module-check:
2285 $knownModuleList = t3lib_div::trimExplode(",",$info["EM_CONF"]["module"],1);
2286 reset($knownModuleList);
2287 while(list(,$mod)=each($knownModuleList)) {
2288 if (@is_dir($absPath.$mod)) {
2289 if (@is_file($absPath.$mod."/conf.php")) {
2290 $confFileInfo = $this->modConfFileAnalysis($absPath.$mod."/conf.php");
2291 if (is_array($confFileInfo["TYPO3_MOD_PATH"])) {
2292 $shouldBePath = $this->typeRelPaths[$info["type"]].$eKey."/".$mod."/";
2293 if (strcmp($confFileInfo["TYPO3_MOD_PATH"][1][1],$shouldBePath)) {
2294 $infoArray["errors"][]="Configured TYPO3_MOD_PATH '".$confFileInfo["TYPO3_MOD_PATH"][1][1]."' different from '".$shouldBePath."'";
2295 }
2296 } else $infoArray["errors"][]="No definition of TYPO3_MOD_PATH constant found inside!";
2297 if (is_array($confFileInfo["MCONF_name"])) {
2298 $mName = $confFileInfo["MCONF_name"][1][1];
2299 $mNameParts = explode("_",$mName);
2300 $infoArray["moduleNames"][]=$mName;
2301 if (!t3lib_div::isFirstPartOfStr($mNameParts[0],$module_prefix) &&
2302 (!$mNameParts[1] || !t3lib_div::isFirstPartOfStr($mNameParts[1],$module_prefix))) {
2303 $infoArray["NSerrors"]["modname"][]=$mName;
2304 } else $infoArray["NSok"]["modname"][]=$mName;
2305 } else $infoArray["errors"][]="No definition of MCONF[name] variable found inside!";
2306 } else $infoArray["errors"][]="Backend module conf file '".$mod."/conf.php' should exist but does not!";
2307 } else $infoArray["errors"][]="Backend module folder '".$mod."/' should exist but does not!";
2308 }
2309 $dirs = t3lib_div::get_dirs($absPath);
2310 if (is_array($dirs)) {
2311 reset($dirs);
2312 while(list(,$mod)=each($dirs)) {
2313 if (!in_array($mod,$knownModuleList) && @is_file($absPath.$mod."/conf.php")) {
2314 $confFileInfo = $this->modConfFileAnalysis($absPath.$mod."/conf.php");
2315 if (is_array($confFileInfo)) {
2316 $infoArray["errors"][]="It seems like there is a backend module in '".$mod."/conf.php"."' which is not configured in ext_emconf.php";
2317 }
2318 }
2319 }
2320 }
2321
2322 // ext_tables.php:
2323 if (@is_file($absPath."ext_tables.php")) {
2324 $content = t3lib_div::getUrl($absPath."ext_tables.php");
2325 if (eregi("t3lib_extMgm::addModule",$content)) $infoArray["flags"][]="Module";
2326 if (eregi("t3lib_extMgm::insertModuleFunction",$content)) $infoArray["flags"][]="Module+";
2327 if (stristr($content,'t3lib_div::loadTCA')) $infoArray["flags"][]='loadTCA';
2328 if (stristr($content,'$TCA[')) $infoArray["flags"][]='TCA';
2329 if (eregi("t3lib_extMgm::addPlugin",$content)) $infoArray["flags"][]="Plugin";
2330 }
2331
2332 // ext_localconf.php:
2333 if (@is_file($absPath."ext_localconf.php")) {
2334 $content = t3lib_div::getUrl($absPath."ext_localconf.php");
2335 if (eregi("t3lib_extMgm::addPItoST43",$content)) $infoArray["flags"][]="Plugin/ST43";
2336 if (eregi("t3lib_extMgm::addPageTSConfig",$content)) $infoArray["flags"][]="Page-TSconfig";
2337 if (eregi("t3lib_extMgm::addUserTSConfig",$content)) $infoArray["flags"][]="User-TSconfig";
2338 if (eregi("t3lib_extMgm::addTypoScriptSetup",$content)) $infoArray["flags"][]="TS/Setup";
2339 if (eregi("t3lib_extMgm::addTypoScriptConstants",$content)) $infoArray["flags"][]="TS/Constants";
2340 }
2341
2342 if (@is_file($absPath."ext_typoscript_constants.txt")) {
2343 $infoArray["TSfiles"][]="Constants";
2344 }
2345 if (@is_file($absPath."ext_typoscript_setup.txt")) {
2346 $infoArray["TSfiles"][]="Setup";
2347 }
2348 if (@is_file($absPath."ext_conf_template.txt")) {
2349 $infoArray["conf"]=1;
2350 }
2351
2352 // Classes:
2353 if ($validity) {
2354 $filesInside = $this->getClassIndexLocallangFiles($absPath,$table_class_prefix,$eKey);
2355 if (is_array($filesInside["errors"])) $infoArray["errors"]=array_merge($infoArray["errors"],$filesInside["errors"]);
2356 if (is_array($filesInside["NSerrors"])) $infoArray["NSerrors"]=array_merge($infoArray["NSerrors"],$filesInside["NSerrors"]);
2357 if (is_array($filesInside["NSok"])) $infoArray["NSok"]=array_merge($infoArray["NSok"],$filesInside["NSok"]);
2358 $infoArray["locallang"]=$filesInside["locallang"];
2359 $infoArray["classes"]=$filesInside["classes"];
2360 }
2361
2362
2363 if ($info["EM_CONF"]["uploadfolder"]) {
2364 $infoArray["uploadfolder"] = $this->ulFolder($eKey);
2365 if (!@is_dir(PATH_site.$infoArray["uploadfolder"])) {
2366 $infoArray["errors"][]="Error: Upload folder '".$infoArray["uploadfolder"]."' did not exist!";
2367 $infoArray["uploadfolder"] = "";
2368 }
2369 }
2370
2371 if ($info["EM_CONF"]["createDirs"]) {
2372 $infoArray["createDirs"] = array_unique(t3lib_div::trimExplode(",",$info["EM_CONF"]["createDirs"],1));
2373 while(list(,$crDir)=each($infoArray["createDirs"])) {
2374 if (!@is_dir(PATH_site.$crDir)) {
2375 $infoArray["errors"][]="Error: Upload folder '".$crDir."' did not exist!";
2376 }
2377 }
2378 }
2379 return $infoArray;
2380 }
2381
2382 /**
2383 * Analyses the php-scripts of an available extension on server
2384 *
2385 * @param [type] $absPath: ...
2386 * @param [type] $table_class_prefix: ...
2387 * @param [type] $eKey: ...
2388 * @return [type] ...
2389 */
2390 function getClassIndexLocallangFiles($absPath,$table_class_prefix,$eKey) {
2391 $filesInside = $this->removePrefixPathFromList($this->getAllFilesAndFoldersInPath(array(),$absPath,"php,inc"),$absPath);
2392 $out=array();
2393 reset($filesInside);
2394 while(list(,$fileName)=each($filesInside)) {
2395 if (substr($fileName,0,4)!="ext_") {
2396 $baseName = basename($fileName);
2397 if (substr($baseName,0,9)=="locallang" && substr($baseName,-4)==".php") {
2398 $out["locallang"][]=$fileName;
2399 } elseif ($baseName!="conf.php") {
2400 if (filesize($absPath.$fileName)<500*1024) {
2401 $fContent = t3lib_div::getUrl($absPath.$fileName);
2402 unset($reg);
2403 if (ereg("\n[[:space:]]*class[[:space:]]*([[:alnum:]_]+)([[:alnum:][:space:]_]*){",$fContent,$reg)) {
2404 // Find classes:
2405 $classesInFile=array();
2406 $lines = explode(chr(10),$fContent);
2407 reset($lines);
2408 while(list($k,$l)=each($lines)) {
2409 $line = trim($l);
2410 unset($reg);
2411 if (ereg("^class[[:space:]]*([[:alnum:]_]+)([[:alnum:][:space:]_]*){",$line,$reg)) {
2412 $out["classes"][]=$reg[1];
2413 $out["files"][$fileName]["classes"][]=$reg[1];
2414 if (substr($reg[1],0,3)!="ux_" && !t3lib_div::isFirstPartOfStr($reg[1],$table_class_prefix) && strcmp(substr($table_class_prefix,0,-1),$reg[1])) {
2415 $out["NSerrors"]["classname"][]=$reg[1];
2416 } else $out["NSok"]["classname"][]=$reg[1];
2417 }
2418 }
2419 // If class file prefixed "class."....
2420 if (substr($baseName,0,6)=="class.") {
2421 $fI=pathinfo($baseName);
2422 $testName=substr($baseName,6,-(1+strlen($fI["extension"])));
2423 if (substr($testName,0,3)!="ux_" && !t3lib_div::isFirstPartOfStr($testName,$table_class_prefix) && strcmp(substr($table_class_prefix,0,-1),$testName)) {
2424 $out["NSerrors"]["classfilename"][]=$baseName;
2425 } else {
2426 $out["NSok"]["classfilename"][]=$baseName;
2427 if (is_array($out["files"][$fileName]["classes"]) && $this->first_in_array($testName,$out["files"][$fileName]["classes"],1)) {
2428 $out["msg"][]="Class filename '".$fileName."' did contain the class '".$testName."' just as it should.";
2429 } else $out["errors"][]="Class filename '".$fileName."' did NOT contain the class '".$testName."'!";
2430 }
2431 }
2432 //
2433 $XclassParts = explode('if (defined(\'TYPO3_MODE\') && $TYPO3_CONF_VARS[TYPO3_MODE][\'XCLASS\']',$fContent,2);
2434 if (count($XclassParts)==2) {
2435 unset($reg);
2436 ereg('^\[\'([[:alnum:]_\/\.]*)\'\]',$XclassParts[1],$reg);
2437 if ($reg[1]) {
2438 $cmpF = "ext/".$eKey."/".$fileName;
2439 if (!strcmp($reg[1],$cmpF)) {
2440 if (strstr($XclassParts[1],'_once($TYPO3_CONF_VARS[TYPO3_MODE][\'XCLASS\'][\''.$cmpF.'\']);')) {
2441 $out["msg"][]="XCLASS OK in ".$fileName;
2442 } else $out["errors"][]="Couldn't find the include_once statement for XCLASS!";
2443 } else $out["errors"][]="The XCLASS filename-key '".$reg[1]."' was different from '".$cmpF."' which it should have been!";
2444 } else $out["errors"][]="No XCLASS filename-key found in file '".$fileName."'. Maybe a regex coding error here...";
2445 } elseif (!$this->first_in_array("ux_",$out["files"][$fileName]["classes"])) $out["errors"][]="No XCLASS inclusion code found in file '".$fileName."'";
2446 }
2447 }
2448 }
2449 }
2450 }
2451 return $out;
2452 }
2453
2454 /**
2455 * Returns true if the $str is found as the first part of a string in $array
2456 *
2457 * @param [type] $str: ...
2458 * @param [type] $array: ...
2459 * @return [type] ...
2460 */
2461 function first_in_array($str,$array,$caseInsensitive=FALSE) {
2462 if ($caseInsensitive) $str = strtolower($str);
2463 if (is_array($array)) {
2464 reset($array);
2465 while(list(,$cl)=each($array)) {
2466 if ($caseInsensitive) $cl = strtolower($cl);
2467 if (t3lib_div::isFirstPartOfStr($cl,$str)) return 1;
2468 }
2469 }
2470 }
2471
2472 /**
2473 * Reads $confFilePath (a module $conf-file) and returns information on the existence of TYPO3_MOD_PATH definition and MCONF_name
2474 *
2475 * @param [type] $confFilePath: ...
2476 * @return [type] ...
2477 */
2478 function modConfFileAnalysis($confFilePath) {
2479 $lines = explode(chr(10),t3lib_div::getUrl($confFilePath));
2480 $confFileInfo=array();
2481 $confFileInfo["lines"]=$lines;
2482
2483 reset($lines);
2484 while(list($k,$l)=each($lines)) {
2485 $line = trim($l);
2486 unset($reg);
2487 if (ereg('^define[[:space:]]*\([[:space:]]*["\']TYPO3_MOD_PATH["\'][[:space:]]*,[[:space:]]*["\']([[:alnum:]_\/\.]+)["\'][[:space:]]*\)[[:space:]]*;',$line,$reg)) {
2488 $confFileInfo["TYPO3_MOD_PATH"]=array($k,$reg);
2489 }
2490 unset($reg);
2491 if (ereg('^\$MCONF\[["\']?name["\']?\][[:space:]]*=[[:space:]]*["\']([[:alnum:]_]+)["\'];',$line,$reg)) {
2492 $confFileInfo["MCONF_name"]=array($k,$reg);
2493 }
2494 }
2495 return $confFileInfo;
2496 }
2497
2498 /**
2499 * Write new TYPO3_MOD_PATH
2500 *
2501 * @param [type] $confFilePath: ...
2502 * @param [type] $type: ...
2503 * @param [type] $mP: ...
2504 * @return [type] ...
2505 */
2506 function writeTYPO3_MOD_PATH($confFilePath,$type,$mP) {
2507 $lines = explode(chr(10),t3lib_div::getUrl($confFilePath));
2508 $confFileInfo=array();
2509 $confFileInfo["lines"]=$lines;
2510
2511 $flag_M=0;
2512 $flag_B=0;
2513
2514 reset($lines);
2515 while(list($k,$l)=each($lines)) {
2516 $line = trim($l);
2517 unset($reg);
2518 if (ereg('^define[[:space:]]*\([[:space:]]*["\']TYPO3_MOD_PATH["\'][[:space:]]*,[[:space:]]*["\']([[:alnum:]_\/\.]+)["\'][[:space:]]*\)[[:space:]]*;',$line,$reg)) {
2519 $lines[$k]=str_replace($reg[0], 'define(\'TYPO3_MOD_PATH\', \''.$this->typeRelPaths[$type].$mP.'\');', $lines[$k]);
2520 $flag_M=$k+1;
2521 }
2522 if (ereg('^\$BACK_PATH[[:space:]]*=[[:space:]]*["\']([[:alnum:]_\/\.]+)["\'][[:space:]]*;',$line,$reg)) {
2523 $lines[$k]=str_replace($reg[0], '$BACK_PATH