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