Fixed bug #14387: Updating the CGLs [was: Remove the feature "Enable extensions witho...
[Packages/TYPO3.CMS.git] / typo3 / mod / tools / em / class.em_index.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2009 Kasper Skaarhoj (kasperYYYY@typo3.com)
6 * (c) 2005-2009 Karsten Dambekalns <karsten@typo3.org>
7 * All rights reserved
8 *
9 * This script is part of the TYPO3 project. The TYPO3 project is
10 * free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * The GNU General Public License can be found at
16 * http://www.gnu.org/copyleft/gpl.html.
17 * A copy is found in the textfile GPL.txt and important notices to the license
18 * from the author is found in LICENSE.txt distributed with these scripts.
19 *
20 *
21 * This script is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * This copyright notice MUST APPEAR in all copies of the script!
27 ***************************************************************/
28 /**
29 * Module: Extension manager
30 *
31 * $Id$
32 *
33 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
34 * @author Karsten Dambekalns <karsten@typo3.org>
35 */
36 /**
37 * [CLASS/FUNCTION INDEX of SCRIPT]
38 *
39 *
40 *
41 * 194: class SC_mod_tools_em_index extends t3lib_SCbase
42 *
43 * SECTION: Standard module initialization
44 * 337: function init()
45 * 417: function handleExternalFunctionValue($MM_key='function', $MS_value=NULL)
46 * 431: function menuConfig()
47 * 508: function main()
48 * 584: function printContent()
49 *
50 * SECTION: Function Menu Applications
51 * 609: function extensionList_loaded()
52 * 664: function extensionList_installed()
53 * 736: function extensionList_import()
54 * 903: function alterSettings()
55 *
56 * SECTION: Command Applications (triggered by GET var)
57 * 1005: function importExtInfo($extKey, $version='')
58 * 1062: function fetchMetaData($metaType)
59 * 1125: function getMirrorURL()
60 * 1158: function installExtension($extKey, $version=null, $mode=EM_INSTALL_VERSION_MIN)
61 * 1279: function importExtFromRep($extKey,$version,$loc,$uploadFlag=0,$dontDelete=0,$directInput='')
62 * 1425: function showExtDetails($extKey)
63 *
64 * SECTION: Application Sub-functions (HTML parts)
65 * 1737: function updatesForm($extKey,$extInfo,$notSilent=0,$script='',$addFields='')
66 * 1768: function extDumpTables($extKey,$extInfo)
67 * 1835: function getFileListOfExtension($extKey,$conf)
68 * 1889: function extDelete($extKey,$extInfo)
69 * 1920: function extUpdateEMCONF($extKey,$extInfo)
70 * 1940: function extBackup($extKey,$extInfo)
71 * 1987: function extBackup_dumpDataTablesLine($tablesArray,$extKey)
72 * 2015: function extInformationArray($extKey,$extInfo,$remote=0)
73 * 2097: function extInformationArray_dbReq($techInfo,$tableHeader=0)
74 * 2110: function extInformationArray_dbInst($dbInst,$current)
75 * 2129: function getRepositoryUploadForm($extKey,$extInfo)
76 *
77 * SECTION: Extension list rendering
78 * 2190: function extensionListRowHeader($trAttrib,$cells,$import=0)
79 * 2251: function extensionListRow($extKey,$extInfo,$cells,$bgColorClass='',$inst_list=array(),$import=0,$altLinkUrl='')
80 *
81 * SECTION: Output helper functions
82 * 2367: function wrapEmail($str,$email)
83 * 2380: function helpCol($key)
84 * 2396: function labelInfo($str)
85 * 2408: function extensionTitleIconHeader($extKey,$extInfo,$align='top')
86 * 2423: function removeButton()
87 * 2432: function installButton()
88 * 2441: function noImportMsg()
89 * 2454: function depToString($dep,$type='depends')
90 * 2473: function stringToDep($dep)
91 *
92 * SECTION: Read information about all available extensions
93 * 2503: function getInstalledExtensions()
94 * 2530: function getInstExtList($path,&$list,&$cat,$type)
95 * 2561: function fixEMCONF($emConf)
96 * 2600: function splitVersionRange($ver)
97 * 2616: function prepareImportExtList()
98 * 2660: function setCat(&$cat,$listArrayPart,$extKey)
99 *
100 * SECTION: Extension analyzing (detailed information)
101 * 2710: function makeDetailedExtensionAnalysis($extKey,$extInfo,$validity=0)
102 * 2892: function getClassIndexLocallangFiles($absPath,$table_class_prefix,$extKey)
103 * 2962: function modConfFileAnalysis($confFilePath)
104 * 2990: function serverExtensionMD5Array($extKey,$conf)
105 * 3015: function findMD5ArrayDiff($current,$past)
106 *
107 * SECTION: File system operations
108 * 3047: function createDirsInPath($dirs,$extDirPath)
109 * 3065: function removeExtDirectory($removePath,$removeContentOnly=0)
110 * 3128: function clearAndMakeExtensionDir($importedData,$type,$dontDelete=0)
111 * 3182: function removeCacheFiles()
112 * 3192: function extractDirsFromFileList($files)
113 * 3218: function getExtPath($extKey,$type)
114 *
115 * SECTION: Writing to "conf.php" and "localconf.php" files
116 * 3252: function writeTYPO3_MOD_PATH($confFilePath,$type,$mP)
117 * 3289: function writeNewExtensionList($newExtList)
118 * 3312: function writeTsStyleConfig($extKey,$arr)
119 * 3334: function updateLocalEM_CONF($extKey,$extInfo)
120 *
121 * SECTION: Compiling upload information, emconf-file etc.
122 * 3376: function construct_ext_emconf_file($extKey,$EM_CONF)
123 * 3407: function arrayToCode($array, $level=0)
124 * 3433: function makeUploadArray($extKey,$conf)
125 * 3502: function getSerializedLocalLang($file,$content)
126 *
127 * SECTION: Managing dependencies, conflicts, priorities, load order of extension keys
128 * 3538: function addExtToList($extKey,$instExtInfo)
129 * 3569: function checkDependencies($extKey, $conf, $instExtInfo)
130 * 3709: function removeExtFromList($extKey,$instExtInfo)
131 * 3746: function removeRequiredExtFromListArr($listArr)
132 * 3761: function managesPriorities($listArr,$instExtInfo)
133 *
134 * SECTION: System Update functions (based on extension requirements)
135 * 3813: function checkClearCache($extInfo)
136 * 3840: function checkUploadFolder($extKey,$extInfo)
137 * 3925: function checkDBupdates($extKey,$extInfo,$infoOnly=0)
138 * 4022: function forceDBupdates($extKey, $extInfo)
139 * 4080: function tsStyleConfigForm($extKey,$extInfo,$output=0,$script='',$addFields='')
140 *
141 * SECTION: Dumping database (MySQL compliant)
142 * 4175: function dumpTableAndFieldStructure($arr)
143 * 4200: function dumpStaticTables($tableList)
144 * 4229: function dumpHeader()
145 * 4246: function dumpTableHeader($table,$fieldKeyInfo,$dropTableIfExists=0)
146 * 4288: function dumpTableContent($table,$fieldStructure)
147 * 4323: function getTableAndFieldStructure($parts)
148 *
149 * SECTION: TER Communication functions
150 * 4373: function uploadExtensionToTER($em)
151 *
152 * SECTION: Various helper functions
153 * 4411: function listOrderTitle($listOrder,$key)
154 * 4436: function makeVersion($v,$mode)
155 * 4448: function renderVersion($v,$raise='')
156 * 4485: function ulFolder($extKey)
157 * 4494: function importAtAll()
158 * 4505: function importAsType($type,$lockType='')
159 * 4527: function deleteAsType($type)
160 * 4548: function versionDifference($v1,$v2,$div=1)
161 * 4560: function first_in_array($str,$array,$caseInsensitive=FALSE)
162 * 4578: function includeEMCONF($path,$_EXTKEY)
163 * 4593: function searchExtension($extKey,$row)
164 *
165 * TOTAL FUNCTIONS: 90
166 * (This index is automatically created/updated by the extension "extdeveval")
167 *
168 */
169
170 // Include classes needed:
171 require_once('class.em_xmlhandler.php');
172 require_once('class.em_terconnection.php');
173 require_once('class.em_unzip.php');
174
175 $GLOBALS['LANG']->includeLLFile('EXT:lang/locallang_mod_tools_em.xml');
176
177 // from tx_ter by Robert Lemke
178 define('TX_TER_RESULT_EXTENSIONSUCCESSFULLYUPLOADED', '10504');
179
180 define('EM_INSTALL_VERSION_MIN', 1);
181 define('EM_INSTALL_VERSION_MAX', 2);
182 define('EM_INSTALL_VERSION_STRICT', 3);
183
184 /**
185 * Module: Extension manager
186 *
187 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
188 * @author Karsten Dambekalns <karsten@typo3.org>
189 * @package TYPO3
190 * @subpackage core
191 */
192 class SC_mod_tools_em_index extends t3lib_SCbase {
193
194 // Internal, static:
195 var $versionDiffFactor = 1; // This means that version difference testing for import is detected for sub-versions only, not dev-versions. Default: 1000
196 var $systemInstall = 0; // If "1" then installs in the sysext directory is allowed. Default: 0
197 var $requiredExt = ''; // List of required extension (from TYPO3_CONF_VARS)
198 var $maxUploadSize = 31457280; // Max size in bytes of extension upload to repository
199 var $kbMax = 500; // Max size in kilobytes for files to be edited.
200 var $doPrintContent = true; // If set (default), the function printContent() will echo the content which was collected in $this->content. You can set this to FALSE in order to echo content from elsewhere, fx. when using outbut buffering
201 var $listingLimit = 500; // List that many extension maximally at one time (fixing memory problems)
202 var $listingLimitAuthor = 250; // List that many extension maximally at one time (fixing memory problems)
203
204 /**
205 * Internal variable loaded with extension categories (for display/listing). Should reflect $categories above
206 * Dynamic var.
207 */
208 var $defaultCategories = Array(
209 'cat' => Array (
210 'be' => array(),
211 'module' => array(),
212 'fe' => array(),
213 'plugin' => array(),
214 'misc' => array(),
215 'services' => array(),
216 'templates' => array(),
217 'example' => array(),
218 'doc' => array()
219 )
220 );
221
222 var $categories = array(); // Extension Categories (static var); see init()
223
224 var $states = array(); // Extension States; see init()
225
226 /**
227 * Colors for extension states
228 */
229 var $stateColors = Array (
230 'alpha' => '#d12438',
231 'beta' => '#97b17e',
232 'stable' => '#3bb65c',
233 'experimental' => '#007eba',
234 'test' => '#979797',
235 'obsolete' => '#000000',
236 'excludeFromUpdates' => '#cf7307'
237 );
238
239 /**
240 * "TYPE" information; labels, paths, description etc. See init()
241 */
242 var $typeLabels = array();
243 var $typeDescr = array();
244 var $typePaths = Array(); // Also static, set in init()
245 var $typeBackPaths = Array(); // Also static, set in init()
246
247 var $typeRelPaths = Array (
248 'S' => 'sysext/',
249 'G' => 'ext/',
250 'L' => '../typo3conf/ext/',
251 );
252
253 var $detailCols = Array (
254 0 => 2,
255 1 => 5,
256 2 => 6,
257 3 => 6,
258 4 => 4,
259 5 => 1
260 );
261
262 var $fe_user = array(
263 'username' => '',
264 'password' => '',
265 );
266
267 var $privacyNotice; // Set in init()
268 var $securityHint; // Set in init()
269 var $editTextExtensions = 'html,htm,txt,css,tmpl,inc,php,sql,conf,cnf,pl,pm,sh,xml,ChangeLog';
270 var $nameSpaceExceptions = 'beuser_tracking,design_components,impexp,static_file_edit,cms,freesite,quickhelp,classic_welcome,indexed_search,sys_action,sys_workflows,sys_todos,sys_messages,direct_mail,sys_stat,tt_address,tt_board,tt_calender,tt_guest,tt_links,tt_news,tt_poll,tt_rating,tt_products,setup,taskcenter,tsconfig_help,context_help,sys_note,tstemplate,lowlevel,install,belog,beuser,phpmyadmin,aboutmodules,imagelist,setup,taskcenter,sys_notepad,viewpage,adodb';
271
272
273
274
275
276 // Default variables for backend modules
277 var $MCONF = array(); // Module configuration
278 var $MOD_MENU = array(); // Module menu items
279 var $MOD_SETTINGS = array(); // Module session settings
280 /**
281 * Document Template Object
282 *
283 * @var noDoc
284 */
285 var $doc;
286 var $content; // Accumulated content
287
288 var $inst_keys = array(); // Storage of installed extensions
289 var $gzcompress = 0; // Is set true, if system support compression.
290
291 /**
292 * instance of TER connection handler
293 *
294 * @var SC_mod_tools_em_terconnection
295 */
296 var $terConnection;
297
298 /**
299 * XML handling class for the TYPO3 Extension Manager
300 *
301 * @var SC_mod_tools_em_xmlhandler
302 */
303 var $xmlhandler;
304 var $JScode; // JavaScript code to be forwared to $this->doc->JScode
305
306 // GPvars:
307 var $CMD = array(); // CMD array
308 var $listRemote; // If set, connects to remote repository
309 var $lookUpStr; // Search string when listing local extensions
310
311
312
313
314 /*********************************
315 *
316 * Standard module initialization
317 *
318 *********************************/
319
320 /**
321 * Standard init function of a module.
322 *
323 * @return void
324 */
325 function init() {
326 global $BE_USER,$LANG,$BACK_PATH,$TYPO3_CONF_VARS;
327
328 /**
329 * Extension Categories (static var)
330 * Content must be redundant with the same internal variable as in class.tx_extrep.php!
331 */
332 $this->categories = array(
333 'be' => $GLOBALS['LANG']->getLL('category_BE'),
334 'module' => $GLOBALS['LANG']->getLL('category_BE_modules'),
335 'fe' => $GLOBALS['LANG']->getLL('category_FE'),
336 'plugin' => $GLOBALS['LANG']->getLL('category_FE_plugins'),
337 'misc' => $GLOBALS['LANG']->getLL('category_miscellanous'),
338 'services' => $GLOBALS['LANG']->getLL('category_services'),
339 'templates' => $GLOBALS['LANG']->getLL('category_templates'),
340 'example' => $GLOBALS['LANG']->getLL('category_examples'),
341 'doc' => $GLOBALS['LANG']->getLL('category_documentation')
342 );
343
344 /**
345 * Extension States
346 * Content must be redundant with the same internal variable as in class.tx_extrep.php!
347 */
348 $this->states = array(
349 'alpha' => $GLOBALS['LANG']->getLL('state_alpha'),
350 'beta' => $GLOBALS['LANG']->getLL('state_beta'),
351 'stable' => $GLOBALS['LANG']->getLL('state_stable'),
352 'experimental' => $GLOBALS['LANG']->getLL('state_experimental'),
353 'test' => $GLOBALS['LANG']->getLL('state_test'),
354 'obsolete' => $GLOBALS['LANG']->getLL('state_obsolete'),
355 'excludeFromUpdates' => $GLOBALS['LANG']->getLL('state_exclude_from_updates')
356 );
357
358 /**
359 * "TYPE" information; labels, paths, description etc.
360 */
361 $this->typeLabels = array(
362 'S' => $GLOBALS['LANG']->getLL('type_system'),
363 'G' => $GLOBALS['LANG']->getLL('type_global'),
364 'L' => $GLOBALS['LANG']->getLL('type_local'),
365 );
366 $this->typeDescr = array(
367 'S' => $GLOBALS['LANG']->getLL('descr_system'),
368 'G' => $GLOBALS['LANG']->getLL('descr_global'),
369 'L' => $GLOBALS['LANG']->getLL('descr_local'),
370 );
371
372 // Setting paths of install scopes:
373 $this->typePaths = Array (
374 'S' => TYPO3_mainDir.'sysext/',
375 'G' => TYPO3_mainDir.'ext/',
376 'L' => 'typo3conf/ext/'
377 );
378 $this->typeBackPaths = Array (
379 'S' => '../../../',
380 'G' => '../../../',
381 'L' => '../../../../'.TYPO3_mainDir
382 );
383
384 $this->privacyNotice = $GLOBALS['LANG']->getLL('privacy_notice');
385 $securityMessage = $GLOBALS['LANG']->getLL('security_warning_extensions') .
386 '<br /><br />' . sprintf($GLOBALS['LANG']->getLL('security_descr'),
387 '<a href="http://typo3.org/teams/security/" target="_blank">', '</a>'
388 );
389 $flashMessage = t3lib_div::makeInstance(
390 't3lib_FlashMessage',
391 $securityMessage,
392 $GLOBALS['LANG']->getLL('security_header'),
393 t3lib_FlashMessage::INFO
394 );
395 $this->securityHint = $flashMessage->render();
396
397 $this->excludeForPackaging = $GLOBALS['TYPO3_CONF_VARS']['EXT']['excludeForPackaging'];
398
399 // Setting module configuration:
400 $this->MCONF = $GLOBALS['MCONF'];
401
402 // Setting GPvars:
403 $this->CMD = is_array(t3lib_div::_GP('CMD')) ? t3lib_div::_GP('CMD') : array();
404 $this->lookUpStr = trim(t3lib_div::_GP('lookUp'));
405 $this->listRemote = t3lib_div::_GP('ter_connect');
406 $this->listRemote_search = trim(t3lib_div::_GP('ter_search'));
407
408
409 // Configure menu
410 $this->menuConfig();
411
412 // Setting internal static:
413 if ($TYPO3_CONF_VARS['EXT']['allowSystemInstall']) $this->systemInstall = 1;
414 $this->requiredExt = t3lib_div::trimExplode(',',$TYPO3_CONF_VARS['EXT']['requiredExt'],1);
415
416
417 // Initialize helper object
418 $this->terConnection = t3lib_div::makeInstance('SC_mod_tools_em_terconnection');
419 $this->terConnection->emObj = $this;
420 $this->terConnection->wsdlURL = $TYPO3_CONF_VARS['EXT']['em_wsdlURL'];
421 $this->xmlhandler = t3lib_div::makeInstance('SC_mod_tools_em_xmlhandler');
422 $this->xmlhandler->emObj = $this;
423 $this->xmlhandler->useObsolete = $this->MOD_SETTINGS['display_obsolete'];
424
425 // Initialize Document Template object:
426 $this->doc = t3lib_div::makeInstance('template');
427 $this->doc->backPath = $BACK_PATH;
428 $this->doc->setModuleTemplate('templates/em_index.html');
429
430 // JavaScript
431 $this->doc->JScode = $this->doc->wrapScriptTags('
432 script_ended = 0;
433 function jumpToUrl(URL) { //
434 window.location.href = URL;
435 }
436 ');
437
438 // Reload left frame menu
439 if ($this->CMD['refreshMenu']) {
440 $this->doc->JScode .= $this->doc->wrapScriptTags('
441 if(top.refreshMenu) {
442 top.refreshMenu();
443 } else {
444 top.TYPO3ModuleMenu.refreshMenu();
445 }
446 ');
447 }
448
449
450 // Descriptions:
451 $this->descrTable = '_MOD_'.$this->MCONF['name'];
452 if ($BE_USER->uc['edit_showFieldHelp']) {
453 $LANG->loadSingleTableDescription($this->descrTable);
454 }
455
456 // Setting username/password etc. for upload-user:
457 $this->fe_user['username'] = $this->MOD_SETTINGS['fe_u'];
458 $this->fe_user['password'] = $this->MOD_SETTINGS['fe_p'];
459 parent::init();
460 $this->handleExternalFunctionValue('singleDetails');
461 }
462
463 /**
464 * This function is a copy of the same function in t3lib_SCbase with one modification:
465 * In contrast to t3lib_SCbase::handleExternalFunctionValue() this function merges the $this->extClassConf array
466 * instead of overwriting it. That was necessary for including the Kickstarter as a submodule into the 'singleDetails'
467 * selectorbox as well as in the main 'function' selectorbox.
468 *
469 * @param string Mod-setting array key
470 * @param string Mod setting value, overriding the one in the key
471 * @return void
472 * @see t3lib_SCbase::handleExternalFunctionValue()
473 */
474 function handleExternalFunctionValue($MM_key='function', $MS_value=NULL) {
475 $MS_value = is_null($MS_value) ? $this->MOD_SETTINGS[$MM_key] : $MS_value;
476 $externalItems = $this->getExternalItemConfig($this->MCONF['name'],$MM_key,$MS_value);
477 if (is_array($externalItems)) $this->extClassConf = array_merge($externalItems,is_array($this->extClassConf)?$this->extClassConf:array());
478 if (is_array($this->extClassConf) && $this->extClassConf['path']) {
479 $this->include_once[]=$this->extClassConf['path'];
480 }
481 }
482
483 /**
484 * Configuration of which mod-menu items can be used
485 *
486 * @return void
487 */
488 function menuConfig() {
489 global $BE_USER, $TYPO3_CONF_VARS;
490
491 // MENU-ITEMS:
492 $this->MOD_MENU = array(
493 'function' => array(
494 0 => $GLOBALS['LANG']->getLL('menu_loaded_extensions'),
495 1 => $GLOBALS['LANG']->getLL('menu_install_extensions'),
496 2 => $GLOBALS['LANG']->getLL('menu_import_extensions'),
497 4 => $GLOBALS['LANG']->getLL('menu_translation_handling'),
498 3 => $GLOBALS['LANG']->getLL('menu_settings'),
499 5 => $GLOBALS['LANG']->getLL('menu_extension_updates'),
500 ),
501 'listOrder' => array(
502 'cat' => $GLOBALS['LANG']->getLL('list_order_category'),
503 'author_company' => $GLOBALS['LANG']->getLL('list_order_author'),
504 'state' => $GLOBALS['LANG']->getLL('list_order_state'),
505 'type' => $GLOBALS['LANG']->getLL('list_order_type'),
506 ),
507 'display_details' => array(
508 1 => $GLOBALS['LANG']->getLL('show_details'),
509 0 => $GLOBALS['LANG']->getLL('show_description'),
510 2 => $GLOBALS['LANG']->getLL('show_more_details'),
511
512 3 => $GLOBALS['LANG']->getLL('show_technical'),
513 4 => $GLOBALS['LANG']->getLL('show_validating'),
514 5 => $GLOBALS['LANG']->getLL('show_changed'),
515 ),
516 'display_shy' => '',
517 'display_own' => '',
518 'display_obsolete' => '',
519 'display_installed' => '',
520 'display_files' => '',
521
522
523 'singleDetails' => array(
524 'info' => $GLOBALS['LANG']->getLL('details_info'),
525 'edit' => $GLOBALS['LANG']->getLL('details_edit'),
526 'backup' => $GLOBALS['LANG']->getLL('details_backup_delete'),
527 'dump' => $GLOBALS['LANG']->getLL('details_dump_db'),
528 'upload' => $GLOBALS['LANG']->getLL('details_upload'),
529 'updateModule' => $GLOBALS['LANG']->getLL('details_update'),
530 ),
531 'fe_u' => '',
532 'fe_p' => '',
533
534 'mirrorListURL' => '',
535 'rep_url' => '',
536 'extMirrors' => '',
537 'selectedMirror' => '',
538
539 'selectedLanguages' => ''
540 );
541
542 $this->MOD_MENU['singleDetails'] = $this->mergeExternalItems($this->MCONF['name'],'singleDetails',$this->MOD_MENU['singleDetails']);
543
544 // page/be_user TSconfig settings and blinding of menu-items
545 if (!$BE_USER->getTSConfigVal('mod.'.$this->MCONF['name'].'.allowTVlisting')) {
546 unset($this->MOD_MENU['display_details'][3]);
547 unset($this->MOD_MENU['display_details'][4]);
548 unset($this->MOD_MENU['display_details'][5]);
549 }
550
551 // CLEANSE SETTINGS
552 $this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::_GP('SET'), $this->MCONF['name']);
553
554 if ($this->MOD_SETTINGS['function']==2) {
555 // If listing from online repository, certain items are removed though:
556 unset($this->MOD_MENU['listOrder']['type']);
557 unset($this->MOD_MENU['display_details'][2]);
558 unset($this->MOD_MENU['display_details'][3]);
559 unset($this->MOD_MENU['display_details'][4]);
560 unset($this->MOD_MENU['display_details'][5]);
561 $this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::_GP('SET'), $this->MCONF['name']);
562 }
563 parent::menuConfig();
564 }
565
566 /**
567 * Main function for Extension Manager module.
568 *
569 * @return void
570 */
571 function main() {
572 global $BE_USER,$LANG,$TYPO3_CONF_VARS;
573
574 if (empty($this->MOD_SETTINGS['mirrorListURL'])) $this->MOD_SETTINGS['mirrorListURL'] = $TYPO3_CONF_VARS['EXT']['em_mirrorListURL'];
575
576 // Starting page:
577 $this->content.=$this->doc->header($GLOBALS['LANG']->getLL('header'));
578 $this->content.=$this->doc->spacer(5);
579
580 // Command given which is executed regardless of main menu setting:
581 if ($this->CMD['showExt']) { // Show details for a single extension
582 $this->showExtDetails($this->CMD['showExt']);
583 } elseif ($this->CMD['requestInstallExtensions']) { // Show details for a single extension
584 $this->requestInstallExtensions($this->CMD['requestInstallExtensions']);
585 } elseif ($this->CMD['importExt'] || $this->CMD['uploadExt']) { // Imports an extension from online rep.
586 $err = $this->importExtFromRep($this->CMD['importExt'],$this->CMD['extVersion'],$this->CMD['loc'],$this->CMD['uploadExt']);
587 if ($err) {
588 $this->content.=$this->doc->section('',$GLOBALS['TBE_TEMPLATE']->rfw($err));
589 }
590 if(!$err && $this->CMD['importExt']) {
591 $this->installTranslationsForExtension($this->CMD['importExt'], $this->getMirrorURL());
592 }
593 } elseif ($this->CMD['importExtInfo']) { // Gets detailed information of an extension from online rep.
594 $this->importExtInfo($this->CMD['importExtInfo'],$this->CMD['extVersion']);
595 } else { // No command - we show what the menu setting tells us:
596 if (t3lib_div::inList('0,1,2',$this->MOD_SETTINGS['function'])) {
597 $menu .= '&nbsp;' . $GLOBALS['LANG']->getLL('group_by') . '&nbsp;' . t3lib_BEfunc::getFuncMenu(0, 'SET[listOrder]', $this->MOD_SETTINGS['listOrder'], $this->MOD_MENU['listOrder']) .
598 '&nbsp;&nbsp;' . $GLOBALS['LANG']->getLL('show') . '&nbsp;' . t3lib_BEfunc::getFuncMenu(0, 'SET[display_details]', $this->MOD_SETTINGS['display_details'], $this->MOD_MENU['display_details']) . '<br />';
599 }
600 if (t3lib_div::inList('0,1,5',$this->MOD_SETTINGS['function'])) {
601 $menu.='<label for="checkDisplayShy">' . $GLOBALS['LANG']->getLL('display_shy') . '</label>&nbsp;&nbsp;' . t3lib_BEfunc::getFuncCheck(0, 'SET[display_shy]', $this->MOD_SETTINGS['display_shy'], '', '', 'id="checkDisplayShy"');
602 }
603 if (t3lib_div::inList('2',$this->MOD_SETTINGS['function']) && strlen($this->fe_user['username'])) {
604 $menu.='<label for="checkDisplayOwn">' . $GLOBALS['LANG']->getLL('only_my_ext') . '</label>&nbsp;&nbsp;' . t3lib_BEfunc::getFuncCheck(0, 'SET[display_own]', $this->MOD_SETTINGS['display_own'], '', '', 'id="checkDisplayOwn"');
605 }
606 if (t3lib_div::inList('0,1,2',$this->MOD_SETTINGS['function'])) {
607 $menu.='&nbsp;&nbsp;<label for="checkDisplayObsolete">' . $GLOBALS['LANG']->getLL('show_obsolete') . '</label>&nbsp;&nbsp;' . t3lib_BEfunc::getFuncCheck(0, 'SET[display_obsolete]', $this->MOD_SETTINGS['display_obsolete'], '', '', 'id="checkDisplayObsolete"');
608 }
609
610 $this->content.=$this->doc->section('','<form action="index.php" method="post" name="pageform"><span class="nobr">' . ($menu ? $menu : '&nbsp;') . '</span></form>');
611 $this->content.=$this->doc->spacer(10);
612
613 switch((string)$this->MOD_SETTINGS['function']) {
614 case '0':
615 // Lists loaded (installed) extensions
616 $this->extensionList_loaded();
617 break;
618 case '1':
619 // Lists the installed (available) extensions
620 $this->extensionList_installed();
621 break;
622 case '2':
623 // Lists the extensions available from online rep.
624 $this->extensionList_import();
625 break;
626 case '3':
627 // Shows the settings screen
628 $this->alterSettings();
629 break;
630 case '4':
631 // Allows to set the translation preferences and check the status
632 $this->translationHandling();
633 break;
634 case '5':
635 // Shows a list of extensions with updates in TER
636 $this->checkForUpdates();
637 break;
638 default:
639 $this->extObjContent();
640 break;
641 }
642 }
643
644 // closing any form?
645 $formTags = substr_count($this->content, '<form') + substr_count($this->content, '</form');
646 if ($formTags % 2 > 0) {
647 $this->content .= '</form>';
648 }
649
650 // Setting up the buttons and markers for docheader
651 $docHeaderButtons = $this->getButtons();
652 $markers = array(
653 'CSH' => $docHeaderButtons['csh'],
654 'FUNC_MENU' => $this->getFuncMenu(),
655 'CONTENT' => $this->content
656 );
657
658 // Build the <body> for the module
659 $this->content = $this->doc->startPage('Extension Manager');
660 $this->content.= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
661 $this->content.= $this->doc->endPage();
662 $this->content = $this->doc->insertStylesAndJS($this->content);
663 }
664
665 /**
666 * Print module content. Called as last thing in the global scope.
667 *
668 * @return void
669 */
670 function printContent() {
671 if ($this->doPrintContent) {
672 echo $this->content;
673 }
674 }
675
676 /**
677 * Create the function menu
678 *
679 * @return string HTML of the function menu
680 */
681 protected function getFuncMenu() {
682 $funcMenu = '';
683 if(!$this->CMD['showExt'] && !$this->CMD['requestInstallExtensions'] && !$this->CMD['importExt'] && !$this->CMD['uploadExt'] && !$this->CMD['importExtInfo']) {
684 $funcMenu = t3lib_BEfunc::getFuncMenu(0, 'SET[function]', $this->MOD_SETTINGS['function'], $this->MOD_MENU['function']);
685 } elseif($this->CMD['showExt'] && (!$this->CMD['standAlone'] && !t3lib_div::_GP('standAlone'))) {
686 $funcMenu = t3lib_BEfunc::getFuncMenu(0, 'SET[singleDetails]', $this->MOD_SETTINGS['singleDetails'], $this->MOD_MENU['singleDetails'], '', '&CMD[showExt]=' . $this->CMD['showExt']);
687 }
688 return $funcMenu;
689 }
690
691 /**
692 * Create the panel of buttons for submitting the form or otherwise perform operations.
693 *
694 * @return array all available buttons as an assoc. array
695 */
696 protected function getButtons() {
697
698 $buttons = array(
699 'csh' => '',
700 'back' => '',
701 'shortcut' => ''
702 );
703 // CSH
704 //$buttons['csh'] = t3lib_BEfunc::cshItem('_MOD_web_func', '', $GLOBALS['BACK_PATH']);
705
706 // Shortcut
707 if ($GLOBALS['BE_USER']->mayMakeShortcut()) {
708 $buttons['shortcut'] = $this->doc->makeShortcutIcon('CMD','function',$this->MCONF['name']);
709 }
710 // Back
711 if(($this->CMD['showExt'] && (!$this->CMD['standAlone'] && !t3lib_div::_GP('standAlone'))) || ($this->CMD['importExt'] || $this->CMD['uploadExt'] && (!$this->CMD['standAlone'])) || $this->CMD['importExtInfo']) {
712 $buttons['back'] = '<a href="index.php" class="typo3-goBack"><img' . t3lib_iconWorks::skinImg($this->doc->backPath, 'gfx/goback.gif') . ' title="' . $GLOBALS['LANG']->getLL('go_back') . '" class="absmiddle" alt="" /></a>';
713 }
714
715 return $buttons;
716 }
717
718
719
720
721
722
723
724
725 /*********************************
726 *
727 * Function Menu Applications
728 *
729 *********************************/
730
731 /**
732 * Listing of loaded (installed) extensions
733 *
734 * @return void
735 */
736 function extensionList_loaded() {
737 global $TYPO3_LOADED_EXT;
738
739 list($list,$cat) = $this->getInstalledExtensions();
740
741 // Loaded extensions
742 $content = '';
743 $lines = array();
744
745 // Available extensions
746 if (is_array($cat[$this->MOD_SETTINGS['listOrder']])) {
747 $content='';
748 $lines=array();
749 $lines[] = $this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="1" height="1" alt="" /></td>'));
750
751 foreach($cat[$this->MOD_SETTINGS['listOrder']] as $catName => $extEkeys) {
752 natcasesort($extEkeys);
753 $extensions = array();
754 foreach ($extEkeys as $extKey => $value) {
755 if (array_key_exists($extKey,$TYPO3_LOADED_EXT) && ($this->MOD_SETTINGS['display_shy'] || !$list[$extKey]['EM_CONF']['shy']) && $this->searchExtension($extKey,$list[$extKey])) {
756 if (in_array($extKey, $this->requiredExt)) {
757 $loadUnloadLink = '<strong>' . $GLOBALS['TBE_TEMPLATE']->rfw($GLOBALS['LANG']->getLL('extension_required_short')) . '</strong>';
758 } else {
759 $loadUnloadLink = '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1').'">'.$this->removeButton().'</a>';
760 }
761
762 $extensions[] = $this->extensionListRow($extKey,$list[$extKey],array('<td class="bgColor">'.$loadUnloadLink.'</td>'));
763 }
764 }
765 if(count($extensions)) {
766 $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><br /></td></tr>';
767 $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><img '.t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'],'gfx/i/sysf.gif', 'width="18" height="16"').' align="top" alt="" /><strong>'.htmlspecialchars($this->listOrderTitle($this->MOD_SETTINGS['listOrder'],$catName)).'</strong></td></tr>';
768 $lines[] = implode(LF,$extensions);
769 }
770 }
771 }
772
773 $content.= t3lib_BEfunc::cshItem('_MOD_tools_em', 'loaded', $GLOBALS['BACK_PATH'],'');
774 $content.= '<form action="index.php" method="post" name="lookupform">';
775 $content.= '<label for="lookUp">' . $GLOBALS['LANG']->getLL('look_up') . '</label> <input type="text" id="lookUp" name="lookUp" value="' . htmlspecialchars($this->lookUpStr) . '" /><input type="submit" value="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:search') . '" /><br /><br />';
776
777 $content.= '</form>
778
779 <!-- Loaded Extensions List -->
780 <table border="0" cellpadding="2" cellspacing="1">'.implode('',$lines).'</table>';
781
782 $this->content.=$this->doc->section($GLOBALS['LANG']->getLL('loaded_exts'),$content,0,1);
783 }
784
785 /**
786 * Listing of available (installed) extensions
787 *
788 * @return void
789 */
790 function extensionList_installed() {
791 global $TYPO3_LOADED_EXT;
792
793 list($list,$cat)=$this->getInstalledExtensions();
794
795 // Available extensions
796 if (is_array($cat[$this->MOD_SETTINGS['listOrder']])) {
797 $content='';
798 $lines=array();
799 $lines[]=$this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="18" height="1" alt="" /></td>'));
800
801 $allKeys=array();
802 foreach($cat[$this->MOD_SETTINGS['listOrder']] as $catName => $extEkeys) {
803 if(!$this->MOD_SETTINGS['display_obsolete'] && $catName=='obsolete') continue;
804
805 $allKeys[]='';
806 $allKeys[]='TYPE: '.$catName;
807
808 natcasesort($extEkeys);
809 $extensions = array();
810 foreach ($extEkeys as $extKey => $value) {
811 $allKeys[]=$extKey;
812 if ((!$list[$extKey]['EM_CONF']['shy'] || $this->MOD_SETTINGS['display_shy']) &&
813 ($list[$extKey]['EM_CONF']['state']!='obsolete' || $this->MOD_SETTINGS['display_obsolete'])
814 && $this->searchExtension($extKey,$list[$extKey])) {
815 $loadUnloadLink = t3lib_extMgm::isLoaded($extKey)?
816 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->removeButton().'</a>':
817 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[load]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->installButton().'</a>';
818 if (in_array($extKey,$this->requiredExt)) {
819 $loadUnloadLink = '<strong>' . $GLOBALS['TBE_TEMPLATE']->rfw($GLOBALS['LANG']->getLL('extension_required_short')) . '</strong>';
820 }
821 $theRowClass = t3lib_extMgm::isLoaded($extKey)? 'em-listbg1' : 'em-listbg2';
822 $extensions[]=$this->extensionListRow($extKey,$list[$extKey],array('<td class="bgColor">'.$loadUnloadLink.'</td>'),$theRowClass);
823 }
824 }
825 if(count($extensions)) {
826 $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><br /></td></tr>';
827 $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><img '.t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'],'gfx/i/sysf.gif', 'width="18" height="16"').'align="top" alt="" /><strong>'.htmlspecialchars($this->listOrderTitle($this->MOD_SETTINGS['listOrder'],$catName)).'</strong></td></tr>';
828 $lines[] = implode(LF,$extensions);
829 }
830 }
831
832 $content.='
833
834
835 <!--
836 EXTENSION KEYS:
837
838 '.trim(implode(LF,$allKeys)).'
839
840 -->
841
842 ';
843
844 $content.= t3lib_BEfunc::cshItem('_MOD_tools_em', 'avail', $GLOBALS['BACK_PATH'], '|<br />');
845 $content.= sprintf($GLOBALS['LANG']->getLL('how_to_install'), $this->installButton()) . ' <br />' .
846 sprintf($GLOBALS['LANG']->getLL('how_to_uninstall'), $this->removeButton()). ' <br /><br />';
847 $content .= '<form action="index.php" method="post" name="lookupform">';
848 $content .= '<label for="lookUp">' . $GLOBALS['LANG']->getLL('look_up') . '</label> <input type="text" id="lookUp" name="lookUp" value="' . htmlspecialchars($this->lookUpStr) . '" /><input type="submit" value="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:search') . '" /></form><br /><br />';
849 $content.= $this->securityHint.'<br /><br />';
850
851 $content.= '<table border="0" cellpadding="2" cellspacing="1">'.implode('',$lines).'</table>';
852
853 $this->content.=$this->doc->section(sprintf($GLOBALS['LANG']->getLL('available_extensions'), $this->MOD_MENU['listOrder'][$this->MOD_SETTINGS['listOrder']]),$content,0,1);
854 }
855 }
856
857 /**
858 * Listing remote extensions from online repository
859 *
860 * @return void
861 */
862 function extensionList_import() {
863 global $TYPO3_LOADED_EXT;
864 $content='';
865
866 // Listing from online repository:
867 if ($this->listRemote) {
868 list($inst_list,) = $this->getInstalledExtensions();
869 $this->inst_keys = array_flip(array_keys($inst_list));
870
871 $this->detailCols[1]+=6;
872
873 // see if we have an extensionlist at all
874 $this->extensionCount = $this->xmlhandler->countExtensions();
875 if (!$this->extensionCount) {
876 $content .= $this->fetchMetaData('extensions');
877 }
878
879 if($this->MOD_SETTINGS['listOrder']=='author_company') {
880 $this->listingLimit = $this->listingLimitAuthor;
881 }
882
883 $this->pointer = intval(t3lib_div::_GP('pointer'));
884 $offset = $this->listingLimit*$this->pointer;
885
886 if($this->MOD_SETTINGS['display_own'] && strlen($this->fe_user['username'])) {
887 $this->xmlhandler->searchExtensionsXML($this->listRemote_search, $this->fe_user['username'], $this->MOD_SETTINGS['listOrder'], TRUE);
888 } else {
889 $this->xmlhandler->searchExtensionsXML($this->listRemote_search, '', $this->MOD_SETTINGS['listOrder'], TRUE, FALSE, $offset, $this->listingLimit);
890 }
891 if (count($this->xmlhandler->extensionsXML)) {
892 list($list,$cat) = $this->prepareImportExtList(true);
893
894 // Available extensions
895 if (is_array($cat[$this->MOD_SETTINGS['listOrder']])) {
896 $lines=array();
897 $lines[]=$this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="18" height="1" alt="" /></td>'),1);
898
899 foreach($cat[$this->MOD_SETTINGS['listOrder']] as $catName => $extEkeys) {
900 if (count($extEkeys)) {
901 $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><br /></td></tr>';
902 $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><img '.t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'],'gfx/i/sysf.gif', 'width="18" height="16"').'align="top" alt="" /><strong>'.htmlspecialchars($this->listOrderTitle($this->MOD_SETTINGS['listOrder'],$catName)).'</strong></td></tr>';
903
904 natcasesort($extEkeys);
905 foreach ($extEkeys as $extKey => $value) {
906 $version = array_keys($list[$extKey]['versions']);
907 $version = end($version);
908 $ext = $list[$extKey]['versions'][$version];
909 $ext['downloadcounter_all'] = $list[$extKey]['downloadcounter'];
910 $ext['_ICON'] = $list[$extKey]['_ICON'];
911 $loadUnloadLink='';
912 if ($inst_list[$extKey]['type']!='S' && (!isset($inst_list[$extKey]) || $this->versionDifference($version,$inst_list[$extKey]['EM_CONF']['version'],$this->versionDiffFactor))) {
913 if (isset($inst_list[$extKey])) {
914 // update
915 if ($inst_list[$extKey]['EM_CONF']['state'] != 'excludeFromUpdates') {
916 $loc= ($inst_list[$extKey]['type']=='G'?'G':'L');
917 $aUrl = 'index.php?CMD[importExt]='.$extKey.'&CMD[extVersion]='.$version.'&CMD[loc]='.$loc;
918 $loadUnloadLink .= '<a href="' . htmlspecialchars($aUrl) . '"><img src="' . $GLOBALS['BACK_PATH'] . 'gfx/import_update.gif" width="12" height="12" title="' . sprintf($GLOBALS['LANG']->getLL('do_update'), ($loc == 'G' ? $GLOBALS['LANG']->getLL('global') : $GLOBALS['LANG']->getLL('local'))) . '" alt="" /></a>';
919 } else {
920 // extension is marked as "excludeFromUpdates"
921 $loadUnloadLink .= '<img src="' . $GLOBALS['BACK_PATH'] . 'gfx/icon_warning.gif" width="18" height="16" title="' . $GLOBALS['LANG']->getLL('excluded_from_updates') . '" alt="" />';
922 }
923 } else {
924 // import
925 $aUrl = 'index.php?CMD[importExt]='.$extKey.'&CMD[extVersion]='.$version.'&CMD[loc]=L';
926 $loadUnloadLink .= '<a href="' . htmlspecialchars($aUrl) . '"><img src="' . $GLOBALS['BACK_PATH'] . 'gfx/import.gif" width="12" height="12" title="' . $GLOBALS['LANG']->getLL('import_to_local_dir') . '" alt="" /></a>';
927 }
928 } else {
929 $loadUnloadLink = '&nbsp;';
930 }
931
932 if (isset($inst_list[$extKey])) {
933 $theRowClass = t3lib_extMgm::isLoaded($extKey) ? 'em-listbg1' : 'em-listbg2';
934 } else {
935 $theRowClass = 'em-listbg3';
936 }
937
938 $lines[]=$this->extensionListRow($extKey,$ext,array('<td class="bgColor">'.$loadUnloadLink.'</td>'),$theRowClass,$inst_list,1,'index.php?CMD[importExtInfo]='.rawurlencode($extKey));
939 unset($list[$extKey]);
940 }
941 }
942 }
943 unset($list);
944
945 // CSH:
946 $content .= t3lib_BEfunc::cshItem('_MOD_tools_em', 'import_ter', $GLOBALS['BACK_PATH'], '|<br />');
947 $onsubmit = "window.location.href='index.php?ter_connect=1&ter_search='+escape(this.elements['lookUp'].value);return false;";
948 $content .= '<form action="index.php" method="post" onsubmit="' . htmlspecialchars($onsubmit) .
949 '"><label for="lookUp">' . $GLOBALS['LANG']->getLL('list_or_look_up_extensions') . '</label><br />
950 <input type="text" id="lookUp" name="lookUp" value="' . htmlspecialchars($this->listRemote_search) .
951 '" /> <input type="submit" value="' . $GLOBALS['LANG']->getLL('look_up_button') . '" /></form><br /><br />';
952
953 $content .= $this->browseLinks();
954
955 $content.= '
956
957 <!-- TER Extensions list -->
958 <table border="0" cellpadding="2" cellspacing="1">'.implode(LF,$lines).'</table>';
959 $content .= '<br />'.$this->browseLinks();
960 $content.= '<br /><br />'.$this->securityHint;
961 $content .= '<br /><br /><strong>' . $GLOBALS['LANG']->getLL('privacy_notice_header') .
962 '</strong><br /> ' . $this->privacyNotice;
963
964 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('extensions_repository_group_by') . ' ' .
965 $this->MOD_MENU['listOrder'][$this->MOD_SETTINGS['listOrder']], $content, 0, 1);
966
967 // Plugins which are NOT uploaded to repository but present on this server.
968 $content='';
969 $lines=array();
970 if (count($this->inst_keys)) {
971 foreach ($this->inst_keys as $extKey => $value) {
972 $this->xmlhandler->searchExtensionsXMLExact($extKey, '', '', true);
973 if((strlen($this->listRemote_search) && !stristr($extKey,$this->listRemote_search)) || isset($this->xmlhandler->extensionsXML[$extKey])) continue;
974
975 $loadUnloadLink = t3lib_extMgm::isLoaded($extKey)?
976 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->removeButton().'</a>':
977 '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[load]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->installButton().'</a>';
978 if (in_array($extKey,$this->requiredExt)) {
979 $loadUnloadLink = '<strong>' .$GLOBALS['TBE_TEMPLATE']->rfw($GLOBALS['LANG']->getLL('extension_required_short')) . '</strong>';
980 }
981 $lines[]=$this->extensionListRow($extKey,$inst_list[$extKey],array('<td class="bgColor">'.$loadUnloadLink.'</td>'),t3lib_extMgm::isLoaded($extKey)?'em-listbg1':'em-listbg2');
982 }
983 }
984 if(count($lines)) {
985 $content .= $GLOBALS['LANG']->getLL('list_of_local_extensions') .
986 '<br />' . $GLOBALS['LANG']->getLL('might_be_user_defined') . '<br /><br />';
987 $content.= '<table border="0" cellpadding="2" cellspacing="1">'.
988 $this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="18" height="1" alt="" /></td>')).
989 implode('',$lines).'</table>';
990 $this->content.=$this->doc->spacer(20);
991 $this->content.=$this->doc->section($GLOBALS['LANG']->getLL('only_on_this_server'), $content, 0, 1);
992 }
993 }
994 } else {
995 $content .= t3lib_BEfunc::cshItem('_MOD_tools_em', 'import_ter', $GLOBALS['BACK_PATH'], '|<br />');
996 $onsubmit = "window.location.href='index.php?ter_connect=1&ter_search='+escape(this.elements['lookUp'].value);return false;";
997 $content .= '<form action="index.php" method="post" onsubmit="' . htmlspecialchars($onsubmit) .
998 '"><label for="lookUp">' .
999 $GLOBALS['LANG']->getLL('list_or_look_up_extensions') . '</label><br />
1000 <input type="text" id="lookUp" name="lookUp" value="' . htmlspecialchars($this->listRemote_search) .
1001 '" /> <input type="submit" value="' . $GLOBALS['LANG']->getLL('look_up_button') . '" /></form><br /><br />';
1002
1003 $content .= '<p><strong>' . $GLOBALS['LANG']->getLL('no_matching_extensions') . '</strong></p>';
1004
1005 $content .= '<br /><br /><strong>' . $GLOBALS['LANG']->getLL('privacy_notice_header') .
1006 '</strong><br /> ' . $this->privacyNotice;
1007 $this->content.=$this->doc->section($GLOBALS['LANG']->getLL('extensions_repository_group_by') . ' ' .
1008 $this->MOD_MENU['listOrder'][$this->MOD_SETTINGS['listOrder']], $content, 0, 1);
1009 }
1010 } else {
1011 // CSH
1012 $content .= t3lib_BEfunc::cshItem('_MOD_tools_em', 'import', $GLOBALS['BACK_PATH'], '|<br />');
1013
1014 $onsubmit = "window.location.href='index.php?ter_connect=1&ter_search='+escape(this.elements['lookUp'].value);return false;";
1015 $content .= '<form action="index.php" method="post" onsubmit="' . htmlspecialchars($onsubmit) .
1016 '"><label for="lookUp">' .
1017 $GLOBALS['LANG']->getLL('list_or_look_up_extensions') . '</label><br />
1018 <input type="text" id="lookUp" name="lookUp" value="" /> <input type="submit" value="' .
1019 $GLOBALS['LANG']->getLL('look_up_button') . '" /><br /><br />';
1020
1021 if ($this->CMD['fetchMetaData']) { // fetches mirror/extension data from online rep.
1022 $content .= $this->fetchMetaData($this->CMD['fetchMetaData']);
1023 } else {
1024 $onCLick = "window.location.href='index.php?CMD[fetchMetaData]=extensions';return false;";
1025 $content .= $GLOBALS['LANG']->getLL('connect_to_ter') . '<br />
1026 <input type="submit" value="' . $GLOBALS['LANG']->getLL('retrieve_update') .
1027 '" onclick="' . htmlspecialchars($onCLick) . '" />';
1028 if (is_file(PATH_site.'typo3temp/extensions.xml.gz')) {
1029 $dateFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'];
1030 $timeFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'];
1031 $content .= ' ' . sprintf($GLOBALS['LANG']->getLL('ext_list_last_updated') . ' ',
1032 date(
1033 $dateFormat . ', ' . $timeFormat,
1034 filemtime(PATH_site . 'typo3temp/extensions.xml.gz')
1035 )
1036 );
1037 }
1038 }
1039 $content.= '</form><br /><br />'.$this->securityHint;
1040 $content .= '<br /><br /><strong>' . $GLOBALS['LANG']->getLL('privacy_notice_header') .
1041 '</strong><br />' . $this->privacyNotice;
1042
1043 $this->content.=$this->doc->section($GLOBALS['LANG']->getLL('in_repository'), $content, 0, 1);
1044 }
1045
1046 // Upload:
1047 if ($this->importAtAll()) {
1048 $content= '<form action="index.php" enctype="'.$GLOBALS['TYPO3_CONF_VARS']['SYS']['form_enctype'].'" method="post">
1049 <label for="upload_ext_file">' . $GLOBALS['LANG']->getLL('upload_t3x') . '</label><br />
1050 <input type="file" size="60" id="upload_ext_file" name="upload_ext_file" /><br />' .
1051 $GLOBALS['LANG']->getLL('upload_to_location') . '<br />
1052 <select name="CMD[loc]">';
1053 if ($this->importAsType('L')) $content .= '<option value="L">' . $GLOBALS['LANG']->getLL('local_folder') . '</option>';
1054 if ($this->importAsType('G')) $content .= '<option value="G">' . $GLOBALS['LANG']->getLL('global_folder') . '</option>';
1055 if ($this->importAsType('S')) $content .= '<option value="S">' . $GLOBALS['LANG']->getLL('system_folder') . '</option>';
1056 $content.='</select><br />
1057 <input type="checkbox" value="1" name="CMD[uploadOverwrite]" id="checkUploadOverwrite" /> <label for="checkUploadOverwrite">' .
1058 $GLOBALS['LANG']->getLL('overwrite_ext') . '</label><br />
1059 <input type="submit" name="CMD[uploadExt]" value="' . $GLOBALS['LANG']->getLL('upload_ext_file') . '" /></form><br />
1060 ';
1061 } else $content=$this->noImportMsg();
1062
1063 $this->content.=$this->doc->spacer(20);
1064 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('upload_ext_directly'), $content, 0, 1);
1065 }
1066
1067 /**
1068 * Generates a link to the next page of extensions
1069 *
1070 * @return void
1071 */
1072 function browseLinks() {
1073 $content = '';
1074 if ($this->pointer) {
1075 $content .= '<a href="' . t3lib_div::linkThisScript(array('pointer' => $this->pointer-1)) .
1076 '" class="typo3-prevPage"><img' . t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'],
1077 'gfx/pilleft_n.gif', 'width="14" height="14"') .
1078 ' alt="' . $GLOBALS['LANG']->getLL('previous_page') . '" /> ' .
1079 $GLOBALS['LANG']->getLL('previous_page') . '</a>';
1080 }
1081 if ($content) $content .= '&nbsp;&nbsp;&nbsp;';
1082 if (intval($this->xmlhandler->matchingCount/$this->listingLimit)>$this->pointer) {
1083 $content .= '<a href="' . t3lib_div::linkThisScript(array('pointer' => $this->pointer+1)) .
1084 '" class="typo3-nextPage"><img' . t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'],
1085 'gfx/pilright_n.gif', 'width="14" height="14"') .
1086 ' alt="' . $GLOBALS['LANG']->getLL('next_page') . '" /> ' .
1087 $GLOBALS['LANG']->getLL('next_page') . '</a>';
1088 }
1089 $upper = (($this->pointer+1)*$this->listingLimit);
1090 if ($upper>$this->xmlhandler->matchingCount) {
1091 $upper = $this->xmlhandler->matchingCount;
1092 }
1093 if ($content) $content .= '<br /><br />' .
1094 sprintf($GLOBALS['LANG']->getLL('showing_extensions_from_to'),
1095 '<strong>' . ($this->pointer*$this->listingLimit+1) . '</strong>',
1096 '<strong>' . $upper . '</strong>'
1097 );
1098 if ($content) $content .= '<br /><br />';
1099 return $content;
1100 }
1101
1102 /**
1103 * Allows changing of settings
1104 *
1105 * @return void
1106 */
1107 function alterSettings() {
1108
1109 // Prepare the HTML output:
1110 $content.= '
1111 ' . t3lib_BEfunc::cshItem('_MOD_tools_em', 'settings', $GLOBALS['BACK_PATH'], '|<br />') . '
1112 <form action="index.php" method="post" name="altersettings">
1113 <fieldset><legend>' . $GLOBALS['LANG']->getLL('user_settings') . '</legend>
1114 <table border="0" cellpadding="2" cellspacing="2">
1115 <tr class="bgColor4">
1116 <td><label for="set_fe_u">' . $GLOBALS['LANG']->getLL('enter_repository_username') . '</label></td>
1117 <td><input type="text" id="set_fe_u" name="SET[fe_u]" value="'.htmlspecialchars($this->MOD_SETTINGS['fe_u']).'" /></td>
1118 </tr>
1119 <tr class="bgColor4">
1120 <td><label for="set_fe_p">' . $GLOBALS['LANG']->getLL('enter_repository_password') . '</label></td>
1121 <td><input type="password" id="set_fe_p" name="SET[fe_p]" value="'.htmlspecialchars($this->MOD_SETTINGS['fe_p']).'" /></td>
1122 </tr>
1123 </table>
1124 <strong>' . $GLOBALS['LANG']->getLL('notice') . '</strong> ' .
1125 $GLOBALS['LANG']->getLL('repository_password_info') . '
1126 </fieldset>
1127 <br />
1128 <br />
1129 <fieldset><legend>' . $GLOBALS['LANG']->getLL('mirror_selection') . '</legend>
1130 <table border="0" cellpadding="2" cellspacing="2">
1131 <tr class="bgColor4">
1132 <td><label for="set_mirror_list_url">' . $GLOBALS['LANG']->getLL('mirror_list_url') . '</label></td>
1133 <td><input type="text" size="50" id="set_mirror_list_url" name="SET[mirrorListURL]" value="'.htmlspecialchars($this->MOD_SETTINGS['mirrorListURL']).'" /></td>
1134 </tr>
1135 </table>
1136 </fieldset>
1137 <br />
1138 <p>' . $GLOBALS['LANG']->getLL('mirror_select') . '<br /><br /></p>
1139 <fieldset><legend>' . $GLOBALS['LANG']->getLL('mirror_list') . '</legend>';
1140 if(!empty($this->MOD_SETTINGS['mirrorListURL'])) {
1141 if ($this->CMD['fetchMetaData']) { // fetches mirror/extension data from online rep.
1142 $content .= $this->fetchMetaData($this->CMD['fetchMetaData']);
1143 } else {
1144 $content .= '<a href="index.php?CMD[fetchMetaData]=mirrors">' . $GLOBALS['LANG']->getLL('mirror_list_reload') . '</a>';
1145 }
1146 }
1147 $content .= '<br />
1148 <table cellspacing="4" style="text-align:left; vertical-alignment:top;">
1149 <tr>
1150 <td>' . $GLOBALS['LANG']->getLL('mirror_use') . '</td>
1151 <td>' . $GLOBALS['LANG']->getLL('mirror_name') . '</td>
1152 <td>' . $GLOBALS['LANG']->getLL('mirror_url') . '</td>
1153 <td>' . $GLOBALS['LANG']->getLL('mirror_country') . '</td>
1154 <td>' . $GLOBALS['LANG']->getLL('mirror_sponsored_by') . '</td>
1155 </tr>
1156 ';
1157
1158 if (!strlen($this->MOD_SETTINGS['extMirrors'])) $this->fetchMetaData('mirrors');
1159 $extMirrors = unserialize($this->MOD_SETTINGS['extMirrors']);
1160 $extMirrors[''] = array('title'=>$GLOBALS['LANG']->getLL('mirror_use_random'));
1161 ksort($extMirrors);
1162 if(is_array($extMirrors)) {
1163 foreach($extMirrors as $k => $v) {
1164 if(isset($v['sponsor'])) {
1165 $sponsor = '<a href="'.htmlspecialchars($v['sponsor']['link']).'" target="_blank"><img src="'.$v['sponsor']['logo'].'" title="'.htmlspecialchars($v['sponsor']['name']).'" alt="'.htmlspecialchars($v['sponsor']['name']).'" /></a>';
1166 }
1167 $selected = ($this->MOD_SETTINGS['selectedMirror']==$k) ? 'checked="checked"' : '';
1168 $content.='<tr class="bgColor4">
1169 <td><input type="radio" name="SET[selectedMirror]" id="selectedMirror'.$k.'" value="'.$k.'" '.$selected.'/></td><td><label for="selectedMirror'.$k.'">'.htmlspecialchars($v['title']).'</label></td><td>'.htmlspecialchars($v['host'].$v['path']).'</td><td>'.$v['country'].'</td><td>'.$sponsor.'</td></tr>';
1170 }
1171 }
1172 $content.= '
1173 </table>
1174 </fieldset>
1175 <fieldset>
1176 <br />
1177 <table border="0" cellpadding="2" cellspacing="2">
1178 <tr class="bgColor4">
1179 <td><label for="set_rep_url">' . $GLOBALS['LANG']->getLL('enter_repository_url') . '</label></td>
1180 <td><input type="text" size="50" id="set_rep_url" name="SET[rep_url]" value="'.htmlspecialchars($this->MOD_SETTINGS['rep_url']).'" /></td>
1181 </tr>
1182 </table>
1183
1184 ' . $GLOBALS['LANG']->getLL('repository_url_hint') . '<br />
1185 </fieldset>
1186 <br />
1187 <input type="submit" value="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_tsfe.xml:update') . '" />
1188 </form>
1189 ';
1190
1191 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('repository_settings'), $content, 0, 1);
1192 }
1193
1194 /**
1195 * Allows to set the translation preferences and check the status
1196 *
1197 * @return void
1198 */
1199 function translationHandling() {
1200 global $LANG, $TYPO3_LOADED_EXT;
1201 $LANG->includeLLFile('EXT:setup/mod/locallang.xml');
1202
1203 //prepare docheader
1204 $docHeaderButtons = $this->getButtons();
1205 $markers = array(
1206 'CSH' => $docHeaderButtons['csh'],
1207 'FUNC_MENU' => $this->getFuncMenu(),
1208 );
1209
1210
1211 $incoming = t3lib_div::_POST('SET');
1212 if(isset($incoming['selectedLanguages']) && is_array($incoming['selectedLanguages'])) {
1213 t3lib_BEfunc::getModuleData($this->MOD_MENU, array('selectedLanguages' => serialize($incoming['selectedLanguages'])), $this->MCONF['name'], '', 'selectedLanguages');
1214 $this->MOD_SETTINGS['selectedLanguages'] = serialize($incoming['selectedLanguages']);
1215 }
1216
1217 $selectedLanguages = unserialize($this->MOD_SETTINGS['selectedLanguages']);
1218 if(count($selectedLanguages)==1 && empty($selectedLanguages[0])) $selectedLanguages = array();
1219 $theLanguages = t3lib_div::trimExplode('|',TYPO3_languages);
1220 foreach($theLanguages as $val) {
1221 if ($val!='default') {
1222 $localLabel = ' - ['.htmlspecialchars($GLOBALS['LOCAL_LANG']['default']['lang_'.$val]).']';
1223 $selected = (is_array($selectedLanguages) && in_array($val, $selectedLanguages)) ? ' selected="selected"' : '';
1224 $opt[$GLOBALS['LANG']->getLL('lang_' . $val, 1) . '--' . $val] = '
1225 <option value="'.$val.'"'.$selected.'>'.$LANG->getLL('lang_'.$val,1).$localLabel.'</option>';
1226 }
1227 }
1228 ksort($opt);
1229
1230 // Prepare the HTML output:
1231 $content.= '
1232 ' . t3lib_BEfunc::cshItem('_MOD_tools_em', 'translation', $GLOBALS['BACK_PATH'], '|<br />') . '
1233 <form action="index.php" method="post" name="translationform">
1234 <fieldset><legend>' . $GLOBALS['LANG']->getLL('translation_settings') . '</legend>
1235 <table border="0" cellpadding="2" cellspacing="2">
1236 <tr class="bgColor4">
1237 <td>' . $GLOBALS['LANG']->getLL('languages_to_fetch') . '</td>
1238 <td>
1239 <select name="SET[selectedLanguages][]" multiple="multiple" size="10">
1240 <option>&nbsp;</option>'.
1241 implode('',$opt).'
1242 </select>
1243 </td>
1244 </tr>
1245 </table>
1246 <br />
1247 <p>' . $GLOBALS['LANG']->getLL('translation_info') . '<br />
1248 <br />' . $GLOBALS['LANG']->getLL('translation_loaded_exts') . '</p>
1249 </fieldset>
1250 <br />
1251 <input type="submit" value="' . $GLOBALS['LANG']->getLL('translation_save_selection') . '" />
1252 <br />
1253 </form>';
1254
1255 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('translation_settings'), $content, 0, 1);
1256
1257 if(count($selectedLanguages)>0) {
1258 $mirrorURL = $this->getMirrorURL();
1259 $content = '<input type="button" value="' . $GLOBALS['LANG']->getLL('translation_check_status_button') .
1260 '" onclick="document.location.href=\'' . htmlspecialchars(t3lib_div::linkThisScript(array('l10n'=>'check'))) .
1261 '\'" />&nbsp;<input type="button" value="' . $GLOBALS['LANG']->getLL('translation_update_button') .
1262 '" onclick="document.location.href=\'' . htmlspecialchars(t3lib_div::linkThisScript(array('l10n'=>'update'))) .
1263 '\'" />';
1264
1265 // as this page loads dynamically, quit output buffering caused by ob_gzhandler
1266 t3lib_div::cleanOutputBuffers();
1267
1268 if(t3lib_div::_GET('l10n') == 'check') {
1269 $loadedExtensions = array_keys($TYPO3_LOADED_EXT);
1270 $loadedExtensions = array_diff($loadedExtensions,array('_CACHEFILE'));
1271
1272 // Override content output - we now do that ourselves:
1273 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('translation_status'), $content, 0, 1);
1274 // Setting up the buttons and markers for docheader
1275 $content = $this->doc->startPage('Extension Manager');
1276 $content.= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
1277 $contentParts=explode('###CONTENT###',$content);
1278
1279 echo $contentParts[0].$this->content;
1280
1281 $this->doPrintContent = FALSE;
1282 flush();
1283
1284 echo '
1285 <br />
1286 <br />
1287 <p id="progress-message">
1288 ' . $GLOBALS['LANG']->getLL('translation_check_status') . '
1289 </p>
1290 <br />
1291 <div style="width:100%; height:20px; border: 1px solid black;">
1292 <div id="progress-bar" style="float: left; width: 0%; height: 20px; background-color:green;">&nbsp;</div>
1293 <div id="transparent-bar" style="float: left; width: 100%; height: 20px; background-color:'.$this->doc->bgColor2.';">&nbsp;</div>
1294 </div>
1295 <br />
1296 <br /><p>' . $GLOBALS['LANG']->getLL('translation_table_check') . '</p><br />
1297 <table border="0" cellpadding="2" cellspacing="2">
1298 <tr class="bgColor2"><td>' . $GLOBALS['LANG']->getLL('translation_extension_key') . '</td>
1299 ';
1300
1301 foreach($selectedLanguages as $lang) {
1302 echo ('<td>'.$LANG->getLL('lang_'.$lang,1).'</td>');
1303 }
1304 echo ('</tr>');
1305
1306 $counter = 1;
1307 foreach($loadedExtensions as $extKey) {
1308
1309 $percentDone = intval (($counter / count($loadedExtensions)) * 100);
1310 echo ('
1311 <script type="text/javascript">
1312 document.getElementById("progress-bar").style.width = "'.$percentDone.'%";
1313 document.getElementById("transparent-bar").style.width = "'.(100-$percentDone).'%";
1314 document.getElementById("progress-message").firstChild.data="' .
1315 sprintf($GLOBALS['LANG']->getLL('translation_checking_extension'), $extKey) . '";
1316 </script>
1317 ');
1318
1319 flush();
1320 $translationStatusArr = $this->terConnection->fetchTranslationStatus($extKey,$mirrorURL);
1321
1322 echo ('<tr class="bgColor4"><td>'.$extKey.'</td>');
1323 foreach($selectedLanguages as $lang) {
1324 // remote unknown -> no l10n available
1325 if(!isset($translationStatusArr[$lang])) {
1326 echo ('<td title="' . $GLOBALS['LANG']->getLL('translation_no_translation') . '">' .
1327 $GLOBALS['LANG']->getLL('translation_n_a') . '</td>');
1328 continue;
1329 }
1330 // determine local md5 from zip
1331 if(is_file(PATH_site.'typo3temp/'.$extKey.'-l10n-'.$lang.'.zip')) {
1332 $localmd5 = md5_file(PATH_site.'typo3temp/'.$extKey.'-l10n-'.$lang.'.zip');
1333 } else {
1334 echo ('<td title="' . $GLOBALS['LANG']->getLL('translation_not_installed') .
1335 '" style="background-color:#ff0">' . $GLOBALS['LANG']->getLL('translation_status_unknown') .
1336 '</td>');
1337 continue;
1338 }
1339 // local!=remote -> needs update
1340 if($localmd5 != $translationStatusArr[$lang]['md5']) {
1341 echo ('<td title="' . $GLOBALS['LANG']->getLL('translation_needs_update') .
1342 '" style="background-color:#ff0">' . $GLOBALS['LANG']->getLL('translation_status_update') .
1343 '</td>');
1344 continue;
1345 }
1346 echo ('<td title="' . $GLOBALS['LANG']->getLL('translation_is_ok') .
1347 '" style="background-color:#69a550">' . $GLOBALS['LANG']->getLL('translation_status_ok') .
1348 '</td>');
1349 }
1350 echo ('</tr>');
1351
1352 $counter ++;
1353 }
1354 echo '</table>
1355 <script type="text/javascript">
1356 document.getElementById("progress-message").firstChild.data="' .
1357 $GLOBALS['LANG']->getLL('translation_check_done') . '";
1358 </script>
1359 ';
1360 echo $contentParts[1] . $this->doc->endPage();
1361 exit;
1362
1363 } elseif(t3lib_div::_GET('l10n') == 'update') {
1364 $loadedExtensions = array_keys($TYPO3_LOADED_EXT);
1365 $loadedExtensions = array_diff($loadedExtensions,array('_CACHEFILE'));
1366
1367 // Override content output - we now do that ourselves:
1368 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('translation_status'), $content, 0, 1);
1369 // Setting up the buttons and markers for docheader
1370 $content = $this->doc->startPage('Extension Manager');
1371 $content.= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
1372 $contentParts=explode('###CONTENT###',$content);
1373
1374 echo $contentParts[0].$this->content;
1375
1376 $this->doPrintContent = FALSE;
1377 flush();
1378
1379 echo ('
1380 <br />
1381 <br />
1382 <p id="progress-message">
1383 ' . $GLOBALS['LANG']->getLL('translation_update_status') . '
1384 </p>
1385 <br />
1386 <div style="width:100%; height:20px; border: 1px solid black;">
1387 <div id="progress-bar" style="float: left; width: 0%; height: 20px; background-color:green;">&nbsp;</div>
1388 <div id="transparent-bar" style="float: left; width: 100%; height: 20px; background-color:'.$this->doc->bgColor2.';">&nbsp;</div>
1389 </div>
1390 <br />
1391 <br /><p>' . $GLOBALS['LANG']->getLL('translation_table_update') . '<br />
1392 <em>' . $GLOBALS['LANG']->getLL('translation_full_check_update') . '</em></p><br />
1393 <table border="0" cellpadding="2" cellspacing="2">
1394 <tr class="bgColor2"><td>' . $GLOBALS['LANG']->getLL('translation_extension_key') . '</td>
1395 ');
1396
1397 foreach($selectedLanguages as $lang) {
1398 echo '<td>'.$LANG->getLL('lang_'.$lang,1).'</td>';
1399 }
1400 echo '</tr>';
1401
1402 $counter = 1;
1403 foreach($loadedExtensions as $extKey) {
1404 $percentDone = intval (($counter / count($loadedExtensions)) * 100);
1405 echo ('
1406 <script type="text/javascript">
1407 document.getElementById("progress-bar").style.width = "'.$percentDone.'%";
1408 document.getElementById("transparent-bar").style.width = "'.(100-$percentDone).'%";
1409 document.getElementById("progress-message").firstChild.data="' .
1410 sprintf($GLOBALS['LANG']->getLL('translation_updating_extension'), $extKey) . '";
1411 </script>
1412 ');
1413
1414 flush();
1415 $translationStatusArr = $this->terConnection->fetchTranslationStatus($extKey,$mirrorURL);
1416
1417 echo ('<tr class="bgColor4"><td>'.$extKey.'</td>');
1418 if(is_array($translationStatusArr)) {
1419 foreach($selectedLanguages as $lang) {
1420 // remote unknown -> no l10n available
1421 if(!isset($translationStatusArr[$lang])) {
1422 echo ('<td title="' . $GLOBALS['LANG']->getLL('translation_no_translation') .
1423 '">' . $GLOBALS['LANG']->getLL('translation_n_a') . '</td>');
1424 continue;
1425 }
1426 // determine local md5 from zip
1427 if(is_file(PATH_site.'typo3temp/'.$extKey.'-l10n-'.$lang.'.zip')) {
1428 $localmd5 = md5_file(PATH_site.'typo3temp/'.$extKey.'-l10n-'.$lang.'.zip');
1429 } else {
1430 $localmd5 = 'zzz';
1431 }
1432 // local!=remote or not installed -> needs update
1433 if($localmd5 != $translationStatusArr[$lang]['md5']) {
1434 $ret = $this->updateTranslation($extKey, $lang, $mirrorURL);
1435 if($ret === true) {
1436 echo ('<td title="' . $GLOBALS['LANG']->getLL('translation_has_been_updated') .
1437 '" style="background-color:#69a550">' . $GLOBALS['LANG']->getLL('translation_status_update') .
1438 '</td>');
1439 } else {
1440 echo ('<td title="' . htmlspecialchars($ret) .
1441 '" style="background-color:#cb3352">' . $GLOBALS['LANG']->getLL('translation_status_error') .
1442 '</td>');
1443 }
1444 continue;
1445 }
1446 echo ('<td title="' . $GLOBALS['LANG']->getLL('translation_is_ok') .
1447 '" style="background-color:#69a550">' . $GLOBALS['LANG']->getLL('translation_status_ok') . '</td>');
1448 }
1449 } else {
1450 echo ('<td colspan="' . count($selectedLanguages) .
1451 '" title="' . $GLOBALS['LANG']->getLL('translation_problems') .
1452 '">' . $GLOBALS['LANG']->getLL('translation_status_could_not_fetch') . '</td>');
1453 }
1454 echo ('</tr>');
1455 $counter++;
1456 }
1457 echo '</table>
1458 <script type="text/javascript">
1459 document.getElementById("progress-message").firstChild.data="' .
1460 $GLOBALS['LANG']->getLL('translation_update_done') . '";
1461 </script>
1462 ';
1463
1464 // Fix permissions on unzipped language xml files in the entire l10n folder and all subfolders
1465 t3lib_div::fixPermissions(PATH_typo3conf . 'l10n', TRUE);
1466
1467 echo $contentParts[1] . $this->doc->endPage();
1468 exit;
1469 }
1470
1471 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('translation_status'), $content, 0, 1);
1472 }
1473 }
1474
1475 /**
1476 * Install translations for all selected languages for an extension
1477 *
1478 * @param string $extKey The extension key to install the translations for
1479 * @param string $lang Language code of translation to fetch
1480 * @param string $mirrorURL Mirror URL to fetch data from
1481 * @return mixed true on success, error string on fauilure
1482 */
1483 function updateTranslation($extKey, $lang, $mirrorURL) {
1484 $l10n = $this->terConnection->fetchTranslation($extKey, $lang, $mirrorURL);
1485 if(is_array($l10n)) {
1486 $file = PATH_site.'typo3temp/'.$extKey.'-l10n-'.$lang.'.zip';
1487 $path = 'l10n/'.$lang.'/';
1488 if(!is_dir(PATH_typo3conf.$path)) t3lib_div::mkdir_deep(PATH_typo3conf,$path);
1489 t3lib_div::writeFile($file, $l10n[0]);
1490 if($this->unzip($file, PATH_typo3conf.$path)) {
1491 return true;
1492 } else {
1493 return $GLOBALS['LANG']->getLL('translation_unpacking_failed');
1494 }
1495 } else {
1496 return $l10n;
1497 }
1498 }
1499
1500 /**
1501 * Install translations for all selected languages for an extension
1502 *
1503 * @param string $extKey The extension key to install the translations for
1504 * @param string $mirrorURL Mirror URL to fetch data from
1505 * @return mixed true on success, error string on fauilure
1506 */
1507 function installTranslationsForExtension($extKey, $mirrorURL) {
1508 $selectedLanguages = unserialize($this->MOD_SETTINGS['selectedLanguages']);
1509 if(!is_array($selectedLanguages)) $selectedLanguages = array();
1510 foreach($selectedLanguages as $lang) {
1511 $l10n = $this->terConnection->fetchTranslation($extKey, $lang, $mirrorURL);
1512 if(is_array($l10n)) {
1513 $file = PATH_typo3conf.'l10n/'.$extKey.'-l10n-'.$lang.'.zip';
1514 $path = 'l10n/'.$lang.'/'.$extKey;
1515 t3lib_div::writeFile($file, $l10n[0]);
1516 if(!is_dir(PATH_typo3conf.$path)) t3lib_div::mkdir_deep(PATH_typo3conf,$path);
1517 if($this->unzip($file, PATH_typo3conf.$path)) {
1518 return true;
1519 } else {
1520 return $GLOBALS['LANG']->getLL('translation_unpacking_failed');
1521 }
1522 } else {
1523 return $l10n;
1524 }
1525 }
1526 }
1527
1528 /**
1529 * Unzips a zip file in the given path.
1530 *
1531 * Uses unzip binary if available, otherwise a pure PHP unzip is used.
1532 *
1533 * @param string $file Full path to zip file
1534 * @param string $path Path to change to before extracting
1535 * @return boolean True on success, false in failure
1536 */
1537 function unzip($file, $path) {
1538 if(strlen($GLOBALS['TYPO3_CONF_VARS']['BE']['unzip_path'])) {
1539 chdir($path);
1540 $cmd = $GLOBALS['TYPO3_CONF_VARS']['BE']['unzip_path'].' -o '.escapeshellarg($file);
1541 exec($cmd, $list, $ret);
1542 return ($ret === 0);
1543 } else {
1544 // we use a pure PHP unzip
1545 $unzip = new em_unzip($file);
1546 $ret = $unzip->extract(array('add_path'=>$path));
1547 return (is_array($ret));
1548 }
1549 }
1550
1551
1552
1553 /*********************************
1554 *
1555 * Command Applications (triggered by GET var)
1556 *
1557 *********************************/
1558
1559 /**
1560 * Returns detailed info about an extension in the online repository
1561 *
1562 * @param string Extension repository uid + optional "private key": [uid]-[key].
1563 * @param [type] $version: ...
1564 * @return void
1565 */
1566 function importExtInfo($extKey, $version='') {
1567
1568 $content = '<form action="index.php" method="post" name="pageform">';
1569
1570 // Fetch remote data:
1571 $this->xmlhandler->searchExtensionsXMLExact($extKey, '', '', true, true);
1572 list($fetchData,) = $this->prepareImportExtList(true);
1573
1574 $versions = array_keys($fetchData[$extKey]['versions']);
1575 natsort($versions);
1576 $version = ($version == '') ? end($versions) : $version;
1577
1578 $opt = array();
1579 foreach($versions as $ver) {
1580 $opt[]='<option value="'.$ver.'"'.(($version == $ver) ? ' selected="selected"' : '').'>'.$ver.'</option>';
1581 }
1582
1583 // "Select version" box:
1584 $onClick = 'window.location.href=\'index.php?CMD[importExtInfo]='.$extKey.'&CMD[extVersion]=\'+document.pageform.extVersion.options[document.pageform.extVersion.selectedIndex].value; return false;';
1585 $select = '<select name="extVersion">' . implode('', $opt) .
1586 '</select> <input type="submit" value="' . $GLOBALS['LANG']->getLL('ext_load_details_button') .
1587 '" onclick="' . htmlspecialchars($onClick) . '" />';
1588
1589 if ($this->importAtAll()) {
1590 // Check for write-protected extension
1591 list($inst_list,) = $this->getInstalledExtensions();
1592 if ($inst_list[$extKey]['EM_CONF']['state'] != 'excludeFromUpdates') {
1593 $onClick = '
1594 window.location.href=\'index.php?CMD[importExt]='.$extKey.'\'
1595 +\'&CMD[extVersion]=\'+document.pageform.extVersion.options[document.pageform.extVersion.selectedIndex].value
1596 +\'&CMD[loc]=\'+document.pageform.loc.options[document.pageform.loc.selectedIndex].value;
1597 return false;';
1598 $select .= ' ' . $GLOBALS['LANG']->getLL('ext_or') . '<br /><br />
1599 <input type="submit" value="' . $GLOBALS['LANG']->getLL('ext_import_update_button') .
1600 '" onclick="' . htmlspecialchars($onClick) . '" /> ' . $GLOBALS['LANG']->getLL('ext_import_update_to') . '
1601 <select name="loc">'.
1602 ($this->importAsType('G', $fetchData['emconf_lockType']) ?
1603 '<option value="G">' . $GLOBALS['LANG']->getLL('ext_import_global') . ' ' . $this->typePaths['G'] . $extKey . '/' .
1604 (@is_dir(PATH_site . $this->typePaths['G'] . $extKey) ?
1605 ' ' . $GLOBALS['LANG']->getLL('ext_import_overwrite') :
1606 ' ' . $GLOBALS['LANG']->getLL('ext_import_folder_empty')
1607 ) . '</option>' : ''
1608 ) .
1609 ($this->importAsType('L', $fetchData['emconf_lockType']) ?
1610 '<option value="L">' . $GLOBALS['LANG']->getLL('ext_import_local') . ' ' . $this->typePaths['L'] . $extKey . '/' .
1611 (@is_dir(PATH_site . $this->typePaths['L'] . $extKey) ?
1612 ' ' . $GLOBALS['LANG']->getLL('ext_import_overwrite') :
1613 ' ' . $GLOBALS['LANG']->getLL('ext_import_folder_empty')
1614 ) . '</option>' : ''
1615 ) .
1616 ($this->importAsType('S', $fetchData['emconf_lockType']) ?
1617 '<option value="S">' . $GLOBALS['LANG']->getLL('ext_import_system') . ' ' . $this->typePaths['S'] . $extKey . '/' .
1618 (@is_dir(PATH_site . $this->typePaths['S'] . $extKey) ?
1619 ' ' . $GLOBALS['LANG']->getLL('ext_import_overwrite') :
1620 ' ' . $GLOBALS['LANG']->getLL('ext_import_folder_empty')
1621 ) . '</option>' : ''
1622 ) .
1623 '</select>
1624 </form>';
1625 } else {
1626 $select .= '<br /><br />' . $GLOBALS['LANG']->getLL('ext_import_excluded_from_updates');
1627 }
1628 } else {
1629 $select .= '<br /><br />' . $this->noImportMsg();
1630 }
1631 $content.= $select;
1632 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('ext_import_select_command'), $content, 0, 1);
1633
1634 // Details:
1635 $eInfo = $fetchData[$extKey]['versions'][$version];
1636 $content='<strong>'.$fetchData[$extKey]['_ICON'].' &nbsp;'.$eInfo['EM_CONF']['title'].' ('.$extKey.', '.$version.')</strong><br /><br />';
1637 $content.=$this->extInformationArray($extKey,$eInfo,1);
1638 $this->content.=$this->doc->spacer(10);
1639 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('ext_import_remote_ext_details'), $content, 0, 1);
1640 }
1641
1642 /**
1643 * Fetches metadata and stores it to the corresponding place. This includes the mirror list,
1644 * extension XML files.
1645 *
1646 * @param string Type of data to fetch: (mirrors)
1647 * @param boolean If true the method doesn't produce any output
1648 * @return void
1649 */
1650 function fetchMetaData($metaType) {
1651 global $TYPO3_CONF_VARS;
1652
1653 switch($metaType) {
1654 case 'mirrors':
1655 $mfile = t3lib_div::tempnam('mirrors');
1656 $mirrorsFile = t3lib_div::getURL($this->MOD_SETTINGS['mirrorListURL'], 0, array(TYPO3_user_agent));
1657 if($mirrorsFile===false) {
1658 t3lib_div::unlink_tempfile($mfile);
1659 $content = '<p>' .
1660 sprintf($GLOBALS['LANG']->getLL('ext_import_list_not_updated'),
1661 $this->MOD_SETTINGS['mirrorListURL']
1662 ) . ' ' .
1663 $GLOBALS['LANG']->getLL('translation_problems') . '</p>';
1664 } else {
1665 t3lib_div::writeFile($mfile, $mirrorsFile);
1666 $mirrors = implode('',gzfile($mfile));
1667 t3lib_div::unlink_tempfile($mfile);
1668
1669 $mirrors = $this->xmlhandler->parseMirrorsXML($mirrors);
1670 if(is_array($mirrors) && count($mirrors)) {
1671 t3lib_BEfunc::getModuleData($this->MOD_MENU, array('extMirrors' => serialize($mirrors)), $this->MCONF['name'], '', 'extMirrors');
1672 $this->MOD_SETTINGS['extMirrors'] = serialize($mirrors);
1673 $content = '<p>' .
1674 sprintf($GLOBALS['LANG']->getLL('ext_import_list_updated'),
1675 count($mirrors)
1676 ) . '</p>';
1677 }
1678 else {
1679 $content = '<p>' . $mirrors . '<br />' . $GLOBALS['LANG']->getLL('ext_import_list_empty') . '</p>';
1680 }
1681 }
1682 break;
1683 case 'extensions':
1684 $this->fetchMetaData('mirrors'); // if we fetch the extensions anyway, we can as well keep this up-to-date
1685
1686 $mirror = $this->getMirrorURL();
1687 $extfile = $mirror.'extensions.xml.gz';
1688 $extmd5 = t3lib_div::getURL($mirror.'extensions.md5', 0, array(TYPO3_user_agent));
1689 if (is_file(PATH_site.'typo3temp/extensions.xml.gz')) {
1690 $localmd5 = md5_file(PATH_site.'typo3temp/extensions.xml.gz');
1691 }
1692
1693 // count cached extensions. If cache is empty re-fill it
1694 $cacheCount = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('extkey', 'cache_extensions');
1695
1696 if($extmd5 === false) {
1697 $content .= '<p>' .
1698 sprintf($GLOBALS['LANG']->getLL('ext_import_md5_not_updated'),
1699 $mirror . 'extensions.md5'
1700 ) .
1701 $GLOBALS['LANG']->getLL('translation_problems') . '</p>';
1702 } elseif($extmd5 == $localmd5 && $cacheCount) {
1703 $flashMessage = t3lib_div::makeInstance(
1704 't3lib_FlashMessage',
1705 $GLOBALS['LANG']->getLL('ext_import_list_unchanged'),
1706 $GLOBALS['LANG']->getLL('ext_import_list_unchanged_header'),
1707 t3lib_FlashMessage::INFO
1708 );
1709 $content .= $flashMessage->render();
1710 } else {
1711 $extXML = t3lib_div::getURL($extfile, 0, array(TYPO3_user_agent));
1712 if($extXML === false) {
1713 $content .= '<p>' .
1714 sprintf($GLOBALS['LANG']->getLL('ext_import_list_unchanged'),
1715 $extfile
1716 ) . ' ' .
1717 $GLOBALS['LANG']->getLL('translation_problems') . '</p>';
1718 } else {
1719 t3lib_div::writeFile(PATH_site.'typo3temp/extensions.xml.gz', $extXML);
1720 $content .= $this->xmlhandler->parseExtensionsXML(PATH_site.'typo3temp/extensions.xml.gz');
1721 }
1722 }
1723 break;
1724 }
1725
1726 return $content;
1727 }
1728
1729 /**
1730 * Returns the base URL for the slected or a random mirror.
1731 *
1732 * @return string The URL for the selected or a random mirror
1733 */
1734 function getMirrorURL() {
1735 if(strlen($this->MOD_SETTINGS['rep_url'])) return $this->MOD_SETTINGS['rep_url'];
1736
1737 $mirrors = unserialize($this->MOD_SETTINGS['extMirrors']);
1738 if(!is_array($mirrors)) {
1739 $this->fetchMetaData('mirrors');
1740 $mirrors = unserialize($this->MOD_SETTINGS['extMirrors']);
1741 if(!is_array($mirrors)) return false;
1742 }
1743 if($this->MOD_SETTINGS['selectedMirror']=='') {
1744 $rand = array_rand($mirrors);
1745 $url = 'http://'.$mirrors[$rand]['host'].$mirrors[$rand]['path'];
1746 }
1747 else {
1748 $url = 'http://'.$mirrors[$this->MOD_SETTINGS['selectedMirror']]['host'].$mirrors[$this->MOD_SETTINGS['selectedMirror']]['path'];
1749 }
1750
1751 return $url;
1752 }
1753
1754
1755
1756 /**
1757 * Installs (activates) an extension
1758 *
1759 * For $mode use the three constants EM_INSTALL_VERSION_MIN, EM_INSTALL_VERSION_MAX, EM_INSTALL_VERSION_STRICT
1760 *
1761 * If an extension is loaded or imported already and the version requirement is matched, it will not be
1762 * fetched from the repository. This means, if you use EM_INSTALL_VERSION_MIN, you will not always get the latest
1763 * version of an extension!
1764 *
1765 * @param string $extKey The extension key to install
1766 * @param string $version A version number that should be installed
1767 * @param int $mode If a version is requested, this determines if it is the min, max or strict version requested
1768 * @return [type] ...
1769 * @todo Make the method able to handle needed interaction somehow (unmatched dependencies)
1770 */
1771 function installExtension($extKey, $version=null, $mode=EM_INSTALL_VERSION_MIN) {
1772 list($inst_list,) = $this->getInstalledExtensions();
1773
1774 // check if it is already installed and loaded with sufficient version
1775 if(isset($inst_list[$extKey])) {
1776 $currentVersion = $inst_list[$extKey]['EM_CONF']['version'];
1777
1778 if(t3lib_extMgm::isLoaded($extKey)) {
1779 if($version===null) {
1780 return array(true, $GLOBALS['LANG']->getLL('ext_import_ext_already_installed_loaded'));
1781 } else {
1782 switch($mode) {
1783 case EM_INSTALL_VERSION_STRICT:
1784 if ($currentVersion == $version) {
1785 return array(true, $GLOBALS['LANG']->getLL('ext_import_ext_already_installed_loaded'));
1786 }
1787 break;
1788 case EM_INSTALL_VERSION_MIN:
1789 if (version_compare($currentVersion, $version, '>=')) {
1790 return array(true, $GLOBALS['LANG']->getLL('ext_import_ext_already_installed_loaded'));
1791 }
1792 break;
1793 case EM_INSTALL_VERSION_MAX:
1794 if (version_compare($currentVersion, $version, '<=')) {
1795 return array(true, $GLOBALS['LANG']->getLL('ext_import_ext_already_installed_loaded'));
1796 }
1797 break;
1798 }
1799 }
1800 } else {
1801 if (!t3lib_extMgm::isLocalconfWritable()) {
1802 return array(false, $GLOBALS['LANG']->getLL('ext_import_p_localconf'));
1803 }
1804 $newExtList = -1;
1805 switch($mode) {
1806 case EM_INSTALL_VERSION_STRICT:
1807 if ($currentVersion == $version) {
1808 $newExtList = $this->addExtToList($extKey, $inst_list);
1809 }
1810 break;
1811 case EM_INSTALL_VERSION_MIN:
1812 if (version_compare($currentVersion, $version, '>=')) {
1813 $newExtList = $this->addExtToList($extKey, $inst_list);
1814 }
1815 break;
1816 case EM_INSTALL_VERSION_MAX:
1817 if (version_compare($currentVersion, $version, '<=')) {
1818 $newExtList = $this->addExtToList($extKey, $inst_list);
1819 }
1820 break;
1821 }
1822 if ($newExtList!=-1) {
1823 $this->writeNewExtensionList($newExtList);
1824 $this->refreshGlobalExtList();
1825 $this->forceDBupdates($extKey, $inst_list[$extKey]);
1826 return array(true, $GLOBALS['LANG']->getLL('ext_import_ext_loaded'));
1827 }
1828 }
1829 }
1830
1831 // at this point we know we need to import (a matching version of) the extension from TER2
1832
1833 // see if we have an extension list at all
1834 if (!$this->xmlhandler->countExtensions()) {
1835 $this->fetchMetaData('extensions');
1836 }
1837 $this->xmlhandler->searchExtensionsXMLExact($extKey, '', '', TRUE, TRUE);
1838
1839 // check if extension can be fetched
1840 if(isset($this->xmlhandler->extensionsXML[$extKey])) {
1841 $versions = array_keys($this->xmlhandler->extensionsXML[$extKey]['versions']);
1842 $latestVersion = end($versions);
1843 switch($mode) {
1844 case EM_INSTALL_VERSION_STRICT:
1845 if(!isset($this->xmlhandler->extensionsXML[$extKey]['versions'][$version])) {
1846 return array(false, $GLOBALS['LANG']->getLL('ext_import_ext_n_a'));
1847 }
1848 break;
1849 case EM_INSTALL_VERSION_MIN:
1850 if (version_compare($latestVersion, $version, '>=')) {
1851 $version = $latestVersion;
1852 } else {
1853 return array(false, $GLOBALS['LANG']->getLL('ext_import_ext_n_a'));
1854 }
1855 break;
1856 case EM_INSTALL_VERSION_MAX:
1857 while (($v = array_pop($versions)) && version_compare($v, $version, '>=')) {
1858 // Loop until a version is found
1859 }
1860
1861 if ($v !== null && version_compare($v, $version, '<=')) {
1862 $version = $v;
1863 } else {
1864 return array(false, $GLOBALS['LANG']->getLL('ext_import_ext_n_a'));
1865 }
1866 break;
1867 }
1868 $this->importExtFromRep($extKey, $version, 'L');
1869 $newExtList = $this->addExtToList($extKey, $inst_list);
1870 if ($newExtList!=-1) {
1871 $this->writeNewExtensionList($newExtList);
1872 $this->refreshGlobalExtList();
1873 $this->forceDBupdates($extKey, $inst_list[$extKey]);
1874 $this->installTranslationsForExtension($extKey, $this->getMirrorURL());
1875 return array(true, $GLOBALS['LANG']->getLL('ext_import_ext_imported'));
1876 } else {
1877 return array(false, $GLOBALS['LANG']->getLL('ext_import_ext_not_loaded'));
1878 }
1879 } else {
1880 return array(false, $GLOBALS['LANG']->getLL('ext_import_ext_n_a_rep'));
1881 }
1882 }
1883
1884 function refreshGlobalExtList() {
1885 global $TYPO3_LOADED_EXT;
1886
1887 $TYPO3_LOADED_EXT = t3lib_extMgm::typo3_loadExtensions();
1888 if ($TYPO3_LOADED_EXT['_CACHEFILE']) {
1889 require(PATH_typo3conf.$TYPO3_LOADED_EXT['_CACHEFILE'].'_ext_localconf.php');
1890 }
1891 return;
1892
1893 $GLOBALS['TYPO3_LOADED_EXT'] = t3lib_extMgm::typo3_loadExtensions();
1894 if ($TYPO3_LOADED_EXT['_CACHEFILE']) {
1895 require(PATH_typo3conf.$TYPO3_LOADED_EXT['_CACHEFILE'].'_ext_localconf.php');
1896 } else {
1897 $temp_TYPO3_LOADED_EXT = $TYPO3_LOADED_EXT;
1898 foreach ($temp_TYPO3_LOADED_EXT as $_EXTKEY => $temp_lEDat) {
1899 if (is_array($temp_lEDat) && $temp_lEDat['ext_localconf.php']) {
1900 $_EXTCONF = $TYPO3_CONF_VARS['EXT']['extConf'][$_EXTKEY];
1901 require($temp_lEDat['ext_localconf.php']);
1902 }
1903 }
1904 }
1905 }
1906
1907
1908 /**
1909 * Imports an extensions from the online repository
1910 * NOTICE: in version 4.0 this changed from "importExtFromRep_old($extRepUid,$loc,$uploadFlag=0,$directInput='',$recentTranslations=0,$incManual=0,$dontDelete=0)"
1911 *
1912 * @param string Extension key
1913 * @param string Version
1914 * @param string Install scope: "L" or "G" or "S"
1915 * @param boolean If true, extension is uploaded as file
1916 * @param boolean If true, extension directory+files will not be deleted before writing the new ones. That way custom files stored in the extension folder will be kept.
1917 * @param array Direct input array (like from kickstarter)
1918 * @return string Return false on success, returns error message if error.
1919 */
1920 function importExtFromRep($extKey,$version,$loc,$uploadFlag=0,$dontDelete=0,$directInput='') {
1921
1922 $uploadSucceed = false;
1923 $uploadedTempFile = '';
1924 if (is_array($directInput)) {
1925 $fetchData = array($directInput,'');
1926 $loc = ($loc==='G'||$loc==='S') ? $loc : 'L';
1927 } elseif ($uploadFlag) {
1928 if (($uploadedTempFile = $this->CMD['alreadyUploaded']) || $_FILES['upload_ext_file']['tmp_name']) {
1929
1930 // Read uploaded file:
1931 if (!$uploadedTempFile) {
1932 if (!is_uploaded_file($_FILES['upload_ext_file']['tmp_name'])) {
1933 t3lib_div::sysLog('Possible file upload attack: '.$_FILES['upload_ext_file']['tmp_name'], 'Extension Manager', 3);
1934
1935 return $GLOBALS['LANG']->getLL('ext_import_file_not_uploaded');
1936 }
1937
1938 $uploadedTempFile = t3lib_div::upload_to_tempfile($_FILES['upload_ext_file']['tmp_name']);
1939 }
1940 $fileContent = t3lib_div::getUrl($uploadedTempFile);
1941
1942 if (!$fileContent) return $GLOBALS['LANG']->getLL('ext_import_file_empty');
1943
1944 // Decode file data:
1945 $fetchData = $this->terConnection->decodeExchangeData($fileContent);
1946
1947 if (is_array($fetchData)) {
1948 $extKey = $fetchData[0]['extKey'];
1949 if ($extKey) {
1950 if (!$this->CMD['uploadOverwrite']) {
1951 $loc = ($loc==='G'||$loc==='S') ? $loc : 'L';
1952 $comingExtPath = PATH_site.$this->typePaths[$loc].$extKey.'/';
1953 if (@is_dir($comingExtPath)) {
1954 $flashMessage = t3lib_div::makeInstance(
1955 't3lib_FlashMessage',
1956 sprintf($GLOBALS['LANG']->getLL('ext_import_ext_present_no_overwrite'), $comingExtPath) .
1957 '<br />' . $GLOBALS['LANG']->getLL('ext_import_ext_present_nothing_done'),
1958 '',
1959 t3lib_FlashMessage::ERROR
1960 );
1961 return $flashMessage->render();
1962 } // ... else go on, install...
1963 } // ... else go on, install...
1964 } else return $GLOBALS['LANG']->getLL('ext_import_no_key');
1965 } else return sprintf($GLOBALS['LANG']->getLL('ext_import_wrong_file_format'), $fetchData);
1966 } else return $GLOBALS['LANG']->getLL('ext_import_no_file');
1967 } else {
1968 $this->xmlhandler->searchExtensionsXMLExact($extKey, '', '', true, true);
1969
1970 // Fetch extension from TER:
1971 if(!strlen($version)) {
1972 $versions = array_keys($this->xmlhandler->extensionsXML[$extKey]['versions']);
1973 $version = end($versions);
1974 }
1975 $fetchData = $this->terConnection->fetchExtension($extKey, $version, $this->xmlhandler->extensionsXML[$extKey]['versions'][$version]['t3xfilemd5'], $this->getMirrorURL());
1976 }
1977
1978 // At this point the extension data should be present; so we want to write it to disc:
1979 if ($this->importAsType($loc)) {
1980 if (is_array($fetchData)) { // There was some data successfully transferred
1981 if ($fetchData[0]['extKey'] && is_array($fetchData[0]['FILES'])) {
1982 $extKey = $fetchData[0]['extKey'];
1983 if(!isset($fetchData[0]['EM_CONF']['constraints'])) $fetchData[0]['EM_CONF']['constraints'] = $this->xmlhandler->extensionsXML[$extKey]['versions'][$version]['dependencies'];
1984 $EM_CONF = $this->fixEMCONF($fetchData[0]['EM_CONF']);
1985 if (!$EM_CONF['lockType'] || !strcmp($EM_CONF['lockType'],$loc)) {
1986 // check dependencies, act accordingly if ext is loaded
1987 list($instExtInfo,)=$this->getInstalledExtensions();
1988 $depStatus = $this->checkDependencies($extKey, $EM_CONF, $instExtInfo);
1989 if(t3lib_extMgm::isLoaded($extKey) && !$depStatus['returnCode']) {
1990 $this->content .= $depStatus['html'];
1991 if ($uploadedTempFile) {
1992 $this->content .= '<input type="hidden" name="CMD[alreadyUploaded]" value="'.$uploadedTempFile.'" />';
1993 }
1994 } else {
1995 $res = $this->clearAndMakeExtensionDir($fetchData[0],$loc,$dontDelete);
1996 if (is_array($res)) {
1997 $extDirPath = trim($res[0]);
1998 if ($extDirPath && @is_dir($extDirPath) && substr($extDirPath,-1)=='/') {
1999
2000 $emConfFile = $this->construct_ext_emconf_file($extKey,$EM_CONF);
2001 $dirs = $this->extractDirsFromFileList(array_keys($fetchData[0]['FILES']));
2002
2003 $res = $this->createDirsInPath($dirs,$extDirPath);
2004 if (!$res) {
2005 $writeFiles = $fetchData[0]['FILES'];
2006 $writeFiles['ext_emconf.php']['content'] = $emConfFile;
2007 $writeFiles['ext_emconf.php']['content_md5'] = md5($emConfFile);
2008
2009 // Write files:
2010 foreach($writeFiles as $theFile => $fileData) {
2011 t3lib_div::writeFile($extDirPath.$theFile,$fileData['content']);
2012 if (!@is_file($extDirPath.$theFile)) {
2013 $content .= sprintf($GLOBALS['LANG']->getLL('ext_import_file_not_created'),
2014 $extDirPath . $theFile) . '<br />';
2015 } elseif (md5(t3lib_div::getUrl($extDirPath.$theFile)) != $fileData['content_md5']) {
2016 $content .= sprintf($GLOBALS['LANG']->getLL('ext_import_file_corrupted'),
2017 $extDirPath . $theFile) . '<br />';
2018 }
2019 }
2020
2021 // No content, no errors. Create success output here:
2022 if (!$content) {
2023 $messageContent = sprintf($GLOBALS['LANG']->getLL('ext_import_success_folder'), $extDirPath) . '<br />';
2024
2025 $uploadSucceed = true;
2026
2027 // Fix TYPO3_MOD_PATH for backend modules in extension:
2028 $modules = t3lib_div::trimExplode(',', $EM_CONF['module'], 1);
2029 if (count($modules)) {
2030 foreach($modules as $mD) {
2031 $confFileName = $extDirPath . $mD . '/conf.php';
2032 if (@is_file($confFileName)) {
2033 $messageContent .= $this->writeTYPO3_MOD_PATH($confFileName, $loc, $extKey . '/' . $mD . '/') . '<br />';
2034 } else {
2035 $messageContent .= sprintf($GLOBALS['LANG']->getLL('ext_import_no_conf_file'),
2036 $confFileName) . '<br />';
2037 }
2038 }
2039 }
2040 // 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.
2041 // But this order of the code works.... (using the empty Array with type, EMCONF and files hereunder).
2042
2043 // Writing to ext_emconf.php:
2044 $sEMD5A = $this->serverExtensionMD5Array($extKey,array('type' => $loc, 'EM_CONF' => array(), 'files' => array()));
2045 $EM_CONF['_md5_values_when_last_written'] = serialize($sEMD5A);
2046 $emConfFile = $this->construct_ext_emconf_file($extKey, $EM_CONF);
2047 t3lib_div::writeFile($extDirPath . 'ext_emconf.php', $emConfFile);
2048
2049 $messageContent .= 'ext_emconf.php: ' . $extDirPath . 'ext_emconf.php<br />';
2050 $messageContent .= $GLOBALS['LANG']->getLL('ext_import_ext_type') . ' ';
2051 $messageContent .= $this->typeLabels[$loc] . '<br />';
2052 $messageContent .= '<br />';
2053
2054 // Remove cache files:
2055 $updateContent = '';
2056 if (t3lib_extMgm::isLoaded($extKey)) {
2057 if ($this->removeCacheFiles()) {
2058 $messageContent .= $GLOBALS['LANG']->getLL('ext_import_cache_files_removed') . '<br />';
2059 }
2060
2061 list($new_list) = $this->getInstalledExtensions();
2062 $updateContent = $this->updatesForm($extKey, $new_list[$extKey], 1, 'index.php?CMD[showExt]=' . $extKey . '&SET[singleDetails]=info');
2063 }
2064
2065 $flashMessage = t3lib_div::makeInstance(
2066 't3lib_FlashMessage',
2067 $messageContent,
2068 $GLOBALS['LANG']->getLL('ext_import_success')
2069 );
2070 $content = $flashMessage->render() . $updateContent;
2071
2072
2073 // Install / Uninstall:
2074 if(!$this->CMD['standAlone']) {
2075 $content .= '<h3>' . $GLOBALS['LANG']->getLL('ext_import_install_uninstall') . '</h3>';
2076 $content.= $new_list[$extKey] ?
2077 '<a href="' . htmlspecialchars('index.php?CMD[showExt]=' . $extKey .
2078 '&CMD[remove]=1&CMD[clrCmd]=1&SET[singleDetails]=info') . '">' .
2079 $this->removeButton() . ' ' . $GLOBALS['LANG']->getLL('ext_import_uninstall') . '</a>' :
2080 '<a href="' . htmlspecialchars('index.php?CMD[showExt]=' . $extKey .
2081 '&CMD[load]=1&CMD[clrCmd]=1&SET[singleDetails]=info') . '">' .
2082 $this->installButton() . ' ' . $GLOBALS['LANG']->getLL('ext_import_install') . '</a>';
2083 } else {
2084 $content = $GLOBALS['LANG']->getLL('ext_import_imported') .
2085 '<br /><br /><a href="javascript:opener.top.content.document.forms[0].submit();window.close();">' .
2086 $GLOBALS['LANG']->getLL('ext_import_close_check') . '</a>';
2087 }
2088 }
2089 } else $content = $res;
2090 } else $content = sprintf($GLOBALS['LANG']->getLL('ext_import_ext_path_different'), $extDirPath);
2091 } else $content = $res;
2092 }
2093 } else $content = sprintf($GLOBALS['LANG']->getLL('ext_import_ext_only_here'),
2094 $this->typePaths[$EM_CONF['lockType']], $EM_CONF['lockType']);
2095 } else $content = $GLOBALS['LANG']->getLL('ext_import_no_ext_key_files');
2096 } else $content = sprintf($GLOBALS['LANG']->getLL('ext_import_data_transfer'), $fetchData);
2097 } else $content = sprintf($GLOBALS['LANG']->getLL('ext_import_no_install_here'), $this->typePaths[$loc]);
2098
2099 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('ext_import_results'), $content, 0, 1);
2100
2101 if ($uploadSucceed && $uploadedTempFile) {
2102 t3lib_div::unlink_tempfile($uploadedTempFile);
2103 }
2104
2105 return false;
2106 }
2107
2108 /**
2109 * Display extensions details.
2110 *
2111 * @param string Extension key
2112 * @return void Writes content to $this->content
2113 */
2114 function showExtDetails($extKey) {
2115 global $TYPO3_LOADED_EXT;
2116
2117 list($list,)=$this->getInstalledExtensions();
2118 $absPath = $this->getExtPath($extKey,$list[$extKey]['type']);
2119
2120 // Check updateModule:
2121 if (isset($list[$extKey]) && @is_file($absPath.'class.ext_update.php')) {
2122 require_once($absPath.'class.ext_update.php');
2123 $updateObj = new ext_update;
2124 if (!$updateObj->access()) {
2125 unset($this->MOD_MENU['singleDetails']['updateModule']);
2126 }
2127 } else {
2128 unset($this->MOD_MENU['singleDetails']['updateModule']);
2129 }
2130
2131 if($this->CMD['doDelete']) {
2132 $this->MOD_MENU['singleDetails'] = array();
2133 }
2134
2135 // Function menu here:
2136 if(!$this->CMD['standAlone'] && !t3lib_div::_GP('standAlone')) {
2137 $content = $GLOBALS['LANG']->getLL('ext_details_ext') . '&nbsp;<strong>' .
2138 $this->extensionTitleIconHeader($extKey, $list[$extKey]) . '</strong> (' . $extKey . ')';
2139 $this->content.= $this->doc->section('', $content);
2140 }
2141
2142 // Show extension details:
2143 if ($list[$extKey]) {
2144
2145 // Checking if a command for install/uninstall is executed:
2146 if (($this->CMD['remove'] || $this->CMD['load']) && !in_array($extKey,$this->requiredExt)) {
2147
2148 // Install / Uninstall extension here:
2149 if (t3lib_extMgm::isLocalconfWritable()) {
2150 // Check dependencies:
2151 $depStatus = $this->checkDependencies($extKey, $list[$extKey]['EM_CONF'], $list);
2152 if(!$this->CMD['remove'] && !$depStatus['returnCode']) {
2153 $this->content .= $depStatus['html'];
2154 $newExtList = -1;
2155 } elseif ($this->CMD['remove']) {
2156 $newExtList = $this->removeExtFromList($extKey,$list);
2157 } else {
2158 $newExtList = $this->addExtToList($extKey,$list);
2159 }
2160
2161 // Successful installation:
2162 if ($newExtList!=-1) {
2163 $updates = '';
2164 if ($this->CMD['load']) {
2165 if($_SERVER['REQUEST_METHOD'] == 'POST') {
2166 $script = t3lib_div::linkThisScript(array('CMD[showExt]' => $extKey, 'CMD[load]' => 1, 'CMD[clrCmd]' => $this->CMD['clrCmd'], 'SET[singleDetails]' => 'info'));
2167 } else {
2168 $script = '';
2169 }
2170 if($this->CMD['standAlone']) {
2171 $standaloneUpdates = '<input type="hidden" name="standAlone" value="1" />';
2172 }
2173 $depsolver = t3lib_div::_POST('depsolver');
2174 if(is_array($depsolver['ignore'])) {
2175 foreach($depsolver['ignore'] as $depK => $depV) {
2176 $dependencyUpdates .= '<input type="hidden" name="depsolver[ignore]['.$depK.']" value="1" />';
2177 }
2178 }
2179 $updatesForm = $this->updatesForm($extKey,$list[$extKey],1,$script, $dependencyUpdates.$standaloneUpdates.'<input type="hidden" name="_do_install" value="1" /><input type="hidden" name="_clrCmd" value="'.$this->CMD['clrCmd'].'" />', TRUE);
2180 if ($updatesForm) {
2181 $updates = $GLOBALS['LANG']->getLL('ext_details_new_tables_fields') . '<br />' .
2182 $GLOBALS['LANG']->getLL('ext_details_new_tables_fields_select') . $updatesForm;
2183 $labelDBUpdate = $GLOBALS['LANG']->csConvObj->conv_case(
2184 $GLOBALS['LANG']->charSet,
2185 $GLOBALS['LANG']->getLL('ext_details_db_needs_update'),
2186 'toUpper'
2187 );
2188 $this->content .= $this->doc->section(
2189 sprintf($GLOBALS['LANG']->getLL('ext_details_installing') . ' ',
2190 $this->extensionTitleIconHeader($extKey, $list[$extKey])
2191 ) . ' ' .
2192 $labelDBUpdate,
2193 $updates, 1, 1, 1, 1
2194 );
2195 }
2196 } elseif ($this->CMD['remove']) {
2197 $updates.= $this->checkClearCache($list[$extKey]);
2198 if ($updates) {
2199 $updates = '
2200 <form action="'.t3lib_div::linkThisScript().'" method="post">'.$updates.'
2201 <br /><input type="submit" name="write" value="' .
2202 $GLOBALS['LANG']->getLL('ext_details_remove_ext') . '" />
2203 <input type="hidden" name="_do_install" value="1" />
2204 <input type="hidden" name="_clrCmd" value="'.$this->CMD['clrCmd'].'" />
2205 <input type="hidden" name="standAlone" value="'.$this->CMD['standAlone'].'" />
2206 </form>';
2207 $labelDBUpdate = $GLOBALS['LANG']->csConvObj->conv_case(
2208 $GLOBALS['LANG']->charSet,
2209 $GLOBALS['LANG']->getLL('ext_details_db_needs_update'),
2210 'toUpper'
2211 );
2212 $this->content .= $this->doc->section(
2213 sprintf($GLOBALS['LANG']->getLL('ext_details_removing') . ' ',
2214 $this->extensionTitleIconHeader($extKey, $list[$extKey])
2215 ) . ' ' .
2216 $labelDBUpdate,
2217 $updates, 1, 1, 1, 1
2218 );
2219 }
2220 }
2221 if (!$updates || t3lib_div::_GP('_do_install')) {
2222 $this->writeNewExtensionList($newExtList);
2223 $action = $this->CMD['load'] ? 'installed' : 'removed';
2224 $GLOBALS['BE_USER']->writelog(5, 1, 0, 0, 'Extension list has been changed, extension %s has been %s', array($extKey, $action));
2225
2226 $messageLabel = 'ext_details_ext_' . $action . '_with_key';
2227 $flashMessage = t3lib_div::makeInstance(
2228 't3lib_FlashMessage',
2229 sprintf($GLOBALS['LANG']->getLL($messageLabel), $extKey),
2230 '',
2231 t3lib_FlashMessage::OK,
2232 TRUE
2233 );
2234 t3lib_FlashMessageQueue::addMessage($flashMessage);
2235
2236 if ($this->CMD['clrCmd'] || t3lib_div::_GP('_clrCmd')) {
2237 if ($this->CMD['load'] && @is_file($absPath.'ext_conf_template.txt')) {
2238 $vA = array('CMD'=>Array('showExt'=>$extKey));
2239 } else {
2240 $vA = array('CMD'=>'');
2241 }
2242 } else {
2243 $vA = array('CMD'=>Array('showExt'=>$extKey));
2244 }
2245 if($this->CMD['standAlone'] || t3lib_div::_GP('standAlone')) {
2246 $this->content .= sprintf($GLOBALS['LANG']->getLL('ext_details_ext_installed_removed'),
2247 ($this->CMD['load'] ?
2248 $GLOBALS['LANG']->getLL('ext_details_installed') :
2249 $GLOBALS['LANG']->getLL('ext_details_removed')
2250 )
2251 ) .
2252 '<br /><br /><a href="javascript:opener.top.content.document.forms[0].submit();window.close();">' .
2253 $GLOBALS['LANG']->getLL('ext_import_close_check') . '</a>';
2254 } else {
2255 // Determine if new modules were installed:
2256 $techInfo = $this->makeDetailedExtensionAnalysis($extKey, $list[$extKey]);
2257 if (($this->CMD['load'] || $this->CMD['remove']) && is_array($techInfo['flags']) && in_array('Module', $techInfo['flags'], true)) {
2258 $vA['CMD']['refreshMenu'] = 1;
2259 }
2260 t3lib_utility_Http::redirect(t3lib_div::linkThisScript($vA));
2261 }
2262 }
2263 }
2264 } else {
2265 $writeAccessError = $GLOBALS['LANG']->csConvObj->conv_case(
2266 $GLOBALS['LANG']->charSet,
2267 $GLOBALS['LANG']->getLL('ext_details_write_access_error'),
2268 'toUpper'
2269 );
2270 $this->content .= $this->doc->section(
2271 sprintf($GLOBALS['LANG']->getLL('ext_details_installing') . ' ',
2272 $this->extensionTitleIconHeader($extKey, $list[$extKey])
2273 ) . ' ' .
2274 $writeAccessError,
2275 $GLOBALS['LANG']->getLL('ext_details_write_error_localconf'),
2276 1, 1, 2, 1
2277 );
2278 }
2279
2280 } elseif ($this->CMD['downloadFile'] && !in_array($extKey,$this->requiredExt)) {
2281
2282 // Link for downloading extension has been clicked - deliver content stream:
2283 $dlFile = $this->CMD['downloadFile'];
2284 if (t3lib_div::isFirstPartOfStr($dlFile,PATH_site) && t3lib_div::isFirstPartOfStr($dlFile,$absPath) && @is_file($dlFile)) {
2285 $mimeType = 'application/octet-stream';
2286 Header('Content-Type: '.$mimeType);
2287 Header('Content-Disposition: attachment; filename='.basename($dlFile));
2288 echo t3lib_div::getUrl($dlFile);
2289 exit;
2290 } else {
2291 throw new RuntimeException(
2292 'TYPO3 Fatal Error: ' . $GLOBALS['LANG']->getLL('ext_details_error_downloading'),
2293 1270853980
2294 );
2295 }
2296
2297 } elseif ($this->CMD['editFile'] && !in_array($extKey,$this->requiredExt)) {
2298
2299 // Editing extension file:
2300 $editFile = $this->CMD['editFile'];
2301 if (t3lib_div::isFirstPartOfStr($editFile,PATH_site) && t3lib_div::isFirstPartOfStr($editFile,$absPath)) { // Paranoia...
2302
2303 $fI = t3lib_div::split_fileref($editFile);
2304 if (@is_file($editFile) && t3lib_div::inList($this->editTextExtensions,($fI['fileext']?$fI['fileext']:$fI['filebody']))) {
2305 if (filesize($editFile)<($this->kbMax*1024)) {
2306 $outCode = '<form action="index.php" method="post" name="editfileform">';
2307 $info = '';
2308 $submittedContent = t3lib_div::_POST('edit');
2309 $saveFlag = 0;
2310
2311 if(isset($submittedContent['file']) && !$GLOBALS['TYPO3_CONF_VARS']['EXT']['noEdit']) { // Check referer here?
2312 $oldFileContent = t3lib_div::getUrl($editFile);
2313 if($oldFileContent != $submittedContent['file']) {
2314 $oldMD5 = md5(str_replace(CR,'',$oldFileContent));
2315 $info .= sprintf(
2316 $GLOBALS['LANG']->getLL('ext_details_md5_previous'),
2317 '<b>' . $oldMD5 . '</b>'
2318 ) . '<br />';
2319 t3lib_div::writeFile($editFile,$submittedContent['file']);
2320 $saveFlag = 1;
2321 } else {
2322 $info .= $GLOBALS['LANG']->getLL('ext_details_no_changes') . '<br />';
2323 }
2324 }
2325
2326 $fileContent = t3lib_div::getUrl($editFile);
2327
2328 $outCode.= sprintf(
2329 $GLOBALS['LANG']->getLL('ext_details_file'),
2330 '<b>' . substr($editFile, strlen($absPath)) . '</b> (' .
2331 t3lib_div::formatSize(filesize($editFile)) . ')<br />'
2332 );
2333 $fileMD5 = md5(str_replace(CR,'',$fileContent));
2334 $info .= sprintf(
2335 $GLOBALS['LANG']->getLL('ext_details_md5_current'),
2336 '<b>' . $fileMD5 . '</b>'
2337 ) . '<br />';
2338 if($saveFlag) {
2339 $saveMD5 = md5(str_replace(CR,'',$submittedContent['file']));
2340 $info .= sprintf(
2341 $GLOBALS['LANG']->getLL('ext_details_md5_submitted'),
2342 '<b>' . $saveMD5 . '</b>'
2343 ) . '<br />';
2344 if ($fileMD5!=$saveMD5) {
2345 $info .= $GLOBALS['TBE_TEMPLATE']->rfw(
2346 '<br /><strong>' . $GLOBALS['LANG']->getLL('ext_details_saving_failed_changes_lost') . '</strong>'
2347 ) . '<br />';
2348 }
2349 else {
2350 $info .= $GLOBALS['TBE_TEMPLATE']->rfw(
2351 '<br /><strong>' . $GLOBALS['LANG']->getLL('ext_details_file_saved') . '</strong>'
2352 ) . '<br />';
2353 }
2354 }
2355
2356 $outCode.= '<textarea name="edit[file]" rows="35" wrap="off"'.$this->doc->formWidthText(48,'width:98%;height:70%','off').' class="fixed-font enable-tab">'.t3lib_div::formatForTextarea($fileContent).'</textarea>';
2357 $outCode.= '<input type="hidden" name="edit[filename]" value="'.$editFile.'" />';
2358 $outCode.= '<input type="hidden" name="CMD[editFile]" value="'.htmlspecialchars($editFile).'" />';
2359 $outCode.= '<input type="hidden" name="CMD[showExt]" value="'.$extKey.'" />';
2360 $outCode.= $info;
2361
2362 if (!$GLOBALS['TYPO3_CONF_VARS']['EXT']['noEdit']) {
2363 $outCode .= '<br /><input type="submit" name="save_file" value="' .
2364 $GLOBALS['LANG']->getLL('ext_details_file_save_button') . '" />';
2365 }
2366 else {
2367 $outCode .= $GLOBALS['TBE_TEMPLATE']->rfw(
2368 '<br />' . $GLOBALS['LANG']->getLL('ext_details_saving_disabled') . ' '
2369 );
2370 }
2371
2372 $onClick = 'window.location.href=\'index.php?CMD[showExt]='.$extKey.'\';return false;';
2373 $outCode .= '<input type="submit" name="cancel" value="' .
2374 $GLOBALS['LANG']->getLL('ext_details_cancel_button') . '" onclick="' .
2375 htmlspecialchars($onClick) . '" /></form>';
2376
2377 $theOutput.=$this->doc->spacer(15);
2378 $theOutput .= $this->doc->section($GLOBALS['LANG']->getLL('ext_details_edit_file'), '', 0, 1);
2379 $theOutput.=$this->doc->sectionEnd().$outCode;
2380 $this->content.=$theOutput;
2381 } else {
2382 $theOutput.=$this->doc->spacer(15);
2383 $theOutput .= $this->doc->section(
2384 sprintf(
2385 $GLOBALS['LANG']->getLL('ext_details_filesize_exceeded_kb'),
2386 $this->kbMax
2387 ),
2388 sprintf(
2389 $GLOBALS['LANG']->getLL('ext_details_file_too_large'),
2390 $this->kbMax
2391 )
2392 );
2393 }
2394 }
2395 } else {
2396 die (sprintf($GLOBALS['LANG']->getLL('ext_details_fatal_edit_error'),
2397 $editFile
2398 )
2399 );
2400 }
2401 } else {
2402
2403 // MAIN:
2404 switch((string)$this->MOD_SETTINGS['singleDetails']) {
2405 case 'info':
2406 // Loaded / Not loaded:
2407 if (!in_array($extKey,$this->requiredExt)) {
2408 if ($TYPO3_LOADED_EXT[$extKey]) {
2409 $content = '<strong>' . $GLOBALS['LANG']->getLL('ext_details_loaded_and_running') . '</strong><br />' .
2410 '<a href="' . htmlspecialchars('index.php?CMD[showExt]=' . $extKey . '&CMD[remove]=1') .
2411 '">' . $GLOBALS['LANG']->getLL('ext_details_remove_button') . ' ' . $this->removeButton() . '</a>';
2412 } else {
2413 $content = $GLOBALS['LANG']->getLL('ext_details_not_loaded') . '<br />'.
2414 '<a href="' . htmlspecialchars('index.php?CMD[showExt]=' . $extKey . '&CMD[load]=1') .
2415 '">' . $GLOBALS['LANG']->getLL('ext_details_install_button') . ' ' . $this->installButton() . '</a>';
2416 }
2417 } else {
2418 $content = $GLOBALS['LANG']->getLL('ext_details_always_loaded');
2419 }
2420 $this->content.=$this->doc->spacer(10);
2421 $this->content .= $this->doc->section(
2422 $GLOBALS['LANG']->getLL('ext_details_current_status'), $content, 0, 1
2423 );
2424
2425 if (t3lib_extMgm::isLoaded($extKey)) {
2426 $updates=$this->updatesForm($extKey,$list[$extKey]);
2427 if ($updates) {
2428 $this->content.=$this->doc->spacer(10);
2429 $this->content .= $this->doc->section(
2430 $GLOBALS['LANG']->getLL('ext_details_update_needed'),
2431 $updates . '<br /><br />' . $GLOBALS['LANG']->getLL('ext_details_notice_static_data'),
2432 0, 1
2433 );
2434 }
2435 }
2436
2437 // Config:
2438 if (@is_file($absPath.'ext_conf_template.txt')) {
2439 $this->content.=$this->doc->spacer(10);
2440 $this->content .= $this->doc->section(
2441 $GLOBALS['LANG']->getLL('ext_details_configuration'),
2442 $GLOBALS['LANG']->getLL('ext_details_notice_clear_cache') . '<br /><br />',
2443 0, 1
2444 );
2445
2446 $this->tsStyleConfigForm($extKey, $list[$extKey]);
2447 }
2448
2449 // Show details:
2450 $content = t3lib_BEfunc::cshItem('_MOD_tools_em', 'info', $GLOBALS['BACK_PATH'], '|<br />');
2451 $content.= $this->extInformationArray($extKey,$list[$extKey]);
2452
2453 $this->content.=$this->doc->spacer(10);
2454 $this->content .= $this->doc->section(
2455 $GLOBALS['LANG']->getLL('ext_details_details'), $content, 0, 1
2456 );
2457 break;
2458 case 'upload':
2459 $em = t3lib_div::_POST('em');
2460 if($em['action'] == 'doUpload') {
2461 $em['extKey'] = $extKey;
2462 $em['extInfo'] = $list[$extKey];
2463 $content = $this->uploadExtensionToTER($em);
2464 $content .= $this->doc->spacer(10);
2465 // Must reload this, because EM_CONF information has been updated!
2466 list($list,)=$this->getInstalledExtensions();
2467 } else {
2468 // CSH:
2469 $content = t3lib_BEfunc::cshItem('_MOD_tools_em', 'upload', $GLOBALS['BACK_PATH'], '|<br />');
2470
2471 // Upload:
2472 if (substr($extKey,0,5)!='user_') {
2473 $content.= $this->getRepositoryUploadForm($extKey,$list[$extKey]);
2474 $eC=0;
2475 } else {
2476 $content .= $GLOBALS['LANG']->getLL('ext_details_no_unique_ext');
2477 $eC=2;
2478 }
2479 if (!$this->fe_user['username']) {
2480 $flashMessage = t3lib_div::makeInstance(
2481 't3lib_FlashMessage',
2482 sprintf($GLOBALS['LANG']->getLL('ext_details_no_username'),
2483 '<a href="index.php?SET[function]=3">', '</a>'
2484 ),
2485 '',
2486 t3lib_FlashMessage::INFO
2487 );
2488 $content .= '<br />' . $flashMessage->render();
2489
2490 }
2491 }
2492 $this->content .= $this->doc->section(
2493 $GLOBALS['LANG']->getLL('ext_details_upload_to_ter'),
2494 $content, 0, 1, $eC
2495 );
2496 break;
2497 case 'backup':
2498 if($this->CMD['doDelete']) {
2499 $content = $this->extDelete($extKey,$list[$extKey]);
2500 $this->content .= $this->doc->section(
2501 $GLOBALS['LANG']->getLL('ext_details_delete'),
2502 $content, 0, 1
2503 );
2504 } else {
2505 $content = t3lib_BEfunc::cshItem('_MOD_tools_em', 'backup_delete', $GLOBALS['BACK_PATH'], '|<br />');
2506 $content.= $this->extBackup($extKey,$list[$extKey]);
2507 $this->content .= $this->doc->section(
2508 $GLOBALS['LANG']->getLL('ext_details_backup'),
2509 $content, 0, 1
2510 );
2511
2512 $content = $this->extDelete($extKey,$list[$extKey]);
2513 $this->content .= $this->doc->section(
2514 $GLOBALS['LANG']->getLL('ext_details_delete'),
2515 $content, 0, 1
2516 );
2517
2518 $content = $this->extUpdateEMCONF($extKey,$list[$extKey]);
2519 $this->content .= $this->doc->section(
2520 $GLOBALS['LANG']->getLL('ext_details_update_em_conf'),
2521 $content, 0, 1
2522 );
2523 }
2524 break;
2525 case 'dump':
2526 $this->extDumpTables($extKey,$list[$extKey]);
2527 break;
2528 case 'edit':
2529 $content = t3lib_BEfunc::cshItem('_MOD_tools_em', 'editfiles', $GLOBALS['BACK_PATH'], '|<br />');
2530 $content.= $this->getFileListOfExtension($extKey,$list[$extKey]);
2531
2532 $this->content.=$this->doc->section(
2533 $GLOBALS['LANG']->getLL('ext_details_ext_files'),
2534 $content, 0, 1
2535 );
2536 break;
2537 case 'updateModule':
2538 $this->content .= $this->doc->section(
2539 $GLOBALS['LANG']->getLL('ext_details_update'),
2540 is_object($updateObj) ?
2541 $updateObj->main() :
2542 $GLOBALS['LANG']->getLL('ext_details_no_update_object'),
2543 0, 1
2544 );
2545 break;
2546 default:
2547 $this->extObjContent();
2548 break;
2549 }
2550 }
2551 }
2552 }
2553
2554 /**
2555 * Outputs a screen from where you can install multiple extensions in one go
2556 * This can be called from external modules with "...index.php?CMD[requestInstallExtensions]=
2557 *
2558 * @param string Comma list of extension keys to install. Renders a screen with checkboxes for all extensions not already imported or installed
2559 * @return void
2560 */
2561 function requestInstallExtensions($extList) {
2562
2563 // Return URL:
2564 $returnUrl = t3lib_div::_GP('returnUrl');
2565 $installOrImportExtension = t3lib_div::_POST('installOrImportExtension');
2566
2567 // Extension List:
2568 $extArray = explode(',',$extList);
2569 $outputRow = array();
2570 $outputRow[] = '
2571 <tr class="bgColor5 tableheader">
2572 <td>' . $GLOBALS['LANG']->getLL('reqInstExt_install_import') . '</td>
2573 <td>' . $GLOBALS['LANG']->getLL('reqInstExt_ext_key') . '</td>
2574 </tr>
2575 ';
2576
2577 foreach($extArray as $extKey) {
2578
2579 // Check for the request:
2580 if ($installOrImportExtension[$extKey]) {
2581 $this->installExtension($extKey);
2582 }
2583
2584 // Display:
2585 if (!t3lib_extMgm::isLoaded($extKey)) {
2586 $outputRow[] = '
2587 <tr class="bgColor4">
2588 <td><input type="checkbox" name="'.htmlspecialchars('installOrImportExtension['.$extKey.']').'" value="1" checked="checked" id="check_'.$extKey.'" /></td>
2589 <td><label for="check_'.$extKey.'">'.htmlspecialchars($extKey).'</label></td>
2590 </tr>
2591 ';
2592 }
2593 }
2594
2595 if (count($outputRow)>1 || !$returnUrl) {
2596 $content = '
2597 <!-- ending page form ... -->
2598 <form action="'.htmlspecialchars(t3lib_div::getIndpEnv('REQUEST_URI')).'" method="post">
2599 <table border="0" cellpadding="1" cellspacing="1">'.implode('',$outputRow).'</table>
2600 <input type="submit" name="_" value="' . $GLOBALS['LANG']->getLL('reqInstExt_import_install_selected') . '" />
2601 </form>';
2602
2603 if ($returnUrl) {
2604 $content.= '
2605 <br />
2606 <br />
2607 <a href="' . htmlspecialchars($returnUrl) . '">' . $GLOBALS['LANG']->getLL('reqInstExt_return') . '</a>
2608 ';
2609 }
2610
2611 $this->content.= $this->doc->section(
2612 $GLOBALS['LANG']->getLL('reqInstExt_imp_inst_ext'), $content, 0, 1
2613 );
2614 } else {
2615 t3lib_utility_Http::redirect($returnUrl);
2616 }
2617 }
2618
2619
2620
2621
2622
2623
2624
2625
2626 /***********************************